diff --git a/spyder/config/utils.py b/spyder/config/utils.py index 86fa5ebbea1..590aec60906 100644 --- a/spyder/config/utils.py +++ b/spyder/config/utils.py @@ -116,9 +116,20 @@ def get_filter(filetypes, ext): def get_edit_filetypes(): """Get all file types supported by the Editor""" - pygments_exts = _get_pygments_extensions() - favorite_exts = ['.py', '.R', '.jl', '.ipynb', '.md', '.pyw', '.pyx', '.C', '.CPP'] - other_exts = [ext for ext in pygments_exts if ext not in favorite_exts] + # The filter details are not hidden on Windows, so we can't use + # all Pygments extensions on that platform + if os.name == 'nt': + supported_exts = [] + else: + supported_exts = _get_pygments_extensions() + + # NOTE: Try to not add too much extensions to this list to not + # make the filter look too big on Windows + favorite_exts = ['.py', '.R', '.jl', '.ipynb', '.md', '.pyw', '.pyx', + '.c', '.cpp', '.json', '.dat', '.csv', '.tsv', '.txt', + '.ini', '.html', '.js', '.h', '.bat'] + + other_exts = [ext for ext in supported_exts if ext not in favorite_exts] all_exts = tuple(favorite_exts + other_exts) text_filetypes = (_("Supported text files"), all_exts) return [text_filetypes] + EDIT_FILETYPES @@ -171,3 +182,26 @@ def is_gtk_desktop(): return False else: return False + + +def is_kde_desktop(): + "Detect if we are running in a KDE desktop" + if sys.platform.startswith('linux'): + xdg_desktop = os.environ.get('XDG_CURRENT_DESKTOP', '') + if xdg_desktop: + if 'KDE' in xdg_desktop: + return True + else: + return False + else: + return False + else: + return False + + +def is_anaconda(): + "Detect if we are running under Anaconda." + for var in os.environ: + if var.startswith('CONDA'): + return True + return False diff --git a/spyder/widgets/editor.py b/spyder/widgets/editor.py index 29974a5ce48..1b764e44343 100644 --- a/spyder/widgets/editor.py +++ b/spyder/widgets/editor.py @@ -24,15 +24,15 @@ from qtpy.QtCore import (QByteArray, QFileInfo, QObject, QPoint, QSize, Qt, QThread, QTimer, Signal, Slot) from qtpy.QtGui import QFont -from qtpy.QtWidgets import (QAction, QApplication, QHBoxLayout, QMainWindow, - QMessageBox, QMenu, QSplitter, QVBoxLayout, - QWidget, QListWidget, QListWidgetItem) +from qtpy.QtWidgets import (QAction, QApplication, QFileDialog, QHBoxLayout, + QMainWindow, QMessageBox, QMenu, QSplitter, + QVBoxLayout, QWidget, QListWidget, QListWidgetItem) # Local imports from spyder.config.base import _, DEBUG, STDERR, STDOUT from spyder.config.gui import config_shortcut, get_shortcut from spyder.config.utils import (get_edit_filetypes, get_edit_filters, - get_filter) + get_filter, is_kde_desktop, is_anaconda) from spyder.py3compat import qbytearray_to_str, to_text_string from spyder.utils import icon_manager as ima from spyder.utils import (codeanalysis, encoding, sourcecode, @@ -593,6 +593,10 @@ def __init__(self, parent, actions): # Reference to save msgbox and avoid memory to be freed. self.msgbox = None + # File types and filters used by the Save As dialog + self.edit_filetypes = None + self.edit_filters = None + @Slot() def show_in_external_file_explorer(self, fnames=None): """Show file in external file explorer""" @@ -1561,12 +1565,29 @@ def file_saved_in_other_editorstack(self, index, filename): finfo.lastmodified = QFileInfo(finfo.filename).lastModified() def select_savename(self, original_filename): + """Select a name to save a file.""" + if self.edit_filetypes is None: + self.edit_filetypes = get_edit_filetypes() + if self.edit_filters is None: + self.edit_filters = get_edit_filters() + + # Don't use filters on KDE to not make the dialog incredible + # slow + # Fixes issue 4156 + if is_kde_desktop() and not is_anaconda(): + filters = '' + selectedfilter = '' + else: + filters = self.edit_filters + selectedfilter = get_filter(self.edit_filetypes, + osp.splitext(original_filename)[1]) + self.redirect_stdio.emit(False) filename, _selfilter = getsavefilename(self, _("Save file"), - original_filename, - get_edit_filters(), - get_filter(get_edit_filetypes(), - osp.splitext(original_filename)[1])) + original_filename, + filters=filters, + selectedfilter=selectedfilter, + options=QFileDialog.HideNameFilterDetails) self.redirect_stdio.emit(True) if filename: return osp.normpath(filename)