Beispiel #1
0
    def generate_editor_fields(self):
        self.password_entry_headerlabel = Granite.HeaderLabel(
            "Choose a Password")

        self.password_entry = Granite.ValidatedEntry()
        self.password_entry.props.activates_default = True
        self.password_entry.props.hexpand = True
        self.password_entry.props.visibility = False
        self.password_entry.connect("changed", self.on_password_entry_changed)

        self.password_levelbar = Gtk.LevelBar().new_for_interval(0.0, 100.0)
        self.password_levelbar.props.mode = Gtk.LevelBarMode.CONTINUOUS
        self.password_levelbar.add_offset_value("low", 30.0)
        self.password_levelbar.add_offset_value("middle", 50.0)
        self.password_levelbar.add_offset_value("high", 80.0)
        self.password_levelbar.add_offset_value("full", 100.0)

        self.password_error_label = Gtk.Label(
            "<span font_size=\"small\">{0}</span>".format("."))
        self.password_error_label.props.halign = Gtk.Align.END
        self.password_error_label.props.justify = Gtk.Justification.RIGHT
        self.password_error_label.props.max_width_chars = 55
        self.password_error_label.props.use_markup = True
        self.password_error_label.props.wrap = True
        self.password_error_label.props.xalign = 1
        self.password_error_revealer = Gtk.Revealer()
        self.password_error_revealer.props.transition_type = Gtk.RevealerTransitionType.CROSSFADE
        self.password_error_revealer.add(self.password_error_label)
        self.password_error_revealer.get_child().get_style_context().add_class(
            Gtk.STYLE_CLASS_WARNING)

        self.confirm_headerlabel = Granite.HeaderLabel("Confirm Password")

        self.confirm_entry = Granite.ValidatedEntry()
        self.confirm_entry.props.activates_default = True
        self.confirm_entry.props.sensitive = False
        self.confirm_entry.props.visibility = False
        self.confirm_entry.connect("changed", self.on_confirm_entry_changed)

        self.confirm_entry_label = Gtk.Label(
            "<span font_size=\"small\">{0}</span>".format("."))
        self.confirm_entry_label.props.halign = Gtk.Align.END
        self.confirm_entry_label.props.justify = Gtk.Justification.RIGHT
        self.confirm_entry_label.props.max_width_chars = 55
        self.confirm_entry_label.props.use_markup = True
        self.confirm_entry_label.props.wrap = True
        self.confirm_entry_label.props.xalign = 1
        self.confirm_entry_revealer = Gtk.Revealer()
        self.confirm_entry_revealer.props.transition_type = Gtk.RevealerTransitionType.CROSSFADE
        self.confirm_entry_revealer.add(self.confirm_entry_label)
        self.confirm_entry_revealer.get_child().get_style_context().add_class(
            Gtk.STYLE_CLASS_ERROR)

        self.add(self.password_entry_headerlabel)
        self.add(self.password_entry)
        self.add(self.password_levelbar)
        self.add(self.password_error_revealer)
        self.add(self.confirm_headerlabel)
        self.add(self.confirm_entry)
        self.add(self.confirm_entry_revealer)
Beispiel #2
0
 def apply_styling(self):
     """Apply elementary OS header styling only for elementary OS"""
     if distro.id() == 'elementary':
         Granite.widgets_utils_set_color_primary(self,
                                                 Gdk.RGBA(red=0.29, green=0.50, blue=0.64, alpha=1.0),
                                                 Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
         self.get_style_context().add_class('elementary')
Beispiel #3
0
    def __init__(self, settings):
        super().__init__()
        self.set_relative_to(None)

        self.settings = settings

        zoom_out_button = Gtk.Button.new_from_icon_name(
            "zoom-out-symbolic", Gtk.IconSize.MENU)
        zoom_out_button.set_action_name('document.zoom_out')
        zoom_out_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(('<Control>minus', ), _('Zoom Out')))

        self.zoom_default_button = Gtk.Button(
            "100%", action_name='document.zoom_default')
        self.zoom_default_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(('<Control>0', ), _('Zoom 1:1')))

        zoom_in_button = Gtk.Button.new_from_icon_name("zoom-in-symbolic",
                                                       Gtk.IconSize.MENU)
        zoom_in_button.set_action_name('document.zoom_in')
        zoom_in_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(('<Control>equal', '<Control>plus'),
                                         _('Zoom In')))

        font_size_grid = Gtk.Grid(column_homogeneous=True,
                                  hexpand=True,
                                  margin=12)
        font_size_grid.get_style_context().add_class(Gtk.STYLE_CLASS_LINKED)
        font_size_grid.add(zoom_out_button)
        font_size_grid.add(self.zoom_default_button)
        font_size_grid.add(zoom_in_button)

        preferences_menuitem = Gtk.ModelButton(text=_("Preferences"),
                                               action_name='app.preferences')
        about_menuitem = Gtk.ModelButton(text=_("About"),
                                         action_name='app.about')
        shortcuts_menuitem = Gtk.ModelButton(text=_("Shortcuts"),
                                             action_name='app.shortcuts')
        quit_menuitem = Gtk.ModelButton(text=_("Quit"), action_name='app.quit')

        menu_separator = Gtk.Separator(margin_top=12,
                                       orientation=Gtk.Orientation.HORIZONTAL)

        menu_grid = Gtk.Grid(margin_bottom=3,
                             orientation=Gtk.Orientation.VERTICAL,
                             width_request=200)
        menu_grid.attach(font_size_grid, 0, 0, 3, 1)
        menu_grid.attach(preferences_menuitem, 0, 1, 3, 1)
        menu_grid.attach(shortcuts_menuitem, 0, 2, 3, 1)
        menu_grid.attach(about_menuitem, 0, 3, 3, 1)
        menu_grid.attach(menu_separator, 0, 4, 3, 1)
        menu_grid.attach(quit_menuitem, 0, 5, 3, 1)

        self.add(menu_grid)

        menu_grid.show_all()

        self.zoom_default_button.set_label(f"{settings.get_int('zoom')}%")
        self.settings.connect('changed', self.on_settings_changed)
Beispiel #4
0
    def __init__(self):
        Granite.WidgetsSourceList.__init__(self)
        self.old_testament = Granite.WidgetsSourceListExpandableItem()
        self.old_testament.props.name = "Old Testament"
        self.new_testament = Granite.WidgetsSourceListExpandableItem()
        self.new_testament.props.name = "New Testament"
        self.root = Granite.WidgetsSourceListExpandableItem()

        self.root.add(self.old_testament)
        self.root.add(self.new_testament)
        self.set_root(self.root)

        self._populate_list()
        self.show_all()
Beispiel #5
0
    def __init__(self, settings):
        super().__init__()

        self.document_mode_active = False
        self.settings = settings

        self.set_title(APP_TITLE)
        self.set_subtitle(APP_SUBTITLE)
        self.set_has_subtitle(True)
        self.set_show_close_button(True)
        self.get_style_context().add_class('norka-header')

        self.add_button = Gtk.Button.new_from_icon_name(
            'document-new', Gtk.IconSize.LARGE_TOOLBAR)
        self.add_button.set_visible(True)
        self.add_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(('<Control>n', ),
                                         'Create new document'))
        self.add_button.set_action_name('document.create')

        self.back_button = Gtk.Button.new_with_label('Documents')
        self.back_button.set_valign(Gtk.Align.CENTER)
        self.back_button.get_style_context().add_class('back-button')
        self.back_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(
                ('<Control>w', ),
                'Save document and return to documents list'))
        self.back_button.set_visible(False)
        self.back_button.set_action_name('document.close')

        self.export_button = Gtk.Button.new_from_icon_name(
            'document-save-as', Gtk.IconSize.LARGE_TOOLBAR)
        self.export_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(('<Control>e', ),
                                         'Export document to file'))
        self.export_button.set_action_name('document.export')
        self.export_button.set_visible(False)

        self.menu_button = Gtk.MenuButton(tooltip_text="Menu")
        self.menu_button.set_image(
            Gtk.Image.new_from_icon_name('open-menu',
                                         Gtk.IconSize.LARGE_TOOLBAR))
        self.menu_button.set_popover(MenuPopover(settings=self.settings))
        self.menu_button.set_visible(True)

        self.pack_start(self.back_button)
        self.pack_start(self.add_button)
        self.pack_end(self.menu_button)
        self.pack_end(self.export_button)
Beispiel #6
0
    def __init__(self):
        Gtk.Box.__init__(self, False, 0)

        try:
            current_locale, encoding = locale.getdefaultlocale()
            locale_path = os.path.join(
                os.path.abspath(os.path.dirname(__file__)), 'locale')
            translate = gettext.translation(cn.App.application_shortname,
                                            locale_path, [current_locale])
            _ = translate.gettext
        except FileNotFoundError:
            _ = str

        # Create welcome widget
        welcome = Granite.WidgetsWelcome()
        welcome = welcome.new("Welcome", cn.App.application_description)

        # Welcome voices
        welcome.append("object-inverse", _('Dark Mode'),
                       _('Switch to the dark side'))
        welcome.append("utilities-terminal", _('Open Terminal'),
                       _('Just an example of action'))
        welcome.append("help-contents", _('Info'),
                       _('Learn more about this application'))

        welcome.connect("activated", self.on_welcome_activated)

        self.add(welcome)
Beispiel #7
0
    def __init__(self, settings, docker):
        super().__init__()
        self.set_halign(Gtk.Align.FILL)
        self.set_valign(Gtk.Align.FILL)
        self.set_hexpand(True)

        self._settings = settings
        self._docker = docker

        self.general_preferences = GeneralSettingsPage(settings=self._settings,
                                                       docker=self._docker)
        self.registry_preferences = RegistrySettingsPage(
            settings=self._settings, docker=self._docker)
        self.k3s_preferences = K3sSettingsPage(settings=self._settings,
                                               docker=self._docker)
        self.hooks_preferences = HooksSettingsPage(settings=self._settings,
                                                   docker=self._docker)

        self.stack = Gtk.Stack()
        self.stack.set_halign(Gtk.Align.FILL)
        self.stack.set_valign(Gtk.Align.FILL)
        self.stack.set_hexpand(True)
        self.stack.set_homogeneous(True)
        self.stack.add_named(self.general_preferences, "settings_page")
        self.stack.add_named(self.registry_preferences, "registry_page")
        self.stack.add_named(self.k3s_preferences, "k3s_page")
        self.stack.add_named(self.hooks_preferences, "hooks_page")

        self.stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
        self.stack.set_transition_duration(100)

        self.settings_sidebar = Granite.SettingsSidebar(stack=self.stack)

        self.add(self.settings_sidebar)
        self.add(self.stack)
Beispiel #8
0
    def __init__(self,
                 settings: ApplicationSettings,
                 cluster: Optional[K3dCluster] = None):
        super().__init__()
        self.set_halign(Gtk.Align.FILL)
        self.set_valign(Gtk.Align.FILL)
        self.set_hexpand(True)

        self._settings = settings

        self.general_settings = GeneralSettingsPage(cluster=cluster,
                                                    settings=settings)
        self.registry_settings = RegistrySettingsPage(cluster=cluster,
                                                      settings=settings)
        self.network_settings = NetworkSettingsPage(cluster=cluster,
                                                    settings=settings)
        self.advanced_settings = AdvancedSettingsPage(cluster=cluster,
                                                      settings=settings)

        self.stack = Gtk.Stack()
        self.stack.set_halign(Gtk.Align.FILL)
        self.stack.set_valign(Gtk.Align.FILL)
        self.stack.set_hexpand(True)
        self.stack.set_homogeneous(True)
        self.stack.add_named(self.general_settings, "settings_page")
        self.stack.add_named(self.registry_settings, "registry_page")
        self.stack.add_named(self.network_settings, "ports_page")
        self.stack.add_named(self.advanced_settings, "advanced_page")
        self.stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
        self.stack.set_transition_duration(100)

        self.settings_sidebar = Granite.SettingsSidebar(stack=self.stack)

        self.add(self.settings_sidebar)
        self.add(self.stack)
    def __init__(self, zettel=Zettel(), letters_per_line = 80):
        super().__init__()
        self._letters_per_line = letters_per_line

        self.text_label = Gtk.Label()
        self.text_label.set_line_wrap(True)
        self.text_label.set_justify(Gtk.Justification.FILL) 
        self.text_label.set_max_width_chars(letters_per_line)

        self.title_label = Granite.HeaderLabel()
        self.tag_label = Gtk.Label()
        self.name_label = Gtk.Label()

        self.text_label.set_selectable(True)
        self.title_label.set_selectable(True)
        self.tag_label.set_selectable(True)
        self.name_label.set_selectable(True)

        self.set_zettel(zettel)

        self.attach(self.title_label, 0, 0, 1, 1)
        self.attach_next_to(self.name_label, self.title_label,
                             Gtk.PositionType.RIGHT, 1, 1)
        self.attach_next_to(self.tag_label, self.title_label,
                        Gtk.PositionType.BOTTOM, 1, 1)
        self.attach_next_to(self.text_label, self.tag_label,
                        Gtk.PositionType.BOTTOM, 1, 1)  

        self.text_label.show()
        self.tag_label.show()
        self.name_label.show()
        self.title_label.show()
Beispiel #10
0
    def __init__(self, parent):
        Gtk.Box.__init__(self, False, 0)
        self.parent = parent

        try:
            current_locale, encoding = locale.getdefaultlocale()
            locale_path = os.path.join(
                os.path.abspath(os.path.dirname(__file__)), 'locale')
            translate = gettext.translation(cn.App.application_shortname,
                                            locale_path, [current_locale])
            _ = translate.gettext
        except FileNotFoundError:
            _ = str

        # Create welcome widget
        self.welcome = Granite.WidgetsWelcome()
        self.welcome = self.welcome.new(cn.App.application_name,
                                        cn.App.application_description)

        # Welcome voices
        self.welcome.append("wine", _('New bottle'), _('Create a new bottle'))
        self.welcome.append("document-import", _('Import and convert'),
                            _('Import a third-party wineprefix'))
        self.welcome.append("gnome-mime-application-x-archive",
                            _('List bottles'), _('List all bottles'))

        self.welcome.connect("activated", self.on_welcome_activated)

        self.add(self.welcome)
Beispiel #11
0
    def __init__(self, parent):
        Gtk.Box.__init__(self, False, 0)
        self.parent = parent

        try:
            current_locale, encoding = locale.getdefaultlocale()
            locale_path = os.path.join(
                os.path.abspath(os.path.dirname(__file__)), 'locale')
            translate = gettext.translation(cn.App.application_shortname,
                                            locale_path, [current_locale])
            _ = translate.gettext
        except FileNotFoundError:
            _ = str

        # Create welcome widget
        welcome = Granite.WidgetsWelcome()
        welcome = welcome.new("Welcome", cn.App.application_description)

        # Welcome voices
        welcome.append("system-search-symbolic", _('New search'),
                       _('Find min of function'))
        welcome.append("help-contents",
                       _('What is the Golden Section Algorithm'),
                       _('Learn more about this algorithm'))

        welcome.connect("activated", self.on_welcome_activated)

        self.add(welcome)
Beispiel #12
0
    def render_writeas(self, content_grid):
        self.writeas_login = Gtk.Entry(hexpand=True, placeholder_text=_("Login"))
        self.writeas_password = Gtk.Entry(hexpand=True, placeholder_text=_("Password"), visibility=False)
        self.writeas_login_button = Gtk.Button(label=_("Login"))
        self.writeas_login_button.connect("clicked", self.on_writeas_login)
        self.writeas_logout_button = Gtk.Button(label=_("Logout"), hexpand=True)
        self.writeas_logout_button.connect("clicked", self.on_writeas_logout)

        content_grid.attach(Granite.HeaderLabel("Write.as"), 0, 3, 3, 1)

        self.writeas_login_revealer = Gtk.Revealer()
        self.writeas_login_revealer.set_transition_type(Gtk.RevealerTransitionType.CROSSFADE)
        login_grid = Gtk.Grid(column_spacing=12, row_spacing=6)
        login_grid.attach(Gtk.Label(_("Login:"******"Password:"******"changed", self.on_settings_changed)
Beispiel #13
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.settings = Gtk.Settings.get_default()

        # main icon/logo
        icon = Gtk.Image()
        icon.set_from_icon_name("com.github.hezral.inspektor",
                                Gtk.IconSize.DIALOG)
        icon.set_pixel_size(128)
        icon.props.valign = Gtk.Align.END
        icon.props.halign = Gtk.Align.CENTER
        icon.props.margin = 15

        # welcome widget
        welcome_widget = Granite.WidgetsWelcome().new(
            "Movens", AppAttributes.application_description)
        welcome_widget.connect("activated", self.on_welcome_activated)

        # welcome menu
        welcome_widget.append("text-x-readme", "README", "Get started manual")
        welcome_widget.append("preferences-desktop", "Preferences",
                              "Configure Movens the way you want it")

        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        box.props.margin = 40
        box.pack_start(icon, False, False, 0)
        box.pack_end(welcome_widget, True, True, 0)

        self.add(box)
Beispiel #14
0
    def _populate_list(self):
        vk = VerseKey()

        for b in range(0, vk.bookCount(1)):
            b += 1
            vk.setBook(b)
            book = Granite.WidgetsSourceListItem()
            book.props.name = vk.getBookName()
            self.old_testament.add(book)

        b = 1
        vk.setTestament(2)
        while b <= vk.bookCount(2):
            b += 1
            vk.setBook(b)
            book = Granite.WidgetsSourceListItem()
            book.props.name = vk.getBookName()
            self.new_testament.add(book)
Beispiel #15
0
    def __init__(self, parent: Gtk.Widget, text: str = None):
        super().__init__(modal=False)
        self.set_default_size(800, 600)
        self.set_transient_for(parent)

        self.header_overlay.add_overlay(self.header_revealer)
        self.header_revealer.set_reveal_child(True)

        # print_button = Gtk.Button.new_from_icon_name('document-print', Gtk.IconSize.LARGE_TOOLBAR)
        # print_button.set_tooltip_markup(Granite.markup_accel_tooltip(None, _('Print document')))
        # print_button.connect('clicked', lambda x: self.emit('print'))

        # self.spinner = Gtk.Spinner(visible=False)
        #
        # header = Gtk.HeaderBar(title=_("Preview"))
        # header.set_has_subtitle(False)
        # header.set_show_close_button(True)
        # header.get_style_context().add_class('norka-header')
        #
        # header.pack_start(self.spinner)
        # header.pack_end(print_button)

        # self.set_titlebar(header)

        self.temp_file = tempfile.NamedTemporaryFile(prefix='norka-',
                                                     delete=False)

        # Render in thread
        if text:
            GObjectWorker.call(Exporter.export_html_preview,
                               (self.temp_file.name, text, True),
                               self.update_html)

        ctx = WebKit2.WebContext.get_default()
        self.web: WebKit2.WebView = WebKit2.WebView.new_with_context(ctx)
        self.web.connect('load-changed', self.on_load_changed)
        web_settings = self.web.get_settings()
        web_settings.set_enable_developer_extras(False)
        web_settings.set_enable_tabs_to_links(False)
        self.web.set_settings(web_settings)

        self.empty = Granite.WidgetsWelcome()
        self.empty.set_title(_('Nothing to preview'))
        self.empty.set_subtitle(_('To render preview open a document'))

        # self.stack = Gtk.Stack()
        # self.stack.add_named(self.empty, 'empty-page')
        # self.stack.add_named(self.web, 'preview-page')

        self.content_deck.add(self.empty)
        self.content_deck.add(self.web)

        self.connect('enter-notify-event', self.on_enter_notify)
        self.connect('leave-notify-event', self.on_leave_notify)
Beispiel #16
0
    def render_medium(self, content_grid):
        self.medium_token = Gtk.Entry(hexpand=True, placeholder_text=_("Token"))
        self.medium_token.set_text(self.settings.get_string('medium-personal-token'))
        self.medium_token.connect("changed", self.on_medium_token)

        self.medium_link = Gtk.LinkButton("https://medium.com/me/settings")
        self.medium_link.set_label(_("Create Integration token and copy it here"))

        content_grid.attach(Granite.HeaderLabel("Medium.com"), 0, 0, 3, 1)
        content_grid.attach(Gtk.Label(_("Personal Token:"), halign=Gtk.Align.END), 0, 1, 1, 1)
        content_grid.attach(self.medium_token, 1, 1, 2, 1)
        content_grid.attach(self.medium_link, 0, 2, 3, 1)
Beispiel #17
0
    def __init__(self):
        Gtk.Box.__init__(self, False, 0)

        # Create welcome widget
        welcome = Granite.WidgetsWelcome()
        welcome = welcome.new("Welcome", cn.App.application_description)

        # Welcome voices
        #welcome.append("object-inverse", "Dark mode", "Switch to the dark side")
        #welcome.append("utilities-terminal", "Open Terminal", "Just an example of action")
        #welcome.append("help-contents", "Info", "Learn more about this application")
        
        welcome.connect("activated", self.on_welcome_activated)

        self.add(welcome)
Beispiel #18
0
    def __init__(self, parent):
        Gtk.Box.__init__(self, False, 0)

        self.parent = parent

        # Create welcome widget
        self.welcome = Granite.WidgetsWelcome()
        self.welcome = self.welcome.new(cn.App.application_name, cn.App.application_description)

        # Welcome voices
        self.welcome.append("document-new", "Create Invoice", "Create a new invoice")


        self.welcome.connect("activated", self.on_welcome_activated)

        self.add(self.welcome)
Beispiel #19
0
    def __init__(self):
        Gtk.Box.__init__(self, False, 0)
        self.light = LightWindow()

        self.settings.set_property("gtk-application-prefer-dark-theme", True)

        # Create welcome widget
        self.welcome = Granite.WidgetsWelcome()
        self.welcome = self.welcome.new("Welcome", "What do you want to do?")

        # Welcome voices
        self.welcome.append("folder-videos", "Open", "Open Video or Playlist")

        self.welcome.connect("activated", self.on_welcome_activated)

        self.add(self.welcome)
Beispiel #20
0
 def __init__(self):
     '''Our class will be a Gtk.Box and will contain our 
     new Welcome Widget.'''
     Gtk.Box.__init__(self, False, 0)
     '''Your app needs translations, right?
     Here we are trying to set the locale_path to the system one, assuming 
     the app is installed.'''
     try:
         current_locale, encoding = locale.getdefaultlocale()
         locale_path = os.path.join(
             os.path.abspath(os.path.dirname(__file__)), 'locale')
         translate = gettext.translation(cn.App.application_shortname,
                                         locale_path, [current_locale])
         _ = translate.gettext
     except FileNotFoundError:
         _ = str
     ''''The self._ can be used for defining a new translation string.
     Note: that if the translation is not loaded (the check above), 
           self._ will be the same as str, so you won't get any errors.'''
     self._ = _
     '''Here we are creating a new Welcome Widget from the Granite library'''
     welcome = Granite.WidgetsWelcome()
     welcome = welcome.new(_("Welcome"), cn.App.application_description)
     '''Let's populate the Welcome menu actions.'''
     welcome.append(
         "weather-clear-night",  # the action icon (a valid icon name)
         _('Dark Mode'),  # the action name
         _('Switch to the dark side')  # the action description
     )
     welcome.append("utilities-terminal", _('Open Terminal'),
                    _('Just an example of action'))
     welcome.append("help-contents", _('Info'),
                    _('Learn more about this application'))
     welcome.append("help-browser", _('Doc'), _('Valadoc for Granite'))
     '''Here we are connecting the on_welcome_activated method to the 
     activated signal of the Welcome Widget, so this will be triggered 
     when an action is activated'''
     welcome.connect("activated", self.on_welcome_activated)
     '''Do you remember the Box we were talking about at the beginning?
     Here, we add the Welcome Widget to this.'''
     self.add(welcome)
Beispiel #21
0
    def __init__(self, app):
        super().__init__(root=Granite.WidgetsSourceListExpandableItem())

        self.app = app
        self.buffers = app.buffers
        self.buffers.connect('on-rename', self.on_buffers_rename)

        self.builder = Gtk.Builder()
        self.builder.add_from_file(
            (self.app.base_path / 'data/window.ui').as_posix())
        self.sidebar_menu = self.builder.get_object('sidebar_menu')

        self.toplevels = []

        self.get_style_context().add_class('sidebar')
        for child in self:
            if hasattr(child, 'set_activate_on_single_click'):  # TreeView
                child.get_style_context().add_class('sidebar')
                child.set_activate_on_single_click(True)

        self.connect('item-selected', self.on_item_selected)
Beispiel #22
0
    def generate_authenticate_fields(self):

        self.current_password_entry = Gtk.Entry()
        self.current_password_entry.props.visibility = False
        self.current_password_entry.set_icon_tooltip_text(
            Gtk.EntryIconPosition.SECONDARY, "Press to authenticate")

        if self.type != "authenticate":
            self.current_password_headerlabel = Granite.HeaderLabel(
                "Current Password")
            self.add(self.current_password_headerlabel)

            self.current_password_entry.connect(
                "icon-release", self.on_current_password_entry_icon_release)
            self.current_password_entry.connect(
                "focus-out-event", self.on_current_password_entry_focus_out)

        self.current_password_entry.connect(
            "changed", self.on_current_password_entry_changed)
        self.current_password_entry.connect(
            "activate", self.on_current_password_entry_activated)

        self.current_password_error_label = Gtk.Label(
            "<span font_size=\"small\">{0}</span>".format(
                "Authentication failed"))
        self.current_password_error_label.props.halign = Gtk.Align.END
        self.current_password_error_label.props.justify = Gtk.Justification.RIGHT
        self.current_password_error_label.props.max_width_chars = 55
        self.current_password_error_label.props.use_markup = True
        self.current_password_error_label.props.wrap = True
        self.current_password_error_label.props.xalign = 1
        self.current_password_error_revealer = Gtk.Revealer()
        self.current_password_error_revealer.props.transition_type = Gtk.RevealerTransitionType.CROSSFADE
        self.current_password_error_revealer.add(
            self.current_password_error_label)
        self.current_password_error_revealer.get_child().get_style_context(
        ).add_class(Gtk.STYLE_CLASS_ERROR)

        self.add(self.current_password_entry)
        self.add(self.current_password_error_revealer)
Beispiel #23
0
    def __init__(self, folder_title=None):
        super().__init__(title=_("Create folder"))

        self.set_default_size(300, 100)
        self.set_modal(True)
        self.set_transient_for(Gtk.Application.get_default().props.active_window)

        header = Granite.HeaderLabel(_('Create folder'), halign=Gtk.Align.CENTER)

        self.entry = Gtk.Entry(placeholder_text=_('Folder name'), hexpand=True)
        self.entry.set_text(folder_title)
        self.entry.connect('activate', lambda entry: self.response(Gtk.ResponseType.ACCEPT))

        layout = Gtk.Grid(row_spacing=12, margin_start=12, margin_end=12)
        layout.attach(header, 0, 0, 1, 1)
        layout.attach(self.entry, 0, 1, 1, 1)

        self.get_content_area().add(layout)
        self.add_button(_("Cancel"), Gtk.ResponseType.CANCEL)

        suggested_button = self.add_button(_("Create"), Gtk.ResponseType.ACCEPT)
        suggested_button.get_style_context().add_class(Gtk.STYLE_CLASS_SUGGESTED_ACTION)

        self.show_all()
Beispiel #24
0
    def __init__(self, settings):
        super().__init__()

        self.document_mode_active = False
        self.settings = settings

        self.set_title(_("Norka"))
        self.set_subtitle(APP_SUBTITLE)
        self.set_has_subtitle(True)
        self.set_show_close_button(True)
        self.get_style_context().add_class('norka-header')

        self.spinner = Gtk.Spinner(visible=False)

        self.import_button = Gtk.Button.new_from_icon_name('document-open', Gtk.IconSize.LARGE_TOOLBAR)
        self.import_button.set_visible(True)
        self.import_button.set_tooltip_markup(Granite.markup_accel_tooltip(('<Control>o',), _('Import file to Norka')))
        self.import_button.set_action_name('document.import')

        self.add_button = Gtk.Button.new_from_icon_name('document-new', Gtk.IconSize.LARGE_TOOLBAR)
        self.add_button.set_visible(True)
        self.add_button.set_tooltip_markup(Granite.markup_accel_tooltip(('<Control>n',), _('Create new document')))
        self.add_button.set_action_name('document.create')

        self.back_button = Gtk.Button.new_with_label(_('Documents'))
        self.back_button.set_valign(Gtk.Align.CENTER)
        self.back_button.get_style_context().add_class('back-button')
        self.back_button.set_tooltip_markup(Granite.markup_accel_tooltip(
            ('<Control>w',),
            _('Save document and return to documents list')))
        self.back_button.set_visible(False)
        self.back_button.set_action_name('document.close')

        # self.search_button = Gtk.ToggleButton()
        # self.search_button.set_image(Gtk.Image.new_from_icon_name('edit-find', Gtk.IconSize.LARGE_TOOLBAR))
        # self.search_button.set_tooltip_markup(Granite.markup_accel_tooltip(('<Control>f',), 'Find text'))
        # self.search_button.set_action_name('document.search_text')
        # self.search_button.set_visible(False)

        self.share_app_menu = Gtk.MenuButton(tooltip_text=_("Share"))
        self.share_app_menu.set_image(Gtk.Image.new_from_icon_name('document-save-as', Gtk.IconSize.LARGE_TOOLBAR))
        self.share_app_menu.set_popover(MenuExport(settings=self.settings))

        self.archived_button = Gtk.ToggleButton()
        self.archived_button.set_image(Gtk.Image.new_from_icon_name('user-trash', Gtk.IconSize.LARGE_TOOLBAR))
        self.archived_button.set_tooltip_markup(Granite.markup_accel_tooltip(None, _('Show Archived files')))
        self.archived_button.set_action_name('document.toggle_archived')
        self.archived_button.set_visible(True)

        self.menu_button = Gtk.MenuButton(tooltip_text=_("Menu"))
        self.menu_button.set_image(Gtk.Image.new_from_icon_name('open-menu', Gtk.IconSize.LARGE_TOOLBAR))
        self.menu_button.set_popover(MenuPopover(settings=self.settings))
        self.menu_button.set_visible(True)

        self.pack_start(self.back_button)
        self.pack_start(self.add_button)
        self.pack_start(self.import_button)
        self.pack_start(self.spinner)
        self.pack_end(self.menu_button)
        self.pack_end(self.share_app_menu)
        self.pack_end(self.archived_button)
Beispiel #25
0
    def __init__(self):
        super().__init__(title=_('Markup Help'))
        self.set_default_size(300, 340)

        h1_label = Gtk.Label(label=f'{self.span_text("#")} {_("Header")} 1',
                             halign=Gtk.Align.START,
                             use_markup=True)
        h1_keys = Granite.AccelLabel(accel_string='<Control>1')

        h2_label = Gtk.Label(label=f'{self.span_text("##")} {_("Header")} 2',
                             halign=Gtk.Align.START,
                             use_markup=True)
        h2_keys = Granite.AccelLabel(accel_string='<Control>2')

        h3_label = Gtk.Label(label=f'{self.span_text("###")} {_("Header")} 3',
                             halign=Gtk.Align.START,
                             use_markup=True)
        h3_keys = Granite.AccelLabel(accel_string='<Control>3')

        bold_label = Gtk.Label(
            label=f'{self.span_text("**")}{_("Bold")}{self.span_text("**")}',
            halign=Gtk.Align.START,
            use_markup=True)
        bold_keys = Granite.AccelLabel(accel_string='<Control>b')

        italic_label = Gtk.Label(
            label=f'{self.span_text("_")}{_("Italic")}{self.span_text("_")}',
            halign=Gtk.Align.START,
            use_markup=True)
        italic_keys = Granite.AccelLabel(accel_string='<Control>i')

        link_label = Gtk.Label(
            label=f'{self.span_text("[")}{_("Link title")}{self.span_text("]")}'
            f'{self.span_text("(")}{_("URL")}{self.span_text(")")}',
            halign=Gtk.Align.START,
            use_markup=True)
        link_keys = Granite.AccelLabel(accel_string='<Control>k')

        image_link_label = Gtk.Label(
            label=
            f'{self.span_text("![")}{_("Image title")}{self.span_text("]")}'
            f'{self.span_text("(")}{_("URL")}{self.span_text(")")}',
            halign=Gtk.Align.START,
            use_markup=True)
        image_link_keys = Granite.AccelLabel(accel_string='<Control><Shift>k')

        list_label = Gtk.Label(label=f'{self.span_text("-")} {_("List")}',
                               halign=Gtk.Align.START,
                               use_markup=True)
        list_keys = Granite.AccelLabel(accel_string='<Control>l')

        ordered_list_label = Gtk.Label(
            label=f'{self.span_text("1.")} {_("Ordered list")}',
            halign=Gtk.Align.START,
            use_markup=True)
        ordered_list_keys = Granite.AccelLabel(
            accel_string='<Control><Shift>l')

        quote_label = Gtk.Label(label=f'{self.span_text(">")} {_("Quote")}',
                                halign=Gtk.Align.START,
                                use_markup=True)
        quote_keys = Granite.AccelLabel(accel_string='<Control><Shift>j')

        code_label = Gtk.Label(
            label=
            f'{self.span_text("`")}{_("Inline code")}{self.span_text("`")}',
            halign=Gtk.Align.START,
            use_markup=True)
        code_keys = Granite.AccelLabel(accel_string='<Control><Shift>c')

        code_block_label = Gtk.Label(
            label=
            f'{self.span_text("```")}{_("Code block")}{self.span_text("```")}',
            halign=Gtk.Align.START,
            use_markup=True)
        code_block_keys = Granite.AccelLabel(accel_string='<Control><Alt>c')

        grid = Gtk.Grid(
            column_spacing=6,
            row_spacing=6,
            margin_start=12,
            margin_end=12,
            margin_top=12,
            margin_bottom=12,
        )

        grid.attach(h1_label, 1, 0, 1, 1)
        grid.attach(h1_keys, 2, 0, 1, 1)
        grid.attach(h2_label, 1, 1, 1, 1)
        grid.attach(h2_keys, 2, 1, 1, 1)
        grid.attach(h3_label, 1, 2, 1, 1)
        grid.attach(h3_keys, 2, 2, 1, 1)

        grid.attach(self.make_sep(), 1, 3, 3, 1)

        grid.attach(bold_label, 1, 4, 1, 1)
        grid.attach(bold_keys, 2, 4, 1, 1)
        grid.attach(italic_label, 1, 5, 1, 1)
        grid.attach(italic_keys, 2, 5, 1, 1)
        grid.attach(link_label, 1, 6, 1, 1)
        grid.attach(link_keys, 2, 6, 1, 1)
        grid.attach(image_link_label, 1, 7, 1, 1)
        grid.attach(image_link_keys, 2, 7, 1, 1)

        grid.attach(self.make_sep(), 1, 8, 3, 1)

        grid.attach(list_label, 1, 9, 1, 1)
        grid.attach(list_keys, 2, 9, 1, 1)
        grid.attach(ordered_list_label, 1, 10, 1, 1)
        grid.attach(ordered_list_keys, 2, 10, 1, 1)
        grid.attach(quote_label, 1, 11, 1, 1)
        grid.attach(quote_keys, 2, 11, 1, 1)

        grid.attach(self.make_sep(), 1, 13, 3, 1)

        grid.attach(code_label, 1, 14, 1, 1)
        grid.attach(code_keys, 2, 14, 1, 1)
        grid.attach(code_block_label, 1, 15, 1, 1)
        grid.attach(code_block_keys, 2, 15, 1, 1)

        self.get_content_area().add(grid)

        self.show_all()
Beispiel #26
0
    def __init__(self, settings, **kwargs):
        super().__init__(**kwargs)

        self.builder = Gtk.Builder.new_from_resource(
            f'{RESOURCE_PREFIX}/ui/headerbar.ui')
        self.header_box: Gtk.Stack = self.builder.get_object('header_box')
        self.grid_header: Handy.HeaderBar = self.builder.get_object(
            'grid_header')
        self.editor_header: Handy.HeaderBar = self.builder.get_object(
            'editor_header')
        self.loader_spinner: Gtk.Spinner = self.builder.get_object(
            'loader_spinner')
        self.editor_spinner: Gtk.Spinner = self.builder.get_object(
            'editor_spinner')
        self.subtitle_path_label: Gtk.Label = self.builder.get_object(
            'subtitle_path_label')
        self.title_label: Gtk.Label = self.builder.get_object('title_label')
        self.subtitle_label: Gtk.Label = self.builder.get_object(
            'subtitle_label')
        self.subtitle_eventbox: Gtk.EventBox = self.builder.get_object(
            'subtitle_eventbox')

        self.stats_mode = StatsMode.STATS

        self.document_mode_active = False
        self.settings = settings

        self.stats = None
        self.document_path = "/"

        self.header_box.set_visible_child_name("grid_header")
        self.add(self.header_box)

        self.subtitle_eventbox.connect('button-release-event',
                                       self.change_subtitle_mode)

        self.import_button: Gtk.Button = self.builder.get_object(
            "import_button")
        self.import_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(('<Control>o', ),
                                         _('Import file to Norka')))
        #
        self.add_button: Gtk.Button = self.builder.get_object("add_button")
        self.add_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(('<Control>n', ),
                                         _('Create new document')))

        self.add_folder_button: Gtk.Button = self.builder.get_object(
            "add_folder_button")
        self.add_folder_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(('<Control><Shift>n', ),
                                         _('Create new folder')))

        self.back_button: Gtk.Button = self.builder.get_object("back_button")
        self.back_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(
                ('<Control>w', ),
                _('Save document and return to documents list')))

        # # self.search_button = Gtk.ToggleButton()
        # # self.search_button.set_image(Gtk.Image.new_from_icon_name('edit-find', Gtk.IconSize.LARGE_TOOLBAR))
        # # self.search_button.set_tooltip_markup(Granite.markup_accel_tooltip(('<Control>f',), 'Find text'))
        # # self.search_button.set_action_name('document.search_text')
        # # self.search_button.set_visible(False)

        self.print_button: Gtk.ToggleButton() = self.builder.get_object(
            "print_button")
        self.print_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(('<Control>p', ),
                                         _('Print the document')))

        self.extended_stats_button: Gtk.ToggleButton(
        ) = self.builder.get_object("extended_stats_button")
        self.extended_stats_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(None, _('Show document info')))

        self.share_app_menu: Gtk.MenuButton = self.builder.get_object(
            "share_app_menu")
        self.share_app_menu.set_image(
            Gtk.Image.new_from_icon_name('document-save-as',
                                         Gtk.IconSize.LARGE_TOOLBAR))
        self.share_app_menu.set_popover(MenuExport(settings=self.settings))

        self.archived_button: Gtk.ToggleButton() = self.builder.get_object(
            "archived_button")
        self.archived_button.set_tooltip_markup(
            Granite.markup_accel_tooltip(None, _('Show Archived files')))

        self.grid_menu_button: Gtk.MenuButton = self.builder.get_object(
            "grid_menu_button")
        self.grid_menu_button.set_image(
            Gtk.Image.new_from_icon_name('open-menu',
                                         Gtk.IconSize.LARGE_TOOLBAR))
        self.grid_menu_button.set_popover(MenuPopover(settings=self.settings))
        self.editor_menu_button: Gtk.MenuButton = self.builder.get_object(
            "editor_menu_button")
        self.editor_menu_button.set_image(
            Gtk.Image.new_from_icon_name('open-menu',
                                         Gtk.IconSize.LARGE_TOOLBAR))
        self.editor_menu_button.set_popover(
            MenuPopover(settings=self.settings))
Beispiel #27
0
    def __init__(self, settings: Gio.Settings, **kwargs):
        super().__init__(**kwargs)

        self.set_default_icon(Pixbuf.new_from_resource_at_scale(
            '/com/github/tenderowl/norka/icons/com.github.tenderowl.norka.svg',
            128, 128, True
        ))
        self.settings = settings
        self._configure_timeout_id = None
        self.preview = None

        self.apply_styling()

        self.current_size = (786, 520)
        self.resize(*self.settings.get_value('window-size'))
        self.connect('configure-event', self.on_configure_event)
        self.connect('destroy', self.on_window_delete_event)

        # Export clients
        self.medium_client = Medium()
        self.writeas_client = Writeas()
        self.uri_to_open = None

        # Make a header
        self.header = Header(self.settings)
        self.set_titlebar(self.header)
        self.header.show()

        # Init screens
        self.welcome_grid = Welcome()
        self.welcome_grid.connect('activated', self.on_welcome_activated)
        self.welcome_grid.connect('document-import', self.on_document_import)

        self.document_grid = DocumentGrid()
        self.document_grid.connect('document-create', self.on_document_create_activated)
        self.document_grid.connect('document-import', self.on_document_import)
        self.document_grid.view.connect('item-activated', self.on_document_item_activated)

        self.editor = Editor()

        self.screens = Gtk.Stack()
        self.screens.set_transition_duration(400)
        self.screens.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)

        self.screens.add_named(self.welcome_grid, 'welcome-grid')
        self.screens.add_named(self.document_grid, 'document-grid')
        self.screens.add_named(self.editor, 'editor-grid')

        self.screens.show_all()

        self.toast = Granite.WidgetsToast()

        self.overlay = Gtk.Overlay()
        self.overlay.add_overlay(self.screens)
        self.overlay.add_overlay(self.toast)
        self.overlay.show_all()

        self.add(self.overlay)

        # Init actions
        self.init_actions()

        # If here's at least one document in storage
        # then show documents grid
        self.check_documents_count()

        # Pull the Settings
        self.toggle_spellcheck(self.settings.get_boolean('spellcheck'))
        self.autosave = self.settings.get_boolean('autosave')
        self.set_autoindent(self.settings.get_boolean('autoindent'))
        self.set_tabs_spaces(self.settings.get_boolean('spaces-instead-of-tabs'))
        self.set_indent_width(self.settings.get_int('indent-width'))
        self.set_style_scheme(self.settings.get_string('stylescheme'))
        self.editor.update_font(self.settings.get_string('font'))
Beispiel #28
0
    gi.require_version('Granite', '1.0')
    gi.require_version('WebKit2', '4.0')
except Exception as e:
    print('''\
Some libraries seem to be missing, try installing:
gir1.2-granite-1.0 gir1.2-webkit2-4.0 gobject-introspection libgirepository1.0-dev
''')
    raise

import sys
from pathlib import Path
sys.path.append(Path(__file__).resolve().parents[1].as_posix())

try:
    from gi.repository import Granite
    _ = Granite.WidgetsSourceList()
except TypeError:
    # File "/usr/lib/python3/dist-packages/gi/overrides/__init__.py", line 326, in new_init
    #   return super_init_func(self, **new_kwargs)
    # TypeError: could not get a reference to type class
    sys.stderr.write(r'''
Error: local version of gir1.2-granite-1.0 appears to be buggy and unusable.
Try to upgrade or reinstall it or run the following potential fix:

$ sudo bash -x -c "\
    sed -i /usr/share/gir-1.0/Granite-1.0.gir -e \
      's/<namespace n/<namespace shared-library=\"libgranite.so\" n/' && \
    g-ir-compiler /usr/share/gir-1.0/Granite-1.0.gir \
      -o /usr/lib/x86_64-linux-gnu/girepository-1.0/Granite-1.0.typelib"

''')
Beispiel #29
0
    def __init__(self, settings: Gio.Settings, storage: Storage, **kwargs):
        super().__init__(**kwargs)

        self.set_default_icon(
            Pixbuf.new_from_resource_at_scale(
                f'{RESOURCE_PREFIX}/icons/com.github.tenderowl.norka.svg', 128,
                128, True))
        self.settings = settings
        self.storage = storage
        self._configure_timeout_id = None
        self.preview = None
        self.extended_stats_dialog = None

        self.apply_styling()

        self.current_size = (786, 520)
        self.resize(*self.settings.get_value('window-size'))

        hints = Gdk.Geometry()
        hints.min_width = 554
        hints.min_height = 435
        self.set_geometry_hints(None, hints, Gdk.WindowHints.MIN_SIZE)
        self.connect('configure-event', self.on_configure_event)
        self.connect('destroy', self.on_window_delete_event)

        # Export clients
        self.medium_client = Medium()
        self.writeas_client = Writeas()
        self.uri_to_open = None

        # Make a header
        self.header = Header(self.settings)
        # self.set_titlebar(self.header)
        self.header.show()

        # Init screens
        self.welcome_grid = Welcome()
        # self.welcome_grid.connect('activated', self.on_welcome_activated)
        self.welcome_grid.connect('document-import', self.on_document_import)

        self.document_grid = DocumentGrid(self.settings, storage=self.storage)
        self.document_grid.connect('path-changed', self.on_path_changed)
        self.document_grid.connect('document-create',
                                   self.on_document_create_activated)
        self.document_grid.connect('document-import', self.on_document_import)
        self.document_grid.connect('rename-folder',
                                   self.on_folder_rename_activated)
        self.document_grid.view.connect('item-activated',
                                        self.on_document_item_activated)

        self.editor = Editor(self.storage, self.settings)
        self.editor.connect('update-document-stats',
                            self.update_document_stats)

        self.screens = Gtk.Stack()
        self.screens.set_transition_duration(400)
        self.screens.set_transition_type(
            Gtk.StackTransitionType.SLIDE_LEFT_RIGHT)

        self.screens.add_named(self.welcome_grid, 'welcome-grid')
        self.screens.add_named(self.document_grid, 'document-grid')
        self.screens.add_named(self.editor, 'editor-grid')

        self.screens.show_all()

        self.toast = Granite.WidgetsToast()

        self.overlay = Gtk.Overlay()
        self.overlay.add_overlay(self.screens)
        self.overlay.add_overlay(self.toast)
        self.overlay.show_all()

        self.content_box.pack_start(self.header, False, False, 0)
        self.content_box.pack_end(self.overlay, True, True, 0)

        # Init actions
        self.init_actions()

        # If here's at least one document in storage
        # then show documents grid
        self.check_grid_items()

        # Pull the Settings
        self.toggle_spellcheck(self.settings.get_boolean('spellcheck'))
        self.autosave = self.settings.get_boolean('autosave')
        self.set_autoindent(self.settings.get_boolean('autoindent'))
        self.set_tabs_spaces(
            self.settings.get_boolean('spaces-instead-of-tabs'))
        self.set_indent_width(self.settings.get_int('indent-width'))
        self.set_style_scheme(self.settings.get_string('stylescheme'))
        self.editor.update_font(self.settings.get_string('font'))
Beispiel #30
0
    def __init__(self, transient_for, settings):
        super().__init__(transient_for=transient_for, modal=False)

        self.settings = settings
        self.set_default_size(340, 340)

        hints = Gdk.Geometry()
        hints.min_width = 340
        hints.min_height = 340
        self.set_geometry_hints(None, hints, Gdk.WindowHints.MIN_SIZE)

        self.set_border_width(5)
        self.set_deletable(False)
        self.set_title(_('Preferences'))

        self.toast = Granite.WidgetsToast(title=_("Toast"))

        indent_width = Gtk.SpinButton.new_with_range(1, 24, 1)
        indent_width.set_value(self.settings.get_int('indent-width'))
        indent_width.connect('value-changed', self.on_indent_width)

        self.sort_switch = Gtk.Switch(halign=Gtk.Align.START,
                                      valign=Gtk.Align.CENTER)
        self.sort_switch.set_state(self.settings.get_boolean('sort-desc'))
        self.sort_switch.connect("state-set", self.on_sort_desc)

        self.spellcheck_switch = Gtk.Switch(halign=Gtk.Align.START,
                                            valign=Gtk.Align.CENTER)
        self.spellcheck_switch.set_state(
            self.settings.get_boolean('spellcheck'))
        self.spellcheck_switch.connect("state-set", self.on_spellcheck)

        self.autosave_switch = Gtk.Switch(halign=Gtk.Align.START,
                                          valign=Gtk.Align.CENTER)
        self.autosave_switch.set_state(self.settings.get_boolean('autosave'))
        self.autosave_switch.connect("state-set", self.on_autosave)

        self.autoindent_switch = Gtk.Switch(halign=Gtk.Align.START,
                                            valign=Gtk.Align.CENTER)
        self.autoindent_switch.set_state(
            self.settings.get_boolean('autoindent'))
        self.autoindent_switch.connect("state-set", self.on_autoindent)

        self.spaces_tabs_switch = Gtk.Switch(halign=Gtk.Align.START,
                                             valign=Gtk.Align.CENTER)
        self.spaces_tabs_switch.set_state(
            self.settings.get_boolean('spaces-instead-of-tabs'))
        self.spaces_tabs_switch.connect("state-set", self.on_spaces_tabs)

        general_grid = Gtk.Grid(column_spacing=12, row_spacing=6)

        general_grid.attach(Granite.HeaderLabel(_("General")), 0, 0, 3, 1)
        general_grid.attach(
            Gtk.Label(_("Save files when changed:"), halign=Gtk.Align.END), 0,
            1, 1, 1)
        general_grid.attach(self.autosave_switch, 1, 1, 1, 1)
        general_grid.attach(
            Gtk.Label(_("Sort documents backwards:"), halign=Gtk.Align.END), 0,
            2, 1, 1)
        general_grid.attach(self.sort_switch, 1, 2, 1, 1)
        general_grid.attach(
            Gtk.Label(_("Spell checking:"), halign=Gtk.Align.END), 0, 3, 1, 1)
        general_grid.attach(self.spellcheck_switch, 1, 3, 1, 1)

        general_grid.attach(Granite.HeaderLabel(_("Tabs")), 0, 4, 3, 1)
        general_grid.attach(
            Gtk.Label(_("Automatic indentation:"), halign=Gtk.Align.END), 0, 5,
            1, 1)
        general_grid.attach(self.autoindent_switch, 1, 5, 1, 1)
        general_grid.attach(
            Gtk.Label(_("Insert spaces instead of tabs:"),
                      halign=Gtk.Align.END), 0, 6, 1, 1)
        general_grid.attach(self.spaces_tabs_switch, 1, 6, 1, 1)
        general_grid.attach(Gtk.Label(_("Tab width:"), halign=Gtk.Align.END),
                            0, 7, 1, 1)
        general_grid.attach(indent_width, 1, 7, 2, 1)

        # Interface grid
        interface_grid = Gtk.Grid(column_spacing=12, row_spacing=6)
        scrolled = Gtk.ScrolledWindow(hexpand=True, vexpand=True)

        self.dark_theme_switch = Gtk.Switch(halign=Gtk.Align.START,
                                            valign=Gtk.Align.CENTER)
        self.dark_theme_switch.set_state(
            self.settings.get_boolean('prefer-dark-theme'))
        self.dark_theme_switch.connect("state-set", self.on_dark_theme)

        style_chooser = GtkSource.StyleSchemeChooserWidget()
        style_chooser.connect('notify::style-scheme', self.on_scheme_changed)
        scrolled.add(style_chooser)

        scheme = GtkSource.StyleSchemeManager().get_scheme(
            self.settings.get_string('stylescheme'))
        if not scheme:
            scheme = GtkSource.StyleSchemeManager().get_scheme("classic")

        style_chooser.set_style_scheme(scheme)

        interface_grid.attach(Granite.HeaderLabel(_("Appearance")), 0, 0, 3, 1)
        interface_grid.attach(
            Gtk.Label(_("Prefer dark theme:"), halign=Gtk.Align.END), 0, 1, 2,
            1)
        interface_grid.attach(self.dark_theme_switch, 2, 1, 1, 1)
        interface_grid.attach(Granite.HeaderLabel(_("Styles")), 0, 2, 3, 1)
        interface_grid.attach(scrolled, 0, 3, 3, 1)

        # Export grid
        export_grid = Gtk.Grid(column_spacing=12, row_spacing=6)

        self.render_medium(export_grid)
        self.render_writeas(export_grid)

        # Main Stack
        main_stack = Gtk.Stack(margin=6, margin_bottom=18, margin_top=8)
        main_stack.add_titled(general_grid, "behavior", _("Behavior"))
        main_stack.add_titled(interface_grid, "interface", _("Interface"))
        main_stack.add_titled(export_grid, "export", _("Export"))

        main_stackswitcher = Gtk.StackSwitcher()
        main_stackswitcher.set_stack(main_stack)
        main_stackswitcher.set_halign(Gtk.Align.CENTER)

        main_grid = Gtk.Grid()
        main_grid.attach(main_stackswitcher, 0, 0, 1, 1)
        main_grid.attach(main_stack, 0, 1, 1, 1)

        self.overlay = Gtk.Overlay()
        self.overlay.add(main_grid)
        self.overlay.add_overlay(self.toast)
        self.get_content_area().add(self.overlay)

        close_button = Gtk.Button(label=_("Close"))
        close_button.connect('clicked', self.on_close_activated)
        self.add_action_widget(close_button, 0)