Re: [PyQt] Processing signals from a called method while the method executes
On 01.07.10 21:35:44, alan moore wrote: I've encountered this problem twice now in subtle ways, I think this is at the root of my last question about the QWebView; I've included sample code this time to illustrate. In the attached script, I have a widget class and a processor class. The processor represents some kind of processing engine that's going to do a lengthy multi-part routine of some kind. The widget class is the gui for the engine. The go button is connected to the process method of the processor object. The process() method emits a signal with a string, does process A for 10 seconds, emits a signal with a string, does process B for 10 seconds, and emits a final signal with a string. The widget class is supposed to be picking up the signals and displaying the strings. So the expected output is: click go first message displays wait 10 seconds second message displays wait 10 seconds final message displays The actual output is that nothing happens for 20 seconds, then all the text displays. Because the widget isn't going to process any received signals until the called method exits. How do I produce the expected behavior here? Don't block the event-loop with your processor. The signals are delivered as you expect, but the widget is not redrawn with that message. The reason is that your processing blocks the Qt event loop and hence no painting is done. Possible options to not block the event loop that long would be to use a QTimer to schedule each part of your processing after the next event-loop run. The other option would be moving the processing into a separate thread, you should only go this route after making familiar with multi-threading though. Andreas -- Break into jail and claim police brutality. ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] multiple inheritance and MappedType
On Thu, 1 Jul 2010 15:51:48 -0600, Clinton Stimpson cjstimp...@gmail.com wrote: Hi, I've got an existing library with python wrappers generated with a different tool, and I've successfully used MappedType to interface with that and I'm getting the interoperability I'm looking for. But now I want to use sip to wrap a class that derives from two classes, one is QObject, and the other is a MappedType. I'm getting an error from sip: A class, exception, namespace or mapped type has already been defined with the same name Is inheritance from a MappedType not supported? Correct. An alternative approach is to invent a new class (as far as SIP is concerned) which you can sub-class from. For example, in Qt QItemSelection is sub-classed from QListQItemSelectionRange (which would be implemented as a MappedType). In PyQt QItemSelection isn't sub-classed from anything but has the useful methods from QList added. Phil ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] SIP Bug: virtual function wrapped twice due to deep inheritance from base class and ABC
On Thu, 1 Jul 2010 17:53:23 -0700 (PDT), Demetrius Cassidy dcassid...@mass.rr.com wrote: Phil, It's not code specific to that class. It's due to the deep inheritance tree. You should be able to run my test code and get the same results. Basically to sum it up: PTCPSocket - PIPDataGramSocket - PIPSocket - PSocket (ABC) PTCPSocket, PIPSocket and PSocket all define a virtual function called 'Listen'. Commenting 'Listen' out from PSocket, and SIP does not include the function twice. Listen is NOT a pure virtual function in the ABC, it has a body. Listen is fully defined in PTCPSocket, and the other classes except PIPDataGramSocket. The error appears in PUDPSocket but you don't even mention that class. Where does it fit in the inheritance tree? Phil Phil Thompson-5 wrote: On Sat, 19 Jun 2010 10:27:55 -0700 (PDT), Demetrius Cassidy dcassid...@mass.rr.com wrote: Basically I have a Listen() function in a derived class, that is also in the base and ABC. For some reason sip ends up wrapping the same function twice (it has a body in the ABC), even though it's a virtual function in all of the derived classes. If I comment out this function in the ABC, everything works fine, but otherwise I get a C2535 compiler error with Visual C++. Here is what sip comes up with: class sipPUDPSocket : public PUDPSocket { /* * There is a protected method for every virtual method visible from * this class. */ protected: PBoolean Listen(unsigned,WORD,PIPSocket::Reusability); /*more wrapped functions*/ PBoolean Listen(unsigned,WORD,PIPSocket::Reusability); // -- duplicate function }; C++ nmake errors: sippyptlibPTCPSocket.cpp .\sippyptlibPTCPSocket.cpp(121) : error C2535: 'PBoolean sipPTCPSocket::Listen(unsigned int,WORD,PSocket::Reusability)' : member function already defined or declared .\sippyptlibPTCPSocket.cpp(102) : see declaration of 'sipPTCPSocket::Listen' .\sippyptlibPTCPSocket.cpp(506) : error C2084: function 'PBoolean sipPTCPSocket: :Listen(unsigned int,WORD,PSocket::Reusability)' already has a body .\sippyptlibPTCPSocket.cpp(102) : see previous definition of 'Listen' Basic code structure based on what I am wrapping - note that I only included the offending function here, as it would be too much code to include everything. But you at least need to include the definition of PUDPSocket. typedef bool PBoolean; class PTCPSocket : PIPDataGramSocket { public: virtual PBoolean Listen(unsigned int, WORD, PSocket::Reusability); } class PIPDataGramSocket : PIPSocket { protected: PIPDataGramSocket(); } class PIPSocket : PSocket { public: virtual PBoolean Listen(unsigned int, WORD, PSocket::Reusability); } class PSocket /Abstract/ { public: /// Flags to reuse of port numbers in Listen() function. enum Reusability { CanReuseAddress, AddressIsExclusive }; virtual PBoolean Listen(unsigned int, WORD, PSocket::Reusability); // commenting this function out fixes this problem protected: /*This function calls os_socket() with the correct parameters for the socket protocol type. */ virtual PBoolean OpenSocket() = 0; }; Phil ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Synchronous WebView.load()
On Fri, 02 Jul 2010 00:31:40 -0500, alan moore m...@alandmoore.com wrote: As I understand it, the webview doesn't actually load the page and update itself until the method call returns; at which point it loads the new page and updates the history. No, the load starts straight away but may not finish until some time later (probably after the method returns). The view will update itself when it has enough of the page loaded to be usefully displayed. The display won't actually change until the even loop runs. To illustrate the problem I'm having a little more clearly, I've attached a sample script. The script is supposed to conduct a brief tour of a list of websites when you hit the go button on the browser toolbar. Each site shows for five seconds, then the next on loads. Only that's not what happens. If you run it, you'll see that hitting go causes the browser to hang for about 20 seconds, then the final comment is all that shows. In other words, for the whole duration of the method call, the main window is asleep. I guess this is just another instance of the trouble I was running into on my other program, which I posted a demonstration script for earlier today. I would really appreciate any help on this matter. You need to get rid of your loop and sleep() and connect to the QWebView.loadFinished() signal. In the connected slot start a timer for 5 seconds. When that timer times out you can then set the next URL. Phil ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Processing signals from a called method while the method executes
On Friday 02 July 2010 1:17:06 am Andreas Pakulat wrote: Don't block the event-loop with your processor. The signals are delivered as you expect, but the widget is not redrawn with that message. The reason is that your processing blocks the Qt event loop and hence no painting is done. Possible options to not block the event loop that long would be to use a QTimer to schedule each part of your processing after the next event-loop run. The other option would be moving the processing into a separate thread, you should only go this route after making familiar with multi-threading though. Andreas Thanks for the reply. I don't think I understand, though. I read in the QTimer documentation where I can do a zero-millisecond timer to schedule things after the next event run, but changing sleep(10) To: QTimer.singleShot(0, lambda: sleep(10)) Seemed like it should do that. It doesn't. Apparently the processor.process() method is still blocking. Where am I going wrong here? ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Synchronous WebView.load()
On Friday 02 July 2010 3:04:40 am you wrote: On Fri, 02 Jul 2010 00:31:40 -0500, alan moore m...@alandmoore.com wrote: As I understand it, the webview doesn't actually load the page and update itself until the method call returns; at which point it loads the new page and updates the history. No, the load starts straight away but may not finish until some time later (probably after the method returns). The view will update itself when it has enough of the page loaded to be usefully displayed. The display won't actually change until the even loop runs. Thanks for the response. From my experimenting with this, apparently the history doesn't update until after the display does. I tried something like this: def reset_browser(self): self.webview.load(self.homepage) while self.webview.history().currentItem().url() != self.homepage: pass self.webview.history().clear() With the idea being that I'd wait until the history had changed to clear it, but it never changed. The while loop went on infinitely. To illustrate the problem I'm having a little more clearly, I've attached a sample script. The script is supposed to conduct a brief tour of a list of websites when you hit the go button on the browser toolbar. Each site shows for five seconds, then the next on loads. Only that's not what happens. If you run it, you'll see that hitting go causes the browser to hang for about 20 seconds, then the final comment is all that shows. In other words, for the whole duration of the method call, the main window is asleep. I guess this is just another instance of the trouble I was running into on my other program, which I posted a demonstration script for earlier today. I would really appreciate any help on this matter. You need to get rid of your loop and sleep() and connect to the QWebView.loadFinished() signal. In the connected slot start a timer for 5 seconds. When that timer times out you can then set the next URL. Phil I can see how that works for this example. In the case of my original program, I'm not so sure. I can't connect webview.history().clear() to loadFinished(), or else every single page load will clear the history. And I can't connect and disconnect in the same callback, because it won't be processed until the callback exits. Thanks again for your help. ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] SIP Bug: virtual function wrapped twice due to deep inheritance from base class and ABC
Sorry Phil - corrected inheritance tree: PUDPSocket - PIPDataGramSocket - PIPSocket - PSocket (ABC) PTCPSocket - PIPSocket - PSocket (ABC) PUDPSocket does not have a 'Listen' function in it, instead it just inherits it from PIPSocket, who overrides PSocket. PTCPSocket DOES include a 'Listen' function in it, and overrides it from PIPSocket and PSocket. I've attached the corresponding sip files and the generated .cpp files from sip. Below I've also included a snippet of the generated code for both classes. The weird thing is that SIP wraps the PIPSocket Listen function, along with the one from PSocket. http://old.nabble.com/file/p29056623/ptlib.rar ptlib.rar class sipPUDPSocket : public PUDPSocket { public: /* * There is a protected method for every virtual method visible from * this class. */ protected: ... PBoolean Listen(unsigned,WORD,PIPSocket::Reusability); PBoolean Listen(const PIPSocket::Address,unsigned,WORD,PIPSocket::Reusability); ... PBoolean Listen(unsigned,WORD,PSocket::Reusability); } class sipPTCPSocket : public PTCPSocket { public: ... /* * There is a protected method for every virtual method visible from * this class. */ protected: PBoolean Listen(unsigned,WORD,PIPSocket::Reusability); PBoolean Listen(const PIPSocket::Address,unsigned,WORD,PIPSocket::Reusability); ... PBoolean Listen(unsigned,WORD,PSocket::Reusability); }; Both classes share the same exact inheritance bug when wrapped: Phil Thompson-5 wrote: On Thu, 1 Jul 2010 17:53:23 -0700 (PDT), Demetrius Cassidy dcassid...@mass.rr.com wrote: Phil, It's not code specific to that class. It's due to the deep inheritance tree. You should be able to run my test code and get the same results. Basically to sum it up: PTCPSocket - PIPDataGramSocket - PIPSocket - PSocket (ABC) PTCPSocket, PIPSocket and PSocket all define a virtual function called 'Listen'. Commenting 'Listen' out from PSocket, and SIP does not include the function twice. Listen is NOT a pure virtual function in the ABC, it has a body. Listen is fully defined in PTCPSocket, and the other classes except PIPDataGramSocket. The error appears in PUDPSocket but you don't even mention that class. Where does it fit in the inheritance tree? Phil Phil Thompson-5 wrote: On Sat, 19 Jun 2010 10:27:55 -0700 (PDT), Demetrius Cassidy dcassid...@mass.rr.com wrote: Basically I have a Listen() function in a derived class, that is also in the base and ABC. For some reason sip ends up wrapping the same function twice (it has a body in the ABC), even though it's a virtual function in all of the derived classes. If I comment out this function in the ABC, everything works fine, but otherwise I get a C2535 compiler error with Visual C++. Here is what sip comes up with: class sipPUDPSocket : public PUDPSocket { /* * There is a protected method for every virtual method visible from * this class. */ protected: PBoolean Listen(unsigned,WORD,PIPSocket::Reusability); /*more wrapped functions*/ PBoolean Listen(unsigned,WORD,PIPSocket::Reusability); // -- duplicate function }; C++ nmake errors: sippyptlibPTCPSocket.cpp .\sippyptlibPTCPSocket.cpp(121) : error C2535: 'PBoolean sipPTCPSocket::Listen(unsigned int,WORD,PSocket::Reusability)' : member function already defined or declared .\sippyptlibPTCPSocket.cpp(102) : see declaration of 'sipPTCPSocket::Listen' .\sippyptlibPTCPSocket.cpp(506) : error C2084: function 'PBoolean sipPTCPSocket: :Listen(unsigned int,WORD,PSocket::Reusability)' already has a body .\sippyptlibPTCPSocket.cpp(102) : see previous definition of 'Listen' Basic code structure based on what I am wrapping - note that I only included the offending function here, as it would be too much code to include everything. But you at least need to include the definition of PUDPSocket. typedef bool PBoolean; class PTCPSocket : PIPDataGramSocket { public: virtual PBoolean Listen(unsigned int, WORD, PSocket::Reusability); } class PIPDataGramSocket : PIPSocket { protected: PIPDataGramSocket(); } class PIPSocket : PSocket { public: virtual PBoolean Listen(unsigned int, WORD, PSocket::Reusability); } class PSocket /Abstract/ { public: /// Flags to reuse of port numbers in Listen() function. enum Reusability { CanReuseAddress, AddressIsExclusive }; virtual PBoolean Listen(unsigned int, WORD, PSocket::Reusability); // commenting this function out fixes this problem protected: /*This function calls os_socket() with the correct parameters for the socket protocol type. */ virtual PBoolean OpenSocket() = 0; }; Phil ___ PyQt
Re: [PyQt] Processing signals from a called method while the method executes
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 7/2/10 3:38 PM, alanm wrote: On Friday 02 July 2010 1:17:06 am Andreas Pakulat wrote: Don't block the event-loop with your processor. The signals are delivered as you expect, but the widget is not redrawn with that message. The reason is that your processing blocks the Qt event loop and hence no painting is done. Possible options to not block the event loop that long would be to use a QTimer to schedule each part of your processing after the next event-loop run. The other option would be moving the processing into a separate thread, you should only go this route after making familiar with multi-threading though. Andreas Thanks for the reply. I don't think I understand, though. I read in the QTimer documentation where I can do a zero-millisecond timer to schedule things after the next event run, but changing sleep(10) To: QTimer.singleShot(0, lambda: sleep(10)) Seemed like it should do that. It doesn't. Apparently the processor.process() method is still blocking. Where am I going wrong here? What this actually does is to start a single-shot QTimer (timing out immediately) to run a callback during the next run of the event-loop; Thus far, you understood things correctly. However, _INSIDE_ this callback, you still set the GUI-thread and, as a consequence, the event-loop to sleep for 10 seconds. This is obviously not what you wanted... A better idea would be to call QTimer.singleShot(1, your_actual_processing_callback) which delivers a timeout event triggering your callback after 10 seconds (1 ms). The difference is that a QTimer runs asynchronously in a thread by itself, while sleep runs synchronously in the thread it is called in, thus blocking the event loop which does the same. The processing callback should be reasonably short-running, otherwise you'll run into the same problem again; in this case, your best bet is to work your way into multithreading using the QThread class and triggering your processing-thread's run method as the timer callback. However, threads are often a good way to mess things up completely (deadlocks etc...), so don't go for them unless you really have to. Jan -BEGIN PGP SIGNATURE- Version: GnuPG/MacGPG2 v2.0.14 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQIcBAEBAgAGBQJMLhvdAAoJEJY4GpQWZadM80EP/iEhiNdKICnezSYwaknTs/Fv GyV9J6LDi+jfj8wf9yMfFxoUp0Qwlu+ncAPMq5MIZG95HPepKEzPn9JY7dA9WfsP +Ehkyb5LiutL3lZCWvHoujFK4zv4XQJJt+llPCOTEjgw93EM2X9UNYcIeTucN6J/ LMSJIldfgBBLzr4NNal3nPEutfM7QTs6FqZ08+P9bBs/cOqf0Y5UbWmwhBxUAPnv zOus/DmQ7GVZcpdoyvjdtmA2JAHJJ8DyJeJC7deOHFVA+E+2Lfu4Uvl+QHZzKGKa fQEySvtG6QvITyNloJvpYozfAM8Rv/Wwb5sIOc8u2cLmUZ0K7UvrN/NK6Y+yhfe+ /NVGKSpoTHeW21ib4q5rK2/tGZ9iCvJRtfmLLGUDWvLlm/OW1Jro2kowXeZAJmmH MVLOMofQOs8ZlefgVwGn2CavMTHDH/lSnLQ/thpQgE0s4Y0M5lANn1TTPM+n5GWf eIIaqc1tzJQI9cdwL6rhbdP3R8Q9EMKMPjupWhC5gEy8SAIMWv1vRD6qVym57ov/ TBoYlEUgx0K1xJMFcCKCwsfI2sUNzL/BYKMf5eG54ij/KxPDhS3Kg6y2IGXglm9r e/ZPIgqBjhbFMxznYui3o2rATPOUU5T7ChP9ONq+R4PCCNWV6L1u/sErqe2c/Fid jpN5/NBrXHrPzAeFxuEv =Cowg -END PGP SIGNATURE- 0x1665A74C.asc Description: application/pgp-keys 0x1665A74C.asc.sig Description: Binary data ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Re: [PyQt] Processing signals from a called method while the method executes
On Friday 02 July 2010 12:03:29 pm Jan Haag wrote: On 7/2/10 3:38 PM, alanm wrote: On Friday 02 July 2010 1:17:06 am Andreas Pakulat wrote: Don't block the event-loop with your processor. The signals are delivered as you expect, but the widget is not redrawn with that message. The reason is that your processing blocks the Qt event loop and hence no painting is done. Possible options to not block the event loop that long would be to use a QTimer to schedule each part of your processing after the next event-loop run. The other option would be moving the processing into a separate thread, you should only go this route after making familiar with multi-threading though. Andreas Thanks for the reply. I don't think I understand, though. I read in the QTimer documentation where I can do a zero-millisecond timer to schedule things after the next event run, but changing sleep(10) To: QTimer.singleShot(0, lambda: sleep(10)) Seemed like it should do that. It doesn't. Apparently the processor.process() method is still blocking. Where am I going wrong here? What this actually does is to start a single-shot QTimer (timing out immediately) to run a callback during the next run of the event-loop; Thus far, you understood things correctly. However, _INSIDE_ this callback, you still set the GUI-thread and, as a consequence, the event-loop to sleep for 10 seconds. This is obviously not what you wanted... A better idea would be to call QTimer.singleShot(1, your_actual_processing_callback) which delivers a timeout event triggering your callback after 10 seconds (1 ms). The difference is that a QTimer runs asynchronously in a thread by itself, while sleep runs synchronously in the thread it is called in, thus blocking the event loop which does the same. I think I confused everyone with the sleep(10) calls; the intention wasn't to actually have a ten second delay, but just to have a place-holder for some real call that might take 10 seconds or more, such as a file copy, subprocess call, etc. Anyway, I finally solved my problem using threads; by making processor subclass QThread instead of QObject, renaming process() to run() and connecting the gobutton to processor.start() I got the correct behavior. Thanks for your response. ___ PyQt mailing listPyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt