Search code examples
qtqwidgetqwebviewqgraphicssceneqtextbrowser

How to make a Qt interactive text editing widget


I want to develop an application with two main widgets one is a text editor and the other one is for graphic viewer.

enter image description here

The basic idea is to let the user hover over any block of code in the text area and the associated part of the drawing gets selected or highlighted.

For the graphic widget, after some research it seems QGraphicsScene fits the requirements the most, but I'm not sure what widget to use for the text editor such that it gives me a signal when hovering over any block of code (and also send a string parameter "id" of the block).

The reverse action is required too, so when the user choose to inspect element in the graphics view the text view is scrolled to view the associate block of code and highlight it (like in Google Chrome "Inspect Element" feature).


Solution

  • To highlight text when an object is hovered in scene you have to reimplement QGraphicsScene and QGraphicsItem (which one you going to use) to inform mainwindow to find and highlight text. Here is sample code to highlight text when an object hovered in scene I used QGraphicsPixmapItem:


    Graphic scene

     class GraphicScene : public QGraphicsScene
    {
        Q_OBJECT
    public:
        GraphicScene();
    
        void EmitItemHoverd(QString name)
        {
          emit SignalItemHovered(name);
        }
    
    
    signals:
        void SignalItemHovered(QString);
    };
    

    GraphicsItem :

    #include "GraphicScene.h"
    
    class GraphicItem : public QGraphicsPixmapItem
    {
        QString itemName;
        GraphicScene * scene;
    public:
        GraphicItem(GraphicScene *s, QString name);//name you can set from editor
    
        void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
    
    };
    GraphicItem::GraphicItem(GraphicScene *s, QString name)
    {
        scene = s;
        itemName = name;
        this->setAcceptHoverEvents(true);
    }
    
    void GraphicItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
    {
        scene->EmitItemHoverd(itemName);
    }
    

    in MainWindow constructor connect

    connect(scene,SIGNAL(SignalItemHovered(QString)),this,SLOT(OnItemHovered(QString)));
    

    Here is slot:

    void MainWindow::OnItemHovered(QString name)
    {
       ui->textEdit->find(name);
      QTextCursor tc = ui->textEdit->textCursor();
      tc.select(QTextCursor::WordUnderCursor);    
      ui->textEdit->find("}");
      QTextCursor tc1 = ui->textEdit->textCursor();
      tc1.select(QTextCursor::WordUnderCursor);
      int pos2 = tc1.selectionStart();
    
      tc.setPosition(pos2,QTextCursor::KeepAnchor);
      ui->textEdit->setTextCursor(tc);
    }
    

    and logic to draw:

        GraphicItem * item = new GraphicItem(scene,"Circle");
    
        QPixmap  map(50,50);
        QPainter * painter= new QPainter(&map);
        painter->setBrush(QBrush(Qt::red,Qt::SolidPattern));
        painter->drawEllipse(20,20,15,15);
        item->setPixmap(map);
    
        scene->addItem(item);
        ui->graphicsView->update();
        delete painter;
    

    NOTE: Using public EmitItemHoverd may be an issue here I used just for sake of explaining the logic you can make it protected with required changes.

    Yeah I knew its half of answer but opposite logic can be implimented based on above