Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- {
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "from PyQt5 import QtCore, QtWidgets, QtGui\n",
- "import sys, math, os, time, re, sqlite3, hashlib"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [],
- "source": [
- "class User:\n",
- " \n",
- " def __init__(self, db, login: str):\n",
- " self.db = db\n",
- " self.login = login\n",
- " self.password = hashlib.md5().hexdigest()\n",
- " self.upload()\n",
- " \n",
- " def setLogin(self, newLogin: str):\n",
- " self.login = newLogin\n",
- " \n",
- " def setPassword(self, newPassword: str):\n",
- " self.password = str(newPassword)\n",
- " \n",
- " def setAvatar(self, newAvatar: str) -> bool:\n",
- " try:\n",
- " self.avatarUrl = newAvatar\n",
- " pixAvatar = QtGui.QPixmap('Avatars/' + self.avatarUrl)\n",
- " self.avatar = QtGui.QIcon(pixAvatar)\n",
- " return True\n",
- " except:\n",
- " return False\n",
- " \n",
- " def registerUser(self) -> int:\n",
- " self.userId = self.db.registerUser(self)\n",
- " return self.userId\n",
- " \n",
- " def upload(self) -> bool:\n",
- " if self.db.userIsRegistered(self):\n",
- " try:\n",
- " self.db.cursor.execute(\"SELECT `user_id`, `user_password`, `user_avatar`, `user_progress` FROM `users` WHERE `user_login` = '{}'\".format(self.login))\n",
- " row = self.db.cursor.fetchone()\n",
- " self.userId = row[0]\n",
- " self.password = row[1]\n",
- " self.setAvatar(row[2])\n",
- " self.progress = row[3]\n",
- " return True\n",
- " finally:\n",
- " pass\n",
- " return False\n",
- " \n",
- " def deleteUser(self):\n",
- " self.db.deleteUser(self)\n",
- " self.__del__()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [],
- "source": [
- "class Database():\n",
- " users = list()\n",
- " \n",
- " def __init__(self, statusBar: QtWidgets.QStatusBar, progressBar: QtWidgets.QProgressBar, enterWindow):\n",
- " self.statusBar = statusBar\n",
- " self.progressBar = progressBar\n",
- " self.enterWindow = enterWindow\n",
- " \n",
- " self.progressBar.setValue(0)\n",
- " self.statusBar.showMessage(\"Подключение к базе данных...\")\n",
- " self.connection = sqlite3.connect(\"nn.db\")\n",
- " self.cursor = self.connection.cursor()\n",
- " \n",
- " self.progressBar.setValue(self.progressBar.maximum() * (1 / 7))\n",
- "\n",
- " self.statusBar.showMessage(\"Сканирование имеющихся таблиц...\")\n",
- " self.cursor.execute(\"SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'\")\n",
- " existingTables = tuple(map(lambda row: row[0], self.cursor.fetchall()))\n",
- " self.progressBar.setValue(self.progressBar.maximum() * (2 / 7))\n",
- " if \"users\" not in existingTables:\n",
- " self.statusBar.showMessage(\"Создание таблицы users...\")\n",
- " self.cursor.execute(\"CREATE TABLE `users` (\"\n",
- " \"`user_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\"\n",
- " \"`user_login` TEXT DEFAULT '' UNIQUE,\"\n",
- " \"`user_password` TEXT DEFAULT '\" + hashlib.md5().hexdigest() + \"',\"\n",
- " \"`user_avatar` TEXT DEFAULT '001-man-13.png',\"\n",
- " \"`user_progress` REAL DEFAULT 0.0\"\n",
- " \")\")\n",
- " self.progressBar.setValue(self.progressBar.maximum() * (3 / 7))\n",
- " if \"saves\" not in existingTables:\n",
- " self.statusBar.showMessage(\"Создание таблицы saves...\")\n",
- " self.cursor.execute(\"CREATE TABLE `saves` (\"\n",
- " \"`user_id` INTEGER NOT NULL,\"\n",
- " \"`type` TEXT DEFAULT '',\"\n",
- " \"`data` TEXT DEFAULT '',\"\n",
- " \"`course_id` INTEGER NOT NULL,\"\n",
- " \"`exercise_id` INTEGER NULL,\"\n",
- " \"FOREIGN KEY (`user_id`) REFERENCES `users`(`user_id`) \"\n",
- " \"ON DELETE CASCADE \"\n",
- " \"ON UPDATE CASCADE\"\n",
- " \")\")\n",
- " self.progressBar.setValue(self.progressBar.maximum() * (4 / 7))\n",
- " if \"courses\" not in existingTables:\n",
- " self.statusBar.showMessage(\"Создание таблицы courses...\")\n",
- " self.cursor.execute(\"CREATE TABLE `courses` (\"\n",
- " \"`course_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\"\n",
- " \"`face` TEXT DEFAULT 'book.png',\"\n",
- " \"`author` TEXT DEFAULT 'Пользователь',\"\n",
- " \"`title` TEXT DEFAULT '',\"\n",
- " \"`description` TEXT DEFAULT ''\"\n",
- " \")\")\n",
- " self.progressBar.setValue(self.progressBar.maximum() * (5 / 7))\n",
- " if \"pages\" not in existingTables:\n",
- " self.statusBar.showMessage(\"Создание таблицы pages...\")\n",
- " self.cursor.execute(\"CREATE TABLE `pages` (\"\n",
- " \"`course_id` INTEGER NOT NULL,\"\n",
- " \"`page` INTEGER DEFAULT 1,\"\n",
- " \"`group` INTEGER NOT NULL,\"\n",
- " \"`title` TEXT DEFAULT '',\"\n",
- " \"`data` TEXT DEFAULT '',\"\n",
- " \"FOREIGN KEY (`course_id`) REFERENCES `courses`(`course_id`) \"\n",
- " \"ON DELETE CASCADE \"\n",
- " \"ON UPDATE CASCADE\"\n",
- " \")\")\n",
- " self.progressBar.setValue(self.progressBar.maximum() * (6 / 7))\n",
- " if \"exercises\" not in existingTables:\n",
- " self.statusBar.showMessage(\"Создание таблицы exercises...\")\n",
- " self.cursor.execute(\"CREATE TABLE `exercises` (\"\n",
- " \"`exercise_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\"\n",
- " \"`course_id` INTEGER NOT NULL,\"\n",
- " \"`page` INTEGER NOT NULL,\"\n",
- " \"`group` INTEGER NOT NULL,\"\n",
- " \"`description` TEXT DEFAULT '',\"\n",
- " \"`type` TEXT DEFAULT '',\"\n",
- " \"`data` TEXT DEFAULT '',\"\n",
- " \"FOREIGN KEY (`course_id`) REFERENCES `courses`(`course_id`)\"\n",
- " \"ON DELETE CASCADE \"\n",
- " \"ON UPDATE CASCADE\"\n",
- " \")\")\n",
- " self.progressBar.setValue(self.progressBar.maximum())\n",
- " self.uploadExistsUsers()\n",
- " \n",
- " def __del__(self):\n",
- " try:\n",
- " self.cursor.close()\n",
- " self.connection.close()\n",
- " except:\n",
- " pass\n",
- " \n",
- " def offerToEnter(self):\n",
- " self.enterWindow.show()\n",
- " \n",
- " def uploadExistsUsers(self):\n",
- " self.progressBar.setValue(0)\n",
- " self.statusBar.showMessage(\"Загрузка пользователей...\")\n",
- " self.cursor.execute(\"SELECT `user_login` FROM `users`\")\n",
- " rows = self.cursor.fetchall()\n",
- " l = len(rows)\n",
- " for i in range(l):\n",
- " foundedUser = User(self, rows[i][0])\n",
- " self.users.append(foundedUser)\n",
- " self.progressBar.setValue(self.progressBar.maximum() * (i + 1) / l)\n",
- " self.progressBar.setValue(self.progressBar.maximum())\n",
- " \n",
- " def userIsRegistered(self, user: User) -> bool:\n",
- " self.cursor.execute(\"SELECT `user_login` FROM `users`\")\n",
- " rows = self.cursor.fetchall()\n",
- " for row in rows:\n",
- " if row[0] == user.login:\n",
- " return True\n",
- " return False\n",
- " \n",
- " def registerUser(self, user: User) -> int:\n",
- " try:\n",
- " if not self.userIsRegistered(user):\n",
- " self.users.append(user)\n",
- " self.cursor.execute(\"INSERT INTO `users` (`user_login`, `user_password`, `user_avatar`) VALUES ('{}', '{}', '{}')\".format(user.login, user.password, user.avatarUrl))\n",
- " else:\n",
- " self.cursor.execute(\"UPDATE `users` SET `user_password` = '{}', `user_avatar` = '{}' WHERE `user_login` = '{}'\".format(user.password, user.avatarUrl, user.login))\n",
- " self.connection.commit()\n",
- " user.upload()\n",
- " return user.userId\n",
- " finally:\n",
- " return -1\n",
- " \n",
- " def deleteUser(self, user: User) -> bool:\n",
- " try:\n",
- " if self.userIsRegistered(user):\n",
- " self.users.remove(user)\n",
- " self.cursor.execute(\"DELETE FROM `users` WHERE `user_login` = '{}'\".format(user.login))\n",
- " self.connection.commit()\n",
- " return True\n",
- " finally:\n",
- " return False"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [],
- "source": [
- "loginRegExp = QtCore.QRegExp(r\"[a-zA-Zа-яА-Я\\_\\$][a-zA-Zа-яА-Я\\_\\$\\-0-9]*\")\n",
- "currentUser = None\n",
- "mainFrame = None"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [],
- "source": [
- "class StyledLabel(QtWidgets.QLabel):\n",
- " \n",
- " def __init__(self, line: str=\"\", parent=None):\n",
- " super().__init__(line, parent)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [],
- "source": [
- "class RegistrationWindow(QtWidgets.QWidget):\n",
- " \n",
- " def __init__(self, enterWindow):\n",
- " super().__init__()\n",
- " self.setWindowTitle(\"Регистрация\")\n",
- " self.enterWindow = enterWindow\n",
- " self.newLogin = enterWindow.loginEdit.text()\n",
- " \n",
- " self.vbox = QtWidgets.QVBoxLayout(self)\n",
- " self.hbox1 = QtWidgets.QHBoxLayout()\n",
- " self.hbox2 = QtWidgets.QHBoxLayout()\n",
- " self.hbox3 = QtWidgets.QHBoxLayout()\n",
- " self.buttonGo = QtWidgets.QPushButton(\"Зарегистрироваться\")\n",
- " self.buttonGo.clicked.connect(self.register)\n",
- " self.label1 = StyledLabel(\"Аватар:\")\n",
- " self.label1.setFixedWidth(96)\n",
- " self.label1.setAlignment(QtCore.Qt.AlignRight)\n",
- " self.label2 = StyledLabel(\"Логин:\")\n",
- " self.label2.setFixedWidth(96)\n",
- " self.label2.setAlignment(QtCore.Qt.AlignRight)\n",
- " self.label3 = StyledLabel(\"Пароль:\")\n",
- " self.label3.setFixedWidth(96)\n",
- " self.label3.setAlignment(QtCore.Qt.AlignRight)\n",
- " self.lineEdit = QtWidgets.QLineEdit()\n",
- " self.lineEdit.setValidator(QtGui.QRegExpValidator(loginRegExp))\n",
- " self.lineEdit.setMaxLength(50)\n",
- " self.avatarsBox = QtWidgets.QComboBox()\n",
- " self.avatarsBox.setIconSize(QtCore.QSize(48, 48))\n",
- " pixList = os.listdir(\"Avatars\")\n",
- " pixList.sort()\n",
- " for pixName in pixList:\n",
- " self.avatarsBox.addItem(QtGui.QIcon(\"Avatars/\" + pixName), pixName)\n",
- " self.pwdEdit = QtWidgets.QLineEdit()\n",
- " self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Password)\n",
- " self.pwdEdit.setMaxLength(32)\n",
- " self.buttonShowPassword = QtWidgets.QCheckBox()\n",
- " self.buttonShowPassword.stateChanged.connect(self.checked)\n",
- " \n",
- " self.hbox1.addWidget(self.label1)\n",
- " self.hbox1.addWidget(self.avatarsBox)\n",
- " self.hbox2.addWidget(self.label2)\n",
- " self.hbox2.addWidget(self.lineEdit)\n",
- " self.hbox3.addWidget(self.label3)\n",
- " self.hbox3.addWidget(self.pwdEdit)\n",
- " self.hbox3.addWidget(self.buttonShowPassword)\n",
- " self.vbox.addLayout(self.hbox1)\n",
- " self.vbox.addLayout(self.hbox2)\n",
- " self.vbox.addLayout(self.hbox3)\n",
- " self.vbox.addWidget(self.buttonGo)\n",
- "\n",
- " def checked(self, newState):\n",
- " if newState == QtCore.Qt.Checked:\n",
- " self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Normal)\n",
- " else:\n",
- " self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Password)\n",
- "\n",
- " def showEvent(self, event):\n",
- " global db\n",
- " db.statusBar.showMessage(\"Регистрация пользователя...\")\n",
- " self.desktop = QtWidgets.QApplication.desktop()\n",
- " x = (self.desktop.width() - self.width()) // 2\n",
- " y = (self.desktop.height() - self.height()) // 2\n",
- " self.move(x, y)\n",
- "\n",
- " def register(self):\n",
- " global db\n",
- " newUser = User(db, self.lineEdit.text())\n",
- " newUser.setAvatar(self.avatarsBox.currentText())\n",
- " newUser.setPassword(hashlib.md5(self.pwdEdit.text().encode()).hexdigest())\n",
- " db.registerUser(newUser)\n",
- " self.hide()\n",
- " self.enterWindow.uploadUsers()\n",
- " self.enterWindow.show()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [],
- "source": [
- "class UsersListItem(QtWidgets.QListWidgetItem):\n",
- "\n",
- " def __init__(self, user: User, parent=None):\n",
- " super().__init__(parent)\n",
- " self.user = user\n",
- " self.setSizeHint(QtCore.QSize(0, 64))\n",
- "\n",
- " def updateItem(self):\n",
- " self.user.upload()\n",
- " self.setIcon(self.user.avatar)\n",
- " 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",
- "\n",
- " def updateUser(self, newUser: User):\n",
- " self.user = newUser\n",
- " self.updateItem()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [],
- "source": [
- "class UsersList(QtWidgets.QListWidget):\n",
- " selectedItem = None\n",
- " autoSelect = False\n",
- "\n",
- " def __init__(self, enterWindow=None):\n",
- " super().__init__(enterWindow)\n",
- " self.enterWindow = enterWindow\n",
- " self.setSortingEnabled(True)\n",
- " self.setAlternatingRowColors(True)\n",
- " self.setIconSize(QtCore.QSize(48, 48))\n",
- " self.itemSelectionChanged.connect(self.itemIsSelected)\n",
- " self.itemClicked.connect(self.itemIsClicked)\n",
- "\n",
- " def updateList(self, enteredLogin: str=\"\"):\n",
- " global db\n",
- " self.clear()\n",
- " if enteredLogin == \"\":\n",
- " for user in db.users:\n",
- " item = UsersListItem(user)\n",
- " item.updateItem()\n",
- " self.addItem(item)\n",
- " else:\n",
- " enteredLogin = enteredLogin.lower()\n",
- " for user in db.users:\n",
- " if user.login.lower().find(enteredLogin) != -1:\n",
- " item = UsersListItem(user)\n",
- " item.updateItem()\n",
- " self.addItem(item)\n",
- " if user is db.users[0]:\n",
- " self.autoSelect = True\n",
- " item.setSelected(True)\n",
- " self.autoSelect = False\n",
- " \n",
- " def itemIsSelected(self):\n",
- " if len(self.selectedItems()) > 0:\n",
- " self.selectedItem = self.selectedItems()[0]\n",
- " if not self.autoSelect:\n",
- " self.enterWindow.loginEdit.setText(self.selectedItem.user.login)\n",
- " self.enterWindow.loginEdit.setFocus(True)\n",
- " \n",
- " def itemIsClicked(self, clickedItem):\n",
- " if len(self.selectedItems()) > 0:\n",
- " self.selectedItem = self.selectedItems()[0]\n",
- " self.enterWindow.loginEdit.setText(self.selectedItem.user.login)\n",
- " self.enterWindow.loginEdit.setFocus(True)\n",
- " \n",
- " def deleteItem(self, item: UsersListItem):\n",
- " try:\n",
- " self.removeItemWidget(item)\n",
- " item.user.deleteUser()\n",
- " finally:\n",
- " return"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [],
- "source": [
- "class EnterWindow(QtWidgets.QWidget):\n",
- "\n",
- " def __init__(self):\n",
- " super().__init__()\n",
- " self.setWindowTitle(\"Вход\")\n",
- "\n",
- " self.vbox = QtWidgets.QVBoxLayout(self)\n",
- " self.loginEdit = QtWidgets.QLineEdit()\n",
- " self.loginEdit.setObjectName(\"loginEdit\")\n",
- " self.loginEdit.setPlaceholderText(\"Введите логин\")\n",
- " self.loginEdit.setValidator(QtGui.QRegExpValidator(loginRegExp))\n",
- " self.loginEdit.textChanged.connect(self.loginChanged)\n",
- " self.vbox.addWidget(self.loginEdit)\n",
- "\n",
- " self.usersList = UsersList(self)\n",
- " self.vbox.addWidget(self.usersList)\n",
- " \n",
- " self.hbox = QtWidgets.QHBoxLayout()\n",
- " self.pwdEdit = QtWidgets.QLineEdit()\n",
- " self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Password)\n",
- " self.pwdEdit.setMaxLength(32)\n",
- " self.pwdEdit.setPlaceholderText(\"Введите пароль\")\n",
- " self.hbox.addWidget(self.pwdEdit)\n",
- " self.buttonShowPassword = QtWidgets.QCheckBox()\n",
- " self.buttonShowPassword.stateChanged.connect(self.checked)\n",
- " self.hbox.addWidget(self.buttonShowPassword)\n",
- " self.vbox.addLayout(self.hbox)\n",
- " \n",
- " self.buttonGo = QtWidgets.QPushButton(\"Войти\")\n",
- " self.buttonGo.clicked.connect(self.enterUser)\n",
- " self.vbox.addWidget(self.buttonGo)\n",
- " \n",
- " self.buttonNew = QtWidgets.QPushButton(\"Новый пользователь\")\n",
- " self.buttonNew.clicked.connect(self.createUser)\n",
- " self.vbox.addWidget(self.buttonNew)\n",
- " \n",
- " self.buttonDelete = QtWidgets.QPushButton(\"Удалить пользователя\")\n",
- " self.buttonDelete.clicked.connect(self.deleteUser)\n",
- " self.vbox.addWidget(self.buttonDelete)\n",
- " \n",
- " def checked(self, newState):\n",
- " if newState == QtCore.Qt.Checked:\n",
- " self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Normal)\n",
- " else:\n",
- " self.pwdEdit.setEchoMode(QtWidgets.QLineEdit.Password)\n",
- " \n",
- " def showEvent(self, event):\n",
- " global db\n",
- " db.statusBar.showMessage(\"Выбор пользователя...\")\n",
- " self.desktop = QtWidgets.QApplication.desktop()\n",
- " x = (self.desktop.width() - self.width()) // 2\n",
- " y = (self.desktop.height() - self.height()) // 2\n",
- " self.move(x, y)\n",
- " \n",
- " def uploadUsers(self):\n",
- " self.usersList.updateList()\n",
- " \n",
- " def loginChanged(self, enteredLogin):\n",
- " self.usersList.updateList(enteredLogin)\n",
- " if self.usersList.count() > 0 and len(enteredLogin) > 0:\n",
- " self.usersList.autoSelect = True\n",
- " self.usersList.item(0).setSelected(True)\n",
- " self.usersList.autoSelect = False\n",
- " \n",
- " def enterUser(self):\n",
- " if self.usersList.selectedItem is None:\n",
- " QtWidgets.QMessageBox.warning(self, \"Ошибка\", \"Выберите пользователя.\")\n",
- " else:\n",
- " pwd = hashlib.md5(self.pwdEdit.text().encode()).hexdigest()\n",
- " if pwd == self.usersList.selectedItem.user.password:\n",
- " global db, currentUser, mainFrame\n",
- " currentUser = self.usersList.selectedItem.user\n",
- " self.hide()\n",
- " mainFrame.menuBar.setEnabled(True)\n",
- " db.statusBar.showMessage(\"Добро пожаловать, {0:s}!\".format(currentUser.login))\n",
- " mainFrame.reloadChoiceList()\n",
- " mainFrame.reloadUser()\n",
- " else:\n",
- " QtWidgets.QMessageBox.warning(self, \"Ошибка\", \"Вы ввели неверный пароль пользователя.\")\n",
- " \n",
- " def closeEvent(self, event):\n",
- " global currentUser\n",
- " if currentUser is None:\n",
- " QtWidgets.QApplication.quit()\n",
- " else:\n",
- " event.accept()\n",
- " \n",
- " def createUser(self):\n",
- " self.hide()\n",
- " self.registrationWindow = RegistrationWindow(self)\n",
- " self.registrationWindow.show()\n",
- " \n",
- " def deleteUser(self):\n",
- " try:\n",
- " global db\n",
- " user = self.usersList.selectedItem.user\n",
- " if db.userIsRegistered(user):\n",
- " self.usersList.deleteItem(self.usersList.selectedItem)\n",
- " self.usersList.updateList()\n",
- " self.loginEdit.setText(\"\")\n",
- " finally:\n",
- " return"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [],
- "source": [
- "class ProgressBar(QtWidgets.QProgressBar):\n",
- " progressBarBrightText = False\n",
- " \n",
- " def __init__(self, parent=None):\n",
- " super().__init__(parent)\n",
- " self.valueChanged.connect(self.loadingUpdate)\n",
- " \n",
- " def loadingUpdate(self, value):\n",
- " self.setFormat(\"{0:d}%\".format(int(self.value() * 100 / self.maximum())))\n",
- " if value * 2 < self.maximum() + self.fontMetrics().width(self.format()) and self.progressBarBrightText:\n",
- " self.setStyleSheet(\"color: rgb(32, 32, 32);\")\n",
- " self.progressBarBrightText = False\n",
- " elif value * 2 >= self.maximum() + self.fontMetrics().width(self.format()) and not self.progressBarBrightText:\n",
- " self.setStyleSheet(\"color: white;\")\n",
- " self.progressBarBrightText = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [],
- "source": [
- "class ProgressBarF(QtWidgets.QProgressBar):\n",
- " progressBarBrightText = False\n",
- " \n",
- " def __init__(self, parent=None):\n",
- " super().__init__(parent)\n",
- " self.valueChanged.connect(self.loadingUpdate)\n",
- " \n",
- " def loadingUpdate(self, value):\n",
- " self.setFormat(\"{0:.2f}%\".format(self.value() * 100 / self.maximum()))\n",
- " if value * 2 < self.maximum() + self.fontMetrics().width(self.format()) and self.progressBarBrightText:\n",
- " self.setStyleSheet(\"color: rgb(32, 32, 32);\")\n",
- " self.progressBarBrightText = False\n",
- " elif value * 2 >= self.maximum() + self.fontMetrics().width(self.format()) and not self.progressBarBrightText:\n",
- " self.setStyleSheet(\"color: white;\")\n",
- " self.progressBarBrightText = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [],
- "source": [
- "class CourseLabel(QtWidgets.QLabel): \n",
- " mouse = 0 # leaveEvent ~ 0, enterEvent ~ 1, mousePressEvent ~ 2\n",
- " \n",
- " def __init__(self, course_id: int):\n",
- " super().__init__()\n",
- " global db\n",
- " db.cursor.execute('SELECT face, author, title, description FROM courses WHERE course_id = {}'.format(course_id))\n",
- " row = db.cursor.fetchone()\n",
- " self.course_id, self.face, self.author, self.title, self.description = course_id, *row\n",
- " self.pixmap = QtGui.QPixmap('Images/' + self.face).scaledToHeight(240)\n",
- " self.setFixedHeight(256)\n",
- " \n",
- " def paintEvent(self, event):\n",
- " painter = QtGui.QPainter(self)\n",
- " painter.setBackgroundMode(QtCore.Qt.TransparentMode)\n",
- " painter.setRenderHint(QtGui.QPainter.Antialiasing, True)\n",
- " if self.mouse == 0:\n",
- " painter.setOpacity(0.125 if self.course_id & 0x01 else 0.0625)\n",
- " elif self.mouse == 1:\n",
- " painter.setOpacity(0.1875)\n",
- " else:\n",
- " painter.setOpacity(0)\n",
- " painter.fillRect(0, 0, self.width() - 2, self.height() - 1, QtGui.QBrush(QtCore.Qt.white, QtCore.Qt.SolidPattern))\n",
- " painter.setOpacity(1.0)\n",
- " painter.drawPixmap(8, 8, self.pixmap.width(), self.pixmap.height(), self.pixmap)\n",
- " painter.setFont(QtGui.QFont('Monaco', 10, QtGui.QFont.Bold))\n",
- " painter.setPen(QtGui.QPen(QtCore.Qt.white, 1))\n",
- " painter.drawText(\n",
- " QtCore.QRect(self.pixmap.width() + 16, 8, self.width() - self.pixmap.width() - 24, 240),\n",
- " QtCore.Qt.AlignLeft | QtCore.Qt.TextWordWrap,\n",
- " 'Автор: {}\\nНазвание: {}'.format(self.author, self.title)\n",
- " )\n",
- " \n",
- " def showEvent(self, event):\n",
- " self.update()\n",
- " \n",
- " def resizeEvent(self, event):\n",
- " self.update()\n",
- " \n",
- " def enterEvent(self, event):\n",
- " self.mouse = 1\n",
- " self.update()\n",
- " self.setCursor(QtCore.Qt.PointingHandCursor)\n",
- " \n",
- " def leaveEvent(self, event):\n",
- " self.mouse = 0\n",
- " self.update()\n",
- " self.setCursor(QtCore.Qt.ArrowCursor)\n",
- " \n",
- " def mousePressEvent(self, event):\n",
- " self.mouse = 2\n",
- " self.update()\n",
- " self.setCursor(QtCore.Qt.ArrowCursor)\n",
- " \"\"\"global mainFrame\n",
- " mainFrame.openCourse(self)\"\"\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'def CourseFrame(QtWidgets.QLabel):\\n \\n pass'"
- ]
- },
- "execution_count": 13,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "\"\"\"def CourseFrame(QtWidgets.QLabel):\n",
- " \n",
- " pass\"\"\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [],
- "source": [
- "class MainArea(QtWidgets.QScrollArea):\n",
- " \n",
- " def __init__(self, mainFrame = None):\n",
- " super().__init__(mainFrame)\n",
- " \n",
- " def resizeEvent(self, event):\n",
- " self.mainPanel.setFixedWidth(self.width() - 16)\n",
- " if self.courses:\n",
- " for courseLabel in self.courses:\n",
- " courseLabel.setFixedWidth(self.width() - 18)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [],
- "source": [
- "class MainFrame(QtWidgets.QWidget):\n",
- " \n",
- " def __init__(self, mainWindow=None):\n",
- " super().__init__(mainWindow)\n",
- " self.mainWindow = mainWindow\n",
- " global mainFrame\n",
- " mainFrame = self\n",
- "\n",
- " self.vbox = QtWidgets.QVBoxLayout(self)\n",
- " self.vbox.setContentsMargins(0, 0, 0, 0)\n",
- " self.vbox.setSpacing(0)\n",
- "\n",
- " # Нижняя строка состояния\n",
- " self.statusBar = QtWidgets.QStatusBar(self)\n",
- " self.statusBar.setObjectName(\"mainStatusBar\")\n",
- " self.statusBar.setFixedHeight(32)\n",
- " self.statusBar.setSizeGripEnabled(False)\n",
- " self.statusBar.setContentsMargins(0, 0, 3, 0)\n",
- "\n",
- " # Индикатор хода прогресса\n",
- " self.progressBar = ProgressBar(self.statusBar)\n",
- " self.progressBar.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)\n",
- " self.progressBar.setFixedWidth(160)\n",
- " self.progressBar.setRange(0, 160)\n",
- " self.statusBar.addPermanentWidget(self.progressBar)\n",
- " \n",
- " self.userLabel = QtWidgets.QLabel()\n",
- " self.userLabel.setObjectName(\"userLabel\")\n",
- " self.userLabel.setFixedHeight(100)\n",
- " self.userLabel.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)\n",
- " self.userLabel.setContentsMargins(4, 8, 4, 4)\n",
- " self.choiceList = QtWidgets.QTreeWidget()\n",
- " self.choiceList.setObjectName(\"choiceList\")\n",
- " self.choiceList.setHeaderHidden(True)\n",
- " self.choiceList.setAnimated(True)\n",
- " header = self.choiceList.header()\n",
- " header.setStretchLastSection(False)\n",
- " header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)\n",
- " self.choiceList.setHeader(header)\n",
- " self.mainPanel = QtWidgets.QLabel()\n",
- " self.mainPanel.setObjectName('mainPanel')\n",
- " self.mainBox = QtWidgets.QVBoxLayout(self.mainPanel)\n",
- " self.mainBox.setContentsMargins(0, 0, 0, 0)\n",
- " self.mainBox.setSpacing(0)\n",
- " self.mainBox.setAlignment(QtCore.Qt.AlignHCenter)\n",
- " self.leftPanel = QtWidgets.QLabel()\n",
- " self.leftBox = QtWidgets.QVBoxLayout()\n",
- " self.leftBox.setContentsMargins(0, 0, 0, 0)\n",
- " self.leftBox.setSpacing(0)\n",
- " self.leftPanel.setLayout(self.leftBox)\n",
- " self.leftBox.addWidget(self.userLabel)\n",
- " self.leftBox.addWidget(self.choiceList)\n",
- " \n",
- " self.itemCourses = QtWidgets.QTreeWidgetItem(self.choiceList)\n",
- " self.itemCourses.setText(0, \"Курсы\")\n",
- " self.itemActiveCourses = QtWidgets.QTreeWidgetItem(self.itemCourses)\n",
- " self.itemActiveCourses.setText(0, \"Активные курсы\")\n",
- " self.itemNonactiveCourses = QtWidgets.QTreeWidgetItem(self.itemCourses)\n",
- " self.itemNonactiveCourses.setText(0, \"Закрытые курсы\")\n",
- " self.itemPrograms = QtWidgets.QTreeWidgetItem(self.choiceList)\n",
- " self.itemPrograms.setText(0, \"Python-программы\")\n",
- " \n",
- " # Режим пользователя\n",
- " self.splitter = QtWidgets.QSplitter()\n",
- " self.splitter.setOrientation(QtCore.Qt.Horizontal)\n",
- " self.splitter.addWidget(self.leftPanel)\n",
- " \n",
- " # Верхнее меню\n",
- " self.menuBar = QtWidgets.QMenuBar()\n",
- " self.menuBar.setFixedHeight(26)\n",
- " \n",
- " self.developerMenu = QtWidgets.QMenu(\"&Разработка\")\n",
- " self.developerMenu.setLayoutDirection(QtCore.Qt.LeftToRight)\n",
- " self.modeGroup = QtWidgets.QActionGroup(self.developerMenu)\n",
- " self.modeGroup.setExclusive(True)\n",
- " self.menuBar.addMenu(self.developerMenu)\n",
- " self.userMode = QtWidgets.QAction(\"Режим пользователя\", self.modeGroup)\n",
- " self.userMode.setCheckable(True)\n",
- " self.developerMode = QtWidgets.QAction(\"Режим разработчика\", self.modeGroup)\n",
- " self.developerMode.setCheckable(True)\n",
- " self.developerMenu.addAction(self.userMode)\n",
- " self.developerMenu.addAction(self.developerMode)\n",
- " self.userMode.setChecked(True)\n",
- " self.menuBar.setDisabled(True)\n",
- " self.modeGroup.triggered.connect(self.modeToggled)\n",
- " self.vbox.addWidget(self.menuBar)\n",
- " self.vbox.addWidget(self.splitter)\n",
- " self.vbox.addWidget(self.statusBar)\n",
- " \n",
- " # Режим разработчика\n",
- " self.developerWidget = QtWidgets.QWidget()\n",
- " self.developerLayout = QtWidgets.QVBoxLayout(self.developerWidget)\n",
- " self.developerLayout.setSpacing(0)\n",
- " self.developerLayout.setContentsMargins(0, 0, 0, 0)\n",
- " \n",
- " self.buttonsArea = QtWidgets.QScrollArea()\n",
- " self.buttonsArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)\n",
- " self.buttonsArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)\n",
- " self.buttonsLabel = QtWidgets.QLabel()\n",
- " self.buttonsArea.setWidget(self.buttonsLabel)\n",
- " self.buttonsBox = QtWidgets.QHBoxLayout(self.buttonsLabel)\n",
- " self.buttonsBox.setContentsMargins(2, 2, 2, 2)\n",
- " self.buttonsBox.setSpacing(2)\n",
- " self.buttonExec = QtWidgets.QPushButton(\"Выполнить запрос (F5)\")\n",
- " self.buttonExec.setShortcut(QtCore.Qt.Key_F5)\n",
- " self.buttonExec.setIcon(QtGui.QIcon(\"Images/exec.png\"))\n",
- " self.buttonExec.setFixedWidth(210)\n",
- " self.buttonExec.clicked.connect(self.execCommand)\n",
- " self.buttonsBox.addWidget(self.buttonExec)\n",
- " self.buttonCommit = QtWidgets.QPushButton(\"Совершить транзакцию (F6)\")\n",
- " self.buttonCommit.setShortcut(QtCore.Qt.Key_F6)\n",
- " self.buttonCommit.setIcon(QtGui.QIcon(\"Images/commit.png\"))\n",
- " self.buttonCommit.setFixedWidth(240)\n",
- " self.buttonCommit.clicked.connect(self.commitCommand)\n",
- " self.buttonsBox.addWidget(self.buttonCommit)\n",
- " self.buttonClear = QtWidgets.QPushButton(\"Очистить консоль (Ctrl+R)\")\n",
- " self.buttonClear.setShortcut(QtCore.Qt.ControlModifier | QtCore.Qt.Key_R)\n",
- " self.buttonClear.setIcon(QtGui.QIcon(\"Images/clear.png\"))\n",
- " self.buttonClear.setFixedWidth(230)\n",
- " self.buttonClear.clicked.connect(self.clearCommand)\n",
- " self.buttonsBox.addWidget(self.buttonClear)\n",
- " self.buttonSave = QtWidgets.QPushButton(\"Сохранить SQL (Ctrl+S)\")\n",
- " self.buttonSave.setShortcut(QtCore.Qt.ControlModifier | QtCore.Qt.Key_S)\n",
- " self.buttonSave.setIcon(QtGui.QIcon(\"Images/save.png\"))\n",
- " self.buttonSave.setFixedWidth(220)\n",
- " self.buttonSave.clicked.connect(self.saveCommand)\n",
- " self.buttonsBox.addWidget(self.buttonSave)\n",
- " self.buttonsArea.setFixedHeight(30)\n",
- " self.buttonsLabel.setFixedSize(QtCore.QSize(self.buttonExec.width() + self.buttonCommit.width() + self.buttonClear.width() + self.buttonSave.width() + 10, 28))\n",
- " self.developerLayout.addWidget(self.buttonsArea)\n",
- " \n",
- " self.devSplitter = QtWidgets.QSplitter()\n",
- " self.devSplitter.setOrientation(QtCore.Qt.Vertical)\n",
- " self.devSplitter.setHandleWidth(4)\n",
- " self.developerLayout.addWidget(self.devSplitter)\n",
- " \n",
- " self.developerTextEdit = QtWidgets.QTextEdit()\n",
- " self.developerTextEdit.setObjectName(\"developerTextEdit\")\n",
- " self.developerTextEdit.setWordWrapMode(False)\n",
- " self.devSplitter.addWidget(self.developerTextEdit)\n",
- " \n",
- " self.consoleTextEdit = QtWidgets.QTextEdit()\n",
- " self.consoleTextEdit.setObjectName(\"consoleTextEdit\")\n",
- " self.consoleTextEdit.setReadOnly(True)\n",
- " self.consoleTextEdit.setWordWrapMode(False)\n",
- " self.devSplitter.addWidget(self.consoleTextEdit)\n",
- " \n",
- " def showEvent(self, event):\n",
- " self.update()\n",
- " \n",
- " def loadDatabase(self):\n",
- " global db\n",
- " db = Database(self.statusBar, self.progressBar, self.enterWindow)\n",
- " \n",
- " # Главная панель\n",
- " self.mainArea = MainArea()\n",
- " self.mainArea.setObjectName(\"mainArea\")\n",
- " self.mainArea.mainBox = self.mainBox\n",
- " self.mainArea.mainPanel = self.mainPanel\n",
- " self.mainArea.courses = []\n",
- " self.mainArea.setWidget(self.mainPanel)\n",
- " db.cursor.execute('SELECT course_id FROM courses')\n",
- " self.course_ids = [row[0] for row in db.cursor.fetchall()]\n",
- " self.courses = []\n",
- " height = 0\n",
- " for course_id in self.course_ids:\n",
- " course = CourseLabel(course_id)\n",
- " self.courses.append(course)\n",
- " self.mainBox.addWidget(course)\n",
- " height += course.height()\n",
- " \n",
- " # Режим пользователя\n",
- " self.splitter.addWidget(self.mainArea)\n",
- " self.splitter.setSizes((320, self.mainArea.width()))\n",
- " self.mainPanel.setFixedWidth(self.mainArea.width() - 16)\n",
- " self.mainPanel.setFixedHeight(height)\n",
- " for course in self.courses:\n",
- " course.setFixedWidth(self.mainArea.width() - 18)\n",
- " self.splitter.setHandleWidth(4)\n",
- " \n",
- " \"\"\"def openCourse(self, courseLabel: CourseLabel):\n",
- " self.currentCourseLabel = courseLabel\n",
- " self.hideListOfCourses()\n",
- " \n",
- " def hideListOfCourses(self):\n",
- " self.opacity1 = QtWidgets.QGraphicsOpacityEffect()\n",
- " self.mainArea.setGraphicsEffect(self.opacity1)\n",
- " self.anim1 = QtCore.QPropertyAnimation(self.opacity1, b\"opacity\")\n",
- " self.anim1.setDuration(250)\n",
- " self.anim1.setStartValue(1.0)\n",
- " self.anim1.setEndValue(0.0)\n",
- " self.anim1.start()\n",
- " self.anim1.finished.connect(self.showCourse)\n",
- " \n",
- " def showCourse(self):\n",
- " self.mainArea.hide()\n",
- " self.opacity2 = QtWidgets.QGraphicsOpacityEffect()\n",
- " \n",
- " # Открываем выбранный курс\n",
- " self.courseFrame = \n",
- " \n",
- " self.mainFrame.setGraphicsEffect(self.opacity2)\n",
- " self.mainFrame.setWindowOpacity(0.0)\n",
- " self.mainFrame.show()\n",
- " self.anim2 = QtCore.QPropertyAnimation(self.opacity2, b\"opacity\")\n",
- " self.anim2.setDuration(250)\n",
- " self.anim2.setStartValue(0.0)\n",
- " self.anim2.setEndValue(1.0)\n",
- " self.anim2.start()\n",
- " self.anim2.finished.connect(self.mainFrameIsVisible)\"\"\"\n",
- " \n",
- " def offerToEnter(self):\n",
- " global db\n",
- " db.offerToEnter()\n",
- " \n",
- " def modeToggled(self, action: QtWidgets.QAction):\n",
- " if self.userMode.isChecked():\n",
- " self.statusBar.showMessage(\"Режим пользователя.\")\n",
- " self.vbox.replaceWidget(self.developerWidget, self.splitter)\n",
- " self.developerWidget.setVisible(False)\n",
- " self.reloadUser()\n",
- " self.reloadChoiceList()\n",
- " self.splitter.setVisible(True)\n",
- " if self.developerMode.isChecked():\n",
- " self.statusBar.showMessage(\"Режим разработчика.\")\n",
- " self.vbox.replaceWidget(self.splitter, self.developerWidget)\n",
- " self.splitter.setVisible(False)\n",
- " self.developerWidget.setVisible(True)\n",
- " \n",
- " def reloadUser(self):\n",
- " self.userLabel.setText('<img src=\"Avatars/{}\" width=\"64\" height=\"64\" align=\"left\" /><span style=\"color: khaki; font-weight: bold\"> {}</span><br><br> Прогресс: {:.1f}'.format(currentUser.avatarUrl, currentUser.login, currentUser.progress))\n",
- " \n",
- " def reloadChoiceList(self):\n",
- " for child in self.itemActiveCourses.takeChildren():\n",
- " self.itemActiveCourses.removeChild(child)\n",
- " for child in self.itemNonactiveCourses.takeChildren():\n",
- " self.itemActiveCourses.removeChild(child)\n",
- " global currentUser\n",
- " if currentUser:\n",
- " global db\n",
- " db.cursor.execute('SELECT course_id, face, title, description FROM courses')\n",
- " rows = db.cursor.fetchall()\n",
- " db.cursor.execute(\"SELECT course_id FROM saves WHERE user_id = {} AND type = 'isActive' AND data = 'True'\".format(currentUser.userId))\n",
- " activeCourses = [r[0] for r in db.cursor.fetchall()]\n",
- " for row in rows:\n",
- " course_id, face, title, description = row\n",
- " newItem = QtWidgets.QTreeWidgetItem(self.itemActiveCourses if (course_id in activeCourses) else self.itemNonactiveCourses)\n",
- " newItem.setText(0, title)\n",
- " \n",
- " def execCommand(self, event):\n",
- " textCursor = QtGui.QTextCursor(self.developerTextEdit.textCursor())\n",
- " text = textCursor.selectedText()\n",
- " if text == \"\":\n",
- " text = self.developerTextEdit.toPlainText()\n",
- " \n",
- " self.statusBar.showMessage(\"Выполнение запроса...\")\n",
- " self.progressBar.setValue(0)\n",
- " self.consoleTextEdit.moveCursor(QtGui.QTextCursor.End)\n",
- " self.consoleTextEdit.insertHtml(\"<span style='font-weight: bold; color: lightgray;'>{0:s}</span><br>\".format(time.asctime()))\n",
- "\n",
- " queries = [q.replace(\"\\\\n\", \"<br>\") for q in re.findall(r\"\\s*((?:(?:\\'[^\\']*?\\')|(?:\\\"[^\\\"]*?\\\")|[^\\\"\\';\\\\]|(?:\\\\(?:[^;]|\\s)))+)\\s*\\\\?;\", text.replace(\"\\\\\\n\", \"\").replace(\"\\n\", \" \"))]\n",
- " global db\n",
- " timeSum, timeBegin, timeEnd = 0, 0, 0\n",
- " db.progressBar.setValue(0)\n",
- " try:\n",
- " qlen = len(queries)\n",
- " for i in range(qlen):\n",
- " timeBegin = time.time()\n",
- " self.consoleTextEdit.setTextColor(QtGui.QColor('gold'))\n",
- " self.consoleTextEdit.insertPlainText(queries[i] + ';\\n')\n",
- " self.consoleTextEdit.setTextColor(QtGui.QColor('#336699'))\n",
- " db.cursor.execute(queries[i])\n",
- " timeEnd = time.time()\n",
- " self.consoleTextEdit.insertHtml(\"<span style='color: green;'>Запрос выполнен за {0:.3f} секунд.</span><br>\".format(timeEnd - timeBegin))\n",
- " timeSum += timeEnd - timeBegin\n",
- " db.progressBar.setValue(db.progressBar.maximum() * (i + 1) / qlen)\n",
- " rows = list(db.cursor.fetchall())\n",
- " desc = False\n",
- " if db.cursor.description:\n",
- " rows.insert(0, [f[0] for f in db.cursor.description])\n",
- " desc = True\n",
- " if rows:\n",
- " rlen = len(rows)\n",
- " wcount = len(rows[0])\n",
- " wmaxlen = [0] * wcount\n",
- " for x in range(wcount):\n",
- " wlen = 0\n",
- " for y in range(rlen):\n",
- " wyxlen = len(str(rows[y][x]))\n",
- " if wyxlen > wlen:\n",
- " wlen = wyxlen\n",
- " wmaxlen[x] = wlen\n",
- " self.consoleTextEdit.insertPlainText(\"+\")\n",
- " for x in range(wcount):\n",
- " self.consoleTextEdit.insertPlainText(\"-\" * (wmaxlen[x] + 2) + (\"+\" if x < (wcount - 1) else \"+\\n\"))\n",
- " if desc:\n",
- " for x in range(wcount):\n",
- " self.consoleTextEdit.insertPlainText(\"|\" + str(rows[0][x]).center(wmaxlen[x] + 2, \" \"))\n",
- " self.consoleTextEdit.insertPlainText(\"|\\n+\")\n",
- " for x in range(wcount):\n",
- " self.consoleTextEdit.insertPlainText(\"-\" * (wmaxlen[x] + 2) + (\"+\" if x < (wcount - 1) else \"+\\n\"))\n",
- " for y in range(1, rlen):\n",
- " for x in range(wcount):\n",
- " self.consoleTextEdit.insertPlainText(\"| \" + str(rows[y][x]).ljust(wmaxlen[x] + 1, \" \"))\n",
- " self.consoleTextEdit.insertPlainText(\"|\\n\")\n",
- " self.consoleTextEdit.insertPlainText(\"+\")\n",
- " for x in range(wcount):\n",
- " self.consoleTextEdit.insertPlainText(\"-\" * (wmaxlen[x] + 2) + (\"+\" if x < (wcount - 1) else \"+\\n\"))\n",
- " self.progressBar.setValue(self.progressBar.maximum() / qlen * (i + 1))\n",
- " self.statusBar.showMessage(\"Запросы выполнены за {0:.3f} секунд.\".format(timeSum))\n",
- " self.consoleTextEdit.insertHtml(\"<span style='color: green;'>Запросы выполнены за {0:.3f} секунд.</span><br><br>\".format(timeSum))\n",
- " except (sqlite3.Error, sqlite3.Warning) as e:\n",
- " self.statusBar.showMessage(\"Режим разработчика.\")\n",
- " self.consoleTextEdit.insertHtml(\"<span style='color: red;'>Ошибка: {}<br><br>\".format(e.args[0].replace(\"<\", \"<\").replace(\">\", \">\")))\n",
- " db.progressBar.setValue(db.progressBar.maximum())\n",
- " \n",
- " self.consoleTextEdit.moveCursor(QtGui.QTextCursor.End)\n",
- " self.progressBar.setValue(self.progressBar.maximum())\n",
- " \n",
- " def commitCommand(self, event):\n",
- " self.statusBar.showMessage(\"Выполнение транзакции...\")\n",
- " self.progressBar.setValue(0)\n",
- " self.consoleTextEdit.moveCursor(QtGui.QTextCursor.End)\n",
- " self.consoleTextEdit.insertHtml(\"<span style='font-weight: bold; color: lightgray;'>{0:s}</span><br>\".format(time.asctime()))\n",
- " \n",
- " global db\n",
- " timeDelta, timeBegin, timeEnd = 0, 0, 0\n",
- " db.progressBar.setValue(0)\n",
- " try:\n",
- " timeBegin = time.time()\n",
- " db.connection.commit()\n",
- " timeEnd = time.time()\n",
- " timeDelta = timeEnd - timeBegin\n",
- " \n",
- " self.statusBar.showMessage(\"Транзакция выполнена за {0:.3f} секунд.\".format(timeDelta))\n",
- " self.consoleTextEdit.insertHtml(\"<span style='color: green;'>Транзакция выполнена за {0:.3f} секунд.</span><br><br>\".format(timeDelta))\n",
- " except:\n",
- " self.statusBar.showMessage(\"Режим разработчика.\")\n",
- " self.consoleTextEdit.insertHtml(\"<span style='color: red;'>Ошибка: не удалось совершить транзакцию.</span><br><br>\")\n",
- " db.progressBar.setValue(db.progressBar.maximum())\n",
- " \n",
- " self.consoleTextEdit.moveCursor(QtGui.QTextCursor.End)\n",
- " self.progressBar.setValue(self.progressBar.maximum())\n",
- " \n",
- " def clearCommand(self):\n",
- " self.consoleTextEdit.clear()\n",
- " self.statusBar.showMessage(\"Консоль очищена...\")\n",
- " \n",
- " def saveCommand(self):\n",
- " try:\n",
- " path = QtWidgets.QFileDialog.getSaveFileName(\n",
- " self,\n",
- " caption=\"Сохранить SQL-код\",\n",
- " directory=\"./\",\n",
- " filter=\"SQL (*.sql);; TXT (*.txt);; Все файлы (*)\",\n",
- " initialFilter= \"SQL (*.sql)\")[0]\n",
- " file = open(path, \"w\")\n",
- " file.write(self.developerTextEdit.toPlainText())\n",
- " file.close()\n",
- " pathConsole = re.search(r\"^(.+?)(?:\\.[^.]+)?$\", path).group(1) + \".txt\"\n",
- " fileHtml = open(pathConsole, \"w\")\n",
- " fileHtml.write(self.consoleTextEdit.toPlainText())\n",
- " fileHtml.close()\n",
- " self.statusBar.showMessage(\"SQL-код сохранён в файле \\\"{0:s}\\\", а данные консоли - в файле \\\"{1:s}\\\".\".format(path, pathConsole))\n",
- " except:\n",
- " self.statusBar.showMessage(\"Произошла ошибка при сохранении SQL-кода и данных консоли.\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [],
- "source": [
- "class GoLink(QtWidgets.QLabel):\n",
- "\n",
- " def __init__(self, text: str=\"\", presentationWindow=None, mainFrame=None):\n",
- " super().__init__(presentationWindow)\n",
- " self.presentationWindow = presentationWindow\n",
- " self.mainFrame = mainFrame\n",
- "\n",
- " self.setAlignment(QtCore.Qt.AlignCenter)\n",
- " self.setText(text)\n",
- "\n",
- " def enterEvent(self, event):\n",
- " self.setCursor(QtCore.Qt.PointingHandCursor)\n",
- "\n",
- " def mousePressEvent(self, event):\n",
- " self.opacity1 = QtWidgets.QGraphicsOpacityEffect()\n",
- " self.presentationWindow.setGraphicsEffect(self.opacity1)\n",
- " self.anim1 = QtCore.QPropertyAnimation(self.opacity1, b\"opacity\")\n",
- " self.anim1.setDuration(250)\n",
- " self.anim1.setStartValue(1.0)\n",
- " self.anim1.setEndValue(0.0)\n",
- " self.anim1.start()\n",
- " self.anim1.finished.connect(self.presentationWindowIsInvisible)\n",
- " \n",
- " def presentationWindowIsInvisible(self):\n",
- " self.presentationWindow.hide()\n",
- " self.opacity2 = QtWidgets.QGraphicsOpacityEffect()\n",
- " self.mainFrame.setGraphicsEffect(self.opacity2)\n",
- " self.mainFrame.setWindowOpacity(0.0)\n",
- " self.mainFrame.show()\n",
- " self.anim2 = QtCore.QPropertyAnimation(self.opacity2, b\"opacity\")\n",
- " self.anim2.setDuration(250)\n",
- " self.anim2.setStartValue(0.0)\n",
- " self.anim2.setEndValue(1.0)\n",
- " self.anim2.start()\n",
- " self.anim2.finished.connect(self.mainFrameIsVisible)\n",
- " \n",
- " def mainFrameIsVisible(self):\n",
- " self.mainFrame.enterWindow = EnterWindow()\n",
- " self.mainFrame.loadDatabase()\n",
- " self.mainFrame.enterWindow.uploadUsers()\n",
- " self.mainFrame.offerToEnter()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [],
- "source": [
- "class PresentationWindow(QtWidgets.QLabel):\n",
- " slideWidth = 1138 # Ширина одного слайда\n",
- " slideHeight = 500 # Высота одного слайда\n",
- " slidesCount = 3 # Количество слайдов\n",
- " movingTime = 750 # Скорость прокрутки слайдов в миллисекундах\n",
- "\n",
- " def __init__(self, mainWindow=None, mainFrame=None):\n",
- " super().__init__(mainWindow) # Экземпляр класса PresentationWindow будет дочерним относительно родителя mainWindow\n",
- " self.mainFrame = mainFrame\n",
- "\n",
- " self.setFixedSize(1200, 640) # Задаем фиксированный размер для презентации\n",
- " self.setAlignment(QtCore.Qt.AlignCenter) # Устанавливаем его в центр окна\n",
- "\n",
- " self.content = QtWidgets.QVBoxLayout(self) # Задаем вертикальный макет для содержания презентации\n",
- " self.scrollArea = QtWidgets.QScrollArea() # Область с прокруткой для перелистывания слайдов\n",
- " self.slides = [QtWidgets.QLabel() for i in range(self.slidesCount)] # Сами слайды (имеют тип QLabel)\n",
- " self.slidesPacket = QtWidgets.QLabel()\n",
- " self.slidesLayout = QtWidgets.QHBoxLayout(self.slidesPacket) # Горизонтальный макет для слайдов\n",
- " self.buttonHBox = QtWidgets.QHBoxLayout() # Горизонтальный макет для radio-кнопок\n",
- "\n",
- " for i in range(self.slidesCount):\n",
- " # Позволим пользователю выделять текст:\n",
- " slide = self.slides[i]\n",
- " # Пишем текст в i-ый слайд:\n",
- " if i == 0:\n",
- " slide.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse | QtCore.Qt.TextSelectableByKeyboard)\n",
- " slide.setText(\"<img src='Images/icon.png' /><br><br>Добро пожаловать в программу <b>NeuralNetworks</b>, которая<br>научит вас программировать искусственные нейросети на языке Python!\")\n",
- " elif i == 1:\n",
- " slide.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse | QtCore.Qt.TextSelectableByKeyboard)\n",
- " slide.setText(\"<b>NeuralNetworks</b> содержит в себе видео-уроки, теорию, тесты<br>и интерпретатор языка программирования <b>Python</b> для написания собственных программ!<br>Результаты заданий буду сохраняться в одну локальную базу данных формата <b>SQLite</b>, которая будет<br>хранить в себе <b>весь прогресс</b> и <b>весь код ваших программ</b>.\")\n",
- " else:\n",
- " self.goBox = QtWidgets.QVBoxLayout(slide)\n",
- " self.goLink = GoLink(\"<b>Давайте приступим...</b>\", self, self.mainFrame)\n",
- " self.goBox.addStretch(1)\n",
- " self.goBox.addWidget(self.goLink)\n",
- " self.goBox.addStretch(1)\n",
- " slide.setAlignment(QtCore.Qt.AlignCenter) # Устанавливаем текст слайда по центру\n",
- " slide.setFixedWidth(self.slideWidth) # Задаем ширину для слайда\n",
- " slide.setObjectName(\"slide\")\n",
- " self.slidesLayout.addWidget(slide) # Добавляем данный слайд в макет\n",
- " # Устанавливаем размер пакета со всеми слайдами:\n",
- " self.slidesPacket.setFixedSize(self.slideWidth * self.slidesCount, self.slideHeight)\n",
- " self.slidesPacket.setObjectName(\"slidesPacket\")\n",
- "\n",
- " self.scrollArea.setObjectName(\"slides\")\n",
- " self.scrollArea.setWidget(self.slidesPacket) # Задаем виджет (QLabel)slidesPacket для области прокрутки\n",
- " self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) # Скрываем полосу прокрутки\n",
- " self.scrollArea.horizontalScrollBar().valueChanged.connect(self.scrollAreaWheelEvent)\n",
- "\n",
- " self.buttonHBox.addStretch(1) # Мы добавим отступы в начале и в конце для кнопок, чтобы они были по середине\n",
- " self.buttons = [QtWidgets.QRadioButton(self) for i in range(self.slidesCount)]\n",
- " self.buttons[0].setChecked(True) # Первый слайд будет виден сначала\n",
- " for button in self.buttons:\n",
- " button.clicked.connect(self.slideToggle)\n",
- " self.buttonHBox.addWidget(button)\n",
- " self.buttonHBox.addStretch(1)\n",
- "\n",
- " # Заполняем содержимое:\n",
- " self.content.addWidget(self.scrollArea)\n",
- " self.content.addLayout(self.buttonHBox)\n",
- "\n",
- " def slideToggle(self, isChecked):\n",
- " if isChecked:\n",
- " # Анимируем горизонтальную прокрутку:\n",
- " self.anim = QtCore.QPropertyAnimation(self.scrollArea.horizontalScrollBar(), b\"value\")\n",
- " self.anim.setDuration(self.movingTime)\n",
- " self.anim.setEasingCurve(QtCore.QEasingCurve.InOutExpo)\n",
- " i = 0\n",
- " for i in range(self.slidesCount):\n",
- " if self.buttons[i].isChecked():\n",
- " break\n",
- " self.anim.setEndValue(self.scrollArea.horizontalScrollBar().pageStep() * i)\n",
- " self.anim.start()\n",
- "\n",
- " def scrollAreaWheelEvent(self, value):\n",
- " k = value / (self.scrollArea.horizontalScrollBar().pageStep() * self.slidesCount)\n",
- " i = 0\n",
- " for i in range(self.slidesCount):\n",
- " if self.buttons[i].isChecked():\n",
- " break\n",
- " j = int(math.ceil(k * self.slidesCount - 0.5))\n",
- " if j != i:\n",
- " self.buttons[j].setChecked(True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [],
- "source": [
- "class MainWindow(QtWidgets.QWidget):\n",
- " sourceSize = QtCore.QSize(1280, 768)\n",
- "\n",
- " def __init__(self):\n",
- " super().__init__()\n",
- "\n",
- " # Создаем произвольное окно с задним фоном:\n",
- " self.setWindowTitle(\"NeuralNetworks\")\n",
- " self.icon = QtGui.QIcon(\"Images/icon.png\")\n",
- " self.setWindowIcon(self.icon)\n",
- " self.resize(self.sourceSize)\n",
- " # Центруем окно по экрану:\n",
- " self.desktop = QtWidgets.QApplication.desktop()\n",
- " x = (self.desktop.width() - self.width()) // 2\n",
- " y = (self.desktop.height() - self.height()) // 2\n",
- " self.move(x, y)\n",
- "\n",
- " self.hbox = QtWidgets.QHBoxLayout(self)\n",
- " self.hbox.setContentsMargins(0, 0, 0, 0)\n",
- " self.mainFrame = MainFrame(self)\n",
- " self.mainFrame.resize(self.sourceSize)\n",
- " self.mainFrame.hide()\n",
- " self.hbox.addWidget(self.mainFrame)\n",
- "\n",
- " self.presentationWindow = PresentationWindow(self, self.mainFrame)\n",
- " self.hbox.addWidget(self.presentationWindow)\n",
- "\n",
- " self.keyEsc = QtWidgets.QShortcut(QtCore.Qt.Key_Escape, self)\n",
- " self.keyEsc.activated.connect(self.pressedKeyEsc)\n",
- "\n",
- " self.keyF11 = QtWidgets.QShortcut(QtCore.Qt.Key_F11, self)\n",
- " self.keyF11.activated.connect(self.pressedKeyF11)\n",
- "\n",
- " def resizeEvent(self, event):\n",
- " self.mainFrame.resize(self.size())\n",
- "\n",
- " def paintEvent(self, event):\n",
- " painter = QtGui.QPainter(self)\n",
- " painter.drawPixmap(0, 0, self.width(), self.height(), QtGui.QPixmap(\"Images/background.jpg\"))\n",
- "\n",
- " def closeEvent(self, event):\n",
- " if currentUser is not None:\n",
- " msgBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Question,\n",
- " \"Закрыть программу\",\n",
- " \"Вы действительно хотите выйти из программы? Все данные будут сохранены.\",\n",
- " QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)\n",
- " msgBox.setDefaultButton(QtWidgets.QMessageBox.No)\n",
- " if msgBox.exec() == QtWidgets.QMessageBox.Yes:\n",
- " QtWidgets.QApplication.closeAllWindows()\n",
- " event.accept()\n",
- " else:\n",
- " event.ignore()\n",
- " else:\n",
- " QtWidgets.QApplication.quit()\n",
- "\n",
- " def pressedKeyEsc(self):\n",
- " self.close()\n",
- "\n",
- " def pressedKeyF11(self):\n",
- " if self.isFullScreen():\n",
- " self.showNormal()\n",
- " else:\n",
- " self.showFullScreen()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "app = QtWidgets.QApplication(sys.argv)\n",
- "\n",
- "qss = open(\"stylesheet.css\")\n",
- "app.setStyleSheet(qss.read())\n",
- "qss.close()\n",
- "\n",
- "mainWindow = MainWindow()\n",
- "mainWindow.show()\n",
- "\n",
- "code = app.exec_()\n",
- "sys.exit(code)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.6.4"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 2
- }
Add Comment
Please, Sign In to add comment