QCompleter runtime crash - c++

I want to do a Code Completer so i subclassed QCompleter:
http://hastebin.com/qeyumevisa.cpp
But, when I try to run this code, i get a runtime error:
And debug output shows:
ASSERT: "d->widget != 0" in file util\qcompleter.cpp, line 1446
Crash seems to come from the line 53:
QCompleter::complete(rect);
How i can fix this bug? Thanks

The assert is fired from QCompleter::complete(rect);
It means that QCompleter::widget() is zero. The private member d->widget is always initialized by zero. Its type is QPointer<QWidget>. The widget is set only by QCompleter::setWidget(QWidget *widget). According to the documentation QCompleter::setWidget(QWidget *widget):
Sets the widget for which completion are provided for to widget. This
function is automatically called when a QCompleter is set on a
QLineEdit using QLineEdit::setCompleter() or on a QComboBox using
QComboBox::setCompleter(). The widget needs to be set explicitly when
providing completions for custom widgets.
Thus, the widget must be set either by QCompleter::setWidget() or by QLineEdit::setCompleter(). If non of those options is used the function QCompleter::complete(rect) crashes if the completion mode is not QCompleter::InlineCompletion.
So, there are two possibilities for the crash:
d->widget is not initialized befor calling QCompleter::complete(rect);
since d->widget is a QPointer it can be automatically set to 0 when the referenced QWidget object is destroyed.

Related

gtkmm 4: How to get X window ID from inside widget?

In gtkmm 4, how can one get the X Window ID of type XID as defined in X11/X.h, from inside a class, that inherits from Gtk::Widget?
Not all of them have one.
Those widgets that do will implement the GtkNative interface, which provides the gtk_native_get_surface function, allowing you to obtain a GdkSurface. In gtkmm, this will correspond to casting to to Gtk::Native and calling get_surface.
To obtain a Window handle from that, you can use the GDK_SURFACE_XID macro. For that, I don’t think a C++ wrapper exists; you will have to call Gdk::Surface::gobj to obtain a GdkSurface * and use the C API.
I wanted to add two things to the accepted answer
It is of course important to check if get_surface() returned a valid nonzero object indeed. Otherwise get the ID after the Widget's signal_realize() is emitted, which is done after the widget is assigned to a surface. This can be achieved by overriding the default handler on_realize()
Instead of casting and calling ((Gtk::Native)this)->get_surface() it is also possible to call like get_native()->get_surface().
In conclusion do
void myWidget::on_realize() {
// Call default handler
Gtk::Widget::on_realize();
XID x_window = GDK_SURFACE_XID(get_native()->get_surface()->gobj());
}
to get the X window ID as early as possible.

How to get the text value of a control through its parent window

I have the following wxDialog parent window:
I have created that parent window by the following code:
settingsFrm settingsWindow(this, "Settings");
settingsWindow.ShowModal();
I have tried to use FindWindowByName to get the value of the first text ctrl as follow:
wxLogMessage(dynamic_cast<wxTextCtrl*>(settingsWindow->FindWindowByName("keywords_txt"))->GetValue());
But unfortunately, it doesn't work and gives me a runtime error.
I don't know if that method suitable to do what I want.
How to get the value/other of a control through its parent window?
From your comments, it seems like you expect the function to find the control from the name of the variable in your code which is not how it works and would be pretty much impossible.
FindWindowByName() uses the window name (and, as a fallback, label, but this is irrelevant here because text controls don't have labels anyhow), so for it to work you need to set the window name when creating the control, using the corresponding parameter of its ctor. This is very rarely useful in C++ code, however, as it's simpler to just store a pointer to the control in some variable and use this instead.
FindWindowByName() can often be useful when creating controls from XRC, however. If you do this, then you should specify names for your controls in XRC and pass the same name to this function.
How did you create the TextCtrl instance? You should have something like wxTextCtrl m_textCtrl1 = new wxTextCtrl(/// arguments); Accessing the value should be very easy, as wxString text = m_textCtrl1->GetValue(); You definitely don't need FindWindowByName just for what you are trying to do here.

Qt connect doesn't recognize with lambda expression

I'm designed a QTableWidget with QPushButton, I would like to connect these buttons with a slot to hide some rows.
I'm using a lambda expression to pass a number of a row. But the compiler doesn't recognized this expression :
connect(this->ui->tableWidget->cellWidget(i,0),&QPushButton::clicked,[this,i]{hideRows(i);});
I have this error:
error: no matching function for call to 'SoftwareUdpater::MainWidget::connect(QWidget*, void (QAbstractButton::*)(bool), SoftwareUdpater::MainWidget::displayTable()::<lambda(int)>)'
The function hideRows(int) is declared as a function. And, as a slot, it doesn't work,
CONFIG += c++11 is added in pro file,
My class MainWidget inherits from QWidget,
Q_OBJECT is added in the header.
So I don't udnerstand why connect() is not recognized by Qt 5.9.1 MinGw 32bit.
Edit: [this,i]() instead of [this](const int i) for the lambda expression
Your connection is wrong. You can't connect a function that doesn't take parameters (clicked()) with a function that takes parameters (your lambda). To verify that this is the case, just do this:
connect(this->ui->tableWidget->cellWidget(i,0),&QPushButton::clicked,[this](){});
And see that it will compile. You have to make your design in such a way that signals and slots are compatible.
Also avoid using lambdas in signals and slots. Read the caveats here.
I was reading your comments on the accepted answer and noticed the root of the problem: This error is being thrown because the effective type of the object — as supplied to QObject::connect; i.e QWidget in your case — does not define the referenced signal QPushButton::clicked.
What likely happened is that the QPushButton pointer was cast into a QWidget and then that pointer was given to connect instead of the original which defines the signal.
Cast the pointer back to a QPushButton * and the error should go away.

Using QtScript outside my main form

I am using Qt5, and trying to learn on how to make an application scriptable.
For this I created a main window that contains some text edits, labels, etc. I then added an option called "script console" to that forms' menu in order for me to open a second form containing just a text edit and a button called "Evaluate".
What I was aiming at was being able to use that second form and through Qt script engine be able to set or get values from my main form, and generally be able to script various functions.
What I tried doing was set up the engine like this
scriptingconsole::scriptingconsole(QWidget *parent) :
QDialog(parent),
ui(new Ui::scriptingconsole)
{
ui->setupUi(this);
QScriptValue appContext = myScriptEngine.newQObject(parent);
myScriptEngine.globalObject().setProperty("app", appContext);
}
I don't get what I was expecting though.
If I try to evaluate the expression "app" I get null as an output.
This works fine if I use myScriptEngine.newQObject(parent) with an object inside the current class (if instead of parent I enter this), but I want to be able to access object in other classes too (hopefully all public slots that are used by my app in general).
Does anyone know what I am doing wrong here and how can I use my scripting console
class to access public slots from my main window?
What's wrong?
I guess it's because you didn't explicitly pass the pointer, which points to your main form, to the constructor of your scriptingconsole. That's why you got NULL as a result. (NULL is default, as you can see QWidget *parent = 0 in every QWidget constructor)
This happens if your object is not dynamically instantiated.
Solution
Dynamically allocate scriptingconsole in your main form:
scriptingconsole* myScriptConsole;
//...
myScriptConsole = new scriptingconsole(this);
// ^^^^
// pass the pointer which points to parent widget
The Qt documentation of QScriptEngine::newQObject says:
Creates a QtScript object that wraps the given QObject object, using the given ownership. The given options control various aspects of the interaction with the resulting script object.
http://qt-project.org/doc/qt-4.8/qscriptengine.html#newQObject
i.e. it wraps a QObject.. You are probably passing NULL to newQObject, for whatever reason. Try setting a breakpoint and evaluating the value of 'parent'.

Qt access violation 0xC0000005 after slot

I have an issue that i just figured out what to do, so maybe you can help me.
I am working on a application that connects to a database, displays the values and allowes the user to update/insert values.
I have a QTabView and inside one of the tabs there are four QTableWidget's.
Inside this Tables is sometimes (depends on the value of the database) a QComboBox to select some predefined Values.
I catch the QComboBox::selectedIndexChanged(int) with a QSignalMapper and have a slot connected to the QSignalMapper to give some information what table it was and what setting was changed. From time to time i create the SettingsMapper new (and delete it before that) to reset the 'outdated' mapper-combobox connections.
So the problem is, that when i change the index inside a combobox, the slot gets called and i can debug into the moc_*.cpp where the switch of the signal/slot connections is, but after that i get the access violation on address 0xC0000005 inside the dlls.
Here the call stack:
QtCored4.dll!6721af70()
[Frames below may be incorrect and/or missing, no symbols loaded for QtCored4.dll]
QtCored4.dll!67219fe5()
QtCored4.dll!67218f14()
QtCored4.dll!67218e48()
QtCored4.dll!6721903d()
QtCored4.dll!6720f874()
QtCored4.dll!6702429b()
QtCored4.dll!670316f3()
QtGuid4.dll!655b93f1()
QtGuid4.dll!650f99d0()
user32.dll!7e41885a()
user32.dll!7e41882a()
user32.dll!7e42b326()
msctf.dll!7472467f()
user32.dll!7e43e1ad()
user32.dll!7e43e18a()
QtCored4.dll!67234b9c()
user32.dll!7e42b372()
user32.dll!7e418734()
user32.dll!7e418816()
user32.dll!7e4189cd()
user32.dll!7e418a10()
QtCored4.dll!672359b6()
ntdll.dll!7c90cfdc()
ntdll.dll!7c958e0d()
ntdll.dll!7c95932a()
ntdll.dll!7c90cfdc()
ntdll.dll!7c9594ca()
ntdll.dll!7c919ca7()
ntdll.dll!7c918f01()
ntdll.dll!7c91925d()
ntdll.dll!7c918f01()
ntdll.dll!7c9101bb()
ntdll.dll!7c9192ef()
ntdll.dll!7c918f01()
ntdll.dll!7c9101bb()
user32.dll!7e4277b0()
user32.dll!7e4277f7()
ntdll.dll!7c90da0c()
kernel32.dll!7c8024c7()
msctf.dll!74725951()
msctf.dll!74725956()
user32.dll!7e418a80()
user32.dll!7e418734()
user32.dll!7e418816()
ntdll.dll!7c96c6a7()
QtCored4.dll!6723c8f6()
datProgram.exe!__tmainCRTStartup() Line 578 + 0x35 bytes C
datProgram.exe.exe!WinMainCRTStartup() Line 403 C
kernel32.dll!7c817067()
`
What makes me curios is, that in another tab is one QTableWidget with the same methods as described above, but the problem does not occur there.
And when running in release version(Ctrl+F5) the problem also seems to be gone ... ò.Ó
Any advice?
From time to time i create the SettingsMapper
new (and delete it before that) to reset
the 'outdated' mapper-combobox connections.
Do you by any chance delete the signal mapper from a slot called by signal sent from that signal mapper? That's not allowed, can't delete the instance when you are currently in a method of that instance.
Solution is to use deleteLater() instead. That will cause the object to be deleted when control returns to event loop.