2018-05-02 20:45:20 +00:00
import collections
2013-02-19 00:11:43 +00:00
import os
2020-04-22 21:00:35 +00:00
2019-11-14 03:56:30 +00:00
from qtpy import QtCore as QC
from qtpy import QtWidgets as QW
from qtpy import QtGui as QG
2020-04-22 21:00:35 +00:00
from hydrus . core import HydrusConstants as HC
from hydrus . core import HydrusData
from hydrus . core import HydrusExceptions
from hydrus . core import HydrusGlobals as HG
from hydrus . core import HydrusSerialisable
from hydrus . core import HydrusText
from hydrus . client import ClientConstants as CC
from hydrus . client import ClientSearch
from hydrus . client import ClientThreading
from hydrus . client . gui import ClientGUICanvas
from hydrus . client . gui import ClientGUICore as CGC
from hydrus . client . gui import ClientGUIDialogs
from hydrus . client . gui import ClientGUIDialogsQuick
from hydrus . client . gui import ClientGUIFunctions
from hydrus . client . gui import ClientGUIManagement
from hydrus . client . gui import ClientGUIMenus
from hydrus . client . gui import ClientGUIResults
from hydrus . client . gui import ClientGUIShortcuts
from hydrus . client . gui import QtPorting as QP
2013-02-19 00:11:43 +00:00
2018-11-28 22:31:04 +00:00
RESERVED_SESSION_NAMES = { ' ' , ' just a blank page ' , ' last session ' , ' exit session ' }
2017-10-25 21:45:15 +00:00
2017-08-16 21:58:06 +00:00
class DialogPageChooser ( ClientGUIDialogs . Dialog ) :
def __init__ ( self , parent , controller ) :
ClientGUIDialogs . Dialog . __init__ ( self , parent , ' new page ' , position = ' center ' )
self . _controller = controller
2020-01-16 02:08:23 +00:00
self . _action_picked = False
2017-08-16 21:58:06 +00:00
self . _result = None
2019-11-14 03:56:30 +00:00
# spawn and add to layout in this order, so focus precipitates from the graphical top
self . _button_7 = QW . QPushButton ( ' ' , self )
self . _button_8 = QW . QPushButton ( ' ' , self )
self . _button_9 = QW . QPushButton ( ' ' , self )
self . _button_4 = QW . QPushButton ( ' ' , self )
self . _button_5 = QW . QPushButton ( ' ' , self )
self . _button_6 = QW . QPushButton ( ' ' , self )
self . _button_1 = QW . QPushButton ( ' ' , self )
self . _button_2 = QW . QPushButton ( ' ' , self )
self . _button_3 = QW . QPushButton ( ' ' , self )
size_policy = self . _button_1 . sizePolicy ( )
size_policy . setVerticalPolicy ( QW . QSizePolicy . Expanding )
size_policy . setRetainSizeWhenHidden ( True )
self . _button_7 . setSizePolicy ( size_policy )
self . _button_8 . setSizePolicy ( size_policy )
self . _button_9 . setSizePolicy ( size_policy )
self . _button_4 . setSizePolicy ( size_policy )
self . _button_5 . setSizePolicy ( size_policy )
self . _button_6 . setSizePolicy ( size_policy )
self . _button_1 . setSizePolicy ( size_policy )
self . _button_2 . setSizePolicy ( size_policy )
self . _button_3 . setSizePolicy ( size_policy )
self . _button_7 . setObjectName ( ' 7 ' )
self . _button_8 . setObjectName ( ' 8 ' )
self . _button_9 . setObjectName ( ' 9 ' )
self . _button_4 . setObjectName ( ' 4 ' )
self . _button_5 . setObjectName ( ' 5 ' )
self . _button_6 . setObjectName ( ' 6 ' )
self . _button_1 . setObjectName ( ' 1 ' )
self . _button_2 . setObjectName ( ' 2 ' )
self . _button_3 . setObjectName ( ' 3 ' )
# this ensures these buttons won't get focus and receive key events, letting dialog handle arrow/number shortcuts
self . _button_7 . setFocusPolicy ( QC . Qt . NoFocus )
self . _button_8 . setFocusPolicy ( QC . Qt . NoFocus )
self . _button_9 . setFocusPolicy ( QC . Qt . NoFocus )
self . _button_4 . setFocusPolicy ( QC . Qt . NoFocus )
self . _button_5 . setFocusPolicy ( QC . Qt . NoFocus )
self . _button_6 . setFocusPolicy ( QC . Qt . NoFocus )
self . _button_1 . setFocusPolicy ( QC . Qt . NoFocus )
self . _button_2 . setFocusPolicy ( QC . Qt . NoFocus )
self . _button_3 . setFocusPolicy ( QC . Qt . NoFocus )
gridbox = QP . GridLayout ( cols = 3 )
QP . AddToLayout ( gridbox , self . _button_7 )
QP . AddToLayout ( gridbox , self . _button_8 )
QP . AddToLayout ( gridbox , self . _button_9 )
QP . AddToLayout ( gridbox , self . _button_4 )
QP . AddToLayout ( gridbox , self . _button_5 )
QP . AddToLayout ( gridbox , self . _button_6 )
QP . AddToLayout ( gridbox , self . _button_1 )
QP . AddToLayout ( gridbox , self . _button_2 )
QP . AddToLayout ( gridbox , self . _button_3 )
self . setLayout ( gridbox )
( width , height ) = ClientGUIFunctions . ConvertTextToPixels ( self , ( 64 , 14 ) )
self . setMinimumWidth ( width )
self . setMinimumHeight ( height )
2017-08-16 21:58:06 +00:00
self . _services = HG . client_controller . services_manager . GetServices ( )
repository_petition_permissions = [ ( content_type , HC . PERMISSION_ACTION_OVERRULE ) for content_type in HC . REPOSITORY_CONTENT_TYPES ]
self . _petition_service_keys = [ service . GetServiceKey ( ) for service in self . _services if service . GetServiceType ( ) in HC . REPOSITORIES and True in ( service . HasPermission ( content_type , action ) for ( content_type , action ) in repository_petition_permissions ) ]
self . _InitButtons ( ' home ' )
2019-11-14 03:56:30 +00:00
self . _button_7 . clicked . connect ( lambda : self . _HitButton ( 7 ) )
self . _button_8 . clicked . connect ( lambda : self . _HitButton ( 8 ) )
self . _button_9 . clicked . connect ( lambda : self . _HitButton ( 9 ) )
self . _button_4 . clicked . connect ( lambda : self . _HitButton ( 4 ) )
self . _button_5 . clicked . connect ( lambda : self . _HitButton ( 5 ) )
self . _button_6 . clicked . connect ( lambda : self . _HitButton ( 6 ) )
self . _button_1 . clicked . connect ( lambda : self . _HitButton ( 1 ) )
self . _button_2 . clicked . connect ( lambda : self . _HitButton ( 2 ) )
self . _button_3 . clicked . connect ( lambda : self . _HitButton ( 3 ) )
2017-08-16 21:58:06 +00:00
def _AddEntry ( self , button , entry ) :
2019-11-14 03:56:30 +00:00
id = int ( button . objectName ( ) )
2017-08-16 21:58:06 +00:00
self . _command_dict [ id ] = entry
( entry_type , obj ) = entry
if entry_type == ' menu ' :
2019-11-14 03:56:30 +00:00
button . setText ( obj )
2017-08-16 21:58:06 +00:00
elif entry_type == ' page_duplicate_filter ' :
2019-11-14 03:56:30 +00:00
button . setText ( ' duplicates processing ' )
2017-08-16 21:58:06 +00:00
elif entry_type == ' pages_notebook ' :
2019-11-14 03:56:30 +00:00
button . setText ( ' page of pages ' )
2017-08-16 21:58:06 +00:00
elif entry_type in ( ' page_query ' , ' page_petitions ' ) :
name = HG . client_controller . services_manager . GetService ( obj ) . GetName ( )
2019-11-14 03:56:30 +00:00
button . setText ( name )
2017-08-16 21:58:06 +00:00
elif entry_type == ' page_import_gallery ' :
2019-11-14 03:56:30 +00:00
button . setText ( ' gallery ' )
2017-08-16 21:58:06 +00:00
2018-04-05 01:22:26 +00:00
elif entry_type == ' page_import_simple_downloader ' :
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
button . setText ( ' simple downloader ' )
2017-08-16 21:58:06 +00:00
2018-05-23 21:05:06 +00:00
elif entry_type == ' page_import_watcher ' :
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
button . setText ( ' watcher ' )
2017-08-16 21:58:06 +00:00
elif entry_type == ' page_import_urls ' :
2019-11-14 03:56:30 +00:00
button . setText ( ' urls ' )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
button . show ( )
2017-08-16 21:58:06 +00:00
def _HitButton ( self , id ) :
if id in self . _command_dict :
( entry_type , obj ) = self . _command_dict [ id ]
if entry_type == ' menu ' :
self . _InitButtons ( obj )
else :
if entry_type == ' page_query ' :
file_service_key = obj
page_name = ' files '
search_enabled = True
2017-12-06 22:06:56 +00:00
new_options = self . _controller . new_options
2017-08-16 21:58:06 +00:00
tag_service_key = new_options . GetKey ( ' default_tag_service_search_page ' )
if not self . _controller . services_manager . ServiceExists ( tag_service_key ) :
tag_service_key = CC . COMBINED_TAG_SERVICE_KEY
2020-03-11 21:52:11 +00:00
tag_search_context = ClientSearch . TagSearchContext ( service_key = tag_service_key )
file_search_context = ClientSearch . FileSearchContext ( file_service_key = file_service_key , tag_search_context = tag_search_context )
2017-08-16 21:58:06 +00:00
2020-04-01 21:51:42 +00:00
self . _result = ( ' page ' , ClientGUIManagement . CreateManagementControllerQuery ( page_name , file_search_context , search_enabled ) )
2017-08-16 21:58:06 +00:00
elif entry_type == ' page_duplicate_filter ' :
self . _result = ( ' page ' , ClientGUIManagement . CreateManagementControllerDuplicateFilter ( ) )
elif entry_type == ' pages_notebook ' :
self . _result = ( ' pages ' , None )
elif entry_type == ' page_import_gallery ' :
2018-08-01 20:44:57 +00:00
self . _result = ( ' page ' , ClientGUIManagement . CreateManagementControllerImportGallery ( ) )
2017-08-16 21:58:06 +00:00
2018-04-05 01:22:26 +00:00
elif entry_type == ' page_import_simple_downloader ' :
2017-08-16 21:58:06 +00:00
2018-04-05 01:22:26 +00:00
self . _result = ( ' page ' , ClientGUIManagement . CreateManagementControllerImportSimpleDownloader ( ) )
2017-08-16 21:58:06 +00:00
2018-05-23 21:05:06 +00:00
elif entry_type == ' page_import_watcher ' :
2017-08-16 21:58:06 +00:00
2018-08-01 20:44:57 +00:00
self . _result = ( ' page ' , ClientGUIManagement . CreateManagementControllerImportMultipleWatcher ( ) )
2017-08-16 21:58:06 +00:00
elif entry_type == ' page_import_urls ' :
self . _result = ( ' page ' , ClientGUIManagement . CreateManagementControllerImportURLs ( ) )
elif entry_type == ' page_petitions ' :
petition_service_key = obj
self . _result = ( ' page ' , ClientGUIManagement . CreateManagementControllerPetitions ( petition_service_key ) )
2020-01-16 02:08:23 +00:00
self . _action_picked = True
2019-11-14 03:56:30 +00:00
self . done ( QW . QDialog . Accepted )
2017-08-16 21:58:06 +00:00
def _InitButtons ( self , menu_keyword ) :
self . _command_dict = { }
entries = [ ]
if menu_keyword == ' home ' :
entries . append ( ( ' menu ' , ' files ' ) )
entries . append ( ( ' menu ' , ' download ' ) )
if len ( self . _petition_service_keys ) > 0 :
entries . append ( ( ' menu ' , ' petitions ' ) )
entries . append ( ( ' menu ' , ' special ' ) )
elif menu_keyword == ' files ' :
entries . append ( ( ' page_query ' , CC . LOCAL_FILE_SERVICE_KEY ) )
entries . append ( ( ' page_query ' , CC . TRASH_SERVICE_KEY ) )
2019-05-22 22:35:06 +00:00
if HG . client_controller . new_options . GetBoolean ( ' advanced_mode ' ) :
entries . append ( ( ' page_query ' , CC . COMBINED_LOCAL_FILE_SERVICE_KEY ) )
2017-08-16 21:58:06 +00:00
for service in self . _services :
if service . GetServiceType ( ) == HC . FILE_REPOSITORY :
entries . append ( ( ' page_query ' , service . GetServiceKey ( ) ) )
elif menu_keyword == ' download ' :
entries . append ( ( ' page_import_urls ' , None ) )
2018-05-23 21:05:06 +00:00
entries . append ( ( ' page_import_watcher ' , None ) )
2018-08-01 20:44:57 +00:00
entries . append ( ( ' page_import_gallery ' , None ) )
2018-04-05 01:22:26 +00:00
entries . append ( ( ' page_import_simple_downloader ' , None ) )
2017-08-16 21:58:06 +00:00
elif menu_keyword == ' petitions ' :
entries = [ ( ' page_petitions ' , service_key ) for service_key in self . _petition_service_keys ]
elif menu_keyword == ' special ' :
entries . append ( ( ' pages_notebook ' , None ) )
entries . append ( ( ' page_duplicate_filter ' , None ) )
if len ( entries ) < = 4 :
2019-11-14 03:56:30 +00:00
self . _button_1 . setVisible ( False )
self . _button_3 . setVisible ( False )
self . _button_5 . setVisible ( False )
self . _button_7 . setVisible ( False )
self . _button_9 . setVisible ( False )
2017-08-16 21:58:06 +00:00
potential_buttons = [ self . _button_8 , self . _button_4 , self . _button_6 , self . _button_2 ]
elif len ( entries ) < = 9 :
potential_buttons = [ self . _button_7 , self . _button_8 , self . _button_9 , self . _button_4 , self . _button_5 , self . _button_6 , self . _button_1 , self . _button_2 , self . _button_3 ]
else :
# sort out a multi-page solution? maybe only if this becomes a big thing; the person can always select from the menus, yeah?
potential_buttons = [ self . _button_7 , self . _button_8 , self . _button_9 , self . _button_4 , self . _button_5 , self . _button_6 , self . _button_1 , self . _button_2 , self . _button_3 ]
entries = entries [ : 9 ]
2018-04-18 22:10:15 +00:00
for entry in entries :
self . _AddEntry ( potential_buttons . pop ( 0 ) , entry )
2017-08-16 21:58:06 +00:00
unused_buttons = potential_buttons
2018-08-01 20:44:57 +00:00
for button in unused_buttons :
2019-11-14 03:56:30 +00:00
button . setVisible ( False )
2018-08-01 20:44:57 +00:00
2017-08-16 21:58:06 +00:00
2020-01-16 02:08:23 +00:00
def event ( self , event ) :
if event . type ( ) == QC . QEvent . WindowDeactivate and not self . _action_picked :
self . done ( QW . QDialog . Rejected )
return True
else :
return ClientGUIDialogs . Dialog . event ( self , event )
2019-11-14 03:56:30 +00:00
def keyPressEvent ( self , event ) :
2017-08-16 21:58:06 +00:00
id = None
2018-05-16 20:09:50 +00:00
( modifier , key ) = ClientGUIShortcuts . ConvertKeyEventToSimpleTuple ( event )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
if key == QC . Qt . Key_Up : id = 8
elif key == QC . Qt . Key_Left : id = 4
elif key == QC . Qt . Key_Right : id = 6
elif key == QC . Qt . Key_Down : id = 2
elif key == QC . Qt . Key_1 and modifier == QC . Qt . KeypadModifier : id = 1
elif key == QC . Qt . Key_2 and modifier == QC . Qt . KeypadModifier : id = 2
elif key == QC . Qt . Key_3 and modifier == QC . Qt . KeypadModifier : id = 3
elif key == QC . Qt . Key_4 and modifier == QC . Qt . KeypadModifier : id = 4
elif key == QC . Qt . Key_5 and modifier == QC . Qt . KeypadModifier : id = 5
elif key == QC . Qt . Key_6 and modifier == QC . Qt . KeypadModifier : id = 6
elif key == QC . Qt . Key_7 and modifier == QC . Qt . KeypadModifier : id = 7
elif key == QC . Qt . Key_8 and modifier == QC . Qt . KeypadModifier : id = 8
elif key == QC . Qt . Key_9 and modifier == QC . Qt . KeypadModifier : id = 9
2020-01-16 02:08:23 +00:00
elif key in ( QC . Qt . Key_Enter , QC . Qt . Key_Return ) :
# get the 'first', scanning from top-left
for possible_id in ( 7 , 8 , 9 , 4 , 5 , 6 , 1 , 2 , 3 ) :
if possible_id in self . _command_dict :
id = possible_id
break
2019-11-14 03:56:30 +00:00
elif key == QC . Qt . Key_Escape :
self . done ( QW . QDialog . Rejected )
2017-08-16 21:58:06 +00:00
return
else :
2019-11-14 03:56:30 +00:00
event . ignore ( )
2017-08-16 21:58:06 +00:00
if id is not None :
self . _HitButton ( id )
def GetValue ( self ) :
return self . _result
2019-11-14 03:56:30 +00:00
class Page ( QW . QSplitter ) :
2013-02-19 00:11:43 +00:00
2017-07-05 21:09:28 +00:00
def __init__ ( self , parent , controller , management_controller , initial_hashes ) :
2015-06-24 22:10:14 +00:00
2019-11-14 03:56:30 +00:00
QW . QSplitter . __init__ ( self , parent )
2013-02-19 00:11:43 +00:00
2020-04-08 21:10:11 +00:00
self . _parent_notebook = parent
2015-11-25 22:00:57 +00:00
self . _controller = controller
2018-05-23 21:05:06 +00:00
self . _page_key = self . _controller . AcquirePageKey ( )
2015-06-24 22:10:14 +00:00
self . _management_controller = management_controller
2017-07-05 21:09:28 +00:00
self . _initial_hashes = initial_hashes
2015-06-24 22:10:14 +00:00
self . _management_controller . SetKey ( ' page ' , self . _page_key )
2015-03-04 22:44:32 +00:00
2017-08-16 21:58:06 +00:00
self . _initialised = False
2013-02-19 00:11:43 +00:00
self . _pretty_status = ' '
2019-11-14 03:56:30 +00:00
self . _search_preview_split = QW . QSplitter ( self )
2013-02-19 00:11:43 +00:00
2020-05-13 19:03:16 +00:00
self . _done_split_setups = False
2019-11-14 03:56:30 +00:00
self . _management_panel = ClientGUIManagement . CreateManagementPanel ( self . _search_preview_split , self , self . _controller , self . _management_controller )
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
file_service_key = self . _management_controller . GetKey ( ' file_service ' )
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
self . _preview_panel = QW . QFrame ( self . _search_preview_split )
2019-11-20 23:10:46 +00:00
self . _preview_panel . setFrameStyle ( QW . QFrame . Panel | QW . QFrame . Sunken )
self . _preview_panel . setLineWidth ( 2 )
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
self . _preview_canvas = ClientGUICanvas . CanvasPanel ( self . _preview_panel , self . _page_key )
2013-02-19 00:11:43 +00:00
2020-02-12 22:50:37 +00:00
self . _media_panel = ClientGUIResults . MediaPanelThumbnails ( self , self . _page_key , file_service_key , [ ] )
2013-09-11 21:28:19 +00:00
2019-11-14 03:56:30 +00:00
vbox = QP . VBoxLayout ( margin = 0 )
2013-09-11 21:28:19 +00:00
2019-11-14 03:56:30 +00:00
QP . AddToLayout ( vbox , self . _preview_canvas , CC . FLAGS_EXPAND_SIZER_BOTH_WAYS )
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
self . _preview_panel . setLayout ( vbox )
2015-06-24 22:10:14 +00:00
2019-11-14 03:56:30 +00:00
self . widget ( 0 ) . setMinimumWidth ( 120 )
self . widget ( 1 ) . setMinimumWidth ( 120 )
self . setStretchFactor ( 0 , 0 )
self . setStretchFactor ( 1 , 1 )
self . _handle_event_filter = QP . WidgetEventFilter ( self . handle ( 1 ) )
self . _handle_event_filter . EVT_LEFT_DCLICK ( self . EventUnsplit )
self . _search_preview_split . widget ( 0 ) . setMinimumHeight ( 180 )
self . _search_preview_split . widget ( 1 ) . setMinimumHeight ( 180 )
self . _search_preview_split . setStretchFactor ( 0 , 1 )
self . _search_preview_split . setStretchFactor ( 1 , 0 )
2019-11-20 23:10:46 +00:00
2019-11-14 03:56:30 +00:00
self . _search_preview_split . _handle_event_filter = QP . WidgetEventFilter ( self . _search_preview_split . handle ( 1 ) )
self . _search_preview_split . _handle_event_filter . EVT_LEFT_DCLICK ( self . EventPreviewUnsplit )
2015-06-24 22:10:14 +00:00
2015-11-25 22:00:57 +00:00
self . _controller . sub ( self , ' SetPrettyStatus ' , ' new_page_status ' )
2018-03-07 22:48:29 +00:00
self . _controller . sub ( self , ' SetSplitterPositions ' , ' set_splitter_positions ' )
2013-02-19 00:11:43 +00:00
2020-03-25 21:15:57 +00:00
self . _ConnectMediaPanelSignals ( )
def _ConnectMediaPanelSignals ( self ) :
self . _media_panel . refreshQuery . connect ( self . RefreshQuery )
self . _media_panel . focusMediaChanged . connect ( self . _preview_canvas . SetMedia )
2020-04-01 21:51:42 +00:00
self . _media_panel . focusMediaCleared . connect ( self . _preview_canvas . ClearMedia )
2020-03-25 21:15:57 +00:00
self . _management_panel . ConnectMediaPanelSignals ( self . _media_panel )
2017-07-05 21:09:28 +00:00
def _SetPrettyStatus ( self , status ) :
self . _pretty_status = status
2018-01-03 22:37:30 +00:00
self . _controller . gui . SetStatusBarDirty ( )
2017-07-05 21:09:28 +00:00
def _SwapMediaPanel ( self , new_panel ) :
2018-02-21 21:59:37 +00:00
# if a new media page comes in while its menu is open, we can enter program instability.
# so let's just put it off.
2019-11-14 03:56:30 +00:00
previous_sizes = self . sizes ( )
2020-03-25 21:15:57 +00:00
self . _preview_canvas . ClearMedia ( )
2017-07-05 21:09:28 +00:00
self . _media_panel . ClearPageKey ( )
2019-08-21 21:34:01 +00:00
media_collect = self . _management_panel . GetMediaCollect ( )
2019-05-15 20:35:00 +00:00
2019-08-21 21:34:01 +00:00
if media_collect . DoesACollect ( ) :
2019-05-15 20:35:00 +00:00
2019-08-21 21:34:01 +00:00
new_panel . Collect ( self . _page_key , media_collect )
2019-05-15 20:35:00 +00:00
2020-04-01 21:51:42 +00:00
media_sort = self . _management_panel . GetMediaSort ( )
2019-05-22 22:35:06 +00:00
2020-04-01 21:51:42 +00:00
new_panel . Sort ( media_sort )
2019-05-22 22:35:06 +00:00
2019-05-15 20:35:00 +00:00
2019-11-14 03:56:30 +00:00
self . _media_panel . setParent ( None )
2019-11-20 23:10:46 +00:00
old_panel = self . _media_panel
2019-11-14 03:56:30 +00:00
self . addWidget ( new_panel )
self . setSizes ( previous_sizes )
2017-07-05 21:09:28 +00:00
2019-11-20 23:10:46 +00:00
self . setStretchFactor ( 1 , 1 )
2018-05-16 20:09:50 +00:00
2017-07-05 21:09:28 +00:00
self . _media_panel = new_panel
2020-03-25 21:15:57 +00:00
self . _ConnectMediaPanelSignals ( )
2018-02-21 21:59:37 +00:00
self . _controller . pub ( ' refresh_page_name ' , self . _page_key )
2019-11-20 23:10:46 +00:00
def clean_up_old_panel ( ) :
2020-03-04 22:12:53 +00:00
if CGC . core ( ) . MenuIsOpen ( ) :
2019-11-20 23:10:46 +00:00
self . _controller . CallLaterQtSafe ( self , 0.5 , clean_up_old_panel )
return
old_panel . deleteLater ( )
clean_up_old_panel ( )
2013-02-19 00:11:43 +00:00
2018-05-02 20:45:20 +00:00
def CheckAbleToClose ( self ) :
self . _management_panel . CheckAbleToClose ( )
2019-06-19 22:08:48 +00:00
def CleanBeforeClose ( self ) :
self . _management_panel . CleanBeforeClose ( )
2020-03-25 21:15:57 +00:00
self . _media_panel . SetFocusedMedia ( None )
2019-06-19 22:08:48 +00:00
2017-07-05 21:09:28 +00:00
def CleanBeforeDestroy ( self ) :
self . _management_panel . CleanBeforeDestroy ( )
2019-11-14 03:56:30 +00:00
self . _preview_canvas . CleanBeforeDestroy ( )
2019-03-06 23:06:22 +00:00
2018-05-23 21:05:06 +00:00
self . _controller . ReleasePageKey ( self . _page_key )
2013-02-19 00:11:43 +00:00
2015-11-04 22:30:28 +00:00
def EventPreviewUnsplit ( self , event ) :
2019-11-14 03:56:30 +00:00
QP . Unsplit ( self . _search_preview_split , self . _preview_panel )
2015-11-04 22:30:28 +00:00
2020-03-25 21:15:57 +00:00
self . _media_panel . SetFocusedMedia ( None )
2015-11-04 22:30:28 +00:00
2013-02-19 00:11:43 +00:00
2015-11-04 22:30:28 +00:00
def EventUnsplit ( self , event ) :
2019-11-14 03:56:30 +00:00
QP . Unsplit ( self , self . _search_preview_split )
2015-11-04 22:30:28 +00:00
2020-03-25 21:15:57 +00:00
self . _media_panel . SetFocusedMedia ( None )
2015-11-04 22:30:28 +00:00
2013-02-19 00:11:43 +00:00
2019-08-21 21:34:01 +00:00
def GetAPIInfoDict ( self , simple ) :
d = { }
d [ ' name ' ] = self . _management_controller . GetPageName ( )
d [ ' page_key ' ] = self . _page_key . hex ( )
d [ ' page_type ' ] = self . _management_controller . GetType ( )
management_info = self . _management_controller . GetAPIInfoDict ( simple )
d [ ' management ' ] = management_info
media_info = self . _media_panel . GetAPIInfoDict ( simple )
d [ ' media ' ] = media_info
return d
2017-07-05 21:09:28 +00:00
def GetHashes ( self ) :
if self . _initialised :
2018-05-30 20:13:21 +00:00
return self . _media_panel . GetHashes ( ordered = True )
2017-07-05 21:09:28 +00:00
else :
return self . _initial_hashes
2015-06-24 22:10:14 +00:00
def GetManagementController ( self ) :
2014-01-22 21:11:22 +00:00
2015-06-24 22:10:14 +00:00
return self . _management_controller
2014-01-22 21:11:22 +00:00
2013-02-19 00:11:43 +00:00
2019-02-27 23:03:30 +00:00
def GetManagementPanel ( self ) :
return self . _management_panel
2015-06-24 22:10:14 +00:00
# used by autocomplete
def GetMedia ( self ) :
2013-02-19 00:11:43 +00:00
2015-06-24 22:10:14 +00:00
return self . _media_panel . GetSortedMedia ( )
2013-02-19 00:11:43 +00:00
2015-06-24 22:10:14 +00:00
2017-12-20 22:55:48 +00:00
def GetMediaPanel ( self ) :
return self . _media_panel
2017-08-16 21:58:06 +00:00
def GetName ( self ) :
return self . _management_controller . GetPageName ( )
2018-05-02 20:45:20 +00:00
def GetNumFileSummary ( self ) :
2017-08-02 21:32:54 +00:00
if self . _initialised :
2018-05-02 20:45:20 +00:00
num_files = self . _media_panel . GetNumFiles ( )
2017-08-02 21:32:54 +00:00
else :
2018-05-02 20:45:20 +00:00
num_files = len ( self . _initial_hashes )
2017-08-02 21:32:54 +00:00
2018-05-02 20:45:20 +00:00
( num_value , num_range ) = self . _management_controller . GetValueRange ( )
if num_value == num_range :
( num_value , num_range ) = ( 0 , 0 )
return ( num_files , ( num_value , num_range ) )
2017-08-02 21:32:54 +00:00
2015-09-16 18:11:00 +00:00
def GetPageKey ( self ) :
return self . _page_key
2018-05-23 21:05:06 +00:00
def GetPageKeys ( self ) :
return { self . _page_key }
2020-04-08 21:10:11 +00:00
def GetParentNotebook ( self ) :
return self . _parent_notebook
2019-08-21 21:34:01 +00:00
def GetSessionAPIInfoDict ( self , is_selected = False ) :
2019-06-05 19:42:39 +00:00
root = { }
root [ ' name ' ] = self . GetName ( )
2019-06-26 21:27:18 +00:00
root [ ' page_key ' ] = self . _page_key . hex ( )
2019-06-05 19:42:39 +00:00
root [ ' page_type ' ] = self . _management_controller . GetType ( )
root [ ' focused ' ] = is_selected
return root
2015-06-24 22:10:14 +00:00
def GetPrettyStatus ( self ) :
2013-02-19 00:11:43 +00:00
2015-06-24 22:10:14 +00:00
return self . _pretty_status
2013-02-19 00:11:43 +00:00
def GetSashPositions ( self ) :
2020-05-27 21:27:52 +00:00
hpos = HC . options [ ' hpos ' ]
2013-02-19 00:11:43 +00:00
2020-05-27 21:27:52 +00:00
sizes = self . sizes ( )
if len ( sizes ) > 1 :
2015-11-04 22:30:28 +00:00
2020-05-27 21:27:52 +00:00
if sizes [ 0 ] != 0 :
hpos = sizes [ 0 ]
2015-11-04 22:30:28 +00:00
2020-05-27 21:27:52 +00:00
vpos = HC . options [ ' vpos ' ]
sizes = self . _search_preview_split . sizes ( )
if len ( sizes ) > 1 :
2016-05-25 21:54:03 +00:00
2020-05-27 21:27:52 +00:00
if sizes [ 1 ] != 0 :
vpos = - sizes [ 1 ]
2016-05-25 21:54:03 +00:00
2020-05-27 21:27:52 +00:00
return ( hpos , vpos )
2013-02-19 00:11:43 +00:00
2019-10-16 20:47:55 +00:00
def GetTotalWeight ( self ) :
num_hashes = len ( self . GetHashes ( ) )
num_seeds = self . _management_controller . GetNumSeeds ( )
# hashes are smaller, but seeds tend to need more cpu, so we'll just say 1:1 for now
return num_hashes + num_seeds
2018-05-16 20:09:50 +00:00
def IsMultipleWatcherPage ( self ) :
return self . _management_controller . GetType ( ) == ClientGUIManagement . MANAGEMENT_TYPE_IMPORT_MULTIPLE_WATCHER
2017-08-16 21:58:06 +00:00
def IsImporter ( self ) :
return self . _management_controller . IsImporter ( )
2017-05-17 21:53:02 +00:00
def IsURLImportPage ( self ) :
return self . _management_controller . GetType ( ) == ClientGUIManagement . MANAGEMENT_TYPE_IMPORT_URLS
2015-11-25 22:00:57 +00:00
def PageHidden ( self ) :
2017-09-27 21:52:54 +00:00
self . _management_panel . PageHidden ( )
self . _media_panel . PageHidden ( )
2020-03-25 21:15:57 +00:00
self . _preview_canvas . PageHidden ( )
2015-11-25 22:00:57 +00:00
2013-02-19 00:11:43 +00:00
2015-11-25 22:00:57 +00:00
def PageShown ( self ) :
2020-05-13 19:03:16 +00:00
if self . isVisible ( ) and not self . _done_split_setups :
2020-05-27 21:27:52 +00:00
self . SetSplitterPositions ( )
2020-05-20 21:36:02 +00:00
2020-05-13 19:03:16 +00:00
self . _done_split_setups = True
2017-09-27 21:52:54 +00:00
self . _management_panel . PageShown ( )
self . _media_panel . PageShown ( )
2020-03-25 21:15:57 +00:00
self . _preview_canvas . PageShown ( )
2015-11-25 22:00:57 +00:00
2013-02-19 00:11:43 +00:00
2015-11-25 22:00:57 +00:00
def RefreshQuery ( self ) :
2017-07-05 21:09:28 +00:00
if self . _initialised :
2020-03-25 21:15:57 +00:00
self . _management_panel . RefreshQuery ( )
2017-07-05 21:09:28 +00:00
2015-11-25 22:00:57 +00:00
2013-02-19 00:11:43 +00:00
def ShowHideSplit ( self ) :
2019-11-14 03:56:30 +00:00
if QP . SplitterVisibleCount ( self ) > 1 :
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
QP . Unsplit ( self , self . _search_preview_split )
2013-02-19 00:11:43 +00:00
2020-03-25 21:15:57 +00:00
self . _media_panel . SetFocusedMedia ( None )
2015-11-04 22:30:28 +00:00
2013-02-19 00:11:43 +00:00
else :
2020-05-27 21:27:52 +00:00
self . SetSplitterPositions ( )
2013-02-19 00:11:43 +00:00
2017-07-05 21:09:28 +00:00
def SetMediaFocus ( self ) :
2019-11-14 03:56:30 +00:00
self . _media_panel . setFocus ( QC . Qt . OtherFocusReason )
2017-07-05 21:09:28 +00:00
def SetMediaResults ( self , media_results ) :
2019-12-18 22:06:34 +00:00
if self . _management_controller . IsImporter ( ) :
file_service_key = CC . LOCAL_FILE_SERVICE_KEY
else :
file_service_key = self . _management_controller . GetKey ( ' file_service ' )
2017-07-05 21:09:28 +00:00
2020-02-12 22:50:37 +00:00
media_panel = ClientGUIResults . MediaPanelThumbnails ( self , self . _page_key , file_service_key , media_results )
2017-07-05 21:09:28 +00:00
self . _SwapMediaPanel ( media_panel )
self . _initialised = True
self . _initial_hashes = [ ]
2019-11-14 03:56:30 +00:00
QP . CallAfter ( self . _management_panel . Start ) # importand this is callafter, so it happens after a heavy session load is done
2017-07-19 21:21:41 +00:00
2013-02-19 00:11:43 +00:00
2019-04-10 22:50:53 +00:00
def SetName ( self , name ) :
2017-08-16 21:58:06 +00:00
return self . _management_controller . SetPageName ( name )
2015-06-24 22:10:14 +00:00
def SetPrettyStatus ( self , page_key , status ) :
if page_key == self . _page_key :
2017-07-05 21:09:28 +00:00
if self . _initialised :
self . _SetPrettyStatus ( status )
2015-06-24 22:10:14 +00:00
2015-11-25 22:00:57 +00:00
def SetSearchFocus ( self ) :
2018-03-28 21:55:58 +00:00
self . _management_panel . SetSearchFocus ( )
2015-11-25 22:00:57 +00:00
2015-06-24 22:10:14 +00:00
2020-05-27 21:27:52 +00:00
def SetSplitterPositions ( self , hpos = None , vpos = None ) :
if hpos is None :
hpos = HC . options [ ' hpos ' ]
if vpos is None :
vpos = HC . options [ ' vpos ' ]
2018-03-07 22:48:29 +00:00
2019-11-28 01:11:46 +00:00
QP . SplitHorizontally ( self . _search_preview_split , self . _management_panel , self . _preview_panel , vpos )
2018-03-07 22:48:29 +00:00
2019-11-28 01:11:46 +00:00
QP . SplitVertically ( self , self . _search_preview_split , self . _media_panel , hpos )
2018-03-07 22:48:29 +00:00
if HC . options [ ' hide_preview ' ] :
2019-11-14 03:56:30 +00:00
QP . CallAfter ( QP . Unsplit , self . _search_preview_split , self . _preview_panel )
2018-03-07 22:48:29 +00:00
2020-03-25 21:15:57 +00:00
def SynchronisedWaitSwitch ( self ) :
2015-11-25 22:00:57 +00:00
2020-03-25 21:15:57 +00:00
self . _management_panel . SynchronisedWaitSwitch ( )
2015-11-25 22:00:57 +00:00
2015-06-24 22:10:14 +00:00
2017-08-16 21:58:06 +00:00
def Start ( self ) :
if self . _initial_hashes is not None and len ( self . _initial_hashes ) > 0 :
2018-01-24 23:09:42 +00:00
self . _controller . CallToThread ( self . THREADLoadInitialMediaResults , self . _controller , self . _initial_hashes )
2017-08-16 21:58:06 +00:00
else :
self . _initialised = True
2019-11-14 03:56:30 +00:00
QP . CallAfter ( self . _management_panel . Start ) # importand this is callafter, so it happens after a heavy session load is done
2017-08-16 21:58:06 +00:00
2018-02-21 21:59:37 +00:00
def SwapMediaPanel ( self , new_panel ) :
2013-02-19 00:11:43 +00:00
2018-02-21 21:59:37 +00:00
self . _SwapMediaPanel ( new_panel )
2017-07-05 21:09:28 +00:00
def TestAbleToClose ( self ) :
2018-05-02 20:45:20 +00:00
try :
self . _management_panel . CheckAbleToClose ( )
except HydrusExceptions . VetoException as e :
2019-01-09 22:59:03 +00:00
reason = str ( e )
2018-05-02 20:45:20 +00:00
2019-09-05 00:05:32 +00:00
message = ' {} Are you sure you want to close it? ' . format ( str ( e ) )
result = ClientGUIDialogsQuick . GetYesNo ( self , message )
2019-11-14 03:56:30 +00:00
if result == QW . QDialog . Rejected :
2018-05-02 20:45:20 +00:00
2019-09-05 00:05:32 +00:00
raise HydrusExceptions . VetoException ( )
2018-05-02 20:45:20 +00:00
2017-07-05 21:09:28 +00:00
2018-01-24 23:09:42 +00:00
def THREADLoadInitialMediaResults ( self , controller , initial_hashes ) :
2019-11-14 03:56:30 +00:00
def qt_code_status ( status ) :
2018-01-24 23:09:42 +00:00
2019-11-14 03:56:30 +00:00
if not self or not QP . isValid ( self ) :
2018-01-24 23:09:42 +00:00
return
self . _SetPrettyStatus ( status )
2019-11-14 03:56:30 +00:00
def qt_code_publish ( media_results ) :
2018-01-24 23:09:42 +00:00
2019-11-14 03:56:30 +00:00
if not self or not QP . isValid ( self ) :
2018-01-24 23:09:42 +00:00
return
self . SetMediaResults ( media_results )
2017-07-05 21:09:28 +00:00
initial_media_results = [ ]
2018-01-24 23:09:42 +00:00
for group_of_initial_hashes in HydrusData . SplitListIntoChunks ( initial_hashes , 256 ) :
2013-02-19 00:11:43 +00:00
2018-01-24 23:09:42 +00:00
more_media_results = controller . Read ( ' media_results ' , group_of_initial_hashes )
2015-05-20 21:31:40 +00:00
2017-07-05 21:09:28 +00:00
initial_media_results . extend ( more_media_results )
2013-02-19 00:11:43 +00:00
2019-01-09 22:59:03 +00:00
status = ' Loading initial files \u2026 ' + HydrusData . ConvertValueRangeToPrettyString ( len ( initial_media_results ) , len ( initial_hashes ) )
2017-07-05 21:09:28 +00:00
2019-11-14 03:56:30 +00:00
QP . CallAfter ( qt_code_status , status )
2013-02-19 00:11:43 +00:00
2017-07-05 21:09:28 +00:00
hashes_to_media_results = { media_result . GetHash ( ) : media_result for media_result in initial_media_results }
2015-09-02 23:16:09 +00:00
2019-06-26 21:27:18 +00:00
sorted_initial_media_results = [ hashes_to_media_results [ hash ] for hash in initial_hashes if hash in hashes_to_media_results ]
2017-07-05 21:09:28 +00:00
2019-11-14 03:56:30 +00:00
QP . CallAfter ( qt_code_publish , sorted_initial_media_results )
2015-09-02 23:16:09 +00:00
2013-02-19 00:11:43 +00:00
2018-05-30 20:13:21 +00:00
def REPEATINGPageUpdate ( self ) :
2017-12-13 22:33:07 +00:00
2018-05-30 20:13:21 +00:00
self . _management_panel . REPEATINGPageUpdate ( )
2017-12-13 22:33:07 +00:00
2019-11-14 03:56:30 +00:00
class PagesNotebook ( QP . TabWidgetWithDnD ) :
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
def __init__ ( self , parent , controller , name ) :
2017-08-09 21:33:51 +00:00
2019-11-14 03:56:30 +00:00
QP . TabWidgetWithDnD . __init__ ( self , parent )
2020-04-08 21:10:11 +00:00
self . _parent_notebook = parent
2020-01-16 02:08:23 +00:00
# this is disabled for now because it seems borked in Qt
2018-06-06 21:27:02 +00:00
if controller . new_options . GetBoolean ( ' notebook_tabs_on_left ' ) :
2019-11-14 03:56:30 +00:00
self . setTabPosition ( QW . QTabWidget . West )
2018-06-06 21:27:02 +00:00
else :
2019-11-14 03:56:30 +00:00
self . setTabPosition ( QW . QTabWidget . North )
2017-08-09 21:33:51 +00:00
self . _controller = controller
2018-05-23 21:05:06 +00:00
self . _page_key = self . _controller . AcquirePageKey ( )
2017-08-16 21:58:06 +00:00
self . _name = name
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
self . _next_new_page_index = None
2017-08-09 21:33:51 +00:00
2017-08-23 21:34:25 +00:00
self . _potential_drag_page = None
2017-08-16 21:58:06 +00:00
self . _closed_pages = [ ]
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
self . _controller . sub ( self , ' RefreshPageName ' , ' refresh_page_name ' )
self . _controller . sub ( self , ' NotifyPageUnclosed ' , ' notify_page_unclosed ' )
2020-06-11 12:01:08 +00:00
self . _controller . sub ( self , ' _UpdatePageTabEliding ' , ' notify_new_options ' )
2017-08-09 21:33:51 +00:00
2019-11-14 03:56:30 +00:00
self . _widget_event_filter = QP . WidgetEventFilter ( self )
self . _widget_event_filter . EVT_LEFT_DCLICK ( self . EventLeftDoubleClick )
self . _widget_event_filter . EVT_MIDDLE_DOWN ( self . EventMiddleClick )
self . _widget_event_filter . EVT_LEFT_DOWN ( lambda ev : ev . accept ( ) )
self . _widget_event_filter . EVT_LEFT_DOWN ( lambda ev : ev . accept ( ) )
2020-05-13 19:03:16 +00:00
self . currentChanged . connect ( self . pageJustChanged )
2019-11-14 03:56:30 +00:00
self . pageDragAndDropped . connect ( self . _RefreshPageNamesAfterDnD )
2020-05-20 21:36:02 +00:00
self . tabBarDoubleClicked . connect ( self . _RenamePage )
2019-11-14 03:56:30 +00:00
self . _previous_page_index = - 1
2017-08-09 21:33:51 +00:00
2020-06-11 12:01:08 +00:00
self . _UpdatePageTabEliding ( )
2017-08-09 21:33:51 +00:00
2019-11-14 03:56:30 +00:00
def _RefreshPageNamesAfterDnD ( self , page_widget , source_widget ) :
if hasattr ( page_widget , ' GetPageKey ' ) :
self . _controller . pub ( ' refresh_page_name ' , page_widget . GetPageKey ( ) )
2020-04-08 21:10:11 +00:00
source_notebook = source_widget . parentWidget ( )
if hasattr ( source_notebook , ' GetPageKey ' ) :
2019-11-14 03:56:30 +00:00
2020-04-08 21:10:11 +00:00
self . _controller . pub ( ' refresh_page_name ' , source_notebook . GetPageKey ( ) )
2019-11-14 03:56:30 +00:00
2020-04-08 21:10:11 +00:00
2020-06-11 12:01:08 +00:00
def _UpdatePageTabEliding ( self ) :
if HG . client_controller . new_options . GetBoolean ( ' elide_page_tab_names ' ) :
self . tabBar ( ) . setElideMode ( QC . Qt . ElideMiddle )
else :
self . tabBar ( ) . setElideMode ( QC . Qt . ElideNone )
2019-11-14 03:56:30 +00:00
def _UpdatePreviousPageIndex ( self ) :
self . _previous_page_index = self . currentIndex ( )
2017-08-16 21:58:06 +00:00
def _ChooseNewPage ( self , insertion_index = None ) :
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
self . _next_new_page_index = insertion_index
with DialogPageChooser ( self , self . _controller ) as dlg :
2017-08-09 21:33:51 +00:00
2019-11-14 03:56:30 +00:00
if dlg . exec ( ) == QW . QDialog . Accepted :
2017-08-16 21:58:06 +00:00
( page_type , page_data ) = dlg . GetValue ( )
if page_type == ' pages ' :
self . NewPagesNotebook ( )
elif page_type == ' page ' :
management_controller = page_data
self . NewPage ( management_controller )
2017-08-09 21:33:51 +00:00
2018-05-16 20:09:50 +00:00
def _CloseAllPages ( self , polite = True , delete_pages = False ) :
2017-08-09 21:33:51 +00:00
2019-11-14 03:56:30 +00:00
closees = [ index for index in range ( self . count ( ) ) ]
2017-08-09 21:33:51 +00:00
2018-05-16 20:09:50 +00:00
self . _ClosePages ( closees , polite , delete_pages = delete_pages )
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
def _CloseLeftPages ( self , from_index ) :
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
message = ' Close all pages to the left? '
2019-09-05 00:05:32 +00:00
result = ClientGUIDialogsQuick . GetYesNo ( self , message )
2019-11-14 03:56:30 +00:00
if result == QW . QDialog . Accepted :
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
closees = [ index for index in range ( self . count ( ) ) if index < from_index ]
2019-09-05 00:05:32 +00:00
self . _ClosePages ( closees )
2017-08-16 21:58:06 +00:00
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
def _CloseOtherPages ( self , except_index ) :
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
message = ' Close all other pages? '
2017-08-09 21:33:51 +00:00
2019-09-05 00:05:32 +00:00
result = ClientGUIDialogsQuick . GetYesNo ( self , message )
2019-11-14 03:56:30 +00:00
if result == QW . QDialog . Accepted :
2017-08-09 21:33:51 +00:00
2019-11-14 03:56:30 +00:00
closees = [ index for index in range ( self . count ( ) ) if index != except_index ]
2019-09-05 00:05:32 +00:00
self . _ClosePages ( closees )
2017-08-09 21:33:51 +00:00
2018-05-16 20:09:50 +00:00
def _ClosePage ( self , index , polite = True , delete_page = False ) :
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
self . _controller . ResetIdleTimer ( )
self . _controller . ResetPageChangeTimer ( )
2017-08-09 21:33:51 +00:00
2019-11-14 03:56:30 +00:00
if index == - 1 or index > self . count ( ) - 1 :
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
return False
2017-08-09 21:33:51 +00:00
2019-11-14 03:56:30 +00:00
page = self . widget ( index )
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
if polite :
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
try :
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
page . TestAbleToClose ( )
2017-08-09 21:33:51 +00:00
2018-05-02 20:45:20 +00:00
except HydrusExceptions . VetoException :
2017-08-09 21:33:51 +00:00
2017-08-16 21:58:06 +00:00
return False
2017-08-09 21:33:51 +00:00
2019-06-19 22:08:48 +00:00
page . CleanBeforeClose ( )
2017-08-09 21:33:51 +00:00
2017-08-23 21:34:25 +00:00
page_key = page . GetPageKey ( )
self . _closed_pages . append ( ( index , page_key ) )
2017-08-09 21:33:51 +00:00
2019-11-14 03:56:30 +00:00
self . removeTab ( index )
self . _UpdatePreviousPageIndex ( )
2013-12-11 22:09:25 +00:00
2017-08-23 21:34:25 +00:00
self . _controller . pub ( ' refresh_page_name ' , self . _page_key )
2018-05-16 20:09:50 +00:00
if delete_page :
self . _controller . pub ( ' notify_deleted_page ' , page )
else :
self . _controller . pub ( ' notify_closed_page ' , page )
self . _controller . pub ( ' notify_new_undo ' )
2013-12-11 22:09:25 +00:00
2017-08-16 21:58:06 +00:00
return True
2013-12-11 22:09:25 +00:00
2013-02-19 00:11:43 +00:00
2018-05-16 20:09:50 +00:00
def _ClosePages ( self , indices , polite = True , delete_pages = False ) :
2015-03-25 22:04:19 +00:00
2017-08-16 21:58:06 +00:00
indices = list ( indices )
2013-02-19 00:11:43 +00:00
2017-08-16 21:58:06 +00:00
indices . sort ( reverse = True ) # so we are closing from the end first
for index in indices :
2015-06-24 22:10:14 +00:00
2018-05-16 20:09:50 +00:00
successful = self . _ClosePage ( index , polite , delete_page = delete_pages )
2015-06-24 22:10:14 +00:00
2017-08-16 21:58:06 +00:00
if not successful :
break
2015-06-24 22:10:14 +00:00
2013-09-04 16:48:44 +00:00
2013-02-19 00:11:43 +00:00
2017-08-16 21:58:06 +00:00
def _CloseRightPages ( self , from_index ) :
2013-03-27 20:02:51 +00:00
2017-08-16 21:58:06 +00:00
message = ' Close all pages to the right? '
2019-09-05 00:05:32 +00:00
result = ClientGUIDialogsQuick . GetYesNo ( self , message )
2019-11-14 03:56:30 +00:00
if result == QW . QDialog . Accepted :
2014-01-22 21:11:22 +00:00
2019-11-14 03:56:30 +00:00
closees = [ index for index in range ( self . count ( ) ) if index > from_index ]
2019-09-05 00:05:32 +00:00
self . _ClosePages ( closees )
2017-08-16 21:58:06 +00:00
2020-03-04 22:12:53 +00:00
def _DuplicatePage ( self , index ) :
if index == - 1 or index > self . count ( ) - 1 :
return False
page = self . widget ( index )
session = GUISession ( ' dupe page session ' )
session . AddPageTuple ( page )
2020-03-18 21:35:57 +00:00
session = session . Duplicate ( ) # this ensures we are using fresh new objects
2020-03-04 22:12:53 +00:00
self . InsertSessionPageTuples ( index + 1 , session . GetPageTuples ( ) )
2017-08-16 21:58:06 +00:00
def _GetDefaultPageInsertionIndex ( self ) :
2017-12-06 22:06:56 +00:00
new_options = self . _controller . new_options
2017-08-16 21:58:06 +00:00
new_page_goes = new_options . GetInteger ( ' default_new_page_goes ' )
2019-11-14 03:56:30 +00:00
current_index = self . currentIndex ( )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
if current_index == - 1 :
2017-08-16 21:58:06 +00:00
new_page_goes = CC . NEW_PAGE_GOES_FAR_LEFT
if new_page_goes == CC . NEW_PAGE_GOES_FAR_LEFT :
insertion_index = 0
elif new_page_goes == CC . NEW_PAGE_GOES_LEFT_OF_CURRENT :
insertion_index = current_index
elif new_page_goes == CC . NEW_PAGE_GOES_RIGHT_OF_CURRENT :
insertion_index = current_index + 1
elif new_page_goes == CC . NEW_PAGE_GOES_FAR_RIGHT :
2019-11-14 03:56:30 +00:00
insertion_index = self . count ( )
2017-08-16 21:58:06 +00:00
return insertion_index
def _GetMediaPages ( self , only_my_level ) :
results = [ ]
for page in self . _GetPages ( ) :
if isinstance ( page , PagesNotebook ) :
if not only_my_level :
results . extend ( page . GetMediaPages ( ) )
else :
results . append ( page )
return results
2017-08-23 21:34:25 +00:00
def _GetIndex ( self , page_key ) :
2019-11-14 03:56:30 +00:00
for ( page , index ) in ( ( self . widget ( index ) , index ) for index in range ( self . count ( ) ) ) :
2017-08-23 21:34:25 +00:00
if page . GetPageKey ( ) == page_key :
return index
raise HydrusExceptions . DataMissing ( )
def _GetNotebookFromScreenPosition ( self , screen_position ) :
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
current_page = self . currentWidget ( )
2017-08-16 21:58:06 +00:00
if current_page is None or not isinstance ( current_page , PagesNotebook ) :
2017-08-23 21:34:25 +00:00
return self
2017-08-16 21:58:06 +00:00
else :
2019-11-14 03:56:30 +00:00
tab_index = ClientGUIFunctions . NotebookScreenToHitTest ( self , screen_position )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
if tab_index != - 1 :
2017-08-16 21:58:06 +00:00
2017-08-23 21:34:25 +00:00
return self
2017-08-16 21:58:06 +00:00
2020-02-26 22:28:52 +00:00
on_child_notebook_somewhere = screen_position . y ( ) > current_page . pos ( ) . y ( )
2017-08-30 20:27:47 +00:00
2017-12-20 22:55:48 +00:00
if on_child_notebook_somewhere :
2017-08-16 21:58:06 +00:00
2017-08-23 21:34:25 +00:00
return current_page . _GetNotebookFromScreenPosition ( screen_position )
2017-08-16 21:58:06 +00:00
2017-08-23 21:34:25 +00:00
return self
2017-08-16 21:58:06 +00:00
2017-08-23 21:34:25 +00:00
def _GetPages ( self ) :
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
return [ self . widget ( i ) for i in range ( self . count ( ) ) ]
2017-08-23 21:34:25 +00:00
2018-02-14 21:47:18 +00:00
def _GetPageFromName ( self , page_name ) :
for page in self . _GetPages ( ) :
2019-04-10 22:50:53 +00:00
if page . GetName ( ) == page_name :
2018-02-14 21:47:18 +00:00
return page
if isinstance ( page , PagesNotebook ) :
result = page . _GetPageFromName ( page_name )
if result is not None :
return result
2017-08-23 21:34:25 +00:00
return None
2017-08-16 21:58:06 +00:00
2017-10-04 17:51:58 +00:00
def _MovePage ( self , page , dest_notebook , insertion_tab_index , follow_dropped_page = False ) :
2020-04-08 21:10:11 +00:00
source_notebook = page . GetParentNotebook ( )
2017-10-04 17:51:58 +00:00
for ( index , p ) in enumerate ( source_notebook . _GetPages ( ) ) :
if p == page :
2019-11-14 03:56:30 +00:00
source_notebook . removeTab ( index )
source_notebook . _UpdatePreviousPageIndex ( )
2017-10-04 17:51:58 +00:00
break
if source_notebook != dest_notebook :
2019-11-14 03:56:30 +00:00
page . setParent ( dest_notebook )
2017-10-04 17:51:58 +00:00
self . _controller . pub ( ' refresh_page_name ' , source_notebook . GetPageKey ( ) )
2019-11-14 03:56:30 +00:00
insertion_tab_index = min ( insertion_tab_index , dest_notebook . count ( ) )
2017-10-04 17:51:58 +00:00
2019-11-14 03:56:30 +00:00
dest_notebook . insertTab ( insertion_tab_index , page , page . GetName ( ) )
2020-04-08 21:10:11 +00:00
2019-11-14 03:56:30 +00:00
if follow_dropped_page : dest_notebook . setCurrentIndex ( insertion_tab_index )
2017-10-04 17:51:58 +00:00
if follow_dropped_page :
self . ShowPage ( page )
self . _controller . pub ( ' refresh_page_name ' , page . GetPageKey ( ) )
2018-04-05 01:22:26 +00:00
def _MovePages ( self , pages , dest_notebook ) :
insertion_tab_index = dest_notebook . GetNumPages ( only_my_level = True )
for page in pages :
2020-04-08 21:10:11 +00:00
if page . GetParentNotebook ( ) != dest_notebook :
2018-04-05 01:22:26 +00:00
self . _MovePage ( page , dest_notebook , insertion_tab_index )
insertion_tab_index + = 1
2017-08-16 21:58:06 +00:00
def _RefreshPageName ( self , index ) :
2019-11-14 03:56:30 +00:00
if index == - 1 or index > self . count ( ) - 1 :
2017-08-16 21:58:06 +00:00
return
2017-12-06 22:06:56 +00:00
new_options = self . _controller . new_options
2017-08-16 21:58:06 +00:00
max_page_name_chars = new_options . GetInteger ( ' max_page_name_chars ' )
page_file_count_display = new_options . GetInteger ( ' page_file_count_display ' )
2018-05-16 20:09:50 +00:00
import_page_progress_display = new_options . GetBoolean ( ' import_page_progress_display ' )
2019-11-14 03:56:30 +00:00
page = self . widget ( index )
2017-08-16 21:58:06 +00:00
2019-04-10 22:50:53 +00:00
page_name = page . GetName ( )
2017-10-25 21:45:15 +00:00
2018-02-07 23:40:33 +00:00
page_name = page_name . replace ( os . linesep , ' ' )
2020-01-02 03:05:35 +00:00
page_name = HydrusText . ElideText ( page_name , max_page_name_chars )
2017-08-16 21:58:06 +00:00
2018-05-16 20:09:50 +00:00
num_string = ' '
( num_files , ( num_value , num_range ) ) = page . GetNumFileSummary ( )
2017-08-16 21:58:06 +00:00
if page_file_count_display == CC . PAGE_FILE_COUNT_DISPLAY_ALL or ( page_file_count_display == CC . PAGE_FILE_COUNT_DISPLAY_ONLY_IMPORTERS and page . IsImporter ( ) ) :
2018-07-04 20:48:28 +00:00
num_string + = HydrusData . ToHumanInt ( num_files )
2018-05-02 20:45:20 +00:00
2018-05-16 20:09:50 +00:00
if import_page_progress_display :
2018-05-02 20:45:20 +00:00
if num_range > 0 and num_value != num_range :
2018-05-16 20:09:50 +00:00
if len ( num_string ) > 0 :
num_string + = ' , '
num_string + = HydrusData . ConvertValueRangeToPrettyString ( num_value , num_range )
2018-05-02 20:45:20 +00:00
2017-08-16 21:58:06 +00:00
2018-05-16 20:09:50 +00:00
if len ( num_string ) > 0 :
2018-05-02 20:45:20 +00:00
page_name + = ' ( ' + num_string + ' ) '
2017-08-16 21:58:06 +00:00
2020-04-22 21:00:35 +00:00
safe_page_name = ClientGUIFunctions . EscapeMnemonics ( page_name )
2018-02-07 23:40:33 +00:00
2020-05-13 19:03:16 +00:00
tab_bar = self . tabBar ( )
existing_page_name = tab_bar . tabText ( index )
2018-02-07 23:40:33 +00:00
if existing_page_name not in ( safe_page_name , page_name ) :
2017-08-16 21:58:06 +00:00
2020-05-13 19:03:16 +00:00
tab_bar . setTabText ( index , safe_page_name )
2017-08-16 21:58:06 +00:00
def _RenamePage ( self , index ) :
2019-11-14 03:56:30 +00:00
if index == - 1 or index > self . count ( ) - 1 :
2017-08-16 21:58:06 +00:00
return
2019-11-14 03:56:30 +00:00
page = self . widget ( index )
2017-08-16 21:58:06 +00:00
2019-04-10 22:50:53 +00:00
current_name = page . GetName ( )
2017-10-25 21:45:15 +00:00
2017-08-16 21:58:06 +00:00
with ClientGUIDialogs . DialogTextEntry ( self , ' Enter the new name. ' , default = current_name , allow_blank = False ) as dlg :
2019-11-14 03:56:30 +00:00
if dlg . exec ( ) == QW . QDialog . Accepted :
2017-08-16 21:58:06 +00:00
new_name = dlg . GetValue ( )
2019-04-10 22:50:53 +00:00
page . SetName ( new_name )
2017-08-16 21:58:06 +00:00
self . _controller . pub ( ' refresh_page_name ' , page . GetPageKey ( ) )
2017-10-04 17:51:58 +00:00
def _SendPageToNewNotebook ( self , index ) :
2019-11-14 03:56:30 +00:00
if 0 < = index and index < = self . count ( ) - 1 :
2018-04-25 22:07:52 +00:00
2019-11-14 03:56:30 +00:00
page = self . widget ( index )
2018-04-25 22:07:52 +00:00
dest_notebook = self . NewPagesNotebook ( forced_insertion_index = index , give_it_a_blank_page = False )
self . _MovePage ( page , dest_notebook , 0 )
2017-10-04 17:51:58 +00:00
def _SendRightPagesToNewNotebook ( self , from_index ) :
message = ' Send all pages to the right to a new page of pages? '
2019-09-05 00:05:32 +00:00
result = ClientGUIDialogsQuick . GetYesNo ( self , message )
2019-11-14 03:56:30 +00:00
if result == QW . QDialog . Accepted :
2017-10-04 17:51:58 +00:00
2019-11-14 03:56:30 +00:00
pages_index = self . count ( )
2019-09-05 00:05:32 +00:00
dest_notebook = self . NewPagesNotebook ( forced_insertion_index = pages_index , give_it_a_blank_page = False )
movees = list ( range ( from_index + 1 , pages_index ) )
movees . reverse ( )
for index in movees :
2017-10-04 17:51:58 +00:00
2019-11-14 03:56:30 +00:00
page = self . widget ( index )
2017-10-04 17:51:58 +00:00
2019-09-05 00:05:32 +00:00
self . _MovePage ( page , dest_notebook , 0 )
2017-10-04 17:51:58 +00:00
2019-07-10 22:38:30 +00:00
def _ShiftPage ( self , page_index , delta = None , new_index = None ) :
new_page_index = page_index
if delta is not None :
new_page_index = page_index + delta
if new_index is not None :
new_page_index = new_index
if new_page_index == page_index :
return
2019-11-14 03:56:30 +00:00
if 0 < = new_page_index and new_page_index < = self . count ( ) - 1 :
page_is_selected = self . currentIndex ( ) == page_index
2019-07-10 22:38:30 +00:00
2019-11-14 03:56:30 +00:00
page = self . widget ( page_index )
name = self . tabText ( page_index )
2019-07-10 22:38:30 +00:00
2019-11-14 03:56:30 +00:00
self . removeTab ( page_index )
2019-07-10 22:38:30 +00:00
2019-11-14 03:56:30 +00:00
self . _UpdatePreviousPageIndex ( )
2019-07-10 22:38:30 +00:00
2019-11-14 03:56:30 +00:00
self . insertTab ( new_page_index , page , name )
if page_is_selected : self . setCurrentIndex ( new_page_index )
2019-07-10 22:38:30 +00:00
2017-08-23 21:34:25 +00:00
def _ShowMenu ( self , screen_position ) :
2019-11-14 03:56:30 +00:00
tab_index = ClientGUIFunctions . NotebookScreenToHitTest ( self , screen_position )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
num_pages = self . count ( )
2017-08-16 21:58:06 +00:00
2018-04-05 01:22:26 +00:00
end_index = num_pages - 1
2017-12-13 22:33:07 +00:00
more_than_one_tab = num_pages > 1
2017-08-16 21:58:06 +00:00
click_over_tab = tab_index != - 1
2018-04-05 01:22:26 +00:00
can_go_left = tab_index > 0
can_go_right = tab_index < end_index
2017-12-13 22:33:07 +00:00
2018-04-05 01:22:26 +00:00
click_over_page_of_pages = False
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
menu = QW . QMenu ( )
2017-08-16 21:58:06 +00:00
2017-10-04 17:51:58 +00:00
if click_over_tab :
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
page = self . widget ( tab_index )
2017-12-13 22:33:07 +00:00
click_over_page_of_pages = isinstance ( page , PagesNotebook )
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' close page ' , ' Close this page. ' , self . _ClosePage , tab_index )
2017-08-16 21:58:06 +00:00
if num_pages > 1 :
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' close other pages ' , ' Close all pages but this one. ' , self . _CloseOtherPages , tab_index )
2017-08-16 21:58:06 +00:00
2017-10-04 17:51:58 +00:00
if can_go_left :
2020-03-04 22:12:53 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' close pages to the left ' , ' Close all pages to the left of this one. ' , self . _CloseLeftPages , tab_index )
2017-08-16 21:58:06 +00:00
2017-10-04 17:51:58 +00:00
if can_go_right :
2020-03-04 22:12:53 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' close pages to the right ' , ' Close all pages to the right of this one. ' , self . _CloseRightPages , tab_index )
2017-08-16 21:58:06 +00:00
ClientGUIMenus . AppendSeparator ( menu )
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' rename page ' , ' Rename this page. ' , self . _RenamePage , tab_index )
2017-08-16 21:58:06 +00:00
2019-12-11 23:18:37 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' new page ' , ' Choose a new page. ' , self . _ChooseNewPage )
2017-12-13 22:33:07 +00:00
2017-08-16 21:58:06 +00:00
if click_over_tab :
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' new page here ' , ' Choose a new page. ' , self . _ChooseNewPage , tab_index )
2017-12-13 22:33:07 +00:00
2020-03-04 22:12:53 +00:00
ClientGUIMenus . AppendSeparator ( menu )
ClientGUIMenus . AppendMenuItem ( menu , ' duplicate page ' , ' Duplicate this page. ' , self . _DuplicatePage , tab_index )
2017-08-16 21:58:06 +00:00
if more_than_one_tab :
2017-12-13 22:33:07 +00:00
ClientGUIMenus . AppendSeparator ( menu )
2017-08-16 21:58:06 +00:00
can_home = tab_index > 1
can_move_left = tab_index > 0
can_move_right = tab_index < end_index
can_end = tab_index < end_index - 1
if can_home :
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' move to left end ' , ' Move this page all the way to the left. ' , self . _ShiftPage , tab_index , new_index = 0 )
2017-08-16 21:58:06 +00:00
if can_move_left :
2020-03-04 22:12:53 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' move left ' , ' Move this page one to the left. ' , self . _ShiftPage , tab_index , delta = - 1 )
2017-08-16 21:58:06 +00:00
if can_move_right :
2020-03-04 22:12:53 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' move right ' , ' Move this page one to the right. ' , self . _ShiftPage , tab_index , 1 )
2017-08-16 21:58:06 +00:00
if can_end :
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' move to right end ' , ' Move this page all the way to the right. ' , self . _ShiftPage , tab_index , new_index = end_index )
2017-08-16 21:58:06 +00:00
2019-07-10 22:38:30 +00:00
ClientGUIMenus . AppendSeparator ( menu )
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' sort pages by most files first ' , ' Sort these pages according to how many files they appear to have. ' , self . _SortPagesByFileCount , ' desc ' )
ClientGUIMenus . AppendMenuItem ( menu , ' sort pages by fewest files first ' , ' Sort these pages according to how few files they appear to have. ' , self . _SortPagesByFileCount , ' asc ' )
2019-07-10 22:38:30 +00:00
2017-08-16 21:58:06 +00:00
2018-04-05 01:22:26 +00:00
ClientGUIMenus . AppendSeparator ( menu )
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' send this page down to a new page of pages ' , ' Make a new page of pages and put this page in it. ' , self . _SendPageToNewNotebook , tab_index )
2018-04-05 01:22:26 +00:00
if can_go_right :
2019-12-11 23:18:37 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' send pages to the right to a new page of pages ' , ' Make a new page of pages and put all the pages to the right into it. ' , self . _SendRightPagesToNewNotebook , tab_index )
2018-04-05 01:22:26 +00:00
2020-04-08 21:10:11 +00:00
2019-11-14 03:56:30 +00:00
if click_over_page_of_pages and page . count ( ) > 0 :
2017-10-04 17:51:58 +00:00
ClientGUIMenus . AppendSeparator ( menu )
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( menu , ' refresh all this page \' s pages ' , ' Command every page below this one to refresh. ' , page . RefreshAllPages )
2017-10-04 17:51:58 +00:00
2017-08-16 21:58:06 +00:00
2018-11-28 22:31:04 +00:00
existing_session_names = self . _controller . Read ( ' serialisable_names ' , HydrusSerialisable . SERIALISABLE_TYPE_GUI_SESSION )
2018-04-05 01:22:26 +00:00
if len ( existing_session_names ) > 0 or click_over_page_of_pages :
ClientGUIMenus . AppendSeparator ( menu )
if len ( existing_session_names ) > 0 :
2019-11-14 03:56:30 +00:00
submenu = QW . QMenu ( menu )
2018-04-05 01:22:26 +00:00
for name in existing_session_names :
2019-12-11 23:18:37 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus . AppendMenuItem ( submenu , name , ' Load this session here. ' , self . AppendGUISession , name )
2018-04-05 01:22:26 +00:00
ClientGUIMenus . AppendMenu ( menu , submenu , ' append session ' )
if click_over_page_of_pages :
2019-11-14 03:56:30 +00:00
submenu = QW . QMenu ( menu )
2018-04-05 01:22:26 +00:00
for name in existing_session_names :
2018-11-28 22:31:04 +00:00
if name in RESERVED_SESSION_NAMES :
2018-04-05 01:22:26 +00:00
continue
2019-12-11 23:18:37 +00:00
ClientGUIMenus . AppendMenuItem ( submenu , name , ' Save this page of pages to the session. ' , self . _controller . gui . ProposeSaveGUISession , notebook = page , name = name )
ClientGUIMenus . AppendMenuItem ( submenu , ' create a new session ' , ' Save this page of pages to the session. ' , self . _controller . gui . ProposeSaveGUISession , notebook = page , suggested_name = page . GetName ( ) )
2018-04-05 01:22:26 +00:00
ClientGUIMenus . AppendMenu ( menu , submenu , ' save this page of pages to a session ' )
2020-03-04 22:12:53 +00:00
CGC . core ( ) . PopupMenu ( self , menu )
2017-08-16 21:58:06 +00:00
2019-07-10 22:38:30 +00:00
def _SortPagesByFileCount ( self , order ) :
ordered_pages = list ( self . GetPages ( ) )
def key ( page ) :
( total_num_files , ( total_num_value , total_num_range ) ) = page . GetNumFileSummary ( )
return ( total_num_files , total_num_range , total_num_value )
ordered_pages . sort ( key = key )
if order == ' desc ' :
ordered_pages . reverse ( )
2019-11-14 03:56:30 +00:00
selected_page = self . currentWidget ( )
2019-07-10 22:38:30 +00:00
pages_to_names = { }
2019-11-14 03:56:30 +00:00
for i in range ( self . count ( ) ) :
2019-07-10 22:38:30 +00:00
2019-11-14 03:56:30 +00:00
page = self . widget ( 0 )
2019-07-10 22:38:30 +00:00
2019-11-14 03:56:30 +00:00
name = self . tabText ( 0 )
2019-07-10 22:38:30 +00:00
pages_to_names [ page ] = name
2019-11-14 03:56:30 +00:00
self . removeTab ( 0 )
self . _UpdatePreviousPageIndex ( )
2019-07-10 22:38:30 +00:00
for page in ordered_pages :
is_selected = page == selected_page
name = pages_to_names [ page ]
2019-11-14 03:56:30 +00:00
self . addTab ( page , name )
if is_selected : self . setCurrentIndex ( self . count ( ) - 1 )
2019-07-10 22:38:30 +00:00
2017-12-13 22:33:07 +00:00
def AppendGUISession ( self , name , load_in_a_page_of_pages = True ) :
2017-08-16 21:58:06 +00:00
2020-02-19 21:48:36 +00:00
job_key = ClientThreading . JobKey ( )
job_key . SetVariable ( ' popup_text_1 ' , ' loading session " {} " \u2026 ' . format ( name ) )
HG . client_controller . pub ( ' message ' , job_key )
# get that message showing before we do the work of loading session
HG . client_controller . app . processEvents ( )
2017-08-16 21:58:06 +00:00
try :
session = self . _controller . Read ( ' serialisable_named ' , HydrusSerialisable . SERIALISABLE_TYPE_GUI_SESSION , name )
except Exception as e :
HydrusData . ShowText ( ' While trying to load session ' + name + ' , this error happened: ' )
HydrusData . ShowException ( e )
self . NewPageQuery ( CC . LOCAL_FILE_SERVICE_KEY )
return
2020-04-08 21:10:11 +00:00
HG . client_controller . app . processEvents ( )
2017-12-13 22:33:07 +00:00
if load_in_a_page_of_pages :
destination = self . NewPagesNotebook ( name = name , give_it_a_blank_page = False )
else :
destination = self
2019-02-13 22:26:43 +00:00
page_tuples = session . GetPageTuples ( )
2017-08-16 21:58:06 +00:00
2020-04-08 21:10:11 +00:00
HG . client_controller . app . processEvents ( )
2017-12-13 22:33:07 +00:00
destination . AppendSessionPageTuples ( page_tuples )
2017-08-16 21:58:06 +00:00
2020-02-19 21:48:36 +00:00
job_key . Delete ( )
2017-08-16 21:58:06 +00:00
2018-11-28 22:31:04 +00:00
def AppendGUISessionBackup ( self , name , timestamp , load_in_a_page_of_pages = True ) :
try :
session = self . _controller . Read ( ' serialisable_named ' , HydrusSerialisable . SERIALISABLE_TYPE_GUI_SESSION , name , timestamp )
except Exception as e :
HydrusData . ShowText ( ' While trying to load session ' + name + ' (ts ' + str ( timestamp ) + ' , this error happened: ' )
HydrusData . ShowException ( e )
self . NewPageQuery ( CC . LOCAL_FILE_SERVICE_KEY )
return
if load_in_a_page_of_pages :
destination = self . NewPagesNotebook ( name = name , give_it_a_blank_page = False )
else :
destination = self
2019-02-13 22:26:43 +00:00
page_tuples = session . GetPageTuples ( )
2018-11-28 22:31:04 +00:00
destination . AppendSessionPageTuples ( page_tuples )
2017-08-16 21:58:06 +00:00
def AppendSessionPageTuples ( self , page_tuples ) :
starting_index = self . _GetDefaultPageInsertionIndex ( )
forced_insertion_index = starting_index
2020-03-04 22:12:53 +00:00
self . InsertSessionPageTuples ( forced_insertion_index , page_tuples )
2017-08-16 21:58:06 +00:00
def ChooseNewPage ( self ) :
self . _ChooseNewPage ( )
def ChooseNewPageForDeepestNotebook ( self ) :
2019-11-14 03:56:30 +00:00
current_page = self . currentWidget ( )
2017-08-16 21:58:06 +00:00
if isinstance ( current_page , PagesNotebook ) :
current_page . ChooseNewPageForDeepestNotebook ( )
else :
self . _ChooseNewPage ( )
2019-06-19 22:08:48 +00:00
def CleanBeforeClose ( self ) :
for page in self . _GetPages ( ) :
page . CleanBeforeClose ( )
2017-08-16 21:58:06 +00:00
def CleanBeforeDestroy ( self ) :
for page in self . _GetPages ( ) :
page . CleanBeforeDestroy ( )
2018-05-23 21:05:06 +00:00
self . _controller . ReleasePageKey ( self . _page_key )
2017-08-16 21:58:06 +00:00
def CloseCurrentPage ( self , polite = True ) :
2019-11-14 03:56:30 +00:00
selection = self . currentIndex ( )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
if selection != - 1 :
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
page = self . widget ( selection )
2017-08-16 21:58:06 +00:00
if isinstance ( page , PagesNotebook ) :
if page . GetNumPages ( ) > 0 :
page . CloseCurrentPage ( polite )
else :
self . _ClosePage ( selection , polite = polite )
else :
self . _ClosePage ( selection , polite = polite )
2017-08-23 21:34:25 +00:00
2017-08-16 21:58:06 +00:00
def EventLeftDoubleClick ( self , event ) :
2019-11-14 03:56:30 +00:00
position = event . pos ( )
2017-08-16 21:58:06 +00:00
2019-12-05 05:29:32 +00:00
screen_pos = self . mapToGlobal ( position )
tab_pos = self . tabBar ( ) . mapFromGlobal ( screen_pos )
tab_index = self . tabBar ( ) . tabAt ( tab_pos )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
if tab_index == - 1 :
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
self . ChooseNewPage ( )
2019-12-05 05:29:32 +00:00
2017-09-06 20:18:20 +00:00
else :
2019-11-14 03:56:30 +00:00
return True # was: event.ignore()
2020-02-12 22:50:37 +00:00
2017-08-16 21:58:06 +00:00
2019-12-11 23:18:37 +00:00
def mouseReleaseEvent ( self , event ) :
if event . button ( ) != QC . Qt . RightButton :
QP . TabWidgetWithDnD . mouseReleaseEvent ( self , event )
return
2017-08-16 21:58:06 +00:00
2020-02-12 22:50:37 +00:00
mouse_position = QG . QCursor . pos ( )
2017-08-23 21:34:25 +00:00
2020-02-12 22:50:37 +00:00
self . _ShowMenu ( mouse_position )
2017-08-16 21:58:06 +00:00
2019-12-11 23:18:37 +00:00
def ShowMenuFromScreenPosition ( self , position ) :
2017-08-16 21:58:06 +00:00
2017-08-23 21:34:25 +00:00
notebook = self . _GetNotebookFromScreenPosition ( position )
2017-08-16 21:58:06 +00:00
notebook . _ShowMenu ( position )
def EventMiddleClick ( self , event ) :
2020-03-04 22:12:53 +00:00
if CGC . core ( ) . MenuIsOpen ( ) :
2017-08-30 20:27:47 +00:00
return
2019-11-14 03:56:30 +00:00
position = event . pos ( )
2017-08-23 21:34:25 +00:00
2019-12-05 05:29:32 +00:00
screen_pos = self . mapToGlobal ( position )
tab_pos = self . tabBar ( ) . mapFromGlobal ( screen_pos )
tab_index = self . tabBar ( ) . tabAt ( tab_pos )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
if tab_index == - 1 :
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
self . ChooseNewPage ( )
2017-08-16 21:58:06 +00:00
else :
self . _ClosePage ( tab_index )
2017-08-23 21:34:25 +00:00
def EventNewPageFromScreenPosition ( self , position ) :
2017-08-16 21:58:06 +00:00
2017-08-23 21:34:25 +00:00
notebook = self . _GetNotebookFromScreenPosition ( position )
2017-08-16 21:58:06 +00:00
notebook . _ChooseNewPage ( )
2019-08-21 21:34:01 +00:00
def GetAPIInfoDict ( self , simple ) :
return { }
2019-12-11 23:18:37 +00:00
def GetCurrentGUISession ( self , name ) :
session = GUISession ( name )
for page in self . _GetPages ( ) :
session . AddPageTuple ( page )
return session
2017-08-16 21:58:06 +00:00
def GetCurrentMediaPage ( self ) :
2019-11-14 03:56:30 +00:00
page = self . currentWidget ( )
2017-08-16 21:58:06 +00:00
if isinstance ( page , PagesNotebook ) :
return page . GetCurrentMediaPage ( )
else :
return page # this can be None
def GetMediaPages ( self , only_my_level = False ) :
return self . _GetMediaPages ( only_my_level )
def GetName ( self ) :
return self . _name
2018-05-02 20:45:20 +00:00
def GetNumFileSummary ( self ) :
total_num_files = 0
total_num_value = 0
total_num_range = 0
for page in self . _GetPages ( ) :
( num_files , ( num_value , num_range ) ) = page . GetNumFileSummary ( )
total_num_files + = num_files
total_num_value + = num_value
total_num_range + = num_range
2017-08-16 21:58:06 +00:00
2018-05-02 20:45:20 +00:00
return ( total_num_files , ( total_num_value , total_num_range ) )
2017-08-16 21:58:06 +00:00
def GetNumPages ( self , only_my_level = False ) :
if only_my_level :
2019-11-14 03:56:30 +00:00
return self . count ( )
2017-08-16 21:58:06 +00:00
else :
total = 0
for page in self . _GetPages ( ) :
if isinstance ( page , PagesNotebook ) :
total + = page . GetNumPages ( False )
else :
total + = 1
return total
2019-06-26 21:27:18 +00:00
def GetOrMakeMultipleWatcherPage ( self , desired_page_name = None , desired_page_key = None , select_page = True ) :
2018-05-16 20:09:50 +00:00
2019-03-20 21:22:10 +00:00
potential_watcher_pages = [ page for page in self . _GetMediaPages ( False ) if page . IsMultipleWatcherPage ( ) ]
2018-05-30 20:13:21 +00:00
2019-06-26 21:27:18 +00:00
if desired_page_key is not None and desired_page_key in ( page . GetPageKey ( ) for page in potential_watcher_pages ) :
potential_watcher_pages = [ page for page in potential_watcher_pages if page . GetPageKey ( ) == desired_page_key ]
elif desired_page_name is not None :
2018-05-30 20:13:21 +00:00
2019-04-10 22:50:53 +00:00
potential_watcher_pages = [ page for page in potential_watcher_pages if page . GetName ( ) == desired_page_name ]
2018-05-30 20:13:21 +00:00
2019-02-27 23:03:30 +00:00
2019-03-20 21:22:10 +00:00
if len ( potential_watcher_pages ) > 0 :
2019-02-27 23:03:30 +00:00
2019-03-20 21:22:10 +00:00
# ok, we can use an existing one. should we use the current?
2019-02-27 23:03:30 +00:00
2019-03-20 21:22:10 +00:00
current_media_page = self . GetCurrentMediaPage ( )
2018-05-16 20:09:50 +00:00
2019-03-20 21:22:10 +00:00
if current_media_page is not None and current_media_page in potential_watcher_pages :
2018-05-16 20:09:50 +00:00
2019-03-20 21:22:10 +00:00
return current_media_page
2018-05-16 20:09:50 +00:00
2019-03-20 21:22:10 +00:00
else :
2018-05-16 20:09:50 +00:00
2019-03-20 21:22:10 +00:00
return potential_watcher_pages [ 0 ]
2018-05-16 20:09:50 +00:00
2019-03-20 21:22:10 +00:00
else :
return self . NewPageImportMultipleWatcher ( page_name = desired_page_name , on_deepest_notebook = True , select_page = select_page )
2018-05-16 20:09:50 +00:00
2019-06-26 21:27:18 +00:00
def GetOrMakeURLImportPage ( self , desired_page_name = None , desired_page_key = None , select_page = True ) :
2019-02-27 23:03:30 +00:00
2019-03-20 21:22:10 +00:00
potential_url_import_pages = [ page for page in self . _GetMediaPages ( False ) if page . IsURLImportPage ( ) ]
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
if desired_page_key is not None and desired_page_key in ( page . GetPageKey ( ) for page in potential_url_import_pages ) :
potential_url_import_pages = [ page for page in potential_url_import_pages if page . GetPageKey ( ) == desired_page_key ]
elif desired_page_name is not None :
2019-02-27 23:03:30 +00:00
2019-04-10 22:50:53 +00:00
potential_url_import_pages = [ page for page in potential_url_import_pages if page . GetName ( ) == desired_page_name ]
2019-02-27 23:03:30 +00:00
2019-03-20 21:22:10 +00:00
if len ( potential_url_import_pages ) > 0 :
2019-02-27 23:03:30 +00:00
2019-03-20 21:22:10 +00:00
# ok, we can use an existing one. should we use the current?
2019-02-27 23:03:30 +00:00
2019-03-20 21:22:10 +00:00
current_media_page = self . GetCurrentMediaPage ( )
2017-08-16 21:58:06 +00:00
2019-03-20 21:22:10 +00:00
if current_media_page is not None and current_media_page in potential_url_import_pages :
2017-08-16 21:58:06 +00:00
2019-03-20 21:22:10 +00:00
return current_media_page
2017-08-16 21:58:06 +00:00
2019-03-20 21:22:10 +00:00
else :
2017-08-16 21:58:06 +00:00
2019-03-20 21:22:10 +00:00
return potential_url_import_pages [ 0 ]
2017-08-16 21:58:06 +00:00
2019-03-20 21:22:10 +00:00
else :
return self . NewPageImportURLs ( page_name = desired_page_name , on_deepest_notebook = True , select_page = select_page )
2017-08-16 21:58:06 +00:00
2019-07-17 22:10:19 +00:00
def GetPageFromPageKey ( self , page_key ) :
2019-08-21 21:34:01 +00:00
if self . _page_key == page_key :
return self
2019-07-17 22:10:19 +00:00
for page in self . _GetPages ( ) :
if page . GetPageKey ( ) == page_key :
return page
if isinstance ( page , PagesNotebook ) :
if page . HasPageKey ( page_key ) :
return page . GetPageFromPageKey ( page_key )
return None
2017-08-16 21:58:06 +00:00
def GetPageKey ( self ) :
return self . _page_key
2018-05-23 21:05:06 +00:00
def GetPageKeys ( self ) :
page_keys = { self . _page_key }
for page in self . _GetPages ( ) :
page_keys . update ( page . GetPageKeys ( ) )
return page_keys
2020-04-08 21:10:11 +00:00
def GetParentNotebook ( self ) :
return self . _parent_notebook
2019-08-21 21:34:01 +00:00
def GetSessionAPIInfoDict ( self , is_selected = True ) :
2019-06-05 19:42:39 +00:00
2019-11-14 03:56:30 +00:00
current_page = self . currentWidget ( )
2019-06-05 19:42:39 +00:00
my_pages_list = [ ]
for page in self . _GetPages ( ) :
2019-08-21 21:34:01 +00:00
page_info_dict = page . GetSessionAPIInfoDict ( is_selected = is_selected )
2019-06-05 19:42:39 +00:00
my_pages_list . append ( page_info_dict )
root = { }
root [ ' name ' ] = self . GetName ( )
2019-06-26 21:27:18 +00:00
root [ ' page_key ' ] = self . _page_key . hex ( )
2019-06-05 19:42:39 +00:00
root [ ' page_type ' ] = ClientGUIManagement . MANAGEMENT_TYPE_PAGE_OF_PAGES
root [ ' selected ' ] = is_selected
root [ ' pages ' ] = my_pages_list
return root
2017-08-16 21:58:06 +00:00
def GetPages ( self ) :
return self . _GetPages ( )
def GetPrettyStatus ( self ) :
2018-05-02 20:45:20 +00:00
( num_files , ( num_value , num_range ) ) = self . GetNumFileSummary ( )
2018-07-04 20:48:28 +00:00
num_string = HydrusData . ToHumanInt ( num_files )
2018-05-02 20:45:20 +00:00
if num_range > 0 and num_value != num_range :
num_string + = ' , ' + HydrusData . ConvertValueRangeToPrettyString ( num_value , num_range )
2019-11-14 03:56:30 +00:00
return HydrusData . ToHumanInt ( self . count ( ) ) + ' pages, ' + num_string + ' files '
2017-08-16 21:58:06 +00:00
2019-02-06 22:41:35 +00:00
def GetTestAbleToCloseStatement ( self ) :
count = collections . Counter ( )
for page in self . _GetMediaPages ( False ) :
try :
page . CheckAbleToClose ( )
except HydrusExceptions . VetoException as e :
reason = str ( e )
count [ reason ] + = 1
if len ( count ) > 0 :
message = ' '
for ( reason , c ) in list ( count . items ( ) ) :
if c == 1 :
message = ' 1 page says: ' + reason
else :
message = HydrusData . ToHumanInt ( c ) + ' pages say: ' + reason
message + = os . linesep
return message
else :
return None
2019-10-16 20:47:55 +00:00
def GetTotalWeight ( self ) :
total_weight = sum ( ( page . GetTotalWeight ( ) for page in self . _GetPages ( ) ) )
return total_weight
2018-05-16 20:09:50 +00:00
def HasMediaPageName ( self , page_name , only_my_level = False ) :
media_pages = self . _GetMediaPages ( only_my_level )
for page in media_pages :
if page . GetName ( ) == page_name :
return True
return False
2017-08-16 21:58:06 +00:00
def HasPage ( self , page ) :
return self . HasPageKey ( page . GetPageKey ( ) )
def HasPageKey ( self , page_key ) :
for page in self . _GetPages ( ) :
if page . GetPageKey ( ) == page_key :
return True
elif isinstance ( page , PagesNotebook ) and page . HasPageKey ( page_key ) :
return True
2018-05-16 20:09:50 +00:00
return False
def HasMultipleWatcherPage ( self ) :
for page in self . _GetPages ( ) :
if isinstance ( page , PagesNotebook ) :
if page . HasMultipleWatcherPage ( ) :
return True
else :
if page . IsMultipleWatcherPage ( ) :
return True
2017-08-16 21:58:06 +00:00
return False
def HasURLImportPage ( self ) :
for page in self . _GetPages ( ) :
if isinstance ( page , PagesNotebook ) :
if page . HasURLImportPage ( ) :
return True
else :
if page . IsURLImportPage ( ) :
return True
return False
2020-03-04 22:12:53 +00:00
def InsertSessionPageTuples ( self , forced_insertion_index , page_tuples ) :
done_first_page = False
for page_tuple in page_tuples :
2020-05-13 19:03:16 +00:00
select_page = not done_first_page
2020-03-04 22:12:53 +00:00
( page_type , page_data ) = page_tuple
if page_type == ' pages ' :
( name , subpage_tuples ) = page_data
try :
2020-05-13 19:03:16 +00:00
page = self . NewPagesNotebook ( name , forced_insertion_index = forced_insertion_index , give_it_a_blank_page = False , select_page = select_page )
2020-03-04 22:12:53 +00:00
page . AppendSessionPageTuples ( subpage_tuples )
except Exception as e :
HydrusData . ShowException ( e )
elif page_type == ' page ' :
( management_controller , initial_hashes ) = page_data
try :
self . NewPage ( management_controller , initial_hashes = initial_hashes , forced_insertion_index = forced_insertion_index , select_page = select_page )
except Exception as e :
HydrusData . ShowException ( e )
forced_insertion_index + = 1
2020-05-13 19:03:16 +00:00
done_first_page = True
2020-03-04 22:12:53 +00:00
2019-02-27 23:03:30 +00:00
def IsMultipleWatcherPage ( self ) :
return False
2018-12-05 22:35:30 +00:00
def IsImporter ( self ) :
return False
2019-02-27 23:03:30 +00:00
def IsURLImportPage ( self ) :
return False
2017-08-16 21:58:06 +00:00
def LoadGUISession ( self , name ) :
2019-11-14 03:56:30 +00:00
if self . count ( ) > 0 :
2017-08-16 21:58:06 +00:00
2019-09-05 00:05:32 +00:00
message = ' Close the current pages and load session " {} " ? ' . format ( name )
result = ClientGUIDialogsQuick . GetYesNo ( self , message , title = ' Clear and load session? ' )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
if result != QW . QDialog . Accepted :
2017-12-13 22:33:07 +00:00
2019-09-05 00:05:32 +00:00
return
2017-12-13 22:33:07 +00:00
2017-08-16 21:58:06 +00:00
2017-12-13 22:33:07 +00:00
try :
self . TestAbleToClose ( )
2018-05-02 20:45:20 +00:00
except HydrusExceptions . VetoException :
2017-12-13 22:33:07 +00:00
return
2018-05-16 20:09:50 +00:00
self . _CloseAllPages ( polite = False , delete_pages = True )
2019-11-14 03:56:30 +00:00
self . _controller . CallLaterQtSafe ( self , 1.0 , self . AppendGUISession , name , load_in_a_page_of_pages = False )
2018-05-16 20:09:50 +00:00
else :
self . AppendGUISession ( name , load_in_a_page_of_pages = False )
2017-08-16 21:58:06 +00:00
2017-12-20 22:55:48 +00:00
def MediaDragAndDropDropped ( self , source_page_key , hashes ) :
2019-07-17 22:10:19 +00:00
source_page = self . GetPageFromPageKey ( source_page_key )
2017-12-20 22:55:48 +00:00
if source_page is None :
return
2019-11-14 03:56:30 +00:00
screen_position = QG . QCursor . pos ( )
2017-12-20 22:55:48 +00:00
dest_notebook = self . _GetNotebookFromScreenPosition ( screen_position )
2019-11-14 03:56:30 +00:00
tab_index = ClientGUIFunctions . NotebookScreenToHitTest ( dest_notebook , screen_position )
2017-12-20 22:55:48 +00:00
do_add = True
# do chase - if we need to chase to an existing dest page on which we dropped files
# do return - if we need to return to source page if we created a new one
2019-11-14 03:56:30 +00:00
if tab_index == - 1 and dest_notebook . currentWidget ( ) and dest_notebook . currentWidget ( ) . rect ( ) . contains ( dest_notebook . currentWidget ( ) . mapFromGlobal ( screen_position ) ) :
2017-12-20 22:55:48 +00:00
2019-11-14 03:56:30 +00:00
dest_page = dest_notebook . currentWidget ( )
2017-12-20 22:55:48 +00:00
2019-11-14 03:56:30 +00:00
elif tab_index == - 1 :
2017-12-20 22:55:48 +00:00
dest_page = dest_notebook . NewPageQuery ( CC . LOCAL_FILE_SERVICE_KEY , initial_hashes = hashes )
do_add = False
else :
2019-11-14 03:56:30 +00:00
dest_page = dest_notebook . widget ( tab_index )
2017-12-20 22:55:48 +00:00
if isinstance ( dest_page , PagesNotebook ) :
result = dest_page . GetCurrentMediaPage ( )
if result is None :
dest_page = dest_page . NewPageQuery ( CC . LOCAL_FILE_SERVICE_KEY , initial_hashes = hashes )
do_add = False
else :
dest_page = result
if dest_page is None :
return # we somehow dropped onto a new notebook that has no pages
if dest_page . GetPageKey ( ) == source_page_key :
return # we dropped onto the same page we picked up on
if do_add :
2019-05-01 21:24:42 +00:00
media_results = self . _controller . Read ( ' media_results ' , hashes , sorted = True )
2017-12-20 22:55:48 +00:00
2019-05-01 21:24:42 +00:00
dest_page . GetMediaPanel ( ) . AddMediaResults ( dest_page . GetPageKey ( ) , media_results )
2017-12-20 22:55:48 +00:00
else :
self . ShowPage ( source_page )
2019-11-14 03:56:30 +00:00
# queryKBM here for instant check, not waiting for event processing to catch up u wot mate
ctrl_down = QW . QApplication . queryKeyboardModifiers ( ) & QC . Qt . ControlModifier
2017-12-20 22:55:48 +00:00
if not ctrl_down :
source_page . GetMediaPanel ( ) . RemoveMedia ( source_page . GetPageKey ( ) , hashes )
2018-02-14 21:47:18 +00:00
def NewPage ( self , management_controller , initial_hashes = None , forced_insertion_index = None , on_deepest_notebook = False , select_page = True ) :
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
if self . window ( ) . isMinimized ( ) :
2019-06-05 19:42:39 +00:00
return None
2019-11-14 03:56:30 +00:00
current_page = self . currentWidget ( )
2017-08-16 21:58:06 +00:00
2017-08-23 21:34:25 +00:00
if on_deepest_notebook and isinstance ( current_page , PagesNotebook ) :
2017-08-16 21:58:06 +00:00
2017-09-13 20:50:41 +00:00
return current_page . NewPage ( management_controller , initial_hashes = initial_hashes , forced_insertion_index = forced_insertion_index , on_deepest_notebook = on_deepest_notebook )
2017-08-16 21:58:06 +00:00
2017-12-13 22:33:07 +00:00
WARNING_TOTAL_PAGES = self . _controller . new_options . GetInteger ( ' total_pages_warning ' )
2017-12-06 22:06:56 +00:00
MAX_TOTAL_PAGES = 200
2019-10-16 20:47:55 +00:00
( total_active_page_count , total_closed_page_count , total_active_weight , total_closed_weight ) = self . _controller . gui . GetTotalPageCounts ( )
2017-12-06 22:06:56 +00:00
if total_active_page_count + total_closed_page_count > = WARNING_TOTAL_PAGES :
2017-08-16 21:58:06 +00:00
2017-12-06 22:06:56 +00:00
self . _controller . gui . DeleteAllClosedPages ( )
2017-08-16 21:58:06 +00:00
2017-12-06 22:06:56 +00:00
if not HG . no_page_limit_mode :
2017-08-16 21:58:06 +00:00
2017-08-23 21:34:25 +00:00
if total_active_page_count > = MAX_TOTAL_PAGES :
2017-12-06 22:06:56 +00:00
message = ' The client should not have more than ' + str ( MAX_TOTAL_PAGES ) + ' pages open, as it leads to program instability! Are you sure you want to open more pages? '
2017-08-23 21:34:25 +00:00
2019-09-05 00:05:32 +00:00
result = ClientGUIDialogsQuick . GetYesNo ( self , message , title = ' Too many pages! ' , yes_label = ' yes, and do not tell me again ' , no_label = ' no ' )
2019-11-14 03:56:30 +00:00
if result == QW . QDialog . Accepted :
2017-12-06 22:06:56 +00:00
2019-09-05 00:05:32 +00:00
HG . no_page_limit_mode = True
self . _controller . pub ( ' notify_new_options ' )
else :
return None
2017-12-06 22:06:56 +00:00
2017-08-23 21:34:25 +00:00
2017-12-06 22:06:56 +00:00
if total_active_page_count == WARNING_TOTAL_PAGES :
2017-08-23 21:34:25 +00:00
2017-12-13 22:33:07 +00:00
HydrusData . ShowText ( ' You have ' + str ( total_active_page_count ) + ' pages open! You can only open a few more before program stability is affected! Please close some now! ' )
2017-08-23 21:34:25 +00:00
2017-08-16 21:58:06 +00:00
self . _controller . ResetIdleTimer ( )
self . _controller . ResetPageChangeTimer ( )
if initial_hashes is None :
initial_hashes = [ ]
page = Page ( self , self . _controller , management_controller , initial_hashes )
if forced_insertion_index is None :
if self . _next_new_page_index is None :
insertion_index = self . _GetDefaultPageInsertionIndex ( )
else :
insertion_index = self . _next_new_page_index
self . _next_new_page_index = None
else :
insertion_index = forced_insertion_index
2019-04-10 22:50:53 +00:00
page_name = page . GetName ( )
2017-08-16 21:58:06 +00:00
2017-10-18 19:41:25 +00:00
# in some unusual circumstances, this gets out of whack
2019-11-14 03:56:30 +00:00
insertion_index = min ( insertion_index , self . count ( ) )
self . insertTab ( insertion_index , page , page_name )
2019-11-28 01:11:46 +00:00
if select_page :
self . setCurrentIndex ( insertion_index )
2017-10-18 19:41:25 +00:00
2017-08-16 21:58:06 +00:00
self . _controller . pub ( ' refresh_page_name ' , page . GetPageKey ( ) )
2017-10-25 21:45:15 +00:00
self . _controller . pub ( ' notify_new_pages ' )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
QP . CallAfter ( page . Start )
2018-03-28 21:55:58 +00:00
if select_page :
2018-05-16 20:09:50 +00:00
page . SetSearchFocus ( )
# this is here for now due to the pagechooser having a double-layer dialog on a booru choice, which messes up some focus inheritance
2019-11-14 03:56:30 +00:00
self . _controller . CallLaterQtSafe ( self , 0.5 , page . SetSearchFocus )
2018-03-28 21:55:58 +00:00
2017-08-16 21:58:06 +00:00
return page
2017-08-23 21:34:25 +00:00
def NewPageDuplicateFilter ( self , on_deepest_notebook = False ) :
2017-08-16 21:58:06 +00:00
management_controller = ClientGUIManagement . CreateManagementControllerDuplicateFilter ( )
2017-08-23 21:34:25 +00:00
return self . NewPage ( management_controller , on_deepest_notebook = on_deepest_notebook )
2017-08-16 21:58:06 +00:00
2018-08-01 20:44:57 +00:00
def NewPageImportGallery ( self , on_deepest_notebook = False ) :
2017-08-16 21:58:06 +00:00
2018-08-01 20:44:57 +00:00
management_controller = ClientGUIManagement . CreateManagementControllerImportGallery ( )
2017-08-16 21:58:06 +00:00
2017-08-23 21:34:25 +00:00
return self . NewPage ( management_controller , on_deepest_notebook = on_deepest_notebook )
2017-08-16 21:58:06 +00:00
2018-04-05 01:22:26 +00:00
def NewPageImportSimpleDownloader ( self , on_deepest_notebook = False ) :
2017-08-16 21:58:06 +00:00
2018-04-05 01:22:26 +00:00
management_controller = ClientGUIManagement . CreateManagementControllerImportSimpleDownloader ( )
2017-08-16 21:58:06 +00:00
2017-08-23 21:34:25 +00:00
return self . NewPage ( management_controller , on_deepest_notebook = on_deepest_notebook )
2017-08-16 21:58:06 +00:00
2019-03-20 21:22:10 +00:00
def NewPageImportMultipleWatcher ( self , page_name = None , url = None , on_deepest_notebook = False , select_page = True ) :
2018-05-16 20:09:50 +00:00
2019-02-27 23:03:30 +00:00
management_controller = ClientGUIManagement . CreateManagementControllerImportMultipleWatcher ( page_name = page_name , url = url )
2018-05-16 20:09:50 +00:00
2019-03-20 21:22:10 +00:00
return self . NewPage ( management_controller , on_deepest_notebook = on_deepest_notebook , select_page = select_page )
2018-05-16 20:09:50 +00:00
2019-03-20 21:22:10 +00:00
def NewPageImportURLs ( self , page_name = None , on_deepest_notebook = False , select_page = True ) :
2017-08-16 21:58:06 +00:00
2019-02-27 23:03:30 +00:00
management_controller = ClientGUIManagement . CreateManagementControllerImportURLs ( page_name = page_name )
2017-08-16 21:58:06 +00:00
2019-03-20 21:22:10 +00:00
return self . NewPage ( management_controller , on_deepest_notebook = on_deepest_notebook , select_page = select_page )
2017-08-16 21:58:06 +00:00
2017-08-23 21:34:25 +00:00
def NewPagePetitions ( self , service_key , on_deepest_notebook = False ) :
2017-08-16 21:58:06 +00:00
management_controller = ClientGUIManagement . CreateManagementControllerPetitions ( service_key )
2017-08-23 21:34:25 +00:00
return self . NewPage ( management_controller , on_deepest_notebook = on_deepest_notebook )
2017-08-16 21:58:06 +00:00
2018-02-14 21:47:18 +00:00
def NewPageQuery ( self , file_service_key , initial_hashes = None , initial_predicates = None , page_name = None , on_deepest_notebook = False , do_sort = False , select_page = True ) :
2017-08-16 21:58:06 +00:00
if initial_hashes is None :
initial_hashes = [ ]
if initial_predicates is None :
initial_predicates = [ ]
if page_name is None :
page_name = ' files '
search_enabled = len ( initial_hashes ) == 0
2017-12-06 22:06:56 +00:00
new_options = self . _controller . new_options
2017-08-16 21:58:06 +00:00
tag_service_key = new_options . GetKey ( ' default_tag_service_search_page ' )
if not self . _controller . services_manager . ServiceExists ( tag_service_key ) :
tag_service_key = CC . COMBINED_TAG_SERVICE_KEY
2020-03-18 21:35:57 +00:00
if file_service_key == CC . COMBINED_FILE_SERVICE_KEY and tag_service_key == CC . COMBINED_TAG_SERVICE_KEY :
2020-04-01 21:51:42 +00:00
file_service_key = CC . COMBINED_LOCAL_FILE_SERVICE_KEY
2020-03-18 21:35:57 +00:00
2020-03-11 21:52:11 +00:00
tag_search_context = ClientSearch . TagSearchContext ( service_key = tag_service_key )
file_search_context = ClientSearch . FileSearchContext ( file_service_key = file_service_key , tag_search_context = tag_search_context , predicates = initial_predicates )
2017-08-16 21:58:06 +00:00
2020-04-01 21:51:42 +00:00
management_controller = ClientGUIManagement . CreateManagementControllerQuery ( page_name , file_search_context , search_enabled )
2017-08-16 21:58:06 +00:00
2018-02-14 21:47:18 +00:00
page = self . NewPage ( management_controller , initial_hashes = initial_hashes , on_deepest_notebook = on_deepest_notebook , select_page = select_page )
2017-10-18 19:41:25 +00:00
if do_sort :
HG . client_controller . pub ( ' do_page_sort ' , page . GetPageKey ( ) )
return page
2017-08-16 21:58:06 +00:00
2018-05-16 20:09:50 +00:00
def NewPagesNotebook ( self , name = ' pages ' , forced_insertion_index = None , on_deepest_notebook = False , give_it_a_blank_page = True , select_page = True ) :
2017-08-23 21:34:25 +00:00
2019-11-14 03:56:30 +00:00
current_page = self . currentWidget ( )
2017-08-23 21:34:25 +00:00
if on_deepest_notebook and isinstance ( current_page , PagesNotebook ) :
2019-02-13 22:26:43 +00:00
return current_page . NewPagesNotebook ( name = name , forced_insertion_index = forced_insertion_index , on_deepest_notebook = on_deepest_notebook , give_it_a_blank_page = give_it_a_blank_page )
2017-08-23 21:34:25 +00:00
2017-08-16 21:58:06 +00:00
self . _controller . ResetIdleTimer ( )
self . _controller . ResetPageChangeTimer ( )
page = PagesNotebook ( self , self . _controller , name )
if forced_insertion_index is None :
if self . _next_new_page_index is None :
insertion_index = self . _GetDefaultPageInsertionIndex ( )
else :
insertion_index = self . _next_new_page_index
self . _next_new_page_index = None
else :
insertion_index = forced_insertion_index
2019-04-10 22:50:53 +00:00
page_name = page . GetName ( )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
self . insertTab ( insertion_index , page , page_name )
2020-05-13 19:03:16 +00:00
if select_page :
self . setCurrentIndex ( insertion_index )
2017-08-16 21:58:06 +00:00
self . _controller . pub ( ' refresh_page_name ' , page . GetPageKey ( ) )
2017-08-30 20:27:47 +00:00
if give_it_a_blank_page :
page . NewPageQuery ( CC . LOCAL_FILE_SERVICE_KEY )
2017-08-16 21:58:06 +00:00
return page
def NotifyPageUnclosed ( self , page ) :
page_key = page . GetPageKey ( )
for ( index , closed_page_key ) in self . _closed_pages :
if page_key == closed_page_key :
2019-11-14 03:56:30 +00:00
page . show ( )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
insert_index = min ( index , self . count ( ) )
2017-08-16 21:58:06 +00:00
2019-04-10 22:50:53 +00:00
name = page . GetName ( )
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
self . insertTab ( insert_index , page , name )
self . setCurrentIndex ( insert_index )
2017-08-16 21:58:06 +00:00
self . _controller . pub ( ' refresh_page_name ' , page . GetPageKey ( ) )
self . _closed_pages . remove ( ( index , closed_page_key ) )
break
def PageHidden ( self ) :
2019-11-14 03:56:30 +00:00
result = self . currentWidget ( )
2017-08-16 21:58:06 +00:00
if result is not None :
result . PageHidden ( )
2020-05-13 19:03:16 +00:00
def pageJustChanged ( self , index ) :
old_selection = self . _previous_page_index
selection = index
if old_selection != - 1 and old_selection < self . count ( ) :
self . widget ( old_selection ) . PageHidden ( )
if selection != - 1 :
new_page = self . widget ( selection )
new_page . PageShown ( )
self . _controller . gui . RefreshStatusBar ( )
self . _previous_page_index = index
self . _controller . pub ( ' notify_page_change ' )
2017-08-16 21:58:06 +00:00
def PageShown ( self ) :
2019-11-14 03:56:30 +00:00
result = self . currentWidget ( )
2017-08-16 21:58:06 +00:00
if result is not None :
result . PageShown ( )
2018-02-14 21:47:18 +00:00
def PresentImportedFilesToPage ( self , hashes , page_name ) :
page = self . _GetPageFromName ( page_name )
if page is None :
page = self . NewPageQuery ( CC . LOCAL_FILE_SERVICE_KEY , initial_hashes = hashes , page_name = page_name , on_deepest_notebook = True , select_page = False )
else :
2019-11-14 03:56:30 +00:00
def qt_finish ( page , media_results ) :
2019-10-16 20:47:55 +00:00
if not page :
return
page . GetMediaPanel ( ) . AddMediaResults ( page . GetPageKey ( ) , media_results )
def do_it ( page , hashes ) :
media_results = self . _controller . Read ( ' media_results ' , hashes , sorted = True )
2019-11-14 03:56:30 +00:00
QP . CallAfter ( qt_finish , page , media_results )
2019-10-16 20:47:55 +00:00
2018-02-14 21:47:18 +00:00
2019-10-16 20:47:55 +00:00
HG . client_controller . CallToThread ( do_it , page , hashes )
2018-02-14 21:47:18 +00:00
return page
2017-10-04 17:51:58 +00:00
def RefreshAllPages ( self ) :
2017-08-16 21:58:06 +00:00
for page in self . _GetPages ( ) :
2017-10-04 17:51:58 +00:00
if isinstance ( page , PagesNotebook ) :
page . RefreshAllPages ( )
else :
page . RefreshQuery ( )
2017-08-16 21:58:06 +00:00
def RefreshPageName ( self , page_key = None ) :
if page_key is None :
2019-11-14 03:56:30 +00:00
for index in range ( self . count ( ) ) :
2017-08-16 21:58:06 +00:00
self . _RefreshPageName ( index )
else :
for ( index , page ) in enumerate ( self . _GetPages ( ) ) :
do_it = False
if page . GetPageKey ( ) == page_key :
do_it = True
elif isinstance ( page , PagesNotebook ) and page . HasPageKey ( page_key ) :
do_it = True
if do_it :
self . _RefreshPageName ( index )
break
2019-04-10 22:50:53 +00:00
def SetName ( self , name ) :
2017-08-16 21:58:06 +00:00
self . _name = name
def ShowPage ( self , showee ) :
for ( i , page ) in enumerate ( self . _GetPages ( ) ) :
2019-11-14 03:56:30 +00:00
if isinstance ( page , QW . QTabWidget ) and page . HasPage ( showee ) :
2017-08-16 21:58:06 +00:00
2019-11-14 03:56:30 +00:00
self . setCurrentIndex ( i )
2017-08-16 21:58:06 +00:00
page . ShowPage ( showee )
break
elif page == showee :
2019-11-14 03:56:30 +00:00
self . setCurrentIndex ( i )
2017-08-16 21:58:06 +00:00
break
2019-02-13 22:26:43 +00:00
def TestAbleToClose ( self ) :
statement = self . GetTestAbleToCloseStatement ( )
if statement is not None :
message = ' Are you sure you want to close this page of pages? '
message + = os . linesep * 2
message + = statement
2019-09-05 00:05:32 +00:00
result = ClientGUIDialogsQuick . GetYesNo ( self , message )
2019-11-14 03:56:30 +00:00
if result == QW . QDialog . Rejected :
2019-02-13 22:26:43 +00:00
2019-09-05 00:05:32 +00:00
raise HydrusExceptions . VetoException ( )
2019-02-13 22:26:43 +00:00
2018-05-30 20:13:21 +00:00
def REPEATINGPageUpdate ( self ) :
2017-12-13 22:33:07 +00:00
pass
2017-08-16 21:58:06 +00:00
class GUISession ( HydrusSerialisable . SerialisableBaseNamed ) :
SERIALISABLE_TYPE = HydrusSerialisable . SERIALISABLE_TYPE_GUI_SESSION
2017-11-29 21:48:23 +00:00
SERIALISABLE_NAME = ' GUI Session '
2019-04-10 22:50:53 +00:00
SERIALISABLE_VERSION = 4
2017-08-16 21:58:06 +00:00
def __init__ ( self , name ) :
HydrusSerialisable . SerialisableBaseNamed . __init__ ( self , name )
2019-02-13 22:26:43 +00:00
self . _page_tuples = [ ]
2017-08-16 21:58:06 +00:00
def _GetPageTuple ( self , page ) :
if isinstance ( page , PagesNotebook ) :
name = page . GetName ( )
page_tuples = [ self . _GetPageTuple ( subpage ) for subpage in page . GetPages ( ) ]
return ( ' pages ' , ( name , page_tuples ) )
else :
management_controller = page . GetManagementController ( )
hashes = list ( page . GetHashes ( ) )
return ( ' page ' , ( management_controller , hashes ) )
def _GetSerialisableInfo ( self ) :
2020-03-04 22:12:53 +00:00
def handle_e ( page_tuple , e ) :
2018-05-09 20:23:00 +00:00
HydrusData . ShowText ( ' Attempting to save a page to the session failed! Its data tuple and error follows! Please close it or see if you can clear any potentially invalid data from it! ' )
HydrusData . ShowText ( page_tuple )
HydrusData . ShowException ( e )
2017-08-16 21:58:06 +00:00
def GetSerialisablePageTuple ( page_tuple ) :
( page_type , page_data ) = page_tuple
if page_type == ' pages ' :
( name , page_tuples ) = page_data
2018-05-09 20:23:00 +00:00
serialisable_page_tuples = [ ]
for pt in page_tuples :
try :
serialisable_page_tuples . append ( GetSerialisablePageTuple ( pt ) )
except Exception as e :
2020-03-04 22:12:53 +00:00
handle_e ( page_tuple , e )
2018-05-09 20:23:00 +00:00
2017-08-16 21:58:06 +00:00
serialisable_page_data = ( name , serialisable_page_tuples )
elif page_type == ' page ' :
( management_controller , hashes ) = page_data
serialisable_management_controller = management_controller . GetSerialisableTuple ( )
2019-01-09 22:59:03 +00:00
serialisable_hashes = [ hash . hex ( ) for hash in hashes ]
2017-08-16 21:58:06 +00:00
serialisable_page_data = ( serialisable_management_controller , serialisable_hashes )
serialisable_tuple = ( page_type , serialisable_page_data )
return serialisable_tuple
serialisable_info = [ ]
2019-02-13 22:26:43 +00:00
for page_tuple in self . _page_tuples :
2017-08-16 21:58:06 +00:00
2018-05-09 20:23:00 +00:00
try :
serialisable_page_tuple = GetSerialisablePageTuple ( page_tuple )
serialisable_info . append ( serialisable_page_tuple )
except Exception as e :
2020-03-04 22:12:53 +00:00
handle_e ( page_tuple , e )
2018-05-09 20:23:00 +00:00
2017-08-16 21:58:06 +00:00
return serialisable_info
def _InitialiseFromSerialisableInfo ( self , serialisable_info ) :
2020-03-04 22:12:53 +00:00
def handle_e ( serialisable_page_tuple , e ) :
2018-05-09 20:23:00 +00:00
HydrusData . ShowText ( ' A page failed to load! Its serialised data and error follows! ' )
HydrusData . ShowText ( serialisable_page_tuple )
HydrusData . ShowException ( e )
2017-08-16 21:58:06 +00:00
def GetPageTuple ( serialisable_page_tuple ) :
( page_type , serialisable_page_data ) = serialisable_page_tuple
if page_type == ' pages ' :
( name , serialisable_page_tuples ) = serialisable_page_data
2018-05-09 20:23:00 +00:00
page_tuples = [ ]
for spt in serialisable_page_tuples :
try :
page_tuples . append ( GetPageTuple ( spt ) )
except Exception as e :
2020-03-04 22:12:53 +00:00
handle_e ( spt , e )
2018-05-09 20:23:00 +00:00
2017-08-16 21:58:06 +00:00
page_data = ( name , page_tuples )
elif page_type == ' page ' :
( serialisable_management_controller , serialisable_hashes ) = serialisable_page_data
management_controller = HydrusSerialisable . CreateFromSerialisableTuple ( serialisable_management_controller )
2019-01-09 22:59:03 +00:00
hashes = [ bytes . fromhex ( hash ) for hash in serialisable_hashes ]
2017-08-16 21:58:06 +00:00
page_data = ( management_controller , hashes )
page_tuple = ( page_type , page_data )
return page_tuple
for serialisable_page_tuple in serialisable_info :
2018-05-09 20:23:00 +00:00
try :
page_tuple = GetPageTuple ( serialisable_page_tuple )
2019-02-13 22:26:43 +00:00
self . _page_tuples . append ( page_tuple )
2018-05-09 20:23:00 +00:00
except Exception as e :
2020-03-04 22:12:53 +00:00
handle_e ( serialisable_page_tuple , e )
2018-05-09 20:23:00 +00:00
2017-08-02 21:32:54 +00:00
def _UpdateSerialisableInfo ( self , version , old_serialisable_info ) :
if version == 1 :
new_serialisable_info = [ ]
for ( page_name , serialisable_management_controller , serialisable_hashes ) in old_serialisable_info :
management_controller = HydrusSerialisable . CreateFromSerialisableTuple ( serialisable_management_controller )
management_controller . SetPageName ( page_name )
serialisable_management_controller = management_controller . GetSerialisableTuple ( )
new_serialisable_info . append ( ( serialisable_management_controller , serialisable_hashes ) )
return ( 2 , new_serialisable_info )
2014-01-22 21:11:22 +00:00
2013-04-24 21:23:53 +00:00
2017-08-16 21:58:06 +00:00
if version == 2 :
new_serialisable_info = [ ]
for ( serialisable_management_controller , serialisable_hashes ) in old_serialisable_info :
new_serialisable_info . append ( ( ' page ' , ( serialisable_management_controller , serialisable_hashes ) ) )
return ( 3 , new_serialisable_info )
2019-04-10 22:50:53 +00:00
if version == 3 :
def clean_tuple ( spt ) :
( page_type , serialisable_page_data ) = spt
if page_type == ' pages ' :
( name , pages_serialisable_page_tuples ) = serialisable_page_data
if name . startswith ( ' [USER] ' ) and len ( name ) > 6 :
name = name [ 6 : ]
pages_serialisable_page_tuples = [ clean_tuple ( pages_spt ) for pages_spt in pages_serialisable_page_tuples ]
return ( ' pages ' , ( name , pages_serialisable_page_tuples ) )
else :
return spt
new_serialisable_info = [ ]
serialisable_page_tuples = old_serialisable_info
for serialisable_page_tuple in serialisable_page_tuples :
serialisable_page_tuple = clean_tuple ( serialisable_page_tuple )
new_serialisable_info . append ( serialisable_page_tuple )
return ( 4 , new_serialisable_info )
2013-02-19 00:11:43 +00:00
2019-02-13 22:26:43 +00:00
def AddPageTuple ( self , page ) :
2017-08-16 21:58:06 +00:00
page_tuple = self . _GetPageTuple ( page )
2013-11-27 18:27:11 +00:00
2019-02-13 22:26:43 +00:00
self . _page_tuples . append ( page_tuple )
2013-11-27 18:27:11 +00:00
2019-02-13 22:26:43 +00:00
def GetPageTuples ( self ) :
2013-02-19 00:11:43 +00:00
2019-02-13 22:26:43 +00:00
return self . _page_tuples
2013-02-19 00:11:43 +00:00
2015-06-24 22:10:14 +00:00
HydrusSerialisable . SERIALISABLE_TYPES_TO_OBJECT_TYPES [ HydrusSerialisable . SERIALISABLE_TYPE_GUI_SESSION ] = GUISession