diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..550d67d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +src/__pycache__ diff --git a/README.md b/README.md index bbbd155..b5001e4 100644 --- a/README.md +++ b/README.md @@ -9,5 +9,5 @@ pip install -r requirements.txt Run with: ``` -python app.py +python src/app.py ``` diff --git a/app.py b/app.py deleted file mode 100644 index 37dc584..0000000 --- a/app.py +++ /dev/null @@ -1,93 +0,0 @@ -from PySide6.QtCore import QSize -from PySide6.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QWidget, QBoxLayout -from PySide6.QtGui import QPixmap - -from typing import final - -import sys - -app = QApplication(sys.argv) - -@final -class Movie: - def __init__(self, name: str, price: float, image: QWidget): - self.name = name - self.price = price - self.image = image - -def createImage(filename: str) -> QWidget: - label = QLabel() - pixmap = QPixmap(filename) - label.setPixmap(pixmap.scaled(300, 300)) - return label - -movies = { - "spiderman": Movie("Spider-Man: Very far from home", 39.95, createImage("resources/spiderman.png")), - "cars2": Movie("Cars 2", 79.95, createImage("resources/cars2.png")), - "leo": Movie("The Nerd Movie", -189.95, createImage("resources/leo.png")) -} - -class MovieView(QWidget): - def __init__(self, movie: Movie): - super().__init__() - - layout = QBoxLayout(QBoxLayout.Direction.TopToBottom) - - self.setWindowTitle("Movie viewer") - label1 = QLabel(f"Buying a ticket for {movie.name}") - label2 = QLabel(f"For cost ${movie.price}") - label3 = movie.image - - layout.addWidget(label1) - layout.addWidget(label2) - layout.addWidget(label3) - - self.setLayout(layout) - -# Main Window -class MainWindow(QMainWindow): - def __init__(self): - super().__init__() - - self.takers: list[MovieView] = [] - - self.setWindowTitle("Cinema Tickets"); - - layout = QBoxLayout(QBoxLayout.Direction.LeftToRight) - - self.spiderman: QPushButton = QPushButton("Buy tickets for spider man"); - self.spiderman.setCheckable(True) - _ = self.spiderman.clicked.connect(self.buySpiderman) - - layout.addWidget(self.spiderman) - - self.cars: QPushButton = QPushButton("Buy tickets for cars 2"); - self.cars.setCheckable(True) - _ = self.cars.clicked.connect(self.buyCars) - - layout.addWidget(self.cars) - - self.leo: QPushButton = QPushButton("Buy tickets for the nerd movie"); - self.leo.setCheckable(True) - _ = self.leo.clicked.connect(self.buyLeo) - - layout.addWidget(self.leo) - - centralWidget = QWidget() - centralWidget.setLayout(layout) - self.setCentralWidget(centralWidget) - - def buySpiderman(self): - self.setCentralWidget(MovieView(movies["spiderman"])) - - def buyLeo(self): - self.setCentralWidget(MovieView(movies["leo"])) - - def buyCars(self): - self.setCentralWidget(MovieView(movies["cars2"])) - - -window = MainWindow() -window.show() - -exit(app.exec()) diff --git a/resources/hairypotty.png b/resources/hairypotty.png new file mode 100644 index 0000000..3b3fac7 Binary files /dev/null and b/resources/hairypotty.png differ diff --git a/src/Movie.py b/src/Movie.py new file mode 100644 index 0000000..4409574 --- /dev/null +++ b/src/Movie.py @@ -0,0 +1,37 @@ +from PySide6.QtWidgets import QWidget, QLabel +from PySide6.QtGui import QPixmap +from typing import final + +@final +class Movie: + """ + Describes a movie which will be displayed in the GUI. + Usage: + Movie("Movie name", , "Path to movie cover image") + """ + def __init__(self, name: str, price: float, image_path: str, description: str): + self.name = name + self.price = price + self.image_path = image_path + self.description = description + +def createImage(filename: str) -> QLabel: + """ + Creates an image (in form of a QLabel) from a provided filename. + The filename must be a path to the image file. + It does not have to be an absolute path. + """ + label = QLabel() + pixmap = QPixmap(filename) + label.setPixmap(pixmap.scaled(300, 450)) + return label + +""" +Dictionary mapping strings (movie ID's) to Movie() objects. +""" +movies = { + "spiderman": Movie("Spider-Man: Very far from home", 39.95, "resources/spiderman.png", "spiderman, spiderman, he's a spider, and he's a man"), + "cars2": Movie("Cars 2", 79.95, "resources/cars2.png", "I am speed"), + "leo": Movie("The Nerd Movie", -189.95, "resources/leo.png", "Did you know that the quadratic formula is negative b plus or minus square root of b squared minus 4 a c all divided by 2 a"), + "hairypotty": Movie("Harry Potter and the Deathly Weapons", 447.95, "resources/hairypotty.png", "Dobby's got a glock") +} diff --git a/src/MovieButton.py b/src/MovieButton.py new file mode 100644 index 0000000..b97fd95 --- /dev/null +++ b/src/MovieButton.py @@ -0,0 +1,30 @@ +from typing import Callable +from PySide6.QtGui import QMouseEvent +from PySide6.QtWidgets import QVBoxLayout, QWidget, QLabel +from PySide6.QtCore import QTimer +from Movie import Movie, createImage + +class MovieButton(QWidget): + """ + Buttons for selecting the movie on the main screen. + Usage: + MovieButton(Movie(...), self.show) + """ + + def __init__(self, movie: Movie, callback: Callable[[], None]): + super().__init__() + + layout = QVBoxLayout() + + self.movie: Movie = movie + + layout.addWidget(createImage(movie.image_path)) + layout.addWidget(QLabel(movie.name)) + + self.setLayout(layout) + self.callback: Callable[[], None] = callback + + + def mousePressEvent(self, event: QMouseEvent): + QTimer.singleShot(0, self.callback) + diff --git a/src/MovieView.py b/src/MovieView.py new file mode 100644 index 0000000..f4a69d5 --- /dev/null +++ b/src/MovieView.py @@ -0,0 +1,40 @@ +from PySide6.QtGui import Qt +from Movie import Movie, createImage +from PySide6.QtWidgets import QHBoxLayout, QPushButton, QWidget, QGridLayout, QLabel + +class MovieView(QWidget): + """ + A QWidget which shows details about a given movie. + Shows cover image, title, price, description. + Also provided a button for buying tickets to the movie. + """ + def __init__(self, movie: Movie): + super().__init__() + + self.setMaximumWidth(800) + self.setMaximumHeight(600) + + # Create layouts + bodylayout = QHBoxLayout() + contentlayout = QGridLayout() + + # Create labels and buttons + label1 = QLabel(f"Buying a ticket for {movie.name}\nFor cost ${movie.price}") + label1.setWordWrap(True) + label2 = QLabel(movie.description) + label2.setWordWrap(True) + label3 = createImage(movie.image_path) + + button1 = QPushButton("Buy") + button1.setMaximumWidth(100) + + contentlayout.addWidget(label1, 0, 0, alignment=Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft) + contentlayout.addWidget(label2, 1, 0, alignment=Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft) + contentlayout.addWidget(button1, 1, 0, alignment=Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignLeft) + + bodylayout.addWidget(label3) + bodylayout.addLayout(contentlayout) + + self.setLayout(bodylayout) + + diff --git a/src/app.py b/src/app.py new file mode 100644 index 0000000..3ba2aec --- /dev/null +++ b/src/app.py @@ -0,0 +1,64 @@ +from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout +from typing import final +import sys + +from Movie import movies +from MovieView import MovieView +from MovieButton import MovieButton + +# Main Window +@final +class MainWindow(QMainWindow): + """ + The main window for Max's movie tickets application. + Usage: + window = MainWindow() + window.show() + """ + + currentMovie: MovieView | None = None + + def __init__(self): + super().__init__() + + self.setWindowTitle("Cinema Tickets") + + # Create the layout for all the movies + layout = QHBoxLayout() + + # Create the buttons for each movie + self.spiderman = MovieButton(movies["spiderman"], self.buySpiderman) + layout.addWidget(self.spiderman) + self.cars = MovieButton(movies["cars2"], self.buyCars) + layout.addWidget(self.cars) + self.leo = MovieButton(movies["leo"], self.buyLeo) + layout.addWidget(self.leo) + self.hairypotty = MovieButton(movies["hairypotty"], self.buyHairyPotty) + layout.addWidget(self.hairypotty) + + centralWidget = QWidget() + centralWidget.setLayout(layout) + self.setCentralWidget(centralWidget) + + # Callback functions to set the movie + def buySpiderman(self): + self.currentMovie = MovieView(movies["spiderman"]) + self.currentMovie.show() + + def buyLeo(self): + self.currentMovie = MovieView(movies["leo"]) + self.currentMovie.show() + + def buyCars(self): + self.currentMovie = MovieView(movies["cars2"]) + self.currentMovie.show() + + def buyHairyPotty(self): + self.currentMovie = MovieView(movies["hairypotty"]) + self.currentMovie.show() + + +app = QApplication(sys.argv) +window = MainWindow() +window.show() +sys.exit(app.exec())