mirror of
https://invent.kde.org/graphics/okular
synced 2024-10-02 14:14:10 +00:00
Replace ToolAction by ToggleActionMenu
Summary: This replaces ToolAction by a near-drop-in replacement named ToggleActionMenu. The new annotation toolbar already uses this (D15580). Unlike ToolAction, ToggleActionMenu inherits from KActionMenu to be more flexible. * Menu can be set from outside, not hard coded. * Default action for toolbar button is controllable from outside. (Theoretically, the button could trigger //anything// now.) * KActionMenu instead of KSelectAction: - Pluggable in other menus, thus called “Menu”. - Doesn’t make the actions exclusive, so //any// actions can be added to the menu. * ImplicitDefaultAction mode can choose the default action of the toolbar buttons automatically, by looking for the first checked action in the menu. Toolbar buttons use the default action //of// this menu, not this menu itself as action. Because the default action is configurable now, D21622 and D21635 (where we tried to fine-tune ToolAction) become obsolete. Screenshot: Everything like before, here with mouse_selecttool added to Tools menu to show submenu capability. {F6884228} Test Plan: ToolAction replacement and ImplicitDefaultAction mode: * Open Okular and look at toolbar button -> has correct tool selected. * Open a document. * Look at toolbar button menu -> Correct menu entries (like before, with ToolAction). * Select some selection tools through shortcuts and toolbar button -> behaves correctly. Usage as submenu: * Add ToggleActionMenu ("mouse_selecttool") to menubar (..../kxmlgui5/okular/part.rc) -> Submenu looks correctly, has no checkbox attached and so on... Toolbar buttons: * Add diverse other actions to the menu -> still works as before. * Add actions when toolbar buttons are already created -> actions are added to existing buttons. * setDefaultAction() to some completely unrelated action. -> ToggleActionMenu does not get confused. Reviewers: simgunz Reviewed By: simgunz Subscribers: aacid, ngraham, simgunz, okular-devel Tags: #okular Differential Revision: https://phabricator.kde.org/D21971
This commit is contained in:
parent
5dfbee0a00
commit
c6d937ab0d
|
@ -395,7 +395,7 @@ set(okularpart_SRCS
|
|||
ui/thumbnaillist.cpp
|
||||
ui/toc.cpp
|
||||
ui/tocmodel.cpp
|
||||
ui/toolaction.cpp
|
||||
ui/toggleactionmenu.cpp
|
||||
ui/videowidget.cpp
|
||||
ui/layers.cpp
|
||||
ui/signatureguiutils.cpp
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
#include "pageviewannotator.h"
|
||||
#include "pageviewmouseannotation.h"
|
||||
#include "priorities.h"
|
||||
#include "toolaction.h"
|
||||
#include "toggleactionmenu.h"
|
||||
#include "okmenutitle.h"
|
||||
#ifdef HAVE_SPEECH
|
||||
#include "tts.h"
|
||||
|
@ -241,6 +241,7 @@ public:
|
|||
QAction * aSpeakPauseResume;
|
||||
KActionCollection * actionCollection;
|
||||
QActionGroup * mouseModeActionGroup;
|
||||
ToggleActionMenu * aMouseModeMenu;
|
||||
QAction * aFitWindowToPage;
|
||||
|
||||
int setting_viewCols;
|
||||
|
@ -705,18 +706,23 @@ void PageView::setupActions( KActionCollection * ac )
|
|||
d->aMouseMagnifier->setActionGroup( d->mouseModeActionGroup );
|
||||
d->aMouseMagnifier->setChecked( Okular::Settings::mouseMode() == Okular::Settings::EnumMouseMode::Magnifier );
|
||||
|
||||
// Mouse-Mode action menu
|
||||
d->aMouseModeMenu = new ToggleActionMenu( QIcon(),QString(), this,
|
||||
ToggleActionMenu::MenuButtonPopup,
|
||||
ToggleActionMenu::ImplicitDefaultAction );
|
||||
d->aMouseModeMenu->addAction( d->aMouseSelect );
|
||||
d->aMouseModeMenu->addAction( d->aMouseTextSelect );
|
||||
d->aMouseModeMenu->addAction( d->aMouseTableSelect );
|
||||
d->aMouseModeMenu->suggestDefaultAction( d->aMouseTextSelect );
|
||||
d->aMouseModeMenu->setText( i18nc( "@action", "Selection Tools" ) );
|
||||
ac->addAction( QStringLiteral( "mouse_selecttools" ), d->aMouseModeMenu );
|
||||
|
||||
d->aToggleAnnotator = new KToggleAction(QIcon::fromTheme( QStringLiteral("draw-freehand") ), i18n("&Review"), this);
|
||||
ac->addAction(QStringLiteral("mouse_toggle_annotate"), d->aToggleAnnotator );
|
||||
d->aToggleAnnotator->setCheckable( true );
|
||||
connect( d->aToggleAnnotator, &QAction::toggled, this, &PageView::slotToggleAnnotator );
|
||||
ac->setDefaultShortcut(d->aToggleAnnotator, Qt::Key_F6);
|
||||
|
||||
ToolAction *ta = new ToolAction( this );
|
||||
ac->addAction( QStringLiteral("mouse_selecttools"), ta );
|
||||
ta->addAction( d->aMouseTextSelect );
|
||||
ta->addAction( d->aMouseSelect );
|
||||
ta->addAction( d->aMouseTableSelect );
|
||||
|
||||
// speak actions
|
||||
#ifdef HAVE_SPEECH
|
||||
d->aSpeakDoc = new QAction( QIcon::fromTheme( QStringLiteral("text-speak") ), i18n( "Speak Whole Document" ), this );
|
||||
|
@ -1258,6 +1264,8 @@ void PageView::updateActionState( bool haspages, bool documentChanged, bool hasf
|
|||
|
||||
if ( d->mouseModeActionGroup )
|
||||
d->mouseModeActionGroup->setEnabled( haspages );
|
||||
if ( d->aMouseModeMenu )
|
||||
d->aMouseModeMenu->setEnabled( haspages );
|
||||
|
||||
if ( d->aRotateClockwise )
|
||||
d->aRotateClockwise->setEnabled( haspages );
|
||||
|
|
152
ui/toggleactionmenu.cpp
Normal file
152
ui/toggleactionmenu.cpp
Normal file
|
@ -0,0 +1,152 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2019 by David Hurka <david.hurka@mailbox.org> *
|
||||
* *
|
||||
* Inspired by and replacing toolaction.h by: *
|
||||
* Copyright (C) 2004-2006 by Albert Astals Cid <aacid@kde.org> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "toggleactionmenu.h"
|
||||
|
||||
#include <QPointer>
|
||||
#include <QMenu>
|
||||
|
||||
ToggleActionMenu::ToggleActionMenu( QObject * parent )
|
||||
: ToggleActionMenu( QIcon(), QString(), parent )
|
||||
{
|
||||
}
|
||||
|
||||
ToggleActionMenu::ToggleActionMenu( const QString &text, QObject * parent )
|
||||
: ToggleActionMenu( QIcon(), text, parent )
|
||||
{
|
||||
}
|
||||
|
||||
ToggleActionMenu::ToggleActionMenu( const QIcon &icon,
|
||||
const QString &text,
|
||||
QObject * parent,
|
||||
PopupMode popupMode,
|
||||
MenuLogic logic )
|
||||
: KActionMenu( icon, text, parent ),
|
||||
m_defaultAction( nullptr ),
|
||||
m_suggestedDefaultAction( nullptr ),
|
||||
m_menuLogic( logic )
|
||||
{
|
||||
connect( this, &QAction::changed, this, &ToggleActionMenu::updateButtons );
|
||||
|
||||
if ( popupMode == DelayedPopup )
|
||||
{
|
||||
setDelayed( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
setDelayed( false );
|
||||
}
|
||||
setStickyMenu( false );
|
||||
|
||||
if ( logic & ImplicitDefaultAction )
|
||||
{
|
||||
connect( menu(), &QMenu::triggered, this, &ToggleActionMenu::setDefaultAction );
|
||||
}
|
||||
}
|
||||
|
||||
QWidget * ToggleActionMenu::createWidget( QWidget * parent )
|
||||
{
|
||||
QToolButton * button = qobject_cast< QToolButton * >( KActionMenu::createWidget( parent ) );
|
||||
if ( !button ) {
|
||||
// This function is used to add a button into the toolbar.
|
||||
// KActionMenu will plug itself as QToolButton.
|
||||
// So, if no QToolButton was returned, this was not called the intended way.
|
||||
return button;
|
||||
}
|
||||
|
||||
// Remove this menu action from the button,
|
||||
// so it doesn't compose a menu of this menu action and its own menu.
|
||||
button->removeAction( this );
|
||||
// The button has lost the menu now, let it use the correct menu.
|
||||
button->setMenu( menu() );
|
||||
|
||||
m_buttons.append( QPointer< QToolButton >( button ) );
|
||||
|
||||
// Apply other properties to the button.
|
||||
updateButtons();
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
void ToggleActionMenu::setDefaultAction( QAction *action )
|
||||
{
|
||||
m_defaultAction = action;
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
void ToggleActionMenu::suggestDefaultAction( QAction *action )
|
||||
{
|
||||
m_suggestedDefaultAction = action;
|
||||
}
|
||||
|
||||
QAction * ToggleActionMenu::checkedAction( QMenu *menu ) const
|
||||
{
|
||||
// Look at each action a in the menu whether it is checked.
|
||||
// If a is a menu, recursively call checkedAction().
|
||||
for ( QAction * a : menu->actions() )
|
||||
{
|
||||
if ( a->isChecked() )
|
||||
{
|
||||
return a;
|
||||
}
|
||||
else if ( a->menu() )
|
||||
{
|
||||
QAction * b = checkedAction( a->menu() );
|
||||
if ( b )
|
||||
{
|
||||
return b;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ToggleActionMenu::updateButtons()
|
||||
{
|
||||
for ( const QPointer< QToolButton > &button : qAsConst( m_buttons ) )
|
||||
{
|
||||
if ( button )
|
||||
{
|
||||
button->setDefaultAction( defaultAction() );
|
||||
|
||||
// Override some properties of the default action,
|
||||
// where the property of this menu makes more sense.
|
||||
button->setEnabled( isEnabled() );
|
||||
|
||||
if ( delayed() )
|
||||
{
|
||||
button->setPopupMode( QToolButton::DelayedPopup );
|
||||
}
|
||||
else if ( stickyMenu() )
|
||||
{
|
||||
button->setPopupMode( QToolButton::InstantPopup );
|
||||
}
|
||||
else
|
||||
{
|
||||
button->setPopupMode( QToolButton::MenuButtonPopup );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QAction * ToggleActionMenu::defaultAction()
|
||||
{
|
||||
if ( ( m_menuLogic & ImplicitDefaultAction ) && !m_defaultAction )
|
||||
{
|
||||
m_defaultAction = checkedAction( menu() );
|
||||
}
|
||||
if ( !m_defaultAction )
|
||||
{
|
||||
m_defaultAction = m_suggestedDefaultAction;
|
||||
}
|
||||
return m_defaultAction;
|
||||
}
|
155
ui/toggleactionmenu.h
Normal file
155
ui/toggleactionmenu.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2019 by David Hurka <david.hurka@mailbox.org> *
|
||||
* *
|
||||
* Inspired by and replacing toolaction.h by: *
|
||||
* Copyright (C) 2004-2006 by Albert Astals Cid <aacid@kde.org> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TOGGLEACTIONMENU_H
|
||||
#define TOGGLEACTIONMENU_H
|
||||
|
||||
#include <KActionMenu>
|
||||
#include <QToolButton>
|
||||
#include <QSet>
|
||||
|
||||
/**
|
||||
* @brief A KActionMenu, with allows to set the default action of its toolbar buttons.
|
||||
*
|
||||
* Usually, a KActionMenu creates toolbar buttons which reflect its own action properties
|
||||
* (icon, text, tooltip, checked state,...), as it is a QAction itself.
|
||||
*
|
||||
* ToggleActionMenu will use its own action properties only when plugged as submenu in another menu.
|
||||
* The default action of the toolbar buttons can easily be changed with the slot setDefaultAction().
|
||||
*
|
||||
* Naming: The user can *Toggle* the checked state of an *Action* by directly clicking the toolbar button,
|
||||
* but can also open a *Menu*.
|
||||
*
|
||||
* @par Intention
|
||||
* Setting the default action of the toolbar button can be useful for:
|
||||
* * Providing the most propably needed entry of a menu directly on the menu button.
|
||||
* * Showing the last used menu entry on the menu button, including its checked state.
|
||||
* The advantage is that the user often does not need to open the menu,
|
||||
* and that the toolbar button shows additional information
|
||||
* like checked state or the user's last selection.
|
||||
*
|
||||
* This shall replace the former ToolAction in Okular,
|
||||
* while beeing flexible enough for other (planned) action menus.
|
||||
*/
|
||||
class ToggleActionMenu : public KActionMenu
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* Defines how the menu behaves.
|
||||
*/
|
||||
enum MenuLogic {
|
||||
DefaultLogic = 0x0,
|
||||
/**
|
||||
* Automatically makes the triggered action the default action, even if in a submenu.
|
||||
* When a toolbar button is constructed,
|
||||
* the default action is set to the default action set with setDefaultAction() before,
|
||||
* otherwise to the first checked action in the menu,
|
||||
* otherwise to the action suggested with suggestDefaultAction().
|
||||
*/
|
||||
ImplicitDefaultAction = 0x1
|
||||
};
|
||||
|
||||
enum PopupMode {
|
||||
DelayedPopup,
|
||||
MenuButtonPopup
|
||||
};
|
||||
|
||||
explicit ToggleActionMenu( QObject *parent );
|
||||
ToggleActionMenu( const QString &text, QObject * parent );
|
||||
/**
|
||||
* Constructs an empty ToggleActionMenu.
|
||||
*
|
||||
* @param icon The icon of this menu, when plugged into another menu.
|
||||
* @param text The name of this menu, when plugged into another menu.
|
||||
* @param parent Parent @c QOject.
|
||||
* @param popupMode The popup mode of the toolbar buttons.
|
||||
* You will want to use @c DelayedPopup or @c MenuButtonPopup,
|
||||
* @c InstantPopup would make @c ToggleActionMenu pointless.
|
||||
* @param logic To define special behaviour of @c ToggleActionMenu,
|
||||
* to simplify the usage.
|
||||
*/
|
||||
ToggleActionMenu( const QIcon &icon,
|
||||
const QString &text,
|
||||
QObject *parent,
|
||||
PopupMode popupMode = MenuButtonPopup,
|
||||
MenuLogic logic = DefaultLogic
|
||||
);
|
||||
|
||||
QWidget *createWidget( QWidget *parent ) override;
|
||||
|
||||
/**
|
||||
* Returns the current default action of the toolbar buttons.
|
||||
*
|
||||
* In ImplicitDefaultAction mode,
|
||||
* when the default action was not yet set with setDefaultAction(),
|
||||
* it will determine it from the first checked action in the menu,
|
||||
* otherwise from the action set with suggestDefaultAction().
|
||||
*/
|
||||
QAction *defaultAction();
|
||||
|
||||
/**
|
||||
* Suggests a default action to be used as fallback.
|
||||
*
|
||||
* It will be used if the default action is not determined another way.
|
||||
* This is useful for ImplicitDefaultAction mode,
|
||||
* when you can not guarrantee that one action in the menu
|
||||
* will be checked.
|
||||
*
|
||||
* @note
|
||||
* In DefaultLogic mode, or when you already have called setDefaultAction(),
|
||||
* you have to use setDefaultAction() instead.
|
||||
*/
|
||||
void suggestDefaultAction( QAction * action );
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Sets the default action of the toolbar buttons.
|
||||
*
|
||||
* This action will be triggered by clicking directly on the toolbar buttons.
|
||||
* It will also set the text, icon, checked state, etc. of the toolbar buttons.
|
||||
*
|
||||
* @note
|
||||
* The default action will not set the enabled state or popup mode of the menu buttons.
|
||||
* These properties are still set by the corresponding properties of this ToggleActionMenu.
|
||||
*
|
||||
* @warning
|
||||
* The action will not be added to the menu,
|
||||
* it usually makes sense to addAction() it before to setDefaultAction() it.
|
||||
*
|
||||
* @see suggestDefaultAction()
|
||||
*/
|
||||
void setDefaultAction( QAction *action );
|
||||
|
||||
private:
|
||||
QAction *m_defaultAction;
|
||||
QAction *m_suggestedDefaultAction;
|
||||
QList< QPointer< QToolButton > > m_buttons;
|
||||
MenuLogic m_menuLogic;
|
||||
|
||||
/**
|
||||
* Returns the first checked action in @p menu and its submenus,
|
||||
* or nullptr if no action is checked.
|
||||
*/
|
||||
QAction *checkedAction( QMenu *menu ) const;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* Updates the toolbar buttons, using both the default action and properties of this menu itself.
|
||||
*
|
||||
* This ensures that the toolbar buttons reflect e. g. a disabled state of this menu.
|
||||
*/
|
||||
void updateButtons();
|
||||
};
|
||||
|
||||
#endif // TOGGLEACTIONMENU_H
|
|
@ -1,87 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2004-2006 by Albert Astals Cid <aacid@kde.org> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "toolaction.h"
|
||||
|
||||
#include <qmenu.h>
|
||||
#include <qtoolbar.h>
|
||||
#include <qtoolbutton.h>
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
ToolAction::ToolAction( QObject *parent )
|
||||
: KSelectAction( parent )
|
||||
{
|
||||
setText( i18n( "Selection Tools" ) );
|
||||
}
|
||||
|
||||
ToolAction::~ToolAction()
|
||||
{
|
||||
}
|
||||
|
||||
void ToolAction::addAction( QAction *action )
|
||||
{
|
||||
bool setDefault = !m_buttons.isEmpty() ? m_buttons.first()->menu()->actions().isEmpty() : false;
|
||||
for ( QToolButton *button : qAsConst(m_buttons) )
|
||||
if ( button )
|
||||
{
|
||||
button->menu()->addAction( action );
|
||||
if ( setDefault )
|
||||
button->setDefaultAction( action );
|
||||
}
|
||||
m_actions.append( action );
|
||||
}
|
||||
|
||||
QWidget* ToolAction::createWidget( QWidget *parent )
|
||||
{
|
||||
QToolBar *toolBar = qobject_cast< QToolBar * >( parent );
|
||||
if ( !toolBar )
|
||||
return nullptr;
|
||||
|
||||
QToolButton *button = new QToolButton( toolBar );
|
||||
button->setAutoRaise( true );
|
||||
button->setFocusPolicy( Qt::NoFocus );
|
||||
button->setIconSize( toolBar->iconSize() );
|
||||
button->setToolButtonStyle( toolBar->toolButtonStyle() );
|
||||
button->setPopupMode( QToolButton::MenuButtonPopup );
|
||||
button->setMenu( new QMenu( button ) );
|
||||
button->setCheckable( true );
|
||||
connect(toolBar, &QToolBar::iconSizeChanged, button, &QToolButton::setIconSize);
|
||||
connect(toolBar, &QToolBar::toolButtonStyleChanged, button, &QToolButton::setToolButtonStyle);
|
||||
connect(button, &QToolButton::triggered, toolBar, &QToolBar::actionTriggered);
|
||||
connect( button->menu(), &QMenu::triggered, this, &ToolAction::slotNewDefaultAction );
|
||||
|
||||
m_buttons.append( button );
|
||||
|
||||
if ( !m_actions.isEmpty() )
|
||||
{
|
||||
button->setDefaultAction( m_actions.first() );
|
||||
for ( QAction *action : qAsConst(m_actions) )
|
||||
{
|
||||
button->menu()->addAction( action );
|
||||
if ( action->isChecked() )
|
||||
button->setDefaultAction( action );
|
||||
}
|
||||
button->setToolTip( i18n("Click to use the current selection tool\nClick on the arrow to choose another selection tool") );
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
void ToolAction::slotNewDefaultAction( QAction *action )
|
||||
{
|
||||
for ( QToolButton *button : qAsConst(m_buttons) )
|
||||
if ( button )
|
||||
{
|
||||
button->setDefaultAction( action );
|
||||
button->setToolTip( i18n("Click to use the current selection tool\nClick on the arrow to choose another selection tool") );
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_toolaction.cpp"
|
|
@ -1,41 +0,0 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2004-2006 by Albert Astals Cid <aacid@kde.org> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TOOLACTION_H
|
||||
#define TOOLACTION_H
|
||||
|
||||
#include <qlist.h>
|
||||
#include <qpointer.h>
|
||||
|
||||
#include <KSelectAction>
|
||||
|
||||
class QToolButton;
|
||||
|
||||
class ToolAction : public KSelectAction
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ToolAction( QObject *parent = nullptr );
|
||||
~ToolAction() override;
|
||||
|
||||
void addAction( QAction *action );
|
||||
|
||||
protected:
|
||||
QWidget* createWidget( QWidget *parent ) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void slotNewDefaultAction( QAction *action );
|
||||
|
||||
private:
|
||||
QList< QPointer< QToolButton > > m_buttons;
|
||||
QList< QAction * > m_actions;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue