hydrus/include/ClientGUIPopupMessages.py

1316 lines
39 KiB
Python
Raw Normal View History

2019-01-09 22:59:03 +00:00
from . import ClientConstants as CC
from . import ClientData
from . import ClientGUICommon
from . import ClientGUIControls
from . import ClientGUIDialogs
2019-07-24 21:39:02 +00:00
from . import ClientGUIDialogsQuick
2019-06-26 21:27:18 +00:00
from . import ClientGUIFunctions
2019-01-09 22:59:03 +00:00
from . import ClientGUIScrolledPanels
from . import ClientGUITopLevelWindows
from . import ClientThreading
from . import HydrusConstants as HC
from . import HydrusData
from . import HydrusExceptions
from . import HydrusGlobals as HG
2017-07-27 00:47:13 +00:00
import os
import sys
import traceback
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
from . import QtPorting as QP
from . import QtPorting as QP
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
class PopupWindow( QW.QFrame ):
2017-07-27 00:47:13 +00:00
2019-06-26 21:27:18 +00:00
def __init__( self, parent, manager ):
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
QW.QFrame.__init__( self, parent )
self.setFrameStyle( QW.QFrame.Box | QW.QFrame.Plain )
2017-07-27 00:47:13 +00:00
2019-06-26 21:27:18 +00:00
self._manager = manager
2019-11-14 03:56:30 +00:00
self._widget_event_filter = QP.WidgetEventFilter( self )
self._widget_event_filter.EVT_RIGHT_DOWN( self.EventDismiss )
2017-07-27 00:47:13 +00:00
def TryToDismiss( self ):
2019-06-26 21:27:18 +00:00
self._manager.Dismiss( self )
2017-07-27 00:47:13 +00:00
def EventDismiss( self, event ):
self.TryToDismiss()
class PopupMessage( PopupWindow ):
TEXT_CUTOFF = 1024
2019-06-26 21:27:18 +00:00
def __init__( self, parent, manager, job_key ):
2017-07-27 00:47:13 +00:00
2019-06-26 21:27:18 +00:00
PopupWindow.__init__( self, parent, manager )
2017-07-27 00:47:13 +00:00
self._job_key = job_key
2019-11-14 03:56:30 +00:00
vbox = QP.VBoxLayout()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._title = ClientGUICommon.BetterStaticText( self )
self._title.setAlignment( QC.Qt.AlignHCenter | QC.Qt.AlignVCenter )
self.setSizePolicy( QW.QSizePolicy.MinimumExpanding, QW.QSizePolicy.Preferred )
2018-04-18 22:10:15 +00:00
popup_message_character_width = HG.client_controller.new_options.GetInteger( 'popup_message_character_width' )
2019-06-26 21:27:18 +00:00
wrap_width = ClientGUIFunctions.ConvertTextToPixelWidth( self._title, popup_message_character_width )
2018-04-18 22:10:15 +00:00
2018-06-20 20:20:22 +00:00
if HG.client_controller.new_options.GetBoolean( 'popup_message_force_min_width' ):
2019-11-14 03:56:30 +00:00
QP.SetMinClientSize( self, ( wrap_width, -1 ) )
2018-06-20 20:20:22 +00:00
2018-07-04 20:48:28 +00:00
self._title.SetWrapWidth( wrap_width )
2019-11-14 03:56:30 +00:00
self._title_ev = QP.WidgetEventFilter( self._title )
self._title_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._title.hide()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._text_1 = ClientGUICommon.BetterStaticText( self, ellipsize_end = True )
2018-07-04 20:48:28 +00:00
self._text_1.SetWrapWidth( wrap_width )
2019-11-14 03:56:30 +00:00
self._text_1_ev = QP.WidgetEventFilter( self._text_1 )
self._text_1_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._text_1.hide()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._gauge_1 = ClientGUICommon.Gauge( self )
self._gauge_1_ev = QP.WidgetEventFilter( self._gauge_1 )
self._gauge_1_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._gauge_1.hide()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._text_2 = ClientGUICommon.BetterStaticText( self, ellipsize_end = True )
2018-07-04 20:48:28 +00:00
self._text_2.SetWrapWidth( wrap_width )
2019-11-14 03:56:30 +00:00
self._text_2_ev = QP.WidgetEventFilter( self._text_2 )
self._text_2_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._text_2.hide()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._gauge_2 = ClientGUICommon.Gauge( self )
self._gauge_2_ev = QP.WidgetEventFilter( self._gauge_2 )
self._gauge_2_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._gauge_2.hide()
2017-07-27 00:47:13 +00:00
2018-06-06 21:27:02 +00:00
self._text_yes_no = ClientGUICommon.BetterStaticText( self )
2018-07-04 20:48:28 +00:00
self._text_yes_no.SetWrapWidth( wrap_width )
2019-11-14 03:56:30 +00:00
self._text_yes_no_ev = QP.WidgetEventFilter( self._text_yes_no )
self._text_yes_no_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._text_yes_no.hide()
2017-10-04 17:51:58 +00:00
self._yes = ClientGUICommon.BetterButton( self, 'yes', self._YesButton )
2019-11-14 03:56:30 +00:00
self._yes.hide()
2017-10-04 17:51:58 +00:00
self._no = ClientGUICommon.BetterButton( self, 'no', self._NoButton )
2019-11-14 03:56:30 +00:00
self._no.hide()
2017-10-04 17:51:58 +00:00
2017-08-02 21:32:54 +00:00
self._network_job_ctrl = ClientGUIControls.NetworkJobControl( self )
2019-11-14 03:56:30 +00:00
self._network_job_ctrl.hide()
2017-07-27 00:47:13 +00:00
self._copy_to_clipboard_button = ClientGUICommon.BetterButton( self, 'copy to clipboard', self.CopyToClipboard )
2019-11-14 03:56:30 +00:00
self._copy_to_clipboard_button_ev = QP.WidgetEventFilter( self._copy_to_clipboard_button )
self._copy_to_clipboard_button_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._copy_to_clipboard_button.hide()
2017-07-27 00:47:13 +00:00
self._show_files_button = ClientGUICommon.BetterButton( self, 'show files', self.ShowFiles )
2019-11-14 03:56:30 +00:00
self._show_files_button_ev = QP.WidgetEventFilter( self._show_files_button )
self._show_files_button_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._show_files_button.hide()
2017-07-27 00:47:13 +00:00
self._show_tb_button = ClientGUICommon.BetterButton( self, 'show traceback', self.ShowTB )
2019-11-14 03:56:30 +00:00
self._show_tb_button_ev = QP.WidgetEventFilter( self._show_tb_button )
self._show_tb_button_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._show_tb_button.hide()
2017-07-27 00:47:13 +00:00
2018-06-06 21:27:02 +00:00
self._tb_text = ClientGUICommon.BetterStaticText( self )
2018-07-04 20:48:28 +00:00
self._tb_text.SetWrapWidth( wrap_width )
2019-11-14 03:56:30 +00:00
self._tb_text_ev = QP.WidgetEventFilter( self._tb_text )
self._tb_text_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._tb_text.hide()
2017-07-27 00:47:13 +00:00
self._copy_tb_button = ClientGUICommon.BetterButton( self, 'copy traceback information', self.CopyTB )
2019-11-14 03:56:30 +00:00
self._copy_tb_button_ev = QP.WidgetEventFilter( self._copy_tb_button )
self._copy_tb_button_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._copy_tb_button.hide()
self._pause_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalPixmaps.pause, self.PausePlay )
self._pause_button_ev = QP.WidgetEventFilter( self._pause_button )
self._pause_button_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._pause_button.hide()
self._cancel_button = ClientGUICommon.BetterBitmapButton( self, CC.GlobalPixmaps.stop, self.Cancel )
self._cancel_button_ev = QP.WidgetEventFilter( self._cancel_button )
self._cancel_button_ev.EVT_RIGHT_DOWN( self.EventDismiss )
self._cancel_button.hide()
hbox = QP.HBoxLayout()
QP.AddToLayout( hbox, self._pause_button, CC.FLAGS_VCENTER )
QP.AddToLayout( hbox, self._cancel_button, CC.FLAGS_VCENTER )
yes_no_hbox = QP.HBoxLayout()
QP.AddToLayout( yes_no_hbox, self._yes, CC.FLAGS_VCENTER )
QP.AddToLayout( yes_no_hbox, self._no, CC.FLAGS_VCENTER )
QP.AddToLayout( vbox, self._title, alignment = QC.Qt.AlignHCenter )
QP.AddToLayout( vbox, self._text_1 )
QP.AddToLayout( vbox, self._gauge_1 )
QP.AddToLayout( vbox, self._text_2 )
QP.AddToLayout( vbox, self._gauge_2 )
QP.AddToLayout( vbox, self._text_yes_no )
QP.AddToLayout( vbox, yes_no_hbox )
QP.AddToLayout( vbox, self._network_job_ctrl )
QP.AddToLayout( vbox, self._copy_to_clipboard_button )
QP.AddToLayout( vbox, self._show_files_button )
QP.AddToLayout( vbox, self._show_tb_button )
QP.AddToLayout( vbox, self._tb_text )
QP.AddToLayout( vbox, self._copy_tb_button )
QP.AddToLayout( vbox, hbox, CC.FLAGS_BUTTON_SIZER )
self.setLayout( vbox )
2017-07-27 00:47:13 +00:00
2017-10-04 17:51:58 +00:00
def _NoButton( self ):
self._job_key.SetVariable( 'popup_yes_no_answer', False )
2017-10-11 17:38:14 +00:00
self._job_key.Delete()
2019-11-14 03:56:30 +00:00
self._yes.hide()
self._no.hide()
2017-10-11 17:38:14 +00:00
2017-10-04 17:51:58 +00:00
2017-07-27 00:47:13 +00:00
def _ProcessText( self, text ):
2019-01-09 22:59:03 +00:00
text = str( text )
2017-07-27 00:47:13 +00:00
if len( text ) > self.TEXT_CUTOFF:
new_text = 'The text is too long to display here. Here is the start of it (the rest is printed to the log):'
new_text += os.linesep * 2
new_text += text[:self.TEXT_CUTOFF]
text = new_text
return text
2017-10-04 17:51:58 +00:00
def _YesButton( self ):
self._job_key.SetVariable( 'popup_yes_no_answer', True )
2017-10-11 17:38:14 +00:00
self._job_key.Delete()
2019-11-14 03:56:30 +00:00
self._yes.hide()
self._no.hide()
2017-10-11 17:38:14 +00:00
2017-10-04 17:51:58 +00:00
2017-07-27 00:47:13 +00:00
def Cancel( self ):
self._job_key.Cancel()
2019-11-14 03:56:30 +00:00
self._pause_button.setEnabled( False )
self._cancel_button.setEnabled( False )
2017-07-27 00:47:13 +00:00
def CopyTB( self ):
HG.client_controller.pub( 'clipboard', 'text', self._job_key.ToString() )
def CopyToClipboard( self ):
result = self._job_key.GetIfHasVariable( 'popup_clipboard' )
if result is not None:
( title, text ) = result
HG.client_controller.pub( 'clipboard', 'text', text )
def PausePlay( self ):
self._job_key.PausePlay()
if self._job_key.IsPaused():
2019-11-14 03:56:30 +00:00
ClientGUIFunctions.SetBitmapButtonBitmap( self._pause_button, CC.GlobalPixmaps.play )
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
ClientGUIFunctions.SetBitmapButtonBitmap( self._pause_button, CC.GlobalPixmaps.pause )
2017-07-27 00:47:13 +00:00
def ShowFiles( self ):
result = self._job_key.GetIfHasVariable( 'popup_files' )
if result is not None:
2017-08-02 21:32:54 +00:00
( popup_files, popup_files_name ) = result
2017-07-27 00:47:13 +00:00
2017-08-02 21:32:54 +00:00
HG.client_controller.pub( 'new_page_query', CC.LOCAL_FILE_SERVICE_KEY, initial_hashes = popup_files, page_name = popup_files_name )
2017-07-27 00:47:13 +00:00
def ShowTB( self ):
2019-11-14 03:56:30 +00:00
if self._tb_text.isVisible():
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._show_tb_button.setText( 'show traceback' )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._tb_text.hide()
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._show_tb_button.setText( 'hide traceback' )
2017-07-27 00:47:13 +00:00
2018-07-04 20:48:28 +00:00
popup_message_character_width = HG.client_controller.new_options.GetInteger( 'popup_message_character_width' )
2019-06-26 21:27:18 +00:00
wrap_width = ClientGUIFunctions.ConvertTextToPixelWidth( self._title, popup_message_character_width )
2018-07-04 20:48:28 +00:00
2019-11-14 03:56:30 +00:00
self._tb_text.show()
2017-07-27 00:47:13 +00:00
2019-06-26 21:27:18 +00:00
self._manager.MakeSureEverythingFits()
2017-07-27 00:47:13 +00:00
def GetJobKey( self ):
return self._job_key
def IsDeleted( self ):
return self._job_key.IsDeleted()
def TryToDismiss( self ):
if self._job_key.IsPausable() or self._job_key.IsCancellable():
return
else:
PopupWindow.TryToDismiss( self )
2018-08-15 20:40:30 +00:00
def UpdateMessage( self ):
2017-07-27 00:47:13 +00:00
2018-07-04 20:48:28 +00:00
popup_message_character_width = HG.client_controller.new_options.GetInteger( 'popup_message_character_width' )
2019-06-26 21:27:18 +00:00
wrap_width = ClientGUIFunctions.ConvertTextToPixelWidth( self._title, popup_message_character_width )
2018-07-04 20:48:28 +00:00
2017-07-27 00:47:13 +00:00
paused = self._job_key.IsPaused()
title = self._job_key.GetIfHasVariable( 'popup_title' )
if title is not None:
2019-11-14 03:56:30 +00:00
self._title.show()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._title.setText( title )
2018-07-04 20:48:28 +00:00
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._title.hide()
2017-07-27 00:47:13 +00:00
popup_text_1 = self._job_key.GetIfHasVariable( 'popup_text_1' )
if popup_text_1 is not None or paused:
if paused:
text = 'paused'
else:
text = popup_text_1
2019-11-14 03:56:30 +00:00
self._text_1.show()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._text_1.setText( text )
2018-07-04 20:48:28 +00:00
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._text_1.hide()
2017-07-27 00:47:13 +00:00
popup_gauge_1 = self._job_key.GetIfHasVariable( 'popup_gauge_1' )
if popup_gauge_1 is not None and not paused:
( gauge_value, gauge_range ) = popup_gauge_1
self._gauge_1.SetRange( gauge_range )
self._gauge_1.SetValue( gauge_value )
2019-11-14 03:56:30 +00:00
self._gauge_1.show()
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._gauge_1.hide()
2017-07-27 00:47:13 +00:00
popup_text_2 = self._job_key.GetIfHasVariable( 'popup_text_2' )
if popup_text_2 is not None and not paused:
text = popup_text_2
2019-11-14 03:56:30 +00:00
self._text_2.setText( self._ProcessText( text ) )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._text_2.show()
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._text_2.hide()
2017-07-27 00:47:13 +00:00
popup_gauge_2 = self._job_key.GetIfHasVariable( 'popup_gauge_2' )
if popup_gauge_2 is not None and not paused:
( gauge_value, gauge_range ) = popup_gauge_2
self._gauge_2.SetRange( gauge_range )
self._gauge_2.SetValue( gauge_value )
2019-11-14 03:56:30 +00:00
self._gauge_2.show()
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._gauge_2.hide()
2017-07-27 00:47:13 +00:00
2017-10-04 17:51:58 +00:00
popup_yes_no_question = self._job_key.GetIfHasVariable( 'popup_yes_no_question' )
if popup_yes_no_question is not None and not paused:
text = popup_yes_no_question
2019-11-14 03:56:30 +00:00
self._text_yes_no.setText( self._ProcessText(text) )
2017-10-04 17:51:58 +00:00
2019-11-14 03:56:30 +00:00
self._text_yes_no.show()
2018-07-04 20:48:28 +00:00
2019-11-14 03:56:30 +00:00
self._yes.show()
self._no.show()
2017-10-04 17:51:58 +00:00
else:
2019-11-14 03:56:30 +00:00
self._text_yes_no.hide()
self._yes.hide()
self._no.hide()
2017-10-04 17:51:58 +00:00
2018-08-15 20:40:30 +00:00
if self._job_key.HasVariable( 'popup_network_job' ):
# this can be validly None, which confuses the getifhas result
popup_network_job = self._job_key.GetIfHasVariable( 'popup_network_job' )
2017-07-27 00:47:13 +00:00
2017-08-02 21:32:54 +00:00
self._network_job_ctrl.SetNetworkJob( popup_network_job )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._network_job_ctrl.show()
2017-07-27 00:47:13 +00:00
else:
2017-08-02 21:32:54 +00:00
self._network_job_ctrl.ClearNetworkJob()
2019-11-14 03:56:30 +00:00
self._network_job_ctrl.hide()
2017-07-27 00:47:13 +00:00
popup_clipboard = self._job_key.GetIfHasVariable( 'popup_clipboard' )
if popup_clipboard is not None:
( title, text ) = popup_clipboard
2019-11-14 03:56:30 +00:00
if self._copy_to_clipboard_button.text() != title:
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._copy_to_clipboard_button.setText( title )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._copy_to_clipboard_button.show()
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._copy_to_clipboard_button.hide()
2017-07-27 00:47:13 +00:00
2017-08-02 21:32:54 +00:00
result = self._job_key.GetIfHasVariable( 'popup_files' )
2017-07-27 00:47:13 +00:00
2017-08-02 21:32:54 +00:00
if result is not None:
( popup_files, popup_files_name ) = result
2017-07-27 00:47:13 +00:00
hashes = popup_files
2018-07-04 20:48:28 +00:00
text = popup_files_name + ' - show ' + HydrusData.ToHumanInt( len( hashes ) ) + ' files'
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
if self._show_files_button.text() != text:
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._show_files_button.setText( text )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._show_files_button.show()
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._show_files_button.hide()
2017-07-27 00:47:13 +00:00
popup_traceback = self._job_key.GetIfHasVariable( 'popup_traceback' )
if popup_traceback is not None:
2019-11-14 03:56:30 +00:00
self._copy_tb_button.show()
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._copy_tb_button.hide()
2017-07-27 00:47:13 +00:00
if popup_traceback is not None:
text = popup_traceback
2019-11-14 03:56:30 +00:00
self._tb_text.setText( self._ProcessText(text) )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._show_tb_button.show()
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._show_tb_button.hide()
self._tb_text.hide()
2017-07-27 00:47:13 +00:00
if self._job_key.IsPausable():
2019-11-14 03:56:30 +00:00
self._pause_button.show()
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._pause_button.hide()
2017-07-27 00:47:13 +00:00
if self._job_key.IsCancellable():
2019-11-14 03:56:30 +00:00
self._cancel_button.show()
2017-07-27 00:47:13 +00:00
else:
2019-11-14 03:56:30 +00:00
self._cancel_button.hide()
# Dirty hack to reduce unnecessary resizing
if self.minimumWidth() < self.sizeHint().width():
self.setMinimumWidth( self.sizeHint().width() )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
class PopupMessageManager( QW.QWidget ):
2017-07-27 00:47:13 +00:00
def __init__( self, parent ):
2019-11-14 03:56:30 +00:00
QW.QWidget.__init__( self, parent )
self.setWindowFlags( QC.Qt.Tool | QC.Qt.FramelessWindowHint )
self.setSizePolicy( QW.QSizePolicy.MinimumExpanding, QW.QSizePolicy.Preferred )
self.setAttribute( QC.Qt.WA_ShowWithoutActivating )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
QP.SetBackgroundColour( self, QP.GetSystemColour( QG.QPalette.Button ) )
2017-07-27 00:47:13 +00:00
2018-08-08 20:29:54 +00:00
self._last_best_size_i_fit_on = ( 0, 0 )
2017-07-27 00:47:13 +00:00
self._max_messages_to_display = 10
2019-11-14 03:56:30 +00:00
vbox = QP.VBoxLayout()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._message_panel = QW.QWidget( self )
2019-06-26 21:27:18 +00:00
2019-11-14 03:56:30 +00:00
self._message_vbox = QP.VBoxLayout( margin = 0 )
vbox.setSizeConstraint( QW.QLayout.SetFixedSize )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._message_panel.setLayout( self._message_vbox )
self._message_panel.setSizePolicy( QW.QSizePolicy.MinimumExpanding, QW.QSizePolicy.Preferred )
2019-06-26 21:27:18 +00:00
self._summary_bar = PopupMessageSummaryBar( self, self )
2019-11-14 03:56:30 +00:00
self._summary_bar.setSizePolicy( QW.QSizePolicy.MinimumExpanding, QW.QSizePolicy.Preferred )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( vbox, self._message_panel )
QP.AddToLayout( vbox, self._summary_bar )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( vbox )
2017-07-27 00:47:13 +00:00
self._pending_job_keys = []
2019-11-14 03:56:30 +00:00
self._gui_event_filter = QP.WidgetEventFilter( parent )
self._gui_event_filter.EVT_SIZE( self.EventParentMovedOrResized )
self._gui_event_filter.EVT_MOVE( self.EventParentMovedOrResized )
2017-07-27 00:47:13 +00:00
HG.client_controller.sub( self, 'AddMessage', 'message' )
self._old_excepthook = sys.excepthook
self._old_show_exception = HydrusData.ShowException
sys.excepthook = ClientData.CatchExceptionClient
HydrusData.ShowException = ClientData.ShowExceptionClient
HydrusData.ShowText = ClientData.ShowTextClient
job_key = ClientThreading.JobKey()
2019-01-09 22:59:03 +00:00
job_key.SetVariable( 'popup_text_1', 'initialising popup message manager\u2026' )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._update_job = HG.client_controller.CallRepeatingQtSafe(self, 0.25, 0.5, self.REPEATINGUpdate)
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
HG.client_controller.CallLaterQtSafe(self, 0.5, self.AddMessage, job_key)
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
HG.client_controller.CallLaterQtSafe(self, 1.0, job_key.Delete)
2017-07-27 00:47:13 +00:00
def _CheckPending( self ):
self._pending_job_keys = [ job_key for job_key in self._pending_job_keys if not job_key.IsDeleted() ]
2019-11-14 03:56:30 +00:00
while len( self._pending_job_keys ) > 0 and self._message_vbox.count() < self._max_messages_to_display:
2017-07-27 00:47:13 +00:00
job_key = self._pending_job_keys.pop( 0 )
2019-06-26 21:27:18 +00:00
window = PopupMessage( self._message_panel, self, job_key )
2017-07-27 00:47:13 +00:00
2018-08-15 20:40:30 +00:00
window.UpdateMessage()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( self._message_vbox, window )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
total_messages = len( self._pending_job_keys ) + self._message_vbox.count()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self._summary_bar.SetNumMessages( total_messages )
2018-05-09 20:23:00 +00:00
2018-05-16 20:09:50 +00:00
if self._NeedsSizeOrShow():
2017-07-27 00:47:13 +00:00
self._SizeAndPositionAndShow()
def _DisplayingError( self ):
2019-11-14 03:56:30 +00:00
for i in range( self._message_vbox.count() ):
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
sizer_item = self._message_vbox.itemAt( i )
message_window = sizer_item.widget()
if not message_window: continue
2017-07-27 00:47:13 +00:00
job_key = message_window.GetJobKey()
if job_key.HasVariable( 'popup_traceback' ):
return True
return False
2018-05-09 20:23:00 +00:00
def _DoDebugHide( self ):
2019-11-14 03:56:30 +00:00
if not QP.isValid( self ): return
2018-05-09 20:23:00 +00:00
2019-11-14 03:56:30 +00:00
parent = self.parentWidget()
2018-05-09 20:23:00 +00:00
possibly_on_hidden_virtual_desktop = not ClientGUITopLevelWindows.MouseIsOnMyDisplay( parent )
2019-11-14 03:56:30 +00:00
going_to_bug_out_at_hide_or_show = possibly_on_hidden_virtual_desktop
2018-05-09 20:23:00 +00:00
new_options = HG.client_controller.new_options
2019-11-14 03:56:30 +00:00
if new_options.GetBoolean( 'hide_message_manager_on_gui_iconise' ) and not self._DisplayingError():
2018-05-09 20:23:00 +00:00
2019-11-14 03:56:30 +00:00
if parent.isMinimized():
2018-05-09 20:23:00 +00:00
2019-11-14 03:56:30 +00:00
self.hide()
2018-05-09 20:23:00 +00:00
return
2019-11-14 03:56:30 +00:00
current_focus_tlp = QW.QApplication.activeWindow()
2018-05-09 20:23:00 +00:00
main_gui_is_active = current_focus_tlp in ( self, parent )
2019-11-14 03:56:30 +00:00
if new_options.GetBoolean( 'hide_message_manager_on_gui_deactive' ) and not self._DisplayingError():
2018-05-09 20:23:00 +00:00
if not main_gui_is_active:
if not going_to_bug_out_at_hide_or_show:
2019-11-14 03:56:30 +00:00
self.hide()
2018-05-09 20:23:00 +00:00
2018-05-16 20:09:50 +00:00
def _NeedsSizeOrShow( self ):
2019-11-14 03:56:30 +00:00
num_messages_displayed = self._message_vbox.count()
2018-05-16 20:09:50 +00:00
there_is_stuff_to_display = num_messages_displayed > 0
2019-11-14 03:56:30 +00:00
is_shown = self.isVisible()
2018-05-16 20:09:50 +00:00
if there_is_stuff_to_display:
if not is_shown:
return True
2019-11-14 03:56:30 +00:00
best_size = self.sizeHint()
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
if best_size != self.size():
2018-05-16 20:09:50 +00:00
return True
else:
if is_shown:
return True
return False
2017-07-27 00:47:13 +00:00
def _SizeAndPositionAndShow( self ):
try:
2019-11-14 03:56:30 +00:00
parent = self.parentWidget()
2017-09-06 20:18:20 +00:00
possibly_on_hidden_virtual_desktop = not ClientGUITopLevelWindows.MouseIsOnMyDisplay( parent )
2019-11-14 03:56:30 +00:00
going_to_bug_out_at_hide_or_show = possibly_on_hidden_virtual_desktop
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
current_focus_tlp = QW.QApplication.activeWindow()
2017-07-27 00:47:13 +00:00
main_gui_is_active = current_focus_tlp in ( self, parent )
on_top_frame_is_active = False
if not main_gui_is_active:
2019-11-14 03:56:30 +00:00
c_f_tlp_is_child_frame_of_main_gui = current_focus_tlp is not None and current_focus_tlp.parentWidget() == parent
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
if c_f_tlp_is_child_frame_of_main_gui:
2017-07-27 00:47:13 +00:00
on_top_frame_is_active = True
2019-11-14 03:56:30 +00:00
num_messages_displayed = self._message_vbox.count()
2017-07-27 00:47:13 +00:00
there_is_stuff_to_display = num_messages_displayed > 0
if there_is_stuff_to_display:
2019-11-14 03:56:30 +00:00
( parent_width, parent_height ) = parent.size().toTuple()
2018-08-15 20:40:30 +00:00
2019-11-14 03:56:30 +00:00
( my_width, my_height ) = self.size().toTuple()
2018-08-15 20:40:30 +00:00
2019-11-14 03:56:30 +00:00
my_x = ( parent_width - my_width ) - 20
my_y = ( parent_height - my_height ) - 25
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
if parent.isVisible():
2017-07-27 00:47:13 +00:00
2019-06-26 21:27:18 +00:00
my_position = ClientGUIFunctions.ClientToScreen( parent, ( my_x, my_y ) )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
if my_position != self.pos():
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self.move( my_position )
2017-07-27 00:47:13 +00:00
# Unhiding tends to raise the main gui tlp, which is annoying if a media viewer window has focus
2019-11-14 03:56:30 +00:00
# Qt port note: the on_top_frame_is_active part was uncommented originally, but it IS annoying since it leads to flickering (e.g. open the options window with this uncommented to see it in action)
show_is_not_annoying = main_gui_is_active or self._DisplayingError() # or on_top_frame_is_active
2017-07-27 00:47:13 +00:00
ok_to_show = show_is_not_annoying and not going_to_bug_out_at_hide_or_show
if ok_to_show:
2019-11-14 03:56:30 +00:00
self.show()
2017-07-27 00:47:13 +00:00
else:
if not going_to_bug_out_at_hide_or_show:
2019-11-14 03:56:30 +00:00
self.hide()
2017-07-27 00:47:13 +00:00
except:
text = 'The popup message manager experienced a fatal error and will now stop working! Please restart the client as soon as possible! If this keeps happening, please email the details and your client.log to the hydrus developer.'
HydrusData.Print( text )
HydrusData.Print( traceback.format_exc() )
2019-11-14 03:56:30 +00:00
QW.QMessageBox.critical( HG.client_controller.gui, 'Error', text )
2017-07-27 00:47:13 +00:00
2018-02-14 21:47:18 +00:00
self._update_job.Cancel()
2017-07-27 00:47:13 +00:00
self.CleanBeforeDestroy()
2019-11-14 03:56:30 +00:00
self.deleteLater()
2017-07-27 00:47:13 +00:00
2018-02-14 21:47:18 +00:00
def _GetAllMessageJobKeys( self ):
job_keys = []
2019-11-14 03:56:30 +00:00
for i in range( self._message_vbox.count() ):
2018-02-14 21:47:18 +00:00
2019-11-14 03:56:30 +00:00
sizer_item = self._message_vbox.itemAt( i )
message_window = sizer_item.widget()
if not message_window: continue
2018-02-14 21:47:18 +00:00
job_key = message_window.GetJobKey()
job_keys.append( job_key )
job_keys.extend( self._pending_job_keys )
return job_keys
2018-05-09 20:23:00 +00:00
def _OKToAlterUI( self ):
2019-11-14 03:56:30 +00:00
if not QP.isValid( self ): return
2018-05-09 20:23:00 +00:00
2019-11-14 03:56:30 +00:00
main_gui = self.parentWidget()
2018-05-09 20:23:00 +00:00
2019-06-19 22:08:48 +00:00
# test both because when user uses a shortcut to send gui to a diff monitor, we can't chase it
# this may need a better test for virtual display dismissal
not_on_hidden_or_virtual_display = ClientGUITopLevelWindows.MouseIsOnMyDisplay( main_gui ) or ClientGUITopLevelWindows.MouseIsOnMyDisplay( self )
2018-05-09 20:23:00 +00:00
2019-11-14 03:56:30 +00:00
main_gui_up = not main_gui.isMinimized()
2018-05-09 20:23:00 +00:00
return not_on_hidden_or_virtual_display and main_gui_up
2018-02-14 21:47:18 +00:00
def _TryToMergeMessage( self, job_key ):
if not job_key.HasVariable( 'popup_files_mergable' ):
return False
result = job_key.GetIfHasVariable( 'popup_files' )
if result is not None:
( hashes, name ) = result
existing_job_keys = self._GetAllMessageJobKeys()
for existing_job_key in existing_job_keys:
if existing_job_key.HasVariable( 'popup_files_mergable' ):
result = existing_job_key.GetIfHasVariable( 'popup_files' )
if result is not None:
( existing_hashes, existing_name ) = result
if existing_name == name:
if isinstance( existing_hashes, list ):
existing_hashes.extend( hashes )
elif isinstance( existing_hashes, set ):
existing_hashes.update( hashes )
return True
return False
2017-07-27 00:47:13 +00:00
def _Update( self ):
if HG.view_shutdown:
2018-02-14 21:47:18 +00:00
self._update_job.Cancel()
self.CleanBeforeDestroy()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self.deleteLater()
2017-07-27 00:47:13 +00:00
return
2019-11-14 03:56:30 +00:00
for i in range( self._message_vbox.count() ):
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
sizer_item = self._message_vbox.itemAt( i )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
message_window = sizer_item.widget()
if message_window:
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
if message_window.IsDeleted():
message_window.TryToDismiss()
break
else:
message_window.UpdateMessage()
2017-07-27 00:47:13 +00:00
def AddMessage( self, job_key ):
try:
2018-02-14 21:47:18 +00:00
was_merged = self._TryToMergeMessage( job_key )
if was_merged:
return
2017-07-27 00:47:13 +00:00
self._pending_job_keys.append( job_key )
2018-05-09 20:23:00 +00:00
if self._OKToAlterUI():
2017-09-13 20:50:41 +00:00
self._CheckPending()
2017-07-27 00:47:13 +00:00
except:
HydrusData.Print( traceback.format_exc() )
def CleanBeforeDestroy( self ):
for job_key in self._pending_job_keys:
if job_key.IsCancellable():
job_key.Cancel()
2019-11-14 03:56:30 +00:00
for i in range( self._message_vbox.count() ):
message_window = self._message_vbox.itemAt( i ).widget()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
if not message_window: continue
2017-07-27 00:47:13 +00:00
job_key = message_window.GetJobKey()
if job_key.IsCancellable():
job_key.Cancel()
sys.excepthook = self._old_excepthook
HydrusData.ShowException = self._old_show_exception
def Dismiss( self, window ):
2019-11-14 03:56:30 +00:00
self._message_vbox.removeWidget( window )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
window.deleteLater()
2017-07-27 00:47:13 +00:00
2018-05-09 20:23:00 +00:00
if self._OKToAlterUI():
self._CheckPending()
2017-07-27 00:47:13 +00:00
def DismissAll( self ):
self._pending_job_keys = [ job_key for job_key in self._pending_job_keys if job_key.IsPausable() or job_key.IsCancellable() ]
2019-11-14 03:56:30 +00:00
items = []
for i in range( self._message_vbox.count() ):
items.append( self._message_vbox.itemAt( i ) )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
for item in items:
message_window = item.widget()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
if not message_window: continue
2017-07-27 00:47:13 +00:00
message_window.TryToDismiss()
self._CheckPending()
2019-06-26 21:27:18 +00:00
def ExpandCollapse( self ):
2019-11-14 03:56:30 +00:00
if self._message_panel.isVisible():
2019-06-26 21:27:18 +00:00
2019-11-14 03:56:30 +00:00
self._message_panel.setVisible( False )
2019-06-26 21:27:18 +00:00
else:
2019-11-14 03:56:30 +00:00
self._message_panel.show()
self.MakeSureEverythingFits()
def resizeEvent( self, event ):
if not self or not QP.isValid( self ): # funny runtime error caused this
return
if self._OKToAlterUI():
2019-06-26 21:27:18 +00:00
2019-11-14 03:56:30 +00:00
self._SizeAndPositionAndShow()
2019-06-26 21:27:18 +00:00
2019-11-14 03:56:30 +00:00
event.ignore()
2019-06-26 21:27:18 +00:00
2019-11-14 03:56:30 +00:00
def EventParentMovedOrResized( self, event ):
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
if not self or not QP.isValid( self ): # funny runtime error caused this
2019-05-22 22:35:06 +00:00
return
2018-05-09 20:23:00 +00:00
if self._OKToAlterUI():
self._SizeAndPositionAndShow()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
return True # was: event.ignore()
2017-07-27 00:47:13 +00:00
def MakeSureEverythingFits( self ):
2018-05-09 20:23:00 +00:00
if self._OKToAlterUI():
self._SizeAndPositionAndShow()
2017-07-27 00:47:13 +00:00
2018-02-14 21:47:18 +00:00
def REPEATINGUpdate( self ):
2017-07-27 00:47:13 +00:00
try:
2018-05-09 20:23:00 +00:00
self._DoDebugHide()
if self._OKToAlterUI():
2017-09-13 20:50:41 +00:00
self._Update()
self._CheckPending()
2017-07-27 00:47:13 +00:00
except:
2018-02-14 21:47:18 +00:00
self._update_job.Cancel()
2017-07-27 00:47:13 +00:00
raise
2019-11-14 03:56:30 +00:00
# This was originally a reviewpanel subclass which is a scroll area subclass, but having it in a scroll area didn't work out with dynamically updating size as the widget contents change.
class PopupMessageDialogPanel( QW.QWidget ):
2017-07-27 00:47:13 +00:00
def __init__( self, parent, job_key ):
2019-11-14 03:56:30 +00:00
QW.QWidget.__init__( self, parent )
2017-07-27 00:47:13 +00:00
2019-09-25 21:34:18 +00:00
self._yesno_open = False
2017-07-27 00:47:13 +00:00
self._job_key = job_key
2019-06-26 21:27:18 +00:00
self._message_window = PopupMessage( self, self, self._job_key )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
vbox = QP.VBoxLayout()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( vbox, self._message_window )
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( vbox )
2017-07-27 00:47:13 +00:00
2018-03-22 00:03:33 +00:00
self._windows_hidden = []
2018-01-17 22:52:10 +00:00
2018-03-22 00:03:33 +00:00
self._HideOtherWindows()
2018-01-17 22:52:10 +00:00
2017-07-27 00:47:13 +00:00
self._message_pubbed = False
2019-11-14 03:56:30 +00:00
self._update_job = HG.client_controller.CallRepeatingQtSafe(self, 0.25, 0.5, self.REPEATINGUpdate)
def CanCancel( self ):
return True
2018-01-03 22:37:30 +00:00
2019-11-14 03:56:30 +00:00
def CanOK( self ):
return True
def CleanBeforeDestroy( self ):
pass
2018-03-22 00:03:33 +00:00
def _HideOtherWindows( self ):
2018-01-17 22:52:10 +00:00
2019-11-14 03:56:30 +00:00
for tlw in QW.QApplication.topLevelWidgets():
2018-01-17 22:52:10 +00:00
if tlw == self:
continue
if not isinstance( tlw, ( ClientGUITopLevelWindows.Frame, ClientGUITopLevelWindows.NewDialog ) ):
continue
2019-11-14 03:56:30 +00:00
if ClientGUIFunctions.IsQtAncestor( self, tlw, through_tlws = True ):
2019-03-27 22:01:02 +00:00
continue
2019-01-09 22:59:03 +00:00
from . import ClientGUI
2018-01-17 22:52:10 +00:00
if isinstance( tlw, ClientGUI.FrameGUI ):
continue
2019-11-14 03:56:30 +00:00
if not tlw.isVisible() or tlw.isMinimized():
2018-01-17 22:52:10 +00:00
continue
2019-11-14 03:56:30 +00:00
tlw.hide()
2018-01-17 22:52:10 +00:00
2018-03-22 00:03:33 +00:00
self._windows_hidden.append( tlw )
2018-01-17 22:52:10 +00:00
2017-07-27 00:47:13 +00:00
def _ReleaseMessage( self ):
if not self._message_pubbed:
HG.client_controller.pub( 'message', self._job_key )
self._message_pubbed = True
2018-01-17 22:52:10 +00:00
self._RestoreOtherWindows()
def _RestoreOtherWindows( self ):
2018-03-22 00:03:33 +00:00
for tlw in self._windows_hidden:
2018-01-17 22:52:10 +00:00
2019-11-14 03:56:30 +00:00
tlw.show()
2018-01-17 22:52:10 +00:00
2018-03-22 00:03:33 +00:00
self._windows_hidden = []
2017-07-27 00:47:13 +00:00
def _Update( self ):
2018-08-15 20:40:30 +00:00
self._message_window.UpdateMessage()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
# Resize the window after updates
# The problem is that when the window is created, the initial size is too small because all widgets are empty before the first update,
# but after it updates it doesn't want to resize the window, rather it just adds scrollbars.
# This is a manual fix. Need to find a better solution...
self.layout().update()
self._message_window.adjustSize()
self.adjustSize()
self.window().adjustSize()
2017-07-27 00:47:13 +00:00
def Dismiss( self, window ):
return
def TryToClose( self ):
if self._job_key.IsDone():
self._ReleaseMessage()
else:
if self._job_key.IsCancellable():
2019-07-24 21:39:02 +00:00
text = 'Cancel/stop job?'
2019-09-25 21:34:18 +00:00
self._yesno_open = True
try:
result = ClientGUIDialogsQuick.GetYesNo( self, text )
finally:
self._yesno_open = False
2019-07-24 21:39:02 +00:00
2019-11-14 03:56:30 +00:00
if result == QW.QDialog.Accepted:
2017-07-27 00:47:13 +00:00
2019-07-24 21:39:02 +00:00
self._job_key.Cancel()
self._ReleaseMessage()
else:
raise HydrusExceptions.VetoException()
2017-07-27 00:47:13 +00:00
else:
2017-12-13 22:33:07 +00:00
raise HydrusExceptions.VetoException( 'Unfortunately, this job cannot be cancelled. If it really is taking too long, please kill the client through task manager.' )
2017-08-02 21:32:54 +00:00
2017-07-27 00:47:13 +00:00
2018-02-14 21:47:18 +00:00
def REPEATINGUpdate( self ):
2017-07-27 00:47:13 +00:00
try:
if self._job_key.IsDone():
2019-09-25 21:34:18 +00:00
if not self._yesno_open: # don't close while a child dialog open m8
2019-11-14 03:56:30 +00:00
parent = self.parentWidget()
2017-07-27 00:47:13 +00:00
2019-11-14 03:56:30 +00:00
if parent.isModal(): # event sometimes fires after modal done
2019-09-25 21:34:18 +00:00
parent.DoOK()
2017-07-27 00:47:13 +00:00
else:
self._Update()
except:
2018-02-14 21:47:18 +00:00
self._update_job.Cancel()
2017-07-27 00:47:13 +00:00
raise
2019-06-26 21:27:18 +00:00
class PopupMessageSummaryBar( PopupWindow ):
def __init__( self, parent, manager ):
PopupWindow.__init__( self, parent, manager )
2019-11-14 03:56:30 +00:00
hbox = QP.HBoxLayout()
2019-06-26 21:27:18 +00:00
self._text = ClientGUICommon.BetterStaticText( self )
self._expand_collapse = ClientGUICommon.BetterButton( self, '\u25bc', self.ExpandCollapse )
dismiss_all = ClientGUICommon.BetterButton( self, 'dismiss all', self._manager.DismissAll )
2019-11-14 03:56:30 +00:00
QP.AddToLayout( hbox, self._text, CC.FLAGS_VCENTER )
QP.AddToLayout( hbox, (20,20), CC.FLAGS_EXPAND_BOTH_WAYS )
QP.AddToLayout( hbox, dismiss_all, CC.FLAGS_VCENTER )
QP.AddToLayout( hbox, self._expand_collapse, CC.FLAGS_VCENTER )
2019-06-26 21:27:18 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( hbox )
2019-06-26 21:27:18 +00:00
def ExpandCollapse( self ):
self._manager.ExpandCollapse()
2019-11-14 03:56:30 +00:00
current_text = self._expand_collapse.text()
2019-06-26 21:27:18 +00:00
if current_text == '\u25bc':
new_text = '\u25b2'
else:
new_text = '\u25bc'
2019-11-14 03:56:30 +00:00
self._expand_collapse.setText( new_text )
2019-06-26 21:27:18 +00:00
2017-07-27 00:47:13 +00:00
2019-06-26 21:27:18 +00:00
def TryToDismiss( self ):
pass
def SetNumMessages( self, num_messages_pending ):
if num_messages_pending == 1:
2019-11-14 03:56:30 +00:00
self._text.setText( '1 message' )
2019-06-26 21:27:18 +00:00
else:
2019-11-14 03:56:30 +00:00
self._text.setText( HydrusData.ToHumanInt(num_messages_pending)+' messages' )
2019-06-26 21:27:18 +00:00