GTK::Socket and Gtk::Plug unexpected behaviour under Gnome and FVWM2 - python

The following code works fine if run within FVWM2. But if you change desktop to Gnome, then the embedded window is destroyed instead of being embedded.
Why is that? What am I missing?...
The code follows but basically all it does is fork. In the child, we create a VPython window an let it idle forever. In the parent, we create a GTK window, find out what the window ID of the child window is, and try to embed it vis a GTK::Socket.
Note that the VPython part maybe irrelevant to this.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import subprocess
import sys
import os
import re
import time
from visual import *
def find_window_id (title):
"""Gets the OpenGL window ID."""
pattern = re.compile('0x[0-9abcdef]{7}')
proc = subprocess.Popen(['xwininfo', '-name', title],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
errors = proc.stderr.readlines()
if errors:
return None
for line in proc.stdout.readlines():
match = pattern.findall(line)
if len(match):
return long(match[0], 16)
return None
class Setting ():
"""VPython/OpenGL class."""
def __init__ (self, w=256, h=256, title='OpenGL via VPython'):
"""Initiator."""
self.width = w
self.height = h
self.title = title
self.scene = display.get_selected()
self.scene.title = self.title
self.scene.width = self.width
self.scene.height = self.height
self.sphere = sphere()
class GTKDisplay ():
def __init__ (self, winID):
"""Initiator: Draws the GTK GUI."""
import gtk
import pygtk
self.OpenGLWindowID = winID
window = gtk.Window()
window.show()
socket = gtk.Socket()
socket.show()
window.add(socket)
window.connect("destroy", lambda w: gtk.main_quit())
socket.add_id(long(self.OpenGLWindowID))
gtk.main()
def main ():
"""Main entry point."""
name = 'sphere OpenGL window'
child_pid = os.fork()
if 0 == child_pid:
sut = Setting(title=name)
else:
winID = None
while not winID:
time.sleep(.1)
winID = find_window_id(name)
try:
gui = GTKDisplay(winID)
except KeyboardInterrupt, err:
print '\nAdieu monde cruel!'
if __name__ == "__main__":
main()
PS: Yes, this is a follow up from this question.

Related

Running raw_input on a pygtk application

I need to make a graphical application that reads data from the console to update some widgets, this will have to do with 2 threads, one for the GUI and one for the console. The problem is that raw_input function does not work and also freezes the application. Here is the code.
import pygtk
pygtk.require('2.0')
import gtk
import gobject
from time import sleep
import sys
import threading
class Worker (threading.Thread):
def __init__(self, app):
threading.Thread.__init__(self)
self.app = app
def run(self):
text = raw_input("Enter some text: ") #It freezes the application
#text = "Hola" #It Works
self.app.writeMessage(text, False)
class Application:
def __init__(self, title, xPos, yPos):
gtk.threads_init()
self.win = gtk.Window()
screen = self.win.get_screen()
screenW = screen.get_width()
screenH = screen.get_height()
windowW = int(screenW * 0.5)
windowH = int(screenH * 0.25)
if type(xPos) is float:
xPos = int(screenW * xPos)
if type(yPos) is float:
yPos = int(screenH * yPos)
self.messageArea = gtk.TextView()
self.scroll = gtk.ScrolledWindow()
self.scroll.add(self.messageArea)
self.win.set_size_request(windowW, windowH)
self.win.set_title(title)
self.win.add(self.scroll)
self.win.show_all()
self.win.move(xPos, yPos)
self.win.connect("destroy", gtk.mainquit)
def doOperation(self, function, *args, **kw):
def idle_func():
try:
gtk.threads_enter()
function(*args, **kw)
return False
finally:
gtk.threads_leave()
gobject.idle_add(idle_func)
def sleeper():
time.sleep(.001)
return 1 # don't forget this otherwise the timeout will be removed
def mainloop(self):
#Trick for running threads and pygtk on win32 enviroment
if sys.platform == 'win32':
gtk.timeout_add(400, self.sleeper)
gtk.threads_enter()
gtk.mainloop()
gtk.threads_leave()
def writeMessage(self, message, isMainThread):
if isMainThread:
buf = self.messageArea.get_buffer()
end_iter = buf.get_end_iter()
buf.insert(end_iter, message)
else:
self.doOperation(self.writeMessage, message, True)
if __name__ == "__main__":
app = Application("Hello", 0, 0)
worker = Worker(app)
app.doOperation(worker.start)
app.mainloop()
Curiously the code only works if you run it in eclipse pydev, but it doesn't is the intention, I must run it from console. So this is the question, how to execute raw_input function and GUI on separate threads?
take a look at this.It explains about absence of event loop support in python and you can disable pygtk event loop after importing it.

Cyclic label update in Python

I'm trying to get dynamic cyclic (every half a second) label updates from a Webservice in Python where I parse a JSON string and return its contents to the GUI (made with Glade 3.8.1).
I have started from a basic example and the code I've written so far looks like this:
import sys
import json
import urllib2
import time
try:
import pygtk
pygtk.require("2.0")
except:
pass
try:
import gtk.glade
import gtk
except:
sys.exit(1)
class cRioHMI():
def on_MainWindow_destroy(self, data = None):
print "quit with cancel"
gtk.main_quit()
def on_gtk_quit_activate(self, data = None):
print "quit from menu"
gtk.main_quit()
def on_btnTest_clicked(self, widget):
print "Button Pressed"
def on_gtk_about_activate(self, data = None):
print "About Page Accessed"
self.response = self.about.run()
self.about.hide()
def __init__(self):
self.gladefile = "Assets/HMI.glade"
self.builder = gtk.Builder()
self.builder.add_from_file(self.gladefile)
self.builder.connect_signals(self)
self.window = self.builder.get_object("MainWindow")
self.about = self.builder.get_object("AboutDialogue")
self.templable = self.builder.get_object("lbl_Temperature")
self.window.show()
def update_Values(self, data = None):
response = urllib2.urlopen('http://10.10.10.11:8001/WebUI/Temperatures/GetTemperatures')
data = json.load(response)
temperature = data['Temperature2'][1]
self.templable.set_text(str(temperature))
time.sleep(.5)
if __name__ == "__main__":
HMI = cRioHMI()
gtk.main()
When I use the code from the update_Values method on a click event, the code performs as expected
def on_btnTest_clicked(self, widget):
response = urllib2.urlopen('http://10.10.10.11:8001/WebUI/Temperatures/GetTemperatures')
data = json.load(response)
temperature = data['Temperature2'][1]
self.templable.set_text(str(temperature))
time.sleep(.5)
print "Button Pressed"
but I would like to update multiple labels in a cyclic manner and still have event driven actions.
What is the best way to do that? Please note, that I'm new to python.
You can use gobject.timeout_add (see the documentation here).
So in your __init__ you would have something like gobject.timeout_add(1000, self.updateValues). If you return False the timeout will not be called again.
You should also not use time.sleep. This is a blocking call. That means your GUI will freeze as it cannot handle incoming events. The same thing will happen with the urllib2.urlopen call, if it takes too much time. To prevent this you can run updateValues in a separate Thread. Then you would have to use gobject.idle_add to set the text of the label (see documentation).
Here is a small example. It is just a counter (and would not need threading) but I marked the place where your urllib2.urlopen would go with a comment:
#!/usr/bin/env python2
from threading import Thread
from pygtk import gtk, gobject
class Window(gtk.Window):
def __init__(self):
gtk.Window.__init__(self)
self.connect('delete-event', gtk.main_quit)
self.label = gtk.Label('1')
self.add(self.label)
gobject.timeout_add_seconds(1, self.threaded)
def threaded(self):
thread = Thread(target=self.updateValues)
thread.start()
return True
def updateValues(self):
# urllib.urlopen calls
n = int(self.label.get_text())
gobject.idle_add(self.label.set_text, str(n + 1))
win = Window()
win.show_all()
gobject.threads_init()
gtk.main()

GTK window capture: VPython (OpenGL) application

Having read the documentation for VPython and GTK threading, it seems to me that it would be possible to embed VPython graphics within a gtk GUI. I know that it is possible with wx on Windows but I am on Linux and using PyGTK. Now, I have managed to get part of the way. I can embed a VPython window provided that it is spawned a separate process. What I would like is to embed it as a thread. The latter would make GUI events that control the OpenGL easier to implement -- via a thread instead of a socket and network calls.
Edit: Apparently nobody knows anything about this... Meh.
Here is the code I have. Uncomment the two commented out lines and comment a few obvious others and you can get to the process spawning code.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
from visual import *
import threading
import Queue
import gtk
import pygtk
import re
import subprocess
class OPenGLThreadClass (threading.Thread):
"""Thread running the VPython code."""
def __init__(self, queue):
threading.Thread.__init__(self)
self.queue = queue
self.name = 'OpenGLThread'
def run (self):
gtk.threads_enter()
self.scene = display.get_selected()
self.scene.title = 'OpenGL test'
s = sphere()
gtk.threads_leave()
#P = subprocess.Popen(['python', 'opengl.py'])
time.sleep(2)
self.queue.put(self.find_window_id())
self.queue.task_done()
def find_window_id (self):
"""Gets the OpenGL window ID."""
pattern = re.compile('0x[0-9abcdef]{7}')
P = subprocess.Popen(['xwininfo', '-name', self.scene.title],
#P = subprocess.Popen(['xwininfo', '-name', 'Visual WeldHead'],
stdout=subprocess.PIPE)
for line in P.stdout.readlines():
match = pattern.findall(line)
if len(match):
ret = long(match[0], 16)
print("OpenGL window id is %d (%s)" % (ret, hex(ret)))
return ret
class GTKWindowThreadClass (threading.Thread):
"""Thread running the GTK code."""
def __init__ (self, winID):
threading.Thread.__init__(self)
self.OpenGLWindowID = winID
self.name = 'GTKThread'
def run (self):
"""Draw the GTK GUI."""
gtk.threads_enter()
window = gtk.Window()
window.show()
socket = gtk.Socket()
socket.show()
window.add(socket)
window.connect("destroy", lambda w: gtk.main_quit())
print("Got winID as %d (%s)" % (self.OpenGLWindowID, hex(self.OpenGLWindowID)))
socket.add_id(long(self.OpenGLWindowID))
gtk.main()
gtk.threads_leave()
def main ():
thread = {}
print("Embedding OpenGL/VPython into GTK GUI")
queue = Queue.Queue()
thread['OpenGL'] = OPenGLThreadClass(queue)
thread['OpenGL'].start()
winID = queue.get()
print("Got winID as %d (%s)" % (winID, hex(winID)))
gtk.gdk.threads_init()
thread['GTK'] = GTKWindowThreadClass(winID)
thread['GTK'].start()
if __name__ == "__main__":
main()
This is the code that works in case anyone cares.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import subprocess
import sys
import os
import re
import time
from visual import *
def find_window_id (title):
"""Gets the OpenGL window ID."""
pattern = re.compile('0x[0-9abcdef]{7}')
proc = subprocess.Popen(['xwininfo', '-name', title],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
errors = proc.stderr.readlines()
if errors:
return None
for line in proc.stdout.readlines():
match = pattern.findall(line)
if len(match):
return long(match[0], 16)
return None
class Setting ():
"""VPython/OpenGL class."""
def __init__ (self, w=256, h=256, title='OpenGL via VPython'):
"""Initiator."""
self.width = w
self.height = h
self.title = title
self.scene = display.get_selected()
self.scene.title = self.title
self.scene.width = self.width
self.scene.height = self.height
self.sphere = sphere()
class GTKDisplay ():
def __init__ (self, winID):
"""Initiator: Draws the GTK GUI."""
import gtk
import pygtk
self.OpenGLWindowID = winID
window = gtk.Window()
window.show()
socket = gtk.Socket()
socket.show()
window.add(socket)
window.connect("destroy", lambda w: gtk.main_quit())
socket.add_id(long(self.OpenGLWindowID))
gtk.main()
def main ():
"""Main entry point."""
name = 'sphere OpenGL window'
child_pid = os.fork()
if 0 == child_pid:
sut = Setting(title=name)
else:
winID = None
while not winID:
time.sleep(.1)
winID = find_window_id(name)
try:
gui = GTKDisplay(winID)
except KeyboardInterrupt, err:
print '\nAdieu monde cruel!'
if __name__ == "__main__":
main()
Note: This does not work under Gnome but works under fvwm2. Go figure...

Python Window Activation

How would I programmatically activate a window in Windows using Python? I'm sending keystrokes to it and at the moment I'm just making sure it's the last application used then sending the keystroke Alt+Tab to switch over to it from the DOS console. Is there a better way (since I've learned by experience that this way is by no means foolproof)?
You can use the win32gui module to do that. First you need to get a valid handle on your window. You can use the win32gui.FindWindow if you know the window class name or the exact title. If not, you can enumerate the windows with the win32gui.EnumWindows and try to find the right one.
Once you have the handle, you can call the win32gui.SetForegroundWindow with the handle. It will activate the window and will be ready for getting your keystrokes.
See an example below. I hope it helps
import win32gui
import re
class WindowMgr:
"""Encapsulates some calls to the winapi for window management"""
def __init__ (self):
"""Constructor"""
self._handle = None
def find_window(self, class_name, window_name=None):
"""find a window by its class_name"""
self._handle = win32gui.FindWindow(class_name, window_name)
def _window_enum_callback(self, hwnd, wildcard):
"""Pass to win32gui.EnumWindows() to check all the opened windows"""
if re.match(wildcard, str(win32gui.GetWindowText(hwnd))) is not None:
self._handle = hwnd
def find_window_wildcard(self, wildcard):
"""find a window whose title matches the wildcard regex"""
self._handle = None
win32gui.EnumWindows(self._window_enum_callback, wildcard)
def set_foreground(self):
"""put the window in the foreground"""
win32gui.SetForegroundWindow(self._handle)
w = WindowMgr()
w.find_window_wildcard(".*Hello.*")
w.set_foreground()
Pywinauto and SWAPY will probably require the least effort to set the focus of a window.
Use SWAPY to auto-generate the python code necessary to retrieve the window object, e.g.:
import pywinauto
# SWAPY will record the title and class of the window you want activated
app = pywinauto.application.Application()
t, c = u'WINDOW SWAPY RECORDS', u'CLASS SWAPY RECORDS'
handle = pywinauto.findwindows.find_windows(title=t, class_name=c)[0]
# SWAPY will also get the window
window = app.window_(handle=handle)
# this here is the only line of code you actually write (SWAPY recorded the rest)
window.SetFocus()
If by chance other windows are in front of the window of interest, not a problem. This additional code or this will make sure it is shown before running the above code:
# minimize then maximize to bring this window in front of all others
window.Minimize()
window.Maximize()
# now you can set its focus
window.SetFocus()
import ctypes, platform
if platform.system() == 'Windows':
Active_W = ctypes.windll.user32.GetActiveWindow()
ctypes.windll.user32.SetWindowPos(Active_W,0,0,0,0,0,0x0002|0x0001)
Here we go. you just need to store the value of the active window.
Pip install keyboard.
Before you set foreground window, simulate a keyboard to esc that is keyboard.send('esc')
You may want to do it three times for either of the following:
Sidebar
Windows key overlay
Task manager which is always on top
Using SetWindowPos or SetForegroundWindow might NOT be enough if the window was minified aka IsIconic! We can use ShowWindow with SW_RESTORE (9):
import ctypes
def activate_window(hwnd):
user32 = ctypes.windll.user32
user32.SetForegroundWindow(hwnd)
if user32.IsIconic(hwnd):
user32.ShowWindow(hwnd, 9)
Depending on how you identify the desired window there are some ways to get the hwnd aka window handle.
You could loop through all the windows to find the right handle according to the pid via user32.GetWindowThreadProcessId or by window name with user32.GetWindowTextW
To get ProcessIds you could use Windows built-in wmic. There are loads of other nifty things you can do with it. (all attributes: wmic process get /?) (get handle is broken tho) For example:
def get_pids(proc_name):
out = subprocess.check_output('wmic process where Name="%s" get ProcessId' % proc_name)
pids = out.decode().strip().split()[1:]
if not pids:
raise WindowsError('Could not find pids for process')
return [int(pid) for pid in pids]
GUI Application to keep windows active
Python3
install library
pip install pywin32
save below code as alive.pyw file
from ctypes import windll, wintypes, byref, c_uint, sizeof, Structure
import tkinter as tk
import ctypes
import sys
import threading
import time
import win32api
import win32con
stop_threads = True
SET_IDLE_TIME = 40 #in seconds
tm1 = time.time()
value = 0
class LASTINPUTINFO(Structure):
_fields_ = [
('cbSize', c_uint),
('dwTime', c_uint),
]
def get_idle_duration():
global value, tm1
lastInputInfo = LASTINPUTINFO()
lastInputInfo.cbSize = sizeof(lastInputInfo)
windll.user32.GetLastInputInfo(byref(lastInputInfo))
# millis = 4294967 - lastInputInfo.dwTime - windll.kernel32.GetTickCount()
# print(windll.kernel32.GetTickCount(), lastInputInfo.dwTime, sizeof(lastInputInfo), millis)
tm2 = time.time() - tm1
last_idel_time = lastInputInfo.dwTime
# print()
if value != last_idel_time:
value = last_idel_time
tm2 = time.time() - time.time()
tm1 = time.time()
# print("time:", tm1)
return tm2
def press_key_2():
global stop_threads, tm1
while True:
if not stop_threads:
break
idle_time = get_idle_duration() #seconds
# print(idle_time)
g = float("{:.2f}".format(idle_time))
st = str(g) + " / " + str(SET_IDLE_TIME)
var.set(st)
time.sleep(0.1)
if idle_time < SET_IDLE_TIME:
continue
print("in ideal state pressing cltr")
win32api.keybd_event(ord('x'), 0, win32con.KEYEVENTF_EXTENDEDKEY, 0)
tm1 = time.time()
#---------------- Monitor threads ------------------------------
t1 = threading.Thread(target=press_key_2, name='t1')
t1.daemon = True
#----------------- TK functions ----------------------
def display_on():
global tk, t1, stop_threads
stop_threads = True
print("Always On")
ctypes.windll.kernel32.SetThreadExecutionState(0x80000002)
root.iconify()
t1.start()
# t2.start()
def display_reset():
print("quit pressed")
global stop_threads
stop_threads = False
ctypes.windll.kernel32.SetThreadExecutionState(0x80000000)
sys.exit(0)
root = tk.Tk()
root.geometry("200x110")
root.title("Devil")
frame = tk.Frame(root)
frame.pack()
var = tk.StringVar()
var_idle = tk.StringVar()
label = tk.Label(frame, textvariable = var)#, bd = 5, justify = tk.RIGHT, padx = 10, pady = 10)
label_idle = tk.Label(frame,textvariable = var_idle)
var_idle.set("Idle Time")
var.set("-")
button = tk.Button(frame,
text="Quit",
fg="red",
command=display_reset)
slogan = tk.Button(frame,
text="Always ON",
command=display_on)
label_idle.pack(side=tk.BOTTOM,padx=15, pady=13)
label.pack(side=tk.BOTTOM,padx=15, pady=5)
slogan.pack(side=tk.LEFT,padx=15, pady=5)
button.pack(side=tk.LEFT,padx=15, pady=5)
root.mainloop()
ctypes.windll.kernel32.SetThreadExecutionState(0x80000000)
To add on #luc's answer, following is how the code would be more verbose about the handle it selected when multiple windows exist:
After pip install pywin32, run
import win32gui
import re
class WindowMgr:
"""Encapsulates some calls to the winapi for window management"""
def __init__ (self):
"""Constructor"""
self._handle = None
self._handles = []
def find_window(self, class_name, window_name=None):
"""find a window by its class_name"""
self._handle = win32gui.FindWindow(class_name, window_name)
def _window_enum_callback(self, hwnd, wildcard):
"""Pass to win32gui.EnumWindows() to check all the opened windows"""
if re.match(wildcard, str(win32gui.GetWindowText(hwnd))) is not None:
self._handles.append(hwnd)
self._handle = hwnd
def find_window_wildcard(self, wildcard):
"""find a window whose title matches the wildcard regex"""
self._handle = None
self._handles = []
win32gui.EnumWindows(self._window_enum_callback, wildcard)
self.set_handle()
def set_foreground(self):
"""put the window in the foreground"""
if self._handle != None:
win32gui.SetForegroundWindow(self._handle)
else:
print("No handle is selected, couldn't set focus")
def set_handle(self):
"""get one handle to operate on from all the matched handles"""
if len(self._handles) < 1:
print("Matched no window")
return False
if len(self._handles) > 1:
print("Selecting the first handle of multiple windows:")
else: # len(self._handles) == 1:
print("Matched a single window:")
self.print_matches()
self._handle = self._handles[0]
return True
def print_matches(self):
"""print the title of each matched handle"""
for hwnd in self._handles:
print("- " + str(win32gui.GetWindowText(hwnd)))
w = WindowMgr()
w.find_window_wildcard(".*Hello.*")
w.set_foreground()
Note: I couldn't make the addition by editing #luc's answer as its suggested edit queue is full.

PyQt: Call a TrayMinimized application

I have an application wich is minimized to the tray (showing an icon) when the user close it. What I need to know is how can I call it back with a combination of keys, like Ctrl+Alt+Something. Actually I call it back when I double-click it, but it will be nice to do the same on a keystroke. Here is a portion of the code:
# -*- coding: utf-8 -*-
"""The user interface for our app"""
import os,sys
import ConfigParser
# Import Qt modules
from PyQt4 import QtCore,QtGui
# Import the compiled UI module
from octo import Ui_Form
CFG_PATH = "etc/config.list" #Config File Path
#config.list vars DEFAULT Values
ClipCount = 8
Static = ""
window = None
# Create a class for our main window
class Main(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
# This is always the same
self.ui=Ui_Form()
self.ui.setupUi(self)
# Window Icon
icon = QtGui.QIcon("SSaver.ico")
self.setWindowIcon(icon)
self.setWindowTitle("Octopy")
# Set the timer =)
self.timer = self.startTimer(1000) #self.killTimer(self.timer)
# Clipboard Counter
self.counter = 0
#Last trapped clipboard
self.LastClip = ""
self.tentacles = [""] * 8
self.cmd = []
self.cmd.append(self.ui.cmd_1)
self.cmd.append(self.ui.cmd_2)
self.cmd.append(self.ui.cmd_3)
self.cmd.append(self.ui.cmd_4)
self.cmd.append(self.ui.cmd_5)
self.cmd.append(self.ui.cmd_6)
self.cmd.append(self.ui.cmd_7)
self.cmd.append(self.ui.cmd_8)
## Events ##
def on_cmd_8_pressed(self): #Clear
for i in range(0,7):
self.tentacles[i] = ""
self.cmd[i].setText(self.tentacles[i])
def on_cmd_1_pressed(self):
t = self.ui.cmd_1.text()
self.setClp(t)
def on_cmd_2_pressed(self):
t = self.ui.cmd_2.text()
self.setClp(t)
def on_cmd_3_pressed(self):
t = self.ui.cmd_3.text()
self.setClp(t)
def on_cmd_4_pressed(self):
t = self.ui.cmd_4.text()
self.setClp(t)
def on_cmd_5_pressed(self):
t = self.ui.cmd_5.text()
self.setClp(t)
def on_cmd_6_pressed(self):
t = self.ui.cmd_6.text()
self.setClp(t)
def on_cmd_7_pressed(self):
t = self.ui.cmd_7.text()
self.setClp(t)
def hideEvent(self,event): # Capture close and minimize events
pass
def keyPressEvent(self,ev):
if ev.key() == 16777216:
self.hide()
def showEvent(self,ev):
self.fillClp()
def timerEvent(self,ev):
c = self.getClp()
if c:
#print c, self.counter
self.tentacles[self.counter] = c
if self.counter < 7:
self.counter += 1
else:
self.counter = 0
self.fillClp()
## Functions ##
def fillClp(self):
for i in range(0,7):
self.cmd[i].setText(self.tentacles[i])
def getClp(self):
clp = QtGui.QApplication.clipboard()
c = clp.text()
if self.LastClip != c:
self.LastClip = c
return c
else:
return None
def setClp(self, t):
clp = QtGui.QApplication.clipboard()
clp.setText(t)
class SystemTrayIcon(QtGui.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
menu = QtGui.QMenu(parent)
# Actions
self.action_quit = QtGui.QAction("Quit", self)
self.action_about = QtGui.QAction("About Octopy", self)
# Add actions to menu
menu.addAction(self.action_about)
menu.addSeparator()
menu.addAction(self.action_quit)
# Connect menu with signals
self.connect(self.action_about, QtCore.SIGNAL("triggered()"), self.about)
self.connect(self.action_quit, QtCore.SIGNAL("triggered()"), self.quit)
# Other signals
traySignal = "activated(QSystemTrayIcon::ActivationReason)"
QtCore.QObject.connect(self, QtCore.SIGNAL(traySignal), self.icon_activated)
# Create Menu
self.setContextMenu(menu)
def quit(self):
w = QtGui.QWidget()
reply = QtGui.QMessageBox.question(w, 'Confirm Action',"Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
QtGui.QApplication.quit()
def about(self):
w = QtGui.QWidget()
QtGui.QMessageBox.information(w, 'About', "Octopy Multi-Clipboard Manager\n Developed by mRt.")
def icon_activated(self, reason):
if reason == QtGui.QSystemTrayIcon.DoubleClick:
window.show()
else:
print "otro"
def main():
# Again, this is boilerplate, it's going to be the same on
# almost every app you write
app = QtGui.QApplication(sys.argv)
# TrayIcon
w = QtGui.QWidget()
icon = QtGui.QIcon("SSaver.ico")
trayIcon = SystemTrayIcon(icon, w)
trayIcon.show()
trayIcon.setToolTip("Octopy Multi-Clipboard Manager")
# Main Window
global window
window=Main()
window.show()
window.setWindowTitle("Octopy")
app.setQuitOnLastWindowClosed(0)
sys.exit(app.exec_())
def readIni():
cfg = ConfigParser.ConfigParser()
cfg.read(CFG_PATH)
ClipCount = int(cfg.get("Other","ClipCount"))
Static = cfg.get("Other","Static")
clip = [""] * int(ClipCount+1)
if __name__ == "__main__":
readIni()
main()
The complete program is hosted on google: http://code.google.com/p/octopys/downloads/list
For a keystroke to be handled by your application when it does not have keyboard focus, you need to install a global shortcut. Qt doesn't support this, but Qxt, a Qt extension library, does. See
http://doc.libqxt.org/0.5.0/classQxtGlobalShortcut.html. I don't know if PyQt bindings exist for Qxt.

Categories

Resources