- Prepare for removing the global installed _() method in builtins - Sort some imports along the way
		
			
				
	
	
		
			218 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com>
 | |
| #
 | |
| # This file is part of Gajim.
 | |
| #
 | |
| # Gajim is free software: you can redistribute it and/or modify
 | |
| # it under the terms of the GNU General Public License as published by
 | |
| # the Free Software Foundation, either version 3 of the License, or
 | |
| # (at your option) any later version.
 | |
| #
 | |
| # Gajim is distributed in the hope that it will be useful,
 | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| # GNU General Public License for more details.
 | |
| #
 | |
| # You should have received a copy of the GNU General Public License
 | |
| # along with Gajim. If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| import os
 | |
| import sys
 | |
| from pathlib import Path
 | |
| 
 | |
| from gi.repository import Gtk
 | |
| from gi.repository import GdkPixbuf
 | |
| from gi.repository import GObject
 | |
| 
 | |
| from gajim.common import app
 | |
| from gajim.common.i18n import _
 | |
| 
 | |
| from gajim.gtk.const import Filter
 | |
| from gajim.gtk.types import FilterList  # pylint: disable=unused-import
 | |
| 
 | |
| 
 | |
| def _require_native() -> bool:
 | |
|     if app.is_flatpak():
 | |
|         return True
 | |
|     if sys.platform in ('win32', 'darwin'):
 | |
|         return True
 | |
|     return False
 | |
| 
 | |
| 
 | |
| # Notes: Adding mime types to Gtk.FileFilter forces non-native dialogs
 | |
| 
 | |
| class BaseFileChooser:
 | |
|     def _on_response(self, dialog, response, accept_cb, cancel_cb):
 | |
|         if response == Gtk.ResponseType.ACCEPT:
 | |
|             if self.get_select_multiple():
 | |
|                 accept_cb(dialog.get_filenames())
 | |
|             else:
 | |
|                 accept_cb(dialog.get_filename())
 | |
| 
 | |
|         if response in (Gtk.ResponseType.CANCEL,
 | |
|                         Gtk.ResponseType.DELETE_EVENT):
 | |
|             if cancel_cb is not None:
 | |
|                 cancel_cb()
 | |
| 
 | |
|     def _add_filters(self, filters):
 | |
|         for filterinfo in filters:
 | |
|             filter_ = Gtk.FileFilter()
 | |
|             filter_.set_name(filterinfo.name)
 | |
|             if isinstance(filterinfo.pattern, list):
 | |
|                 for mime_type in filterinfo.pattern:
 | |
|                     filter_.add_mime_type(mime_type)
 | |
|             else:
 | |
|                 filter_.add_pattern(filterinfo.pattern)
 | |
|             self.add_filter(filter_)
 | |
|             if filterinfo.default:
 | |
|                 self.set_filter(filter_)
 | |
| 
 | |
|     def _update_preview(self, filechooser):
 | |
|         path_to_file = filechooser.get_preview_filename()
 | |
|         preview = filechooser.get_preview_widget()
 | |
|         if path_to_file is None or os.path.isdir(path_to_file):
 | |
|             # nothing to preview
 | |
|             preview.clear()
 | |
|             return
 | |
|         try:
 | |
|             pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
 | |
|                 path_to_file, *self._preivew_size)
 | |
|         except GObject.GError:
 | |
|             preview.clear()
 | |
|             return
 | |
|         filechooser.get_preview_widget().set_from_pixbuf(pixbuf)
 | |
| 
 | |
| 
 | |
| class BaseFileOpenDialog:
 | |
| 
 | |
|     _title = _('Choose File to Send…')
 | |
|     _filters = [Filter(_('All files'), '*', True)]  # type: FilterList
 | |
| 
 | |
| 
 | |
| class BaseAvatarChooserDialog:
 | |
| 
 | |
|     _title = _('Choose Avatar…')
 | |
|     _preivew_size = (100, 100)
 | |
| 
 | |
|     if _require_native():
 | |
|         _filters = [Filter(_('PNG files'), '*.png', True),
 | |
|                     Filter(_('JPEG files'), '*.jp*g', False),
 | |
|                     Filter(_('SVG files'), '*.svg', False)]  # type: FilterList
 | |
|     else:
 | |
|         _filters = [Filter(_('Images'), ['image/png',
 | |
|                                          'image/jpeg',
 | |
|                                          'image/svg+xml'], True)]
 | |
| 
 | |
| 
 | |
| class NativeFileChooserDialog(Gtk.FileChooserNative, BaseFileChooser):
 | |
| 
 | |
|     _title = ''
 | |
|     _filters = []  # type: FilterList
 | |
|     _action = Gtk.FileChooserAction.OPEN
 | |
| 
 | |
|     def __init__(self, accept_cb, cancel_cb=None, transient_for=None,
 | |
|                  path=None, file_name=None, select_multiple=False,
 | |
|                  modal=False):
 | |
| 
 | |
|         Gtk.FileChooserNative.__init__(self,
 | |
|                                        title=self._title,
 | |
|                                        action=self._action,
 | |
|                                        transient_for=transient_for)
 | |
| 
 | |
|         self.set_current_folder(path or str(Path.home()))
 | |
|         if file_name is not None:
 | |
|             self.set_current_name(file_name)
 | |
|         self.set_select_multiple(select_multiple)
 | |
|         self.set_do_overwrite_confirmation(True)
 | |
|         self.set_modal(modal)
 | |
|         self._add_filters(self._filters)
 | |
| 
 | |
|         self.connect('response', self._on_response, accept_cb, cancel_cb)
 | |
|         self.show()
 | |
| 
 | |
| 
 | |
| class ArchiveChooserDialog(NativeFileChooserDialog):
 | |
| 
 | |
|     _title = _('Choose Archive')
 | |
|     _filters = [Filter(_('All files'), '*', False),
 | |
|                 Filter(_('ZIP files'), '*.zip', True)]
 | |
| 
 | |
| 
 | |
| class FileSaveDialog(NativeFileChooserDialog):
 | |
| 
 | |
|     _title = _('Save File as…')
 | |
|     _filters = [Filter(_('All files'), '*', True)]
 | |
|     _action = Gtk.FileChooserAction.SAVE
 | |
| 
 | |
| 
 | |
| class AvatarSaveDialog(FileSaveDialog):
 | |
| 
 | |
|     if sys.platform == 'win32':
 | |
|         _filters = [Filter(_('Images'), '*.png;*.jpg;*.jpeg;*.svg', True)]
 | |
| 
 | |
| 
 | |
| class NativeFileOpenDialog(BaseFileOpenDialog, NativeFileChooserDialog):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| class NativeAvatarChooserDialog(BaseAvatarChooserDialog, NativeFileChooserDialog):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| class GtkFileChooserDialog(Gtk.FileChooserDialog, BaseFileChooser):
 | |
| 
 | |
|     _title = ''
 | |
|     _filters = []  # type: FilterList
 | |
|     _action = Gtk.FileChooserAction.OPEN
 | |
|     _preivew_size = (200, 200)
 | |
| 
 | |
|     def __init__(self, accept_cb, cancel_cb=None, transient_for=None,
 | |
|                  path=None, file_name=None, select_multiple=False,
 | |
|                  preview=True, modal=False):
 | |
| 
 | |
|         Gtk.FileChooserDialog.__init__(
 | |
|             self,
 | |
|             title=self._title,
 | |
|             action=self._action,
 | |
|             buttons=[Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
 | |
|                      Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT],
 | |
|             transient_for=transient_for)
 | |
| 
 | |
|         self.set_current_folder(path or str(Path.home()))
 | |
|         if file_name is not None:
 | |
|             self.set_current_name(file_name)
 | |
|         self.set_select_multiple(select_multiple)
 | |
|         self.set_do_overwrite_confirmation(True)
 | |
|         self.set_modal(modal)
 | |
|         self._add_filters(self._filters)
 | |
| 
 | |
|         if preview:
 | |
|             self.set_use_preview_label(False)
 | |
|             self.set_preview_widget(Gtk.Image())
 | |
|             self.connect('selection-changed', self._update_preview)
 | |
| 
 | |
|         self.connect('response', self._on_response, accept_cb, cancel_cb)
 | |
|         self.show()
 | |
| 
 | |
|     def _on_response(self, *args):
 | |
|         super()._on_response(*args)
 | |
|         self.destroy()
 | |
| 
 | |
| 
 | |
| class GtkFileOpenDialog(BaseFileOpenDialog, GtkFileChooserDialog):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| class GtkAvatarChooserDialog(BaseAvatarChooserDialog, GtkFileChooserDialog):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| def FileChooserDialog(*args, **kwargs):
 | |
|     if _require_native():
 | |
|         return NativeFileOpenDialog(*args, **kwargs)
 | |
|     return GtkFileOpenDialog(*args, **kwargs)
 | |
| 
 | |
| 
 | |
| def AvatarChooserDialog(*args, **kwargs):
 | |
|     if _require_native():
 | |
|         return NativeAvatarChooserDialog(*args, **kwargs)
 | |
|     return GtkAvatarChooserDialog(*args, **kwargs)
 |