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

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).

Related

How to capture user comments in watson conversation where we cant define intent

Iam working on small flow in watson conversation.Currently I want to capture the comments given by the user,but Iam not sure what would be the intent or entity to be used if any in this case.
To be more clear,
1.In one dialog node,watson will give some data and ask to provide comments if required
2..If yes .It will ask for comments .Then user will provide some
3.On enter it should go to Thankyou node where it will display some acknowledgement
and jump back to main branch node.
Issue for me here is:
On which condition can I go to Thankyou node after user gives his comment since I cant
give any intent or entity.
Can someone help me with any ideas
If you wish your thanks you node to always execute, and say thanks for our feedback etc, then the easiest condition to add is simply "true" so just add the word true into the trigger / condition element, and the node will always be executed. This is also a great condition to add to any conversation flow as the last default node.

Change checkbox state to not checked when other checkbox is checked pyqt

I'm using Qt Designer and pyqt code to write an app.
I have a very simple question: in my UI I have 2 checkboxes and what I need is to set the first checkbox as always unchecked when the second checkbox is unchecked.
In other words the first checkbox can be checked only when the second checkbox is checked, but the second checkbox can be checked also if the first one is not checked.
In Qt Designer I have not find an easy way to do that with the Signals/Slots function.
I had a look in the Qt API and I tried to write some code:
class CreateRIVLayerDialog(QDialog, FORM_CLASS):
def __init__(self, iface)
# some more code here...
if self.addCheckDB.isChecked():
self.addCheck.setChecked(False)
but without results.
Does anybody have some hints?
Thanks
The simplest way is with two signal connections, one of which can be done in Qt Designer.
Your design requires that "the first checkbox can be checked only when the second checkbox is checked". This is equivalent to saying the first checkbox should be disabled when the second checkbox is unchecked. Disabling the checkbox makes it clear to the user that the option is unavailable.
So in Qt Designer, you should connect the toggled signal of checkbox2 to the setEnabled slot of checkbox1. (It may also be necessary to set the initial enabled state of checkbox1 in Qt Designer as well).
Then, in your code, you should make a second connection, like this:
self.checkbox2.toggled.connect(
lambda checked: not checked and self.checkbox1.setChecked(False))
This will clear the checked state of checkbox1 whenever checkbox2 is unchecked.
If you wanted to do the whole thing in code, it would look like this:
self.checkbox1.setEnabled(False)
self.checkbox2.toggled.connect(self.checkbox1.setEnabled)
self.checkbox2.toggled.connect(
lambda checked: not checked and self.checkbox1.setChecked(False))
Just use signals. You are correct when saying that you cannot directly do that via the designer since you have to invert the checked property. The easiest and most readable way that comes to my mind is using a common slot plus an internal member variable that holds the checked state for both:
Add self._toggle = INITIAL_VALUE to your class - the INITIAL_VALUE holds a boolean value, which you use to check/uncheck your checkboxes
self._toggle = True
self.check1 = QCheckBox('Check 1', self)
self.check1.setChecked(self._toggle)
self.check2 = QCheckBox('Check 2', self)
self.check2.setChecked(not self._toggle)
Add a slot:
#pyqtSlot()
def toggle(self):
self._toggle = not self._toggle
self.check1.setChecked(self._toggle)
self.check2.setChecked(not self._toggle)
Connect the clicked signal of both checkboxes to this slot.
Warning! Do not use the stateChanged signal here or you will start an infinite recursion. :3
self.check1.clicked.connect(self.toggle)
self.check2.clicked.connect(self.toggle)
What I'm doing here is basically taking over the change of the state of both checkboxes and do it manually using the value of self._toggle for the first checkbox and the inverted value of self._toggle for the second checkbox.
If you want less inverting inside the slot the following also works though it is less readable omho:
#pyqtSlot()
def toggle(self):
self.check2.setChecked(self._toggle) # Old value of our check1 becomes the value of check2
self._toggle = not self._toggle # Invert
self.check1.setChecked(self._toggle) # New value is assigned to check1
Note: You can also use isChecked() inside the slot and do all of the above without the extra variable however I find this more readable and with much less function calls (every isChecked() and setChecked() is a function call)
I know I am late to this party but there is a way to accomplish this easier and I think how the original person wanted. Here you go. If you have a checkbox_1 and you check/uncheck it, it connects to the following function.
def Change_the_Checkbox_Function(self):
if self.checkbox_1.isChecked():
if self.checkbox_2.isChecked():
pass
else:
self.checkbox_2.setChecked(True)
else:
self.checkbox_2.setChecked(False)
If you want checkbox_1 to check or uncheck many other checkboxes (like a select all), then instead of checkbox_1 directly calling the above function, you have another function that calls other functions to check/uncheck the boxes, as follows:
def Select_ALL_checkboxes(self):
self.Change_the_Checkbox_1_Function()
self.Change_the_Checkbox_2_Function()
self.Change_the_Checkbox_3_Function()
....etc
To me, this follows the most logical way without getting too technical. It works well and is fast. May not be the most efficient or prettiest, but I found this to be the best way to check/uncheck many checkboxes at once.

Input for key mapping

To make my application more flexible to user I want to add possibility user to chose Hot keys for some actions in app.
To do this I'll gooing to make some page on settings window.
where Action name and input(QLineEdit) where keys will be desplayd like
Quit |Alt+Q|
What was the best way to capture such Hot Keys?
Well, to start with, you can setShortcut for your QAction, which will do exactly what you want (trigger QAction, when user hit sequence), example:
myAction->setShortcut(QKeySequence(Qt::Key_Backspace));
for more details, look up documentation of QKeySequence class
EDIT: to grab the sequence itself, look here - https://stackoverflow.com/a/6665017/1741118 . This answer should work. You can derive from widgets, where you would enter sequence, override QKeyPressEvent there or just set QEventFilter on every widget, that you want to capture events for key sequence

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")

Implementing Undo/Redo within a TextArea

Im wondering how to implement undo redo functionality with a TextArea. I already have an undoredo framework functionality working, now I have two questions.
When do I start/stop a new undo/redo command, eg when a user hits undo, how far back do I go.
How do I implement this(1.) in a normal TextArea
My thinking:
I thinking that I should create a new undo command, when anything but a alphanumber+space is hit. To do this I would use the keyDown event and test if the key is alpha num if it is not I will reset the command.
Sound good?
Listening for keydown events would miss any text editing that user does with the mouse (cut/copy/paste).
I think a better approach would be to listen for 'change' event on the control (which fires whenever the content changes through user input), and just push the full content of the control (its 'text' or 'htmlText' attribute) with every change event into a undo-buffer (an Array of Strings). I assume that the memory usage is not an issue (it probably isn't, depending on the expected size of the controls content and number of undo levels).
This way, you implement undo/redo just by copying the corresponding control state (moving up and down through array, basically) in the undo buffer back into the control.
The 'proper' approach would be to track the actual edits, and would be condsiderably more complicated.
1.When do I start/stop a new undo/redo command, eg when a user hits undo, how far back do I go.
Do you think your users will need to undo multiple steps? If so, then you may want to have a history (e.g. Paint .NET) and allow infinite undo-s. Otherwise, just remember the most recently performed action.
1.) You should listen for the Event.CHANGE event on the TextField and create a history step each time the event is fired. A history step consists in your case of two values: old and new.
Old is the value of the TextField before change, new is its value after the change.
2.) Your history is a sequence of actions or you can use the Memento Pattern. I think actions are much easier to use. A history action has two methods, undo() and redo(). So in undo() you have to say textField.text = oldContent and in the redo() method you say textField.text = newContent. Your history will also need a pointer to the current action.
3.) To make it a little bit better. You should not listen only for Event.CHANGE but instead listen for the first CHANGE and then the next FOCUS_OUT for that TextField. In that case, a history step is only created once I stop editing the TextField. But it depends on your TextField and how you want to distribute history steps. A multiline TextField should not create a history step only on FOCUS_OUT :)

Resources