Source code for menus

# -*- coding: utf-8 -*-

# Copyright Martin Manns
# Distributed under the terms of the GNU General Public License

# --------------------------------------------------------------------
# pyspread 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 3 of the License, or
# (at your option) any later version.
#
# pyspread is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyspread.  If not, see <http://www.gnu.org/licenses/>.
# --------------------------------------------------------------------

"""

**Provides**

* :class:`MenuBar`: QMenuBar, the main menubar
* :class:`FileMenu`: File menu for the main menubar
* :class:`EditMenu`: Edit menu for the main menubar
* :class:`ViewMenu`: View menu for the main menubar
* :class:`FormatMenu`: Format menu for the main menubar
* :class:`MacroMenu`: Macro menu for the main menubar
* :class:`HelpMenu`: Help menu for the main menubar
* :class:`FileHistoryMenu`: Menu showing recent files
* :class:`BorderChoiceMenu`: QMenu for choosing cell borders
* :class:`BorderWidthMenu`: QMenu for choosing the cell border width

"""

from functools import partial
from pathlib import Path

from PyQt5.QtWidgets import (
        QMenuBar, QMenu, QAction, QMainWindow, QWidget, QToolBar)

try:
    import matplotlib.figure as matplotlib_figure
except ImportError:
    matplotlib_figure = None

try:
    from pyspread.actions import MainWindowActions
    from pyspread.icons import Icon
except ImportError:
    from actions import MainWindowActions
    from icons import Icon





[docs]class FileMenu(QMenu): """File menu for the main menubar""" def __init__(self, parent: QWidget, actions: MainWindowActions): """ :param parent: Parent widget :param actions: Main window actions """ super().__init__('&File', parent) self.parent = parent self.addAction(actions.new) self.addAction(actions.open) self.history_submenu = FileHistoryMenu(self, actions) self.history_action = self.addMenu(self.history_submenu) self.addSeparator() self.addAction(actions.save) self.addAction(actions.save_as) self.addSeparator() self.addAction(actions.imprt) self.addAction(actions.export) self.addSeparator() self.addAction(actions.approve) self.addSeparator() self.addAction(actions.clear_globals) self.addSeparator() self.addAction(actions.print_preview) self.addAction(actions.print) self.addSeparator() self.addAction(actions.preferences) self.addSeparator() self.addAction(actions.quit)
[docs]class EditMenu(QMenu): """Edit menu for the main menubar""" def __init__(self, parent: QWidget, actions: MainWindowActions): """ :param parent: Parent widget :param actions: Main window actions """ super().__init__('&Edit', parent) self.addAction(actions.undo) self.addAction(actions.redo) self.addSeparator() self.addAction(actions.cut) self.addAction(actions.copy) self.addAction(actions.copy_results) self.addAction(actions.paste) self.addAction(actions.paste_as) self.addSeparator() self.addAction(actions.find) self.addAction(actions.replace) self.addSeparator() self.addAction(actions.toggle_selection_mode) self.addSeparator() self.addAction(actions.quote) self.addSeparator() self.addAction(actions.insert_rows) self.addAction(actions.insert_columns) self.addAction(actions.insert_table) self.addSeparator() self.addAction(actions.delete_rows) self.addAction(actions.delete_columns) self.addAction(actions.delete_table) self.addSeparator() self.addAction(actions.resize_grid)
[docs]class ViewMenu(QMenu): """View menu for the main menubar""" def __init__(self, parent: QWidget, actions: MainWindowActions): """ :param parent: Parent widget :param actions: Main window actions """ super().__init__('&View', parent) self.addAction(actions.fullscreen) self.addSeparator() self.toolbar_submenu = self.addMenu('Toolbars') self.toolbar_submenu.addAction(actions.toggle_main_toolbar) self.toolbar_submenu.addAction(actions.toggle_macro_toolbar) self.toolbar_submenu.addAction(actions.toggle_format_toolbar) self.toolbar_submenu.addAction(actions.toggle_find_toolbar) self.addAction(actions.toggle_entry_line_dock) self.addAction(actions.toggle_macro_dock) self.addSeparator() self.addAction(actions.goto_cell) self.addSeparator() self.addAction(actions.toggle_spell_checker) self.addSeparator() self.addAction(actions.zoom_in) self.addAction(actions.zoom_out) self.addAction(actions.zoom_1) self.addSeparator() self.addAction(actions.refresh_cells) self.addAction(actions.toggle_periodic_updates) self.addSeparator() self.addAction(actions.show_frozen)
[docs]class FormatMenu(QMenu): """Format menu for the main menubar""" def __init__(self, parent: QWidget, actions: MainWindowActions): """ :param parent: Parent widget :param actions: Main window actions """ super().__init__('&Format', parent) self.addAction(actions.copy_format) self.addAction(actions.paste_format) self.addSeparator() self.addAction(actions.font) self.addAction(actions.bold) self.addAction(actions.italics) self.addAction(actions.underline) self.addAction(actions.strikethrough) self.addSeparator() self.renderer_submenu = self.addMenu('Cell renderer') self.renderer_submenu.addAction(actions.text) self.renderer_submenu.addAction(actions.image) self.renderer_submenu.addAction(actions.markup) if matplotlib_figure is not None: self.renderer_submenu.addAction(actions.matplotlib) self.addAction(actions.freeze_cell) self.addAction(actions.lock_cell) self.addAction(actions.button_cell) self.addSeparator() self.addAction(actions.merge_cells) self.addSeparator() self.rotation_submenu = self.addMenu('Rotation') self.rotation_submenu.addAction(actions.rotate_0) self.rotation_submenu.addAction(actions.rotate_90) self.rotation_submenu.addAction(actions.rotate_180) self.rotation_submenu.addAction(actions.rotate_270) self.justification_submenu = self.addMenu('Justification') self.justification_submenu.addAction(actions.justify_left) self.justification_submenu.addAction(actions.justify_center) self.justification_submenu.addAction(actions.justify_right) self.justification_submenu.addAction(actions.justify_fill) self.alignment_submenu = self.addMenu('Alignment') self.alignment_submenu.addAction(actions.align_top) self.alignment_submenu.addAction(actions.align_center) self.alignment_submenu.addAction(actions.align_bottom) self.addSeparator() self.border_submenu = BorderChoiceMenu(actions) self.addMenu(self.border_submenu) self.line_width_submenu = BorderWidthMenu(actions) self.addMenu(self.line_width_submenu) self.addSeparator() self.addAction(actions.text_color) self.addAction(actions.line_color) self.addAction(actions.background_color)
[docs]class MacroMenu(QMenu): """Macro menu for the main menubar""" def __init__(self, parent: QWidget, actions: MainWindowActions): """ :param parent: Parent widget :param actions: Main window actions """ super().__init__('&Macro', parent) self.addAction(actions.insert_image) if matplotlib_figure is not None: self.addAction(actions.insert_chart)
[docs]class HelpMenu(QMenu): """Help menu for the main menubar""" def __init__(self, parent: QWidget, actions: MainWindowActions): """ :param parent: Parent widget :param actions: Main window actions """ super().__init__('&Help', parent) self.addAction(actions.manual) self.addAction(actions.tutorial) self.addSeparator() self.addAction(actions.dependencies) self.addSeparator() self.addAction(actions.about)
[docs]class FileHistoryMenu(QMenu): """Menu that displays the file history""" def __init__(self, parent: QWidget, actions: MainWindowActions): """ :param parent: Parent widget :param actions: Main window actions """ super().__init__('&Recent files', parent) self.main_window = parent.parent.main_window
[docs] def update(self): """Updates file history menu""" self.clear() settings = self.main_window.settings for posixpath in settings.file_history[:settings.max_file_history]: filepath = Path(posixpath) if filepath.is_file(): action = QAction(filepath.name, self) action.setStatusTip(posixpath) self.addAction(action) action.triggered.connect(self.on_recent)
[docs] def on_recent(self): """Event handler for file history menu""" posixpath = self.sender().statusTip() self.main_window.workflows.file_open_recent(posixpath)
[docs]class BorderChoiceMenu(QMenu): """QMenu for choosing cell borders that shall be manipulated""" def __init__(self, actions: MainWindowActions): """ :param actions: Main window actions """ super().__init__() self.setTitle("Formatted borders") self.setIcon(Icon.border_menu) self.addAction(actions.format_borders_all) self.addAction(actions.format_borders_top) self.addAction(actions.format_borders_bottom) self.addAction(actions.format_borders_left) self.addAction(actions.format_borders_right) self.addAction(actions.format_borders_outer) self.addAction(actions.format_borders_inner) self.addAction(actions.format_borders_top_bottom)
[docs]class BorderWidthMenu(QMenu): """QMenu for choosing the cell border width""" def __init__(self, actions: MainWindowActions): """ :param actions: Main window actions """ super().__init__() self.setTitle("Border width") self.setIcon(Icon.format_borders) self.addAction(actions.format_borders_0) self.addAction(actions.format_borders_1) self.addAction(actions.format_borders_2) self.addAction(actions.format_borders_4) self.addAction(actions.format_borders_8) self.addAction(actions.format_borders_16) self.addAction(actions.format_borders_32) self.addAction(actions.format_borders_64)
[docs]class GridContextMenu(QMenu): """Context menu for grid""" def __init__(self, actions: MainWindowActions): """ :param actions: Main window actions """ super().__init__() self.addAction(actions.cut) self.addAction(actions.copy) self.addAction(actions.copy_results) self.addAction(actions.copy_format) self.addAction(actions.paste) self.addAction(actions.paste_as) self.addAction(actions.paste_format) self.addSeparator() self.addAction(actions.toggle_selection_mode) self.addSeparator() self.addAction(actions.copy_format) self.addAction(actions.paste_format) self.addSeparator() self.addAction(actions.toggle_selection_mode) self.addSeparator() self.addAction(actions.quote) self.addSeparator() self.addAction(actions.insert_rows) self.addAction(actions.insert_columns) self.addAction(actions.insert_table) self.addSeparator() self.addAction(actions.delete_rows) self.addAction(actions.delete_columns) self.addAction(actions.delete_table)
[docs]class HorizontalHeaderContextMenu(QMenu): """Context menu for horizontal grid header""" def __init__(self, actions: MainWindowActions): """ :param actions: Main window actions """ super().__init__() self.addAction(actions.insert_columns) self.addAction(actions.delete_columns)
[docs]class VerticalHeaderContextMenu(QMenu): """Context menu for vertical grid header""" def __init__(self, actions: MainWindowActions): """ :param actions: Main window actions """ super().__init__() self.addAction(actions.insert_rows) self.addAction(actions.delete_rows)
[docs]class TableChoiceContextMenu(QMenu): """Context menu for table choice""" def __init__(self, actions: MainWindowActions): """ :param actions: Main window actions """ super().__init__() self.addAction(actions.insert_table) self.addAction(actions.delete_table)
[docs]class ToolbarManagerMenu(QMenu): """Menu with all actions of a toolbar that allows toggling visibility""" def __init__(self, toolbar: QToolBar): """ :param toolbar: Toolbar that the menu is managing """ super().__init__() self.toolbar = toolbar for action in toolbar.actions(): if action.isSeparator(): self.addSeparator() else: self.addAction(self._get_toggle_action(action)) self.update_checked_states()
[docs] def _get_toggle_action(self, action: QAction) -> QAction: """Returns a toggle action for a toolbar action :param action: Toolbar action for which the toggle state is returned """ taction = QAction(action.icon(), action.text(), action, checkable=True) taction.triggered.connect(partial(self.on_toggled, action)) return taction
[docs] def update_checked_states(self): """Updates checked states""" for tool_action, action in zip(self.toolbar.actions(), self.actions()): action.setChecked(tool_action.isVisible())
[docs] def on_toggled(self, action: QAction, toggled: bool): """Action toggle event handler :param action: Toolbar action for which visibility is toggled :param toggled: If False then action is set invisible and vice versa """ action.setVisible(toggled)