Version 126
|
@ -8,6 +8,24 @@
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h3>changelog</h3>
|
<h3>changelog</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li><h3>version 126</h3></li>
|
||||||
|
<ul>
|
||||||
|
<li>restored a dll that I thought was no longer needed, but was actually doing some weirder gif rendering</li>
|
||||||
|
<li>added 'remove' to fullscreen menu</li>
|
||||||
|
<li>harmonised thumbnail and fullscreen right click menus a bit more</li>
|
||||||
|
<li>added pause button to popup messages for repo update and subscription processing</li>
|
||||||
|
<li>moved service_identifier switchover forward</li>
|
||||||
|
<li>moved all service fetching to streamlined and non-laggy manager</li>
|
||||||
|
<li>changed client options to store default tag repository in a better way</li>
|
||||||
|
<li>changed subscriptions to store their advanced tag options in a better way</li>
|
||||||
|
<li>fixed a 'missing service' bug in advanced tag options</li>
|
||||||
|
<li>remade idle calculation into a much better gui-based rather than db-based test</li>
|
||||||
|
<li>fiddled more with maintenance timing, hopefully for the good</li>
|
||||||
|
<li>new screenshots in the help index pages!</li>
|
||||||
|
<li>improved how auto repo and server setup work and report their status</li>
|
||||||
|
<li>the client's UPnP daemon will no longer spam errors if your IGD doesn't support UPnP</li>
|
||||||
|
<li>fixed a bad db call in server's UPnP daemon</li>
|
||||||
|
</ul>
|
||||||
<li><h3>version 125</h3></li>
|
<li><h3>version 125</h3></li>
|
||||||
<ul>
|
<ul>
|
||||||
<li>moved client splash screen and client boot to application event loop (i.e. your mouse won't hourglass over it now)</li>
|
<li>moved client splash screen and client boot to application event loop (i.e. your mouse won't hourglass over it now)</li>
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
<p>Because hydrus stores everything inside itself, it is entirely portable. You can extract it to a usb stick, move it from one place to another, have multiple installs for multiple purposes, wrap it all up inside a truecrypt volume, whatever you like. The .exe installer will write some unavoidable uninstall registry stuff to windows that'll mess with this, but the client itself will run fine in a different location.</p>
|
<p>Because hydrus stores everything inside itself, it is entirely portable. You can extract it to a usb stick, move it from one place to another, have multiple installs for multiple purposes, wrap it all up inside a truecrypt volume, whatever you like. The .exe installer will write some unavoidable uninstall registry stuff to windows that'll mess with this, but the client itself will run fine in a different location.</p>
|
||||||
<h3>updating</h3>
|
<h3>updating</h3>
|
||||||
<p>You don't <i>have</i> to update every week, but I generally recommend it. The different versions of client and server can talk with each other until I increment the private <i>network protocol version</i> (which happens every couple of months), at which point you will get polite error messages if you try to connect to a newer server with an older client or <i>vice versa</i>. Read my tumblr posts and judge for yourself what you want to do.</p>
|
<p>You don't <i>have</i> to update every week, but I generally recommend it. The different versions of client and server can talk with each other until I increment the private <i>network protocol version</i> (which happens every couple of months), at which point you will get polite error messages if you try to connect to a newer server with an older client or <i>vice versa</i>. Read my tumblr posts and judge for yourself what you want to do.</p>
|
||||||
<p>All your files and settings and synchronisation progress will be remembered after the update. Unless the update specifically disables something, nothing will be deleted or lost.</p>
|
|
||||||
<p>Whenever you start the client, it checks the version of its database. If the database is old, it makes the appropriate changes, in sequential order (i.e. to do v70->v75, the client would first apply v70->v71, then v71->v72 and so on), until the database is caught up.</p>
|
|
||||||
<p>If the client you want to update is running, remember to close it first!</p>
|
<p>If the client you want to update is running, remember to close it first!</p>
|
||||||
<p>If you use the installer, just download the new installer and run it. It should detect where the last install was and overwrite everything automatically.</p>
|
<p>If you use the installer, just download the new installer and run it. It should detect where the last install was and overwrite everything automatically.</p>
|
||||||
<p>If you extract, then just extract right on top of your current install and overwrite manually. Then run client.exe as normal.</p>
|
<p>If you extract, then just extract right on top of your current install and overwrite manually. Then run client.exe as normal.</p>
|
||||||
|
<p>All your files and settings and synchronisation progress will be remembered after the update. Unless the update specifically disables something, nothing will be deleted or lost.</p>
|
||||||
|
<p>Whenever you start the client, it checks the version of its database. If the database is old, it makes the appropriate changes, in sequential order (i.e. to do v70->v75, the client would first apply v70->v71, then v71->v72 and so on), until the database is caught up. If this process will take a while (like an hour, sometimes!) I will say so in my tumblr post.</p>
|
||||||
<h3>backing up</h3>
|
<h3>backing up</h3>
|
||||||
<p>You <i>do</i> backup, right? <i>Right</i>?</p>
|
<p>You <i>do</i> backup, right? <i>Right</i>?</p>
|
||||||
<p>I run a backup every week so that if my computer blows up, I'll at worst have lost a few days' work. Before I had a backup regime, I once lost an entire drive with tens of thousands of files, and it didn't feel great at all. I only push backups so hard so you might avoid what I felt. ;_;</p>
|
<p>I run a backup every week so that if my computer blows up, I'll at worst have lost a few days' work. Before I had a backup regime, I once lost an entire drive with tens of thousands of files, and it didn't feel great at all. I only push backups so hard so you might avoid what I felt. ;_;</p>
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
<p>If you want to backup hydrus, you can either go <i>database->create database backup</i> or just shut the client down and copy the entire install directory somewhere.</p>
|
<p>If you want to backup hydrus, you can either go <i>database->create database backup</i> or just shut the client down and copy the entire install directory somewhere.</p>
|
||||||
<p>I recommend you do it before you update, just in case there is a problem with my code that breaks your database. If that happens, please <a href="contact.html">contact me</a>, describing the problem, and revert to the functioning older version. I'll get on any problems like that immediately.</p>
|
<p>I recommend you do it before you update, just in case there is a problem with my code that breaks your database. If that happens, please <a href="contact.html">contact me</a>, describing the problem, and revert to the functioning older version. I'll get on any problems like that immediately.</p>
|
||||||
<h3>linux and os x</h3>
|
<h3>linux and os x</h3>
|
||||||
<p>I now make an OS X release, although it is very prototype. A linux release should follow in a few weeks.</p>
|
<p>I now make OS X and Linux releases. They are not as good as the Windows releases because I am not as experienced in their OSs' weirdnesses. When I find time, I improve them.</p>
|
||||||
<p class="right"><a href="getting_started_files.html">Let's import some files! ----></a></p>
|
<p class="right"><a href="getting_started_files.html">Let's import some files! ----></a></p>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -5,13 +5,14 @@
|
||||||
<link href="style.css" rel="stylesheet" type="text/css" />
|
<link href="style.css" rel="stylesheet" type="text/css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a class="screenshot" href="client_empty.png" title="the main screen, just after you start up"><img src="client_empty_small.png" /></a>
|
<a class="screenshot" href="screenshot_empty.png" title="an empty page. you can search in many ways, not just tags"><img src="screenshot_empty_thumb.png" /></a>
|
||||||
<a class="screenshot" href="client_autism.png" title="an example search"><img src="client_autism_small.png" /></a>
|
<a class="screenshot" href="screenshot_general_search.png" title="a normal tag search"><img src="screenshot_general_search_thumb.png" /></a>
|
||||||
<a class="screenshot" href="lib_gc.png" title="a well-tagged webcomic, sorted and viewed by chapter"><img src="lib_gc_small.png" /></a>
|
<a class="screenshot" href="screenshot_big_search.png" title="the client can easily search, display and manage thousands of files"><img src="screenshot_big_search_thumb.png" /></a>
|
||||||
<a class="screenshot" href="client_fullscreen.png" title="reading the webcomic in fullscreen"><img src="client_fullscreen_small.png" /></a>
|
<a class="screenshot" href="screenshot_gunnerkrigg_collect.png" title="files can be sorted and collected by their tags"><img src="screenshot_gunnerkrigg_collect_thumb.png" /></a>
|
||||||
<a class="screenshot" href="lib_rec.png" title="file repository view, with some files local and some not"><img src="lib_rec_small.png" /></a>
|
<a class="screenshot" href="screenshot_fullscreen_blame.png" title="fullscreen view is clean and fast"><img src="screenshot_fullscreen_blame_thumb.png" /></a>
|
||||||
<a class="screenshot" href="lib_party_hard.png" title="now with swf support!"><img src="lib_party_hard_small.png" /></a>
|
<a class="screenshot" href="screenshot_video.png" title="many file formats are supported"><img src="screenshot_video_thumb.png" /></a>
|
||||||
<a class="screenshot" href="client_auto.png" title="an example of tag-autocomplete, which only displays results applicable to the current query"><img src="client_auto_small.png" /></a>
|
<a class="screenshot" href="screenshot_booru.png" title="you can run your own (simple!) booru"><img src="screenshot_booru_thumb.png" /></a>
|
||||||
|
<a class="screenshot" href="screenshot_advanced_autocomplete.png" title="the tag autocomplete is a powerful tool that can get complicated if you want it to. this screenshot shows a tag sibling, where one tag is immediately swapped with another, and a non-local search, where results that are known but not on the computer are shown"><img src="screenshot_advanced_autocomplete_thumb.png" /></a>
|
||||||
<h3>hydrus help</h3>
|
<h3>hydrus help</h3>
|
||||||
<p>Although I've tried to make hydrus's interface simple, its underlying concepts are not. Please read the introduction and skim the getting started guide at the least, and if you want to get started with my server, you'll probably want to check out the access keys section.</p>
|
<p>Although I've tried to make hydrus's interface simple, its underlying concepts are not. Please read the introduction and skim the getting started guide at the least, and if you want to get started with my server, you'll probably want to check out the access keys section.</p>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -8,23 +8,23 @@
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<h3>on being anonymous</h3>
|
<h3>on being anonymous</h3>
|
||||||
<p>I am convinced that having the option of anonymous speech is extremely valuable to the modern development of free culture and society.</p>
|
<p>I am convinced that having the option of anonymous speech is extremely valuable to the modern development of free culture and society.</p>
|
||||||
<p>When people have no fear of personal repercussion, they can reveal corruptions and admit truths they otherwise never would. Their words are insightful and stupid, convincing and hurtful, hilarious and ridiculous. Try it; it's fun!</p>
|
<p>When people do not have to fear personal repercussion, they can reveal corruptions and admit truths they otherwise never would. Their words are insightful and stupid, convincing and hurtful, hilarious and ridiculous. It's fun!</p>
|
||||||
<p>Nearly all forums and social networking platforms use the same pseudonymous username/password archetype, and nearly all of them have the same problems with drama, sockpuppets, and egotistical mods. Sometimes the price is worth it, and sometimes it is not.</p>
|
<p>Nearly all forums and social networking platforms use the same pseudonymous username/password system, and nearly all of them have the same problems with drama, sockpuppets, and egotistical mods. Sometimes the price is worth it, and sometimes it is not.</p>
|
||||||
<p>I think people should have the <i>option</i> to interact with others anonymously if they wish, and further should always have the choice to filter or entirely block anonymously submitted content (or anything else!). I want people to decide for themselves what they see, not anyone else.</p>
|
<p>I think people should have the <i>option</i> to interact with others anonymously if they wish, and further should always have the choice to filter or entirely block anonymously submitted content (or anything else!). I want people to decide for themselves what they see, not anyone else.</p>
|
||||||
<p>There are several online platforms that support anonymity, usually through a web browser, but most have terribly inefficient code, and their actual anonymity is often impotent window dressing, an afterthought. Logs of IP addresses are kept routinely, available for any admin (or anyone else who gains access to the server) to peruse.</p>
|
<p>There are several online platforms that support anonymity, usually through a web browser, but most have terribly inefficient code, and their actual anonymity is unreliable. Logs of IP addresses are kept routinely, available for any admin (or anyone else who gains access to the server) to peruse.</p>
|
||||||
<p>I think we can do better.</p>
|
<p>I think we can do better.</p>
|
||||||
<h3>the hydrus network</h3>
|
<h3>the hydrus network</h3>
|
||||||
<p>So! I'm developing a program that helps people manage their files together anonymously. My primary concern is in enabling you to do what you want with your stuff, and that's it. You can share tags and files with other people, but you don't have to connect to anything if you don't want to. I don't plan to ever record metrics on users, nor serve ads, nor charge for my software.</p>
|
<p>So! I'm developing a program that helps people manage their files together anonymously. I want to help you do what you want with your stuff, and that's it. You can share tags and files with other people, but you don't have to connect to anything if you don't want to. The default is <b>no sharing</b>. I don't plan to ever record metrics on users, nor serve ads, nor charge for my software.</p>
|
||||||
<p>There are a number of new concepts involved, and it can get as complicated as you like. If you are totally new to the idea of personal media collections and tagging, I advise you start slow, walk through the getting started guides, and experiment doing different things. You'll be importing thousands of files and applying <i>tens</i> of thousands of tags in no time.</p>
|
<p>There are a number of new concepts involved, and it can get as complicated as you like. If you are totally new to the idea of personal media collections and tagging, I advise you start slow, walk through the getting started guides, and experiment doing different things. You'll be importing thousands of files and applying <i>tens</i> of thousands of tags in no time.</p>
|
||||||
<p>The client is chiefly a file database. It manages your media far better than an explorer window. Here's a screenshot of one of my test installs with a very general search:</p>
|
<p>The client is chiefly a file database. It manages your media far better than an explorer window or some online gallery. Here's a screenshot of one of my test installs with a very general search:</p>
|
||||||
<p><a href="example_client.png"><img src="example_client.png" width="960" height="540" title="WELCOME TO INTERNET" /></a></p>
|
<p><a href="example_client.png"><img src="example_client.png" width="960" height="540" title="WELCOME TO INTERNET" /></a></p>
|
||||||
<p>There is also a server that anyone can run to store files or tags for sharing between many users. I run a tag service with several million tags that you are welcome to access and contribute to.</p>
|
<p>As well as the client, there is also a server that anyone can run to store files or tags for sharing between many users. I run a tag service with several million tags that you are welcome to access and contribute to.</p>
|
||||||
<p>I'm working on adding peer-to-peer anonymous communication.</p>
|
<p>I'm working on adding peer-to-peer anonymous communication.</p>
|
||||||
<h3>statement of principles</h3>
|
<h3>statement of principles</h3>
|
||||||
<ul class="bulletpoint">
|
<ul class="bulletpoint">
|
||||||
<li>No speech should be outlawed.</li>
|
<li>No speech should be outlawed.</li>
|
||||||
<li>Everyone should be able to control their own media diet.</li>
|
<li>Everyone should be able to control their own media diet.</li>
|
||||||
<li>The data on someone's computer and the logs of their network activity should be absolutely private.</li>
|
<li>Computer data and network logs should be absolutely private.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>None of the above are currently true, but I would love to live in a world where they were. My software is an attempt to move us a little closer.</p>
|
<p>None of the above are currently true, but I would love to live in a world where they were. My software is an attempt to move us a little closer.</p>
|
||||||
<p>I try to side with the person over the authority, the distributed over the centralised. I still use gmail and youtube just like pretty much everyone, but I would rather be using different systems, especially in ten years. No one seemed to be making what I wanted, so I decided to do it myself, and here we are.</p>
|
<p>I try to side with the person over the authority, the distributed over the centralised. I still use gmail and youtube just like pretty much everyone, but I would rather be using different systems, especially in ten years. No one seemed to be making what I wanted, so I decided to do it myself, and here we are.</p>
|
||||||
|
|
After Width: | Height: | Size: 409 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 2.0 MiB |
After Width: | Height: | Size: 133 KiB |
After Width: | Height: | Size: 2.2 MiB |
After Width: | Height: | Size: 123 KiB |
After Width: | Height: | Size: 37 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 2.3 MiB |
After Width: | Height: | Size: 107 KiB |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 124 KiB |
After Width: | Height: | Size: 324 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 411 KiB |
After Width: | Height: | Size: 49 KiB |
|
@ -283,7 +283,7 @@ CLIENT_DEFAULT_OPTIONS[ 'shortcuts' ] = shortcuts
|
||||||
|
|
||||||
CLIENT_DEFAULT_OPTIONS[ 'confirm_client_exit' ] = False
|
CLIENT_DEFAULT_OPTIONS[ 'confirm_client_exit' ] = False
|
||||||
|
|
||||||
CLIENT_DEFAULT_OPTIONS[ 'default_tag_repository' ] = HC.LOCAL_TAG_SERVICE_IDENTIFIER
|
CLIENT_DEFAULT_OPTIONS[ 'default_tag_repository' ] = HC.LOCAL_TAG_SERVICE_KEY
|
||||||
CLIENT_DEFAULT_OPTIONS[ 'default_tag_sort' ] = SORT_BY_LEXICOGRAPHIC_ASC
|
CLIENT_DEFAULT_OPTIONS[ 'default_tag_sort' ] = SORT_BY_LEXICOGRAPHIC_ASC
|
||||||
|
|
||||||
CLIENT_DEFAULT_OPTIONS[ 'pause_export_folders_sync' ] = False
|
CLIENT_DEFAULT_OPTIONS[ 'pause_export_folders_sync' ] = False
|
||||||
|
@ -1160,7 +1160,7 @@ class LocalBooruCache( object ):
|
||||||
|
|
||||||
def _RefreshShares( self ):
|
def _RefreshShares( self ):
|
||||||
|
|
||||||
self._local_booru_service = HC.app.Read( 'service', HC.LOCAL_BOORU_SERVICE_IDENTIFIER )
|
self._local_booru_service = HC.app.GetManager( 'services' ).GetService( HC.LOCAL_BOORU_SERVICE_IDENTIFIER.GetServiceKey() )
|
||||||
|
|
||||||
self._keys_to_infos = {}
|
self._keys_to_infos = {}
|
||||||
|
|
||||||
|
@ -2293,6 +2293,8 @@ class Service( HC.HydrusYAMLBase ):
|
||||||
self._name = name
|
self._name = name
|
||||||
self._info = info
|
self._info = info
|
||||||
|
|
||||||
|
self._lock = threading.Lock()
|
||||||
|
|
||||||
HC.pubsub.sub( self, 'ProcessServiceUpdates', 'service_updates_data' )
|
HC.pubsub.sub( self, 'ProcessServiceUpdates', 'service_updates_data' )
|
||||||
|
|
||||||
|
|
||||||
|
@ -2565,29 +2567,14 @@ class ServiceManager( object ):
|
||||||
HC.pubsub.sub( self, 'RefreshServices', 'notify_new_services_data' )
|
HC.pubsub.sub( self, 'RefreshServices', 'notify_new_services_data' )
|
||||||
|
|
||||||
|
|
||||||
def GetName( self, service_key ):
|
|
||||||
|
|
||||||
with self._lock:
|
|
||||||
|
|
||||||
service = self._keys_to_services[ service_key ]
|
|
||||||
|
|
||||||
return service.GetName()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def GetService( self, service_key ):
|
def GetService( self, service_key ):
|
||||||
|
|
||||||
with self._lock: return self._keys_to_services[ service_key ]
|
with self._lock: return self._keys_to_services[ service_key ]
|
||||||
|
|
||||||
|
|
||||||
def GetType( self, service_key ):
|
def GetServices( self, types = HC.ALL_SERVICES ):
|
||||||
|
|
||||||
with self._lock:
|
with self._lock: return [ service for service in self._keys_to_services.values() if service.GetType() in types ]
|
||||||
|
|
||||||
service = self._keys_to_services[ service_key ]
|
|
||||||
|
|
||||||
return service.GetType()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def RefreshServices( self ):
|
def RefreshServices( self ):
|
||||||
|
|
|
@ -31,7 +31,7 @@ from twisted.internet import defer
|
||||||
ID_ANIMATED_EVENT_TIMER = wx.NewId()
|
ID_ANIMATED_EVENT_TIMER = wx.NewId()
|
||||||
ID_MAINTENANCE_EVENT_TIMER = wx.NewId()
|
ID_MAINTENANCE_EVENT_TIMER = wx.NewId()
|
||||||
|
|
||||||
MAINTENANCE_PERIOD = 12 * 60
|
MAINTENANCE_PERIOD = 5 * 60
|
||||||
|
|
||||||
class Controller( wx.App ):
|
class Controller( wx.App ):
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ The database will be locked while the backup occurs, which may lock up your gui
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def CurrentlyIdle( self ): return HC.GetNow() - self._timestamps[ 'last_user_db_use' ] > 30 * 60 # 30 mins since last user-initiated media_results query
|
def CurrentlyIdle( self ): return HC.GetNow() - self._timestamps[ 'last_user_action' ] > 30 * 60 # 30 mins since last canvas media swap
|
||||||
|
|
||||||
def EventPubSub( self, event ):
|
def EventPubSub( self, event ):
|
||||||
|
|
||||||
|
@ -208,9 +208,10 @@ The database will be locked while the backup occurs, which may lock up your gui
|
||||||
|
|
||||||
self._managers = {}
|
self._managers = {}
|
||||||
|
|
||||||
|
self._managers[ 'services' ] = CC.ServiceManager()
|
||||||
|
|
||||||
self._managers[ 'hydrus_sessions' ] = HydrusSessions.HydrusSessionManagerClient()
|
self._managers[ 'hydrus_sessions' ] = HydrusSessions.HydrusSessionManagerClient()
|
||||||
self._managers[ 'local_booru' ] = CC.LocalBooruCache()
|
self._managers[ 'local_booru' ] = CC.LocalBooruCache()
|
||||||
self._managers[ 'services' ] = CC.ServiceManager()
|
|
||||||
self._managers[ 'tag_censorship' ] = HydrusTags.TagCensorshipManager()
|
self._managers[ 'tag_censorship' ] = HydrusTags.TagCensorshipManager()
|
||||||
self._managers[ 'tag_siblings' ] = HydrusTags.TagSiblingsManager()
|
self._managers[ 'tag_siblings' ] = HydrusTags.TagSiblingsManager()
|
||||||
self._managers[ 'tag_parents' ] = HydrusTags.TagParentsManager()
|
self._managers[ 'tag_parents' ] = HydrusTags.TagParentsManager()
|
||||||
|
@ -265,9 +266,9 @@ The database will be locked while the backup occurs, which may lock up your gui
|
||||||
|
|
||||||
HC.pubsub.pub( 'set_splash_text', 'fattening service info' )
|
HC.pubsub.pub( 'set_splash_text', 'fattening service info' )
|
||||||
|
|
||||||
service_identifiers = self.Read( 'service_identifiers' )
|
services = self.GetManager( 'services' ).GetServices()
|
||||||
|
|
||||||
for service_identifier in service_identifiers: self.Read( 'service_info', service_identifier )
|
for service in services: self.Read( 'service_info', service.GetKey() )
|
||||||
|
|
||||||
self._timestamps[ 'service_info_cache_fatten' ] = HC.GetNow()
|
self._timestamps[ 'service_info_cache_fatten' ] = HC.GetNow()
|
||||||
|
|
||||||
|
@ -314,12 +315,7 @@ The database will be locked while the backup occurs, which may lock up your gui
|
||||||
else: return text.lower()
|
else: return text.lower()
|
||||||
|
|
||||||
|
|
||||||
def Read( self, action, *args, **kwargs ):
|
def Read( self, action, *args, **kwargs ): return self._Read( action, *args, **kwargs )
|
||||||
|
|
||||||
if action == 'media_results': self._timestamps[ 'last_user_db_use' ] = HC.GetNow()
|
|
||||||
|
|
||||||
return self._Read( action, *args, **kwargs )
|
|
||||||
|
|
||||||
|
|
||||||
def ReadDaemon( self, action, *args, **kwargs ):
|
def ReadDaemon( self, action, *args, **kwargs ):
|
||||||
|
|
||||||
|
@ -330,9 +326,11 @@ The database will be locked while the backup occurs, which may lock up your gui
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def ResetIdleTimer( self ): self._timestamps[ 'last_user_action' ] = HC.GetNow()
|
||||||
|
|
||||||
def RestartBooru( self ):
|
def RestartBooru( self ):
|
||||||
|
|
||||||
service = self.Read( 'service', HC.LOCAL_BOORU_SERVICE_IDENTIFIER )
|
service = self.GetManager( 'services' ).GetService( HC.LOCAL_BOORU_SERVICE_IDENTIFIER.GetServiceKey() )
|
||||||
|
|
||||||
info = service.GetInfo()
|
info = service.GetInfo()
|
||||||
|
|
||||||
|
@ -506,7 +504,7 @@ Once it is done, the client will restart.'''
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
query_hash_ids = HC.app.Read( 'file_query_ids', search_context )
|
query_hash_ids = self.Read( 'file_query_ids', search_context )
|
||||||
|
|
||||||
query_hash_ids = list( query_hash_ids )
|
query_hash_ids = list( query_hash_ids )
|
||||||
|
|
||||||
|
@ -537,13 +535,13 @@ Once it is done, the client will restart.'''
|
||||||
|
|
||||||
sub_query_hash_ids = query_hash_ids[ last_i : i ]
|
sub_query_hash_ids = query_hash_ids[ last_i : i ]
|
||||||
|
|
||||||
more_media_results = HC.app.Read( 'media_results_from_ids', file_service_identifier, sub_query_hash_ids )
|
more_media_results = self.Read( 'media_results_from_ids', file_service_identifier, sub_query_hash_ids )
|
||||||
|
|
||||||
media_results.extend( more_media_results )
|
media_results.extend( more_media_results )
|
||||||
|
|
||||||
HC.pubsub.pub( 'set_num_query_results', len( media_results ), len( query_hash_ids ) )
|
HC.pubsub.pub( 'set_num_query_results', len( media_results ), len( query_hash_ids ) )
|
||||||
|
|
||||||
HC.app.WaitUntilGoodTimeToUseGUIThread()
|
self.WaitUntilGoodTimeToUseGUIThread()
|
||||||
|
|
||||||
|
|
||||||
HC.pubsub.pub( 'file_query_done', query_key, media_results )
|
HC.pubsub.pub( 'file_query_done', query_key, media_results )
|
||||||
|
@ -558,7 +556,7 @@ Once it is done, the client will restart.'''
|
||||||
self._timestamps[ 'last_check_idle_time' ] = HC.GetNow()
|
self._timestamps[ 'last_check_idle_time' ] = HC.GetNow()
|
||||||
|
|
||||||
# this tests if we probably just woke up from a sleep
|
# this tests if we probably just woke up from a sleep
|
||||||
if HC.GetNow() - last_time_this_ran > MAINTENANCE_PERIOD * 1.2: return
|
if HC.GetNow() - last_time_this_ran > MAINTENANCE_PERIOD + ( 5 * 60 ): return
|
||||||
|
|
||||||
if self.CurrentlyIdle(): self.MaintainDB()
|
if self.CurrentlyIdle(): self.MaintainDB()
|
||||||
|
|
||||||
|
|
|
@ -1316,11 +1316,7 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
c.execute( 'REPLACE INTO hydrus_sessions ( service_id, session_key, expiry ) VALUES ( ?, ?, ? );', ( service_id, sqlite3.Binary( session_key ), expiry ) )
|
c.execute( 'REPLACE INTO hydrus_sessions ( service_id, session_key, expiry ) VALUES ( ?, ?, ? );', ( service_id, sqlite3.Binary( session_key ), expiry ) )
|
||||||
|
|
||||||
|
|
||||||
def _AddService( self, c, service_identifier, info ):
|
def _AddService( self, c, service_key, service_type, name, info ):
|
||||||
|
|
||||||
service_key = service_identifier.GetServiceKey()
|
|
||||||
service_type = service_identifier.GetType()
|
|
||||||
name = service_identifier.GetName()
|
|
||||||
|
|
||||||
if service_type in HC.LOCAL_SERVICES:
|
if service_type in HC.LOCAL_SERVICES:
|
||||||
|
|
||||||
|
@ -2497,10 +2493,6 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
|
|
||||||
service_type = service_identifier.GetType()
|
service_type = service_identifier.GetType()
|
||||||
|
|
||||||
repository = self._GetService( c, service_id )
|
|
||||||
|
|
||||||
account = repository.GetInfo( 'account' )
|
|
||||||
|
|
||||||
if service_type == HC.TAG_REPOSITORY:
|
if service_type == HC.TAG_REPOSITORY:
|
||||||
|
|
||||||
updates = []
|
updates = []
|
||||||
|
@ -2657,57 +2649,30 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
return reason_id
|
return reason_id
|
||||||
|
|
||||||
|
|
||||||
def _GetService( self, c, parameter ):
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
if type( parameter ) == int: service_id = parameter
|
|
||||||
elif type( parameter ) == HC.ClientServiceIdentifier: service_id = self._GetServiceId( c, parameter )
|
|
||||||
|
|
||||||
except: raise Exception( 'Service error in database.' )
|
|
||||||
|
|
||||||
result = c.execute( 'SELECT service_key, service_type, name, info FROM services WHERE service_id = ?;', ( service_id, ) ).fetchone()
|
|
||||||
|
|
||||||
if result is None: raise Exception( 'Service error in database.' )
|
|
||||||
|
|
||||||
( service_key, service_type, name, info ) = result
|
|
||||||
|
|
||||||
service = CC.Service( service_key, service_type, name, info )
|
|
||||||
|
|
||||||
return service
|
|
||||||
|
|
||||||
|
|
||||||
def _GetServices( self, c, limited_types = HC.ALL_SERVICES ):
|
def _GetServices( self, c, limited_types = HC.ALL_SERVICES ):
|
||||||
|
|
||||||
service_ids = [ service_id for ( service_id, ) in c.execute( 'SELECT service_id FROM services WHERE service_type IN ' + HC.SplayListForDB( limited_types ) + ';' ) ]
|
services = []
|
||||||
|
|
||||||
services = [ self._GetService( c, service_id ) for service_id in service_ids ]
|
for result in c.execute( 'SELECT service_key, service_type, name, info FROM services WHERE service_type IN ' + HC.SplayListForDB( limited_types ) + ';' ):
|
||||||
|
|
||||||
|
( service_key, service_type, name, info ) = result
|
||||||
|
|
||||||
|
services.append( CC.Service( service_key, service_type, name, info ) )
|
||||||
|
|
||||||
|
|
||||||
return services
|
return services
|
||||||
|
|
||||||
|
|
||||||
def _GetServiceId( self, c, parameter ):
|
def _GetServiceId( self, c, parameter ):
|
||||||
|
|
||||||
if type( parameter ) in ( str, unicode ):
|
if type( parameter ) == HC.ClientServiceIdentifier: service_key = parameter.GetServiceKey()
|
||||||
|
else: service_key = parameter
|
||||||
result = c.execute( 'SELECT service_id FROM services WHERE name = ?;', ( parameter, ) ).fetchone()
|
|
||||||
|
result = c.execute( 'SELECT service_id FROM services WHERE service_key = ?;', ( sqlite3.Binary( service_key ), ) ).fetchone()
|
||||||
if result is None: raise Exception( 'Service id error in database' )
|
|
||||||
|
if result is None: raise Exception( 'Service id error in database' )
|
||||||
( service_id, ) = result
|
|
||||||
|
( service_id, ) = result
|
||||||
elif type( parameter ) == HC.ClientServiceIdentifier:
|
|
||||||
|
|
||||||
service_type = parameter.GetType()
|
|
||||||
|
|
||||||
service_key = parameter.GetServiceKey()
|
|
||||||
|
|
||||||
result = c.execute( 'SELECT service_id FROM services WHERE service_key = ?;', ( sqlite3.Binary( service_key ), ) ).fetchone()
|
|
||||||
|
|
||||||
if result is None: raise Exception( 'Service id error in database' )
|
|
||||||
|
|
||||||
( service_id, ) = result
|
|
||||||
|
|
||||||
|
|
||||||
return service_id
|
return service_id
|
||||||
|
|
||||||
|
@ -2727,11 +2692,11 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
|
|
||||||
def _GetServiceIdentifiers( self, c, limited_types = HC.ALL_SERVICES ): return { HC.ClientServiceIdentifier( service_key, service_type, name ) for ( service_key, service_type, name ) in c.execute( 'SELECT service_key, service_type, name FROM services WHERE service_type IN ' + HC.SplayListForDB( limited_types ) + ';' ) }
|
def _GetServiceIdentifiers( self, c, limited_types = HC.ALL_SERVICES ): return { HC.ClientServiceIdentifier( service_key, service_type, name ) for ( service_key, service_type, name ) in c.execute( 'SELECT service_key, service_type, name FROM services WHERE service_type IN ' + HC.SplayListForDB( limited_types ) + ';' ) }
|
||||||
|
|
||||||
def _GetServiceInfo( self, c, service_identifier ):
|
def _GetServiceInfo( self, c, service_key ):
|
||||||
|
|
||||||
service_id = self._GetServiceId( c, service_identifier )
|
service_id = self._GetServiceId( c, service_key )
|
||||||
|
|
||||||
service_type = service_identifier.GetType()
|
service_type = self._GetServiceType( c, service_id )
|
||||||
|
|
||||||
if service_type == HC.LOCAL_FILE: info_types = { HC.SERVICE_INFO_NUM_FILES, HC.SERVICE_INFO_TOTAL_SIZE, HC.SERVICE_INFO_NUM_DELETED_FILES }
|
if service_type == HC.LOCAL_FILE: info_types = { HC.SERVICE_INFO_NUM_FILES, HC.SERVICE_INFO_TOTAL_SIZE, HC.SERVICE_INFO_NUM_DELETED_FILES }
|
||||||
elif service_type == HC.FILE_REPOSITORY: info_types = { HC.SERVICE_INFO_NUM_FILES, HC.SERVICE_INFO_TOTAL_SIZE, HC.SERVICE_INFO_NUM_DELETED_FILES, HC.SERVICE_INFO_NUM_THUMBNAILS, HC.SERVICE_INFO_NUM_THUMBNAILS_LOCAL }
|
elif service_type == HC.FILE_REPOSITORY: info_types = { HC.SERVICE_INFO_NUM_FILES, HC.SERVICE_INFO_TOTAL_SIZE, HC.SERVICE_INFO_NUM_DELETED_FILES, HC.SERVICE_INFO_NUM_THUMBNAILS, HC.SERVICE_INFO_NUM_THUMBNAILS_LOCAL }
|
||||||
|
@ -3022,14 +2987,6 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
result = { dump_name.decode( 'hex' ) : data for ( dump_name, data ) in result.items() }
|
result = { dump_name.decode( 'hex' ) : data for ( dump_name, data ) in result.items() }
|
||||||
|
|
||||||
|
|
||||||
if dump_type == YAML_DUMP_ID_SUBSCRIPTION:
|
|
||||||
|
|
||||||
for ( dump_name, data ) in result.items():
|
|
||||||
|
|
||||||
data[ 'advanced_tag_options' ] = dict( data[ 'advanced_tag_options' ] )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
if dump_type == YAML_DUMP_ID_LOCAL_BOORU: dump_name = dump_name.encode( 'hex' )
|
if dump_type == YAML_DUMP_ID_LOCAL_BOORU: dump_name = dump_name.encode( 'hex' )
|
||||||
|
@ -3046,15 +3003,7 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
|
|
||||||
if result is None: raise Exception( dump_name + ' was not found!' )
|
if result is None: raise Exception( dump_name + ' was not found!' )
|
||||||
|
|
||||||
else:
|
else: ( result, ) = result
|
||||||
|
|
||||||
( result, ) = result
|
|
||||||
|
|
||||||
if dump_type == YAML_DUMP_ID_SUBSCRIPTION:
|
|
||||||
|
|
||||||
result[ 'advanced_tag_options' ] = dict( result[ 'advanced_tag_options' ] )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -3827,14 +3776,12 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
|
|
||||||
def _ResetService( self, c, service_identifier ):
|
def _ResetService( self, c, service_identifier ):
|
||||||
|
|
||||||
service_name = service_identifier.GetName()
|
name = service_identifier.GetName()
|
||||||
service_type = service_identifier.GetType()
|
service_type = service_identifier.GetType()
|
||||||
|
|
||||||
service_id = self._GetServiceId( c, service_identifier )
|
service_id = self._GetServiceId( c, service_identifier )
|
||||||
|
|
||||||
service = self._GetService( c, service_id )
|
( info, ) = c.execute( 'SELECT info FROM services WHERE service_id = ?;', ( service_id, ) ).fetchone()
|
||||||
|
|
||||||
info = service.GetInfo()
|
|
||||||
|
|
||||||
c.execute( 'DELETE FROM services WHERE service_id = ?;', ( service_id, ) )
|
c.execute( 'DELETE FROM services WHERE service_id = ?;', ( service_id, ) )
|
||||||
|
|
||||||
|
@ -3852,14 +3799,16 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
self.pub_after_commit( 'notify_restart_repo_sync_daemon' )
|
self.pub_after_commit( 'notify_restart_repo_sync_daemon' )
|
||||||
|
|
||||||
|
|
||||||
self._AddService( c, service_identifier, info )
|
service_key = service_identifier.GetServiceKey()
|
||||||
|
|
||||||
|
self._AddService( c, service_key, service_type, name, info )
|
||||||
|
|
||||||
self.pub_service_updates_after_commit( { service_identifier : [ HC.ServiceUpdate( HC.SERVICE_UPDATE_RESET ) ] } )
|
self.pub_service_updates_after_commit( { service_identifier : [ HC.ServiceUpdate( HC.SERVICE_UPDATE_RESET ) ] } )
|
||||||
self.pub_after_commit( 'notify_new_pending' )
|
self.pub_after_commit( 'notify_new_pending' )
|
||||||
self.pub_after_commit( 'notify_new_services_data' )
|
self.pub_after_commit( 'notify_new_services_data' )
|
||||||
self.pub_after_commit( 'notify_new_services_gui' )
|
self.pub_after_commit( 'notify_new_services_gui' )
|
||||||
self.pub_after_commit( 'permissions_are_stale' )
|
self.pub_after_commit( 'permissions_are_stale' )
|
||||||
HC.ShowText( 'reset ' + service_name )
|
HC.ShowText( 'reset ' + name )
|
||||||
|
|
||||||
|
|
||||||
def _SetTagCensorship( self, c, info ):
|
def _SetTagCensorship( self, c, info ):
|
||||||
|
@ -3901,8 +3850,6 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
|
|
||||||
c.execute( 'DELETE FROM yaml_dumps WHERE dump_type = ? AND dump_name = ?;', ( dump_type, dump_name ) )
|
c.execute( 'DELETE FROM yaml_dumps WHERE dump_type = ? AND dump_name = ?;', ( dump_type, dump_name ) )
|
||||||
|
|
||||||
if dump_type == YAML_DUMP_ID_SUBSCRIPTION: data[ 'advanced_tag_options' ] = data[ 'advanced_tag_options' ].items()
|
|
||||||
|
|
||||||
try: c.execute( 'INSERT INTO yaml_dumps ( dump_type, dump_name, dump ) VALUES ( ?, ?, ? );', ( dump_type, dump_name, data ) )
|
try: c.execute( 'INSERT INTO yaml_dumps ( dump_type, dump_name, dump ) VALUES ( ?, ?, ? );', ( dump_type, dump_name, data ) )
|
||||||
except:
|
except:
|
||||||
|
|
||||||
|
@ -4290,11 +4237,10 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
|
|
||||||
server_admin_service_id = self._GetServiceId( c, server_admin_service_identifier )
|
server_admin_service_id = self._GetServiceId( c, server_admin_service_identifier )
|
||||||
|
|
||||||
server_admin = self._GetService( c, server_admin_service_id )
|
( server_admin_info, ) = c.execute( 'SELECT info FROM services WHERE service_id = ?;', ( server_admin_service_id, ) ).fetchone()
|
||||||
|
|
||||||
server_admin_credentials = server_admin.GetCredentials()
|
host = server_admin_info[ 'host' ]
|
||||||
|
server_admin_port = server_admin_info[ 'port' ]
|
||||||
( host, server_admin_port ) = server_admin_credentials.GetAddress()
|
|
||||||
|
|
||||||
recalc_combined_mappings = False
|
recalc_combined_mappings = False
|
||||||
|
|
||||||
|
@ -4315,9 +4261,7 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
|
|
||||||
name = HC.service_string_lookup[ service_type ] + ' at ' + host + ':' + HC.u( info[ 'port' ] )
|
name = HC.service_string_lookup[ service_type ] + ' at ' + host + ':' + HC.u( info[ 'port' ] )
|
||||||
|
|
||||||
client_service_identifier = HC.ClientServiceIdentifier( service_key, service_type, name )
|
self._AddService( c, service_key, service_type, name, info )
|
||||||
|
|
||||||
self._AddService( c, client_service_identifier, info )
|
|
||||||
|
|
||||||
elif action == HC.DELETE:
|
elif action == HC.DELETE:
|
||||||
|
|
||||||
|
@ -4406,7 +4350,11 @@ class ServiceDB( FileDB, MessageDB, TagDB, RatingDB ):
|
||||||
|
|
||||||
( service_identifier, info ) = details
|
( service_identifier, info ) = details
|
||||||
|
|
||||||
self._AddService( c, service_identifier, info )
|
service_key = service_identifier.GetServiceKey()
|
||||||
|
service_type = service_identifier.GetType()
|
||||||
|
name = service_identifier.GetName()
|
||||||
|
|
||||||
|
self._AddService( c, service_key, service_type, name, info )
|
||||||
|
|
||||||
elif action == HC.DELETE:
|
elif action == HC.DELETE:
|
||||||
|
|
||||||
|
@ -4570,10 +4518,10 @@ class DB( ServiceDB ):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
self._local_file_service_id = self._GetServiceId( c, HC.LOCAL_FILE_SERVICE_IDENTIFIER )
|
self._local_file_service_id = self._GetServiceId( c, HC.LOCAL_FILE_SERVICE_KEY )
|
||||||
self._local_tag_service_id = self._GetServiceId( c, HC.LOCAL_TAG_SERVICE_IDENTIFIER )
|
self._local_tag_service_id = self._GetServiceId( c, HC.LOCAL_TAG_SERVICE_KEY )
|
||||||
self._combined_file_service_id = self._GetServiceId( c, HC.COMBINED_FILE_SERVICE_IDENTIFIER )
|
self._combined_file_service_id = self._GetServiceId( c, HC.COMBINED_FILE_SERVICE_KEY )
|
||||||
self._combined_tag_service_id = self._GetServiceId( c, HC.COMBINED_TAG_SERVICE_IDENTIFIER )
|
self._combined_tag_service_id = self._GetServiceId( c, HC.COMBINED_TAG_SERVICE_KEY )
|
||||||
|
|
||||||
options = self._GetOptions( c )
|
options = self._GetOptions( c )
|
||||||
|
|
||||||
|
@ -4820,9 +4768,12 @@ class DB( ServiceDB ):
|
||||||
|
|
||||||
for init_service_identifier in init_service_identifiers:
|
for init_service_identifier in init_service_identifiers:
|
||||||
|
|
||||||
|
service_key = init_service_identifier.GetServiceKey()
|
||||||
|
service_type = init_service_identifier.GetType()
|
||||||
|
name = init_service_identifier.GetName()
|
||||||
info = {}
|
info = {}
|
||||||
|
|
||||||
self._AddService( c, init_service_identifier, info )
|
self._AddService( c, service_key, service_type, name, info )
|
||||||
|
|
||||||
|
|
||||||
c.executemany( 'INSERT INTO yaml_dumps VALUES ( ?, ?, ? );', ( ( YAML_DUMP_ID_REMOTE_BOORU, name, booru ) for ( name, booru ) in CC.DEFAULT_BOORUS.items() ) )
|
c.executemany( 'INSERT INTO yaml_dumps VALUES ( ?, ?, ? );', ( ( YAML_DUMP_ID_REMOTE_BOORU, name, booru ) for ( name, booru ) in CC.DEFAULT_BOORUS.items() ) )
|
||||||
|
@ -4940,6 +4891,9 @@ class DB( ServiceDB ):
|
||||||
|
|
||||||
if version == 114:
|
if version == 114:
|
||||||
|
|
||||||
|
service_key = HC.LOCAL_BOORU_SERVICE_IDENTIFIER.GetServiceKey()
|
||||||
|
service_type = HC.LOCAL_BOORU_SERVICE_IDENTIFIER.GetType()
|
||||||
|
name = HC.LOCAL_BOORU_SERVICE_IDENTIFIER.GetName()
|
||||||
info = {}
|
info = {}
|
||||||
|
|
||||||
self._AddService( c, HC.LOCAL_BOORU_SERVICE_IDENTIFIER, info )
|
self._AddService( c, HC.LOCAL_BOORU_SERVICE_IDENTIFIER, info )
|
||||||
|
@ -5064,6 +5018,35 @@ class DB( ServiceDB ):
|
||||||
c.execute( 'UPDATE services SET info = ? WHERE service_id = ?;', ( info, service_id ) )
|
c.execute( 'UPDATE services SET info = ? WHERE service_id = ?;', ( info, service_id ) )
|
||||||
|
|
||||||
|
|
||||||
|
if version == 125:
|
||||||
|
|
||||||
|
( HC.options, ) = c.execute( 'SELECT options FROM options;' ).fetchone()
|
||||||
|
|
||||||
|
HC.options[ 'default_tag_repository' ] = HC.options[ 'default_tag_repository' ].GetServiceKey()
|
||||||
|
|
||||||
|
c.execute( 'UPDATE options SET options = ?;', ( HC.options, ) )
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
results = c.execute( 'SELECT * FROM yaml_dumps WHERE dump_type = ?;', ( YAML_DUMP_ID_SUBSCRIPTION, ) ).fetchall()
|
||||||
|
|
||||||
|
for ( dump_type, dump_name, dump ) in results:
|
||||||
|
|
||||||
|
advanced_tag_options = dump[ 'advanced_tag_options' ]
|
||||||
|
|
||||||
|
new_advanced_tag_options = {}
|
||||||
|
|
||||||
|
for ( service_identifier, namespaces ) in advanced_tag_options:
|
||||||
|
|
||||||
|
new_advanced_tag_options[ service_identifier.GetServiceKey() ] = namespaces
|
||||||
|
|
||||||
|
|
||||||
|
dump[ 'advanced_tag_options' ] = new_advanced_tag_options
|
||||||
|
|
||||||
|
c.execute( 'UPDATE yaml_dumps SET dump = ? WHERE dump_type = ? and dump_name = ?;', ( dump, dump_type, dump_name ) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
c.execute( 'UPDATE version SET version = ?;', ( version + 1, ) )
|
c.execute( 'UPDATE version SET version = ?;', ( version + 1, ) )
|
||||||
|
|
||||||
HC.is_db_updated = True
|
HC.is_db_updated = True
|
||||||
|
@ -7096,7 +7079,6 @@ class DB( ServiceDB ):
|
||||||
elif action == 'ratings_media_result': result = self._GetRatingsMediaResult( c, *args, **kwargs )
|
elif action == 'ratings_media_result': result = self._GetRatingsMediaResult( c, *args, **kwargs )
|
||||||
elif action == 'remote_booru': result = self._GetYAMLDump( c, YAML_DUMP_ID_REMOTE_BOORU, *args, **kwargs )
|
elif action == 'remote_booru': result = self._GetYAMLDump( c, YAML_DUMP_ID_REMOTE_BOORU, *args, **kwargs )
|
||||||
elif action == 'remote_boorus': result = self._GetYAMLDump( c, YAML_DUMP_ID_REMOTE_BOORU )
|
elif action == 'remote_boorus': result = self._GetYAMLDump( c, YAML_DUMP_ID_REMOTE_BOORU )
|
||||||
elif action == 'service': result = self._GetService( c, *args, **kwargs )
|
|
||||||
elif action == 'service_identifiers': result = self._GetServiceIdentifiers( c, *args, **kwargs )
|
elif action == 'service_identifiers': result = self._GetServiceIdentifiers( c, *args, **kwargs )
|
||||||
elif action == 'service_info': result = self._GetServiceInfo( c, *args, **kwargs )
|
elif action == 'service_info': result = self._GetServiceInfo( c, *args, **kwargs )
|
||||||
elif action == 'services': result = self._GetServices( c, *args, **kwargs )
|
elif action == 'services': result = self._GetServices( c, *args, **kwargs )
|
||||||
|
@ -7557,7 +7539,7 @@ def DAEMONDownloadFiles():
|
||||||
|
|
||||||
if service_identifier == HC.LOCAL_FILE_SERVICE_IDENTIFIER: break
|
if service_identifier == HC.LOCAL_FILE_SERVICE_IDENTIFIER: break
|
||||||
|
|
||||||
try: file_repository = HC.app.ReadDaemon( 'service', service_identifier )
|
try: file_repository = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
except: continue
|
except: continue
|
||||||
|
|
||||||
HC.pubsub.pub( 'downloads_status', HC.ConvertIntToPrettyString( num_downloads ) + ' file downloads' )
|
HC.pubsub.pub( 'downloads_status', HC.ConvertIntToPrettyString( num_downloads ) + ' file downloads' )
|
||||||
|
@ -7611,7 +7593,7 @@ def DAEMONDownloadThumbnails():
|
||||||
|
|
||||||
if len( thumbnail_hashes_i_need ) > 0:
|
if len( thumbnail_hashes_i_need ) > 0:
|
||||||
|
|
||||||
try: file_repository = HC.app.ReadDaemon( 'service', service_identifier )
|
try: file_repository = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
except: continue
|
except: continue
|
||||||
|
|
||||||
if file_repository.CanDownload():
|
if file_repository.CanDownload():
|
||||||
|
@ -7711,7 +7693,7 @@ def DAEMONResizeThumbnails():
|
||||||
|
|
||||||
def DAEMONSynchroniseAccounts():
|
def DAEMONSynchroniseAccounts():
|
||||||
|
|
||||||
services = HC.app.ReadDaemon( 'services', HC.RESTRICTED_SERVICES )
|
services = HC.app.GetManager( 'services' ).GetServices( HC.RESTRICTED_SERVICES )
|
||||||
|
|
||||||
do_notify = False
|
do_notify = False
|
||||||
|
|
||||||
|
@ -7771,7 +7753,7 @@ def DAEMONSynchroniseMessages():
|
||||||
|
|
||||||
service_type = service_identifier.GetType()
|
service_type = service_identifier.GetType()
|
||||||
|
|
||||||
try: service = HC.app.ReadDaemon( 'service', service_identifier )
|
try: service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
except: continue
|
except: continue
|
||||||
|
|
||||||
if service.CanCheck():
|
if service.CanCheck():
|
||||||
|
@ -7794,7 +7776,7 @@ def DAEMONSynchroniseMessages():
|
||||||
|
|
||||||
HC.app.WriteSynchronous( 'contact_associated', service_identifier )
|
HC.app.WriteSynchronous( 'contact_associated', service_identifier )
|
||||||
|
|
||||||
service = HC.app.ReadDaemon( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
contact = service.GetContact()
|
contact = service.GetContact()
|
||||||
|
|
||||||
|
@ -7893,7 +7875,7 @@ def DAEMONSynchroniseMessages():
|
||||||
my_public_key = contact_from.GetPublicKey()
|
my_public_key = contact_from.GetPublicKey()
|
||||||
my_contact_key = contact_from.GetContactKey()
|
my_contact_key = contact_from.GetContactKey()
|
||||||
|
|
||||||
my_message_depot = HC.app.ReadDaemon( 'service', contact_from )
|
my_message_depot = HC.app.GetManager( 'services' ).GetService( contact_from.GetServiceKey() )
|
||||||
|
|
||||||
from_connection = my_message_depot.GetConnection()
|
from_connection = my_message_depot.GetConnection()
|
||||||
|
|
||||||
|
@ -7957,7 +7939,7 @@ def DAEMONSynchroniseRepositories():
|
||||||
service_type = service_identifier.GetType()
|
service_type = service_identifier.GetType()
|
||||||
service_key = service_identifier.GetServiceKey()
|
service_key = service_identifier.GetServiceKey()
|
||||||
|
|
||||||
try: service = HC.app.ReadDaemon( 'service', service_identifier )
|
try: service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
except: continue
|
except: continue
|
||||||
|
|
||||||
info = service.GetInfo()
|
info = service.GetInfo()
|
||||||
|
@ -7966,19 +7948,34 @@ def DAEMONSynchroniseRepositories():
|
||||||
|
|
||||||
if service.CanDownloadUpdate():
|
if service.CanDownloadUpdate():
|
||||||
|
|
||||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, 'checking ' + name + ' repository' )
|
job_key = HC.JobKey( pausable = True, cancellable = False )
|
||||||
|
|
||||||
|
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, 'checking ' + name + ' repository', job_key )
|
||||||
|
|
||||||
HC.pubsub.pub( 'message', message )
|
HC.pubsub.pub( 'message', message )
|
||||||
|
|
||||||
while service.CanDownloadUpdate():
|
while service.CanDownloadUpdate():
|
||||||
|
|
||||||
|
while job_key.IsPaused():
|
||||||
|
|
||||||
|
message.SetInfo( 'text', 'paused' )
|
||||||
|
|
||||||
|
time.sleep( 1 )
|
||||||
|
|
||||||
|
if HC.shutdown: raise Exception( 'application shutting down!' )
|
||||||
|
|
||||||
|
if message.IsClosed(): return
|
||||||
|
|
||||||
|
|
||||||
while HC.options[ 'pause_repo_sync' ]:
|
while HC.options[ 'pause_repo_sync' ]:
|
||||||
|
|
||||||
message.SetInfo( 'text', 'Repository synchronisation paused' )
|
message.SetInfo( 'text', 'repository synchronisation paused' )
|
||||||
|
|
||||||
time.sleep( 5 )
|
time.sleep( 5 )
|
||||||
|
|
||||||
if HC.shutdown: raise Exception( 'Application shutting down!' )
|
if HC.shutdown: raise Exception( 'application shutting down!' )
|
||||||
|
|
||||||
|
if message.IsClosed(): return
|
||||||
|
|
||||||
if HC.repos_changed:
|
if HC.repos_changed:
|
||||||
|
|
||||||
|
@ -7990,7 +7987,7 @@ def DAEMONSynchroniseRepositories():
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if HC.shutdown: raise Exception( 'Application shutting down!' )
|
if HC.shutdown: raise Exception( 'application shutting down!' )
|
||||||
|
|
||||||
now = HC.GetNow()
|
now = HC.GetNow()
|
||||||
|
|
||||||
|
@ -8036,7 +8033,7 @@ def DAEMONSynchroniseRepositories():
|
||||||
|
|
||||||
time.sleep( 0.10 )
|
time.sleep( 0.10 )
|
||||||
|
|
||||||
try: service = HC.app.ReadDaemon( 'service', service_identifier )
|
try: service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
except: break
|
except: break
|
||||||
|
|
||||||
|
|
||||||
|
@ -8045,19 +8042,34 @@ def DAEMONSynchroniseRepositories():
|
||||||
|
|
||||||
if service.CanProcessUpdate():
|
if service.CanProcessUpdate():
|
||||||
|
|
||||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, 'processing ' + name + ' repository' )
|
job_key = HC.JobKey( pausable = True, cancellable = False )
|
||||||
|
|
||||||
|
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, 'processing ' + name + ' repository', job_key )
|
||||||
|
|
||||||
HC.pubsub.pub( 'message', message )
|
HC.pubsub.pub( 'message', message )
|
||||||
|
|
||||||
while service.CanProcessUpdate():
|
while service.CanProcessUpdate():
|
||||||
|
|
||||||
|
while job_key.IsPaused():
|
||||||
|
|
||||||
|
message.SetInfo( 'text', 'paused' )
|
||||||
|
|
||||||
|
time.sleep( 1 )
|
||||||
|
|
||||||
|
if HC.shutdown: raise Exception( 'application shutting down!' )
|
||||||
|
|
||||||
|
if message.IsClosed(): return
|
||||||
|
|
||||||
|
|
||||||
while HC.options[ 'pause_repo_sync' ]:
|
while HC.options[ 'pause_repo_sync' ]:
|
||||||
|
|
||||||
message.SetInfo( 'text', 'Repository synchronisation paused' )
|
message.SetInfo( 'text', 'repository synchronisation paused' )
|
||||||
|
|
||||||
time.sleep( 5 )
|
time.sleep( 5 )
|
||||||
|
|
||||||
if HC.shutdown: raise Exception( 'Application shutting down!' )
|
if HC.shutdown: raise Exception( 'application shutting down!' )
|
||||||
|
|
||||||
|
if message.IsClosed(): return
|
||||||
|
|
||||||
if HC.repos_changed:
|
if HC.repos_changed:
|
||||||
|
|
||||||
|
@ -8069,7 +8081,7 @@ def DAEMONSynchroniseRepositories():
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if HC.shutdown: raise Exception( 'Application shutting down!' )
|
if HC.shutdown: raise Exception( 'application shutting down!' )
|
||||||
|
|
||||||
now = HC.GetNow()
|
now = HC.GetNow()
|
||||||
|
|
||||||
|
@ -8168,7 +8180,7 @@ def DAEMONSynchroniseRepositories():
|
||||||
|
|
||||||
time.sleep( 0.10 )
|
time.sleep( 0.10 )
|
||||||
|
|
||||||
try: service = HC.app.ReadDaemon( 'service', service_identifier )
|
try: service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
except: break
|
except: break
|
||||||
|
|
||||||
|
|
||||||
|
@ -8225,7 +8237,9 @@ def DAEMONSynchroniseSubscriptions():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, 'checking ' + name + ' subscription' )
|
job_key = HC.JobKey( pausable = True, cancellable = False )
|
||||||
|
|
||||||
|
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, 'checking ' + name + ' subscription', job_key )
|
||||||
|
|
||||||
HC.pubsub.pub( 'message', message )
|
HC.pubsub.pub( 'message', message )
|
||||||
|
|
||||||
|
@ -8291,6 +8305,17 @@ def DAEMONSynchroniseSubscriptions():
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
|
while job_key.IsPaused():
|
||||||
|
|
||||||
|
message.SetInfo( 'text', 'paused' )
|
||||||
|
|
||||||
|
time.sleep( 1 )
|
||||||
|
|
||||||
|
if HC.shutdown: return
|
||||||
|
|
||||||
|
if message.IsClosed(): return
|
||||||
|
|
||||||
|
|
||||||
while HC.options[ 'pause_subs_sync' ]:
|
while HC.options[ 'pause_subs_sync' ]:
|
||||||
|
|
||||||
message.SetInfo( 'text', 'subscriptions paused' )
|
message.SetInfo( 'text', 'subscriptions paused' )
|
||||||
|
@ -8299,6 +8324,8 @@ def DAEMONSynchroniseSubscriptions():
|
||||||
|
|
||||||
if HC.shutdown: return
|
if HC.shutdown: return
|
||||||
|
|
||||||
|
if message.IsClosed(): return
|
||||||
|
|
||||||
if HC.subs_changed:
|
if HC.subs_changed:
|
||||||
|
|
||||||
message.Close()
|
message.Close()
|
||||||
|
@ -8467,6 +8494,8 @@ def DAEMONSynchroniseSubscriptions():
|
||||||
message.SetInfo( 'hashes', successful_hashes )
|
message.SetInfo( 'hashes', successful_hashes )
|
||||||
message.SetInfo( 'mode', 'files' )
|
message.SetInfo( 'mode', 'files' )
|
||||||
|
|
||||||
|
job_key.SetPausable( False )
|
||||||
|
|
||||||
else: message.Close()
|
else: message.Close()
|
||||||
|
|
||||||
last_checked = now
|
last_checked = now
|
||||||
|
@ -8504,13 +8533,17 @@ def DAEMONSynchroniseSubscriptions():
|
||||||
|
|
||||||
def DAEMONUPnP():
|
def DAEMONUPnP():
|
||||||
|
|
||||||
local_ip = HydrusNATPunch.GetLocalIP()
|
try:
|
||||||
|
|
||||||
|
local_ip = HydrusNATPunch.GetLocalIP()
|
||||||
|
|
||||||
|
current_mappings = HydrusNATPunch.GetUPnPMappings()
|
||||||
|
|
||||||
|
our_mappings = { ( internal_client, internal_port ) : external_port for ( description, internal_client, internal_port, external_ip_address, external_port, protocol, enabled ) in current_mappings }
|
||||||
|
|
||||||
|
except: return # This IGD probably doesn't support UPnP, so don't spam the user with errors they can't fix!
|
||||||
|
|
||||||
current_mappings = HydrusNATPunch.GetUPnPMappings()
|
services = HC.app.GetManager( 'services' ).GetServices( ( HC.LOCAL_BOORU, ) )
|
||||||
|
|
||||||
our_mappings = { ( internal_client, internal_port ) : external_port for ( description, internal_client, internal_port, external_ip_address, external_port, protocol, enabled ) in current_mappings }
|
|
||||||
|
|
||||||
services = HC.app.ReadDaemon( 'services', ( HC.LOCAL_BOORU, ) )
|
|
||||||
|
|
||||||
for service in services:
|
for service in services:
|
||||||
|
|
||||||
|
|
|
@ -144,17 +144,17 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
job_key = HC.JobKey()
|
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||||
|
|
||||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, 'gathering pending and petitioned' )
|
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, 'gathering pending and petitioned', job_key )
|
||||||
|
|
||||||
HC.pubsub.pub( 'message', message )
|
HC.pubsub.pub( 'message', message )
|
||||||
|
|
||||||
result = HC.app.Read( 'pending', service_identifier )
|
result = HC.app.Read( 'pending', service_identifier )
|
||||||
|
|
||||||
service_type = service_identifier.GetType()
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service_type = service.GetType()
|
||||||
|
|
||||||
if service_type == HC.FILE_REPOSITORY:
|
if service_type == HC.FILE_REPOSITORY:
|
||||||
|
|
||||||
|
@ -172,7 +172,6 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
i = 1
|
i = 1
|
||||||
|
|
||||||
message.SetInfo( 'job_key', job_key )
|
|
||||||
message.SetInfo( 'range', gauge_range )
|
message.SetInfo( 'range', gauge_range )
|
||||||
message.SetInfo( 'value', i )
|
message.SetInfo( 'value', i )
|
||||||
message.SetInfo( 'text', 'connecting to repository' )
|
message.SetInfo( 'text', 'connecting to repository' )
|
||||||
|
@ -325,7 +324,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
subject_access_key = dlg.GetValue().decode( 'hex' )
|
subject_access_key = dlg.GetValue().decode( 'hex' )
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
response = service.Request( HC.GET, 'account_info', { 'subject_access_key' : subject_access_key.encode( 'hex' ) } )
|
response = service.Request( HC.GET, 'account_info', { 'subject_access_key' : subject_access_key.encode( 'hex' ) } )
|
||||||
|
|
||||||
|
@ -338,178 +337,193 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
def _AutoRepoSetup( self ):
|
def _AutoRepoSetup( self ):
|
||||||
|
|
||||||
|
def do_it():
|
||||||
|
|
||||||
|
edit_log = []
|
||||||
|
|
||||||
|
tag_repo_identifier = HC.ClientServiceIdentifier( os.urandom( 32 ), HC.TAG_REPOSITORY, 'public tag repository' )
|
||||||
|
|
||||||
|
tag_repo_info = {}
|
||||||
|
|
||||||
|
tag_repo_info[ 'host' ] = 'hydrus.no-ip.org'
|
||||||
|
tag_repo_info[ 'port' ] = 45871
|
||||||
|
tag_repo_info[ 'access_key' ] = '4a285629721ca442541ef2c15ea17d1f7f7578b0c3f4f5f2a05f8f0ab297786f'.decode( 'hex' )
|
||||||
|
|
||||||
|
edit_log.append( ( HC.ADD, ( tag_repo_identifier, tag_repo_info ) ) )
|
||||||
|
|
||||||
|
file_repo_identifier = HC.ClientServiceIdentifier( os.urandom( 32 ), HC.FILE_REPOSITORY, 'read-only art file repository' )
|
||||||
|
|
||||||
|
file_repo_info = {}
|
||||||
|
|
||||||
|
file_repo_info[ 'host' ] = 'hydrus.no-ip.org'
|
||||||
|
file_repo_info[ 'port' ] = 45872
|
||||||
|
file_repo_info[ 'access_key' ] = '8f8a3685abc19e78a92ba61d84a0482b1cfac176fd853f46d93fe437a95e40a5'.decode( 'hex' )
|
||||||
|
|
||||||
|
edit_log.append( ( HC.ADD, ( file_repo_identifier, file_repo_info ) ) )
|
||||||
|
|
||||||
|
HC.app.Write( 'update_services', edit_log )
|
||||||
|
|
||||||
|
HC.ShowText( 'Auto repo setup done! Check services->review services to see your new services.' )
|
||||||
|
|
||||||
|
|
||||||
message = 'This will attempt to set up your client with my repositories\' credentials, letting you tag on the public tag repository and see some files.'
|
message = 'This will attempt to set up your client with my repositories\' credentials, letting you tag on the public tag repository and see some files.'
|
||||||
|
|
||||||
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
|
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
|
||||||
|
|
||||||
if dlg.ShowModal() == wx.ID_YES:
|
if dlg.ShowModal() == wx.ID_YES: HydrusThreading.CallToThread( do_it )
|
||||||
|
|
||||||
edit_log = []
|
|
||||||
|
|
||||||
tag_repo_identifier = HC.ClientServiceIdentifier( os.urandom( 32 ), HC.TAG_REPOSITORY, 'public tag repository' )
|
|
||||||
|
|
||||||
tag_repo_info = {}
|
|
||||||
|
|
||||||
tag_repo_info[ 'host' ] = 'hydrus.no-ip.org'
|
|
||||||
tag_repo_info[ 'port' ] = 45871
|
|
||||||
tag_repo_info[ 'access_key' ] = '4a285629721ca442541ef2c15ea17d1f7f7578b0c3f4f5f2a05f8f0ab297786f'.decode( 'hex' )
|
|
||||||
|
|
||||||
edit_log.append( ( HC.ADD, ( tag_repo_identifier, tag_repo_info ) ) )
|
|
||||||
|
|
||||||
file_repo_identifier = HC.ClientServiceIdentifier( os.urandom( 32 ), HC.FILE_REPOSITORY, 'read-only art file repository' )
|
|
||||||
|
|
||||||
file_repo_info = {}
|
|
||||||
|
|
||||||
file_repo_info[ 'host' ] = 'hydrus.no-ip.org'
|
|
||||||
file_repo_info[ 'port' ] = 45872
|
|
||||||
file_repo_info[ 'access_key' ] = '8f8a3685abc19e78a92ba61d84a0482b1cfac176fd853f46d93fe437a95e40a5'.decode( 'hex' )
|
|
||||||
|
|
||||||
edit_log.append( ( HC.ADD, ( file_repo_identifier, file_repo_info ) ) )
|
|
||||||
|
|
||||||
HC.app.Write( 'update_services', edit_log )
|
|
||||||
|
|
||||||
HC.ShowText( 'Auto repo setup done!' )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _AutoServerSetup( self ):
|
def _AutoServerSetup( self ):
|
||||||
|
|
||||||
host = '127.0.0.1'
|
def do_it():
|
||||||
port = HC.DEFAULT_SERVER_ADMIN_PORT
|
|
||||||
|
host = '127.0.0.1'
|
||||||
|
port = HC.DEFAULT_SERVER_ADMIN_PORT
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
connection = httplib.HTTPConnection( '127.0.0.1', HC.DEFAULT_SERVER_ADMIN_PORT, timeout = 20 )
|
||||||
|
|
||||||
|
connection.connect()
|
||||||
|
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
already_running = True
|
||||||
|
|
||||||
|
except:
|
||||||
|
|
||||||
|
already_running = False
|
||||||
|
|
||||||
|
|
||||||
|
if already_running:
|
||||||
|
|
||||||
|
HC.ShowText( 'The server appears to be already running. Either that, or something else is using port ' + HC.u( HC.DEFAULT_SERVER_ADMIN_PORT ) + '.' )
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
HC.ShowText( 'starting server' )
|
||||||
|
|
||||||
|
my_scriptname = sys.argv[0]
|
||||||
|
|
||||||
|
if my_scriptname.endswith( 'pyw' ): subprocess.Popen( [ 'pythonw', HC.BASE_DIR + os.path.sep + 'server.pyw' ] )
|
||||||
|
else:
|
||||||
|
|
||||||
|
# The problem here is that, for mystical reasons, a PyInstaller exe can't launch another using subprocess, so we do it via explorer.
|
||||||
|
|
||||||
|
subprocess.Popen( [ 'explorer', HC.BASE_DIR + os.path.sep + 'server.exe' ] )
|
||||||
|
|
||||||
|
|
||||||
|
time.sleep( 10 ) # give it time to init its db
|
||||||
|
|
||||||
|
except:
|
||||||
|
|
||||||
|
HC.ShowText( 'I tried to start the server, but something failed!' )
|
||||||
|
HC.ShowText( traceback.format_exc() )
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HC.ShowText( 'creating admin service' )
|
||||||
|
|
||||||
|
edit_log = []
|
||||||
|
|
||||||
|
admin_service_identifier = HC.ClientServiceIdentifier( os.urandom( 32 ), HC.SERVER_ADMIN, 'local server admin' )
|
||||||
|
|
||||||
|
admin_service_info = {}
|
||||||
|
|
||||||
|
admin_service_info[ 'host' ] = host
|
||||||
|
admin_service_info[ 'port' ] = port
|
||||||
|
admin_service_info[ 'access_key' ] = ''
|
||||||
|
|
||||||
|
edit_log.append( ( HC.ADD, ( admin_service_identifier, admin_service_info ) ) )
|
||||||
|
|
||||||
|
HC.app.Write( 'update_services', edit_log )
|
||||||
|
|
||||||
|
time.sleep( 5 )
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
|
||||||
|
time.sleep( i + 1 )
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
service = HC.app.GetManager( 'services' ).GetService( admin_service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
|
break
|
||||||
|
|
||||||
|
except: pass
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
if i > 5:
|
||||||
|
|
||||||
|
HC.ShowText( 'For some reason, I could not add the new server to the db! Perhaps it is very busy. Please email the hydrus developer, or sort it out yourself!' )
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
response = service.Request( HC.GET, 'init' )
|
||||||
|
|
||||||
|
access_key = response[ 'access_key' ]
|
||||||
|
|
||||||
|
update = { 'access_key' : access_key }
|
||||||
|
|
||||||
|
edit_log = [ ( HC.EDIT, ( admin_service_identifier, ( admin_service_identifier, update ) ) ) ]
|
||||||
|
|
||||||
|
HC.app.Write( 'update_services', edit_log )
|
||||||
|
|
||||||
|
HC.ShowText( 'admin service initialised' )
|
||||||
|
|
||||||
|
wx.CallAfter( ClientGUICommon.ShowKeys, 'access', ( access_key, ) )
|
||||||
|
|
||||||
|
time.sleep( 5 )
|
||||||
|
|
||||||
|
service = HC.app.GetManager( 'services' ).GetService( admin_service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
HC.ShowText( 'creating tag and file services' )
|
||||||
|
|
||||||
|
tag_server_service_identifier = HC.ServerServiceIdentifier( os.urandom( 32 ), HC.TAG_REPOSITORY )
|
||||||
|
|
||||||
|
tag_options = HC.DEFAULT_OPTIONS[ HC.TAG_REPOSITORY ]
|
||||||
|
tag_options[ 'port' ] = HC.DEFAULT_SERVICE_PORT
|
||||||
|
|
||||||
|
file_server_service_identifier = HC.ServerServiceIdentifier( os.urandom( 32 ), HC.FILE_REPOSITORY )
|
||||||
|
|
||||||
|
file_options = HC.DEFAULT_OPTIONS[ HC.FILE_REPOSITORY ]
|
||||||
|
file_options[ 'port' ] = HC.DEFAULT_SERVICE_PORT + 1
|
||||||
|
|
||||||
|
edit_log = []
|
||||||
|
|
||||||
|
edit_log.append( ( HC.ADD, ( tag_server_service_identifier, tag_options ) ) )
|
||||||
|
edit_log.append( ( HC.ADD, ( file_server_service_identifier, file_options ) ) )
|
||||||
|
|
||||||
|
response = service.Request( HC.POST, 'services', { 'edit_log' : edit_log } )
|
||||||
|
|
||||||
|
service_identifiers_to_access_keys = dict( response[ 'service_identifiers_to_access_keys' ] )
|
||||||
|
|
||||||
|
HC.app.Write( 'update_server_services', admin_service_identifier, edit_log, service_identifiers_to_access_keys )
|
||||||
|
|
||||||
|
HC.ShowText( 'Done! Check services->review services to see your new server and its services.' )
|
||||||
|
|
||||||
|
|
||||||
message = 'This will attempt to start the server in the same install directory as this client, initialise it, and store the resultant admin accounts in the client.'
|
message = 'This will attempt to start the server in the same install directory as this client, initialise it, and store the resultant admin accounts in the client.'
|
||||||
|
|
||||||
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
|
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
|
||||||
|
|
||||||
if dlg.ShowModal() == wx.ID_YES:
|
if dlg.ShowModal() == wx.ID_YES: HydrusThreading.CallToThread( do_it )
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
connection = httplib.HTTPConnection( '127.0.0.1', HC.DEFAULT_SERVER_ADMIN_PORT, timeout = 20 )
|
|
||||||
|
|
||||||
connection.connect()
|
|
||||||
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
already_running = True
|
|
||||||
|
|
||||||
except:
|
|
||||||
|
|
||||||
already_running = False
|
|
||||||
|
|
||||||
|
|
||||||
if already_running:
|
|
||||||
|
|
||||||
message = 'The server appears to be already running. Either that, or something else is using port ' + HC.u( HC.DEFAULT_SERVER_ADMIN_PORT ) + '.' + os.linesep + 'Would you like to try to initialise the server that is already running?'
|
|
||||||
|
|
||||||
with ClientGUIDialogs.DialogYesNo( self, message ) as dlg:
|
|
||||||
|
|
||||||
if dlg.ShowModal() != wx.ID_YES: return
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
my_scriptname = sys.argv[0]
|
|
||||||
|
|
||||||
if my_scriptname.endswith( 'pyw' ): subprocess.Popen( [ 'pythonw', HC.BASE_DIR + os.path.sep + 'server.pyw' ] )
|
|
||||||
else:
|
|
||||||
|
|
||||||
# The problem here is that, for mystical reasons, a PyInstaller exe can't launch another using subprocess, so we do it via explorer.
|
|
||||||
|
|
||||||
subprocess.Popen( [ 'explorer', HC.BASE_DIR + os.path.sep + 'server.exe' ] )
|
|
||||||
|
|
||||||
|
|
||||||
time.sleep( 10 ) # give it time to init its db
|
|
||||||
|
|
||||||
except:
|
|
||||||
|
|
||||||
wx.MessageBox( 'I tried to start the server, but something failed!' )
|
|
||||||
wx.MessageBox( traceback.format_exc() )
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
edit_log = []
|
|
||||||
|
|
||||||
admin_service_identifier = HC.ClientServiceIdentifier( os.urandom( 32 ), HC.SERVER_ADMIN, 'local server admin' )
|
|
||||||
|
|
||||||
admin_service_info = {}
|
|
||||||
|
|
||||||
admin_service_info[ 'host' ] = host
|
|
||||||
admin_service_info[ 'port' ] = port
|
|
||||||
admin_service_info[ 'access_key' ] = ''
|
|
||||||
|
|
||||||
edit_log.append( ( HC.ADD, ( admin_service_identifier, admin_service_info ) ) )
|
|
||||||
|
|
||||||
HC.app.Write( 'update_services', edit_log )
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
while True:
|
|
||||||
|
|
||||||
time.sleep( i + 1 )
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
service = HC.app.Read( 'service', admin_service_identifier )
|
|
||||||
|
|
||||||
break
|
|
||||||
|
|
||||||
except: pass
|
|
||||||
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
if i > 5:
|
|
||||||
|
|
||||||
wx.MessageBox( 'For some reason, I could not add the new server to the db! Perhaps it is very busy. Please contact the administrator, or sort it out yourself!' )
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
|
|
||||||
response = service.Request( HC.GET, 'init' )
|
|
||||||
|
|
||||||
access_key = response[ 'access_key' ]
|
|
||||||
|
|
||||||
update = { 'access_key' : access_key }
|
|
||||||
|
|
||||||
edit_log = [ ( HC.EDIT, ( admin_service_identifier, ( admin_service_identifier, update ) ) ) ]
|
|
||||||
|
|
||||||
HC.app.Write( 'update_services', edit_log )
|
|
||||||
|
|
||||||
ClientGUICommon.ShowKeys( 'access', ( access_key, ) )
|
|
||||||
|
|
||||||
#
|
|
||||||
|
|
||||||
tag_server_service_identifier = HC.ServerServiceIdentifier( os.urandom( 32 ), HC.TAG_REPOSITORY )
|
|
||||||
|
|
||||||
tag_options = HC.DEFAULT_OPTIONS[ HC.TAG_REPOSITORY ]
|
|
||||||
tag_options[ 'port' ] = HC.DEFAULT_SERVICE_PORT
|
|
||||||
|
|
||||||
file_server_service_identifier = HC.ServerServiceIdentifier( os.urandom( 32 ), HC.FILE_REPOSITORY )
|
|
||||||
|
|
||||||
file_options = HC.DEFAULT_OPTIONS[ HC.FILE_REPOSITORY ]
|
|
||||||
file_options[ 'port' ] = HC.DEFAULT_SERVICE_PORT + 1
|
|
||||||
|
|
||||||
edit_log = []
|
|
||||||
|
|
||||||
edit_log.append( ( HC.ADD, ( tag_server_service_identifier, tag_options ) ) )
|
|
||||||
edit_log.append( ( HC.ADD, ( file_server_service_identifier, file_options ) ) )
|
|
||||||
|
|
||||||
response = service.Request( HC.POST, 'services', { 'edit_log' : edit_log } )
|
|
||||||
|
|
||||||
service_identifiers_to_access_keys = dict( response[ 'service_identifiers_to_access_keys' ] )
|
|
||||||
|
|
||||||
HC.app.Write( 'update_server_services', admin_service_identifier, edit_log, service_identifiers_to_access_keys )
|
|
||||||
|
|
||||||
wx.MessageBox( 'Done! Check services->review services to see your new server and its services.' )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -521,7 +535,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
if dlg.ShowModal() == wx.ID_YES:
|
if dlg.ShowModal() == wx.ID_YES:
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
with wx.BusyCursor(): service.Request( HC.POST, 'backup' )
|
with wx.BusyCursor(): service.Request( HC.POST, 'backup' )
|
||||||
|
|
||||||
|
@ -611,7 +625,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
hash = dlg.GetValue().decode( 'hex' )
|
hash = dlg.GetValue().decode( 'hex' )
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
with wx.BusyCursor(): response = service.Request( HC.GET, 'ip', { 'hash' : hash.encode( 'hex' ) } )
|
with wx.BusyCursor(): response = service.Request( HC.GET, 'ip', { 'hash' : hash.encode( 'hex' ) } )
|
||||||
|
|
||||||
|
@ -746,13 +760,13 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
def view():
|
def view():
|
||||||
|
|
||||||
services = HC.app.Read( 'services' )
|
services = HC.app.GetManager( 'services' ).GetServices()
|
||||||
|
|
||||||
tag_repositories = [ service for service in services if service.GetServiceIdentifier().GetType() == HC.TAG_REPOSITORY ]
|
tag_repositories = [ service for service in services if service.GetType() == HC.TAG_REPOSITORY ]
|
||||||
|
|
||||||
petition_resolve_tag_service_identifiers = [ repository.GetServiceIdentifier() for repository in tag_repositories if repository.GetInfo( 'account' ).HasPermission( HC.RESOLVE_PETITIONS ) ]
|
petition_resolve_tag_service_identifiers = [ repository.GetServiceIdentifier() for repository in tag_repositories if repository.GetInfo( 'account' ).HasPermission( HC.RESOLVE_PETITIONS ) ]
|
||||||
|
|
||||||
file_repositories = [ service for service in services if service.GetServiceIdentifier().GetType() == HC.FILE_REPOSITORY ]
|
file_repositories = [ service for service in services if service.GetType() == HC.FILE_REPOSITORY ]
|
||||||
|
|
||||||
file_service_identifiers = [ repository.GetServiceIdentifier() for repository in file_repositories ]
|
file_service_identifiers = [ repository.GetServiceIdentifier() for repository in file_repositories ]
|
||||||
petition_resolve_file_service_identifiers = [ repository.GetServiceIdentifier() for repository in file_repositories if repository.GetInfo( 'account' ).HasPermission( HC.RESOLVE_PETITIONS ) ]
|
petition_resolve_file_service_identifiers = [ repository.GetServiceIdentifier() for repository in file_repositories if repository.GetInfo( 'account' ).HasPermission( HC.RESOLVE_PETITIONS ) ]
|
||||||
|
@ -897,15 +911,15 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
def admin():
|
def admin():
|
||||||
|
|
||||||
services = HC.app.Read( 'services' )
|
services = HC.app.GetManager( 'services' ).GetServices()
|
||||||
|
|
||||||
tag_repositories = [ service for service in services if service.GetServiceIdentifier().GetType() == HC.TAG_REPOSITORY ]
|
tag_repositories = [ service for service in services if service.GetType() == HC.TAG_REPOSITORY ]
|
||||||
admin_tag_service_identifiers = [ repository.GetServiceIdentifier() for repository in tag_repositories if repository.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
|
admin_tag_service_identifiers = [ repository.GetServiceIdentifier() for repository in tag_repositories if repository.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
|
||||||
|
|
||||||
file_repositories = [ service for service in services if service.GetServiceIdentifier().GetType() == HC.FILE_REPOSITORY ]
|
file_repositories = [ service for service in services if service.GetType() == HC.FILE_REPOSITORY ]
|
||||||
admin_file_service_identifiers = [ repository.GetServiceIdentifier() for repository in file_repositories if repository.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
|
admin_file_service_identifiers = [ repository.GetServiceIdentifier() for repository in file_repositories if repository.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
|
||||||
|
|
||||||
servers_admin = [ service for service in services if service.GetServiceIdentifier().GetType() == HC.SERVER_ADMIN ]
|
servers_admin = [ service for service in services if service.GetType() == HC.SERVER_ADMIN ]
|
||||||
server_admin_identifiers = [ service.GetServiceIdentifier() for service in servers_admin if service.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
|
server_admin_identifiers = [ service.GetServiceIdentifier() for service in servers_admin if service.GetInfo( 'account' ).HasPermission( HC.GENERAL_ADMIN ) ]
|
||||||
|
|
||||||
if len( admin_tag_service_identifiers ) > 0 or len( admin_file_service_identifiers ) > 0 or len( server_admin_identifiers ) > 0:
|
if len( admin_tag_service_identifiers ) > 0 or len( admin_file_service_identifiers ) > 0 or len( server_admin_identifiers ) > 0:
|
||||||
|
@ -1227,7 +1241,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
def _ModifyAccount( self, service_identifier ):
|
def _ModifyAccount( self, service_identifier ):
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
with ClientGUIDialogs.DialogTextEntry( self, 'Enter the access key for the account to be modified.' ) as dlg:
|
with ClientGUIDialogs.DialogTextEntry( self, 'Enter the access key for the account to be modified.' ) as dlg:
|
||||||
|
|
||||||
|
@ -1313,7 +1327,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
if service_identifier is not None:
|
if service_identifier is not None:
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
account = service.GetInfo( 'account' )
|
account = service.GetInfo( 'account' )
|
||||||
|
|
||||||
|
@ -1395,7 +1409,7 @@ class FrameGUI( ClientGUICommon.FrameThatResizes ):
|
||||||
|
|
||||||
news = dlg.GetValue()
|
news = dlg.GetValue()
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
with wx.BusyCursor(): service.Request( HC.POST, 'news', { 'news' : news } )
|
with wx.BusyCursor(): service.Request( HC.POST, 'news', { 'news' : news } )
|
||||||
|
|
||||||
|
@ -1592,7 +1606,9 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
||||||
|
|
||||||
url_string = url
|
url_string = url
|
||||||
|
|
||||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, url_string )
|
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||||
|
|
||||||
|
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, url_string, job_key )
|
||||||
|
|
||||||
HC.pubsub.pub( 'message', message )
|
HC.pubsub.pub( 'message', message )
|
||||||
|
|
||||||
|
@ -1620,7 +1636,7 @@ The password is cleartext here but obscured in the entry dialog. Enter a blank p
|
||||||
|
|
||||||
def _Stats( self, service_identifier ):
|
def _Stats( self, service_identifier ):
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
response = service.Request( HC.GET, 'stats' )
|
response = service.Request( HC.GET, 'stats' )
|
||||||
|
|
||||||
|
@ -2505,7 +2521,7 @@ class FrameReviewServices( ClientGUICommon.Frame ):
|
||||||
|
|
||||||
def _DisplayAccountInfo( self ):
|
def _DisplayAccountInfo( self ):
|
||||||
|
|
||||||
self._service = HC.app.Read( 'service', self._service_identifier )
|
self._service = HC.app.GetManager( 'services' ).GetService( self._service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
service_type = self._service_identifier.GetType()
|
service_type = self._service_identifier.GetType()
|
||||||
|
|
||||||
|
@ -2636,7 +2652,7 @@ class FrameReviewServices( ClientGUICommon.Frame ):
|
||||||
|
|
||||||
if service_type in HC.REPOSITORIES + HC.LOCAL_SERVICES:
|
if service_type in HC.REPOSITORIES + HC.LOCAL_SERVICES:
|
||||||
|
|
||||||
service_info = HC.app.Read( 'service_info', self._service_identifier )
|
service_info = HC.app.Read( 'service_info', self._service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
if service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ):
|
if service_type in ( HC.LOCAL_FILE, HC.FILE_REPOSITORY ):
|
||||||
|
|
||||||
|
@ -2781,7 +2797,7 @@ class FrameReviewServices( ClientGUICommon.Frame ):
|
||||||
|
|
||||||
( name, text, timeout, ( num_hashes, hashes, share_key ) ) = shares[0]
|
( name, text, timeout, ( num_hashes, hashes, share_key ) ) = shares[0]
|
||||||
|
|
||||||
self._service = HC.app.Read( 'service', HC.LOCAL_BOORU_SERVICE_IDENTIFIER )
|
self._service = HC.app.GetManager( 'services' ).GetService( HC.LOCAL_BOORU_SERVICE_IDENTIFIER.GetServiceKey() )
|
||||||
|
|
||||||
info = self._service.GetInfo()
|
info = self._service.GetInfo()
|
||||||
|
|
||||||
|
@ -2805,7 +2821,7 @@ class FrameReviewServices( ClientGUICommon.Frame ):
|
||||||
|
|
||||||
( name, text, timeout, ( num_hashes, hashes, share_key ) ) = shares[0]
|
( name, text, timeout, ( num_hashes, hashes, share_key ) ) = shares[0]
|
||||||
|
|
||||||
self._service = HC.app.Read( 'service', HC.LOCAL_BOORU_SERVICE_IDENTIFIER )
|
self._service = HC.app.GetManager( 'services' ).GetService( HC.LOCAL_BOORU_SERVICE_IDENTIFIER.GetServiceKey() )
|
||||||
|
|
||||||
info = self._service.GetInfo()
|
info = self._service.GetInfo()
|
||||||
|
|
||||||
|
|
|
@ -433,6 +433,19 @@ class Canvas( object ):
|
||||||
self.Bind( wx.EVT_PAINT, self.EventPaint )
|
self.Bind( wx.EVT_PAINT, self.EventPaint )
|
||||||
|
|
||||||
|
|
||||||
|
def _CopyHashToClipboard( self ):
|
||||||
|
|
||||||
|
if wx.TheClipboard.Open():
|
||||||
|
|
||||||
|
data = wx.TextDataObject( self._current_display_media.GetHash().encode( 'hex' ) )
|
||||||
|
|
||||||
|
wx.TheClipboard.SetData( data )
|
||||||
|
|
||||||
|
wx.TheClipboard.Close()
|
||||||
|
|
||||||
|
else: wx.MessageBox( 'I could not get permission to access the clipboard.' )
|
||||||
|
|
||||||
|
|
||||||
def _DrawBackgroundBitmap( self ):
|
def _DrawBackgroundBitmap( self ):
|
||||||
|
|
||||||
( client_width, client_height ) = self.GetClientSize()
|
( client_width, client_height ) = self.GetClientSize()
|
||||||
|
@ -539,7 +552,7 @@ class Canvas( object ):
|
||||||
if service_identifier in self._service_identifiers_to_services: service = self._service_identifiers_to_services[ service_identifier ]
|
if service_identifier in self._service_identifiers_to_services: service = self._service_identifiers_to_services[ service_identifier ]
|
||||||
else:
|
else:
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
self._service_identifiers_to_services[ service_identifier ] = service
|
self._service_identifiers_to_services[ service_identifier ] = service
|
||||||
|
|
||||||
|
@ -757,6 +770,8 @@ class Canvas( object ):
|
||||||
|
|
||||||
if media != self._current_media:
|
if media != self._current_media:
|
||||||
|
|
||||||
|
HC.app.ResetIdleTimer()
|
||||||
|
|
||||||
with wx.FrozenWindow( self ):
|
with wx.FrozenWindow( self ):
|
||||||
|
|
||||||
self._current_media = media
|
self._current_media = media
|
||||||
|
@ -1051,6 +1066,30 @@ class CanvasFullscreenMediaList( ClientGUIMixins.ListeningMediaList, Canvas, Cli
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _Remove( self ):
|
||||||
|
|
||||||
|
next_media = self._GetNext( self._current_media )
|
||||||
|
|
||||||
|
if next_media == self._current_media: next_media = None
|
||||||
|
|
||||||
|
hashes = { self._current_display_media.GetHash() }
|
||||||
|
|
||||||
|
HC.pubsub.pub( 'remove_media', self._page_key, hashes )
|
||||||
|
|
||||||
|
singleton_media = { self._current_display_media }
|
||||||
|
|
||||||
|
ClientGUIMixins.ListeningMediaList._RemoveMedia( self, singleton_media, {} )
|
||||||
|
|
||||||
|
if self.HasNoMedia(): self.EventClose( None )
|
||||||
|
elif self.HasMedia( self._current_media ):
|
||||||
|
|
||||||
|
self._DrawBackgroundBitmap()
|
||||||
|
|
||||||
|
self._DrawCurrentMedia()
|
||||||
|
|
||||||
|
else: self.SetMedia( next_media )
|
||||||
|
|
||||||
|
|
||||||
def _ShowFirst( self ): self.SetMedia( self._GetFirst() )
|
def _ShowFirst( self ): self.SetMedia( self._GetFirst() )
|
||||||
|
|
||||||
def _ShowLast( self ): self.SetMedia( self._GetLast() )
|
def _ShowLast( self ): self.SetMedia( self._GetLast() )
|
||||||
|
@ -1459,6 +1498,7 @@ class CanvasFullscreenMediaListBrowser( CanvasFullscreenMediaList ):
|
||||||
if command == 'archive': self._Archive()
|
if command == 'archive': self._Archive()
|
||||||
elif command == 'copy_files':
|
elif command == 'copy_files':
|
||||||
with wx.BusyCursor(): HC.app.Write( 'copy_files', ( self._current_media.GetHash(), ) )
|
with wx.BusyCursor(): HC.app.Write( 'copy_files', ( self._current_media.GetHash(), ) )
|
||||||
|
elif command == 'copy_hash': self._CopyHashToClipboard()
|
||||||
elif command == 'copy_local_url': self._CopyLocalUrlToClipboard()
|
elif command == 'copy_local_url': self._CopyLocalUrlToClipboard()
|
||||||
elif command == 'copy_path': self._CopyPathToClipboard()
|
elif command == 'copy_path': self._CopyPathToClipboard()
|
||||||
elif command == 'delete': self._Delete()
|
elif command == 'delete': self._Delete()
|
||||||
|
@ -1481,6 +1521,7 @@ class CanvasFullscreenMediaListBrowser( CanvasFullscreenMediaList ):
|
||||||
elif command == 'pan_left': self._DoManualPan( -distance, 0 )
|
elif command == 'pan_left': self._DoManualPan( -distance, 0 )
|
||||||
elif command == 'pan_right': self._DoManualPan( distance, 0 )
|
elif command == 'pan_right': self._DoManualPan( distance, 0 )
|
||||||
|
|
||||||
|
elif command == 'remove': self._Remove()
|
||||||
elif command == 'slideshow': self._StartSlideshow( data )
|
elif command == 'slideshow': self._StartSlideshow( data )
|
||||||
elif command == 'slideshow_pause_play': self._PausePlaySlideshow()
|
elif command == 'slideshow_pause_play': self._PausePlaySlideshow()
|
||||||
elif command == 'zoom_in': self._ZoomIn()
|
elif command == 'zoom_in': self._ZoomIn()
|
||||||
|
@ -1511,9 +1552,9 @@ class CanvasFullscreenMediaListBrowser( CanvasFullscreenMediaList ):
|
||||||
|
|
||||||
def EventShowMenu( self, event ):
|
def EventShowMenu( self, event ):
|
||||||
|
|
||||||
services = HC.app.Read( 'services' )
|
services = HC.app.GetManager( 'services' ).GetServices()
|
||||||
|
|
||||||
local_ratings_services = [ service for service in services if service.GetServiceIdentifier().GetType() in ( HC.LOCAL_RATING_LIKE, HC.LOCAL_RATING_NUMERICAL ) ]
|
local_ratings_services = [ service for service in services if service.GetType() in ( HC.LOCAL_RATING_LIKE, HC.LOCAL_RATING_NUMERICAL ) ]
|
||||||
|
|
||||||
i_can_post_ratings = len( local_ratings_services ) > 0
|
i_can_post_ratings = len( local_ratings_services ) > 0
|
||||||
|
|
||||||
|
@ -1550,25 +1591,33 @@ class CanvasFullscreenMediaListBrowser( CanvasFullscreenMediaList ):
|
||||||
|
|
||||||
menu.AppendSeparator()
|
menu.AppendSeparator()
|
||||||
|
|
||||||
menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'manage_tags' ), 'manage tags' )
|
manage_menu = wx.Menu()
|
||||||
|
|
||||||
if i_can_post_ratings: menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'manage_ratings' ), 'manage ratings' )
|
manage_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'manage_tags' ), 'tags' )
|
||||||
|
|
||||||
|
if i_can_post_ratings: manage_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'manage_ratings' ), 'ratings' )
|
||||||
|
|
||||||
|
menu.AppendMenu( CC.ID_NULL, 'manage', manage_menu )
|
||||||
|
|
||||||
menu.AppendSeparator()
|
menu.AppendSeparator()
|
||||||
|
|
||||||
if self._current_media.HasInbox(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'archive' ), '&archive' )
|
if self._current_media.HasInbox(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'archive' ), '&archive' )
|
||||||
if self._current_media.HasArchive(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'inbox' ), 'return to &inbox' )
|
if self._current_media.HasArchive(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'inbox' ), 'return to &inbox' )
|
||||||
|
menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'remove', HC.LOCAL_FILE_SERVICE_IDENTIFIER ), '&remove' )
|
||||||
menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'delete', HC.LOCAL_FILE_SERVICE_IDENTIFIER ), '&delete' )
|
menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'delete', HC.LOCAL_FILE_SERVICE_IDENTIFIER ), '&delete' )
|
||||||
|
|
||||||
menu.AppendSeparator()
|
share_menu = wx.Menu()
|
||||||
|
|
||||||
copy_menu = wx.Menu()
|
copy_menu = wx.Menu()
|
||||||
|
|
||||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_files' ) , 'file' )
|
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_files' ) , 'file' )
|
||||||
|
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_hash' ) , 'hash' )
|
||||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_path' ) , 'path' )
|
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_path' ) , 'path' )
|
||||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_local_url' ) , 'local url' )
|
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_local_url' ) , 'local url' )
|
||||||
|
|
||||||
menu.AppendMenu( CC.ID_NULL, 'copy', copy_menu )
|
share_menu.AppendMenu( CC.ID_NULL, 'copy', copy_menu )
|
||||||
|
|
||||||
|
menu.AppendMenu( CC.ID_NULL, 'share', share_menu )
|
||||||
|
|
||||||
menu.AppendSeparator()
|
menu.AppendSeparator()
|
||||||
|
|
||||||
|
@ -1582,7 +1631,7 @@ class CanvasFullscreenMediaListBrowser( CanvasFullscreenMediaList ):
|
||||||
slideshow.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'slideshow', 80 ), 'william gibson' )
|
slideshow.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'slideshow', 80 ), 'william gibson' )
|
||||||
slideshow.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'slideshow' ), 'custom interval' )
|
slideshow.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'slideshow' ), 'custom interval' )
|
||||||
|
|
||||||
menu.AppendMenu( CC.ID_NULL, 'Start Slideshow', slideshow )
|
menu.AppendMenu( CC.ID_NULL, 'start slideshow', slideshow )
|
||||||
if self._timer_slideshow.IsRunning(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'slideshow_pause_play' ), 'stop slideshow' )
|
if self._timer_slideshow.IsRunning(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'slideshow_pause_play' ), 'stop slideshow' )
|
||||||
|
|
||||||
self._menu_open = True
|
self._menu_open = True
|
||||||
|
@ -1838,6 +1887,7 @@ class CanvasFullscreenMediaListCustomFilter( CanvasFullscreenMediaList ):
|
||||||
if command == 'archive': self._Archive()
|
if command == 'archive': self._Archive()
|
||||||
elif command == 'copy_files':
|
elif command == 'copy_files':
|
||||||
with wx.BusyCursor(): HC.app.Write( 'copy_files', ( self._current_media.GetHash(), ) )
|
with wx.BusyCursor(): HC.app.Write( 'copy_files', ( self._current_media.GetHash(), ) )
|
||||||
|
elif command == 'copy_hash': self._CopyHashToClipboard()
|
||||||
elif command == 'copy_local_url': self._CopyLocalUrlToClipboard()
|
elif command == 'copy_local_url': self._CopyLocalUrlToClipboard()
|
||||||
elif command == 'copy_path': self._CopyPathToClipboard()
|
elif command == 'copy_path': self._CopyPathToClipboard()
|
||||||
elif command == 'delete': self._Delete()
|
elif command == 'delete': self._Delete()
|
||||||
|
@ -1851,6 +1901,7 @@ class CanvasFullscreenMediaListCustomFilter( CanvasFullscreenMediaList ):
|
||||||
elif command == 'inbox': self._Inbox()
|
elif command == 'inbox': self._Inbox()
|
||||||
elif command == 'manage_ratings': self._ManageRatings()
|
elif command == 'manage_ratings': self._ManageRatings()
|
||||||
elif command == 'manage_tags': self._ManageTags()
|
elif command == 'manage_tags': self._ManageTags()
|
||||||
|
elif command == 'remove': self._Remove()
|
||||||
elif command == 'slideshow': self._StartSlideshow( data )
|
elif command == 'slideshow': self._StartSlideshow( data )
|
||||||
elif command == 'slideshow_pause_play': self._PausePlaySlideshow()
|
elif command == 'slideshow_pause_play': self._PausePlaySlideshow()
|
||||||
elif command == 'zoom_in': self._ZoomIn()
|
elif command == 'zoom_in': self._ZoomIn()
|
||||||
|
@ -1914,19 +1965,35 @@ class CanvasFullscreenMediaListCustomFilter( CanvasFullscreenMediaList ):
|
||||||
|
|
||||||
menu.AppendSeparator()
|
menu.AppendSeparator()
|
||||||
|
|
||||||
|
manage_menu = wx.Menu()
|
||||||
|
|
||||||
|
manage_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'manage_tags' ), 'tags' )
|
||||||
|
|
||||||
|
if i_can_post_ratings: manage_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'manage_ratings' ), 'ratings' )
|
||||||
|
|
||||||
|
menu.AppendMenu( CC.ID_NULL, 'manage', manage_menu )
|
||||||
|
|
||||||
|
menu.AppendSeparator()
|
||||||
|
|
||||||
if self._current_media.HasInbox(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'archive' ), '&archive' )
|
if self._current_media.HasInbox(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'archive' ), '&archive' )
|
||||||
if self._current_media.HasArchive(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'inbox' ), 'return to &inbox' )
|
if self._current_media.HasArchive(): menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'inbox' ), 'return to &inbox' )
|
||||||
|
menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'remove', HC.LOCAL_FILE_SERVICE_IDENTIFIER ), '&remove' )
|
||||||
menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'delete', HC.LOCAL_FILE_SERVICE_IDENTIFIER ), '&delete' )
|
menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'delete', HC.LOCAL_FILE_SERVICE_IDENTIFIER ), '&delete' )
|
||||||
|
|
||||||
menu.AppendSeparator()
|
menu.AppendSeparator()
|
||||||
|
|
||||||
|
share_menu = wx.Menu()
|
||||||
|
|
||||||
copy_menu = wx.Menu()
|
copy_menu = wx.Menu()
|
||||||
|
|
||||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_files' ) , 'file' )
|
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_files' ) , 'file' )
|
||||||
|
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_hash' ) , 'hash' )
|
||||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_path' ) , 'path' )
|
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_path' ) , 'path' )
|
||||||
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_local_url' ) , 'local url' )
|
copy_menu.Append( CC.MENU_EVENT_ID_TO_ACTION_CACHE.GetId( 'copy_local_url' ) , 'local url' )
|
||||||
|
|
||||||
menu.AppendMenu( CC.ID_NULL, 'copy', copy_menu )
|
share_menu.AppendMenu( CC.ID_NULL, 'copy', copy_menu )
|
||||||
|
|
||||||
|
menu.AppendMenu( CC.ID_NULL, 'share', share_menu )
|
||||||
|
|
||||||
menu.AppendSeparator()
|
menu.AppendSeparator()
|
||||||
|
|
||||||
|
@ -2578,7 +2645,7 @@ class RatingsFilterFrameLike( CanvasFullscreenMediaListFilter ):
|
||||||
CanvasFullscreenMediaListFilter.__init__( self, my_parent, page_key, HC.LOCAL_FILE_SERVICE_IDENTIFIER, [], media_results )
|
CanvasFullscreenMediaListFilter.__init__( self, my_parent, page_key, HC.LOCAL_FILE_SERVICE_IDENTIFIER, [], media_results )
|
||||||
|
|
||||||
self._rating_service_identifier = service_identifier
|
self._rating_service_identifier = service_identifier
|
||||||
self._service = HC.app.Read( 'service', service_identifier )
|
self._service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
FullscreenPopoutFilterLike( self )
|
FullscreenPopoutFilterLike( self )
|
||||||
|
|
||||||
|
@ -2651,7 +2718,7 @@ class RatingsFilterFrameNumerical( ClientGUICommon.FrameThatResizes ):
|
||||||
if service_identifier.GetType() == HC.LOCAL_RATING_LIKE: self._score_gap = 1.0
|
if service_identifier.GetType() == HC.LOCAL_RATING_LIKE: self._score_gap = 1.0
|
||||||
else:
|
else:
|
||||||
|
|
||||||
self._service = HC.app.Read( 'service', service_identifier )
|
self._service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
( self._lower, self._upper ) = self._service.GetLowerUpper()
|
( self._lower, self._upper ) = self._service.GetLowerUpper()
|
||||||
|
|
||||||
|
|
|
@ -2607,6 +2607,8 @@ class PopupMessageGauge( PopupMessage ):
|
||||||
|
|
||||||
PopupMessage.__init__( self, parent, message )
|
PopupMessage.__init__( self, parent, message )
|
||||||
|
|
||||||
|
self._job_key = self._message.GetJobKey()
|
||||||
|
|
||||||
self._done = False
|
self._done = False
|
||||||
|
|
||||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||||
|
@ -2620,11 +2622,16 @@ class PopupMessageGauge( PopupMessage ):
|
||||||
self._gauge = Gauge( self, size = ( 380, -1 ) )
|
self._gauge = Gauge( self, size = ( 380, -1 ) )
|
||||||
self._gauge.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
self._gauge.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||||
|
|
||||||
|
self._pause_button = wx.Button( self, label = 'pause' )
|
||||||
|
self._pause_button.Bind( wx.EVT_BUTTON, self.EventPauseButton )
|
||||||
|
self._pause_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||||
|
|
||||||
self._cancel_button = wx.Button( self, label = 'cancel' )
|
self._cancel_button = wx.Button( self, label = 'cancel' )
|
||||||
self._cancel_button.Bind( wx.EVT_BUTTON, self.EventCancelButton )
|
self._cancel_button.Bind( wx.EVT_BUTTON, self.EventCancelButton )
|
||||||
self._cancel_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
self._cancel_button.Bind( wx.EVT_RIGHT_DOWN, self.EventDismiss )
|
||||||
|
|
||||||
hbox.AddF( self._gauge, FLAGS_EXPAND_BOTH_WAYS )
|
hbox.AddF( self._gauge, FLAGS_EXPAND_BOTH_WAYS )
|
||||||
|
hbox.AddF( self._pause_button, FLAGS_MIXED )
|
||||||
hbox.AddF( self._cancel_button, FLAGS_MIXED )
|
hbox.AddF( self._cancel_button, FLAGS_MIXED )
|
||||||
|
|
||||||
self._show_file_button = wx.Button( self )
|
self._show_file_button = wx.Button( self )
|
||||||
|
@ -2637,6 +2644,8 @@ class PopupMessageGauge( PopupMessage ):
|
||||||
|
|
||||||
self.SetSizer( vbox )
|
self.SetSizer( vbox )
|
||||||
|
|
||||||
|
self._created = HC.GetNow()
|
||||||
|
|
||||||
|
|
||||||
def Dismiss( self ):
|
def Dismiss( self ):
|
||||||
|
|
||||||
|
@ -2653,6 +2662,8 @@ class PopupMessageGauge( PopupMessage ):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if self._job_key.IsPaused(): self._job_key.Cancel()
|
||||||
|
|
||||||
PopupMessage.Dismiss( self )
|
PopupMessage.Dismiss( self )
|
||||||
|
|
||||||
|
|
||||||
|
@ -2660,14 +2671,28 @@ class PopupMessageGauge( PopupMessage ):
|
||||||
|
|
||||||
if self._message.GetInfo( 'mode' ) == 'cancelable gauge':
|
if self._message.GetInfo( 'mode' ) == 'cancelable gauge':
|
||||||
|
|
||||||
job_key = self._message.GetInfo( 'job_key' )
|
self._job_key.Cancel()
|
||||||
|
|
||||||
job_key.Cancel()
|
|
||||||
|
|
||||||
self._cancel_button.Disable()
|
self._cancel_button.Disable()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def EventPauseButton( self, event ):
|
||||||
|
|
||||||
|
if self._job_key.IsPaused():
|
||||||
|
|
||||||
|
self._job_key.Resume()
|
||||||
|
|
||||||
|
self._pause_button.SetLabel( 'pause' )
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
self._job_key.Pause()
|
||||||
|
|
||||||
|
self._pause_button.SetLabel( 'resume' )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def EventShowFileButton( self, event ):
|
def EventShowFileButton( self, event ):
|
||||||
|
|
||||||
hashes = self._message.GetInfo( 'hashes' )
|
hashes = self._message.GetInfo( 'hashes' )
|
||||||
|
@ -2681,6 +2706,9 @@ class PopupMessageGauge( PopupMessage ):
|
||||||
|
|
||||||
mode = self._message.GetInfo( 'mode' )
|
mode = self._message.GetInfo( 'mode' )
|
||||||
text = self._message.GetInfo( 'text' )
|
text = self._message.GetInfo( 'text' )
|
||||||
|
|
||||||
|
if self._job_key.IsPausable(): self._pause_button.Show()
|
||||||
|
else: self._pause_button.Hide()
|
||||||
|
|
||||||
if mode == 'files':
|
if mode == 'files':
|
||||||
|
|
||||||
|
@ -3667,7 +3695,7 @@ class AdvancedTagOptions( AdvancedOptions ):
|
||||||
self._namespaces = namespaces
|
self._namespaces = namespaces
|
||||||
self._initial_settings = initial_settings
|
self._initial_settings = initial_settings
|
||||||
|
|
||||||
self._service_identifiers_to_checkbox_info = {}
|
self._service_keys_to_checkbox_info = {}
|
||||||
|
|
||||||
AdvancedOptions.__init__( self, parent, 'advanced tag options' )
|
AdvancedOptions.__init__( self, parent, 'advanced tag options' )
|
||||||
|
|
||||||
|
@ -3678,21 +3706,23 @@ class AdvancedTagOptions( AdvancedOptions ):
|
||||||
|
|
||||||
self._vbox.Clear( True )
|
self._vbox.Clear( True )
|
||||||
|
|
||||||
self._service_identifiers_to_checkbox_info = {}
|
self._service_keys_to_checkbox_info = {}
|
||||||
|
|
||||||
service_identifiers = HC.app.Read( 'service_identifiers', ( HC.TAG_REPOSITORY, HC.LOCAL_TAG ) )
|
services = HC.app.GetManager( 'services' ).GetServices( ( HC.TAG_REPOSITORY, HC.LOCAL_TAG ) )
|
||||||
|
|
||||||
if len( service_identifiers ) > 0:
|
if len( services ) > 0:
|
||||||
|
|
||||||
outer_gridbox = wx.FlexGridSizer( 0, 2 )
|
outer_gridbox = wx.FlexGridSizer( 0, 2 )
|
||||||
|
|
||||||
outer_gridbox.AddGrowableCol( 1, 1 )
|
outer_gridbox.AddGrowableCol( 1, 1 )
|
||||||
|
|
||||||
for service_identifier in service_identifiers:
|
for service in services:
|
||||||
|
|
||||||
self._service_identifiers_to_checkbox_info[ service_identifier ] = []
|
service_key = service.GetKey()
|
||||||
|
|
||||||
outer_gridbox.AddF( wx.StaticText( panel, label = service_identifier.GetName() ), FLAGS_MIXED )
|
self._service_keys_to_checkbox_info[ service_key ] = []
|
||||||
|
|
||||||
|
outer_gridbox.AddF( wx.StaticText( panel, label = service.GetName() ), FLAGS_MIXED )
|
||||||
|
|
||||||
vbox = wx.BoxSizer( wx.VERTICAL )
|
vbox = wx.BoxSizer( wx.VERTICAL )
|
||||||
|
|
||||||
|
@ -3703,12 +3733,12 @@ class AdvancedTagOptions( AdvancedOptions ):
|
||||||
|
|
||||||
namespace_checkbox = wx.CheckBox( panel, label = label )
|
namespace_checkbox = wx.CheckBox( panel, label = label )
|
||||||
|
|
||||||
if service_identifier in self._initial_settings and namespace in self._initial_settings[ service_identifier ]: namespace_checkbox.SetValue( True )
|
if service_key in self._initial_settings and namespace in self._initial_settings[ service_key ]: namespace_checkbox.SetValue( True )
|
||||||
else: namespace_checkbox.SetValue( False )
|
else: namespace_checkbox.SetValue( False )
|
||||||
|
|
||||||
namespace_checkbox.Bind( wx.EVT_CHECKBOX, self.EventChecked )
|
namespace_checkbox.Bind( wx.EVT_CHECKBOX, self.EventChecked )
|
||||||
|
|
||||||
self._service_identifiers_to_checkbox_info[ service_identifier ].append( ( namespace, namespace_checkbox ) )
|
self._service_keys_to_checkbox_info[ service_key ].append( ( namespace, namespace_checkbox ) )
|
||||||
|
|
||||||
vbox.AddF( namespace_checkbox, FLAGS_EXPAND_BOTH_WAYS )
|
vbox.AddF( namespace_checkbox, FLAGS_EXPAND_BOTH_WAYS )
|
||||||
|
|
||||||
|
@ -3746,11 +3776,11 @@ class AdvancedTagOptions( AdvancedOptions ):
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
|
|
||||||
for ( service_identifier, checkbox_info ) in self._service_identifiers_to_checkbox_info.items():
|
for ( service_key, checkbox_info ) in self._service_keys_to_checkbox_info.items():
|
||||||
|
|
||||||
namespaces = [ namespace for ( namespace, checkbox ) in checkbox_info if checkbox.GetValue() == True ]
|
namespaces = [ namespace for ( namespace, checkbox ) in checkbox_info if checkbox.GetValue() == True ]
|
||||||
|
|
||||||
result[ service_identifier ] = namespaces
|
result[ service_key ] = namespaces
|
||||||
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -3767,13 +3797,13 @@ class AdvancedTagOptions( AdvancedOptions ):
|
||||||
|
|
||||||
def SetInfo( self, info ):
|
def SetInfo( self, info ):
|
||||||
|
|
||||||
for ( service_identifier, checkbox_info ) in self._service_identifiers_to_checkbox_info.items():
|
for ( service_key, checkbox_info ) in self._service_keys_to_checkbox_info.items():
|
||||||
|
|
||||||
if service_identifier in info:
|
if service_key in info:
|
||||||
|
|
||||||
for ( namespace, checkbox ) in checkbox_info:
|
for ( namespace, checkbox ) in checkbox_info:
|
||||||
|
|
||||||
if namespace in info[ service_identifier ]: checkbox.SetValue( True )
|
if namespace in info[ service_key ]: checkbox.SetValue( True )
|
||||||
else: checkbox.SetValue( False )
|
else: checkbox.SetValue( False )
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ def SelectServiceIdentifier( permission = None, service_types = HC.ALL_SERVICES,
|
||||||
|
|
||||||
if service_identifiers is None:
|
if service_identifiers is None:
|
||||||
|
|
||||||
services = HC.app.Read( 'services', service_types )
|
services = HC.app.GetManager( 'services' ).GetServices( service_types )
|
||||||
|
|
||||||
if permission is not None: services = [ service for service in services if service.GetInfo( 'account' ).HasPermission( permission ) ]
|
if permission is not None: services = [ service for service in services if service.GetInfo( 'account' ).HasPermission( permission ) ]
|
||||||
|
|
||||||
|
@ -608,7 +608,7 @@ class DialogGenerateNewAccounts( Dialog ):
|
||||||
|
|
||||||
self._num.SetValue( 1 )
|
self._num.SetValue( 1 )
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
response = service.Request( HC.GET, 'account_types' )
|
response = service.Request( HC.GET, 'account_types' )
|
||||||
|
|
||||||
|
@ -670,7 +670,7 @@ class DialogGenerateNewAccounts( Dialog ):
|
||||||
|
|
||||||
lifetime = self._lifetime.GetClientData( self._lifetime.GetSelection() )
|
lifetime = self._lifetime.GetClientData( self._lifetime.GetSelection() )
|
||||||
|
|
||||||
service = HC.app.Read( 'service', self._service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( self._service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
|
@ -894,7 +894,7 @@ class DialogInputCustomFilterAction( Dialog ):
|
||||||
|
|
||||||
service_identifier = self._ratings_like_service_identifiers.GetClientData( selection )
|
service_identifier = self._ratings_like_service_identifiers.GetClientData( selection )
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
self._current_ratings_like_service = service
|
self._current_ratings_like_service = service
|
||||||
|
|
||||||
|
@ -918,7 +918,7 @@ class DialogInputCustomFilterAction( Dialog ):
|
||||||
|
|
||||||
service_identifier = self._ratings_numerical_service_identifiers.GetClientData( selection )
|
service_identifier = self._ratings_numerical_service_identifiers.GetClientData( selection )
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
self._current_ratings_numerical_service = service
|
self._current_ratings_numerical_service = service
|
||||||
|
|
||||||
|
@ -1535,8 +1535,8 @@ class DialogInputFileSystemPredicate( Dialog ):
|
||||||
|
|
||||||
def PopulateControls():
|
def PopulateControls():
|
||||||
|
|
||||||
self._local_numericals = HC.app.Read( 'services', ( HC.LOCAL_RATING_NUMERICAL, ) )
|
self._local_numericals = HC.app.GetManager( 'services' ).GetServices( ( HC.LOCAL_RATING_NUMERICAL, ) )
|
||||||
self._local_likes = HC.app.Read( 'services', ( HC.LOCAL_RATING_LIKE, ) )
|
self._local_likes = HC.app.GetManager( 'services' ).GetServices( ( HC.LOCAL_RATING_LIKE, ) )
|
||||||
|
|
||||||
for service in self._local_numericals: self._service_numerical.Append( service.GetServiceIdentifier().GetName(), service )
|
for service in self._local_numericals: self._service_numerical.Append( service.GetServiceIdentifier().GetName(), service )
|
||||||
|
|
||||||
|
@ -2108,7 +2108,7 @@ class DialogInputLocalBooruShare( Dialog ):
|
||||||
|
|
||||||
def EventCopyExternalShareURL( self, event ):
|
def EventCopyExternalShareURL( self, event ):
|
||||||
|
|
||||||
self._service = HC.app.Read( 'service', HC.LOCAL_BOORU_SERVICE_IDENTIFIER )
|
self._service = HC.app.GetManager( 'services' ).GetService( HC.LOCAL_BOORU_SERVICE_IDENTIFIER.GetServiceKey() )
|
||||||
|
|
||||||
info = self._service.GetInfo()
|
info = self._service.GetInfo()
|
||||||
|
|
||||||
|
@ -2125,7 +2125,7 @@ class DialogInputLocalBooruShare( Dialog ):
|
||||||
|
|
||||||
def EventCopyInternalShareURL( self, event ):
|
def EventCopyInternalShareURL( self, event ):
|
||||||
|
|
||||||
self._service = HC.app.Read( 'service', HC.LOCAL_BOORU_SERVICE_IDENTIFIER )
|
self._service = HC.app.GetManager( 'services' ).GetService( HC.LOCAL_BOORU_SERVICE_IDENTIFIER.GetServiceKey() )
|
||||||
|
|
||||||
info = self._service.GetInfo()
|
info = self._service.GetInfo()
|
||||||
|
|
||||||
|
@ -3550,7 +3550,7 @@ class DialogModifyAccounts( Dialog ):
|
||||||
|
|
||||||
Dialog.__init__( self, parent, 'modify account' )
|
Dialog.__init__( self, parent, 'modify account' )
|
||||||
|
|
||||||
self._service = HC.app.Read( 'service', service_identifier )
|
self._service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
self._subject_identifiers = list( subject_identifiers )
|
self._subject_identifiers = list( subject_identifiers )
|
||||||
|
|
||||||
InitialiseControls()
|
InitialiseControls()
|
||||||
|
@ -3766,9 +3766,9 @@ class DialogPageChooser( Dialog ):
|
||||||
|
|
||||||
ArrangeControls()
|
ArrangeControls()
|
||||||
|
|
||||||
self._services = HC.app.Read( 'services' )
|
self._services = HC.app.GetManager( 'services' ).GetServices()
|
||||||
|
|
||||||
self._petition_service_identifiers = [ service.GetServiceIdentifier() for service in self._services if service.GetServiceIdentifier().GetType() in HC.REPOSITORIES and service.GetInfo( 'account' ).HasPermission( HC.RESOLVE_PETITIONS ) ]
|
self._petition_service_identifiers = [ service.GetServiceIdentifier() for service in self._services if service.GetType() in HC.REPOSITORIES and service.GetInfo( 'account' ).HasPermission( HC.RESOLVE_PETITIONS ) ]
|
||||||
|
|
||||||
self._InitButtons( 'home' )
|
self._InitButtons( 'home' )
|
||||||
|
|
||||||
|
@ -3975,7 +3975,7 @@ class DialogPathsToTagsRegex( Dialog ):
|
||||||
|
|
||||||
def PopulateControls():
|
def PopulateControls():
|
||||||
|
|
||||||
services = HC.app.Read( 'services', ( HC.TAG_REPOSITORY, ) )
|
services = HC.app.GetManager( 'services' ).GetServices( ( HC.TAG_REPOSITORY, ) )
|
||||||
|
|
||||||
for service in services:
|
for service in services:
|
||||||
|
|
||||||
|
@ -3999,7 +3999,9 @@ class DialogPathsToTagsRegex( Dialog ):
|
||||||
|
|
||||||
self._tag_repositories.AddPage( page, name )
|
self._tag_repositories.AddPage( page, name )
|
||||||
|
|
||||||
default_tag_repository = HC.options[ 'default_tag_repository' ]
|
default_tag_repository_key = HC.options[ 'default_tag_repository' ]
|
||||||
|
|
||||||
|
default_tag_repository = HC.app.GetManager( 'services' ).GetService( default_tag_repository_key )
|
||||||
|
|
||||||
self._tag_repositories.Select( default_tag_repository.GetName() )
|
self._tag_repositories.Select( default_tag_repository.GetName() )
|
||||||
|
|
||||||
|
@ -4890,6 +4892,8 @@ class DialogSelectYoutubeURL( Dialog ):
|
||||||
|
|
||||||
url_string = title + ' ' + resolution + ' ' + extension
|
url_string = title + ' ' + resolution + ' ' + extension
|
||||||
|
|
||||||
|
job_key = HC.JobKey( pausable = False, cancellable = False )
|
||||||
|
|
||||||
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, url_string )
|
message = HC.MessageGauge( HC.MESSAGE_TYPE_GAUGE, url_string )
|
||||||
|
|
||||||
HydrusThreading.CallToThread( HydrusDownloading.THREADDownloadURL, message, url, url_string )
|
HydrusThreading.CallToThread( HydrusDownloading.THREADDownloadURL, message, url, url_string )
|
||||||
|
|
|
@ -209,7 +209,7 @@ class DialogManageAccountTypes( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
def PopulateControls():
|
def PopulateControls():
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
response = service.Request( HC.GET, 'account_types' )
|
response = service.Request( HC.GET, 'account_types' )
|
||||||
|
|
||||||
|
@ -383,7 +383,7 @@ class DialogManageAccountTypes( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
def EventOK( self, event ):
|
def EventOK( self, event ):
|
||||||
|
|
||||||
service = HC.app.Read( 'service', self._service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( self._service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
service.Request( HC.POST, 'account_types', { 'edit_log' : self._edit_log } )
|
service.Request( HC.POST, 'account_types', { 'edit_log' : self._edit_log } )
|
||||||
|
|
||||||
|
@ -2845,7 +2845,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
||||||
self._default_tag_sort.Append( 'incidence (desc)', CC.SORT_BY_INCIDENCE_DESC )
|
self._default_tag_sort.Append( 'incidence (desc)', CC.SORT_BY_INCIDENCE_DESC )
|
||||||
self._default_tag_sort.Append( 'incidence (asc)', CC.SORT_BY_INCIDENCE_ASC )
|
self._default_tag_sort.Append( 'incidence (asc)', CC.SORT_BY_INCIDENCE_ASC )
|
||||||
|
|
||||||
self._default_tag_repository = wx.Choice( self._gui_page )
|
self._default_tag_repository = ClientGUICommon.BetterChoice( self._gui_page )
|
||||||
|
|
||||||
self._fullscreen_borderless = wx.CheckBox( self._gui_page )
|
self._fullscreen_borderless = wx.CheckBox( self._gui_page )
|
||||||
|
|
||||||
|
@ -3050,11 +3050,13 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
||||||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_DESC: self._default_tag_sort.Select( 2 )
|
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_DESC: self._default_tag_sort.Select( 2 )
|
||||||
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_ASC: self._default_tag_sort.Select( 3 )
|
elif HC.options[ 'default_tag_sort' ] == CC.SORT_BY_INCIDENCE_ASC: self._default_tag_sort.Select( 3 )
|
||||||
|
|
||||||
service_identifiers = HC.app.Read( 'service_identifiers', ( HC.LOCAL_TAG, HC.TAG_REPOSITORY ) )
|
services = HC.app.GetManager( 'services' ).GetServices( ( HC.LOCAL_TAG, HC.TAG_REPOSITORY ) )
|
||||||
|
|
||||||
for service_identifier in service_identifiers: self._default_tag_repository.Append( service_identifier.GetName(), service_identifier )
|
for service in services: self._default_tag_repository.Append( service.GetName(), service.GetKey() )
|
||||||
|
|
||||||
self._default_tag_repository.SetStringSelection( HC.options[ 'default_tag_repository' ].GetName() )
|
default_tag_repository_key = HC.options[ 'default_tag_repository' ]
|
||||||
|
|
||||||
|
self._default_tag_repository.SelectClientData( default_tag_repository_key )
|
||||||
|
|
||||||
self._fullscreen_borderless.SetValue( HC.options[ 'fullscreen_borderless' ] )
|
self._fullscreen_borderless.SetValue( HC.options[ 'fullscreen_borderless' ] )
|
||||||
|
|
||||||
|
@ -3644,7 +3646,7 @@ class DialogManageOptions( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
HC.options[ 'shortcuts' ] = shortcuts
|
HC.options[ 'shortcuts' ] = shortcuts
|
||||||
|
|
||||||
HC.options[ 'default_tag_repository' ] = self._default_tag_repository.GetClientData( self._default_tag_repository.GetSelection() )
|
HC.options[ 'default_tag_repository' ] = self._default_tag_repository.GetChoice()
|
||||||
HC.options[ 'default_tag_sort' ] = self._default_tag_sort.GetClientData( self._default_tag_sort.GetSelection() )
|
HC.options[ 'default_tag_sort' ] = self._default_tag_sort.GetClientData( self._default_tag_sort.GetSelection() )
|
||||||
|
|
||||||
new_local_port = self._local_port.GetValue()
|
new_local_port = self._local_port.GetValue()
|
||||||
|
@ -3948,7 +3950,7 @@ class DialogManageRatings( ClientGUIDialogs.Dialog ):
|
||||||
wx.Panel.__init__( self, parent )
|
wx.Panel.__init__( self, parent )
|
||||||
|
|
||||||
self._service_identifier = service_identifier
|
self._service_identifier = service_identifier
|
||||||
self._service = HC.app.Read( 'service', service_identifier )
|
self._service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
self._media = media
|
self._media = media
|
||||||
|
|
||||||
|
@ -4290,7 +4292,7 @@ class DialogManageServer( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
self._service_identifier = service_identifier
|
self._service_identifier = service_identifier
|
||||||
|
|
||||||
self._service = HC.app.Read( 'service', self._service_identifier )
|
self._service = HC.app.GetManager( 'services' ).GetService( self._service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
InitialiseControls()
|
InitialiseControls()
|
||||||
|
|
||||||
|
@ -4606,7 +4608,7 @@ class DialogManageServices( ClientGUIDialogs.Dialog ):
|
||||||
parent_listbook.AddPage( listbook, name )
|
parent_listbook.AddPage( listbook, name )
|
||||||
|
|
||||||
|
|
||||||
services = HC.app.Read( 'services', manageable_service_types )
|
services = HC.app.GetManager( 'services' ).GetServices( manageable_service_types )
|
||||||
|
|
||||||
for service in services:
|
for service in services:
|
||||||
|
|
||||||
|
@ -5960,9 +5962,11 @@ class DialogManageTagCensorship( ClientGUIDialogs.Dialog ):
|
||||||
self._tag_services.AddPage( page, name )
|
self._tag_services.AddPage( page, name )
|
||||||
|
|
||||||
|
|
||||||
default_tag_repository = HC.options[ 'default_tag_repository' ]
|
default_tag_repository_key = HC.options[ 'default_tag_repository' ]
|
||||||
|
|
||||||
self._tag_services.Select( default_tag_repository.GetName() )
|
service = HC.app.GetManager( 'services' ).GetService( default_tag_repository_key )
|
||||||
|
|
||||||
|
self._tag_services.Select( service.GetName() )
|
||||||
|
|
||||||
|
|
||||||
def ArrangeControls():
|
def ArrangeControls():
|
||||||
|
@ -6130,7 +6134,7 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
def PopulateControls():
|
def PopulateControls():
|
||||||
|
|
||||||
services = HC.app.Read( 'services', ( HC.TAG_REPOSITORY, ) )
|
services = HC.app.GetManager( 'services' ).GetServices( ( HC.TAG_REPOSITORY, ) )
|
||||||
|
|
||||||
for service in services:
|
for service in services:
|
||||||
|
|
||||||
|
@ -6154,9 +6158,11 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
self._tag_repositories.AddPage( page, name )
|
self._tag_repositories.AddPage( page, name )
|
||||||
|
|
||||||
default_tag_repository = HC.options[ 'default_tag_repository' ]
|
default_tag_repository_key = HC.options[ 'default_tag_repository' ]
|
||||||
|
|
||||||
self._tag_repositories.Select( default_tag_repository.GetName() )
|
service = HC.app.GetManager( 'services' ).GetService( default_tag_repository_key )
|
||||||
|
|
||||||
|
self._tag_repositories.Select( service.GetName() )
|
||||||
|
|
||||||
|
|
||||||
def ArrangeControls():
|
def ArrangeControls():
|
||||||
|
@ -6309,7 +6315,7 @@ class DialogManageTagParents( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
if self._service_identifier != HC.LOCAL_TAG_SERVICE_IDENTIFIER:
|
if self._service_identifier != HC.LOCAL_TAG_SERVICE_IDENTIFIER:
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
self._account = service.GetInfo( 'account' )
|
self._account = service.GetInfo( 'account' )
|
||||||
|
|
||||||
|
@ -6598,7 +6604,7 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
self._tag_repositories.AddPage( page, name )
|
self._tag_repositories.AddPage( page, name )
|
||||||
|
|
||||||
services = HC.app.Read( 'services', ( HC.TAG_REPOSITORY, ) )
|
services = HC.app.GetManager( 'services' ).GetServices( ( HC.TAG_REPOSITORY, ) )
|
||||||
|
|
||||||
for service in services:
|
for service in services:
|
||||||
|
|
||||||
|
@ -6616,9 +6622,11 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
default_tag_repository = HC.options[ 'default_tag_repository' ]
|
default_tag_repository_key = HC.options[ 'default_tag_repository' ]
|
||||||
|
|
||||||
self._tag_repositories.Select( default_tag_repository.GetName() )
|
service = HC.app.GetManager( 'services' ).GetService( default_tag_repository_key )
|
||||||
|
|
||||||
|
self._tag_repositories.Select( service.GetName() )
|
||||||
|
|
||||||
|
|
||||||
def ArrangeControls():
|
def ArrangeControls():
|
||||||
|
@ -6777,7 +6785,7 @@ class DialogManageTagSiblings( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
if self._service_identifier != HC.LOCAL_TAG_SERVICE_IDENTIFIER:
|
if self._service_identifier != HC.LOCAL_TAG_SERVICE_IDENTIFIER:
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
self._account = service.GetInfo( 'account' )
|
self._account = service.GetInfo( 'account' )
|
||||||
|
|
||||||
|
@ -7273,9 +7281,11 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
||||||
self._tag_repositories.AddPage( page_info, name )
|
self._tag_repositories.AddPage( page_info, name )
|
||||||
|
|
||||||
|
|
||||||
default_tag_repository = HC.options[ 'default_tag_repository' ]
|
default_tag_repository_key = HC.options[ 'default_tag_repository' ]
|
||||||
|
|
||||||
self._tag_repositories.Select( default_tag_repository.GetName() )
|
service = HC.app.GetManager( 'services' ).GetService( default_tag_repository_key )
|
||||||
|
|
||||||
|
self._tag_repositories.Select( service.GetName() )
|
||||||
|
|
||||||
|
|
||||||
def ArrangeControls():
|
def ArrangeControls():
|
||||||
|
@ -7449,7 +7459,7 @@ class DialogManageTags( ClientGUIDialogs.Dialog ):
|
||||||
|
|
||||||
if not self._i_am_local_tag_service:
|
if not self._i_am_local_tag_service:
|
||||||
|
|
||||||
service = HC.app.Read( 'service', tag_service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( tag_service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
self._account = service.GetInfo( 'account' )
|
self._account = service.GetInfo( 'account' )
|
||||||
|
|
||||||
|
|
|
@ -639,10 +639,15 @@ class ManagementPanelDumper( ManagementPanel ):
|
||||||
|
|
||||||
advanced_tag_options = self._advanced_tag_options.GetInfo()
|
advanced_tag_options = self._advanced_tag_options.GetInfo()
|
||||||
|
|
||||||
for ( service_identifier, namespaces ) in advanced_tag_options.items():
|
for ( service_key, namespaces ) in advanced_tag_options.items():
|
||||||
|
|
||||||
tags_manager = media.GetTagsManager()
|
tags_manager = media.GetTagsManager()
|
||||||
|
|
||||||
|
try: service = HC.app.GetManager( 'services' ).GetService( service_key )
|
||||||
|
except: continue
|
||||||
|
|
||||||
|
service_identifier = service.GetKey()
|
||||||
|
|
||||||
current = tags_manager.GetCurrent( service_identifier )
|
current = tags_manager.GetCurrent( service_identifier )
|
||||||
pending = tags_manager.GetPending( service_identifier )
|
pending = tags_manager.GetPending( service_identifier )
|
||||||
|
|
||||||
|
@ -1820,7 +1825,7 @@ class ManagementPanelPetitions( ManagementPanel ):
|
||||||
|
|
||||||
ManagementPanel.__init__( self, parent, page, page_key, file_service_identifier, starting_from_session = starting_from_session )
|
ManagementPanel.__init__( self, parent, page, page_key, file_service_identifier, starting_from_session = starting_from_session )
|
||||||
|
|
||||||
self._service = HC.app.Read( 'service', self._petition_service_identifier )
|
self._service = HC.app.GetManager( 'services' ).GetService( self._petition_service_identifier.GetServiceKey() )
|
||||||
self._can_ban = self._service.GetInfo( 'account' ).HasPermission( HC.MANAGE_USERS )
|
self._can_ban = self._service.GetInfo( 'account' ).HasPermission( HC.MANAGE_USERS )
|
||||||
|
|
||||||
self._num_petitions = None
|
self._num_petitions = None
|
||||||
|
|
|
@ -91,6 +91,7 @@ class MediaPanel( ClientGUIMixins.ListeningMediaList, wx.ScrolledWindow ):
|
||||||
HC.pubsub.sub( self, 'Collect', 'collect_media' )
|
HC.pubsub.sub( self, 'Collect', 'collect_media' )
|
||||||
HC.pubsub.sub( self, 'Sort', 'sort_media' )
|
HC.pubsub.sub( self, 'Sort', 'sort_media' )
|
||||||
HC.pubsub.sub( self, 'FileDumped', 'file_dumped' )
|
HC.pubsub.sub( self, 'FileDumped', 'file_dumped' )
|
||||||
|
HC.pubsub.sub( self, 'RemoveMedia', 'remove_media' )
|
||||||
|
|
||||||
self._PublishSelectionChange()
|
self._PublishSelectionChange()
|
||||||
|
|
||||||
|
@ -815,6 +816,16 @@ class MediaPanel( ClientGUIMixins.ListeningMediaList, wx.ScrolledWindow ):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def RemoveMedia( self, page_key, hashes ):
|
||||||
|
|
||||||
|
if page_key == self._page_key:
|
||||||
|
|
||||||
|
media = self._GetMedia( hashes )
|
||||||
|
|
||||||
|
self._RemoveMedia( media, {} )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def SetFocussedMedia( self, page_key, media ):
|
def SetFocussedMedia( self, page_key, media ):
|
||||||
|
|
||||||
if page_key == self._page_key:
|
if page_key == self._page_key:
|
||||||
|
@ -1678,13 +1689,13 @@ class MediaPanelThumbnails( MediaPanel ):
|
||||||
|
|
||||||
multiple_selected = num_selected > 1
|
multiple_selected = num_selected > 1
|
||||||
|
|
||||||
services = HC.app.Read( 'services' )
|
services = HC.app.GetManager( 'services' ).GetServices()
|
||||||
|
|
||||||
tag_repositories = [ service for service in services if service.GetServiceIdentifier().GetType() == HC.TAG_REPOSITORY ]
|
tag_repositories = [ service for service in services if service.GetType() == HC.TAG_REPOSITORY ]
|
||||||
|
|
||||||
file_repositories = [ service for service in services if service.GetServiceIdentifier().GetType() == HC.FILE_REPOSITORY ]
|
file_repositories = [ service for service in services if service.GetType() == HC.FILE_REPOSITORY ]
|
||||||
|
|
||||||
local_ratings_services = [ service for service in services if service.GetServiceIdentifier().GetType() in ( HC.LOCAL_RATING_LIKE, HC.LOCAL_RATING_NUMERICAL ) ]
|
local_ratings_services = [ service for service in services if service.GetType() in ( HC.LOCAL_RATING_LIKE, HC.LOCAL_RATING_NUMERICAL ) ]
|
||||||
|
|
||||||
i_can_post_ratings = len( local_ratings_services ) > 0
|
i_can_post_ratings = len( local_ratings_services ) > 0
|
||||||
|
|
||||||
|
|
|
@ -626,7 +626,7 @@ class DestinationPanel( wx.Panel ):
|
||||||
elif command == 'read': status = 'read'
|
elif command == 'read': status = 'read'
|
||||||
elif command == 'unread': status = 'sent'
|
elif command == 'unread': status = 'sent'
|
||||||
|
|
||||||
my_message_depot = HC.app.Read( 'service', self._identity )
|
my_message_depot = HC.app.GetManager( 'services' ).GetService( self._identity.GetServiceKey() )
|
||||||
|
|
||||||
connection = my_message_depot.GetConnection()
|
connection = my_message_depot.GetConnection()
|
||||||
|
|
||||||
|
@ -1250,7 +1250,7 @@ class DraftPanel( wx.Panel ):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
my_message_depot = HC.app.Read( 'service', self._contact_from )
|
my_message_depot = HC.app.GetManager( 'services' ).GetService( self._contact_from.GetServiceKey() )
|
||||||
|
|
||||||
connection = my_message_depot.GetConnection()
|
connection = my_message_depot.GetConnection()
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ options = {}
|
||||||
# Misc
|
# Misc
|
||||||
|
|
||||||
NETWORK_VERSION = 13
|
NETWORK_VERSION = 13
|
||||||
SOFTWARE_VERSION = 125
|
SOFTWARE_VERSION = 126
|
||||||
|
|
||||||
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
UNSCALED_THUMBNAIL_DIMENSIONS = ( 200, 200 )
|
||||||
|
|
||||||
|
@ -1522,12 +1522,17 @@ class ClientServiceIdentifier( HydrusYAMLBase ):
|
||||||
|
|
||||||
def GetType( self ): return self._type
|
def GetType( self ): return self._type
|
||||||
|
|
||||||
LOCAL_FILE_SERVICE_IDENTIFIER = ClientServiceIdentifier( 'local files', LOCAL_FILE, 'local files' )
|
LOCAL_FILE_SERVICE_KEY = 'local files'
|
||||||
LOCAL_TAG_SERVICE_IDENTIFIER = ClientServiceIdentifier( 'local tags', LOCAL_TAG, 'local tags' )
|
LOCAL_TAG_SERVICE_KEY = 'local tags'
|
||||||
LOCAL_BOORU_SERVICE_IDENTIFIER = ClientServiceIdentifier( 'local booru', LOCAL_BOORU, 'local booru' )
|
LOCAL_BOORU_SERVICE_KEY = 'local booru'
|
||||||
COMBINED_FILE_SERVICE_IDENTIFIER = ClientServiceIdentifier( 'all known files', COMBINED_FILE, 'all known files' )
|
COMBINED_FILE_SERVICE_KEY = 'all known files'
|
||||||
COMBINED_TAG_SERVICE_IDENTIFIER = ClientServiceIdentifier( 'all known tags', COMBINED_TAG, 'all known tags' )
|
COMBINED_TAG_SERVICE_KEY = 'all known tags'
|
||||||
NULL_SERVICE_IDENTIFIER = ClientServiceIdentifier( '', NULL_SERVICE, 'no service' )
|
|
||||||
|
LOCAL_FILE_SERVICE_IDENTIFIER = ClientServiceIdentifier( LOCAL_FILE_SERVICE_KEY, LOCAL_FILE, 'local files' )
|
||||||
|
LOCAL_TAG_SERVICE_IDENTIFIER = ClientServiceIdentifier( LOCAL_TAG_SERVICE_KEY, LOCAL_TAG, 'local tags' )
|
||||||
|
LOCAL_BOORU_SERVICE_IDENTIFIER = ClientServiceIdentifier( LOCAL_BOORU_SERVICE_KEY, LOCAL_BOORU, 'local booru' )
|
||||||
|
COMBINED_FILE_SERVICE_IDENTIFIER = ClientServiceIdentifier( COMBINED_FILE_SERVICE_KEY, COMBINED_FILE, 'all known files' )
|
||||||
|
COMBINED_TAG_SERVICE_IDENTIFIER = ClientServiceIdentifier( COMBINED_TAG_SERVICE_KEY, COMBINED_TAG, 'all known tags' )
|
||||||
|
|
||||||
class ClientToServerUpdate( HydrusYAMLBase ):
|
class ClientToServerUpdate( HydrusYAMLBase ):
|
||||||
|
|
||||||
|
@ -1742,10 +1747,13 @@ class JobDatabase( object ):
|
||||||
|
|
||||||
class JobKey( object ):
|
class JobKey( object ):
|
||||||
|
|
||||||
def __init__( self ):
|
def __init__( self, pausable = True, cancellable = True ):
|
||||||
|
|
||||||
self._key = os.urandom( 32 )
|
self._key = os.urandom( 32 )
|
||||||
|
|
||||||
|
self._pausable = pausable
|
||||||
|
self._cancellable = cancellable
|
||||||
|
|
||||||
self._begun = threading.Event()
|
self._begun = threading.Event()
|
||||||
self._done = threading.Event()
|
self._done = threading.Event()
|
||||||
self._cancelled = threading.Event()
|
self._cancelled = threading.Event()
|
||||||
|
@ -1770,6 +1778,11 @@ class JobKey( object ):
|
||||||
self.Finish()
|
self.Finish()
|
||||||
|
|
||||||
|
|
||||||
|
def DeleteVariable( self, name ):
|
||||||
|
|
||||||
|
with self._variable_lock: del self._variables[ name ]
|
||||||
|
|
||||||
|
|
||||||
def Finish( self ): self._done.set()
|
def Finish( self ): self._done.set()
|
||||||
|
|
||||||
def GetKey( self ): return self._key
|
def GetKey( self ): return self._key
|
||||||
|
@ -1786,10 +1799,14 @@ class JobKey( object ):
|
||||||
|
|
||||||
def IsBegun( self ): return self._begun.is_set()
|
def IsBegun( self ): return self._begun.is_set()
|
||||||
|
|
||||||
|
def IsCancellable( self ): return self._cancellable
|
||||||
|
|
||||||
def IsCancelled( self ): return shutdown or self._cancelled.is_set()
|
def IsCancelled( self ): return shutdown or self._cancelled.is_set()
|
||||||
|
|
||||||
def IsDone( self ): return shutdown or self._done.is_set()
|
def IsDone( self ): return shutdown or self._done.is_set()
|
||||||
|
|
||||||
|
def IsPausable( self ): return self._pausable
|
||||||
|
|
||||||
def IsPaused( self ): return self._paused.is_set()
|
def IsPaused( self ): return self._paused.is_set()
|
||||||
|
|
||||||
def IsWorking( self ): return self.IsBegun() and not self.IsDone()
|
def IsWorking( self ): return self.IsBegun() and not self.IsDone()
|
||||||
|
@ -1804,6 +1821,10 @@ class JobKey( object ):
|
||||||
|
|
||||||
def Resume( self ): self._paused.clear()
|
def Resume( self ): self._paused.clear()
|
||||||
|
|
||||||
|
def SetCancellable( self, value ): self._cancellable = value
|
||||||
|
|
||||||
|
def SetPausable( self, value ): self._pausable = value
|
||||||
|
|
||||||
def SetVariable( self, name, value ):
|
def SetVariable( self, name, value ):
|
||||||
|
|
||||||
with self._variable_lock: self._variables[ name ] = value
|
with self._variable_lock: self._variables[ name ] = value
|
||||||
|
@ -1906,16 +1927,18 @@ class Message( object ):
|
||||||
|
|
||||||
class MessageGauge( Message ):
|
class MessageGauge( Message ):
|
||||||
|
|
||||||
def __init__( self, message_type, text ):
|
def __init__( self, message_type, text, job_key ):
|
||||||
|
|
||||||
info = {}
|
Message.__init__( self, message_type, {} )
|
||||||
|
|
||||||
info[ 'mode' ] = 'text'
|
self._info[ 'mode' ] = 'text'
|
||||||
info[ 'text' ] = text
|
self._info[ 'text' ] = text
|
||||||
|
|
||||||
Message.__init__( self, message_type, info )
|
self._job_key = job_key
|
||||||
|
|
||||||
|
|
||||||
|
def GetJobKey( self ): return self._job_key
|
||||||
|
|
||||||
class Predicate( HydrusYAMLBase ):
|
class Predicate( HydrusYAMLBase ):
|
||||||
|
|
||||||
yaml_tag = u'!Predicate'
|
yaml_tag = u'!Predicate'
|
||||||
|
@ -2224,7 +2247,8 @@ class ServerServiceIdentifier( HydrusYAMLBase ):
|
||||||
|
|
||||||
def GetType( self ): return self._type
|
def GetType( self ): return self._type
|
||||||
|
|
||||||
SERVER_ADMIN_IDENTIFIER = ServerServiceIdentifier( 'server admin', SERVER_ADMIN )
|
SERVER_ADMIN_KEY = 'server admin'
|
||||||
|
SERVER_ADMIN_IDENTIFIER = ServerServiceIdentifier( SERVER_ADMIN_KEY, SERVER_ADMIN )
|
||||||
|
|
||||||
class ServiceUpdate( object ):
|
class ServiceUpdate( object ):
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,10 @@ def ConvertTagsToServiceIdentifiersToTags( tags, advanced_tag_options ):
|
||||||
siblings_manager = HC.app.GetManager( 'tag_siblings' )
|
siblings_manager = HC.app.GetManager( 'tag_siblings' )
|
||||||
parents_manager = HC.app.GetManager( 'tag_parents' )
|
parents_manager = HC.app.GetManager( 'tag_parents' )
|
||||||
|
|
||||||
for ( service_identifier, namespaces ) in advanced_tag_options.items():
|
for ( service_key, namespaces ) in advanced_tag_options.items():
|
||||||
|
|
||||||
|
try: service_identifier = HC.app.GetManager( 'services' ).GetService( service_key ).GetServiceIdentifier()
|
||||||
|
except: continue
|
||||||
|
|
||||||
if len( namespaces ) > 0:
|
if len( namespaces ) > 0:
|
||||||
|
|
||||||
|
@ -1766,6 +1769,7 @@ def THREADDownloadURL( message, url, url_string ):
|
||||||
message.SetInfo( 'range', None )
|
message.SetInfo( 'range', None )
|
||||||
message.SetInfo( 'value', None )
|
message.SetInfo( 'value', None )
|
||||||
message.SetInfo( 'mode', 'gauge' )
|
message.SetInfo( 'mode', 'gauge' )
|
||||||
|
|
||||||
temp_path = HC.http.Request( HC.GET, url, response_to_path = True, report_hooks = [ hook ] )
|
temp_path = HC.http.Request( HC.GET, url, response_to_path = True, report_hooks = [ hook ] )
|
||||||
|
|
||||||
message.SetInfo( 'range', None )
|
message.SetInfo( 'range', None )
|
||||||
|
|
|
@ -120,7 +120,7 @@ class HydrusSessionManagerClient( object ):
|
||||||
|
|
||||||
# session key expired or not found
|
# session key expired or not found
|
||||||
|
|
||||||
service = HC.app.Read( 'service', service_identifier )
|
service = HC.app.GetManager( 'services' ).GetService( service_identifier.GetServiceKey() )
|
||||||
|
|
||||||
( response, cookies ) = service.Request( HC.GET, 'session_key', return_cookies = True )
|
( response, cookies ) = service.Request( HC.GET, 'session_key', return_cookies = True )
|
||||||
|
|
||||||
|
|
|
@ -2884,9 +2884,9 @@ def DAEMONUPnP():
|
||||||
|
|
||||||
service_identifiers = HC.app.ReadDaemon( 'service_identifiers' )
|
service_identifiers = HC.app.ReadDaemon( 'service_identifiers' )
|
||||||
|
|
||||||
all_options = { service_identifier : HC.app.ReadDaemon( 'options', service_identifier ) for service_identifier in service_identifiers }
|
all_infos = HC.app.ReadDaemon( 'services' )
|
||||||
|
|
||||||
for ( service_identifier, options ) in all_options.items():
|
for ( service_identifier, options ) in all_infos:
|
||||||
|
|
||||||
internal_port = options[ 'port' ]
|
internal_port = options[ 'port' ]
|
||||||
upnp = options[ 'upnp' ]
|
upnp = options[ 'upnp' ]
|
||||||
|
@ -2899,12 +2899,12 @@ def DAEMONUPnP():
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for ( service_identifier, options ) in all_options.items():
|
for ( service_identifier, options ) in all_infos:
|
||||||
|
|
||||||
internal_port = options[ 'port' ]
|
internal_port = options[ 'port' ]
|
||||||
upnp = options[ 'upnp' ]
|
upnp = options[ 'upnp' ]
|
||||||
|
|
||||||
if ( local_ip, internal_port ) not in our_mappings:
|
if upnp is not None and ( local_ip, internal_port ) not in our_mappings:
|
||||||
|
|
||||||
external_port = upnp
|
external_port = upnp
|
||||||
|
|
||||||
|
|
|
@ -961,14 +961,6 @@ class TestClientDB( unittest.TestCase ):
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
result = self._read( 'service', HC.LOCAL_FILE_SERVICE_IDENTIFIER )
|
|
||||||
|
|
||||||
self.assertEqual( result.GetServiceIdentifier(), HC.LOCAL_FILE_SERVICE_IDENTIFIER )
|
|
||||||
|
|
||||||
result = self._read( 'service', HC.LOCAL_TAG_SERVICE_IDENTIFIER )
|
|
||||||
|
|
||||||
self.assertEqual( result.GetServiceIdentifier(), HC.LOCAL_TAG_SERVICE_IDENTIFIER )
|
|
||||||
|
|
||||||
result = self._read( 'services', ( HC.LOCAL_FILE, HC.LOCAL_TAG ) )
|
result = self._read( 'services', ( HC.LOCAL_FILE, HC.LOCAL_TAG ) )
|
||||||
|
|
||||||
result_s_is = { service.GetServiceIdentifier() for service in result }
|
result_s_is = { service.GetServiceIdentifier() for service in result }
|
||||||
|
@ -977,7 +969,7 @@ class TestClientDB( unittest.TestCase ):
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
result = self._read( 'service_info', HC.LOCAL_FILE_SERVICE_IDENTIFIER )
|
result = self._read( 'service_info', HC.LOCAL_FILE_SERVICE_IDENTIFIER.GetServiceKey() )
|
||||||
|
|
||||||
self.assertEqual( type( result ), dict )
|
self.assertEqual( type( result ), dict )
|
||||||
|
|
||||||
|
@ -1055,18 +1047,7 @@ class TestClientDB( unittest.TestCase ):
|
||||||
|
|
||||||
self._write( 'update_services', edit_log )
|
self._write( 'update_services', edit_log )
|
||||||
|
|
||||||
with self.assertRaises( HydrusExceptions.DBException ):
|
# update this ~sometime~ to test the new services manager object, which should update with these changes!
|
||||||
|
|
||||||
self._read( 'service', new_local_like )
|
|
||||||
|
|
||||||
|
|
||||||
result = self._read( 'service', other_new_tag_repo )
|
|
||||||
|
|
||||||
host = other_new_tag_repo_info_updated[ 'host' ]
|
|
||||||
port = other_new_tag_repo_info_updated[ 'port' ]
|
|
||||||
access_key = other_new_tag_repo_info_updated[ 'access_key' ]
|
|
||||||
|
|
||||||
self.assertEqual( result.GetCredentials(), CC.Credentials( host, port, access_key ) )
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
|
@ -1076,10 +1057,7 @@ class TestClientDB( unittest.TestCase ):
|
||||||
|
|
||||||
self._write( 'update_services', edit_log )
|
self._write( 'update_services', edit_log )
|
||||||
|
|
||||||
with self.assertRaises( HydrusExceptions.DBException ):
|
# update this ~sometime~ to test the new services manager object, which should update with these changes!
|
||||||
|
|
||||||
self._read( 'service', other_new_tag_repo )
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
|
@ -58,8 +58,8 @@ class TestHydrusDownloadingFunctions( unittest.TestCase ):
|
||||||
|
|
||||||
advanced_tag_options = {}
|
advanced_tag_options = {}
|
||||||
|
|
||||||
advanced_tag_options[ local ] = [ '', 'character' ]
|
advanced_tag_options[ local.GetServiceKey() ] = [ '', 'character' ]
|
||||||
advanced_tag_options[ remote ] = [ '', 'character' ]
|
advanced_tag_options[ remote.GetServiceKey() ] = [ '', 'character' ]
|
||||||
|
|
||||||
tags = [ 'a', 'character:b', 'series:c' ]
|
tags = [ 'a', 'character:b', 'series:c' ]
|
||||||
|
|
||||||
|
|
7
test.py
|
@ -52,6 +52,11 @@ class App( wx.App ):
|
||||||
self._reads[ 'messaging_sessions' ] = []
|
self._reads[ 'messaging_sessions' ] = []
|
||||||
self._reads[ 'tag_censorship' ] = []
|
self._reads[ 'tag_censorship' ] = []
|
||||||
self._reads[ 'options' ] = CC.CLIENT_DEFAULT_OPTIONS
|
self._reads[ 'options' ] = CC.CLIENT_DEFAULT_OPTIONS
|
||||||
|
|
||||||
|
services = []
|
||||||
|
services.append( CC.Service( HC.LOCAL_BOORU_SERVICE_KEY, HC.LOCAL_BOORU, 'local booru', {} ) )
|
||||||
|
self._reads[ 'services' ] = services
|
||||||
|
|
||||||
self._reads[ 'sessions' ] = []
|
self._reads[ 'sessions' ] = []
|
||||||
self._reads[ 'tag_parents' ] = {}
|
self._reads[ 'tag_parents' ] = {}
|
||||||
self._reads[ 'tag_service_precedence' ] = []
|
self._reads[ 'tag_service_precedence' ] = []
|
||||||
|
@ -65,6 +70,8 @@ class App( wx.App ):
|
||||||
|
|
||||||
self._managers = {}
|
self._managers = {}
|
||||||
|
|
||||||
|
self._managers[ 'services' ] = CC.ServiceManager()
|
||||||
|
|
||||||
self._managers[ 'hydrus_sessions' ] = HydrusSessions.HydrusSessionManagerClient()
|
self._managers[ 'hydrus_sessions' ] = HydrusSessions.HydrusSessionManagerClient()
|
||||||
self._managers[ 'tag_censorship' ] = HydrusTags.TagCensorshipManager()
|
self._managers[ 'tag_censorship' ] = HydrusTags.TagCensorshipManager()
|
||||||
self._managers[ 'tag_siblings' ] = HydrusTags.TagSiblingsManager()
|
self._managers[ 'tag_siblings' ] = HydrusTags.TagSiblingsManager()
|
||||||
|
|