1111from qgis .PyQt .QtCore import pyqtSignal
1212from qgis .PyQt .QtWidgets import (
1313 QVBoxLayout , QHBoxLayout , QFormLayout , QLineEdit , QPushButton ,
14- QLabel , QFileDialog , QProgressBar , QMessageBox , QCheckBox , QSpinBox
14+ QLabel , QFileDialog , QProgressBar , QMessageBox , QCheckBox , QSpinBox , QTextEdit
1515)
1616from qgis .PyQt .QtGui import QFont
1717from qgis .core import QgsProject , QgsVectorLayer , QgsVectorFileWriter
@@ -89,7 +89,7 @@ def setup_ui(self):
8989 self .pixel_label .setEnabled (False )
9090 self .pixel_spinbox = QSpinBox ()
9191 self .pixel_spinbox .setRange (100 , 10000 )
92- self .pixel_spinbox .setValue (300 )
92+ self .pixel_spinbox .setValue (1920 )
9393 self .pixel_spinbox .setSuffix (" px" )
9494 self .pixel_spinbox .setEnabled (False )
9595 pixel_layout .addWidget (self .pixel_label )
@@ -105,6 +105,29 @@ def setup_ui(self):
105105
106106 layout .addLayout (image_group )
107107
108+ # Archive notes section
109+ notes_group = QVBoxLayout ()
110+ notes_group .setSpacing (8 )
111+
112+ notes_label = QLabel ("Archive Notes (optional):" )
113+ notes_label .setStyleSheet ("font-weight: bold;" )
114+ notes_group .addWidget (notes_label )
115+
116+ self .notes_textedit = QTextEdit ()
117+ self .notes_textedit .setPlaceholderText ("Enter optional notes about this archive (e.g., purpose, context, modifications made)..." )
118+ self .notes_textedit .setMaximumHeight (80 )
119+ self .notes_textedit .setStyleSheet (
120+ "QTextEdit { "
121+ "border: 1px solid #ddd; "
122+ "border-radius: 4px; "
123+ "padding: 8px; "
124+ "font-size: 12px; "
125+ "}"
126+ )
127+ notes_group .addWidget (self .notes_textedit )
128+
129+ layout .addLayout (notes_group )
130+
108131 # Archive button
109132 self .archive_btn = QPushButton ("Create Portable Archive" )
110133 self .archive_btn .setStyleSheet (
@@ -186,6 +209,7 @@ def _show_help_popup(self):
186209 "</ul>"
187210 "<h4>Result:</h4>"
188211 "<p>A <b>'{project_name}_portable.qgs'</b> file that can be opened on any computer without needing PostgreSQL access.</p>"
212+ "<p>An <b>'archive_report.txt'</b> file is also created with details about the archiving process, including date, source project, and any user notes.</p>"
189213 "<h4>⚠️ Important notes:</h4>"
190214 "<ul>"
191215 "<li><b>Large files:</b> DCIM folders and media files will be copied (may take time)</li>"
@@ -215,6 +239,65 @@ def _browse_output_folder(self):
215239 self .output_folder_edit .setText (folder )
216240 self .emit_log (f"Output folder set to: { folder } " )
217241
242+ def _create_archive_report (self , output_folder , project_file , resized_images_count = 0 ):
243+ """Create an archive report file with details about the archiving process"""
244+ try :
245+ from datetime import datetime
246+
247+ report_path = Path (output_folder ) / "archive_report.txt"
248+
249+ # Get current date and time
250+ current_datetime = datetime .now ().strftime ("%Y-%m-%d %H:%M:%S" )
251+
252+ # Get project information
253+ project_name = os .path .splitext (os .path .basename (project_file ))[0 ]
254+ project_path = str (project_file )
255+
256+ # Get user notes
257+ user_notes = self .notes_textedit .toPlainText ().strip ()
258+
259+ # Create report content
260+ report_lines = [
261+ "QGIS PORTABLE PROJECT ARCHIVE REPORT" ,
262+ "=" * 45 ,
263+ "" ,
264+ f"Archive Date: { current_datetime } " ,
265+ f"Source Project: { project_name } " ,
266+ f"Source Path: { project_path } " ,
267+ f"Output Folder: { output_folder } " ,
268+ "" ,
269+ "PROCESSING DETAILS:" ,
270+ "- PostgreSQL layers converted to GeoPackage format" ,
271+ "- All project files and folders copied to output directory" ,
272+ "- Project file updated to reference local data sources" ,
273+ ]
274+
275+ # Add image resizing info if applicable
276+ if self .resize_images_checkbox .isChecked ():
277+ max_pixels = self .pixel_spinbox .value ()
278+ report_lines .extend ([
279+ f"- Images resized to maximum { max_pixels } px on long side" ,
280+ f"- Total images processed: { resized_images_count } "
281+ ])
282+
283+ # Add user notes if provided
284+ if user_notes :
285+ report_lines .extend ([
286+ "" ,
287+ "USER NOTES:" ,
288+ "-" * 12 ,
289+ user_notes
290+ ])
291+
292+ # Write report file
293+ with open (report_path , 'w' , encoding = 'utf-8' ) as f :
294+ f .write ("\n " .join (report_lines ))
295+
296+ self .emit_log (f"Archive report created: { report_path } " )
297+
298+ except Exception as e :
299+ self .emit_log (f"Could not create archive report: { str (e )} " )
300+
218301 def _resize_images_in_folder (self , folder_path , max_long_side ):
219302 """Resize all images in a folder if their long side exceeds max_long_side"""
220303 supported_formats = ('.jpg' , '.jpeg' , '.png' , '.tiff' , '.tif' , '.bmp' , '.webp' )
@@ -345,7 +428,7 @@ def _on_archive_project(self):
345428 project_dir = project_file .parent
346429 total_files = len ([item for item in project_dir .iterdir () if item .name != project_file .name ])
347430
348- total_steps = total_files + total_layers + 2 # +2 for project copy and final update
431+ total_steps = total_files + total_layers + 3 # +3 for project copy, final update, and report creation
349432 current_step = 0
350433
351434 # Switch to determinate progress
@@ -394,11 +477,11 @@ def _on_archive_project(self):
394477 self .progress_bar .setValue (current_step )
395478
396479 # 2. Resize images in DCIM folders if requested
480+ total_resized = 0
397481 if self .resize_images_checkbox .isChecked () and dcim_folders :
398482 max_pixels = self .pixel_spinbox .value ()
399483 self .emit_log (f"Resizing images in DCIM folders to { max_pixels } px long side..." )
400484
401- total_resized = 0
402485 for dcim_folder in dcim_folders :
403486 self .progress_label .setText (f"Processing images in { dcim_folder .name } ..." )
404487 resized_count = self ._resize_images_in_folder (str (dcim_folder ), max_pixels )
@@ -474,6 +557,16 @@ def _on_archive_project(self):
474557 current_step += 1
475558 self .progress_bar .setValue (current_step )
476559
560+ # 6. Create archive report
561+ self .progress_label .setText ("Creating archive report..." )
562+ self ._create_archive_report (
563+ str (output_folder ),
564+ str (project_file ),
565+ total_resized
566+ )
567+ current_step += 1
568+ self .progress_bar .setValue (current_step )
569+
477570 self .progress_label .setText ("Complete!" )
478571 self .emit_log (f"✓ Successfully archived project '{ project_name } ' to { export_path } " )
479572 self .project_archived .emit (str (export_path ))
0 commit comments