diff --git a/src/README.md b/src/README.md index 95036b0..5193974 100644 --- a/src/README.md +++ b/src/README.md @@ -4,14 +4,6 @@ Below is a list of (some) WindTerm components in alphabetical order, along with a brief description of each. -## CircularBuffer.h - -A quick circular buffer template class. - -## Cryptographic.h/cpp - -A very safe encryption class using the PBKDF2-algorithm as defined in RFC 8018. WindTerm uses this class together with the user's master password to protect user data, including passwords, private keys and so on. - ## Onigmo An improved version based on Onigmo 5.13.5. In particular, **the addition of iterator makes it possible to match gap buffer or nonadjacent memory blocks.** Please refer to the sample files for how to use. @@ -20,18 +12,30 @@ An improved version based on Onigmo 5.13.5. In particular, **the addition of ite An improved version based on [ptyqt](https://github.com/kafeg/ptyqt). **Almost all the code was rewritten to make the pty more robust and stable.** -## ScopeGuard.h - -A class of which the sole purpose is to run the function f in its destructor. This is useful for guaranteeing your cleanup code is executed. - -## Spin.h - -A high-performance spin mutex and locker. - ## Protocol/TelentProtocol.h/cpp An implementation of Telnet protocol. +## Utility/CircularBuffer.h + +A quick circular buffer template class. + +## Utility/Cryptographic.h/cpp + +A very safe encryption class using the PBKDF2-algorithm as defined in RFC 8018. WindTerm uses this class together with the user's master password to protect user data, including passwords, private keys and so on. + +## Utility/ScopeGuard.h + +A class of which the sole purpose is to run the function f in its destructor. This is useful for guaranteeing your cleanup code is executed. + +## Utility/Spin.h + +A high-performance spin mutex and locker. + ## Utility/ThreadLocal.h/cpp A high-performance thread local storage. + +## Widgets/Scrollbar.h/cpp + +A scrollbar supports 64-bit ranges. diff --git a/src/Widgets/ScrollBar.cpp b/src/Widgets/ScrollBar.cpp new file mode 100644 index 0000000..c503089 --- /dev/null +++ b/src/Widgets/ScrollBar.cpp @@ -0,0 +1,153 @@ + /* + * 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 "ScrollBar.h" + +#include +#include + +ScrollBar::ScrollBar(Qt::Orientation orientation, QWidget *parent /*= nullptr*/) + : QScrollBar(orientation, parent) +{ + m_maximum = QScrollBar::maximum(); + m_minimum = QScrollBar::minimum(); + m_value = QScrollBar::value(); + + setContextMenuPolicy(Qt::PreventContextMenu); + createConnections(); +} + +void ScrollBar::createConnections() { + connect(this, &QScrollBar::valueChanged, this, [this](qint64 value) { + if (m_maximum > INT_MAX) { + value *= (double)m_maximum / INT_MAX; + } + + if (m_value != value) { + qint64 oldValue = m_value; + m_value = value; + + emit valueChanged(m_value, oldValue); + } + }); + + connect(this, &QScrollBar::actionTriggered, this, [this](int action) { + qint64 oldValue = m_value; + + switch (action) { + case QAbstractSlider::SliderMove: + if (m_maximum > INT_MAX) { + m_value = (QScrollBar::sliderPosition() * ((double)m_maximum / INT_MAX)); + } else { + m_value = QScrollBar::sliderPosition(); + } + break; + case QAbstractSlider::SliderPageStepAdd: + m_value = std::min(m_maximum, m_value + pageStep()); + break; + case QAbstractSlider::SliderPageStepSub: + m_value = std::max(m_minimum, m_value - pageStep()); + break; + case QAbstractSlider::SliderSingleStepAdd: + m_value = std::min(m_maximum, m_value + singleStep()); + break; + case QAbstractSlider::SliderSingleStepSub: + m_value = std::max(m_minimum, m_value - singleStep()); + break; + case QAbstractSlider::SliderToMaximum: + m_value = m_maximum; + break; + case QAbstractSlider::SliderToMinimum: + m_value = m_minimum; + break; + } + + if (m_maximum > INT_MAX) { + Q_ASSERT(QScrollBar::maximum() == INT_MAX); + QScrollBar::setSliderPosition(m_value * ((double)INT_MAX / m_maximum)); + } + + if (m_value != oldValue) { + emit valueChanged(m_value, oldValue); + } + }); +} + +bool ScrollBar::setMaximum(qint64 maximum) { + return setRange(std::min(m_minimum, maximum), maximum); +} + +bool ScrollBar::setMinimum(qint64 minimum) { + return setRange(minimum, std::max(minimum, m_maximum)); +} + +bool ScrollBar::setPage(int page) { + if (page > 0 && page != QScrollBar::pageStep()) { + QScrollBar::setPageStep(page); + emit pageChanged(page); + + return true; + } + return false; +} + +bool ScrollBar::setRange(qint64 minimum, qint64 maximum) { + if (minimum >= 0 && minimum <= maximum && (m_minimum != minimum || m_maximum != maximum)) { + m_maximum = maximum; + m_minimum = minimum; + + QScrollBar::setRange( + (m_minimum > INT_MAX) ? INT_MAX : m_minimum, + (m_maximum > INT_MAX) ? INT_MAX : m_maximum + ); + emit rangeChanged(minimum, maximum); + + return true; + } + return false; +} + +bool ScrollBar::setSingleStep(int singleStep) { + if (singleStep > 0 && singleStep != QScrollBar::singleStep()) { + QScrollBar::setSingleStep(singleStep); + emit singleStepChanged(singleStep); + + return true; + } + return false; +} + +bool ScrollBar::setValue(qint64 value) { + value = qBound(m_minimum, value, m_maximum); + + if (m_value != value) { + qint64 oldValue = m_value; + m_value = value; + + if (m_maximum > INT_MAX) { + value *= (double)INT_MAX / m_maximum; + } + + { + QSignalBlocker blocker(this); + QScrollBar::setValue(value); + } + emit valueChanged(m_value, oldValue); + + return true; + } + return false; +} \ No newline at end of file diff --git a/src/Widgets/ScrollBar.h b/src/Widgets/ScrollBar.h new file mode 100644 index 0000000..00d5ba5 --- /dev/null +++ b/src/Widgets/ScrollBar.h @@ -0,0 +1,59 @@ + /* + * 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 SCROLLBAR_H +#define SCROLLBAR_H + +#pragma once + +#include + +class ScrollBar : public QScrollBar +{ + Q_OBJECT + +public: + explicit ScrollBar(Qt::Orientation orientation, QWidget *parent = nullptr); + virtual ~ScrollBar() = default; + + qint64 maximum() const { return m_maximum; } + qint64 minimum() const { return m_minimum; } + bool setMaximum(qint64 maximum); + bool setMinimum(qint64 minimum); + bool setPage(int page); + bool setRange(qint64 minimum, qint64 maximum); + bool setSingleStep(int singleStep); + bool setValue(qint64 value); + qint64 value() const { return m_value; } + +private: + void createConnections(); + +Q_SIGNALS: + void pageChanged(int page) const; + void rangeChanged(qint64 minimum, qint64 maximum) const; + void singleStepChanged(int singleStep) const; + void valueChanged(qint64 value, qint64 oldValue) const; + +private: + Q_DISABLE_COPY(ScrollBar) + + qint64 m_maximum; + qint64 m_minimum; + qint64 m_value; +}; + +#endif // SCROLLBAR_H \ No newline at end of file