def move_files(self): """ Callback function that invokes FileOrganizer's move_files function """ # Explicit conversion to string to avoid complications in posixpath # Skip the first two spaces displayed in each filename of the # Destination directory. Only consider the checked items origin_filenames = [str(self.origin_content.model.item(i).text()[2:]) for i in range(self.origin_content.model.rowCount()) if self.origin_content.model.item(i).checkState()] try: FileOrganizer.move_files(str(self.browse_textbox1.text()), origin_filenames, str(self.browse_textbox2.text()), self.button_group.checkedId(), (self.custom_combo.currentIndex(), str(self.custom_textbox.text())), (self.numbering_check.isChecked(), str(self.numbering_digits.text()), self.numbering_combo.currentIndex(), str(self.numbering_rename.text())), (self.remove_check.isChecked(), str(self.remove_textbox.text())), self.lowercase_check.isChecked(), self.duplicate_check.isChecked(), self.replace_files.isChecked()) except FileOrganizer.NoSelectedFiles: self.status_label.setText("No selected files to move!") return # Refill the ListViews with their new file content after # the last operation self.origin_content.populate_list(retrieve_directory_content( self.browse_textbox1.text()), True) self.destination_content.populate_list(retrieve_directory_content( self.browse_textbox2.text()), False) # Set the Toggle All Checkbox Off too self.toggle_all_left.setChecked(False) # Update the status bar self.status_label.setText("Moved files from {} to {}".format( self.browse_textbox1.text(), self.browse_textbox2.text()))
def file_dialog1(self): """ Opens QFileDialog for the Origin Folder's Browse button. """ path = QtGui.QFileDialog.getExistingDirectory(self, "Open Directory", norm_pathname(self.browse_textbox1.text()), QtGui.QFileDialog.ShowDirsOnly) if path: self.browse_textbox1.setText(path) self.origin_content.populate_list(retrieve_directory_content(path), True)
def file_dialog2(self): """ Opens QFileDialog for the Destination Folder's Browse button. """ path = QtGui.QFileDialog.getExistingDirectory(self, "Open Directory", norm_pathname(self.browse_textbox2.text()), QtGui.QFileDialog.ShowDirsOnly) if path: self.browse_textbox2.setText(path) self.destination_content.populate_list(retrieve_directory_content(path), False)
def __init__(self): # Standard reference to QtGui.QMainWindow"s __init__ super(FileOrganizerWindow, self).__init__() # Create and set the container"s central widget of the window main_container = QtGui.QWidget(self) self.setCentralWidget(main_container) # Horizontal container of all the layouts in the window main_layout = QtGui.QHBoxLayout() # --------- LEFT SIDE FOLDER (ORIGIN) --------- # Horizontal layout for the origin folder left_side_layout = QtGui.QVBoxLayout() # Origin folder label origin_label = new_label("Origin Folder", 10, bold=True) # Browse origin folder textbox and button browse_origin_layout = QtGui.QHBoxLayout() self.browse_textbox1 = BrowserTextbox() self.browse_button1 = new_button("Browse", 8) # Toggle All button (Origin folder) check_origin_layout = QtGui.QHBoxLayout() self.toggle_all_left = new_checkbox("Toggle All Files") # Directory content list self.origin_content = DirectoryContentList() # Fill the origin_content list with the user's Home content # which will differ with the right side in that it's checkable self.origin_content.populate_list(retrieve_directory_content( expanduser("~")), True) # Set the content of the origin textbox to Home too self.browse_textbox1.setText(norm_pathname(expanduser("~"))) # --------- RIGHT SIDE FOLDER (DESTINATION) --------- # Horizontal layout for the destination folder right_side_layout = QtGui.QVBoxLayout() # Destination folder label destination_label = new_label("Destination Folder", 10, True) # Browse origin folder text and button browse_destination_layout = QtGui.QHBoxLayout() self.browse_textbox2 = BrowserTextbox(left_side=False) self.browse_button2 = new_button("Browse", 8) destination_content_label = new_label("Current Files:", 9) # Destination directory content list self.destination_content = DirectoryContentList() # Fill the Destination Content list with the script's location self.destination_content.populate_list(retrieve_directory_content( norm_pathname()), False) # Set the content of the destination textbox to getcwd() too self.browse_textbox2.setText(norm_pathname()) # Options layout options_layout = QtGui.QVBoxLayout() # Pre-order Frame and Layout order_frame = new_frame(main_container, "preorder_frame", raised=True) order_layout = QtGui.QVBoxLayout() order_label = new_label("Pre-Order By:", 9, True) # Pre-order's Radio Button Group self.button_group = QtGui.QButtonGroup(self) # Pre-order Radio options (layout, button and label for each) # Set an incremental id for each radio button abc_layout = QtGui.QHBoxLayout() abc_radio = QtGui.QRadioButton() abc_radio.setChecked(True) self.button_group.addButton(abc_radio) self.button_group.setId(abc_radio, 0) abc_label = new_label("A - Z", 8) zyx_layout = QtGui.QHBoxLayout() zyx_radio = QtGui.QRadioButton() self.button_group.addButton(zyx_radio) self.button_group.setId(zyx_radio, 1) zyx_label = new_label("Z - A", 8) date_layout = QtGui.QHBoxLayout() date_radio = QtGui.QRadioButton() self.button_group.addButton(date_radio) self.button_group.setId(date_radio, 2) date_label = new_label("Creation Date", 8) custom_layout = QtGui.QHBoxLayout() custom_radio = QtGui.QRadioButton() custom_layout.addStretch(1) self.button_group.addButton(custom_radio) self.button_group.setId(custom_radio, 3) self.custom_combo = new_combo(("Detect numbers after this pattern:", "Detect numbers before this pattern:")) self.custom_textbox = new_line_edit(120) # Rename Frame rename_frame = new_frame(main_container, "rename_frame", raised=True) rename_layout = QtGui.QVBoxLayout() rename_label = new_label("Rename Pattern (Optional):", 9, True) # Rename Frame's widgets numbering_layout = QtGui.QHBoxLayout() self.numbering_check = new_checkbox("Insert numeration with ") self.numbering_digits = new_line_edit(40) self.numbering_digits.setText("4") numbering_label = new_label("digits", 9) self.numbering_combo = new_combo(("after this string:", "before this string:")) self.numbering_rename = new_line_edit(120) remove_layout = QtGui.QHBoxLayout() self.remove_check = new_checkbox("Remove the following characters: ") self.remove_textbox = new_line_edit(80) lowercase_layout = QtGui.QHBoxLayout() self.lowercase_check = new_checkbox("Transform to lowercase") # Process options combo self.duplicate_check = new_checkbox("Duplicate files instead") # Replace existing files checkbox self.replace_files = new_checkbox("Avoid replacing existing files") # Move Files button self.apply_button = new_button("Move Files", 10, 350) # --------- CONNECTIONS AND SIGNALS --------- # Origin folder Browse button connection self.connect(self.browse_button1, Signal("clicked()"), self.file_dialog1) # Destination folder Browse button connection self.connect(self.browse_button2, Signal("clicked()"), self.file_dialog2) # Origin folder's "Toggle All" checkbox connection self.connect(self.toggle_all_left, Signal("clicked()"), self.toggle_origin_items) # Move Files button signal connection self.connect(self.apply_button, QtCore.SIGNAL("clicked()"), self.move_files) # --------- LAYOUTS --------- # Origin folder's layout left_side_layout.addWidget(origin_label) add_space(left_side_layout, 0, 10) browse_origin_layout.addWidget(self.browse_textbox1) add_space(browse_origin_layout, 15, 0) browse_origin_layout.addWidget(self.browse_button1) add_space(browse_origin_layout, 15, 0) left_side_layout.addLayout(browse_origin_layout) add_space(left_side_layout, 0, 10) check_origin_layout.addWidget(self.toggle_all_left) check_origin_layout.setAlignment(QtCore.Qt.AlignLeft) left_side_layout.addLayout(check_origin_layout) add_space(left_side_layout, 0, 10) left_side_layout.addWidget(self.origin_content) main_layout.addLayout(left_side_layout) # Destination folder's layout right_side_layout.addWidget(destination_label) add_space(right_side_layout, 0, 10) browse_destination_layout.addWidget(self.browse_textbox2) add_space(browse_destination_layout, 15, 0) browse_destination_layout.addWidget(self.browse_button2) add_space(browse_destination_layout, 15, 0) right_side_layout.addLayout(browse_destination_layout) add_space(right_side_layout, 0, 10) right_side_layout.addWidget(destination_content_label) add_space(right_side_layout, 0, 10) right_side_layout.addWidget(self.destination_content) # Options' layout options_vbox = QtGui.QVBoxLayout() # Pre-Order Layout order_layout.addWidget(order_label) abc_layout.addWidget(abc_radio) abc_layout.addWidget(abc_label) abc_layout.setAlignment(QtCore.Qt.AlignLeft) add_space(order_layout, 0, 5) order_layout.addLayout(abc_layout) zyx_layout.addWidget(zyx_radio) zyx_layout.addWidget(zyx_label) zyx_layout.setAlignment(QtCore.Qt.AlignLeft) add_space(order_layout, 0, 5) order_layout.addLayout(zyx_layout) date_layout.addWidget(date_radio) date_layout.addWidget(date_label) date_layout.setAlignment(QtCore.Qt.AlignLeft) add_space(order_layout, 0, 5) order_layout.addLayout(date_layout) custom_layout.addWidget(custom_radio) custom_layout.addWidget(self.custom_combo) custom_layout.addWidget(self.custom_textbox) custom_layout.setAlignment(QtCore.Qt.AlignLeft) add_space(order_layout, 0, 5) order_layout.addLayout(custom_layout) order_frame.setLayout(order_layout) add_space(options_vbox, 0, 20) options_vbox.addWidget(order_frame) # Rename Frame's Layout rename_layout.addWidget(rename_label) numbering_layout.addWidget(self.numbering_check) numbering_layout.addWidget(self.numbering_digits) numbering_layout.addWidget(numbering_label) numbering_layout.addWidget(self.numbering_combo) numbering_layout.addWidget(self.numbering_rename) numbering_layout.setAlignment(QtCore.Qt.AlignLeft) add_space(rename_layout, 0, 10) rename_layout.addLayout(numbering_layout) remove_layout.addWidget(self.remove_check) remove_layout.addWidget(self.remove_textbox) remove_layout.addStretch(1) remove_layout.setAlignment(QtCore.Qt.AlignLeft) add_space(rename_layout, 0, 10) rename_layout.addLayout(remove_layout) lowercase_layout.addWidget(self.lowercase_check) lowercase_layout.setAlignment(QtCore.Qt.AlignLeft) add_space(rename_layout, 0, 10) rename_layout.addLayout(lowercase_layout) rename_layout.setAlignment(QtCore.Qt.AlignLeft) rename_frame.setLayout(rename_layout) add_space(options_vbox, 0, 20) options_vbox.addWidget(rename_frame) add_space(options_vbox, 0, 20) # Additional Options' addition to layout options_vbox.addWidget(self.duplicate_check) add_space(options_vbox, 0, 5) options_vbox.addWidget(self.replace_files) add_space(options_vbox, 0, 15) options_vbox.addWidget(self.apply_button) options_vbox.setAlignment(QtCore.Qt.AlignTop) # Add each of the elements with a separation of 20 pixels # between them; add a line between them add_space(main_layout, 20, 0) main_layout.addWidget(add_line(200)) add_space(main_layout, 20, 0) main_layout.addLayout(right_side_layout) add_space(main_layout, 20, 0) main_layout.addWidget(add_line(200)) add_space(main_layout, 20, 0) main_layout.addLayout(options_vbox) # Add the main Window's StatusBar for warnings self.status_label = new_label("", 8, color="333333") self.statusBar().addPermanentWidget(self.status_label) main_container.setLayout(main_layout) self.setWindowTitle("File Organizer") self.setObjectName("fileorganizerUI")