running draw_polygon example in CGAl package in qt widget application












1















I try to following CGAL example in Qt widget application :
example



main.ccp:



#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv)
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}


mainwindow.ccp :



#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/draw_polyhedron.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;

void MainWindow::on_pushButton_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this,tr("Open .off model"), "/home", tr("*.off"));

draw_poly(fileName);
}

void MainWindow::draw_poly(QString fileName)
{
QByteArray inBytes;
const char *c;
inBytes = fileName.toUtf8();
c = inBytes.constData();
std::ifstream input(c);

if (!input || !(input >> mesh) || mesh.is_empty()) {
std::cerr << "Not a valid off file." << std::endl;
// return 1;
}

input >> mesh;

CGAL::draw(mesh);
}


when I ran it , it open dialog file to select .off file ,then it shows the following error:



QCoreApplication::exec: The event loop is already running


any help ,please ?










share|improve this question



























    1















    I try to following CGAL example in Qt widget application :
    example



    main.ccp:



    #include "mainwindow.h"
    #include <QApplication>

    int main(int argc, char *argv)
    {
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
    }


    mainwindow.ccp :



    #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
    #include <CGAL/Polyhedron_3.h>
    #include <CGAL/IO/Polyhedron_iostream.h>
    #include <CGAL/draw_polyhedron.h>
    #include <fstream>
    typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
    typedef CGAL::Polyhedron_3<Kernel> Polyhedron;

    void MainWindow::on_pushButton_clicked()
    {
    QString fileName = QFileDialog::getOpenFileName(this,tr("Open .off model"), "/home", tr("*.off"));

    draw_poly(fileName);
    }

    void MainWindow::draw_poly(QString fileName)
    {
    QByteArray inBytes;
    const char *c;
    inBytes = fileName.toUtf8();
    c = inBytes.constData();
    std::ifstream input(c);

    if (!input || !(input >> mesh) || mesh.is_empty()) {
    std::cerr << "Not a valid off file." << std::endl;
    // return 1;
    }

    input >> mesh;

    CGAL::draw(mesh);
    }


    when I ran it , it open dialog file to select .off file ,then it shows the following error:



    QCoreApplication::exec: The event loop is already running


    any help ,please ?










    share|improve this question

























      1












      1








      1








      I try to following CGAL example in Qt widget application :
      example



      main.ccp:



      #include "mainwindow.h"
      #include <QApplication>

      int main(int argc, char *argv)
      {
      QApplication a(argc, argv);
      MainWindow w;
      w.show();

      return a.exec();
      }


      mainwindow.ccp :



      #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
      #include <CGAL/Polyhedron_3.h>
      #include <CGAL/IO/Polyhedron_iostream.h>
      #include <CGAL/draw_polyhedron.h>
      #include <fstream>
      typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
      typedef CGAL::Polyhedron_3<Kernel> Polyhedron;

      void MainWindow::on_pushButton_clicked()
      {
      QString fileName = QFileDialog::getOpenFileName(this,tr("Open .off model"), "/home", tr("*.off"));

      draw_poly(fileName);
      }

      void MainWindow::draw_poly(QString fileName)
      {
      QByteArray inBytes;
      const char *c;
      inBytes = fileName.toUtf8();
      c = inBytes.constData();
      std::ifstream input(c);

      if (!input || !(input >> mesh) || mesh.is_empty()) {
      std::cerr << "Not a valid off file." << std::endl;
      // return 1;
      }

      input >> mesh;

      CGAL::draw(mesh);
      }


      when I ran it , it open dialog file to select .off file ,then it shows the following error:



      QCoreApplication::exec: The event loop is already running


      any help ,please ?










      share|improve this question














      I try to following CGAL example in Qt widget application :
      example



      main.ccp:



      #include "mainwindow.h"
      #include <QApplication>

      int main(int argc, char *argv)
      {
      QApplication a(argc, argv);
      MainWindow w;
      w.show();

      return a.exec();
      }


      mainwindow.ccp :



      #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
      #include <CGAL/Polyhedron_3.h>
      #include <CGAL/IO/Polyhedron_iostream.h>
      #include <CGAL/draw_polyhedron.h>
      #include <fstream>
      typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
      typedef CGAL::Polyhedron_3<Kernel> Polyhedron;

      void MainWindow::on_pushButton_clicked()
      {
      QString fileName = QFileDialog::getOpenFileName(this,tr("Open .off model"), "/home", tr("*.off"));

      draw_poly(fileName);
      }

      void MainWindow::draw_poly(QString fileName)
      {
      QByteArray inBytes;
      const char *c;
      inBytes = fileName.toUtf8();
      c = inBytes.constData();
      std::ifstream input(c);

      if (!input || !(input >> mesh) || mesh.is_empty()) {
      std::cerr << "Not a valid off file." << std::endl;
      // return 1;
      }

      input >> mesh;

      CGAL::draw(mesh);
      }


      when I ran it , it open dialog file to select .off file ,then it shows the following error:



      QCoreApplication::exec: The event loop is already running


      any help ,please ?







      c++ qt qt-creator fedora cgal






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 14 '18 at 10:48









      n.mn.m

      618




      618
























          2 Answers
          2






          active

          oldest

          votes


















          2














          I'm using Qt5 in daily business, and once considered CGAL as possible application base (without going further into this direction – not yet). Hence, this question made me curious.



          I digged through the source code of CGAL on github and found out why the error message



          QCoreApplication::exec: The event loop is already running


          occurs.



          For this, I copied the relevant lines from CGAL on github: Polyhedron/include/CGAL/draw_polyhedron.h:



          template<class Polyhedron, class ColorFunctor>
          void draw(const Polyhedron& apoly,
          const char* title,
          bool nofill,
          const ColorFunctor& fcolor)
          {
          #if defined(CGAL_TEST_SUITE)
          bool cgal_test_suite=true;
          #else
          bool cgal_test_suite=false;
          #endif

          if (!cgal_test_suite)
          {
          int argc=1;
          const char* argv[2]={"polyhedron_viewer",""};
          QApplication app(argc,const_cast<char**>(argv));
          SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
          mainwindow(app.activeWindow(), apoly, title, nofill, fcolor);
          mainwindow.show();
          app.exec();
          }
          }


          Looking at this source code, it becomes obvious that CGAL::draw() is a small ful-featured Qt application in itself which establishs its own QApplication instance. The OP in turn tried to embed the CGAL::draw() in her/his own Qt application. It is not allowed to instance any derivates of QCoreApplication more than once (according to Qt doc. of QApplication):




          For any GUI application using Qt, there is precisely one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time.




          (Emphasizing not mine.)



          The CGAL doc. provides an (even shorter) example in Polyhedron/draw_polyhedron.cpp to do this right:



          #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
          #include <CGAL/Polyhedron_3.h>
          #include <CGAL/IO/Polyhedron_iostream.h>
          #include <CGAL/draw_polyhedron.h>
          #include <fstream>
          typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
          typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
          int main(int argc, char* argv)
          {
          Polyhedron P;
          std::ifstream in1((argc>1)?argv[1]:"data/cross.off");
          in1 >> P;
          CGAL::draw(P);
          return EXIT_SUCCESS;
          }


          but there is no place to insert the QFileDialog at the right point.



          Hence, CGAL::draw() is the wrong tool for what OP (probably) intends to do – embed CGAL polyhedron rendering into a Qt application. For this, it is necessary to use the things directly which are called somewhere inside of CGAL::draw().



          So, this is what seems appropriate to me:

          making SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> a (main or child) widget in OPs Qt application.



          I then walked a bit through the github repo to find out from which Qt widget CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> is actually derived from and found the following inheritance:



          CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
          |
          V
          CGAL::Basic_viewer_qt
          |
          V
          CGAL::QGLViewer
          |
          +--------------+--------------+
          | |
          V V
          QOpenGLWidget QOpenGLFunctions


          So, CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> can be used like any QWidget (which involves making it the main window). It can become as well the center widget of a QMainWindow which gets a menu bar/tool bar with the QAction to open the QFileDialog, request a file path, open a file stream with this file path, and load a mesh from this file stream.



          There is another minor detail where I stumbled over: The CGAL::Polyhedron has to be given to the CGAL::SimplePolyhedronViewerQt in the constructor and by const reference. To consider this, it's IMHO necessary (after successful loading of mesh) to construct the CGAL::SimplePolyhedronViewerQt instance by new and set/add it to parent widget afterwards. If this is not acceptable it's probably necessary to go even deeper and replace the CGAL::SimplePolyhedronViewerQt by an own implementation, using the source code of the former as “cheat-sheet”.



          This is how such an application could look like:



          #include <fstream>

          #include <QtWidgets>

          #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
          #include <CGAL/Polyhedron_3.h>
          #include <CGAL/IO/Polyhedron_iostream.h>
          #include <CGAL/draw_polyhedron.h>

          typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
          typedef CGAL::Polyhedron_3<Kernel> Polyhedron;

          int main(int argc, char **argv)
          {
          qDebug() << "Qt Version:" << QT_VERSION_STR;
          QApplication app(argc, argv);
          CGAL::DefaultColorFunctorPolyhedron fColor;
          Polyhedron mesh;
          // setup UI
          QMainWindow qWin;
          QToolBar qToolbar;
          QAction qCmdLoad(QString::fromUtf8("Load File..."));
          qToolbar.addAction(&qCmdLoad);
          qWin.addToolBar(&qToolbar);
          qWin.show();
          // install signal handlers
          QObject::connect(&qCmdLoad, &QAction::triggered,
          [&qWin, &mesh, &fColor]() {
          const QString filePath = QFileDialog::getOpenFileName(
          &qWin,
          QString::fromUtf8("Open .off model"),
          QString::fromUtf8("/home"),
          QString::fromUtf8("*.off"));
          if (filePath.isEmpty()) return;
          std::ifstream fIn(filePath.toUtf8().data());
          if (!(fIn >> mesh) || mesh.is_empty()) {
          qDebug() << "Loading of" << filePath << "failed!";
          return;
          }
          qWin.setCentralWidget(
          new CGAL::SimplePolyhedronViewerQt<Polyhedron, CGAL::DefaultColorFunctorPolyhedron>(
          &qWin, mesh, "Basic Polyhedron Viewer", false, fColor));
          qWin.centralWidget()->show();
          });
          // runtime loop
          return app.exec();
          }


          Please, take this with a “grain of salt” – I've no CGAL at hand and couldn't compile/test the above code.






          share|improve this answer


























          • @n.m Did you try this sample code? Please, drop a comment if you cannot compile it. I did it carefully but, nevertheless, the compiler usually finds something to complain about.

            – Scheff
            Nov 15 '18 at 7:13











          • thanks a lot for your effort @Scheff

            – n.m
            Nov 15 '18 at 10:54











          • @n.m I read this as: You got it running? Nice to hear.

            – Scheff
            Nov 15 '18 at 10:55











          • unfortunately I still have a problem in using SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> ,it cannot be used as a type

            – n.m
            Nov 15 '18 at 11:10













          • qWin.setCentralWidget( new SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>( qWin, mesh, "Basic Polyhedron Viewer", false, fColor));

            – n.m
            Nov 15 '18 at 11:13



















          0














          CGAL::draw() already handles the Qt stuff. You are trying to open a mainwindow in another one. Just call CGAL::draw(mesh) in your main() function without anything else and it will work.



          EDIT: Which is exactly what Sheff explained in a much more detailed way.






          share|improve this answer
























          • it's working in main() but I want to use it in a GUI application so I want to use it in a method and call it

            – n.m
            Nov 15 '18 at 11:15











          • You cannot do that. You'll have to extract the significant code from Surface_mesh/include/CGAL/draw_surface_mesh.h and GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h and adapt it to your application.

            – mgimeno
            Nov 15 '18 at 15:06











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53298405%2frunning-draw-polygon-example-in-cgal-package-in-qt-widget-application%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          I'm using Qt5 in daily business, and once considered CGAL as possible application base (without going further into this direction – not yet). Hence, this question made me curious.



          I digged through the source code of CGAL on github and found out why the error message



          QCoreApplication::exec: The event loop is already running


          occurs.



          For this, I copied the relevant lines from CGAL on github: Polyhedron/include/CGAL/draw_polyhedron.h:



          template<class Polyhedron, class ColorFunctor>
          void draw(const Polyhedron& apoly,
          const char* title,
          bool nofill,
          const ColorFunctor& fcolor)
          {
          #if defined(CGAL_TEST_SUITE)
          bool cgal_test_suite=true;
          #else
          bool cgal_test_suite=false;
          #endif

          if (!cgal_test_suite)
          {
          int argc=1;
          const char* argv[2]={"polyhedron_viewer",""};
          QApplication app(argc,const_cast<char**>(argv));
          SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
          mainwindow(app.activeWindow(), apoly, title, nofill, fcolor);
          mainwindow.show();
          app.exec();
          }
          }


          Looking at this source code, it becomes obvious that CGAL::draw() is a small ful-featured Qt application in itself which establishs its own QApplication instance. The OP in turn tried to embed the CGAL::draw() in her/his own Qt application. It is not allowed to instance any derivates of QCoreApplication more than once (according to Qt doc. of QApplication):




          For any GUI application using Qt, there is precisely one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time.




          (Emphasizing not mine.)



          The CGAL doc. provides an (even shorter) example in Polyhedron/draw_polyhedron.cpp to do this right:



          #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
          #include <CGAL/Polyhedron_3.h>
          #include <CGAL/IO/Polyhedron_iostream.h>
          #include <CGAL/draw_polyhedron.h>
          #include <fstream>
          typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
          typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
          int main(int argc, char* argv)
          {
          Polyhedron P;
          std::ifstream in1((argc>1)?argv[1]:"data/cross.off");
          in1 >> P;
          CGAL::draw(P);
          return EXIT_SUCCESS;
          }


          but there is no place to insert the QFileDialog at the right point.



          Hence, CGAL::draw() is the wrong tool for what OP (probably) intends to do – embed CGAL polyhedron rendering into a Qt application. For this, it is necessary to use the things directly which are called somewhere inside of CGAL::draw().



          So, this is what seems appropriate to me:

          making SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> a (main or child) widget in OPs Qt application.



          I then walked a bit through the github repo to find out from which Qt widget CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> is actually derived from and found the following inheritance:



          CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
          |
          V
          CGAL::Basic_viewer_qt
          |
          V
          CGAL::QGLViewer
          |
          +--------------+--------------+
          | |
          V V
          QOpenGLWidget QOpenGLFunctions


          So, CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> can be used like any QWidget (which involves making it the main window). It can become as well the center widget of a QMainWindow which gets a menu bar/tool bar with the QAction to open the QFileDialog, request a file path, open a file stream with this file path, and load a mesh from this file stream.



          There is another minor detail where I stumbled over: The CGAL::Polyhedron has to be given to the CGAL::SimplePolyhedronViewerQt in the constructor and by const reference. To consider this, it's IMHO necessary (after successful loading of mesh) to construct the CGAL::SimplePolyhedronViewerQt instance by new and set/add it to parent widget afterwards. If this is not acceptable it's probably necessary to go even deeper and replace the CGAL::SimplePolyhedronViewerQt by an own implementation, using the source code of the former as “cheat-sheet”.



          This is how such an application could look like:



          #include <fstream>

          #include <QtWidgets>

          #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
          #include <CGAL/Polyhedron_3.h>
          #include <CGAL/IO/Polyhedron_iostream.h>
          #include <CGAL/draw_polyhedron.h>

          typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
          typedef CGAL::Polyhedron_3<Kernel> Polyhedron;

          int main(int argc, char **argv)
          {
          qDebug() << "Qt Version:" << QT_VERSION_STR;
          QApplication app(argc, argv);
          CGAL::DefaultColorFunctorPolyhedron fColor;
          Polyhedron mesh;
          // setup UI
          QMainWindow qWin;
          QToolBar qToolbar;
          QAction qCmdLoad(QString::fromUtf8("Load File..."));
          qToolbar.addAction(&qCmdLoad);
          qWin.addToolBar(&qToolbar);
          qWin.show();
          // install signal handlers
          QObject::connect(&qCmdLoad, &QAction::triggered,
          [&qWin, &mesh, &fColor]() {
          const QString filePath = QFileDialog::getOpenFileName(
          &qWin,
          QString::fromUtf8("Open .off model"),
          QString::fromUtf8("/home"),
          QString::fromUtf8("*.off"));
          if (filePath.isEmpty()) return;
          std::ifstream fIn(filePath.toUtf8().data());
          if (!(fIn >> mesh) || mesh.is_empty()) {
          qDebug() << "Loading of" << filePath << "failed!";
          return;
          }
          qWin.setCentralWidget(
          new CGAL::SimplePolyhedronViewerQt<Polyhedron, CGAL::DefaultColorFunctorPolyhedron>(
          &qWin, mesh, "Basic Polyhedron Viewer", false, fColor));
          qWin.centralWidget()->show();
          });
          // runtime loop
          return app.exec();
          }


          Please, take this with a “grain of salt” – I've no CGAL at hand and couldn't compile/test the above code.






          share|improve this answer


























          • @n.m Did you try this sample code? Please, drop a comment if you cannot compile it. I did it carefully but, nevertheless, the compiler usually finds something to complain about.

            – Scheff
            Nov 15 '18 at 7:13











          • thanks a lot for your effort @Scheff

            – n.m
            Nov 15 '18 at 10:54











          • @n.m I read this as: You got it running? Nice to hear.

            – Scheff
            Nov 15 '18 at 10:55











          • unfortunately I still have a problem in using SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> ,it cannot be used as a type

            – n.m
            Nov 15 '18 at 11:10













          • qWin.setCentralWidget( new SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>( qWin, mesh, "Basic Polyhedron Viewer", false, fColor));

            – n.m
            Nov 15 '18 at 11:13
















          2














          I'm using Qt5 in daily business, and once considered CGAL as possible application base (without going further into this direction – not yet). Hence, this question made me curious.



          I digged through the source code of CGAL on github and found out why the error message



          QCoreApplication::exec: The event loop is already running


          occurs.



          For this, I copied the relevant lines from CGAL on github: Polyhedron/include/CGAL/draw_polyhedron.h:



          template<class Polyhedron, class ColorFunctor>
          void draw(const Polyhedron& apoly,
          const char* title,
          bool nofill,
          const ColorFunctor& fcolor)
          {
          #if defined(CGAL_TEST_SUITE)
          bool cgal_test_suite=true;
          #else
          bool cgal_test_suite=false;
          #endif

          if (!cgal_test_suite)
          {
          int argc=1;
          const char* argv[2]={"polyhedron_viewer",""};
          QApplication app(argc,const_cast<char**>(argv));
          SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
          mainwindow(app.activeWindow(), apoly, title, nofill, fcolor);
          mainwindow.show();
          app.exec();
          }
          }


          Looking at this source code, it becomes obvious that CGAL::draw() is a small ful-featured Qt application in itself which establishs its own QApplication instance. The OP in turn tried to embed the CGAL::draw() in her/his own Qt application. It is not allowed to instance any derivates of QCoreApplication more than once (according to Qt doc. of QApplication):




          For any GUI application using Qt, there is precisely one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time.




          (Emphasizing not mine.)



          The CGAL doc. provides an (even shorter) example in Polyhedron/draw_polyhedron.cpp to do this right:



          #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
          #include <CGAL/Polyhedron_3.h>
          #include <CGAL/IO/Polyhedron_iostream.h>
          #include <CGAL/draw_polyhedron.h>
          #include <fstream>
          typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
          typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
          int main(int argc, char* argv)
          {
          Polyhedron P;
          std::ifstream in1((argc>1)?argv[1]:"data/cross.off");
          in1 >> P;
          CGAL::draw(P);
          return EXIT_SUCCESS;
          }


          but there is no place to insert the QFileDialog at the right point.



          Hence, CGAL::draw() is the wrong tool for what OP (probably) intends to do – embed CGAL polyhedron rendering into a Qt application. For this, it is necessary to use the things directly which are called somewhere inside of CGAL::draw().



          So, this is what seems appropriate to me:

          making SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> a (main or child) widget in OPs Qt application.



          I then walked a bit through the github repo to find out from which Qt widget CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> is actually derived from and found the following inheritance:



          CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
          |
          V
          CGAL::Basic_viewer_qt
          |
          V
          CGAL::QGLViewer
          |
          +--------------+--------------+
          | |
          V V
          QOpenGLWidget QOpenGLFunctions


          So, CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> can be used like any QWidget (which involves making it the main window). It can become as well the center widget of a QMainWindow which gets a menu bar/tool bar with the QAction to open the QFileDialog, request a file path, open a file stream with this file path, and load a mesh from this file stream.



          There is another minor detail where I stumbled over: The CGAL::Polyhedron has to be given to the CGAL::SimplePolyhedronViewerQt in the constructor and by const reference. To consider this, it's IMHO necessary (after successful loading of mesh) to construct the CGAL::SimplePolyhedronViewerQt instance by new and set/add it to parent widget afterwards. If this is not acceptable it's probably necessary to go even deeper and replace the CGAL::SimplePolyhedronViewerQt by an own implementation, using the source code of the former as “cheat-sheet”.



          This is how such an application could look like:



          #include <fstream>

          #include <QtWidgets>

          #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
          #include <CGAL/Polyhedron_3.h>
          #include <CGAL/IO/Polyhedron_iostream.h>
          #include <CGAL/draw_polyhedron.h>

          typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
          typedef CGAL::Polyhedron_3<Kernel> Polyhedron;

          int main(int argc, char **argv)
          {
          qDebug() << "Qt Version:" << QT_VERSION_STR;
          QApplication app(argc, argv);
          CGAL::DefaultColorFunctorPolyhedron fColor;
          Polyhedron mesh;
          // setup UI
          QMainWindow qWin;
          QToolBar qToolbar;
          QAction qCmdLoad(QString::fromUtf8("Load File..."));
          qToolbar.addAction(&qCmdLoad);
          qWin.addToolBar(&qToolbar);
          qWin.show();
          // install signal handlers
          QObject::connect(&qCmdLoad, &QAction::triggered,
          [&qWin, &mesh, &fColor]() {
          const QString filePath = QFileDialog::getOpenFileName(
          &qWin,
          QString::fromUtf8("Open .off model"),
          QString::fromUtf8("/home"),
          QString::fromUtf8("*.off"));
          if (filePath.isEmpty()) return;
          std::ifstream fIn(filePath.toUtf8().data());
          if (!(fIn >> mesh) || mesh.is_empty()) {
          qDebug() << "Loading of" << filePath << "failed!";
          return;
          }
          qWin.setCentralWidget(
          new CGAL::SimplePolyhedronViewerQt<Polyhedron, CGAL::DefaultColorFunctorPolyhedron>(
          &qWin, mesh, "Basic Polyhedron Viewer", false, fColor));
          qWin.centralWidget()->show();
          });
          // runtime loop
          return app.exec();
          }


          Please, take this with a “grain of salt” – I've no CGAL at hand and couldn't compile/test the above code.






          share|improve this answer


























          • @n.m Did you try this sample code? Please, drop a comment if you cannot compile it. I did it carefully but, nevertheless, the compiler usually finds something to complain about.

            – Scheff
            Nov 15 '18 at 7:13











          • thanks a lot for your effort @Scheff

            – n.m
            Nov 15 '18 at 10:54











          • @n.m I read this as: You got it running? Nice to hear.

            – Scheff
            Nov 15 '18 at 10:55











          • unfortunately I still have a problem in using SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> ,it cannot be used as a type

            – n.m
            Nov 15 '18 at 11:10













          • qWin.setCentralWidget( new SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>( qWin, mesh, "Basic Polyhedron Viewer", false, fColor));

            – n.m
            Nov 15 '18 at 11:13














          2












          2








          2







          I'm using Qt5 in daily business, and once considered CGAL as possible application base (without going further into this direction – not yet). Hence, this question made me curious.



          I digged through the source code of CGAL on github and found out why the error message



          QCoreApplication::exec: The event loop is already running


          occurs.



          For this, I copied the relevant lines from CGAL on github: Polyhedron/include/CGAL/draw_polyhedron.h:



          template<class Polyhedron, class ColorFunctor>
          void draw(const Polyhedron& apoly,
          const char* title,
          bool nofill,
          const ColorFunctor& fcolor)
          {
          #if defined(CGAL_TEST_SUITE)
          bool cgal_test_suite=true;
          #else
          bool cgal_test_suite=false;
          #endif

          if (!cgal_test_suite)
          {
          int argc=1;
          const char* argv[2]={"polyhedron_viewer",""};
          QApplication app(argc,const_cast<char**>(argv));
          SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
          mainwindow(app.activeWindow(), apoly, title, nofill, fcolor);
          mainwindow.show();
          app.exec();
          }
          }


          Looking at this source code, it becomes obvious that CGAL::draw() is a small ful-featured Qt application in itself which establishs its own QApplication instance. The OP in turn tried to embed the CGAL::draw() in her/his own Qt application. It is not allowed to instance any derivates of QCoreApplication more than once (according to Qt doc. of QApplication):




          For any GUI application using Qt, there is precisely one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time.




          (Emphasizing not mine.)



          The CGAL doc. provides an (even shorter) example in Polyhedron/draw_polyhedron.cpp to do this right:



          #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
          #include <CGAL/Polyhedron_3.h>
          #include <CGAL/IO/Polyhedron_iostream.h>
          #include <CGAL/draw_polyhedron.h>
          #include <fstream>
          typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
          typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
          int main(int argc, char* argv)
          {
          Polyhedron P;
          std::ifstream in1((argc>1)?argv[1]:"data/cross.off");
          in1 >> P;
          CGAL::draw(P);
          return EXIT_SUCCESS;
          }


          but there is no place to insert the QFileDialog at the right point.



          Hence, CGAL::draw() is the wrong tool for what OP (probably) intends to do – embed CGAL polyhedron rendering into a Qt application. For this, it is necessary to use the things directly which are called somewhere inside of CGAL::draw().



          So, this is what seems appropriate to me:

          making SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> a (main or child) widget in OPs Qt application.



          I then walked a bit through the github repo to find out from which Qt widget CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> is actually derived from and found the following inheritance:



          CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
          |
          V
          CGAL::Basic_viewer_qt
          |
          V
          CGAL::QGLViewer
          |
          +--------------+--------------+
          | |
          V V
          QOpenGLWidget QOpenGLFunctions


          So, CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> can be used like any QWidget (which involves making it the main window). It can become as well the center widget of a QMainWindow which gets a menu bar/tool bar with the QAction to open the QFileDialog, request a file path, open a file stream with this file path, and load a mesh from this file stream.



          There is another minor detail where I stumbled over: The CGAL::Polyhedron has to be given to the CGAL::SimplePolyhedronViewerQt in the constructor and by const reference. To consider this, it's IMHO necessary (after successful loading of mesh) to construct the CGAL::SimplePolyhedronViewerQt instance by new and set/add it to parent widget afterwards. If this is not acceptable it's probably necessary to go even deeper and replace the CGAL::SimplePolyhedronViewerQt by an own implementation, using the source code of the former as “cheat-sheet”.



          This is how such an application could look like:



          #include <fstream>

          #include <QtWidgets>

          #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
          #include <CGAL/Polyhedron_3.h>
          #include <CGAL/IO/Polyhedron_iostream.h>
          #include <CGAL/draw_polyhedron.h>

          typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
          typedef CGAL::Polyhedron_3<Kernel> Polyhedron;

          int main(int argc, char **argv)
          {
          qDebug() << "Qt Version:" << QT_VERSION_STR;
          QApplication app(argc, argv);
          CGAL::DefaultColorFunctorPolyhedron fColor;
          Polyhedron mesh;
          // setup UI
          QMainWindow qWin;
          QToolBar qToolbar;
          QAction qCmdLoad(QString::fromUtf8("Load File..."));
          qToolbar.addAction(&qCmdLoad);
          qWin.addToolBar(&qToolbar);
          qWin.show();
          // install signal handlers
          QObject::connect(&qCmdLoad, &QAction::triggered,
          [&qWin, &mesh, &fColor]() {
          const QString filePath = QFileDialog::getOpenFileName(
          &qWin,
          QString::fromUtf8("Open .off model"),
          QString::fromUtf8("/home"),
          QString::fromUtf8("*.off"));
          if (filePath.isEmpty()) return;
          std::ifstream fIn(filePath.toUtf8().data());
          if (!(fIn >> mesh) || mesh.is_empty()) {
          qDebug() << "Loading of" << filePath << "failed!";
          return;
          }
          qWin.setCentralWidget(
          new CGAL::SimplePolyhedronViewerQt<Polyhedron, CGAL::DefaultColorFunctorPolyhedron>(
          &qWin, mesh, "Basic Polyhedron Viewer", false, fColor));
          qWin.centralWidget()->show();
          });
          // runtime loop
          return app.exec();
          }


          Please, take this with a “grain of salt” – I've no CGAL at hand and couldn't compile/test the above code.






          share|improve this answer















          I'm using Qt5 in daily business, and once considered CGAL as possible application base (without going further into this direction – not yet). Hence, this question made me curious.



          I digged through the source code of CGAL on github and found out why the error message



          QCoreApplication::exec: The event loop is already running


          occurs.



          For this, I copied the relevant lines from CGAL on github: Polyhedron/include/CGAL/draw_polyhedron.h:



          template<class Polyhedron, class ColorFunctor>
          void draw(const Polyhedron& apoly,
          const char* title,
          bool nofill,
          const ColorFunctor& fcolor)
          {
          #if defined(CGAL_TEST_SUITE)
          bool cgal_test_suite=true;
          #else
          bool cgal_test_suite=false;
          #endif

          if (!cgal_test_suite)
          {
          int argc=1;
          const char* argv[2]={"polyhedron_viewer",""};
          QApplication app(argc,const_cast<char**>(argv));
          SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
          mainwindow(app.activeWindow(), apoly, title, nofill, fcolor);
          mainwindow.show();
          app.exec();
          }
          }


          Looking at this source code, it becomes obvious that CGAL::draw() is a small ful-featured Qt application in itself which establishs its own QApplication instance. The OP in turn tried to embed the CGAL::draw() in her/his own Qt application. It is not allowed to instance any derivates of QCoreApplication more than once (according to Qt doc. of QApplication):




          For any GUI application using Qt, there is precisely one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time.




          (Emphasizing not mine.)



          The CGAL doc. provides an (even shorter) example in Polyhedron/draw_polyhedron.cpp to do this right:



          #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
          #include <CGAL/Polyhedron_3.h>
          #include <CGAL/IO/Polyhedron_iostream.h>
          #include <CGAL/draw_polyhedron.h>
          #include <fstream>
          typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
          typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
          int main(int argc, char* argv)
          {
          Polyhedron P;
          std::ifstream in1((argc>1)?argv[1]:"data/cross.off");
          in1 >> P;
          CGAL::draw(P);
          return EXIT_SUCCESS;
          }


          but there is no place to insert the QFileDialog at the right point.



          Hence, CGAL::draw() is the wrong tool for what OP (probably) intends to do – embed CGAL polyhedron rendering into a Qt application. For this, it is necessary to use the things directly which are called somewhere inside of CGAL::draw().



          So, this is what seems appropriate to me:

          making SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> a (main or child) widget in OPs Qt application.



          I then walked a bit through the github repo to find out from which Qt widget CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> is actually derived from and found the following inheritance:



          CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>
          |
          V
          CGAL::Basic_viewer_qt
          |
          V
          CGAL::QGLViewer
          |
          +--------------+--------------+
          | |
          V V
          QOpenGLWidget QOpenGLFunctions


          So, CGAL::SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> can be used like any QWidget (which involves making it the main window). It can become as well the center widget of a QMainWindow which gets a menu bar/tool bar with the QAction to open the QFileDialog, request a file path, open a file stream with this file path, and load a mesh from this file stream.



          There is another minor detail where I stumbled over: The CGAL::Polyhedron has to be given to the CGAL::SimplePolyhedronViewerQt in the constructor and by const reference. To consider this, it's IMHO necessary (after successful loading of mesh) to construct the CGAL::SimplePolyhedronViewerQt instance by new and set/add it to parent widget afterwards. If this is not acceptable it's probably necessary to go even deeper and replace the CGAL::SimplePolyhedronViewerQt by an own implementation, using the source code of the former as “cheat-sheet”.



          This is how such an application could look like:



          #include <fstream>

          #include <QtWidgets>

          #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
          #include <CGAL/Polyhedron_3.h>
          #include <CGAL/IO/Polyhedron_iostream.h>
          #include <CGAL/draw_polyhedron.h>

          typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
          typedef CGAL::Polyhedron_3<Kernel> Polyhedron;

          int main(int argc, char **argv)
          {
          qDebug() << "Qt Version:" << QT_VERSION_STR;
          QApplication app(argc, argv);
          CGAL::DefaultColorFunctorPolyhedron fColor;
          Polyhedron mesh;
          // setup UI
          QMainWindow qWin;
          QToolBar qToolbar;
          QAction qCmdLoad(QString::fromUtf8("Load File..."));
          qToolbar.addAction(&qCmdLoad);
          qWin.addToolBar(&qToolbar);
          qWin.show();
          // install signal handlers
          QObject::connect(&qCmdLoad, &QAction::triggered,
          [&qWin, &mesh, &fColor]() {
          const QString filePath = QFileDialog::getOpenFileName(
          &qWin,
          QString::fromUtf8("Open .off model"),
          QString::fromUtf8("/home"),
          QString::fromUtf8("*.off"));
          if (filePath.isEmpty()) return;
          std::ifstream fIn(filePath.toUtf8().data());
          if (!(fIn >> mesh) || mesh.is_empty()) {
          qDebug() << "Loading of" << filePath << "failed!";
          return;
          }
          qWin.setCentralWidget(
          new CGAL::SimplePolyhedronViewerQt<Polyhedron, CGAL::DefaultColorFunctorPolyhedron>(
          &qWin, mesh, "Basic Polyhedron Viewer", false, fColor));
          qWin.centralWidget()->show();
          });
          // runtime loop
          return app.exec();
          }


          Please, take this with a “grain of salt” – I've no CGAL at hand and couldn't compile/test the above code.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 17 '18 at 23:30

























          answered Nov 14 '18 at 11:38









          ScheffScheff

          7,82021325




          7,82021325













          • @n.m Did you try this sample code? Please, drop a comment if you cannot compile it. I did it carefully but, nevertheless, the compiler usually finds something to complain about.

            – Scheff
            Nov 15 '18 at 7:13











          • thanks a lot for your effort @Scheff

            – n.m
            Nov 15 '18 at 10:54











          • @n.m I read this as: You got it running? Nice to hear.

            – Scheff
            Nov 15 '18 at 10:55











          • unfortunately I still have a problem in using SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> ,it cannot be used as a type

            – n.m
            Nov 15 '18 at 11:10













          • qWin.setCentralWidget( new SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>( qWin, mesh, "Basic Polyhedron Viewer", false, fColor));

            – n.m
            Nov 15 '18 at 11:13



















          • @n.m Did you try this sample code? Please, drop a comment if you cannot compile it. I did it carefully but, nevertheless, the compiler usually finds something to complain about.

            – Scheff
            Nov 15 '18 at 7:13











          • thanks a lot for your effort @Scheff

            – n.m
            Nov 15 '18 at 10:54











          • @n.m I read this as: You got it running? Nice to hear.

            – Scheff
            Nov 15 '18 at 10:55











          • unfortunately I still have a problem in using SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> ,it cannot be used as a type

            – n.m
            Nov 15 '18 at 11:10













          • qWin.setCentralWidget( new SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>( qWin, mesh, "Basic Polyhedron Viewer", false, fColor));

            – n.m
            Nov 15 '18 at 11:13

















          @n.m Did you try this sample code? Please, drop a comment if you cannot compile it. I did it carefully but, nevertheless, the compiler usually finds something to complain about.

          – Scheff
          Nov 15 '18 at 7:13





          @n.m Did you try this sample code? Please, drop a comment if you cannot compile it. I did it carefully but, nevertheless, the compiler usually finds something to complain about.

          – Scheff
          Nov 15 '18 at 7:13













          thanks a lot for your effort @Scheff

          – n.m
          Nov 15 '18 at 10:54





          thanks a lot for your effort @Scheff

          – n.m
          Nov 15 '18 at 10:54













          @n.m I read this as: You got it running? Nice to hear.

          – Scheff
          Nov 15 '18 at 10:55





          @n.m I read this as: You got it running? Nice to hear.

          – Scheff
          Nov 15 '18 at 10:55













          unfortunately I still have a problem in using SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> ,it cannot be used as a type

          – n.m
          Nov 15 '18 at 11:10







          unfortunately I still have a problem in using SimplePolyhedronViewerQt<Polyhedron, ColorFunctor> ,it cannot be used as a type

          – n.m
          Nov 15 '18 at 11:10















          qWin.setCentralWidget( new SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>( qWin, mesh, "Basic Polyhedron Viewer", false, fColor));

          – n.m
          Nov 15 '18 at 11:13





          qWin.setCentralWidget( new SimplePolyhedronViewerQt<Polyhedron, ColorFunctor>( qWin, mesh, "Basic Polyhedron Viewer", false, fColor));

          – n.m
          Nov 15 '18 at 11:13













          0














          CGAL::draw() already handles the Qt stuff. You are trying to open a mainwindow in another one. Just call CGAL::draw(mesh) in your main() function without anything else and it will work.



          EDIT: Which is exactly what Sheff explained in a much more detailed way.






          share|improve this answer
























          • it's working in main() but I want to use it in a GUI application so I want to use it in a method and call it

            – n.m
            Nov 15 '18 at 11:15











          • You cannot do that. You'll have to extract the significant code from Surface_mesh/include/CGAL/draw_surface_mesh.h and GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h and adapt it to your application.

            – mgimeno
            Nov 15 '18 at 15:06
















          0














          CGAL::draw() already handles the Qt stuff. You are trying to open a mainwindow in another one. Just call CGAL::draw(mesh) in your main() function without anything else and it will work.



          EDIT: Which is exactly what Sheff explained in a much more detailed way.






          share|improve this answer
























          • it's working in main() but I want to use it in a GUI application so I want to use it in a method and call it

            – n.m
            Nov 15 '18 at 11:15











          • You cannot do that. You'll have to extract the significant code from Surface_mesh/include/CGAL/draw_surface_mesh.h and GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h and adapt it to your application.

            – mgimeno
            Nov 15 '18 at 15:06














          0












          0








          0







          CGAL::draw() already handles the Qt stuff. You are trying to open a mainwindow in another one. Just call CGAL::draw(mesh) in your main() function without anything else and it will work.



          EDIT: Which is exactly what Sheff explained in a much more detailed way.






          share|improve this answer













          CGAL::draw() already handles the Qt stuff. You are trying to open a mainwindow in another one. Just call CGAL::draw(mesh) in your main() function without anything else and it will work.



          EDIT: Which is exactly what Sheff explained in a much more detailed way.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 15 '18 at 8:31









          mgimenomgimeno

          1214




          1214













          • it's working in main() but I want to use it in a GUI application so I want to use it in a method and call it

            – n.m
            Nov 15 '18 at 11:15











          • You cannot do that. You'll have to extract the significant code from Surface_mesh/include/CGAL/draw_surface_mesh.h and GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h and adapt it to your application.

            – mgimeno
            Nov 15 '18 at 15:06



















          • it's working in main() but I want to use it in a GUI application so I want to use it in a method and call it

            – n.m
            Nov 15 '18 at 11:15











          • You cannot do that. You'll have to extract the significant code from Surface_mesh/include/CGAL/draw_surface_mesh.h and GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h and adapt it to your application.

            – mgimeno
            Nov 15 '18 at 15:06

















          it's working in main() but I want to use it in a GUI application so I want to use it in a method and call it

          – n.m
          Nov 15 '18 at 11:15





          it's working in main() but I want to use it in a GUI application so I want to use it in a method and call it

          – n.m
          Nov 15 '18 at 11:15













          You cannot do that. You'll have to extract the significant code from Surface_mesh/include/CGAL/draw_surface_mesh.h and GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h and adapt it to your application.

          – mgimeno
          Nov 15 '18 at 15:06





          You cannot do that. You'll have to extract the significant code from Surface_mesh/include/CGAL/draw_surface_mesh.h and GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h and adapt it to your application.

          – mgimeno
          Nov 15 '18 at 15:06


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53298405%2frunning-draw-polygon-example-in-cgal-package-in-qt-widget-application%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          List item for chat from Array inside array React Native

          Thiostrepton

          Caerphilly