Is it possible to override non-virtual slots in Qt? - c++

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();
}
};

Related

How to override undo / redo in QPlainTextEdit

I am sub-classing QPlainText edit and I would like to be able to intercept undo / redo commands so that I can implement custom functionality.
I realise that I can disable the undo / redo capability with setUndoRedoEnabled and I can detect Ctrl+Z and Ctrl+Y key presses. However, this doesn't seem like the best cross platform way of doing it.
Any advice?
You simply need to reimplement the slots :
class MyTestEdit : public QPlainTextEdit {
Q_OBJECT
public slots:
void redo() { ... }
void undo() { ... }
};
Signal and slots are exactly like other c++ methods. If you reimplement them in a subclass, they will be called instead of the the parent's.
I think you can use "QUndoStack" for this.
In you subclass's constructor (constructor is better), call a method that creates Undo and Redo actions to handle for your class.
Prototype:
//Call this function to register undo and redo actions.
Void methodCrteaesUndoandRedoActions()
{
QUndoStack unStack = new QUndoStack (this);
QAction *undoAct = undoStack->createUndoAction(this);
QAction *RedoAct = undoStack->createRedoAction(this);
}
//Implement below functions in your class to handle the business.
void undo()
{
}
void redo()
{
}

QTableWidgetDervied::cellChanged

When I edit cells cellChanged is not called. What did I do wrong?
class QTableWidgetDerived : public QTableWidget
{
Q_OBJECT
//...
protected:
void cellChanged(int row, int column)
{
//...
}
//...
};
class QTableWidgetDerived : public QTableWidget
{
Q_OBJECT
public:
//...
void f(int, int);
protected:
void cellChanged(int row, int column)
{
//...
}
//...
};
connect(this, SIGNAL(cellChanged(int, int)), this, SLOT(f(int, int)));
This does not work. What is wrong?
void cellChanged(int row, int column) is a SIGNAL, not a virtual function you can override. Just connect the SIGNAL to a SLOT and go on.
When I edit cells cellChanged is not called. What did I do wrong?
It cannot be called, only emitted sine it is a signal and not a method or slot.
Respectively, when you subclass QTableWidget, you do not need to put the declaration into your class.
Furthermore, your connect usage is wrong. You are trying to use it outside the class which is wrong. I suggest to put that into an actual method, otherwise it will not even compile.
Also, while it is not a compilation error not to use the arguments from cellChanged in your slot, you may wish to revisit that decision based on your use case.
Furthermore, your slot is not marked as slot, just a regular public method in your class declaration. You would need to change it to something like this, otherwise, again, it will not be acceptable and you will likely get runtime issues which is probably your issue in here:
public slots:
void f();

Qt4: connect slot and signal from other forms

I have a small problem. I want run function in MainWindow from AnotherWindow. I can't set connect() for it.
Main class: MainWindow
Other form: AnotherWindow
Function in main class: setVariable(QString)
Function in other form: btnClicked()
I have now connected button signal clicked():
// In AnotherWindow.cpp
connect(ui->btnOK, SIGNAL(clicked()), this, SLOT(btnOkClicked()));
// Function in same file
void interfaceWindow::btnOkClicked() {
/* Some actions - emit signal? */
this->close();
}
btnOkClicked() are declared as private slot.
// In MainWindow.cpp
void MainWindow::setVariable(QString _var) {
this->var = _var;
}
setVariable(QString) are declared as public slot.
How I can send variable from AnotherForm (from btnOkClicked() function) to MainWindow (setVariable(QString) function) ? How and where I must send signal and make connection?
I readed about signals and slots, but my code don't work - I don't paste it here because it's terrible :)
Any help for Qt newbie?
You need to have an reference of AnotherWindow in MainWindow OR vice versa. Then you need the following things:
// AnotherWindow.h
signals:
void buttonOkClickedSignal(QString var);
// AnotherWindow.cpp
void interfaceWindow::btnOkClicked() {
emit buttonOkClickedSignal("The button got clicked!");
this->close();
}
Next step varies based on whether MainWindow has reference to AnotherWindow or vice versa. You can either:
// AnotherWindow.cpp
connect(this, SIGNAL(buttonOkClickedSignal(QString), &mainWindow, SLOT(setVariable(QString)));
or:
// MainWindow.cpp
connect(&anotherWindow, SIGNAL(buttonOkClickedSignal(QString), this, (SLOT(setVariable(QString)));
If you are invoking the slot through signal it shouldn't matter whether it's private or public (see Qt Documentation).
Hope this helps.
I'm not entirely sure I understand your question, but let me try.
You want to be able to fire a slot in another class. There are a few ways you can do that.
Declare one as a friend class to the other. Then they can see the protected and private variables/memebers
It is possible to make slots static so you can call them without a class object.
For example,
class MainWindow {
private slot:
void setVariable(QString);
}
class AnotherWindow {
friend class MainWindow;
MainWindow *window;
public:
AnotherWindow() {
connect(this, SIGNAL(fire(QString)), window, SLOT(setVariable(QString)));
}
signals:
void fire(QString);
public slots:
void onButtonClicked() {
emit fire(QString);
}
}
The previous is pseudocode so don't expect it to compile. I think this is what you want. Basically since your slot is private on MainWindow you need to make it a friend. To connect, it needs to be a member. Then when the onButtonClicked slot is evoked, then it fire()s the setVarialbe() slot.
Here is a simple code for your another window:
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget * parent = 0)
{
okBtn = new QPushButton ("I am Ok!");
MyData = "";
connect(okBtn ,SIGNAL(clicked()),this,SLOT(OnOk()));
}
~MyWidget();
private:
QString MyData;
QPushButton * okBtn;
//something that modify string MyData
signals:
void MyDataSignal(QString);
//Internal slot that emits signal with proper data
private slots:
void OnOk()
{
if(MyData!="")
{
emit MyDataSignal(MyData);
}
}
};
Now in MainWindow create an object of MyWidget (suppose myWid)and connect it to slot
connect(myWid, SIGNAL(MyDataSignal(QString)),this,SLOT(OnMyWidOkClicked(QString)));
the signal will pass string to slot.
While making signals and slots keep in mind following points:
To connect a signal to a slot (or to another signal), they must have the same parameter
Parameters should be in the same order in both signal and slot.
if a signal has more parameters than the slot it is connected to, the additional parameters are simply ignored but opposite is not possible.
If you will connect a signal that have unmatched parameters to slot then no compile time error will occur but at run time command window will show a warning that signal/slot/connection does not exist.

Signal/Slots feature for different classes in Qt C++

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.

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.