gmessage{gWidgets} incorrect (?) behaviour - r

Here is the simplest possible example:
library(gWidgets)
gmessage("error test", icon="error")
gmessage("error test", icon="error")
If you choose tcltk as the gui toolkit the code works as expected, i.e. when the dialog appears clicking 'cancel' button dismisses the dialog and returns control back to your R session. But if you choose RGtk2, the second call to 'gmessage' does not produce any dialog or it is invisible, and as the 'gmessage' is a modal dialog, you lose control of your session.
If this is not a bug, please tell me what the correct way of calling 'gmessage' with RGtk2. Thank you.
P.S. There is a reason I don't provide parent/container as an argument. Just don't want to widen discussion.
P.P.S. I use R 2.14 (company decision) on openSuSE.

Related

How to get the clicked choice in the closing form dialog?

When I close the Form appear this DialogBox
I need to get the action clicked in this dialog (for example Yes or No etc...) in Form's method canClose
In debug the last point is in:
\Forms\MyForm\Methods\canClose
ret = super();
How I can get the clicked choice?
Thanks in advice.
You cannot get the answer from the prompt.
The return value of super is true, if the user can leave the form.
You do not describe what you want to achieve, but "No" is the answer to your question.
The prompt comes when a value in the record is change and the users press the Esc key. If the user selects Yes, the write method is called. So you may set a flag canClose and then test it in write. But I honestly not see the reason why this would be useful.
Check some lookup and dialog forms.
They uses closeOk, closedOk, closeCancel and closedCancel methods.
There are also closeSelect and closeSelectRecord methods to assign selected record (check also selectMode method on the form).

QFileDialog component signals

I am subclassing QFileDialog to try to get some custom behavior. I would like to connect to signals emitted by components of the dialog, e.g. the textEdited signal when the file name line edit is manually edited. I understand that QFileDialog emits some signals itself, but these do not cover the cases I would like to respond to.
I have two ways about this I can think of, but don't know how to implement. One is to somehow attain a reference to the component to connect to it's signal. The other would be something with event filters, but the event source is the dialog itself, so I don't know how to determine where mouse clicks or key presses occur.
Are either of these methods feasible? Or another way?
Here is one option (your first suggestion):
dialog = QFileDialog()
layout = dialog.layout()
# for i in range(layout.rowCount()):
# for j in range(layout.columnCount()):
# try:
# print i,j
# print layout.itemAtPosition(i,j).widget()
# except:
# pass
line_edit = layout.itemAtPosition(2,1).widget()
line_edit.setText('Hello Stack Overflow')
dialog.exec_()
This gives you access to the QLineEdit in the dialog, which has a bunch of signals you can connect to.
I've also included the code I used to find this widget. I just iterated over the widgets in the layout of the dialog and found the indices of the one I was after. So if you need access to anything else in the dialog, you should be able to find it pretty easily!
Downside to this method: If the layout changes in a future version of Qt, this will break. I suppose you could make the algorithm more robust by looking for widgets that are instances of QLineEdit, but there are always risks with hacky approaches like this!

RGTK2 block user input while processing

I have written a GUI in R with RGTK2 and Tcltk that does a lot of fairly heavy calculations and aggregations on big data sets.
I would like to find a way to stop the user interface from accepting user inputs while it is processing a large data set, and ideally, change the interface color, popup a dialogue, or change the mouse pointer to an hourglass/spinner to indicate to users that the application is active.
The implementation that I want would look something like:
gSignalConnect(bigRedButton,"clicked",
f=function(widget)
{
something$start() # object with method that blocks further user input
# and pops up loading bar or "Processing" dialogue
# (or possibly spins the mouse)
# Code that does a very big set of calculations
something$stop() # unblocks user inputs and removes visual impedance
}
)
I have tried using gtkDialogue to solve the problem, but this seems to stop execution of the whole program until one closes the dialogue, which rather defeats the purpose.
Any help would be greatly appreciated.
So the magic method is gtkWidgetSetSensitive:
gSignalConnect(bigRedButton,"clicked",
f=function(widget)
{
gtkWidgetSetSensitive(Window,FALSE)
# Code that does a very big set of calculations
gtkWidgetSetSensitive(Window,TRUE)
}
)
This method turns the targeted widget (which can be an individual button, textEntry, comboBox, etc...) gray and blocks input.

R and gWidgets: Event trigger on close of a widget

I'm currently working on a small GUI based application using gWidgets (RGtk2).
I've encountered a question which I was unable to solve by myself using the documentation provided in the gWidgets package:
Is it possible to trigger an event, i.e. a function, when the user clicks on the red cross to close the GUI / widgets/ main window? For usability reasons I don't want to have an extra button though it will definitely work.
PS: I don't think an example is necessary here but if any of you insists I will add one.
Try
addhandlerdestroy( myWidget, handler = f_exit )
where
f_exit <- function( h,...
{
# your code, maybe simply
dispose( myWidget )
}

Asynchronous validation in QWizard

I'm writing a wizard UI based on the QWizard Qt object. There's one particular situation where I want the user to log in to a service using host, username, and password. The rest of the wizard then manipulates this service to do various setup tasks. The login may take a while, especially in error cases where the DNS name takes a long time to resolve -- or perhaps it may not even resolve at all.
So my idea is to make all three fields mandatory using the registerField mechanism, and when the user hits Next, we show a little throbber on the wizard page saying "Connecting to server, please wait..." while we try to connect in the background. If the connection succeeds, we advance to the next page. If not, we highlight the offending field and ask the user to try again.
However, I'm at a loss for how to accomplish this. The options I've thought of:
1) Override validatePage and have it start a thread in the background. Enter a wait inside validatePage() that pumps the Qt event loop until the thread finishes. You'd think this was the ugliest solution, but...
2) Hide the real Next button and add a custom Next button that, when clicked, dispatches my long running function in a thread and waits for a 'validation complete' signal to be raised by something. When that happens, we manually call QWizard::next() (and we completely bypass the real validation logic from validatePage and friends.) This is even uglier, but moves the ugliness to a different level that may make development easier.
Surely there's a better way?
It's not as visually appealing, but you could add a connecting page, and move to that page. If the connection succeeds, call next() on the wizard, and if the connection fails, call previous() and highlight the appropriate fields. It has the advantage of being relatively straightforward to code.
My final choice was #2 (override the Next button, simulate its behavior, but capture its click events manually and do the things I want to with it.) Writing the glue to define the Next button's behavior was minimal, and I was able to subclass QWizardPage with a number of hooks that let me run my task ON the same page, instead of having to switch to an interstitial page and worry about whether to go forwards or backwards. Thanks Caleb for your answer though.
I know this has already been answered (a long time ago!) but in case anyone else is having the same challenge. Another method for this is to create a QLineEdit, initiate it as empty and set it as a mandatory registered field. This will mean that "Next" is not enabled until it is filled with some text.
Run your connection task as normal and when it completes use setText to update the QLineEdit to "True" or "Logged in" or anything other than empty. This will then mean the built in isComplete function will be passed as this previously missing mandatory field is now complete. If you never add it to the layout then it won't be seen and the user won't be able to interact with it.
As an example ...
self.validated_field = QLineEdit("")
self.registerField('validated*', self.validated_field)
and then when your login process completes successfully
self.validated_field.setText("True")
This should do it and is very lightweight. Be sure though that you consider the scenario where a user then goes back to that page and whether you need to reset the field to blank. If that's the case then just add in the initialisePage() function to set it back to blank
self.validated_field.setText("")
Thinking about it you could also add the line edit to the display and disable it so that a user cannot update it and then give it a meaningful completion message to act as a status update...
self.validated_field = QLineEdit("")
self.validated_field.setDisabled(True)
self.validated_field.setStyleSheet("border:0;background-color:none")
self.main_layout.addWidget(self.validated_field)
self.registerField('validated*', self.validated_field)
and then when you update it..
self.validated_field.setText("Logged in")

Resources