deluge/deluge/ui/gtk3/path_chooser.py
Calum Lind 92a048625a [GTK3] Fix the transient parent for PathChooser
The filechooser dialog was wrongly transient to the main window causing
weird behaviour, namely the main window moving but dialog remaining in
place when attempting to move the child dialog.

The solution is to pass the parent dialog to PathChooser so it can be
properly set the filechooser dialog transient property.

Fixed the Preferences dialog not being set to be modal to main window.
2018-11-02 08:45:39 +00:00

202 lines
7.3 KiB
Python

# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 Bro <bro.development@gmail.com>
#
# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
from __future__ import unicode_literals
import logging
import deluge.component as component
from deluge.ui.client import client
from .path_combo_chooser import PathChooserComboBox
log = logging.getLogger(__name__)
def singleton(cls):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
return getinstance
@singleton
class PathChoosersHandler(component.Component):
def __init__(self, paths_config_key=None):
# self.chooser_name = "PathChooser_%d" % (len(PathChooser.path_choosers) +1)
component.Component.__init__(self, 'PathChoosersHandler')
self.path_choosers = []
self.paths_list_keys = []
self.config_properties = {}
self.started = False
self.config_keys_to_funcs_mapping = {
'path_chooser_show_chooser_button_on_localhost': 'filechooser_button_visible',
'path_chooser_show_path_entry': 'path_entry_visible',
'path_chooser_auto_complete_enabled': 'auto_complete_enabled',
'path_chooser_show_folder_name': 'show_folder_name_on_button',
'path_chooser_accelerator_string': 'accelerator_string',
'path_chooser_show_hidden_files': 'show_hidden_files',
'path_chooser_max_popup_rows': 'max_popup_rows',
}
def start(self):
self.started = True
self.update_config_from_core()
def stop(self):
self.started = False
def update_config_from_core(self):
def _on_config_values(config):
self.config_properties.update(config)
for chooser in self.path_choosers:
chooser.set_config(config)
keys = list(self.config_keys_to_funcs_mapping)
keys += self.paths_list_keys
client.core.get_config_values(keys).addCallback(_on_config_values)
def register_chooser(self, chooser):
chooser.config_key_funcs = {}
for key in self.config_keys_to_funcs_mapping:
chooser.config_key_funcs[key] = [None, None]
chooser.config_key_funcs[key][0] = getattr(
chooser, 'get_%s' % self.config_keys_to_funcs_mapping[key]
)
chooser.config_key_funcs[key][1] = getattr(
chooser, 'set_%s' % self.config_keys_to_funcs_mapping[key]
)
self.path_choosers.append(chooser)
if chooser.paths_config_key not in self.paths_list_keys:
self.paths_list_keys.append(chooser.paths_config_key)
if self.started:
self.update_config_from_core()
else:
chooser.set_config(self.config_properties)
def set_value_for_path_choosers(self, value, key):
for chooser in self.path_choosers:
chooser.config_key_funcs[key][1](value)
# Save to core
if key is not 'path_chooser_max_popup_rows':
client.core.set_config({key: value})
else:
# Since the max rows value can be changed fast with a spinbutton, we
# delay saving to core until the values hasn't been changed in 1 second.
self.max_rows_value_set = value
def update(value_):
# The value hasn't been changed in one second, so save to core
if self.max_rows_value_set == value_:
client.core.set_config({'path_chooser_max_popup_rows': value})
from twisted.internet import reactor
reactor.callLater(1, update, value)
def on_list_values_changed(self, values, key, caller):
# Save to core
config = {key: values}
client.core.set_config(config)
# Set the values on all path choosers with that key
for chooser in self.path_choosers:
# Found chooser with values from 'key'
if chooser.paths_config_key == key:
chooser.set_values(values)
def get_config_keys(self):
keys = list(self.config_keys_to_funcs_mapping)
keys += self.paths_list_keys
return keys
class PathChooser(PathChooserComboBox):
def __init__(self, paths_config_key=None, parent=None):
self.paths_config_key = paths_config_key
super(PathChooser, self).__init__(parent=parent)
self.chooser_handler = PathChoosersHandler()
self.chooser_handler.register_chooser(self)
self.set_auto_completer_func(self.on_completion)
self.connect('list-values-changed', self.on_list_values_changed_event)
self.connect(
'auto-complete-enabled-toggled', self.on_auto_complete_enabled_toggled
)
self.connect('show-filechooser-toggled', self.on_show_filechooser_toggled)
self.connect(
'show-folder-name-on-button', self.on_show_folder_on_button_toggled
)
self.connect('show-path-entry-toggled', self.on_show_path_entry_toggled)
self.connect('accelerator-set', self.on_accelerator_set)
self.connect('max-rows-changed', self.on_max_rows_changed)
self.connect('show-hidden-files-toggled', self.on_show_hidden_files_toggled)
def on_auto_complete_enabled_toggled(self, widget, value):
self.chooser_handler.set_value_for_path_choosers(
value, 'path_chooser_auto_complete_enabled'
)
def on_show_filechooser_toggled(self, widget, value):
self.chooser_handler.set_value_for_path_choosers(
value, 'path_chooser_show_chooser_button_on_localhost'
)
def on_show_folder_on_button_toggled(self, widget, value):
self.chooser_handler.set_value_for_path_choosers(
value, 'path_chooser_show_folder_name'
)
def on_show_path_entry_toggled(self, widget, value):
self.chooser_handler.set_value_for_path_choosers(
value, 'path_chooser_show_path_entry'
)
def on_accelerator_set(self, widget, value):
self.chooser_handler.set_value_for_path_choosers(
value, 'path_chooser_accelerator_string'
)
def on_show_hidden_files_toggled(self, widget, value):
self.chooser_handler.set_value_for_path_choosers(
value, 'path_chooser_show_hidden_files'
)
def on_max_rows_changed(self, widget, value):
self.chooser_handler.set_value_for_path_choosers(
value, 'path_chooser_max_popup_rows'
)
def on_list_values_changed_event(self, widget, values):
self.chooser_handler.on_list_values_changed(values, self.paths_config_key, self)
def set_config(self, config):
self.config = config
for key in self.config_key_funcs:
if key in config:
try:
self.config_key_funcs[key][1](config[key])
except TypeError as ex:
log.warning('TypeError: %s', ex)
# Set the saved paths
if self.paths_config_key and self.paths_config_key in config:
self.set_values(config[self.paths_config_key])
def on_completion(self, args):
def on_paths_cb(args):
self.complete(args)
d = client.core.get_completion_paths(args)
d.addCallback(on_paths_cb)