-
Notifications
You must be signed in to change notification settings - Fork 210
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #276 from SpreadSheets600/main
Added File Sorter UI Issue #252
- Loading branch information
Showing
102 changed files
with
648 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
import os | ||
import csv | ||
import shutil | ||
|
||
import tkinter as tk | ||
|
||
from tkinter import * | ||
from tkinter import ttk | ||
from tkinter.ttk import * | ||
|
||
from datetime import datetime | ||
|
||
import tkinter.font as tkFont | ||
|
||
from tkinter import filedialog | ||
|
||
files_organized = False | ||
|
||
moved_files = [] | ||
|
||
def log_file_movement(log_file, time, source_file, target_folder): | ||
with open(log_file, mode='a', newline='') as file: | ||
log_writer = csv.writer(file) | ||
log_writer.writerow([time, source_file, target_folder]) | ||
|
||
def undo(): | ||
for (source, target) in moved_files: | ||
shutil.move(target, source) | ||
print_text(f"Undo: Moved {target} back to {source}") | ||
print_text("Undo") | ||
global files_organized | ||
|
||
files_organized = False | ||
undo_button.config(state=tk.DISABLED) | ||
|
||
def organize_files(): | ||
|
||
directory = directory_entry.get() | ||
file_extensions = extensions_entry.get().split(',') | ||
file_extensions = [ext.strip() for ext in file_extensions if ext] | ||
|
||
log_file = log_entry.get() | ||
|
||
if not os.path.exists(directory): | ||
print_text("Directory does not exist.") | ||
return | ||
|
||
try: | ||
if log_file: | ||
log_file_exists = os.path.exists(log_file) | ||
with open(log_file, mode='a', newline='') as file: | ||
log_writer = csv.writer(file) | ||
if not log_file_exists: | ||
log_writer.writerow(["Time", "Source File", "Target Folder"]) | ||
|
||
for root, dirs, files in os.walk(directory): | ||
for file in files: | ||
file_extension = os.path.splitext(file)[1] | ||
if not file_extensions or file_extension in file_extensions: | ||
target_subdirectory = os.path.join(directory, file_extension[1:].upper() + " Files") | ||
|
||
if not os.path.exists(target_subdirectory): | ||
os.mkdir(target_subdirectory) | ||
|
||
source_path = os.path.join(root, file) | ||
target_path = os.path.join(target_subdirectory, file) | ||
|
||
try: | ||
shutil.move(source_path, target_path) | ||
print_text(f"Moved {file} to {target_subdirectory}") | ||
|
||
if log_file: | ||
log_file_movement(log_file, datetime.now().strftime("%Y-%m-%d %H:%M:%S"), file, target_subdirectory) | ||
|
||
moved_files.append((source_path, target_path)) | ||
except Exception as e: | ||
print_text(f"Error moving {file}: {str(e)}") | ||
|
||
print_text("File organization completed") | ||
|
||
global files_organized | ||
files_organized = True | ||
|
||
if files_organized: | ||
undo_button.config(state=tk.NORMAL) | ||
|
||
except KeyboardInterrupt: | ||
print_text("\nFile organization interrupted. Starting the undo process...") | ||
undo() | ||
print_text("Undo completed. No files are moved.") | ||
return | ||
|
||
def change_theme(): | ||
|
||
global window | ||
|
||
if window.tk.call("ttk::style", "theme", "use") == "azure-dark": | ||
|
||
window.tk.call("set_theme", "light") | ||
|
||
else: | ||
|
||
window.tk.call("set_theme", "dark") | ||
|
||
# Tkinter GUI Code | ||
|
||
window = tk.Tk() | ||
window.title("File Organizer") | ||
|
||
height = 500 | ||
width = 600 | ||
|
||
window.geometry(f"{width}x{height}") | ||
|
||
font = "Consolas" | ||
|
||
window.resizable(width=True, height=True) | ||
|
||
window.tk.call("source", r"Theme\azure.tcl") | ||
window.tk.call("set_theme", "light") | ||
|
||
text = tk.Text(window) | ||
|
||
roots_frame = tk.LabelFrame(window, labelanchor="n", bg="white") | ||
roots_frame.place(x= 25,y=300, width=550, height= 150) | ||
|
||
def print_text(text): | ||
|
||
global roots_frame | ||
|
||
Label(roots_frame, text=text,font=('Consolas 10'), fg="black").pack() | ||
|
||
|
||
app_label = ttk.Label(window, text = "File Sorter", font= "Consolas 30") | ||
app_label.place(y=10, x=180) | ||
|
||
directory_label = ttk.Label(window, text="Directory Path", font=font) | ||
directory_label.place(y=85, x=10) | ||
|
||
directory_entry = ttk.Entry(window) | ||
directory_entry.place(y=80, x=200, width=200) | ||
|
||
browse_button = ttk.Button(window, text="Browse", command=lambda: [directory_entry.insert(0, filedialog.askdirectory())]) | ||
browse_button.place(y=80, x=450) | ||
|
||
extensions_label = ttk.Label(window, text="File Extensions", font = font) | ||
extensions_label.place(y=130, x=10) | ||
|
||
extensions_entry = ttk.Entry(window) | ||
extensions_entry.place(y=125, x=200, width=200) | ||
|
||
log_label = ttk.Label(window, text="Log File", font = font) | ||
log_label.place(y=180, x=10) | ||
|
||
log_entry = ttk.Entry(window) | ||
log_entry.place(y=175, x=200, width=200) | ||
|
||
organize_button = ttk.Button(window, text="Organize Files", command=organize_files) | ||
organize_button.place(y=220, x=200, width=110) | ||
|
||
undo_button = ttk.Button(window, text="Undo", command=undo, state=tk.DISABLED) | ||
undo_button.place(y=220, x=330, width=70) | ||
|
||
button = ttk.Button(window, text="Theme", command=change_theme, compound="left" ) | ||
button.place(y = 220, x = 450) | ||
|
||
window.mainloop() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# File Organizer | ||
|
||
File Organizer is a simple Python script and GUI application for organizing files in a directory based on their file extensions. It allows you to specify a directory, file extensions, and an optional log file for tracking file movements. | ||
|
||
---- | ||
|
||
![image](https://github.com/SpreadSheets600/File-Sorter/assets/115402296/5907a1d1-548f-48da-81d7-1ec352a9c57b) | ||
|
||
---- | ||
|
||
## Features | ||
|
||
- Organize files in a directory based on their file extensions. | ||
- Log file movements with timestamps. | ||
- Undo file organization. | ||
- Choose between light and dark themes. | ||
|
||
## Getting Started | ||
|
||
These instructions will help you get a copy of the project up and running on your local machine for development and testing purposes. | ||
|
||
### Prerequisites | ||
|
||
- Python 3.x | ||
- Tkinter (usually included with Python, no separate installation required) | ||
|
||
### Installation | ||
|
||
1. Clone the repository: | ||
|
||
```bash | ||
git clone https://github.com/yourusername/file-organizer.git | ||
``` | ||
|
||
2. Change into the project directory: | ||
|
||
```bash | ||
cd file-organizer | ||
``` | ||
|
||
3. Ensure the Azure-ttk-theme folder is in the correct location, as it is required for the application's theme. | ||
Without the theme, the application will not work. (Make changes to line number 117 And 120) | ||
|
||
```python | ||
window.iconbitmap(r"") | ||
window.resizable(width=True, height=True) # App Icon Location | ||
|
||
window.tk.call("source", r"\Theme\azure.tcl") | ||
window.tk.call("set_theme", "light") # `azure.tcl` Location From Theme Folder | ||
``` | ||
|
||
4. Run the application: | ||
|
||
```bash | ||
python App.py | ||
``` | ||
|
||
## Usage | ||
|
||
1. Launch the application by running 'App.py`. | ||
|
||
2. Provide the following information in the GUI: | ||
- Directory Path: The directory you want to organize. | ||
- File Extensions: Comma-separated file extensions (e.g., `pdf, txt, docx`). | ||
- Log File (Optional): Path to a log file for tracking file movements. | ||
|
||
3. Click the "Organize Files" button to start the organization process. | ||
|
||
4. You can undo the file organization by clicking the "Undo" button. | ||
|
||
5. Change the theme between light and dark with the "Theme" button. | ||
|
||
|
||
## Contributing | ||
|
||
If you would like to contribute to this project, you can follow these steps: | ||
|
||
1. Fork the repository. | ||
2. Create a new branch for your feature: `git checkout -b feature-name` | ||
3. Make your changes and commit them: `git commit -m 'Add some feature'` | ||
4. Push to the branch: `git push origin feature-name` | ||
5. Create a pull request. | ||
|
||
|
||
## Acknowledgments | ||
|
||
- Thanks to the Python community for creating powerful libraries and tools. | ||
- Special thanks to contributors. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# Copyright © 2021 rdbende <rdbende@gmail.com> | ||
|
||
source [file join [file dirname [info script]] theme light.tcl] | ||
source [file join [file dirname [info script]] theme dark.tcl] | ||
|
||
option add *tearOff 0 | ||
|
||
proc set_theme {mode} { | ||
if {$mode == "dark"} { | ||
ttk::style theme use "azure-dark" | ||
|
||
array set colors { | ||
-fg "#ffffff" | ||
-bg "#333333" | ||
-disabledfg "#ffffff" | ||
-disabledbg "#737373" | ||
-selectfg "#ffffff" | ||
-selectbg "#007fff" | ||
} | ||
|
||
ttk::style configure . \ | ||
-background $colors(-bg) \ | ||
-foreground $colors(-fg) \ | ||
-troughcolor $colors(-bg) \ | ||
-focuscolor $colors(-selectbg) \ | ||
-selectbackground $colors(-selectbg) \ | ||
-selectforeground $colors(-selectfg) \ | ||
-insertcolor $colors(-fg) \ | ||
-insertwidth 1 \ | ||
-fieldbackground $colors(-selectbg) \ | ||
-font {"Segoe Ui" 10} \ | ||
-borderwidth 1 \ | ||
-relief flat | ||
|
||
tk_setPalette background [ttk::style lookup . -background] \ | ||
foreground [ttk::style lookup . -foreground] \ | ||
highlightColor [ttk::style lookup . -focuscolor] \ | ||
selectBackground [ttk::style lookup . -selectbackground] \ | ||
selectForeground [ttk::style lookup . -selectforeground] \ | ||
activeBackground [ttk::style lookup . -selectbackground] \ | ||
activeForeground [ttk::style lookup . -selectforeground] | ||
|
||
ttk::style map . -foreground [list disabled $colors(-disabledfg)] | ||
|
||
option add *font [ttk::style lookup . -font] | ||
option add *Menu.selectcolor $colors(-fg) | ||
|
||
} elseif {$mode == "light"} { | ||
ttk::style theme use "azure-light" | ||
|
||
array set colors { | ||
-fg "#000000" | ||
-bg "#ffffff" | ||
-disabledfg "#737373" | ||
-disabledbg "#ffffff" | ||
-selectfg "#ffffff" | ||
-selectbg "#007fff" | ||
} | ||
|
||
ttk::style configure . \ | ||
-background $colors(-bg) \ | ||
-foreground $colors(-fg) \ | ||
-troughcolor $colors(-bg) \ | ||
-focuscolor $colors(-selectbg) \ | ||
-selectbackground $colors(-selectbg) \ | ||
-selectforeground $colors(-selectfg) \ | ||
-insertcolor $colors(-fg) \ | ||
-insertwidth 1 \ | ||
-fieldbackground $colors(-selectbg) \ | ||
-font {"Segoe Ui" 10} \ | ||
-borderwidth 1 \ | ||
-relief flat | ||
|
||
tk_setPalette background [ttk::style lookup . -background] \ | ||
foreground [ttk::style lookup . -foreground] \ | ||
highlightColor [ttk::style lookup . -focuscolor] \ | ||
selectBackground [ttk::style lookup . -selectbackground] \ | ||
selectForeground [ttk::style lookup . -selectforeground] \ | ||
activeBackground [ttk::style lookup . -selectbackground] \ | ||
activeForeground [ttk::style lookup . -selectforeground] | ||
|
||
ttk::style map . -foreground [list disabled $colors(-disabledfg)] | ||
|
||
option add *font [ttk::style lookup . -font] | ||
option add *Menu.selectcolor $colors(-fg) | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.