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. Basic file handling with QDirModel and QTreeView
Qt 6.11 is out! See what's new in the release blog

Basic file handling with QDirModel and QTreeView

Scheduled Pinned Locked Moved Solved General and Desktop
20 Posts 4 Posters 6.7k Views 2 Watching
  • 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.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #11

    AFAICS, you are re-creating every QAction every time you generate your contextual menu. So before you trigger that once, you likely don't have any shortcut for your application.

    What is usually done is to create your QAction once in a central place (usually the constructor) and then re-use them as necessary to build menus/contextual menus etc.

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

    1 Reply Last reply
    0
    • SikarjanS Offline
      SikarjanS Offline
      Sikarjan
      wrote on last edited by
      #12

      Thanks for the hint. I did that. I moved the QAction block into the constructor of MainWindow but my shortcuts still do not work. I've been reading the QAction help but I do not see what I am doing differently from the example...

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

        Did you took a look at the Application Example ? They show how to create QAction and use them from several places.

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

        1 Reply Last reply
        0
        • SikarjanS Offline
          SikarjanS Offline
          Sikarjan
          wrote on last edited by Sikarjan
          #14

          My shortcuts cannot work because the triggered action is not connect to a slot! I was handling everything in one function and this function could not be entered by the shortcut. So now I am redoing my entire code and define the action, connect it so a slot and handle the action in the slot. But it still does not work! While compiling I get an error:

          QMetaObject::connectSlotsByName: No matching signal for on_pDel_triggered()
          
          pDel = new QAction(tr("delete"), this);
          pDel->setShortcut(QKeySequence(Qt::Key_Delete));
          connect(pDel, QAction::triggered, this, MainWindow::on_pDel_triggered);
          

          Why is this just not working?

          EDIT:
          Apparently on_ is not allowed for a custom slot... I changed the slot name to pDel_triggered() and now the app complies but the shortcut is still not working =( Also if I use the context menu now the slot is called twice.

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

            The on_WidgetName_SignalName pattern is used by the connectSlotsByName method to automatically create the connection between the signal SignalName from the widget named WidgetName to that slot. The most common use case is designer based widgets.

            Can you show the complete code where you setup your action ?

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

            1 Reply Last reply
            0
            • SikarjanS Offline
              SikarjanS Offline
              Sikarjan
              wrote on last edited by Sikarjan
              #16

              @SGaist Thanks a lot for taking so much interest in my problem.
              Here is what I currently have. I solved the issue with the signal being emitted twice over the context menu but I am still not getting anywhere with my shortcuts. Currently I am focussing on pDel.

              MainWindow::MainWindow(QWidget *parent) :
                  QMainWindow(parent),
                  ui(new Ui::MainWindow)
              {
                  isCtrlPressed = false;
                  pCopyPath = "";
                  isCutAction = false;
                  fileContextMenu = new QMenu(ui->treeView);
              
                  // Define actions for explorer
                  pOpen = new QAction(QIcon(":/icon/icons/openEnable.png"),tr("open"), this);
                  pRename = new QAction(tr("rename"), this);
                  pRename->setShortcut(QKeySequence(Qt::Key_F2));
                  pDel = new QAction(tr("delete"), fileContextMenu);
                  pDel->setShortcut(QKeySequence(Qt::Key_Delete));
                  connect(pDel, SIGNAL(triggered()), this, SLOT(pDel_triggered()));
                  pCopy =new QAction(QIcon(":/icon/icons/copyEnable.png"),tr("&copy"), this);
                  pCopy->setShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_C));
                  pCut = new QAction(QIcon(":/icon/icons/cutEnable.png"), tr("cut"), this);
                  pCut->setShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_X));
                  pPast = new QAction(QIcon(":/icon/icons/pastEnable.png"), tr("past"), this);
                  pAddFolder = new QAction(tr("Create Folder"), this);
                  pAddFile = new QAction(QIcon(":/icon/icons/newEnable.png"),tr("Add new file"), this);
              
                  fileContextMenu->addAction(pOpen);
                  fileContextMenu->addAction(pRename);
                  fileContextMenu->addSeparator();
                  fileContextMenu->addAction(pCopy);
                  fileContextMenu->addAction(pCut);
                  fileContextMenu->addAction(pPast);
                  fileContextMenu->addSeparator();
                  fileContextMenu->addAction(pAddFile);
                  fileContextMenu->addAction(pAddFolder);
                  fileContextMenu->addSeparator();
                  fileContextMenu->addAction(pDel);
              
                  [...]
              
                  dirModel = new QFileSystemModel(this);
                  dirModel->setReadOnly(false);
                  connect(dirModel, SIGNAL(fileRenamed(QString,QString,QString)), this, SLOT(fileRenamed(QString,QString,QString)));
                  ui->treeView->setModel(dirModel);
                  ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
                  connect(ui->treeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDirContextMenu(QPoint)));
              }
              
              void MainWindow::showDirContextMenu(const QPoint &pos){
                  QModelIndex index=ui->treeView->indexAt(pos);
                  bool isRoot = false;
              
                  if(!index.isValid()){
                      index = dirModel->index(projects[ui->projectSelector->currentText()]);
                      isRoot = true;
                  }
              
                  bool isDir = dirModel->isDir(index);
              
                  if(isRoot){
                      pRename->setEnabled(false);
                      pDel->setEnabled(false);
                      pCopy->setEnabled(false);
                      pCut->setEnabled(false);
                  }else{
                      pRename->setEnabled(true);
                      pDel->setEnabled(true);
                      pCopy->setEnabled(true);
                      pCut->setEnabled(true);
                  }
              
                  if(pCopyPath != "" && isDir){
                      pPast->setEnabled(true);
                      pPast->setStatusTip(tr("Insert")+ ": " + pCopyPath.section("/",-1,-1));
                  }else{
                      pPast->setEnabled(false);
                  }
              
                  QAction* selectedItem = fileContextMenu->exec(ui->treeView->viewport()->mapToGlobal(pos));
              
                  if(selectedItem == pOpen){
                      on_treeView_doubleClicked(index);
                  }else if [...]
              }
              
              void MainWindow::pDel_triggered()
              {
                  QModelIndex index = ui->treeView->currentIndex();
                  qDebug() << dirModel->filePath(index);
              }
              

              Action without a shortcut I plan to handle in the showDirContextMenu function. The other I plan to handle by signal and slots but currently the function pDel_triggered is only entered if I use the context menu. The shortcut is doing nothing.

              Last thing I tried was to change the parents for the contectMenu and the actions.

              J.HilkJ 1 Reply Last reply
              0
              • SikarjanS Sikarjan

                @SGaist Thanks a lot for taking so much interest in my problem.
                Here is what I currently have. I solved the issue with the signal being emitted twice over the context menu but I am still not getting anywhere with my shortcuts. Currently I am focussing on pDel.

                MainWindow::MainWindow(QWidget *parent) :
                    QMainWindow(parent),
                    ui(new Ui::MainWindow)
                {
                    isCtrlPressed = false;
                    pCopyPath = "";
                    isCutAction = false;
                    fileContextMenu = new QMenu(ui->treeView);
                
                    // Define actions for explorer
                    pOpen = new QAction(QIcon(":/icon/icons/openEnable.png"),tr("open"), this);
                    pRename = new QAction(tr("rename"), this);
                    pRename->setShortcut(QKeySequence(Qt::Key_F2));
                    pDel = new QAction(tr("delete"), fileContextMenu);
                    pDel->setShortcut(QKeySequence(Qt::Key_Delete));
                    connect(pDel, SIGNAL(triggered()), this, SLOT(pDel_triggered()));
                    pCopy =new QAction(QIcon(":/icon/icons/copyEnable.png"),tr("&copy"), this);
                    pCopy->setShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_C));
                    pCut = new QAction(QIcon(":/icon/icons/cutEnable.png"), tr("cut"), this);
                    pCut->setShortcut(QKeySequence(Qt::ControlModifier + Qt::Key_X));
                    pPast = new QAction(QIcon(":/icon/icons/pastEnable.png"), tr("past"), this);
                    pAddFolder = new QAction(tr("Create Folder"), this);
                    pAddFile = new QAction(QIcon(":/icon/icons/newEnable.png"),tr("Add new file"), this);
                
                    fileContextMenu->addAction(pOpen);
                    fileContextMenu->addAction(pRename);
                    fileContextMenu->addSeparator();
                    fileContextMenu->addAction(pCopy);
                    fileContextMenu->addAction(pCut);
                    fileContextMenu->addAction(pPast);
                    fileContextMenu->addSeparator();
                    fileContextMenu->addAction(pAddFile);
                    fileContextMenu->addAction(pAddFolder);
                    fileContextMenu->addSeparator();
                    fileContextMenu->addAction(pDel);
                
                    [...]
                
                    dirModel = new QFileSystemModel(this);
                    dirModel->setReadOnly(false);
                    connect(dirModel, SIGNAL(fileRenamed(QString,QString,QString)), this, SLOT(fileRenamed(QString,QString,QString)));
                    ui->treeView->setModel(dirModel);
                    ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
                    connect(ui->treeView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDirContextMenu(QPoint)));
                }
                
                void MainWindow::showDirContextMenu(const QPoint &pos){
                    QModelIndex index=ui->treeView->indexAt(pos);
                    bool isRoot = false;
                
                    if(!index.isValid()){
                        index = dirModel->index(projects[ui->projectSelector->currentText()]);
                        isRoot = true;
                    }
                
                    bool isDir = dirModel->isDir(index);
                
                    if(isRoot){
                        pRename->setEnabled(false);
                        pDel->setEnabled(false);
                        pCopy->setEnabled(false);
                        pCut->setEnabled(false);
                    }else{
                        pRename->setEnabled(true);
                        pDel->setEnabled(true);
                        pCopy->setEnabled(true);
                        pCut->setEnabled(true);
                    }
                
                    if(pCopyPath != "" && isDir){
                        pPast->setEnabled(true);
                        pPast->setStatusTip(tr("Insert")+ ": " + pCopyPath.section("/",-1,-1));
                    }else{
                        pPast->setEnabled(false);
                    }
                
                    QAction* selectedItem = fileContextMenu->exec(ui->treeView->viewport()->mapToGlobal(pos));
                
                    if(selectedItem == pOpen){
                        on_treeView_doubleClicked(index);
                    }else if [...]
                }
                
                void MainWindow::pDel_triggered()
                {
                    QModelIndex index = ui->treeView->currentIndex();
                    qDebug() << dirModel->filePath(index);
                }
                

                Action without a shortcut I plan to handle in the showDirContextMenu function. The other I plan to handle by signal and slots but currently the function pDel_triggered is only entered if I use the context menu. The shortcut is doing nothing.

                Last thing I tried was to change the parents for the contectMenu and the actions.

                J.HilkJ Offline
                J.HilkJ Offline
                J.Hilk
                Moderators
                wrote on last edited by
                #17

                @Sikarjan

                hi,

                a quick look into the docu, and I found this paragraph:

                Once a QAction has been created it should be added to the relevant menu and toolbar, then connected to the slot which will perform the action.
                

                You did not post the connects in your code-example, so did you keep to that order, did you mix it up? :-)


                Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                Q: What's that?
                A: It's blue light.
                Q: What does it do?
                A: It turns blue.

                1 Reply Last reply
                0
                • SikarjanS Offline
                  SikarjanS Offline
                  Sikarjan
                  wrote on last edited by
                  #18

                  Hi @J-Hilk,

                  I did connect the action, see above:

                      pDel = new QAction(tr("delete"), fileContextMenu);
                      pDel->setShortcut(QKeySequence(Qt::Key_Delete));
                      connect(pDel, SIGNAL(triggered()), this, SLOT(pDel_triggered()));
                  

                  So I believe I did this correct. The connect works because I see an output when I use the context menu.

                  J.HilkJ 1 Reply Last reply
                  0
                  • SikarjanS Sikarjan

                    Hi @J-Hilk,

                    I did connect the action, see above:

                        pDel = new QAction(tr("delete"), fileContextMenu);
                        pDel->setShortcut(QKeySequence(Qt::Key_Delete));
                        connect(pDel, SIGNAL(triggered()), this, SLOT(pDel_triggered()));
                    

                    So I believe I did this correct. The connect works because I see an output when I use the context menu.

                    J.HilkJ Offline
                    J.HilkJ Offline
                    J.Hilk
                    Moderators
                    wrote on last edited by
                    #19

                    @Sikarjan
                    ah,

                    Oh! Sorry I obviously missed that, you should use more linebreaks/paragraphs in your code :-)

                    But, at least Qt::Key_Delete should work, as it is set up correctly.

                    I'm sorry, but I have not much experience with QActions, but you should be in good hands with @SGaist .


                    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                    Q: What's that?
                    A: It's blue light.
                    Q: What does it do?
                    A: It turns blue.

                    1 Reply Last reply
                    0
                    • SikarjanS Offline
                      SikarjanS Offline
                      Sikarjan
                      wrote on last edited by
                      #20

                      Found the error! =) I got a hint on Stackoverflow. It is not enough to add the action to the menu, you also have to add the action to the widget. In my case the treeView.

                      1 Reply Last reply
                      2

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved