QStandardItemModel - how to ignore data changed event by row moved but NOT by cell changes from user - c++

I'm using QStandardItemModel with table view.
My table allows moving rows and for user to edit a cell.
I want to catch the cell changes from user edits.
Problem is, if a user drags a row, and/or edits cells the same signals are fired. How can I grab the cell changes and ignore the row changes?

Solution is to Subclass the QStandarItemModel. Don't waste time trying to track from the GUI by item selected, clicked, pressed. Once you subclass, you're now in control of how the model (which is your data) is going to work, we can do anything.
In particular, look at ::itemData, the ::dropMimeData and ::setData functions. Between those items you know which are from internal dnd or not. You can store to var's, emit by Qt's sig/slot mechanism to GUI, or whatever your class needs.
Another useful tool is to hook into the deleget closeEditor func:
#include <QAbstractItemDelegate>
QAbstractItemDelegate * d = tv->itemDelegate();
connect(d, &QAbstractItemDelegate::closeEditor, this, &MainWindow::endEditHint);
Hope this helps anyone who might have this arise.

Related

Signal editTextChanged for editable QComboBox sets cursor position at end after setEditText

There is editable QComboxBox. It handles all the functionality well except for the case when we edit/insert/delete character of a string in position other than end.
e.g. "Hello" , if we delete 'e' cursor reaches at end.
currently editTextChanged(string) signal handling is such that inside it setEditText(string) has been called which causes the cursor to reach at end.
Have gone through some other stackoverflow forums where people have suggested to use -> saving initial cursor position , then call setEditText and then reset the cursor to saved position. This looks good but looks like workaround soln.
Wanted to know whether there can be other way to
i) call setEditText when focus has been lost.(QFocusEvent will not work since derived class is inherited from QObject not QWidget) or
ii) call comboBox->lineEdit functionality to do setEditText.
tried below but it doesn't work
connect(qcomboBox->lineEdit(), SIGNAL(editingFinished()), this, SLOT(textChanged()));
Following are the links which I have gone through
1) editFinished for editable comboBox
2) saving cursor postion
You can install an event filter on the QComboBox and detect its focus in/out events that way. Look up QObject::installEventFilter in the documentation; it's pretty straightforward to use.
All of the events received by QComboBox will go through your class first, and you can decide what to do about them, if anything. That gives you the ability to change one class's behavior (i.e. the QComboBox) from another class (your's) without subclassing QComboBox.

How to get UI objects to only appear in dialog AFTER button is clicked

I have a dialog that initially has several buttons, let's call them Write, View, OK, and Cancel.
The way it should to is to have the dialog upon creation only have those three buttons and nothing more.
When the Write button is cancelled, it's supposed to create a QLineEdit object in the window above the buttons where the user can enter a new string,which when OK is then clicked will be added to an external QStringList.
When View is clicked, LineEdit should go away (if it's up) and a QListView to come up instead to view everything in that list.
The problem is, I know how to use hide() to get objects that are already in the dialog to NOT appear.
but I am having trouble figuring out how to get an object not currently on the table to appear. I'm new to using Qt so it may be something easy I'm just accidentally overlooking (in fact I hope it is).
Could anyone please offer advice? Thanks!
Just create the items normally and then set:
ui->control->setVisible(false);
after you have created the UI (after ui->setupUi(this);) possibly in the constructor (in case you use code generated by Qt Creator).
And when you need them:
ui->control->setVisible(true);
Doc for this:
http://qt-project.org/doc/qt-4.8/qwidget.html#visible-prop
when using a QListView you should also have a QListModel that provides the data to it, if you only have QStrings then a QStringListModel is premade for you to use
to add a row you can do:
int rows = model->rowCount();
model->addRow(rows,1);
QModelIndex index = model->index(rows,0);
model->setData(index, string);

QTableView doesn't respond to dataChanged when not focused

I have a QTableView that's connected to a QAbstractTableModel subclass. I'm editing the data owned by the model in response to user input in a different control (not the QTableView), and then I'm calling a method on the model that emits the dataChanged event:
void CharacterModel::characterChanged(int idx)
{
emit dataChanged(index(idx, 0), index(idx, (int)kNumColumns));
}
This works, as long as the QTableView is focused. As soon as it's not, it no longer shows the updated data. If I focus it again, it updates immediately. For example, I modified my code that's calling the above method to call setFocus() on the table view right afterwards, and everything is fine - except that my editing control loses focus every time I do anything. Not OK. I have several editing controls, including spin boxes; if I click on the spin box arrow, the FIRST update is displayed (because the table view is still focused), but then the spin box gets focused and all subsequent changes don't get displayed.
Anybody have any idea what's going on? This seems to be extremely well-defined behavior, but I can't find any reference to it anywhere.
Thanks,
Aaron
I think I've solved this. Turns out the solution is to call tableView->viewport()->repaint() after the dataChanged event fires. Calling tableView->repaint() doesn't do it.

How to emit signal, when user changes row with keyboard arrows in tableView?

I have two tableViews, in one I load album names, in the other I want to load tracks from selected album.
Problem is simple: I can't use signals such as activated, mouse clicked, etc. I want to change stuff in the tracks tableView simply by the highlighting row in the album names tableView.
Summary: emit signal when user changes row and find out on which row he is now.
See the Handling selection of items section in the Qt Model/Views documentation.
In essence, what you need to use is your QTableView's selection model which has signals for when the selection changes in the table. You access the view's selection model via it's selectionModel() member function.
Ok,so i have solved this problem like this:
First, you must obtain QItemSelectionModel !after! the table was filled:
QItemSelectionModel *select = ui->tableView->selectionModel();
Then connect SIGNAL "selectionChanged" with you own SLOT function:
connect(select, SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
this, SLOT(change_table()));

Qt/C++: Signal for when a QListWidgetItem is checked?

In my form I have a QListWidget which contains checkable QListWidgetItems. I'm looking for a way to capture the event of a QListWidgetItem being checked/unchecked. I don't see any such signal existing for this but maybe I'm wrong. What I'm currently doing is using the QListWidget::itemClicked() signal and checking the checkState of the QListWidgetItem, but this isn't what I want because this event happens any time the item is clicked, not just went the checkmark is toggled. Can anyone give some assistance? Thanks!
Apparently no such signal is provided, your best bet is to use QListWidget::itemChanged(QListWidgetItem* item) , and scan the resulting item->checkState(). This should be a slight improvement over using itemClicked
An extra option is to use your own QAbstractListModel with a QListView. At first this does add some extra code as you need to add your own management code . But you do get a lower level access. Basically because the QListView will ask your model what to do. It will also relay input back to your listmodel where you can hook into it.
Alternatively you could subclass QStandardItemModel and catch certain edits related to changing the checkbox.