How to open a .jpg image using QListWidget? - c++

I am having some .jpg images in a folder which need to be displayed in QtListWidget. I am able to display the list of items in a particular folder in QtListWidget, but unable to open the item when i click it. I learned in tutorial one should use "connect" for doing it, i tried it but error is happening.
My code in .cpp file is as follows. Any help is most welcomed...
QDir myPath("/home/mit/Desktop/Ui_dev_mits_cars/visual_image");
myPath.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
myList = myPath.entryList();
ui->listWidget1->addItems(myList);

Right, so the issue is at least two-folded with your code:
connect(MyList,SIGNAL(doubleClicked(QListWidgetItem *)),this,SLOT(test(QListWidgetItem *)));
First of all, you are trying to use a QStringList value based object rather than pointer. Also, you should use the pointer pointing to the QListWidget instance.
Secondly, you are using the signal wrong. It is parameter is a QModelIndex as opposed to a QListWidgetItem. See the documentation for details:
void QAbstractItemView::doubleClicked(const QModelIndex & index) [signal]
This signal is emitted when a mouse button is double-clicked. The item the mouse was double-clicked on is specified by index. The signal is only emitted when the index is valid.
So, grab the model index and in your slot, get the data out of that model index either by using the internal pointer, or preferrably the data() method.

Related

QT: Searching through QTreeView/QFileSystemModel with a QDtring for a QModelIndex index

I'm working on a custom QDialog for the user to choose a directory on the filesystem. I'm using a QFIleSystemModel inside a QTreeView. Whenever the user selects an item in the QTreeView the directory is written to a QLineEdit. My problem is I would like to do the opposite of-sorts by expanding through the QTreeView nodes by taking the typed text and... well... obviously expanding the nodes if the text typed is an existing, absolute path.
I've searched for quite a few variations of my problem(although I know it's very loaded) and looked through a lot of the documentation of the classes but I can't find anything to really help me. I'm guessing I need to use QTreeView::expand(const QModelIndex) to expand them after finding but searching through the index is my biggest problem as of now. I'm open for any suggestions and any help is truly appreciated. Thank you in advanced and sorry for making such a wall of text.
searching through the index is my biggest problem as of now
And index is just a "pointer" to an item in the model. You can't search "through" it, because there is nothing "in" an index. It's just a pointer to exactly one item.
You should search through the model. The index(const QString & path) method does that for you. Given a path, it returns an index into the element at the end of the path. You can then iterate upwards to extend the items:
// ...because QModelIndex::operator= doesn't exist
QModelIndex & assign(QModelIndex & dst, const QModelIndex & src) {
dst.~QModelIndex();
new (&dst) QModelIndex(src);
return dst;
}
void extend(const QString & path, QTreeView * view) {
auto fs = qobject_cast<QFileSystemModel*>(view->model());
if (!fs) return;
auto idx = fs->index(path);
// ascend up from the child item and expand items in the tree
while (idx.isValid()) {
view->expand(idx);
assign(idx, idx.parent());
}
}
You can use this method with the last item removed from the path as well, since - presumably - the last item might not be valid, and thus fs->index might fail.
Have you check here?
[Model/View Programming][Insert and delete rows in QTreeView]
http://doc.qt.io/qt-4.8/model-view-programming.html
QTreeView & QAbstractItemModel & insertRow
As base design principle, View only render the data.You should not expect to modify the data via View directly.

QT QIcon properties for custom widget in designer

I have been working for a little while now on creating a QT custom designer widget for GUI menus. The idea being that you simply drag it into the designer, select the number of frames you'd like, how many buttons per frame, etc. and it generates and sizes everything for you.
The way the widget is structured there are properties to configure each button for the frame you are in. For example, you would use the button0Text field to enter text under Button0 while editing in frame 0, then use it again to edit Button0 which is in frame 1. Both buttons would retain the individual changes for each frame.
The Problem
Normally when I switch frames all of my properties are updated to reflect the status of the frame. The exception being QIcon. The correct icon is retained in the actual graphical representation and builds correctly, however the file path in the property list is always of the last edited for that property. I think this will be extremely confusing to an end user and I have found no way to fix it. So for example, if I set text and icons in frame 0 then switch to frame 1 the text in the property list will update to reflect the state of frame 1 but the icon path names will still show my last edit in frame 0 and not the actual icon in frame 1.
I have tried things as simple as:
setProperty("button0Icon", getButton0Icon());
That code works on properties like text, but not for the icon. I try executing it immediately after changing frames.
I have also tried:
#ifndef Q_WS_QWS
QDesignerFormWindowInterface *form = QDesignerFormWindowInterface::findFormWindow(this);
if(form){
QDesignerFormEditorInterface *editor = form->core();
QExtensionManager *manager = editor->extensionManager();
QDesignerPropertySheetExtension *sheet;
sheet = qt_extension<QDesignerPropertySheetExtension*>(manager, this);
int propertyIndex = sheet->indexOf("button0Icon");
sheet->setChanged(propertyIndex, true);
sheet->setProperty(propertyIndex, getButton0Icon());
}
#endif
And:
int propertyIndex = this->metaObject()->indexOfProperty("button0Icon");
QMetaProperty property = this->metaObject()->property(propertyIndex);
property.write(this, QIcon());
Nothing seems to update the property list in the designer.
I have all properties, including all QIcon properties properly declared in the header file with Q_PROPERTY and assigned getter and setter functions.
To be clear, the icon values are indeed retained through each frame when compiled. So it is functioning, just unclear for most users.
If anyone has any experience with this or any ideas please let me know. Thanks.
I have discovered that QIcon does not store file names/paths. The file names are only used for the creation of the QIcon. I think this is most likely the reason I do not get any feedback in the Property Browser for my QIcon properties.
Instead I have chosen to hide this property in the designer and add three new ones. Three QUrl properties, each of which is used to supply an image file. I use three because I want to construct a QIcon that contains Modes/States for normal, disabled, and pressed operations.
I take each of these QUrls and save them in QStringLists behind the scenes so their values are stored. I then construct my QIcon using the file names provided from the QUrls.
I would much prefer to be using the native QIcon in the designer for this, any thoughts or feedback are appreciated.

Is there any way to save the order of columns?

I currently have a tableview attached to a class that is derived from QSortFilterProxyModel. Now I wanted to know if there is any way by which I can store the order of columns since the users tend to move the columns back and forth. Also is there any signal that is emitted when a user changes the order of the columns.I search this but I cannot find anything that might tel me when a column is moved around and how i can save the tablew columns orders.
Any suggetsions would be appreciated
You need to obtain a QHeaderView object using QTableView::horizontalHeader. You can use QHeaderView::saveState and QHeaderView::restoreState to save state of columns. You can use QHeaderView::sectionMoved signal to detect column moving.
The reason why you cannot find the relevant signal in the documentation because you are checking an about 6-7 years old documentation. That is, it is Qt 4.1. The signal in question was added to Qt in version 4.6.
QAbstractItemModel has this signal recently:
void QAbstractItemModel::columnsMoved(const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationColumn) [signal]
This signal is emitted after columns have been moved within the model. The items between sourceStart and sourceEnd inclusive, under the given sourceParent item have been moved to destinationParent starting at the column destinationColumn.
Note: Components connected to this signal use it to adapt to changes in the model's dimensions. It can only be emitted by the QAbstractItemModel implementation, and cannot be explicitly emitted in subclass code.
This function was introduced in QtCore 4.6.
This looks like what you are looking for. See the documentation for further details:
http://qt-project.org/doc/qt-5.0/qtcore/qabstractitemmodel.html#columnsMoved
Also, do not forget the fact that you will actually need QAbstractTableModel in the end of the day.
If you really wish, you could catch this signal as well:
void QHeaderView::sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) [signal]
This signal is emitted when a section is moved. The section's logical index is specified by logicalIndex, the old index by oldVisualIndex, and the new index position by newVisualIndex.
Please refer to the documentation for further details:
http://qt-project.org/doc/qt-5.1/qtwidgets/qheaderview.html#sectionMoved

Undo for individual cells of QTableWidget in Qt?

I have a QTableWidget in my Main Window class.
I am unable to find a functionality which will undo the text change for the specified cell.
What I want to do is:
void myCellUndoFunc(int row, int col)
{
table->item(row, col)->undo(); //table is my QTableWidget
}
The problem is that there is no such undo().
So my question is, can there be a workaround for this problem using maybe some foo-doo combination of SIGNAL's & SLOT's?
Thanks!
PS: Please do not suggest to use Model/View framework because I have used QTableWidget extensively in my application. Sorry for the same.
Maybe you should use the
void QTableWidgetItem::setData ( int role, const QVariant & value ) [virtual]
using the Qt::UserRole you are able to specify the last value. In your method u can access the previously set value with the data()-Method. The only thing you have to do is always keep the old value up-to-date.
Before you set the new value of the QTableWidgetItem
tw->setData(Qt::UserRole, tw->text())
and on undo u could than retrieve the data with
tw->setText(tw->data(Qt::UserRole).toString())
where "tw" is the current QTableWidgetItem using the contextmenu-event, the clicked-event or whatever u want. You could also subclass the QTableWidgetItem and handle this whole thing internally in your class, creating an undo()-method, storing the old value, etc.

Qt QTreeView not updating when adding to model

The source code relating to this question is available on my public Git repository on BitBucket.
I'm trying to dynamically add some items to a QTreeView model using the following code in mainwindow.cpp:
if(dlg->exec() == QDialog::Accepted) {
QList<QVariant> qList;
qList << item.name << "1111 0000" << "0x00";
HidDescriptorTreeItem *item1 = new HidDescriptorTreeItem(qList, hidDescriptorTreeModel->root());
hidDescriptorTreeModel->root()->appendChild(item1);
}
This works when run from within my MainWindow constructor, just after ui->setupUi(this), but I need this to run from within an event filter, but the same code doesn't get the QTreeView updating. When I set a breakpoint at mainwindow.cpp:70 and step through the next few lines, I can see the data is being added to the Model, but I need the QTreeView to refresh.
I understand this is done by emitting dataChanged(), but not really sure how to do this. The signal signature for the dataChanged signal looks as follows:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
so I need to come up with topLeft and bottomRight QModelIndex instances. How do I build/obtain these from item1 in the above snippet?
Also, where does beginInsertRows() and endInsertRows() come into view with this, should I be calling these functions?
From QAbstractItemModel documentation:
void QAbstractItemModel::beginInsertRows ( const QModelIndex & parent, int first, int last ) [protected]
Begins a row insertion operation.
When reimplementing insertRows() in a subclass, you must call this function before inserting data into the model's underlying data store.
The parent index corresponds to the parent into which the new rows are inserted; first and last are the row numbers that the new rows will have after they have been inserted.
The other protected functions say similar things.
And insertRows() says:
If you implement your own model, you can reimplement this function if
you want to support insertions. Alternatively, you can provide your
own API for altering the data. In either case, you will need to call
beginInsertRows() and endInsertRows() to notify other components that
the model has changed.
Take a look to QAbstractItemModel protected functions and signals
Views connect to those signals to know when model data changes and rearrange data inside. The functions emit the signals internally to make it easy for you to warn the view when it has happenned. But signals can only be emitted by abstract class.
Components connected to this signal use it to adapt to changes in the
model's dimensions. It can only be emitted by the QAbstractItemModel
implementation, and cannot be explicitly emitted in subclass code.
So you will have to stick to the methods.
Edit in answer to your comment:
Indeed, Items should have a reference to model and tell it about changes, check theses lines from QStandardItem:
void QStandardItem::emitDataChanged()
void QStandardItem::removeRows(int row, int count)
( Note, how, in second, it calls model's rowsAboutToBeRemoved() and rowsRemoved() )
Maybe you should try to use QStandardItem and QStandardItemModel.
Either direct or subclassing. It will hide a lot of ugly stuff.
There's also a less proper but much easier way to achieve this - emit layoutChanged() instead of dataChanged(). More info - https://stackoverflow.com/a/41536459/635693