ä»»æã®ç°å¢å¤æ°ãGUIã§å¤æ´ãã¦å¤é¨ããã»ã¹ãèµ·åãããã¼ã«ãä½æ
ç°å¢å¤æ°ã¯ç«¯æ«ã·ã§ã«ã®bashãzshã§ã¯exportãtcshã§ã¯setenvã¨ããã³ãã³ãã§ã¹ã¯ãªããããè¨å®ã§ãããããã¹ã¯ãããç°å¢ãªã©ã§GUIãç¨ãã¦ç°å¢å¤æ°ãè¨å®ãããã¨ã¯ã§ããªããããGUIä¸ã§ç°å¢å¤æ°ãä¸è¦§ã«ç»é²ãã¦ã¢ããªã±ã¼ã·ã§ã³ä¸é¨ã®å
¥åæ¬ã«å
¥åããã³ãã³ãè¡ãå®è¡ã§ãããã¼ã«ãä½æãã¦ã¿ãã
åä½ã«ã¯PyGTK(ãã¼ã¸ã§ã³2.6以ä¸)ã¨PyGObjectã®ããã±ã¼ã¸ãå¿
è¦ã
[ä»»æ]ãã¡ã¤ã«å: setenvexecpygtk.py
#! /usr/bin/python # -*- encoding: utf-8 -*- import shlex import sys import os try: import pygtk pygtk.require('2.0') except: pass try: import gtk except: print >> sys.stderr, 'Error: PyGTK is not installed' sys.exit(1) try: from glib import spawn_async as glib_spawn_async from glib import SPAWN_SEARCH_PATH as glib_SPAWN_SEARCH_PATH from glib import GError as glib_GError except: try: from gobject import spawn_async as glib_spawn_async from gobject import SPAWN_SEARCH_PATH as glib_SPAWN_SEARCH_PATH from gobject import GError as glib_GError except: print >> sys.stderr, 'Error: cannot import GLib functions' sys.exit(1) class TreeViewWithColumn(gtk.TreeView): """ ã³ã©ã ãå«ãã ããªã¼ãã¥ã¼ """ ( COLUMN_NAME, COLUMN_VALUE, COLUMN_ORIG, ) = range(3) def __init__(self, *args, **kwargs): gtk.TreeView.__init__(self, *args, **kwargs) # ã»ã«ã®ã¬ã³ãã© self.__renderer_name = gtk.CellRendererText() self.__renderer_name.connect('edited', self.__on_text_edited, self.COLUMN_NAME) # æå¾ã®å¼æ°ã¯ã¦ã¼ã¶ãã¼ã¿ self.__renderer_name.set_property('editable', True) self.__renderer_value = gtk.CellRendererText() self.__renderer_value.connect('edited', self.__on_text_edited, self.COLUMN_VALUE) self.__renderer_value.set_property('editable', True) # ã³ã©ã ã®è¨å® self.__col_name = gtk.TreeViewColumn('Name', self.__renderer_name, text=self.COLUMN_NAME) self.__col_name.set_resizable(True) self.__col_name.set_min_width(100) self.__col_value = gtk.TreeViewColumn('Value', self.__renderer_value, text=self.COLUMN_VALUE) self.__col_value.set_resizable(True) # ã³ã©ã ã追å self.append_column(self.__col_name) self.append_column(self.__col_value) # è¤æ°è¡é¸æãå¯è½ã«ãã self.get_selection().set_mode(gtk.SELECTION_MULTIPLE) def __on_text_edited(self, widget, path, new_text, col): """ ããã¹ãç¨ã»ã«ãç·¨éãããã¨ãã®å¦ç col(ã¦ã¼ã¶ãã¼ã¿)ã¯ã³ã©ã çªå· """ # get_model()ã§ããªã¼ãã¥ã¼ã«é¢é£ä»ãããããã¼ã¿ãåãåºã㦠# å¼æ°ã®æ å ±ã¨ãããã¦ãã¼ã¿ã®å¤ãå¤æ´ãã model = self.get_model() model.set_value(model.get_iter(path), col, new_text) class MainWindow(gtk.Window): """ ã¡ã¤ã³ã¦ã£ã³ã㦠""" def __init__(self, *args, **kwargs): gtk.Window.__init__(self, *args, **kwargs) # ã·ã§ã¼ãã«ãããã¼(ã¢ã¯ã»ã©ã¬ã¼ã¿) self.__accelgroup = gtk.AccelGroup() self.add_accel_group(self.__accelgroup) # ã¡ãã¥ã¼é ç® self.__item_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.__accelgroup) self.__menu_file = gtk.Menu() self.__menu_file.add(self.__item_quit) self.__item_file = gtk.MenuItem('_File') self.__item_file.set_submenu(self.__menu_file) self.__menubar = gtk.MenuBar() self.__menubar.append(self.__item_file) # ããªã¼ãã¥ã¼ self.__treeview = TreeViewWithColumn(model=gtk.ListStore(str, str, str)) self.__treeview.set_rules_hint(True) # ããªã¼ãã¥ã¼åãã¹ã¯ãã¼ã«ã¦ã£ã³ã㦠self.__sw = gtk.ScrolledWindow() self.__sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.__sw.add(self.__treeview) # å®è¡ãã¿ã³ self.__btn_exec = gtk.Button(stock=gtk.STOCK_EXECUTE) # 追å /åé¤/ã¯ãªã¢ãã¿ã³ self.__btn_add = gtk.Button(stock=gtk.STOCK_ADD) self.__btn_del = gtk.Button(stock=gtk.STOCK_DELETE) self.__btn_clear = gtk.Button(stock=gtk.STOCK_CLEAR) # åå/å¤/ã³ãã³ãè¡ã®ããã¹ãå ¥åæ¬(ã¨ã³ããª) self.__entry_name = gtk.Entry() self.__entry_value = gtk.Entry() self.__entry_cmdline = gtk.Entry() # ã©ãã« self.__label_name = gtk.Label() self.__label_name.set_text_with_mnemonic('_Name:') self.__label_name.set_mnemonic_widget(self.__entry_name) self.__label_value = gtk.Label() self.__label_value.set_text_with_mnemonic('_Value:') self.__label_value.set_mnemonic_widget(self.__entry_value) # ã¬ã¤ã¢ã¦ãç¨ã³ã³ãã self.__table_add = gtk.Table(2, 2) self.__table_add.attach(self.__label_name, 0, 1, 0, 1) # X:0-1 Y:0-1 å·¦ä¸ self.__table_add.attach(self.__entry_name, 1, 2, 0, 1) # X:1-2 Y:0-1 å³ä¸ self.__table_add.attach(self.__label_value, 0, 1, 1, 2) # X:0-1 Y:1-2 å·¦ä¸ self.__table_add.attach(self.__entry_value, 1, 2, 1, 2) # X:1-2 Y:1-2 å³ä¸ self.__vbox_btn = gtk.VBox() # åé¤/ã¯ãªã¢ãã¿ã³ã縦ã«ä¸¦ã¹ã self.__vbox_btn.pack_start(self.__btn_del, expand=False) self.__vbox_btn.pack_start(self.__btn_clear, expand=False) self.__hbox_add = gtk.HBox() self.__hbox_add.pack_start(self.__table_add) self.__hbox_add.pack_start(self.__btn_add, expand=False, fill=False) self.__hbox_tv = gtk.HBox() # ããªã¼ãã¥ã¼ã¨ãã¿ã³ç¾¤ã横㫠self.__hbox_tv.pack_start(self.__sw) self.__hbox_tv.pack_start(self.__vbox_btn, expand=False, fill=False) self.__hbox_cmdline = gtk.HBox() # ã³ãã³ãè¡ã¨å®è¡ãã¿ã³ã横㫠self.__hbox_cmdline.pack_start(self.__entry_cmdline) self.__hbox_cmdline.pack_start(self.__btn_exec, expand=False, fill=False) self.__vbox = gtk.VBox() self.__vbox.pack_start(self.__menubar, expand=False, fill=False) self.__vbox.pack_start(self.__hbox_add, expand=False, fill=False) self.__vbox.pack_start(self.__hbox_tv) self.__vbox.pack_start(self.__hbox_cmdline, expand=False, fill=False) # ã·ã°ãã« self.connect('delete_event', gtk.main_quit) self.__item_quit.connect('activate', gtk.main_quit) self.__btn_add.connect('clicked', self.__on_btn_add_clicked) self.__btn_del.connect('clicked', self.__on_btn_del_clicked) self.__btn_clear.connect('clicked', self.__on_btn_clear_clicked) self.__btn_exec.connect('clicked', self.__on_btn_exec_clicked) self.__entry_cmdline.connect('activate', self.__on_btn_exec_clicked) # ã¦ã£ã³ã㦠self.add(self.__vbox) self.set_size_request(350, 300) self.set_title('SetEnvExecPyGTK') # ã³ãã³ãè¡é¨åã«ãã©ã¼ã«ã¹ self.__entry_cmdline.grab_focus() def __on_btn_add_clicked(self, widget): """ 追å ãã¿ã³ãæ¼ãããã¨ãã®å¦ç ã¢ãã«ã«ååã¨å¤ã®ããã¹ãã¨ã³ããªã®å¤ã追å """ name = self.__entry_name.get_text() value = self.__entry_value.get_text() # ååã空ã®å ´åã¯åãä»ããªããã¨ã«ãã(å¤ã空æååã¯OK) if name == '': return try: orig = os.environ[name] except: orig = None # ListStore/TreeModelã¸ãã¼ã¿è¿½å self.__treeview.get_model().append((name, value, orig)) # ã¿ãã«ã§è¿½å self.__entry_name.set_text('') self.__entry_value.set_text('') def __on_btn_del_clicked(self, widget): """ åé¤ãã¿ã³ãæ¼ãããã¨ãã®å¦ç é¸æãããè¤æ°ã®é ç®ãã¢ãã«ããåé¤ """ (model, selected) = self.__treeview.get_selection().get_selected_rows() iters = [model.get_iter(path) for path in selected] for iter in iters: (name, value, orig) = model.get(iter, self.__treeview.COLUMN_NAME, self.__treeview.COLUMN_VALUE, self.__treeview.COLUMN_ORIG) # å ã®å¤ã«æ»ã if orig: os.environ[name] = orig else: # ç°å¢å¤æ°ãæ¶ãå ´åã¯delæã§(Noneã®å¤ãæå®ãã¦ããã¡) del os.environ[name] # æ¶ã model.remove(iter) def __on_btn_clear_clicked(self, widget): """ ã¯ãªã¢ãã¿ã³ãæ¼ãããã¨ãã®å¦ç ã¢ãã«ã®ãã¼ã¿ãå ¨ã¦æ¶ã clear()ãç¨ãããæ¶ããªããç°å¢å¤æ°ãæ»ãã¦ãã """ model = self.__treeview.get_model() iter = model.get_iter_first() if iter: # 空ã®å ´åã®å¯¾ç while True: (name, value, orig) = model.get(iter, self.__treeview.COLUMN_NAME, self.__treeview.COLUMN_VALUE, self.__treeview.COLUMN_ORIG) # æ»ã if orig: os.environ[name] = orig else: del os.environ[name] # æ¶ã if model.remove(iter) == False: # PyGTK 2.4æªæºã§ã¯æåãç°ãªã break def __on_btn_exec_clicked(self, widget): """ å®è¡ãã¿ã³ãæ¼ãããã¨ãã®å¦ç """ # ç°å¢å¤æ°ã®è¨å® model = self.__treeview.get_model() iter = model.get_iter_first() # ããªã¼ãã¥ã¼ã®åãã¼ã¿ãèªã¿è¾¼ãã§ç°å¢å¤æ°ã«ã»ãã while iter: (name, value, orig) = model.get(iter, self.__treeview.COLUMN_NAME, self.__treeview.COLUMN_VALUE, self.__treeview.COLUMN_ORIG) os.environ[name] = value iter = model.iter_next(iter) # éåæã§ã³ãã³ããå®è¡ # glib.SPAWN_SEARCH_PATHã«ããPATHããå®è¡ãã¡ã¤ã«ã®æ¢ç´¢ãè¡ã # 失æããã¨glib.GErrorä¾å¤ãçºç try: glib_spawn_async(shlex.split(self.__entry_cmdline.get_text()), flags=glib_SPAWN_SEARCH_PATH) except glib_GError, (msg): errdlg = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_CLOSE, message_format=str(msg)) errdlg.set_title('Spawn failed') errdlg.run() errdlg.destroy() # ã³ãã³ãè¡ã®å ¥åæ¬ãã空ã«ãã self.__entry_cmdline.set_text('') class SetEnvExecPyGTK: """ ç°å¢å¤æ°ãã»ãããã¦ã³ãã³ããå®è¡ããGUIãã¼ã« """ def main(self): """ ã¢ããªã±ã¼ã·ã§ã³ã®ã¡ã¤ã³å¦ç """ win = MainWindow() win.show_all() gtk.main() if __name__ == '__main__': app = SetEnvExecPyGTK() app.main()
ã¡ã¢
- ä¸è¦§ã«è¿½å ãããé ç®ãã³ãã³ãå®è¡åã«ç°å¢å¤æ°ã«è¨å®ããé ç®ã®ãªã¹ãããã®åé¤æã«ãã®ç°å¢å¤æ°ãåé¤ããã®ã ããDISPLAYãªã©ãå ã å®ç¾©ããã¦ããç°å¢å¤æ°ãæ¶ãã¦ãã¾ãã®ã¯åé¡ãªã®ã§ããªã¹ãã®é表示é ç®ã¨ãã¦ã追å åã®ãã®ç°å¢å¤æ°ã®å¤ããè¨ããå ã æªå®ç¾©ã ã£ããã®ã¯ãªã¹ãããæ¶ãããã¨ãã«ç°å¢å¤æ°ããã®ã¾ã¾åé¤ããããå ã å¤ã®å®ç¾©ããã¦ãããã®ã¯å ã®å¤ã復å ããããã«ãã¦ãã
- å¤é¨ã³ãã³ãã®èµ·åã«ã¯PyGObjectã®glib.spawn_async()*1ã使ç¨ãã¦ãããããã®é¢æ°ã¯ã³ãã³ãè¡ããªã¹ãã§åãä»ãããããããã¹ãå ¥åæ¬ã®æååãåå²ããã®ã«ãコマンド行のような文字列を解析してリストに格納する上でのメモ(後半)ãã®shlex.split()ãç¨ãã¦ãã*2
- Pythonå ã§ç°å¢å¤æ°ãè¨å®ããã«ã¯os.environã¸ã®ä»£å ¥ã§ããããæªå®ç¾©ã«ããã«ã¯delæãç¨ãã
é¢é£è¨äº:
- PyGTKでツリービューにリストのデータ(ListStore)を表示(概要とメモ)
- Vala言語で外部プロセスを実行する(簡単な例・メモ)
- Vala言語で外部プロセスを実行する(簡単な例・コード例と出力結果)
- コマンド行のような文字列を解析してリストに格納する上でのメモ(前半)
- コマンド行のような文字列を解析してリストに格納する上でのメモ(後半)
é¢é£URL:
使ç¨ãããã¼ã¸ã§ã³:
- PyGObject 2.20.0
- PyGTK 2.16.0
*1:GLibã®å¤é¨ããã»ã¹éåæå®è¡é¢æ°ãPythonããå©ç¨ãããã®ã§ãValaè¨èªã§ä»¥åãVala言語で外部プロセスを実行する(簡単な例・メモ)ãããã®ä¸é£ã®è¨äºã§æ±ã£ã¦ãã
*2:ãªã¹ãã¸ã®åå²ã®å¦çã¯ä¸åº¦èªåã§æ¸ãã¦ããããshlex.split()ã使ãããã¨ãåãã£ã¦ãããã¡ãã«å¤æ´ãã