Movie Search - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: General (https://python-forum.io/forum-1.html) +--- Forum: Code sharing (https://python-forum.io/forum-5.html) +--- Thread: Movie Search (/thread-40687.html) |
Movie Search - menator01 - Sep-07-2023 I've finished the movie search script. Still a little ruff around the edges but, works. I had trouble placing text in the textbox so I went with using a frame in the textbox. That way I could kinda order the layout a little. I welcome any input. Remember it will take a few seconds to get the results as it does a few queries. My understanding of the imdb database may search through several pages to get the information. # Do the imports from imdb import Cinemagoer import tkinter as tk from tkinter import ttk from urllib.request import urlopen from PIL import ImageTk, Image import io class Data: ''' The Data class retrieves all information from user input Searches person and movies returns all relevant information ''' def __init__(self): self.action = Cinemagoer() def search_person(self, name): person = self.action.search_person(name.strip())[0] return person.get('name'), person.personID def get_person(self, id): person = self.action.get_person(id) jobs = [job for job in person.get('filmography').keys()] movies = [movie for movie in person['filmography'][jobs[0]]] return person.get('name'), movies def search_movies(self, title): return self.action.search_movie(title) def get_movie(self, movie_id): if movie_id: movie = self.action.get_movie(movie_id) return movie class Window: ''' Window class is for visual and has fields and buttons for the Controller class to use ''' def __init__(self, parent): parent.columnconfigure(0, weight=1) parent.rowconfigure(0, weight=1) parent.minsize(800,600) parent['padx'] = 5 parent['pady'] = 3 parent['bg'] = '#c0c0c0' parent.title('Movie Search') container = tk.Frame(parent, bg='#333333') container.grid(column=0, row=0, sticky='news') container.grid_columnconfigure(0, weight=3) container.grid_rowconfigure(3, weight=3) header = tk.Label(container, text='Movie Search', fg='#ffffff', bg='#333333') header['font'] = 'tk.HEADER 28 bold' header.grid(column=0, row=0, sticky='new', padx=2, pady=2) self.msg = tk.Label(container, text='Messages: ', bg='#555555', fg='#FFFFFF', anchor='w', padx=10) self.msg['font'] = 'tk.MENU 13 normal' self.msg.grid(column=0, row=1, sticky='new', padx=2, pady=2) row1 = tk.Frame(container, bg='#555555') row1.grid(column=0, row=2, sticky='new', padx=2, pady=2) for i in range(5): weight = 4 if i == 3 else 3 row1.grid_columnconfigure(i, weight=weight, uniform='cols') row2 = tk.Frame(container, bg='#555555') row2.grid(column=0, row=3, sticky='news', padx=2, pady=2) row2.grid_columnconfigure(0, weight=3, uniform='tree') row2.grid_columnconfigure(2, weight=3, uniform='tree') row2.grid_rowconfigure(0, weight=3) row3 = tk.Frame(container, bg='#555555') row3.grid(column=0, row=4, sticky='new', padx=2, pady=2) row3.grid_columnconfigure(0, weight=3) label = tk.Label(row1, text='Search by:', bg='#555555', fg='#ffffff') label['font'] = 'None 12 normal' label.grid(column=0, row=0, sticky='new', padx=2, pady=4) self.options = ['Actors/Actresses', 'Movie Title'] self.picked = tk.StringVar() self.picked.set(self.options[0]) self.searchby = tk.OptionMenu(row1, self.picked, *self.options) self.searchby['font'] = 'None 10 normal' self.searchby.grid(column=1, row=0, sticky='new', padx=2, pady=4) self.searchby.config(border=0) label = tk.Label(row1, text='Search For:', bg='#555555', fg='#ffffff') label['font'] = 'None 12 normal' label.grid(column=2, row=0, sticky='new', padx=2, pady=4) self.entry = tk.Entry(row1) self.entry['font'] = 'None 12 normal' self.entry.grid(column=3, row=0, sticky='new', padx=2, pady=4) self.button = tk.Button(row1, text='Search') self.button.grid(column=4, row=0, sticky='new', padx=2) columns = ('Title', 'Released', 'Movie ID') self.left_tree = ttk.Treeview(row2, columns=columns, show='headings', selectmode='browse') for column in columns: if column == columns[0]: self.left_tree.column(column, minwidth=0, width=300, stretch='yes') else: self.left_tree.column(column, minwidth=0, width=100) self.left_tree.heading(column, text=column.title()) self.left_tree.grid(column=0, row=0, sticky='news', padx=2) left_scroll = tk.Scrollbar(row2, orient='vertical', command=self.left_tree.yview) self.left_tree.config(yscrollcommand=left_scroll.set) left_scroll.grid(column=1, row=0, sticky='ns', padx=2) self.textbox = tk.Text(row2) self.textbox.grid(column=2, row=0, sticky='news', padx=2) self.textbox.grid_columnconfigure(0, weight=3) textbox_scroll = tk.Scrollbar(row2, orient='vertical', command=self.textbox.yview) self.textbox.config(yscrollcommand=textbox_scroll.set) textbox_scroll.grid(column=3, row=0, sticky='ns', padx=2) sig = tk.Label(row3, text='my-python.org', bg='#333333', fg='#ffffff') sig['font'] = 'None 10 normal' sig.grid(column=0, row=0, sticky='new') class Controller: ''' Controller class handles all communications between the Data and Window class ''' def __init__(self, data, window): self.data = data self.window = window self.images = [] # Button Commands self.window.button['command'] = self.search #Dropdown command self.window.picked.trace('w', self.clear) # Bind treeview self.window.left_tree.bind('<<TreeviewSelect>>', self.details) def search(self): ''' Search method will lookup either actor or movie depending on the selection in the Window class. At the momment the search only works for finding actors and actresses ''' # Clear the views self.window.left_tree.delete(*self.window.left_tree.get_children()) self.window.textbox.delete('1.0', 'end') try: self.frame.destroy() except AttributeError: pass # Get the param for either person search or movie search picked = self.window.picked.get() # Get the name of the search. person or movie name = self.window.entry.get().strip() # Set alternation colors for the treeview self.window.left_tree.tag_configure('oddrow', background='#ccceee') self.window.left_tree.tag_configure('evenrow', background='white') # Clear the entry field self.window.entry.delete(0, 'end') # # Person was selected for search if picked == 'Actors/Actresses': self.window.msg['text'] = f'Messages: Search results for {name.title()}' # Call the Data class search_person method person = self.data.search_person(name.strip()) # Get relevant data using the person[1] which is set to the person id data = self.data.get_person(person[1]) # Create empty list to hold the data wanted movie_list = [] # Loop through the data getting relevant information # Also checking that there is a year for the movie release # This helps in not getting any movies not yet released for movie in data[1]: if movie.get('year'): movie_list.append((movie.get('title'), movie.get('year'), movie.movieID)) elif movie.get('year') == None: year = self.data.get_movie(movie.movieID).get('year') if year: movie_list.append((movie.get('title'), year, movie.movieID)) else: pass else: movies = self.data.search_movies(name.strip()) movie_list = [] for movie in movies: if movie.get('year'): movie_list.append((movie.get('title'), movie.get('year'), movie.movieID)) elif movie.get('year') == None: year = self.data.get_movie(movie.movieID).get('year') if year: movie_list.append((movie.get('title'), year, movie.movieID)) else: pass movie_list.sort(key=lambda year: year[1]) # Loop through the movie_list and insert into the treeview with alternating colors for index, movie in enumerate(movie_list): if index % 2 == 0: self.window.left_tree.insert('', index, values=(movie[0], movie[1], movie[2]), tags=('oddrow',)) else: self.window.left_tree.insert('', index, values=(movie[0], movie[1], movie[2]), tags=('evenrow',)) def details(self, id): item = self.window.left_tree.focus() try: id = self.window.left_tree.item(item)['values'][2] except IndexError: pass try: self.frame.destroy() except AttributeError: pass try: details = self.data.get_movie(id) title = details.get('title') cast = details.get('cast') year = details.get('year') plot = details.get('plot outline') cover = details.get('cover') rating = details.get('rating') air_date = details.get('original air date') cast_list = [c.get('name') for c in cast] cast = ', '.join(cast_list) img_url = urlopen(cover).read() img = Image.open(io.BytesIO(img_url)) image = ImageTk.PhotoImage(img) self.frame = tk.Frame(self.window.textbox,bg='white') self.frame.grid(column=0, row=0, sticky='news') self.frame.grid_columnconfigure(0, weight=3) label = tk.Label(self.frame, text=f'Title', anchor='w',bg='white') label['font'] = 'tk.HEADER 10 bold' label.grid(column=0,row=0,sticky='new',pady=8) label = tk.Label(self.frame, text=f'{title}', anchor='w',bg='white') label.grid(column=1,row=0,sticky='new',pady=8) label = tk.Label(self.frame, text=f'Year:', anchor='w',bg='white') label['font'] = 'tk.HEADER 10 bold' label.grid(column=0, row=1, sticky='new',pady=8) label = tk.Label(self.frame, text=f'{year}', anchor='w',bg='white') label.grid(column=1, row=1, sticky='new',pady=8) label = tk.Label(self.frame, text=f'Air Date:', anchor='w',bg='white') label['font'] = 'tk.HEADER 10 bold' label.grid(column=0, row=2, sticky='new',pady=8) label = tk.Label(self.frame, text=f'{air_date}', anchor='w',bg='white') label.grid(column=1, row=2, sticky='new',pady=8) label = tk.Label(self.frame, text=f'Cover Image:', image=image, compound='bottom',anchor='w',bg='white') label['font'] = 'tk.HEADER 10 bold' label.grid(column=0, row=3, columnspan=2, sticky='new',pady=8) label = tk.Label(self.frame, text=f'Rating:', anchor='w',bg='white') label['font'] = 'tk.HEADER 10 bold' label.grid(column=0, row=4, sticky='new',pady=8) label = tk.Label(self.frame, text=f'{rating}', anchor='w',bg='white') label.grid(column=1, row=4, sticky='new',pady=8) label = tk.Label(self.frame, text=f'Plot:', anchor='w', wraplength=800, justify='left',bg='white') label['font'] = 'tk.HEADER 10 bold' label.grid(column=0, row=5, sticky='new',pady=8) label = tk.Label(self.frame, text=f'{plot}', anchor='w', wraplength=800, justify='left',bg='white') label.grid(column=1, row=5, sticky='new',pady=8) label = tk.Label(self.frame, text=f'Cast:', anchor='w', wraplength=800, justify='left',bg='white') label['font'] = 'tk.HEADER 10 bold' label.grid(column=0, row=6, sticky='new',pady=8) label = tk.Label(self.frame, text=f'{cast}', anchor='w', wraplength=800, justify='left',bg='white') label.grid(column=1, row=6, sticky='new',pady=8) self.window.textbox.delete('1.0', tk.END) self.window.textbox.insert('end', self.frame) self.images.append(image) except TypeError: pass def clear(self, write, index, mode): # Clear the treevies self.window.left_tree.delete(*self.window.left_tree.get_children()) self.window.textbox.delete('1.0', 'end') self.window.msg['text'] = 'Messages: ' try: self.frame.destroy() except AttributeError: pass if __name__ == '__main__': root = tk.Tk() img = urlopen('https://my-python.org/images/code-forum/light/light_on.png') data = img.read() image = tk.PhotoImage(data=data) root.wm_iconphoto(True, image) controller = Controller(Data(), Window(root)) root.mainloop() RE: Movie Search - menator01 - Sep-10-2023 Updated version. Still haven't worked on the messages box part. May remove. Not sure yet. # Do the imports from imdb import Cinemagoer import tkinter as tk from tkinter import ttk from urllib.request import urlopen from PIL import ImageTk, Image import io class Database: def __init__(self): self.query = Cinemagoer() def search_person(self, name): return self.query.search_person(name.strip())[0] def get_person(self, id): return self.query.get_person(id.strip()) def search_movie(self, name): return self.query.search_movie(name.strip()) def get_movie(self, id): return self.query.get_movie(id.strip()) class Window: def __init__(self, parent): parent.columnconfigure(0, weight=1) parent.rowconfigure(0, weight=1) parent.minsize(1204, 768) parent.title('Movie Search') # Containers container = tk.Frame(parent, bg='#cecece') container.grid(column=0, row=0, sticky='news', padx=5, pady=5) container.grid_columnconfigure(0, weight=3) container.grid_rowconfigure(3, weight=3) # Header headerframe = tk.Frame(container, bg='#333333') headerframe['highlightbackground'] = '#000000' headerframe['highlightcolor'] = '#000000' headerframe['highlightthickness'] = 1 headerframe.grid(column=0, row=0, sticky='new', pady=1) headerframe.grid_columnconfigure(0, weight=3) # Messages msgframe = tk.Frame(container, bg='#333333') msgframe['highlightbackground'] = '#000000' msgframe['highlightcolor'] = '#000000' msgframe['highlightthickness'] = 1 msgframe.grid(column=0, row=1, sticky='new', pady=1) msgframe.grid_columnconfigure(1, weight=3) # Search Fields searchframe = tk.Frame(container, bg='#555555') searchframe.grid(column=0, row=2, sticky='new') for i in range(5): weight = 4 if i == 3 else 1 searchframe.columnconfigure(i, weight=weight, uniform='cols') dataframe = tk.Frame(container,bg='#555555') dataframe.grid(column=0, row=3, sticky='news') dataframe.columnconfigure(0, weight=3, uniform='data') dataframe.columnconfigure(1, weight=3, uniform='data') dataframe.rowconfigure(0, weight=3) leftframe = tk.Frame(dataframe, bg='#555555') leftframe.grid(column=0, row=0, sticky='news', padx=2) leftframe.grid_columnconfigure(0, weight=3) leftframe.grid_rowconfigure(0, weight=3) rightframe = tk.Frame(dataframe, bg='white', padx=10, pady=10) rightframe.grid(column=1, row=0, sticky='news') rightframe.grid_columnconfigure(0, weight=3) rightframe.grid_rowconfigure(0, weight=3) footerframe = tk.Frame(container) footerframe.grid(column=0, row=4, sticky='new') # Label and field widgets label = tk.Label(headerframe, text='Movie Search') label['bg'] = '#555555' label['fg'] = '#ffffff' label['font'] = (None, 28, 'bold') label.grid(column=0, row=0, sticky='new', ipadx=10, ipady=5) label = tk.Label(msgframe, text='MSG: ', bg='#555555', fg='#ffffff') label['font'] = (None, 12, 'bold') label.grid(column=0, row=0, padx=2, pady=3, ipadx=3, ipady=3) self.msg = tk.Label(msgframe, anchor='w', bg='#555555', fg='cyan') self.msg['font'] = (None, 12, 'normal') self.msg.grid(column=1, row=0, sticky='new', padx=2, pady=3, ipadx=3, ipady=3) label = tk.Label(searchframe, text='Searchby:', bg='#555555', fg='#ffffff') label['font'] = (None, 12, 'bold') label.grid(column=0, row=0, padx=2, pady=4, sticky='new') options = ['Person', 'Movie'] self.term = tk.StringVar() self.term.set(options[0]) option = tk.OptionMenu(searchframe, self.term, *options) option['font'] = (None, 10, 'normal') option.grid(column=1, row=0, padx=2, sticky='new') label = tk.Label(searchframe, text='Search for:', bg='#555555', fg='#ffffff') label['font'] = (None, 12, 'bold') label.grid(column=2, row=0, padx=4, pady=4, sticky='new') self.entry = tk.Entry(searchframe) self.entry['font'] = (None, 12, 'normal') self.entry.grid(column=3, row=0, padx=4, pady=4, sticky='new') self.button = tk.Button(searchframe, text='Search', cursor='hand2') self.button.grid(column=4, row=0, padx=2, sticky='new') self.tree = ttk.Treeview(leftframe, selectmode='browse', show='headings', cursor='hand2') self.tree.grid(column=0, row=0, sticky='news') tree_scrollbar = tk.Scrollbar(leftframe, orient='vertical', command=self.tree.yview) self.tree.configure(yscrollcommand=tree_scrollbar.set) tree_scrollbar.configure(bg='#444444', activebackground='#666666', cursor='hand2') tree_scrollbar.grid(column=1, row=0, sticky='ns', padx=4) self.tree2 = tk.Text(rightframe, wrap=tk.WORD) self.tree2['highlightthickness'] = 0 self.tree2['borderwidth'] = 0 self.tree2['state'] = 'disabled' self.tree2.grid(column=0, row=0, sticky='news') tree2_scrollbar = tk.Scrollbar(rightframe, orient='vertical', command=self.tree2.yview) self.tree2.configure(yscrollcommand=tree2_scrollbar.set) tree2_scrollbar.configure(bg='#444444', activebackground='#666666', cursor='hand2') tree2_scrollbar.grid(column=1, row=0, sticky='ns', padx=4) footer = tk.Label(footerframe, text='mypython.org', bg='#333333', fg='#ffffff') footer['font'] = (None, 12, 'italic bold') footer['cursor'] = 'hand2' footer.pack(expand=True, fill='x', pady=5, ipady=3) class Controller: def __init__(self, window, database): self.window = window self.database = database # Button Commands self.window.button['command'] = self.search self.window.entry.bind('<Return>', lambda event: self.search()) # Clear trees self.window.term.trace('w', self.clear) # Bind treeview self.window.tree.bind('<<TreeviewSelect>>', self.details) def clear(self, write, index, mode): self.window.entry.delete(0, 'end') self.window.tree.delete(*self.window.tree.get_children()) self.window.tree2['state'] = 'normal' self.window.tree2.delete('1.0', 'end') self.window.tree2['state'] = 'disabled' def search(self): name = self.window.entry.get().strip() self.clear(None, None, None) self.window.tree.tag_configure('oddrow', background='#ccceee') self.window.tree.tag_configure('evenrow', background='#eeefff') if self.window.term.get() == 'Person': if name: person = self.database.search_person(name) data = self.get_person(person.personID) data.sort() self.window.tree['columns'] = ['title', 'id'] self.window.tree.column('title', minwidth=0, stretch='yes') self.window.tree.column('id', minwidth=0, width=100, stretch='no') self.window.tree.heading('title', text=f'Title\'s') self.window.tree.heading('id', text=f'Movie ID') for index, movie in enumerate(data): if index % 2 == 0: self.window.tree.insert('', 'end', values=(movie[0], movie[1],), tags=('oddrow',)) else: self.window.tree.insert('', 'end', values=(movie[0],movie[1]), tags=('evenrow',)) elif self.window.term.get() == 'Movie': if name: data = self.database.search_movie(name) data.sort() self.window.tree['columns'] = ['title', 'id'] self.window.tree.column('title', minwidth=0, stretch='yes') self.window.tree.column('id', minwidth=0, width=100, stretch='no') self.window.tree.heading('title', text=f'Title\'s') self.window.tree.heading('id', text=f'Movie ID') for index, movie in enumerate(data): if index % 2 == 0: self.window.tree.insert('', 'end', values=(movie.get('title'), movie.movieID,), tags=('oddrow',)) else: self.window.tree.insert('', 'end', values=(movie.get('title'), movie.movieID,), tags=('evenrow',)) def get_person(self, personid): person = self.database.get_person(personid) jobs = [job for job in person.get('filmography')] movies = [movie for movie in person['filmography'][jobs[0]]] titles = [] for movie in movies: titles.append((movie.get('title'), movie.movieID)) return titles def search_movie(self, name): return self.database.search_movie(name) def get_movie(self, movieid): return self.database.get_movie(str(movieid)) def details(self, event): try: item = self.window.tree.focus() movieid = self.window.tree.item(item)['values'][1] data = self.get_movie(movieid) except IndexError: pass else: title = data.get('title') year = data.get('production status') if 'production status' in data.keys() else data.get('year') cover = data.get('full-size cover url') cast = [name.get('name') for name in data.get('cast')] plot_outline = data.get('plot outline') aired = data.get('original air date') rating = data.get('rating') img_url = urlopen(cover).read() img = Image.open(io.BytesIO(img_url)) img = img.resize((300,400)) image = ImageTk.PhotoImage(img) alist = [f'Title: {title}', 'img', f'\n\nYear: {year}', f'Aired: {aired}', f'Rating: {rating}', f'Plot Outline:\n{plot_outline}', f'Cast:\n{", ".join(cast)}'] self.window.tree2['state'] = 'normal' self.window.tree2.delete('1.0', 'end') for index, data in enumerate(alist): if data == 'img': self.window.tree2.image_create('end', image=image) else: self.window.tree2.insert('end', f'{data}\n\n') self.window.tree2['state'] = 'disabled' image.bk=image if __name__ == '__main__': root = tk.Tk() controller = Controller(Window(root), Database()) img = urlopen('https://my-python.org/images/png/ratt.png') data = img.read() image = tk.PhotoImage(data=data) root.wm_iconphoto(True, image) root.mainloop() RE: Movie Search - menator01 - Sep-15-2023 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()) RE: Movie Search - gluke15 - Oct-30-2023 Good job RE: Movie Search - EdwardMatthew - Jan-24-2024 (Sep-07-2023, 04:36 AM)menator01 Wrote: I've finished the movie search script. Still a little ruff around the edges but, works. I had trouble placing text in the textbox so I went with using a frame in the textbox. That way I could kinda order the layout a little. I welcome any input. Remember it will take a few seconds to get the results as it does a few queries. My understanding of the IMDb database may search through several pages to get the information. Great job on completing the movie search script! Using a frame in the textbox for layout sounds like a smart workaround. Excited to see your progress and any future refinements. |