[solved] directory tree and file list Beginners question



  • I am trying to build directory list that is attached to a files list. But I have a mistake when the user clicks on the directory view (left side) it should appear in the files list on the right. Any body can figure the mistake?
    I can not access dirmodel model from inside the slot fn, program breaks.

    @
    #ifndef WIDGET_H
    #define WIDGET_H

    #include <QWidget>
    #include <QModelIndex>
    #include <QFileSystemModel>
    #include <QString>
    #include <QListView>

    class Widget : public QWidget
    {
    Q_OBJECT

    public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    private:
    QFileSystemModel *dirmodel;
    QFileSystemModel *filemodel;
    QString spath;
    QListView *fileview;

    public slots:
    void on_dirview_clicked(QModelIndex index);
    };

    #endif // WIDGET_H

    @

    @
    #include "widget.h"

    #include <QtGui/QApplication>
    #include <QtCore>
    #include <QtGui>
    #include <QDebug>
    #include <QString>

    Widget::Widget(QWidget *parent) :
    QWidget(parent)
    {

    QLabel *folderlabel = new QLabel;
    QLabel *fileslabel = new QLabel;
    
    QWidget *window = new QWidget;
    QGridLayout *layout = new QGridLayout;
    QTreeView *dirview = new QTreeView;
    QListView *fileview = new QListView;
    QFileSystemModel *dirmodel = new QFileSystemModel(this);
    QFileSystemModel *filemodel = new QFileSystemModel(this);
    
    connect (dirview,SIGNAL(clicked(QModelIndex)),this, SLOT(on_dirview_clicked(QModelIndex)));
    
    folderlabel->setText("Folders");
    fileslabel->setText("Database Accepted Files");
    
    QString spath = QDir::currentPath();
    
    dirmodel->setRootPath(spath);
    dirmodel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs);
    
    
    dirview->setModel(dirmodel);
    
    filemodel->setRootPath(spath);
    filemodel->setFilter(QDir::NoDotAndDotDot | QDir::Files);
    fileview->setModel(filemodel);
    
    layout->addWidget(folderlabel,0,0);
    layout->addWidget(fileslabel,0,1);
    
    layout->addWidget(dirview,1,0);
    layout->addWidget(fileview,1,1);
    
    window->setLayout(layout);
    window->show();
    

    }

    Widget::~Widget()
    {

    }

    void Widget::on_dirview_clicked(QModelIndex index)
    {

    qDebug() << dirmodel->filePath(index);
    

    // qDebug()<< index.row();

    // qDebug() << dirmodel->fileInfo(index).absoluteFilePath();
    //fileview->setRootIndex(filemodel->setRootPath(spath));

    }

    @



  • In your constructor you are creating local instances of fileview, dirmodel, filemodel and spath, they(fileview, dirmodel, filemodel) will exist only in constructor function, after that way will go out of scope(program will still work because this variables will exist somewhere on heap). You have declared same variables in the class(they are class global), use them instead....

    Read about "C++ local/global ":http://www.learncpp.com/cpp-tutorial/42-global-variables/variables and "stack/heap":http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/.

    Use "this" pointer for class wide declared variables to easy separate local variables from global...
    There is also good idea to free memory on destruction....
    @delete this->fileview;@ and so on in your destructor @Widget::~Widget@

    @
    this->fileview = new QListView;
    this->dirmodel = new QFileSystemModel(this);
    this->filemodel = new QFileSystemModel(this);
    ...
    this->spath = QDir::currentPath();
    @



  • Many thanks I works now perfect



  • Please add prefix [SOLVED] left to the topic subject. Thanks!



  • I have another question. I need to call this widget from inside another widget called login.

    I included the header file widget.h into the login.h, then from inside the login.cpp I created the widget

    widget =w

    it shows the widget window but does not show the listview .. You remember we made the listview we made them in the h file of widget class
    @
    private:
    QFileSystemModel *dirmodel;
    QFileSystemModel *filemodel;
    QString input_filename;
    QListWidget *fileview;
    QTreeView *dirview;
    QString filename;
    @



  • should it be a child from the other widget (login) ?



  • I don't really understand what are you talking about...

    you need to reach private member of type QListView in MyWidget from your Login class instance?
    something like that?:
    @
    class Login
    {
    Login(){
    this->w = new MyWidget();
    this->w->fileview... //This is what you mean? If yes then make your fileview public instead of private...
    }
    private:
    MyWidget * w;
    }
    @



  • When I click on loginbrowse, the browse widget opens its window. However only labels exist on the window without the listview and treeview.

    Login class
    @
    #include "browse.h"

    void Login::on_loginbrowse_clicked()
    {
    // selecting a new setting.dB file

    Browse w("Setting.dB"); // Browse searching for Setting.dB
    

    }
    @

    browse class with the listview
    @
    #ifndef BROWSE_H
    #define BROWSE_H
    #include "login.h"

    #include <QWidget>
    #include <QModelIndex>
    #include <QFileSystemModel>
    #include <QString>
    #include <QListWidget>
    #include <QTreeView>
    #include <QPushButton>

    class Browse : public QWidget
    {
    Q_OBJECT

    public:
    explicit Browse(QString input_filename, QWidget *parent = 0);
    ~Browse();

    private:
    QFileSystemModel *dirmodel;
    QFileSystemModel *filemodel;
    QString input_filename; //file name we need user to select. It is input from the mainwindow
    QListWidget *fileview;
    QTreeView *dirview;
    QString filename;

    public slots:
    void on_dirview_clicked(QModelIndex index);
    void on_fileview_clicked(QModelIndex index);
    void ok_pushbutton_clicked();

    };

    #endif // WIDGET_H
    @

    @
    #include "browse.h"

    #include <QtGui/QApplication>
    #include <QtCore>
    #include <QtGui>
    #include <QDebug>
    #include <QString>
    #include <QPushButton>
    #include <QSpacerItem>
    #include <QFile>

    Browse::Browse(QString input_filename, QWidget *parent) :
    QWidget(parent)
    {

    qDebug() << "input filename " <&lt; input_filename;
    
    QLabel *title = new QLabel;
    
    QLabel *folderlabel = new QLabel;
    QLabel *fileslabel = new QLabel;
    
    QWidget *window = new QWidget;
    QGridLayout *layout = new QGridLayout;
    
    //this-&gt;fileview = new QListView;
    this->fileview = new QListWidget;
    this->dirview = new QTreeView;
    
    this->dirmodel = new QFileSystemModel;
    this->filemodel = new QFileSystemModel;
    QPushButton *okbutton = new QPushButton;
    okbutton->setText("OK");
    
    connect (dirview,SIGNAL(clicked(QModelIndex)),this, SLOT(on_dirview_clicked(QModelIndex)));
    connect (fileview,SIGNAL(clicked(QModelIndex)),this, SLOT(on_fileview_clicked(QModelIndex)));
    
    connect (okbutton,SIGNAL(clicked()),this,SLOT(ok_pushbutton_clicked()));
    
    title->setText("Select folder containing the database file - Setting.dB  !");
    
    folderlabel->setText("Folders");
    fileslabel->setText("Database Files");
    
    QString spath;
    spath = QDir::currentPath();
    
    dirmodel->setRootPath(spath);
    dirmodel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs);
    dirview->setModel(dirmodel);
    for (int i=1; i<=4; i++)
    {   dirview->hideColumn(i);}
    

    /*
    filemodel->setRootPath(spath);
    filemodel->setFilter(QDir::NoDotAndDotDot | QDir::Files);
    fileview->setModel(filemodel);
    */

    //QSpacerItem *spacer = new QSpacerItem;
    
    layout->addWidget(title,0,0);
    
    layout->addWidget(folderlabel,1,0);
    layout->addWidget(fileslabel,1,1);
    
    layout->addWidget(dirview,2,0);
    layout->addWidget(fileview,2,1);
    
    //layout->addWidget(spacer,3,1);
    layout->addWidget(okbutton,3,1);
    
    window->setLayout(layout);
    
    //window->showMaximized();
    window->show();
    

    }

    Browse::~Browse()
    {
    delete this->filemodel;
    delete this->fileview;
    delete this->dirview;
    delete this->dirmodel;
    }

    void Browse::on_dirview_clicked(QModelIndex index)
    {
    QString spath;
    spath = this->dirmodel->fileInfo(index).absoluteFilePath();
    qDebug() << spath;
    QString dbfile;
    dbfile = spath + "/freeswitch.txt";
    bool fileexist = QFile::exists(dbfile);
    if (fileexist) // dbfile exists
    {
    fileview->addItem("Freeswitch.txt");
    this->filename=dbfile;
    fileview->item(0)->setSelected(true);
    }

    //this->fileview->setRootIndex(filemodel->setRootPath(spath));
    

    }

    void Browse::on_fileview_clicked(QModelIndex index)
    {
    //filename = this->filemodel->fileInfo(index).absoluteFilePath();
    qDebug() << this->filename;
    }

    void Browse::ok_pushbutton_clicked()
    {
    //QString a = this->fileview->SelectedClicked;
    qDebug() << this->filename << "folder and path";
    QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection);//important line

    }

    @



  • I'm wondering how does it work at all :) Have you read links I've send you?
    I hope this program is only for your learning and testing Qt, right?
    @
    Browse * w = new Browse("Setting.dB");
    w->show();
    @

    make it modal if you need. "setWindowModality":http://qt-project.org/doc/qt-4.8/qwidget.html#windowModality-prop

    Why do you need another one QWidget in your Browse class if your Browse class is an QWidget already?

    delete this:
    @QWidget *window = new QWidget;@

    and change this:
    @
    window->setLayout(layout);
    //window->showMaximized();
    window->show();
    @

    to:

    @this->setLayout(layout);@



  • yes i read the link. Yes, I am learning QT and Cpp newly. It works now, my friend. Thank you



  • It's OK. Qt tutorials and videos will help you a lot too!



  • I have another question, that i would appreciate if you help me with it.
    I am using MAC, it is possible from my MAC QT to produce an exe compiled version and / or linux or should I install QT over windows and linux?



  • No you can't, you can maybe cross-compile for linux, but not for windows(you can cross-compile for linux and install complete cygwin system on your windows, it will work, maybe....).



  • how do you use the setwindowmodality?
    I need the browse window to be child and can not be reopened unless before closed

    @
    Browse * w = new Browse(dB_Setting);
    w->show;
    @

    @ Browse class

    this->setWindowModality(Qt::WindowModal);
    @



  • Set it in your Browse class constructor:
    @
    Browser::Browser(QWidget *parent):QWidget(parent)
    {
    qDebug() << "input filename " << input_filename;
    this->setWindowModality(Qt::ApplicationModal);
    @

    If you really want to block event loop of main application and stay in on_loginbrowse_clicked function till user closes browse widget, make your Browse class subclass QDialog instead of QWidget, QDialog has own event loop. So your code will work well:

    @
    class Browse : public QDialog
    {
    Q_OBJECT
    public:
    ...
    @

    @
    void Login::on_loginbrowse_clicked()
    {
    // selecting a new setting.dB file
    Browse w("Setting.dB"); // Browse searching for Setting.dB
    }@



  • I changed to QDialog as follows

    @

    class Browse : public QDialog
    {
    Q_OBJECT

    public:
    explicit Browse(QString input_filename, QWidget *parent = 0);
    ~Browse();
    QString OutputFileName;

    @

    @

    QString InputFileName;

    Browse::Browse(QString input_filename, QWidget *parent) :
    QDialog(parent)
    {

    @

    Then i use the following to test waiting loop of QDialog

    @
    oid Login::on_loginbrowse_clicked()
    {
    Browse * w = new Browse(dB_Setting);
    w->show();
    qDebug() << "return from browse";
    }
    @

    but when i click on browse, it prints return . It should wait till i select a file and then I should return the file name selected. I am still struggeling with it.



  • OK I found it, it should be
    @
    w->exec();
    @

    and not
    @
    w->show();
    @

    but how to return the value selected?



  • I've told you, if you use QDialog you can use your code:

    @
    oid Login::on_loginbrowse_clicked()
    {
    Browse w(this,dB_Setting);
    w.exec();
    qDebug() << "return from browse";
    }
    @



  • Or so... :)

    You need filename value, right? Create function for getting this value:
    @
    public:
    QString getValue(){return this->filename;}

    @

    after dialog exits you can get your value like this:
    @
    void Login::on_loginbrowse_clicked()
    {
    Browse * w = new Browse(dB_Setting);
    w->exec();
    qDebug() << "return from browse: " << w->getValue();
    //and don't forget to delete this instance:
    delete w;
    }
    @



  • I have an issue over MAC. I need to show drives or at least to start with the current apppath folder

    I used the following filter but I don't see drives, I have / only however when i loads, it shows volumes folder and the dissapears. I can not set the current path of the modelview to the current directory called set in AppPath QString.

    @
    dirmodel->setFilter(QDir::Dirs | QDir::Drives | QDir::NoDotAndDotDot | QDir::AllDirs);
    @



  • Solved showing drives in MAC, since folder volumes is hidden, I used QDir::Hidden.
    Although this is not the proper way but it is a bug in QT "Reported here":https://bugreports.qt-project.org/browse/QTBUG-6875

    @
    dirmodel->setFilter(QDir::Dirs | QDir::Drives | QDir::Hidden | QDir::NoDotAndDotDot | QDir::AllDirs);
    @



  • I have another question, I created a QDialog on the fly as this, then I want to differentiate between being closed normally with the (x) button or being closed through the ok button.

    @
    QDialog *modifypsswdwin = new QDialog (this);
    QLabel *newpsd1 = new QLabel(this); newpsd1->setText("New password");
    QPushButton *modifypsswdwin_ok = new QPushButton(this); modifypsswdwin_ok->setText("OK");
    connect(modifypsswdwin_ok,SIGNAL(clicked()),modifypsswdwin,SLOT(close()));
    int ret=modifypsswdwin.exec();
    @

    I searched and found that I need to do
    @
    QDialog.setResult(1)
    @

    but the question is how to setthe result if i have only 1 line in the connect. Is it possible to write multiple commands in the slot(close)?

    thank you



  • I found it, we should connect accept to the button as well

    connect(modifypsswdwin_ok,SIGNAL(clicked()),modifypsswdwin,SLOT(accept()));
    connect(modifypsswdwin_ok,SIGNAL(clicked()),modifypsswdwin,SLOT(close()));
    


  • I have a problem with the stylesheet. I use a style sheet file. I want to set a style sheet for this browse class from the file and not hardcoded. It works when it is hardcorded in the program but i don't know how to call it in the file. I tried #Browse and tried QDialogBox#Browse but did not work.

    Any idea?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.