Question

I've created a custom QLineEdit widget that handles drag and drop of files. Everything is working great with that part, but as soon as I add a Class variable the application crashes either at the construction of the class or at destruction:

  • When my variable is QString, it crashes at construction
  • When my variable is QString*, it crashed at destruction

I tried deleting the variable (QString*) in the destructor, same issue...

Any ideas?

Header:

#ifndef DROPLINEEDIT_H
#define DROPLINEEDIT_H

#include <QLineEdit>
#include <QDragEnterEvent>
#include <QMimeData>
#include <QFileInfo>
#include <QString>
#include <QDebug>


class DropLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit DropLineEdit(QWidget *parent = 0);
    ~DropLineEdit();

protected:
    virtual void dragEnterEvent(QDragEnterEvent *event);
    virtual void dropEvent(QDropEvent *event);
    virtual void dragLeaveEvent(QDragLeaveEvent *event);

signals:

public slots:

private:

    QString * mFileName;

};

#endif // DROPLINEEDIT_H

Source:

#include "droplineedit.h"

DropLineEdit::DropLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
    setAcceptDrops(true);
    this->setReadOnly(true);
    this->setStyleSheet("QLineEdit { border: 2px solid gray ; border-radius: 8px ; padding: 0 6px }");
}

DropLineEdit::~DropLineEdit()
{
    if(!mFileName){
        delete mFileName;
    }
}

// **************************************** PROTECTED METHODS **************************************** //

void DropLineEdit::dragEnterEvent(QDragEnterEvent *event){
    this->setStyleSheet("QLineEdit { border: 3px solid black ; border-radius: 8px ; padding: 0 6px }");
    event->accept();
}
void DropLineEdit::dragLeaveEvent(QDragLeaveEvent *event){
    this->setStyleSheet("QLineEdit { border: 2px solid gray ; border-radius: 8px ; padding: 0 6px }");
    event->accept();
}

void DropLineEdit::dropEvent(QDropEvent *event){
    // Get the data. If multiple files are dropped, take only the first one and fetch save its info
    QList<QUrl> list = event->mimeData()->urls();
    QFileInfo * fileInfo = new QFileInfo(list.at(0).toLocalFile());

    qDebug() << fileInfo->absoluteFilePath();
    mFileName = new QString(fileInfo->absoluteFilePath());

    this->setText(fileInfo->fileName());
    this->setStyleSheet("QLineEdit { border: 2px solid gray ; border-radius: 8px ; padding: 0 6px }");
    event->accept();
}
Was it helpful?

Solution 2

I was getting this as an error in debug: "invalid address specified to rtlfreeheap"

I did some research on that and found out that it could be related to an internal issue with Qt (the way object constructors are called). I went back in my main application to see how I called my DropLineEdit object and notice that I forgot to remove the setAcceptDrops(true) after creating DropLineEdit Classe (the object was formerly a normal QLineEdit before I created DropLineEdit).

Here was the function call:

DropLineEdit* Instrument::createDropLineEdit(){
    DropLineEdit * lineEdit = new DropLineEdit();
    lineEdit->setAcceptDrops(true);
    return lineEdit;
}

Changed to:

DropLineEdit* Instrument::createDropLineEdit(){
    DropLineEdit * lineEdit = new DropLineEdit();
    return lineEdit;
}

After removing that redundant call (redundant since the acceptdrops was set in the constructor), I didn't get any application crash either with QString or QString* as member variable of DropLineEdit Class. I used a QString (not the pointer) and I was able to make my Class do what is was supposed to.

Thanks for your replies guys. Much appreciated.

OTHER TIPS

Add this to the constructor:

mFileName = 0;

You need to initialize the pointer. Otherwise it will have random value and you will be unable to check if you have created an object.

Modify the destructor:

delete mFileName;

You need to delete object if it's not NULL (your version is the opposite). delete will perform the check internally.

Note that if mFileName = new QString... is executed multiple times, several objects will be created. You need to delete previous object before creating new one if you need to avoid memory leak.

However, all the above information is provided for general education. You should not use QString* here. Non-pointer QString class member will be much more correct. In this case you don't need to use new or delete, you don't need to care about pointers and memory at all.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top