Mercurial > octave
changeset 29467:80457383d5e1
allow rotated tabs in the file editor (bug #60276)
* gui-preferences-ed.h: define new preference names and default values
* file-editor.cc (notice_settings): set rotation mode for tabs,
compute height and width depending on rotation, set style sheet
with desired sizes, omit close button in case of rotation
* settings-dialog.cc (settings_dialog): initials new items with the values
from the settings file;
(write_changed_settings): write current values into the settings file
* settings-dialog.ui: new preferences for tab rotation and max. tab width
* tab-bar.cc (set_rotated): new function for settings the rotation state;
(tabSizeHint): reimplemented size hint allowing rotated tabs;
(paintEvent): reimplemented paint event allowing rotated tabs
* tab-bar.h new functions set_rotated, tabSizeHint, and paintEvent,
new class variable m_rotated
author | Torsten Lilge <ttl-octave@mailbox.org> |
---|---|
date | Sun, 28 Mar 2021 22:55:08 +0200 |
parents | 7c8a70e4daad |
children | 46def32e6806 |
files | libgui/src/gui-preferences-ed.h libgui/src/m-editor/file-editor.cc libgui/src/settings-dialog.cc libgui/src/settings-dialog.ui libgui/src/tab-bar.cc libgui/src/tab-bar.h |
diffstat | 6 files changed, 182 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- a/libgui/src/gui-preferences-ed.h Sun Mar 28 15:35:05 2021 -0400 +++ b/libgui/src/gui-preferences-ed.h Sun Mar 28 22:55:08 2021 +0200 @@ -204,6 +204,12 @@ const gui_pref ed_tab_position ("editor/tab_position", QVariant (QTabWidget::North)); +const gui_pref +ed_tabs_rotated ("editor/tabs_rotated", QVariant (false)); + +const gui_pref +ed_tabs_max_width ("editor/tabs_max_width", QVariant (0)); + // File handling const gui_pref
--- a/libgui/src/m-editor/file-editor.cc Sun Mar 28 15:35:05 2021 -0400 +++ b/libgui/src/m-editor/file-editor.cc Sun Mar 28 22:55:08 2021 +0200 @@ -1238,26 +1238,24 @@ int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); m_tool_bar->setIconSize (QSize (icon_size, icon_size)); - // Tab position + // Tab position and rotation QTabWidget::TabPosition pos = static_cast<QTabWidget::TabPosition> (settings->value (ed_tab_position).toInt ()); + bool rotated = settings->value (ed_tabs_rotated).toBool (); m_tab_widget->setTabPosition (pos); - // Update style sheet properties depending on position - QString width_str ("width"); - QString height_str ("height"); - if (pos == QTabWidget::West || pos == QTabWidget::East) - { - width_str = QString ("height"); - height_str = QString ("width"); - } - - // Min and max width for full path titles - int tab_width_min = settings->value (ed_notebook_tab_width_min) - .toInt (); - int tab_width_max = settings->value (ed_notebook_tab_width_max) - .toInt (); + if (rotated) + m_tab_widget->setTabsClosable (false); // No close buttons + // FIXME: close buttons can not be correctly placed in rotated tabs + + // Get the tab bar and set the rotation + int rotation = rotated; + if (pos == QTabWidget::West) + rotation = -rotation; + + tab_bar *bar = m_tab_widget->get_tab_bar (); + bar->set_rotated (rotation); // Get suitable height of a tab related to font and icon size int height = 1.5*QFontMetrics (m_tab_widget->font ()).height (); @@ -1265,13 +1263,32 @@ if (is > height) height = is; - // Style sheet for tab height - QString style_sheet = QString ("QTabBar::tab {max-" + height_str + ": %1px;}") - .arg (height); - - // Style sheet for tab height together with width + // Calculate possibly limited width and set the elide mode + int chars = settings->value (ed_tabs_max_width).toInt (); + int width = 9999; + if (chars > 0) + width = chars * QFontMetrics (m_tab_widget->font ()).averageCharWidth (); + + // Get tab bar size properties for style sheet depending on rotation + QString width_str ("width"); + QString height_str ("height"); + if ((pos == QTabWidget::West) || (pos == QTabWidget::East)) + { + width_str = QString ("height"); + height_str = QString ("width"); + } + + QString style_sheet + = QString ("QTabBar::tab {max-" + height_str + ": %1px;\n" + "max-" + width_str + ": %2px; }") + .arg (height).arg (width); + + // Style sheet for tab height together with width when full path is shown if (settings->value (ed_long_window_title).toBool ()) { + // Min and max width for full path titles + int tab_width_min = settings->value (ed_notebook_tab_width_min).toInt (); + int tab_width_max = settings->value (ed_notebook_tab_width_max).toInt (); style_sheet = QString ("QTabBar::tab " " {max-" + height_str + ": %1px;" " min-" + width_str + ": %2px;" @@ -1279,21 +1296,21 @@ .arg (height).arg (tab_width_min).arg (tab_width_max); m_tab_widget->setElideMode (Qt::ElideLeft); } - else - { - m_tab_widget->setElideMode (Qt::ElideNone); - } #if defined (Q_OS_MAC) // FIXME: This is a workaround for missing tab close buttons on MacOS // in several Qt versions (https://bugreports.qt.io/browse/QTBUG-61092) - QString close_button_css - ("QTabBar::close-button" - " { width: 6px; image: url(:/actions/icons/widget-close.png);}\n" - "QTabBar::close-button:hover" - " { background-color: #cccccc; }"); - - style_sheet = style_sheet + close_button_css; + if (! rotated) + { + QString close_button_css_mac ( + "QTabBar::close-button" + " { width: 6px; image: url(:/actions/icons/widget-close.png);" + " subcontrol-position: button; }\n" + "QTabBar::close-button:hover" + " { background-color: #cccccc; }"); + + style_sheet = style_sheet + close_button_css_mac; + } #endif m_tab_widget->setStyleSheet (style_sheet);
--- a/libgui/src/settings-dialog.cc Sun Mar 28 15:35:05 2021 -0400 +++ b/libgui/src/settings-dialog.cc Sun Mar 28 22:55:08 2021 +0200 @@ -311,6 +311,9 @@ editor_combox_tab_pos->setCurrentIndex (settings->value (ed_tab_position).toInt ()); + editor_cb_tabs_rotated->setChecked (settings->value (ed_tabs_rotated).toBool ()); + editor_sb_tabs_max_width->setValue (settings->value (ed_tabs_max_width).toInt ()); + int selected_comment_string, selected_uncomment_string; if (settings->contains (ed_comment_str.key)) // new version (radio buttons) @@ -961,6 +964,8 @@ settings->setValue (ed_default_eol_mode.key, combo_eol_mode->currentIndex ()); settings->setValue (ed_tab_position.key, editor_combox_tab_pos->currentIndex ()); + settings->setValue (ed_tabs_rotated.key, editor_cb_tabs_rotated->isChecked ()); + settings->setValue (ed_tabs_max_width.key, editor_sb_tabs_max_width->value ()); // Comment strings int rb_uncomment = 0;
--- a/libgui/src/settings-dialog.ui Sun Mar 28 15:35:05 2021 -0400 +++ b/libgui/src/settings-dialog.ui Sun Mar 28 22:55:08 2021 +0200 @@ -32,7 +32,7 @@ </size> </property> <property name="currentIndex"> - <number>0</number> + <number>2</number> </property> <widget class="QWidget" name="tab_general"> <property name="enabled"> @@ -863,7 +863,7 @@ <x>0</x> <y>0</y> <width>1021</width> - <height>1529</height> + <height>1530</height> </rect> </property> <layout class="QVBoxLayout" name="verticalLayout_16"> @@ -1225,6 +1225,32 @@ <property name="orientation"> <enum>Qt::Horizontal</enum> </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QCheckBox" name="editor_cb_tabs_rotated"> + <property name="toolTip"> + <string><html><head/><body><p>Roate tabs: Vertical when at top or bottom and horizontal when left or right. The close button is not shown in rotated tabs.</p></body></html></string> + </property> + <property name="text"> + <string>Rotated tabs</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_33"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> @@ -1238,7 +1264,7 @@ <item row="0" column="0"> <widget class="QLabel" name="label_30"> <property name="text"> - <string>Tab position</string> + <string>Position</string> </property> </widget> </item> @@ -1342,6 +1368,40 @@ </property> </spacer> </item> + <item row="0" column="3"> + <layout class="QHBoxLayout" name="horizontalLayout_15"> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Max. tab width in chars (0: no limit)</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="editor_sb_tabs_max_width"> + <property name="toolTip"> + <string><html><head/><body><p>Max. width of a tab in characters (average char. width). Especially useful for rotated tabs.</p></body></html></string> + </property> + <property name="maximum"> + <number>64</number> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_38"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> </layout> </item> </layout>
--- a/libgui/src/tab-bar.cc Sun Mar 28 15:35:05 2021 -0400 +++ b/libgui/src/tab-bar.cc Sun Mar 28 22:55:08 2021 +0200 @@ -34,12 +34,21 @@ namespace octave { + // + // Reimplemented QTabbar + // + tab_bar::tab_bar (QWidget *p) : QTabBar (p), m_context_menu (new QMenu (this)) { } tab_bar::~tab_bar (void) { } + void tab_bar::set_rotated (int rotated) + { + m_rotated = rotated; + } + // slots for tab navigation void tab_bar::switch_left_tab (void) { @@ -121,6 +130,48 @@ setCurrentIndex (tab_with_focus); } + // Reimplemented size hint allowing rotated tabs + QSize tab_bar::tabSizeHint (int idx) const + { + QSize s = QTabBar::tabSizeHint (idx); + if (m_rotated) + s.transpose(); + + return s; + } + + // Reimplemented paint event allowing rotated tabs + void tab_bar::paintEvent(QPaintEvent *e) + { + // Just process the original event if not rotated + if (! m_rotated) + return QTabBar::paintEvent (e); + + // Process the event for rotated tabs + QStylePainter painter (this); + QStyleOptionTab opt; + + for (int idx = 0; idx < count(); idx++) + { + initStyleOption (&opt, idx); + painter.drawControl (QStyle::CE_TabBarTabShape, opt); + painter.save (); + + QSize s = opt.rect.size(); + s.transpose(); + QRect rect (QPoint (), s); + rect.moveCenter (opt.rect.center ()); + opt.rect = rect; + + QPoint p = tabRect (idx).center (); + painter.translate (p); + painter.rotate (-m_rotated*90); + painter.translate (-p); + painter.drawControl (QStyle::CE_TabBarTabLabel, opt); + painter.restore (); + } + } + // Reimplement mouse event for filtering out the desired mouse clicks void tab_bar::mousePressEvent (QMouseEvent *me) {
--- a/libgui/src/tab-bar.h Sun Mar 28 15:35:05 2021 -0400 +++ b/libgui/src/tab-bar.h Sun Mar 28 22:55:08 2021 +0200 @@ -31,11 +31,15 @@ #include <QMenu> #include <QMouseEvent> +#include <QSize> +#include <QStyleOptionTab> +#include <QStylePainter> #include <QTabBar> namespace octave { - // Subclassed QTabBar for usable tab-bar and reimplemented mouse event + // Subclassed QTabBar for usable tab-bar, rotated tabs and + // reimplemented mouse event class tab_bar : public QTabBar { @@ -47,7 +51,9 @@ ~tab_bar (void); + void set_rotated (int rotated); QMenu *get_context_menu (void) { return m_context_menu; }; + QSize tabSizeHint (int idx) const; signals: @@ -67,6 +73,7 @@ protected: + void paintEvent(QPaintEvent *e); void mousePressEvent(QMouseEvent *event); private: @@ -75,6 +82,7 @@ QMenu *m_context_menu; QList <QAction *> m_ctx_actions; + int m_rotated; }; }