Results 1 to 4 of 4

Thread: Writing custom QIODevice with 2 channels

  1. #1
    Join Date
    Aug 2017
    Posts
    2
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Question Writing custom QIODevice with 2 channels

    I am trying to implement custom QIODevice.
    I have detector which will be using 2 tcp sockets, one for sending commands and receiving responses, the other one just for reading data.
    How should I do it? I tried to create my class, derive it from QIODevice and implement pure virtual methods, but I faced some dificulties.

    I have the following piece of code:
    Qt Code:
    1. class Detector : public QIODevice {
    2. Q_OBJECT
    3. Q_DISABLE_COPY(MasterDevice)
    4.  
    5. public:
    6. enum CHANNEL_TYPE {
    7. DataChannel,
    8. ControlChannel
    9. };
    10.  
    11. private:
    12. QTcpSocket *controlDevice;
    13. QTcpSocket *dataDevice;
    14.  
    15. QHostAddress hostAddress;
    16.  
    17. quint16 dataPort;
    18. quint16 controlPort;
    19.  
    20. public:
    21. explicit Detector(QObject *parent, QHostAddress hostAddress, quint16 dataPort, quint16 controlPort)
    22. : QIODevice(parent)
    23. , hostAddress(hostAddress)
    24. , dataPort(dataPort)
    25. , controlPort(controlPort)
    26. {
    27. controlDevice = new QTcpSocket(this);
    28. connect(controlDevice, SIGNAL(readyRead()),this, SLOT(controlChannelReadReady()));
    29.  
    30. dataDevice = new QTcpSocket(this);
    31. connect(dataDevice, SIGNAL(readyRead()),this, SLOT(dataChannelReadReady()));
    32. }
    33.  
    34. virtual ~Detector() {}
    35.  
    36. bool open(OpenMode mode) override {
    37. QIODevice::open(mode);
    38.  
    39. controlDevice->connectToHost(hostAddress, controlPort, QTcpSocket::ReadWrite);
    40. dataDevice->connectToHost(hostAddress, dataPort, QTcpSocket::ReadOnly);
    41. }
    42.  
    43. qint64 readData(char *data, qint64 maxSize) override {
    44. QTcpSocket *socket;
    45.  
    46. switch ( currentReadChannel() ) {
    47. case DataChannel:
    48. socket = dataDevice;
    49. break;
    50. case ControlChannel:
    51. socket = controlDevice;
    52. break;
    53. default:
    54. return -1;
    55. break;
    56. }
    57.  
    58. return socket->read(data, maxSize);
    59. }
    60.  
    61. qint64 writeData(const char * data, qint64 maxSize) override {
    62. QTcpSocket *socket;
    63.  
    64. switch ( currentWriteChannel() ) {
    65. case DataChannel:
    66. socket = dataDevice;
    67. break;
    68. case ControlChannel:
    69. socket = controlDevice;
    70. break;
    71. default:
    72. return -1;
    73. break;
    74. }
    75.  
    76. return socket->write(data, maxSize);
    77. }
    78.  
    79. private slots:
    80. void controlChannelReadReady() {
    81. emit channelReadyRead(ControlChannel);
    82. }
    83.  
    84. void dataChannelReadReady() {
    85. emit channelReadyRead(DataChannel);
    86. }
    87. };
    To copy to clipboard, switch view to plain text mode 

    So basically my question is, how do I handle those channels, because for example from qt documentation I have this

    Qt Code:
    1. bool QIODevice::open(OpenMode mode)
    To copy to clipboard, switch view to plain text mode 

    Opens the device and sets its OpenMode to mode. Returns true if successful; otherwise returns false. This function should be called from any reimplementations of open() or other functions that open the device.
    So I have to invoke it from my overrided Open() method, but I looked at the implementation of this method and I saw that it is setting the number of channels to 1. How can I change this number?
    What for are those buffers that I am inheriting from QIODevice, how should I use them?
    Am I missing the point of creating custom QIODevice? If so, please explain it to me.
    Last edited by notfound404; 15th August 2017 at 17:55.

  2. #2
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Writing custom QIODevice with 2 channels

    Umm...
    Based on your code, there is no need to sublcass QIODevice, since you are doing nothing that the current QTcpSockets are not doing (QTcpSocket is a QIODevice).
    You detector class can be a simple QObject, which basically managers the the reading and writing to your two sockets (which is basically what your code appears to be trying to do).
    Line 37 in your code simply is not needed and is doing nothing of value.
    This way you don't have to implement the virtuals of QIOdevice and you can mold your API as you need it.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  3. #3
    Join Date
    Aug 2017
    Posts
    2
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: Writing custom QIODevice with 2 channels

    First of all thank you for your reply. Much appreciated.

    Quote Originally Posted by high_flyer View Post
    Based on your code, there is no need to subcass QIODevice, since you are doing nothing that the current QTcpSockets are not doing (QTcpSocket is a QIODevice). You detector class can be a simple QObject...
    I agree that looking at my code there is no need for that, but I do want to extend my custom object, so that I will be able to take advantage of many other funcionalities of QIODevice, like for example being able to use QDataStream, which in constructor takes QIODevice. Moreover I would like to make my application very easy to reuse, by just replacing my custom QIODevice object to any other QIODevice object when it would be necessary.

    Quote Originally Posted by high_flyer View Post
    Line 37 in your code simply is not needed and is doing nothing of value.
    Yes, for now I am not using it, however it is setting some variables (Readonly / Writeonly) which I can check later on, in for example read / write methods to made them work corectly.

    And one more thing, why QT made such a beautiful class as QIODevice with support for multichannel communication when as far as I know no other QT object that is inheriting from it is using those channels?
    Last edited by notfound404; 16th August 2017 at 09:27.

  4. #4
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Writing custom QIODevice with 2 channels

    I agree that looking at my code there is no need for that, but I do want to extend my custom object, so that I will be able to take advantage of many other funcionalities of QIODevice, like for example being able to use QDataStream, which in constructor takes QIODevice. Moreover I would like to make my application very easy to reuse, by just replacing my custom QIODevice object to any other QIODevice object when it would be necessary.
    Again, you CAN take advantage of these features by calling them on your QTcpSocket.

    Yes, for now I am not using it, however it is setting some variables (Readonly / Writeonly) which I can check later on, in for example read / write methods to made them work corectly.

    And one more thing, why QT made such a beautiful class as QIODevice with support for multichannel communication when as far as I know no other QT object that is inheriting from it is using those channels?
    Its sound to me you do not fully understand what subclassing is used for.
    Qt offers QIODevice for people to be able to write new QIODevices and to have an "interface" class to all QIODevices that are already implemented by Qt, this is what OOP is all about.
    That means if you have a new type of hardware that needs different implementation of writing, reading etc, then you can implement it in a way that will conform to QIODevice and allow you to use it with other Qt QIODevice consumer classes.
    This is however NOT what you are doing.
    You are fully content with using the functionality offered by QTcpSocket. (Based on the posted code).
    You don't need a new low level implementation of the socket, you simply have a case where you need to coordinate between two sockets - that is NOT a new device, that is simply a manager class.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  5. The following user says thank you to high_flyer for this useful post:

    notfound404 (16th August 2017)

Similar Threads

  1. BLE Writing to Custom Characteristic
    By GeorgeIoak in forum Qt Programming
    Replies: 1
    Last Post: 2nd March 2017, 17:39
  2. Phonon - Custom QIODevice to support encrypted files
    By hunsrus in forum Qt Programming
    Replies: 3
    Last Post: 27th November 2012, 12:40
  3. QImageReader with custom QIODevice implementation
    By psih128 in forum Qt Programming
    Replies: 0
    Last Post: 10th August 2011, 04:39
  4. Haw many channels does a QPixmap have?
    By ricardo in forum Qt Programming
    Replies: 1
    Last Post: 19th July 2009, 17:39
  5. Replies: 1
    Last Post: 26th January 2007, 08:10

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.