def get_icon(name, default=None, resample=False): """Return image inside a QIcon object. default: default image name or icon resample: if True, manually resample icon pixmaps for usual sizes (16, 24, 32, 48, 96, 128, 256). This is recommended for QMainWindow icons created from SVG images on non-Windows platforms due to a Qt bug (see Issue 1314). """ icon_path = get_image_path(name, default=None) if icon_path is not None: icon = QIcon(icon_path) elif isinstance(default, QIcon): icon = default elif default is None: try: icon = get_std_icon(name[:-4]) except AttributeError: icon = QIcon(get_image_path(name, default)) else: icon = QIcon(get_image_path(name, default)) if resample: icon0 = QIcon() for size in (16, 24, 32, 48, 96, 128, 256, 512): icon0.addPixmap(icon.pixmap(size, size)) return icon0 else: return icon
def get_icon_by_extension(fname, scale_factor): """Return the icon depending on the file extension""" application_icons = {} application_icons.update(BIN_FILES) application_icons.update(DOCUMENT_FILES) if osp.isdir(fname): return icon('DirOpenIcon', scale_factor) else: basename = osp.basename(fname) __, extension = osp.splitext(basename.lower()) mime_type, __ = mime.guess_type(basename) icon_by_extension = icon('FileIcon', scale_factor) if extension in OFFICE_FILES: icon_by_extension = icon(OFFICE_FILES[extension], scale_factor) if extension in LANGUAGE_ICONS: icon_by_extension = icon(LANGUAGE_ICONS[extension], scale_factor) else: if extension == '.ipynb': if is_dark_interface(): icon_by_extension = QIcon( get_image_path('notebook_dark.svg')) else: icon_by_extension = QIcon( get_image_path('notebook_light.svg')) elif extension == '.tex': if is_dark_interface(): icon_by_extension = QIcon( get_image_path('file_type_tex.svg')) else: icon_by_extension = QIcon( get_image_path('file_type_light_tex.svg')) elif mime_type is not None: try: # Fix for issue 5080. Even though # mimetypes.guess_type documentation states that # the return value will be None or a tuple of # the form type/subtype, in the Windows registry, # .sql has a mimetype of text\plain # instead of text/plain therefore mimetypes is # returning it incorrectly. file_type, bin_name = mime_type.split('/') except ValueError: file_type = 'text' if file_type == 'text': icon_by_extension = icon('TextFileIcon', scale_factor) elif file_type == 'audio': icon_by_extension = icon('AudioFileIcon', scale_factor) elif file_type == 'video': icon_by_extension = icon('VideoFileIcon', scale_factor) elif file_type == 'image': icon_by_extension = icon('ImageFileIcon', scale_factor) elif file_type == 'application': if bin_name in application_icons: icon_by_extension = icon(application_icons[bin_name], scale_factor) return icon_by_extension
def get_icon_by_extension(fname, scale_factor): """Return the icon depending on the file extension""" application_icons = {} application_icons.update(BIN_FILES) application_icons.update(DOCUMENT_FILES) if osp.isdir(fname): return icon('DirOpenIcon', scale_factor) else: basename = osp.basename(fname) __, extension = osp.splitext(basename.lower()) mime_type, __ = mime.guess_type(basename) icon_by_extension = icon('FileIcon', scale_factor) if extension in OFFICE_FILES: icon_by_extension = icon(OFFICE_FILES[extension], scale_factor) if extension in LANGUAGE_ICONS: icon_by_extension = icon(LANGUAGE_ICONS[extension], scale_factor) else: if extension == '.ipynb': if is_dark_interface(): icon_by_extension = QIcon( get_image_path('notebook_dark.svg')) else: icon_by_extension = QIcon( get_image_path('notebook_light.svg')) elif mime_type is not None: try: # Fix for issue 5080. Even though # mimetypes.guess_type documentation states that # the return value will be None or a tuple of # the form type/subtype, in the Windows registry, # .sql has a mimetype of text\plain # instead of text/plain therefore mimetypes is # returning it incorrectly. file_type, bin_name = mime_type.split('/') except ValueError: file_type = 'text' if file_type == 'text': icon_by_extension = icon('TextFileIcon', scale_factor) elif file_type == 'audio': icon_by_extension = icon('AudioFileIcon', scale_factor) elif file_type == 'video': icon_by_extension = icon('VideoFileIcon', scale_factor) elif file_type == 'image': icon_by_extension = icon('ImageFileIcon', scale_factor) elif file_type == 'application': if bin_name in application_icons: icon_by_extension = icon( application_icons[bin_name], scale_factor) return icon_by_extension
def __init__(self, parent): super(KiteIntegrationInfo, self).__init__(parent) # Images images_layout = QHBoxLayout() if is_dark_interface(): icon_filename = 'spyder_kite.svg' else: icon_filename = 'spyder_kite_dark.svg' image_path = get_image_path(icon_filename) image = QPixmap(image_path) image_label = QLabel() screen = QApplication.primaryScreen() device_image_ratio = screen.devicePixelRatio() if device_image_ratio > 1: image.setDevicePixelRatio(device_image_ratio) else: image_height = image.height() * 0.5 image_width = image.width() * 0.5 image = image.scaled(image_width, image_height, Qt.KeepAspectRatio, Qt.SmoothTransformation) image_label.setPixmap(image) images_layout.addStretch() images_layout.addWidget(image_label) images_layout.addStretch() # Label integration_label = QLabel( _("Now Spyder can use <a href=\"{kite_url}\">Kite</a> to " "provide better and more accurate code completions in its " "editor <br>for the most important packages in the Python " "scientific ecosystem, such as Numpy, <br>Matplotlib and " "Pandas.<br><br>Would you like to install it or learn more " "about it?<br><br><i>Note:</i> Kite is free to use " "but is not an open source program.").format( kite_url=KITE_SPYDER_URL)) integration_label.setOpenExternalLinks(True) # Buttons buttons_layout = QHBoxLayout() learn_more_button = QPushButton(_('Learn more')) learn_more_button.setAutoDefault(False) install_button = QPushButton(_('Install Kite')) install_button.setAutoDefault(False) dismiss_button = QPushButton(_('Dismiss')) dismiss_button.setAutoDefault(False) buttons_layout.addStretch() buttons_layout.addWidget(install_button) buttons_layout.addWidget(learn_more_button) buttons_layout.addWidget(dismiss_button) general_layout = QVBoxLayout() general_layout.addLayout(images_layout) general_layout.addWidget(integration_label) general_layout.addLayout(buttons_layout) self.setLayout(general_layout) learn_more_button.clicked.connect(self.sig_learn_more_button_clicked) install_button.clicked.connect(self.sig_install_button_clicked) dismiss_button.clicked.connect(self.sig_dismiss_button_clicked)
def set_data(self, title, content, current, image, run, frames=None, step=None): """ """ self.label_title.setText(title) self.combo_title.clear() self.combo_title.addItems(frames) self.combo_title.setCurrentIndex(step) # min_content_len = max([len(f) for f in frames]) # self.combo_title.setMinimumContentsLength(min_content_len) # Fix and try to see how it looks with a combo box self.label_current.setText(current) self.button_current.setText(current) self.label_content.setText(content) self.image = image if image is None: self.label_image.setFixedHeight(1) self.label_image.setFixedWidth(1) else: extension = image.split('.')[-1] self.image = QPixmap(get_image_path(image), extension) self.label_image.setPixmap(self.image) self.label_image.setFixedSize(self.image.size()) if run is None: self.button_run.setVisible(False) else: self.button_run.setDisabled(False) self.button_run.setVisible(True) # Refresh layout self.layout().activate()
def __init__(self, parent): super(KiteWelcome, self).__init__(parent) self.setFixedHeight(350) # Left side install_info = QLabel( _("<big><b>Level up your completions with " "Kite</b></big><br><br>" "Kite is a native app that runs locally " "on your computer <br>and uses machine learning " "to provide advanced <br>completions.<br><br>" "✓ Specialized support for Python " "data analysis packages<br><br>" "✓ 1.5x more completions " "than the builtin engine<br><br>" "✓ Completions ranked by code context <br><br>" "✓ Full line code completions<br><br>" "✓ 100% local - no internet " "connection required<br><br>" "✓ 100% free to use<br><br>" "<a href=\"https://kite.com/spyder-integration\">" "Go to Kite website</a>")) install_info.setOpenExternalLinks(True) # Right side action_layout = QVBoxLayout() install_gif_source = get_image_path('kite.gif') install_gif = QMovie(install_gif_source) install_gif_label = QLabel() install_gif.start() install_image = install_gif.currentPixmap() image_height = install_image.height() * 0.8 image_width = install_image.width() * 0.8 install_gif.setScaledSize(QSize(image_width, image_height)) install_gif_label.setMovie(install_gif) button_layout = QHBoxLayout() install_button = QPushButton(_('Install Kite')) dismiss_button = QPushButton(_('Dismiss')) button_layout.addStretch() button_layout.addWidget(install_button) button_layout.addWidget(dismiss_button) button_layout.addStretch() action_layout.addWidget(install_gif_label) action_layout.addStretch() action_layout.addLayout(button_layout) # Layout general_layout = QHBoxLayout() general_layout.addWidget(install_info) general_layout.addLayout(action_layout) self.setLayout(general_layout) # Signals install_button.clicked.connect(self.sig_install_button_clicked) dismiss_button.clicked.connect(self.sig_dismiss_button_clicked)
def show_loading_message(self): """Create html page to show while the documentation is generated.""" loading_message = _("Retrieving documentation") loading_img = get_image_path('loading_sprites.png') if os.name == 'nt': loading_img = loading_img.replace('\\', '/') self.set_rich_text_html( loading(loading_message, loading_img, css_path=self.css_path), QUrl.fromLocalFile(self.css_path))
def show_loading_page(self): """Show a loading animation while the kernel is starting.""" loading_template = Template(LOADING) loading_img = get_image_path('loading_sprites.png') if os.name == 'nt': loading_img = loading_img.replace('\\', '/') message = _("Connecting to kernel...") page = loading_template.substitute(css_path=CSS_PATH, loading_img=loading_img, message=message) self.setHtml(page)
def _create_loading_page(self): """Create html page to show while the kernel is starting""" loading_template = Template(LOADING) loading_img = get_image_path('loading_sprites.png') if os.name == 'nt': loading_img = loading_img.replace('\\', '/') message = _("Connecting to kernel...") page = loading_template.substitute(css_path=self.css_path, loading_img=loading_img, message=message) return page
def _create_loading_page(self): """Create html page to show while the kernel is starting""" loading_template = Template(LOADING) loading_img = get_image_path('loading_sprites.png') if os.name == 'nt': loading_img = loading_img.replace('\\', '/') message = _("Connecting to kernel...") page = loading_template.substitute(css_path=CSS_PATH, loading_img=loading_img, message=message) return page
def create_splash_screen(): """Create splash screen.""" if not running_under_pytest(): splash = QSplashScreen(QPixmap(get_image_path('splash.svg'))) splash_font = splash.font() splash_font.setPixelSize(10) splash.setFont(splash_font) else: splash = None return splash
def get_kite_icon(scale_factor=0.85): """Return the Kite logo taking into account the theme of the interface.""" icon_path = 'kite_light.svg' if is_dark_interface(): icon_path = 'kite_dark.svg' pixmap = QPixmap(get_image_path(icon_path)) if scale_factor is not None: pixmap_height = 16 * scale_factor pixmap_width = 16 * scale_factor pixmap = pixmap.scaled(pixmap_width, pixmap_height, aspectRatioMode=Qt.KeepAspectRatio, transformMode=Qt.SmoothTransformation) kite_icon = QIcon(pixmap) return kite_icon
def __init__(self): super(Restarter, self).__init__() self.ellipsis = ['', '.', '..', '...', '..', '.'] # Widgets self.timer_ellipsis = QTimer(self) self.splash = QSplashScreen(QPixmap(get_image_path('splash.svg'), 'svg')) # Widget setup self.setVisible(False) font = self.splash.font() font.setPixelSize(10) self.splash.setFont(font) self.splash.show() self.timer_ellipsis.timeout.connect(self.animate_ellipsis)
def __init__(self): super(Restarter, self).__init__() self.ellipsis = ['', '.', '..', '...', '..', '.'] # Widgets self.timer_ellipsis = QTimer(self) self.splash = QSplashScreen( QPixmap(get_image_path('splash.svg'), 'svg')) # Widget setup self.setVisible(False) font = self.splash.font() font.setPixelSize(10) self.splash.setFont(font) self.splash.show() self.timer_ellipsis.timeout.connect(self.animate_ellipsis)
def __init__(self, parent): """Create About Spyder dialog with general information.""" QDialog.__init__(self, parent) versions = get_versions() # Show Git revision for development version revlink = '' if versions['revision']: rev = versions['revision'] revlink = " (<a href='https://github.com/spyder-ide/spyder/" \ "commit/%s'>Commit: %s</a>)" % (rev, rev) # Get current font properties font = self.font() font_family = font.family() font_size = font.pointSize() if sys.platform == 'darwin': font_size -= 2 self.label = QLabel( _(""" <div style='font-family: "{font_family}"; font-size: {font_size}pt; font-weight: normal; '> <p> <b>Spyder {spyder_ver}</b> {revision} <br> The Scientific Python Development Environment | <a href="{website_url}">Spyder-IDE.org</a> <br> Copyright © 2009-2020 Spyder Project Contributors and <a href="{github_url}/blob/master/AUTHORS.txt">others</a>. <br> Distributed under the terms of the <a href="{github_url}/blob/master/LICENSE.txt">MIT License</a>. </p> <p> Created by Pierre Raybaut; current maintainer is Carlos Cordoba. Developed by the <a href="{github_url}/graphs/contributors">international Spyder community</a>. Many thanks to all the Spyder beta testers and dedicated users. </p> <p>For help with Spyder errors and crashes, please read our <a href="{trouble_url}">Troubleshooting Guide</a>, and for bug reports and feature requests, visit our <a href="{github_url}">Github site</a>. For project discussion, see our <a href="{forum_url}">Google Group</a>. </p> <p> This project is part of a larger effort to promote and facilitate the use of Python for scientific and engineering software development. The popular Python distributions <a href="https://www.anaconda.com/download/">Anaconda</a> and <a href="https://winpython.github.io/">WinPython</a> also contribute to this plan. </p> <p> Python {python_ver} {bitness}-bit | Qt {qt_ver} | {qt_api} {qt_api_ver} | {os_name} {os_ver} </p> <p><small>Certain source files under other compatible permissive licenses and/or originally by other authors. Spyder 3 theme icons derived from <a href="https://fontawesome.com/">Font Awesome</a> 4.7 (© 2016 David Gandy; SIL OFL 1.1) and <a href="http://materialdesignicons.com/">Material Design</a> (© 2014 Austin Andrews; SIL OFL 1.1). Most Spyder 2 theme icons sourced from the <a href="https://www.everaldo.com">Crystal Project iconset</a> (© 2006-2007 Everaldo Coelho; LGPL 2.1+). Other icons from <a href="http://p.yusukekamiyamane.com/">Yusuke Kamiyamane</a> (© 2013 Yusuke Kamiyamane; CC-BY 3.0), the <a href="http://www.famfamfam.com/lab/icons/silk/">FamFamFam Silk icon set</a> 1.3 (© 2006 Mark James; CC-BY 2.5), and the <a href="https://www.kde.org/">KDE Oxygen icons</a> (© 2007 KDE Artists; LGPL 3.0+).</small> </p> <p> See the <a href="{github_url}/blob/master/NOTICE.txt">NOTICE</a> file for full legal information. </p> </div> """.format( spyder_ver=versions['spyder'], revision=revlink, website_url=__website_url__, github_url=__project_url__, trouble_url=__trouble_url__, forum_url=__forum_url__, python_ver=versions['python'], bitness=versions['bitness'], qt_ver=versions['qt'], qt_api=versions['qt_api'], qt_api_ver=versions['qt_api_ver'], os_name=versions['system'], os_ver=versions['release'], font_family=font_family, font_size=font_size, ))) self.label.setWordWrap(True) self.label.setAlignment(Qt.AlignTop) self.label.setOpenExternalLinks(True) if is_dark_interface(): icon_filename = "spyder.svg" else: icon_filename = "spyder_dark.svg" pixmap = QPixmap(get_image_path(icon_filename)) self.label_pic = QLabel(self) self.label_pic.setPixmap(pixmap.scaled(64, 64)) self.label_pic.setAlignment(Qt.AlignTop) btn = QPushButton(_("Copy to clipboard"), ) bbox = QDialogButtonBox(QDialogButtonBox.Ok) # Widget setup self.setWindowIcon(ima.icon('tooloptions')) self.setModal(False) # Layout tophlayout = QHBoxLayout() tophlayout.addWidget(self.label_pic) tophlayout.addWidget(self.label) btmhlayout = QHBoxLayout() btmhlayout.addWidget(btn) btmhlayout.addStretch() btmhlayout.addWidget(bbox) vlayout = QVBoxLayout() vlayout.addLayout(tophlayout) vlayout.addLayout(btmhlayout) self.setLayout(vlayout) self.setFixedSize(410, 560) # Signals btn.clicked.connect(self.copy_to_clipboard) bbox.accepted.connect(self.accept)
def __init__(self, parent, opacity, duration, easing_curve, tour=None): super(FadingTipBox, self).__init__(parent, opacity, duration, easing_curve) self.holder = self.anim # needed for qt to work self.parent = parent self.tour = tour self.frames = None self.color_top = QColor.fromRgb(230, 230, 230) self.color_back = QColor.fromRgb(255, 255, 255) self.offset_shadow = 0 self.fixed_width = 300 self.key_pressed = None self.setAttribute(Qt.WA_TranslucentBackground) self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setModal(False) # Widgets def toolbutton(icon): bt = QToolButton() bt.setAutoRaise(True) bt.setIcon(icon) return bt self.button_close = toolbutton(ima.icon("tour.close")) self.button_home = toolbutton(ima.icon("tour.home")) self.button_previous = toolbutton(ima.icon("tour.previous")) self.button_end = toolbutton(ima.icon("tour.end")) self.button_next = toolbutton(ima.icon("tour.next")) self.button_run = QPushButton(_('Run code')) self.button_disable = None self.button_current = QToolButton() self.label_image = QLabel() self.label_title = QLabel() self.combo_title = QComboBox() self.label_current = QLabel() self.label_content = QLabel() self.label_content.setMinimumWidth(self.fixed_width) self.label_content.setMaximumWidth(self.fixed_width) self.label_current.setAlignment(Qt.AlignCenter) self.label_content.setWordWrap(True) self.widgets = [self.label_content, self.label_title, self.label_current, self.combo_title, self.button_close, self.button_run, self.button_next, self.button_previous, self.button_end, self.button_home, self.button_current] arrow = get_image_path('hide.png') self.stylesheet = '''QComboBox { padding-left: 5px; background-color: rgbs(230,230,230,100%); border-width: 0px; border-radius: 0px; min-height:20px; max-height:20px; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top left; border-width: 0px; } QComboBox::down-arrow { image: url(''' + arrow + '''); } ''' # Windows fix, slashes should be always in unix-style self.stylesheet = self.stylesheet.replace('\\', '/') self.setFocusPolicy(Qt.StrongFocus) for widget in self.widgets: widget.setFocusPolicy(Qt.NoFocus) widget.setStyleSheet(self.stylesheet) layout_top = QHBoxLayout() layout_top.addWidget(self.combo_title) layout_top.addStretch() layout_top.addWidget(self.button_close) layout_top.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_content = QHBoxLayout() layout_content.addWidget(self.label_content) layout_content.addWidget(self.label_image) layout_content.addSpacerItem(QSpacerItem(5, 5)) layout_run = QHBoxLayout() layout_run.addStretch() layout_run.addWidget(self.button_run) layout_run.addStretch() layout_run.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_navigation = QHBoxLayout() layout_navigation.addWidget(self.button_home) layout_navigation.addWidget(self.button_previous) layout_navigation.addStretch() layout_navigation.addWidget(self.label_current) layout_navigation.addStretch() layout_navigation.addWidget(self.button_next) layout_navigation.addWidget(self.button_end) layout_navigation.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout = QVBoxLayout() layout.addLayout(layout_top) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_content) layout.addLayout(layout_run) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_navigation) layout.addSpacerItem(QSpacerItem(self.offset_shadow, self.offset_shadow)) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.set_funcs_before_fade_in([self._disable_widgets]) self.set_funcs_after_fade_in([self._enable_widgets, self.setFocus]) self.set_funcs_before_fade_out([self._disable_widgets]) self.setContextMenuPolicy(Qt.CustomContextMenu)
def __init__(self, parent, opacity, duration, easing_curve, tour=None): super(FadingTipBox, self).__init__(parent, opacity, duration, easing_curve) self.holder = self.anim # needed for qt to work self.parent = parent self.tour = tour self.frames = None self.color_top = QColor.fromRgb(230, 230, 230) self.color_back = QColor.fromRgb(255, 255, 255) self.offset_shadow = 0 self.fixed_width = 300 self.key_pressed = None self.setAttribute(Qt.WA_TranslucentBackground) self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setModal(False) # Widgets self.button_home = QPushButton("<<") self.button_close = QPushButton("X") self.button_previous = QPushButton(" < ") self.button_end = QPushButton(">>") self.button_next = QPushButton(" > ") self.button_run = QPushButton(_('Run code')) self.button_disable = None self.button_current = QToolButton() self.label_image = QLabel() self.label_title = QLabel() self.combo_title = QComboBox() self.label_current = QLabel() self.label_content = QLabel() self.label_content.setMinimumWidth(self.fixed_width) self.label_content.setMaximumWidth(self.fixed_width) self.label_current.setAlignment(Qt.AlignCenter) self.label_content.setWordWrap(True) self.widgets = [ self.label_content, self.label_title, self.label_current, self.combo_title, self.button_close, self.button_run, self.button_next, self.button_previous, self.button_end, self.button_home, self.button_current ] arrow = get_image_path('hide.png') self.stylesheet = '''QPushButton { background-color: rgbs(200,200,200,100%); color: rgbs(0,0,0,100%); border-style: outset; border-width: 1px; border-radius: 3px; border-color: rgbs(100,100,100,100%); padding: 2px; } QPushButton:hover { background-color: rgbs(150, 150, 150, 100%); } QPushButton:disabled { background-color: rgbs(230,230,230,100%); color: rgbs(200,200,200,100%); border-color: rgbs(200,200,200,100%); } QComboBox { padding-left: 5px; background-color: rgbs(230,230,230,100%); border-width: 0px; border-radius: 0px; min-height:20px; max-height:20px; } QComboBox::drop-down { subcontrol-origin: padding; subcontrol-position: top left; border-width: 0px; } QComboBox::down-arrow { image: url(''' + arrow + '''); } ''' # Windows fix, slashes should be always in unix-style self.stylesheet = self.stylesheet.replace('\\', '/') self.setFocusPolicy(Qt.StrongFocus) for widget in self.widgets: widget.setFocusPolicy(Qt.NoFocus) widget.setStyleSheet(self.stylesheet) layout_top = QHBoxLayout() layout_top.addWidget(self.combo_title) layout_top.addStretch() layout_top.addWidget(self.button_close) layout_top.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_content = QHBoxLayout() layout_content.addWidget(self.label_content) layout_content.addWidget(self.label_image) layout_content.addSpacerItem(QSpacerItem(5, 5)) layout_run = QHBoxLayout() layout_run.addStretch() layout_run.addWidget(self.button_run) layout_run.addStretch() layout_run.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_navigation = QHBoxLayout() layout_navigation.addWidget(self.button_home) layout_navigation.addWidget(self.button_previous) layout_navigation.addStretch() layout_navigation.addWidget(self.label_current) layout_navigation.addStretch() layout_navigation.addWidget(self.button_next) layout_navigation.addWidget(self.button_end) layout_navigation.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout = QVBoxLayout() layout.addLayout(layout_top) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_content) layout.addLayout(layout_run) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_navigation) layout.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.set_funcs_before_fade_in([self._disable_widgets]) self.set_funcs_after_fade_in([self._enable_widgets, self.setFocus]) self.set_funcs_before_fade_out([self._disable_widgets]) self.setContextMenuPolicy(Qt.CustomContextMenu)
def get_image_label(name, default="not_found.png"): """Return image inside a QLabel object""" label = QLabel() label.setPixmap(QPixmap(get_image_path(name, default))) return label
def main(): #========================================================================== # Proper high DPI scaling is available in Qt >= 5.6.0. This attibute must # be set before creating the application. #========================================================================== if CONF.get('main', 'high_dpi_custom_scale_factor'): factors = str(CONF.get('main', 'high_dpi_custom_scale_factors')) f = list(filter(None, factors.split(';'))) if len(f) == 1: os.environ['QT_SCALE_FACTOR'] = f[0] else: os.environ['QT_SCREEN_SCALE_FACTORS'] = factors else: os.environ['QT_SCALE_FACTOR'] = '' os.environ['QT_SCREEN_SCALE_FACTORS'] = '' # Splash screen # ------------------------------------------------------------------------- # Start Qt Splash to inform the user of the current status app = qapplication() restarter = Restarter() if PYQT5: APP_ICON = QIcon(get_image_path("spyder.svg")) else: APP_ICON = QIcon(get_image_path("spyder.png")) app.setWindowIcon(APP_ICON) restarter.set_splash_message(_('Closing Spyder')) # Get variables # Note: Variables defined in app/mainwindow.py 'restart()' method spyder_args = os.environ.pop('SPYDER_ARGS', None) pid = os.environ.pop('SPYDER_PID', None) is_bootstrap = os.environ.pop('SPYDER_IS_BOOTSTRAP', None) reset = os.environ.pop('SPYDER_RESET', None) # Get the spyder base folder based on this file this_folder = osp.split(osp.dirname(osp.abspath(__file__)))[0] spyder_folder = osp.split(this_folder)[0] if not any([spyder_args, pid, is_bootstrap, reset]): error = "This script can only be called from within a Spyder instance" raise RuntimeError(error) # Variables were stored as string literals in the environment, so to use # them we need to parse them in a safe manner. is_bootstrap = ast.literal_eval(is_bootstrap) pid = ast.literal_eval(pid) args = ast.literal_eval(spyder_args) reset = ast.literal_eval(reset) # Enforce the --new-instance flag when running spyder if '--new-instance' not in args: if is_bootstrap and '--' not in args: args = args + ['--', '--new-instance'] else: args.append('--new-instance') # Create the arguments needed for reseting if '--' in args: args_reset = ['--', '--reset'] else: args_reset = ['--reset'] # Arrange arguments to be passed to the restarter and reset subprocess args = ' '.join(args) args_reset = ' '.join(args_reset) # Get python excutable running this script python = sys.executable # Build the command if is_bootstrap: spyder = osp.join(spyder_folder, 'bootstrap.py') else: spyderdir = osp.join(spyder_folder, 'spyder') spyder = osp.join(spyderdir, 'app', 'start.py') command = '"{0}" "{1}" {2}'.format(python, spyder, args) # Adjust the command and/or arguments to subprocess depending on the OS shell = not IS_WINDOWS # Before launching a new Spyder instance we need to make sure that the # previous one has closed. We wait for a fixed and "reasonable" amount of # time and check, otherwise an error is launched wait_time = 90 if IS_WINDOWS else 30 # Seconds for counter in range(int(wait_time / SLEEP_TIME)): if not is_pid_running(pid): break time.sleep(SLEEP_TIME) # Throttling control QApplication.processEvents() # Needed to refresh the splash else: # The old spyder instance took too long to close and restart aborts restarter.launch_error_message(error_type=CLOSE_ERROR) env = os.environ.copy() # Reset Spyder (if required) # ------------------------------------------------------------------------- if reset: restarter.set_splash_message(_('Resetting Spyder to defaults')) command_reset = '"{0}" "{1}" {2}'.format(python, spyder, args_reset) try: p = subprocess.Popen(command_reset, shell=shell, env=env) except Exception as error: restarter.launch_error_message(error_type=RESET_ERROR, error=error) else: p.communicate() pid_reset = p.pid # Before launching a new Spyder instance we need to make sure that the # reset subprocess has closed. We wait for a fixed and "reasonable" # amount of time and check, otherwise an error is launched. wait_time = 20 # Seconds for counter in range(int(wait_time / SLEEP_TIME)): if not is_pid_running(pid_reset): break time.sleep(SLEEP_TIME) # Throttling control QApplication.processEvents() # Needed to refresh the splash else: # The reset subprocess took too long and it is killed try: p.kill() except OSError as error: restarter.launch_error_message(error_type=RESET_ERROR, error=error) else: restarter.launch_error_message(error_type=RESET_ERROR) # Restart # ------------------------------------------------------------------------- restarter.set_splash_message(_('Restarting')) try: subprocess.Popen(command, shell=shell, env=env) except Exception as error: restarter.launch_error_message(error_type=RESTART_ERROR, error=error)
Taken from the QCrash Project: https://github.com/ColinDuquesnoy/QCrash """ import sys from qtpy.QtCore import QEvent, Qt, QSize from qtpy.QtWidgets import (QDialog, QFormLayout, QLabel, QLineEdit, QPushButton, QTabWidget, QVBoxLayout, QWidget) from spyder.config.base import _ from spyder.config.base import get_image_path from spyder.py3compat import to_text_string GH_MARK_NORMAL = get_image_path('GitHub-Mark.png') GH_MARK_LIGHT = get_image_path('GitHub-Mark-Light.png') class DlgGitHubLogin(QDialog): """Dialog to submit error reports to Github.""" def __init__(self, parent, username): super(DlgGitHubLogin, self).__init__(parent) title = _("Sign in to Github") self.resize(366, 248) self.setWindowTitle(title) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) # Header
def main(): #========================================================================== # Proper high DPI scaling is available in Qt >= 5.6.0. This attibute must # be set before creating the application. #========================================================================== if CONF.get('main', 'high_dpi_custom_scale_factor'): factors = str(CONF.get('main', 'high_dpi_custom_scale_factors')) f = list(filter(None, factors.split(';'))) if len(f) == 1: os.environ['QT_SCALE_FACTOR'] = f[0] else: os.environ['QT_SCREEN_SCALE_FACTORS'] = factors else: os.environ['QT_SCALE_FACTOR'] = '' os.environ['QT_SCREEN_SCALE_FACTORS'] = '' # Splash screen # ------------------------------------------------------------------------- # Start Qt Splash to inform the user of the current status app = qapplication() restarter = Restarter() if PYQT5: APP_ICON = QIcon(get_image_path("spyder.svg")) else: APP_ICON = QIcon(get_image_path("spyder.png")) app.setWindowIcon(APP_ICON) restarter.set_splash_message(_('Closing Spyder')) # Get variables # Note: Variables defined in app/spyder.py 'restart()' method spyder_args = os.environ.pop('SPYDER_ARGS', None) pid = os.environ.pop('SPYDER_PID', None) is_bootstrap = os.environ.pop('SPYDER_IS_BOOTSTRAP', None) reset = os.environ.pop('SPYDER_RESET', None) # Get the spyder base folder based on this file this_folder = osp.split(osp.dirname(osp.abspath(__file__)))[0] spyder_folder = osp.split(this_folder)[0] if not any([spyder_args, pid, is_bootstrap, reset]): error = "This script can only be called from within a Spyder instance" raise RuntimeError(error) # Variables were stored as string literals in the environment, so to use # them we need to parse them in a safe manner. is_bootstrap = ast.literal_eval(is_bootstrap) pid = ast.literal_eval(pid) args = ast.literal_eval(spyder_args) reset = ast.literal_eval(reset) # Enforce the --new-instance flag when running spyder if '--new-instance' not in args: if is_bootstrap and '--' not in args: args = args + ['--', '--new-instance'] else: args.append('--new-instance') # Create the arguments needed for reseting if '--' in args: args_reset = ['--', '--reset'] else: args_reset = ['--reset'] # Arrange arguments to be passed to the restarter and reset subprocess args = ' '.join(args) args_reset = ' '.join(args_reset) # Get python excutable running this script python = sys.executable # Build the command if is_bootstrap: spyder = osp.join(spyder_folder, 'bootstrap.py') else: spyderdir = osp.join(spyder_folder, 'spyder') spyder = osp.join(spyderdir, 'app', 'start.py') command = '"{0}" "{1}" {2}'.format(python, spyder, args) # Adjust the command and/or arguments to subprocess depending on the OS shell = not IS_WINDOWS # Before launching a new Spyder instance we need to make sure that the # previous one has closed. We wait for a fixed and "reasonable" amount of # time and check, otherwise an error is launched wait_time = 90 if IS_WINDOWS else 30 # Seconds for counter in range(int(wait_time/SLEEP_TIME)): if not is_pid_running(pid): break time.sleep(SLEEP_TIME) # Throttling control QApplication.processEvents() # Needed to refresh the splash else: # The old spyder instance took too long to close and restart aborts restarter.launch_error_message(error_type=CLOSE_ERROR) env = os.environ.copy() # Reset Spyder (if required) # ------------------------------------------------------------------------- if reset: restarter.set_splash_message(_('Resetting Spyder to defaults')) command_reset = '"{0}" "{1}" {2}'.format(python, spyder, args_reset) try: p = subprocess.Popen(command_reset, shell=shell, env=env) except Exception as error: restarter.launch_error_message(error_type=RESET_ERROR, error=error) else: p.communicate() pid_reset = p.pid # Before launching a new Spyder instance we need to make sure that the # reset subprocess has closed. We wait for a fixed and "reasonable" # amount of time and check, otherwise an error is launched. wait_time = 20 # Seconds for counter in range(int(wait_time/SLEEP_TIME)): if not is_pid_running(pid_reset): break time.sleep(SLEEP_TIME) # Throttling control QApplication.processEvents() # Needed to refresh the splash else: # The reset subprocess took too long and it is killed try: p.kill() except OSError as error: restarter.launch_error_message(error_type=RESET_ERROR, error=error) else: restarter.launch_error_message(error_type=RESET_ERROR) # Restart # ------------------------------------------------------------------------- restarter.set_splash_message(_('Restarting')) try: subprocess.Popen(command, shell=shell, env=env) except Exception as error: restarter.launch_error_message(error_type=RESTART_ERROR, error=error)
def get_kite_icon(): """Return the Kite logo taking into account the theme of the interface.""" icon_path = 'kite_dark.svg' if is_dark_interface() else 'kite_light.svg' return QIcon(get_image_path(icon_path))
def __init__(self, parent): super(KiteIntegrationInfo, self).__init__(parent) # Images images_layout = QHBoxLayout() icon_filename = 'kite_completions.png' image_path = get_image_path(icon_filename) image = QPixmap(image_path) image_label = QLabel() screen = QApplication.primaryScreen() image_label = QLabel() image_height = int(image.height() * self.ICON_SCALE_FACTOR) image_width = int(image.width() * self.ICON_SCALE_FACTOR) image = image.scaled(image_width, image_height, Qt.KeepAspectRatio, Qt.SmoothTransformation) image_label.setPixmap(image) images_layout.addStretch() images_layout.addWidget(image_label) images_layout.addStretch() ilayout = QHBoxLayout() ilayout.addLayout(images_layout) # Label integration_label_title = QLabel( "Get better code completions in Spyder") integration_label_title.setStyleSheet( f"font-size: {self.TITLE_FONT_SIZE}") integration_label_title.setWordWrap(True) integration_label = QLabel( _("Now Spyder can use Kite to provide better code " "completions for key packages in the scientific Python " "Ecosystem. Install Kite for a better editor experience in " "Spyder. <br><br>Kite is free to use but is not open " "source. <a href=\"{kite_url}\">Learn more about Kite </a>"). format(kite_url=KITE_SPYDER_URL)) integration_label.setStyleSheet(f"font-size: {self.CONTENT_FONT_SIZE}") integration_label.setOpenExternalLinks(True) integration_label.setWordWrap(True) integration_label.setFixedWidth(360) label_layout = QVBoxLayout() label_layout.addWidget(integration_label_title) label_layout.addWidget(integration_label) # Buttons buttons_layout = QHBoxLayout() install_button = QPushButton(_('Install Kite')) install_button.setAutoDefault(False) install_button.setStyleSheet("background-color: #3775A9;" f"font-size: {self.BUTTONS_FONT_SIZE};" f"padding: {self.BUTTONS_PADDING}") dismiss_button = QPushButton(_('Dismiss')) dismiss_button.setAutoDefault(False) dismiss_button.setStyleSheet("background-color: #60798B;" f"font-size: {self.BUTTONS_FONT_SIZE};" f"padding: {self.BUTTONS_PADDING}") buttons_layout.addStretch() buttons_layout.addWidget(install_button) if not MAC: buttons_layout.addSpacing(10) buttons_layout.addWidget(dismiss_button) # Buttons with label vertical_layout = QVBoxLayout() if not MAC: vertical_layout.addStretch() vertical_layout.addLayout(label_layout) vertical_layout.addSpacing(20) vertical_layout.addLayout(buttons_layout) vertical_layout.addStretch() else: vertical_layout.addLayout(label_layout) vertical_layout.addLayout(buttons_layout) general_layout = QHBoxLayout() general_layout.addStretch() general_layout.addLayout(ilayout) general_layout.addSpacing(15) general_layout.addLayout(vertical_layout) general_layout.addStretch() self.setLayout(general_layout) # Signals install_button.clicked.connect(self.sig_install_button_clicked) dismiss_button.clicked.connect(self.sig_dismiss_button_clicked) if is_dark_interface(): self.setStyleSheet("background-color: #262E38") self.setContentsMargins(18, 40, 18, 40) if not MAC: self.setFixedSize(800, 350)
def __init__(self, parent, opacity, duration, easing_curve, tour=None, color_top=None, color_back=None, combobox_background=None): super(FadingTipBox, self).__init__(parent, opacity, duration, easing_curve) self.holder = self.anim # needed for qt to work self.parent = parent self.tour = tour self.frames = None self.offset_shadow = 0 self.fixed_width = 300 self.key_pressed = None self.setAttribute(Qt.WA_TranslucentBackground) self.setWindowFlags(Qt.Dialog | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.setModal(False) # Widgets def toolbutton(icon): bt = QToolButton() bt.setAutoRaise(True) bt.setIcon(icon) return bt self.button_close = toolbutton(ima.icon("tour.close")) self.button_home = toolbutton(ima.icon("tour.home")) self.button_previous = toolbutton(ima.icon("tour.previous")) self.button_end = toolbutton(ima.icon("tour.end")) self.button_next = toolbutton(ima.icon("tour.next")) self.button_run = QPushButton(_('Run code')) self.button_disable = None self.button_current = QToolButton() self.label_image = QLabel() self.label_title = QLabel() self.combo_title = QComboBox() self.label_current = QLabel() self.label_content = QLabel() self.label_content.setMinimumWidth(self.fixed_width) self.label_content.setMaximumWidth(self.fixed_width) self.label_current.setAlignment(Qt.AlignCenter) self.label_content.setWordWrap(True) self.widgets = [ self.label_content, self.label_title, self.label_current, self.combo_title, self.button_close, self.button_run, self.button_next, self.button_previous, self.button_end, self.button_home, self.button_current ] arrow = get_image_path('hide.png') self.color_top = color_top self.color_back = color_back self.combobox_background = combobox_background self.stylesheet = '''QComboBox {{ padding-left: 5px; background-color: {} border-width: 0px; border-radius: 0px; min-height:20px; max-height:20px; }} QComboBox::drop-down {{ subcontrol-origin: padding; subcontrol-position: top left; border-width: 0px; }} QComboBox::down-arrow {{ image: url({}); }} '''.format(self.combobox_background.name(), arrow) # Windows fix, slashes should be always in unix-style self.stylesheet = self.stylesheet.replace('\\', '/') self.setFocusPolicy(Qt.StrongFocus) for widget in self.widgets: widget.setFocusPolicy(Qt.NoFocus) widget.setStyleSheet(self.stylesheet) layout_top = QHBoxLayout() layout_top.addWidget(self.combo_title) layout_top.addStretch() layout_top.addWidget(self.button_close) layout_top.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_content = QHBoxLayout() layout_content.addWidget(self.label_content) layout_content.addWidget(self.label_image) layout_content.addSpacerItem(QSpacerItem(5, 5)) layout_run = QHBoxLayout() layout_run.addStretch() layout_run.addWidget(self.button_run) layout_run.addStretch() layout_run.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout_navigation = QHBoxLayout() layout_navigation.addWidget(self.button_home) layout_navigation.addWidget(self.button_previous) layout_navigation.addStretch() layout_navigation.addWidget(self.label_current) layout_navigation.addStretch() layout_navigation.addWidget(self.button_next) layout_navigation.addWidget(self.button_end) layout_navigation.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout = QVBoxLayout() layout.addLayout(layout_top) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_content) layout.addLayout(layout_run) layout.addStretch() layout.addSpacerItem(QSpacerItem(15, 15)) layout.addLayout(layout_navigation) layout.addSpacerItem( QSpacerItem(self.offset_shadow, self.offset_shadow)) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.set_funcs_before_fade_in([self._disable_widgets]) self.set_funcs_after_fade_in([self._enable_widgets, self.setFocus]) self.set_funcs_before_fade_out([self._disable_widgets]) self.setContextMenuPolicy(Qt.CustomContextMenu)
def __init__(self, parent): super(KiteInstallation, self).__init__(parent) # Left side action_layout = QVBoxLayout() progress_layout = QHBoxLayout() self._progress_widget = QWidget(self) self._progress_widget.setFixedHeight(50) self._progress_filter = HoverEventFilter() self._progress_bar = QProgressBar(self) self._progress_bar.setFixedWidth(180) self._progress_widget.installEventFilter(self._progress_filter) self.cancel_button = QPushButton() self.cancel_button.setIcon(ima.icon('DialogCloseButton')) self.cancel_button.hide() progress_layout.addWidget(self._progress_bar, alignment=Qt.AlignLeft) progress_layout.addWidget(self.cancel_button) self._progress_widget.setLayout(progress_layout) self._progress_label = QLabel(_('Downloading')) install_info = QLabel( _("Kite comes with a native app called the Copilot <br>" "which provides you with real time <br>" "documentation as you code.<br><br>" "When Kite is done installing, the Copilot will <br>" "launch automatically and guide you throught the <br>" "rest of the setup process.")) button_layout = QHBoxLayout() self.ok_button = QPushButton(_('OK')) button_layout.addStretch() button_layout.addWidget(self.ok_button) button_layout.addStretch() action_layout.addStretch() action_layout.addWidget(self._progress_label) action_layout.addWidget(self._progress_widget) action_layout.addWidget(install_info) action_layout.addSpacing(10) action_layout.addLayout(button_layout) action_layout.addStretch() # Right side copilot_image_source = get_image_path('kite_copilot.png') copilot_image = QPixmap(copilot_image_source) copilot_label = QLabel() screen = QApplication.primaryScreen() device_pixel_ratio = screen.devicePixelRatio() if device_pixel_ratio > 1: copilot_image.setDevicePixelRatio(device_pixel_ratio) copilot_label.setPixmap(copilot_image) else: image_height = int(copilot_image.height() * 0.4) image_width = int(copilot_image.width() * 0.4) copilot_label.setPixmap( copilot_image.scaled(image_width, image_height, Qt.KeepAspectRatio, Qt.SmoothTransformation)) # Layout general_layout = QHBoxLayout() general_layout.addLayout(action_layout) general_layout.addWidget(copilot_label) self.setLayout(general_layout) # Signals self._progress_filter.sig_hover_enter.connect( lambda: self.cancel_button.show()) self._progress_filter.sig_hover_leave.connect( lambda: self.cancel_button.hide())