목차
- 개발환경
- 개발완료보고서
- 요구사항보고서
- 일정표
- db 테이블 구조화, ERD
- 순서도
- 목업 이미지, QT디자인
- 파일 첨부
- 실행 화면(캡쳐, 영상)
- 소스코드 전문
- 서버 관련 코드
- 클라이언트 관련 코드
- 메인 함수
개발환경
- 운영체제: Window OS, Window 10
- 개발언어: Python 3.11
- 개발 툴: Pycharm
- DBSM: PostgreSQL
- 추가 패키지: PyQt, Qt Desinger
개발완료보고서
요구사항분석서
일정표
DB 테이블 구조화, ERD
순서도
목업이미지, QT 제작 이미지
목업 이미지
QT 제작 이미지
파일 첨부
https://github.com/guaba98/TeamCollaborationTool/tree/main
실행 화면
실행영상
관리자 화면 실행 영상
소스코드 전문
서버 관련
class server.py
더보기
import json
import sqlite3
import select
from socket import *
from threading import *
from main_code.domain.class_db_connector import DBConnector
from main_code.domain.class_db_connector import DBConnector
# 사용할 구분자
header_split = chr(1)
list_split_1 = chr(2)
list_split_2 = chr(3)
class Server():
'''
실습실 소연: 10.10.20.103
실습실 종혁: 10.10.20.109
기숙사 독서실 : 192.168.0.88
'''
# HOST = '10.10.20.103'#gethostbyname(gethostname())
HOST = gethostbyname(gethostname())
PORT = 5050
BUFFER = 50000
FORMAT = 'utf-8'
connected_member = list()
def __init__(self, db_conn: DBConnector):
self._serverSocket = socket(AF_INET, SOCK_STREAM)
self.db_conn = db_conn
self.server_socket = None
self.config = None
self.sockets_list = list()
self.clients = dict()
self.thread_for_run = None
self.run_signal = True
def start(self):
if self.thread_for_run is not None: # 실행중이면 종료 시키기
return
self.server_socket = socket(AF_INET, SOCK_STREAM) # AF_INET(ipv4를 의미)
self.server_socket.bind((self.HOST, self.PORT)) # 바인딩
self.server_socket.listen() # 리슨 시작
self.sockets_list.clear() # 소켓리스트 클리어
self.sockets_list.append(self.server_socket)
self.run_signal = True
self.thread_for_run = Thread(target=self.run)
self.thread_for_run.start()
def stop(self):
self.run_signal = False
if self.thread_for_run is not None:
self.thread_for_run.join()
self.server_socket.close()
self.thread_for_run = None
def run(self):
while True:
if self.run_signal is False:
break
try:
read_sockets, _, exception_sockets = select.select(self.sockets_list, [], self.sockets_list, 0.1)
except Exception:
continue
for notified_socket in read_sockets:
if notified_socket == self.server_socket:
client_socket, client_address = self.server_socket.accept()
user = self.receive_message(client_socket)
if user is False:
continue
self.sockets_list.append(client_socket)
self.clients[client_socket] = user
else:
message = self.receive_message(notified_socket)
if message is False:
self.sockets_list.remove(notified_socket)
del self.clients[notified_socket]
continue
for notified_socket in exception_sockets:
self.sockets_list.remove(notified_socket)
del self.clients[notified_socket]
def send_message(self, client_socket: socket, result):
client_socket.send(result)
def receive_message(self, client_socket: socket):
try:
recv_message = client_socket.recv(self.BUFFER)
decode_msg = recv_message.decode(self.FORMAT).strip() # recv 메시지
header = decode_msg.split(header_split)[0] # recv 메시지의 header
if header == 'login': # client에서 유저 id pw를 받아와 db에서 조회후 client에 결과값을 보낸다
substance = decode_msg.split(header_split)[1]
data = substance.split(list_split_1)
id, pw = data
result = self.db_conn.log_in(id, pw)
if result is False: # 아이디와 비밀번호가 없으면 False를 보낸다
response_header = f"{f'login{header_split}{False}':{self.BUFFER}}".encode(self.FORMAT)
self.send_message(client_socket, response_header)
else: # 아이디와 비밀번호가 맞으면 유저정보를 보내준다
user_info = json.dumps(result)
self.db_conn.insert_login_log(login_id=id) # 로그인 기록 저장
response_header = f"{f'login{header_split}{user_info}'}"
client_socket.send(bytes(response_header, "UTF-8"))
elif header == 'duple': # 회원가입 아이디 중복확인
substance = decode_msg.split(header_split)[1]
join_username = substance
result = self.db_conn.duple_reg_id(join_username) # DB에 연결해 아이디 중복확인
if result: # 사용 가능한 아이디일 때
response_header = f"{f'duple{header_split}{True}':{self.BUFFER}}".encode(self.FORMAT)
self.send_message(client_socket, response_header)
else: # 사용 불가능한 아이디일 때 (중복일 때)
response_header = f"{f'duple{header_split}{False}':{self.BUFFER}}".encode(self.FORMAT)
self.send_message(client_socket, response_header)
elif header == 'insertuser': # 회원가입
register_user_info = decode_msg.split(header_split)[1]
register_user_info =eval(register_user_info)
result = self.db_conn.insert_user(register_user_info)
if result is True:
response_header = f"{f'insertuser{header_split}{True}':{self.BUFFER}}".encode(self.FORMAT)
self.send_message(client_socket, response_header)
elif result is False:
response_header = f"{f'insertuser{header_split}{False}':{self.BUFFER}}".encode(self.FORMAT)
self.send_message(client_socket, response_header)
elif header == 'send_chat': # 채팅 받기
send_chat = decode_msg.split(header_split)[1] # 데이터 받아오기
send_chat2 = send_chat.split(list_split_1)
user_no, team_no, name, chat = send_chat2
result = self.db_conn.insert_chat_log(user_no, chat)
response_header = f"{f'recv_chat{header_split}{user_no}{list_split_1}{team_no}{list_split_1}{name}{list_split_1}{chat}'}" # 헤더만들기
clients = self.clients.copy()
for i in clients:
try:
i.send(bytes(response_header, "UTF-8"))
except:
continue
elif header == 'get_notice': # 공지 client에 보내주기
recv_msg = decode_msg.split(header_split)[1]
recv_msg = recv_msg.split(list_split_1)
user_no, user_nn = recv_msg
if '관리자' in user_nn:
result = self.db_conn.return_notice_all_data()
else:
result = self.db_conn.get_notice_list(user_no)
result = json.dumps(result)
response_header = f"{f'recv_get_notice{header_split}{result}'}"
client_socket.send(bytes(response_header, "UTF-8"))
elif header == 'get_todolist': #
todolist_info = decode_msg.split(header_split)[1] # 데이터 받아오기
todolist_info = todolist_info.split(list_split_1)
user_no, team_name = todolist_info
# 투두 리스트 받아오기
todo_result = self.db_conn.get_todo_list(user_no)
# 멤버 받아오기
member_result = self.db_conn.return_team_members(user_no)
# 합치기
result = todo_result ,member_result
result = json.dumps(result)
response_header = f"{f'recv_get_todolist{header_split}{result}'}"
client_socket.send(bytes(response_header, "UTF-8"))
elif header == 'get_todolist2': #
todolist_info = decode_msg.split(header_split)[1] # 데이터 받아오기
todolist_info = todolist_info.split(list_split_1)
user_id, user_name, user_no = todolist_info
# 투두 리스트 받아오기
result = self.db_conn.get_todo_list(user_no)
# 합치기
result = json.dumps(result)
response_header = f"{f'recv_get_member_todo_list_for_admin{header_split}{result}{list_split_1}{user_id}{list_split_1}{user_name}'}"
client_socket.send(bytes(response_header, "UTF-8"))
elif header == 'update_user_message':
proflie_message = decode_msg.split(header_split)[1]
proflie_message = proflie_message.split(list_split_1)
user_no, user_message = proflie_message
self.db_conn.update_profile_message(user_no, user_message)
response_header = f"{f'update_user_message{header_split}{user_message}':{self.BUFFER}}".encode(self.FORMAT)
self.send_message(client_socket, response_header)
elif header == 'update_todo_checked':
proflie_message = decode_msg.split(header_split)[1]
proflie_message = proflie_message.split(list_split_1)
todo_id, checked = proflie_message
self.db_conn.update_todo_list(todo_id, int(checked))
elif header == 'insert_todo':
proflie_message = decode_msg.split(header_split)[1]
proflie_message = eval(proflie_message)
title, contents, user_no = proflie_message
self.db_conn.insert_todo_list(user_no, title, contents)
response_header = f"{f'recv_insert_todo{header_split}':{self.BUFFER}}".encode(self.FORMAT)
self.send_message(client_socket, response_header)
elif header == 'insert_notice':
proflie_message = decode_msg.split(header_split)[1]
proflie_message = eval(proflie_message)
title, contents, team = proflie_message
title_no = self.db_conn.return_team_num(team)
self.db_conn.insert_notice_data(title_no, title, contents)
response_header = f"{f'recv_insert_notice{header_split}':{self.BUFFER}}".encode(self.FORMAT)
self.send_message(client_socket, response_header)
# 팀목록 요청받음
elif header == 'get_team_name_list':
result = self.db_conn.return_team_name()
response_header = f"{f'recv_get_team_name_list{header_split}{result}':{self.BUFFER}}".encode(self.FORMAT)
self.send_message(client_socket, response_header)
elif header == 'get_team_name_list2':
result = self.db_conn.return_team_name()
response_header = f"{f'recv_get_team_name_list2{header_split}{result}':{self.BUFFER}}".encode(self.FORMAT)
self.send_message(client_socket, response_header)
# 팀이름을 인자로 멤버들 받아오기
elif header == 'get_team_member':
team_name = decode_msg.split(header_split)[1]
result = self.db_conn.return_team_members_for_admin(team_name)
result = json.dumps(result)
response_header = f"{f'recv_get_team_member{header_split}{result}'}"
client_socket.send(bytes(response_header, "UTF-8"))
elif header == 'delete_notice':
notice_title = decode_msg.split(header_split)[1]
result = self.db_conn.delete_notice_data(notice_title)
elif header == 'admin_del_todo_list_send':
result = decode_msg.split(header_split)[1]
self.db_conn.delete_todo_data(result)
elif header == 'admin_todo_checked_send':
result = decode_msg.split(header_split)[1]
todo_id, checked = result.split(list_split_1)
result = self.db_conn.update_todo_list(todo_id, checked)
# 그래프 만드는 값 보내기
elif header == 'get_matplotlib':
result = decode_msg.split(header_split)[1]
result = self.db_conn.return_todo_list_dict(result)
result = json.dumps(result)
response_header = f"{f'get_matplotlib{header_split}{result}'}"
client_socket.send(bytes(response_header, "UTF-8"))
elif header == 'admin_todo_list_plus':
result = decode_msg.split(header_split)[1]
title, contents, user_id = result.split(list_split_1)
user_no = self.db_conn.return_user_no(user_id)
self.db_conn.insert_admin_todo_list(user_no, title, contents)
result = self.db_conn.return_todo_list_by_title(title)
result = json.dumps(result)
response_header = f"{f'recv_get_member_todo_list_for_admin2{header_split}{result}'}"
client_socket.send(bytes(response_header, "UTF-8"))
elif header == 'get_chatin_log':
result = decode_msg.split(header_split)[1]
user_id = result
chat_log = self.db_conn.return_chat_log(user_id)
result = json.dumps(chat_log)
response_header = f"{f'recv_get_chatin_log{header_split}{result}'}"
client_socket.send(bytes(response_header, "UTF-8"))
except:
pass
클라이언트 관련
class_clinet.py
더보기
from threading import *
from socket import *
# import socket
# _SERVER_IP = '10.10.20.109'
_SERVER_IP = gethostbyname(gethostname())
_SERVER_PORT = 5050
BUFFER = 50000
FORMAT = "utf-8"
_CONNECT = (_SERVER_IP, _SERVER_PORT)
header_split = chr(1)
list_split_1 = chr(2)
list_split_2 = chr(3)
class ClientApp:
def __init__(self, client_controller=None):
super().__init__()
self.client_controller = client_controller
self.client_socket = None
self._connected = None
self.connect_server()
self.listeningThread = Thread(target=self.check_server_response, daemon=True)
self.listeningThread.start()
# client 로그인 유저 정보 저장
self.user_no = None
self.user_id = None
self.user_name = None
self.user_pw = None
self.user_nickname = None
self.user_message = None
self.user_create_date = None
self.user_team = None
self.team_no = 1
def connect_server(self):
self.client_socket = socket(AF_INET, SOCK_STREAM)
self.client_socket.connect(_CONNECT)
message = f"{f'enter{header_split}접속한다':{BUFFER}}".encode(FORMAT)
self.client_send_message(message)
self._connected = True
def client_send_message(self, message):
self.client_socket.send(message)
def client_send_chat_message(self, input_chat):
team_no = 1
message = f"{f'send_chat{header_split}{self.user_no}{list_split_1}{team_no}{list_split_1}{self.user_name}{list_split_1}{input_chat}':{BUFFER}}".encode(
FORMAT)
self.client_socket.send(message)
def client_send_get_todolist(self):
message = f"{f'get_todolist{header_split}{self.user_no}{list_split_1}{self.team_no}':{BUFFER}}".encode(
FORMAT)
self.client_socket.send(message)
def client_send_json_message(self, message):
self.client_socket.send((bytes(message, "UTF-8")))
def check_server_response(self):
while self._connected:
try:
response = self.client_socket.recv(BUFFER).decode(FORMAT).strip()
self._parse_packet(response)
except Exception as e:
pass
def _parse_packet(self, p: str):
parsed = p.split(header_split)
header = parsed[0].strip()
if header == 'login':
result = parsed[1]
if result == 'False':
self.client_controller.emit_login(False)
else:
result = eval(result)
result = result[0]
self.user_no, self.user_name, self.user_id, self.user_pw, self.user_nickname, self.user_message, self.user_create_date, self.user_team = result
self.client_controller.emit_login(True)
elif header == 'duple':
result = parsed[1]
if result == 'False':
self.client_controller.emit_duple(False)
else:
self.client_controller.emit_duple(True)
elif header == 'insertuser':
result = parsed[1]
if result == 'False':
self.client_controller.emit_insertuser(False)
else:
self.client_controller.emit_insertuser(True)
if header == 'recv_chat':
result = parsed[1]
result = result.split(list_split_1)
self.client_controller.emit_recv_chat(result)
elif header == 'recv_get_notice':
result = parsed[1]
result = eval(result)
self.client_controller.emit_recv_get_notice(result)
elif header == 'recv_get_todolist':
result = parsed[1]
result = eval(result)
self.client_controller.emit_recv_get_todolist(result)
elif header == 'recv_get_member_todo_list_for_admin':
result = parsed[1]
result = result.split(list_split_1)
todo_list, user_id, user_name = result
todo_list = eval(todo_list)
result = todo_list, user_id, user_name
self.client_controller.emit_member_todo_list_for_admin(result)
elif header == 'recv_get_member_todo_list_for_admin2':
result = parsed[1]
todo_list = eval(result)
self.client_controller.emit_member_todo_list_for_admin2(todo_list)
elif header == 'update_user_message':
result = parsed[1]
self.user_message = result
self.client_controller.emit_update_user_message()
elif header == 'recv_insert_todo':
result = parsed[1]
self.client_controller.emit_refresh_todolist()
elif header == 'recv_insert_notice':
result = parsed[1]
self.client_controller.emit_refresh_notice()
elif header == 'recv_get_team_name_list':
result = parsed[1]
result = eval(result)
self.client_controller.emit_admin_login(result)
elif header == 'recv_get_team_name_list2':
result = parsed[1]
result = eval(result)
self.client_controller.emit_set_combobox(result)
elif header == 'recv_get_team_member':
result = parsed[1]
result = eval(result)
self.client_controller.emit_get_team_member(result)
elif header == 'get_matplotlib':
result = parsed[1]
result = eval(result)
self.client_controller.emit_set_matplotlib(result)
elif header == 'recv_get_chatin_log':
result = parsed[1]
result = eval(result)
self.client_controller.emit_get_chatin_log(result)
client_controller.py
더보기
import random
import sys
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import QPoint, Qt, pyqtSignal
from class_client.class_client import ClientApp
# ui 임풜트 예아
from main_code.front.main_window import NoticeBorad
header_split = chr(1)
list_split_1 = chr(2)
list_split_2 = chr(3)
BUFFER = 50000
FORMAT = "utf-8"
def set_main_window(clientcontroller):
main_window = NoticeBorad(clientcontroller)
return main_window
class ClientController(QtWidgets.QWidget):
def __init__(self, client_app=ClientApp):
super().__init__()
self.client_app = ClientApp(self)
# self.client_app.set_widget(self)
# ui 인슬퉐트화
self.main_window = NoticeBorad(self)
# ui 동작 관련 변수
self.list_widget_geometry_x = None
self.list_widget_geometry_y = None
self.drag_start_position = QPoint(0, 0)
self.main_window = None
# 좌상단 프로필
def emit_update_user_message(self):
self.main_window.update_user_message_signal.emit()
def emit_get_team_member(self, p):
self.main_window.get_team_member_signal.emit(p)
# 그래프
def emit_set_matplotlib(self, p):
self.main_window.set_matplotlib_signal.emit(p)
# 투두 ==============================
def emit_recv_get_todolist(self, p):
self.main_window.recv_get_todolist_signal.emit(p)
def emit_member_todo_list_for_admin(self, p):
self.main_window.member_todo_list_for_admin_signal.emit(p)
def emit_member_todo_list_for_admin2(self, p):
self.main_window.member_todo_list_for_admin_signal2.emit(p)
def emit_refresh_todolist(self):
self.main_window.refresh_todolist_signal.emit()
# 공지 ==============================
def emit_recv_get_notice(self, p):
self.main_window.recv_get_notice_signal.emit(p)
def emit_refresh_notice(self):
self.main_window.refresh_notice_signal.emit()
# 클라이언트에 send메시지 보내기======================================================================
# main_window에서 만든 구분자 send
def controller_send_message(self, message):
self.client_app.client_send_message(message)
# 메시지 send
def controller_send_chat_message(self, input_chat):
self.client_app.client_send_chat_message(input_chat)
def controller_send_get_todolist(self):
self.client_app.client_send_get_todolist()
# 데이터가 많아 list로 보낼때
def controller_send_json_message(self, message):
self.client_app.client_send_json_message(message)
# widget 이동 함수============================================================
def mousePressEvent(self, widget, event):
self.drag_start_position = QPoint(widget.x(), widget.y())
if event.button() == Qt.LeftButton:
self.drag_start_position = event.globalPos() - widget.frameGeometry().topLeft()
event.accept()
def mouseMoveEvent(self, widget, event):
if event.buttons() == Qt.LeftButton:
widget.move(event.globalPos() - self.drag_start_position)
event.accept()
# 런처 실행시 나오는 window ===========================================================================
def run(self): # 시작화면 show
self.main_window = set_main_window(self)
# self.main_window.show()
self.main_window.show()
def re_(self):
self.main_window = set_main_window(self)
self.main_window.show()
# self.main_window.show()
# 로그인 ===============================================================
def emit_login(self, p):
# 로그인 결과값 main에 전달 False면 실패창 True면 성공창 main화면 전환
if p:
self.main_window.recv_login_signal.emit(p)
else:
self.main_window.recv_login_signal.emit(p)
def emit_admin_login(self, p):
self.main_window.admin_login_signal.emit(p)
# 회원가입 ============================================================
def emit_duple(self, result): # 아이디 중복 확인 결과 보내기
self.main_window.reg_id_lab_signal.emit(result)
def emit_set_combobox(self, result):
self.main_window.set_combobox_signal.emit(result)
def emit_insertuser(self, result): # 회원가입 성공 결과 보내기
self.main_window.recv_emit_insertuser.emit(result)
def send_register_user_info(self):
pass
# 채팅=====================================================================
# 서버에서 받은 메시지을 누가 보낸것 인지 구분
def emit_recv_chat(self, result):
user_no, team_no, name, chat = result
if user_no == str(self.client_app.user_no): # 본인이 보낸 메시지면
self.main_window.emit_signal_my_chat.emit(result)
else: # 다른 유저가 보낸 메시지면
self.main_window.emit_signal_chat.emit(result)
def emit_get_chatin_log(self, result):
for i in result:
self.main_window.emit_signal_chat.emit(i)
메인 윈도우
main_window.py
더보기
# 모듈
import json
import sys
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.font_manager as fm
from PyQt5.QtWidgets import QMainWindow, QLayout, QLabel, QPushButton, QLineEdit, QTextEdit, QGraphicsDropShadowEffect, \
QApplication
from PyQt5.QtCore import Qt, pyqtSignal, QSize, QTimer
from PyQt5.QtGui import QFontDatabase, QIcon, QColor, QPixmap
# UI
from main_code.front.message import YourMsg, MyMsg # 메세지
# from main_code.front.client_controller import ClientController
from main_code.front.ui.ui_class_notice_board import Ui_NoticeBoard # 메인 화면
from main_code.front.profile_widget import ProFile # 프로필 변경
from main_code.front.category_list import CtgList # 카테고리 리스트
from main_code.front.Warning_dialog import DialogWarning # 경고창
from main_code.front.Font import Font # 폰트 클래스
from main_code.front.notice import Notice # 공지 캐러셀
from main_code.front.todolist import TodoList # 투두리스트 캐러셀
from main_code.front.notice_dialog import DialogNoticeAdd, DialogToDoAdd # 공지 다이얼로그, 투두리스트 다이얼로그
from main_code.front.team_process_list import MemberList # 관리자 창에서 보이는 멤버 리스트 캐럿셀
from main_code.front.admin_todo_edit_dialog import AdminTodoAdd # 관리자가 개인별 투두리스트 조회 및 추가하는 창
# 전역변수
header_split = chr(1)
list_split_1 = chr(2)
list_split_2 = chr(3)
BUFFER = 50000
FORMAT = "utf-8"
# def character_page_event(img):
# mywindow2 = AdminTodoAdd(img) # 캐릭터 버튼 프래스 이밴트 다이얼 로그
# mywindow2.exec()
class NoticeBorad(QMainWindow, Ui_NoticeBoard):
# 시그널 선언
reg_id_lab_signal = pyqtSignal(bool)
recv_emit_insertuser = pyqtSignal(bool)
emit_signal_my_chat = pyqtSignal(list)
emit_signal_chat = pyqtSignal(list)
recv_login_signal = pyqtSignal(bool)
recv_get_notice_signal = pyqtSignal(list)
recv_get_todolist_signal = pyqtSignal(list)
member_todo_list_for_admin_signal = pyqtSignal(tuple)
member_todo_list_for_admin_signal2 = pyqtSignal(list)
refresh_todolist_signal = pyqtSignal()
refresh_notice_signal = pyqtSignal()
admin_login_signal = pyqtSignal(list)
set_combobox_signal = pyqtSignal(list)
update_user_message_signal = pyqtSignal()
get_team_member_signal = pyqtSignal(list)
set_matplotlib_signal = pyqtSignal(list)
def __init__(self, client_controller):
super().__init__()
self.adminadd = None
self.ctg_clicked = None
self.user_role = None # 로그인한 유저의 역할
self.setupUi(self)
self.client_controller = client_controller
self.Warn = DialogWarning()
self.font = Font()
self.team_list = None
self.Notice_add = None
self.Todo_add = None
# window frame 설정
self.setAttribute(Qt.WA_TranslucentBackground, True)
self.setWindowFlags(Qt.FramelessWindowHint)
# 변수
self.init_var()
# 버튼 트리거 함수 호출
self.set_btn_trigger()
self.init_func()
def create_donut_chart(self, todo_people: list, todo_cnt: list):
sizes = todo_cnt
labels = todo_people
colors = ['#0F9B58', '#0FBC74', '#53B83A', '#3EC56B', '#1AA867', '#0FAF52', '#0FAF6B', '#53AF37']
# 비율에 따라 도넛 모양으로 그래프 그리기
plt.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90, wedgeprops=dict(width=0.4))
# 도넛 모양으로 그래프 그리기
centre_circle = plt.Circle((0, 0), 0.70, fc='white')
fig = plt.gcf()
fig.gca().add_artist(centre_circle)
# 모두 동일한 비율로 그리기
plt.axis('equal')
plt.tight_layout()
# 변수
def init_var(self):
self.ctg_clicked = None # 카테고리 버튼 클릭 확인(공지, 투두리스트)
self.update_timer = QTimer(self)
self.update_timer.setInterval(10)
self.vsb = self.chat_scrollarea.verticalScrollBar()
# widget 이동 함수=======================================================================
def mousePressEvent(self, event):
self.client_controller.mousePressEvent(self, event)
def mouseMoveEvent(self, event):
self.client_controller.mouseMoveEvent(self, event)
# 시그널======================================================================
def init_func(self):
"""클라이언트 - 서버 받는 시그널"""
self.reg_id_lab_signal.connect(self.set_reg_id_lab)
self.recv_emit_insertuser.connect(self.insertuser)
self.emit_signal_my_chat.connect(self.recv_my_chat)
self.emit_signal_chat.connect(self.recv_chat)
self.recv_login_signal.connect(self.login)
self.recv_get_notice_signal.connect(self.set_notice)
self.recv_get_todolist_signal.connect(self.set_todolist)
self.member_todo_list_for_admin_signal.connect(self.show_member_todo_list_for_admin2)
self.member_todo_list_for_admin_signal2.connect(self.show_member_todo_list_for_admin3)
self.refresh_todolist_signal.connect(self.get_todolist)
self.refresh_notice_signal.connect(self.get_notice)
self.admin_login_signal.connect(self.set_admin_ctg)
self.update_timer.timeout.connect(self.set_scrollbar)
self.set_combobox_signal.connect(self.set_combobox)
self.update_user_message_signal.connect(self.set_user_message)
self.get_team_member_signal.connect(self.set_team_member)
self.set_matplotlib_signal.connect(self.set_matplotlib)
self.update_timer.start()
def set_main_page_profil(self):
user_team = self.client_controller.client_app.user_name
user_name = self.client_controller.client_app.user_team
self.user_team.setText(user_team)
self.user_name.setText(user_name)
def set_user_message(self):
state = self.client_controller.client_app.user_message
self.user_state.setText(state)
def set_scrollbar(self):
if self.vsb.value() != self.vsb.maximum():
self.vsb.setValue(self.vsb.maximum())
def set_btn_trigger(self):
"""UI 버튼 시그널 연결"""
self.login_btn.clicked.connect(lambda state: self.click_login_btn()) # 로긴 버튼
self.register_btn.clicked.connect(lambda state: self.click_register_btn()) # 회원가입 화면 이동 버튼
self.reg_register_btn.clicked.connect(lambda state: self.click_reg_register_btn()) # 회원가입 버튼
self.send_btn.clicked.connect(lambda state: self.click_send_btn()) # 채팅 전송 버튼
self.chat_edit.returnPressed.connect(self.click_send_btn)
self.plus_button.clicked.connect(lambda state: self.click_plus_button())
def set_font(self):
"""기본 폰트 적용하는 부분"""
# 로그인 창
self.login_title_lab.setFont(Font.title(1))
self.login_id_lab.setFont(Font.text(3))
self.login_pw_lab.setFont(Font.text(3))
self.login_id_edit.setFont(Font.text(3, False))
self.login_pw_edit.setFont(Font.text(3, False))
self.login_btn.setFont(Font.button(2))
self.register_btn.setFont(Font.button(2))
# 회원가입 창
reg_lab = self.register_page.findChildren(QLabel)
reg_edit = self.register_page.findChildren(QLineEdit)
[lab.setFont(Font.text(3)) for lab in reg_lab]
self.comboBox.setFont(Font.text(3))
[edit.setFont(Font.text(3, False)) for edit in reg_edit]
self.reg_title_lab.setFont(Font.title(2))
self.reg_sub_title.setFont(Font.text(3))
self.reg_register_btn.setFont(Font.button(1))
# -- 메인창
# 프로필창
profile_lab = self.profile_widget.findChildren(QLabel)
[lab.setFont(Font.text(3)) for lab in profile_lab]
# 채팅
self.chat_edit.setFont(Font.text(2))
# 관리자 페이지창
self.team_process_lab.setFont(Font.text(1))
self.team_todo_label.setFont(Font.text(1))
self.label.setFont(Font.title(3))
def ctg_list_show(self):
"""카테고리 넣어주기"""
self.ctg_dict = {
'프로필 수정': ['user.png', None],
'채팅': ['send_black.png', self.chat_page],
'공지': ['bell.png', self.notice_page],
'투두리스트': ['heart.png', self.notice_page],
'로그아웃': ['out.png', self.notice_page]
}
self.ctg_list = list(self.ctg_dict.keys())
self.event_dict = {'채팅': [None, self.pass_, self.plus_button.hide],
'공지': [self.notice_v_lay, self.get_notice, self.plus_button.hide],
'투두리스트': [self.notice_v_lay, self.get_todolist, self.plus_button.show],
'로그아웃': [None, self.logout_, self.plus_button.show],
'....': [self.team_mem_v_lay, self.plus_button.hide]
}
for ctg in self.ctg_list: # 카테고리 이미지, 카테고리 이름 넣어주기
img_name = self.ctg_dict[ctg][0]
ctg_ = CtgList(img_name=img_name, c_name=ctg, parent=self, role=self.user_role)
self.category_v_lay.addWidget(ctg_)
def pass_(self):
pass
def click_plus_button(self):
actions = {
'공지': self.Notice_add.exec_,
'투두리스트': self.Todo_add.exec_
}
action = actions.get(self.ctg_clicked)
if action:
action()
def ctg_list_trigger(self, ctg_name):
"""카테고리에 따라 페이지 변경 혹은 창 띄우기"""
name = self.client_controller.client_app.user_name
state = self.client_controller.client_app.user_message
self.ctg_clicked = ctg_name
for c in self.ctg_list:
if ctg_name == '프로필 수정':
img_path = 'user_green.png'
p_ = ProFile(self, img=img_path, name=name, state=state)
p_.show_dialog()
break
elif ctg_name == c:
self.clear_layout(self.event_dict[ctg_name][0]) # 레이아웃 비우기
self.event_dict[ctg_name][1]()
self.event_dict[ctg_name][2]()
self.inner_stackedWidget.setCurrentWidget(self.ctg_dict[c][1])
def admin_ctg_list_show(self, result):
"""카테고리 넣어주기"""
self.admin_ctg_dict = {
'프로필 수정': ['user.png', None],
'채팅': ['send_black.png', self.chat_page],
'공지': ['bell.png', self.notice_page],
}
# 팀카테고리 이미지, 화면 딕셔너리에 저장
for i in result:
self.admin_ctg_dict[i] = ['user.png', self.team_page]
self.admin_ctg_dict['로그아웃'] = ['out.png', self.notice_page]
self.admin_ctg_list = list(self.admin_ctg_dict.keys())
self.adminevent_dict = {'채팅': [None, self.pass_, self.plus_button.hide],
'공지': [self.notice_v_lay, self.get_notice, self.plus_button.show],
'투두리스트': [self.notice_v_lay, self.get_todolist, self.plus_button.show],
'로그아웃': [None, self.logout_, self.plus_button.show]
}
# 팀카테고리별 클릭 이벤트 설정
for i in result:
self.adminevent_dict[i] = [None, self.get_team_member, self.plus_button.hide]
for ctg in self.admin_ctg_list: # 카테고리 이미지, 카테고리 이름 넣어주기
img_name = self.admin_ctg_dict[ctg][0]
ctg_ = CtgList(img_name=img_name, c_name=ctg, parent=self, role=self.user_role)
self.category_v_lay.addWidget(ctg_)
def logout_(self):
self.close()
self.client_controller.re_()
# self.stackedWidget.setCurrentWidget(self.login_page)
def admin_ctg_list_trigger(self, ctg_name):
"""카테고리에 따라 페이지 변경 혹은 창 띄우기(관리자)"""
name = self.client_controller.client_app.user_name
state = self.client_controller.client_app.user_message
self.ctg_clicked = ctg_name
for c in self.admin_ctg_list:
if ctg_name == '프로필 수정':
p_ = ProFile(self, img=None, name=name, state=state)
p_.show_dialog()
break
# 클릭한 카테고리의 이름이 팀이름중 하나이면
if ctg_name in self.team_list:
self.get_matplotlib(ctg_name)
self.get_team_member(ctg_name)
break
elif ctg_name == c:
self.clear_layout(self.adminevent_dict[ctg_name][0]) # 레이아웃 비우기
self.adminevent_dict[ctg_name][1]()
self.adminevent_dict[ctg_name][2]()
self.inner_stackedWidget.setCurrentWidget(self.admin_ctg_dict[c][1])
def get_matplotlib(self, ctg_name):
message = f"{f'get_matplotlib{header_split}{ctg_name}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
# people, cnt = self.data.return_todo_list_dict('개발부') # db에서 값 가져오기(서버에서 연결하는 부분으로 추가 예정)
def set_matplotlib(self, result):
# 캔버스 만들어서 그래프 그리기
self.clear_layout(self.v_lay_graph)
canvas = FigureCanvas(plt.figure())
self.v_lay_graph.addWidget(canvas)
people, cnt = result
self.create_donut_chart(people, cnt)
def set_admin_ctg(self, result):
self.admin_ctg_list_show(result)
def show_member_todo_list_for_admin(self, user_id, user_no, user_name):
message = f"{f'get_todolist2{header_split}{user_id}{list_split_1}{user_name}{list_split_1}{user_no}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
def show_member_todo_list_for_admin3(self, result):
self.adminadd.test(result)
# 유저 프로필 상메 업데이트
def update_user_message(self, user_message):
message = f"{f'update_user_message{header_split}{self.client_controller.client_app.user_no}{list_split_1}{user_message}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
# 레이아웃 비우기
def clear_layout(self, layout: QLayout):
"""레이아웃 안의 모든 객체를 지웁니다."""
if layout is None or not layout.count():
return
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.setParent(None)
# 아이템이 레이아웃일 경우 재귀 호출로 레이아웃 내의 위젯 삭제
else:
self.clear_layout(item.layout())
# 팀 화면============================================
# 팀이름을 인자로 멤버들 반환요청
def get_team_member(self, ctg_name):
self.label.setText(ctg_name)
message = f"{f'get_team_member{header_split}{ctg_name}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
# 팀원 목록 반환받음
def set_team_member(self, result):
self.inner_stackedWidget.setCurrentWidget(self.team_page)
self.clear_layout(self.team_mem_v_lay)
members = result
for i in members:
user = MemberList(self, i)
self.team_mem_v_lay.addWidget(user)
def admin_del_todo_list_send2(self, todo_title):
message = f"{f'admin_del_todo_list_send{header_split}{todo_title}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
def admin_todo_checked_send2(self, todo_id, checked):
message = f"{f'admin_todo_checked_send{header_split}{todo_id}{list_split_1}{checked}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
def admin_todo_list_plus2(self, title, contents, user_id):
message = f"{f'admin_todo_list_plus{header_split}{title}{list_split_1}{contents}{list_split_1}{user_id}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
pass
# 투루리스트==========================================
def insert_todo_list(self, title, contents):
msg = title, contents, self.client_controller.client_app.user_no
message = f"{f'insert_todo{header_split}{msg}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
def get_todolist(self):
self.clear_layout(self.notice_v_lay) # 레이아웃 비우기
self.client_controller.controller_send_get_todolist()
def set_todolist(self, result):
"""
받아온 유저의 투두리스트들을 캐러셀로 만들어 집어넣는다
:param result:
:return:
"""
people_lab = result[1]
if len(people_lab) == 0:
people_lab = None
else:
pass
for i in result[0]:
todo = TodoList(self, i, people_lab, self.user_role)
self.notice_v_lay.addWidget(todo)
def send_todo_list_checked(self, todo_id, btn_checked):
message = f"{f'update_todo_checked{header_split}{todo_id}{list_split_1}{btn_checked}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
# 공지 화면 =====================================================================================
def insert_notice(self, title, contents, team):
msg = title, contents, team
message = f"{f'insert_notice{header_split}{msg}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
def set_notice(self, result):
for i in result:
notice = Notice(self, i, self.user_role)
self.notice_v_lay.addWidget(notice)
def del_notice(self, title):
msg = title
message = f"{f'delete_notice{header_split}{msg}':{BUFFER}}".encode(FORMAT)
self.client_controller.controller_send_message(message)
# 공지를 db에요청 함수
def get_notice(self):
self.clear_layout(self.notice_v_lay) # 레이아웃 비우기
# 유저가 입력한 로그인 정보 encode
user_no = self.client_controller.client_app.user_no
user_nn = self.client_controller.client_app.user_nickname
message = f"{f'get_notice{header_split}{user_no}{list_split_1}{user_nn}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
# window widget show=======================================================================
def show(self):
message = f"{f'get_team_name_list2{header_split}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
self.stackedWidget.setCurrentWidget(self.login_page)
self.inner_stackedWidget.setCurrentWidget(self.chat_page)
self.set_font() # 폰트 설정
self.style_init() # ui 설정
super().show()
def style_init(self):
# 카테고리 바 그림자 넣기
self.set_background_color(self.category_bar)
def set_background_color(self, obj):
effect = QGraphicsDropShadowEffect()
effect.setColor(QColor(0, 0, 0, 150))
effect.setBlurRadius(5)
effect.setOffset(5, 5) # 객체와 그림자 사이의 거리 또는 변위
obj.setGraphicsEffect(effect)
# 채팅 =========================================================================================
# 전송버튼 클릭시 채팅을 서버에 보내는 함수
def get_chat(self): # 로그인 할때 채팅 기록 불러오기
user_id = self.client_controller.client_app.user_id
message = f"{f'get_chatin_log{header_split}{user_id}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
def click_send_btn(self):
if len(self.chat_edit.text()) >= 1:
input_chat = self.chat_edit.text()
self.chat_edit.clear() # 채팅바 클리어
self.client_controller.controller_send_chat_message(input_chat) # 입력된 채팅 client_controller에 보내기
# 서버에서 채팅 메시지 받는 함수
def recv_my_chat(self, result): # 본인이 보낸 메시지라면
user_no, team_no, name, chat = result
message_widget = MyMsg(name, chat)
self.chat_v_lay.addWidget(message_widget)
def recv_chat(self, result): # 다른 사람이 보낸 메시지라면
if len(result) > 2:
user_no, team_no, name, chat = result
else:
name, chat = result
message_widget = YourMsg(name, chat)
self.chat_v_lay.addWidget(message_widget)
# 채팅방 입장시 db에 저장된 채팅 요청
def send_det_chat(self):
message = f"{f'get_chat{header_split}{user_input_id}':{BUFFER}}".encode(FORMAT)
self.client_controller.controller_send_message(message)
# 로그인 함수=======================================================================
def click_login_btn(self):
user_input_id = self.login_id_edit.text() # 유저가 입력한 id
user_input_pw = self.login_pw_edit.text() # 유저가 입력한 pw
self.login_id_edit.clear()
self.login_pw_edit.clear()
# 유저가 입력한 로그인 정보 encode
message = f"{f'login{header_split}{user_input_id}{list_split_1}{user_input_pw}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
# 로그인 결과 알림 및 화면 전환
def login(self, result):
self.user_role = self.client_controller.client_app.user_nickname
if result:
if '관리자' in self.client_controller.client_app.user_nickname:
# db에 있는 팀명 리스트 요청 리스트 받아올때 카테고리 집어넣기
# 유저가 입력한 로그인 정보 encode
message = f"{f'get_team_name_list{header_split}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
else:
self.ctg_list_show() # 카테고리 넣어주기
self.set_main_page_profil()
self.set_user_message()
self.get_chat()
self.Warn.set_dialog_type(bt_cnt=1, t_type='login_cmplt') # 알림창 띄우기
self.Warn.show_dialog()
self.user_role = self.client_controller.client_app.user_nickname
# self.login_user_role(user_role)
self.stackedWidget.setCurrentWidget(self.main_page) # 화면전환
else:
self.Warn.set_dialog_type(bt_cnt=1, t_type='loginfailed') # 알림창 띄우기
# 회원 가입 함수=======================================================================
def insertuser(self, result):
if result:
self.Warn.set_dialog_type(bt_cnt=1, t_type='register_cmplt')
self.Warn.show_dialog()
self.stackedWidget.setCurrentWidget(self.login_page)
else:
self.Warn.set_dialog_type(bt_cnt=1, t_type='register_failed')
self.Warn.show_dialog()
def set_combobox(self, result):
self.team_list = result
self.Notice_add = DialogNoticeAdd(self, self.team_list)
self.Todo_add = DialogToDoAdd(self, self.team_list)
for i in result:
self.comboBox.addItem(i)
# 회원 가입 화면 으로 이동 하는 함수
def click_register_btn(self):
self.stackedWidget.setCurrentWidget(self.register_page)
# 아이디 중복 검사
def click_reg_register_btn(self):
self.send_duple()
# 아이디 중복검사후 pw name nickname 검사
def click_reg_register_btn2(self):
if self.register_check():
self.register_user()
# 유저가 입력한 아이디 server에 보내서 중복확인
def send_duple(self):
input_reg_id = self.reg_id_edit.text()
message = f"{f'duple{header_split}{input_reg_id}':{BUFFER}}".encode(
FORMAT)
self.client_controller.controller_send_message(message)
# 조건 충족 회원가입 진행
def register_user(self):
input_reg_id = self.reg_id_edit.text()
input_reg_pw = self.reg_pw_edit.text()
input_reg_name = self.reg_name_edit.text()
input_reg_nn = self.reg_nn_edit.text()
input_reg_team = self.comboBox.currentText()
result = [input_reg_id, input_reg_pw, input_reg_name, input_reg_nn, input_reg_team]
user_info = json.dumps(result)
message = f"{f'insertuser{header_split}{user_info}'}"
self.client_controller.controller_send_json_message(message)
# 아이디 중복검사 결과에따른 이벤트
def set_reg_id_lab(self, result):
if result is True:
self.reg_id_lab.setText('ID 사용가능')
self.reg_id_lab.setStyleSheet('color:blue;')
self.click_reg_register_btn2()
else:
self.reg_id_lab.setText('ID 사용불가')
self.reg_id_lab.setStyleSheet('color:red;')
def set_reg_name_lab(self):
self.reg_name_lab.setText('이름은 두 글자 이상이여야 합니다.')
self.reg_name_lab_lab.setStyleSheet('color:red;')
def set_reg_nn_lab(self):
self.reg_nn_lab.setText('닉네임은 두 글자 이상이여야 합니다.')
self.reg_nn_lab.setStyleSheet('color:red;')
def set_reg_pw_lab(self):
self.reg_pw_lab.setText('비밀번호가 같지 않습니다.')
self.reg_pw_lab.setStyleSheet('color:red;')
def set_reg_pw_lab2(self):
self.reg_pw_lab.setText('비밀번호를 6자리 이상 적어주세요.')
self.reg_pw_lab.setStyleSheet('color:red;')
# 유저가 입력한 회원가입조건 검사
def register_check(self):
self.reg_name_lab.setText('이름')
self.reg_nn_lab.setText('닉네임')
self.reg_pw_lab.setText('비밀번호')
if len(self.reg_name_edit.text()) < 2:
self.set_reg_name_lab()
return False
else:
self.reg_name_lab.setStyleSheet('color:black;')
if len(self.reg_nn_edit.text()) < 2:
self.set_reg_nn_lab()
return False
else:
self.reg_nn_lab.setStyleSheet('color:black;')
if len(self.reg_pw_edit.text()) < 6:
self.set_reg_pw_lab2()
return False
else:
self.reg_pw_lab.setStyleSheet('color:black;')
if self.reg_pw_edit.text() != self.reg_pw_check_edit.text():
self.set_reg_pw_lab()
return False
if self.reg_id_lab.text() != 'ID 사용가능':
return False
return True
def log_out(self):
"""로그아웃 함수"""
self.user_role = None
self.stackedWidget.setCurrentWidget(self.login_page)
'공부_백업용 > 프로젝트 모음' 카테고리의 다른 글
[팀프로젝트 주제발표] 머신러닝과 딥러닝을 활용한 출결관리 시스템 주제 발표 (0) | 2023.08.31 |
---|---|
[팀프로젝트] (23.7.31 ~ 8.12) 빅데이터 분석을 활용한 프렌차이즈(올리브영) 창업 지역 추천 프로그램 (0) | 2023.08.21 |
[팀프로젝트] (23.7.10 ~ 7.16) 채팅 프로그램 만들기 개발완료보고서 (2) | 2023.08.19 |
[팀프로젝트] (23.7.3 ~ 7.8) 서울 관광 프로그램 개발완성보고서 (0) | 2023.08.19 |
[개인프로젝트] (23.6.13 ~ 6.23) 메가커피 키오스크 만들기 개발완료보고서 (5) | 2023.08.18 |