Version 582
This commit is contained in:
parent
b1b4beea75
commit
39fc04a3a1
|
@ -7,6 +7,43 @@ title: Changelog
|
|||
!!! note
|
||||
This is the new changelog, only the most recent builds. For all versions, see the [old changelog](old_changelog.html).
|
||||
|
||||
## [Version 582](https://github.com/hydrusnetwork/hydrus/releases/tag/v582)
|
||||
|
||||
### fixes
|
||||
|
||||
* fixed an issue where setting a file 'collect' was not automatically sorting the collected objects internally properly. normally when you collect, each collected object is supposed to be sorted internally by filesize or namespace or whatever--this is working again
|
||||
* fixed a weird internal error state in the import folders manager where it could get confused about and throw an error regarding the import folders' next work times if an internal update notification occured during an import folder working
|
||||
* fixed a typo error with the shortcut set 'special duplicate' button
|
||||
* fixed pasting new query texts into the manage subscriptions dialog when one of the pasted texts resurrects a DEAD query. my new summary generation text was handling the DEAD report wrong!
|
||||
|
||||
### misc
|
||||
|
||||
* the advanced 'all deleted files' service, which is mostly just used for behind the scenes caching calculations, is renamed to 'deleted from anywhere'. the related 'regen->all deleted files' database command is also moved to 'check and repair->sync combined deleted files'
|
||||
* the edit tag filter panel's 'load' button now shows all the current tag repositories' tag filters
|
||||
* when you hit ctrl-enter on some tags (or otherwise trigger a linked remove+add action) in an active search list (e.g. top-left on a search page), which causes those tags to invert and thus sometimes sorted to a different position, the current selection now propagates through the inversion, with the keyboard focus moved to the post-topmost item. so, you can now basically hit ctrl+enter twice for a no-op
|
||||
* fixed the paste button in the new 'purge tags' dialog
|
||||
* thanks to a user, we have a new 'Purple' stylesheet
|
||||
* I tweaked the some default stylesheet colours and think I fixed the display of the 'valid/invalid' controls you sometimes see (for instance in the new regex input, which goes green/red) for dark mode stylesheets that don't define colours for these. previously, the dark mode text, usually a light grey, was being washed out by the default green
|
||||
|
||||
### custom colours in QSS
|
||||
|
||||
* you can now set the _options->colours_ colours in a QSS stylesheet! if you are a stylesheet maker, check the default_hydrus.qss file to see how it works--it is the same deal as the animation scanbar previously
|
||||
* the options in _options->colours_ remain, but they are now wrapped in a 'overwrite your stylesheet with these colours' checkbox _for now_. existing users are going to be set to 'yes overwrite', so nothing will suddenly change, but new users are going to default to using whatever the current QSS says. in future, I may collapse the light/darkmode distinction into one option set; I may morph it into a "colour highly rated files' thumbnail borders gold" dynamic options system; I may simply delete the whole thing and replace it with in-client QSS editing or something. not sure, so let's see how it goes and how Qt 7's darkmode stuff turns out.
|
||||
* I have pasted the hydrus default darkmode colours into all the other stylesheets that come with the program, so new users selecting a darkmode style are going to get something reasonable out of the box rather than the previous ugly clash. the users who made the original stylesheets are welcome to figure out better colours and send them in
|
||||
* if you are not set to override with the custom colours in _options->colours_, then hitting _help->darkmode_ now gives you a popup telling you what is going on
|
||||
|
||||
### sidecar UI
|
||||
|
||||
* the four 'edit sidecars' panels (under manual imports, import folders, manual exports, and export folders), which use paths and media as sources respectively, now have test panels to review the current sidecar route you have set up. they use up to 25 rows of example file paths/media from the actual thing you are working on. it provides a live update of what the sources you set up will load, so you know you have the json parse or .txt separator set up correct
|
||||
* for the export folders case, there is a button in the panel 'edit export folders' panel to populate the text context, under your control, since this involves a potentially slow file search
|
||||
* there is more to do here. I would like better test panels in the sub-dialogs and I'd like to collapse the related 'eight-nested-dialogs-deep' problem, and in the string processing and parsing UI more generally, but I'm happy with this step forward. let me know where it goes wrong!
|
||||
|
||||
### advanced autocomplete logic fixes
|
||||
|
||||
* when you enter a wildcard into a Read tag autocomplete, it no longer always delivers the 'always autocompleting' version. so, if you enter `sa*s`, it will suggest `sa*s (wildcard search)` and perhaps `sa*s (any namespace)`, but it will no longer suggest the `sa*s*` variants until you, obviously, actually type that trailing asterisk yourself. I intermittently had no idea what the hell I was doing when I originally developed this stuff
|
||||
* the 'unnamespaced input gives `(any namespace)` wildcard results' tag display option is now correctly negatively enforced when entering unnamespaced wildcards. previously it was always adding them, and sometimes inserting them at the top of the list. the `(any namespace)` variant is now always below the unnamespaced when both are present
|
||||
* fixed up a bunch of jank unit tests that were testing this badly
|
||||
|
||||
## [Version 581](https://github.com/hydrusnetwork/hydrus/releases/tag/v581)
|
||||
|
||||
### misc
|
||||
|
@ -333,40 +370,3 @@ title: Changelog
|
|||
* the local booru review services panel no longer shows nor allows management of its shares
|
||||
* deleted the local booru unit tests
|
||||
* deleted the local booru help and ancient screenshots
|
||||
|
||||
## [Version 572](https://github.com/hydrusnetwork/hydrus/releases/tag/v572)
|
||||
|
||||
### misc
|
||||
|
||||
* added a new checkbox to _options->files and trash_ to say 'include skipped files when you remove files after archive/delete'
|
||||
* thanks to a user, we now have an 'e621' stylsheet in _options->style_. this is the first default stylesheet that uses assets (some checkbox etc.. svgs), which means some users--I think just those who run from source--will need to be careful that their CWD is the hydrus install dir when they boot, or this won't load properly! if you try it and get errors in your log as it tries to load the svgs, let me know!
|
||||
|
||||
### share menu
|
||||
|
||||
* like the 'open' menu a couple weeks ago, the 'share' menu off of thumbnails or the media viewer is rewritten to nicer code. no major differences, but it has a clearer, universal layout, provides more options for 'the currently focused file' vs 'all selected files', is more careful about only providing commands it can deliver on (e.g. no file copy for remote files), and now everything it does is mappable in the shortcut system under the 'media' shortcut set
|
||||
* you can now copy a file's thumbnail as a bitmap from this menu!
|
||||
* the canvas now supports 'export files'. the 'export files' window just pops on top of it with the one file
|
||||
* 'copy file id' is no longer hidden by advanced mode--go nuts!
|
||||
* the share menu no longer has 'share on local booru'. the local booru service was an interesting experiment, but I could never find time to properly dev it and there are better answers with the Client API or simple third-party image hosting services that you can drag and drop to. thus, I am finally sunsetting it. I'll strip away its features over the coming weeks until it is completely removed
|
||||
|
||||
### shortcut updates
|
||||
|
||||
* the 'copy file hash' shortcut actions, which used to be four separate things, have been collapsed to one action that has a 'hash type' dropdown (and a 'target' dropdown to select either all selected files or just the currently focused file, which will default to 'all selected' on update, which was the previous behaviour). you can also now set 'pixel_hash' or 'blurhash' as the hash type
|
||||
* the 'copy file bitmap' shortcuts have similarly been collapsed down to one action with a dropdown, also with the new 'copy thumbnail' command
|
||||
* the 'copy files', 'copy file paths', and 'copy file id' shortcuts now have a dropdown for whether you want all selected files or just the currently focused file. updated commands will default to 'all selected', which was the previous behaviour
|
||||
* added a 'copy ipfs multihash' shortcut action, which has this new 'focused vs all selected' parameter and the ipfs service to copy from as its options
|
||||
|
||||
### boring code cleanup
|
||||
|
||||
* wrote a new command for copying arbitrary file hashes, with a new 'file command target'
|
||||
* simplified the media hash copying code
|
||||
* wrote a new command for copying arbitrary bitmap types
|
||||
* combined the bitmap copying code into one shared function call and simplified the surrounding code
|
||||
* combined the file and path copying code into shared functions, simplified the code, and added tech for focused vs all selected targeting
|
||||
* and the same thing for copying ipfs multihashes
|
||||
* wrote a routine to copy a file's thumbnail in the normal clipboard copying pubsub
|
||||
* with the recent rounds of simplication, the core thumbnail menu call is now but a mere 600 lines of spaghetti code
|
||||
* misc renaming of some enums here so they are more in agreement ('xxx files' instead of 'xxx file', etc...)
|
||||
* renamed the various simple commands I have replaced in the past few weeks as 'legacy', so we don't accidentally refer to them again in real code
|
||||
* the unit test for 'dateparser decode' is no longer run if dateparser is not in the environment
|
||||
* fixed the file metadata parsing unit tests to account for newer ffmpeg, which sees a -10ms different duration on one of the test files, and made the various tests +/-20% lenient to handle this stuff if it comes up again in future
|
||||
|
|
|
@ -286,7 +286,7 @@ You won't see all of these, but the service `type` enum is:
|
|||
* 15 - all local files -- all files on hard disk ('all my files' + updates + trash)
|
||||
* 17 - file notes
|
||||
* 18 - Client API
|
||||
* 19 - all deleted files -- you can ignore this
|
||||
* 19 - deleted from anywhere -- you can ignore this
|
||||
* 20 - local updates -- a file domain to store repository update files in
|
||||
* 21 - all my files -- union of all local file domains
|
||||
* 22 - a 'inc/dec' rating service with positive integer rating
|
||||
|
@ -2142,7 +2142,7 @@ Response:
|
|||
|
||||
**It is possible for the king to not be available.** Every group has a king, but if that file has been deleted, or if the file domain here is limited and the king is on a different file service, then it may not be available. A similar issue occurs when you search for filtering pairs--while it is ideal to compare kings with kings, if you set 'files must be pixel dupes', then the user will expect to see those pixel duplicates, not their champions--you may be forced to compare non-kings. `king_is_on_file_domain` lets you know if the king is on the file domain you set, and `king_is_local` lets you know if it is on the hard disk--if `king_is_local=true`, you can do a `/get_files/file` request on it. It is generally rare, but you have to deal with the king being unavailable--in this situation, your best bet is to just use the file itself as its own representative.
|
||||
|
||||
All the relationships you get are filtered by the file domain. If you set the file domain to 'all known files', you will get every relationship a file has, including all deleted files, which is often less useful than you would think. The default, 'all my files' is usually most useful.
|
||||
All the relationships you get are filtered by the file domain. If you set the file domain to 'all known files', you will get every relationship a file has, including all deleted files, which is often less useful than you would think. The default, 'all my files', is usually most useful.
|
||||
|
||||
A file that has no duplicates is considered to be in a duplicate group of size 1 and thus is always its own king.
|
||||
|
||||
|
|
|
@ -34,6 +34,36 @@
|
|||
<div class="content">
|
||||
<h1 id="changelog"><a href="#changelog">changelog</a></h1>
|
||||
<ul>
|
||||
<li>
|
||||
<h2 id="version_582"><a href="#version_582">version 582</a></h2>
|
||||
<ul>
|
||||
<li><h3>fixes</h3></li>
|
||||
<li>fixed an issue where setting a file 'collect' was not automatically sorting the collected objects internally properly. normally when you collect, each collected object is supposed to be sorted internally by filesize or namespace or whatever--this is working again</li>
|
||||
<li>fixed a weird internal error state in the import folders manager where it could get confused about and throw an error regarding the import folders' next work times if an internal update notification occured during an import folder working</li>
|
||||
<li>fixed a typo error with the shortcut set 'special duplicate' button</li>
|
||||
<li>fixed pasting new query texts into the manage subscriptions dialog when one of the pasted texts resurrects a DEAD query. my new summary generation text was handling the DEAD report wrong!</li>
|
||||
<li><h3>misc</h3></li>
|
||||
<li>the advanced 'all deleted files' service, which is mostly just used for behind the scenes caching calculations, is renamed to 'deleted from anywhere'. the related 'regen->all deleted files' database command is also moved to 'check and repair->sync combined deleted files'</li>
|
||||
<li>the edit tag filter panel's 'load' button now shows all the current tag repositories' tag filters</li>
|
||||
<li>when you hit ctrl-enter on some tags (or otherwise trigger a linked remove+add action) in an active search list (e.g. top-left on a search page), which causes those tags to invert and thus sometimes sorted to a different position, the current selection now propagates through the inversion, with the keyboard focus moved to the post-topmost item. so, you can now basically hit ctrl+enter twice for a no-op</li>
|
||||
<li>fixed the paste button in the new 'purge tags' dialog</li>
|
||||
<li>thanks to a user, we have a new 'Purple' stylesheet</li>
|
||||
<li>I tweaked the some default stylesheet colours and think I fixed the display of the 'valid/invalid' controls you sometimes see (for instance in the new regex input, which goes green/red) for dark mode stylesheets that don't define colours for these. previously, the dark mode text, usually a light grey, was being washed out by the default green</li>
|
||||
<li><h3>custom colours in QSS</h3></li>
|
||||
<li>you can now set the _options->colours_ colours in a QSS stylesheet! if you are a stylesheet maker, check the default_hydrus.qss file to see how it works--it is the same deal as the animation scanbar previously</li>
|
||||
<li>the options in _options->colours_ remain, but they are now wrapped in a 'overwrite your stylesheet with these colours' checkbox _for now_. existing users are going to be set to 'yes overwrite', so nothing will suddenly change, but new users are going to default to using whatever the current QSS says. in future, I may collapse the light/darkmode distinction into one option set; I may morph it into a "colour highly rated files' thumbnail borders gold" dynamic options system; I may simply delete the whole thing and replace it with in-client QSS editing or something. not sure, so let's see how it goes and how Qt 7's darkmode stuff turns out.</li>
|
||||
<li>I have pasted the hydrus default darkmode colours into all the other stylesheets that come with the program, so new users selecting a darkmode style are going to get something reasonable out of the box rather than the previous ugly clash. the users who made the original stylesheets are welcome to figure out better colours and send them in</li>
|
||||
<li>if you are not set to override with the custom colours in _options->colours_, then hitting _help->darkmode_ now gives you a popup telling you what is going on</li>
|
||||
<li><h3>sidecar UI</h3></li>
|
||||
<li>the four 'edit sidecars' panels (under manual imports, import folders, manual exports, and export folders), which use paths and media as sources respectively, now have test panels to review the current sidecar route you have set up. they use up to 25 rows of example file paths/media from the actual thing you are working on. it provides a live update of what the sources you set up will load, so you know you have the json parse or .txt separator set up correct</li>
|
||||
<li>for the export folders case, there is a button in the panel 'edit export folders' panel to populate the text context, under your control, since this involves a potentially slow file search</li>
|
||||
<li>there is more to do here. I would like better test panels in the sub-dialogs and I'd like to collapse the related 'eight-nested-dialogs-deep' problem, and in the string processing and parsing UI more generally, but I'm happy with this step forward. let me know where it goes wrong!</li>
|
||||
<li><h3>advanced autocomplete logic fixes</h3></li>
|
||||
<li>when you enter a wildcard into a Read tag autocomplete, it no longer always delivers the 'always autocompleting' version. so, if you enter `sa*s`, it will suggest `sa*s (wildcard search)` and perhaps `sa*s (any namespace)`, but it will no longer suggest the `sa*s*` variants until you, obviously, actually type that trailing asterisk yourself. I intermittently had no idea what the hell I was doing when I originally developed this stuff</li>
|
||||
<li>the 'unnamespaced input gives `(any namespace)` wildcard results' tag display option is now correctly negatively enforced when entering unnamespaced wildcards. previously it was always adding them, and sometimes inserting them at the top of the list. the `(any namespace)` variant is now always below the unnamespaced when both are present</li>
|
||||
<li>fixed up a bunch of jank unit tests that were testing this badly</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h2 id="version_581"><a href="#version_581">version 581</a></h2>
|
||||
<ul>
|
||||
|
|
|
@ -256,7 +256,8 @@ class ClientOptions( HydrusSerialisable.SerialisableBase ):
|
|||
'enable_truncated_images_pil' : True,
|
||||
'do_icc_profile_normalisation' : True,
|
||||
'mpv_available_at_start' : ClientGUIMPV.MPV_IS_AVAILABLE,
|
||||
'do_sleep_check' : True
|
||||
'do_sleep_check' : True,
|
||||
'override_stylesheet_colours' : False
|
||||
}
|
||||
|
||||
#
|
||||
|
|
|
@ -1272,7 +1272,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
init_service_info = [
|
||||
( CC.COMBINED_TAG_SERVICE_KEY, HC.COMBINED_TAG, 'all known tags' ),
|
||||
( CC.COMBINED_FILE_SERVICE_KEY, HC.COMBINED_FILE, 'all known files' ),
|
||||
( CC.COMBINED_DELETED_FILE_SERVICE_KEY, HC.COMBINED_DELETED_FILE, 'all deleted files' ),
|
||||
( CC.COMBINED_DELETED_FILE_SERVICE_KEY, HC.COMBINED_DELETED_FILE, 'deleted from anywhere' ),
|
||||
( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, HC.COMBINED_LOCAL_FILE, 'all local files' ),
|
||||
( CC.COMBINED_LOCAL_MEDIA_SERVICE_KEY, HC.COMBINED_LOCAL_MEDIA, 'all my files' ),
|
||||
( CC.LOCAL_FILE_SERVICE_KEY, HC.LOCAL_FILE_DOMAIN, 'my files' ),
|
||||
|
@ -5802,7 +5802,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
service_ids_to_nums_cleared = self.modules_files_storage.ClearLocalDeleteRecord()
|
||||
|
||||
self._SyncCombinedDeletedFiles()
|
||||
self._ResyncCombinedDeletedFiles()
|
||||
|
||||
else:
|
||||
|
||||
|
@ -5810,7 +5810,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
service_ids_to_nums_cleared = self.modules_files_storage.ClearLocalDeleteRecord( hash_ids )
|
||||
|
||||
self._SyncCombinedDeletedFiles( hash_ids )
|
||||
self._ResyncCombinedDeletedFiles( hash_ids )
|
||||
|
||||
|
||||
self._ExecuteMany( 'UPDATE service_info SET info = info + ? WHERE service_id = ? AND info_type = ?;', ( ( -num_cleared, clear_service_id, HC.SERVICE_INFO_NUM_DELETED_FILES ) for ( clear_service_id, num_cleared ) in service_ids_to_nums_cleared.items() ) )
|
||||
|
@ -8423,6 +8423,84 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
|
||||
|
||||
def _ResyncCombinedDeletedFiles( self, hash_ids = None, do_full_rebuild = False ):
|
||||
|
||||
combined_files_stakeholder_service_ids = self.modules_services.GetServiceIds( HC.FILE_SERVICES_COVERED_BY_COMBINED_DELETED_FILE )
|
||||
|
||||
hash_ids_that_are_desired = set()
|
||||
|
||||
if hash_ids is None:
|
||||
|
||||
for service_id in combined_files_stakeholder_service_ids:
|
||||
|
||||
hash_ids_that_are_desired.update( self.modules_files_storage.GetDeletedHashIdsList( service_id ) )
|
||||
|
||||
|
||||
existing_hash_ids = set( self.modules_files_storage.GetCurrentHashIdsList( self.modules_services.combined_deleted_file_service_id ) )
|
||||
|
||||
else:
|
||||
|
||||
for service_id in combined_files_stakeholder_service_ids:
|
||||
|
||||
hash_ids_that_are_desired.update( self.modules_files_storage.FilterHashIdsToStatus( service_id, hash_ids, HC.CONTENT_STATUS_DELETED ) )
|
||||
|
||||
|
||||
existing_hash_ids = self.modules_files_storage.FilterHashIdsToStatus( self.modules_services.combined_deleted_file_service_id, hash_ids, HC.CONTENT_STATUS_CURRENT )
|
||||
|
||||
|
||||
if do_full_rebuild:
|
||||
|
||||
# this happens in the full 'regenerate' call from the UI database menu. full wipe and recalculation to get any errant timestamps
|
||||
|
||||
hash_ids_to_remove = existing_hash_ids
|
||||
hash_ids_to_add = hash_ids_that_are_desired
|
||||
|
||||
else:
|
||||
|
||||
hash_ids_to_remove = existing_hash_ids.difference( hash_ids_that_are_desired )
|
||||
hash_ids_to_add = hash_ids_that_are_desired.difference( existing_hash_ids )
|
||||
|
||||
|
||||
if len( hash_ids_to_remove ) > 0:
|
||||
|
||||
self._DeleteFiles( self.modules_services.combined_deleted_file_service_id, hash_ids_to_remove, only_if_current = True )
|
||||
|
||||
|
||||
if len( hash_ids_to_add ) > 0:
|
||||
|
||||
hash_ids_to_earliest_timestamps_ms = {}
|
||||
|
||||
for service_id in combined_files_stakeholder_service_ids:
|
||||
|
||||
hash_ids_to_both_timestamps_ms = self.modules_files_storage.GetDeletedHashIdsToTimestampsMS( service_id, hash_ids_to_add )
|
||||
|
||||
for ( hash_id, ( timestamp_ms, original_timestamp_ms ) ) in hash_ids_to_both_timestamps_ms.items():
|
||||
|
||||
if hash_id in hash_ids_to_earliest_timestamps_ms:
|
||||
|
||||
if timestamp_ms is not None:
|
||||
|
||||
existing_timestamp = hash_ids_to_earliest_timestamps_ms[ hash_id ]
|
||||
|
||||
if existing_timestamp is None or timestamp_ms < existing_timestamp:
|
||||
|
||||
hash_ids_to_earliest_timestamps_ms[ hash_id ] = timestamp_ms
|
||||
|
||||
|
||||
|
||||
else:
|
||||
|
||||
hash_ids_to_earliest_timestamps_ms[ hash_id ] = timestamp_ms
|
||||
|
||||
|
||||
|
||||
|
||||
rows = list( hash_ids_to_earliest_timestamps_ms.items() )
|
||||
|
||||
self._AddFiles( self.modules_services.combined_deleted_file_service_id, rows )
|
||||
|
||||
|
||||
|
||||
def _ResyncTagMappingsCacheFiles( self, tag_service_key = None ):
|
||||
|
||||
job_status = ClientThreading.JobStatus( cancellable = True )
|
||||
|
@ -8577,84 +8655,6 @@ class DB( HydrusDB.HydrusDB ):
|
|||
self._SaveOptions( self._controller.options )
|
||||
|
||||
|
||||
def _SyncCombinedDeletedFiles( self, hash_ids = None, do_full_rebuild = False ):
|
||||
|
||||
combined_files_stakeholder_service_ids = self.modules_services.GetServiceIds( HC.FILE_SERVICES_COVERED_BY_COMBINED_DELETED_FILE )
|
||||
|
||||
hash_ids_that_are_desired = set()
|
||||
|
||||
if hash_ids is None:
|
||||
|
||||
for service_id in combined_files_stakeholder_service_ids:
|
||||
|
||||
hash_ids_that_are_desired.update( self.modules_files_storage.GetDeletedHashIdsList( service_id ) )
|
||||
|
||||
|
||||
existing_hash_ids = set( self.modules_files_storage.GetCurrentHashIdsList( self.modules_services.combined_deleted_file_service_id ) )
|
||||
|
||||
else:
|
||||
|
||||
for service_id in combined_files_stakeholder_service_ids:
|
||||
|
||||
hash_ids_that_are_desired.update( self.modules_files_storage.FilterHashIdsToStatus( service_id, hash_ids, HC.CONTENT_STATUS_DELETED ) )
|
||||
|
||||
|
||||
existing_hash_ids = self.modules_files_storage.FilterHashIdsToStatus( self.modules_services.combined_deleted_file_service_id, hash_ids, HC.CONTENT_STATUS_CURRENT )
|
||||
|
||||
|
||||
if do_full_rebuild:
|
||||
|
||||
# this happens in the full 'regenerate' call from the UI database menu. full wipe and recalculation to get any errant timestamps
|
||||
|
||||
hash_ids_to_remove = existing_hash_ids
|
||||
hash_ids_to_add = hash_ids_that_are_desired
|
||||
|
||||
else:
|
||||
|
||||
hash_ids_to_remove = existing_hash_ids.difference( hash_ids_that_are_desired )
|
||||
hash_ids_to_add = hash_ids_that_are_desired.difference( existing_hash_ids )
|
||||
|
||||
|
||||
if len( hash_ids_to_remove ) > 0:
|
||||
|
||||
self._DeleteFiles( self.modules_services.combined_deleted_file_service_id, hash_ids_to_remove, only_if_current = True )
|
||||
|
||||
|
||||
if len( hash_ids_to_add ) > 0:
|
||||
|
||||
hash_ids_to_earliest_timestamps_ms = {}
|
||||
|
||||
for service_id in combined_files_stakeholder_service_ids:
|
||||
|
||||
hash_ids_to_both_timestamps_ms = self.modules_files_storage.GetDeletedHashIdsToTimestampsMS( service_id, hash_ids_to_add )
|
||||
|
||||
for ( hash_id, ( timestamp_ms, original_timestamp_ms ) ) in hash_ids_to_both_timestamps_ms.items():
|
||||
|
||||
if hash_id in hash_ids_to_earliest_timestamps_ms:
|
||||
|
||||
if timestamp_ms is not None:
|
||||
|
||||
existing_timestamp = hash_ids_to_earliest_timestamps_ms[ hash_id ]
|
||||
|
||||
if existing_timestamp is None or timestamp_ms < existing_timestamp:
|
||||
|
||||
hash_ids_to_earliest_timestamps_ms[ hash_id ] = timestamp_ms
|
||||
|
||||
|
||||
|
||||
else:
|
||||
|
||||
hash_ids_to_earliest_timestamps_ms[ hash_id ] = timestamp_ms
|
||||
|
||||
|
||||
|
||||
|
||||
rows = list( hash_ids_to_earliest_timestamps_ms.items() )
|
||||
|
||||
self._AddFiles( self.modules_services.combined_deleted_file_service_id, rows )
|
||||
|
||||
|
||||
|
||||
def _UndeleteFiles( self, service_id, hash_ids ):
|
||||
|
||||
if service_id in ( self.modules_services.combined_local_file_service_id, self.modules_services.combined_local_media_service_id, self.modules_services.trash_service_id ):
|
||||
|
@ -9263,7 +9263,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
try:
|
||||
|
||||
self._SyncCombinedDeletedFiles( do_full_rebuild = False ) # first time I wrote do_full_rebuild, it was too slow!
|
||||
self._ResyncCombinedDeletedFiles( do_full_rebuild = False ) # first time I wrote do_full_rebuild, it was too slow!
|
||||
|
||||
except Exception as e:
|
||||
|
||||
|
@ -10417,6 +10417,39 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
|
||||
|
||||
if version == 581:
|
||||
|
||||
try:
|
||||
|
||||
new_options = self.modules_serialisable.GetJSONDump( HydrusSerialisable.SERIALISABLE_TYPE_CLIENT_OPTIONS )
|
||||
|
||||
new_options.SetBoolean( 'override_stylesheet_colours', True )
|
||||
|
||||
self.modules_serialisable.SetJSONDump( new_options )
|
||||
|
||||
except Exception as e:
|
||||
|
||||
HydrusData.PrintException( e )
|
||||
|
||||
message = 'Trying to update your options failed! Please let hydrus dev know!'
|
||||
|
||||
self.pub_initial_message( message )
|
||||
|
||||
|
||||
try:
|
||||
|
||||
self._Execute( 'UPDATE services SET name = ? WHERE name = ? and service_type = ?;', ( 'deleted from anywhere', 'all deleted files', HC.COMBINED_DELETED_FILE ) )
|
||||
|
||||
except Exception as e:
|
||||
|
||||
HydrusData.PrintException( e )
|
||||
|
||||
message = 'Trying to rename "all deleted files" failed! Please let hydrus dev know!'
|
||||
|
||||
self.pub_initial_message( message )
|
||||
|
||||
|
||||
|
||||
self._controller.frame_splash_status.SetTitleText( 'updated db to v{}'.format( HydrusNumbers.ToHumanInt( version + 1 ) ) )
|
||||
|
||||
self._Execute( 'UPDATE version SET version = ?;', ( version + 1, ) )
|
||||
|
@ -10934,7 +10967,6 @@ class DB( HydrusDB.HydrusDB ):
|
|||
elif action == 'process_repository_content': result = self._ProcessRepositoryContent( *args, **kwargs )
|
||||
elif action == 'process_repository_definitions': result = self.modules_repositories.ProcessRepositoryDefinitions( *args, **kwargs )
|
||||
elif action == 'push_recent_tags': self.modules_recent_tags.PushRecentTags( *args, **kwargs )
|
||||
elif action == 'regenerate_combined_deleted_files': self._SyncCombinedDeletedFiles( *args, **kwargs )
|
||||
elif action == 'regenerate_local_hash_cache': self._RegenerateLocalHashCache( *args, **kwargs )
|
||||
elif action == 'regenerate_local_tag_cache': self._RegenerateLocalTagCache( *args, **kwargs )
|
||||
elif action == 'regenerate_similar_files': self.modules_similar_files.RegenerateTree( *args, **kwargs )
|
||||
|
@ -10961,6 +10993,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
elif action == 'reset_repository': self._ResetRepository( *args, **kwargs )
|
||||
elif action == 'reset_repository_processing': self._ResetRepositoryProcessing( *args, **kwargs )
|
||||
elif action == 'reset_potential_search_status': self._PerceptualHashesResetSearchFromHashes( *args, **kwargs )
|
||||
elif action == 'resync_combined_deleted_files': self._ResyncCombinedDeletedFiles( *args, **kwargs )
|
||||
elif action == 'resync_tag_mappings_cache_files': self._ResyncTagMappingsCacheFiles( *args, **kwargs )
|
||||
elif action == 'save_options': self._SaveOptions( *args, **kwargs )
|
||||
elif action == 'serialisable': self.modules_serialisable.SetJSONDump( *args, **kwargs )
|
||||
|
|
|
@ -399,7 +399,7 @@ class ClientDBMappingsCounts( ClientDBModule.ClientDBModule ):
|
|||
|
||||
else:
|
||||
|
||||
# for instance this is a search for 'my files' deleted files, but we are searching on 'all deleted files' domain
|
||||
# for instance this is a search for 'my files' deleted files, but we are searching on 'deleted from anywhere' domain
|
||||
|
||||
current_min = 0
|
||||
pending_min = 0
|
||||
|
|
|
@ -3233,10 +3233,14 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
check_submenu = ClientGUIMenus.GenerateMenu( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( check_submenu, 'database integrity' + HC.UNICODE_ELLIPSIS, 'Examine the database for file corruption.', self._CheckDBIntegrity )
|
||||
ClientGUIMenus.AppendMenuItem( check_submenu, 'repopulate truncated mappings tables' + HC.UNICODE_ELLIPSIS, 'Use the mappings cache to try to repair a previously damaged mappings file.', self._RepopulateMappingsTables )
|
||||
ClientGUIMenus.AppendMenuItem( check_submenu, 'resync tag mappings cache files' + HC.UNICODE_ELLIPSIS, 'Check the tag mappings cache for surplus or missing files.', self._ResyncTagMappingsCacheFiles )
|
||||
ClientGUIMenus.AppendMenuItem( check_submenu, 'fix logically inconsistent mappings' + HC.UNICODE_ELLIPSIS, 'Remove tags that are occupying two mutually exclusive states.', self._FixLogicallyInconsistentMappings )
|
||||
ClientGUIMenus.AppendSeparator( check_submenu )
|
||||
ClientGUIMenus.AppendMenuItem( check_submenu, 'fix invalid tags' + HC.UNICODE_ELLIPSIS, 'Scan the database for invalid tags.', self._RepairInvalidTags )
|
||||
ClientGUIMenus.AppendMenuItem( check_submenu, 'fix logically inconsistent mappings' + HC.UNICODE_ELLIPSIS, 'Remove tags that are occupying two mutually exclusive states.', self._FixLogicallyInconsistentMappings )
|
||||
ClientGUIMenus.AppendSeparator( check_submenu )
|
||||
ClientGUIMenus.AppendMenuItem( check_submenu, 'repopulate truncated mappings tables' + HC.UNICODE_ELLIPSIS, 'Use the mappings cache to try to repair a previously damaged mappings file.', self._RepopulateMappingsTables )
|
||||
ClientGUIMenus.AppendSeparator( check_submenu )
|
||||
ClientGUIMenus.AppendMenuItem( check_submenu, 'resync combined deleted files' + HC.UNICODE_ELLIPSIS, 'Resynchronise the store of all known deleted files.', self._ResyncCombinedDeletedFiles )
|
||||
ClientGUIMenus.AppendMenuItem( check_submenu, 'resync tag mappings cache files' + HC.UNICODE_ELLIPSIS, 'Check the tag mappings cache for surplus or missing files.', self._ResyncTagMappingsCacheFiles )
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, check_submenu, 'check and repair' )
|
||||
|
||||
|
@ -3256,7 +3260,6 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
ClientGUIMenus.AppendSeparator( regen_submenu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( regen_submenu, 'all deleted files' + HC.UNICODE_ELLIPSIS, 'Resynchronise the store of all known deleted files.', self._RegenerateCombinedDeletedFiles )
|
||||
ClientGUIMenus.AppendMenuItem( regen_submenu, 'local hashes cache' + HC.UNICODE_ELLIPSIS, 'Repopulate the cache hydrus uses for fast hash lookup for local files.', self._RegenerateLocalHashCache )
|
||||
ClientGUIMenus.AppendMenuItem( regen_submenu, 'local tags cache' + HC.UNICODE_ELLIPSIS, 'Repopulate the cache hydrus uses for fast tag lookup for local files.', self._RegenerateLocalTagCache )
|
||||
|
||||
|
@ -5221,22 +5224,6 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
self._statusbar.SetStatusText( db_status, 5, tooltip = db_tooltip )
|
||||
|
||||
|
||||
def _RegenerateCombinedDeletedFiles( self ):
|
||||
|
||||
message = 'This will resynchronise the "all deleted files" cache to the actual records in the database, ensuring that various tag searches over the deleted files domain give correct counts and file results. It isn\'t super important, but this routine fixes it if it is desynchronised.'
|
||||
message += '\n' * 2
|
||||
message += 'It should not take all that long, but if you have a lot of deleted files, it can take a little while, during which the gui may hang.'
|
||||
message += '\n' * 2
|
||||
message += 'If you do not have a specific reason to run this, it is pointless.'
|
||||
|
||||
result = ClientGUIDialogsQuick.GetYesNo( self, message, yes_label = 'do it', no_label = 'forget it' )
|
||||
|
||||
if result == QW.QDialog.Accepted:
|
||||
|
||||
self._controller.Write( 'regenerate_combined_deleted_files', do_full_rebuild = True )
|
||||
|
||||
|
||||
|
||||
def _RegenerateTagCache( self ):
|
||||
|
||||
message = 'This will delete and then recreate the fast search cache for one or all tag services.'
|
||||
|
@ -5670,6 +5657,22 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
self._controller.pub( 'set_splitter_positions', HC.options[ 'hpos' ], HC.options[ 'vpos' ] )
|
||||
|
||||
|
||||
def _ResyncCombinedDeletedFiles( self ):
|
||||
|
||||
message = 'This will resynchronise the "deleted from anywhere" cache to the actual records in the database, ensuring that various tag searches over the deleted files domain give correct counts and file results. It isn\'t super important, but this routine fixes it if it is desynchronised.'
|
||||
message += '\n' * 2
|
||||
message += 'It should not take all that long, but if you have a lot of deleted files, it can take a little while, during which the gui may hang.'
|
||||
message += '\n' * 2
|
||||
message += 'If you do not have a specific reason to run this, it is pointless.'
|
||||
|
||||
result = ClientGUIDialogsQuick.GetYesNo( self, message, yes_label = 'do it', no_label = 'forget it' )
|
||||
|
||||
if result == QW.QDialog.Accepted:
|
||||
|
||||
self._controller.Write( 'resync_combined_deleted_files', do_full_rebuild = True )
|
||||
|
||||
|
||||
|
||||
def _ResyncTagMappingsCacheFiles( self ):
|
||||
|
||||
message = 'This will scan your mappings cache for surplus or missing files and correct them. This is useful if you see ghost files or if searches miss files that have the tag.'
|
||||
|
@ -7393,6 +7396,11 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
def FlipDarkmode( self ):
|
||||
|
||||
if not self._new_options.GetBoolean( 'override_stylesheet_colours' ):
|
||||
|
||||
ClientGUIDialogsMessage.ShowWarning( self, 'Hey, this command comes from an old colour system. If you want to change to darkmode, try _options->style_ instead. Or, if you know what you are doing, make sure you flip the "override" checkbox in _options->colours_ and then try this again.' )
|
||||
|
||||
|
||||
current_colourset = self._new_options.GetString( 'current_colourset' )
|
||||
|
||||
if current_colourset == 'darkmode':
|
||||
|
|
|
@ -248,7 +248,7 @@ class EditShortcutSetPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
if addee_shortcut not in all_existing_shortcuts:
|
||||
|
||||
add_rows.append( [ ( addee_shortcut, command ) ] )
|
||||
add_rows.append( ( addee_shortcut, command ) )
|
||||
|
||||
all_existing_shortcuts.add( addee_shortcut )
|
||||
|
||||
|
|
|
@ -1343,7 +1343,7 @@ class ShortcutSet( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
def GetShortcutsAndCommands( self ):
|
||||
|
||||
return list( self )
|
||||
return list( self._shortcuts_to_commands.items() )
|
||||
|
||||
|
||||
def HasCommand( self, shortcut: Shortcut ):
|
||||
|
|
|
@ -137,6 +137,8 @@ class StringMatchButton( ClientGUICommon.BetterButton ):
|
|||
|
||||
class StringProcessorButton( ClientGUICommon.BetterButton ):
|
||||
|
||||
valueChanged = QC.Signal()
|
||||
|
||||
def __init__( self, parent, string_processor: ClientStrings.StringProcessor, test_data_callable: typing.Callable[ [], ClientParsing.ParsingTestData ] ):
|
||||
|
||||
ClientGUICommon.BetterButton.__init__( self, parent, 'edit string processor', self._Edit )
|
||||
|
@ -163,6 +165,8 @@ class StringProcessorButton( ClientGUICommon.BetterButton ):
|
|||
|
||||
self._UpdateLabel()
|
||||
|
||||
self.valueChanged.emit()
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -926,8 +926,10 @@ class EditSubscriptionPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
if len( DEAD_query_headers ) > 0:
|
||||
|
||||
DEAD_query_header_texts = [ query_header.GetQueryText() for query_header in DEAD_query_headers ]
|
||||
|
||||
message += '\n' * 2
|
||||
message += f'The DEAD queries{HydrusText.ConvertManyStringsToNiceInsertableHumanSummary(DEAD_query_headers)}were revived.'
|
||||
message += f'The DEAD queries{HydrusText.ConvertManyStringsToNiceInsertableHumanSummary(DEAD_query_header_texts)}were revived.'
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1431,6 +1431,20 @@ class EditTagFilterPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
|
||||
|
||||
tag_repositories = CG.client_controller.services_manager.GetServices( ( HC.TAG_REPOSITORY, ) )
|
||||
|
||||
if len( tag_repositories ) > 0:
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
for service in sorted( tag_repositories, key = lambda s: s.GetName() ):
|
||||
|
||||
tag_filter = service.GetTagFilter()
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( menu, f'tag filter for "{service.GetName()}"', 'load the serverside tag filter for this service', self.SetValue, tag_filter )
|
||||
|
||||
|
||||
|
||||
CGC.core().PopupMenu( self, menu )
|
||||
|
||||
|
||||
|
|
|
@ -143,9 +143,19 @@ def AddAudioVolumeMenu( menu, canvas_type ):
|
|||
|
||||
class CanvasBackgroundColourGenerator( object ):
|
||||
|
||||
def __init__( self, my_canvas ):
|
||||
|
||||
self._my_canvas = my_canvas
|
||||
|
||||
|
||||
def _GetColourFromOptions( self ):
|
||||
|
||||
return self._my_canvas.GetColour( CC.COLOUR_MEDIA_BACKGROUND )
|
||||
|
||||
|
||||
def GetColour( self ) -> QG.QColor:
|
||||
|
||||
return CG.client_controller.new_options.GetColour( CC.COLOUR_MEDIA_BACKGROUND )
|
||||
return self._GetColourFromOptions()
|
||||
|
||||
|
||||
def CanDoTransparencyCheckerboard( self ) -> bool:
|
||||
|
@ -156,13 +166,6 @@ class CanvasBackgroundColourGenerator( object ):
|
|||
|
||||
class CanvasBackgroundColourGeneratorDuplicates( CanvasBackgroundColourGenerator ):
|
||||
|
||||
def __init__( self, duplicate_canvas ):
|
||||
|
||||
CanvasBackgroundColourGenerator.__init__( self )
|
||||
|
||||
self._duplicate_canvas = duplicate_canvas
|
||||
|
||||
|
||||
def CanDoTransparencyCheckerboard( self ) -> bool:
|
||||
|
||||
return CG.client_controller.new_options.GetBoolean( 'draw_transparency_checkerboard_media_canvas' ) or CG.client_controller.new_options.GetBoolean( 'draw_transparency_checkerboard_media_canvas_duplicates' )
|
||||
|
@ -172,11 +175,11 @@ class CanvasBackgroundColourGeneratorDuplicates( CanvasBackgroundColourGenerator
|
|||
|
||||
new_options = CG.client_controller.new_options
|
||||
|
||||
normal_colour = new_options.GetColour( CC.COLOUR_MEDIA_BACKGROUND )
|
||||
normal_colour = self._GetColourFromOptions()
|
||||
|
||||
if self._duplicate_canvas.IsShowingAPair():
|
||||
if self._my_canvas.IsShowingAPair():
|
||||
|
||||
if self._duplicate_canvas.IsShowingFileA():
|
||||
if self._my_canvas.IsShowingFileA():
|
||||
|
||||
duplicate_intensity = new_options.GetNoneableInteger( 'duplicate_background_switch_intensity_a' )
|
||||
|
||||
|
@ -315,14 +318,21 @@ class Canvas( CAC.ApplicationCommandProcessorMixin, QW.QWidget ):
|
|||
|
||||
def __init__( self, parent, location_context: ClientLocation.LocationContext ):
|
||||
|
||||
self._qss_colours = {
|
||||
CC.COLOUR_MEDIA_BACKGROUND : QG.QColor( 255, 255, 255 ),
|
||||
CC.COLOUR_MEDIA_TEXT : QG.QColor( 0, 0, 0 )
|
||||
}
|
||||
|
||||
QW.QWidget.__init__( self, parent )
|
||||
CAC.ApplicationCommandProcessorMixin.__init__( self )
|
||||
|
||||
self.setObjectName( 'HydrusMediaViewer' )
|
||||
|
||||
self.setSizePolicy( QW.QSizePolicy.Expanding, QW.QSizePolicy.Expanding )
|
||||
|
||||
self._location_context = location_context
|
||||
|
||||
self._background_colour_generator = CanvasBackgroundColourGenerator()
|
||||
self._background_colour_generator = CanvasBackgroundColourGenerator( self )
|
||||
|
||||
self._current_media_start_time_ms = HydrusTime.GetNowMS()
|
||||
|
||||
|
@ -705,6 +715,18 @@ class Canvas( CAC.ApplicationCommandProcessorMixin, QW.QWidget ):
|
|||
return self._my_shortcuts_handler.GetCustomShortcutNames()
|
||||
|
||||
|
||||
def GetColour( self, colour_type ):
|
||||
|
||||
if self._new_options.GetBoolean( 'override_stylesheet_colours' ):
|
||||
|
||||
return self._new_options.GetColour( colour_type )
|
||||
|
||||
else:
|
||||
|
||||
return self._qss_colours.get( colour_type, QG.QColor( 127, 127, 127 ) )
|
||||
|
||||
|
||||
|
||||
def ManageNotes( self, canvas_key, name_to_start_on = None ):
|
||||
|
||||
if canvas_key == self._canvas_key:
|
||||
|
@ -1313,6 +1335,29 @@ class Canvas( CAC.ApplicationCommandProcessorMixin, QW.QWidget ):
|
|||
|
||||
|
||||
|
||||
def get_hmv_background( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_MEDIA_BACKGROUND ]
|
||||
|
||||
|
||||
def get_hmv_text( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_MEDIA_TEXT ]
|
||||
|
||||
|
||||
def set_hmv_background( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_MEDIA_BACKGROUND ] = colour
|
||||
|
||||
|
||||
def set_hmv_text( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_MEDIA_TEXT ] = colour
|
||||
|
||||
|
||||
hmv_background = QC.Property( QG.QColor, get_hmv_background, set_hmv_background )
|
||||
hmv_text = QC.Property( QG.QColor, get_hmv_text, set_hmv_text )
|
||||
|
||||
|
||||
class MediaContainerDragClickReportingFilter( QC.QObject ):
|
||||
|
||||
|
@ -1843,7 +1888,9 @@ class CanvasWithDetails( Canvas ):
|
|||
|
||||
# top-middle
|
||||
|
||||
painter.setPen( QG.QPen( self._new_options.GetColour( CC.COLOUR_MEDIA_TEXT ) ) )
|
||||
pen_colour = self.GetColour( CC.COLOUR_MEDIA_TEXT )
|
||||
|
||||
painter.setPen( QG.QPen( pen_colour ) )
|
||||
|
||||
current_y = 3
|
||||
|
||||
|
@ -1971,7 +2018,9 @@ class CanvasWithDetails( Canvas ):
|
|||
current_y += 18
|
||||
|
||||
|
||||
painter.setPen( QG.QPen( self._new_options.GetColour( CC.COLOUR_MEDIA_TEXT ) ) )
|
||||
pen_colour = self.GetColour( CC.COLOUR_MEDIA_TEXT )
|
||||
|
||||
painter.setPen( QG.QPen( pen_colour ) )
|
||||
|
||||
# repo strings
|
||||
|
||||
|
|
|
@ -879,7 +879,7 @@ class AnimationBar( QW.QWidget ):
|
|||
|
||||
QW.QWidget.__init__( self, parent )
|
||||
|
||||
self._colours = {
|
||||
self._qss_colours = {
|
||||
'hab_border' : QG.QColor( 0, 0, 0 ),
|
||||
'hab_background' : QG.QColor( 240, 240, 240 ),
|
||||
'hab_nub' : QG.QColor( 96, 96, 96 )
|
||||
|
@ -907,7 +907,7 @@ class AnimationBar( QW.QWidget ):
|
|||
|
||||
self.setProperty( 'playing', False )
|
||||
|
||||
background_colour = self._colours[ 'hab_background' ]
|
||||
background_colour = self._qss_colours[ 'hab_background' ]
|
||||
|
||||
painter.setBackground( background_colour )
|
||||
|
||||
|
@ -963,7 +963,7 @@ class AnimationBar( QW.QWidget ):
|
|||
my_width = self.size().width()
|
||||
my_height = self.size().height()
|
||||
|
||||
background_colour = self._colours[ 'hab_background' ]
|
||||
background_colour = self._qss_colours[ 'hab_background' ]
|
||||
|
||||
if paused:
|
||||
|
||||
|
@ -1039,7 +1039,7 @@ class AnimationBar( QW.QWidget ):
|
|||
|
||||
if nub_x is not None:
|
||||
|
||||
painter.fillRect( nub_x, 0, animated_scanbar_nub_width, my_height, self._colours[ 'hab_nub' ] )
|
||||
painter.fillRect( nub_x, 0, animated_scanbar_nub_width, my_height, self._qss_colours[ 'hab_nub' ] )
|
||||
|
||||
|
||||
#
|
||||
|
@ -1075,7 +1075,7 @@ class AnimationBar( QW.QWidget ):
|
|||
|
||||
painter.setBrush( QC.Qt.NoBrush )
|
||||
|
||||
painter.setPen( QG.QPen( self._colours[ 'hab_border' ] ) )
|
||||
painter.setPen( QG.QPen( self._qss_colours[ 'hab_border' ] ) )
|
||||
|
||||
painter.drawRect( 0, 0, my_width - 1, my_height - 1 )
|
||||
|
||||
|
@ -1260,32 +1260,32 @@ class AnimationBar( QW.QWidget ):
|
|||
|
||||
def get_hab_background( self ):
|
||||
|
||||
return self._colours[ 'hab_background' ]
|
||||
return self._qss_colours[ 'hab_background' ]
|
||||
|
||||
|
||||
def get_hab_border( self ):
|
||||
|
||||
return self._colours[ 'hab_border' ]
|
||||
return self._qss_colours[ 'hab_border' ]
|
||||
|
||||
|
||||
def get_hab_nub( self ):
|
||||
|
||||
return self._colours[ 'hab_nub' ]
|
||||
return self._qss_colours[ 'hab_nub' ]
|
||||
|
||||
|
||||
def set_hab_background( self, colour ):
|
||||
|
||||
self._colours[ 'hab_background' ] = colour
|
||||
self._qss_colours[ 'hab_background' ] = colour
|
||||
|
||||
|
||||
def set_hab_border( self, colour ):
|
||||
|
||||
self._colours[ 'hab_border' ] = colour
|
||||
self._qss_colours[ 'hab_border' ] = colour
|
||||
|
||||
|
||||
def set_hab_nub( self, colour ):
|
||||
|
||||
self._colours[ 'hab_nub' ] = colour
|
||||
self._qss_colours[ 'hab_nub' ] = colour
|
||||
|
||||
|
||||
hab_border = QC.Property( QG.QColor, get_hab_border, set_hab_border )
|
||||
|
|
|
@ -21,6 +21,7 @@ from hydrus.client import ClientGlobals as CG
|
|||
from hydrus.client import ClientLocation
|
||||
from hydrus.client import ClientThreading
|
||||
from hydrus.client.exporting import ClientExportingFiles
|
||||
from hydrus.client.gui import ClientGUIAsync
|
||||
from hydrus.client.gui import ClientGUIDialogsMessage
|
||||
from hydrus.client.gui import ClientGUIDialogsQuick
|
||||
from hydrus.client.gui import ClientGUIFunctions
|
||||
|
@ -30,10 +31,12 @@ from hydrus.client.gui.lists import ClientGUIListBoxes
|
|||
from hydrus.client.gui.lists import ClientGUIListConstants as CGLC
|
||||
from hydrus.client.gui.lists import ClientGUIListCtrl
|
||||
from hydrus.client.gui.metadata import ClientGUIMetadataMigration
|
||||
from hydrus.client.gui.metadata import ClientGUIMetadataMigrationTest
|
||||
from hydrus.client.gui.metadata import ClientGUITime
|
||||
from hydrus.client.gui.panels import ClientGUIScrolledPanels
|
||||
from hydrus.client.gui.search import ClientGUIACDropdown
|
||||
from hydrus.client.gui.widgets import ClientGUICommon
|
||||
from hydrus.client.media import ClientMedia
|
||||
from hydrus.client.media import ClientMediaFileFilter
|
||||
from hydrus.client.metadata import ClientContentUpdates
|
||||
from hydrus.client.metadata import ClientMetadataMigrationExporters
|
||||
|
@ -301,8 +304,11 @@ class EditExportFolderPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
metadata_routers = export_folder.GetMetadataRouters()
|
||||
allowed_importer_classes = [ ClientMetadataMigrationImporters.SingleFileMetadataImporterMediaTags, ClientMetadataMigrationImporters.SingleFileMetadataImporterMediaNotes, ClientMetadataMigrationImporters.SingleFileMetadataImporterMediaURLs, ClientMetadataMigrationImporters.SingleFileMetadataImporterMediaTimestamps ]
|
||||
allowed_exporter_classes = [ ClientMetadataMigrationExporters.SingleFileMetadataExporterTXT, ClientMetadataMigrationExporters.SingleFileMetadataExporterJSON ]
|
||||
self._test_context_factory = ClientGUIMetadataMigrationTest.MigrationTestContextFactoryMedia( [] )
|
||||
|
||||
self._metadata_routers_button = ClientGUIMetadataMigration.SingleFileMetadataRoutersButton( self._metadata_routers_box, metadata_routers, allowed_importer_classes, allowed_exporter_classes )
|
||||
self._metadata_routers_button = ClientGUIMetadataMigration.SingleFileMetadataRoutersButton( self._metadata_routers_box, metadata_routers, allowed_importer_classes, allowed_exporter_classes, self._test_context_factory )
|
||||
|
||||
self._update_test_context_factory_button = ClientGUICommon.BetterButton( self._metadata_routers_box, 'update test example files', self._UpdateTestExampleFiles )
|
||||
|
||||
#
|
||||
|
||||
|
@ -381,6 +387,7 @@ If you select synchronise, be careful!'''
|
|||
self._phrase_box.Add( phrase_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
|
||||
self._metadata_routers_box.Add( self._metadata_routers_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
self._metadata_routers_box.Add( self._update_test_context_factory_button, CC.FLAGS_ON_RIGHT )
|
||||
|
||||
vbox = QP.VBoxLayout()
|
||||
|
||||
|
@ -400,6 +407,17 @@ If you select synchronise, be careful!'''
|
|||
self._delete_from_client_after_export.clicked.connect( self.EventDeleteFilesAfterExport )
|
||||
self._run_regularly.clicked.connect( self._UpdateRunRegularly )
|
||||
|
||||
self._tag_autocomplete.searchChanged.connect( self._SearchUpdated )
|
||||
|
||||
self._SearchUpdated()
|
||||
|
||||
|
||||
def _SearchUpdated( self ):
|
||||
|
||||
self._update_test_context_factory_button.setText( 'update test example files' )
|
||||
|
||||
self._update_test_context_factory_button.setEnabled( True )
|
||||
|
||||
|
||||
def _UpdateRunRegularly( self ):
|
||||
|
||||
|
@ -409,6 +427,39 @@ If you select synchronise, be careful!'''
|
|||
self._show_working_popup.setEnabled( run_regularly )
|
||||
|
||||
|
||||
def _UpdateTestExampleFiles( self ):
|
||||
|
||||
file_search_context = self._tag_autocomplete.GetFileSearchContext()
|
||||
|
||||
def work_callable():
|
||||
|
||||
sort_by = ClientMedia.MediaSort( ( 'system', CC.SORT_FILES_BY_FILESIZE ), CC.SORT_ASC )
|
||||
|
||||
query_hash_ids = CG.client_controller.Read( 'file_query_ids', file_search_context, limit_sort_by = sort_by )
|
||||
|
||||
query_hash_ids = list( query_hash_ids )[:ClientGUIMetadataMigrationTest.HOW_MANY_EXAMPLE_OBJECTS_TO_USE]
|
||||
|
||||
media_results = CG.client_controller.Read( 'media_results_from_ids', query_hash_ids )
|
||||
|
||||
return media_results
|
||||
|
||||
|
||||
def publish_callable( media_results ):
|
||||
|
||||
self._test_context_factory.SetExampleMediaResults( media_results )
|
||||
|
||||
self._update_test_context_factory_button.setText( f'got {HydrusNumbers.ToHumanInt(len( media_results))} files!' )
|
||||
|
||||
|
||||
self._update_test_context_factory_button.setEnabled( False )
|
||||
|
||||
self._update_test_context_factory_button.setText( 'loading' + HC.UNICODE_ELLIPSIS )
|
||||
|
||||
async_job = ClientGUIAsync.AsyncQtJob( self, work_callable, publish_callable )
|
||||
|
||||
async_job.start()
|
||||
|
||||
|
||||
def _UpdateTypeDeleteUI( self ):
|
||||
|
||||
if self._type.GetValue() == HC.EXPORT_FOLDER_TYPE_SYNCHRONISE:
|
||||
|
@ -531,8 +582,6 @@ class ReviewExportFilesPanel( ClientGUIScrolledPanels.ReviewPanel ):
|
|||
|
||||
self._tags_box = ClientGUIListBoxes.StaticBoxSorterForListBoxTags( self, 'files\' tags', tag_presentation_location )
|
||||
|
||||
services_manager = CG.client_controller.services_manager
|
||||
|
||||
t = ClientGUIListBoxes.ListBoxTagsMedia( self._tags_box, ClientTags.TAG_DISPLAY_DISPLAY_ACTUAL, tag_presentation_location, include_counts = True )
|
||||
|
||||
self._tags_box.SetTagsBox( t )
|
||||
|
@ -575,7 +624,11 @@ class ReviewExportFilesPanel( ClientGUIScrolledPanels.ReviewPanel ):
|
|||
allowed_importer_classes = [ ClientMetadataMigrationImporters.SingleFileMetadataImporterMediaTags, ClientMetadataMigrationImporters.SingleFileMetadataImporterMediaNotes, ClientMetadataMigrationImporters.SingleFileMetadataImporterMediaURLs, ClientMetadataMigrationImporters.SingleFileMetadataImporterMediaTimestamps ]
|
||||
allowed_exporter_classes = [ ClientMetadataMigrationExporters.SingleFileMetadataExporterTXT, ClientMetadataMigrationExporters.SingleFileMetadataExporterJSON ]
|
||||
|
||||
self._metadata_routers_button = ClientGUIMetadataMigration.SingleFileMetadataRoutersButton( self, metadata_routers, allowed_importer_classes, allowed_exporter_classes )
|
||||
example_media_results = [ m.GetMediaResult() for m in list( flat_media )[:ClientGUIMetadataMigrationTest.HOW_MANY_EXAMPLE_OBJECTS_TO_USE] ]
|
||||
|
||||
test_context_factory = ClientGUIMetadataMigrationTest.MigrationTestContextFactoryMedia( example_media_results )
|
||||
|
||||
self._metadata_routers_button = ClientGUIMetadataMigration.SingleFileMetadataRoutersButton( self, metadata_routers, allowed_importer_classes, allowed_exporter_classes, test_context_factory )
|
||||
|
||||
self._export = QW.QPushButton( 'export', self )
|
||||
self._export.clicked.connect( self._DoExport )
|
||||
|
|
|
@ -29,6 +29,7 @@ from hydrus.client.gui.lists import ClientGUIListBoxes
|
|||
from hydrus.client.gui.lists import ClientGUIListConstants as CGLC
|
||||
from hydrus.client.gui.lists import ClientGUIListCtrl
|
||||
from hydrus.client.gui.metadata import ClientGUIMetadataMigration
|
||||
from hydrus.client.gui.metadata import ClientGUIMetadataMigrationTest
|
||||
from hydrus.client.gui.metadata import ClientGUITime
|
||||
from hydrus.client.gui.networking import ClientGUINetworkJobControl
|
||||
from hydrus.client.gui.panels import ClientGUIScrolledPanels
|
||||
|
@ -1070,8 +1071,9 @@ class EditLocalImportFilenameTaggingPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
allowed_importer_classes = [ ClientMetadataMigrationImporters.SingleFileMetadataImporterTXT, ClientMetadataMigrationImporters.SingleFileMetadataImporterJSON ]
|
||||
allowed_exporter_classes = [ ClientMetadataMigrationExporters.SingleFileMetadataExporterMediaTags, ClientMetadataMigrationExporters.SingleFileMetadataExporterMediaNotes, ClientMetadataMigrationExporters.SingleFileMetadataExporterMediaURLs, ClientMetadataMigrationExporters.SingleFileMetadataExporterMediaTimestamps ]
|
||||
test_context_factory = ClientGUIMetadataMigrationTest.MigrationTestContextFactorySidecar( self._paths[ : ClientGUIMetadataMigrationTest.HOW_MANY_EXAMPLE_OBJECTS_TO_USE ] )
|
||||
|
||||
self._metadata_routers_panel = ClientGUIMetadataMigration.SingleFileMetadataRoutersControl( self, metadata_routers, allowed_importer_classes, allowed_exporter_classes )
|
||||
self._metadata_routers_panel = ClientGUIMetadataMigration.SingleFileMetadataRoutersControl( self, metadata_routers, allowed_importer_classes, allowed_exporter_classes, test_context_factory )
|
||||
|
||||
#
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ from hydrus.client.gui.importing import ClientGUIImportOptions
|
|||
from hydrus.client.gui.lists import ClientGUIListConstants as CGLC
|
||||
from hydrus.client.gui.lists import ClientGUIListCtrl
|
||||
from hydrus.client.gui.metadata import ClientGUIMetadataMigration
|
||||
from hydrus.client.gui.metadata import ClientGUIMetadataMigrationTest
|
||||
from hydrus.client.gui.metadata import ClientGUITime
|
||||
from hydrus.client.gui.panels import ClientGUIScrolledPanels
|
||||
from hydrus.client.gui.widgets import ClientGUICommon
|
||||
|
@ -260,9 +261,9 @@ class EditImportFolderPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
allowed_importer_classes = [ ClientMetadataMigrationImporters.SingleFileMetadataImporterTXT, ClientMetadataMigrationImporters.SingleFileMetadataImporterJSON ]
|
||||
allowed_exporter_classes = [ ClientMetadataMigrationExporters.SingleFileMetadataExporterMediaTags, ClientMetadataMigrationExporters.SingleFileMetadataExporterMediaNotes, ClientMetadataMigrationExporters.SingleFileMetadataExporterMediaURLs, ClientMetadataMigrationExporters.SingleFileMetadataExporterMediaTimestamps ]
|
||||
|
||||
self._metadata_routers_button = ClientGUIMetadataMigration.SingleFileMetadataRoutersButton( self, metadata_routers, allowed_importer_classes, allowed_exporter_classes )
|
||||
self._sidecar_test_context_factory = ClientGUIMetadataMigrationTest.MigrationTestContextFactorySidecar( [] )
|
||||
|
||||
services_manager = CG.client_controller.services_manager
|
||||
self._metadata_routers_button = ClientGUIMetadataMigration.SingleFileMetadataRoutersButton( self, metadata_routers, allowed_importer_classes, allowed_exporter_classes, self._sidecar_test_context_factory )
|
||||
|
||||
#
|
||||
|
||||
|
@ -379,6 +380,10 @@ class EditImportFolderPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
self._UpdateCheckRegularly()
|
||||
|
||||
self._path.dirPickerChanged.connect( self._PathChanged )
|
||||
|
||||
self._PathChanged()
|
||||
|
||||
|
||||
def _AddFilenameTaggingOptions( self ):
|
||||
|
||||
|
@ -601,6 +606,27 @@ class EditImportFolderPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
self._filename_tagging_options.SelectDatas( edited_datas )
|
||||
|
||||
|
||||
def _PathChanged( self ):
|
||||
|
||||
path = self._path.GetPath()
|
||||
|
||||
try:
|
||||
|
||||
if os.path.exists( path ) and os.path.isdir( path ):
|
||||
|
||||
filenames = list( os.listdir( path ) )[:ClientGUIMetadataMigrationTest.HOW_MANY_EXAMPLE_OBJECTS_TO_USE]
|
||||
|
||||
example_paths = [ os.path.join( path, filename ) for filename in filenames ]
|
||||
|
||||
self._sidecar_test_context_factory.SetExampleFilePaths( example_paths )
|
||||
|
||||
|
||||
except:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def _UpdateCheckRegularly( self ):
|
||||
|
||||
if self._check_regularly.isChecked():
|
||||
|
|
|
@ -1070,8 +1070,6 @@ class ListBox( QW.QScrollArea ):
|
|||
self.setWidget( ListBox._InnerWidget( self ) )
|
||||
self.setWidgetResizable( True )
|
||||
|
||||
self._background_colour = QG.QColor( 255, 255, 255 )
|
||||
|
||||
self._ordered_terms = []
|
||||
self._terms_to_logical_indices = {}
|
||||
self._terms_to_positional_indices = {}
|
||||
|
@ -1295,6 +1293,11 @@ class ListBox( QW.QScrollArea ):
|
|||
self._selected_terms = set()
|
||||
|
||||
|
||||
def _GetBackgroundColour( self ):
|
||||
|
||||
return QG.QColor( 255, 255, 255 )
|
||||
|
||||
|
||||
def _GetLogicalIndexFromTerm( self, term ):
|
||||
|
||||
if term in self._terms_to_logical_indices:
|
||||
|
@ -1775,7 +1778,9 @@ class ListBox( QW.QScrollArea ):
|
|||
|
||||
def _Redraw( self, painter ):
|
||||
|
||||
painter.setBackground( QG.QBrush( self._background_colour ) )
|
||||
bg_colour = self._GetBackgroundColour()
|
||||
|
||||
painter.setBackground( QG.QBrush( bg_colour ) )
|
||||
|
||||
painter.eraseRect( painter.viewport() )
|
||||
|
||||
|
@ -1889,7 +1894,9 @@ class ListBox( QW.QScrollArea ):
|
|||
painter.fillRect( background_colour_x, y_top, rect_width, text_height, namespace_colour )
|
||||
|
||||
|
||||
text_pen = QG.QPen( self._background_colour )
|
||||
pen_colour = self._GetBackgroundColour()
|
||||
|
||||
text_pen = QG.QPen( pen_colour )
|
||||
|
||||
else:
|
||||
|
||||
|
@ -2444,10 +2451,16 @@ class ListBoxTags( ListBox ):
|
|||
|
||||
self._tag_display_type = tag_display_type
|
||||
|
||||
self._qss_colours = {
|
||||
CC.COLOUR_TAGS_BOX : QG.QColor( 255, 255, 255 ),
|
||||
}
|
||||
|
||||
terms_may_have_sibling_or_parent_info = self._tag_display_type == ClientTags.TAG_DISPLAY_STORAGE
|
||||
|
||||
ListBox.__init__( self, parent, terms_may_have_sibling_or_parent_info, *args, **kwargs )
|
||||
|
||||
self.setObjectName( 'HydrusTagList' )
|
||||
|
||||
if terms_may_have_sibling_or_parent_info:
|
||||
|
||||
self._show_parent_decorators = CG.client_controller.new_options.GetBoolean( 'show_parent_decorators_on_storage_taglists' )
|
||||
|
@ -2539,6 +2552,20 @@ class ListBoxTags( ListBox ):
|
|||
return False
|
||||
|
||||
|
||||
def _GetBackgroundColour( self ):
|
||||
|
||||
new_options = CG.client_controller.new_options
|
||||
|
||||
if new_options.GetBoolean( 'override_stylesheet_colours' ):
|
||||
|
||||
return new_options.GetColour( CC.COLOUR_TAGS_BOX )
|
||||
|
||||
else:
|
||||
|
||||
return self._qss_colours.get( CC.COLOUR_TAGS_BOX, QG.QColor( 127, 127, 127 ) )
|
||||
|
||||
|
||||
|
||||
def _GetRowsOfTextsAndColours( self, term: ClientGUIListBoxesData.ListBoxItem ):
|
||||
|
||||
namespace_colours = self._GetNamespaceColours()
|
||||
|
@ -2733,10 +2760,6 @@ class ListBoxTags( ListBox ):
|
|||
|
||||
def _UpdateBackgroundColour( self ):
|
||||
|
||||
new_options = CG.client_controller.new_options
|
||||
|
||||
self._background_colour = new_options.GetColour( CC.COLOUR_TAGS_BOX )
|
||||
|
||||
self.widget().update()
|
||||
|
||||
|
||||
|
@ -3596,6 +3619,19 @@ class ListBoxTags( ListBox ):
|
|||
pass
|
||||
|
||||
|
||||
def get_htl_background( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_TAGS_BOX ]
|
||||
|
||||
|
||||
def set_htl_background( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_TAGS_BOX ] = colour
|
||||
|
||||
|
||||
htl_background = QC.Property( QG.QColor, get_htl_background, set_htl_background )
|
||||
|
||||
|
||||
class ListBoxTagsPredicates( ListBoxTags ):
|
||||
|
||||
def __init__( self, *args, tag_display_type = ClientTags.TAG_DISPLAY_DISPLAY_ACTUAL, **kwargs ):
|
||||
|
|
|
@ -1565,3 +1565,20 @@ register_column_type( COLUMN_LIST_DEFERRED_DELETE_TABLE_DATA.ID, COLUMN_LIST_DEF
|
|||
register_column_type( COLUMN_LIST_DEFERRED_DELETE_TABLE_DATA.ID, COLUMN_LIST_DEFERRED_DELETE_TABLE_DATA.ROWS, 'num rows', False, 12, True )
|
||||
|
||||
default_column_list_sort_lookup[ COLUMN_LIST_DEFERRED_DELETE_TABLE_DATA.ID ] = ( COLUMN_LIST_DEFERRED_DELETE_TABLE_DATA.NAME, True )
|
||||
|
||||
class COLUMN_LIST_METADATA_ROUTER_TEST_RESULTS( COLUMN_LIST_DEFINITION ):
|
||||
|
||||
ID = 73
|
||||
|
||||
TEST_OBJECT = 0
|
||||
IMPORTER_STRINGS = 1
|
||||
PROCESSED_STRINGS = 2
|
||||
|
||||
|
||||
column_list_type_name_lookup[ COLUMN_LIST_METADATA_ROUTER_TEST_RESULTS.ID ] = 'metadata router test results'
|
||||
|
||||
register_column_type( COLUMN_LIST_METADATA_ROUTER_TEST_RESULTS.ID, COLUMN_LIST_METADATA_ROUTER_TEST_RESULTS.TEST_OBJECT, 'source item', False, 32, True )
|
||||
register_column_type( COLUMN_LIST_METADATA_ROUTER_TEST_RESULTS.ID, COLUMN_LIST_METADATA_ROUTER_TEST_RESULTS.IMPORTER_STRINGS, 'sourced strings', False, 48, True )
|
||||
register_column_type( COLUMN_LIST_METADATA_ROUTER_TEST_RESULTS.ID, COLUMN_LIST_METADATA_ROUTER_TEST_RESULTS.PROCESSED_STRINGS, 'processed strings', False, 48, True )
|
||||
|
||||
default_column_list_sort_lookup[ COLUMN_LIST_METADATA_ROUTER_TEST_RESULTS.ID ] = ( COLUMN_LIST_METADATA_ROUTER_TEST_RESULTS.TEST_OBJECT, True )
|
||||
|
|
|
@ -16,8 +16,11 @@ from hydrus.client.gui import ClientGUIStringControls
|
|||
from hydrus.client.gui import ClientGUITopLevelWindowsPanels
|
||||
from hydrus.client.gui import QtPorting as QP
|
||||
from hydrus.client.gui.lists import ClientGUIListBoxes
|
||||
from hydrus.client.gui.lists import ClientGUIListConstants as CGLC
|
||||
from hydrus.client.gui.lists import ClientGUIListCtrl
|
||||
from hydrus.client.gui.metadata import ClientGUIMetadataMigrationExporters
|
||||
from hydrus.client.gui.metadata import ClientGUIMetadataMigrationImporters
|
||||
from hydrus.client.gui.metadata import ClientGUIMetadataMigrationTest
|
||||
from hydrus.client.gui.panels import ClientGUIScrolledPanels
|
||||
from hydrus.client.gui.widgets import ClientGUICommon
|
||||
from hydrus.client.metadata import ClientMetadataMigration
|
||||
|
@ -25,13 +28,14 @@ from hydrus.client.metadata import ClientMetadataMigrationExporters
|
|||
|
||||
class EditSingleFileMetadataRouterPanel( ClientGUIScrolledPanels.EditPanel ):
|
||||
|
||||
def __init__( self, parent: QW.QWidget, router: ClientMetadataMigration.SingleFileMetadataRouter, allowed_importer_classes: list, allowed_exporter_classes: list ):
|
||||
def __init__( self, parent: QW.QWidget, router: ClientMetadataMigration.SingleFileMetadataRouter, allowed_importer_classes: list, allowed_exporter_classes: list, test_context_factory: ClientGUIMetadataMigrationTest.MigrationTestContextFactory ):
|
||||
|
||||
ClientGUIScrolledPanels.EditPanel.__init__( self, parent )
|
||||
|
||||
self._original_router = router
|
||||
self._allowed_importer_classes = allowed_importer_classes
|
||||
self._allowed_exporter_classes = allowed_exporter_classes
|
||||
self._test_context_factory = test_context_factory
|
||||
|
||||
importers = self._original_router.GetImporters()
|
||||
string_processor = self._original_router.GetStringProcessor()
|
||||
|
@ -66,13 +70,60 @@ class EditSingleFileMetadataRouterPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
#
|
||||
|
||||
self._test_panel = ClientGUICommon.StaticBox( self, 'testing' )
|
||||
|
||||
self._test_panel_help_st = ClientGUICommon.BetterStaticText( self._test_panel, 'Add a source and this will show test data.' )
|
||||
self._test_notebook = ClientGUICommon.BetterNotebook( self._test_panel )
|
||||
|
||||
#
|
||||
|
||||
self._test_panel.Add( self._test_notebook, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
self._test_panel.Add( self._test_panel_help_st, CC.FLAGS_CENTER_PERPENDICULAR )
|
||||
|
||||
vbox = QP.VBoxLayout()
|
||||
|
||||
QP.AddToLayout( vbox, self._importers_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
QP.AddToLayout( vbox, self._processing_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
QP.AddToLayout( vbox, self._exporter_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
self.widget().setLayout( vbox )
|
||||
hbox = QP.HBoxLayout()
|
||||
|
||||
QP.AddToLayout( hbox, vbox, CC.FLAGS_EXPAND_BOTH_WAYS_POLITE )
|
||||
QP.AddToLayout( hbox, self._test_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
self.widget().setLayout( hbox )
|
||||
|
||||
self._importers_list.listBoxChanged.connect( self._UpdateTestPanel )
|
||||
self._string_processor_button.valueChanged.connect( self._UpdateTestPanel )
|
||||
|
||||
self._UpdateTestPanel()
|
||||
|
||||
|
||||
def _ConvertTestRowToListCtrlTuples( self, test_row ):
|
||||
|
||||
( importer, test_object ) = test_row
|
||||
|
||||
string_processor = self._string_processor_button.GetValue()
|
||||
|
||||
test_object_pretty = self._test_context_factory.GetTestObjectString( test_object )
|
||||
importer_strings_output = sorted( self._test_context_factory.GetExampleTestStrings( importer, test_object ) )
|
||||
|
||||
if string_processor.MakesChanges():
|
||||
|
||||
processed_strings_output = string_processor.ProcessStrings( importer_strings_output )
|
||||
|
||||
else:
|
||||
|
||||
processed_strings_output = [ 'no changes' ]
|
||||
|
||||
|
||||
pretty_importer_strings_output = ', '.join( importer_strings_output )
|
||||
pretty_processed_strings_output = ', '.join( processed_strings_output )
|
||||
|
||||
display_tuple = ( test_object_pretty, pretty_importer_strings_output, pretty_processed_strings_output )
|
||||
sort_tuple = ( test_object_pretty, len( importer_strings_output ), len( processed_strings_output ) )
|
||||
|
||||
return ( display_tuple, sort_tuple )
|
||||
|
||||
|
||||
def _GetExampleStringProcessorTestData( self ):
|
||||
|
@ -110,6 +161,50 @@ class EditSingleFileMetadataRouterPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
return router
|
||||
|
||||
|
||||
def _UpdateTestPanel( self ):
|
||||
|
||||
importers = self._importers_list.GetData()
|
||||
|
||||
while self._test_notebook.count() > len( importers ):
|
||||
|
||||
last_page_index = self._test_notebook.count() - 1
|
||||
|
||||
page = self._test_notebook.widget( last_page_index )
|
||||
|
||||
self._test_notebook.removeTab( last_page_index )
|
||||
|
||||
page.deleteLater()
|
||||
|
||||
|
||||
we_got_importers = len( self._importers_list.GetData() ) > 0
|
||||
|
||||
self._test_notebook.setVisible( we_got_importers )
|
||||
self._test_panel_help_st.setVisible( not we_got_importers )
|
||||
|
||||
for ( i, importer ) in enumerate( self._importers_list.GetData() ):
|
||||
|
||||
if self._test_notebook.count() < i + 1:
|
||||
|
||||
# make this our new listctrl
|
||||
list_ctrl = ClientGUIListCtrl.BetterListCtrl( self._test_notebook, CGLC.COLUMN_LIST_METADATA_ROUTER_TEST_RESULTS.ID, 11, self._ConvertTestRowToListCtrlTuples )
|
||||
|
||||
self._test_notebook.addTab( list_ctrl, 'init' )
|
||||
|
||||
|
||||
page_name = HydrusText.ElideText( importer.ToString(), 14 )
|
||||
|
||||
self._test_notebook.setTabText( i, page_name )
|
||||
|
||||
list_ctrl = self._test_notebook.widget( i )
|
||||
|
||||
test_objects = self._test_context_factory.GetTestObjects()
|
||||
|
||||
list_ctrl.SetData( [ ( importer, test_object ) for test_object in test_objects ] )
|
||||
|
||||
list_ctrl.UpdateDatas()
|
||||
|
||||
|
||||
|
||||
def GetValue( self ) -> ClientMetadataMigration.SingleFileMetadataRouter:
|
||||
|
||||
router = self._GetValue()
|
||||
|
@ -125,12 +220,13 @@ def convert_router_to_pretty_string( router: ClientMetadataMigration.SingleFileM
|
|||
|
||||
class SingleFileMetadataRoutersControl( ClientGUIListBoxes.AddEditDeleteListBox ):
|
||||
|
||||
def __init__( self, parent: QW.QWidget, routers: typing.Collection[ ClientMetadataMigration.SingleFileMetadataRouter ], allowed_importer_classes: list, allowed_exporter_classes: list ):
|
||||
def __init__( self, parent: QW.QWidget, routers: typing.Collection[ ClientMetadataMigration.SingleFileMetadataRouter ], allowed_importer_classes: list, allowed_exporter_classes: list, test_context_factory: ClientGUIMetadataMigrationTest.MigrationTestContextFactory ):
|
||||
|
||||
ClientGUIListBoxes.AddEditDeleteListBox.__init__( self, parent, 5, convert_router_to_pretty_string, self._AddRouter, self._EditRouter )
|
||||
|
||||
self._allowed_importer_classes = allowed_importer_classes
|
||||
self._allowed_exporter_classes = allowed_exporter_classes
|
||||
self._test_context_factory = test_context_factory
|
||||
|
||||
self.AddDatas( routers )
|
||||
|
||||
|
@ -197,7 +293,7 @@ class SingleFileMetadataRoutersControl( ClientGUIListBoxes.AddEditDeleteListBox
|
|||
|
||||
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit metadata migration router' ) as dlg:
|
||||
|
||||
panel = EditSingleFileMetadataRouterPanel( self, router, self._allowed_importer_classes, self._allowed_exporter_classes )
|
||||
panel = EditSingleFileMetadataRouterPanel( self, router, self._allowed_importer_classes, self._allowed_exporter_classes, self._test_context_factory )
|
||||
|
||||
dlg.SetPanel( panel )
|
||||
|
||||
|
@ -217,13 +313,14 @@ class SingleFileMetadataRoutersButton( QW.QPushButton ):
|
|||
|
||||
valueChanged = QC.Signal()
|
||||
|
||||
def __init__( self, parent: QW.QWidget, routers: typing.Collection[ ClientMetadataMigration.SingleFileMetadataRouter ], allowed_importer_classes: list, allowed_exporter_classes: list ):
|
||||
def __init__( self, parent: QW.QWidget, routers: typing.Collection[ ClientMetadataMigration.SingleFileMetadataRouter ], allowed_importer_classes: list, allowed_exporter_classes: list, test_context_factory: ClientGUIMetadataMigrationTest.MigrationTestContextFactory ):
|
||||
|
||||
QW.QPushButton.__init__( self, parent )
|
||||
|
||||
self._routers = routers
|
||||
self._allowed_importer_classes = allowed_importer_classes
|
||||
self._allowed_exporter_classes = allowed_exporter_classes
|
||||
self._test_context_factory = test_context_factory
|
||||
|
||||
self._RefreshLabel()
|
||||
|
||||
|
@ -236,7 +333,7 @@ class SingleFileMetadataRoutersButton( QW.QPushButton ):
|
|||
|
||||
panel = ClientGUIScrolledPanels.EditSingleCtrlPanel( dlg )
|
||||
|
||||
control = SingleFileMetadataRoutersControl( panel, self._routers, self._allowed_importer_classes, self._allowed_exporter_classes )
|
||||
control = SingleFileMetadataRoutersControl( panel, self._routers, self._allowed_importer_classes, self._allowed_exporter_classes, self._test_context_factory )
|
||||
|
||||
panel.SetControl( control )
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
import typing
|
||||
|
||||
from hydrus.client.media import ClientMediaResult
|
||||
from hydrus.client.metadata import ClientMetadataMigrationImporters
|
||||
|
||||
HOW_MANY_EXAMPLE_OBJECTS_TO_USE = 25
|
||||
|
||||
class MigrationTestContextFactory( object ):
|
||||
|
||||
def GetExampleTestStrings( self, importer: ClientMetadataMigrationImporters.SingleFileMetadataImporter, test_object: object ):
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def GetExampleTestStringGroups( self, importer: ClientMetadataMigrationImporters.SingleFileMetadataImporter ) -> typing.Collection[ typing.Tuple[ str, typing.Collection[ str ] ] ]:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def GetTestObjects( self ) -> typing.Collection[ object ]:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def GetTestObjectString( self, test_object: object ) -> str:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
|
||||
class MigrationTestContextFactorySidecar( MigrationTestContextFactory ):
|
||||
|
||||
def __init__( self, example_file_paths: typing.Collection[ str ] ):
|
||||
|
||||
MigrationTestContextFactory.__init__( self )
|
||||
|
||||
self._example_file_paths = example_file_paths
|
||||
|
||||
|
||||
def GetExampleTestStrings( self, importer: ClientMetadataMigrationImporters.SingleFileMetadataImporterSidecar, test_object: str ):
|
||||
|
||||
return importer.Import( test_object )
|
||||
|
||||
|
||||
def GetTestObjects( self ) -> typing.Collection[ str ]:
|
||||
|
||||
return self._example_file_paths
|
||||
|
||||
|
||||
def GetTestObjectString( self, test_object: str ) -> str:
|
||||
|
||||
return test_object
|
||||
|
||||
|
||||
def SetExampleFilePaths( self, paths: typing.Collection[ str ] ):
|
||||
|
||||
self._example_file_paths = paths
|
||||
|
||||
|
||||
|
||||
class MigrationTestContextFactoryMedia( MigrationTestContextFactory ):
|
||||
|
||||
def __init__( self, example_media_results: typing.Collection[ ClientMediaResult.MediaResult ] ):
|
||||
|
||||
MigrationTestContextFactory.__init__( self )
|
||||
|
||||
self._example_media_results = example_media_results
|
||||
|
||||
|
||||
def GetExampleTestStrings( self, importer: ClientMetadataMigrationImporters.SingleFileMetadataImporterMedia, test_object: ClientMediaResult.MediaResult ):
|
||||
|
||||
return importer.Import( test_object )
|
||||
|
||||
|
||||
def GetTestObjects( self ) -> typing.Collection[ ClientMediaResult.MediaResult ]:
|
||||
|
||||
return self._example_media_results
|
||||
|
||||
|
||||
def GetTestObjectString( self, test_object: ClientMediaResult.MediaResult ) -> str:
|
||||
|
||||
return test_object.GetHash().hex()
|
||||
|
||||
|
||||
def SetExampleMediaResults( self, media_results: typing.Collection[ ClientMediaResult.MediaResult ] ):
|
||||
|
||||
self._example_media_results = media_results
|
||||
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import collections
|
||||
import itertools
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
import typing
|
||||
|
@ -171,6 +170,20 @@ class MediaPanel( CAC.ApplicationCommandProcessorMixin, ClientMedia.ListeningMed
|
|||
|
||||
QW.QScrollArea.__init__( self, parent )
|
||||
|
||||
self._qss_colours = {
|
||||
CC.COLOUR_THUMBGRID_BACKGROUND : QG.QColor( 255, 255, 255 ),
|
||||
CC.COLOUR_THUMB_BACKGROUND : QG.QColor( 255, 255, 255 ),
|
||||
CC.COLOUR_THUMB_BACKGROUND_SELECTED : QG.QColor( 217, 242, 255 ),
|
||||
CC.COLOUR_THUMB_BACKGROUND_REMOTE : QG.QColor( 32, 32, 36 ),
|
||||
CC.COLOUR_THUMB_BACKGROUND_REMOTE_SELECTED : QG.QColor( 64, 64, 72 ),
|
||||
CC.COLOUR_THUMB_BORDER : QG.QColor( 223, 227, 230 ),
|
||||
CC.COLOUR_THUMB_BORDER_SELECTED : QG.QColor( 1, 17, 26 ),
|
||||
CC.COLOUR_THUMB_BORDER_REMOTE : QG.QColor( 248, 208, 204 ),
|
||||
CC.COLOUR_THUMB_BORDER_REMOTE_SELECTED : QG.QColor( 227, 66, 52 )
|
||||
}
|
||||
|
||||
self.setObjectName( 'HydrusMediaList' )
|
||||
|
||||
self.setFrameStyle( QW.QFrame.Panel | QW.QFrame.Sunken )
|
||||
self.setLineWidth( 2 )
|
||||
|
||||
|
@ -1916,6 +1929,20 @@ class MediaPanel( CAC.ApplicationCommandProcessorMixin, ClientMedia.ListeningMed
|
|||
self.Sort()
|
||||
|
||||
|
||||
def GetColour( self, colour_type ):
|
||||
|
||||
if CG.client_controller.new_options.GetBoolean( 'override_stylesheet_colours' ):
|
||||
|
||||
bg_colour = CG.client_controller.new_options.GetColour( colour_type )
|
||||
|
||||
else:
|
||||
|
||||
bg_colour = self._qss_colours.get( colour_type, QG.QColor( 127, 127, 127 ) )
|
||||
|
||||
|
||||
return bg_colour
|
||||
|
||||
|
||||
def GetTotalFileSize( self ):
|
||||
|
||||
return 0
|
||||
|
@ -2522,6 +2549,106 @@ class MediaPanel( CAC.ApplicationCommandProcessorMixin, ClientMedia.ListeningMed
|
|||
pass
|
||||
|
||||
|
||||
def get_hmrp_background( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_THUMBGRID_BACKGROUND ]
|
||||
|
||||
|
||||
def get_hmrp_thumbnail_local_background_normal( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_THUMB_BACKGROUND ]
|
||||
|
||||
|
||||
def get_hmrp_thumbnail_local_background_selected( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_THUMB_BACKGROUND_SELECTED ]
|
||||
|
||||
|
||||
def get_hmrp_thumbnail_local_border_normal( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_THUMB_BORDER ]
|
||||
|
||||
|
||||
def get_hmrp_thumbnail_local_border_selected( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_THUMB_BORDER_SELECTED ]
|
||||
|
||||
|
||||
def get_hmrp_thumbnail_not_local_background_normal( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_THUMB_BACKGROUND_REMOTE ]
|
||||
|
||||
|
||||
def get_hmrp_thumbnail_not_local_background_selected( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_THUMB_BACKGROUND_REMOTE_SELECTED ]
|
||||
|
||||
|
||||
def get_hmrp_thumbnail_not_local_border_normal( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_THUMB_BORDER_REMOTE ]
|
||||
|
||||
|
||||
def get_hmrp_thumbnail_not_local_border_selected( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_THUMB_BORDER_REMOTE_SELECTED ]
|
||||
|
||||
|
||||
def set_hmrp_background( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_THUMBGRID_BACKGROUND ] = colour
|
||||
|
||||
|
||||
def set_hmrp_thumbnail_local_background_normal( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_THUMB_BACKGROUND ] = colour
|
||||
|
||||
|
||||
def set_hmrp_thumbnail_local_background_selected( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_THUMB_BACKGROUND_SELECTED ] = colour
|
||||
|
||||
|
||||
def set_hmrp_thumbnail_local_border_normal( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_THUMB_BORDER ] = colour
|
||||
|
||||
|
||||
def set_hmrp_thumbnail_local_border_selected( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_THUMB_BORDER_SELECTED ] = colour
|
||||
|
||||
|
||||
def set_hmrp_thumbnail_not_local_background_normal( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_THUMB_BACKGROUND_REMOTE ] = colour
|
||||
|
||||
|
||||
def set_hmrp_thumbnail_not_local_background_selected( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_THUMB_BACKGROUND_REMOTE_SELECTED ] = colour
|
||||
|
||||
|
||||
def set_hmrp_thumbnail_not_local_border_normal( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_THUMB_BORDER_REMOTE ] = colour
|
||||
|
||||
|
||||
def set_hmrp_thumbnail_not_local_border_selected( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_THUMB_BORDER_REMOTE_SELECTED ] = colour
|
||||
|
||||
|
||||
hmrp_background = QC.Property( QG.QColor, get_hmrp_background, set_hmrp_background )
|
||||
hmrp_thumbnail_local_background_normal = QC.Property( QG.QColor, get_hmrp_thumbnail_local_background_normal, set_hmrp_thumbnail_local_background_normal )
|
||||
hmrp_thumbnail_local_background_selected = QC.Property( QG.QColor, get_hmrp_thumbnail_local_background_selected, set_hmrp_thumbnail_local_background_selected )
|
||||
hmrp_thumbnail_local_border_normal = QC.Property( QG.QColor, get_hmrp_thumbnail_local_border_normal, set_hmrp_thumbnail_local_border_normal )
|
||||
hmrp_thumbnail_local_border_selected = QC.Property( QG.QColor, get_hmrp_thumbnail_local_border_selected, set_hmrp_thumbnail_local_border_selected )
|
||||
hmrp_thumbnail_not_local_background_normal = QC.Property( QG.QColor, get_hmrp_thumbnail_not_local_background_normal, set_hmrp_thumbnail_not_local_background_normal )
|
||||
hmrp_thumbnail_not_local_background_selected = QC.Property( QG.QColor, get_hmrp_thumbnail_not_local_background_selected, set_hmrp_thumbnail_not_local_background_selected )
|
||||
hmrp_thumbnail_not_local_border_normal = QC.Property( QG.QColor, get_hmrp_thumbnail_not_local_border_normal, set_hmrp_thumbnail_not_local_border_normal )
|
||||
hmrp_thumbnail_not_local_border_selected = QC.Property( QG.QColor, get_hmrp_thumbnail_not_local_border_selected, set_hmrp_thumbnail_not_local_border_selected )
|
||||
|
||||
class _InnerWidget( QW.QWidget ):
|
||||
|
||||
def __init__( self, parent ):
|
||||
|
@ -2535,7 +2662,7 @@ class MediaPanel( CAC.ApplicationCommandProcessorMixin, ClientMedia.ListeningMed
|
|||
|
||||
painter = QG.QPainter( self )
|
||||
|
||||
bg_colour = CG.client_controller.new_options.GetColour( CC.COLOUR_THUMBGRID_BACKGROUND )
|
||||
bg_colour = self._parent.GetColour( CC.COLOUR_THUMBGRID_BACKGROUND )
|
||||
|
||||
painter.setBackground( QG.QBrush( bg_colour ) )
|
||||
|
||||
|
@ -2724,7 +2851,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
new_options = CG.client_controller.new_options
|
||||
|
||||
bg_colour = CG.client_controller.new_options.GetColour( CC.COLOUR_THUMBGRID_BACKGROUND )
|
||||
bg_colour = self.GetColour( CC.COLOUR_THUMBGRID_BACKGROUND )
|
||||
|
||||
if HG.thumbnail_debug_mode and page_index % 2 == 0:
|
||||
|
||||
|
@ -2785,7 +2912,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
y = ( thumbnail_row - ( page_index * self._num_rows_per_canvas_page ) ) * thumbnail_span_height + thumbnail_margin
|
||||
|
||||
painter.drawImage( x, y, thumbnail.GetQtImage( self.devicePixelRatio() ) )
|
||||
painter.drawImage( x, y, thumbnail.GetQtImage( self, self.devicePixelRatio() ) )
|
||||
|
||||
else:
|
||||
|
||||
|
@ -2846,7 +2973,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
self._StopFading( hash )
|
||||
|
||||
bitmap = thumbnail.GetQtImage( self.devicePixelRatio() )
|
||||
bitmap = thumbnail.GetQtImage( self, self.devicePixelRatio() )
|
||||
|
||||
fade_thumbnails = CG.client_controller.new_options.GetBoolean( 'fade_thumbnails' )
|
||||
|
||||
|
@ -4475,7 +4602,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
y_start = self._parent._GetYStart()
|
||||
|
||||
bg_colour = CG.client_controller.new_options.GetColour( CC.COLOUR_THUMBGRID_BACKGROUND )
|
||||
bg_colour = self._parent.GetColour( CC.COLOUR_THUMBGRID_BACKGROUND )
|
||||
|
||||
painter.setBackground( QG.QBrush( bg_colour ) )
|
||||
|
||||
|
@ -4801,7 +4928,7 @@ class Thumbnail( Selectable ):
|
|||
self._last_lower_summary = None
|
||||
|
||||
|
||||
def GetQtImage( self, device_pixel_ratio ) -> QG.QImage:
|
||||
def GetQtImage( self, media_panel: MediaPanel, device_pixel_ratio ) -> QG.QImage:
|
||||
|
||||
# we probably don't really want to say DPR as a param here, but instead ask for a qt_image in a certain resolution?
|
||||
# or just give the qt_image to be drawn to?
|
||||
|
@ -4901,7 +5028,9 @@ class Thumbnail( Selectable ):
|
|||
|
||||
painter.setFont( f )
|
||||
|
||||
painter.fillRect( thumbnail_border, thumbnail_border, width - ( thumbnail_border * 2 ), height - ( thumbnail_border * 2 ), new_options.GetColour( background_colour_type ) )
|
||||
bg_color = media_panel.GetColour( background_colour_type )
|
||||
|
||||
painter.fillRect( thumbnail_border, thumbnail_border, width - ( thumbnail_border * 2 ), height - ( thumbnail_border * 2 ), bg_color )
|
||||
|
||||
raw_thumbnail_qt_image = thumbnail_hydrus_bmp.GetQtImage()
|
||||
|
||||
|
@ -5043,7 +5172,9 @@ class Thumbnail( Selectable ):
|
|||
# _ .___//_/ /_/|_| \___//_/ /____/ _\__, / \____/ \__/ \____/ /_/ /_/\___//_/ /_/ (_)
|
||||
# /_/ /____/
|
||||
|
||||
painter.setBrush( QG.QBrush( new_options.GetColour( border_colour_type ) ) )
|
||||
bd_colour = media_panel.GetColour( border_colour_type )
|
||||
|
||||
painter.setBrush( QG.QBrush( bd_colour ) )
|
||||
painter.setPen( QG.QPen( QC.Qt.NoPen ) )
|
||||
|
||||
rectangles = []
|
||||
|
|
|
@ -198,24 +198,26 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
self._new_options = CG.client_controller.new_options
|
||||
|
||||
help_text = 'Hey, this page is pretty old. We want to eventually move its capabilities to the more flexible "style" page, but for now, several custom widgets have hardcoded colours set here.'
|
||||
help_text = 'Hey, this page is pretty old, and hydev is in the process of transforming it into a different system. Colours are generally managed through QSS stylesheets now, under the "style" page, but you can still override some stuff here if you want.'
|
||||
help_text += '\n' * 2
|
||||
help_text += 'In a similar way, the "darkmode" here only changes these colours, it does not change the stylesheet. Please bear with the awkwardness of these two systems, we do plan to improve them, thank you!'
|
||||
help_text += 'The "darkmode" in hydrus is also very old and only changes these colours; it does not change the stylesheet. Please bear with the awkwardness, this will be cleaned up eventually, thank you!'
|
||||
|
||||
self._help_label = ClientGUICommon.BetterStaticText( self, label = help_text )
|
||||
|
||||
self._help_label.setObjectName( 'HydrusWarning' )
|
||||
|
||||
coloursets_panel = ClientGUICommon.StaticBox( self, 'coloursets' )
|
||||
self._help_label.setWordWrap( True )
|
||||
|
||||
self._current_colourset = ClientGUICommon.BetterChoice( coloursets_panel )
|
||||
self._override_stylesheet_colours = QW.QCheckBox( self )
|
||||
|
||||
self._coloursets_panel = ClientGUICommon.StaticBox( self, 'coloursets' )
|
||||
|
||||
self._current_colourset = ClientGUICommon.BetterChoice( self._coloursets_panel )
|
||||
|
||||
self._current_colourset.addItem( 'default', 'default' )
|
||||
self._current_colourset.addItem( 'darkmode', 'darkmode' )
|
||||
|
||||
self._current_colourset.SetValue( self._new_options.GetString( 'current_colourset' ) )
|
||||
|
||||
self._notebook = QW.QTabWidget( coloursets_panel )
|
||||
self._notebook = QW.QTabWidget( self._coloursets_panel )
|
||||
|
||||
self._gui_colours = {}
|
||||
|
||||
|
@ -292,20 +294,44 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
#
|
||||
|
||||
coloursets_panel.Add( ClientGUICommon.WrapInText( self._current_colourset, coloursets_panel, 'current colourset: ' ), CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
coloursets_panel.Add( self._notebook, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
self._override_stylesheet_colours.setChecked( self._new_options.GetBoolean( 'override_stylesheet_colours' ) )
|
||||
self._current_colourset.SetValue( self._new_options.GetString( 'current_colourset' ) )
|
||||
|
||||
#
|
||||
|
||||
rows = []
|
||||
|
||||
rows.append( ( 'override what is set in the stylesheet with the colours on this page: ', self._override_stylesheet_colours ) )
|
||||
|
||||
gridbox = ClientGUICommon.WrapInGrid( self, rows )
|
||||
|
||||
self._coloursets_panel.Add( ClientGUICommon.WrapInText( self._current_colourset, self._coloursets_panel, 'current colourset: ' ), CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
self._coloursets_panel.Add( self._notebook, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
vbox = QP.VBoxLayout()
|
||||
|
||||
QP.AddToLayout( vbox, self._help_label, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
QP.AddToLayout( vbox, coloursets_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
QP.AddToLayout( vbox, gridbox, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
QP.AddToLayout( vbox, self._coloursets_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
vbox.addStretch( 1 )
|
||||
|
||||
self.setLayout( vbox )
|
||||
|
||||
self._override_stylesheet_colours.clicked.connect( self._UpdateOverride )
|
||||
|
||||
self._UpdateOverride()
|
||||
|
||||
|
||||
def _UpdateOverride( self ):
|
||||
|
||||
self._coloursets_panel.setEnabled( self._override_stylesheet_colours.isChecked() )
|
||||
|
||||
|
||||
def UpdateOptions( self ):
|
||||
|
||||
self._new_options.SetBoolean( 'override_stylesheet_colours', self._override_stylesheet_colours.isChecked() )
|
||||
|
||||
for colourset in self._gui_colours:
|
||||
|
||||
for ( colour_type, ctrl ) in list(self._gui_colours[ colourset ].items()):
|
||||
|
@ -3940,12 +3966,14 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
#
|
||||
|
||||
help_text = 'Hey, there are several colours, mostly for custom widgets, not set here. Check the "colours" page out!'
|
||||
help_text = 'Hey, there are several custom widget colours that can be overridden in the "colours" page!'
|
||||
|
||||
self._help_label = ClientGUICommon.BetterStaticText( self, label = help_text )
|
||||
|
||||
self._help_label.setObjectName( 'HydrusWarning' )
|
||||
|
||||
self._help_label.setWordWrap( True )
|
||||
|
||||
self._qt_style_name = ClientGUICommon.BetterChoice( self )
|
||||
self._qt_stylesheet_name = ClientGUICommon.BetterChoice( self )
|
||||
|
||||
|
@ -3992,9 +4020,7 @@ class ManageOptionsPanel( ClientGUIScrolledPanels.ManagePanel ):
|
|||
|
||||
text = 'The current styles are what your Qt has available, the stylesheets are what .css and .qss files are currently in install_dir/static/qss.'
|
||||
text += '\n' * 2
|
||||
text += 'Note that there are several colours not handled by this yet. Check out the "colours" page of this options to change them.'
|
||||
text += '\n' * 2
|
||||
text += 'Also, if you run from source and you select e621 or another stylesheet that includes external (svg) assets, you must make sure that your CWD is the hydrus install folder when you boot.'
|
||||
text += 'If you run from source and you select e621 or another stylesheet that includes external (svg) assets, you must make sure that your CWD is the hydrus install folder when you boot.'
|
||||
|
||||
st = ClientGUICommon.BetterStaticText( self, label = text )
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import os
|
|||
import typing
|
||||
|
||||
from qtpy import QtCore as QC
|
||||
from qtpy import QtGui as QG
|
||||
from qtpy import QtWidgets as QW
|
||||
|
||||
from hydrus.core import HydrusConstants as HC
|
||||
|
@ -799,9 +800,15 @@ class AutoCompleteDropdown( CAC.ApplicationCommandProcessorMixin, QW.QWidget ):
|
|||
|
||||
def __init__( self, parent ):
|
||||
|
||||
self._qss_colours = {
|
||||
CC.COLOUR_AUTOCOMPLETE_BACKGROUND : QG.QColor( 235, 248, 255 )
|
||||
}
|
||||
|
||||
QW.QWidget.__init__( self, parent )
|
||||
CAC.ApplicationCommandProcessorMixin.__init__( self )
|
||||
|
||||
self.setObjectName( 'HydrusTagAutocomplete' )
|
||||
|
||||
self._can_intercept_unusual_key_events = True
|
||||
|
||||
if self.window() == CG.client_controller.gui:
|
||||
|
@ -823,8 +830,6 @@ class AutoCompleteDropdown( CAC.ApplicationCommandProcessorMixin, QW.QWidget ):
|
|||
|
||||
self.setFocusProxy( self._text_ctrl )
|
||||
|
||||
self._UpdateBackgroundColour()
|
||||
|
||||
self._last_attempted_dropdown_width = 0
|
||||
|
||||
self._text_ctrl_widget_event_filter = QP.WidgetEventFilter( self._text_ctrl )
|
||||
|
@ -949,6 +954,8 @@ class AutoCompleteDropdown( CAC.ApplicationCommandProcessorMixin, QW.QWidget ):
|
|||
# trying a second go to see if that improves some positioning
|
||||
CG.client_controller.CallLaterQtSafe( self, 0.25, 'hide/show dropdown', self._DropdownHideShow )
|
||||
|
||||
CG.client_controller.CallLaterQtSafe( self, 0.05, 'do autocomplete background colour', self._UpdateBackgroundColour )
|
||||
|
||||
|
||||
def _BroadcastChoices( self, predicates, shift_down ):
|
||||
|
||||
|
@ -1165,14 +1172,14 @@ class AutoCompleteDropdown( CAC.ApplicationCommandProcessorMixin, QW.QWidget ):
|
|||
|
||||
def _UpdateBackgroundColour( self ):
|
||||
|
||||
colour = CG.client_controller.new_options.GetColour( CC.COLOUR_AUTOCOMPLETE_BACKGROUND )
|
||||
bg_colour = self.GetColour( CC.COLOUR_AUTOCOMPLETE_BACKGROUND )
|
||||
|
||||
if not self._can_intercept_unusual_key_events:
|
||||
|
||||
colour = ClientGUIFunctions.GetLighterDarkerColour( colour )
|
||||
bg_colour = ClientGUIFunctions.GetLighterDarkerColour( bg_colour )
|
||||
|
||||
|
||||
QP.SetBackgroundColour( self._text_ctrl, colour )
|
||||
QP.SetBackgroundColour( self._text_ctrl, bg_colour )
|
||||
|
||||
self._text_ctrl.update()
|
||||
|
||||
|
@ -1410,6 +1417,20 @@ class AutoCompleteDropdown( CAC.ApplicationCommandProcessorMixin, QW.QWidget ):
|
|||
|
||||
|
||||
|
||||
def GetColour( self, colour_type ):
|
||||
|
||||
new_options = CG.client_controller.new_options
|
||||
|
||||
if new_options.GetBoolean( 'override_stylesheet_colours' ):
|
||||
|
||||
return new_options.GetColour( colour_type )
|
||||
|
||||
else:
|
||||
|
||||
return self._qss_colours.get( colour_type, QG.QColor( 127, 127, 127 ) )
|
||||
|
||||
|
||||
|
||||
def MoveNotebookPageFocus( self, index = None, direction = None ):
|
||||
|
||||
new_index = None
|
||||
|
@ -1534,6 +1555,18 @@ class AutoCompleteDropdown( CAC.ApplicationCommandProcessorMixin, QW.QWidget ):
|
|||
self._DropdownHideShow()
|
||||
|
||||
|
||||
def get_hta_background( self ):
|
||||
|
||||
return self._qss_colours[ CC.COLOUR_AUTOCOMPLETE_BACKGROUND ]
|
||||
|
||||
|
||||
def set_hta_background( self, colour ):
|
||||
|
||||
self._qss_colours[ CC.COLOUR_AUTOCOMPLETE_BACKGROUND ] = colour
|
||||
|
||||
|
||||
hta_background = QC.Property( QG.QColor, get_hta_background, set_hta_background )
|
||||
|
||||
|
||||
class ChildrenTab( ListBoxTagsPredicatesAC ):
|
||||
|
||||
|
@ -2932,6 +2965,8 @@ class ListBoxTagsActiveSearchPredicates( ClientGUIListBoxes.ListBoxTagsPredicate
|
|||
terms_to_be_added = set()
|
||||
terms_to_be_removed = set()
|
||||
|
||||
terms_to_select = set()
|
||||
|
||||
for predicate in predicates:
|
||||
|
||||
predicate = predicate.GetCountlessCopy()
|
||||
|
@ -2953,7 +2988,14 @@ class ListBoxTagsActiveSearchPredicates( ClientGUIListBoxes.ListBoxTagsPredicate
|
|||
|
||||
m_e_preds = self._GetMutuallyExclusivePredicates( predicate )
|
||||
|
||||
terms_to_be_removed.update( ( self._GenerateTermFromPredicate( pred ) for pred in m_e_preds ) )
|
||||
new_removees = [ self._GenerateTermFromPredicate( pred ) for pred in m_e_preds ]
|
||||
|
||||
if True in ( t in self._selected_terms for t in new_removees ):
|
||||
|
||||
terms_to_select.add( term )
|
||||
|
||||
|
||||
terms_to_be_removed.update( new_removees )
|
||||
|
||||
|
||||
|
||||
|
@ -2964,6 +3006,15 @@ class ListBoxTagsActiveSearchPredicates( ClientGUIListBoxes.ListBoxTagsPredicate
|
|||
|
||||
self._Sort()
|
||||
|
||||
if len( terms_to_select ) > 0:
|
||||
|
||||
self._selected_terms.update( terms_to_select )
|
||||
|
||||
earliest_guy = sorted( terms_to_select, key = lambda t: self._terms_to_logical_indices[ t ] )[0]
|
||||
|
||||
self._Hit( False, False, self._terms_to_logical_indices[ earliest_guy ] )
|
||||
|
||||
|
||||
self._DataHasChanged()
|
||||
|
||||
|
||||
|
|
|
@ -73,6 +73,8 @@ class ReviewPurgeTagsPanel( ClientGUIScrolledPanels.ReviewPanel ):
|
|||
|
||||
self.widget().setLayout( vbox )
|
||||
|
||||
self._autocomplete.tagsPasted.connect( self._tags_to_remove.AddTags )
|
||||
|
||||
|
||||
def Go( self ):
|
||||
|
||||
|
|
|
@ -1346,7 +1346,10 @@ class ImportFoldersManager( object ):
|
|||
|
||||
with self._lock:
|
||||
|
||||
del self._import_folder_names_to_next_work_time_cache[ name ]
|
||||
if name in self._import_folder_names_to_next_work_time_cache:
|
||||
|
||||
del self._import_folder_names_to_next_work_time_cache[ name ]
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
@ -1365,7 +1368,10 @@ class ImportFoldersManager( object ):
|
|||
|
||||
if next_work_time is None:
|
||||
|
||||
del self._import_folder_names_to_next_work_time_cache[ name ]
|
||||
if name in self._import_folder_names_to_next_work_time_cache:
|
||||
|
||||
del self._import_folder_names_to_next_work_time_cache[ name ]
|
||||
|
||||
|
||||
else:
|
||||
|
||||
|
|
|
@ -1324,16 +1324,16 @@ class MediaList( object ):
|
|||
|
||||
def Sort( self, media_sort = None ):
|
||||
|
||||
for media in self._collected_media:
|
||||
|
||||
media.Sort( media_sort )
|
||||
|
||||
|
||||
if media_sort is None:
|
||||
|
||||
media_sort = self._media_sort
|
||||
|
||||
|
||||
for media in self._collected_media:
|
||||
|
||||
media.Sort( media_sort )
|
||||
|
||||
|
||||
self._media_sort = media_sort
|
||||
|
||||
media_sort_fallback = CG.client_controller.new_options.GetFallbackSort()
|
||||
|
|
|
@ -167,8 +167,7 @@ class ParsedAutocompleteText( object ):
|
|||
|
||||
search_texts = []
|
||||
|
||||
allow_unnamespaced_search_gives_any_namespace_wildcards_values = [ True ]
|
||||
always_autocompleting_values = [ True, False ]
|
||||
allow_unnamespaced_search_gives_any_namespace_wildcards_values = []
|
||||
|
||||
if '*' in self.raw_content:
|
||||
|
||||
|
@ -176,20 +175,11 @@ class ParsedAutocompleteText( object ):
|
|||
allow_unnamespaced_search_gives_any_namespace_wildcards_values.append( False )
|
||||
|
||||
|
||||
allow_unnamespaced_search_gives_any_namespace_wildcards_values.append( True )
|
||||
|
||||
for allow_unnamespaced_search_gives_any_namespace_wildcards in allow_unnamespaced_search_gives_any_namespace_wildcards_values:
|
||||
|
||||
for always_autocompleting in always_autocompleting_values:
|
||||
|
||||
search_texts.append( self._GetSearchText( always_autocompleting, allow_auto_wildcard_conversion = allow_unnamespaced_search_gives_any_namespace_wildcards, force_do_not_collapse = True ) )
|
||||
|
||||
|
||||
|
||||
for s in list( search_texts ):
|
||||
|
||||
if ':' not in s:
|
||||
|
||||
search_texts.append( '*:{}'.format( s ) )
|
||||
|
||||
search_texts.append( self._GetSearchText( False, allow_auto_wildcard_conversion = allow_unnamespaced_search_gives_any_namespace_wildcards, force_do_not_collapse = True ) )
|
||||
|
||||
|
||||
search_texts = HydrusData.DedupeList( search_texts )
|
||||
|
|
|
@ -105,7 +105,7 @@ options = {}
|
|||
# Misc
|
||||
|
||||
NETWORK_VERSION = 20
|
||||
SOFTWARE_VERSION = 581
|
||||
SOFTWARE_VERSION = 582
|
||||
CLIENT_API_VERSION = 65
|
||||
|
||||
SERVER_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||
|
|
|
@ -520,7 +520,7 @@ class TestTagObjects( unittest.TestCase ):
|
|||
|
||||
bool_tests( parsed_autocomplete_text, [ True, True, False, True, False, False, True ] )
|
||||
search_text_tests( parsed_autocomplete_text, [ 'samus*', 'samus*' ] )
|
||||
read_predicate_tests( parsed_autocomplete_text, [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 'samus*' ), [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 'samus*' ), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, '*:samus*' ) ] ] )
|
||||
read_predicate_tests( parsed_autocomplete_text, [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 'samus*' ), [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 'samus*' ) ] ] )
|
||||
|
||||
#
|
||||
|
||||
|
@ -545,7 +545,7 @@ class TestTagObjects( unittest.TestCase ):
|
|||
|
||||
bool_tests( parsed_autocomplete_text, [ True, True, False, True, False, False, True ] )
|
||||
search_text_tests( parsed_autocomplete_text, [ 's*s', 's*s*' ] )
|
||||
read_predicate_tests( parsed_autocomplete_text, [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s*' ), [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s*' ), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s' ), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, '*:s*s*' ), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, '*:s*s' ) ] ] )
|
||||
read_predicate_tests( parsed_autocomplete_text, [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s' ), [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s' ) ] ] )
|
||||
|
||||
#
|
||||
|
||||
|
@ -553,7 +553,7 @@ class TestTagObjects( unittest.TestCase ):
|
|||
|
||||
bool_tests( parsed_autocomplete_text, [ True, True, False, True, False, False, False ] )
|
||||
search_text_tests( parsed_autocomplete_text, [ 's*s', 's*s*' ] )
|
||||
read_predicate_tests( parsed_autocomplete_text, [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s*', inclusive = False ), [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s*', inclusive = False ), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s', inclusive = False ), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, '*:s*s*', inclusive = False ), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, '*:s*s', inclusive = False ) ] ] )
|
||||
read_predicate_tests( parsed_autocomplete_text, [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s', inclusive = False ), [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s', inclusive = False ) ] ] )
|
||||
|
||||
#
|
||||
|
||||
|
@ -575,7 +575,7 @@ class TestTagObjects( unittest.TestCase ):
|
|||
|
||||
bool_tests( parsed_autocomplete_text, [ True, True, False, True, False, False, True ] )
|
||||
search_text_tests( parsed_autocomplete_text, [ 's*s a*n', 's*s a*n*' ] )
|
||||
read_predicate_tests( parsed_autocomplete_text, [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s a*n*' ), [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s a*n*' ), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s a*n' ), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, '*:s*s a*n*' ), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, '*:s*s a*n' ) ] ] )
|
||||
read_predicate_tests( parsed_autocomplete_text, [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s a*n' ), [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 's*s a*n' ) ] ] )
|
||||
|
||||
#
|
||||
|
||||
|
@ -615,7 +615,7 @@ class TestTagObjects( unittest.TestCase ):
|
|||
|
||||
bool_tests( parsed_autocomplete_text, [ True, True, False, True, False, False, True ] )
|
||||
search_text_tests( parsed_autocomplete_text, [ 'n*n g*s e*n:as*ka', 'n*n g*s e*n:as*ka*' ] )
|
||||
read_predicate_tests( parsed_autocomplete_text, [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 'n*n g*s e*n:as*ka*' ), [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 'n*n g*s e*n:as*ka*' ), ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 'n*n g*s e*n:as*ka' ) ] ] )
|
||||
read_predicate_tests( parsed_autocomplete_text, [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 'n*n g*s e*n:as*ka' ), [ ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_WILDCARD, 'n*n g*s e*n:as*ka' ) ] ] )
|
||||
|
||||
#
|
||||
|
||||
|
|
|
@ -436,3 +436,51 @@ QLabel#HydrusHyperlink
|
|||
{
|
||||
qproperty-link_color: #ffa02f;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -437,3 +437,51 @@ QLabel#HydrusHyperlink
|
|||
{
|
||||
qproperty-link_color: #ffa02f;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -459,3 +459,51 @@ QLabel#HydrusHyperlink
|
|||
{
|
||||
qproperty-link_color: #8be9fd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -439,3 +439,51 @@ QLabel#HydrusHyperlink
|
|||
{
|
||||
qproperty-link_color: #8be9fd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -440,3 +440,51 @@ QLabel#HydrusHyperlink
|
|||
{
|
||||
qproperty-link_color: #8be9fd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -395,3 +395,51 @@ QLabel#HydrusHyperlink
|
|||
{
|
||||
qproperty-link_color: #ffa02f;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -396,3 +396,51 @@ QLabel#HydrusHyperlink
|
|||
{
|
||||
qproperty-link_color: #ffa02f;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -487,3 +487,51 @@ QLabel#HydrusHyperlink
|
|||
{
|
||||
qproperty-link_color: #50fa7b;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -488,3 +488,51 @@ QLabel#HydrusHyperlink
|
|||
{
|
||||
qproperty-link_color: #50fa7b;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -437,3 +437,51 @@ QLabel#HydrusHyperlink
|
|||
{
|
||||
qproperty-link_color: white;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -438,3 +438,51 @@ QLabel#HydrusHyperlink
|
|||
{
|
||||
qproperty-link_color: white;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
A Purple theme for Hydrus Network by B1N4RYJ4N
|
||||
Version..: 1.0
|
||||
|
||||
To achieve the intended results you must:
|
||||
|
||||
1. Activate dark mode
|
||||
2. adjust the Qt style to Fusion
|
||||
3. adjust the Qt stylesheet to Purple
|
||||
4. adjust the current colourset under files > options > colors > current colourset to darkmode
|
||||
5. adjust your color values under files > options > colors > darkmode like so:
|
||||
|
||||
thumbnail background normal..: #2D1F2D
|
||||
thumbnail background selected: #8E4585
|
||||
thumbnail border normal......: #8E4585
|
||||
thumbnail border selected....: #6B3A65
|
||||
thumbnail grid background....: #2D1F2D
|
||||
autocomplete background......: #6B3A65
|
||||
media viewer background......: #2D1F2D
|
||||
media viewer text............: #E6D0E6
|
||||
tag box background...........: #2D1F2D
|
||||
|
||||
6. adjust your tag presentation color values under files > options > tag presentation > (On thumbnail top, On thumbnail bottom-right, On media viewer top) like so:
|
||||
|
||||
background colour............: #8E4585
|
||||
text colour..................: #E6D0E6
|
||||
*/
|
||||
|
||||
|
||||
/* General settings */
|
||||
QAbstractItemView {
|
||||
background-color: #2D1F2D;
|
||||
}
|
||||
|
||||
QWidget {
|
||||
color: #E6D0E6;
|
||||
background-color: #2D1F2D;
|
||||
alternate-background-color: #2D1F2D;
|
||||
}
|
||||
|
||||
QWidget::disabled {
|
||||
background-color: #2D1F2D;
|
||||
}
|
||||
|
||||
QWidget::item::selected {
|
||||
color: #FFF;
|
||||
background-color: #8E4585;
|
||||
}
|
||||
|
||||
QWidget::item:hover {
|
||||
color: #FFF;
|
||||
background-color: #8E4585;
|
||||
}
|
||||
|
||||
QWidget#HydrusAnimationBar
|
||||
{
|
||||
qproperty-hab_border: #6B3A65;
|
||||
qproperty-hab_background: #8E4585;
|
||||
qproperty-hab_nub: #D070C0;
|
||||
}
|
||||
|
||||
/* Tooltips */
|
||||
QToolTip {
|
||||
color: #FFD0FF;
|
||||
border: 1px solid black;
|
||||
background-color: #2D1F2D;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
/* Menüs */
|
||||
QMenu {
|
||||
color: #E6D0E6;
|
||||
background: #2D1F2D;
|
||||
}
|
||||
|
||||
QMenu::item:selected {
|
||||
color: #FFF;
|
||||
background: #8E4585;
|
||||
}
|
||||
|
||||
/* Menüleiste */
|
||||
QMenuBar::item:selected {
|
||||
color: #FFF;
|
||||
background: #8E4585;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
QPushButton {
|
||||
color: #E6D0E6;
|
||||
background-color: #2D1F2D;
|
||||
}
|
||||
|
||||
QPushButton::hover {
|
||||
color: #FFF;
|
||||
background-color: #2D1F2D;
|
||||
}
|
||||
|
||||
QPushButton#HydrusAccept {
|
||||
color: #A0FFA0;
|
||||
}
|
||||
|
||||
QPushButton#HydrusCancel {
|
||||
color: #FFA0A0;
|
||||
}
|
||||
|
||||
/* Tabs */
|
||||
QTabBar::tab {
|
||||
color: #FFD0FF;
|
||||
background-color: #231823;
|
||||
padding: 3px 10px 2px 10px;
|
||||
}
|
||||
|
||||
QTabBar::tab:selected {
|
||||
color: #FFF;
|
||||
background-color: #8E4585;
|
||||
}
|
||||
|
||||
QTabBar::tab:hover:!selected {
|
||||
color: #FFF;
|
||||
background-color: #8E4585;
|
||||
}
|
||||
|
||||
/* Eingabefelder */
|
||||
QLineEdit {
|
||||
border: 1px solid #8E4585;
|
||||
border-radius: 1px;
|
||||
background-color: #433043;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
QLineEdit:focus {
|
||||
color: #FFF;
|
||||
border: 1px solid #E6D0E6;
|
||||
}
|
||||
|
||||
/* Fortschrittsbalken */
|
||||
QProgressBar {
|
||||
color: #E6D0E6;
|
||||
border: 1px solid #8E4585;
|
||||
text-align: center;
|
||||
padding: 1px;
|
||||
border-radius: 0px;
|
||||
background-color: #433043;
|
||||
width: 15px;
|
||||
qproperty-textVisible: true;
|
||||
}
|
||||
|
||||
QProgressBar::chunk {
|
||||
background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 0,
|
||||
stop: 0 #B058A7,
|
||||
stop: 0.4999 #8E4585,
|
||||
stop: 0.5 #7D3A74,
|
||||
stop: 1 #6B3A65);
|
||||
border-radius: 0px;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
/* Header lines */
|
||||
QHeaderView::section {
|
||||
background-color: #6B3A65;
|
||||
color: #E6D0E6;
|
||||
padding-left: 4px;
|
||||
border: 1px solid #8E4585;
|
||||
}
|
||||
|
||||
/* Scrollbar */
|
||||
QScrollBar {
|
||||
background: #2D1F2D;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
QScrollBar:vertical {
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
QScrollBar:horizontal {
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
QScrollBar::handle {
|
||||
background: #6B3A65;
|
||||
border: 2px solid #8E4585;
|
||||
border-radius: 7px;
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical {
|
||||
margin: 2px 2px 2px 2px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal {
|
||||
margin: 2px 2px 2px 2px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:hover {
|
||||
background: #8E4585;
|
||||
border-color: #B058A7;
|
||||
}
|
||||
|
||||
QScrollBar::handle:pressed {
|
||||
background: #B058A7;
|
||||
border-color: #D070C0;
|
||||
}
|
||||
|
||||
QScrollBar::add-line, QScrollBar::sub-line {
|
||||
background: #433043;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:vertical {
|
||||
subcontrol-position: bottom;
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:vertical {
|
||||
subcontrol-position: top;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:horizontal {
|
||||
subcontrol-position: right;
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:horizontal {
|
||||
subcontrol-position: left;
|
||||
}
|
||||
|
||||
QScrollBar::up-arrow, QScrollBar::down-arrow,
|
||||
QScrollBar::left-arrow, QScrollBar::right-arrow {
|
||||
background: #8E4585;
|
||||
height: 6px;
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
QScrollBar::add-page, QScrollBar::sub-page {
|
||||
background: #3D2A3D;
|
||||
}
|
||||
|
||||
/* Text fields */
|
||||
QTextEdit {
|
||||
color: #D0B0D0;
|
||||
background-color: #433043;
|
||||
}
|
||||
|
||||
QPlainTextEdit {
|
||||
background-color: #433043;
|
||||
color: #E6D0E6;
|
||||
}
|
||||
|
||||
/* Special text fields */
|
||||
QTextEdit#HydrusValid, QLineEdit#HydrusValid {
|
||||
color: #2D1F2D;
|
||||
background-color: #A0E6A0;
|
||||
}
|
||||
|
||||
QTextEdit#HydrusIndeterminate, QLineEdit#HydrusIndeterminateValid {
|
||||
color: #2D1F2D;
|
||||
background-color: #D0B0FF;
|
||||
}
|
||||
|
||||
QTextEdit#HydrusInvalid, QLineEdit#HydrusInvalid {
|
||||
color: #2D1F2D;
|
||||
background-color: #E6A0A0;
|
||||
}
|
||||
|
||||
/* Labels */
|
||||
QLabel#HydrusValid {
|
||||
color: #A0FFA0;
|
||||
}
|
||||
|
||||
QLabel#HydrusIndeterminate {
|
||||
color: #D0B0FF;
|
||||
}
|
||||
|
||||
QLabel#HydrusInvalid {
|
||||
color: #FFA0A0;
|
||||
}
|
||||
|
||||
QLabel#HydrusWarning {
|
||||
color: #FFA0A0;
|
||||
}
|
||||
|
||||
/* Checkboxes */
|
||||
QCheckBox#HydrusWarning {
|
||||
color: #FFA0A0;
|
||||
}
|
||||
|
||||
/* Hyperlinks */
|
||||
QLabel#HydrusHyperlink
|
||||
{
|
||||
qproperty-link_color: #D070C0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
/*
|
||||
Default QSS for hydrus. This is prepended to any stylesheet loaded in hydrus.
|
||||
Copying these entries in your own stylesheets should override these settings.
|
||||
This will get more work in future.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -14,12 +13,13 @@ Here are some text and background colours
|
|||
|
||||
QLabel#HydrusValid
|
||||
{
|
||||
color: #008000;
|
||||
color: #008000;
|
||||
}
|
||||
|
||||
QLineEdit#HydrusValid, QTextEdit#HydrusValid, QPlainTextEdit#HydrusValid
|
||||
{
|
||||
background-color: #80ff80;
|
||||
color: #000000;
|
||||
background-color: #80ff80;
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,12 +27,13 @@ QLineEdit#HydrusValid, QTextEdit#HydrusValid, QPlainTextEdit#HydrusValid
|
|||
|
||||
QLabel#HydrusIndeterminate
|
||||
{
|
||||
color: #000080;
|
||||
color: #000080;
|
||||
}
|
||||
|
||||
QLineEdit#HydrusIndeterminate, QTextEdit#HydrusIndeterminate, QPlainTextEdit#HydrusIndeterminate
|
||||
{
|
||||
background-color: #000080;
|
||||
color: #000000;
|
||||
background-color: #000080;
|
||||
}
|
||||
|
||||
|
||||
|
@ -40,12 +41,13 @@ QLineEdit#HydrusIndeterminate, QTextEdit#HydrusIndeterminate, QPlainTextEdit#Hyd
|
|||
|
||||
QLabel#HydrusInvalid
|
||||
{
|
||||
color: #800000;
|
||||
color: #800000;
|
||||
}
|
||||
|
||||
QLineEdit#HydrusInvalid, QTextEdit#HydrusInvalid, QPlainTextEdit#HydrusInvalid
|
||||
{
|
||||
background-color: #ff8080;
|
||||
color: #000000;
|
||||
background-color: #ff8080;
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,7 +55,7 @@ QLineEdit#HydrusInvalid, QTextEdit#HydrusInvalid, QPlainTextEdit#HydrusInvalid
|
|||
|
||||
QLabel#HydrusWarning, QCheckBox#HydrusWarning
|
||||
{
|
||||
color: #800000;
|
||||
color: #800000;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -64,12 +66,12 @@ Buttons on dialogs
|
|||
|
||||
QPushButton#HydrusAccept
|
||||
{
|
||||
color: #008000;
|
||||
color: #008000;
|
||||
}
|
||||
|
||||
QPushButton#HydrusCancel
|
||||
{
|
||||
color: #800000;
|
||||
color: #800000;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -80,12 +82,12 @@ This is the green/red button that switches 'include current tags' and similar st
|
|||
|
||||
QPushButton#HydrusOnOffButton[hydrus_on=true]
|
||||
{
|
||||
color: #008000;
|
||||
color: #008000;
|
||||
}
|
||||
|
||||
QPushButton#HydrusOnOffButton[hydrus_on=false]
|
||||
{
|
||||
color: #800000;
|
||||
color: #800000;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -96,12 +98,12 @@ This is the Command Palette (default Ctrl+P), and specifically the background co
|
|||
|
||||
QLocatorResultWidget#selectedLocatorResult
|
||||
{
|
||||
background-color: palette(highlight);
|
||||
background-color: palette(highlight);
|
||||
}
|
||||
|
||||
QLocatorResultWidget QWidget
|
||||
{
|
||||
background: transparent;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
|
||||
|
@ -115,21 +117,73 @@ These are drawn by hydev on a blank canvas, so they work a little different.
|
|||
|
||||
/*
|
||||
|
||||
The scanbar beneath video/audio in the media viewer.
|
||||
The main colours in the _options->colours_ panel. This used to be hardcoded, with no way to change it in QSS, but now the QSS is the default and the options panel has the choice of overriding what the current stylesheet suggests.
|
||||
|
||||
*/
|
||||
|
||||
QWidget#HydrusAnimationBar
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hab_border: #000000;
|
||||
qproperty-hab_background: #f0f0f0;
|
||||
qproperty-hab_nub: #606060;
|
||||
qproperty-hmrp_background: #ffffff;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #ffffff;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #d9f2ff;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #01111a;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #202024;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #404048;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #ffffff;
|
||||
qproperty-hmv_text: #000000;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #ebf8ff;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #ffffff;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
And this one is odd since we are assigning a colour to <a> html richtext inside a QLabel.
|
||||
Other custom stuff
|
||||
|
||||
*/
|
||||
|
||||
/* The scanbar beneath video/audio in the media viewer. */
|
||||
|
||||
QWidget#HydrusAnimationBar
|
||||
{
|
||||
qproperty-hab_border: #000000;
|
||||
qproperty-hab_background: #f0f0f0;
|
||||
qproperty-hab_nub: #606060;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Clickable Links
|
||||
|
||||
This one is odd since we are assigning a colour to <a> html richtext inside a QLabel.
|
||||
We hack it with hardcoded 'style' attribute in the html in python code.
|
||||
|
||||
*/
|
||||
|
@ -137,5 +191,5 @@ We hack it with hardcoded 'style' attribute in the html in python code.
|
|||
|
||||
QLabel#HydrusHyperlink
|
||||
{
|
||||
qproperty-link_color: palette(link);
|
||||
qproperty-link_color: palette(link);
|
||||
}
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
Default QSS for hydrus. This is prepended to any stylesheet loaded in hydrus.
|
||||
Copying these entries in your own stylesheets should override these settings.
|
||||
This will get more work in future.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Here are some text and background colours
|
||||
|
||||
*/
|
||||
|
||||
/* Example: This regex is valid */
|
||||
|
||||
QLabel#HydrusValid
|
||||
{
|
||||
color: #2ed42e;
|
||||
}
|
||||
|
||||
QLineEdit#HydrusValid, QTextEdit#HydrusValid, QPlainTextEdit#HydrusValid
|
||||
{
|
||||
background-color: #80ff80;
|
||||
}
|
||||
|
||||
|
||||
/* Duplicates 'middle' text colour */
|
||||
|
||||
QLabel#HydrusIndeterminate
|
||||
{
|
||||
color: #8080ff;
|
||||
}
|
||||
|
||||
QLineEdit#HydrusIndeterminate, QTextEdit#HydrusIndeterminate, QPlainTextEdit#HydrusIndeterminate
|
||||
{
|
||||
background-color: #8080ff;
|
||||
}
|
||||
|
||||
|
||||
/* Example: This regex is invalid */
|
||||
|
||||
QLabel#HydrusInvalid
|
||||
{
|
||||
color: #ff7171;
|
||||
}
|
||||
|
||||
QLineEdit#HydrusInvalid, QTextEdit#HydrusInvalid, QPlainTextEdit#HydrusInvalid
|
||||
{
|
||||
background-color: #ff8080;
|
||||
}
|
||||
|
||||
|
||||
/* Example: Your files are going to be deleted! */
|
||||
|
||||
QLabel#HydrusWarning, QCheckBox#HydrusWarning
|
||||
{
|
||||
color: #ff7171;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Buttons on dialogs
|
||||
|
||||
*/
|
||||
|
||||
QPushButton#HydrusAccept
|
||||
{
|
||||
color: #2ed42e;
|
||||
}
|
||||
|
||||
QPushButton#HydrusCancel
|
||||
{
|
||||
color: #ff7171;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
This is the green/red button that switches 'include current tags' and similar states on/off
|
||||
|
||||
*/
|
||||
|
||||
QPushButton#HydrusOnOffButton[hydrus_on=true]
|
||||
{
|
||||
color: #2ed42e;
|
||||
}
|
||||
|
||||
QPushButton#HydrusOnOffButton[hydrus_on=false]
|
||||
{
|
||||
color: #ff7171;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
This is the Command Palette (default Ctrl+P), and specifically the background colour of the item you currently have selected.
|
||||
|
||||
*/
|
||||
|
||||
QLocatorResultWidget#selectedLocatorResult
|
||||
{
|
||||
background-color: palette(highlight);
|
||||
}
|
||||
|
||||
QLocatorResultWidget QWidget
|
||||
{
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Custom Controls
|
||||
|
||||
These are drawn by hydev on a blank canvas, so they work a little different.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
The scanbar beneath video/audio in the media viewer.
|
||||
|
||||
*/
|
||||
|
||||
QWidget#HydrusAnimationBar
|
||||
{
|
||||
qproperty-hab_border: #000000;
|
||||
qproperty-hab_background: #606060;
|
||||
qproperty-hab_nub: #f0f0f0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
And this one is odd since we are assigning a colour to <a> html richtext inside a QLabel.
|
||||
We hack it with hardcoded 'style' attribute in the html in python code.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
QLabel#HydrusHyperlink
|
||||
{
|
||||
qproperty-link_color: palette(link);
|
||||
}
|
|
@ -668,3 +668,51 @@ QLocatorResultWidget#selectedLocatorResult {
|
|||
background: #2b538e;
|
||||
border-bottom: 1px solid#2b538e;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here is more hydev added--now we have this tech, I am copying the default 'darkmode' colours in the options to all of the darkmode stylesheets so the default choice for new users isn't the dark/light jank-mix. Stylesheet authors are welcome to fix this up with better colours for their particular style and send them in.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* The main thumbnail grid. */
|
||||
|
||||
QWidget#HydrusMediaList
|
||||
{
|
||||
qproperty-hmrp_background: #343434;
|
||||
qproperty-hmrp_thumbnail_local_background_normal: #404048;
|
||||
qproperty-hmrp_thumbnail_local_border_normal: #91a3b0;
|
||||
qproperty-hmrp_thumbnail_local_background_selected: #708090;
|
||||
qproperty-hmrp_thumbnail_local_border_selected: #dfe3e6;
|
||||
qproperty-hmrp_thumbnail_not_local_background_normal: #400d02;
|
||||
qproperty-hmrp_thumbnail_not_local_border_normal: #f8d0cc;
|
||||
qproperty-hmrp_thumbnail_not_local_background_selected: #ab274f;
|
||||
qproperty-hmrp_thumbnail_not_local_border_selected: #e34234;
|
||||
}
|
||||
|
||||
|
||||
/* The media viewer. */
|
||||
|
||||
QWidget#HydrusMediaViewer
|
||||
{
|
||||
qproperty-hmv_background: #343434;
|
||||
qproperty-hmv_text: #708090;
|
||||
}
|
||||
|
||||
|
||||
/* The tag autocomplete text input. */
|
||||
|
||||
QWidget#HydrusTagAutocomplete
|
||||
{
|
||||
qproperty-hta_background: #536267;
|
||||
}
|
||||
|
||||
|
||||
/* Tag lists across the program. */
|
||||
|
||||
QWidget#HydrusTagList
|
||||
{
|
||||
qproperty-htl_background: #232629;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,7 @@ Place a .css or .qss Qt StyleSheet file in here, and hydrus will provide it as a
|
|||
|
||||
Don't edit any of the files in here in place--they'll just be overwritten the next time you update. Copy to your own custom filenames if you want to edit anything.
|
||||
|
||||
The default_hydrus.qss is used by the client to draw some custom widget colours. It is prepended to any custom stylesheet that is loaded, check it out for the class names you want want to override in your own custom QSS.
|
||||
|
||||
This is still a bit of a test. I think to do this properly we'll want to move to folders so we can include additional assets like images.
|
||||
The default_hydrus.qss is used by the client to draw some custom widget colours. It is prepended to any custom stylesheet that is loaded, so check it out for the class names you want want to override in your own QSS.
|
||||
|
||||
Here's some examples, there are some QSS files buried here:
|
||||
|
||||
|
|
Loading…
Reference in New Issue