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. QSvgRenderer and QByteArray problem

QSvgRenderer and QByteArray problem

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 4 Posters 1.5k Views 3 Watching
  • 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.
  • JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by JonB
    #1

    This is a question about my using QSvgRenderer and it not behaving as I would expect. Now initially that sounds scary, because I'm probably the only one using it here, but don't let it put you off this question: it might be a question about QByteArray and strings instead... :)

    I have some SVG I am loading into a QGraphicsSvgItem. What it is/does really shouldn't matter, but someone will want to know, so here it is:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <svg version="1.1">
        <g id="src/plugins/projectexplorer/images/buildstepdisable">
          <rect
             style="fill:#ffffff;fill-opacity:1"
             width="16"
             height="16"
             x="48"
             y="552" />
          <circle
             style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:1.42;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
             cx="56"
             cy="560"
             r="5.2929001" />
          <path
             d="m 52,564 c 8,-8 8,-8 8,-8"
             style="fill:none;stroke:#000000;stroke-width:1.42;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
        </g>
    </svg>
    

    Now, if I have just this in a file and I create via

    QSvgRenderer *svgRenderer = new QSvgRenderer(QString("/home/jon/QtTests/QtSvg/qtcreatoricons2.svg"));
    QGraphicsSvgItem *svgItem = new QGraphicsSvgItem(this);
    svgItem->setSharedRenderer(svgRenderer);
    

    all is well, the icon gets rendered fine.

    But I don't want such a small piece of literal in a file. I want to do it from a literal string in code. I'm going to need to use the constructor QSvgRenderer::QSvgRenderer(const QByteArray &contents, QObject *parent = nullptr), right?

    Constructs a new renderer with the given parent and loads the SVG data from the byte array specified by contents.

    So I'm going to need a QByteArray. I copy & paste the above file content into code:

        static QByteArray svg =
            R"(
                <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                ...
                )";
        QSvgRenderer *svgRenderer = new QSvgRenderer(svg);
    

    No icon now appears. QSvgRenderer & QGraphicsSvgItem are pretty (totally) quiet when they don't get what they want, so I don't get any message to tell me what might have happened. But no icon appearing happens whenever the SVG presented is not acceptable, that must be the case. [UPDATE: Yes: I found bool QSvgRenderer::isValid() const, sure enough that returns true when initialised from my file but false when from my byte array.]

    Why? Is there anything wrong with my R"( ... )" around all that file content? Or assigning it to a QByteArray? How can I "debug" what the issue is (no, I don't have Qt sources)?

    artwawA raven-worxR 2 Replies Last reply
    0
    • JonBJ JonB

      @artwaw
      Well, what a surprise (not!), of course it works if I open the file and read in its bytes.
      The question is: why is my literal R(" ... )", where the ... is replaced by pasting the whole of the file content into the code, not producing a similarly-acceptable QByteArray content...?

      To be sure, a copy paste of what I have in code reads:

          static QByteArray svg =
              R"(
                  <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                  <svg version="1.1">
                      <g id="src/plugins/projectexplorer/images/buildstepdisable">
                        <rect
                           style="fill:#ffffff;fill-opacity:1"
                           width="16"
                           height="16"
                           x="48"
                           y="552" />
                        <circle
                           style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:1.42;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
                           cx="56"
                           cy="560"
                           r="5.2929001" />
                        <path
                           d="m 52,564 c 8,-8 8,-8 8,-8"
                           style="fill:none;stroke:#000000;stroke-width:1.42;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
                      </g>
                  </svg>
                  )";
      

      Can anyone spot anything wrong?

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by raven-worx
      #6

      @JonB
      ok, your problem is simply that your XML starts with an empty line, which makes it invalid.
      The check of mine above prints: XML Error: "invalid name for processing instruction 2 22"

      Change

      R"(
                  <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                  .....
      

      to

      R"(<?xml version="1.0" encoding="UTF-8" standalone="no"?>
           ....
      

      and it should work.

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      JonBJ 1 Reply Last reply
      3
      • JonBJ JonB

        This is a question about my using QSvgRenderer and it not behaving as I would expect. Now initially that sounds scary, because I'm probably the only one using it here, but don't let it put you off this question: it might be a question about QByteArray and strings instead... :)

        I have some SVG I am loading into a QGraphicsSvgItem. What it is/does really shouldn't matter, but someone will want to know, so here it is:

        <?xml version="1.0" encoding="UTF-8" standalone="no"?>
        <svg version="1.1">
            <g id="src/plugins/projectexplorer/images/buildstepdisable">
              <rect
                 style="fill:#ffffff;fill-opacity:1"
                 width="16"
                 height="16"
                 x="48"
                 y="552" />
              <circle
                 style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:1.42;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
                 cx="56"
                 cy="560"
                 r="5.2929001" />
              <path
                 d="m 52,564 c 8,-8 8,-8 8,-8"
                 style="fill:none;stroke:#000000;stroke-width:1.42;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
            </g>
        </svg>
        

        Now, if I have just this in a file and I create via

        QSvgRenderer *svgRenderer = new QSvgRenderer(QString("/home/jon/QtTests/QtSvg/qtcreatoricons2.svg"));
        QGraphicsSvgItem *svgItem = new QGraphicsSvgItem(this);
        svgItem->setSharedRenderer(svgRenderer);
        

        all is well, the icon gets rendered fine.

        But I don't want such a small piece of literal in a file. I want to do it from a literal string in code. I'm going to need to use the constructor QSvgRenderer::QSvgRenderer(const QByteArray &contents, QObject *parent = nullptr), right?

        Constructs a new renderer with the given parent and loads the SVG data from the byte array specified by contents.

        So I'm going to need a QByteArray. I copy & paste the above file content into code:

            static QByteArray svg =
                R"(
                    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                    ...
                    )";
            QSvgRenderer *svgRenderer = new QSvgRenderer(svg);
        

        No icon now appears. QSvgRenderer & QGraphicsSvgItem are pretty (totally) quiet when they don't get what they want, so I don't get any message to tell me what might have happened. But no icon appearing happens whenever the SVG presented is not acceptable, that must be the case. [UPDATE: Yes: I found bool QSvgRenderer::isValid() const, sure enough that returns true when initialised from my file but false when from my byte array.]

        Why? Is there anything wrong with my R"( ... )" around all that file content? Or assigning it to a QByteArray? How can I "debug" what the issue is (no, I don't have Qt sources)?

        artwawA Offline
        artwawA Offline
        artwaw
        wrote on last edited by
        #2

        @JonB Both constructors do

        /*!
            Loads the specified SVG format \a contents, returning true if the content
            was successfully parsed; otherwise returns false.
        */
        bool QSvgRenderer::load(const QByteArray &contents)
        {
            Q_D(QSvgRenderer);
            return loadDocument(this, d, contents);
        }
        

        but I don't have the sources to dig deeper. What could you possibly test is if your QByteArray is same as the content of the file, maybe load the content of the file into QByteArray and try too?

        For more information please re-read.

        Kind Regards,
        Artur

        JonBJ 2 Replies Last reply
        0
        • artwawA artwaw

          @JonB Both constructors do

          /*!
              Loads the specified SVG format \a contents, returning true if the content
              was successfully parsed; otherwise returns false.
          */
          bool QSvgRenderer::load(const QByteArray &contents)
          {
              Q_D(QSvgRenderer);
              return loadDocument(this, d, contents);
          }
          

          but I don't have the sources to dig deeper. What could you possibly test is if your QByteArray is same as the content of the file, maybe load the content of the file into QByteArray and try too?

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #3

          @artwaw
          Well, I know there are some differences. In file the lines are against the left-margin, in the literal string the lines start with whitespace per the pasted indentation in code inside the R"( ... "). But whitespace shouldn't be relevant here.....

          Let me go at least do as you say and load the file into memory QByteArray and see how it goes....

          1 Reply Last reply
          1
          • artwawA artwaw

            @JonB Both constructors do

            /*!
                Loads the specified SVG format \a contents, returning true if the content
                was successfully parsed; otherwise returns false.
            */
            bool QSvgRenderer::load(const QByteArray &contents)
            {
                Q_D(QSvgRenderer);
                return loadDocument(this, d, contents);
            }
            

            but I don't have the sources to dig deeper. What could you possibly test is if your QByteArray is same as the content of the file, maybe load the content of the file into QByteArray and try too?

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #4

            @artwaw
            Well, what a surprise (not!), of course it works if I open the file and read in its bytes.
            The question is: why is my literal R(" ... )", where the ... is replaced by pasting the whole of the file content into the code, not producing a similarly-acceptable QByteArray content...?

            To be sure, a copy paste of what I have in code reads:

                static QByteArray svg =
                    R"(
                        <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                        <svg version="1.1">
                            <g id="src/plugins/projectexplorer/images/buildstepdisable">
                              <rect
                                 style="fill:#ffffff;fill-opacity:1"
                                 width="16"
                                 height="16"
                                 x="48"
                                 y="552" />
                              <circle
                                 style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:1.42;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
                                 cx="56"
                                 cy="560"
                                 r="5.2929001" />
                              <path
                                 d="m 52,564 c 8,-8 8,-8 8,-8"
                                 style="fill:none;stroke:#000000;stroke-width:1.42;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
                            </g>
                        </svg>
                        )";
            

            Can anyone spot anything wrong?

            raven-worxR 1 Reply Last reply
            0
            • JonBJ JonB

              This is a question about my using QSvgRenderer and it not behaving as I would expect. Now initially that sounds scary, because I'm probably the only one using it here, but don't let it put you off this question: it might be a question about QByteArray and strings instead... :)

              I have some SVG I am loading into a QGraphicsSvgItem. What it is/does really shouldn't matter, but someone will want to know, so here it is:

              <?xml version="1.0" encoding="UTF-8" standalone="no"?>
              <svg version="1.1">
                  <g id="src/plugins/projectexplorer/images/buildstepdisable">
                    <rect
                       style="fill:#ffffff;fill-opacity:1"
                       width="16"
                       height="16"
                       x="48"
                       y="552" />
                    <circle
                       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:1.42;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
                       cx="56"
                       cy="560"
                       r="5.2929001" />
                    <path
                       d="m 52,564 c 8,-8 8,-8 8,-8"
                       style="fill:none;stroke:#000000;stroke-width:1.42;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
                  </g>
              </svg>
              

              Now, if I have just this in a file and I create via

              QSvgRenderer *svgRenderer = new QSvgRenderer(QString("/home/jon/QtTests/QtSvg/qtcreatoricons2.svg"));
              QGraphicsSvgItem *svgItem = new QGraphicsSvgItem(this);
              svgItem->setSharedRenderer(svgRenderer);
              

              all is well, the icon gets rendered fine.

              But I don't want such a small piece of literal in a file. I want to do it from a literal string in code. I'm going to need to use the constructor QSvgRenderer::QSvgRenderer(const QByteArray &contents, QObject *parent = nullptr), right?

              Constructs a new renderer with the given parent and loads the SVG data from the byte array specified by contents.

              So I'm going to need a QByteArray. I copy & paste the above file content into code:

                  static QByteArray svg =
                      R"(
                          <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                          ...
                          )";
                  QSvgRenderer *svgRenderer = new QSvgRenderer(svg);
              

              No icon now appears. QSvgRenderer & QGraphicsSvgItem are pretty (totally) quiet when they don't get what they want, so I don't get any message to tell me what might have happened. But no icon appearing happens whenever the SVG presented is not acceptable, that must be the case. [UPDATE: Yes: I found bool QSvgRenderer::isValid() const, sure enough that returns true when initialised from my file but false when from my byte array.]

              Why? Is there anything wrong with my R"( ... )" around all that file content? Or assigning it to a QByteArray? How can I "debug" what the issue is (no, I don't have Qt sources)?

              raven-worxR Offline
              raven-worxR Offline
              raven-worx
              Moderators
              wrote on last edited by raven-worx
              #5

              @JonB
              A quick way if the XML is still valid after you created the bytearray:

              QDomDocument doc;
              int errorLine, errorColumn;
              QString errorMsg;
              if( !doc.setContent(data, &errorMsg, &errorLine, &errorColumn ) )
                  qDebug() << "XML Error:" << errorMsg << errorLine << errorColumn;
              

              --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
              If you have a question please use the forum so others can benefit from the solution in the future

              1 Reply Last reply
              1
              • JonBJ JonB

                @artwaw
                Well, what a surprise (not!), of course it works if I open the file and read in its bytes.
                The question is: why is my literal R(" ... )", where the ... is replaced by pasting the whole of the file content into the code, not producing a similarly-acceptable QByteArray content...?

                To be sure, a copy paste of what I have in code reads:

                    static QByteArray svg =
                        R"(
                            <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                            <svg version="1.1">
                                <g id="src/plugins/projectexplorer/images/buildstepdisable">
                                  <rect
                                     style="fill:#ffffff;fill-opacity:1"
                                     width="16"
                                     height="16"
                                     x="48"
                                     y="552" />
                                  <circle
                                     style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:1.42;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
                                     cx="56"
                                     cy="560"
                                     r="5.2929001" />
                                  <path
                                     d="m 52,564 c 8,-8 8,-8 8,-8"
                                     style="fill:none;stroke:#000000;stroke-width:1.42;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
                                </g>
                            </svg>
                            )";
                

                Can anyone spot anything wrong?

                raven-worxR Offline
                raven-worxR Offline
                raven-worx
                Moderators
                wrote on last edited by raven-worx
                #6

                @JonB
                ok, your problem is simply that your XML starts with an empty line, which makes it invalid.
                The check of mine above prints: XML Error: "invalid name for processing instruction 2 22"

                Change

                R"(
                            <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                            .....
                

                to

                R"(<?xml version="1.0" encoding="UTF-8" standalone="no"?>
                     ....
                

                and it should work.

                --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                If you have a question please use the forum so others can benefit from the solution in the future

                JonBJ 1 Reply Last reply
                3
                • raven-worxR raven-worx

                  @JonB
                  ok, your problem is simply that your XML starts with an empty line, which makes it invalid.
                  The check of mine above prints: XML Error: "invalid name for processing instruction 2 22"

                  Change

                  R"(
                              <?xml version="1.0" encoding="UTF-8" standalone="no"?>
                              .....
                  

                  to

                  R"(<?xml version="1.0" encoding="UTF-8" standalone="no"?>
                       ....
                  

                  and it should work.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #7

                  @raven-worx said in QSvgRenderer and QByteArray problem:

                  ok, your problem is simply that your XML starts with an empty line, which makes it invalid.

                  I literally had just wondered about exactly this myself (honest!), and was about to test removing it when you replied!

                  I like your idea of the XML read, I agree that would have told me the problem here. But --- just to verify --- there is no way I can get that error message out of new QSvgRenderer(QByteArray svg) call, is there?

                  raven-worxR 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @raven-worx said in QSvgRenderer and QByteArray problem:

                    ok, your problem is simply that your XML starts with an empty line, which makes it invalid.

                    I literally had just wondered about exactly this myself (honest!), and was about to test removing it when you replied!

                    I like your idea of the XML read, I agree that would have told me the problem here. But --- just to verify --- there is no way I can get that error message out of new QSvgRenderer(QByteArray svg) call, is there?

                    raven-worxR Offline
                    raven-worxR Offline
                    raven-worx
                    Moderators
                    wrote on last edited by
                    #8

                    @JonB said in QSvgRenderer and QByteArray problem:

                    there is no way I can get that error message out of new QSvgRenderer(QByteArray svg) call, is there?

                    no. You can jsut check the return value of load() or isValid()

                    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                    If you have a question please use the forum so others can benefit from the solution in the future

                    JonBJ 2 Replies Last reply
                    0
                    • raven-worxR raven-worx

                      @JonB said in QSvgRenderer and QByteArray problem:

                      there is no way I can get that error message out of new QSvgRenderer(QByteArray svg) call, is there?

                      no. You can jsut check the return value of load() or isValid()

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #9

                      @raven-worx
                      Yeah, I want a lastLoadError() method :)

                      It's working now, I'll mark your earlier as the solution, thank you :)

                      1 Reply Last reply
                      0
                      • raven-worxR raven-worx

                        @JonB said in QSvgRenderer and QByteArray problem:

                        there is no way I can get that error message out of new QSvgRenderer(QByteArray svg) call, is there?

                        no. You can jsut check the return value of load() or isValid()

                        JonBJ Offline
                        JonBJ Offline
                        JonB
                        wrote on last edited by JonB
                        #10

                        @raven-worx
                        If you're still here, one quick not-quite-related question, else I might have to open a new topic....

                        Do you happen to know: I am using this QGraphicsSvgItem to put a small "icon overlay" on a QGraphicsPixmapItem. Problem: I allow "zoom" (via mousewheel) on the graphics items/view/scene. Works fine, the QGraphicsPixmapItem with their pixmaps grow/shrink. But this QGraphicsSvgItem icon overlay --- which is a child of the QGraphicsPixmapItem --- does not change size in response. SVG does not scale? QGraphicsSvgItem does not scale? The particular SVG I am using is set not to scale? Any idea what I should do?

                        EDIT Hang on, sorry, I may be mistaken. At present the overlay icon is so small it's hard to tell, maybe it is scaling and I can't see. I need to go make it bigger....

                        JoeCFDJ 1 Reply Last reply
                        0
                        • JonBJ JonB

                          @raven-worx
                          If you're still here, one quick not-quite-related question, else I might have to open a new topic....

                          Do you happen to know: I am using this QGraphicsSvgItem to put a small "icon overlay" on a QGraphicsPixmapItem. Problem: I allow "zoom" (via mousewheel) on the graphics items/view/scene. Works fine, the QGraphicsPixmapItem with their pixmaps grow/shrink. But this QGraphicsSvgItem icon overlay --- which is a child of the QGraphicsPixmapItem --- does not change size in response. SVG does not scale? QGraphicsSvgItem does not scale? The particular SVG I am using is set not to scale? Any idea what I should do?

                          EDIT Hang on, sorry, I may be mistaken. At present the overlay icon is so small it's hard to tell, maybe it is scaling and I can't see. I need to go make it bigger....

                          JoeCFDJ Offline
                          JoeCFDJ Offline
                          JoeCFD
                          wrote on last edited by JoeCFD
                          #11

                          @JonB You may need to override func shape to change the size of your icon. This is how I draw my circle inside my class RadioNode : public QGraphicsSvgItem. Catch mouse wheel event and set new diameter, then update?

                          QPainterPath RadioNode::shape() const
                          {
                              QPainterPath path;
                              path.addEllipse( -m_diameter * 0.5, -m_diameter * 0.5, m_diameter, m_diameter );
                              return path;
                          }
                          
                          JonBJ 1 Reply Last reply
                          0
                          • JoeCFDJ JoeCFD

                            @JonB You may need to override func shape to change the size of your icon. This is how I draw my circle inside my class RadioNode : public QGraphicsSvgItem. Catch mouse wheel event and set new diameter, then update?

                            QPainterPath RadioNode::shape() const
                            {
                                QPainterPath path;
                                path.addEllipse( -m_diameter * 0.5, -m_diameter * 0.5, m_diameter, m_diameter );
                                return path;
                            }
                            
                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by
                            #12

                            @JoeCFD
                            I think I am just wrong to have said it does not scale. I think it does. Playing with it now....

                            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