Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Converting Enums to Strings for QPrinter
QtWS25 Last Chance

Converting Enums to Strings for QPrinter

Scheduled Pinned Locked Moved Unsolved General and Desktop
qprinterenumqt4qmetaobject
13 Posts 4 Posters 5.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    DougyDrumz
    wrote on last edited by
    #1

    I want to be able to convert the QPrinter enums to strings so I can pass them to lp. There are lots of examples using QMetaObject to do this. Unfortunately "'staticMetaObject' is not a member of 'QPrinter'". Any ideas?

    Dougy Drumz

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Indeed QPrinter is not a QObject based class. One thing you can do is to write conversion functions that maps the enum you need to QStrings.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • W Offline
        W Offline
        Wilk
        wrote on last edited by Wilk
        #3

        Hi
        I've created the following code to enable easy conversion between enum values and strings:

        #define DECLARE_ENUM_TYPE(NAME, ...) \
        	class NAME { \
        	public: \
        		typedef enum { \
        			Invalid ## NAME = -1, \
        			___LOWER_BOUND___ = -1, \
        			__VA_ARGS__,\
        			___UPPER_BOUND___, \
        			___VALUES_COUNT___ = ___UPPER_BOUND___, \
        		} enum_t; \
        		\
        		NAME () \
        			: _value (Invalid ## NAME) {} \
        		explicit NAME (enum_t i_value): \
        			_value (i_value) {} \
        		\
        		NAME (const NAME& i_other): \
        			_value (i_other._value) {} \
        		\
        		NAME (const char* i_name): \
        			_value (Invalid ## NAME) { \
        			std::string name (i_name); \
        			\
        			if (textValueMap ().count (name)) { \
        				_value = textValueMap ()[name]; \
        			} \
        		} \
        		\
        		operator const char*() const { \
        			char* text = "Invalid";\
        			\
        			if (Invalid ## NAME != _value) { \
        				text = (char*)(&(valueTexts ()[valueTextIndexes () [_value]])); \
        			} \
        			\
        			return text; \
        		} \
        		\
        		operator enum_t() const { \
        			return _value; \
        		} \
        		\
        		NAME& operator= (const NAME& i_other) { \
        			_value = i_other._value; \
        			return *this; \
        		} \
        		NAME& operator= (const enum_t& i_value) { \
        			_value = i_value; \
        			return *this; \
        		} \
        		\
        		\
        	private: \
        		const char* valueTexts () const { \
        			static const char* s_valueTexts = buildValueTexts (); \
        			\
        			return s_valueTexts; \
        		} \
        		\
        		const size_t* valueTextIndexes () const { \
        			static const size_t* s_valueTextIndexes = buildValueTextIndexes (); \
        			\
        			return s_valueTextIndexes; \
        		} \
        		\
        		std::map< std::string, enum_t > textValueMap () const { \
        			static std::map< std::string, enum_t > s_textValueMap (buildTextValueMap ()); \
        			\
        			return s_textValueMap; \
        		}\
        		\
        		size_t* buildValueTextIndexes () const { \
        			static size_t s_valueTextIndexes[___VALUES_COUNT___]; \
        			\
        			s_valueTextIndexes [0] = 0; \
        			\
        			char comaSeparatedValueText[] = #__VA_ARGS__; \
        			\
        			for (size_t \
        					charIndex (1), \
        					maxIndex (strlen (comaSeparatedValueText)), \
        					valueForText (1); \
        				charIndex < maxIndex; \
        				++charIndex) { \
        				if (((',' == comaSeparatedValueText [charIndex - 1]) || \
        					(' ' == comaSeparatedValueText [charIndex - 1])) && \
        					((',' != comaSeparatedValueText [charIndex]) && \
        					(' ' != comaSeparatedValueText [charIndex]))) { \
        					s_valueTextIndexes [valueForText] = charIndex; \
        					valueForText += 1; \
        				} \
        			} \
        			\
        			return s_valueTextIndexes; \
        		} \
        		\
        		char* buildValueTexts () const { \
        			static char s_valueTexts[] = #__VA_ARGS__; \
        			\
        			for (size_t \
        					charIndex (0), \
        					maxIndex (strlen (s_valueTexts)); \
        				charIndex < maxIndex; \
        				++charIndex) { \
        				if (',' == s_valueTexts [charIndex]) { \
        					s_valueTexts [charIndex] = 0; \
        				} \
        			} \
        			\
        			return s_valueTexts; \
        		} \
        		\
        		std::map< std::string, enum_t > buildTextValueMap () const { \
        			static std::map< std::string, enum_t > s_textValueMap; \
        			\
        			for ( \
        				size_t value = 0; \
        				value < ___VALUES_COUNT___; \
        				++value) { \
        				s_textValueMap [&(valueTexts ()[valueTextIndexes () [value]])] = enum_t (value); \
        			} \
        			\
        			return s_textValueMap; \
        		} \
        		\
        		\
        		enum_t _value; \
        	};
        Obviously, it does not do exactly what you want, but you may try to use it as startup point for your solution.
        
        1 Reply Last reply
        0
        • D Offline
          D Offline
          DougyDrumz
          wrote on last edited by
          #4

          Looks fascinating, but I'm having a hard time seeing the forest for the trees. Do you have sample code which calls this macro?

          Dougy Drumz

          kshegunovK W 2 Replies Last reply
          0
          • D DougyDrumz

            Looks fascinating, but I'm having a hard time seeing the forest for the trees. Do you have sample code which calls this macro?

            kshegunovK Offline
            kshegunovK Offline
            kshegunov
            Moderators
            wrote on last edited by kshegunov
            #5

            @DougyDrumz
            Maybe try something simpler than generating classes with macros? This should suffice:

            // These two statics you could also put in your class if you wish (it'd be better even)
            static QPair<EnumType, QString> nameTable[] = {
                qMakePair(EnumValue1, QStringLiteral("EnumValue1")),
                qMakePair(EnumValue2, QStringLiteral("EnumValue2"))
            };
            static const qint32 EnumTypeValuesNumber = 2;
            
            class MyClass
            {
                QHash<EnumType, QString> enumToNameHash;
                QHash<QString, EnumType> nameToEnumHash;
            
                QString enumToString(EnumType enumValue)
                {
                    if (enumToNameHash.isEmpty())  {
                        // Lazy init the hash table
                        enumToNameHash.reserve(EnumTypeValuesNumber);
                        for (qint32 i = 0; i < EnumTypeValuesNumber; i++)
                            enumToNameHash.insert(nameTable[i].first, nameTable[i].second);
                    }
            
                    return enumToNameHash.value(enumValue);
                }
            
                EnumType stringToEnum(QString enumName)
                {
                    if (nameToEnumHash.isEmpty())  {
                        // Lazy init the hash table
                        nameToEnumHash.reserve(EnumTypeValuesNumber);
                        for (qint32 i = 0; i < EnumTypeValuesNumber; i++)
                            nameToEnumHash.insert(nameTable[i].second, nameTable[i].first);
                    }
            
                    return nameToEnumHash.value(enumName);
                }
            
                // ...
            };
            

            As a side note, you could also simplify it a bit if your enums are ordered and are starting from 0. Then one of the hash tables isn't needed. Additionally, you could put one value at the end of the enum to serve as the number of values constant instead of creating its own variable, e.g:

            enum MyEnumType  {
                EnumValue1 = 0, EnumValue2, EnumTypeValuesNumber
            }
            

            Kind regards.

            Read and abide by the Qt Code of Conduct

            W 1 Reply Last reply
            0
            • D Offline
              D Offline
              DougyDrumz
              wrote on last edited by
              #6

              I'm a little confused here. What both of you appear to be doing is making a mapping between an enum value and a string representing that value when a class is created. Please correct me if I'm wrong. What I want to do is extract the string representation of an enum value for a class that already exists - in my case QPrinter. The staticMetaObject is a great paradigm for this. Unfortunately there is no staticMetaObject for QPrinter. Do I need to parse the OPrinter header file and grab the strings there? I've seen examples similar to that around.

              I was hoping for some simple magic, but as we know, there is no magic.

              Dougy Drumz

              kshegunovK 1 Reply Last reply
              0
              • D DougyDrumz

                I'm a little confused here. What both of you appear to be doing is making a mapping between an enum value and a string representing that value when a class is created. Please correct me if I'm wrong. What I want to do is extract the string representation of an enum value for a class that already exists - in my case QPrinter. The staticMetaObject is a great paradigm for this. Unfortunately there is no staticMetaObject for QPrinter. Do I need to parse the OPrinter header file and grab the strings there? I've seen examples similar to that around.

                I was hoping for some simple magic, but as we know, there is no magic.

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on last edited by
                #7

                @DougyDrumz
                Well, I'm not aware of any other way ... an enum is an integer wrapped in a nice language construct, nothing else. In the end the moc will do it in similar fashion, that's why you need to use all that macros for the meta-object system ...

                Read and abide by the Qt Code of Conduct

                1 Reply Last reply
                0
                • D DougyDrumz

                  Looks fascinating, but I'm having a hard time seeing the forest for the trees. Do you have sample code which calls this macro?

                  W Offline
                  W Offline
                  Wilk
                  wrote on last edited by
                  #8

                  @DougyDrumz Sorry for making you wait: yesterday forum was down right after your question, and today I've just got to computer.

                  // Definition of enum class
                  DECLARE_ENUM_TYPE (
                  	DatasetElementType,
                  	int8_t,
                  	uint8_t,
                  	int16_t,
                  	uint16_t,
                  	int32_t,
                  	uint32_t,
                  	int64_t,
                  	uint64_t,
                  	float_t,
                  	double_t
                  )
                  

                  Then you can use it anewhere in your code:

                  DatasetElementType_t value (DatasetElementType_t::uint8_t);
                  
                  qDebug () << value; // Output: uint8_t
                  
                  value = DatasetElementType ("uint16_t"); // Create by enum element name, for example, during deserialization.
                  
                  qDebug () << value; // Output: uint16_t
                  

                  I've undestud that you want to convert to string and vise versa values from existing enum. Ofcourse, the solution that I've proposed is not exactly the thing you want. However, you may try to implement something like this to be able to wrap QPrinter enum. I don't know any other sane solution for this problem.

                  1 Reply Last reply
                  0
                  • kshegunovK kshegunov

                    @DougyDrumz
                    Maybe try something simpler than generating classes with macros? This should suffice:

                    // These two statics you could also put in your class if you wish (it'd be better even)
                    static QPair<EnumType, QString> nameTable[] = {
                        qMakePair(EnumValue1, QStringLiteral("EnumValue1")),
                        qMakePair(EnumValue2, QStringLiteral("EnumValue2"))
                    };
                    static const qint32 EnumTypeValuesNumber = 2;
                    
                    class MyClass
                    {
                        QHash<EnumType, QString> enumToNameHash;
                        QHash<QString, EnumType> nameToEnumHash;
                    
                        QString enumToString(EnumType enumValue)
                        {
                            if (enumToNameHash.isEmpty())  {
                                // Lazy init the hash table
                                enumToNameHash.reserve(EnumTypeValuesNumber);
                                for (qint32 i = 0; i < EnumTypeValuesNumber; i++)
                                    enumToNameHash.insert(nameTable[i].first, nameTable[i].second);
                            }
                    
                            return enumToNameHash.value(enumValue);
                        }
                    
                        EnumType stringToEnum(QString enumName)
                        {
                            if (nameToEnumHash.isEmpty())  {
                                // Lazy init the hash table
                                nameToEnumHash.reserve(EnumTypeValuesNumber);
                                for (qint32 i = 0; i < EnumTypeValuesNumber; i++)
                                    nameToEnumHash.insert(nameTable[i].second, nameTable[i].first);
                            }
                    
                            return nameToEnumHash.value(enumName);
                        }
                    
                        // ...
                    };
                    

                    As a side note, you could also simplify it a bit if your enums are ordered and are starting from 0. Then one of the hash tables isn't needed. Additionally, you could put one value at the end of the enum to serve as the number of values constant instead of creating its own variable, e.g:

                    enum MyEnumType  {
                        EnumValue1 = 0, EnumValue2, EnumTypeValuesNumber
                    }
                    

                    Kind regards.

                    W Offline
                    W Offline
                    Wilk
                    wrote on last edited by
                    #9

                    @kshegunov Hi.
                    Basicaly you are wrong and my solution is much easier. The reason for this is pretty simple: proposed macros may be created and debuged once and then anyone may use it for as much as he wants. And addition of new values in enum does not require to change some other code to support it - in you solution you have to edit nameTable every time you add enum members. However my solution lacks ability to create enums where values start not from 0.

                    kshegunovK 1 Reply Last reply
                    0
                    • W Wilk

                      @kshegunov Hi.
                      Basicaly you are wrong and my solution is much easier. The reason for this is pretty simple: proposed macros may be created and debuged once and then anyone may use it for as much as he wants. And addition of new values in enum does not require to change some other code to support it - in you solution you have to edit nameTable every time you add enum members. However my solution lacks ability to create enums where values start not from 0.

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by
                      #10

                      @Wilk

                      Basicaly you are wrong and my solution is much easier. The reason for this is pretty simple: proposed macros may be created and debuged once and then anyone may use it for as much as he wants.

                      Surely, why bother with functions if you can use macros ...

                      Read and abide by the Qt Code of Conduct

                      W 1 Reply Last reply
                      0
                      • kshegunovK kshegunov

                        @Wilk

                        Basicaly you are wrong and my solution is much easier. The reason for this is pretty simple: proposed macros may be created and debuged once and then anyone may use it for as much as he wants.

                        Surely, why bother with functions if you can use macros ...

                        W Offline
                        W Offline
                        Wilk
                        wrote on last edited by
                        #11

                        @kshegunov
                        I don't understand you. Macros is a powerfull tool which can be reliable is used in a right way. Just take a look at Qt itself and you will find out quite a lot of macros.

                        kshegunovK 1 Reply Last reply
                        0
                        • W Wilk

                          @kshegunov
                          I don't understand you. Macros is a powerfull tool which can be reliable is used in a right way. Just take a look at Qt itself and you will find out quite a lot of macros.

                          kshegunovK Offline
                          kshegunovK Offline
                          kshegunov
                          Moderators
                          wrote on last edited by
                          #12

                          @Wilk
                          This is beside the scope of this thread and to be honest I don't want to enter in fruitless discussions. Whatever the reason is that you think using macros is best in this case I don't have a problem with, in any case it's your choice how you will do your coding.

                          Read and abide by the Qt Code of Conduct

                          1 Reply Last reply
                          0
                          • D Offline
                            D Offline
                            DougyDrumz
                            wrote on last edited by
                            #13

                            Let me tone down this discussion by saying that the original reason for my question has disappeared. I misunderstood how QPrinter worked. I thought I would need the string versions of the QPrintDialog enums to pass on to lp. Turns out QPrinter does what I need to do automatically and I don't need to call lp. Thanks for the lively discussion though.

                            Dougy Drumz

                            1 Reply Last reply
                            0

                            • Login

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • Users
                            • Groups
                            • Search
                            • Get Qt Extensions
                            • Unsolved