def boot(): args = sys.argv[1:] if len(args) > 0: only_run = args[0] else: only_run = None try: threading.Thread(target=reactor.run, kwargs={ 'installSignalHandlers': 0 }).start() QP.MonkeyPatchMissingMethods() app = QW.QApplication(sys.argv) app.call_after_catcher = QP.CallAfterEventCatcher(app) try: # we run the tests on the Qt thread atm # keep a window alive the whole time so the app doesn't finish its mainloop win = QW.QWidget(None) win.setWindowTitle('Running tests...') controller = TestController.Controller(win, only_run) def do_it(): controller.Run(win) QP.CallAfter(do_it) app.exec_() except: HydrusData.DebugPrint(traceback.format_exc()) finally: HG.view_shutdown = True controller.pubimmediate('wake_daemons') HG.model_shutdown = True controller.pubimmediate('wake_daemons') controller.TidyUp() except: HydrusData.DebugPrint(traceback.format_exc()) finally: reactor.callFromThread(reactor.stop) print('This was version ' + str(HC.SOFTWARE_VERSION)) input()
def __init__(self, parent, media): self._hashes = set() for m in media: self._hashes.update(m.GetHashes()) ClientGUIDialogs.Dialog.__init__( self, parent, 'manage ratings for ' + HydrusData.ToHumanInt(len(self._hashes)) + ' files', position='topleft') # like_services = HG.client_controller.services_manager.GetServices( (HC.LOCAL_RATING_LIKE, )) numerical_services = HG.client_controller.services_manager.GetServices( (HC.LOCAL_RATING_NUMERICAL, )) self._panels = [] if len(like_services) > 0: self._panels.append(self._LikePanel(self, like_services, media)) if len(numerical_services) > 0: self._panels.append( self._NumericalPanel(self, numerical_services, media)) self._apply = QW.QPushButton('apply', self) self._apply.clicked.connect(self.EventOK) self._apply.setObjectName('HydrusAccept') self._cancel = QW.QPushButton('cancel', self) self._cancel.clicked.connect(self.reject) self._cancel.setObjectName('HydrusCancel') # buttonbox = QP.HBoxLayout() QP.AddToLayout(buttonbox, self._apply, CC.FLAGS_CENTER_PERPENDICULAR) QP.AddToLayout(buttonbox, self._cancel, CC.FLAGS_CENTER_PERPENDICULAR) vbox = QP.VBoxLayout() for panel in self._panels: QP.AddToLayout(vbox, panel, CC.FLAGS_EXPAND_PERPENDICULAR) QP.AddToLayout(vbox, buttonbox, CC.FLAGS_ON_RIGHT) self.setLayout(vbox) size_hint = self.sizeHint() QP.SetInitialSize(self, size_hint) # self._my_shortcut_handler = ClientGUIShortcuts.ShortcutsHandler( self, ['global', 'media'])
def __init__(self, parent, service_key): Dialog.__init__(self, parent, 'configure new accounts') self._service_key = service_key self._num = QP.MakeQSpinBox(self, min=1, max=10000, width=80) self._account_types = ClientGUICommon.BetterChoice(self) self._lifetime = ClientGUICommon.BetterChoice(self) self._ok = QW.QPushButton('OK', self) self._ok.clicked.connect(self.EventOK) self._ok.setObjectName('HydrusAccept') self._cancel = QW.QPushButton('Cancel', self) self._cancel.clicked.connect(self.reject) self._cancel.setObjectName('HydrusCancel') # self._num.setValue(1) service = HG.client_controller.services_manager.GetService(service_key) response = service.Request(HC.GET, 'account_types') account_types = response['account_types'] for account_type in account_types: self._account_types.addItem(account_type.GetTitle(), account_type) self._account_types.setCurrentIndex(0) for (s, value) in HC.lifetimes: self._lifetime.addItem(s, value) self._lifetime.setCurrentIndex(3) # one year # ctrl_box = QP.HBoxLayout() QP.AddToLayout(ctrl_box, ClientGUICommon.BetterStaticText(self, 'generate'), CC.FLAGS_CENTER_PERPENDICULAR) QP.AddToLayout(ctrl_box, self._num, CC.FLAGS_CENTER_PERPENDICULAR) QP.AddToLayout(ctrl_box, self._account_types, CC.FLAGS_CENTER_PERPENDICULAR) QP.AddToLayout( ctrl_box, ClientGUICommon.BetterStaticText(self, 'accounts, to expire in'), CC.FLAGS_CENTER_PERPENDICULAR) QP.AddToLayout(ctrl_box, self._lifetime, CC.FLAGS_CENTER_PERPENDICULAR) 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, ctrl_box, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR) QP.AddToLayout(vbox, b_box, CC.FLAGS_ON_RIGHT) self.setLayout(vbox) size_hint = self.sizeHint() QP.SetInitialSize(self, size_hint) ClientGUIFunctions.SetFocusLater(self._ok)
def __init__(self, parent, namespace='', regex=''): Dialog.__init__(self, parent, 'configure quick namespace') self._namespace = QW.QLineEdit(self) self._regex = QW.QLineEdit(self) self._shortcuts = ClientGUICommon.RegexButton(self) self._regex_intro_link = ClientGUICommon.BetterHyperLink( self, 'a good regex introduction', 'https://www.aivosto.com/vbtips/regex.html') self._regex_practise_link = ClientGUICommon.BetterHyperLink( self, 'regex practice', 'https://regexr.com/3cvmf') self._ok = QW.QPushButton('OK', self) self._ok.clicked.connect(self.EventOK) self._ok.setObjectName('HydrusAccept') self._cancel = QW.QPushButton('Cancel', self) self._cancel.clicked.connect(self.reject) self._cancel.setObjectName('HydrusCancel') # self._namespace.setText(namespace) self._regex.setText(regex) # control_box = QP.HBoxLayout() QP.AddToLayout(control_box, self._namespace, CC.FLAGS_EXPAND_BOTH_WAYS) QP.AddToLayout(control_box, ClientGUICommon.BetterStaticText(self, ':'), CC.FLAGS_CENTER_PERPENDICULAR) QP.AddToLayout(control_box, self._regex, CC.FLAGS_EXPAND_BOTH_WAYS) 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() intro = r'Put the namespace (e.g. page) on the left.' + os.linesep + r'Put the regex (e.g. [1-9]+\d*(?=.{4}$)) on the right.' + os.linesep + r'All files will be tagged with "namespace:regex".' QP.AddToLayout(vbox, ClientGUICommon.BetterStaticText(self, intro), CC.FLAGS_EXPAND_PERPENDICULAR) QP.AddToLayout(vbox, control_box, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR) QP.AddToLayout(vbox, self._shortcuts, CC.FLAGS_ON_RIGHT) QP.AddToLayout(vbox, self._regex_intro_link, CC.FLAGS_ON_RIGHT) QP.AddToLayout(vbox, self._regex_practise_link, CC.FLAGS_ON_RIGHT) 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)
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)
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() if export_path is not None: 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, 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)
def CallBlockingToQt(self, win, func, *args, **kwargs): def qt_code(win: QW.QWidget, job_key: ClientThreading.JobKey): try: if win is not None and not QP.isValid(win): raise HydrusExceptions.QtDeadWindowException( 'Parent Window was destroyed before Qt command was called!' ) result = func(*args, **kwargs) job_key.SetVariable('result', result) except (HydrusExceptions.QtDeadWindowException, HydrusExceptions.DBCredentialsException, HydrusExceptions.ShutdownException) as e: job_key.SetErrorException(e) except Exception as e: job_key.SetErrorException(e) HydrusData.Print('CallBlockingToQt just caught this error:') HydrusData.DebugPrint(traceback.format_exc()) finally: job_key.Finish() job_key = ClientThreading.JobKey() job_key.Begin() QP.CallAfter(qt_code, win, job_key) while not job_key.IsDone(): if HG.model_shutdown: raise HydrusExceptions.ShutdownException( 'Application is shutting down!') time.sleep(0.05) if job_key.HasVariable('result'): # result can be None, for qt_code that has no return variable result = job_key.GetIfHasVariable('result') return result if job_key.HadError(): e = job_key.GetErrorException() raise e raise HydrusExceptions.ShutdownException()
def SetControl(self, control): self._control = control QP.AddToLayout(self._vbox, control, CC.FLAGS_EXPAND_BOTH_WAYS)
def __init__(self, parent, predicates: typing.Collection[ClientSearch.Predicate]): ClientGUIScrolledPanels.EditPanel.__init__(self, parent) predicates = list(predicates) predicates.sort(key=lambda p: p.ToString(with_count=False)) self._uneditable_predicates = [] self._invertible_pred_buttons = [] self._editable_pred_panels = [] rating_preds = [] # I hate this pred comparison stuff, but let's hang in there until we split this stuff up by type mate # then we can just have a dict type->panel_class lookup or whatever # also it would be nice to have proper rating editing here, think about it AGE_DELTA_PRED = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_AGE, ('>', 'delta', (2000, 1, 1, 1))) MODIFIED_DELTA_PRED = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_MODIFIED_TIME, ('>', 'delta', (2000, 1, 1, 1))) KNOWN_URL_EXACT = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_KNOWN_URLS, (True, 'exact_match', '', '')) KNOWN_URL_DOMAIN = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_KNOWN_URLS, (True, 'domain', '', '')) KNOWN_URL_REGEX = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_KNOWN_URLS, (True, 'regex', '', '')) FILE_VIEWS_PRED = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_VIEWING_STATS, ('views', ('media', ), '>', 0)) for predicate in predicates: predicate_type = predicate.GetType() if predicate_type == ClientSearch.PREDICATE_TYPE_OR_CONTAINER: self._editable_pred_panels.append( ClientGUIPredicatesOR.ORPredicateControl(self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_AGE: if predicate.IsUIEditable(AGE_DELTA_PRED): self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemAgeDelta( self, predicate)) else: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemAgeDate( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_MODIFIED_TIME: if predicate.IsUIEditable(MODIFIED_DELTA_PRED): self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemModifiedDelta(self, predicate)) else: self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemModifiedDate(self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_HEIGHT: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemHeight( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_WIDTH: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemWidth( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemRatio( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_PIXELS: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemNumPixels( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_DURATION: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemDuration( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FRAMERATE: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemFramerate( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_FRAMES: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemNumFrames( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_SERVICE: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemFileService( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_KNOWN_URLS: if predicate.IsUIEditable(KNOWN_URL_EXACT): self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsExactURL(self, predicate)) elif predicate.IsUIEditable(KNOWN_URL_DOMAIN): self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsDomain(self, predicate)) elif predicate.IsUIEditable(KNOWN_URL_REGEX): self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsRegex(self, predicate)) else: self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsURLClass(self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_HASH: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemHash( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_LIMIT: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemLimit( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_MIME: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemMime( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_TAGS: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemNumTags( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_NOTES: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemNumNotes( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_HAS_NOTE_NAME: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemHasNoteName( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_WORDS: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemNumWords( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_SIMILAR_TO: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemSimilarTo( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_SIZE: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemSize( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_TAG_AS_NUMBER: self._editable_pred_panels.append( ClientGUIPredicatesSingle.PanelPredicateSystemTagAsNumber( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS_COUNT: self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemDuplicateRelationships( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_VIEWING_STATS: if predicate.IsUIEditable(FILE_VIEWS_PRED): self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemFileViewingStatsViews( self, predicate)) else: self._editable_pred_panels.append( ClientGUIPredicatesSingle. PanelPredicateSystemFileViewingStatsViewtime( self, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_RATING: rating_preds.append(predicate) elif predicate.IsInvertible(): self._invertible_pred_buttons.append( ClientGUIPredicatesSingle.InvertiblePredicateButton( self, predicate)) else: self._uneditable_predicates.append(predicate) if len(rating_preds) > 0: self._editable_pred_panels.append( ClientGUIPredicatesMultiple.PanelPredicateSystemRating( self, rating_preds)) vbox = QP.VBoxLayout() for button in self._invertible_pred_buttons: QP.AddToLayout(vbox, button, CC.FLAGS_EXPAND_PERPENDICULAR) for panel in self._editable_pred_panels: QP.AddToLayout(vbox, panel, CC.FLAGS_EXPAND_PERPENDICULAR) self.widget().setLayout(vbox)
def __init__(self, parent, predicate: ClientSearch.Predicate): ClientGUIScrolledPanels.EditPanel.__init__(self, parent) predicate_type = predicate.GetType() self._predicates = [] label = None editable_pred_panels = [] static_pred_buttons = [] recent_predicate_types = [predicate_type] if predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_AGE: static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_AGE, ('<', 'delta', (0, 0, 1, 0))), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_AGE, ('<', 'delta', (0, 0, 7, 0))), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_AGE, ('<', 'delta', (0, 1, 0, 0))), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemAgeDelta, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemAgeDate, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_MODIFIED_TIME: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemModifiedDelta, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemModifiedDate, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_DIMENSIONS: recent_predicate_types = [ ClientSearch.PREDICATE_TYPE_SYSTEM_HEIGHT, ClientSearch.PREDICATE_TYPE_SYSTEM_WIDTH, ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO, ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_PIXELS ] static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO, ('=', 16, 9)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO, ('=', 9, 16)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO, ('=', 4, 3)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_RATIO, ('=', 1, 1)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_WIDTH, ('=', 1920)), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_HEIGHT, ('=', 1080))), forced_label='1080p')) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_WIDTH, ('=', 1280)), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_HEIGHT, ('=', 720))), forced_label='720p')) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_WIDTH, ('=', 3840)), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_HEIGHT, ('=', 2160))), forced_label='4k')) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemHeight, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemWidth, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemRatio, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemNumPixels, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_DURATION: recent_predicate_types = [ ClientSearch.PREDICATE_TYPE_SYSTEM_DURATION, ClientSearch.PREDICATE_TYPE_SYSTEM_FRAMERATE, ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_FRAMES ] static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_DURATION, ('>', 0)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_DURATION, ('=', 0)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_FRAMERATE, ('=', 30)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_FRAMERATE, ('=', 60)), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemDuration, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemFramerate, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemNumFrames, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_SERVICE: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemFileService, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_KNOWN_URLS: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsExactURL, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsDomain, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsRegex, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemKnownURLsURLClass, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_HAS_AUDIO: recent_predicate_types = [] static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_HAS_AUDIO, True), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_HAS_AUDIO, False), ))) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_HASH: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemHash, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_LIMIT: label = 'system:limit clips a large search result down to the given number of files. It is very useful for processing in smaller batches.' label += os.linesep * 2 label += 'For all the simpler sorts (filesize, duration, etc...), it will select the n largest/smallest in the result set appropriate for that sort. For complicated sorts like tags, it will sample randomly.' static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_LIMIT, 64), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_LIMIT, 256), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_LIMIT, 1024), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemLimit, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_MIME: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemMime, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_TAGS: static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_TAGS, (None, '>', 0)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_TAGS, (None, '=', 0)), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemNumTags, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NOTES: recent_predicate_types = [ ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_NOTES, ClientSearch.PREDICATE_TYPE_SYSTEM_HAS_NOTE_NAME ] static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_NOTES, ('>', 0)), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_NOTES, ('=', 0)), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemNumNotes, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemHasNoteName, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_NUM_WORDS: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemNumWords, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_RATING: services_manager = HG.client_controller.services_manager ratings_services = services_manager.GetServices( (HC.LOCAL_RATING_LIKE, HC.LOCAL_RATING_NUMERICAL)) if len(ratings_services) > 0: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesMultiple.PanelPredicateSystemRating, (predicate, ))) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_SIMILAR_TO: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemSimilarTo, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_SIZE: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemSize, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_TAG_AS_NUMBER: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle.PanelPredicateSystemTagAsNumber, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS: static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch. PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS_KING, False), ))) static_pred_buttons.append( ClientGUIPredicatesSingle.StaticSystemPredicateButton( self, self, (ClientSearch.Predicate( ClientSearch. PREDICATE_TYPE_SYSTEM_FILE_RELATIONSHIPS_KING, True), ))) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemDuplicateRelationships, predicate)) elif predicate_type == ClientSearch.PREDICATE_TYPE_SYSTEM_FILE_VIEWING_STATS: editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemFileViewingStatsViews, predicate)) editable_pred_panels.append( self._PredOKPanel( self, ClientGUIPredicatesSingle. PanelPredicateSystemFileViewingStatsViewtime, predicate)) vbox = QP.VBoxLayout() if label is not None: st = ClientGUICommon.BetterStaticText(self, label=label) st.setWordWrap(True) QP.AddToLayout(vbox, st, CC.FLAGS_EXPAND_PERPENDICULAR) recent_predicates = [] if len(recent_predicate_types) > 0: recent_predicates = HG.client_controller.new_options.GetRecentPredicates( recent_predicate_types) if len(recent_predicates) > 0: recent_predicates_box = ClientGUICommon.StaticBox( self, 'recent') for recent_predicate in recent_predicates: button = ClientGUIPredicatesSingle.StaticSystemPredicateButton( recent_predicates_box, self, (recent_predicate, )) recent_predicates_box.Add(button, CC.FLAGS_EXPAND_PERPENDICULAR) QP.AddToLayout(vbox, recent_predicates_box, CC.FLAGS_EXPAND_PERPENDICULAR) for button in static_pred_buttons: QP.AddToLayout(vbox, button, CC.FLAGS_EXPAND_PERPENDICULAR) for panel in editable_pred_panels: QP.AddToLayout(vbox, panel, CC.FLAGS_EXPAND_PERPENDICULAR) if len(static_pred_buttons) > 0 and len(editable_pred_panels) == 0: HG.client_controller.CallAfterQtSafe( static_pred_buttons[0], static_pred_buttons[0].setFocus, QC.Qt.OtherFocusReason) self.widget().setLayout(vbox)
def __init__( self, parent ): QW.QWidget.__init__( self, parent ) self.setWindowFlags( QC.Qt.Tool | QC.Qt.FramelessWindowHint ) self.setAttribute( QC.Qt.WA_ShowWithoutActivating ) self.setSizePolicy( QW.QSizePolicy.MinimumExpanding, QW.QSizePolicy.Preferred ) self._last_best_size_i_fit_on = ( 0, 0 ) self._max_messages_to_display = 10 vbox = QP.VBoxLayout() self._message_panel = QW.QWidget( self ) self._message_vbox = QP.VBoxLayout( margin = 0 ) vbox.setSizeConstraint( QW.QLayout.SetFixedSize ) self._message_panel.setLayout( self._message_vbox ) self._message_panel.setSizePolicy( QW.QSizePolicy.MinimumExpanding, QW.QSizePolicy.Preferred ) self._summary_bar = PopupMessageSummaryBar( self, self ) self._summary_bar.setSizePolicy( QW.QSizePolicy.MinimumExpanding, QW.QSizePolicy.Preferred ) QP.AddToLayout( vbox, self._message_panel ) QP.AddToLayout( vbox, self._summary_bar ) self.setLayout( vbox ) self._pending_job_keys = [] self._gui_event_filter = QP.WidgetEventFilter( parent ) self._gui_event_filter.EVT_SIZE( self.EventParentMovedOrResized ) self._gui_event_filter.EVT_MOVE( self.EventParentMovedOrResized ) HG.client_controller.sub( self, 'AddMessage', 'message' ) self._old_excepthook = sys.excepthook self._old_show_exception = HydrusData.ShowException self._old_show_exception_tuple = HydrusData.ShowExceptionTuple self._old_show_text = HydrusData.ShowText sys.excepthook = ClientData.CatchExceptionClient HydrusData.ShowException = ClientData.ShowExceptionClient HydrusData.ShowExceptionTuple = ClientData.ShowExceptionTupleClient HydrusData.ShowText = ClientData.ShowTextClient job_key = ClientThreading.JobKey() job_key.SetVariable( 'popup_text_1', 'initialising popup message manager\u2026' ) self._update_job = HG.client_controller.CallRepeatingQtSafe( self, 0.25, 0.5, 'repeating popup message update', self.REPEATINGUpdate ) self._summary_bar.expandCollapse.connect( self.ExpandCollapse ) HG.client_controller.CallLaterQtSafe( self, 0.5, 'initialise message', self.AddMessage, job_key ) HG.client_controller.CallLaterQtSafe( self, 1.0, 'delete initial message', job_key.Delete )
def __init__( self, parent, manager, job_key: ClientThreading.JobKey ): 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 = ClientGUINetworkJobControl.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._user_callable_button = ClientGUICommon.BetterButton( self, 'run command', self.CallUserCallable ) self._user_callable_button_ev = QP.WidgetEventFilter( self._user_callable_button ) self._user_callable_button_ev.EVT_RIGHT_DOWN( self.EventDismiss ) self._user_callable_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_CENTER_PERPENDICULAR ) QP.AddToLayout( hbox, self._cancel_button, CC.FLAGS_CENTER_PERPENDICULAR ) yes_no_hbox = QP.HBoxLayout() QP.AddToLayout( yes_no_hbox, self._yes, CC.FLAGS_CENTER_PERPENDICULAR ) QP.AddToLayout( yes_no_hbox, self._no, CC.FLAGS_CENTER_PERPENDICULAR ) 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._user_callable_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_ON_RIGHT ) self.setLayout( vbox )
def CreateTopImage(width, title, payload_description, text): text_extent_qt_image = HG.client_controller.bitmap_manager.GetQtImage( 20, 20, 24) painter = QG.QPainter(text_extent_qt_image) text_font = QW.QApplication.font() basic_font_size = text_font.pointSize() payload_description_font = QW.QApplication.font() payload_description_font.setPointSize(int(basic_font_size * 1.4)) title_font = QW.QApplication.font() title_font.setPointSize(int(basic_font_size * 2.0)) texts_to_draw = [] current_y = 6 for (t, f) in ((title, title_font), (payload_description, payload_description_font), (text, text_font)): painter.setFont(f) wrapped_texts = WrapText(painter, t, width - 20) line_height = painter.fontMetrics().height() wrapped_texts_with_ys = [] if len(wrapped_texts) > 0: current_y += 10 for wrapped_text in wrapped_texts: wrapped_texts_with_ys.append((wrapped_text, current_y)) current_y += line_height + 4 texts_to_draw.append((wrapped_texts_with_ys, f)) current_y += 6 top_height = current_y del painter del text_extent_qt_image # top_qt_image = HG.client_controller.bitmap_manager.GetQtImage( width, top_height, 24) painter = QG.QPainter(top_qt_image) painter.setBackground(QG.QBrush(QC.Qt.white)) painter.eraseRect(painter.viewport()) # painter.drawPixmap(width - 16 - 5, 5, CC.global_pixmaps().file_repository) # for (wrapped_texts_with_ys, f) in texts_to_draw: painter.setFont(f) for (wrapped_text, y) in wrapped_texts_with_ys: text_size = painter.fontMetrics().size(QC.Qt.TextSingleLine, wrapped_text) QP.DrawText(painter, (width - text_size.width()) // 2, y, wrapped_text) del painter data_bytearray = top_qt_image.bits() if QP.qtpy.PYSIDE2: data_bytes = bytes(data_bytearray) elif QP.qtpy.PYQT5: data_bytes = data_bytearray.asstring(top_height * width * 3) top_image_rgb = numpy.fromstring(data_bytes, dtype='uint8').reshape( (top_height, width, 3)) top_image = cv2.cvtColor(top_image_rgb, cv2.COLOR_RGB2GRAY) top_height_header = struct.pack('!H', top_height) byte0 = top_height_header[0:1] byte1 = top_height_header[1:2] top_image[0][0] = ord(byte0) top_image[0][1] = ord(byte1) return top_image
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 = ClientGUICommon.BetterSpinBox(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, payload_length) = ClientSerialisable.GetPayloadBytesAndLength( self._payload_obj) payload_description += ' - {}'.format( HydrusData.ToHumanBytes(payload_length)) 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, 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 -->', object_name='HydrusIndeterminate') 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._intended_files_per_check.setToolTip( 'How many new files you want the checker to find on each check. If a source is producing about 2 files a day, and this is set to 6, you will probably get a check every three days. You probably want this to be a low number, like 1-4.' ) self._never_faster_than = TimeDeltaCtrl(self._reactive_check_panel, min=never_faster_than_min, days=True, hours=True, minutes=True, seconds=True) self._never_faster_than.setToolTip( 'Even if the download source produces many new files, the checker will never ask for a check more often than this. This is a safety measure.' ) self._never_slower_than = TimeDeltaCtrl(self._reactive_check_panel, min=never_slower_than_min, days=True, hours=True, minutes=True, seconds=True) self._never_slower_than.setToolTip( 'Even if the download source slows down significantly, the checker will make sure it checks at least this often anyway, just to catch a future wave in time.' ) # 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._flat_check_period.setToolTip( 'Always use the same check delay. It is based on the time the last check completed, not the time the last check was due. If you want once a day with no skips, try setting this to 23 hours.' ) # 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) # # label = 'This checks more or less frequently based on how fast the download source is producing new files.' st = ClientGUICommon.BetterStaticText(self._reactive_check_panel, label=label) st.setWordWrap(True) 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(st, CC.FLAGS_EXPAND_PERPENDICULAR) 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_EXPAND_PERPENDICULAR) label = 'If you do not understand this panel, use the buttons! The defaults are fine for most purposes!' st = ClientGUICommon.BetterStaticText(self._reactive_check_panel, label=label) st.setWordWrap(True) st.setObjectName('HydrusWarning') QP.AddToLayout(vbox, st, CC.FLAGS_EXPAND_PERPENDICULAR) 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) vbox.addStretch(1) self.widget().setLayout(vbox) # self._flat_check_period_checkbox.clicked.connect( self.EventFlatPeriodCheck)
def __init__( self, parent, export_folder: ClientExporting.ExportFolder ): ClientGUIScrolledPanels.EditPanel.__init__( self, parent ) self._export_folder = export_folder ( name, path, export_type, delete_from_client_after_export, file_search_context, run_regularly, period, phrase, self._last_checked, paused, run_now ) = self._export_folder.ToTuple() self._path_box = ClientGUICommon.StaticBox( self, 'name and location' ) self._name = QW.QLineEdit( self._path_box ) self._path = QP.DirPickerCtrl( self._path_box ) # self._type_box = ClientGUICommon.StaticBox( self, 'type of export' ) self._type = ClientGUICommon.BetterChoice( self._type_box ) self._type.addItem( 'regular', HC.EXPORT_FOLDER_TYPE_REGULAR ) self._type.addItem( 'synchronise', HC.EXPORT_FOLDER_TYPE_SYNCHRONISE ) self._delete_from_client_after_export = QW.QCheckBox( self._type_box ) # self._query_box = ClientGUICommon.StaticBox( self, 'query to export' ) self._page_key = 'export folders placeholder' self._tag_autocomplete = ClientGUIACDropdown.AutoCompleteDropdownTagsRead( self._query_box, self._page_key, file_search_context, allow_all_known_files = False, force_system_everything = True ) # self._period_box = ClientGUICommon.StaticBox( self, 'export period' ) self._period = ClientGUITime.TimeDeltaButton( self._period_box, min = 3 * 60, days = True, hours = True, minutes = True ) self._run_regularly = QW.QCheckBox( self._period_box ) self._paused = QW.QCheckBox( self._period_box ) self._run_now = QW.QCheckBox( self._period_box ) # self._phrase_box = ClientGUICommon.StaticBox( self, 'filenames' ) self._pattern = QW.QLineEdit( self._phrase_box ) self._examples = ClientGUICommon.ExportPatternButton( self._phrase_box ) # self._name.setText( name ) self._path.SetPath( path ) self._type.SetValue( export_type ) self._delete_from_client_after_export.setChecked( delete_from_client_after_export ) self._period.SetValue( period ) self._run_regularly.setChecked( run_regularly ) self._paused.setChecked( paused ) self._run_now.setChecked( run_now ) self._pattern.setText( phrase ) # rows = [] rows.append( ( 'name: ', self._name ) ) rows.append( ( 'folder path: ', self._path ) ) gridbox = ClientGUICommon.WrapInGrid( self._path_box, rows ) self._path_box.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR ) # text = '''regular - try to export the files to the directory, overwriting if the filesize if different synchronise - try to export the files to the directory, overwriting if the filesize if different, and delete anything else in the directory If you select synchronise, be careful!''' st = ClientGUICommon.BetterStaticText( self._type_box, label = text ) st.setWordWrap( True ) self._type_box.Add( st, CC.FLAGS_EXPAND_PERPENDICULAR ) self._type_box.Add( self._type, CC.FLAGS_EXPAND_PERPENDICULAR ) rows = [] rows.append( ( 'delete files from client after export: ', self._delete_from_client_after_export ) ) gridbox = ClientGUICommon.WrapInGrid( self._type_box, rows ) self._type_box.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR ) self._query_box.Add( self._tag_autocomplete ) self._period_box.Add( self._period, CC.FLAGS_EXPAND_PERPENDICULAR ) rows = [] rows.append( ( 'run regularly?: ', self._run_regularly ) ) rows.append( ( 'paused: ', self._paused ) ) rows.append( ( 'run on dialog ok: ', self._run_now ) ) gridbox = ClientGUICommon.WrapInGrid( self._period_box, rows ) self._period_box.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR ) phrase_hbox = QP.HBoxLayout() QP.AddToLayout( phrase_hbox, self._pattern, CC.FLAGS_EXPAND_BOTH_WAYS ) QP.AddToLayout( phrase_hbox, self._examples, CC.FLAGS_CENTER_PERPENDICULAR ) self._phrase_box.Add( phrase_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR ) vbox = QP.VBoxLayout() QP.AddToLayout( vbox, self._path_box, CC.FLAGS_EXPAND_PERPENDICULAR ) QP.AddToLayout( vbox, self._type_box, CC.FLAGS_EXPAND_PERPENDICULAR ) QP.AddToLayout( vbox, self._query_box, CC.FLAGS_EXPAND_BOTH_WAYS ) QP.AddToLayout( vbox, self._period_box, CC.FLAGS_EXPAND_PERPENDICULAR ) QP.AddToLayout( vbox, self._phrase_box, CC.FLAGS_EXPAND_PERPENDICULAR ) self.widget().setLayout( vbox ) self._UpdateTypeDeleteUI() self._type.currentIndexChanged.connect( self._UpdateTypeDeleteUI ) self._delete_from_client_after_export.clicked.connect( self.EventDeleteFilesAfterExport )
def __init__(self, parent, api_permissions): ClientGUIScrolledPanels.EditPanel.__init__(self, parent) self._original_api_permissions = api_permissions self._access_key = QW.QLineEdit() self._access_key.setReadOnly(True) width = ClientGUIFunctions.ConvertTextToPixelWidth( self._access_key, 66) self.setMinimumWidth(width) self._name = QW.QLineEdit(self) self._basic_permissions = QP.CheckListBox(self) for permission in ClientAPI.ALLOWED_PERMISSIONS: self._basic_permissions.Append( ClientAPI.basic_permission_to_str_lookup[permission], permission) search_tag_filter = api_permissions.GetSearchTagFilter() message = 'The API will only permit searching for tags that pass through this filter.' message += os.linesep * 2 message += 'If you want to allow all tags, just leave it as is, permitting everything. If you want to limit it to just one tag, such as "do waifu2x on this", set up a whitelist with only that tag allowed.' self._search_tag_filter = ClientGUITags.TagFilterButton( self, message, search_tag_filter, label_prefix='permitted tags: ') # access_key = api_permissions.GetAccessKey() self._access_key.setText(access_key.hex()) name = api_permissions.GetName() self._name.setText(name) basic_permissions = api_permissions.GetBasicPermissions() self._basic_permissions.SetCheckedData(basic_permissions) # rows = [] rows.append(('access key: ', self._access_key)) rows.append(('name: ', self._name)) rows.append(('permissions: ', self._basic_permissions)) rows.append(('tag search permissions: ', self._search_tag_filter)) gridbox = ClientGUICommon.WrapInGrid(self, rows) vbox = QP.VBoxLayout() QP.AddToLayout(vbox, gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR) self.widget().setLayout(vbox) # self._UpdateEnabled() self._basic_permissions.checkListBoxChanged.connect( self._UpdateEnabled)
def do_it( directory, neighbouring_txt_tag_service_keys, delete_afterwards, export_symlinks, quit_afterwards ): pauser = HydrusData.BigJobPauser() for ( index, ( ordering_index, media ) ) in enumerate( to_do ): try: QP.CallAfter( qt_update_label, HydrusData.ConvertValueRangeToPrettyString(index+1,num_to_do) ) hash = media.GetHash() mime = media.GetMime() path = self._GetPath( media ) path = os.path.normpath( path ) if not path.startswith( directory ): raise Exception( 'It seems a destination path was above the main export directory! The file was "{}" and its destination path was "{}".'.format( hash.hex(), path ) ) path_dir = os.path.dirname( path ) HydrusPaths.MakeSureDirectoryExists( path_dir ) if export_tag_txts: tags_manager = media.GetTagsManager() tags = set() for service_key in neighbouring_txt_tag_service_keys: current_tags = tags_manager.GetCurrent( service_key, ClientTags.TAG_DISPLAY_ACTUAL ) tags.update( current_tags ) tags = sorted( tags ) txt_path = path + '.txt' with open( txt_path, 'w', encoding = 'utf-8' ) as f: f.write( os.linesep.join( tags ) ) source_path = client_files_manager.GetFilePath( hash, mime, check_file_exists = False ) if export_symlinks: os.symlink( source_path, path ) else: HydrusPaths.MirrorFile( source_path, path ) HydrusPaths.MakeFileWriteable( path ) except: QP.CallAfter( QW.QMessageBox.information, self, 'Information', 'Encountered a problem while attempting to export file with index '+str(ordering_index+1)+':'+os.linesep*2+traceback.format_exc() ) break pauser.Pause() if delete_afterwards: QP.CallAfter( qt_update_label, 'deleting' ) delete_lock_for_archived_files = HG.client_controller.new_options.GetBoolean( 'delete_lock_for_archived_files' ) if delete_lock_for_archived_files: deletee_hashes = { media.GetHash() for ( ordering_index, media ) in to_do if not media.HasArchive() } else: deletee_hashes = { media.GetHash() for ( ordering_index, media ) in to_do } chunks_of_hashes = HydrusData.SplitListIntoChunks( deletee_hashes, 64 ) reason = 'Deleted after manual export to "{}".'.format( directory ) content_updates = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, chunk_of_hashes, reason = reason ) for chunk_of_hashes in chunks_of_hashes ] for content_update in content_updates: HG.client_controller.WriteSynchronous( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ content_update ] } ) QP.CallAfter( qt_update_label, 'done!' ) time.sleep( 1 ) QP.CallAfter( qt_update_label, 'export' ) QP.CallAfter( qt_done, quit_afterwards )
def __init__( self, parent, service_key, media, activate_callable ): QW.QWidget.__init__( self, parent ) self._service_key = service_key self._media = media self._new_options = HG.client_controller.new_options layout_mode = self._new_options.GetNoneableString( 'suggested_tags_layout' ) self._notebook = None if layout_mode == 'notebook': self._notebook = ClientGUICommon.BetterNotebook( self ) panel_parent = self._notebook else: panel_parent = self panels = [] self._favourite_tags = None favourites = HG.client_controller.new_options.GetSuggestedTagsFavourites( self._service_key ) if len( favourites ) > 0: self._favourite_tags = FavouritesTagsPanel( panel_parent, service_key, media, activate_callable ) self._favourite_tags.mouseActivationOccurred.connect( self.mouseActivationOccurred ) panels.append( ( 'favourites', self._favourite_tags ) ) self._related_tags = None if self._new_options.GetBoolean( 'show_related_tags' ) and len( media ) == 1: self._related_tags = RelatedTagsPanel( panel_parent, service_key, media, activate_callable ) self._related_tags.mouseActivationOccurred.connect( self.mouseActivationOccurred ) panels.append( ( 'related', self._related_tags ) ) self._file_lookup_script_tags = None if self._new_options.GetBoolean( 'show_file_lookup_script_tags' ) and len( media ) == 1: self._file_lookup_script_tags = FileLookupScriptTagsPanel( panel_parent, service_key, media, activate_callable ) self._file_lookup_script_tags.mouseActivationOccurred.connect( self.mouseActivationOccurred ) panels.append( ( 'file lookup scripts', self._file_lookup_script_tags ) ) self._recent_tags = None if self._new_options.GetNoneableInteger( 'num_recent_tags' ) is not None: self._recent_tags = RecentTagsPanel( panel_parent, service_key, media, activate_callable ) self._recent_tags.mouseActivationOccurred.connect( self.mouseActivationOccurred ) panels.append( ( 'recent', self._recent_tags ) ) hbox = QP.HBoxLayout() if layout_mode == 'notebook': for ( name, panel ) in panels: self._notebook.addTab( panel, name ) QP.AddToLayout( hbox, self._notebook, CC.FLAGS_EXPAND_BOTH_WAYS ) elif layout_mode == 'columns': for ( name, panel ) in panels: QP.AddToLayout( hbox, panel, CC.FLAGS_EXPAND_PERPENDICULAR ) self.setLayout( hbox ) if len( panels ) == 0: self.hide()
def EventText(self, text): QP.CallAfter(self._CheckText)
if len(args) > 0: only_run = args[0] else: only_run = None try: threading.Thread(target=reactor.run, kwargs={ 'installSignalHandlers': 0 }).start() QP.MonkeyPatchMissingMethods() app = QW.QApplication(sys.argv) app.call_after_catcher = QP.CallAfterEventCatcher(app) try: # we run the tests on the Qt thread atm # keep a window alive the whole time so the app doesn't finish its mainloop win = QW.QWidget(None) win.setWindowTitle('Running tests...') controller = TestController.Controller(win, only_run) def do_it():
def __init__(self, parent, service_key, tags, expand_parents=True, message=''): Dialog.__init__(self, parent, 'input tags') self._service_key = service_key self._tags = ClientGUIListBoxes.ListBoxTagsStringsAddRemove( self, service_key=service_key) 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)
def __init__(self, parent, existing_folders_to_names, foldername, name, file_search_context, synchronised, media_sort, media_collect): ClientGUIScrolledPanels.EditPanel.__init__(self, parent) self._existing_folders_to_names = existing_folders_to_names self._original_folder_and_name = (foldername, name) self._foldername = QW.QLineEdit(self) self._name = QW.QLineEdit(self) self._media_sort = ClientGUIResultsSortCollect.MediaSortControl(self) self._media_collect = ClientGUIResultsSortCollect.MediaCollectControl( self, silent=True) page_key = HydrusData.GenerateKey() from hydrus.client.gui.search import ClientGUIACDropdown self._tag_autocomplete = ClientGUIACDropdown.AutoCompleteDropdownTagsRead( self, page_key, file_search_context, media_sort_widget=self._media_sort, media_collect_widget=self._media_collect, synchronised=synchronised, hide_favourites_edit_actions=True) self._include_media_sort = QW.QCheckBox(self) self._include_media_collect = QW.QCheckBox(self) width = ClientGUIFunctions.ConvertTextToPixelWidth( self._include_media_collect, 48) self._include_media_collect.setMinimumWidth(width) self._include_media_sort.stateChanged.connect(self._UpdateWidgets) self._include_media_collect.stateChanged.connect(self._UpdateWidgets) # if foldername is not None: self._foldername.setText(foldername) self._name.setText(name) if media_sort is not None: self._include_media_sort.setChecked(True) self._media_sort.SetSort(media_sort) if media_collect is not None: self._include_media_collect.setChecked(True) self._media_collect.SetCollect(media_collect) # rows = [] rows.append(('folder (blank for none): ', self._foldername)) rows.append(('name: ', self._name)) top_gridbox = ClientGUICommon.WrapInGrid(self, rows) rows = [] rows.append(('save sort: ', self._include_media_sort)) rows.append(('sort: ', self._media_sort)) rows.append(('save collect: ', self._include_media_collect)) rows.append(('collect: ', self._media_collect)) bottom_gridbox = ClientGUICommon.WrapInGrid(self, rows) vbox = QP.VBoxLayout() QP.AddToLayout(vbox, top_gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR) QP.AddToLayout(vbox, self._tag_autocomplete, CC.FLAGS_EXPAND_BOTH_WAYS) QP.AddToLayout(vbox, bottom_gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR) self.widget().setLayout(vbox)
def __init__(self, parent, service_key, subject_identifiers): Dialog.__init__(self, parent, 'modify account') self._service = HG.client_controller.services_manager.GetService( service_key) self._subject_identifiers = list(subject_identifiers) # self._account_info_panel = ClientGUICommon.StaticBox( self, 'account info') self._subject_text = QW.QLabel(self._account_info_panel) # self._account_types_panel = ClientGUICommon.StaticBox( self, 'account types') self._account_types = QW.QComboBox(self._account_types_panel) self._account_types_ok = QW.QPushButton('OK', self._account_types_panel) self._account_types_ok.clicked.connect(self.EventChangeAccountType) # self._expiration_panel = ClientGUICommon.StaticBox( self, 'change expiration') self._add_to_expires = QW.QComboBox(self._expiration_panel) self._add_to_expires_ok = QW.QPushButton('OK', self._expiration_panel) self._add_to_expires.clicked.connect(self.EventAddToExpires) self._set_expires = QW.QComboBox(self._expiration_panel) self._set_expires_ok = QW.QPushButton('OK', self._expiration_panel) self._set_expires_ok.clicked.connect(self.EventSetExpires) # self._ban_panel = ClientGUICommon.StaticBox(self, 'bans') self._ban = QW.QPushButton('ban user', self._ban_panel) self._ban.clicked.connect(self.EventBan) QP.SetBackgroundColour(self._ban, (255, 0, 0)) QP.SetForegroundColour(self._ban, (255, 255, 0)) self._superban = QW.QPushButton( 'ban user and delete every contribution they have ever made', self._ban_panel) self._superban.clicked.connect(self.EventSuperban) QP.SetBackgroundColour(self._superban, (255, 0, 0)) QP.SetForegroundColour(self._superban, (255, 255, 0)) self._exit = QW.QPushButton('Exit', self) self._exit.clicked.connect(self.reject) # if len(self._subject_identifiers) == 1: (subject_identifier, ) = self._subject_identifiers response = self._service.Request( HC.GET, 'account_info', {'subject_identifier': subject_identifier}) subject_string = str(response['account_info']) else: subject_string = 'modifying ' + HydrusData.ToHumanInt( len(self._subject_identifiers)) + ' accounts' self._subject_text.setText(subject_string) # response = self._service.Request(HC.GET, 'account_types') account_types = response['account_types'] for account_type in account_types: self._account_types.addItem(account_type.ConvertToString(), account_type) self._account_types.setCurrentIndex(0) # for (label, value) in HC.lifetimes: if value is not None: self._add_to_expires.addItem( label, value) # don't want 'add no limit' self._add_to_expires.setCurrentIndex(1) # three months for (label, value) in HC.lifetimes: self._set_expires.addItem(label, value) self._set_expires.setCurrentIndex(1) # three months # self._account_info_panel.Add(self._subject_text, CC.FLAGS_EXPAND_PERPENDICULAR) account_types_hbox = QP.HBoxLayout() QP.AddToLayout(account_types_hbox, self._account_types, CC.FLAGS_CENTER_PERPENDICULAR) QP.AddToLayout(account_types_hbox, self._account_types_ok, CC.FLAGS_CENTER_PERPENDICULAR) self._account_types_panel.Add(account_types_hbox, CC.FLAGS_EXPAND_PERPENDICULAR) add_to_expires_box = QP.HBoxLayout() QP.AddToLayout(add_to_expires_box, QW.QLabel('add to expires: ', self._expiration_panel), CC.FLAGS_CENTER_PERPENDICULAR) QP.AddToLayout(add_to_expires_box, self._add_to_expires, CC.FLAGS_EXPAND_BOTH_WAYS) QP.AddToLayout(add_to_expires_box, self._add_to_expires_ok, CC.FLAGS_CENTER_PERPENDICULAR) set_expires_box = QP.HBoxLayout() QP.AddToLayout(set_expires_box, QW.QLabel('set expires to: ', self._expiration_panel), CC.FLAGS_CENTER_PERPENDICULAR) QP.AddToLayout(set_expires_box, self._set_expires, CC.FLAGS_EXPAND_BOTH_WAYS) QP.AddToLayout(set_expires_box, self._set_expires_ok, CC.FLAGS_CENTER_PERPENDICULAR) self._expiration_panel.Add(add_to_expires_box, CC.FLAGS_EXPAND_PERPENDICULAR) self._expiration_panel.Add(set_expires_box, CC.FLAGS_EXPAND_PERPENDICULAR) self._ban_panel.Add(self._ban, CC.FLAGS_EXPAND_PERPENDICULAR) self._ban_panel.Add(self._superban, CC.FLAGS_EXPAND_PERPENDICULAR) vbox = QP.VBoxLayout() QP.AddToLayout(vbox, self._account_info_panel, CC.FLAGS_EXPAND_PERPENDICULAR) QP.AddToLayout(vbox, self._account_types_panel, CC.FLAGS_EXPAND_PERPENDICULAR) QP.AddToLayout(vbox, self._expiration_panel, CC.FLAGS_EXPAND_PERPENDICULAR) QP.AddToLayout(vbox, self._ban_panel, CC.FLAGS_EXPAND_PERPENDICULAR) QP.AddToLayout(vbox, self._exit, CC.FLAGS_ON_RIGHT) self.setLayout(vbox) size_hint = self.sizeHint() QP.SetInitialSize(self, size_hint) HG.client_controller.CallAfterQtSafe(self._exit, self._exit.setFocus, QC.Qt.OtherFocusReason)
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_ON_RIGHT ) 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): title = 'manage local upnp' ClientGUIDialogs.Dialog.__init__(self, parent, title) self._status_st = ClientGUICommon.BetterStaticText(self) self._mappings_listctrl_panel = ClientGUIListCtrl.BetterListCtrlPanel( self) self._mappings_list = ClientGUIListCtrl.BetterListCtrl( self._mappings_listctrl_panel, CGLC.COLUMN_LIST_MANAGE_UPNP_MAPPINGS.ID, 12, self._ConvertDataToListCtrlTuples, delete_key_callback=self._Remove, activation_callback=self._Edit) self._mappings_listctrl_panel.SetListCtrl(self._mappings_list) self._mappings_listctrl_panel.AddButton('add custom mapping', self._Add) self._mappings_listctrl_panel.AddButton( 'edit mapping', self._Edit, enabled_only_on_single_selection=True) self._mappings_listctrl_panel.AddButton('remove mapping', self._Remove, enabled_only_on_selection=True) self._ok = QW.QPushButton('ok', self) self._ok.clicked.connect(self.EventOK) self._ok.setObjectName('HydrusAccept') # vbox = QP.VBoxLayout() QP.AddToLayout(vbox, self._status_st, CC.FLAGS_EXPAND_PERPENDICULAR) QP.AddToLayout(vbox, self._mappings_listctrl_panel, CC.FLAGS_EXPAND_BOTH_WAYS) QP.AddToLayout(vbox, self._ok, CC.FLAGS_ON_RIGHT) self.setLayout(vbox) size_hint = self.sizeHint() size_hint.setWidth(max(size_hint.width(), 760)) QP.SetInitialSize(self, size_hint) # self._mappings_lookup = set() self._mappings_list.Sort() self._external_ip = None self._started_external_ip_fetch = False self._RefreshMappings()
def __init__( self, parent, min = 1, days = False, hours = False, minutes = False, seconds = False, monthly_allowed = False, monthly_label = 'monthly' ): QW.QWidget.__init__( self, parent ) self._min = min self._show_days = days self._show_hours = hours self._show_minutes = minutes self._show_seconds = seconds self._monthly_allowed = monthly_allowed hbox = QP.HBoxLayout( margin = 0 ) if self._show_days: self._days = QP.MakeQSpinBox( self, min=0, max=3653, width = 50 ) self._days.valueChanged.connect( self.EventChange ) QP.AddToLayout( hbox, self._days, CC.FLAGS_CENTER_PERPENDICULAR ) QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'days'), CC.FLAGS_CENTER_PERPENDICULAR ) if self._show_hours: self._hours = QP.MakeQSpinBox( self, min=0, max=23, width = 45 ) self._hours.valueChanged.connect( self.EventChange ) QP.AddToLayout( hbox, self._hours, CC.FLAGS_CENTER_PERPENDICULAR ) QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'hours'), CC.FLAGS_CENTER_PERPENDICULAR ) if self._show_minutes: self._minutes = QP.MakeQSpinBox( self, min=0, max=59, width = 45 ) self._minutes.valueChanged.connect( self.EventChange ) QP.AddToLayout( hbox, self._minutes, CC.FLAGS_CENTER_PERPENDICULAR ) QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'minutes'), CC.FLAGS_CENTER_PERPENDICULAR ) if self._show_seconds: self._seconds = QP.MakeQSpinBox( self, min=0, max=59, width = 45 ) self._seconds.valueChanged.connect( self.EventChange ) QP.AddToLayout( hbox, self._seconds, CC.FLAGS_CENTER_PERPENDICULAR ) QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,'seconds'), CC.FLAGS_CENTER_PERPENDICULAR ) if self._monthly_allowed: self._monthly = QW.QCheckBox( self ) self._monthly.clicked.connect( self.EventChange ) QP.AddToLayout( hbox, self._monthly, CC.FLAGS_CENTER_PERPENDICULAR ) QP.AddToLayout( hbox, ClientGUICommon.BetterStaticText(self,monthly_label), CC.FLAGS_CENTER_PERPENDICULAR ) self.setLayout( hbox )
def __init__(self, parent, share_key, name, text, timeout, hashes, new_share=False): Dialog.__init__(self, parent, 'configure local booru share') self._name = QW.QLineEdit(self) self._text = QW.QPlainTextEdit(self) self._text.setMinimumHeight(100) message = 'expires in' self._timeout_number = ClientGUICommon.NoneableSpinCtrl( self, message, none_phrase='no expiration', max=1000000, multiplier=1) self._timeout_multiplier = ClientGUICommon.BetterChoice(self) self._timeout_multiplier.addItem('minutes', 60) self._timeout_multiplier.addItem('hours', 60 * 60) self._timeout_multiplier.addItem('days', 60 * 60 * 24) self._copy_internal_share_link = QW.QPushButton( 'copy internal share link', self) self._copy_internal_share_link.clicked.connect( self.EventCopyInternalShareURL) self._copy_external_share_link = QW.QPushButton( 'copy external share link', self) self._copy_external_share_link.clicked.connect( self.EventCopyExternalShareURL) self._ok = QW.QPushButton('ok', self) self._ok.clicked.connect(self.accept) self._ok.setObjectName('HydrusAccept') self._cancel = QW.QPushButton('cancel', self) self._cancel.clicked.connect(self.reject) self._cancel.setObjectName('HydrusCancel') # self._share_key = share_key self._name.setText(name) self._text.setPlainText(text) if timeout is None: self._timeout_number.SetValue(None) self._timeout_multiplier.SetValue(60) else: time_left = HydrusData.GetTimeDeltaUntilTime(timeout) if time_left < 60 * 60 * 12: time_value = 60 elif time_left < 60 * 60 * 24 * 7: time_value = 60 * 60 else: time_value = 60 * 60 * 24 self._timeout_number.SetValue(time_left // time_value) self._timeout_multiplier.SetValue(time_value) self._hashes = hashes self._service = HG.client_controller.services_manager.GetService( CC.LOCAL_BOORU_SERVICE_KEY) internal_port = self._service.GetPort() if internal_port is None: self._copy_internal_share_link.setEnabled(False) self._copy_external_share_link.setEnabled(False) # rows = [] rows.append(('share name: ', self._name)) rows.append(('share text: ', self._text)) gridbox = ClientGUICommon.WrapInGrid(self, rows) timeout_box = QP.HBoxLayout() QP.AddToLayout(timeout_box, self._timeout_number, CC.FLAGS_EXPAND_BOTH_WAYS) QP.AddToLayout(timeout_box, self._timeout_multiplier, CC.FLAGS_EXPAND_BOTH_WAYS) link_box = QP.HBoxLayout() QP.AddToLayout(link_box, self._copy_internal_share_link, CC.FLAGS_CENTER_PERPENDICULAR) QP.AddToLayout(link_box, self._copy_external_share_link, CC.FLAGS_CENTER_PERPENDICULAR) 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() intro = 'Sharing ' + HydrusData.ToHumanInt(len( self._hashes)) + ' files.' intro += os.linesep + 'Title and text are optional.' if new_share: intro += os.linesep + 'The link will not work until you ok this dialog.' QP.AddToLayout(vbox, ClientGUICommon.BetterStaticText(self, intro), CC.FLAGS_EXPAND_PERPENDICULAR) QP.AddToLayout(vbox, gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR) QP.AddToLayout(vbox, timeout_box, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR) QP.AddToLayout(vbox, link_box, CC.FLAGS_ON_RIGHT) QP.AddToLayout(vbox, b_box, CC.FLAGS_ON_RIGHT) self.setLayout(vbox) size_hint = self.sizeHint() size_hint.setWidth(max(size_hint.width(), 350)) QP.SetInitialSize(self, size_hint) ClientGUIFunctions.SetFocusLater(self._ok)
def EventShowMenu(self): QP.CallAfter(self._ShowMenu)