How do I replicate the gtk_button_click function in GTK4 - button

All,
As I continue to learn how to migrate code I built for GTK3 to GTK4, I continue to encounter instances where functions in GTK3 no longer exist in GTK4. As an example, I had built a small test program that uses a standard button with an image to launch the color chooser instead of using directly presenting a GTK color button. This was done for aesthetics. The method I used was having both a GTK color button that was not visible along with a standard button with an image. Within the program I connected the "button click" signal to function "on_buttoncolor_clicked" to the standard button. Following is the simple code within that function that then emits a "button click" signal for the color button.
void on_buttoncolor_clicked (GtkButton *b)
{
gtk_button_clicked(GTK_BUTTON(button));
}
When I ported this over and attempted to compile this program with the GTK4 libraries, the compilation erred out indicating that this function was not found.
To get around this, I had attempted to attach an image to the GTK color button, but that produced spurious errors when clicking on the button. So, I would like to be able to replicate the "gtk_button_clicked" function. Any advice on this would be appreciated. FYI, I am attaching a small image of how the GTK3 version of the user interface looks like.
Regards,
Craig

All,
I did attempt to replicate sending a "button click" signal to the color button using the "g_signal_emit" function, but that signal was unknown to the color button.
After digging into the source code for the color button widget, I determined that a "button click" signal does get attached to a button element that is a part of the "GtkColorButton" structure. So, I directed the "g_signal_emit" function at the "button element" within the structure by revising my code.
First, I cloned the structure for the "GtkColorButton" widget which gave me access to the structure.
struct _GtkColorButton {
GtkWidget parent_instance;
GtkWidget *button;
GtkWidget *swatch;
GtkWidget *cs_dialog;
char *title;
GdkRGBA rgba;
guint use_alpha : 1;
guint show_editor : 1;
guint modal : 1;
};
Then, I revised the signal connection to use "g_signal_connect_swapped" to reference the color button to the signal.
g_signal_connect_swapped (button "clicked",
G_CALLBACK (on_button_clicked), buttoncolor);
Next, I revised the signal emission function to be directed at the button element within the "GtkColorButton" widget.
void on_button_clicked (GtkColorButton *b)
{
g_signal_emit (b->button,
g_signal_lookup ("clicked", G_OBJECT_CLASS_TYPE
(GTK_WIDGET_GET_CLASS(GTK_BUTTON(button)))), 0);
}
This resulted in the expected color selection dialog appearing when the standard label button is clicked as noted in the newly attached image.
With this resolution, I believe that this issue can be closed.
Regards,
Craig

Related

Next and previous control button in winAPI to go to next page (c++)

I am creating an winAPI application in c++ I have a photo in preview pane and I want to create two buttons NEXT and PREVIOUS on clicking them I will go to the next page .
Could you please give me the idea how to do that in c++ ??
Do I need to use QT libraray or it can be done using the in built function of WinAPI like -
HWND hwndButton1 = CreateWindow(L"BUTTON",L"NEXT",WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,550,800,100,30,m_hwndPreview,(HMENU)buttonid1,(HINSTANCE)GetWindowLong(m_hwndPreview, -6),NULL);
HWND hwndButton2 = CreateWindow(L"BUTTON",L"PREVIOUS",WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,650,800,100,30,m_hwndPreview,(HMENU)buttonid2,(HINSTANCE)GetWindowLong(m_hwndPreview, -6),NULL);
and then using WM_COMMAND for both the button clicks.
Am I going right?
I just want my API application work like a .pdf extension file...as in PDF files we have up and down arrow and on clicking upon them we can go to the next page..In winAPIc++ I couldn't find any such arrow function.. please tell me if there is any such arrow up/down function present to go to next page (because I am very less interested in creating NEXT and PREVIOUS button using createwindow function.. It looks odd).
You have not mentioned what tools you are using, so we don't know if you have a resouce editor. You should research that in a forum appropriate for the tools. If you think writing one line of code to create a button is "very complicated" then you need a better tool.
If you do not want the buttons to appear on top of the picture then you need another place to put them. One common possibility is a toolbar. It is a strip for buttons along the top or bottom of the main window:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb760435(v=vs.85).aspx
With a resource editor you can draw an arrow on the button. Without a resource editor you can set the button text to a unicode arrow:
SetWindowText(hwndButton1, L"\x25bc"); // down arrow, use 25b2 for up arrow
Most buttons (and other controls) are created using a resource editor, placing the controls on a dialog template or a toolbar resource. If you do that Windows will create the buttons when you create the dialog or toolbar. This method is much preferred because Windows will adjust the size of the buttons as required for the screen settings in use.
If you can't do that you must use CreateWindow as you are doing.
Finally it is done.. I have created the buttons neither using Qt or nor using any createWindowEx..The best and easy approach to follow is resource editor ...just put some button on dialog and use IDD_MAINDIALOG (in my case)
m_hwndPreview = CreateDialogParam( g_hInst,MAKEINTRESOURCE(IDD_MAINDIALOG), m_hwndParent,(DLGPROC)DialogProc, (LPARAM)this);
and then
BOOL CALLBACK AMEPreviewHandler::DialogProc(HWND m_hwndPreview, UINT Umsg, WPARAM wParam, LPARAM lParam)
{
switch(Umsg) // handle these messages
{ .........
}
....
}
and thats done. Very easy task.

Qt WebView and clicking on a google map

Has anyone tried to click on a google map displayed in Qt QWebView via one of QWebView's mouse event methods? I want to do this in this way becouse I need to run some actions both in Qt and in google map (when I click on map I want to add e. g. a bus stop - it'll load inside the programme and the marker will apear on the map). I've got a method for adding a placemark and I know I can call it, but I've got problem with passing correct position.
void MyWebView::mousePressEvent(QMouseEvent * e) {
QString command = "placeMarker(new google.maps.LatLng(";
command.append(new QString(e->x()));
command.append(", ");
command.append(QString(e->y()));
command.append("))");
this->page()->mainFrame()->evaluateJavaScript(command);
}

Program crashes with WebKit Previewer example with on_textEdit_textChanged()

I recreated the example of a webkit that displays the content of a textEdit containing HTML: http://qt-project.org/doc/qt-4.8/webkit-previewer.html
I changed it so rather than the webkit HTML being changed upon clicking the button, it's changed upon the text in the textEdit being changed:
// changed when button is click. Works fine.
void Previewer::on_previewButton_clicked()
{
// Update the contents in web viewer
QString text = htmlTextEdit->toPlainText();
webView->setHtml(text);
}
// change when text is changed. Crashes.
void Previewer::on_htmlTextEdit_textChanged()
{
// Update the contents in web viewer
QString text = "<html><body><h1>No crash!</h1></body></html>";
webView->setHtml(text);
}
This causes the program to crash as soon as it starts. I altered the program to run the function only a bit later (I thought maybe something needed to be initialized) but it still crashed once it reached the textChanged function. Why is it crashing? How can I fix this?
Your program is entering an infinite loop because, in the example, there's a connection between the webView's loadFinished(bool) signal and the text/html editor's updateTextEdit() slot.
Basically, editing the HTML causes the page to load again, which causes an update to the editor, which causes the page to load again, so on and so forth.
A quick way I solved this was to add a static bool flag to the updateTextEdit SLOT/function that only allows it to run once.
void MainWindow::updateTextEdit()
{
static bool once = false;
if (once) {
return;
}
once = true;
QWebFrame *mainFrame = centralWidget->webView->page()->mainFrame();
QString frameText = mainFrame->toHtml();
centralWidget->plainTextEdit->setPlainText(frameText);
}
Doing this worked for me, but your version might work differently than mine. I followed the example closely, but added an htmlchanged() slot to the previewer class, and made the connection like so:
connect(centralWidget->plainTextEdit, SIGNAL(textChanged()), centralWidget, SLOT(html_changed()));
Also, I'm no expert, but I'm pretty sure this is not the best way to get around this, and I assume that updateTextEdit() needs to run more than once. It'll work for the time being, though.

Qt : Tooltip on wrong input

I have a QLineEdit, on which I have set a QRegExpValidator, that allows the user to input only one whitespace between words.
Now I want that whenever the user tries to enter more than one whitespaces, the tooltip of the QLineEdit should show up, but I'm not getting any method to implement it.
Thanx :)
It seems there is no direct method to perform what you want. One way to do above is to handle QLineEdit's textChanged() signal. Then you can check that string against your regular expression using QRegExp::exactMatch() function and if it don't match then show tooltip.
Connect the signal..
...
connect(ui->lineEdit,SIGNAL(textChanged(QString)),this,SLOT(onTextChanged(QString)));
...
Here your slot goes..
void MainWindow::onTextChanged(QString text)
{
QRegExp regExp;
regExp.setPattern("[^0-9]*"); // For example I have taken simpler regex..
if(regExp.exactMatch(text))
{
m_correctText = text; // Correct text so far..
QToolTip::hideText();
}
else
{
QPoint point = QPoint(geometry().left() + ui->lineEdit->geometry().left(),
geometry().top() + ui->lineEdit->geometry().bottom());
ui->lineEdit->setText(m_correctText); // Reset previous text..
QToolTip::showText(point,"Cannot enter number..");
}
}
I don't remember explicit API for showing a tooltip. I'm afraid you'll have to go with popping up a custom tool window (i.e. a parent-less QWidget) to achieve the desired result.
If you want to style your own popup window like a standard tooltip, QStyle should have something for that. If in doubt, read into the Qt source code where it renders the tooltip. That'll tell you which style elements to use.

Connecting to a signal hidden by QMessageBox

I want to show the user a warning QMessageBox with a link inside. This is relatively easy, I just need to make sure I set the RichText text format on the message box and the QMessageBox setup does the rest. However, I would also like to close the message box (as in some-sort-of-call-to done()) if the user clicks on the link - the semantic being that the user acknowledged the message and made a decision.
The problem: QMessageBox hides the linkActivated signal coming from its inner QLabel (which is used to store the text).
I thought I could extend the QMessageBox class and do this very ugly hack in the constructor:
QLabel *lbl = findChild<QLabel*>(QString("qt_msgbox_label"));
assert(lbl != NULL);
connect(lbl, SIGNAL(linkActivated(const QString&)), this, SLOT(handle_link_activation(const QString&)));
but although the label found with findChild is not null, and the "qt_msgbox_label" is definitely correct (c/p'ed from the source), and there is no "no such signal/slot" message, my slot never gets called when I click the link.
I'd like to avoid writing my own QDialog which would mimic the QMessageBox behavior. Does anyone have any idea on how I can catch that signal?
Try defining your own link "protocol" i.e. msgboxurl://yoururl.is.here and install url handler for it
QDesktopServices::setUrlHandler("msgboxurl", urlHandlerObj, "slotName");
urlHandlerObj may be object that created message box. In slot you can just hide your message box and take url part after // and open it with QDesktopServices::openUrl but remember that you have to prepend then http/https prefix (on some platforms url without "scheme" is not handled properly). Slot handling url must have same parameters as QDesktopServices::openUrl static method

Resources