Version 214
This commit is contained in:
parent
7e5baabffb
commit
2b1f40cf2a
11
README.md
11
README.md
|
@ -1,14 +1,15 @@
|
||||||
## Hydrus Image Tagging Network (Client and Server)
|
## Hydrus Network (Client and Server)
|
||||||
|
|
||||||
The hydrus network client is an application written for anon and other internet-fluent media nerds who have large image/swf collections. It browses with tags instead of folders, a little like a *booru on your desktop. Tags and files can be anonymously shared through custom servers that any user may run. Everything is free, and the source code is included with the release. It is developed for Windows, but fairly functional builds for Linux and OS X are released at the same time.
|
The hydrus network client is an application written for Anon and other internet-fluent media nerds who have large image/swf/webm collections. It browses with tags instead of folders, a little like a *booru on your desktop. Tags and files can be anonymously shared through custom servers that any user may run. Everything is free, and the source code is included with the release. It is developed for Windows, but fairly functional builds for Linux and OS X are released at the same time.
|
||||||
|
|
||||||
The software is constantly being improved. I put out a new release every Wednesday by 8pm Eastern.
|
I am continually working on the software and try to put out a new release every Wednesday by 8pm Eastern.
|
||||||
|
|
||||||
This github repository is currently a weekly sync with my home dev environment, where I work on hydrus by myself. Feel free to fork, but please don't make pull requests at this time.
|
This github repository is currently a weekly sync with my home dev environment, where I work on hydrus by myself. Feel free to fork, but please don't make pull requests at this time. I am also not active on Github, so if you have feedback of any sort, please email me, post on my 8chan board, or message me on tumblr or twitter.
|
||||||
|
|
||||||
The program can do quite a lot! Please check out the help inside the release or [here](http://hydrusnetwork.github.io/hydrus/help).
|
The client can do quite a lot! Please check out the help inside the release or [here](http://hydrusnetwork.github.io/hydrus/help), which includes a comprehensive getting started guide.
|
||||||
|
|
||||||
* [homepage](http://hydrusnetwork.github.io/hydrus/)
|
* [homepage](http://hydrusnetwork.github.io/hydrus/)
|
||||||
|
* [email](mailto:hydrus.admin@gmail.com)
|
||||||
* [8chan board](https://8ch.net/hydrus/index.html)
|
* [8chan board](https://8ch.net/hydrus/index.html)
|
||||||
* [twitter](https://twitter.com/hydrusnetwork)
|
* [twitter](https://twitter.com/hydrusnetwork)
|
||||||
* [tumblr](http://hydrus.tumblr.com/)
|
* [tumblr](http://hydrus.tumblr.com/)
|
||||||
|
|
|
@ -8,6 +8,36 @@
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h3>changelog</h3>
|
<h3>changelog</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li><h3>version 214</h3></li>
|
||||||
|
<ul>
|
||||||
|
<li>wrote a new resizing dialog 'edit' class for simple resizing dialogs</li>
|
||||||
|
<li>added comprehensive frame size and position options for the new system to the gui options panel</li>
|
||||||
|
<li>moved review services frame to the new sizing system</li>
|
||||||
|
<li>windows that initialise maximised will correctly return to their last remembered size and position on a restore event</li>
|
||||||
|
<li>maximising a window by dragging it to the top edge of the screen should remember last position as the initial drag start position more reliably</li>
|
||||||
|
<li>positioning code is a little safer</li>
|
||||||
|
<li>fixed some missing recalculation of best/min size for wx.notebooks after page change</li>
|
||||||
|
<li>fixed missing recalculation of scrolledpanel's virtualsize after child wx.notebook's page change</li>
|
||||||
|
<li>fixed bad parentage for file import status frames</li>
|
||||||
|
<li>hid file import status button in manage import folders and subscriptions dialogs for non-Windows, as this is very broken, and the parentage fix wasn't enough</li>
|
||||||
|
<li>improved fuzzy padding on size calculations</li>
|
||||||
|
<li>refactored and cleaned and harmonised a bunch of the new window resizing code</li>
|
||||||
|
<li>suggested tags - favourites tag entry in options is now a live autocomplete dropdown</li>
|
||||||
|
<li>cleaned suggested tags - favourites layout in options</li>
|
||||||
|
<li>suggested tags listbox now sets its width to exactly fit its tags</li>
|
||||||
|
<li>improved workflow logic of removing/petitioning siblings and parents (shouldn't get stuck in loops as much now)</li>
|
||||||
|
<li>tag listboxes will update when tag siblings change</li>
|
||||||
|
<li>the 'auto-replace siblings' state on manage tags will no longer incorrectly apply to removal actions</li>
|
||||||
|
<li>import status caches now display errors in a more straightforward way</li>
|
||||||
|
<li>errors sent to import status caches are now also printed to the log</li>
|
||||||
|
<li>simplified how database exceptions are caught and displayed</li>
|
||||||
|
<li>database exceptions now preserve the original exception type</li>
|
||||||
|
<li>fixed db-side traceback line spacing in database exceptions</li>
|
||||||
|
<li>improved general database exception rendering</li>
|
||||||
|
<li>fixed imports for videos with negative start time</li>
|
||||||
|
<li>deleting videos from the trash that are currently rendering should be more reliable</li>
|
||||||
|
<li>crash.log now goes to the db dir, unless that isn't determined yet or is unwritable, in which case the traceback goes to console</li>
|
||||||
|
</ul>
|
||||||
<li><h3>version 213</h3></li>
|
<li><h3>version 213</h3></li>
|
||||||
<ul>
|
<ul>
|
||||||
<li>created a new tag listbox for the new suggested tags control</li>
|
<li>created a new tag listbox for the new suggested tags control</li>
|
||||||
|
|
|
@ -2162,7 +2162,7 @@ class TagSiblingsManager( object ):
|
||||||
|
|
||||||
self._lock = threading.Lock()
|
self._lock = threading.Lock()
|
||||||
|
|
||||||
self._controller.sub( self, 'RefreshSiblings', 'notify_new_siblings' )
|
self._controller.sub( self, 'RefreshSiblings', 'notify_new_siblings_data' )
|
||||||
|
|
||||||
|
|
||||||
def _CollapseTags( self, tags ):
|
def _CollapseTags( self, tags ):
|
||||||
|
|
|
@ -10,6 +10,12 @@ import wx.lib.newevent
|
||||||
|
|
||||||
ID_NULL = wx.NewId()
|
ID_NULL = wx.NewId()
|
||||||
|
|
||||||
|
# timers
|
||||||
|
|
||||||
|
ID_TIMER_UPDATES = wx.NewId()
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
CAN_HIDE_MOUSE = True
|
CAN_HIDE_MOUSE = True
|
||||||
|
|
||||||
# Hue is generally 200, Sat and Lum changes based on need
|
# Hue is generally 200, Sat and Lum changes based on need
|
||||||
|
|
|
@ -2295,7 +2295,8 @@ class DB( HydrusDB.HydrusDB ):
|
||||||
|
|
||||||
|
|
||||||
self.pub_after_commit( 'notify_new_pending' )
|
self.pub_after_commit( 'notify_new_pending' )
|
||||||
self.pub_after_commit( 'notify_new_siblings' )
|
self.pub_after_commit( 'notify_new_siblings_data' )
|
||||||
|
self.pub_after_commit( 'notify_new_siblings_gui' )
|
||||||
self.pub_after_commit( 'notify_new_parents' )
|
self.pub_after_commit( 'notify_new_parents' )
|
||||||
|
|
||||||
self.pub_service_updates_after_commit( { service_key : [ HydrusData.ServiceUpdate( HC.SERVICE_UPDATE_DELETE_PENDING ) ] } )
|
self.pub_service_updates_after_commit( { service_key : [ HydrusData.ServiceUpdate( HC.SERVICE_UPDATE_DELETE_PENDING ) ] } )
|
||||||
|
@ -5175,14 +5176,20 @@ class DB( HydrusDB.HydrusDB ):
|
||||||
HydrusData.ShowText( 'The client is running out of memory! Restart it ASAP!' )
|
HydrusData.ShowText( 'The client is running out of memory! Restart it ASAP!' )
|
||||||
|
|
||||||
|
|
||||||
( etype, value, tb ) = sys.exc_info()
|
if job.IsSynchronous():
|
||||||
|
|
||||||
db_traceback = os.linesep.join( traceback.format_exception( etype, value, tb ) )
|
db_traceback = 'Database ' + traceback.format_exc()
|
||||||
|
|
||||||
new_e = HydrusExceptions.DBException( HydrusData.ToUnicode( e ), 'Unknown Caller, probably GUI.', db_traceback )
|
first_line = HydrusData.ToUnicode( type( e ).__name__ ) + ': ' + HydrusData.ToUnicode( e )
|
||||||
|
|
||||||
|
new_e = HydrusExceptions.DBException( first_line, db_traceback )
|
||||||
|
|
||||||
|
job.PutResult( new_e )
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
HydrusData.ShowException( e )
|
||||||
|
|
||||||
if job.IsSynchronous(): job.PutResult( new_e )
|
|
||||||
else: HydrusData.ShowException( new_e )
|
|
||||||
|
|
||||||
|
|
||||||
def _ProcessContentUpdatePackage( self, service_key, content_update_package, job_key ):
|
def _ProcessContentUpdatePackage( self, service_key, content_update_package, job_key ):
|
||||||
|
@ -5805,7 +5812,8 @@ class DB( HydrusDB.HydrusDB ):
|
||||||
if notify_new_pending: self.pub_after_commit( 'notify_new_pending' )
|
if notify_new_pending: self.pub_after_commit( 'notify_new_pending' )
|
||||||
if notify_new_siblings:
|
if notify_new_siblings:
|
||||||
|
|
||||||
self.pub_after_commit( 'notify_new_siblings' )
|
self.pub_after_commit( 'notify_new_siblings_data' )
|
||||||
|
self.pub_after_commit( 'notify_new_siblings_gui' )
|
||||||
self.pub_after_commit( 'notify_new_parents' )
|
self.pub_after_commit( 'notify_new_parents' )
|
||||||
|
|
||||||
elif notify_new_parents:
|
elif notify_new_parents:
|
||||||
|
@ -7753,11 +7761,13 @@ class DB( HydrusDB.HydrusDB ):
|
||||||
|
|
||||||
prefixes_to_locations = dict( self._c.execute( 'SELECT prefix, location FROM client_files_locations;' ).fetchall() )
|
prefixes_to_locations = dict( self._c.execute( 'SELECT prefix, location FROM client_files_locations;' ).fetchall() )
|
||||||
|
|
||||||
|
( total_to_do, ) = self._c.execute( 'SELECT COUNT( * ) FROM files_info WHERE mime IN ( ?, ? );', ( HC.IMAGE_PNG, HC.IMAGE_GIF ) ).fetchone()
|
||||||
|
|
||||||
for ( i, ( hash, mime ) ) in enumerate( self._c.execute( 'SELECT hash, mime FROM files_info, hashes USING ( hash_id ) WHERE mime IN ( ?, ? );', ( HC.IMAGE_PNG, HC.IMAGE_GIF ) ) ):
|
for ( i, ( hash, mime ) ) in enumerate( self._c.execute( 'SELECT hash, mime FROM files_info, hashes USING ( hash_id ) WHERE mime IN ( ?, ? );', ( HC.IMAGE_PNG, HC.IMAGE_GIF ) ) ):
|
||||||
|
|
||||||
if ( i + 1 ) % 50 == 0:
|
if ( i + 1 ) % 50 == 0:
|
||||||
|
|
||||||
self._controller.pub( 'splash_set_status_text', 'regenerating thumbnails: ' + HydrusData.ConvertIntToPrettyString( i + 1 ) )
|
self._controller.pub( 'splash_set_status_text', 'regenerating thumbnails: ' + HydrusData.ConvertValueRangeToPrettyString( i + 1, total_to_do ) )
|
||||||
|
|
||||||
|
|
||||||
hash_hex = hash.encode( 'hex' )
|
hash_hex = hash.encode( 'hex' )
|
||||||
|
|
|
@ -39,27 +39,18 @@ def CatchExceptionClient( etype, value, tb ):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
|
trace_list = traceback.format_tb( tb )
|
||||||
|
|
||||||
|
trace = ''.join( trace_list )
|
||||||
|
|
||||||
job_key = ClientThreading.JobKey()
|
job_key = ClientThreading.JobKey()
|
||||||
|
|
||||||
if etype == HydrusExceptions.ShutdownException:
|
if etype == HydrusExceptions.ShutdownException:
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
elif etype == HydrusExceptions.DBException:
|
|
||||||
|
|
||||||
( text, caller_traceback, db_traceback ) = value
|
|
||||||
|
|
||||||
job_key.SetVariable( 'popup_title', 'Database Error!' )
|
|
||||||
job_key.SetVariable( 'popup_text_1', text )
|
|
||||||
job_key.SetVariable( 'popup_caller_traceback', caller_traceback )
|
|
||||||
job_key.SetVariable( 'popup_db_traceback', db_traceback )
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
trace_list = traceback.format_tb( tb )
|
|
||||||
|
|
||||||
trace = ''.join( trace_list )
|
|
||||||
|
|
||||||
if etype == wx.PyDeadObjectError:
|
if etype == wx.PyDeadObjectError:
|
||||||
|
|
||||||
HydrusData.Print( 'Got a PyDeadObjectError, which can probably be ignored, but here it is anyway:' )
|
HydrusData.Print( 'Got a PyDeadObjectError, which can probably be ignored, but here it is anyway:' )
|
||||||
|
@ -69,9 +60,11 @@ def CatchExceptionClient( etype, value, tb ):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
first_line = HydrusData.ToUnicode( value ).split( os.linesep )[0]
|
||||||
|
|
||||||
try: job_key.SetVariable( 'popup_title', HydrusData.ToUnicode( etype.__name__ ) )
|
try: job_key.SetVariable( 'popup_title', HydrusData.ToUnicode( etype.__name__ ) )
|
||||||
except: job_key.SetVariable( 'popup_title', HydrusData.ToUnicode( etype ) )
|
except: job_key.SetVariable( 'popup_title', HydrusData.ToUnicode( etype ) )
|
||||||
job_key.SetVariable( 'popup_text_1', HydrusData.ToUnicode( value ) )
|
job_key.SetVariable( 'popup_text_1', first_line )
|
||||||
job_key.SetVariable( 'popup_traceback', trace )
|
job_key.SetVariable( 'popup_traceback', trace )
|
||||||
|
|
||||||
|
|
||||||
|
@ -258,34 +251,28 @@ def GetMediasTagCount( pool, tag_service_key = CC.COMBINED_TAG_SERVICE_KEY, coll
|
||||||
|
|
||||||
def ShowExceptionClient( e ):
|
def ShowExceptionClient( e ):
|
||||||
|
|
||||||
|
( etype, value, tb ) = sys.exc_info()
|
||||||
|
|
||||||
|
if etype is None:
|
||||||
|
|
||||||
|
etype = type( e )
|
||||||
|
value = HydrusData.ToUnicode( e )
|
||||||
|
|
||||||
|
trace = ''.join( traceback.format_stack() )
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
trace = ''.join( traceback.format_exception( etype, value, tb ) )
|
||||||
|
|
||||||
|
|
||||||
job_key = ClientThreading.JobKey()
|
job_key = ClientThreading.JobKey()
|
||||||
|
|
||||||
if isinstance( e, HydrusExceptions.ShutdownException ):
|
if isinstance( e, HydrusExceptions.ShutdownException ):
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
elif isinstance( e, HydrusExceptions.DBException ):
|
|
||||||
|
|
||||||
( text, caller_traceback, db_traceback ) = e.args
|
|
||||||
|
|
||||||
job_key.SetVariable( 'popup_title', 'Database Error!' )
|
|
||||||
job_key.SetVariable( 'popup_text_1', text )
|
|
||||||
job_key.SetVariable( 'popup_caller_traceback', caller_traceback )
|
|
||||||
job_key.SetVariable( 'popup_db_traceback', db_traceback )
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
( etype, value, tb ) = sys.exc_info()
|
|
||||||
|
|
||||||
if etype is None:
|
|
||||||
|
|
||||||
etype = type( e )
|
|
||||||
value = HydrusData.ToUnicode( e )
|
|
||||||
|
|
||||||
trace = ''.join( traceback.format_stack() )
|
|
||||||
|
|
||||||
else: trace = ''.join( traceback.format_exception( etype, value, tb ) )
|
|
||||||
|
|
||||||
if etype == wx.PyDeadObjectError:
|
if etype == wx.PyDeadObjectError:
|
||||||
|
|
||||||
HydrusData.Print( 'Got a PyDeadObjectError, which can probably be ignored, but here it is anyway:' )
|
HydrusData.Print( 'Got a PyDeadObjectError, which can probably be ignored, but here it is anyway:' )
|
||||||
|
@ -299,7 +286,10 @@ def ShowExceptionClient( e ):
|
||||||
else: title = HydrusData.ToUnicode( etype )
|
else: title = HydrusData.ToUnicode( etype )
|
||||||
|
|
||||||
job_key.SetVariable( 'popup_title', title )
|
job_key.SetVariable( 'popup_title', title )
|
||||||
job_key.SetVariable( 'popup_text_1', HydrusData.ToUnicode( value ) )
|
|
||||||
|
first_line = HydrusData.ToUnicode( value ).split( os.linesep )[0]
|
||||||
|
|
||||||
|
job_key.SetVariable( 'popup_text_1', first_line )
|
||||||
job_key.SetVariable( 'popup_traceback', trace )
|
job_key.SetVariable( 'popup_traceback', trace )
|
||||||
|
|
||||||
|
|
||||||
|
@ -457,6 +447,8 @@ class ClientOptions( HydrusSerialisable.SerialisableBase ):
|
||||||
self._dictionary[ 'frame_locations' ][ 'manage_tags_dialog' ] = ( False, False, None, None, ( -1, 1 ), 'topleft', False, False )
|
self._dictionary[ 'frame_locations' ][ 'manage_tags_dialog' ] = ( False, False, None, None, ( -1, 1 ), 'topleft', False, False )
|
||||||
self._dictionary[ 'frame_locations' ][ 'manage_tags_frame' ] = ( False, False, None, None, ( -1, 1 ), 'topleft', False, False )
|
self._dictionary[ 'frame_locations' ][ 'manage_tags_frame' ] = ( False, False, None, None, ( -1, 1 ), 'topleft', False, False )
|
||||||
self._dictionary[ 'frame_locations' ][ 'media_viewer' ] = ( True, True, ( 640, 480 ), ( 70, 70 ), ( -1, -1 ), 'topleft', True, True )
|
self._dictionary[ 'frame_locations' ][ 'media_viewer' ] = ( True, True, ( 640, 480 ), ( 70, 70 ), ( -1, -1 ), 'topleft', True, True )
|
||||||
|
self._dictionary[ 'frame_locations' ][ 'regular_dialog' ] = ( False, False, None, None, ( -1, -1 ), 'topleft', False, False )
|
||||||
|
self._dictionary[ 'frame_locations' ][ 'review_services' ] = ( False, True, None, None, ( -1, -1 ), 'topleft', False, False )
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
|
@ -621,6 +613,11 @@ class ClientOptions( HydrusSerialisable.SerialisableBase ):
|
||||||
return self._dictionary[ 'frame_locations' ][ frame_key ]
|
return self._dictionary[ 'frame_locations' ][ frame_key ]
|
||||||
|
|
||||||
|
|
||||||
|
def GetFrameLocations( self ):
|
||||||
|
|
||||||
|
return self._dictionary[ 'frame_locations' ].items()
|
||||||
|
|
||||||
|
|
||||||
def GetNoneableInteger( self, name ):
|
def GetNoneableInteger( self, name ):
|
||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
@ -1875,7 +1872,8 @@ class ServiceRepository( ServiceRestricted ):
|
||||||
finally:
|
finally:
|
||||||
|
|
||||||
HydrusGlobals.client_controller.pub( 'notify_new_pending' )
|
HydrusGlobals.client_controller.pub( 'notify_new_pending' )
|
||||||
HydrusGlobals.client_controller.pub( 'notify_new_siblings' )
|
HydrusGlobals.client_controller.pub( 'notify_new_siblings_data' )
|
||||||
|
HydrusGlobals.client_controller.pub( 'notify_new_siblings_gui' )
|
||||||
HydrusGlobals.client_controller.pub( 'notify_new_parents' )
|
HydrusGlobals.client_controller.pub( 'notify_new_parents' )
|
||||||
|
|
||||||
|
|
||||||
|
|
1076
include/ClientGUI.py
1076
include/ClientGUI.py
File diff suppressed because it is too large
Load Diff
|
@ -8,6 +8,7 @@ import ClientGUIDialogs
|
||||||
import ClientGUIDialogsManage
|
import ClientGUIDialogsManage
|
||||||
import ClientGUIHoverFrames
|
import ClientGUIHoverFrames
|
||||||
import ClientGUIPanels
|
import ClientGUIPanels
|
||||||
|
import ClientGUITopLevelWindows
|
||||||
import ClientMedia
|
import ClientMedia
|
||||||
import ClientRatings
|
import ClientRatings
|
||||||
import collections
|
import collections
|
||||||
|
@ -898,7 +899,7 @@ class Canvas( wx.Window ):
|
||||||
title = 'manage tags'
|
title = 'manage tags'
|
||||||
frame_key = 'manage_tags_frame'
|
frame_key = 'manage_tags_frame'
|
||||||
|
|
||||||
manage_tags = ClientGUICommon.FrameThatResizesAndTakesPanel( self, title, frame_key )
|
manage_tags = ClientGUITopLevelWindows.FrameThatTakesScrollablePanel( self, title, frame_key )
|
||||||
|
|
||||||
panel = ClientGUIPanels.ManageTagsPanel( manage_tags, self._file_service_key, ( self._current_display_media, ), immediate_commit = True, canvas_key = self._canvas_key )
|
panel = ClientGUIPanels.ManageTagsPanel( manage_tags, self._file_service_key, ( self._current_display_media, ), immediate_commit = True, canvas_key = self._canvas_key )
|
||||||
|
|
||||||
|
@ -1697,11 +1698,11 @@ class CanvasPanel( Canvas ):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class CanvasFrame( ClientGUICommon.FrameThatResizes ):
|
class CanvasFrame( ClientGUITopLevelWindows.FrameThatResizes ):
|
||||||
|
|
||||||
def __init__( self, parent ):
|
def __init__( self, parent ):
|
||||||
|
|
||||||
ClientGUICommon.FrameThatResizes.__init__( self, parent, 'hydrus client media viewer', 'media_viewer', float_on_parent = False )
|
ClientGUITopLevelWindows.FrameThatResizes.__init__( self, parent, 'hydrus client media viewer', 'media_viewer', float_on_parent = False )
|
||||||
|
|
||||||
|
|
||||||
def Close( self ):
|
def Close( self ):
|
||||||
|
@ -1736,7 +1737,7 @@ class CanvasFrame( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
self.SetSizer( vbox )
|
self.SetSizer( vbox )
|
||||||
|
|
||||||
self._SetSizeAndPosition( self._frame_key )
|
ClientGUITopLevelWindows.SetTLWSizeAndPosition( self, self._frame_key )
|
||||||
|
|
||||||
self.Show( True )
|
self.Show( True )
|
||||||
|
|
||||||
|
|
|
@ -1800,370 +1800,6 @@ class FitResistantStaticText( wx.StaticText ):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Frame( wx.Frame ):
|
|
||||||
|
|
||||||
def __init__( self, parent, title, float_on_parent = True ):
|
|
||||||
|
|
||||||
HydrusGlobals.client_controller.ResetIdleTimer()
|
|
||||||
|
|
||||||
if parent is None:
|
|
||||||
|
|
||||||
pos = wx.DefaultPosition
|
|
||||||
style = wx.DEFAULT_FRAME_STYLE
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
if isinstance( parent, wx.TopLevelWindow ):
|
|
||||||
|
|
||||||
parent_tlp = parent
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
parent_tlp = parent.GetTopLevelParent()
|
|
||||||
|
|
||||||
|
|
||||||
( tlp_x, tlp_y ) = parent_tlp.GetPositionTuple()
|
|
||||||
|
|
||||||
pos = ( tlp_x + 50, tlp_y + 50 )
|
|
||||||
|
|
||||||
if float_on_parent:
|
|
||||||
|
|
||||||
style = wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
style = wx.DEFAULT_FRAME_STYLE
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
wx.Frame.__init__( self, parent, title = title, pos = pos, style = style )
|
|
||||||
|
|
||||||
self._new_options = HydrusGlobals.client_controller.GetNewOptions()
|
|
||||||
|
|
||||||
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
|
|
||||||
|
|
||||||
self.SetIcon( wx.Icon( os.path.join( HC.STATIC_DIR, 'hydrus.ico' ), wx.BITMAP_TYPE_ICO ) )
|
|
||||||
|
|
||||||
|
|
||||||
def _ExpandSizeIfPossible( self, frame_key, desired_size_delta ):
|
|
||||||
|
|
||||||
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = self._new_options.GetFrameLocation( frame_key )
|
|
||||||
|
|
||||||
parent = self.GetParent()
|
|
||||||
|
|
||||||
if not self.IsMaximized() and not self.IsFullScreen():
|
|
||||||
|
|
||||||
( current_width, current_height ) = self.GetSize()
|
|
||||||
|
|
||||||
( desired_delta_width, desired_delta_height ) = desired_size_delta
|
|
||||||
|
|
||||||
min_width = current_width + desired_delta_width
|
|
||||||
min_height = current_height + desired_delta_height
|
|
||||||
|
|
||||||
if parent is None:
|
|
||||||
|
|
||||||
width = min_width + 20
|
|
||||||
height = min_height + 20
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
( parent_window_width, parent_window_height ) = self.GetParent().GetTopLevelParent().GetSize()
|
|
||||||
|
|
||||||
max_width = parent_window_width - 100
|
|
||||||
max_height = parent_window_height - 100
|
|
||||||
|
|
||||||
( width_gravity, height_gravity ) = default_gravity
|
|
||||||
|
|
||||||
if width_gravity == -1:
|
|
||||||
|
|
||||||
width = min_width
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
width = int( width_gravity * max_width )
|
|
||||||
|
|
||||||
|
|
||||||
if height_gravity == -1:
|
|
||||||
|
|
||||||
height = min_height
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
height = int( height_gravity * max_height )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if width > current_width or height > current_height:
|
|
||||||
|
|
||||||
self.SetSize( ( width, height ) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _GetSafePosition( self, position ):
|
|
||||||
|
|
||||||
( p_x, p_y ) = position
|
|
||||||
|
|
||||||
# some window managers size the windows just off screen to cut off borders
|
|
||||||
( test_x, test_y ) = ( p_x + 20, p_y + 20 )
|
|
||||||
|
|
||||||
display_index = wx.Display.GetFromPoint( ( test_x, test_y ) )
|
|
||||||
|
|
||||||
if display_index == wx.NOT_FOUND:
|
|
||||||
|
|
||||||
return wx.DefaultPosition
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
display = wx.Display( display_index )
|
|
||||||
|
|
||||||
geometry = display.GetGeometry()
|
|
||||||
|
|
||||||
x_bad = test_x < geometry.x or test_x > geometry.x + geometry.width
|
|
||||||
y_bad = test_y < geometry.y or test_y > geometry.y + geometry.height
|
|
||||||
|
|
||||||
if x_bad or y_bad:
|
|
||||||
|
|
||||||
return wx.DefaultPosition
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
return position
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _SaveSizeAndPosition( self, frame_key ):
|
|
||||||
|
|
||||||
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = self._new_options.GetFrameLocation( frame_key )
|
|
||||||
|
|
||||||
maximised = self.IsMaximized()
|
|
||||||
fullscreen = self.IsFullScreen()
|
|
||||||
|
|
||||||
if not ( maximised or fullscreen ):
|
|
||||||
|
|
||||||
# when dragging window up to be maximised, reported position is sometimes a bit dodgy
|
|
||||||
# so, filter out the invalid answers
|
|
||||||
|
|
||||||
if self._GetSafePosition( self.GetPositionTuple() ) != wx.DefaultPosition:
|
|
||||||
|
|
||||||
last_size = self.GetSizeTuple()
|
|
||||||
last_position = self._GetSafePosition( self.GetPositionTuple() )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self._new_options.SetFrameLocation( frame_key, remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen )
|
|
||||||
|
|
||||||
|
|
||||||
def _SetSizeAndPosition( self, frame_key ):
|
|
||||||
|
|
||||||
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = self._new_options.GetFrameLocation( frame_key )
|
|
||||||
|
|
||||||
parent = self.GetParent()
|
|
||||||
|
|
||||||
if remember_size and last_size is not None:
|
|
||||||
|
|
||||||
( width, height ) = last_size
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
( min_width, min_height ) = self.GetEffectiveMinSize()
|
|
||||||
|
|
||||||
min_width += 30
|
|
||||||
min_height += 30
|
|
||||||
|
|
||||||
if parent is None:
|
|
||||||
|
|
||||||
width = min_width
|
|
||||||
height = min_height
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
( parent_window_width, parent_window_height ) = self.GetParent().GetTopLevelParent().GetSize()
|
|
||||||
|
|
||||||
max_width = parent_window_width - 100
|
|
||||||
max_height = parent_window_height - 100
|
|
||||||
|
|
||||||
( width_gravity, height_gravity ) = default_gravity
|
|
||||||
|
|
||||||
if width_gravity == -1:
|
|
||||||
|
|
||||||
width = min_width
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
width = int( width_gravity * max_width )
|
|
||||||
|
|
||||||
|
|
||||||
if height_gravity == -1:
|
|
||||||
|
|
||||||
height = min_height
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
height = int( height_gravity * max_height )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.SetInitialSize( ( width, height ) )
|
|
||||||
|
|
||||||
if maximised:
|
|
||||||
|
|
||||||
self.Maximize()
|
|
||||||
|
|
||||||
|
|
||||||
if fullscreen:
|
|
||||||
|
|
||||||
wx.CallAfter( self.ShowFullScreen, True, wx.FULLSCREEN_ALL )
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
|
|
||||||
pos = None
|
|
||||||
|
|
||||||
if remember_position and last_position is not None:
|
|
||||||
|
|
||||||
pos = last_position
|
|
||||||
|
|
||||||
elif default_position == 'topleft' and parent is not None:
|
|
||||||
|
|
||||||
if isinstance( parent, wx.TopLevelWindow ):
|
|
||||||
|
|
||||||
parent_tlp = parent
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
parent_tlp = parent.GetTopLevelParent()
|
|
||||||
|
|
||||||
|
|
||||||
( pos_x, pos_y ) = parent_tlp.GetPositionTuple()
|
|
||||||
|
|
||||||
pos = ( pos_x + 50, pos_y + 50 )
|
|
||||||
|
|
||||||
elif default_position == 'center':
|
|
||||||
|
|
||||||
wx.CallAfter( self.Center )
|
|
||||||
|
|
||||||
|
|
||||||
if pos is not None:
|
|
||||||
|
|
||||||
pos = self._GetSafePosition( pos )
|
|
||||||
|
|
||||||
self.SetPosition( pos )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def SetInitialSize( self, ( width, height ) ):
|
|
||||||
|
|
||||||
( display_width, display_height ) = wx.GetDisplaySize()
|
|
||||||
|
|
||||||
width = min( display_width, width )
|
|
||||||
height = min( display_height, height )
|
|
||||||
|
|
||||||
wx.Frame.SetInitialSize( self, ( width, height ) )
|
|
||||||
|
|
||||||
min_width = min( 240, width )
|
|
||||||
min_height = min( 180, height )
|
|
||||||
|
|
||||||
self.SetMinSize( ( min_width, min_height ) )
|
|
||||||
|
|
||||||
|
|
||||||
class FrameThatResizes( Frame ):
|
|
||||||
|
|
||||||
def __init__( self, parent, title, frame_key, float_on_parent = True ):
|
|
||||||
|
|
||||||
self._frame_key = frame_key
|
|
||||||
|
|
||||||
Frame.__init__( self, parent, title, float_on_parent )
|
|
||||||
|
|
||||||
self.Bind( wx.EVT_SIZE, self.EventSizeInfoChanged )
|
|
||||||
self.Bind( wx.EVT_MOVE, self.EventSizeInfoChanged )
|
|
||||||
self.Bind( wx.EVT_CLOSE, self.EventSizeInfoChanged )
|
|
||||||
self.Bind( wx.EVT_MAXIMIZE, self.EventSizeInfoChanged )
|
|
||||||
|
|
||||||
|
|
||||||
def EventSizeInfoChanged( self, event ):
|
|
||||||
|
|
||||||
self._SaveSizeAndPosition( self._frame_key )
|
|
||||||
|
|
||||||
event.Skip()
|
|
||||||
|
|
||||||
|
|
||||||
class FrameThatResizesAndTakesPanel( FrameThatResizes ):
|
|
||||||
|
|
||||||
def __init__( self, parent, title, frame_key, float_on_parent = True ):
|
|
||||||
|
|
||||||
self._panel = None
|
|
||||||
|
|
||||||
FrameThatResizes.__init__( self, parent, title, frame_key, float_on_parent )
|
|
||||||
|
|
||||||
self._ok = wx.Button( self, label = 'close' )
|
|
||||||
self._ok.Bind( wx.EVT_BUTTON, self.EventCloseButton )
|
|
||||||
|
|
||||||
self.Bind( wx.EVT_MENU, self.EventMenu )
|
|
||||||
self.Bind( CC.EVT_SIZE_CHANGED, self.EventChildSizeChanged )
|
|
||||||
|
|
||||||
|
|
||||||
def EventMenu( self, event ):
|
|
||||||
|
|
||||||
action = ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetAction( event.GetId() )
|
|
||||||
|
|
||||||
if action is not None:
|
|
||||||
|
|
||||||
( command, data ) = action
|
|
||||||
|
|
||||||
if command == 'ok':
|
|
||||||
|
|
||||||
self.Close()
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
event.Skip()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def EventCloseButton( self, event ):
|
|
||||||
|
|
||||||
self.Close()
|
|
||||||
|
|
||||||
|
|
||||||
def EventChildSizeChanged( self, event ):
|
|
||||||
|
|
||||||
if self._panel is not None:
|
|
||||||
|
|
||||||
( current_panel_width, current_panel_height ) = self._panel.GetSize()
|
|
||||||
( desired_panel_width, desired_panel_height ) = self._panel.GetVirtualSize()
|
|
||||||
|
|
||||||
desired_delta_width = max( 0, desired_panel_width - current_panel_width )
|
|
||||||
desired_delta_height = max( 0, desired_panel_height - current_panel_height )
|
|
||||||
|
|
||||||
if desired_delta_width > 0 or desired_delta_height > 0:
|
|
||||||
|
|
||||||
self._ExpandSizeIfPossible( self._frame_key, ( desired_delta_width, desired_delta_height ) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def SetPanel( self, panel ):
|
|
||||||
|
|
||||||
self._panel = panel
|
|
||||||
|
|
||||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
|
||||||
|
|
||||||
vbox.AddF( self._panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
||||||
vbox.AddF( self._ok, CC.FLAGS_LONE_BUTTON )
|
|
||||||
|
|
||||||
self.SetSizer( vbox )
|
|
||||||
|
|
||||||
self._SetSizeAndPosition( self._frame_key )
|
|
||||||
|
|
||||||
self.Show( True )
|
|
||||||
|
|
||||||
self._panel.SetupScrolling()
|
|
||||||
|
|
||||||
|
|
||||||
class Gauge( wx.Gauge ):
|
class Gauge( wx.Gauge ):
|
||||||
|
|
||||||
def __init__( self, *args, **kwargs ):
|
def __init__( self, *args, **kwargs ):
|
||||||
|
@ -2613,6 +2249,7 @@ class ListBook( wx.Panel ):
|
||||||
|
|
||||||
class ListBox( wx.ScrolledWindow ):
|
class ListBox( wx.ScrolledWindow ):
|
||||||
|
|
||||||
|
TEXT_X_PADDING = 3
|
||||||
delete_key_activates = False
|
delete_key_activates = False
|
||||||
|
|
||||||
def __init__( self, parent, min_height = 250 ):
|
def __init__( self, parent, min_height = 250 ):
|
||||||
|
@ -2888,7 +2525,7 @@ class ListBox( wx.ScrolledWindow ):
|
||||||
|
|
||||||
dc.SetTextForeground( text_colour )
|
dc.SetTextForeground( text_colour )
|
||||||
|
|
||||||
( x, y ) = ( 3, i * self._text_y )
|
( x, y ) = ( self.TEXT_X_PADDING, i * self._text_y )
|
||||||
|
|
||||||
dc.DrawText( text, x, y )
|
dc.DrawText( text, x, y )
|
||||||
|
|
||||||
|
@ -3074,6 +2711,11 @@ class ListBox( wx.ScrolledWindow ):
|
||||||
else: return self._strings_to_terms[ s ]
|
else: return self._strings_to_terms[ s ]
|
||||||
|
|
||||||
|
|
||||||
|
def GetIdealHeight( self ):
|
||||||
|
|
||||||
|
return self._text_y * len( self._ordered_strings ) + 20
|
||||||
|
|
||||||
|
|
||||||
def SetTexts( self, ordered_strings ):
|
def SetTexts( self, ordered_strings ):
|
||||||
|
|
||||||
if ordered_strings != self._ordered_strings:
|
if ordered_strings != self._ordered_strings:
|
||||||
|
@ -3101,6 +2743,8 @@ class ListBoxTags( ListBox ):
|
||||||
self.Bind( wx.EVT_MIDDLE_DOWN, self.EventMouseMiddleClick )
|
self.Bind( wx.EVT_MIDDLE_DOWN, self.EventMouseMiddleClick )
|
||||||
self.Bind( wx.EVT_MENU, self.EventMenu )
|
self.Bind( wx.EVT_MENU, self.EventMenu )
|
||||||
|
|
||||||
|
HydrusGlobals.client_controller.sub( self, 'SiblingsHaveChanged', 'notify_new_siblings_gui' )
|
||||||
|
|
||||||
|
|
||||||
def _GetNamespaceColours( self ): return HC.options[ 'namespace_colours' ]
|
def _GetNamespaceColours( self ): return HC.options[ 'namespace_colours' ]
|
||||||
|
|
||||||
|
@ -3406,6 +3050,11 @@ class ListBoxTags( ListBox ):
|
||||||
return self._selected_terms
|
return self._selected_terms
|
||||||
|
|
||||||
|
|
||||||
|
def SiblingsHaveChanged( self ):
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ListBoxTagsAutocompleteDropdown( ListBoxTags ):
|
class ListBoxTagsAutocompleteDropdown( ListBoxTags ):
|
||||||
|
|
||||||
has_counts = True
|
has_counts = True
|
||||||
|
@ -3847,6 +3496,11 @@ class ListBoxTagsStrings( ListBoxTags ):
|
||||||
self._RecalcTags()
|
self._RecalcTags()
|
||||||
|
|
||||||
|
|
||||||
|
def SiblingsHaveChanged( self ):
|
||||||
|
|
||||||
|
self._RecalcTags()
|
||||||
|
|
||||||
|
|
||||||
class ListBoxTagsStringsAddRemove( ListBoxTagsStrings ):
|
class ListBoxTagsStringsAddRemove( ListBoxTagsStrings ):
|
||||||
|
|
||||||
def __init__( self, parent, removed_callable = None, show_sibling_text = True ):
|
def __init__( self, parent, removed_callable = None, show_sibling_text = True ):
|
||||||
|
@ -3947,6 +3601,22 @@ class ListBoxTagsSuggestions( ListBoxTagsStrings ):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def SetTags( self, tags ):
|
||||||
|
|
||||||
|
ListBoxTagsStrings.SetTags( self, tags )
|
||||||
|
|
||||||
|
if len( tags ) > 0:
|
||||||
|
|
||||||
|
dc = wx.MemoryDC( self._client_bmp )
|
||||||
|
|
||||||
|
dc.SetFont( wx.SystemSettings.GetFont( wx.SYS_DEFAULT_GUI_FONT ) )
|
||||||
|
|
||||||
|
width = max( ( dc.GetTextExtent( s )[0] for s in self._ordered_strings ) )
|
||||||
|
|
||||||
|
self.SetMinClientSize( ( width + 2 * self.TEXT_X_PADDING, -1 ) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ListBoxTagsPredicates( ListBoxTags ):
|
class ListBoxTagsPredicates( ListBoxTags ):
|
||||||
|
|
||||||
delete_key_activates = True
|
delete_key_activates = True
|
||||||
|
@ -4396,6 +4066,11 @@ class ListBoxTagsSelection( ListBoxTags ):
|
||||||
self._last_media = media
|
self._last_media = media
|
||||||
|
|
||||||
|
|
||||||
|
def SiblingsHaveChanged( self ):
|
||||||
|
|
||||||
|
self.SetTagsByMedia( self._last_media, force_reload = True )
|
||||||
|
|
||||||
|
|
||||||
class ListBoxTagsSelectionHoverFrame( ListBoxTagsSelection ):
|
class ListBoxTagsSelectionHoverFrame( ListBoxTagsSelection ):
|
||||||
|
|
||||||
def __init__( self, parent, canvas_key ):
|
def __init__( self, parent, canvas_key ):
|
||||||
|
@ -6271,7 +5946,7 @@ class SeedCacheControl( SaneListCtrl ):
|
||||||
pretty_status = CC.status_string_lookup[ status ]
|
pretty_status = CC.status_string_lookup[ status ]
|
||||||
pretty_added = HydrusData.ConvertTimestampToPrettyAgo( added_timestamp )
|
pretty_added = HydrusData.ConvertTimestampToPrettyAgo( added_timestamp )
|
||||||
pretty_modified = HydrusData.ConvertTimestampToPrettyAgo( last_modified_timestamp )
|
pretty_modified = HydrusData.ConvertTimestampToPrettyAgo( last_modified_timestamp )
|
||||||
pretty_note = note
|
pretty_note = note.split( os.linesep )[0]
|
||||||
|
|
||||||
return ( pretty_seed, pretty_status, pretty_added, pretty_modified, pretty_note )
|
return ( pretty_seed, pretty_status, pretty_added, pretty_modified, pretty_note )
|
||||||
|
|
||||||
|
@ -6813,75 +6488,6 @@ class RadioBox( StaticBox ):
|
||||||
|
|
||||||
def SetString( self, index, text ): self._indices_to_radio_buttons[ index ].SetLabelText( text )
|
def SetString( self, index, text ): self._indices_to_radio_buttons[ index ].SetLabelText( text )
|
||||||
|
|
||||||
class ShowKeys( Frame ):
|
|
||||||
|
|
||||||
def __init__( self, key_type, keys ):
|
|
||||||
|
|
||||||
if key_type == 'registration': title = 'Registration Keys'
|
|
||||||
elif key_type == 'access': title = 'Access Keys'
|
|
||||||
|
|
||||||
# give it no parent, so this doesn't close when the dialog is closed!
|
|
||||||
Frame.__init__( self, None, HydrusGlobals.client_controller.PrepStringForDisplay( title ) )
|
|
||||||
|
|
||||||
self._key_type = key_type
|
|
||||||
self._keys = keys
|
|
||||||
|
|
||||||
#
|
|
||||||
|
|
||||||
self._text_ctrl = wx.TextCtrl( self, style = wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_DONTWRAP )
|
|
||||||
|
|
||||||
self._save_to_file = wx.Button( self, label = 'save to file' )
|
|
||||||
self._save_to_file.Bind( wx.EVT_BUTTON, self.EventSaveToFile )
|
|
||||||
|
|
||||||
self._done = wx.Button( self, id = wx.ID_OK, label = 'done' )
|
|
||||||
self._done.Bind( wx.EVT_BUTTON, self.EventDone )
|
|
||||||
|
|
||||||
#
|
|
||||||
|
|
||||||
if key_type == 'registration': prepend = 'r'
|
|
||||||
else: prepend = ''
|
|
||||||
|
|
||||||
self._text = os.linesep.join( [ prepend + key.encode( 'hex' ) for key in self._keys ] )
|
|
||||||
|
|
||||||
self._text_ctrl.SetValue( self._text )
|
|
||||||
|
|
||||||
#
|
|
||||||
|
|
||||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
|
||||||
|
|
||||||
vbox.AddF( self._text_ctrl, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
||||||
vbox.AddF( self._save_to_file, CC.FLAGS_LONE_BUTTON )
|
|
||||||
vbox.AddF( self._done, CC.FLAGS_LONE_BUTTON )
|
|
||||||
|
|
||||||
self.SetSizer( vbox )
|
|
||||||
|
|
||||||
( x, y ) = self.GetEffectiveMinSize()
|
|
||||||
|
|
||||||
if x < 500: x = 500
|
|
||||||
if y < 200: y = 200
|
|
||||||
|
|
||||||
self.SetInitialSize( ( x, y ) )
|
|
||||||
|
|
||||||
self.Show( True )
|
|
||||||
|
|
||||||
|
|
||||||
def EventDone( self, event ): self.Close()
|
|
||||||
|
|
||||||
def EventSaveToFile( self, event ):
|
|
||||||
|
|
||||||
filename = 'keys.txt'
|
|
||||||
|
|
||||||
with wx.FileDialog( None, style=wx.FD_SAVE, defaultFile = filename ) as dlg:
|
|
||||||
|
|
||||||
if dlg.ShowModal() == wx.ID_OK:
|
|
||||||
|
|
||||||
path = HydrusData.ToUnicode( dlg.GetPath() )
|
|
||||||
|
|
||||||
with open( path, 'wb' ) as f: f.write( HydrusData.ToByteString( self._text ) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WaitingPolitelyStaticText( wx.StaticText ):
|
class WaitingPolitelyStaticText( wx.StaticText ):
|
||||||
|
|
||||||
def __init__( self, parent, page_key ):
|
def __init__( self, parent, page_key ):
|
||||||
|
|
|
@ -18,6 +18,7 @@ import ClientFiles
|
||||||
import ClientGUICommon
|
import ClientGUICommon
|
||||||
import ClientGUICollapsible
|
import ClientGUICollapsible
|
||||||
import ClientGUIPredicates
|
import ClientGUIPredicates
|
||||||
|
import ClientGUITopLevelWindows
|
||||||
import ClientThreading
|
import ClientThreading
|
||||||
import collections
|
import collections
|
||||||
import gc
|
import gc
|
||||||
|
@ -301,199 +302,6 @@ class Dialog( wx.Dialog ):
|
||||||
HydrusGlobals.client_controller.ResetIdleTimer()
|
HydrusGlobals.client_controller.ResetIdleTimer()
|
||||||
|
|
||||||
|
|
||||||
def _ExpandSizeIfPossible( self, frame_key, desired_size_delta ):
|
|
||||||
|
|
||||||
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = self._new_options.GetFrameLocation( frame_key )
|
|
||||||
|
|
||||||
parent = self.GetParent()
|
|
||||||
|
|
||||||
if not self.IsMaximized() and not self.IsFullScreen():
|
|
||||||
|
|
||||||
( current_width, current_height ) = self.GetSize()
|
|
||||||
|
|
||||||
( desired_delta_width, desired_delta_height ) = desired_size_delta
|
|
||||||
|
|
||||||
min_width = current_width + desired_delta_width
|
|
||||||
min_height = current_height + desired_delta_height
|
|
||||||
|
|
||||||
if parent is None:
|
|
||||||
|
|
||||||
width = min_width + 20
|
|
||||||
height = min_height + 20
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
( parent_window_width, parent_window_height ) = self.GetParent().GetTopLevelParent().GetSize()
|
|
||||||
|
|
||||||
max_width = parent_window_width - 100
|
|
||||||
max_height = parent_window_height - 100
|
|
||||||
|
|
||||||
( width_gravity, height_gravity ) = default_gravity
|
|
||||||
|
|
||||||
if width_gravity == -1:
|
|
||||||
|
|
||||||
width = min_width
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
width = int( width_gravity * max_width )
|
|
||||||
|
|
||||||
|
|
||||||
if height_gravity == -1:
|
|
||||||
|
|
||||||
height = min_height
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
height = int( height_gravity * max_height )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if width > current_width or height > current_height:
|
|
||||||
|
|
||||||
self.SetSize( ( width, height ) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _GetSafePosition( self, position ):
|
|
||||||
|
|
||||||
display_index = wx.Display.GetFromPoint( position )
|
|
||||||
|
|
||||||
if display_index == wx.NOT_FOUND:
|
|
||||||
|
|
||||||
position = wx.DefaultPosition
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
display = wx.Display( display_index )
|
|
||||||
|
|
||||||
geometry = display.GetGeometry()
|
|
||||||
|
|
||||||
( p_x, p_y ) = position
|
|
||||||
|
|
||||||
x_bad = p_x < geometry.x or p_x > geometry.x + geometry.width
|
|
||||||
y_bad = p_y < geometry.y or p_y > geometry.y + geometry.height
|
|
||||||
|
|
||||||
if x_bad or y_bad:
|
|
||||||
|
|
||||||
position = wx.DefaultPosition
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return position
|
|
||||||
|
|
||||||
|
|
||||||
def _SaveSizeAndPosition( self, frame_key ):
|
|
||||||
|
|
||||||
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = self._new_options.GetFrameLocation( frame_key )
|
|
||||||
|
|
||||||
last_size = self.GetSizeTuple()
|
|
||||||
|
|
||||||
last_position = self._GetSafePosition( self.GetPositionTuple() )
|
|
||||||
|
|
||||||
self._new_options.SetFrameLocation( frame_key, remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen )
|
|
||||||
|
|
||||||
|
|
||||||
def _SetSizeAndPosition( self, frame_key ):
|
|
||||||
|
|
||||||
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = self._new_options.GetFrameLocation( frame_key )
|
|
||||||
|
|
||||||
parent = self.GetParent()
|
|
||||||
|
|
||||||
if remember_size and last_size is not None:
|
|
||||||
|
|
||||||
( width, height ) = last_size
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
( min_width, min_height ) = self.GetEffectiveMinSize()
|
|
||||||
|
|
||||||
min_width += 30
|
|
||||||
min_height += 30
|
|
||||||
|
|
||||||
if parent is None:
|
|
||||||
|
|
||||||
width = min_width
|
|
||||||
height = min_height
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
( parent_window_width, parent_window_height ) = self.GetParent().GetTopLevelParent().GetSize()
|
|
||||||
|
|
||||||
max_width = parent_window_width - 100
|
|
||||||
max_height = parent_window_height - 100
|
|
||||||
|
|
||||||
( width_gravity, height_gravity ) = default_gravity
|
|
||||||
|
|
||||||
if width_gravity == -1:
|
|
||||||
|
|
||||||
width = min_width
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
width = int( width_gravity * max_width )
|
|
||||||
|
|
||||||
|
|
||||||
if height_gravity == -1:
|
|
||||||
|
|
||||||
height = min_height
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
height = int( height_gravity * max_height )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.SetInitialSize( ( width, height ) )
|
|
||||||
|
|
||||||
if maximised:
|
|
||||||
|
|
||||||
self.Maximize()
|
|
||||||
|
|
||||||
|
|
||||||
if fullscreen:
|
|
||||||
|
|
||||||
wx.CallAfter( self.ShowFullScreen, True, wx.FULLSCREEN_ALL )
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
|
|
||||||
pos = None
|
|
||||||
|
|
||||||
if remember_position and last_position is not None:
|
|
||||||
|
|
||||||
pos = last_position
|
|
||||||
|
|
||||||
elif default_position == 'topleft' and parent is not None:
|
|
||||||
|
|
||||||
if isinstance( parent, wx.TopLevelWindow ):
|
|
||||||
|
|
||||||
parent_tlp = parent
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
parent_tlp = parent.GetTopLevelParent()
|
|
||||||
|
|
||||||
|
|
||||||
( pos_x, pos_y ) = parent_tlp.GetPositionTuple()
|
|
||||||
|
|
||||||
pos = ( pos_x + 50, pos_y + 50 )
|
|
||||||
|
|
||||||
elif default_position == 'center':
|
|
||||||
|
|
||||||
wx.CallAfter( self.Center )
|
|
||||||
|
|
||||||
|
|
||||||
if pos is not None:
|
|
||||||
|
|
||||||
pos = self._GetSafePosition( pos )
|
|
||||||
|
|
||||||
self.SetPosition( pos )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def EventDialogButton( self, event ): self.EndModal( event.GetId() )
|
def EventDialogButton( self, event ): self.EndModal( event.GetId() )
|
||||||
|
|
||||||
def SetInitialSize( self, ( width, height ) ):
|
def SetInitialSize( self, ( width, height ) ):
|
||||||
|
@ -511,92 +319,6 @@ class Dialog( wx.Dialog ):
|
||||||
self.SetMinSize( ( min_width, min_height ) )
|
self.SetMinSize( ( min_width, min_height ) )
|
||||||
|
|
||||||
|
|
||||||
class DialogManageApply( Dialog ):
|
|
||||||
|
|
||||||
def __init__( self, parent, title, frame_key ):
|
|
||||||
|
|
||||||
self._frame_key = frame_key
|
|
||||||
self._panel = None
|
|
||||||
|
|
||||||
Dialog.__init__( self, parent, title )
|
|
||||||
|
|
||||||
self._apply = wx.Button( self, id = wx.ID_OK, label = 'apply' )
|
|
||||||
self._apply.Bind( wx.EVT_BUTTON, self.EventOk )
|
|
||||||
self._apply.SetForegroundColour( ( 0, 128, 0 ) )
|
|
||||||
|
|
||||||
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'cancel' )
|
|
||||||
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
|
|
||||||
|
|
||||||
self.Bind( wx.EVT_MENU, self.EventMenu )
|
|
||||||
self.Bind( CC.EVT_SIZE_CHANGED, self.EventChildSizeChanged )
|
|
||||||
|
|
||||||
|
|
||||||
def EventChildSizeChanged( self, event ):
|
|
||||||
|
|
||||||
if self._panel is not None:
|
|
||||||
|
|
||||||
( current_panel_width, current_panel_height ) = self._panel.GetSize()
|
|
||||||
( desired_panel_width, desired_panel_height ) = self._panel.GetVirtualSize()
|
|
||||||
|
|
||||||
desired_delta_width = max( 0, desired_panel_width - current_panel_width )
|
|
||||||
desired_delta_height = max( 0, desired_panel_height - current_panel_height )
|
|
||||||
|
|
||||||
if desired_delta_width > 0 or desired_delta_height > 0:
|
|
||||||
|
|
||||||
self._ExpandSizeIfPossible( self._frame_key, ( desired_delta_width, desired_delta_height ) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def EventMenu( self, event ):
|
|
||||||
|
|
||||||
action = ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetAction( event.GetId() )
|
|
||||||
|
|
||||||
if action is not None:
|
|
||||||
|
|
||||||
( command, data ) = action
|
|
||||||
|
|
||||||
if command == 'ok':
|
|
||||||
|
|
||||||
self.EventOk( None )
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
event.Skip()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def EventOk( self, event ):
|
|
||||||
|
|
||||||
self._panel.CommitChanges()
|
|
||||||
|
|
||||||
self._SaveSizeAndPosition( self._frame_key )
|
|
||||||
|
|
||||||
self.EndModal( wx.ID_OK )
|
|
||||||
|
|
||||||
|
|
||||||
def SetPanel( self, panel ):
|
|
||||||
|
|
||||||
self._panel = panel
|
|
||||||
|
|
||||||
buttonbox = wx.BoxSizer( wx.HORIZONTAL )
|
|
||||||
|
|
||||||
buttonbox.AddF( self._apply, CC.FLAGS_MIXED )
|
|
||||||
buttonbox.AddF( self._cancel, CC.FLAGS_MIXED )
|
|
||||||
|
|
||||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
|
||||||
|
|
||||||
vbox.AddF( self._panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
|
||||||
vbox.AddF( buttonbox, CC.FLAGS_BUTTON_SIZER )
|
|
||||||
|
|
||||||
self.SetSizer( vbox )
|
|
||||||
|
|
||||||
self._SetSizeAndPosition( self._frame_key )
|
|
||||||
|
|
||||||
self._panel.SetupScrolling()
|
|
||||||
|
|
||||||
|
|
||||||
class DialogAdvancedContentUpdate( Dialog ):
|
class DialogAdvancedContentUpdate( Dialog ):
|
||||||
|
|
||||||
COPY = 0
|
COPY = 0
|
||||||
|
@ -1095,7 +817,7 @@ class DialogGenerateNewAccounts( Dialog ):
|
||||||
|
|
||||||
registration_keys = response[ 'registration_keys' ]
|
registration_keys = response[ 'registration_keys' ]
|
||||||
|
|
||||||
ClientGUICommon.ShowKeys( 'registration', registration_keys )
|
ClientGUITopLevelWindows.ShowKeys( 'registration', registration_keys )
|
||||||
|
|
||||||
finally: self.EndModal( wx.ID_OK )
|
finally: self.EndModal( wx.ID_OK )
|
||||||
|
|
||||||
|
|
|
@ -2721,6 +2721,11 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
||||||
self._seed_cache_button.Bind( wx.EVT_BUTTON, self.EventSeedCache )
|
self._seed_cache_button.Bind( wx.EVT_BUTTON, self.EventSeedCache )
|
||||||
self._seed_cache_button.SetToolTipString( 'open detailed file import status' )
|
self._seed_cache_button.SetToolTipString( 'open detailed file import status' )
|
||||||
|
|
||||||
|
if not HC.PLATFORM_WINDOWS:
|
||||||
|
|
||||||
|
self._seed_cache_button.Hide()
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
self._file_box = ClientGUICommon.StaticBox( self._panel, 'file options' )
|
self._file_box = ClientGUICommon.StaticBox( self._panel, 'file options' )
|
||||||
|
@ -3058,7 +3063,9 @@ class DialogManageImportFoldersEdit( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
seed_cache = self._import_folder.GetSeedCache()
|
seed_cache = self._import_folder.GetSeedCache()
|
||||||
|
|
||||||
HydrusGlobals.client_controller.pub( 'show_seed_cache', seed_cache )
|
import ClientGUI
|
||||||
|
|
||||||
|
ClientGUI.FrameSeedCache( self, HydrusGlobals.client_controller, seed_cache )
|
||||||
|
|
||||||
|
|
||||||
def GetInfo( self ):
|
def GetInfo( self ):
|
||||||
|
@ -5352,6 +5359,11 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
||||||
self._seed_cache_button.Bind( wx.EVT_BUTTON, self.EventSeedCache )
|
self._seed_cache_button.Bind( wx.EVT_BUTTON, self.EventSeedCache )
|
||||||
self._seed_cache_button.SetToolTipString( 'open detailed url cache status' )
|
self._seed_cache_button.SetToolTipString( 'open detailed url cache status' )
|
||||||
|
|
||||||
|
if not HC.PLATFORM_WINDOWS:
|
||||||
|
|
||||||
|
self._seed_cache_button.Hide()
|
||||||
|
|
||||||
|
|
||||||
self._reset_cache_button = wx.Button( self._info_panel, label = ' reset url cache on dialog ok ' )
|
self._reset_cache_button = wx.Button( self._info_panel, label = ' reset url cache on dialog ok ' )
|
||||||
self._reset_cache_button.Bind( wx.EVT_BUTTON, self.EventResetCache )
|
self._reset_cache_button.Bind( wx.EVT_BUTTON, self.EventResetCache )
|
||||||
|
|
||||||
|
@ -5565,7 +5577,9 @@ class DialogManageSubscriptions( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
seed_cache = self._original_subscription.GetSeedCache()
|
seed_cache = self._original_subscription.GetSeedCache()
|
||||||
|
|
||||||
HydrusGlobals.client_controller.pub( 'show_seed_cache', seed_cache )
|
import ClientGUI
|
||||||
|
|
||||||
|
ClientGUI.FrameSeedCache( self, HydrusGlobals.client_controller, seed_cache )
|
||||||
|
|
||||||
|
|
||||||
def EventSiteChanged( self, event ): self._PresentForSiteType()
|
def EventSiteChanged( self, event ): self._PresentForSiteType()
|
||||||
|
@ -6179,7 +6193,7 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
if potential_child == potential_parent: return False
|
if potential_child == potential_parent: return False
|
||||||
|
|
||||||
current_pairs = self._current_statuses_to_pairs[ HC.CURRENT ].union( self._current_statuses_to_pairs[ HC.PENDING ] )
|
current_pairs = self._current_statuses_to_pairs[ HC.CURRENT ].union( self._current_statuses_to_pairs[ HC.PENDING ] ).difference( self._current_statuses_to_pairs[ HC.PETITIONED ] )
|
||||||
|
|
||||||
current_children = { child for ( child, parent ) in current_pairs }
|
current_children = { child for ( child, parent ) in current_pairs }
|
||||||
|
|
||||||
|
@ -6770,7 +6784,7 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
( potential_old, potential_new ) = potential_pair
|
( potential_old, potential_new ) = potential_pair
|
||||||
|
|
||||||
current_pairs = self._current_statuses_to_pairs[ HC.CURRENT ].union( self._current_statuses_to_pairs[ HC.PENDING ] )
|
current_pairs = self._current_statuses_to_pairs[ HC.CURRENT ].union( self._current_statuses_to_pairs[ HC.PENDING ] ).difference( self._current_statuses_to_pairs[ HC.PETITIONED ] )
|
||||||
|
|
||||||
current_olds = { old for ( old, new ) in current_pairs }
|
current_olds = { old for ( old, new ) in current_pairs }
|
||||||
|
|
||||||
|
@ -6862,7 +6876,7 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
do_it = True
|
do_it = True
|
||||||
|
|
||||||
current_pairs = self._current_statuses_to_pairs[ HC.CURRENT ].union( self._current_statuses_to_pairs[ HC.PENDING ] )
|
current_pairs = self._current_statuses_to_pairs[ HC.CURRENT ].union( self._current_statuses_to_pairs[ HC.PENDING ] ).difference( self._current_statuses_to_pairs[ HC.PETITIONED ] )
|
||||||
|
|
||||||
current_olds = { current_old for ( current_old, current_new ) in current_pairs }
|
current_olds = { current_old for ( current_old, current_new ) in current_pairs }
|
||||||
|
|
||||||
|
@ -6890,7 +6904,7 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
current_pairs = self._current_statuses_to_pairs[ HC.CURRENT ].union( self._current_statuses_to_pairs[ HC.PENDING ] )
|
current_pairs = self._current_statuses_to_pairs[ HC.CURRENT ].union( self._current_statuses_to_pairs[ HC.PENDING ] ).difference( self._current_statuses_to_pairs[ HC.PETITIONED ] )
|
||||||
|
|
||||||
current_olds = { current_old for ( current_old, current_new ) in current_pairs }
|
current_olds = { current_old for ( current_old, current_new ) in current_pairs }
|
||||||
|
|
||||||
|
|
|
@ -1822,7 +1822,9 @@ class ManagementPanelGalleryImport( ManagementPanel ):
|
||||||
|
|
||||||
seed_cache = self._gallery_import.GetSeedCache()
|
seed_cache = self._gallery_import.GetSeedCache()
|
||||||
|
|
||||||
self._controller.pub( 'show_seed_cache', seed_cache )
|
import ClientGUI
|
||||||
|
|
||||||
|
ClientGUI.FrameSeedCache( self, HydrusGlobals.client_controller, seed_cache )
|
||||||
|
|
||||||
|
|
||||||
def SetSearchFocus( self, page_key ):
|
def SetSearchFocus( self, page_key ):
|
||||||
|
@ -1963,7 +1965,9 @@ class ManagementPanelHDDImport( ManagementPanel ):
|
||||||
|
|
||||||
seed_cache = self._hdd_import.GetSeedCache()
|
seed_cache = self._hdd_import.GetSeedCache()
|
||||||
|
|
||||||
self._controller.pub( 'show_seed_cache', seed_cache )
|
import ClientGUI
|
||||||
|
|
||||||
|
ClientGUI.FrameSeedCache( self, HydrusGlobals.client_controller, seed_cache )
|
||||||
|
|
||||||
|
|
||||||
def TestAbleToClose( self ):
|
def TestAbleToClose( self ):
|
||||||
|
@ -2333,7 +2337,9 @@ class ManagementPanelPageOfImagesImport( ManagementPanel ):
|
||||||
|
|
||||||
seed_cache = self._page_of_images_import.GetSeedCache()
|
seed_cache = self._page_of_images_import.GetSeedCache()
|
||||||
|
|
||||||
self._controller.pub( 'show_seed_cache', seed_cache )
|
import ClientGUI
|
||||||
|
|
||||||
|
ClientGUI.FrameSeedCache( self, HydrusGlobals.client_controller, seed_cache )
|
||||||
|
|
||||||
|
|
||||||
def SetSearchFocus( self, page_key ):
|
def SetSearchFocus( self, page_key ):
|
||||||
|
@ -3129,7 +3135,9 @@ class ManagementPanelThreadWatcherImport( ManagementPanel ):
|
||||||
|
|
||||||
seed_cache = self._thread_watcher_import.GetSeedCache()
|
seed_cache = self._thread_watcher_import.GetSeedCache()
|
||||||
|
|
||||||
self._controller.pub( 'show_seed_cache', seed_cache )
|
import ClientGUI
|
||||||
|
|
||||||
|
ClientGUI.FrameSeedCache( self, HydrusGlobals.client_controller, seed_cache )
|
||||||
|
|
||||||
|
|
||||||
def EventTimesToCheck( self, event ):
|
def EventTimesToCheck( self, event ):
|
||||||
|
|
|
@ -8,6 +8,7 @@ import ClientGUIDialogs
|
||||||
import ClientGUIDialogsManage
|
import ClientGUIDialogsManage
|
||||||
import ClientGUICanvas
|
import ClientGUICanvas
|
||||||
import ClientGUIPanels
|
import ClientGUIPanels
|
||||||
|
import ClientGUITopLevelWindows
|
||||||
import ClientMedia
|
import ClientMedia
|
||||||
import collections
|
import collections
|
||||||
import HydrusExceptions
|
import HydrusExceptions
|
||||||
|
@ -386,6 +387,11 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
||||||
|
|
||||||
if file_service_key in local_file_services:
|
if file_service_key in local_file_services:
|
||||||
|
|
||||||
|
if file_service_key == CC.TRASH_SERVICE_KEY:
|
||||||
|
|
||||||
|
self._SetFocussedMedia( None )
|
||||||
|
|
||||||
|
|
||||||
HydrusGlobals.client_controller.Write( 'content_updates', { file_service_key : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, hashes ) ] } )
|
HydrusGlobals.client_controller.Write( 'content_updates', { file_service_key : [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, hashes ) ] } )
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -785,7 +791,7 @@ class MediaPanel( ClientMedia.ListeningMediaList, wx.ScrolledWindow ):
|
||||||
title = 'manage tags for ' + HydrusData.ConvertIntToPrettyString( num_files ) + ' files'
|
title = 'manage tags for ' + HydrusData.ConvertIntToPrettyString( num_files ) + ' files'
|
||||||
frame_key = 'manage_tags_dialog'
|
frame_key = 'manage_tags_dialog'
|
||||||
|
|
||||||
with ClientGUIDialogs.DialogManageApply( self, title, frame_key ) as dlg:
|
with ClientGUITopLevelWindows.DialogManage( self, title, frame_key ) as dlg:
|
||||||
|
|
||||||
panel = ClientGUIPanels.ManageTagsPanel( dlg, self._file_service_key, self._selected_media )
|
panel = ClientGUIPanels.ManageTagsPanel( dlg, self._file_service_key, self._selected_media )
|
||||||
|
|
||||||
|
|
|
@ -1399,14 +1399,14 @@ class MessagePanel( wx.Panel ):
|
||||||
|
|
||||||
# here starts the message reboot code
|
# here starts the message reboot code
|
||||||
|
|
||||||
class IMFrame( ClientGUICommon.Frame ):
|
class IMFrame( ClientGUITopLevelWindows.Frame ):
|
||||||
|
|
||||||
def __init__( self, parent, me_account, them_account, context ):
|
def __init__( self, parent, me_account, them_account, context ):
|
||||||
|
|
||||||
me_name = me_account.GetNameBlah()
|
me_name = me_account.GetNameBlah()
|
||||||
them_name = them_account.GetNameBlah()
|
them_name = them_account.GetNameBlah()
|
||||||
|
|
||||||
ClientGUICommon.Frame.__init__( self, parent, title = me_name + ' talking to ' + them_name )
|
ClientGUITopLevelWindows.Frame.__init__( self, parent, title = me_name + ' talking to ' + them_name )
|
||||||
|
|
||||||
self._me_label = MeLabel( self, me_account ) # maybe these two should be the same, and infer me/them status itself
|
self._me_label = MeLabel( self, me_account ) # maybe these two should be the same, and infer me/them status itself
|
||||||
self._them_label = ThemLabel( self, them_account )
|
self._them_label = ThemLabel( self, them_account )
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,536 @@
|
||||||
|
import ClientCaches
|
||||||
|
import ClientConstants as CC
|
||||||
|
import HydrusConstants as HC
|
||||||
|
import HydrusData
|
||||||
|
import HydrusGlobals
|
||||||
|
import os
|
||||||
|
import wx
|
||||||
|
|
||||||
|
CHILD_POSITION_PADDING = 50
|
||||||
|
FUZZY_PADDING = 30
|
||||||
|
|
||||||
|
def GetSafePosition( position ):
|
||||||
|
|
||||||
|
( p_x, p_y ) = position
|
||||||
|
|
||||||
|
# some window managers size the windows just off screen to cut off borders
|
||||||
|
# so choose a test position that's a little more lenient
|
||||||
|
( test_x, test_y ) = ( p_x + FUZZY_PADDING, p_y + FUZZY_PADDING )
|
||||||
|
|
||||||
|
display_index = wx.Display.GetFromPoint( ( test_x, test_y ) )
|
||||||
|
|
||||||
|
if display_index == wx.NOT_FOUND:
|
||||||
|
|
||||||
|
return wx.DefaultPosition
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
return position
|
||||||
|
|
||||||
|
|
||||||
|
def GetSafeSize( tlw, min_size, gravity ):
|
||||||
|
|
||||||
|
( min_width, min_height ) = min_size
|
||||||
|
|
||||||
|
parent = tlw.GetParent()
|
||||||
|
|
||||||
|
if parent is None:
|
||||||
|
|
||||||
|
width = min_width
|
||||||
|
height = min_height
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
( parent_window_width, parent_window_height ) = parent.GetTopLevelParent().GetSize()
|
||||||
|
|
||||||
|
max_width = parent_window_width - 2 * CHILD_POSITION_PADDING
|
||||||
|
max_height = parent_window_height - 2 * CHILD_POSITION_PADDING
|
||||||
|
|
||||||
|
( width_gravity, height_gravity ) = gravity
|
||||||
|
|
||||||
|
if width_gravity == -1:
|
||||||
|
|
||||||
|
width = min_width
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
width = int( width_gravity * max_width )
|
||||||
|
|
||||||
|
|
||||||
|
if height_gravity == -1:
|
||||||
|
|
||||||
|
height = min_height
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
height = int( height_gravity * max_height )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
( display_width, display_height ) = wx.GetDisplaySize()
|
||||||
|
|
||||||
|
width = min( display_width, width )
|
||||||
|
height = min( display_height, height )
|
||||||
|
|
||||||
|
return ( width, height )
|
||||||
|
|
||||||
|
def ExpandTLWIfPossible( tlw, frame_key, desired_size_delta ):
|
||||||
|
|
||||||
|
new_options = HydrusGlobals.client_controller.GetNewOptions()
|
||||||
|
|
||||||
|
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = new_options.GetFrameLocation( frame_key )
|
||||||
|
|
||||||
|
if not tlw.IsMaximized() and not tlw.IsFullScreen():
|
||||||
|
|
||||||
|
( current_width, current_height ) = tlw.GetSize()
|
||||||
|
|
||||||
|
( desired_delta_width, desired_delta_height ) = desired_size_delta
|
||||||
|
|
||||||
|
min_width = current_width + desired_delta_width + FUZZY_PADDING
|
||||||
|
min_height = current_height + desired_delta_height + FUZZY_PADDING
|
||||||
|
|
||||||
|
( width, height ) = GetSafeSize( tlw, ( min_width, min_height ), default_gravity )
|
||||||
|
|
||||||
|
if width > current_width or height > current_height:
|
||||||
|
|
||||||
|
tlw.SetSize( ( width, height ) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def SaveTLWSizeAndPosition( tlw, frame_key ):
|
||||||
|
|
||||||
|
new_options = HydrusGlobals.client_controller.GetNewOptions()
|
||||||
|
|
||||||
|
( 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 not ( maximised or fullscreen ):
|
||||||
|
|
||||||
|
safe_position = GetSafePosition( tlw.GetPositionTuple() )
|
||||||
|
|
||||||
|
if safe_position != wx.DefaultPosition:
|
||||||
|
|
||||||
|
last_size = tlw.GetSizeTuple()
|
||||||
|
last_position = safe_position
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
new_options.SetFrameLocation( frame_key, remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen )
|
||||||
|
|
||||||
|
def SetTLWSizeAndPosition( tlw, frame_key ):
|
||||||
|
|
||||||
|
new_options = HydrusGlobals.client_controller.GetNewOptions()
|
||||||
|
|
||||||
|
( remember_size, remember_position, last_size, last_position, default_gravity, default_position, maximised, fullscreen ) = new_options.GetFrameLocation( frame_key )
|
||||||
|
|
||||||
|
parent = tlw.GetParent()
|
||||||
|
|
||||||
|
if remember_size and last_size is not None:
|
||||||
|
|
||||||
|
( width, height ) = last_size
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
( min_width, min_height ) = tlw.GetEffectiveMinSize()
|
||||||
|
|
||||||
|
min_width += FUZZY_PADDING
|
||||||
|
min_height += FUZZY_PADDING
|
||||||
|
|
||||||
|
( width, height ) = GetSafeSize( tlw, ( min_width, min_height ), default_gravity )
|
||||||
|
|
||||||
|
|
||||||
|
tlw.SetInitialSize( ( width, height ) )
|
||||||
|
|
||||||
|
min_width = min( 240, width )
|
||||||
|
min_height = min( 240, height )
|
||||||
|
|
||||||
|
tlw.SetMinSize( ( min_width, min_height ) )
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
if remember_position and last_position is not None:
|
||||||
|
|
||||||
|
safe_position = GetSafePosition( last_position )
|
||||||
|
|
||||||
|
tlw.SetPosition( safe_position )
|
||||||
|
|
||||||
|
elif default_position == 'topleft':
|
||||||
|
|
||||||
|
if parent is not None:
|
||||||
|
|
||||||
|
if isinstance( parent, wx.TopLevelWindow ):
|
||||||
|
|
||||||
|
parent_tlp = parent
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
parent_tlp = parent.GetTopLevelParent()
|
||||||
|
|
||||||
|
|
||||||
|
( parent_x, parent_y ) = parent_tlp.GetPositionTuple()
|
||||||
|
|
||||||
|
tlw.SetPosition( ( parent_x + CHILD_POSITION_PADDING, parent_y + CHILD_POSITION_PADDING ) )
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
safe_position = GetSafePosition( ( 0 + CHILD_POSITION_PADDING, 0 + CHILD_POSITION_PADDING ) )
|
||||||
|
|
||||||
|
tlw.SetPosition( safe_position )
|
||||||
|
|
||||||
|
|
||||||
|
elif default_position == 'center':
|
||||||
|
|
||||||
|
wx.CallAfter( tlw.Center )
|
||||||
|
|
||||||
|
|
||||||
|
# if these aren't callafter, the size and pos calls don't stick if a restore event happens
|
||||||
|
|
||||||
|
if maximised:
|
||||||
|
|
||||||
|
wx.CallAfter( tlw.Maximize )
|
||||||
|
|
||||||
|
|
||||||
|
if fullscreen:
|
||||||
|
|
||||||
|
wx.CallAfter( tlw.ShowFullScreen, True, wx.FULLSCREEN_ALL )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class NewDialog( wx.Dialog ):
|
||||||
|
|
||||||
|
def __init__( self, parent, title ):
|
||||||
|
|
||||||
|
style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER
|
||||||
|
|
||||||
|
if not HC.PLATFORM_LINUX and parent is not None:
|
||||||
|
|
||||||
|
style |= wx.FRAME_FLOAT_ON_PARENT
|
||||||
|
|
||||||
|
|
||||||
|
wx.Dialog.__init__( self, parent, title = title, style = style )
|
||||||
|
|
||||||
|
self._new_options = HydrusGlobals.client_controller.GetNewOptions()
|
||||||
|
|
||||||
|
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
|
||||||
|
|
||||||
|
self.SetIcon( wx.Icon( os.path.join( HC.STATIC_DIR, 'hydrus.ico' ), wx.BITMAP_TYPE_ICO ) )
|
||||||
|
|
||||||
|
self.Bind( wx.EVT_BUTTON, self.EventDialogButton )
|
||||||
|
|
||||||
|
HydrusGlobals.client_controller.ResetIdleTimer()
|
||||||
|
|
||||||
|
|
||||||
|
def EventDialogButton( self, event ): self.EndModal( event.GetId() )
|
||||||
|
|
||||||
|
class DialogThatResizes( NewDialog ):
|
||||||
|
|
||||||
|
def __init__( self, parent, title, frame_key ):
|
||||||
|
|
||||||
|
self._frame_key = frame_key
|
||||||
|
|
||||||
|
NewDialog.__init__( self, parent, title )
|
||||||
|
|
||||||
|
|
||||||
|
class DialogThatTakesScrollablePanel( DialogThatResizes ):
|
||||||
|
|
||||||
|
def __init__( self, parent, title, frame_key ):
|
||||||
|
|
||||||
|
self._panel = None
|
||||||
|
|
||||||
|
DialogThatResizes.__init__( self, parent, title, frame_key )
|
||||||
|
|
||||||
|
self._apply = wx.Button( self, id = wx.ID_OK, label = 'apply' )
|
||||||
|
self._apply.Bind( wx.EVT_BUTTON, self.EventOk )
|
||||||
|
self._apply.SetForegroundColour( ( 0, 128, 0 ) )
|
||||||
|
|
||||||
|
self._cancel = wx.Button( self, id = wx.ID_CANCEL, label = 'cancel' )
|
||||||
|
self._cancel.SetForegroundColour( ( 128, 0, 0 ) )
|
||||||
|
|
||||||
|
self.Bind( wx.EVT_MENU, self.EventMenu )
|
||||||
|
self.Bind( CC.EVT_SIZE_CHANGED, self.EventChildSizeChanged )
|
||||||
|
|
||||||
|
|
||||||
|
def EventChildSizeChanged( self, event ):
|
||||||
|
|
||||||
|
if self._panel is not None:
|
||||||
|
|
||||||
|
# the min size here is to compensate for wx.Notebook and anything else that don't update virtualsize on page change
|
||||||
|
|
||||||
|
( current_panel_width, current_panel_height ) = self._panel.GetSize()
|
||||||
|
( desired_panel_width, desired_panel_height ) = self._panel.GetVirtualSize()
|
||||||
|
( min_panel_width, min_panel_height ) = self._panel.GetEffectiveMinSize()
|
||||||
|
|
||||||
|
desired_delta_width = max( 0, desired_panel_width - current_panel_width, min_panel_width - current_panel_width )
|
||||||
|
desired_delta_height = max( 0, desired_panel_height - current_panel_height, min_panel_height - current_panel_height )
|
||||||
|
|
||||||
|
if desired_delta_width > 0 or desired_delta_height > 0:
|
||||||
|
|
||||||
|
ExpandTLWIfPossible( self, self._frame_key, ( desired_delta_width, desired_delta_height ) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def EventMenu( self, event ):
|
||||||
|
|
||||||
|
action = ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetAction( event.GetId() )
|
||||||
|
|
||||||
|
if action is not None:
|
||||||
|
|
||||||
|
( command, data ) = action
|
||||||
|
|
||||||
|
if command == 'ok':
|
||||||
|
|
||||||
|
self.EventOk( None )
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def EventOk( self, event ):
|
||||||
|
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
def SetPanel( self, panel ):
|
||||||
|
|
||||||
|
self._panel = panel
|
||||||
|
|
||||||
|
buttonbox = wx.BoxSizer( wx.HORIZONTAL )
|
||||||
|
|
||||||
|
buttonbox.AddF( self._apply, CC.FLAGS_MIXED )
|
||||||
|
buttonbox.AddF( self._cancel, CC.FLAGS_MIXED )
|
||||||
|
|
||||||
|
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||||
|
|
||||||
|
vbox.AddF( self._panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||||
|
vbox.AddF( buttonbox, CC.FLAGS_BUTTON_SIZER )
|
||||||
|
|
||||||
|
self.SetSizer( vbox )
|
||||||
|
|
||||||
|
SetTLWSizeAndPosition( self, self._frame_key )
|
||||||
|
|
||||||
|
self._panel.SetupScrolling()
|
||||||
|
|
||||||
|
|
||||||
|
class DialogEdit( DialogThatTakesScrollablePanel ):
|
||||||
|
|
||||||
|
def __init__( self, parent, title ):
|
||||||
|
|
||||||
|
DialogThatTakesScrollablePanel.__init__( self, parent, title, 'regular_dialog' )
|
||||||
|
|
||||||
|
|
||||||
|
def EventOk( self, event ):
|
||||||
|
|
||||||
|
SaveTLWSizeAndPosition( self, self._frame_key )
|
||||||
|
|
||||||
|
self.EndModal( wx.ID_OK )
|
||||||
|
|
||||||
|
|
||||||
|
class DialogManage( DialogThatTakesScrollablePanel ):
|
||||||
|
|
||||||
|
def EventOk( self, event ):
|
||||||
|
|
||||||
|
self._panel.CommitChanges()
|
||||||
|
|
||||||
|
SaveTLWSizeAndPosition( self, self._frame_key )
|
||||||
|
|
||||||
|
self.EndModal( wx.ID_OK )
|
||||||
|
|
||||||
|
|
||||||
|
class Frame( wx.Frame ):
|
||||||
|
|
||||||
|
def __init__( self, parent, title, float_on_parent = True ):
|
||||||
|
|
||||||
|
style = wx.DEFAULT_FRAME_STYLE
|
||||||
|
|
||||||
|
if float_on_parent:
|
||||||
|
|
||||||
|
style |= wx.FRAME_FLOAT_ON_PARENT
|
||||||
|
|
||||||
|
|
||||||
|
wx.Frame.__init__( self, parent, title = title, style = style )
|
||||||
|
|
||||||
|
self._new_options = HydrusGlobals.client_controller.GetNewOptions()
|
||||||
|
|
||||||
|
self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ) )
|
||||||
|
|
||||||
|
self.SetIcon( wx.Icon( os.path.join( HC.STATIC_DIR, 'hydrus.ico' ), wx.BITMAP_TYPE_ICO ) )
|
||||||
|
|
||||||
|
HydrusGlobals.client_controller.ResetIdleTimer()
|
||||||
|
|
||||||
|
|
||||||
|
class FrameThatResizes( Frame ):
|
||||||
|
|
||||||
|
def __init__( self, parent, title, frame_key, float_on_parent = True ):
|
||||||
|
|
||||||
|
self._frame_key = frame_key
|
||||||
|
|
||||||
|
Frame.__init__( self, parent, title, float_on_parent )
|
||||||
|
|
||||||
|
self.Bind( wx.EVT_SIZE, self.EventSizeAndPositionChanged )
|
||||||
|
self.Bind( wx.EVT_MOVE_END, self.EventSizeAndPositionChanged )
|
||||||
|
self.Bind( wx.EVT_CLOSE, self.EventSizeAndPositionChanged )
|
||||||
|
self.Bind( wx.EVT_MAXIMIZE, self.EventSizeAndPositionChanged )
|
||||||
|
|
||||||
|
|
||||||
|
def EventSizeAndPositionChanged( self, event ):
|
||||||
|
|
||||||
|
SaveTLWSizeAndPosition( self, self._frame_key )
|
||||||
|
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
|
|
||||||
|
class FrameThatTakesScrollablePanel( FrameThatResizes ):
|
||||||
|
|
||||||
|
def __init__( self, parent, title, frame_key, float_on_parent = True ):
|
||||||
|
|
||||||
|
self._panel = None
|
||||||
|
|
||||||
|
FrameThatResizes.__init__( self, parent, title, frame_key, float_on_parent )
|
||||||
|
|
||||||
|
self._ok = wx.Button( self, label = 'close' )
|
||||||
|
self._ok.Bind( wx.EVT_BUTTON, self.EventCloseButton )
|
||||||
|
|
||||||
|
self.Bind( wx.EVT_MENU, self.EventMenu )
|
||||||
|
self.Bind( CC.EVT_SIZE_CHANGED, self.EventChildSizeChanged )
|
||||||
|
|
||||||
|
|
||||||
|
def EventMenu( self, event ):
|
||||||
|
|
||||||
|
action = ClientCaches.MENU_EVENT_ID_TO_ACTION_CACHE.GetAction( event.GetId() )
|
||||||
|
|
||||||
|
if action is not None:
|
||||||
|
|
||||||
|
( command, data ) = action
|
||||||
|
|
||||||
|
if command == 'ok':
|
||||||
|
|
||||||
|
self.Close()
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def EventCloseButton( self, event ):
|
||||||
|
|
||||||
|
self.Close()
|
||||||
|
|
||||||
|
|
||||||
|
def EventChildSizeChanged( self, event ):
|
||||||
|
|
||||||
|
if self._panel is not None:
|
||||||
|
|
||||||
|
# the min size here is to compensate for wx.Notebook and anything else that don't update virtualsize on page change
|
||||||
|
|
||||||
|
( current_panel_width, current_panel_height ) = self._panel.GetSize()
|
||||||
|
( desired_panel_width, desired_panel_height ) = self._panel.GetVirtualSize()
|
||||||
|
( min_panel_width, min_panel_height ) = self._panel.GetEffectiveMinSize()
|
||||||
|
|
||||||
|
desired_delta_width = max( 0, desired_panel_width - current_panel_width, min_panel_width - current_panel_width )
|
||||||
|
desired_delta_height = max( 0, desired_panel_height - current_panel_height, min_panel_height - current_panel_height )
|
||||||
|
|
||||||
|
if desired_delta_width > 0 or desired_delta_height > 0:
|
||||||
|
|
||||||
|
ExpandTLWIfPossible( self, self._frame_key, ( desired_delta_width, desired_delta_height ) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def SetPanel( self, panel ):
|
||||||
|
|
||||||
|
self._panel = panel
|
||||||
|
|
||||||
|
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||||
|
|
||||||
|
vbox.AddF( self._panel, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||||
|
vbox.AddF( self._ok, CC.FLAGS_LONE_BUTTON )
|
||||||
|
|
||||||
|
self.SetSizer( vbox )
|
||||||
|
|
||||||
|
SetTLWSizeAndPosition( self, self._frame_key )
|
||||||
|
|
||||||
|
self.Show( True )
|
||||||
|
|
||||||
|
self._panel.SetupScrolling()
|
||||||
|
|
||||||
|
|
||||||
|
class ShowKeys( Frame ):
|
||||||
|
|
||||||
|
def __init__( self, key_type, keys ):
|
||||||
|
|
||||||
|
if key_type == 'registration': title = 'Registration Keys'
|
||||||
|
elif key_type == 'access': title = 'Access Keys'
|
||||||
|
|
||||||
|
# give it no parent, so this doesn't close when the dialog is closed!
|
||||||
|
Frame.__init__( self, None, HydrusGlobals.client_controller.PrepStringForDisplay( title ) )
|
||||||
|
|
||||||
|
self._key_type = key_type
|
||||||
|
self._keys = keys
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
self._text_ctrl = wx.TextCtrl( self, style = wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_DONTWRAP )
|
||||||
|
|
||||||
|
self._save_to_file = wx.Button( self, label = 'save to file' )
|
||||||
|
self._save_to_file.Bind( wx.EVT_BUTTON, self.EventSaveToFile )
|
||||||
|
|
||||||
|
self._done = wx.Button( self, label = 'done' )
|
||||||
|
self._done.Bind( wx.EVT_BUTTON, self.EventDone )
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
if key_type == 'registration': prepend = 'r'
|
||||||
|
else: prepend = ''
|
||||||
|
|
||||||
|
self._text = os.linesep.join( [ prepend + key.encode( 'hex' ) for key in self._keys ] )
|
||||||
|
|
||||||
|
self._text_ctrl.SetValue( self._text )
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||||
|
|
||||||
|
vbox.AddF( self._text_ctrl, CC.FLAGS_EXPAND_BOTH_WAYS )
|
||||||
|
vbox.AddF( self._save_to_file, CC.FLAGS_LONE_BUTTON )
|
||||||
|
vbox.AddF( self._done, CC.FLAGS_LONE_BUTTON )
|
||||||
|
|
||||||
|
self.SetSizer( vbox )
|
||||||
|
|
||||||
|
( x, y ) = self.GetEffectiveMinSize()
|
||||||
|
|
||||||
|
if x < 500: x = 500
|
||||||
|
if y < 200: y = 200
|
||||||
|
|
||||||
|
self.SetInitialSize( ( x, y ) )
|
||||||
|
|
||||||
|
self.Show( True )
|
||||||
|
|
||||||
|
|
||||||
|
def EventDone( self, event ):
|
||||||
|
|
||||||
|
self.Close()
|
||||||
|
|
||||||
|
|
||||||
|
def EventSaveToFile( self, event ):
|
||||||
|
|
||||||
|
filename = 'keys.txt'
|
||||||
|
|
||||||
|
with wx.FileDialog( None, style=wx.FD_SAVE, defaultFile = filename ) as dlg:
|
||||||
|
|
||||||
|
if dlg.ShowModal() == wx.ID_OK:
|
||||||
|
|
||||||
|
path = HydrusData.ToUnicode( dlg.GetPath() )
|
||||||
|
|
||||||
|
with open( path, 'wb' ) as f: f.write( HydrusData.ToByteString( self._text ) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -242,21 +242,15 @@ class GalleryImport( HydrusSerialisable.SerialisableBase ):
|
||||||
|
|
||||||
except HydrusExceptions.MimeException as e:
|
except HydrusExceptions.MimeException as e:
|
||||||
|
|
||||||
error_text = HydrusData.ToUnicode( e )
|
|
||||||
|
|
||||||
status = CC.STATUS_UNINTERESTING_MIME
|
status = CC.STATUS_UNINTERESTING_MIME
|
||||||
|
|
||||||
self._seed_cache.UpdateSeedStatus( url, status, note = error_text )
|
self._seed_cache.UpdateSeedStatus( url, status )
|
||||||
|
|
||||||
except Exception:
|
except Exception as e:
|
||||||
|
|
||||||
error_text = traceback.format_exc()
|
|
||||||
|
|
||||||
HydrusData.Print( error_text )
|
|
||||||
|
|
||||||
status = CC.STATUS_FAILED
|
status = CC.STATUS_FAILED
|
||||||
|
|
||||||
self._seed_cache.UpdateSeedStatus( url, status, note = error_text )
|
self._seed_cache.UpdateSeedStatus( url, status, exception = e )
|
||||||
|
|
||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
@ -720,20 +714,15 @@ class HDDImport( HydrusSerialisable.SerialisableBase ):
|
||||||
|
|
||||||
except HydrusExceptions.MimeException as e:
|
except HydrusExceptions.MimeException as e:
|
||||||
|
|
||||||
error_text = HydrusData.ToUnicode( e )
|
|
||||||
|
|
||||||
status = CC.STATUS_UNINTERESTING_MIME
|
status = CC.STATUS_UNINTERESTING_MIME
|
||||||
|
|
||||||
self._paths_cache.UpdateSeedStatus( path, status, note = error_text )
|
self._paths_cache.UpdateSeedStatus( path, status )
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
||||||
error_text = traceback.format_exc()
|
|
||||||
HydrusData.Print( error_text )
|
|
||||||
|
|
||||||
status = CC.STATUS_FAILED
|
status = CC.STATUS_FAILED
|
||||||
|
|
||||||
self._paths_cache.UpdateSeedStatus( path, status, note = error_text )
|
self._paths_cache.UpdateSeedStatus( path, status, exception = e )
|
||||||
|
|
||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
@ -1141,14 +1130,13 @@ class ImportFolder( HydrusSerialisable.SerialisableBaseNamed ):
|
||||||
self._path_cache.UpdateSeedStatus( path, CC.STATUS_UNINTERESTING_MIME )
|
self._path_cache.UpdateSeedStatus( path, CC.STATUS_UNINTERESTING_MIME )
|
||||||
|
|
||||||
|
|
||||||
except Exception:
|
except Exception as e:
|
||||||
|
|
||||||
error_text = traceback.format_exc()
|
error_text = traceback.format_exc()
|
||||||
|
|
||||||
HydrusData.Print( 'A file failed to import from import folder ' + self._name + ':' )
|
HydrusData.Print( 'A file failed to import from import folder ' + self._name + ':' )
|
||||||
HydrusData.Print( error_text )
|
|
||||||
|
|
||||||
self._path_cache.UpdateSeedStatus( path, CC.STATUS_FAILED, note = error_text )
|
self._path_cache.UpdateSeedStatus( path, CC.STATUS_FAILED, exception = e )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1345,20 +1333,15 @@ class PageOfImagesImport( HydrusSerialisable.SerialisableBase ):
|
||||||
|
|
||||||
except HydrusExceptions.MimeException as e:
|
except HydrusExceptions.MimeException as e:
|
||||||
|
|
||||||
error_text = HydrusData.ToUnicode( e )
|
|
||||||
|
|
||||||
status = CC.STATUS_UNINTERESTING_MIME
|
status = CC.STATUS_UNINTERESTING_MIME
|
||||||
|
|
||||||
self._urls_cache.UpdateSeedStatus( file_url, status, note = error_text )
|
self._urls_cache.UpdateSeedStatus( file_url, status )
|
||||||
|
|
||||||
except Exception:
|
except Exception as e:
|
||||||
|
|
||||||
error_text = traceback.format_exc()
|
|
||||||
HydrusData.Print( error_text )
|
|
||||||
|
|
||||||
status = CC.STATUS_FAILED
|
status = CC.STATUS_FAILED
|
||||||
|
|
||||||
self._urls_cache.UpdateSeedStatus( file_url, status, note = error_text )
|
self._urls_cache.UpdateSeedStatus( file_url, status, exception = e )
|
||||||
|
|
||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
@ -1956,10 +1939,22 @@ class SeedCache( HydrusSerialisable.SerialisableBase ):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def UpdateSeedStatus( self, seed, status, note = '' ):
|
def UpdateSeedStatus( self, seed, status, note = '', exception = None ):
|
||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
|
||||||
|
if exception is not None:
|
||||||
|
|
||||||
|
first_line = HydrusData.ToUnicode( exception ).split( os.linesep )[0]
|
||||||
|
|
||||||
|
note = first_line + u'\u2026 (Copy note to see full error)'
|
||||||
|
note += os.linesep
|
||||||
|
note += traceback.format_exc()
|
||||||
|
|
||||||
|
HydrusData.Print( 'Error when processing ' + seed + '!' )
|
||||||
|
HydrusData.Print( traceback.format_exc() )
|
||||||
|
|
||||||
|
|
||||||
note = HydrusData.ToUnicode( note )
|
note = HydrusData.ToUnicode( note )
|
||||||
|
|
||||||
seed_info = self._seeds_to_info[ seed ]
|
seed_info = self._seeds_to_info[ seed ]
|
||||||
|
@ -2173,22 +2168,17 @@ class Subscription( HydrusSerialisable.SerialisableBaseNamed ):
|
||||||
|
|
||||||
except HydrusExceptions.MimeException as e:
|
except HydrusExceptions.MimeException as e:
|
||||||
|
|
||||||
error_text = HydrusData.ToUnicode( e )
|
|
||||||
|
|
||||||
status = CC.STATUS_UNINTERESTING_MIME
|
status = CC.STATUS_UNINTERESTING_MIME
|
||||||
|
|
||||||
self._seed_cache.UpdateSeedStatus( url, status, note = error_text )
|
self._seed_cache.UpdateSeedStatus( url, status )
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
||||||
error_count += 1
|
error_count += 1
|
||||||
|
|
||||||
error_text = traceback.format_exc()
|
|
||||||
HydrusData.Print( error_text )
|
|
||||||
|
|
||||||
status = CC.STATUS_FAILED
|
status = CC.STATUS_FAILED
|
||||||
|
|
||||||
self._seed_cache.UpdateSeedStatus( url, status, note = error_text )
|
self._seed_cache.UpdateSeedStatus( url, status, exception = e )
|
||||||
|
|
||||||
time.sleep( 10 )
|
time.sleep( 10 )
|
||||||
|
|
||||||
|
@ -2646,20 +2636,15 @@ class ThreadWatcherImport( HydrusSerialisable.SerialisableBase ):
|
||||||
|
|
||||||
except HydrusExceptions.MimeException as e:
|
except HydrusExceptions.MimeException as e:
|
||||||
|
|
||||||
error_text = HydrusData.ToUnicode( e )
|
|
||||||
|
|
||||||
status = CC.STATUS_UNINTERESTING_MIME
|
status = CC.STATUS_UNINTERESTING_MIME
|
||||||
|
|
||||||
self._urls_cache.UpdateSeedStatus( file_url, status, note = error_text )
|
self._urls_cache.UpdateSeedStatus( file_url, status )
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
||||||
error_text = traceback.format_exc()
|
|
||||||
HydrusData.Print( error_text )
|
|
||||||
|
|
||||||
status = CC.STATUS_FAILED
|
status = CC.STATUS_FAILED
|
||||||
|
|
||||||
self._urls_cache.UpdateSeedStatus( file_url, status, note = error_text )
|
self._urls_cache.UpdateSeedStatus( file_url, status, exception = e )
|
||||||
|
|
||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
|
|
@ -48,7 +48,7 @@ options = {}
|
||||||
# Misc
|
# Misc
|
||||||
|
|
||||||
NETWORK_VERSION = 17
|
NETWORK_VERSION = 17
|
||||||
SOFTWARE_VERSION = 213
|
SOFTWARE_VERSION = 214
|
||||||
|
|
||||||
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||||
|
|
||||||
|
|
|
@ -1829,26 +1829,13 @@ class JobDatabase( object ):
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
if self._result_ready.wait( 5 ) == True: break
|
if self._result_ready.wait( 2 ) == True: break
|
||||||
elif HydrusGlobals.model_shutdown: raise HydrusExceptions.ShutdownException( 'Application quit before db could serve result!' )
|
elif HydrusGlobals.model_shutdown: raise HydrusExceptions.ShutdownException( 'Application quit before db could serve result!' )
|
||||||
|
|
||||||
|
|
||||||
if isinstance( self._result, Exception ):
|
if isinstance( self._result, Exception ):
|
||||||
|
|
||||||
if isinstance( self._result, HydrusExceptions.DBException ):
|
raise self._result
|
||||||
|
|
||||||
( text, gumpf, db_traceback ) = self._result.args
|
|
||||||
|
|
||||||
trace_list = traceback.format_stack()
|
|
||||||
|
|
||||||
caller_traceback = 'Stack Trace (most recent call last):' + os.linesep * 2 + os.linesep.join( trace_list )
|
|
||||||
|
|
||||||
raise HydrusExceptions.DBException( text, caller_traceback, db_traceback )
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
raise self._result
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
|
import os
|
||||||
|
|
||||||
class CantRenderWithCVException( Exception ): pass
|
class CantRenderWithCVException( Exception ): pass
|
||||||
class DataMissing( Exception ): pass
|
class DataMissing( Exception ): pass
|
||||||
class DBException( Exception ): pass
|
|
||||||
|
class DBException( Exception ):
|
||||||
|
|
||||||
|
def __str__( self ):
|
||||||
|
|
||||||
|
return os.linesep.join( self.args )
|
||||||
|
|
||||||
|
|
||||||
class DBAccessException( Exception ): pass
|
class DBAccessException( Exception ): pass
|
||||||
class FileMissingException( Exception ): pass
|
class FileMissingException( Exception ): pass
|
||||||
class MimeException( Exception ): pass
|
class MimeException( Exception ): pass
|
||||||
|
|
|
@ -151,7 +151,7 @@ def Hydrusffmpeg_parse_infos(filename, print_infos=False):
|
||||||
|
|
||||||
if 'start:' in line:
|
if 'start:' in line:
|
||||||
|
|
||||||
m = re.search( '(start\\: )' + '[0-9]\\.[0-9]*', line )
|
m = re.search( '(start\\: )' + '-?[0-9]\\.[0-9]*', line )
|
||||||
|
|
||||||
start_offset = float( line[ m.start() + 7 : m.end() ] )
|
start_offset = float( line[ m.start() + 7 : m.end() ] )
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue