284 lines
9.6 KiB
C++
284 lines
9.6 KiB
C++
#include "menudialog.h"
|
|
#include "ui_menudialog.h"
|
|
#include <QScrollBar>
|
|
#include <QScreen>
|
|
#include "icon.h"
|
|
#include "helper.h"
|
|
#include "scroller.h"
|
|
#include "settings.h"
|
|
|
|
const char * MENU_TOP_LEVEL_ITEM_PROPERTY = "toplevel";
|
|
const int MENU_WIDTH_EXTRA_SPACE = 40;
|
|
|
|
MenuDialog::MenuDialog(QMenuBar * menuBar, QWidget *parent) :
|
|
QDialog(parent),
|
|
ui(new Ui::MenuDialog),
|
|
menuBar(menuBar)
|
|
{
|
|
ui->setupUi(this);
|
|
setupMenu();
|
|
|
|
ui->listWidget->setFocusProxy(this);
|
|
ui->listWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
|
ui->listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
ui->listWidget->setContentsMargins(0,0,0,0);
|
|
ui->listWidget->setSpacing(0);
|
|
connect(ui->listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(onItemClicked(QListWidgetItem*)));
|
|
|
|
if (Settings::get("enable_android_gestures") == "yes") {
|
|
Scroller::enableGestures(ui->listWidget);
|
|
}
|
|
|
|
minWidth = 0;
|
|
action = nullptr;
|
|
animationInProgress = false;
|
|
QEasingCurve easingIn(QEasingCurve::OutCubic);
|
|
animationIn = new QPropertyAnimation(this, "geometry");
|
|
animationIn->setDuration(ANDROID_DIALOG_ANIMATION_DURATION);
|
|
animationIn->setEasingCurve(easingIn);
|
|
connect(animationIn, SIGNAL(finished()), this, SLOT(animationInFinished()));
|
|
|
|
if (parent != nullptr) {
|
|
parent->installEventFilter(this);
|
|
}
|
|
}
|
|
|
|
MenuDialog::~MenuDialog()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void MenuDialog::setupMenu()
|
|
{
|
|
mainMenu = new QMenu(this);
|
|
subMenu = new QMenu(this);
|
|
backAction = new QAction(this);
|
|
|
|
QAction * fileAction = mainMenu->addAction(tr("File"));
|
|
fileAction->setIcon(Icon::get("actionNewFile", QIcon(":/icons/document-new.png")));
|
|
fileAction->setData(QVariant("menuFile"));
|
|
fileAction->setProperty(MENU_TOP_LEVEL_ITEM_PROPERTY, 1);
|
|
connect(fileAction, SIGNAL(triggered(bool)), this, SLOT(topLevelItemTriggered(bool)));
|
|
|
|
QAction * editAction = mainMenu->addAction(tr("Edit"));
|
|
editAction->setIcon(Icon::get("actionEdit", QIcon(":/icons/edit.png")));
|
|
editAction->setData(QVariant("menuEdit"));
|
|
editAction->setProperty(MENU_TOP_LEVEL_ITEM_PROPERTY, 1);
|
|
connect(editAction, SIGNAL(triggered(bool)), this, SLOT(topLevelItemTriggered(bool)));
|
|
|
|
QAction * gitAction = mainMenu->addAction(tr("Git"));
|
|
gitAction->setIcon(Icon::get("actionGitCommit", QIcon(":/icons/ok.png")));
|
|
gitAction->setData(QVariant("menuGit"));
|
|
gitAction->setProperty(MENU_TOP_LEVEL_ITEM_PROPERTY, 1);
|
|
connect(gitAction, SIGNAL(triggered(bool)), this, SLOT(topLevelItemTriggered(bool)));
|
|
|
|
QAction * toolsAction = mainMenu->addAction(tr("Tools"));
|
|
toolsAction->setIcon(Icon::get("actionSettings", QIcon(":/icons/configure.png")));
|
|
toolsAction->setData(QVariant("menuTools"));
|
|
toolsAction->setProperty(MENU_TOP_LEVEL_ITEM_PROPERTY, 1);
|
|
connect(toolsAction, SIGNAL(triggered(bool)), this, SLOT(topLevelItemTriggered(bool)));
|
|
|
|
QAction * viewAction = mainMenu->addAction(tr("View"));
|
|
viewAction->setIcon(Icon::get("actionSplitTab", QIcon(":/icons/split.png")));
|
|
viewAction->setData(QVariant("menuView"));
|
|
viewAction->setProperty(MENU_TOP_LEVEL_ITEM_PROPERTY, 1);
|
|
connect(viewAction, SIGNAL(triggered(bool)), this, SLOT(topLevelItemTriggered(bool)));
|
|
|
|
QAction * contextMenuAction = new QAction(this);
|
|
contextMenuAction->setText(tr("Context menu"));
|
|
contextMenuAction->setIcon(Icon::get("actionMenu", QIcon(":/icons/list.png")));
|
|
contextMenuAction->setProperty(MENU_TOP_LEVEL_ITEM_PROPERTY, 0);
|
|
connect(contextMenuAction, SIGNAL(triggered(bool)), this, SLOT(contextMenuItemTriggered(bool)));
|
|
mainMenu->addAction(contextMenuAction);
|
|
|
|
QAction * preferencesAction = new QAction(this);
|
|
preferencesAction->setText(tr("Preferences"));
|
|
preferencesAction->setIcon(Icon::get("actionSettings", QIcon(":/icons/configure.png")));
|
|
preferencesAction->setProperty(MENU_TOP_LEVEL_ITEM_PROPERTY, 0);
|
|
connect(preferencesAction, SIGNAL(triggered(bool)), this, SLOT(preferencesItemTriggered(bool)));
|
|
mainMenu->addAction(preferencesAction);
|
|
|
|
QAction * helpAction = mainMenu->addAction(tr("Help"));
|
|
helpAction->setIcon(Icon::get("actionHelpAbout", QIcon(":/icons/help-info.png")));
|
|
helpAction->setData(QVariant("menuHelp"));
|
|
helpAction->setProperty(MENU_TOP_LEVEL_ITEM_PROPERTY, 1);
|
|
connect(helpAction, SIGNAL(triggered(bool)), this, SLOT(topLevelItemTriggered(bool)));
|
|
|
|
QAction * exitAction = new QAction(this);
|
|
exitAction->setText(tr("Exit"));
|
|
exitAction->setIcon(Icon::get("actionUndo", QIcon(":/icons/edit-undo.png")));
|
|
exitAction->setProperty(MENU_TOP_LEVEL_ITEM_PROPERTY, 0);
|
|
connect(exitAction, SIGNAL(triggered(bool)), this, SLOT(exitItemTriggered(bool)));
|
|
mainMenu->addAction(exitAction);
|
|
|
|
backAction->setText(tr("Back"));
|
|
backAction->setIcon(Icon::get("actionUndo", QIcon(":/icons/edit-undo.png")));
|
|
backAction->setProperty(MENU_TOP_LEVEL_ITEM_PROPERTY, 1);
|
|
connect(backAction, SIGNAL(triggered(bool)), this, SLOT(backItemTriggered(bool)));
|
|
}
|
|
|
|
void MenuDialog::build() {
|
|
build(mainMenu->actions());
|
|
}
|
|
|
|
void MenuDialog::build(QList<QAction *> actions) {
|
|
ui->listWidget->clear();
|
|
subMenu->clear();
|
|
actionsList = actions;
|
|
action = nullptr;
|
|
for (int i=0; i<actionsList.size(); i++) {
|
|
QAction * action = actionsList.at(i);
|
|
if (action->isSeparator()) continue;
|
|
QListWidgetItem * item = new QListWidgetItem();
|
|
if (!action->isEnabled()) {
|
|
Qt::ItemFlags flags = item->flags();
|
|
flags = flags & ~Qt::ItemIsEnabled;
|
|
item->setFlags(flags);
|
|
}
|
|
QIcon icon = action->isChecked() ? Icon::get("actionGitCommit", QIcon(":/icons/ok.png")) : action->icon();
|
|
if (icon.isNull()) icon.addFile(":/icons/blank.png", QSize(ICON_SIZE, ICON_SIZE), QIcon::Normal);
|
|
icon.addFile(":/icons/blank.png", QSize(ICON_SIZE, ICON_SIZE), QIcon::Disabled);
|
|
item->setIcon(icon);
|
|
QString text = action->text().replace("&","");
|
|
int p = text.indexOf("\t");
|
|
if (p > 0) text = text.mid(0, p);
|
|
item->setText(text);
|
|
item->setData(Qt::UserRole, QVariant(i));
|
|
addItem(item);
|
|
}
|
|
}
|
|
|
|
void MenuDialog::addItem(QListWidgetItem * item)
|
|
{
|
|
ui->listWidget->addItem(item);
|
|
}
|
|
|
|
int MenuDialog::exec()
|
|
{
|
|
setVisible(true);
|
|
updateGeometry();
|
|
animateIn();
|
|
setVisible(false);
|
|
return QDialog::exec();
|
|
|
|
}
|
|
|
|
void MenuDialog::onItemClicked(QListWidgetItem *item)
|
|
{
|
|
int index = item->data(Qt::UserRole).toInt();
|
|
if (index >= 0 && index < actionsList.size()) {
|
|
action = actionsList.at(index);
|
|
if (!action->isSeparator() && action->isEnabled()) {
|
|
QVariant prop = action->property(MENU_TOP_LEVEL_ITEM_PROPERTY);
|
|
if (!prop.isValid() || prop.toInt() != 1) {
|
|
done(QDialog::Accepted);
|
|
}
|
|
action->activate(QAction::Trigger);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MenuDialog::topLevelItemTriggered(bool)
|
|
{
|
|
QAction * action = qobject_cast<QAction *>(sender());
|
|
if (action != nullptr) {
|
|
subMenu->clear();
|
|
subMenu->addAction(backAction);
|
|
QString name = action->data().toString();
|
|
QMenu * menu = menuBar->findChild<QMenu *>(name);
|
|
if (menu == nullptr) return;
|
|
menu->aboutToShow();
|
|
buildSubMenu(menu);
|
|
build(subMenu->actions());
|
|
updateGeometry();
|
|
animateIn();
|
|
}
|
|
}
|
|
|
|
void MenuDialog::buildSubMenu(QMenu * menu)
|
|
{
|
|
QList<QAction *> actions = menu->actions();
|
|
for (QAction * action : actions) {
|
|
if (action->isSeparator()) continue;
|
|
QMenu * menu = action->menu();
|
|
if (menu != nullptr) {
|
|
buildSubMenu(menu);
|
|
continue;
|
|
}
|
|
subMenu->addAction(action);
|
|
}
|
|
}
|
|
|
|
void MenuDialog::backItemTriggered(bool)
|
|
{
|
|
build();
|
|
updateGeometry();
|
|
animateIn();
|
|
}
|
|
|
|
void MenuDialog::contextMenuItemTriggered(bool)
|
|
{
|
|
emit showContextMenu();
|
|
}
|
|
|
|
void MenuDialog::preferencesItemTriggered(bool)
|
|
{
|
|
emit showPreferences();
|
|
}
|
|
|
|
void MenuDialog::exitItemTriggered(bool)
|
|
{
|
|
emit quit();
|
|
}
|
|
|
|
void MenuDialog::animateIn()
|
|
{
|
|
if (animationInProgress) return;
|
|
animationInProgress = true;
|
|
if (!isVisible()) setVisible(true);
|
|
raise();
|
|
QRect rect = geometry();
|
|
animationIn->setStartValue(QRect(rect.x()-rect.width(), rect.y(), rect.width(), rect.height()));
|
|
animationIn->setEndValue(QRect(rect.x(), rect.y(), rect.width(), rect.height()));
|
|
animationIn->start();
|
|
}
|
|
|
|
void MenuDialog::animationInFinished()
|
|
{
|
|
animationInProgress = false;
|
|
}
|
|
|
|
void MenuDialog::updateGeometry()
|
|
{
|
|
int width = 0;
|
|
int rowsCo = ui->listWidget->model()->rowCount();
|
|
for (int i=0; i<rowsCo; i++) {
|
|
QModelIndex modelIndex = ui->listWidget->model()->index(i, 0);
|
|
int w = ui->listWidget->sizeHintForIndex(modelIndex).width();
|
|
if (w > width) width = w;
|
|
}
|
|
if (width == 0) width = ui->listWidget->sizeHintForColumn(0);
|
|
width += ui->listWidget->frameWidth() * 2;
|
|
if (ui->listWidget->verticalScrollBar()->isVisible()) width += ui->listWidget->verticalScrollBar()->width();
|
|
width += MENU_WIDTH_EXTRA_SPACE;
|
|
if (width < minWidth) width = minWidth;
|
|
else minWidth = width;
|
|
QScreen * screen = QGuiApplication::primaryScreen();
|
|
if (width > screen->availableGeometry().width()) width = screen->availableGeometry().width();
|
|
int height = screen->availableGeometry().height();
|
|
ui->listWidget->setFixedWidth(width);
|
|
ui->listWidget->setFixedHeight(height);
|
|
setMinimumWidth(width);
|
|
setMinimumHeight(height);
|
|
setGeometry(0, 0, width, height);
|
|
}
|
|
|
|
bool MenuDialog::eventFilter(QObject *watched, QEvent *event)
|
|
{
|
|
if (watched == parent() && event->type() == QEvent::Resize) {
|
|
updateGeometry();
|
|
}
|
|
return false;
|
|
}
|
|
|