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. Q_NAMESPACE across multiple files

Q_NAMESPACE across multiple files

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 2 Posters 1.1k 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.
  • C Offline
    C Offline
    Creaperdown
    wrote on last edited by
    #1

    Hey, I have a folder called common/enums in which I want to store some enums which I also want to register to QML. I am using Q_NAMESPACE combined with Q_ENUM_NS to do this. This works just fine for one enum, but when adding another, I am getting this error:

    In file included from /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/mocs_compilation.cpp:3:
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_common_mocked_namespace.cpp:24:8: error: redefinition of ‘struct qt_meta_stringdata_application_t’
    24 | struct qt_meta_stringdata_application_t {
    |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/mocs_compilation.cpp:2:
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_book_operation_status.cpp:24:8: note: previous definition of ‘struct qt_meta_stringdata_application_t’
    24 | struct qt_meta_stringdata_application_t {
    |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_common_mocked_namespace.cpp:33:47: error: redefinition of ‘const qt_meta_stringdata_application_t qt_meta_stringdata_application’
    33 | static const qt_meta_stringdata_application_t qt_meta_stringdata_application = {
    |                                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_book_operation_status.cpp:33:47: note: ‘const qt_meta_stringdata_application_t qt_meta_stringdata_application’ previously defined here
    33 | static const qt_meta_stringdata_application_t qt_meta_stringdata_application = {
    |                                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_common_mocked_namespace.cpp:42:19: error: redefinition of ‘const uint qt_meta_data_application []’
    42 | static const uint qt_meta_data_application[] = {
    |                   ^~~~~~~~~~~~~~~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_book_operation_status.cpp:53:19: note: ‘const uint qt_meta_data_application [34]’ previously defined here
    53 | static const uint qt_meta_data_application[] = {
    |                   ^~~~~~~~~~~~~~~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_common_mocked_namespace.cpp:58:38: error: redefinition of ‘const QMetaObject application::staticMetaObject’
    58 | QT_INIT_METAOBJECT const QMetaObject application::staticMetaObject = { {
    |                                      ^~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_book_operation_status.cpp:81:38: note: ‘const QMetaObject application::staticMetaObject’ previously defined here
    81 | QT_INIT_METAOBJECT const QMetaObject application::staticMetaObject = { {
    |                                      ^~~~~~~~~~~
    In file included from /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/mocs_compilation.cpp:4:
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_settings_keys.cpp:24:8: error: redefinition of ‘struct qt_meta_stringdata_application_t’
    24 | struct qt_meta_stringdata_application_t {
    |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_book_operation_status.cpp:24:8: note: previous definition of ‘struct qt_meta_stringdata_application_t’
    24 | struct qt_meta_stringdata_application_t {
    |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_settings_keys.cpp:33:47: error: redefinition of ‘const qt_meta_stringdata_application_t qt_meta_stringdata_application’
    33 | static const qt_meta_stringdata_application_t qt_meta_stringdata_application = {
    |                                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_book_operation_status.cpp:33:47: note: ‘const qt_meta_stringdata_application_t qt_meta_stringdata_application’ previously defined here
    33 | static const qt_meta_stringdata_application_t qt_meta_stringdata_application = {
    |                                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_settings_keys.cpp:57:19: error: redefinition of ‘const uint qt_meta_data_application []’
    57 | static const uint qt_meta_data_application[] = {
    |                   ^~~~~~~~~~~~~~~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_book_operation_status.cpp:53:19: note: ‘const uint qt_meta_data_application [34]’ previously defined here
    53 | static const uint qt_meta_data_application[] = {
    |                   ^~~~~~~~~~~~~~~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_settings_keys.cpp:88:38: error: redefinition of ‘const QMetaObject application::staticMetaObject’
    88 | QT_INIT_METAOBJECT const QMetaObject application::staticMetaObject = { {
    |                                      ^~~~~~~~~~~
    /home/creapermann/Programming/Etovex/Librum/build-Debug/src/application/application_autogen/QVJXAE3BGF/moc_book_operation_status.cpp:81:38: note: ‘const QMetaObject application::staticMetaObject’ previously defined here
    81 | QT_INIT_METAOBJECT const QMetaObject application::staticMetaObject = { {
    |                                      ^~~~~~~~~~~
    [35/87] Building CXX object src/application/core/gene...ularGenerator_comicbook.dir/generator_comicbook.cpp.o
    ninja: build stopped: subcommand failed.
    

    I known that this is a known bug (or problem), since there are multiple bug reports for it (https://bugreports.qt.io/browse/QTBUG-68611).
    Non the less, is there a work around so that one is able to have enums in the same namespace registered to QML?
    My classes both look like this (Just with a different enum name):

    namespace application
    {
    
    Q_NAMESPACE
    
    enum class BookOperationStatus
    {
        Success,
        OpeningBookFailed,
        BookDoesNotExist,
        PropertyDoesNotExist,
        TagDoesNotExist,
        TagAlreadyExists,
        OperationFailed
    };
    
    Q_ENUM_NS(BookOperationStatus)
    
    }  // namespace application
    

    Thanks in advance

    1 Reply Last reply
    0
    • C Offline
      C Offline
      ChrisW67
      wrote on last edited by ChrisW67
      #2

      @Creaperdown said in Q_NAMESPACE across multiple files:

      Non the less, is there a work around so that one is able to have enums in the same namespace registered to QML?

      Perhaps this will work for you.
      Group all the QObject-related declarations into a single header and put nothing QObject related in the others. Use a little macro magic to get all the enum declarations inside a single namespace { } block to work around moc not having a full C++ parser.

      #ifndef ENUMDECL_H
      #define ENUMDECL_H
      
      #include <QObject>
      
      namespace application
      {
      
      #include "enum1.h"
      #include "enum2.h"
      
      Q_NAMESPACE
      Q_ENUM_NS(Enum1)
      Q_ENUM_NS(Enum2)
      
      }
      
      #endif // ENUMDECL_H
      
      #ifndef ENUM1_H
      #define ENUM1_H
      
      #ifndef ENUMDECL_H
      namespace application
      {
      #endif
      
      enum class Enum1
      {
          Enum1_Value1,
          Enum1_Value2,
          Enum1_Value3
      };
      
      #ifndef ENUMDECL_H
      }  // namespace application
      #endif
      
      #endif // ENUM1_H
      
      #ifndef ENUM2_H
      #define ENUM2_H
      
      #ifndef ENUMDECL_H
      namespace application
      {
      #endif
      
      enum class Enum2
      {
          Enum2_Value1,
          Enum2_Value2,
          Enum2_Value3
      };
      
      #ifndef ENUMDECL_H
      }  // namespace application
      #endif
      
      #endif // ENUM2_H
      
      HEADERS += \
          enumdecl.h
      

      You will get just the one moc-related bunch of static structures in your code.

      Edit: Not exactly sure how it will go with CMake

      C 2 Replies Last reply
      0
      • C ChrisW67

        @Creaperdown said in Q_NAMESPACE across multiple files:

        Non the less, is there a work around so that one is able to have enums in the same namespace registered to QML?

        Perhaps this will work for you.
        Group all the QObject-related declarations into a single header and put nothing QObject related in the others. Use a little macro magic to get all the enum declarations inside a single namespace { } block to work around moc not having a full C++ parser.

        #ifndef ENUMDECL_H
        #define ENUMDECL_H
        
        #include <QObject>
        
        namespace application
        {
        
        #include "enum1.h"
        #include "enum2.h"
        
        Q_NAMESPACE
        Q_ENUM_NS(Enum1)
        Q_ENUM_NS(Enum2)
        
        }
        
        #endif // ENUMDECL_H
        
        #ifndef ENUM1_H
        #define ENUM1_H
        
        #ifndef ENUMDECL_H
        namespace application
        {
        #endif
        
        enum class Enum1
        {
            Enum1_Value1,
            Enum1_Value2,
            Enum1_Value3
        };
        
        #ifndef ENUMDECL_H
        }  // namespace application
        #endif
        
        #endif // ENUM1_H
        
        #ifndef ENUM2_H
        #define ENUM2_H
        
        #ifndef ENUMDECL_H
        namespace application
        {
        #endif
        
        enum class Enum2
        {
            Enum2_Value1,
            Enum2_Value2,
            Enum2_Value3
        };
        
        #ifndef ENUMDECL_H
        }  // namespace application
        #endif
        
        #endif // ENUM2_H
        
        HEADERS += \
            enumdecl.h
        

        You will get just the one moc-related bunch of static structures in your code.

        Edit: Not exactly sure how it will go with CMake

        C Offline
        C Offline
        Creaperdown
        wrote on last edited by
        #3
        This post is deleted!
        1 Reply Last reply
        0
        • C ChrisW67

          @Creaperdown said in Q_NAMESPACE across multiple files:

          Non the less, is there a work around so that one is able to have enums in the same namespace registered to QML?

          Perhaps this will work for you.
          Group all the QObject-related declarations into a single header and put nothing QObject related in the others. Use a little macro magic to get all the enum declarations inside a single namespace { } block to work around moc not having a full C++ parser.

          #ifndef ENUMDECL_H
          #define ENUMDECL_H
          
          #include <QObject>
          
          namespace application
          {
          
          #include "enum1.h"
          #include "enum2.h"
          
          Q_NAMESPACE
          Q_ENUM_NS(Enum1)
          Q_ENUM_NS(Enum2)
          
          }
          
          #endif // ENUMDECL_H
          
          #ifndef ENUM1_H
          #define ENUM1_H
          
          #ifndef ENUMDECL_H
          namespace application
          {
          #endif
          
          enum class Enum1
          {
              Enum1_Value1,
              Enum1_Value2,
              Enum1_Value3
          };
          
          #ifndef ENUMDECL_H
          }  // namespace application
          #endif
          
          #endif // ENUM1_H
          
          #ifndef ENUM2_H
          #define ENUM2_H
          
          #ifndef ENUMDECL_H
          namespace application
          {
          #endif
          
          enum class Enum2
          {
              Enum2_Value1,
              Enum2_Value2,
              Enum2_Value3
          };
          
          #ifndef ENUMDECL_H
          }  // namespace application
          #endif
          
          #endif // ENUM2_H
          
          HEADERS += \
              enumdecl.h
          

          You will get just the one moc-related bunch of static structures in your code.

          Edit: Not exactly sure how it will go with CMake

          C Offline
          C Offline
          Creaperdown
          wrote on last edited by
          #4

          @ChrisW67 Thanks, this fixes it. Do you think there might be a way without the macro magic here though?

          1 Reply Last reply
          0
          • C Offline
            C Offline
            Creaperdown
            wrote on last edited by
            #5

            A solution I came up with, is putting every enum into its own unique namespace to avoid the MOC duplication problems:

            #pragma once
            #include <QObject>
            
            // Each enum needs to be in a separate namespace due to a Qt bug reported at:
            // https://bugreports.qt.io/browse/QTBUG-81792
            //
            // This causes not being able to register multiple enums to the Qt type system
            // and to QML (Q_NAMESPACE and Q_ENUM_NS), if they are in the same namespace.
            // The work around is to create a separate namespace for each enum.
            namespace application::setting_keys
            {
            
            Q_NAMESPACE
            
            enum class SettingKeys
            {
                Theme,
                PageSpacing,
                DisplayBookTitleInTitlebar,
                LayoutDirection,
                DisplayMode,
                PageTransition,
                DefaultZoom,
                SmoothScrolling,
                LoopAfterLastPage,
                CursorMode
            };
            
            Q_ENUM_NS(SettingKeys)
            
            }  // namespace application::setting_keys
            
            // Because the enum shouldn't be in a separate namespace in the first place,
            // make the namespace available to all of its users to avoid syntactic clutter.
            using namespace application::setting_keys;
            

            If anyone finds a better solution, please let me know.

            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