c
cordsac17. Oktober 2017 05:26

How can I open SVG file through QT

I'm trying to develop flowchart diagram application using QT with C++. I'm planing to design basic shapes of flowchart, such as rectangle, ellipse,polygon and line item(arrow).In this code I designed rectangle and ellipse items and content of the QGraphicView saved properly.But problem is I can't open .SVG file properly. Program open rectangle shapes only. How can I open other shapes?  such as  ellipse,polygon and line item(arrow).


I'm new to this QT with C++ application  development.So please help me to solve this problem.here with I attach sample .SVG file.

ReadSvg.cpp

#include "readsvg.h"
#include <QPen>
#include <QFile>
#include <QMessageBox>
#include <QDomDocument>
#include <QStringList>

ReadSVG::ReadSVG()
{

}

QList<QGraphicsRectItem *> ReadSVG::getElements(const QString filename)
{
    QList<QGraphicsRectItem *> rectList;    // We declare in the stack a list of rectangles

    QDomDocument doc;       // document object
    QFile file(filename);   // Open our SVG file
    // If it did not open or could not transfer content to QDocDocument
    if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
        return rectList;    // then return the list, but empty

    // Look in the document for all objects with the tag g
    QDomNodeList gList = doc.elementsByTagName("g");
    // We start to sort them out
    for (int i = 0; i < gList.size(); i++) {
        QDomNode gNode = gList.item(i);     // Select the node from the list
        QDomElement rectangle = gNode.firstChildElement("rect");    // And we search in it for an element with the tag rect

        // If the resulting elements are not zero, then
        if (rectangle.isNull()){
            continue;
        } else {
            // begin to form a rectangle
            QGraphicsRectItem *rect = new QGraphicsRectItem();
            // This flag makes the object moveable, it will be required for verification
            rect->setFlag(QGraphicsItem::ItemIsMovable);
            // We take sizes from the rect tag
            QDomElement gElement = gNode.toElement();
            rect->setRect(rectangle.attribute("x").toInt(),
                          rectangle.attribute("y").toInt(),
                          rectangle.attribute("width").toInt(),
                          rectangle.attribute("height").toInt());

            /*
               We take the parameters of the colors gNode from the node element
               yes yes yes ... it's from gNode, not from rectangle. These parameters are stored in the tag g
             */
            QColor fillColor(gElement.attribute("fill", "#ffffff"));    // fill color
            fillColor.setAlphaF(gElement.attribute("fill-opacity","0").toFloat());
            rect->setBrush(QBrush(fillColor));

            // as well as the color and thickness of the outline
            QColor strokeColor(gElement.attribute("stroke", "#000000"));
            strokeColor.setAlphaF(gElement.attribute("stroke-opacity").toFloat());

            rect->setPen(QPen(strokeColor,gElement.attribute("stroke-width", "0").toInt()));
            rectList.append(rect);  // add a rectangle to the list
        }
    }
    file.close();
    return rectList;
}

QList<QGraphicsEllipseItem*> ReadSVG::getEllipses(const QString filename)
{
    QList<QGraphicsEllipseItem *> ellipsesList;

    QDomDocument doc;
    QFile file(filename);

    if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
        return ellipsesList;

    QDomNodeList gList = doc.elementsByTagName("g");
    for (int i = 0; i < gList.size(); i++) {
        QDomNode gNode = gList.item(i);
        QDomElement ellipseElement = gNode.firstChildElement("ellipse");

        if (ellipseElement.isNull()){
            continue;
        } else {
            QGraphicsEllipseItem *ellipseItem = new QGraphicsEllipseItem();
            ellipseItem->setFlag(QGraphicsItem::ItemIsMovable);

            QDomElement gElement = gNode.toElement();
            ellipseItem->setRect(ellipseElement.attribute("cx").toFloat() - ellipseElement.attribute("rx").toFloat(),
                                 ellipseElement.attribute("cy").toFloat() - ellipseElement.attribute("ry").toFloat(),
                                 ellipseElement.attribute("rx").toFloat() * 2,
                                 ellipseElement.attribute("ry").toFloat() * 2);

            QColor fillColor(ellipseElement.attribute("style").split(";").at(0).split(":").at(1));
            ellipseItem->setBrush(QBrush(fillColor));

            QColor strokeColor(gElement.attribute("stroke", "#000000"));
            strokeColor.setAlphaF(gElement.attribute("stroke-opacity").toFloat());

            ellipseItem->setPen(QPen(strokeColor,gElement.attribute("stroke-width", "0").toInt()));
            ellipsesList.append(ellipseItem);
        }
    }
    file.close();
    return ellipsesList;
}

QRectF ReadSVG::getSizes(const QString filename)
{
    QDomDocument doc;       // initialize the QDomDocument object on the stack
    QFile file(filename);   // Open our SVG file
    // If it did not open or could not transfer content to QDocDocument
    if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
        return QRectF(0,0,200,200); // then return the values ​​for the default scene

    QDomNodeList list = doc.elementsByTagName("svg");
    if(list.length() > 0) {
        QDomElement svgElement = list.item(0).toElement();
        QStringList parameters = svgElement.attribute("viewBox").split(" ");
        return QRectF(parameters.at(0).toInt(),
                      parameters.at(1).toInt(),
                      parameters.at(2).toInt(),
                      parameters.at(3).toInt());
    }
    return QRectF(0,0,200,200);
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include "readsvg.h"

#include <QCursor>
#include <QFileDialog>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    scene = new QGraphicsScene(this);
    ui->graphicsView->setScene(scene);

    QBrush redBrush(Qt::red);
    QBrush blueBrush(Qt::blue);
    QPen blackPen(Qt::black);
    blackPen.setWidth(6);

    elipse = scene->addEllipse(10,10,100,100,blackPen,redBrush);
    rect = scene->addRect(-10,-10,100,100,blackPen,blueBrush);
    rect->setFlag(QGraphicsItem::ItemIsMovable, true);


}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()
{
    QString fileName= QFileDialog::getSaveFileName(this, "Save image", QCoreApplication::applicationDirPath(), "BMP Files (*.bmp);;JPEG (*.JPEG);;PNG (*.png)" );
        if (!fileName.isNull())
        {
            QPixmap pixMap = this->ui->graphicsView->grab();
            pixMap.save(fileName);
        }
}

void Widget::on_btnSave_clicked()
{
    // Заберём путь к файлу и его имененем, который будем создавать
    QString newPath = QFileDialog::getSaveFileName(this, trUtf8("Save SVG"),
        path, tr("SVG files (*.svg)"));

    if (newPath.isEmpty())
        return;

    path = newPath;

    QSvgGenerator generator;        // Создаём объект генератора файла
    generator.setFileName(path);    // Устанавливаем путь к файлу, куда будет сохраняться векторная графика
    generator.setSize(QSize(scene->width(), scene->height()));  // Устанавливаем размеры рабочей области документа в миллиметрах
    generator.setViewBox(QRect(0, 0, scene->width(), scene->height())); // Устанавливаем рабочую область в координатах
    generator.setTitle(trUtf8("SVG Example"));                          // Титульное название документа
    generator.setDescription(trUtf8("File created by SVG Example"));    // Описание документа

    // С помощью класса QPainter
    QPainter painter;
    painter.begin(&generator);  // Устанавливаем устройство/объект в котором будем производить отрисовку
    scene->render(&painter);    // Отрисовываем содержимое сцены с помощью painter в целевое устройство/объект
    painter.end();              // Заканчиваем отрисовку

    // По окончанию отрисовки получим векторный файл с содержимым графической сцены
}


void Widget::on_btnOpen_clicked()
{
    QString newPath = QFileDialog::getOpenFileName(this, trUtf8("Open SVG"),
                                                   path, tr("SVG files (*.svg)"));
    if (newPath.isEmpty())
        return;

    path = newPath;
    scene->clear();

    //scene->setSceneRect(ReadSVG::getSizes(path)); // Set the size of the graphic scene

    // Install the objects on the graphical scene, get them using the getElements
    /*foreach (QGraphicsRectItem *item, ReadSVG::getElements(path)) {
        QGraphicsRectItem *rect = item;
        scene->addItem(rect);
    }*/

    scene->setSceneRect(ReadSVG::getSizes(path));
    foreach (QGraphicsEllipseItem *itemE, ReadSVG::getEllipses(path)) {
        QGraphicsEllipseItem *elips = itemE;
        scene->addItem(elips);
    }


}
sample.svg
Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Stabiles Hosting des sozialen Netzwerks EVILEG. Wir empfehlen VDS-Hosting für Django-Projekte.

Magst du es? In sozialen Netzwerken teilen!

6
Evgenii Legotckoi
  • 17. Oktober 2017 06:01
  • Die Antwort wurde als Lösung markiert.

Hello.

Yes... This SVG file have another structure of tags.
Just see the following part of SVG via any text editor.
<g fill="#ff0000" fill-opacity="1" stroke="#000000" stroke-opacity="1" stroke-width="6" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,379,152)"
font-family="MS Shell Dlg 2" font-size="7.8" font-weight="400" font-style="normal" 
>
<circle cx="60" cy="60" r="50"/>
</g>
I wrote example for You for ellipse tag, because I had SVG file of another version (from Inkscape progam). But You have circle tag.

Therefore need to write some another code like this.
QList<QGraphicsEllipseItem*> SvgReader::getEllipses(const QString filename)
{
    QList<QGraphicsEllipseItem *> ellipsesList;

    QDomDocument doc;
    QFile file(filename);

    if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
        return ellipsesList;

    QDomNodeList gList = doc.elementsByTagName("g");
    for (int i = 0; i < gList.size(); i++) {
        QDomNode gNode = gList.item(i);
        QDomElement ellipseElement = gNode.firstChildElement("circle");

        if (ellipseElement.isNull()){
            continue;
        } else {
            QGraphicsEllipseItem *ellipseItem = new QGraphicsEllipseItem();
            ellipseItem->setFlag(QGraphicsItem::ItemIsMovable);

            QDomElement gElement = gNode.toElement();
            ellipseItem->setRect(ellipseElement.attribute("cx").toFloat() - ellipseElement.attribute("r").toFloat(),
                                 ellipseElement.attribute("cy").toFloat() - ellipseElement.attribute("r").toFloat(),
                                 ellipseElement.attribute("r").toFloat() * 2,
                                 ellipseElement.attribute("r").toFloat() * 2);

            QColor fillColor(gElement.attribute("fill", "#ffffff")); 
            fillColor.setAlphaF(gElement.attribute("fill-opacity","0").toFloat());
            rect->setBrush(QBrush(fillColor));

            QColor strokeColor(gElement.attribute("stroke", "#000000"));
            strokeColor.setAlphaF(gElement.attribute("stroke-opacity").toFloat());

            ellipseItem->setPen(QPen(strokeColor,gElement.attribute("stroke-width", "0").toInt()));
            ellipsesList.append(ellipseItem);
        }
    }
    file.close();
    return ellipsesList;
}
Check it, please.
I think it should work, but I haven`t opportunity to check this code now. If it will not work, just write about it, then I will check it after my job.
    c
    • 17. Oktober 2017 06:57

    Thank you very much sir,my problem solved :) Is this the way to do for other ? I mean polygon,line shape(arrow line)

      Evgenii Legotckoi
      • 17. Oktober 2017 07:20

      Yes. Just You need see xml structure of your svg file, tags for figures (polygon, paths, lines and so on) and realize same functions for all figures.

        c
        • 17. Oktober 2017 07:42

        Okay sir :) I'll do so

          Evgenii Legotckoi
          • 17. Oktober 2017 07:50
          • (bearbeitet)

          Good luck.
          If You will need some another advice, do not hesitate to ask a new question on this forum.

            c
            • 17. Oktober 2017 09:28

            Okay,Thank you sir :)

              Kommentare

              Nur autorisierte Benutzer können Kommentare posten.
              Bitte Anmelden oder Registrieren
              Letzte Kommentare
              A
              ALO1ZE19. Oktober 2024 08:19
              Fb3-Dateileser auf Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
              ИМ
              Игорь Максимов5. Oktober 2024 07:51
              Django – Lektion 064. So schreiben Sie eine Python-Markdown-Erweiterung Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
              d
              dblas55. Juli 2024 11:02
              QML - Lektion 016. SQLite-Datenbank und das Arbeiten damit in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
              k
              kmssr8. Februar 2024 18:43
              Qt Linux - Lektion 001. Autorun Qt-Anwendung unter Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
              Qt WinAPI - Lektion 007. Arbeiten mit ICMP-Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
              Jetzt im Forum diskutieren
              J
              JacobFib17. Oktober 2024 03:27
              добавить qlineseries в функции Пользователь может получить любые разъяснения по интересующим вопросам, касающимся обработки его персональных данных, обратившись к Оператору с помощью электронной почты https://topdecorpro.ru…
              JW
              Jhon Wick1. Oktober 2024 15:52
              Indian Food Restaurant In Columbus OH| Layla’s Kitchen Indian Restaurant If you're looking for a truly authentic https://www.laylaskitchenrestaurantohio.com/ , Layla’s Kitchen Indian Restaurant is your go-to destination. Located at 6152 Cleveland Ave, Colu…
              КГ
              Кирилл Гусарев27. September 2024 09:09
              Не запускается программа на Qt: точка входа в процедуру не найдена в библиотеке DLL Написал программу на C++ Qt в Qt Creator, сбилдил Release с помощью MinGW 64-bit, бинарнику напихал dll-ки с помощью windeployqt.exe. При попытке запуска моей сбилженной программы выдаёт три оши…
              F
              Fynjy22. Juli 2024 04:15
              при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

              Folgen Sie uns in sozialen Netzwerken