parent
380b0fd520
commit
09daba5aec
|
@ -7,6 +7,49 @@ title: Changelog
|
|||
!!! note
|
||||
This is the new changelog, only the most recent builds. For all versions, see the [old changelog](old_changelog.html).
|
||||
|
||||
## [Version 561](https://github.com/hydrusnetwork/hydrus/releases/tag/v561)
|
||||
|
||||
### rearranging thumbnails
|
||||
|
||||
* on the thumbnail menu, there is a new 'move' submenu. you can move the current selection of files to the start or end of the media list, or to one before or after the earliest selected file, or to the file you right-clicked on to create the menu, or to the first file's position if the selection is not contiguous. if the selection is non-contiguous, it will be made so in the move
|
||||
* added these rearrange commands to the shortcuts system, as 'move thumbnails' under the 'thumbnails' set. I wasn't sure whether to add some default shortcuts, like ctrl+numpad 7/3/4/6 for home/end/left/right or something--let me know what you think
|
||||
|
||||
### misc
|
||||
|
||||
* thanks to user help, fixed a stupid typo from last week that caused some bad errors (including crashes, in some cases) when doing non-simple duplicate filtering (issue #1514). this is the issue the v560a hotfix was made for
|
||||
* fixed another stupid content update typo that was causing 'already in db' results to not get metadata updates
|
||||
* as a hardcoded shortcut, Ctrl+C or Ctrl+Insert now copies the currently selected tags in any taglist. it'll output the full tag/predicate text, with namespace, no counts
|
||||
* I've shortened some thumbnail/media-viewer menu labels, made the 'delete' line into a submenu, and ensured the top info line is always a short variant, with detailed info bumped off to the submenu off the top line. I hate how these menus are often super-wide and thus a pain to navigate to the submenus, so let me know what situations still make them wide
|
||||
* the file log arrow button menu now has entries for 'delete already in db' and 'delete everything'
|
||||
* the 'add these tags to the favourites list?' yes/no now only fires if you try to add more than five tags ot once
|
||||
* the various dialogs in the client that auto-yes or auto-no now show a live countdown in their title string
|
||||
* the window position saving system is now stricter about what it records. maximised and fullscreen state is only saved if 'remember size' is false, and the last size/position is not saved at all if 'remember size/position' is false (previously, it would save these values but not restore them, but let's try being more precise here)
|
||||
* fixed a 'omg what happened, closing the window now' error in the duplicate filter if you try to 'go back' while it is loading a new set of pairs to show
|
||||
* fixed the 'vacuum db' command to correctly save 'last vacuumed time' for all files vacuumed in a job, not just the last!
|
||||
* whenever a `copy2` file copy (which includes copying file times and permission bits) fails for permission reasons, hydrus now falls back to a normal `copy` and logs the failure, including the modified time that failed to copy (which is the bit we actually care about here)
|
||||
|
||||
### db update stuff
|
||||
|
||||
* if there is a known bitrot issue on update, you now get a nicer error message. rather than the actual error, you are now told which version is safe to update to. to christen this system, I've added a check for the recent millisecond timestamp conversion, which caused some issues for users updating older clients. **if your client is v551 or older and you try to update to v561 or later, you will be told to update to v558 first.** sorry for the inconvenience here, and thank you for the reports (issue #1512)
|
||||
* if you try to boot a database more than 50 versions earlier than the code, the client-based version popups now happen in the correct order, with the >50 exception firing before the >15 warning
|
||||
* when an update asks a not-super-important yes/no question, I will now make it auto-yes or auto-no after ten minutes with the recommended value. this will ensure that automatic updaters will still progress (previously, they were hanging forever!)
|
||||
|
||||
### some downloader stuff
|
||||
|
||||
* thanks to a user, the derpibooru now fetches the post description as a note and the source as an associable URL. I tweaked the submitted stuff a bit, simplifying the parsing and discluding 'No description provided.' notes
|
||||
* thanks to a user, the e621 parser can now grab files from posts where the (spicy, I think) content is normally not shown due to a guest login. the posts still won't show up in guest-login gallery searches, so this won't alter your normal results, but if you run into a post like this in your browser and drag-and-drop it onto the client, it now works
|
||||
* I tried to improve the parsing system's de-newlining. this thing is a long-time hack--I've never liked it and I want to replace it with proper multi-line support--but for now I've made sure the de-newliner strips each line of leading/trailing whitespace and discards empty lines. the mode that _doesn't_ collapse newlines (note parsing, for the most part) now _does_ strip leading/trailing newlines along with other whitespace, meaning you no longer have to try and strip extra `<p>` and `<br>` tags and stuff yourself when grabbing notes. also, the formula UI where it says 'Newlines are collapsed before...' now says when it won't be collapsing newlines due to it being a note parser
|
||||
* the String Match processing step now explicitly removes newlines before it runs, meaning it can still catch multi-line notes properly. you can now run a proper regex on a multi-line note
|
||||
|
||||
### boring cleanup
|
||||
|
||||
* optimised some thumbnail handling code, stuff like fetching the current list of sorted selected media
|
||||
* large collections will be a little faster to select and otherwise do operations on
|
||||
* sketched out a new `ClientGlobals` and client controller interface and started refactoring various HG.client_controller to the new CG. this makes no important running changes, but it cleans the messy HG file and will help future coding and type checking in the IDE as it is fleshed out
|
||||
* added some help text to the edit file maintenance panel and fixed some gonk layout in the 'add new work' panel
|
||||
* fixed some instances of the 'unknown' import status showing as a blank string
|
||||
* fixed an error message in the export folder export job that fired when a file to be exported is missing--it was just giving blank instead of the file hash, and its direction to file maintenance was old and unclear
|
||||
|
||||
## [Version 560](https://github.com/hydrusnetwork/hydrus/releases/tag/v560)
|
||||
|
||||
### editing times for multiple files
|
||||
|
@ -455,48 +498,3 @@ title: Changelog
|
|||
* fixed a timing issue that meant popup messages were auto-dismissed from the popup toaster up to a second after they were being 'deleted' by their parent functiions. subscription flow felt more laggy because of this
|
||||
* fixed the file info manager's duplicate call to duplicate unusual metadata like has_exif and blurhash
|
||||
* removed some old code that isn't used any more
|
||||
|
||||
## [Version 551](https://github.com/hydrusnetwork/hydrus/releases/tag/v551)
|
||||
|
||||
### misc
|
||||
|
||||
* thanks to a user, we have a new checkbox under _options->thumbnails_ that disables thumbnail fading. they'll just blink into place in one frame as soon as ready
|
||||
* after looking at this code myself, I gave it a full clean. the actual thumbnail fade animation is now handled with some proper objects rather than a scatter of variables passed around
|
||||
* I also doubled the default fade time to 500ms. I expect I'll add an option for it, especially if we rework all this into the proper Qt animation engine and get it performing better
|
||||
* fixed the crashes users on PyQt were seeing! I made one tiny change (1->1.0) last week, and PyQt didn't like it, so any view of Mr Bones or 'open externally' panels, or the media viewer top-right ratings hover was leading to program instability
|
||||
* the system predicates for 'has/no duration', 'has/no frames', 'has/no notes', 'has/no words' (i.e. the respective 'num x' system pred, but either = 0 or >0) are now aware that they are each others' inverse, so if you ctrl+double-click or do similar edit actions, they'll flip
|
||||
* updated the 'PTR for dummies' page to link to a new QuickSync source, kindly maintained and hosted by a user
|
||||
|
||||
### code cleanup and misc bug fixes
|
||||
|
||||
* sped up some random iteration across the program (e.g. when deciding which order to waterfall thumbnails in, which can suffer from overhead if you do a fast giganto-scroll)
|
||||
* cleaned up the code that does image alpha channel (transparency) detection, comparison, and stripping
|
||||
* unified how the variety of image loads and conversions perform the 'strip this image of useless transparency data' normalisation step. thumbnails from krita, svg, and pdf are now stripped of useless alpha. also, all 'import this serialised object png' avenues now handle pngs with spurious alpha
|
||||
* I think I fixed the alpha channel stripping code to handle 'LA' (greyscale with transparency) files. if you try to import a hydrus serialised object png file that is for some crazy reason now LA, I think it'll work!
|
||||
* when a files popup message filters its current files and the count goes to 0 (happens if you re-click the button after deleting everything it has to show), the message now auto-dismisses itself (previously it was nuking the button but staying as a thin strip of null panel space)
|
||||
* fixed a bug where `system:date` predicates were displaying labels an hour off (usually midnight -> 11pm, thus cycling back to the previous day) thanks to the clocks changed (in the USA) last weekend. I suspect there is more of this, here and there, so let me know what you see
|
||||
* fixed a counting typo error with the delete files code when you delete the last file in a domain but the domain thinks it already has 0 files
|
||||
* fixed up similar code across the database to forestall future typos on SQLite SUMs
|
||||
* improved and unified the 'hydrus temp dir' management code. if the specific per-process hydrus temp dir is cleared out by an external factor (I'm guessing just the OS cleaning up during a long running client session), hydrus should just simply make a new folder as needed. with luck, this will fix a problem with drag and drop export that ran into this
|
||||
|
||||
### many file move/copy error handling improvements
|
||||
|
||||
* _tl;dr: if hydrus can't put a file somewhere, it deals with that better now_
|
||||
* improved how file move/merge function reports its errors, and how all its callers handle them
|
||||
* the 'rename a file's file extension when its filetype changes' job now correctly recognises when it fails to rename a file due to a reason other than the file being currently in use
|
||||
* import folders now correctly detect when they fail to 'move' action a file out after processing
|
||||
* the check file integrity routine now correctly detects when it fails to move a damaged file from file storage to a landing zone in the main db directory. this failure now cancels the job properly and prints a nicer error to the log
|
||||
* improved how the file copy/mirror function reports its errors, and how all its callers handle them
|
||||
* saving a serialised object png now properly catches a 'transfer from temp dir to dest location' move error
|
||||
* the internal database backup and restore routines now detect file copy errors better
|
||||
* a drag and drop export operation that wants to put the files in the temp dir and also fails to collect its files nicely now correctly raises an error
|
||||
* failing to set the mpv file on options save (and the subsequent mpv-load action) now reports its error correctly
|
||||
* exporting update files now handles a missing update file more gracefully
|
||||
* mergedirectory and mirrordirectory now fail instantly after any single error, rather than several
|
||||
* added some more file/directory pre-checks to all the merge/mirror functions
|
||||
* deleted some old unused code here
|
||||
|
||||
### client api
|
||||
|
||||
* thanks to a user, the Client API now has a 'generate_hashes' endpoint that returns the sha256 hash (and pixel hash and perceptual hashes of any appropriate image file) of any file you give it
|
||||
* the client api version is now 55
|
||||
|
|
|
@ -181,7 +181,7 @@ As a result, if you get a failure on trying to do a big update, try cutting the
|
|||
|
||||
If you narrow the gap down to just one version and still get an error, please let me know. I am very interested in these sorts of problems and will be happy to help figure out a fix with you (and everyone else who might be affected).
|
||||
|
||||
_All that said, and while updating is complex and every client is different, various user reports over the years suggest this route works and is efficient: 204 > 238 > 246 > 291 > 328 > 335 > 376 > 421 > 466 > 474 ? 480 > 521_
|
||||
_All that said, and while updating is complex and every client is different, various user reports over the years suggest this route works and is efficient: 204 > 238 > 246 > 291 > 328 > 335 > 376 > 421 > 466 > 474 ? 480 > 521 ? 558_
|
||||
|
||||
## Backing up
|
||||
|
||||
|
|
|
@ -34,6 +34,42 @@
|
|||
<div class="content">
|
||||
<h1 id="changelog"><a href="#changelog">changelog</a></h1>
|
||||
<ul>
|
||||
<li>
|
||||
<h2 id="version_561"><a href="#version_561">version 561</a></h2>
|
||||
<ul>
|
||||
<li><h3>rearranging thumbnails</h3></li>
|
||||
<li>on the thumbnail menu, there is a new 'move' submenu. you can move the current selection of files to the start or end of the media list, or to one before or after the earliest selected file, or to the file you right-clicked on to create the menu, or to the first file's position if the selection is not contiguous. if the selection is non-contiguous, it will be made so in the move</li>
|
||||
<li>added these rearrange commands to the shortcuts system, as 'move thumbnails' under the 'thumbnails' set. I wasn't sure whether to add some default shortcuts, like ctrl+numpad 7/3/4/6 for home/end/left/right or something--let me know what you think</li>
|
||||
<li><h3>misc</h3></li>
|
||||
<li>thanks to user help, fixed a stupid typo from last week that caused some bad errors (including crashes, in some cases) when doing non-simple duplicate filtering (issue #1514). this is the issue the v560a hotfix was made for</li>
|
||||
<li>fixed another stupid content update typo that was causing 'already in db' results to not get metadata updates</li>
|
||||
<li>as a hardcoded shortcut, Ctrl+C or Ctrl+Insert now copies the currently selected tags in any taglist. it'll output the full tag/predicate text, with namespace, no counts</li>
|
||||
<li>I've shortened some thumbnail/media-viewer menu labels, made the 'delete' line into a submenu, and ensured the top info line is always a short variant, with detailed info bumped off to the submenu off the top line. I hate how these menus are often super-wide and thus a pain to navigate to the submenus, so let me know what situations still make them wide</li>
|
||||
<li>the file log arrow button menu now has entries for 'delete already in db' and 'delete everything'</li>
|
||||
<li>the 'add these tags to the favourites list?' yes/no now only fires if you try to add more than five tags ot once</li>
|
||||
<li>the various dialogs in the client that auto-yes or auto-no now show a live countdown in their title string</li>
|
||||
<li>the window position saving system is now stricter about what it records. maximised and fullscreen state is only saved if 'remember size' is false, and the last size/position is not saved at all if 'remember size/position' is false (previously, it would save these values but not restore them, but let's try being more precise here)</li>
|
||||
<li>fixed a 'omg what happened, closing the window now' error in the duplicate filter if you try to 'go back' while it is loading a new set of pairs to show</li>
|
||||
<li>fixed the 'vacuum db' command to correctly save 'last vacuumed time' for all files vacuumed in a job, not just the last!</li>
|
||||
<li>whenever a `copy2` file copy (which includes copying file times and permission bits) fails for permission reasons, hydrus now falls back to a normal `copy` and logs the failure, including the modified time that failed to copy (which is the bit we actually care about here)</li>
|
||||
<li><h3>db update stuff</h3></li>
|
||||
<li>if there is a known bitrot issue on update, you now get a nicer error message. rather than the actual error, you are now told which version is safe to update to. to christen this system, I've added a check for the recent millisecond timestamp conversion, which caused some issues for users updating older clients. **if your client is v551 or older and you try to update to v561 or later, you will be told to update to v558 first.** sorry for the inconvenience here, and thank you for the reports (issue #1512)</li>
|
||||
<li>if you try to boot a database more than 50 versions earlier than the code, the client-based version popups now happen in the correct order, with the >50 exception firing before the >15 warning</li>
|
||||
<li>when an update asks a not-super-important yes/no question, I will now make it auto-yes or auto-no after ten minutes with the recommended value. this will ensure that automatic updaters will still progress (previously, they were hanging forever!)</li>
|
||||
<li><h3>some downloader stuff</h3></li>
|
||||
<li>thanks to a user, the derpibooru now fetches the post description as a note and the source as an associable URL. I tweaked the submitted stuff a bit, simplifying the parsing and discluding 'No description provided.' notes</li>
|
||||
<li>thanks to a user, the e621 parser can now grab files from posts where the (spicy, I think) content is normally not shown due to a guest login. the posts still won't show up in guest-login gallery searches, so this won't alter your normal results, but if you run into a post like this in your browser and drag-and-drop it onto the client, it now works</li>
|
||||
<li>I tried to improve the parsing system's de-newlining. this thing is a long-time hack--I've never liked it and I want to replace it with proper multi-line support--but for now I've made sure the de-newliner strips each line of leading/trailing whitespace and discards empty lines. the mode that _doesn't_ collapse newlines (note parsing, for the most part) now _does_ strip leading/trailing newlines along with other whitespace, meaning you no longer have to try and strip extra `<p>` and `<br>` tags and stuff yourself when grabbing notes. also, the formula UI where it says 'Newlines are collapsed before...' now says when it won't be collapsing newlines due to it being a note parser</li>
|
||||
<li>the String Match processing step now explicitly removes newlines before it runs, meaning it can still catch multi-line notes properly. you can now run a proper regex on a multi-line note</li>
|
||||
<li><h3>boring cleanup</h3></li>
|
||||
<li>optimised some thumbnail handling code, stuff like fetching the current list of sorted selected media</li>
|
||||
<li>large collections will be a little faster to select and otherwise do operations on</li>
|
||||
<li>sketched out a new `ClientGlobals` and client controller interface and started refactoring various HG.client_controller to the new CG. this makes no important running changes, but it cleans the messy HG file and will help future coding and type checking in the IDE as it is fleshed out</li>
|
||||
<li>added some help text to the edit file maintenance panel and fixed some gonk layout in the 'add new work' panel</li>
|
||||
<li>fixed some instances of the 'unknown' import status showing as a blank string</li>
|
||||
<li>fixed an error message in the export folder export job that fired when a file to be exported is missing--it was just giving blank instead of the file hash, and its direction to file maintenance was old and unclear</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
<h2 id="version_560"><a href="#version_560">version 560</a></h2>
|
||||
<ul>
|
||||
|
|
|
@ -159,6 +159,10 @@ SIMPLE_OPEN_FILE_IN_FILE_EXPLORER = 146
|
|||
SIMPLE_COPY_LITTLE_BMP = 147
|
||||
SIMPLE_MOVE_THUMBNAIL_FOCUS = 148
|
||||
SIMPLE_SELECT_FILES = 149
|
||||
SIMPLE_REARRANGE_THUMBNAILS = 150
|
||||
|
||||
REARRANGE_THUMBNAILS_TYPE_FIXED = 0
|
||||
REARRANGE_THUMBNAILS_TYPE_COMMAND = 1
|
||||
|
||||
MOVE_HOME = 0
|
||||
MOVE_END = 1
|
||||
|
@ -168,6 +172,7 @@ MOVE_UP = 4
|
|||
MOVE_DOWN = 5
|
||||
MOVE_PAGE_UP = 6
|
||||
MOVE_PAGE_DOWN = 7
|
||||
MOVE_TO_FOCUS = 8
|
||||
|
||||
move_enum_to_str_lookup = {
|
||||
MOVE_HOME : 'home',
|
||||
|
@ -177,7 +182,8 @@ move_enum_to_str_lookup = {
|
|||
MOVE_UP : 'up',
|
||||
MOVE_DOWN : 'down',
|
||||
MOVE_PAGE_UP : 'page up',
|
||||
MOVE_PAGE_DOWN : 'page down'
|
||||
MOVE_PAGE_DOWN : 'page down',
|
||||
MOVE_TO_FOCUS : 'to focus'
|
||||
}
|
||||
|
||||
SELECTION_STATUS_NORMAL = 0
|
||||
|
@ -338,7 +344,8 @@ simple_enum_to_str_lookup = {
|
|||
SIMPLE_GLOBAL_FORCE_ANIMATION_SCANBAR_SHOW : 'force the animation scanbar to show (flip on/off)',
|
||||
SIMPLE_OPEN_COMMAND_PALETTE : 'open the command palette',
|
||||
SIMPLE_MOVE_THUMBNAIL_FOCUS : 'move the thumbnail focus',
|
||||
SIMPLE_SELECT_FILES : 'select files'
|
||||
SIMPLE_SELECT_FILES : 'select files',
|
||||
SIMPLE_REARRANGE_THUMBNAILS : 'move thumbnails',
|
||||
}
|
||||
|
||||
legacy_simple_str_to_enum_lookup = {
|
||||
|
@ -758,6 +765,19 @@ class ApplicationCommand( HydrusSerialisable.SerialisableBase ):
|
|||
|
||||
s = f'{s} ({file_filter.ToString()})'
|
||||
|
||||
elif action == SIMPLE_REARRANGE_THUMBNAILS:
|
||||
|
||||
( rearrange_type, rearrange_data ) = self.GetSimpleData()
|
||||
|
||||
if rearrange_type == REARRANGE_THUMBNAILS_TYPE_COMMAND:
|
||||
|
||||
s = f'{s} ({move_enum_to_str_lookup[ rearrange_data ]})'
|
||||
|
||||
elif rearrange_type == REARRANGE_THUMBNAILS_TYPE_FIXED:
|
||||
|
||||
s = f'{s} (to index {HydrusData.ToHumanInt(rearrange_data)})'
|
||||
|
||||
|
||||
|
||||
return s
|
||||
|
||||
|
|
|
@ -452,7 +452,7 @@ STATUS_SKIPPED = 8
|
|||
STATUS_SUCCESSFUL_AND_CHILD_FILES = 9
|
||||
|
||||
status_string_lookup = {
|
||||
STATUS_UNKNOWN : '',
|
||||
STATUS_UNKNOWN : 'unknown',
|
||||
STATUS_SUCCESSFUL_AND_NEW : 'successful',
|
||||
STATUS_SUCCESSFUL_BUT_REDUNDANT : 'already in db',
|
||||
STATUS_DELETED : 'deleted',
|
||||
|
@ -461,7 +461,7 @@ status_string_lookup = {
|
|||
STATUS_PAUSED : 'paused',
|
||||
STATUS_VETOED : 'ignored',
|
||||
STATUS_SKIPPED : 'skipped',
|
||||
STATUS_SUCCESSFUL_AND_CHILD_FILES : 'completed'
|
||||
STATUS_SUCCESSFUL_AND_CHILD_FILES : 'created children'
|
||||
}
|
||||
|
||||
SUCCESSFUL_IMPORT_STATES = { STATUS_SUCCESSFUL_AND_NEW, STATUS_SUCCESSFUL_BUT_REDUNDANT, STATUS_SUCCESSFUL_AND_CHILD_FILES }
|
||||
|
|
|
@ -27,6 +27,7 @@ from hydrus.client import ClientConstants as CC
|
|||
from hydrus.client import ClientDaemons
|
||||
from hydrus.client import ClientDefaults
|
||||
from hydrus.client import ClientFiles
|
||||
from hydrus.client import ClientGlobals as CG
|
||||
from hydrus.client import ClientOptions
|
||||
from hydrus.client import ClientServices
|
||||
from hydrus.client import ClientThreading
|
||||
|
@ -35,6 +36,7 @@ from hydrus.client.db import ClientDB
|
|||
from hydrus.client.gui import ClientGUIDialogsMessage
|
||||
from hydrus.client.gui import ClientGUISplash
|
||||
from hydrus.client.gui import QtPorting as QP
|
||||
from hydrus.client.interfaces import ClientControllerInterface
|
||||
|
||||
if not HG.twisted_is_broke:
|
||||
|
||||
|
@ -127,13 +129,13 @@ class App( QW.QApplication ):
|
|||
|
||||
# this is also called explicitly right at the end of the program. I set setQuitonLastWindowClosed False and then call quit explicitly, so it needs to be idempotent on the exit calls
|
||||
|
||||
if HG.client_controller is not None:
|
||||
if CG.client_controller is not None:
|
||||
|
||||
if HG.client_controller.ProgramIsShuttingDown():
|
||||
if CG.client_controller.ProgramIsShuttingDown():
|
||||
|
||||
screw_it_time = HydrusTime.GetNow() + 30
|
||||
|
||||
while not HG.client_controller.ProgramIsShutDown():
|
||||
while not CG.client_controller.ProgramIsShutDown():
|
||||
|
||||
time.sleep( 0.5 )
|
||||
|
||||
|
@ -145,14 +147,14 @@ class App( QW.QApplication ):
|
|||
|
||||
else:
|
||||
|
||||
HG.client_controller.SetDoingFastExit( True )
|
||||
CG.client_controller.SetDoingFastExit( True )
|
||||
|
||||
HG.client_controller.Exit()
|
||||
CG.client_controller.Exit()
|
||||
|
||||
|
||||
|
||||
|
||||
class Controller( HydrusController.HydrusController ):
|
||||
class Controller( ClientControllerInterface.ClientControllerInterface, HydrusController.HydrusController ):
|
||||
|
||||
my_instance = None
|
||||
|
||||
|
@ -169,10 +171,12 @@ class Controller( HydrusController.HydrusController ):
|
|||
self.gui = None
|
||||
|
||||
HydrusController.HydrusController.__init__( self, db_dir )
|
||||
ClientControllerInterface.ClientControllerInterface.__init__( self )
|
||||
|
||||
self._name = 'client'
|
||||
|
||||
HG.client_controller = self
|
||||
CG.client_controller = self
|
||||
|
||||
# just to set up some defaults, in case some db update expects something for an odd yaml-loading reason
|
||||
self.options = ClientDefaults.GetClientDefaultOptions()
|
||||
|
@ -1062,7 +1066,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
if self.new_options.GetBoolean( 'boot_with_network_traffic_paused' ):
|
||||
|
||||
HG.client_controller.new_options.SetBoolean( 'pause_all_new_network_traffic', True )
|
||||
CG.client_controller.new_options.SetBoolean( 'pause_all_new_network_traffic', True )
|
||||
|
||||
|
||||
self.parsing_cache = ClientCaches.ParsingCache()
|
||||
|
@ -1261,7 +1265,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
self.frame_splash_status.SetTitleText( 'booting gui' + HC.UNICODE_ELLIPSIS )
|
||||
|
||||
subscriptions = HG.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION )
|
||||
subscriptions = CG.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION )
|
||||
|
||||
self.files_maintenance_manager = ClientFiles.FilesMaintenanceManager( self )
|
||||
|
||||
|
@ -1316,7 +1320,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
def qt_code_pregui():
|
||||
|
||||
shortcut_sets = HG.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SHORTCUT_SET )
|
||||
shortcut_sets = CG.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SHORTCUT_SET )
|
||||
|
||||
from hydrus.client.gui import ClientGUIShortcuts
|
||||
|
||||
|
@ -2106,7 +2110,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
def SynchroniseAccounts( self ):
|
||||
|
||||
if HG.client_controller.new_options.GetBoolean( 'pause_all_new_network_traffic' ):
|
||||
if CG.client_controller.new_options.GetBoolean( 'pause_all_new_network_traffic' ):
|
||||
|
||||
return
|
||||
|
||||
|
@ -2126,7 +2130,7 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
def SynchroniseRepositories( self ):
|
||||
|
||||
if HG.client_controller.new_options.GetBoolean( 'pause_all_new_network_traffic' ):
|
||||
if CG.client_controller.new_options.GetBoolean( 'pause_all_new_network_traffic' ):
|
||||
|
||||
return
|
||||
|
||||
|
@ -2223,6 +2227,12 @@ class Controller( HydrusController.HydrusController ):
|
|||
|
||||
QP.CallAfter( QW.QApplication.exit )
|
||||
|
||||
except HydrusExceptions.DBVersionException as e:
|
||||
|
||||
self.BlockingSafeShowCriticalMessage( 'database version error', str( e ) )
|
||||
|
||||
QP.CallAfter( QW.QApplication.exit, 1 )
|
||||
|
||||
except HydrusExceptions.DBAccessException as e:
|
||||
|
||||
trace = traceback.format_exc()
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import typing
|
||||
|
||||
from hydrus.client.interfaces import ClientControllerInterface
|
||||
|
||||
# TODO: move all HG.client_controller references here, and the various like 'mpv report mode' stuff
|
||||
# make a ServerGlobals too, I think!
|
||||
client_controller: typing.Optional[ ClientControllerInterface.ClientControllerInterface ] = None
|
|
@ -786,6 +786,11 @@ class ParseFormula( HydrusSerialisable.SerialisableBase ):
|
|||
# maybe should use HydrusText.DeserialiseNewlinedTexts, but that might change/break some existing parsers with the strip() trim
|
||||
raw_texts = [ HydrusText.RemoveNewlines( raw_text ) for raw_text in raw_texts ]
|
||||
|
||||
else:
|
||||
|
||||
# note this does get rid of leading/trailing newlines, which is fine!
|
||||
raw_texts = [ raw_text.strip() for raw_text in raw_texts ]
|
||||
|
||||
|
||||
texts = self._string_processor.ProcessStrings( raw_texts )
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ from hydrus.core import HydrusData
|
|||
from hydrus.core import HydrusExceptions
|
||||
from hydrus.core import HydrusSerialisable
|
||||
from hydrus.core import HydrusTags
|
||||
from hydrus.core import HydrusText
|
||||
from hydrus.core import HydrusTime
|
||||
|
||||
from hydrus.client import ClientTime
|
||||
|
@ -733,7 +734,9 @@ class StringMatch( StringProcessingStep ):
|
|||
|
||||
try:
|
||||
|
||||
result = re.search( r, text )
|
||||
text_to_test = ''.join( text.splitlines() ).strip()
|
||||
|
||||
result = re.search( r, text_to_test )
|
||||
|
||||
except Exception as e:
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ from hydrus.client import ClientAPI
|
|||
from hydrus.client import ClientConstants as CC
|
||||
from hydrus.client import ClientDefaults
|
||||
from hydrus.client import ClientFiles
|
||||
from hydrus.client import ClientGlobals as CG
|
||||
from hydrus.client import ClientLocation
|
||||
from hydrus.client import ClientOptions
|
||||
from hydrus.client import ClientServices
|
||||
|
@ -177,7 +178,7 @@ def report_content_speed_to_job_status( job_status, rows_done, total_rows, preci
|
|||
|
||||
popup_message = 'content row ' + HydrusData.ConvertValueRangeToPrettyString( rows_done, total_rows ) + ': processing ' + row_name + ' at ' + rows_s + ' rows/s'
|
||||
|
||||
HG.client_controller.frame_splash_status.SetText( popup_message, print_to_log = False )
|
||||
CG.client_controller.frame_splash_status.SetText( popup_message, print_to_log = False )
|
||||
job_status.SetStatusText( popup_message, 2 )
|
||||
|
||||
def report_speed_to_job_status( job_status, precise_timestamp, num_rows, row_name ):
|
||||
|
@ -188,7 +189,7 @@ def report_speed_to_job_status( job_status, precise_timestamp, num_rows, row_nam
|
|||
|
||||
popup_message = 'processing ' + row_name + ' at ' + rows_s + ' rows/s'
|
||||
|
||||
HG.client_controller.frame_splash_status.SetText( popup_message, print_to_log = False )
|
||||
CG.client_controller.frame_splash_status.SetText( popup_message, print_to_log = False )
|
||||
job_status.SetStatusText( popup_message, 2 )
|
||||
|
||||
def report_speed_to_log( precise_timestamp, num_rows, row_name ):
|
||||
|
@ -212,7 +213,7 @@ class JobDatabaseClient( HydrusData.JobDatabase ):
|
|||
|
||||
if HG.db_ui_hang_relief_mode:
|
||||
|
||||
if QC.QThread.currentThread() == HG.client_controller.main_qt_thread:
|
||||
if QC.QThread.currentThread() == CG.client_controller.main_qt_thread:
|
||||
|
||||
HydrusData.Print( 'ui-hang event processing: begin' )
|
||||
QW.QApplication.instance().processEvents()
|
||||
|
@ -1093,7 +1094,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
orphans_found = True
|
||||
|
||||
client_files_manager = HG.client_controller.client_files_manager
|
||||
client_files_manager = CG.client_controller.client_files_manager
|
||||
|
||||
those_that_exist_on_disk = set()
|
||||
|
||||
|
@ -1168,7 +1169,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
hashes = self.modules_hashes_local_cache.GetHashes( [ row[0] for row in import_rows ] )
|
||||
|
||||
HG.client_controller.pub( 'new_page_query', location_context, initial_hashes = hashes, page_name = 'reparented file records' )
|
||||
CG.client_controller.pub( 'new_page_query', location_context, initial_hashes = hashes, page_name = 'reparented file records' )
|
||||
|
||||
|
||||
|
||||
|
@ -1947,7 +1948,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
if max_num_pairs is None:
|
||||
|
||||
max_num_pairs = HG.client_controller.new_options.GetInteger( 'duplicate_filter_max_batch_size' )
|
||||
max_num_pairs = CG.client_controller.new_options.GetInteger( 'duplicate_filter_max_batch_size' )
|
||||
|
||||
|
||||
# we need to batch non-intersecting decisions here to keep it simple at the gui-level
|
||||
|
@ -2446,7 +2447,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
if len( hashes_that_need_refresh ) > 0:
|
||||
|
||||
HG.client_controller.pub( 'new_file_info', hashes_that_need_refresh )
|
||||
CG.client_controller.pub( 'new_file_info', hashes_that_need_refresh )
|
||||
|
||||
|
||||
|
||||
|
@ -4570,7 +4571,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
needed_hashes = []
|
||||
|
||||
client_files_manager = HG.client_controller.client_files_manager
|
||||
client_files_manager = CG.client_controller.client_files_manager
|
||||
|
||||
for hash_id in needed_hash_ids:
|
||||
|
||||
|
@ -5619,7 +5620,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
text = 'searching potential duplicates: {}'.format( HydrusData.ToHumanInt( num_done ) )
|
||||
|
||||
HG.client_controller.frame_splash_status.SetSubtext( text )
|
||||
CG.client_controller.frame_splash_status.SetSubtext( text )
|
||||
|
||||
for ( i, hash_id ) in enumerate( group_of_hash_ids ):
|
||||
|
||||
|
@ -5638,7 +5639,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
|
||||
|
||||
should_stop = HG.client_controller.ShouldStopThisWork( maintenance_mode, stop_time = stop_time )
|
||||
should_stop = CG.client_controller.ShouldStopThisWork( maintenance_mode, stop_time = stop_time )
|
||||
|
||||
if should_stop:
|
||||
|
||||
|
@ -6013,7 +6014,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
if action == HC.CONTENT_UPDATE_ADD:
|
||||
|
||||
if not HG.client_controller.tag_display_manager.TagOK( ClientTags.TAG_DISPLAY_STORAGE, service_key, tag ):
|
||||
if not CG.client_controller.tag_display_manager.TagOK( ClientTags.TAG_DISPLAY_STORAGE, service_key, tag ):
|
||||
|
||||
continue
|
||||
|
||||
|
@ -6026,7 +6027,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
elif action == HC.CONTENT_UPDATE_PEND:
|
||||
|
||||
if not HG.client_controller.tag_display_manager.TagOK( ClientTags.TAG_DISPLAY_STORAGE, service_key, tag ):
|
||||
if not CG.client_controller.tag_display_manager.TagOK( ClientTags.TAG_DISPLAY_STORAGE, service_key, tag ):
|
||||
|
||||
continue
|
||||
|
||||
|
@ -9803,6 +9804,8 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
|
||||
|
||||
# bitrot gap here, update code above should never run!
|
||||
|
||||
if version == 553:
|
||||
|
||||
try:
|
||||
|
@ -9879,7 +9882,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
from hydrus.client.gui import ClientGUIDialogsQuick
|
||||
|
||||
result = ClientGUIDialogsQuick.GetYesNo( None, message, title = 'Regen animation thumbnails?' )
|
||||
result = ClientGUIDialogsQuick.GetYesNo( None, message, title = 'Regen animation thumbnails?', auto_yes_time = 600 )
|
||||
|
||||
return result == QW.QDialog.Accepted
|
||||
|
||||
|
@ -10055,6 +10058,38 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
|
||||
|
||||
if version == 560:
|
||||
|
||||
try:
|
||||
|
||||
domain_manager = self.modules_serialisable.GetJSONDump( HydrusSerialisable.SERIALISABLE_TYPE_NETWORK_DOMAIN_MANAGER )
|
||||
|
||||
domain_manager.Initialise()
|
||||
|
||||
#
|
||||
|
||||
domain_manager.OverwriteDefaultParsers( [
|
||||
'derpibooru.org file page parser',
|
||||
'e621 file page parser'
|
||||
] )
|
||||
|
||||
#
|
||||
|
||||
domain_manager.TryToLinkURLClassesAndParsers()
|
||||
|
||||
#
|
||||
|
||||
self.modules_serialisable.SetJSONDump( domain_manager )
|
||||
|
||||
except Exception as e:
|
||||
|
||||
HydrusData.PrintException( e )
|
||||
|
||||
message = 'Trying to update some downloaders failed! Please let hydrus dev know!'
|
||||
|
||||
self.pub_initial_message( message )
|
||||
|
||||
|
||||
|
||||
self._controller.frame_splash_status.SetTitleText( 'updated db to v{}'.format( HydrusData.ToHumanInt( version + 1 ) ) )
|
||||
|
||||
|
@ -10464,6 +10499,8 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
self._CloseDBConnection()
|
||||
|
||||
successful_names = []
|
||||
|
||||
try:
|
||||
|
||||
for name in ok_names:
|
||||
|
@ -10492,6 +10529,8 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
HydrusData.Print( 'Vacuumed ' + db_path + ' in ' + HydrusTime.TimeDeltaToPrettyTimeDelta( time_took ) )
|
||||
|
||||
successful_names.append( name )
|
||||
|
||||
except Exception as e:
|
||||
|
||||
HydrusData.Print( 'vacuum failed:' )
|
||||
|
@ -10504,8 +10543,6 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
HydrusData.ShowText( text )
|
||||
|
||||
self._InitDBConnection()
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
@ -10516,7 +10553,11 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
self._InitDBConnection()
|
||||
|
||||
self.modules_db_maintenance.RegisterSuccessfulVacuum( name )
|
||||
for name in successful_names:
|
||||
|
||||
# can't do this without the db connection lol
|
||||
self.modules_db_maintenance.RegisterSuccessfulVacuum( name )
|
||||
|
||||
|
||||
job_status.SetStatusText( 'done!' )
|
||||
|
||||
|
@ -10644,7 +10685,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
for filename in self._db_filenames.values():
|
||||
|
||||
HG.client_controller.frame_splash_status.SetText( filename )
|
||||
CG.client_controller.frame_splash_status.SetText( filename )
|
||||
|
||||
source = os.path.join( path, filename )
|
||||
dest = os.path.join( self._db_dir, filename )
|
||||
|
@ -10675,7 +10716,7 @@ class DB( HydrusDB.HydrusDB ):
|
|||
|
||||
|
||||
|
||||
HG.client_controller.frame_splash_status.SetText( 'media files' )
|
||||
CG.client_controller.frame_splash_status.SetText( 'media files' )
|
||||
|
||||
client_files_source = os.path.join( path, 'client_files' )
|
||||
client_files_default = os.path.join( self._db_dir, 'client_files' )
|
||||
|
|
|
@ -567,7 +567,7 @@ class ExportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
|||
|
||||
except HydrusExceptions.FileMissingException:
|
||||
|
||||
raise Exception( 'A file to be exported, hash "{}", was missing! You should run file maintenance (under database->maintenance->files) to check the files for the export folder\'s search, and possibly all your files.' )
|
||||
raise Exception( f'A file to be exported, hash "{hash.hex()}", was missing! You should run "missing file" file maintenance (under database->file maintenance->manage scheduled jobs) to check if any other files in your export folder\'s search--or your whole database--are also missing.' )
|
||||
|
||||
|
||||
try:
|
||||
|
|
|
@ -40,6 +40,7 @@ from hydrus.core.networking import HydrusNetworking
|
|||
|
||||
from hydrus.client import ClientApplicationCommand as CAC
|
||||
from hydrus.client import ClientConstants as CC
|
||||
from hydrus.client import ClientGlobals as CG
|
||||
from hydrus.client import ClientLocation
|
||||
from hydrus.client import ClientParsing
|
||||
from hydrus.client import ClientPaths
|
||||
|
@ -101,7 +102,7 @@ MENU_ORDER = [ 'file', 'undo', 'pages', 'database', 'network', 'services', 'tags
|
|||
|
||||
def GetTagServiceKeyForMaintenance( win: QW.QWidget ):
|
||||
|
||||
tag_services = HG.client_controller.services_manager.GetServices( HC.REAL_TAG_SERVICES )
|
||||
tag_services = CG.client_controller.services_manager.GetServices( HC.REAL_TAG_SERVICES )
|
||||
|
||||
choice_tuples = [ ( 'all services', None, 'Do it for everything. Can take a long time!' ) ]
|
||||
|
||||
|
@ -124,7 +125,7 @@ def THREADUploadPending( service_key ):
|
|||
|
||||
try:
|
||||
|
||||
service = HG.client_controller.services_manager.GetService( service_key )
|
||||
service = CG.client_controller.services_manager.GetService( service_key )
|
||||
|
||||
service_name = service.GetName()
|
||||
service_type = service.GetServiceType()
|
||||
|
@ -143,7 +144,7 @@ def THREADUploadPending( service_key ):
|
|||
|
||||
job_status.SetStatusTitle( 'uploading pending to ' + service_name )
|
||||
|
||||
nums_pending = HG.client_controller.Read( 'nums_pending' )
|
||||
nums_pending = CG.client_controller.Read( 'nums_pending' )
|
||||
|
||||
nums_pending_for_this_service = nums_pending[ service_key ]
|
||||
|
||||
|
@ -215,13 +216,13 @@ def THREADUploadPending( service_key ):
|
|||
unauthorised_job_status.FinishAndDismiss( 120 )
|
||||
|
||||
|
||||
call = HydrusData.Call( HG.client_controller.pub, 'open_manage_services_and_try_to_auto_create_account', service_key )
|
||||
call = HydrusData.Call( CG.client_controller.pub, 'open_manage_services_and_try_to_auto_create_account', service_key )
|
||||
|
||||
call.SetLabel( 'open manage services and check for auto-creatable accounts' )
|
||||
|
||||
unauthorised_job_status.SetUserCallable( call )
|
||||
|
||||
HG.client_controller.pub( 'message', unauthorised_job_status )
|
||||
CG.client_controller.pub( 'message', unauthorised_job_status )
|
||||
|
||||
|
||||
if len( paused_content_types ) > 0:
|
||||
|
@ -248,9 +249,9 @@ def THREADUploadPending( service_key ):
|
|||
|
||||
current_ideal_weight = 100
|
||||
|
||||
result = HG.client_controller.Read( 'pending', service_key, content_types_to_request, ideal_weight = current_ideal_weight )
|
||||
result = CG.client_controller.Read( 'pending', service_key, content_types_to_request, ideal_weight = current_ideal_weight )
|
||||
|
||||
HG.client_controller.pub( 'message', job_status )
|
||||
CG.client_controller.pub( 'message', job_status )
|
||||
|
||||
no_results_found = result is None
|
||||
|
||||
|
@ -258,7 +259,7 @@ def THREADUploadPending( service_key ):
|
|||
|
||||
time_started_this_loop = HydrusTime.GetNowPrecise()
|
||||
|
||||
nums_pending = HG.client_controller.Read( 'nums_pending' )
|
||||
nums_pending = CG.client_controller.Read( 'nums_pending' )
|
||||
|
||||
nums_pending_for_this_service = nums_pending[ service_key ]
|
||||
|
||||
|
@ -297,7 +298,7 @@ def THREADUploadPending( service_key ):
|
|||
|
||||
media_result = result
|
||||
|
||||
client_files_manager = HG.client_controller.client_files_manager
|
||||
client_files_manager = CG.client_controller.client_files_manager
|
||||
|
||||
hash = media_result.GetHash()
|
||||
mime = media_result.GetMime()
|
||||
|
@ -330,7 +331,7 @@ def THREADUploadPending( service_key ):
|
|||
|
||||
if len( content_updates ) > 0:
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'content_updates', ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdates( service_key, content_updates ) )
|
||||
CG.client_controller.WriteSynchronous( 'content_updates', ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdates( service_key, content_updates ) )
|
||||
|
||||
|
||||
elif service_type == HC.IPFS:
|
||||
|
@ -376,9 +377,9 @@ def THREADUploadPending( service_key ):
|
|||
return
|
||||
|
||||
|
||||
HG.client_controller.pub( 'notify_new_pending' )
|
||||
CG.client_controller.pub( 'notify_new_pending' )
|
||||
|
||||
HG.client_controller.WaitUntilViewFree()
|
||||
CG.client_controller.WaitUntilViewFree()
|
||||
|
||||
total_time_this_loop_took = HydrusTime.GetNowPrecise() - time_started_this_loop
|
||||
|
||||
|
@ -391,7 +392,7 @@ def THREADUploadPending( service_key ):
|
|||
current_ideal_weight = min( 500, int( current_ideal_weight * 1.05 ) )
|
||||
|
||||
|
||||
result = HG.client_controller.Read( 'pending', service_key, content_types_to_request, ideal_weight = current_ideal_weight )
|
||||
result = CG.client_controller.Read( 'pending', service_key, content_types_to_request, ideal_weight = current_ideal_weight )
|
||||
|
||||
|
||||
finished_all_uploads = result is None
|
||||
|
@ -414,7 +415,7 @@ def THREADUploadPending( service_key ):
|
|||
|
||||
HydrusData.ShowText( 'Found a possible hash in that error message--trying to show it in a new page.' )
|
||||
|
||||
HG.client_controller.pub( 'imported_files_to_page', [ possible_hash ], 'files that did not upload right' )
|
||||
CG.client_controller.pub( 'imported_files_to_page', [ possible_hash ], 'files that did not upload right' )
|
||||
|
||||
|
||||
job_status.SetStatusText( service.GetName() + ' error' )
|
||||
|
@ -425,7 +426,7 @@ def THREADUploadPending( service_key ):
|
|||
|
||||
finally:
|
||||
|
||||
HG.client_controller.pub( 'notify_pending_upload_finished', service_key )
|
||||
CG.client_controller.pub( 'notify_pending_upload_finished', service_key )
|
||||
|
||||
HydrusData.Print( job_status.ToString() )
|
||||
|
||||
|
@ -460,7 +461,7 @@ def THREADUploadPending( service_key ):
|
|||
)
|
||||
|
||||
|
||||
HG.client_controller.Write( 'delete_service_info', service_key, types_to_delete )
|
||||
CG.client_controller.Write( 'delete_service_info', service_key, types_to_delete )
|
||||
|
||||
|
||||
|
||||
|
@ -842,7 +843,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
library_version_lines.append( 'psd_tools present: {}'.format( HydrusPSDHandling.PSD_TOOLS_OK ) )
|
||||
library_version_lines.append( 'speedcopy (experimental test) present: {}'.format( HydrusFileHandling.SPEEDCOPY_OK ) )
|
||||
library_version_lines.append( 'install dir: {}'.format( HC.BASE_DIR ) )
|
||||
library_version_lines.append( 'db dir: {}'.format( HG.client_controller.db_dir ) )
|
||||
library_version_lines.append( 'db dir: {}'.format( CG.client_controller.db_dir ) )
|
||||
library_version_lines.append( 'temp dir: {}'.format( HydrusTemp.GetCurrentTempDir() ) )
|
||||
library_version_lines.append( 'db cache size per file: {}MB'.format( HG.db_cache_size ) )
|
||||
library_version_lines.append( 'db journal mode: {}'.format( HG.db_journal_mode ) )
|
||||
|
@ -1037,7 +1038,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
self._controller.Write( 'backup', path )
|
||||
|
||||
HG.client_controller.new_options.SetNoneableInteger( 'last_backup_time', HydrusTime.GetNow() )
|
||||
CG.client_controller.new_options.SetNoneableInteger( 'last_backup_time', HydrusTime.GetNow() )
|
||||
|
||||
self._did_a_backup_this_session = True
|
||||
|
||||
|
@ -1257,7 +1258,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
HydrusData.ShowText( message )
|
||||
|
||||
|
||||
HG.client_controller.CallToThread( do_it )
|
||||
CG.client_controller.CallToThread( do_it )
|
||||
|
||||
|
||||
|
||||
|
@ -1527,7 +1528,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
#
|
||||
|
||||
service_keys = list( HG.client_controller.services_manager.GetServiceKeys( ( HC.TAG_REPOSITORY, ) ) )
|
||||
service_keys = list( CG.client_controller.services_manager.GetServiceKeys( ( HC.TAG_REPOSITORY, ) ) )
|
||||
|
||||
if len( service_keys ) > 0:
|
||||
|
||||
|
@ -1537,13 +1538,13 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
job_status.SetStatusTitle( 'auto-account creation test' )
|
||||
|
||||
call = HydrusData.Call( HG.client_controller.pub, 'open_manage_services_and_try_to_auto_create_account', service_key )
|
||||
call = HydrusData.Call( CG.client_controller.pub, 'open_manage_services_and_try_to_auto_create_account', service_key )
|
||||
|
||||
call.SetLabel( 'open manage services and check for auto-creatable accounts' )
|
||||
|
||||
job_status.SetUserCallable( call )
|
||||
|
||||
HG.client_controller.pub( 'message', job_status )
|
||||
CG.client_controller.pub( 'message', job_status )
|
||||
|
||||
|
||||
#
|
||||
|
@ -1594,13 +1595,13 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
note_import_options = NoteImportOptions.NoteImportOptions()
|
||||
note_import_options.SetIsDefault( True )
|
||||
|
||||
call = HydrusData.Call( HG.client_controller.pub, 'make_new_subscription_gap_downloader', ( b'', 'safebooru tag search' ), 'skirt', file_import_options, tag_import_options, note_import_options, 2 )
|
||||
call = HydrusData.Call( CG.client_controller.pub, 'make_new_subscription_gap_downloader', ( b'', 'safebooru tag search' ), 'skirt', file_import_options, tag_import_options, note_import_options, 2 )
|
||||
|
||||
call.SetLabel( 'start a new downloader for this to fill in the gap!' )
|
||||
|
||||
job_status.SetUserCallable( call )
|
||||
|
||||
HG.client_controller.pub( 'message', job_status )
|
||||
CG.client_controller.pub( 'message', job_status )
|
||||
|
||||
#
|
||||
|
||||
|
@ -1755,7 +1756,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
if result == QW.QDialog.Accepted:
|
||||
|
||||
services = HG.client_controller.services_manager.GetServices()
|
||||
services = CG.client_controller.services_manager.GetServices()
|
||||
|
||||
choice_tuples = [ ( service.GetName(), service.GetServiceKey(), service.GetName() ) for service in services ]
|
||||
|
||||
|
@ -1958,7 +1959,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
page.PageHidden()
|
||||
|
||||
|
||||
HG.client_controller.pub( 'pause_all_media' )
|
||||
CG.client_controller.pub( 'pause_all_media' )
|
||||
|
||||
for tlw in visible_tlws:
|
||||
|
||||
|
@ -2062,7 +2063,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
try:
|
||||
|
||||
job_status.SetStatusTitle( 'importing updates' )
|
||||
HG.client_controller.pub( 'message', job_status )
|
||||
CG.client_controller.pub( 'message', job_status )
|
||||
|
||||
for ( i, update_path ) in enumerate( update_paths ):
|
||||
|
||||
|
@ -2178,7 +2179,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
additional_service_keys_to_tags = ClientTags.ServiceKeysToTags()
|
||||
|
||||
|
||||
url = HG.client_controller.network_engine.domain_manager.NormaliseURL( url )
|
||||
url = CG.client_controller.network_engine.domain_manager.NormaliseURL( url )
|
||||
|
||||
( url_type, match_name, can_parse, cannot_parse_reason ) = self._controller.network_engine.domain_manager.GetURLParseCapability( url )
|
||||
|
||||
|
@ -2398,7 +2399,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
def work_callable( args ):
|
||||
|
||||
all_locations_are_default = HG.client_controller.client_files_manager.AllLocationsAreDefault()
|
||||
all_locations_are_default = CG.client_controller.client_files_manager.AllLocationsAreDefault()
|
||||
|
||||
return all_locations_are_default
|
||||
|
||||
|
@ -2413,7 +2414,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
self._menubar_database_update_backup.setVisible( all_locations_are_default and backup_path is not None )
|
||||
|
||||
last_backup_time = HG.client_controller.new_options.GetNoneableInteger( 'last_backup_time' )
|
||||
last_backup_time = CG.client_controller.new_options.GetNoneableInteger( 'last_backup_time' )
|
||||
|
||||
message = 'update database backup'
|
||||
|
||||
|
@ -2437,8 +2438,8 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
self._menubar_database_multiple_location_label.setVisible( not all_locations_are_default )
|
||||
|
||||
self._menubar_database_file_maintenance_during_idle.setChecked( HG.client_controller.new_options.GetBoolean( 'file_maintenance_during_idle' ) )
|
||||
self._menubar_database_file_maintenance_during_active.setChecked( HG.client_controller.new_options.GetBoolean( 'file_maintenance_during_active' ) )
|
||||
self._menubar_database_file_maintenance_during_idle.setChecked( CG.client_controller.new_options.GetBoolean( 'file_maintenance_during_idle' ) )
|
||||
self._menubar_database_file_maintenance_during_active.setChecked( CG.client_controller.new_options.GetBoolean( 'file_maintenance_during_active' ) )
|
||||
|
||||
|
||||
return ClientGUIAsync.AsyncQtUpdater( self, loading_callable, work_callable, publish_callable )
|
||||
|
@ -2454,8 +2455,8 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
def work_callable( args ):
|
||||
|
||||
import_folder_names = HG.client_controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FOLDER )
|
||||
export_folder_names = HG.client_controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_EXPORT_FOLDER )
|
||||
import_folder_names = CG.client_controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_IMPORT_FOLDER )
|
||||
export_folder_names = CG.client_controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_EXPORT_FOLDER )
|
||||
|
||||
return ( import_folder_names, export_folder_names )
|
||||
|
||||
|
@ -2506,7 +2507,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
|
||||
|
||||
simple_non_windows = not HC.PLATFORM_WINDOWS and not HG.client_controller.new_options.GetBoolean( 'advanced_mode' )
|
||||
simple_non_windows = not HC.PLATFORM_WINDOWS and not CG.client_controller.new_options.GetBoolean( 'advanced_mode' )
|
||||
|
||||
windows_or_advanced_non_windows = not simple_non_windows
|
||||
|
||||
|
@ -2534,11 +2535,11 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
self._menubar_network_nudge_subs.setVisible( advanced_mode )
|
||||
|
||||
self._menubar_network_all_traffic_paused.setChecked( HG.client_controller.new_options.GetBoolean( 'pause_all_new_network_traffic' ) )
|
||||
self._menubar_network_all_traffic_paused.setChecked( CG.client_controller.new_options.GetBoolean( 'pause_all_new_network_traffic' ) )
|
||||
|
||||
self._menubar_network_subscriptions_paused.setChecked( HG.client_controller.new_options.GetBoolean( 'pause_subs_sync' ) )
|
||||
self._menubar_network_subscriptions_paused.setChecked( CG.client_controller.new_options.GetBoolean( 'pause_subs_sync' ) )
|
||||
|
||||
self._menubar_network_paged_import_queues_paused.setChecked( HG.client_controller.new_options.GetBoolean( 'pause_all_file_queues' ) )
|
||||
self._menubar_network_paged_import_queues_paused.setChecked( CG.client_controller.new_options.GetBoolean( 'pause_all_file_queues' ) )
|
||||
|
||||
|
||||
return ClientGUIAsync.AsyncQtUpdater( self, loading_callable, work_callable, publish_callable )
|
||||
|
@ -2555,11 +2556,11 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
def work_callable( args ):
|
||||
|
||||
gui_session_names = HG.client_controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION_CONTAINER )
|
||||
gui_session_names = CG.client_controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION_CONTAINER )
|
||||
|
||||
if len( gui_session_names ) > 0:
|
||||
|
||||
gui_session_names_to_backup_timestamps_ms = HG.client_controller.Read( 'serialisable_names_to_backup_timestamps_ms', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION_CONTAINER )
|
||||
gui_session_names_to_backup_timestamps_ms = CG.client_controller.Read( 'serialisable_names_to_backup_timestamps_ms', HydrusSerialisable.SERIALISABLE_TYPE_GUI_SESSION_CONTAINER )
|
||||
|
||||
else:
|
||||
|
||||
|
@ -2724,7 +2725,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
def work_callable( args ):
|
||||
|
||||
nums_pending = HG.client_controller.Read( 'nums_pending' )
|
||||
nums_pending = CG.client_controller.Read( 'nums_pending' )
|
||||
|
||||
return nums_pending
|
||||
|
||||
|
@ -2984,8 +2985,8 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
def publish_callable( result ):
|
||||
|
||||
self._menubar_tags_tag_display_maintenance_during_idle.setChecked( HG.client_controller.new_options.GetBoolean( 'tag_display_maintenance_during_idle' ) )
|
||||
self._menubar_tags_tag_display_maintenance_during_active.setChecked( HG.client_controller.new_options.GetBoolean( 'tag_display_maintenance_during_active' ) )
|
||||
self._menubar_tags_tag_display_maintenance_during_idle.setChecked( CG.client_controller.new_options.GetBoolean( 'tag_display_maintenance_during_idle' ) )
|
||||
self._menubar_tags_tag_display_maintenance_during_active.setChecked( CG.client_controller.new_options.GetBoolean( 'tag_display_maintenance_during_active' ) )
|
||||
|
||||
|
||||
return ClientGUIAsync.AsyncQtUpdater( self, loading_callable, work_callable, publish_callable )
|
||||
|
@ -3357,8 +3358,8 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
profile_mode_message += 'More information is available in the help, under \'reducing program lag\'.'
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( profiling, 'what is this?', 'Show profile info.', ClientGUIDialogsMessage.ShowInformation, self, profile_mode_message )
|
||||
ClientGUIMenus.AppendMenuCheckItem( profiling, 'profile mode', 'Run detailed \'profiles\'.', HG.profile_mode, HG.client_controller.FlipProfileMode )
|
||||
ClientGUIMenus.AppendMenuCheckItem( profiling, 'query planner mode', 'Run detailed \'query plans\'.', HG.query_planner_mode, HG.client_controller.FlipQueryPlannerMode )
|
||||
ClientGUIMenus.AppendMenuCheckItem( profiling, 'profile mode', 'Run detailed \'profiles\'.', HG.profile_mode, CG.client_controller.FlipProfileMode )
|
||||
ClientGUIMenus.AppendMenuCheckItem( profiling, 'query planner mode', 'Run detailed \'query plans\'.', HG.query_planner_mode, CG.client_controller.FlipQueryPlannerMode )
|
||||
|
||||
ClientGUIMenus.AppendMenu( debug, profiling, 'profiling' )
|
||||
|
||||
|
@ -3387,7 +3388,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
gui_actions = ClientGUIMenus.GenerateMenu( debug )
|
||||
|
||||
default_location_context = HG.client_controller.new_options.GetDefaultLocalLocationContext()
|
||||
default_location_context = CG.client_controller.new_options.GetDefaultLocalLocationContext()
|
||||
|
||||
def flip_macos_antiflicker():
|
||||
|
||||
|
@ -3413,7 +3414,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
ClientGUIMenus.AppendMenuItem( gui_actions, 'make a QMessageBox', 'Open a modal message dialog.', self._DebugMakeQMessageBox )
|
||||
ClientGUIMenus.AppendMenuItem( gui_actions, 'make a new page in five seconds', 'Throw a delayed page at the main notebook, giving you time to minimise or otherwise alter the client before it arrives.', self._controller.CallLater, 5, self._controller.pub, 'new_page_query', default_location_context )
|
||||
ClientGUIMenus.AppendMenuItem( gui_actions, 'refresh pages menu in five seconds', 'Delayed refresh the pages menu, giving you time to minimise or otherwise alter the client before it arrives.', self._controller.CallLater, 5, self._menu_updater_pages.update )
|
||||
ClientGUIMenus.AppendMenuItem( gui_actions, 'publish some sub files in five seconds', 'Publish some files like a subscription would.', self._controller.CallLater, 5, lambda: HG.client_controller.pub( 'imported_files_to_page', [ HydrusData.GenerateKey() for i in range( 5 ) ], 'example sub files' ) )
|
||||
ClientGUIMenus.AppendMenuItem( gui_actions, 'publish some sub files in five seconds', 'Publish some files like a subscription would.', self._controller.CallLater, 5, lambda: CG.client_controller.pub( 'imported_files_to_page', [ HydrusData.GenerateKey() for i in range( 5 ) ], 'example sub files' ) )
|
||||
ClientGUIMenus.AppendMenuItem( gui_actions, 'make a parentless text ctrl dialog', 'Make a parentless text control in a dialog to test some character event catching.', self._DebugMakeParentlessTextCtrl )
|
||||
ClientGUIMenus.AppendMenuItem( gui_actions, 'reset multi-column list settings to default', 'Reset all multi-column list widths and other display settings to default.', self._DebugResetColumnListManager )
|
||||
ClientGUIMenus.AppendMenuItem( gui_actions, 'force a main gui layout now', 'Tell the gui to relayout--useful to test some gui bootup layout issues.', self.adjustSize )
|
||||
|
@ -3681,7 +3682,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
special_command_menu = ClientGUIMenus.GenerateMenu( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( special_command_menu, 'clear all multiwatcher highlights', 'Command all multiwatcher pages to clear their highlighted watchers.', HG.client_controller.pub, 'clear_multiwatcher_highlights' )
|
||||
ClientGUIMenus.AppendMenuItem( special_command_menu, 'clear all multiwatcher highlights', 'Command all multiwatcher pages to clear their highlighted watchers.', CG.client_controller.pub, 'clear_multiwatcher_highlights' )
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, special_command_menu, 'special commands' )
|
||||
|
||||
|
@ -3816,7 +3817,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
if load_a_blank_page:
|
||||
|
||||
default_location_context = HG.client_controller.new_options.GetDefaultLocalLocationContext()
|
||||
default_location_context = CG.client_controller.new_options.GetDefaultLocalLocationContext()
|
||||
|
||||
self._notebook.NewPageQuery( default_location_context, on_deepest_notebook = True )
|
||||
|
||||
|
@ -3883,7 +3884,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
def _STARTManageAccountTypes( self, service_key ):
|
||||
|
||||
admin_service = HG.client_controller.services_manager.GetService( service_key )
|
||||
admin_service = CG.client_controller.services_manager.GetService( service_key )
|
||||
|
||||
job_status = ClientThreading.JobStatus()
|
||||
|
||||
|
@ -3920,7 +3921,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
def _ManageAccountTypes( self, service_key, account_types ):
|
||||
|
||||
admin_service = HG.client_controller.services_manager.GetService( service_key )
|
||||
admin_service = CG.client_controller.services_manager.GetService( service_key )
|
||||
|
||||
title = 'edit account types'
|
||||
|
||||
|
@ -4011,7 +4012,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
url_class_keys_to_display = domain_manager.GetURLClassKeysToDisplay()
|
||||
|
||||
show_unmatched_urls_in_media_viewer = HG.client_controller.new_options.GetBoolean( 'show_unmatched_urls_in_media_viewer' )
|
||||
show_unmatched_urls_in_media_viewer = CG.client_controller.new_options.GetBoolean( 'show_unmatched_urls_in_media_viewer' )
|
||||
|
||||
panel = ClientGUIDownloaders.EditDownloaderDisplayPanel( dlg, self._controller.network_engine, gugs, gug_keys_to_display, url_classes, url_class_keys_to_display, show_unmatched_urls_in_media_viewer )
|
||||
|
||||
|
@ -4024,7 +4025,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
domain_manager.SetGUGKeysToDisplay( gug_keys_to_display )
|
||||
domain_manager.SetURLClassKeysToDisplay( url_class_keys_to_display )
|
||||
|
||||
HG.client_controller.new_options.SetBoolean( 'show_unmatched_urls_in_media_viewer', show_unmatched_urls_in_media_viewer )
|
||||
CG.client_controller.new_options.SetBoolean( 'show_unmatched_urls_in_media_viewer', show_unmatched_urls_in_media_viewer )
|
||||
|
||||
|
||||
|
||||
|
@ -4378,7 +4379,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
self._controller.pub( 'notify_new_colourset' )
|
||||
self._controller.pub( 'notify_new_favourite_tags' )
|
||||
|
||||
self._menu_item_help_darkmode.setChecked( HG.client_controller.new_options.GetString( 'current_colourset' ) == 'darkmode' )
|
||||
self._menu_item_help_darkmode.setChecked( CG.client_controller.new_options.GetString( 'current_colourset' ) == 'darkmode' )
|
||||
|
||||
self._UpdateSystemTrayIcon()
|
||||
|
||||
|
@ -4537,7 +4538,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'edit tag repository tag filter' ) as dlg:
|
||||
|
||||
namespaces = HG.client_controller.network_engine.domain_manager.GetParserNamespaces()
|
||||
namespaces = CG.client_controller.network_engine.domain_manager.GetParserNamespaces()
|
||||
|
||||
message = 'The repository will apply this to all new pending tags that are uploaded to it. Anything that does not pass is silently discarded.'
|
||||
|
||||
|
@ -4678,7 +4679,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
query_log_container = ClientImportSubscriptionQuery.SubscriptionQueryLogContainer( missing_query_log_container_name )
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'serialisable', query_log_container )
|
||||
CG.client_controller.WriteSynchronous( 'serialisable', query_log_container )
|
||||
|
||||
|
||||
for subscription in subscriptions:
|
||||
|
@ -4692,7 +4693,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
|
||||
|
||||
HG.client_controller.subscriptions_manager.SetSubscriptions( subscriptions ) # save the reset
|
||||
CG.client_controller.subscriptions_manager.SetSubscriptions( subscriptions ) # save the reset
|
||||
|
||||
else:
|
||||
|
||||
|
@ -4718,7 +4719,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
for surplus_query_log_container_name in surplus_query_log_container_names:
|
||||
|
||||
surplus_query_log_container = HG.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION_QUERY_LOG_CONTAINER, surplus_query_log_container_name )
|
||||
surplus_query_log_container = CG.client_controller.Read( 'serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION_QUERY_LOG_CONTAINER, surplus_query_log_container_name )
|
||||
|
||||
backup_path = os.path.join( sub_dir, 'qlc_{}.json'.format( surplus_query_log_container_name ) )
|
||||
|
||||
|
@ -4727,7 +4728,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
f.write( surplus_query_log_container.DumpToString() )
|
||||
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'delete_serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION_QUERY_LOG_CONTAINER, surplus_query_log_container_name )
|
||||
CG.client_controller.WriteSynchronous( 'delete_serialisable_named', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION_QUERY_LOG_CONTAINER, surplus_query_log_container_name )
|
||||
|
||||
|
||||
else:
|
||||
|
@ -4772,9 +4773,9 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
try:
|
||||
|
||||
HG.client_controller.subscriptions_manager.PauseSubscriptionsForEditing()
|
||||
CG.client_controller.subscriptions_manager.PauseSubscriptionsForEditing()
|
||||
|
||||
while HG.client_controller.subscriptions_manager.SubscriptionsRunning():
|
||||
while CG.client_controller.subscriptions_manager.SubscriptionsRunning():
|
||||
|
||||
time.sleep( 0.1 )
|
||||
|
||||
|
@ -4789,7 +4790,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
job_status.FinishAndDismiss()
|
||||
|
||||
|
||||
subscriptions = HG.client_controller.subscriptions_manager.GetSubscriptions()
|
||||
subscriptions = CG.client_controller.subscriptions_manager.GetSubscriptions()
|
||||
|
||||
expected_query_log_container_names = set()
|
||||
|
||||
|
@ -4798,7 +4799,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
expected_query_log_container_names.update( subscription.GetAllQueryLogContainerNames() )
|
||||
|
||||
|
||||
actual_query_log_container_names = set( HG.client_controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION_QUERY_LOG_CONTAINER ) )
|
||||
actual_query_log_container_names = set( CG.client_controller.Read( 'serialisable_names', HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION_QUERY_LOG_CONTAINER ) )
|
||||
|
||||
missing_query_log_container_names = expected_query_log_container_names.difference( actual_query_log_container_names )
|
||||
|
||||
|
@ -4814,14 +4815,14 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
controller.pub( 'message', done_job_status )
|
||||
|
||||
HG.client_controller.WriteSynchronous(
|
||||
CG.client_controller.WriteSynchronous(
|
||||
'serialisable_atomic',
|
||||
overwrite_types_and_objs = ( [ HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION ], subscriptions ),
|
||||
set_objs = edited_query_log_containers,
|
||||
deletee_types_to_names = { HydrusSerialisable.SERIALISABLE_TYPE_SUBSCRIPTION_QUERY_LOG_CONTAINER : deletee_query_log_container_names }
|
||||
)
|
||||
|
||||
HG.client_controller.subscriptions_manager.SetSubscriptions( subscriptions )
|
||||
CG.client_controller.subscriptions_manager.SetSubscriptions( subscriptions )
|
||||
|
||||
except HydrusExceptions.QtDeadWindowException:
|
||||
|
||||
|
@ -4829,7 +4830,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
except HydrusExceptions.CancelledException:
|
||||
|
||||
HG.client_controller.subscriptions_manager.Wake()
|
||||
CG.client_controller.subscriptions_manager.Wake()
|
||||
|
||||
finally:
|
||||
|
||||
|
@ -4838,7 +4839,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
finally:
|
||||
|
||||
HG.client_controller.subscriptions_manager.ResumeSubscriptionsAfterEditing()
|
||||
CG.client_controller.subscriptions_manager.ResumeSubscriptionsAfterEditing()
|
||||
|
||||
|
||||
|
||||
|
@ -5126,7 +5127,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
busy_tooltip = None
|
||||
|
||||
|
||||
( db_status, job_name ) = HG.client_controller.GetDBStatus()
|
||||
( db_status, job_name ) = CG.client_controller.GetDBStatus()
|
||||
|
||||
if job_name is not None and job_name != '':
|
||||
|
||||
|
@ -5529,7 +5530,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
def _STARTReviewAllAccounts( self, service_key ):
|
||||
|
||||
admin_service = HG.client_controller.services_manager.GetService( service_key )
|
||||
admin_service = CG.client_controller.services_manager.GetService( service_key )
|
||||
|
||||
job_status = ClientThreading.JobStatus()
|
||||
|
||||
|
@ -5719,7 +5720,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
# job key
|
||||
|
||||
client_api_service = HG.client_controller.services_manager.GetService( CC.CLIENT_API_SERVICE_KEY )
|
||||
client_api_service = CG.client_controller.services_manager.GetService( CC.CLIENT_API_SERVICE_KEY )
|
||||
|
||||
port = client_api_service.GetPort()
|
||||
|
||||
|
@ -5731,7 +5732,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
client_api_service._port = port
|
||||
|
||||
HG.client_controller.RestartClientServerServices()
|
||||
CG.client_controller.RestartClientServerServices()
|
||||
|
||||
time.sleep( 5 )
|
||||
|
||||
|
@ -5742,7 +5743,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
access_key = api_permissions.GetAccessKey()
|
||||
|
||||
HG.client_controller.client_api_manager.AddAccess( api_permissions )
|
||||
CG.client_controller.client_api_manager.AddAccess( api_permissions )
|
||||
|
||||
#
|
||||
|
||||
|
@ -5752,7 +5753,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
job_status.SetStatusTitle( 'client api test' )
|
||||
|
||||
HG.client_controller.pub( 'message', job_status )
|
||||
CG.client_controller.pub( 'message', job_status )
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
@ -5790,7 +5791,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
job_status.SetStatusText( 'add url test' )
|
||||
|
||||
local_tag_services = HG.client_controller.services_manager.GetServices( ( HC.LOCAL_TAG, ) )
|
||||
local_tag_services = CG.client_controller.services_manager.GetServices( ( HC.LOCAL_TAG, ) )
|
||||
|
||||
local_tag_service = random.choice( local_tag_services )
|
||||
|
||||
|
@ -5946,7 +5947,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
return page.GetPageKey()
|
||||
|
||||
|
||||
page_key = HG.client_controller.CallBlockingToQt( HG.client_controller.gui, qt_session_gubbins )
|
||||
page_key = CG.client_controller.CallBlockingToQt( CG.client_controller.gui, qt_session_gubbins )
|
||||
|
||||
#
|
||||
|
||||
|
@ -5969,7 +5970,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
#
|
||||
|
||||
HG.client_controller.client_api_manager.DeleteAccess( ( access_key, ) )
|
||||
CG.client_controller.client_api_manager.DeleteAccess( ( access_key, ) )
|
||||
|
||||
#
|
||||
|
||||
|
@ -5977,14 +5978,14 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
client_api_service._port = None
|
||||
|
||||
HG.client_controller.RestartClientServerServices()
|
||||
CG.client_controller.RestartClientServerServices()
|
||||
|
||||
|
||||
job_status.FinishAndDismiss()
|
||||
|
||||
|
||||
|
||||
HG.client_controller.CallToThread( do_it )
|
||||
CG.client_controller.CallToThread( do_it )
|
||||
|
||||
|
||||
def _RunUITest( self ):
|
||||
|
@ -5995,41 +5996,41 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
t = 0.25
|
||||
|
||||
default_location_context = HG.client_controller.new_options.GetDefaultLocalLocationContext()
|
||||
default_location_context = CG.client_controller.new_options.GetDefaultLocalLocationContext()
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self._notebook.NewPageQuery, default_location_context, page_name = 'test', on_deepest_notebook = True )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self._notebook.NewPageQuery, default_location_context, page_name = 'test', on_deepest_notebook = True )
|
||||
|
||||
t += 0.25
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_PAGE_OF_PAGES ) )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_PAGE_OF_PAGES ) )
|
||||
|
||||
t += 0.25
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', page_of_pages.NewPageQuery, default_location_context, page_name ='test', on_deepest_notebook = False )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', page_of_pages.NewPageQuery, default_location_context, page_name ='test', on_deepest_notebook = False )
|
||||
|
||||
t += 0.25
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_DUPLICATE_FILTER_PAGE ) )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_DUPLICATE_FILTER_PAGE ) )
|
||||
|
||||
t += 0.25
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_GALLERY_DOWNLOADER_PAGE ) )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_GALLERY_DOWNLOADER_PAGE ) )
|
||||
|
||||
t += 0.25
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_SIMPLE_DOWNLOADER_PAGE ) )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_SIMPLE_DOWNLOADER_PAGE ) )
|
||||
|
||||
t += 0.25
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_URL_DOWNLOADER_PAGE ) )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_URL_DOWNLOADER_PAGE ) )
|
||||
|
||||
t += 0.25
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_WATCHER_DOWNLOADER_PAGE ) )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_NEW_WATCHER_DOWNLOADER_PAGE ) )
|
||||
|
||||
t += 0.25
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProposeSaveGUISession, CC.LAST_SESSION_SESSION_NAME )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProposeSaveGUISession, CC.LAST_SESSION_SESSION_NAME )
|
||||
|
||||
return page_of_pages
|
||||
|
||||
|
@ -6038,7 +6039,7 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
self._notebook.CloseCurrentPage()
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, 0.5, 'test job', self._UnclosePage )
|
||||
CG.client_controller.CallLaterQtSafe( self, 0.5, 'test job', self._UnclosePage )
|
||||
|
||||
|
||||
def qt_close_pages( page_of_pages ):
|
||||
|
@ -6051,23 +6052,23 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
for i in indices:
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', page_of_pages._ClosePage, i )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', page_of_pages._ClosePage, i )
|
||||
|
||||
t += 0.25
|
||||
|
||||
|
||||
t += 0.25
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self._notebook.CloseCurrentPage )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self._notebook.CloseCurrentPage )
|
||||
|
||||
t += 0.25
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self.DeleteAllClosedPages )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self.DeleteAllClosedPages )
|
||||
|
||||
|
||||
def qt_test_ac():
|
||||
|
||||
default_location_context = HG.client_controller.new_options.GetDefaultLocalLocationContext()
|
||||
default_location_context = CG.client_controller.new_options.GetDefaultLocalLocationContext()
|
||||
|
||||
SYS_PRED_REFRESH = 1.0
|
||||
|
||||
|
@ -6075,17 +6076,17 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
t = 0.5
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', page.SetSearchFocus )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', page.SetSearchFocus )
|
||||
|
||||
ac_widget = page.GetManagementPanel()._tag_autocomplete._text_ctrl
|
||||
|
||||
t += 0.5
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_SET_MEDIA_FOCUS ) )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_SET_MEDIA_FOCUS ) )
|
||||
|
||||
t += 0.5
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_SET_SEARCH_FOCUS ) )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self.ProcessApplicationCommand, CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_SET_SEARCH_FOCUS ) )
|
||||
|
||||
t += 0.5
|
||||
|
||||
|
@ -6093,36 +6094,36 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
for c in 'the colour of her hair':
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, ord( c ), text = c )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, ord( c ), text = c )
|
||||
|
||||
t += 0.01
|
||||
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
|
||||
t += SYS_PRED_REFRESH
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
|
||||
t += SYS_PRED_REFRESH
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Down )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Down )
|
||||
|
||||
t += 0.05
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
|
||||
t += SYS_PRED_REFRESH
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Down )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Down )
|
||||
|
||||
t += 0.05
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
|
||||
t += SYS_PRED_REFRESH
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
|
||||
for i in range( 16 ):
|
||||
|
||||
|
@ -6130,44 +6131,44 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
for j in range( i + 1 ):
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Down )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Down )
|
||||
|
||||
t += 0.1
|
||||
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
|
||||
t += SYS_PRED_REFRESH
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, None, QC.Qt.Key_Return )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, None, QC.Qt.Key_Return )
|
||||
|
||||
|
||||
t += 1.0
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Down )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Down )
|
||||
|
||||
t += 0.05
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', uias.Char, ac_widget, QC.Qt.Key_Return )
|
||||
|
||||
t += 1.0
|
||||
|
||||
HG.client_controller.CallLaterQtSafe( self, t, 'test job', self._notebook.CloseCurrentPage )
|
||||
CG.client_controller.CallLaterQtSafe( self, t, 'test job', self._notebook.CloseCurrentPage )
|
||||
|
||||
|
||||
def do_it():
|
||||
|
||||
# pages
|
||||
|
||||
page_of_pages = HG.client_controller.CallBlockingToQt( self, qt_open_pages )
|
||||
page_of_pages = CG.client_controller.CallBlockingToQt( self, qt_open_pages )
|
||||
|
||||
time.sleep( 4 )
|
||||
|
||||
HG.client_controller.CallBlockingToQt( self, qt_close_unclose_one_page )
|
||||
CG.client_controller.CallBlockingToQt( self, qt_close_unclose_one_page )
|
||||
|
||||
time.sleep( 1.5 )
|
||||
|
||||
HG.client_controller.CallBlockingToQt( self, qt_close_pages, page_of_pages )
|
||||
CG.client_controller.CallBlockingToQt( self, qt_close_pages, page_of_pages )
|
||||
|
||||
time.sleep( 5 )
|
||||
|
||||
|
@ -6175,10 +6176,10 @@ class FrameGUI( CAC.ApplicationCommandProcessorMixin, ClientGUITopLevelWindows.M
|
|||
|
||||
# a/c
|
||||
|
||||
HG.client_controller.CallBlockingToQt( self, qt_test_ac )
|
||||
CG.client_controller.CallBlockingToQt( self, qt_test_ac )
|
||||
|
||||
|
||||
HG.client_controller.CallToThread( do_it )
|
||||
CG.client_controller.CallToThread( do_it )
|
||||
|
||||
|
||||
def _RunServerTest( self, do_boot = True ):
|
||||
|
@ -6868,7 +6869,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
def _UpdateSystemTrayIcon( self, currently_booting = False ):
|
||||
|
||||
if not ClientGUISystemTray.SystemTrayAvailable() or ( not HC.PLATFORM_WINDOWS and not HG.client_controller.new_options.GetBoolean( 'advanced_mode' ) ):
|
||||
if not ClientGUISystemTray.SystemTrayAvailable() or ( not HC.PLATFORM_WINDOWS and not CG.client_controller.new_options.GetBoolean( 'advanced_mode' ) ):
|
||||
|
||||
return
|
||||
|
||||
|
@ -7013,7 +7014,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
else:
|
||||
|
||||
HG.client_controller.pub( 'pause_all_media' )
|
||||
CG.client_controller.pub( 'pause_all_media' )
|
||||
|
||||
title = job_status.GetStatusTitle()
|
||||
|
||||
|
@ -7310,7 +7311,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
self._new_options.SetString( 'current_colourset', new_colourset )
|
||||
|
||||
HG.client_controller.pub( 'notify_new_colourset' )
|
||||
CG.client_controller.pub( 'notify_new_colourset' )
|
||||
|
||||
|
||||
def FlipNetworkTrafficPaused( self ):
|
||||
|
@ -7416,7 +7417,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
shown = not self._currently_minimised_to_system_tray
|
||||
|
||||
windows_or_advanced_mode = HC.PLATFORM_WINDOWS or HG.client_controller.new_options.GetBoolean( 'advanced_mode' )
|
||||
windows_or_advanced_mode = HC.PLATFORM_WINDOWS or CG.client_controller.new_options.GetBoolean( 'advanced_mode' )
|
||||
|
||||
good_to_go = ClientGUISystemTray.SystemTrayAvailable() and windows_or_advanced_mode
|
||||
|
||||
|
@ -7817,11 +7818,11 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
elif action == CAC.SIMPLE_GLOBAL_PROFILE_MODE_FLIP:
|
||||
|
||||
HG.client_controller.FlipProfileMode()
|
||||
CG.client_controller.FlipProfileMode()
|
||||
|
||||
elif action == CAC.SIMPLE_GLOBAL_FORCE_ANIMATION_SCANBAR_SHOW:
|
||||
|
||||
HG.client_controller.new_options.FlipBoolean( 'force_animation_scanbar_show' )
|
||||
CG.client_controller.new_options.FlipBoolean( 'force_animation_scanbar_show' )
|
||||
|
||||
elif action == CAC.SIMPLE_OPEN_COMMAND_PALETTE:
|
||||
|
||||
|
@ -8069,7 +8070,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
|
||||
try:
|
||||
|
||||
text = HG.client_controller.GetClipboardText()
|
||||
text = CG.client_controller.GetClipboardText()
|
||||
|
||||
except HydrusExceptions.DataMissing:
|
||||
|
||||
|
@ -8318,7 +8319,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
return
|
||||
|
||||
|
||||
HG.client_controller.pub( 'pause_all_media' )
|
||||
CG.client_controller.pub( 'pause_all_media' )
|
||||
|
||||
try:
|
||||
|
||||
|
@ -8484,7 +8485,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
|||
text = 'Is now a good time for the client to do up to ' + HydrusData.ToHumanInt( idle_shutdown_max_minutes ) + ' minutes\' maintenance work? (Will auto-no in 15 seconds)'
|
||||
text += os.linesep * 2
|
||||
|
||||
if HG.client_controller.IsFirstStart():
|
||||
if CG.client_controller.IsFirstStart():
|
||||
|
||||
text += 'Since this is your first session, this maintenance should just be some quick initialisation work. It should only take a few seconds.'
|
||||
text += os.linesep * 2
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import os
|
||||
import time
|
||||
|
||||
from qtpy import QtWidgets as QW
|
||||
|
||||
from hydrus.core import HydrusConstants as HC
|
||||
from hydrus.core import HydrusExceptions
|
||||
from hydrus.core import HydrusGlobals as HG
|
||||
from hydrus.core import HydrusTime
|
||||
|
||||
from hydrus.client import ClientPaths
|
||||
from hydrus.client.gui import ClientGUIScrolledPanelsButtonQuestions
|
||||
|
@ -81,6 +83,41 @@ def GetInterstitialFilteringAnswer( win, label ):
|
|||
return result
|
||||
|
||||
|
||||
|
||||
def run_auto_yes_no_gubbins( dlg: QW.QDialog, time_to_fire, original_title, action_description, end_state ):
|
||||
|
||||
def qt_set_title():
|
||||
|
||||
time_string = HydrusTime.TimestampToPrettyTimeDelta( time_to_fire, just_now_threshold = 0, just_now_string = 'imminently' )
|
||||
|
||||
title = f'{original_title} (will {action_description} {time_string})'
|
||||
|
||||
dlg.setWindowTitle( title )
|
||||
|
||||
|
||||
def qt_fire_button():
|
||||
|
||||
if dlg.isModal():
|
||||
|
||||
dlg.done( end_state )
|
||||
|
||||
|
||||
|
||||
while not HydrusTime.TimeHasPassed( time_to_fire ):
|
||||
|
||||
job = HG.client_controller.CallLaterQtSafe( dlg, 0.0, 'dialog auto yes/no title set', qt_set_title )
|
||||
|
||||
if job.IsDead(): # window closed
|
||||
|
||||
return
|
||||
|
||||
|
||||
time.sleep( 1 )
|
||||
|
||||
|
||||
job = HG.client_controller.CallLaterQtSafe( dlg, 0.0, 'dialog auto yes/no fire', qt_fire_button )
|
||||
|
||||
|
||||
def GetYesNo( win, message, title = 'Are you sure?', yes_label = 'yes', no_label = 'no', auto_yes_time = None, auto_no_time = None, check_for_cancelled = False ):
|
||||
|
||||
with ClientGUITopLevelWindowsPanels.DialogCustomButtonQuestion( win, title ) as dlg:
|
||||
|
@ -89,32 +126,22 @@ def GetYesNo( win, message, title = 'Are you sure?', yes_label = 'yes', no_label
|
|||
|
||||
dlg.SetPanel( panel )
|
||||
|
||||
if auto_yes_time is None and auto_no_time is None:
|
||||
|
||||
return dlg.exec() if not check_for_cancelled else ( dlg.exec(), dlg.WasCancelled() )
|
||||
|
||||
else:
|
||||
if auto_yes_time is not None or auto_no_time is not None:
|
||||
|
||||
if auto_yes_time is not None:
|
||||
|
||||
job = HG.client_controller.CallLaterQtSafe( dlg, auto_yes_time, 'dialog auto-yes', dlg.done, QW.QDialog.Accepted )
|
||||
HG.client_controller.CallToThread( run_auto_yes_no_gubbins, dlg, HydrusTime.GetNow() + auto_yes_time, dlg.windowTitle(), 'auto-yes', QW.QDialog.Accepted )
|
||||
|
||||
elif auto_no_time is not None:
|
||||
|
||||
job = HG.client_controller.CallLaterQtSafe( dlg, auto_no_time, 'dialog auto-no', dlg.done, QW.QDialog.Rejected )
|
||||
|
||||
|
||||
try:
|
||||
|
||||
return dlg.exec() if not check_for_cancelled else ( dlg.exec(), dlg.WasCancelled() )
|
||||
|
||||
finally:
|
||||
|
||||
job.Cancel()
|
||||
HG.client_controller.CallToThread( run_auto_yes_no_gubbins, dlg, HydrusTime.GetNow() + auto_no_time, dlg.windowTitle(), 'auto-no', QW.QDialog.Rejected )
|
||||
|
||||
|
||||
|
||||
return dlg.exec() if not check_for_cancelled else ( dlg.exec(), dlg.WasCancelled() )
|
||||
|
||||
|
||||
|
||||
def GetYesYesNo( win, message, title = 'Are you sure?', yes_tuples = None, no_label = 'no' ):
|
||||
|
||||
with ClientGUITopLevelWindowsPanels.DialogCustomButtonQuestion( win, title ) as dlg:
|
||||
|
|
|
@ -219,7 +219,8 @@ def ShowFilesInNewPage( file_seed_cache: ClientImportFileSeeds.FileSeedCache, sh
|
|||
|
||||
def PopulateFileSeedCacheMenu( win: QW.QWidget, menu: QW.QMenu, file_seed_cache: ClientImportFileSeeds.FileSeedCache ):
|
||||
|
||||
num_successful = file_seed_cache.GetFileSeedCount( CC.STATUS_SUCCESSFUL_AND_NEW ) + file_seed_cache.GetFileSeedCount( CC.STATUS_SUCCESSFUL_BUT_REDUNDANT )
|
||||
num_already_in = file_seed_cache.GetFileSeedCount( CC.STATUS_SUCCESSFUL_BUT_REDUNDANT )
|
||||
num_successful = file_seed_cache.GetFileSeedCount( CC.STATUS_SUCCESSFUL_AND_NEW ) + num_already_in
|
||||
num_vetoed = file_seed_cache.GetFileSeedCount( CC.STATUS_VETOED )
|
||||
num_deleted = file_seed_cache.GetFileSeedCount( CC.STATUS_DELETED )
|
||||
num_errors = file_seed_cache.GetFileSeedCount( CC.STATUS_ERROR )
|
||||
|
@ -242,6 +243,11 @@ def PopulateFileSeedCacheMenu( win: QW.QWidget, menu: QW.QMenu, file_seed_cache:
|
|||
ClientGUIMenus.AppendMenuItem( menu, 'delete {} \'successful\' file import items from the queue'.format( HydrusData.ToHumanInt( num_successful ) ), 'Tell this log to clear out successful files, reducing the size of the queue.', ClearFileSeeds, win, file_seed_cache, ( CC.STATUS_SUCCESSFUL_AND_NEW, CC.STATUS_SUCCESSFUL_BUT_REDUNDANT, CC.STATUS_SUCCESSFUL_AND_CHILD_FILES ) )
|
||||
|
||||
|
||||
if num_already_in > 0:
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( menu, 'delete {} \'already in db\' file import items from the queue'.format( HydrusData.ToHumanInt( num_already_in ) ), 'Tell this log to clear out successful but non-new files, reducing the size of the queue.', ClearFileSeeds, win, file_seed_cache, ( CC.STATUS_SUCCESSFUL_BUT_REDUNDANT, ) )
|
||||
|
||||
|
||||
if num_deleted > 0:
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( menu, 'delete {} \'previously deleted\' file import items from the queue'.format( HydrusData.ToHumanInt( num_deleted ) ), 'Tell this log to clear out deleted files, reducing the size of the queue.', ClearFileSeeds, win, file_seed_cache, ( CC.STATUS_DELETED, ) )
|
||||
|
@ -262,6 +268,13 @@ def PopulateFileSeedCacheMenu( win: QW.QWidget, menu: QW.QMenu, file_seed_cache:
|
|||
ClientGUIMenus.AppendMenuItem( menu, 'delete {} \'skipped\' file import items from the queue'.format( HydrusData.ToHumanInt( num_skipped ) ), 'Tell this log to clear out skipped files, reducing the size of the queue.', ClearFileSeeds, win, file_seed_cache, ( CC.STATUS_SKIPPED, ) )
|
||||
|
||||
|
||||
if len( file_seed_cache ) > 0:
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( menu, 'delete everything from the queue', 'Tell this log to clear out everything, resetting the queue to empty.', ClearFileSeeds, win, file_seed_cache, ( CC.STATUS_UNKNOWN, CC.STATUS_SUCCESSFUL_AND_NEW, CC.STATUS_SUCCESSFUL_BUT_REDUNDANT, CC.STATUS_DELETED, CC.STATUS_ERROR, CC.STATUS_VETOED, CC.STATUS_SKIPPED, CC.STATUS_SUCCESSFUL_AND_CHILD_FILES ) )
|
||||
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
if num_successful > 0:
|
||||
|
@ -354,7 +367,7 @@ class EditFileSeedCachePanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
note = file_seed.note
|
||||
|
||||
pretty_file_seed_data = str( file_seed_data )
|
||||
pretty_status = CC.status_string_lookup[ status ]
|
||||
pretty_status = CC.status_string_lookup[ status ] if status != CC.STATUS_UNKNOWN else ''
|
||||
pretty_added = ClientTime.TimestampToPrettyTimeDelta( added )
|
||||
pretty_modified = ClientTime.TimestampToPrettyTimeDelta( modified )
|
||||
|
||||
|
|
|
@ -297,7 +297,7 @@ class EditGallerySeedLogPanel( ClientGUIScrolledPanels.EditPanel ):
|
|||
|
||||
pretty_gallery_seed_index = HydrusData.ToHumanInt( gallery_seed_index )
|
||||
pretty_url = url
|
||||
pretty_status = CC.status_string_lookup[ status ]
|
||||
pretty_status = CC.status_string_lookup[ status ] if status != CC.STATUS_UNKNOWN else ''
|
||||
pretty_added = ClientTime.TimestampToPrettyTimeDelta( added )
|
||||
pretty_modified = ClientTime.TimestampToPrettyTimeDelta( modified )
|
||||
pretty_note = note.split( os.linesep )[0]
|
||||
|
|
|
@ -2614,6 +2614,12 @@ class ReviewFileMaintenance( ClientGUIScrolledPanels.ReviewPanel ):
|
|||
|
||||
vbox = QP.VBoxLayout()
|
||||
|
||||
text = 'Here is the outstanding file maintenance work. This will be slowly completed in the background, usually a file every few seconds (you can edit this under _options->maintenance and processing_). Although you can rush work if you want to, it is best to generally leave it alone.'
|
||||
|
||||
st = ClientGUICommon.BetterStaticText( self._current_work_panel, text )
|
||||
st.setWordWrap( True )
|
||||
|
||||
QP.AddToLayout( vbox, st, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
QP.AddToLayout( vbox, jobs_listctrl_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
self._current_work_panel.setLayout( vbox )
|
||||
|
@ -2643,7 +2649,7 @@ class ReviewFileMaintenance( ClientGUIScrolledPanels.ReviewPanel ):
|
|||
QP.AddToLayout( hbox, self._run_search_st, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
QP.AddToLayout( hbox, self._run_search, CC.FLAGS_CENTER_PERPENDICULAR )
|
||||
|
||||
self._search_panel.Add( self._tag_autocomplete, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
self._search_panel.Add( self._tag_autocomplete, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
self._search_panel.Add( hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
|
||||
#
|
||||
|
@ -2692,12 +2698,17 @@ class ReviewFileMaintenance( ClientGUIScrolledPanels.ReviewPanel ):
|
|||
|
||||
vbox = QP.VBoxLayout()
|
||||
|
||||
label = 'First, select which files you wish to queue up for the job using a normal search. Hit \'run this search\' to select those files.'
|
||||
label += os.linesep
|
||||
label += 'Then select the job type and click \'add job\'.'
|
||||
label = 'Here you can queue up new file maintenance work. You determine the files to run a job on by loading a normal file search.'
|
||||
label += '\n' * 2
|
||||
label += 'Once your search is set, you need to hit \'run this search\' to actually load up the files. Then select the job type to apply and click \'add job\'. Click \'see description\' for more information on the job.'
|
||||
label += '\n' * 2
|
||||
label += 'Be cautious--do not queue up an integrity scan for all your files on a whim! If you don\'t know what a job does, do not add it!'
|
||||
|
||||
QP.AddToLayout( vbox, ClientGUICommon.BetterStaticText(self._new_work_panel,label=label), CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
QP.AddToLayout( vbox, self._search_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
st = ClientGUICommon.BetterStaticText( self._new_work_panel, label )
|
||||
st.setWordWrap( True )
|
||||
|
||||
QP.AddToLayout( vbox, st, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
QP.AddToLayout( vbox, self._search_panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
QP.AddToLayout( vbox, self._button_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
QP.AddToLayout( vbox, self._action_panel, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
|
|
|
@ -439,8 +439,9 @@ SHORTCUTS_THUMBNAILS_ACTIONS = [
|
|||
CAC.SIMPLE_LAUNCH_THE_ARCHIVE_DELETE_FILTER,
|
||||
CAC.SIMPLE_OPEN_FILE_IN_EXTERNAL_PROGRAM,
|
||||
CAC.SIMPLE_OPEN_FILE_IN_FILE_EXPLORER,
|
||||
CAC.SIMPLE_SELECT_FILES,
|
||||
CAC.SIMPLE_MOVE_THUMBNAIL_FOCUS,
|
||||
CAC.SIMPLE_SELECT_FILES
|
||||
CAC.SIMPLE_REARRANGE_THUMBNAILS
|
||||
]
|
||||
|
||||
simple_shortcut_name_to_action_lookup = {
|
||||
|
|
|
@ -192,8 +192,11 @@ def SaveTLWSizeAndPosition( tlw: QW.QWidget, frame_key ):
|
|||
|
||||
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = new_options.GetFrameLocation( frame_key )
|
||||
|
||||
maximised = tlw.isMaximized()
|
||||
fullscreen = tlw.isFullScreen()
|
||||
if remember_size:
|
||||
|
||||
maximised = tlw.isMaximized()
|
||||
fullscreen = tlw.isFullScreen()
|
||||
|
||||
|
||||
if not ( maximised or fullscreen ):
|
||||
|
||||
|
@ -201,8 +204,15 @@ def SaveTLWSizeAndPosition( tlw: QW.QWidget, frame_key ):
|
|||
|
||||
if safe_position is not None:
|
||||
|
||||
last_size = ( tlw.size().width(), tlw.size().height() )
|
||||
last_position = ( safe_position.x(), safe_position.y() )
|
||||
if remember_size:
|
||||
|
||||
last_size = ( tlw.size().width(), tlw.size().height() )
|
||||
|
||||
|
||||
if remember_position:
|
||||
|
||||
last_position = ( safe_position.x(), safe_position.y() )
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -2898,6 +2898,11 @@ class CanvasFilterDuplicates( CanvasWithHovers ):
|
|||
|
||||
def _RewindProcessing( self ) -> bool:
|
||||
|
||||
if self._currently_fetching_pairs:
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def test_we_can_pop():
|
||||
|
||||
if len( self._processed_pairs ) == 0:
|
||||
|
@ -4513,15 +4518,20 @@ class CanvasMediaListBrowser( CanvasMediaListNavigable ):
|
|||
|
||||
info_lines = self._current_media.GetPrettyInfoLines()
|
||||
|
||||
top_line = info_lines.pop( 0 )
|
||||
|
||||
info_menu = ClientGUIMenus.GenerateMenu( menu )
|
||||
|
||||
ClientGUIMediaMenus.AddPrettyInfoLines( info_menu, info_lines )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( info_menu )
|
||||
|
||||
ClientGUIMediaMenus.AddFileViewingStatsMenu( info_menu, ( self._current_media, ) )
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, info_menu, top_line )
|
||||
filetype_summary = ClientMedia.GetMediasFiletypeSummaryString( [ self._current_media ] )
|
||||
size_summary = HydrusData.ToHumanBytes( self._current_media.GetSize() )
|
||||
|
||||
info_summary = f'{filetype_summary}, {size_summary}'
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, info_menu, info_summary )
|
||||
|
||||
#
|
||||
|
||||
|
@ -4550,11 +4560,9 @@ class CanvasMediaListBrowser( CanvasMediaListNavigable ):
|
|||
ClientGUIMenus.AppendMenuItem( zoom_menu, 'zoom to max', 'Set the zoom to the maximum possible.', self._media_container.ZoomMax )
|
||||
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, zoom_menu, 'current zoom: {}'.format( ClientData.ConvertZoomToPercentage( self._media_container.GetCurrentZoom() ) ) )
|
||||
ClientGUIMenus.AppendMenu( menu, zoom_menu, 'zoom: {}'.format( ClientData.ConvertZoomToPercentage( self._media_container.GetCurrentZoom() ) ) )
|
||||
|
||||
|
||||
AddAudioVolumeMenu( menu, self.CANVAS_TYPE )
|
||||
|
||||
if self.parentWidget().isFullScreen():
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( menu, 'exit fullscreen', 'Make this media viewer a regular window with borders.', self.parentWidget().FullscreenSwitch )
|
||||
|
@ -4585,6 +4593,10 @@ class CanvasMediaListBrowser( CanvasMediaListNavigable ):
|
|||
ClientGUIMenus.AppendMenuItem( menu, 'stop slideshow', 'Stop the current slideshow.', self._PausePlaySlideshow )
|
||||
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
AddAudioVolumeMenu( menu, self.CANVAS_TYPE )
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( menu, 'remove from view', 'Remove this file from the list you are viewing.', self._Remove )
|
||||
|
@ -4611,9 +4623,16 @@ class CanvasMediaListBrowser( CanvasMediaListNavigable ):
|
|||
|
||||
local_file_service_keys_we_are_in = sorted( locations_manager.GetCurrent().intersection( local_file_service_keys ), key = HG.client_controller.services_manager.GetName )
|
||||
|
||||
for file_service_key in local_file_service_keys_we_are_in:
|
||||
if len( local_file_service_keys_we_are_in ) > 0:
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( menu, 'delete from {}'.format( HG.client_controller.services_manager.GetName( file_service_key ) ), 'Delete this file.', self._Delete, file_service_key = file_service_key )
|
||||
delete_menu = ClientGUIMenus.GenerateMenu( menu )
|
||||
|
||||
for file_service_key in local_file_service_keys_we_are_in:
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( delete_menu, 'from {}'.format( HG.client_controller.services_manager.GetName( file_service_key ) ), 'Delete this file.', self._Delete, file_service_key = file_service_key )
|
||||
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, delete_menu, 'delete' )
|
||||
|
||||
|
||||
#
|
||||
|
|
|
@ -1174,6 +1174,29 @@ class ListBox( QW.QScrollArea ):
|
|||
self._last_view_start = None
|
||||
|
||||
|
||||
def _CopySelectedTexts( self ):
|
||||
|
||||
if len( self._selected_terms ) > 1:
|
||||
|
||||
# keep order
|
||||
terms = [ term for term in self._ordered_terms if term in self._selected_terms ]
|
||||
|
||||
else:
|
||||
|
||||
# nice and fast
|
||||
terms = self._selected_terms
|
||||
|
||||
|
||||
texts = [ term.GetCopyableText() for term in terms ]
|
||||
|
||||
if len( texts ) > 0:
|
||||
|
||||
text = '\n'.join( texts )
|
||||
|
||||
HG.client_controller.pub( 'clipboard', 'text', text )
|
||||
|
||||
|
||||
|
||||
def _DataHasChanged( self ):
|
||||
|
||||
self._SetVirtualSize()
|
||||
|
@ -1984,6 +2007,10 @@ class ListBox( QW.QScrollArea ):
|
|||
|
||||
self.widget().update()
|
||||
|
||||
elif ctrl and key_code in ( ord( 'C' ), ord( 'c' ), QC.Qt.Key_Insert ):
|
||||
|
||||
self._CopySelectedTexts()
|
||||
|
||||
else:
|
||||
|
||||
hit_logical_index = None
|
||||
|
@ -2011,7 +2038,7 @@ class ListBox( QW.QScrollArea ):
|
|||
ctrl = False
|
||||
|
||||
hit_logical_index = ( self._last_hit_logical_index - 1 ) % len( self._ordered_terms )
|
||||
|
||||
|
||||
elif ctrl and key_code in ( ord( 'N' ), ord( 'n' ) ):
|
||||
|
||||
# remove ctrl key to make it act exactly like the down arrow
|
||||
|
@ -3289,15 +3316,18 @@ class ListBoxTags( ListBox ):
|
|||
|
||||
def add_favourite_tags( tags ):
|
||||
|
||||
message = f'Add{HydrusData.ConvertManyStringsToNiceInsertableHumanSummary( tags )}to the favourites list?'
|
||||
|
||||
from hydrus.client.gui import ClientGUIDialogsQuick
|
||||
|
||||
result = ClientGUIDialogsQuick.GetYesNo( self, message )
|
||||
|
||||
if result != QW.QDialog.Accepted:
|
||||
if len( tags ) > 5:
|
||||
|
||||
return
|
||||
message = f'Add{HydrusData.ConvertManyStringsToNiceInsertableHumanSummary( tags )}to the favourites list?'
|
||||
|
||||
from hydrus.client.gui import ClientGUIDialogsQuick
|
||||
|
||||
result = ClientGUIDialogsQuick.GetYesNo( self, message )
|
||||
|
||||
if result != QW.QDialog.Accepted:
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
favourite_tags = set( HG.client_controller.new_options.GetStringList( 'favourite_tags' ) )
|
||||
|
|
|
@ -11,6 +11,7 @@ from hydrus.core import HydrusSerialisable
|
|||
from hydrus.core import HydrusTime
|
||||
|
||||
from hydrus.client import ClientConstants as CC
|
||||
from hydrus.client import ClientGlobals as CG
|
||||
from hydrus.client import ClientSerialisable
|
||||
from hydrus.client.gui import ClientGUIDragDrop
|
||||
from hydrus.client.gui import ClientGUICore as CGC
|
||||
|
@ -47,7 +48,7 @@ class BetterListCtrl( QW.QTreeWidget ):
|
|||
|
||||
self._column_list_type = column_list_type
|
||||
|
||||
self._column_list_status: ClientGUIListStatus.ColumnListStatus = HG.client_controller.column_list_manager.GetStatus( self._column_list_type )
|
||||
self._column_list_status: ClientGUIListStatus.ColumnListStatus = CG.client_controller.column_list_manager.GetStatus( self._column_list_type )
|
||||
self._original_column_list_status = self._column_list_status
|
||||
|
||||
self.setAlternatingRowColors( True )
|
||||
|
@ -106,7 +107,7 @@ class BetterListCtrl( QW.QTreeWidget ):
|
|||
|
||||
self.setMinimumWidth( total_width )
|
||||
'''
|
||||
main_tlw = HG.client_controller.GetMainTLW()
|
||||
main_tlw = CG.client_controller.GetMainTLW()
|
||||
|
||||
# if last section is set too low, for instance 3, the column seems unable to ever shrink from initial (expanded to fill space) size
|
||||
# _ _ ___ _ _ __ __ ___
|
||||
|
@ -180,8 +181,8 @@ class BetterListCtrl( QW.QTreeWidget ):
|
|||
self.header().setContextMenuPolicy( QC.Qt.CustomContextMenu )
|
||||
self.header().customContextMenuRequested.connect( self._ShowHeaderMenu )
|
||||
|
||||
HG.client_controller.sub( self, 'NotifySettingsUpdated', 'reset_all_listctrl_status' )
|
||||
HG.client_controller.sub( self, 'NotifySettingsUpdated', 'reset_listctrl_status' )
|
||||
CG.client_controller.sub( self, 'NotifySettingsUpdated', 'reset_all_listctrl_status' )
|
||||
CG.client_controller.sub( self, 'NotifySettingsUpdated', 'reset_listctrl_status' )
|
||||
|
||||
|
||||
def _AddDataInfo( self, data_info ):
|
||||
|
@ -227,7 +228,7 @@ class BetterListCtrl( QW.QTreeWidget ):
|
|||
|
||||
self._column_list_status = self._GenerateCurrentStatus()
|
||||
|
||||
HG.client_controller.column_list_manager.SaveStatus( self._column_list_status )
|
||||
CG.client_controller.column_list_manager.SaveStatus( self._column_list_status )
|
||||
|
||||
|
||||
def _GenerateCurrentStatus( self ) -> ClientGUIListStatus.ColumnListStatus:
|
||||
|
@ -236,7 +237,7 @@ class BetterListCtrl( QW.QTreeWidget ):
|
|||
|
||||
status.SetColumnListType( self._column_list_type )
|
||||
|
||||
main_tlw = HG.client_controller.GetMainTLW()
|
||||
main_tlw = CG.client_controller.GetMainTLW()
|
||||
|
||||
columns = []
|
||||
|
||||
|
@ -391,7 +392,7 @@ class BetterListCtrl( QW.QTreeWidget ):
|
|||
|
||||
name = CGLC.column_list_type_name_lookup[ self._column_list_type ]
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( menu, f'reset default column widths for "{name}" lists', 'Reset the column widths and other display settings for all lists of this type', HG.client_controller.column_list_manager.ResetToDefaults, self._column_list_type )
|
||||
ClientGUIMenus.AppendMenuItem( menu, f'reset default column widths for "{name}" lists', 'Reset the column widths and other display settings for all lists of this type', CG.client_controller.column_list_manager.ResetToDefaults, self._column_list_type )
|
||||
|
||||
CGC.core().PopupMenu( self, menu )
|
||||
|
||||
|
@ -713,7 +714,7 @@ class BetterListCtrl( QW.QTreeWidget ):
|
|||
self.blockSignals( True )
|
||||
self.header().blockSignals( True )
|
||||
|
||||
self._column_list_status: ClientGUIListStatus.ColumnListStatus = HG.client_controller.column_list_manager.GetStatus( self._column_list_type )
|
||||
self._column_list_status: ClientGUIListStatus.ColumnListStatus = CG.client_controller.column_list_manager.GetStatus( self._column_list_type )
|
||||
self._original_column_list_status = self._column_list_status
|
||||
|
||||
#
|
||||
|
@ -722,7 +723,7 @@ class BetterListCtrl( QW.QTreeWidget ):
|
|||
|
||||
#
|
||||
|
||||
main_tlw = HG.client_controller.GetMainTLW()
|
||||
main_tlw = CG.client_controller.GetMainTLW()
|
||||
|
||||
MIN_SECTION_SIZE_CHARS = 3
|
||||
|
||||
|
@ -934,7 +935,7 @@ class BetterListCtrl( QW.QTreeWidget ):
|
|||
|
||||
last_column_chars = self._original_column_list_status.GetColumnWidth( last_column_type )
|
||||
|
||||
main_tlw = HG.client_controller.GetMainTLW()
|
||||
main_tlw = CG.client_controller.GetMainTLW()
|
||||
|
||||
width += ClientGUIFunctions.ConvertTextToPixelWidth( main_tlw, last_column_chars )
|
||||
|
||||
|
@ -1165,7 +1166,7 @@ class BetterListCtrlPanel( QW.QWidget ):
|
|||
|
||||
json = export_object.DumpToString()
|
||||
|
||||
HG.client_controller.pub( 'clipboard', 'text', json )
|
||||
CG.client_controller.pub( 'clipboard', 'text', json )
|
||||
|
||||
|
||||
|
||||
|
@ -1297,11 +1298,11 @@ class BetterListCtrlPanel( QW.QWidget ):
|
|||
|
||||
def _ImportFromClipboard( self ):
|
||||
|
||||
if HG.client_controller.ClipboardHasImage():
|
||||
if CG.client_controller.ClipboardHasImage():
|
||||
|
||||
try:
|
||||
|
||||
qt_image = HG.client_controller.GetClipboardImage()
|
||||
qt_image = CG.client_controller.GetClipboardImage()
|
||||
|
||||
except:
|
||||
|
||||
|
@ -1332,7 +1333,7 @@ class BetterListCtrlPanel( QW.QWidget ):
|
|||
|
||||
try:
|
||||
|
||||
raw_text = HG.client_controller.GetClipboardText()
|
||||
raw_text = CG.client_controller.GetClipboardText()
|
||||
|
||||
except HydrusExceptions.DataMissing as e:
|
||||
|
||||
|
|
|
@ -588,9 +588,8 @@ class MediaPanel( CAC.ApplicationCommandProcessorMixin, ClientMedia.ListeningMed
|
|||
|
||||
num_selected = self._GetNumSelected()
|
||||
|
||||
( num_files_descriptor, selected_files_descriptor ) = self._GetSortedSelectedMimeDescriptors()
|
||||
|
||||
num_files_string = '{} {}'.format( HydrusData.ToHumanInt( num_files ), num_files_descriptor )
|
||||
num_files_string = ClientMedia.GetMediasFiletypeSummaryString( self._sorted_media )
|
||||
selected_files_string = ClientMedia.GetMediasFiletypeSummaryString( self._selected_media )
|
||||
|
||||
s = num_files_string # 23 files
|
||||
|
||||
|
@ -615,14 +614,10 @@ class MediaPanel( CAC.ApplicationCommandProcessorMixin, ClientMedia.ListeningMed
|
|||
s += ' - '
|
||||
|
||||
# if 1 selected, we show the whole mime string, so no need to specify
|
||||
if num_selected == 1 or selected_files_descriptor == num_files_descriptor:
|
||||
if num_selected == 1 or selected_files_string == num_files_string:
|
||||
|
||||
selected_files_string = HydrusData.ToHumanInt( num_selected )
|
||||
|
||||
else:
|
||||
|
||||
selected_files_string = '{} {}'.format( HydrusData.ToHumanInt( num_selected ), selected_files_descriptor )
|
||||
|
||||
|
||||
if num_selected == 1: # 23 files - 1 video selected, file_info
|
||||
|
||||
|
@ -771,17 +766,8 @@ class MediaPanel( CAC.ApplicationCommandProcessorMixin, ClientMedia.ListeningMed
|
|||
|
||||
def _GetSelectedMediaOrdered( self ):
|
||||
|
||||
medias = []
|
||||
|
||||
for media in self._sorted_media:
|
||||
|
||||
if media in self._selected_media:
|
||||
|
||||
medias.append( media )
|
||||
|
||||
|
||||
|
||||
return medias
|
||||
# note that this is fast because sorted_media is custom
|
||||
return sorted( self._selected_media, key = lambda m: self._sorted_media.index( m ) )
|
||||
|
||||
|
||||
def _GetSimilarTo( self, max_hamming ):
|
||||
|
@ -2249,6 +2235,72 @@ class MediaPanel( CAC.ApplicationCommandProcessorMixin, ClientMedia.ListeningMed
|
|||
|
||||
self._CopyHashesToClipboard( 'sha512' )
|
||||
|
||||
elif action == CAC.SIMPLE_REARRANGE_THUMBNAILS:
|
||||
|
||||
ordered_selected_media = self._GetSelectedMediaOrdered()
|
||||
|
||||
( rearrange_type, rearrange_data ) = command.GetSimpleData()
|
||||
|
||||
insertion_index = None
|
||||
|
||||
if rearrange_type == CAC.REARRANGE_THUMBNAILS_TYPE_FIXED:
|
||||
|
||||
insertion_index = rearrange_data
|
||||
|
||||
elif rearrange_type == CAC.REARRANGE_THUMBNAILS_TYPE_COMMAND:
|
||||
|
||||
rearrange_command = rearrange_data
|
||||
|
||||
if rearrange_command == CAC.MOVE_HOME:
|
||||
|
||||
insertion_index = 0
|
||||
|
||||
elif rearrange_command == CAC.MOVE_END:
|
||||
|
||||
insertion_index = len( self._sorted_media )
|
||||
|
||||
else:
|
||||
|
||||
if len( self._selected_media ) > 0:
|
||||
|
||||
if rearrange_command in ( CAC.MOVE_LEFT, CAC.MOVE_RIGHT ):
|
||||
|
||||
ordered_selected_media = self._GetSelectedMediaOrdered()
|
||||
|
||||
earliest_index = self._sorted_media.index( ordered_selected_media[0] )
|
||||
|
||||
if rearrange_command == CAC.MOVE_LEFT:
|
||||
|
||||
if earliest_index > 0:
|
||||
|
||||
insertion_index = earliest_index - 1
|
||||
|
||||
|
||||
elif rearrange_command == CAC.MOVE_RIGHT:
|
||||
|
||||
insertion_index = earliest_index + 1
|
||||
|
||||
|
||||
elif rearrange_command == CAC.MOVE_TO_FOCUS:
|
||||
|
||||
if self._focused_media is not None:
|
||||
|
||||
focus_index = self._sorted_media.index( self._focused_media )
|
||||
|
||||
insertion_index = focus_index
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if insertion_index is None:
|
||||
|
||||
return
|
||||
|
||||
|
||||
self.MoveMedia( ordered_selected_media, insertion_index = insertion_index )
|
||||
|
||||
elif action == CAC.SIMPLE_SHOW_DUPLICATES:
|
||||
|
||||
if self._HasFocusSingleton():
|
||||
|
@ -3180,6 +3232,13 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
|
||||
|
||||
def _NotifyThumbnailsHaveMoved( self ):
|
||||
|
||||
self._DirtyAllPages()
|
||||
|
||||
self.widget().update()
|
||||
|
||||
|
||||
def _RecalculateVirtualSize( self, called_from_resize_event = False ):
|
||||
|
||||
my_size = QP.ScrollAreaVisibleRect( self ).size()
|
||||
|
@ -3561,6 +3620,15 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
self.ShowMenu()
|
||||
|
||||
|
||||
def MoveMedia( self, medias: typing.List[ ClientMedia.Media ], insertion_index: int ):
|
||||
|
||||
MediaPanel.MoveMedia( self, medias, insertion_index )
|
||||
|
||||
self._NotifyThumbnailsHaveMoved()
|
||||
|
||||
self._ScrollToMedia( medias[0] )
|
||||
|
||||
|
||||
def NewThumbnails( self, hashes ):
|
||||
|
||||
affected_thumbnails = self._GetMedia( hashes )
|
||||
|
@ -3654,11 +3722,15 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
rows = -1
|
||||
columns = 0
|
||||
|
||||
else: # MOVE_DOWN
|
||||
elif move_direction == CAC.MOVE_DOWN:
|
||||
|
||||
rows = 1
|
||||
columns = 0
|
||||
|
||||
else:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
self._MoveThumbnailFocus( rows, columns, shift )
|
||||
|
||||
|
@ -3835,7 +3907,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
rescind_unpin_phrase = 'rescind unpin from'
|
||||
|
||||
archive_phrase = 'archive selected'
|
||||
inbox_phrase = 'return selected to inbox'
|
||||
inbox_phrase = 're-inbox selected'
|
||||
local_delete_phrase = 'delete selected'
|
||||
delete_physically_phrase = 'delete selected physically now'
|
||||
undelete_phrase = 'undelete selected'
|
||||
|
@ -3860,7 +3932,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
rescind_unpin_phrase = 'rescind unpin from'
|
||||
|
||||
archive_phrase = 'archive'
|
||||
inbox_phrase = 'return to inbox'
|
||||
inbox_phrase = 're-inbox'
|
||||
local_delete_phrase = 'delete'
|
||||
delete_physically_phrase = 'delete physically now'
|
||||
undelete_phrase = 'undelete'
|
||||
|
@ -4000,12 +4072,12 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
selection_info_menu = ClientGUIMenus.GenerateMenu( menu )
|
||||
|
||||
selected_files_string = ClientMedia.GetMediasFiletypeSummaryString( self._selected_media )
|
||||
|
||||
selection_info_menu_label = f'{selected_files_string}, {self._GetPrettyTotalSize( only_selected = True )}'
|
||||
|
||||
if multiple_selected:
|
||||
|
||||
( num_files_descriptor, selected_files_descriptor ) = self._GetSortedSelectedMimeDescriptors()
|
||||
|
||||
selection_info_menu_label = '{} {}, {}'.format( HydrusData.ToHumanInt( num_selected ), selected_files_descriptor, self._GetPrettyTotalSize( only_selected = True ) )
|
||||
|
||||
pretty_total_duration = self._GetPrettyTotalDuration( only_selected = True )
|
||||
|
||||
if pretty_total_duration != '':
|
||||
|
@ -4019,13 +4091,11 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
pretty_info_lines = list( focus_singleton.GetPrettyInfoLines() )
|
||||
|
||||
top_line = pretty_info_lines.pop( 0 )
|
||||
|
||||
selection_info_menu_label = top_line
|
||||
|
||||
ClientGUIMediaMenus.AddPrettyInfoLines( selection_info_menu, pretty_info_lines )
|
||||
|
||||
|
||||
ClientGUIMenus.AppendSeparator( selection_info_menu )
|
||||
|
||||
ClientGUIMediaMenus.AddFileViewingStatsMenu( selection_info_menu, self._selected_media )
|
||||
|
||||
if len( disparate_current_file_service_keys ) > 0:
|
||||
|
@ -4098,7 +4168,6 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
ClientGUIMediaMenus.AddServiceKeyLabelsToMenu( selection_info_menu, common_petitioned_ipfs_service_keys, unpin_phrase )
|
||||
|
||||
|
||||
|
||||
if len( selection_info_menu.actions() ) == 0:
|
||||
|
||||
selection_info_menu.deleteLater()
|
||||
|
@ -4131,6 +4200,26 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
AddSelectMenu( self, menu, filter_counts, all_specific_file_domains, has_local_and_remote )
|
||||
AddRemoveMenu( self, menu, filter_counts, all_specific_file_domains, has_local_and_remote )
|
||||
|
||||
if len( self._selected_media ) > 0:
|
||||
|
||||
ordered_selected_media = self._GetSelectedMediaOrdered()
|
||||
|
||||
try:
|
||||
|
||||
earliest_index = self._sorted_media.index( ordered_selected_media[0] )
|
||||
|
||||
num_selected = len( self._selected_media )
|
||||
|
||||
selection_is_contiguous = num_selected > 0 and self._sorted_media.index( ordered_selected_media[-1] ) - earliest_index == num_selected - 1
|
||||
|
||||
AddMoveMenu( self, menu, self._selected_media, self._sorted_media, self._focused_media, selection_is_contiguous, earliest_index )
|
||||
|
||||
except HydrusExceptions.DataMissing:
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
ClientGUIMenus.AppendSeparator( menu )
|
||||
|
||||
if has_local:
|
||||
|
@ -4159,9 +4248,18 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
local_file_service_keys_we_are_in = sorted( current_file_service_keys.intersection( user_command_deletable_file_service_keys ), key = HG.client_controller.services_manager.GetName )
|
||||
|
||||
for file_service_key in local_file_service_keys_we_are_in:
|
||||
if len( local_file_service_keys_we_are_in ) > 0:
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( menu, '{} from {}'.format( local_delete_phrase, HG.client_controller.services_manager.GetName( file_service_key ) ), 'Delete the selected files.', self._Delete, file_service_key )
|
||||
delete_menu = ClientGUIMenus.GenerateMenu( menu )
|
||||
|
||||
for file_service_key in local_file_service_keys_we_are_in:
|
||||
|
||||
service_name = HG.client_controller.services_manager.GetName( file_service_key )
|
||||
|
||||
ClientGUIMenus.AppendMenuItem( delete_menu, f'from {service_name}', f'Delete the selected files from {service_name}.', self._Delete, file_service_key )
|
||||
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, delete_menu, local_delete_phrase )
|
||||
|
||||
|
||||
if selection_has_trash:
|
||||
|
@ -4528,9 +4626,7 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
MediaPanel.Sort( self, media_sort )
|
||||
|
||||
self._DirtyAllPages()
|
||||
|
||||
self.widget().update()
|
||||
self._NotifyThumbnailsHaveMoved()
|
||||
|
||||
|
||||
def ThumbnailsReset( self ):
|
||||
|
@ -4768,7 +4864,81 @@ class MediaPanelThumbnails( MediaPanel ):
|
|||
|
||||
|
||||
|
||||
def AddRemoveMenu( win: MediaPanel, menu, filter_counts, all_specific_file_domains, has_local_and_remote ):
|
||||
|
||||
def AddMoveMenu( win: MediaPanel, menu: QW.QMenu, selected_media: typing.Set[ ClientMedia.Media ], sorted_media: ClientMedia.SortedList, focused_media: typing.Optional[ ClientMedia.Media ], selection_is_contiguous: bool, earliest_index: int ):
|
||||
|
||||
if len( selected_media ) == 0 or len( selected_media ) == len( sorted_media ):
|
||||
|
||||
return
|
||||
|
||||
|
||||
move_menu = ClientGUIMenus.GenerateMenu( menu )
|
||||
|
||||
if earliest_index > 0:
|
||||
|
||||
ClientGUIMenus.AppendMenuItem(
|
||||
move_menu,
|
||||
'to start',
|
||||
'Move the selected thumbnails to the start of the media list.',
|
||||
win.ProcessApplicationCommand,
|
||||
CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_REARRANGE_THUMBNAILS, ( CAC.REARRANGE_THUMBNAILS_TYPE_COMMAND, CAC.MOVE_HOME ) )
|
||||
)
|
||||
|
||||
ClientGUIMenus.AppendMenuItem(
|
||||
move_menu,
|
||||
'back one',
|
||||
'Move the selected thumbnails back one position.',
|
||||
win.ProcessApplicationCommand,
|
||||
CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_REARRANGE_THUMBNAILS, ( CAC.REARRANGE_THUMBNAILS_TYPE_COMMAND, CAC.MOVE_LEFT ) )
|
||||
)
|
||||
|
||||
|
||||
if focused_media is not None:
|
||||
|
||||
try:
|
||||
|
||||
focused_index = sorted_media.index( focused_media )
|
||||
|
||||
if focused_index != earliest_index or not selection_is_contiguous:
|
||||
|
||||
ClientGUIMenus.AppendMenuItem(
|
||||
move_menu,
|
||||
'to here',
|
||||
'Move the selected thumbnails to the focused position (most likely the one you clicked on).',
|
||||
win.ProcessApplicationCommand,
|
||||
CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_REARRANGE_THUMBNAILS, ( CAC.REARRANGE_THUMBNAILS_TYPE_COMMAND, CAC.MOVE_TO_FOCUS ) )
|
||||
)
|
||||
|
||||
|
||||
except HydrusExceptions.DataMissing:
|
||||
|
||||
pass
|
||||
|
||||
|
||||
|
||||
if earliest_index + len( selected_media ) < len( sorted_media ):
|
||||
|
||||
ClientGUIMenus.AppendMenuItem(
|
||||
move_menu,
|
||||
'forward one',
|
||||
'Move the selected thumbnails forward one position.',
|
||||
win.ProcessApplicationCommand,
|
||||
CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_REARRANGE_THUMBNAILS, ( CAC.REARRANGE_THUMBNAILS_TYPE_COMMAND, CAC.MOVE_RIGHT ) )
|
||||
)
|
||||
|
||||
ClientGUIMenus.AppendMenuItem(
|
||||
move_menu,
|
||||
'to end',
|
||||
'Move the selected thumbnails to the end of the media list.',
|
||||
win.ProcessApplicationCommand,
|
||||
CAC.ApplicationCommand.STATICCreateSimpleCommand( CAC.SIMPLE_REARRANGE_THUMBNAILS, ( CAC.REARRANGE_THUMBNAILS_TYPE_COMMAND, CAC.MOVE_END ) )
|
||||
)
|
||||
|
||||
|
||||
ClientGUIMenus.AppendMenu( menu, move_menu, 'move' )
|
||||
|
||||
|
||||
def AddRemoveMenu( win: MediaPanel, menu: QW.QMenu, filter_counts, all_specific_file_domains, has_local_and_remote ):
|
||||
|
||||
file_filter_all = ClientMediaFileFilter.FileFilter( ClientMediaFileFilter.FILE_FILTER_ALL )
|
||||
|
||||
|
|
|
@ -133,7 +133,17 @@ class EditCompoundFormulaPanel( EditSpecificFormulaPanel ):
|
|||
edit_panel.Add( formulae_hbox, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
edit_panel.Add( ae_button_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
edit_panel.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
edit_panel.Add( ClientGUICommon.BetterStaticText( edit_panel, 'Newlines are removed from parsed strings right after parsing, before string processing.', ellipsize_end = True ), CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
if collapse_newlines:
|
||||
|
||||
label = 'Newlines are removed from parsed strings right after parsing, before string processing.'
|
||||
|
||||
else:
|
||||
|
||||
label = 'Newlines are not collapsed here (probably a note parser)'
|
||||
|
||||
|
||||
edit_panel.Add( ClientGUICommon.BetterStaticText( edit_panel, label, ellipsize_end = True ), CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
edit_panel.Add( self._string_processor_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
#
|
||||
|
@ -322,7 +332,17 @@ class EditContextVariableFormulaPanel( EditSpecificFormulaPanel ):
|
|||
gridbox = ClientGUICommon.WrapInGrid( edit_panel, rows )
|
||||
|
||||
edit_panel.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
edit_panel.Add( ClientGUICommon.BetterStaticText( edit_panel, 'Newlines are removed from parsed strings right after parsing, before string processing.', ellipsize_end = True ), CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
if collapse_newlines:
|
||||
|
||||
label = 'Newlines are removed from parsed strings right after parsing, before string processing.'
|
||||
|
||||
else:
|
||||
|
||||
label = 'Newlines are not collapsed here (probably a note parser)'
|
||||
|
||||
|
||||
edit_panel.Add( ClientGUICommon.BetterStaticText( edit_panel, label, ellipsize_end = True ), CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
edit_panel.Add( self._string_processor_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
#
|
||||
|
@ -847,7 +867,17 @@ class EditHTMLFormulaPanel( EditSpecificFormulaPanel ):
|
|||
edit_panel.Add( tag_rules_hbox, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
edit_panel.Add( ae_button_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
edit_panel.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
edit_panel.Add( ClientGUICommon.BetterStaticText( edit_panel, 'Newlines are removed from parsed strings right after parsing, before string processing.', ellipsize_end = True ), CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
if collapse_newlines:
|
||||
|
||||
label = 'Newlines are removed from parsed strings right after parsing, before string processing.'
|
||||
|
||||
else:
|
||||
|
||||
label = 'Newlines are not collapsed here (probably a note parser)'
|
||||
|
||||
|
||||
edit_panel.Add( ClientGUICommon.BetterStaticText( edit_panel, label, ellipsize_end = True ), CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
edit_panel.Add( self._string_processor_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
#
|
||||
|
@ -1195,7 +1225,17 @@ class EditJSONFormulaPanel( EditSpecificFormulaPanel ):
|
|||
edit_panel.Add( parse_rules_hbox, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
edit_panel.Add( ae_button_hbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
edit_panel.Add( gridbox, CC.FLAGS_EXPAND_SIZER_PERPENDICULAR )
|
||||
edit_panel.Add( ClientGUICommon.BetterStaticText( edit_panel, 'Newlines are removed from parsed strings right after parsing, before string processing.', ellipsize_end = True ), CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
if collapse_newlines:
|
||||
|
||||
label = 'Newlines are removed from parsed strings right after parsing, before string processing.'
|
||||
|
||||
else:
|
||||
|
||||
label = 'Newlines are not collapsed here (probably a note parser)'
|
||||
|
||||
|
||||
edit_panel.Add( ClientGUICommon.BetterStaticText( edit_panel, label, ellipsize_end = True ), CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
edit_panel.Add( self._string_processor_button, CC.FLAGS_EXPAND_PERPENDICULAR )
|
||||
|
||||
#
|
||||
|
|
|
@ -331,6 +331,7 @@ class RatingNumericalSubPanel( QW.QWidget ):
|
|||
|
||||
|
||||
|
||||
|
||||
class RatingIncDecSubPanel( QW.QWidget ):
|
||||
|
||||
def __init__( self, parent: QW.QWidget ):
|
||||
|
@ -396,6 +397,7 @@ class RatingIncDecSubPanel( QW.QWidget ):
|
|||
self._ratings_incdec.SetValue( action )
|
||||
|
||||
|
||||
|
||||
class SimpleSubPanel( QW.QWidget ):
|
||||
|
||||
def __init__( self, parent: QW.QWidget, shortcuts_name: str ):
|
||||
|
@ -430,6 +432,31 @@ class SimpleSubPanel( QW.QWidget ):
|
|||
|
||||
#
|
||||
|
||||
self._thumbnail_rearrange_panel = QW.QWidget( self )
|
||||
|
||||
self._thumbnail_rearrange_type = ClientGUICommon.BetterChoice( self )
|
||||
|
||||
for rearrange_type in [
|
||||
CAC.MOVE_HOME,
|
||||
CAC.MOVE_END,
|
||||
CAC.MOVE_LEFT,
|
||||
CAC.MOVE_RIGHT,
|
||||
CAC.MOVE_TO_FOCUS
|
||||
]:
|
||||
|
||||
self._thumbnail_rearrange_type.addItem( CAC.move_enum_to_str_lookup[ rearrange_type ], rearrange_type )
|
||||
|
||||
|
||||
#
|
||||
|
||||
vbox = QP.VBoxLayout()
|
||||
|
||||
QP.AddToLayout( vbox, self._thumbnail_rearrange_type, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
||||
self._thumbnail_rearrange_panel.setLayout( vbox )
|
||||
|
||||
#
|
||||
|
||||
vbox = QP.VBoxLayout()
|
||||
|
||||
QP.AddToLayout( vbox, self._duplicate_type, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||
|
@ -530,6 +557,7 @@ class SimpleSubPanel( QW.QWidget ):
|
|||
QP.AddToLayout( vbox, self._seek_panel, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
||||
QP.AddToLayout( vbox, self._thumbnail_move_panel, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
||||
QP.AddToLayout( vbox, self._file_filter_panel, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
||||
QP.AddToLayout( vbox, self._thumbnail_rearrange_panel, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
|
||||
|
||||
self.setLayout( vbox )
|
||||
|
||||
|
@ -542,6 +570,7 @@ class SimpleSubPanel( QW.QWidget ):
|
|||
|
||||
action = self._simple_actions.GetValue()
|
||||
|
||||
self._duplicates_type_panel.setVisible( action == CAC.SIMPLE_REARRANGE_THUMBNAILS )
|
||||
self._duplicates_type_panel.setVisible( action == CAC.SIMPLE_SHOW_DUPLICATES )
|
||||
self._seek_panel.setVisible( action == CAC.SIMPLE_MEDIA_SEEK_DELTA )
|
||||
self._thumbnail_move_panel.setVisible( action == CAC.SIMPLE_MOVE_THUMBNAIL_FOCUS )
|
||||
|
@ -586,6 +615,12 @@ class SimpleSubPanel( QW.QWidget ):
|
|||
|
||||
simple_data = file_filter
|
||||
|
||||
elif action == CAC.SIMPLE_REARRANGE_THUMBNAILS:
|
||||
|
||||
rearrange_type = self._thumbnail_rearrange_type.GetValue()
|
||||
|
||||
simple_data = ( CAC.REARRANGE_THUMBNAILS_TYPE_COMMAND, rearrange_type )
|
||||
|
||||
else:
|
||||
|
||||
simple_data = None
|
||||
|
@ -633,6 +668,12 @@ class SimpleSubPanel( QW.QWidget ):
|
|||
|
||||
self._file_filter.SetValue( file_filter )
|
||||
|
||||
elif action == CAC.SIMPLE_REARRANGE_THUMBNAILS:
|
||||
|
||||
( rearrange_type, rearrange_data ) = command.GetSimpleData()
|
||||
|
||||
self._thumbnail_rearrange_type.SetValue( rearrange_data )
|
||||
|
||||
|
||||
self._UpdateControls()
|
||||
|
||||
|
@ -742,6 +783,7 @@ class TagSubPanel( QW.QWidget ):
|
|||
self._tag_value.setText( tag )
|
||||
|
||||
|
||||
|
||||
class ApplicationCommandWidget( ClientGUIScrolledPanels.EditPanel ):
|
||||
|
||||
PANEL_SIMPLE = 0
|
||||
|
|
|
@ -552,7 +552,7 @@ class FileImportJob( object ):
|
|||
|
||||
hashes = { self.GetHash() }
|
||||
|
||||
content_update_package = ClientContentUpdates.ContentUpdatePackage.AddContentUpdate( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, ClientContentUpdates.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, hashes ) )
|
||||
content_update_package = ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdate( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, ClientContentUpdates.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, hashes ) )
|
||||
|
||||
HG.client_controller.Write( 'content_updates', content_update_package )
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
from qtpy import QtWidgets as QW
|
||||
|
||||
from hydrus.core.interfaces import HydrusControllerInterface
|
||||
|
||||
from hydrus.client import ClientThreading
|
||||
|
||||
class ClientControllerInterface( HydrusControllerInterface.HydrusControllerInterface ):
|
||||
|
||||
def CallBlockingToQt( self, win: QW.QWidget, func: callable, *args, **kwargs ) -> object:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def CallAfterQtSafe( self, window: QW.QWidget, label: str, func: callable, *args, **kwargs ) -> ClientThreading.QtAwareJob:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def CallLaterQtSafe( self, window: QW.QWidget, initial_delay: float, label: str, func: callable, *args, **kwargs ) -> ClientThreading.QtAwareJob:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def CallRepeatingQtSafe( self, window: QW.QWidget, initial_delay: float, period: float, label: str, func: callable, *args, **kwargs ) -> ClientThreading.QtAwareRepeatingJob:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
|
|
@ -114,6 +114,82 @@ def GetMediaResultsTagCount( media_results, tag_service_key, tag_display_type ):
|
|||
return GetTagsManagersTagCount( tags_managers, tag_service_key, tag_display_type )
|
||||
|
||||
|
||||
def GetMediasFiletypeSummaryString( medias: typing.Collection[ "Media" ] ):
|
||||
|
||||
def GetDescriptor( plural, classes, num_collections ):
|
||||
|
||||
suffix = 's' if plural else ''
|
||||
|
||||
if len( classes ) == 0:
|
||||
|
||||
return 'file' + suffix
|
||||
|
||||
|
||||
if len( classes ) == 1:
|
||||
|
||||
( mime, ) = classes
|
||||
|
||||
if mime == HC.APPLICATION_HYDRUS_CLIENT_COLLECTION:
|
||||
|
||||
collections_suffix = 's' if num_collections > 1 else ''
|
||||
|
||||
return 'file{} in {} collection{}'.format( suffix, HydrusData.ToHumanInt( num_collections ), collections_suffix )
|
||||
|
||||
else:
|
||||
|
||||
return HC.mime_string_lookup[ mime ] + suffix
|
||||
|
||||
|
||||
|
||||
if len( classes.difference( HC.IMAGES ) ) == 0:
|
||||
|
||||
return 'image' + suffix
|
||||
|
||||
elif len( classes.difference( HC.ANIMATIONS ) ) == 0:
|
||||
|
||||
return 'animation' + suffix
|
||||
|
||||
elif len( classes.difference( HC.VIDEO ) ) == 0:
|
||||
|
||||
return 'video' + suffix
|
||||
|
||||
elif len( classes.difference( HC.AUDIO ) ) == 0:
|
||||
|
||||
return 'audio file' + suffix
|
||||
|
||||
else:
|
||||
|
||||
return 'file' + suffix
|
||||
|
||||
|
||||
|
||||
num_files = sum( [ media.GetNumFiles() for media in medias ] )
|
||||
|
||||
if num_files > 1000:
|
||||
|
||||
filetype_summary = 'files'
|
||||
|
||||
else:
|
||||
|
||||
mimes = { media.GetMime() for media in medias }
|
||||
|
||||
if HC.APPLICATION_HYDRUS_CLIENT_COLLECTION in mimes:
|
||||
|
||||
num_collections = len( [ media for media in medias if isinstance( media, MediaCollection ) ] )
|
||||
|
||||
else:
|
||||
|
||||
num_collections = 0
|
||||
|
||||
|
||||
plural = len( medias ) > 1 or sum( ( m.GetNumFiles() for m in medias ) ) > 1
|
||||
|
||||
filetype_summary = GetDescriptor( plural, mimes, num_collections )
|
||||
|
||||
|
||||
return f'{HydrusData.ToHumanInt( num_files )} {filetype_summary}'
|
||||
|
||||
|
||||
def GetMediasTagCount( pool, tag_service_key, tag_display_type ):
|
||||
|
||||
tags_managers = []
|
||||
|
@ -1091,6 +1167,13 @@ class MediaList( object ):
|
|||
return len( self._sorted_media ) == 0
|
||||
|
||||
|
||||
def MoveMedia( self, medias: typing.List[ Media ], insertion_index: int ):
|
||||
|
||||
self._sorted_media.move_items( medias, insertion_index )
|
||||
|
||||
self._RecalcHashes()
|
||||
|
||||
|
||||
def ProcessContentUpdatePackage( self, full_content_update_package: ClientContentUpdates.ContentUpdatePackage ):
|
||||
|
||||
if not full_content_update_package.HasContent():
|
||||
|
@ -2950,6 +3033,9 @@ class SortedList( object ):
|
|||
|
||||
|
||||
def index( self, item ):
|
||||
"""
|
||||
This is fast!
|
||||
"""
|
||||
|
||||
if self._indices_dirty:
|
||||
|
||||
|
@ -2968,11 +3054,71 @@ class SortedList( object ):
|
|||
return result
|
||||
|
||||
|
||||
def insert_items( self, items ):
|
||||
def insert_items( self, items, insertion_index = None ):
|
||||
|
||||
self.append_items( items )
|
||||
if insertion_index is None:
|
||||
|
||||
self.append_items( items )
|
||||
|
||||
self.sort()
|
||||
|
||||
else:
|
||||
|
||||
# don't forget we can insert elements in the final slot for an append, where index >= len( muh_list )
|
||||
|
||||
for ( i, item ) in enumerate( items ):
|
||||
|
||||
self._sorted_list.insert( insertion_index + i, item )
|
||||
|
||||
|
||||
self._DirtyIndices()
|
||||
|
||||
|
||||
self.sort()
|
||||
|
||||
def move_items( self, new_items: typing.List, insertion_index: int ):
|
||||
|
||||
items_to_move = []
|
||||
items_before_insertion_index = 0
|
||||
|
||||
if insertion_index < 0:
|
||||
|
||||
insertion_index = max( 0, len( self._sorted_list ) + ( insertion_index + 1 ) )
|
||||
|
||||
|
||||
for new_item in new_items:
|
||||
|
||||
try:
|
||||
|
||||
index = self.index( new_item )
|
||||
|
||||
except HydrusExceptions.DataMissing:
|
||||
|
||||
continue
|
||||
|
||||
|
||||
items_to_move.append( new_item )
|
||||
|
||||
if index < insertion_index:
|
||||
|
||||
items_before_insertion_index += 1
|
||||
|
||||
|
||||
|
||||
if items_before_insertion_index > 0: # i.e. we are moving to the right
|
||||
|
||||
items_before_insertion_index -= 1
|
||||
|
||||
|
||||
adjusted_insertion_index = insertion_index# - items_before_insertion_index
|
||||
|
||||
if len( items_to_move ) == 0:
|
||||
|
||||
return
|
||||
|
||||
|
||||
self.remove_items( items_to_move )
|
||||
|
||||
self.insert_items( items_to_move, insertion_index = adjusted_insertion_index )
|
||||
|
||||
|
||||
def remove_items( self, items ):
|
||||
|
|
|
@ -38,6 +38,7 @@ from hydrus.core.networking import HydrusServerResources
|
|||
from hydrus.client import ClientAPI
|
||||
from hydrus.client import ClientOptions
|
||||
from hydrus.client import ClientConstants as CC
|
||||
from hydrus.client import ClientGlobals as CG
|
||||
from hydrus.client import ClientLocation
|
||||
from hydrus.client import ClientThreading
|
||||
from hydrus.client import ClientTime
|
||||
|
@ -154,7 +155,7 @@ def CheckFileService( file_service_key: bytes ):
|
|||
|
||||
try:
|
||||
|
||||
service = HG.client_controller.services_manager.GetService( file_service_key )
|
||||
service = CG.client_controller.services_manager.GetService( file_service_key )
|
||||
|
||||
except:
|
||||
|
||||
|
@ -173,7 +174,7 @@ def CheckTagService( tag_service_key: bytes ):
|
|||
|
||||
try:
|
||||
|
||||
service = HG.client_controller.services_manager.GetService( tag_service_key )
|
||||
service = CG.client_controller.services_manager.GetService( tag_service_key )
|
||||
|
||||
except:
|
||||
|
||||
|
@ -226,7 +227,7 @@ def GetServicesDict():
|
|||
HC.LOCAL_FILE_TRASH_DOMAIN
|
||||
]
|
||||
|
||||
services = HG.client_controller.services_manager.GetServices( service_types )
|
||||
services = CG.client_controller.services_manager.GetServices( service_types )
|
||||
|
||||
services_dict = {}
|
||||
|
||||
|
@ -264,7 +265,7 @@ def GetServiceKeyFromName( service_name: str ):
|
|||
|
||||
try:
|
||||
|
||||
service_key = HG.client_controller.services_manager.GetServiceKeyFromName( HC.ALL_SERVICES, service_name )
|
||||
service_key = CG.client_controller.services_manager.GetServiceKeyFromName( HC.ALL_SERVICES, service_name )
|
||||
|
||||
except HydrusExceptions.DataMissing:
|
||||
|
||||
|
@ -739,7 +740,7 @@ def ParseHashes( request: HydrusServerRequest.HydrusRequest, optional = False ):
|
|||
|
||||
hash_id = request.parsed_request_args.GetValue( 'file_id', int )
|
||||
|
||||
hash_ids_to_hashes = HG.client_controller.Read( 'hash_ids_to_hashes', hash_ids = [ hash_id ] )
|
||||
hash_ids_to_hashes = CG.client_controller.Read( 'hash_ids_to_hashes', hash_ids = [ hash_id ] )
|
||||
|
||||
if len( hash_ids_to_hashes ) > 0:
|
||||
|
||||
|
@ -753,7 +754,7 @@ def ParseHashes( request: HydrusServerRequest.HydrusRequest, optional = False ):
|
|||
|
||||
hash_ids = request.parsed_request_args.GetValue( 'file_ids', list, expected_list_type = int )
|
||||
|
||||
hash_ids_to_hashes = HG.client_controller.Read( 'hash_ids_to_hashes', hash_ids = hash_ids )
|
||||
hash_ids_to_hashes = CG.client_controller.Read( 'hash_ids_to_hashes', hash_ids = hash_ids )
|
||||
|
||||
hashes.extend( [ hash_ids_to_hashes[ hash_id ] for hash_id in hash_ids ] )
|
||||
|
||||
|
@ -1016,15 +1017,15 @@ class HydrusResourceBooruFile( HydrusResourceBooru ):
|
|||
|
||||
is_attachment = request.parsed_request_args.GetValue( 'download', bool, default_value = False )
|
||||
|
||||
HG.client_controller.local_booru_manager.CheckFileAuthorised( share_key, hash )
|
||||
CG.client_controller.local_booru_manager.CheckFileAuthorised( share_key, hash )
|
||||
|
||||
media_result = HG.client_controller.local_booru_manager.GetMediaResult( share_key, hash )
|
||||
media_result = CG.client_controller.local_booru_manager.GetMediaResult( share_key, hash )
|
||||
|
||||
try:
|
||||
|
||||
mime = media_result.GetMime()
|
||||
|
||||
path = HG.client_controller.client_files_manager.GetFilePath( hash, mime )
|
||||
path = CG.client_controller.client_files_manager.GetFilePath( hash, mime )
|
||||
|
||||
except HydrusExceptions.FileMissingException:
|
||||
|
||||
|
@ -1045,7 +1046,7 @@ class HydrusResourceBooruGallery( HydrusResourceBooru ):
|
|||
|
||||
share_key = request.parsed_request_args.GetValue( 'share_key', bytes )
|
||||
|
||||
local_booru_manager = HG.client_controller.local_booru_manager
|
||||
local_booru_manager = CG.client_controller.local_booru_manager
|
||||
|
||||
local_booru_manager.CheckShareAuthorised( share_key )
|
||||
|
||||
|
@ -1127,7 +1128,7 @@ class HydrusResourceBooruPage( HydrusResourceBooru ):
|
|||
share_key = request.parsed_request_args.GetValue( 'share_key', bytes )
|
||||
hash = request.parsed_request_args.GetValue( 'hash', bytes )
|
||||
|
||||
local_booru_manager = HG.client_controller.local_booru_manager
|
||||
local_booru_manager = CG.client_controller.local_booru_manager
|
||||
|
||||
local_booru_manager.CheckFileAuthorised( share_key, hash )
|
||||
|
||||
|
@ -1216,7 +1217,7 @@ class HydrusResourceBooruThumbnail( HydrusResourceBooru ):
|
|||
share_key = request.parsed_request_args.GetValue( 'share_key', bytes )
|
||||
hash = request.parsed_request_args.GetValue( 'hash', bytes )
|
||||
|
||||
local_booru_manager = HG.client_controller.local_booru_manager
|
||||
local_booru_manager = CG.client_controller.local_booru_manager
|
||||
|
||||
local_booru_manager.CheckFileAuthorised( share_key, hash )
|
||||
|
||||
|
@ -1230,7 +1231,7 @@ class HydrusResourceBooruThumbnail( HydrusResourceBooru ):
|
|||
|
||||
try:
|
||||
|
||||
path = HG.client_controller.client_files_manager.GetThumbnailPath( media_result )
|
||||
path = CG.client_controller.client_files_manager.GetThumbnailPath( media_result )
|
||||
|
||||
if not os.path.exists( path ):
|
||||
|
||||
|
@ -1306,7 +1307,7 @@ class HydrusResourceClientAPI( HydrusServerResources.HydrusResource ):
|
|||
|
||||
HydrusServerResources.HydrusResource._reportRequestStarted( self, request )
|
||||
|
||||
HG.client_controller.ResetIdleTimerFromClientAPI()
|
||||
CG.client_controller.ResetIdleTimerFromClientAPI()
|
||||
|
||||
|
||||
def _checkService( self, request: HydrusServerRequest.HydrusRequest ):
|
||||
|
@ -1424,7 +1425,7 @@ class HydrusResourceClientAPIRestricted( HydrusResourceClientAPI ):
|
|||
|
||||
try:
|
||||
|
||||
api_permissions = HG.client_controller.client_api_manager.GetPermissions( access_key )
|
||||
api_permissions = CG.client_controller.client_api_manager.GetPermissions( access_key )
|
||||
|
||||
except HydrusExceptions.DataMissing as e:
|
||||
|
||||
|
@ -1482,7 +1483,7 @@ class HydrusResourceClientAPIRestricted( HydrusResourceClientAPI ):
|
|||
|
||||
try:
|
||||
|
||||
access_key = HG.client_controller.client_api_manager.GetAccessKey( session_key )
|
||||
access_key = CG.client_controller.client_api_manager.GetAccessKey( session_key )
|
||||
|
||||
except HydrusExceptions.DataMissing as e:
|
||||
|
||||
|
@ -1504,7 +1505,7 @@ class HydrusResourceClientAPIRestrictedAccountSessionKey( HydrusResourceClientAP
|
|||
|
||||
def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ):
|
||||
|
||||
new_session_key = HG.client_controller.client_api_manager.GenerateSessionKey( request.client_api_permissions.GetAccessKey() )
|
||||
new_session_key = CG.client_controller.client_api_manager.GenerateSessionKey( request.client_api_permissions.GetAccessKey() )
|
||||
|
||||
body_dict = {}
|
||||
|
||||
|
@ -1583,7 +1584,7 @@ class HydrusResourceClientAPIRestrictedGetService( HydrusResourceClientAPIRestri
|
|||
|
||||
try:
|
||||
|
||||
service_key = HG.client_controller.services_manager.GetServiceKeyFromName( allowed_service_types, service_name )
|
||||
service_key = CG.client_controller.services_manager.GetServiceKeyFromName( allowed_service_types, service_name )
|
||||
|
||||
except HydrusExceptions.DataMissing:
|
||||
|
||||
|
@ -1597,7 +1598,7 @@ class HydrusResourceClientAPIRestrictedGetService( HydrusResourceClientAPIRestri
|
|||
|
||||
try:
|
||||
|
||||
service = HG.client_controller.services_manager.GetService( service_key )
|
||||
service = CG.client_controller.services_manager.GetService( service_key )
|
||||
|
||||
except HydrusExceptions.DataMissing:
|
||||
|
||||
|
@ -1662,7 +1663,7 @@ class HydrusResourceClientAPIRestrictedGetServices( HydrusResourceClientAPIRestr
|
|||
|
||||
for ( service_types, name ) in jobs:
|
||||
|
||||
services = HG.client_controller.services_manager.GetServices( service_types )
|
||||
services = CG.client_controller.services_manager.GetServices( service_types )
|
||||
|
||||
services_list = []
|
||||
|
||||
|
@ -1726,7 +1727,7 @@ class HydrusResourceClientAPIRestrictedAddFilesAddFile( HydrusResourceClientAPIR
|
|||
|
||||
( os_file_handle, temp_path ) = request.temp_file_info
|
||||
|
||||
file_import_options = HG.client_controller.new_options.GetDefaultFileImportOptions( FileImportOptions.IMPORT_TYPE_QUIET )
|
||||
file_import_options = CG.client_controller.new_options.GetDefaultFileImportOptions( FileImportOptions.IMPORT_TYPE_QUIET )
|
||||
|
||||
file_import_job = ClientImportFiles.FileImportJob( temp_path, file_import_options )
|
||||
|
||||
|
@ -1773,7 +1774,7 @@ class HydrusResourceClientAPIRestrictedAddFilesArchiveFiles( HydrusResourceClien
|
|||
|
||||
content_update_package = ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdate( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, content_update )
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
CG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
||||
|
@ -1797,11 +1798,11 @@ class HydrusResourceClientAPIRestrictedAddFilesDeleteFiles( HydrusResourceClient
|
|||
|
||||
hashes = set( ParseHashes( request ) )
|
||||
|
||||
location_context.LimitToServiceTypes( HG.client_controller.services_manager.GetServiceType, ( HC.COMBINED_LOCAL_FILE, HC.COMBINED_LOCAL_MEDIA, HC.LOCAL_FILE_DOMAIN ) )
|
||||
location_context.LimitToServiceTypes( CG.client_controller.services_manager.GetServiceType, ( HC.COMBINED_LOCAL_FILE, HC.COMBINED_LOCAL_MEDIA, HC.LOCAL_FILE_DOMAIN ) )
|
||||
|
||||
if HG.client_controller.new_options.GetBoolean( 'delete_lock_for_archived_files' ):
|
||||
if CG.client_controller.new_options.GetBoolean( 'delete_lock_for_archived_files' ):
|
||||
|
||||
media_results = HG.client_controller.Read( 'media_results', hashes )
|
||||
media_results = CG.client_controller.Read( 'media_results', hashes )
|
||||
|
||||
undeletable_media_results = [ m for m in media_results if m.IsDeleteLocked() ]
|
||||
|
||||
|
@ -1821,7 +1822,7 @@ class HydrusResourceClientAPIRestrictedAddFilesDeleteFiles( HydrusResourceClient
|
|||
|
||||
content_update_package = ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdate( service_key, content_update )
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
CG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
@ -1840,7 +1841,7 @@ class HydrusResourceClientAPIRestrictedAddFilesUnarchiveFiles( HydrusResourceCli
|
|||
|
||||
content_update_package = ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdate( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, content_update )
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
CG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
||||
|
@ -1855,7 +1856,7 @@ class HydrusResourceClientAPIRestrictedAddFilesUndeleteFiles( HydrusResourceClie
|
|||
|
||||
hashes = set( ParseHashes( request ) )
|
||||
|
||||
location_context.LimitToServiceTypes( HG.client_controller.services_manager.GetServiceType, ( HC.LOCAL_FILE_DOMAIN, HC.COMBINED_LOCAL_MEDIA ) )
|
||||
location_context.LimitToServiceTypes( CG.client_controller.services_manager.GetServiceType, ( HC.LOCAL_FILE_DOMAIN, HC.COMBINED_LOCAL_MEDIA ) )
|
||||
|
||||
content_update = ClientContentUpdates.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_UNDELETE, hashes )
|
||||
|
||||
|
@ -1863,7 +1864,7 @@ class HydrusResourceClientAPIRestrictedAddFilesUndeleteFiles( HydrusResourceClie
|
|||
|
||||
content_update_package = ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdate( service_key, content_update )
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
CG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
@ -1952,7 +1953,7 @@ class HydrusResourceClientAPIRestrictedAddNotesSetNotes( HydrusResourceClientAPI
|
|||
|
||||
hash_id = request.parsed_request_args.GetValue( 'file_id', int )
|
||||
|
||||
hash_ids_to_hashes = HG.client_controller.Read( 'hash_ids_to_hashes', hash_ids = [ hash_id ] )
|
||||
hash_ids_to_hashes = CG.client_controller.Read( 'hash_ids_to_hashes', hash_ids = [ hash_id ] )
|
||||
|
||||
hash = hash_ids_to_hashes[ hash_id ]
|
||||
|
||||
|
@ -1983,7 +1984,7 @@ class HydrusResourceClientAPIRestrictedAddNotesSetNotes( HydrusResourceClientAPI
|
|||
note_import_options.SetExtendExistingNoteIfPossible( extend_existing_note_if_possible )
|
||||
note_import_options.SetConflictResolution( conflict_resolution )
|
||||
|
||||
media_result = HG.client_controller.Read( 'media_result', hash )
|
||||
media_result = CG.client_controller.Read( 'media_result', hash )
|
||||
|
||||
existing_names_to_notes = media_result.GetNotesManager().GetNamesToNotes()
|
||||
|
||||
|
@ -1998,7 +1999,7 @@ class HydrusResourceClientAPIRestrictedAddNotesSetNotes( HydrusResourceClientAPI
|
|||
|
||||
content_update_package = ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdates( CC.LOCAL_NOTES_SERVICE_KEY, content_updates )
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
CG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
|
||||
|
||||
body_dict = {}
|
||||
|
@ -2025,7 +2026,7 @@ class HydrusResourceClientAPIRestrictedAddNotesDeleteNotes( HydrusResourceClient
|
|||
|
||||
hash_id = request.parsed_request_args.GetValue( 'file_id', int )
|
||||
|
||||
hash_ids_to_hashes = HG.client_controller.Read( 'hash_ids_to_hashes', hash_ids = [ hash_id ] )
|
||||
hash_ids_to_hashes = CG.client_controller.Read( 'hash_ids_to_hashes', hash_ids = [ hash_id ] )
|
||||
|
||||
hash = hash_ids_to_hashes[ hash_id ]
|
||||
|
||||
|
@ -2040,7 +2041,7 @@ class HydrusResourceClientAPIRestrictedAddNotesDeleteNotes( HydrusResourceClient
|
|||
|
||||
content_update_package = ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdates( CC.LOCAL_NOTES_SERVICE_KEY, content_updates )
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
CG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
||||
|
@ -2232,7 +2233,7 @@ class HydrusResourceClientAPIRestrictedAddTagsAddTags( HydrusResourceClientAPIRe
|
|||
|
||||
if content_update_package.HasContent():
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
CG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
@ -2252,7 +2253,7 @@ class HydrusResourceClientAPIRestrictedAddTagsSearchTags( HydrusResourceClientAP
|
|||
|
||||
def _GetParsedAutocompleteText( self, search, tag_service_key ) -> ClientSearchAutocomplete.ParsedAutocompleteText:
|
||||
|
||||
tag_autocomplete_options = HG.client_controller.tag_display_manager.GetTagAutocompleteOptions( tag_service_key )
|
||||
tag_autocomplete_options = CG.client_controller.tag_display_manager.GetTagAutocompleteOptions( tag_service_key )
|
||||
|
||||
collapse_search_characters = True
|
||||
|
||||
|
@ -2283,7 +2284,7 @@ class HydrusResourceClientAPIRestrictedAddTagsSearchTags( HydrusResourceClientAP
|
|||
|
||||
search_namespaces_into_full_tags = parsed_autocomplete_text.GetTagAutocompleteOptions().SearchNamespacesIntoFullTags()
|
||||
|
||||
predicates = HG.client_controller.Read( 'autocomplete_predicates', tag_display_type, file_search_context, search_text = autocomplete_search_text, job_status = job_status, search_namespaces_into_full_tags = search_namespaces_into_full_tags )
|
||||
predicates = CG.client_controller.Read( 'autocomplete_predicates', tag_display_type, file_search_context, search_text = autocomplete_search_text, job_status = job_status, search_namespaces_into_full_tags = search_namespaces_into_full_tags )
|
||||
|
||||
display_tag_service_key = tag_context.display_service_key
|
||||
|
||||
|
@ -2337,7 +2338,7 @@ class HydrusResourceClientAPIRestrictedAddTagsGetTagSiblingsParents( HydrusResou
|
|||
|
||||
tags = HydrusTags.CleanTags( tags )
|
||||
|
||||
tags_to_service_keys_to_siblings_and_parents = HG.client_controller.Read( 'tag_siblings_and_parents_lookup', tags )
|
||||
tags_to_service_keys_to_siblings_and_parents = CG.client_controller.Read( 'tag_siblings_and_parents_lookup', tags )
|
||||
|
||||
tags_dict = {}
|
||||
|
||||
|
@ -2440,7 +2441,7 @@ class HydrusResourceClientAPIRestrictedAddURLsAssociateURL( HydrusResourceClient
|
|||
|
||||
|
||||
|
||||
domain_manager = HG.client_controller.network_engine.domain_manager
|
||||
domain_manager = CG.client_controller.network_engine.domain_manager
|
||||
|
||||
try:
|
||||
|
||||
|
@ -2481,7 +2482,7 @@ class HydrusResourceClientAPIRestrictedAddURLsAssociateURL( HydrusResourceClient
|
|||
|
||||
if content_update_package.HasContent():
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
CG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
@ -2505,14 +2506,14 @@ class HydrusResourceClientAPIRestrictedAddURLsGetURLFiles( HydrusResourceClientA
|
|||
|
||||
try:
|
||||
|
||||
normalised_url = HG.client_controller.network_engine.domain_manager.NormaliseURL( url )
|
||||
normalised_url = CG.client_controller.network_engine.domain_manager.NormaliseURL( url )
|
||||
|
||||
except HydrusExceptions.URLClassException as e:
|
||||
|
||||
raise HydrusExceptions.BadRequestException( e )
|
||||
|
||||
|
||||
url_statuses = HG.client_controller.Read( 'url_statuses', normalised_url )
|
||||
url_statuses = CG.client_controller.Read( 'url_statuses', normalised_url )
|
||||
|
||||
json_happy_url_statuses = []
|
||||
|
||||
|
@ -2567,9 +2568,9 @@ class HydrusResourceClientAPIRestrictedAddURLsGetURLInfo( HydrusResourceClientAP
|
|||
|
||||
try:
|
||||
|
||||
normalised_url = HG.client_controller.network_engine.domain_manager.NormaliseURL( url )
|
||||
normalised_url = CG.client_controller.network_engine.domain_manager.NormaliseURL( url )
|
||||
|
||||
( url_type, match_name, can_parse, cannot_parse_reason ) = HG.client_controller.network_engine.domain_manager.GetURLParseCapability( normalised_url )
|
||||
( url_type, match_name, can_parse, cannot_parse_reason ) = CG.client_controller.network_engine.domain_manager.GetURLParseCapability( normalised_url )
|
||||
|
||||
except HydrusExceptions.URLClassException as e:
|
||||
|
||||
|
@ -2654,12 +2655,12 @@ class HydrusResourceClientAPIRestrictedAddURLsImportURL( HydrusResourceClientAPI
|
|||
|
||||
def do_it():
|
||||
|
||||
return HG.client_controller.gui.ImportURLFromAPI( url, filterable_tags, additional_service_keys_to_tags, destination_page_name, destination_page_key, show_destination_page )
|
||||
return CG.client_controller.gui.ImportURLFromAPI( url, filterable_tags, additional_service_keys_to_tags, destination_page_name, destination_page_key, show_destination_page )
|
||||
|
||||
|
||||
try:
|
||||
|
||||
( normalised_url, result_text ) = HG.client_controller.CallBlockingToQt( HG.client_controller.gui, do_it )
|
||||
( normalised_url, result_text ) = CG.client_controller.CallBlockingToQt( CG.client_controller.gui, do_it )
|
||||
|
||||
except HydrusExceptions.URLClassException as e:
|
||||
|
||||
|
@ -2706,7 +2707,7 @@ class HydrusResourceClientAPIRestrictedEditRatingsSetRating( HydrusResourceClien
|
|||
|
||||
rating = request.parsed_request_args[ 'rating' ]
|
||||
|
||||
rating_service = HG.client_controller.services_manager.GetService( rating_service_key )
|
||||
rating_service = CG.client_controller.services_manager.GetService( rating_service_key )
|
||||
|
||||
rating_service_type = rating_service.GetServiceType()
|
||||
|
||||
|
@ -2771,7 +2772,7 @@ class HydrusResourceClientAPIRestrictedEditRatingsSetRating( HydrusResourceClien
|
|||
|
||||
content_update_package = ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdate( rating_service_key, content_update )
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
CG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
||||
|
@ -2798,7 +2799,7 @@ class HydrusResourceClientAPIRestrictedEditTimesSetTime( HydrusResourceClientAPI
|
|||
raise HydrusExceptions.BadRequestException( 'Did not find any hashes to apply the times to!' )
|
||||
|
||||
|
||||
media_results = HG.client_controller.Read( 'media_results', hashes )
|
||||
media_results = CG.client_controller.Read( 'media_results', hashes )
|
||||
|
||||
if 'timestamp' in request.parsed_request_args:
|
||||
|
||||
|
@ -2857,12 +2858,12 @@ class HydrusResourceClientAPIRestrictedEditTimesSetTime( HydrusResourceClientAPI
|
|||
|
||||
file_service_key = request.parsed_request_args.GetValue( 'file_service_key', bytes )
|
||||
|
||||
if not HG.client_controller.services_manager.ServiceExists( file_service_key ):
|
||||
if not CG.client_controller.services_manager.ServiceExists( file_service_key ):
|
||||
|
||||
raise HydrusExceptions.BadRequestException( 'Sorry, do not know that service!' )
|
||||
|
||||
|
||||
if HG.client_controller.services_manager.GetServiceType( file_service_key ) not in HC.REAL_FILE_SERVICES:
|
||||
if CG.client_controller.services_manager.GetServiceType( file_service_key ) not in HC.REAL_FILE_SERVICES:
|
||||
|
||||
raise HydrusExceptions.BadRequestException( 'Sorry, you have to specify a file service service key!' )
|
||||
|
||||
|
@ -2915,7 +2916,7 @@ class HydrusResourceClientAPIRestrictedEditTimesSetTime( HydrusResourceClientAPI
|
|||
|
||||
content_update_package = ClientContentUpdates.ContentUpdatePackage.STATICCreateFromContentUpdates( CC.COMBINED_LOCAL_FILE_SERVICE_KEY, content_updates )
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
CG.client_controller.WriteSynchronous( 'content_updates', content_update_package )
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
||||
|
@ -2996,7 +2997,7 @@ class HydrusResourceClientAPIRestrictedGetFilesSearchFiles( HydrusResourceClient
|
|||
|
||||
request.disconnect_callables.append( job_status.Cancel )
|
||||
|
||||
hash_ids = HG.client_controller.Read( 'file_query_ids', file_search_context, job_status = job_status, sort_by = sort_by, apply_implicit_limit = False )
|
||||
hash_ids = CG.client_controller.Read( 'file_query_ids', file_search_context, job_status = job_status, sort_by = sort_by, apply_implicit_limit = False )
|
||||
|
||||
|
||||
request.client_api_permissions.SetLastSearchResults( hash_ids )
|
||||
|
@ -3005,7 +3006,7 @@ class HydrusResourceClientAPIRestrictedGetFilesSearchFiles( HydrusResourceClient
|
|||
|
||||
if return_hashes:
|
||||
|
||||
hash_ids_to_hashes = HG.client_controller.Read( 'hash_ids_to_hashes', hash_ids = hash_ids )
|
||||
hash_ids_to_hashes = CG.client_controller.Read( 'hash_ids_to_hashes', hash_ids = hash_ids )
|
||||
|
||||
# maintain sort
|
||||
body_dict[ 'hashes' ] = [ hash_ids_to_hashes[ hash_id ].hex() for hash_id in hash_ids ]
|
||||
|
@ -3035,7 +3036,7 @@ class HydrusResourceClientAPIRestrictedGetFilesGetFile( HydrusResourceClientAPIR
|
|||
|
||||
request.client_api_permissions.CheckPermissionToSeeFiles( ( file_id, ) )
|
||||
|
||||
( media_result, ) = HG.client_controller.Read( 'media_results_from_ids', ( file_id, ) )
|
||||
( media_result, ) = CG.client_controller.Read( 'media_results_from_ids', ( file_id, ) )
|
||||
|
||||
elif 'hash' in request.parsed_request_args:
|
||||
|
||||
|
@ -3043,7 +3044,7 @@ class HydrusResourceClientAPIRestrictedGetFilesGetFile( HydrusResourceClientAPIR
|
|||
|
||||
hash = request.parsed_request_args.GetValue( 'hash', bytes )
|
||||
|
||||
media_result = HG.client_controller.Read( 'media_result', hash )
|
||||
media_result = CG.client_controller.Read( 'media_result', hash )
|
||||
|
||||
else:
|
||||
|
||||
|
@ -3060,7 +3061,7 @@ class HydrusResourceClientAPIRestrictedGetFilesGetFile( HydrusResourceClientAPIR
|
|||
hash = media_result.GetHash()
|
||||
mime = media_result.GetMime()
|
||||
|
||||
path = HG.client_controller.client_files_manager.GetFilePath( hash, mime )
|
||||
path = CG.client_controller.client_files_manager.GetFilePath( hash, mime )
|
||||
|
||||
if not os.path.exists( path ):
|
||||
|
||||
|
@ -3093,7 +3094,7 @@ class HydrusResourceClientAPIRestrictedGetFilesGetRenderedFile( HydrusResourceCl
|
|||
|
||||
request.client_api_permissions.CheckPermissionToSeeFiles( ( file_id, ) )
|
||||
|
||||
( media_result, ) = HG.client_controller.Read( 'media_results_from_ids', ( file_id, ) )
|
||||
( media_result, ) = CG.client_controller.Read( 'media_results_from_ids', ( file_id, ) )
|
||||
|
||||
elif 'hash' in request.parsed_request_args:
|
||||
|
||||
|
@ -3101,7 +3102,7 @@ class HydrusResourceClientAPIRestrictedGetFilesGetRenderedFile( HydrusResourceCl
|
|||
|
||||
hash = request.parsed_request_args.GetValue( 'hash', bytes )
|
||||
|
||||
media_result = HG.client_controller.Read( 'media_result', hash )
|
||||
media_result = CG.client_controller.Read( 'media_result', hash )
|
||||
|
||||
else:
|
||||
|
||||
|
@ -3118,7 +3119,7 @@ class HydrusResourceClientAPIRestrictedGetFilesGetRenderedFile( HydrusResourceCl
|
|||
raise HydrusExceptions.BadRequestException('Requested file is not an image!')
|
||||
|
||||
|
||||
renderer: ClientRendering.ImageRenderer = HG.client_controller.GetCache( 'images' ).GetImageRenderer( media_result )
|
||||
renderer: ClientRendering.ImageRenderer = CG.client_controller.GetCache( 'images' ).GetImageRenderer( media_result )
|
||||
|
||||
while not renderer.IsReady():
|
||||
|
||||
|
@ -3184,7 +3185,7 @@ class HydrusResourceClientAPIRestrictedGetFilesFileHashes( HydrusResourceClientA
|
|||
|
||||
CheckHashLength( source_hashes, hash_type = source_hash_type )
|
||||
|
||||
source_to_desired = HG.client_controller.Read( 'file_hashes', source_hashes, source_hash_type, desired_hash_type )
|
||||
source_to_desired = CG.client_controller.Read( 'file_hashes', source_hashes, source_hash_type, desired_hash_type )
|
||||
|
||||
encoded_source_to_desired = { source_hash.hex() : desired_hash.hex() for ( source_hash, desired_hash ) in source_to_desired.items() }
|
||||
|
||||
|
@ -3235,7 +3236,7 @@ class HydrusResourceClientAPIRestrictedGetFilesFileMetadata( HydrusResourceClien
|
|||
|
||||
hashes = ParseHashes( request )
|
||||
|
||||
hash_ids_to_hashes = HG.client_controller.Read( 'hash_ids_to_hashes', hashes = hashes, create_new_hash_ids = create_new_file_ids )
|
||||
hash_ids_to_hashes = CG.client_controller.Read( 'hash_ids_to_hashes', hashes = hashes, create_new_hash_ids = create_new_file_ids )
|
||||
|
||||
hashes_to_hash_ids = { hash : hash_id for ( hash_id, hash ) in hash_ids_to_hashes.items() }
|
||||
|
||||
|
@ -3268,7 +3269,7 @@ class HydrusResourceClientAPIRestrictedGetFilesFileMetadata( HydrusResourceClien
|
|||
|
||||
elif only_return_basic_information:
|
||||
|
||||
file_info_managers = HG.client_controller.Read( 'file_info_managers_from_ids', hash_ids )
|
||||
file_info_managers = CG.client_controller.Read( 'file_info_managers_from_ids', hash_ids )
|
||||
|
||||
hashes_to_file_info_managers = { file_info_manager.hash : file_info_manager for file_info_manager in file_info_managers }
|
||||
|
||||
|
@ -3318,11 +3319,11 @@ class HydrusResourceClientAPIRestrictedGetFilesFileMetadata( HydrusResourceClien
|
|||
|
||||
else:
|
||||
|
||||
media_results = HG.client_controller.Read( 'media_results_from_ids', hash_ids )
|
||||
media_results = CG.client_controller.Read( 'media_results_from_ids', hash_ids )
|
||||
|
||||
hashes_to_media_results = { media_result.GetFileInfoManager().hash : media_result for media_result in media_results }
|
||||
|
||||
services_manager = HG.client_controller.services_manager
|
||||
services_manager = CG.client_controller.services_manager
|
||||
|
||||
rating_service_keys = services_manager.GetServiceKeys( HC.RATINGS_SERVICES )
|
||||
tag_service_keys = services_manager.GetServiceKeys( HC.ALL_TAG_SERVICES )
|
||||
|
@ -3331,9 +3332,9 @@ class HydrusResourceClientAPIRestrictedGetFilesFileMetadata( HydrusResourceClien
|
|||
|
||||
ipfs_service_keys = services_manager.GetServiceKeys( ( HC.IPFS, ) )
|
||||
|
||||
thumbnail_bounding_dimensions = HG.client_controller.options[ 'thumbnail_dimensions' ]
|
||||
thumbnail_scale_type = HG.client_controller.new_options.GetInteger( 'thumbnail_scale_type' )
|
||||
thumbnail_dpr_percent = HG.client_controller.new_options.GetInteger( 'thumbnail_dpr_percent' )
|
||||
thumbnail_bounding_dimensions = CG.client_controller.options[ 'thumbnail_dimensions' ]
|
||||
thumbnail_scale_type = CG.client_controller.new_options.GetInteger( 'thumbnail_scale_type' )
|
||||
thumbnail_dpr_percent = CG.client_controller.new_options.GetInteger( 'thumbnail_dpr_percent' )
|
||||
|
||||
for hash in hashes:
|
||||
|
||||
|
@ -3461,9 +3462,9 @@ class HydrusResourceClientAPIRestrictedGetFilesFileMetadata( HydrusResourceClien
|
|||
|
||||
try:
|
||||
|
||||
normalised_url = HG.client_controller.network_engine.domain_manager.NormaliseURL( known_url )
|
||||
normalised_url = CG.client_controller.network_engine.domain_manager.NormaliseURL( known_url )
|
||||
|
||||
( url_type, match_name, can_parse, cannot_parse_reason ) = HG.client_controller.network_engine.domain_manager.GetURLParseCapability( normalised_url )
|
||||
( url_type, match_name, can_parse, cannot_parse_reason ) = CG.client_controller.network_engine.domain_manager.GetURLParseCapability( normalised_url )
|
||||
|
||||
except HydrusExceptions.URLClassException as e:
|
||||
|
||||
|
@ -3606,7 +3607,7 @@ class HydrusResourceClientAPIRestrictedGetFilesGetThumbnail( HydrusResourceClien
|
|||
|
||||
request.client_api_permissions.CheckPermissionToSeeFiles( ( file_id, ) )
|
||||
|
||||
( media_result, ) = HG.client_controller.Read( 'media_results_from_ids', ( file_id, ) )
|
||||
( media_result, ) = CG.client_controller.Read( 'media_results_from_ids', ( file_id, ) )
|
||||
|
||||
elif 'hash' in request.parsed_request_args:
|
||||
|
||||
|
@ -3614,7 +3615,7 @@ class HydrusResourceClientAPIRestrictedGetFilesGetThumbnail( HydrusResourceClien
|
|||
|
||||
hash = request.parsed_request_args.GetValue( 'hash', bytes )
|
||||
|
||||
media_result = HG.client_controller.Read( 'media_result', hash )
|
||||
media_result = CG.client_controller.Read( 'media_result', hash )
|
||||
|
||||
else:
|
||||
|
||||
|
@ -3632,7 +3633,7 @@ class HydrusResourceClientAPIRestrictedGetFilesGetThumbnail( HydrusResourceClien
|
|||
|
||||
try:
|
||||
|
||||
path = HG.client_controller.client_files_manager.GetThumbnailPath( media_result )
|
||||
path = CG.client_controller.client_files_manager.GetThumbnailPath( media_result )
|
||||
|
||||
if not os.path.exists( path ):
|
||||
|
||||
|
@ -3679,7 +3680,7 @@ class HydrusResourceClientAPIRestrictedManageCookiesGetCookies( HydrusResourceCl
|
|||
|
||||
network_context = ClientNetworkingContexts.NetworkContext( CC.NETWORK_CONTEXT_DOMAIN, domain )
|
||||
|
||||
session = HG.client_controller.network_engine.session_manager.GetSession( network_context )
|
||||
session = CG.client_controller.network_engine.session_manager.GetSession( network_context )
|
||||
|
||||
body_cookies_list = []
|
||||
|
||||
|
@ -3736,7 +3737,7 @@ class HydrusResourceClientAPIRestrictedManageCookiesSetCookies( HydrusResourceCl
|
|||
|
||||
network_context = ClientNetworkingContexts.NetworkContext( CC.NETWORK_CONTEXT_DOMAIN, domain )
|
||||
|
||||
session = HG.client_controller.network_engine.session_manager.GetSession( network_context )
|
||||
session = CG.client_controller.network_engine.session_manager.GetSession( network_context )
|
||||
|
||||
if value is None:
|
||||
|
||||
|
@ -3751,10 +3752,10 @@ class HydrusResourceClientAPIRestrictedManageCookiesSetCookies( HydrusResourceCl
|
|||
ClientNetworkingFunctions.AddCookieToSession( session, name, value, domain, path, expires )
|
||||
|
||||
|
||||
HG.client_controller.network_engine.session_manager.SetSessionDirty( network_context )
|
||||
CG.client_controller.network_engine.session_manager.SetSessionDirty( network_context )
|
||||
|
||||
|
||||
if HG.client_controller.new_options.GetBoolean( 'notify_client_api_cookies' ) and len( domains_cleared ) + len( domains_set ) > 0:
|
||||
if CG.client_controller.new_options.GetBoolean( 'notify_client_api_cookies' ) and len( domains_cleared ) + len( domains_set ) > 0:
|
||||
|
||||
domains_cleared = sorted( domains_cleared )
|
||||
domains_set = sorted( domains_set )
|
||||
|
@ -3777,7 +3778,7 @@ class HydrusResourceClientAPIRestrictedManageCookiesSetCookies( HydrusResourceCl
|
|||
|
||||
job_status.FinishAndDismiss( 5 )
|
||||
|
||||
HG.client_controller.pub( 'message', job_status )
|
||||
CG.client_controller.pub( 'message', job_status )
|
||||
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
@ -3799,7 +3800,7 @@ class HydrusResourceClientAPIRestrictedManageCookiesSetUserAgent( HydrusResource
|
|||
user_agent = ClientDefaults.DEFAULT_USER_AGENT
|
||||
|
||||
|
||||
HG.client_controller.network_engine.domain_manager.SetCustomHeader( ClientNetworkingContexts.GLOBAL_NETWORK_CONTEXT, 'User-Agent', value = user_agent )
|
||||
CG.client_controller.network_engine.domain_manager.SetCustomHeader( ClientNetworkingContexts.GLOBAL_NETWORK_CONTEXT, 'User-Agent', value = user_agent )
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
||||
|
@ -3856,7 +3857,7 @@ class HydrusResourceClientAPIRestrictedManageCookiesGetHeaders( HydrusResourceCl
|
|||
|
||||
network_context = GenerateNetworkContextFromRequest( request )
|
||||
|
||||
ncs_to_header_dicts = HG.client_controller.network_engine.domain_manager.GetNetworkContextsToCustomHeaderDicts()
|
||||
ncs_to_header_dicts = CG.client_controller.network_engine.domain_manager.GetNetworkContextsToCustomHeaderDicts()
|
||||
|
||||
body_dict = {}
|
||||
|
||||
|
@ -3898,7 +3899,7 @@ class HydrusResourceClientAPIRestrictedManageCookiesSetHeaders( HydrusResourceCl
|
|||
|
||||
for ( key, info_dict ) in http_header_objects.items():
|
||||
|
||||
ncs_to_header_dicts = HG.client_controller.network_engine.domain_manager.GetNetworkContextsToCustomHeaderDicts()
|
||||
ncs_to_header_dicts = CG.client_controller.network_engine.domain_manager.GetNetworkContextsToCustomHeaderDicts()
|
||||
|
||||
if network_context in ncs_to_header_dicts:
|
||||
|
||||
|
@ -3942,7 +3943,7 @@ class HydrusResourceClientAPIRestrictedManageCookiesSetHeaders( HydrusResourceCl
|
|||
|
||||
if key in headers_dict:
|
||||
|
||||
HG.client_controller.network_engine.domain_manager.DeleteCustomHeader( network_context, key )
|
||||
CG.client_controller.network_engine.domain_manager.DeleteCustomHeader( network_context, key )
|
||||
|
||||
headers_cleared.add( key )
|
||||
|
||||
|
@ -3976,7 +3977,7 @@ class HydrusResourceClientAPIRestrictedManageCookiesSetHeaders( HydrusResourceCl
|
|||
|
||||
if do_it:
|
||||
|
||||
HG.client_controller.network_engine.domain_manager.SetCustomHeader( network_context, key, value = value, approved = approved, reason = reason )
|
||||
CG.client_controller.network_engine.domain_manager.SetCustomHeader( network_context, key, value = value, approved = approved, reason = reason )
|
||||
|
||||
|
||||
|
||||
|
@ -3994,11 +3995,11 @@ class HydrusResourceClientAPIRestrictedManageCookiesSetHeaders( HydrusResourceCl
|
|||
|
||||
headers_altered.add( key )
|
||||
|
||||
HG.client_controller.network_engine.domain_manager.SetCustomHeader( network_context, key, approved = approved, reason = reason )
|
||||
CG.client_controller.network_engine.domain_manager.SetCustomHeader( network_context, key, approved = approved, reason = reason )
|
||||
|
||||
|
||||
|
||||
if HG.client_controller.new_options.GetBoolean( 'notify_client_api_cookies' ) and len( headers_cleared ) + len( headers_set ) + len( headers_altered ) > 0:
|
||||
if CG.client_controller.new_options.GetBoolean( 'notify_client_api_cookies' ) and len( headers_cleared ) + len( headers_set ) + len( headers_altered ) > 0:
|
||||
|
||||
message_lines = [ 'Headers sent from API:' ]
|
||||
|
||||
|
@ -4025,7 +4026,7 @@ class HydrusResourceClientAPIRestrictedManageCookiesSetHeaders( HydrusResourceCl
|
|||
|
||||
job_status.FinishAndDismiss( 5 )
|
||||
|
||||
HG.client_controller.pub( 'message', job_status )
|
||||
CG.client_controller.pub( 'message', job_status )
|
||||
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
@ -4056,7 +4057,7 @@ class HydrusResourceClientAPIRestrictedManageDatabaseLockOff( HydrusResourceClie
|
|||
raise HydrusExceptions.BadRequestException( 'The server is not busy!' )
|
||||
|
||||
|
||||
HG.client_controller.db.PauseAndDisconnect( False )
|
||||
CG.client_controller.db.PauseAndDisconnect( False )
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
||||
|
@ -4074,13 +4075,13 @@ class HydrusResourceClientAPIRestrictedManageDatabaseLockOn( HydrusResourceClien
|
|||
raise HydrusExceptions.BadRequestException( 'The client was already locked!' )
|
||||
|
||||
|
||||
HG.client_controller.db.PauseAndDisconnect( True )
|
||||
CG.client_controller.db.PauseAndDisconnect( True )
|
||||
|
||||
TIME_BLOCK = 0.25
|
||||
|
||||
for i in range( int( 5 / TIME_BLOCK ) ):
|
||||
|
||||
if not HG.client_controller.db.IsConnected():
|
||||
if not CG.client_controller.db.IsConnected():
|
||||
|
||||
break
|
||||
|
||||
|
@ -4115,7 +4116,7 @@ class HydrusResourceClientAPIRestrictedManageDatabaseMrBones( HydrusResourceClie
|
|||
|
||||
request.disconnect_callables.append( job_status.Cancel )
|
||||
|
||||
boned_stats = HG.client_controller.Read( 'boned_stats', file_search_context = file_search_context, job_status = job_status )
|
||||
boned_stats = CG.client_controller.Read( 'boned_stats', file_search_context = file_search_context, job_status = job_status )
|
||||
|
||||
body_dict = { 'boned_stats' : boned_stats }
|
||||
|
||||
|
@ -4136,11 +4137,11 @@ class HydrusResourceClientAPIRestrictedManageDatabaseGetClientOptions( HydrusRes
|
|||
|
||||
OLD_OPTIONS_DEFAULT = ClientDefaults.GetClientDefaultOptions()
|
||||
|
||||
old_options = HG.client_controller.options
|
||||
old_options = CG.client_controller.options
|
||||
|
||||
old_options = { key : value for ( key, value ) in old_options.items() if key in OLD_OPTIONS_DEFAULT }
|
||||
|
||||
new_options: ClientOptions.ClientOptions = HG.client_controller.new_options
|
||||
new_options: ClientOptions.ClientOptions = CG.client_controller.new_options
|
||||
|
||||
options_dict = {
|
||||
'booleans' : new_options.GetAllBooleans(),
|
||||
|
@ -4196,7 +4197,7 @@ class HydrusResourceClientAPIRestrictedManageFileRelationshipsGetRelationships(
|
|||
hashes = ParseHashes( request )
|
||||
|
||||
# maybe in future we'll just get the media results and dump the dict from there, but whatever
|
||||
hashes_to_file_duplicates = HG.client_controller.Read( 'file_relationships_for_api', location_context, hashes )
|
||||
hashes_to_file_duplicates = CG.client_controller.Read( 'file_relationships_for_api', location_context, hashes )
|
||||
|
||||
body_dict = { 'file_relationships' : hashes_to_file_duplicates }
|
||||
|
||||
|
@ -4220,7 +4221,7 @@ class HydrusResourceClientAPIRestrictedManageFileRelationshipsGetPotentialsCount
|
|||
max_hamming_distance
|
||||
) = ParseDuplicateSearch( request )
|
||||
|
||||
count = HG.client_controller.Read( 'potential_duplicates_count', file_search_context_1, file_search_context_2, dupe_search_type, pixel_dupes_preference, max_hamming_distance )
|
||||
count = CG.client_controller.Read( 'potential_duplicates_count', file_search_context_1, file_search_context_2, dupe_search_type, pixel_dupes_preference, max_hamming_distance )
|
||||
|
||||
body_dict = { 'potential_duplicates_count' : count }
|
||||
|
||||
|
@ -4244,9 +4245,9 @@ class HydrusResourceClientAPIRestrictedManageFileRelationshipsGetPotentialPairs(
|
|||
max_hamming_distance
|
||||
) = ParseDuplicateSearch( request )
|
||||
|
||||
max_num_pairs = request.parsed_request_args.GetValue( 'max_num_pairs', int, default_value = HG.client_controller.new_options.GetInteger( 'duplicate_filter_max_batch_size' ) )
|
||||
max_num_pairs = request.parsed_request_args.GetValue( 'max_num_pairs', int, default_value = CG.client_controller.new_options.GetInteger( 'duplicate_filter_max_batch_size' ) )
|
||||
|
||||
filtering_pairs_media_results = HG.client_controller.Read( 'duplicate_pairs_for_filtering', file_search_context_1, file_search_context_2, dupe_search_type, pixel_dupes_preference, max_hamming_distance, max_num_pairs = max_num_pairs )
|
||||
filtering_pairs_media_results = CG.client_controller.Read( 'duplicate_pairs_for_filtering', file_search_context_1, file_search_context_2, dupe_search_type, pixel_dupes_preference, max_hamming_distance, max_num_pairs = max_num_pairs )
|
||||
|
||||
filtering_pairs_hashes = [ ( m1.GetHash().hex(), m2.GetHash().hex() ) for ( m1, m2 ) in filtering_pairs_media_results ]
|
||||
|
||||
|
@ -4272,7 +4273,7 @@ class HydrusResourceClientAPIRestrictedManageFileRelationshipsGetRandomPotential
|
|||
max_hamming_distance
|
||||
) = ParseDuplicateSearch( request )
|
||||
|
||||
hashes = HG.client_controller.Read( 'random_potential_duplicate_hashes', file_search_context_1, file_search_context_2, dupe_search_type, pixel_dupes_preference, max_hamming_distance )
|
||||
hashes = CG.client_controller.Read( 'random_potential_duplicate_hashes', file_search_context_1, file_search_context_2, dupe_search_type, pixel_dupes_preference, max_hamming_distance )
|
||||
|
||||
body_dict = { 'random_potential_duplicate_hashes' : [ hash.hex() for hash in hashes ] }
|
||||
|
||||
|
@ -4292,7 +4293,7 @@ class HydrusResourceClientAPIRestrictedManageFileRelationshipsSetKings( HydrusRe
|
|||
|
||||
for hash in hashes:
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'duplicate_set_king', hash )
|
||||
CG.client_controller.WriteSynchronous( 'duplicate_set_king', hash )
|
||||
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
@ -4363,7 +4364,7 @@ class HydrusResourceClientAPIRestrictedManageFileRelationshipsSetRelationships(
|
|||
all_hashes.update( ( hash_a, hash_b ) )
|
||||
|
||||
|
||||
media_results = HG.client_controller.Read( 'media_results', all_hashes )
|
||||
media_results = CG.client_controller.Read( 'media_results', all_hashes )
|
||||
|
||||
hashes_to_media_results = { media_result.GetHash() : media_result for media_result in media_results }
|
||||
|
||||
|
@ -4383,7 +4384,7 @@ class HydrusResourceClientAPIRestrictedManageFileRelationshipsSetRelationships(
|
|||
|
||||
if do_default_content_merge:
|
||||
|
||||
duplicate_content_merge_options = HG.client_controller.new_options.GetDuplicateContentMergeOptions( duplicate_type )
|
||||
duplicate_content_merge_options = CG.client_controller.new_options.GetDuplicateContentMergeOptions( duplicate_type )
|
||||
|
||||
content_update_packages.append( duplicate_content_merge_options.ProcessPairIntoContentUpdatePackage( first_media, second_media, file_deletion_reason = file_deletion_reason, delete_first = delete_first, delete_second = delete_second ) )
|
||||
|
||||
|
@ -4418,7 +4419,7 @@ class HydrusResourceClientAPIRestrictedManageFileRelationshipsSetRelationships(
|
|||
|
||||
else:
|
||||
|
||||
local_file_service_keys = HG.client_controller.services_manager.GetServiceKeys( ( HC.LOCAL_FILE_DOMAIN, ) )
|
||||
local_file_service_keys = CG.client_controller.services_manager.GetServiceKeys( ( HC.LOCAL_FILE_DOMAIN, ) )
|
||||
|
||||
deletee_service_keys = media.GetLocationsManager().GetCurrent().intersection( local_file_service_keys )
|
||||
|
||||
|
@ -4439,7 +4440,7 @@ class HydrusResourceClientAPIRestrictedManageFileRelationshipsSetRelationships(
|
|||
|
||||
if len( database_write_rows ) > 0:
|
||||
|
||||
HG.client_controller.WriteSynchronous( 'duplicate_pair_status', database_write_rows )
|
||||
CG.client_controller.WriteSynchronous( 'duplicate_pair_status', database_write_rows )
|
||||
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
@ -4462,7 +4463,7 @@ class HydrusResourceClientAPIRestrictedManagePagesAddFiles( HydrusResourceClient
|
|||
|
||||
def do_it( page_key, media_results ):
|
||||
|
||||
page = HG.client_controller.gui.GetPageFromPageKey( page_key )
|
||||
page = CG.client_controller.gui.GetPageFromPageKey( page_key )
|
||||
|
||||
from hydrus.client.gui.pages import ClientGUIPages
|
||||
|
||||
|
@ -4488,11 +4489,11 @@ class HydrusResourceClientAPIRestrictedManagePagesAddFiles( HydrusResourceClient
|
|||
|
||||
hashes = ParseHashes( request )
|
||||
|
||||
media_results = HG.client_controller.Read( 'media_results', hashes, sorted = True )
|
||||
media_results = CG.client_controller.Read( 'media_results', hashes, sorted = True )
|
||||
|
||||
try:
|
||||
|
||||
HG.client_controller.CallBlockingToQt( HG.client_controller.gui, do_it, page_key, media_results )
|
||||
CG.client_controller.CallBlockingToQt( CG.client_controller.gui, do_it, page_key, media_results )
|
||||
|
||||
except HydrusExceptions.DataMissing as e:
|
||||
|
||||
|
@ -4511,14 +4512,14 @@ class HydrusResourceClientAPIRestrictedManagePagesFocusPage( HydrusResourceClien
|
|||
|
||||
def do_it( page_key ):
|
||||
|
||||
return HG.client_controller.gui.ShowPage( page_key )
|
||||
return CG.client_controller.gui.ShowPage( page_key )
|
||||
|
||||
|
||||
page_key = request.parsed_request_args.GetValue( 'page_key', bytes )
|
||||
|
||||
try:
|
||||
|
||||
HG.client_controller.CallBlockingToQt( HG.client_controller.gui, do_it, page_key )
|
||||
CG.client_controller.CallBlockingToQt( CG.client_controller.gui, do_it, page_key )
|
||||
|
||||
except HydrusExceptions.DataMissing as e:
|
||||
|
||||
|
@ -4536,10 +4537,10 @@ class HydrusResourceClientAPIRestrictedManagePagesGetPages( HydrusResourceClient
|
|||
|
||||
def do_it():
|
||||
|
||||
return HG.client_controller.gui.GetCurrentSessionPageAPIInfoDict()
|
||||
return CG.client_controller.gui.GetCurrentSessionPageAPIInfoDict()
|
||||
|
||||
|
||||
page_info_dict = HG.client_controller.CallBlockingToQt( HG.client_controller.gui, do_it )
|
||||
page_info_dict = CG.client_controller.CallBlockingToQt( CG.client_controller.gui, do_it )
|
||||
|
||||
body_dict = { 'pages' : page_info_dict }
|
||||
|
||||
|
@ -4557,14 +4558,14 @@ class HydrusResourceClientAPIRestrictedManagePagesGetPageInfo( HydrusResourceCli
|
|||
|
||||
def do_it( page_key, simple ):
|
||||
|
||||
return HG.client_controller.gui.GetPageAPIInfoDict( page_key, simple )
|
||||
return CG.client_controller.gui.GetPageAPIInfoDict( page_key, simple )
|
||||
|
||||
|
||||
page_key = request.parsed_request_args.GetValue( 'page_key', bytes )
|
||||
|
||||
simple = request.parsed_request_args.GetValue( 'simple', bool, default_value = True )
|
||||
|
||||
page_info_dict = HG.client_controller.CallBlockingToQt( HG.client_controller.gui, do_it, page_key, simple )
|
||||
page_info_dict = CG.client_controller.CallBlockingToQt( CG.client_controller.gui, do_it, page_key, simple )
|
||||
|
||||
if page_info_dict is None:
|
||||
|
||||
|
@ -4587,14 +4588,14 @@ class HydrusResourceClientAPIRestrictedManagePagesRefreshPage( HydrusResourceCli
|
|||
|
||||
def do_it( page_key ):
|
||||
|
||||
return HG.client_controller.gui.RefreshPage( page_key )
|
||||
return CG.client_controller.gui.RefreshPage( page_key )
|
||||
|
||||
|
||||
page_key = request.parsed_request_args.GetValue( 'page_key', bytes )
|
||||
|
||||
try:
|
||||
|
||||
HG.client_controller.CallBlockingToQt( HG.client_controller.gui, do_it, page_key )
|
||||
CG.client_controller.CallBlockingToQt( CG.client_controller.gui, do_it, page_key )
|
||||
|
||||
except HydrusExceptions.DataMissing as e:
|
||||
|
||||
|
@ -4700,7 +4701,7 @@ class HydrusResourceClientAPIRestrictedManagePopupsAddPopup( HydrusResourceClien
|
|||
|
||||
HandlePopupUpdate( job_status, request )
|
||||
|
||||
HG.client_controller.pub( 'message', job_status )
|
||||
CG.client_controller.pub( 'message', job_status )
|
||||
|
||||
body_dict = {
|
||||
'job_status': JobStatusToDict( job_status )
|
||||
|
@ -4718,7 +4719,7 @@ def GetJobStatusFromRequest( request: HydrusServerRequest.HydrusRequest ) -> Cli
|
|||
|
||||
job_status_key = request.parsed_request_args.GetValue( 'job_status_key', bytes )
|
||||
|
||||
job_status_queue: ClientGUIPopupMessages.JobStatusPopupQueue = HG.client_controller.job_status_popup_queue
|
||||
job_status_queue: ClientGUIPopupMessages.JobStatusPopupQueue = CG.client_controller.job_status_popup_queue
|
||||
|
||||
job_status = job_status_queue.GetJobStatus( job_status_key )
|
||||
|
||||
|
@ -4743,7 +4744,7 @@ class HydrusResourceClientAPIRestrictedManagePopupsCallUserCallable( HydrusResou
|
|||
raise HydrusExceptions.BadRequestException('This job doesn\'t have a user callable!')
|
||||
|
||||
|
||||
HG.client_controller.CallBlockingToQt( HG.client_controller.gui, user_callable )
|
||||
CG.client_controller.CallBlockingToQt( CG.client_controller.gui, user_callable )
|
||||
|
||||
response_context = HydrusServerResources.ResponseContext( 200 )
|
||||
|
||||
|
@ -4819,7 +4820,7 @@ class HydrusResourceClientAPIRestrictedManagePopupsGetPopups( HydrusResourceClie
|
|||
|
||||
def _threadDoGETJob( self, request: HydrusServerRequest.HydrusRequest ):
|
||||
|
||||
job_status_queue: ClientGUIPopupMessages.JobStatusPopupQueue = HG.client_controller.job_status_popup_queue
|
||||
job_status_queue: ClientGUIPopupMessages.JobStatusPopupQueue = CG.client_controller.job_status_popup_queue
|
||||
|
||||
only_in_view = request.parsed_request_args.GetValue( 'only_in_view', bool, default_value = False )
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ options = {}
|
|||
# Misc
|
||||
|
||||
NETWORK_VERSION = 20
|
||||
SOFTWARE_VERSION = 560
|
||||
SOFTWARE_VERSION = 561
|
||||
CLIENT_API_VERSION = 60
|
||||
|
||||
SERVER_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||
|
|
|
@ -236,16 +236,28 @@ class HydrusDB( HydrusDBBase.DBBase ):
|
|||
self._ReportOverupdatedDB( version )
|
||||
|
||||
|
||||
if version < HC.SOFTWARE_VERSION - 50:
|
||||
|
||||
raise HydrusExceptions.DBVersionException( 'Your current database version of hydrus ' + str( version ) + ' is too old for this software version ' + str( HC.SOFTWARE_VERSION ) + ' to update. Please try updating with version ' + str( version + 45 ) + ' or earlier first.' )
|
||||
|
||||
|
||||
bitrot_rows = [
|
||||
( 'client', 551, 558, 'millisecond timestamp conversion' )
|
||||
]
|
||||
|
||||
for ( bitrot_db_name, latest_affected_version, safe_update_version, reason ) in bitrot_rows:
|
||||
|
||||
if self._db_name == bitrot_db_name and version <= latest_affected_version:
|
||||
|
||||
raise HydrusExceptions.DBVersionException( f'Sorry, due to a bitrot issue ({reason}), you cannot update to this software version (v{HC.SOFTWARE_VERSION}) if your database is on v{latest_affected_version} or earlier (you are on v{version}). Please download and update to v{safe_update_version} first!' )
|
||||
|
||||
|
||||
|
||||
if version < ( HC.SOFTWARE_VERSION - 15 ):
|
||||
|
||||
self._ReportUnderupdatedDB( version )
|
||||
|
||||
|
||||
if version < HC.SOFTWARE_VERSION - 50:
|
||||
|
||||
raise Exception( 'Your current database version of hydrus ' + str( version ) + ' is too old for this software version ' + str( HC.SOFTWARE_VERSION ) + ' to update. Please try updating with version ' + str( version + 45 ) + ' or earlier first.' )
|
||||
|
||||
|
||||
self._RepairDB( version )
|
||||
|
||||
while version < HC.SOFTWARE_VERSION:
|
||||
|
|
|
@ -47,6 +47,7 @@ class DBException( HydrusException ):
|
|||
|
||||
class DBAccessException( HydrusException ): pass
|
||||
class DBCredentialsException( HydrusException ): pass
|
||||
class DBVersionException( HydrusException ): pass
|
||||
class FileMissingException( HydrusException ): pass
|
||||
class DirectoryMissingException( HydrusException ): pass
|
||||
class SerialisationException( HydrusException ): pass
|
||||
|
|
|
@ -635,8 +635,17 @@ def safe_copy2( source, dest ):
|
|||
|
||||
if FileModifiedTimeIsOk( mtime ):
|
||||
|
||||
# this overwrites on conflict without hassle
|
||||
shutil.copy2( source, dest )
|
||||
try:
|
||||
|
||||
# this overwrites on conflict without hassle
|
||||
shutil.copy2( source, dest )
|
||||
|
||||
except PermissionError:
|
||||
|
||||
HydrusData.Print( f'Failed to copy2 metadata from {source} to {dest}! mtime was {HydrusTime.TimestampToPrettyTime( mtime )}' )
|
||||
|
||||
shutil.copy( source, dest )
|
||||
|
||||
|
||||
else:
|
||||
|
||||
|
|
|
@ -281,16 +281,24 @@ def NonFailingUnicodeDecode( data, encoding ):
|
|||
|
||||
return ( text, encoding )
|
||||
|
||||
|
||||
def RemoveNewlines( text: str ) -> str:
|
||||
|
||||
text = ''.join( text.splitlines() )
|
||||
good_lines = [ l.strip() for l in text.splitlines() ]
|
||||
|
||||
good_lines = [ l for l in good_lines if l != '' ]
|
||||
|
||||
# I really want to make this ' '.join(), but I'm sure that would break some old parsers
|
||||
text = ''.join( good_lines )
|
||||
|
||||
return text
|
||||
|
||||
|
||||
def SortStringsIgnoringCase( list_of_strings ):
|
||||
|
||||
list_of_strings.sort( key = lambda s: s.lower() )
|
||||
|
||||
|
||||
def StripIOInputLine( t ):
|
||||
|
||||
t = re_leading_byte_order_mark.sub( '', t )
|
||||
|
|
|
@ -16,6 +16,7 @@ from hydrus.core import HydrusConstants as HC
|
|||
from hydrus.core import HydrusData
|
||||
from hydrus.core import HydrusExceptions
|
||||
from hydrus.core import HydrusGlobals as HG
|
||||
from hydrus.core import HydrusPaths
|
||||
from hydrus.core import HydrusTags
|
||||
from hydrus.core import HydrusText
|
||||
from hydrus.core import HydrusTime
|
||||
|
@ -5988,7 +5989,7 @@ class TestClientAPI( unittest.TestCase ):
|
|||
|
||||
file_path = HG.test_controller.client_files_manager.GetFilePath( hash, HC.IMAGE_PNG, check_file_exists = False )
|
||||
|
||||
shutil.copy2( path, file_path )
|
||||
HydrusPaths.safe_copy2( path, file_path )
|
||||
|
||||
thumb_hash = b'\x17\xde\xd6\xee\x1b\xfa\x002\xbdj\xc0w\x92\xce5\xf0\x12~\xfe\x915\xb3\xb3tA\xac\x90F\x95\xc2T\xc5'
|
||||
|
||||
|
@ -5996,7 +5997,7 @@ class TestClientAPI( unittest.TestCase ):
|
|||
|
||||
thumb_path = HG.test_controller.client_files_manager._GenerateExpectedThumbnailPath( hash )
|
||||
|
||||
shutil.copy2( path, thumb_path )
|
||||
HydrusPaths.safe_copy2( path, thumb_path )
|
||||
|
||||
api_permissions = set_up_permissions[ 'search_green_files' ]
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ from hydrus.client import ClientConstants as CC
|
|||
from hydrus.client import ClientDefaults
|
||||
from hydrus.client import ClientFiles
|
||||
from hydrus.client import ClientFilesPhysical
|
||||
from hydrus.client import ClientGlobals as CG
|
||||
from hydrus.client import ClientOptions
|
||||
from hydrus.client import ClientManagers
|
||||
from hydrus.client import ClientServices
|
||||
|
@ -195,6 +196,8 @@ class Controller( object ):
|
|||
HG.server_controller = self
|
||||
HG.test_controller = self
|
||||
|
||||
CG.client_controller = self
|
||||
|
||||
self.db = self
|
||||
self.gui = self
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 3.1 KiB |
Loading…
Reference in New Issue