OESF | ELSI | pdaXrom | OpenZaurus | Zaurus Themes | Community Links | Ibiblio

IPB

Welcome Guest ( Log In | Register )

 
Reply to this topicStart new topic
> Using "cancel" In Qtopia Apps
kopsis
post Nov 23 2004, 11:57 AM
Post #1





Group: Members
Posts: 329
Joined: 1-July 04
Member No.: 3,880



For a while now I've had a Qtopia application where I wanted to use the "Cancel" button to do something other than close the app. None of my Google or ZUG searches ever turned up the answer so today I decided to dig around a bit in the Qtopia source code. What I discovered is the following very simple trick:

Assuming you have a pointer "main" to your QMainWindow object, you can simply do the following:
CODE
main->setWFlags(main->getWFlags() | WStyle_Customize);


This causes the QPEApplication class to ignore the "Cancel" button and pass it on as a normal key event. The only side effect that I've noticed is that the "Ok" button will no longer be mapped to "Return" but if your app needs "Cancel" control, that may actually be a bonus.

This is probably old news to most Qtopia developers, but I wasn't able to find this info anywhere. Sooner or later someone else is going to need this so hopefully this post will save them from trudging through the Qtopia source code.
Go to the top of the page
 
+Quote Post
vanstrien
post Nov 23 2004, 12:37 PM
Post #2





Group: Members
Posts: 58
Joined: 22-August 03
From: Houston / London
Member No.: 374



Good timing. I was just about to ask a question regarding closing apps, but this might be the answer I need.

Please tell me what you think:

My apps save conifguration values when the app closes down. I use the destructive close, not really knowing how it works, but because a posting I read somewhere said to use it. This means that if the user closes an app with the X on the title bar, the app calls all the destructors.

However, if the user closes the app with the cancel button, I don't get my destructors called and my apps don't save any configuration information. Is this a good time to use the code you pasted above? Or is there a better way to do it?
Go to the top of the page
 
+Quote Post
zenyatta
post Nov 23 2004, 01:59 PM
Post #3





Group: Members
Posts: 366
Joined: 4-November 03
From: Slovakia
Member No.: 850



I once desperately needed to solve this in a Python/PyQt app. What I came up with is about 1000% more complicated than kopsis' solution but it worked for me. The thing is, when you press the Cancel button you actually do receive the keypress but only *after* the corresponding CloseEvent. So I created an event filter that, upon catching a CloseEvent, sets up a 50ms timer. If it catches a Cancel KeyEvent during those 50ms, the app goes on and the Cancel keypress is processed. If the timer times out and there is no Cancel key, the app closes (because you've tapped the X button on the title bar).

Of course, all that would mean that you can *never* close the app with the Cancel key so my filter can be turned off when you don't need to capture the Cancel key.

In retrospect, maybe I shouldn't've been so scared of the WStyle_Customize flag wink.gif

z.
Go to the top of the page
 
+Quote Post
kopsis
post Nov 23 2004, 08:03 PM
Post #4





Group: Members
Posts: 329
Joined: 1-July 04
Member No.: 3,880



QUOTE(vanstrien @ Nov 23 2004, 12:37 PM)
However, if the user closes the app with the cancel button, I don't get my destructors called and my apps don't save any configuration information.  Is this a good time to use the code you pasted above?  Or is there a better way to do it?

I've always subscribed to the philosophy that destructors are for cleaning up memory and not much else. What I usually do is put all my application "cleanup" code (generally saving state info) in a dedicated member function in my QPEApplication derived class. Then I put a call to that method in my "main" right after the call to run(). Doing it that way seems to catch all the normal exit paths.

I only recommend the Cancel button capture technique when your app wants to do something other than exit when cancel is pressed. For example, in my app cancel is like a "back" button.
Go to the top of the page
 
+Quote Post
zenyatta
post Nov 24 2004, 02:10 AM
Post #5





Group: Members
Posts: 366
Joined: 4-November 03
From: Slovakia
Member No.: 850



In my case Cancel is used to finish in-place editing of a table cell, discarding the changes.
Go to the top of the page
 
+Quote Post
lpotter
post Nov 28 2004, 10:38 AM
Post #6





Group: Members
Posts: 451
Joined: 27-November 03
From: Brisbane, Australia
Member No.: 1,001



Why not override keyPressEvent( QKeyEvent *e) or keyReleaseEvent( QKeyEvent *e)
and handle it that way?
CODE
void myApp::keyReleaseEvent( QKeyEvent *e) {
 switch ( e->key() ) {
  case Key_Cancel:
       someRemarkableFunction();
       break;
 };
}
Go to the top of the page
 
+Quote Post
kopsis
post Nov 29 2004, 05:34 AM
Post #7





Group: Members
Posts: 329
Joined: 1-July 04
Member No.: 3,880



QUOTE(lpotter @ Nov 28 2004, 10:38 AM)
Why not override keyPressEvent( QKeyEvent *e) or keyReleaseEvent( QKeyEvent *e)
and handle it that way?

That was the first thing I tried but (at least in Python + PyQt) it doesn't work. In looking at the Qtopia source code for the QPEApplication class, it appears that there's a protected QPEApplication::qwsEventFilter() method that snags the "special" Qtopia keys (Ok, Cancel, App buttons, etc.) and has it's way with them before they make it to keyPressEvent(). Though Cancel will eventually propogate to keyPressEvent(), it happens only after qwsEventFilter() has called close() on the active window. You can use Zenyatta's technique of disregarding the close() in certain circumstances, but that's quite a bit more complicated.

The next logical approach ... overriding qwsEventFilter() in my QPEApplication derived class ... also failed. I suspect that's because qwsEventFilter() is protected and non-virtual, but it could also just be a Python thing (I didn't try it in C++). In any case, the only simple, reliable technique I found for PyQt was my WStyle_Customize hack.
Go to the top of the page
 
+Quote Post
lpotter
post Nov 29 2004, 10:35 AM
Post #8





Group: Members
Posts: 451
Joined: 27-November 03
From: Brisbane, Australia
Member No.: 1,001



You then also need to use this function:
CODE
QPEApplication::grabKeyboard();

QPEApplication::grabKeyboard();
Go to the top of the page
 
+Quote Post
kopsis
post Nov 29 2004, 01:55 PM
Post #9





Group: Members
Posts: 329
Joined: 1-July 04
Member No.: 3,880



Ok, out of curiosity I tried adding grabKeyboard(). It successfully captured the app launching keys but, as I expected, the Cancel button waltzes right through.

Keep in mind that I'm working with the Sharp ROM which is somewhere between Qtopia 1.4 and 1.5. If you take a look at the source for QPEApplication::qwsEventFilter() in old versions of qpeapplication.cpp you'll see that Key_Escape, Key_F30, and Key_F33 each get special handling that is not circumvented by grabKeyboard(). Only Key_F1 through Key_F29 go through the if (d->kbgrabbed) logic. I just pulled down Qtopia 1.7 and this problem has definitely been fixed there, but until someone at Trolltech persuades Sharp to release a ROM with up-to-date Qtopia libraries, I'm gonna have to stick with my Cancel hack.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



RSS Lo-Fi Version Time is now: 21st July 2014 - 11:22 PM