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. Custom IP Editor Plugin crashes in Application
QtWS25 Last Chance

Custom IP Editor Plugin crashes in Application

Scheduled Pinned Locked Moved Solved General and Desktop
ip editorcustomplugingui development
7 Posts 2 Posters 2.6k Views
  • 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.
  • Sh1gsS Offline
    Sh1gsS Offline
    Sh1gs
    wrote on last edited by
    #1

    Hello,

    Due to the nature of my job, I can't post a whole lot of code in the topics I create, however, for this case, I was given permission to type out my code since no one else in my department has a lot of experience with this.

    Anyhoo, I took a lot of inspiration from this post. The biggest difference being that I am adding touch screen functionality with a popup number pad. Please bare with me as I'm still learning the intricacies that QT offers for custom plugins and such. If you see a better way to do things, please let me know.

    Now, the problem I am having is, I create a custom IP Editor plugin (I will provide the code shortly). I add the plugin to my application by including the .pri. I also put the .dll in the qt/plugins/designer folder. When I run my application and I go to use my plugin, it works fine for a time, and then it crashes. I've pulled my hair out trying to figure out why and I just can't seem to get it.

    My plugin contains the following files:

    numpad.h

    #include <QWidgets>
    
    namespace Ui{
    class Numpad;
    }
    
    class NumPad : public QWidget
    {
         Q_OBJECT
    
    public:
         explicit NumPad(QWidget *parent = 0);
         QPushButton *seven, *eight, *nine, *four, *five, *six, *one, *two, *three, *zero, *dot, *del, *done;
         ~NumPad();
    
    signals:
         void sendData(const QString &text);
    
    private slots:
         void btnClicked();
    
    private:
         Ui::NumPad *ui;
         void createNumPad();
    };
    

    I also have a numpad.ui file. It contains a QFrame named numPad. In the .cpp file, the buttons are being added to that QFrame. Admittedly, I could've added the buttons manually and only had the one function that sends the text, I may amend this later.

    numpad.cpp

    #include "numpad.h"
    #include "ui_numpad.h"
    
    NumPad::NumPad(QWidget *parent) : QWidget(parent), ui(new Ui::NumPad)
    {
         ui->setupUI(this);
         createNumPad();
    }
    
    void NumPad::createNumPad()
    {
         seven = new QPushButton(tr("7"), ui->numPad);
         seven->setFocusPolicy(Qt::NoFocus);
         seven->setStyleSheet("font:bold; font-size:12pt;");
         seven->setGeometry(0,0,61,36);
    ...
         del = new QPushButton(tr("DEL"), ui->numPad);
         del->setFocusPolicy(Qt::NoFocus);
         del->setStyleSheet("font:bold; font-size:12pt;");
         del->setGeometry(0,144,183,36);
         del->setAutoRepeat(true);
    
         connect(seven, &QPushButton::clicked, this, &NumPad::btnClicked);
    ...
    }
    
    void NumPad::btnClicked()
    {
         QPushButton *btn = qobject_cast<QPushButton*>(sender());
         emit this->sendData(btn->text());
    }
    
    NumPad::~NumPad
    {
         delete ui;
    }
    

    In my ipeditor.ui I have 4 LineEdits, and 3 Labels so it looks similar to ___.___.___.___ I have a frame around all of those so it looks like a nice cohesive unit, rather than 7 different widgets. Then my IpEditor files are as follows:

    ipeditor.h

    #include <QWidgets>
    #include "numpad.h"
    
    namespace Ui{
    class IPEditor;
    }
    
    class IPEditor : public QWidget
    {
         Q_OBJECT
    
    public:
         explicit IPEditor(QWidget *parent = 0);
         ~IPEditor();
    
    public slots:
         void receiveData(const QString &text);
         void txtChanged(QLineEdit *input);
    
    signals:
         void sigTxtChanged(QLineEdit *input);
    
    protected:
         bool eventFilter(QObject *obj, QEvent *e);
    
    private:
         Ui::IPEditor *ui;
         class Numpad *num;
         QLineEdit *curEdit;
         QList<QLineEdit*> leList;
         void movNextLE(int i);
         void movPrevLE(int i);
         void popupNumPad();
         void setupIP();
    };
    

    ipeditor.cpp

    #include "ipeditor.h"
    #include "ui_ipeditor.h"
    
    IPEditor::IPEditor(QWidget *parent) : QWidget(parent), ui(new Ui::IPEditor)
    {
         ui->setupUI(this);
         this->setFixedSize(183,32);
         leList << ui->firstOct << ui->secondOct << ui->thirdOct << ui->fourthOct; //putting my ui LineEdits in a list
         setupIP();
    }
    
    void IPEditor::setupIP()
    {
    //Upon initialization, the IP Editor is empty, and only allows the user to click on the first LineEdit
         for(int i = 0; i != leList.size(); i++)
           if(leList[i]->text.isEmpty(){
             leList[i]->setFocusPolicy(Qt::NoFocus);
             leList[i]->setReadOnly(true);
             leList[i]->setMaxLength(3);
             leList[i]->setValidator(new QIntValidator(0,255, this));
           }
           leList[0]->setFocusPolicy(Qt::ClickFocus);
           leList[0]->setReadOnly(false);
           leList[i]->installEventFilter(this);
         }
         connect(this, SIGNAL(sigTxtChangedd(QLineEdit*)), this, SLOT(txtChanged(QLineEdit*)), Qt::QueuedConnection);
    }
    
    bool IPEditor::eventFilter(QObject *obj, QEvent *e)
    {
         if(e->type() == QEvent::FocusIn){
           curEdit = qobject_cast<QLineEdit*>(obj);
    //this assumes the user has closed the popupnumpad and intends to change one of the LineEdits
           if(!curEdit->text.isEmpty(){ 
             if(num->isVisible())
               num->close();
           }
           popupNumPad();
         }
         else if(e->type() == QEvent::KeyPress){
           QKeyEvent *leEvent = static_cast<QKeyEvent*>(e);
           for(int i=0; i != leList.size(); i++){
             QLineEdit *input = leList[i];
             if(input == obj){
               switch(leEvent->key()){
               case Qt::Key_0:
                 if(input->text().isEmpty() || input->text() == "0")
                   movNextLE(i);
                 emit txtChanged(input);
                 break;
               case Qt::Key_Backspace:
                 if(input->text().isEmpty() || input->cursorPosition() == 0)
                   movPrevLE(i);
                 break;
               case Qt::Key_Period:
                 movNextLE(i);
                 break;
               case Qt::Key_Tab:
                 movNextLE(i);
                 return true;
                 break;
               case Qt::Key_Return:
                 num->close();
                 input->clearFocus();
                 input->setFocusPolicy(Qt::ClickFocus);
                 return true;
                 break;
               case Qt::Key_Enter:
                 num->close();
                 input->clearFocus();
                 input->setFocusPolicy(Qt::ClickFocus);
                 break;
               case Qt::Key_Left:
                 if(input->cursorPosition == 0)
                   movPrevLE(i);
                 break;
               case Qt::Key_Right:
                 if(input->text().isEmpty() || input->text().size() == input->cursorPosition()))
                   movNextLE(i);
               default:
                 emit txtChanged(input);
                 break;
               }
             }
           }
         }
         return QOBject::eventFilter(obj, e);
    }
    
    void IPEditor::popupNumPad()
    {
    //calculates geometry of parent application and will popup the numberpad above or below the IP Editor
         num = new NumPad(parentWidget());
         QRect guiArea = parentWidget()->geometry();
         QPoint point(this->geometry().x(), this->geometry().y() + ui->ipFrame->height());
         QRect frame = num->geometry();
    
         if(point.y() + num->height() > guiArea.bottom()){
           frame.setX(point.x());
           frame.setY(point.y() - ui->ipFrame->height() - num->height());
           num->setGeometry(frame.x(), frame.y(), num->width(), num->height());
           connect(num, SIGNAL(sendData(QString)), this, SLOT(receiveData(QString)));
           num->show();
         }
         else{
           frame.setX(point.x());
           frame.setY(point.y());
           num->setGeometry(frame.x(), frame.y(), num->width(), num->height());
           connect(num, SIGNAL(sendData(QString)), this, SLOT(receiveData(QString)));
           num->show();
        }
        num->setAttribute(Qt::WA_DeleteOnClose);
    }
    
    void IPEditor::receiveData(const QString &text)
    {
         if(text == "DEL"){
           QKeyEvent *event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier, text, true);
           QApplication::sendEvent(this, event);
           QApplication::postEvent(curEdit, event);
           QKeyEvent *rE = new QKeyEvent(QEvent::KeyRelease, Qt::Key_Backspace, Qt::NoModifier, text, true);
           QApplication::sendEvent(this, rE);
           QApplication::postEvent(curEdit, rE;
         }
         else if(text == "DONE"){
           QKeyEvent *event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier, text);
           QApplication::sendEvent(this, event);
           QApplication::postEvent(curEdit, event);
         }
         else if(text == "."){
           QKeyEvent *event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Period, Qt::NoModifier, text);
           QApplication::sendEvent(this, event);
           QApplication::postEvent(curEdit, event);
         }
         else if(text == "0"){
           QKeyEvent *event = new QKeyEvent(QEvent::KeyPress, Qt::Key_0, Qt::NoModifier, text);
           QApplication::sendEvent(this, event);
           QApplication::postEvent(curEdit, event);
         }
         else{
           QKeyEvent *event = new QKeyEvent(QEvent::KeyPress, 0, Qt::NoModifier, text);
           QApplication::sendEvent(this, event);
           QApplication::postEvent(curEdit, event);
         }
    }
    
    void IPEditor::txtChanged(QLineEdit *input)
    {
         for(int i = 0; i != leList.size(); i++){
           if(input == leList[i]{
             if((input->text().size() == 2 && input->text().size() == input->cursorPosition()) || input->text() == "0"){
               if(i+1 != leList.size())
                 movNextLE(i);
             }
           }
         }
    }
    
    void IPEditor::movNextLE(int i)
    {
         if(i+1 != leList.size()){
           num->close();
           leList[i+1]->setFocus();
           leList[i+1]->setReadOnly(false);
           leList[i+1]->setFocusPolicy(Qt::ClickFocus);
           leList[i+1]->setCursorPosition(0);
           leList[i+1]->selectAll();
         }
    }
    
    void IPEditor::movPrevLE(int i)
    {
         if(i!=0){ //this was added in the event that the user wanted to clear the IP Editor
           if(leList[i]->text().isEmpty()){
             leList[i]->setReadOnly(true);
             leList[i]->setFocusPolicy(Qt::NoFocus);
           }
         num->close();
         leList[i-1]->setFocus();
         leList[i-1]->setCursorPosition(leList[i-1]->text().size());
         }
    }
    
    IPEditor::~IPEditor()
    {
         delete ui;
    }
    

    I know it's really clunky, and can be improved. What I'm having trouble is when I use this plugin in an application, say I enter an IP Address 123.12.15.5 and I close the popup number pad, if I click on any of the LineEdits to change the mask, it crashes. But it doesn't always crash after clicking a LineEdit immediately. Sometimes it's the 4th or 5th LineEdit that I click that it'll crash. I don't understand. I THINK it has something to do with the Focus of each LineEdit creating an instance of the popup numberpad and then closing/deleting it when another LineEdit gains focus. So, I'm not sure if I should instead do something like
    num->hide(); and then deleteLater

    Any insight would be appreciated. I sincerely apologize if this is jumbled, but I will do my best to clarify any questions you have.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Can you post the stack trace of your crash ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      Sh1gsS 1 Reply Last reply
      1
      • SGaistS SGaist

        Hi,

        Can you post the stack trace of your crash ?

        Sh1gsS Offline
        Sh1gsS Offline
        Sh1gs
        wrote on last edited by
        #3

        Hello @SGaist

        Please forgive my noob of a question, how do I get the stack trace? I'm using Windows.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          When running Qt Creator and your app crashes it shows a window at the bottom with the call stack. You need to use a debug build of your app.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          Sh1gsS 1 Reply Last reply
          0
          • SGaistS SGaist

            When running Qt Creator and your app crashes it shows a window at the bottom with the call stack. You need to use a debug build of your app.

            Sh1gsS Offline
            Sh1gsS Offline
            Sh1gs
            wrote on last edited by
            #5

            @SGaist

            It seems that I get a segmentation fault when it gets to my eventFilter with the line

            if(num->isVisible())
            

            My intention here is to check if a numpad already exists, for example, moving between LineEdits that already have text in them, so that another numpad isn't created. If I take this line out completely, my numpad stays open and won't close even when "Done" or "Enter" is pressed.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Didn't you used to delete your numpad object ? If so you are likely trying to access a dangling pointer.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              Sh1gsS 1 Reply Last reply
              1
              • SGaistS SGaist

                Didn't you used to delete your numpad object ? If so you are likely trying to access a dangling pointer.

                Sh1gsS Offline
                Sh1gsS Offline
                Sh1gs
                wrote on last edited by
                #7

                @SGaist

                Ok, after fiddling around with debugging and testing things, I believe I have solved it. So my thought process was the user inputs an IP Address 123.123.123.123 and before closing the popup numberpad, clicks on the different LineEdits to change the IP Mask 123.15.16.5. That is why I was checking if(num->isVisible()) because then it would close/delete/popup each time a LineEdit is clicked. I was having problems/segmentation faults because after the user clicks "Done" (or presses Enter/Return on the keyboard), the popup is deleted so checking isVisible()) resulted in errors.

                To fix this, I created a boolean value numVis that is true if the numberpad is visible, and false otherwise. It is this value that I am now checking and everything seems to work just fine. I hope this makes sense.

                I will go ahead and mark this as solved.

                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