diff --git a/Course.py b/Course.py new file mode 100644 index 0000000..523171f --- /dev/null +++ b/Course.py @@ -0,0 +1,125 @@ +class Course: + def __init__(self, course_initial, course_name, section_number, total_seat, department_name, department_initial, + faculty_name, faculty_initial, exam_date, exam_day, theory_1_day, theory_1_time, theory_2_day=None, + theory_2_time=None): + self.course_initial = course_initial + self.course_name = course_name + self.section_number = section_number + self.total_seat = total_seat + if self.total_seat is None: + self.total_seat = 0 + self.department_name = department_name + self.department_initial = department_initial + self.faculty_name = faculty_name + self.faculty_initial = faculty_initial + + # exam + self.exam_date = exam_date + e_day = exam_day.split('(')[0] + if e_day[-1] == ' ': + self.exam_day = e_day[0:len(e_day) - 1] + else: + self.exam_day = e_day + e_time = exam_day.split('(')[-1] + e_time = e_time[0:len(e_time) - 1] + self.exam_time_start = e_time.split('-')[0] + self.exam_time_end = e_time.split('-')[1] + + # Theory + self.theory_1_day = theory_1_day + + if len(theory_1_time) == 51: + temp_time = theory_1_time[17:34] + self.theory_1_time_start = temp_time.split('-')[0] + self.theory_1_time_end = temp_time.split('-')[1] + self.setLab(self.theory_1_day, theory_1_time[:17]+theory_1_time[34:], None, None) + elif len(theory_1_time) == 34: + self.theory_1_time_start = theory_1_time[0:17].split('-')[0] + self.theory_1_time_end = theory_1_time[0:17].split('-')[1] + theory_2_day = self.theory_1_day + theory_2_time = theory_1_time[0:17] + else: + self.theory_1_time_start = theory_1_time.split('-')[0] + self.theory_1_time_end = theory_1_time.split('-')[1] + + if theory_2_day is None: + self.theory_2_day = False + self.theory_2_time_start = False + self.theory_2_time_end = False + else: + self.theory_2_day = theory_2_day + + if len(theory_2_time) == 51: + temp_time = theory_2_time[17:34] + self.theory_2_time_start = temp_time.split('-')[0] + self.theory_2_time_end = temp_time.split('-')[1] + self.setLab(self.theory_2_day, theory_2_time[:17]+theory_1_time[34:], None, None) + elif len(theory_2_time) == 34: + self.setLab(self.theory_2_day, theory_2_time, None, None) + self.theory_2_day = False + self.theory_2_time_start = False + self.theory_2_time_end = False + else: + self.theory_2_time_start = theory_2_time.split('-')[0] + self.theory_2_time_end = theory_2_time.split('-')[1] + + self.labAvailable = False + self.lab_1_day = None + self.lab_2_day = None + self.lab_1_time_start = None + self.lab_1_time_end = None + self.lab_2_time_start = None + self.lab_2_time_end = None + self.booked_seat = 0 + self.available_seat = self.total_seat + + def setLab(self, day1, time1, day2, time2): + self.labAvailable = True + self.lab_1_day = day1 + if len(time1) > 20: + self.lab_2_day = day1 + new_time_1 = time1[0:17] + new_time_2 = time1[17:] + self.lab_1_time_start = new_time_1.split('-')[0] + self.lab_1_time_end = new_time_1.split('-')[1] + self.lab_2_time_start = new_time_2.split('-')[0] + self.lab_2_time_end = new_time_2.split('-')[1] + if ((int(self.lab_1_time_start[:2]) * 60) + int(self.lab_1_time_start[3:5])) > ( + (int(self.lab_2_time_start[:2]) * 60) + int(self.lab_2_time_start[3:5])): + self.lab_1_day, self.lab_2_day = (self.lab_2_day, self.lab_1_day) + self.lab_1_time_start, self.lab_2_time_start = (self.lab_2_time_start, self.lab_1_time_start) + self.lab_1_time_end, self.lab_2_time_end = (self.lab_2_time_end, self.lab_1_time_end) + else: + self.lab_1_time_start = time1.split('-')[0] + self.lab_1_time_end = time1.split('-')[1] + if day2 is not None: + self.lab_2_day = day2 + self.lab_2_time_start = time2.split('-')[0] + self.lab_2_time_end = time2.split('-')[1] + if ((int(self.lab_1_time_start[:2]) * 60) + int(self.lab_1_time_start[3:5])) > ( + (int(self.lab_2_time_start[:2]) * 60) + int(self.lab_2_time_start[3:5])): + self.lab_1_day, self.lab_2_day = (self.lab_2_day, self.lab_1_day) + self.lab_1_time_start, self.lab_2_time_start = (self.lab_2_time_start, self.lab_1_time_start) + self.lab_1_time_end, self.lab_2_time_end = (self.lab_2_time_end, self.lab_1_time_end) + + def setSeatStatus(self, booked_seat): + self.booked_seat = booked_seat + self.available_seat = int(self.total_seat) - int(self.booked_seat) + + def __str__(self): + if self.total_seat == 0: + if self.theory_2_day: + return f"{self.course_initial} [{self.section_number}] - {self.faculty_initial} - SL: N/A - T: {self.theory_1_day[0:2]},{self.theory_2_day[0:2]} ({self.theory_1_time_start}-{self.theory_1_time_end})" + else: + return f"{self.course_initial} [{self.section_number}] - {self.faculty_initial} - SL: N/A - T: {self.theory_1_day[0:2]} ({self.theory_1_time_start}-{self.theory_1_time_end})" + else: + if self.theory_2_day: + return f"{self.course_initial} [{self.section_number}] - {self.faculty_initial} - SL: {self.available_seat} - T: {self.theory_1_day[0:2]},{self.theory_2_day[0:2]} ({self.theory_1_time_start}-{self.theory_1_time_end})" + else: + return f"{self.course_initial} [{self.section_number}] - {self.faculty_initial} - SL: {self.available_seat} - T: {self.theory_1_day[0:2]} ({self.theory_1_time_start}-{self.theory_1_time_end})" + + def table_string(self): + return f'{self.course_initial} [{self.section_number}] - {self.faculty_initial}' + + def advance_string(self): + return f'{self.course_initial} {self.course_name} {self.section_number} {self.total_seat} {self.department_name} {self.department_initial} {self.faculty_name} {self.faculty_initial} {self.exam_date} {self.exam_day} {self.exam_time_start} {self.exam_time_end} {self.theory_1_day} {self.theory_1_time_start} {self.theory_1_time_end} {self.theory_2_day} {self.theory_2_time_start} {self.theory_2_time_end} {self.lab_1_day} {self.lab_1_time_start} {self.lab_1_time_end} {self.lab_2_day} {self.lab_2_time_start} {self.lab_2_time_end} {self.booked_seat} {self.available_seat}' \ No newline at end of file diff --git a/ObjectBuilder.py b/ObjectBuilder.py new file mode 100644 index 0000000..37a01be --- /dev/null +++ b/ObjectBuilder.py @@ -0,0 +1,25 @@ +from PyQt6 import QtCore, QtGui + + +def object_builder(obj, coordinate, text=None, font_size=None, isBold=False, css="", connected=None, mousePointer=None, tooltip=None): + item = obj + item.setGeometry(QtCore.QRect(coordinate[0], coordinate[1], coordinate[2], coordinate[3])) + if text is not None: + if str(type(obj)) != "": + item.setText(text) + else: + item.setPlaceholderText(text) + if font_size is not None: + font = QtGui.QFont() + font.setPointSize(font_size) + font.setBold(isBold) + item.setFont(font) + item.setStyleSheet(css) + if connected is not None: + item.clicked.connect(connected) + if mousePointer is not None: + item.setCursor(mousePointer) + if tooltip is not None: + item.setToolTip(tooltip) + + return item diff --git a/README.md b/README.md new file mode 100644 index 0000000..7123df9 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +Check your pre advising time clash in advance with this application \ No newline at end of file diff --git a/advance.py b/advance.py new file mode 100644 index 0000000..9fc60c0 --- /dev/null +++ b/advance.py @@ -0,0 +1,845 @@ +import webbrowser +from PyQt6 import QtCore, QtWidgets, QtGui +from PyQt6.QtCore import Qt +from PyQt6.QtGui import QCursor +from PyQt6.QtWidgets import QMessageBox, QTableWidgetItem, QListWidgetItem +from ObjectBuilder import object_builder +from internetChecker import internet_checker +from Course import Course +from seatStatusThread import jsonThread, loggedInThread + + +def myNameClicked(): + webbrowser.open_new('https://www.facebook.com/ShariarShuvo01/') + + +def githubClicked(): + webbrowser.open_new('https://github.com/ShariarShuvo1/bracu-pre-advising-checker') + + +def listUpdate(listName, searchBar): + text = searchBar.text() + for element in range(len(listName)): + item = listName.item(element) + if text.lower() not in item.text().lower(): + item.setHidden(True) + else: + item.setHidden(False) + + +def isChecked(check_mark): + return check_mark.checkState() == Qt.CheckState.Checked + + +def showWarning(text: str): + msg = QMessageBox() + msg.resize(400, 170) + msg.setMinimumSize(QtCore.QSize(400, 170)) + msg.setBaseSize(QtCore.QSize(400, 170)) + msg.setIcon(msg.Icon.Warning) + msg.setText(text) + msg.setWindowTitle("Invalid Course") + msg.setStandardButtons(msg.StandardButton.Close) + msg.exec() + + +class Ui_AdvanceWindow(object): + def __init__(self): + self.github = None + self.my_name = None + self.seats_data = None + self.table: QtWidgets.QTableWidget = None + self.advanceSearch: QtWidgets.QCheckBox = None + self.item_exist = None + self.founded_item: Course = None + self.bound = None + self.course_list = [] + self.json = None + self.jsonThreadParser = None + self.font_size = None + self.unitWidth = None + self.unitHeight = None + self.width = None + self.height = None + self.labClash: QtWidgets.QCheckBox = None + self.theoryClash: QtWidgets.QCheckBox = None + self.examClash: QtWidgets.QCheckBox = None + self.pointingHandMouse = QCursor(Qt.CursorShape.PointingHandCursor) + self.disableAllRestriction: QtWidgets.QCheckBox = None + self.sameCourse: QtWidgets.QCheckBox = None + self.seatLimit: QtWidgets.QCheckBox = None + self.reloadButton: QtWidgets.QPushButton = None + self.right_search: QtWidgets.QLineEdit = None + self.left_search: QtWidgets.QLineEdit = None + self.details_listViewer: QtWidgets.QListWidget = None + self.clearButton: QtWidgets.QPushButton = None + self.removeButton: QtWidgets.QPushButton = None + self.addButton: QtWidgets.QPushButton = None + self.right_listViewer: QtWidgets.QListWidget = None + self.left_listViewer: QtWidgets.QListWidget = None + self.backButton: QtWidgets.QPushButton = None + self.advance_ui = None + self.htmlThreadParser = None + self.centralwidget = None + self.MainWindow = None + self.AdvanceWindow = None + self.html = None + + def labUpdate(self, item): + day_name = {11: "Sunday", 12: "Monday", 13: "Tuesday", 14: "Wednesday", 15: "Thursday", 16: "Friday", + 17: "Saturday"} + day1 = None + time1 = None + day2 = None + time2 = None + for i in range(11, len(item)): + if item[i] is not None and day1 is None: + day1 = day_name[i] + time1 = item[i] + elif item[i] is not None: + day2 = day_name[i] + time2 = item[i] + for course in self.course_list: + if course.course_initial == item[1] and course.section_number == item[3]: + course.setLab(day1, time1, day2, time2) + break + + def createCourse(self): + self.json = self.json['rows'] + for element in self.json: + item = element['cell'] + if item[10] is not None: + day_name = {11: "Sunday", 12: "Monday", 13: "Tuesday", 14: "Wednesday", 15: "Thursday", 16: "Friday", + 17: "Saturday"} + day1 = None + time1 = None + day2 = None + time2 = None + for i in range(11, len(item)): + if item[i] is not None and day1 is None: + day1 = day_name[i] + time1 = item[i] + elif item[i] is not None: + day2 = day_name[i] + time2 = item[i] + self.course_list.append( + Course(item[1], item[2], item[3], item[4], item[5], item[6], item[7], item[8], item[9], item[10], + day1, time1, day2, time2)) + else: + self.labUpdate(item) + + def updateSeatStatus(self): + inserted_count = 0 + self.seats_data = self.seats_data['rows'] + for element in self.seats_data: + item = element['cell'] + name = item[2] + section = item[7] + seat_booked = item[9] + if len(seat_booked) == 0: + seat_booked = 0 + for course in self.course_list: + if name == course.course_initial and section == course.section_number: + course.setSeatStatus(seat_booked) + inserted_count += 1 + break + print(len(self.course_list) - inserted_count) + + def download(self): + self.AdvanceWindow.setCursor(QCursor(Qt.CursorShape.BusyCursor)) + self.jsonThreadParser = jsonThread() + self.jsonThreadParser.setter( + "https://usis.bracu.ac.bd/academia/academicSection/listAcademicSectionWithSchedule?academiaSession=627122&_search=false&nd=1692364983604&rows=-1&page=1&sidx=course_code&sord=asc", + self.advance_ui, self.session) + self.jsonThreadParser.start() + + def FoundSeatData(self): + self.AdvanceWindow.setCursor(QCursor(Qt.CursorShape.ArrowCursor)) + self.updateSeatStatus() + self.add_to_list() + + def FoundJson(self): + self.createCourse() + self.htmlThreadParser = loggedInThread() + self.htmlThreadParser.setter( + "https://usis.bracu.ac.bd/academia/studentCourse/showCourseStatusList?query=&academiaSession=627122&_search=false&nd=1692363291093&rows=-1&page=1&sidx=id&sord=desc", + self.advance_ui, self.session) + self.htmlThreadParser.start() + + def find_row_number(self, time_string): + for i in range(self.table.rowCount()): + if self.table.verticalHeaderItem(i).text() == time_string: + return i + + def find_column_number(self, day): + for i in range(self.table.columnCount()): + if self.table.horizontalHeaderItem(i).text() == f' {day} ': + return i + + def get_row_col(self, time1, time2, day): + time_string = f'{time1} - \n{time2}' + row = self.find_row_number(time_string) + column = self.find_column_number(day) + return [row, column] + + def setting_table(self, row, column, txt: str): + temp_txt = self.table.item(row, column) + if temp_txt is None: + temp = QTableWidgetItem(txt) + temp.setForeground(QtGui.QColor('yellow')) + self.table.setItem(row, column, temp) + self.table.showRow(row) + else: + temp = QTableWidgetItem(f'{temp_txt.text()}\n{txt}') + temp.setForeground(QtGui.QColor('red')) + self.table.setItem(row, column, temp) + self.table.showRow(row) + + def resize_table(self): + self.table.resizeColumnsToContents() + self.table.resizeRowsToContents() + + def add_to_table(self, list_text): + current_course: Course = self.find_course_by_string(list_text) + if current_course.theory_1_day is not None: + row, column = self.get_row_col(current_course.theory_1_time_start, current_course.theory_1_time_end, + current_course.theory_1_day) + self.setting_table(row, column, current_course.table_string()) + if current_course.theory_2_day is not False: + row, column = self.get_row_col(current_course.theory_2_time_start, current_course.theory_2_time_end, + current_course.theory_2_day) + self.setting_table(row, column, current_course.table_string()) + if current_course.lab_1_day is not None: + row, column = self.get_row_col(current_course.lab_1_time_start, current_course.lab_1_time_end, + current_course.lab_1_day) + self.setting_table(row, column, current_course.table_string().split(' - ')[0] + ' - LAB') + if current_course.lab_2_day is not None: + row, column = self.get_row_col(current_course.lab_2_time_start, current_course.lab_2_time_end, + current_course.lab_2_day) + self.setting_table(row, column, current_course.table_string().split(' - ')[0] + ' - LAB') + self.resize_table() + + def add_to_list(self): + for course in self.course_list: + self.left_listViewer.addItem(str(course)) + + def setupBody(self): + if internet_checker(): + self.download() + + self.font_size = int(0.8 * self.unitWidth) + + # Back Button + self.backButton = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), + (int(self.unitWidth * 0.5), 1, self.unitWidth * 6, self.unitHeight * 4), + "<- BACK", self.font_size, False, + "QPushButton::!hover { border: 1px solid white; background-color: rgba(0, 0, 0, 0);} QPushButton::hover {border : 1px solid red; background-color: rgba(0, 0, 0, 0);};", + self.backButtonClicked, self.pointingHandMouse, "Return to home page") + + # Restart Button + self.reloadButton = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), ( + int((self.unitWidth * 6.5) + (self.unitWidth * 0.5)), 1, self.unitWidth * 6, self.unitHeight * 4), "Reload", + self.font_size, False, + "QPushButton::!hover { border: 1px solid white; background-color: rgba(0, 0, 0, 0);} QPushButton::hover {border : 1px solid green; background-color: rgba(0, 0, 0, 0);};", + self.reloadButtonClicked, self.pointingHandMouse, + "Reload the data from USIS. This will clear all of your list") + + # Disable Seat Limit + self.seatLimit = object_builder(QtWidgets.QCheckBox(parent=self.centralwidget), ( + int((self.unitWidth * 13) + (self.unitWidth * 0.5)), 1, self.unitWidth * 10, self.unitHeight * 4), + "Disable Seat Limit", self.font_size, False, + "border: 1px solid white; background-color: rgba(0, 0, 0, 0);", + self.seatLimitClicked, self.pointingHandMouse, + "You will be able to select sections which does not have any seat left") + + # Allow Same Course + self.sameCourse = object_builder(QtWidgets.QCheckBox(parent=self.centralwidget), ( + int((self.unitWidth * 23.5) + (self.unitWidth * 0.5)), 1, self.unitWidth * 11, self.unitHeight * 4), + "Allow Same Course", self.font_size, False, + "border: 1px solid white; background-color: rgba(0, 0, 0, 0);", + self.sameCourseClicked, self.pointingHandMouse, + "You will be able to select same course multiple times") + + # Allow Exam Clash + self.examClash = object_builder(QtWidgets.QCheckBox(parent=self.centralwidget), ( + int((self.unitWidth * 35) + (self.unitWidth * 0.5)), 1, self.unitWidth * 10, self.unitHeight * 4), + "Allow Exam Clash", self.font_size, False, + "border: 1px solid white; background-color: rgba(0, 0, 0, 0);", + self.examClashClicked, self.pointingHandMouse, + "You will be able to select courses with same exam date") + + # Allow Theory Clash + self.theoryClash = object_builder(QtWidgets.QCheckBox(parent=self.centralwidget), ( + int((self.unitWidth * 45.5) + (self.unitWidth * 0.5)), 1, self.unitWidth * 11, self.unitHeight * 4), + "Allow Theory Clash", self.font_size, False, + "border: 1px solid white; background-color: rgba(0, 0, 0, 0);", + self.theoryClashClicked, self.pointingHandMouse, + "You will be able to select courses with same theory schedule") + + # Allow Lab Clash + self.labClash = object_builder(QtWidgets.QCheckBox(parent=self.centralwidget), ( + int((self.unitWidth * 57) + (self.unitWidth * 0.5)), 1, self.unitWidth * 11, self.unitHeight * 4), + "Allow Lab Clash", self.font_size, False, + "border: 1px solid white; background-color: rgba(0, 0, 0, 0);", + self.labClashClicked, self.pointingHandMouse, + "You will be able to select courses with same lab schedule") + self.labClash.setChecked(True) + + # Disable all restriction + self.disableAllRestriction = object_builder(QtWidgets.QCheckBox(parent=self.centralwidget), ( + int((self.unitWidth * 68.5) + (self.unitWidth * 0.5)), 1, self.unitWidth * 12, self.unitHeight * 4), + "Disable All Restriction", self.font_size, False, + "border: 1px solid white; background-color: rgba(0, 0, 0, 0);", + self.disableAllRestrictionClicked, self.pointingHandMouse, + "There will be no restriction to add courses") + + # Advance Search + self.advanceSearch = object_builder(QtWidgets.QCheckBox(parent=self.centralwidget), ( + int((self.unitWidth * 81) + (self.unitWidth * 0.5)), 1, self.unitWidth * 9, self.unitHeight * 4), + "Advance Search", self.font_size, False, + "border: 1px solid white; background-color: rgba(0, 0, 0, 0);", + self.advanceSearchClicked, self.pointingHandMouse, + "You will be able to filter data using keyword") + + # Left Search Bar + self.left_search: QtWidgets.QLineEdit = object_builder(QtWidgets.QLineEdit(parent=self.centralwidget), ( + int(self.unitWidth * 0.5), int(self.unitHeight * 5), int(self.unitWidth * 15), int(self.unitHeight * 4)), + "Search", self.font_size + 5, False, + "QLineEdit{border:1px solid white; color: white}") + self.left_search.textEdited.connect(self.leftSearchChanged) + + # Left List Viewer + self.left_listViewer: QtWidgets.QListWidget = object_builder(QtWidgets.QListWidget(parent=self.centralwidget), ( + int(self.unitWidth * 0.5), int(self.unitHeight * 10), int(self.unitWidth * 15), + int((self.unitHeight * 100) - (self.unitHeight * 11))), None, self.font_size, False, + "QListWidget{border:1px solid white; alternate-background-color: #232323;background-color: black;};") + self.left_listViewer.setAlternatingRowColors(True) + self.left_listViewer.itemSelectionChanged.connect(self.left_listViewer_selection_changed) + + # # Add Button + self.addButton = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), ( + int(self.unitWidth * 16), int(self.unitHeight * 10), int(self.unitWidth * 6), int(self.unitHeight * 4)), + "Add ->", self.font_size, True, + "QPushButton{border:1px solid yellow} QPushButton::hover{border:1px solid green; color:green}", + self.addButtonClicked, self.pointingHandMouse, + "Add the selected course to your list") + + # Remove Button + self.removeButton = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), ( + int(self.unitWidth * 16), int(self.unitHeight * 14.5), int(self.unitWidth * 6), int(self.unitHeight * 4)), + "<- Remove", self.font_size, True, + "QPushButton{border:1px solid yellow} QPushButton::hover{border:1px solid magenta; color: magenta}", + self.removeButtonClicked, self.pointingHandMouse, + "Remove the course from your list") + # + # Clear All Button + self.clearButton = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), ( + int(self.unitWidth * 16), int(self.unitHeight * 19), int(self.unitWidth * 6), int(self.unitHeight * 4)), + "Clear -X", self.font_size, True, + "QPushButton{border:1px solid yellow} QPushButton::hover{border:1px solid red; color:red}", + self.clearButtonClicked, self.pointingHandMouse, + "Remove all the course from your list") + + # Right Search Bar + self.right_search: QtWidgets.QLineEdit = object_builder(QtWidgets.QLineEdit(parent=self.centralwidget), ( + int(self.unitWidth * 22.5), int(self.unitHeight * 5), int(self.unitWidth * 15), int(self.unitHeight * 4)), + "Search", self.font_size + 5, False, + "QLineEdit{border:1px solid white; color: white}") + self.right_search.textEdited.connect(self.rightSearchChanged) + + # Right List Viewer + self.right_listViewer = object_builder(QtWidgets.QListWidget(parent=self.centralwidget), ( + int(self.unitWidth * 22.5), int(self.unitHeight * 10), int(self.unitWidth * 15), int(self.unitHeight * 25)), + None, self.font_size, False, + "QListWidget{border:1px solid white; alternate-background-color: #232323;background-color: black;};") + self.right_listViewer.setAlternatingRowColors(True) + self.right_listViewer.itemSelectionChanged.connect(self.right_listViewer_selection_changed) + + # Details Viewer + self.details_listViewer: QtWidgets.QListWidget = object_builder( + QtWidgets.QListWidget(parent=self.centralwidget), ( + int(self.unitWidth * 22.5), int(self.unitHeight * 36), int(self.unitWidth * 15), + int((self.unitHeight * 100) - (self.unitHeight * 37))), None, self.font_size, False, + "QListWidget{border:1px solid white; color:white; alternate-background-color: #232323;background-color: black;};") + self.details_listViewer.setAlternatingRowColors(True) + self.setupSchedule() + + self.my_name = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), ( + int(self.unitWidth * 38), int((self.unitHeight * 100) - (self.unitHeight * 10)) + int(self.unitHeight * 5), + int(self.unitWidth * 15), int(self.unitHeight * 2)), "Created By: Shariar Islam Shuvo", self.font_size, + False, + "QPushButton::hover{color:red}", myNameClicked, self.pointingHandMouse, + "Click to visit my Facebook Profile") + self.github = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), ( + int(self.unitWidth * 55), int((self.unitHeight * 100) - (self.unitHeight * 10)) + int(self.unitHeight * 5), + int(self.unitWidth * 6), int(self.unitHeight * 2)), "GitHub", self.font_size, False, + "QPushButton::hover{color:red}", githubClicked, self.pointingHandMouse, + "Click to visit GitHub repo for this project") + + def setupSchedule(self): + self.table = QtWidgets.QTableWidget(parent=self.centralwidget) + self.table.setGeometry(QtCore.QRect(int(self.unitWidth * 38), int(self.unitHeight * 5), + int((self.unitWidth * 100) - (self.unitWidth * 39)), + int((self.unitHeight * 100) - (self.unitHeight * 10)))) + self.table.setRowCount(26) + self.table.setColumnCount(7) + + days = [" Saturday ", " Sunday ", " Monday ", " Tuesday ", " Wednesday ", " Thursday ", " Friday "] + times = ['08:00 AM - \n09:20 AM', '08:00 AM - \n11:05 AM', '09:00 AM - \n09:55 AM', '09:00 AM - \n12:00 PM', + '09:00 AM - \n12:05 PM', '09:00 AM - \n01:10 PM', '09:30 AM - \n10:50 AM', '10:05 AM - \n11:00 AM', + '11:00 AM - \n12:20 PM', '11:00 AM - \n01:30 AM', '11:10 AM - \n12:05 PM', '12:15 PM - \n01:10 PM', + '12:30 PM - \n01:30 PM', '12:30 PM - \n01:50 PM', '01:20 PM - \n02:15 PM', '02:00 PM - \n02:55 PM', + '02:00 PM - \n03:20 PM', '02:00 PM - \n04:00 PM', '02:00 PM - \n05:05 PM', '03:05 PM - \n04:00 PM', + '03:30 PM - \n04:50 PM', '04:10 PM - \n05:05 PM', '05:00 PM - \n06:20 PM', '05:00 PM - \n06:30 PM', + '05:05 PM - \n06:00 PM', '06:00 PM - \n09:00 PM'] + self.table.setHorizontalHeaderLabels(days) + self.table.setVerticalHeaderLabels(times) + self.table.setAlternatingRowColors(True) + for i in range(0, 26): + self.table.hideRow(i) + self.resize_table() + self.table.setDisabled(True) + + def setupUi(self, AdvanceWindow, MainWindow, advance_ui, session): + self.session = session + self.advance_ui = advance_ui + self.AdvanceWindow = AdvanceWindow + self.MainWindow = MainWindow + self.unitHeight = int(self.height / 100) + self.unitWidth = int(self.width / 100) + AdvanceWindow.resize(self.width, self.height) + AdvanceWindow.setMinimumSize(QtCore.QSize(self.width, self.height)) + AdvanceWindow.setBaseSize(QtCore.QSize(self.width, self.height)) + AdvanceWindow.setStyleSheet("background-color: black; color: yellow") + AdvanceWindow.setWindowTitle("Pre Advising Advance") + self.centralwidget = QtWidgets.QWidget(parent=AdvanceWindow) + + self.setupBody() + + # Initiate texts + AdvanceWindow.setCentralWidget(self.centralwidget) + QtCore.QMetaObject.connectSlotsByName(AdvanceWindow) + + def show_description(self, course_name, section): + current_course: Course = None + for course in self.course_list: + if course.course_initial == course_name and course.section_number == section: + current_course = course + break + self.details_listViewer.clear() + self.details_listViewer.addItem(f'Course Name: {current_course.course_name}') + self.details_listViewer.addItem(f'Course Code: {current_course.course_initial}') + self.details_listViewer.addItem(f'Section Number: {current_course.section_number}') + self.details_listViewer.addItem(f'Total Seat: {current_course.total_seat}') + self.details_listViewer.addItem(f'Booked Seat: {current_course.booked_seat}') + self.details_listViewer.addItem(f'Available Seat: {current_course.available_seat}') + self.details_listViewer.addItem(f'Faculty Name: {current_course.faculty_name}') + self.details_listViewer.addItem(f'Faculty Initial: {current_course.faculty_initial}') + self.details_listViewer.addItem(f'Department Name: {current_course.department_name}') + self.details_listViewer.addItem(f'Department Initial: {current_course.department_initial}') + self.details_listViewer.addItem("") + self.details_listViewer.addItem(f'Mid-Term Date: {current_course.exam_date}') + self.details_listViewer.addItem( + f'Mid-Term Time: ({current_course.exam_time_start} - {current_course.exam_time_end})') + self.details_listViewer.addItem(f'Mid-Term Day: {current_course.exam_day}') + self.details_listViewer.addItem("") + self.details_listViewer.addItem(f'Theory Class Day 1: {current_course.theory_1_day}') + self.details_listViewer.addItem( + f'Theory Class Day 1 Time: ({current_course.theory_1_time_start} - {current_course.theory_1_time_end})') + if current_course.theory_2_day is not None: + self.details_listViewer.addItem(f'Theory Class Day 2: {current_course.theory_2_day}') + self.details_listViewer.addItem( + f'Theory Class Day 2 Time: ({current_course.theory_2_time_start} - {current_course.theory_2_time_end})') + self.details_listViewer.addItem("") + if current_course.labAvailable: + if current_course.lab_2_day is not None: + self.details_listViewer.addItem(f'Lab Day: {current_course.lab_1_day}') + self.details_listViewer.addItem( + f'Lab Time First Half: ({current_course.lab_1_time_start} - {current_course.lab_1_time_end})') + self.details_listViewer.addItem( + f'Lab Time Second Half: ({current_course.lab_2_time_start} - {current_course.lab_2_time_end})') + else: + self.details_listViewer.addItem(f'Lab Day 1: {current_course.lab_1_day}') + self.details_listViewer.addItem( + f'Lab Day 1 Time: ({current_course.lab_1_time_start} - {current_course.lab_1_time_end})') + self.details_listViewer.addItem(f'Lab Day 2: {current_course.lab_2_day}') + self.details_listViewer.addItem( + f'Lab Time Second Half: ({current_course.lab_2_time_start} - {current_course.lab_2_time_end})') + + def find_course_by_string(self, item): + for course in self.course_list: + if str(course) == item: + return course + + def already_exist(self, element): + for i in range(len(self.left_listViewer)): + if self.left_listViewer.item(i).text() == element: + return True + return False + + def add_to_right_list(self, element): + self.right_listViewer.addItem(element) + self.add_to_table(element) + + def bound_checker(self, item): + self.founded_item: Course = self.find_course_by_string(item) + self.item_exist = self.already_exist(item) + self.bound = [True] * 5 + for i in range(len(self.right_listViewer)): + if self.right_listViewer.item(i).text() == item: + showWarning("You can not take same course section twice") + self.bound[0] = False + if False in self.bound: + return False + if not isChecked(self.seatLimit): + if self.founded_item.available_seat == 0 and self.founded_item.total_seat != 0: + showWarning("There are no seat left!") + self.bound[0] = False + if False in self.bound: + return False + if not isChecked(self.sameCourse): + temp_course = item.split()[0] + for i in range(len(self.right_listViewer)): + comp_course = self.right_listViewer.item(i).text().split()[0] + if temp_course == comp_course: + showWarning("Your already took this Course!") + self.bound[1] = False + break + if False in self.bound: + return False + if not isChecked(self.examClash): + for i in range(len(self.right_listViewer)): + temp_course = self.find_course_by_string(self.right_listViewer.item(i).text()) + if self.founded_item.exam_date == temp_course.exam_date and self.founded_item.exam_time_start == temp_course.exam_time_start: + showWarning(f"Your Exam Date Clashes with\n{temp_course}") + self.bound[2] = False + break + if False in self.bound: + return False + if not isChecked(self.theoryClash): + for i in range(len(self.right_listViewer)): + temp_course: Course = self.find_course_by_string(self.right_listViewer.item(i).text()) + temp_list = [temp_course.theory_1_day, temp_course.theory_1_time_start, temp_course.theory_1_time_end] + if self.founded_item.theory_1_day in temp_list and ( + self.founded_item.theory_1_time_start in temp_list or self.founded_item.theory_1_time_end in temp_list): + showWarning(f"Your Theory Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.theory_2_day is not None: + if self.founded_item.theory_2_day in temp_list and ( + self.founded_item.theory_2_time_start in temp_list or self.founded_item.theory_2_time_end in temp_list): + showWarning(f"Your Theory Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if temp_course.theory_2_day is not None: + temp_list = [temp_course.theory_2_day, temp_course.theory_2_time_start, + temp_course.theory_2_time_end] + if self.founded_item.theory_1_day in temp_list and ( + self.founded_item.theory_1_time_start in temp_list or self.founded_item.theory_1_time_end in temp_list): + showWarning(f"Your Theory Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.theory_2_day is not None: + if self.founded_item.theory_2_day in temp_list and ( + self.founded_item.theory_2_time_start in temp_list or self.founded_item.theory_2_time_end in temp_list): + showWarning(f"Your Theory Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if not self.bound[3]: + break + if False in self.bound: + return False + if not isChecked(self.labClash): + for i in range(len(self.right_listViewer)): + temp_course: Course = self.find_course_by_string(self.right_listViewer.item(i).text()) + temp_list = [temp_course.theory_1_day, temp_course.theory_1_time_start, temp_course.theory_1_time_end] + if self.founded_item.lab_1_day in temp_list and ( + self.founded_item.lab_1_time_start in temp_list or self.founded_item.lab_1_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.lab_2_day is not None: + if self.founded_item.lab_2_day in temp_list and ( + self.founded_item.lab_2_time_start in temp_list or self.founded_item.lab_2_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if temp_course.theory_2_day is not None: + temp_list = [temp_course.theory_2_day, temp_course.theory_2_time_start, + temp_course.theory_2_time_end] + if self.founded_item.lab_1_day in temp_list and ( + self.founded_item.lab_1_time_start in temp_list or self.founded_item.lab_1_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.lab_2_day is not None: + if self.founded_item.lab_2_day in temp_list and ( + self.founded_item.lab_2_time_start in temp_list or self.founded_item.lab_2_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + temp_list = [temp_course.lab_1_day, temp_course.lab_1_time_start, temp_course.lab_1_time_end] + if self.founded_item.lab_1_day in temp_list and ( + self.founded_item.lab_1_time_start in temp_list or self.founded_item.lab_1_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.lab_2_day is not None: + if self.founded_item.lab_2_day in temp_list and ( + self.founded_item.lab_2_time_start in temp_list or self.founded_item.lab_2_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if temp_course.theory_2_day is not None: + temp_list = [temp_course.lab_2_day, temp_course.lab_2_time_start, temp_course.lab_2_time_end] + if self.founded_item.lab_1_day in temp_list and ( + self.founded_item.lab_1_time_start in temp_list or self.founded_item.lab_1_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.lab_2_day is not None: + if self.founded_item.lab_2_day in temp_list and ( + self.founded_item.lab_2_time_start in temp_list or self.founded_item.lab_2_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if not self.bound[3]: + break + if False in self.bound: + return False + else: + return True + + def addButtonClicked(self): + item = self.left_listViewer.currentItem() + if item is not None: + item = item.text() + if isChecked(self.disableAllRestriction): + self.add_to_right_list(item) + elif self.bound_checker(item): + self.add_to_right_list(item) + + def removing_table(self, row, column, txt: str): + table_item = self.table.item(row, column) + if len(table_item.text()) == len(txt): + self.table.takeItem(row, column) + else: + temp: str = table_item.text() + idx = temp.find(f'\n{temp}') + if idx > 0: + temp1 = temp[:idx] + if len(temp) == idx + len(txt) + 1: + temp2 = '' + else: + temp2 = temp[idx + len(txt) + 1:] + temp = temp1 + temp2 + else: + temp = temp[len(txt) + 1:] + if temp.count('\n') > 0: + self.table.takeItem(row, column) + element = QTableWidgetItem(temp) + element.setForeground(QtGui.QColor('red')) + self.table.setItem(row, column, element) + else: + self.table.takeItem(row, column) + element = QTableWidgetItem(temp) + element.setForeground(QtGui.QColor('yellow')) + self.table.setItem(row, column, QTableWidgetItem(element)) + found_item = False + for i in range(7): + if self.table.item(row, i) is not None: + if self.table.item(row, i).text() != '': + found_item = True + if not found_item: + self.table.hideRow(row) + + def remove_from_table(self, temp_item): + txt = temp_item.text() + current_course: Course = self.find_course_by_string(txt) + if current_course.theory_1_day is not None: + row, column = self.get_row_col(current_course.theory_1_time_start, current_course.theory_1_time_end, + current_course.theory_1_day) + self.removing_table(row, column, current_course.table_string()) + if current_course.theory_2_day is not None: + row, column = self.get_row_col(current_course.theory_2_time_start, current_course.theory_2_time_end, + current_course.theory_2_day) + self.removing_table(row, column, current_course.table_string()) + if current_course.lab_1_day is not None: + row, column = self.get_row_col(current_course.lab_1_time_start, current_course.lab_1_time_end, + current_course.lab_1_day) + self.removing_table(row, column, current_course.table_string().split(' - ')[0] + ' - LAB') + if current_course.lab_2_day is not None: + row, column = self.get_row_col(current_course.lab_2_time_start, current_course.lab_2_time_end, + current_course.lab_2_day) + self.removing_table(row, column, current_course.table_string().split(' - ')[0] + ' - LAB') + self.resize_table() + + def removeButtonClicked(self): + item = self.right_listViewer.currentRow() + if item != -1: + temp_item = self.right_listViewer.takeItem(item) + self.remove_from_table(temp_item) + + def clearButtonClicked(self): + mn = self.table.rowCount() + for i in range(mn): + for j in range(self.table.columnCount()): + self.table.takeItem(i, j) + self.table.hideRow(i) + self.resize_table() + self.right_listViewer.clear() + self.advanceSearch.setChecked(False) + self.seatLimit.setChecked(False) + self.sameCourse.setChecked(False) + self.examClash.setChecked(False) + self.theoryClash.setChecked(False) + self.labClash.setChecked(True) + self.disableAllRestriction.setChecked(False) + + def left_listViewer_selection_changed(self): + if self.left_listViewer.currentItem() is not None: + item = self.left_listViewer.currentItem().text() + course_name = item.split('[')[0] + course_name = course_name[0:len(course_name) - 1] + section = item.split('[')[1] + section = section[0:2] + self.show_description(course_name, section) + + def right_listViewer_selection_changed(self): + item = self.right_listViewer.currentItem() + if item is not None: + item = item.text() + course_name = item.split('[')[0] + course_name = course_name[0:len(course_name) - 1] + section = item.split('[')[1] + section = section[0:2] + self.show_description(course_name, section) + + def backButtonClicked(self): + self.MainWindow.show() + self.AdvanceWindow.hide() + + def seatLimitClicked(self): + if not isChecked(self.seatLimit): + self.disableAllRestriction.setChecked(False) + if isChecked(self.labClash) and isChecked(self.theoryClash) and isChecked(self.examClash) and isChecked( + self.seatLimit) and isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(True) + + def sameCourseClicked(self): + if not isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(False) + if isChecked(self.labClash) and isChecked(self.theoryClash) and isChecked(self.examClash) and isChecked( + self.seatLimit) and isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(True) + + def examClashClicked(self): + if not isChecked(self.examClash): + self.disableAllRestriction.setChecked(False) + if isChecked(self.labClash) and isChecked(self.theoryClash) and isChecked(self.examClash) and isChecked( + self.seatLimit) and isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(True) + + def theoryClashClicked(self): + if not isChecked(self.theoryClash): + self.disableAllRestriction.setChecked(False) + if isChecked(self.labClash) and isChecked(self.theoryClash) and isChecked(self.examClash) and isChecked( + self.seatLimit) and isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(True) + + def labClashClicked(self): + if not isChecked(self.labClash): + self.disableAllRestriction.setChecked(False) + if isChecked(self.labClash) and isChecked(self.theoryClash) and isChecked(self.examClash) and isChecked( + self.seatLimit) and isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(True) + + def advanceSearchClicked(self): + if isChecked(self.advanceSearch): + msg = QMessageBox() + msg.resize(600, 250) + msg.setMinimumSize(QtCore.QSize(600, 250)) + msg.setBaseSize(QtCore.QSize(600, 250)) + msg.setIcon(msg.Icon.Warning) + msg.setText( + f"You will be able to search with custom parameter\nlike: faculty name, specific time in any order etc\n\nbut your searching will be too much slower\nEx: zaber mohammad cse220 sunday tuesday\nEx: cse320 gazzali\nEx: cse260 monday\n\nAre you sure you want to activate advance search?") + msg.setWindowTitle("Performance Warning!") + msg.setStandardButtons(msg.StandardButton.Yes | msg.StandardButton.No) + msg.exec() + if msg.standardButton(msg.clickedButton()) == msg.StandardButton.No: + self.advanceSearch.setChecked(False) + + def disableAllRestrictionClicked(self): + if isChecked(self.disableAllRestriction): + self.seatLimit.setChecked(True) + self.sameCourse.setChecked(True) + self.examClash.setChecked(True) + self.theoryClash.setChecked(True) + self.labClash.setChecked(True) + else: + self.seatLimit.setChecked(False) + self.sameCourse.setChecked(False) + self.examClash.setChecked(False) + self.theoryClash.setChecked(False) + self.labClash.setChecked(False) + + def reloadButtonClicked(self): + msg = QMessageBox() + msg.resize(300, 170) + msg.setMinimumSize(QtCore.QSize(300, 170)) + msg.setBaseSize(QtCore.QSize(300, 170)) + msg.setIcon(msg.Icon.Warning) + msg.setText(f"All of your list will be LOST\nDo you want to Reload?") + msg.setWindowTitle("Reload Warning!") + msg.setStandardButtons(msg.StandardButton.Yes | msg.StandardButton.No) + msg.exec() + + if msg.standardButton(msg.clickedButton()) == msg.StandardButton.Yes: + if internet_checker(): + self.clearButtonClicked() + self.left_listViewer.clear() + self.right_listViewer.clear() + self.details_listViewer.clear() + self.download() + + def advanceListUpdate(self, listName, searchBar): + if len(searchBar.text()) > 0: + text_array = searchBar.text().split(' ') + for part in text_array: + for element in range(len(listName)): + item = listName.item(element) + current_course: Course = self.find_course_by_string(item.text()) + if part.lower() not in current_course.advance_string().lower(): + item.setHidden(True) + else: + item.setHidden(False) + + def leftSearchChanged(self): + self.left_listViewer.setCurrentItem(QListWidgetItem(None)) + self.right_listViewer.setCurrentItem(QListWidgetItem(None)) + if isChecked(self.advanceSearch): + self.advanceListUpdate(self.left_listViewer, self.left_search) + else: + listUpdate(self.left_listViewer, self.left_search) + + def rightSearchChanged(self): + self.left_listViewer.setCurrentItem(QListWidgetItem(None)) + self.right_listViewer.setCurrentItem(QListWidgetItem(None)) + if isChecked(self.advanceSearch): + self.advanceListUpdate(self.right_listViewer, self.right_search) + else: + listUpdate(self.right_listViewer, self.right_search) + + +if __name__ == "__main__": + import sys + + app = QtWidgets.QApplication(sys.argv) + AdvanceWindow = QtWidgets.QMainWindow() + ui = Ui_AdvanceWindow() + screenSize = app.screens()[0].availableGeometry() + ui.height = screenSize.height() + ui.width = screenSize.width() + ui.setupUi(AdvanceWindow, None, ui, None) + AdvanceWindow.show() + sys.exit(app.exec()) diff --git a/basic.py b/basic.py new file mode 100644 index 0000000..9c76683 --- /dev/null +++ b/basic.py @@ -0,0 +1,708 @@ +import requests +import webbrowser +from PyQt6 import QtCore, QtWidgets, QtGui +from PyQt6.QtCore import Qt +from PyQt6.QtGui import QCursor +from PyQt6.QtWidgets import QMessageBox, QTableWidgetItem, QListWidgetItem +from ObjectBuilder import object_builder +from internetChecker import internet_checker +from Course import Course +from seatStatusThread import htmlThread, jsonThread + + +def listUpdate(listName, searchBar): + text = searchBar.text() + for element in range(len(listName)): + item = listName.item(element) + if text.lower() not in item.text().lower(): + item.setHidden(True) + else: + item.setHidden(False) + + +def isChecked(check_mark): + return check_mark.checkState() == Qt.CheckState.Checked + + +def showWarning(text: str): + msg = QMessageBox() + msg.resize(400, 170) + msg.setMinimumSize(QtCore.QSize(400, 170)) + msg.setBaseSize(QtCore.QSize(400, 170)) + msg.setIcon(msg.Icon.Warning) + msg.setText(text) + msg.setWindowTitle("Invalid Course") + msg.setStandardButtons(msg.StandardButton.Close) + msg.exec() + + +def myNameClicked(): + webbrowser.open_new('https://www.facebook.com/ShariarShuvo01/') + + +def githubClicked(): + webbrowser.open_new('https://github.com/ShariarShuvo1/bracu-pre-advising-checker') + + +class Ui_BasicWindow(object): + def __init__(self): + self.github = None + self.my_name = None + self.table: QtWidgets.QTableWidget = None + self.advanceSearch: QtWidgets.QCheckBox = None + self.item_exist = None + self.founded_item: Course = None + self.bound = None + self.course_list = [] + self.json = None + self.jsonThreadParser = None + self.font_size = None + self.unitWidth = None + self.unitHeight = None + self.width = None + self.height = None + self.labClash: QtWidgets.QCheckBox = None + self.theoryClash: QtWidgets.QCheckBox = None + self.examClash: QtWidgets.QCheckBox = None + self.pointingHandMouse = QCursor(Qt.CursorShape.PointingHandCursor) + self.disableAllRestriction: QtWidgets.QCheckBox = None + self.sameCourse: QtWidgets.QCheckBox = None + self.seatLimit: QtWidgets.QCheckBox = None + self.reloadButton: QtWidgets.QPushButton = None + self.right_search: QtWidgets.QLineEdit = None + self.left_search: QtWidgets.QLineEdit = None + self.details_listViewer: QtWidgets.QListWidget = None + self.clearButton: QtWidgets.QPushButton = None + self.removeButton: QtWidgets.QPushButton = None + self.addButton: QtWidgets.QPushButton = None + self.right_listViewer: QtWidgets.QListWidget = None + self.left_listViewer: QtWidgets.QListWidget = None + self.backButton: QtWidgets.QPushButton = None + self.basic_ui = None + self.htmlThreadParser = None + self.BasicWindow = None + self.centralwidget = None + self.MainWindow = None + self.html = None + + def labUpdate(self, item): + day_name = {11: "Sunday", 12: "Monday", 13: "Tuesday", 14: "Wednesday", 15: "Thursday", 16: "Friday", 17: "Saturday"} + day1 = None + time1 = None + day2 = None + time2 = None + for i in range(11, len(item)): + if item[i] is not None and day1 is None: + day1 = day_name[i] + time1 = item[i] + elif item[i] is not None: + day2 = day_name[i] + time2 = item[i] + for course in self.course_list: + if course.course_initial == item[1] and course.section_number == item[3]: + course.setLab(day1, time1, day2, time2) + break + + def createCourse(self): + self.json = self.json['rows'] + for element in self.json: + item = element['cell'] + if item[10] is not None: + day_name = {11: "Sunday", 12: "Monday", 13: "Tuesday", 14: "Wednesday", 15: "Thursday", 16: "Friday", 17: "Saturday"} + day1 = None + time1 = None + day2 = None + time2 = None + for i in range(11, len(item)): + if item[i] is not None and day1 is None: + day1 = day_name[i] + time1 = item[i] + elif item[i] is not None: + day2 = day_name[i] + time2 = item[i] + self.course_list.append(Course(item[1], item[2], item[3], item[4], item[5], item[6], item[7], item[8], item[9], item[10], day1, time1, day2, time2)) + else: + self.labUpdate(item) + + def updateSeatStatus(self): + raw_data = self.html.find_all('tr') + inserted_count = 0 + for tr in raw_data: + td = tr.find_all('td') + name = str(td[1])[str(td[1]).find('>') + 1:str(td[1]).find('') + 1:str(td[5]).find('') + 1:str(td[8]).find('", self.font_size, True, "QPushButton{border:1px solid yellow} QPushButton::hover{border:1px solid green; color:green}", self.addButtonClicked, self.pointingHandMouse, "Add the selected course to your list") + + # Remove Button + self.removeButton = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), (int(self.unitWidth*16), int(self.unitHeight*14.5), int(self.unitWidth*6), int(self.unitHeight*4)), "<- Remove", self.font_size, True, "QPushButton{border:1px solid yellow} QPushButton::hover{border:1px solid magenta; color: magenta}", self.removeButtonClicked, self.pointingHandMouse, "Remove the course from your list") + # + # Clear All Button + self.clearButton = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), (int(self.unitWidth*16), int(self.unitHeight*19), int(self.unitWidth*6), int(self.unitHeight*4)), "Clear -X", self.font_size, True, "QPushButton{border:1px solid yellow} QPushButton::hover{border:1px solid red; color:red}", self.clearButtonClicked, self.pointingHandMouse, "Remove all the course from your list") + + # Right Search Bar + self.right_search: QtWidgets.QLineEdit = object_builder(QtWidgets.QLineEdit(parent=self.centralwidget), (int(self.unitWidth*22.5), int(self.unitHeight*5), int(self.unitWidth*15), int(self.unitHeight*4)), "Search", self.font_size+5, False, "QLineEdit{border:1px solid white; color: white}") + self.right_search.textEdited.connect(self.rightSearchChanged) + + # Right List Viewer + self.right_listViewer = object_builder(QtWidgets.QListWidget(parent=self.centralwidget), (int(self.unitWidth*22.5), int(self.unitHeight*10), int(self.unitWidth*15), int(self.unitHeight*25)), None, self.font_size, False, "QListWidget{border:1px solid white; alternate-background-color: #232323;background-color: black;};") + self.right_listViewer.setAlternatingRowColors(True) + self.right_listViewer.itemSelectionChanged.connect(self.right_listViewer_selection_changed) + + # Details Viewer + self.details_listViewer: QtWidgets.QListWidget = object_builder(QtWidgets.QListWidget(parent=self.centralwidget), (int(self.unitWidth*22.5), int(self.unitHeight*36), int(self.unitWidth*15), int((self.unitHeight*100)-(self.unitHeight*37))), None, self.font_size, False, "QListWidget{border:1px solid white; color:white; alternate-background-color: #232323;background-color: black;};") + self.details_listViewer.setAlternatingRowColors(True) + self.setupSchedule() + + self.my_name = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), (int(self.unitWidth*38), int((self.unitHeight*100) - (self.unitHeight*10)) + int(self.unitHeight*5), int(self.unitWidth*15), int(self.unitHeight*2)), "Created By: Shariar Islam Shuvo", self.font_size, False, "QPushButton::hover{color:red}", myNameClicked, self.pointingHandMouse, "Click to visit my Facebook Profile") + self.github = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), (int(self.unitWidth * 55), int((self.unitHeight * 100) - (self.unitHeight * 10)) + int(self.unitHeight * 5), int(self.unitWidth * 6), int(self.unitHeight * 2)), "GitHub", self.font_size, False, "QPushButton::hover{color:red}", githubClicked, self.pointingHandMouse, "Click to visit GitHub repo for this project") + + def setupSchedule(self): + self.table = QtWidgets.QTableWidget(parent=self.centralwidget) + self.table.setGeometry(QtCore.QRect(int(self.unitWidth*38), int(self.unitHeight*5), int((self.unitWidth*100) - (self.unitWidth*39)), int((self.unitHeight*100) - (self.unitHeight*10)))) + self.table.setRowCount(26) + self.table.setColumnCount(7) + + days = [" Saturday ", " Sunday ", " Monday ", " Tuesday ", " Wednesday ", " Thursday ", " Friday "] + times = ['08:00 AM - \n09:20 AM', '08:00 AM - \n11:05 AM', '09:00 AM - \n09:55 AM', '09:00 AM - \n12:00 PM', '09:00 AM - \n12:05 PM', '09:00 AM - \n01:10 PM', '09:30 AM - \n10:50 AM', '10:05 AM - \n11:00 AM', '11:00 AM - \n12:20 PM', '11:00 AM - \n01:30 AM', '11:10 AM - \n12:05 PM', '12:15 PM - \n01:10 PM', '12:30 PM - \n01:30 PM', '12:30 PM - \n01:50 PM', '01:20 PM - \n02:15 PM', '02:00 PM - \n02:55 PM', '02:00 PM - \n03:20 PM', '02:00 PM - \n04:00 PM', '02:00 PM - \n05:05 PM', '03:05 PM - \n04:00 PM', '03:30 PM - \n04:50 PM', '04:10 PM - \n05:05 PM', '05:00 PM - \n06:20 PM', '05:00 PM - \n06:30 PM', '05:05 PM - \n06:00 PM', '06:00 PM - \n09:00 PM'] + self.table.setHorizontalHeaderLabels(days) + self.table.setVerticalHeaderLabels(times) + self.table.setAlternatingRowColors(True) + for i in range(0, 26): + self.table.hideRow(i) + self.resize_table() + self.table.setDisabled(True) + + def setupUi(self, BasicWindow, MainWindow, basic_ui): + self.basic_ui = basic_ui + self.BasicWindow = BasicWindow + self.MainWindow = MainWindow + self.unitHeight = int(self.height/100) + self.unitWidth = int(self.width/100) + BasicWindow.resize(self.width, self.height) + BasicWindow.setMinimumSize(QtCore.QSize(self.width, self.height)) + BasicWindow.setBaseSize(QtCore.QSize(self.width, self.height)) + BasicWindow.setStyleSheet("background-color: black; color: yellow") + BasicWindow.setWindowTitle("Pre Advising Basic") + self.centralwidget = QtWidgets.QWidget(parent=BasicWindow) + + self.setupBody() + + # Initiate texts + BasicWindow.setCentralWidget(self.centralwidget) + QtCore.QMetaObject.connectSlotsByName(BasicWindow) + + def show_description(self, course_name, section): + current_course: Course = None + for course in self.course_list: + if course.course_initial == course_name and course.section_number == section: + current_course = course + break + self.details_listViewer.clear() + self.details_listViewer.addItem(f'Course Name: {current_course.course_name}') + self.details_listViewer.addItem(f'Course Code: {current_course.course_initial}') + self.details_listViewer.addItem(f'Section Number: {current_course.section_number}') + self.details_listViewer.addItem(f'Total Seat: {current_course.total_seat}') + self.details_listViewer.addItem(f'Booked Seat: {current_course.booked_seat}') + self.details_listViewer.addItem(f'Available Seat: {current_course.available_seat}') + self.details_listViewer.addItem(f'Faculty Name: {current_course.faculty_name}') + self.details_listViewer.addItem(f'Faculty Initial: {current_course.faculty_initial}') + self.details_listViewer.addItem(f'Department Name: {current_course.department_name}') + self.details_listViewer.addItem(f'Department Initial: {current_course.department_initial}') + self.details_listViewer.addItem("") + self.details_listViewer.addItem(f'Mid-Term Date: {current_course.exam_date}') + self.details_listViewer.addItem(f'Mid-Term Time: ({current_course.exam_time_start} - {current_course.exam_time_end})') + self.details_listViewer.addItem(f'Mid-Term Day: {current_course.exam_day}') + self.details_listViewer.addItem("") + self.details_listViewer.addItem(f'Theory Class Day 1: {current_course.theory_1_day}') + self.details_listViewer.addItem(f'Theory Class Day 1 Time: ({current_course.theory_1_time_start} - {current_course.theory_1_time_end})') + if current_course.theory_2_day is not None: + self.details_listViewer.addItem(f'Theory Class Day 2: {current_course.theory_2_day}') + self.details_listViewer.addItem(f'Theory Class Day 2 Time: ({current_course.theory_2_time_start} - {current_course.theory_2_time_end})') + self.details_listViewer.addItem("") + if current_course.labAvailable: + if current_course.lab_2_day is not None: + self.details_listViewer.addItem(f'Lab Day: {current_course.lab_1_day}') + self.details_listViewer.addItem(f'Lab Time First Half: ({current_course.lab_1_time_start} - {current_course.lab_1_time_end})') + self.details_listViewer.addItem(f'Lab Time Second Half: ({current_course.lab_2_time_start} - {current_course.lab_2_time_end})') + else: + self.details_listViewer.addItem(f'Lab Day 1: {current_course.lab_1_day}') + self.details_listViewer.addItem(f'Lab Day 1 Time: ({current_course.lab_1_time_start} - {current_course.lab_1_time_end})') + self.details_listViewer.addItem(f'Lab Day 2: {current_course.lab_2_day}') + self.details_listViewer.addItem(f'Lab Time Second Half: ({current_course.lab_2_time_start} - {current_course.lab_2_time_end})') + + def find_course_by_string(self, item): + for course in self.course_list: + if str(course) == item: + return course + + def already_exist(self, element): + for i in range(len(self.left_listViewer)): + if self.left_listViewer.item(i).text() == element: + return True + return False + + def add_to_right_list(self, element): + self.right_listViewer.addItem(element) + self.add_to_table(element) + + def bound_checker(self, item): + self.founded_item: Course = self.find_course_by_string(item) + self.item_exist = self.already_exist(item) + self.bound = [True]*5 + for i in range(len(self.right_listViewer)): + if self.right_listViewer.item(i).text() == item: + showWarning("You can not take same course section twice") + self.bound[0] = False + if False in self.bound: + return False + if not isChecked(self.seatLimit): + if self.founded_item.available_seat == 0 and self.founded_item.total_seat != 0: + showWarning("There are no seat left!") + self.bound[0] = False + if False in self.bound: + return False + if not isChecked(self.sameCourse): + temp_course = item.split()[0] + for i in range(len(self.right_listViewer)): + comp_course = self.right_listViewer.item(i).text().split()[0] + if temp_course == comp_course: + showWarning("Your already took this Course!") + self.bound[1] = False + break + if False in self.bound: + return False + if not isChecked(self.examClash): + for i in range(len(self.right_listViewer)): + temp_course = self.find_course_by_string(self.right_listViewer.item(i).text()) + if self.founded_item.exam_date == temp_course.exam_date and self.founded_item.exam_time_start == temp_course.exam_time_start: + showWarning(f"Your Exam Date Clashes with\n{temp_course}") + self.bound[2] = False + break + if False in self.bound: + return False + if not isChecked(self.theoryClash): + for i in range(len(self.right_listViewer)): + temp_course: Course = self.find_course_by_string(self.right_listViewer.item(i).text()) + temp_list = [temp_course.theory_1_day, temp_course.theory_1_time_start, temp_course.theory_1_time_end] + if self.founded_item.theory_1_day in temp_list and (self.founded_item.theory_1_time_start in temp_list or self.founded_item.theory_1_time_end in temp_list): + showWarning(f"Your Theory Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.theory_2_day is not None: + if self.founded_item.theory_2_day in temp_list and (self.founded_item.theory_2_time_start in temp_list or self.founded_item.theory_2_time_end in temp_list): + showWarning(f"Your Theory Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if temp_course.theory_2_day is not None: + temp_list = [temp_course.theory_2_day, temp_course.theory_2_time_start, temp_course.theory_2_time_end] + if self.founded_item.theory_1_day in temp_list and (self.founded_item.theory_1_time_start in temp_list or self.founded_item.theory_1_time_end in temp_list): + showWarning(f"Your Theory Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.theory_2_day is not None: + if self.founded_item.theory_2_day in temp_list and (self.founded_item.theory_2_time_start in temp_list or self.founded_item.theory_2_time_end in temp_list): + showWarning(f"Your Theory Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if not self.bound[3]: + break + if False in self.bound: + return False + if not isChecked(self.labClash): + for i in range(len(self.right_listViewer)): + temp_course: Course = self.find_course_by_string(self.right_listViewer.item(i).text()) + temp_list = [temp_course.theory_1_day, temp_course.theory_1_time_start, temp_course.theory_1_time_end] + if self.founded_item.lab_1_day in temp_list and (self.founded_item.lab_1_time_start in temp_list or self.founded_item.lab_1_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.lab_2_day is not None: + if self.founded_item.lab_2_day in temp_list and (self.founded_item.lab_2_time_start in temp_list or self.founded_item.lab_2_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if temp_course.theory_2_day is not None: + temp_list = [temp_course.theory_2_day, temp_course.theory_2_time_start, temp_course.theory_2_time_end] + if self.founded_item.lab_1_day in temp_list and (self.founded_item.lab_1_time_start in temp_list or self.founded_item.lab_1_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.lab_2_day is not None: + if self.founded_item.lab_2_day in temp_list and (self.founded_item.lab_2_time_start in temp_list or self.founded_item.lab_2_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + temp_list = [temp_course.lab_1_day, temp_course.lab_1_time_start, temp_course.lab_1_time_end] + if self.founded_item.lab_1_day in temp_list and (self.founded_item.lab_1_time_start in temp_list or self.founded_item.lab_1_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.lab_2_day is not None: + if self.founded_item.lab_2_day in temp_list and (self.founded_item.lab_2_time_start in temp_list or self.founded_item.lab_2_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if temp_course.theory_2_day is not None: + temp_list = [temp_course.lab_2_day, temp_course.lab_2_time_start, temp_course.lab_2_time_end] + if self.founded_item.lab_1_day in temp_list and (self.founded_item.lab_1_time_start in temp_list or self.founded_item.lab_1_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if self.founded_item.lab_2_day is not None: + if self.founded_item.lab_2_day in temp_list and (self.founded_item.lab_2_time_start in temp_list or self.founded_item.lab_2_time_end in temp_list): + showWarning(f"Your LAB Class Clashes with\n{temp_course}") + self.bound[3] = False + break + if not self.bound[3]: + break + if False in self.bound: + return False + else: + return True + + def addButtonClicked(self): + item = self.left_listViewer.currentItem() + if item is not None: + item = item.text() + if isChecked(self.disableAllRestriction): + self.add_to_right_list(item) + elif self.bound_checker(item): + self.add_to_right_list(item) + + def removing_table(self, row, column, txt: str): + table_item = self.table.item(row, column) + if len(table_item.text()) == len(txt): + self.table.takeItem(row, column) + else: + temp: str = table_item.text() + idx = temp.find(f'\n{temp}') + if idx > 0: + temp1 = temp[:idx] + if len(temp) == idx+len(txt)+1: + temp2 = '' + else: + temp2 = temp[idx+len(txt)+1:] + temp = temp1 + temp2 + else: + temp = temp[len(txt)+1:] + if temp.count('\n') > 0: + self.table.takeItem(row, column) + element = QTableWidgetItem(temp) + element.setForeground(QtGui.QColor('red')) + self.table.setItem(row, column, element) + else: + self.table.takeItem(row, column) + element = QTableWidgetItem(temp) + element.setForeground(QtGui.QColor('yellow')) + self.table.setItem(row, column, QTableWidgetItem(element)) + found_item = False + for i in range(7): + if self.table.item(row, i) is not None: + if self.table.item(row, i).text() != '': + found_item = True + if not found_item: + self.table.hideRow(row) + + def remove_from_table(self, temp_item): + txt = temp_item.text() + current_course: Course = self.find_course_by_string(txt) + if current_course.theory_1_day is not None: + row, column = self.get_row_col(current_course.theory_1_time_start, current_course.theory_1_time_end, current_course.theory_1_day) + self.removing_table(row, column, current_course.table_string()) + if current_course.theory_2_day is not None: + row, column = self.get_row_col(current_course.theory_2_time_start, current_course.theory_2_time_end, current_course.theory_2_day) + self.removing_table(row, column, current_course.table_string()) + if current_course.lab_1_day is not None: + row, column = self.get_row_col(current_course.lab_1_time_start, current_course.lab_1_time_end, current_course.lab_1_day) + self.removing_table(row, column, current_course.table_string().split(' - ')[0] + ' - LAB') + if current_course.lab_2_day is not None: + row, column = self.get_row_col(current_course.lab_2_time_start, current_course.lab_2_time_end, current_course.lab_2_day) + self.removing_table(row, column, current_course.table_string().split(' - ')[0] + ' - LAB') + self.resize_table() + + def removeButtonClicked(self): + item = self.right_listViewer.currentRow() + if item != -1: + temp_item = self.right_listViewer.takeItem(item) + self.remove_from_table(temp_item) + + def clearButtonClicked(self): + mn = self.table.rowCount() + for i in range(mn): + for j in range(self.table.columnCount()): + self.table.takeItem(i, j) + self.table.hideRow(i) + self.resize_table() + self.right_listViewer.clear() + self.advanceSearch.setChecked(False) + self.seatLimit.setChecked(False) + self.sameCourse.setChecked(False) + self.examClash.setChecked(False) + self.theoryClash.setChecked(False) + self.labClash.setChecked(True) + self.disableAllRestriction.setChecked(False) + + def left_listViewer_selection_changed(self): + if self.left_listViewer.currentItem() is not None: + item = self.left_listViewer.currentItem().text() + course_name = item.split('[')[0] + course_name = course_name[0:len(course_name)-1] + section = item.split('[')[1] + section = section[0:2] + self.show_description(course_name, section) + + def right_listViewer_selection_changed(self): + item = self.right_listViewer.currentItem() + if item is not None: + item = item.text() + course_name = item.split('[')[0] + course_name = course_name[0:len(course_name)-1] + section = item.split('[')[1] + section = section[0:2] + self.show_description(course_name, section) + + def backButtonClicked(self): + self.MainWindow.show() + self.BasicWindow.hide() + + def seatLimitClicked(self): + if not isChecked(self.seatLimit): + self.disableAllRestriction.setChecked(False) + if isChecked(self.labClash) and isChecked(self.theoryClash) and isChecked(self.examClash) and isChecked(self.seatLimit) and isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(True) + + def sameCourseClicked(self): + if not isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(False) + if isChecked(self.labClash) and isChecked(self.theoryClash) and isChecked(self.examClash) and isChecked(self.seatLimit) and isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(True) + + def examClashClicked(self): + if not isChecked(self.examClash): + self.disableAllRestriction.setChecked(False) + if isChecked(self.labClash) and isChecked(self.theoryClash) and isChecked(self.examClash) and isChecked(self.seatLimit) and isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(True) + + def theoryClashClicked(self): + if not isChecked(self.theoryClash): + self.disableAllRestriction.setChecked(False) + if isChecked(self.labClash) and isChecked(self.theoryClash) and isChecked(self.examClash) and isChecked(self.seatLimit) and isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(True) + + def labClashClicked(self): + if not isChecked(self.labClash): + self.disableAllRestriction.setChecked(False) + if isChecked(self.labClash) and isChecked(self.theoryClash) and isChecked(self.examClash) and isChecked(self.seatLimit) and isChecked(self.sameCourse): + self.disableAllRestriction.setChecked(True) + + def advanceSearchClicked(self): + if isChecked(self.advanceSearch): + msg = QMessageBox() + msg.resize(600, 250) + msg.setMinimumSize(QtCore.QSize(600, 250)) + msg.setBaseSize(QtCore.QSize(600, 250)) + msg.setIcon(msg.Icon.Warning) + msg.setText(f"You will be able to search with custom parameter\nlike: faculty name, specific time in any order etc\n\nbut your searching will be too much slower\nEx: zaber mohammad cse220 sunday tuesday\nEx: cse320 gazzali\nEx: cse260 monday\n\nAre you sure you want to activate advance search?") + msg.setWindowTitle("Performance Warning!") + msg.setStandardButtons(msg.StandardButton.Yes | msg.StandardButton.No) + msg.exec() + if msg.standardButton(msg.clickedButton()) == msg.StandardButton.No: + self.advanceSearch.setChecked(False) + + def disableAllRestrictionClicked(self): + if isChecked(self.disableAllRestriction): + self.seatLimit.setChecked(True) + self.sameCourse.setChecked(True) + self.examClash.setChecked(True) + self.theoryClash.setChecked(True) + self.labClash.setChecked(True) + else: + self.seatLimit.setChecked(False) + self.sameCourse.setChecked(False) + self.examClash.setChecked(False) + self.theoryClash.setChecked(False) + self.labClash.setChecked(False) + + def reloadButtonClicked(self): + msg = QMessageBox() + msg.resize(300, 170) + msg.setMinimumSize(QtCore.QSize(300, 170)) + msg.setBaseSize(QtCore.QSize(300, 170)) + msg.setIcon(msg.Icon.Warning) + msg.setText(f"All of your list will be LOST\nDo you want to Reload?") + msg.setWindowTitle("Reload Warning!") + msg.setStandardButtons(msg.StandardButton.Yes | msg.StandardButton.No) + msg.exec() + + if msg.standardButton(msg.clickedButton()) == msg.StandardButton.Yes: + if internet_checker(): + self.clearButtonClicked() + self.left_listViewer.clear() + self.right_listViewer.clear() + self.details_listViewer.clear() + self.download() + + def advanceListUpdate(self, listName, searchBar): + if len(searchBar.text()) > 0: + text_array = searchBar.text().split(' ') + for part in text_array: + for element in range(len(listName)): + item = listName.item(element) + current_course: Course = self.find_course_by_string(item.text()) + if part.lower() not in current_course.advance_string().lower(): + item.setHidden(True) + else: + item.setHidden(False) + + def leftSearchChanged(self): + self.left_listViewer.setCurrentItem(QListWidgetItem(None)) + self.right_listViewer.setCurrentItem(QListWidgetItem(None)) + if isChecked(self.advanceSearch): + self.advanceListUpdate(self.left_listViewer, self.left_search) + else: + listUpdate(self.left_listViewer, self.left_search) + + def rightSearchChanged(self): + self.left_listViewer.setCurrentItem(QListWidgetItem(None)) + self.right_listViewer.setCurrentItem(QListWidgetItem(None)) + if isChecked(self.advanceSearch): + self.advanceListUpdate(self.right_listViewer, self.right_search) + else: + listUpdate(self.right_listViewer, self.right_search) + + +if __name__ == "__main__": + import sys + + app = QtWidgets.QApplication(sys.argv) + BasicWindow = QtWidgets.QMainWindow() + ui = Ui_BasicWindow() + screenSize = app.screens()[0].availableGeometry() + ui.height = screenSize.height() + ui.width = screenSize.width() + ui.setupUi(BasicWindow, None, ui) + BasicWindow.show() + sys.exit(app.exec()) diff --git a/internetChecker.py b/internetChecker.py new file mode 100644 index 0000000..d61cb59 --- /dev/null +++ b/internetChecker.py @@ -0,0 +1,36 @@ +import requests +from PyQt6 import QtCore +from PyQt6.QtWidgets import QMessageBox + + +def internetActive(url="https://www.google.com", timeout=10): + try: + requests.get(url, timeout=timeout) + return True + except (requests.ConnectionError, requests.Timeout) as exception: + return False + + +def warningMessageBox(text_message="No Internet", title_message="No Internet"): + msg = QMessageBox() + msg.resize(250, 160) + msg.setMinimumSize(QtCore.QSize(250, 160)) + msg.setBaseSize(QtCore.QSize(250, 160)) + msg.setText(text_message) + msg.setWindowTitle(title_message) + msg.setStandardButtons(QMessageBox.StandardButton.Close) + if text_message != "No Internet": + msg.setIcon(QMessageBox.Icon.Warning) + else: + msg.setIcon(QMessageBox.Icon.Critical) + msg.exec() + + +def internet_checker(): + if not internetActive(): + warningMessageBox() + return False + if not internetActive("https://usis.bracu.ac.bd/academia/"): + warningMessageBox("USIS server down!", "USIS down!") + return False + return True diff --git a/login.py b/login.py new file mode 100644 index 0000000..26bdb7c --- /dev/null +++ b/login.py @@ -0,0 +1,85 @@ +from PyQt6 import QtCore, QtWidgets +from PyQt6.QtWidgets import QLineEdit, QPushButton, QLabel +from bs4 import BeautifulSoup +from ObjectBuilder import object_builder +import requests + + +class Ui_LoginWindow(object): + + def __init__(self): + self.main_ui = None + self.MainWindow = None + self.message: QLabel = None + self.LoginWindow = None + self.s = None + self.login: QPushButton = None + self.password: QLineEdit = None + self.email: QLineEdit = None + self.centralwidget = None + + def setupUi(self, LoginWindow, MainWindow, main_ui): + self.LoginWindow = LoginWindow + self.MainWindow = MainWindow + self.main_ui = main_ui + self.s = requests.Session() + LoginWindow.setStyleSheet("background-color: black; color: yellow") + LoginWindow.setWindowTitle("Sign In") + LoginWindow.setFixedSize(400, 200) + self.centralwidget = QtWidgets.QWidget(parent=LoginWindow) + + self.email = object_builder(QtWidgets.QLineEdit(parent=self.centralwidget), (20, 20, 350, 30), "USIS Email", 15, + True, "background-color: rgba(23, 23, 23, 1);") + + self.password: QtWidgets.QLineEdit = object_builder(QtWidgets.QLineEdit(parent=self.centralwidget), (20, 70, 350, 30), + "USIS Password", 15, True, "background-color: rgba(23, 23, 23, 1);") + self.password.setEchoMode(QLineEdit.EchoMode.Password) + + self.login = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), (150, 120, 100, 40), "Login", 15, + True, + "QPushButton::!hover{border: 2px solid yellow; background-color: rgba(0, 0, 0, 0);} QPushButton::hover{border : 2px solid red; background-color: rgba(0, 0, 0, 0);};", + self.loginClicked) + + self.message = object_builder(QtWidgets.QLabel(parent=self.centralwidget), (20, 170, 350, 20), "", 13, False, + "background-color: black;") + + LoginWindow.setCentralWidget(self.centralwidget) + QtCore.QMetaObject.connectSlotsByName(LoginWindow) + + def loginChecker(self): + loginPage = self.s.get('https://usis.bracu.ac.bd/academia/dashBoard/show') + html = BeautifulSoup(loginPage.content, 'html.parser') + if len(str(html)) < 20000: + return False + else: + return True + + def do_login(self): + email = self.email.text() + password = self.password.text() + self.s.get("https://usis.bracu.ac.bd/academia/j_spring_security_check") + self.s.post("https://usis.bracu.ac.bd/academia/j_spring_security_check", + data={'j_username': email, 'j_password': password}) + if self.loginChecker(): + self.LoginWindow.hide() + self.main_ui.loggedIn(self.s) + else: + self.message.setText("Wrong Email/Password. Try Again!") + + def loginClicked(self): + self.message.setText("") + self.do_login() + + +if __name__ == "__main__": + import sys + + app = QtWidgets.QApplication(sys.argv) + LoginWindow = QtWidgets.QMainWindow() + ui = Ui_LoginWindow() + screenSize = app.screens()[0].availableGeometry() + ui.height = screenSize.height() + ui.width = screenSize.width() + ui.setupUi(LoginWindow, None, ui) + LoginWindow.show() + sys.exit(app.exec()) diff --git a/main.py b/main.py index 46682fd..3439051 100644 --- a/main.py +++ b/main.py @@ -1,564 +1,167 @@ -#https://github.com/ShariarShuvo1/bracu-pre-advising-checker -#Author: Md. Shariar Islam Shuvo -#email: shariaislamshuvo@gmail.com - - -from bs4 import BeautifulSoup -import requests -from tkinter import * -import tkinter.messagebox import webbrowser - - -#Tkinter window setup -root = Tk() -root.title("Pre Advising Checker") -root.configure(background="black") - -#setting window size -screen_height = 650 -screen_width = 1150 -root.geometry(f'{screen_width}x{screen_height}') - - -#--------------------- classes ----------------------# -class Subject: - def __init__(self,name,faculty,section, totalSeat,seatBooked,seatAvailable,day1,day2,lab1,lab2,classTime_start,classTime_end,labTime1_start,labTime2_start,labTime1_end,labTime2_end,classRoomNumber,labRoomNumber): - self.name = name - self.faculty =faculty - self.section = section - self.totalSeat = totalSeat - self.seatBooked = seatBooked - self.seatAvailable = seatAvailable - self.day1 = day1 - self.day2 = day2 - self.lab1 = lab1 - self.lab2 = lab2 - self.classTime_start = classTime_start - self.classTime_end = classTime_end - self.labTime1_start = labTime1_start - self.labTime1_end = labTime1_end - self.labTIme2_start = labTime2_start - self.labTIme2_end = labTime2_end - self.classRoomNumebr = classRoomNumber - self.labRoomNumber = labRoomNumber - - def __str__(self): - st = f'{self.section: ^15}{self.name: <13}{self.faculty: <14}{self.seatAvailable: <6}{self.classTime_start: <15}' - return st - - -#Check Internet -def internetAvailable(): - availale = False - url = "https://admissions.bracu.ac.bd/academia/admissionRequirement/getAvailableSeatStatus" - timeout = 10 - try: - requests.get(url,timeout=timeout) - availale = True - except(requests.ConnectionError,requests.Timeout) as exception: - availale = False - return availale - - -# Function for checking the key pressed and updating the listbox ##used geeksforgeeks code -def checkkey(event): - value = event.widget.get() - # get data from l - if value == '': - data = courseList - else: - data = [] - for item in courseList: - if value.lower() in str(item).lower(): - data.append(item) - # update data in listbox - update(data) - -###used geeksforgeeks code -def update(data): - - # clear previous data - courseListViewer.delete(0, 'end') - # put new data - for item in data: - courseListViewer.insert('end', str(item)) - - -if internetAvailable() == False: - #adding error text - noInternetLabel = Label(root, text = "Please Connect to the internet\nand restart the application!", bg = "red", fg="black", font=("Arial",45)) - noInternetLabel.place(x=screen_width//2,y=screen_height//2,anchor=CENTER) - -else: - s=requests.Session() - html = s.get("https://admissions.bracu.ac.bd/academia/admissionRequirement/getAvailableSeatStatus") - html = BeautifulSoup(html.content,'html.parser') - rawData = html.find_all('tr') - allSubjects = list() - - - for tr in rawData: - td = tr.find_all('td') - name = str(td[1])[str(td[1]).find('>')+1:str(td[1]).find('')+1:str(td[3]).find('')+1:str(td[5]).find('3): - section = int(section[:2]) - else: - section = int(section) - totalSeat = int(str(td[7])[str(td[7]).find('>')+1:str(td[7]).find('')+1:str(td[8]).find('')+1:str(td[9]).find('')+1:str(td[6]).find('', checkkey) - - #Titles - titleString = f"{'Section':<10}{'Course':<12}{'Faculty':<13}{'Free':<10}{'Time':<10}" - titleForList = Label(mainFrame,text=titleString, font = ("Ariel",13),fg='yellow') - titleForList.grid(row=1,column=1,sticky='w') - - - #list box - courseListViewer = Listbox(mainFrame,width= 33,height = 15) - courseListViewer.grid(row=2,column=1,sticky='w') - update(courseList) - - - selectedCourses = list() - - - - - - - #--------------------------------RIGHT--------------------------------# - # Function for checking the key pressed and updating the listbox ##used geeksforgeeks code - def checkkey_right(event): - value = event.widget.get() - # get data from l - if value == '': - data = selectedCourses - else: - data = [] - for item in selectedCourses: - if value.lower() in str(item).lower(): - data.append(item) - # update data in listbox - update_right(data) - - ###used geeksforgeeks code - def update_right(data): - - # clear previous data - courseListViewer_right.delete(0, 'end') - # put new data - for item in data: - courseListViewer_right.insert('end', str(item)) - - #Right viewer - - #Search box - entryBox_right = Entry(mainFrame,width=31,fg='yellow') - entryBox_right.grid(row=0,column=3) - entryBox_right.bind('', checkkey_right) - - #Titles - titleForList_right = Label(mainFrame,text=titleString, font = ("Ariel",13),fg='yellow') - titleForList_right.grid(row=1,column=3,sticky='w') - - #list box - courseListViewer_right = Listbox(mainFrame,width= 33,height = 15) - courseListViewer_right.grid(row=2,column=3,sticky='w') - update_right(selectedCourses) - #--------------------------------RIGHT--------------------------------# - - - #--------------------------------Table--------------------------------# - frame = LabelFrame(root,text="Class Schedule",bg='black') - frame.grid(row = 1, column=0,sticky='n',padx=0,pady=0) - - - totalRow = 8 - totalColumn = 8 - dayNameList = ['Day/Time','Saturday','Sunday','Monday','Tuesday','Wednesday','Thursday','Friday'] - timeNameList = ['08:00 AM\n08:20 AM','09:30 AM\n10:50 AM','11:00 AM\n12:20 PM','12:30 PM\n01:50 PM','02:00 PM\n03:20 PM','03:30 PM\n04:50 PM','05:00 PM\n06:20 PM'] - table = { - 'Saturday': {'08:00 AM': [],'09:30 AM': [],'11:00 AM': [],'12:30 PM': [],'02:00 PM': [],'03:30 PM': [],'05:00 PM': []}, - 'Sunday': {'08:00 AM': [],'09:30 AM': [],'11:00 AM': [],'12:30 PM': [],'02:00 PM': [],'03:30 PM': [],'05:00 PM': []}, - 'Monday': {'08:00 AM': [],'09:30 AM': [],'11:00 AM': [],'12:30 PM': [],'02:00 PM': [],'03:30 PM': [],'05:00 PM': []}, - 'Tuesday': {'08:00 AM': [],'09:30 AM': [],'11:00 AM': [],'12:30 PM': [],'02:00 PM': [],'03:30 PM': [],'05:00 PM': []}, - 'Wednesday': {'08:00 AM': [],'09:30 AM': [],'11:00 AM': [],'12:30 PM': [],'02:00 PM': [],'03:30 PM': [],'05:00 PM': []}, - 'Thursday': {'08:00 AM': [],'09:30 AM': [],'11:00 AM': [],'12:30 PM': [],'02:00 PM': [],'03:30 PM': [],'05:00 PM': []}, - 'Friday': {'08:00 AM': [],'09:30 AM': [],'11:00 AM': [],'12:30 PM': [],'02:00 PM': [],'03:30 PM': [],'05:00 PM': []}, - } - for r in range(totalRow): - for c in range(totalColumn): - if r==0: - lbl = Label(frame,text=dayNameList[c],font=("Ariel",10,'bold'),fg='#b8b8b8',width=13,height=2,borderwidth=1,relief = 'solid',padx=0,pady=0) - elif r>0 and c==0: - lbl = Label(frame,text=timeNameList[r-1],font=("Ariel",10,'bold'),fg='#b8b8b8',width=13,height=3,borderwidth=1,relief = 'solid',padx=0,pady=0) +from PyQt6 import QtCore, QtWidgets +from PyQt6.QtCore import Qt +from PyQt6.QtGui import QCursor +from basic import Ui_BasicWindow +from advance import Ui_AdvanceWindow +from login import Ui_LoginWindow +from internetChecker import internet_checker +from ObjectBuilder import object_builder + + +def myNameClicked(): + webbrowser.open_new('https://www.facebook.com/ShariarShuvo01/') + + +def githubClicked(): + webbrowser.open_new('https://github.com/ShariarShuvo1/bracu-pre-advising-checker') + + +class Ui_MainWindow(object): + def __init__(self): + self.github = None + self.my_name = None + self.main_ui = None + self.login_ui = None + self.LoginWindow = None + self.login_window_generated = False + self.width = None + self.height = None + self.pointingHandMouse = QCursor(Qt.CursorShape.PointingHandCursor) + self.advance_ui = None + self.advanceWindow = None + self.basic_ui = None + self.basicWindow = None + self.myName = None + self.advance_button = None + self.comment_text_2 = None + self.heading_text_2 = None + self.basic_button = None + self.comment_text_1 = None + self.heading_text_1 = None + self.centralwidget = None + self.header = None + self.basic_window_generated = False + self.advance_window_generated = False + + def setupUi(self, MainWindow, main_ui): + + self.main_ui = main_ui + MainWindow.resize(900, 600) + MainWindow.setMinimumSize(QtCore.QSize(900, 600)) + MainWindow.setBaseSize(QtCore.QSize(900, 600)) + MainWindow.setStyleSheet("background-color: black; color: yellow") + MainWindow.setWindowTitle("Pre Advising") + + self.centralwidget = QtWidgets.QWidget(parent=MainWindow) + + # header + self.header = object_builder(QtWidgets.QLabel(parent=self.centralwidget), (219, 69, 461, 101), "Pre Advising", + 80, True, "") + self.header.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + + # Name + self.myName: QtWidgets.QPushButton = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), (488, 147, 151, 20), + "by Shariar Islam Shuvo", None, True, + "QPushButton::!hover{background-color: rgba(0, 0, 0, 0);} QPushButton::hover{background-color: rgba(0, 0, 0, 0); color:red;}", + myNameClicked, None, "You are welcome :)") + + # Heading Text 1 + self.heading_text_1 = object_builder(QtWidgets.QLabel(parent=self.centralwidget), (124, 280, 261, 71), + "Basic Advising", 29, True, "background-color: rgba(23, 23, 23, 1);") + self.heading_text_1.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + + # Comment Text 1 + self.comment_text_1 = object_builder(QtWidgets.QLabel(parent=self.centralwidget), (124, 351, 261, 91), + "This mode will only work during Pre Advising time [NO USIS SIGN IN REQUIRED]", + None, True, "background-color: rgba(23, 23, 23, 1); color:white") + self.comment_text_1.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.comment_text_1.setWordWrap(True) + + # Basic Button + self.basic_button = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), (124, 280, 265, 166), None, + None, False, + "QPushButton::!hover{border: 2px solid yellow; background-color: rgba(0, 0, 0, 0);} QPushButton::hover{border : 2px solid red; background-color: rgba(0, 0, 0, 0);};", + self.basicButtonClicked, self.pointingHandMouse, + "This mode will update data from https://admissions.bracu.ac.bd/academia/admissionRequirement/getAvailableSeatStatus which is not always accurate") + + # Heading Text 2 + self.heading_text_2 = object_builder(QtWidgets.QLabel(parent=self.centralwidget), (513, 280, 261, 71), + "Advance Advising", 29, True, "background-color: rgba(23, 23, 23, 1);") + self.heading_text_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + + # Comment Text 2 + self.comment_text_2 = object_builder(QtWidgets.QLabel(parent=self.centralwidget), (513, 351, 261, 91), + "This mode will always work [USIS SIGN IN REQUIRED]", None, True, + "background-color: rgba(23, 23, 23, 1); color:white") + self.comment_text_2.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.comment_text_2.setWordWrap(True) + + # Advance Button + self.advance_button = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), (511, 280, 265, 166), + None, None, False, + "QPushButton::!hover{border: 2px solid yellow; background-color: rgba(0, 0, 0, 0);} QPushButton::hover{border : 2px solid red; background-color: rgba(0, 0, 0, 0);};", + self.advanceButtonClicked, self.pointingHandMouse, + "This mode will update data directly from USIS which is much more accurate than basic mode") + + self.my_name = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), (30, 560, 200, 20), + "Created By: Shariar Islam Shuvo", 12, False, + "QPushButton::hover{color:red}", myNameClicked, self.pointingHandMouse, + "Click to visit my Facebook Profile") + self.github = object_builder(QtWidgets.QPushButton(parent=self.centralwidget), (250, 560, 150, 20), "GitHub", 12, + False, "QPushButton::hover{color:red}", githubClicked, self.pointingHandMouse, + "Click to visit GitHub repo for this project") + + # Initiate texts + MainWindow.setCentralWidget(self.centralwidget) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def basicButtonClicked(self): + if internet_checker(): + MainWindow.hide() + if not self.basic_window_generated: + self.basic_window_generated = True + self.basicWindow = QtWidgets.QMainWindow() + self.basic_ui = Ui_BasicWindow() + self.basic_ui.height = self.height + self.basic_ui.width = self.width + self.basic_ui.setupUi(self.basicWindow, MainWindow, self.basic_ui) + self.basicWindow.show() + + def loggedIn(self, session): + if not self.advance_window_generated: + self.advance_window_generated = True + self.advanceWindow = QtWidgets.QMainWindow() + self.advance_ui = Ui_AdvanceWindow() + self.advance_ui.height = self.height + self.advance_ui.width = self.width + self.advance_ui.setupUi(self.advanceWindow, MainWindow, self.advance_ui, session) + self.advanceWindow.show() + + def advanceButtonClicked(self): + if internet_checker(): + MainWindow.hide() + if not self.login_window_generated: + self.login_window_generated = True + self.LoginWindow = QtWidgets.QMainWindow() + self.login_ui = Ui_LoginWindow() + self.login_ui.height = self.height + self.login_ui.width = self.width + self.login_ui.setupUi(self.LoginWindow, MainWindow, self.main_ui) + self.LoginWindow.show() else: - lbl = Label(frame,text="",font=("Ariel",10),fg='white',width=13,height=3,borderwidth=1,relief = 'solid',padx=0,pady=0) - table[dayNameList[c]][timeNameList[r-1][:8]].append(lbl) - lbl.grid(row=r,column=c) - - def update_table(selectedCourses): - for val in table.values(): - for v in val.values(): - v[0].config(text='',fg='white') - for course in selectedCourses: - if len(table[course.day1][course.classTime_start][0].cget('text'))<1 and (table[course.day1][course.classTime_start][0].cget('text') != f'{course.name} - Theory'): - table[course.day1][course.classTime_start][0].config(text=f'{course.name} - Theory') - elif len(table[course.day1][course.classTime_start][0].cget('text'))>1 and (table[course.day1][course.classTime_start][0].cget('text') != f'{course.name} - Theory'): - st = table[course.day1][course.classTime_start][0].cget('text') - st+= f'\n{course.name} - Theory' - table[course.day1][course.classTime_start][0].config(text=st,fg='red') - - if len(table[course.day2][course.classTime_start][0].cget('text'))<1 and (table[course.day2][course.classTime_start][0].cget('text') != f'{course.name} - Theory'): - table[course.day2][course.classTime_start][0].config(text=f'{course.name} - Theory') - elif len(table[course.day2][course.classTime_start][0].cget('text'))>1 and (table[course.day2][course.classTime_start][0].cget('text') != f'{course.name} - Theory'): - st = table[course.day2][course.classTime_start][0].cget('text') - st+= f'\n{course.name} - Theory' - table[course.day2][course.classTime_start][0].config(text=st,fg='red') - - if len(course.lab1)>2: - if len(table[course.lab1][course.labTime1_start][0].cget('text'))<1 and (table[course.lab1][course.labTime1_start][0].cget('text') != f'{course.name} - LAB'): - table[course.lab1][course.labTime1_start][0].config(text=f'{course.name} - LAB',fg='#a3bfff') - elif len(table[course.lab1][course.labTime1_start][0].cget('text'))>1 and (table[course.lab1][course.labTime1_start][0].cget('text') != f'{course.name} - LAB'): - st = table[course.lab1][course.labTime1_start][0].cget('text') - st+= f'\n{course.name} - LAB' - table[course.lab1][course.labTime1_start][0].config(text=st,fg='red') - - if len(table[course.lab2][course.labTIme2_start][0].cget('text'))<1 and (table[course.lab2][course.labTIme2_start][0].cget('text') != f'{course.name} - LAB'): - table[course.lab2][course.labTIme2_start][0].config(text=f'{course.name} - LAB',fg='#a3bfff') - elif len(table[course.lab2][course.labTIme2_start][0].cget('text'))>1 and (table[course.lab2][course.labTIme2_start][0].cget('text') != f'{course.name} - LAB'): - st = table[course.lab2][course.labTIme2_start][0].cget('text') - st+= f'\n{course.name} - LAB' - table[course.lab2][course.labTIme2_start][0].config(text=st,fg='red') - - - #--------------------------------Table--------------------------------# - - def subjectAvailability(name): - for ele in selectedCourses: - if name == ele.name: - return True - return False - - - def sectionFinder(section,subject): - if len(selectedCourses)==8: - tkinter.messagebox.showinfo("Error!","You have already selected maximum number of courses for 1 semester") - else: - for obj in courseList: - if obj.name == subject and obj.section == section and subjectAvailability(subject): - tkinter.messagebox.showinfo("Error!","This subject has already been added") - break - elif obj.name == subject and obj.section == section and obj.seatAvailable<1: - tkinter.messagebox.showinfo("Error!","This class is already full") - break - elif obj.name == subject and obj.section == section: - selectedCourses.append(obj) - break - - #Buttons - def addBut(): - st = courseListViewer.get(ANCHOR) - if(len(st)!=0): - sectionFinder(int(st.split()[0]),st.split()[1]) - else: - tkinter.messagebox.showinfo("Error!","To add, select from the left panle") - update_table(selectedCourses) - update_right(selectedCourses) - - - - def removeBut(): - st = courseListViewer_right.get(ANCHOR) - if(len(st) ==0): - tkinter.messagebox.showinfo("Error!","To remove, select from the right panle") - return - section = int(st.split()[0]) - subject = st.split()[1] - obj = None - for i in range (len(selectedCourses)): - if selectedCourses[i].section == section and selectedCourses[i].name==subject: - obj = selectedCourses[i] - break - selectedCourses.remove(obj) - update_table(selectedCourses) - update_right(selectedCourses) - - def clearBut(): - selectedCourses.clear() - update_table(selectedCourses) - update_right(selectedCourses) - - #Add - addButton = Button(mainFrame,text='Add',command=addBut,font = ('Ariel',15,'bold'), width =6, fg = 'green',padx=0,pady=0) - addButton.grid(row=2,column=2,sticky='n') - #Remove - removeButton = Button(mainFrame,text='Remove',command=removeBut,font = ('Ariel',15,'bold'),width =6,fg='red',padx=0,pady=0) - removeButton.grid(row=2,column=2,sticky='w') - - #clear - removeButton = Button(mainFrame,text='Clear',command=clearBut,font = ('Ariel',15,'bold'),width =6,fg='black',padx=0,pady=0) - removeButton.grid(row=2,column=2,sticky='s') - - #------------------ GUI ----------------------# - - - #------------------ Details Panle -----------------------# - details = LabelFrame(root,text='Details') - details.grid(row=0,column=1,sticky='n',padx=10,pady=10) - - detailsLabel = Label(details,text = "",font =('Arial',20,'bold')) - detailsLabel.grid(row=1,column=0,sticky='w') - Label(details,text=f'Course Initial:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=2,column=0,sticky='w') - Label(details,text=f'Faculty:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=3,column=0,sticky='w') - Label(details,text=f'Section:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=4,column=0,sticky='w') - Label(details,text=f'Total Seat:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=5,column=0,sticky='w') - Label(details,text=f'Seat Booked:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=6,column=0,sticky='w') - Label(details,text=f'Free Seat:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=7,column=0,sticky='w') - Label(details,text=f'Theory Class:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=8,column=0,sticky='w') - Label(details,text=f'Theory Class Time:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=9,column=0,sticky='w') - Label(details,text=f'Class Room:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=10,column=0,sticky='w') - Label(details,text=f'Lab Class:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=11,column=0,sticky='w') - Label(details,text=f'Theory Class Time:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=12,column=0,sticky='w') - Label(details,text=f'Lab Room:',font =('Arial',13),width=20,fg='yellow',borderwidth=1,relief = 'solid',padx=0,pady=0).grid(row=13,column=0,sticky='w') - - - label1=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label1.grid(row=2,column=1,sticky='w') - label2=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label2.grid(row=3,column=1,sticky='w') - label3=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label3.grid(row=4,column=1,sticky='w') - label4=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label4.grid(row=5,column=1,sticky='w') - label5=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label5.grid(row=6,column=1,sticky='w') - label6=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label6.grid(row=7,column=1,sticky='w') - label7=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label7.grid(row=8,column=1,sticky='w') - label8=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label8.grid(row=9,column=1,sticky='w') - label9=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label9.grid(row=10,column=1,sticky='w') - label10=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label10.grid(row=11,column=1,sticky='w') - label11=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label11.grid(row=12,column=1,sticky='w') - label12=Label(details,text=f'',font =('Arial',13),width=20,fg='#fc03f0',borderwidth=1,relief = 'solid',padx=0,pady=0) - label12.grid(row=13,column=1,sticky='w') - - def detailsBut(): - stx = courseListViewer.get(ANCHOR) - section = int(stx.split()[0]) - subject = stx.split()[1] - currentObj = None - for obj in courseList: - if obj.name == subject and obj.section == section: - currentObj = obj - break - - label1.config(text=f'{currentObj.name}') - label2.config(text=f'{currentObj.faculty}') - label3.config(text=f'{currentObj.section}') - label4.config(text=f'{currentObj.totalSeat}') - label5.config(text=f'{currentObj.seatBooked}') - label6.config(text=f'{currentObj.seatAvailable}') - label7.config(text=f'{currentObj.day1}, {currentObj.day2}') - label8.config(text=f'{currentObj.classTime_start} - {currentObj.classTime_end}') - label9.config(text=f'{currentObj.classRoomNumebr}') - label10.config(text=f'{currentObj.lab1}') - label11.config(text=f'{currentObj.labTime1_start} - {currentObj.labTIme2_end}') - label12.config(text=f'{currentObj.labRoomNumber}') - - - - detailsButton = Button(details,text = 'Show Details',command=detailsBut,font = ('Ariel',15,'bold'),width =12,fg='#5c0049',padx=0,pady=0) - detailsButton.grid(row=0,column=0,sticky='w') - - - - #------------------ Details Panle -----------------------# - - #------------------ Linkes --------------------# - def callback(url): - webbrowser.open_new(url) - - github = Label(root,text='GitHub', fg="blue", bg='black', cursor="hand",font=("bold")) - github.grid(row=1,column=1,sticky='sw') - github.bind("",lambda e: callback("https://github.com/ShariarShuvo1/bracu-pre-advising-checker")) - - - myName = Label(root,text='Made by: Shariar Islam Shuvo',fg='yellow',bg='black',cursor='hand') - myName.grid(row=1,column=1,sticky='s') - myName.bind("",lambda e: callback("https://www.facebook.com/ShariarShuvo01/")) - #------------------ Linkes --------------------# - - + self.advanceWindow.show() +if __name__ == "__main__": + import sys -root.mainloop() \ No newline at end of file + app = QtWidgets.QApplication(sys.argv) + MainWindow = QtWidgets.QMainWindow() + ui = Ui_MainWindow() + screenSize = app.screens()[0].availableGeometry() + ui.height = screenSize.height() + ui.width = screenSize.width() + ui.setupUi(MainWindow, ui) + MainWindow.show() + sys.exit(app.exec()) diff --git a/seatStatusThread.py b/seatStatusThread.py new file mode 100644 index 0000000..5e97fb0 --- /dev/null +++ b/seatStatusThread.py @@ -0,0 +1,57 @@ +from PyQt6 import QtCore +import requests +from bs4 import BeautifulSoup + + +class htmlThread(QtCore.QThread): + + def setter(self, url, ui): + self.url = url + self.html = None + self.ui = ui + + def getter(self): + self.ui.html = self.html + self.ui.FoundHtml() + + def run(self): + s = requests.Session() + html = s.get(self.url) + s.close() + self.html = BeautifulSoup(html.content, 'html.parser') + self.getter() + + +class jsonThread(QtCore.QThread): + + def setter(self, url, ui, session): + self.session = session + self.url = url + self.json_content = None + self.ui = ui + + def getter(self): + self.ui.json = self.json_content + self.ui.FoundJson() + + def run(self): + self.json_content: requests.get = self.session.get(self.url).json() + print() + self.getter() + + +class loggedInThread(QtCore.QThread): + + def setter(self, url, ui, session): + self.session = session + self.url = url + self.json_content = None + self.ui = ui + + def getter(self): + self.ui.seats_data = self.json_content + self.ui.FoundSeatData() + + def run(self): + self.json_content = self.session.get(self.url).json() + self.getter()