from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QMessageBox, QWidget, QApplication from PyQt5.QtCore import Qt from PyQt5.QtGui import QIcon import os from db.database import register_admin from gui.custom_notifications import CustomNotificationDialog import config class RegisterDialog(QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle('Register') # Ensure this dialog is a real top-level window so taskbar uses app icon. self.setWindowFlags((self.windowFlags() | Qt.Window) & ~Qt.WindowContextHelpButtonHint | Qt.WindowMinimizeButtonHint) icon_path = config.get_app_icon_path() if icon_path: self.setWindowIcon(QIcon(icon_path)) self._apply_responsive_size(600, 500) if icon_path: self.setWindowIcon(QIcon(icon_path)) # Set background color self.setStyleSheet("QDialog { background-color: #fafafa; }") # Main layout layout = QVBoxLayout() layout.setContentsMargins(40, 40, 40, 40) layout.setSpacing(5) # Title title = QLabel('Sistem Klasifikasi Jurusan') title.setStyleSheet("font-size: 28px; font-weight: bold; color: #1a202c; margin-bottom: 5px; margin-top: 0px;font-family: 'Segoe UI', Arial, sans-serif;") title.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) title.setWordWrap(True) layout.addWidget(title) subtitle = QLabel('Registrasi Akun Baru') subtitle.setStyleSheet("font-size: 18px; color: #4a5568; margin-bottom: 30px;font-family: 'Segoe UI', Arial, sans-serif;") subtitle.setAlignment(Qt.AlignCenter) layout.addWidget(subtitle) # Username self.label_user = QLabel('Username') self.label_user.setStyleSheet("font-size: 18px; color: #2d3748; font-weight: bold; margin-bottom: 0px;font-family: 'Segoe UI', Arial, sans-serif;") layout.addWidget(self.label_user) self.input_user = QLineEdit() self.input_user.setFixedHeight(64) from PyQt5.QtWidgets import QSizePolicy self.input_user.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) #self.input_user.setFixedWidth(520) self.input_user.setPlaceholderText('Masukkan username') self.input_user.setStyleSheet("font-size: 20px; padding: 0px 12px; margin-bottom: 20px; color: #2d3748; background-color: white; border: 1px solid #e2e8f0; border-radius: 6px;font-family: 'Segoe UI', Arial, sans-serif;") layout.addWidget(self.input_user) # Password self.label_pass = QLabel('Password') self.label_pass.setStyleSheet("font-size: 18px; color: #2d3748; font-weight: bold; margin-bottom: 0px;font-family: 'Segoe UI', Arial, sans-serif;") layout.addWidget(self.label_pass) # Password container with toggle button password_container = QHBoxLayout() password_container.setSpacing(0) password_container.setContentsMargins(0, 0, 0, 0) self.input_pass = QLineEdit() self.input_pass.setFixedHeight(64) from PyQt5.QtWidgets import QSizePolicy self.input_pass.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) #self.input_pass.setFixedWidth(465) self.input_pass.setPlaceholderText('Masukkan password') self.input_pass.setEchoMode(QLineEdit.Password) self.input_pass.setStyleSheet("font-size: 20px; padding: 0px 12px; color: #2d3748; background-color: white; border: 1px solid #e2e8f0; border-top-left-radius: 6px; border-bottom-left-radius: 6px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-right: none;font-family: 'Segoe UI', Arial, sans-serif;") self.input_pass.setMinimumWidth(0) self.btn_toggle_pass = QPushButton('👁') self.btn_toggle_pass.setFixedSize(64, 64) self.btn_toggle_pass.setStyleSheet(""" QPushButton { font-size: 18px; border: 1px solid #e2e8f0; border-left: none; border-top-left-radius: 0px; border-bottom-left-radius: 0px; border-top-right-radius: 6px; border-bottom-right-radius: 6px; background-color: white; color: #718096; margin-left: -8px; } QPushButton:hover { background-color: #f7fafc; color: #4a5568; } QPushButton:pressed { background-color: #edf2f7; } """) self.btn_toggle_pass.setCursor(Qt.PointingHandCursor) self.btn_toggle_pass.clicked.connect(self.toggle_password_visibility) self.password_visible = False password_container.addWidget(self.input_pass) password_container.addWidget(self.btn_toggle_pass) password_container.setStretch(0, 1) password_widget = QWidget() password_widget.setLayout(password_container) password_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) password_widget.setStyleSheet("margin-bottom: 20px;") layout.addWidget(password_widget) # Confirm Password self.label_confirm = QLabel('Konfirmasi Password') self.label_confirm.setStyleSheet("font-size: 18px; color: #2d3748; font-weight: bold; margin-bottom: 0px;font-family: 'Segoe UI', Arial, sans-serif;") layout.addWidget(self.label_confirm) # Confirm password container with toggle button confirm_container = QHBoxLayout() confirm_container.setSpacing(0) confirm_container.setContentsMargins(0, 0, 0, 0) self.input_confirm = QLineEdit() self.input_confirm.setFixedHeight(74) self.input_confirm.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) #self.input_confirm.setFixedWidth(465) self.input_confirm.setPlaceholderText('Masukkan password kembali') self.input_confirm.setEchoMode(QLineEdit.Password) self.input_confirm.setStyleSheet("font-size: 20px; padding: 0px 12px; color: #2d3748; background-color: white; border: 1px solid #e2e8f0; border-top-left-radius: 6px; border-bottom-left-radius: 6px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-right: none;font-family: 'Segoe UI', Arial, sans-serif;") self.input_confirm.setMinimumWidth(0) self.btn_toggle_confirm = QPushButton('👁') self.btn_toggle_confirm.setFixedSize(74, 74) self.btn_toggle_confirm.setStyleSheet(""" QPushButton { font-size: 18px; border: 1px solid #e2e8f0; border-left: none; border-top-left-radius: 0px; border-bottom-left-radius: 0px; border-top-right-radius: 6px; border-bottom-right-radius: 6px; background-color: white; color: #718096; margin-left: 0px; } QPushButton:hover { background-color: #f7fafc; color: #4a5568; } QPushButton:pressed { background-color: #edf2f7; } """) self.btn_toggle_confirm.setCursor(Qt.PointingHandCursor) self.btn_toggle_confirm.clicked.connect(self.toggle_confirm_visibility) self.confirm_visible = False confirm_container.addWidget(self.input_confirm) confirm_container.addWidget(self.btn_toggle_confirm) confirm_container.setStretch(0, 1) self.confirm_widget = QWidget() self.confirm_widget.setLayout(confirm_container) self.confirm_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.confirm_widget.setMinimumWidth(0) self.confirm_widget.setMaximumWidth(16777215) self.confirm_widget.setStyleSheet("margin-bottom: 30px;") layout.addWidget(self.confirm_widget) # Register button self.btn_register = QPushButton('Register') self.btn_register.setFixedHeight(60) self.btn_register.setCursor(Qt.PointingHandCursor) self.btn_register.setStyleSheet(""" QPushButton { font-size: 18px; font-weight: bold; background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #667eea, stop:1 #764ba2); color: white; border: none; border-radius: 6px; margin-bottom: 20px; font-family: 'Segoe UI', Arial, sans-serif; } QPushButton:hover { background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #5568d3, stop:1 #6a3b91); } QPushButton:pressed { background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #4a5abc, stop:1 #5a3080); } """) self.btn_register.clicked.connect(self.handle_register) layout.addWidget(self.btn_register) # Back to login link container login_container = QHBoxLayout() login_container.setContentsMargins(0, 0, 0, 0) login_container.setSpacing(5) login_container.addStretch() # Center the content # Normal text part self.label_login_text = QLabel('Sudah punya akun?') self.label_login_text.setStyleSheet(""" QLabel { font-size: 16px; color: #4a5568; background-color: transparent; font-family: 'Segoe UI', Arial, sans-serif; } """) login_container.addWidget(self.label_login_text) # Clickable login link self.btn_back = QPushButton('Login disini') self.btn_back.setFixedHeight(36) self.btn_back.setStyleSheet(""" QPushButton { font-size: 16px; font-weight: bold; color: #667eea; background-color: transparent; border: none; text-decoration: underline; font-family: 'Segoe UI', Arial, sans-serif; } QPushButton:hover { color: #764ba2; } """) self.btn_back.clicked.connect(self.back_to_login) self.btn_back.setCursor(Qt.PointingHandCursor) login_container.addWidget(self.btn_back) login_container.addStretch() # Center the content login_widget = QWidget() login_widget.setLayout(login_container) layout.addWidget(login_widget) # Enter key triggers register self.input_user.returnPressed.connect(self.handle_register) self.input_pass.returnPressed.connect(self.handle_register) self.input_confirm.returnPressed.connect(self.handle_register) self.setLayout(layout) self.register_success = False self.back_to_login_clicked = False self.should_show_login = False # Flag untuk menunjukkan bahwa user ingin kembali ke halaman login self._sync_confirm_row_width() self._native_icon_applied = False def _apply_native_windows_icon(self): """Set native HWND icons to avoid default taskbar icon on first window show.""" if os.name != 'nt': return icon_path = config.get_app_icon_path() if not icon_path or not os.path.exists(icon_path): return try: import ctypes WM_SETICON = 0x0080 ICON_SMALL = 0 ICON_BIG = 1 IMAGE_ICON = 1 LR_LOADFROMFILE = 0x0010 LR_DEFAULTSIZE = 0x0040 hicon = ctypes.windll.user32.LoadImageW( None, icon_path, IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE, ) if hicon: hwnd = int(self.winId()) ctypes.windll.user32.SendMessageW(hwnd, WM_SETICON, ICON_SMALL, hicon) ctypes.windll.user32.SendMessageW(hwnd, WM_SETICON, ICON_BIG, hicon) except Exception: pass def showEvent(self, event): super().showEvent(event) if not self._native_icon_applied: self._apply_native_windows_icon() self._native_icon_applied = True # Clear form setiap kali dialog ditampilkan self.clear_form() def clear_form(self): """Clear all input fields in the register form""" self.input_user.clear() self.input_pass.clear() self.input_confirm.clear() # Reset password visibility if self.password_visible: self.input_pass.setEchoMode(QLineEdit.Password) self.password_visible = False if self.confirm_visible: self.input_confirm.setEchoMode(QLineEdit.Password) self.confirm_visible = False self.btn_toggle_pass.setText('👁') self.btn_toggle_confirm.setText('👁') # Set focus to username field self.input_user.setFocus() def _apply_responsive_size(self, base_width, base_height): """Apply fixed size that adapts for smaller screens.""" screen = QApplication.primaryScreen() if not screen: self.setFixedSize(base_width, base_height) return available = screen.availableGeometry() width = min(base_width, max(540, int(available.width() * 0.92))) height = min(base_height, max(430, int(available.height() * 0.90))) self.setFixedSize(width, height) def _sync_confirm_row_width(self): """Keep confirm-password row width exactly aligned with username input.""" if hasattr(self, 'input_user') and hasattr(self, 'confirm_widget'): self.confirm_widget.setFixedWidth(self.input_user.width()) def resizeEvent(self, event): super().resizeEvent(event) self._sync_confirm_row_width() def toggle_password_visibility(self): """Toggle password visibility""" if self.password_visible: self.input_pass.setEchoMode(QLineEdit.Password) self.password_visible = False else: self.input_pass.setEchoMode(QLineEdit.Normal) self.password_visible = True def toggle_confirm_visibility(self): """Toggle confirm password visibility""" if self.confirm_visible: self.input_confirm.setEchoMode(QLineEdit.Password) self.confirm_visible = False else: self.input_confirm.setEchoMode(QLineEdit.Normal) self.confirm_visible = True #proses ambil data input def handle_register(self): username = self.input_user.text().strip() password = self.input_pass.text() confirm_password = self.input_confirm.text() # Validasi input if not username or not password or not confirm_password: CustomNotificationDialog.show_warning(self, 'Warning!', 'Semua field harus diisi!', 'OK', compact=True) return if len(username) < 3: CustomNotificationDialog.show_warning(self, 'Warning!', 'Username minimal 3 karakter!', 'OK', compact=True) return if len(password) < 6: CustomNotificationDialog.show_warning(self, 'Warning!', 'Password minimal 6 karakter!', 'OK', compact=True) return if password != confirm_password: CustomNotificationDialog.show_warning(self, 'Warning!', 'Password dan konfirmasi password tidak cocok!', 'OK', compact=True) return # Coba register try: register_admin(username, password) self.register_success = True CustomNotificationDialog.show_success(self, 'Registrasi Berhasil!', f'Akun {username} berhasil dibuat!\nSilakan login untuk melanjutkan.', 'OK', compact=True) self.accept() except Exception as e: error_msg = str(e) if 'duplicate' in error_msg.lower() or 'unique' in error_msg.lower(): CustomNotificationDialog.show_error(self, 'Error!', 'Username sudah digunakan!\nPilih username lain.', 'Coba Lagi', compact=True) else: CustomNotificationDialog.show_error(self, 'Error!', f'Gagal mendaftar:\n{error_msg}', 'Coba Lagi', compact=True) def back_to_login(self): """Tutup register dialog dan set flag untuk menampilkan login dialog""" self.should_show_login = True self.reject()