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.
Related
I would like to run some of my code when the resizeColumnsToContents slot gets called. However the resizeColumnToContents slot is not virtual. Is there any other way to achieve this?
If the slot was virtual this is what I would like to do:
class DerivedTableView : public QTableView
{
public:
void resizeColumnsToContents()
{
printf("The user wants to resize the columns\n");
QTableView::resizeColumnsToContents();
}
};
How can I access widgets from a customized widget?
For example:
I have a customized widget:
Now I have a "user info" form that has a QWidget promoted to "My Custom Widget":
How can I get the text from my custom widget? (e.g. QLineEdit->text())
The right way is to create a suitable accessor method in your MyCustomWidget implementation:
namespace Ui {
class MyCustomWidget;
}
class MyCustomWidget : public QWidget
{
// You may also wish to add WRITE and NOTIFY methods;
// that's left as an exercise for the reader.
Q_PROPERTY(QString name READ name)
const std::unique_ptr<Ui::MyCustomWidget> ui;
public:
explicit MyCustomWidget(QWidget *parent = 0);
~MyCustomWidget();
QString name() const;
};
#include "ui_mycustomwidget.h"
// Constructor and destructor
MyCustomWidget::MyCustomWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::MyCustomWidget)
{}
MyCustomWidget::~MyCustomWidget() = default;
// Accessor
QString MyCustomWidget::name() const
{
return ui->nameEdit->text();
}
You can then call the MyCustomWidget::name() method from within methods of UserInfo in the normal way:
ui->customWidget->name();
You'll want to create similar accessors for address() and phone() too, of course.
The hacky way would be to obtain the line-edit by name, using QObject::findChild<QLineEdit>(). That really breaks encapsulation, and I won't describe that further.
QLineEdit->text() is syntactically incorrect and won't compile. QLineEdit::text() will not compile either, because text() is non-static member and this call does not make sense without a QLineEdit object.
Back to your question, first you need to access a custom widget itself. It's easy, once you named the widget somehow in the editor:
In this example its name is customWidget. Thus, in the ui private member of QDialog class you'll find a public member named customWidget, which has type MyCustomWidget and corresponds to a widget on the picture. Having this, you may access the public members of customWidget. QDialog corresponds to your User Info widget class.
For example, you may declare signals (let's call them value1Changed(QString), value2Changed(QString) and so on) in MyCustomWidget and forward signals from QLineEdits to these signals using signal-to-signal connect(). Then you may connect value1Changed to any slot of QDialog or any other object from the scope where customWidget pointer is visible.
Another way to go is to declare public methods like QString getLine1Content() const in MyCustomWidget and access them from QDialog whenever you want.
These are not the only methods to access members of a custom widget, but the most frequently used ones.
Based on the answers, I created some getters and setters methods to get and set the values of the fields in the "My Custom Widget".
In my MyCustomWidget class I created the getters and setters for each field:
public:
void setNameLineEdit(QString value);
QString getNameLineEdit();
void setAddressLineEdit(QString value);
QString getAddressLineEdit();
void setPhoneLineEdit(QString value);
QString getPhoneLineEdit();
And then:
void MyCustomWidget::setNameLineEdit(QString value)
{
ui->nameLineEdit->setText(value);
}
QString MyCustomWidget::getNameLineEdit()
{
return ui->nameLineEdit->text();
}
...
Now I can access these methods from my UserInfo class:
ui->myCustomWidget->setNameLineEdit( QString("Paul") );
Thanks a lot for all help.
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.
According to the help of Qt for QWebPage [Slot ShoudInteruptJavaScript], located here:
This function is called when a JavaScript program is running for a long period of time.
If the user wanted to stop the JavaScript the implementation should return true; otherwise false.
The default implementation executes the query using QMessageBox::information with QMessageBox::Yes and QMessageBox::No buttons.
Warning: Because of binary compatibility constraints, this function is not virtual. If you want to provide your own implementation in a QWebPage subclass, reimplement the shouldInterruptJavaScript() slot in your subclass instead. QtWebKit will dynamically detect the slot and call it.
I don't want qt show a message when javascript runnig for long period of time.
So, how can i reimplement ShoudInteruptJavaScript? and where should i create it?
Please show me a sample
Thanks
All the info you need is in the documentation.
Create a new custom class that inherits from QWebPage, make sure it's a Q_OBJECT to receive signals.
class MyFunkyPage : public QWebPage {
Q_OBJECT
public slots:
bool shouldInterruptJavaScript() {
QApplication::processEvents(QEventLoop::AllEvents, 42);
// Ignore the error
return false;
}
};
Set the page of your QWebView to a custom subclass of QWebPage.
setPage(new MyFunkyPage());
Then when your page gets this signal it won't stop the script from executing, and it won't show a dialog.
The MyFunkyPage solution potentially leaks memory and causes crashes because the object passed to setPage has no parent and setPage does not take ownership. Instead,
class QWebPageWithoutJsWarning : public QWebPage {
Q_OBJECT
public:
QWebPageWithoutJsWarning(QObject* parent = 0) : QWebPage(parent) {}
public slots:
bool shouldInterruptJavaScript() {
return false;
}
};
Set the page of your QWebView to the custom subclass of QWebPage, parented on the WebView,
void suppressJSWarning(QWebView& webView) {
webView.setPage(new QWebPageWithoutJsWarning(&webView));
}
#anson-mackeracher almost had it right.
Qt needs it to be a private slot, not a public one. Here's what works for my class:
class MyFunkyPage : public QWebPage {
Q_OBJECT
private slots:
bool shouldInterruptJavaScript() {
// Ignore the error (return true to kill the runaway JavaScript)
return false;
}
};
Set the page of your QWebView to a custom subclass of QWebPage.
setPage(new MyFunkyPage());
I just tested this with Qt 4.8.4 and it works like a charm. I didn't need the processEvents call.
For just one class , i declare a slot and a signal , and in slot method definition i call signal method with emit keyword. But how can i emit signals with one class to another class which has a slot.
Well i try with a button to modify a label text. Button is created by A class (which must emit a signal) , and label is created by class B which must have a slot to modify text on it
It seems like you have class 1, which has a method that will be executed, and will call "emit". When that happens, the slot of another class will find out.
definition of 1st class:
class songs_text {
public:
signals:
void send_signal();
}
int songs_text:function() {
emit send_signal();
}
definition of class 2:
class wind {
public slots:
void continue_job() {
};
}
and your main program:
Wind wind();
Get_source songs_text(&mtempfile);
QObject::connect(&songs_text, SIGNAL(send_signal()),
&wind, SLOT(continue_job()));
Add a public method in the class named void emitSignalBlahBlah() to be a wrapper around the emit code. Then, all the other classes that need to fire this signal will access this object and call the method to do it.