I'm trying to implement pinned menu items for use in a list of recently opened files. (For example, like Microsoft Office 2007 and 2010 do.) I'm almost there, but I haven't been able to properly align the pin images. What I need is something like putting a grid layout on the whole menu, but I don't think I can do that. Any suggestions? I've appended my pinmenu code and a test program.
// pinmenu.cpp
#include "pinmenu.h"
PinMenu
::PinMenu(const QString
& title,
int id,
bool pinstate
) : QWidgetAction(NULL) {
pinLayout->setMargin(0);
pinLayout->setContentsMargins(5, 3, 5, 3);
pinTitle = new ClickableLabel(title);
// This ugly attempt to line up the pin icons will break if title is too long,
// and it doesn't even succeed in lining up the icons very well.
int pixelWidth = pinTitle->fontMetrics().boundingRect(pinTitle->text()).width();
pinLayout->setSpacing(200 - pixelWidth);
pinLayout->addWidget(pinTitle);
pinImage = new ClickableLabel();
pinLayout->addWidget(pinImage);
pinWidget->setLayout(pinLayout);
setPinState(pinstate);
setDefaultWidget(pinWidget);
idno = id;
connect(pinTitle, SIGNAL(clicked()), this, SLOT(slot_textClicked()));
connect(pinImage, SIGNAL(clicked()), this, SLOT(slot_pinClicked()));
}
PinMenu::~PinMenu()
{
delete pinLayout;
delete pinWidget;
}
bool PinMenu::isPinned()
{
return pinned;
}
bool PinMenu::togglePin()
{
setPinState(!pinned);
return pinned;
}
void PinMenu::setPinState(bool pin)
{
pinned = pin;
pinImage->setPixmap(pinned ? pinmap : unpinmap);
}
void PinMenu::slot_textClicked()
{
emit signal_textClicked(idno);
}
void PinMenu::slot_pinClicked()
{
togglePin();
// Don't emit this signal - it closes the menu
// emit signal_pinClicked(idno);
}
// pinmenu.cpp
#include "pinmenu.h"
PinMenu::PinMenu(const QString& title, int id, bool pinstate) : QWidgetAction(NULL)
{
pinmap = QPixmap(":/pin.png");
unpinmap = QPixmap(":/unpin.png");
pinWidget = new QWidget();
pinLayout = new QHBoxLayout();
pinLayout->setMargin(0);
pinLayout->setContentsMargins(5, 3, 5, 3);
pinTitle = new ClickableLabel(title);
// This ugly attempt to line up the pin icons will break if title is too long,
// and it doesn't even succeed in lining up the icons very well.
int pixelWidth = pinTitle->fontMetrics().boundingRect(pinTitle->text()).width();
pinLayout->setSpacing(200 - pixelWidth);
pinLayout->addWidget(pinTitle);
pinImage = new ClickableLabel();
pinLayout->addWidget(pinImage);
pinWidget->setLayout(pinLayout);
setPinState(pinstate);
setDefaultWidget(pinWidget);
idno = id;
connect(pinTitle, SIGNAL(clicked()), this, SLOT(slot_textClicked()));
connect(pinImage, SIGNAL(clicked()), this, SLOT(slot_pinClicked()));
}
PinMenu::~PinMenu()
{
delete pinLayout;
delete pinWidget;
}
bool PinMenu::isPinned()
{
return pinned;
}
bool PinMenu::togglePin()
{
setPinState(!pinned);
return pinned;
}
void PinMenu::setPinState(bool pin)
{
pinned = pin;
pinImage->setPixmap(pinned ? pinmap : unpinmap);
}
void PinMenu::slot_textClicked()
{
emit signal_textClicked(idno);
}
void PinMenu::slot_pinClicked()
{
togglePin();
// Don't emit this signal - it closes the menu
// emit signal_pinClicked(idno);
}
To copy to clipboard, switch view to plain text mode
// pinmenu.h
#ifndef PINMENU_H
#define PINMENU_H
#include <QWidgetAction>
#include <QHBoxLayout>
#include "clickablelabel.h"
{
Q_OBJECT
public:
PinMenu(const QString& title, int id, bool pinstate);
~PinMenu();
bool isPinned();
bool togglePin();
void setPinState(bool pin);
private:
int idno;
bool pinned;
ClickableLabel *pinImage;
ClickableLabel *pinTitle;
private slots:
void slot_textClicked();
void slot_pinClicked();
signals:
void signal_textClicked(int);
void signal_pinClicked(int);
};
#endif // PINMENU_H
// pinmenu.h
#ifndef PINMENU_H
#define PINMENU_H
#include <QWidgetAction>
#include <QHBoxLayout>
#include "clickablelabel.h"
class PinMenu : public QWidgetAction
{
Q_OBJECT
public:
PinMenu(const QString& title, int id, bool pinstate);
~PinMenu();
bool isPinned();
bool togglePin();
void setPinState(bool pin);
private:
int idno;
bool pinned;
ClickableLabel *pinImage;
ClickableLabel *pinTitle;
QPixmap pinmap;
QPixmap unpinmap;
QWidget *pinWidget;
QHBoxLayout *pinLayout;
private slots:
void slot_textClicked();
void slot_pinClicked();
signals:
void signal_textClicked(int);
void signal_pinClicked(int);
};
#endif // PINMENU_H
To copy to clipboard, switch view to plain text mode
// main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
MainWindow w(0);
w.show();
return a.exec();
}
// main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w(0);
w.show();
return a.exec();
}
To copy to clipboard, switch view to plain text mode
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "pinmenu.h"
#include <QMessageBox>
#include <QHBoxLayout>
#include <QLabel>
MainWindow
::MainWindow(QWidget *parent
) {
ui->setupUi(this);
QMenu *fileMenu
= menuBar
()->addMenu
(tr
("&File"));
// Avoid warning that open is not used in this test program
// QAction *open = addMenuItem(fileMenu, tr("&Open"), SLOT(slot_open_clicked()));
addMenuItem(fileMenu, tr("&Open"), SLOT(slot_open_clicked()));
QMenu *openRecentFilesMenu
= fileMenu
->addMenu
(tr
("&Recently used files"));
addMenuItem(fileMenu, tr("E&xit"), SLOT(slot_close_clicked()));
PinMenu *pinMenuAction1 = new PinMenu(tr("Short name"), 1, true);
openRecentFilesMenu->addAction(pinMenuAction1);
connect(pinMenuAction1, SIGNAL(signal_textClicked(int)), this, SLOT(slot_textClicked(int)));
// connect(pinMenuAction1, SIGNAL(signal_pinClicked(int)), this, SLOT(slot_iconClicked(int)));
PinMenu *pinMenuAction2 = new PinMenu(tr("Long name to test alignment"), 2, false);
openRecentFilesMenu->addAction(pinMenuAction2);
connect(pinMenuAction2, SIGNAL(signal_textClicked(int)), this, SLOT(slot_textClicked(int)));
// connect(pinMenuAction2, SIGNAL(signal_pinClicked(int)), this, SLOT(slot_iconClicked(int)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::slot_close_clicked()
{
close();
}
void MainWindow::slot_open_clicked()
{
// Code here to open file
}
void MainWindow::slot_textClicked(int id)
{
QMessageBox::information(this,
"Info", tr
("Text clicked, id = %1").
arg(id
));
}
void MainWindow::slot_iconClicked(int id)
{
QMessageBox::information(this,
"Info", tr
("Icon clicked, id = %1").
arg(id
));
}
{
connect(openAction, SIGNAL(triggered()), this, method);
whichMenu->addAction(openAction);
return openAction;
}
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "pinmenu.h"
#include <QMessageBox>
#include <QHBoxLayout>
#include <QLabel>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
// Avoid warning that open is not used in this test program
// QAction *open = addMenuItem(fileMenu, tr("&Open"), SLOT(slot_open_clicked()));
addMenuItem(fileMenu, tr("&Open"), SLOT(slot_open_clicked()));
QMenu *openRecentFilesMenu = fileMenu->addMenu(tr("&Recently used files"));
addMenuItem(fileMenu, tr("E&xit"), SLOT(slot_close_clicked()));
PinMenu *pinMenuAction1 = new PinMenu(tr("Short name"), 1, true);
openRecentFilesMenu->addAction(pinMenuAction1);
connect(pinMenuAction1, SIGNAL(signal_textClicked(int)), this, SLOT(slot_textClicked(int)));
// connect(pinMenuAction1, SIGNAL(signal_pinClicked(int)), this, SLOT(slot_iconClicked(int)));
PinMenu *pinMenuAction2 = new PinMenu(tr("Long name to test alignment"), 2, false);
openRecentFilesMenu->addAction(pinMenuAction2);
connect(pinMenuAction2, SIGNAL(signal_textClicked(int)), this, SLOT(slot_textClicked(int)));
// connect(pinMenuAction2, SIGNAL(signal_pinClicked(int)), this, SLOT(slot_iconClicked(int)));
fileMenu->setLayout(new QGridLayout());
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::slot_close_clicked()
{
close();
}
void MainWindow::slot_open_clicked()
{
// Code here to open file
}
void MainWindow::slot_textClicked(int id)
{
QMessageBox::information(this, "Info", tr("Text clicked, id = %1").arg(id));
}
void MainWindow::slot_iconClicked(int id)
{
QMessageBox::information(this, "Info", tr("Icon clicked, id = %1").arg(id));
}
QAction *MainWindow::addMenuItem(QMenu *whichMenu, QString menuText, const char *method)
{
QAction *openAction = new QAction(menuText, this);
connect(openAction, SIGNAL(triggered()), this, method);
whichMenu->addAction(openAction);
return openAction;
}
To copy to clipboard, switch view to plain text mode
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui/QMainWindow>
namespace Ui
{
class MainWindow;
}
{
Q_OBJECT
public:
~MainWindow();
private:
private slots:
void slot_close_clicked();
void slot_open_clicked();
void slot_iconClicked(int id);
void slot_textClicked(int id);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui/QMainWindow>
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
private:
QAction *addMenuItem(QMenu *whichMenu, QString menuText, const char *method);
private slots:
void slot_close_clicked();
void slot_open_clicked();
void slot_iconClicked(int id);
void slot_textClicked(int id);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
To copy to clipboard, switch view to plain text mode
// clickablelabel.cpp
#include "clickablelabel.h"
// This comes from http://qt-project.org/wiki/Make-a-QLabel-Clickable
// License is Creative Commons Attribution-ShareAlike 2.5 Generic
ClickableLabel
::ClickableLabel(const QString
& text,
QWidget *parent
) : {
this->setText(text);
}
ClickableLabel::~ClickableLabel()
{
}
void ClickableLabel
::mousePressEvent (QMouseEvent * /* event */) {
emit clicked();
}
// clickablelabel.cpp
#include "clickablelabel.h"
// This comes from http://qt-project.org/wiki/Make-a-QLabel-Clickable
// License is Creative Commons Attribution-ShareAlike 2.5 Generic
ClickableLabel::ClickableLabel(const QString& text, QWidget *parent) :
QLabel(parent)
{
this->setText(text);
}
ClickableLabel::~ClickableLabel()
{
}
void ClickableLabel::mousePressEvent (QMouseEvent * /* event */)
{
emit clicked();
}
To copy to clipboard, switch view to plain text mode
// clickablelabel.h
#ifndef CLICKABLELABEL_H
#define CLICKABLELABEL_H
// This comes from http://qt-project.org/wiki/Make-a-QLabel-Clickable
// License is Creative Commons Attribution-ShareAlike 2.5 Generic
#include <QLabel>
class ClickableLabel
: public QLabel {
Q_OBJECT
public:
explicit ClickableLabel
(const QString
& text
="",
QWidget *parent
= 0);
~ClickableLabel();
signals:
void clicked();
protected:
};
#endif // CLICKABLELABEL_H
// clickablelabel.h
#ifndef CLICKABLELABEL_H
#define CLICKABLELABEL_H
// This comes from http://qt-project.org/wiki/Make-a-QLabel-Clickable
// License is Creative Commons Attribution-ShareAlike 2.5 Generic
#include <QLabel>
class ClickableLabel : public QLabel
{
Q_OBJECT
public:
explicit ClickableLabel(const QString& text ="", QWidget *parent = 0);
~ClickableLabel();
signals:
void clicked();
protected:
void mousePressEvent(QMouseEvent *event) ;
};
#endif // CLICKABLELABEL_H
To copy to clipboard, switch view to plain text mode
Bookmarks