Moved Ui::TimePart to separated file.

This commit is contained in:
23rd 2022-03-28 12:26:41 +03:00
parent 2256b4b8ea
commit c026c1125e
4 changed files with 170 additions and 142 deletions

View file

@ -176,6 +176,8 @@ PRIVATE
ui/widgets/input_fields.h
ui/widgets/labels.cpp
ui/widgets/labels.h
ui/widgets/fields/time_part_input.cpp
ui/widgets/fields/time_part_input.h
ui/widgets/menu/menu.cpp
ui/widgets/menu/menu.h
ui/widgets/menu/menu_action.cpp

View file

@ -0,0 +1,123 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include "ui/widgets/fields/time_part_input.h"
#include "ui/ui_utility.h" // WheelDirection
#include <QtCore/QRegularExpression>
namespace Ui {
std::optional<int> TimePart::number() {
const auto text = getLastText();
auto view = QStringView(text);
while (view.size() > 1 && view.at(0) == '0') {
view = base::StringViewMid(view, 1);
}
return QRegularExpression("^\\d+$").match(view).hasMatch()
? std::make_optional(view.toInt())
: std::nullopt;
}
void TimePart::setMaxValue(int value) {
_maxValue = value;
_maxDigits = 0;
while (value > 0) {
++_maxDigits;
value /= 10;
}
}
void TimePart::setWheelStep(int value) {
_wheelStep = value;
}
rpl::producer<> TimePart::erasePrevious() const {
return _erasePrevious.events();
}
rpl::producer<QChar> TimePart::putNext() const {
return _putNext.events();
}
void TimePart::keyPressEvent(QKeyEvent *e) {
const auto isBackspace = (e->key() == Qt::Key_Backspace);
const auto isBeginning = (cursorPosition() == 0);
if (isBackspace && isBeginning && !hasSelectedText()) {
_erasePrevious.fire({});
} else {
MaskedInputField::keyPressEvent(e);
}
}
void TimePart::wheelEvent(QWheelEvent *e) {
const auto direction = WheelDirection(e);
const auto now = number();
if (!now.has_value()) {
return;
}
auto time = *now + (direction * _wheelStep);
const auto max = _maxValue + 1;
if (time < 0) {
time += max;
} else if (time >= max) {
time -= max;
}
setText(QString::number(time));
}
void TimePart::correctValue(
const QString &was,
int wasCursor,
QString &now,
int &nowCursor) {
auto newText = QString();
auto newCursor = -1;
const auto oldCursor = nowCursor;
const auto oldLength = now.size();
auto accumulated = 0;
auto limit = 0;
for (; limit != oldLength; ++limit) {
if (now[limit].isDigit()) {
accumulated *= 10;
accumulated += (now[limit].unicode() - '0');
if (accumulated > _maxValue || limit == _maxDigits) {
break;
}
}
}
for (auto i = 0; i != limit;) {
if (now[i].isDigit()) {
newText += now[i];
}
if (++i == oldCursor) {
newCursor = newText.size();
}
}
if (newCursor < 0) {
newCursor = newText.size();
}
if (newText != now) {
now = newText;
setText(now);
startPlaceholderAnimation();
}
if (newCursor != nowCursor) {
nowCursor = newCursor;
setCursorPosition(nowCursor);
}
if (accumulated > _maxValue
|| (limit == _maxDigits && oldLength > _maxDigits)) {
if (oldCursor > limit) {
_putNext.fire('0' + (accumulated % 10));
} else {
_putNext.fire(0);
}
}
}
} // namespace Ui

View file

@ -0,0 +1,44 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#pragma once
#include "ui/widgets/input_fields.h"
namespace Ui {
class TimePart : public MaskedInputField {
public:
using MaskedInputField::MaskedInputField;
void setMaxValue(int value);
void setWheelStep(int value);
[[nodiscard]] rpl::producer<> erasePrevious() const;
[[nodiscard]] rpl::producer<QChar> putNext() const;
[[nodiscard]] std::optional<int> number();
protected:
void keyPressEvent(QKeyEvent *e) override;
void wheelEvent(QWheelEvent *e) override;
void correctValue(
const QString &was,
int wasCursor,
QString &now,
int &nowCursor) override;
private:
int _maxValue = 0;
int _maxDigits = 0;
int _wheelStep = 0;
rpl::event_stream<> _erasePrevious;
rpl::event_stream<QChar> _putNext;
};
} // namespace Ui

View file

@ -6,9 +6,7 @@
//
#include "ui/widgets/time_input.h"
#include "ui/widgets/input_fields.h"
#include "ui/ui_utility.h"
#include "base/qt/qt_common_adapters.h"
#include "ui/widgets/fields/time_part_input.h"
#include <QtCore/QRegularExpression>
#include <QTime>
@ -48,145 +46,6 @@ QString GetMinute(const QString &value) {
} // namespace
class TimePart final : public MaskedInputField {
public:
using MaskedInputField::MaskedInputField;
void setMaxValue(int value);
void setWheelStep(int value);
[[nodiscard]] rpl::producer<> erasePrevious() const;
[[nodiscard]] rpl::producer<QChar> putNext() const;
[[nodiscard]] std::optional<int> number();
protected:
void keyPressEvent(QKeyEvent *e) override;
void wheelEvent(QWheelEvent *e) override;
void correctValue(
const QString &was,
int wasCursor,
QString &now,
int &nowCursor) override;
private:
int _maxValue = 0;
int _maxDigits = 0;
int _wheelStep = 0;
rpl::event_stream<> _erasePrevious;
rpl::event_stream<QChar> _putNext;
};
std::optional<int> TimePart::number() {
const auto text = getLastText();
auto view = QStringView(text);
while (view.size() > 1 && view.at(0) == '0') {
view = base::StringViewMid(view, 1);
}
return QRegularExpression("^\\d+$").match(view).hasMatch()
? std::make_optional(view.toInt())
: std::nullopt;
}
void TimePart::setMaxValue(int value) {
_maxValue = value;
_maxDigits = 0;
while (value > 0) {
++_maxDigits;
value /= 10;
}
}
void TimePart::setWheelStep(int value) {
_wheelStep = value;
}
rpl::producer<> TimePart::erasePrevious() const {
return _erasePrevious.events();
}
rpl::producer<QChar> TimePart::putNext() const {
return _putNext.events();
}
void TimePart::keyPressEvent(QKeyEvent *e) {
const auto isBackspace = (e->key() == Qt::Key_Backspace);
const auto isBeginning = (cursorPosition() == 0);
if (isBackspace && isBeginning && !hasSelectedText()) {
_erasePrevious.fire({});
} else {
MaskedInputField::keyPressEvent(e);
}
}
void TimePart::wheelEvent(QWheelEvent *e) {
const auto direction = WheelDirection(e);
const auto now = number();
if (!now.has_value()) {
return;
}
auto time = *now + (direction * _wheelStep);
const auto max = _maxValue + 1;
if (time < 0) {
time += max;
} else if (time >= max) {
time -= max;
}
setText(QString::number(time));
}
void TimePart::correctValue(
const QString &was,
int wasCursor,
QString &now,
int &nowCursor) {
auto newText = QString();
auto newCursor = -1;
const auto oldCursor = nowCursor;
const auto oldLength = now.size();
auto accumulated = 0;
auto limit = 0;
for (; limit != oldLength; ++limit) {
if (now[limit].isDigit()) {
accumulated *= 10;
accumulated += (now[limit].unicode() - '0');
if (accumulated > _maxValue || limit == _maxDigits) {
break;
}
}
}
for (auto i = 0; i != limit;) {
if (now[i].isDigit()) {
newText += now[i];
}
if (++i == oldCursor) {
newCursor = newText.size();
}
}
if (newCursor < 0) {
newCursor = newText.size();
}
if (newText != now) {
now = newText;
setText(now);
startPlaceholderAnimation();
}
if (newCursor != nowCursor) {
nowCursor = newCursor;
setCursorPosition(nowCursor);
}
if (accumulated > _maxValue
|| (limit == _maxDigits && oldLength > _maxDigits)) {
if (oldCursor > limit) {
_putNext.fire('0' + (accumulated % 10));
} else {
_putNext.fire(0);
}
}
}
TimeInput::TimeInput(
QWidget *parent,
const QString &value,