GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
tab-bar.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2018-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 // This file implements a tab bar derived from QTabBar with a contextmenu
27 // and possibility to close a tab via double-left or middle mouse click.
28 
29 #if defined (HAVE_CONFIG_H)
30 # include "config.h"
31 #endif
32 
33 #include "tab-bar.h"
34 
35 namespace octave
36 {
38  : QTabBar (p), m_context_menu (new QMenu (this))
39  { }
40 
42  {
43  delete m_context_menu;
44  }
45 
46  // slots for tab navigation
48  {
49  switch_tab (-1);
50  }
51 
53  {
54  switch_tab (1);
55  }
56 
58  {
59 #if defined (HAVE_QTABWIDGET_SETMOVABLE)
60  switch_tab (-1, true);
61 #endif
62  }
63 
65  {
66 #if defined (HAVE_QTABWIDGET_SETMOVABLE)
67  switch_tab (1, true);
68 #endif
69  }
70 
71  void tab_bar::switch_tab (int direction, bool movetab)
72  {
73  int tabs = count ();
74 
75  if (tabs < 2)
76  return;
77 
78  int old_pos = currentIndex ();
79  int new_pos = currentIndex () + direction;
80 
81  if (new_pos < 0 || new_pos >= tabs)
82  new_pos = new_pos - direction*tabs;
83 
84  if (movetab)
85  {
86 #if defined (HAVE_QTABWIDGET_SETMOVABLE)
87  moveTab (old_pos, new_pos);
88  setCurrentIndex (old_pos);
89  setCurrentIndex (new_pos);
90 #endif
91  }
92  else
93  setCurrentIndex (new_pos);
94  }
95 
97  {
98  QString current_title = tabText (currentIndex ());
99  int tab_with_focus = 0;
100 
101  // Get all tab title and sort
102  QStringList tab_texts;
103 
104  for (int i = 0; i < count (); i++)
105  tab_texts.append (tabText (i));
106 
107  tab_texts.sort ();
108 
109  // Move tab into the order of the generated string list
110  for (int title = 0; title < tab_texts.count (); title++)
111  {
112  // Target tab is same as place of title in QStringList.
113  // Find index of next title in string list, leaving out the
114  // tabs (or titles) that were already moved.
115  for (int tab = title; tab < count (); tab++)
116  {
117  if (tabText (tab) == tab_texts.at (title))
118  {
119  // Index of next tile found, so move tab into next position
120  moveTab (tab, title);
121 
122  if (tab_texts.at (title) == current_title)
123  tab_with_focus = title;
124 
125  break;
126  }
127  }
128  }
129 
130  setCurrentIndex (tab_with_focus);
131  }
132 
133  // Reimplement mouse event for filtering out the desired mouse clicks
134  void tab_bar::mousePressEvent (QMouseEvent *me)
135  {
136  QPoint click_pos;
137  int clicked_idx = -1;
138 
139  // detect the tab where the click occurred
140  for (int i = 0; i < count (); i++)
141  {
142  click_pos = mapToGlobal (me->pos ());
143  if (tabRect (i).contains (mapFromGlobal (click_pos)))
144  {
145  clicked_idx = i;
146  break;
147  }
148  }
149 
150  // If a tab was clicked
151  if (clicked_idx >= 0)
152  {
153  int current_idx = currentIndex ();
154  int current_count = count ();
155 
156  // detect the mouse click
157  if ((me->type () == QEvent::MouseButtonDblClick
158  && me->button() == Qt::LeftButton)
159  || (me->type () != QEvent::MouseButtonDblClick
160  && me->button() == Qt::MidButton))
161  {
162  // Middle click or double click -> close the tab
163  // Make the clicked tab the current one and close it
164  setCurrentIndex (clicked_idx);
165  emit close_current_tab_signal (true);
166  // Was the closed tab before or after the previously current tab?
167  // According to the result, use previous index or reduce it by one
168  if (current_idx - clicked_idx > 0)
169  setCurrentIndex (current_idx - 1);
170  else if (current_idx - clicked_idx < 0)
171  setCurrentIndex (current_idx);
172  }
173  else if (me->type () != QEvent::MouseButtonDblClick
174  && me->button() == Qt::RightButton)
175  {
176  // Right click, show context menu
177  setCurrentIndex (clicked_idx);
178  if (! m_context_menu->exec (click_pos))
179  {
180  // No action selected, back to previous tab
181  setCurrentIndex (current_idx);
182  }
183  else if (count () < current_count)
184  {
185  // A tab was closed:
186  // Was the possibly only closed tab before or after the
187  // previously current tab? According to the result, use previous
188  // index or reduce it by one. Also prevent using a too large
189  // index if other or all files were closed.
190  int new_idx = count () - 1;
191  if (new_idx > 0)
192  {
193  if (current_idx - clicked_idx > 0)
194  new_idx = current_idx - 1;
195  else if (current_idx - clicked_idx < 0)
196  new_idx = current_idx;
197  }
198  if (new_idx >= 0)
199  setCurrentIndex (new_idx);
200  }
201  }
202  else
203  {
204  // regular handling of the mouse event
205  QTabBar::mousePressEvent (me);
206  }
207  }
208  else
209  {
210  // regular handling of the mouse event
211  QTabBar::mousePressEvent (me);
212  }
213  }
214 }
void close_current_tab_signal(bool)
void mousePressEvent(QMouseEvent *event)
Definition: tab-bar.cc:134
void switch_left_tab(void)
Definition: tab-bar.cc:47
void move_tab_left(void)
Definition: tab-bar.cc:57
void switch_tab(int direction, bool movetab=false)
Definition: tab-bar.cc:71
QMenu * m_context_menu
Definition: tab-bar.h:70
tab_bar(QWidget *p)
Definition: tab-bar.cc:37
void sort_tabs_alph(void)
Definition: tab-bar.cc:96
void switch_right_tab(void)
Definition: tab-bar.cc:52
void move_tab_right(void)
Definition: tab-bar.cc:64
~tab_bar(void)
Definition: tab-bar.cc:41