View previous topic :: View next topic |
Author |
Message |
Xaid Guru
Joined: 30 Oct 2004 Posts: 474 Location: Edmonton / Alberta
|
Posted: Fri Aug 26, 2005 3:55 am Post subject: Obrun an Openbox/*Box Run dialog written in Python and GTK2 |
|
|
Last update: 28-08-2005
Hi,
This is a small "run dialog" program that I wrote, there are probably a dozen like it but it was a good practice for me since I'm a beginner in Python and I thought that someone else might find it useful.
It saves a history list of the commands that you ran, and keeps them in ~/.obrun_history, the number of items it saves can be changed by editing obrun.py and changing self.maxHistoryEntries from 20 to whatever you want.
You'll need Python, Gtk+2.4+ and Pygtk-2.6.1+ (it might work with older versions too).
I'd appreciate any comments/suggestions.
To see a screenshot of it you can clickhttp://cypher.homelinux.net:9000/~ghost/images/obrun.png, and a quick link to obrun.py can be found in here as well http://cypher.homelinux.net:9000/~ghost/files/obrun.py. I'm hosting those 2 files on my main box so it might not always be online, if thats the case then the code listing below is the same so you can just copy and paste it.
If you save this as obrun.py and put it in ~/.config/openbox , then just edit rc.xml and add something like
Code: |
<keybind key="A-F2">
<action name="Execute"><execute>~/.config/openbox/obrun.py</execute></action>
</keybind>
|
and restart Openbox then you can launch this by pressing ALT+ F2.
Code: |
#!/usr/bin/python
# Copyright 2005 Zaid A. <zaid.box@gmail.com>
# Distributed under the terms of the GNU General Public License v2
import os
import pygtk
pygtk.require('2.0')
import gtk
class ObRun(gtk.Window):
def deleteEventCallback(self, widget, event, data=None):
return False
def okButtonCallback(self, widget, data=None):
program = self.programPath.get_text()
programArgs = program.split(' ')
self.saveHistory(program)
self.executeProgram(programArgs)
def cancelButtonCallback(self, widget, data=None):
raise SystemExit
def executeProgram(self, args):
childPID = os.fork()
if childPID == 0:
try:
os.execvpe(args[0], args, os.environ)
except OSError:
errorDialog = gtk.Dialog(title="Error", parent=None, flags=gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK))
errorDialog.vbox.pack_start(gtk.Label("An error has occured while trying to execute the program."),
expand=True, padding=15)
errorDialog.set_default_response(gtk.RESPONSE_OK)
errorDialog.show_all()
if errorDialog.run() == gtk.RESPONSE_OK:
errorDialog.destroy()
if childPID != 0:
raise SystemExit
def duplicateExists(self, itemToCheck):
for entry in self.historyList:
for i in range(1):
if itemToCheck == entry[i]:
return True
return False
def loadHistory(self):
try:
os.stat(os.path.expanduser("~")+ "/.obrun_history")
except OSError:
historyFile = open(os.path.expanduser("~")+ "/.obrun_history", "w")
historyFile.close()
historyFile = open(os.path.expanduser("~")+ "/.obrun_history", "r")
historyLines = historyFile.readlines()
historyFile.close()
entryCount = 0
for entry in historyLines:
if entryCount == self.maxHistoryEntries:
break
self.historyList.append([entry.strip()])
entryCount = entryCount+1
def saveHistory(self, entry):
entryCount = 0
historyFile = open(os.path.expanduser("~") +"/.obrun_history", "w")
if self.duplicateExists(entry) == False:
self.historyList.append([entry])
for item in self.historyList:
if entryCount == self.maxHistoryEntries:
break
for i in range(1):
historyFile.write(item[i] + "\n")
entryCount = entryCount +1
historyFile.close()
def __init__(self):
gtk.Window.__init__(self, type=gtk.WINDOW_TOPLEVEL)
self.set_position(gtk.WIN_POS_CENTER)
self.set_size_request(250,90)
self.set_border_width(5)
self.set_title("Run application")
self.connect("delete-event", self.deleteEventCallback)
self.connect("destroy", lambda destroyCallback: gtk.main_quit())
self.vbox = gtk.VBox()
self.hbox = gtk.HBox()
self.okButton = gtk.Button(stock=gtk.STOCK_OK)
self.cancelButton = gtk.Button(stock=gtk.STOCK_CANCEL)
self.okButton.connect("clicked", self.okButtonCallback)
self.cancelButton.connect("clicked", self.cancelButtonCallback)
self.programPath = gtk.Entry()
self.completionWidget = gtk.EntryCompletion()
self.historyList = gtk.ListStore(str)
self.maxHistoryEntries = 20
self.loadHistory()
self.completionWidget.set_model(self.historyList)
self.completionWidget.set_text_column(0)
self.programPath.set_completion(self.completionWidget)
self.programPath.connect("activate", self.okButtonCallback)
self.hbox.pack_start(self.okButton,expand=False, padding=4)
self.hbox.pack_start(self.cancelButton, expand=False, padding=4)
self.vbox.pack_start(self.programPath, expand=False, padding=5)
self.vbox.pack_start(self.hbox, expand=False, padding=5)
self.add(self.vbox)
def main(self):
self.show_all()
gtk.main()
if __name__ == '__main__':
runDialog = ObRun()
runDialog.main()
|
Edit: Added a delete-event callback.
Edit2: Fixed a typo when calling connect with the "delete-event"
Edited on 27/08/2005: Added links for a screenshot and a direct link to the file.
Last edited by Xaid on Sun Aug 28, 2005 8:25 pm; edited 3 times in total |
|
Back to top |
|
|
croakinglizard n00b
Joined: 11 Jan 2005 Posts: 13
|
Posted: Fri Aug 26, 2005 6:00 am Post subject: |
|
|
I get this error.
Traceback (most recent call last):
File "./obrun.py", line 132, in ?
runDialog = ObRun()
File "./obrun.py", line 93, in __init__
self.connect("delete-event", self.deleteEventCallback())
TypeError: deleteEventCallback() takes at least 3 arguments (1 given) |
|
Back to top |
|
|
Xaid Guru
Joined: 30 Oct 2004 Posts: 474 Location: Edmonton / Alberta
|
Posted: Fri Aug 26, 2005 6:14 am Post subject: |
|
|
I made a last minute typo I updated the listing now to include it, basically this is what should be changed:
Code: |
self.connect("delete-event", self.deleteEventCallback())
|
should be:
Code: |
self.connect("delete-event", self.deleteEventCallback)
|
let me know if this fixes it or not. |
|
Back to top |
|
|
croakinglizard n00b
Joined: 11 Jan 2005 Posts: 13
|
Posted: Fri Aug 26, 2005 6:59 am Post subject: |
|
|
It works now. Thanks. |
|
Back to top |
|
|
ClieX n00b
Joined: 19 Jan 2005 Posts: 44 Location: Europe/Moscow
|
Posted: Fri Aug 26, 2005 4:58 pm Post subject: |
|
|
Xaid
Can you show a screenshot of this program? _________________ Gentoo Base System version 1.6.13, Stage 1/3 with NPTL,UTF-8
GCC 3.4.4-r1, GLIBC 2.3.5-r1, 2.6.13.2-nitro1
GNOME 2.12 |
|
Back to top |
|
|
Xaid Guru
Joined: 30 Oct 2004 Posts: 474 Location: Edmonton / Alberta
|
|
Back to top |
|
|
ClieX n00b
Joined: 19 Jan 2005 Posts: 44 Location: Europe/Moscow
|
Posted: Fri Aug 26, 2005 9:44 pm Post subject: |
|
|
Thx, links work.
Good program! _________________ Gentoo Base System version 1.6.13, Stage 1/3 with NPTL,UTF-8
GCC 3.4.4-r1, GLIBC 2.3.5-r1, 2.6.13.2-nitro1
GNOME 2.12 |
|
Back to top |
|
|
Xaid Guru
Joined: 30 Oct 2004 Posts: 474 Location: Edmonton / Alberta
|
Posted: Fri Aug 26, 2005 9:53 pm Post subject: |
|
|
ClieX,
Thanks for the input
I'm planning of adding a keybinding for a quick exit, for example, pressing ESC will quit it.
The links should be up most of the day until I shutdown the box around 3 AM. |
|
Back to top |
|
|
Xaid Guru
Joined: 30 Oct 2004 Posts: 474 Location: Edmonton / Alberta
|
Posted: Sun Aug 28, 2005 8:29 pm Post subject: |
|
|
A quick update, I just modified the code to fix a small bug where it was storing duplicate entries for the programs, for example, suppose you run xclock twice, then it will store xclock twice in the history file (so when you run the dialog and press 'x' you will see xclock twice), I fixed this by adding a small duplicateExists() function which takes care of that, you will have to delete the history file (~/.obrun_history) if it contains duplicate entries (I didn't add the check to the loadHistory() function since I didn't think it was neccessary if saveHistory() was fixed).
If you have any problems/comments post back. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|