Added missing files and removed unnessesary ones
This commit is contained in:
1 parent
c3fa5367c3
commit
199dd693e4
41 files changed
+1442
-50
No files matched your search
Vendored
-50
@@ -1,50 +0,0 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"algorithm": "cpp",
|
||||
"iostream": "cpp",
|
||||
"numeric": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"random": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"new": "cpp",
|
||||
"numbers": "cpp",
|
||||
"ostream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cstring": "cpp"
|
||||
}
|
||||
}
|
||||
+240
@@ -545,3 +545,243 @@ void boo(int* ptr) {
|
||||
## Структуры
|
||||
|
||||
> Структура - тип данных, позоляющий объединить несколько переменных в одной еденице.
|
||||
|
||||
```C++
|
||||
#include <iostream>
|
||||
|
||||
struct Employee {
|
||||
short id;
|
||||
int age;
|
||||
double salary;
|
||||
};
|
||||
|
||||
Employee john = {5, 20, 30.0};
|
||||
std::cout << john.id << ' ' << john.age << ' ' << john.salary << '\n';
|
||||
```
|
||||
|
||||
## Перечисления
|
||||
|
||||
> Перечисление - это пользовательский тип данных, который представляет собой набор именованных констант, которым присваиваются целочисленные значения. Весит как *int*
|
||||
|
||||
```C++
|
||||
#include <iostream>
|
||||
|
||||
enum Weekday {
|
||||
Monday,
|
||||
Tuesday,
|
||||
Wednesday,
|
||||
Thursday,
|
||||
Friday,
|
||||
Saturday,
|
||||
Sunday,
|
||||
};
|
||||
|
||||
enum Weekday2 {
|
||||
Monday = 1,
|
||||
Tuesday = 2,
|
||||
Wednesday = 3,
|
||||
Thursday = 4,
|
||||
Friday = 5,
|
||||
Saturday = 6,
|
||||
Sunday = 7,
|
||||
};
|
||||
|
||||
Weekday today = Saturday;
|
||||
```
|
||||
|
||||
Weekday полностью аналогичен Weekday2
|
||||
|
||||
## Объединение
|
||||
|
||||
> Объединение - это пользовательский тип данных, позволяющий хранить различные типы данных в одной области памяти. Объединение занимает память, достаточную для хранения переменной имеющий самый большой размер.
|
||||
|
||||
```C++
|
||||
union MyUnion{
|
||||
int intValue;
|
||||
char charValue;
|
||||
};
|
||||
|
||||
MyUnion val = 65;
|
||||
int a = val.intValue; // 65
|
||||
char b = val.charValue; // 'A'
|
||||
```
|
||||
|
||||
## Передача значений в функцию (Подробнее)
|
||||
|
||||
* Передача по значению (создаётся копия, может быть медленно, используется для примитивов)
|
||||
|
||||
```C++
|
||||
void increment(int a) {
|
||||
a++;
|
||||
}
|
||||
|
||||
int a = 5;
|
||||
increment(&a); // a остаётся 5
|
||||
```
|
||||
|
||||
* Передача по ссылке (копия не создаётся, используется для больших значений / структур, аналогична передаче по значению, но синтаксис проще)
|
||||
|
||||
```C++
|
||||
void increment(int& a) {
|
||||
a++;
|
||||
}
|
||||
|
||||
int a = 5;
|
||||
increment(a); // a становится 6
|
||||
```
|
||||
|
||||
* Передача по указателю (копия не создаётся, используется в основном для массивов)
|
||||
|
||||
```C++
|
||||
void increment(int* a) {
|
||||
(*a)++;
|
||||
}
|
||||
|
||||
int a = 5;
|
||||
increment(&a); // a тоже становится 6
|
||||
```
|
||||
|
||||
## Классы
|
||||
|
||||
> Классы - шаблон или описание, определяющее структуру поведения объектов.
|
||||
> Объект - экземляр класса
|
||||
|
||||
```С++
|
||||
class ClassName{
|
||||
// Поля и методы класса
|
||||
};
|
||||
```
|
||||
|
||||
> Поля класса - переменные, котроые представляют состояие объетогв класса
|
||||
> Методы класа - функции, которые определяют поведение объектов класса
|
||||
|
||||
```С++
|
||||
ClassName objectName; // создание объекта класса просто
|
||||
|
||||
ClassName objectName = new ClassName(); //создание объекта класса сложно
|
||||
delete objectName;
|
||||
```
|
||||
|
||||
## Пример
|
||||
|
||||
```С++
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
class Person{
|
||||
public:
|
||||
std::string name;
|
||||
int age;
|
||||
|
||||
void displayInfo(){
|
||||
std::count << "Name: " << name << ", Age: " << age << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
int main(){
|
||||
Person person1;
|
||||
person1.name = "Alice";
|
||||
person1.age = 25;
|
||||
person1.displayInfo();
|
||||
|
||||
Person* person2 = new Person();
|
||||
person2 -> name = "Bob";
|
||||
person2 -> age = 30;
|
||||
person2 -> displayInfo();
|
||||
|
||||
delete person2;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
> Пользовательский тип данных
|
||||
|
||||
### Модификаторы доступа
|
||||
|
||||
* public - доступно всем (по умолчанию в struct)
|
||||
* private - доступно только внутри класса (по умолчанию в class)
|
||||
* protected - достпуно внутри класса и наследникам
|
||||
|
||||
### Конструктор и деструктор
|
||||
|
||||
> Конструктор - функция, которая вызывается при инициализации класса (может быть несколько)
|
||||
> Деструктор - функция, которая вызывается при уничтожении объекта
|
||||
|
||||
```C++
|
||||
#include <iostream>
|
||||
|
||||
class MyClass {
|
||||
public:
|
||||
MyClass() {
|
||||
std::cout << "Constructed\n";
|
||||
}
|
||||
|
||||
MyClass(int val) {
|
||||
std::cout << "Constucted" << val << '\n';f
|
||||
}
|
||||
|
||||
~MyClass() {
|
||||
std::cout << "Destroyed\n";
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### this
|
||||
|
||||
> this - указатель на объект вызвовший метод
|
||||
|
||||
```C++
|
||||
#include <string>
|
||||
|
||||
class Foo{
|
||||
public:
|
||||
Person(std::string val) {
|
||||
this->name = val;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## ООП
|
||||
|
||||
> Инкапсуляция - данные класса скрыты от прямого доступа и манипулиций извне класса
|
||||
> Наследование - создаёт классы-потомки
|
||||
> Полимарфизм - разные классы используют один и тот же интерфейс
|
||||
|
||||
```C++
|
||||
#include <iostream>
|
||||
|
||||
class Figure {
|
||||
public:
|
||||
virtual void draw() {
|
||||
std::cout << "Draw figure\n";
|
||||
}
|
||||
};
|
||||
|
||||
class Circe: public Figure {
|
||||
public:
|
||||
void draw() override {
|
||||
std::cout << "Draw circle\n";
|
||||
}
|
||||
};
|
||||
|
||||
class Rectangle: public Figure {
|
||||
public:
|
||||
void draw() override {
|
||||
std::cout << "Draw rectangle\n";
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
Figure* figure = new Figure();
|
||||
Figure* circle = new Circle():
|
||||
Figure* rectangle = new Rectangle();
|
||||
|
||||
figure->draw();
|
||||
circle->draw();
|
||||
rectangle->draw();
|
||||
|
||||
delete figure;
|
||||
delete circle;
|
||||
delete rectangle;
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
class Person {
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
public:
|
||||
Person(const std::string& name) {
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
void printName() {
|
||||
std::cout << this->name << '\n';
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
class Student {
|
||||
std::string name;
|
||||
int age;
|
||||
double average_grade;
|
||||
|
||||
public:
|
||||
Student(std::string name, int age, double average) {
|
||||
this->name = name;
|
||||
this->age = age;
|
||||
this->average_grade = average;
|
||||
}
|
||||
|
||||
std::string& get_name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
int get_age() {
|
||||
return age;
|
||||
}
|
||||
|
||||
double get_average_grade() {
|
||||
return average_grade;
|
||||
}
|
||||
|
||||
void status() {
|
||||
if (average_grade >= 4 && average_grade < 5) {
|
||||
std::cout << "Student is хорошист" << '\n';
|
||||
} else if (average_grade = 5) {
|
||||
std::cout << "Student is отличник" << '\n';
|
||||
} else if (average_grade < 3) {
|
||||
std::cout << "Student is двоечник" << '\n';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
Student student1("George", 19, 3.5);
|
||||
Student student2("Paul", 14, 4.8);
|
||||
Student student3("Vasyok", 17, 5);
|
||||
|
||||
student1.status();
|
||||
student2.status();
|
||||
student3.status();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <iostream>
|
||||
|
||||
struct Account {
|
||||
int number;
|
||||
int money;
|
||||
int percentage;
|
||||
|
||||
public:
|
||||
Account(int number, int money, int percentage) {
|
||||
this->number = number;
|
||||
this->money = money;
|
||||
this->percentage = percentage;
|
||||
}
|
||||
|
||||
void refill(int amount) {
|
||||
money += amount;
|
||||
}
|
||||
|
||||
void withdraw(int amount) {
|
||||
money -= amount;
|
||||
}
|
||||
|
||||
void PrintInformation() {
|
||||
std::cout << number << ' ' << money << ' ' << percentage << '\n';
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
Account* account1 = new Account(21213, 500, 15);
|
||||
account1->PrintInformation();
|
||||
account1->refill(200);
|
||||
account1->withdraw(50);
|
||||
account1->PrintInformation();
|
||||
|
||||
Account* account2 = new Account(1934, 800, 10);
|
||||
account2->PrintInformation();
|
||||
account2->refill(150);
|
||||
account2->withdraw(23);
|
||||
account2->PrintInformation();
|
||||
}
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
import sys
|
||||
from time import strftime
|
||||
|
||||
from PyQt6.QtCore import QTimer
|
||||
from PyQt6.QtWidgets import QApplication, QLCDNumber, QVBoxLayout, QWidget
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setGeometry(100, 100, 800, 400)
|
||||
self.setWindowTitle("Clock")
|
||||
vbox = QVBoxLayout()
|
||||
|
||||
self.timer = QTimer()
|
||||
self.timer.timeout.connect(self.update_clock)
|
||||
self.timer.start(200)
|
||||
|
||||
self.lcd = QLCDNumber()
|
||||
vbox.addWidget(self.lcd)
|
||||
self.setLayout(vbox)
|
||||
|
||||
def update_clock(self) -> None:
|
||||
time_ = strftime("%H:%M:%S")
|
||||
self.lcd.setDigitCount(8)
|
||||
self.lcd.display(time_)
|
||||
|
||||
|
||||
def main():
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 347 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
Executable
+21
@@ -0,0 +1,21 @@
|
||||
import sys
|
||||
|
||||
from PyQt6.QtWidgets import QApplication, QWidget
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.setGeometry(*(500,) * 4)
|
||||
self.setWindowTitle("Окно")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
import sys
|
||||
|
||||
from PyQt6.QtWidgets import (
|
||||
QApplication,
|
||||
QWidget,
|
||||
QHBoxLayout,
|
||||
QSpinBox,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
)
|
||||
from PyQt6.QtGui import QFont
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.setGeometry(*(500,) * 4)
|
||||
self.setWindowTitle("Окно")
|
||||
self.price = 300
|
||||
self.amount = 0
|
||||
|
||||
hbox = QHBoxLayout()
|
||||
|
||||
self.line_edit = QLineEdit(str(self.price))
|
||||
self.line_edit.setFont(QFont("Times", 14))
|
||||
|
||||
self.spin_box = QSpinBox()
|
||||
self.spin_box.valueChanged.connect(self.handle_spin_box)
|
||||
self.result = QLabel(str(self.total))
|
||||
|
||||
hbox.addWidget(self.line_edit)
|
||||
hbox.addWidget(self.spin_box)
|
||||
hbox.addWidget(self.result)
|
||||
|
||||
self.setLayout(hbox)
|
||||
|
||||
def handle_spin_box(self) -> None:
|
||||
try:
|
||||
self.price = int(self.line_edit.text())
|
||||
except ValueError:
|
||||
return
|
||||
self.amount = self.spin_box.value()
|
||||
self.result.setText(str(self.total))
|
||||
|
||||
@property
|
||||
def total(self) -> int:
|
||||
return self.amount * self.price
|
||||
|
||||
def handle_line_edit(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
import sys
|
||||
|
||||
from PyQt6.QtWidgets import QApplication, QWidget, QLabel
|
||||
from PyQt6.QtGui import QPixmap
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.setGeometry(*(500,) * 4)
|
||||
self.setWindowTitle("Окно")
|
||||
|
||||
label = QLabel(self)
|
||||
label.setText("Текст")
|
||||
label.move(300, 300)
|
||||
|
||||
pixmap = QPixmap()
|
||||
lable_pic = QLabel(self)
|
||||
lable_pic.setPicture(pixmap)
|
||||
lable_pic.move(200, 200)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
import sys
|
||||
|
||||
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton
|
||||
from PyQt6.QtCore import QSize
|
||||
from PyQt6.QtGui import QFont, QIcon
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.setGeometry(*(500,) * 4)
|
||||
self.setWindowTitle("Окно")
|
||||
self.create_button()
|
||||
|
||||
def create_button(self) -> None:
|
||||
btn = QPushButton("Click", self)
|
||||
btn.setGeometry(*(100,) * 4)
|
||||
btn.setFont(QFont("Times", 14, QFont.Weight.ExtraBold))
|
||||
btn.setIcon(QIcon("cat1.jpg"))
|
||||
btn.setIconSize(QSize(50, 50))
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
import sys
|
||||
|
||||
from PyQt6.QtGui import QFont
|
||||
from PyQt6.QtWidgets import QApplication, QLineEdit, QWidget
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.setGeometry(*(500,) * 4)
|
||||
self.setWindowTitle("Окно")
|
||||
|
||||
line_edit = QLineEdit(self)
|
||||
line_edit.setFont(QFont("Times", 14))
|
||||
line_edit.setPlaceholderText("Enter your password")
|
||||
line_edit.setEchoMode(QLineEdit.EchoMode.Password)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
import sys
|
||||
|
||||
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.setGeometry(*(500,) * 4)
|
||||
self.setWindowTitle("Окно")
|
||||
|
||||
btn1 = QPushButton("One")
|
||||
btn2 = QPushButton("Two")
|
||||
btn3 = QPushButton("Three")
|
||||
|
||||
layout = QHBoxLayout()
|
||||
layout.addWidget(btn1)
|
||||
layout.addWidget(btn2)
|
||||
layout.addWidget(btn3)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
import sys
|
||||
|
||||
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.setGeometry(*(500,) * 4)
|
||||
self.setWindowTitle("Окно")
|
||||
|
||||
btn1 = QPushButton("One")
|
||||
btn2 = QPushButton("Two")
|
||||
btn3 = QPushButton("Three")
|
||||
|
||||
layout = QVBoxLayout()
|
||||
layout.addWidget(btn1)
|
||||
layout.addWidget(btn2)
|
||||
layout.addWidget(btn3)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
import sys
|
||||
|
||||
from PyQt6.QtCore import QSize
|
||||
from PyQt6.QtGui import QIcon
|
||||
from PyQt6.QtWidgets import (
|
||||
QApplication,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QRadioButton,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
|
||||
ICON_SIZE = 100
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.setGeometry(200, 200, 400, 300)
|
||||
self.setWindowTitle("Окно")
|
||||
self.create_radio()
|
||||
|
||||
def create_radio(self) -> None:
|
||||
hbox = QHBoxLayout()
|
||||
|
||||
rad1 = QRadioButton("Cat 1")
|
||||
rad1.setIcon(QIcon("cat1.jpg"))
|
||||
rad1.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
|
||||
rad1.toggled.connect(self.radio_selected)
|
||||
|
||||
rad2 = QRadioButton("Cat 2")
|
||||
rad2.setIcon(QIcon("cat2.jpg"))
|
||||
rad2.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
|
||||
rad2.toggled.connect(self.radio_selected)
|
||||
|
||||
hbox.addWidget(rad1)
|
||||
hbox.addWidget(rad2)
|
||||
|
||||
vbox = QVBoxLayout()
|
||||
|
||||
self.label = QLabel("")
|
||||
|
||||
vbox.addWidget(self.label)
|
||||
vbox.addLayout(hbox)
|
||||
self.setLayout(vbox)
|
||||
|
||||
def radio_selected(self) -> None:
|
||||
radio_btn = self.sender()
|
||||
if radio_btn.isEnabled():
|
||||
self.label.setText(f"You have chosen {radio_btn.text().lower()}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
import sys
|
||||
|
||||
from PyQt6.QtCore import QSize
|
||||
from PyQt6.QtGui import QIcon
|
||||
from PyQt6.QtWidgets import (
|
||||
QApplication,
|
||||
QCheckBox,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
ICON_SIZE = 100
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.setGeometry(200, 200, 400, 300)
|
||||
self.setWindowTitle("Окно")
|
||||
self.create_radio()
|
||||
|
||||
def create_radio(self) -> None:
|
||||
hbox = QHBoxLayout()
|
||||
|
||||
self.check1 = QCheckBox("Cat 1")
|
||||
self.check1.setIcon(QIcon("cat1.jpg"))
|
||||
self.check1.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
|
||||
self.check1.toggled.connect(self.radio_selected)
|
||||
|
||||
self.check2 = QCheckBox("Cat 2")
|
||||
self.check2.setIcon(QIcon("cat2.jpg"))
|
||||
self.check2.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
|
||||
self.check2.toggled.connect(self.radio_selected)
|
||||
|
||||
hbox.addWidget(self.check1)
|
||||
hbox.addWidget(self.check2)
|
||||
|
||||
vbox = QVBoxLayout()
|
||||
|
||||
self.label = QLabel("You haven't chosen anything")
|
||||
|
||||
vbox.addWidget(self.label)
|
||||
vbox.addLayout(hbox)
|
||||
self.setLayout(vbox)
|
||||
|
||||
def radio_selected(self) -> None:
|
||||
text = "You have chosen "
|
||||
if self.check1.isChecked():
|
||||
text += self.check1.text().lower() + ", "
|
||||
if self.check2.isChecked():
|
||||
text += self.check2.text().lower()
|
||||
if not any((self.check1.isChecked(), self.check2.isChecked())):
|
||||
text = "You haven't chosen anything"
|
||||
text = text.removesuffix(", ")
|
||||
self.label.setText(text)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+70
@@ -0,0 +1,70 @@
|
||||
import sys
|
||||
from enum import StrEnum
|
||||
|
||||
from PyQt6.QtGui import QFont
|
||||
from PyQt6.QtWidgets import (
|
||||
QApplication,
|
||||
QComboBox,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
|
||||
class CatType(StrEnum):
|
||||
ORANGE = "one orange brain cell"
|
||||
VOID = "void"
|
||||
DUST = "dust kitty"
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.setGeometry(*(500,) * 4)
|
||||
self.setWindowTitle("Окно")
|
||||
self.current_type = CatType.ORANGE
|
||||
self.create_combo()
|
||||
|
||||
def create_combo(self) -> None:
|
||||
hbox = QHBoxLayout()
|
||||
|
||||
label = QLabel("Select cat type:")
|
||||
label.setFont(QFont("Times", 15))
|
||||
|
||||
self.combo = QComboBox(self)
|
||||
for cat_type in CatType:
|
||||
self.combo.addItem(cat_type.capitalize())
|
||||
self.combo.currentTextChanged.connect(self.combo_changed)
|
||||
|
||||
hbox.addWidget(label)
|
||||
hbox.addWidget(self.combo)
|
||||
|
||||
vbox = QVBoxLayout()
|
||||
self.label_result = QLabel(
|
||||
f"Current cat: {self.current_type.capitalize()}",
|
||||
)
|
||||
|
||||
self.label_result.setFont(QFont("Times", 15))
|
||||
|
||||
vbox = QVBoxLayout()
|
||||
vbox.addWidget(self.label_result)
|
||||
vbox.addLayout(hbox)
|
||||
self.setLayout(vbox)
|
||||
|
||||
def combo_changed(self) -> None:
|
||||
self.current_type = CatType(self.combo.currentText().lower())
|
||||
self.label_result.setText(
|
||||
f"Current cat: {self.current_type.capitalize()}",
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
Whitespace-only changes.
Executable
Whitespace-only changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
Executable
+207
@@ -0,0 +1,207 @@
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum, auto
|
||||
from random import sample
|
||||
from typing import Any, Callable, Iterator, Self
|
||||
|
||||
from PyQt6 import QtGui
|
||||
from PyQt6.QtCore import QSize, Qt, QTimer
|
||||
from PyQt6.QtGui import QIcon
|
||||
from PyQt6.QtWidgets import (
|
||||
QApplication,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QLCDNumber,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True, frozen=True)
|
||||
class Cords:
|
||||
x: int
|
||||
y: int
|
||||
|
||||
|
||||
class ButtonType(StrEnum):
|
||||
EMPTY = auto()
|
||||
BOMB = auto()
|
||||
NUMBER = auto()
|
||||
|
||||
|
||||
class Button(QPushButton):
|
||||
def __init__(
|
||||
self,
|
||||
cords: Cords,
|
||||
handler1: Callable[[Self, bool], Any],
|
||||
handler2: Callable[[Self], Any],
|
||||
) -> None:
|
||||
super().__init__()
|
||||
self.setFixedSize(50, 50)
|
||||
self.type = ButtonType.EMPTY
|
||||
self.number = 0
|
||||
self.cords = cords
|
||||
self.marked: bool = False
|
||||
self.revealed: bool = False
|
||||
self.left_handler = handler1
|
||||
self.right_handler = handler2
|
||||
|
||||
def reveal(self) -> Iterator[Cords]:
|
||||
self.revealed = True
|
||||
self.setStyleSheet("background-color: grey")
|
||||
if self.type is ButtonType.NUMBER:
|
||||
self.setText(str(self.number))
|
||||
|
||||
def mousePressEvent(self, e: QtGui.QMouseEvent) -> None:
|
||||
if e.button() is Qt.MouseButton.LeftButton:
|
||||
self.left_handler(self, True)
|
||||
elif e.button() is Qt.MouseButton.RightButton:
|
||||
self.right_handler(self)
|
||||
|
||||
def get_neighbors(self) -> Iterator[Cords]:
|
||||
for x in range(self.cords.x - 1, self.cords.x + 2):
|
||||
for y in range(self.cords.y - 1, self.cords.y + 2):
|
||||
if x < 0 or x >= 10:
|
||||
continue
|
||||
if y < 0 or y >= 10:
|
||||
continue
|
||||
if Cords(x, y) == self.cords:
|
||||
continue
|
||||
yield Cords(x, y)
|
||||
|
||||
def update_texture(self) -> None:
|
||||
if self.marked:
|
||||
self.setIcon(QIcon("flag.jpg"))
|
||||
self.setIconSize(QSize(50, 50))
|
||||
else:
|
||||
self.setIcon(QIcon())
|
||||
# TODO: remove
|
||||
if self.type is ButtonType.BOMB:
|
||||
self.setStyleSheet("background-color: red")
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.setGeometry(0, 0, 500, 500)
|
||||
self.seconds = 0
|
||||
self.revealed_buttons: set[Cords] = set()
|
||||
self.timer = QTimer()
|
||||
self.timer.timeout.connect(self.show_time)
|
||||
self.timer.setInterval(1000)
|
||||
self.timer.start()
|
||||
self.bomb_amount = 10
|
||||
self.flags_amount = 0
|
||||
self.setWindowTitle("Окно")
|
||||
self.create_buttons()
|
||||
self.select_bombs()
|
||||
|
||||
def create_buttons(self) -> None:
|
||||
vbox = QVBoxLayout()
|
||||
|
||||
hbox = QHBoxLayout()
|
||||
self.counter = QLabel(f"{self.flags_amount}/{self.bomb_amount}")
|
||||
finish_button = QPushButton()
|
||||
finish_button.setText("FINISH")
|
||||
finish_button.clicked.connect(self.finish)
|
||||
self.time = QLCDNumber()
|
||||
self.time.setDigitCount(5)
|
||||
self.time.display("00:00")
|
||||
hbox.addWidget(self.counter)
|
||||
hbox.addWidget(finish_button)
|
||||
hbox.addWidget(self.time)
|
||||
|
||||
vbox.addLayout(hbox)
|
||||
|
||||
self.buttons: list[list[Button]] = []
|
||||
for x in range(10):
|
||||
hbox = QHBoxLayout()
|
||||
row = []
|
||||
|
||||
for y in range(10):
|
||||
button = Button(
|
||||
Cords(x, y),
|
||||
self.button_clicked,
|
||||
self.set_flag,
|
||||
)
|
||||
row.append(button)
|
||||
hbox.addWidget(button)
|
||||
|
||||
self.buttons.append(row)
|
||||
vbox.addLayout(hbox)
|
||||
self.setLayout(vbox)
|
||||
|
||||
def select_bombs(self) -> None:
|
||||
buttons = [j for i in self.buttons for j in i]
|
||||
bombs = sample(buttons, self.bomb_amount)
|
||||
for bomb in bombs:
|
||||
bomb.type = ButtonType.BOMB
|
||||
# TODO: remove
|
||||
bomb.setStyleSheet("background-color: red")
|
||||
for bomb in bombs:
|
||||
for cords in bomb.get_neighbors():
|
||||
button = self.buttons[cords.x][cords.y]
|
||||
if button.type is ButtonType.BOMB:
|
||||
continue
|
||||
button.type = ButtonType.NUMBER
|
||||
button.number += 1
|
||||
|
||||
def button_clicked(self, button: Button, user: bool) -> None:
|
||||
if button.cords in self.revealed_buttons:
|
||||
return
|
||||
self.revealed_buttons.add(button.cords)
|
||||
if button.type is ButtonType.BOMB:
|
||||
if user:
|
||||
QMessageBox.warning(self, "You lost", "You lost")
|
||||
self.close()
|
||||
return
|
||||
button.reveal()
|
||||
if button.type is ButtonType.NUMBER:
|
||||
return
|
||||
for cords in button.get_neighbors():
|
||||
neighbor = self.buttons[cords.x][cords.y]
|
||||
self.button_clicked(neighbor, False)
|
||||
|
||||
def set_flag(self, button: Button) -> None:
|
||||
if button.revealed:
|
||||
return
|
||||
was_marked = button.marked
|
||||
button.marked = not was_marked
|
||||
button.update_texture()
|
||||
if was_marked:
|
||||
self.flags_amount -= 1
|
||||
else:
|
||||
self.flags_amount += 1
|
||||
self.counter.setText(f"{self.flags_amount}/{self.bomb_amount}")
|
||||
|
||||
def finish(self) -> None:
|
||||
buttons = [j for i in self.buttons for j in i]
|
||||
bomb = ButtonType.BOMB
|
||||
if not all(button.marked for button in buttons if button.type is bomb):
|
||||
QMessageBox.warning(self, "You lost", "You lost")
|
||||
self.close()
|
||||
return
|
||||
QMessageBox.information(self, "You won", "You won")
|
||||
self.close()
|
||||
|
||||
def show_time(self) -> None:
|
||||
self.seconds += 1
|
||||
minutes, seconds = divmod(self.seconds, 60)
|
||||
self.time.display(f"{minutes:0>2}:{seconds:0>2}")
|
||||
if minutes >= 5:
|
||||
QMessageBox.warning(self, "You lost", "You lost")
|
||||
self.close()
|
||||
return
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = QApplication(sys.argv)
|
||||
window = Window()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+419
@@ -0,0 +1,419 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
import psycopg2
|
||||
from psycopg2 import extensions
|
||||
from PyQt6.QtWidgets import (
|
||||
QApplication,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QTableWidget,
|
||||
QTableWidgetItem,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
|
||||
from cryptography.exceptions import InvalidKey
|
||||
|
||||
|
||||
def get_kdf(salt: bytes) -> Scrypt:
|
||||
return Scrypt(salt, length=128, n=2**14, r=8, p=1)
|
||||
|
||||
|
||||
def encrypt(password: str) -> bytes:
|
||||
salt = os.urandom(64)
|
||||
return (salt, get_kdf(salt).derive(password.encode("UTF-8")))
|
||||
|
||||
|
||||
def check_password(password: str, salt: bytes, expected: bytes) -> bool:
|
||||
try:
|
||||
get_kdf(salt).verify(password.encode("UTF-8"), expected)
|
||||
except InvalidKey:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
Student = tuple[int, str, str, str]
|
||||
|
||||
HOST = "127.0.0.1"
|
||||
USER = "tester"
|
||||
PASSWORD = "example123!"
|
||||
PORT = 5432
|
||||
DATABASE = "testing"
|
||||
|
||||
|
||||
class Connection:
|
||||
connection: Optional[extensions.connection] = None
|
||||
|
||||
@classmethod
|
||||
def get(cls) -> extensions.connection:
|
||||
if cls.connection is not None:
|
||||
return cls.connection
|
||||
try:
|
||||
cls.connection = psycopg2.connect(
|
||||
host=HOST, user=USER, password=PASSWORD, database=DATABASE
|
||||
)
|
||||
cls.connection.autocommit = True
|
||||
except Exception as e:
|
||||
print(type(e))
|
||||
raise
|
||||
return cls.connection
|
||||
|
||||
@classmethod
|
||||
def close(cls) -> None:
|
||||
if cls.connection is not None:
|
||||
cls.connection.close()
|
||||
cls.connection = None
|
||||
|
||||
@classmethod
|
||||
def get_all_data(cls) -> list[Student]:
|
||||
with cls.get().cursor() as cursor:
|
||||
cursor.execute("SELECT * FROM students ORDER BY id")
|
||||
return cursor.fetchall()
|
||||
|
||||
@classmethod
|
||||
def get_user(cls, login: str) -> Optional[tuple[bytes, bytes]]:
|
||||
with cls.get().cursor() as cursor:
|
||||
cursor.execute(
|
||||
"SELECT salt, password, admin FROM users WHERE login = %s",
|
||||
(login,),
|
||||
)
|
||||
result = cursor.fetchone()
|
||||
if result is None:
|
||||
return None
|
||||
return (bytes(result[0]), bytes(result[1]), result[2])
|
||||
|
||||
|
||||
def prepare_database() -> None:
|
||||
with Connection.get().cursor() as cursor:
|
||||
cursor.execute("DROP TABLE IF EXISTS students")
|
||||
cursor.execute(
|
||||
"CREATE TABLE students("
|
||||
"id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,"
|
||||
"surname VARCHAR(255),"
|
||||
"name VARCHAR(255),"
|
||||
"group_ VARCHAR(255))"
|
||||
)
|
||||
cursor.execute("DROP TABLE IF EXISTS users")
|
||||
cursor.execute(
|
||||
"CREATE TABLE users("
|
||||
"id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,"
|
||||
"login VARCHAR(255),"
|
||||
"salt BYTEA,"
|
||||
"password BYTEA,"
|
||||
"admin BOOLEAN)"
|
||||
)
|
||||
|
||||
|
||||
def add_test_data() -> None:
|
||||
with Connection.get().cursor() as cursor:
|
||||
cursor.execute(
|
||||
"INSERT INTO STUDENTS(name, surname, group_) VALUES "
|
||||
"('Nick', 'Stepanov', 'programmer'),"
|
||||
"('Maxim', 'Yes', 'programmer')"
|
||||
)
|
||||
admin_creds = encrypt("admin")
|
||||
user_creds = encrypt("example123!")
|
||||
cursor.execute(
|
||||
"INSERT INTO users(login, salt, password, admin) VALUES "
|
||||
"('admin', %s, %s, true),"
|
||||
"('user', %s, %s, false)",
|
||||
(*admin_creds, *user_creds),
|
||||
)
|
||||
|
||||
|
||||
class Window(QWidget):
|
||||
def __init__(self, is_admin: bool):
|
||||
super().__init__()
|
||||
self.is_admin = is_admin
|
||||
self.setGeometry(200, 200, 700, 400)
|
||||
self.setWindowTitle("SQL Test")
|
||||
self.vbox = QVBoxLayout()
|
||||
self.setLayout(self.vbox)
|
||||
self.need_clean = []
|
||||
self.update()
|
||||
|
||||
def update(self, data: Optional[list[Student]] = None):
|
||||
self.clean_widgets()
|
||||
|
||||
if data is None:
|
||||
data = Connection.get_all_data()
|
||||
|
||||
hbox_buttons = QHBoxLayout()
|
||||
but1 = QPushButton("Create")
|
||||
but1.clicked.connect(self.button_create_handler)
|
||||
but2 = QPushButton("Edit")
|
||||
but2.clicked.connect(self.button_edit_handler)
|
||||
but3 = QPushButton("Remove")
|
||||
but3.clicked.connect(self.button_remove_handler)
|
||||
but4 = QPushButton("Find")
|
||||
but4.clicked.connect(self.button_find_handler)
|
||||
hbox_buttons.addWidget(but1)
|
||||
hbox_buttons.addWidget(but2)
|
||||
hbox_buttons.addWidget(but3)
|
||||
hbox_buttons.addWidget(but4)
|
||||
self.add_widget_to_need_clean(but1, but2, but3, but4)
|
||||
|
||||
hbox_id = QHBoxLayout()
|
||||
label_id = QLabel("ID")
|
||||
self.text_id = QLineEdit()
|
||||
hbox_id.addWidget(label_id)
|
||||
hbox_id.addWidget(self.text_id)
|
||||
self.add_widget_to_need_clean(hbox_id, label_id, self.text_id)
|
||||
|
||||
hbox_surname = QHBoxLayout()
|
||||
label_surname = QLabel("Surname")
|
||||
self.text_surname = QLineEdit()
|
||||
hbox_surname.addWidget(label_surname)
|
||||
hbox_surname.addWidget(self.text_surname)
|
||||
self.add_widget_to_need_clean(
|
||||
hbox_surname,
|
||||
label_surname,
|
||||
self.text_surname,
|
||||
)
|
||||
|
||||
hbox_name = QHBoxLayout()
|
||||
label_name = QLabel("Name")
|
||||
self.text_name = QLineEdit()
|
||||
hbox_name.addWidget(label_name)
|
||||
hbox_name.addWidget(self.text_name)
|
||||
self.add_widget_to_need_clean(hbox_name, label_name, self.text_name)
|
||||
|
||||
hbox_group = QHBoxLayout()
|
||||
label_group = QLabel("Group")
|
||||
self.text_group = QLineEdit()
|
||||
hbox_group.addWidget(label_group)
|
||||
hbox_group.addWidget(self.text_group)
|
||||
self.add_widget_to_need_clean(hbox_group, label_group, self.text_group)
|
||||
|
||||
hbox_table = QHBoxLayout()
|
||||
table = self.form_table(data)
|
||||
hbox_table.addWidget(table)
|
||||
self.add_widget_to_need_clean(table)
|
||||
|
||||
self.vbox.addLayout(hbox_id)
|
||||
self.vbox.addLayout(hbox_surname)
|
||||
self.vbox.addLayout(hbox_name)
|
||||
self.vbox.addLayout(hbox_group)
|
||||
self.vbox.addLayout(hbox_buttons)
|
||||
self.vbox.addLayout(hbox_table)
|
||||
|
||||
def add_widget_to_need_clean(self, *args):
|
||||
for el in args:
|
||||
self.need_clean.append(el)
|
||||
|
||||
def clean_widgets(self):
|
||||
if self.need_clean:
|
||||
for widget in self.need_clean:
|
||||
widget.deleteLater()
|
||||
self.need_clean.clear()
|
||||
|
||||
@staticmethod
|
||||
def form_table(data: list[Student]) -> QTableWidget:
|
||||
table = QTableWidget()
|
||||
table.setRowCount(10)
|
||||
table.setColumnCount(4)
|
||||
table.setHorizontalHeaderLabels(("ID", "Surname", "Name", "Group"))
|
||||
for i, row in enumerate(data):
|
||||
for j, column in enumerate(map(str, row)):
|
||||
table.setItem(i, j, QTableWidgetItem(column))
|
||||
return table
|
||||
|
||||
def button_edit_handler(self):
|
||||
if not self.is_admin:
|
||||
return QMessageBox().warning(
|
||||
self, "Rights", "You have to be an admin to do that"
|
||||
)
|
||||
with Connection.get().cursor() as cursor:
|
||||
cursor.execute("SELECT * FROM students;")
|
||||
students = cursor.fetchall()
|
||||
indexes = []
|
||||
for student in students:
|
||||
indexes.append(str(student[0]))
|
||||
if self.text_id.text() in indexes:
|
||||
commands = []
|
||||
if self.text_surname.text() != "":
|
||||
commands.append(
|
||||
"UPDATE students SET surname = '"
|
||||
+ self.text_surname.text()
|
||||
+ "' "
|
||||
+ "WHERE id = "
|
||||
+ self.text_id.text()
|
||||
+ ";"
|
||||
)
|
||||
if self.text_name.text() != "":
|
||||
commands.append(
|
||||
"UPDATE students SET name = '"
|
||||
+ self.text_name.text()
|
||||
+ "' "
|
||||
+ "WHERE id = "
|
||||
+ self.text_id.text()
|
||||
+ ";"
|
||||
)
|
||||
if self.text_group.text() != "":
|
||||
commands.append(
|
||||
"UPDATE students SET gr = '"
|
||||
+ self.text_group.text()
|
||||
+ "' "
|
||||
+ "WHERE id = "
|
||||
+ self.text_id.text()
|
||||
+ ";"
|
||||
)
|
||||
with Connection.get().cursor() as cursor:
|
||||
for command in commands:
|
||||
cursor.execute(command)
|
||||
QMessageBox.information(self, "Info", "Data changed")
|
||||
else:
|
||||
QMessageBox.warning(self, "Error", "Data not changed")
|
||||
self.update()
|
||||
|
||||
def button_create_handler(self):
|
||||
if not self.is_admin:
|
||||
return QMessageBox().warning(
|
||||
self, "Rights", "You have to be an admin to do that"
|
||||
)
|
||||
name = self.text_name.text()
|
||||
surname = self.text_surname.text()
|
||||
group = self.text_group.text()
|
||||
if not all((surname, name, group)):
|
||||
QMessageBox.warning(self, "Invalid id", "Invalid id")
|
||||
return
|
||||
with Connection.get().cursor() as cursor:
|
||||
cursor.execute(
|
||||
"INSERT INTO students(name, surname, group_) VALUES (%s, %s, %s)", # noqa
|
||||
(name, surname, group),
|
||||
)
|
||||
self.update()
|
||||
|
||||
def button_remove_handler(self) -> None:
|
||||
if not self.is_admin:
|
||||
return QMessageBox().warning(
|
||||
self, "Rights", "You have to be an admin to do that"
|
||||
)
|
||||
try:
|
||||
id = int(self.text_id.text())
|
||||
except ValueError:
|
||||
QMessageBox.warning(self, "Invalid ID", "Invalid ID")
|
||||
return
|
||||
with Connection.get().cursor() as cursor:
|
||||
cursor.execute("DELETE FROM students WHERE id = %s", (id,))
|
||||
self.update()
|
||||
|
||||
def button_find_handler(self) -> None:
|
||||
id = self.text_id.text()
|
||||
name = self.text_name.text()
|
||||
surname = self.text_surname.text()
|
||||
group = self.text_group.text()
|
||||
filters = []
|
||||
params = []
|
||||
if id:
|
||||
if not id.isnumeric():
|
||||
QMessageBox.warning(self, "Invalid id", "Invalid id")
|
||||
return
|
||||
filters.append("id = %s")
|
||||
params.append(id)
|
||||
if name:
|
||||
filters.append("LOWER(name) ~ %s")
|
||||
params.append(name.lower())
|
||||
if surname:
|
||||
filters.append("LOWER(surname) ~ %s")
|
||||
params.append(surname.lower())
|
||||
if group:
|
||||
filters.append("LOWER(group_) ~ %s")
|
||||
params.append(group.lower())
|
||||
|
||||
with Connection.get().cursor() as cursor:
|
||||
if not params:
|
||||
filters = ""
|
||||
else:
|
||||
filters = f" WHERE {' AND '.join(filters)}"
|
||||
query = f"SELECT * FROM students{filters} ORDER BY id"
|
||||
cursor.execute(query, params)
|
||||
data = cursor.fetchall()
|
||||
self.update(data)
|
||||
|
||||
|
||||
class WindowPW(QWidget):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.loged_in = False
|
||||
self.is_admin = False
|
||||
self.setGeometry(200, 200, 250, 150)
|
||||
self.setWindowTitle("Login")
|
||||
label = QLabel("Name", self)
|
||||
label.move(10, 10)
|
||||
self.line_login = QLineEdit(self)
|
||||
self.line_login.move(100, 10)
|
||||
label_pw = QLabel("password", self)
|
||||
label_pw.move(10, 50)
|
||||
self.line_pw = QLineEdit(self)
|
||||
self.line_pw.move(100, 50)
|
||||
register_but = QPushButton("Register", self)
|
||||
register_but.move(25, 100)
|
||||
register_but.clicked.connect(self.register_handler)
|
||||
but = QPushButton("OK", self)
|
||||
but.clicked.connect(self.but_handler)
|
||||
but.move(100, 100)
|
||||
|
||||
def but_handler(self) -> None:
|
||||
login = self.line_login.text().strip()
|
||||
password = self.line_pw.text().strip()
|
||||
user = Connection.get_user(login)
|
||||
if user is None:
|
||||
self.close()
|
||||
return QMessageBox.warning(self, "Bye!", "Wrong creds")
|
||||
salt, expected, admin = Connection.get_user(login)
|
||||
if check_password(password, salt, expected):
|
||||
self.loged_in = True
|
||||
self.is_admin = admin
|
||||
else:
|
||||
QMessageBox.warning(self, "Bye!", "Wrong creds")
|
||||
self.close()
|
||||
|
||||
def register_handler(self) -> None:
|
||||
login = self.line_login.text().strip()
|
||||
password = self.line_pw.text().strip()
|
||||
if not (login and password):
|
||||
return QMessageBox().warning(
|
||||
self, "Wrong creds", "You must input both login and password"
|
||||
)
|
||||
with Connection.get().cursor() as cursor:
|
||||
cursor.execute(
|
||||
"SELECT true FROM users WHERE login = %s LIMIT 1",
|
||||
(login,),
|
||||
)
|
||||
if cursor.fetchone() is not None:
|
||||
return QMessageBox().warning(
|
||||
self, "Wrong creds", "Login already exists"
|
||||
)
|
||||
cursor.execute(
|
||||
"INSERT INTO users(login, salt, password) VALUES (%s, %s, %s)",
|
||||
(login, *encrypt(password)),
|
||||
)
|
||||
self.loged_in = True
|
||||
self.close()
|
||||
|
||||
|
||||
def main() -> None:
|
||||
prepare_database()
|
||||
add_test_data()
|
||||
app = QApplication(sys.argv)
|
||||
window = WindowPW()
|
||||
window.show()
|
||||
result = app.exec()
|
||||
if not window.loged_in:
|
||||
sys.exit(result)
|
||||
window = Window(window.is_admin)
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user