Results 1 to 7 of 7

Thread: template to retrieve QIODevice subclass

  1. #1
    Join Date
    Jun 2010
    Posts
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Question template to retrieve QIODevice subclass

    Hello everybody,

    I am trying to develop a class which has two QIODevice * members
    and forwards data from the input device to the output device.
    My problem is that my devices are:
    - a SerialIODevice * (derived from QextSerialPort)
    - a SslIODevice * (derived from QSslSocket)
    - other derived classes to come

    when I call open, getChar, write, ... members,
    the members of QIODevice are called instead of the members of the derived
    classes.
    I tried to perform qobject_cast based tests in my code and it works.
    However the code becomes very compliated. Now I am trying to develop
    a template function which will perform the casting work and return
    a pointer to the derived class. As it is the first time I develop template
    functions, I have compilation errors I don'manage to solve even after
    a lot of googleing. Errors are related to unfound prototype where I use
    my template function.

    Below are relevant parts of my code. Thanks in advance for helping me.

    Regards.

    .h file:
    Qt Code:
    1. #ifndef MY_CLASS_H
    2. #define MY_CLASS_H
    3.  
    4. #include <QObject>
    5. #include <QThread>
    6. #include <QIODevice>
    7.  
    8. class MyClass : public QThread
    9. {
    10. Q_OBJECT
    11.  
    12. public:
    13.  
    14. explicit MyClass(QIODevice* inputDevice = 0, QObject *parent = 0);
    15. ~MyClass();
    16.  
    17. some members ...
    18.  
    19. private:
    20.  
    21. template <class T>
    22. T* device_cast(QIODevice* device);
    23.  
    24. QIODevice* m_pInputDevice;
    25. QIODevice* m_pForwardDevice;
    26.  
    27. some other members ...
    28.  
    29. };
    30.  
    31. #endif // MY_CLASS_H
    To copy to clipboard, switch view to plain text mode 

    .cpp file:
    Qt Code:
    1. #include "MyClass.h"
    2. #include <SerialIODevice.h>
    3. //#include <SslIODevice.h>
    4.  
    5. MyClass::MyClass(QIODevice* inputDevice, QObject *parent) :
    6. QThread(parent), m_pInputDevice(inputDevice), m_pForwardDevice(NULL), m_bForwardData(false)
    7. {
    8. }
    9.  
    10. MyClass::~MyClass()
    11. {
    12. if(m_pInputDevice && device_cast(m_pInputDevice)->isOpen())
    13. device_cast(m_pInputDevice)->close();
    14.  
    15. if(m_pForwardDevice && device_cast(m_pForwardDevice)->isOpen())
    16. device_cast(m_pForwardDevice)->close();
    17. }
    18.  
    19. // use case example
    20. void MyClass::sendData(quint8 id, QByteArray data)
    21. {
    22. if (!m_pInputDevice)
    23. {
    24. emit error("Input device not set!");
    25. return;
    26. }
    27.  
    28. if (!device_cast(m_pInputDevice)->isOpen())
    29. {
    30. emit error("Input device is not open");
    31. return;
    32. }
    33.  
    34. if (device_cast(m_pInputDevice)->openMode() == QIODevice::ReadOnly)
    35. {
    36. emit error("Input device is in read only mode!");
    37. return;
    38. }
    39.  
    40. // some processing...
    41.  
    42. if(device_cast(m_pInputDevice)->write(data) == -1)
    43. emit error("Data output failed.");
    44. }
    45.  
    46. template <class T>
    47. T* MyClass::device_cast(QIODevice* device)
    48. {
    49. if(qobject_cast<SerialIODevice*>(device))
    50. return qobject_cast<SerialIODevice*>(device);
    51. else
    52. return device;
    53. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Apr 2010
    Location
    Rostov-na-Donu, Russia
    Posts
    153
    Thanks
    2
    Thanked 26 Times in 23 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: template to retrieve QIODevice subclass

    Just move implementation of a template to header

  3. #3
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: template to retrieve QIODevice subclass

    Q_OBJECT macro and template classes can't be used together. And also I fail to see the point of your "device_cast" method. The return type has to be known at the time of calling so essentially T can only be QIODevice or QObject because the method has to be able to return QIODevice* with each call. And if that's the case then the method doesn't do any casting, it simply checks whether the device inherits SerialIODevice. You can rewrite the method as:
    Qt Code:
    1. QIODevice *MyClass::device_cast(QIODevice *device) {
    2. return device;
    3. }
    To copy to clipboard, switch view to plain text mode 

    ... which doesn't make much sense, of course.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  4. #4
    Join Date
    Jun 2010
    Posts
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: template to retrieve QIODevice subclass

    Thank you for both your answers.

    borisbn: I'm not at home right now but I will try your solution asap.

    wysota: Do you have a better means to propose in order to achieve my goal? At the moment the best I can do apart testing the qobject_cast return value is to retrieve the class name as a string using QMetaObject but then I don't know how to get my pointer from this string (apart from testing all the possible cases which is quite the same as testing qobject_cast return value...)

    thank you again.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: template to retrieve QIODevice subclass

    Quote Originally Posted by onil View Post
    wysota: Do you have a better means to propose in order to achieve my goal?
    I have no idea what you want to achieve. You always need to assign a return value of a function to a variable of specific type, it won't be determined for you. If you have such constructions:

    Qt Code:
    1. Class1* func(int) { return new Class1(); }
    2. Class2* func(int) { return new Class2(); }
    To copy to clipboard, switch view to plain text mode 
    Then the compiler will throw a compilation error, regardless if you use a template or not, because it will never know which version of func() to choose, especially if Class1 is castable to Class2 or the other way round.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  6. #6
    Join Date
    Jun 2010
    Posts
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: template to retrieve QIODevice subclass

    Hi,
    borisbn: I have tried your solution but still have 'no matching function for call to 'MyClass::device_cast(QIODevice*&)'

    wysota: Yes I know that a function has to return a specific type. However I was hoping (and maybe I'm wrong) that using a template function I can have a function that returns SerialIODevice* when my QIODevice* is also a SerialIODevice*, a SslIODevice* when my QIODevice* is also a SslIODevice* and so on.
    If none of the tested types are found, the default return type would be a QIODevice*.

    What I exactly want is to store pointers to QIODevices in my class members in order to be able to use any class derived from QIODevice, BUT to call the subclass's functions when I make a call to memeber's functions (getChar, write, open, ...).

    Regards.

  7. #7
    Join Date
    Jun 2010
    Posts
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: template to retrieve QIODevice subclass

    Hello everybody,

    I have been very busy in the last couple of weeks so I left this problem aside. Yesterday I managed to solve my problem using the QMetaObject functionalities. See code example below to see how I managed to achieve my goal.

    Thank you all for your help.

    Regards.


    myClass.h:
    Qt Code:
    1. #ifndef MY_CLASS_H
    2. #define MY_CLASS_H
    3.  
    4. #include <QObject>
    5. #include <QThread>
    6. #include <QIODevice>
    7.  
    8. class MyClass : public QThread
    9. {
    10. Q_OBJECT
    11.  
    12. public:
    13.  
    14. explicit MyClass(QIODevice* inputDevice = 0, QObject *parent = 0);
    15. ~MyClass();
    16.  
    17. void sendData(quint8 id, QByteArray data);
    18.  
    19. some other members ...
    20.  
    21. private:
    22.  
    23. QIODevice* m_pInputDevice;
    24. QIODevice* m_pForwardDevice;
    25.  
    26. some other members ...
    27.  
    28. };
    29.  
    30. #endif // MY_CLASS_H
    To copy to clipboard, switch view to plain text mode 

    myClass.cpp
    Qt Code:
    1. #include "MyClass.h"
    2.  
    3. MyClass::MyClass(QIODevice* inputDevice, QObject *parent) :
    4. QThread(parent), m_pInputDevice(inputDevice), m_pForwardDevice(NULL), m_bForwardData(false)
    5. {
    6. }
    7.  
    8. MyClass::~MyClass()
    9. {
    10. bool bRet;
    11. if(m_pInputDevice)
    12. {
    13. QMetaObject::invokeMethod(m_pInputDevice, "isOpen",
    14. Qt::DirectConnection, Q_RETURN_ARG(bool, bRet));
    15. if(bRet)
    16. {
    17. QMetaObject::invokeMethod(m_pInputDevice, "close",
    18. Qt::DirectConnection);
    19. }
    20. }
    21.  
    22. if(m_pForwardDevice)
    23. {
    24. QMetaObject::invokeMethod(m_pForwardDevice, "isOpen",
    25. Qt::DirectConnection, Q_RETURN_ARG(bool, bRet));
    26. if(bRet)
    27. {
    28. QMetaObject::invokeMethod(m_pForwardDevice, "close",
    29. Qt::DirectConnection);
    30. }
    31. }
    32. }
    33.  
    34. // use case example
    35.  
    36. void MyClass::sendData(quint8 id, QByteArray data)
    37. {
    38. bool bRet;
    39. if (!m_pInputDevice)
    40. {
    41. emit error("Input device not set!");
    42. return;
    43. }
    44.  
    45. QMetaObject::invokeMethod(m_pInputDevice, "isOpen",
    46. Qt::DirectConnection, Q_RETURN_ARG(bool, bRet));
    47. if(!bRet)
    48. {
    49. emit error("Input device is not open");
    50. return;
    51. }
    52.  
    53. QFlags<QIODevice::OpenModeFlag> openMode;
    54. QMetaObject::invokeMethod(m_pInputDevice, "openMode",
    55. Qt::DirectConnection, Q_RETURN_ARG(QFlags<QIODevice::OpenModeFlag>, openMode));
    56. if (openMode == QIODevice::ReadOnly)
    57. {
    58. emit error("Input device is in read only mode!");
    59. return;
    60. }
    61.  
    62. // some processing...
    63.  
    64. qint64 bytesWritten;
    65. QMetaObject::invokeMethod(m_pInputDevice, "write",
    66. Qt::DirectConnection, Q_RETURN_ARG(qint64, bytesWritten), Q_ARG(QByteArray, data));
    67. if(bytesWritten == -1)
    68. emit error("Data output failed.");
    69. }
    To copy to clipboard, switch view to plain text mode 


    Example of SslIODevice

    SslIODevice.h:
    Qt Code:
    1. #ifndef SSL_IO_DEVICE_H
    2. #define SSL_IO_DEVICE_H
    3.  
    4. #include <QSslSocket>
    5.  
    6. class SslIODevice : public QSslSocket
    7. {
    8. Q_OBJECT
    9.  
    10. public:
    11.  
    12. explicit SslIODevice();
    13. ~SslIODevice();
    14.  
    15. //For each QIODevice method I use
    16. Q_INVOKABLE [I]returnType[/I] method([I]args[/I]);
    17. some other members ...
    18.  
    19. private:
    20.  
    21. some private members ...
    22.  
    23. };
    24.  
    25. #endif // SSL_IO_DEVICE_H
    To copy to clipboard, switch view to plain text mode 

    SslIODevice.cpp
    Qt Code:
    1. #include "SslIODevice.h"
    2.  
    3. SslIODevice::SslIODevice() :
    4. QSslSocket()
    5. {
    6. }
    7.  
    8. SslIODevice::~SslIODevice()
    9. {
    10. }
    11.  
    12. //For each QIODevice method I use
    13. [I]returnType[/I] SslIODevice::method([I]args[/I])
    14. {
    15. return QSslSocket::method([I]args[/I]);
    16. }
    To copy to clipboard, switch view to plain text mode 

Similar Threads

  1. Replies: 8
    Last Post: 12th February 2010, 03:41
  2. QIODevice
    By sabeesh in forum Newbie
    Replies: 1
    Last Post: 26th September 2007, 11:01
  3. QIODevice read()
    By ShaChris23 in forum Newbie
    Replies: 1
    Last Post: 3rd May 2007, 01:29
  4. QIODEvice
    By mickey in forum Qt Programming
    Replies: 2
    Last Post: 5th July 2006, 20:00
  5. QIODevice::bytesAvailable() always returning 0
    By quickNitin in forum Newbie
    Replies: 6
    Last Post: 14th June 2006, 14:04

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.