Blackberry 10 SystemPrompt->inputField does not change value on user input - qt

I need to display system input dialog: title, some text, input field, OK & Cancel buttons.
I'm new to BB development, so I carefully read docs and samples: http://developer.blackberry.com/native/documentation/cascades/ui/dialogs_toasts/prompts.html
and write the same code (let's say doc author cheated a bit in the most important part - not covering obtaining of user input with non-compiling source code - "qDebug() << "Prompt Accepted:" << text;").
void MainPage::showPrompt() {
SystemPrompt *dialog = new SystemPrompt();
dialog->inputField()->setDefaultText("TEST");
QObject::connect(dialog, SIGNAL(finished(bb::system::SystemUiResult::Type)),
this, SLOT(promptHandler(bb::system::SystemUiResult::Type)));
dialog->show();
}
void MainPage::promptHandler(bb::system::SystemUiResult::Type value) {
if (value == SystemUiResult::ConfirmButtonSelection) {
SystemPrompt *dialog = (SystemPrompt *)QObject::sender();
qDebug("text is: '%s'", qPrintable(dialog->inputField()->defaultText()));
}
}
Regardless of user input on device/simulator, inputField()->defaultText() value is always "TEST" as it was initialized.
How do I get the user input here? dialog->exec() does not change anything.
PS. Expert level question: And how do I allow empty input in SystemPrompt dialog (by default "OK" button becomes disabled on empty input).

Shame upon me. I did not read documentation carefully.
->inputFieldTextEntry() does contain the user input.
PS. First time I see such sophisticated logic of handling such simple thing as user input in text edit...

Related

Xamarin Forms Prism DialogService takes some seconds to show up

My Dialog is a simple Frame with an Image, a label to display a question and two more labels (Yes / No) with TapCommand.
I've set up the container with the DialogPage.xaml and DialogPageViewModel and injected in the ViewModel I want to open the dialog.
Here is the code I'm using to call the Dialog:
public void ShowDialog()
{
_dialogService.ShowDialog("DiscardPopup", CloseDialogCallback);
}
void CloseDialogCallback(IDialogResult dialogResult)
{
var goBack = dialogResult.Parameters.GetValue<bool>("GoBack");
if (goBack)
NavigationService.GoBackAsync();
}
If the user taps over the "Yes label", I execute this command:
YesCommand = new DelegateCommand(() => YesTapped());
private void YesTapped()
{
IDialogParameters pa = new DialogParameters();
pa.Add("GoBack", true);
RequestClose(pa);
}
If the user taps over the "No label", I simply call:
NoCommand = new DelegateCommand(() => RequestClose(null));
The "problem" is when the ShowDialog is fired, the DiscardPopup is taking up to 3 seconds to show up.
Is there a way to make it faster?
The same happens with the TapCommands, 2 - 3 seconds when the RequestClose is invoked.
Without actual code telling you exactly what the issue is, is going to be best guess. Based on your feedback to my comments above I would suggest the following:
Try displaying the dialog on a test page that doesn't have a complex layout. My guess is that you won't see such a long load time. If that's the case this would point to your layout being overly complex and that the lag time is due to the device struggling to re-render the View
Try using Prism.Plugin.Popups. You'll need to initialize Rg.Plugins.Popup and register the DialogService. You can see docs on that at http://popups.prismplugins.com

ActionEvent get source of button JavaFX

I have about 10 buttons which are going to be sent to the same method. I want the method to identify the source. So the method knows button "done" has evoked this function. Then I can add a switch case of if statement to handle them accordingly. This is what I have tried
//Call:
btnDone.setOnAction(e -> test(e));
public void test(ActionEvent e) {
System.out.println("Action 1: " + e.getTarget());
System.out.println("Action 2: " + e.getSource());
System.out.println("Action 3: " + e.getEventType());
System.out.println("Action 4: " + e.getClass());
}
Output Result:
Action 1: Button#27099741[styleClass=button]'Done'
Action 2: Button#27099741[styleClass=button]'Done'
Action 3: ACTION
Action 4: class javafx.event.ActionEvent
Done is the text on the button. As you can see I could use e.getTarget() and/or e.getSource() then I'll have to substring it, so only the "Done" appears. Is there any other way to get the string in the apostrophe instead of having to substring.
UPDATE: I have tried passing Button and it works but I still want to
know a solution using ActionEvent.
//Call:
btnDone.setOnAction(e -> test(btnDone));
public void test(Button e) {
System.out.println("Action 1: " + e.getText());
}
Output is Action 1: Done
Typically I much prefer using a different method for each button. It's generally a very bad idea to rely on the text in the button (e.g. what will happen to the logic if you want to internationalize your application?).
If you really want to get the text in the button (and again, I have to emphasize that you really don't want to do this), just use a downcast:
String text = ((Button)e.getSource()).getText();
As #James_D pointed out, relying on the button text displayed to the user is a bad idea for various reason (tho probably sufficient for your case!)
A different approach would be, to assign IDs to the buttons and then retrieving them in the callback method. That would look something like that:
// that goes to the place where you create your buttons
buttonDone.setId("done");
...
// that goes inside the callback method
String id = ((Node) event.getSource()).getId()
switch(id) {
case "done":
// your code for "buttonDone"
break;
}

Avoid duplicate Tabs in QTabWidget

I have an application, in which I have added a QTabWidget.
Tabs are closable.
When I add new tab, if the tab is already added, it still add new tab and make duplicate.
I want to avoid this duplication.
If the tab is opened already then It just active that tab and not open again.
You help will be appreciated.
Thanks
To add on top of Prakash's answer, be aware that some times the tab title is not a good identifier of the content of the tab (this of course depends on the situation). For example, you might have a file manager where the current directory is the title of the tab, but there might be different directories with the same name across your filesystem.
I would follow the following strategy for identifying tab contents: Qt allows you to set dynamical properties to widgets (see QObject::setProperty), so each time you create a new tab, for example of a file manager, you might do something like
widget = ...
widget->setProperty("tab_dir_fullpath", the_full_path);
tabWidget->addWidget(widget, directory_name);
where the_full_path would be a unique identifier (in this example, the full absolute path to the current directory), which will not be displayed to the user but which you can later use to see if a given directory is already open.
Then, when opening a new tab, you should check whether the same full path is already open:
for (int k = 0; k < tabWidget->count(); ++k) {
if (tabWidget->widget(k)->property("tab_dir_fullpath").toString() == the_full_path_to_open) {
tabWidget->setCurrentIndex(k);
return;
}
}
... // open new tab, as in the previous snippet.
Use tabText(int index) to get the identifier of the each tab before adding a new tab addTab(QWidget * page, const QString & label) and compare the label texts, if already exist just setCurrentIndex of that index or else add a new tab.
Inspired by Noor Nawaz's comment, my approch is:
void MainWindow::openPanel1()
{
for(int i=0;i<ui->tabWidget->count();i++) {
if(ui->tabWidget->tabText(i) == "Panel1") {
ui->tabWidget->setCurrentIndex(i);
return;
}
}
Panel1 = new panel1Widget();
int index = ui->tabWidget->addTab(Panel1,"Panel1");
ui->tabWidget->setCurrentIndex(index);
}
Also its very good to use setTabData() instead of property which is more proper way of doing.

Catching/Connecting QPushButtons inside a QTableWidget to a function

Im a student developer using Qt to build a GUI to help users plot specific columns of data located in multiple files. The feature I'm setting up allows users to select a file using a button in each row. So the button originally would say browse and then user clicks it to open a dialog to select a file then the button text is replaced with the file name selected. Sorry for the story; my simple attempt to add some clarity.
The problem I'm having is I'm not sure how to set a policy up for the button clicked. I'd imagine that I'd have to extend the functionality of each of the QPushButtons but I don't really know how to do that. So far I am using the following to set the cell widget.
//with row count set dimensions are set becasue column count is static
//begin bulding custom widgets/QTableWidgetItems into cells
for(int x = 0; x < ui->tableWidgetPlotLineList->rowCount(); x++)
{
for(int y = 0; y < ui->tableWidgetPlotLineList->columnCount(); y++)
{
if(y == 1)
{
//install button widget for file selection
QPushButton *fileButton = new QPushButton();
if(setDataStruct.plotLineListData.at(rowCount).lineFileName != "");
{
fileButton->setText(setDataStruct.plotLineListData.at(rowCount).lineFileName);
}
else
{
fileButton->setText("Browse...");
}
ui->tableWidgetPlotLineList->setCellWidget(x, y, fileButton);
}
I was thinking that
connect(ui->tableWidgetPlotLineList->row(x), SIGNAL(fileButton->clicked()), this, SLOT(selectPlotLineFile(x));
might do the trick but I think I'm probably going in the wrong direction here. Honestly I'm not even too sure as to where it would go...
Thanks so much for reading my post. Please let me know if there is anything lacking from this post and I will update it immediately. I'd also like to thank any contributions to this post in advance!
connect(ui->tableWidgetPlotLineList->row(x), SIGNAL(fileButton->clicked()), this, SLOT(selectPlotLineFile(x));
Is not syntactically correct for a signal/slot connection. Something like this would be more appropriate:
connect(fileButton, SIGNAL(clicked()), this, SLOT(selectPlotLineFile(x));
...
If you need access to the specific button that emited the clicked() signal than you could use the sender() function in your slot:
void selectPlotLineFile() {
QPushButton *button = dynamic_cast<QPushButton*>( sender() )
}
Now you may be wondering how you know which row to operate on. There are several different approaches, one of the easier ones being to maintain a QMap<QPushButton*, int> member variable that you can use to lookup which button belongs to which row.

Qt: two actions in menu (with the same text)

I create a menu dynamically. I add several checkable actions into one menu. Sometimes actions may have the same text that user sees. It's up to user (actually user adds commands into menu).
The problem is in this case clicking works wrong. If I click on the first action (from 2 with the same texts) everything is good but if I click on the second one, both actions are selected. I don't understand why. The code where actions have been created is here:
for (int i = 0; i< currentList.size(); i++)
{
QString lanKey = currentList.at(i)->Language->toString();
QAction* lanAction = new QAction(this);
QString name ="action_" + currentList.at(i)->Id->toString();
lanAction->setObjectName(name);
lanAction->setText(lanKey);
lanAction->setCheckable(true);
lanAction->setData(i);
connect(lanAction, SIGNAL(triggered(bool)), this, SLOT(ShowSomething(bool)));
ui->menuMy->addAction(lanAction);
}
Here, lanKey is language that may be the same for different actions. Anyway click on the specific action should lead only to checking of this action. What's wrong?
The slot is here:
void VMainWindow::ShowSomething(bool IsTriggered)
{
QAction* senderAction = (QAction*)sender();
int listIndex = senderAction->data().toInt();
if (IsTriggered)
{
CreateEditor(subtitles, listIndex);
}
else
{
//hide this editor
QString name = "editor" + editorsList->Id->toString();
QDockWidget* editorDock = this->findChild<QDockWidget*>(name);
if (editorDock != 0)
{
this->removeDockWidget(editorDock);
this->setLayout(layout());
}
}
}
Thanks
The source of problem is found: it turned out that the slot finds the checked action wrong - by text, not by id.
I can't find a logical issue in the code you posted so far. Here are a couple of options which I would try in order to resolve this problem:
Limit the users possibilities when adding items to a menu so that he can't add two items with the same name.
Add qDebug() output to ShowSomething to see if there is a problem with signals&slots. For example, if the slot gets called once for the first item but twice for the second item there is a problem there.
Debug into CreateEditor step-by-step.
As the problem seems to appear only for actions with a similar name, you should make sure that you never make a lookup of an action (or something related) by its text() but rather by its data() or objectName() (assuming that currentList.at(i)->Id will always be unique)

Resources