summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--AUTHORS11
-rw-r--r--CMakeLists.txt33
-rw-r--r--INSTALL2
-rw-r--r--TRANSLATION4
-rw-r--r--doc/LaTeX/zusfassung.log333
-rw-r--r--doc/doxconf10
-rwxr-xr-xformat.sh14
-rw-r--r--i18n/pvs_ar_JO.ts31
-rw-r--r--i18n/pvs_de_DE.ts31
-rw-r--r--i18n/pvs_es_MX.ts31
-rw-r--r--i18n/pvs_fr_FR.ts31
-rw-r--r--i18n/pvs_pl_PL.ts31
-rw-r--r--i18n/pvsgui_ar_JO.ts286
-rw-r--r--i18n/pvsgui_de_DE.ts294
-rw-r--r--i18n/pvsgui_es_MX.ts284
-rw-r--r--i18n/pvsgui_fr_FR.ts286
-rw-r--r--i18n/pvsgui_pl_PL.ts286
-rw-r--r--i18n/pvsmgr_ar_JO.ts321
-rw-r--r--i18n/pvsmgr_de_DE.ts321
-rw-r--r--i18n/pvsmgr_es_MX.ts321
-rw-r--r--i18n/pvsmgr_fr_FR.ts321
-rw-r--r--i18n/pvsmgr_pl_PL.ts321
-rw-r--r--icons/README8
-rw-r--r--icons/gearsgo.pngbin0 -> 5692 bytes
-rw-r--r--icons/gearsstop.pngbin0 -> 5051 bytes
-rw-r--r--icons/remote-control-all.pngbin0 -> 5365 bytes
-rw-r--r--icons/remote-control.pngbin0 -> 3657 bytes
-rw-r--r--pvsmgr.qrc3
-rwxr-xr-xspam5
-rw-r--r--src/core/pvsClient.cpp19
-rw-r--r--src/core/pvsClient.h13
-rw-r--r--src/core/pvsConnectionManager.cpp42
-rw-r--r--src/gui/connectionList.cpp3
-rw-r--r--src/gui/connectionWindow.cpp29
-rw-r--r--src/gui/connectionWindow.h4
-rw-r--r--src/gui/dialog.cpp2
-rw-r--r--src/gui/frame.cpp339
-rw-r--r--src/gui/frame.h32
-rw-r--r--src/gui/mainWindow.cpp206
-rw-r--r--src/gui/mainWindow.h11
-rw-r--r--src/gui/processWidget.cpp98
-rw-r--r--src/gui/processWidget.h35
-rw-r--r--src/gui/processesDialog.cpp60
-rw-r--r--src/gui/processesDialog.h37
-rw-r--r--src/gui/processesStartDialog.cpp75
-rw-r--r--src/gui/processesStartDialog.h31
-rw-r--r--src/gui/ui/mainwindow.ui10
-rw-r--r--src/gui/ui/mainwindowtouch.ui24
-rw-r--r--src/gui/ui/processWidget.ui227
-rw-r--r--src/gui/ui/processesDialog.ui92
-rw-r--r--src/gui/ui/processesStartDialog.ui69
-rw-r--r--src/input/CMakeLists.txt175
-rw-r--r--src/input/allowLocalOrPrivileged.cpp21
-rw-r--r--src/input/detail/Makefile.autogen5
-rw-r--r--src/input/detail/gen/gen_typeList.cpp118
-rw-r--r--src/input/detail/policyChain.h74
-rw-r--r--src/input/detail/systemTraits.h94
-rw-r--r--src/input/detail/typeList.h76
-rw-r--r--src/input/detail/typeList_autogen.h62
-rw-r--r--src/input/i18n.h33
-rw-r--r--src/input/i18n/pvsinput_ar_JO.ts147
-rw-r--r--src/input/i18n/pvsinput_de_DE.ts165
-rw-r--r--src/input/i18n/pvsinput_es_MX.ts147
-rw-r--r--src/input/i18n/pvsinput_fr_FR.ts147
-rw-r--r--src/input/i18n/pvsinput_pl_PL.ts147
-rw-r--r--src/input/incompatibleHandler.h37
-rw-r--r--src/input/inputEvent.cpp155
-rw-r--r--src/input/inputEvent.h398
-rw-r--r--src/input/inputEventHandler.cpp33
-rw-r--r--src/input/inputEventHandler.h398
-rw-r--r--src/input/inputEventNonQt.cpp17
-rw-r--r--src/input/inputHandlerChains.h40
-rw-r--r--src/input/killX11Handler.cpp89
-rw-r--r--src/input/killX11Handler.h42
-rw-r--r--src/input/logNonMatchingHandler.cpp27
-rw-r--r--src/input/logNonMatchingHandler.h36
-rw-r--r--src/input/magicSysRqHandler.cpp28
-rw-r--r--src/input/magicSysRqHandler.h38
-rw-r--r--src/input/org.openslx.pvs.input.policy18
-rw-r--r--src/input/privilegedHandlerForwarder.cpp82
-rw-r--r--src/input/privilegedHandlerForwarder.h47
-rw-r--r--src/input/privilegedInputHandlerChain.cpp32
-rw-r--r--src/input/pvsCheckPrivileges.cpp550
-rw-r--r--src/input/pvsCheckPrivileges.h196
-rw-r--r--src/input/pvsPrivInputHandler.cpp124
-rw-r--r--src/input/pvsPrivInputHandler.h54
-rw-r--r--src/input/pvsPrivInputSignalHandler.cpp69
-rw-r--r--src/input/pvsPrivInputSignalHandler.h64
-rw-r--r--src/input/pvsPrivInputSocket.cpp233
-rw-r--r--src/input/pvsPrivInputSocket.h75
-rw-r--r--src/input/pvsSyslog.cpp133
-rw-r--r--src/input/pvsSyslog.h72
-rw-r--r--src/input/pvsprivinputd.conf28
-rw-r--r--src/input/pvsprivinputd.cpp264
-rw-r--r--src/input/pvsprivinputd.gentooinit.in37
-rw-r--r--src/input/pvsprivinputd.lsbinit.in152
-rw-r--r--src/input/rebootSystemHandler.cpp32
-rw-r--r--src/input/rebootSystemHandler.h36
-rw-r--r--src/input/sayHelloHandler.cpp25
-rw-r--r--src/input/sayHelloHandler.h35
-rw-r--r--src/input/unprivilegedInputHandlerChain.cpp34
-rw-r--r--src/input/x11FakeKeyboardHandler.cpp877
-rw-r--r--src/input/x11FakeKeyboardHandler.h40
-rw-r--r--src/input/x11FakeMouseHandler.cpp59
-rw-r--r--src/input/x11FakeMouseHandler.h46
-rw-r--r--src/input/x11InputUtils.cpp29
-rw-r--r--src/input/x11InputUtils.h30
-rwxr-xr-xsrc/pvs.cpp120
-rwxr-xr-xsrc/pvs.h14
-rw-r--r--src/pvsDaemon.cpp13
-rw-r--r--src/pvsgui.cpp37
-rw-r--r--src/pvsmgr.cpp3
-rw-r--r--src/pvsmgrtouch.cpp3
-rw-r--r--src/util/clientGUIUtils.cpp3
-rwxr-xr-xsrc/util/clientGUIUtils.h12
-rwxr-xr-xsrc/util/clientGUIUtils_X11.cpp11
-rw-r--r--src/version.h4
118 files changed, 10412 insertions, 1108 deletions
diff --git a/.gitignore b/.gitignore
index 3245ec2..e2dc5a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
.cproject
.project
build/
+Debug/
diff --git a/AUTHORS b/AUTHORS
index daf9a81..a081ceb 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,19 +2,20 @@ Initial design and first versions:
Simon Wittenberg <wittenb@informatik.uni-freiburg.de>
Involved team members at the moment:
+Fabian Schillinger <schillif@informatik.uni-freiburg.de>
+Johann Latocha <johann@latocha.de>
+Sébastien Braun <sebb@yellowhippy.org>
+
+Credits of left team members:
Johann Betz <jbetz@informatik.uni-freiburg.de>
Javier Castillo <castillf@informatik.uni-freiburg.de>
-Johann Latocha <johann@latocha.de>
Achille Nana <achille.achille@gmail.com>
Simon Rettberg <simon.rettberg@gmail.com>
Fadi Salameh <fadi84@hotmail.com>
Alexander Hoppe <a.hoppe@gmail.com>
Benjamin Lieberwirt <benjamin.lieberwirth@googlemail.com>
-Credits of left team members:
--
-
Project management, supervision:
Dirk von Suchodoletz <dvs@openslx.com>
Sebastian Schmelzer <sebastian@schmelzer.ws>
-Simon Wittenberg <wittenb@informatik.uni-freiburg.de> \ No newline at end of file
+Johann Latocha <johann@latocha.de> \ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0b5e89e..4eeaea8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,8 +27,20 @@ FIND_PACKAGE( VNC REQUIRED )
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}
${CMAKE_BINARY_DIR}
+ ${X11_INCLUDE_DIR}
+ ${X11_XTest_INCLUDE_PATH}
+ ${X11_Xinput_INCLUDE_PATH}
)
+IF(NOT X11_XTest_FOUND)
+ MESSAGE(FATAL_ERROR "Could not find X11 extension XTest or its developer files.")
+ENDIF()
+IF(NOT X11_Xinput_FOUND)
+ MESSAGE(FATAL_ERROR "Could not find X11 extension Xinput or its developer files.")
+ENDIF()
+
+ADD_SUBDIRECTORY(src/input)
+
IF(WIN32)
SET(sysdep_suffix _Win32)
INCLUDE_DIRECTORIES(
@@ -90,6 +102,9 @@ SET( PVSMGR_SRCS
src/util/TextFile.cpp
src/util/serviceDiscoveryUtil.cpp
src/gui/aboutDialog.cpp
+ src/gui/processesDialog.cpp
+ src/gui/processesStartDialog.cpp
+ src/gui/processWidget.cpp
src/gui/multicastConfigDialog.cpp
)
@@ -139,10 +154,13 @@ SET( PVSMGR_UIS
src/gui/ui/mainwindow.ui
src/gui/ui/profileDialog.ui
src/gui/ui/dialog.ui
+ src/gui/ui/processesStartDialog.ui
src/gui/ui/projectionDialog.ui
src/gui/ui/aboutDialog.ui
src/gui/ui/serverChatDialog.ui
src/gui/ui/clientFileSendDialog.ui
+ src/gui/ui/processesDialog.ui
+ src/gui/ui/processWidget.ui
src/gui/ui/multicastConfigDialog.ui
)
@@ -150,6 +168,7 @@ SET( PVSMGRTOUCH_UIS
src/gui/ui/mainwindowtouch.ui
src/gui/ui/profileDialog.ui
src/gui/ui/dialog.ui
+ src/gui/ui/processesStartDialog.ui
src/gui/ui/projectionDialog.ui
src/gui/ui/aboutDialog.ui
src/gui/ui/serverChatDialog.ui
@@ -190,6 +209,7 @@ SET( PVSMGR_MOC_HDRS
src/gui/connectionFrame.h
src/gui/profileDialog.h
src/gui/dialog.h
+ src/gui/processesStartDialog.h
src/gui/projectionDialog.h
src/gui/serverChatDialog.h
src/gui/serverFileTransfert.h
@@ -200,6 +220,8 @@ SET( PVSMGR_MOC_HDRS
src/net/pvsServiceBroadcast.h
src/net/SslServer.h
src/gui/aboutDialog.h
+ src/gui/processesDialog.h
+ src/gui/processWidget.h
src/gui/multicastConfigDialog.h
)
@@ -343,6 +365,7 @@ TARGET_LINK_LIBRARIES( pvsmgr
${VNC_LIBRARIES}
${X11_LIBRARIES}
pvsmcast
+ pvsinput
)
ENDIF(WIN32)
@@ -356,6 +379,7 @@ ELSEIF(UNIX)
${VNC_LIBRARIES}
${X11_LIBRARIES}
pvsmcast
+ pvsinput
)
ENDIF(WIN32)
@@ -371,7 +395,10 @@ ELSEIF(UNIX)
${QT_LIBRARIES}
${VNC_LIBRARIES}
${X11_LIBRARIES}
- pvsmcast
+ ${X11_XTest_LIB}
+ ${X11_Xinput_LIB}
+ pvsmcast
+ pvsinput
)
ENDIF(WIN32)
@@ -421,8 +448,8 @@ SET( CPACK_GENERATOR "DEB;RPM" )
SET( CPACK_SET_DESTDIR "ON" )
SET( CPACK_PACKAGE_NAME "pvs" )
SET( CPACK_PACKAGE_VERSION_MAJOR "2" )
-SET( CPACK_PACKAGE_VERSION_MINOR "0" )
-SET( CPACK_PACKAGE_VERSION_PATCH "3" )
+SET( CPACK_PACKAGE_VERSION_MINOR "8" )
+SET( CPACK_PACKAGE_VERSION_PATCH "0" )
SET( CPACK_PACKAGE_DESCRIPTION_SUMMARY "Pool Video Switch" )
SET( CPACK_PACKAGE_DESCRIPTION "")
SET( CPACK_PACKAGE_CONTACT "Simon Wittenberg <wittenb@informatik.uni-freiburg.de>" )
diff --git a/INSTALL b/INSTALL
index cfb079b..6a7d736 100644
--- a/INSTALL
+++ b/INSTALL
@@ -6,6 +6,8 @@
The following packages are required:
libvncserver-dev
libx11-dev
+ libxi-dev
+ libxtst-dev
libqt4-dev >= 4.5.3
qt4-dev-tools >= 4.5.3
cmake >= 2.4.0
diff --git a/TRANSLATION b/TRANSLATION
index 74a10cb..1d04f06 100644
--- a/TRANSLATION
+++ b/TRANSLATION
@@ -1,4 +1,2 @@
Javier Castillo <castillf@informatik.uni-freiburg.de>
-Johann Latocha <johann@latocha.de>
-Achille Nana <achille.achille@gmail.com>
-Fadi Salameh <fadi84@hotmail.com> \ No newline at end of file
+Johann Latocha <johann@latocha.de> \ No newline at end of file
diff --git a/doc/LaTeX/zusfassung.log b/doc/LaTeX/zusfassung.log
new file mode 100644
index 0000000..4924af6
--- /dev/null
+++ b/doc/LaTeX/zusfassung.log
@@ -0,0 +1,333 @@
+This is pdfTeX, Version 3.1415926-1.40.10 (TeX Live 2009/Debian) (format=pdflatex 2010.9.4) 2 OCT 2010 17:00
+entering extended mode
+ restricted \write18 enabled.
+ %&-line parsing enabled.
+**zusfassung.tex
+(./zusfassung.tex
+LaTeX2e <2009/09/24>
+Babel <v3.8l> and hyphenation patterns for english, usenglishmax, dumylang, noh
+yphenation, loaded.
+! Undefined control sequence.
+l.2 \small
+
+?
+! Undefined control sequence.
+l.3 \section
+ *{Zusammenfassung}
+?
+
+! LaTeX Error: Missing \begin{document}.
+
+See the LaTeX manual or LaTeX Companion for explanation.
+Type H <return> for immediate help.
+ ...
+
+l.3 \section*
+ {Zusammenfassung}
+?
+Missing character: There is no * in font nullfont!
+Missing character: There is no Z in font nullfont!
+Missing character: There is no u in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no a in font nullfont!
+Missing character: There is no m in font nullfont!
+Missing character: There is no m in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no f in font nullfont!
+Missing character: There is no a in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no u in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no g in font nullfont!
+Missing character: There is no D in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no P in font nullfont!
+Missing character: There is no o in font nullfont!
+Missing character: There is no o in font nullfont!
+Missing character: There is no l in font nullfont!
+Missing character: There is no V in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no d in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no o in font nullfont!
+Missing character: There is no S in font nullfont!
+Missing character: There is no w in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no c in font nullfont!
+Missing character: There is no h in font nullfont!
+Missing character: There is no ( in font nullfont!
+Missing character: There is no P in font nullfont!
+Missing character: There is no V in font nullfont!
+Missing character: There is no S in font nullfont!
+Missing character: There is no ) in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no A in font nullfont!
+Missing character: There is no p in font nullfont!
+Missing character: There is no p in font nullfont!
+Missing character: There is no l in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no k in font nullfont!
+Missing character: There is no a in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no o in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no , in font nullfont!
+Missing character: There is no d in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no g in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no Z in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no m in font nullfont!
+Missing character: There is no Z in font nullfont!
+Missing character: There is no u in font nullfont!
+Missing character: There is no g in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no d in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no O in font nullfont!
+Missing character: There is no p in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no S in font nullfont!
+Missing character: There is no L in font nullfont!
+Missing character: There is no X in font nullfont!
+Missing character: There is no - in font nullfont!
+Missing character: There is no P in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no o in font nullfont!
+Missing character: There is no j in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no k in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no a in font nullfont!
+Missing character: There is no m in font nullfont!
+Missing character: There is no R in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no c in font nullfont!
+Missing character: There is no h in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no z in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no u in font nullfont!
+Missing character: There is no m in font nullfont!
+Missing character: There is no d in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no U in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no v in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no à in font nullfont!
+Missing character: There is no ¤ in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no F in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no b in font nullfont!
+Missing character: There is no u in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no g in font nullfont!
+Missing character: There is no u in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no d in font nullfont!
+Missing character: There is no a in font nullfont!
+Missing character: There is no m in font nullfont!
+Missing character: There is no L in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no h in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no u in font nullfont!
+Missing character: There is no h in font nullfont!
+Missing character: There is no l in font nullfont!
+Missing character: There is no f in font nullfont!
+Missing character: There is no à in font nullfont!
+Missing character: There is no ¼ in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no K in font nullfont!
+Missing character: There is no o in font nullfont!
+Missing character: There is no m in font nullfont!
+Missing character: There is no m in font nullfont!
+Missing character: There is no u in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no k in font nullfont!
+Missing character: There is no a in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no o in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no y in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no m in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no w in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no c in font nullfont!
+Missing character: There is no k in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no l in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no w in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no d in font nullfont!
+Missing character: There is no . in font nullfont!
+
+Overfull \hbox (20.0pt too wide) in paragraph at lines 3--5
+[]
+ []
+
+
+! LaTeX Error: Missing \begin{document}.
+
+See the LaTeX manual or LaTeX Companion for explanation.
+Type H <return> for immediate help.
+ ...
+
+l.6 I
+ nzwischen liegt die Version 3 vor ...
+?
+Missing character: There is no I in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no z in font nullfont!
+Missing character: There is no w in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no c in font nullfont!
+Missing character: There is no h in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no l in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no g in font nullfont!
+Missing character: There is no t in font nullfont!
+Missing character: There is no d in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no V in font nullfont!
+Missing character: There is no e in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no s in font nullfont!
+Missing character: There is no i in font nullfont!
+Missing character: There is no o in font nullfont!
+Missing character: There is no n in font nullfont!
+Missing character: There is no 3 in font nullfont!
+Missing character: There is no v in font nullfont!
+Missing character: There is no o in font nullfont!
+Missing character: There is no r in font nullfont!
+Missing character: There is no . in font nullfont!
+Missing character: There is no . in font nullfont!
+Missing character: There is no . in font nullfont!
+
+Overfull \hbox (20.0pt too wide) in paragraph at lines 6--7
+[]
+ []
+
+
+! LaTeX Error: The font size command \normalsize is not defined:
+ there is probably something wrong with the class file.
+
+See the LaTeX manual or LaTeX Companion for explanation.
+Type H <return> for immediate help.
+ ...
+
+l.9 \normalsize
+
+?
+
+! LaTeX Error: The font size command \normalsize is not defined:
+ there is probably something wrong with the class file.
+
+See the LaTeX manual or LaTeX Companion for explanation.
+Type H <return> for immediate help.
+ ...
+
+l.10 \newpage
+
+?
+[1])
+*
+(Please type a command or say `\end')
+*
+(Please type a command or say `\end')
+*
+(Please type a command or say `\end')
+*q
+
+! LaTeX Error: Missing \begin{document}.
+
+See the LaTeX manual or LaTeX Companion for explanation.
+Type H <return> for immediate help.
+ ...
+
+<*> q
+
+? \end
+Type <return> to proceed, S to scroll future error messages,
+R to run without stopping, Q to run quietly,
+I to insert something,
+1 or ... or 9 to ignore the next 1 to 9 tokens of input,
+H for help, X to quit.
+? x
+
+Here is how much of TeX's memory you used:
+ 8 strings out of 495061
+ 296 string characters out of 1182622
+ 45108 words of memory out of 3000000
+ 3283 multiletter control sequences out of 15000+50000
+ 3640 words of font info for 14 fonts, out of 3000000 for 9000
+ 28 hyphenation exceptions out of 8191
+ 19i,4n,14p,221b,113s stack positions out of 5000i,500n,10000p,200000b,50000s
+Output written on zusfassung.pdf (1 page, 914 bytes).
+PDF statistics:
+ 6 PDF objects out of 1000 (max. 8388607)
+ 0 named destinations out of 1000 (max. 500000)
+ 1 words of extra memory for PDF output out of 10000 (max. 10000000)
+
diff --git a/doc/doxconf b/doc/doxconf
index 50334c7..e3e32a6 100644
--- a/doc/doxconf
+++ b/doc/doxconf
@@ -564,7 +564,7 @@ WARN_LOGFILE = ./doxwarnlog
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = ./pvsClient.h ./pvsClient.cpp ./pvs.h ./pvs.cpp ./pvsDaemon.h ./pvsDaemon.cpp ./src
+INPUT = ../pvsClient.h ../pvsClient.cpp ../pvs.h ../pvs.cpp ../pvsDaemon.h ../pvsDaemon.cpp ../src
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -1210,13 +1210,13 @@ ENABLE_PREPROCESSING = YES
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
-MACRO_EXPANSION = NO
+MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
-EXPAND_ONLY_PREDEF = NO
+EXPAND_ONLY_PREDEF = YES
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
@@ -1244,7 +1244,9 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED =
+PREDEFINED = "DOXYGEN_RUNNING" \
+ "BEGIN_POLICY_CLASS(name)=class name" \
+ "END_POLICY_CLASS=;"
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
diff --git a/format.sh b/format.sh
deleted file mode 100755
index d2a218f..0000000
--- a/format.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-echo "Do not use, it sucks..."
-exit
-# Note: As astyle seems to change the way of indenting things in detail in every release,
-# it makes no sense to use this frequently, cause it would require everyone to use the
-# same version of astyle, otherwise you get lots of modified files on every commit :(
-
-FILES=`find src/ -name \*.cpp && find src/ -name \*.h`
-
-# option -j would add { } to every if-statement, but not supported in <1.24
-for i in $FILES; do
- astyle --style=ansi -A1 $i
-done
diff --git a/i18n/pvs_ar_JO.ts b/i18n/pvs_ar_JO.ts
index 2f5b77e..8e8a15e 100644
--- a/i18n/pvs_ar_JO.ts
+++ b/i18n/pvs_ar_JO.ts
@@ -4,27 +4,50 @@
<context>
<name>PVS</name>
<message>
- <location filename="../src/pvs.cpp" line="277"/>
+ <location filename="../src/pvs.cpp" line="353"/>
<source>Message</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="355"/>
+ <location filename="../src/pvs.cpp" line="431"/>
<source>VNC connection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="355"/>
+ <location filename="../src/pvs.cpp" line="431"/>
<source>The host </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="357"/>
+ <location filename="../src/pvs.cpp" line="433"/>
<source> requested your screen!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
+ <name>PVSIncomingMulticastTransfer</name>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="105"/>
+ <source>Aborted</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="109"/>
+ <source>Unrecoverable data corruption</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="112"/>
+ <source>Connection was reset</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="115"/>
+ <source>Unrecoverable data loss. Try a lower transfer rate</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
<location filename="../src/pvsDaemon.cpp" line="28"/>
diff --git a/i18n/pvs_de_DE.ts b/i18n/pvs_de_DE.ts
index 20da674..e6f7bf6 100644
--- a/i18n/pvs_de_DE.ts
+++ b/i18n/pvs_de_DE.ts
@@ -4,27 +4,50 @@
<context>
<name>PVS</name>
<message>
- <location filename="../src/pvs.cpp" line="277"/>
+ <location filename="../src/pvs.cpp" line="353"/>
<source>Message</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="355"/>
+ <location filename="../src/pvs.cpp" line="431"/>
<source>VNC connection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="355"/>
+ <location filename="../src/pvs.cpp" line="431"/>
<source>The host </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="357"/>
+ <location filename="../src/pvs.cpp" line="433"/>
<source> requested your screen!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
+ <name>PVSIncomingMulticastTransfer</name>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="105"/>
+ <source>Aborted</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="109"/>
+ <source>Unrecoverable data corruption</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="112"/>
+ <source>Connection was reset</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="115"/>
+ <source>Unrecoverable data loss. Try a lower transfer rate</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
<location filename="../src/pvsDaemon.cpp" line="28"/>
diff --git a/i18n/pvs_es_MX.ts b/i18n/pvs_es_MX.ts
index 2f5b77e..8e8a15e 100644
--- a/i18n/pvs_es_MX.ts
+++ b/i18n/pvs_es_MX.ts
@@ -4,27 +4,50 @@
<context>
<name>PVS</name>
<message>
- <location filename="../src/pvs.cpp" line="277"/>
+ <location filename="../src/pvs.cpp" line="353"/>
<source>Message</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="355"/>
+ <location filename="../src/pvs.cpp" line="431"/>
<source>VNC connection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="355"/>
+ <location filename="../src/pvs.cpp" line="431"/>
<source>The host </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="357"/>
+ <location filename="../src/pvs.cpp" line="433"/>
<source> requested your screen!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
+ <name>PVSIncomingMulticastTransfer</name>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="105"/>
+ <source>Aborted</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="109"/>
+ <source>Unrecoverable data corruption</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="112"/>
+ <source>Connection was reset</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="115"/>
+ <source>Unrecoverable data loss. Try a lower transfer rate</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
<location filename="../src/pvsDaemon.cpp" line="28"/>
diff --git a/i18n/pvs_fr_FR.ts b/i18n/pvs_fr_FR.ts
index 2f5b77e..8e8a15e 100644
--- a/i18n/pvs_fr_FR.ts
+++ b/i18n/pvs_fr_FR.ts
@@ -4,27 +4,50 @@
<context>
<name>PVS</name>
<message>
- <location filename="../src/pvs.cpp" line="277"/>
+ <location filename="../src/pvs.cpp" line="353"/>
<source>Message</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="355"/>
+ <location filename="../src/pvs.cpp" line="431"/>
<source>VNC connection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="355"/>
+ <location filename="../src/pvs.cpp" line="431"/>
<source>The host </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="357"/>
+ <location filename="../src/pvs.cpp" line="433"/>
<source> requested your screen!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
+ <name>PVSIncomingMulticastTransfer</name>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="105"/>
+ <source>Aborted</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="109"/>
+ <source>Unrecoverable data corruption</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="112"/>
+ <source>Connection was reset</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="115"/>
+ <source>Unrecoverable data loss. Try a lower transfer rate</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
<location filename="../src/pvsDaemon.cpp" line="28"/>
diff --git a/i18n/pvs_pl_PL.ts b/i18n/pvs_pl_PL.ts
index 2f5b77e..8e8a15e 100644
--- a/i18n/pvs_pl_PL.ts
+++ b/i18n/pvs_pl_PL.ts
@@ -4,27 +4,50 @@
<context>
<name>PVS</name>
<message>
- <location filename="../src/pvs.cpp" line="277"/>
+ <location filename="../src/pvs.cpp" line="353"/>
<source>Message</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="355"/>
+ <location filename="../src/pvs.cpp" line="431"/>
<source>VNC connection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="355"/>
+ <location filename="../src/pvs.cpp" line="431"/>
<source>The host </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvs.cpp" line="357"/>
+ <location filename="../src/pvs.cpp" line="433"/>
<source> requested your screen!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
+ <name>PVSIncomingMulticastTransfer</name>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="105"/>
+ <source>Aborted</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="109"/>
+ <source>Unrecoverable data corruption</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="112"/>
+ <source>Connection was reset</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/net/pvsIncomingMulticastTransfer.cpp" line="115"/>
+ <source>Unrecoverable data loss. Try a lower transfer rate</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
<location filename="../src/pvsDaemon.cpp" line="28"/>
diff --git a/i18n/pvsgui_ar_JO.ts b/i18n/pvsgui_ar_JO.ts
index 59b40b9..65f432c 100644
--- a/i18n/pvsgui_ar_JO.ts
+++ b/i18n/pvsgui_ar_JO.ts
@@ -101,158 +101,199 @@
<context>
<name>ClientConfigDialogClass</name>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="200"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="248"/>
<source>PVS - Configuration</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="201"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="249"/>
<source>Allow vnc access to lecturer?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="202"/>
- <location filename="../build/ui_clientConfigDialog.h" line="206"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="250"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="254"/>
<source>Full access</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="203"/>
- <location filename="../build/ui_clientConfigDialog.h" line="207"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="251"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="255"/>
<source>View only</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="204"/>
- <location filename="../build/ui_clientConfigDialog.h" line="208"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="252"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="256"/>
<source>None</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="205"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="253"/>
<source>Allow vnc access to other?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="209"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="257"/>
<source>Accept chat messages</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="210"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="258"/>
<source>Accept file transfers</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="211"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="259"/>
<source>Permissions</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="214"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="262"/>
<source>Top Left</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="215"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="263"/>
<source>Top Center</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="216"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="264"/>
<source>Top Right</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="217"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="265"/>
<source>Bottom Left</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="218"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="266"/>
<source>Bottom Center</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="219"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="267"/>
<source>Bottom Right</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="221"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="269"/>
<source>Display</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="270"/>
+ <source>Network Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="271"/>
+ <source>Reload List</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="272"/>
+ <source>Network</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientFileReceiveDialog</name>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="63"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="101"/>
<source>PVS File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="63"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="101"/>
<source>User &apos;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="64"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="102"/>
<source>&apos; would like to send you a file: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="75"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="113"/>
<source>Open File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="150"/>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="156"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="188"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="194"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="151"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="189"/>
<source>File Transfer complete.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="157"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="195"/>
<source>File Transfer canceled!</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="232"/>
+ <source>Where should I save %1?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="242"/>
+ <source>Could not rename file</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="242"/>
+ <source>Failed to rename %1 to %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="254"/>
+ <source>File transfer failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="254"/>
+ <source>File transfer failed for the following reason:
+%1</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientFileReceiveDialogClass</name>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="131"/>
<source>Receiving from:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="132"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="127"/>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="136"/>
<source>0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="135"/>
<source>/</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation type="unfinished"></translation>
</message>
@@ -260,57 +301,109 @@
<context>
<name>ClientFileSendDialog</name>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="66"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="78"/>
<source>Open File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="184"/>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="190"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="90"/>
+ <source>Send File</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="110"/>
+ <source>all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="111"/>
+ <source>Waiting to start</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="123"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="129"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="141"/>
+ <source>File Send error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="123"/>
+ <source>Error communicating with backend: %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="129"/>
+ <source>Something went wrong while communicating with backend, but I don&apos;t know what.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="141"/>
+ <source>Could not create a multicast transfer: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="207"/>
+ <source>Receiver declined</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="265"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="271"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="185"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="266"/>
<source>File Transfer complete.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="191"/>
- <source>File Transfer canceled!</source>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="272"/>
+ <source>File Transfer canceled: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="284"/>
+ <source>You clicked &apos;Cancel&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="291"/>
+ <source>Socket Error</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ClientFileSendDialogClass</name>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="131"/>
<source>Sending to:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="132"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="127"/>
- <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="136"/>
<source>0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="135"/>
<source>/</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation type="unfinished"></translation>
</message>
@@ -318,52 +411,48 @@
<context>
<name>ClientNicklistDialogClass</name>
<message>
- <location filename="../build/ui_clientNicklistDialog.h" line="84"/>
+ <location filename="../build/ui_clientNicklistDialog.h" line="91"/>
<source>PVS - Users</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientNicklistDialog.h" line="85"/>
+ <location filename="../build/ui_clientNicklistDialog.h" line="92"/>
<source>Select user:</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../build/ui_clientNicklistDialog.h" line="93"/>
+ <source>Send to &amp;all</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientToolbarClass</name>
<message>
- <location filename="../build/ui_clientToolbar.h" line="166"/>
+ <location filename="../build/ui_clientToolbar.h" line="160"/>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="168"/>
+ <location filename="../build/ui_clientToolbar.h" line="162"/>
<source>Menu</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="170"/>
+ <location filename="../build/ui_clientToolbar.h" line="164"/>
<source>Host:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="172"/>
+ <location filename="../build/ui_clientToolbar.h" line="166"/>
<source>Click to connect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="174"/>
+ <location filename="../build/ui_clientToolbar.h" line="168"/>
<source>-</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location filename="../build/ui_clientToolbar.h" line="175"/>
- <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;DejaVu Sans&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600; font-style:italic; color:#0055ff;&quot;&gt;Pool Video Switch&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>InfoDialogClass</name>
@@ -394,125 +483,138 @@ p, li { white-space: pre-wrap; }
<context>
<name>PVSGUI</name>
<message>
- <location filename="../src/pvsgui.cpp" line="35"/>
+ <location filename="../src/pvsgui.cpp" line="40"/>
<source>Connect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="189"/>
+ <location filename="../src/pvsgui.cpp" line="230"/>
<source>Show &amp;toolbar</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="191"/>
+ <location filename="../src/pvsgui.cpp" line="232"/>
<source>&amp;Disconnect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="192"/>
+ <location filename="../src/pvsgui.cpp" line="233"/>
<source>C&amp;hat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="193"/>
+ <location filename="../src/pvsgui.cpp" line="234"/>
<source>&amp;Send File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="194"/>
+ <location filename="../src/pvsgui.cpp" line="235"/>
<source>&amp;Config</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="195"/>
+ <location filename="../src/pvsgui.cpp" line="236"/>
<source>&amp;Information</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="196"/>
+ <location filename="../src/pvsgui.cpp" line="237"/>
<source>&amp;About</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="197"/>
+ <location filename="../src/pvsgui.cpp" line="238"/>
<source>&amp;Quit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="285"/>
- <location filename="../src/pvsgui.cpp" line="300"/>
- <location filename="../src/pvsgui.cpp" line="380"/>
+ <location filename="../src/pvsgui.cpp" line="290"/>
+ <location filename="../src/pvsgui.cpp" line="305"/>
+ <location filename="../src/pvsgui.cpp" line="385"/>
<source>PVS Connection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="285"/>
+ <location filename="../src/pvsgui.cpp" line="290"/>
<source>Please enter password (If not needed leave blank):</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="301"/>
+ <location filename="../src/pvsgui.cpp" line="306"/>
<source>Are you sure you want to disconnect?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="324"/>
- <location filename="../src/pvsgui.cpp" line="346"/>
+ <location filename="../src/pvsgui.cpp" line="329"/>
+ <location filename="../src/pvsgui.cpp" line="351"/>
<source>PVS connection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="324"/>
- <location filename="../src/pvsgui.cpp" line="338"/>
+ <location filename="../src/pvsgui.cpp" line="329"/>
+ <location filename="../src/pvsgui.cpp" line="343"/>
<source>Connected to </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="346"/>
- <location filename="../src/pvsgui.cpp" line="358"/>
+ <location filename="../src/pvsgui.cpp" line="351"/>
+ <location filename="../src/pvsgui.cpp" line="363"/>
<source>Disconnected</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="380"/>
+ <location filename="../src/pvsgui.cpp" line="385"/>
<source>New host available: </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
+ <name>PVSNetworkInterfaceListModel</name>
+ <message>
+ <location filename="../src/net/pvsNetworkInterfaceListModel.cpp" line="63"/>
+ <source>Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
- <location filename="../src/pvsgui.cpp" line="419"/>
+ <location filename="../src/pvsgui.cpp" line="430"/>
<source>Usage: pvsgui [OPTIONS]...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="420"/>
+ <location filename="../src/pvsgui.cpp" line="431"/>
<source>Start the Pool Video Switch GUI.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="421"/>
+ <location filename="../src/pvsgui.cpp" line="432"/>
<source>Options:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="422"/>
- <source>Start only with systray icon.</source>
+ <location filename="../src/pvsgui.cpp" line="433"/>
+ <source>Start with toolbar.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="423"/>
+ <location filename="../src/pvsgui.cpp" line="434"/>
+ <source>Set toolbar position (0-5)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/pvsgui.cpp" line="435"/>
<source>Show this help text and quit.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="424"/>
+ <location filename="../src/pvsgui.cpp" line="436"/>
<source>Show version and quit.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="433"/>
+ <location filename="../src/pvsgui.cpp" line="445"/>
<source>Version: </source>
<translation type="unfinished"></translation>
</message>
diff --git a/i18n/pvsgui_de_DE.ts b/i18n/pvsgui_de_DE.ts
index ba2fe27..229ab15 100644
--- a/i18n/pvsgui_de_DE.ts
+++ b/i18n/pvsgui_de_DE.ts
@@ -101,158 +101,199 @@
<context>
<name>ClientConfigDialogClass</name>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="200"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="248"/>
<source>PVS - Configuration</source>
<translation>PVS - Konfiguration</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="201"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="249"/>
<source>Allow vnc access to lecturer?</source>
<translation>Dozenten VNC Zugriff erlauben?</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="202"/>
- <location filename="../build/ui_clientConfigDialog.h" line="206"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="250"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="254"/>
<source>Full access</source>
<translation>Voller Zugriff</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="203"/>
- <location filename="../build/ui_clientConfigDialog.h" line="207"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="251"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="255"/>
<source>View only</source>
<translation>Nur zuschauen</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="204"/>
- <location filename="../build/ui_clientConfigDialog.h" line="208"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="252"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="256"/>
<source>None</source>
<translation>Kein</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="205"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="253"/>
<source>Allow vnc access to other?</source>
<translation>Anderen VNC Zugriff erlauben?</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="209"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="257"/>
<source>Accept chat messages</source>
<translation>Chat Nachrichten erlauben</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="210"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="258"/>
<source>Accept file transfers</source>
<translation>Dateiübertragung erlauben</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="211"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="259"/>
<source>Permissions</source>
<translation>Rechte</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="214"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="262"/>
<source>Top Left</source>
<translation>Oben Links</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="215"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="263"/>
<source>Top Center</source>
<translation>Oben Mitte</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="216"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="264"/>
<source>Top Right</source>
<translation>Oben Rechts</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="217"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="265"/>
<source>Bottom Left</source>
<translation>Unten Links</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="218"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="266"/>
<source>Bottom Center</source>
<translation>Unten Mitte</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="219"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="267"/>
<source>Bottom Right</source>
<translation>Unten Rechts</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="221"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="269"/>
<source>Display</source>
<translation>Anzeige</translation>
</message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="270"/>
+ <source>Network Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="271"/>
+ <source>Reload List</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="272"/>
+ <source>Network</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientFileReceiveDialog</name>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="63"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="101"/>
<source>PVS File Transfer</source>
<translation>PVS Dateiübertragung</translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="63"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="101"/>
<source>User &apos;</source>
<translation>Benutzer &apos;</translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="64"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="102"/>
<source>&apos; would like to send you a file: </source>
<translation>&apos; möchte ihnen eine Datei senden:</translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="75"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="113"/>
<source>Open File</source>
<translation>Datei Öffnen</translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="150"/>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="156"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="188"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="194"/>
<source>PVS - File Transfer</source>
<translation>PVS - Dateiübertragung</translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="151"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="189"/>
<source>File Transfer complete.</source>
<translation>Dateiübertragung beendet.</translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="157"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="195"/>
<source>File Transfer canceled!</source>
<translation>Dateiübertragung abgebrochen!</translation>
</message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="232"/>
+ <source>Where should I save %1?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="242"/>
+ <source>Could not rename file</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="242"/>
+ <source>Failed to rename %1 to %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="254"/>
+ <source>File transfer failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="254"/>
+ <source>File transfer failed for the following reason:
+%1</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientFileReceiveDialogClass</name>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation>PVS - Dateiübertragung</translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="131"/>
<source>Receiving from:</source>
<translation>Empfang von:</translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="132"/>
<source>unknown</source>
<translation>unbekannt</translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="127"/>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="136"/>
<source>0</source>
<translation>0</translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="135"/>
<source>/</source>
<translation>/</translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation>&amp;Abbruch</translation>
</message>
@@ -260,57 +301,113 @@
<context>
<name>ClientFileSendDialog</name>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="66"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="78"/>
<source>Open File</source>
<translation>Datei Öffnen</translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="184"/>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="190"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="90"/>
+ <source>Send File</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="110"/>
+ <source>all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="111"/>
+ <source>Waiting to start</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="123"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="129"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="141"/>
+ <source>File Send error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="123"/>
+ <source>Error communicating with backend: %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="129"/>
+ <source>Something went wrong while communicating with backend, but I don&apos;t know what.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="141"/>
+ <source>Could not create a multicast transfer: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="207"/>
+ <source>Receiver declined</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="265"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="271"/>
<source>PVS - File Transfer</source>
<translation>PBS -Dateiübertragung</translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="185"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="266"/>
<source>File Transfer complete.</source>
<translation>Dateiübertragung beendet.</translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="191"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="272"/>
+ <source>File Transfer canceled: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="284"/>
+ <source>You clicked &apos;Cancel&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="291"/>
+ <source>Socket Error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<source>File Transfer canceled!</source>
- <translation>Dateiübertragung abgebrochen!</translation>
+ <translation type="obsolete">Dateiübertragung abgebrochen!</translation>
</message>
</context>
<context>
<name>ClientFileSendDialogClass</name>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation>PVS - Dateiübertragung</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="131"/>
<source>Sending to:</source>
<translation>Senden an:</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="132"/>
<source>unknown</source>
<translation>unbekannt</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="127"/>
- <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="136"/>
<source>0</source>
<translation>0</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="135"/>
<source>/</source>
<translation>/</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation>&amp;Abbruch</translation>
</message>
@@ -318,40 +415,45 @@
<context>
<name>ClientNicklistDialogClass</name>
<message>
- <location filename="../build/ui_clientNicklistDialog.h" line="84"/>
+ <location filename="../build/ui_clientNicklistDialog.h" line="91"/>
<source>PVS - Users</source>
<translation>PVS - Benutzer</translation>
</message>
<message>
- <location filename="../build/ui_clientNicklistDialog.h" line="85"/>
+ <location filename="../build/ui_clientNicklistDialog.h" line="92"/>
<source>Select user:</source>
<translation>Benutzer auswählen:</translation>
</message>
+ <message>
+ <location filename="../build/ui_clientNicklistDialog.h" line="93"/>
+ <source>Send to &amp;all</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientToolbarClass</name>
<message>
- <location filename="../build/ui_clientToolbar.h" line="166"/>
+ <location filename="../build/ui_clientToolbar.h" line="160"/>
<source>Form</source>
<translation></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="168"/>
+ <location filename="../build/ui_clientToolbar.h" line="162"/>
<source>Menu</source>
<translation>Menü</translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="170"/>
+ <location filename="../build/ui_clientToolbar.h" line="164"/>
<source>Host:</source>
<translation></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="172"/>
+ <location filename="../build/ui_clientToolbar.h" line="166"/>
<source>Click to connect</source>
<translation>Zum Verbinden Klicken</translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="174"/>
+ <location filename="../build/ui_clientToolbar.h" line="168"/>
<source>-</source>
<translation></translation>
</message>
@@ -363,15 +465,6 @@
<source>Allow VNC</source>
<translation type="obsolete">VNC erlauben</translation>
</message>
- <message>
- <location filename="../build/ui_clientToolbar.h" line="175"/>
- <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;DejaVu Sans&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600; font-style:italic; color:#0055ff;&quot;&gt;Pool Video Switch&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
- <translation></translation>
- </message>
</context>
<context>
<name>InfoDialogClass</name>
@@ -402,125 +495,142 @@ p, li { white-space: pre-wrap; }
<context>
<name>PVSGUI</name>
<message>
- <location filename="../src/pvsgui.cpp" line="35"/>
+ <location filename="../src/pvsgui.cpp" line="40"/>
<source>Connect</source>
<translation>Verbinden</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="189"/>
+ <location filename="../src/pvsgui.cpp" line="230"/>
<source>Show &amp;toolbar</source>
<translation>&amp;Werkzeugleiste anzeigen</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="191"/>
+ <location filename="../src/pvsgui.cpp" line="232"/>
<source>&amp;Disconnect</source>
<translation>&amp;Trennen</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="192"/>
+ <location filename="../src/pvsgui.cpp" line="233"/>
<source>C&amp;hat</source>
<translation></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="193"/>
+ <location filename="../src/pvsgui.cpp" line="234"/>
<source>&amp;Send File</source>
<translation>Datei &amp;Senden</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="194"/>
+ <location filename="../src/pvsgui.cpp" line="235"/>
<source>&amp;Config</source>
<translation>&amp;Konfiguration</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="195"/>
+ <location filename="../src/pvsgui.cpp" line="236"/>
<source>&amp;Information</source>
<translation>&amp;Information</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="196"/>
+ <location filename="../src/pvsgui.cpp" line="237"/>
<source>&amp;About</source>
<translation>&amp;Ãœber</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="197"/>
+ <location filename="../src/pvsgui.cpp" line="238"/>
<source>&amp;Quit</source>
<translation>&amp;Beenden</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="285"/>
- <location filename="../src/pvsgui.cpp" line="300"/>
- <location filename="../src/pvsgui.cpp" line="380"/>
+ <location filename="../src/pvsgui.cpp" line="290"/>
+ <location filename="../src/pvsgui.cpp" line="305"/>
+ <location filename="../src/pvsgui.cpp" line="385"/>
<source>PVS Connection</source>
<translation>PVS Verbindung</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="285"/>
+ <location filename="../src/pvsgui.cpp" line="290"/>
<source>Please enter password (If not needed leave blank):</source>
<translation>Bitte geben sie ein Passwor ein (Falls nicht erforderlich einfach leer lassen):</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="301"/>
+ <location filename="../src/pvsgui.cpp" line="306"/>
<source>Are you sure you want to disconnect?</source>
<translation>Sind sie sicher dass sie die Verbindung trennen möchten?</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="324"/>
- <location filename="../src/pvsgui.cpp" line="346"/>
+ <location filename="../src/pvsgui.cpp" line="329"/>
+ <location filename="../src/pvsgui.cpp" line="351"/>
<source>PVS connection</source>
<translation>PVS Verbindung</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="324"/>
- <location filename="../src/pvsgui.cpp" line="338"/>
+ <location filename="../src/pvsgui.cpp" line="329"/>
+ <location filename="../src/pvsgui.cpp" line="343"/>
<source>Connected to </source>
<translation>Verbunden mit </translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="346"/>
- <location filename="../src/pvsgui.cpp" line="358"/>
+ <location filename="../src/pvsgui.cpp" line="351"/>
+ <location filename="../src/pvsgui.cpp" line="363"/>
<source>Disconnected</source>
<translation>Getrennt</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="380"/>
+ <location filename="../src/pvsgui.cpp" line="385"/>
<source>New host available: </source>
<translation>Neuer Host verfügbar: </translation>
</message>
</context>
<context>
+ <name>PVSNetworkInterfaceListModel</name>
+ <message>
+ <location filename="../src/net/pvsNetworkInterfaceListModel.cpp" line="63"/>
+ <source>Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
- <location filename="../src/pvsgui.cpp" line="419"/>
+ <location filename="../src/pvsgui.cpp" line="430"/>
<source>Usage: pvsgui [OPTIONS]...</source>
<translation>Aufruf: pvsgui [OPTIONEN]...</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="420"/>
+ <location filename="../src/pvsgui.cpp" line="431"/>
<source>Start the Pool Video Switch GUI.</source>
<translation>Startet die Pool Video Switch GUI.</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="421"/>
+ <location filename="../src/pvsgui.cpp" line="432"/>
<source>Options:</source>
<translation>Optionen:</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="422"/>
+ <location filename="../src/pvsgui.cpp" line="433"/>
+ <source>Start with toolbar.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/pvsgui.cpp" line="434"/>
+ <source>Set toolbar position (0-5)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<source>Start only with systray icon.</source>
- <translation>Starte nur mit Symbol in Systray.</translation>
+ <translation type="obsolete">Starte nur mit Symbol in Systray.</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="423"/>
+ <location filename="../src/pvsgui.cpp" line="435"/>
<source>Show this help text and quit.</source>
<translation>Zeige diesen Hilfetext an und beende.</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="424"/>
+ <location filename="../src/pvsgui.cpp" line="436"/>
<source>Show version and quit.</source>
<translation>Zeige Versionsinformationen an und beende.</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="433"/>
+ <location filename="../src/pvsgui.cpp" line="445"/>
<source>Version: </source>
<translation>Version: </translation>
</message>
diff --git a/i18n/pvsgui_es_MX.ts b/i18n/pvsgui_es_MX.ts
index d3cb2d6..5fddda9 100644
--- a/i18n/pvsgui_es_MX.ts
+++ b/i18n/pvsgui_es_MX.ts
@@ -101,158 +101,199 @@
<context>
<name>ClientConfigDialogClass</name>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="200"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="248"/>
<source>PVS - Configuration</source>
<translation>PVS - Configuración</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="201"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="249"/>
<source>Allow vnc access to lecturer?</source>
<translation>Permitir al profesor el acceso VNC?</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="202"/>
- <location filename="../build/ui_clientConfigDialog.h" line="206"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="250"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="254"/>
<source>Full access</source>
<translation>Acceso completo</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="203"/>
- <location filename="../build/ui_clientConfigDialog.h" line="207"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="251"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="255"/>
<source>View only</source>
<translation>Solo ver</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="204"/>
- <location filename="../build/ui_clientConfigDialog.h" line="208"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="252"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="256"/>
<source>None</source>
<translation>Ninguno</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="205"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="253"/>
<source>Allow vnc access to other?</source>
<translation>Permitir a otros el acceso VNC?</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="209"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="257"/>
<source>Accept chat messages</source>
<translation>Aceptar mensages de chat?</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="210"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="258"/>
<source>Accept file transfers</source>
<translation>Aceptar transferencias de datos?</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="211"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="259"/>
<source>Permissions</source>
<translation>Permisos</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="214"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="262"/>
<source>Top Left</source>
<translation>Esquina superior izquierda</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="215"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="263"/>
<source>Top Center</source>
<translation>Arriba centrado</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="216"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="264"/>
<source>Top Right</source>
<translation>Esquina superion derecha</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="217"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="265"/>
<source>Bottom Left</source>
<translation>Esquina inferior izquierda</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="218"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="266"/>
<source>Bottom Center</source>
<translation>Abajo centrado</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="219"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="267"/>
<source>Bottom Right</source>
<translation>Esquina inferior derecha</translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="221"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="269"/>
<source>Display</source>
<translation>Pantalla</translation>
</message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="270"/>
+ <source>Network Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="271"/>
+ <source>Reload List</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="272"/>
+ <source>Network</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientFileReceiveDialog</name>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="63"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="101"/>
<source>PVS File Transfer</source>
<translation>PVS Transferencia de datos</translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="63"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="101"/>
<source>User &apos;</source>
<translation>Usuario &apos;</translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="64"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="102"/>
<source>&apos; would like to send you a file: </source>
<translation>&apos; desea enviarle un archivo: </translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="75"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="113"/>
<source>Open File</source>
<translation>Abiri archivo</translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="150"/>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="156"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="188"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="194"/>
<source>PVS - File Transfer</source>
<translation>PVS - Transferencia de datos</translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="151"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="189"/>
<source>File Transfer complete.</source>
<translation>La transferencia de datos ha sido completada.</translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="157"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="195"/>
<source>File Transfer canceled!</source>
<translation>La transferencia de datos ha sido cancelada!</translation>
</message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="232"/>
+ <source>Where should I save %1?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="242"/>
+ <source>Could not rename file</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="242"/>
+ <source>Failed to rename %1 to %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="254"/>
+ <source>File transfer failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="254"/>
+ <source>File transfer failed for the following reason:
+%1</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientFileReceiveDialogClass</name>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation>PVS - Transferencia de datos</translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="131"/>
<source>Receiving from:</source>
<translation>Recibiendo de:</translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="132"/>
<source>unknown</source>
<translation>desconocido</translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="127"/>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="136"/>
<source>0</source>
<translation>0</translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="135"/>
<source>/</source>
<translation>/</translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation>&amp;Cancelar</translation>
</message>
@@ -260,57 +301,113 @@
<context>
<name>ClientFileSendDialog</name>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="66"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="78"/>
<source>Open File</source>
<translation>Abrir archivo</translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="184"/>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="190"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="90"/>
+ <source>Send File</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="110"/>
+ <source>all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="111"/>
+ <source>Waiting to start</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="123"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="129"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="141"/>
+ <source>File Send error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="123"/>
+ <source>Error communicating with backend: %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="129"/>
+ <source>Something went wrong while communicating with backend, but I don&apos;t know what.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="141"/>
+ <source>Could not create a multicast transfer: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="207"/>
+ <source>Receiver declined</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="265"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="271"/>
<source>PVS - File Transfer</source>
<translation>PVS - Transferencia de datos</translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="185"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="266"/>
<source>File Transfer complete.</source>
<translation>La transferencia de datos ha sido completada.</translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="191"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="272"/>
+ <source>File Transfer canceled: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="284"/>
+ <source>You clicked &apos;Cancel&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="291"/>
+ <source>Socket Error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<source>File Transfer canceled!</source>
- <translation>La transferencia de datos ha sido cancelada!</translation>
+ <translation type="obsolete">La transferencia de datos ha sido cancelada!</translation>
</message>
</context>
<context>
<name>ClientFileSendDialogClass</name>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation>PVS - Transferencia de datos</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="131"/>
<source>Sending to:</source>
<translation>Enviando a:</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="132"/>
<source>unknown</source>
<translation>desconocido</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="127"/>
- <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="136"/>
<source>0</source>
<translation>0</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="135"/>
<source>/</source>
<translation>/</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation>&amp;Cancelar</translation>
</message>
@@ -318,40 +415,45 @@
<context>
<name>ClientNicklistDialogClass</name>
<message>
- <location filename="../build/ui_clientNicklistDialog.h" line="84"/>
+ <location filename="../build/ui_clientNicklistDialog.h" line="91"/>
<source>PVS - Users</source>
<translation>PVS - Usuarios</translation>
</message>
<message>
- <location filename="../build/ui_clientNicklistDialog.h" line="85"/>
+ <location filename="../build/ui_clientNicklistDialog.h" line="92"/>
<source>Select user:</source>
<translation>Seleccionar usuario:</translation>
</message>
+ <message>
+ <location filename="../build/ui_clientNicklistDialog.h" line="93"/>
+ <source>Send to &amp;all</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientToolbarClass</name>
<message>
- <location filename="../build/ui_clientToolbar.h" line="166"/>
+ <location filename="../build/ui_clientToolbar.h" line="160"/>
<source>Form</source>
<translation>de</translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="168"/>
+ <location filename="../build/ui_clientToolbar.h" line="162"/>
<source>Menu</source>
<translation>Menu</translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="170"/>
+ <location filename="../build/ui_clientToolbar.h" line="164"/>
<source>Host:</source>
<translation>Host:</translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="172"/>
+ <location filename="../build/ui_clientToolbar.h" line="166"/>
<source>Click to connect</source>
<translation>Click para conectar</translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="174"/>
+ <location filename="../build/ui_clientToolbar.h" line="168"/>
<source>-</source>
<translation>-</translation>
</message>
@@ -364,13 +466,12 @@
<translation type="obsolete">Permitir VNC</translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="175"/>
<source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;DejaVu Sans&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600; font-style:italic; color:#0055ff;&quot;&gt;Pool Video Switch&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
- <translation>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+ <translation type="obsolete">&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;DejaVu Sans&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
@@ -414,125 +515,138 @@ p, li { white-space: pre-wrap; }
<context>
<name>PVSGUI</name>
<message>
- <location filename="../src/pvsgui.cpp" line="35"/>
+ <location filename="../src/pvsgui.cpp" line="40"/>
<source>Connect</source>
<translation>Conectar</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="189"/>
+ <location filename="../src/pvsgui.cpp" line="230"/>
<source>Show &amp;toolbar</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="191"/>
+ <location filename="../src/pvsgui.cpp" line="232"/>
<source>&amp;Disconnect</source>
<translation>&amp;Desconectar</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="192"/>
+ <location filename="../src/pvsgui.cpp" line="233"/>
<source>C&amp;hat</source>
<translation>???</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="193"/>
+ <location filename="../src/pvsgui.cpp" line="234"/>
<source>&amp;Send File</source>
<translation>&amp;Enviar archivo</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="194"/>
+ <location filename="../src/pvsgui.cpp" line="235"/>
<source>&amp;Config</source>
<translation>&amp;Configuración</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="195"/>
+ <location filename="../src/pvsgui.cpp" line="236"/>
<source>&amp;Information</source>
<translation>&amp;Información</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="196"/>
+ <location filename="../src/pvsgui.cpp" line="237"/>
<source>&amp;About</source>
<translation>&amp;Acerca de</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="197"/>
+ <location filename="../src/pvsgui.cpp" line="238"/>
<source>&amp;Quit</source>
<translation>&amp;Cerrar</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="285"/>
- <location filename="../src/pvsgui.cpp" line="300"/>
- <location filename="../src/pvsgui.cpp" line="380"/>
+ <location filename="../src/pvsgui.cpp" line="290"/>
+ <location filename="../src/pvsgui.cpp" line="305"/>
+ <location filename="../src/pvsgui.cpp" line="385"/>
<source>PVS Connection</source>
<translation>PVS Connección</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="285"/>
+ <location filename="../src/pvsgui.cpp" line="290"/>
<source>Please enter password (If not needed leave blank):</source>
<translation>Porfavor ingrese una contraseña (Deje la seccion vacia si no lo necesita):</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="301"/>
+ <location filename="../src/pvsgui.cpp" line="306"/>
<source>Are you sure you want to disconnect?</source>
<translation>Realmente desea desconectarse?</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="324"/>
- <location filename="../src/pvsgui.cpp" line="346"/>
+ <location filename="../src/pvsgui.cpp" line="329"/>
+ <location filename="../src/pvsgui.cpp" line="351"/>
<source>PVS connection</source>
<translation>PVS Connección</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="324"/>
- <location filename="../src/pvsgui.cpp" line="338"/>
+ <location filename="../src/pvsgui.cpp" line="329"/>
+ <location filename="../src/pvsgui.cpp" line="343"/>
<source>Connected to </source>
<translation>Connectar a </translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="346"/>
- <location filename="../src/pvsgui.cpp" line="358"/>
+ <location filename="../src/pvsgui.cpp" line="351"/>
+ <location filename="../src/pvsgui.cpp" line="363"/>
<source>Disconnected</source>
<translation>Desconectado</translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="380"/>
+ <location filename="../src/pvsgui.cpp" line="385"/>
<source>New host available: </source>
<translation>Nuevo Host disponible: </translation>
</message>
</context>
<context>
+ <name>PVSNetworkInterfaceListModel</name>
+ <message>
+ <location filename="../src/net/pvsNetworkInterfaceListModel.cpp" line="63"/>
+ <source>Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
- <location filename="../src/pvsgui.cpp" line="419"/>
+ <location filename="../src/pvsgui.cpp" line="430"/>
<source>Usage: pvsgui [OPTIONS]...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="420"/>
+ <location filename="../src/pvsgui.cpp" line="431"/>
<source>Start the Pool Video Switch GUI.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="421"/>
+ <location filename="../src/pvsgui.cpp" line="432"/>
<source>Options:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="422"/>
- <source>Start only with systray icon.</source>
+ <location filename="../src/pvsgui.cpp" line="433"/>
+ <source>Start with toolbar.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="423"/>
+ <location filename="../src/pvsgui.cpp" line="434"/>
+ <source>Set toolbar position (0-5)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/pvsgui.cpp" line="435"/>
<source>Show this help text and quit.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="424"/>
+ <location filename="../src/pvsgui.cpp" line="436"/>
<source>Show version and quit.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="433"/>
+ <location filename="../src/pvsgui.cpp" line="445"/>
<source>Version: </source>
<translation type="unfinished">Version: </translation>
</message>
diff --git a/i18n/pvsgui_fr_FR.ts b/i18n/pvsgui_fr_FR.ts
index 59b40b9..65f432c 100644
--- a/i18n/pvsgui_fr_FR.ts
+++ b/i18n/pvsgui_fr_FR.ts
@@ -101,158 +101,199 @@
<context>
<name>ClientConfigDialogClass</name>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="200"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="248"/>
<source>PVS - Configuration</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="201"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="249"/>
<source>Allow vnc access to lecturer?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="202"/>
- <location filename="../build/ui_clientConfigDialog.h" line="206"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="250"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="254"/>
<source>Full access</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="203"/>
- <location filename="../build/ui_clientConfigDialog.h" line="207"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="251"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="255"/>
<source>View only</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="204"/>
- <location filename="../build/ui_clientConfigDialog.h" line="208"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="252"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="256"/>
<source>None</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="205"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="253"/>
<source>Allow vnc access to other?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="209"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="257"/>
<source>Accept chat messages</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="210"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="258"/>
<source>Accept file transfers</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="211"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="259"/>
<source>Permissions</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="214"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="262"/>
<source>Top Left</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="215"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="263"/>
<source>Top Center</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="216"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="264"/>
<source>Top Right</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="217"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="265"/>
<source>Bottom Left</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="218"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="266"/>
<source>Bottom Center</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="219"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="267"/>
<source>Bottom Right</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="221"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="269"/>
<source>Display</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="270"/>
+ <source>Network Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="271"/>
+ <source>Reload List</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="272"/>
+ <source>Network</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientFileReceiveDialog</name>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="63"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="101"/>
<source>PVS File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="63"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="101"/>
<source>User &apos;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="64"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="102"/>
<source>&apos; would like to send you a file: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="75"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="113"/>
<source>Open File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="150"/>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="156"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="188"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="194"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="151"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="189"/>
<source>File Transfer complete.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="157"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="195"/>
<source>File Transfer canceled!</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="232"/>
+ <source>Where should I save %1?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="242"/>
+ <source>Could not rename file</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="242"/>
+ <source>Failed to rename %1 to %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="254"/>
+ <source>File transfer failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="254"/>
+ <source>File transfer failed for the following reason:
+%1</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientFileReceiveDialogClass</name>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="131"/>
<source>Receiving from:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="132"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="127"/>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="136"/>
<source>0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="135"/>
<source>/</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation type="unfinished"></translation>
</message>
@@ -260,57 +301,109 @@
<context>
<name>ClientFileSendDialog</name>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="66"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="78"/>
<source>Open File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="184"/>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="190"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="90"/>
+ <source>Send File</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="110"/>
+ <source>all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="111"/>
+ <source>Waiting to start</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="123"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="129"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="141"/>
+ <source>File Send error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="123"/>
+ <source>Error communicating with backend: %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="129"/>
+ <source>Something went wrong while communicating with backend, but I don&apos;t know what.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="141"/>
+ <source>Could not create a multicast transfer: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="207"/>
+ <source>Receiver declined</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="265"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="271"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="185"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="266"/>
<source>File Transfer complete.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="191"/>
- <source>File Transfer canceled!</source>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="272"/>
+ <source>File Transfer canceled: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="284"/>
+ <source>You clicked &apos;Cancel&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="291"/>
+ <source>Socket Error</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ClientFileSendDialogClass</name>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="131"/>
<source>Sending to:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="132"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="127"/>
- <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="136"/>
<source>0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="135"/>
<source>/</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation type="unfinished"></translation>
</message>
@@ -318,52 +411,48 @@
<context>
<name>ClientNicklistDialogClass</name>
<message>
- <location filename="../build/ui_clientNicklistDialog.h" line="84"/>
+ <location filename="../build/ui_clientNicklistDialog.h" line="91"/>
<source>PVS - Users</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientNicklistDialog.h" line="85"/>
+ <location filename="../build/ui_clientNicklistDialog.h" line="92"/>
<source>Select user:</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../build/ui_clientNicklistDialog.h" line="93"/>
+ <source>Send to &amp;all</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientToolbarClass</name>
<message>
- <location filename="../build/ui_clientToolbar.h" line="166"/>
+ <location filename="../build/ui_clientToolbar.h" line="160"/>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="168"/>
+ <location filename="../build/ui_clientToolbar.h" line="162"/>
<source>Menu</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="170"/>
+ <location filename="../build/ui_clientToolbar.h" line="164"/>
<source>Host:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="172"/>
+ <location filename="../build/ui_clientToolbar.h" line="166"/>
<source>Click to connect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="174"/>
+ <location filename="../build/ui_clientToolbar.h" line="168"/>
<source>-</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location filename="../build/ui_clientToolbar.h" line="175"/>
- <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;DejaVu Sans&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600; font-style:italic; color:#0055ff;&quot;&gt;Pool Video Switch&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>InfoDialogClass</name>
@@ -394,125 +483,138 @@ p, li { white-space: pre-wrap; }
<context>
<name>PVSGUI</name>
<message>
- <location filename="../src/pvsgui.cpp" line="35"/>
+ <location filename="../src/pvsgui.cpp" line="40"/>
<source>Connect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="189"/>
+ <location filename="../src/pvsgui.cpp" line="230"/>
<source>Show &amp;toolbar</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="191"/>
+ <location filename="../src/pvsgui.cpp" line="232"/>
<source>&amp;Disconnect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="192"/>
+ <location filename="../src/pvsgui.cpp" line="233"/>
<source>C&amp;hat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="193"/>
+ <location filename="../src/pvsgui.cpp" line="234"/>
<source>&amp;Send File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="194"/>
+ <location filename="../src/pvsgui.cpp" line="235"/>
<source>&amp;Config</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="195"/>
+ <location filename="../src/pvsgui.cpp" line="236"/>
<source>&amp;Information</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="196"/>
+ <location filename="../src/pvsgui.cpp" line="237"/>
<source>&amp;About</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="197"/>
+ <location filename="../src/pvsgui.cpp" line="238"/>
<source>&amp;Quit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="285"/>
- <location filename="../src/pvsgui.cpp" line="300"/>
- <location filename="../src/pvsgui.cpp" line="380"/>
+ <location filename="../src/pvsgui.cpp" line="290"/>
+ <location filename="../src/pvsgui.cpp" line="305"/>
+ <location filename="../src/pvsgui.cpp" line="385"/>
<source>PVS Connection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="285"/>
+ <location filename="../src/pvsgui.cpp" line="290"/>
<source>Please enter password (If not needed leave blank):</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="301"/>
+ <location filename="../src/pvsgui.cpp" line="306"/>
<source>Are you sure you want to disconnect?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="324"/>
- <location filename="../src/pvsgui.cpp" line="346"/>
+ <location filename="../src/pvsgui.cpp" line="329"/>
+ <location filename="../src/pvsgui.cpp" line="351"/>
<source>PVS connection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="324"/>
- <location filename="../src/pvsgui.cpp" line="338"/>
+ <location filename="../src/pvsgui.cpp" line="329"/>
+ <location filename="../src/pvsgui.cpp" line="343"/>
<source>Connected to </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="346"/>
- <location filename="../src/pvsgui.cpp" line="358"/>
+ <location filename="../src/pvsgui.cpp" line="351"/>
+ <location filename="../src/pvsgui.cpp" line="363"/>
<source>Disconnected</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="380"/>
+ <location filename="../src/pvsgui.cpp" line="385"/>
<source>New host available: </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
+ <name>PVSNetworkInterfaceListModel</name>
+ <message>
+ <location filename="../src/net/pvsNetworkInterfaceListModel.cpp" line="63"/>
+ <source>Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
- <location filename="../src/pvsgui.cpp" line="419"/>
+ <location filename="../src/pvsgui.cpp" line="430"/>
<source>Usage: pvsgui [OPTIONS]...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="420"/>
+ <location filename="../src/pvsgui.cpp" line="431"/>
<source>Start the Pool Video Switch GUI.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="421"/>
+ <location filename="../src/pvsgui.cpp" line="432"/>
<source>Options:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="422"/>
- <source>Start only with systray icon.</source>
+ <location filename="../src/pvsgui.cpp" line="433"/>
+ <source>Start with toolbar.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="423"/>
+ <location filename="../src/pvsgui.cpp" line="434"/>
+ <source>Set toolbar position (0-5)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/pvsgui.cpp" line="435"/>
<source>Show this help text and quit.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="424"/>
+ <location filename="../src/pvsgui.cpp" line="436"/>
<source>Show version and quit.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="433"/>
+ <location filename="../src/pvsgui.cpp" line="445"/>
<source>Version: </source>
<translation type="unfinished"></translation>
</message>
diff --git a/i18n/pvsgui_pl_PL.ts b/i18n/pvsgui_pl_PL.ts
index 59b40b9..65f432c 100644
--- a/i18n/pvsgui_pl_PL.ts
+++ b/i18n/pvsgui_pl_PL.ts
@@ -101,158 +101,199 @@
<context>
<name>ClientConfigDialogClass</name>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="200"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="248"/>
<source>PVS - Configuration</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="201"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="249"/>
<source>Allow vnc access to lecturer?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="202"/>
- <location filename="../build/ui_clientConfigDialog.h" line="206"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="250"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="254"/>
<source>Full access</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="203"/>
- <location filename="../build/ui_clientConfigDialog.h" line="207"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="251"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="255"/>
<source>View only</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="204"/>
- <location filename="../build/ui_clientConfigDialog.h" line="208"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="252"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="256"/>
<source>None</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="205"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="253"/>
<source>Allow vnc access to other?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="209"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="257"/>
<source>Accept chat messages</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="210"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="258"/>
<source>Accept file transfers</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="211"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="259"/>
<source>Permissions</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="214"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="262"/>
<source>Top Left</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="215"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="263"/>
<source>Top Center</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="216"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="264"/>
<source>Top Right</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="217"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="265"/>
<source>Bottom Left</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="218"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="266"/>
<source>Bottom Center</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="219"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="267"/>
<source>Bottom Right</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientConfigDialog.h" line="221"/>
+ <location filename="../build/ui_clientConfigDialog.h" line="269"/>
<source>Display</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="270"/>
+ <source>Network Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="271"/>
+ <source>Reload List</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_clientConfigDialog.h" line="272"/>
+ <source>Network</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientFileReceiveDialog</name>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="63"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="101"/>
<source>PVS File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="63"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="101"/>
<source>User &apos;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="64"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="102"/>
<source>&apos; would like to send you a file: </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="75"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="113"/>
<source>Open File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="150"/>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="156"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="188"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="194"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="151"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="189"/>
<source>File Transfer complete.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileReceiveDialog.cpp" line="157"/>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="195"/>
<source>File Transfer canceled!</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="232"/>
+ <source>Where should I save %1?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="242"/>
+ <source>Could not rename file</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="242"/>
+ <source>Failed to rename %1 to %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="254"/>
+ <source>File transfer failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileReceiveDialog.cpp" line="254"/>
+ <source>File transfer failed for the following reason:
+%1</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientFileReceiveDialogClass</name>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="131"/>
<source>Receiving from:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="132"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="127"/>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="136"/>
<source>0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="135"/>
<source>/</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileReceiveDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileReceiveDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation type="unfinished"></translation>
</message>
@@ -260,57 +301,109 @@
<context>
<name>ClientFileSendDialog</name>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="66"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="78"/>
<source>Open File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="184"/>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="190"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="90"/>
+ <source>Send File</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="110"/>
+ <source>all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="111"/>
+ <source>Waiting to start</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="123"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="129"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="141"/>
+ <source>File Send error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="123"/>
+ <source>Error communicating with backend: %1: %2</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="129"/>
+ <source>Something went wrong while communicating with backend, but I don&apos;t know what.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="141"/>
+ <source>Could not create a multicast transfer: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="207"/>
+ <source>Receiver declined</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="265"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="271"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="185"/>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="266"/>
<source>File Transfer complete.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/clientFileSendDialog.cpp" line="191"/>
- <source>File Transfer canceled!</source>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="272"/>
+ <source>File Transfer canceled: %1</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="284"/>
+ <source>You clicked &apos;Cancel&apos;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/clientFileSendDialog.cpp" line="291"/>
+ <source>Socket Error</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ClientFileSendDialogClass</name>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="131"/>
<source>Sending to:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="132"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="127"/>
- <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="136"/>
<source>0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="135"/>
<source>/</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation type="unfinished"></translation>
</message>
@@ -318,52 +411,48 @@
<context>
<name>ClientNicklistDialogClass</name>
<message>
- <location filename="../build/ui_clientNicklistDialog.h" line="84"/>
+ <location filename="../build/ui_clientNicklistDialog.h" line="91"/>
<source>PVS - Users</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientNicklistDialog.h" line="85"/>
+ <location filename="../build/ui_clientNicklistDialog.h" line="92"/>
<source>Select user:</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../build/ui_clientNicklistDialog.h" line="93"/>
+ <source>Send to &amp;all</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ClientToolbarClass</name>
<message>
- <location filename="../build/ui_clientToolbar.h" line="166"/>
+ <location filename="../build/ui_clientToolbar.h" line="160"/>
<source>Form</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="168"/>
+ <location filename="../build/ui_clientToolbar.h" line="162"/>
<source>Menu</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="170"/>
+ <location filename="../build/ui_clientToolbar.h" line="164"/>
<source>Host:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="172"/>
+ <location filename="../build/ui_clientToolbar.h" line="166"/>
<source>Click to connect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientToolbar.h" line="174"/>
+ <location filename="../build/ui_clientToolbar.h" line="168"/>
<source>-</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location filename="../build/ui_clientToolbar.h" line="175"/>
- <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;DejaVu Sans&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:10pt; font-weight:600; font-style:italic; color:#0055ff;&quot;&gt;Pool Video Switch&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>InfoDialogClass</name>
@@ -394,125 +483,138 @@ p, li { white-space: pre-wrap; }
<context>
<name>PVSGUI</name>
<message>
- <location filename="../src/pvsgui.cpp" line="35"/>
+ <location filename="../src/pvsgui.cpp" line="40"/>
<source>Connect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="189"/>
+ <location filename="../src/pvsgui.cpp" line="230"/>
<source>Show &amp;toolbar</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="191"/>
+ <location filename="../src/pvsgui.cpp" line="232"/>
<source>&amp;Disconnect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="192"/>
+ <location filename="../src/pvsgui.cpp" line="233"/>
<source>C&amp;hat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="193"/>
+ <location filename="../src/pvsgui.cpp" line="234"/>
<source>&amp;Send File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="194"/>
+ <location filename="../src/pvsgui.cpp" line="235"/>
<source>&amp;Config</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="195"/>
+ <location filename="../src/pvsgui.cpp" line="236"/>
<source>&amp;Information</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="196"/>
+ <location filename="../src/pvsgui.cpp" line="237"/>
<source>&amp;About</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="197"/>
+ <location filename="../src/pvsgui.cpp" line="238"/>
<source>&amp;Quit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="285"/>
- <location filename="../src/pvsgui.cpp" line="300"/>
- <location filename="../src/pvsgui.cpp" line="380"/>
+ <location filename="../src/pvsgui.cpp" line="290"/>
+ <location filename="../src/pvsgui.cpp" line="305"/>
+ <location filename="../src/pvsgui.cpp" line="385"/>
<source>PVS Connection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="285"/>
+ <location filename="../src/pvsgui.cpp" line="290"/>
<source>Please enter password (If not needed leave blank):</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="301"/>
+ <location filename="../src/pvsgui.cpp" line="306"/>
<source>Are you sure you want to disconnect?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="324"/>
- <location filename="../src/pvsgui.cpp" line="346"/>
+ <location filename="../src/pvsgui.cpp" line="329"/>
+ <location filename="../src/pvsgui.cpp" line="351"/>
<source>PVS connection</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="324"/>
- <location filename="../src/pvsgui.cpp" line="338"/>
+ <location filename="../src/pvsgui.cpp" line="329"/>
+ <location filename="../src/pvsgui.cpp" line="343"/>
<source>Connected to </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="346"/>
- <location filename="../src/pvsgui.cpp" line="358"/>
+ <location filename="../src/pvsgui.cpp" line="351"/>
+ <location filename="../src/pvsgui.cpp" line="363"/>
<source>Disconnected</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="380"/>
+ <location filename="../src/pvsgui.cpp" line="385"/>
<source>New host available: </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
+ <name>PVSNetworkInterfaceListModel</name>
+ <message>
+ <location filename="../src/net/pvsNetworkInterfaceListModel.cpp" line="63"/>
+ <source>Interface</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>QObject</name>
<message>
- <location filename="../src/pvsgui.cpp" line="419"/>
+ <location filename="../src/pvsgui.cpp" line="430"/>
<source>Usage: pvsgui [OPTIONS]...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="420"/>
+ <location filename="../src/pvsgui.cpp" line="431"/>
<source>Start the Pool Video Switch GUI.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="421"/>
+ <location filename="../src/pvsgui.cpp" line="432"/>
<source>Options:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="422"/>
- <source>Start only with systray icon.</source>
+ <location filename="../src/pvsgui.cpp" line="433"/>
+ <source>Start with toolbar.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="423"/>
+ <location filename="../src/pvsgui.cpp" line="434"/>
+ <source>Set toolbar position (0-5)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/pvsgui.cpp" line="435"/>
<source>Show this help text and quit.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="424"/>
+ <location filename="../src/pvsgui.cpp" line="436"/>
<source>Show version and quit.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/pvsgui.cpp" line="433"/>
+ <location filename="../src/pvsgui.cpp" line="445"/>
<source>Version: </source>
<translation type="unfinished"></translation>
</message>
diff --git a/i18n/pvsmgr_ar_JO.ts b/i18n/pvsmgr_ar_JO.ts
index a5a9a8a..d434341 100644
--- a/i18n/pvsmgr_ar_JO.ts
+++ b/i18n/pvsmgr_ar_JO.ts
@@ -40,33 +40,33 @@
<context>
<name>ClientFileSendDialogClass</name>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="131"/>
<source>Sending to:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="132"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="127"/>
- <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="136"/>
<source>0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="135"/>
<source>/</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation type="unfinished"></translation>
</message>
@@ -270,420 +270,457 @@ Perform an unprojection or remove remote help to get a target.</source>
<context>
<name>Frame</name>
<message>
- <location filename="../src/gui/frame.cpp" line="49"/>
+ <location filename="../src/gui/frame.cpp" line="54"/>
<source>View</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="50"/>
+ <location filename="../src/gui/frame.cpp" line="55"/>
<source>Foto</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="51"/>
- <location filename="../src/gui/frame.cpp" line="276"/>
+ <location filename="../src/gui/frame.cpp" line="56"/>
+ <location filename="../src/gui/frame.cpp" line="323"/>
<source>Lock this client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="53"/>
+ <location filename="../src/gui/frame.cpp" line="58"/>
<source>Set as Superclient</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="271"/>
+ <location filename="../src/gui/frame.cpp" line="59"/>
+ <location filename="../src/gui/frame.cpp" line="387"/>
+ <source>Enable Remote Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="61"/>
+ <location filename="../src/gui/frame.cpp" line="414"/>
+ <source>Remote Control All Clients</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="318"/>
<source>Unlock this client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="311"/>
+ <location filename="../src/gui/frame.cpp" line="358"/>
<source>You can&apos;t lock a Superclient-machine.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="320"/>
+ <location filename="../src/gui/frame.cpp" line="367"/>
<source>Set client as Superclient</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="327"/>
+ <location filename="../src/gui/frame.cpp" line="374"/>
<source>Unset client as Superclient</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="394"/>
+ <source>Disable Remote Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="408"/>
+ <source>Remote Control only this Client</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>MainWindow</name>
<message>
- <location filename="../build/ui_mainwindow.h" line="410"/>
- <location filename="../src/gui/mainWindow.cpp" line="122"/>
+ <location filename="../build/ui_mainwindow.h" line="418"/>
+ <location filename="../src/gui/mainWindow.cpp" line="126"/>
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="124"/>
+ <location filename="../src/gui/mainWindow.cpp" line="128"/>
<source>Remove the vnc-Connection for the selected client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="127"/>
+ <location filename="../src/gui/mainWindow.cpp" line="131"/>
<source>Show the selected client in the whole window</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="131"/>
+ <location filename="../src/gui/mainWindow.cpp" line="135"/>
<source>Make a screenshot for the selected client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="425"/>
- <location filename="../src/gui/mainWindow.cpp" line="132"/>
+ <location filename="../build/ui_mainwindow.h" line="433"/>
+ <location filename="../src/gui/mainWindow.cpp" line="136"/>
<source>Lock or Unlock all Clients</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="155"/>
+ <location filename="../src/gui/mainWindow.cpp" line="160"/>
<source>The pvs manager</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="741"/>
+ <location filename="../src/gui/mainWindow.cpp" line="745"/>
<source>This operation can only be performed for one selected Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="785"/>
+ <location filename="../src/gui/mainWindow.cpp" line="789"/>
<source>This operation can only be performed if you have selected a Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="824"/>
+ <location filename="../src/gui/mainWindow.cpp" line="828"/>
<source>This operation can only be performed for at least one selected Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1099"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1103"/>
<source>You have to set a Superclient-machine before performing this action.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1176"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1180"/>
<source>Open Image</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1177"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1181"/>
<source>Image Files (*.png *.jpg *.svg)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="383"/>
+ <location filename="../build/ui_mainwindow.h" line="391"/>
<source>PVSmgr</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="384"/>
+ <location filename="../build/ui_mainwindow.h" line="392"/>
<source>Show Username</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="385"/>
+ <location filename="../build/ui_mainwindow.h" line="393"/>
<source>Ctrl+3</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="386"/>
+ <location filename="../build/ui_mainwindow.h" line="394"/>
<source>Show IP</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="387"/>
+ <location filename="../build/ui_mainwindow.h" line="395"/>
<source>Ctrl+2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="388"/>
+ <location filename="../build/ui_mainwindow.h" line="396"/>
<source>VNC-Placeholders</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="389"/>
+ <location filename="../build/ui_mainwindow.h" line="397"/>
<source>Show Log</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="390"/>
+ <location filename="../build/ui_mainwindow.h" line="398"/>
<source>Ctrl+L</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="391"/>
+ <location filename="../build/ui_mainwindow.h" line="399"/>
<source>Show Normal</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="392"/>
+ <location filename="../build/ui_mainwindow.h" line="400"/>
<source>Ctrl+O</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="393"/>
+ <location filename="../build/ui_mainwindow.h" line="401"/>
<source>Show Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="394"/>
+ <location filename="../build/ui_mainwindow.h" line="402"/>
<source>Ctrl+E</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="395"/>
+ <location filename="../build/ui_mainwindow.h" line="403"/>
<source>Show Network</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="396"/>
+ <location filename="../build/ui_mainwindow.h" line="404"/>
<source>Ctrl+N</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="397"/>
+ <location filename="../build/ui_mainwindow.h" line="405"/>
<source>Show Terminal</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="398"/>
+ <location filename="../build/ui_mainwindow.h" line="406"/>
<source>Ctrl+T</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="399"/>
+ <location filename="../build/ui_mainwindow.h" line="407"/>
<source>Show Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="400"/>
+ <location filename="../build/ui_mainwindow.h" line="408"/>
<source>Ctrl+G</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="401"/>
+ <location filename="../build/ui_mainwindow.h" line="409"/>
<source>About pvs</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="402"/>
+ <location filename="../build/ui_mainwindow.h" line="410"/>
<source>Ctrl+P</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="403"/>
+ <location filename="../build/ui_mainwindow.h" line="411"/>
<source>100 x 100</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="404"/>
+ <location filename="../build/ui_mainwindow.h" line="412"/>
<source>200 x 200</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="405"/>
+ <location filename="../build/ui_mainwindow.h" line="413"/>
<source>500 x 500</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="406"/>
+ <location filename="../build/ui_mainwindow.h" line="414"/>
<source>&amp;Disconnect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="407"/>
+ <location filename="../build/ui_mainwindow.h" line="415"/>
<source>Ctrl+W</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="408"/>
+ <location filename="../build/ui_mainwindow.h" line="416"/>
<source>&amp;Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="412"/>
+ <location filename="../build/ui_mainwindow.h" line="420"/>
<source>Ctrl+Q</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="413"/>
- <location filename="../build/ui_mainwindow.h" line="415"/>
+ <location filename="../build/ui_mainwindow.h" line="421"/>
+ <location filename="../build/ui_mainwindow.h" line="423"/>
<source>Foto</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="417"/>
+ <location filename="../build/ui_mainwindow.h" line="425"/>
<source>Ctrl+F</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="418"/>
+ <location filename="../build/ui_mainwindow.h" line="426"/>
<source>view</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="420"/>
+ <location filename="../build/ui_mainwindow.h" line="428"/>
<source>View</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="422"/>
+ <location filename="../build/ui_mainwindow.h" line="430"/>
<source>Ctrl+V</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="423"/>
+ <location filename="../build/ui_mainwindow.h" line="431"/>
<source>lock</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="427"/>
+ <location filename="../build/ui_mainwindow.h" line="435"/>
<source>Ctrl+A</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="428"/>
+ <location filename="../build/ui_mainwindow.h" line="436"/>
<source>Profile &amp;manager</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="429"/>
+ <location filename="../build/ui_mainwindow.h" line="437"/>
<source>Ctrl+M</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="430"/>
+ <location filename="../build/ui_mainwindow.h" line="438"/>
<source>Show Name</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="431"/>
+ <location filename="../build/ui_mainwindow.h" line="439"/>
<source>Ctrl+1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="432"/>
+ <location filename="../build/ui_mainwindow.h" line="440"/>
<source>Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="434"/>
+ <location filename="../build/ui_mainwindow.h" line="442"/>
<source>Start Chat with client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="436"/>
+ <location filename="../build/ui_mainwindow.h" line="444"/>
<source>Ctrl+D</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="437"/>
+ <location filename="../build/ui_mainwindow.h" line="445"/>
<source>-</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="438"/>
+ <location filename="../build/ui_mainwindow.h" line="446"/>
+ <source>&amp;Configure...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="448"/>
+ <source>Configure Network Parameters</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="450"/>
<source>showProcesses</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="440"/>
- <location filename="../src/gui/mainWindow.cpp" line="135"/>
+ <location filename="../build/ui_mainwindow.h" line="452"/>
+ <location filename="../src/gui/mainWindow.cpp" line="140"/>
<source>Show Processes of the selected Client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="442"/>
+ <location filename="../build/ui_mainwindow.h" line="454"/>
<source>border-color: rgb(0, 0, 0);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="443"/>
+ <location filename="../build/ui_mainwindow.h" line="455"/>
<source>VNC quality</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="446"/>
+ <location filename="../build/ui_mainwindow.h" line="458"/>
<source>HIGH</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="447"/>
+ <location filename="../build/ui_mainwindow.h" line="459"/>
<source>MEDIUM</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="448"/>
+ <location filename="../build/ui_mainwindow.h" line="460"/>
<source>LOW</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="450"/>
+ <location filename="../build/ui_mainwindow.h" line="462"/>
<source>Set password</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="453"/>
+ <location filename="../build/ui_mainwindow.h" line="465"/>
<source>Thumbnailratio</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="454"/>
+ <location filename="../build/ui_mainwindow.h" line="466"/>
<source>Thumbnailrate</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="456"/>
+ <location filename="../build/ui_mainwindow.h" line="468"/>
<source> 0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="457"/>
+ <location filename="../build/ui_mainwindow.h" line="469"/>
<source>%</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="458"/>
+ <location filename="../build/ui_mainwindow.h" line="470"/>
<source>background-color: rgb(255, 255, 255);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="459"/>
+ <location filename="../build/ui_mainwindow.h" line="471"/>
<source>background-color: rgb(150, 150, 150);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="460"/>
+ <location filename="../build/ui_mainwindow.h" line="472"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="461"/>
+ <location filename="../build/ui_mainwindow.h" line="473"/>
<source>Load profile </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="462"/>
+ <location filename="../build/ui_mainwindow.h" line="474"/>
<source>&amp;Clients</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="463"/>
+ <location filename="../build/ui_mainwindow.h" line="475"/>
<source>&amp;Logging</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="464"/>
+ <location filename="../build/ui_mainwindow.h" line="476"/>
<source>&amp;Help</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="465"/>
+ <location filename="../build/ui_mainwindow.h" line="477"/>
+ <source>Network</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="478"/>
<source>toolBar</source>
<translation type="unfinished"></translation>
</message>
@@ -707,6 +744,102 @@ Perform an unprojection or remove remote help to get a target.</source>
</message>
</context>
<context>
+ <name>MulticastConfigDialog</name>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="81"/>
+ <source>OK</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="94"/>
+ <source>Not a valid IP Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="103"/>
+ <source>Not a valid IPv4 Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="113"/>
+ <source>Not an IPv4 multicast address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="133"/>
+ <source>Not a number</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="140"/>
+ <source>Must be positive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="147"/>
+ <source>Must not be a privileged port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="155"/>
+ <source>Port number too large</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MulticastConfigDialogClass</name>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="145"/>
+ <source>PVS - Multicast Configuration</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="146"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Sans Serif&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;table style=&quot;-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;&quot;&gt;
+&lt;tr&gt;
+&lt;td style=&quot;border: none;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You need to specify connection parameters for multicast messaging on your network. These parameters will automatically be distributed to client computers, so you need to assign them only once.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You will probably want to assign an address from the &lt;span style=&quot; text-decoration: underline;&quot;&gt;239.0.0.0/8&lt;/span&gt; &amp;quot;Administratively Scoped&amp;quot; range.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Do not assign arbitrary numbers without checking with your network administrator!&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="157"/>
+ <source>Multicast Group Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="158"/>
+ <source>...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="159"/>
+ <location filename="../build/ui_multicastConfigDialog.h" line="161"/>
+ <source>&lt;span style=&quot; font-weight:600; color:#008800;&quot;&gt;OK&lt;/span&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="160"/>
+ <source>Data Port (1024-65535)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="162"/>
+ <source>Transmission Rate</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="163"/>
+ <source> KiB/s</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>ProjectionDialog</name>
<message>
<location filename="../src/gui/projectionDialog.cpp" line="28"/>
diff --git a/i18n/pvsmgr_de_DE.ts b/i18n/pvsmgr_de_DE.ts
index a7ba2a0..921b5ba 100644
--- a/i18n/pvsmgr_de_DE.ts
+++ b/i18n/pvsmgr_de_DE.ts
@@ -40,33 +40,33 @@
<context>
<name>ClientFileSendDialogClass</name>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation>PVS - Dateiübertragung</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="131"/>
<source>Sending to:</source>
<translation>Senden an:</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="132"/>
<source>unknown</source>
<translation>unbekannt</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="127"/>
- <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="136"/>
<source>0</source>
<translation>0</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="135"/>
<source>/</source>
<translation>/</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation>&amp;Abbruch</translation>
</message>
@@ -270,420 +270,457 @@ Perform an unprojection or remove remote help to get a target.</source>
<context>
<name>Frame</name>
<message>
- <location filename="../src/gui/frame.cpp" line="49"/>
+ <location filename="../src/gui/frame.cpp" line="54"/>
<source>View</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="50"/>
+ <location filename="../src/gui/frame.cpp" line="55"/>
<source>Foto</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="51"/>
- <location filename="../src/gui/frame.cpp" line="276"/>
+ <location filename="../src/gui/frame.cpp" line="56"/>
+ <location filename="../src/gui/frame.cpp" line="323"/>
<source>Lock this client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="53"/>
+ <location filename="../src/gui/frame.cpp" line="58"/>
<source>Set as Superclient</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="271"/>
+ <location filename="../src/gui/frame.cpp" line="59"/>
+ <location filename="../src/gui/frame.cpp" line="387"/>
+ <source>Enable Remote Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="61"/>
+ <location filename="../src/gui/frame.cpp" line="414"/>
+ <source>Remote Control All Clients</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="318"/>
<source>Unlock this client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="311"/>
+ <location filename="../src/gui/frame.cpp" line="358"/>
<source>You can&apos;t lock a Superclient-machine.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="320"/>
+ <location filename="../src/gui/frame.cpp" line="367"/>
<source>Set client as Superclient</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="327"/>
+ <location filename="../src/gui/frame.cpp" line="374"/>
<source>Unset client as Superclient</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="394"/>
+ <source>Disable Remote Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="408"/>
+ <source>Remote Control only this Client</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>MainWindow</name>
<message>
- <location filename="../build/ui_mainwindow.h" line="410"/>
- <location filename="../src/gui/mainWindow.cpp" line="122"/>
+ <location filename="../build/ui_mainwindow.h" line="418"/>
+ <location filename="../src/gui/mainWindow.cpp" line="126"/>
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="124"/>
+ <location filename="../src/gui/mainWindow.cpp" line="128"/>
<source>Remove the vnc-Connection for the selected client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="127"/>
+ <location filename="../src/gui/mainWindow.cpp" line="131"/>
<source>Show the selected client in the whole window</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="131"/>
+ <location filename="../src/gui/mainWindow.cpp" line="135"/>
<source>Make a screenshot for the selected client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="425"/>
- <location filename="../src/gui/mainWindow.cpp" line="132"/>
+ <location filename="../build/ui_mainwindow.h" line="433"/>
+ <location filename="../src/gui/mainWindow.cpp" line="136"/>
<source>Lock or Unlock all Clients</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="155"/>
+ <location filename="../src/gui/mainWindow.cpp" line="160"/>
<source>The pvs manager</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="741"/>
+ <location filename="../src/gui/mainWindow.cpp" line="745"/>
<source>This operation can only be performed for one selected Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="785"/>
+ <location filename="../src/gui/mainWindow.cpp" line="789"/>
<source>This operation can only be performed if you have selected a Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="824"/>
+ <location filename="../src/gui/mainWindow.cpp" line="828"/>
<source>This operation can only be performed for at least one selected Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1099"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1103"/>
<source>You have to set a Superclient-machine before performing this action.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1176"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1180"/>
<source>Open Image</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1177"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1181"/>
<source>Image Files (*.png *.jpg *.svg)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="383"/>
+ <location filename="../build/ui_mainwindow.h" line="391"/>
<source>PVSmgr</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="384"/>
+ <location filename="../build/ui_mainwindow.h" line="392"/>
<source>Show Username</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="385"/>
+ <location filename="../build/ui_mainwindow.h" line="393"/>
<source>Ctrl+3</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="386"/>
+ <location filename="../build/ui_mainwindow.h" line="394"/>
<source>Show IP</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="387"/>
+ <location filename="../build/ui_mainwindow.h" line="395"/>
<source>Ctrl+2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="388"/>
+ <location filename="../build/ui_mainwindow.h" line="396"/>
<source>VNC-Placeholders</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="389"/>
+ <location filename="../build/ui_mainwindow.h" line="397"/>
<source>Show Log</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="390"/>
+ <location filename="../build/ui_mainwindow.h" line="398"/>
<source>Ctrl+L</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="391"/>
+ <location filename="../build/ui_mainwindow.h" line="399"/>
<source>Show Normal</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="392"/>
+ <location filename="../build/ui_mainwindow.h" line="400"/>
<source>Ctrl+O</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="393"/>
+ <location filename="../build/ui_mainwindow.h" line="401"/>
<source>Show Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="394"/>
+ <location filename="../build/ui_mainwindow.h" line="402"/>
<source>Ctrl+E</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="395"/>
+ <location filename="../build/ui_mainwindow.h" line="403"/>
<source>Show Network</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="396"/>
+ <location filename="../build/ui_mainwindow.h" line="404"/>
<source>Ctrl+N</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="397"/>
+ <location filename="../build/ui_mainwindow.h" line="405"/>
<source>Show Terminal</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="398"/>
+ <location filename="../build/ui_mainwindow.h" line="406"/>
<source>Ctrl+T</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="399"/>
+ <location filename="../build/ui_mainwindow.h" line="407"/>
<source>Show Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="400"/>
+ <location filename="../build/ui_mainwindow.h" line="408"/>
<source>Ctrl+G</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="401"/>
+ <location filename="../build/ui_mainwindow.h" line="409"/>
<source>About pvs</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="402"/>
+ <location filename="../build/ui_mainwindow.h" line="410"/>
<source>Ctrl+P</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="403"/>
+ <location filename="../build/ui_mainwindow.h" line="411"/>
<source>100 x 100</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="404"/>
+ <location filename="../build/ui_mainwindow.h" line="412"/>
<source>200 x 200</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="405"/>
+ <location filename="../build/ui_mainwindow.h" line="413"/>
<source>500 x 500</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="406"/>
+ <location filename="../build/ui_mainwindow.h" line="414"/>
<source>&amp;Disconnect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="407"/>
+ <location filename="../build/ui_mainwindow.h" line="415"/>
<source>Ctrl+W</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="408"/>
+ <location filename="../build/ui_mainwindow.h" line="416"/>
<source>&amp;Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="412"/>
+ <location filename="../build/ui_mainwindow.h" line="420"/>
<source>Ctrl+Q</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="413"/>
- <location filename="../build/ui_mainwindow.h" line="415"/>
+ <location filename="../build/ui_mainwindow.h" line="421"/>
+ <location filename="../build/ui_mainwindow.h" line="423"/>
<source>Foto</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="417"/>
+ <location filename="../build/ui_mainwindow.h" line="425"/>
<source>Ctrl+F</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="418"/>
+ <location filename="../build/ui_mainwindow.h" line="426"/>
<source>view</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="420"/>
+ <location filename="../build/ui_mainwindow.h" line="428"/>
<source>View</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="422"/>
+ <location filename="../build/ui_mainwindow.h" line="430"/>
<source>Ctrl+V</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="423"/>
+ <location filename="../build/ui_mainwindow.h" line="431"/>
<source>lock</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="427"/>
+ <location filename="../build/ui_mainwindow.h" line="435"/>
<source>Ctrl+A</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="428"/>
+ <location filename="../build/ui_mainwindow.h" line="436"/>
<source>Profile &amp;manager</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="429"/>
+ <location filename="../build/ui_mainwindow.h" line="437"/>
<source>Ctrl+M</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="430"/>
+ <location filename="../build/ui_mainwindow.h" line="438"/>
<source>Show Name</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="431"/>
+ <location filename="../build/ui_mainwindow.h" line="439"/>
<source>Ctrl+1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="432"/>
+ <location filename="../build/ui_mainwindow.h" line="440"/>
<source>Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="434"/>
+ <location filename="../build/ui_mainwindow.h" line="442"/>
<source>Start Chat with client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="436"/>
+ <location filename="../build/ui_mainwindow.h" line="444"/>
<source>Ctrl+D</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="437"/>
+ <location filename="../build/ui_mainwindow.h" line="445"/>
<source>-</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="438"/>
+ <location filename="../build/ui_mainwindow.h" line="446"/>
+ <source>&amp;Configure...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="448"/>
+ <source>Configure Network Parameters</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="450"/>
<source>showProcesses</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="440"/>
- <location filename="../src/gui/mainWindow.cpp" line="135"/>
+ <location filename="../build/ui_mainwindow.h" line="452"/>
+ <location filename="../src/gui/mainWindow.cpp" line="140"/>
<source>Show Processes of the selected Client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="442"/>
+ <location filename="../build/ui_mainwindow.h" line="454"/>
<source>border-color: rgb(0, 0, 0);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="443"/>
+ <location filename="../build/ui_mainwindow.h" line="455"/>
<source>VNC quality</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="446"/>
+ <location filename="../build/ui_mainwindow.h" line="458"/>
<source>HIGH</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="447"/>
+ <location filename="../build/ui_mainwindow.h" line="459"/>
<source>MEDIUM</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="448"/>
+ <location filename="../build/ui_mainwindow.h" line="460"/>
<source>LOW</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="450"/>
+ <location filename="../build/ui_mainwindow.h" line="462"/>
<source>Set password</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="453"/>
+ <location filename="../build/ui_mainwindow.h" line="465"/>
<source>Thumbnailratio</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="454"/>
+ <location filename="../build/ui_mainwindow.h" line="466"/>
<source>Thumbnailrate</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="456"/>
+ <location filename="../build/ui_mainwindow.h" line="468"/>
<source> 0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="457"/>
+ <location filename="../build/ui_mainwindow.h" line="469"/>
<source>%</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="458"/>
+ <location filename="../build/ui_mainwindow.h" line="470"/>
<source>background-color: rgb(255, 255, 255);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="459"/>
+ <location filename="../build/ui_mainwindow.h" line="471"/>
<source>background-color: rgb(150, 150, 150);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="460"/>
+ <location filename="../build/ui_mainwindow.h" line="472"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="461"/>
+ <location filename="../build/ui_mainwindow.h" line="473"/>
<source>Load profile </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="462"/>
+ <location filename="../build/ui_mainwindow.h" line="474"/>
<source>&amp;Clients</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="463"/>
+ <location filename="../build/ui_mainwindow.h" line="475"/>
<source>&amp;Logging</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="464"/>
+ <location filename="../build/ui_mainwindow.h" line="476"/>
<source>&amp;Help</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="465"/>
+ <location filename="../build/ui_mainwindow.h" line="477"/>
+ <source>Network</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="478"/>
<source>toolBar</source>
<translation type="unfinished"></translation>
</message>
@@ -707,6 +744,102 @@ Perform an unprojection or remove remote help to get a target.</source>
</message>
</context>
<context>
+ <name>MulticastConfigDialog</name>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="81"/>
+ <source>OK</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="94"/>
+ <source>Not a valid IP Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="103"/>
+ <source>Not a valid IPv4 Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="113"/>
+ <source>Not an IPv4 multicast address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="133"/>
+ <source>Not a number</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="140"/>
+ <source>Must be positive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="147"/>
+ <source>Must not be a privileged port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="155"/>
+ <source>Port number too large</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MulticastConfigDialogClass</name>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="145"/>
+ <source>PVS - Multicast Configuration</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="146"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Sans Serif&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;table style=&quot;-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;&quot;&gt;
+&lt;tr&gt;
+&lt;td style=&quot;border: none;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You need to specify connection parameters for multicast messaging on your network. These parameters will automatically be distributed to client computers, so you need to assign them only once.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You will probably want to assign an address from the &lt;span style=&quot; text-decoration: underline;&quot;&gt;239.0.0.0/8&lt;/span&gt; &amp;quot;Administratively Scoped&amp;quot; range.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Do not assign arbitrary numbers without checking with your network administrator!&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="157"/>
+ <source>Multicast Group Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="158"/>
+ <source>...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="159"/>
+ <location filename="../build/ui_multicastConfigDialog.h" line="161"/>
+ <source>&lt;span style=&quot; font-weight:600; color:#008800;&quot;&gt;OK&lt;/span&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="160"/>
+ <source>Data Port (1024-65535)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="162"/>
+ <source>Transmission Rate</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="163"/>
+ <source> KiB/s</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>ProjectionDialog</name>
<message>
<location filename="../src/gui/projectionDialog.cpp" line="28"/>
diff --git a/i18n/pvsmgr_es_MX.ts b/i18n/pvsmgr_es_MX.ts
index 75999b9..86a21b8 100644
--- a/i18n/pvsmgr_es_MX.ts
+++ b/i18n/pvsmgr_es_MX.ts
@@ -40,33 +40,33 @@
<context>
<name>ClientFileSendDialogClass</name>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation>PVS - Transferencia de datos</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="131"/>
<source>Sending to:</source>
<translation>Enviando a:</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="132"/>
<source>unknown</source>
<translation>desconocido</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="127"/>
- <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="136"/>
<source>0</source>
<translation>0</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="135"/>
<source>/</source>
<translation>/</translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation>&amp;Cancelar</translation>
</message>
@@ -270,420 +270,457 @@ Perform an unprojection or remove remote help to get a target.</source>
<context>
<name>Frame</name>
<message>
- <location filename="../src/gui/frame.cpp" line="49"/>
+ <location filename="../src/gui/frame.cpp" line="54"/>
<source>View</source>
<translation>Ver</translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="50"/>
+ <location filename="../src/gui/frame.cpp" line="55"/>
<source>Foto</source>
<translation>Imagen</translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="51"/>
- <location filename="../src/gui/frame.cpp" line="276"/>
+ <location filename="../src/gui/frame.cpp" line="56"/>
+ <location filename="../src/gui/frame.cpp" line="323"/>
<source>Lock this client</source>
<translation>Bloquear este cliente</translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="53"/>
+ <location filename="../src/gui/frame.cpp" line="58"/>
<source>Set as Superclient</source>
<translation>Asignar como super cliente</translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="271"/>
+ <location filename="../src/gui/frame.cpp" line="59"/>
+ <location filename="../src/gui/frame.cpp" line="387"/>
+ <source>Enable Remote Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="61"/>
+ <location filename="../src/gui/frame.cpp" line="414"/>
+ <source>Remote Control All Clients</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="318"/>
<source>Unlock this client</source>
<translation>Desbloquear este cliente</translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="311"/>
+ <location filename="../src/gui/frame.cpp" line="358"/>
<source>You can&apos;t lock a Superclient-machine.</source>
<translation>Super clientes no pueden ser bloqueados.</translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="320"/>
+ <location filename="../src/gui/frame.cpp" line="367"/>
<source>Set client as Superclient</source>
<translation>Asignar cliente como super cliente</translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="327"/>
+ <location filename="../src/gui/frame.cpp" line="374"/>
<source>Unset client as Superclient</source>
<translation>Desactivar como super cliente</translation>
</message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="394"/>
+ <source>Disable Remote Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="408"/>
+ <source>Remote Control only this Client</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>MainWindow</name>
<message>
- <location filename="../build/ui_mainwindow.h" line="410"/>
- <location filename="../src/gui/mainWindow.cpp" line="122"/>
+ <location filename="../build/ui_mainwindow.h" line="418"/>
+ <location filename="../src/gui/mainWindow.cpp" line="126"/>
<source>Exit</source>
<translation>Salir</translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="124"/>
+ <location filename="../src/gui/mainWindow.cpp" line="128"/>
<source>Remove the vnc-Connection for the selected client(s)</source>
<translation>Remover la conexión VNC de los clientes seleccionados</translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="127"/>
+ <location filename="../src/gui/mainWindow.cpp" line="131"/>
<source>Show the selected client in the whole window</source>
<translation>Mostrar el cliente seleccionado en toda la ventana</translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="131"/>
+ <location filename="../src/gui/mainWindow.cpp" line="135"/>
<source>Make a screenshot for the selected client(s)</source>
<translation>Capturar la pantalla de los clientes seleccionados</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="425"/>
- <location filename="../src/gui/mainWindow.cpp" line="132"/>
+ <location filename="../build/ui_mainwindow.h" line="433"/>
+ <location filename="../src/gui/mainWindow.cpp" line="136"/>
<source>Lock or Unlock all Clients</source>
<translation>Bloquear o desbloquear todos los clientes</translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="155"/>
+ <location filename="../src/gui/mainWindow.cpp" line="160"/>
<source>The pvs manager</source>
<translation>PVS Manager</translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="741"/>
+ <location filename="../src/gui/mainWindow.cpp" line="745"/>
<source>This operation can only be performed for one selected Client!</source>
<translation>Esta operación solamente puede ser realizada para un cliente!</translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="785"/>
+ <location filename="../src/gui/mainWindow.cpp" line="789"/>
<source>This operation can only be performed if you have selected a Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="824"/>
+ <location filename="../src/gui/mainWindow.cpp" line="828"/>
<source>This operation can only be performed for at least one selected Client!</source>
<translation>Esta operación solamente puede ser realizada para el ultimo cliente seleccionado!</translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1099"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1103"/>
<source>You have to set a Superclient-machine before performing this action.</source>
<translation>Usted debe asignar un super cliente antes de realizar esta acción.</translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1176"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1180"/>
<source>Open Image</source>
<translation>Abrir imagen</translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1177"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1181"/>
<source>Image Files (*.png *.jpg *.svg)</source>
<translation>Extensión de imagenes (*.png *.jpg *.svg)</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="383"/>
+ <location filename="../build/ui_mainwindow.h" line="391"/>
<source>PVSmgr</source>
<translation>PVSmgr</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="384"/>
+ <location filename="../build/ui_mainwindow.h" line="392"/>
<source>Show Username</source>
<translation>Mostrar nombre de usuario</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="385"/>
+ <location filename="../build/ui_mainwindow.h" line="393"/>
<source>Ctrl+3</source>
<translation>Ctrl+3</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="386"/>
+ <location filename="../build/ui_mainwindow.h" line="394"/>
<source>Show IP</source>
<translation>Mostrar IP</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="387"/>
+ <location filename="../build/ui_mainwindow.h" line="395"/>
<source>Ctrl+2</source>
<translation>Ctrl+2</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="388"/>
+ <location filename="../build/ui_mainwindow.h" line="396"/>
<source>VNC-Placeholders</source>
<translation>VNC - Marcadores de posición</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="389"/>
+ <location filename="../build/ui_mainwindow.h" line="397"/>
<source>Show Log</source>
<translation>Mostrar Log</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="390"/>
+ <location filename="../build/ui_mainwindow.h" line="398"/>
<source>Ctrl+L</source>
<translation>Ctrl+L</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="391"/>
+ <location filename="../build/ui_mainwindow.h" line="399"/>
<source>Show Normal</source>
<translation>Mostrar normal</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="392"/>
+ <location filename="../build/ui_mainwindow.h" line="400"/>
<source>Ctrl+O</source>
<translation>Ctrl+O</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="393"/>
+ <location filename="../build/ui_mainwindow.h" line="401"/>
<source>Show Error</source>
<translation>Mostrar Errores</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="394"/>
+ <location filename="../build/ui_mainwindow.h" line="402"/>
<source>Ctrl+E</source>
<translation>Ctrl+E</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="395"/>
+ <location filename="../build/ui_mainwindow.h" line="403"/>
<source>Show Network</source>
<translation>Mostrar Red</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="396"/>
+ <location filename="../build/ui_mainwindow.h" line="404"/>
<source>Ctrl+N</source>
<translation></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="397"/>
+ <location filename="../build/ui_mainwindow.h" line="405"/>
<source>Show Terminal</source>
<translation>Mostrar Linea de comandos</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="398"/>
+ <location filename="../build/ui_mainwindow.h" line="406"/>
<source>Ctrl+T</source>
<translation>Ctrl+T</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="399"/>
+ <location filename="../build/ui_mainwindow.h" line="407"/>
<source>Show Chat</source>
<translation>Mostrar Chat</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="400"/>
+ <location filename="../build/ui_mainwindow.h" line="408"/>
<source>Ctrl+G</source>
<translation>Ctrl+G</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="401"/>
+ <location filename="../build/ui_mainwindow.h" line="409"/>
<source>About pvs</source>
<translation>Acerca de PVS</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="402"/>
+ <location filename="../build/ui_mainwindow.h" line="410"/>
<source>Ctrl+P</source>
<translation>Ctrl+P</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="403"/>
+ <location filename="../build/ui_mainwindow.h" line="411"/>
<source>100 x 100</source>
<translation>100 x 100</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="404"/>
+ <location filename="../build/ui_mainwindow.h" line="412"/>
<source>200 x 200</source>
<translation>200 x 200</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="405"/>
+ <location filename="../build/ui_mainwindow.h" line="413"/>
<source>500 x 500</source>
<translation>500 x 500</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="406"/>
+ <location filename="../build/ui_mainwindow.h" line="414"/>
<source>&amp;Disconnect</source>
<translation>&amp;Desconectar</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="407"/>
+ <location filename="../build/ui_mainwindow.h" line="415"/>
<source>Ctrl+W</source>
<translation>Ctrl+W</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="408"/>
+ <location filename="../build/ui_mainwindow.h" line="416"/>
<source>&amp;Exit</source>
<translation>&amp;Salir</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="412"/>
+ <location filename="../build/ui_mainwindow.h" line="420"/>
<source>Ctrl+Q</source>
<translation>Ctrl+Q</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="413"/>
- <location filename="../build/ui_mainwindow.h" line="415"/>
+ <location filename="../build/ui_mainwindow.h" line="421"/>
+ <location filename="../build/ui_mainwindow.h" line="423"/>
<source>Foto</source>
<translation>Imagen</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="417"/>
+ <location filename="../build/ui_mainwindow.h" line="425"/>
<source>Ctrl+F</source>
<translation>Ctrl+F</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="418"/>
+ <location filename="../build/ui_mainwindow.h" line="426"/>
<source>view</source>
<translation>ver</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="420"/>
+ <location filename="../build/ui_mainwindow.h" line="428"/>
<source>View</source>
<translation>Ver</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="422"/>
+ <location filename="../build/ui_mainwindow.h" line="430"/>
<source>Ctrl+V</source>
<translation>Ctrl+V</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="423"/>
+ <location filename="../build/ui_mainwindow.h" line="431"/>
<source>lock</source>
<translation>bloquear</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="427"/>
+ <location filename="../build/ui_mainwindow.h" line="435"/>
<source>Ctrl+A</source>
<translation>Ctrl+A</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="428"/>
+ <location filename="../build/ui_mainwindow.h" line="436"/>
<source>Profile &amp;manager</source>
<translation>Perfil &amp;manager</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="429"/>
+ <location filename="../build/ui_mainwindow.h" line="437"/>
<source>Ctrl+M</source>
<translation>Ctrl+M</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="430"/>
+ <location filename="../build/ui_mainwindow.h" line="438"/>
<source>Show Name</source>
<translation>Mostrar nombre</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="431"/>
+ <location filename="../build/ui_mainwindow.h" line="439"/>
<source>Ctrl+1</source>
<translation>Ctrl+1</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="432"/>
+ <location filename="../build/ui_mainwindow.h" line="440"/>
<source>Chat</source>
<translation>Chat</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="434"/>
+ <location filename="../build/ui_mainwindow.h" line="442"/>
<source>Start Chat with client(s)</source>
<translation>Iniciar Chat con cliente(s)</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="436"/>
+ <location filename="../build/ui_mainwindow.h" line="444"/>
<source>Ctrl+D</source>
<translation>Ctrl+D</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="437"/>
+ <location filename="../build/ui_mainwindow.h" line="445"/>
<source>-</source>
<translation>-</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="438"/>
+ <location filename="../build/ui_mainwindow.h" line="446"/>
+ <source>&amp;Configure...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="448"/>
+ <source>Configure Network Parameters</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="450"/>
<source>showProcesses</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="440"/>
- <location filename="../src/gui/mainWindow.cpp" line="135"/>
+ <location filename="../build/ui_mainwindow.h" line="452"/>
+ <location filename="../src/gui/mainWindow.cpp" line="140"/>
<source>Show Processes of the selected Client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="442"/>
+ <location filename="../build/ui_mainwindow.h" line="454"/>
<source>border-color: rgb(0, 0, 0);</source>
<translation>border-color: rgb(0, 0, 0);</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="443"/>
+ <location filename="../build/ui_mainwindow.h" line="455"/>
<source>VNC quality</source>
<translation>VNC calidad</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="446"/>
+ <location filename="../build/ui_mainwindow.h" line="458"/>
<source>HIGH</source>
<translation>Alta</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="447"/>
+ <location filename="../build/ui_mainwindow.h" line="459"/>
<source>MEDIUM</source>
<translation>Media</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="448"/>
+ <location filename="../build/ui_mainwindow.h" line="460"/>
<source>LOW</source>
<translation>Baja</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="450"/>
+ <location filename="../build/ui_mainwindow.h" line="462"/>
<source>Set password</source>
<translation>Asignar contraseña</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="453"/>
+ <location filename="../build/ui_mainwindow.h" line="465"/>
<source>Thumbnailratio</source>
<translation>Radio de la vista en miniatura</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="454"/>
+ <location filename="../build/ui_mainwindow.h" line="466"/>
<source>Thumbnailrate</source>
<translation>Frecuancia de actualización para las vistas en miniatura</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="456"/>
+ <location filename="../build/ui_mainwindow.h" line="468"/>
<source> 0</source>
<translation> 0</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="457"/>
+ <location filename="../build/ui_mainwindow.h" line="469"/>
<source>%</source>
<translation>%</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="458"/>
+ <location filename="../build/ui_mainwindow.h" line="470"/>
<source>background-color: rgb(255, 255, 255);</source>
<translation>background-color: rgb(255, 255, 255);</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="459"/>
+ <location filename="../build/ui_mainwindow.h" line="471"/>
<source>background-color: rgb(150, 150, 150);</source>
<translation>background-color: rgb(150, 150, 150);</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="460"/>
+ <location filename="../build/ui_mainwindow.h" line="472"/>
<source>&amp;File</source>
<translation>&amp;Archivo</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="461"/>
+ <location filename="../build/ui_mainwindow.h" line="473"/>
<source>Load profile </source>
<translation>Cargar perfil</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="462"/>
+ <location filename="../build/ui_mainwindow.h" line="474"/>
<source>&amp;Clients</source>
<translation>&amp;Clientes</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="463"/>
+ <location filename="../build/ui_mainwindow.h" line="475"/>
<source>&amp;Logging</source>
<translation>&amp;Logging</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="464"/>
+ <location filename="../build/ui_mainwindow.h" line="476"/>
<source>&amp;Help</source>
<translation>&amp;Ayuda</translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="465"/>
+ <location filename="../build/ui_mainwindow.h" line="477"/>
+ <source>Network</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="478"/>
<source>toolBar</source>
<translation>Barra de herramientas</translation>
</message>
@@ -707,6 +744,102 @@ Perform an unprojection or remove remote help to get a target.</source>
</message>
</context>
<context>
+ <name>MulticastConfigDialog</name>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="81"/>
+ <source>OK</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="94"/>
+ <source>Not a valid IP Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="103"/>
+ <source>Not a valid IPv4 Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="113"/>
+ <source>Not an IPv4 multicast address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="133"/>
+ <source>Not a number</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="140"/>
+ <source>Must be positive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="147"/>
+ <source>Must not be a privileged port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="155"/>
+ <source>Port number too large</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MulticastConfigDialogClass</name>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="145"/>
+ <source>PVS - Multicast Configuration</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="146"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Sans Serif&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;table style=&quot;-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;&quot;&gt;
+&lt;tr&gt;
+&lt;td style=&quot;border: none;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You need to specify connection parameters for multicast messaging on your network. These parameters will automatically be distributed to client computers, so you need to assign them only once.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You will probably want to assign an address from the &lt;span style=&quot; text-decoration: underline;&quot;&gt;239.0.0.0/8&lt;/span&gt; &amp;quot;Administratively Scoped&amp;quot; range.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Do not assign arbitrary numbers without checking with your network administrator!&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="157"/>
+ <source>Multicast Group Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="158"/>
+ <source>...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="159"/>
+ <location filename="../build/ui_multicastConfigDialog.h" line="161"/>
+ <source>&lt;span style=&quot; font-weight:600; color:#008800;&quot;&gt;OK&lt;/span&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="160"/>
+ <source>Data Port (1024-65535)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="162"/>
+ <source>Transmission Rate</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="163"/>
+ <source> KiB/s</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>ProjectionDialog</name>
<message>
<location filename="../src/gui/projectionDialog.cpp" line="28"/>
diff --git a/i18n/pvsmgr_fr_FR.ts b/i18n/pvsmgr_fr_FR.ts
index a5a9a8a..d434341 100644
--- a/i18n/pvsmgr_fr_FR.ts
+++ b/i18n/pvsmgr_fr_FR.ts
@@ -40,33 +40,33 @@
<context>
<name>ClientFileSendDialogClass</name>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="131"/>
<source>Sending to:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="132"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="127"/>
- <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="136"/>
<source>0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="135"/>
<source>/</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation type="unfinished"></translation>
</message>
@@ -270,420 +270,457 @@ Perform an unprojection or remove remote help to get a target.</source>
<context>
<name>Frame</name>
<message>
- <location filename="../src/gui/frame.cpp" line="49"/>
+ <location filename="../src/gui/frame.cpp" line="54"/>
<source>View</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="50"/>
+ <location filename="../src/gui/frame.cpp" line="55"/>
<source>Foto</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="51"/>
- <location filename="../src/gui/frame.cpp" line="276"/>
+ <location filename="../src/gui/frame.cpp" line="56"/>
+ <location filename="../src/gui/frame.cpp" line="323"/>
<source>Lock this client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="53"/>
+ <location filename="../src/gui/frame.cpp" line="58"/>
<source>Set as Superclient</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="271"/>
+ <location filename="../src/gui/frame.cpp" line="59"/>
+ <location filename="../src/gui/frame.cpp" line="387"/>
+ <source>Enable Remote Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="61"/>
+ <location filename="../src/gui/frame.cpp" line="414"/>
+ <source>Remote Control All Clients</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="318"/>
<source>Unlock this client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="311"/>
+ <location filename="../src/gui/frame.cpp" line="358"/>
<source>You can&apos;t lock a Superclient-machine.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="320"/>
+ <location filename="../src/gui/frame.cpp" line="367"/>
<source>Set client as Superclient</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="327"/>
+ <location filename="../src/gui/frame.cpp" line="374"/>
<source>Unset client as Superclient</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="394"/>
+ <source>Disable Remote Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="408"/>
+ <source>Remote Control only this Client</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>MainWindow</name>
<message>
- <location filename="../build/ui_mainwindow.h" line="410"/>
- <location filename="../src/gui/mainWindow.cpp" line="122"/>
+ <location filename="../build/ui_mainwindow.h" line="418"/>
+ <location filename="../src/gui/mainWindow.cpp" line="126"/>
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="124"/>
+ <location filename="../src/gui/mainWindow.cpp" line="128"/>
<source>Remove the vnc-Connection for the selected client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="127"/>
+ <location filename="../src/gui/mainWindow.cpp" line="131"/>
<source>Show the selected client in the whole window</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="131"/>
+ <location filename="../src/gui/mainWindow.cpp" line="135"/>
<source>Make a screenshot for the selected client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="425"/>
- <location filename="../src/gui/mainWindow.cpp" line="132"/>
+ <location filename="../build/ui_mainwindow.h" line="433"/>
+ <location filename="../src/gui/mainWindow.cpp" line="136"/>
<source>Lock or Unlock all Clients</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="155"/>
+ <location filename="../src/gui/mainWindow.cpp" line="160"/>
<source>The pvs manager</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="741"/>
+ <location filename="../src/gui/mainWindow.cpp" line="745"/>
<source>This operation can only be performed for one selected Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="785"/>
+ <location filename="../src/gui/mainWindow.cpp" line="789"/>
<source>This operation can only be performed if you have selected a Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="824"/>
+ <location filename="../src/gui/mainWindow.cpp" line="828"/>
<source>This operation can only be performed for at least one selected Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1099"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1103"/>
<source>You have to set a Superclient-machine before performing this action.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1176"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1180"/>
<source>Open Image</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1177"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1181"/>
<source>Image Files (*.png *.jpg *.svg)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="383"/>
+ <location filename="../build/ui_mainwindow.h" line="391"/>
<source>PVSmgr</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="384"/>
+ <location filename="../build/ui_mainwindow.h" line="392"/>
<source>Show Username</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="385"/>
+ <location filename="../build/ui_mainwindow.h" line="393"/>
<source>Ctrl+3</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="386"/>
+ <location filename="../build/ui_mainwindow.h" line="394"/>
<source>Show IP</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="387"/>
+ <location filename="../build/ui_mainwindow.h" line="395"/>
<source>Ctrl+2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="388"/>
+ <location filename="../build/ui_mainwindow.h" line="396"/>
<source>VNC-Placeholders</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="389"/>
+ <location filename="../build/ui_mainwindow.h" line="397"/>
<source>Show Log</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="390"/>
+ <location filename="../build/ui_mainwindow.h" line="398"/>
<source>Ctrl+L</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="391"/>
+ <location filename="../build/ui_mainwindow.h" line="399"/>
<source>Show Normal</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="392"/>
+ <location filename="../build/ui_mainwindow.h" line="400"/>
<source>Ctrl+O</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="393"/>
+ <location filename="../build/ui_mainwindow.h" line="401"/>
<source>Show Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="394"/>
+ <location filename="../build/ui_mainwindow.h" line="402"/>
<source>Ctrl+E</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="395"/>
+ <location filename="../build/ui_mainwindow.h" line="403"/>
<source>Show Network</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="396"/>
+ <location filename="../build/ui_mainwindow.h" line="404"/>
<source>Ctrl+N</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="397"/>
+ <location filename="../build/ui_mainwindow.h" line="405"/>
<source>Show Terminal</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="398"/>
+ <location filename="../build/ui_mainwindow.h" line="406"/>
<source>Ctrl+T</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="399"/>
+ <location filename="../build/ui_mainwindow.h" line="407"/>
<source>Show Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="400"/>
+ <location filename="../build/ui_mainwindow.h" line="408"/>
<source>Ctrl+G</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="401"/>
+ <location filename="../build/ui_mainwindow.h" line="409"/>
<source>About pvs</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="402"/>
+ <location filename="../build/ui_mainwindow.h" line="410"/>
<source>Ctrl+P</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="403"/>
+ <location filename="../build/ui_mainwindow.h" line="411"/>
<source>100 x 100</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="404"/>
+ <location filename="../build/ui_mainwindow.h" line="412"/>
<source>200 x 200</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="405"/>
+ <location filename="../build/ui_mainwindow.h" line="413"/>
<source>500 x 500</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="406"/>
+ <location filename="../build/ui_mainwindow.h" line="414"/>
<source>&amp;Disconnect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="407"/>
+ <location filename="../build/ui_mainwindow.h" line="415"/>
<source>Ctrl+W</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="408"/>
+ <location filename="../build/ui_mainwindow.h" line="416"/>
<source>&amp;Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="412"/>
+ <location filename="../build/ui_mainwindow.h" line="420"/>
<source>Ctrl+Q</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="413"/>
- <location filename="../build/ui_mainwindow.h" line="415"/>
+ <location filename="../build/ui_mainwindow.h" line="421"/>
+ <location filename="../build/ui_mainwindow.h" line="423"/>
<source>Foto</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="417"/>
+ <location filename="../build/ui_mainwindow.h" line="425"/>
<source>Ctrl+F</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="418"/>
+ <location filename="../build/ui_mainwindow.h" line="426"/>
<source>view</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="420"/>
+ <location filename="../build/ui_mainwindow.h" line="428"/>
<source>View</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="422"/>
+ <location filename="../build/ui_mainwindow.h" line="430"/>
<source>Ctrl+V</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="423"/>
+ <location filename="../build/ui_mainwindow.h" line="431"/>
<source>lock</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="427"/>
+ <location filename="../build/ui_mainwindow.h" line="435"/>
<source>Ctrl+A</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="428"/>
+ <location filename="../build/ui_mainwindow.h" line="436"/>
<source>Profile &amp;manager</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="429"/>
+ <location filename="../build/ui_mainwindow.h" line="437"/>
<source>Ctrl+M</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="430"/>
+ <location filename="../build/ui_mainwindow.h" line="438"/>
<source>Show Name</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="431"/>
+ <location filename="../build/ui_mainwindow.h" line="439"/>
<source>Ctrl+1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="432"/>
+ <location filename="../build/ui_mainwindow.h" line="440"/>
<source>Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="434"/>
+ <location filename="../build/ui_mainwindow.h" line="442"/>
<source>Start Chat with client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="436"/>
+ <location filename="../build/ui_mainwindow.h" line="444"/>
<source>Ctrl+D</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="437"/>
+ <location filename="../build/ui_mainwindow.h" line="445"/>
<source>-</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="438"/>
+ <location filename="../build/ui_mainwindow.h" line="446"/>
+ <source>&amp;Configure...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="448"/>
+ <source>Configure Network Parameters</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="450"/>
<source>showProcesses</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="440"/>
- <location filename="../src/gui/mainWindow.cpp" line="135"/>
+ <location filename="../build/ui_mainwindow.h" line="452"/>
+ <location filename="../src/gui/mainWindow.cpp" line="140"/>
<source>Show Processes of the selected Client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="442"/>
+ <location filename="../build/ui_mainwindow.h" line="454"/>
<source>border-color: rgb(0, 0, 0);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="443"/>
+ <location filename="../build/ui_mainwindow.h" line="455"/>
<source>VNC quality</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="446"/>
+ <location filename="../build/ui_mainwindow.h" line="458"/>
<source>HIGH</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="447"/>
+ <location filename="../build/ui_mainwindow.h" line="459"/>
<source>MEDIUM</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="448"/>
+ <location filename="../build/ui_mainwindow.h" line="460"/>
<source>LOW</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="450"/>
+ <location filename="../build/ui_mainwindow.h" line="462"/>
<source>Set password</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="453"/>
+ <location filename="../build/ui_mainwindow.h" line="465"/>
<source>Thumbnailratio</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="454"/>
+ <location filename="../build/ui_mainwindow.h" line="466"/>
<source>Thumbnailrate</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="456"/>
+ <location filename="../build/ui_mainwindow.h" line="468"/>
<source> 0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="457"/>
+ <location filename="../build/ui_mainwindow.h" line="469"/>
<source>%</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="458"/>
+ <location filename="../build/ui_mainwindow.h" line="470"/>
<source>background-color: rgb(255, 255, 255);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="459"/>
+ <location filename="../build/ui_mainwindow.h" line="471"/>
<source>background-color: rgb(150, 150, 150);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="460"/>
+ <location filename="../build/ui_mainwindow.h" line="472"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="461"/>
+ <location filename="../build/ui_mainwindow.h" line="473"/>
<source>Load profile </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="462"/>
+ <location filename="../build/ui_mainwindow.h" line="474"/>
<source>&amp;Clients</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="463"/>
+ <location filename="../build/ui_mainwindow.h" line="475"/>
<source>&amp;Logging</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="464"/>
+ <location filename="../build/ui_mainwindow.h" line="476"/>
<source>&amp;Help</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="465"/>
+ <location filename="../build/ui_mainwindow.h" line="477"/>
+ <source>Network</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="478"/>
<source>toolBar</source>
<translation type="unfinished"></translation>
</message>
@@ -707,6 +744,102 @@ Perform an unprojection or remove remote help to get a target.</source>
</message>
</context>
<context>
+ <name>MulticastConfigDialog</name>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="81"/>
+ <source>OK</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="94"/>
+ <source>Not a valid IP Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="103"/>
+ <source>Not a valid IPv4 Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="113"/>
+ <source>Not an IPv4 multicast address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="133"/>
+ <source>Not a number</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="140"/>
+ <source>Must be positive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="147"/>
+ <source>Must not be a privileged port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="155"/>
+ <source>Port number too large</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MulticastConfigDialogClass</name>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="145"/>
+ <source>PVS - Multicast Configuration</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="146"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Sans Serif&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;table style=&quot;-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;&quot;&gt;
+&lt;tr&gt;
+&lt;td style=&quot;border: none;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You need to specify connection parameters for multicast messaging on your network. These parameters will automatically be distributed to client computers, so you need to assign them only once.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You will probably want to assign an address from the &lt;span style=&quot; text-decoration: underline;&quot;&gt;239.0.0.0/8&lt;/span&gt; &amp;quot;Administratively Scoped&amp;quot; range.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Do not assign arbitrary numbers without checking with your network administrator!&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="157"/>
+ <source>Multicast Group Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="158"/>
+ <source>...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="159"/>
+ <location filename="../build/ui_multicastConfigDialog.h" line="161"/>
+ <source>&lt;span style=&quot; font-weight:600; color:#008800;&quot;&gt;OK&lt;/span&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="160"/>
+ <source>Data Port (1024-65535)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="162"/>
+ <source>Transmission Rate</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="163"/>
+ <source> KiB/s</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>ProjectionDialog</name>
<message>
<location filename="../src/gui/projectionDialog.cpp" line="28"/>
diff --git a/i18n/pvsmgr_pl_PL.ts b/i18n/pvsmgr_pl_PL.ts
index a5a9a8a..d434341 100644
--- a/i18n/pvsmgr_pl_PL.ts
+++ b/i18n/pvsmgr_pl_PL.ts
@@ -40,33 +40,33 @@
<context>
<name>ClientFileSendDialogClass</name>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="123"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
<source>PVS - File Transfer</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="125"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="131"/>
<source>Sending to:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="126"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="132"/>
<source>unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="127"/>
- <location filename="../build/ui_clientFileSendDialog.h" line="129"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="134"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="136"/>
<source>0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="128"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="135"/>
<source>/</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_clientFileSendDialog.h" line="130"/>
+ <location filename="../build/ui_clientFileSendDialog.h" line="137"/>
<source>&amp;Cancel</source>
<translation type="unfinished"></translation>
</message>
@@ -270,420 +270,457 @@ Perform an unprojection or remove remote help to get a target.</source>
<context>
<name>Frame</name>
<message>
- <location filename="../src/gui/frame.cpp" line="49"/>
+ <location filename="../src/gui/frame.cpp" line="54"/>
<source>View</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="50"/>
+ <location filename="../src/gui/frame.cpp" line="55"/>
<source>Foto</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="51"/>
- <location filename="../src/gui/frame.cpp" line="276"/>
+ <location filename="../src/gui/frame.cpp" line="56"/>
+ <location filename="../src/gui/frame.cpp" line="323"/>
<source>Lock this client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="53"/>
+ <location filename="../src/gui/frame.cpp" line="58"/>
<source>Set as Superclient</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="271"/>
+ <location filename="../src/gui/frame.cpp" line="59"/>
+ <location filename="../src/gui/frame.cpp" line="387"/>
+ <source>Enable Remote Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="61"/>
+ <location filename="../src/gui/frame.cpp" line="414"/>
+ <source>Remote Control All Clients</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="318"/>
<source>Unlock this client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="311"/>
+ <location filename="../src/gui/frame.cpp" line="358"/>
<source>You can&apos;t lock a Superclient-machine.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="320"/>
+ <location filename="../src/gui/frame.cpp" line="367"/>
<source>Set client as Superclient</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/frame.cpp" line="327"/>
+ <location filename="../src/gui/frame.cpp" line="374"/>
<source>Unset client as Superclient</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="394"/>
+ <source>Disable Remote Control</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/frame.cpp" line="408"/>
+ <source>Remote Control only this Client</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>MainWindow</name>
<message>
- <location filename="../build/ui_mainwindow.h" line="410"/>
- <location filename="../src/gui/mainWindow.cpp" line="122"/>
+ <location filename="../build/ui_mainwindow.h" line="418"/>
+ <location filename="../src/gui/mainWindow.cpp" line="126"/>
<source>Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="124"/>
+ <location filename="../src/gui/mainWindow.cpp" line="128"/>
<source>Remove the vnc-Connection for the selected client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="127"/>
+ <location filename="../src/gui/mainWindow.cpp" line="131"/>
<source>Show the selected client in the whole window</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="131"/>
+ <location filename="../src/gui/mainWindow.cpp" line="135"/>
<source>Make a screenshot for the selected client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="425"/>
- <location filename="../src/gui/mainWindow.cpp" line="132"/>
+ <location filename="../build/ui_mainwindow.h" line="433"/>
+ <location filename="../src/gui/mainWindow.cpp" line="136"/>
<source>Lock or Unlock all Clients</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="155"/>
+ <location filename="../src/gui/mainWindow.cpp" line="160"/>
<source>The pvs manager</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="741"/>
+ <location filename="../src/gui/mainWindow.cpp" line="745"/>
<source>This operation can only be performed for one selected Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="785"/>
+ <location filename="../src/gui/mainWindow.cpp" line="789"/>
<source>This operation can only be performed if you have selected a Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="824"/>
+ <location filename="../src/gui/mainWindow.cpp" line="828"/>
<source>This operation can only be performed for at least one selected Client!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1099"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1103"/>
<source>You have to set a Superclient-machine before performing this action.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1176"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1180"/>
<source>Open Image</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../src/gui/mainWindow.cpp" line="1177"/>
+ <location filename="../src/gui/mainWindow.cpp" line="1181"/>
<source>Image Files (*.png *.jpg *.svg)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="383"/>
+ <location filename="../build/ui_mainwindow.h" line="391"/>
<source>PVSmgr</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="384"/>
+ <location filename="../build/ui_mainwindow.h" line="392"/>
<source>Show Username</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="385"/>
+ <location filename="../build/ui_mainwindow.h" line="393"/>
<source>Ctrl+3</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="386"/>
+ <location filename="../build/ui_mainwindow.h" line="394"/>
<source>Show IP</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="387"/>
+ <location filename="../build/ui_mainwindow.h" line="395"/>
<source>Ctrl+2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="388"/>
+ <location filename="../build/ui_mainwindow.h" line="396"/>
<source>VNC-Placeholders</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="389"/>
+ <location filename="../build/ui_mainwindow.h" line="397"/>
<source>Show Log</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="390"/>
+ <location filename="../build/ui_mainwindow.h" line="398"/>
<source>Ctrl+L</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="391"/>
+ <location filename="../build/ui_mainwindow.h" line="399"/>
<source>Show Normal</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="392"/>
+ <location filename="../build/ui_mainwindow.h" line="400"/>
<source>Ctrl+O</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="393"/>
+ <location filename="../build/ui_mainwindow.h" line="401"/>
<source>Show Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="394"/>
+ <location filename="../build/ui_mainwindow.h" line="402"/>
<source>Ctrl+E</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="395"/>
+ <location filename="../build/ui_mainwindow.h" line="403"/>
<source>Show Network</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="396"/>
+ <location filename="../build/ui_mainwindow.h" line="404"/>
<source>Ctrl+N</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="397"/>
+ <location filename="../build/ui_mainwindow.h" line="405"/>
<source>Show Terminal</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="398"/>
+ <location filename="../build/ui_mainwindow.h" line="406"/>
<source>Ctrl+T</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="399"/>
+ <location filename="../build/ui_mainwindow.h" line="407"/>
<source>Show Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="400"/>
+ <location filename="../build/ui_mainwindow.h" line="408"/>
<source>Ctrl+G</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="401"/>
+ <location filename="../build/ui_mainwindow.h" line="409"/>
<source>About pvs</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="402"/>
+ <location filename="../build/ui_mainwindow.h" line="410"/>
<source>Ctrl+P</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="403"/>
+ <location filename="../build/ui_mainwindow.h" line="411"/>
<source>100 x 100</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="404"/>
+ <location filename="../build/ui_mainwindow.h" line="412"/>
<source>200 x 200</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="405"/>
+ <location filename="../build/ui_mainwindow.h" line="413"/>
<source>500 x 500</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="406"/>
+ <location filename="../build/ui_mainwindow.h" line="414"/>
<source>&amp;Disconnect</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="407"/>
+ <location filename="../build/ui_mainwindow.h" line="415"/>
<source>Ctrl+W</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="408"/>
+ <location filename="../build/ui_mainwindow.h" line="416"/>
<source>&amp;Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="412"/>
+ <location filename="../build/ui_mainwindow.h" line="420"/>
<source>Ctrl+Q</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="413"/>
- <location filename="../build/ui_mainwindow.h" line="415"/>
+ <location filename="../build/ui_mainwindow.h" line="421"/>
+ <location filename="../build/ui_mainwindow.h" line="423"/>
<source>Foto</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="417"/>
+ <location filename="../build/ui_mainwindow.h" line="425"/>
<source>Ctrl+F</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="418"/>
+ <location filename="../build/ui_mainwindow.h" line="426"/>
<source>view</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="420"/>
+ <location filename="../build/ui_mainwindow.h" line="428"/>
<source>View</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="422"/>
+ <location filename="../build/ui_mainwindow.h" line="430"/>
<source>Ctrl+V</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="423"/>
+ <location filename="../build/ui_mainwindow.h" line="431"/>
<source>lock</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="427"/>
+ <location filename="../build/ui_mainwindow.h" line="435"/>
<source>Ctrl+A</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="428"/>
+ <location filename="../build/ui_mainwindow.h" line="436"/>
<source>Profile &amp;manager</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="429"/>
+ <location filename="../build/ui_mainwindow.h" line="437"/>
<source>Ctrl+M</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="430"/>
+ <location filename="../build/ui_mainwindow.h" line="438"/>
<source>Show Name</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="431"/>
+ <location filename="../build/ui_mainwindow.h" line="439"/>
<source>Ctrl+1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="432"/>
+ <location filename="../build/ui_mainwindow.h" line="440"/>
<source>Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="434"/>
+ <location filename="../build/ui_mainwindow.h" line="442"/>
<source>Start Chat with client(s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="436"/>
+ <location filename="../build/ui_mainwindow.h" line="444"/>
<source>Ctrl+D</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="437"/>
+ <location filename="../build/ui_mainwindow.h" line="445"/>
<source>-</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="438"/>
+ <location filename="../build/ui_mainwindow.h" line="446"/>
+ <source>&amp;Configure...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="448"/>
+ <source>Configure Network Parameters</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="450"/>
<source>showProcesses</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="440"/>
- <location filename="../src/gui/mainWindow.cpp" line="135"/>
+ <location filename="../build/ui_mainwindow.h" line="452"/>
+ <location filename="../src/gui/mainWindow.cpp" line="140"/>
<source>Show Processes of the selected Client</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="442"/>
+ <location filename="../build/ui_mainwindow.h" line="454"/>
<source>border-color: rgb(0, 0, 0);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="443"/>
+ <location filename="../build/ui_mainwindow.h" line="455"/>
<source>VNC quality</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="446"/>
+ <location filename="../build/ui_mainwindow.h" line="458"/>
<source>HIGH</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="447"/>
+ <location filename="../build/ui_mainwindow.h" line="459"/>
<source>MEDIUM</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="448"/>
+ <location filename="../build/ui_mainwindow.h" line="460"/>
<source>LOW</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="450"/>
+ <location filename="../build/ui_mainwindow.h" line="462"/>
<source>Set password</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="453"/>
+ <location filename="../build/ui_mainwindow.h" line="465"/>
<source>Thumbnailratio</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="454"/>
+ <location filename="../build/ui_mainwindow.h" line="466"/>
<source>Thumbnailrate</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="456"/>
+ <location filename="../build/ui_mainwindow.h" line="468"/>
<source> 0</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="457"/>
+ <location filename="../build/ui_mainwindow.h" line="469"/>
<source>%</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="458"/>
+ <location filename="../build/ui_mainwindow.h" line="470"/>
<source>background-color: rgb(255, 255, 255);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="459"/>
+ <location filename="../build/ui_mainwindow.h" line="471"/>
<source>background-color: rgb(150, 150, 150);</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="460"/>
+ <location filename="../build/ui_mainwindow.h" line="472"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="461"/>
+ <location filename="../build/ui_mainwindow.h" line="473"/>
<source>Load profile </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="462"/>
+ <location filename="../build/ui_mainwindow.h" line="474"/>
<source>&amp;Clients</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="463"/>
+ <location filename="../build/ui_mainwindow.h" line="475"/>
<source>&amp;Logging</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="464"/>
+ <location filename="../build/ui_mainwindow.h" line="476"/>
<source>&amp;Help</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../build/ui_mainwindow.h" line="465"/>
+ <location filename="../build/ui_mainwindow.h" line="477"/>
+ <source>Network</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_mainwindow.h" line="478"/>
<source>toolBar</source>
<translation type="unfinished"></translation>
</message>
@@ -707,6 +744,102 @@ Perform an unprojection or remove remote help to get a target.</source>
</message>
</context>
<context>
+ <name>MulticastConfigDialog</name>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="81"/>
+ <source>OK</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="94"/>
+ <source>Not a valid IP Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="103"/>
+ <source>Not a valid IPv4 Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="113"/>
+ <source>Not an IPv4 multicast address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="133"/>
+ <source>Not a number</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="140"/>
+ <source>Must be positive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="147"/>
+ <source>Must not be a privileged port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../src/gui/multicastConfigDialog.cpp" line="155"/>
+ <source>Port number too large</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>MulticastConfigDialogClass</name>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="145"/>
+ <source>PVS - Multicast Configuration</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="146"/>
+ <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Sans Serif&apos;; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;table style=&quot;-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;&quot;&gt;
+&lt;tr&gt;
+&lt;td style=&quot;border: none;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You need to specify connection parameters for multicast messaging on your network. These parameters will automatically be distributed to client computers, so you need to assign them only once.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You will probably want to assign an address from the &lt;span style=&quot; text-decoration: underline;&quot;&gt;239.0.0.0/8&lt;/span&gt; &amp;quot;Administratively Scoped&amp;quot; range.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Do not assign arbitrary numbers without checking with your network administrator!&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="157"/>
+ <source>Multicast Group Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="158"/>
+ <source>...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="159"/>
+ <location filename="../build/ui_multicastConfigDialog.h" line="161"/>
+ <source>&lt;span style=&quot; font-weight:600; color:#008800;&quot;&gt;OK&lt;/span&gt;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="160"/>
+ <source>Data Port (1024-65535)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="162"/>
+ <source>Transmission Rate</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../build/ui_multicastConfigDialog.h" line="163"/>
+ <source> KiB/s</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>ProjectionDialog</name>
<message>
<location filename="../src/gui/projectionDialog.cpp" line="28"/>
diff --git a/icons/README b/icons/README
index eccf713..0ce733d 100644
--- a/icons/README
+++ b/icons/README
@@ -1,3 +1,5 @@
-network-configure.png has been taken from the
-Nuvola 1.0 Icon Set, generously provided under the LGPL by its designer,
-David Vignoni. See http://www.icon-king.com/projects/nuvola/
+network-configure.png, remote-control.png and remote-control-all.png
+have been taken from the Nuvola 1.0 Icon Set, generously provided
+under the LGPL by its designer, David Vignoni.
+
+See http://www.icon-king.com/projects/nuvola/
diff --git a/icons/gearsgo.png b/icons/gearsgo.png
new file mode 100644
index 0000000..e5c3217
--- /dev/null
+++ b/icons/gearsgo.png
Binary files differ
diff --git a/icons/gearsstop.png b/icons/gearsstop.png
new file mode 100644
index 0000000..23adfbb
--- /dev/null
+++ b/icons/gearsstop.png
Binary files differ
diff --git a/icons/remote-control-all.png b/icons/remote-control-all.png
new file mode 100644
index 0000000..bc7e2ae
--- /dev/null
+++ b/icons/remote-control-all.png
Binary files differ
diff --git a/icons/remote-control.png b/icons/remote-control.png
new file mode 100644
index 0000000..ba460dd
--- /dev/null
+++ b/icons/remote-control.png
Binary files differ
diff --git a/pvsmgr.qrc b/pvsmgr.qrc
index ada3c1e..b4de3bc 100644
--- a/pvsmgr.qrc
+++ b/pvsmgr.qrc
@@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/">
+ <file>icons/gearsgo.png</file>
<file>icons/gears.png</file>
<file>icons/projection.png</file>
<file>icons/reset.png</file>
@@ -21,6 +22,8 @@
<file alias="chat">icons/chat.png</file>
<file alias="cam32.svg">icons/cam32.svg</file>
<file alias="netconf">icons/network_configure.png</file>
+ <file alias="remotecontrol" >icons/remote-control.png</file>
+ <file alias="remotecontrolall" >icons/remote-control-all.png</file>
<file alias="AUTHORS">AUTHORS</file>
<file alias="TRANSLATION">TRANSLATION</file>
</qresource>
diff --git a/spam b/spam
deleted file mode 100755
index 73d6814..0000000
--- a/spam
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-while [ 1 -lt 2 ]; do
- wget --secure-protocol=SSLv3 --no-check-certificate -O index.html https://localhost:3490/
-done
diff --git a/src/core/pvsClient.cpp b/src/core/pvsClient.cpp
index 0d08b1d..0448f97 100644
--- a/src/core/pvsClient.cpp
+++ b/src/core/pvsClient.cpp
@@ -299,3 +299,22 @@ void PVSClient::vncFinished()
_vncPasswordReceived = false;
}
+QVector<QString> PVSClient::getProcessesVector()
+{
+ return processesVector;
+}
+
+void PVSClient::clearProcessesVector()
+{
+ processesVector.clear();
+}
+
+void PVSClient::processesVectorAdd(QString msg)
+{
+ if (msg.indexOf("<#>") > 0)
+ processesVector.append(msg);
+ else if (msg.indexOf("vector ready") == 0)
+ {
+ emit processVectorReady(true);
+ }
+}
diff --git a/src/core/pvsClient.h b/src/core/pvsClient.h
index 180995a..e547e12 100644
--- a/src/core/pvsClient.h
+++ b/src/core/pvsClient.h
@@ -15,6 +15,7 @@
#include "src/net/pvsClientConnection.h"
#include "src/gui/frame.h"
#include <QtCore/QThread>
+#include <QVector>
class PVSServer;
class VNCConnection;
@@ -104,6 +105,16 @@ public:
int getClientindex() { return _clientIndex; }
int getConnectionId() { return _pvsClientConnection->getID(); }
+ QVector<QString> getProcessesVector();
+
+
+public slots:
+ void processesVectorAdd(QString msg);
+ void clearProcessesVector();
+
+signals:
+ void processVectorReady( bool );
+
private Q_SLOTS:
void vncFinished();
@@ -124,6 +135,8 @@ private:
QString _vncRwPassword;
int _clientIndex;
bool _vncAllowed, _vncRequested, _vncPasswordReceived, _vncRwPasswordReceived, _vncInitMutex, _vncProject;
+ QVector<QString> processesVector;
+
};
#endif
diff --git a/src/core/pvsConnectionManager.cpp b/src/core/pvsConnectionManager.cpp
index 5bf6418..db302c4 100644
--- a/src/core/pvsConnectionManager.cpp
+++ b/src/core/pvsConnectionManager.cpp
@@ -192,6 +192,9 @@ void PVSConnectionManager::onCommand(PVSMsg command)
{
QString message = command.getMessage();
QString ident = command.getIdent();
+
+ PVSClient* tmp = getClientFromConnectionId(command.getSndID());
+
if (ident.compare("VNCSRVRESULT") == 0)
{
int e = string2Int(message);
@@ -218,6 +221,45 @@ void PVSConnectionManager::onCommand(PVSMsg command)
break;
}
}
+ if (ident.compare("PROCESSES") == 0)
+ {
+ QString id = int2String(command.getSndID());
+ if (message.startsWith("START"))
+ {
+ QString msgcontent = message.remove(0,6);
+ if (msgcontent.startsWith("ERROR"))
+ {
+ ConsoleLog writeError("[Client: " + id + ", PROCESS] could not start: " +msgcontent.remove(0,6));
+ }
+ else
+ {
+ //ConsoleLog writeLine(QString("[Client: " + id + ", PROCESS] started: " +msgcontent));
+ }
+ }
+ if (message.startsWith("STOP"))
+ {
+ QString msgcontent = message.remove(0,5);
+ if (msgcontent.startsWith("ERROR"))
+ {
+ ConsoleLog writeError("[Client: " + id + ", PROCESS] could not stop: " +msgcontent.remove(0,6));
+ }
+ else
+ {
+ //ConsoleLog writeLine(QString("[Client: " + id + ", PROCESS] stopped: " +msgcontent));
+ }
+ }
+ if (message.startsWith("SHOW"))
+ {
+ QString msgcontent = message.remove(0,5);
+ if (msgcontent.startsWith("ERROR"))
+ ConsoleLog writeError("[Client: " + id + ", PROCESS] could not show processes: " +msgcontent.remove(0,6));
+ else if (msgcontent.startsWith("clear"))
+ tmp->clearProcessesVector();
+ else if (msgcontent.startsWith("finished"))
+ tmp->processesVectorAdd("vector ready");
+ else tmp->processesVectorAdd(message);
+ }
+ }
else if (ident == "MCASTFTANNOUNCE")
{
_pvsServer.sendToAll(command);
diff --git a/src/gui/connectionList.cpp b/src/gui/connectionList.cpp
index 2f9829e..f0fb7d6 100644
--- a/src/gui/connectionList.cpp
+++ b/src/gui/connectionList.cpp
@@ -502,6 +502,9 @@ void ConnectionList::on_unlock_all()
void ConnectionList::on_unproject_all()
{
MainWindow::getConnectionWindow()->unprojectAllStations();
+ sourceList.clear();
+ targetList.clear();
+ sourceMap.clear();
}
diff --git a/src/gui/connectionWindow.cpp b/src/gui/connectionWindow.cpp
index cf51051..df31562 100644
--- a/src/gui/connectionWindow.cpp
+++ b/src/gui/connectionWindow.cpp
@@ -472,6 +472,35 @@ void ConnectionWindow::messageStation(QString ident, QString message,
pvsCon->sendMessage(PVSMESSAGE, ident, message);
}
+/*
+ * to send COMMAND instead of PVSMESSaGE
+ */
+bool ConnectionWindow::commandStations(QString ident, QString message) {
+ if (std::list<QString>* messageList = MainWindow::getConnectionList()->getSelectedClients()) {
+ if (!messageList->empty()) {
+ for (std::list<QString>::iterator tmpIt = messageList->begin(); tmpIt
+ != messageList->end(); tmpIt++) {
+ PVSClient
+ * tmpConnection =
+ PVSConnectionManager::getManager()->getClientFromIp(
+ (*tmpIt).toUtf8().data());
+ // we don't want to lock the dozent machine
+ if (tmpConnection && tmpConnection->getConnectionFrame()->getFrame() &&
+ !tmpConnection->getConnectionFrame()->getFrame()->isDozent())
+ {
+ //messageStation(ident, message, tmpConnection);
+ tmpConnection->sendMessage(PVSCOMMAND, ident, message);
+ } else {
+ // scream in agony
+ }
+ }
+ }
+ delete messageList;
+ }
+ return true;
+}
+
+
bool ConnectionWindow::lockStationsWithMessage(QString message)
{
if (!hasDozent)
diff --git a/src/gui/connectionWindow.h b/src/gui/connectionWindow.h
index 81b5033..55442db 100644
--- a/src/gui/connectionWindow.h
+++ b/src/gui/connectionWindow.h
@@ -9,6 +9,7 @@
#include <iostream>
#include <math.h>
#include <QSettings>
+#include <QPointer>
#define FRAME_DELAY 1000 // to comply with the standard value in the gui
@@ -83,6 +84,7 @@ public:
bool lockInvertStations();
void lockInvertStation(PVSClient* pvsCon);
bool messageStations(QString ident, QString message);
+ bool commandStations(QString ident, QString message);
void messageStation(QString ident, QString message, PVSClient* pvsCon);
bool lockStationsWithMessage(QString message);
void lockStationsWithMessage(QString message, PVSClient* pvsCon);
@@ -109,7 +111,7 @@ protected:
private:
ConnectionFrame* newConFrame(PVSClient* newConnection); // returns a new frame for the given connection
ConnectionFrame* currentSingleFrame; // pointer to the frame thats currently in FullScreen
- ConnectionFrame* _closeupFrame;
+ QPointer<ConnectionFrame> _closeupFrame;
QPoint currentPosition (ConnectionFrame* cF);
QMenu *menu;
QAction *newDummy;
diff --git a/src/gui/dialog.cpp b/src/gui/dialog.cpp
index 3c9b7a2..5f24009 100644
--- a/src/gui/dialog.cpp
+++ b/src/gui/dialog.cpp
@@ -30,7 +30,7 @@ Dialog::Dialog(QWidget *parent) :
connect( dui->send, SIGNAL( clicked()), this, SLOT( send()));
connect( dui->cancel, SIGNAL( clicked()), this, SLOT( NotSend()));
- connect(dui->message, SIGNAL(textChanged()), this, SLOT(textchange()));
+ connect( dui->message, SIGNAL(textChanged()), this, SLOT(textchange()));
}
Dialog::~Dialog()
diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp
index cb79643..561f3ce 100644
--- a/src/gui/frame.cpp
+++ b/src/gui/frame.cpp
@@ -18,11 +18,15 @@
# -----------------------------------------------------------------------------
*/
+#include <src/input/inputEvent.h>
#include "frame.h"
#include <src/gui/mainWindow.h>
#include <iostream>
#include <QPixmap>
+#define MOUSE_MOTION_SEND_INTERVAL 100 /* msecs */
+#define SPECIAL_EVENT_WAIT_TIME 5000 /* msecs */
+
Frame::Frame(const QString & text, QWidget * parent) :
QLabel(parent), _clientVNCThread(0)
{
@@ -43,18 +47,40 @@ Frame::Frame(const QString & text, QWidget * parent) :
_isLocked = false;
_dozent = false;
_uy = _ux = 0;
+ _isCloseUp = false;
//QIcon icon;
//icon.addFile(QString::fromUtf8(), QSize(), QIcon::Normal, QIcon::Off);
button_closeUp = createToolButton(tr("View"), QIcon(":/restore"),SLOT(closeUp()));
+ button_closeUp->setCheckable(true);
button_foto = createToolButton(tr("Foto"), QIcon(":/photos"),SLOT(foto()));
button_lock = createToolButton(tr("Lock this client"), QIcon(":/lock"),SLOT(setLock()));
//button_unlock = createToolButton(tr("Unlock this client"), QIcon(":/lock"),SLOT(setLock()));
button_dozent = createToolButton(tr("Set as Superclient"), QIcon(":/dozent2"),SLOT(setDozent()));
+ button_control = createToolButton(tr("Enable Remote Control"), QIcon(":/remotecontrol"), SLOT(remoteControlClicked()));
+ button_control->setCheckable(true);
+ button_control_all = createToolButton(tr("Remote Control All Clients"), QIcon(":/remotecontrolall"), SLOT(remoteControlAllClicked()));
+ button_control_all->setCheckable(true);
connect(this, SIGNAL(clicked()), this, SLOT(slotClicked()));
ip = "";
setToolButtonListVisible(false);
+
+ _remoteControlEnabled = false;
+ _remoteControlToAll = false;
+
+ _mouseMotionEventTimer = new QTimer(this);
+ _mouseMotionEventTimer->setInterval(MOUSE_MOTION_SEND_INTERVAL);
+ _mouseMotionEventTimer->setSingleShot(false);
+ connect(_mouseMotionEventTimer, SIGNAL(timeout()), this, SLOT(sendMouseMotionEvent()));
+
+ _mousePositionChanged = true;
+
+ _specialEventTimer = new QTimer(this);
+ _specialEventTimer->setInterval(SPECIAL_EVENT_WAIT_TIME);
+ _specialEventTimer->setSingleShot(true);
+ connect(_specialEventTimer, SIGNAL(timeout()), this, SLOT(showSpecialEventMenu()));
+
}
Frame::~Frame()
@@ -216,23 +242,45 @@ void Frame::slotClicked()
void Frame::mousePressEvent(QMouseEvent* event)
{
- emit clicked();
- if (event->button() == Qt::RightButton)
- {
- /*if (!_dummy)
- DelDummy->setDisabled(true);
- menu->exec(QCursor::pos());*/
- }
- else
- {
+ if(!_remoteControlEnabled)
+ {
+ emit clicked();
+ if (event->button() == Qt::RightButton)
+ {
+ /*if (!_dummy)
+ DelDummy->setDisabled(true);
+ menu->exec(QCursor::pos());*/
+ }
+ else
+ {
- }
- QLabel::mousePressEvent(event);
+ }
+ QLabel::mousePressEvent(event);
+ }
+ else
+ {
+ event->accept();
+ ConsoleLog writeLine("Captured remote control mousePressEvent");
+
+ updateMousePosition(event);
+ sendInputEvent(InputEvent::mousePressRelease(event->button(), event->buttons()));
+ }
}
void Frame::mouseReleaseEvent ( QMouseEvent * event )
{
- QLabel::mouseReleaseEvent(event);
+ if(!_remoteControlEnabled)
+ {
+ QLabel::mouseReleaseEvent(event);
+ }
+ else
+ {
+ event->accept();
+ ConsoleLog writeLine("Captured remote control mouseReleaseEvent");
+
+ updateMousePosition(event);
+ sendInputEvent(InputEvent::mousePressRelease(event->button(), event->buttons()));
+ }
}
QToolButton* Frame::createToolButton(const QString &toolTip, const QIcon &icon, const char *member)
@@ -287,7 +335,11 @@ QImage Frame::getImageForFoto()
void Frame::closeUp()
{
emit clicked();
- MainWindow::getWindow()->closeUp();
+
+ if(_isCloseUp)
+ MainWindow::getWindow()->unCloseUp(getConFrame());
+ else
+ MainWindow::getWindow()->closeUp(getConFrame());
}
void Frame::foto()
@@ -330,3 +382,264 @@ void Frame::setDozent()
getConFrame()->setDozent(true);
}
}
+
+void Frame::setCloseUp(bool value)
+{
+ _isCloseUp = value;
+ button_closeUp->setChecked(value);
+}
+
+void Frame::remoteControlClicked()
+{
+ if(_remoteControlEnabled)
+ {
+ setMouseTracking(false);
+ _mouseMotionEventTimer->stop();
+ button_control->setToolTip(tr("Enable Remote Control"));
+ _remoteControlEnabled = false;
+ button_control->setChecked(false);
+ releaseKeyboard();
+ }
+ else
+ {
+ button_control->setToolTip(tr("Disable Remote Control"));
+ _remoteControlEnabled = true;
+ button_control->setChecked(true);
+ _mouseMotionEventTimer->start();
+ setMouseTracking(true);
+ if(_mouseOver)
+ grabKeyboard();
+ }
+}
+
+void Frame::remoteControlAllClicked()
+{
+ if(_remoteControlToAll)
+ {
+ button_control_all->setToolTip(tr("Remote Control only this Client"));
+ button_control_all->setChecked(false);
+ _remoteControlToAll = false;
+ }
+ else
+ {
+ button_control_all->setToolTip(tr("Remote Control All Clients"));
+ button_control_all->setChecked(true);
+ _remoteControlToAll = true;
+ }
+}
+
+
+
+void Frame::sendMouseMotionEvent()
+{
+ InputEvent evt = InputEvent::mouseMotion(_lastRecordedMousePosition.x(), _lastRecordedMousePosition.y());
+
+ if(!_mousePositionChanged)
+ return;
+
+ _mousePositionChanged = false;
+ sendInputEvent(evt);
+}
+
+void Frame::sendInputEvent(InputEvent const& evt)
+{
+ QString str;
+ eventToString(evt, str);
+ PVSMsg msg(PVSCOMMAND, "INPUTEVENT", str);
+
+ if(_remoteControlEnabled)
+ {
+ if(_remoteControlToAll)
+ {
+ ConsoleLog writeLine(QString("sendInputEvent(%1) to one").arg(evt.toString()));
+ PVSConnectionManager::getManager()->getServer()->sendToAll(msg);
+ }
+ else
+ {
+ ConsoleLog writeLine(QString("sendInputEvent(%1) to all").arg(evt.toString()));
+ _cFrame->getConnection()->sendMessage(msg);
+ }
+ }
+ else
+ {
+ ConsoleLog writeLine("sendMouseMotionEvent() disabled");
+ }
+}
+
+void Frame::mouseMoveEvent(QMouseEvent* event)
+{
+ QPoint newPosition = rescalePosition(event->posF());
+ if(newPosition != _lastRecordedMousePosition) {
+ _lastRecordedMousePosition = newPosition;
+ _mousePositionChanged = true;
+ ConsoleLog writeLine(QString("Mouse moved to (%1,%2)").arg(_lastRecordedMousePosition.x()).arg(_lastRecordedMousePosition.y()));
+ }
+}
+
+QPoint Frame::rescalePosition(QPointF guipos)
+{
+ if(!_clientVNCThread)
+ return QPoint();
+
+ QSize s = size();
+ QSize t = _clientVNCThread->getSize();
+ qreal px, py;
+ px = guipos.x() * t.width() / (qreal)s.width();
+ py = guipos.y() * t.height() / (qreal)s.height();
+ return QPoint((int)px, (int)py);
+}
+
+void Frame::updateMousePosition(QMouseEvent* event)
+{
+ QPoint oldPosition = _lastRecordedMousePosition;
+ _lastRecordedMousePosition = rescalePosition(event->posF());
+ _mousePositionChanged = oldPosition != _lastRecordedMousePosition;
+ sendMouseMotionEvent();
+}
+
+void Frame::enterEvent(QEvent* event)
+{
+ _mouseOver = true;
+ if(_remoteControlEnabled)
+ {
+ grabKeyboard();
+ }
+}
+
+void Frame::leaveEvent(QEvent* event)
+{
+ _mouseOver = false;
+ if(_remoteControlEnabled)
+ {
+ releaseKeyboard();
+ }
+}
+
+void Frame::keyPressEvent(QKeyEvent* event)
+{
+ if(_remoteControlEnabled)
+ {
+ if(event->key() == Qt::Key_Menu)
+ {
+ qDebug("Menu has been pressed");
+ if(!event->isAutoRepeat())
+ _specialEventTimer->start();
+ }
+ else
+ {
+ // The action of the keyboard may depend on the position of the pointer
+ sendMouseMotionEvent();
+
+ int key = event->key();
+
+ if(key >= ' ' && key < 0x100)
+ {
+ // the key is a Latin1 key. We need to find out the correct code to send.
+ QString text = event->text();
+ if(text.length() == 1 && text.at(0).row() == 0)
+ {
+ QChar c = text.at(0);
+
+ // The next problem is that it may be a control character.
+ // This happens when Ctrl is pressed, so we only
+ // modify keys if they are lowercase or uppercase
+ // versions of the keycode.
+
+ if(c.toLower().toLatin1() == (char)key || c.toUpper().toLatin1() == (char)key)
+ {
+ // We found a Latin1 char and pray it is the correct case.
+ key = c.cell();
+ }
+ }
+ }
+ sendInputEvent(InputEvent::keyboardPress(key, event->modifiers()));
+ }
+ }
+ else
+ {
+ QLabel::keyPressEvent(event);
+ }
+}
+
+void Frame::keyReleaseEvent(QKeyEvent* event)
+{
+ if(_remoteControlEnabled)
+ {
+ sendMouseMotionEvent();
+ if(event->key() == Qt::Key_Menu)
+ {
+ if(!event->isAutoRepeat())
+ {
+ qDebug("Menu has been released");
+ if(_specialEventTimer->isActive())
+ {
+ qDebug("Pressing key on client");
+ // Pressing the key has been deferred, so do it now:
+ sendInputEvent(InputEvent::keyboardPress(event->key(), event->modifiers()));
+ }
+ sendInputEvent(InputEvent::keyboardRelease(event->key(), event->modifiers()));
+ _specialEventTimer->stop();
+ }
+ }
+ else
+ {
+ // The action of the keyboard may depend on the position of the pointer
+ sendInputEvent(InputEvent::keyboardRelease(event->key(), event->modifiers()));
+ }
+ }
+ else
+ {
+ QLabel::keyReleaseEvent(event);
+ }
+}
+
+bool Frame::event(QEvent* event)
+{
+ if(_remoteControlEnabled)
+ {
+ bool recognized;
+ switch(event->type())
+ {
+ case QEvent::ShortcutOverride:
+ recognized = true;
+ event->accept();
+ break;
+ case QEvent::KeyPress:
+ recognized = true;
+ keyPressEvent(static_cast<QKeyEvent*>(event));
+ break;
+ case QEvent::KeyRelease:
+ recognized = true;
+ keyReleaseEvent(static_cast<QKeyEvent*>(event));
+ break;
+ default:
+ recognized = false;
+ }
+ if(recognized && event->isAccepted())
+ return true;
+ }
+ return QLabel::event(event);
+}
+
+void Frame::showSpecialEventMenu()
+{
+ qDebug("Trying to show menu...");
+ QMenu* menu = new QMenu(this);
+ QList<SpecialInputEventDescription> specialEvents = SpecialInputEventDescription::describeSpecialEvents();
+ QListIterator<SpecialInputEventDescription> iter(specialEvents);
+ int i;
+ for(i = 0;
+ iter.hasNext();
+ i++)
+ {
+ QAction* act = menu->addAction(iter.next().description);
+ act->setData(i);
+ }
+ QAction* selected = menu->exec(QCursor::pos());
+ if(selected)
+ {
+ int index = selected->data().toInt();
+ sendInputEvent(specialEvents.at(index).toEvent());
+ }
+ delete menu;
+}
diff --git a/src/gui/frame.h b/src/gui/frame.h
index 3004e0c..4a3dd11 100644
--- a/src/gui/frame.h
+++ b/src/gui/frame.h
@@ -8,6 +8,7 @@ class VNCClientThread;
class ConnectionWindow;
class ConnectionFrame;
class MainWindow;
+class InputEvent;
class Frame: public QLabel
{
@@ -48,8 +49,13 @@ public:
QToolButton* button_lock;
QToolButton* button_unlock;
QToolButton* button_dozent;
+ QToolButton* button_control;
+ QToolButton* button_control_all;
QList<QToolButton*> toolButtonList;
+ bool _remoteControlEnabled;
+ bool _remoteControlToAll;
+
public Q_SLOTS:
void updateImage(int x, int y, int w, int h);
void iamDown();
@@ -68,13 +74,26 @@ public Q_SLOTS:
void setLock();
//void unlock();
void setDozent();
+ void setCloseUp(bool value);
+
+private Q_SLOTS:
+ void remoteControlClicked();
+ void remoteControlAllClicked();
+ void sendMouseMotionEvent();
+ void showSpecialEventMenu();
signals:
- void clicked();
+ void clicked();
protected:
void paintEvent(QPaintEvent *event);
void mousePressEvent ( QMouseEvent * event );
void mouseReleaseEvent ( QMouseEvent * event );
+ void mouseMoveEvent ( QMouseEvent * event );
+ void enterEvent(QEvent* event);
+ void leaveEvent(QEvent* event);
+ void keyPressEvent(QKeyEvent* event);
+ void keyReleaseEvent(QKeyEvent* event);
+ bool event(QEvent* event);
private:
QToolButton* createToolButton(const QString &toolTip, const QIcon &icon, const char *member);
@@ -85,6 +104,17 @@ private:
bool _isLocked;
bool _dozent;
int _ux, _uy;
+ bool _isCloseUp;
+
+ // for remote control:
+ QPoint _lastRecordedMousePosition;
+ bool _mousePositionChanged;
+ QTimer* _mouseMotionEventTimer;
+ bool _mouseOver;
+ QTimer* _specialEventTimer;
+ QPoint rescalePosition(QPointF guiPosition);
+ void updateMousePosition(QMouseEvent* event);
+ void sendInputEvent(InputEvent const&);
};
#endif /* FRAME_H_ */
diff --git a/src/gui/mainWindow.cpp b/src/gui/mainWindow.cpp
index 0f2fd0e..1376851 100644
--- a/src/gui/mainWindow.cpp
+++ b/src/gui/mainWindow.cpp
@@ -35,6 +35,7 @@ using namespace std;
#include <src/gui/connectionList.h>
#include <src/gui/connectionWindow.h>
#include <src/gui/profileDialog.h>
+#include <src/gui/processesDialog.h>
//#include <src/gui/dialog.h>
#include <src/core/pvsConnectionManager.h>
#include <src/gui/multicastConfigDialog.h>
@@ -98,7 +99,7 @@ MainWindow::MainWindow(QWidget *parent) :
#ifdef MAINWINDOW_USE_TOUCHGUI //only used for the touchgui
// define the slots we want to use
- connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(combobox1(int))); // Combobox 1 verknüpfen mit IndexChangend Signal
+ connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(combobox1(int))); // Combobox 1 verkn��pfen mit IndexChangend Signal
connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(setindexback()));
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(createProfile())); // profile button
@@ -112,6 +113,7 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->actionUnprojection, SIGNAL(triggered()), this, SLOT(unprojecttoolbar()));
connect(ui->actionDozent, SIGNAL(triggered()), this, SLOT(setdozenttoolbar()));
connect(ui->actionShowProcesses, SIGNAL(triggered()), this, SLOT(showProcesses()));
+ connect(ui->actionStartProcess, SIGNAL(triggered()), this, SLOT(startProcess()));
// Ui specific settings
@@ -138,6 +140,8 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->actionConfigure_Network, SIGNAL(triggered()), this, SLOT(configureNetwork()));
connect(ui->actionShowProcesses, SIGNAL(triggered()), this, SLOT(showProcesses()));
ui->actionShowProcesses->setStatusTip(tr("Show Processes of the selected Client"));
+ connect(ui->actionStartProcess, SIGNAL(triggered()), this, SLOT(startProcess()));
+ ui->actionStartProcess->setStatusTip(tr("Starts Process on the selected Client(s)"));
connect(ui->actionShow_Username, SIGNAL(triggered()), this, SLOT(showusername()));
connect(ui->actionShow_Hostname_IP, SIGNAL(triggered()), this, SLOT(showip()));
@@ -270,24 +274,24 @@ void MainWindow::loadSettings()
if (current.compare("default") == 0)
{
setWindowTitle("PVSmgr - Default");
- QPoint pos1 = settings.value("default/1", QPoint(0, 0)).toPoint();
- MainWindow::getConnectionWindow()->addFrameBySettings("1", pos1);
- QPoint pos2 = settings.value("default/2", QPoint(194, 0)).toPoint();
- MainWindow::getConnectionWindow()->addFrameBySettings("2", pos2);
- QPoint pos3 = settings.value("default/3", QPoint(388, 0)).toPoint();
- MainWindow::getConnectionWindow()->addFrameBySettings("3", pos3);
- QPoint pos4 = settings.value("default/4", QPoint(582, 0)).toPoint();
- MainWindow::getConnectionWindow()->addFrameBySettings("4", pos4);
- QPoint pos5 = settings.value("default/5", QPoint(0, 173)).toPoint();
- MainWindow::getConnectionWindow()->addFrameBySettings("5", pos5);
- QPoint pos6 = settings.value("default/6", QPoint(194, 173)).toPoint();
- MainWindow::getConnectionWindow()->addFrameBySettings("6", pos6);
- QPoint pos7 = settings.value("default/7", QPoint(388, 173)).toPoint();
- MainWindow::getConnectionWindow()->addFrameBySettings("7", pos7);
- QPoint pos8 = settings.value("default/8", QPoint(582, 173)).toPoint();
- MainWindow::getConnectionWindow()->addFrameBySettings("8", pos8);
- QPoint pos9 = settings.value("default/9", QPoint(293, 346)).toPoint();
- MainWindow::getConnectionWindow()->addFrameBySettings("9", pos9);
+// QPoint pos1 = settings.value("default/1", QPoint(0, 0)).toPoint();
+// MainWindow::getConnectionWindow()->addFrameBySettings("1", pos1);
+// QPoint pos2 = settings.value("default/2", QPoint(194, 0)).toPoint();
+// MainWindow::getConnectionWindow()->addFrameBySettings("2", pos2);
+// QPoint pos3 = settings.value("default/3", QPoint(388, 0)).toPoint();
+// MainWindow::getConnectionWindow()->addFrameBySettings("3", pos3);
+// QPoint pos4 = settings.value("default/4", QPoint(582, 0)).toPoint();
+// MainWindow::getConnectionWindow()->addFrameBySettings("4", pos4);
+// QPoint pos5 = settings.value("default/5", QPoint(0, 173)).toPoint();
+// MainWindow::getConnectionWindow()->addFrameBySettings("5", pos5);
+// QPoint pos6 = settings.value("default/6", QPoint(194, 173)).toPoint();
+// MainWindow::getConnectionWindow()->addFrameBySettings("6", pos6);
+// QPoint pos7 = settings.value("default/7", QPoint(388, 173)).toPoint();
+// MainWindow::getConnectionWindow()->addFrameBySettings("7", pos7);
+// QPoint pos8 = settings.value("default/8", QPoint(582, 173)).toPoint();
+// MainWindow::getConnectionWindow()->addFrameBySettings("8", pos8);
+// QPoint pos9 = settings.value("default/9", QPoint(293, 346)).toPoint();
+// MainWindow::getConnectionWindow()->addFrameBySettings("9", pos9);
QString title = "PVSmgr - ";
title.append(_profilName);
@@ -711,61 +715,82 @@ void MainWindow::closeUp()
{
std::list<QString>* selectedClients =
MainWindow::getConnectionList()->getSelectedClients();
- if (!is_closeup)
+
+ if(selectedClients->size() != 1)
+ // Cannot closeUp zero or more than one frames.
+ return;
+
+ PVSClient* pvsClient = PVSConnectionManager::getManager()->getClientFromIp(selectedClients->front());
+
+ closeUp(pvsClient->getConnectionFrame(), pvsClient);
+}
+
+void MainWindow::closeUp(ConnectionFrame* connFrame, PVSClient* pvsClient)
+{
+ std::list<QString>* selectedClients =
+ MainWindow::getConnectionList()->getSelectedClients();
+
+ if(selectedClients->size() != 1)
+ // Cannot closeUp zero or more than one frames.
+ return;
+
+ if(!pvsClient)
+ pvsClient = connFrame->getConnection();
+
+ // Do we already have a closeUp Frame?
+ ConnectionFrame* closeupFrame = conWin->getCloseupFrame();
+
+ if(closeupFrame)
{
- if (selectedClients->size() == 1)
- {
- PVSClient * pvsClient =
- PVSConnectionManager::getManager()->getClientFromIp(
- selectedClients->front().toStdString().c_str());
- _framePosOnCloseUp = pvsClient->getConnectionFrame()->pos();//get the actualy position before run closeup
- if (pvsClient->getVNCConnection())
- {
- conWin->setCloseupFrame(pvsClient->getConnectionFrame());
- _updatefreq
- = pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->getUpdatefreq();
- pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(
- 50);
- pvsClient->getConnectionFrame()->move(5, 5);
- pvsClient->getConnectionFrame()->setWindowFlags(
- Qt::WindowStaysOnTopHint);
- pvsClient->getConnectionFrame()->raise();
- pvsClient->getConnectionFrame()->paintCloseUp(
- ui->widget->width(), ui->widget->height());
-
- is_closeup = true;
- conWin->setCloseupFrame(pvsClient->getConnectionFrame());
- }
- }
+ // Is it the same as the sender one?
+ if(connFrame == closeupFrame)
+ // Then it already is close up.
+ return;
else
- {
- QString
- message =
- QString(
- tr(
- "This operation can only be performed for one selected Client!"));
- QMessageBox::information(this, "PVS", message);
- }
+ // We need to un-closeUp the currently selected closeUp-Frame.
+ unCloseUp(closeupFrame);
}
- else if (conWin->getCloseupFrame())
+
+ _framePosOnCloseUp = connFrame->pos();//get the actualy position before run closeup
+ if (pvsClient->getVNCConnection())
{
- /*PVSClient* pvsClient =
- PVSConnectionManager::getManager()->getClientFromIp(
- selectedClients->front().toStdString().c_str());*/
- conWin->getCloseupFrame()->setWindowFlags(Qt::Widget);
- conWin->getCloseupFrame()->paintCloseUp(
- conWin->getCloseupFrame()->getPrevWidth(),
- conWin->getCloseupFrame()->getPrevHeight());
- conWin->getCloseupFrame()->move(_framePosOnCloseUp);//back to the position before the closeup
- if (conWin->getCloseupFrame()->getConnection()->getVNCConnection())
- conWin->getCloseupFrame()->getFrame()->getVNCClientThread()->setUpdatefreq(
- _updatefreq);
-
- is_closeup = false;
- conWin->setCloseupFrame(NULL);
+ conWin->setCloseupFrame(connFrame);
+ _updatefreq = connFrame->getFrame()->getVNCClientThread()->getUpdatefreq();
+ connFrame->getFrame()->getVNCClientThread()->setUpdatefreq(
+ 50);
+ connFrame->move(5, 5);
+ connFrame->setWindowFlags(Qt::WindowStaysOnTopHint);
+ connFrame->raise();
+ connFrame->paintCloseUp(ui->widget->width(), ui->widget->height());
+
+ conWin->setCloseupFrame(connFrame);
+
+ Frame* frame = connFrame->getFrame();
+ if(frame)
+ frame->setCloseUp(true);
}
}
+void MainWindow::unCloseUp(ConnectionFrame* connFrame)
+{
+ if(!connFrame)
+ return;
+
+ connFrame->setWindowFlags(Qt::Widget);
+ connFrame->paintCloseUp(
+ connFrame->getPrevWidth(),
+ connFrame->getPrevHeight());
+ connFrame->move(_framePosOnCloseUp);//back to the position before the closeup
+ if (connFrame->getConnection()->getVNCConnection())
+ connFrame->getFrame()->getVNCClientThread()->setUpdatefreq(_updatefreq);
+
+ Frame* frame = connFrame->getFrame();
+ if(frame)
+ frame->setCloseUp(false);
+
+ conWin->setCloseupFrame(NULL);
+}
+
/* Perform some action if actionShowProcesses button was pressed
*
*/
@@ -773,13 +798,50 @@ void MainWindow::showProcesses()
{
std::list<QString>* selectedClients =
MainWindow::getConnectionList()->getSelectedClients();
- if (selectedClients->size() == 1)
+ if (selectedClients->size() >= 1)
+ {
+ ProcessDialog procDialog;
+ procDialog.exec();
+
+ }
+ else
+ {
+ QString
+ message =
+ QString(
+ tr(
+ "This operation can only be performed if you have selected at least one Client!"));
+ QMessageBox::information(this, "PVS", message);
+ }
+
+}
+
+
+/* Perform some action if actionStartProcess button was pressed
+ *
+ */
+void MainWindow::startProcess()
+{
+ std::list<QString>* selectedClients =
+ MainWindow::getConnectionList()->getSelectedClients();
+ if (selectedClients->size() >= 1)
{
// do stuff
- PVSClient * pvsClient =
+ /*PVSClient * pvsClient =
PVSConnectionManager::getManager()->getClientFromIp(
- selectedClients->front().toStdString().c_str());
- pvsClient->sendMessage(PVSCOMMAND, "SHOWPROCESSES", "");
+ selectedClients->front().toStdString().c_str());*/
+
+ ProcessesStartDialog procD;
+ QString myString = NULL;
+ int result = procD.exec();
+
+ if (result == 1)
+ {
+ myString = MainWindow::getWindow()->getProcessesDialog();
+ if(!myString.isEmpty())
+ MainWindow::getConnectionWindow()->commandStations("STARTPROCESS",myString);
+ }
+
}
else
{
@@ -787,7 +849,7 @@ void MainWindow::showProcesses()
message =
QString(
tr(
- "This operation can only be performed if you have selected a Client!"));
+ "This operation can only be performed if you have selected at least one Client!"));
QMessageBox::information(this, "PVS", message);
}
}
diff --git a/src/gui/mainWindow.h b/src/gui/mainWindow.h
index 88756fd..58787ed 100644
--- a/src/gui/mainWindow.h
+++ b/src/gui/mainWindow.h
@@ -10,9 +10,11 @@
#include <src/gui/connectionWindow.h>
#include <src/gui/profileDialog.h>
//#include <src/gui/dialog.h>
+#include <src/gui/processesStartDialog.h>
#include <src/core/pvsClient.h>
#include <src/core/pvsConnectionManager.h>
#include "src/gui/aboutDialog.h"
+#include "src/gui/processesDialog.h"
#include "src/gui/serverChatDialog.h"
#include <src/gui/serverFileTransfert.h>
@@ -94,6 +96,9 @@ public:
void setMsgDialog(QString msgd){msgDialog = msgd;};
QString getMsgDialog(){return msgDialog;};
+ void setProcessesDialog(QString procd){procDialog = procd;};
+ QString getProcessesDialog(){return procDialog;};
+
bool isLockAllStatus()
{
return _isLockAll;
@@ -131,9 +136,10 @@ private:
ConnectionDialog* pwDiag;
ConnectionDialog* messageDiag;*/
- AboutDialog *_aboutDialog;
+ AboutDialog *_aboutDialog;
QString msgDialog;
+ QString procDialog;
bool bgimage;
bool locked, locked1;
bool force_square;
@@ -172,6 +178,8 @@ public slots:
void clientlisthide();
void projecttoolbar();
void unprojecttoolbar();
+ void closeUp(ConnectionFrame* connFrame, PVSClient* client = 0);
+ void unCloseUp(ConnectionFrame* connFrame);
void closeUp();
void foto();
void backgroundpicture();
@@ -179,6 +187,7 @@ public slots:
void setdozenttoolbar();
void startChatDialog();
void showProcesses();
+ void startProcess();
private slots:
void onToggleLog(bool showtime);
diff --git a/src/gui/processWidget.cpp b/src/gui/processWidget.cpp
new file mode 100644
index 0000000..9b59b2a
--- /dev/null
+++ b/src/gui/processWidget.cpp
@@ -0,0 +1,98 @@
+/*
+# Copyright (c) 2010 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# processWidget.cpp
+ Widget to start/stop processes on a client. This widget is used in
+ processesDialog.cpp as a tab in the QTabWidget
+# -----------------------------------------------------------------------------
+*/
+
+#include "processesDialog.h"
+#include "processWidget.h"
+#include "ui_processWidget.h"
+
+ProcessWidget::ProcessWidget(QWidget *parent, PVSClient *cl):
+ QWidget(parent),
+ prowui(new Ui::ProcessWidget)
+{
+ prowui->setupUi(this);
+
+ client = cl;
+
+ connect( prowui->startButton, SIGNAL( clicked()), this, SLOT( startProcess()));
+ connect( prowui->refreshButton, SIGNAL( clicked()), this, SLOT( refrProcessList()));
+ connect( prowui->stopButton, SIGNAL( clicked()), this, SLOT( stopProcess()));
+ connect( client, SIGNAL( processVectorReady(bool)), this, SLOT( refrProcessList()));
+
+ sendCommand("SHOWPROCESSES", "");
+}
+
+void ProcessWidget::startProcess()
+{
+ QMessageBox::StandardButton start = QMessageBox::question(0,
+ tr("PVS Start Process"), tr("Do you want to start the process: ") + prowui->processLineEdit->text() +
+ tr(" on User '") + client->getDesktopName() + tr("' ?"),
+ QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+
+ if (start == QMessageBox::Ok)
+ {
+ sendCommand("STARTPROCESS", prowui->processLineEdit->text());
+ sendCommand("SHOWPROCESSES", "");
+ }
+ prowui->processLineEdit->clear();
+}
+
+void ProcessWidget::refrProcessList()
+{
+ for(int i=prowui->processTable->rowCount(); i == 0; i--)
+ {
+ prowui->processTable->removeRow(i);
+ }
+ prowui->processTable->setRowCount(0);
+ QVector<QString> processes = client->getProcessesVector();
+
+ for (int i=0; i<processes.size(); i++)
+ {
+ prowui->processTable->setRowCount(i+1);
+ QStringList processesList = processes.at(i).split(QRegExp("<#>"));
+ for (int j=0; j<processesList.size()&&j<3; j++)
+ {
+ prowui->processTable->setItem(i,j,new QTableWidgetItem(processesList.at(j),0));
+ }
+ }
+ prowui->processTable->selectRow(0);
+}
+
+void ProcessWidget::stopProcess()
+{
+ if (prowui->processTable->rowCount() > 0)
+ {
+ QMessageBox::StandardButton start = QMessageBox::question(0,
+ tr("PVS Start Process"), tr("Do you want to stop the process: ") + prowui->processTable->item(prowui->processTable->currentRow(),1)->text() +
+ tr(" on User '") + client->getDesktopName() + tr("' ?"),
+ QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
+ if (start == QMessageBox::Ok)
+ {
+ sendCommand("KILLPROCESS", prowui->processTable->item(prowui->processTable->currentRow(),0)->text());
+ sendCommand("SHOWPROCESSES", "");
+ }
+ }
+}
+
+void ProcessWidget::sendCommand(QString ident, QString message)
+{
+ client->sendMessage(PVSCOMMAND, ident, message);
+}
+
+ProcessWidget::~ProcessWidget()
+{
+ delete prowui;
+}
diff --git a/src/gui/processWidget.h b/src/gui/processWidget.h
new file mode 100644
index 0000000..7e7eb72
--- /dev/null
+++ b/src/gui/processWidget.h
@@ -0,0 +1,35 @@
+#ifndef PROCESSWIDGET_H_
+#define PROCESSWIDGET_H_
+
+#include <QDialog>
+#include <QtGui>
+#include <QVector>
+
+namespace Ui {
+ class ProcessWidget;
+}
+
+class PVSClient;
+class ProcessWidget: public QWidget
+{
+ Q_OBJECT
+
+public:
+ ProcessWidget(QWidget *parent, PVSClient *client);
+ ~ ProcessWidget();
+ QAbstractItemModel *model;
+public slots:
+ void refrProcessList();
+
+private:
+ Ui::ProcessWidget *prowui;
+ PVSClient *client;
+ QVector<QString> *processes;
+
+private slots:
+ void startProcess();
+ void stopProcess();
+ void sendCommand(QString ident, QString message);
+};
+
+#endif
diff --git a/src/gui/processesDialog.cpp b/src/gui/processesDialog.cpp
new file mode 100644
index 0000000..cda76ea
--- /dev/null
+++ b/src/gui/processesDialog.cpp
@@ -0,0 +1,60 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# processesDialog.cpp
+ Dialog where a tab with running processes for every client is shown
+# -----------------------------------------------------------------------------
+*/
+
+#include "processesDialog.h"
+#include "ui_processesDialog.h"
+#include <src/gui/processWidget.h>
+//#include <src/gui/mainWindow.h>
+
+ProcessDialog::ProcessDialog(QDialog *parent) :
+ QDialog(parent),
+ procui(new Ui::ProcessesDialog)
+{
+ procui->setupUi(this);
+
+ tWidget = new QTabWidget;
+ procui->grLayout->addWidget(tWidget);
+
+ connect( tWidget, SIGNAL( currentChanged(int)), this, SLOT( currChanged()));
+
+ std::list<PVSClient*> listAll =
+ PVSConnectionManager::getManager()->getConnections();
+ for (std::list<PVSClient*>::iterator it = listAll.begin(); it
+ != listAll.end(); it++)
+ {
+ if (*it == NULL || (*it)->getConnectionFrame() == NULL) continue;
+ if ((*it)->getConnectionFrame()->getFrame() &&
+ /*!(*it)->getConnectionFrame()->getFrame()->isDozent() &&*/
+ (*it)->getVNCConnection())
+ tWidget->addTab(new ProcessWidget(0, *it), (*it)->getUserName());
+ else if (!(*it)->getConnectionFrame()->getFrame())
+ ConsoleLog writeError(QString("The Frame connection from client: ").
+ append((*it)->getConnectionFrame()->getTaskbarTitle()).
+ append(QString(" is corrupted. Reconnect the client it again.")));
+ }
+}
+
+// if other Tab is activated we say our tab to refresh the processList
+void ProcessDialog::currChanged()
+{
+ ProcessWidget *temp = static_cast<ProcessWidget*>(tWidget->currentWidget());
+ temp->refrProcessList();
+}
+
+ProcessDialog::~ProcessDialog()
+{
+ delete procui;
+}
diff --git a/src/gui/processesDialog.h b/src/gui/processesDialog.h
new file mode 100644
index 0000000..9d98136
--- /dev/null
+++ b/src/gui/processesDialog.h
@@ -0,0 +1,37 @@
+#ifndef PROCESSESDIALOG_H
+#define PROCESSESDIALOG_H
+
+#include <QDialog>
+#include <QtGui>
+#include <src/gui/processWidget.h>
+#include <src/gui/mainWindow.h>
+#include <list>
+
+
+namespace Ui {
+ class ProcessesDialog;
+}
+
+class ConnectionList;
+class PVSClient;
+class PVSConnectionManager;
+class ProcessesWidget;
+class MainWindow;
+
+class ProcessDialog : public QDialog {
+ Q_OBJECT
+public:
+ ProcessDialog(QDialog *parent = 0);
+ ~ProcessDialog();
+
+
+private:
+ Ui::ProcessesDialog *procui;
+ QTabWidget *tWidget;
+ QDialogButtonBox *buttonBox;
+
+private slots:
+ void currChanged();
+};
+
+#endif // PROCESSESDIALOG_H
diff --git a/src/gui/processesStartDialog.cpp b/src/gui/processesStartDialog.cpp
new file mode 100644
index 0000000..b4c8c79
--- /dev/null
+++ b/src/gui/processesStartDialog.cpp
@@ -0,0 +1,75 @@
+/*
+# Copyright (c) 2010 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# processesStartDialog.cpp
+ Dialog to get process to send to clients
+# -----------------------------------------------------------------------------
+*/
+
+#include "processesStartDialog.h"
+#include "ui_processesStartDialog.h"
+#include <src/gui/mainWindow.h>
+
+ProcessesStartDialog::ProcessesStartDialog(QWidget *parent) :
+ QDialog(parent)
+{
+ textLabel = new QLabel;
+ textLabel->setText("Process to start:");
+
+ messageEdit = new QLineEdit;
+
+ layout = new QGridLayout;
+
+ sendButton = new QPushButton(tr("Start"));
+ cancelButton = new QPushButton(tr("Cancel"));
+
+ connect( sendButton, SIGNAL( clicked()), this, SLOT( send()));
+ connect( cancelButton, SIGNAL( clicked()), this, SLOT( NotSend()));
+
+ layout->addWidget(textLabel,0,0);
+ layout->addWidget(messageEdit,1,0);
+ layout->addWidget(cancelButton,2,0);
+ layout->addWidget(sendButton,2,0);
+
+ setLayout(layout);
+ setWindowTitle(tr("PVS start Process"));
+}
+
+ProcessesStartDialog::~ProcessesStartDialog()
+{
+ //delete procstartui;
+}
+
+void ProcessesStartDialog::send()
+{
+ QString procd = messageEdit->text();
+ MainWindow::getWindow()->setProcessesDialog(procd);
+ messageEdit->clear();
+ emit accept();
+}
+
+void ProcessesStartDialog::NotSend()
+{
+ messageEdit->clear();
+ emit reject();
+}
+
+/*void ProcessesStartDialog::changeEvent(QEvent *e)
+{
+ //QDialog::changeEvent(e);
+ //switch (e->type()) {
+ //case QEvent::LanguageChange:
+ // procstartui->retranslateUi(this);
+ // break;
+ //default:
+ // break;
+ //}
+}*/
diff --git a/src/gui/processesStartDialog.h b/src/gui/processesStartDialog.h
new file mode 100644
index 0000000..61aee4f
--- /dev/null
+++ b/src/gui/processesStartDialog.h
@@ -0,0 +1,31 @@
+#ifndef PROCESSESSTARTDIALOG_H
+#define PROCESSESSTARTDIALOG_H
+
+#include <QDialog>
+#include <QtGui>
+
+
+class MainWindow;
+
+class ProcessesStartDialog : public QDialog {
+ Q_OBJECT
+public:
+ ProcessesStartDialog(QWidget *parent = 0);
+ ~ProcessesStartDialog();
+
+/*protected:
+ void changeEvent(QEvent *e);*/
+
+private:
+ QGridLayout *layout;
+ QLabel *textLabel;
+ QLineEdit *messageEdit;
+ QPushButton *sendButton;
+ QPushButton *cancelButton;
+
+private slots:
+ void send();
+ void NotSend();
+};
+
+#endif // PROCESSESSTARTDIALOG_H
diff --git a/src/gui/ui/mainwindow.ui b/src/gui/ui/mainwindow.ui
index 7913e38..d444092 100644
--- a/src/gui/ui/mainwindow.ui
+++ b/src/gui/ui/mainwindow.ui
@@ -294,6 +294,7 @@
<addaction name="actionLock"/>
<addaction name="actionChat"/>
<addaction name="actionShowProcesses"/>
+ <addaction name="actionStartProcess"/>
</widget>
<action name="actionShow_Username">
<property name="checkable">
@@ -559,6 +560,15 @@
<string>Show Processes of the selected Client</string>
</property>
</action>
+ <action name="actionStartProcess">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/icons/gearsgo.png</normaloff>:/icons/gearsgo.png</iconset>
+ </property>
+ <property name="text">
+ <string>Start Process</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
diff --git a/src/gui/ui/mainwindowtouch.ui b/src/gui/ui/mainwindowtouch.ui
index 24f40b6..3480f09 100644
--- a/src/gui/ui/mainwindowtouch.ui
+++ b/src/gui/ui/mainwindowtouch.ui
@@ -28,8 +28,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>1329</width>
- <height>660</height>
+ <width>1335</width>
+ <height>673</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">
@@ -347,27 +347,18 @@
<bool>false</bool>
</attribute>
<addaction name="action_Exit"/>
- <addaction name="separator"/>
<addaction name="actionFoto"/>
- <addaction name="separator"/>
<addaction name="actionView"/>
- <addaction name="separator"/>
<addaction name="actionProjection"/>
- <addaction name="separator"/>
<addaction name="actionUnprojection"/>
- <addaction name="separator"/>
<addaction name="actionLocksingle"/>
- <addaction name="separator"/>
<addaction name="actionUnlocksingle"/>
- <addaction name="separator"/>
<addaction name="actionLock"/>
- <addaction name="separator"/>
<addaction name="actionresetall"/>
- <addaction name="separator"/>
<addaction name="actionDozent"/>
- <addaction name="separator"/>
<addaction name="actionConfigure_Network"/>
<addaction name="actionShowProcesses"/>
+ <addaction name="actionStartProcess"/>
</widget>
<action name="actionShow_Username">
<property name="checkable">
@@ -660,6 +651,15 @@
<string>Show Processes of the selected Client</string>
</property>
</action>
+ <action name="actionStartProcess">
+ <property name="icon">
+ <iconset resource="../../../pvsmgr.qrc">
+ <normaloff>:/icons/gearsgo.png</normaloff>:/icons/gearsgo.png</iconset>
+ </property>
+ <property name="text">
+ <string>Start Process</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
diff --git a/src/gui/ui/processWidget.ui b/src/gui/ui/processWidget.ui
new file mode 100644
index 0000000..3e7f55e
--- /dev/null
+++ b/src/gui/ui/processWidget.ui
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ProcessWidget</class>
+ <widget class="QWidget" name="ProcessWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>646</width>
+ <height>504</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <widget class="QWidget" name="verticalLayoutWidget_2">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>631</width>
+ <height>481</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Prozessliste</string>
+ </property>
+ <widget class="QWidget" name="verticalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>24</y>
+ <width>611</width>
+ <height>361</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTableWidget" name="processTable">
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="showDropIndicator" stdset="0">
+ <bool>false</bool>
+ </property>
+ <property name="dragDropOverwriteMode">
+ <bool>false</bool>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <property name="gridStyle">
+ <enum>Qt::DotLine</enum>
+ </property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <property name="wordWrap">
+ <bool>false</bool>
+ </property>
+ <property name="cornerButtonEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="rowCount">
+ <number>0</number>
+ </property>
+ <attribute name="horizontalHeaderVisible">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="horizontalHeaderCascadingSectionResizes">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="verticalHeaderHighlightSections">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="horizontalHeaderCascadingSectionResizes">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="horizontalHeaderVisible">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="verticalHeaderHighlightSections">
+ <bool>true</bool>
+ </attribute>
+ <column>
+ <property name="text">
+ <string>ID</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Commandline</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="refreshButton">
+ <property name="text">
+ <string>Aktualisieren</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="stopButton">
+ <property name="text">
+ <string>Prozess beenden</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>80</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Prozess starten</string>
+ </property>
+ <widget class="QWidget" name="horizontalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>20</y>
+ <width>611</width>
+ <height>51</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLineEdit" name="processLineEdit"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="startButton">
+ <property name="text">
+ <string>Prozess starten</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/gui/ui/processesDialog.ui b/src/gui/ui/processesDialog.ui
new file mode 100644
index 0000000..4ac4859
--- /dev/null
+++ b/src/gui/ui/processesDialog.ui
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ProcessesDialog</class>
+ <widget class="QDialog" name="ProcessesDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>654</width>
+ <height>562</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Prozesse</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="geometry">
+ <rect>
+ <x>310</x>
+ <y>530</y>
+ <width>341</width>
+ <height>32</height>
+ </rect>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Close</set>
+ </property>
+ <property name="centerButtons">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QWidget" name="widget" native="true">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>651</width>
+ <height>531</height>
+ </rect>
+ </property>
+ <widget class="QWidget" name="gridLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>651</width>
+ <height>521</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="grLayout"/>
+ </widget>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ProcessesDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ProcessesDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/gui/ui/processesStartDialog.ui b/src/gui/ui/processesStartDialog.ui
new file mode 100644
index 0000000..5d8c7ee
--- /dev/null
+++ b/src/gui/ui/processesStartDialog.ui
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ProcessesStartDialog</class>
+ <widget class="QDialog" name="ProcessesStartDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>393</width>
+ <height>109</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Start Process</string>
+ </property>
+ <widget class="QWidget" name="layoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>20</y>
+ <width>351</width>
+ <height>71</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLineEdit" name="message"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>5</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>108</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancel">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="send">
+ <property name="text">
+ <string>Send</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt
new file mode 100644
index 0000000..26eeb64
--- /dev/null
+++ b/src/input/CMakeLists.txt
@@ -0,0 +1,175 @@
+include(${QT_USE_FILE})
+
+set(pvsinput_SRCS
+ inputEvent.cpp
+ unprivilegedInputHandlerChain.cpp
+ inputEventHandler.cpp
+ logNonMatchingHandler.cpp
+ )
+
+set(feature_DEFS)
+
+if(UNIX)
+ find_file(XINPUT2_HDR X11/extensions/XInput2.h)
+ if(XINPUT2_HDR)
+ list(APPEND feature_DEFS
+ HAVE_XINPUT2_H)
+ endif()
+
+ find_file(XINPUT_HDR X11/extensions/XInput.h)
+ if(XINPUT_HDR)
+ list(APPEND feature_DEFS
+ HAVE_XINPUT_H)
+ endif()
+
+ find_file(XKBLIB_HDR X11/XKBlib.h)
+ if(XKBLIB_HDR)
+ list(APPEND feature_DEFS
+ HAVE_XKBLIB_H)
+ endif()
+
+ set(pvsprivinputd_SRCS
+ pvsprivinputd.cpp
+ pvsPrivInputHandler.cpp
+ pvsCheckPrivileges.cpp
+ pvsSyslog.cpp
+ pvsPrivInputSignalHandler.cpp
+ rebootSystemHandler.cpp
+ killX11Handler.cpp
+ magicSysRqHandler.cpp
+ sayHelloHandler.cpp
+ privilegedInputHandlerChain.cpp
+ allowLocalOrPrivileged.cpp
+ )
+
+ set(pvsprivinputd_MOC_HDRS
+ pvsPrivInputHandler.h
+ pvsCheckPrivileges.h
+ pvsSyslog.h
+ pvsPrivInputSignalHandler.h
+ )
+
+ qt4_wrap_cpp(pvsprivinputd_MOC_SRCS
+ ${pvsprivinputd_MOC_HDRS}
+ )
+
+ add_executable(pvsprivinputd
+ ${pvsprivinputd_SRCS}
+ ${pvsprivinputd_MOC_SRCS}
+ )
+
+ set_property(SOURCE ${pvsprivinputd_SRCS} ${pvsprivinputd_MOC_SRCS}
+ APPEND
+ PROPERTY COMPILE_FLAGS " -I${QT_QTCORE_INCLUDE_DIR} -I${QT_QTDBUS_INCLUDE_DIR} -I${QT_QTNETWORK_INCLUDE_DIR}")
+
+ target_link_libraries(pvsprivinputd
+ pvsinput
+ ${QT_QTCORE_LIBRARY}
+ ${QT_QTDBUS_LIBRARY}
+ ${QT_QTNETWORK_LIBRARY}
+ )
+
+ list(APPEND pvsinput_SRCS
+ pvsPrivInputSocket.cpp
+ x11InputUtils.cpp
+ x11FakeKeyboardHandler.cpp
+ x11FakeMouseHandler.cpp
+ privilegedHandlerForwarder.cpp
+ )
+
+ # we need pkg-config to find out where to install the action file:
+ find_package(PkgConfig)
+ if(NOT PKG_CONFIG_FOUND)
+ # we will try to make a best effort and put our policy file into
+ # ${PREFIX}/share/polkit-1, but only if we can find
+ # the pkexec executable.
+ find_program(PKEXEC_LOCATION pkexec)
+ if(PKEXEC_LOCATION OR ENABLE_POLKIT)
+ set(POLKIT_FOUND ON)
+ set(POLKIT_PREFIX ${CMAKE_INSTALL_PREFIX})
+ set(POLKIT_POLICY_DIR ${POLKIT_PREFIX}/share/polkit-1/actions)
+ endif()
+ else()
+ pkg_check_modules(POLKIT "polkit-gobject-1")
+ if(POLKIT_FOUND)
+ execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} polkit-gobject-1 --variable=policydir
+ OUTPUT_VARIABLE POLKIT_POLICY_DIR
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(NOT POLKIT_POLICY_DIR)
+ set(POLKIT_FOUND OFF)
+ endif()
+ endif()
+ endif()
+
+ # now, arrange for policykit integration:
+ if(POLKIT_FOUND OR ENABLE_POLKIT)
+ if(NOT POLKIT_POLICY_DIR)
+ message(SEND_ERROR "PolicyKit integration is enabled, but cannot find PolicyKit's actions directory. Please set POLKIT_POLICY_DIR to the right value")
+ endif()
+
+ install(FILES org.openslx.pvs.input.policy
+ DESTINATION ${POLKIT_POLICY_DIR})
+ set_property(SOURCE ${pvsprivinputd_SRCS}
+ APPEND
+ PROPERTY COMPILE_DEFINITIONS HAVE_POLKIT)
+ message(STATUS "PolicyKit integration: enabled")
+ else()
+ message(STATUS "PolicyKit integration: disabled")
+ endif()
+
+ # Install a pvsprivinputd.conf template
+ install(FILES pvsprivinputd.conf
+ DESTINATION /etc
+ PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
+
+ # Install the daemon
+ install(TARGETS pvsprivinputd
+ DESTINATION sbin)
+endif()
+
+set_property(SOURCE ${pvsinput_SRCS} ${pvsprivinputd_SRCS}
+ APPEND
+ PROPERTY COMPILE_DEFINITIONS ${feature_DEFS}
+)
+
+set(pvsinput_TSS
+ i18n/pvsinput_de_DE.ts
+ i18n/pvsinput_fr_FR.ts
+ i18n/pvsinput_es_MX.ts
+ i18n/pvsinput_ar_JO.ts
+ i18n/pvsinput_pl_PL.ts)
+
+QT4_CREATE_TRANSLATION(pvsinput_QMS
+ ${pvsinput_SRCS}
+ ${pvsprivinputd_SRCS}
+ ${pvsinput_TSS})
+
+# Generate an RCC file for our translations:
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pvsinput.qrc"
+ "<RCC version='1.0'><qresource prefix='/i18n/pvsinput'>")
+foreach(qm ${pvsinput_QMS})
+ file(RELATIVE_PATH qm_rel ${CMAKE_CURRENT_BINARY_DIR} ${qm})
+ get_filename_component(qm_basename ${qm} NAME)
+ file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/pvsinput.qrc"
+ "<file alias='${qm_basename}'>${qm_rel}</file>")
+endforeach()
+file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/pvsinput.qrc" "</qresource></RCC>")
+
+qt4_add_resources(pvsinput_RCS
+ "${CMAKE_CURRENT_BINARY_DIR}/pvsinput.qrc")
+
+add_library(
+ pvsinput
+ STATIC
+ ${pvsinput_SRCS}
+ ${pvsinput_RCS}
+)
+
+if(EXISTS /etc/gentoo-release)
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pvsprivinputd.gentooinit.in ${CMAKE_CURRENT_BINARY_DIR}/pvsprivinputd.init @ONLY@)
+else()
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pvsprivinputd.lsbinit.in ${CMAKE_CURRENT_BINARY_DIR}/pvsprivinputd.init @ONLY@)
+endif()
+install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/pvsprivinputd.init
+ DESTINATION /etc/init.d
+ RENAME pvsprivinputd)
diff --git a/src/input/allowLocalOrPrivileged.cpp b/src/input/allowLocalOrPrivileged.cpp
new file mode 100644
index 0000000..ba456dc
--- /dev/null
+++ b/src/input/allowLocalOrPrivileged.cpp
@@ -0,0 +1,21 @@
+/*
+ * inputHandlerSecurityPolicies.cpp
+ *
+ * Created on: Oct 7, 2010
+ * Author: brs
+ */
+
+#include "inputEventHandler.h"
+#include "pvsCheckPrivileges.h"
+
+bool input_policy::AllowLocalOrPrivileged::allow(InputEventContext const* ctx)
+{
+ if(ctx)
+ {
+ if(PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::SESSION_LOCAL, ctx))
+ return true;
+ if(PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::USER_PRIVILEGED, ctx))
+ return true;
+ }
+ return false;
+}
diff --git a/src/input/detail/Makefile.autogen b/src/input/detail/Makefile.autogen
new file mode 100644
index 0000000..cbd52be
--- /dev/null
+++ b/src/input/detail/Makefile.autogen
@@ -0,0 +1,5 @@
+all : typeList_autogen.h
+.PHONY : all
+
+typeList_autogen.h : gen/gen_typeList
+ gen/gen_typeList > typeList_autogen.h
diff --git a/src/input/detail/gen/gen_typeList.cpp b/src/input/detail/gen/gen_typeList.cpp
new file mode 100644
index 0000000..21056f9
--- /dev/null
+++ b/src/input/detail/gen/gen_typeList.cpp
@@ -0,0 +1,118 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # detail/gen/gen_policyChain.cpp:
+ # - generate the input_policy::detail::TypeList class
+ # --------------------------------------------------------------------------
+ */
+
+#include <iostream>
+
+using namespace std;
+
+#define NUM_MAX_ENTRIES 16
+
+int main(int, char**)
+{
+ int i;
+
+ cout << "template<";
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "typename T" << i << " = void";
+ }
+ cout << ">\nstruct TypeList {\n";
+ cout << "typedef T0 head;\n";
+ cout << "typedef TypeList<";
+ for(i = 1; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i > 1)
+ cout << ", ";
+ cout << "T" << i;
+ }
+ cout << ", void > tail;\n";
+ cout << "};\n";
+
+ // Contains:
+ cout << "template<typename Needle, typename Haystack>\n"
+ "struct Contains { static const int index = -1; static const bool value = false; };\n";
+
+ // specializations:
+ cout << "#ifndef DOXYGEN_RUNNING\n";
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ int j;
+
+ cout << "template<typename Needle";
+ for(j = 0; j < NUM_MAX_ENTRIES; j++)
+ {
+ if(j == i)
+ continue;
+ cout << ", typename T" << j;
+ }
+ cout << ">\nstruct Contains<Needle, TypeList<";
+ for(j = 0; j < NUM_MAX_ENTRIES; j++)
+ {
+ if(j)
+ cout << ", ";
+ if(j == i)
+ cout << "Needle";
+ else
+ cout << "T" << j;
+ }
+ cout << "> >\n{ static const int index = " << i << "; static const bool value = true; };\n";
+ }
+ cout << "#endif\n";
+
+ // Empty List:
+ cout << "typedef TypeList<";
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "void";
+ }
+ cout << " > EmptyList;\n";
+
+ // Macros:
+ cout << "#define IMPLICIT_TYPE_LIST_PARAMS(prefix) ";
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "typename prefix##" << i << " = void";
+ }
+ cout << "\n";
+
+ cout << "#define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) ";
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "typename prefix##" << i;
+ }
+ cout << "\n";
+
+ cout << "#define IMPLICIT_TYPE_LIST_ARGS(prefix) ";
+ for(i = 0; i < NUM_MAX_ENTRIES; i++)
+ {
+ if(i)
+ cout << ", ";
+ cout << "prefix##" << i;
+ }
+ cout << "\n";
+
+ cout << "#define IMPLICIT_TYPE_LIST(prefix) ::input_policy::detail::TypeList<IMPLICIT_TYPE_LIST_ARGS(prefix) >\n";
+
+ return 0;
+}
diff --git a/src/input/detail/policyChain.h b/src/input/detail/policyChain.h
new file mode 100644
index 0000000..efaf371
--- /dev/null
+++ b/src/input/detail/policyChain.h
@@ -0,0 +1,74 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # detail/policyChain.h:
+ # - Tie together the different bits of policy information a handler may
+ # give us
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef POLICYCHAIN_H_
+#define POLICYCHAIN_H_
+
+#include "typeList.h"
+
+namespace input_policy
+{
+namespace detail
+{
+
+template<typename BaseCase, typename PolicyList>
+struct PolicyChain : public PolicyList::head::template apply_<PolicyChain<BaseCase, typename PolicyList::tail> >
+{
+};
+
+template<typename BaseCase>
+struct PolicyChain<BaseCase, EmptyList> : public BaseCase
+{
+};
+
+}
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Macros that enable specification of policies:
+// A policy is declared like this:
+// template< PARAM1, PARAM2, ... >
+// BEGIN_POLICY_CLASS(MyPolicy) {
+// static const int field1 = 2;
+// ...
+// } END_POLICY_CLASS(MyPolicy);
+/////////////////////////////////////////////////////////////////////////
+#define BEGIN_POLICY_CLASS(policyName) \
+ struct policyName { \
+ template<typename NextPolicy> \
+ struct apply_ : public NextPolicy
+#define END_POLICY_CLASS \
+ ; };
+
+/////////////////////////////////////////////////////////////////////////
+// A macro that enables us to use a template parameter list
+// in a class using a policy, like this:
+//
+// template<POLICY_PARAMS>
+// struct MyPolicyBasedClass
+// {
+// typedef USE_POLICY(baseCase) policy_type;
+// };
+//
+// now, the following type is valid:
+// MyPolicyBasedClass<Policy1, Policy2>
+/////////////////////////////////////////////////////////////////////////
+#define POLICY_PARAMS IMPLICIT_TYPE_LIST_PARAMS(Policy)
+#define POLICY_PARAMS_LIST IMPLICIT_TYPE_LIST(Policy)
+#define USE_POLICY(baseCase) ::input_policy::detail::PolicyChain<baseCase, POLICY_PARAMS_LIST>
+
+#endif /* POLICYCHAIN_H_ */
diff --git a/src/input/detail/systemTraits.h b/src/input/detail/systemTraits.h
new file mode 100644
index 0000000..7f5582f
--- /dev/null
+++ b/src/input/detail/systemTraits.h
@@ -0,0 +1,94 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # detail/systemTraits.h:
+ # - Define system traits and provide a way to match against them
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef SYSTEMTRAITS_H_
+#define SYSTEMTRAITS_H_
+
+#include "typeList.h"
+
+#define DEFINE_SYSTEM_TRAIT(name) struct name;
+#define BEGIN_SYSTEM_TRAITS typedef TypeList<
+#define END_SYSTEM_TRAITS > SystemTraits;
+
+namespace input_policy
+{
+
+// Trait names are externally visible.
+DEFINE_SYSTEM_TRAIT(UnixLike)
+DEFINE_SYSTEM_TRAIT(LinuxSystem)
+DEFINE_SYSTEM_TRAIT(X11GUI)
+DEFINE_SYSTEM_TRAIT(ConsoleKitSupported)
+
+namespace detail
+{
+BEGIN_SYSTEM_TRAITS
+#ifdef __linux
+UnixLike,
+LinuxSystem,
+X11GUI,
+ConsoleKitSupported
+#endif
+END_SYSTEM_TRAITS
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Boolean logic as applied to system traits
+/////////////////////////////////////////////////////////////////////////
+template<IMPLICIT_TYPE_LIST_PARAMS(T)>
+struct AllOf;
+
+template<IMPLICIT_TYPE_LIST_PARAMS(T)>
+struct AnyOf;
+
+namespace detail
+{
+/////////////////////////////////////////////////////////////////////////
+// Does the list of system traits match what we have given?
+/////////////////////////////////////////////////////////////////////////
+template<typename Needles, typename Haystack>
+struct Matches
+{
+ // if Needles is neither AnyOf<...> nor AllOf<...>
+ // then we need to know if the Haystack contains it:
+ static const bool value = Contains<Needles, Haystack>::value;
+};
+
+template<typename Haystack>
+struct MatchesPredicate
+{
+ template<typename Needle>
+ struct apply
+ {
+ static const bool value = Matches<Needle, Haystack>::value;
+ };
+};
+
+template<IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(T), typename Haystack>
+struct Matches<AnyOf<IMPLICIT_TYPE_LIST_ARGS(T)>, Haystack>
+{
+ static const bool value = ForAnyInTypeList<MatchesPredicate<Haystack>, IMPLICIT_TYPE_LIST(T)>::value;
+};
+
+template<IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(T), typename Haystack>
+struct Matches<AllOf<IMPLICIT_TYPE_LIST_ARGS(T)>, Haystack>
+{
+ static const bool value = ForAllInTypeList<MatchesPredicate<Haystack>, IMPLICIT_TYPE_LIST(T)>::value;
+};
+}
+
+}
+
+#endif /* SYSTEMTRAITS_H_ */
diff --git a/src/input/detail/typeList.h b/src/input/detail/typeList.h
new file mode 100644
index 0000000..5b915a9
--- /dev/null
+++ b/src/input/detail/typeList.h
@@ -0,0 +1,76 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # detail/typeList.h:
+ # - Compile-time metaprogramming facilities: Type Lists and Member Check
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef TYPELIST_H_
+#define TYPELIST_H_
+
+namespace input_policy
+{
+namespace detail
+{
+
+/////////////////////////////////////////////////////////////////////////
+// TypeList, Contains, EmptyList:
+// This class is autogenerated by gen/gen_typeList.cpp
+/////////////////////////////////////////////////////////////////////////
+#include "typeList_autogen.h"
+
+/////////////////////////////////////////////////////////////////////////
+// Type-level functions that do not need to be autogenerated as they
+// do not depend on the maximum number of entries:
+//
+// ForAnyInTypeList<Predicate, List>::value == true
+// if there is any entry E in List for which
+// Predicate::apply<E>::value == true
+/////////////////////////////////////////////////////////////////////////
+template<typename Predicate, typename List>
+struct ForAnyInTypeList
+{
+ static const bool value =
+ Predicate::template apply<typename List::head>::value ||
+ ForAnyInTypeList<Predicate, typename List::tail>::value;
+};
+
+template<typename Predicate>
+struct ForAnyInTypeList<Predicate, EmptyList>
+{
+ static const bool value = false;
+};
+
+/////////////////////////////////////////////////////////////////////////
+// ForAllInTypeList<Predicate, List>::value == true
+// if there is not any entry E in List for which
+// Predicate::apply<E>::value == false
+/////////////////////////////////////////////////////////////////////////
+template<typename Predicate, typename List>
+struct ForAllInTypeList
+{
+ static const bool value =
+ Predicate::template apply<typename List::head>::value &&
+ ForAllInTypeList<Predicate, typename List::tail>::value;
+};
+
+template<typename Predicate>
+struct ForAllInTypeList<Predicate, EmptyList>
+{
+ static const bool value = true;
+};
+
+}
+
+}
+
+#endif /* TYPELIST_H_ */
diff --git a/src/input/detail/typeList_autogen.h b/src/input/detail/typeList_autogen.h
new file mode 100644
index 0000000..79f1335
--- /dev/null
+++ b/src/input/detail/typeList_autogen.h
@@ -0,0 +1,62 @@
+template<typename T0 = void, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void, typename T13 = void, typename T14 = void, typename T15 = void>
+struct TypeList {
+typedef T0 head;
+typedef TypeList<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, void > tail;
+};
+template<typename Needle, typename Haystack>
+struct Contains { static const int index = -1; static const bool value = false; };
+#ifndef DOXYGEN_RUNNING
+template<typename Needle, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<Needle, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 0; static const bool value = true; };
+template<typename Needle, typename T0, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, Needle, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 1; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, Needle, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 2; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, Needle, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 3; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, Needle, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 4; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, Needle, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 5; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, Needle, T7, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 6; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, Needle, T8, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 7; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, Needle, T9, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 8; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, Needle, T10, T11, T12, T13, T14, T15> >
+{ static const int index = 9; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Needle, T11, T12, T13, T14, T15> >
+{ static const int index = 10; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T12, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, Needle, T12, T13, T14, T15> >
+{ static const int index = 11; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T13, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, Needle, T13, T14, T15> >
+{ static const int index = 12; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T14, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, Needle, T14, T15> >
+{ static const int index = 13; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T15>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, Needle, T15> >
+{ static const int index = 14; static const bool value = true; };
+template<typename Needle, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14>
+struct Contains<Needle, TypeList<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, Needle> >
+{ static const int index = 15; static const bool value = true; };
+#endif
+typedef TypeList<void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void > EmptyList;
+#define IMPLICIT_TYPE_LIST_PARAMS(prefix) typename prefix##0 = void, typename prefix##1 = void, typename prefix##2 = void, typename prefix##3 = void, typename prefix##4 = void, typename prefix##5 = void, typename prefix##6 = void, typename prefix##7 = void, typename prefix##8 = void, typename prefix##9 = void, typename prefix##10 = void, typename prefix##11 = void, typename prefix##12 = void, typename prefix##13 = void, typename prefix##14 = void, typename prefix##15 = void
+#define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) typename prefix##0, typename prefix##1, typename prefix##2, typename prefix##3, typename prefix##4, typename prefix##5, typename prefix##6, typename prefix##7, typename prefix##8, typename prefix##9, typename prefix##10, typename prefix##11, typename prefix##12, typename prefix##13, typename prefix##14, typename prefix##15
+#define IMPLICIT_TYPE_LIST_ARGS(prefix) prefix##0, prefix##1, prefix##2, prefix##3, prefix##4, prefix##5, prefix##6, prefix##7, prefix##8, prefix##9, prefix##10, prefix##11, prefix##12, prefix##13, prefix##14, prefix##15
+#define IMPLICIT_TYPE_LIST(prefix) ::input_policy::detail::TypeList<IMPLICIT_TYPE_LIST_ARGS(prefix) >
diff --git a/src/input/i18n.h b/src/input/i18n.h
new file mode 100644
index 0000000..d64c7cf
--- /dev/null
+++ b/src/input/i18n.h
@@ -0,0 +1,33 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # i18n.h:
+ # - For library users: Make sure the translations are linked and registered
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef I18N_H_
+#define I18N_H_
+
+#include <QCoreApplication>
+#include <QLocale>
+#include <QTranslator>
+
+#define USE_PVSINPUT_TRANSLATIONS \
+ do { \
+ Q_INIT_RESOURCE(pvsinput); \
+ QTranslator* translator = new QTranslator(QCoreApplication::instance()); \
+ translator->load("pvsinput_" + QLocale::system().name(), ":/i18n/pvsinput"); \
+ QCoreApplication::instance()->installTranslator(translator); \
+ } while(false)
+
+
+#endif /* I18N_H_ */
diff --git a/src/input/i18n/pvsinput_ar_JO.ts b/src/input/i18n/pvsinput_ar_JO.ts
new file mode 100644
index 0000000..bf25eda
--- /dev/null
+++ b/src/input/i18n/pvsinput_ar_JO.ts
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="ar_JO">
+<context>
+ <name>InputEvent</name>
+ <message>
+ <location filename="../inputEvent.cpp" line="131"/>
+ <source>Say Hello</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="132"/>
+ <source>Reboot</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="133"/>
+ <source>Kill X Server</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="134"/>
+ <source>Reboot immediately</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="135"/>
+ <source>Power off immediately</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="136"/>
+ <source>Crash System</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="137"/>
+ <source>Turn off raw keyboard mode</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="138"/>
+ <source>Send SIGTERM to all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="139"/>
+ <source>Send SIGKILL to all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="140"/>
+ <source>Kill all on this terminal</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="141"/>
+ <source>Activate OOM killer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="142"/>
+ <source>Make real-time tasks niceable</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="143"/>
+ <source>Force-thaw filesystems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="144"/>
+ <source>Sync all mounted filesystems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="145"/>
+ <source>Remount all readonly</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="146"/>
+ <source>Show all held locks</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="147"/>
+ <source>Show stack traces</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="148"/>
+ <source>Dump memory info</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="149"/>
+ <source>Dump registers and flags</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="150"/>
+ <source>Dump timers and clockevents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="151"/>
+ <source>Dump task list</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="152"/>
+ <source>Dump uninterruptible tasks</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="153"/>
+ <source>Dump ftrace buffer</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <location filename="../pvsprivinputd.cpp" line="66"/>
+ <source>Usage: %1 [--help|-h] [--daemon|-d] [--log=&lt;Logger&gt;|-l&lt;Logger&gt;]
+
+Options:
+ --help, -h Show this message
+ --daemon, -d Run in background
+ --log=&lt;Logger&gt;,
+ -l&lt;Logger&gt; Redirect all output to &lt;Logger&gt;
+ valid values are:
+ - any file name
+ - `syslog&apos; to redirect output to the system log
+ - `null&apos; to discard output (default)
+ (without quotes)
+
+Signals:
+ SIGINT, SIGTERM (or press Ctrl+C when run in foreground)
+ Quit
+ SIGHUP Reload configuration and cached user data
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/src/input/i18n/pvsinput_de_DE.ts b/src/input/i18n/pvsinput_de_DE.ts
new file mode 100644
index 0000000..002016a
--- /dev/null
+++ b/src/input/i18n/pvsinput_de_DE.ts
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="de_DE">
+<context>
+ <name>InputEvent</name>
+ <message>
+ <location filename="../inputEvent.cpp" line="131"/>
+ <source>Say Hello</source>
+ <translation>Hallo sagen</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="132"/>
+ <source>Reboot</source>
+ <translation>Neustart</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="133"/>
+ <source>Kill X Server</source>
+ <translation>X-Server töten</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="134"/>
+ <source>Reboot immediately</source>
+ <translation>Sofort neu starten</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="135"/>
+ <source>Power off immediately</source>
+ <translation>Sofort abschalten</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="136"/>
+ <source>Crash System</source>
+ <translation>Systemabsturz</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="137"/>
+ <source>Turn off raw keyboard mode</source>
+ <translation>RAW-Tastatur-Modus abschalten</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="138"/>
+ <source>Send SIGTERM to all</source>
+ <translation>SIGTERM an alle Prozesse senden</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="139"/>
+ <source>Send SIGKILL to all</source>
+ <translation>SIGKILL an alle Prozesse senden</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="140"/>
+ <source>Kill all on this terminal</source>
+ <translation>Alle Prozesse an diesem Terminal töten</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="141"/>
+ <source>Activate OOM killer</source>
+ <translation>OOM-Killer aktivieren</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="142"/>
+ <source>Make real-time tasks niceable</source>
+ <translation>Nice für Echtzeitprozesse ermöglichen</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="143"/>
+ <source>Force-thaw filesystems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="144"/>
+ <source>Sync all mounted filesystems</source>
+ <translation>Alle eingebundenen Dateisysteme sync(2)en</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="145"/>
+ <source>Remount all readonly</source>
+ <translation>Alle Dateisysteme nur-lesbar mounten</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="146"/>
+ <source>Show all held locks</source>
+ <translation>Alle gehaltenen Sperren zeigen</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="147"/>
+ <source>Show stack traces</source>
+ <translation>Stacktraces anzigen</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="148"/>
+ <source>Dump memory info</source>
+ <translation>Speicherinfo anzeigen</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="149"/>
+ <source>Dump registers and flags</source>
+ <translation>Register und Flags anzeigen</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="150"/>
+ <source>Dump timers and clockevents</source>
+ <translation>Timer und Clockevents anzeigen</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="151"/>
+ <source>Dump task list</source>
+ <translation>Taskliste anzeigen</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="152"/>
+ <source>Dump uninterruptible tasks</source>
+ <translation>Ununterbrechbare Tasks anzeigen</translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="153"/>
+ <source>Dump ftrace buffer</source>
+ <translation>ftrace-Puffer anzeigen</translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <location filename="../pvsprivinputd.cpp" line="66"/>
+ <source>Usage: %1 [--help|-h] [--daemon|-d] [--log=&lt;Logger&gt;|-l&lt;Logger&gt;]
+
+Options:
+ --help, -h Show this message
+ --daemon, -d Run in background
+ --log=&lt;Logger&gt;,
+ -l&lt;Logger&gt; Redirect all output to &lt;Logger&gt;
+ valid values are:
+ - any file name
+ - `syslog&apos; to redirect output to the system log
+ - `null&apos; to discard output (default)
+ (without quotes)
+
+Signals:
+ SIGINT, SIGTERM (or press Ctrl+C when run in foreground)
+ Quit
+ SIGHUP Reload configuration and cached user data
+</source>
+ <translation>Verwendung: %1 [--help|-h] [--daemon|-d] [--log=&lt;Logger&gt;|-l&lt;Logger&gt;]
+
+Optionen:
+ --help, -h Diese Nachricht anzeigen
+ --daemon, -d Im Hintergrund laufen
+ --log=&lt;Logger&gt;,
+ -l&lt;Logger&gt; Alle Ausgaben an &lt;Logger&gt; weiterleiten
+ Mögliche Werte für &lt;Logger&gt;:
+ - Ein Dateiname
+ - `syslog&apos;, um Ausgaben an das Systemlog zu leiten
+ - `null&apos;, um Ausgaben zu verwerfen
+ Standardwert: null
+ Werte ohne Anführungszeichen eingeben
+
+Signale:
+ SIGINT, SIGTERM (oder Strg+C wenn nicht im Hintergrund)
+ Beenden
+ SIGHUP Konfiguration und Benutzerdatenbank neu laden
+</translation>
+ </message>
+</context>
+</TS>
diff --git a/src/input/i18n/pvsinput_es_MX.ts b/src/input/i18n/pvsinput_es_MX.ts
new file mode 100644
index 0000000..d805d0e
--- /dev/null
+++ b/src/input/i18n/pvsinput_es_MX.ts
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="es_MX">
+<context>
+ <name>InputEvent</name>
+ <message>
+ <location filename="../inputEvent.cpp" line="131"/>
+ <source>Say Hello</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="132"/>
+ <source>Reboot</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="133"/>
+ <source>Kill X Server</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="134"/>
+ <source>Reboot immediately</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="135"/>
+ <source>Power off immediately</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="136"/>
+ <source>Crash System</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="137"/>
+ <source>Turn off raw keyboard mode</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="138"/>
+ <source>Send SIGTERM to all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="139"/>
+ <source>Send SIGKILL to all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="140"/>
+ <source>Kill all on this terminal</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="141"/>
+ <source>Activate OOM killer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="142"/>
+ <source>Make real-time tasks niceable</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="143"/>
+ <source>Force-thaw filesystems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="144"/>
+ <source>Sync all mounted filesystems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="145"/>
+ <source>Remount all readonly</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="146"/>
+ <source>Show all held locks</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="147"/>
+ <source>Show stack traces</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="148"/>
+ <source>Dump memory info</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="149"/>
+ <source>Dump registers and flags</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="150"/>
+ <source>Dump timers and clockevents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="151"/>
+ <source>Dump task list</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="152"/>
+ <source>Dump uninterruptible tasks</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="153"/>
+ <source>Dump ftrace buffer</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <location filename="../pvsprivinputd.cpp" line="66"/>
+ <source>Usage: %1 [--help|-h] [--daemon|-d] [--log=&lt;Logger&gt;|-l&lt;Logger&gt;]
+
+Options:
+ --help, -h Show this message
+ --daemon, -d Run in background
+ --log=&lt;Logger&gt;,
+ -l&lt;Logger&gt; Redirect all output to &lt;Logger&gt;
+ valid values are:
+ - any file name
+ - `syslog&apos; to redirect output to the system log
+ - `null&apos; to discard output (default)
+ (without quotes)
+
+Signals:
+ SIGINT, SIGTERM (or press Ctrl+C when run in foreground)
+ Quit
+ SIGHUP Reload configuration and cached user data
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/src/input/i18n/pvsinput_fr_FR.ts b/src/input/i18n/pvsinput_fr_FR.ts
new file mode 100644
index 0000000..af231ea
--- /dev/null
+++ b/src/input/i18n/pvsinput_fr_FR.ts
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+<context>
+ <name>InputEvent</name>
+ <message>
+ <location filename="../inputEvent.cpp" line="131"/>
+ <source>Say Hello</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="132"/>
+ <source>Reboot</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="133"/>
+ <source>Kill X Server</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="134"/>
+ <source>Reboot immediately</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="135"/>
+ <source>Power off immediately</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="136"/>
+ <source>Crash System</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="137"/>
+ <source>Turn off raw keyboard mode</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="138"/>
+ <source>Send SIGTERM to all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="139"/>
+ <source>Send SIGKILL to all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="140"/>
+ <source>Kill all on this terminal</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="141"/>
+ <source>Activate OOM killer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="142"/>
+ <source>Make real-time tasks niceable</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="143"/>
+ <source>Force-thaw filesystems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="144"/>
+ <source>Sync all mounted filesystems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="145"/>
+ <source>Remount all readonly</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="146"/>
+ <source>Show all held locks</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="147"/>
+ <source>Show stack traces</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="148"/>
+ <source>Dump memory info</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="149"/>
+ <source>Dump registers and flags</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="150"/>
+ <source>Dump timers and clockevents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="151"/>
+ <source>Dump task list</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="152"/>
+ <source>Dump uninterruptible tasks</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="153"/>
+ <source>Dump ftrace buffer</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <location filename="../pvsprivinputd.cpp" line="66"/>
+ <source>Usage: %1 [--help|-h] [--daemon|-d] [--log=&lt;Logger&gt;|-l&lt;Logger&gt;]
+
+Options:
+ --help, -h Show this message
+ --daemon, -d Run in background
+ --log=&lt;Logger&gt;,
+ -l&lt;Logger&gt; Redirect all output to &lt;Logger&gt;
+ valid values are:
+ - any file name
+ - `syslog&apos; to redirect output to the system log
+ - `null&apos; to discard output (default)
+ (without quotes)
+
+Signals:
+ SIGINT, SIGTERM (or press Ctrl+C when run in foreground)
+ Quit
+ SIGHUP Reload configuration and cached user data
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/src/input/i18n/pvsinput_pl_PL.ts b/src/input/i18n/pvsinput_pl_PL.ts
new file mode 100644
index 0000000..11365c0
--- /dev/null
+++ b/src/input/i18n/pvsinput_pl_PL.ts
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="pl_PL">
+<context>
+ <name>InputEvent</name>
+ <message>
+ <location filename="../inputEvent.cpp" line="131"/>
+ <source>Say Hello</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="132"/>
+ <source>Reboot</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="133"/>
+ <source>Kill X Server</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="134"/>
+ <source>Reboot immediately</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="135"/>
+ <source>Power off immediately</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="136"/>
+ <source>Crash System</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="137"/>
+ <source>Turn off raw keyboard mode</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="138"/>
+ <source>Send SIGTERM to all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="139"/>
+ <source>Send SIGKILL to all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="140"/>
+ <source>Kill all on this terminal</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="141"/>
+ <source>Activate OOM killer</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="142"/>
+ <source>Make real-time tasks niceable</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="143"/>
+ <source>Force-thaw filesystems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="144"/>
+ <source>Sync all mounted filesystems</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="145"/>
+ <source>Remount all readonly</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="146"/>
+ <source>Show all held locks</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="147"/>
+ <source>Show stack traces</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="148"/>
+ <source>Dump memory info</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="149"/>
+ <source>Dump registers and flags</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="150"/>
+ <source>Dump timers and clockevents</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="151"/>
+ <source>Dump task list</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="152"/>
+ <source>Dump uninterruptible tasks</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../inputEvent.cpp" line="153"/>
+ <source>Dump ftrace buffer</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <location filename="../pvsprivinputd.cpp" line="66"/>
+ <source>Usage: %1 [--help|-h] [--daemon|-d] [--log=&lt;Logger&gt;|-l&lt;Logger&gt;]
+
+Options:
+ --help, -h Show this message
+ --daemon, -d Run in background
+ --log=&lt;Logger&gt;,
+ -l&lt;Logger&gt; Redirect all output to &lt;Logger&gt;
+ valid values are:
+ - any file name
+ - `syslog&apos; to redirect output to the system log
+ - `null&apos; to discard output (default)
+ (without quotes)
+
+Signals:
+ SIGINT, SIGTERM (or press Ctrl+C when run in foreground)
+ Quit
+ SIGHUP Reload configuration and cached user data
+</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
diff --git a/src/input/incompatibleHandler.h b/src/input/incompatibleHandler.h
new file mode 100644
index 0000000..5a92806
--- /dev/null
+++ b/src/input/incompatibleHandler.h
@@ -0,0 +1,37 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # incompatibleHandler.h:
+ # - A handler that is not compatible with any system.
+ # The presence of this file does no harm whatsoever,
+ # since there will never be any references generated to the class
+ # it defines, and allows us to test the claim that
+ # the Require<...> policy does a better job than the preprocessor.
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef INCOMPATIBLEHANDLERTYPE_H_
+#define INCOMPATIBLEHANDLERTYPE_H_
+
+#include "inputEventHandler.h"
+
+namespace incompatible {
+ struct Incompatible;
+}
+
+class IncompatibleHandler : public InputEventHandler<
+ input_policy::Require<incompatible::Incompatible> >
+{
+ void doHandle(InputEvent const&, InputEventContext const*);
+};
+
+
+#endif /* INCOMPATIBLEHANDLERTYPE_H_ */
diff --git a/src/input/inputEvent.cpp b/src/input/inputEvent.cpp
new file mode 100644
index 0000000..cff1ac8
--- /dev/null
+++ b/src/input/inputEvent.cpp
@@ -0,0 +1,155 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # inputEvent.h:
+ # - Definition of an input event - utility routines
+ # --------------------------------------------------------------------------
+ */
+
+#include <QBuffer>
+#include <QByteArray>
+#include <QCoreApplication>
+#include <QDataStream>
+#include <QKeyEvent>
+#include <QMouseEvent>
+#include <QString>
+#include "inputEvent.h"
+#include <src/util/consoleLogger.h>
+
+// We implement operators to serialize and load an event:
+/**
+ * Serialize an input event to a \ref QDataStream.
+ */
+QDataStream& operator <<(QDataStream& ostrm, InputEvent const& evt)
+{
+ ostrm << evt._type << evt._code << evt._value;
+ return ostrm;
+}
+
+/**
+ * Load an input event from a \ref QDataStream.
+ */
+QDataStream& operator >>(QDataStream& istrm, InputEvent& evt)
+{
+ istrm >> evt._type >> evt._code >> evt._value;
+ return istrm;
+}
+
+/**
+ * Produce a string-encodeable representation of an input event.
+ * This consists of a base64-encoded binary representation as
+ * generated by \ref{operator<<(QDataStream&, InputEvent const&)}.
+ */
+void eventToString(InputEvent const& evt, QString& str)
+{
+ QByteArray ba;
+ QBuffer buf(&ba);
+ buf.open(QIODevice::WriteOnly);
+ QDataStream out(&buf);
+ out << evt;
+ str = QString::fromAscii(ba.toBase64());
+}
+
+/**
+ * Decode the string representation of an input-event produced by
+ * \ref eventToString.
+ */
+bool eventFromString(QString const& str, InputEvent& evt)
+{
+ // TODO This does not do proper error checking. Only use from trusted sources!
+ QByteArray ba = QByteArray::fromBase64(str.toAscii());
+ QBuffer buf(&ba);
+ buf.open(QIODevice::ReadOnly);
+ QDataStream in(&buf);
+ in >> evt;
+ return true;
+}
+
+quint16 InputEvent::mouseButtonsFromQt(int b)
+{
+ quint16 ret = 0;
+ if(b & Qt::LeftButton)
+ {
+ ret |= EB_LEFT;
+ }
+ if(b & Qt::RightButton)
+ {
+ ret |= EB_RIGHT;
+ }
+ if(b & Qt::MidButton)
+ {
+ ret |= EB_MIDDLE;
+ }
+ return ret;
+}
+
+InputEvent InputEvent::mousePressRelease(int qt_button, int qt_buttons)
+{
+ quint16 button = mouseButtonsFromQt(qt_button);
+ quint16 buttons = mouseButtonsFromQt(qt_buttons);
+ quint16 code;
+
+ if(buttons & button)
+ {
+ code = EC_PRESS;
+ }
+ else
+ {
+ code = EC_RELEASE;
+ }
+
+ quint32 value = ((quint32)button << 16) | buttons;
+ return InputEvent(ET_BUTTON, code, value);
+}
+
+InputEvent InputEvent::keyboardPress(int key, int mods)
+{
+ quint32 value = key | mods;
+ return InputEvent(ET_KEY, EC_PRESS, value);
+}
+
+InputEvent InputEvent::keyboardRelease(int key, int mods)
+{
+ quint32 value = key | mods;
+ return InputEvent(ET_KEY, EC_RELEASE, value);
+}
+
+#define describe(list, description, type, code, value) \
+ list.append(SpecialInputEventDescription(InputEvent::type, InputEvent::code, value, description))
+
+QList<SpecialInputEventDescription> SpecialInputEventDescription::describeSpecialEvents()
+{
+ QList<SpecialInputEventDescription> list;
+ describe(list, InputEvent::tr("Say Hello"), ET_SPECIAL, EC_SAY_HELLO, 0);
+ describe(list, InputEvent::tr("Reboot"), ET_SPECIAL, EC_REBOOT, 0);
+ describe(list, InputEvent::tr("Kill X Server"), ET_SPECIAL, EC_KILL_X, 0);
+ describe(list, InputEvent::tr("Reboot immediately"), ET_SPECIAL, EC_SYSRQ, 'b');
+ describe(list, InputEvent::tr("Power off immediately"), ET_SPECIAL, EC_SYSRQ, 'o');
+ describe(list, InputEvent::tr("Crash System"), ET_SPECIAL, EC_SYSRQ, 'c');
+ describe(list, InputEvent::tr("Turn off raw keyboard mode"), ET_SPECIAL, EC_SYSRQ, 'r');
+ describe(list, InputEvent::tr("Send SIGTERM to all"), ET_SPECIAL, EC_SYSRQ, 'e');
+ describe(list, InputEvent::tr("Send SIGKILL to all"), ET_SPECIAL, EC_SYSRQ, 'i');
+ describe(list, InputEvent::tr("Kill all on this terminal"), ET_SPECIAL, EC_SYSRQ, 'k');
+ describe(list, InputEvent::tr("Activate OOM killer"), ET_SPECIAL, EC_SYSRQ, 'f');
+ describe(list, InputEvent::tr("Make real-time tasks niceable"), ET_SPECIAL, EC_SYSRQ, 'n');
+ describe(list, InputEvent::tr("Force-thaw filesystems"), ET_SPECIAL, EC_SYSRQ, 'j');
+ describe(list, InputEvent::tr("Sync all mounted filesystems"), ET_SPECIAL, EC_SYSRQ, 's');
+ describe(list, InputEvent::tr("Remount all readonly"), ET_SPECIAL, EC_SYSRQ, 'u');
+ describe(list, InputEvent::tr("Show all held locks"), ET_SPECIAL, EC_SYSRQ, 'd');
+ describe(list, InputEvent::tr("Show stack traces"), ET_SPECIAL, EC_SYSRQ, 'l');
+ describe(list, InputEvent::tr("Dump memory info"), ET_SPECIAL, EC_SYSRQ, 'm');
+ describe(list, InputEvent::tr("Dump registers and flags"), ET_SPECIAL, EC_SYSRQ, 'p');
+ describe(list, InputEvent::tr("Dump timers and clockevents"), ET_SPECIAL, EC_SYSRQ, 'q');
+ describe(list, InputEvent::tr("Dump task list"), ET_SPECIAL, EC_SYSRQ, 't');
+ describe(list, InputEvent::tr("Dump uninterruptible tasks"), ET_SPECIAL, EC_SYSRQ, 'w');
+ describe(list, InputEvent::tr("Dump ftrace buffer"), ET_SPECIAL, EC_SYSRQ, 'z');
+ return list;
+}
diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h
new file mode 100644
index 0000000..4e132eb
--- /dev/null
+++ b/src/input/inputEvent.h
@@ -0,0 +1,398 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # inputEvent.h:
+ # - Definition of an input event
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef INPUTEVENT_H_
+#define INPUTEVENT_H_
+
+#include <cassert>
+#include <QCoreApplication> // for translation
+#include <QString>
+
+struct QDataStream;
+struct QString;
+struct QMouseEvent;
+struct QKeyEvent;
+
+/**
+ * The inputEvent class represents a single input event.
+ * An input event is any of:
+ * - Pressing or releasing a keyboard key,
+ * - Moving the mouse pointer,
+ * - Pressing or releasing a mouse button,
+ * - Special system events like "reboot".
+ *
+ * Events are described by the \ref type(), \ref code()
+ * and \ref value(). Possible values for \ref type() are given by
+ * the \c ET_* constants, and for \ref code() by the \c EC_* constants.
+ */
+class InputEvent
+{
+private:
+ friend QDataStream& operator<<(QDataStream&, InputEvent const&);
+ friend QDataStream& operator>>(QDataStream&, InputEvent&);
+
+ friend void eventToString(InputEvent const& evt, QString& str);
+ friend bool eventFromString(QString const& str, InputEvent& evt);
+
+ quint16 _type;
+ quint16 _code;
+ quint32 _value;
+
+ // InputEvents are immutable. Prohibit assignment:
+ InputEvent& operator=(InputEvent const&); // There intentionally is no implementation.
+
+public:
+ InputEvent(quint16 type, quint16 code, quint32 value = 0) : _type(type), _code(code), _value(value)
+ {
+ }
+
+ InputEvent(InputEvent const& other) : _type(other._type), _code(other._code), _value(other._value)
+ {
+ }
+
+ InputEvent()
+ {
+ }
+
+ /** \name Factory Functions */
+ /* @{ */
+
+ /**
+ * Generates an event for a mouse button press or release.
+ * \param button The button that caused this event, as defined by \ref Qt::MouseButton.
+ * \param buttons The buttons that were pressed at the moment the event was generated, as defined by \ref Qt::MouseButtons.
+ * If the event is a button press, this includes the pressed button. If it is a button release,
+ * it does not include the pressed button.
+ */
+ static InputEvent mousePressRelease(int button, int buttons);
+
+ /**
+ * Generates an event for a keyboard press.
+ * \param key The key code that generated this event, as defined by \ref Qt::Key.
+ * \param mods The modificator keys that were pressed at the moment the event was generated,
+ * as defined by \ref Qt::KeyboardModifiers.
+ */
+ static InputEvent keyboardPress(int key, int mods);
+
+ /**
+ * Generates an event for a keyboard release.
+ * \param key The key code that generated this event, as defined by \ref Qt::Key.
+ * \param mods The modificator keys that were pressed at the moment the event was generated,
+ * as defined by \ref Qt::KeyboardModifiers.
+ */
+ static InputEvent keyboardRelease(int key, int mods);
+
+ /**
+ * Generates an event for a mouse pointer movement.
+ * \param x,y X and Y coordinates of the mouse pointer.
+ */
+ static InputEvent mouseMotion(quint16 x, quint16 y)
+ {
+ return InputEvent(ET_POINTER, 0, ((quint32)x << 16) | y);
+ }
+
+ /* @} */
+
+ /** \name Event Types */
+ /* @{ */
+ static const quint16 ET_KEY = 0; /**< The event is related to the keyboard */
+ static const quint16 ET_BUTTON = 1; /**< The event is related to a mouse button */
+ static const quint16 ET_POINTER = 2; /**< The event is related to the mouse pointer */
+ static const quint16 ET_SPECIAL = 3; /**< The event is a special system event */
+ /* @} */
+
+ /** \name Event Codes */
+ /* @{ */
+ static const quint16 EC_PRESS = 0; /**< The event is a press (keyboard or mouse button) */
+ static const quint16 EC_RELEASE = 1; /**< The event is a release (keyboard or mouse button) */
+ static const quint16 EC_REBOOT = 2; /**< The event is a request to reboot (special system event) */
+ static const quint16 EC_SYSRQ = 3; /**< The event is a request to perform a Magic-SysRq function (special system event) */
+ static const quint16 EC_KILL_X = 4; /**< The event is a request to kill the X Server (special system event) */
+ static const quint16 EC_SAY_HELLO = 5; /**< The event is a request to write a line to the log file (special system event) */
+ /* @} */
+
+ /** \name Mouse Button Flags */
+ /* @{ */
+ static const quint16 EB_LEFT = 1; /**< The left mouse button */
+ static const quint16 EB_MIDDLE = 2; /**< The middle mouse button */
+ static const quint16 EB_RIGHT = 4; /**< The right mouse button */
+ /* @} */
+
+ static const quint32 MODIFIER_MASK =
+ 0x7e000000;
+
+ /** \name Event Decoding Functions */
+ /* @{ */
+
+ /**
+ * Return the event type, as defined by the \c ET_* constants.
+ */
+ quint16 type() const
+ {
+ return _type;
+ }
+
+ /**
+ * Return the event code, as defined by the \c EC_* constants.
+ */
+ quint16 code() const
+ {
+ return _code;
+ }
+
+ /**
+ * Return the value associated with the event. The interpretation
+ * differs according to event type and code:
+ * - If the event type is \c ET_KEY, the value specifies which
+ * key and modifiers were pressed.
+ * - If the event type is \c ET_BUTTON, the value specifies which
+ * buttons were pressed and which button generated the event.
+ * - If the event type is \c ET_POINTER, the value specifies the
+ * screen coordinates the mouse has moved to.
+ * - If the event type is \c ET_SPECIAL, the interpretation
+ * depends on the event code.
+ */
+ quint32 value() const
+ {
+ return _value;
+ }
+
+ /**
+ * True if the event is a keyboard event.
+ */
+ bool isKeyboard() const
+ {
+ return _type == ET_KEY;
+ }
+
+ /**
+ * True if the event is a mouse button event.
+ */
+ bool isButton() const
+ {
+ return _type == ET_BUTTON;
+ }
+
+ /**
+ * True if the event is a mouse pointer event.
+ */
+ bool isPointer() const
+ {
+ return _type == ET_POINTER;
+ }
+
+ /**
+ * True if the event is a special system event.
+ */
+ bool isSpecial() const
+ {
+ return _type == ET_SPECIAL;
+ }
+
+ /**
+ * True if the event is a keyboard or mouse button press event.
+ */
+ bool isPress() const
+ {
+ return _code == EC_PRESS;
+ }
+
+ /**
+ * True if the event is a keyboard or mouse button release event.
+ */
+ bool isRelease() const
+ {
+ return _code == EC_RELEASE;
+ }
+
+ /**
+ * The mouse button that generated this event.
+ * \return one of the \c EB_* constants.
+ */
+ quint16 pressedButton() const
+ {
+ assert(_type == ET_BUTTON);
+ return (_value >> 16);
+ }
+
+ /**
+ * The mouse buttons that were pressed at the moment the
+ * event was generated.
+ * \return a bitwise or of \c EB_* constants.
+ */
+ quint16 heldButtons() const
+ {
+ assert(_type == ET_BUTTON);
+ return (_value & 0xffff);
+ }
+
+ /**
+ * The X coordinate the pointer was moved to.
+ */
+ quint16 xCoord() const
+ {
+ assert(_type == ET_POINTER);
+ return (_value >> 16);
+ }
+
+ /**
+ * The Y coordinate the pointer was moved to.
+ */
+ quint16 yCoord() const
+ {
+ assert(_type == ET_POINTER);
+ return (_value & 0xffff);
+ }
+
+ /**
+ * The key that generated the event, as defined by \ref Qt::Key.
+ */
+ quint32 qtKeysym() const
+ {
+ return _value & ~MODIFIER_MASK;
+ }
+
+ /**
+ * The modifier keys that were pressed at the moment the event was generated,
+ * as defined by \ref Qt::KeyboardModifiers.
+ */
+ quint32 qtModifiers() const
+ {
+ return _value & MODIFIER_MASK;
+ }
+ /* @} */
+
+
+ /** \name Conversion Functions */
+ /* @{ */
+
+ /**
+ * Converts mouse buttons from the bit flags defined by \ref Qt::MouseButton
+ * to their internal representation as defined in \ref "Mouse Button Flags".
+ * \returns A bitwise or of \c EB_* values.
+ */
+ static quint16 mouseButtonsFromQt(int b);
+
+ /**
+ * Converts an event type as given by the \c ET_* constants to
+ * a string.
+ */
+ static QString typeToString(quint16 type)
+ {
+ switch(type)
+ {
+ case ET_BUTTON:
+ return "BUTTON";
+ case ET_KEY:
+ return "KEY";
+ case ET_POINTER:
+ return "POINTER";
+ case ET_SPECIAL:
+ return "SPECIAL";
+ default:
+ return QString::number(type, 16);
+ }
+ }
+
+ /**
+ * Converts an event code as given by the \c EC_* constants to
+ * a string.
+ */
+ static QString codeToString(quint16 code)
+ {
+ switch(code)
+ {
+ case EC_PRESS:
+ return "PRESS";
+ case EC_RELEASE:
+ return "RELEASE";
+ case EC_SYSRQ:
+ return "SYSRQ";
+ case EC_REBOOT:
+ return "REBOOT";
+ case EC_KILL_X:
+ return "KILL_X";
+ default:
+ return QString::number(code, 16);
+ }
+ }
+
+ /**
+ * Convert the event to a human-readable representation.
+ */
+ QString toString() const
+ {
+ return QString("%1:%2:%3").arg(typeToString(_type)).arg(codeToString(_code)).arg(_value, 8, 16, QLatin1Char('0'));
+ }
+
+ /* @} */
+
+ // We want to enable InputEvent as a translation context, so we fake the tr method:
+ static QString tr(const char* string)
+ {
+ return QCoreApplication::translate("InputEvent", string);
+ }
+};
+
+/**
+ * The SpecialInputEventDescription class provides a human-readable
+ * name for special system events.
+ *
+ * To use the translations of these descriptions in your program,
+ * you need to link to the \c libpvsinput library and
+ * use the \ref USE_PVSINPUT_TRANSLATIONS macro in your
+ * \c main function.
+ */
+struct SpecialInputEventDescription
+{
+ /**
+ * Initialize an instance of the SpecialInputEventDescription class.
+ * This is only meant to be called from describeSpecialEvents().
+ * If you need to add more special event descriptions, do so from there.
+ */
+ SpecialInputEventDescription(quint16 type, quint16 code, quint32 value, QString const& description_)
+ : type(type), code(code), value(value), description(description_)
+ {
+ }
+
+ /** \name InputEvent fields
+ * \see InputEvent
+ */
+ /* @{ */
+ quint16 type;
+ quint16 code;
+ quint32 value;
+ /* @} */
+
+ QString description; /**< Human-readable description for a special input event. Can be translated via the
+ InputEvent::tr(char const*) method. */
+
+ /**
+ * Returns an \ref InputEvent corresponding to this description.
+ */
+ InputEvent toEvent() const
+ {
+ return InputEvent(type, code, value);
+ }
+
+ /**
+ * Returns a \ref QList of all known special system events with their human-readable
+ * description.
+ */
+ static QList<SpecialInputEventDescription> describeSpecialEvents();
+};
+
+#endif /* INPUTEVENT_H_ */
diff --git a/src/input/inputEventHandler.cpp b/src/input/inputEventHandler.cpp
new file mode 100644
index 0000000..5298aed
--- /dev/null
+++ b/src/input/inputEventHandler.cpp
@@ -0,0 +1,33 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # inputEventHandler.h:
+ # - Common definitions for input event handlers - implementation
+ # --------------------------------------------------------------------------
+ */
+
+#include "inputEventHandler.h"
+#include "pvsCheckPrivileges.h"
+
+InputEventHandlerBase::HandlerStatus InputEventHandlerBase::handle(InputEvent const& evt, InputEventContext const* ctx)
+{
+ if(!isApplicable(evt, ctx))
+ return HANDLER_NOT_APPLICABLE;
+ if(!allow(evt, ctx))
+ return HANDLER_NOT_ALLOWED;
+ doHandle(evt, ctx);
+ return HANDLER_MATCHED;
+}
+
+bool input_policy::AllowEverybody::allow(InputEventContext const*)
+{
+ return true;
+}
diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h
new file mode 100644
index 0000000..783640f
--- /dev/null
+++ b/src/input/inputEventHandler.h
@@ -0,0 +1,398 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # inputEventHandler.h:
+ # - Common definitions for input event handlers
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef INPUTEVENTHANDLER_H_
+#define INPUTEVENTHANDLER_H_
+
+#include <QtGlobal>
+#include <QtDebug>
+#include <QList>
+#include <QString>
+#include <QCoreApplication>
+#include <src/input/inputEvent.h>
+#include "detail/policyChain.h"
+#include "detail/systemTraits.h"
+
+/**
+ * For handling access control, this specifies who sent the input event.
+ * This only really makes sense in the privileged input handler chain.
+ */
+struct InputEventContext
+{
+ InputEventContext()
+ {
+ hasBeenDenied = false;
+ }
+
+ virtual pid_t senderPid() const = 0; /**< PID of the sending process */
+ virtual uid_t senderUid() const = 0; /**< UID of the sending process */
+ virtual gid_t senderGid() const = 0; /**< GID of the sending process */
+
+ /** Support the generation of meaningful log messages. */
+ mutable bool hasBeenDenied;
+};
+
+namespace input_policy
+{
+
+/////////////////////////////////////////////////////////////////////////
+// Policy:
+// Modifies the behaviour of an input handler class.
+//
+// There are several kinds of policy:
+// - Security Policy (When to allow a certain action)
+// - System Requirements (When to enable a certain handler)
+// - Applicability (When to consider a certain handler)
+//
+// Policies are tied together using the detail::PolicyChain class.
+/////////////////////////////////////////////////////////////////////////
+
+/**
+ * Security Policy.
+ * At the moment there are two security policies:
+ * -* If the user is on a local seat, allow. If the user is privileged,
+ * allow. Else deny.
+ * -* Allow everybody.
+ *
+ * Additional security policies can be added by following the example
+ * set by \ref AllowLocalOrPrivileged
+ *
+ * \param PolicyImpl The implementation class that security decisions
+ * should be delegated to.
+ * \see {AllowLocalOrPrivileged}
+ * \see {AllowEverybody}
+ */
+template<typename PolicyImpl>
+BEGIN_POLICY_CLASS(Security)
+{
+ bool allow(InputEventContext const* context)
+ {
+ return PolicyImpl::allow(context);
+ }
+}
+END_POLICY_CLASS
+
+/**
+ * Check the default security model.
+ */
+struct AllowLocalOrPrivileged
+{
+ static bool allow(InputEventContext const*);
+};
+
+/**
+ * Do not restrict execution.
+ */
+struct AllowEverybody
+{
+ static bool allow(InputEventContext const*);
+};
+
+/**
+ * Shorthand for unrestricted execution.
+ */
+typedef Security<AllowEverybody> Unprivileged;
+
+/**
+ * System Requirements.
+ *
+ * At the moment, this is trivial, as PVS only runs on Linux. But,
+ * as porting efforts are already underway, we include the necessary
+ * machinery anyway.
+ *
+ * \param Trait... a list of system traits that need to be
+ * present in order for the handler that this policy is applied to
+ * to run.
+ */
+#ifdef DOXYGEN_RUNNING
+template<typename Trait...>
+#else
+template<IMPLICIT_TYPE_LIST_PARAMS(Trait)>
+#endif
+BEGIN_POLICY_CLASS(Require)
+{
+ static const bool areSystemRequirementsFulfilled =
+ (NextPolicy::areSystemRequirementsFulfilled
+ && !NextPolicy::areSystemRequirementsVacuouslyFulfilled)
+ || detail::Matches<AllOf<IMPLICIT_TYPE_LIST_ARGS(Trait)>, detail::SystemTraits>::value;
+ static const bool areSystemRequirementsVacuouslyFulfilled = false;
+}
+END_POLICY_CLASS
+
+#ifndef DOXYGEN_RUNNING
+enum {
+ HANDLER_CODE_DONT_CARE = 0xffff,
+ HANDLER_VALUE_DONT_CARE = 0xffffffff
+};
+#endif
+
+/**
+ * Event selection.
+ *
+ * This policy makes the handler it is applied to applicable if the
+ * template parameters \c EventType, \c EventCode and \c EventValue
+ * match the corresponding fields of the incoming \ref InputEvent.
+ *
+ * Can be applied multiple times, and will be combined by logical
+ * OR.
+ *
+ * \param EventType Match the \ref InputEvent::type() field.
+ * \param EventCode (optional:) Match the \ref InputEvent::code() field.
+ * \param EventValue (optional:) Match the \ref InputEvent::value() field.
+ */
+template<unsigned short EventType,
+ unsigned short EventCode = HANDLER_CODE_DONT_CARE,
+ unsigned int EventValue = HANDLER_VALUE_DONT_CARE>
+BEGIN_POLICY_CLASS(Match)
+{
+ bool isApplicable(InputEvent const& evt)
+ {
+ if(evt.type() != EventType)
+ return NextPolicy::isApplicable(evt);
+ if(EventCode != HANDLER_CODE_DONT_CARE && evt.code() != EventCode)
+ return NextPolicy::isApplicable(evt);
+ if(EventValue != HANDLER_VALUE_DONT_CARE && evt.value() != EventValue)
+ return NextPolicy::isApplicable(evt);
+ return true;
+ }
+};
+END_POLICY_CLASS
+
+#ifndef DOXYGEN_RUNNING
+namespace detail
+{
+
+/////////////////////////////////////////////////////////////////////////
+// Base case: If no policies are given:
+/////////////////////////////////////////////////////////////////////////
+struct InputEventHandlerPolicyBase
+{
+ // The default security policy applies
+ typedef AllowLocalOrPrivileged DefaultSecurityPolicyImpl;
+
+ bool allow(InputEventContext const* context)
+ {
+ return DefaultSecurityPolicyImpl::allow(context);
+ }
+
+ // A handler that does not specify requirements works
+ // everywhere
+ static const bool areSystemRequirementsFulfilled = true;
+
+ // We need this to implement proper logical OR
+ static const bool areSystemRequirementsVacuouslyFulfilled = true;
+
+ // Generate an error when no match policy is given.
+ bool isApplicable(InputEvent const&)
+ {
+ return false;
+ }
+
+ // If any policy implementation needs an initialization hook:
+ // Don't forget to call NextPolicy::initialize() in your
+ // implementation!
+ void initialize()
+ {
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_RUNNING
+
+}
+
+/**
+ * Base class without template parameters to enable making a list of
+ * polymorphic event handlers.
+ *
+ * The actual handler class needs to provide \ref doHandle and can
+ * override \ref allow and \ref isApplicable.
+ *
+ * \note Do not derive from InputEventHandlerBase to implement
+ * new event handlers! Derive from InputEventHandler instead.
+ */
+class InputEventHandlerBase
+{
+public:
+ enum HandlerStatus
+ {
+ HANDLER_MATCHED, /**< The handler matched the input event and was executed. */
+ HANDLER_NOT_ALLOWED, /**< Execution of the handler was prevented by security policy. */
+ HANDLER_NOT_APPLICABLE /**< The handler did not match the input event. */
+ };
+
+ virtual void initialize() = 0;
+ HandlerStatus handle(InputEvent const& evt, InputEventContext const* context = 0);
+
+protected:
+ /**
+ * Check security preconditions for the execution of this handler.
+ * This is normally handled by the \ref input_policy::Security policy.
+ */
+ virtual bool allow(InputEvent const& event, InputEventContext const* context = 0) = 0;
+
+ /**
+ * Check if this handler can handle the incoming input event.
+ * This is normally handled by the \ref input_policy::Match policy.
+ */
+ virtual bool isApplicable(InputEvent const& event, InputEventContext const* context = 0) = 0;
+
+ /**
+ * Actually handle the incoming event.
+ * It is assumed that all preconditions have been checked and the handler
+ * has been initialized at the point where this method is called.
+ */
+ virtual void doHandle(InputEvent const& event, InputEventContext const* context = 0) = 0;
+};
+
+/**
+ * Base class for input event handlers.
+ */
+#ifdef DOXYGEN_RUNNING
+template<typename Policy...>
+#else
+template<POLICY_PARAMS>
+#endif
+class InputEventHandler : public InputEventHandlerBase
+{
+#ifndef DOXYGEN_RUNNING
+protected:
+ // instantiate our policy:
+ typedef USE_POLICY(input_policy::detail::InputEventHandlerPolicyBase) policy_type;
+ policy_type policy;
+#endif
+
+public:
+ void initialize()
+ {
+ policy.initialize();
+ }
+
+ /** Export this so the handler chain can decide whether to include this handler */
+ static const bool areSystemRequirementsFulfilled = policy_type::areSystemRequirementsFulfilled;
+
+protected:
+
+ bool allow(InputEvent const&, InputEventContext const* context = 0)
+ {
+ return policy.allow(context);
+ }
+
+ bool isApplicable(InputEvent const& event, InputEventContext const* = 0)
+ {
+ return policy.isApplicable(event);
+ }
+};
+
+/**
+ * Chain \ref InputEventHandler instances together.
+ * The chain is also responsible for the creation of instances.
+ *
+ * \see privilegedInputEventHandlerChain.cpp
+ * \see unprivilegedInputEventHandlerChain.cpp
+ */
+class InputEventHandlerChain
+{
+private:
+ QList<InputEventHandlerBase*> handlers;
+
+#ifndef DOXYGEN_RUNNING // Implementation detail
+ /////////////////////////////////////////////////////////////////////////
+ // We need to statically dispatch on a static member of HandlerType.
+ // Unfortunately, we cannot specialize member functions of a template.
+ // So, we need to make this a class with a static non-template member.
+ /////////////////////////////////////////////////////////////////////////
+ template<bool Compatible, typename HandlerType>
+ struct ConditionallyAppend
+ {
+ /////////////////////////////////////////////////////////////////////////
+ // This method will never be instantiated for handlers that are
+ // not Compatible, thus generating no reference to HandlerType
+ // and permitting compilation to proceed without
+ // tedious nested preprocessor conditionals.
+ /////////////////////////////////////////////////////////////////////////
+ static void doIt(InputEventHandlerChain* chain)
+ {
+ chain->handlers.append(new HandlerType);
+ }
+ };
+
+ template<typename HandlerType>
+ struct ConditionallyAppend<false, HandlerType>
+ {
+ static void doIt(InputEventHandlerChain*)
+ {
+ }
+ };
+#endif // DOXYGEN_RUNNING
+
+public:
+ /**
+ * Add an event handler to the chain.
+ *
+ * \param fake_parameter The parameter is only for
+ * compilers which cannot handle template member functions
+ * correctly.
+ * \return A reference to the receiver, for invocation chaining.
+ *
+ * \note Do not pass a value to this function. The function
+ * handles creation of an instance itself.
+ */
+ template<typename HandlerType>
+ InputEventHandlerChain& add(HandlerType const* fake_parameter = 0)
+ {
+ ConditionallyAppend<HandlerType::areSystemRequirementsFulfilled, HandlerType>::doIt(this);
+ return *this;
+ }
+
+ /**
+ * Call \ref InputEventHandlerBase::initialize() on all
+ * handlers in the chain.
+ */
+ void initialize()
+ {
+ QListIterator<InputEventHandlerBase*> i(handlers);
+ while(i.hasNext())
+ {
+ i.next()->initialize();
+ }
+ }
+
+ /**
+ * Handle an input event. All handlers in the chain are tried
+ * in the order they were added, until one handler's
+ * implementation of InputEventHandlerBase::handle() returns
+ * InputEventHandlerBase::HANDLER_MATCHED.
+ */
+ void handle(InputEvent const& event, InputEventContext const* context = 0)
+ {
+ QListIterator<InputEventHandlerBase*> i(handlers);
+ while(i.hasNext())
+ {
+ switch(i.next()->handle(event, context))
+ {
+ case InputEventHandlerBase::HANDLER_MATCHED:
+ return;
+ case InputEventHandlerBase::HANDLER_NOT_ALLOWED:
+ context->hasBeenDenied = true;
+ case InputEventHandlerBase::HANDLER_NOT_APPLICABLE:
+ continue;
+ }
+ }
+ }
+};
+
+#endif /* INPUTEVENTHANDLER_H_ */
diff --git a/src/input/inputEventNonQt.cpp b/src/input/inputEventNonQt.cpp
new file mode 100644
index 0000000..a7455fd
--- /dev/null
+++ b/src/input/inputEventNonQt.cpp
@@ -0,0 +1,17 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # inputEvent.h:
+ # - Input Event routines that need not be linked against Qt
+ # --------------------------------------------------------------------------
+ */
+
+
diff --git a/src/input/inputHandlerChains.h b/src/input/inputHandlerChains.h
new file mode 100644
index 0000000..773303b
--- /dev/null
+++ b/src/input/inputHandlerChains.h
@@ -0,0 +1,40 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # inputHandlerChains.h:
+ # - Definition of the input handler chains - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef INPUTHANDLERCHAIN_H_
+#define INPUTHANDLERCHAIN_H_
+
+#include "inputEventHandler.h"
+
+/** \defgroup iehc {Input Event Handler Chains} */
+/* @{ */
+
+/**
+ * Make an instance of InputEventHandlerChain that handles
+ * unprivileged input events, with a PrivilegedInputForwarder
+ * instance at the end.
+ */
+InputEventHandlerChain makeUnprivilegedInputEventHandlerChain();
+
+/**
+ * Make an instance of InputEventHandlerChain that handles
+ * privileged events.
+ */
+InputEventHandlerChain makePrivilegedInputEventHandlerChain();
+
+/* @} */
+
+#endif /* INPUTHANDLERCHAIN_H_ */
diff --git a/src/input/killX11Handler.cpp b/src/input/killX11Handler.cpp
new file mode 100644
index 0000000..8fa8c24
--- /dev/null
+++ b/src/input/killX11Handler.cpp
@@ -0,0 +1,89 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # killX11Handler.h
+ # - Kill the X11 Server - implementation
+ # --------------------------------------------------------------------------
+ */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <cerrno>
+#include <QDir>
+#include <QFileInfo>
+#include <QStringList>
+#include "pvsCheckPrivileges.h"
+#include "killX11Handler.h"
+
+using namespace std;
+
+void KillX11Handler::doHandle(InputEvent const&, InputEventContext const* ctx)
+{
+ // Find out which display device is used:
+ QString displayDevice = PVSCheckPrivileges::instance()->getX11DisplayDevice(ctx);
+ QString displayDeviceAbs = QFileInfo(displayDevice).canonicalFilePath();
+
+ if(displayDevice.isNull())
+ {
+ qWarning("Can not kill X server for %d,%d,%d: No Display Device", ctx->senderPid(), ctx->senderUid(), ctx->senderGid());
+ return;
+ }
+
+ QList<pid_t> pids;
+
+ // Find all processes that have it opened:
+ QDir proc("/proc");
+ QFileInfoList entries = proc.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
+ foreach(QFileInfo fi, entries)
+ {
+ // We are only interested in numerical ids:
+ bool ok;
+ pid_t pid = fi.fileName().toUInt(&ok);
+ if(!ok)
+ continue;
+
+ // We have a pid. Now check open files:
+ QDir fds(QString("/proc/%1/fd").arg(pid));
+ qDebug("Searching for X server in %s", fds.absolutePath().toLocal8Bit().constData());
+ QFileInfoList fdfiles = fds.entryInfoList(QDir::Files);
+ foreach(QFileInfo fdfile, fdfiles)
+ {
+ qDebug(" Looking for terminal in %s", fdfile.absoluteFilePath().toLocal8Bit().constData());
+ QFileInfo fdTarget(fdfile.readLink());
+ if(fdTarget.canonicalFilePath() == displayDeviceAbs)
+ {
+ qDebug(" ... found");
+ pids << pid;
+ }
+ }
+ }
+
+ // If everything is well, we have exactly one pid:
+ if(pids.size() != 1)
+ {
+ QStringList pidStrs;
+ foreach(pid_t pid, pids)
+ {
+ pidStrs << QString::number(pid);
+ }
+
+ qWarning("Display device %s is open by multiple or zero processes (%s). We don't know which is X. Aborting.",
+ displayDeviceAbs.toLocal8Bit().constData(),
+ pidStrs.join(", ").toLocal8Bit().constData());
+ return;
+ }
+
+ // We found the PID for the X server. Now kill it.
+ QString exe = QFileInfo(QString("/proc/%1/exe").arg(pids[0])).readLink();
+ qDebug("Killing X server, PID %d, exe name %s with SIGTERM", pids[0], exe.toLocal8Bit().constData());
+
+ kill(pids[0], SIGTERM);
+}
diff --git a/src/input/killX11Handler.h b/src/input/killX11Handler.h
new file mode 100644
index 0000000..6501d5d
--- /dev/null
+++ b/src/input/killX11Handler.h
@@ -0,0 +1,42 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # killX11Handler.h
+ # - Kill the X11 Server - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef KILLX11HANDLER_H_
+#define KILLX11HANDLER_H_
+
+#include <QCoreApplication>
+#include "inputEventHandler.h"
+
+/**
+ * Kills the X11 Server on Linux.
+ */
+class KillX11Handler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_SPECIAL, InputEvent::EC_KILL_X>,
+ input_policy::Require<input_policy::LinuxSystem> >
+{
+public:
+
+ /**
+ * Kills the X11 Server on Linux.
+ *
+ * The X11-Server is found by asking ConsoleKit for its controlling
+ * tty. The sole process that has an open file descriptor referencing it
+ * must be the X Server. It is then sent SIGTERM.
+ */
+ void doHandle(InputEvent const&, InputEventContext const*);
+};
+
+#endif /* KILLX11HANDLER_H_ */
diff --git a/src/input/logNonMatchingHandler.cpp b/src/input/logNonMatchingHandler.cpp
new file mode 100644
index 0000000..b0aa93a
--- /dev/null
+++ b/src/input/logNonMatchingHandler.cpp
@@ -0,0 +1,27 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/input/nonMatchingHandler.cpp:
+# - Log events that were not matched by another handler - implementation
+# -----------------------------------------------------------------------------
+*/
+
+#include "logNonMatchingHandler.h"
+#include <QtDebug>
+
+void LogNonMatchingHandler::doHandle(InputEvent const& event, InputEventContext const* context)
+{
+ // It's not really nonmatched if it has already been denied
+ if(!context || !context->hasBeenDenied)
+ {
+ qWarning("No matching handler found for event %s", event.toString().toLocal8Bit().constData());
+ }
+}
diff --git a/src/input/logNonMatchingHandler.h b/src/input/logNonMatchingHandler.h
new file mode 100644
index 0000000..ab95bce
--- /dev/null
+++ b/src/input/logNonMatchingHandler.h
@@ -0,0 +1,36 @@
+/*
+# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+#
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+#
+# If you have any feedback please consult http://openslx.org/feedback and
+# send your suggestions, praise, or complaints to feedback@openslx.org
+#
+# General information about OpenSLX can be found at http://openslx.org/
+# -----------------------------------------------------------------------------
+# src/input/nonMatchingHandler.h:
+# - Log events that were not matched by another handler - interface
+# -----------------------------------------------------------------------------
+*/
+
+#ifndef LOGNONMATCHINGHANDLER_H_
+#define LOGNONMATCHINGHANDLER_H_
+
+#include "inputEventHandler.h"
+
+/**
+ * Send a qWarning() for any InputEvent that does not have a matching handler.
+ */
+class LogNonMatchingHandler : public InputEventHandler<input_policy::Unprivileged>
+{
+public:
+ bool isApplicable(InputEvent const&, InputEventContext const*)
+ {
+ return true;
+ }
+
+ void doHandle(InputEvent const&, InputEventContext const*);
+};
+
+#endif /* LOGNONMATCHINGHANDLER_H_ */
diff --git a/src/input/magicSysRqHandler.cpp b/src/input/magicSysRqHandler.cpp
new file mode 100644
index 0000000..7c38216
--- /dev/null
+++ b/src/input/magicSysRqHandler.cpp
@@ -0,0 +1,28 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # inputEventHandler.h:
+ # - Common definitions for input event handlers
+ # --------------------------------------------------------------------------
+ */
+
+#include <QFile>
+#include "magicSysRqHandler.h"
+
+void MagicSysRqHandler::doHandle(InputEvent const& evt, InputEventContext const*)
+{
+ QFile trigger("/proc/sysrq-trigger");
+ trigger.open(QIODevice::WriteOnly);
+ char c = (char)(evt.value() & 0xff);
+ trigger.write(&c, 1);
+ trigger.flush();
+ trigger.close();
+}
diff --git a/src/input/magicSysRqHandler.h b/src/input/magicSysRqHandler.h
new file mode 100644
index 0000000..5afe259
--- /dev/null
+++ b/src/input/magicSysRqHandler.h
@@ -0,0 +1,38 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # magicSysRqHandler.h
+ # - Trigger Magic-SysRq functions - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef MAGICSYSRQHANDLER_H_
+#define MAGICSYSRQHANDLER_H_
+
+#include "inputEventHandler.h"
+
+/**
+ * Emulate the magic SysRq-Key on Linux.
+ */
+class MagicSysRqHandler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ>,
+ input_policy::Require<input_policy::LinuxSystem> >
+{
+public:
+
+ /**
+ * Send the least significant byte of \c evt's InputEvent::value()
+ * to the magic \c /proc/sysrq-trigger file.
+ */
+ void doHandle(InputEvent const& evt, InputEventContext const* ctx);
+};
+
+#endif /* MAGICSYSRQHANDLER_H_ */
diff --git a/src/input/org.openslx.pvs.input.policy b/src/input/org.openslx.pvs.input.policy
new file mode 100644
index 0000000..f4a73e6
--- /dev/null
+++ b/src/input/org.openslx.pvs.input.policy
@@ -0,0 +1,18 @@
+<?xml version="1.0" ?>
+<!DOCTYPE policyconfig PUBLIC
+ "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<policyconfig>
+ <vendor>The OpenSLX project</vendor>
+ <vendor_url>http://lab.openslx.org/pvs</vendor_url>
+
+ <action id="org.openslx.pvs.privilegedinput">
+ <description>Use privileged input actions in PVS</description>
+ <message>Authentication is required to let PVS use privileged input actions</message>
+ <defaults>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ <allow_any>auth_admin_keep</allow_any>
+ </defaults>
+ </action>
+</policyconfig>
diff --git a/src/input/privilegedHandlerForwarder.cpp b/src/input/privilegedHandlerForwarder.cpp
new file mode 100644
index 0000000..17c4ab1
--- /dev/null
+++ b/src/input/privilegedHandlerForwarder.cpp
@@ -0,0 +1,82 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # inputHandlerChain.cpp:
+ # - Forward privileged input events to a special handler process - implementation
+ # --------------------------------------------------------------------------
+ */
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <cassert>
+#include <cerrno>
+#include <cstring>
+#include <string>
+#include <QSettings>
+#include <QtDebug>
+#include "pvsPrivInputSocket.h"
+#include "privilegedHandlerForwarder.h"
+
+using namespace std;
+
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX 108 /* according to unix(7) */
+#endif
+
+void PrivilegedHandlerForwarder::initialize()
+{
+ QSettings settings(QSettings::NativeFormat, QSettings::SystemScope, "openslx", "pvsinputd");
+
+ QString defaultPath = "/tmp/pvsprivinputd.sock";
+ QByteArray socketPath = settings.value("socketpath", defaultPath).toString().toLocal8Bit();
+
+ _socket = pvsPrivInputMakeClientSocket();
+ if(_socket < 0)
+ {
+ return;
+ }
+}
+
+void PrivilegedHandlerForwarder::doHandle(InputEvent const& evt, InputEventContext const*)
+{
+ qDebug("Trying to handle %s in PrivilegedHandlerForwarder", evt.toString().toLocal8Bit().constData());
+ if(_socket < 0)
+ {
+ initialize();
+ }
+
+ QByteArray data;
+ QDataStream strm(&data, QIODevice::WriteOnly);
+ strm.setByteOrder(QDataStream::BigEndian);
+ strm << evt;
+
+ assert(data.size() == 8);
+
+ int delta = 0;
+ int count = 0;
+ do {
+ delta = write(_socket, data.constData(), data.size());
+ if(delta < 0)
+ {
+ qWarning("Error while communicating with pvsprivinputd: %s", strerror(errno));
+ close(_socket);
+
+ // Try again:
+ initialize();
+ }
+ else if(delta != 8)
+ {
+ // This should normally not happen.
+ qWarning("Could not send a complete packet. Only %d bytes sent", delta);
+ }
+ count++;
+ } while(delta != 8 && count < 3);
+}
diff --git a/src/input/privilegedHandlerForwarder.h b/src/input/privilegedHandlerForwarder.h
new file mode 100644
index 0000000..ea3326a
--- /dev/null
+++ b/src/input/privilegedHandlerForwarder.h
@@ -0,0 +1,47 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # inputHandlerChain.h:
+ # - Forward privileged input events to a special handler process.
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef PRIVILEGEDHANDLERFORWARDER_H_
+#define PRIVILEGEDHANDLERFORWARDER_H_
+
+#include "inputEventHandler.h"
+
+/**
+ * Forward the incoming InputEvent to \c pvsprivinputd.
+ */
+class PrivilegedHandlerForwarder : public InputEventHandler<
+ input_policy::Require<input_policy::UnixLike>,
+ input_policy::Unprivileged>
+{
+public:
+
+ /**
+ * Forward \c evt to \c pvsprivinputd, taking care that
+ * the security context is correctly sent.
+ */
+ void doHandle(InputEvent const& evt, InputEventContext const* = 0);
+
+ /**
+ * Read the address of \c pvsprivinputd's listening socket
+ * from its configuration and connect to it.
+ */
+ void initialize();
+
+private:
+ int _socket;
+};
+
+#endif /* PRIVILEGEDHANDLERFORWARDER_H_ */
diff --git a/src/input/privilegedInputHandlerChain.cpp b/src/input/privilegedInputHandlerChain.cpp
new file mode 100644
index 0000000..c1e8629
--- /dev/null
+++ b/src/input/privilegedInputHandlerChain.cpp
@@ -0,0 +1,32 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # privilegedInputHandlerChain.cpp
+ # - Definition of the input handler chains - implementation for privileged
+ # chain
+ # --------------------------------------------------------------------------
+ */
+
+#include "rebootSystemHandler.h"
+#include "sayHelloHandler.h"
+#include "killX11Handler.h"
+#include "magicSysRqHandler.h"
+#include "inputHandlerChains.h"
+#include "logNonMatchingHandler.h"
+
+InputEventHandlerChain makePrivilegedInputEventHandlerChain()
+{
+ return InputEventHandlerChain().add<RebootLinuxSystemHandler>()
+ .add<SayHelloHandler>()
+ .add<KillX11Handler>()
+ .add<MagicSysRqHandler>()
+ .add<LogNonMatchingHandler>();
+}
diff --git a/src/input/pvsCheckPrivileges.cpp b/src/input/pvsCheckPrivileges.cpp
new file mode 100644
index 0000000..2026c0a
--- /dev/null
+++ b/src/input/pvsCheckPrivileges.cpp
@@ -0,0 +1,550 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsCheckPrivileges.cpp:
+ # - A small program that checks whether or not it is called from
+ # a physical seat and conditionally executes the pvs input daemon.
+ # Additional security-relevant conditions should be checked here.
+ #
+ # The program is called with exactly one parameter, specifying the
+ # number of the file descriptor which is to be passed to its child.
+ # --------------------------------------------------------------------------
+ */
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <iostream>
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>
+#include <QCoreApplication>
+#include <QDir>
+#include <QFileInfo>
+#include <QFileSystemWatcher>
+#include <QSettings>
+#include <QTimer>
+#include <QtDBus/QDBusArgument>
+#include <QtDBus/QDBusConnection>
+#include <QtDBus/QDBusInterface>
+#include <QtDBus/QDBusMetaType>
+#include <QtDBus/QDBusReply>
+#include <QtGlobal>
+#include <QDebug>
+#include <QUuid>
+#include "pvsPrivInputSocket.h"
+#include "pvsCheckPrivileges.h"
+
+using namespace std;
+
+#define TIMEOUT_VALUE 10000 /* Wait for max. 10 seconds */
+
+// We need these classes for PolicyKit access:
+struct PolKitSubject {
+ QString subject_kind;
+ QMap<QString, QVariant> subject_details;
+};
+Q_DECLARE_METATYPE(PolKitSubject);
+
+QDBusArgument& operator<<(QDBusArgument& arg, PolKitSubject const& subj)
+{
+ arg.beginStructure();
+ arg << subj.subject_kind << subj.subject_details;
+ arg.endStructure();
+ return arg;
+}
+
+QDBusArgument const& operator>>(QDBusArgument const& arg, PolKitSubject& subj)
+{
+ arg.beginStructure();
+ arg >> subj.subject_kind >> subj.subject_details;
+ arg.endStructure();
+ return arg;
+}
+
+struct PolKitAuthReply {
+ bool isAuthorized;
+ bool isChallenge;
+ QMap<QString, QString> details;
+};
+Q_DECLARE_METATYPE(PolKitAuthReply);
+
+QDBusArgument& operator<<(QDBusArgument& arg, PolKitAuthReply const& reply)
+{
+ arg.beginStructure();
+ arg << reply.isAuthorized << reply.isChallenge << reply.details;
+ arg.endStructure();
+ return arg;
+}
+
+QDBusArgument const& operator>>(QDBusArgument const& arg, PolKitAuthReply& reply)
+{
+ arg.beginStructure();
+ arg >> reply.isAuthorized >> reply.isChallenge >> reply.details;
+ arg.endStructure();
+ return arg;
+}
+
+// We need to pass QMap<QString, QString> to QVariant:
+typedef QMap<QString, QString> QStringStringMap;
+Q_DECLARE_METATYPE(QStringStringMap)
+
+PVSCheckPrivileges* PVSCheckPrivileges::instance()
+{
+ static PVSCheckPrivileges* static_instance = 0;
+ if(!static_instance)
+ {
+ static_instance = new PVSCheckPrivileges();
+ }
+ return static_instance;
+}
+
+void PVSCheckPrivileges::deleteInstance()
+{
+ delete instance();
+}
+
+PVSCheckPrivileges::PVSCheckPrivileges(QObject* parent)
+ : QObject(parent)
+{
+ // initialise our cache:
+ updateCachedUserDatabase();
+ rereadConfiguration();
+
+ // and make it update itself:
+ QStringList paths;
+ paths << "/etc/passwd" << "/etc/group" << pvsPrivInputGetSettingsPath();
+ _watcher = new QFileSystemWatcher(paths, this);
+ connect(_watcher, SIGNAL(fileChanged(QString const&)), this, SLOT(updateCachedUserDatabase()));
+ connect(_watcher, SIGNAL(fileChanged(QString const&)), this, SLOT(rereadConfiguration()));
+}
+
+PVSCheckPrivileges::~PVSCheckPrivileges()
+{
+}
+
+QString PVSCheckPrivileges::getSessionReference(CachedInputContext const& sender)
+{
+ if(!sender.isValid())
+ {
+ return QString();
+ }
+
+ QString sessionReference = _savedConsoleKitSession.value(sender, QString());
+ if(sessionReference.isNull())
+ {
+ QDBusConnection conn = QDBusConnection::systemBus();
+ // Find the name of the current session:
+ QDBusInterface manager("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", "org.freedesktop.ConsoleKit.Manager", conn);
+ QDBusReply<QDBusObjectPath> replyGetSession = manager.call(QDBus::Block, "GetSessionForUnixProcess", (quint32)sender.pid);
+ if(!replyGetSession.isValid())
+ {
+ qWarning("Reply to GetSessionForUnixProcess is invalid: %s: %s", replyGetSession.error().name().toLocal8Bit().constData(), replyGetSession.error().message().toLocal8Bit().constData());
+ return QString();
+ }
+ _savedConsoleKitSession[sender] = sessionReference = replyGetSession.value().path();
+ }
+ return sessionReference;
+}
+
+PVSCheckPrivileges::SessionKind PVSCheckPrivileges::getSessionKind(CachedInputContext const& sender)
+{
+ if(!sender.isValid())
+ {
+ return SESSION_UNKNOWN;
+ }
+
+ // if the sender is root, we always suppose he works locally.
+ if(sender.uid == 0)
+ {
+ return SESSION_LOCAL;
+ }
+
+ QString sessionReference = getSessionReference(sender);
+ if(sessionReference.isNull())
+ {
+ return SESSION_LOOKUP_FAILURE;
+ }
+
+ QDBusConnection conn = QDBusConnection::systemBus();
+ QDBusInterface session("org.freedesktop.ConsoleKit", sessionReference, "org.freedesktop.ConsoleKit.Session", conn);
+ QDBusReply<bool> replyIsLocal = session.call(QDBus::Block, "IsLocal");
+
+ if(!replyIsLocal.isValid())
+ {
+ qWarning("Unable to find out whether the current session is local: %s: %s", replyIsLocal.error().name().toLocal8Bit().constData(), replyIsLocal.error().message().toLocal8Bit().constData());
+ return SESSION_LOOKUP_FAILURE;
+ }
+ return replyIsLocal.value() ? SESSION_LOCAL : SESSION_NONLOCAL;
+}
+
+PVSCheckPrivileges::UserPrivilege PVSCheckPrivileges::getUserPrivilege(CachedInputContext const& sender)
+{
+ // Always allow root:
+ if(sender.uid == 0)
+ {
+ return USER_PRIVILEGED;
+ }
+
+ // Or if the user is one of those enumerated in the privileged-users configuration value:
+ if(_privilegedUsers.contains(sender.uid))
+ {
+ return USER_PRIVILEGED;
+ }
+
+ // Or if the user is a member of one of the groups enumerated in the privileged-groups configuration value:
+ foreach(gid_t gid, _privilegedGroups)
+ {
+ if(_userGroupMap.contains(sender.uid, gid))
+ {
+ return USER_PRIVILEGED;
+ }
+ }
+
+ // User is not trivially privileged, so try to check with PolicyKit.
+#ifdef HAVE_POLKIT // but only if it is present
+ // For PolKit, we need the start-time of the process.
+ // On Linux, we can get it from /proc:
+ QString procStat = QString("/proc/%1/stat").arg(sender.pid);
+ QFile procStatFile(procStat);
+ if(!procStatFile.exists())
+ {
+ qWarning("Could not look up any info on process %d, its %s file does not exist", sender.pid, procStat.toLocal8Bit().constData());
+ return USER_LOOKUP_FAILURE;
+ }
+ procStatFile.open(QIODevice::ReadOnly);
+ QByteArray procStatBytes = procStatFile.readAll();
+ qDebug() << "Read stat file: " << procStatBytes;
+ QString procStatLine = QString::fromLocal8Bit(procStatBytes.constData(), procStatBytes.length());
+ QStringList procStatFields = procStatLine.split(QRegExp("\\s+"));
+ qDebug() << "Found stat fields: " << procStatFields;
+ bool ok;
+ quint64 startTime = procStatFields[21].toULongLong(&ok);
+ if(!ok)
+ {
+ qWarning("Could not find out start time for process %d", (int)sender.pid);
+ return USER_LOOKUP_FAILURE;
+ }
+
+ // Okay, we got the startTime. Now ask PolicyKit:
+
+ QDBusConnection conn = QDBusConnection::systemBus();
+ QDBusInterface intf("org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority", "org.freedesktop.PolicyKit1.Authority", conn);
+ PolKitSubject subj;
+ subj.subject_kind = "unix-process";
+ subj.subject_details["pid"] = (quint32)sender.pid;
+ subj.subject_details["start-time"] = startTime;
+ QDBusReply<PolKitAuthReply> reply = intf.call(QDBus::Block,
+ QLatin1String("CheckAuthorization"),
+ QVariant::fromValue(subj),
+ "org.openslx.pvs.privilegedinput",
+ QVariant::fromValue(QMap<QString, QString>()) /* No details */,
+ (quint32)1 /* Allow Interaction */,
+ QUuid::createUuid().toString() /* Cancellation ID */);
+ if(!reply.isValid())
+ {
+ QDBusError err = reply.error();
+
+ qWarning("Reply to CheckAuthorization is invalid: %s: %s", err.name().toLocal8Bit().constData(), err.message().toLocal8Bit().constData());
+ return USER_LOOKUP_FAILURE;
+ }
+ return reply.value().isAuthorized ? USER_PRIVILEGED : USER_UNPRIVILEGED;
+#else
+ return USER_UNPRIVILEGED;
+#endif
+}
+
+QString PVSCheckPrivileges::getX11SessionName(CachedInputContext const& sender)
+{
+ QString sessionReference = getSessionReference(sender);
+ if(sessionReference.isNull())
+ {
+ return QString();
+ }
+
+ QDBusConnection conn = QDBusConnection::systemBus();
+ QDBusInterface intf("org.freedesktop.ConsoleKit", sessionReference, "org.freedesktop.ConsoleKit.Session", conn);
+ QDBusReply<QString> reply = intf.call(QDBus::Block, QLatin1String("GetX11Display"));
+ if(!reply.isValid())
+ {
+ QDBusError err = reply.error();
+
+ qWarning("Reply to GetX11Display is invalid: %s: %s", err.name().toLocal8Bit().constData(), err.message().toLocal8Bit().constData());
+ return QString();
+ }
+
+ return reply.value();
+}
+
+QString PVSCheckPrivileges::getX11DisplayDevice(CachedInputContext const& sender)
+{
+ QString sessionReference = getSessionReference(sender);
+ if(sessionReference.isNull())
+ {
+ return QString();
+ }
+
+ QDBusConnection conn = QDBusConnection::systemBus();
+ QDBusInterface intf("org.freedesktop.ConsoleKit", sessionReference, "org.freedesktop.ConsoleKit.Session", conn);
+ QDBusReply<QString> reply = intf.call(QDBus::Block, QLatin1String("GetX11DisplayDevice"));
+ if(!reply.isValid())
+ {
+ QDBusError err = reply.error();
+
+ qWarning("Reply to GetX11DisplayDevice is invalid: %s: %s", err.name().toLocal8Bit().constData(), err.message().toLocal8Bit().constData());
+ return QString();
+ }
+
+ return reply.value();
+}
+
+bool PVSCheckPrivileges::require(SessionKind sessionKind, CachedInputContext const& sender)
+{
+ SessionKind cachedSessionKind;
+
+ if(sessionKind == SESSION_NONLOCAL)
+ {
+ // All sessions are at least non-local
+ return true;
+ }
+ else if(sessionKind == SESSION_LOCAL)
+ {
+ if((cachedSessionKind = _savedSessionKind.value(sender, SESSION_UNKNOWN)) == SESSION_UNKNOWN)
+ {
+ cachedSessionKind = getSessionKind(sender);
+ if(cachedSessionKind != SESSION_LOOKUP_FAILURE)
+ _savedSessionKind[sender] = cachedSessionKind;
+ qDebug("Got session kind: %s", toString(cachedSessionKind).toLocal8Bit().constData());
+ }
+
+ switch(cachedSessionKind)
+ {
+ case SESSION_LOOKUP_FAILURE:
+ case SESSION_UNKNOWN:
+ {
+ // If we cannot find out the correct session kind, look up what we should do in
+ // the configuration:
+ QSettings* config = pvsPrivInputGetSettings();
+ QVariant assumeLocal = config->value("assume-session-local", false);
+ if(!assumeLocal.canConvert(QVariant::Bool))
+ {
+ qWarning("There is an assume-session-local setting, but cannot convert it to boolean");
+ return false;
+ }
+ return assumeLocal.toBool();
+ }
+ case SESSION_LOCAL:
+ return true;
+ case SESSION_NONLOCAL:
+ return false;
+ default:
+ qWarning("Internal error: Undefined session kind %d", (int)cachedSessionKind);
+ return false;
+ }
+ }
+ else
+ {
+ qWarning("Internal error: It does not make sense to require an unknown session or undefined session kind %d", (int)sessionKind);
+ return false;
+ }
+}
+
+bool PVSCheckPrivileges::require(UserPrivilege userPrivilege, CachedInputContext const& sender)
+{
+ UserPrivilege cachedUserPrivilege;
+
+ if(userPrivilege == USER_UNPRIVILEGED)
+ {
+ // All users are unprivileged
+ return true;
+ }
+ else if(userPrivilege == USER_PRIVILEGED)
+ {
+ if((cachedUserPrivilege = _savedUserPrivilege.value(sender, USER_UNKNOWN)) == USER_UNKNOWN)
+ {
+ cachedUserPrivilege = getUserPrivilege(sender);
+ if(cachedUserPrivilege != USER_LOOKUP_FAILURE)
+ _savedUserPrivilege[sender] = cachedUserPrivilege;
+ qDebug("Got user privilege: %s", toString(cachedUserPrivilege).toLocal8Bit().constData());
+ }
+
+ switch(cachedUserPrivilege)
+ {
+ case USER_LOOKUP_FAILURE:
+ case USER_UNKNOWN:
+ {
+ // If we cannot find out the correct user privilege level, look up what we should do in
+ // the configuration:
+ QSettings* config = pvsPrivInputGetSettings();
+ QVariant assumePrivileged = config->value("assume-user-privileged", false);
+ if(!assumePrivileged.canConvert(QVariant::Bool))
+ {
+ qWarning("There is an assume-session-local setting, but cannot convert it to boolean");
+ return false;
+ }
+ return assumePrivileged.toBool();
+ }
+ case USER_PRIVILEGED:
+ return true;
+ case USER_UNPRIVILEGED:
+ return false;
+ default:
+ qWarning("Internal error: Found undefined user privilege level %d", (int)cachedUserPrivilege);
+ _savedUserPrivilege.remove(sender);
+ return false;
+ }
+ }
+ else
+ {
+ qWarning("Internal error: It does not make sense to require an unknown or undefined user privilege level %d", (int)userPrivilege);
+ return false;
+ }
+}
+
+bool PVSCheckPrivileges::require(SessionKind sessionKind,
+ UserPrivilege userPrivilege,
+ CachedInputContext const& sender)
+{
+ if(!require(sessionKind, sender))
+ return false;
+ if(!require(userPrivilege, sender))
+ return false;
+ return true;
+}
+
+uint qHash(CachedInputContext const& p)
+{
+ return qHash(qMakePair(p.pid, qMakePair(p.uid, p.gid)));
+}
+
+void PVSCheckPrivileges::updateCachedUserDatabase()
+{
+ QHash<QString, uid_t> userNames;
+
+ _userGroupMap.clear();
+
+ // assemble a list of known users and their primary groups:
+ setpwent(); // open the user database
+ struct passwd* userrec;
+ while((userrec = getpwent()))
+ {
+ userNames.insert(userrec->pw_name, userrec->pw_uid);
+ _userGroupMap.insert(userrec->pw_uid, userrec->pw_gid);
+ }
+ endpwent(); // close the database
+
+ // augment with secondary groups:
+ setgrent(); // open the group database
+ struct group* grouprec;
+ while((grouprec = getgrent()))
+ {
+ char** membername = grouprec->gr_mem;
+ while(*membername)
+ {
+ uid_t uid = userNames.value(*membername, (uid_t)-1);
+ if(uid != (uid_t)-1)
+ {
+ _userGroupMap.insert(uid, grouprec->gr_gid);
+ }
+ membername++;
+ }
+ }
+ endgrent();
+
+ // decisions may have changed, so clear the caches:
+ _savedUserPrivilege.clear();
+}
+
+void PVSCheckPrivileges::rereadConfiguration()
+{
+ QSettings* settings = pvsPrivInputReopenSettings();
+
+ _privilegedGroups.clear();
+ QVariant groupList = settings->value("privileged-groups");
+ if(groupList.isValid())
+ {
+ if(!groupList.canConvert(QVariant::StringList))
+ {
+ qWarning("There is a privileged-groups setting, but it cannot be converted to a list of strings.");
+ goto endGroupListScan;
+ }
+
+ QStringList groups = groupList.toStringList();
+ foreach(QString groupName, groups)
+ {
+ bool ok;
+ gid_t gid = groupName.toUInt(&ok);
+ if(ok)
+ {
+ _privilegedGroups.append(gid);
+ }
+ else
+ {
+ // lookup the name:
+ QByteArray groupNameBytes = groupName.toLocal8Bit();
+ struct group* group = getgrnam(groupNameBytes.constData());
+ if(group)
+ {
+ _privilegedGroups.append(group->gr_gid);
+ }
+ else
+ {
+ qWarning("privileged-groups setting contains %s which is neither a numeric GID "
+ "nor a valid group name. Skipping.",
+ groupNameBytes.constData());
+ }
+ }
+ }
+ }
+
+endGroupListScan:
+ _privilegedUsers.clear();
+ QVariant userList = settings->value("privileged-users");
+ if(userList.isValid())
+ {
+ if(!userList.canConvert(QVariant::StringList))
+ {
+ qWarning("There is a privileged-users setting, but it cannot be converted to a list of strings.");
+ goto endUserListScan;
+ }
+
+ QStringList users = userList.toStringList();
+ foreach(QString userName, users)
+ {
+ bool ok;
+ uid_t uid = userName.toUInt(&ok);
+ if(ok)
+ {
+ _privilegedUsers.append(uid);
+ }
+ else
+ {
+ // lookup the name:
+ QByteArray userNameBytes = userName.toLocal8Bit();
+ struct passwd* user = getpwnam(userNameBytes.constData());
+ if(user)
+ {
+ _privilegedUsers.append(user->pw_uid);
+ }
+ else
+ {
+ qWarning("privileged-users setting contains %s which is neither a numeric UID "
+ "nor a valid user name. Skipping.",
+ userNameBytes.constData());
+ }
+ }
+ }
+ }
+
+endUserListScan:
+ return;
+}
diff --git a/src/input/pvsCheckPrivileges.h b/src/input/pvsCheckPrivileges.h
new file mode 100644
index 0000000..37c4c04
--- /dev/null
+++ b/src/input/pvsCheckPrivileges.h
@@ -0,0 +1,196 @@
+/*
+ # Copyright (c) 2009,2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # -----------------------------------------------------------------------------
+ # src/net/pvsCheckPrivileges_linux.h
+ # - Linux implementation of privilege checking
+ # -----------------------------------------------------------------------------
+ */
+
+#ifndef PVSCHECKPRIVILEGES_H_
+#define PVSCHECKPRIVILEGES_H_
+
+#include <sys/types.h>
+#include <QObject>
+#include <QString>
+#include <QList>
+#include <QMultiMap>
+#include <QHash>
+#include "inputEventHandler.h"
+
+/**
+ * Store the information in an InputEventContext as a plain old datatype.
+ */
+struct CachedInputContext
+{
+ CachedInputContext(InputEventContext const* source)
+ {
+ if(source)
+ {
+ pid = source->senderPid();
+ uid = source->senderUid();
+ gid = source->senderGid();
+ }
+ else
+ {
+ pid = (pid_t)-1;
+ uid = (uid_t)-1;
+ gid = (gid_t)-1;
+ }
+ }
+
+ CachedInputContext()
+ {
+ pid = (pid_t)-1;
+ uid = (uid_t)-1;
+ gid = (gid_t)-1;
+ }
+
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+
+ bool isValid() const
+ {
+ return (pid != (pid_t)-1) && (uid != (uid_t)-1) && (gid != (gid_t)-1);
+ }
+
+ bool operator==(CachedInputContext const& other) const
+ {
+ return (other.pid == pid) && (other.uid == uid) && (other.gid == gid);
+ }
+};
+uint qHash(CachedInputContext const& p);
+
+class QFileSystemWatcher;
+
+/**
+ * Check user privileges and handle communications with ConsoleKit and PolicyKit.
+ * This is a singleton class.
+ */
+class PVSCheckPrivileges : public QObject
+{
+ Q_OBJECT
+public:
+ /**
+ * SessionKind distinguishes between local and remote users.
+ */
+ typedef enum {
+ SESSION_LOCAL, /**< User is local */
+ SESSION_NONLOCAL, /**< User is remote */
+ SESSION_LOOKUP_FAILURE, /**< Failure to look up whether the user is local or remote */
+ SESSION_UNKNOWN /**< User session kind not (yet) known */
+ } SessionKind;
+
+ /**
+ * UserPrivilege distinguishes between privileged and unprivileged users.
+ */
+ typedef enum {
+ USER_PRIVILEGED, /**< User is privileged */
+ USER_UNPRIVILEGED, /**< User is unprivileged */
+ USER_LOOKUP_FAILURE, /**< Failure to look up whether the user is privileged or unprivileged */
+ USER_UNKNOWN /**< User privilege level not (yet) known */
+ } UserPrivilege;
+
+ /** \name Conversion Functions */
+ /* @{ */
+
+ static QString toString(SessionKind k)
+ {
+ switch(k)
+ {
+ case SESSION_LOOKUP_FAILURE: return "SESSION_LOOKUP_FAILURE";
+ case SESSION_LOCAL: return "SESSION_LOCAL";
+ case SESSION_NONLOCAL: return "SESSION_NONLOCAL";
+ case SESSION_UNKNOWN: return "SESSION_UNKNOWN";
+ default: return QString("unknown value (%1)").arg(k);
+ }
+ }
+
+ static QString toString(UserPrivilege k)
+ {
+ switch(k)
+ {
+ case USER_PRIVILEGED: return "USER_PRIVILEGED";
+ case USER_UNPRIVILEGED: return "USER_UNPRIVILEGED";
+ case USER_LOOKUP_FAILURE: return "USER_LOOKUP_FAILURE";
+ case USER_UNKNOWN: return "USER_UNKNOWN";
+ default: return QString("unknown value (%1)").arg(k);
+ }
+ }
+
+ /* @} */
+
+ /** \name Singleton pattern */
+ /* @{ */
+
+ /** Retrieve the singleton instance. */
+ static PVSCheckPrivileges* instance();
+
+ /** Delete the singleton instance. */
+ static void deleteInstance();
+
+ /* @} */
+
+ /** \name Privilege Checks */
+ /* @{ */
+
+ /** Check for a minimum SessionKind level. \return true if the requirement is fulfilled. */
+ bool require(SessionKind sessionKind, CachedInputContext const& sender);
+
+ /** Check for a minimum UserPrivilege level. \return true if the requirement is fulfilled. */
+ bool require(UserPrivilege userPrivilege, CachedInputContext const& sender);
+
+ /** Check for a minimum SessionKind and UserPrivilege level. \return true if both requirements are fulfilled. */
+ bool require(SessionKind sessionKind, UserPrivilege userPrivilege, CachedInputContext const& sender);
+
+ /* @} */
+
+ /** \name Session Information */
+ /* @{ */
+
+ /** Retrieve the name of the user's X session, according to ConsoleKit. */
+ QString getX11SessionName(CachedInputContext const& sender);
+
+ /** Retrieve the TTY device of the user's X session, according to ConsoleKit. */
+ QString getX11DisplayDevice(CachedInputContext const& sender);
+
+public slots:
+ void updateCachedUserDatabase();
+ void rereadConfiguration();
+
+private:
+ PVSCheckPrivileges(QObject* parent = 0);
+ virtual ~PVSCheckPrivileges();
+
+ typedef QPair<pid_t, QPair<uid_t, gid_t> > piduidgid;
+ piduidgid makePidUidGid(pid_t pid, uid_t uid, gid_t gid)
+ {
+ return qMakePair(pid, qMakePair(uid, gid));
+ }
+
+ QString getSessionReference(CachedInputContext const& sender);
+ SessionKind getSessionKind(CachedInputContext const& sender);
+ UserPrivilege getUserPrivilege(CachedInputContext const& sender);
+
+ static PVSCheckPrivileges* _instance;
+
+ QHash<CachedInputContext, UserPrivilege> _savedUserPrivilege;
+ QHash<CachedInputContext, SessionKind> _savedSessionKind;
+ QHash<CachedInputContext, QString> _savedConsoleKitSession;
+
+ QList<uid_t> _privilegedUsers;
+ QList<gid_t> _privilegedGroups;
+ QMultiMap<uid_t, gid_t> _userGroupMap;
+ QFileSystemWatcher* _watcher;
+};
+
+#endif /* PVSCHECKPRIVILEGES_H_ */
diff --git a/src/input/pvsPrivInputHandler.cpp b/src/input/pvsPrivInputHandler.cpp
new file mode 100644
index 0000000..d33697a
--- /dev/null
+++ b/src/input/pvsPrivInputHandler.cpp
@@ -0,0 +1,124 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsPrivInputHandler.h
+ # - Handle privileged input connection requests - implementation
+ # --------------------------------------------------------------------------
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <cerrno>
+#include <QtDebug>
+#include <QSocketNotifier>
+#include "inputEvent.h"
+#include "inputHandlerChains.h"
+#include "pvsPrivInputSocket.h"
+#include "pvsPrivInputHandler.h"
+
+using namespace std;
+
+class PrivInputContext : public InputEventContext
+{
+public:
+ PrivInputContext(pid_t pid, uid_t uid, gid_t gid)
+ : _pid(pid), _uid(uid), _gid(gid)
+ {
+ }
+
+ pid_t senderPid() const
+ {
+ return _pid;
+ }
+
+ uid_t senderUid() const
+ {
+ return _uid;
+ }
+
+ gid_t senderGid() const
+ {
+ return _gid;
+ }
+
+private:
+ pid_t _pid;
+ uid_t _uid;
+ gid_t _gid;
+};
+
+PVSPrivInputHandler::PVSPrivInputHandler(int fd, QObject* parent) :
+ QObject(parent)
+{
+ _fd = fd;
+ _notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
+ _notifier->setEnabled(true);
+ connect(_notifier, SIGNAL(activated(int)), this, SLOT(canRead()));
+ _handlerChain = makePrivilegedInputEventHandlerChain();
+}
+
+PVSPrivInputHandler::~PVSPrivInputHandler()
+{
+ delete _notifier;
+}
+
+void PVSPrivInputHandler::canRead()
+{
+ _notifier->setEnabled(false);
+
+ // We need to retrieve the credentials of the process:
+ size_t siz = 8;
+ _messageAssembly.clear();
+ _messageAssembly.resize(8);
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+ int err;
+
+ if(!pvsPrivInputRecvMessage(_fd, _messageAssembly.data(), siz, pid, uid, gid, &err))
+ {
+ switch(err)
+ {
+ case EAGAIN:
+#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
+ case EWOULDBLOCK:
+#endif
+ // That's okay. Nothing to do.
+ break;
+ case 0:
+ // We'll survive. There was no actual error, just the library routine
+ // that decided it did not really want to receive that packet.
+ break;
+ default:
+ qWarning("Something bad just happened, and cannot handle it. Panicking.");
+ close(_fd);
+ deleteLater();
+ return;
+ }
+ }
+ else
+ {
+ if(siz != 8)
+ {
+ qWarning("Malformed PVS Input Event packet");
+ return;
+ }
+ QDataStream strm(&_messageAssembly, QIODevice::ReadOnly);
+ InputEvent evt;
+ strm.setByteOrder(QDataStream::BigEndian);
+ strm >> evt;
+ PrivInputContext ctx(pid, uid, gid);
+ _handlerChain.handle(evt, &ctx);
+ }
+
+ _notifier->setEnabled(true);
+}
diff --git a/src/input/pvsPrivInputHandler.h b/src/input/pvsPrivInputHandler.h
new file mode 100644
index 0000000..015dfa1
--- /dev/null
+++ b/src/input/pvsPrivInputHandler.h
@@ -0,0 +1,54 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsPrivInputHandler.h
+ # - Handle privileged input connection requests - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef PVSPRIVINPUTHANDLER_H_
+#define PVSPRIVINPUTHANDLER_H_
+
+#include <QObject>
+#include <QHash>
+#include <QPointer>
+#include "inputEventHandler.h"
+
+class QSocketNotifier;
+
+/**
+ * Handle socket communication with instances of the PVS Client Daemon.
+ *
+ * \note This runs in the context of a Qt main loop. It does not start
+ * a handler thread.
+ */
+class PVSPrivInputHandler : public QObject
+{
+ Q_OBJECT
+public:
+ /**
+ * Listen for InputEvents on file descriptor \c fd.
+ */
+ PVSPrivInputHandler(int fd, QObject* parent = 0);
+ virtual ~PVSPrivInputHandler();
+
+private slots:
+ void canRead();
+
+private:
+ QSocketNotifier* _notifier;
+ QByteArray _messageAssembly;
+ int _bytes;
+ int _fd;
+ InputEventHandlerChain _handlerChain;
+};
+
+#endif /* PVSPRIVINPUTHANDLER_H_ */
diff --git a/src/input/pvsPrivInputSignalHandler.cpp b/src/input/pvsPrivInputSignalHandler.cpp
new file mode 100644
index 0000000..b09c335
--- /dev/null
+++ b/src/input/pvsPrivInputSignalHandler.cpp
@@ -0,0 +1,69 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsPrivInputSignalHandler.cpp:
+ # - Handle signals forwarded over a file descriptor - implementation
+ # --------------------------------------------------------------------------
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <cerrno>
+#include "pvsPrivInputSocket.h"
+#include "pvsPrivInputSignalHandler.h"
+
+void PVSPrivInputSignalHandler::signalReceived(int sigfd)
+{
+ int signum;
+
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+ int err;
+ size_t siz = sizeof(signum);
+
+ if(!pvsPrivInputRecvMessage(sigfd, &signum, siz, pid, uid, gid, &err))
+ {
+ qWarning("Should have received a signal but could not read message: %s", strerror(err));
+ return;
+ }
+
+ if(siz != sizeof(signum))
+ {
+ qWarning("Sould have received a message of size %d bytes but got %d bytes instead. Discarding message.", (int)sizeof(signum), (int)siz);
+ return;
+ }
+
+ if(!_allowUnauthenticatedKilling && pid != getpid())
+ {
+ qCritical("SOMETHING STRANGE IS GOING ON!\nReceived signal %d from PID %d\nPlease kill me instead of sending me signal notifications.", signum, (int)pid);
+ return;
+ }
+
+ switch(signum)
+ {
+ case SIGINT:
+ qDebug("Caught SIGINT. Quitting.");
+ emit terminate();
+ break;
+ case SIGTERM:
+ qDebug("Caught SIGTERM. Quitting.");
+ emit terminate();
+ break;
+ case SIGHUP:
+ qDebug("Caught SIGHUP. Reloading configuration.");
+ emit reloadConfiguration();
+ break;
+ default:
+ qWarning("Received signal %d, but don't know how to handle it.", signum);
+ }
+}
diff --git a/src/input/pvsPrivInputSignalHandler.h b/src/input/pvsPrivInputSignalHandler.h
new file mode 100644
index 0000000..bc549ec
--- /dev/null
+++ b/src/input/pvsPrivInputSignalHandler.h
@@ -0,0 +1,64 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsPrivInputSignalHandler.h:
+ # - Handle signals forwarded over a file descriptor - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef PVSPRIVINPUTSIGNALHANDLER_H_
+#define PVSPRIVINPUTSIGNALHANDLER_H_
+
+#include <QObject>
+
+/**
+ * Handle signals.
+ *
+ * This class reads \c int values from a file descriptor and dispatches sends
+ * Qt signals according to the \c SIG... value the integer represents.
+ * The purpose of this mechanism is to integrate (asynchronous) Unix signal
+ * handling into the synchronous event-driven Qt main loop. The main() function
+ * is expected to open a socket pair and install handlers for all relevant signals
+ * that simply write the number of the signal to that pipe.
+ *
+ * If allowUnauthenticatedKilling() has not been called, this class only accepts
+ * signal numbers that are sent by the same process.
+ */
+class PVSPrivInputSignalHandler : public QObject
+{
+ Q_OBJECT
+public:
+ PVSPrivInputSignalHandler(QObject* parent = 0)
+ : QObject(parent)
+ {
+ }
+
+ /** If \c value is \c true, allow sending signal numbers from other processes. */
+ void allowUnauthenticatedKilling(bool value)
+ {
+ _allowUnauthenticatedKilling = value;
+ }
+
+public slots:
+ /** Connect this slot to a \c QSocketNotifier's \c activated(int) signal. */
+ void signalReceived(int sigfd);
+
+signals:
+ /** SIGTERM */
+ void terminate();
+ /** SIGHUP */
+ void reloadConfiguration();
+
+private:
+ bool _allowUnauthenticatedKilling;
+};
+
+#endif /* PVSPRIVINPUTSIGNALHANDLER_H_ */
diff --git a/src/input/pvsPrivInputSocket.cpp b/src/input/pvsPrivInputSocket.cpp
new file mode 100644
index 0000000..df5dff5
--- /dev/null
+++ b/src/input/pvsPrivInputSocket.cpp
@@ -0,0 +1,233 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsPrivInputSocket.h:
+ # - Centralize knowledge of socket address and connection options
+ # for pvsprivinputd - implementation
+ # --------------------------------------------------------------------------
+ */
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <cerrno>
+#include <QtDebug>
+#include <QSettings>
+#include "pvsPrivInputSocket.h"
+
+using namespace std;
+
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX 108 /* according to unix(7) */
+#endif
+
+static QSettings* pvsPrivInputSettings = 0;
+
+QString pvsPrivInputGetSettingsPath()
+{
+ return "/etc/pvsprivinputd.conf";
+}
+
+QSettings* pvsPrivInputGetSettings()
+{
+ if(!pvsPrivInputSettings)
+ {
+ pvsPrivInputSettings = new QSettings(pvsPrivInputGetSettingsPath(), QSettings::IniFormat);
+ }
+ return pvsPrivInputSettings;
+}
+
+QSettings* pvsPrivInputReopenSettings()
+{
+ if(pvsPrivInputSettings)
+ {
+ delete pvsPrivInputSettings;
+ pvsPrivInputSettings = 0;
+ }
+ return pvsPrivInputGetSettings();
+}
+
+QString pvsPrivInputGetSocketAddress()
+{
+ return pvsPrivInputGetSettings()->value("socketpath", "/tmp/pvsprivinputd.sock").toString();
+}
+
+bool pvsPrivInputEnableReceiveCredentials(int sock)
+{
+ int passcred = 1;
+ if(setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &passcred, sizeof(passcred)) < 0)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+int pvsPrivInputMakeClientSocket()
+{
+ int sock = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(sock < 0)
+ {
+ qWarning("Could not create a socket: %s", strerror(errno));
+ return -1;
+ }
+
+ QByteArray socketPath = pvsPrivInputGetSocketAddress().toLocal8Bit();
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, socketPath.constData(), UNIX_PATH_MAX - 1);
+ if(connect(sock, reinterpret_cast<struct sockaddr*>(&addr),
+ sizeof(addr)) < 0)
+ {
+ qWarning("Could not connect to pvsprivinputd at %s: %s", socketPath.constData(), strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+int pvsPrivInputMakeServerSocket()
+{
+ int sock = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(sock < 0)
+ {
+ qCritical("Could not create a socket: %s", strerror(errno));
+ return -1;
+ }
+
+ // Bind to the address:
+ QByteArray socketPath = pvsPrivInputGetSocketAddress().toLocal8Bit();
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, socketPath.constData(), UNIX_PATH_MAX - 1);
+ if(bind(sock, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0)
+ {
+ qCritical("Could not bind socket to %s", strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+ // Announce that credentials are requested:
+ if(!pvsPrivInputEnableReceiveCredentials(sock))
+ {
+ // We will not operate without credentials.
+ qCritical("Could not request peer credentials: %s", strerror(errno));
+ close(sock);
+ return -1;
+ }
+
+#if 0 /* Only for SOCK_STREAM: */
+ // Listen for connections:
+ if(listen(sock, 1) < 0)
+ {
+ qCritical("Could not listen for connections to %s: %s", socketPath.constData(), strerror(errno));
+ close(sock);
+ return -1;
+ }
+#endif
+
+ return sock;
+}
+
+bool pvsPrivInputSendMessage(int sock, void* buf, size_t _len, int* err)
+{
+ /*
+ * Portability note: All UNIX-like systems can transmit credentials over UNIX
+ * sockets, but only Linux does it automagically.
+ */
+
+ long len = (long)_len;
+
+ // send(2) does not split messages on a SOCK_DGRAM socket.
+ int e = send(sock, buf, len, 0);
+ if(e < 0)
+ {
+ qWarning("Failed to send message of length %d over socket %d: %s", (unsigned)len, e, strerror(errno));
+ if(err)
+ *err = errno;
+ return false;
+ }
+ else if(e < len)
+ {
+ qWarning("Failed to send a complete message of length %d over socket %d, only %d bytes were sent", (unsigned)len, sock, e);
+ if(err)
+ *err = errno;
+ return false;
+ }
+
+ return true;
+}
+
+bool pvsPrivInputRecvMessage(int sock, void* buf, size_t& len,
+ pid_t& pid, uid_t& uid, gid_t& gid, int* err)
+{
+ struct iovec iov;
+ struct msghdr msg;
+ char ctlbuf[1024];
+ iov.iov_base = buf;
+ iov.iov_len = len;
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = &ctlbuf;
+ msg.msg_controllen = sizeof(ctlbuf);
+ msg.msg_flags = 0;
+ int bytes_read = recvmsg(sock, &msg, 0);
+ if(bytes_read < 0)
+ {
+ qWarning("Could not read from socket: %s", strerror(errno));
+ if(err)
+ *err = errno;
+ return false;
+ }
+
+ pid = -1;
+ uid = -1;
+ gid = -1;
+
+ struct cmsghdr* cmsg;
+ for(cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if(cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS)
+ {
+ struct ucred* creds = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsg));
+ pid = creds->pid;
+ uid = creds->uid;
+ gid = creds->gid;
+ break;
+ }
+ else if(cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS)
+ {
+ // We need to close passed file descriptors. If we don't, we
+ // have a denial-of-service vulnerability.
+ int* fds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
+ unsigned num_fds = cmsg->cmsg_len / sizeof(int);
+ for(unsigned i = 0; i < num_fds; i++)
+ {
+ close(fds[i]);
+ }
+ }
+ }
+
+ if(pid == (pid_t)-1 || uid == (uid_t)-1 || gid == (gid_t)-1)
+ {
+ *err = 0;
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/input/pvsPrivInputSocket.h b/src/input/pvsPrivInputSocket.h
new file mode 100644
index 0000000..a57d730
--- /dev/null
+++ b/src/input/pvsPrivInputSocket.h
@@ -0,0 +1,75 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsPrivInputSocket.h:
+ # - Centralize knowledge of socket address and connection options
+ # for pvsprivinputd - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef PVSPRIVINPUTSOCKET_H_
+#define PVSPRIVINPUTSOCKET_H_
+
+#include <sys/types.h>
+#include <cstring>
+#include <QString>
+
+class QSettings;
+
+/**
+ * Load \c pvsprivinputd's configuration. This keeps a cached copy.
+ */
+QSettings* pvsPrivInputGetSettings();
+
+/**
+ * Update the cached configuration copy kept by pvsPrivInputGetSettings().
+ */
+QSettings* pvsPrivInputReopenSettings();
+
+/**
+ * Hardcoded to \c /etc/pvsprivinputd.conf
+ */
+QString pvsPrivInputGetSettingsPath();
+
+/**
+ * Retrieve the path at which \c pvsprivinputd listens for datagrams from
+ * its configuration.
+ */
+QString pvsPrivInputGetSocketAddress();
+
+/**
+ * Enable the receiving of sender credentials on a \c unix(7) socket.
+ */
+bool pvsPrivInputEnableReceiveCredentials(int sock);
+
+/**
+ * Make a \c unix(7) socket that is suitable for sending authenticated
+ * datagrams to \c pvsprivinputd.
+ */
+int pvsPrivInputMakeClientSocket();
+
+/**
+ * Make a listening \c unix(7) socket at the address specified by
+ * pvsPrivInputGetSocketAddress() that receives sender credentials.
+ */
+int pvsPrivInputMakeServerSocket();
+
+/**
+ * Send an authenticated message on a \c unix(7) socket.
+ */
+bool pvsPrivInputSendMessage(int sock, void* buf, size_t len, int* err = 0);
+
+/**
+ * Receive an authenticated message on a \c unix(7) socket.
+ */
+bool pvsPrivInputRecvMessage(int sock, void* buf, size_t& len, pid_t& pid, uid_t& uid, gid_t& gid, int* err = 0);
+
+#endif /* PVSPRIVINPUTSOCKET_H_ */
diff --git a/src/input/pvsSyslog.cpp b/src/input/pvsSyslog.cpp
new file mode 100644
index 0000000..6a9be31
--- /dev/null
+++ b/src/input/pvsSyslog.cpp
@@ -0,0 +1,133 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsSyslog.cpp:
+ # - Send output to syslog or to a file - implementation
+ # --------------------------------------------------------------------------
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <cerrno>
+#include <syslog.h>
+#include <QFile>
+#include <QTextStream>
+#include "pvsSyslog.h"
+
+using namespace std;
+
+#define PVS_LOG_BUFSIZ 8192
+
+void PVSLogRedirector::inputAvailableOn(int fd)
+{
+ QByteArray readbuf;
+ readbuf.resize(PVS_LOG_BUFSIZ);
+ ssize_t siz;
+ bool cont = true;
+
+ do
+ {
+ siz = recv(fd, readbuf.data(), readbuf.size(), MSG_DONTWAIT);
+ if(siz > 0)
+ {
+ _buf.append(readbuf.constData(), siz);
+
+ // Send lines:
+ int oldnpos = -1;
+ int npos = -1;
+ while((npos = _buf.indexOf('\n', oldnpos + 1)) >= 0)
+ {
+ if((oldnpos + 1) == npos)
+ {
+ oldnpos = npos;
+ continue;
+ }
+ QString line = QString::fromLocal8Bit(_buf.constData() + oldnpos + 1, npos - oldnpos - 1);
+ doRedirectInput(line);
+ oldnpos = npos;
+ }
+
+ // All complete lines have been sent. Remove sent bytes from buffer.
+ _buf.remove(0, oldnpos + 1);
+
+ // If line length is too large, send it now.
+ if(_buf.size() >= BUFSIZ)
+ {
+ QString longLine = QString::fromLocal8Bit(_buf.constData(), _buf.size());
+ doRedirectInput(longLine);
+ _buf.clear();
+ }
+ }
+ else if(siz == 0)
+ {
+ // Socket closed on other end.
+ break;
+ }
+ else if(siz < 0)
+ {
+ int err = errno;
+ switch(err)
+ {
+ case EAGAIN:
+#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
+ case EWOULDBLOCK:
+#endif
+ // We read all there is to read.
+ cont = false;
+ break;
+ default:
+ // Something happened.
+ // We can't inform the user via qDebug() and friends as that would loop right back to us again,
+ // so we emit a log line.
+ doRedirectInput(QString("Error in logging code: Could not read log input: %s").arg(strerror(err)));
+ cont = false;
+ }
+ }
+ }
+ while(cont);
+}
+
+PVSSyslogRedirector::PVSSyslogRedirector()
+{
+ openlog("pvsprivinputd", LOG_PID, LOG_USER);
+}
+
+PVSSyslogRedirector::~PVSSyslogRedirector()
+{
+ closelog();
+}
+
+void PVSSyslogRedirector::doRedirectInput(QString const& line)
+{
+ QByteArray bytes = line.toLocal8Bit();
+ syslog(LOG_NOTICE, "%s", bytes.data());
+}
+
+PVSLogfileRedirector::PVSLogfileRedirector(QString const& filename)
+{
+ _file = new QFile(filename, this);
+ _file->open(QIODevice::Append);
+ _stream = new QTextStream(_file);
+}
+
+PVSLogfileRedirector::~PVSLogfileRedirector()
+{
+ _stream->flush();
+ _file->close();
+ delete _stream;
+ delete _file;
+}
+
+void PVSLogfileRedirector::doRedirectInput(QString const& line)
+{
+ *_stream << line << flush;
+}
diff --git a/src/input/pvsSyslog.h b/src/input/pvsSyslog.h
new file mode 100644
index 0000000..36ee2e0
--- /dev/null
+++ b/src/input/pvsSyslog.h
@@ -0,0 +1,72 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsSyslog.h:
+ # - Send output to syslog or to a file - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef PVSSYSLOG_H_
+#define PVSSYSLOG_H_
+
+#include <QObject>
+#include <QString>
+
+/**
+ * Listen on a socket or a pipe and redirect input lines to a child class.
+ */
+class PVSLogRedirector : public QObject
+{
+ Q_OBJECT
+public slots:
+ void inputAvailableOn(int fd);
+
+protected:
+ virtual void doRedirectInput(QString const& line) = 0;
+
+private:
+ QByteArray _buf;
+};
+
+/**
+ * Redirect log lines to a Unix syslog service.
+ */
+class PVSSyslogRedirector : public PVSLogRedirector
+{
+public:
+ PVSSyslogRedirector();
+ virtual ~PVSSyslogRedirector();
+
+protected:
+ void doRedirectInput(QString const& line);
+};
+
+class QFile;
+class QTextStream;
+
+/**
+ * Redirect log lines to a file.
+ */
+class PVSLogfileRedirector : public PVSLogRedirector
+{
+public:
+ PVSLogfileRedirector(QString const& filename);
+ virtual ~PVSLogfileRedirector();
+
+protected:
+ void doRedirectInput(QString const& line);
+
+private:
+ QFile* _file;
+ QTextStream* _stream;
+};
+
+#endif /* PVSSYSLOG_H_ */
diff --git a/src/input/pvsprivinputd.conf b/src/input/pvsprivinputd.conf
new file mode 100644
index 0000000..a62a922
--- /dev/null
+++ b/src/input/pvsprivinputd.conf
@@ -0,0 +1,28 @@
+;; Lines starting with `;' are comments.
+;;
+;; socketpath:
+;; Where pvsprivinputd should put its listening socket.
+socketpath = /tmp/pvsprivinputd.sock
+
+;; privileged-users:
+;; Comma-separated list of users that are allowed to run privileged actions
+privileged-users = root
+
+;; privileged-groups:
+;; Comma-separated list of user groups that are allowed to run privileged actions
+; privileged-groups = wheel
+
+;; assume-session-local:
+;; Assume that a session is local if it can not be looked up in ConsoleKit,
+;; for example, if you are not running ConsoleKit.
+;;
+;; WARNING: Setting this to true may be a security risk. Running ConsoleKit is
+;; really recommended.
+; assume-session-local = false
+
+;; assume-user-privileged:
+;; Assume that a user is privileged if he/she can not be looked up in
+;; the user database or PolicyKit fails to deliver an answer.
+;;
+;; WARNING: Setting this to true is most definitely a security risk.
+; assume-user-privileged = false \ No newline at end of file
diff --git a/src/input/pvsprivinputd.cpp b/src/input/pvsprivinputd.cpp
new file mode 100644
index 0000000..df3acfc
--- /dev/null
+++ b/src/input/pvsprivinputd.cpp
@@ -0,0 +1,264 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # pvsprivinputd.cpp:
+ # - Handle privileged input events - daemon
+ # --------------------------------------------------------------------------
+ */
+
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <signal.h>
+#include <unistd.h>
+#include <cerrno>
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include <QtDebug>
+#include <QFileInfo>
+#include <QSettings>
+#include <QCoreApplication>
+#include <QStringList>
+#include <QSocketNotifier>
+#include "pvsCheckPrivileges.h"
+#include "pvsPrivInputSocket.h"
+#include "pvsPrivInputHandler.h"
+#include "pvsPrivInputSignalHandler.h"
+#include "pvsSyslog.h"
+
+using namespace std;
+
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX 108 /* according to unix(7) */
+#endif
+
+QByteArray socketPath;
+int signalFds[2];
+
+QTextStream qout(stdout, QIODevice::WriteOnly);
+QTextStream qerr(stderr, QIODevice::WriteOnly);
+
+static void unlinkSocket()
+{
+ if(!socketPath.isNull())
+ {
+ unlink(socketPath.constData());
+ }
+}
+
+static void onCaughtSignal(int signum)
+{
+ pvsPrivInputSendMessage(signalFds[0], &signum, sizeof(signum), 0);
+}
+
+static void usage()
+{
+ qout << QObject::tr(
+ "Usage: %1 [--help|-h] [--daemon|-d] [--log=<Logger>|-l<Logger>]\n"
+ "\n"
+ "Options:\n"
+ " --help, -h Show this message\n"
+ " --daemon, -d Run in background\n"
+ " --log=<Logger>,\n"
+ " -l<Logger> Redirect all output to <Logger>\n"
+ " valid values are:\n"
+ " - any file name\n"
+ " - `syslog' to redirect output to the system log\n"
+ " - `null' to discard output (default)\n"
+ " (without quotes)\n"
+ "\n"
+ "Signals:\n"
+ " SIGINT, SIGTERM (or press Ctrl+C when run in foreground)\n"
+ " Quit\n"
+ " SIGHUP Reload configuration and cached user data\n").arg(qApp->arguments().at(0)) << flush;
+}
+
+int main(int argc, char** argv)
+{
+ QCoreApplication app(argc, argv);
+ app.setApplicationName("pvsprivinputd");
+ app.setOrganizationName("openslx");
+
+ bool no_fork = true;
+ QString logTarget = "null";
+
+ foreach(QString arg, app.arguments().mid(1))
+ {
+ if(arg == "--daemon" || arg == "-d")
+ {
+ no_fork = false;
+ }
+ else if(arg.startsWith("-l"))
+ {
+ logTarget = arg.mid(2);
+ }
+ else if(arg.startsWith("--log="))
+ {
+ logTarget = arg.mid(6);
+ }
+ else if(arg == "--help" || arg == "-h")
+ {
+ usage();
+ return EXIT_SUCCESS;
+ }
+ else
+ {
+ qout << "Unexpected argument: " << arg << endl;
+ usage();
+ return EXIT_FAILURE;
+ }
+ }
+
+ if(logTarget != "null" && logTarget != "syslog")
+ {
+ logTarget = QFileInfo(logTarget).absoluteFilePath();
+ qout << "Writing log to " << logTarget << endl;
+ }
+
+ if(!no_fork)
+ {
+ pid_t pid;
+ pid_t sid;
+
+ pid = fork();
+ if(pid < 0)
+ {
+ qCritical("Could not fork: %s", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ if(pid > 0)
+ {
+ exit(EXIT_SUCCESS);
+ }
+
+ // We are now inside a child process.
+ // Detach from parent:
+ sid = setsid();
+ if(sid < 0)
+ {
+ qCritical("Could not detach from parent process: %s", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ // Change to some benign directory:
+ if(chdir("/") < 0)
+ {
+ qCritical("Could not change directory: %s", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ // Okay, we are running as a daemon. Defer reopening standard file descriptors
+ // so we can report errors.
+
+ // Set the file creation mask to allow all processes to connect to
+ // the socket (access control is handled differently):
+ umask(0);
+
+ // Store the socket path before the signal handler is installed so it does not risk segfaulting
+ // due to bad timing.
+ socketPath = pvsPrivInputGetSocketAddress().toLocal8Bit();
+
+ // Ignore SIGPIPE. Connection errors are handled internally.
+ // According to signal(2), the only error is that the signal number
+ // is invalid. This cannot happen.
+ signal(SIGPIPE, SIG_IGN);
+
+ // Create our socket:
+ int sock = pvsPrivInputMakeServerSocket();
+ if(sock < 0)
+ {
+ exit(EXIT_FAILURE);
+ }
+
+ // Install our main object
+ PVSPrivInputHandler* handler = new PVSPrivInputHandler(sock, &app);
+ // When the handler gets deleted, we want to quit the application
+ QObject::connect(handler, SIGNAL(destroyed(QObject*)), &app, SLOT(quit()));
+
+ // set up signal handling:
+ if(socketpair(AF_UNIX, SOCK_DGRAM, 0, signalFds) < 0)
+ {
+ qCritical("Could not set up signal handling. Giving up.");
+ exit(EXIT_FAILURE);
+ }
+ PVSPrivInputSignalHandler sigHandler;
+ QSocketNotifier sigintWatcher(signalFds[1], QSocketNotifier::Read);
+ sigHandler.allowUnauthenticatedKilling(!pvsPrivInputEnableReceiveCredentials(signalFds[1]));
+ QObject::connect(&sigintWatcher, SIGNAL(activated(int)), &sigHandler, SLOT(signalReceived(int)));
+ QObject::connect(&sigHandler, SIGNAL(terminate()), &app, SLOT(quit()));
+ QObject::connect(&sigHandler, SIGNAL(reloadConfiguration()), PVSCheckPrivileges::instance(), SLOT(updateCachedUserDatabase()));
+ QObject::connect(&sigHandler, SIGNAL(reloadConfiguration()), PVSCheckPrivileges::instance(), SLOT(rereadConfiguration()));
+ signal(SIGINT, onCaughtSignal);
+ signal(SIGTERM, onCaughtSignal);
+ signal(SIGHUP, onCaughtSignal);
+
+ PVSLogRedirector* logRedir = 0;
+ QSocketNotifier* logNotif = 0;
+ // Our setup is complete.
+ if(!no_fork)
+ {
+ // Reopen standard file descriptors:
+ freopen("/dev/null", "r", stdin);
+
+ if(logTarget == "null")
+ {
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
+ }
+ else if(logTarget == "syslog")
+ {
+ logRedir = new PVSSyslogRedirector();
+ }
+ else
+ {
+ logRedir = new PVSLogfileRedirector(logTarget);
+ }
+
+ if(logRedir)
+ {
+ int logFds[2];
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, logFds) < 0)
+ {
+ qWarning("Could not open a socket pair: %s", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
+ logNotif = new QSocketNotifier(logFds[1], QSocketNotifier::Read);
+ QObject::connect(logNotif, SIGNAL(activated(int)), logRedir, SLOT(inputAvailableOn(int)));
+
+ // redirect stdout and stderr:
+ dup2(logFds[0], 1);
+ dup2(logFds[0], 2);
+ }
+ }
+
+ atexit(unlinkSocket);
+
+ qout << "PVS Privileged Input Daemon initialization complete. Entering main loop." << endl;
+
+ // and run the main loop.
+ int ret = app.exec();
+
+ if(logRedir)
+ {
+ delete logNotif;
+ delete logRedir;
+ }
+
+ PVSCheckPrivileges::deleteInstance();
+
+ qout << "PVS Privileged Input Daemon deinitialization complete. Exiting." << endl;
+
+ return ret;
+}
diff --git a/src/input/pvsprivinputd.gentooinit.in b/src/input/pvsprivinputd.gentooinit.in
new file mode 100644
index 0000000..03ade0f
--- /dev/null
+++ b/src/input/pvsprivinputd.gentooinit.in
@@ -0,0 +1,37 @@
+#!/sbin/runscript
+# Copyright (C) 2010 OpenSKX Project, Computer Center of the University of Freiburg, Germany
+# This program is free software distributed under the GPL version 2.
+# See http://openslx.org/COPYING
+
+opts="${opts} reload"
+
+PVSPRIVINPUTD_BINARY="@CMAKE_INSTALL_PREFIX@/sbin/pvsprivinputd"
+PVSPRIVINPUTD_PIDFILE="/var/run/pvsprivinputd.pid"
+
+depend() {
+ use net
+ use logger
+ before dbus
+}
+
+start() {
+ ebegin "Starting pvsprivinputd"
+ start-stop-daemon --start --pidfile "${PVSPRIVINPUTD_PIDFILE}" \
+ --exec "${PVSPRIVINPUTD_BINARY}" -- \
+ -d -lsyslog
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping pvsprivinputd"
+ start-stop-daemon --stop --signal SIGINT --pidfile "${PVSPRIVINPUTD_PIDFILE}" \
+ --exec "${PVSPRIVINPUTD_BINARY}"
+ eend $?
+}
+
+reload() {
+ ebegin "Realoding pvsprivinputd's configuration"
+ start-stop-daemon --stop --signal SIGHUP --pidfile "${PVSPRIVINPUTD_PIDFILE}" \
+ --oknodo --exec "${PVSPRIVINPUTD_BINARY}"
+ eend $?
+}
diff --git a/src/input/pvsprivinputd.lsbinit.in b/src/input/pvsprivinputd.lsbinit.in
new file mode 100644
index 0000000..9b4293e
--- /dev/null
+++ b/src/input/pvsprivinputd.lsbinit.in
@@ -0,0 +1,152 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides: pvsprivinputd
+# Required-Start: $remote_fs $syslog
+# Required-Stop: $remote_fs $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: PVS Privileged Input Daemon
+# Description: Support system service for PVS.
+### END INIT INFO
+
+# Author: Sebastien Braun <sebastien@sebbraun.de>
+#
+# Please remove the "Author" lines above and replace them
+# with your own name if you copy and modify this script.
+
+# Do NOT "set -e"
+
+# PATH should only include /usr/* if it runs after the mountnfs.sh script
+PATH=/sbin:/usr/sbin:/bin:/usr/bin
+DESC="Support system service for PVS"
+NAME=pvsprivinputd
+DAEMON=@CMAKE_INSTALL_PREFIX@/sbin/pvsprivinputd
+DAEMON_ARGS="-d -lsyslog"
+PIDFILE=/var/run/$NAME.pid
+SCRIPTNAME=/etc/init.d/$NAME
+
+# Exit if the package is not installed
+[ -x "$DAEMON" ] || exit 0
+
+# Read configuration variable file if it is present
+[ -r /etc/default/$NAME ] && . /etc/default/$NAME
+
+# Load the VERBOSE setting and other rcS variables
+. /lib/init/vars.sh
+
+# Define LSB log_* functions.
+# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
+. /lib/lsb/init-functions
+
+#
+# Function that starts the daemon/service
+#
+do_start()
+{
+ # Return
+ # 0 if daemon has been started
+ # 1 if daemon was already running
+ # 2 if daemon could not be started
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
+ || return 1
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
+ $DAEMON_ARGS \
+ || return 2
+ # Add code here, if necessary, that waits for the process to be ready
+ # to handle requests from services started subsequently which depend
+ # on this one. As a last resort, sleep for some time.
+}
+
+#
+# Function that stops the daemon/service
+#
+do_stop()
+{
+ # Return
+ # 0 if daemon has been stopped
+ # 1 if daemon was already stopped
+ # 2 if daemon could not be stopped
+ # other if a failure occurred
+ start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
+ RETVAL="$?"
+ [ "$RETVAL" = 2 ] && return 2
+ # Wait for children to finish too if this is a daemon that forks
+ # and if the daemon is only ever run from this initscript.
+ # If the above conditions are not satisfied then add some other code
+ # that waits for the process to drop all resources that could be
+ # needed by services started subsequently. A last resort is to
+ # sleep for some time.
+ start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
+ [ "$?" = 2 ] && return 2
+ # Many daemons don't delete their pidfiles when they exit.
+ rm -f $PIDFILE
+ return "$RETVAL"
+}
+
+#
+# Function that sends a SIGHUP to the daemon/service
+#
+do_reload() {
+ #
+ # If the daemon can reload its configuration without
+ # restarting (for example, when it is sent a SIGHUP),
+ # then implement that here.
+ #
+ start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
+ return 0
+}
+
+case "$1" in
+ start)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
+ do_start
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ stop)
+ [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
+ 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
+ esac
+ ;;
+ status)
+ status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
+ ;;
+ reload|force-reload)
+ #
+ # If do_reload() is not implemented then leave this commented out
+ # and leave 'force-reload' as an alias for 'restart'.
+ #
+ log_daemon_msg "Reloading $DESC" "$NAME"
+ do_reload
+ log_end_msg $?
+ ;;
+ restart)
+ log_daemon_msg "Restarting $DESC" "$NAME"
+ do_stop
+ case "$?" in
+ 0|1)
+ do_start
+ case "$?" in
+ 0) log_end_msg 0 ;;
+ 1) log_end_msg 1 ;; # Old process is still running
+ *) log_end_msg 1 ;; # Failed to start
+ esac
+ ;;
+ *)
+ # Failed to stop
+ log_end_msg 1
+ ;;
+ esac
+ ;;
+ *)
+ echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
+ exit 3
+ ;;
+esac
+
+:
diff --git a/src/input/rebootSystemHandler.cpp b/src/input/rebootSystemHandler.cpp
new file mode 100644
index 0000000..6c5c63a
--- /dev/null
+++ b/src/input/rebootSystemHandler.cpp
@@ -0,0 +1,32 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # rebootSystemHandler.cpp
+ # - Handle system reboot requests - implementation
+ # --------------------------------------------------------------------------
+ */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <cerrno>
+#include <QtDebug>
+#include "rebootSystemHandler.h"
+
+using namespace std;
+
+void RebootLinuxSystemHandler::doHandle(InputEvent const& evt, InputEventContext const* ctx)
+{
+ // Rebooting a linux system is particulary easy:
+ if(kill(1, SIGINT) < 0)
+ {
+ qWarning("Could not kill /sbin/init: %s", strerror(errno));
+ }
+}
diff --git a/src/input/rebootSystemHandler.h b/src/input/rebootSystemHandler.h
new file mode 100644
index 0000000..357dcad
--- /dev/null
+++ b/src/input/rebootSystemHandler.h
@@ -0,0 +1,36 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # rebootSystemHandler.h
+ # - Handle system reboot requests - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef REBOOTSYSTEMHANDLER_H_
+#define REBOOTSYSTEMHANDLER_H_
+
+#include <QCoreApplication>
+#include "inputEventHandler.h"
+
+/**
+ * Reboot a Linux system.
+ */
+class RebootLinuxSystemHandler : public InputEventHandler<
+ input_policy::Require<input_policy::LinuxSystem> >
+{
+public:
+ /**
+ * Send SIGINT to the process with PID 1.
+ */
+ void doHandle(InputEvent const&, InputEventContext const*);
+};
+
+#endif /* REBOOTSYSTEMHANDLER_H_ */
diff --git a/src/input/sayHelloHandler.cpp b/src/input/sayHelloHandler.cpp
new file mode 100644
index 0000000..301709f
--- /dev/null
+++ b/src/input/sayHelloHandler.cpp
@@ -0,0 +1,25 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # rebootSystemHandler.h
+ # - Handle "say hello" requests - interface
+ # --------------------------------------------------------------------------
+ */
+
+#include "sayHelloHandler.h"
+#include <iostream>
+
+using namespace std;
+
+void SayHelloHandler::doHandle(InputEvent const&, InputEventContext const* ctx)
+{
+ cerr << "I'm right here! You sent this message from pid " << ctx->senderPid() << " as user " << ctx->senderUid() << " with gid " << ctx->senderGid() << endl;
+}
diff --git a/src/input/sayHelloHandler.h b/src/input/sayHelloHandler.h
new file mode 100644
index 0000000..24118cf
--- /dev/null
+++ b/src/input/sayHelloHandler.h
@@ -0,0 +1,35 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # rebootSystemHandler.h
+ # - Handle "say hello" requests - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef SAYHELLOHANDLER_CPP_
+#define SAYHELLOHANDLER_CPP_
+
+#include <QCoreApplication>
+#include "inputEventHandler.h"
+
+/**
+ * Write a line to the log stating the PID, UID and GID of the
+ * PVS Client Daemon.
+ */
+class SayHelloHandler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_SPECIAL, InputEvent::EC_SAY_HELLO>,
+ input_policy::Security<input_policy::AllowEverybody> >
+{
+public:
+ void doHandle(InputEvent const&, InputEventContext const*);
+};
+
+#endif /* SAYHELLOHANDLER_CPP_ */
diff --git a/src/input/unprivilegedInputHandlerChain.cpp b/src/input/unprivilegedInputHandlerChain.cpp
new file mode 100644
index 0000000..3f47631
--- /dev/null
+++ b/src/input/unprivilegedInputHandlerChain.cpp
@@ -0,0 +1,34 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # privilegedInputHandlerChain.cpp
+ # - Definition of the input handler chains - implementation for
+ # unprivileged chain
+ # --------------------------------------------------------------------------
+ */
+
+#include "x11FakeKeyboardHandler.h"
+#include "x11FakeMouseHandler.h"
+#include "privilegedHandlerForwarder.h"
+#include "incompatibleHandler.h"
+#include "inputHandlerChains.h"
+#include "logNonMatchingHandler.h"
+
+InputEventHandlerChain makeUnprivilegedInputEventHandlerChain()
+{
+ return InputEventHandlerChain().add<X11FakeKeyboardHandler>()
+ .add<X11FakeMouseButtonHandler>()
+ .add<X11FakeMouseMovementHandler>()
+ .add<PrivilegedHandlerForwarder>()
+ .add<IncompatibleHandler>() // See comments in incompatibleHandler.h
+ .add<LogNonMatchingHandler>();
+}
+
diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp
new file mode 100644
index 0000000..f27ea1e
--- /dev/null
+++ b/src/input/x11FakeKeyboardHandler.cpp
@@ -0,0 +1,877 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # x11FakeKeyboardHandler.cpp:
+ # - Handle keyboard events on X11 - interface
+ # --------------------------------------------------------------------------
+ */
+
+#include <map>
+#include <set>
+#include <cassert>
+// Qt headers need to be included before X11 headers
+#include <QApplication>
+#include <QtCore>
+#include "x11FakeKeyboardHandler.h"
+// #include <multimap>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <X11/keysymdef.h>
+#include <X11/extensions/XTest.h>
+#ifdef HAVE_XINPUT2_H
+# include <X11/extensions/XInput2.h>
+#else
+# include <X11/extensions/XInput.h>
+#endif
+#include <X11/XKBlib.h>
+#include <src/util/consoleLogger.h>
+#include "x11InputUtils.h"
+
+// X11 supports 8 modifiers, so a bitmask of modifiers fits into a byte:
+typedef unsigned char XModifiers;
+
+// For debugging output, these are the names of modifier keys:
+char modifiernames[][8] = {
+ "SHIFT",
+ "LOCK",
+ "CONTROL",
+ "MOD1",
+ "MOD2",
+ "MOD3",
+ "MOD4",
+ "MOD5"
+};
+
+// We generally want to find a key sequence with as few modifiers as
+// possible. These are all modifier combinations sorted by number of
+// bits set:
+char modifierpriority[256] = {
+ 0, 1, 2, 4, 8, 16, 32, 64, 128,
+ 3, 5, 6, 9, 10, 12, 17, 18,
+ 20, 24, 33, 34, 36, 40, 48, 65,
+ 66, 68, 72, 80, 96, 129, 130, 132,
+ 136, 144, 160, 192, 7, 11, 13, 14,
+ 19, 21, 22, 25, 26, 28, 35, 37,
+ 38, 41, 42, 44, 49, 50, 52, 56,
+ 67, 69, 70, 73, 74, 76, 81, 82,
+ 84, 88, 97, 98, 100, 104, 112, 131,
+ 133, 134, 137, 138, 140, 145, 146, 148,
+ 152, 161, 162, 164, 168, 176, 193, 194,
+ 196, 200, 208, 224, 15, 23, 27, 29,
+ 30, 39, 43, 45, 46, 51, 53, 54,
+ 57, 58, 60, 71, 75, 77, 78, 83,
+ 85, 86, 89, 90, 92, 99, 101, 102,
+ 105, 106, 108, 113, 114, 116, 120, 135,
+ 139, 141, 142, 147, 149, 150, 153, 154,
+ 156, 163, 165, 166, 169, 170, 172, 177,
+ 178, 180, 184, 195, 197, 198, 201, 202,
+ 204, 209, 210, 212, 216, 225, 226, 228,
+ 232, 240, 31, 47, 55, 59, 61, 62,
+ 79, 87, 91, 93, 94, 103, 107, 109,
+ 110, 115, 117, 118, 121, 122, 124, 143,
+ 151, 155, 157, 158, 167, 171, 173, 174,
+ 179, 181, 182, 185, 186, 188, 199, 203,
+ 205, 206, 211, 213, 214, 217, 218, 220,
+ 227, 229, 230, 233, 234, 236, 241, 242,
+ 244, 248, 63, 95, 111, 119, 123, 125,
+ 126, 159, 175, 183, 187, 189, 190, 207,
+ 215, 219, 221, 222, 231, 235, 237, 238,
+ 243, 245, 246, 249, 250, 252, 127, 191,
+ 223, 239, 247, 251, 253, 254, 255
+};
+
+QString modifiersToString(XModifiers mods)
+{
+ QString s;
+ for(int i = 0; i < 8; i++)
+ {
+ if(mods & (1<<i))
+ {
+ s += modifiernames[i];
+ s += ", ";
+ }
+ }
+ s.chop(2);
+ return s;
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Input event translation code
+/////////////////////////////////////////////////////////////////////////
+
+// We need to translate between Qt's keycodes and X11's keycodes.
+// Unfortunately, there does not seem to be a direct correspondence
+// between them, so we are stuck with storing a lookup table:
+typedef std::map<quint32, KeySym> KeycodeLookupTable;
+KeycodeLookupTable keysyms;
+
+// The following code has been partially autogenerated by
+// an insane sed(1) script and then hand-edited to make
+// the errors go away.
+void initializeKeycodeLookupTable() {
+ keysyms[Qt::Key_Escape] = XK_Escape;
+ keysyms[Qt::Key_Tab] = XK_Tab;
+ keysyms[Qt::Key_Backtab] = XK_ISO_Left_Tab;
+ keysyms[Qt::Key_Backspace] = XK_BackSpace;
+ keysyms[Qt::Key_Return] = XK_Return;
+ keysyms[Qt::Key_Enter] = XK_KP_Enter;
+ keysyms[Qt::Key_Insert] = XK_Insert;
+ keysyms[Qt::Key_Delete] = XK_Delete;
+ keysyms[Qt::Key_Pause] = XK_Pause;
+ keysyms[Qt::Key_Print] = XK_Print;
+ keysyms[Qt::Key_SysReq] = XK_Sys_Req;
+ keysyms[Qt::Key_Clear] = XK_Clear;
+ keysyms[Qt::Key_Home] = XK_Home;
+ keysyms[Qt::Key_End] = XK_End;
+ keysyms[Qt::Key_Left] = XK_Left;
+ keysyms[Qt::Key_Up] = XK_Up;
+ keysyms[Qt::Key_Right] = XK_Right;
+ keysyms[Qt::Key_Down] = XK_Down;
+ keysyms[Qt::Key_PageUp] = XK_Page_Up;
+ keysyms[Qt::Key_PageDown] = XK_Page_Down;
+ keysyms[Qt::Key_Shift] = XK_Shift_L;
+ keysyms[Qt::Key_Control] = XK_Control_L;
+ keysyms[Qt::Key_Meta] = XK_Meta_L;
+ keysyms[Qt::Key_Alt] = XK_Alt_L;
+ keysyms[Qt::Key_CapsLock] = XK_Caps_Lock;
+ keysyms[Qt::Key_NumLock] = XK_Num_Lock;
+ keysyms[Qt::Key_ScrollLock] = XK_Scroll_Lock;
+ keysyms[Qt::Key_F1] = XK_F1;
+ keysyms[Qt::Key_F2] = XK_F2;
+ keysyms[Qt::Key_F3] = XK_F3;
+ keysyms[Qt::Key_F4] = XK_F4;
+ keysyms[Qt::Key_F5] = XK_F5;
+ keysyms[Qt::Key_F6] = XK_F6;
+ keysyms[Qt::Key_F7] = XK_F7;
+ keysyms[Qt::Key_F8] = XK_F8;
+ keysyms[Qt::Key_F9] = XK_F9;
+ keysyms[Qt::Key_F10] = XK_F10;
+ keysyms[Qt::Key_F11] = XK_F11;
+ keysyms[Qt::Key_F12] = XK_F12;
+ keysyms[Qt::Key_F13] = XK_F13;
+ keysyms[Qt::Key_F14] = XK_F14;
+ keysyms[Qt::Key_F15] = XK_F15;
+ keysyms[Qt::Key_F16] = XK_F16;
+ keysyms[Qt::Key_F17] = XK_F17;
+ keysyms[Qt::Key_F18] = XK_F18;
+ keysyms[Qt::Key_F19] = XK_F19;
+ keysyms[Qt::Key_F20] = XK_F20;
+ keysyms[Qt::Key_F21] = XK_F21;
+ keysyms[Qt::Key_F22] = XK_F22;
+ keysyms[Qt::Key_F23] = XK_F23;
+ keysyms[Qt::Key_F24] = XK_F24;
+ keysyms[Qt::Key_F25] = XK_F25;
+ keysyms[Qt::Key_F26] = XK_F26;
+ keysyms[Qt::Key_F27] = XK_F27;
+ keysyms[Qt::Key_F28] = XK_F28;
+ keysyms[Qt::Key_F29] = XK_F29;
+ keysyms[Qt::Key_F30] = XK_F30;
+ keysyms[Qt::Key_F31] = XK_F31;
+ keysyms[Qt::Key_F32] = XK_F32;
+ keysyms[Qt::Key_F33] = XK_F33;
+ keysyms[Qt::Key_F34] = XK_F34;
+ keysyms[Qt::Key_F35] = XK_F35;
+ keysyms[Qt::Key_Super_L] = XK_Super_L;
+ keysyms[Qt::Key_Super_R] = XK_Super_R;
+ keysyms[Qt::Key_Menu] = XK_Menu;
+ keysyms[Qt::Key_Hyper_L] = XK_Hyper_L;
+ keysyms[Qt::Key_Hyper_R] = XK_Hyper_R;
+ keysyms[Qt::Key_Help] = XK_Help;
+
+ // Latin1 symbols do directly map to
+ // Keycodes both in Qt and in X11:
+ for(int i = 0x20; i < 0x100; i++)
+ {
+ keysyms[i] = i;
+ }
+
+ keysyms[Qt::Key_AltGr] = XK_ISO_Level3_Shift;
+ keysyms[Qt::Key_Multi_key] = XK_Multi_key;
+ keysyms[Qt::Key_Codeinput] = XK_Codeinput;
+ keysyms[Qt::Key_SingleCandidate] = XK_SingleCandidate;
+ keysyms[Qt::Key_MultipleCandidate] = XK_MultipleCandidate;
+ keysyms[Qt::Key_PreviousCandidate] = XK_PreviousCandidate;
+ keysyms[Qt::Key_Mode_switch] = XK_Mode_switch;
+ keysyms[Qt::Key_Kanji] = XK_Kanji;
+ keysyms[Qt::Key_Muhenkan] = XK_Muhenkan;
+ keysyms[Qt::Key_Henkan] = XK_Henkan;
+ keysyms[Qt::Key_Romaji] = XK_Romaji;
+ keysyms[Qt::Key_Hiragana] = XK_Hiragana;
+ keysyms[Qt::Key_Katakana] = XK_Katakana;
+ keysyms[Qt::Key_Hiragana_Katakana] = XK_Hiragana_Katakana;
+ keysyms[Qt::Key_Zenkaku] = XK_Zenkaku;
+ keysyms[Qt::Key_Hankaku] = XK_Hankaku;
+ keysyms[Qt::Key_Zenkaku_Hankaku] = XK_Zenkaku_Hankaku;
+ keysyms[Qt::Key_Touroku] = XK_Touroku;
+ keysyms[Qt::Key_Massyo] = XK_Massyo;
+ keysyms[Qt::Key_Kana_Lock] = XK_Kana_Lock;
+ keysyms[Qt::Key_Kana_Shift] = XK_Kana_Shift;
+ keysyms[Qt::Key_Eisu_Shift] = XK_Eisu_Shift;
+ keysyms[Qt::Key_Eisu_toggle] = XK_Eisu_toggle;
+ keysyms[Qt::Key_Hangul] = XK_Hangul;
+ keysyms[Qt::Key_Hangul_Hanja] = XK_Hangul_Hanja;
+ keysyms[Qt::Key_Hangul] = XK_Hangul;
+ keysyms[Qt::Key_Hangul_Start] = XK_Hangul_Start;
+ keysyms[Qt::Key_Hangul_End] = XK_Hangul_End;
+ keysyms[Qt::Key_Hangul_Hanja] = XK_Hangul_Hanja;
+ keysyms[Qt::Key_Hangul_Jamo] = XK_Hangul_Jamo;
+ keysyms[Qt::Key_Hangul_Romaja] = XK_Hangul_Romaja;
+ keysyms[Qt::Key_Hangul_Jeonja] = XK_Hangul_Jeonja;
+ keysyms[Qt::Key_Hangul_Banja] = XK_Hangul_Banja;
+ keysyms[Qt::Key_Hangul_PreHanja] = XK_Hangul_PreHanja;
+ keysyms[Qt::Key_Hangul_PostHanja] = XK_Hangul_PostHanja;
+ keysyms[Qt::Key_Hangul_Special] = XK_Hangul_Special;
+ keysyms[Qt::Key_Dead_Grave] = XK_dead_grave;
+ keysyms[Qt::Key_Dead_Acute] = XK_dead_acute;
+ keysyms[Qt::Key_Dead_Circumflex] = XK_dead_circumflex;
+ keysyms[Qt::Key_Dead_Tilde] = XK_dead_tilde;
+ keysyms[Qt::Key_Dead_Macron] = XK_dead_macron;
+ keysyms[Qt::Key_Dead_Breve] = XK_dead_breve;
+ keysyms[Qt::Key_Dead_Abovedot] = XK_dead_abovedot;
+ keysyms[Qt::Key_Dead_Diaeresis] = XK_dead_diaeresis;
+ keysyms[Qt::Key_Dead_Abovering] = XK_dead_abovering;
+ keysyms[Qt::Key_Dead_Doubleacute] = XK_dead_doubleacute;
+ keysyms[Qt::Key_Dead_Caron] = XK_dead_caron;
+ keysyms[Qt::Key_Dead_Cedilla] = XK_dead_cedilla;
+ keysyms[Qt::Key_Dead_Ogonek] = XK_dead_ogonek;
+ keysyms[Qt::Key_Dead_Iota] = XK_dead_iota;
+ keysyms[Qt::Key_Dead_Voiced_Sound] = XK_dead_voiced_sound;
+ keysyms[Qt::Key_Dead_Semivoiced_Sound] = XK_dead_semivoiced_sound;
+ keysyms[Qt::Key_Dead_Belowdot] = XK_dead_belowdot;
+ keysyms[Qt::Key_Dead_Hook] = XK_dead_hook;
+ keysyms[Qt::Key_Dead_Horn] = XK_dead_horn;
+ keysyms[Qt::Key_Select] = XK_Select;
+ keysyms[Qt::Key_Cancel] = XK_Cancel;
+ keysyms[Qt::Key_Execute] = XK_Execute;
+ keysyms[Qt::Key_unknown] = XK_VoidSymbol;
+}
+
+// We need to store how to generate KeySyms:
+struct KeySymInfo
+{
+ KeyCode keycode;
+ XModifiers neededModifiers;
+ XModifiers modifierMask;
+};
+typedef std::map<KeySym, KeySymInfo> KeySymToInfoMap;
+KeySymToInfoMap keysymInfos;
+
+// What keys do we need to press to generate the
+// modifiers?
+int modifierKeycodes[8];
+// How do the X11 modifiers relate to Qt's KeyboardModifiers?
+Qt::KeyboardModifier modifierMeaning[8];
+
+// How do the X11 modifiers correspond to Qt's KeyboardModifiers?
+typedef std::map<XModifiers, Qt::KeyboardModifier> XToQtModifierMap;
+XToQtModifierMap XToQtModifier;
+typedef std::map<Qt::KeyboardModifier, XModifiers> QtToXModifierMap;
+QtToXModifierMap QtToXModifier;
+
+
+// And how do the modifiers relate to Keycodes?
+typedef std::multimap<XModifiers, int> ModifierToKeycodeMap;
+ModifierToKeycodeMap ModifierToKeycode;
+typedef std::map<int, XModifiers> KeycodeToModifierMap;
+KeycodeToModifierMap KeycodeToModifier;
+
+#ifdef HAVE_XKBLIB_H
+void recordModifierMapping(XkbDescPtr keybDesc, int keycode, Qt::KeyboardModifier qtMod)
+{
+ XModifiers rmod = 0;
+ if(QtToXModifier.find(qtMod) == QtToXModifier.end())
+ {
+ for(int i = 1; i < 0x100; i <<= 1)
+ {
+ if(keybDesc->map->modmap[keycode] == i)
+ {
+ rmod = i;
+ XToQtModifier[rmod] = qtMod;
+ QtToXModifier[qtMod] = rmod;
+ }
+ }
+ }
+ else
+ {
+ rmod = QtToXModifier[qtMod];
+ }
+
+ if(rmod)
+ {
+ ModifierToKeycode.insert(std::make_pair(rmod, keycode));
+ KeycodeToModifier[keycode] = rmod;
+ ConsoleLog writeLine(QString("%1 %2 %3 ... generates modifier %4").arg(keycode, 3).arg("", 40).arg("", 40).arg(rmod, 2, 16));
+ }
+}
+#endif
+
+// We need to query the input devices, preferrable through XInput2, but
+// if that is not available we will contend ourselves with XInput1:
+#ifndef HAVE_XINPUT2_H
+# define XIAllDevices 1 /* does not matter */
+# define XIDeviceInfo XDeviceInfo
+# define XIQueryDevice(dpy, which, ninfos) XListInputDevices(dpy, ninfos)
+# define XIFreeDeviceInfo(infos) XFreeDeviceList(infos)
+# define XIMasterKeyboard IsXKeyboard
+# define XISlaveKeyboard IsXExtensionKeyboard
+ static inline Atom* getDeviceProperties(Display* dpy, XIDeviceInfo* devinfo, int* nprops)
+ {
+ if(devinfo->use == IsXKeyboard)
+ {
+ // According to XOpenDevice(3X11) you cannot open the Core Keyboard.
+ *nprops = 0;
+ return 0;
+ }
+
+ XDevice* dev = XOpenDevice(dpy, devinfo->id);
+ Atom* props = XListDeviceProperties(dpy, dev, nprops);
+ XCloseDevice(dpy, dev);
+ return props;
+ }
+#else
+ static inline Atom* getDeviceProperties(Display* dpy, XIDeviceInfo* devinfo, int* nprops)
+ {
+ return XIListProperties(dpy, devinfo->deviceid, nprops);
+ }
+#endif
+
+// Initialize the above data structures:
+void initializeBasicKeycodes()
+{
+ // We temporarily need a list of all known KeySyms:
+ typedef std::set<KeySym> KeySymSet;
+ KeySymSet knownKeySyms;
+
+ for(KeycodeLookupTable::const_iterator kcIter = keysyms.begin();
+ kcIter != keysyms.end();
+ kcIter++)
+ {
+ knownKeySyms.insert((*kcIter).second);
+ }
+
+ // Mark everything as unknown initially
+ for(int i = 0; i < 8; i++) {
+ modifierKeycodes[i] = -1;
+ }
+ keysymInfos.clear();
+
+ Display* dpy = X11InputUtils::display();
+
+ // Find out the valid range of keycodes
+ int minKeycode, maxKeycode;
+ XDisplayKeycodes(dpy, &minKeycode, &maxKeycode);
+
+ // Initialize the XKB client-side code, and find out whether
+ // the XKB extension is present in the server.
+ int xkbOpcode, xkbEvent, xkbError, xkbMajor, xkbMinor;
+#ifdef HAVE_XKBLIB_H
+ bool xkbPresent = XkbQueryExtension(dpy, &xkbOpcode, &xkbEvent, &xkbError, &xkbMajor, &xkbMinor);
+#else
+ bool xkbPresent = false;
+#endif
+
+ if(!xkbPresent) {
+ // No XKB. This is probably not a very recent
+ // system, but we will do the best we can.
+ // Retrieve the keyboard mapping
+ int keysymsPerCode;
+ const int count = maxKeycode - minKeycode + 1;
+ KeySym* mapping = XGetKeyboardMapping(dpy, minKeycode, count, &keysymsPerCode);
+
+ // and traverse every entry
+ for(int i = 0; i < count; i++)
+ {
+ for(int j = 0; j < 0x100; j++)
+ {
+ const XModifiers mods = modifierpriority[j];
+ if(mods >= keysymsPerCode)
+ continue;
+
+ const int idx = i * keysymsPerCode + mods;
+ const KeySym ks = mapping[idx];
+ const int keycode = minKeycode + i;
+
+ // to find out if there is a KeySym there that we know about
+ if(knownKeySyms.find(ks) != knownKeySyms.end())
+ {
+ // that we have not yet found,
+ if(keysymInfos.find(ks) != keysymInfos.end())
+ continue; // already found
+
+ // and record its keycode and needed modifiers.
+ KeySymInfo info;
+ info.keycode = keycode;
+ info.neededModifiers = mods;
+ info.modifierMask = mods;
+ keysymInfos[ks] = info;
+ }
+ }
+ }
+
+ // We are finished, free the mapping structure.
+ XFree(mapping);
+
+ // find out which keycodes cause the modifier state bits:
+ XModifierKeymap* modkm;
+ modkm = XGetModifierMapping(dpy);
+
+ const int shiftCode = XKeysymToKeycode(dpy, XK_Shift_L);
+ const int controlCode = XKeysymToKeycode(dpy, XK_Control_L);
+ const int altCode = XKeysymToKeycode(dpy, XK_Alt_L);
+ const int metaCode = XKeysymToKeycode(dpy, XK_Meta_L);
+ const int switchCode = XKeysymToKeycode(dpy, XK_Mode_switch);
+
+ // and use this information to find out which
+ // X11 modifiers correspond to Qt's modifiers:
+ for(int i = 0; i < 8; i++) {
+ for(int j = 0; j < modkm->max_keypermod; j++) {
+ const int idx = i * modkm->max_keypermod + j;
+ const int kc = modkm->modifiermap[idx];
+
+ ModifierToKeycode.insert(std::make_pair((1<<i), kc));
+ KeycodeToModifier[kc] = (1<<i);
+ if(kc == shiftCode) {
+ XToQtModifier[1<<i] = Qt::ShiftModifier;
+ } else if(kc == controlCode) {
+ XToQtModifier[1<<i] = Qt::ControlModifier;
+ } else if(kc == altCode) {
+ XToQtModifier[1<<i] = Qt::AltModifier;
+ } else if(kc == metaCode) {
+ XToQtModifier[1<<i] = Qt::MetaModifier;
+ } else if(kc == switchCode) {
+ XToQtModifier[1<<i] = Qt::GroupSwitchModifier;
+ }
+
+ // and record the keycode we need to press/release
+ // to activate or deactivate a modifier:
+ if(modifierKeycodes[i] != -1) {
+ continue; // already found
+ }
+
+ // select one arbitrarily
+ modifierKeycodes[i] = kc;
+ }
+ }
+
+ XFreeModifiermap(modkm);
+ }
+#ifdef HAVE_XKBLIB_H
+ else
+ {
+ // XKB is present.
+
+ // As different input devices can have different keymaps,
+ // we need to find out what device XTest will send events on:
+ unsigned int xkbDeviceId = XkbUseCoreKbd;
+
+
+ // Is XInput present?
+#if defined(HAVE_XINPUT_H) || defined(HAVE_XINPUT2_H)
+ // We don't care about these:
+ int i1, i2, i3;
+ bool haveXInput = XQueryExtension(dpy, "XInputExtension", &i1, &i2, &i3);
+
+ if(haveXInput)
+ {
+ Atom xtestDeviceProp = XInternAtom(dpy, "XTEST Device", false);
+
+ // Find the list of input devices:
+ int ndevinfos;
+ XIDeviceInfo* devinfos = XIQueryDevice(dpy, XIAllDevices, &ndevinfos);
+ if(devinfos)
+ {
+#ifndef HAVE_XINPUT2_H
+# define deviceid id
+#endif
+ for(int i = 0; i < ndevinfos && xkbDeviceId == XkbUseCoreKbd; i++)
+ {
+ XIDeviceInfo* devinfo = devinfos + i;
+ qDebug("Found device %lu of type %d with name %s", (unsigned long)devinfo->deviceid, devinfo->use, devinfo->name);
+
+ // We want it to be a keyboard.
+ if(devinfo->use != XIMasterKeyboard && devinfo->use != XISlaveKeyboard)
+ continue;
+
+ int nprops;
+ Atom* props = getDeviceProperties(dpy, devinfo, &nprops);
+ if(props)
+ {
+ for(int j = 0; j < nprops && xkbDeviceId == XkbUseCoreKbd; j++)
+ {
+ Atom prop = props[j];
+ if(prop == xtestDeviceProp)
+ {
+ // The device is the XTest Keyboard:
+ xkbDeviceId = devinfo->deviceid;
+ }
+ }
+ XFree(props);
+ }
+ }
+ XIFreeDeviceInfo(devinfos);
+#ifdef deviceid /* XInput1 */
+# undef deviceid
+#endif
+ }
+ }
+#endif /* HAVE_XINPUT_H || HAVE_XINPUT2_H */
+
+ // at this point, xkbDeviceId contains the identifier
+ // of the XTEST Device, or xkbUseCoreKbd if none was
+ // found.
+
+ // Okay, we know which device to query. Now get its keymap:
+ XkbDescPtr keybDesc = XkbGetKeyboard(dpy, XkbAllComponentsMask, xkbDeviceId);
+ if(!keybDesc)
+ {
+ qWarning("Unable to retrieve keyboard description for device %d. Falling back to unreliable global mapping", xkbDeviceId);
+ }
+
+ // This is basically the same loop as above, it just queries XKB
+ // instead of the old core Xlib routines.
+ for(int i = minKeycode; i <= maxKeycode; i++)
+ {
+ for(int j = 0; j <= 0xff; j++)
+ {
+ XModifiers mods = modifierpriority[j];
+ KeySym ks = 0;
+ unsigned int unconsumed;
+ if(keybDesc)
+ {
+ if(!XkbTranslateKeyCode(keybDesc, i, mods, &unconsumed, &ks) || ks == NoSymbol)
+ continue;
+ }
+ else
+ {
+ if(!XkbLookupKeySym(dpy, i, mods, &unconsumed, &ks) || ks == NoSymbol)
+ continue;
+ }
+
+ if(knownKeySyms.find(ks) != knownKeySyms.end())
+ {
+ if(mods & ~unconsumed)
+ {
+ // we would be recording extraneous modifiers
+ continue;
+ }
+
+ if(keysymInfos.find(ks) != keysymInfos.end())
+ continue;
+
+ KeySymInfo info;
+ info.keycode = i;
+ info.neededModifiers = mods & unconsumed;
+ info.modifierMask = unconsumed;
+ keysymInfos[ks] = info;
+
+ ConsoleLog writeLine(QString("%1 %2 %3 %4")
+ .arg(i, 3)
+ .arg(modifiersToString(info.neededModifiers), 40)
+ .arg(modifiersToString(info.modifierMask), 40)
+ .arg(XKeysymToString(ks)));
+ }
+
+ if(j == 0)
+ {
+ switch(ks)
+ {
+ case XK_Shift_L:
+ case XK_Shift_R:
+ recordModifierMapping(keybDesc, i, Qt::ShiftModifier);
+ break;
+ case XK_Control_L:
+ case XK_Control_R:
+ recordModifierMapping(keybDesc, i, Qt::ControlModifier);
+ break;
+ case XK_Meta_L:
+ case XK_Meta_R:
+ recordModifierMapping(keybDesc, i, Qt::MetaModifier);
+ break;
+ case XK_Alt_L:
+ case XK_Alt_R:
+ recordModifierMapping(keybDesc, i, Qt::AltModifier);
+ break;
+ case XK_ISO_Level3_Shift:
+ recordModifierMapping(keybDesc, i, Qt::GroupSwitchModifier);
+ break;
+ }
+ }
+ }
+ }
+
+ // Free the keyboard description:
+ if(keybDesc)
+ {
+ XkbFreeKeyboard(keybDesc, XkbAllComponentsMask, true);
+ }
+ }
+#endif /* HAVE_XKBLIB_H */
+
+ ConsoleLog writeLine("After initialization, XToQtModifier has the following entries:");
+ for(XToQtModifierMap::const_iterator i = XToQtModifier.begin();
+ i != XToQtModifier.end();
+ i++)
+ {
+ ConsoleLog writeLine(QString(" %1 %2").arg(i->first, 2, 16).arg(i->second, 8, 16));
+ }
+}
+
+// Translate a Qt KeyboardModifiers flag to
+// its corresponding X11 modifier bitmask
+XModifiers translateModifiers(quint32 mods)
+{
+ XModifiers ret = 0;
+
+ for(int j = 0; j < 8; j++) {
+ XModifiers i = 1<<j;
+
+ if(mods & XToQtModifier[i])
+ {
+ ret |= i;
+ }
+ }
+
+ return ret;
+}
+
+// We need to keep track of which modifiers
+// are currently active
+typedef std::set<int> IntSet;
+IntSet pressedModifierKeys;
+XModifiers currentModifiers = 0;
+
+void trackModifiers(int keycode, bool down)
+{
+ // is this a modifier key?
+ const bool isModifier = KeycodeToModifier.find(keycode) != KeycodeToModifier.end();
+
+ if(!isModifier)
+ {
+ return;
+ }
+
+ if(down) {
+ pressedModifierKeys.insert(keycode);
+ } else {
+ pressedModifierKeys.erase(keycode);
+ }
+
+ IntSet::iterator i, end = pressedModifierKeys.end();
+ XModifiers modifs = 0;
+ for(i = pressedModifierKeys.begin(); i != end; i++)
+ {
+ KeycodeToModifierMap::iterator foundCode = KeycodeToModifier.find(*i);
+ if(foundCode != KeycodeToModifier.end())
+ {
+ modifs |= (*foundCode).second;
+ }
+ }
+ currentModifiers = modifs;
+
+ ConsoleLog writeLine(QString("[trackModifiers] current modifiers: %1").arg(modifiersToString(modifs)));
+}
+
+// And, if we need to tweak the modifiers to generate
+// a particular keysym, we need to keep track of which
+// ones we pressed or released.
+typedef std::pair<int, bool> ModifierTweak;
+typedef std::vector<ModifierTweak> TweakSequence;
+
+// Tweak the modifiers to reach the neededState, from actualState
+// and record tweaks in the tracker.
+void tweakModifiers(Display* dpy, XModifiers neededState, XModifiers actualState, TweakSequence& tracker)
+{
+ if(neededState == actualState)
+ // nothing to do.
+ return;
+
+ ConsoleLog writeLine(QString("tweakModifiers: Trying to get to `%1' from `%2'").arg(modifiersToString(neededState)).arg(modifiersToString(actualState)));
+ for(int j = 0; j < 8; j++)
+ {
+ XModifiers i = 1<<j;
+
+ // Do we need to activate the modifier?
+ if((i & neededState) && !(i & actualState))
+ {
+ ConsoleLog writeLine(QString("tweakModifiers: Modifier %1 needs to be pressed").arg(modifiernames[j]));
+
+ //find the keycode
+ ModifierToKeycodeMap::iterator iter = ModifierToKeycode.find(i);
+
+ if((iter == ModifierToKeycode.end()) || ((*iter).first != i))
+ {
+ // we don't know a key that triggers this modifier
+ continue;
+ }
+
+ XTestFakeKeyEvent(dpy, (*iter).second, 1, CurrentTime);
+
+ // record the tweak
+ tracker.push_back(std::make_pair((*iter).second, true));
+ }
+ // or do we need to deactivate it?
+ else if((!(i & neededState)) && (i & actualState))
+ {
+ ConsoleLog writeLine(QString("tweakModifiers: Modifier %1 needs to be released").arg(modifiernames[j]));
+
+ int kc = -1;
+
+ // first, check whether any of the currently pressed keys has triggered this modifier:
+ IntSet::iterator iter, end = pressedModifierKeys.end();
+ for(iter = pressedModifierKeys.begin(); iter != end; iter++)
+ {
+ KeycodeToModifierMap::iterator modmapIter = KeycodeToModifier.find(*iter);
+ if(modmapIter != KeycodeToModifier.end()) {
+ if(modmapIter->second == i) {
+ kc = *iter;
+
+ // release this key:
+ XTestFakeKeyEvent(dpy, kc, 0, CurrentTime);
+ tracker.push_back(std::make_pair(kc, false));
+ }
+ }
+ }
+
+ if(kc == -1) {
+ // strange, but we need to release some other key:
+ // we don't know which one, so we abort this and hope for the best
+ continue;
+ }
+ }
+ }
+}
+
+// Undo a recorded sequence of modifier tweaks
+void untweakModifiers(Display* dpy, TweakSequence& tracker)
+{
+ TweakSequence::reverse_iterator i, end = tracker.rend();
+ for(i = tracker.rbegin(); i != end; i++) {
+ ModifierTweak& t = *i;
+ XTestFakeKeyEvent(dpy, t.first, !t.second, CurrentTime);
+ }
+}
+
+// initialize the handler
+void X11FakeKeyboardHandler::initialize()
+{
+ initializeKeycodeLookupTable();
+ initializeBasicKeycodes();
+ pressedModifierKeys.clear();
+ currentModifiers = 0;
+}
+
+// actually try our best to generate the correct input sequence
+// for the event
+void X11FakeKeyboardHandler::doHandle(InputEvent const& evt, InputEventContext const*)
+{
+ Display* dpy = X11InputUtils::display();
+
+ XTestGrabControl(dpy, 1);
+
+ // find out which keysym caused this event:
+ KeycodeLookupTable::const_iterator i = keysyms.find(evt.qtKeysym());
+ if(i == keysyms.end()) {
+ // Special cases. We don't know how to directly translate those, so we will try to emulate them.
+ ConsoleLog writeLine(QString("Unknown keysym received: %1").arg(evt.qtKeysym(), 8, 16));
+ } else {
+ KeySym ks = (*i).second;
+
+ KeySymToInfoMap::const_iterator infoIter = keysymInfos.find(ks);
+ if(infoIter != keysymInfos.end())
+ {
+ KeySymInfo info = infoIter->second;
+
+ if(evt.isPress())
+ {
+ QString format = "Trying to press the key for %1 with modifiers %2 (X: %3, Qt: %4), while current modifiers are %5 and needed are %6 with mask %7";
+ if(ks >= ' ' && ks < 0x100)
+ {
+ ConsoleLog writeLine(format
+ .arg((char)ks)
+ .arg(modifiersToString(translateModifiers(evt.qtModifiers())))
+ .arg(translateModifiers(evt.qtModifiers()), 2, 16)
+ .arg(evt.qtModifiers(), 8, 16)
+ .arg(modifiersToString(currentModifiers))
+ .arg(modifiersToString(info.neededModifiers))
+ .arg(modifiersToString(info.modifierMask)));
+ }
+ else
+ {
+ ConsoleLog writeLine(format
+ .arg(XKeysymToString(ks))
+ .arg(modifiersToString(translateModifiers(evt.qtModifiers())))
+ .arg(translateModifiers(evt.qtModifiers()), 2, 16)
+ .arg(evt.qtModifiers(), 8, 16)
+ .arg(modifiersToString(currentModifiers))
+ .arg(modifiersToString(info.neededModifiers))
+ .arg(modifiersToString(info.modifierMask)));
+ }
+
+ // what modifier keys do we need to press?
+ XModifiers mods = translateModifiers(evt.qtModifiers());
+ XModifiers needed = info.neededModifiers;
+ XModifiers mask = info.modifierMask;
+
+ // This is quite ad-hoc, but we do NOT want to
+ // mask Alt.
+ // On some configurations, the F-Keys consume Alt,
+ // and when we AND it out, we disable Alt+Fn
+ // combinations. That's just wrong.
+ // FIXME: Are there situations
+ // where we actually need to keep Alt masked?
+ // Hint: I found none.
+ // If so, how do we determine that?
+ QtToXModifierMap::const_iterator altIter = QtToXModifier.find(Qt::AltModifier);
+ if(altIter != QtToXModifier.end())
+ {
+ mask &= ~(altIter->second);
+ }
+
+ // Determine which modifiers actually need to be active
+ XModifiers neededMods;
+ neededMods = (mods
+ & (needed | ~mask)) // Cleer the needed-clear modifiers
+ | (needed & mask); // Set the needed-set modifiers
+
+ // Modifiers need to be tracked BEFORE tweaking, as we may be
+ // pressing a modifier key, and we don't want to release it
+ // when untweaking.
+ trackModifiers(info.keycode, true);
+
+ // now, tweak the modifiers
+ TweakSequence tweaks;
+ tweakModifiers(dpy, neededMods, currentModifiers, tweaks);
+
+ // press the key:
+ XTestFakeKeyEvent(dpy, info.keycode, 1, CurrentTime);
+
+ // and release the modifiers:
+ untweakModifiers(dpy, tweaks);
+ }
+ else
+ {
+ // just release the key.
+ XTestFakeKeyEvent(dpy, info.keycode, 0, CurrentTime);
+ trackModifiers(info.keycode, false);
+ }
+ }
+ else
+ {
+ ConsoleLog writeLine(QString("No keycode is mapped to `%1'").arg(XKeysymToString(ks)));
+ }
+ }
+
+ XTestGrabControl(dpy, 0);
+
+ // Since there may not be a mainloop running, we need to manually flush the event queue
+ XFlush(dpy);
+}
diff --git a/src/input/x11FakeKeyboardHandler.h b/src/input/x11FakeKeyboardHandler.h
new file mode 100644
index 0000000..7f2d12e
--- /dev/null
+++ b/src/input/x11FakeKeyboardHandler.h
@@ -0,0 +1,40 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # x11FakeKeyboardHandler.h:
+ # - Handle keyboard events on X11 - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef X11FAKEKEYBOARDHANDLER_H_
+#define X11FAKEKEYBOARDHANDLER_H_
+
+#include "inputEventHandler.h"
+
+/**
+ * Send keyboard events via the XTest extension.
+ * This is unbelievably brittle in the face of non-system-standard keyboard
+ * mappings. Every Linux distribution seems to set up XTest handling in
+ * a different way. The code goes out of its way to find a usable mapping
+ * and use it.
+ */
+class X11FakeKeyboardHandler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_KEY, InputEvent::EC_PRESS>,
+ input_policy::Match<InputEvent::ET_KEY, InputEvent::EC_RELEASE>,
+ input_policy::Require<input_policy::X11GUI>,
+ input_policy::Unprivileged>
+{
+public:
+ void doHandle(InputEvent const&, InputEventContext const* = 0);
+ void initialize();
+};
+
+#endif /* X11FAKEKEYBOARDHANDLER_H_ */
diff --git a/src/input/x11FakeMouseHandler.cpp b/src/input/x11FakeMouseHandler.cpp
new file mode 100644
index 0000000..605fe2c
--- /dev/null
+++ b/src/input/x11FakeMouseHandler.cpp
@@ -0,0 +1,59 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # x11FakeMouseHandler.h:
+ # - Handle mouse events on X11 - implementation
+ # --------------------------------------------------------------------------
+ */
+
+#include "x11FakeMouseHandler.h" // need to include before X headers
+#include <src/util/consoleLogger.h>
+#include <X11/extensions/XTest.h>
+#include "x11InputUtils.h"
+
+void X11FakeMouseButtonHandler::doHandle(InputEvent const& evt, InputEventContext const*)
+{
+ quint16 pressedButton = evt.pressedButton();
+
+ Display* dpy = X11InputUtils::display();
+
+ XTestGrabControl(dpy, 1);
+ for(int i = 0; i < 16; i++) {
+ if((1<<i) == pressedButton)
+ {
+ ConsoleLog writeLine(QString("Got mouse button event: button %1 %2").arg(i + 1).arg(evt.isPress() ? "pressed" : "released"));
+ if(!XTestFakeButtonEvent(dpy, i + 1, evt.isPress(), CurrentTime))
+ {
+ ConsoleLog writeLine("[ERROR] XTestFakeButtonEvent failed");
+ }
+ }
+ }
+ XTestGrabControl(dpy, 0);
+
+ // Since there may not be a mainloop running, we need to manually flush the event queue
+ XFlush(dpy);
+}
+
+void X11FakeMouseMovementHandler::doHandle(InputEvent const& evt, InputEventContext const*)
+{
+ ConsoleLog writeLine(QString("Received mouse motion event (%1,%2)").arg(evt.xCoord()).arg(evt.yCoord()));
+ Display* dpy = X11InputUtils::display();
+ int screen = 0 /* DefaultScreen(dpy) */;
+ XTestGrabControl(dpy, 1);
+ if(!XTestFakeMotionEvent(dpy, screen, evt.xCoord(), evt.yCoord(), CurrentTime))
+ {
+ ConsoleLog writeLine("[ERROR] XTestFakeMotionEvent failed");
+ }
+ XTestGrabControl(dpy, 0);
+
+ // Since there may not be a mainloop running, we need to manually flush the event queue
+ XFlush(dpy);
+}
diff --git a/src/input/x11FakeMouseHandler.h b/src/input/x11FakeMouseHandler.h
new file mode 100644
index 0000000..2700829
--- /dev/null
+++ b/src/input/x11FakeMouseHandler.h
@@ -0,0 +1,46 @@
+/*
+ # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # --------------------------------------------------------------------------
+ # x11FakeMouseHandler.h:
+ # - Handle mouse events on X11 - interface
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef X11FAKEMOUSEHANDLER_H_
+#define X11FAKEMOUSEHANDLER_H_
+
+#include "inputEventHandler.h"
+
+/**
+ * Send mouse button events via the XTest extension.
+ */
+class X11FakeMouseButtonHandler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_BUTTON>,
+ input_policy::Require<input_policy::X11GUI>,
+ input_policy::Unprivileged>
+{
+public:
+ void doHandle(InputEvent const&, InputEventContext const* = 0);
+};
+
+/**
+ * Send mouse pointer events via the XTest extension.
+ */
+class X11FakeMouseMovementHandler : public InputEventHandler<
+ input_policy::Match<InputEvent::ET_POINTER>,
+ input_policy::Require<input_policy::X11GUI>,
+ input_policy::Unprivileged>
+{
+public:
+ void doHandle(InputEvent const&, InputEventContext const* = 0);
+};
+
+#endif /* X11FAKEMOUSEHANDLER_H_ */
diff --git a/src/input/x11InputUtils.cpp b/src/input/x11InputUtils.cpp
new file mode 100644
index 0000000..b589bd6
--- /dev/null
+++ b/src/input/x11InputUtils.cpp
@@ -0,0 +1,29 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # ------------------------------------------------------------------------
+ # src/input/x11InputUtils.h:
+ # Utilities for input handling under X11 - implementation
+ */
+
+#include "x11InputUtils.h"
+
+static Display* _dpy = 0;
+
+void X11InputUtils::setDisplay(Display* dpy)
+{
+ _dpy = dpy;
+}
+
+Display* X11InputUtils::display()
+{
+ return _dpy;
+}
diff --git a/src/input/x11InputUtils.h b/src/input/x11InputUtils.h
new file mode 100644
index 0000000..94b3116
--- /dev/null
+++ b/src/input/x11InputUtils.h
@@ -0,0 +1,30 @@
+/*
+ # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
+ # Freiburg
+ #
+ # This program is free software distributed under the GPL version 2.
+ # See http://openslx.org/COPYING
+ #
+ # If you have any feedback please consult http://openslx.org/feedback and
+ # send your suggestions, praise, or complaints to feedback@openslx.org
+ #
+ # General information about OpenSLX can be found at http://openslx.org/
+ # ------------------------------------------------------------------------
+ # src/input/x11InputUtils.h:
+ # Utilities for input handling under X11 - interface
+ */
+
+#ifndef X11INPUTUTILS_H_
+#define X11INPUTUTILS_H_
+
+#include <X11/Xlib.h>
+
+/**
+ * Store the X11 Display.
+ */
+struct X11InputUtils {
+ static void setDisplay(Display*);
+ static Display* display();
+};
+
+#endif /* X11INPUTUTILS_H_ */
diff --git a/src/pvs.cpp b/src/pvs.cpp
index cd9ed2d..755eea5 100755
--- a/src/pvs.cpp
+++ b/src/pvs.cpp
@@ -19,6 +19,9 @@
#include "src/net/pvsMsg.h"
#include "src/net/pvsServiceDiscovery.h"
#include "src/net/pvsDiscoveredServer.h"
+#include "src/input/inputEvent.h"
+#include "src/input/inputHandlerChains.h"
+#include "src/input/x11InputUtils.h"
#include "src/net/mcast/McastConfiguration.h"
#include "src/net/pvsOutgoingMulticastTransfer.h"
#include "src/net/pvsIncomingMulticastTransfer.h"
@@ -90,6 +93,8 @@ PVS::PVS() :
sigaction(SIGHUP, &act, 0);
sigaction(SIGINT, &act, 0);
sigaction(SIGQUIT, &act, 0);
+
+ initializeInputEventHandling();
#endif /*__WIN32__*/
}
@@ -191,6 +196,15 @@ void PVS::onCommand(PVSMsg cmdMessage)
unlock();
return;
}
+ if (ident.compare("INPUTEVENT") == 0)
+ {
+ InputEvent evt;
+ if(inputEventsAllowed())
+ {
+ eventFromString(message, evt);
+ handleInputEvent(evt);
+ }
+ }
if (ident.compare("MCASTFTRETRY") == 0)
{
QStringList fields = message.split(':');
@@ -248,15 +262,21 @@ void PVS::onCommand(PVSMsg cmdMessage)
}
if (ident.compare("SHOWPROCESSES") == 0)
{
- // do stuff to show processes
- // to test if SHOWPROCESSES command is submitted correct uncomment following lines
- // a messagebox will appear on the client
- // emit showMessage("Show Processes", "", true);
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PROCESSES", "SHOW clear")); //tell the client that we want to clear his process-list
+ showProc();
return;
}
+ if (ident.compare("STARTPROCESS") == 0)
+ {
+ QProcess *proc = new QProcess( this );
+ proc->start(message); //we try to run the process with the name message
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PROCESSES", "START Process "+message+": started"));
+ return;
+ }
if (ident.compare("KILLPROCESS") == 0)
{
- // do stuff to kill a process
+ QProcess *proc = new QProcess( this );
+ proc->start("kill "+message); //we try to kill the process with the given ID
return;
}
@@ -736,6 +756,28 @@ bool PVS::createMulticastTransfer(QString const& objectPath, quint64& transferID
return true;
}
+// Input handling
+
+bool PVS::inputEventsAllowed()
+{
+ QString lecturer = getConfigValue("Permissions/vnc_lecturer");
+ return lecturer == "rw";
+}
+
+void PVS::handleInputEvent(InputEvent const& evt)
+{
+ QString s = evt.toString();
+ ConsoleLog writeLine(QString("Received input event: %1").arg(s.toLocal8Bit().constData()));
+ _inputEventHandlers.handle(evt);
+}
+
+void PVS::initializeInputEventHandling()
+{
+ X11InputUtils::setDisplay(X11Info::display());
+ _inputEventHandlers = makeUnprivilegedInputEventHandlerChain();
+ _inputEventHandlers.initialize();
+}
+
void PVS::cancelOutgoingMulticastTransfer(quint64 transferID)
{
PVSOutgoingMulticastTransfer* transfer = _outgoingTransfers.value(transferID, 0);
@@ -892,3 +934,71 @@ QString PVS::getConfigValue(QString key)
{
return _settings.value(key).toString();
}
+
+void PVS::showProc()
+{
+ //look at procfs
+ QDir procfs("/proc");
+ QStringList proc = procfs.entryList();
+ int uid = getuid();
+ bool write;
+
+ for (int i=0;i<proc.length();i++) //every directory in /proc is checked
+ {
+ write = false;
+ QString tmp = proc.at(i);
+ QString snd = "";
+ if (!tmp.contains(QRegExp("\\D"))) //we have to check if name is number
+ {
+ QString name = "";
+ QFile file("/proc/"+tmp+QString("/status")); //read status file
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ return;
+
+ QTextStream in(&file);
+ QString line = in.readLine();
+ while (!line.isNull())
+ {
+ if (line.startsWith("Name:")) //to get the name of our process
+ {
+ name = line.remove(0,6);
+ snd.append(tmp).append(QString("<#>")).append(line).append("<#>");
+ //lets check if the process belongs to our PVS better not to show it if we dont want to crash PVS
+ } else if (line.startsWith("Gid:")) //and to check that the process is a user process
+ //we had to read name first because every file in /proc
+ //has size 0 byte
+ {
+ line.remove(0,5);
+ if (line.startsWith(QString::number(uid)))
+ write = true;
+ else break;
+
+ }
+ line = in.readLine();
+ }
+ if (write)
+ {
+ if ((name.startsWith("pvs")) || (name.startsWith("dbus")))
+ write = false;
+ }
+ if (write) //if process belongs to user (and not to PVS) we go on
+ {
+ QFile file("/proc/"+tmp+QString("/cmdline")); //and read cmdline
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ return;
+
+ QTextStream in(&file);
+ QString line = in.readLine();
+ while (!line.isNull())
+ {
+ int templength = snd.length()+3;
+ snd.append(line.left(150+templength)); //but only up to a length of 150-name-id-seperators
+ break;
+ }
+ }
+ if (write) //if process belongs to user we send the line to client
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PROCESSES", "SHOW "+snd));
+ }
+ }
+ _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PROCESSES", "SHOW finished")); //at the end we send that every process has been sent
+}
diff --git a/src/pvs.h b/src/pvs.h
index 5c35a0e..db87b8e 100755
--- a/src/pvs.h
+++ b/src/pvs.h
@@ -26,9 +26,14 @@
#include "src/version.h"
#include "src/util/consoleLogger.h"
#include "src/util/clientGUIUtils.h"
+#include <QFile>
+#include <QTextStream>
+#include <QDir>
+#include "src/input/inputEventHandler.h"
class PVSServiceDiscovery;
class PVSDiscoveredServer;
+class InputEvent;
class McastConfiguration;
class PVSOutgoingMulticastTransfer;
class PVSIncomingMulticastTransfer;
@@ -154,6 +159,8 @@ private:
int stopVNCScript(); ///< stop the vnc server (via script)
static void signalHandler(int signal); //handles posix signals
+ void showProc(); //sends list of user processes to connection manager
+
PVSServerConnection* _pvsServerConnection; ///< our tcp connection object to the pvsserver
PVSServiceDiscovery *_sdClient;
@@ -165,6 +172,13 @@ private:
int _timerLockTest;
int _timerLockDelay;
+ // input event handling:
+ InputEventHandlerChain _inputEventHandlers;
+ bool inputEventsAllowed();
+ void handleInputEvent(InputEvent const& evt);
+ void initializeInputEventHandling();
+
+ // multicast transfer
McastConfiguration* _masterMcastConfig;
QHash<quint64, PVSOutgoingMulticastTransfer*> _outgoingTransfers;
QHash<quint64, PVSIncomingMulticastTransfer*> _incomingTransfers;
diff --git a/src/pvsDaemon.cpp b/src/pvsDaemon.cpp
index 4918a60..1784a14 100644
--- a/src/pvsDaemon.cpp
+++ b/src/pvsDaemon.cpp
@@ -64,6 +64,9 @@ int main(int argc, char** argv)
bool _daemon = false;
int frequency = 5;
int port = -1;
+#ifdef as_daemon
+ bool no_fork = false;
+#endif
QCoreApplication app(argc, argv);
app.setOrganizationName("openslx");
@@ -119,6 +122,9 @@ int main(int argc, char** argv)
{ "freq", required_argument, 0, 'f' },
{ "client", required_argument, 0, 'e' },
{ "script", required_argument, 0, 's' },
+#ifdef as_daemon
+ { "no-fork", no_argument, 0, 'F' },
+#endif
{ 0, 0, 0, 0 },
};
/* getopt_long stores the option index here. */
@@ -226,6 +232,13 @@ int main(int argc, char** argv)
}
break;
}
+#ifdef as_daemon
+ case 'F':
+ {
+ no_fork = true;
+ break;
+ }
+#endif
case '?':
{
ConsoleLog writeError(
diff --git a/src/pvsgui.cpp b/src/pvsgui.cpp
index eb1383b..1520c81 100644
--- a/src/pvsgui.cpp
+++ b/src/pvsgui.cpp
@@ -450,24 +450,6 @@ void printVersion()
int main(int argc, char *argv[])
{
- QtSingleApplication app(argc, argv);
- app.setQuitOnLastWindowClosed(false);
- app.setOrganizationName("openslx");
- app.setOrganizationDomain("openslx.org");
- app.setApplicationName("pvsgui");
-
- // only one instance should be allowed
- if (app.sendMessage(""))
- {
- qDebug("[PVSGUI] ERROR: Already running. Exiting");
- return 0;
- }
-
- // use system locale as language to translate gui
- QTranslator translator;
- translator.load(":pvsgui");
- app.installTranslator(&translator);
-
bool visible = false;
int position = -1;
@@ -506,6 +488,25 @@ int main(int argc, char *argv[])
opt = getopt_long( argc, argv, optString, longOpts, &longIndex );
}
+
+ QtSingleApplication app(argc, argv);
+ app.setQuitOnLastWindowClosed(false);
+ app.setOrganizationName("openslx");
+ app.setOrganizationDomain("openslx.org");
+ app.setApplicationName("pvsgui");
+
+ // only one instance should be allowed
+ if (app.sendMessage(""))
+ {
+ qDebug("[PVSGUI] ERROR: Already running. Exiting");
+ return 0;
+ }
+
+ // use system locale as language to translate gui
+ QTranslator translator;
+ translator.load(":pvsgui");
+ app.installTranslator(&translator);
+
PVSGUI pvsgui;
pvsgui.setPosition(position);
pvsgui.setVisible(visible);
diff --git a/src/pvsmgr.cpp b/src/pvsmgr.cpp
index dd00c0e..f543c6d 100644
--- a/src/pvsmgr.cpp
+++ b/src/pvsmgr.cpp
@@ -19,6 +19,7 @@
#include "gui/mainWindow.h"
#include "util/consoleLogger.h"
#include "util/CertManager.h"
+#include "src/input/i18n.h"
QApplication *qtApp;
@@ -35,6 +36,8 @@ int main(int argc, char** argv)
translator.load(":pvsmgr");
qtApp->installTranslator(&translator);
+ USE_PVSINPUT_TRANSLATIONS;
+
ConsoleLog setLogName(QString("log.server"));
ConsoleLog writeLine(QString("PVS-Server started."));
diff --git a/src/pvsmgrtouch.cpp b/src/pvsmgrtouch.cpp
index d14ea56..4a1a97d 100644
--- a/src/pvsmgrtouch.cpp
+++ b/src/pvsmgrtouch.cpp
@@ -18,6 +18,7 @@
#include <QtGui/QDesktopServices>
#include "util/consoleLogger.h"
#include "util/CertManager.h"
+#include "src/input/i18n.h"
QApplication *qtApp;
@@ -34,6 +35,8 @@ int main(int argc, char** argv)
translator.load(":pvsmgr");
qtApp->installTranslator(&translator);*/
+ USE_PVSINPUT_TRANSLATIONS;
+
ConsoleLog setLogName(QString("log.server"));
ConsoleLog writeLine(QString("PVS-Server started."));
diff --git a/src/util/clientGUIUtils.cpp b/src/util/clientGUIUtils.cpp
index 4d4cc0d..ff002d3 100644
--- a/src/util/clientGUIUtils.cpp
+++ b/src/util/clientGUIUtils.cpp
@@ -2,7 +2,7 @@
BlankScreen::BlankScreen()
{
- dpy = XOpenDisplay(NULL);
+ dpy = X11Info::display();
scr = DefaultScreen(dpy);
assert(dpy);
blackColor = BlackPixel(dpy, DefaultScreen(dpy));
@@ -142,3 +142,4 @@ bool BlankScreen::unlock()
lockMsg.clear();
return !(locked = false);
}
+
diff --git a/src/util/clientGUIUtils.h b/src/util/clientGUIUtils.h
index b04d3fe..7f7ea47 100755
--- a/src/util/clientGUIUtils.h
+++ b/src/util/clientGUIUtils.h
@@ -25,4 +25,14 @@ private:
BlankScreen_Sysdep* _sysdep;
};
-#endif \ No newline at end of file
+#ifndef __WIN32__
+# include <X11/Xlib.h>
+
+class X11Info
+{
+public:
+ static Display* display();
+};
+#endif /* !__WIN32__ */
+
+#endif
diff --git a/src/util/clientGUIUtils_X11.cpp b/src/util/clientGUIUtils_X11.cpp
index 29c96f0..4b5afe0 100755
--- a/src/util/clientGUIUtils_X11.cpp
+++ b/src/util/clientGUIUtils_X11.cpp
@@ -166,3 +166,14 @@ bool BlankScreen::unlock()
_sysdep->lockMsg.clear();
return !(_sysdep->locked = false);
}
+
+static Display* _dpy = 0;
+
+Display* X11Info::display()
+{
+ if(!_dpy)
+ {
+ _dpy = XOpenDisplay(0);
+ }
+ return _dpy;
+}
diff --git a/src/version.h b/src/version.h
index de5c6aa..a08c819 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1,2 +1,2 @@
-#define VERSION_STRING "2.0.5"
-#define VERSION_NUMBER 205
+#define VERSION_STRING "2.8.0"
+#define VERSION_NUMBER 280