What signal emitted when hide a row or column in QTableView? - c++

As QTableView has public function setRowHidden() and setColumnHidden(), but if person A performs hide operation, how can person B get to know the changes? If there is a signal available that gives an idea about the geometry changes in QTableView ?
Thanks ahead.

No, signal is not emitted an doc doesn't say anything about it, but you can make it easily by yourself.
Just create subclass of QTableView and override setRowHidden and setColumnHidden methods, call original methods and add your signal emissions inside. Something like that:
MyTableView.h
#include <QTableView>
class MyTableView : public QTableView
{
Q_OBJECT
public:
MyTableView(QWidget *parent = Q_NULLPTR);
~MyTableView();
void setColumnHidden(int column, bool hide);
void setRowHidden(int row, bool hide);
signals:
void columnHidden(int column, bool hide);
void rowHidden(int row, bool hide);
};
MyTableView.cpp
#include "mytableview.h"
MyTableView::MyTableView(QWidget *parent) : QTableView(parent)
{
}
MyTableView::~MyTableView()
{
}
void MyTableView::setRowHidden(int row, bool hide)
{
QTableView::setRowHidden(row, hide);
emit rowHidden(row, hide);
}
void MyTableView::setColumnHidden(int column, bool hide)
{
QTableView::setColumnHidden(column, hide);
emit columnHidden(column, hide);
}
Now you can call your overloaded methods just like the original ones.

With the happiest mood, I finally found the solution to observe the hide/show behavior of a row/column in tableView. The method still goes-back to the signal/slot mechanism. Just because of strange terminology in Qt's system, some concepts are really not very straight-forward and confusing.
QTableView *tableView = new QTableView;
tableView->setRowHidden(0, true);
This will make a tableView's the 0st row hide. This operation actually just makes the row's section resizes. The result of this is the size of the section is ZERO, and signal sectionResized() emitted.

Related

QTableView does not detect doubleClick [duplicate]

My application starts with an empty table, and I want to imlement different methods to add items. One should be by double-clicking the table's unused area (or "background") that is not occupied by any cells. When a cell is double-clicked, I want the default behavior.
I've found way to do this by re-implementing QAbstractScrollArea::mouseDoubleClickEvent() method in my TestTable class:
#include <QMouseEvent>
#include <QTableView>
class TestTable : public QTableView
{
Q_OBJECT
signals:
void backgroundDoubleClickEvent(void);
protected:
void mouseDoubleClickEvent (QMouseEvent* e)
{
if (indexAt(e->pos()).isValid())
{
QTableView::mouseDoubleClickEvent(e);
}
else
{
e->accept();
emit backgroundDoubleClickEvent();
}
}
};
This works, but is there a more elegant way of doing this without subclassing QTableView?
I'm not aware of any limitations of my current implementation. Are there obvious caveats?
If you don't want to subclass QTableView, try installEventFilter

Catch double click in QTableView's unused area

My application starts with an empty table, and I want to imlement different methods to add items. One should be by double-clicking the table's unused area (or "background") that is not occupied by any cells. When a cell is double-clicked, I want the default behavior.
I've found way to do this by re-implementing QAbstractScrollArea::mouseDoubleClickEvent() method in my TestTable class:
#include <QMouseEvent>
#include <QTableView>
class TestTable : public QTableView
{
Q_OBJECT
signals:
void backgroundDoubleClickEvent(void);
protected:
void mouseDoubleClickEvent (QMouseEvent* e)
{
if (indexAt(e->pos()).isValid())
{
QTableView::mouseDoubleClickEvent(e);
}
else
{
e->accept();
emit backgroundDoubleClickEvent();
}
}
};
This works, but is there a more elegant way of doing this without subclassing QTableView?
I'm not aware of any limitations of my current implementation. Are there obvious caveats?
If you don't want to subclass QTableView, try installEventFilter

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

How do I detect row selections in QListView <- > QAbstractListModel with Item Delegate?

It seems there is zero built-in selection support with my choice of QListView -> QAbstractListModel. Do I have to write everything from scratch? the catching of a selection event in the UI, the marking of the model item as selected, etc? It seems there is no out-of-the-box support for this.
the weird thing is that there is a QItemSelectionModel that does support this, but you cannot use it with QListView as it’s not derived from QAbstract….
Should my model class use multiple inheritance to inherit both from QItemSelectionModel and QAbstractListModel? Otherwise I don’t see how I can avoid having to re-writing this functionality myself.
My final goal is for the delegate that draws my items to know if the item is selected, both in the paint and the sizeHint function.
QListView is derived from QAbstractItemView, which has a method to get the selection model:
QItemSelectionModel *selectionModel = myView->selectionModel();
This method returns a pointer to the selection model, which is long-lived, i.e., you can save the pointer, connect to its signals, etc.
The answer given by Daniel is correct, but it is better to show it with an example suitable for beginners:
class MyCustomModel : public QAbstractListModel
{
Q_OBJECT
public:
ImageCollectionModel(QObject *parent, MyCustomCollection *data);
: QObject(parent)
, m_myData(data)
{
}
public slots:
void onSelectedItemsChanged(QItemSelection selected, QItemSelection deselected)
{
// Here is where your model receives the notification on what items are currently
// selected and deselected
if (!selected.empty())
{
int index = selected.first().indexes().first().row();
emit mySelectedItemChanged(m_myData->at(index));
}
}
signals:
void mySelectedItemChanged(MyCustomItem item);
private:
MyCustomCollection *m_myData;
// QAbstractItemModel interface
public:
int rowCount(const QModelIndex &) const override;
QVariant data(const QModelIndex &index, int role) const override;
};
When you pass your custom model to the QListView, that's a great opportunity to connect it:
ui->myListView->setModel(m_myModel);
connect(ui->myListView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
m_myModel, SLOT(onSelectedItemsChanged(QItemSelection, QItemSelection)));

Get previous value of QComboBox, which is in a QTableWidget, when the value is changed

Say I have a QTableWidget and in each row there is a QComboBox and a QSpinBox. Consider that I store their values is a QMap<QString /*Combo box val*/,int /*spin box val*/> theMap;
When comboBoxes value or spin boxes value is being changed I want to update theMap. So I should know what was the former value of the combo box in order to replace with the new value of the comboBox and also take care of the value of the spin box.
How can I do this?
P.S. I have decided to create a slot that when you click on a table, it stores the current value of the combo box of that row. But this works only when you press on row caption. In other places (clicking on a combobox or on a spinbox) itemSelectionChanged() signal of QTableWidget does not work.
So in general my problem is to store the value of the combo box of selected row, and the I will get ComboBox or SpinBox change even and will process theMap easily.
How about creating your own, derived QComboBox class, something along the lines of:
class MyComboBox : public QComboBox
{
Q_OBJECT
private:
QString _oldText;
public:
MyComboBox(QWidget *parent=0) : QComboBox(parent), _oldText()
{
connect(this,SIGNAL(editTextChanged(const QString&)), this,
SLOT(myTextChangedSlot(const QString&)));
connect(this,SIGNAL(currentIndexChanged(const QString&)), this,
SLOT(myTextChangedSlot(const QString&)));
}
private slots:
myTextChangedSlot(const QString &newText)
{
emit myTextChangedSignal(_oldText, newText);
_oldText = newText;
}
signals:
myTextChangedSignal(const QString &oldText, const QString &newText);
};
And then just connect to myTextChangedSignal instead, which now additionally provides the old combo box text.
I hope that helps.
A bit late but I had the same problem and solved in this way:
class CComboBox : public QComboBox
{
Q_OBJECT
public:
CComboBox(QWidget *parent = 0) : QComboBox(parent) {}
QString GetPreviousText() { return m_PreviousText; }
protected:
void mousePressEvent(QMouseEvent *e)
{
m_PreviousText = this->currentText();
QComboBox::mousePressEvent(e);
}
private:
QString m_PreviousText;
};
My suggestion is to implement a model, which would help you make a clean separation between the data, and the UI editing the data. Your model would then get notified that a given model index (row and column) changed to the new data, and you could change whatever other data you needed to at that point.
I was just having a similar issue, but for me i needed the previous index for something very trivial so defining and implementing a whole class for it was unjustified.
So what I did instead was keep an argument called say 'previousIndex' and updated it's value only after I had done everything I needed with it