diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a47fb1d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +__pycache__ \ No newline at end of file diff --git a/UI/main.py b/UI/main.py index 39835e3..0a2a024 100644 --- a/UI/main.py +++ b/UI/main.py @@ -9,6 +9,28 @@ def __init__(self): super().__init__() self.setupUi(self) + # Connect buttons to functions + self.convert.clicked.connect(self.onConvertClicked) + self.copyButton.clicked.connect(self.onCopyClicked) + + def onConvertClicked(self): + # For now, just show a message - conversion logic will be added later + self.msg.setText("Conversion functionality will be implemented soon!") + + def onCopyClicked(self): + # Copy the content of the output text area to clipboard + clipboard = QApplication.clipboard() + clipboard.setText(self.harvardTextBox.toPlainText()) + + # Show a temporary message + original_msg = self.msg.text() + self.msg.setText("✓ Copied to clipboard!") + + # Reset message after 2 seconds + from PySide6.QtCore import QTimer + + QTimer.singleShot(2000, lambda: self.msg.setText(original_msg)) + if __name__ == "__main__": app = QApplication(sys.argv) diff --git a/UI/myui.py b/UI/myui.py index bc8f77c..015f306 100644 --- a/UI/myui.py +++ b/UI/myui.py @@ -8,6 +8,8 @@ ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ +import sys + from PySide6.QtCore import ( QCoreApplication, QDate, @@ -43,6 +45,7 @@ from PySide6.QtWidgets import ( QApplication, QGridLayout, + QHBoxLayout, QLabel, QMainWindow, QMenuBar, @@ -51,6 +54,7 @@ QSpacerItem, QStatusBar, QTextEdit, + QVBoxLayout, QWidget, ) @@ -59,84 +63,202 @@ class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName("MainWindow") - MainWindow.resize(800, 600) + MainWindow.resize(900, 600) + MainWindow.setMinimumSize(QSize(800, 500)) + + # Center the window on screen + screen = QApplication.primaryScreen() + screen_geometry = screen.geometry() + window_geometry = MainWindow.geometry() + MainWindow.move( + (screen_geometry.width() - window_geometry.width()) // 2, + (screen_geometry.height() - window_geometry.height()) // 2, + ) + self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") - self.gridLayoutWidget = QWidget(self.centralwidget) - self.gridLayoutWidget.setObjectName("gridLayoutWidget") - self.gridLayoutWidget.setGeometry(QRect(100, 40, 591, 481)) - self.gridLayout = QGridLayout(self.gridLayoutWidget) - self.gridLayout.setObjectName("gridLayout") - self.gridLayout.setContentsMargins(0, 0, 0, 0) - self.msg = QLabel(self.gridLayoutWidget) - self.msg.setObjectName("msg") - self.msg.setMinimumSize(QSize(0, 80)) - self.gridLayout.addWidget(self.msg, 3, 0, 1, 3) + # Main vertical layout + self.mainLayout = QVBoxLayout(self.centralwidget) + self.mainLayout.setObjectName("mainLayout") + self.mainLayout.setContentsMargins(20, 20, 20, 20) + self.mainLayout.setSpacing(15) - self.harvardTextBox = QTextEdit(self.gridLayoutWidget) - self.harvardTextBox.setObjectName("harvardTextBox") + # Horizontal layout for the two text areas + self.textAreasLayout = QHBoxLayout() + self.textAreasLayout.setObjectName("textAreasLayout") + self.textAreasLayout.setSpacing(15) + + # Left side: BibTeX input area with layout + self.inputGroup = QWidget() + self.inputGroup.setObjectName("inputGroup") + self.inputLayout = QVBoxLayout(self.inputGroup) + self.inputLayout.setObjectName("inputLayout") + self.inputLayout.setContentsMargins(0, 0, 0, 0) + self.inputLayout.setSpacing(5) - self.gridLayout.addWidget(self.harvardTextBox, 1, 2, 1, 1) + self.label_2 = QLabel(self.inputGroup) + self.label_2.setObjectName("label_2") + self.label_2.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.inputLayout.addWidget(self.label_2) - self.bibTexBox = QTextEdit(self.gridLayoutWidget) + self.bibTexBox = QTextEdit(self.inputGroup) self.bibTexBox.setObjectName("bibTexBox") + self.inputLayout.addWidget(self.bibTexBox) - self.gridLayout.addWidget(self.bibTexBox, 1, 0, 1, 1) + self.textAreasLayout.addWidget(self.inputGroup) - self.convert = QPushButton(self.gridLayoutWidget) - self.convert.setObjectName("convert") + # Right side: Harvard output area with layout and copy button + self.outputGroup = QWidget() + self.outputGroup.setObjectName("outputGroup") + self.outputLayout = QVBoxLayout(self.outputGroup) + self.outputLayout.setObjectName("outputLayout") + self.outputLayout.setContentsMargins(0, 0, 0, 0) + self.outputLayout.setSpacing(5) - self.gridLayout.addWidget(self.convert, 1, 1, 1, 1) + self.label_3 = QLabel(self.outputGroup) + self.label_3.setObjectName("label_3") + self.label_3.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.outputLayout.addWidget(self.label_3) - self.horizontalSpacer = QSpacerItem( - 40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum - ) + # Output text area with copy button container + self.outputTextContainer = QWidget() + self.outputTextContainer.setObjectName("outputTextContainer") + self.outputTextLayout = QVBoxLayout(self.outputTextContainer) + self.outputTextLayout.setObjectName("outputTextLayout") + self.outputTextLayout.setContentsMargins(0, 0, 0, 0) + self.outputTextLayout.setSpacing(5) + + self.harvardTextBox = QTextEdit(self.outputTextContainer) + self.harvardTextBox.setObjectName("harvardTextBox") + self.harvardTextBox.setReadOnly(True) # Make output read-only + self.outputTextLayout.addWidget(self.harvardTextBox) - self.gridLayout.addItem(self.horizontalSpacer, 2, 1, 1, 1) + # Copy button at bottom-right + self.copyButtonLayout = QHBoxLayout() + self.copyButtonLayout.setObjectName("copyButtonLayout") + self.copyButtonLayout.addStretch() # Push button to right - self.label_2 = QLabel(self.gridLayoutWidget) - self.label_2.setObjectName("label_2") - self.label_2.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.copyButton = QPushButton(self.outputTextContainer) + self.copyButton.setObjectName("copyButton") + self.copyButtonLayout.addWidget(self.copyButton) - self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1) + self.outputTextLayout.addLayout(self.copyButtonLayout) + self.outputLayout.addWidget(self.outputTextContainer) - self.label_3 = QLabel(self.gridLayoutWidget) - self.label_3.setObjectName("label_3") - self.label_3.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.textAreasLayout.addWidget(self.outputGroup) + self.mainLayout.addLayout(self.textAreasLayout) + + # Convert button centered at the bottom + self.buttonLayout = QHBoxLayout() + self.buttonLayout.setObjectName("buttonLayout") + self.buttonLayout.addStretch() - self.gridLayout.addWidget(self.label_3, 0, 2, 1, 1) + self.convert = QPushButton(self.centralwidget) + self.convert.setObjectName("convert") + self.buttonLayout.addWidget(self.convert) - self.label_4 = QLabel(self.gridLayoutWidget) - self.label_4.setObjectName("label_4") + self.buttonLayout.addStretch() + self.mainLayout.addLayout(self.buttonLayout) - self.gridLayout.addWidget(self.label_4, 2, 0, 1, 1) + # Message label + self.msg = QLabel(self.centralwidget) + self.msg.setObjectName("msg") + self.msg.setMinimumSize(QSize(0, 30)) + self.msg.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.mainLayout.addWidget(self.msg) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) self.menubar.setObjectName("menubar") - self.menubar.setGeometry(QRect(0, 0, 800, 22)) + self.menubar.setGeometry(QRect(0, 0, 900, 22)) MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) + # Apply UNSW branding colors + self.applyUNSWBranding(MainWindow) + self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) # setupUi + def applyUNSWBranding(self, MainWindow): + # UNSW official brand colors (updated) + unsw_yellow = QColor("#FFE600") # Primary: UNSW Yellow + unsw_charcoal = QColor("#231F20") # Secondary: Charcoal + unsw_light_grey = QColor("#F5F5F5") # Light background for read-only + + # Set window title bar color (Windows only) + try: + MainWindow.setStyleSheet( + f""" + QMainWindow {{ + background-color: #FFFFFF; + }} + QLabel {{ + font-weight: 500; + color: {unsw_charcoal.name()}; + }} + QPushButton {{ + background-color: {unsw_yellow.name()}; + color: {unsw_charcoal.name()}; + border: 2px solid {unsw_charcoal.name()}; + padding: 8px 24px; + font-weight: 600; + border-radius: 4px; + }} + QPushButton:hover {{ + background-color: {unsw_charcoal.name()}; + color: {unsw_yellow.name()}; + }} + QPushButton:pressed {{ + background-color: #{int(unsw_charcoal.rgb() & 0xFFFFFF) - 0x222222:06x}; + }} + QTextEdit {{ + border: 2px solid {unsw_charcoal.name()}; + border-radius: 4px; + padding: 8px; + font-family: 'Courier New', monospace; + font-size: 10pt; + }} + QTextEdit:focus {{ + border-color: {unsw_yellow.name()}; + outline: none; + }} + """ + ) + except (TypeError, ValueError, AttributeError) as e: + # Log style sheet errors but continue execution + print(f"Warning: Could not apply complete styling: {e}", file=sys.stderr) + + # Set placeholder text for input text area + self.bibTexBox.setPlaceholderText("Paste BibTeX Here") + + # Set read-only appearance for output text area + palette = self.harvardTextBox.palette() + palette.setColor(QPalette.ColorRole.Base, unsw_light_grey) + self.harvardTextBox.setPalette(palette) + def retranslateUi(self, MainWindow): MainWindow.setWindowTitle( - QCoreApplication.translate("MainWindow", "MainWindow", None) + QCoreApplication.translate( + "MainWindow", "UNSW Harvard Reference Generator", None + ) ) self.msg.setText("") self.convert.setText(QCoreApplication.translate("MainWindow", "Convert", None)) - self.label_2.setText(QCoreApplication.translate("MainWindow", "BibTeX", None)) + self.copyButton.setText(QCoreApplication.translate("MainWindow", "Copy", None)) + self.label_2.setText( + QCoreApplication.translate("MainWindow", "BibTeX Input", None) + ) self.label_3.setText( - QCoreApplication.translate("MainWindow", "Harvard(UNSW)", None) + QCoreApplication.translate( + "MainWindow", "Harvard Reference (UNSW Style)", None + ) ) - self.label_4.setText(QCoreApplication.translate("MainWindow", "Message:", None)) # retranslateUi diff --git a/USAGE.md b/USAGE.md new file mode 100644 index 0000000..e3353bd --- /dev/null +++ b/USAGE.md @@ -0,0 +1,81 @@ +# UNSW Harvard Reference Generator + +A desktop application built with PySide6 for converting BibTeX entries from Google Scholar to UNSW Harvard reference style. + +## Features + +- **Clean UI**: Modern interface following UNSW branding guidelines +- **BibTeX Input**: Paste BibTeX entries from Google Scholar +- **Harvard Output**: View formatted UNSW Harvard references +- **Copy Functionality**: Quick copy to clipboard +- **Responsive Design**: Centered window with minimum size constraints + +## Installation + +1. **Clone the repository**: + ```bash + git clone + cd UNSWHarvardReferenceFormatGeneration + ``` + +2. **Activate the virtual environment**: + ```bash + # Windows + .venv\Scripts\activate + + # macOS/Linux + source .venv/bin/activate + ``` + +3. **Install dependencies**: + ```bash + pip install -r UI/requirements.txt + ``` + +## Usage + +1. **Run the application**: + ```bash + # Windows + .venv\Scripts\python UI\main.py + + # macOS/Linux + .venv/bin/python UI/main.py + ``` + +2. **Paste BibTeX content** into the left text area + +3. **Click "Convert"** (conversion logic coming soon) + +4. **Copy the generated Harvard reference** using the Copy button + +## UI Layout + +- **Left Panel**: BibTeX input area with placeholder text +- **Right Panel**: Read-only Harvard reference output with Copy button +- **Bottom Center**: Prominent Convert button +- **Status Bar**: Feedback messages + +## Branding + +Uses official UNSW colors: +- Primary: UNSW Blue (#00338D) +- Secondary: UNSW Gold (#FFB81C) +- Light Blue: #E6EDF6 (for read-only areas) + +## Technical Stack + +- **Python 3.12+** +- **PySide6** - Qt UI framework +- **Qt Designer** - UI layout design + +## Development + +To modify the UI: +1. Edit `UI/main.ui` using Qt Designer +2. Regenerate Python code: `pyside6-uic UI/main.ui -o UI/myui.py` +3. Update functionality in `UI/main.py` + +## License + +MIT \ No newline at end of file