initial push
This commit is contained in:
parent
f1918a3b53
commit
16745002e8
18
README.md
18
README.md
|
@ -1,3 +1,19 @@
|
||||||
# BulkR
|
# BulkR
|
||||||
|
|
||||||
Bulk renaming utility written with python and Gtk.
|
Bulk renaming utility written with python and Gtk.
|
||||||
|
|
||||||
|
# Notes
|
||||||
|
|
||||||
|
|
||||||
|
<h6>Install Setup</h6>
|
||||||
|
```
|
||||||
|
sudo apt-get install python3.8 python3-setproctitle python3-gi
|
||||||
|
```
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
<ul>
|
||||||
|
<li>Add logic for stub instances.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
# Images
|
||||||
|
![1 BulkR clean slate. ](images/pic1.png)
|
||||||
|
![2 BulkR loaded dir and some actions. ](images/pic2.png)
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
|
@ -0,0 +1,29 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
|
||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from __builtins__ import Builtins
|
||||||
|
from controller import Controller
|
||||||
|
|
||||||
|
|
||||||
|
class Window(Gtk.Window, Builtins):
|
||||||
|
"""docstring for Main."""
|
||||||
|
|
||||||
|
def __init__(self, args):
|
||||||
|
super(Window, self).__init__()
|
||||||
|
|
||||||
|
self.add(Controller(args))
|
||||||
|
self.connect("delete-event", Gtk.main_quit)
|
||||||
|
self.set_default_size(800, 600)
|
||||||
|
self.set_title(f"{app_name}")
|
||||||
|
self.set_icon_from_file("/usr/share/bulkr/bulkr.png")
|
||||||
|
self.set_gravity(5) # 5 = CENTER
|
||||||
|
self.set_position(3) # 4 = CENTER_ALWAYS
|
||||||
|
self.show_all()
|
|
@ -0,0 +1,94 @@
|
||||||
|
# Python imports
|
||||||
|
import builtins, os
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
class Builtins:
|
||||||
|
""" Create an pub/sub systems. """
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.USER_HOME = path.expanduser('~')
|
||||||
|
self.block_from_update = False
|
||||||
|
self.block_to_update = False
|
||||||
|
self.active_path = None
|
||||||
|
self.from_changes = []
|
||||||
|
self.to_changes = []
|
||||||
|
|
||||||
|
# NOTE: The format used is list of [type, target, (data,)] Where:
|
||||||
|
# type is useful context for control flow,
|
||||||
|
# target is the method to call,
|
||||||
|
# data is the method parameters to give
|
||||||
|
# Where data may be any kind of data
|
||||||
|
self._gui_events = []
|
||||||
|
self._module_events = []
|
||||||
|
|
||||||
|
|
||||||
|
# Makeshift fake "events" type system FIFO
|
||||||
|
def _pop_gui_event(self):
|
||||||
|
if len(self._gui_events) > 0:
|
||||||
|
return self._gui_events.pop(0)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _pop_module_event(self):
|
||||||
|
if len(self._module_events) > 0:
|
||||||
|
return self._module_events.pop(0)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def set_active_path(self, _file):
|
||||||
|
if os.path.isdir(_file) :
|
||||||
|
self.from_changes.clear()
|
||||||
|
self.active_path = _file
|
||||||
|
for f in os.listdir(_file):
|
||||||
|
self.from_changes.append(f)
|
||||||
|
|
||||||
|
self.to_changes = self.from_changes
|
||||||
|
event_system.push_gui_event(["update-from", None, ()])
|
||||||
|
event_system.push_gui_event(["update-to", None, ()])
|
||||||
|
|
||||||
|
def reset_to_view(self):
|
||||||
|
self.to_changes = self.from_changes
|
||||||
|
event_system.push_gui_event(["update-to", None, ()])
|
||||||
|
|
||||||
|
def reset_from_view(self):
|
||||||
|
self.set_active_path(self.active_path)
|
||||||
|
|
||||||
|
def push_gui_event(self, event):
|
||||||
|
if len(event) == 3:
|
||||||
|
self._gui_events.append(event)
|
||||||
|
return None
|
||||||
|
|
||||||
|
raise Exception("Invald event format! Please do: [type, target, (data,)]")
|
||||||
|
|
||||||
|
def push_module_event(self, event):
|
||||||
|
if len(event) == 3:
|
||||||
|
self._module_events.append(event)
|
||||||
|
return None
|
||||||
|
|
||||||
|
raise Exception("Invald event format! Please do: [type, target, (data,)]")
|
||||||
|
|
||||||
|
def read_gui_event(self):
|
||||||
|
return self._gui_events[0]
|
||||||
|
|
||||||
|
def read_module_event(self):
|
||||||
|
return self._module_events[0]
|
||||||
|
|
||||||
|
def consume_gui_event(self):
|
||||||
|
return self._pop_gui_event()
|
||||||
|
|
||||||
|
def consume_module_event(self):
|
||||||
|
return self._pop_module_event()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: Just reminding myself we can add to builtins two different ways...
|
||||||
|
# __builtins__.update({"event_system": Builtins()})
|
||||||
|
builtins.app_name = "Bulk-Renamer"
|
||||||
|
builtins.event_system = Builtins()
|
||||||
|
builtins.event_sleep_time = 0.1
|
||||||
|
builtins.debug = False
|
||||||
|
builtins.trace_debug = False
|
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
|
||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from __builtins__ import Builtins
|
||||||
|
from Window import Window
|
||||||
|
from controller import Controller
|
||||||
|
|
||||||
|
|
||||||
|
class Main(Window):
|
||||||
|
"""docstring for Main."""
|
||||||
|
|
||||||
|
def __init__(self, args):
|
||||||
|
super(Main, self).__init__(args)
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
|
||||||
|
# Python imports
|
||||||
|
import sys, argparse
|
||||||
|
from setproctitle import setproctitle
|
||||||
|
|
||||||
|
# Gtk imports
|
||||||
|
import gi, faulthandler, signal
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import GLib
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from __init__ import Main
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
setproctitle('Bulk-Renamer')
|
||||||
|
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, Gtk.main_quit)
|
||||||
|
faulthandler.enable() # For better debug info
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
# Add long and short arguments
|
||||||
|
parser.add_argument("--file", "-f", default="default", help="JUST SOME FILE ARG.")
|
||||||
|
|
||||||
|
# Read arguments (If any...)
|
||||||
|
args = parser.parse_args()
|
||||||
|
main = Main(args)
|
||||||
|
Gtk.main()
|
||||||
|
except Exception as e:
|
||||||
|
print( repr(e) )
|
|
@ -0,0 +1,57 @@
|
||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from mixins import CommonActionsMixin
|
||||||
|
|
||||||
|
|
||||||
|
class ChangeView(Gtk.Box, CommonActionsMixin):
|
||||||
|
def __init__(self):
|
||||||
|
super(ChangeView, self).__init__()
|
||||||
|
|
||||||
|
from_container = Gtk.Box()
|
||||||
|
to_container = Gtk.Box()
|
||||||
|
from_scroll_vw, \
|
||||||
|
self.from_store = self._create_treeview_widget(title="From:")
|
||||||
|
to_scroll_vw, \
|
||||||
|
self.to_store = self._create_treeview_widget(title="To:")
|
||||||
|
|
||||||
|
from_container.add(from_scroll_vw)
|
||||||
|
to_container.add(to_scroll_vw)
|
||||||
|
|
||||||
|
from_container.set_orientation(1)
|
||||||
|
to_container.set_orientation(1)
|
||||||
|
|
||||||
|
self.set_spacing(20)
|
||||||
|
self.set_border_width(2)
|
||||||
|
self.set_homogeneous(True)
|
||||||
|
self.add(from_container)
|
||||||
|
self.add(to_container)
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
|
||||||
|
def update_from_list(self):
|
||||||
|
if event_system.block_from_update:
|
||||||
|
return
|
||||||
|
|
||||||
|
print("Updating From List...")
|
||||||
|
if self.from_store:
|
||||||
|
self.from_store.clear()
|
||||||
|
|
||||||
|
for i, change in enumerate(event_system.from_changes):
|
||||||
|
self.from_store.insert(i, [change])
|
||||||
|
|
||||||
|
def update_to_list(self):
|
||||||
|
if event_system.block_to_update:
|
||||||
|
return
|
||||||
|
|
||||||
|
print("Updating To List...")
|
||||||
|
if self.to_store:
|
||||||
|
self.to_store.clear()
|
||||||
|
|
||||||
|
for i, change in enumerate(event_system.to_changes):
|
||||||
|
self.to_store.insert(i, [change])
|
|
@ -0,0 +1,167 @@
|
||||||
|
# Python imports
|
||||||
|
import os, sys, threading, time
|
||||||
|
|
||||||
|
# lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import GLib
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from mixins import CommonActionsMixin
|
||||||
|
from . import ChangeView
|
||||||
|
from .widgets import *
|
||||||
|
|
||||||
|
|
||||||
|
def threaded(fn):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
class Controller(Gtk.Box, CommonActionsMixin):
|
||||||
|
def __init__(self, args):
|
||||||
|
super(Controller, self).__init__()
|
||||||
|
|
||||||
|
# Add header
|
||||||
|
self.change_view = ChangeView()
|
||||||
|
action_bar = Gtk.Box()
|
||||||
|
file_choser = Gtk.FileChooserButton(title="Directory Chooser", action=2) # 2 = SELECT_FOLDER
|
||||||
|
file_filter = Gtk.FileFilter()
|
||||||
|
file_choser.show()
|
||||||
|
file_choser.set_filename(event_system.USER_HOME)
|
||||||
|
file_filter.add_mime_type("inode/directory")
|
||||||
|
file_choser.add_filter(file_filter)
|
||||||
|
|
||||||
|
label = Gtk.Label(label="Bulk Action Type: ")
|
||||||
|
data = ["Insert", "Replace", "Remove", "Remove From / To", "Case"]
|
||||||
|
self.store, self.combo_box = self._create_combobox_widget(data)
|
||||||
|
|
||||||
|
add_button = Gtk.Button(label="Add Action")
|
||||||
|
test_all_button = Gtk.Button(label="Preview")
|
||||||
|
reset_button = Gtk.Button(label="Reset")
|
||||||
|
run_button = Gtk.Button(label="Run")
|
||||||
|
|
||||||
|
action_bar.add(label)
|
||||||
|
action_bar.add(self.combo_box)
|
||||||
|
action_bar.add(add_button)
|
||||||
|
action_bar.add(test_all_button)
|
||||||
|
action_bar.add(reset_button)
|
||||||
|
action_bar.set_homogeneous(True)
|
||||||
|
action_bar.set_spacing(20)
|
||||||
|
action_bar.show_all()
|
||||||
|
|
||||||
|
run_button.connect("clicked", self._run_all)
|
||||||
|
add_button.connect("clicked", self._add_action)
|
||||||
|
test_all_button.connect("clicked", self._test_all)
|
||||||
|
reset_button.connect("clicked", self._reset_to_view)
|
||||||
|
file_choser.connect("file-set", self.update_dir_path)
|
||||||
|
|
||||||
|
actions_scroll_label = Gtk.Label(label="Actions:")
|
||||||
|
actions_scroll_label.set_xalign(-20)
|
||||||
|
actions_scroll_view, self.actions_list_view = self._create_listBox_widget()
|
||||||
|
|
||||||
|
self.set_spacing(20)
|
||||||
|
self.set_margin_top(5)
|
||||||
|
self.set_margin_bottom(10)
|
||||||
|
self.set_margin_left(15)
|
||||||
|
self.set_margin_right(15)
|
||||||
|
self.set_orientation(1)
|
||||||
|
|
||||||
|
self.add(file_choser)
|
||||||
|
self.add(action_bar)
|
||||||
|
self.add(self.change_view)
|
||||||
|
self.add(actions_scroll_label)
|
||||||
|
self.add(actions_scroll_view)
|
||||||
|
self.add(run_button)
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
self.gui_event_observer()
|
||||||
|
self.action_collection = []
|
||||||
|
|
||||||
|
|
||||||
|
@threaded
|
||||||
|
def gui_event_observer(self):
|
||||||
|
while True:
|
||||||
|
time.sleep(event_sleep_time)
|
||||||
|
event = event_system.consume_gui_event()
|
||||||
|
if event:
|
||||||
|
try:
|
||||||
|
type, target, data = event
|
||||||
|
if type:
|
||||||
|
method = getattr(self.__class__, "_handle_gui_event")
|
||||||
|
GLib.idle_add(method, *(self, type, target, data))
|
||||||
|
else:
|
||||||
|
method = getattr(self.__class__, target)
|
||||||
|
GLib.idle_add(method, *(self, *data,))
|
||||||
|
except Exception as e:
|
||||||
|
print(repr(e))
|
||||||
|
|
||||||
|
|
||||||
|
def update_dir_path(self, widget):
|
||||||
|
path = widget.get_filename()
|
||||||
|
event_system.set_active_path(path)
|
||||||
|
|
||||||
|
def _handle_gui_event(self, type, target, parameters):
|
||||||
|
if type == "update-from":
|
||||||
|
self.change_view.update_from_list()
|
||||||
|
return
|
||||||
|
|
||||||
|
if type == "update-to":
|
||||||
|
self.change_view.update_to_list()
|
||||||
|
return
|
||||||
|
|
||||||
|
for action in self.action_collection:
|
||||||
|
if action == target:
|
||||||
|
if type == "delete":
|
||||||
|
self.action_collection.remove(target)
|
||||||
|
target.delete()
|
||||||
|
if type == "run":
|
||||||
|
target.run()
|
||||||
|
|
||||||
|
|
||||||
|
def _add_action(self, widget):
|
||||||
|
itr = self.combo_box.get_active_iter()
|
||||||
|
text = self.store.get(itr, 0)[0]
|
||||||
|
widget = self._str_to_class( self._clean_text(text) )
|
||||||
|
|
||||||
|
print(f"Adding: {self._clean_text(text)}")
|
||||||
|
self.actions_list_view.add(widget)
|
||||||
|
self.action_collection.append(widget)
|
||||||
|
|
||||||
|
def _test_all(self, widget=None):
|
||||||
|
event_system.block_to_update = True
|
||||||
|
event_system.reset_to_view()
|
||||||
|
for action in self.action_collection:
|
||||||
|
action.run()
|
||||||
|
|
||||||
|
event_system.block_to_update = False
|
||||||
|
event_system.push_gui_event(["update-to", self, ()])
|
||||||
|
|
||||||
|
def _reset_to_view(self, widget):
|
||||||
|
event_system.reset_to_view()
|
||||||
|
|
||||||
|
def _run_all(self, widget):
|
||||||
|
if not event_system.active_path:
|
||||||
|
print("No active path set. Returning...")
|
||||||
|
return
|
||||||
|
|
||||||
|
self._test_all()
|
||||||
|
dir = event_system.active_path
|
||||||
|
for i, file in enumerate(event_system.from_changes):
|
||||||
|
fPath = f"{dir}/{file}"
|
||||||
|
tPath = f"{dir}/{event_system.to_changes[i]}"
|
||||||
|
if fPath != tPath:
|
||||||
|
try:
|
||||||
|
os.rename(fPath, tPath)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Cant Move: {fPath}\nTo File: {tPath}")
|
||||||
|
|
||||||
|
event_system.reset_from_view()
|
||||||
|
|
||||||
|
def _clean_text(self, text):
|
||||||
|
return text.replace(" ", "") \
|
||||||
|
.replace("/", "")
|
||||||
|
|
||||||
|
def _str_to_class(self, class_name):
|
||||||
|
return getattr(sys.modules[__name__], class_name)()
|
|
@ -0,0 +1,2 @@
|
||||||
|
from .ChangeView import ChangeView
|
||||||
|
from .Controller import Controller
|
|
@ -0,0 +1,47 @@
|
||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from mixins import CommonActionsMixin
|
||||||
|
|
||||||
|
|
||||||
|
class Case(Gtk.Box, CommonActionsMixin):
|
||||||
|
def __init__(self):
|
||||||
|
super(Case, self).__init__()
|
||||||
|
|
||||||
|
label = Gtk.Label(label="Case")
|
||||||
|
data = ["Title Case", "UPPER", "lower", "InVert CaSe --> iNvERT cAsE"]
|
||||||
|
self.store, self.combo_box = self._create_combobox_widget(data)
|
||||||
|
|
||||||
|
label.set_hexpand(True)
|
||||||
|
|
||||||
|
self.add_widgets([label, self.combo_box])
|
||||||
|
self.set_spacing(20)
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
new_collection = []
|
||||||
|
itr = self.combo_box.get_active_iter()
|
||||||
|
type = self.store.get(itr, 0)[0]
|
||||||
|
|
||||||
|
print(f"Changing Case...")
|
||||||
|
if type == "Title Case":
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
new_collection.append(name.title())
|
||||||
|
if type == "UPPER":
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
new_collection.append(name.upper())
|
||||||
|
if type == "lower":
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
new_collection.append(name.lower())
|
||||||
|
if type == "InVert CaSe --> iNvERT cAsE":
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
new_collection.append(name.swapcase())
|
||||||
|
|
||||||
|
event_system.to_changes = new_collection
|
||||||
|
event_system.push_gui_event(["update-to", self, ()])
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Python imports
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from mixins import CommonActionsMixin
|
||||||
|
|
||||||
|
|
||||||
|
class Insert(Gtk.Box, CommonActionsMixin):
|
||||||
|
def __init__(self):
|
||||||
|
super(Insert, self).__init__()
|
||||||
|
|
||||||
|
label = Gtk.Label(label="Insert: ")
|
||||||
|
self.insert_entry = Gtk.Entry()
|
||||||
|
self.insert_entry.set_hexpand(True)
|
||||||
|
self.insert_entry.set_placeholder_text("Insert...")
|
||||||
|
|
||||||
|
data = ["Start", "End", "Position"]
|
||||||
|
self.store, self.combo_box = self._create_combobox_widget(data)
|
||||||
|
|
||||||
|
self.spin_button = self._create_spinbutton_widget()
|
||||||
|
|
||||||
|
self.add_widgets([label, self.insert_entry, self.combo_box, self.spin_button])
|
||||||
|
self.set_spacing(20)
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
new_collection = []
|
||||||
|
insert_str = self.insert_entry.get_text()
|
||||||
|
itr = self.combo_box.get_active_iter()
|
||||||
|
type = self.store.get(itr, 0)[0]
|
||||||
|
|
||||||
|
print(f"Inserting...")
|
||||||
|
if type == "Start":
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
new_collection.append(f"{insert_str}{name}")
|
||||||
|
if type == "End":
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
base, file_extension = self.get_file_parts()
|
||||||
|
new_collection.append(f"{base}{insert_str}{file_extension}")
|
||||||
|
if type == "Position":
|
||||||
|
position = self.spin_button.get_value_as_int()
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
name = f"{name[:position]}{insert_str}{name[position:]}"
|
||||||
|
new_collection.append(f"{name}")
|
||||||
|
|
||||||
|
event_system.to_changes = new_collection
|
||||||
|
event_system.push_gui_event(["update-to", self, ()])
|
||||||
|
|
||||||
|
|
||||||
|
def _combo_box_changed(self, widget, eve=None):
|
||||||
|
itr = widget.get_active_iter()
|
||||||
|
type = self.store.get(itr, 0)[0]
|
||||||
|
|
||||||
|
if type == "Position":
|
||||||
|
self.spin_button.set_sensitive(True)
|
||||||
|
else:
|
||||||
|
self.spin_button.set_sensitive(False)
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from mixins import CommonActionsMixin
|
||||||
|
|
||||||
|
|
||||||
|
class Remove(Gtk.Box, CommonActionsMixin):
|
||||||
|
def __init__(self):
|
||||||
|
super(Remove, self).__init__()
|
||||||
|
|
||||||
|
label = Gtk.Label(label="Remove: ")
|
||||||
|
self.entry_from = Gtk.Entry()
|
||||||
|
|
||||||
|
data = ["All", "Word Start", "Word End", "First Instance", "Last Instance", "RegEx"]
|
||||||
|
self.store, self.combo_box = self._create_combobox_widget(data)
|
||||||
|
|
||||||
|
self.entry_from.set_hexpand(True)
|
||||||
|
self.entry_from.set_placeholder_text("Remove...")
|
||||||
|
|
||||||
|
self.add_widgets([label, self.entry_from, self.combo_box])
|
||||||
|
self.set_spacing(20)
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
from_str = self.entry_from.get_text()
|
||||||
|
if from_str:
|
||||||
|
new_collection = []
|
||||||
|
itr = self.combo_box.get_active_iter()
|
||||||
|
type = self.store.get(itr, 0)[0]
|
||||||
|
print(f"To Remove: {from_str}")
|
||||||
|
|
||||||
|
if type == "All":
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
new_collection.append(name.replace(from_str, ''))
|
||||||
|
if type == "Word Start":
|
||||||
|
print("Stub...")
|
||||||
|
if type == "Word End":
|
||||||
|
print("Stub...")
|
||||||
|
if type == "First Instance":
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
new_collection.append( name.replace(from_str, "", 1) )
|
||||||
|
if type == "Last Instance":
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
new_collection.append( self._replace_last(name, from_str, "") )
|
||||||
|
if type == "RegEx":
|
||||||
|
print("Stub...")
|
||||||
|
|
||||||
|
event_system.to_changes = new_collection
|
||||||
|
event_system.push_gui_event(["update-to", self, ()])
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from mixins import CommonActionsMixin
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveFromTo(Gtk.Box, CommonActionsMixin):
|
||||||
|
def __init__(self):
|
||||||
|
super(RemoveFromTo, self).__init__()
|
||||||
|
|
||||||
|
label = Gtk.Label(label="Remove From / To: ")
|
||||||
|
self.entry_from = Gtk.Entry()
|
||||||
|
self.entry_to = Gtk.Entry()
|
||||||
|
|
||||||
|
self.entry_from.set_hexpand(True)
|
||||||
|
self.entry_to.set_hexpand(True)
|
||||||
|
self.entry_from.set_placeholder_text("From...")
|
||||||
|
self.entry_to.set_placeholder_text("To...")
|
||||||
|
|
||||||
|
self.add_widgets([label, self.entry_from, self.entry_to])
|
||||||
|
|
||||||
|
self.set_spacing(20)
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
fsub = self.entry_from.get_text()
|
||||||
|
tsub = self.entry_to.get_text()
|
||||||
|
|
||||||
|
if fsub and tsub:
|
||||||
|
new_collection = []
|
||||||
|
print(f"From: {fsub}\nTo: {tsub}")
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
startIndex = name.index(fsub) + 1
|
||||||
|
endIndex = name.index(tsub)
|
||||||
|
toRemove = name[startIndex:endIndex]
|
||||||
|
new_collection.append(name.replace(toRemove, ''))
|
||||||
|
|
||||||
|
event_system.to_changes = new_collection
|
||||||
|
event_system.push_gui_event(["update-to", self, ()])
|
|
@ -0,0 +1,41 @@
|
||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from mixins import CommonActionsMixin
|
||||||
|
|
||||||
|
|
||||||
|
class Replace(Gtk.Box, CommonActionsMixin):
|
||||||
|
def __init__(self):
|
||||||
|
super(Replace, self).__init__()
|
||||||
|
|
||||||
|
label = Gtk.Label(label="Replace With: ")
|
||||||
|
self.entry_from = Gtk.Entry()
|
||||||
|
self.entry_to = Gtk.Entry()
|
||||||
|
|
||||||
|
self.entry_from.set_hexpand(True)
|
||||||
|
self.entry_to.set_hexpand(True)
|
||||||
|
self.entry_from.set_placeholder_text("From...")
|
||||||
|
self.entry_to.set_placeholder_text("To...")
|
||||||
|
|
||||||
|
self.add_widgets([label, self.entry_from, self.entry_to])
|
||||||
|
|
||||||
|
self.set_spacing(20)
|
||||||
|
self.show_all()
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
fsub = self.entry_from.get_text()
|
||||||
|
tsub = self.entry_to.get_text()
|
||||||
|
if fsub and tsub:
|
||||||
|
new_collection = []
|
||||||
|
print(f"From: {fsub}\nTo: {tsub}")
|
||||||
|
for name in event_system.to_changes:
|
||||||
|
new_collection.append(name.replace(fsub, tsub))
|
||||||
|
|
||||||
|
event_system.to_changes = new_collection
|
||||||
|
event_system.push_gui_event(["update-to", self, ()])
|
|
@ -0,0 +1,5 @@
|
||||||
|
from .Insert import Insert
|
||||||
|
from .Replace import Replace
|
||||||
|
from .Remove import Remove
|
||||||
|
from .RemoveFromTo import RemoveFromTo
|
||||||
|
from .Case import Case
|
|
@ -0,0 +1,124 @@
|
||||||
|
# Python imports
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
# lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
class CommonActionsMixin:
|
||||||
|
def add_widgets(self, widgets):
|
||||||
|
for widget in widgets:
|
||||||
|
self.add(widget)
|
||||||
|
|
||||||
|
remove_button = Gtk.Button(label="X")
|
||||||
|
test_button = Gtk.Button(label="Test")
|
||||||
|
|
||||||
|
remove_button.connect("clicked", self._remove_self)
|
||||||
|
test_button.connect("clicked", self._do_run)
|
||||||
|
|
||||||
|
remove_button.set_size_request(120, 32)
|
||||||
|
test_button.set_size_request(120, 32)
|
||||||
|
|
||||||
|
self.add(test_button)
|
||||||
|
self.add(remove_button)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
self.get_parent().destroy()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_parts(self, name):
|
||||||
|
file_extension = pathlib.Path(name).suffix
|
||||||
|
base = name.split(file_extension)[0]
|
||||||
|
return base, file_extension
|
||||||
|
|
||||||
|
def _has_method(self, obj, name):
|
||||||
|
''' Checks if a given method exists. '''
|
||||||
|
return callable(getattr(obj, name, None))
|
||||||
|
|
||||||
|
def _replace_last(self, string, find, replace):
|
||||||
|
reversed = string[::-1]
|
||||||
|
replaced = reversed.replace(find[::-1], replace[::-1], 1)
|
||||||
|
return replaced[::-1]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_self(self, widget):
|
||||||
|
event_system.push_gui_event(["delete", self, ()])
|
||||||
|
|
||||||
|
def _do_run(self, widget):
|
||||||
|
event_system.push_gui_event(["run", self, ()])
|
||||||
|
|
||||||
|
|
||||||
|
def _create_spinbutton_widget(self):
|
||||||
|
spin_button = Gtk.SpinButton()
|
||||||
|
spin_button.set_numeric(True)
|
||||||
|
spin_button.set_wrap(True)
|
||||||
|
spin_button.set_digits(0)
|
||||||
|
spin_button.set_increments(1.0, 1.0)
|
||||||
|
spin_button.set_range(1, 1000000)
|
||||||
|
spin_button.set_sensitive(False)
|
||||||
|
|
||||||
|
return spin_button
|
||||||
|
|
||||||
|
def _create_combobox_widget(self, data):
|
||||||
|
cell = Gtk.CellRendererText()
|
||||||
|
store = Gtk.ListStore(str)
|
||||||
|
|
||||||
|
for row in data:
|
||||||
|
store.append([row])
|
||||||
|
|
||||||
|
combo_box = Gtk.ComboBox()
|
||||||
|
combo_box.set_model(store)
|
||||||
|
combo_box.pack_start(cell, True)
|
||||||
|
combo_box.add_attribute(cell, 'text', 0)
|
||||||
|
combo_box.set_active(0)
|
||||||
|
|
||||||
|
if self._has_method(self, "_combo_box_changed"):
|
||||||
|
combo_box.connect("changed", self._combo_box_changed)
|
||||||
|
|
||||||
|
return store, combo_box
|
||||||
|
|
||||||
|
def _create_treeview_widget(self, title = "Not Set"):
|
||||||
|
scroll = Gtk.ScrolledWindow()
|
||||||
|
grid = Gtk.TreeView()
|
||||||
|
store = Gtk.ListStore(str)
|
||||||
|
column = Gtk.TreeViewColumn(title)
|
||||||
|
name = Gtk.CellRendererText()
|
||||||
|
selec = grid.get_selection()
|
||||||
|
|
||||||
|
grid.set_model(store)
|
||||||
|
selec.set_mode(2)
|
||||||
|
|
||||||
|
column.pack_start(name, True)
|
||||||
|
column.add_attribute(name, "text", 0)
|
||||||
|
column.set_expand(False)
|
||||||
|
|
||||||
|
grid.append_column(column)
|
||||||
|
grid.set_search_column(0)
|
||||||
|
grid.set_headers_visible(True)
|
||||||
|
grid.set_enable_tree_lines(False)
|
||||||
|
|
||||||
|
grid.show_all()
|
||||||
|
scroll.add(grid)
|
||||||
|
grid.columns_autosize()
|
||||||
|
scroll.set_size_request(360, 240)
|
||||||
|
return scroll, store
|
||||||
|
|
||||||
|
def _create_listBox_widget(self,):
|
||||||
|
scroll = Gtk.ScrolledWindow()
|
||||||
|
grid = Gtk.ListBox()
|
||||||
|
viewport = Gtk.Viewport()
|
||||||
|
|
||||||
|
grid.show_all()
|
||||||
|
viewport.add(grid)
|
||||||
|
scroll.add(viewport)
|
||||||
|
|
||||||
|
scroll.set_size_request(360, 200)
|
||||||
|
return scroll, grid
|
|
@ -0,0 +1 @@
|
||||||
|
from .CommonActionsMixin import CommonActionsMixin
|
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Loading…
Reference in New Issue