mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 18:21:42 -05:00
307 lines
7.7 KiB
C++
307 lines
7.7 KiB
C++
/*
|
|
This file is part of Telegram Desktop,
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
For license and copyright information please follow this link:
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
*/
|
|
#include "passport/passport_edit_identity_box.h"
|
|
|
|
#include "passport/passport_panel_controller.h"
|
|
#include "ui/widgets/input_fields.h"
|
|
#include "ui/widgets/buttons.h"
|
|
#include "ui/text_options.h"
|
|
#include "lang/lang_keys.h"
|
|
#include "core/file_utilities.h"
|
|
#include "styles/style_widgets.h"
|
|
#include "styles/style_boxes.h"
|
|
#include "styles/style_passport.h"
|
|
|
|
namespace Passport {
|
|
|
|
class ScanButton : public Ui::RippleButton {
|
|
public:
|
|
ScanButton(
|
|
QWidget *parent,
|
|
const QString &title,
|
|
const QString &description);
|
|
|
|
void setImage(const QImage &image);
|
|
void setDescription(const QString &description);
|
|
|
|
rpl::producer<> deleteClicks() const {
|
|
return _delete->clicks();
|
|
}
|
|
|
|
protected:
|
|
int resizeGetHeight(int newWidth) override;
|
|
|
|
void paintEvent(QPaintEvent *e) override;
|
|
|
|
private:
|
|
int countAvailableWidth() const;
|
|
int countAvailableWidth(int newWidth) const;
|
|
|
|
Text _title;
|
|
Text _description;
|
|
int _titleHeight = 0;
|
|
int _descriptionHeight = 0;
|
|
QImage _image;
|
|
object_ptr<Ui::IconButton> _delete = { nullptr };
|
|
|
|
};
|
|
|
|
ScanButton::ScanButton(
|
|
QWidget *parent,
|
|
const QString &title,
|
|
const QString &description)
|
|
: RippleButton(parent, st::passportRowRipple)
|
|
, _title(
|
|
st::semiboldTextStyle,
|
|
title,
|
|
Ui::NameTextOptions())
|
|
, _description(
|
|
st::defaultTextStyle,
|
|
description,
|
|
Ui::NameTextOptions())
|
|
, _delete(this, st::passportScanDelete) {
|
|
}
|
|
|
|
void ScanButton::setImage(const QImage &image) {
|
|
_image = image;
|
|
update();
|
|
}
|
|
|
|
void ScanButton::setDescription(const QString &description) {
|
|
_description.setText(
|
|
st::defaultTextStyle,
|
|
description,
|
|
Ui::NameTextOptions());
|
|
update();
|
|
}
|
|
|
|
int ScanButton::resizeGetHeight(int newWidth) {
|
|
const auto availableWidth = countAvailableWidth(newWidth);
|
|
_titleHeight = st::semiboldFont->height;
|
|
_descriptionHeight = st::normalFont->height;
|
|
const auto result = st::passportRowPadding.top()
|
|
+ _titleHeight
|
|
+ st::passportRowSkip
|
|
+ _descriptionHeight
|
|
+ st::passportRowPadding.bottom();
|
|
const auto right = st::passportRowPadding.right();
|
|
_delete->moveToRight(
|
|
right,
|
|
(result - _delete->height()) / 2,
|
|
newWidth);
|
|
return result;
|
|
}
|
|
|
|
int ScanButton::countAvailableWidth(int newWidth) const {
|
|
return newWidth
|
|
- st::passportRowPadding.left()
|
|
- st::passportRowPadding.right()
|
|
- _delete->width();
|
|
}
|
|
|
|
int ScanButton::countAvailableWidth() const {
|
|
return countAvailableWidth(width());
|
|
}
|
|
|
|
void ScanButton::paintEvent(QPaintEvent *e) {
|
|
Painter p(this);
|
|
|
|
const auto ms = getms();
|
|
paintRipple(p, 0, 0, ms);
|
|
|
|
auto left = st::passportRowPadding.left();
|
|
auto availableWidth = countAvailableWidth();
|
|
auto top = st::passportRowPadding.top();
|
|
const auto size = height() - top - st::passportRowPadding.bottom();
|
|
if (_image.isNull()) {
|
|
p.fillRect(left, top, size, size, Qt::black);
|
|
} else {
|
|
PainterHighQualityEnabler hq(p);
|
|
if (_image.width() > _image.height()) {
|
|
auto newheight = size * _image.height() / _image.width();
|
|
p.drawImage(QRect(left, top + (size - newheight) / 2, size, newheight), _image);
|
|
} else {
|
|
auto newwidth = size * _image.width() / _image.height();
|
|
p.drawImage(QRect(left + (size - newwidth) / 2, top, newwidth, size), _image);
|
|
}
|
|
}
|
|
left += size + st::passportRowPadding.left();
|
|
availableWidth -= size + st::passportRowPadding.left();
|
|
|
|
_title.drawLeftElided(p, left, top, availableWidth, width());
|
|
top += _titleHeight + st::passportRowSkip;
|
|
|
|
_description.drawLeftElided(p, left, top, availableWidth, width());
|
|
top += _descriptionHeight + st::passportRowPadding.bottom();
|
|
}
|
|
|
|
IdentityBox::IdentityBox(
|
|
QWidget*,
|
|
not_null<PanelController*> controller,
|
|
int valueIndex,
|
|
const IdentityData &data,
|
|
std::vector<ScanInfo> &&files)
|
|
: _controller(controller)
|
|
, _valueIndex(valueIndex)
|
|
, _files(std::move(files))
|
|
, _uploadScan(this, "Upload scans") // #TODO langs
|
|
, _name(
|
|
this,
|
|
st::defaultInputField,
|
|
langFactory(lng_signup_firstname),
|
|
data.name)
|
|
, _surname(
|
|
this,
|
|
st::defaultInputField,
|
|
langFactory(lng_signup_lastname),
|
|
data.surname) {
|
|
}
|
|
|
|
void IdentityBox::prepare() {
|
|
setTitle(langFactory(lng_passport_identity_title));
|
|
|
|
auto index = 0;
|
|
for (const auto &scan : _files) {
|
|
_scans.push_back(object_ptr<ScanButton>(
|
|
this,
|
|
QString("Scan %1").arg(++index), // #TODO langs
|
|
scan.status));
|
|
_scans.back()->setImage(scan.thumb);
|
|
_scans.back()->resizeToWidth(st::boxWideWidth);
|
|
_scans.back()->deleteClicks(
|
|
) | rpl::start_with_next([=] {
|
|
_controller->deleteScan(_valueIndex, index - 1);
|
|
}, lifetime());
|
|
}
|
|
|
|
addButton(langFactory(lng_settings_save), [=] {
|
|
save();
|
|
});
|
|
addButton(langFactory(lng_cancel), [=] {
|
|
closeBox();
|
|
});
|
|
_controller->scanUpdated(
|
|
) | rpl::start_with_next([=](ScanInfo &&info) {
|
|
updateScan(std::move(info));
|
|
}, lifetime());
|
|
|
|
_uploadScan->addClickHandler([=] {
|
|
chooseScan();
|
|
});
|
|
setDimensions(st::boxWideWidth, countHeight());
|
|
}
|
|
|
|
int IdentityBox::countHeight() const {
|
|
auto height = st::contactPadding.top();
|
|
for (const auto &scan : _scans) {
|
|
height += scan->height();
|
|
}
|
|
height += st::contactPadding.top()
|
|
+ _uploadScan->height()
|
|
+ st::contactSkip
|
|
+ _name->height()
|
|
+ st::contactSkip
|
|
+ _surname->height()
|
|
+ st::contactPadding.bottom()
|
|
+ st::boxPadding.bottom();
|
|
return height;
|
|
}
|
|
|
|
void IdentityBox::updateScan(ScanInfo &&info) {
|
|
const auto i = ranges::find(_files, info.key, [](const ScanInfo &file) {
|
|
return file.key;
|
|
});
|
|
if (i != _files.end()) {
|
|
*i = info;
|
|
_scans[i - _files.begin()]->setDescription(i->status);
|
|
_scans[i - _files.begin()]->setImage(i->thumb);
|
|
} else {
|
|
_files.push_back(std::move(info));
|
|
_scans.push_back(object_ptr<ScanButton>(
|
|
this,
|
|
QString("Scan %1").arg(_files.size()),
|
|
_files.back().status));
|
|
_scans.back()->setImage(_files.back().thumb);
|
|
_scans.back()->resizeToWidth(st::boxWideWidth);
|
|
_scans.back()->show();
|
|
updateControlsPosition();
|
|
setDimensions(st::boxWideWidth, countHeight());
|
|
}
|
|
update();
|
|
}
|
|
|
|
void IdentityBox::setInnerFocus() {
|
|
_name->setFocusFast();
|
|
}
|
|
|
|
void IdentityBox::resizeEvent(QResizeEvent *e) {
|
|
BoxContent::resizeEvent(e);
|
|
|
|
_name->resize((width()
|
|
- st::boxPadding.left()
|
|
- st::boxPadding.right()),
|
|
_name->height());
|
|
_surname->resize(_name->width(), _surname->height());
|
|
|
|
updateControlsPosition();
|
|
}
|
|
|
|
void IdentityBox::updateControlsPosition() {
|
|
auto top = st::contactPadding.top();
|
|
for (const auto &scan : _scans) {
|
|
scan->moveToLeft(0, top);
|
|
top += scan->height();
|
|
}
|
|
top += st::contactPadding.top();
|
|
_uploadScan->moveToLeft(st::boxPadding.left(), top);
|
|
top += _uploadScan->height() + st::contactSkip;
|
|
_name->moveToLeft(st::boxPadding.left(), top);
|
|
top += _name->height() + st::contactSkip;
|
|
_surname->moveToLeft(st::boxPadding.left(), top);
|
|
}
|
|
|
|
void IdentityBox::chooseScan() {
|
|
const auto filter = FileDialog::AllFilesFilter()
|
|
+ qsl(";;Image files (*")
|
|
+ cImgExtensions().join(qsl(" *"))
|
|
+ qsl(")");
|
|
const auto callback = [=](FileDialog::OpenResult &&result) {
|
|
if (result.paths.size() == 1) {
|
|
encryptScan(result.paths.front());
|
|
} else if (!result.remoteContent.isEmpty()) {
|
|
encryptScanContent(std::move(result.remoteContent));
|
|
}
|
|
};
|
|
FileDialog::GetOpenPath(
|
|
"Choose scan image",
|
|
filter,
|
|
base::lambda_guarded(this, callback));
|
|
}
|
|
|
|
void IdentityBox::encryptScan(const QString &path) {
|
|
encryptScanContent([&] {
|
|
QFile f(path);
|
|
if (!f.open(QIODevice::ReadOnly)) {
|
|
return QByteArray();
|
|
}
|
|
return f.readAll();
|
|
}());
|
|
}
|
|
|
|
void IdentityBox::encryptScanContent(QByteArray &&content) {
|
|
_controller->uploadScan(_valueIndex, std::move(content));
|
|
}
|
|
|
|
void IdentityBox::save() {
|
|
auto data = IdentityData();
|
|
data.name = _name->getLastText();
|
|
data.surname = _surname->getLastText();
|
|
_controller->saveValueIdentity(_valueIndex, data);
|
|
}
|
|
|
|
} // namespace Passport
|