Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nx-libs
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
dimbor
nx-libs
Commits
df79c3b3
You need to sign in or sign up before continuing.
Unverified
Commit
df79c3b3
authored
Mar 01, 2019
by
Mike Gabriel
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'uli42-pr/add_nxdialog' into 3.6.x
Attributes GH PR #767:
https://github.com/ArcticaProject/nx-libs/pull/767
parents
4538d213
d0e40f8b
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
394 additions
and
0 deletions
+394
-0
nxdialog
nxdialog/nxdialog
+394
-0
No files found.
nxdialog/nxdialog
0 → 100755
View file @
df79c3b3
#!/usr/bin/env python
#
# ^^^ This is working with python2 and python3 so we choose a shebang
# that will find either version.
# Citing PEP394: "One exception to this is scripts that are
# deliberately written to be source compatible with both Python
# 2.x and 3.x. Such scripts may continue to use python on their
# shebang line.
# Copyright (C) 2008 Google Inc.
# Copyright (C) 2019 Ulrich Sibiller <uli42@gmx.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
# This version is based on the nxdialog.py of the long abandoned
# Google project "neatx" (https://code.google.com/archive/p/neatx/).
# List of changes:
# - pulled in the few parts of the neatx python modules that are actually
# to make it a standlone script
# - added usage output
# - dropped logging code, print errors to stderr
# - can handle the "yesno" dialog type
# - added missing docstrings
# - pylint improvements
# - removed neatx entry from the pulldoww menu
# - use PyGObject instead of PyGtk and thus Gtk3
# - replace optparse by argparse
# - make code compatible to python2 and python3.
"""nxdialog program for handling dialog display."""
# If an "NX_CLIENT" environment variable is not provided to nxagent
# nxcomp library assumes this script is located in /usr/NX/bin/nxclient
#
# Example:
# nxdialog --dialog yesno --message "message text" --caption "message title" --parent 0
from
__future__
import
print_function
import
argparse
import
os
import
signal
import
sys
import
gi
gi
.
require_version
(
'Gtk'
,
'3.0'
)
# pylint: disable=wrong-import-position
from
gi.repository
import
Gtk
,
Gdk
,
GdkX11
PROGRAM
=
"nxdialog"
DISCONNECT
=
1
TERMINATE
=
2
EXIT_SUCCESS
=
0
EXIT_FAILURE
=
1
CANCEL_TEXT
=
"Cancel"
DISCONNECT_TEXT
=
"Disconnect"
TERMINATE_TEXT
=
"Terminate"
YES_TEXT
=
"Yes"
NO_TEXT
=
"No"
DLG_TYPE_ERROR
=
"error"
DLG_TYPE_OK
=
"ok"
DLG_TYPE_PANIC
=
"panic"
DLG_TYPE_PULLDOWN
=
"pulldown"
DLG_TYPE_QUIT
=
"quit"
DLG_TYPE_YESNO
=
"yesno"
DLG_TYPE_YESNOSUSPEND
=
"yesnosuspend"
VALID_DLG_TYPES
=
frozenset
([
DLG_TYPE_ERROR
,
DLG_TYPE_OK
,
DLG_TYPE_PANIC
,
DLG_TYPE_PULLDOWN
,
DLG_TYPE_QUIT
,
DLG_TYPE_YESNO
,
DLG_TYPE_YESNOSUSPEND
,
])
class
PullDownMenu
(
object
):
""" Shows a popup menu to disconnect/terminate session. """
def
__init__
(
self
,
window_id
):
""" Initializes this class.
@type window_id: int
@param window_id: X11 window id of target window
"""
self
.
window_id
=
window_id
self
.
result
=
None
def
show
(
self
):
""" Shows popup and returns result. """
display
=
Gdk
.
Display
.
get_default
()
win
=
GdkX11
.
X11Window
.
foreign_new_for_display
(
display
,
self
.
window_id
)
menu
=
Gtk
.
Menu
()
menu
.
connect
(
"deactivate"
,
self
.
menu_deactivate
)
# TODO: Show title item in bold font
title
=
Gtk
.
MenuItem
(
label
=
"Session control"
)
title
.
set_sensitive
(
False
)
menu
.
append
(
title
)
disconnect
=
Gtk
.
MenuItem
(
label
=
DISCONNECT_TEXT
)
disconnect
.
connect
(
"activate"
,
self
.
item_activate
,
DISCONNECT
)
menu
.
append
(
disconnect
)
terminate
=
Gtk
.
MenuItem
(
label
=
TERMINATE_TEXT
)
terminate
.
connect
(
"activate"
,
self
.
item_activate
,
TERMINATE
)
menu
.
append
(
terminate
)
menu
.
append
(
Gtk
.
SeparatorMenuItem
())
cancel
=
Gtk
.
MenuItem
(
label
=
CANCEL_TEXT
)
menu
.
append
(
cancel
)
menu
.
show_all
()
menu
.
popup
(
parent_menu_shell
=
None
,
parent_menu_item
=
None
,
func
=
self
.
pos_menu
,
data
=
win
,
button
=
0
,
activate_time
=
Gtk
.
get_current_event_time
())
Gtk
.
main
()
return
self
.
result
def
item_activate
(
self
,
_
,
result
):
""" called when a menu item is selected """
self
.
result
=
result
Gtk
.
main_quit
()
@staticmethod
def
menu_deactivate
(
_
):
""" called when menu is deactivated """
Gtk
.
main_quit
()
@staticmethod
def
pos_menu
(
menu
,
_xpos
,
_ypos
,
*
data
):
""" Positions menu at the top center of the parent window. """
parent
=
data
[
0
]
# Get parent geometry and origin
_
,
_
,
win_width
,
_
=
parent
.
get_geometry
()
_
,
win_x
,
win_y
=
parent
.
get_origin
()
# Calculate width of menu
#menu_width = menu.get_preferred_width().natural_width
menu_width
=
menu
.
get_allocated_width
()
# Calculate center
center_x
=
int
(
win_x
+
((
win_width
-
menu_width
)
/
2
))
return
(
center_x
,
win_y
,
True
)
def
show_yes_no_suspend_box
(
title
,
text
):
""" Shows a message box to disconnect/terminate session.
@type title: str
@param title: Message box title
@type text: str
@param text: Message box text
@return: Choosen action
"""
dlg
=
Gtk
.
MessageDialog
(
type
=
Gtk
.
MessageType
.
QUESTION
,
flags
=
Gtk
.
DialogFlags
.
MODAL
)
dlg
.
set_title
(
title
)
dlg
.
set_markup
(
text
)
dlg
.
add_button
(
DISCONNECT_TEXT
,
DISCONNECT
)
dlg
.
add_button
(
TERMINATE_TEXT
,
TERMINATE
)
dlg
.
add_button
(
CANCEL_TEXT
,
Gtk
.
ResponseType
.
CANCEL
)
res
=
dlg
.
run
()
if
res
in
(
DISCONNECT
,
TERMINATE
):
return
res
# Everything else is cancel
return
None
def
show_yes_no_box
(
title
,
text
):
""" Shows a message box with answers yes and no.
@type title: str
@param title: Message box title
@type text: str
@param text: Message box text
@return: Choosen action
"""
dlg
=
Gtk
.
MessageDialog
(
type
=
Gtk
.
MessageType
.
QUESTION
,
flags
=
Gtk
.
DialogFlags
.
MODAL
)
dlg
.
set_title
(
title
)
dlg
.
set_markup
(
text
)
dlg
.
add_button
(
YES_TEXT
,
TERMINATE
)
dlg
.
add_button
(
NO_TEXT
,
Gtk
.
ResponseType
.
CANCEL
)
res
=
dlg
.
run
()
if
res
==
TERMINATE
:
return
res
# Everything else is cancel
return
None
def
handle_session_action
(
agentpid
,
action
):
""" Execute session action choosen by user.
@type agentpid: int
@param agentpid: Nxagent process id as passed by command line
@type action: int or None
@param action: Choosen action
"""
if
action
==
DISCONNECT
:
print
(
"Disconnecting from session, sending SIGHUP to
%
s"
%
(
agentpid
))
if
agentpid
!=
0
:
os
.
kill
(
agentpid
,
signal
.
SIGHUP
)
elif
action
==
TERMINATE
:
print
(
"Terminating session, sending SIGTERM to process
%
s"
%
(
agentpid
))
if
agentpid
!=
0
:
os
.
kill
(
agentpid
,
signal
.
SIGTERM
)
elif
action
is
None
:
pass
else
:
raise
NotImplementedError
()
def
show_simple_message_box
(
icon
,
title
,
text
):
""" Shows a simple message box.
@type icon: QMessageBox.Icon
@param icon: Icon for message box
@type title: str
@param title: Message box title
@type text: str
@param text: Message box text
"""
dlg
=
Gtk
.
MessageDialog
(
type
=
icon
,
flags
=
Gtk
.
DialogFlags
.
MODAL
,
buttons
=
Gtk
.
ButtonsType
.
OK
)
dlg
.
set_title
(
title
)
dlg
.
set_markup
(
text
)
dlg
.
run
()
class
NxDialogProgram
(
object
):
""" the main program """
def
__init__
(
self
):
self
.
args
=
None
self
.
options
=
None
def
main
(
self
):
""" let's do something """
try
:
self
.
options
=
self
.
parse_args
()
self
.
run
()
except
(
SystemExit
,
KeyboardInterrupt
):
raise
except
Exception
as
expt
:
sys
.
stderr
.
write
(
"Caught exception:
%
s
\n
"
%
(
expt
))
sys
.
exit
(
EXIT_FAILURE
)
@staticmethod
def
parse_args
():
""" init parser """
parser
=
argparse
.
ArgumentParser
(
description
=
"Helper for nxagent to display dialogs"
)
# nxagent 3.5.99.18 only uses yesno, ok, pulldown and yesnosuspend
# yesno dialogs will always kill the session if "yes" is selected
parser
.
add_argument
(
"--dialog"
,
dest
=
"dialog_type"
,
help
=
'type of dialog to show, one of "yesno",
\
"ok", "error", "panic", "quit", "pulldown",
\
"yesnosuspend"'
)
parser
.
add_argument
(
"--message"
,
dest
=
"text"
,
help
=
"message text to display in the dialog"
)
parser
.
add_argument
(
"--caption"
,
dest
=
"caption"
,
help
=
"window title of the dialog"
)
parser
.
add_argument
(
"--display"
,
dest
=
"display"
,
help
=
"X11 display where the dialog should be
\
shown"
)
parser
.
add_argument
(
"--parent"
,
type
=
int
,
dest
=
"agentpid"
,
help
=
"pid of the nxagent"
)
parser
.
add_argument
(
"--window"
,
type
=
int
,
dest
=
"window"
,
help
=
"id of window where to embed the
\
pulldown dialog type"
)
# -class, -local, -allowmultiple are unused in nxlibs 3.5.99.18
parser
.
add_argument
(
"--class"
,
dest
=
"dlgclass"
,
default
=
"info"
,
help
=
"class of the message (info, warning, error)
\
default: info) [currently unimplemented]"
)
parser
.
add_argument
(
"--local"
,
action
=
"store_true"
,
dest
=
"local"
,
help
=
"specify that proxy mode is used
\
[currently unimplemented]"
)
parser
.
add_argument
(
"--allowmultiple"
,
action
=
"store_true"
,
dest
=
"allowmultiple"
,
help
=
"allow launching more than one dialog with
\
the same message [currently unimplemented]"
)
return
parser
.
parse_args
()
def
run
(
self
):
""" Disconnect/terminate NX session upon user's request. """
if
not
self
.
options
.
dialog_type
:
sys
.
stderr
.
write
(
"Dialog type not supplied via --type
\n
"
)
sys
.
exit
(
EXIT_FAILURE
)
dlgtype
=
self
.
options
.
dialog_type
if
dlgtype
not
in
VALID_DLG_TYPES
:
sys
.
stderr
.
write
(
"Invalid dialog type '
%
s'
\n
"
%
(
dlgtype
))
sys
.
exit
(
EXIT_FAILURE
)
if
dlgtype
in
(
DLG_TYPE_PULLDOWN
,
DLG_TYPE_YESNOSUSPEND
,
DLG_TYPE_YESNO
)
and
self
.
options
.
agentpid
is
None
:
sys
.
stderr
.
write
(
"Agent pid not supplied via --parent
\n
"
)
sys
.
exit
(
EXIT_FAILURE
)
if
dlgtype
==
DLG_TYPE_PULLDOWN
and
not
self
.
options
.
window
:
sys
.
stderr
.
write
(
"Window id not supplied via --window
\n
"
)
sys
.
exit
(
EXIT_FAILURE
)
if
self
.
options
.
caption
:
message_caption
=
self
.
options
.
caption
else
:
message_caption
=
sys
.
argv
[
0
]
if
self
.
options
.
text
:
message_text
=
self
.
options
.
text
else
:
message_text
=
""
if
self
.
options
.
display
:
os
.
environ
[
"DISPLAY"
]
=
self
.
options
.
display
if
dlgtype
==
DLG_TYPE_OK
:
show_simple_message_box
(
Gtk
.
MessageType
.
INFO
,
message_caption
,
message_text
)
elif
dlgtype
in
(
DLG_TYPE_ERROR
,
DLG_TYPE_PANIC
):
show_simple_message_box
(
Gtk
.
MessageType
.
ERROR
,
message_caption
,
message_text
)
elif
dlgtype
==
DLG_TYPE_PULLDOWN
:
handle_session_action
(
self
.
options
.
agentpid
,
PullDownMenu
(
self
.
options
.
window
)
.
show
())
elif
dlgtype
==
DLG_TYPE_YESNOSUSPEND
:
handle_session_action
(
self
.
options
.
agentpid
,
show_yes_no_suspend_box
(
message_caption
,
message_text
))
elif
dlgtype
==
DLG_TYPE_YESNO
:
handle_session_action
(
self
.
options
.
agentpid
,
show_yes_no_box
(
message_caption
,
message_text
))
else
:
# TODO: Implement all dialog types
sys
.
stderr
.
write
(
"Dialog type '
%
s' not implemented"
%
(
dlgtype
))
sys
.
exit
(
EXIT_FAILURE
)
NxDialogProgram
()
.
main
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment