SChkBtn.grid(row=0, column=3, sticky=W) #SPframe spacer (this is a dumb way) label = Label(SPframe, text=" ") label.grid(row=0, column=4, sticky=W) #WAD name WNlabel = Label(root, text="") WNlabel.grid(row=1, column=1, sticky=W) #WAD name progress bar WADprogress = Progressbar(root, orient=HORIZONTAL, length=200, mode='determinate') WADprogress.grid_remove() levels = 0 mode = [0] #WAD selector function def wadnamechange1(event): global playwad global playlevel global playmaster global levels global mode WADprogress.grid(row=1, column=1, sticky=E) if W1listbox.get(W1listbox.curselection()) == "DOOM": WNlabel.config(text="The Ultimate Doom")
class CPDApp(Tk): def __init__(self): # Poppler setup path = "poppler-0.68.0\\bin" os.environ["PATH"] += os.pathsep + path # Initialize Tk.__init__(self) self.title('CAD Plagiarism Detetctor') h = 490 w = 400 # Get screen height and width hs = self.winfo_screenheight() # height of the screen ws = self.winfo_screenwidth() # width of the screen # Calculate x and y coordinates x = (ws / 2) - (w / 2) y = (hs / 2) - (h / 2) # Set window in the middle of the screen self.geometry('%dx%d+%d+%d' % (w, h, x, y)) # Set GUI elements frame = Frame(self) frame.pack() sus_label = Label(frame, text='Suspicious Pairs') sus_label.grid(row=0, column=1) self.progress_bar = Progressbar(frame, orient='horizontal', length=100, mode='determinate') self.progress_bar.grid(row=1, column=1, pady=(0, 3)) self.progress_bar.grid_remove() listbox_frame = Frame(frame) listbox_frame.grid(row=2, column=0, columnspan=3) self.sus_listbox = Listbox(listbox_frame, width=40, height=15, selectmode='single') self.sus_listbox.pack(side='left', fill='y') self.sus_listbox.bind('<<ListboxSelect>>', self.displayFile) scrollbar = Scrollbar(listbox_frame, orient='vertical') scrollbar.config(command=self.sus_listbox.yview) scrollbar.pack(side='right', fill='y') self.sus_listbox.config(yscrollcommand=scrollbar.set) self.mask_button = Button(frame, text='Mask', width=12, command=self.chooseMask) self.mask_button.grid(row=3, column=0, pady=(3, 0)) self.input_button = Button(frame, text='Input Folder', width=12, command=self.chooseInputFolder) self.input_button.grid(row=3, column=1, pady=(3, 0)) self.output_button = Button(frame, text='Output Folder', width=12, command=self.chooseOutputFolder) self.output_button.grid(row=3, column=2, pady=(3, 0)) subsection_label = Label(frame, text='Subsections:') subsection_label.grid(row=4, column=0, columnspan=2, pady=(3, 0)) self.subsection_entry = Entry(frame, width=12) self.subsection_entry.grid(row=4, column=1, columnspan=2, pady=(3, 0)) log_name_label = Label(frame, text='Output File Name:') log_name_label.grid(row=5, column=0, columnspan=2, pady=(3, 0)) self.log_name_entry = Entry(frame, width=12) self.log_name_entry.grid(row=5, column=1, columnspan=2, pady=(3, 0)) slider_label = Label(frame, text='Sensitivity') slider_label.grid(row=6, column=1, pady=(3, 0)) lenient_label = Label(frame, text='Lenient') lenient_label.grid(row=7, column=0, pady=(3, 0), sticky='e') strict_label = Label(frame, text='Strict ') strict_label.grid(row=7, column=2, pady=(3, 0), sticky='w') self.slider = Scale(frame, from_=0.7, to=0.848, orient='horizontal', resolution=0.001, showvalue=0) self.slider.set(0.774) self.slider.grid(row=7, column=1, pady=(3, 0)) self.reset_button = Button(frame, text='Reset Sensitivity', width=12, command=self.resetSensitivity) self.reset_button.grid(row=8, column=1, pady=(3, 0)) self.start_button = Button(frame, text='Start', width=12, command=self.start) self.start_button.grid(row=9, column=1, pady=(10, 0)) self.mask_path = '' # Path to mask file self.output_path = '' # Path to where the log will be placed self.input_path = '' # Path to input files self.images_path = '' # Path to converted files self.image_folder_list = [] # List of image folders self.file_names = {} # Dictionary of the PDF names self.file_count = 0 # Number of files self.num_subsections = 7 # Number of subsections within the images self.sensitivity = self.slider.get( ) # Sensitivity when determining plagiarism # What to do on close self.protocol("WM_DELETE_WINDOW", self.close) def start(self): # Clear listbox self.sus_listbox.delete(0, 'end') # Check that user provided input if (self.subsection_entry.get() == '') or (self.log_name_entry.get() == '') or (not self.mask_path) or ( not self.output_path) or (not self.input_path): messagebox.showinfo('CAD Plagiarism Detector', 'Please provide input needed for processing.') return # Check that subsections is a number try: self.num_subsections = int(self.subsection_entry.get()) except ValueError: messagebox.showerror('CAD Plagiarism Detector', 'Subsections must be a number.') return # Disable input self.toggleInputState() # Show progress bar self.progress_bar.grid() # Make path to images folder. Tag on date and time for uniqueness. self.images_path = self.input_path + '/images_' + time.strftime( "%Y-%m-%d-%H-%M-%S") os.mkdir(self.images_path) # Add to image folder list self.image_folder_list.append(self.images_path) # Compare the images self.processing_thread = threading.Thread(target=self.compareImages, name='processing_thread', daemon=True) self.processing_thread.start() def close(self): # Delete image folders if it still exists for i in self.image_folder_list: try: shutil.rmtree(i) except PermissionError: messagebox.showerror('CAD Plagiarism Detector', 'Unable to delete images folder.') self.destroy() def toggleInputState(self): # Toggle button state to 'normal' or 'disabled' if self.mask_button['state'] == 'normal': self.mask_button['state'] = 'disabled' else: self.mask_button['state'] = 'normal' if self.output_button['state'] == 'normal': self.output_button['state'] = 'disabled' else: self.output_button['state'] = 'normal' if self.input_button['state'] == 'normal': self.input_button['state'] = 'disabled' else: self.input_button['state'] = 'normal' if self.start_button['state'] == 'normal': self.start_button['state'] = 'disabled' else: self.start_button['state'] = 'normal' if self.subsection_entry['state'] == 'normal': self.subsection_entry['state'] = 'disabled' else: self.subsection_entry['state'] = 'normal' if self.log_name_entry['state'] == 'normal': self.log_name_entry['state'] = 'disabled' else: self.log_name_entry['state'] = 'normal' if self.slider['state'] == 'normal': self.slider['state'] = 'disabled' else: self.slider['state'] = 'normal' if self.reset_button['state'] == 'normal': self.reset_button['state'] = 'disabled' else: self.reset_button['state'] = 'normal' def chooseMask(self): self.mask_path = filedialog.askopenfilename() def chooseOutputFolder(self): self.output_path = filedialog.askdirectory() def chooseInputFolder(self): self.input_path = filedialog.askdirectory() def resetSensitivity(self): # Reset sensitivity slider to default self.slider.set(0.774) def displayFile(self, event): # Display selected files from the listbox w = event.widget try: index = w.curselection()[0] value = w.get(index) path1 = '' path2 = '' try: path1 = self.input_path + '/' + value[ 0] + '_' + self.file_names[value[0]] except KeyError: path1 = self.input_path + '/' + value[0] try: path2 = self.input_path + '/' + value[ 2] + '_' + self.file_names[value[2]] except KeyError: path2 = self.input_path + '/' + value[2] subprocess.Popen([path1], shell=True) subprocess.Popen([path2], shell=True) except IndexError: # If user clicks the listbox before anything is in it pass def checkFileType(self, path): # Check file type kind = filetype.guess(path) if kind is None: messagebox.showerror('CAD Plagiarism Detector', 'Unable to determine file type.') return return kind.extension def convertToImage(self, pdf): # Must convert to jpg pages = convert_from_path(self.input_path + "/" + pdf) image = pdf.replace('PDF', 'jpg') image_path = self.images_path + "/" + image for page in pages: page.save(image_path, 'JPEG') def convertToImages(self): self.file_count = 0 valid = False # Loop through directory, converting PDFs to JPGs for entry in os.listdir(self.input_path): path = os.path.join(self.input_path, entry) if os.path.isfile(path): # Check file type if self.checkFileType(path) == 'pdf': self.convertToImage(entry) # Must convert to jpg self.file_count += 1 # Need a file count for the progress bar # Make a dictionary mapping student names to the rest of the file names # Needed for displaying the PDFs upon clicking a pair in the listbox entry_split = entry.split('_', 1) try: self.file_names[entry_split[0]] = entry_split[1] except IndexError: # File name might not be formatted in expected way with name_number.. etc. # In this case, there's no need to make a dictionary, listbox will just have the file name pass valid = True # Set to valid # Not a PDF else: messagebox.showerror('CAD Plagiarism Detector', 'File type is not PDF.') # Need to have a pair to compare if self.file_count < 2: valid = False return valid def Nmaxelements(self, list1, N): final_list = [] for i in range(0, N): max1 = 0 num = 0 for j in range(len(list1)): if list1[j][1] > max1: max1 = list1[j][1] num = list1[j][0] list1.remove((num, max1)) final_list.append((num, max1)) return final_list def compareSubimages(self, image1, image2): im = cv2.imread(self.images_path + "/" + image1) im2 = cv2.imread(self.images_path + "/" + image2) mask = cv2.imread(self.mask_path, 0) res = cv2.bitwise_and(im, im, mask=mask) imgray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(imgray, 127, 255, 0) contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) num = 0 contourArea = [] for i in contours: contourArea.append((num, cv2.contourArea(i))) num = num + 1 #We add 3 to the number of contours we're looking for since we need to account for the popping of the largest contour from the mask #and to ensure we catch all subsections that need to be compared BiggestContours = self.Nmaxelements(contourArea, self.num_subsections + 3) #pop the biggest contour which would the outline of the mask BiggestContours.pop(0) average_similarity = 0 for i in BiggestContours: x, y, w, h = cv2.boundingRect(contours[i[0]]) crop_img = im[y:y + h, x:x + w] res = cv2.matchTemplate(im2, crop_img, cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) average_similarity = average_similarity + max_val average_similarity = average_similarity / len(BiggestContours) return average_similarity def compareImages(self): # Convert to images if needed valid = self.convertToImages() if not valid: # If there are no valid files, return # Tell user messagebox.showerror('CAD Plagiarism Detector', 'Files not valid for processing.') # Enable buttons and entry again self.toggleInputState() return # Number of files in self.file_count # Find number of possible pairs num_pairs = math.factorial(self.file_count) / ( math.factorial(2) * math.factorial(self.file_count - 2)) # To keep track of processed images processed = [] # Create log file log_file_path = self.output_path + '/' + str(self.log_name_entry.get( )) + '_' + time.strftime('%Y-%m-%d-%H-%M-%S') + '.csv' log_file = open(log_file_path, 'a') # Process the files count = 0 for entry in os.listdir(self.images_path): if os.path.isfile(os.path.join(self.images_path, entry)): for entry2 in os.listdir(self.images_path): if os.path.isfile(os.path.join( self.images_path, entry2)) and entry != entry2 and frozenset( (entry, entry2)) not in processed: count += 1 # Find average similarity average_similarity = self.compareSubimages( entry, entry2) # Get sensitivity self.sensitivity = self.slider.get() # Make list to go in listbox inner_list = [] # Return the first chunk of student name, up to the first underscore (_) entry_split = entry.split('_', 1) first_name = entry_split[0] entry2_split = entry2.split('_', 1) second_name = entry2_split[0] # If input isn't formatted in the expected way -- name_number_... etc, put file name in the listbox if '.jpg' in first_name: first_name = first_name.replace('.jpg', '.pdf') if '.jpg' in second_name: second_name = second_name.replace('.jpg', '.pdf') # Add names to list inner_list.append(first_name) inner_list.append('and') inner_list.append(second_name) if average_similarity >= self.sensitivity and average_similarity <= 0.98: # Write to log file log_file.write(entry + ',' + entry2 + ',' + ', Suspicious\n') log_file.flush() # Add list to listbox self.sus_listbox.insert('end', inner_list) self.update() elif average_similarity > 0.98: # Write to log file log_file.write(entry + ',' + entry2 + ',' + ', Very Suspicious\n') log_file.flush() # Add list to listbox self.sus_listbox.insert('end', inner_list) self.update() # Mark as processed processed.append(frozenset((entry, entry2))) # Update progress bar self.progress_bar['value'] = (count / num_pairs) * 100 self.update() time.sleep(1) # Show that comparisons are complete messagebox.showinfo('CAD Plagiarism Detector', 'Done processing files.') # Enable buttons and entry again self.toggleInputState() # Make progress bar invisible and reset to 0 self.progress_bar['value'] = 0 self.progress_bar.grid_remove() # Close log file log_file.close()
class Application(Frame): def __init__(self, master=None): super().__init__(master) self.master = master self.grid(row=0, column=0, sticky="nesw", padx=20, pady=20) self._create_widgets() self._selected_genre = set() self._helper = None self._books = [] self._is_started = False def _add_titles_to_listbox(self): books = [] self.books.delete(0, tk.END) for genre in sorted(self._selected_genre): books.extend(self._helper.get_books_in_genres(self._books, genre)) books.sort() self.books.insert(tk.END, *books) def _create_widgets(self): def _create_label(frame, text, coordinates): label = Label(frame, text=text, justify=tk.LEFT, anchor="w", width=20) label.grid(row=coordinates[0], column=coordinates[1]) _create_label(self, "Output Folder:", (0, 0)) self.output_path = Entry(self) self.output_path.grid(row=1, column=0, columnspan=2, sticky="ew", pady=(0, 15)) _create_label(self, "Available Genres:", (2, 0)) _create_label(self, "Books to Download:", (2, 1)) self.genres = tk.Listbox(self, selectmode="multiple") def on_genre_select(evt): indices = evt.widget.curselection() self._selected_genre.clear() for index in indices: value = evt.widget.get(index) self._selected_genre.add(value) self._add_titles_to_listbox() self.genres.bind("<<ListboxSelect>>", on_genre_select) self.genres["height"] = 20 self.genres["width"] = 30 self.genres.grid(row=3, column=0, padx=(0, 10)) self.books = tk.Listbox(self) self.books["height"] = 20 self.books["width"] = 30 self.books.grid(row=3, column=1, padx=(10, 0)) self._pdf = tk.IntVar(value=1) self.pdf = Checkbutton(self, text="PDF", variable=self._pdf) self.pdf.grid(row=4, column=0, pady=10) self._epub = tk.IntVar(value=1) self.epub = Checkbutton(self, text="EPUB", variable=self._epub) self.epub.grid(row=4, column=1, pady=10) self._status_text = tk.StringVar() self.status = Label(self, textvariable=self._status_text) self.status.grid(row=5, column=0, columnspan=2) self._current_bar_value = tk.IntVar(value=0) self.bar = Progressbar(self, variable=self._current_bar_value) self._download_btn = tk.StringVar() db = Button(self, textvariable=self._download_btn) db["command"] = self.start_download self._download_btn.set("Download") db.grid(row=7, column=0, columnspan=2, pady=10) LOG.info("All widgets created.") def set_output_folder(self, path): if self.output_path: self.output_path.insert(tk.END, path) def populate_genres(self, genres): self._genre_mapping = genres for genre in sorted(genres): self.genres.insert(tk.END, genre) LOG.info("Added {} genres".format(len(genres))) def start_download(self): titles = self.books.get(0, tk.END) if not titles: self._status_text.set("Please select a genre to continue") return self._is_started = not self._is_started self._toggle_state(not self._is_started) if self._is_started: books = self._books.copy() for book in books.iterrows(): if book[1]["Book Title"] not in titles: books = books.drop(index=book[0]) LOG.info("Starting to download {} books".format(len(books))) self.bar["maximum"] = len(books) self._helper.STOP_FLAG = False self._download_thread = threading.Thread( daemon=True, target=self._helper.download_books, args=(books, self.output_path.get()), kwargs={ "pdf": self._pdf.get(), "epub": self._epub.get(), "verbose": True, "label": self._status_text, "progressbar": self._current_bar_value, }, ) self._download_thread.start() self._thread_check_in(self._download_thread) else: self._helper.STOP_FLAG = True def _thread_check_in(self, thread, period=100): if thread.isAlive(): self.master.after(period, self._thread_check_in, thread, period) else: self._is_started = False self._toggle_state(True) def _toggle_state(self, enable): state = tk.NORMAL if enable else tk.DISABLED text = "Download" if enable else "Stop" status = "" if enable else "Starting downloader ..." self.output_path.config(state=state) self.genres.config(state=state) self.books.config(state=state) self.pdf.config(state=state) self.epub.config(state=state) self._download_btn.set(text) self._status_text.set(status) if enable: self.bar.grid_remove() else: self.bar.grid(row=6, column=0, columnspan=2, pady=10, sticky="ew")
class Creator: def __init__(self): self.__thread_pool_executor = futures.ThreadPoolExecutor(max_workers=1) self.__ttk = Tk() self.__confwindow() self.__gui = Frame(self.__ttk, bd=10) self.__gui.grid() self.__gui.place(relx=0.5, rely=0.5, anchor=CENTER) self.__s = Label(self.__gui, text='') self.__status = Label(self.__gui, text='') self.__var = IntVar() self.__progress = Progressbar(self.__gui, orient=HORIZONTAL, length=400, mode='determinate') self.i_folder_selected = "" self.o_folder_selected = "" def __confwindow(self): """ this will resize window """ window_height = 530 window_width = 900 screen_width = self.__ttk.winfo_screenwidth() screen_height = self.__ttk.winfo_screenheight() x_cordinate = int((screen_width / 2) - (window_width / 2)) y_cordinate = int((screen_height / 2) - (window_height / 2)) self.__ttk.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate)) # gui.geometry("530x400") self.__ttk.resizable(False, False) self.__ttk.title("Dataset Creator") self.__ttk.deiconify() def openwindow(self): """ this will open window """ # -------------- title label ----------- # Label(self.__gui, text='Dataset Creator', font=('Helvetica', 18, 'bold')).grid(row=0, column=0, padx=10, pady=10) # -------------- File and Folder selection ----------- # def setfolderpath(): self.i_folder_selected = filedialog.askdirectory() # delete content from position 0 to end b2.delete(0, END) # insert new_text at position 0 b2.insert(0, self.i_folder_selected) def setfilepath(): self.o_folder_selected = filedialog.askdirectory() # delete content from position 0 to end b5.delete(0, END) # insert new_text at position 0 b5.insert(0, self.o_folder_selected) selection = Frame(self.__gui) # buttons.pack(fill="x") selection.grid() b1 = Label(selection, text="Select Input Files Folder") b2 = Entry(selection, width=30) b3 = Button(selection, text="Browse Folder", command=setfolderpath) b1.grid(row=1, column=1) b2.grid(row=1, column=2) b3.grid(row=1, column=3) b4 = Label(selection, text="Select Output Images Folder") b5 = Entry(selection, width=30) b6 = Button(selection, text="Browse Folder", command=setfilepath) b4.grid(row=2, column=1, padx=5, pady=5) b5.grid(row=2, column=2, padx=5, pady=5) b6.grid(row=2, column=3, padx=5, pady=5) # -------------- title label ----------- # Label(self.__gui, text='Select File Type', font=('Helvetica', 10, 'bold')).grid(row=3, column=0, padx=10, pady=10) # -------------- radio button frame ----------- # frm = Frame(self.__gui, bd=10) frm.grid() self.__var.set(1) mild = Radiobutton(frm, text='PDF', variable=self.__var, value=1) mild.grid(row=4, column=0) medium = Radiobutton(frm, text='TIF', variable=self.__var, value=2) medium.grid(row=4, column=1) # -------------- buttons frame ----------- # frm1 = Frame(self.__gui, bd=10) frm1.grid() d = Button(frm1, text="Start Process", command=self.__start, width=12) d.grid(row=5, column=0, padx=10, pady=0) c = Button(frm1, text="Cancel", command=self.__closewindow, width=12) # c['state'] = 'disabled' or 'normal' c.grid(row=5, column=1, padx=10, pady=30) # -------------- progressbar ----------- # self.__progress.grid(row=6, column=0, padx=0, pady=0) self.__progress.grid_remove() self.__status.grid(row=7, column=0, padx=0, pady=0) self.__s.grid(row=8, column=0, padx=10, pady=30) self.__ttk.tk.call( 'wm', 'iconphoto', self.__ttk._w, PhotoImage(file=dirname(abspath(__file__)) + os.sep + 'da_icon.png')) self.__ttk.mainloop() def __setcount(self, file, count, length, output): """ this will set counter in window """ if file is not None: if count == length: self.__progress.grid() self.__progress['value'] = 100 self.__s[ 'text'] = "Image extraction completed from all files,\nplease find images at " + output self.__status['text'] = str(count) + " of " + str( length) + " file(s) completed" else: self.__progress.grid() self.__progress['value'] = int((count / length) * 100) self.__s['text'] = os.path.basename( file) + " is being extracted...." self.__status['text'] = str(count) + " of " + str( length) + " file(s) completed" else: self.__s['text'] = "No Files Found" def __pdfutil(self, file, output_path): """ this will extract text from pdf file """ if platform.system() == 'Windows': images = convert_from_path( file, poppler_path=dirname(abspath(__file__)) + os.sep + 'poppler' + os.sep + 'bin') else: images = convert_from_path(file) file_name = os.path.basename(file) for i, img in enumerate(images, start=1): path = output_path + os.sep + file_name + '_' + str(i) + ".jpg" img.save(path, 'JPEG') def __tifutil(self, file, output_path): """ this will extract text from tif images """ file_name = os.path.basename(file) images = MultiImage(file, plugin='pil') for i, img in enumerate(images, start=1): pil_img = pillowimg.fromarray(img) path = output_path + os.sep + file_name + '_' + str(i) + ".jpg" pil_img.save(path, 'JPEG') def __extractor(self): """ this will read files from input folder and starts process """ if self.__var.get() == 2: files = glob.glob(self.i_folder_selected + "/*.TIF") + glob.glob(self.i_folder_selected + "/*.TIFF") ll = len(files) if ll != 0: for i, file in enumerate(files): self.__setcount(file, i, ll, self.o_folder_selected) self.__tifutil(file, self.o_folder_selected) self.__setcount("", ll, ll, self.o_folder_selected) else: print('No file found') elif self.__var.get() == 1: files = glob.glob(self.i_folder_selected + "/*.PDF") ll = len(files) if ll != 0: for i, file in enumerate(files): self.__setcount(file, i, ll, self.o_folder_selected) self.__pdfutil(file, self.o_folder_selected) self.__setcount("", ll, ll, self.o_folder_selected) else: print('No file found') def __start(self): """ this will start process in thread """ self.__thread_pool_executor.submit(self.__extractor) def __closewindow(self): """ this will close window """ self.__thread_pool_executor.shutdown(wait=False) self.__ttk.quit() self.__ttk.destroy() raise ValueError()
class SearchBar(Frame, GUIComponent): REGEX_RATING = re.compile(r"^[0-9](\.[0-9])?$") def __init__(self, master, genres): super().__init__(master) self.__media_choice = StringVar() self.__rating_choice = None self.__genre_choice = StringVar() self.__search = None self.__progressbar = None self.__search_serie_input = None # genres has the following structure: # [{'id': 4, 'genre': 'Action'}, {'id': 1, 'genre': 'Adventure'},...] # but it's more useful the following structure # {'Action': 4, 'Adventure': 1} self.__genres = {} for genre in genres: self.__genres[genre["genre"]] = genre["id"] self.__genres["Todos"] = 0 self.__search_results = None self.grid_columnconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) self.grid_columnconfigure(2, weight=1) self.grid_columnconfigure(3, weight=1) self.grid_rowconfigure(0, weight=1) self.grid_rowconfigure(1, weight=1) self.grid_rowconfigure(2, weight=1) # Override def init_components(self): self.__init_labels() self.__init_interactive_widgets() self.__progressbar = Progressbar(self, orient=HORIZONTAL, length=100, mode="determinate") def __init_labels(self): default_kwargs = {"sticky": 's', "padx": 5, "pady": 3} content_type_label = Label(self, text="Tipo de contenido") rating_label = Label(self, text="Rating mínimo") genre_label = Label(self, text="Género") content_type_label.grid(row=0, column=0, **default_kwargs) rating_label.grid(row=0, column=2, **default_kwargs) genre_label.grid(row=0, column=3, **default_kwargs) def __init_interactive_widgets(self): default_kwargs = {"sticky": 'n', "padx": 7, "pady": 5} # Type of media dropdown initialization opts_dropdown = ["Película", "Episodio", "Episodio o Película"] self.__media_choice.set(opts_dropdown[-1]) media_dropdown = OptionMenu(self, self.__media_choice, *opts_dropdown) media_dropdown.grid(row=1, column=0, **default_kwargs) # Search input initialization self.__search = InputWithPlaceholder( master=self, placeholder="Encuentra lo que buscas...", width=40) self.__search.init_components() self.__search.grid(row=1, column=1, **default_kwargs) # minimum rating initialization self.__rating_choice = Spinbox(self, from_=0, to=10, increment=0.5) self.__rating_choice.grid(row=1, column=2, **default_kwargs) # genre dropdown initialization opts_dropdown = list(self.__genres.keys()) self.__genre_choice.set(opts_dropdown[-1]) genre_dropdown = OptionMenu(self, self.__genre_choice, *opts_dropdown) genre_dropdown.grid(row=1, column=3, **default_kwargs) # search button initialization search_button = Button(self, text="Buscar", command=self.__on_click_search) search_button.grid(row=1, column=4, **default_kwargs) # NOW THE FOURTH ROW, CONTAINING THE SEARCH BY SERIE # (the third row is for the progressbar only) search_serie_label = Label(self, text="Buscar episodios de la serie con ID:") search_serie_label.grid(row=3, column=0, **default_kwargs) self.__search_serie_input = InputWithPlaceholder( master=self, placeholder="ID de la serie \"tt#####\"", width=40) self.__search_serie_input.init_components() self.__search_serie_input.grid(row=3, column=1, **default_kwargs) search_serie_button = Button(self, text="Buscar episodios", command=self.__on_click_search_episodes) search_serie_button.grid(row=3, column=2, **default_kwargs) def __on_click_search(self): # Get selected values media_choice = self.__media_choice.get() search = '' if self.__search.placeholder_is_active else self.__search.get( ).strip() rating_choice = self.__rating_choice.get() genre_choice = self.__genre_choice.get() # check if rating is valid if not SearchBar.REGEX_RATING.match(rating_choice): messagebox.showerror( "Rating no válido", "El rating debe tener un formato de #.#, y debe estar entre 0 y 10" ) return if len(search) > 100: messagebox.showerror( "Búsqueda muy larga", "Por favor limite su búsqueda a 100 caracteres") return rating_choice = float(rating_choice) # Prepare payload if media_choice == "Episodio o Película": media_choice = "video" elif media_choice == "Película": media_choice = "movie" else: media_choice = "episode" genre_idx = self.__genres[genre_choice] payload = { "type_of_content": media_choice, "search": search, "min_rating": rating_choice, "genre": genre_idx } # Send payload status_queue = Queue() request = Request(status_queue, "media", body=payload) print("Searching", payload) request.start() error = False self.__progressbar.grid(row=2, column=0, sticky='n', pady=3) self.__progressbar["value"] = 25 while True: if not status_queue.empty(): tmp_response = status_queue.get() if tmp_response == "sent": self.__progressbar["value"] = 50 elif tmp_response == "received": self.__progressbar["value"] = 75 elif tmp_response == "ok": self.__progressbar["value"] = 100 break elif tmp_response == "error": error = True break self.__progressbar.grid_remove() if error: messagebox.showerror( "Error", "Algo malo ha sucedido al realizar la búsqueda") return response = status_queue.get() if self.__search_results is None: raise MissingProperty("search_results", self) self.__search_results.clear_all() if media_choice == "movie": self.__show_response(response, "movies") elif media_choice == "episode": self.__show_response(response, "episodes") else: self.__show_response(response, "movies") self.__show_response(response, "episodes") def __show_response(self, response, content_type): res = response[content_type] if content_type == "movies": self.__search_results.insert_movie_results(res) else: self.__search_results.insert_episode_results(res) def __on_click_search_episodes(self, *args): serie_id = self.__search_serie_input.get().strip() serie_id = serie_id.replace("tt", '') if not serie_id.isnumeric(): messagebox.showerror( "ID de la serie no válido", "Ingrese un ID correcto, puede ser un número o las letras \"tt\" seguidas del ID" ) return serie_id = int(serie_id) payload = {"serie_id": serie_id} status_queue = Queue() request = Request(status_queue, "episodes", body=payload) print("Searching", payload) request.start() error = False self.__progressbar.grid(row=2, column=0, sticky='n', pady=3) self.__progressbar["value"] = 25 while True: if not status_queue.empty(): tmp_response = status_queue.get() if tmp_response == "sent": self.__progressbar["value"] = 50 elif tmp_response == "received": self.__progressbar["value"] = 75 elif tmp_response == "ok": self.__progressbar["value"] = 100 break elif tmp_response == "error": error = True break self.__progressbar.grid_remove() if error: messagebox.showerror( "Error", "Algo malo ha sucedido al realizar la búsqueda") return response = status_queue.get() if self.__search_results is None: raise MissingProperty("search_results", self) self.__search_results.clear_all() response = {"movies": [], "episodes": response["episodes"]} self.__show_response(response, "movies") self.__show_response(response, "episodes") def __update_serie_search(self, serie_id): self.__search_serie_input.delete(0, END) self.__search_serie_input.insert(0, serie_id) self.__on_click_search_episodes(None) @property def search_results(self): return self.__search_results is not None @search_results.setter def search_results(self, search_result_obj): if self.__search_results is not None: raise ValueError("search_results already has a value") self.__search_results = search_result_obj self.__search_results.cb_search_serie = self.__update_serie_search