1. DayCalOwner 모델 변경

# 화주 모델
class DayCalOwner(Base):
    __tablename__ = 'daycal_owner'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String, unique=True)

    def __init__(self, name):
        self.name = name
  • autoincrement 가 설정된 id 속성을 추가

  • primary key를 name에서 id로 변경
  • name을 primaryk 중복 불가능한 값으로 하기 위해 unique 설정

 

 

2. actions.py

from PySide6.QtWidgets import QLabel, QGridLayout, QPushButton, QLineEdit
from sqlalchemy.exc import DatabaseError
from sqlalchemy.orm.exc import UnmappedInstanceError

from controller.db_manager import session
from models.models import DayCalOwner
from widgets.simple import Dialog


# 화주 추가
def create_owner(main_window, table_widget, name_data=None):
    # 입력받은 이름이 이미 있는 경우
    if name_data:
        name = name_data

    # 이름을 입력받아야 하는 경우
    else:
        # 다이얼로그 위젯 생성
        create_owner_dialog = Dialog()
        create_owner_dialog.setWindowTitle('화주 추가')
        create_owner_dialog.setGeometry(500, 500, 300, 50)

        # 화주 이름을 입력받기 위한 다이얼로그 ui 세팅
        grid = QGridLayout()
        input_name = QLineEdit()
        input_name.setPlaceholderText('화주 이름')
        input_name.returnPressed.connect(create_owner_dialog.success)
        submit = QPushButton('추가')
        submit.clicked.connect(create_owner_dialog.success)
        grid.addWidget(QLabel('화주 이름: '), 0, 0, 1, 1)
        grid.addWidget(input_name, 0, 1, 1, 2)
        grid.addWidget(submit, 1, 0, 1, 3)
        create_owner_dialog.setLayout(grid)

        # 다이얼로그를 modal 하게 표시
        create_owner_dialog.show_modal()

        # 입력이 취소된경우 (다이얼로그를 그냥 종료한 경우) 추가절차 종료
        if create_owner_dialog.canceled:
            return

        # 다이얼로그에서 입력이 완료되면 입력받은 이름을 name 으로 설정
        name = input_name.text()

    # 새 화주 추가
    new_owner = DayCalOwner(name)
    try:
        session.add(new_owner)
        session.commit()
        table_widget.owner_added(name)
    except DatabaseError:
        main_window.statusBar().showMessage('>> 이미 등록된 화주입니다.')
        session.rollback()
  • main_window 에 구현했던 화주 추가 액션을 controller 디렉토리의 actions.py 로 이동

  • self 대신 메인윈도우의 인스턴스와 화주 추가 결과를 반영할 table이 위치한 위젯의 인스턴스를 인자로 받음

  • dialog를 통하지않고 이름을 입력받을 상황을 대비하여 name_data 인자를 추가

  • name_data가 입력되었다면 다이얼로그로 이름을 입력받지 않고 name_data를 name으로 설정

  • 중복된 이름일 경우 status bar에 이미 등록된 화주임을 표시

  • name이 더이상 primary key가 아닌 unique key이기 때문에 이름이 중복될 경우 add 가 아닌 commit단계에서
    예외가 발생한다. 그러므로 예외 발생시 이미 적용된 add 를 취소하기 위해 rollback을 호출해줘야한다.

 

from controller import actions

    ``` 생략 ```
 
        # 화주추가 액션 추가
        create_owner = QAction(QIcon('src/img/create_owner_icon.png'), '화주 추가', self)
        create_owner.setShortcut('Ctrl+Shift+A')
        create_owner.setStatusTip('화주 추가')
        create_owner.triggered.connect(lambda: actions.create_owner(self, self.central_widget.doc_tab.tab1))
        file_menu.addAction(create_owner)
        tool_bar.addAction(create_owner)
        
    ``` 생략 ```
  • contoller.actions를 import 한 뒤 create_owner 액션의 triggered 시그널에 lambda 함수의 형태로 연결해준다.

 

 

3. simple.py

from PySide6.QtCore import QDateTime, QTimer
from PySide6.QtWidgets import QLabel, QDialog


# 시간레이블 클래스(QLabel 상속)
# 1초마다 현재 날짜/시간을 갱신하여 표시하는 레이블
class TimeLabel(QLabel):
    def __init__(self):
        super().__init__()
        self.setText(QDateTime.currentDateTime().toString('yyyy년 MM월 dd일 ddd hh:mm:ss'))
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.timeout)
        self.timer.start(100)

    def timeout(self):
        self.setText(QDateTime.currentDateTime().toString('yyyy년 MM월 dd일 ddd hh:mm:ss'))


# 다이얼로그(QDialog 상속)
class Dialog(QDialog):
    def __init__(self):
        super().__init__()
        self.canceled = True

    def show_modal(self):
        return super().exec_()

    def success(self):
        self.canceled = False
        self.close()
  • Dialog, TimeLabel 등의 구조가 간단한 위젯들을 widgets/simple.py 에 분리

 

 

4. DayCal 위젯

# 일일 정산서 계산서 위젯
class DayCal(QWidget):
    # 생성자
    def __init__(self):
        super().__init__()
        self.owners = [q.name for q in session.query(DayCalOwner).order_by(DayCalOwner.id)]
        self.num_of_owners = len(self.owners)
        self.input_table = QTableWidget()
        self.input_table.setParent(self)
        self.init_ui()

    ``` 생략 ```
  • 화주 데이터의 id를 기반으로 순서를 유지하도록 쿼리시에 order_by 를 통해 id를 기준으로 오름차순 정렬

 

 

5. create_owner 수정

# 화주 추가
def create_owner(main_window, table_widget, name_data=None):
    # 입력받은 이름이 이미 있는 경우
    if name_data:
        name = name_data

    # 이름을 입력받아야 하는 경우
    else:
        # 다이얼로그 위젯 생성
        create_owner_dialog = Dialog()
        create_owner_dialog.setWindowTitle('화주 추가')
        create_owner_dialog.setGeometry(500, 500, 300, 50)

        # 화주 이름을 입력받기 위한 다이얼로그 ui 세팅
        grid = QGridLayout()
        input_name = QLineEdit()
        input_name.setPlaceholderText('화주 이름')
        input_name.returnPressed.connect(create_owner_dialog.success)
        submit = QPushButton('추가')
        submit.clicked.connect(create_owner_dialog.success)
        grid.addWidget(QLabel('화주 이름: '), 0, 0, 1, 1)
        grid.addWidget(input_name, 0, 1, 1, 2)
        grid.addWidget(submit, 1, 0, 1, 3)
        create_owner_dialog.setLayout(grid)

        # 다이얼로그를 modal 하게 표시
        create_owner_dialog.show_modal()

        # 입력이 취소된경우 (다이얼로그를 그냥 종료한 경우) 추가절차 종료
        if create_owner_dialog.canceled:
            return

        # 다이얼로그에서 입력이 완료되면 입력받은 이름을 name 으로 설정
        name = input_name.text()

    # 새 화주 추가
    new_owner = DayCalOwner(name)
    try:
        session.add(new_owner)
        session.commit()
        table_widget.owner_added(name)
    except DatabaseError:
        main_window.statusBar().showMessage('>> 이미 등록된 화주입니다.')
        session.rollback()
  • 이름을 입력하기 위한 위젯을 QPlainText 에서 QLineEdit 으로 변경

  • returnPressed 시그널을 사용하여 엔터키에도 반응하도록 수정
  • 다이얼로그에 canceled 속성을 추가하여 단순 종료와 데이터를 정상적으로 제출한 종료를 구분

  • 데이터를 정상적으로 제출했을 때만 기능이 동작하도록 수정

 

'개인 프로젝트 > Accounting Program' 카테고리의 다른 글

#17 QTableView  (0) 2021.11.22
#16 화주 삭제, 화주 이름 변경  (0) 2021.11.02
#14 화주 추가  (0) 2021.11.01
#13 데이터베이스 연결  (0) 2021.10.30
#12 메인 화면 구성  (0) 2021.10.28

+ Recent posts