I'm done now. I have bloated lsmodules beyond all reason.
It is getting to the point where I have repeated myself a couple of times, and it would benefit from a refactor (e.g. some things would work out nicer if we store a list of module folder paths in the MainWindow class), but everything seems to work in my manual testing so far.
Code: Select all
#!/usr/bin/python3
## Porteus Module Activation Status
## Author: jssouza
import os
import shutil
import glob
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Vte', '2.91')
from gi.repository import Gtk, Vte, Gdk, GdkPixbuf, Gio, GLib
from subprocess import run
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
class TermWindow(Gtk.Window):
def __init__(self, command_args):
Gtk.Window.__init__(self, title = "Update Module ", border_width = 5, height_request = 500, width_request = 550, icon_name = "system-settings")
self.vb = Gtk.Box(spacing = 5, orientation = Gtk.Orientation.VERTICAL)
self.vb.set_homogeneous(False)
terminal = Vte.Terminal()
pty = Vte.Pty.new_sync(Vte.PtyFlags.DEFAULT)
terminal.set_pty(pty)
pty.spawn_async(None, command_args, None, GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None, -1, None, self.ready)
self.connect("delete-event", self.on_window_close)
scrolledwindow = Gtk.ScrolledWindow()
scrolledwindow.add(terminal)
self.vb.pack_start(scrolledwindow, True, True, 0)
self.hb_bottom = Gtk.Box(spacing = 5)
self.hb_bottom.set_homogeneous(False)
self.ok_button = Gtk.Button.new_with_label("Quit")
self.ok_button.connect("clicked", self.on_quit_button_clicked)
self.hb_bottom.pack_end(self.ok_button, False, False, 6)
self.vb.pack_start(self.hb_bottom, False, False, 6)
self.add(self.vb)
def ready(self, pty, task):
# print('ready')
None
def on_window_close(self):
self.destroy()
def on_quit_button_clicked(self, button):
self.destroy()
class PortModules:
'''Port Modules Class'''
backing_files = []
extramod_dirs = []
extramod_paths = {}
is_copy_2_ram = False
def __init__(self):
self.set_extra_mods()
self.check_copy2ram()
def check_copy2ram(self):
with open('/etc/bootcmd.cfg', encoding = 'utf-8') as fd:
self.is_copy_2_ram = "copy2ram" in fd.read()
def set_extra_mods(self):
with open('/etc/bootcmd.cfg', encoding = 'utf-8') as fd:
for fline in fd:
if fline.startswith('extramod='):
fline = fline[9:-1]
self.extramod_dirs = fline.split(';')
i = len(self.extramod_dirs)
while i > 0:
if self.extramod_dirs[i - 1].startswith("UUID") or self.extramod_dirs[i - 1].startswith("LABEL"):
index = self.extramod_dirs[i - 1].find("/")
self.extramod_dirs[i - 1] = self.extramod_dirs[i - 1][index + 1:]
i -= 1
# print(self.extramod_dirs)
def set_extra_mod_paths(self):
self.extramod_paths.clear()
for extramod_dir in self.extramod_dirs:
for backing_file in self.backing_files:
if extramod_dir + "/" in backing_file:
index = backing_file.rfind("/")
self.extramod_paths[extramod_dir] = backing_file[:index]
break
return self.extramod_paths
def set_backing_files(self):
del self.backing_files[:]
os.chdir('/sys/block/')
loop_devices = glob.glob('loop*')
for loop_device in loop_devices:
if os.path.exists('/sys/block/' + loop_device + '/loop/'):
with open('/sys/block/' + loop_device + '/loop/backing_file', encoding = 'utf-8') as fd:
fline = fd.read()
if fline[:-1].endswith(".xzm"):
self.backing_files.append(fline[:-1])
return len(self.backing_files)
# print(self.backing_files)
def populate_modules(self, path):
module_list = {}
if os.path.exists(path):
os.chdir(path)
modules = glob.glob('*.xzm')
modules.sort()
for module in modules:
if os.path.realpath(module) in self.backing_files:
is_activated = True
self.backing_files.remove(os.path.realpath(module))
else:
is_activated = False
module_list[os.path.realpath(module)] = is_activated
return module_list
def populate_remaining_modules(self):
module_list = {}
for backing_file in self.backing_files:
module_list[backing_file] = True
return module_list
class MoveWindow(Gtk.Window):
'''dialog for moving modules between different folders'''
def __init__(self, parent: Gtk.Window, folder_list: list[str], mod_path: str):
Gtk.Window.__init__(self, title = "Move Module", border_width = 10, height_request = 300, width_request = 350, icon_name = "folder-move")
self.parent = parent
self.mod_path = mod_path
self.mod_name = os.path.basename(mod_path)
self.connect("delete-event", self.on_window_close)
self.vb = Gtk.Box(spacing = 10, orientation = Gtk.Orientation.VERTICAL)
self.vb.set_homogeneous(False)
self.hb1 = Gtk.Box(spacing = 5)
self.l_intro = Gtk.Label(label = "Select a new folder for the module")
self.l_intro.set_justify(Gtk.Justification.LEFT)
self.hb1.pack_start(self.l_intro, False, False, 0)
self.vb.pack_start(self.hb1, False, False, 0)
self.hb2 = Gtk.Box(spacing = 5)
self.l_mod_name = Gtk.Label()
self.l_mod_name.set_markup(f"<b>{self.mod_name}</b>")
self.l_mod_name.set_justify(Gtk.Justification.CENTER)
self.hb2.pack_start(self.l_mod_name, True, True, 0)
self.vb.pack_start(self.hb2, False, False, 0)
self.folder_store = Gtk.ListStore(str)
for fp in folder_list:
self.folder_store.append([fp])
self.folder_view = Gtk.TreeView(model = self.folder_store)
column = Gtk.TreeViewColumn("Folders")
folder_renderer_text = Gtk.CellRendererText()
column.pack_start(folder_renderer_text, False)
column.add_attribute(folder_renderer_text, "text", 0)
self.folder_view.append_column(column)
self.vb.pack_start(self.folder_view, False, False, 0)
self.hb4 = Gtk.Box(spacing = 5)
self.cancel_button = Gtk.Button.new_with_label("Cancel")
self.cancel_button.connect("clicked", self.on_window_close, None)
self.hb4.pack_start(self.cancel_button, True, False, 0)
self.move_button = Gtk.Button.new_with_label("Move")
self.move_button.connect("clicked", self.move_module_file)
self.hb4.pack_end(self.move_button, True, False, 0)
self.vb.pack_end(self.hb4, False, False, 0)
self.add(self.vb)
def on_window_close(self, _arg1, _arg2):
self.destroy()
self.parent.set_modules_model()
def move_module_file(self, _arg):
model, treeiter = self.folder_view.get_selection().get_selected()
new_folder = model[treeiter][0]
new_path = os.path.join(new_folder, self.mod_name)
if os.path.exists(self.mod_path) and not os.path.exists(new_path):
try:
shutil.move(self.mod_path, new_path)
print(f'Moved {self.mod_path} to {new_path}')
except OSError:
self.parent.msg_dialog("Operating system error: could not move the module.")
else:
self.parent.msg_dialog("Destination file already exists!")
print(f'Not OK to move {self.mod_path} to {new_path}')
self.on_window_close(None, None)
class MainWindow(Gtk.Window):
portdir_env_dir = os.environ["PORTDIR"]
bootdev_env_dir = os.environ["BOOTDEV"]
extra_mod_paths = {}
port_modules = PortModules()
theme = Gtk.IconTheme.get_default()
activated_icon = Gtk.IconTheme.load_icon(theme, "gtk-yes", 24, Gtk.IconLookupFlags.USE_BUILTIN)
not_activated_icon = Gtk.IconTheme.load_icon(theme, "gtk-no", 24, Gtk.IconLookupFlags.USE_BUILTIN)
#add_icon = Gtk.IconTheme.load_icon(theme, "gtk-add", 24, Gtk.IconLookupFlags.USE_BUILTIN)
new_enabled = shutil.which('gtk-slapt-mod')
update_enabled = shutil.which('upgrade-mods')
def __init__(self):
Gtk.Window.__init__(self, title = "Porteus Modules", border_width = 5, height_request = 550, width_request = 500, icon_name = "cdr")
self.vb = Gtk.Box(spacing = 5, orientation = Gtk.Orientation.VERTICAL)
self.vb.set_homogeneous(False)
self.hb_top = Gtk.Box(spacing = 5)
self.hb_top.set_homogeneous(False)
self.l_num_mods_txt = Gtk.Label(label = "Modules Activated: ")
self.l_num_mods_txt.set_justify(Gtk.Justification.RIGHT)
self.l_num_mods = Gtk.Label(label = "")
self.l_num_mods.set_justify(Gtk.Justification.LEFT)
self.spinner = Gtk.Spinner()
self.hb_top.pack_start(self.l_num_mods_txt, False, False, 0)
self.hb_top.pack_start(self.l_num_mods, False, False, 0)
self.hb_top.pack_start(self.spinner, False, False, 0)
self.add_button = Gtk.Button.new_from_icon_name("folder-new", Gtk.IconSize.BUTTON)
self.add_button.set_tooltip_text("New custom module folder")
#self.add_button.set_relief(Gtk.ReliefStyle.NONE)
self.add_button.connect("clicked", self.on_add_button_clicked)
self.hb_top.pack_end(self.add_button, False, False, 0)
self.mod_add_button = Gtk.Button.new_from_icon_name("cdr", Gtk.IconSize.BUTTON)
self.mod_add_button.set_tooltip_text("Activate module (browse)")
#self.mod_add_button.set_relief(Gtk.ReliefStyle.NONE)
self.mod_add_button.connect("clicked", self.on_mod_add_button_clicked)
self.hb_top.pack_end(self.mod_add_button, False, False, 0)
self.refresh_button = Gtk.Button.new_from_icon_name("view-refresh", Gtk.IconSize.BUTTON)
self.refresh_button.set_tooltip_text("Refresh module list")
self.refresh_button.connect("clicked", self.on_refresh_button_clicked)
self.hb_top.pack_end(self.refresh_button, False, False, 0)
if self.new_enabled:
self.new_button = Gtk.Button.new_from_icon_name("go-down", Gtk.IconSize.BUTTON)
self.new_button.set_tooltip_text("Get new modules")
self.new_button.connect("clicked", self.on_new_button_clicked)
self.hb_top.pack_end(self.new_button, False, False, 0)
self.vb.pack_start(self.hb_top, False, False, 5)
self.ts_modules_model = Gtk.TreeStore(GdkPixbuf.Pixbuf, str, bool, str)
self.tree_view = Gtk.TreeView(model = self.ts_modules_model)
self.setup_tree_view()
self.tree_view.connect("row-activated", self.on_row_activated)
self.right_click_menu = Gtk.Menu()
self.tree_view.connect("button-press-event", self.on_tree_button_press)
self.scrolled_win = Gtk.ScrolledWindow()
self.scrolled_win.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
self.scrolled_win.add(self.tree_view)
self.vb.pack_start(self.scrolled_win, True, True, 0)
self.hb_bottom = Gtk.Box(spacing = 5)
self.hb_bottom.set_homogeneous(False)
self.l_mod_path = Gtk.Label(label = "")
self.hb_bottom.pack_start(self.l_mod_path, False, False, 6)
self.vb.pack_start(self.hb_bottom, False, False, 6)
self.add(self.vb)
self.select = self.tree_view.get_selection()
self.select.connect("changed", self.on_tree_selection_changed)
self.gio_file = Gio.File.new_for_path("/mnt/live/memory/images")
self.monitor = self.gio_file.monitor_directory(Gio.FileMonitorFlags.NONE, None)
self.monitor.connect("changed", self.on_mods_dir_changed)
if self.bootdev_env_dir.startswith("/mnt/isoloop"):
self.bootdev_env_dir = "/mnt/live" + self.portdir_env_dir
self.set_modules_model()
def msg_dialog(self, msg):
dialog = Gtk.MessageDialog(transient_for=self,
flags=0,
message_type=Gtk.MessageType.INFO,
buttons=Gtk.ButtonsType.OK,
text=msg)
dialog.run()
dialog.destroy()
def on_refresh_button_clicked(self, button):
self.set_modules_model()
def on_new_button_clicked(self, button):
self.do_new(None, None)
def on_add_button_clicked(self, button):
dialog = Gtk.FileChooserDialog(title = "Choose a modules directory", parent = self,
action = Gtk.FileChooserAction.SELECT_FOLDER)
dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
"Select", Gtk.ResponseType.OK)
dialog.set_default_size(800, 400)
response = dialog.run()
if Gtk.ResponseType.OK == response:
self.add_custom_modules_path(dialog.get_filename())
dialog.destroy()
def on_mod_add_button_clicked(self, button):
dialog = Gtk.FileChooserDialog(title = "Choose a module to activate/deactivate", parent = self,
action = Gtk.FileChooserAction.OPEN)
dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
"Select", Gtk.ResponseType.OK)
dialog.set_default_size(800, 400)
response = dialog.run()
if Gtk.ResponseType.OK == response:
run(["/usr/bin/activate", dialog.get_filename()])
dialog.destroy()
def add_custom_modules_path(self, dir_path):
if os.path.exists(dir_path):
if dir_path.startswith(self.portdir_env_dir + "/base") or \
dir_path.startswith(self.portdir_env_dir + "/modules") or \
dir_path.startswith(self.portdir_env_dir + "/optional"):
self.msg_dialog("Porteus directories already added")
return
for extra_mod_path in self.extra_mod_paths:
if dir_path == self.extra_mod_paths[extra_mod_path]:
self.msg_dialog("Directory already added as part of extramod= cheatcode")
return
if os.path.exists(os.environ["HOME"] + "/.config/lsmodules"):
with open(os.environ["HOME"] + "/.config/lsmodules", mode = "r", encoding = "utf-8") as fd:
for fline in fd:
if fline.startswith("#"):
fline = fline[1:]
fline = fline.lstrip()
if fline.startswith("$PORTDIR"):
fline = fline.replace("$PORTDIR", self.portdir_env_dir)
if fline.startswith("$BOOTDEV"):
fline = fline.replace("$BOOTDEV", self.bootdev_env_dir)
if dir_path == fline[:-1]:
self.msg_dialog("Directory already added")
return
with open(os.environ["HOME"] + "/.config/lsmodules", mode = "a", encoding = "utf-8") as fd:
fd.write(dir_path + "\n")
else:
with open(os.environ["HOME"] + "/.config/lsmodules", mode = "a+", encoding = "utf-8") as fd:
fd.write(dir_path + "\n")
self.set_modules_model()
def on_tree_selection_changed(self, selection):
model, iter = selection.get_selected()
if iter is not None:
if model[iter][0] is not None:
self.l_mod_path.set_markup("<i>" + model[iter][3] + "/" + model[iter][1] + "</i>")
else:
self.l_mod_path.set_text("")
def on_row_activated(self, tree_view, path, column):
self.spinner.start()
model = tree_view.get_model()
iter = model.get_iter(path)
row = model.get(iter, 0, 1, 2, 3)
if row[0] is not None:
if row[3] not in self.portdir_env_dir + "/base/" and row[3] not in "/mnt/live/memory/copy2ram":
if row[2]:
cmd_string = "deactivate"
else:
cmd_string = "activate"
mod_path = row[3] + "/" + row[1]
GLib.timeout_add(100, self.run_module_activator, cmd_string, mod_path)
else:
self.msg_dialog("Base Modules should not be Activated/Deactivated")
self.spinner.stop()
def run_module_activator(self, cmd_string, mod_path):
run([cmd_string, mod_path])
def on_tree_button_press(self, treeview, event):
clicked_path, clicked_column, cell_x, cell_y = treeview.get_path_at_pos(event.x, event.y)
if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3 and clicked_path:
clicked_data = treeview.get_model()[clicked_path]
clicked_mod_path = f"{clicked_data[3]}/{clicked_data[1]}"
is_activated = clicked_data[2]
self.build_and_show_right_click_menu(clicked_mod_path, is_activated)
def build_and_show_right_click_menu(self, mod_path, is_activated):
menu = self.right_click_menu
if menu.is_visible:
menu.hide()
for mi in menu.get_children():
menu.remove(mi)
activation_label = "Deactivate..." if is_activated else "Activate..."
activation_item = Gtk.MenuItem(label=activation_label)
activation_item.connect("button-press-event", self.do_activation, mod_path, is_activated)
menu.append(activation_item)
if self.new_enabled:
new_item = Gtk.MenuItem(label="New...")
new_item.connect("button-press-event", self.do_new)
menu.append(new_item)
move_item = Gtk.MenuItem(label="Move...")
move_item.connect("button-press-event", self.do_move, mod_path, is_activated)
menu.append(move_item)
if self.update_enabled:
update_item = Gtk.MenuItem(label="Update...")
update_item.connect("button-press-event", self.do_update, mod_path)
menu.append(update_item)
delete_item = Gtk.MenuItem(label="Delete...")
delete_item.connect("button-press-event", self.do_delete, mod_path, is_activated)
menu.append(delete_item)
menu.show_all()
menu.popup(None, None, None, None, 0, Gtk.get_current_event_time())
def do_activation(self, menu_item, event, mod_path, is_activated):
self.spinner.start()
cmd_string = "deactivate" if is_activated else "activate"
if self.portdir_env_dir + "/base/" in mod_path or "/mnt/live/memory/copy2ram" in mod_path:
self.msg_dialog("Base Modules should not be Activated/Deactivated")
self.spinner.stop()
else:
GLib.timeout_add(100, self.run_module_activator, cmd_string, mod_path)
def do_new(self, menu_item, event):
if self.new_enabled:
pid, fdin, fdout, fderr = GLib.spawn_async([self.new_enabled])
else:
self.msg_dialog("Module Maker program is not installed.")
def do_move(self, menu_item, event, mod_path, is_activated):
if is_activated:
self.msg_dialog("You cannot move an activated module. Deactivate it first!")
else:
# assemble folder list
# this would be easier if we had done it at init time
default_folder_names = ['base', 'modules', 'optional']
folder_set = {self.portdir_env_dir + '/' + fname for fname in default_folder_names if os.path.exists(self.portdir_env_dir + '/' + fname)}
for emp in self.port_modules.extramod_dirs:
if os.path.exists(emp):
folder_set.add(emp)
for row in self.ts_modules_model:
folder_title = row[1]
if 'Custom Dir (' in folder_title:
folder_title_stripped = folder_title.replace('Custom Dir (', '')
folder_title_stripped = folder_title_stripped[:-1]
if os.path.exists(folder_title_stripped):
folder_set.add(folder_title_stripped)
if 'Extramod Dir (' in folder_title:
folder_title_stripped = folder_title.replace('Extramod Dir (', '')
folder_title_stripped = folder_title_stripped[:-1]
if os.path.exists(folder_title_stripped):
folder_set.add(folder_title_stripped)
def folder_add_fn(store, treepath, treeiter):
if store[treeiter][3]:
folder_set.add(store[treeiter][3])
self.ts_modules_model.foreach(folder_add_fn)
print(folder_set)
print(mod_path)
move_window = MoveWindow(self, list(folder_set), mod_path)
move_window.set_modal(True)
move_window.show_all()
def do_update(self, menu_item, event, mod_path):
if self.update_enabled:
term_window = TermWindow([self.update_enabled, "-Uv", mod_path])
# term_window = TermWindow(["echo", "hi"])
term_window.show_all()
def do_delete(self, menu_item, event, mod_path, is_activated):
if is_activated:
self.msg_dialog("You cannot delete an activated module. Deactivate it first!")
else:
mod_name = os.path.basename(mod_path)
confirm_text = f"Do you really want to delete {mod_name}?"
confirm_delete_dialog = Gtk.MessageDialog(transient_for=self,
flags=0,
message_type=Gtk.MessageType.WARNING,
text=confirm_text)
confirm_delete_dialog.format_secondary_text("This cannot be undone.")
confirm_delete_dialog.add_button(button_text="Cancel",
response_id=Gtk.ResponseType.CANCEL)
confirm_delete_dialog.add_button(button_text="Delete",
response_id=Gtk.ResponseType.ACCEPT)
user_response = confirm_delete_dialog.run()
if user_response == Gtk.ResponseType.ACCEPT and os.path.exists(mod_path):
try:
os.remove(mod_path)
self.set_modules_model()
except OSError:
self.parent.msg_dialog("Operating system error: could not delete the module.")
confirm_delete_dialog.destroy()
def cell_data_func(self, column, renderer, model, iter, data):
row = model.get(iter, 0, 1)
if row[0] is None:
markup_txt = "<b>" + row[1] + "</b>"
renderer.set_property("markup", markup_txt)
def setup_tree_view(self):
column = Gtk.TreeViewColumn("Module Name")
renderer_pixbuf = Gtk.CellRendererPixbuf()
renderer_text = Gtk.CellRendererText()
column.pack_start(renderer_pixbuf, False)
column.pack_start(renderer_text, False)
column.add_attribute(renderer_pixbuf, "pixbuf", 0)
column.add_attribute(renderer_text, "text", 1)
column.set_cell_data_func(renderer_text, self.cell_data_func, None)
# column.set_sort_column_id(1)
self.tree_view.append_column(column)
def insert_modules_in_model(self, module_list, iter):
for module in module_list:
(dirname, filename) = os.path.split(module)
if True == module_list[module]:
icon = self.activated_icon
else:
icon = self.not_activated_icon
self.ts_modules_model.append(iter, [icon, filename, module_list[module], dirname])
def on_mods_dir_changed(self, monitor, file1, file2, event_type):
if event_type == Gio.FileMonitorEvent.CREATED or event_type == Gio.FileMonitorEvent.DELETED:
GLib.timeout_add_seconds(1, self.set_modules_model)
def set_modules_model(self):
self.ts_modules_model.clear()
self.extra_mod_paths.clear()
num_modules = 0
num_activated_modules = self.port_modules.set_backing_files()
self.extra_mod_paths = self.port_modules.set_extra_mod_paths()
if self.port_modules.is_copy_2_ram:
iter = self.ts_modules_model.append(None, [None, "Copied to RAM", None, None])
module_list = self.port_modules.populate_modules("/mnt/live/memory/copy2ram/")
num_modules += len(module_list)
self.insert_modules_in_model(module_list, iter)
elif os.path.exists(self.portdir_env_dir):
iter = self.ts_modules_model.append(None, [None, "Base", None, None])
module_list = self.port_modules.populate_modules(self.portdir_env_dir + "/base/")
num_modules += len(module_list)
self.insert_modules_in_model(module_list, iter)
iter = self.ts_modules_model.append(None, [None, "Modules", None, None])
module_list = self.port_modules.populate_modules(self.portdir_env_dir + "/modules/")
num_modules += len(module_list)
self.insert_modules_in_model(module_list, iter)
if os.path.exists(self.portdir_env_dir + "/optional/"):
iter = self.ts_modules_model.append(None, [None, "Optional", None, None])
module_list = self.port_modules.populate_modules(self.portdir_env_dir + "/optional/")
num_modules += len(module_list)
sub_dirs = next(os.walk(self.portdir_env_dir + "/optional/"))[1]
self.insert_modules_in_model(module_list, iter)
if sub_dirs:
for sub_dir in sub_dirs:
module_list = self.port_modules.populate_modules(self.portdir_env_dir + "/optional/" + sub_dir + "/")
num_modules += len(module_list)
self.insert_modules_in_model(module_list, iter)
''' Extramod Dirs '''
for extra_mod_path in self.extra_mod_paths:
# print(extra_mod_path, self.extra_mod_paths[extra_mod_path])
iter = self.ts_modules_model.append(None, [None, "Extramod Dir (" + extra_mod_path + ")", None, None])
module_list = self.port_modules.populate_modules(self.extra_mod_paths[extra_mod_path] + "/")
num_modules += len(module_list)
self.insert_modules_in_model(module_list, iter)
''' User defined Dirs '''
if os.path.exists(os.environ["HOME"] + "/.config/lsmodules"):
with open(os.environ["HOME"] + "/.config/lsmodules", mode = "r", encoding = "utf-8") as fd:
for fline in fd:
if fline.startswith("#"):
continue
fline = fline.lstrip()
fline = fline[:-1]
if fline.startswith("$PORTDIR"):
fline = fline.replace("$PORTDIR", self.portdir_env_dir)
elif fline.startswith("$BOOTDEV"):
fline = fline.replace("$BOOTDEV", self.bootdev_env_dir)
if os.path.exists(fline):
iter = self.ts_modules_model.append(None, [None, "Custom Dir (" + fline + ")", None, None])
module_list = self.port_modules.populate_modules(fline + "/")
num_modules += len(module_list)
self.insert_modules_in_model(module_list, iter)
''' Remaining Modules '''
module_list = self.port_modules.populate_remaining_modules()
if module_list:
iter = self.ts_modules_model.append(None, [None, "Other", None, None])
self.insert_modules_in_model(module_list, iter)
num_modules += len(module_list)
self.l_num_mods.set_text(str(num_activated_modules) + "/" + str(num_modules))
self.tree_view.expand_all()
selection = self.tree_view.get_selection()
path = Gtk.TreePath([0, 0])
selection.select_path(path)
self.spinner.stop()
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
#widget = Gtk.TreeViewColumn()
#print(dir(widget.props))