Howto display QPixmap and Text?
Hello,
I have a sql database with the following tables:
table content
id integer, content text
table images
id integer, shortname text, data blob
The following snippet is from content.conten:
Code:
This is an example text with an image :img1. The text is very senseless. Here another image :img2.
I have to replace the ":img(id)" keywords by the correct image.
I generate a QPixmap of each image by QPixmap::loadFromData(const QByteArray&). To show them in a QLabel inline the text module doesn't seem possible. I see no way to create a QLabel for each text module and each image. (IMHO would it be very bad design)
Maybe QTextBrowser could be the right GUI element but sometimes I have to replace only the images on user input. Do I use a QTextDocument than?
What other possibilities I have to display the information to the user?
Bye
Re: Howto display QPixmap and Text?
QLabel is fine - you can use the <img> tag to add images to your text.
Re: Howto display QPixmap and Text?
I know that QLabel supports rich text. But I have a QPixmap object and I don't know how to insert it inline a QLabel.
Something like the following won't work:
Code:
pixmap.loadFromData(_data);
label->setText("some senseless text with an image <img src="+pixmap+"/>");
Sure it is possible to get the image from the database, create a QPixmap object, save it in a temporary file and include this e.g. <img src="temp.png" />. But isn't there an easier way?
Re: Howto display QPixmap and Text?
There are many ways :) You can try embedding the data directly in the URL although I'm not sure if Qt Rich Text supports it or you can use the resource system or a similar system based on QAbstractFileEngine.
Re: Howto display QPixmap and Text?
Embedding in the URL isn't supported by Qt's Rich Text.
I don't want to use the resource system because i have to export the images from database into regular files.
Is subclassing QAbstractFileEngine really necessary?
Re: Howto display QPixmap and Text?
Quote:
Originally Posted by
segi
Is subclassing QAbstractFileEngine really necessary?
No, you can register the data with the resource system dynamically through QResource::registerResource(). Of course you need to properly feed the data.
Re: Howto display QPixmap and Text?
I read much about QResource now. That isn't what I really want.
To subclass QAbstractFileEngine seems the best solution. But IHMO it's a lot of work and the documentation of it is not as good as of the other Qt classes.
I have a some code which not working well:
Code:
// sqlfileengine.h
#ifndef SQLFILEENGINE_H
#define SQLFILEENGINE_H
#include <QAbstractFileEngine>
#include <QAbstractFileEngineHandler>
class SqlFileEngine;
{
public:
SqlFileEngineHandler();
};
{
public:
SqlFileEngine();
explicit SqlFileEngine(const QString& file);
virtual QString fileName
(FileName
file=DefaultName
) const;
virtual void setFileName(const QString& file);
qint64 read(char* data, qint64 maxlen);
bool atEnd () const;
qint64 size() const;
qint64 pos() const;
private:
void init();
qint64 _pos;
};
#endif /* end of SQLFILEENGINE_H */
// sqlfileengine.cpp
#include "sqlfileengine.h"
#include <QByteArray>
#include <QDebug>
#include <QString>
#include <QStringList>
#include <QSqlQuery>
#include <QVariant>
// SqlFileEngineHandler
SqlFileEngineHandler::SqlFileEngineHandler()
{
}
{
return filename.toLower().startsWith("sql:") ? new SqlFileEngine(filename) : 0;
}
// SqlFileEngine
SqlFileEngine::SqlFileEngine()
{
}
SqlFileEngine::SqlFileEngine(const QString& file)
: _pos(0)
{
qDebug() << "SqlFileEngine ctor";
setFileName(file);
init();
}
QString SqlFileEngine
::fileName(FileName
file) const {
Q_UNUSED(file);
return _filename;
}
void SqlFileEngine::setFileName(const QString& file)
{
_filename=file.section(':', 1);
qDebug() << "SqlFileEngine::setFileName() " << _filename;
}
bool SqlFileEngine
::open(QIODevice::OpenMode openMode
) {
Q_UNUSED(openMode);
qDebug() << "SqlFileEngine::open() ";
return true;
}
qint64 SqlFileEngine::read(char* data, qint64 maxlen)
{
qDebug() << "SqlFileEngine::read(" << data << "," << maxlen << ")";
if(atEnd())
return 0;
if(!_data.isEmpty())
{
qstrcpy(data, curData.data());
qDebug() << data;
_pos+=curData.size();
qDebug() << _pos;
}
return 0;
}
bool SqlFileEngine::atEnd() const
{
return (_pos>=size());
}
qint64 SqlFileEngine::size() const
{
return _data.size();
}
qint64 SqlFileEngine::pos() const
{
return _pos;
}
void SqlFileEngine::init()
{
// filename == table/col/id
query.prepare("SELECT "+strl.at(1)+" FROM "+strl.at(0)+" WHERE id=:id");
query.bindValue(":table", strl.at(0));
query.bindValue(":col", strl.at(1));
query.bindValue(":id", strl.at(2));
qDebug() << "SELECT " << strl.at(1) << " FROM " << strl.at(0) << " WHERE id=" << strl.at(2);
if(query.exec())
{
while(query.next())
{
qDebug() << query.value(0).toByteArray();
_data=query.value(0).toByteArray();
}
}
}
// main.cpp
#include "sqlfileengine.h"
#include <QApplication>
#include <QLabel>
#include <QSqlDatabase>
int main(int argc, char* argv[])
{
db.setDatabaseName("/home/segi/user.db");
if(!db.open())
{
qWarning("Couldn't open database.");
return -1;
}
SqlFileEngineHandler engine;
label.setText("<img src=\"sql:images/image/1\" />");
label.show();
return app.exec();
}
I only get something like that:
Code:
SqlFileEngine::setFileName() images/image/1
SELECT "image" FROM "images" WHERE id="1"
SqlFileEngine::open()
SqlFileEngine::read( ¶ôß3·iøìº¿ñs·▒ , 1 )
SqlFileEngine::read( PNG
▒
, 16384 )
SqlFileEngine::read( ¶ôß3·iøìº¿ñs·▒ , 1 )
SqlFileEngine::read( PNG
▒
, 16384 )
SqlFileEngine::read( ¶ôß3·iøìº¿ñs·▒8 , 1 )
SqlFileEngine::read( PNG
▒
, 16384 )
SqlFileEngine::read( ¶ôß3·iøìº¿ñs·▒8 , 1 )
SqlFileEngine::read( PNG
▒
, 16384 )
...
Is there another method to tell that the end of file is reached than return 0 in SqlFileEngine::read?
What do I wrong?
Where can I find better/more information about subclassing QAbstractFileEngine? (What have i to reimplement and so on.)
Bye
Re: Howto display QPixmap and Text?
1 Attachment(s)
Re: Howto display QPixmap and Text?
By the way, here is a quick implementation.
Re: Howto display QPixmap and Text?
Thank you very much.
I get it working. But why the read method is called so much times?
I add a debug message to your MemFileHandler::read method and get the following output:
Code:
Starting /home/segi/tmp/memfilehandler/memfilehandler...
read: return 2844 counter 0
read: return 2844 counter 1
read: return 2844 counter 2
...
read: return 2844 counter 27
Can I avoid these additional calls?
Sadly there are a lot of errors at runtime:
I tried big images: e.g. /usr/share/wallpapers/default-1600x1200.png
Code:
Starting /home/segi/tmp/memfilehandler/memfilehandler...
read: return 16384 counter 0
read: return 16384 counter 1
read: return 16384 counter 2
...
read: return 16384 counter 27
read: return 53 counter 28
read: return 16384 counter 29
libpng error: IDAT: CRC error
What can I do to avoid this error?
On jpeg files I get:
Code:
Starting /home/segi/tmp/memfilehandler/memfilehandler...
read: return 378 counter 0
read: return 378 counter 1
Not a JPEG file: starts with 0xff 0xd9
I created a new jpg with gimp (100x100px only a white background).
qDebug() << QImageReader::supportedImageFormats():
Code:
Starting /home/sebastian/tmp/memfilehandler/memfilehandler...
("BW", "EPS", "EPSF", "EPSI", "EXR", "PCX", "PSD", "RGB", "RGBA", "SGI", "TGA", "XCF",
"bmp", "bw", "dds", "eps", "epsf", "epsi", "exr", "gif", "ico", "jp2", "jpeg", "jpg",
"mng", "pbm", "pcx", "pgm", "png", "ppm", "psd", "rgb", "rgba", "sgi", "svg",
"tga", "tif", "tiff", "xbm", "xcf", "xpm", "xv")
What's the problem?
Bye
Re: Howto display QPixmap and Text?
Quote:
Originally Posted by
segi
T
I tried big images: e.g. /usr/share/wallpapers/default-1600x1200.png
Code:
...
libpng error: IDAT: CRC error
What can I do to avoid this error?
Sorry, my fault. I just copied and modified your MemFileHandler::read() method.
I add and the error on big files is gone.
But why is this method called so often?
Why doesn't work jpg files?
Bye
Re: Howto display QPixmap and Text?
What does QImageReader::supportedImageFormats() have to do with this?
About the handler - it's probably buggy (although I can't see the bug) or incomplete. You'd have to reimplement every method from the interface and see which methods get called.
Re: Howto display QPixmap and Text?
Quote:
Originally Posted by
wysota
What does QImageReader::supportedImageFormats() have to do with this?
I thought the jpeg error would reasoned by a missing library or something like that.
Bye
Re: Howto display QPixmap and Text?
I now reimplement QAbstractFileEngine::isSequential() because it's called very often in the following methods:
Code:
somewhere in /usr/lib/kde4/plugins/imageformats/kimg_eps.so
If QAbstractFileEngine::isSequential() returns false QAbstractFileEngine::seek() is calling and the file will read once again. My isSequential() returns always true. (Now isSequential() is calling over 30 times but IHMO it's ok.)
wysota: Thank you for your efforts.
I try to solve the JPEG problem in another thread.
Bye
Re: Howto display QPixmap and Text?
But the device is not sequential...
Re: Howto display QPixmap and Text?
Mh, I thought sequential means: "ABCDEFGH" and reading follows in the same order.
I read the data from the sql table into a QByteArray. Isn't a QByteArray sequential in RAM?
(I'm not a professional programmer. I don't really know how a QByteArray is stored in RAM.)
This little change solves all my problems:
Big files could be read in and jpg files are also read correctly.
But I want to do it in the right way.
I can't find another possibility to stop countless recalls of QAbstractFileEngine::read.
Maybe QAbstractFileEngine::seek would be right. But I don't know what to change.
Bye
Re: Howto display QPixmap and Text?
Quote:
Originally Posted by
segi
Mh, I thought sequential means: "ABCDEFGH" and reading follows in the same order.
Sequential means you don't know how much data is available in the device and that you can only go "forward" with processing the data and never look back. In other words a sequential device is a device where implementing size() and seek() is not possible.
An opposite to sequential is "random access". QByteArray is a random-access (index based) container.
My implementation of seek() is correct, the problem is elsewhere.
1 Attachment(s)
Re: Howto display QPixmap and Text?
Here is a corrected implementation - I wasn't updating position after a read attempt.
Re: Howto display QPixmap and Text?
Thank you very much. It works like expected. (and isSequential() returns false now)
The main problem was that i have testing with your little application and don't update the file position, too. I already noticed this a few posts above and changed it only in my app. Sorry for any inconvenience.
A last little question....
The application output:
Code:
/home/segi/tmp/IMG_9066.JPG
Open ok
RAW: 2188490
File read
virtual qint64 MemFileHandler::read(char*, qint64) 0 2188490
READ: 2188490
MEM: 2188490
virtual qint64 MemFileHandler::read(char*, qint64) 0 16384
READ: 16384
virtual bool MemFileHandler::seek(qint64) 0
virtual qint64 MemFileHandler::read(char*, qint64) 0 16384
READ: 16384
virtual bool MemFileHandler::seek(qint64) 0
virtual bool MemFileHandler::seek(qint64) 16384
virtual qint64 MemFileHandler::read(char*, qint64) 16384
READ: 16384
virtual qint64 MemFileHandler::read(char*, qint64) 32768 16384
READ: 16384
virtual qint64 MemFileHandler::read(char*, qint64) 49152 16384
Why does Qt call this methods a few times before reading the real data?
Code:
virtual bool MemFileHandler::seek(qint64) 0
virtual qint64 MemFileHandler::read(char*, qint64) 0 16384
Is it possible that the QImageIOHandler wants to find out which image format the file is of?
Bye
Re: Howto display QPixmap and Text?
Yes, that's possible. But that's just a guess. Is it important for you in any way? You can probably force the device to be sequential to omit that, if you want. But I wouldn't do that.
Re: Howto display QPixmap and Text?
It's not important for my app. I don't want to change this behaviour.
I only want to know what happens.