[solved]Problem with actions in dynamically created menu.



  • I am trying to make menu with last 10 urls entered in my application. It is the menu that shows up at side when you move mouse cursor on it (I am not sure how its called). I have already made slot that creates actions and adds them into menu when the signal aboutToShow() is called. There can be 0-10 urls showed depending on how much urls are saved in .history.txt file. I connected all actions to the same slot selectedFromHistory() which will take the selected url and set variable url and show it up in line edit. But my problem is I can't figure out how can I know which action was selected. Is there some way to find which action from menuAction was selected, somehow find the index of this action in the list or something? Also I never tried make menu dynamically so if there is some better way than I used please tell me.

    @void MainWindow::history(){
    ui->menuLast_10_downloads->clear();
    if(!QFile::exists(".history.txt"))return;
    QFile fil(".history.txt");
    fil.open(QIODevice::ReadOnly);
    QTextStream ts(&fil);
    QStringList urls ;//probably should make this as global
    while(!ts.atEnd()) {
    QString line = ts.readLine();
    urls.append(line.split(" ").at(line.split(" ").count()-1));
    }
    while(urls.count()>10)
    urls.removeAt(0);
    int a=urls.count(); //latest entered url is shown at top
    QList<QAction*> menuAction;
    int b=0 ;
    while(a--){
    QAction *act=new QAction(this);
    act->setText(urls.at(a));
    menuAction.append(act););
    int a=urls.count(); //newest url is shown at top
    ui->menuLast_10_downloads->addAction(menuAction.at(b));
    connect(menuAction.at(b),SIGNAL(triggered()),this,SLOT(selectedFromHistory()));
    b++;
    }
    }
    void MainWindow::selectedFromHistory(){
    //will add code here as soon as ill find out which action has called the slot
    }@


  • Moderators

    You can use QAction::setData() to add the url as internal action data. Then, in your slot do
    @
    void MainWindow::selectedFromHistory(){
    QAction* action = qobject_cast<QAction*>(sender());
    if(action)
    {
    QString url = action.data().toString();
    //do something with the url
    }
    }
    @
    Or, if you're using Qt5 and a C++11 compiler, you can use a lambda:
    @
    QString url = urls.at(a);
    connect(menuAction.at(b), &QAction::triggered, =url{selectedFromHistory( url );});

    //and then
    void MainWindow::selectedFromHistory(QString url)
    {
    //do something with url
    }
    @
    As for creating menu. If your file is long you are wasting a lot of cycles with this:
    @
    while(urls.count()>10)
    urls.removeAt(0);
    @
    Also because a and b are not great names for variables your code is getting hard to follow.
    You don't need to explicitly remove items from a list to skip them.
    Instead of adding and removing things left and right construct a proper loop:
    @
    int lastIndex = qMax( 0, urls.size() - 11);

    for(int i = urls.size() - 1; i > lastIndex; --i)
    {
    ...
    action->setText(urls(i));
    }
    @


Log in to reply
 

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