Python/PyQt/Qt QMenu QAction syntax - python

I have a syntax/understanding problem in an application using Python 3, PyQt5 and Qt5. I am unsure which of these is causing the problem.
I am charged with porting a GUI application which worked under Windows to Linux, with newer versions of libraries. I do not have access to the original running under Windows.
In several places I see:
menu = QMenu(self)
action = menu.addAction("Some string")
action.triggered[()].connect(self.handler)
I presume this used to work. I am porting to Python 3.5, PyQt 5.7 & Qt 5.7. I have reason to believe the code was written for earlier versions of each of these.
Executing it now generates a 'there is no matching overloaded signal' error, on the action.triggered[()] segment.
By guesswork and looking at a couple of examples I found somewhere, I have changed the last line to:
action.triggered.connect(self.handler)
and it seems to work now.
Could someone explain what the original triggered[()] syntax meant/worked, and which "product" the evident change was in --- it would be nice to be able to read about where this got changed? Is my replacement by simply triggered correct/same behaviour?

The relevant change happened in PyQt-5.3. It is not entirely safe to simply remove the old syntax, as this could easily create a subtle bug in both current and future code.
The issue is that certain signals like triggered will always send a default boolean value unless you take steps to eliminate it. Qt defines these signals like this:
triggered(bool checked = false)
PyQt previously implemented this as two overloads:
triggered(bool checked)
triggered()
and if you wanted to explicitly select the latter overload, you had to use the following slightly awkward sytax:
triggered[()].connect(slot)
But this is now no longer an option, as only the first overload is implemented. So to get exactly the same behaviour, it is necessary to either wrap the handler like this:
triggered.connect(lambda checked: slot())
or decorate it like this:
#QtCore.pyqtSlot()
def handleTriggered(self):
pass
Otherwise, it is quite easy to fall into a little trap. Imagine you have a method defined like this:
def frobnicate(self, foobar=True):
if foobar:
# do something nice
else:
# empty my home directory without prompting
Later on, you decide to hook this up to a button, like this:
self.button.clicked.connect(self.frobnicate)
Which all seems perfectly fine, until you find out that the clicked signal works just like triggered, and always sends False by default...
Of course, if you're absolutely certain that you will never connect slots which take arguments to signals like triggered and clicked, you could get away with connecting them all in the simplistic fashion shown above. But, really, that is just an accident waiting to happen...

Related

How I can be aware of a code change in the return when using unpacking

Recently I have a problem when a coworker made a change in a signature for a function return, we have clients that call the function in this way:
example = function()
But then as I was depending on his changes, he unintentionally change to this:
example, other_stuff = function()
I was not aware of this change, I did the merge and everything seem ok but then the error happen as I was expecting one value, but now it was trying to unpack two
So my question is knowing python is not a typed language, is there a way to know this happen and prevent this behavior (a tool or something), because sadly was until a runtime error was raise when I notice this, or how did we need to handle this
Sounds like a process error. An API shouldn't change its signature without considering its users. Within a project its easy, just search. Externally, the API version number should be bumped and the change should be in the change notes.
The API should have unit tests which include return value tests. "he unintentionally changed" issues should all be caught there. Since this didn't happen, a bug report against the tests should be written.
Of course, the coworker could just change those tests. But all of that should be in a code reviewed change set in your source repository. The coworker should have to justify the change and how to mitigate breakage. Since this API appears to have external clients, it should be very difficult to get an API signature change as all clients will need to be notified.

Is there a way to override this already existing function?

What I want to specifically know is if there is a way to customize a piece of code already running by certain software.
I'll explain quickly the process of this software. When opening, of course there's all those pieces of codes being loaded, mostly divised in two entities, UI and Core, mostly because it will eventually be able to work without an interface (which is not the case right now, but that's not my point here).
So the soft is structure mostly like this:
software/
core/
some_functions.py
ui/
function_a.py
class processUIBase(inheritanceUI):
def __init__(blabla):
code = foo
def method(self):
print "hello world"
def createWidget(self):
widget = QLabel('Widget setting:')
layout.addWidget(widget)
return widget
function_b.py
[...]
Then comes in the plugins. There's a folder the software checks to bring the plugins, which works in a similar fashion (core/Ui).
/home/.software/
Startup/ (What is loaded as plugins with the core)
__init__.py
plugins_that_works_well.py
StartupUI/ (What is loaded as plugins with the UI)
__init__.py
menu.py
Basically, all this works right now.
But what I'd like to know is if there's a way for me to make something in the plugins folder (so without touching the software's base scripts) to override, for example, the function 'createWidget', to add some new lines (eg: widget_b = QCheckbox, layout,addWidget(widget_b).
How can I achieve that?
Thanks!
It's difficult to change the behavior of code you can't directly modify. One solution that's kind of risky, but which is possible to do, is to swap out the original version of the function/class in the module with your own version, such that your own version acts very similar.
Here, you might be able to make a subclass and reassign it:
from software.ui import function_a
# maintain a reference to the original version, so it doesn't get lost
_ProcessUIBase = function_a.ProcessUIBase
# make a new subclass that does what you want
class ProcessUICustom(_ProcessUIBase):
# override the superclass's method
def createWidget(self):
# add the functionality you want
self.widget_b = QCheckbox, layout,addWidget(widget_b)
# then do the original functionality
return super().createWidget()
# replace the original class with our new version
function_a.ProcessUIBase = ProcessUICustom
This change will reflect across the rest of the program (as soon as someone imports the module in which you do this) for anything else that tries to use function_a.ProcessUIBase. It won't affect any other programs that import the same library, and the change will revert as soon as the program finishes executing. Also, there are ways around it by using importlib to reload the original function_a, which will wipe away the change. But it might be what you're looking for in this case.
Note that, if something else in the main part of the program has already imported ProcessUIBase directly (i.e. not just the module it's in, but the actual class):
from software.ui.function_a import ProcessUIBase
then this won't affect the version that's already been imported.
In essence, this is like changing someone's address in a directory. You can misdirect new people who look for that person, but if someone else already knows where to find that person, they won't be fooled.

Python. Get flashing/blinking windows of a chat

I want to focus a windows when it is blinking/flashing. The more common case is when someone sends some text by a chat software (for example MSN). In this case the windows bar is going to start blink in the start bar. I don't know if i am explaining myself. I want to get the HWND of the blinking windows. If more info is necesary to understand it, I will try to explain me better.
I have already searched info about this case but I find nothing. Maybe it can be resolver using "win32gui" library.
Thank you for your help!!!
First, most programs flash their windows by calling FlashWindowEx (or some higher-level function that wraps it). But there are a few apps—mostly from Microsoft—that do some custom stuff instead that looks like window-flashing to the end user, but may not look the same under the covers. Hopefully, you don't care about any such custom apps.
Anyway, the easiest way to capture that information is to install a shell hook with SetWindowsHookEx or RegisterShellHookWindow. (You could instead explicitly inject code in front of user32.dll… but you don't want to try that from Python.) When you do this, Windows will treat your window as if it were part of Explorer (the "shell") and send it special messages about what other programs are doing—in particular, WM_SHELLHOOKMESSAGE.
As forivall pointed out, this might be easier to do from AutoHotkey—this answer in the forums shows how to do it. It might also be easier to do from VB, or even C++. Yes, those languages are generally more difficult than Python, but the actual logic in your code is pretty trivial, and the only hard part is getting the shell hook messages, and that part will be easier in those languages. Another alternative is to use IronPython and do it via .NET.
But you asked if it's possible to do it from Python, and… yes, it is. I believe the relevant functions are not wrapped up by win32gui, so you'll have to use ctypes to do it from Python. See this SO question for a possible example, and look at some of the Related questions on the side and the ctypes docs for other examples of using ctypes to call different functions out of user.dll.
If you want to set a windows hook, the key function will look something like this (see ShellProc for details):
HSHELL_REDRAW=6
WM_SHELL=10
def my_callback(nCode, wParam, lParam):
if nCode == HSHELL_REDRAW and lParam:
got_flashing_window_with_hwnd(wParam)
hook = user32.SetWindowsHookEx(WM_SHELL, my_callback, None, 0)
But you need to set the types and push the callback through ctypes.
If you already have a window that you're managing from Python, it's probably easier to set yourself up as a shell hook window instead:
user32.RegisterShellHookWindow(my_hwnd)
Then, in your window proc:
WM_SHELLHOOKMESSAGE = None
def wndproc(hWnd, uMsg, lParam, wParam):
if WM_SHELLHOOKMESSAGE is None:
WM_SHELLHOOKMESSAGE = user32.RegisterWindowMessage('SHELLHOOK')
if uMsg == WM_SHELLHOOKMESSAGE and wParam == HSHELL_FLASH:
got_flashing_window_with_hwnd(lParam)
I'm not sure whether you need elevated privileges for either of these, but I would suspect you do.

Drag drop support for a GtkTreeView where the model is filtered and sorted

As the title suggests, I have a gtk.TreeView whose model is sorted and filtered. According to the documentation: "Drag and drop reordering of rows only works with unsorted stores.". The only other information given relates to using external sources, which in this case I don't need.
I tried implementing it anyway, providing handlers to the drag-dest received and drag-drop signals, but still get the following error:
GtkWarning: You must override the default 'drag_data_received' handler on GtkTreeView when using models that don't support the GtkTreeDragDest interface and enabling drag-and-drop. The simplest way to do this is to connect to 'drag_data_received' and call g_signal_stop_emission_by_name() in your signal handler to prevent the default handler from running. Look at the source code for the default handler in gtktreeview.c to get an idea what your handler should do. (gtktreeview.c is in the GTK source code.) If you're using GTK from a language other than C, there may be a more natural way to override default handlers, e.g. via derivation.
Despite this, although I haven't implemented it yet, it looks like I could make it work, since it doesn't crash. Nevertheless, this is a warning I'd rather not have.
So, Is there a python equivalent of g_signal_stop_emission_by_name, or am I going about this the wrong way?
I got a bit confused as I already had a "drag-drop" handler but was sorted once I implemented the following:
def __init__(self):
self.treeview.connect("drag_data_received", self.on_drag_data_received)
def on_drag_data_received(self, widget, drag_context, x, y, selection_data, info, timestamp):
widget.stop_emission('drag_data_received')
Just to add, according to pygtk docs, *emit_stop_by_name* and *stop_emission* are identical.
It is gobject.GObject.emit_stop_by_name(). I don't know if what you are doing will succeed, but there is no "standard" way I can think of.
Instead of implementing yourself, you could try using Py-gtktree: see example called drag_between_tree_and_list.py. You can sort the tree on the right and still be able to drag into it with items dragged in automatically placed in the "correct" position. It doesn't allow draggin anywhere into the tree, but for a different reason: example explicitly requests this.
I got rid of the warning by using treeview.stop_emission('drag-drop-received') in my own drag-drop-received signal handler. Perhaps the method by doublep will also work, although I haven't tried it.

X11 - How to raise another application's window using Python

I'd like to be able to raise another application's Window using Python.
I did see this, which I suppose I could try:
X11: raise an existing window via command line?
However, I'd prefer to do it in Python if at all possible.
To activate another window, the right thing to do on the Xlib protocol layer is to send a _NET_ACTIVE_WINDOW message as described in the EWMH spec
http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html
This could be done with python-xlib (presumably) or with gdk_window_focus() on a foreign GdkWindow using GDK through pygtk
_NET_ACTIVE_WINDOW is superior to XRaiseWindow() and has been in all the important WMs for many many years.
You should avoid XSetInputFocus() which will cause problems (especially if you get the timestamp wrong). The issue is that the WM can't intercept the SetInputFocus() so it causes weird race conditions and UI inconsistencies.
Really only _NET_ACTIVE_WINDOW works properly, which is why it was invented, because the previous hacks were bad.
There is a library called libwnck that will let you activate windows (among other things) but unfortunately it adds quite a lot of overhead because it always tracks all open windows from any app, even if you don't need to do that. However if you want to track windows from other apps anyway, then libwnck has a function to activate those windows that does the right thing and would be a good choice.
The strictly correct approach is to check for EWMH _NET_ACTIVE_WINDOW support (EWMH documents how to do this) and fall back to XRaiseWindow if the WM doesn't have _NET_ACTIVE_WINDOW. However, since any WM that's been actively worked on in the last many years has EWMH, lots of people are lazy about the fallback for legacy WMs.
You need to use python-xlib and call .circulate(Xlib.X.RaiseLowest) on the window object (which can be identified in many, many different ways -- can't guess which one is appropriate for you from the zero amount of info about it in your Q;-). For a great example of using python-xlib, check out the tinywm window manager -- after the C version, the author gives a Python version that takes about 30 non-blank, non-comment lines (for a usable, if tiny, window manager...!-).
You can have a look at the python ewmh package. Documentation contains examples, but here is how you can achieve what you want:
from ewmh import EWMH
import random
ewmh = EWMH()
# get every displayed windows
wins = ewmh.getClientList()
# let's active one window randomly
ewmh.setActiveWindow(random.choice(wins))
# flush requests - that's actually do the real job
ewmh.display.flush()

Categories