Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Obrun an Openbox/*Box Run dialog written in Python and GTK2
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Unsupported Software
View previous topic :: View next topic  
Author Message
Xaid
Guru
Guru


Joined: 30 Oct 2004
Posts: 474
Location: Edmonton / Alberta

PostPosted: Fri Aug 26, 2005 3:55 am    Post subject: Obrun an Openbox/*Box Run dialog written in Python and GTK2 Reply with quote

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
View user's profile Send private message
croakinglizard
n00b
n00b


Joined: 11 Jan 2005
Posts: 13

PostPosted: Fri Aug 26, 2005 6:00 am    Post subject: Reply with quote

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
View user's profile Send private message
Xaid
Guru
Guru


Joined: 30 Oct 2004
Posts: 474
Location: Edmonton / Alberta

PostPosted: Fri Aug 26, 2005 6:14 am    Post subject: Reply with quote

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
View user's profile Send private message
croakinglizard
n00b
n00b


Joined: 11 Jan 2005
Posts: 13

PostPosted: Fri Aug 26, 2005 6:59 am    Post subject: Reply with quote

It works now. Thanks.
Back to top
View user's profile Send private message
ClieX
n00b
n00b


Joined: 19 Jan 2005
Posts: 44
Location: Europe/Moscow

PostPosted: Fri Aug 26, 2005 4:58 pm    Post subject: Reply with quote

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
View user's profile Send private message
Xaid
Guru
Guru


Joined: 30 Oct 2004
Posts: 474
Location: Edmonton / Alberta

PostPosted: Fri Aug 26, 2005 8:08 pm    Post subject: Reply with quote

Here's a quick link to the program (if you don't feel like copying + pasting) http://cypher.homelinux.net:9000/~ghost/files/obrun.py
And thats a screenshot of it in action when its showing the matching entries for a program http://cypher.homelinux.net:9000/~ghost/images/obrun.png
Thats hosted on my home box so it might not be always available.
Let me know if those links work or not.
Back to top
View user's profile Send private message
ClieX
n00b
n00b


Joined: 19 Jan 2005
Posts: 44
Location: Europe/Moscow

PostPosted: Fri Aug 26, 2005 9:44 pm    Post subject: Reply with quote

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
View user's profile Send private message
Xaid
Guru
Guru


Joined: 30 Oct 2004
Posts: 474
Location: Edmonton / Alberta

PostPosted: Fri Aug 26, 2005 9:53 pm    Post subject: Reply with quote

ClieX,
Thanks for the input :D
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
View user's profile Send private message
Xaid
Guru
Guru


Joined: 30 Oct 2004
Posts: 474
Location: Edmonton / Alberta

PostPosted: Sun Aug 28, 2005 8:29 pm    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Unsupported Software All times are GMT
Page 1 of 1

 
Jump to:  
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