Skip to content

Commit

Permalink
Merge pull request #259 from cary-rowen/feature/individual-file-assoc…
Browse files Browse the repository at this point in the history
…iation

Implement individual file type association/disassociation in FileAssociationDialog. Added functionality to dynamically update button labels and actions for each file type.
  • Loading branch information
cary-rowen authored Aug 26, 2024
2 parents c83e13c + d928485 commit d82ec27
Show file tree
Hide file tree
Showing 4 changed files with 4,116 additions and 4,034 deletions.
80 changes: 60 additions & 20 deletions bookworm/gui/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from bookworm.paths import app_path
from bookworm.platforms import PLATFORM
from bookworm.resources import app_icons
from bookworm.shell import shell_disintegrate, shell_integrate
from bookworm.shell import shell_disintegrate, shell_integrate,is_file_type_associated
from bookworm.shellinfo import get_ext_info
from bookworm.signals import app_started, config_updated
from bookworm.utils import restart_application
Expand All @@ -39,7 +39,6 @@ class ReconciliationStrategies(IntEnum):
load = auto()
save = auto()


class FileAssociationDialog(SimpleDialog):
"""Associate supported file types."""

Expand All @@ -58,8 +57,8 @@ def addControls(self, parent):
parent,
-1,
_(
"This dialog will help you to setup file associations.\n"
"Associating files with Bookworm means that when you click on a file in windows explorer, it will be opened in Bookworm by default "
"This dialog will help you to set up file associations.\n"
"Associating files with Bookworm means that when you click on a file in Windows Explorer, it will be opened in Bookworm by default."
),
)
masterPanel = sc.SizedPanel(parent, -1)
Expand All @@ -69,39 +68,80 @@ def addControls(self, parent):
assoc_btn = CommandLinkButton(
panel1,
-1,
# Translators: the main label of a button
_("Associate all"),
# Translators: the note of a button
_("Use Bookworm to open all supported document formats"),
)
half = len(self.ext_info) / 2
buttonPanel = panel1
for i, (ext, metadata) in enumerate(self.ext_info):
if i >= half:
buttonPanel = panel2
# Translators: the main label of a button
mlbl = _("Associate files of type {format}").format(format=metadata[1])
# Translators: the note of a button
nlbl = _(
"Associate files with {ext} extension so they always open in Bookworm"
).format(ext=ext)
btn = CommandLinkButton(buttonPanel, -1, mlbl, nlbl)
self.Bind(
wx.EVT_BUTTON,
lambda e, args=(ext, metadata[1]): self.onFileAssoc(*args),
btn,
)
# Create button
btn = CommandLinkButton(buttonPanel, -1, "", "")
# Update the button with the correct label and event handler
self.update_button_for_file_type(btn, ext, metadata)
dissoc_btn = CommandLinkButton(
panel2,
-1,
# Translators: the main label of a button
_("Dissociate all supported file types"),
# Translators: the note of a button
_("Remove previously associated file types"),
)
self.Bind(wx.EVT_BUTTON, lambda e: self.onBatchAssoc(assoc=True), assoc_btn)
self.Bind(wx.EVT_BUTTON, lambda e: self.onBatchAssoc(assoc=False), dissoc_btn)

def update_button_for_file_type(self, btn, ext, metadata):
"""
Updates the button's label and event handler based on the file type's association status.
Args:
btn (wx.CommandLinkButton): The button to update.
ext (str): The file extension associated with the button.
metadata (tuple): The metadata tuple containing prog_id, description, and icon.
"""
is_associated = is_file_type_associated(ext)
if is_associated:
# Translators: the main label of a button
mlbl = _("Dissociate files of type {format}").format(format=metadata[1])
# Translators: the note of a button
nlbl = _("Dissociate files with {ext} extension so they no longer open in Bookworm").format(ext=ext)
btn.SetLabel(mlbl)
btn.SetNote(nlbl)
btn.Bind(wx.EVT_BUTTON, lambda e: self.on_disassociate(btn, ext, metadata))
else:
# Translators: the main label of a button
mlbl = _("Associate files of type {format}").format(format=metadata[1])
# Translators: the note of a button
nlbl = _("Associate files with {ext} extension so they always open in Bookworm").format(ext=ext)
btn.SetLabel(mlbl)
btn.SetNote(nlbl)
btn.Bind(wx.EVT_BUTTON, lambda e: self.on_associate(btn, ext, metadata))

def on_disassociate(self, btn, ext, metadata):
"""
Handles the disassociation of a file type.
Args:
btn (wx.CommandLinkButton): The button associated with the action.
ext (str): The file extension to disassociate.
metadata (tuple): The metadata associated with the file type.
"""
shell_disintegrate(supported=ext)
# After disassociating, update the button to reflect the change
self.update_button_for_file_type(btn, ext, metadata)

def on_associate(self, btn, ext, metadata):
"""
Handles the association of a file type.
Args:
btn (wx.CommandLinkButton): The button associated with the action.
ext (str): The file extension to associate.
metadata (tuple): The metadata associated with the file type.
"""
shell_integrate(supported=ext)
# After associating, update the button to reflect the change
self.update_button_for_file_type(btn, ext, metadata)

def getButtons(self, parent):
btnsizer = wx.StdDialogButtonSizer()
cancelBtn = wx.Button(self, wx.ID_CANCEL, _("&Close"))
Expand Down
16 changes: 16 additions & 0 deletions bookworm/platforms/win32/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,19 @@ def shell_disintegrate(supported="*"):
for ext, (prog_id, desc, icon) in doctypes.items():
remove_association(ext, prog_id)
shell_notify_association_changed()


def is_file_type_associated(ext):
ext_info = get_ext_info([ext])
prog_id, _, _ = ext_info[ext]
try:
with RegKey.LocalSoftware(rf"{ext}\OpenWithProgids") as key:
key.get_value(prog_id)
return True
except FileNotFoundError:
return False
except PermissionError:
return False
except Exception as e:
log.exception(f"Unexpected error when checking file association for {ext}: {str(e)}")
return False
Loading

0 comments on commit d82ec27

Please sign in to comment.