I am working on a simple drawing widget in Qt (all of the following is within one class). In the header file, I have defined
private:
QPointF translateToCanvas (QPointF input);
and in the CPP file I have defined
QPointF translateToCanvas (QPointF input) {
return input - QPointF(CANVAS_MARGIN_X, CANVAS_MARGIN_Y);
}
Somewhere else in the code, I call this with
QPointF newPoint = translateToCanvas(anotherPoint);
Whenever I compile, it gives me the error "undefined reference to `MyClass::translateToCanvas(QPointF)'", and this is happening inside the stuff that moc's generating and not actually my literal code.
What could be causing this error in Qt? (I'm using Qt Creator with Qt 4.5.)
This has nothing to do with Qt.
QPointF translateToCanvas (QPointF input) {
return input - QPointF(CANVAS_MARGIN_X, CANVAS_MARGIN_Y);
}
defines a standalone function named translateToCanvas, which has nothing to do with the private method you declared in your class, other than happening to have the same name. You want
QPointF MyClass::translateToCanvas (QPointF input) {
return input - QPointF(CANVAS_MARGIN_X, CANVAS_MARGIN_Y);
}
Related
I've made a MyComponent QML component with some property:
Q_PROPERTY(PendingList* list MEMBER list)
and a function:
Q_INVOKABLE void send();
It can be created in QML:
MyComponent {
id: myComponent
}
When I call somewhere the myComponent.send() while the list property is not defined, how can I properly report the problem in the stderr? I'd like to see the *.qml file name and line number where send() was called or the line number of the myComponent creation.
Is there a proper way to maybe get the QML stack trace or generate QQmlError or throw an exception that will be handled by the QML engine?
Will have to use some private stuff.
QTDD14 - Categorized logging in QML - Giuseppe D'Angelo
Git repository with the slides and the code: qmllogging
Short Version
Add to CMakeLists.txt:
include_directories(${Qt5Quick_PRIVATE_INCLUDE_DIRS})
Add some QV8Engine stuff to your Q_INVOKABLE function or slot:
#include <QtQml>
#include <private/qv4engine_p.h>
#include <private/qv8engine_p.h>
void Logger::log(const QString &message)
{
const QV4::StackFrame frame = QV8Engine::getV4(m_engine)->currentStackFrame();
QMessageLogger(qPrintable(frame.source),
frame.line,
qPrintable(frame.function)).warning("%s", qPrintable(message));
}
Geting the engine for that function:
QQuickView view;
m_engine = view.engine();
Also set the message pattern to actually show the line number (somewhere in the beginning of main.cpp is fine):
qSetMessagePattern("%{file}:%{line} - %{message}");
I have the following:
QString themePath(":/themes/");
std::vector<QString> resourcePaths;
resourcePaths.push_back(QString("html/details.html"));
std::vector<QFile> resources;
for (std::vector<QString>::iterator it = resourcePaths.begin(); it != resourcePaths.end(); ++it) {
QString path = QString("%1%2/%3").arg(themePath, THEME, *it);
QFile resource(path);
resources.push_back(resource);
}
gives me the following error:
error: 'QFile::QFile(const QFile&)' is private.
I get the same error if I use QList instead of std::vector.
Thank you for your attention.
The problem, is that you use QFile values in the container which implicitly perform copying of items with using the copy constructor which is private member function of QFile class. The compiler tells you that. To solve this you can try to simply store QFile pointers instead.
I have looked at several different tutorials and all the code looks the same but when I try to compile it I get two errors. They are no match for call to '(QFile) (QString&)' no match for call to '(QTextSteam) (Qfile)'. Could you please explain why? The following is part of my code if you need more just ask.
my header chunk of code
private:
QLabel *label;
QTextEdit *left;
QTextEdit *right;
QLineEdit *user;
QTextStream file;
QFile namefile;
QString name;
QString n;
my source code
n ="name.txt";
namefile(n);
if (!namefile.open(QFile::ReadOnly))
{
return;
}
file(&namefile);
name=file.readLine();
right->setText(name);
Your question seems to have more to do with C++ than with Qt. In particular, it would be worthwhile for you to look into C++ initialization lists, and how class members are constructed in general.
In any event, I am assuming that the code you've listed as "my source code" is in the constructor of a class. One option is to first re-order the private members such that they are listed in order of initialization:
private:
QString n;
QFile namefile;
QTextStream file;
QString name;
Then to initialize them in the initialization list of the class constructor:
MyClass::MyClass()
:n("name.txt")
,namefile(n)
,file(&namefile)
{
if (!namefile.open(QIODevice::ReadOnly))
{
return;
}
name = file.readLine();
// Rest of your code goes here.
}
There are other ways of accomplishing this, but I'll leave it to you to research what I've suggested above.
Just change
file.setDevice(&namefile);
i trying to created a Qt application multilanguage with Qt linguist.
I place this code in an function of my MainWindow :
translator.load(":/lang/English");
qApp->installTranslator(&translator);
ui->retranslateUi(this);
With the QTranslator declare in my MainWindow.h and all my string i want translate enclose by tr() . But with that, all QObject added dynamicaly by the code of my MainWindow.cpp, for example the title of a QTableWidget, are not translated.
If i place an other translator in my main.cpp, all my string are translate but i must created language button in my application and so i can't place translator in main.cpp.
Do you have an idea to help me?
Thx for your answers.
Gat
When you add a translation in your application using qApp->installTranslator(& aTranslator) then all the following calls to QObject::tr() (and similar functions) will look up in the translator for a translated text. So you should call retranslateUi() after qApp->installTranslator(). Actually you might event not call it there, you may reimplement QWidget::changeEvent() and intercept any QEvent::LanguageChange event.
void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
// Someone called qApp->installTranslator() with a new translation.
// Let's update the user visible strings.
// This function was created by uic from the Designer form.
// It translates all user visible texts in the form.
ui->retranslateUi(this);
// This function must be written by you. It translates other user visible
// texts that are not in the form. See down for an example.
this->retranslateUi();
break;
default:
break;
}
}
ui->retranslateUi() just calls QObject::tr() for each user visible string in the ui. It is called automatically at the end of setupUi() and populates the form's widgets with translated text (have a look, it is defined by uic in ui_MainWindow.h file). You may want to take a similar approach with other user visible texts, like the title of a QTableWidget. All the strings are set in a function (named perhaps retranslateUi() for consistency) which is called at application starts (or, better, after the relevant widgets are created) and every time a new translations is loaded.
MainWindow::MainWindow(QWidget * parent)
: QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Creates other widgets, but do not set their user visible texts.
tableWidget = new QTableWidget(this);
...
someControl = new QLineEdit(this);
someOtherControl = new QSpinBox(this);
someModel = new MyModel(this);
...
// Ok, *now* we set their texts.
this->retranslateUi();
}
...
void MainWindow::retranslateUi()
{
// This function will be called (either manually or automatically by
// `changeEvent()`) when a new translator has installed, hence all the `tr()`
// calls will return the right translation for the last installed language.
QStringList labels;
labels.append(tr("First column"));
labels.append(tr("Second column"));
labels.append(tr("Third column"));
tableWidget->setHorizontalHeaderLabels(labels);
someControl->setText(tr("Control name"));
someOtherControl->setText(tr("Other control name"));
// Perhaps you have a model that need to be retranslated too
// (you need to write its `retranslateUi()` function):
someModel->retranslateUi();
...
}
Also, please note that if you are doing something like
void MainWindow::someFunction()
{
...
QTranslator translator;
translator.load(":/lang/English");
qApp->installTranslator(& translator);
...
}
as soon as that function returns the variable translator gets destroyed, so next time QObject::tr() is called the address stored with qApp->installTranslator(& translator) will be invalid. So you must allocate translator on the heap with new (and possibly deleting it with delete when you do not need it anymore). An exception is if you are doing that in main() before calling QCoreApplication::exec() since that function is blocking and will not return until application is closed.
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
...
QTranslator translator;
translator.load(":/lang/English");
app.installTranslator(& translator);
...
app.exec(); // This function will return only on application's exit.
// Hence `translator` will outlive the application, there is
// no need to worry about it.
}
I am developing a custom exception, where I'd need a QString member. Something like:
class MyException
{
private:
const QString fDescription;
public:
MyException(QString desc);
};
MyException::MyException(QString desc) : fDescription(desc)
{}
When I try to use it:
if (isErrorEncountered)
{
MyException e(QString("Descriptive message here..."));
throw e;
}
I get a segmentation fault.
The symptoms are similar as described here:
Qt QString cloning Segmentation Fault
The SIGSEGV originates from QBasicAtomicInt::ref, coming from QString::QString(const QString &other).
It seems to me as if there is an attempt to copy an invalid QString within a copy constructor. It is my understanding, that the QString keeps a pointer to its content as long as there is a valid reference to it. If a copy of MyException instance is being made, is it not true that the temporary stack instance has not left the scope and the copy should succeed?
When I implement MyException without a QString member, everything work well.
The answer to the question is "Yes, a QString can safely be a member in an exception."
The problems which I encountered were due to the fact that the object, acting as a source of data for the fDescription, had a bug. It implemented a getter method:
class Source
{
private: QString fData;
public: QString GetData(void) { this->fData; } // There is a missing return
}
Of course, the result of this call was the random value residing on the stack at the moment and hence the SIGSEGV.
The QString behaves as expected and with a valid reference to it, there are no problems using it in the exception.
The precise point where the SIGSEGV was raised was leaving the scope of the try block, where a copy of the exception is being constructed (remember: throw by value, catch by reference). The default copy constructor tries to create a shallow copy of all members and fails on accessing the invalid QString reference.