Version 179
This commit is contained in:
parent
440a4c0cc2
commit
f929f878b3
|
@ -8,6 +8,40 @@
|
|||
<div class="content">
|
||||
<h3>changelog</h3>
|
||||
<ul>
|
||||
<li><h3>version 179</h3></li>
|
||||
<ul>
|
||||
<li>all tag listboxes support multiple selection</li>
|
||||
<li>all tag listboxes manipulate their data as sets of tags rather than individual tags</li>
|
||||
<li>all tag listboxes report to their callbacks as sets of tags</li>
|
||||
<li>many dialogs and other windows that use tag listboxes now deal with tags as sets</li>
|
||||
<li>double clicking the media viewer's tag hover window now launches the manage tags dialog</li>
|
||||
<li>the media viewer's tag hover window now includes (+1) counts like the manage tags dialog--harmonising the underlying canvas tag list will follow</li>
|
||||
<li>lots of tag/sibling/parent code has been iterated over</li>
|
||||
<li>ditched some misc redundant code and needlessly tightly coupled object relationships</li>
|
||||
<li>some bizarro tag sibling dialog code has been rewritten</li>
|
||||
<li>the autocomplete dropdown for 'writing' will now not expand search results to include parents when the receiving control isn't interested in them or it is otherwise not appropriate</li>
|
||||
<li>when the autocomplete dropdown does have parents, they will be selected in a group with their child</li>
|
||||
<li>the autocomplete dropdown for writing now broadcasts 'I'm done with tagging, close the dialog pls' in a better way</li>
|
||||
<li>'activating' the sibling or parent dialogs' listcontrols (usually by hitting enter) now processes all rows that are selected, not just the first</li>
|
||||
<li>manage siblings and parents dialogs can now take multiple initialising tags from the taglist right-click menu</li>
|
||||
<li>removed some redundant listbox code</li>
|
||||
<li>cleaned up and improved some tag list event processing</li>
|
||||
<li>cleaned up some taglist right-click menu code</li>
|
||||
<li>added system-wide mouse idle test to idle calculation. you can set this in files->options->maintenance and processing, and it defaults to ten minutes</li>
|
||||
<li>import folders now support tag import options' explicit tags for multiple tags to any tag service</li>
|
||||
<li>existing import folders will be updated to the new version, and if a local tag exists, it will be intserted into the new import tag options</li>
|
||||
<li>fixed a hentai foundry page parsing bug</li>
|
||||
<li>the deviant art downloader can now download >1024 pixel width versions of images via the download button (and a bit of cookie magic)</li>
|
||||
<li>gallery page queries that 404 (like for a non-existent username) will now report 'Gallery 404' rather than spamming the gallery's whole custom 404 html page to the status box</li>
|
||||
<li>fixed a bad layout flag that meant some namespace checkboxes in tag import options could remain hidden during first panel expand until first mouseover</li>
|
||||
<li>the import status frame now initialises its status text properly</li>
|
||||
<li>fixed last week's num_tags optimisations, which accidentally broke num_tags < x for x > 1</li>
|
||||
<li>the client should work on both OpenCV 2.4.x and 3.0.0 (thankfully, the only difference for our purposes turned out to be some static variable renaming)</li>
|
||||
<li>the Windows and OS X releases now come with OpenCV 3.0.0</li>
|
||||
<li>increased the max period of import and export folders to 30 days</li>
|
||||
<li>the launchfile/directory thread is now a daemon, so the (some flavours of Linux) client can shutdown even if an externally launched file/dir remains open</li>
|
||||
<li>misc cleanup</li>
|
||||
</ul>
|
||||
<li><h3>version 178</h3></li>
|
||||
<ul>
|
||||
<li>import tag options now supports 'explicit tags', which will be added to all files imported</li>
|
||||
|
|
|
@ -1126,6 +1126,12 @@ class WebSessionManagerClient( object ):
|
|||
|
||||
# name not found, or expired
|
||||
|
||||
if name == 'deviant art':
|
||||
|
||||
( response_gumpf, cookies ) = HydrusGlobals.client_controller.DoHTTP( HC.GET, 'http://www.deviantart.com/', return_cookies = True )
|
||||
|
||||
expires = now + 30 * 86400
|
||||
|
||||
if name == 'hentai foundry':
|
||||
|
||||
( response_gumpf, cookies ) = HydrusGlobals.client_controller.DoHTTP( HC.GET, 'http://www.hentai-foundry.com/?enterAgree=1', return_cookies = True )
|
||||
|
|
|
@ -28,7 +28,7 @@ Ctrl + A - Select all
|
|||
Escape - Deselect all
|
||||
Ctrl + C - Copy selected files to clipboard
|
||||
|
||||
- In Fullscreen -
|
||||
- In Media Viewer -
|
||||
Shift-LeftClick-Drag - Drag (in Filter)
|
||||
Ctrl + MouseWheel - Zoom
|
||||
Z - Zoom Full/Fit'''
|
||||
|
|
|
@ -43,6 +43,8 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
HydrusGlobals.client_controller = self
|
||||
|
||||
self._last_mouse_position = None
|
||||
|
||||
|
||||
def _InitDB( self ):
|
||||
|
||||
|
@ -148,6 +150,31 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
|
||||
|
||||
def CheckMouseIdle( self ):
|
||||
|
||||
mouse_position = wx.GetMousePosition()
|
||||
|
||||
if self._last_mouse_position is None:
|
||||
|
||||
self._last_mouse_position = mouse_position
|
||||
|
||||
elif mouse_position != self._last_mouse_position:
|
||||
|
||||
idle_before = self.CurrentlyIdle()
|
||||
|
||||
self._timestamps[ 'last_mouse_action' ] = HydrusData.GetNow()
|
||||
|
||||
self._last_mouse_position = mouse_position
|
||||
|
||||
idle_after = self.CurrentlyIdle()
|
||||
|
||||
if idle_before != idle_after:
|
||||
|
||||
self.pub( 'refresh_status' )
|
||||
|
||||
|
||||
|
||||
|
||||
def Clipboard( self, data_type, data ):
|
||||
|
||||
# need this cause can't do it in a non-gui thread
|
||||
|
@ -234,12 +261,48 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
def CurrentlyIdle( self ):
|
||||
|
||||
if self._options[ 'idle_period' ] == 0:
|
||||
# the existence of an idle test permits a True result
|
||||
# any single fail vetoes a True
|
||||
|
||||
possibly_idle = False
|
||||
definitely_not_idle = False
|
||||
|
||||
if self._options[ 'idle_period' ] > 0:
|
||||
|
||||
if HydrusData.TimeHasPassed( self._timestamps[ 'last_user_action' ] + self._options[ 'idle_period' ] ):
|
||||
|
||||
possibly_idle = True
|
||||
|
||||
else:
|
||||
|
||||
definitely_not_idle = True
|
||||
|
||||
|
||||
|
||||
if self._options[ 'idle_mouse_period' ] > 0:
|
||||
|
||||
if HydrusData.TimeHasPassed( self._timestamps[ 'last_mouse_action' ] + self._options[ 'idle_mouse_period' ] ):
|
||||
|
||||
possibly_idle = True
|
||||
|
||||
else:
|
||||
|
||||
definitely_not_idle = True
|
||||
|
||||
|
||||
|
||||
if definitely_not_idle:
|
||||
|
||||
return False
|
||||
|
||||
elif possibly_idle:
|
||||
|
||||
return True
|
||||
|
||||
else:
|
||||
|
||||
return False
|
||||
|
||||
|
||||
return HydrusData.TimeHasPassed( self._timestamps[ 'last_user_action' ] + self._options[ 'idle_period' ] )
|
||||
|
||||
|
||||
def DoHTTP( self, *args, **kwargs ): return self._http.Request( *args, **kwargs )
|
||||
|
@ -295,7 +358,10 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
def ForceIdle( self ):
|
||||
|
||||
self._timestamps[ 'last_user_action' ] = 0
|
||||
del self._timestamps[ 'last_user_action' ]
|
||||
del self._timestamps[ 'last_mouse_action' ]
|
||||
|
||||
self._last_mouse_position = None
|
||||
|
||||
self.pub( 'wake_daemons' )
|
||||
self.pub( 'refresh_status' )
|
||||
|
@ -422,6 +488,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
self.RestartBooru()
|
||||
|
||||
self._daemons.append( HydrusThreading.DAEMONWorker( self, 'CheckImportFolders', ClientDaemons.DAEMONCheckImportFolders, ( 'notify_restart_import_folders_daemon', 'notify_new_import_folders' ), period = 180 ) )
|
||||
self._daemons.append( HydrusThreading.DAEMONWorker( self, 'CheckMouseIdle', ClientDaemons.DAEMONCheckMouseIdle, period = 10 ) )
|
||||
self._daemons.append( HydrusThreading.DAEMONWorker( self, 'CheckExportFolders', ClientDaemons.DAEMONCheckExportFolders, ( 'notify_restart_export_folders_daemon', 'notify_new_export_folders' ), period = 180 ) )
|
||||
self._daemons.append( HydrusThreading.DAEMONWorker( self, 'DownloadFiles', ClientDaemons.DAEMONDownloadFiles, ( 'notify_new_downloads', 'notify_new_permissions' ), pre_callable_wait = 0 ) )
|
||||
self._daemons.append( HydrusThreading.DAEMONWorker( self, 'MaintainTrash', ClientDaemons.DAEMONMaintainTrash, init_wait = 60 ) )
|
||||
|
@ -506,7 +573,10 @@ class Controller( HydrusController.HydrusController ):
|
|||
else: return text.lower()
|
||||
|
||||
|
||||
def ResetIdleTimer( self ): self._timestamps[ 'last_user_action' ] = HydrusData.GetNow()
|
||||
def ResetIdleTimer( self ):
|
||||
|
||||
self._timestamps[ 'last_user_action' ] = HydrusData.GetNow()
|
||||
|
||||
|
||||
def ResetPageChangeTimer( self ):
|
||||
|
||||
|
|
|
@ -2733,6 +2733,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
num_tags_zero = False
|
||||
num_tags_nonzero = False
|
||||
max_num_tags_exists = False
|
||||
|
||||
tag_predicates = []
|
||||
|
||||
|
@ -2778,10 +2779,12 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
|
||||
|
||||
if num_tags_zero or num_tags_nonzero:
|
||||
|
||||
if tag_service_key == CC.COMBINED_TAG_SERVICE_KEY: service_phrase = ''
|
||||
else: service_phrase = 'service_id = ' + HydrusData.ToString( tag_service_id ) + ' AND '
|
||||
tag_predicates_care_about_zero_counts = len( tag_predicates ) > 0 and False not in ( pred( 0 ) for pred in tag_predicates )
|
||||
|
||||
if tag_service_key == CC.COMBINED_TAG_SERVICE_KEY: service_phrase = ''
|
||||
else: service_phrase = 'service_id = ' + HydrusData.ToString( tag_service_id ) + ' AND '
|
||||
|
||||
if num_tags_zero or num_tags_nonzero or tag_predicates_care_about_zero_counts:
|
||||
|
||||
nonzero_tag_query_hash_ids = { id for ( id, ) in self._c.execute( 'SELECT DISTINCT hash_id FROM mappings WHERE ' + service_phrase + 'hash_id IN ' + HydrusData.SplayListForDB( query_hash_ids ) + ' AND status IN ' + HydrusData.SplayListForDB( statuses ) + ';' ) }
|
||||
|
||||
|
@ -2791,20 +2794,15 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
if len( tag_predicates ) > 0:
|
||||
|
||||
if tag_service_key == CC.COMBINED_TAG_SERVICE_KEY: service_phrase = ''
|
||||
else: service_phrase = 'service_id = ' + HydrusData.ToString( tag_service_id ) + ' AND '
|
||||
|
||||
old_query_hash_ids = query_hash_ids
|
||||
|
||||
nonzero_counts_query = 'SELECT hash_id, COUNT( DISTINCT tag_id ) FROM mappings WHERE ' + service_phrase + 'hash_id IN ' + HydrusData.SplayListForDB( query_hash_ids ) + ' AND status IN ' + HydrusData.SplayListForDB( statuses ) + ' GROUP BY hash_id;'
|
||||
|
||||
query_hash_ids = { id for ( id, count ) in self._c.execute( nonzero_counts_query ) if False not in ( pred( count ) for pred in tag_predicates ) }
|
||||
|
||||
include_zero_count_in_calculation = False not in ( pred( 0 ) for pred in tag_predicates )
|
||||
|
||||
if include_zero_count_in_calculation:
|
||||
if tag_predicates_care_about_zero_counts:
|
||||
|
||||
zero_hash_ids = old_query_hash_ids.difference( query_hash_ids )
|
||||
zero_hash_ids = old_query_hash_ids.difference( nonzero_tag_query_hash_ids )
|
||||
|
||||
query_hash_ids.update( zero_hash_ids )
|
||||
|
||||
|
@ -5836,9 +5834,19 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
|
||||
period = details[ 'check_period' ]
|
||||
|
||||
tag = details[ 'local_tag' ]
|
||||
|
||||
import_folder = ClientImporting.ImportFolder( name, path, import_file_options = import_file_options, actions = actions, action_locations = {}, period = period, open_popup = True, tag = tag )
|
||||
service_keys_to_explicit_tags = dict()
|
||||
|
||||
if tag is not None:
|
||||
|
||||
service_keys_to_explicit_tags[ CC.LOCAL_TAG_SERVICE_KEY ] = { tag }
|
||||
|
||||
|
||||
import_tag_options = ClientData.ImportTagOptions( service_keys_to_explicit_tags = service_keys_to_explicit_tags )
|
||||
|
||||
import_folder = ClientImporting.ImportFolder( name, path, import_file_options = import_file_options, import_tag_options = import_tag_options, actions = actions, action_locations = {}, period = period, open_popup = True )
|
||||
|
||||
import_folder._last_checked = details[ 'last_checked' ]
|
||||
|
||||
|
|
|
@ -69,6 +69,10 @@ def DAEMONCheckImportFolders():
|
|||
|
||||
|
||||
|
||||
def DAEMONCheckMouseIdle():
|
||||
|
||||
HydrusGlobals.client_controller.CheckMouseIdle()
|
||||
|
||||
def DAEMONDownloadFiles():
|
||||
|
||||
hashes = HydrusGlobals.client_controller.Read( 'downloads' )
|
||||
|
|
|
@ -27,6 +27,7 @@ def GetClientDefaultOptions():
|
|||
options[ 'ac_timings' ] = ( 3, 500, 250 )
|
||||
options[ 'thread_checker_timings' ] = ( 3, 1200 )
|
||||
options[ 'idle_period' ] = 60 * 30
|
||||
options[ 'idle_mouse_period' ] = 60 * 10
|
||||
options[ 'idle_cpu_max' ] = 50
|
||||
options[ 'idle_shutdown' ] = CC.IDLE_ON_SHUTDOWN_ASK_FIRST
|
||||
options[ 'idle_shutdown_max_minutes' ] = 30
|
||||
|
|
|
@ -723,6 +723,15 @@ class GalleryBooru( Gallery ):
|
|||
|
||||
class GalleryDeviantArt( Gallery ):
|
||||
|
||||
def _AddSessionCookies( self, request_headers ):
|
||||
|
||||
manager = HydrusGlobals.client_controller.GetManager( 'web_sessions' )
|
||||
|
||||
cookies = manager.GetCookies( 'deviant art' )
|
||||
|
||||
ClientNetworking.AddCookiesToHeaders( cookies, request_headers )
|
||||
|
||||
|
||||
def _GetGalleryPageURL( self, query, page_index ):
|
||||
|
||||
artist = query
|
||||
|
@ -774,30 +783,45 @@ class GalleryDeviantArt( Gallery ):
|
|||
return ( urls, definitely_no_more_pages )
|
||||
|
||||
|
||||
def _ParseImagePage( self, html ):
|
||||
def _ParseImagePage( self, html, referer_url ):
|
||||
|
||||
soup = bs4.BeautifulSoup( html )
|
||||
|
||||
img = soup.find( class_ = 'dev-content-full' )
|
||||
download_button = soup.find( 'a', class_ = 'dev-page-download' )
|
||||
|
||||
if img is None:
|
||||
if download_button is None:
|
||||
|
||||
# this probably means it is mature
|
||||
# DA hide the url pretty much everywhere except the tumblr share thing
|
||||
# this method maxes out at 1024 width
|
||||
|
||||
a_tumblr = soup.find( id = 'gmi-ResourceViewShareTumblr' )
|
||||
img = soup.find( class_ = 'dev-content-full' )
|
||||
|
||||
tumblr_url = a_tumblr[ 'href' ] # http://www.tumblr.com/share/photo?source=http%3A%2F%2Fimg09.deviantart.net%2Ff19a%2Fi%2F2015%2F054%2Fe%2Fd%2Fass_by_gmgkaiser-d8j7ija.png&caption=%3Ca+href%3D%22http%3A%2F%2Fgmgkaiser.deviantart.com%2Fart%2Fass-515992726%22%3Eass%3C%2Fa%3E+by+%3Ca+href%3D%22http%3A%2F%2Fgmgkaiser.deviantart.com%2F%22%3EGMGkaiser%3C%2Fa%3E&clickthru=http%3A%2F%2Fgmgkaiser.deviantart.com%2Fart%2Fass-515992726
|
||||
|
||||
parse_result = urlparse.urlparse( tumblr_url )
|
||||
|
||||
query_parse_result = urlparse.parse_qs( parse_result.query )
|
||||
|
||||
img_url = query_parse_result[ 'source' ][0] # http://img09.deviantart.net/f19a/i/2015/054/e/d/ass_by_gmgkaiser-d8j7ija.png
|
||||
if img is None:
|
||||
|
||||
# this probably means it is mature
|
||||
# DA hide the url pretty much everywhere except the tumblr share thing
|
||||
|
||||
a_tumblr = soup.find( id = 'gmi-ResourceViewShareTumblr' )
|
||||
|
||||
tumblr_url = a_tumblr[ 'href' ] # http://www.tumblr.com/share/photo?source=http%3A%2F%2Fimg09.deviantart.net%2Ff19a%2Fi%2F2015%2F054%2Fe%2Fd%2Fass_by_gmgkaiser-d8j7ija.png&caption=%3Ca+href%3D%22http%3A%2F%2Fgmgkaiser.deviantart.com%2Fart%2Fass-515992726%22%3Eass%3C%2Fa%3E+by+%3Ca+href%3D%22http%3A%2F%2Fgmgkaiser.deviantart.com%2F%22%3EGMGkaiser%3C%2Fa%3E&clickthru=http%3A%2F%2Fgmgkaiser.deviantart.com%2Fart%2Fass-515992726
|
||||
|
||||
parse_result = urlparse.urlparse( tumblr_url )
|
||||
|
||||
query_parse_result = urlparse.parse_qs( parse_result.query )
|
||||
|
||||
img_url = query_parse_result[ 'source' ][0] # http://img09.deviantart.net/f19a/i/2015/054/e/d/ass_by_gmgkaiser-d8j7ija.png
|
||||
|
||||
else:
|
||||
|
||||
img_url = img[ 'src' ]
|
||||
|
||||
|
||||
else:
|
||||
|
||||
img_url = img[ 'src' ]
|
||||
# something like http://www.deviantart.com/download/518046750/varda_and_the_sacred_trees_of_valinor_by_implosinoatic-d8kfjfi.jpg?token=476cb73aa2ab22bb8554542bc9f14982e09bd534&ts=1445717843
|
||||
# given the right cookies, it redirects to the truly fullsize image_url
|
||||
# otherwise, it seems to redirect to a small interstitial redirect page that heads back to the original image page
|
||||
|
||||
img_url = download_button[ 'href' ]
|
||||
|
||||
|
||||
return img_url
|
||||
|
@ -807,7 +831,7 @@ class GalleryDeviantArt( Gallery ):
|
|||
|
||||
html = self._FetchData( url, report_hooks = report_hooks )
|
||||
|
||||
return self._ParseImagePage( html )
|
||||
return self._ParseImagePage( html, url )
|
||||
|
||||
|
||||
def GetFile( self, temp_path, url, report_hooks = None ):
|
||||
|
@ -925,6 +949,11 @@ class GalleryHentaiFoundry( Gallery ):
|
|||
|
||||
def correct_url( href ):
|
||||
|
||||
if href is None:
|
||||
|
||||
return False
|
||||
|
||||
|
||||
# a good url is in the form "/pictures/user/artist_name/file_id/title"
|
||||
|
||||
if href.count( '/' ) == 5 and href.startswith( '/pictures/user/' ):
|
||||
|
|
|
@ -376,14 +376,22 @@ class ExportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
def DoWork( self ):
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' checking' )
|
||||
|
||||
if HydrusData.TimeHasPassed( self._last_checked + self._period ):
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' time to begin' )
|
||||
|
||||
folder_path = self._name
|
||||
|
||||
if os.path.exists( folder_path ) and os.path.isdir( folder_path ):
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' folder checks out ok' )
|
||||
|
||||
query_hash_ids = HydrusGlobals.client_controller.Read( 'file_query_ids', self._file_search_context )
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' results found: ' + str( len( query_hash_ids ) ) )
|
||||
|
||||
query_hash_ids = list( query_hash_ids )
|
||||
|
||||
random.shuffle( query_hash_ids )
|
||||
|
@ -400,6 +408,8 @@ class ExportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
while i < len( query_hash_ids ):
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' building results: ' + str( i ) + '/' + str( len( query_hash_ids ) ) )
|
||||
|
||||
if HC.options[ 'pause_export_folders_sync' ]: return
|
||||
|
||||
if i == 0: ( last_i, i ) = ( 0, base )
|
||||
|
@ -412,12 +422,21 @@ class ExportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
media_results.extend( more_media_results )
|
||||
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' media_results: ' + str( len( media_results ) ) )
|
||||
|
||||
#
|
||||
|
||||
terms = ParseExportPhrase( self._phrase )
|
||||
|
||||
previous_filenames = set( os.listdir( folder_path ) )
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' existing filenames: ' + str( len( previous_filenames ) ) )
|
||||
if HydrusGlobals.special_debug_mode:
|
||||
for previous_filename in previous_filenames:
|
||||
|
||||
print( previous_filename )
|
||||
|
||||
|
||||
sync_filenames = set()
|
||||
|
||||
for media_result in media_results:
|
||||
|
@ -431,54 +450,54 @@ class ExportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
filename = GenerateExportFilename( media_result, terms ) + HC.mime_ext_lookup[ mime ]
|
||||
|
||||
dest_path = folder_path + os.path.sep + filename
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' dest path: ' + dest_path )
|
||||
do_copy = True
|
||||
|
||||
if filename in sync_filenames:
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' it was already attempted this run' )
|
||||
do_copy = False
|
||||
|
||||
elif os.path.exists( dest_path ):
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' it exists' )
|
||||
dest_info = os.lstat( dest_path )
|
||||
|
||||
dest_size = dest_info[6]
|
||||
|
||||
if dest_size == size:
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' and the file size is the same' )
|
||||
do_copy = False
|
||||
|
||||
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' copy decision: ' + str( do_copy ) )
|
||||
if do_copy:
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' copy started' )
|
||||
shutil.copy( source_path, dest_path )
|
||||
shutil.copystat( source_path, dest_path )
|
||||
|
||||
try: os.chmod( dest_path, stat.S_IWRITE | stat.S_IREAD )
|
||||
except: pass
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' copy ok' )
|
||||
|
||||
sync_filenames.add( filename )
|
||||
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' media results done' )
|
||||
if self._export_type == HC.EXPORT_FOLDER_TYPE_SYNCHRONISE:
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' inside sync delete code' )
|
||||
deletee_filenames = previous_filenames.difference( sync_filenames )
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' delete filenames: ' + str( len( deletee_filenames ) ) )
|
||||
for deletee_filename in deletee_filenames:
|
||||
|
||||
deletee_path = folder_path + os.path.sep + deletee_filename
|
||||
|
||||
if HydrusGlobals.special_debug_mode: print( deletee_path )
|
||||
ClientData.DeletePath( deletee_path )
|
||||
|
||||
|
||||
|
||||
|
||||
self._last_checked = HydrusData.GetNow()
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' writing self back to db' )
|
||||
HydrusGlobals.client_controller.WriteSynchronous( 'serialisable', self )
|
||||
|
||||
if HydrusGlobals.special_debug_mode: HydrusData.ShowText( self._name + ' saved ok' )
|
||||
|
||||
|
||||
def ToTuple( self ):
|
||||
|
|
|
@ -1012,10 +1012,13 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
|||
menu.AppendMenu( wx.ID_NONE, p( 'Links' ), links )
|
||||
|
||||
db_profile_mode_id = ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'db_profile_mode' )
|
||||
special_debug_mode_id = ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'special_debug_mode' )
|
||||
|
||||
debug = wx.Menu()
|
||||
debug.AppendCheckItem( db_profile_mode_id, p( '&DB Profile Mode' ) )
|
||||
debug.Check( db_profile_mode_id, HydrusGlobals.db_profile_mode )
|
||||
debug.AppendCheckItem( special_debug_mode_id, p( '&Special Debug Mode' ) )
|
||||
debug.Check( special_debug_mode_id, HydrusGlobals.special_debug_mode )
|
||||
debug.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'force_idle' ), p( 'Force Idle Mode' ) )
|
||||
debug.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'force_unbusy' ), p( 'Force Unbusy Mode' ) )
|
||||
debug.Append( ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetPermanentId( 'debug_garbage' ), p( 'Garbage' ) )
|
||||
|
@ -2137,6 +2140,10 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
if page is not None: page.ShowHideSplit()
|
||||
|
||||
elif command == 'site': webbrowser.open( 'https://hydrusnetwork.github.io/hydrus/' )
|
||||
elif command == 'special_debug_mode':
|
||||
|
||||
HydrusGlobals.special_debug_mode = not HydrusGlobals.special_debug_mode
|
||||
|
||||
elif command == 'start_url_download': self._StartURLDownload()
|
||||
elif command == 'start_youtube_download': self._StartYoutubeDownload()
|
||||
elif command == 'stats': self._Stats( data )
|
||||
|
@ -3342,10 +3349,12 @@ class FrameSeedCache( ClientGUICommon.Frame ):
|
|||
|
||||
HydrusGlobals.client_controller.sub( self, 'NotifySeedUpdated', 'seed_cache_seed_updated' )
|
||||
|
||||
wx.CallAfter( self._UpdateText )
|
||||
|
||||
wx.CallAfter( self.Raise )
|
||||
|
||||
|
||||
def NotifySeedUpdated( self, seed ):
|
||||
def _UpdateText( self ):
|
||||
|
||||
( status, ( total_processed, total ) ) = self._seed_cache.GetStatus()
|
||||
|
||||
|
@ -3354,6 +3363,11 @@ class FrameSeedCache( ClientGUICommon.Frame ):
|
|||
self.Layout()
|
||||
|
||||
|
||||
def NotifySeedUpdated( self, seed ):
|
||||
|
||||
self._UpdateText()
|
||||
|
||||
|
||||
class FrameSplash( ClientGUICommon.Frame ):
|
||||
|
||||
WIDTH = 300
|
||||
|
|
|
@ -588,6 +588,7 @@ class Canvas( object ):
|
|||
HydrusGlobals.client_controller.sub( self, 'ZoomOut', 'canvas_zoom_out' )
|
||||
HydrusGlobals.client_controller.sub( self, 'ZoomSwitch', 'canvas_zoom_switch' )
|
||||
HydrusGlobals.client_controller.sub( self, 'OpenExternally', 'canvas_open_externally' )
|
||||
HydrusGlobals.client_controller.sub( self, 'ManageTags', 'canvas_manage_tags' )
|
||||
|
||||
|
||||
def _Archive( self ): HydrusGlobals.client_controller.Write( 'content_updates', { CC.LOCAL_FILE_SERVICE_KEY : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, ( self._current_display_media.GetHash(), ) ) ] } )
|
||||
|
@ -772,6 +773,7 @@ class Canvas( object ):
|
|||
with ClientGUIDialogsManage.DialogManageTags( self, self._file_service_key, ( self._current_display_media, ), canvas_key = self._canvas_key ) as dlg:
|
||||
|
||||
dlg.ShowModal()
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1023,6 +1025,14 @@ class Canvas( object ):
|
|||
|
||||
def KeepCursorAlive( self ): pass
|
||||
|
||||
def ManageTags( self, canvas_key ):
|
||||
|
||||
if canvas_key == self._canvas_key:
|
||||
|
||||
self._ManageTags()
|
||||
|
||||
|
||||
|
||||
def MouseIsNearAnimationBar( self ):
|
||||
|
||||
return self._media_container.MouseIsNearAnimationBar()
|
||||
|
@ -1487,7 +1497,7 @@ class CanvasFullscreenMediaList( ClientMedia.ListeningMediaList, CanvasWithDetai
|
|||
|
||||
def __init__( self, my_parent, page_key, media_results ):
|
||||
|
||||
ClientGUICommon.FrameThatResizes.__init__( self, my_parent, resize_option_prefix = 'fs_', title = 'hydrus client fullscreen media viewer' )
|
||||
ClientGUICommon.FrameThatResizes.__init__( self, my_parent, resize_option_prefix = 'fs_', title = 'hydrus client media viewer' )
|
||||
CanvasWithDetails.__init__( self, HydrusGlobals.client_controller.GetCache( 'fullscreen' ) )
|
||||
ClientMedia.ListeningMediaList.__init__( self, CC.LOCAL_FILE_SERVICE_KEY, media_results )
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -286,7 +286,9 @@ class DialogAdvancedContentUpdate( Dialog ):
|
|||
self._go = wx.Button( self._internal_actions, label = 'Go!' )
|
||||
self._go.Bind( wx.EVT_BUTTON, self.EventGo )
|
||||
|
||||
self._tag_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self._internal_actions, self.SetSomeTag, CC.COMBINED_FILE_SERVICE_KEY, self._service_key )
|
||||
expand_parents = False
|
||||
|
||||
self._tag_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self._internal_actions, self.SetSomeTags, expand_parents, CC.COMBINED_FILE_SERVICE_KEY, self._service_key )
|
||||
self._specific_tag = wx.StaticText( self._internal_actions, label = '', size = ( 100, -1 ) )
|
||||
|
||||
self._import_from_hta = wx.Button( self._internal_actions, label = 'one-time mass import or delete using a hydrus tag archive' )
|
||||
|
@ -418,6 +420,9 @@ class DialogAdvancedContentUpdate( Dialog ):
|
|||
|
||||
def EventGo( self, event ):
|
||||
|
||||
# at some point, rewrite this to cope with multiple tags. setsometag is ready to go on that front
|
||||
# this should prob be with a listbox so people can enter their new multiple tags in several separate goes, rather than overwriting every time
|
||||
|
||||
with DialogYesNo( self, 'Are you sure?' ) as dlg:
|
||||
|
||||
if dlg.ShowModal() != wx.ID_YES: return
|
||||
|
@ -475,13 +480,14 @@ class DialogAdvancedContentUpdate( Dialog ):
|
|||
|
||||
|
||||
|
||||
def SetSomeTag( self, tag, parents = None ):
|
||||
def SetSomeTags( self, tags ):
|
||||
|
||||
if parents is None: parents = []
|
||||
|
||||
self._tag = tag
|
||||
|
||||
self._specific_tag.SetLabel( tag )
|
||||
if len( tags ) > 0:
|
||||
|
||||
self._tag = list( tags )[0]
|
||||
|
||||
self._specific_tag.SetLabel( self._tag )
|
||||
|
||||
|
||||
|
||||
class DialogButtonChoice( Dialog ):
|
||||
|
@ -844,7 +850,10 @@ class DialogInputCustomFilterAction( Dialog ):
|
|||
|
||||
self._tag_service_keys = wx.Choice( self._tag_panel )
|
||||
self._tag_value = wx.TextCtrl( self._tag_panel, style = wx.TE_READONLY )
|
||||
self._tag_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self._tag_panel, self.SetTag, CC.LOCAL_FILE_SERVICE_KEY, CC.COMBINED_TAG_SERVICE_KEY )
|
||||
|
||||
expand_parents = False
|
||||
|
||||
self._tag_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self._tag_panel, self.SetTags, expand_parents, CC.LOCAL_FILE_SERVICE_KEY, CC.COMBINED_TAG_SERVICE_KEY )
|
||||
|
||||
self._ok_tag = wx.Button( self._tag_panel, label = 'ok' )
|
||||
self._ok_tag.Bind( wx.EVT_BUTTON, self.EventOKTag )
|
||||
|
@ -1142,6 +1151,8 @@ class DialogInputCustomFilterAction( Dialog ):
|
|||
|
||||
def EventOKTag( self, event ):
|
||||
|
||||
# this could support multiple tags now
|
||||
|
||||
selection = self._tag_service_keys.GetSelection()
|
||||
|
||||
if selection != wx.NOT_FOUND:
|
||||
|
@ -1175,11 +1186,14 @@ class DialogInputCustomFilterAction( Dialog ):
|
|||
return ( ( pretty_modifier, pretty_key, pretty_service_key, self._pretty_action ), ( modifier, key, self._service_key, self._action ) )
|
||||
|
||||
|
||||
def SetTag( self, tag, parents = None ):
|
||||
def SetTags( self, tags ):
|
||||
|
||||
if parents is None: parents = []
|
||||
|
||||
self._tag_value.SetValue( tag )
|
||||
if len( tags ) > 0:
|
||||
|
||||
tag = list( tags )[0]
|
||||
|
||||
self._tag_value.SetValue( tag )
|
||||
|
||||
|
||||
|
||||
class DialogInputFileSystemPredicates( Dialog ):
|
||||
|
@ -2460,7 +2474,9 @@ class DialogInputTags( Dialog ):
|
|||
|
||||
self._tags = ClientGUICommon.ListBoxTagsStrings( self )
|
||||
|
||||
self._tag_box = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.AddTag, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
expand_parents = True
|
||||
|
||||
self._tag_box = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.EnterTags, expand_parents, CC.LOCAL_FILE_SERVICE_KEY, service_key, null_entry_callable = self.Ok )
|
||||
|
||||
self._ok = wx.Button( self, id= wx.ID_OK, label = 'Ok' )
|
||||
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
|
||||
|
@ -2496,17 +2512,17 @@ class DialogInputTags( Dialog ):
|
|||
wx.CallAfter( self._tag_box.SetFocus )
|
||||
|
||||
|
||||
def AddTag( self, tag, parents = None ):
|
||||
def EnterTags( self, tags, parents = None ):
|
||||
|
||||
if parents is None: parents = []
|
||||
if parents is None:
|
||||
|
||||
parents = []
|
||||
|
||||
|
||||
if tag is None:
|
||||
if len( tags ) > 0:
|
||||
|
||||
self.EndModal( wx.ID_OK )
|
||||
|
||||
else:
|
||||
|
||||
self._tags.AddTag( tag, parents )
|
||||
self._tags.EnterTags( tags )
|
||||
self._tags.AddTags( parents )
|
||||
|
||||
|
||||
|
||||
|
@ -2515,6 +2531,11 @@ class DialogInputTags( Dialog ):
|
|||
return self._tags.GetTags()
|
||||
|
||||
|
||||
def Ok( self ):
|
||||
|
||||
self.EndModal( wx.ID_OK )
|
||||
|
||||
|
||||
class DialogInputUPnPMapping( Dialog ):
|
||||
|
||||
def __init__( self, parent, external_port, protocol_type, internal_port, description, duration ):
|
||||
|
@ -3404,19 +3425,23 @@ class DialogPathsToTags( Dialog ):
|
|||
|
||||
self._tags_panel = ClientGUICommon.StaticBox( self, 'tags for all' )
|
||||
|
||||
self._tags = ClientGUICommon.ListBoxTagsStrings( self._tags_panel, self.TagRemoved )
|
||||
self._tags = ClientGUICommon.ListBoxTagsStrings( self._tags_panel, self.TagsRemoved )
|
||||
|
||||
self._tag_box = ClientGUICommon.AutoCompleteDropdownTagsWrite( self._tags_panel, self.AddTag, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
expand_parents = True
|
||||
|
||||
self._tag_box = ClientGUICommon.AutoCompleteDropdownTagsWrite( self._tags_panel, self.EnterTags, expand_parents, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
|
||||
#
|
||||
|
||||
self._single_tags_panel = ClientGUICommon.StaticBox( self, 'tags just for selected files' )
|
||||
|
||||
self._paths_to_single_tags = collections.defaultdict( list )
|
||||
self._paths_to_single_tags = collections.defaultdict( set )
|
||||
|
||||
self._single_tags = ClientGUICommon.ListBoxTagsStrings( self._single_tags_panel, self.SingleTagRemoved )
|
||||
self._single_tags = ClientGUICommon.ListBoxTagsStrings( self._single_tags_panel, self.SingleTagsRemoved )
|
||||
|
||||
self._single_tag_box = ClientGUICommon.AutoCompleteDropdownTagsWrite( self._single_tags_panel, self.AddTagSingle, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
expand_parents = True
|
||||
|
||||
self._single_tag_box = ClientGUICommon.AutoCompleteDropdownTagsWrite( self._single_tags_panel, self.EnterTagsSingle, expand_parents, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
|
||||
|
||||
def PopulateControls():
|
||||
|
@ -3544,7 +3569,10 @@ class DialogPathsToTags( Dialog ):
|
|||
except: pass
|
||||
|
||||
|
||||
if path in self._paths_to_single_tags: tags.extend( self._paths_to_single_tags[ path ] )
|
||||
if path in self._paths_to_single_tags:
|
||||
|
||||
tags.extend( list( self._paths_to_single_tags[ path ] ) )
|
||||
|
||||
|
||||
num_namespace = self._num_namespace.GetValue()
|
||||
|
||||
|
@ -3581,48 +3609,6 @@ class DialogPathsToTags( Dialog ):
|
|||
|
||||
|
||||
|
||||
def AddTag( self, tag, parents = None ):
|
||||
|
||||
if parents is None: parents = []
|
||||
|
||||
if tag is not None:
|
||||
|
||||
self._tags.AddTag( tag, parents )
|
||||
|
||||
self._RefreshFileList()
|
||||
|
||||
|
||||
|
||||
def AddTagSingle( self, tag, parents = None ):
|
||||
|
||||
if parents is None: parents = []
|
||||
|
||||
if tag is not None:
|
||||
|
||||
self._single_tags.AddTag( tag, parents )
|
||||
|
||||
indices = self._paths_list.GetAllSelected()
|
||||
|
||||
for index in indices:
|
||||
|
||||
( ( original_num, processed_num ), path, old_tags ) = self._paths_list.GetClientData( index )
|
||||
|
||||
if tag in self._paths_to_single_tags[ path ]: self._paths_to_single_tags[ path ].remove( tag )
|
||||
else:
|
||||
|
||||
self._paths_to_single_tags[ path ].append( tag )
|
||||
|
||||
for parent in parents:
|
||||
|
||||
if parent not in self._paths_to_single_tags[ path ]: self._paths_to_single_tags[ path ].append( parent )
|
||||
|
||||
|
||||
|
||||
|
||||
self._RefreshFileList()
|
||||
|
||||
|
||||
|
||||
def DeleteQuickNamespaces( self ):
|
||||
|
||||
self._quick_namespaces_list.RemoveAllSelected()
|
||||
|
@ -3630,6 +3616,61 @@ class DialogPathsToTags( Dialog ):
|
|||
self._RefreshFileList()
|
||||
|
||||
|
||||
def EnterTags( self, tags, parents = None ):
|
||||
|
||||
if parents is None:
|
||||
|
||||
parents = []
|
||||
|
||||
|
||||
if len( tags ) > 0:
|
||||
|
||||
self._tags.EnterTags( tags )
|
||||
self._tags.AddTags( parents )
|
||||
|
||||
self._RefreshFileList()
|
||||
|
||||
|
||||
|
||||
def EnterTagsSingle( self, tags, parents = None ):
|
||||
|
||||
if parents is None:
|
||||
|
||||
parents = []
|
||||
|
||||
|
||||
if len( tags ) > 0:
|
||||
|
||||
self._single_tags.EnterTags( tags )
|
||||
self._single_tags.AddTags( parents )
|
||||
|
||||
indices = self._paths_list.GetAllSelected()
|
||||
|
||||
for index in indices:
|
||||
|
||||
( ( original_num, processed_num ), path, old_pretty_tags ) = self._paths_list.GetClientData( index )
|
||||
|
||||
current_tags = self._paths_to_single_tags[ path ]
|
||||
|
||||
for tag in tags:
|
||||
|
||||
if tag in current_tags:
|
||||
|
||||
current_tags.discard( tag )
|
||||
|
||||
else:
|
||||
|
||||
current_tags.add( tag )
|
||||
|
||||
|
||||
|
||||
current_tags.update( parents )
|
||||
|
||||
|
||||
self._RefreshFileList()
|
||||
|
||||
|
||||
|
||||
def EventAddRegex( self, event ):
|
||||
|
||||
regex = self._regex_box.GetValue()
|
||||
|
@ -3708,7 +3749,10 @@ class DialogPathsToTags( Dialog ):
|
|||
|
||||
path = self._paths_list.GetClientData( index )[1]
|
||||
|
||||
if path in self._paths_to_single_tags: single_tags.update( self._paths_to_single_tags[ path ] )
|
||||
if path in self._paths_to_single_tags:
|
||||
|
||||
single_tags.update( self._paths_to_single_tags[ path ] )
|
||||
|
||||
|
||||
|
||||
self._single_tag_box.Enable()
|
||||
|
@ -3760,7 +3804,7 @@ class DialogPathsToTags( Dialog ):
|
|||
|
||||
def SetTagBoxFocus( self ): self._tag_box.SetFocus()
|
||||
|
||||
def SingleTagRemoved( self, tag ):
|
||||
def SingleTagsRemoved( self, tags ):
|
||||
|
||||
indices = self._paths_list.GetAllSelected()
|
||||
|
||||
|
@ -3768,13 +3812,18 @@ class DialogPathsToTags( Dialog ):
|
|||
|
||||
( ( original_num, processed_num ), path, old_tags ) = self._paths_list.GetClientData( index )
|
||||
|
||||
if tag in self._paths_to_single_tags[ path ]: self._paths_to_single_tags[ path ].remove( tag )
|
||||
current_tags = self._paths_to_single_tags[ path ]
|
||||
|
||||
current_tags.difference_update( tags )
|
||||
|
||||
|
||||
self._RefreshFileList()
|
||||
|
||||
|
||||
def TagRemoved( self, tag ): self._RefreshFileList()
|
||||
def TagsRemoved( self, tag ):
|
||||
|
||||
self._RefreshFileList()
|
||||
|
||||
|
||||
|
||||
class DialogRegisterService( Dialog ):
|
||||
|
|
|
@ -1656,7 +1656,7 @@ class DialogManageExportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._period = wx.SpinCtrl( self._period_box )
|
||||
|
||||
self._period.SetRange( 3, 180 )
|
||||
self._period.SetRange( 3, 60 * 24 * 30 )
|
||||
|
||||
self._period.SetValue( period / 60 )
|
||||
|
||||
|
@ -1729,17 +1729,6 @@ If you select synchronise, be careful!'''
|
|||
|
||||
wx.CallAfter( self._ok.SetFocus )
|
||||
|
||||
HydrusGlobals.client_controller.sub( self, 'AddPredicate', 'add_predicate' )
|
||||
HydrusGlobals.client_controller.sub( self, 'RemovePredicate', 'remove_predicate' )
|
||||
|
||||
|
||||
def AddPredicate( self, page_key, predicate ):
|
||||
|
||||
if page_key == self._page_key:
|
||||
|
||||
if self._predicates_box.HasPredicate( predicate ): self._predicates_box.RemovePredicate( predicate )
|
||||
else: self._predicates_box.AddPredicate( predicate )
|
||||
|
||||
|
||||
|
||||
def EventOK( self, event ):
|
||||
|
@ -1778,17 +1767,6 @@ If you select synchronise, be careful!'''
|
|||
return self._export_folder
|
||||
|
||||
|
||||
def RemovePredicate( self, page_key, predicate ):
|
||||
|
||||
if page_key == self._page_key:
|
||||
|
||||
if self._predicates_box.HasPredicate( predicate ):
|
||||
|
||||
self._predicates_box.RemovePredicate( predicate )
|
||||
|
||||
|
||||
|
||||
|
||||
class DialogManageImageboards( ClientGUIDialogs.Dialog ):
|
||||
|
||||
def __init__( self, parent ):
|
||||
|
@ -2513,7 +2491,7 @@ class DialogManageImportFolders( ClientGUIDialogs.Dialog ):
|
|||
|
||||
ClientGUIDialogs.Dialog.__init__( self, parent, 'manage import folders' )
|
||||
|
||||
self._import_folders = ClientGUICommon.SaneListCtrl( self, 120, [ ( 'name', 120 ), ( 'path', -1 ), ( 'check period', 120 ), ( 'local tag', 120 ) ], delete_key_callback = self.Delete )
|
||||
self._import_folders = ClientGUICommon.SaneListCtrl( self, 120, [ ( 'name', 120 ), ( 'path', -1 ), ( 'check period', 120 ) ], delete_key_callback = self.Delete )
|
||||
|
||||
self._add_button = wx.Button( self, label = 'add' )
|
||||
self._add_button.Bind( wx.EVT_BUTTON, self.EventAdd )
|
||||
|
@ -2539,11 +2517,11 @@ class DialogManageImportFolders( ClientGUIDialogs.Dialog ):
|
|||
|
||||
for import_folder in import_folders:
|
||||
|
||||
( name, path, check_period, tag ) = import_folder.ToListBoxTuple()
|
||||
( name, path, check_period ) = import_folder.ToListBoxTuple()
|
||||
|
||||
( pretty_check_period, pretty_tag ) = self._GetPrettyVariables( check_period, tag )
|
||||
pretty_check_period = self._GetPrettyVariables( check_period )
|
||||
|
||||
self._import_folders.Append( ( name, path, pretty_check_period, pretty_tag ), ( name, path, check_period, tag ) )
|
||||
self._import_folders.Append( ( name, path, pretty_check_period ), ( name, path, check_period ) )
|
||||
|
||||
self._names_to_import_folders[ name ] = import_folder
|
||||
|
||||
|
@ -2596,11 +2574,11 @@ class DialogManageImportFolders( ClientGUIDialogs.Dialog ):
|
|||
|
||||
import_folder = dlg.GetInfo()
|
||||
|
||||
( name, path, check_period, tag ) = import_folder.ToListBoxTuple()
|
||||
( name, path, check_period ) = import_folder.ToListBoxTuple()
|
||||
|
||||
( pretty_check_period, pretty_tag ) = self._GetPrettyVariables( check_period, tag )
|
||||
pretty_check_period = self._GetPrettyVariables( check_period )
|
||||
|
||||
self._import_folders.Append( ( name, path, pretty_check_period, pretty_tag ), ( name, path, check_period, tag ) )
|
||||
self._import_folders.Append( ( name, path, pretty_check_period ), ( name, path, check_period ) )
|
||||
|
||||
self._names_to_import_folders[ name ] = import_folder
|
||||
|
||||
|
@ -2608,14 +2586,11 @@ class DialogManageImportFolders( ClientGUIDialogs.Dialog ):
|
|||
|
||||
|
||||
|
||||
def _GetPrettyVariables( self, check_period, tag ):
|
||||
def _GetPrettyVariables( self, check_period ):
|
||||
|
||||
pretty_check_period = HydrusData.ToString( check_period / 60 ) + ' minutes'
|
||||
|
||||
if tag == None: pretty_tag = ''
|
||||
else: pretty_tag = tag
|
||||
|
||||
return ( pretty_check_period, pretty_tag )
|
||||
return pretty_check_period
|
||||
|
||||
|
||||
def Delete( self ):
|
||||
|
@ -2629,7 +2604,7 @@ class DialogManageImportFolders( ClientGUIDialogs.Dialog ):
|
|||
|
||||
existing_names = set()
|
||||
|
||||
for ( name, path, check_period, tag ) in client_data:
|
||||
for ( name, path, check_period ) in client_data:
|
||||
|
||||
existing_names.add( name )
|
||||
|
||||
|
@ -2669,7 +2644,7 @@ class DialogManageImportFolders( ClientGUIDialogs.Dialog ):
|
|||
|
||||
for index in indices:
|
||||
|
||||
( name, path, check_period, tag ) = self._import_folders.GetClientData( index )
|
||||
( name, path, check_period ) = self._import_folders.GetClientData( index )
|
||||
|
||||
import_folder = self._names_to_import_folders[ name ]
|
||||
|
||||
|
@ -2679,11 +2654,11 @@ class DialogManageImportFolders( ClientGUIDialogs.Dialog ):
|
|||
|
||||
import_folder = dlg.GetInfo()
|
||||
|
||||
( name, path, check_period, tag ) = import_folder.ToListBoxTuple()
|
||||
( name, path, check_period ) = import_folder.ToListBoxTuple()
|
||||
|
||||
( pretty_check_period, pretty_tag ) = self._GetPrettyVariables( check_period, tag )
|
||||
pretty_check_period = self._GetPrettyVariables( check_period )
|
||||
|
||||
self._import_folders.UpdateRow( index, ( name, path, pretty_check_period, pretty_tag ), ( name, path, check_period, tag ) )
|
||||
self._import_folders.UpdateRow( index, ( name, path, pretty_check_period ), ( name, path, check_period ) )
|
||||
|
||||
self._names_to_import_folders[ name ] = import_folder
|
||||
|
||||
|
@ -2697,7 +2672,7 @@ class DialogManageImportFolders( ClientGUIDialogs.Dialog ):
|
|||
|
||||
names_to_save = set()
|
||||
|
||||
for ( name, path, check_period, tag ) in client_data:
|
||||
for ( name, path, check_period ) in client_data:
|
||||
|
||||
names_to_save.add( name )
|
||||
|
||||
|
@ -2729,7 +2704,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._import_folder = import_folder
|
||||
|
||||
( name, path, mimes, import_file_options, actions, action_locations, period, open_popup, tag, paused ) = self._import_folder.ToTuple()
|
||||
( name, path, mimes, import_file_options, import_tag_options, actions, action_locations, period, open_popup, paused ) = self._import_folder.ToTuple()
|
||||
|
||||
self._folder_box = ClientGUICommon.StaticBox( self, 'folder options' )
|
||||
|
||||
|
@ -2739,10 +2714,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._open_popup = wx.CheckBox( self._folder_box )
|
||||
|
||||
self._tag = wx.TextCtrl( self._folder_box )
|
||||
self._tag.SetToolTipString( 'add this tag on the local tag service to anything imported from the folder' )
|
||||
|
||||
self._period = wx.SpinCtrl( self._folder_box, min = 3, max = 1440 )
|
||||
self._period = wx.SpinCtrl( self._folder_box, min = 3, max = 60 * 24 * 30 )
|
||||
|
||||
self._paused = wx.CheckBox( self._folder_box )
|
||||
|
||||
|
@ -2783,6 +2755,8 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
self._location_failed = wx.DirPickerCtrl( self._file_box, style = wx.DIRP_USE_TEXTCTRL )
|
||||
|
||||
self._import_file_options = ClientGUIOptionsPanels.OptionsPanelImportFiles( self._file_box )
|
||||
self._import_tag_options = ClientGUIOptionsPanels.OptionsPanelTags( self._file_box )
|
||||
self._import_tag_options.SetNamespaces( [] )
|
||||
|
||||
#
|
||||
|
||||
|
@ -2799,11 +2773,6 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
self._path.SetPath( path )
|
||||
self._open_popup.SetValue( open_popup )
|
||||
|
||||
if tag is not None:
|
||||
|
||||
self._tag.SetValue( tag )
|
||||
|
||||
|
||||
self._period.SetValue( period / 60 )
|
||||
self._paused.SetValue( paused )
|
||||
|
||||
|
@ -2834,6 +2803,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
|
||||
|
||||
self._import_file_options.SetOptions( import_file_options )
|
||||
self._import_tag_options.SetOptions( import_tag_options )
|
||||
|
||||
#
|
||||
|
||||
|
@ -2853,9 +2823,6 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
gridbox.AddF( wx.StaticText( self._folder_box, label = 'currently paused: '), CC.FLAGS_MIXED )
|
||||
gridbox.AddF( self._paused, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._folder_box, label = 'local tag to add to all imported files: '), CC.FLAGS_MIXED )
|
||||
gridbox.AddF( self._tag, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._folder_box, label = 'open a popup if new files imported: '), CC.FLAGS_MIXED )
|
||||
gridbox.AddF( self._open_popup, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
|
@ -2892,6 +2859,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._file_box.AddF( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
self._file_box.AddF( self._import_file_options, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
self._file_box.AddF( self._import_tag_options, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
#
|
||||
|
||||
|
@ -3016,6 +2984,7 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
path = self._path.GetPath()
|
||||
mimes = self._mimes.GetInfo()
|
||||
import_file_options = self._import_file_options.GetOptions()
|
||||
import_tag_options = self._import_tag_options.GetOptions()
|
||||
|
||||
actions = {}
|
||||
action_locations = {}
|
||||
|
@ -3047,16 +3016,9 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
|||
period = self._period.GetValue() * 60
|
||||
open_popup = self._open_popup.GetValue()
|
||||
|
||||
tag = self._tag.GetValue()
|
||||
|
||||
if tag == '':
|
||||
|
||||
tag = None
|
||||
|
||||
|
||||
paused = self._paused.GetValue()
|
||||
|
||||
self._import_folder.SetTuple( name, path, mimes, import_file_options, actions, action_locations, period, open_popup, tag, paused )
|
||||
self._import_folder.SetTuple( name, path, mimes, import_file_options, import_tag_options, actions, action_locations, period, open_popup, paused )
|
||||
|
||||
return self._import_folder
|
||||
|
||||
|
@ -3205,11 +3167,9 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def EventEditNamespaceColour( self, event ):
|
||||
|
||||
result = self._namespace_colours.GetSelectedNamespaceColour()
|
||||
results = self._namespace_colours.GetSelectedNamespaceColours()
|
||||
|
||||
if result is not None:
|
||||
|
||||
( namespace, colour ) = result
|
||||
for ( namespace, colour ) in results:
|
||||
|
||||
colour_data = wx.ColourData()
|
||||
|
||||
|
@ -3495,6 +3455,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
self._processing_panel = ClientGUICommon.StaticBox( self, 'processing' )
|
||||
|
||||
self._idle_period = wx.SpinCtrl( self._idle_panel, min = 0, max = 1000 )
|
||||
self._idle_mouse_period = wx.SpinCtrl( self._idle_panel, min = 0, max = 1000 )
|
||||
self._idle_cpu_max = wx.SpinCtrl( self._idle_panel, min = 0, max = 100 )
|
||||
|
||||
self._idle_shutdown = ClientGUICommon.BetterChoice( self._idle_panel )
|
||||
|
@ -3514,6 +3475,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
#
|
||||
|
||||
self._idle_period.SetValue( HC.options[ 'idle_period' ] / 60 )
|
||||
self._idle_mouse_period.SetValue( HC.options[ 'idle_mouse_period' ] / 60 )
|
||||
self._idle_cpu_max.SetValue( HC.options[ 'idle_cpu_max' ] )
|
||||
self._idle_shutdown.SelectClientData( HC.options[ 'idle_shutdown' ] )
|
||||
self._idle_shutdown_max_minutes.SetValue( HC.options[ 'idle_shutdown_max_minutes' ] )
|
||||
|
@ -3528,9 +3490,12 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
|
||||
gridbox.AddGrowableCol( 1, 1 )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._idle_panel, label = 'Minutes of inactivity until client is considered idle (0 for never): ' ), CC.FLAGS_MIXED )
|
||||
gridbox.AddF( wx.StaticText( self._idle_panel, label = 'Minutes of general client inactivity until client is considered idle (0 for never): ' ), CC.FLAGS_MIXED )
|
||||
gridbox.AddF( self._idle_period, CC.FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._idle_panel, label = 'Minutes of unmoving mouse until client is considered idle (0 for never): ' ), CC.FLAGS_MIXED )
|
||||
gridbox.AddF( self._idle_mouse_period, CC.FLAGS_MIXED )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self._idle_panel, label = 'Do not start a job if any CPU core has more than this percent usage: ' ), CC.FLAGS_MIXED )
|
||||
gridbox.AddF( self._idle_cpu_max, CC.FLAGS_MIXED )
|
||||
|
||||
|
@ -3585,6 +3550,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
def UpdateOptions( self ):
|
||||
|
||||
HC.options[ 'idle_period' ] = 60 * self._idle_period.GetValue()
|
||||
HC.options[ 'idle_mouse_period' ] = 60 * self._idle_mouse_period.GetValue()
|
||||
HC.options[ 'idle_cpu_max' ] = self._idle_cpu_max.GetValue()
|
||||
HC.options[ 'idle_shutdown' ] = self._idle_shutdown.GetChoice()
|
||||
HC.options[ 'idle_shutdown_max_minutes' ] = self._idle_shutdown_max_minutes.GetValue()
|
||||
|
@ -4533,7 +4499,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
|||
gridbox.AddF( wx.StaticText( self, label = 'MB memory reserved for preview cache: ' ), CC.FLAGS_MIXED )
|
||||
gridbox.AddF( previews_sizer, CC.FLAGS_NONE )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self, label = 'MB memory reserved for fullscreen cache: ' ), CC.FLAGS_MIXED )
|
||||
gridbox.AddF( wx.StaticText( self, label = 'MB memory reserved for media viewer cache: ' ), CC.FLAGS_MIXED )
|
||||
gridbox.AddF( fullscreens_sizer, CC.FLAGS_NONE )
|
||||
|
||||
gridbox.AddF( wx.StaticText( self, label = 'Autocomplete character threshold: ' ), CC.FLAGS_MIXED )
|
||||
|
@ -7207,48 +7173,37 @@ class DialogManageTagCensorship( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def __init__( self, parent, service_key ):
|
||||
|
||||
def InitialiseControls():
|
||||
|
||||
choice_pairs = [ ( 'blacklist', True ), ( 'whitelist', False ) ]
|
||||
|
||||
self._blacklist = ClientGUICommon.RadioBox( self, 'type', choice_pairs )
|
||||
|
||||
self._tags = ClientGUICommon.ListBoxTagsCensorship( self )
|
||||
|
||||
self._tag_input = wx.TextCtrl( self, style = wx.TE_PROCESS_ENTER )
|
||||
self._tag_input.Bind( wx.EVT_KEY_DOWN, self.EventKeyDownTag )
|
||||
|
||||
|
||||
def PopulateControls():
|
||||
|
||||
( blacklist, tags ) = HydrusGlobals.client_controller.Read( 'tag_censorship', service_key )
|
||||
|
||||
if blacklist: self._blacklist.SetSelection( 0 )
|
||||
else: self._blacklist.SetSelection( 1 )
|
||||
|
||||
for tag in tags: self._tags.AddTag( tag )
|
||||
|
||||
|
||||
def ArrangeControls():
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
vbox.AddF( self._blacklist, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._tags, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
vbox.AddF( self._tag_input, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
self._service_key = service_key
|
||||
|
||||
InitialiseControls()
|
||||
choice_pairs = [ ( 'blacklist', True ), ( 'whitelist', False ) ]
|
||||
|
||||
PopulateControls()
|
||||
self._blacklist = ClientGUICommon.RadioBox( self, 'type', choice_pairs )
|
||||
|
||||
ArrangeControls()
|
||||
self._tags = ClientGUICommon.ListBoxTagsCensorship( self )
|
||||
|
||||
self._tag_input = wx.TextCtrl( self, style = wx.TE_PROCESS_ENTER )
|
||||
self._tag_input.Bind( wx.EVT_KEY_DOWN, self.EventKeyDownTag )
|
||||
|
||||
#
|
||||
|
||||
( blacklist, tags ) = HydrusGlobals.client_controller.Read( 'tag_censorship', service_key )
|
||||
|
||||
if blacklist: self._blacklist.SetSelection( 0 )
|
||||
else: self._blacklist.SetSelection( 1 )
|
||||
|
||||
self._tags.AddTags( tags )
|
||||
|
||||
#
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
vbox.AddF( self._blacklist, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( self._tags, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
vbox.AddF( self._tag_input, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
|
||||
def EventKeyDownTag( self, event ):
|
||||
|
@ -7257,7 +7212,7 @@ class DialogManageTagCensorship( ClientGUIDialogs.Dialog ):
|
|||
|
||||
tag = self._tag_input.GetValue()
|
||||
|
||||
self._tags.AddTag( tag )
|
||||
self._tags.EnterTags( { tag } )
|
||||
|
||||
self._tag_input.SetValue( '' )
|
||||
|
||||
|
@ -7413,7 +7368,7 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
|
||||
class _Panel( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, service_key, tag = None ):
|
||||
def __init__( self, parent, service_key, tags = None ):
|
||||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
|
@ -7439,13 +7394,13 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
self._tag_parents.Bind( wx.EVT_LIST_ITEM_SELECTED, self.EventItemSelected )
|
||||
self._tag_parents.Bind( wx.EVT_LIST_ITEM_DESELECTED, self.EventItemSelected )
|
||||
|
||||
removed_callable = lambda tag: 1
|
||||
self._children = ClientGUICommon.ListBoxTagsStrings( self )
|
||||
self._parents = ClientGUICommon.ListBoxTagsStrings( self )
|
||||
|
||||
self._children = ClientGUICommon.ListBoxTagsStrings( self, removed_callable )
|
||||
self._parents = ClientGUICommon.ListBoxTagsStrings( self, removed_callable )
|
||||
expand_parents = True
|
||||
|
||||
self._child_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.AddChild, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
self._parent_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.AddParent, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
self._child_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.EnterChildren, expand_parents, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
self._parent_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.EnterParents, expand_parents, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
|
||||
self._add = wx.Button( self, label = 'add' )
|
||||
self._add.Bind( wx.EVT_BUTTON, self.EventAddButton )
|
||||
|
@ -7475,7 +7430,10 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._tag_parents.SortListItems( 2 )
|
||||
|
||||
if tag is not None: self.AddChild( tag )
|
||||
if tags is not None:
|
||||
|
||||
self.EnterChildren( tags )
|
||||
|
||||
|
||||
#
|
||||
|
||||
|
@ -7737,29 +7695,25 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
else: self._add.Enable()
|
||||
|
||||
|
||||
def AddChild( self, tag, parents = None ):
|
||||
def EnterChildren( self, tags, parents = None ):
|
||||
|
||||
if parents is None: parents = []
|
||||
|
||||
if tag is not None:
|
||||
if len( tags ) > 0:
|
||||
|
||||
if tag in self._parents.GetTags(): self._parents.AddTag( tag )
|
||||
self._parents.RemoveTags( tags )
|
||||
|
||||
self._children.AddTag( tag )
|
||||
self._children.AddTags( tags )
|
||||
|
||||
self._SetButtonStatus()
|
||||
|
||||
|
||||
|
||||
def AddParent( self, tag, parents = None ):
|
||||
def EnterParents( self, tags, parents = None ):
|
||||
|
||||
if parents is None: parents = []
|
||||
|
||||
if tag is not None:
|
||||
if len( tags ) > 0:
|
||||
|
||||
if tag in self._children.GetTags(): self._children.AddTag( tag )
|
||||
self._children.RemoveTags( tags )
|
||||
|
||||
self._parents.AddTag( tag )
|
||||
self._parents.AddTags( tags )
|
||||
|
||||
self._SetButtonStatus()
|
||||
|
||||
|
@ -7767,15 +7721,23 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def EventActivated( self, event ):
|
||||
|
||||
parents_to_children = collections.defaultdict( set )
|
||||
|
||||
all_selected = self._tag_parents.GetAllSelected()
|
||||
|
||||
if len( all_selected ) > 0:
|
||||
|
||||
selection = all_selected[0]
|
||||
for selection in all_selected:
|
||||
|
||||
( status, child, parent ) = self._tag_parents.GetClientData( selection )
|
||||
|
||||
self._AddPairs( ( child, ), parent )
|
||||
parents_to_children[ parent ].add( child )
|
||||
|
||||
|
||||
if len( parents_to_children ) > 0:
|
||||
|
||||
for ( parent, children ) in parents_to_children.items():
|
||||
|
||||
self._AddPairs( children, parent )
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -7843,73 +7805,64 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def __init__( self, parent, tag = None ):
|
||||
|
||||
def InitialiseControls():
|
||||
|
||||
self._tag_repositories = ClientGUICommon.ListBook( self )
|
||||
self._tag_repositories.Bind( wx.EVT_NOTEBOOK_PAGE_CHANGED, self.EventServiceChanged )
|
||||
|
||||
self._ok = wx.Button( self, id = wx.ID_OK, label = 'ok' )
|
||||
self._ok.Bind( wx.EVT_BUTTON, self.EventOK )
|
||||
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
|
||||
|
||||
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'cancel' )
|
||||
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
|
||||
|
||||
|
||||
def PopulateControls():
|
||||
|
||||
page = self._Panel( self._tag_repositories, CC.LOCAL_TAG_SERVICE_KEY, tag )
|
||||
|
||||
name = CC.LOCAL_TAG_SERVICE_KEY
|
||||
|
||||
self._tag_repositories.AddPage( name, page )
|
||||
|
||||
services = HydrusGlobals.client_controller.GetServicesManager().GetServices( ( HC.TAG_REPOSITORY, ) )
|
||||
|
||||
for service in services:
|
||||
|
||||
account = service.GetInfo( 'account' )
|
||||
|
||||
if account.HasPermission( HC.POST_DATA ) or account.IsUnknownAccount():
|
||||
|
||||
name = service.GetName()
|
||||
service_key = service.GetServiceKey()
|
||||
|
||||
self._tag_repositories.AddPageArgs( name, self._Panel, ( self._tag_repositories, service_key, tag ), {} )
|
||||
|
||||
|
||||
|
||||
default_tag_repository_key = HC.options[ 'default_tag_repository' ]
|
||||
|
||||
service = HydrusGlobals.client_controller.GetServicesManager().GetService( default_tag_repository_key )
|
||||
|
||||
self._tag_repositories.Select( service.GetName() )
|
||||
|
||||
|
||||
def ArrangeControls():
|
||||
|
||||
buttons = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
buttons.AddF( self._ok, CC.FLAGS_SMALL_INDENT )
|
||||
buttons.AddF( self._cancel, CC.FLAGS_SMALL_INDENT )
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
vbox.AddF( self._tag_repositories, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
vbox.AddF( buttons, CC.FLAGS_BUTTON_SIZER )
|
||||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
self.SetInitialSize( ( 550, 780 ) )
|
||||
|
||||
|
||||
ClientGUIDialogs.Dialog.__init__( self, parent, 'tag siblings' )
|
||||
|
||||
InitialiseControls()
|
||||
self._tag_repositories = ClientGUICommon.ListBook( self )
|
||||
self._tag_repositories.Bind( wx.EVT_NOTEBOOK_PAGE_CHANGED, self.EventServiceChanged )
|
||||
|
||||
PopulateControls()
|
||||
self._ok = wx.Button( self, id = wx.ID_OK, label = 'ok' )
|
||||
self._ok.Bind( wx.EVT_BUTTON, self.EventOK )
|
||||
self._ok.SetForegroundColour( ( 0, 128, 0 ) )
|
||||
|
||||
ArrangeControls()
|
||||
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'cancel' )
|
||||
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
|
||||
|
||||
#
|
||||
|
||||
page = self._Panel( self._tag_repositories, CC.LOCAL_TAG_SERVICE_KEY, tag )
|
||||
|
||||
name = CC.LOCAL_TAG_SERVICE_KEY
|
||||
|
||||
self._tag_repositories.AddPage( name, page )
|
||||
|
||||
services = HydrusGlobals.client_controller.GetServicesManager().GetServices( ( HC.TAG_REPOSITORY, ) )
|
||||
|
||||
for service in services:
|
||||
|
||||
account = service.GetInfo( 'account' )
|
||||
|
||||
if account.HasPermission( HC.POST_DATA ) or account.IsUnknownAccount():
|
||||
|
||||
name = service.GetName()
|
||||
service_key = service.GetServiceKey()
|
||||
|
||||
self._tag_repositories.AddPageArgs( name, self._Panel, ( self._tag_repositories, service_key, tag ), {} )
|
||||
|
||||
|
||||
|
||||
default_tag_repository_key = HC.options[ 'default_tag_repository' ]
|
||||
|
||||
service = HydrusGlobals.client_controller.GetServicesManager().GetService( default_tag_repository_key )
|
||||
|
||||
self._tag_repositories.Select( service.GetName() )
|
||||
|
||||
#
|
||||
|
||||
buttons = wx.BoxSizer( wx.HORIZONTAL )
|
||||
|
||||
buttons.AddF( self._ok, CC.FLAGS_SMALL_INDENT )
|
||||
buttons.AddF( self._cancel, CC.FLAGS_SMALL_INDENT )
|
||||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
vbox.AddF( self._tag_repositories, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
vbox.AddF( buttons, CC.FLAGS_BUTTON_SIZER )
|
||||
|
||||
self.SetSizer( vbox )
|
||||
|
||||
self.SetInitialSize( ( 550, 780 ) )
|
||||
|
||||
#
|
||||
|
||||
interested_actions = [ 'set_search_focus' ]
|
||||
|
||||
|
@ -7969,7 +7922,7 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
|||
|
||||
class _Panel( wx.Panel ):
|
||||
|
||||
def __init__( self, parent, service_key, tag = None ):
|
||||
def __init__( self, parent, service_key, tags = None ):
|
||||
|
||||
wx.Panel.__init__( self, parent )
|
||||
|
||||
|
@ -7999,11 +7952,13 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
|||
|
||||
removed_callable = lambda tags: 1
|
||||
|
||||
self._old_siblings = ClientGUICommon.ListBoxTagsStrings( self, removed_callable )
|
||||
self._old_siblings = ClientGUICommon.ListBoxTagsStrings( self )
|
||||
self._new_sibling = wx.StaticText( self )
|
||||
|
||||
self._old_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.AddOld, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
self._new_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.SetNew, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
expand_parents = False
|
||||
|
||||
self._old_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.EnterOlds, expand_parents, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
self._new_input = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.SetNew, expand_parents, CC.LOCAL_FILE_SERVICE_KEY, service_key )
|
||||
|
||||
self._add = wx.Button( self, label = 'add' )
|
||||
self._add.Bind( wx.EVT_BUTTON, self.EventAddButton )
|
||||
|
@ -8033,7 +7988,10 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._tag_siblings.SortListItems( 2 )
|
||||
|
||||
if tag is not None: self.AddOld( tag )
|
||||
if tags is not None:
|
||||
|
||||
self.EnterOlds( tags )
|
||||
|
||||
|
||||
#
|
||||
|
||||
|
@ -8314,35 +8272,41 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
|||
else: self._add.Enable()
|
||||
|
||||
|
||||
def AddOld( self, old, parents = None ):
|
||||
def EnterOlds( self, olds ):
|
||||
|
||||
if parents is None: parents = []
|
||||
potential_olds = olds
|
||||
|
||||
if old is not None:
|
||||
olds = set()
|
||||
|
||||
for potential_old in potential_olds:
|
||||
|
||||
do_it = True
|
||||
|
||||
current_pairs = self._current_statuses_to_pairs[ HC.CURRENT ].union( self._current_statuses_to_pairs[ HC.PENDING ] )
|
||||
|
||||
current_olds = { current_old for ( current_old, current_new ) in current_pairs }
|
||||
|
||||
# test for ambiguity
|
||||
|
||||
while old in current_olds:
|
||||
while potential_old in current_olds:
|
||||
|
||||
olds_to_news = dict( current_pairs )
|
||||
|
||||
new = olds_to_news[ old ]
|
||||
conflicting_new = olds_to_news[ potential_old ]
|
||||
|
||||
message = 'There already is a relationship set for ' + old + '! It goes to ' + new + '.'
|
||||
message = 'There already is a relationship set for ' + potential_old + '! It goes to ' + conflicting_new + '.'
|
||||
message += os.linesep * 2
|
||||
message += 'You cannot have two siblings for the same original term.'
|
||||
|
||||
with ClientGUIDialogs.DialogYesNo( self, message, title = 'Choose what to do.', yes_label = 'I want to overwrite the existing record', no_label = 'do nothing' ) as dlg:
|
||||
|
||||
if self._service_key != CC.LOCAL_TAG_SERVICE_KEY:
|
||||
if dlg.ShowModal() == wx.ID_YES:
|
||||
|
||||
if dlg.ShowModal() != wx.ID_YES: return
|
||||
self._AddPairs( [ potential_old ], conflicting_new )
|
||||
|
||||
self._AddPairs( [ old ] , new )
|
||||
else:
|
||||
|
||||
do_it = False
|
||||
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
@ -8351,30 +8315,41 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
|||
current_olds = { current_old for ( current_old, current_new ) in current_pairs }
|
||||
|
||||
|
||||
if do_it:
|
||||
|
||||
olds.add( potential_old )
|
||||
|
||||
|
||||
|
||||
#
|
||||
if self._current_new in olds:
|
||||
|
||||
self.SetNew( set() )
|
||||
|
||||
|
||||
if old is not None:
|
||||
|
||||
if old == self._current_new: self.SetNew( None )
|
||||
|
||||
self._old_siblings.AddTag( old )
|
||||
|
||||
self._old_siblings.EnterTags( olds )
|
||||
|
||||
self._SetButtonStatus()
|
||||
|
||||
|
||||
def EventActivated( self, event ):
|
||||
|
||||
news_to_olds = collections.defaultdict( set )
|
||||
|
||||
all_selected = self._tag_siblings.GetAllSelected()
|
||||
|
||||
if len( all_selected ) > 0:
|
||||
|
||||
selection = all_selected[0]
|
||||
for selection in all_selected:
|
||||
|
||||
( status, old, new ) = self._tag_siblings.GetClientData( selection )
|
||||
|
||||
self._AddPairs( [ old ], new )
|
||||
news_to_olds[ new ].add( old )
|
||||
|
||||
|
||||
if len( news_to_olds ) > 0:
|
||||
|
||||
for ( new, olds ) in news_to_olds.items():
|
||||
|
||||
self._AddPairs( olds, new )
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -8386,8 +8361,8 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._AddPairs( olds, self._current_new )
|
||||
|
||||
self._old_siblings.SetTags( [] )
|
||||
self.SetNew( None )
|
||||
self._old_siblings.SetTags( set() )
|
||||
self.SetNew( set() )
|
||||
|
||||
self._SetButtonStatus()
|
||||
|
||||
|
@ -8435,19 +8410,24 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
|||
return ( self._service_key, content_updates )
|
||||
|
||||
|
||||
def SetNew( self, new, parents = None ):
|
||||
def SetNew( self, new_tags ):
|
||||
|
||||
if parents is None: parents = []
|
||||
|
||||
if new is None: self._new_sibling.SetLabel( '' )
|
||||
if len( new_tags ) == 0:
|
||||
|
||||
self._new_sibling.SetLabel( '' )
|
||||
|
||||
self._current_new = None
|
||||
|
||||
else:
|
||||
|
||||
if new in self._old_siblings.GetTags(): self._old_siblings.AddTag( new )
|
||||
new = list( new_tags )[0]
|
||||
|
||||
self._old_siblings.RemoveTags( { new } )
|
||||
|
||||
self._new_sibling.SetLabel( new )
|
||||
|
||||
|
||||
self._current_new = new
|
||||
self._current_new = new
|
||||
|
||||
|
||||
self._SetButtonStatus()
|
||||
|
||||
|
@ -8788,7 +8768,7 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._tags_box_sorter = ClientGUICommon.StaticBoxSorterForListBoxTags( self, 'tags' )
|
||||
|
||||
self._tags_box = ClientGUICommon.ListBoxTagsSelectionTagsDialog( self._tags_box_sorter, self.AddTag )
|
||||
self._tags_box = ClientGUICommon.ListBoxTagsSelectionTagsDialog( self._tags_box_sorter, self.AddTags )
|
||||
|
||||
self._tags_box_sorter.SetTagsBox( self._tags_box )
|
||||
|
||||
|
@ -8797,7 +8777,9 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
|||
|
||||
self._tags_box_sorter.AddF( self._show_deleted_checkbox, CC.FLAGS_LONE_BUTTON )
|
||||
|
||||
self._add_tag_box = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.AddTag, self._file_service_key, self._tag_service_key )
|
||||
expand_parents = True
|
||||
|
||||
self._add_tag_box = ClientGUICommon.AutoCompleteDropdownTagsWrite( self, self.AddTags, expand_parents, self._file_service_key, self._tag_service_key, null_entry_callable = self.Ok )
|
||||
|
||||
self._modify_mappers = wx.Button( self, label = 'Modify mappers' )
|
||||
self._modify_mappers.Bind( wx.EVT_BUTTON, self.EventModify )
|
||||
|
@ -8972,16 +8954,24 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
|||
self._tags_box.SetTagsByMedia( self._media, force_reload = True )
|
||||
|
||||
|
||||
def AddTag( self, tag, parents = None ):
|
||||
def AddTags( self, tags, parents = None ):
|
||||
|
||||
if parents is None: parents = []
|
||||
if parents is None:
|
||||
|
||||
parents = []
|
||||
|
||||
|
||||
if tag is None: wx.PostEvent( self, wx.CommandEvent( commandType = wx.wxEVT_COMMAND_MENU_SELECTED, winid = ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'ok' ) ) )
|
||||
else:
|
||||
if len( tags ) > 0:
|
||||
|
||||
self._AddTag( tag )
|
||||
for tag in tags:
|
||||
|
||||
self._AddTag( tag )
|
||||
|
||||
|
||||
for parent in parents: self._AddTag( parent, only_add = True )
|
||||
for parent in parents:
|
||||
|
||||
self._AddTag( parent, only_add = True )
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -8998,11 +8988,16 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def EventModify( self, event ):
|
||||
|
||||
tag = self._tags_box.GetSelectedTag()
|
||||
contents = []
|
||||
|
||||
if tag is not None:
|
||||
tags = self._tags_box.GetSelectedTags()
|
||||
|
||||
for tag in tags:
|
||||
|
||||
contents = [ HydrusData.Content( HC.CONTENT_TYPE_MAPPING, ( tag, hash ) ) for hash in self._hashes ]
|
||||
contents.extend( [ HydrusData.Content( HC.CONTENT_TYPE_MAPPING, ( tag, hash ) ) for hash in self._hashes ] )
|
||||
|
||||
|
||||
if len( contents ) > 0:
|
||||
|
||||
subject_identifiers = [ HydrusData.AccountIdentifier( content = content ) for content in contents ]
|
||||
|
||||
|
@ -9028,7 +9023,10 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
|||
|
||||
tags = HydrusTags.CleanTags( tags )
|
||||
|
||||
for tag in tags: self._AddTag( tag, only_add = True )
|
||||
for tag in tags:
|
||||
|
||||
self._AddTag( tag, only_add = True )
|
||||
|
||||
|
||||
except: wx.MessageBox( 'I could not understand what was in the clipboard' )
|
||||
|
||||
|
@ -9091,6 +9089,11 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
|||
|
||||
def HasChanges( self ): return len( self._content_updates ) > 0
|
||||
|
||||
def Ok( self ):
|
||||
|
||||
wx.PostEvent( self, wx.CommandEvent( commandType = wx.wxEVT_COMMAND_MENU_SELECTED, winid = ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetTemporaryId( 'ok' ) ) )
|
||||
|
||||
|
||||
def SetMedia( self, media ):
|
||||
|
||||
self._content_updates = []
|
||||
|
|
|
@ -644,7 +644,7 @@ class FullscreenHoverFrameTags( FullscreenHoverFrame ):
|
|||
|
||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||
|
||||
self._tags = ClientGUICommon.ListBoxTags( self )
|
||||
self._tags = ClientGUICommon.ListBoxTagsSelectionHoverFrame( self, self._canvas_key )
|
||||
|
||||
vbox.AddF( self._tags, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
||||
|
||||
|
@ -675,22 +675,10 @@ class FullscreenHoverFrameTags( FullscreenHoverFrame ):
|
|||
|
||||
def _ResetTags( self ):
|
||||
|
||||
if self._current_media is None: tags_i_want_to_display = []
|
||||
else:
|
||||
if self._current_media is not None:
|
||||
|
||||
tags_manager = self._current_media.GetTagsManager()
|
||||
self._tags.SetTagsByMedia( [ self._current_media ], force_reload = True )
|
||||
|
||||
siblings_manager = HydrusGlobals.client_controller.GetManager( 'tag_siblings' )
|
||||
|
||||
current = siblings_manager.CollapseTags( tags_manager.GetCurrent() )
|
||||
pending = siblings_manager.CollapseTags( tags_manager.GetPending() )
|
||||
|
||||
tags_i_want_to_display = list( current.union( pending ) )
|
||||
|
||||
tags_i_want_to_display.sort()
|
||||
|
||||
|
||||
self._tags.SetTexts( tags_i_want_to_display )
|
||||
|
||||
|
||||
def ProcessContentUpdates( self, service_keys_to_content_updates ):
|
||||
|
@ -727,13 +715,4 @@ class FullscreenHoverFrameTags( FullscreenHoverFrame ):
|
|||
self._ResetTags()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -2542,7 +2542,6 @@ class ManagementPanelQuery( ManagementPanel ):
|
|||
if len( initial_predicates ) > 0 and not file_search_context.IsComplete(): wx.CallAfter( self._DoQuery )
|
||||
|
||||
HydrusGlobals.client_controller.sub( self, 'AddMediaResultsFromQuery', 'add_media_results_from_query' )
|
||||
HydrusGlobals.client_controller.sub( self, 'AddPredicate', 'add_predicate' )
|
||||
HydrusGlobals.client_controller.sub( self, 'ChangeFileRepositoryPubsub', 'change_file_repository' )
|
||||
HydrusGlobals.client_controller.sub( self, 'ChangeTagRepositoryPubsub', 'change_tag_repository' )
|
||||
HydrusGlobals.client_controller.sub( self, 'IncludeCurrent', 'notify_include_current' )
|
||||
|
@ -2550,7 +2549,6 @@ class ManagementPanelQuery( ManagementPanel ):
|
|||
HydrusGlobals.client_controller.sub( self, 'SearchImmediately', 'notify_search_immediately' )
|
||||
HydrusGlobals.client_controller.sub( self, 'ShowQuery', 'file_query_done' )
|
||||
HydrusGlobals.client_controller.sub( self, 'RefreshQuery', 'refresh_query' )
|
||||
HydrusGlobals.client_controller.sub( self, 'RemovePredicate', 'remove_predicate' )
|
||||
|
||||
|
||||
def _DoQuery( self ):
|
||||
|
@ -2599,39 +2597,6 @@ class ManagementPanelQuery( ManagementPanel ):
|
|||
if query_key == self._query_key: HydrusGlobals.client_controller.pub( 'add_media_results', self._page_key, media_results, append = False )
|
||||
|
||||
|
||||
def AddPredicate( self, page_key, predicate ):
|
||||
|
||||
if self._controller.GetVariable( 'search_enabled' ) and page_key == self._page_key:
|
||||
|
||||
if predicate is not None:
|
||||
|
||||
( predicate_type, value, inclusive ) = predicate.GetInfo()
|
||||
|
||||
if predicate_type in [ HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, HC.PREDICATE_TYPE_SYSTEM_LIMIT, HC.PREDICATE_TYPE_SYSTEM_SIZE, HC.PREDICATE_TYPE_SYSTEM_DIMENSIONS, HC.PREDICATE_TYPE_SYSTEM_AGE, HC.PREDICATE_TYPE_SYSTEM_HASH, HC.PREDICATE_TYPE_SYSTEM_DURATION, HC.PREDICATE_TYPE_SYSTEM_NUM_WORDS, HC.PREDICATE_TYPE_SYSTEM_MIME, HC.PREDICATE_TYPE_SYSTEM_RATING, HC.PREDICATE_TYPE_SYSTEM_SIMILAR_TO, HC.PREDICATE_TYPE_SYSTEM_FILE_SERVICE ]:
|
||||
|
||||
with ClientGUIDialogs.DialogInputFileSystemPredicates( self, predicate_type ) as dlg:
|
||||
|
||||
if dlg.ShowModal() == wx.ID_OK: predicates = dlg.GetPredicates()
|
||||
else: return
|
||||
|
||||
|
||||
elif predicate_type == HC.PREDICATE_TYPE_SYSTEM_UNTAGGED: predicates = ( ClientData.Predicate( HC.PREDICATE_TYPE_SYSTEM_NUM_TAGS, ( '=', 0 ) ), )
|
||||
else:
|
||||
|
||||
predicates = ( predicate, )
|
||||
|
||||
|
||||
for predicate in predicates:
|
||||
|
||||
if self._current_predicates_box.HasPredicate( predicate ): self._current_predicates_box.RemovePredicate( predicate )
|
||||
else: self._current_predicates_box.AddPredicate( predicate )
|
||||
|
||||
|
||||
|
||||
self._DoQuery()
|
||||
|
||||
|
||||
|
||||
def ChangeFileRepositoryPubsub( self, page_key, service_key ):
|
||||
|
||||
if page_key == self._page_key:
|
||||
|
@ -2690,19 +2655,6 @@ class ManagementPanelQuery( ManagementPanel ):
|
|||
if page_key == self._page_key: self._DoQuery()
|
||||
|
||||
|
||||
def RemovePredicate( self, page_key, predicate ):
|
||||
|
||||
if page_key == self._page_key:
|
||||
|
||||
if self._current_predicates_box.HasPredicate( predicate ):
|
||||
|
||||
self._current_predicates_box.RemovePredicate( predicate )
|
||||
|
||||
self._DoQuery()
|
||||
|
||||
|
||||
|
||||
|
||||
def SearchImmediately( self, page_key, value ):
|
||||
|
||||
if page_key == self._page_key:
|
||||
|
|
|
@ -453,12 +453,12 @@ class OptionsPanelTags( OptionsPanel ):
|
|||
|
||||
def SetNamespaces( self, namespaces ):
|
||||
|
||||
self._vbox.Clear( True )
|
||||
|
||||
self._service_keys_to_checkbox_info = {}
|
||||
self._service_keys_to_explicit_button_info = {}
|
||||
self._button_ids_to_service_keys = {}
|
||||
|
||||
self._vbox.Clear( True )
|
||||
|
||||
services = HydrusGlobals.client_controller.GetServicesManager().GetServices( ( HC.TAG_REPOSITORY, HC.LOCAL_TAG ) )
|
||||
|
||||
button_id = 1
|
||||
|
@ -505,12 +505,12 @@ class OptionsPanelTags( OptionsPanel ):
|
|||
|
||||
button_id += 1
|
||||
|
||||
vbox.AddF( explicit_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
vbox.AddF( explicit_button, CC.FLAGS_MIXED )
|
||||
|
||||
outer_gridbox.AddF( vbox, CC.FLAGS_MIXED )
|
||||
outer_gridbox.AddF( vbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
||||
|
||||
|
||||
self._vbox.AddF( outer_gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
self._vbox.AddF( outer_gridbox, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ class GalleryImport( HydrusSerialisable.SerialisableBase ):
|
|||
HydrusGlobals.client_controller.pub( 'add_media_results', page_key, ( media_result, ) )
|
||||
|
||||
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
|
||||
error_text = traceback.format_exc()
|
||||
|
||||
|
@ -353,13 +353,22 @@ class GalleryImport( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
except Exception as e:
|
||||
|
||||
traceback.print_exc()
|
||||
if isinstance( e, HydrusExceptions.NotFoundException ):
|
||||
|
||||
text = 'Gallery 404'
|
||||
|
||||
else:
|
||||
|
||||
text = str( e )
|
||||
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
with self._lock:
|
||||
|
||||
self._current_gallery_stream_identifier = None
|
||||
|
||||
self._SetGalleryStatus( page_key, str( e ) )
|
||||
self._SetGalleryStatus( page_key, text )
|
||||
|
||||
|
||||
time.sleep( 5 )
|
||||
|
@ -774,9 +783,9 @@ HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIAL
|
|||
class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
||||
|
||||
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FOLDER
|
||||
SERIALISABLE_VERSION = 1
|
||||
SERIALISABLE_VERSION = 2
|
||||
|
||||
def __init__( self, name, path = '', import_file_options = None, mimes = None, actions = None, action_locations = None, period = 3600, open_popup = True, tag = None ):
|
||||
def __init__( self, name, path = '', import_file_options = None, import_tag_options = None, mimes = None, actions = None, action_locations = None, period = 3600, open_popup = True ):
|
||||
|
||||
if mimes is None:
|
||||
|
||||
|
@ -788,6 +797,13 @@ class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
import_file_options = ClientDefaults.GetDefaultImportFileOptions()
|
||||
|
||||
|
||||
if import_tag_options is None:
|
||||
|
||||
new_options = HydrusGlobals.client_controller.GetNewOptions()
|
||||
|
||||
import_tag_options = new_options.GetDefaultImportTagOptions( ClientDownloading.GalleryIdentifier( HC.SITE_TYPE_DEFAULT ) )
|
||||
|
||||
|
||||
if actions is None:
|
||||
|
||||
actions = {}
|
||||
|
@ -808,11 +824,11 @@ class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
self._path = path
|
||||
self._mimes = mimes
|
||||
self._import_file_options = import_file_options
|
||||
self._import_tag_options = import_tag_options
|
||||
self._actions = actions
|
||||
self._action_locations = action_locations
|
||||
self._period = period
|
||||
self._open_popup = open_popup
|
||||
self._tag = tag
|
||||
|
||||
self._path_cache = SeedCache()
|
||||
self._last_checked = 0
|
||||
|
@ -914,26 +930,51 @@ class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
def _GetSerialisableInfo( self ):
|
||||
|
||||
serialisable_import_file_options = self._import_file_options.GetSerialisableTuple()
|
||||
serialisable_import_tag_options = self._import_tag_options.GetSerialisableTuple()
|
||||
serialisable_path_cache = self._path_cache.GetSerialisableTuple()
|
||||
|
||||
# json turns int dict keys to strings
|
||||
action_pairs = self._actions.items()
|
||||
action_location_pairs = self._action_locations.items()
|
||||
|
||||
return ( self._path, self._mimes, serialisable_import_file_options, action_pairs, action_location_pairs, self._period, self._open_popup, self._tag, serialisable_path_cache, self._last_checked, self._paused )
|
||||
return ( self._path, self._mimes, serialisable_import_file_options, serialisable_import_tag_options, action_pairs, action_location_pairs, self._period, self._open_popup, serialisable_path_cache, self._last_checked, self._paused )
|
||||
|
||||
|
||||
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
|
||||
|
||||
( self._path, self._mimes, serialisable_import_file_options, action_pairs, action_location_pairs, self._period, self._open_popup, self._tag, serialisable_path_cache, self._last_checked, self._paused ) = serialisable_info
|
||||
( self._path, self._mimes, serialisable_import_file_options, serialisable_import_tag_options, action_pairs, action_location_pairs, self._period, self._open_popup, serialisable_path_cache, self._last_checked, self._paused ) = serialisable_info
|
||||
|
||||
self._actions = dict( action_pairs )
|
||||
self._action_locations = dict( action_location_pairs )
|
||||
|
||||
self._import_file_options = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_import_file_options )
|
||||
self._import_tag_options = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_import_tag_options )
|
||||
self._path_cache = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_path_cache )
|
||||
|
||||
|
||||
def _UpdateSerialisableInfo( self, version, old_serialisable_info ):
|
||||
|
||||
if version == 1:
|
||||
|
||||
( path, mimes, serialisable_import_file_options, action_pairs, action_location_pairs, period, open_popup, tag, serialisable_path_cache, last_checked, paused ) = old_serialisable_info
|
||||
|
||||
service_keys_to_explicit_tags = {}
|
||||
|
||||
if tag is not None:
|
||||
|
||||
service_keys_to_explicit_tags[ CC.LOCAL_TAG_SERVICE_KEY ] = { tag }
|
||||
|
||||
|
||||
import_tag_options = ClientData.ImportTagOptions( service_keys_to_explicit_tags = service_keys_to_explicit_tags )
|
||||
|
||||
serialisable_import_tag_options = import_tag_options.GetSerialisableTuple()
|
||||
|
||||
new_serialisable_info = ( path, mimes, serialisable_import_file_options, serialisable_import_tag_options, action_pairs, action_location_pairs, period, open_popup, serialisable_path_cache, last_checked, paused )
|
||||
|
||||
return ( 2, new_serialisable_info )
|
||||
|
||||
|
||||
|
||||
def DoWork( self ):
|
||||
|
||||
if HydrusGlobals.view_shutdown:
|
||||
|
@ -976,22 +1017,13 @@ class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
if mime in self._mimes:
|
||||
|
||||
if self._tag is None:
|
||||
|
||||
service_keys_to_tags = {}
|
||||
|
||||
else:
|
||||
|
||||
service_keys_to_tags = { CC.LOCAL_TAG_SERVICE_KEY : [ self._tag ] }
|
||||
|
||||
|
||||
( status, hash ) = HydrusGlobals.client_controller.WriteSynchronous( 'import_file', path, import_file_options = self._import_file_options )
|
||||
|
||||
self._path_cache.UpdateSeedStatus( path, status )
|
||||
|
||||
if status in ( CC.STATUS_SUCCESSFUL, CC.STATUS_REDUNDANT ):
|
||||
|
||||
service_keys_to_content_updates = ClientData.ConvertServiceKeysToTagsToServiceKeysToContentUpdates( { hash }, service_keys_to_tags )
|
||||
service_keys_to_content_updates = self._import_tag_options.GetServiceKeysToContentUpdates( hash, set() )
|
||||
|
||||
if len( service_keys_to_content_updates ) > 0:
|
||||
|
||||
|
@ -1009,7 +1041,7 @@ class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
self._path_cache.UpdateSeedStatus( path, CC.STATUS_UNINTERESTING_MIME )
|
||||
|
||||
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
|
||||
error_text = traceback.format_exc()
|
||||
|
||||
|
@ -1046,15 +1078,15 @@ class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
def ToListBoxTuple( self ):
|
||||
|
||||
return ( self._name, self._path, self._period, self._tag )
|
||||
return ( self._name, self._path, self._period )
|
||||
|
||||
|
||||
def ToTuple( self ):
|
||||
|
||||
return ( self._name, self._path, self._mimes, self._import_file_options, self._actions, self._action_locations, self._period, self._open_popup, self._tag, self._paused )
|
||||
return ( self._name, self._path, self._mimes, self._import_file_options, self._import_tag_options, self._actions, self._action_locations, self._period, self._open_popup, self._paused )
|
||||
|
||||
|
||||
def SetTuple( self, name, path, mimes, import_file_options, actions, action_locations, period, open_popup, tag, paused ):
|
||||
def SetTuple( self, name, path, mimes, import_file_options, import_tag_options, actions, action_locations, period, open_popup, paused ):
|
||||
|
||||
if path != self._path:
|
||||
|
||||
|
@ -1070,11 +1102,11 @@ class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
self._path = path
|
||||
self._mimes = mimes
|
||||
self._import_file_options = import_file_options
|
||||
self._import_tag_options
|
||||
self._actions = actions
|
||||
self._action_locations = action_locations
|
||||
self._period = period
|
||||
self._open_popup = open_popup
|
||||
self._tag = tag
|
||||
self._paused = paused
|
||||
|
||||
|
||||
|
@ -1203,7 +1235,7 @@ class PageOfImagesImport( HydrusSerialisable.SerialisableBase ):
|
|||
HydrusGlobals.client_controller.pub( 'add_media_results', page_key, ( media_result, ) )
|
||||
|
||||
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
|
||||
error_text = traceback.format_exc()
|
||||
print( error_text )
|
||||
|
@ -1824,8 +1856,6 @@ class Subscription( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
self._gallery_stream_identifiers = ClientDownloading.GetGalleryStreamIdentifiers( self._gallery_identifier )
|
||||
|
||||
( namespaces, search_value ) = ClientDefaults.GetDefaultNamespacesAndSearchValue( self._gallery_identifier )
|
||||
|
||||
self._query = ''
|
||||
self._period = 86400 * 7
|
||||
self._get_tags_if_redundant = False
|
||||
|
@ -2151,7 +2181,7 @@ class Subscription( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
if error_next_check_time > periodic_next_check_time and not HydrusData.TimeHasPassed( error_next_check_time ):
|
||||
|
||||
interim_text = ' | due to error + ' + HydrusData.ConvertTimestampToPrettySync( self._last_error ) + ', next check '
|
||||
interim_text = ' | due to error ' + HydrusData.ConvertTimestampToPrettySync( self._last_error ) + ', next check '
|
||||
next_check_time = error_next_check_time
|
||||
|
||||
else:
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import ClientFiles
|
||||
import cv2
|
||||
import HydrusConstants as HC
|
||||
import HydrusData
|
||||
import HydrusExceptions
|
||||
|
|
|
@ -37,7 +37,7 @@ options = {}
|
|||
# Misc
|
||||
|
||||
NETWORK_VERSION = 17
|
||||
SOFTWARE_VERSION = 178
|
||||
SOFTWARE_VERSION = 179
|
||||
|
||||
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class HydrusDB( object ):
|
|||
|
||||
def _AnalyzeAfterUpdate( self ):
|
||||
|
||||
print( 'Analysing db after update.' )
|
||||
print( 'Analyzing db after update...' )
|
||||
|
||||
self._c.execute( 'ANALYZE' )
|
||||
|
||||
|
|
|
@ -300,7 +300,11 @@ def LaunchDirectory( path ):
|
|||
|
||||
|
||||
|
||||
threading.Thread( target = do_it ).start()
|
||||
thread = threading.Thread( target = do_it )
|
||||
|
||||
thread.daemon = True
|
||||
|
||||
thread.start()
|
||||
|
||||
def LaunchFile( path ):
|
||||
|
||||
|
@ -325,5 +329,9 @@ def LaunchFile( path ):
|
|||
|
||||
|
||||
|
||||
threading.Thread( target = do_it ).start()
|
||||
thread = threading.Thread( target = do_it )
|
||||
|
||||
thread.daemon = True
|
||||
|
||||
thread.start()
|
||||
|
|
@ -11,4 +11,5 @@ is_first_start = False
|
|||
is_db_updated = False
|
||||
|
||||
db_profile_mode = False
|
||||
special_debug_mode = False
|
||||
server_busy = False
|
||||
|
|
|
@ -18,8 +18,14 @@ import HydrusData
|
|||
import HydrusFileHandling
|
||||
import HydrusGlobals
|
||||
|
||||
#LINEAR_SCALE_PALETTE = [ 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, 47, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 51, 52, 52, 52, 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57, 58, 58, 58, 59, 59, 59, 60, 60, 60, 61, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 65, 65, 65, 66, 66, 66, 67, 67, 67, 68, 68, 68, 69, 69, 69, 70, 70, 70, 71, 71, 71, 72, 72, 72, 73, 73, 73, 74, 74, 74, 75, 75, 75, 76, 76, 76, 77, 77, 77, 78, 78, 78, 79, 79, 79, 80, 80, 80, 81, 81, 81, 82, 82, 82, 83, 83, 83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 87, 87, 87, 88, 88, 88, 89, 89, 89, 90, 90, 90, 91, 91, 91, 92, 92, 92, 93, 93, 93, 94, 94, 94, 95, 95, 95, 96, 96, 96, 97, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 103, 104, 104, 104, 105, 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 116, 116, 116, 117, 117, 117, 118, 118, 118, 119, 119, 119, 120, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123, 123, 124, 124, 124, 125, 125, 125, 126, 126, 126, 127, 127, 127, 128, 128, 128, 129, 129, 129, 130, 130, 130, 131, 131, 131, 132, 132, 132, 133, 133, 133, 134, 134, 134, 135, 135, 135, 136, 136, 136, 137, 137, 137, 138, 138, 138, 139, 139, 139, 140, 140, 140, 141, 141, 141, 142, 142, 142, 143, 143, 143, 144, 144, 144, 145, 145, 145, 146, 146, 146, 147, 147, 147, 148, 148, 148, 149, 149, 149, 150, 150, 150, 151, 151, 151, 152, 152, 152, 153, 153, 153, 154, 154, 154, 155, 155, 155, 156, 156, 156, 157, 157, 157, 158, 158, 158, 159, 159, 159, 160, 160, 160, 161, 161, 161, 162, 162, 162, 163, 163, 163, 164, 164, 164, 165, 165, 165, 166, 166, 166, 167, 167, 167, 168, 168, 168, 169, 169, 169, 170, 170, 170, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, 175, 175, 175, 176, 176, 176, 177, 177, 177, 178, 178, 178, 179, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, 183, 184, 184, 184, 185, 185, 185, 186, 186, 186, 187, 187, 187, 188, 188, 188, 189, 189, 189, 190, 190, 190, 191, 191, 191, 192, 192, 192, 193, 193, 193, 194, 194, 194, 195, 195, 195, 196, 196, 196, 197, 197, 197, 198, 198, 198, 199, 199, 199, 200, 200, 200, 201, 201, 201, 202, 202, 202, 203, 203, 203, 204, 204, 204, 205, 205, 205, 206, 206, 206, 207, 207, 207, 208, 208, 208, 209, 209, 209, 210, 210, 210, 211, 211, 211, 212, 212, 212, 213, 213, 213, 214, 214, 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, 218, 218, 218, 219, 219, 219, 220, 220, 220, 221, 221, 221, 222, 222, 222, 223, 223, 223, 224, 224, 224, 225, 225, 225, 226, 226, 226, 227, 227, 227, 228, 228, 228, 229, 229, 229, 230, 230, 230, 231, 231, 231, 232, 232, 232, 233, 233, 233, 234, 234, 234, 235, 235, 235, 236, 236, 236, 237, 237, 237, 238, 238, 238, 239, 239, 239, 240, 240, 240, 241, 241, 241, 242, 242, 242, 243, 243, 243, 244, 244, 244, 245, 245, 245, 246, 246, 246, 247, 247, 247, 248, 248, 248, 249, 249, 249, 250, 250, 250, 251, 251, 251, 252, 252, 252, 253, 253, 253, 254, 254, 254, 255, 255, 255 ]
|
||||
|
||||
if cv2.__version__.startswith( '2' ):
|
||||
|
||||
IMREAD_UNCHANGED = cv2.CV_LOAD_IMAGE_UNCHANGED
|
||||
|
||||
else:
|
||||
|
||||
IMREAD_UNCHANGED = cv2.IMREAD_UNCHANGED
|
||||
|
||||
def ConvertToPngIfBmp( path ):
|
||||
|
||||
with open( path, 'rb' ) as f: header = f.read( 2 )
|
||||
|
@ -127,7 +133,7 @@ def GenerateNumPyImageFromPILImage( pil_image ):
|
|||
|
||||
def GeneratePerceptualHash( path ):
|
||||
|
||||
numpy_image = cv2.imread( path, cv2.CV_LOAD_IMAGE_UNCHANGED )
|
||||
numpy_image = cv2.imread( path, IMREAD_UNCHANGED )
|
||||
|
||||
( y, x, depth ) = numpy_image.shape
|
||||
|
||||
|
|
|
@ -21,13 +21,31 @@ if HC.PLATFORM_LINUX: FFMPEG_PATH = '' + HC.BIN_DIR + os.path.sep + 'ffmpeg'
|
|||
elif HC.PLATFORM_OSX: FFMPEG_PATH = '' + HC.BIN_DIR + os.path.sep + 'ffmpeg'
|
||||
elif HC.PLATFORM_WINDOWS: FFMPEG_PATH = '' + HC.BIN_DIR + os.path.sep + 'ffmpeg.exe'
|
||||
|
||||
if cv2.__version__.startswith( '2' ):
|
||||
|
||||
CAP_PROP_FRAME_COUNT = cv2.cv.CV_CAP_PROP_FRAME_COUNT
|
||||
CAP_PROP_FPS = cv2.cv.CV_CAP_PROP_FPS
|
||||
CAP_PROP_FRAME_WIDTH = cv2.cv.CV_CAP_PROP_FRAME_WIDTH
|
||||
CAP_PROP_FRAME_HEIGHT = cv2.cv.CV_CAP_PROP_FRAME_HEIGHT
|
||||
CAP_PROP_CONVERT_RGB = cv2.cv.CV_CAP_PROP_CONVERT_RGB
|
||||
CAP_PROP_POS_FRAMES = cv2.cv.CV_CAP_PROP_POS_FRAMES
|
||||
|
||||
else:
|
||||
|
||||
CAP_PROP_FRAME_COUNT = cv2.CAP_PROP_FRAME_COUNT
|
||||
CAP_PROP_FPS = cv2.CAP_PROP_FPS
|
||||
CAP_PROP_FRAME_WIDTH = cv2.CAP_PROP_FRAME_WIDTH
|
||||
CAP_PROP_FRAME_HEIGHT = cv2.CAP_PROP_FRAME_HEIGHT
|
||||
CAP_PROP_CONVERT_RGB = cv2.CAP_PROP_CONVERT_RGB
|
||||
CAP_PROP_POS_FRAMES = cv2.CAP_PROP_POS_FRAMES
|
||||
|
||||
def GetCVVideoProperties( path ):
|
||||
|
||||
capture = cv2.VideoCapture( path )
|
||||
|
||||
num_frames = int( capture.get( cv2.cv.CV_CAP_PROP_FRAME_COUNT ) )
|
||||
num_frames = int( capture.get( CAP_PROP_FRAME_COUNT ) )
|
||||
|
||||
fps = capture.get( cv2.cv.CV_CAP_PROP_FPS )
|
||||
fps = capture.get( CAP_PROP_FPS )
|
||||
|
||||
length_in_seconds = num_frames / fps
|
||||
|
||||
|
@ -35,9 +53,9 @@ def GetCVVideoProperties( path ):
|
|||
|
||||
duration = length_in_ms
|
||||
|
||||
width = int( capture.get( cv2.cv.CV_CAP_PROP_FRAME_WIDTH ) )
|
||||
width = int( capture.get( CAP_PROP_FRAME_WIDTH ) )
|
||||
|
||||
height = int( capture.get( cv2.cv.CV_CAP_PROP_FRAME_HEIGHT ) )
|
||||
height = int( capture.get( CAP_PROP_FRAME_HEIGHT ) )
|
||||
|
||||
return ( ( width, height ), duration, num_frames )
|
||||
|
||||
|
@ -98,7 +116,7 @@ def GetVideoFrameDuration( path ):
|
|||
|
||||
cv_video = cv2.VideoCapture( path )
|
||||
|
||||
fps = cv_video.get( cv2.cv.CV_CAP_PROP_FPS )
|
||||
fps = cv_video.get( CAP_PROP_FPS )
|
||||
|
||||
if fps == 0: raise HydrusExceptions.CantRenderWithCVException()
|
||||
|
||||
|
@ -487,7 +505,7 @@ class GIFRenderer( object ):
|
|||
|
||||
self._cv_video = cv2.VideoCapture( self._path )
|
||||
|
||||
self._cv_video.set( cv2.cv.CV_CAP_PROP_CONVERT_RGB, True )
|
||||
self._cv_video.set( CAP_PROP_CONVERT_RGB, True )
|
||||
|
||||
self._next_render_index = 0
|
||||
self._last_frame = None
|
||||
|
@ -560,7 +578,7 @@ class GIFRenderer( object ):
|
|||
self._cv_video.release()
|
||||
self._cv_video.open( self._path )
|
||||
|
||||
#self._cv_video.set( cv2.cv.CV_CAP_PROP_POS_FRAMES, 0.0 )
|
||||
#self._cv_video.set( CAP_PROP_POS_FRAMES, 0.0 )
|
||||
|
||||
else:
|
||||
|
||||
|
@ -579,6 +597,6 @@ class GIFRenderer( object ):
|
|||
|
||||
while self._next_render_index < index: self._GetCurrentFrame()
|
||||
|
||||
#self._cv_video.set( cv2.cv.CV_CAP_PROP_POS_FRAMES, index )
|
||||
#self._cv_video.set( CV_CAP_PROP_POS_FRAMES, index )
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ class TestDaemons( unittest.TestCase ):
|
|||
|
||||
#
|
||||
|
||||
import_folder = ClientImporting.ImportFolder( 'imp', path = test_dir, tag = 'local tag' )
|
||||
import_folder = ClientImporting.ImportFolder( 'imp', path = test_dir )
|
||||
|
||||
HydrusGlobals.test_controller.SetRead( 'serialisable_named', [ import_folder ] )
|
||||
|
||||
|
|
|
@ -698,7 +698,7 @@ class TestClientDB( unittest.TestCase ):
|
|||
def test_import_folders( self ):
|
||||
|
||||
import_folder_1 = ClientImporting.ImportFolder( 'imp 1', path = HC.DB_DIR, mimes = HC.VIDEO, open_popup = False )
|
||||
import_folder_2 = ClientImporting.ImportFolder( 'imp 2', path = HC.DB_DIR, mimes = HC.IMAGES, period = 1200, open_popup = False, tag = 'test' )
|
||||
import_folder_2 = ClientImporting.ImportFolder( 'imp 2', path = HC.DB_DIR, mimes = HC.IMAGES, period = 1200, open_popup = False )
|
||||
|
||||
#
|
||||
|
||||
|
|
Loading…
Reference in New Issue