PDA

View Full Version : One popup menu added to few tool buttons



atomic
11th August 2014, 14:44
Hi,

In my application i have some tool buttons which have the same popup menu which include actions - open, copy, and remove.




QMenu menu;

QAction * open = new QAction( "Open", &menu );
open->setShortcuts( QKeySequence::Open );

//... other actions

menu.addAction( open );
menu.addAction( copy );
menu.addAction( remove );

ui->left->setPopupMode( QToolButton::DelayedPopup );
ui->left->setMenu( &menu );

ui->mid->setPopupMode( QToolButton::DelayedPopup );
ui->mid->setMenu( &menu );

ui->right->setPopupMode( QToolButton::DelayedPopup );
ui->right->setMenu( &menu );

// connects

connect( open, SIGNAL(triggered()), this, SLOT(open()) );



Now if user select some action in menu on some button I don't know how I can detect which of buttons relates this action.

How I can do this?
Thanks,

anda_skoa
11th August 2014, 16:42
If they are the same action, then the trigger event does not matter.

If it does then they are not the same action.

But you could try checking the current focus widget.

Cheers,
_

atomic
11th August 2014, 19:35
Every button represents file in the filesystem and contains full path.
Please look for these images.
1054910550

Functions open, copy and remove take QString as parametr so I need know which path send.
I hope you understand me.

anda_skoa
11th August 2014, 20:11
When you create the buttons, create a menu and actions for each.
You can e.g. use QSIgnalMapper to map the otherwise parameterless triggered() signals to a slot that takes the filename or set the filename as data on each action and retrieve the sending action using QObject::sender() in the slot, or connect to the menu's signals

Cheers,
_

atomic
12th August 2014, 13:40
Unfortunately QObject::sender() return QAction which I clicked not button which relates.
I can write separate menu with separate actions to every button but then I have duplicate
practically the same code for every button...

this is my example code

.h


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMenu>
#include <QDebug>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

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

void createMenu();

public slots:
void open();
void copy();
void remove();

private:
Ui::MainWindow *ui;
QMenu menu;
};

#endif // MAINWINDOW_H


and .cpp


#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

createMenu();

ui->button1->setMenu( &menu );
ui->button2->setMenu( &menu );
ui->button3->setMenu( &menu );
}

MainWindow::~MainWindow()
{
delete ui;
}


void MainWindow::createMenu()
{
menu.setObjectName( "menu" );

QAction * open = new QAction( "Open", &menu );
open->setObjectName( "open" );
open->setShortcuts( QKeySequence::Open );

connect( open, SIGNAL(triggered()), this, SLOT(open()) );

QAction * copy = new QAction( "Copy", &menu );
copy->setObjectName( "copy" );
copy->setShortcuts( QKeySequence::Copy );

connect( copy, SIGNAL(triggered()), this, SLOT(copy()) );

QAction * remove = new QAction( "Remove", &menu );
remove->setObjectName( "remove" );
remove->setShortcuts(QKeySequence::Delete );

connect( remove, SIGNAL(triggered()), this, SLOT(remove()) );

menu.addAction( open );
menu.addAction( copy );
menu.addAction( remove );

}

void MainWindow::open()
{
qDebug()<< QObject::sender()->objectName();
}

void MainWindow::copy()
{
qDebug()<< QObject::sender()->objectName();
}

void MainWindow::remove()
{

qDebug()<< QObject::sender()->objectName();
}

anda_skoa
12th August 2014, 14:20
Unfortunately QObject::sender() return QAction which I clicked not button which relates.

Obviously, it is the sender of the signal that triggered the slot. It is also what I wrote.

For the respective option the reference information would be attached to the action as user data, see QAction::setData).



I can write separate menu with separate actions to every button but then I have duplicate
practically the same code for every button...

Exactly, ideally as a component and just instantiated multiple times.

Cheers,
_

atomic
13th August 2014, 11:53
Or you don't understand me and my problem or... I don't know.
You say that the best solution is write for each button sparate menu and actions?
And have in class 3 menu and 3 open, copy and remove functions? please no...
I can't agree with you.

Look what i have now and comment this please

I create enum class


enum class Side {
left, right
} activeSide;


added all buttons to QButtonGroup with id


buttonGroup.addButton( ui->button1, 1 );
buttonGroup.addButton( ui->button2, 2 );


next connected buttonGroup signal buttonPressed to slot in my class where i detect active button


connect( &buttonGroup, SIGNAL(buttonPressed(int)) , this,
SLOT(registerId(int)) );

void MainWindow::registerId(int currentButton )
{
switch( currentButton ) {
case 1:
activeSide = Side::left;
break;
case 2:
activeSide = Side::right;
break;
}
}


and now i can create only 2 function( independent of number of buttons ).
- one without parameters
- one with parameters as QString



void MainWindow::open()
{
switch( activeSide ) {
case Side::left:
open( ui->button1.text() );
break;
case Side::right:
open( ui->button2.text() );
break;
}
}

void MainWindow::open(const QString &path)
{
QDesktopServices::openUrl( QUrl::fromLocalFile( path ) );
}


What do you think about this code?
Regards,

anda_skoa
13th August 2014, 11:58
You could even use the enum value as the id.

Cheers,
_

atomic
13th August 2014, 12:13
In QButtonGroup instead int?
But then this must be simple enum not enum class to provide conversion between string and int.
Is this what you mean?

anda_skoa
13th August 2014, 13:25
Yes. Would remove the necessity of a switch, the int would be the value you are looking for.

Cheers,
_