Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Movie Search
#3
A PyQt6 version. (Still needs tweaks)

from PyQt6.QtWidgets import(QApplication, QMainWindow, QWidget,QGridLayout,
                            QComboBox, QLineEdit, QPushButton,QListWidget,
                            QScrollArea, QLabel, QHBoxLayout, QFrame)
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QPixmap, QImage, QIcon
from PyQt6 import sip
from imdb import Cinemagoer
import requests
import sys


class Data:
    def __init__(self):
        self.action = Cinemagoer()

    def search_person(self, name):
        return self.action.search_person(name.strip())
     
    def get_person(self, id):
        return self.action.get_person(id)
     
    def search_movie(self, name):
        return self.action.search_movie(name)
     
    def get_movie(self, movieid):
        return self.action.get_movie(movieid)


class Window(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Get screen size and set minimum size
        app = QApplication.instance()
        screen = app.primaryScreen()
        screensize = screen.geometry()
        width = screensize.width()
        height = screensize.height()
        self.setMinimumSize(width//2, height//2+20)

        # Set taskbar icon
        img_url = 'https://my-python.org/images/python-forum/on.png'
        image = QImage()
        image.loadFromData(requests.get(img_url).content)
        self.setWindowIcon(QIcon(QPixmap(image)))

        # Setup the main container
        container = QGridLayout()
        widget = QWidget()
        widget.setLayout(container)
        self.setCentralWidget(widget)
        self.show()        

        # Create the header
        header = QLabel('Movie Finder')
        header.setAlignment(Qt.AlignmentFlag.AlignCenter)
        header.setStyleSheet('''font-size: 40px; font-weight: bold; color:white;
                             background-color: #333333; padding: 10 0 10px 0;''')
        
        # Add to main container
        container.addWidget(header, 0,0,1,5,Qt.AlignmentFlag.AlignTop)
        container.setRowStretch(0,0)

        # Set a common style for field headers
        common = 'font-weight: bold; padding:0 16px 0 16px;'

        # Set header label
        label = QLabel('Search By:')
        label.setStyleSheet(common)
        container.addWidget(label, 1,0,1,1,Qt.AlignmentFlag.AlignTop)

        # Create combobox
        self.forwhat = QComboBox()
        self.forwhat.addItems(['Person', 'Movie'])
        container.addWidget(self.forwhat, 1,1,1,1,Qt.AlignmentFlag.AlignTop)

        # Create header label
        label = QLabel('Search For:')
        label.setStyleSheet(common)
        container.addWidget(label, 1,2,1,1,Qt.AlignmentFlag.AlignTop)

        # Create enty field
        self.term = QLineEdit()
        self.term.setPlaceholderText('Search for a person\'s name')
        container.addWidget(self.term, 1,3,1,1,Qt.AlignmentFlag.AlignTop)

        # Create button
        self.button = QPushButton('Search')
        self.button.setCursor(Qt.CursorShape(13))
        container.addWidget(self.button, 1,4,1,1,Qt.AlignmentFlag.AlignTop)
        container.setRowStretch(1, 0)

        # Create hbox container
        hbox = QHBoxLayout()
        container.addLayout(hbox, 2, 0, 1,5, Qt.AlignmentFlag.AlignTop)
        
        # Create listbox to hold list of movies
        self.listbox = QListWidget()
        self.listbox.setSpacing(5)
        hbox.addWidget(self.listbox)

        # Create a frame spacer, Data will be added to a grid in the controller class
        self.frame = QFrame()
        self.frame.setFrameStyle(6)
        self.frame.setStyleSheet('background-color: white;')
        self.scrollbar = QScrollArea(widget)
        self.scrollbar.setWidget(self.frame)
        self.scrollbar.setWidgetResizable(True)
        hbox.addWidget(self.scrollbar)
        hbox.setStretch(0,1)
        hbox.setStretch(1,1)

        # Create a footer
        label = QLabel('my-python.org')
        label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        label.setStyleSheet('''font-size: 14; background-color: #333333; 
                            color: #ffffff; padding: 8px; font-style: italic;''')
        container.addWidget(label, 3,0,1,5, Qt.AlignmentFlag.AlignTop)
        

class Controller:
    def __init__(self, data, window):
        self.data = data
        self.window = window

        # Button commands
        self.window.button.clicked.connect(self.search)
 
        # Place holder text
        self.window.forwhat.currentTextChanged.connect(self.whatchange)
 
        # Detect if the return key was pressed
        self.window.term.returnPressed.connect(self.search)
 
        # List item was clicked
        self.window.listbox.itemClicked.connect(self.getmovie)

    def search(self):
        ''' Method for doing searches - Search depends on forwhat dropdown value'''
        # Get search term
        term = self.window.term.text().strip()
        reset_slider = self.window.listbox.verticalScrollBar()
        reset_slider.setValue(0)


        # Create empty list to hold movie titles
        titles = []

        # Check if the search field is empty. If not do search
        if term:
            # Clear all fields
            self.clear(self.window.frame.layout())

            # Setup a layout to hold the data
            self.layout = QGridLayout()
            self.window.frame.setLayout(self.layout)

            # Are we searching for a person or movie
            forwhat = self.window.forwhat.currentText()

            ''' We are searching for a person. Get the persons id, then get person data. '''
            if forwhat == 'Person':
                personid = self.data.search_person(term)[0].personID
                person = self.data.get_person(personid)
 
                # Get the jobs the person has worked on from filmography
                jobs = [job for job in person.get('filmography')]

                # We want movies the person acted in 
                movies = [movie for movie in person['filmography'][jobs[0]]]

            # A movie title was entered for the forwhat variable
            elif forwhat == 'Movie':
                movies = self.data.search_movie(term)

            # Get all the movies from the search and append to the empty list.
            # Also getting the movie id to later use for getting the movie details.
            # Right now just using movie title to search and get id to get details.
            for movie in movies:
                    titles.append((movie.get('title'), movie.movieID))

            # Add movies to the listbox for display
            for title in titles:
                self.window.listbox.addItem(title[0])
                
        else:
            return False

    def display(self, movie):
        ''' The display method take the data passed and breaks it down into parts we want.
            Currently, all we want is title, year, cover image, rating, plot, and cast.
        '''
        title = movie.get('title')
        year = movie.get('production status') if 'production status' in movie.keys() else movie.get('year')
        cover = movie.get('full-size cover url')
        rating = movie.get('rating')
        plot = movie.get('plot outline')
        cast = [name.get('name') for name in movie.get('cast')]

        # Reset slider position to 0
        reset_slider = self.window.scrollbar.verticalScrollBar()
        reset_slider.setValue(0)

        # Start adding data to our layout for display
        header = QLabel(title)
        header.setAlignment(Qt.AlignmentFlag.AlignCenter)
        header.setStyleSheet('''background-color: #555555; color: #ffffff;
                             font-size: 20px; font-weight: bold; padding: 8px 0 8px 0;''')
        self.layout.addWidget(header, 0, 0,1,4, Qt.AlignmentFlag.AlignTop)
        self.layout.setRowStretch(0, 0)

        # Check if there is a cover photo. If there is retrieve and resize
        # and attach toa label for display
        if cover is not None:
            image = QImage()
            image.loadFromData(requests.get(cover).content)
            label = QLabel()
            label.setFixedSize(300,300)
            pixmap = QPixmap(image)
            label.setPixmap(pixmap.scaled(300,300))

        # Else there was not a cover image. Create a label to show instead
        else:
            label = QLabel('No image available')
            label.setFrameStyle(6)
            label.setFixedSize(300,300)
            label.setAlignment(Qt.AlignmentFlag.AlignCenter)
            label.setStyleSheet('background-color: #F2F3F5;')

        # Add the label to our layout
        self.layout.addWidget(label, 1,0,3,1, Qt.AlignmentFlag.AlignTop)
        self.layout.setRowStretch(1, 0)

        # The spacer is used to keep everything pushed up
        # using rowstretch
        spacer = QFrame()
        self.layout.addWidget(spacer, 5,0,1,1)
        self.layout.setRowStretch(5, 1)

        # Put other stats to the right of the image
        label = QLabel('Released:')
        label.setStyleSheet('font-weight: bold;')
        self.layout.addWidget(label, 1,1,1,1, Qt.AlignmentFlag.AlignTop)
        self.layout.addWidget(QLabel(str(year)), 1,2,1,1, Qt.AlignmentFlag.AlignTop)
        self.layout.addWidget(spacer, 1,3,2,1)
        self.layout.setColumnStretch(0,0)
        self.layout.setColumnStretch(1,0)
        self.layout.setColumnStretch(2,0)
        self.layout.setColumnStretch(3,1)

        label = QLabel('Rating:')
        label.setStyleSheet('font-weight: bold;')
        self.layout.addWidget(label, 2,1,1,1, Qt.AlignmentFlag.AlignTop)
        self.layout.addWidget(QLabel(str(rating)), 2,2,1,1, Qt.AlignmentFlag.AlignTop)
        self.layout.addWidget(spacer, 3,1,1,1)
        self.layout.setRowStretch(0,0)
        self.layout.setRowStretch(1,0)
        self.layout.setRowStretch(3,1)

        label = QLabel('Plot Outline:')
        label.setStyleSheet('font-weight: bold;')
        self.layout.addWidget(label, 4,0,1,4, Qt.AlignmentFlag.AlignTop)
        plot_label = QLabel(plot)
        plot_label.setWordWrap(True)
        self.layout.addWidget(plot_label, 5,0,1,4, Qt.AlignmentFlag.AlignTop)

        self.layout.setRowStretch(4, 0)
        self.layout.setRowStretch(5, 0)

        label = QLabel('Cast:')
        label.setStyleSheet('font-weight: bold;')
        self.layout.addWidget(label, 6,0,1,4, Qt.AlignmentFlag.AlignTop)
        cast_label = QLabel(', '.join(cast))
        cast_label.setWordWrap(True)
        self.layout.addWidget(cast_label, 7,0,1,4, Qt.AlignmentFlag.AlignTop)

        self.layout.addWidget(spacer, 8,0,1,1)
        self.layout.setRowStretch(6, 0)
        self.layout.setRowStretch(7, 0)
        self.layout.setRowStretch(8, 2)      

    def getmovie(self, movie):
        ''' Method for getting movie data. '''
        movieid = self.data.search_movie(movie.text())[0].movieID
        title = self.data.get_movie(movieid)
        self.display(title)

    def clear(self, layout=None):
        ''' method for clearing fields, list and frames '''
        self.window.term.clear()
        self.window.listbox.clear()
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.deleteLater()
                else:
                    self.deleteLayout(item.layout())
            sip.delete(layout)
        
    def whatchange(self):
        ''' Method changes the placeholder in the entry field '''
        self.clear(self.window.frame.layout())
        if self.window.forwhat.currentText() == 'Person':
            self.window.term.setPlaceholderText('Search for a person\'s name')
        elif self.window.forwhat.currentText() == 'Movie':
            self.window.term.setPlaceholderText('Search for a movie title')


if __name__ == '__main__':
    app = QApplication([])
    controller = Controller(Data(), Window())
    sys.exit(app.exec())
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply


Messages In This Thread
Movie Search - by menator01 - Sep-07-2023, 04:36 AM
RE: Movie Search - by menator01 - Sep-10-2023, 09:59 PM
RE: Movie Search - by menator01 - Sep-15-2023, 01:30 AM
RE: Movie Search - by gluke15 - Oct-30-2023, 03:13 PM
RE: Movie Search - by EdwardMatthew - Jan-24-2024, 12:29 PM

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020