Creating a loop inside GtkDialog - c++

I have a GtkDialog set up like this:
GtkWidget *dialog;
dialog = gtk_message_dialog_new(GTK_WINDOW(window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"Information");
gtk_window_set_title(GTK_WINDOW(dialog), "Information");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
However, when the dialog is open I want to have an infinite loop, which would be exited when the OK button is pressed. Is something like that possible to achieve?

Just run gtk_dialog_run in a do/while loop and test its return value in the while. That return value tells you which button has been pressed (most probably GTK_RESPONSE_ACCEPT in your case).
Please read the documentation for gtk_dialog_run, that's explained there.

Related

Qt didn't continue run instructions after specific code

I'm trying to make QInputDialog put values into an array using a for loop but after reaching the max value it didn't continue to run code after the loop until I exit my program
void MainWindow::on_pushButton_clicked()
{
nb = ui->lineEdit->text().toInt();
for(i=1;i<=nb;i++)
{
QInputDialog *ValDialog = new QInputDialog();
b[i] =ValDialog->getInt(this,"Best Fit","Block No : " + i,1,0,100000,1);
}
std::cout << "aAA\n" + b[0];
//UNRUNABBLE instructions
}
Code after the for loop didn't run at all until I stopped the run.
According to Qt's documentation: https://doc.qt.io/qt-5/qinputdialog.html#getInt QInputDialog::getInt(...) will create a modal window. A modal window is basically blocking the main window (your MainWindow class) until a user closes it.
This is intentional, so that you do not continue in the code, until a result is ready. If you wish to execute something after the dialog is shown, but not yet closed, you should probably use a different approach (maybe derive your own QDialog).

Qt wizard back button Ui issue

I'm new with Qt and I'm making a little application. I've do it with QWizard and QWizardPages.
I Have added 2 CustomButtons to the wizard so it has 5 buttons down: ButA, ButB, Back, Next/Finish, and Cancel.
ButA and ButB don't have to appear in all WizardPages. Eg:
WP0: just ButB
WP1: ButA and ButB
To do that, I have:
void WP0::initializePage()
{
wizard()->button(QWizard::CustomButton1)->setVisible(false);
}
With that when the app starts, you can't see butA. BUT if you go to the next page (where you see ButA and ButB) and then you click on BackButton, then you see ButA in WP0.
I supose that then you click on BackButton there is no call to WP0::initializePage() so my question is: how or where should I call that wizard()->button(QWizard::CustomButton1)->setVisible(false);
to never see ButA on WP0 ? Or what should I do?
I don't know if I understand your question completely. your description is kind of complicated. I think you should try button's events. It means you should call this function in press event or something like that and it's better that you define a boolean variable for true or false and call it by reference. I think this should solve your problem.

CheckBox value in different file

I need to access the checkbox value in a different program. Check box is initiated in ToolDlg.cpp
DDX_Control(pDX, IDC_CalculateTBA, m_CalculateTBA);
in the oninitdialog initiated like this:
m_CalculateTBA.SetCheck(0);
CalculateAnalyticTBA = false;
void CToolDlg::OnBnClickedCheck3()
{
CalculateAnalyticTBA = m_CalculateTBA.GetCheck();
}
I need checkbox value in SetCal.cpp program. Here is the code i am trying in this program:
CToolDlg dialog;
if( dialog.CalculateAnalyticTBA )
{
Do some thing
}
But the dialog.CalculateAnalyticTBA is always tru even though i don't check the check box.
Plz let me know if you need any other info. Thanx for help.
It looks like you're creating a dialog, and never showing it. So CalculateAnalyticTBA has whatever value you gave it in the constructor of your CToolDlg class (or, if you didn't, whatever value the compiler gave it).
In order for this value to be set you must at least create the dialog so that the Data Exchange code (which invokes the DDX_Control and handles the binding of the checkbox and the variable) has a chance to run.
The correct way is to create and display the CToolDlg dialog and wait for the user to select his choices then only process the choices when the user finally click the "OK" button.
CToolDlg dialog;
// create and display the dialog
if (dialog.DoModal()==IDOK)
{ // user clicked the ok button, now do the work
....
}

Gtk hiding window on it's callback

I have a function that I want to hide on pressing a button. I've read that I can define multiple callbacks on a signal and they will be called in the same order as defined. So I wanted to execute two functions on button press and I wanted one of them to hide window that contains this button. I tried to do it like this:
g_signal_connect(btn_confirm, "clicked", G_CALLBACK(function_that_does_stuff), NULL);
g_signal_connect(btn_confirm, "clicked", G_CALLBACK(kill_window), add_conn_win);
...
void kill_window ( GtkWidget* wdgt, GtkWidget* win )
{
gtk_widget_hide_all(win);
}
But this isn't working. Window's still there. Can someone tell me how to do that?
First things first, see what the documentation says about gtk_widget_hide_all():
gtk_widget_hide_all has been deprecated since version 2.24 and should not be used in newly-written code
Instead you should use gtk_widget_hide (). The specification says that it
Reverses the effects of gtk_widget_show(), causing the widget to be hidden (invisible to the user).
As a comment said, make sure your callbacks are being triggered. Then try
gtk_widget_hide (win);
I think that should do the work, let me know if it helps!

deadlock problem with threads in GTK

In my GUI, I have a list store treeview in my main window. When the user double clicks a row, a dialog pops up. The problem is that the data I populate in the dialog box takes a while to process, so what I've done is started a thread (using boost threads) to do the dialog box calculations.
In main:
.......
g_signal_connect (G_OBJECT (m_treeview), "row_activated", G_CALLBACK (m_row_activated),
(gpointer) main_window);
.......
In m_row_activated:
.........
// combo_box and dialog are GtkWidget* global variables
create_dialog(dialog, combo_box); // function creates the combobox
set_combo_box_with_loading_message;
gtk_widget_show_all (dialog);
thread m_thread (bind (&do_dialog_calculations, data1, data2, combobox));
.........
In do_dialog_calculations:
.........
// do_calculations takes about 15 seconds to complete
do_calculations(MyData data1, MyData data2, combobox);
gdk_threads_enter();
gtk_combo_box_append_text(...);
gdk_threads_leave()
Everything works fine (i.e. when the user double clicks a row, a dialog pops up immediately with a loading message and it is populated eventually when the thread returns), but my problem is when the user closes the dialog before do_calculations in do_dialog_calculations completes. If the dialog is destroyed, my combobox within it will be destroyed and my call to gtk_combo_box_append_text will seg fault.
I tried to test the combo box before updating it:
In do_dialog_calculations:
.........
do_calculations(MyData data1, MyData data2, combobox);
gdk_threads_enter();
if (GTK_IS_COMBO_BOX (combobox))
gtk_combo_box_append_text(...);
gdk_threads_leave()
but this results in a deadlock at the call to GTK_IS_COMBO_BOX. I think this is beause GTK_IS_COMBO_BOX probably calls gdk_threads_enter(). I've also tried testing for NULL
if (combobox == NULL)
but that doesn't seem to work either. Any suggestions on how to get around this problem?
UPDATE: The deadlock at GTK_IS_COMBO_BOX only occurs if I close the dialog immediately after it opens (i.e. before do_calculations() completes. If I just let the dialog sit, it will eventually update. Also, if I switch the combobox check before writing calling gdk_threads_enter():
if (GTK_IS_COMBO_BOX (combobox)
{
gdk_threads_enter();
gtk_combo_box_append_text(...);
gdk_threads_leave();
}
No deadlock occurs when I destroy the dialog before this code executes. However, I'm afraid of the rare possibility that the user will close the dialog after the GTK_IS_COMBO_BOX check completes.
PS - I use threads to do my dialog box calculations because the dialog boxes are non modal, and I want the user to be able to do other things with the main UI while the dialog boxes populate.
I think this is beause GTK_IS_COMBO_BOX probably calls gdk_threads_enter()
I don't think this is the case. These macros are generally pretty simple and I wouldn't expect it to take a lock. In fact, as far as I can tell the whole idea of gdk_threads_enter is that the library itself shouldn't call this, only code that knows it's running in another thread should.
Here's my idea: Did you forget to call g_thread_init and gdk_threads_init?
Also, one thing to keep in mind... By default, gdk_threads_enter is not using a recursive mutex. Though some people have religious objections to recursive mutexes, it's possible to have gdk_threads_enter use one:
static GStaticRecMutex my_gdk_lock;
static void my_gdk_lock_enter() {g_static_rec_mutex_lock(&my_gdk_lock);}
static void my_gdk_lock_leave() {g_static_rec_mutex_unlock(&my_gdk_lock);}
// ...
g_thread_init(NULL);
g_static_rec_mutex_init(&my_gdk_lock);
gdk_threads_set_lock_functions(G_CALLBACK(my_gdk_lock_enter),
G_CALLBACK(my_gdk_lock_leave));
gdk_threads_init();
// ...
Update: From your comment it sounds like you have a race condition between destroying the dialog and populating the combo box. One potential solution is that you bump up the reference count of the combo box (i.e. gtk_widget_ref) so that it doesn't get freed while your asynchronous worker is doing something. Then release it with gtk_widget_unref when the other thread no longer needs the pointer.