Merge remote-tracking branch 'origin/enhanced-tab-widget'

This commit is contained in:
Matthias Koefferlein 2022-10-13 22:46:46 +02:00
commit 48ec894b1e
14 changed files with 573 additions and 80 deletions

View File

@ -125,6 +125,10 @@
<file alias="m45_24px@2x.png">images/m45_24px@2x.png</file>
<file alias="m90_24px.png">images/m90_24px.png</file>
<file alias="m90_24px@2x.png">images/m90_24px@2x.png</file>
<file alias="menu_16px.png">images/menu_16px.png</file>
<file alias="menu_16px@2x.png">images/menu_16px@2x.png</file>
<file alias="menu_24px.png">images/menu_24px.png</file>
<file alias="menu_24px@2x.png">images/menu_24px@2x.png</file>
<file alias="move_24px.png">images/move_24px.png</file>
<file alias="move_24px@2x.png">images/move_24px@2x.png</file>
<file alias="move_simple_16px.png">images/move_simple_16px.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

166
src/icons/svg/menu_16px.svg Normal file
View File

@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="16"
height="16"
viewBox="0 0 4.2333332 4.2333335"
version="1.1"
id="svg1011"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="menu_16px.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1013"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="px"
showgrid="true"
units="px"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:bbox-nodes="true"
inkscape:snap-others="false"
inkscape:zoom="12.224789"
inkscape:cx="5.2352644"
inkscape:cy="7.2802895"
inkscape:window-width="1535"
inkscape:window-height="752"
inkscape:window-x="160"
inkscape:window-y="197"
inkscape:window-maximized="0"
inkscape:current-layer="layer1"
width="16px">
<inkscape:grid
type="xygrid"
id="grid1074"
spacingx="0.13229167"
spacingy="0.13229167"
empspacing="2" />
</sodipodi:namedview>
<defs
id="defs1008">
<linearGradient
id="linearGradient3600">
<stop
style="stop-color:#ff9f3f;stop-opacity:1;"
offset="0"
id="stop3602" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3604" />
</linearGradient>
<linearGradient
id="linearGradient5268">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5270" />
<stop
style="stop-color:#adadad;stop-opacity:1;"
offset="1"
id="stop5272" />
</linearGradient>
<linearGradient
id="linearGradient5280">
<stop
style="stop-color:#ababab;stop-opacity:1;"
offset="0"
id="stop5282" />
<stop
style="stop-color:#535353;stop-opacity:1;"
offset="1"
id="stop5284" />
</linearGradient>
<linearGradient
id="linearGradient5298">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop5300" />
<stop
id="stop5306"
offset="0.50000167"
style="stop-color:#8f8f8f;stop-opacity:1;" />
<stop
style="stop-color:#353535;stop-opacity:1;"
offset="1"
id="stop5302" />
</linearGradient>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="color:#000000;overflow:visible;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.52916667;stroke-linejoin:round;stroke-dashoffset:2.5;stroke-opacity:0.5;stroke-miterlimit:4;stroke-dasharray:none"
id="rect1249"
width="2.6458335"
height="0.5291667"
x="0.79374993"
y="0.79374999" />
<rect
style="color:#000000;overflow:visible;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.52916667;stroke-linejoin:round;stroke-dashoffset:2.5;stroke-opacity:0.5;stroke-miterlimit:4;stroke-dasharray:none"
id="rect1251"
width="2.6458335"
height="0.52916664"
x="0.79375011"
y="1.8520834" />
<rect
style="color:#000000;overflow:visible;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.52916667;stroke-linejoin:round;stroke-dashoffset:2.5;stroke-opacity:0.5;stroke-miterlimit:4;stroke-dasharray:none"
id="rect1253"
width="2.6458335"
height="0.52916682"
x="0.79374993"
y="2.9104168" />
<rect
style="fill:none;stroke:#865b26;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect3596"
width="4.2333326"
height="4.2333331"
x="3.3333333e-07"
y="3.3333333e-07"
inkscape:export-filename="/home/matthias/klayout/master/src/lay/lay/images/back.png"
inkscape:export-xdpi="27.093315"
inkscape:export-ydpi="27.093315" />
<rect
style="fill:none;fill-opacity:1;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5220"
width="4.2333336"
height="4.2333336"
x="-8.8817842e-16"
y="-7.7715612e-16"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25.399982"
inkscape:export-ydpi="25.399982" />
<rect
style="color:#000000;overflow:visible;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5"
id="rect946"
width="2.6458335"
height="0.5291667"
x="0.79374993"
y="0.79374999" />
<rect
style="color:#000000;overflow:visible;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5"
id="rect946-3"
width="2.6458335"
height="0.52916664"
x="0.79375011"
y="1.8520834" />
<rect
style="color:#000000;overflow:visible;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5"
id="rect1121"
width="2.6458335"
height="0.52916682"
x="0.79374993"
y="2.9104168" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

187
src/icons/svg/menu_24px.svg Normal file
View File

@ -0,0 +1,187 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="24"
height="24"
viewBox="0 0 6.3499998 6.3500002"
version="1.1"
id="svg1011"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="menu_24px.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1013"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="px"
showgrid="true"
units="px"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
inkscape:bbox-nodes="true"
inkscape:snap-others="false"
inkscape:zoom="17.288462"
inkscape:cx="14.518353"
inkscape:cy="13.187986"
inkscape:window-width="1535"
inkscape:window-height="752"
inkscape:window-x="160"
inkscape:window-y="197"
inkscape:window-maximized="0"
inkscape:current-layer="layer1"
width="16px">
<inkscape:grid
type="xygrid"
id="grid1074"
spacingx="0.13229167"
spacingy="0.13229167"
empspacing="2" />
</sodipodi:namedview>
<defs
id="defs1008">
<linearGradient
id="linearGradient3600">
<stop
style="stop-color:#ff9f3f;stop-opacity:1;"
offset="0"
id="stop3602" />
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3604" />
</linearGradient>
<linearGradient
id="linearGradient5268">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop5270" />
<stop
style="stop-color:#adadad;stop-opacity:1;"
offset="1"
id="stop5272" />
</linearGradient>
<linearGradient
id="linearGradient5280">
<stop
style="stop-color:#ababab;stop-opacity:1;"
offset="0"
id="stop5282" />
<stop
style="stop-color:#535353;stop-opacity:1;"
offset="1"
id="stop5284" />
</linearGradient>
<linearGradient
id="linearGradient5298">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop5300" />
<stop
id="stop5306"
offset="0.50000167"
style="stop-color:#8f8f8f;stop-opacity:1;" />
<stop
style="stop-color:#353535;stop-opacity:1;"
offset="1"
id="stop5302" />
</linearGradient>
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="color:#000000;overflow:visible;fill:none;fill-opacity:0.5;stroke:#ffffff;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5;stroke-opacity:0.5"
id="rect1173"
width="3.7041667"
height="0.5291667"
x="1.3229167"
y="1.3229166" />
<rect
style="color:#000000;overflow:visible;fill:none;fill-opacity:0.5;stroke:#ffffff;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5;stroke-opacity:0.5"
id="rect1175"
width="3.7041667"
height="0.5291667"
x="1.3229167"
y="4.4979167" />
<rect
style="color:#000000;overflow:visible;fill:none;fill-opacity:0.5;stroke:#ffffff;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5;stroke-opacity:0.5"
id="rect1177"
width="3.7041667"
height="0.5291667"
x="1.3229167"
y="2.9104166" />
<rect
style="fill:none;stroke:#865b26;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect3596"
width="4.2333326"
height="4.2333331"
x="3.3333333e-07"
y="3.3333333e-07"
inkscape:export-filename="/home/matthias/klayout/master/src/lay/lay/images/back.png"
inkscape:export-xdpi="27.093315"
inkscape:export-ydpi="27.093315" />
<rect
style="fill:none;fill-opacity:1;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5220"
width="4.2333336"
height="4.2333336"
x="-8.8817842e-16"
y="-7.7715612e-16"
inkscape:export-filename="/home/matthias/klayout/trunk/src/lay/images/find.png"
inkscape:export-xdpi="25.399982"
inkscape:export-ydpi="25.399982" />
<rect
style="color:#000000;overflow:visible;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5"
id="rect946"
width="3.7041667"
height="0.5291667"
x="1.3229167"
y="1.3229166" />
<rect
style="color:#000000;overflow:visible;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5"
id="rect1163"
width="3.7041667"
height="0.5291667"
x="1.3229167"
y="4.4979167" />
<rect
style="color:#000000;overflow:visible;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5"
id="rect1165"
width="3.7041667"
height="0.5291667"
x="1.3229167"
y="2.9104166" />
<rect
style="color:#000000;overflow:visible;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5"
id="rect1167"
width="3.7041667"
height="0.5291667"
x="1.3229167"
y="1.3229166" />
<rect
style="color:#000000;overflow:visible;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5"
id="rect1169"
width="3.7041667"
height="0.5291667"
x="1.3229167"
y="4.4979167" />
<rect
style="color:#000000;overflow:visible;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264582;stroke-linejoin:round;stroke-dashoffset:2.5"
id="rect1171"
width="3.7041667"
height="0.5291667"
x="1.3229167"
y="2.9104166" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -11,7 +11,7 @@ HEADERS = \
layClipDialog.h \
layControlWidgetStack.h \
layCrashMessage.h \
layEnhancedTabWidget.h \
layEnhancedTabBar.h \
layFillDialog.h \
layGSIHelpProvider.h \
layHelpAboutDialog.h \
@ -122,7 +122,7 @@ SOURCES = \
layClipDialog.cc \
layControlWidgetStack.cc \
layCrashMessage.cc \
layEnhancedTabWidget.cc \
layEnhancedTabBar.cc \
layFillDialog.cc \
layGSIHelpProvider.cc \
layHelpAboutDialog.cc \

View File

@ -21,7 +21,7 @@
*/
#include "layEnhancedTabWidget.h"
#include "layEnhancedTabBar.h"
#include <QAction>
#include <QActionGroup>
@ -35,18 +35,18 @@ namespace lay
// ---------------------------------------------------------------------------------------------
// EnhancedTabWidget implementation
EnhancedTabWidget::EnhancedTabWidget (QWidget *parent)
: QTabWidget (parent)
EnhancedTabBar::EnhancedTabBar (QWidget *parent)
: QTabBar (parent)
{
mp_list_tool_button = new QToolButton (this);
mp_list_tool_button->setAutoRaise (true);
mp_list_tool_button->setIcon (QIcon (QString::fromUtf8 (":/find_16px.png")));
mp_list_tool_button->setIconSize (QSize (20, 20));
mp_list_tool_button->hide ();
mp_list_tool_button->setIcon (QIcon (QString::fromUtf8 (":/menu_24px.png")));
mp_list_tool_button->setIconSize (QSize (24, 24));
mp_list_tool_button->setMenu (new QMenu (this));
mp_list_tool_button->setPopupMode (QToolButton::InstantPopup);
mp_list_tool_button->setToolButtonStyle (Qt::ToolButtonIconOnly);
mp_list_tool_button->setToolTip ( tr ("List of all opened views"));
setCornerWidget (mp_list_tool_button, Qt::TopRightCorner);
mp_list_tool_button->setToolTip (tr ("List of all opened views"));
connect (mp_list_tool_button->menu (), SIGNAL (aboutToShow()),
this, SLOT (list_tool_button_menu_about_to_show()));
@ -58,26 +58,29 @@ EnhancedTabWidget::EnhancedTabWidget (QWidget *parent)
this, SLOT (list_action_group_triggered(QAction *)));
}
EnhancedTabWidget::~EnhancedTabWidget () = default;
void EnhancedTabWidget::tabInserted (int index)
EnhancedTabBar::~EnhancedTabBar ()
{
QTabWidget::tabInserted (index);
// .. nothing yet ..
}
void EnhancedTabBar::tabInserted (int index)
{
QTabBar::tabInserted (index);
update_list_button_visibility ();
}
void EnhancedTabWidget::tabRemoved (int index)
void EnhancedTabBar::tabRemoved (int index)
{
QTabWidget::tabRemoved (index);
QTabBar::tabRemoved (index);
update_list_button_visibility ();
}
void EnhancedTabWidget::list_action_group_triggered (QAction *action)
void EnhancedTabBar::list_action_group_triggered (QAction *action)
{
setCurrentIndex (action->data ().toInt ());
}
void EnhancedTabWidget::list_tool_button_menu_about_to_show ()
void EnhancedTabBar::list_tool_button_menu_about_to_show ()
{
mp_list_tool_button->menu ()->clear ();
if (count () > 1) {
@ -91,11 +94,9 @@ void EnhancedTabWidget::list_tool_button_menu_about_to_show ()
}
}
void EnhancedTabWidget::update_list_button_visibility()
void EnhancedTabBar::update_list_button_visibility()
{
if (cornerWidget (Qt::TopRightCorner) != nullptr) {
cornerWidget (Qt::TopRightCorner)->setVisible (count () > 1);
}
mp_list_tool_button->setVisible (count () > 1);
}
}

View File

@ -24,7 +24,7 @@
#ifndef HDR_layEnhancedTabWidget
#define HDR_layEnhancedTabWidget
#include <QTabWidget>
#include <QTabBar>
class QActionGroup;
class QToolButton;
@ -32,14 +32,16 @@ class QToolButton;
namespace lay
{
class EnhancedTabWidget
: public QTabWidget
class EnhancedTabBar
: public QTabBar
{
Q_OBJECT
public:
EnhancedTabWidget (QWidget *parent);
~EnhancedTabWidget () override;
EnhancedTabBar (QWidget *parent);
~EnhancedTabBar () override;
QToolButton *menu_button () { return mp_list_tool_button; }
protected:
void tabInserted (int index) override;

View File

@ -397,8 +397,14 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection
QAction *action = new QAction (tr ("Close All"), this);
connect (action, SIGNAL (triggered ()), this, SLOT (close_all ()));
tabWidget->addAction (action);
action = new QAction (tr ("Close All Except Current"), this);
connect (action, SIGNAL (triggered ()), this, SLOT (close_all_but_current ()));
action = new QAction (tr ("Close All Except This"), this);
connect (action, SIGNAL (triggered ()), this, SLOT (close_all_but_this ()));
tabWidget->addAction (action);
action = new QAction (tr ("Close All Left"), this);
connect (action, SIGNAL (triggered ()), this, SLOT (close_all_left ()));
tabWidget->addAction (action);
action = new QAction (tr ("Close All Right"), this);
connect (action, SIGNAL (triggered ()), this, SLOT (close_all_right ()));
tabWidget->addAction (action);
dbgOn->setEnabled (true);
@ -468,6 +474,8 @@ MacroEditorDialog::MacroEditorDialog (lay::Dispatcher *pr, lym::MacroCollection
connect (replaceAllButton, SIGNAL (clicked ()), this, SLOT (replace_all_button_clicked ()));
connect (allVariables, SIGNAL (clicked (bool)), variableList, SLOT (set_show_all (bool)));
tabWidget->installEventFilter (this);
splitter->setCollapsible (1, false);
replaceFrame->hide ();
@ -1535,7 +1543,13 @@ MacroEditorDialog::eventFilter (QObject *obj, QEvent *event)
}
}
} else if (obj == tabWidget->tabBar () && dynamic_cast<QMouseEvent *> (event) != 0) {
// just spy on the events, don't eat them
QMouseEvent *mouse_event = dynamic_cast<QMouseEvent *> (event);
m_mouse_pos = mouse_event->pos ();
}
return false;
}
@ -2263,7 +2277,25 @@ END_PROTECTED
}
void
MacroEditorDialog::close_all_but_current ()
MacroEditorDialog::close_all_but_this ()
{
close_many (0);
}
void
MacroEditorDialog::close_all_left ()
{
close_many (-1);
}
void
MacroEditorDialog::close_all_right ()
{
close_many (1);
}
void
MacroEditorDialog::close_many (int r2c)
{
if (m_in_exec) {
return;
@ -2271,17 +2303,19 @@ MacroEditorDialog::close_all_but_current ()
BEGIN_PROTECTED
QWidget *cw = tabWidget->currentWidget ();
int ci = tabWidget->currentIndex ();
int ci = tabWidget->tabBar ()->tabAt (m_mouse_pos);
if (ci < 0) {
close_all ();
return;
}
std::set<QWidget *> removed;
for (int i = tabWidget->count (); i > 0; ) {
--i;
if (i != ci) {
if ((r2c == 0 && i != ci) ||
(r2c < 0 && i < ci) ||
(r2c > 0 && i > ci)) {
removed.insert (tabWidget->widget (i));
tabWidget->removeTab (i);
}
}
@ -2289,7 +2323,7 @@ BEGIN_PROTECTED
std::map <lym::Macro *, MacroEditorPage *> new_widgets;
for (std::map <lym::Macro *, MacroEditorPage *>::iterator p = m_tab_widgets.begin (); p != m_tab_widgets.end (); ++p) {
if (cw && p->second == cw) {
if (removed.find (p->second) == removed.end ()) {
new_widgets.insert (*p);
} else {
if (p->second) {

View File

@ -213,7 +213,9 @@ private slots:
void search_finished ();
void tab_close_requested (int);
void close_all ();
void close_all_but_current ();
void close_all_but_this ();
void close_all_left ();
void close_all_right ();
void replace_mode_button_clicked ();
void replace_next_button_clicked ();
void replace_all_button_clicked ();
@ -264,6 +266,7 @@ private:
void move_subfolder (lym::MacroCollection *source, lym::MacroCollection *target);
lay::MacroEditorPage *create_page (lym::Macro *macro);
void open_macro (lym::Macro *macro);
void close_many (int which_relative_to_current);
void ensure_writeable_collection_selected ();
void update_console_text ();
void start_exec (gsi::Interpreter *interpreter);
@ -303,6 +306,7 @@ private:
lay::Dispatcher *mp_plugin_root;
lym::MacroCollection *mp_root;
bool m_first_show;
QPoint m_mouse_pos;
bool m_debugging_on;
lym::Macro *mp_run_macro;
std::vector<lym::Macro *> m_macro_templates;

View File

@ -70,7 +70,7 @@
#include "layDialogs.h"
#include "laybasicConfig.h"
#include "layConfig.h"
#include "layEnhancedTabWidget.h"
#include "layEnhancedTabBar.h"
#include "layMainWindow.h"
#include "layHelpDialog.h"
#include "layNavigator.h"
@ -228,14 +228,43 @@ MainWindow::MainWindow (QApplication *app, const char *name, bool undo_enabled)
vbl->setContentsMargins (0, 0, 0, 0);
vbl->setSpacing (0);
mp_tab_widget = new EnhancedTabWidget (mp_main_frame);
vbl->addWidget (mp_tab_widget);
connect (mp_tab_widget, SIGNAL (currentChanged (int)), this, SLOT (view_selected (int)));
QHBoxLayout *vbh_tab = new QHBoxLayout (mp_main_frame);
vbh_tab->setSpacing (6);
vbl->addLayout (vbh_tab);
EnhancedTabBar *enh_tab_widget = new EnhancedTabBar (mp_main_frame);
mp_tab_bar = enh_tab_widget;
mp_tab_bar->installEventFilter (this);
vbh_tab->addWidget (enh_tab_widget);
vbh_tab->addWidget (enh_tab_widget->menu_button ());
connect (mp_tab_bar, SIGNAL (currentChanged (int)), this, SLOT (view_selected (int)));
#if QT_VERSION >= 0x040500
mp_tab_widget->setTabsClosable(true);
connect (mp_tab_widget, SIGNAL (tabCloseRequested (int)), this, SLOT (tab_close_requested (int)));
mp_tab_bar->setTabsClosable (true);
connect (mp_tab_bar, SIGNAL (tabCloseRequested (int)), this, SLOT (tab_close_requested (int)));
#endif
mp_tab_bar->setContextMenuPolicy (Qt::ActionsContextMenu);
QAction *action = new QAction (tr ("Close All"), this);
connect (action, SIGNAL (triggered ()), this, SLOT (close_all_views ()));
mp_tab_bar->addAction (action);
action = new QAction (tr ("Close All Except This"), this);
connect (action, SIGNAL (triggered ()), this, SLOT (close_all_except_this ()));
mp_tab_bar->addAction (action);
action = new QAction (tr ("Close All Left"), this);
connect (action, SIGNAL (triggered ()), this, SLOT (close_all_views_left ()));
mp_tab_bar->addAction (action);
action = new QAction (tr ("Close All Right"), this);
connect (action, SIGNAL (triggered ()), this, SLOT (close_all_views_right ()));
mp_tab_bar->addAction (action);
action = new QAction (this);
action->setSeparator (true);
mp_tab_bar->addAction (action);
action = new QAction (tr ("Clone Panel"), this);
connect (action, SIGNAL (triggered ()), this, SLOT (clone ()));
mp_tab_bar->addAction (action);
mp_hp_dock_widget = new QDockWidget (QObject::tr ("Cells"), this);
mp_hp_dock_widget->setObjectName (QString::fromUtf8 ("hp_dock_widget"));
mp_hp_stack = new ControlWidgetStack (mp_hp_dock_widget, "hp_stack");
@ -683,8 +712,8 @@ MainWindow::close_all ()
// Clear the tab bar
bool f = m_disable_tab_selected;
m_disable_tab_selected = true;
while (mp_tab_widget->count () > 0) {
mp_tab_widget->removeTab (mp_tab_widget->count () - 1);
while (mp_tab_bar->count () > 0) {
mp_tab_bar->removeTab (mp_tab_bar->count () - 1);
}
m_disable_tab_selected = f;
@ -2315,7 +2344,7 @@ MainWindow::view_selected (int index)
// Hint: setting the focus to the tab bar avoids problem with dangling keyboard focus.
// Sometimes, the focus was set to the hierarchy level spin buttons which caught Copy&Paste
// events in effect.
mp_tab_widget->setFocus ();
mp_tab_bar->setFocus ();
if (! m_disable_tab_selected) {
select_view (index);
@ -2336,7 +2365,7 @@ MainWindow::select_view (int index)
tl_assert (index >= 0 && index < int (views ()));
mp_tab_widget->setCurrentIndex (index);
mp_tab_bar->setCurrentIndex (index);
bool box_set = (m_synchronized_views && current_view () != 0);
db::DBox box;
@ -2565,7 +2594,7 @@ MainWindow::clone_current_view ()
bool f = m_disable_tab_selected;
m_disable_tab_selected = true;
int index = mp_tab_widget->insertTab (-1, mp_views.back (), tl::to_qstring (view->title ()));
int index = mp_tab_bar->insertTab (-1, tl::to_qstring (view->title ()));
m_disable_tab_selected = f;
view_created_event (index);
@ -2577,27 +2606,29 @@ MainWindow::clone_current_view ()
void
MainWindow::cm_close_all ()
{
interactive_close_view (-1, false);
interactive_close_view (0, views (), false, false);
}
void
MainWindow::cm_close ()
{
interactive_close_view (index_of (lay::LayoutView::current ()), false);
int current_index = index_of (lay::LayoutView::current ());
if (current_index >= 0) {
interactive_close_view (current_index, current_index + 1, false, false);
}
}
void
MainWindow::tab_close_requested (int index)
{
interactive_close_view (index, true);
interactive_close_view (index, index + 1, false, true);
}
void
MainWindow::interactive_close_view (int index, bool all_cellviews)
MainWindow::interactive_close_view (int from, int to, bool invert_range, bool all_cellviews)
{
if (index < 0) {
// close all views
// closes views in range [from, to[ (invert_range=false) or outside this range (invert_range=true)
if (invert_range || from + 1 != to) {
bool can_close = true;
@ -2605,7 +2636,11 @@ MainWindow::interactive_close_view (int index, bool all_cellviews)
std::string dirty_files;
std::set<std::string> seen_names;
for (index = 0; index < int (views ()); ++index) {
for (int index = 0; index < int (views ()); ++index) {
if ((index >= from && index < to) == invert_range) {
continue;
}
for (unsigned int i = 0; i < view (index)->cellviews (); ++i) {
@ -2653,28 +2688,31 @@ MainWindow::interactive_close_view (int index, bool all_cellviews)
if (can_close) {
BEGIN_PROTECTED
while (views () > 0) {
close_view (0);
for (int index = int (views ()); index > 0; ) {
--index;
if ((index >= from && index < to) != invert_range) {
close_view (index);
}
}
END_PROTECTED
}
} else if (view (index)) {
} else if (view (from)) {
std::vector <int> selected;
if (view (index)->cellviews () > 1) {
if (view (from)->cellviews () > 1) {
if (all_cellviews) {
for (int i = 0; i < int (view (index)->cellviews ()); ++i) {
for (int i = 0; i < int (view (from)->cellviews ()); ++i) {
selected.push_back (i);
}
} else {
SelectCellViewForm form (0, view (index), tl::to_string (QObject::tr ("Select Layouts To Close")));
form.set_selection (view (index)->active_cellview_index ());
SelectCellViewForm form (0, view (from), tl::to_string (QObject::tr ("Select Layouts To Close")));
form.set_selection (view (from)->active_cellview_index ());
if (form.exec () != QDialog::Accepted) {
return;
@ -2687,7 +2725,7 @@ MainWindow::interactive_close_view (int index, bool all_cellviews)
}
} else if (view (index)->cellviews () > 0) {
} else if (view (from)->cellviews () > 0) {
selected.push_back (0);
}
@ -2698,7 +2736,7 @@ MainWindow::interactive_close_view (int index, bool all_cellviews)
for (std::vector <int>::const_iterator i = selected.begin (); i != selected.end (); ++i) {
const lay::CellView &cv = view (index)->cellview (*i);
const lay::CellView &cv = view (from)->cellview (*i);
if (cv->layout ().is_editable () && cv->is_dirty ()) {
@ -2715,7 +2753,7 @@ MainWindow::interactive_close_view (int index, bool all_cellviews)
}
for (std::vector <int>::const_iterator ii = selected.begin (); ii != selected.end (); ++ii) {
if (view (index)->cellview (*ii)->name () == name) {
if (view (from)->cellview (*ii)->name () == name) {
--count;
}
}
@ -2758,14 +2796,14 @@ MainWindow::interactive_close_view (int index, bool all_cellviews)
BEGIN_PROTECTED
// Actually erase the selected cellviews
if (view (index)->cellviews () == selected.size ()) {
if (view (from)->cellviews () == selected.size ()) {
// all cellviews selected - simply close
close_view (index);
close_view (from);
} else {
std::sort (selected.begin (), selected.end ());
int offset = 0;
for (std::vector <int>::const_iterator i = selected.begin (); i != selected.end (); ++i) {
view (index)->erase_cellview ((unsigned int)(*i - offset));
view (from)->erase_cellview ((unsigned int)(*i - offset));
++offset;
}
}
@ -2775,19 +2813,58 @@ MainWindow::interactive_close_view (int index, bool all_cellviews)
}
} else {
close_view (index);
close_view (from);
}
}
}
void
MainWindow::clone ()
{
clone_current_view ();
}
void
MainWindow::close_current_view ()
{
close_view (index_of (lay::LayoutView::current ()));
}
void
MainWindow::close_all_views ()
{
cm_close_all ();
}
void
MainWindow::close_all_except_this ()
{
int index = mp_tab_bar->tabAt (m_mouse_pos);
if (index >= 0) {
interactive_close_view (index, index + 1, true, false);
}
}
void
MainWindow::close_all_views_left ()
{
int index = mp_tab_bar->tabAt (m_mouse_pos);
if (index >= 0) {
interactive_close_view (0, index, false, false);
}
}
void
MainWindow::close_all_views_right ()
{
int index = mp_tab_bar->tabAt (m_mouse_pos);
if (index >= 0) {
interactive_close_view (index + 1, views (), false, false);
}
}
void
MainWindow::close_view (int index)
{
@ -2806,7 +2883,7 @@ MainWindow::close_view (int index)
box = view (index)->viewport ().box ();
}
mp_tab_widget->removeTab (index);
mp_tab_bar->removeTab (index);
mp_view_stack->remove_widget (index);
mp_lp_stack->remove_widget (index);
mp_layer_toolbox_stack->remove_widget (index);
@ -3382,7 +3459,7 @@ MainWindow::create_view ()
bool f = m_disable_tab_selected;
m_disable_tab_selected = true;
int index = mp_tab_widget->insertTab (-1, mp_views.back (), tl::to_qstring (current_view ()->title ()));
int index = mp_tab_bar->insertTab (-1, tl::to_qstring (current_view ()->title ()));
m_disable_tab_selected = f;
view_created_event (index);
@ -3445,7 +3522,7 @@ MainWindow::create_or_load_layout (const std::string *filename, const db::LoadLa
bool f = m_disable_tab_selected;
m_disable_tab_selected = true;
int index = mp_tab_widget->insertTab (-1, mp_views.back (), QString ());
int index = mp_tab_bar->insertTab (-1, QString ());
update_tab_title (index);
m_disable_tab_selected = f;
view_created_event (index);
@ -3485,8 +3562,8 @@ MainWindow::update_tab_title (int i)
title += v->title ();
}
if (tl::to_string (mp_tab_widget->tabText (i)) != title) {
mp_tab_widget->setTabText (i, tl::to_qstring (title));
if (tl::to_string (mp_tab_bar->tabText (i)) != title) {
mp_tab_bar->setTabText (i, tl::to_qstring (title));
}
if (v) {
@ -3501,8 +3578,8 @@ MainWindow::update_tab_title (int i)
files += tl::to_string (tr ("(not saved)"));
}
}
if (tl::to_string (mp_tab_widget->tabToolTip (i)) != files) {
mp_tab_widget->setTabToolTip (i, tl::to_qstring (files));
if (tl::to_string (mp_tab_bar->tabToolTip (i)) != files) {
mp_tab_bar->setTabToolTip (i, tl::to_qstring (files));
}
}
}
@ -3958,6 +4035,17 @@ MainWindow::dragEnterEvent(QDragEnterEvent *event)
}
}
bool
MainWindow::eventFilter (QObject *watched, QEvent *event)
{
// spy on the mouse events of the tab bar so we can tell which tab the menu was issued on
if (watched == mp_tab_bar && dynamic_cast<QMouseEvent *> (event) != 0) {
m_mouse_pos = dynamic_cast<QMouseEvent *> (event)->pos ();
}
return QMainWindow::eventFilter (watched, event);
}
void
MainWindow::dropEvent(QDropEvent *event)
{

View File

@ -51,7 +51,7 @@
#include "tlDeferredExecution.h"
#include "gsi.h"
class QTabWidget;
class QTabBar;
class QToolBar;
class QLabel;
class QAction;
@ -632,6 +632,11 @@ public slots:
void exit ();
void close_current_view ();
void close_view (int index);
void close_all_views ();
void close_all_except_this ();
void close_all_views_left ();
void close_all_views_right ();
void clone ();
void tab_close_requested (int);
void open_recent (size_t n);
void open_recent_session (size_t n);
@ -675,6 +680,7 @@ protected:
void update_content ();
void do_update_menu ();
void do_update_mru_menus ();
bool eventFilter (QObject *watched, QEvent *event);
private:
lay::Dispatcher m_dispatcher;
@ -682,7 +688,8 @@ private:
TextProgressDelegate m_text_progress;
// Main menu
QTabWidget *mp_tab_widget;
QTabBar *mp_tab_bar;
QPoint m_mouse_pos;
QToolBar *mp_tool_bar;
QDockWidget *mp_navigator_dock_widget;
lay::Navigator *mp_navigator;
@ -802,7 +809,7 @@ private:
int dirty_files (std::string &dirty_files);
void load_layer_props_from_file (const std::string &fn);
void interactive_close_view (int index, bool all_cellviews);
void interactive_close_view (int from, int to, bool invert_range, bool all_cellviews);
void call_on_current_view (void (lay::LayoutView::*func) (), const std::string &op_desc);
void current_view_changed ();
void update_window_title ();