PageRenderTime 49ms CodeModel.GetById 8ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 0ms

/neatx/lib/app/nxdialog.py

http://neatx.googlecode.com/
Python | 264 lines | 148 code | 47 blank | 69 comment | 6 complexity | 2bf286411f30ced367bbbc9aacf4eb3c MD5 | raw file
  1#
  2#
  3
  4# Copyright (C) 2008 Google Inc.
  5#
  6# This program is free software; you can redistribute it and/or modify
  7# it under the terms of the GNU General Public License as published by
  8# the Free Software Foundation; either version 2 of the License, or
  9# (at your option) any later version.
 10#
 11# This program is distributed in the hope that it will be useful, but
 12# WITHOUT ANY WARRANTY; without even the implied warranty of
 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14# General Public License for more details.
 15#
 16# You should have received a copy of the GNU General Public License
 17# along with this program; if not, write to the Free Software
 18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 19# 02110-1301, USA.
 20
 21
 22"""nxdialog program for handling dialog display."""
 23
 24
 25# If an "NX_CLIENT" environment variable is not provided to nxagent
 26# nxcomp library assumes this script is located in /usr/NX/bin/nxclient
 27
 28import pygtk
 29pygtk.require("2.0")
 30import gtk
 31
 32import logging
 33import optparse
 34import os
 35import signal
 36import sys
 37
 38from neatx import cli
 39from neatx import constants
 40from neatx import errors
 41from neatx import utils
 42
 43
 44PROGRAM = "nxdialog"
 45
 46DISCONNECT = 1
 47TERMINATE = 2
 48
 49CANCEL_TEXT = "Cancel"
 50DISCONNECT_TEXT = "Disconnect"
 51TERMINATE_TEXT = "Terminate"
 52
 53
 54class PullDownMenu:
 55  """Shows a popup menu to disconnect/terminate session.
 56
 57  """
 58  def __init__(self, window_id):
 59    """Initializes this class.
 60
 61    @type window_id: int
 62    @param window_id: X11 window id of target window
 63
 64    """
 65    self._window_id = window_id
 66    self._result = None
 67
 68  def Show(self):
 69    """Shows popup and returns result.
 70
 71    """
 72    win = gtk.gdk.window_foreign_new(self._window_id)
 73
 74    menu = gtk.Menu()
 75    menu.connect("deactivate", self._MenuDeactivate)
 76
 77    # TODO: Show title item in bold font
 78    title = gtk.MenuItem(label="Neatx session")
 79    title.set_sensitive(False)
 80    menu.append(title)
 81
 82    disconnect = gtk.MenuItem(label=DISCONNECT_TEXT)
 83    disconnect.connect("activate", self._ItemActivate, DISCONNECT)
 84    menu.append(disconnect)
 85
 86    terminate = gtk.MenuItem(label=TERMINATE_TEXT)
 87    terminate.connect("activate", self._ItemActivate, TERMINATE)
 88    menu.append(terminate)
 89
 90    menu.append(gtk.SeparatorMenuItem())
 91
 92    cancel = gtk.MenuItem(label=CANCEL_TEXT)
 93    menu.append(cancel)
 94
 95    menu.show_all()
 96
 97    menu.popup(parent_menu_shell=None, parent_menu_item=None,
 98               func=self._PosMenu, data=win,
 99               button=0, activate_time=gtk.get_current_event_time())
100
101    gtk.main()
102
103    return self._result
104
105  def _ItemActivate(self, _, result):
106    self._result = result
107    gtk.main_quit()
108
109  def _MenuDeactivate(self, _):
110    logging.debug("Aborting pulldown menu")
111    gtk.main_quit()
112
113  def _PosMenu(self, menu, parent):
114    """Positions menu at the top center of the parent window.
115
116    """
117    # Get parent geometry and origin
118    (_, _, win_width, win_height, _) = parent.get_geometry()
119    (win_x, win_y) = parent.get_origin()
120
121    # Calculate width of menu
122    (menu_width, menu_height) = menu.size_request()
123
124    # Calculate center
125    x = win_x + ((win_width - menu_width) / 2)
126
127    return (x, win_y, True)
128
129
130def ShowYesNoSuspendBox(title, text):
131  """Shows a message box to disconnect/terminate session.
132
133  @type title: str
134  @param title: Message box title
135  @type text: str
136  @param text: Message box text
137  @return: Choosen action
138
139  """
140  dlg = gtk.MessageDialog(type=gtk.MESSAGE_QUESTION, flags=gtk.DIALOG_MODAL)
141  dlg.set_title(title)
142  dlg.set_markup(text)
143  dlg.add_button(DISCONNECT_TEXT, DISCONNECT)
144  dlg.add_button(TERMINATE_TEXT, TERMINATE)
145  dlg.add_button(CANCEL_TEXT, gtk.RESPONSE_CANCEL)
146
147  res = dlg.run()
148
149  if res in (DISCONNECT, TERMINATE):
150    return res
151
152  # Everything else is cancel
153  return None
154
155
156def HandleSessionAction(agentpid, action):
157  """Execute session action choosen by user.
158
159  @type agentpid: int
160  @param agentpid: Nxagent process id as passed by command line
161  @type action: int or None
162  @param action: Choosen action
163
164  """
165  if action == DISCONNECT:
166    logging.info("Disconnecting from session, sending SIGHUP to %s", agentpid)
167    os.kill(agentpid, signal.SIGHUP)
168
169  elif action == TERMINATE:
170    logging.info("Terminating session, sending SIGTERM to process %s",
171                 agentpid)
172    os.kill(agentpid, signal.SIGTERM)
173
174  elif action is None:
175    logging.debug("Dialog canceled, nothing to do")
176
177  else:
178    raise NotImplementedError()
179
180
181def ShowSimpleMessageBox(icon, title, text):
182  """Shows a simple message box.
183
184  @type icon: QMessageBox.Icon
185  @param icon: Icon for message box
186  @type title: str
187  @param title: Message box title
188  @type text: str
189  @param text: Message box text
190
191  """
192  dlg = gtk.MessageDialog(type=icon, flags=gtk.DIALOG_MODAL,
193                          buttons=gtk.BUTTONS_OK)
194  dlg.set_title(title)
195  dlg.set_markup(text)
196  dlg.run()
197
198
199class NxDialogProgram(cli.GenericProgram):
200  def BuildOptions(self):
201    options = cli.GenericProgram.BuildOptions(self)
202    options.extend([
203      optparse.make_option("--caption", type="string", dest="caption"),
204      optparse.make_option("--dialog", type="string", dest="dialog_type"),
205      optparse.make_option("--display", type="string", dest="display"),
206      optparse.make_option("--message", type="string", dest="text"),
207      optparse.make_option("--parent", type="int", dest="agentpid"),
208      optparse.make_option("--window", type="int", dest="window"),
209      ])
210    return options
211
212  def Run(self):
213    """Disconnect/terminate NX session upon user's request.
214
215    """
216    logging.debug("Nxdialog options: %r", self.options)
217
218    dlgtype = self.options.dialog_type
219
220    if dlgtype not in constants.VALID_DLG_TYPES:
221      logging.error("Dialog type '%s' not supported", dlgtype)
222      sys.exit(constants.EXIT_FAILURE)
223
224    if dlgtype in (constants.DLG_TYPE_PULLDOWN,
225        constants.DLG_TYPE_YESNOSUSPEND) and not self.options.agentpid:
226      logging.error("Agent pid not supplied via --parent")
227      sys.exit(constants.EXIT_FAILURE)
228
229    if self.options.caption:
230      message_caption = self.options.caption
231    else:
232      message_caption = sys.argv[0]
233
234    if self.options.text:
235      message_text = self.options.text
236    else:
237      message_text = ""
238
239    if self.options.display:
240      os.environ["DISPLAY"] = self.options.display
241
242    if dlgtype == constants.DLG_TYPE_OK:
243      ShowSimpleMessageBox(gtk.MESSAGE_INFO, message_caption, message_text)
244
245    elif dlgtype in (constants.DLG_TYPE_ERROR, constants.DLG_TYPE_PANIC):
246      ShowSimpleMessageBox(gtk.MESSAGE_ERROR, message_caption, message_text)
247
248    elif dlgtype == constants.DLG_TYPE_PULLDOWN:
249      HandleSessionAction(self.options.agentpid,
250                          PullDownMenu(self.options.window).Show())
251
252    elif dlgtype == constants.DLG_TYPE_YESNOSUSPEND:
253      HandleSessionAction(self.options.agentpid,
254                          ShowYesNoSuspendBox(message_caption, message_text))
255
256    else:
257      # TODO: Implement all dialog types
258      raise errors.GenericError("Dialog type %r not implemented" %
259                                self.options.dialog_type)
260
261
262def Main():
263  logsetup = utils.LoggingSetup(PROGRAM)
264  NxDialogProgram(logsetup).Main()