Getting value from QTableWidgetItem - c++

I want to set QTableWidgetItem's data as an image. imagePath may be different each time.
QTableWidgetItem *itemMedia = new QTableWidgetItem();
itemMedia->setTextAlignment(Qt::AlignCenter);
itemMedia->setData(Qt::DecorationRole, QPixmap(imagePath).scaled(width, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation));
m_table->setItem(0,0,itemMedia);
m_table->setItem(0,1,itemMedia);
m_table->setItem(1,0,itemMedia);
m_table->setItem(1,1,itemMedia);
I've created it nicely. Next, I want to get data with this:
connect(m_table, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(onItemClicked(QTableWidgetItem *)));
void MUCSharedMedia::onItemClicked(QTableWidgetItem *item)
{
qDebug()<<"DecorationRole: " <<item->data(Qt::DecorationRole).toString();
qDebug()<<"DisplayRole: " <<item->data(Qt::DisplayRole).toString();
}
Actually I want imagePath in one of this role , but I get this line in Application Console:
DecorationRole: ""
DisplayRole: ""
How to get value? Any suggestion?
EDITED:
I want to show image on each QTableWidgetItem after that I want to store image path of images which I've shown.

If you need to store QString actually, you need DisplayRole two times:
itemMedia->setData(Qt::DisplayRole, imagePath);
qDebug()<<"DisplayRole: " <<item->data(Qt::DisplayRole).toString();
EDIT: if you need to show image and get image file path I suggest you another way:
1) Set image like you did:
itemMedia->setData(Qt::DecorationRole, QPixmap(imagePath).scaled(width, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation));
2) Set image path using Qt::UserRole
itemMedia->setData(Qt::UserRole, imagePath);
When you need it:
qDebug()<<"File Path: " <<item->data(Qt::UserRole).toString();
But application will use image for displaying.

QTableWidgetItem::data() returns QVariant where you'll get the data with QVariant::value().
Alternatively, use QTableWidget::text().
http://doc.qt.io/qt-5/qtablewidgetitem.html

You store a QPixmap:
itemMedia->setData(Qt::DecorationRole, QPixmap(imagePath).scaled(width, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation));
but try to extract it as a QString:
qDebug()<<"DecorationRole: " <<item->data(Qt::DecorationRole).toString();
That will always give you a default-constructed (i.e. empty) QString.
You want to retrieve it as a QPixmap:
item->data(Qt::DecorationRole).value<QPixmap>()
(though there's little point sending that to a QDebug stream!)
There's a good chance you want the original, unscaled pixmap. In which case, you'll need to store that as well, perhaps in Qt::UserRole:
itemMedia->setData(Qt::UserRole, QPixmap(imagePath));
and change the retrieval to match.

Related

How to use a custom validation function for a QCompleter in a QComboBox

I have a string matching function to be used for searching for names that is more advanced than QString::contains() (e. g. when you search for "mueller", it will match "Müller").
I'd like to use this function to search inside a QComboBox. The default completion almost does what I need: If I do
combobox->setEditable(true);
combobox->setInsertPolicy(QComboBox::NoInsert);
combobox->completer()->setCompletionMode(QCompleter::PopupCompletion);
and type some text in the QComboBox's lineedit, the popup pops up, only showing entries starting what has been typed.
This is what I want, but I would like the QCompleter to evaluate matches using my search function rather than the QString::startsWith() that is apparently used here (and setting the mode to Qt::MatchContains is better but still not sufficient).
Is there any way to customize the completer's search function?
Thanks for all help!
I ended up using an own QCompleter and set it for the QComboBox's QLineEdit. The completer does not use the combobox's model, but an own one, which is filled with data everytime the entered text changes.
Can be done as follows:
m_matchingNames = new QStringListModel(this);
m_nameCompleter = new QCompleter(m_matchingNames, this);
m_nameCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
m_playersSelect->setEditable(true);
m_playersSelect->setInsertPolicy(QComboBox::NoInsert);
m_playersSelect->setCompleter(0);
m_playersSelect->lineEdit()->setCompleter(m_nameCompleter);
connect(m_playersSelect->lineEdit(), &QLineEdit::textEdited, this, &ScorePage::nameSearchChanged);
and
void ScorePage::nameSearchChanged(const QString &text)
{
QStringList possibleNames;
for (const QString &name : m_availableNames) {
if (checkMatch(name, text)) {
possibleNames << name;
}
}
m_matchingNames->setStringList(possibleNames);
}
Most probably not the most prerformant solution, but it works :-)
One then can also connect to QCompleter::activated() to process what has been chosen from the list and e. g. do a QComboBox::setCurrentIndex() or such.

How can I display the image as a thumbnail

I have a QTreeView to display the hard drives and Directories. also I have a QListView to display the images files as the following:
But I want to display the images as thumbnails, like the following:
My code:
mainWidget::mainWidget(QWidget *parent) : QWidget(parent), ui(new Ui::mainWidget){
ui->setupUi(this);
dirsModel = new QFileSystemModel;
filesModel = new QFileSystemModel;
dirsModel->setRootPath("");
ui->treeView->setModel(dirsModel);
ui->listView->setModel(filesModel);
dirsModel->setFilter(QDir::AllDirs | QDir::NoDotAndDotDot);
filesModel->setFilter(QDir::Files);
ui->treeView->hideColumn(1);
ui->treeView->hideColumn(2);
ui->treeView->hideColumn(3);
ui->treeView->header()->hide();
}
void mainWidget::on_treeView_clicked(const QModelIndex &index){
ui->listView->setRootIndex(filesModel->setRootPath(dirsModel->filePath(index)));
}
Unfortunately, I don't know what is the way of changing the image view from icon to thumbnail.
Depending on what you are after there are better ways to go about it I think, but here is an example based on a project of mine in python:
What you can do is subclass the QFileIconProvider:
ICON_SIZE = QSize(64,64)
accepted_types = (".jpg",".tiff",".png",".exr",".psd")
# this depends on the plugins you have installed,
# PSD and EXR requires external ones).
class IconProvider(QFileIconProvider):
def __init__(self) -> None:
super().__init__()
def icon(self, type: 'QFileIconProvider.IconType'):
fn = type.filePath()
if fn.endswith(accepted_types):
a = QPixmap(ICON_SIZE)
a.load(fn)
return QIcon(a)
else:
return super().icon(type)
Then on the Model you use:
self.fileSystemModel.setIconProvider(IconProvider)
Example on TreeView:
You should use special ViewMode:
ui->listView->setViewMode(QListView::IconMode);
But it will show you only icons(not whole images), so I think you should create for example QStandardItemModel (because QFileSystemModel is not very suitable) and set pixmap to this model with Qt::DecorationRole, but scale this images to smaller size. As you understand if there are many images in the dir, this process can be long.
As you can see, you should every time (every on_treeView_clicked) get new list of images in the directory, You can do this with:
QStringList QDir::entryList(const QStringList & nameFilters, Filters filters = NoFilter, SortFlags sort = NoSort) const
with special filters. When you have list of files, in the loop you can create pixmaps, scale it and set to model.
By default QListView::IconMode provide Free movement. If you want avoid this you should use:
ui->listView->setMovement(QListView::Static);

Qt: Linking my model data with a QListView

I'm writing my first Qt project (so I'm new to the environment) and I've got this project build using the MVC design pattern.
It's a pretty basic note manager/editor. I've got a class uiman ("Ui Manager") which takes care of my UI, and my function to open a notes database (which is just a list of text files to open)
void uiman::openDBDialog(){
QFileDialog dialog;
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setDirectory("/Users/myuserdir/Desktop");
dialog.setFilter(QDir::Files);
dialog.setWindowTitle("Open File");
dialog.setNameFilter("Textie Notes DB(*.db)");
dialog.exec();
QString pathDB = dialog.selectedFiles().first();
model = new notesModel();
model->setNotesDB(new QString(pathDB.toUtf8().constData()));
refreshAll();
}
so far, so good. I take the path of my database and give it to my model, which should now manage the rest.
Now, the refreshAll() function should take the list I opened up and show them in my QListView, but I can't parse the file and append items on the go using clear() and append() unlike the QListWidget. So, how do I approach building a vector (I suppose) of names from my file and feeding them to my QListView?
Sorry if I'm not being clear, but the official documentation hasn't been clear enough.
Edit: This is my model, nodesmodel, and here's the code.
notesModel::notesModel(QObject *parent) :
QFileSystemModel(parent)
{
QStringList noteList;
}
void notesModel::setNotesDB(QString *dbpath){
// open the notes database
databasepath = dbpath;
}
QFile* notesModel::getDB(){
if(this->dbFile == NULL)
this->dbFile = new QFile(databasepath- >toUtf8().constData());
return this->dbFile;
}
As you already noticed, you do not add/remove data from the viewer widget itself, this is done in the model.
You can set the model with the setModel() method.
If you want to show a simple QString list, then you can use:
QStringList strings;
strings << "String 1" << "String 2" << "String 3";
model = new QStringListModel(strings, parent);
view->setModel(model);
// model is managed by parent, and will be deleted when parent is deleted.
// If you create multiple models you might consider other memory management strategy
To read a text file and store its lines in a QStringList, see this answer.

Qt: save entire QScrollArea contents as an image

I am trying to save the contents of a QScrollArea as an image.
Currently, I am doing it this way...
QPixmap pixmap(ui->overview->rect().size());
ui->overview->render(&pixmap, QPoint(),QRegion(ui->overview->rect()));
QString saveFilename = QFileDialog::getSaveFileName(this, "Save as", "Choose a filename","PNG(*.png);; TIFF(*.tiff *.tif);; JPEG(*.jpg *.jpeg)");
if(!pixmap.save(saveFilename))
{
QMessageBox::warning(this, "Error","File could not be saved", QMessageBox::Ok);
}
But if the contents exceed one screen (and you need to scroll to see the entire image) and I save that,
the image only shows the part of the screen it's currently on.
How can I save the full contents of the scrollArea so that the image shows the entire thing, and not just a part of it?
QImage img(ui->scrollAreaWidgetContents->size(),QImage::Format::Format_ARGB32);
QPainter painter(&img);
ui->scrollAreaWidgetContents->render(&painter);
bool istrue = img.save("/file.jpg");

Add icon to status bar - Qt

I have an icon that is saved in a format:
//icon.h
extern const unsigned char icon[];
//icon.cpp
const unsigned char icon[]={0x17,0x3f,0x0c,....,0x10,0x06}
Now i want to add this icon to the status bar.
How do i do it?
Thank you.
First create a widget that loads the icon data, like a QLabel on which you set a QPixmap. What format is that image in? You will have to load it into your pixmap using one of the constructors, or you could try loading it with loadFromData().
Then add that widget to the status bar like so:
statusBar()->addWidget(yourIconWidget);
Have a look at statusBar(), addWidget() and addPermanentWidget().
An example of how to create the widget could be:
QPixmap *pixmap = new QPixmap;
// Note that here I don't specify the format to make it try to autodetect it,
// but you can specify this if you want to.
pixmap->loadFromData(icon, sizeof(icon) / sizeof(unsigned char));
QLabel *iconLbl = new QLabel;
iconLbl->setPixmap(pix);
statusBar()->addWidget(iconLbl);
Specifying the format, as I mentioned above, is elaborated upon here.