In QTableView, What "signal" triggers the editing mode - qt

I'm trying to write some Inherit class (Let's call it A) from QTableView, and hope to overwrite the slot
void edit ( const QModelIndex & index )
from QAbstractItemView. I know that this function can trigger editing mode, but here is my question: I hope that whenever editing mode are triggered by user in this class A, the program can go inside the overwritten slot A::edit.
However, it seems only when A::edit are directly called, the program can get in.
Since QTableView comes from QAbstractItemView, if the editing mode is triggered by other way(such as mouse double click), the program will run default QAbstractItemView::edit instead of A::edit.
I tried to connect the signal "activated", but apparently it's not the correct signal to trigger editing mode. Is there anyway to do something every time when an editor is triggered?
Also, I'd like to do something when the editing mode is ended by pressing Enter or ESC or mouse clicking on other place. The same situation happens at the slot
void editorDestroyed ( QObject * editor )
Can anyone help me to solve this problem?
I'll really appreciate it, thanks!

QAbstractItemView::edit(const QModelIndex& index) is not virtual, so that's why when you call it directly you get your subclass's behavior, but when existing code calls it they get they base class behavior. If that doesn't ring a bell, read that link; Qt has a lot of virtual and non-virtual functions and knowing what the difference is will save you a lot of headaches.
However, QAbstractItemView::edit(const QModelIndex& index, EditTrigger trigger, QEvent* event) is virtual, so you can override it. I haven't verified it, but presumably the non-virtual edit() calls this edit(), so it should have the same effect.
QAbstractItemView::editorDestroyed(QObject* editor) is also virtual, so I'm not sure why it isn't be working. However, there is also QAbstractItemView::closeEditor(QWidget* editor, QAbstractItemDelegate::EndEditHint hint) which is also virtual, so you might want to try reimplementing that in your subclass. The closeEditor() documentation also suggests commitData(), which is also virtual. The Qt item views have a lot of similar methods, so don't assume that the first one you see is going to do exactly what you want/expect.
FYI, in case your not used to reimplementing virtual methods in a subclass, the fastest/easiest way to make sure your implementation is being called is to do something like:
class A : public QTableView {
void closeEditor ( QWidget * editor, QAbstractItemDelegate::EndEditHint hint ) {
qDebug("my closeEditor was called!");
// call the real implementation so that the base class continues to work properly
QTableView::closeEditor(editor, hint);
}
};
You could do this with edit(), editorDestroyed(), closeEditor(), and commitData() to see which ones are called when.

Related

Application GUI state saving in Qt

What is an optimal and an appropriate way to save the state of a Qt GUI so I get the same state I had back when I closed the application ?
By state I mean : current indexes (for combo box ...), color palette, widgets positions... right before closing the application
You can use the QSettings class.
Simple use of QSettings class (code inspired from Qt's documentation):
In the main-window of your application code member functions that saves and restore the settings:
void MainWindow::writeSettings()
{
QSettings settings("reaffer Soft", "reafferApp");
settings.beginGroup("MainWindow");
settings.setValue("size", size());
settings.setValue("pos", pos());
settings.endGroup();
}
void MainWindow::readSettings()
{
QSettings settings("reaffer Soft", "reafferApp");
settings.beginGroup("MainWindow");
resize(settings.value("size", QSize(400, 400)).toSize());
move(settings.value("pos", QPoint(200, 200)).toPoint());
settings.endGroup();
}
Call those 2 functions from the MainWindow constructor and from the closeEvent override, like this:
MainWindow::MainWindow()
{
// code from constructor
//...
readSettings();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
//optional check if the user really want to quit
// and/or if the user want to save settings
writeSettings();
event->accept();
}
The direct answer requires specific elaborated design for your code and not really a short Qt question or even the question specific to Qt. That is about C++ which is not the VM-based language that assists with serializing the state of program code to data. Having all objects serializable we can then attempt to apply certain C++/Qt classes/techniques.
This task is much easier to accomplish with languages like Java, though. And with C++/Qt you have to routinely make serialize-able / serialize / restore everything that is running in your code and still no guarantee that works as long as the context is not fully captured. This task is not easy for sure and makes sense only in specific application.
The most you can get directly from Qt is to save/restore QMainWindow and other independent widgets geometry (position/size):
saveGeometry
restoreGeometry
... and that solution is still somewhat incomplete or you may/not use QSettings for the storage.
I use QSettings for this. With routines similar to Zlatomir's.
For each window I have in the project I use a different section in QSettings and have readSettings() and writeSettings() in the source for each window.
Anything on the form that I want to persist I have to explicitly save and recall. In the case of a QComboBox it would be something like:
QSettings settings("Organisation", "MySoftware");
settings.beginGroup("WindowNumberTwo");
settings.setValue("ComboIndex", combobox->currentIndex());
// save more values here
// ...
settings.endGroup();
I don't know of a built in way to persist your window states - it has to be don't value by value.

Qt - signal for when QListWidget row is edited?

I am working in Qt4.7, and I have a QListWidget in my dialog. I have a QString that needs to match the current text in the row of this widget (the individual rows are editable). Looking at the signals associated with QListWidget, there seem to be signals for when a different index is selected but none for when the text of a the currently selected row changes. I thought currentTextChanged(QString) would do it, but it didn't. I also thought to try to connect each individual row to something, but QListWidgetItem doesn't have any built-in signals. Does anyone know of a way to do this? Thanks!
At first it seems like QListWidget::itemChanged is the way to go, but soon you run into a problem: the signal is sent for everything - inserts, changing colors, checking boxes, and anything else that "changes" the item! Predelnik pointed that out in his answer. Some people have tried to put in flags and filter everywhere by intercepting various signals to find out if editing was the actual event. It gets very messy.
There is also QAbstractItemModel::dataChanged , which would seem like a good solution. It even has a parameter "const QVector& lstRoles" so you could scan for Qt::EditRole and see if it was really edited. Alas, there's a catch - it gets called for everything just like QListWidget::itemChanged and unfortunately, for QListWidget anyway, the roles parameter is always empty when it's called (I tried it). So much for that idea...
Fortunately, there's still hope... This solution does the trick! :
http://falsinsoft.blogspot.com/2013/11/qlistwidget-and-item-edit-event.html
He uses QAbstractItemDelegate::closeEditor, but I prefer using QAbstractItemDelegate::commitData.
So make a connect like so...
connect(ui.pLstItems->itemDelegate(), &QAbstractItemDelegate::commitData, this, &MyWidget::OnLstItemsCommitData);
Then implement the slot like this...
void MyWidget::OnLstItemsCommitData(QWidget* pLineEdit)
{
QString strNewText = reinterpret_cast<QLineEdit*>(pLineEdit)->text();
int nRow = ui.pLstItems->currentRow();
// do whatever you need here....
}
Now you have a slot that gets called only when the list item's text has been edited!
I guess you need to look into the following signal:
void QListWidget::itemChanged(QListWidgetItem * item)
But be careful because it's being sent every time some property of item changed, not only text. I remember when we ran into the problem once when we changed item colors and got tons of false positive slots called because of that. If you need more fine tuning I guess it's better to write model/view classes yourself and not rely on QListWidget.

QFileDialog used as widget

My goal is: user can choose file (only *mp3) and after clicking twice on it it should play (so the QString to file should be send to play() function)
Firstly I started to work with QTreeView, but it has signal when the file is selected.
So I decided to create QFileDialog and used it as widget built-in into MainWindow.
The only problem that I have, that after double-click it disappears. It is possible to avoid it?
Should I work with some QDialog::finished() signal or, QDialog::done()?
First, you can get a double-click signal from QTreeView; it's:
void doubleClicked( const QModelIndex & index );
Second, if you really want to use the QFileDialog that way, first override closeEvent( QCloseEvent * event). Inside, if you want to close the dialog, do event->accept();, otherwise just do event->ignore();. Connect to QFileDialog::currentChanged( const QString & path ); to get the filename the user double-clicks. One last thing--be sure to create the QFileDialog on the heap (using new), not on the stack (a local), and call show() on it instead of exec().
Remember that you can supply it with a parent (this) and you won't need to delete it later.
connect(file_dialog, SIGNAL(finished(int)), file_dialog, SLOT(open()));
This seems to work fine. The geometry stays fixed and it remembers the last path allright..

How can I programmatically commit data from QTableWidget, which contain some items in editing state?

How can I autocommit data from QTableWidget, that is in editing state, when I fire some command?
Assume, that there is some grid and data in it (editable thorough delegate that fires QComboBox editor). So, one starting to select option in combo, but do not finish editing, then hit some button, that executes action, that uses data from that combo, but new choise is not committed yet :\
How can I programmatically finish editing in table?
I mean some not strict 'loop all items and finish editing' way, that I consider as bad and ugly.
OOPS: worked too much, so, haven't realised, that there could be only one pending editor at time. Question is still here.
There is a protected slot named "commitData" in the tableWidget. You can inherit from tableWidget, then add your own public method (or slot) and send a signal (or simply call commitData method) from there.
There is one problem. You'll need to provide the editor object, but tableWidget gives you no way to get the pointer you need.
If you're using your own createEditor method, you can save the pointer to the editor somewhere, where your method can get it. It's a hack, but it's the only way i know.
The current editor does not seem to be accessible from outside of the view, but its content is committed when the current model index changes. So a simple way to force a commit seems to be to call
table->setCurrentIndex (QModelIndex ())
plus restoring your previous current index afterwards if the widget is not discarded yet.
This is quite an old question but it still came up quite high on Google so just in case anyone else needs the answer QTableView has a protected method
void currentChanged(const QModelIndex &current, const QModelIndex &previous)
which causes the data to be commited and QTableWidget is built on QTableView so that should still work. I found this info on the Qt Forum.

Segmentation fault in Qt application framework

this generates a segmentation fault becuase of "QColor colorMap[9]";. If I remove colorMap the segmentation fault goes away. If I put it back. It comes back. If I do a clean all then build all, it goes away. If I increase its arraysize it comes back. On the other hand if I reduce it it doesnt come back. I tired adding this array to another project and
What could be happening. I am really curious to know. I have removed everything else in that class. This widget subclassed is used to promote a widget in a QMainWindow.
class LevelIndicator : public QWidget
{
public:
LevelIndicator(QWidget * parent);
void paintEvent(QPaintEvent * event );
float percent;
QColor colorMap[9];
int NUM_GRADS;
};
the error happens inside ui_mainwindow.h at one of these lines:
hpaFwdPwrLvl->setObjectName(QString::fromUtf8("hpaFwdPwrLvl"));
verticalLayout->addWidget(hpaFwdPwrLvl);
I know i am not providing much but I will give alink to the app. Im trying to see if anyone has a quick answer for this.
If I do a clean all then build all, it goes away.
This makes it sound as though your build system isn't recognizing a dependency and that a change to that class definition isn't triggering a rebuild of something that should be recompiled when the definition changes.
Make sure class LevelIndicator is defined in exactly one place (generally that would be a header file that gets included by whatever modules need to use a LevelIndicator object). Also make sure that any global/static instances of LevelIndicator objects are following the one definition rule.
Firstly it might not be QColor, that may simply be changing the memory layout enough that a buffer overrun somewhere else triggers a segfault - try a different size QColor ..[1] for example.
Can QColor be used as an array like this, does it have the correct default ctor?

Resources