tdesktop/Telegram/SourceFiles/boxes/passcodebox.cpp

280 lines
8.8 KiB
C++

/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
#include "stdafx.h"
#include "lang.h"
#include "passcodebox.h"
#include "window.h"
#include "localstorage.h"
PasscodeBox::PasscodeBox(bool turningOff) : _turningOff(turningOff),
_about(st::addContactWidth - st::addContactPadding.left() - st::addContactPadding.right()),
_saveButton(this, lang(lng_settings_save), st::btnSelectDone),
_cancelButton(this, lang(lng_cancel), st::btnSelectCancel),
_oldPasscode(this, st::inpAddContact, lang(lng_passcode_enter_old)),
_newPasscode(this, st::inpAddContact, lang(lng_passcode_enter_new)),
_reenterPasscode(this, st::inpAddContact, lang(lng_passcode_confirm_new)),
a_opacity(0, 1), _hiding(false) {
_width = st::addContactWidth;
_about.setRichText(st::usernameFont, lang(lng_passcode_about));
int32 aboutHeight = _about.countHeight(_width - st::addContactPadding.left() - st::addContactPadding.right());
_oldPasscode.setEchoMode(QLineEdit::Password);
_newPasscode.setEchoMode(QLineEdit::Password);
_reenterPasscode.setEchoMode(QLineEdit::Password);
if (turningOff) {
_oldPasscode.show();
_boxTitle = lang(lng_passcode_remove);
_height = st::addContactTitleHeight + st::addContactPadding.top() + 1 * _oldPasscode.height() + st::usernameSkip + aboutHeight + st::addContactPadding.bottom() + _saveButton.height();
} else {
if (cHasPasscode()) {
_oldPasscode.show();
_boxTitle = lang(lng_passcode_change);
_height = st::addContactTitleHeight + st::addContactPadding.top() + 3 * _oldPasscode.height() + st::usernameSkip * 2 + 1 * st::addContactDelta + aboutHeight + st::addContactPadding.bottom() + _saveButton.height();
} else {
_oldPasscode.hide();
_boxTitle = lang(lng_passcode_create);
_height = st::addContactTitleHeight + st::addContactPadding.top() + 2 * _oldPasscode.height() + st::usernameSkip + 1 * st::addContactDelta + aboutHeight + st::addContactPadding.bottom() + _saveButton.height();
}
}
_oldPasscode.setGeometry(st::addContactPadding.left(), st::addContactTitleHeight + st::addContactPadding.top(), _width - st::addContactPadding.left() - st::addContactPadding.right(), _oldPasscode.height());
_newPasscode.setGeometry(st::addContactPadding.left(), _oldPasscode.y() + ((turningOff || cHasPasscode()) ? (_oldPasscode.height() + st::usernameSkip) : 0), _oldPasscode.width(), _oldPasscode.height());
_reenterPasscode.setGeometry(st::addContactPadding.left(), _newPasscode.y() + _newPasscode.height() + st::addContactDelta, _newPasscode.width(), _newPasscode.height());
int32 buttonTop = _height - _cancelButton.height();
_cancelButton.move(0, buttonTop);
_saveButton.move(_width - _saveButton.width(), buttonTop);
connect(&_saveButton, SIGNAL(clicked()), this, SLOT(onSave()));
connect(&_cancelButton, SIGNAL(clicked()), this, SLOT(onCancel()));
_badOldTimer.setSingleShot(true);
connect(&_badOldTimer, SIGNAL(timeout()), this, SLOT(onBadOldPasscode()));
connect(&_oldPasscode, SIGNAL(changed()), this, SLOT(onOldChanged()));
connect(&_newPasscode, SIGNAL(changed()), this, SLOT(onNewChanged()));
connect(&_reenterPasscode, SIGNAL(changed()), this, SLOT(onNewChanged()));
resize(_width, _height);
showAll();
_cache = myGrab(this, rect());
hideAll();
}
void PasscodeBox::hideAll() {
_oldPasscode.hide();
_newPasscode.hide();
_reenterPasscode.hide();
_saveButton.hide();
_cancelButton.hide();
}
void PasscodeBox::showAll() {
if (_turningOff) {
_oldPasscode.show();
_newPasscode.hide();
_reenterPasscode.hide();
} else {
if (cHasPasscode()) {
_oldPasscode.show();
} else {
_oldPasscode.hide();
}
_newPasscode.show();
_reenterPasscode.show();
}
_saveButton.show();
_cancelButton.show();
}
void PasscodeBox::keyPressEvent(QKeyEvent *e) {
if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
if (_oldPasscode.hasFocus()) {
if (_turningOff) {
onSave();
} else {
_newPasscode.setFocus();
}
} else if (_newPasscode.hasFocus()) {
_reenterPasscode.setFocus();
} else if (_reenterPasscode.hasFocus()) {
if (cHasPasscode() && _oldPasscode.text().isEmpty()) {
_oldPasscode.setFocus();
_oldPasscode.notaBene();
} else if (_newPasscode.text().isEmpty()) {
_newPasscode.setFocus();
_newPasscode.notaBene();
} else if (_reenterPasscode.text().isEmpty()) {
_reenterPasscode.notaBene();
} else {
onSave();
}
}
} else if (e->key() == Qt::Key_Escape) {
onCancel();
}
}
void PasscodeBox::parentResized() {
QSize s = parentWidget()->size();
setGeometry((s.width() - _width) / 2, (s.height() - _height) / 2, _width, _height);
update();
}
void PasscodeBox::paintEvent(QPaintEvent *e) {
QPainter p(this);
if (_cache.isNull()) {
if (!_hiding || a_opacity.current() > 0.01) {
// fill bg
p.fillRect(QRect(QPoint(0, 0), size()), st::boxBG->b);
// paint shadows
p.fillRect(0, st::addContactTitleHeight, _width, st::scrollDef.topsh, st::scrollDef.shColor->b);
p.fillRect(0, size().height() - st::btnSelectCancel.height - st::scrollDef.bottomsh, _width, st::scrollDef.bottomsh, st::scrollDef.shColor->b);
p.setPen(st::usernameColor->p);
_about.draw(p, st::addContactPadding.left(), (_turningOff ? _oldPasscode : _reenterPasscode).y() + _oldPasscode.height() + st::usernameSkip, _width - st::addContactPadding.left() - st::addContactPadding.right());
if (!_oldError.isEmpty()) {
p.setPen(st::setErrColor->p);
p.drawText(QRect(0, _oldPasscode.y() + _oldPasscode.height(), _width, st::usernameSkip), _oldError, style::al_center);
}
if (!_newError.isEmpty()) {
p.setPen(st::setErrColor->p);
p.drawText(QRect(0, _reenterPasscode.y() + _reenterPasscode.height(), _width, st::usernameSkip), _newError, style::al_center);
}
// paint button sep
p.fillRect(st::btnSelectCancel.width, size().height() - st::btnSelectCancel.height, st::lineWidth, st::btnSelectCancel.height, st::btnSelectSep->b);
// draw box title / text
p.setPen(st::black->p);
p.setFont(st::addContactTitleFont->f);
p.drawText(st::addContactTitlePos.x(), st::addContactTitlePos.y() + st::addContactTitleFont->ascent, _boxTitle);
}
} else {
p.setOpacity(a_opacity.current());
p.drawPixmap(0, 0, _cache);
}
}
void PasscodeBox::animStep(float64 dt) {
if (dt >= 1) {
a_opacity.finish();
_cache = QPixmap();
if (!_hiding) {
showAll();
if (_oldPasscode.isHidden()) {
_newPasscode.setFocus();
} else {
_oldPasscode.setFocus();
}
}
} else {
a_opacity.update(dt, anim::linear);
}
update();
}
void PasscodeBox::onSave() {
QString old = _oldPasscode.text(), pwd = _newPasscode.text(), conf = _reenterPasscode.text();
if (_turningOff || cHasPasscode()) {
if (Local::checkPasscode(old.toUtf8())) {
if (_turningOff) pwd = conf = QString();
} else {
_oldPasscode.setDisabled(true);
_newPasscode.setDisabled(true);
_reenterPasscode.setDisabled(true);
_saveButton.setDisabled(true);
_oldError = QString();
update();
_badOldTimer.start(WrongPasscodeTimeout);
return;
}
}
if (!_turningOff && pwd.isEmpty()) {
_newPasscode.setFocus();
_newPasscode.notaBene();
return;
}
if (pwd != conf) {
_reenterPasscode.setFocus();
_reenterPasscode.notaBene();
if (!conf.isEmpty()) {
_newError = lang(lng_passcode_differ);
update();
}
} else if (!_turningOff && cHasPasscode() && old == pwd) {
_newPasscode.setFocus();
_newPasscode.notaBene();
_newError = lang(lng_passcode_is_same);
update();
} else {
Local::setPasscode(pwd.toUtf8());
App::wnd()->checkAutoLock();
App::wnd()->getTitle()->showUpdateBtn();
emit closed();
}
}
void PasscodeBox::onBadOldPasscode() {
_oldPasscode.setDisabled(false);
_newPasscode.setDisabled(false);
_reenterPasscode.setDisabled(false);
_saveButton.setDisabled(false);
_oldPasscode.selectAll();
_oldPasscode.setFocus();
_oldPasscode.notaBene();
_oldError = lang(lng_passcode_wrong);
update();
}
void PasscodeBox::onOldChanged() {
if (!_oldError.isEmpty()) {
_oldError = QString();
update();
}
}
void PasscodeBox::onNewChanged() {
if (!_newError.isEmpty()) {
_newError = QString();
update();
}
}
void PasscodeBox::onCancel() {
emit closed();
}
void PasscodeBox::startHide() {
_hiding = true;
if (_cache.isNull()) {
_cache = myGrab(this, rect());
hideAll();
}
a_opacity.start(0);
}
PasscodeBox::~PasscodeBox() {
}