Compiler recognizing wrong function with same name - c++

Im implementing a new slot which just has to call the method reset(). My new class is subclassing QAbstractListModel in which QAbstractListModel::reset() exists.
//stationlist.h
class StationListModel : public QAbstractListModel
{
Q_OBJECT
...
public slots:
void dataChanged();
//stationlist.cpp
...
void StationListModel::dataChanged()
{
reset();
}
However, in the implementation the method reset() is recognized as QTextStream::reset() and doesn't compile because of this. What could be the cause for such behaviour?

Thanks to the comment, the conclusion is that the method QAbstractListModel::reset() doesn't exist.
It is here only still available fer backwards compatibility http://qt-project.org/doc/qt-5.1/qtcore/qabstractitemmodel-compat.html#reset.
I believe that QTextStream::reset() is just something that the QtCreator offered as a global autocomplete.
The solution is to use non deprecated method.

Related

Inherit signals and slots from a base class in Qt

I have created:
class A : public QObject
{
Q_OBJECT
public signals:
Q_SIGNAL void mySignal();
};
And I would like to derive:
class B : public A
{
//Some added functionality
};
And still be able to connect mySignal() emitted by B (which it inherited from A) to a slot in my QMainWindow:
B b;
connect(&b, SIGNAL(mySignal()), this, SLOT(aSlot()));
Currently this method results in "multiple definition of "A::disconnected()" and the compiler points me to the moc file here:
void A::disconnected()
{
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
}
What is the problem here?
I have done my research but what I found seems to be on different types of inheritance patterns and I don't understand Qt enough to port conclusions here.
Edit: I had stupidly forgotten the & in my original post, thanks Scheff's cat - I've updated my problem.
For those of you who have the same problem as this one, check your source file for a potential definition of A::mySignal()... I had created an empty definition of the function, as usual, whereas apparently MOC creates one for us. Resulting in multiple definitions.

C++ QT Call C++ function in QJSEngine

I'm trying to call a function which is implemented in C++ to call in a JS function, which gets evaluated with the QT QJSEngine.
So far I have tried this
class Person : public QObject {
Q_OBJECT
public:
Q_INVOKABLE cppFunction(int a);
};
My function evuation looks like this
QJSValue formulaFunction = jsEngine->evaluate("(function(" + functionArgList.join(",") + "){ " + formula + "})");
In formula I have a call to cppFunction and functionArgList provides the arguments, these work fine, I have checked them.
So, but somehow it doesn't get called, I don't get an error too. Am I missing something or should it work this way?
So, after some research I got it running.
class MyObject : public QObject{
Q_OBJECT
public:
Q_INVOKABLE MyObject() {}
Q_INVOKABLE bool hasChannel(int id);
};
QJSEngine engine;
QJSValue injectedObject;
injectedObject= engine.newQMetaObject(&MyObject::staticMetaObject);
engine.globalObject().setProperty("MyObject", injectedObject);
So, here I'm creating a new class which is inheriting from QObject.
The class has two methods, every method I want to invoke in the QJSEngine has to provide the Q_INVOKABLE Label in front of the method declaration.
An example JS code run by the engine would look like this
let myObject = new MyObject();
myObject.hasChannel(1234);
I don't know if the injected prefix is appropriate, but I couldn't think of a better one

Is there a way to customize the compile error/warning message?

For example, if I have a class like this:
class Widget {
public:
virtual void Init(); // In this function, call some virtual function
// to construct the object
void Paint(); // Deprecated, use paintWidget instead
void PaintWidget(); // A new implementation of paint
... // Other stuff, including a virtual function
// which need to be called to construct the object
}
The construction of a Widget requires a virtual function call (that's why I wrote the Widget::Init()). Is there a way to make a constraint on Widget::Init() so that it must be called before any use of the object, and raise error if the user violates the constraint? Another problem is creating a customize warning message for a deprecated method. With the code above, if a user of my class calls Widget::paint(), how can I tell them to use Widget::paintWidget() instead of deprecated Widget::paint(), and tell them about the consequence of using the deprecated one? Thank you.
Part 1 of your question:
No, there is no good way of giving a custom message on using a private method. What I would do is to make sure that you only have a public API which forwards to the private implementation. This can be done via some pimple pattern or by creating a facade.
As you did not specify the way someone would get the Widget, I'm currently assuming a Singleton.
class Widget {
public:
Widget() : _impl(getHoldOfPrivateWidgetViaSingleton())
{
_impl.init();
}
// ...
private:
PrivateWidget &_impl;
};
// Note: rename of the Widget in your example
class PrivateWidget {
private:
friend class Widget;
PrivateWidget();
// ...
};
The disadvantage of doing this is that you will have to write some/a lot of forwarding code.
Part 2 of your question:
class Widget {
public:
void Init();
[[deprecated("use paintWidget instead")]] void Paint();
void PaintWidget(); // A new implementation of paint
...
private:
Widget();
...
}
Note that if you don't have access to a modern compiler with C++17 enabled, you might want to check out your compiler specific attributes.
You can use #warning directive, most of the widespread compilers (GCC, VC, Intels and Mac), support #warning message.
#warning "this is deprecated, use the Init() method instead"
A good practive is to not only show a warning (which people can ignore), but make the compiling fail, using the #error directive (which is quite standard):
# error "this method is forbidden and private"
As a Visual Studio specific solution, you can use pragma.

Sub-classing QCompleter, virtual slot in my sub-class not being called

I am sub-classing QCompleter to give it some special functionality. I want activated() to be fired when there is only one completion in the model with the given prefix, but that's not where I'm having a problem.
I have created a virtual setCompleterPrefix() in my sub-class but the compiler doesn't seem to notice it. Instead the base QCompleter::setCompletionPrefix() is called when the user enters a prefix. Am I doing something wrong?
Here is my class:
#ifndef INSTANTCOMPLETER_H
#define INSTANTCOMPLETER_H
#include <QCompleter>
namespace Reliant
{
class InstantCompleter : public QCompleter
{
Q_OBJECT
public:
explicit InstantCompleter(QObject* parent = 0);
private:
signals:
public slots:
virtual void setCompletionPrefix(const QString &prefix);
};
}
#endif // INSTANTCOMPLETER_H
Definition:
#include "instantcompleter.h"
using Reliant::InstantCompleter;
InstantCompleter::InstantCompleter(QObject* parent) :
QCompleter(parent)
{
}
void InstantCompleter::setCompletionPrefix(const QString &prefix)
{
int completionCount = this->completionCount();
if(completionCount == 1 && setCurrentRow(0))
emit activated(currentCompletion());
else
QCompleter::setCompletionPrefix(prefix);
}
You can use the model returned by QCompleter::completionModel() and its signals to track the completion count:
InstantCompleter::InstantCompleter(QObject* parent) :
QCompleter(parent)
{
connect(completionModel(), SIGNAL(layoutChanged()), SLOT(completionModelChanged()));
}
// declared in the "private slots:" section
void InstantCompleter::completionModelChanged()
{
if (completionCount() == 1 && setCurrentRow(0))
emit activated(currentCompletion());
}
According to this "This method is also a Qt slot with the C++ signature void setCompletionPrefix(const QString&)." from http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qcompleter.html#setCompletionPrefix that function isn't virtual and thus can't be overriden. I suspect that there's an alternate interface to override that capability though.
In order to override a method in C++, the base class must define it as virtual. Adding virtual to the method in your subclass does not change this behaviour.
Likewise, there is no way of overriding that method (unless you have a commercial license and change the Qt Framework for your needs which I wouldn't recommend) and you have to think of another way.

Broken indentation for Qt-specific constructions in Visual Studio

Automatic indentation in VS editor obviously does not know about Qt. And declarations of signals and slots are auto-formatted like this:
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass();
signals: // <-- Broken indentation
void someSignal();
public slots: // <-- Also broken
void someSlot();
};
I want "signals:" and "slots:" automatically formatted just like access specifiers. What are the options? (I'm using VS2010)
In short answer seems to be NO. Maybe not what you are looking for but maybe you can live with this:
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass();
private:
Q_SIGNAL void someSignal();
public:
Q_SLOT void someSlot();
};
(It's ugly but it seems you can't have your cake and eat it too ;)
Just something I'm wondering about: Is it worth the effort to build a plugin for automatic formatting? Do we really use CTRL-A CTRL-F so much? If so, then yes it could be a pain. But normally if you are working on header files declaring a new method (signal or slot) should not mess up the previous corrected indentation. Perhaps you have some reasons that justifies this?