def create_splash_screen(): """Create splash screen.""" if not running_under_pytest(): splash = QSplashScreen(QPixmap(get_image_path('splash'))) splash_font = splash.font() splash_font.setPixelSize(14) splash.setFont(splash_font) else: splash = None return splash
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') 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 show_loading_message(self): """Create html page to show while the documentation is generated.""" self.sig_render_started.emit() loading_message = _("Retrieving documentation") loading_img = get_image_path('loading_sprites') 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 create_application(): """Create application and patch sys.exit.""" # Our QApplication app = qapplication() # --- Set application icon app_icon = QIcon(get_image_path("spyder")) app.setWindowIcon(app_icon) # Required for correct icon on GNOME/Wayland: if hasattr(app, 'setDesktopFileName'): app.setDesktopFileName('spyder') # ---- Monkey patching QApplication class FakeQApplication(QApplication): """Spyder's fake QApplication""" def __init__(self, args): self = app # analysis:ignore @staticmethod def exec_(): """Do nothing because the Qt mainloop is already running""" pass from qtpy import QtWidgets QtWidgets.QApplication = FakeQApplication # ---- Monkey patching sys.exit def fake_sys_exit(arg=[]): pass sys.exit = fake_sys_exit # ---- Monkey patching sys.excepthook to avoid crashes in PyQt 5.5+ def spy_excepthook(type_, value, tback): sys.__excepthook__(type_, value, tback) if running_installer_test(): # This will exit Spyder with exit code 1 without invoking # macOS system dialogue window. raise SystemExit(1) sys.excepthook = spy_excepthook # Removing arguments from sys.argv as in standard Python interpreter sys.argv = [''] return app
def __init__(self): super(Restarter, self).__init__() self.ellipsis = ['', '.', '..', '...', '..', '.'] # Widgets self.timer_ellipsis = QTimer(self) self.splash = QSplashScreen(QPixmap(get_image_path('splash'), '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 get_icon(self, name, 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 spyder-ide/spyder#1314. """ icon_path = get_image_path(name) icon = QIcon(icon_path) 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(self, name, resample=False): """Return image inside a QIcon object. Parameters ---------- name: str Image name or icon resample: bool 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 spyder-ide/spyder#1314. """ icon_path = get_image_path(name) if resample: # This only applies to the Spyder 2 icons icon = QIcon(icon_path) icon0 = QIcon() for size in (16, 24, 32, 48, 96, 128, 256, 512): icon0.addPixmap(icon.pixmap(size, size)) return icon0 else: icon = QIcon() # Normal state normal_state = QPixmap(icon_path) icon.addPixmap(normal_state, QIcon.Normal) # This is the color GammaRay reports for icons in disabled # buttons, both for the dark and light themes disabled_color = QColor(150, 150, 150) # Paint icon with the previous color to get the disabled state. # Taken from https://stackoverflow.com/a/65618075/438386 disabled_state = QPixmap(icon_path) qp = QPainter(disabled_state) qp.setCompositionMode(QPainter.CompositionMode_SourceIn) qp.fillRect(disabled_state.rect(), disabled_color) qp.end() icon.addPixmap(disabled_state, QIcon.Disabled) return icon
def create_splash_screen(): """Create splash screen.""" if not running_under_pytest(): image = QImage(500, 400, QImage.Format_ARGB32_Premultiplied) image.fill(0) painter = QPainter(image) renderer = QSvgRenderer(get_image_path('splash')) renderer.render(painter) painter.end() pm = QPixmap.fromImage(image) pm = pm.copy(0, 0, 500, 400) splash = QSplashScreen(pm) splash_font = splash.font() splash_font.setPixelSize(14) splash.setFont(splash_font) else: splash = None return splash
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.setVisible(True) if sys.platform == "darwin": self.button_run.setToolTip("Not available on macOS") # Refresh layout self.layout().activate()
def get_image_label(name, default="not_found"): """Return image inside a QLabel object""" label = QLabel() label.setPixmap(QPixmap(get_image_path(name, default))) return label
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.setOpenExternalLinks(True) 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') 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): """Create About Spyder dialog with general information.""" QDialog.__init__(self, parent) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) 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) self.label.setTextInteractionFlags(Qt.TextBrowserInteraction) self.label.setFixedWidth(350) icon_filename = "spyder_about" pixmap = QPixmap(get_image_path(icon_filename)) self.label_pic = QLabel(self) self.label_pic.setPixmap( pixmap.scaledToWidth(64, Qt.SmoothTransformation)) self.label_pic.setAlignment(Qt.AlignTop) btn = QPushButton(_("Copy to clipboard"), ) bbox = QDialogButtonBox(QDialogButtonBox.Ok) # Widget setup self.setWindowIcon(ima.icon('MessageBoxInformation')) 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(self) vlayout.addLayout(tophlayout) vlayout.addSpacing(25) vlayout.addLayout(btmhlayout) vlayout.setSizeConstraint(vlayout.SetFixedSize) # Signals btn.clicked.connect(self.copy_to_clipboard) bbox.accepted.connect(self.accept)
def __init__(self, parent): super(KiteIntegrationInfo, self).__init__(parent) # Images images_layout = QHBoxLayout() icon_filename = 'kite_completions' image_path = get_image_path(icon_filename) image = QPixmap(image_path) image_label = QLabel() image_label = QLabel() image_height = int(image.height() * DialogStyle.IconScaleFactor) image_width = int(image.width() * DialogStyle.IconScaleFactor) 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: {DialogStyle.TitleFontSize}") 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: {DialogStyle.ContentFontSize}") 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 install_button_color = QStylePalette.COLOR_ACCENT_2 install_button_hover = QStylePalette.COLOR_ACCENT_3 install_button_pressed = QStylePalette.COLOR_ACCENT_4 dismiss_button_color = QStylePalette.COLOR_BACKGROUND_4 dismiss_button_hover = QStylePalette.COLOR_BACKGROUND_5 dismiss_button_pressed = QStylePalette.COLOR_BACKGROUND_6 font_color = QStylePalette.COLOR_TEXT_1 buttons_layout = QHBoxLayout() install_button = QPushButton(_('Install Kite')) install_button.setAutoDefault(False) install_button.setStyleSheet( ("QPushButton {{ " "background-color: {background_color};" "border-color: {border_color};" "font-size: {font_size};" "color: {font_color};" "padding: {padding}}}" "QPushButton:hover:!pressed {{ " "background-color: {color_hover}}}" "QPushButton:pressed {{ " "background-color: {color_pressed}}}").format( background_color=install_button_color, border_color=install_button_color, font_size=DialogStyle.ButtonsFontSize, font_color=font_color, padding=DialogStyle.ButtonsPadding, color_hover=install_button_hover, color_pressed=install_button_pressed)) dismiss_button = QPushButton(_('Dismiss')) dismiss_button.setAutoDefault(False) dismiss_button.setStyleSheet( ("QPushButton {{ " "background-color: {background_color};" "border-color: {border_color};" "font-size: {font_size};" "color: {font_color};" "padding: {padding}}}" "QPushButton:hover:!pressed {{ " "background-color: {color_hover}}}" "QPushButton:pressed {{ " "background-color: {color_pressed}}}").format( background_color=dismiss_button_color, border_color=dismiss_button_color, font_size=DialogStyle.ButtonsFontSize, font_color=font_color, padding=DialogStyle.ButtonsPadding, color_hover=dismiss_button_hover, color_pressed=dismiss_button_pressed)) 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) self.setStyleSheet( f"background-color: {QStylePalette.COLOR_BACKGROUND_2}") self.setContentsMargins(18, 40, 18, 40) if not MAC: self.setFixedSize(800, 350)
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') 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())
def __init__(self, parent): super(KiteIntegrationInfo, self).__init__(parent) # Images images_layout = QHBoxLayout() icon_filename = 'kite_completions' 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 main(): #========================================================================== # Proper high DPI scaling is available in Qt >= 5.6.0. This attribute 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() APP_ICON = QIcon(get_image_path("spyder")) 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 resetting 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 executable 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 __init__(self, parent): """Create About Spyder dialog with general information.""" QDialog.__init__(self, parent) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) 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'>%s</a>" % (rev, rev)) # Get current font properties font = self.font() font_family = font.family() buttons_padding = DialogStyle.ButtonsPadding buttons_font_size = DialogStyle.ButtonsFontSize font_size = DialogStyle.ContentFontSize dialog_background_color = QStylePalette.COLOR_BACKGROUND_2 twitter_url = "https://twitter.com/Spyder_IDE", facebook_url = "https://www.facebook.com/SpyderIDE", youtube_url = "https://www.youtube.com/Spyder-IDE", instagram_url = "https://www.instagram.com/spyderide/", self.label_overview = QLabel(f""" <div style='font-family: "{font_family}"; font-size: {font_size}; font-weight: normal; '> <br> <p> <b> Spyder IDE</b> <br> <br> The Scientific Python Development Environment | <a href="{website_url}">Spyder-IDE.org</a> <br> <p> Python {versions['python']} {versions['bitness']}-bit | Qt {versions['qt']} | {versions['qt_api']} {versions['qt_api_ver']} | {versions['system']} {versions['release']} </p> <br> <br> <a href="{project_url}">GitHub</a> | <a href="{twitter_url}"> Twitter</a> | <a href="{facebook_url}">Facebook</a> | <a href="{youtube_url}"> YouTube</a> | <a href="{instagram_url}">Instagram</a> </div>""") self.label_community = QLabel(f""" <div style='font-family: "{font_family}"; font-size: {font_size}; font-weight: normal; '> <br> <p> Created by Pierre Raybaut; current maintainer is Carlos Cordoba. Developed by the <a href="{project_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="{project_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> </div>""") self.label_legal = QLabel(f""" <div style='font-family: "{font_family}"; font-size: {font_size}; font-weight: normal; '> <br> <p> Copyright © 2009-2020 Spyder Project Contributors and <a href="{project_url}/blob/master/AUTHORS.txt">others</a>. Distributed under the terms of the <a href="{project_url}/blob/master/LICENSE.txt">MIT License</a>. </p> <p> <p>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+). </p> <p> Splash screen photo by <a href="https://unsplash.com/@benchaccounting?utm_source= unsplash&utm_medium=referral&utm_content=creditCopyText">Bench Accounting</a> on <a href="https://unsplash.com/?utm_source= unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash </a> </p> <p> See the <a href="{project_url}/blob/master/NOTICE.txt">NOTICE</a> file for full legal information. </p> </div> """) for label in [ self.label_overview, self.label_community, self.label_legal ]: label.setWordWrap(True) label.setAlignment(Qt.AlignTop) label.setOpenExternalLinks(True) label.setTextInteractionFlags(Qt.TextBrowserInteraction) label.setContentsMargins(15, 0, 25, 0) icon_filename = "spyder_about" pixmap = QPixmap(get_image_path(icon_filename)) self.label_pic = QLabel(self) self.label_pic.setPixmap( pixmap.scaledToWidth(100, Qt.SmoothTransformation)) self.label_pic.setAlignment(Qt.AlignBottom) self.info = QLabel((""" <div style='font-family: "{font_family}"; font-size: {font_size}; font-weight: normal; '> <p> <b>Spyder IDE</b> <br>{spyder_ver} <br>{revision} <br>({installer}) <br>""").format(spyder_ver=versions['spyder'], revision=revlink, installer=versions['installer'], font_family=font_family, font_size=font_size)) self.info.setAlignment(Qt.AlignHCenter) btn = QPushButton(_("Copy version info"), ) bbox = QDialogButtonBox(QDialogButtonBox.Ok) bbox.setStyleSheet(f"font-size: {buttons_font_size};" f"padding: {buttons_padding}") btn.setStyleSheet(f"font-size: {buttons_font_size};" f"padding: {buttons_padding}") # Widget setup self.setWindowIcon(ima.icon('MessageBoxInformation')) self.setModal(False) # Layout piclayout = QVBoxLayout() piclayout.addWidget(self.label_pic) piclayout.addWidget(self.info) piclayout.setContentsMargins(20, 0, 15, 0) scroll_overview = QScrollArea(self) scroll_overview.setWidgetResizable(True) scroll_overview.setWidget(self.label_overview) scroll_community = QScrollArea(self) scroll_community.setWidgetResizable(True) scroll_community.setWidget(self.label_community) scroll_legal = QScrollArea(self) scroll_legal.setWidgetResizable(True) scroll_legal.setWidget(self.label_legal) self.tabs = QTabWidget() self.tabs.addTab(scroll_overview, _('Overview')) self.tabs.addTab(scroll_community, _('Community')) self.tabs.addTab(scroll_legal, _('Legal')) self.tabs.setStyleSheet(f"background-color: {dialog_background_color}") tabslayout = QHBoxLayout() tabslayout.addWidget(self.tabs) tabslayout.setSizeConstraint(tabslayout.SetFixedSize) tabslayout.setContentsMargins(0, 15, 15, 0) btmhlayout = QHBoxLayout() btmhlayout.addWidget(btn) btmhlayout.addWidget(bbox) btmhlayout.setContentsMargins(100, 20, 0, 20) btmhlayout.addStretch() vlayout = QVBoxLayout() vlayout.addLayout(tabslayout) vlayout.addLayout(btmhlayout) vlayout.setSizeConstraint(vlayout.SetFixedSize) mainlayout = QHBoxLayout(self) mainlayout.addLayout(piclayout) mainlayout.addLayout(vlayout) # Signals btn.clicked.connect(self.copy_to_clipboard) bbox.accepted.connect(self.accept) # Size self.resize(550, 430) # Style css = APP_STYLESHEET.get_copy() css = css.get_stylesheet() css.QDialog.setValues(backgroundColor=dialog_background_color) css.QLabel.setValues(backgroundColor=dialog_background_color) self.setStyleSheet(str(css))
def __init__(self, parent, tour_function): super().__init__(parent) if MAC: flags = (self.windowFlags() | Qt.WindowStaysOnTopHint & ~Qt.WindowContextHelpButtonHint) else: flags = self.windowFlags() & ~Qt.WindowContextHelpButtonHint self.setWindowFlags(flags) self.tour_function = tour_function # Image images_layout = QHBoxLayout() icon_filename = 'tour-spyder-logo' image_path = get_image_path(icon_filename) image = QPixmap(image_path) image_label = QLabel() image_height = image.height() * self.ICON_SCALE_FACTOR image_width = 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() if MAC: images_layout.setContentsMargins(0, -5, 20, 0) else: images_layout.setContentsMargins(0, -8, 35, 0) # Label tour_label_title = QLabel(_("Welcome to Spyder!")) tour_label_title.setStyleSheet(f"font-size: {self.TITLE_FONT_SIZE}") tour_label_title.setWordWrap(True) tour_label = QLabel( _("Check out our interactive tour to " "explore some of Spyder's panes and features.")) tour_label.setStyleSheet(f"font-size: {self.CONTENT_FONT_SIZE}") tour_label.setWordWrap(True) tour_label.setFixedWidth(340) # Buttons buttons_layout = QHBoxLayout() dialog_tour_color = QStylePalette.COLOR_BACKGROUND_2 start_tour_color = QStylePalette.COLOR_ACCENT_2 start_tour_hover = QStylePalette.COLOR_ACCENT_3 start_tour_pressed = QStylePalette.COLOR_ACCENT_4 dismiss_tour_color = QStylePalette.COLOR_BACKGROUND_4 dismiss_tour_hover = QStylePalette.COLOR_BACKGROUND_5 dismiss_tour_pressed = QStylePalette.COLOR_BACKGROUND_6 font_color = QStylePalette.COLOR_TEXT_1 self.launch_tour_button = QPushButton(_('Start tour')) self.launch_tour_button.setStyleSheet( ("QPushButton {{ " "background-color: {background_color};" "border-color: {border_color};" "font-size: {font_size};" "color: {font_color};" "padding: {padding}}}" "QPushButton:hover:!pressed {{ " "background-color: {color_hover}}}" "QPushButton:pressed {{ " "background-color: {color_pressed}}}").format( background_color=start_tour_color, border_color=start_tour_color, font_size=self.BUTTONS_FONT_SIZE, font_color=font_color, padding=self.BUTTONS_PADDING, color_hover=start_tour_hover, color_pressed=start_tour_pressed)) self.launch_tour_button.setAutoDefault(False) self.dismiss_button = QPushButton(_('Dismiss')) self.dismiss_button.setStyleSheet( ("QPushButton {{ " "background-color: {background_color};" "border-color: {border_color};" "font-size: {font_size};" "color: {font_color};" "padding: {padding}}}" "QPushButton:hover:!pressed {{ " "background-color: {color_hover}}}" "QPushButton:pressed {{ " "background-color: {color_pressed}}}").format( background_color=dismiss_tour_color, border_color=dismiss_tour_color, font_size=self.BUTTONS_FONT_SIZE, font_color=font_color, padding=self.BUTTONS_PADDING, color_hover=dismiss_tour_hover, color_pressed=dismiss_tour_pressed)) self.dismiss_button.setAutoDefault(False) buttons_layout.addStretch() buttons_layout.addWidget(self.launch_tour_button) if not MAC: buttons_layout.addSpacing(10) buttons_layout.addWidget(self.dismiss_button) layout = QHBoxLayout() layout.addLayout(images_layout) label_layout = QVBoxLayout() label_layout.addWidget(tour_label_title) if not MAC: label_layout.addSpacing(3) label_layout.addWidget(tour_label) else: label_layout.addWidget(tour_label) label_layout.addSpacing(10) 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() if not MAC: general_layout.addStretch() general_layout.addLayout(layout) general_layout.addSpacing(1) general_layout.addLayout(vertical_layout) general_layout.addStretch() else: general_layout.addLayout(layout) general_layout.addLayout(vertical_layout) self.setLayout(general_layout) self.launch_tour_button.clicked.connect(self._start_tour) self.dismiss_button.clicked.connect(self.close) self.setStyleSheet(f"background-color:{dialog_tour_color}") self.setContentsMargins(18, 40, 18, 40) if not MAC: self.setFixedSize(640, 280)