From 996920dc91df824412b5b5812f2b2a68044de31b Mon Sep 17 00:00:00 2001 From: KingToolbox Date: Sun, 18 Oct 2020 15:24:48 +0800 Subject: [PATCH] Add a convenient splitter for showing and hiding widgets. --- src/README.md | 4 ++ src/Widgets/Splitter.cpp | 144 +++++++++++++++++++++++++++++++++++++++ src/Widgets/Splitter.h | 56 +++++++++++++++ 3 files changed, 204 insertions(+) create mode 100644 src/Widgets/Splitter.cpp create mode 100644 src/Widgets/Splitter.h diff --git a/src/README.md b/src/README.md index 48e1b64..fd0f074 100644 --- a/src/README.md +++ b/src/README.md @@ -45,3 +45,7 @@ A popup widget. ## Widgets/Scrollbar.h/cpp A scrollbar supports 64-bit ranges. + +## Widgets/Splitter.h/cpp + +A convenient splitter for showing and hiding widgets. \ No newline at end of file diff --git a/src/Widgets/Splitter.cpp b/src/Widgets/Splitter.cpp new file mode 100644 index 0000000..accc5c7 --- /dev/null +++ b/src/Widgets/Splitter.cpp @@ -0,0 +1,144 @@ + /* + * Copyright 2020, WindTerm. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Splitter.h" + +#include +#include + +const char* const SPLITTER_RATIO = "ratio"; + +Splitter::Splitter(QWidget *parent) + : QSplitter(parent) + , m_mainIndex(0) +{} + +Splitter::~Splitter() +{} + +void Splitter::showIndex(int index) { + if (isIndexVisible(index)) + return; + + emit showIndexRequested(index); + + if (QSplitterHandle *handle = this->handle(index)) { + QList sizes = this->sizes(); + + int total = 0; + for (int size : sizes) { + total += size; + } + + float ratio = handle->property(SPLITTER_RATIO).toFloat(); + if (ratio == 0.0) { + ratio = 0.18f; + } + + int offset = 0; + int size = total * ratio; + + if (index > 0) { + for (int i = 0; i < index; i++) { + offset += sizes[i]; + } + offset -= size; + } else { + offset = size; + } + + if (index <= m_mainIndex) { + index += 1; + } + moveSplitter(offset, index); + } +} + +void Splitter::hideIndex(int index) { + if (isIndexVisible(index) == false) + return; + + emit hideIndexRequested(index); + + if (QSplitterHandle *handle = this->handle(index)) { + QList sizes = this->sizes(); + int size = sizes[index]; + + float total = 0; + for (int size : sizes) { + total += size; + } + handle->setProperty(SPLITTER_RATIO, size / total); + + int offset = 0; + for (int i = 0; i <= index; i++) { + if (i == index && index <= m_mainIndex) + break; + offset += sizes[i]; + } + + if (index <= m_mainIndex) { + index += 1; + } + moveSplitter(offset, index); + } +} + +bool Splitter::isIndexVisible(int index) { + if (index >= 0 && index < count()) { + return sizes()[index] > 0; + } + + Q_ASSERT(false); + return false; +} + +void Splitter::setIndexVisible(int index, bool visible) { + if (visible) { + showIndex(index); + } else { + hideIndex(index); + } +} + +void Splitter::setMainIndex(int mainIndex) { + m_mainIndex = mainIndex; +} + +bool Splitter::eventFilter(QObject *obj, QEvent *event) { + if (event->type() == QEvent::MouseButtonDblClick) { + if (QSplitterHandle *handle = dynamic_cast(obj)) { + for (int i = 0; i < count(); i++) { + if (handle == this->handle(i)) { + if (i <= m_mainIndex && i > 0) { + i--; + } + bool visible = isIndexVisible(i); + setIndexVisible(i, !visible); + break; + } + } + } + } + return QSplitter::eventFilter(obj, event); +} + +QSplitterHandle *Splitter::createHandle() { + QSplitterHandle *handle = QSplitter::createHandle(); + handle->installEventFilter(this); + + return handle; +} \ No newline at end of file diff --git a/src/Widgets/Splitter.h b/src/Widgets/Splitter.h new file mode 100644 index 0000000..0a5fbc4 --- /dev/null +++ b/src/Widgets/Splitter.h @@ -0,0 +1,56 @@ + /* + * Copyright 2020, WindTerm. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SPLITTER_H +#define SPLITTER_H + +#pragma once + +#include + +extern const char* const SPLITTER_RATIO; + +class Splitter : public QSplitter +{ + Q_OBJECT + +public: + explicit Splitter(QWidget *parent = 0); + ~Splitter(); + + void showIndex(int index); + void hideIndex(int index); + bool isIndexVisible(int index); + void setIndexVisible(int index, bool visible); + + void setMainIndex(int mainIndex); + +protected: + bool eventFilter(QObject *obj, QEvent *event); + + QSplitterHandle *createHandle(); + +Q_SIGNALS: + void showIndexRequested(int index); + void hideIndexRequested(int index); + +private: + Q_DISABLE_COPY(Splitter) + + int m_mainIndex; +}; + +#endif // SPLITTER_H \ No newline at end of file