@@ -16,13 +16,15 @@ class Mode:
1616 """Represents a PDF processing mode with all associated metadata."""
1717
1818 def __init__ (self , name , display_name , section_title , placeholder , help_text ,
19- process_func , output_suffix ):
19+ core_func , parse_input_func , check_overwrite_func , output_suffix ):
2020 self .name = name
2121 self .display_name = display_name
2222 self .section_title = section_title
2323 self .placeholder = placeholder
2424 self .help_text = help_text
25- self .process_func = process_func
25+ self .core_func = core_func # The actual PDF manipulation function
26+ self .parse_input_func = parse_input_func # Function to parse/validate user input
27+ self .check_overwrite_func = check_overwrite_func # Function to check if files exist
2628 self .output_suffix = output_suffix
2729
2830
@@ -64,6 +66,59 @@ def parse_page_ranges(page_input):
6466 return sorted (pages )
6567
6668
69+ def parse_chunk_size (chunk_input ):
70+ """Parse and validate chunk size input."""
71+ try :
72+ chunk_size = int (chunk_input )
73+ if chunk_size <= 0 :
74+ raise ValueError ("Chunk size must be a positive integer." )
75+ return chunk_size
76+ except ValueError :
77+ raise ValueError ("Chunk size must be a positive integer." )
78+
79+
80+ def check_overwrite_single_file (output_path , parsed_input = None ):
81+ """Check if a single output file exists."""
82+ return output_path and os .path .exists (output_path )
83+
84+
85+ def check_overwrite_split_files (output_path , parsed_input = None ):
86+ """Check if any split output files would be overwritten."""
87+ if not output_path :
88+ return False
89+
90+ output_file = Path (output_path )
91+ base_name = output_file .stem
92+ output_dir = output_file .parent
93+
94+ # Check if part1 exists as a simple overwrite check
95+ first_file = output_dir / f"{ base_name } _part1.pdf"
96+ return first_file .exists ()
97+
98+
99+ def check_overwrite_image_files (output_path , parsed_input ):
100+ """Check if any image output files would be overwritten.
101+
102+ Args:
103+ output_path: Path template for output files
104+ parsed_input: List of page numbers to convert
105+ """
106+ if not output_path :
107+ return False
108+
109+ output_file = Path (output_path )
110+ base_name = output_file .stem
111+ output_dir = output_file .parent
112+
113+ # Check if any of the image files exist
114+ for page_num in parsed_input :
115+ image_file = output_dir / f"{ base_name } _page{ page_num } .png"
116+ if image_file .exists ():
117+ return True
118+
119+ return False
120+
121+
67122def trim_pdf (input_path , page_numbers , output_path ):
68123 """Create a new PDF with only the specified pages."""
69124 reader = PdfReader (input_path )
@@ -200,7 +255,9 @@ def __init__(self):
200255 section_title = "Page Ranges" ,
201256 placeholder = "e.g., 1-3,5,6-9,11" ,
202257 help_text = "Examples: 1-3,5,6-9,11 or 1,3,5 or 10-20" ,
203- process_func = self ._process_selection ,
258+ core_func = trim_pdf ,
259+ parse_input_func = parse_page_ranges ,
260+ check_overwrite_func = check_overwrite_single_file ,
204261 output_suffix = "_trimmed"
205262 ),
206263 Mode (
@@ -209,7 +266,9 @@ def __init__(self):
209266 section_title = "Chunk Size" ,
210267 placeholder = "e.g., 10" ,
211268 help_text = "Number of pages per file (greater than 0)" ,
212- process_func = self ._process_split ,
269+ core_func = split_pdf ,
270+ parse_input_func = parse_chunk_size ,
271+ check_overwrite_func = check_overwrite_split_files ,
213272 output_suffix = "_split"
214273 ),
215274 Mode (
@@ -218,7 +277,9 @@ def __init__(self):
218277 section_title = "Page Ranges" ,
219278 placeholder = "e.g., 1-3,5,6-9,11" ,
220279 help_text = "Examples: 1-3,5,6-9,11 or 1,3,5 or 10-20" ,
221- process_func = self ._process_image ,
280+ core_func = convert_to_images ,
281+ parse_input_func = parse_page_ranges ,
282+ check_overwrite_func = check_overwrite_image_files ,
222283 output_suffix = "_images"
223284 )
224285 ]
@@ -439,81 +500,28 @@ def process_pdf(self):
439500 QApplication .processEvents ()
440501
441502 try :
442- # Use the current mode's process function
443- self .current_mode .process_func (page_input )
444- except Exception as e :
445- self .status_label .setText ("Failed" )
446- self .status_label .setStyleSheet ("color: #f44336;" )
447- QMessageBox .critical (self , "Error" , str (e ))
448-
449- def _process_selection (self , page_input ):
450- """Process PDF in selection mode."""
451- self ._ensure_output_path ()
452- try :
453- page_numbers = parse_page_ranges (page_input )
454- except (ValueError , AttributeError ) as e :
455- raise ValueError (f"Invalid page format:\n { str (e )} " )
456-
457- if self .output_path and os .path .exists (self .output_path ):
458- if not self ._confirm_overwrite ():
459- return
460-
461- message = trim_pdf (self .input_path , page_numbers , self .output_path )
462- self ._show_success (message )
463-
464- def _process_split (self , chunk_input ):
465- """Process PDF in split mode."""
466- self ._ensure_output_path ()
467- try :
468- chunk_size = int (chunk_input )
469- if chunk_size <= 0 :
470- raise ValueError ("Chunk size must be a positive integer." )
471- except ValueError :
472- raise ValueError ("Chunk size must be a positive integer." )
473-
474- # Check if any output files would be overwritten
475- if self .output_path :
476- output_file = Path (self .output_path )
477- base_name = output_file .stem
478- output_dir = output_file .parent
503+ # Validate output path
504+ self ._ensure_output_path ()
479505
480- # Check if part1 exists as a simple overwrite check
481- first_file = output_dir / f"{ base_name } _part1.pdf"
482- if first_file .exists ():
506+ # Parse/validate input using mode-specific parser
507+ try :
508+ parsed_input = self .current_mode .parse_input_func (page_input )
509+ except (ValueError , AttributeError ) as e :
510+ raise ValueError (f"Invalid input:\n { str (e )} " )
511+
512+ # Check for file overwrites using mode-specific checker
513+ if self .current_mode .check_overwrite_func (self .output_path , parsed_input ):
483514 if not self ._confirm_overwrite ():
484515 return
485-
486- message = split_pdf (self .input_path , chunk_size , self .output_path )
487- self ._show_success (message )
488-
489- def _process_image (self , page_input ):
490- """Process PDF in image mode."""
491- self ._ensure_output_path ()
492- try :
493- page_numbers = parse_page_ranges (page_input )
494- except (ValueError , AttributeError ) as e :
495- raise ValueError (f"Invalid page format:\n { str (e )} " )
496-
497- # Check if any output files would be overwritten
498- if self .output_path :
499- output_file = Path (self .output_path )
500- base_name = output_file .stem
501- output_dir = output_file .parent
502516
503- # Check if any of the image files exist
504- files_exist = False
505- for page_num in page_numbers :
506- image_file = output_dir / f"{ base_name } _page{ page_num } .png"
507- if image_file .exists ():
508- files_exist = True
509- break
517+ # Execute the core PDF manipulation function
518+ message = self .current_mode .core_func (self .input_path , parsed_input , self .output_path )
519+ self ._show_success (message )
510520
511- if files_exist :
512- if not self ._confirm_overwrite ():
513- return
514-
515- message = convert_to_images (self .input_path , page_numbers , self .output_path )
516- self ._show_success (message )
521+ except Exception as e :
522+ self .status_label .setText ("Failed" )
523+ self .status_label .setStyleSheet ("color: #f44336;" )
524+ QMessageBox .critical (self , "Error" , str (e ))
517525
518526 def _confirm_overwrite (self ):
519527 """Ask user to confirm file overwrite."""
0 commit comments