From a2faa42d0fd315b3f454e661fc9413d3569d7317 Mon Sep 17 00:00:00 2001 From: Hualet Wang Date: Thu, 22 Aug 2024 22:24:04 +0800 Subject: [PATCH 1/9] feat: remove the limit of term splitting a feature request from here: https://bbs.deepin.org/post/277237 --- src/main/mainwindow.cpp | 20 ++---- src/views/termwidget.cpp | 25 +------ src/views/termwidget.h | 7 -- src/views/termwidgetpage.cpp | 131 +++++++++++++++++++++-------------- 4 files changed, 85 insertions(+), 98 deletions(-) diff --git a/src/main/mainwindow.cpp b/src/main/mainwindow.cpp index a114a2f9f..d516030b5 100644 --- a/src/main/mainwindow.cpp +++ b/src/main/mainwindow.cpp @@ -1132,14 +1132,8 @@ inline void MainWindow::slotShortcutHorizonzalSplit() if (Service::instance()->isCountEnable()) { TermWidgetPage *page = currentPage(); if (page) { - if (page->currentTerminal()) { - int layer = page->currentTerminal()->getTermLayer(); - DSplitter *splitter = qobject_cast(page->currentTerminal()->parentWidget()); - if (1 == layer || (2 == layer && splitter && Qt::Horizontal == splitter->orientation())) { - page->split(Qt::Horizontal); - return ; - } - } + page->split(Qt::Horizontal); + return ; } } qInfo() << "can't split vertical again"; @@ -1151,14 +1145,8 @@ inline void MainWindow::slotShortcutVerticalSplit() if (Service::instance()->isCountEnable()) { TermWidgetPage *page = currentPage(); if (page) { - if (page->currentTerminal()) { - int layer = page->currentTerminal()->getTermLayer(); - DSplitter *splitter = qobject_cast(page->currentTerminal()->parentWidget()); - if (1 == layer || (2 == layer && splitter && Qt::Vertical == splitter->orientation())) { - page->split(Qt::Vertical); - return ; - } - } + page->split(Qt::Vertical); + return ; } } qInfo() << "can't split vertical again"; diff --git a/src/views/termwidget.cpp b/src/views/termwidget.cpp index acbe3b1f3..ee2c14ea2 100644 --- a/src/views/termwidget.cpp +++ b/src/views/termwidget.cpp @@ -481,15 +481,8 @@ void TermWidget::addMenuActions(const QPoint &pos) m_menu->addSeparator(); - - DSplitter *splitter = qobject_cast(parentWidget()); - int layer = getTermLayer(); - - if (1 == layer || (2 == layer && splitter && Qt::Horizontal == splitter->orientation())) - m_menu->addAction(tr("Horizontal split"), this, &TermWidget::onHorizontalSplit); - - if (1 == layer || (2 == layer && splitter && Qt::Vertical == splitter->orientation())) - m_menu->addAction(tr("Vertical split"), this, &TermWidget::onVerticalSplit); + m_menu->addAction(tr("Horizontal split"), this, &TermWidget::onHorizontalSplit); + m_menu->addAction(tr("Vertical split"), this, &TermWidget::onVerticalSplit); /******** Modify by n014361 wangpeili 2020-02-21: 增加关闭窗口和关闭其它窗口菜单 ****************/ m_menu->addAction(QObject::tr("Close workspace"), this, &TermWidget::onCloseCurrWorkSpace); @@ -555,14 +548,12 @@ void TermWidget::addMenuActions(const QPoint &pos) inline void TermWidget::onHorizontalSplit() { - getTermLayer(); // menu关闭与分屏同时进行时,会导致QT计算光标位置异常。 QTimer::singleShot(10, this, &TermWidget::splitHorizontal); } inline void TermWidget::onVerticalSplit() { - getTermLayer(); // menu关闭与分屏同时进行时,会导致QT计算光标位置异常。 QTimer::singleShot(10, this, &TermWidget::splitVertical); } @@ -824,18 +815,6 @@ void TermWidget::setDeleteMode(const EraseMode &deleteMode) QTermWidget::setDeleteMode(&ch, length); } -int TermWidget::getTermLayer() -{ - int layer = 1; - QWidget *currentW = this; - while (currentW->parentWidget() != parentPage()) { - layer++; - currentW = currentW->parentWidget(); - } - qInfo() << "getTermLayer = " << layer; - return layer; -} - void TermWidget::setTabFormat(const QString &tabFormat) { // 非全局设置优先级更高 diff --git a/src/views/termwidget.h b/src/views/termwidget.h index 10dd28800..f06f6a996 100644 --- a/src/views/termwidget.h +++ b/src/views/termwidget.h @@ -189,13 +189,6 @@ class TermWidget : public QTermWidget */ void setDeleteMode(const EraseMode &deleteMode); - /** - * @brief 获取当前terminal距离page的层次.用于限定分屏 - * @author ut000439 王培利 - * @return - */ - int getTermLayer(); - /** * @brief 设置标签标题格式(全局设置) * @author ut000610 戴正文 diff --git a/src/views/termwidgetpage.cpp b/src/views/termwidgetpage.cpp index 4ba89dbb6..a71b0dade 100644 --- a/src/views/termwidgetpage.cpp +++ b/src/views/termwidgetpage.cpp @@ -19,6 +19,23 @@ #include #include +static void setEqualSizes(QSplitter *splitter) +{ + QList sizes = splitter->sizes(); + int totalSize = 0; + for (int size : sizes) { + totalSize += size; + } + + int equalSize = totalSize / sizes.size(); + for (int i = 0; i < sizes.size(); ++i) { + sizes[i] = equalSize; + } + + splitter->setSizes(sizes); +} + + TermWidgetPage::TermWidgetPage(const TermProperties &properties, QWidget *parent) : QWidget(parent), m_findBar(new PageSearchBar(this)) { @@ -85,21 +102,26 @@ void TermWidgetPage::setParentMainWindow(MainWindow *mainWin) m_MainWindow = mainWin; } +// TODO(hualet): maybe implement a subclass of DSplitter and +// override the createHandle method, all setSplitStyle should +// be removed. void TermWidgetPage::setSplitStyle(DSplitter *splitter) { splitter->setHandleWidth(1); - QSplitterHandle *handle = splitter->handle(1); - - if (handle) { - //分割线颜色暂时设置为Highlight颜色,需要和UI确认下 - //此处代码暂时保留 //DPalette pa = DPaletteHelper::instance()->palette(handle); - //bug#57044 中的分割线颜色,保留的代码对默认主题,和十个内置主题的颜色是正确获取,但是在自定义的颜色获取存在异常,采取如下方式获取 - DPalette pa = DGuiApplicationHelper::instance()->applicationPalette(); - QColor splitBrush = pa.color(DPalette::Highlight); - pa.setBrush(DPalette::Background, splitBrush); - handle->setPalette(pa); - handle->setBackgroundRole(QPalette::Background); - handle->setAutoFillBackground(true); + + for (int i = 1; i < splitter->count(); ++i) { + QSplitterHandle *handle = splitter->handle(i); + if (handle) { + //分割线颜色暂时设置为Highlight颜色,需要和UI确认下 + //此处代码暂时保留 //DPalette pa = DPaletteHelper::instance()->palette(handle); + //bug#57044 中的分割线颜色,保留的代码对默认主题,和十个内置主题的颜色是正确获取,但是在自定义的颜色获取存在异常,采取如下方式获取 + DPalette pa = DGuiApplicationHelper::instance()->applicationPalette(); + QColor splitBrush = pa.color(DPalette::Highlight); + pa.setBrush(DPalette::Background, splitBrush); + handle->setPalette(pa); + handle->setBackgroundRole(QPalette::Background); + handle->setAutoFillBackground(true); + } } } @@ -119,22 +141,35 @@ void TermWidgetPage::split(Qt::Orientation orientation) { parentMainWindow()->showPlugin(MainWindow::PLUGIN_TYPE_NONE); TermWidget *term = m_currentTerm; - if (1 == getTerminalCount()) { - qInfo() << "first split"; - QSplitter *firstSplit = createSubSplit(term, orientation); - m_layout->addWidget(firstSplit); - //return ; + + QSplitter *splitter = qobject_cast(term->parent()); + // if there's already a splitter, and the orientation is correct, + // just add a new term to the splitter. + if (splitter && splitter->orientation() != orientation) { + TermProperties properties(term->workingDirectory()); + TermWidget *newTerm = createTerm(properties); + splitter->addWidget(newTerm); + setSplitStyle(splitter); + setCurrentTerminal(newTerm); } else { - qInfo() << "not first split"; - QSplitter *upSplit = qobject_cast(term->parent()); - int index = upSplit->indexOf(term); - QList parentSizes = upSplit->sizes(); - - // 用新的Split分割布局替换原来的位置 - QSplitter *subSplit = createSubSplit(term, orientation); - upSplit->insertWidget(index, subSplit); - upSplit->setSizes(parentSizes); - setSplitStyle(upSplit); + // if there's no splitter, or the orientation is not correct, + // create a new splitter, put the 2 terms into the splitter, + // and put the splitter the right postion. + int index = 0; + if (splitter) { + index = splitter->indexOf(term); + } else { + index = m_layout->indexOf(term); + } + + QSplitter *newSplitter = createSubSplit(term, orientation); + + if (splitter) { + splitter->insertWidget(index, newSplitter); + setEqualSizes(splitter); + } else { + m_layout->insertWidget(index, newSplitter); + } } /******** Add by ut001000 renfeixiang 2020-08-07:新增分屏时改变大小,bug#41436***************/ @@ -180,40 +215,32 @@ void TermWidgetPage::closeSplit(TermWidget *term, bool hasConfirmed) showExitConfirmDialog(Utils::CloseType_Terminal, 1, parentMainWindow()); return; } - QSplitter *upSplit = qobject_cast(term->parent()); - term->setParent(nullptr); - // 另一个兄弟也可能是终端,也可能是split, - QWidget *brother = upSplit->widget(0); - TermWidget *nextTerm = upSplit->findChild(); - // 如果上级是分屏 - if ("QSplitter" == QString(upSplit->parent()->metaObject()->className())) { - QSplitter *upupSplit = qobject_cast(upSplit->parent()); - //兄弟替换parent split - upupSplit->replaceWidget(upupSplit->indexOf(upSplit), brother); - } - // 上级不是分屏控件,就是布局在控制了 - else { - qInfo() << "TermWidgetPage only one term exist!"; - m_layout->addWidget(brother); - } - // 子控件的变化会引起焦点的变化,控制焦点要放在最后 - if (nextTerm != nullptr) { - qInfo() << "nextTerm change" << m_currentTerm->getSessionId(); - nextTerm->setFocus(); - } else { - qInfo() << "can not found nextTerm in TermWidget"; + QSplitter *upSplit = qobject_cast(term->parent()); + if (upSplit && upSplit->count() == 1) { + upSplit->setParent(nullptr); + upSplit->deleteLater(); + upSplit = nullptr; } + // TODO(hualet): set focus to another TermWidget. + // 释放控件,并隐藏term、upSplit,避免出现闪现窗口bug#80809 + term->setParent(nullptr); term->hide(); term->deleteLater(); // 断开相关的连接:(UT_MainWindow_Test, slotShortcutCloseWorkspace)出现的崩溃问题 Settings::instance()->disconnect(term); - upSplit->hide(); - upSplit->setParent(nullptr); - upSplit->deleteLater(); + + if (upSplit) { + upSplit->setFocus(); + } + + // upSplit->hide(); + // upSplit->setParent(nullptr); + // upSplit->deleteLater(); + qInfo() << "page terminal count =" << getTerminalCount(); /******** Add by ut001000 renfeixiang 2020-08-07:关闭分屏时改变大小,bug#41436***************/ parentMainWindow()->updateMinHeight(); From aca7f98ae17cbfdb2b08831e95932d99cf9ced28 Mon Sep 17 00:00:00 2001 From: Hualet Wang Date: Mon, 26 Aug 2024 14:20:13 +0800 Subject: [PATCH 2/9] fix: no term gets focus after closing one fix no term gets focus after closing one, which will cause crashes if you hit Alt+Q in sequence. --- src/views/termwidgetpage.cpp | 48 +++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/views/termwidgetpage.cpp b/src/views/termwidgetpage.cpp index a71b0dade..140281209 100644 --- a/src/views/termwidgetpage.cpp +++ b/src/views/termwidgetpage.cpp @@ -35,6 +35,26 @@ static void setEqualSizes(QSplitter *splitter) splitter->setSizes(sizes); } +// Find the previous term widget in the widget tree. +static TermWidget* WidgetTreeReverseFindTerm(QWidget *widget) +{ + QList termList = widget->findChildren(); + for (TermWidget *t : termList) { + if (t) { + qInfo() << "TermWidget found in current widget:" << t; + return t; + } + } + + QWidget *parent = widget->parentWidget(); + if (parent) { + qInfo() << "Searching in parent widget:" << parent; + return WidgetTreeReverseFindTerm(parent); + } + qInfo() << "No TermWidget found in the widget tree."; + return nullptr; +} + TermWidgetPage::TermWidgetPage(const TermProperties &properties, QWidget *parent) : QWidget(parent), m_findBar(new PageSearchBar(this)) @@ -216,16 +236,9 @@ void TermWidgetPage::closeSplit(TermWidget *term, bool hasConfirmed) return; } + QWidget *parentWidget = term->parentWidget(); - QSplitter *upSplit = qobject_cast(term->parent()); - if (upSplit && upSplit->count() == 1) { - upSplit->setParent(nullptr); - upSplit->deleteLater(); - upSplit = nullptr; - } - - // TODO(hualet): set focus to another TermWidget. - + // step1, delete the term // 释放控件,并隐藏term、upSplit,避免出现闪现窗口bug#80809 term->setParent(nullptr); term->hide(); @@ -233,13 +246,19 @@ void TermWidgetPage::closeSplit(TermWidget *term, bool hasConfirmed) // 断开相关的连接:(UT_MainWindow_Test, slotShortcutCloseWorkspace)出现的崩溃问题 Settings::instance()->disconnect(term); - if (upSplit) { - upSplit->setFocus(); + // step2, find the next term to get focus + TermWidget *nextTerm = WidgetTreeReverseFindTerm(parentWidget); + if (nextTerm) { + setCurrentTerminal(nextTerm); } - // upSplit->hide(); - // upSplit->setParent(nullptr); - // upSplit->deleteLater(); + // step3, futurer clean the parent splitter if it's empty + QSplitter *upSplit = qobject_cast(parentWidget); + if (upSplit && upSplit->count() == 0) { + upSplit->setParent(nullptr); + upSplit->deleteLater(); + upSplit = nullptr; + } qInfo() << "page terminal count =" << getTerminalCount(); /******** Add by ut001000 renfeixiang 2020-08-07:关闭分屏时改变大小,bug#41436***************/ @@ -736,6 +755,7 @@ void TermWidgetPage::setCurrentTerminal(TermWidget *term) TermWidget *oldTerm = m_currentTerm; m_currentTerm = term; if (oldTerm != m_currentTerm) { + m_currentTerm->setFocus(); // 当前界面切换 qInfo() << "m_currentTerm change" << m_currentTerm->getSessionId(); QString tabTitle = term->getTabTitle(); From ef451de530f5d08d5d1ff9137c22a0ad6a2611e5 Mon Sep 17 00:00:00 2001 From: Hualet Wang Date: Mon, 26 Aug 2024 14:56:56 +0800 Subject: [PATCH 3/9] fix: change minimum size set on TermWidget original minimum size relies on the limit of one can only split the terminal once, since we removed the limits, the minimum size should change accordingly --- src/views/termwidget.cpp | 7 ++----- src/views/termwidget.h | 3 +++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/views/termwidget.cpp b/src/views/termwidget.cpp index ee2c14ea2..882ebf8a2 100644 --- a/src/views/termwidget.cpp +++ b/src/views/termwidget.cpp @@ -121,11 +121,7 @@ TermWidget::TermWidget(const TermProperties &properties, QWidget *parent) : QTer // 按键滚动 setPressingScroll(Settings::instance()->PressingScroll()); - /******** Modify by ut000439 wangpeili 2020-07-27: fix bug 39371: 分屏线可以拉到边****/ - // 以最小mainwindow分4屏为标准的最小大小 - /******** Modify by ut001000 renfeixiang 2020-08-07:修改成根据全局变量m_MinWidth,m_MinHeight计算出term的最小高度和宽度***************/ - setMinimumSize(MainWindow::m_MinWidth / 2, (MainWindow::m_MinHeight - WIN_TITLE_BAR_HEIGHT) / 2); - /********************* Modify by n014361 wangpeili End ************************/ + setMinimumSize(MIN_WIDTH, MIN_HEIGHT); QString currentEnvLanguage = Utils::getCurrentEnvLanguage(); // 判断是维吾尔语或者藏语时 @@ -481,6 +477,7 @@ void TermWidget::addMenuActions(const QPoint &pos) m_menu->addSeparator(); + // TODO(hualet): check container size before split m_menu->addAction(tr("Horizontal split"), this, &TermWidget::onHorizontalSplit); m_menu->addAction(tr("Vertical split"), this, &TermWidget::onVerticalSplit); diff --git a/src/views/termwidget.h b/src/views/termwidget.h index f06f6a996..aee64f8fb 100644 --- a/src/views/termwidget.h +++ b/src/views/termwidget.h @@ -65,6 +65,9 @@ class TermWidget : public QTermWidget { Q_OBJECT public: + static const int MIN_WIDTH = 160; + static const int MIN_HEIGHT = 80; + TermWidget(const TermProperties &properties, QWidget *parent = nullptr); ~TermWidget(); /** From 7dc5ab42f319de05dc4fce95ee49a105b4ba27fe Mon Sep 17 00:00:00 2001 From: Hualet Wang Date: Wed, 28 Aug 2024 18:33:16 +0800 Subject: [PATCH 4/9] fix: new term not showing in the right position fix the bug that new term not showing right after the old one after the splitting --- src/views/termwidgetpage.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/views/termwidgetpage.cpp b/src/views/termwidgetpage.cpp index 140281209..05ad9f0ee 100644 --- a/src/views/termwidgetpage.cpp +++ b/src/views/termwidgetpage.cpp @@ -163,25 +163,20 @@ void TermWidgetPage::split(Qt::Orientation orientation) TermWidget *term = m_currentTerm; QSplitter *splitter = qobject_cast(term->parent()); + int index = splitter ? splitter->indexOf(term) : m_layout->indexOf(term); + // if there's already a splitter, and the orientation is correct, // just add a new term to the splitter. if (splitter && splitter->orientation() != orientation) { TermProperties properties(term->workingDirectory()); TermWidget *newTerm = createTerm(properties); - splitter->addWidget(newTerm); + splitter->insertWidget(index+1, newTerm); // insert after the current term setSplitStyle(splitter); setCurrentTerminal(newTerm); } else { // if there's no splitter, or the orientation is not correct, // create a new splitter, put the 2 terms into the splitter, - // and put the splitter the right postion. - int index = 0; - if (splitter) { - index = splitter->indexOf(term); - } else { - index = m_layout->indexOf(term); - } - + // and replace the old term with the splitter. QSplitter *newSplitter = createSubSplit(term, orientation); if (splitter) { From eee66bcacbf2fa4ddfed02ad35f95d2b3431815e Mon Sep 17 00:00:00 2001 From: Hualet Wang Date: Fri, 30 Aug 2024 00:05:50 +0800 Subject: [PATCH 5/9] fix: new term resized wrongly fix the bug that new term has wrong size after splitting --- src/views/termwidgetpage.cpp | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/views/termwidgetpage.cpp b/src/views/termwidgetpage.cpp index 05ad9f0ee..e12e3e8f1 100644 --- a/src/views/termwidgetpage.cpp +++ b/src/views/termwidgetpage.cpp @@ -19,22 +19,6 @@ #include #include -static void setEqualSizes(QSplitter *splitter) -{ - QList sizes = splitter->sizes(); - int totalSize = 0; - for (int size : sizes) { - totalSize += size; - } - - int equalSize = totalSize / sizes.size(); - for (int i = 0; i < sizes.size(); ++i) { - sizes[i] = equalSize; - } - - splitter->setSizes(sizes); -} - // Find the previous term widget in the widget tree. static TermWidget* WidgetTreeReverseFindTerm(QWidget *widget) { @@ -170,7 +154,15 @@ void TermWidgetPage::split(Qt::Orientation orientation) if (splitter && splitter->orientation() != orientation) { TermProperties properties(term->workingDirectory()); TermWidget *newTerm = createTerm(properties); + + // copy the size of the current term to the new term, so the new term will + // keep the same size portion as the current term after the splitter relayout. + // this behavior is copied form iTerm2. + QList sizes = splitter->sizes(); + sizes.insert(index+1, sizes.at(index)); splitter->insertWidget(index+1, newTerm); // insert after the current term + splitter->setSizes(sizes); + setSplitStyle(splitter); setCurrentTerminal(newTerm); } else { @@ -180,8 +172,12 @@ void TermWidgetPage::split(Qt::Orientation orientation) QSplitter *newSplitter = createSubSplit(term, orientation); if (splitter) { + // see above splitter->insertWidget part to know why. + QList sizes = splitter->sizes(); + sizes.insert(index, sizes.at(index)); splitter->insertWidget(index, newSplitter); - setEqualSizes(splitter); + splitter->setSizes(sizes); + setSplitStyle(splitter); } else { m_layout->insertWidget(index, newSplitter); } @@ -204,6 +200,7 @@ DSplitter *TermWidgetPage::createSubSplit(TermWidget *term, Qt::Orientation orie TermProperties properties(term->workingDirectory()); term->setParent(nullptr); TermWidget *newTerm = createTerm(properties); + newTerm->resize(term->size()); // 意义与名称是相反的 DSplitter *subSplit = new DSplitter(orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, @@ -212,7 +209,6 @@ DSplitter *TermWidgetPage::createSubSplit(TermWidget *term, Qt::Orientation orie subSplit->setFocusPolicy(Qt::NoFocus); subSplit->insertWidget(0, term); subSplit->insertWidget(1, newTerm); - subSplit->setSizes({ 1, 1 }); setSplitStyle(subSplit); setCurrentTerminal(newTerm); /******** Modify by ut000439 wangpeili 2020-07-27: fix bug 39371: 分屏线可以拉到边****/ From 69cc00a6657353955ec8d80e55066bf36cd29304 Mon Sep 17 00:00:00 2001 From: Hualet Wang Date: Fri, 30 Aug 2024 23:16:35 +0800 Subject: [PATCH 6/9] fix: disable splitting menu if there's no room disable splitting menu when there's no enough room for splitting --- src/views/termwidget.cpp | 39 ++++++++++++++++++++++++++++++++++++--- src/views/termwidget.h | 5 +++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/views/termwidget.cpp b/src/views/termwidget.cpp index 882ebf8a2..9cf18ef96 100644 --- a/src/views/termwidget.cpp +++ b/src/views/termwidget.cpp @@ -38,6 +38,37 @@ DWIDGET_USE_NAMESPACE using namespace Konsole; + +static bool CanSplit(TermWidget *term, Qt::Orientation ori) { + QSplitter *splitter = qobject_cast(term->parentWidget()); + int minimumSize = ori == Qt::Horizontal ? TermWidget::MIN_WIDTH : TermWidget::MIN_HEIGHT; + if (splitter) { + if (splitter->orientation() == ori) { + QList sizes = splitter->sizes(); + // new term has same size portion as the current one. + sizes.append(sizes.at(splitter->indexOf(term))); + + double sum = 0; + for (int i = 0; i < sizes.count(); i++) { + sum += sizes.at(i); + } + + for(int i = 0; i < sizes.count(); i++) { + int totalSize = ori == Qt::Horizontal ? splitter->width() : splitter->height(); + int actualSize = (totalSize) * (sizes.at(i) / sum); + if (actualSize < minimumSize) + return false; + } + } else { + int splitterSize = ori == Qt::Horizontal ? splitter->width() : splitter->height(); + if (splitterSize / 2.0 < minimumSize) + return false; + } + } + + return true; +} + TermWidget::TermWidget(const TermProperties &properties, QWidget *parent) : QTermWidget(0, parent), m_properties(properties) { Utils::set_Object_Name(this); @@ -477,9 +508,11 @@ void TermWidget::addMenuActions(const QPoint &pos) m_menu->addSeparator(); - // TODO(hualet): check container size before split - m_menu->addAction(tr("Horizontal split"), this, &TermWidget::onHorizontalSplit); - m_menu->addAction(tr("Vertical split"), this, &TermWidget::onVerticalSplit); + QAction *action = 0; + action = m_menu->addAction(tr("Horizontal split"), this, &TermWidget::onHorizontalSplit); + action->setEnabled(CanSplit(this, Qt::Vertical)); + action = m_menu->addAction(tr("Vertical split"), this, &TermWidget::onVerticalSplit); + action->setEnabled(CanSplit(this, Qt::Horizontal)); /******** Modify by n014361 wangpeili 2020-02-21: 增加关闭窗口和关闭其它窗口菜单 ****************/ m_menu->addAction(QObject::tr("Close workspace"), this, &TermWidget::onCloseCurrWorkSpace); diff --git a/src/views/termwidget.h b/src/views/termwidget.h index aee64f8fb..b32db22f0 100644 --- a/src/views/termwidget.h +++ b/src/views/termwidget.h @@ -65,8 +65,9 @@ class TermWidget : public QTermWidget { Q_OBJECT public: - static const int MIN_WIDTH = 160; - static const int MIN_HEIGHT = 80; + // 9:6 + static const int MIN_WIDTH = 180; + static const int MIN_HEIGHT = 120; TermWidget(const TermProperties &properties, QWidget *parent = nullptr); ~TermWidget(); From 85a2d92f25d02cca24a354d060bed5edb5ed6bc4 Mon Sep 17 00:00:00 2001 From: Hualet Wang Date: Fri, 30 Aug 2024 23:38:44 +0800 Subject: [PATCH 7/9] fix: shortcut can still do splitting on room left fix shortcut still work even when there's no room for splitting --- src/main/mainwindow.cpp | 4 ++-- src/views/termwidget.cpp | 31 ------------------------------- src/views/termwidget.h | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/main/mainwindow.cpp b/src/main/mainwindow.cpp index d516030b5..a5dd7308c 100644 --- a/src/main/mainwindow.cpp +++ b/src/main/mainwindow.cpp @@ -1131,7 +1131,7 @@ inline void MainWindow::slotShortcutHorizonzalSplit() // 判读数量是否允许分屏 if (Service::instance()->isCountEnable()) { TermWidgetPage *page = currentPage(); - if (page) { + if (page && CanSplit(page->currentTerminal(), Qt::Vertical)) { page->split(Qt::Horizontal); return ; } @@ -1144,7 +1144,7 @@ inline void MainWindow::slotShortcutVerticalSplit() // 判读数量是否允许分屏 if (Service::instance()->isCountEnable()) { TermWidgetPage *page = currentPage(); - if (page) { + if (page && CanSplit(page->currentTerminal(), Qt::Horizontal)) { page->split(Qt::Vertical); return ; } diff --git a/src/views/termwidget.cpp b/src/views/termwidget.cpp index 9cf18ef96..bdd9d259c 100644 --- a/src/views/termwidget.cpp +++ b/src/views/termwidget.cpp @@ -38,37 +38,6 @@ DWIDGET_USE_NAMESPACE using namespace Konsole; - -static bool CanSplit(TermWidget *term, Qt::Orientation ori) { - QSplitter *splitter = qobject_cast(term->parentWidget()); - int minimumSize = ori == Qt::Horizontal ? TermWidget::MIN_WIDTH : TermWidget::MIN_HEIGHT; - if (splitter) { - if (splitter->orientation() == ori) { - QList sizes = splitter->sizes(); - // new term has same size portion as the current one. - sizes.append(sizes.at(splitter->indexOf(term))); - - double sum = 0; - for (int i = 0; i < sizes.count(); i++) { - sum += sizes.at(i); - } - - for(int i = 0; i < sizes.count(); i++) { - int totalSize = ori == Qt::Horizontal ? splitter->width() : splitter->height(); - int actualSize = (totalSize) * (sizes.at(i) / sum); - if (actualSize < minimumSize) - return false; - } - } else { - int splitterSize = ori == Qt::Horizontal ? splitter->width() : splitter->height(); - if (splitterSize / 2.0 < minimumSize) - return false; - } - } - - return true; -} - TermWidget::TermWidget(const TermProperties &properties, QWidget *parent) : QTermWidget(0, parent), m_properties(properties) { Utils::set_Object_Name(this); diff --git a/src/views/termwidget.h b/src/views/termwidget.h index b32db22f0..86ca80450 100644 --- a/src/views/termwidget.h +++ b/src/views/termwidget.h @@ -464,4 +464,35 @@ private slots: bool m_remotePasswordIsReady = false; }; +static bool CanSplit(TermWidget *term, Qt::Orientation ori) { + qDebug() << "CanSplit:" << term << ori; + QSplitter *splitter = qobject_cast(term->parentWidget()); + int minimumSize = ori == Qt::Horizontal ? TermWidget::MIN_WIDTH : TermWidget::MIN_HEIGHT; + if (splitter) { + if (splitter->orientation() == ori) { + QList sizes = splitter->sizes(); + // new term has same size portion as the current one. + sizes.append(sizes.at(splitter->indexOf(term))); + + double sum = 0; + for (int i = 0; i < sizes.count(); i++) { + sum += sizes.at(i); + } + + for(int i = 0; i < sizes.count(); i++) { + int totalSize = ori == Qt::Horizontal ? splitter->width() : splitter->height(); + int actualSize = (totalSize) * (sizes.at(i) / sum); + if (actualSize < minimumSize) + return false; + } + } else { + int splitterSize = ori == Qt::Horizontal ? splitter->width() : splitter->height(); + if (splitterSize / 2.0 < minimumSize) + return false; + } + } + + return true; +} + #endif // TERMWIDGET_H From a72aac8143f5c75e6bbd41ff78226c39c53f9082 Mon Sep 17 00:00:00 2001 From: Hualet Wang Date: Sat, 31 Aug 2024 00:00:13 +0800 Subject: [PATCH 8/9] fix: crash of unfound size createSubSplit has side effects, it removes the term form its parent, so find size of it in QSplitter::sizes crashes. --- src/views/termwidgetpage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/termwidgetpage.cpp b/src/views/termwidgetpage.cpp index e12e3e8f1..d26adc3e1 100644 --- a/src/views/termwidgetpage.cpp +++ b/src/views/termwidgetpage.cpp @@ -169,16 +169,16 @@ void TermWidgetPage::split(Qt::Orientation orientation) // if there's no splitter, or the orientation is not correct, // create a new splitter, put the 2 terms into the splitter, // and replace the old term with the splitter. - QSplitter *newSplitter = createSubSplit(term, orientation); - if (splitter) { // see above splitter->insertWidget part to know why. QList sizes = splitter->sizes(); sizes.insert(index, sizes.at(index)); + QSplitter *newSplitter = createSubSplit(term, orientation); splitter->insertWidget(index, newSplitter); splitter->setSizes(sizes); setSplitStyle(splitter); } else { + QSplitter *newSplitter = createSubSplit(term, orientation); m_layout->insertWidget(index, newSplitter); } } From 084e08663582960e3cdd1785074b2f37b93592ef Mon Sep 17 00:00:00 2001 From: Hualet Wang Date: Mon, 2 Sep 2024 23:13:16 +0800 Subject: [PATCH 9/9] chore: some code refactory - change CanSplit to a public funtion of TermWidget - change MIN_WIDTH and MIN_HEIGHT of TermWidget to private --- src/main/mainwindow.cpp | 4 ++-- src/views/termwidget.cpp | 36 ++++++++++++++++++++++++++++++++++-- src/views/termwidget.h | 40 ++++++---------------------------------- 3 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/main/mainwindow.cpp b/src/main/mainwindow.cpp index a5dd7308c..0a2bdd79f 100644 --- a/src/main/mainwindow.cpp +++ b/src/main/mainwindow.cpp @@ -1131,7 +1131,7 @@ inline void MainWindow::slotShortcutHorizonzalSplit() // 判读数量是否允许分屏 if (Service::instance()->isCountEnable()) { TermWidgetPage *page = currentPage(); - if (page && CanSplit(page->currentTerminal(), Qt::Vertical)) { + if (page && page->currentTerminal()->canSplit(Qt::Vertical)) { page->split(Qt::Horizontal); return ; } @@ -1144,7 +1144,7 @@ inline void MainWindow::slotShortcutVerticalSplit() // 判读数量是否允许分屏 if (Service::instance()->isCountEnable()) { TermWidgetPage *page = currentPage(); - if (page && CanSplit(page->currentTerminal(), Qt::Horizontal)) { + if (page && page->currentTerminal()->canSplit(Qt::Horizontal)) { page->split(Qt::Vertical); return ; } diff --git a/src/views/termwidget.cpp b/src/views/termwidget.cpp index bdd9d259c..6828439bf 100644 --- a/src/views/termwidget.cpp +++ b/src/views/termwidget.cpp @@ -479,9 +479,9 @@ void TermWidget::addMenuActions(const QPoint &pos) QAction *action = 0; action = m_menu->addAction(tr("Horizontal split"), this, &TermWidget::onHorizontalSplit); - action->setEnabled(CanSplit(this, Qt::Vertical)); + action->setEnabled(canSplit(Qt::Vertical)); action = m_menu->addAction(tr("Vertical split"), this, &TermWidget::onVerticalSplit); - action->setEnabled(CanSplit(this, Qt::Horizontal)); + action->setEnabled(canSplit(Qt::Horizontal)); /******** Modify by n014361 wangpeili 2020-02-21: 增加关闭窗口和关闭其它窗口菜单 ****************/ m_menu->addAction(QObject::tr("Close workspace"), this, &TermWidget::onCloseCurrWorkSpace); @@ -1011,6 +1011,38 @@ bool TermWidget::isInRemoteServer() return false; } +bool TermWidget::canSplit(Qt::Orientation ori) { + qDebug() << "CanSplit:" << ori; + QSplitter *splitter = qobject_cast(this->parentWidget()); + int minimumSize = ori == Qt::Horizontal ? TermWidget::MIN_WIDTH : TermWidget::MIN_HEIGHT; + if (splitter) { + if (splitter->orientation() == ori) { + QList sizes = splitter->sizes(); + // new term has same size portion as the current one. + sizes.append(sizes.at(splitter->indexOf(this))); + + double sum = 0; + for (int i = 0; i < sizes.count(); i++) { + sum += sizes.at(i); + } + + for(int i = 0; i < sizes.count(); i++) { + int totalSize = ori == Qt::Horizontal ? splitter->width() : splitter->height(); + int actualSize = (totalSize) * (sizes.at(i) / sum); + if (actualSize < minimumSize) + return false; + } + } else { + int splitterSize = ori == Qt::Horizontal ? splitter->width() : splitter->height(); + if (splitterSize / 2.0 < minimumSize) + return false; + } + } + + return true; +} + + void TermWidget::setTermOpacity(qreal opacity) { //这里再次判断一遍,因为刚启动时,还是需要判断一次当前是否开启了窗口特效 diff --git a/src/views/termwidget.h b/src/views/termwidget.h index 86ca80450..60831bca3 100644 --- a/src/views/termwidget.h +++ b/src/views/termwidget.h @@ -65,9 +65,7 @@ class TermWidget : public QTermWidget { Q_OBJECT public: - // 9:6 - static const int MIN_WIDTH = 180; - static const int MIN_HEIGHT = 120; + bool canSplit(Qt::Orientation ori); TermWidget(const TermProperties &properties, QWidget *parent = nullptr); ~TermWidget(); @@ -83,6 +81,7 @@ class TermWidget : public QTermWidget * @return */ bool isInRemoteServer(); + public: /** * @brief 设置不透明度 @@ -462,37 +461,10 @@ private slots: QString m_remotePassword; //是否准备远程 bool m_remotePasswordIsReady = false; -}; -static bool CanSplit(TermWidget *term, Qt::Orientation ori) { - qDebug() << "CanSplit:" << term << ori; - QSplitter *splitter = qobject_cast(term->parentWidget()); - int minimumSize = ori == Qt::Horizontal ? TermWidget::MIN_WIDTH : TermWidget::MIN_HEIGHT; - if (splitter) { - if (splitter->orientation() == ori) { - QList sizes = splitter->sizes(); - // new term has same size portion as the current one. - sizes.append(sizes.at(splitter->indexOf(term))); - - double sum = 0; - for (int i = 0; i < sizes.count(); i++) { - sum += sizes.at(i); - } - - for(int i = 0; i < sizes.count(); i++) { - int totalSize = ori == Qt::Horizontal ? splitter->width() : splitter->height(); - int actualSize = (totalSize) * (sizes.at(i) / sum); - if (actualSize < minimumSize) - return false; - } - } else { - int splitterSize = ori == Qt::Horizontal ? splitter->width() : splitter->height(); - if (splitterSize / 2.0 < minimumSize) - return false; - } - } - - return true; -} + // 9:6 + static const int MIN_WIDTH = 180; + static const int MIN_HEIGHT = 120; +}; #endif // TERMWIDGET_H