daily pastebin goal
63%
SHARE
TWEET

Untitled

a guest May 27th, 2018 109 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. {
  2.  "cells": [
  3.   {
  4.    "cell_type": "code",
  5.    "execution_count": 1,
  6.    "metadata": {},
  7.    "outputs": [],
  8.    "source": [
  9.     "from PyQt5 import QtCore, QtWidgets, QtGui\n",
  10.     "import sys, math, os, time, re, sqlite3, hashlib"
  11.    ]
  12.   },
  13.   {
  14.    "cell_type": "code",
  15.    "execution_count": 2,
  16.    "metadata": {},
  17.    "outputs": [],
  18.    "source": [
  19.     "class User:\n",
  20.     "    \n",
  21.     "    def __init__(self, db, login: str):\n",
  22.     "        self.db = db\n",
  23.     "        self.login = login\n",
  24.     "        self.password = hashlib.md5().hexdigest()\n",
  25.     "        self.upload()\n",
  26.     "    \n",
  27.     "    def setLogin(self, newLogin: str):\n",
  28.     "        self.login = newLogin\n",
  29.     "    \n",
  30.     "    def setPassword(self, newPassword: str):\n",
  31.     "        self.password = str(newPassword)\n",
  32.     "    \n",
  33.     "    def setAvatar(self, newAvatar: str) -> bool:\n",
  34.     "        try:\n",
  35.     "            self.avatarUrl = newAvatar\n",
  36.     "            pixAvatar = QtGui.QPixmap('Avatars/' + self.avatarUrl)\n",
  37.     "            self.avatar = QtGui.QIcon(pixAvatar)\n",
  38.     "            return True\n",
  39.     "        except:\n",
  40.     "            return False\n",
  41.     "    \n",
  42.     "    def registerUser(self) -> int:\n",
  43.     "        self.userId = self.db.registerUser(self)\n",
  44.     "        return self.userId\n",
  45.     "    \n",
  46.     "    def upload(self) -> bool:\n",
  47.     "        if self.db.userIsRegistered(self):\n",
  48.     "            try:\n",
  49.     "                self.db.cursor.execute(\"SELECT `user_id`, `user_password`, `user_avatar`, `user_progress` FROM `users` WHERE `user_login` = '{}'\".format(self.login))\n",
  50.     "                row = self.db.cursor.fetchone()\n",
  51.     "                self.userId = row[0]\n",
  52.     "                self.password = row[1]\n",
  53.     "                self.setAvatar(row[2])\n",
  54.     "                self.progress = row[3]\n",
  55.     "                return True\n",
  56.     "            finally:\n",
  57.     "                pass\n",
  58.     "        return False\n",
  59.     "    \n",
  60.     "    def deleteUser(self):\n",
  61.     "        self.db.deleteUser(self)\n",
  62.     "        self.__del__()"
  63.    ]
  64.   },
  65.   {
  66.    "cell_type": "code",
  67.    "execution_count": 3,
  68.    "metadata": {},
  69.    "outputs": [],
  70.    "source": [
  71.     "class Database():\n",
  72.     "    users = list()\n",
  73.     "    \n",
  74.     "    def __init__(self, statusBar: QtWidgets.QStatusBar, progressBar: QtWidgets.QProgressBar, enterWindow):\n",
  75.     "        self.statusBar = statusBar\n",
  76.     "        self.progressBar = progressBar\n",
  77.     "        self.enterWindow = enterWindow\n",
  78.     "        \n",
  79.     "        self.progressBar.setValue(0)\n",
  80.     "        self.statusBar.showMessage(\"Подключение к базе данных...\")\n",
  81.     "        self.connection = sqlite3.connect(\"nn.db\")\n",
  82.     "        self.cursor = self.connection.cursor()\n",
  83.     "        \n",
  84.     "        self.progressBar.setValue(self.progressBar.maximum() * (1 / 7))\n",
  85.     "\n",
  86.     "        self.statusBar.showMessage(\"Сканирование имеющихся таблиц...\")\n",
  87.     "        self.cursor.execute(\"SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'\")\n",
  88.     "        existingTables = tuple(map(lambda row: row[0], self.cursor.fetchall()))\n",
  89.     "        self.progressBar.setValue(self.progressBar.maximum() * (2 / 7))\n",
  90.     "        if \"users\" not in existingTables:\n",
  91.     "            self.statusBar.showMessage(\"Создание таблицы users...\")\n",
  92.     "            self.cursor.execute(\"CREATE TABLE `users` (\"\n",
  93.     "                                    \"`user_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\"\n",
  94.     "                                    \"`user_login` TEXT DEFAULT '' UNIQUE,\"\n",
  95.     "                                    \"`user_password` TEXT DEFAULT '\" + hashlib.md5().hexdigest() + \"',\"\n",
  96.     "                                    \"`user_avatar` TEXT DEFAULT '001-man-13.png',\"\n",
  97.     "                                    \"`user_progress` REAL DEFAULT 0.0\"\n",
  98.     "                                \")\")\n",
  99.     "            self.progressBar.setValue(self.progressBar.maximum() * (3 / 7))\n",
  100.     "        if \"saves\" not in existingTables:\n",
  101.     "            self.statusBar.showMessage(\"Создание таблицы saves...\")\n",
  102.     "            self.cursor.execute(\"CREATE TABLE `saves` (\"\n",
  103.     "                                    \"`user_id` INTEGER NOT NULL,\"\n",
  104.     "                                    \"`type` TEXT DEFAULT '',\"\n",
  105.     "                                    \"`data` TEXT DEFAULT '',\"\n",
  106.     "                                    \"`course_id` INTEGER NOT NULL,\"\n",
  107.     "                                    \"`exercise_id` INTEGER NULL,\"\n",
  108.     "                                    \"FOREIGN KEY (`user_id`) REFERENCES `users`(`user_id`) \"\n",
  109.     "                                        \"ON DELETE CASCADE \"\n",
  110.     "                                        \"ON UPDATE CASCADE\"\n",
  111.     "                                \")\")\n",
  112.     "            self.progressBar.setValue(self.progressBar.maximum() * (4 / 7))\n",
  113.     "        if \"courses\" not in existingTables:\n",
  114.     "            self.statusBar.showMessage(\"Создание таблицы courses...\")\n",
  115.     "            self.cursor.execute(\"CREATE TABLE `courses` (\"\n",
  116.     "                                    \"`course_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\"\n",
  117.     "                                    \"`face` TEXT DEFAULT 'book.png',\"\n",
  118.     "                                    \"`author` TEXT DEFAULT 'Пользователь',\"\n",
  119.     "                                    \"`title` TEXT DEFAULT '',\"\n",
  120.     "                                    \"`description` TEXT DEFAULT ''\"\n",
  121.     "                                \")\")\n",
  122.     "            self.progressBar.setValue(self.progressBar.maximum() * (5 / 7))\n",
  123.     "        if \"pages\" not in existingTables:\n",
  124.     "            self.statusBar.showMessage(\"Создание таблицы pages...\")\n",
  125.     "            self.cursor.execute(\"CREATE TABLE `pages` (\"\n",
  126.     "                                    \"`course_id` INTEGER NOT NULL,\"\n",
  127.     "                                    \"`page` INTEGER DEFAULT 1,\"\n",
  128.     "                                    \"`group` INTEGER NOT NULL,\"\n",
  129.     "                                    \"`title` TEXT DEFAULT '',\"\n",
  130.     "                                    \"`data` TEXT DEFAULT '',\"\n",
  131.     "                                    \"FOREIGN KEY (`course_id`) REFERENCES `courses`(`course_id`) \"\n",
  132.     "                                        \"ON DELETE CASCADE \"\n",
  133.     "                                        \"ON UPDATE CASCADE\"\n",
  134.     "                                \")\")\n",
  135.     "            self.progressBar.setValue(self.progressBar.maximum() * (6 / 7))\n",
  136.     "        if \"exercises\" not in existingTables:\n",
  137.     "            self.statusBar.showMessage(\"Создание таблицы exercises...\")\n",
  138.     "            self.cursor.execute(\"CREATE TABLE `exercises` (\"\n",
  139.     "                                    \"`exercise_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\"\n",
  140.     "                                    \"`course_id` INTEGER NOT NULL,\"\n",
  141.     "                                    \"`page` INTEGER NOT NULL,\"\n",
  142.     "                                    \"`group` INTEGER NOT NULL,\"\n",
  143.     "                                    \"`description` TEXT DEFAULT '',\"\n",
  144.     "                                    \"`type` TEXT DEFAULT '',\"\n",
  145.     "                                    \"`data` TEXT DEFAULT '',\"\n",
  146.     "                                    \"FOREIGN KEY (`course_id`) REFERENCES `courses`(`course_id`)\"\n",
  147.     "                                        \"ON DELETE CASCADE \"\n",
  148.     "                                        \"ON UPDATE CASCADE\"\n",
  149.     "                                \")\")\n",
  150.     "        self.progressBar.setValue(self.progressBar.maximum())\n",
  151.     "        self.uploadExistsUsers()\n",
  152.     "    \n",
  153.     "    def __del__(self):\n",
  154.     "        try:\n",
  155.     "            self.cursor.close()\n",
  156.     "            self.connection.close()\n",
  157.     "        except:\n",
  158.     "            pass\n",
  159.     "    \n",
  160.     "    def offerToEnter(self):\n",
  161.     "        self.enterWindow.show()\n",
  162.     "    \n",
  163.     "    def uploadExistsUsers(self):\n",
  164.     "        self.progressBar.setValue(0)\n",
  165.     "        self.statusBar.showMessage(\"Загрузка пользователей...\")\n",
  166.     "        self.cursor.execute(\"SELECT `user_login` FROM `users`\")\n",
  167.     "        rows = self.cursor.fetchall()\n",
  168.     "        l = len(rows)\n",
  169.     "        for i in range(l):\n",
  170.     "            foundedUser = User(self, rows[i][0])\n",
  171.     "            self.users.append(foundedUser)\n",
  172.     "            self.progressBar.setValue(self.progressBar.maximum() * (i + 1) / l)\n",
  173.     "        self.progressBar.setValue(self.progressBar.maximum())\n",
  174.     "    \n",
  175.     "    def userIsRegistered(self, user: User) -> bool:\n",
  176.     "        self.cursor.execute(\"SELECT `user_login` FROM `users`\")\n",
  177.     "        rows = self.cursor.fetchall()\n",
  178.     "        for row in rows:\n",
  179.     "            if row[0] == user.login:\n",
  180.     "                return True\n",
  181.     "        return False\n",
  182.     "    \n",
  183.     "    def registerUser(self, user: User) -> int:\n",
  184.     "        try:\n",
  185.     "            if not self.userIsRegistered(user):\n",
  186.     "                self.users.append(user)\n",
  187.     "                self.cursor.execute(\"INSERT INTO `users` (`user_login`, `user_password`, `user_avatar`) VALUES ('{}', '{}', '{}')\".format(user.login, user.password, user.avatarUrl))\n",
  188.     "            else:\n",
  189.     "                self.cursor.execute(\"UPDATE `users` SET `user_password` = '{}', `user_avatar` = '{}' WHERE `user_login` = '{}'\".format(user.password, user.avatarUrl, user.login))\n",
  190.     "            self.connection.commit()\n",
  191.     "            user.upload()\n",
  192.     "            return user.userId\n",
  193.     "        finally:\n",
  194.     "            return -1\n",
  195.     "    \n",
  196.     "    def deleteUser(self, user: User) -> bool:\n",
  197.     "        try:\n",
  198.     "            if self.userIsRegistered(user):\n",
  199.     "                self.users.remove(user)\n",
  200.     "                self.cursor.execute(\"DELETE FROM `users` WHERE `user_login` = '{}'\".format(user.login))\n",
  201.     "                self.connection.commit()\n",
  202.     "                return True\n",
  203.     "        finally:\n",
  204.     "            return False"
  205.    ]
  206.   },
  207.   {
  208.    "cell_type": "code",
  209.    "execution_count": 4,
  210.    "metadata": {},
  211.    "outputs": [],
  212.    "source": [
  213.     "loginRegExp = QtCore.QRegExp(r\"[a-zA-Zа-яА-Я\\_\\$][a-zA-Zа-яА-Я\\_\\$\\-0-9]*\")\n",
  214.     "currentUser = None\n",
  215.     "mainFrame = None"
  216.    ]
  217.   },
  218.   {
  219.    "cell_type": "code",
  220.    "execution_count": 5,
  221.    "metadata": {},
  222.    "outputs": [],
  223.    "source": [
  224.     "class StyledLabel(QtWidgets.QLabel):\n",
  225.     "    \n",
  226.     "    def __init__(self,  line: str=\"\", parent=None):\n",
  227.     "        super().__init__(line, parent)"
  228.    ]
  229.   },
  230.   {
  231.    "cell_type": "code",
  232.    "execution_count": 6,
  233.    "metadata": {},
  234.    "outputs": [],
  235.    "source": [
  236.     "class RegistrationWindow(QtWidgets.QWidget):\n",
  237.     "    \n",
  238.     "    def __init__(self, enterWindow):\n",
  239.     "        super().__init__()\n",
  240.     "        self.setWindowTitle(\"Регистрация\")\n",
  241.     "        self.enterWindow = enterWindow\n",
  242.     "        self.newLogin = enterWindow.loginEdit.text()\n",
  243.     "        \n",
  244.     "        self.vbox = QtWidgets.QVBoxLayout(self)\n",
  245.     "        self.hbox1 = QtWidgets.QHBoxLayout()\n",
  246.     "        self.hbox2 = QtWidgets.QHBoxLayout()\n",
  247.     "        self.hbox3 = QtWidgets.QHBoxLayout()\n",
  248.     "        self.buttonGo = QtWidgets.QPushButton(\"Зарегистрироваться\")\n",
  249.     "        self.buttonGo.clicked.connect(self.register)\n",
  250.     "        self.label1 = StyledLabel(\"Аватар:\")\n",
  251.     "        self.label1.setFixedWidth(96)\n",
  252.     "        self.label1.setAlignment(QtCore.Qt.AlignRight)\n",
  253.     "        self.label2 = StyledLabel(\"Логин:\")\n",
  254.     "        self.label2.setFixedWidth(96)\n",
  255.     "        self.label2.setAlignment(QtCore.Qt.AlignRight)\n",
  256.     "        self.label3 = StyledLabel(\"Пароль:\")\n",
  257.     "        self.label3.setFixedWidth(96)\n",
  258.     "        self.label3.setAlignment(QtCore.Qt.AlignRight)\n",
  259.     "        self.lineEdit = QtWidgets.QLineEdit()\n",
  260.     "        self.lineEdit.setValidator(QtGui.QRegExpValidator(loginRegExp))\n",
  261.     "        self.lineEdit.setMaxLength(50)\n",
  262.     "        self.avatarsBox = QtWidgets.QComboBox()\n",
  263.     "        self.avatarsBox.setIconSize(QtCore.QSize(48, 48))\n",
  264.     "        pixList = os.listdir(\"Avatars\")\n",
  265.     "        pixList.sort()\n",
  266.     "        for pixName in pixList:\n",
  267.     "            self.avatarsBox.addItem(QtGui.QIcon(\"Avatars/\" + pixName), pixName)\n",
  268.     "        self.pwdEdit = QtWidgets.QLineEdit()\n",
  269.     "        self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Password)\n",
  270.     "        self.pwdEdit.setMaxLength(32)\n",
  271.     "        self.buttonShowPassword = QtWidgets.QCheckBox()\n",
  272.     "        self.buttonShowPassword.stateChanged.connect(self.checked)\n",
  273.     "        \n",
  274.     "        self.hbox1.addWidget(self.label1)\n",
  275.     "        self.hbox1.addWidget(self.avatarsBox)\n",
  276.     "        self.hbox2.addWidget(self.label2)\n",
  277.     "        self.hbox2.addWidget(self.lineEdit)\n",
  278.     "        self.hbox3.addWidget(self.label3)\n",
  279.     "        self.hbox3.addWidget(self.pwdEdit)\n",
  280.     "        self.hbox3.addWidget(self.buttonShowPassword)\n",
  281.     "        self.vbox.addLayout(self.hbox1)\n",
  282.     "        self.vbox.addLayout(self.hbox2)\n",
  283.     "        self.vbox.addLayout(self.hbox3)\n",
  284.     "        self.vbox.addWidget(self.buttonGo)\n",
  285.     "\n",
  286.     "    def checked(self, newState):\n",
  287.     "        if newState == QtCore.Qt.Checked:\n",
  288.     "            self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Normal)\n",
  289.     "        else:\n",
  290.     "            self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Password)\n",
  291.     "\n",
  292.     "    def showEvent(self, event):\n",
  293.     "        global db\n",
  294.     "        db.statusBar.showMessage(\"Регистрация пользователя...\")\n",
  295.     "        self.desktop = QtWidgets.QApplication.desktop()\n",
  296.     "        x = (self.desktop.width() - self.width()) // 2\n",
  297.     "        y = (self.desktop.height() - self.height()) // 2\n",
  298.     "        self.move(x, y)\n",
  299.     "\n",
  300.     "    def register(self):\n",
  301.     "        global db\n",
  302.     "        newUser = User(db, self.lineEdit.text())\n",
  303.     "        newUser.setAvatar(self.avatarsBox.currentText())\n",
  304.     "        newUser.setPassword(hashlib.md5(self.pwdEdit.text().encode()).hexdigest())\n",
  305.     "        db.registerUser(newUser)\n",
  306.     "        self.hide()\n",
  307.     "        self.enterWindow.uploadUsers()\n",
  308.     "        self.enterWindow.show()"
  309.    ]
  310.   },
  311.   {
  312.    "cell_type": "code",
  313.    "execution_count": 7,
  314.    "metadata": {},
  315.    "outputs": [],
  316.    "source": [
  317.     "class UsersListItem(QtWidgets.QListWidgetItem):\n",
  318.     "\n",
  319.     "    def __init__(self, user: User, parent=None):\n",
  320.     "        super().__init__(parent)\n",
  321.     "        self.user = user\n",
  322.     "        self.setSizeHint(QtCore.QSize(0, 64))\n",
  323.     "\n",
  324.     "    def updateItem(self):\n",
  325.     "        self.user.upload()\n",
  326.     "        self.setIcon(self.user.avatar)\n",
  327.     "        self.setText(\"{0}\\nПрогресс: {1: >5.1f}%\\n{2:\\u25CB<10}\".format(self.user.login, int(self.user.progress * 10) / 10.0, \"\\u25CF\" * int(self.user.progress // 10)))\n",
  328.     "\n",
  329.     "    def updateUser(self, newUser: User):\n",
  330.     "        self.user = newUser\n",
  331.     "        self.updateItem()"
  332.    ]
  333.   },
  334.   {
  335.    "cell_type": "code",
  336.    "execution_count": 8,
  337.    "metadata": {},
  338.    "outputs": [],
  339.    "source": [
  340.     "class UsersList(QtWidgets.QListWidget):\n",
  341.     "    selectedItem = None\n",
  342.     "    autoSelect = False\n",
  343.     "\n",
  344.     "    def __init__(self, enterWindow=None):\n",
  345.     "        super().__init__(enterWindow)\n",
  346.     "        self.enterWindow = enterWindow\n",
  347.     "        self.setSortingEnabled(True)\n",
  348.     "        self.setAlternatingRowColors(True)\n",
  349.     "        self.setIconSize(QtCore.QSize(48, 48))\n",
  350.     "        self.itemSelectionChanged.connect(self.itemIsSelected)\n",
  351.     "        self.itemClicked.connect(self.itemIsClicked)\n",
  352.     "\n",
  353.     "    def updateList(self, enteredLogin: str=\"\"):\n",
  354.     "        global db\n",
  355.     "        self.clear()\n",
  356.     "        if enteredLogin == \"\":\n",
  357.     "            for user in db.users:\n",
  358.     "                item = UsersListItem(user)\n",
  359.     "                item.updateItem()\n",
  360.     "                self.addItem(item)\n",
  361.     "        else:\n",
  362.     "            enteredLogin = enteredLogin.lower()\n",
  363.     "            for user in db.users:\n",
  364.     "                if user.login.lower().find(enteredLogin) != -1:\n",
  365.     "                    item = UsersListItem(user)\n",
  366.     "                    item.updateItem()\n",
  367.     "                    self.addItem(item)\n",
  368.     "                    if user is db.users[0]:\n",
  369.     "                        self.autoSelect = True\n",
  370.     "                        item.setSelected(True)\n",
  371.     "                        self.autoSelect = False\n",
  372.     "    \n",
  373.     "    def itemIsSelected(self):\n",
  374.     "        if len(self.selectedItems()) > 0:\n",
  375.     "            self.selectedItem = self.selectedItems()[0]\n",
  376.     "            if not self.autoSelect:\n",
  377.     "                self.enterWindow.loginEdit.setText(self.selectedItem.user.login)\n",
  378.     "                self.enterWindow.loginEdit.setFocus(True)\n",
  379.     "    \n",
  380.     "    def itemIsClicked(self, clickedItem):\n",
  381.     "        if len(self.selectedItems()) > 0:\n",
  382.     "            self.selectedItem = self.selectedItems()[0]\n",
  383.     "            self.enterWindow.loginEdit.setText(self.selectedItem.user.login)\n",
  384.     "            self.enterWindow.loginEdit.setFocus(True)\n",
  385.     "    \n",
  386.     "    def deleteItem(self, item: UsersListItem):\n",
  387.     "        try:\n",
  388.     "            self.removeItemWidget(item)\n",
  389.     "            item.user.deleteUser()\n",
  390.     "        finally:\n",
  391.     "            return"
  392.    ]
  393.   },
  394.   {
  395.    "cell_type": "code",
  396.    "execution_count": 9,
  397.    "metadata": {},
  398.    "outputs": [],
  399.    "source": [
  400.     "class EnterWindow(QtWidgets.QWidget):\n",
  401.     "\n",
  402.     "    def __init__(self):\n",
  403.     "        super().__init__()\n",
  404.     "        self.setWindowTitle(\"Вход\")\n",
  405.     "\n",
  406.     "        self.vbox = QtWidgets.QVBoxLayout(self)\n",
  407.     "        self.loginEdit = QtWidgets.QLineEdit()\n",
  408.     "        self.loginEdit.setObjectName(\"loginEdit\")\n",
  409.     "        self.loginEdit.setPlaceholderText(\"Введите логин\")\n",
  410.     "        self.loginEdit.setValidator(QtGui.QRegExpValidator(loginRegExp))\n",
  411.     "        self.loginEdit.textChanged.connect(self.loginChanged)\n",
  412.     "        self.vbox.addWidget(self.loginEdit)\n",
  413.     "\n",
  414.     "        self.usersList = UsersList(self)\n",
  415.     "        self.vbox.addWidget(self.usersList)\n",
  416.     "        \n",
  417.     "        self.hbox = QtWidgets.QHBoxLayout()\n",
  418.     "        self.pwdEdit = QtWidgets.QLineEdit()\n",
  419.     "        self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Password)\n",
  420.     "        self.pwdEdit.setMaxLength(32)\n",
  421.     "        self.pwdEdit.setPlaceholderText(\"Введите пароль\")\n",
  422.     "        self.hbox.addWidget(self.pwdEdit)\n",
  423.     "        self.buttonShowPassword = QtWidgets.QCheckBox()\n",
  424.     "        self.buttonShowPassword.stateChanged.connect(self.checked)\n",
  425.     "        self.hbox.addWidget(self.buttonShowPassword)\n",
  426.     "        self.vbox.addLayout(self.hbox)\n",
  427.     "        \n",
  428.     "        self.buttonGo = QtWidgets.QPushButton(\"Войти\")\n",
  429.     "        self.buttonGo.clicked.connect(self.enterUser)\n",
  430.     "        self.vbox.addWidget(self.buttonGo)\n",
  431.     "        \n",
  432.     "        self.buttonNew = QtWidgets.QPushButton(\"Новый пользователь\")\n",
  433.     "        self.buttonNew.clicked.connect(self.createUser)\n",
  434.     "        self.vbox.addWidget(self.buttonNew)\n",
  435.     "        \n",
  436.     "        self.buttonDelete = QtWidgets.QPushButton(\"Удалить пользователя\")\n",
  437.     "        self.buttonDelete.clicked.connect(self.deleteUser)\n",
  438.     "        self.vbox.addWidget(self.buttonDelete)\n",
  439.     "    \n",
  440.     "    def checked(self, newState):\n",
  441.     "        if newState == QtCore.Qt.Checked:\n",
  442.     "            self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Normal)\n",
  443.     "        else:\n",
  444.     "            self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Password)\n",
  445.     "    \n",
  446.     "    def showEvent(self, event):\n",
  447.     "        global db\n",
  448.     "        db.statusBar.showMessage(\"Выбор пользователя...\")\n",
  449.     "        self.desktop = QtWidgets.QApplication.desktop()\n",
  450.     "        x = (self.desktop.width() - self.width()) // 2\n",
  451.     "        y = (self.desktop.height() - self.height()) // 2\n",
  452.     "        self.move(x, y)\n",
  453.     "    \n",
  454.     "    def uploadUsers(self):\n",
  455.     "        self.usersList.updateList()\n",
  456.     "    \n",
  457.     "    def loginChanged(self, enteredLogin):\n",
  458.     "        self.usersList.updateList(enteredLogin)\n",
  459.     "        if self.usersList.count() > 0 and len(enteredLogin) > 0:\n",
  460.     "            self.usersList.autoSelect = True\n",
  461.     "            self.usersList.item(0).setSelected(True)\n",
  462.     "            self.usersList.autoSelect = False\n",
  463.     "    \n",
  464.     "    def enterUser(self):\n",
  465.     "        if self.usersList.selectedItem is None:\n",
  466.     "            QtWidgets.QMessageBox.warning(self, \"Ошибка\", \"Выберите пользователя.\")\n",
  467.     "        else:\n",
  468.     "            pwd = hashlib.md5(self.pwdEdit.text().encode()).hexdigest()\n",
  469.     "            if pwd == self.usersList.selectedItem.user.password:\n",
  470.     "                global db, currentUser, mainFrame\n",
  471.     "                currentUser = self.usersList.selectedItem.user\n",
  472.     "                self.hide()\n",
  473.     "                mainFrame.menuBar.setEnabled(True)\n",
  474.     "                db.statusBar.showMessage(\"Добро пожаловать, {0:s}!\".format(currentUser.login))\n",
  475.     "                mainFrame.reloadChoiceList()\n",
  476.     "                mainFrame.reloadUser()\n",
  477.     "            else:\n",
  478.     "                QtWidgets.QMessageBox.warning(self, \"Ошибка\", \"Вы ввели неверный пароль пользователя.\")\n",
  479.     "    \n",
  480.     "    def closeEvent(self, event):\n",
  481.     "        global currentUser\n",
  482.     "        if currentUser is None:\n",
  483.     "            QtWidgets.QApplication.quit()\n",
  484.     "        else:\n",
  485.     "            event.accept()\n",
  486.     "    \n",
  487.     "    def createUser(self):\n",
  488.     "        self.hide()\n",
  489.     "        self.registrationWindow = RegistrationWindow(self)\n",
  490.     "        self.registrationWindow.show()\n",
  491.     "    \n",
  492.     "    def deleteUser(self):\n",
  493.     "        try:\n",
  494.     "            global db\n",
  495.     "            user = self.usersList.selectedItem.user\n",
  496.     "            if db.userIsRegistered(user):\n",
  497.     "                self.usersList.deleteItem(self.usersList.selectedItem)\n",
  498.     "                self.usersList.updateList()\n",
  499.     "                self.loginEdit.setText(\"\")\n",
  500.     "        finally:\n",
  501.     "            return"
  502.    ]
  503.   },
  504.   {
  505.    "cell_type": "code",
  506.    "execution_count": 10,
  507.    "metadata": {},
  508.    "outputs": [],
  509.    "source": [
  510.     "class ProgressBar(QtWidgets.QProgressBar):\n",
  511.     "    progressBarBrightText = False\n",
  512.     "    \n",
  513.     "    def __init__(self, parent=None):\n",
  514.     "        super().__init__(parent)\n",
  515.     "        self.valueChanged.connect(self.loadingUpdate)\n",
  516.     "    \n",
  517.     "    def loadingUpdate(self, value):\n",
  518.     "        self.setFormat(\"{0:d}%\".format(int(self.value() * 100 / self.maximum())))\n",
  519.     "        if value * 2 < self.maximum() + self.fontMetrics().width(self.format()) and self.progressBarBrightText:\n",
  520.     "            self.setStyleSheet(\"color: rgb(32, 32, 32);\")\n",
  521.     "            self.progressBarBrightText = False\n",
  522.     "        elif value * 2 >= self.maximum() + self.fontMetrics().width(self.format()) and not self.progressBarBrightText:\n",
  523.     "            self.setStyleSheet(\"color: white;\")\n",
  524.     "            self.progressBarBrightText = True"
  525.    ]
  526.   },
  527.   {
  528.    "cell_type": "code",
  529.    "execution_count": 11,
  530.    "metadata": {},
  531.    "outputs": [],
  532.    "source": [
  533.     "class ProgressBarF(QtWidgets.QProgressBar):\n",
  534.     "    progressBarBrightText = False\n",
  535.     "    \n",
  536.     "    def __init__(self, parent=None):\n",
  537.     "        super().__init__(parent)\n",
  538.     "        self.valueChanged.connect(self.loadingUpdate)\n",
  539.     "    \n",
  540.     "    def loadingUpdate(self, value):\n",
  541.     "        self.setFormat(\"{0:.2f}%\".format(self.value() * 100 / self.maximum()))\n",
  542.     "        if value * 2 < self.maximum() + self.fontMetrics().width(self.format()) and self.progressBarBrightText:\n",
  543.     "            self.setStyleSheet(\"color: rgb(32, 32, 32);\")\n",
  544.     "            self.progressBarBrightText = False\n",
  545.     "        elif value * 2 >= self.maximum() + self.fontMetrics().width(self.format()) and not self.progressBarBrightText:\n",
  546.     "            self.setStyleSheet(\"color: white;\")\n",
  547.     "            self.progressBarBrightText = True"
  548.    ]
  549.   },
  550.   {
  551.    "cell_type": "code",
  552.    "execution_count": 12,
  553.    "metadata": {},
  554.    "outputs": [],
  555.    "source": [
  556.     "class CourseLabel(QtWidgets.QLabel): \n",
  557.     "    mouse = 0  # leaveEvent ~ 0, enterEvent ~ 1, mousePressEvent ~ 2\n",
  558.     "    \n",
  559.     "    def __init__(self, course_id: int):\n",
  560.     "        super().__init__()\n",
  561.     "        global db\n",
  562.     "        db.cursor.execute('SELECT face, author, title, description FROM courses WHERE course_id = {}'.format(course_id))\n",
  563.     "        row = db.cursor.fetchone()\n",
  564.     "        self.course_id, self.face, self.author, self.title, self.description = course_id, *row\n",
  565.     "        self.pixmap = QtGui.QPixmap('Images/' + self.face).scaledToHeight(240)\n",
  566.     "        self.setFixedHeight(256)\n",
  567.     "    \n",
  568.     "    def paintEvent(self, event):\n",
  569.     "        painter = QtGui.QPainter(self)\n",
  570.     "        painter.setBackgroundMode(QtCore.Qt.TransparentMode)\n",
  571.     "        painter.setRenderHint(QtGui.QPainter.Antialiasing, True)\n",
  572.     "        if self.mouse == 0:\n",
  573.     "            painter.setOpacity(0.125 if self.course_id & 0x01 else 0.0625)\n",
  574.     "        elif self.mouse == 1:\n",
  575.     "            painter.setOpacity(0.1875)\n",
  576.     "        else:\n",
  577.     "            painter.setOpacity(0)\n",
  578.     "        painter.fillRect(0, 0, self.width() - 2, self.height() - 1, QtGui.QBrush(QtCore.Qt.white, QtCore.Qt.SolidPattern))\n",
  579.     "        painter.setOpacity(1.0)\n",
  580.     "        painter.drawPixmap(8, 8, self.pixmap.width(), self.pixmap.height(), self.pixmap)\n",
  581.     "        painter.setFont(QtGui.QFont('Monaco', 10, QtGui.QFont.Bold))\n",
  582.     "        painter.setPen(QtGui.QPen(QtCore.Qt.white, 1))\n",
  583.     "        painter.drawText(\n",
  584.     "            QtCore.QRect(self.pixmap.width() + 16, 8, self.width() - self.pixmap.width() - 24, 240),\n",
  585.     "            QtCore.Qt.AlignLeft | QtCore.Qt.TextWordWrap,\n",
  586.     "            'Автор: {}\\nНазвание: {}'.format(self.author, self.title)\n",
  587.     "        )\n",
  588.     "    \n",
  589.     "    def showEvent(self, event):\n",
  590.     "        self.update()\n",
  591.     "    \n",
  592.     "    def resizeEvent(self, event):\n",
  593.     "        self.update()\n",
  594.     "    \n",
  595.     "    def enterEvent(self, event):\n",
  596.     "        self.mouse = 1\n",
  597.     "        self.update()\n",
  598.     "        self.setCursor(QtCore.Qt.PointingHandCursor)\n",
  599.     "    \n",
  600.     "    def leaveEvent(self, event):\n",
  601.     "        self.mouse = 0\n",
  602.     "        self.update()\n",
  603.     "        self.setCursor(QtCore.Qt.ArrowCursor)\n",
  604.     "    \n",
  605.     "    def mousePressEvent(self, event):\n",
  606.     "        self.mouse = 2\n",
  607.     "        self.update()\n",
  608.     "        self.setCursor(QtCore.Qt.ArrowCursor)\n",
  609.     "        \"\"\"global mainFrame\n",
  610.     "        mainFrame.openCourse(self)\"\"\""
  611.    ]
  612.   },
  613.   {
  614.    "cell_type": "code",
  615.    "execution_count": 13,
  616.    "metadata": {},
  617.    "outputs": [
  618.     {
  619.      "data": {
  620.       "text/plain": [
  621.        "'def CourseFrame(QtWidgets.QLabel):\\n    \\n    pass'"
  622.       ]
  623.      },
  624.      "execution_count": 13,
  625.      "metadata": {},
  626.      "output_type": "execute_result"
  627.     }
  628.    ],
  629.    "source": [
  630.     "\"\"\"def CourseFrame(QtWidgets.QLabel):\n",
  631.     "    \n",
  632.     "    pass\"\"\""
  633.    ]
  634.   },
  635.   {
  636.    "cell_type": "code",
  637.    "execution_count": 14,
  638.    "metadata": {},
  639.    "outputs": [],
  640.    "source": [
  641.     "class MainArea(QtWidgets.QScrollArea):\n",
  642.     "    \n",
  643.     "    def __init__(self, mainFrame = None):\n",
  644.     "        super().__init__(mainFrame)\n",
  645.     "    \n",
  646.     "    def resizeEvent(self, event):\n",
  647.     "        self.mainPanel.setFixedWidth(self.width() - 16)\n",
  648.     "        if self.courses:\n",
  649.     "            for courseLabel in self.courses:\n",
  650.     "                courseLabel.setFixedWidth(self.width() - 18)"
  651.    ]
  652.   },
  653.   {
  654.    "cell_type": "code",
  655.    "execution_count": 15,
  656.    "metadata": {},
  657.    "outputs": [],
  658.    "source": [
  659.     "class MainFrame(QtWidgets.QWidget):\n",
  660.     "    \n",
  661.     "    def __init__(self, mainWindow=None):\n",
  662.     "        super().__init__(mainWindow)\n",
  663.     "        self.mainWindow = mainWindow\n",
  664.     "        global mainFrame\n",
  665.     "        mainFrame = self\n",
  666.     "\n",
  667.     "        self.vbox = QtWidgets.QVBoxLayout(self)\n",
  668.     "        self.vbox.setContentsMargins(0, 0, 0, 0)\n",
  669.     "        self.vbox.setSpacing(0)\n",
  670.     "\n",
  671.     "        # Нижняя строка состояния\n",
  672.     "        self.statusBar = QtWidgets.QStatusBar(self)\n",
  673.     "        self.statusBar.setObjectName(\"mainStatusBar\")\n",
  674.     "        self.statusBar.setFixedHeight(32)\n",
  675.     "        self.statusBar.setSizeGripEnabled(False)\n",
  676.     "        self.statusBar.setContentsMargins(0, 0, 3, 0)\n",
  677.     "\n",
  678.     "        # Индикатор хода прогресса\n",
  679.     "        self.progressBar = ProgressBar(self.statusBar)\n",
  680.     "        self.progressBar.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)\n",
  681.     "        self.progressBar.setFixedWidth(160)\n",
  682.     "        self.progressBar.setRange(0, 160)\n",
  683.     "        self.statusBar.addPermanentWidget(self.progressBar)\n",
  684.     "        \n",
  685.     "        self.userLabel = QtWidgets.QLabel()\n",
  686.     "        self.userLabel.setObjectName(\"userLabel\")\n",
  687.     "        self.userLabel.setFixedHeight(100)\n",
  688.     "        self.userLabel.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)\n",
  689.     "        self.userLabel.setContentsMargins(4, 8, 4, 4)\n",
  690.     "        self.choiceList = QtWidgets.QTreeWidget()\n",
  691.     "        self.choiceList.setObjectName(\"choiceList\")\n",
  692.     "        self.choiceList.setHeaderHidden(True)\n",
  693.     "        self.choiceList.setAnimated(True)\n",
  694.     "        header = self.choiceList.header()\n",
  695.     "        header.setStretchLastSection(False)\n",
  696.     "        header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)\n",
  697.     "        self.choiceList.setHeader(header)\n",
  698.     "        self.mainPanel = QtWidgets.QLabel()\n",
  699.     "        self.mainPanel.setObjectName('mainPanel')\n",
  700.     "        self.mainBox = QtWidgets.QVBoxLayout(self.mainPanel)\n",
  701.     "        self.mainBox.setContentsMargins(0, 0, 0, 0)\n",
  702.     "        self.mainBox.setSpacing(0)\n",
  703.     "        self.mainBox.setAlignment(QtCore.Qt.AlignHCenter)\n",
  704.     "        self.leftPanel = QtWidgets.QLabel()\n",
  705.     "        self.leftBox = QtWidgets.QVBoxLayout()\n",
  706.     "        self.leftBox.setContentsMargins(0, 0, 0, 0)\n",
  707.     "        self.leftBox.setSpacing(0)\n",
  708.     "        self.leftPanel.setLayout(self.leftBox)\n",
  709.     "        self.leftBox.addWidget(self.userLabel)\n",
  710.     "        self.leftBox.addWidget(self.choiceList)\n",
  711.     "        \n",
  712.     "        self.itemCourses = QtWidgets.QTreeWidgetItem(self.choiceList)\n",
  713.     "        self.itemCourses.setText(0, \"Курсы\")\n",
  714.     "        self.itemActiveCourses = QtWidgets.QTreeWidgetItem(self.itemCourses)\n",
  715.     "        self.itemActiveCourses.setText(0, \"Активные курсы\")\n",
  716.     "        self.itemNonactiveCourses = QtWidgets.QTreeWidgetItem(self.itemCourses)\n",
  717.     "        self.itemNonactiveCourses.setText(0, \"Закрытые курсы\")\n",
  718.     "        self.itemPrograms = QtWidgets.QTreeWidgetItem(self.choiceList)\n",
  719.     "        self.itemPrograms.setText(0, \"Python-программы\")\n",
  720.     "        \n",
  721.     "        # Режим пользователя\n",
  722.     "        self.splitter = QtWidgets.QSplitter()\n",
  723.     "        self.splitter.setOrientation(QtCore.Qt.Horizontal)\n",
  724.     "        self.splitter.addWidget(self.leftPanel)\n",
  725.     "        \n",
  726.     "        # Верхнее меню\n",
  727.     "        self.menuBar = QtWidgets.QMenuBar()\n",
  728.     "        self.menuBar.setFixedHeight(26)\n",
  729.     "        \n",
  730.     "        self.developerMenu = QtWidgets.QMenu(\"&Разработка\")\n",
  731.     "        self.developerMenu.setLayoutDirection(QtCore.Qt.LeftToRight)\n",
  732.     "        self.modeGroup = QtWidgets.QActionGroup(self.developerMenu)\n",
  733.     "        self.modeGroup.setExclusive(True)\n",
  734.     "        self.menuBar.addMenu(self.developerMenu)\n",
  735.     "        self.userMode = QtWidgets.QAction(\"Режим пользователя\", self.modeGroup)\n",
  736.     "        self.userMode.setCheckable(True)\n",
  737.     "        self.developerMode = QtWidgets.QAction(\"Режим разработчика\", self.modeGroup)\n",
  738.     "        self.developerMode.setCheckable(True)\n",
  739.     "        self.developerMenu.addAction(self.userMode)\n",
  740.     "        self.developerMenu.addAction(self.developerMode)\n",
  741.     "        self.userMode.setChecked(True)\n",
  742.     "        self.menuBar.setDisabled(True)\n",
  743.     "        self.modeGroup.triggered.connect(self.modeToggled)\n",
  744.     "        self.vbox.addWidget(self.menuBar)\n",
  745.     "        self.vbox.addWidget(self.splitter)\n",
  746.     "        self.vbox.addWidget(self.statusBar)\n",
  747.     "        \n",
  748.     "        # Режим разработчика\n",
  749.     "        self.developerWidget = QtWidgets.QWidget()\n",
  750.     "        self.developerLayout = QtWidgets.QVBoxLayout(self.developerWidget)\n",
  751.     "        self.developerLayout.setSpacing(0)\n",
  752.     "        self.developerLayout.setContentsMargins(0, 0, 0, 0)\n",
  753.     "        \n",
  754.     "        self.buttonsArea = QtWidgets.QScrollArea()\n",
  755.     "        self.buttonsArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)\n",
  756.     "        self.buttonsArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)\n",
  757.     "        self.buttonsLabel = QtWidgets.QLabel()\n",
  758.     "        self.buttonsArea.setWidget(self.buttonsLabel)\n",
  759.     "        self.buttonsBox = QtWidgets.QHBoxLayout(self.buttonsLabel)\n",
  760.     "        self.buttonsBox.setContentsMargins(2, 2, 2, 2)\n",
  761.     "        self.buttonsBox.setSpacing(2)\n",
  762.     "        self.buttonExec = QtWidgets.QPushButton(\"Выполнить запрос (F5)\")\n",
  763.     "        self.buttonExec.setShortcut(QtCore.Qt.Key_F5)\n",
  764.     "        self.buttonExec.setIcon(QtGui.QIcon(\"Images/exec.png\"))\n",
  765.     "        self.buttonExec.setFixedWidth(210)\n",
  766.     "        self.buttonExec.clicked.connect(self.execCommand)\n",
  767.     "        self.buttonsBox.addWidget(self.buttonExec)\n",
  768.     "        self.buttonCommit = QtWidgets.QPushButton(\"Совершить транзакцию (F6)\")\n",
  769.     "        self.buttonCommit.setShortcut(QtCore.Qt.Key_F6)\n",
  770.     "        self.buttonCommit.setIcon(QtGui.QIcon(\"Images/commit.png\"))\n",
  771.     "        self.buttonCommit.setFixedWidth(240)\n",
  772.     "        self.buttonCommit.clicked.connect(self.commitCommand)\n",
  773.     "        self.buttonsBox.addWidget(self.buttonCommit)\n",
  774.     "        self.buttonClear = QtWidgets.QPushButton(\"Очистить консоль (Ctrl+R)\")\n",
  775.     "        self.buttonClear.setShortcut(QtCore.Qt.ControlModifier | QtCore.Qt.Key_R)\n",
  776.     "        self.buttonClear.setIcon(QtGui.QIcon(\"Images/clear.png\"))\n",
  777.     "        self.buttonClear.setFixedWidth(230)\n",
  778.     "        self.buttonClear.clicked.connect(self.clearCommand)\n",
  779.     "        self.buttonsBox.addWidget(self.buttonClear)\n",
  780.     "        self.buttonSave = QtWidgets.QPushButton(\"Сохранить SQL (Ctrl+S)\")\n",
  781.     "        self.buttonSave.setShortcut(QtCore.Qt.ControlModifier | QtCore.Qt.Key_S)\n",
  782.     "        self.buttonSave.setIcon(QtGui.QIcon(\"Images/save.png\"))\n",
  783.     "        self.buttonSave.setFixedWidth(220)\n",
  784.     "        self.buttonSave.clicked.connect(self.saveCommand)\n",
  785.     "        self.buttonsBox.addWidget(self.buttonSave)\n",
  786.     "        self.buttonsArea.setFixedHeight(30)\n",
  787.     "        self.buttonsLabel.setFixedSize(QtCore.QSize(self.buttonExec.width() + self.buttonCommit.width() + self.buttonClear.width() + self.buttonSave.width() + 10, 28))\n",
  788.     "        self.developerLayout.addWidget(self.buttonsArea)\n",
  789.     "        \n",
  790.     "        self.devSplitter = QtWidgets.QSplitter()\n",
  791.     "        self.devSplitter.setOrientation(QtCore.Qt.Vertical)\n",
  792.     "        self.devSplitter.setHandleWidth(4)\n",
  793.     "        self.developerLayout.addWidget(self.devSplitter)\n",
  794.     "        \n",
  795.     "        self.developerTextEdit = QtWidgets.QTextEdit()\n",
  796.     "        self.developerTextEdit.setObjectName(\"developerTextEdit\")\n",
  797.     "        self.developerTextEdit.setWordWrapMode(False)\n",
  798.     "        self.devSplitter.addWidget(self.developerTextEdit)\n",
  799.     "        \n",
  800.     "        self.consoleTextEdit = QtWidgets.QTextEdit()\n",
  801.     "        self.consoleTextEdit.setObjectName(\"consoleTextEdit\")\n",
  802.     "        self.consoleTextEdit.setReadOnly(True)\n",
  803.     "        self.consoleTextEdit.setWordWrapMode(False)\n",
  804.     "        self.devSplitter.addWidget(self.consoleTextEdit)\n",
  805.     "    \n",
  806.     "    def showEvent(self, event):\n",
  807.     "        self.update()\n",
  808.     "    \n",
  809.     "    def loadDatabase(self):\n",
  810.     "        global db\n",
  811.     "        db = Database(self.statusBar, self.progressBar, self.enterWindow)\n",
  812.     "        \n",
  813.     "        # Главная панель\n",
  814.     "        self.mainArea = MainArea()\n",
  815.     "        self.mainArea.setObjectName(\"mainArea\")\n",
  816.     "        self.mainArea.mainBox = self.mainBox\n",
  817.     "        self.mainArea.mainPanel = self.mainPanel\n",
  818.     "        self.mainArea.courses = []\n",
  819.     "        self.mainArea.setWidget(self.mainPanel)\n",
  820.     "        db.cursor.execute('SELECT course_id FROM courses')\n",
  821.     "        self.course_ids = [row[0] for row in db.cursor.fetchall()]\n",
  822.     "        self.courses = []\n",
  823.     "        height = 0\n",
  824.     "        for course_id in self.course_ids:\n",
  825.     "            course = CourseLabel(course_id)\n",
  826.     "            self.courses.append(course)\n",
  827.     "            self.mainBox.addWidget(course)\n",
  828.     "            height += course.height()\n",
  829.     "        \n",
  830.     "        # Режим пользователя\n",
  831.     "        self.splitter.addWidget(self.mainArea)\n",
  832.     "        self.splitter.setSizes((320, self.mainArea.width()))\n",
  833.     "        self.mainPanel.setFixedWidth(self.mainArea.width() - 16)\n",
  834.     "        self.mainPanel.setFixedHeight(height)\n",
  835.     "        for course in self.courses:\n",
  836.     "            course.setFixedWidth(self.mainArea.width() - 18)\n",
  837.     "        self.splitter.setHandleWidth(4)\n",
  838.     "    \n",
  839.     "    \"\"\"def openCourse(self, courseLabel: CourseLabel):\n",
  840.     "        self.currentCourseLabel = courseLabel\n",
  841.     "        self.hideListOfCourses()\n",
  842.     "    \n",
  843.     "    def hideListOfCourses(self):\n",
  844.     "        self.opacity1 = QtWidgets.QGraphicsOpacityEffect()\n",
  845.     "        self.mainArea.setGraphicsEffect(self.opacity1)\n",
  846.     "        self.anim1 = QtCore.QPropertyAnimation(self.opacity1, b\"opacity\")\n",
  847.     "        self.anim1.setDuration(250)\n",
  848.     "        self.anim1.setStartValue(1.0)\n",
  849.     "        self.anim1.setEndValue(0.0)\n",
  850.     "        self.anim1.start()\n",
  851.     "        self.anim1.finished.connect(self.showCourse)\n",
  852.     "    \n",
  853.     "    def showCourse(self):\n",
  854.     "        self.mainArea.hide()\n",
  855.     "        self.opacity2 = QtWidgets.QGraphicsOpacityEffect()\n",
  856.     "        \n",
  857.     "        # Открываем выбранный курс\n",
  858.     "        self.courseFrame = \n",
  859.     "        \n",
  860.     "        self.mainFrame.setGraphicsEffect(self.opacity2)\n",
  861.     "        self.mainFrame.setWindowOpacity(0.0)\n",
  862.     "        self.mainFrame.show()\n",
  863.     "        self.anim2 = QtCore.QPropertyAnimation(self.opacity2, b\"opacity\")\n",
  864.     "        self.anim2.setDuration(250)\n",
  865.     "        self.anim2.setStartValue(0.0)\n",
  866.     "        self.anim2.setEndValue(1.0)\n",
  867.     "        self.anim2.start()\n",
  868.     "        self.anim2.finished.connect(self.mainFrameIsVisible)\"\"\"\n",
  869.     "    \n",
  870.     "    def offerToEnter(self):\n",
  871.     "        global db\n",
  872.     "        db.offerToEnter()\n",
  873.     "    \n",
  874.     "    def modeToggled(self, action: QtWidgets.QAction):\n",
  875.     "        if self.userMode.isChecked():\n",
  876.     "            self.statusBar.showMessage(\"Режим пользователя.\")\n",
  877.     "            self.vbox.replaceWidget(self.developerWidget, self.splitter)\n",
  878.     "            self.developerWidget.setVisible(False)\n",
  879.     "            self.reloadUser()\n",
  880.     "            self.reloadChoiceList()\n",
  881.     "            self.splitter.setVisible(True)\n",
  882.     "        if self.developerMode.isChecked():\n",
  883.     "            self.statusBar.showMessage(\"Режим разработчика.\")\n",
  884.     "            self.vbox.replaceWidget(self.splitter, self.developerWidget)\n",
  885.     "            self.splitter.setVisible(False)\n",
  886.     "            self.developerWidget.setVisible(True)\n",
  887.     "    \n",
  888.     "    def reloadUser(self):\n",
  889.     "        self.userLabel.setText('<img src=\"Avatars/{}\" width=\"64\" height=\"64\" align=\"left\" /><span style=\"color: khaki; font-weight: bold\">&nbsp;{}</span><br><br>&nbsp;Прогресс: {:.1f}'.format(currentUser.avatarUrl, currentUser.login, currentUser.progress))\n",
  890.     "    \n",
  891.     "    def reloadChoiceList(self):\n",
  892.     "        for child in self.itemActiveCourses.takeChildren():\n",
  893.     "            self.itemActiveCourses.removeChild(child)\n",
  894.     "        for child in self.itemNonactiveCourses.takeChildren():\n",
  895.     "            self.itemActiveCourses.removeChild(child)\n",
  896.     "        global currentUser\n",
  897.     "        if currentUser:\n",
  898.     "            global db\n",
  899.     "            db.cursor.execute('SELECT course_id, face, title, description FROM courses')\n",
  900.     "            rows = db.cursor.fetchall()\n",
  901.     "            db.cursor.execute(\"SELECT course_id FROM saves WHERE user_id = {} AND type = 'isActive' AND data = 'True'\".format(currentUser.userId))\n",
  902.     "            activeCourses = [r[0] for r in db.cursor.fetchall()]\n",
  903.     "            for row in rows:\n",
  904.     "                course_id, face, title, description = row\n",
  905.     "                newItem = QtWidgets.QTreeWidgetItem(self.itemActiveCourses if (course_id in activeCourses) else self.itemNonactiveCourses)\n",
  906.     "                newItem.setText(0, title)\n",
  907.     "    \n",
  908.     "    def execCommand(self, event):\n",
  909.     "        textCursor = QtGui.QTextCursor(self.developerTextEdit.textCursor())\n",
  910.     "        text = textCursor.selectedText()\n",
  911.     "        if text == \"\":\n",
  912.     "            text = self.developerTextEdit.toPlainText()\n",
  913.     "        \n",
  914.     "        self.statusBar.showMessage(\"Выполнение запроса...\")\n",
  915.     "        self.progressBar.setValue(0)\n",
  916.     "        self.consoleTextEdit.moveCursor(QtGui.QTextCursor.End)\n",
  917.     "        self.consoleTextEdit.insertHtml(\"<span style='font-weight: bold; color: lightgray;'>{0:s}</span><br>\".format(time.asctime()))\n",
  918.     "\n",
  919.     "        queries = [q.replace(\"\\\\n\", \"<br>\") for q in re.findall(r\"\\s*((?:(?:\\'[^\\']*?\\')|(?:\\\"[^\\\"]*?\\\")|[^\\\"\\';\\\\]|(?:\\\\(?:[^;]|\\s)))+)\\s*\\\\?;\", text.replace(\"\\\\\\n\", \"\").replace(\"\\n\", \" \"))]\n",
  920.     "        global db\n",
  921.     "        timeSum, timeBegin, timeEnd = 0, 0, 0\n",
  922.     "        db.progressBar.setValue(0)\n",
  923.     "        try:\n",
  924.     "            qlen = len(queries)\n",
  925.     "            for i in range(qlen):\n",
  926.     "                timeBegin = time.time()\n",
  927.     "                self.consoleTextEdit.setTextColor(QtGui.QColor('gold'))\n",
  928.     "                self.consoleTextEdit.insertPlainText(queries[i] + ';\\n')\n",
  929.     "                self.consoleTextEdit.setTextColor(QtGui.QColor('#336699'))\n",
  930.     "                db.cursor.execute(queries[i])\n",
  931.     "                timeEnd = time.time()\n",
  932.     "                self.consoleTextEdit.insertHtml(\"<span style='color: green;'>Запрос выполнен за {0:.3f} секунд.</span><br>\".format(timeEnd - timeBegin))\n",
  933.     "                timeSum += timeEnd - timeBegin\n",
  934.     "                db.progressBar.setValue(db.progressBar.maximum() * (i + 1) / qlen)\n",
  935.     "                rows = list(db.cursor.fetchall())\n",
  936.     "                desc = False\n",
  937.     "                if db.cursor.description:\n",
  938.     "                    rows.insert(0, [f[0] for f in db.cursor.description])\n",
  939.     "                    desc = True\n",
  940.     "                if rows:\n",
  941.     "                    rlen = len(rows)\n",
  942.     "                    wcount = len(rows[0])\n",
  943.     "                    wmaxlen = [0] * wcount\n",
  944.     "                    for x in range(wcount):\n",
  945.     "                        wlen = 0\n",
  946.     "                        for y in range(rlen):\n",
  947.     "                            wyxlen = len(str(rows[y][x]))\n",
  948.     "                            if wyxlen > wlen:\n",
  949.     "                                wlen = wyxlen\n",
  950.     "                        wmaxlen[x] = wlen\n",
  951.     "                    self.consoleTextEdit.insertPlainText(\"+\")\n",
  952.     "                    for x in range(wcount):\n",
  953.     "                        self.consoleTextEdit.insertPlainText(\"-\" * (wmaxlen[x] + 2) + (\"+\" if x < (wcount - 1) else \"+\\n\"))\n",
  954.     "                    if desc:\n",
  955.     "                        for x in range(wcount):\n",
  956.     "                            self.consoleTextEdit.insertPlainText(\"|\" + str(rows[0][x]).center(wmaxlen[x] + 2, \" \"))\n",
  957.     "                        self.consoleTextEdit.insertPlainText(\"|\\n+\")\n",
  958.     "                        for x in range(wcount):\n",
  959.     "                            self.consoleTextEdit.insertPlainText(\"-\" * (wmaxlen[x] + 2) + (\"+\" if x < (wcount - 1) else \"+\\n\"))\n",
  960.     "                    for y in range(1, rlen):\n",
  961.     "                        for x in range(wcount):\n",
  962.     "                            self.consoleTextEdit.insertPlainText(\"| \" + str(rows[y][x]).ljust(wmaxlen[x] + 1, \" \"))\n",
  963.     "                        self.consoleTextEdit.insertPlainText(\"|\\n\")\n",
  964.     "                    self.consoleTextEdit.insertPlainText(\"+\")\n",
  965.     "                    for x in range(wcount):\n",
  966.     "                        self.consoleTextEdit.insertPlainText(\"-\" * (wmaxlen[x] + 2) + (\"+\" if x < (wcount - 1) else \"+\\n\"))\n",
  967.     "                self.progressBar.setValue(self.progressBar.maximum() / qlen * (i + 1))\n",
  968.     "            self.statusBar.showMessage(\"Запросы выполнены за {0:.3f} секунд.\".format(timeSum))\n",
  969.     "            self.consoleTextEdit.insertHtml(\"<span style='color: green;'>Запросы выполнены за {0:.3f} секунд.</span><br><br>\".format(timeSum))\n",
  970.     "        except (sqlite3.Error, sqlite3.Warning) as e:\n",
  971.     "            self.statusBar.showMessage(\"Режим разработчика.\")\n",
  972.     "            self.consoleTextEdit.insertHtml(\"<span style='color: red;'>Ошибка: {}<br><br>\".format(e.args[0].replace(\"<\", \"<\").replace(\">\", \">\")))\n",
  973.     "        db.progressBar.setValue(db.progressBar.maximum())\n",
  974.     "        \n",
  975.     "        self.consoleTextEdit.moveCursor(QtGui.QTextCursor.End)\n",
  976.     "        self.progressBar.setValue(self.progressBar.maximum())\n",
  977.     "    \n",
  978.     "    def commitCommand(self, event):\n",
  979.     "        self.statusBar.showMessage(\"Выполнение транзакции...\")\n",
  980.     "        self.progressBar.setValue(0)\n",
  981.     "        self.consoleTextEdit.moveCursor(QtGui.QTextCursor.End)\n",
  982.     "        self.consoleTextEdit.insertHtml(\"<span style='font-weight: bold; color: lightgray;'>{0:s}</span><br>\".format(time.asctime()))\n",
  983.     "        \n",
  984.     "        global db\n",
  985.     "        timeDelta, timeBegin, timeEnd = 0, 0, 0\n",
  986.     "        db.progressBar.setValue(0)\n",
  987.     "        try:\n",
  988.     "            timeBegin = time.time()\n",
  989.     "            db.connection.commit()\n",
  990.     "            timeEnd = time.time()\n",
  991.     "            timeDelta = timeEnd - timeBegin\n",
  992.     "            \n",
  993.     "            self.statusBar.showMessage(\"Транзакция выполнена за {0:.3f} секунд.\".format(timeDelta))\n",
  994.     "            self.consoleTextEdit.insertHtml(\"<span style='color: green;'>Транзакция выполнена за {0:.3f} секунд.</span><br><br>\".format(timeDelta))\n",
  995.     "        except:\n",
  996.     "            self.statusBar.showMessage(\"Режим разработчика.\")\n",
  997.     "            self.consoleTextEdit.insertHtml(\"<span style='color: red;'>Ошибка: не удалось совершить транзакцию.</span><br><br>\")\n",
  998.     "        db.progressBar.setValue(db.progressBar.maximum())\n",
  999.     "        \n",
  1000.     "        self.consoleTextEdit.moveCursor(QtGui.QTextCursor.End)\n",
  1001.     "        self.progressBar.setValue(self.progressBar.maximum())\n",
  1002.     "    \n",
  1003.     "    def clearCommand(self):\n",
  1004.     "        self.consoleTextEdit.clear()\n",
  1005.     "        self.statusBar.showMessage(\"Консоль очищена...\")\n",
  1006.     "    \n",
  1007.     "    def saveCommand(self):\n",
  1008.     "        try:\n",
  1009.     "            path = QtWidgets.QFileDialog.getSaveFileName(\n",
  1010.     "                self,\n",
  1011.     "                caption=\"Сохранить SQL-код\",\n",
  1012.     "                directory=\"./\",\n",
  1013.     "                filter=\"SQL (*.sql);; TXT (*.txt);; Все файлы (*)\",\n",
  1014.     "                initialFilter= \"SQL (*.sql)\")[0]\n",
  1015.     "            file = open(path, \"w\")\n",
  1016.     "            file.write(self.developerTextEdit.toPlainText())\n",
  1017.     "            file.close()\n",
  1018.     "            pathConsole = re.search(r\"^(.+?)(?:\\.[^.]+)?$\", path).group(1) + \".txt\"\n",
  1019.     "            fileHtml = open(pathConsole, \"w\")\n",
  1020.     "            fileHtml.write(self.consoleTextEdit.toPlainText())\n",
  1021.     "            fileHtml.close()\n",
  1022.     "            self.statusBar.showMessage(\"SQL-код сохранён в файле \\\"{0:s}\\\", а данные консоли - в файле \\\"{1:s}\\\".\".format(path, pathConsole))\n",
  1023.     "        except:\n",
  1024.     "            self.statusBar.showMessage(\"Произошла ошибка при сохранении SQL-кода и данных консоли.\")"
  1025.    ]
  1026.   },
  1027.   {
  1028.    "cell_type": "code",
  1029.    "execution_count": 16,
  1030.    "metadata": {},
  1031.    "outputs": [],
  1032.    "source": [
  1033.     "class GoLink(QtWidgets.QLabel):\n",
  1034.     "\n",
  1035.     "    def __init__(self, text: str=\"\", presentationWindow=None, mainFrame=None):\n",
  1036.     "        super().__init__(presentationWindow)\n",
  1037.     "        self.presentationWindow = presentationWindow\n",
  1038.     "        self.mainFrame = mainFrame\n",
  1039.     "\n",
  1040.     "        self.setAlignment(QtCore.Qt.AlignCenter)\n",
  1041.     "        self.setText(text)\n",
  1042.     "\n",
  1043.     "    def enterEvent(self, event):\n",
  1044.     "        self.setCursor(QtCore.Qt.PointingHandCursor)\n",
  1045.     "\n",
  1046.     "    def mousePressEvent(self, event):\n",
  1047.     "        self.opacity1 = QtWidgets.QGraphicsOpacityEffect()\n",
  1048.     "        self.presentationWindow.setGraphicsEffect(self.opacity1)\n",
  1049.     "        self.anim1 = QtCore.QPropertyAnimation(self.opacity1, b\"opacity\")\n",
  1050.     "        self.anim1.setDuration(250)\n",
  1051.     "        self.anim1.setStartValue(1.0)\n",
  1052.     "        self.anim1.setEndValue(0.0)\n",
  1053.     "        self.anim1.start()\n",
  1054.     "        self.anim1.finished.connect(self.presentationWindowIsInvisible)\n",
  1055.     "    \n",
  1056.     "    def presentationWindowIsInvisible(self):\n",
  1057.     "        self.presentationWindow.hide()\n",
  1058.     "        self.opacity2 = QtWidgets.QGraphicsOpacityEffect()\n",
  1059.     "        self.mainFrame.setGraphicsEffect(self.opacity2)\n",
  1060.     "        self.mainFrame.setWindowOpacity(0.0)\n",
  1061.     "        self.mainFrame.show()\n",
  1062.     "        self.anim2 = QtCore.QPropertyAnimation(self.opacity2, b\"opacity\")\n",
  1063.     "        self.anim2.setDuration(250)\n",
  1064.     "        self.anim2.setStartValue(0.0)\n",
  1065.     "        self.anim2.setEndValue(1.0)\n",
  1066.     "        self.anim2.start()\n",
  1067.     "        self.anim2.finished.connect(self.mainFrameIsVisible)\n",
  1068.     "        \n",
  1069.     "    def mainFrameIsVisible(self):\n",
  1070.     "        self.mainFrame.enterWindow = EnterWindow()\n",
  1071.     "        self.mainFrame.loadDatabase()\n",
  1072.     "        self.mainFrame.enterWindow.uploadUsers()\n",
  1073.     "        self.mainFrame.offerToEnter()"
  1074.    ]
  1075.   },
  1076.   {
  1077.    "cell_type": "code",
  1078.    "execution_count": 17,
  1079.    "metadata": {},
  1080.    "outputs": [],
  1081.    "source": [
  1082.     "class PresentationWindow(QtWidgets.QLabel):\n",
  1083.     "    slideWidth = 1138  # Ширина одного слайда\n",
  1084.     "    slideHeight = 500  # Высота одного слайда\n",
  1085.     "    slidesCount = 3  # Количество слайдов\n",
  1086.     "    movingTime = 750  # Скорость прокрутки слайдов в миллисекундах\n",
  1087.     "\n",
  1088.     "    def __init__(self, mainWindow=None, mainFrame=None):\n",
  1089.     "        super().__init__(mainWindow)  # Экземпляр класса PresentationWindow будет дочерним относительно родителя mainWindow\n",
  1090.     "        self.mainFrame = mainFrame\n",
  1091.     "\n",
  1092.     "        self.setFixedSize(1200, 640)  # Задаем фиксированный размер для презентации\n",
  1093.     "        self.setAlignment(QtCore.Qt.AlignCenter)  # Устанавливаем его в центр окна\n",
  1094.     "\n",
  1095.     "        self.content = QtWidgets.QVBoxLayout(self)  # Задаем вертикальный макет для содержания презентации\n",
  1096.     "        self.scrollArea = QtWidgets.QScrollArea()  # Область с прокруткой для перелистывания слайдов\n",
  1097.     "        self.slides = [QtWidgets.QLabel() for i in range(self.slidesCount)]  # Сами слайды (имеют тип QLabel)\n",
  1098.     "        self.slidesPacket = QtWidgets.QLabel()\n",
  1099.     "        self.slidesLayout = QtWidgets.QHBoxLayout(self.slidesPacket)  # Горизонтальный макет для слайдов\n",
  1100.     "        self.buttonHBox = QtWidgets.QHBoxLayout()  # Горизонтальный макет для radio-кнопок\n",
  1101.     "\n",
  1102.     "        for i in range(self.slidesCount):\n",
  1103.     "            # Позволим пользователю выделять текст:\n",
  1104.     "            slide = self.slides[i]\n",
  1105.     "            # Пишем текст в i-ый слайд:\n",
  1106.     "            if i == 0:\n",
  1107.     "                slide.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse | QtCore.Qt.TextSelectableByKeyboard)\n",
  1108.     "                slide.setText(\"<img src='Images/icon.png' /><br><br>Добро пожаловать в программу <b>NeuralNetworks</b>, которая<br>научит вас программировать искусственные нейросети на языке Python!\")\n",
  1109.     "            elif i == 1:\n",
  1110.     "                slide.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse | QtCore.Qt.TextSelectableByKeyboard)\n",
  1111.     "                slide.setText(\"<b>NeuralNetworks</b> содержит в себе видео-уроки, теорию, тесты<br>и интерпретатор языка программирования <b>Python</b> для написания собственных программ!<br>Результаты заданий буду сохраняться в одну локальную базу данных формата <b>SQLite</b>, которая будет<br>хранить в себе <b>весь прогресс</b> и <b>весь код ваших программ</b>.\")\n",
  1112.     "            else:\n",
  1113.     "                self.goBox = QtWidgets.QVBoxLayout(slide)\n",
  1114.     "                self.goLink = GoLink(\"<b>Давайте приступим...</b>\", self, self.mainFrame)\n",
  1115.     "                self.goBox.addStretch(1)\n",
  1116.     "                self.goBox.addWidget(self.goLink)\n",
  1117.     "                self.goBox.addStretch(1)\n",
  1118.     "            slide.setAlignment(QtCore.Qt.AlignCenter)  # Устанавливаем текст слайда по центру\n",
  1119.     "            slide.setFixedWidth(self.slideWidth)  # Задаем ширину для слайда\n",
  1120.     "            slide.setObjectName(\"slide\")\n",
  1121.     "            self.slidesLayout.addWidget(slide)  # Добавляем данный слайд в макет\n",
  1122.     "        # Устанавливаем размер пакета со всеми слайдами:\n",
  1123.     "        self.slidesPacket.setFixedSize(self.slideWidth * self.slidesCount, self.slideHeight)\n",
  1124.     "        self.slidesPacket.setObjectName(\"slidesPacket\")\n",
  1125.     "\n",
  1126.     "        self.scrollArea.setObjectName(\"slides\")\n",
  1127.     "        self.scrollArea.setWidget(self.slidesPacket)  # Задаем виджет (QLabel)slidesPacket для области прокрутки\n",
  1128.     "        self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)  # Скрываем полосу прокрутки\n",
  1129.     "        self.scrollArea.horizontalScrollBar().valueChanged.connect(self.scrollAreaWheelEvent)\n",
  1130.     "\n",
  1131.     "        self.buttonHBox.addStretch(1)  # Мы добавим отступы в начале и в конце для кнопок, чтобы они были по середине\n",
  1132.     "        self.buttons = [QtWidgets.QRadioButton(self) for i in range(self.slidesCount)]\n",
  1133.     "        self.buttons[0].setChecked(True)  # Первый слайд будет виден сначала\n",
  1134.     "        for button in self.buttons:\n",
  1135.     "            button.clicked.connect(self.slideToggle)\n",
  1136.     "            self.buttonHBox.addWidget(button)\n",
  1137.     "        self.buttonHBox.addStretch(1)\n",
  1138.     "\n",
  1139.     "        # Заполняем содержимое:\n",
  1140.     "        self.content.addWidget(self.scrollArea)\n",
  1141.     "        self.content.addLayout(self.buttonHBox)\n",
  1142.     "\n",
  1143.     "    def slideToggle(self, isChecked):\n",
  1144.     "        if isChecked:\n",
  1145.     "            # Анимируем горизонтальную прокрутку:\n",
  1146.     "            self.anim = QtCore.QPropertyAnimation(self.scrollArea.horizontalScrollBar(), b\"value\")\n",
  1147.     "            self.anim.setDuration(self.movingTime)\n",
  1148.     "            self.anim.setEasingCurve(QtCore.QEasingCurve.InOutExpo)\n",
  1149.     "            i = 0\n",
  1150.     "            for i in range(self.slidesCount):\n",
  1151.     "                if self.buttons[i].isChecked():\n",
  1152.     "                    break\n",
  1153.     "            self.anim.setEndValue(self.scrollArea.horizontalScrollBar().pageStep() * i)\n",
  1154.     "            self.anim.start()\n",
  1155.     "\n",
  1156.     "    def scrollAreaWheelEvent(self, value):\n",
  1157.     "        k = value / (self.scrollArea.horizontalScrollBar().pageStep() * self.slidesCount)\n",
  1158.     "        i = 0\n",
  1159.     "        for i in range(self.slidesCount):\n",
  1160.     "            if self.buttons[i].isChecked():\n",
  1161.     "                break\n",
  1162.     "        j = int(math.ceil(k * self.slidesCount - 0.5))\n",
  1163.     "        if j != i:\n",
  1164.     "            self.buttons[j].setChecked(True)"
  1165.    ]
  1166.   },
  1167.   {
  1168.    "cell_type": "code",
  1169.    "execution_count": 18,
  1170.    "metadata": {},
  1171.    "outputs": [],
  1172.    "source": [
  1173.     "class MainWindow(QtWidgets.QWidget):\n",
  1174.     "    sourceSize = QtCore.QSize(1280, 768)\n",
  1175.     "\n",
  1176.     "    def __init__(self):\n",
  1177.     "        super().__init__()\n",
  1178.     "\n",
  1179.     "        # Создаем произвольное окно с задним фоном:\n",
  1180.     "        self.setWindowTitle(\"NeuralNetworks\")\n",
  1181.     "        self.icon = QtGui.QIcon(\"Images/icon.png\")\n",
  1182.     "        self.setWindowIcon(self.icon)\n",
  1183.     "        self.resize(self.sourceSize)\n",
  1184.     "        # Центруем окно по экрану:\n",
  1185.     "        self.desktop = QtWidgets.QApplication.desktop()\n",
  1186.     "        x = (self.desktop.width() - self.width()) // 2\n",
  1187.     "        y = (self.desktop.height() - self.height()) // 2\n",
  1188.     "        self.move(x, y)\n",
  1189.     "\n",
  1190.     "        self.hbox = QtWidgets.QHBoxLayout(self)\n",
  1191.     "        self.hbox.setContentsMargins(0, 0, 0, 0)\n",
  1192.     "        self.mainFrame = MainFrame(self)\n",
  1193.     "        self.mainFrame.resize(self.sourceSize)\n",
  1194.     "        self.mainFrame.hide()\n",
  1195.     "        self.hbox.addWidget(self.mainFrame)\n",
  1196.     "\n",
  1197.     "        self.presentationWindow = PresentationWindow(self, self.mainFrame)\n",
  1198.     "        self.hbox.addWidget(self.presentationWindow)\n",
  1199.     "\n",
  1200.     "        self.keyEsc = QtWidgets.QShortcut(QtCore.Qt.Key_Escape, self)\n",
  1201.     "        self.keyEsc.activated.connect(self.pressedKeyEsc)\n",
  1202.     "\n",
  1203.     "        self.keyF11 = QtWidgets.QShortcut(QtCore.Qt.Key_F11, self)\n",
  1204.     "        self.keyF11.activated.connect(self.pressedKeyF11)\n",
  1205.     "\n",
  1206.     "    def resizeEvent(self, event):\n",
  1207.     "        self.mainFrame.resize(self.size())\n",
  1208.     "\n",
  1209.     "    def paintEvent(self, event):\n",
  1210.     "        painter = QtGui.QPainter(self)\n",
  1211.     "        painter.drawPixmap(0, 0, self.width(), self.height(), QtGui.QPixmap(\"Images/background.jpg\"))\n",
  1212.     "\n",
  1213.     "    def closeEvent(self, event):\n",
  1214.     "        if currentUser is not None:\n",
  1215.     "            msgBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Question,\n",
  1216.     "                \"Закрыть программу\",\n",
  1217.     "                \"Вы действительно хотите выйти из программы? Все данные будут сохранены.\",\n",
  1218.     "                QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)\n",
  1219.     "            msgBox.setDefaultButton(QtWidgets.QMessageBox.No)\n",
  1220.     "            if msgBox.exec() == QtWidgets.QMessageBox.Yes:\n",
  1221.     "                QtWidgets.QApplication.closeAllWindows()\n",
  1222.     "                event.accept()\n",
  1223.     "            else:\n",
  1224.     "                event.ignore()\n",
  1225.     "        else:\n",
  1226.     "            QtWidgets.QApplication.quit()\n",
  1227.     "\n",
  1228.     "    def pressedKeyEsc(self):\n",
  1229.     "        self.close()\n",
  1230.     "\n",
  1231.     "    def pressedKeyF11(self):\n",
  1232.     "        if self.isFullScreen():\n",
  1233.     "            self.showNormal()\n",
  1234.     "        else:\n",
  1235.     "            self.showFullScreen()"
  1236.    ]
  1237.   },
  1238.   {
  1239.    "cell_type": "code",
  1240.    "execution_count": null,
  1241.    "metadata": {},
  1242.    "outputs": [],
  1243.    "source": [
  1244.     "app = QtWidgets.QApplication(sys.argv)\n",
  1245.     "\n",
  1246.     "qss = open(\"stylesheet.css\")\n",
  1247.     "app.setStyleSheet(qss.read())\n",
  1248.     "qss.close()\n",
  1249.     "\n",
  1250.     "mainWindow = MainWindow()\n",
  1251.     "mainWindow.show()\n",
  1252.     "\n",
  1253.     "code = app.exec_()\n",
  1254.     "sys.exit(code)"
  1255.    ]
  1256.   },
  1257.   {
  1258.    "cell_type": "code",
  1259.    "execution_count": null,
  1260.    "metadata": {},
  1261.    "outputs": [],
  1262.    "source": []
  1263.   }
  1264.  ],
  1265.  "metadata": {
  1266.   "kernelspec": {
  1267.    "display_name": "Python 3",
  1268.    "language": "python",
  1269.    "name": "python3"
  1270.   },
  1271.   "language_info": {
  1272.    "codemirror_mode": {
  1273.     "name": "ipython",
  1274.     "version": 3
  1275.    },
  1276.    "file_extension": ".py",
  1277.    "mimetype": "text/x-python",
  1278.    "name": "python",
  1279.    "nbconvert_exporter": "python",
  1280.    "pygments_lexer": "ipython3",
  1281.    "version": "3.6.4"
  1282.   }
  1283.  },
  1284.  "nbformat": 4,
  1285.  "nbformat_minor": 2
  1286. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top