2015-03-25 22:04:19 +00:00
import ClientCaches
2015-04-01 20:44:54 +00:00
import ClientData
2015-05-20 21:31:40 +00:00
import ClientDaemons
2013-11-06 18:22:07 +00:00
import hashlib
2013-09-25 20:20:10 +00:00
import httplib
2015-04-01 20:44:54 +00:00
import HydrusConstants as HC
import HydrusController
import HydrusData
2013-07-24 20:26:00 +00:00
import HydrusExceptions
2015-04-01 20:44:54 +00:00
import HydrusGlobals
2014-01-29 21:59:42 +00:00
import HydrusNetworking
2013-03-15 02:38:12 +00:00
import HydrusSessions
2013-09-25 20:20:10 +00:00
import HydrusServer
2013-07-17 20:56:13 +00:00
import HydrusTags
2014-05-21 21:37:35 +00:00
import HydrusThreading
2013-02-19 00:11:43 +00:00
import ClientConstants as CC
import ClientDB
import ClientGUI
2013-05-29 20:19:54 +00:00
import ClientGUIDialogs
2013-02-19 00:11:43 +00:00
import os
2013-08-28 21:31:52 +00:00
import random
2015-04-08 18:10:50 +00:00
import sqlite3
2014-01-08 18:40:02 +00:00
import subprocess
2013-07-24 20:26:00 +00:00
import sys
2015-04-08 18:10:50 +00:00
import threading
2013-02-19 00:11:43 +00:00
import time
import traceback
import wx
import wx . richtext
2013-10-02 22:06:06 +00:00
from twisted . internet import reactor
2013-10-23 21:36:47 +00:00
from twisted . internet import defer
2013-02-19 00:11:43 +00:00
ID_ANIMATED_EVENT_TIMER = wx . NewId ( )
ID_MAINTENANCE_EVENT_TIMER = wx . NewId ( )
2014-08-13 22:18:12 +00:00
MAINTENANCE_PERIOD = 5 * 60
2014-08-06 20:29:17 +00:00
2015-04-01 20:44:54 +00:00
class Controller ( HydrusController . HydrusController ) :
2014-12-03 22:56:40 +00:00
2015-04-01 20:44:54 +00:00
db_class = ClientDB . DB
2013-05-08 20:31:00 +00:00
2014-01-08 18:40:02 +00:00
def BackupDatabase ( self ) :
with wx . DirDialog ( self . _gui , ' Select backup location. ' ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
path = dlg . GetPath ( )
2014-12-10 22:02:39 +00:00
text = ' Are you sure " ' + path + ' " is the correct directory? '
text + = os . linesep * 2
text + = ' Everything already in that directory will be deleted before the backup starts. '
text + = os . linesep * 2
text + = ' The database will be locked while the backup occurs, which may lock up your gui as well. '
2014-01-08 18:40:02 +00:00
2014-12-10 22:02:39 +00:00
with ClientGUIDialogs . DialogYesNo ( self . _gui , text ) as dlg_yn :
2014-01-08 18:40:02 +00:00
if dlg_yn . ShowModal ( ) == wx . ID_YES :
self . Write ( ' backup ' , path )
2014-09-03 20:26:49 +00:00
def Clipboard ( self , data_type , data ) :
2013-02-19 00:11:43 +00:00
# need this cause can't do it in a non-gui thread
2014-09-03 20:26:49 +00:00
if data_type == ' paths ' :
2013-02-19 00:11:43 +00:00
paths = data
if wx . TheClipboard . Open ( ) :
2013-03-15 02:38:12 +00:00
data = wx . DataObjectComposite ( )
2013-02-19 00:11:43 +00:00
2013-03-15 02:38:12 +00:00
file_data = wx . FileDataObject ( )
for path in paths : file_data . AddFile ( path )
text_data = wx . TextDataObject ( os . linesep . join ( paths ) )
data . Add ( file_data , True )
data . Add ( text_data , False )
2013-02-19 00:11:43 +00:00
wx . TheClipboard . SetData ( data )
wx . TheClipboard . Close ( )
2013-03-15 02:38:12 +00:00
else : wx . MessageBox ( ' Could not get permission to access the clipboard! ' )
2013-02-19 00:11:43 +00:00
2014-09-03 20:26:49 +00:00
elif data_type == ' text ' :
2013-03-23 17:57:29 +00:00
text = data
if wx . TheClipboard . Open ( ) :
data = wx . TextDataObject ( text )
wx . TheClipboard . SetData ( data )
wx . TheClipboard . Close ( )
else : wx . MessageBox ( ' I could not get permission to access the clipboard. ' )
2014-11-20 01:48:04 +00:00
elif data_type == ' bmp ' :
media = data
2015-04-01 20:44:54 +00:00
image_container = wx . GetApp ( ) . Cache ( ' fullscreen ' ) . GetImage ( media )
2014-11-20 01:48:04 +00:00
def THREADWait ( ) :
# have to do this in thread, because the image rendered needs the wx event queue to render
start_time = time . time ( )
while not image_container . IsRendered ( ) :
if time . time ( ) - start_time > 15 : raise Exception ( ' The image did not render in fifteen seconds, so the attempt to copy it to the clipboard was abandoned. ' )
time . sleep ( 0.1 )
wx . CallAfter ( CopyToClipboard )
def CopyToClipboard ( ) :
if wx . TheClipboard . Open ( ) :
hydrus_bmp = image_container . GetHydrusBitmap ( )
wx_bmp = hydrus_bmp . GetWxBitmap ( )
data = wx . BitmapDataObject ( wx_bmp )
wx . TheClipboard . SetData ( data )
wx . TheClipboard . Close ( )
else : wx . MessageBox ( ' I could not get permission to access the clipboard. ' )
HydrusThreading . CallToThread ( THREADWait )
2013-02-19 00:11:43 +00:00
2014-12-03 22:56:40 +00:00
def CurrentlyIdle ( self ) :
2015-05-13 20:22:39 +00:00
if self . _options [ ' idle_period ' ] == 0 : return False
2014-12-03 22:56:40 +00:00
2015-05-13 20:22:39 +00:00
return HydrusData . GetNow ( ) - self . _timestamps [ ' last_user_action ' ] > self . _options [ ' idle_period ' ]
2014-12-03 22:56:40 +00:00
2014-02-19 22:37:23 +00:00
2015-04-01 20:44:54 +00:00
def DoHTTP ( self , * args , * * kwargs ) : return self . _http . Request ( * args , * * kwargs )
2013-02-19 00:11:43 +00:00
2015-06-03 21:05:13 +00:00
def ForceIdle ( self ) :
self . _timestamps [ ' last_user_action ' ] = 0
HydrusGlobals . pubsub . pub ( ' refresh_status ' )
2013-02-19 00:11:43 +00:00
def GetGUI ( self ) : return self . _gui
2014-09-03 20:26:49 +00:00
def GetManager ( self , manager_type ) : return self . _managers [ manager_type ]
2013-10-09 18:13:42 +00:00
2015-05-13 20:22:39 +00:00
def GetOptions ( self ) :
return self . _options
2014-08-06 20:29:17 +00:00
def InitCheckPassword ( self ) :
while True :
with wx . PasswordEntryDialog ( None , ' Enter your password ' , ' Enter password ' ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
2015-05-13 20:22:39 +00:00
if hashlib . sha256 ( dlg . GetValue ( ) ) . digest ( ) == self . _options [ ' password ' ] : break
2014-08-06 20:29:17 +00:00
else : raise HydrusExceptions . PermissionException ( )
def InitDB ( self ) :
db_initialised = False
while not db_initialised :
try :
2015-04-01 20:44:54 +00:00
HydrusController . HydrusController . InitDB ( self )
2014-08-06 20:29:17 +00:00
db_initialised = True
except HydrusExceptions . DBAccessException as e :
2015-03-25 22:04:19 +00:00
try : print ( HydrusData . ToString ( e ) )
except : print ( repr ( HydrusData . ToString ( e ) ) )
2014-08-06 20:29:17 +00:00
2015-04-08 18:10:50 +00:00
def wx_code ( ) :
message = ' This instance of the client had a problem connecting to the database, which probably means an old instance is still closing. '
message + = os . linesep * 2
message + = ' If the old instance does not close for a _very_ long time, you can usually safely force-close it from task manager. '
2014-08-06 20:29:17 +00:00
2015-04-08 18:10:50 +00:00
with ClientGUIDialogs . DialogYesNo ( None , message , ' There was a problem connecting to the database. ' , yes_label = ' wait a bit, then try again ' , no_label = ' forget it ' ) as dlg :
if dlg . ShowModal ( ) == wx . ID_YES : time . sleep ( 3 )
else : raise HydrusExceptions . PermissionException ( )
2014-08-06 20:29:17 +00:00
2015-04-08 18:10:50 +00:00
HydrusThreading . CallBlockingToWx ( wx_code )
2014-08-06 20:29:17 +00:00
def InitGUI ( self ) :
self . _managers = { }
2015-03-18 21:46:29 +00:00
self . _managers [ ' services ' ] = ClientData . ServicesManager ( )
2014-08-13 22:18:12 +00:00
2014-08-06 20:29:17 +00:00
self . _managers [ ' hydrus_sessions ' ] = HydrusSessions . HydrusSessionManagerClient ( )
2015-03-18 21:46:29 +00:00
self . _managers [ ' local_booru ' ] = ClientCaches . LocalBooruCache ( )
2014-08-06 20:29:17 +00:00
self . _managers [ ' tag_censorship ' ] = HydrusTags . TagCensorshipManager ( )
self . _managers [ ' tag_siblings ' ] = HydrusTags . TagSiblingsManager ( )
self . _managers [ ' tag_parents ' ] = HydrusTags . TagParentsManager ( )
2015-03-18 21:46:29 +00:00
self . _managers [ ' undo ' ] = ClientData . UndoManager ( )
2014-08-06 20:29:17 +00:00
self . _managers [ ' web_sessions ' ] = HydrusSessions . WebSessionManagerClient ( )
2015-04-01 20:44:54 +00:00
self . _caches [ ' fullscreen ' ] = ClientCaches . RenderedImageCache ( ' fullscreen ' )
self . _caches [ ' preview ' ] = ClientCaches . RenderedImageCache ( ' preview ' )
self . _caches [ ' thumbnail ' ] = ClientCaches . ThumbnailCache ( )
2014-08-06 20:29:17 +00:00
2015-06-10 19:40:25 +00:00
if HC . options [ ' proxy ' ] is not None :
( proxytype , host , port , username , password ) = HC . options [ ' proxy ' ]
HydrusNetworking . SetProxy ( proxytype , host , port , username , password )
2014-08-06 20:29:17 +00:00
CC . GlobalBMPs . STATICInitialise ( )
self . _gui = ClientGUI . FrameGUI ( )
2015-03-25 22:04:19 +00:00
HydrusGlobals . pubsub . sub ( self , ' Clipboard ' , ' clipboard ' )
HydrusGlobals . pubsub . sub ( self , ' RestartServer ' , ' restart_server ' )
HydrusGlobals . pubsub . sub ( self , ' RestartBooru ' , ' restart_booru ' )
2014-08-06 20:29:17 +00:00
# this is because of some bug in wx C++ that doesn't add these by default
wx . richtext . RichTextBuffer . AddHandler ( wx . richtext . RichTextHTMLHandler ( ) )
wx . richtext . RichTextBuffer . AddHandler ( wx . richtext . RichTextXMLHandler ( ) )
2015-03-25 22:04:19 +00:00
if HydrusGlobals . is_first_start : wx . CallAfter ( self . _gui . DoFirstStart )
if HydrusGlobals . is_db_updated : wx . CallLater ( 1 , HydrusData . ShowText , ' The client has updated to version ' + HydrusData . ToString ( HC . SOFTWARE_VERSION ) + ' ! ' )
2014-08-06 20:29:17 +00:00
self . RestartServer ( )
self . RestartBooru ( )
2015-05-20 21:31:40 +00:00
self . StartDaemons ( )
2014-08-06 20:29:17 +00:00
2015-06-03 21:05:13 +00:00
self . ResetIdleTimer ( )
2014-08-06 20:29:17 +00:00
2013-02-19 00:11:43 +00:00
def MaintainDB ( self ) :
2015-03-25 22:04:19 +00:00
now = HydrusData . GetNow ( )
2013-02-19 00:11:43 +00:00
shutdown_timestamps = self . Read ( ' shutdown_timestamps ' )
2015-05-13 20:22:39 +00:00
if self . _options [ ' maintenance_vacuum_period ' ] != 0 :
2014-12-03 22:56:40 +00:00
2015-05-13 20:22:39 +00:00
if now - shutdown_timestamps [ CC . SHUTDOWN_TIMESTAMP_VACUUM ] > self . _options [ ' maintenance_vacuum_period ' ] : self . Write ( ' vacuum ' )
2014-12-03 22:56:40 +00:00
2015-05-13 20:22:39 +00:00
if self . _options [ ' maintenance_delete_orphans_period ' ] != 0 :
2014-12-03 22:56:40 +00:00
2015-05-13 20:22:39 +00:00
if now - shutdown_timestamps [ CC . SHUTDOWN_TIMESTAMP_DELETE_ORPHANS ] > self . _options [ ' maintenance_delete_orphans_period ' ] : self . Write ( ' delete_orphans ' )
2014-12-03 22:56:40 +00:00
2013-02-19 00:11:43 +00:00
2015-04-08 18:10:50 +00:00
if self . _timestamps [ ' last_service_info_cache_fatten ' ] != 0 and now - self . _timestamps [ ' last_service_info_cache_fatten ' ] > 60 * 20 :
2014-08-06 20:29:17 +00:00
2015-04-08 18:10:50 +00:00
HydrusGlobals . pubsub . pub ( ' splash_set_text ' , ' fattening service info ' )
2014-04-23 20:56:12 +00:00
2014-08-13 22:18:12 +00:00
services = self . GetManager ( ' services ' ) . GetServices ( )
2014-04-23 20:56:12 +00:00
2014-12-17 22:35:12 +00:00
for service in services :
try : self . Read ( ' service_info ' , service . GetServiceKey ( ) )
except : pass # sometimes this breaks when a service has just been removed and the client is closing, so ignore the error
2014-04-23 20:56:12 +00:00
2015-03-25 22:04:19 +00:00
self . _timestamps [ ' last_service_info_cache_fatten ' ] = HydrusData . GetNow ( )
2014-08-06 20:29:17 +00:00
2015-03-25 22:04:19 +00:00
HydrusGlobals . pubsub . pub ( ' clear_closed_pages ' )
2014-04-23 20:56:12 +00:00
2013-02-19 00:11:43 +00:00
def OnInit ( self ) :
2014-10-29 21:39:01 +00:00
2015-04-01 20:44:54 +00:00
HydrusController . HydrusController . OnInit ( self )
2014-10-29 21:39:01 +00:00
2013-09-25 20:20:10 +00:00
self . _local_service = None
2014-07-09 22:15:14 +00:00
self . _booru_service = None
2013-09-25 20:20:10 +00:00
2015-04-01 20:44:54 +00:00
self . _http = HydrusNetworking . HTTPConnectionManager ( )
2013-11-06 18:22:07 +00:00
2013-02-19 00:11:43 +00:00
try :
2015-04-08 18:10:50 +00:00
splash = ClientGUI . FrameSplash ( )
2013-02-19 00:11:43 +00:00
except :
2014-08-06 20:29:17 +00:00
print ( ' There was an error trying to start the splash screen! ' )
2013-02-19 00:11:43 +00:00
2014-08-06 20:29:17 +00:00
print ( traceback . format_exc ( ) )
2013-02-19 00:11:43 +00:00
2014-08-06 20:29:17 +00:00
try : wx . CallAfter ( splash . Destroy )
2014-01-22 21:11:22 +00:00
except : pass
2014-08-06 20:29:17 +00:00
return False
2013-02-19 00:11:43 +00:00
2015-04-08 18:10:50 +00:00
boot_thread = threading . Thread ( target = self . THREADBootEverything , name = ' Application Boot Thread ' )
wx . CallAfter ( boot_thread . start )
return True
2013-02-19 00:11:43 +00:00
def PrepStringForDisplay ( self , text ) :
2015-05-13 20:22:39 +00:00
if self . _options [ ' gui_capitalisation ' ] : return text
2013-02-19 00:11:43 +00:00
else : return text . lower ( )
2015-03-25 22:04:19 +00:00
def ResetIdleTimer ( self ) : self . _timestamps [ ' last_user_action ' ] = HydrusData . GetNow ( )
2014-08-13 22:18:12 +00:00
2014-07-09 22:15:14 +00:00
def RestartBooru ( self ) :
2015-03-25 22:04:19 +00:00
service = self . GetManager ( ' services ' ) . GetService ( CC . LOCAL_BOORU_SERVICE_KEY )
2014-07-09 22:15:14 +00:00
info = service . GetInfo ( )
port = info [ ' port ' ]
def TWISTEDRestartServer ( ) :
def StartServer ( * args , * * kwargs ) :
try :
try :
2015-06-10 19:40:25 +00:00
connection = HydrusNetworking . GetLocalConnection ( port )
2014-07-09 22:15:14 +00:00
connection . close ( )
2015-03-25 22:04:19 +00:00
text = ' The client \' s booru server could not start because something was already bound to port ' + HydrusData . ToString ( port ) + ' . '
2014-07-09 22:15:14 +00:00
text + = os . linesep * 2
text + = ' This usually means another hydrus client is already running and occupying that port. It could be a previous instantiation of this client that has yet to shut itself down. '
text + = os . linesep * 2
text + = ' You can change the port this client tries to host its local server on in services->manage services. '
2015-03-25 22:04:19 +00:00
wx . CallLater ( 1 , HydrusData . ShowText , text )
2014-07-09 22:15:14 +00:00
except :
2015-03-25 22:04:19 +00:00
self . _booru_service = reactor . listenTCP ( port , HydrusServer . HydrusServiceBooru ( CC . LOCAL_BOORU_SERVICE_KEY , HC . LOCAL_BOORU , ' This is the local booru. ' ) )
2014-07-09 22:15:14 +00:00
try :
2015-06-10 19:40:25 +00:00
connection = HydrusNetworking . GetLocalConnection ( port )
2014-07-09 22:15:14 +00:00
connection . close ( )
2015-06-10 19:40:25 +00:00
except Exception as e :
2014-07-09 22:15:14 +00:00
2015-06-10 19:40:25 +00:00
text = ' Tried to bind port ' + HydrusData . ToString ( port ) + ' for the local booru, but it failed: '
text + = os . linesep * 2
text + = HydrusData . ToString ( e )
2014-07-09 22:15:14 +00:00
2015-03-25 22:04:19 +00:00
wx . CallLater ( 1 , HydrusData . ShowText , text )
2014-07-09 22:15:14 +00:00
2015-06-03 21:05:13 +00:00
except Exception as e :
wx . CallAfter ( HydrusData . ShowException , e )
2014-07-09 22:15:14 +00:00
if self . _booru_service is None : StartServer ( )
else :
deferred = defer . maybeDeferred ( self . _booru_service . stopListening )
deferred . addCallback ( StartServer )
reactor . callFromThread ( TWISTEDRestartServer )
2013-09-25 20:20:10 +00:00
def RestartServer ( self ) :
2015-05-13 20:22:39 +00:00
port = self . _options [ ' local_port ' ]
2013-09-25 20:20:10 +00:00
def TWISTEDRestartServer ( ) :
2013-10-23 21:36:47 +00:00
def StartServer ( * args , * * kwargs ) :
2013-09-25 20:20:10 +00:00
try :
2013-10-02 22:06:06 +00:00
try :
2015-06-10 19:40:25 +00:00
connection = HydrusNetworking . GetLocalConnection ( port )
2013-10-02 22:06:06 +00:00
connection . close ( )
2015-03-25 22:04:19 +00:00
text = ' The client \' s local server could not start because something was already bound to port ' + HydrusData . ToString ( port ) + ' . '
2014-05-28 21:03:24 +00:00
text + = os . linesep * 2
text + = ' This usually means another hydrus client is already running and occupying that port. It could be a previous instantiation of this client that has yet to shut itself down. '
text + = os . linesep * 2
text + = ' You can change the port this client tries to host its local server on in file->options. '
2013-10-02 22:06:06 +00:00
2015-03-25 22:04:19 +00:00
wx . CallLater ( 1 , HydrusData . ShowText , text )
2013-10-02 22:06:06 +00:00
except :
2015-03-25 22:04:19 +00:00
self . _local_service = reactor . listenTCP ( port , HydrusServer . HydrusServiceLocal ( CC . LOCAL_FILE_SERVICE_KEY , HC . LOCAL_FILE , ' This is the local file service. ' ) )
2013-10-02 22:06:06 +00:00
try :
2015-06-10 19:40:25 +00:00
connection = HydrusNetworking . GetLocalConnection ( port )
2013-10-02 22:06:06 +00:00
connection . close ( )
2015-06-10 19:40:25 +00:00
except Exception as e :
2013-10-02 22:06:06 +00:00
2015-06-10 19:40:25 +00:00
text = ' Tried to bind port ' + HydrusData . ToString ( port ) + ' for the local server, but it failed: '
text + = os . linesep * 2
text + = HydrusData . ToString ( e )
2013-10-02 22:06:06 +00:00
2015-03-25 22:04:19 +00:00
wx . CallLater ( 1 , HydrusData . ShowText , text )
2013-10-02 22:06:06 +00:00
2015-06-03 21:05:13 +00:00
except Exception as e :
wx . CallAfter ( HydrusData . ShowException , e )
2013-09-25 20:20:10 +00:00
if self . _local_service is None : StartServer ( )
else :
2013-10-23 21:36:47 +00:00
deferred = defer . maybeDeferred ( self . _local_service . stopListening )
2013-09-25 20:20:10 +00:00
2013-10-23 21:36:47 +00:00
deferred . addCallback ( StartServer )
2013-09-25 20:20:10 +00:00
2013-10-02 22:06:06 +00:00
reactor . callFromThread ( TWISTEDRestartServer )
2013-09-25 20:20:10 +00:00
2014-01-08 18:40:02 +00:00
def RestoreDatabase ( self ) :
with wx . DirDialog ( self . _gui , ' Select backup location. ' ) as dlg :
if dlg . ShowModal ( ) == wx . ID_OK :
path = dlg . GetPath ( )
2014-12-10 22:02:39 +00:00
text = ' Are you sure you want to restore a backup from " ' + path + ' " ? '
text + = os . linesep * 2
text + = ' Everything in your current database will be deleted! '
text + = os . linesep * 2
text + = ' The gui will shut down, and then it will take a while to complete the restore. Once it is done, the client will restart. '
2014-01-08 18:40:02 +00:00
2014-12-10 22:02:39 +00:00
with ClientGUIDialogs . DialogYesNo ( self . _gui , text ) as dlg_yn :
2014-01-08 18:40:02 +00:00
if dlg_yn . ShowModal ( ) == wx . ID_YES :
2015-06-17 20:01:41 +00:00
def THREADRestart ( ) :
wx . CallAfter ( self . _gui . Exit )
while not self . _db . LoopIsFinished ( ) : time . sleep ( 0.1 )
self . _db . RestoreBackup ( path )
cmd = [ sys . executable ]
cmd . extend ( sys . argv )
subprocess . Popen ( cmd )
2014-01-08 18:40:02 +00:00
2015-06-17 20:01:41 +00:00
restart_thread = threading . Thread ( target = THREADRestart , name = ' Application Restart Thread ' )
2014-01-08 18:40:02 +00:00
2015-06-17 20:01:41 +00:00
wx . CallAfter ( restart_thread . start )
2014-01-08 18:40:02 +00:00
2014-05-21 21:37:35 +00:00
def StartFileQuery ( self , query_key , search_context ) : HydrusThreading . CallToThread ( self . THREADDoFileQuery , query_key , search_context )
2013-08-28 21:31:52 +00:00
2015-05-20 21:31:40 +00:00
def StartDaemons ( self ) :
HydrusThreading . DAEMONWorker ( ' CheckImportFolders ' , ClientDaemons . DAEMONCheckImportFolders , ( ' notify_restart_import_folders_daemon ' , ' notify_new_import_folders ' ) , period = 180 )
HydrusThreading . DAEMONWorker ( ' CheckExportFolders ' , ClientDaemons . DAEMONCheckExportFolders , ( ' notify_restart_export_folders_daemon ' , ' notify_new_export_folders ' ) , period = 180 )
HydrusThreading . DAEMONWorker ( ' DownloadFiles ' , ClientDaemons . DAEMONDownloadFiles , ( ' notify_new_downloads ' , ' notify_new_permissions ' ) )
HydrusThreading . DAEMONWorker ( ' ResizeThumbnails ' , ClientDaemons . DAEMONResizeThumbnails , period = 3600 * 24 , init_wait = 600 )
HydrusThreading . DAEMONWorker ( ' SynchroniseAccounts ' , ClientDaemons . DAEMONSynchroniseAccounts , ( ' permissions_are_stale ' , ) )
HydrusThreading . DAEMONWorker ( ' SynchroniseRepositories ' , ClientDaemons . DAEMONSynchroniseRepositories , ( ' notify_restart_repo_sync_daemon ' , ' notify_new_permissions ' ) )
HydrusThreading . DAEMONWorker ( ' SynchroniseSubscriptions ' , ClientDaemons . DAEMONSynchroniseSubscriptions , ( ' notify_restart_subs_sync_daemon ' , ' notify_new_subscriptions ' ) , period = 360 , init_wait = 120 )
2015-06-17 20:01:41 +00:00
HydrusThreading . DAEMONWorker ( ' UPnP ' , ClientDaemons . DAEMONUPnP , ( ' notify_new_upnp_mappings ' , ) , init_wait = 120 , pre_callable_wait = 6 )
2015-05-20 21:31:40 +00:00
HydrusThreading . DAEMONQueue ( ' FlushRepositoryUpdates ' , ClientDaemons . DAEMONFlushServiceUpdates , ' service_updates_delayed ' , period = 5 )
2013-08-28 21:31:52 +00:00
def THREADDoFileQuery ( self , query_key , search_context ) :
2015-03-04 22:44:32 +00:00
query_hash_ids = self . Read ( ' file_query_ids ' , search_context )
query_hash_ids = list ( query_hash_ids )
random . shuffle ( query_hash_ids )
limit = search_context . GetSystemPredicates ( ) . GetLimit ( )
if limit is not None : query_hash_ids = query_hash_ids [ : limit ]
service_key = search_context . GetFileServiceKey ( )
media_results = [ ]
2015-04-22 22:57:25 +00:00
for sub_query_hash_ids in HydrusData . SplitListIntoChunks ( query_hash_ids , 256 ) :
2013-08-28 21:31:52 +00:00
2015-03-04 22:44:32 +00:00
if query_key . IsCancelled ( ) : return
2013-08-28 21:31:52 +00:00
2015-03-04 22:44:32 +00:00
more_media_results = self . Read ( ' media_results_from_ids ' , service_key , sub_query_hash_ids )
2013-08-28 21:31:52 +00:00
2015-03-04 22:44:32 +00:00
media_results . extend ( more_media_results )
2013-08-28 21:31:52 +00:00
2015-03-25 22:04:19 +00:00
HydrusGlobals . pubsub . pub ( ' set_num_query_results ' , len ( media_results ) , len ( query_hash_ids ) )
2013-08-28 21:31:52 +00:00
2015-04-01 20:44:54 +00:00
self . WaitUntilWXThreadIdle ( )
2013-08-28 21:31:52 +00:00
2015-03-04 22:44:32 +00:00
2015-03-25 22:04:19 +00:00
HydrusGlobals . pubsub . pub ( ' file_query_done ' , query_key , media_results )
2013-08-28 21:31:52 +00:00
2015-04-08 18:10:50 +00:00
def THREADBootEverything ( self ) :
try :
HydrusGlobals . pubsub . pub ( ' splash_set_text ' , ' booting db ' )
self . InitDB ( ) # can't run on wx thread because we need event queue free to update splash text
2015-05-13 20:22:39 +00:00
self . _options = wx . GetApp ( ) . Read ( ' options ' )
HC . options = self . _options
2015-04-29 19:20:35 +00:00
2015-05-13 20:22:39 +00:00
if self . _options [ ' password ' ] is not None :
2015-04-08 18:10:50 +00:00
HydrusGlobals . pubsub . pub ( ' splash_set_text ' , ' waiting for password ' )
HydrusThreading . CallBlockingToWx ( self . InitCheckPassword )
HydrusGlobals . pubsub . pub ( ' splash_set_text ' , ' booting gui ' )
HydrusThreading . CallBlockingToWx ( self . InitGUI )
except HydrusExceptions . PermissionException as e : pass
except :
2015-04-22 22:57:25 +00:00
traceback . print_exc ( )
2015-04-08 18:10:50 +00:00
text = ' A serious error occured while trying to start the program. Its traceback has been written to client.log. '
print ( text )
wx . CallAfter ( wx . MessageBox , text )
finally :
HydrusGlobals . pubsub . pub ( ' splash_destroy ' )
def THREADExitEverything ( self ) :
2015-06-03 21:05:13 +00:00
2015-04-08 18:10:50 +00:00
HydrusGlobals . pubsub . pub ( ' splash_set_text ' , ' exiting gui ' )
gui = self . GetGUI ( )
try : HydrusThreading . CallBlockingToWx ( gui . TestAbleToClose )
except : return
try :
HydrusThreading . CallBlockingToWx ( gui . Shutdown )
HydrusGlobals . pubsub . pub ( ' splash_set_text ' , ' exiting db ' )
HydrusThreading . CallBlockingToWx ( self . MaintainDB )
self . ShutdownDB ( ) # can't run on wx thread because we need event queue free to update splash text
except HydrusExceptions . PermissionException as e : pass
except :
2015-04-22 22:57:25 +00:00
traceback . print_exc ( )
2015-04-08 18:10:50 +00:00
text = ' A serious error occured while trying to exit the program. Its traceback has been written to client.log. You may need to quit the program from task manager. '
print ( text )
wx . CallAfter ( wx . MessageBox , text )
finally :
HydrusGlobals . pubsub . pub ( ' splash_destroy ' )
2013-02-19 00:11:43 +00:00
def Write ( self , action , * args , * * kwargs ) :
2013-12-04 22:44:16 +00:00
if action == ' content_updates ' : self . _managers [ ' undo ' ] . AddCommand ( ' content_updates ' , * args , * * kwargs )
2013-07-10 20:25:57 +00:00
2015-04-01 20:44:54 +00:00
return HydrusController . HydrusController . Write ( self , action , * args , * * kwargs )
2013-07-31 21:26:38 +00:00
2013-02-19 00:11:43 +00:00