c
cordsac17 октября 2017 г. 5: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
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

6
Evgenii Legotckoi
  • 17 октября 2017 г. 6:01
  • Ответ был помечен как решение.

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 октября 2017 г. 6: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 октября 2017 г. 7: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 октября 2017 г. 7:42

        Okay sir :) I'll do so

          Evgenii Legotckoi
          • 17 октября 2017 г. 7:50
          • (ред.)

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

            c
            • 17 октября 2017 г. 9:28

            Okay,Thank you sir :)

              Комментарии

              Только авторизованные пользователи могут публиковать комментарии.
              Пожалуйста, авторизуйтесь или зарегистрируйтесь
              AD

              C++ - Тест 004. Указатели, Массивы и Циклы

              • Результат:50баллов,
              • Очки рейтинга-4
              m
              • molni99
              • 26 октября 2024 г. 9:37

              C++ - Тест 004. Указатели, Массивы и Циклы

              • Результат:80баллов,
              • Очки рейтинга4
              m
              • molni99
              • 26 октября 2024 г. 9:29

              C++ - Тест 004. Указатели, Массивы и Циклы

              • Результат:20баллов,
              • Очки рейтинга-10
              Последние комментарии
              i
              innorwall14 ноября 2024 г. 8:03
              Как написать игру на Qt - Урок 3. Взаимодействие с другими объектами what is priligy tablets What happens during the LASIK surgery process
              i
              innorwall14 ноября 2024 г. 5:09
              Использование переменных объявленных в CMakeLists.txt внутри C++ файлов where can i buy priligy online safely Tom Platz How about things like we read about in the magazines like roid rage and does that really
              i
              innorwall12 ноября 2024 г. 7:12
              Django - Урок 055. Как написать функционал auto populate field Freckles because of several brand names retin a, atralin buy generic priligy
              i
              innorwall12 ноября 2024 г. 3:23
              QML - Урок 035. Использование перечислений в QML без C++ priligy cvs 24 Together with antibiotics such as amphotericin B 10, griseofulvin 11 and streptomycin 12, chloramphenicol 9 is in the World Health Organisation s List of Essential Medici…
              i
              innorwall12 ноября 2024 г. 0:50
              Qt/C++ - Урок 052. Кастомизация Qt Аудио плеера в стиле AIMP It decreases stress, supports hormone balance, and regulates and increases blood flow to the reproductive organs buy priligy online safe Promising data were reported in a PDX model re…
              Сейчас обсуждают на форуме
              i
              innorwall14 ноября 2024 г. 9:39
              добавить qlineseries в функции Listen intently to what Jerry says about Conditional Acceptance because that s the bargaining chip in the song and dance you will have to engage in to protect yourself and your family from AMI S…
              i
              innorwall11 ноября 2024 г. 19:55
              Всё ещё разбираюсь с кешем. priligy walgreens levitra dulcolax carbs The third ring was found to be made up of ultra relativistic electrons, which are also present in both the outer and inner rings
              9
              9Anonim25 октября 2024 г. 17:10
              Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
              ИМ
              Игорь Максимов3 октября 2024 г. 12:05
              Реализация навигации по разделам Спасибо Евгений!

              Следите за нами в социальных сетях