def __init__(self, parent, message, yes_label='yes', no_label='no'):

        ClientGUIScrolledPanels.ResizingScrolledPanel.__init__(self, parent)

        self._yes = ClientGUICommon.BetterButton(self, yes_label,
                                                 self.parentWidget().done,
                                                 QW.QDialog.Accepted)
        self._yes.setObjectName('HydrusAccept')
        self._yes.setText(yes_label)

        self._no = ClientGUICommon.BetterButton(self, no_label,
                                                self.parentWidget().done,
                                                QW.QDialog.Rejected)
        self._no.setObjectName('HydrusCancel')
        self._no.setText(no_label)

        #

        hbox = QP.HBoxLayout()

        QP.AddToLayout(hbox, self._yes)
        QP.AddToLayout(hbox, self._no)

        vbox = QP.VBoxLayout()

        text = ClientGUICommon.BetterStaticText(self, message)
        text.setWordWrap(True)

        QP.AddToLayout(vbox, text)
        QP.AddToLayout(vbox, hbox, CC.FLAGS_BUTTON_SIZER)

        self.widget().setLayout(vbox)

        HG.client_controller.CallAfterQtSafe(self._yes, self._yes.setFocus,
                                             QC.Qt.OtherFocusReason)
    def __init__(self, parent, label):

        ClientGUIScrolledPanels.ResizingScrolledPanel.__init__(self, parent)

        self._commit = ClientGUICommon.BetterButton(self,
                                                    'commit and continue',
                                                    self.parentWidget().done,
                                                    QW.QDialog.Accepted)
        self._commit.setObjectName('HydrusAccept')

        self._back = ClientGUICommon.BetterButton(self, 'go back',
                                                  self.parentWidget().done,
                                                  QW.QDialog.Rejected)

        vbox = QP.VBoxLayout()

        QP.AddToLayout(
            vbox,
            QP.MakeQLabelWithAlignment(label, self, QC.Qt.AlignVCenter
                                       | QC.Qt.AlignHCenter),
            CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._commit, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR)
        QP.AddToLayout(
            vbox,
            QP.MakeQLabelWithAlignment('-or-', self, QC.Qt.AlignVCenter
                                       | QC.Qt.AlignHCenter),
            CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._back, CC.FLAGS_EXPAND_PERPENDICULAR)

        self.widget().setLayout(vbox)

        HG.client_controller.CallAfterQtSafe(self._commit,
                                             self._commit.setFocus,
                                             QC.Qt.OtherFocusReason)
Example #3
0
 def __init__( self, parent, label ):
     
     ClientGUIScrolledPanels.ResizingScrolledPanel.__init__( self, parent )
     
     self._commit = ClientGUICommon.BetterButton( self, 'commit', self.parentWidget().done, QW.QDialog.Accepted )
     self._commit.setObjectName( 'HydrusAccept' )
     
     self._forget = ClientGUICommon.BetterButton( self, 'forget', self.parentWidget().done, QW.QDialog.Rejected )
     self._forget.setObjectName( 'HydrusCancel' )
     
     def cancel_callback( parent ):
         
         parent.SetCancelled( True )
         parent.done( QW.QDialog.Rejected )
         
     
     self._back = ClientGUICommon.BetterButton( self, 'back to filtering', cancel_callback, parent )
     
     hbox = QP.HBoxLayout()
     
     QP.AddToLayout( hbox, self._commit, CC.FLAGS_EXPAND_BOTH_WAYS )
     QP.AddToLayout( hbox, self._forget, CC.FLAGS_EXPAND_BOTH_WAYS )
     
     vbox = QP.VBoxLayout()
     
     QP.AddToLayout( vbox, QP.MakeQLabelWithAlignment( label, self, QC.Qt.AlignVCenter | QC.Qt.AlignHCenter ), CC.FLAGS_EXPAND_PERPENDICULAR )
     QP.AddToLayout( vbox, hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
     QP.AddToLayout( vbox, QP.MakeQLabelWithAlignment( '-or-', self, QC.Qt.AlignVCenter | QC.Qt.AlignHCenter ), CC.FLAGS_EXPAND_PERPENDICULAR )
     QP.AddToLayout( vbox, self._back, CC.FLAGS_EXPAND_PERPENDICULAR )
     
     self.widget().setLayout( vbox )
     
     HG.client_controller.CallAfterQtSafe( self._commit, self._commit.setFocus, QC.Qt.OtherFocusReason )
    def __init__(self,
                 parent,
                 message,
                 title='Are you sure?',
                 yes_tuples=None,
                 no_label='no'):

        if yes_tuples is None:

            yes_tuples = [('yes', 'yes')]

        Dialog.__init__(self, parent, title, position='center')

        self._value = None

        yes_buttons = []

        for (label, data) in yes_tuples:

            yes_button = ClientGUICommon.BetterButton(self, label, self._DoYes,
                                                      data)
            yes_button.setObjectName('HydrusAccept')

            yes_buttons.append(yes_button)

        self._no = ClientGUICommon.BetterButton(self, no_label, self.done,
                                                QW.QDialog.Rejected)
        self._no.setObjectName('HydrusCancel')

        #

        hbox = QP.HBoxLayout()

        for yes_button in yes_buttons:

            QP.AddToLayout(hbox, yes_button, CC.FLAGS_CENTER_PERPENDICULAR)

        QP.AddToLayout(hbox, self._no, CC.FLAGS_CENTER_PERPENDICULAR)

        vbox = QP.VBoxLayout()

        text = ClientGUICommon.BetterStaticText(self, message)
        text.setWordWrap(True)

        QP.AddToLayout(vbox, text, CC.FLAGS_EXPAND_BOTH_WAYS)
        QP.AddToLayout(vbox, hbox, CC.FLAGS_ON_RIGHT)

        self.setLayout(vbox)

        size_hint = self.sizeHint()

        size_hint.setWidth(max(size_hint.width(), 250))

        QP.SetInitialSize(self, size_hint)

        HG.client_controller.CallAfterQtSafe(yes_buttons[0],
                                             yes_buttons[0].setFocus,
                                             QC.Qt.OtherFocusReason)
Example #5
0
    def __init__(self, parent, service_key, media, activate_callable):

        QW.QWidget.__init__(self, parent)

        self._service_key = service_key
        self._media = media
        self._last_fetched_tags = []

        self._script_choice = ClientGUICommon.BetterChoice(self)

        self._script_choice.setEnabled(False)

        self._have_fetched = False

        self._fetch_button = ClientGUICommon.BetterButton(
            self, 'fetch tags', self.FetchTags)

        self._fetch_button.setEnabled(False)

        self._script_management = ClientGUIParsing.ScriptManagementControl(
            self)

        self._tags = ListBoxTagsSuggestionsFavourites(self,
                                                      self._service_key,
                                                      activate_callable,
                                                      sort_tags=True)

        self._add_all = ClientGUICommon.BetterButton(self, 'add all',
                                                     self._tags.ActivateAll)

        vbox = QP.VBoxLayout()

        QP.AddToLayout(vbox, self._script_choice,
                       CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._fetch_button, CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._script_management,
                       CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._add_all, CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._tags, CC.FLAGS_EXPAND_BOTH_WAYS)

        self._SetTags([])

        self.setLayout(vbox)

        self._FetchScripts()

        self._tags.mouseActivationOccurred.connect(
            self.mouseActivationOccurred)
Example #6
0
 def AddButton( self, label, clicked_func, enabled_only_on_selection = False, enabled_only_on_single_selection = False, enabled_check_func = None ):
     
     button = ClientGUICommon.BetterButton( self, label, clicked_func )
     
     self._AddButton( button, enabled_only_on_selection = enabled_only_on_selection, enabled_only_on_single_selection = enabled_only_on_single_selection, enabled_check_func = enabled_check_func )
     
     self._UpdateButtons()
 def __init__( self, parent, external_port, protocol_type, internal_port, description, duration ):
     
     Dialog.__init__( self, parent, 'configure upnp mapping' )
     
     self._external_port = QP.MakeQSpinBox( self, min=0, max=65535 )
     
     self._protocol_type = ClientGUICommon.BetterChoice( self )
     self._protocol_type.addItem( 'TCP', 'TCP' )
     self._protocol_type.addItem( 'UDP', 'UDP' )
     
     self._internal_port = QP.MakeQSpinBox( self, min=0, max=65535 )
     self._description = QW.QLineEdit( self )
     self._duration = QP.MakeQSpinBox( self, min=0, max=86400 )
     
     self._ok = ClientGUICommon.BetterButton( self, 'OK', self.done, QW.QDialog.Accepted )
     self._ok.setObjectName( 'HydrusAccept' )
     
     self._cancel = QW.QPushButton( 'Cancel', self )
     self._cancel.clicked.connect( self.reject )
     self._cancel.setObjectName( 'HydrusCancel' )
     
     #
     
     self._external_port.setValue( external_port )
     
     if protocol_type == 'TCP': self._protocol_type.setCurrentIndex( 0 )
     elif protocol_type == 'UDP': self._protocol_type.setCurrentIndex( 1 )
     
     self._internal_port.setValue( internal_port )
     self._description.setText( description )
     self._duration.setValue( duration )
     
     #
     
     rows = []
     
     rows.append( ( 'external port: ', self._external_port ) )
     rows.append( ( 'protocol type: ', self._protocol_type ) )
     rows.append( ( 'internal port: ', self._internal_port ) )
     rows.append( ( 'description: ', self._description ) )
     rows.append( ( 'duration (0 = indefinite): ', self._duration ) )
     
     gridbox = ClientGUICommon.WrapInGrid( self, rows )
     
     b_box = QP.HBoxLayout()
     QP.AddToLayout( b_box, self._ok, CC.FLAGS_CENTER_PERPENDICULAR )
     QP.AddToLayout( b_box, self._cancel, CC.FLAGS_CENTER_PERPENDICULAR )
     
     vbox = QP.VBoxLayout()
     
     QP.AddToLayout( vbox, gridbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
     QP.AddToLayout( vbox, b_box, CC.FLAGS_ON_RIGHT )
     
     self.setLayout( vbox )
     
     size_hint = self.sizeHint()
     
     QP.SetInitialSize( self, size_hint )
     
     HG.client_controller.CallAfterQtSafe( self._ok, self._ok.setFocus, QC.Qt.OtherFocusReason)
Example #8
0
 def __init__( self, parent, manager ):
     
     PopupWindow.__init__( self, parent, manager )
     
     hbox = QP.HBoxLayout()
     
     self._text = ClientGUICommon.BetterStaticText( self )
     
     self._expand_collapse = ClientGUICommon.BetterButton( self, '\u25bc', self.ExpandCollapse )
     
     dismiss_all = ClientGUICommon.BetterButton( self, 'dismiss all', self._manager.DismissAll )
     
     QP.AddToLayout( hbox, self._text, CC.FLAGS_VCENTER )
     QP.AddToLayout( hbox, (20,20), CC.FLAGS_EXPAND_BOTH_WAYS )
     QP.AddToLayout( hbox, dismiss_all, CC.FLAGS_VCENTER )
     QP.AddToLayout( hbox, self._expand_collapse, CC.FLAGS_VCENTER )
     
     self.setLayout( hbox )
 def __init__( self, parent, service_key, tags, expand_parents = True, message = '', show_sibling_text = False ):
     
     Dialog.__init__( self, parent, 'input tags' )
     
     self._service_key = service_key
     
     self._tags = ClientGUIListBoxes.ListBoxTagsStringsAddRemove( self, service_key = service_key, show_sibling_text = show_sibling_text )
     
     self._expand_parents = expand_parents
     
     self._tag_autocomplete = ClientGUIACDropdown.AutoCompleteDropdownTagsWrite( self, self.EnterTags, self._expand_parents, CC.LOCAL_FILE_SERVICE_KEY, service_key, null_entry_callable = self.OK, show_paste_button = True )
     
     self._ok = ClientGUICommon.BetterButton( self, 'OK', self.done, QW.QDialog.Accepted )
     self._ok.setObjectName( 'HydrusAccept' )
     
     self._cancel = QW.QPushButton( 'Cancel', self )
     self._cancel.clicked.connect( self.reject )
     self._cancel.setObjectName( 'HydrusCancel' )
     
     #
     
     self._tags.SetTags( tags )
     
     #
     
     b_box = QP.HBoxLayout()
     
     QP.AddToLayout( b_box, self._ok, CC.FLAGS_CENTER_PERPENDICULAR )
     QP.AddToLayout( b_box, self._cancel, CC.FLAGS_CENTER_PERPENDICULAR )
     
     vbox = QP.VBoxLayout()
     
     if message != '':
         
         st = ClientGUICommon.BetterStaticText( self, message )
         
         st.setWordWrap( True )
         
         QP.AddToLayout( vbox, st, CC.FLAGS_EXPAND_PERPENDICULAR )
         
     
     QP.AddToLayout( vbox, self._tags, CC.FLAGS_EXPAND_BOTH_WAYS )
     QP.AddToLayout( vbox, self._tag_autocomplete )
     QP.AddToLayout( vbox, b_box, CC.FLAGS_ON_RIGHT )
     
     self.setLayout( vbox )
     
     size_hint = self.sizeHint()
     
     size_hint.setWidth( max( size_hint.width(), 300 ) )
     
     QP.SetInitialSize( self, size_hint )
     
     HG.client_controller.CallAfterQtSafe( self._tag_autocomplete, self._tag_autocomplete.setFocus, QC.Qt.OtherFocusReason)
Example #10
0
 def __init__( self, parent, management_controller = None ):
     
     QW.QWidget.__init__( self, parent )
     
     self._management_controller = management_controller
     
     self._sort_type = ( 'system', CC.SORT_FILES_BY_FILESIZE )
     
     self._sort_type_button = ClientGUICommon.BetterButton( self, 'sort', self._SortTypeButtonClick )
     self._sort_order_choice = ClientGUICommon.BetterChoice( self )
     
     type_width = ClientGUIFunctions.ConvertTextToPixelWidth( self._sort_type_button, 14 )
     
     self._sort_type_button.setMinimumWidth( type_width )
     
     asc_width = ClientGUIFunctions.ConvertTextToPixelWidth( self._sort_order_choice, 14 )
     
     self._sort_order_choice.setMinimumWidth( asc_width )
     
     self._sort_order_choice.addItem( '', CC.SORT_ASC )
     
     self._UpdateSortTypeLabel()
     self._UpdateAscLabels()
     
     #
     
     hbox = QP.HBoxLayout( margin = 0 )
     
     QP.AddToLayout( hbox, self._sort_type_button, CC.FLAGS_EXPAND_BOTH_WAYS )
     QP.AddToLayout( hbox, self._sort_order_choice, CC.FLAGS_CENTER_PERPENDICULAR )
     
     self.setLayout( hbox )
     
     HG.client_controller.sub( self, 'ACollectHappened', 'a_collect_happened' )
     HG.client_controller.sub( self, 'BroadcastSort', 'do_page_sort' )
     
     if self._management_controller is not None and self._management_controller.HasVariable( 'media_sort' ):
         
         media_sort = self._management_controller.GetVariable( 'media_sort' )
         
         try:
             
             self.SetSort( media_sort )
             
         except:
             
             default_sort = ClientMedia.MediaSort( ( 'system', CC.SORT_FILES_BY_FILESIZE ), CC.SORT_ASC )
             
             self.SetSort( default_sort )
             
         
     
     self._sort_order_choice.currentIndexChanged.connect( self.EventSortAscChoice )
Example #11
0
    def __init__(self, parent, manager):

        PopupWindow.__init__(self, parent, manager)

        hbox = QP.HBoxLayout()

        self._text = ClientGUICommon.BetterStaticText(self)

        self._expand_collapse = ClientGUICommon.BetterButton(
            self, '\u25bc', self.ExpandCollapse)

        dismiss_all = ClientGUICommon.BetterButton(self, 'dismiss all',
                                                   self._manager.DismissAll)

        QP.AddToLayout(hbox, self._text, CC.FLAGS_CENTER_PERPENDICULAR)
        hbox.addStretch(1)
        QP.AddToLayout(hbox, dismiss_all, CC.FLAGS_CENTER_PERPENDICULAR)
        QP.AddToLayout(hbox, self._expand_collapse,
                       CC.FLAGS_CENTER_PERPENDICULAR)

        self.setLayout(hbox)
    def __init__(self, parent, url_tree):

        Dialog.__init__(self, parent, 'select items')

        self._tree = QP.TreeWidgetWithInheritedCheckState(self)

        self._ok = ClientGUICommon.BetterButton(self, 'OK', self.done,
                                                QW.QDialog.Accepted)
        self._ok.setObjectName('HydrusAccept')

        self._cancel = QW.QPushButton('Cancel', self)
        self._cancel.clicked.connect(self.reject)
        self._cancel.setObjectName('HydrusCancel')

        #

        (text_gumpf, name, size, children) = url_tree

        root_name = self._RenderItemName(name, size)

        root_item = QW.QTreeWidgetItem()
        root_item.setText(0, root_name)
        root_item.setCheckState(0, QC.Qt.Checked)
        self._tree.addTopLevelItem(root_item)

        self._AddDirectory(root_item, children)

        root_item.setExpanded(True)

        #

        button_hbox = QP.HBoxLayout()

        QP.AddToLayout(button_hbox, self._ok, CC.FLAGS_CENTER_PERPENDICULAR)
        QP.AddToLayout(button_hbox, self._cancel,
                       CC.FLAGS_CENTER_PERPENDICULAR)

        vbox = QP.VBoxLayout()

        QP.AddToLayout(vbox, self._tree, CC.FLAGS_EXPAND_BOTH_WAYS)
        QP.AddToLayout(vbox, button_hbox, CC.FLAGS_ON_RIGHT)

        self.setLayout(vbox)

        size_hint = self.sizeHint()

        size_hint.setWidth(max(size_hint.width(), 640))
        size_hint.setHeight(max(size_hint.height(), 640))

        QP.SetInitialSize(self, size_hint)
    def __init__(self, controller, title,
                 frame_splash_status: FrameSplashStatus):

        self._controller = controller

        QW.QWidget.__init__(self, None)

        self.setWindowFlag(QC.Qt.CustomizeWindowHint)
        self.setWindowFlag(QC.Qt.WindowContextHelpButtonHint, on=False)
        self.setWindowFlag(QC.Qt.WindowCloseButtonHint, on=False)
        self.setWindowFlag(QC.Qt.WindowMaximizeButtonHint, on=False)
        self.setAttribute(QC.Qt.WA_DeleteOnClose)

        self.setWindowTitle(title)

        self.setWindowIcon(QG.QIcon(self._controller.frame_icon_pixmap))

        self._my_panel = FrameSplashPanel(self, self._controller,
                                          frame_splash_status)

        self._cancel_shutdown_maintenance = ClientGUICommon.BetterButton(
            self, 'stop shutdown maintenance', self.CancelShutdownMaintenance)

        self._cancel_shutdown_maintenance.hide()

        #

        self._vbox = QP.VBoxLayout()

        QP.AddToLayout(self._vbox, self._cancel_shutdown_maintenance,
                       CC.FLAGS_EXPAND_PERPENDICULAR)

        QP.AddToLayout(self._vbox, self._my_panel,
                       CC.FLAGS_EXPAND_SIZER_BOTH_WAYS)

        self.setLayout(self._vbox)

        screen = ClientGUIFunctions.GetMouseScreen()

        if screen is not None:

            self.move(screen.availableGeometry().center() -
                      self.rect().center())

        self.show()

        self.raise_()
    def __init__(self, parent, payload_objs):

        ClientGUIScrolledPanels.ReviewPanel.__init__(self, parent)

        self._payload_objs = payload_objs

        self._directory_picker = QP.DirPickerCtrl(self)

        dp_width = ClientGUIFunctions.ConvertTextToPixelWidth(
            self._directory_picker, 52)

        self._directory_picker.setMinimumWidth(dp_width)

        self._width = QP.MakeQSpinBox(self, min=100, max=4096)

        self._export = ClientGUICommon.BetterButton(self, 'export',
                                                    self.Export)

        #

        last_png_export_dir = HG.client_controller.new_options.GetNoneableString(
            'last_png_export_dir')

        if last_png_export_dir is not None:

            self._directory_picker.SetPath(last_png_export_dir)

        self._width.setValue(512)

        self._Update()

        #

        rows = []

        rows.append(('export path: ', self._directory_picker))
        rows.append(('png width: ', self._width))
        rows.append(('', self._export))

        gridbox = ClientGUICommon.WrapInGrid(self, rows)

        self.widget().setLayout(gridbox)

        self._directory_picker.dirPickerChanged.connect(self._Update)
Example #15
0
    def __init__(self, parent, checker_options):

        ClientGUIScrolledPanels.EditPanel.__init__(self, parent)

        help_button = ClientGUICommon.BetterBitmapButton(
            self,
            CC.global_pixmaps().help, self._ShowHelp)
        help_button.setToolTip('Show help regarding these checker options.')

        help_hbox = ClientGUICommon.WrapInText(help_button, self,
                                               'help for this panel -->',
                                               QG.QColor(0, 0, 255))

        from hydrus.client import ClientDefaults

        defaults_panel = ClientGUICommon.StaticBox(self, 'reasonable defaults')

        defaults_1 = ClientGUICommon.BetterButton(
            defaults_panel, 'thread', self.SetValue,
            ClientDefaults.GetDefaultCheckerOptions('thread'))
        defaults_2 = ClientGUICommon.BetterButton(
            defaults_panel, 'slow thread', self.SetValue,
            ClientDefaults.GetDefaultCheckerOptions('slow thread'))
        defaults_3 = ClientGUICommon.BetterButton(
            defaults_panel, 'faster tag subscription', self.SetValue,
            ClientDefaults.GetDefaultCheckerOptions('fast tag subscription'))
        defaults_4 = ClientGUICommon.BetterButton(
            defaults_panel, 'medium tag/artist subscription', self.SetValue,
            ClientDefaults.GetDefaultCheckerOptions('artist subscription'))
        defaults_5 = ClientGUICommon.BetterButton(
            defaults_panel, 'slower tag subscription', self.SetValue,
            ClientDefaults.GetDefaultCheckerOptions('slow tag subscription'))

        #

        # add statictext or whatever that will update on any updates above to say 'given velocity of blah and last check at blah, next check in 5 mins'
        # or indeed this could just take the file_seed cache and last check of the caller, if there is one
        # this would be more useful to the user, to know 'right, on ok, it'll refresh in 30 mins'
        # this is actually more complicated--it also needs last check time to calc a fresh file velocity based on new death_file_velocity

        #

        min_unit_value = 0
        max_unit_value = 1000
        min_time_delta = 60

        self._death_file_velocity = VelocityCtrl(self,
                                                 min_unit_value,
                                                 max_unit_value,
                                                 min_time_delta,
                                                 days=True,
                                                 hours=True,
                                                 minutes=True,
                                                 per_phrase='in',
                                                 unit='files')

        self._flat_check_period_checkbox = QW.QCheckBox(self)

        #

        if HG.client_controller.new_options.GetBoolean('advanced_mode'):

            never_faster_than_min = 1
            never_slower_than_min = 1

            flat_check_period_min = 1

        else:

            never_faster_than_min = 30
            never_slower_than_min = 600

            flat_check_period_min = 180

        self._reactive_check_panel = ClientGUICommon.StaticBox(
            self, 'reactive checking')

        self._intended_files_per_check = QP.MakeQSpinBox(
            self._reactive_check_panel, min=1, max=1000)

        self._never_faster_than = TimeDeltaCtrl(self._reactive_check_panel,
                                                min=never_faster_than_min,
                                                days=True,
                                                hours=True,
                                                minutes=True,
                                                seconds=True)

        self._never_slower_than = TimeDeltaCtrl(self._reactive_check_panel,
                                                min=never_slower_than_min,
                                                days=True,
                                                hours=True,
                                                minutes=True,
                                                seconds=True)

        #

        self._static_check_panel = ClientGUICommon.StaticBox(
            self, 'static checking')

        self._flat_check_period = TimeDeltaCtrl(self._static_check_panel,
                                                min=flat_check_period_min,
                                                days=True,
                                                hours=True,
                                                minutes=True,
                                                seconds=True)

        #

        self.SetValue(checker_options)

        #

        defaults_panel.Add(defaults_1, CC.FLAGS_EXPAND_PERPENDICULAR)
        defaults_panel.Add(defaults_2, CC.FLAGS_EXPAND_PERPENDICULAR)
        defaults_panel.Add(defaults_3, CC.FLAGS_EXPAND_PERPENDICULAR)
        defaults_panel.Add(defaults_4, CC.FLAGS_EXPAND_PERPENDICULAR)
        defaults_panel.Add(defaults_5, CC.FLAGS_EXPAND_PERPENDICULAR)

        #

        #

        rows = []

        rows.append(
            ('intended new files per check: ', self._intended_files_per_check))
        rows.append(
            ('never check faster than once per: ', self._never_faster_than))
        rows.append(
            ('never check slower than once per: ', self._never_slower_than))

        gridbox = ClientGUICommon.WrapInGrid(self._reactive_check_panel, rows)

        self._reactive_check_panel.Add(gridbox,
                                       CC.FLAGS_EXPAND_SIZER_PERPENDICULAR)

        #

        rows = []

        rows.append(('check period: ', self._flat_check_period))

        gridbox = ClientGUICommon.WrapInGrid(self._static_check_panel, rows)

        self._static_check_panel.Add(gridbox,
                                     CC.FLAGS_EXPAND_SIZER_PERPENDICULAR)

        #

        rows = []

        rows.append(('stop checking if new files found falls below: ',
                     self._death_file_velocity))
        rows.append(('just check at a static, regular interval: ',
                     self._flat_check_period_checkbox))

        gridbox = ClientGUICommon.WrapInGrid(self, rows)

        vbox = QP.VBoxLayout()

        QP.AddToLayout(vbox, help_hbox, CC.FLAGS_BUTTON_SIZER)
        QP.AddToLayout(vbox, defaults_panel, CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR)

        if HG.client_controller.new_options.GetBoolean('advanced_mode'):

            label = 'As you are in advanced mode, these options have extremely low limits. This is intended only for testing and small scale private network tasks. Do not use very fast check times for real world use on public websites, as it is wasteful and rude, hydrus will be overloaded with high-CPU parsing work, and you may get your IP banned.'

            st = ClientGUICommon.BetterStaticText(self, label=label)
            st.setObjectName('HydrusWarning')

            st.setWordWrap(True)

            QP.AddToLayout(vbox, st, CC.FLAGS_EXPAND_PERPENDICULAR)

        QP.AddToLayout(vbox, self._reactive_check_panel,
                       CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._static_check_panel,
                       CC.FLAGS_EXPAND_PERPENDICULAR)

        self.widget().setLayout(vbox)

        #

        self._flat_check_period_checkbox.clicked.connect(
            self.EventFlatPeriodCheck)
    def __init__(self, parent, selectable_mimes):

        OptionsPanel.__init__(self, parent)

        self._selectable_mimes = set(selectable_mimes)

        self._mimes_to_checkboxes = {}
        self._general_mime_types_to_checkboxes = {}
        self._general_mime_types_to_buttons = {}

        general_mime_types = []

        general_mime_types.append(HC.GENERAL_IMAGE)
        general_mime_types.append(HC.GENERAL_ANIMATION)
        general_mime_types.append(HC.GENERAL_VIDEO)
        general_mime_types.append(HC.GENERAL_AUDIO)
        general_mime_types.append(HC.GENERAL_APPLICATION)

        gridbox = QP.GridLayout(cols=3)

        gridbox.setColumnStretch(2, 1)

        for general_mime_type in general_mime_types:

            mimes_in_type = self._GetMimesForGeneralMimeType(general_mime_type)

            if len(mimes_in_type) == 0:

                continue

            general_mime_checkbox = QW.QCheckBox(
                HC.mime_string_lookup[general_mime_type], self)
            general_mime_checkbox.clicked.connect(self.EventMimeGroupCheckbox)

            self._general_mime_types_to_checkboxes[
                general_mime_type] = general_mime_checkbox

            QP.AddToLayout(gridbox, general_mime_checkbox,
                           CC.FLAGS_CENTER_PERPENDICULAR)

            show_hide_button = ClientGUICommon.BetterButton(
                self, self.BUTTON_CURRENTLY_SHOWING, self._ButtonShowHide,
                general_mime_type)

            max_width = ClientGUIFunctions.ConvertTextToPixelWidth(
                show_hide_button, 5)

            show_hide_button.setMaximumWidth(max_width)

            self._general_mime_types_to_buttons[
                general_mime_type] = show_hide_button

            QP.AddToLayout(gridbox, show_hide_button,
                           CC.FLAGS_CENTER_PERPENDICULAR)

            vbox = QP.VBoxLayout()

            for mime in mimes_in_type:

                m_checkbox = QW.QCheckBox(HC.mime_string_lookup[mime], self)
                m_checkbox.clicked.connect(self.EventMimeCheckbox)

                self._mimes_to_checkboxes[mime] = m_checkbox

                QP.AddToLayout(vbox, m_checkbox, CC.FLAGS_EXPAND_PERPENDICULAR)

            QP.AddToLayout(gridbox, vbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS)

        self.setLayout(gridbox)
    def __init__(self,
                 parent,
                 message,
                 default='',
                 placeholder=None,
                 allow_blank=False,
                 suggestions=None,
                 max_chars=None,
                 password_entry=False,
                 min_char_width=72):

        if suggestions is None:

            suggestions = []

        Dialog.__init__(self, parent, 'enter text', position='center')

        self._chosen_suggestion = None
        self._allow_blank = allow_blank
        self._max_chars = max_chars

        button_choices = []

        for text in suggestions:

            button_choices.append(
                ClientGUICommon.BetterButton(self, text, self.ButtonChoice,
                                             text))

        self._text = QW.QLineEdit(self)
        self._text.textChanged.connect(self.EventText)
        self._text.installEventFilter(
            ClientGUICommon.TextCatchEnterEventFilter(self._text,
                                                      self.EnterText))

        width = ClientGUIFunctions.ConvertTextToPixelWidth(
            self._text, min_char_width)

        self._text.setMinimumWidth(width)

        if password_entry:

            self._text.setEchoMode(QW.QLineEdit.Password)

        if self._max_chars is not None:

            self._text.setMaxLength(self._max_chars)

        self._ok = ClientGUICommon.BetterButton(self, 'ok', self.done,
                                                QW.QDialog.Accepted)
        self._ok.setObjectName('HydrusAccept')

        self._cancel = QW.QPushButton('cancel', self)
        self._cancel.clicked.connect(self.reject)
        self._cancel.setObjectName('HydrusCancel')

        #

        self._text.setText(default)

        if placeholder is not None:

            self._text.setPlaceholderText(placeholder)

        if len(default) > 0:

            self._text.setSelection(0, len(default))

        self._CheckText()

        #

        hbox = QP.HBoxLayout()

        QP.AddToLayout(hbox, self._ok, CC.FLAGS_CENTER_PERPENDICULAR)
        QP.AddToLayout(hbox, self._cancel, CC.FLAGS_CENTER_PERPENDICULAR)

        st_message = ClientGUICommon.BetterStaticText(self, message)
        st_message.setWordWrap(True)

        vbox = QP.VBoxLayout()

        QP.AddToLayout(vbox, st_message, CC.FLAGS_EXPAND_PERPENDICULAR)

        for button in button_choices:

            QP.AddToLayout(vbox, button, CC.FLAGS_EXPAND_PERPENDICULAR)

        QP.AddToLayout(vbox, self._text, CC.FLAGS_EXPAND_BOTH_WAYS)
        QP.AddToLayout(vbox, hbox, CC.FLAGS_ON_RIGHT)

        self.setLayout(vbox)

        size_hint = self.sizeHint()

        size_hint.setWidth(max(size_hint.width(), 250))

        QP.SetInitialSize(self, size_hint)
Example #18
0
    def __init__(self, parent, flat_media, do_export_and_then_quit=False):

        ClientGUIScrolledPanels.ReviewPanel.__init__(self, parent)

        new_options = HG.client_controller.new_options

        self._media_to_paths = {}
        self._existing_filenames = set()
        self._last_phrase_used = ''
        self._last_dir_used = ''

        self._tags_box = ClientGUIListBoxes.StaticBoxSorterForListBoxTags(
            self, 'files\' tags')

        services_manager = HG.client_controller.services_manager

        self._neighbouring_txt_tag_service_keys = services_manager.FilterValidServiceKeys(
            new_options.GetKeyList(
                'default_neighbouring_txt_tag_service_keys'))

        t = ClientGUIListBoxes.ListBoxTagsMedia(self._tags_box,
                                                ClientTags.TAG_DISPLAY_ACTUAL,
                                                include_counts=True)

        self._tags_box.SetTagsBox(t)

        self._tags_box.setMinimumSize(QC.QSize(220, 300))

        self._paths = ClientGUIListCtrl.BetterListCtrl(
            self,
            CGLC.COLUMN_LIST_EXPORT_FILES.ID,
            24,
            self._ConvertDataToListCtrlTuples,
            use_simple_delete=True)

        self._paths.Sort()

        self._export_path_box = ClientGUICommon.StaticBox(self, 'export path')

        self._directory_picker = QP.DirPickerCtrl(self._export_path_box)
        self._directory_picker.dirPickerChanged.connect(self._RefreshPaths)

        self._open_location = QW.QPushButton('open this location',
                                             self._export_path_box)
        self._open_location.clicked.connect(self.EventOpenLocation)

        self._filenames_box = ClientGUICommon.StaticBox(self, 'filenames')

        self._pattern = QW.QLineEdit(self._filenames_box)

        self._update = QW.QPushButton('update', self._filenames_box)
        self._update.clicked.connect(self._RefreshPaths)

        self._examples = ClientGUICommon.ExportPatternButton(
            self._filenames_box)

        self._delete_files_after_export = QW.QCheckBox(
            'delete files from client after export?', self)
        self._delete_files_after_export.setObjectName('HydrusWarning')

        self._export_symlinks = QW.QCheckBox('EXPERIMENTAL: export symlinks',
                                             self)
        self._export_symlinks.setObjectName('HydrusWarning')

        text = 'This will export all the files\' tags, newline separated, into .txts beside the files themselves.'

        self._export_tag_txts_services_button = ClientGUICommon.BetterButton(
            self, 'set .txt services', self._SetTxtServices)

        self._export_tag_txts = QW.QCheckBox('export tags to .txt files?',
                                             self)
        self._export_tag_txts.setToolTip(text)
        self._export_tag_txts.clicked.connect(self.EventExportTagTxtsChanged)

        self._export = QW.QPushButton('export', self)
        self._export.clicked.connect(self._DoExport)

        #

        export_path = ClientExporting.GetExportPath()

        self._directory_picker.SetPath(export_path)

        phrase = new_options.GetString('export_phrase')

        self._pattern.setText(phrase)

        if len(self._neighbouring_txt_tag_service_keys) > 0:

            self._export_tag_txts.setChecked(True)

        self._paths.SetData(list(enumerate(flat_media)))

        self._delete_files_after_export.setChecked(
            HG.client_controller.new_options.GetBoolean(
                'delete_files_after_export'))
        self._delete_files_after_export.clicked.connect(
            self.EventDeleteFilesChanged)

        if not HG.client_controller.new_options.GetBoolean('advanced_mode'):

            self._export_symlinks.setVisible(False)

        #

        top_hbox = QP.HBoxLayout()

        QP.AddToLayout(top_hbox, self._tags_box, CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(top_hbox, self._paths, CC.FLAGS_EXPAND_BOTH_WAYS)

        hbox = QP.HBoxLayout()

        QP.AddToLayout(hbox, self._directory_picker, CC.FLAGS_EXPAND_BOTH_WAYS)
        QP.AddToLayout(hbox, self._open_location,
                       CC.FLAGS_CENTER_PERPENDICULAR)

        self._export_path_box.Add(hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR)

        hbox = QP.HBoxLayout()

        QP.AddToLayout(hbox, self._pattern, CC.FLAGS_EXPAND_BOTH_WAYS)
        QP.AddToLayout(hbox, self._update, CC.FLAGS_CENTER_PERPENDICULAR)
        QP.AddToLayout(hbox, self._examples, CC.FLAGS_CENTER_PERPENDICULAR)

        self._filenames_box.Add(hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR)

        txt_hbox = QP.HBoxLayout()

        QP.AddToLayout(txt_hbox, self._export_tag_txts_services_button,
                       CC.FLAGS_CENTER_PERPENDICULAR)
        QP.AddToLayout(txt_hbox, self._export_tag_txts,
                       CC.FLAGS_CENTER_PERPENDICULAR)

        vbox = QP.VBoxLayout()

        QP.AddToLayout(vbox, top_hbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS)
        QP.AddToLayout(vbox, self._export_path_box,
                       CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._filenames_box,
                       CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._delete_files_after_export,
                       CC.FLAGS_ON_RIGHT)
        QP.AddToLayout(vbox, self._export_symlinks, CC.FLAGS_ON_RIGHT)
        QP.AddToLayout(vbox, txt_hbox, CC.FLAGS_ON_RIGHT)
        QP.AddToLayout(vbox, self._export, CC.FLAGS_ON_RIGHT)

        self.widget().setLayout(vbox)

        self._RefreshTags()

        self._UpdateTxtButton()

        HG.client_controller.CallAfterQtSafe(self._export,
                                             self._export.setFocus,
                                             QC.Qt.OtherFocusReason)

        self._paths.itemSelectionChanged.connect(self._RefreshTags)

        if do_export_and_then_quit:

            QP.CallAfter(self._DoExport, True)
    def __init__(self, parent, manager, job_key):

        PopupWindow.__init__(self, parent, manager)

        self.setSizePolicy(QW.QSizePolicy.MinimumExpanding,
                           QW.QSizePolicy.Fixed)

        self._job_key = job_key

        vbox = QP.VBoxLayout()

        self._title = ClientGUICommon.BetterStaticText(self)
        self._title.setAlignment(QC.Qt.AlignHCenter | QC.Qt.AlignVCenter)

        font = self._title.font()
        font.setBold(True)
        self._title.setFont(font)

        popup_message_character_width = HG.client_controller.new_options.GetInteger(
            'popup_message_character_width')

        popup_char_width = ClientGUIFunctions.ConvertTextToPixelWidth(
            self._title, popup_message_character_width)

        if HG.client_controller.new_options.GetBoolean(
                'popup_message_force_min_width'):

            #QP.SetMinClientSize( self, ( wrap_width, -1 ) )
            self.setFixedWidth(popup_char_width)

        else:

            self.setMaximumWidth(popup_char_width)

        self._title.setWordWrap(True)
        self._title_ev = QP.WidgetEventFilter(self._title)
        self._title_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._title.hide()

        self._text_1 = ClientGUICommon.BetterStaticText(self)
        self._text_1.setWordWrap(True)
        self._text_1_ev = QP.WidgetEventFilter(self._text_1)
        self._text_1_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._text_1.hide()

        self._gauge_1 = ClientGUICommon.Gauge(self)
        self._gauge_1_ev = QP.WidgetEventFilter(self._gauge_1)
        self._gauge_1_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._gauge_1.setMinimumWidth(int(popup_char_width * 0.9))
        self._gauge_1.hide()

        self._text_2 = ClientGUICommon.BetterStaticText(self)
        self._text_2.setWordWrap(True)
        self._text_2_ev = QP.WidgetEventFilter(self._text_2)
        self._text_2_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._text_2.hide()

        self._gauge_2 = ClientGUICommon.Gauge(self)
        self._gauge_2_ev = QP.WidgetEventFilter(self._gauge_2)
        self._gauge_2_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._gauge_2.setMinimumWidth(int(popup_char_width * 0.9))
        self._gauge_2.hide()

        self._text_yes_no = ClientGUICommon.BetterStaticText(self)
        self._text_yes_no_ev = QP.WidgetEventFilter(self._text_yes_no)
        self._text_yes_no_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._text_yes_no.hide()

        self._yes = ClientGUICommon.BetterButton(self, 'yes', self._YesButton)
        self._yes.hide()

        self._no = ClientGUICommon.BetterButton(self, 'no', self._NoButton)
        self._no.hide()

        self._network_job_ctrl = ClientGUIControls.NetworkJobControl(self)
        self._network_job_ctrl.hide()

        self._copy_to_clipboard_button = ClientGUICommon.BetterButton(
            self, 'copy to clipboard', self.CopyToClipboard)
        self._copy_to_clipboard_button_ev = QP.WidgetEventFilter(
            self._copy_to_clipboard_button)
        self._copy_to_clipboard_button_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._copy_to_clipboard_button.hide()

        self._show_files_button = ClientGUICommon.BetterButton(
            self, 'show files', self.ShowFiles)
        self._show_files_button_ev = QP.WidgetEventFilter(
            self._show_files_button)
        self._show_files_button_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._show_files_button.hide()

        self._show_tb_button = ClientGUICommon.BetterButton(
            self, 'show traceback', self.ShowTB)
        self._show_tb_button_ev = QP.WidgetEventFilter(self._show_tb_button)
        self._show_tb_button_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._show_tb_button.hide()

        self._tb_text = ClientGUICommon.BetterStaticText(self)
        self._tb_text_ev = QP.WidgetEventFilter(self._tb_text)
        self._tb_text_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._tb_text.setWordWrap(True)
        self._tb_text.hide()

        self._copy_tb_button = ClientGUICommon.BetterButton(
            self, 'copy traceback information', self.CopyTB)
        self._copy_tb_button_ev = QP.WidgetEventFilter(self._copy_tb_button)
        self._copy_tb_button_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._copy_tb_button.hide()

        self._pause_button = ClientGUICommon.BetterBitmapButton(
            self,
            CC.global_pixmaps().pause, self.PausePlay)
        self._pause_button_ev = QP.WidgetEventFilter(self._pause_button)
        self._pause_button_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._pause_button.hide()

        self._cancel_button = ClientGUICommon.BetterBitmapButton(
            self,
            CC.global_pixmaps().stop, self.Cancel)
        self._cancel_button_ev = QP.WidgetEventFilter(self._cancel_button)
        self._cancel_button_ev.EVT_RIGHT_DOWN(self.EventDismiss)
        self._cancel_button.hide()

        hbox = QP.HBoxLayout()

        QP.AddToLayout(hbox, self._pause_button, CC.FLAGS_VCENTER)
        QP.AddToLayout(hbox, self._cancel_button, CC.FLAGS_VCENTER)

        yes_no_hbox = QP.HBoxLayout()

        QP.AddToLayout(yes_no_hbox, self._yes, CC.FLAGS_VCENTER)
        QP.AddToLayout(yes_no_hbox, self._no, CC.FLAGS_VCENTER)

        QP.AddToLayout(vbox, self._title, CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._text_1, CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._gauge_1, CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._text_2, CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._gauge_2, CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, self._text_yes_no, CC.FLAGS_EXPAND_PERPENDICULAR)
        QP.AddToLayout(vbox, yes_no_hbox)
        QP.AddToLayout(vbox, self._network_job_ctrl)
        QP.AddToLayout(vbox, self._copy_to_clipboard_button)
        QP.AddToLayout(vbox, self._show_files_button)
        QP.AddToLayout(vbox, self._show_tb_button)
        QP.AddToLayout(vbox, self._tb_text)
        QP.AddToLayout(vbox, self._copy_tb_button)
        QP.AddToLayout(vbox, hbox, CC.FLAGS_BUTTON_SIZER)

        self.setLayout(vbox)
Example #20
0
 def __init__( self, parent, payload_obj, title = None, description = None, payload_description = None ):
     
     ClientGUIScrolledPanels.ReviewPanel.__init__( self, parent )
     
     self._payload_obj = payload_obj
     
     self._filepicker = QP.FilePickerCtrl( self, wildcard = 'PNG (*.png)' )
     self._filepicker.SetSaveMode( True )
     
     flp_width = ClientGUIFunctions.ConvertTextToPixelWidth( self._filepicker, 64 )
     
     self._filepicker.setMinimumWidth( flp_width )
     
     self._title = QW.QLineEdit( self )
     
     self._payload_description = QW.QLineEdit( self )
     
     self._text = QW.QLineEdit( self )
     
     self._width = QP.MakeQSpinBox( self, min=100, max=4096 )
     
     self._export = ClientGUICommon.BetterButton( self, 'export', self.Export )
     
     #
     
     if payload_description is None:
         
         ( payload_description, payload_bytes ) = ClientSerialisable.GetPayloadDescriptionAndBytes( self._payload_obj )
         
     else:
         
         payload_bytes = ClientSerialisable.GetPayloadBytes( self._payload_obj )
         
         payload_description += ' - ' + HydrusData.ToHumanBytes( len( payload_bytes ) )
         
     
     self._payload_description.setText( payload_description )
     
     self._payload_description.setEnabled( False )
     
     self._width.setValue( 512 )
     
     last_png_export_dir = HG.client_controller.new_options.GetNoneableString( 'last_png_export_dir' )
     
     if title is not None:
         
         name = title
         
     elif isinstance( self._payload_obj, HydrusSerialisable.SerialisableBaseNamed ):
         
         name = self._payload_obj.GetName()
         
     else:
         
         name = payload_description
         
     
     self._title.setText( name )
     
     if description is not None:
         
         self._text.setText( description )
         
     
     if last_png_export_dir is not None:
         
         filename = name + '.png'
         
         filename = HydrusPaths.SanitizeFilename( filename )
         
         path = os.path.join( last_png_export_dir, filename )
         
         self._filepicker.SetPath( path )
         
     
     self._Update()
     
     #
     
     rows = []
     
     rows.append( ( 'export path: ', self._filepicker ) )
     rows.append( ( 'title: ', self._title ) )
     rows.append( ( 'payload description: ', self._payload_description ) )
     rows.append( ( 'your description (optional): ', self._text ) )
     rows.append( ( 'png width: ', self._width ) )
     rows.append( ( '', self._export ) )
     
     gridbox = ClientGUICommon.WrapInGrid( self, rows )
     
     self.widget().setLayout( gridbox )
     
     self._filepicker.filePickerChanged.connect( self._Update )
     self._title.textChanged.connect( self._Update )
    def __init__(self, parent, all_shortcuts):

        ClientGUIScrolledPanels.EditPanel.__init__(self, parent)

        help_button = ClientGUICommon.BetterBitmapButton(
            self,
            CC.global_pixmaps().help, self._ShowHelp)
        help_button.setToolTip('Show help regarding editing shortcuts.')

        reserved_panel = ClientGUICommon.StaticBox(
            self, 'built-in hydrus shortcut sets')

        self._reserved_shortcuts = ClientGUIListCtrl.BetterListCtrl(
            reserved_panel,
            CGLC.COLUMN_LIST_SHORTCUT_SETS.ID,
            6,
            data_to_tuples_func=self._GetTuples,
            activation_callback=self._EditReserved)

        self._reserved_shortcuts.setMinimumSize(QC.QSize(320, 200))

        self._edit_reserved_button = ClientGUICommon.BetterButton(
            reserved_panel, 'edit', self._EditReserved)
        self._restore_defaults_button = ClientGUICommon.BetterButton(
            reserved_panel, 'restore defaults', self._RestoreDefaults)

        #

        custom_panel = ClientGUICommon.StaticBox(self, 'custom user sets')

        self._custom_shortcuts = ClientGUIListCtrl.BetterListCtrl(
            custom_panel,
            CGLC.COLUMN_LIST_SHORTCUT_SETS.ID,
            6,
            data_to_tuples_func=self._GetTuples,
            delete_key_callback=self._Delete,
            activation_callback=self._EditCustom)

        self._add_button = ClientGUICommon.BetterButton(
            custom_panel, 'add', self._Add)
        self._edit_custom_button = ClientGUICommon.BetterButton(
            custom_panel, 'edit', self._EditCustom)
        self._delete_button = ClientGUICommon.BetterButton(
            custom_panel, 'delete', self._Delete)

        if not HG.client_controller.new_options.GetBoolean('advanced_mode'):

            custom_panel.hide()

        #

        reserved_shortcuts = [
            shortcuts for shortcuts in all_shortcuts if shortcuts.GetName() in
            ClientGUIShortcuts.SHORTCUTS_RESERVED_NAMES
        ]
        custom_shortcuts = [
            shortcuts for shortcuts in all_shortcuts if shortcuts.GetName()
            not in ClientGUIShortcuts.SHORTCUTS_RESERVED_NAMES
        ]

        self._reserved_shortcuts.AddDatas(reserved_shortcuts)

        self._reserved_shortcuts.Sort()

        self._original_custom_names = set()

        for shortcuts in custom_shortcuts:

            self._custom_shortcuts.AddDatas((shortcuts, ))

            self._original_custom_names.add(shortcuts.GetName())

        self._custom_shortcuts.Sort()

        #

        button_hbox = QP.HBoxLayout()

        QP.AddToLayout(button_hbox, self._edit_reserved_button,
                       CC.FLAGS_CENTER_PERPENDICULAR)
        QP.AddToLayout(button_hbox, self._restore_defaults_button,
                       CC.FLAGS_CENTER_PERPENDICULAR)

        reserved_panel.Add(self._reserved_shortcuts,
                           CC.FLAGS_EXPAND_SIZER_BOTH_WAYS)
        reserved_panel.Add(button_hbox, CC.FLAGS_ON_RIGHT)

        #

        button_hbox = QP.HBoxLayout()

        QP.AddToLayout(button_hbox, self._add_button,
                       CC.FLAGS_CENTER_PERPENDICULAR)
        QP.AddToLayout(button_hbox, self._edit_custom_button,
                       CC.FLAGS_CENTER_PERPENDICULAR)
        QP.AddToLayout(button_hbox, self._delete_button,
                       CC.FLAGS_CENTER_PERPENDICULAR)

        custom_panel_message = 'Custom shortcuts are advanced. They apply to the media viewer and must be turned on to take effect.'

        st = ClientGUICommon.BetterStaticText(custom_panel,
                                              custom_panel_message)
        st.setWordWrap(True)

        custom_panel.Add(st, CC.FLAGS_EXPAND_PERPENDICULAR)
        custom_panel.Add(self._custom_shortcuts,
                         CC.FLAGS_EXPAND_SIZER_BOTH_WAYS)
        custom_panel.Add(button_hbox, CC.FLAGS_ON_RIGHT)

        #

        vbox = QP.VBoxLayout()

        QP.AddToLayout(vbox, help_button, CC.FLAGS_ON_RIGHT)
        QP.AddToLayout(vbox, reserved_panel, CC.FLAGS_EXPAND_BOTH_WAYS)
        QP.AddToLayout(vbox, custom_panel, CC.FLAGS_EXPAND_BOTH_WAYS)

        self.widget().setLayout(vbox)