[Solved] Basic QIODevice subclass in Qt4
-
QIODevice is a base class. It defines the interface.
If you look at the docs of QFile, "it's stated":http://doc.qt.nokia.com/latest/qfile.html#signals :
bq. Unlike other QIODevice implementations, such as QTcpSocket, QFile does not emit the aboutToClose(), bytesWritten(), or readyRead() signals. This implementation detail means that QFile is not suitable for reading and writing certain types of files, such as device files on Unix platforms.
qbuffer.cpp emits it on line 82.
qprocess.cpp emits it on line 980.
qwindowspipewriter.cpp emits it on line 163.
For all sockets, I did not check now.
-
[quote author="Volker" date="1300991199"]Just a short note: It may be handy to provide some custom signal encryptedBytesWritten() just like signals in "QSslSocket:: encryptedBytesWritten()":http://doc.qt.nokia.com/4.7/qsslsocket.html#encryptedBytesWritten. This counts the bytes that were actually written to the underlying device (it might differ from the bytes that went in!).[/quote]
Wouldn't that be overkill, because you already have access to the underlying QIODevice directly? If you're interested in what was written, couldn't simply connect to that IODevices' bytesWritten() signal?
-
[quote author="Andre" date="1301002233"]
Wouldn't that be overkill, because you already have access to the underlying QIODevice directly? If you're interested in what was written, couldn't simply connect to that IODevices' bytesWritten() signal?[/quote]Only if it's not a QFile!
bq. Unlike other QIODevice implementations, such as QTcpSocket, QFile does not emit the aboutToClose(), bytesWritten(), or readyRead() signals. This implementation detail means that QFile is not suitable for reading and writing certain types of files, such as device files on Unix platforms.
-
[quote author="Andre" date="1301002233"]
[quote author="Volker" date="1300991199"]Just a short note: It may be handy to provide some custom signal encryptedBytesWritten() just like signals in "QSslSocket:: encryptedBytesWritten()":http://doc.qt.nokia.com/4.7/qsslsocket.html#encryptedBytesWritten. This counts the bytes that were actually written to the underlying device (it might differ from the bytes that went in!).[/quote]Wouldn't that be overkill, because you already have access to the underlying QIODevice directly? If you're interested in what was written, couldn't simply connect to that IODevices' bytesWritten() signal?[/quote]
In this case yes, you're right. I had that QSslSocket in mind, but you do not have access to the "regular" TCP socket in that case.
-
There is a more enhanced eexample, also in the wiki now: "Simple Crypt IO Device":http://developer.qt.nokia.com/wiki/Simple_Crypt_IO_Device . It uses the "SimpleCrypt class":http://developer.qt.nokia.com/wiki/Simple_encryption to encrypt the data and stores it via a custom IO device in any other device.
-
Wow, Fantastic, Marvelous, Wonderful, Excellent!!
You guys Rock!
I've tried the classes out and great, I'm sure many will benefit from your brilliant contributions!I've added a couple modifications to your SimpleCryptDevice class.
SimpleCryptDevice.h
@
// ----- construction -----
/**- Constructor.
- Constructs a SimpleCryptDevice instance.
- The underlyingDevice needs to be set with setDevice.
- The crypt key can be set by setKey.
- @param parent parent object, see Qt documentation
/
SimpleCryptDevice(QObject parent=0);
// ----- methods ----
/** - Sets the underlyingDevice
/
void setDevice(QIODevice underlyingDevice) {m_underlyingDevice = underlyingDevice;}
/** - Returns the last error that occurred.
/
int lastError() const {return m_crypto.lastError();}
signals:
/* - This signal is emitted when SimpleCryptDevice writes a block of raw data to the underlying device.
/
void blockWritten();
@
SimpleCryptDevice.cpp
@
SimpleCryptDevice::SimpleCryptDevice(QObject parent)
{
}
int SimpleCryptDevice::writeBlock(const QByteArray& bytesToWrite)
{
//...
//..
//.
emit blockWritten();
return realBytesWritten;
}
return 0;
}
@
Justification of modification:
- blockWritten() signal
** to provide feedback to a QProgressBar.
*** I externally calculate how many blocks will be written dependent on the block size chosen - Bare constructor
** to connect the signals before I define the device. - lastError()
** to have access to the last error
Although the compiled code works fine, I would apreciate if you point out any error / malpractice I have done.
Thanks loads again!
-
There is a potiential danger, that you have not set the underlying device before you start using the device if you take it out of the constructor. Because of the guarantee what was there before your modification, there is no check for that. Other than that, I can think of no major issues.
-
That was exactly why the underlying device was part of the constructor. It does not make sense to reuse the SimpleCrypDevice with another base device. And also not without an underlying device.
The signal looks good. I will add it to gitorious and the wiki.
-
Aha ok,
Thanks for the warning.So I have restructured my code to connect the signal after getting the device parent pointer.
I have taken away the bare constructor and the setDevice method.I have maintained the lastError() addition
@ int lastError() const {return m_crypto.lastError();} @
to be able to access the error. As m_crypto, (SimpleCrypt object) is private, there is no other way of accessing the error from a simpleCryptDevice instance otherwise, right?