hydrus/hydrus/client/gui/widgets/ClientGUICommon.py

1793 lines
52 KiB
Python
Raw Normal View History

2013-02-19 00:11:43 +00:00
import os
2018-09-26 19:05:12 +00:00
import re
2020-05-13 19:03:16 +00:00
import typing
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
2020-07-29 20:52:44 +00:00
from hydrus.client import ClientApplicationCommand as CAC
2020-04-22 21:00:35 +00:00
from hydrus.client import ClientConstants as CC
from hydrus.client import ClientPaths
from hydrus.client.gui import ClientGUICore as CGC
from hydrus.client.gui import ClientGUIFunctions
from hydrus.client.gui import ClientGUIMenus
from hydrus.client.gui import ClientGUIShortcuts
from hydrus.client.gui import QtPorting as QP
2013-02-19 00:11:43 +00:00
2020-02-05 22:55:21 +00:00
CANVAS_MEDIA_VIEWER = 0
CANVAS_PREVIEW = 1
canvas_str_lookup = {}
canvas_str_lookup[ CANVAS_MEDIA_VIEWER ] = 'media viewer'
canvas_str_lookup[ CANVAS_PREVIEW ] = 'preview'
2020-07-29 20:52:44 +00:00
def AddGridboxStretchSpacer( layout: QW.QGridLayout ):
layout.addItem( QW.QSpacerItem( 10, 10, QW.QSizePolicy.Expanding, QW.QSizePolicy.Fixed ) )
2019-11-14 03:56:30 +00:00
def WrapInGrid( parent, rows, expand_text = False, add_stretch_at_end = True ):
2016-08-31 19:55:14 +00:00
2019-11-14 03:56:30 +00:00
gridbox = QP.GridLayout( cols = 2 )
2016-08-31 19:55:14 +00:00
if expand_text:
2019-11-14 03:56:30 +00:00
gridbox.setColumnStretch( 0, 1 )
2016-08-31 19:55:14 +00:00
text_flags = CC.FLAGS_EXPAND_BOTH_WAYS
2020-07-29 20:52:44 +00:00
control_flags = CC.FLAGS_CENTER_PERPENDICULAR
sizer_flags = CC.FLAGS_CENTER_PERPENDICULAR
2016-08-31 19:55:14 +00:00
else:
2019-11-14 03:56:30 +00:00
gridbox.setColumnStretch( 1, 1 )
2016-08-31 19:55:14 +00:00
2020-07-29 20:52:44 +00:00
text_flags = CC.FLAGS_ON_LEFT
2019-11-14 03:56:30 +00:00
control_flags = CC.FLAGS_NONE
2016-09-07 20:01:05 +00:00
sizer_flags = CC.FLAGS_EXPAND_SIZER_BOTH_WAYS
2016-08-31 19:55:14 +00:00
for ( text, control ) in rows:
2020-02-12 22:50:37 +00:00
if isinstance( text, BetterStaticText ):
st = text
else:
st = BetterStaticText( parent, text )
2018-04-18 22:10:15 +00:00
2019-11-14 03:56:30 +00:00
if isinstance( control, QW.QLayout ):
2016-09-07 20:01:05 +00:00
cflags = sizer_flags
else:
cflags = control_flags
2019-11-14 03:56:30 +00:00
if control.toolTip() != '':
2018-04-18 22:10:15 +00:00
2019-11-14 03:56:30 +00:00
st.setToolTip( control.toolTip() )
2018-04-18 22:10:15 +00:00
2017-04-19 20:58:30 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( gridbox, st, text_flags )
QP.AddToLayout( gridbox, control, cflags )
2016-08-31 19:55:14 +00:00
2020-03-11 21:52:11 +00:00
if add_stretch_at_end:
gridbox.setRowStretch( gridbox.rowCount(), 1 )
2016-08-31 19:55:14 +00:00
return gridbox
2018-02-28 22:30:36 +00:00
def WrapInText( control, parent, text, colour = None ):
2016-08-17 20:07:22 +00:00
2019-11-14 03:56:30 +00:00
hbox = QP.HBoxLayout()
2016-08-17 20:07:22 +00:00
2017-04-19 20:58:30 +00:00
st = BetterStaticText( parent, text )
2018-02-28 22:30:36 +00:00
if colour is not None:
2019-11-14 03:56:30 +00:00
QP.SetForegroundColour( st, colour )
2018-02-28 22:30:36 +00:00
2020-07-29 20:52:44 +00:00
QP.AddToLayout( hbox, st, CC.FLAGS_CENTER_PERPENDICULAR )
2019-11-14 03:56:30 +00:00
QP.AddToLayout( hbox, control, CC.FLAGS_EXPAND_BOTH_WAYS )
2016-08-17 20:07:22 +00:00
return hbox
2019-06-05 19:42:39 +00:00
class ShortcutAwareToolTipMixin( object ):
def __init__( self, tt_callable ):
self._tt_callable = tt_callable
self._tt = ''
self._simple_shortcut_command = None
2020-03-25 21:15:57 +00:00
if ClientGUIShortcuts.shortcuts_manager_initialised():
ClientGUIShortcuts.shortcuts_manager().shortcutsChanged.connect( self.RefreshToolTip )
2019-06-05 19:42:39 +00:00
def _RefreshToolTip( self ):
tt = self._tt
if self._simple_shortcut_command is not None:
tt += os.linesep * 2
tt += '----------'
2020-03-25 21:15:57 +00:00
names_to_shortcuts = ClientGUIShortcuts.shortcuts_manager().GetNamesToShortcuts( self._simple_shortcut_command )
2019-06-05 19:42:39 +00:00
if len( names_to_shortcuts ) > 0:
2020-05-13 19:03:16 +00:00
names = sorted( names_to_shortcuts.keys() )
2019-06-05 19:42:39 +00:00
for name in names:
shortcuts = names_to_shortcuts[ name ]
2020-05-13 19:03:16 +00:00
shortcut_strings = sorted( ( shortcut.ToString() for shortcut in shortcuts ) )
2019-06-05 19:42:39 +00:00
if name in ClientGUIShortcuts.shortcut_names_to_pretty_names:
pretty_name = ClientGUIShortcuts.shortcut_names_to_pretty_names[ name ]
else:
pretty_name = name
2019-06-05 19:42:39 +00:00
tt += os.linesep * 2
tt += ', '.join( shortcut_strings )
tt += os.linesep
tt += '({}->{})'.format( pretty_name, CAC.simple_enum_to_str_lookup[ self._simple_shortcut_command ] )
2019-06-05 19:42:39 +00:00
else:
tt += os.linesep * 2
tt += 'no shortcuts set'
tt += os.linesep
tt += '({})'.format( CAC.simple_enum_to_str_lookup[ self._simple_shortcut_command ] )
2019-06-05 19:42:39 +00:00
self._tt_callable( tt )
2020-03-25 21:15:57 +00:00
def RefreshToolTip( self ):
2019-06-05 19:42:39 +00:00
2020-03-25 21:15:57 +00:00
if ClientGUIShortcuts.shortcuts_manager_initialised():
self._RefreshToolTip()
2019-06-05 19:42:39 +00:00
def SetToolTipWithShortcuts( self, tt: str, simple_shortcut_command: int ):
2019-06-05 19:42:39 +00:00
self._tt = tt
self._simple_shortcut_command = simple_shortcut_command
self._RefreshToolTip()
2019-11-14 03:56:30 +00:00
class BetterBitmapButton( ShortcutAwareToolTipMixin, QW.QPushButton ):
2017-01-18 22:52:39 +00:00
2017-01-25 22:56:55 +00:00
def __init__( self, parent, bitmap, func, *args, **kwargs ):
2017-01-18 22:52:39 +00:00
2019-11-14 03:56:30 +00:00
QW.QPushButton.__init__( self, parent )
self.setIcon( QG.QIcon( bitmap ) )
self.setIconSize( bitmap.size() )
self.setSizePolicy( QW.QSizePolicy.Maximum, QW.QSizePolicy.Maximum )
ShortcutAwareToolTipMixin.__init__( self, self.setToolTip )
2017-01-18 22:52:39 +00:00
2017-01-25 22:56:55 +00:00
self._func = func
2017-01-18 22:52:39 +00:00
self._args = args
self._kwargs = kwargs
2019-06-05 19:42:39 +00:00
2019-11-14 03:56:30 +00:00
self.clicked.connect( self.EventButton )
2017-01-18 22:52:39 +00:00
2019-11-14 03:56:30 +00:00
def EventButton( self ):
2017-01-18 22:52:39 +00:00
2017-01-25 22:56:55 +00:00
self._func( *self._args, **self._kwargs )
2017-01-18 22:52:39 +00:00
2019-11-14 03:56:30 +00:00
class BetterButton( ShortcutAwareToolTipMixin, QW.QPushButton ):
2016-10-19 20:02:56 +00:00
2017-01-25 22:56:55 +00:00
def __init__( self, parent, label, func, *args, **kwargs ):
2016-10-19 20:02:56 +00:00
2019-11-14 03:56:30 +00:00
QW.QPushButton.__init__( self, parent )
ShortcutAwareToolTipMixin.__init__( self, self.setToolTip )
2017-04-19 20:58:30 +00:00
2019-11-14 03:56:30 +00:00
self.setText( label )
2016-10-19 20:02:56 +00:00
2017-01-25 22:56:55 +00:00
self._func = func
2016-12-07 22:12:52 +00:00
self._args = args
self._kwargs = kwargs
2021-04-07 21:26:45 +00:00
self._yes_no_text = None
2019-11-14 03:56:30 +00:00
self.clicked.connect( self.EventButton )
2016-10-19 20:02:56 +00:00
2019-11-14 03:56:30 +00:00
def EventButton( self ):
2016-10-19 20:02:56 +00:00
2021-04-07 21:26:45 +00:00
if self._yes_no_text is not None:
from hydrus.client.gui import ClientGUIDialogsQuick
result = ClientGUIDialogsQuick.GetYesNo( self, message = self._yes_no_text )
if result != QW.QDialog.Accepted:
return
2017-01-25 22:56:55 +00:00
self._func( *self._args, **self._kwargs )
2016-10-19 20:02:56 +00:00
2021-04-07 21:26:45 +00:00
def SetYesNoText( self, text: str ):
# this should probably be setyesnotextfactory, but WHATEVER for now
self._yes_no_text = text
2019-11-14 03:56:30 +00:00
def setText( self, label ):
2017-05-31 21:50:53 +00:00
2020-04-22 21:00:35 +00:00
button_label = ClientGUIFunctions.EscapeMnemonics( label )
2017-05-31 21:50:53 +00:00
2019-11-14 03:56:30 +00:00
QW.QPushButton.setText( self, button_label )
2017-05-31 21:50:53 +00:00
2019-11-14 03:56:30 +00:00
class BetterChoice( QW.QComboBox ):
def __init__( self, *args, **kwargs ):
2019-02-06 22:41:35 +00:00
2019-11-14 03:56:30 +00:00
QW.QComboBox.__init__( self, *args, **kwargs )
self.setMaxVisibleItems( 32 )
2019-02-06 22:41:35 +00:00
2019-11-14 03:56:30 +00:00
def addItem( self, display_string, client_data ):
2017-10-11 17:38:14 +00:00
2019-11-14 03:56:30 +00:00
QW.QComboBox.addItem( self, display_string, client_data )
2017-10-11 17:38:14 +00:00
2019-11-14 03:56:30 +00:00
if self.count() == 1:
2017-10-11 17:38:14 +00:00
2019-11-14 03:56:30 +00:00
self.setCurrentIndex( 0 )
2017-10-11 17:38:14 +00:00
2019-07-24 21:39:02 +00:00
def GetValue( self ):
2016-10-19 20:02:56 +00:00
2019-11-14 03:56:30 +00:00
selection = self.currentIndex()
2016-10-19 20:02:56 +00:00
2019-11-14 03:56:30 +00:00
if selection != -1:
2019-05-08 21:06:42 +00:00
2020-03-18 21:35:57 +00:00
return self.itemData( selection, QC.Qt.UserRole )
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
elif self.count() > 0:
2019-05-08 21:06:42 +00:00
2020-03-18 21:35:57 +00:00
return self.itemData( 0, QC.Qt.UserRole )
2019-05-08 21:06:42 +00:00
else:
return None
2016-10-19 20:02:56 +00:00
2019-07-24 21:39:02 +00:00
def SetValue( self, data ):
2016-10-19 20:02:56 +00:00
2019-11-14 03:56:30 +00:00
for i in range( self.count() ):
2016-10-19 20:02:56 +00:00
2020-03-18 21:35:57 +00:00
if data == self.itemData( i, QC.Qt.UserRole ):
2016-10-19 20:02:56 +00:00
2019-11-14 03:56:30 +00:00
self.setCurrentIndex( i )
2016-10-19 20:02:56 +00:00
return
2019-11-14 03:56:30 +00:00
if self.count() > 0:
2016-11-09 23:13:22 +00:00
2019-11-14 03:56:30 +00:00
self.setCurrentIndex( 0 )
2016-11-09 23:13:22 +00:00
2016-10-19 20:02:56 +00:00
2019-11-14 03:56:30 +00:00
class BetterColourControl( QP.ColourPickerCtrl ):
2018-09-26 19:05:12 +00:00
def __init__( self, *args, **kwargs ):
2019-11-14 03:56:30 +00:00
QP.ColourPickerCtrl.__init__( self, *args, **kwargs )
2018-09-26 19:05:12 +00:00
2019-11-14 03:56:30 +00:00
self._widget_event_filter = QP.WidgetEventFilter( self )
2018-09-26 19:05:12 +00:00
def _ImportHexFromClipboard( self ):
try:
import_string = HG.client_controller.GetClipboardText()
except Exception as e:
2019-11-14 03:56:30 +00:00
QW.QMessageBox.critical( self, 'Error', str(e) )
2018-09-26 19:05:12 +00:00
return
if import_string.startswith( '#' ):
import_string = import_string[1:]
import_string = '#' + re.sub( '[^0-9a-fA-F]', '', import_string )
if len( import_string ) != 7:
2019-11-14 03:56:30 +00:00
QW.QMessageBox.critical( self, 'Error', 'That did not appear to be a hex string!' )
2018-09-26 19:05:12 +00:00
return
try:
2019-11-14 03:56:30 +00:00
colour = QG.QColor( import_string )
2018-09-26 19:05:12 +00:00
except Exception as e:
2019-11-14 03:56:30 +00:00
QW.QMessageBox.critical( self, 'Error', str(e) )
2018-09-26 19:05:12 +00:00
HydrusData.ShowException( e )
return
self.SetColour( colour )
2020-02-12 22:50:37 +00:00
def contextMenuEvent( self, event ):
if event.reason() == QG.QContextMenuEvent.Keyboard:
self.ShowMenu()
2019-12-11 23:18:37 +00:00
def mouseReleaseEvent( self, event ):
if event.button() != QC.Qt.RightButton:
QP.ColourPickerCtrl.mouseReleaseEvent( self, event )
return
2018-09-26 19:05:12 +00:00
2020-02-12 22:50:37 +00:00
self.ShowMenu()
def ShowMenu( self ):
2019-11-14 03:56:30 +00:00
menu = QW.QMenu()
2018-09-26 19:05:12 +00:00
2019-11-14 03:56:30 +00:00
hex_string = self.GetColour().name( QG.QColor.HexRgb )
2018-09-26 19:05:12 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus.AppendMenuItem( menu, 'copy ' + hex_string + ' to the clipboard', 'Copy the current colour to the clipboard.', HG.client_controller.pub, 'clipboard', 'text', hex_string )
ClientGUIMenus.AppendMenuItem( menu, 'import a hex colour from the clipboard', 'Look at the clipboard for a colour in the format #FF0000, and set the colour.', self._ImportHexFromClipboard )
2018-09-26 19:05:12 +00:00
2020-03-04 22:12:53 +00:00
CGC.core().PopupMenu( self, menu )
2018-09-26 19:05:12 +00:00
2019-11-14 03:56:30 +00:00
class BetterNotebook( QW.QTabWidget ):
2018-05-16 20:09:50 +00:00
def _ShiftSelection( self, delta ):
2019-11-14 03:56:30 +00:00
existing_selection = self.currentIndex()
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
if existing_selection != -1:
2018-05-16 20:09:50 +00:00
2019-11-14 03:56:30 +00:00
new_selection = ( existing_selection + delta ) % self.count()
2018-05-16 20:09:50 +00:00
if new_selection != existing_selection:
2019-11-14 03:56:30 +00:00
self.setCurrentIndex( new_selection )
2018-05-16 20:09:50 +00:00
2020-05-13 19:03:16 +00:00
def DeleteAllPages( self ):
while self.count() > 0:
page = self.widget( 0 )
self.removeTab( 0 )
page.deleteLater()
2018-05-16 20:09:50 +00:00
def GetPages( self ):
2019-11-14 03:56:30 +00:00
return [ self.widget( i ) for i in range( self.count() ) ]
2018-05-16 20:09:50 +00:00
def SelectLeft( self ):
self._ShiftSelection( -1 )
2019-05-08 21:06:42 +00:00
def SelectPage( self, page ):
2019-11-14 03:56:30 +00:00
for i in range( self.count() ):
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
if self.widget( i ) == page:
2019-05-08 21:06:42 +00:00
2019-11-14 03:56:30 +00:00
self.setCurrentIndex( i )
2019-05-08 21:06:42 +00:00
return
2018-05-16 20:09:50 +00:00
def SelectRight( self ):
self._ShiftSelection( 1 )
2019-11-14 03:56:30 +00:00
class BetterRadioBox( QP.RadioBox ):
2017-01-04 22:48:23 +00:00
def __init__( self, *args, **kwargs ):
self._indices_to_data = { i : data for ( i, ( s, data ) ) in enumerate( kwargs[ 'choices' ] ) }
kwargs[ 'choices' ] = [ s for ( s, data ) in kwargs[ 'choices' ] ]
2019-11-14 03:56:30 +00:00
QP.RadioBox.__init__( self, *args, **kwargs )
2017-01-04 22:48:23 +00:00
2019-07-24 21:39:02 +00:00
def GetValue( self ):
2017-01-04 22:48:23 +00:00
2019-11-14 03:56:30 +00:00
index = self.GetCurrentIndex()
2017-01-04 22:48:23 +00:00
return self._indices_to_data[ index ]
2020-11-18 22:15:21 +00:00
def SetValue( self, data ):
for ( i, d ) in self._indices_to_data.items():
if d == data:
self.Select( i )
return
2019-11-14 03:56:30 +00:00
class BetterStaticText( QP.EllipsizedLabel ):
2017-04-19 20:58:30 +00:00
2018-11-07 23:09:40 +00:00
def __init__( self, parent, label = None, tooltip_label = False, **kwargs ):
2017-04-19 20:58:30 +00:00
2019-11-14 03:56:30 +00:00
ellipsize_end = 'ellipsize_end' in kwargs and kwargs[ 'ellipsize_end' ]
QP.EllipsizedLabel.__init__( self, parent, ellipsize_end = ellipsize_end )
2017-04-19 20:58:30 +00:00
2019-11-28 01:11:46 +00:00
# otherwise by default html in 'this is a <hr> parsing step' stuff renders fully lmaoooo
self.setTextFormat( QC.Qt.PlainText )
2018-11-07 23:09:40 +00:00
self._tooltip_label = tooltip_label
2019-11-14 03:56:30 +00:00
if 'ellipsize_end' in kwargs and kwargs[ 'ellipsize_end' ]:
2018-11-07 23:09:40 +00:00
self._tooltip_label = True
2018-07-04 20:48:28 +00:00
self._last_set_text = '' # we want a separate copy since the one we'll send to the st will be wrapped and have additional '\n's
self._wrap_width = None
2017-04-19 20:58:30 +00:00
if label is not None:
2019-11-14 03:56:30 +00:00
self.setText( label )
2017-04-19 20:58:30 +00:00
2019-11-20 23:10:46 +00:00
2021-02-24 22:35:18 +00:00
def clear( self ):
self._last_set_text = ''
QP.EllipsizedLabel.clear( self )
2019-11-14 03:56:30 +00:00
def setText( self, text ):
# this doesn't need mnemonic escape _unless_ a buddy is set, wew lad
2017-07-12 20:03:45 +00:00
2018-07-04 20:48:28 +00:00
if text != self._last_set_text:
self._last_set_text = text
2017-07-12 20:03:45 +00:00
2019-11-14 03:56:30 +00:00
QP.EllipsizedLabel.setText( self, text )
2017-07-12 20:03:45 +00:00
2018-11-07 23:09:40 +00:00
if self._tooltip_label:
2019-11-14 03:56:30 +00:00
self.setToolTip( text )
2018-11-07 23:09:40 +00:00
2018-07-04 20:48:28 +00:00
2018-08-29 20:20:41 +00:00
class BetterHyperLink( BetterStaticText ):
def __init__( self, parent, label, url ):
BetterStaticText.__init__( self, parent, label )
self._url = url
2019-11-14 03:56:30 +00:00
self.setToolTip( self._url )
self.setTextFormat( QC.Qt.RichText )
self.setTextInteractionFlags( QC.Qt.TextBrowserInteraction )
2018-08-29 20:20:41 +00:00
2019-11-14 03:56:30 +00:00
self.setText( '<a href="{}">{}</a>'.format( url, label ) )
2019-11-20 23:10:46 +00:00
2019-12-11 23:18:37 +00:00
self.linkActivated.connect( self.Activated )
def Activated( self ):
ClientPaths.LaunchURLInWebBrowser( self._url )
2019-11-14 03:56:30 +00:00
class BufferedWindow( QW.QWidget ):
2013-03-15 02:38:12 +00:00
def __init__( self, *args, **kwargs ):
2019-11-14 03:56:30 +00:00
QW.QWidget.__init__( self, *args )
2013-03-15 02:38:12 +00:00
if 'size' in kwargs:
2020-02-26 22:28:52 +00:00
size = kwargs[ 'size' ]
if isinstance( size, QC.QSize ):
self.setFixedSize( kwargs[ 'size' ] )
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
def _Draw( self, painter ):
2015-11-18 22:44:07 +00:00
raise NotImplementedError()
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
def paintEvent( self, event ):
2015-11-18 22:44:07 +00:00
2019-11-14 03:56:30 +00:00
painter = QG.QPainter( self )
2015-11-18 22:44:07 +00:00
2019-11-14 03:56:30 +00:00
self._Draw( painter )
2013-03-15 02:38:12 +00:00
2015-05-13 20:22:39 +00:00
class BufferedWindowIcon( BufferedWindow ):
2020-05-06 21:31:41 +00:00
def __init__( self, parent, bmp, click_callable = None ):
2015-05-13 20:22:39 +00:00
2019-11-14 03:56:30 +00:00
BufferedWindow.__init__( self, parent, size = bmp.size() )
2015-05-13 20:22:39 +00:00
self._bmp = bmp
2020-05-06 21:31:41 +00:00
self._click_callable = click_callable
2015-05-13 20:22:39 +00:00
2015-11-18 22:44:07 +00:00
2019-11-14 03:56:30 +00:00
def _Draw( self, painter ):
2015-05-13 20:22:39 +00:00
2019-11-14 03:56:30 +00:00
background_colour = QP.GetBackgroundColour( self.parentWidget() )
2015-05-13 20:22:39 +00:00
2019-11-14 03:56:30 +00:00
painter.setBackground( QG.QBrush( background_colour ) )
2015-05-13 20:22:39 +00:00
2019-11-14 03:56:30 +00:00
painter.eraseRect( painter.viewport() )
2015-05-13 20:22:39 +00:00
2019-11-14 03:56:30 +00:00
if isinstance( self._bmp, QG.QImage ):
painter.drawImage( 0, 0, self._bmp )
else:
painter.drawPixmap( 0, 0, self._bmp )
2015-05-13 20:22:39 +00:00
2020-05-06 21:31:41 +00:00
def mousePressEvent( self, event ):
if self._click_callable is None:
return BufferedWindow.mousePressEvent( self, event )
else:
self._click_callable()
2017-09-27 21:52:54 +00:00
class CheckboxManager( object ):
def GetCurrentValue( self ):
raise NotImplementedError()
def Invert( self ):
raise NotImplementedError()
2018-06-27 19:27:05 +00:00
class CheckboxManagerBoolean( CheckboxManager ):
def __init__( self, obj, name ):
CheckboxManager.__init__( self )
self._obj = obj
self._name = name
def GetCurrentValue( self ):
if not self._obj:
return False
return getattr( self._obj, self._name )
def Invert( self ):
if not self._obj:
return
value = getattr( self._obj, self._name )
setattr( self._obj, self._name, not value )
2017-09-27 21:52:54 +00:00
class CheckboxManagerCalls( CheckboxManager ):
def __init__( self, invert_call, value_call ):
CheckboxManager.__init__( self )
self._invert_call = invert_call
self._value_call = value_call
def GetCurrentValue( self ):
return self._value_call()
def Invert( self ):
self._invert_call()
class CheckboxManagerOptions( CheckboxManager ):
def __init__( self, boolean_name ):
CheckboxManager.__init__( self )
self._boolean_name = boolean_name
def GetCurrentValue( self ):
2017-12-06 22:06:56 +00:00
new_options = HG.client_controller.new_options
2017-09-27 21:52:54 +00:00
return new_options.GetBoolean( self._boolean_name )
def Invert( self ):
2017-12-06 22:06:56 +00:00
new_options = HG.client_controller.new_options
2017-09-27 21:52:54 +00:00
new_options.InvertBoolean( self._boolean_name )
2019-07-31 22:01:02 +00:00
HG.client_controller.pub( 'checkbox_manager_inverted' )
2020-10-28 22:20:33 +00:00
HG.client_controller.pub( 'notify_new_menu_option' )
2019-07-31 22:01:02 +00:00
2017-09-27 21:52:54 +00:00
2019-11-14 03:56:30 +00:00
class AlphaColourControl( QW.QWidget ):
2018-03-07 22:48:29 +00:00
def __init__( self, parent ):
2019-11-14 03:56:30 +00:00
QW.QWidget.__init__( self, parent )
2018-03-07 22:48:29 +00:00
2018-09-26 19:05:12 +00:00
self._colour_picker = BetterColourControl( self )
2018-03-07 22:48:29 +00:00
2019-11-14 03:56:30 +00:00
self._alpha_selector = QP.MakeQSpinBox( self, min=0, max=255 )
hbox = QP.HBoxLayout( spacing = 5 )
2018-03-07 22:48:29 +00:00
2020-07-29 20:52:44 +00:00
QP.AddToLayout( hbox, self._colour_picker, CC.FLAGS_CENTER_PERPENDICULAR )
QP.AddToLayout( hbox, BetterStaticText(self,'alpha:'), CC.FLAGS_CENTER_PERPENDICULAR )
QP.AddToLayout( hbox, self._alpha_selector, CC.FLAGS_CENTER_PERPENDICULAR )
2018-03-07 22:48:29 +00:00
2019-11-14 03:56:30 +00:00
hbox.addStretch( 1 )
2018-03-07 22:48:29 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( hbox )
2018-03-07 22:48:29 +00:00
def GetValue( self ):
colour = self._colour_picker.GetColour()
2019-11-14 03:56:30 +00:00
a = self._alpha_selector.value()
2018-03-07 22:48:29 +00:00
2020-02-26 22:28:52 +00:00
colour.setAlpha( a )
2018-03-07 22:48:29 +00:00
return colour
2020-02-26 22:28:52 +00:00
def SetValue( self, colour: QG.QColor ):
2018-03-07 22:48:29 +00:00
2020-02-26 22:28:52 +00:00
picker_colour = QG.QColor( colour.rgb() )
2018-03-07 22:48:29 +00:00
2020-03-04 22:12:53 +00:00
self._colour_picker.SetColour( picker_colour )
2018-03-07 22:48:29 +00:00
2020-02-26 22:28:52 +00:00
self._alpha_selector.setValue( colour.alpha() )
2018-03-07 22:48:29 +00:00
2017-08-30 20:27:47 +00:00
class ExportPatternButton( BetterButton ):
2014-02-26 22:09:54 +00:00
def __init__( self, parent ):
2017-08-30 20:27:47 +00:00
BetterButton.__init__( self, parent, 'pattern shortcuts', self._Hit )
2014-02-26 22:09:54 +00:00
2017-08-30 20:27:47 +00:00
def _Hit( self ):
2014-02-26 22:09:54 +00:00
2019-11-14 03:56:30 +00:00
menu = QW.QMenu()
2014-02-26 22:09:54 +00:00
2017-08-30 20:27:47 +00:00
ClientGUIMenus.AppendMenuLabel( menu, 'click on a phrase to copy to clipboard' )
2014-02-26 22:09:54 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus.AppendSeparator( menu )
2014-02-26 22:09:54 +00:00
2019-12-05 05:29:32 +00:00
ClientGUIMenus.AppendMenuItem( menu, 'unique numerical file id - {file_id}', 'copy "{file_id}" to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '{file_id}' )
2019-11-14 03:56:30 +00:00
ClientGUIMenus.AppendMenuItem( menu, 'the file\'s hash - {hash}', 'copy "{hash}" to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '{hash}' )
ClientGUIMenus.AppendMenuItem( menu, 'all the file\'s tags - {tags}', 'copy "{tags}" to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '{tags}' )
ClientGUIMenus.AppendMenuItem( menu, 'all the file\'s non-namespaced tags - {nn tags}', 'copy "{nn tags}" to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '{nn tags}' )
2014-02-26 22:09:54 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus.AppendSeparator( menu )
2014-02-26 22:09:54 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus.AppendMenuItem( menu, 'all instances of a particular namespace - [\u2026]', 'copy "[\u2026]" to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '[\u2026]' )
2014-02-26 22:09:54 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus.AppendSeparator( menu )
2014-02-26 22:09:54 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus.AppendMenuItem( menu, 'a particular tag, if the file has it - (\u2026)', 'copy "(\u2026)" to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '(\u2026)' )
2014-02-26 22:09:54 +00:00
2020-03-04 22:12:53 +00:00
CGC.core().PopupMenu( self, menu )
2014-02-26 22:09:54 +00:00
2019-11-14 03:56:30 +00:00
class Gauge( QW.QProgressBar ):
2013-03-15 02:38:12 +00:00
def __init__( self, *args, **kwargs ):
2019-11-14 03:56:30 +00:00
QW.QProgressBar.__init__( self, *args, **kwargs )
2013-03-15 02:38:12 +00:00
2018-05-09 20:23:00 +00:00
self._actual_value = None
2017-07-12 20:03:45 +00:00
self._actual_range = None
self._is_pulsing = False
2013-03-15 02:38:12 +00:00
2021-04-28 21:43:16 +00:00
self.SetRange( 1 )
self.SetValue( 0 )
2013-03-15 02:38:12 +00:00
2018-05-09 20:23:00 +00:00
def GetValueRange( self ):
if self._actual_range is None:
2019-11-14 03:56:30 +00:00
range = self.maximum()
2018-05-09 20:23:00 +00:00
else:
range = self._actual_range
return ( self._actual_value, range )
2017-07-12 20:03:45 +00:00
def SetRange( self, range ):
2013-03-15 02:38:12 +00:00
2021-04-28 21:43:16 +00:00
if range is None or range == 0:
2017-01-25 22:56:55 +00:00
self.Pulse()
2013-03-15 02:38:12 +00:00
else:
if self._is_pulsing:
self.StopPulsing()
2017-07-12 20:03:45 +00:00
if range > 1000:
self._actual_range = range
range = 1000
else:
self._actual_range = None
2019-11-14 03:56:30 +00:00
if range != self.maximum():
2017-07-12 20:03:45 +00:00
2019-11-14 03:56:30 +00:00
QW.QProgressBar.setMaximum( self, range )
2017-07-12 20:03:45 +00:00
2013-03-15 02:38:12 +00:00
def SetValue( self, value ):
2018-05-09 20:23:00 +00:00
self._actual_value = value
if not self._is_pulsing:
2017-01-25 22:56:55 +00:00
if value is None:
2017-07-12 20:03:45 +00:00
self.Pulse()
2017-07-12 20:03:45 +00:00
else:
if self._actual_range is not None:
2019-01-09 22:59:03 +00:00
value = min( int( 1000 * ( value / self._actual_range ) ), 1000 )
2017-07-12 20:03:45 +00:00
2019-11-14 03:56:30 +00:00
value = min( value, self.maximum() )
2017-08-09 21:33:51 +00:00
2019-11-14 03:56:30 +00:00
if value != self.value():
2019-11-14 03:56:30 +00:00
QW.QProgressBar.setValue( self, value )
2017-07-12 20:03:45 +00:00
2017-01-25 22:56:55 +00:00
2013-03-15 02:38:12 +00:00
def StopPulsing( self ):
self._is_pulsing = False
self.SetRange( 1 )
self.SetValue( 0 )
2019-11-14 03:56:30 +00:00
def Pulse( self ):
2021-04-07 21:26:45 +00:00
# pulse looked stupid, was turning on too much, should improve it later
#self.setMaximum( 0 )
2019-11-14 03:56:30 +00:00
2021-04-07 21:26:45 +00:00
#self.setMinimum( 0 )
self.SetRange( 1 )
self.SetValue( 0 )
2019-11-14 03:56:30 +00:00
self._is_pulsing = True
class ListBook( QW.QWidget ):
2013-03-15 02:38:12 +00:00
def __init__( self, *args, **kwargs ):
2019-11-14 03:56:30 +00:00
QW.QWidget.__init__( self, *args, **kwargs )
2013-03-15 02:38:12 +00:00
2016-05-18 20:07:14 +00:00
self._keys_to_active_pages = {}
self._keys_to_proto_pages = {}
2015-05-06 20:26:18 +00:00
2019-11-14 03:56:30 +00:00
self._list_box = QW.QListWidget( self )
self._list_box.setSelectionMode( QW.QListWidget.SingleSelection )
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
self._empty_panel = QW.QWidget( self )
2013-03-15 02:38:12 +00:00
2016-05-18 20:07:14 +00:00
self._current_key = None
2013-03-15 02:38:12 +00:00
self._current_panel = self._empty_panel
2019-11-14 03:56:30 +00:00
self._panel_sizer = QP.VBoxLayout()
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( self._panel_sizer, self._empty_panel, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
hbox = QP.HBoxLayout( margin = 0 )
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( hbox, self._list_box, CC.FLAGS_EXPAND_PERPENDICULAR )
QP.AddToLayout( hbox, self._panel_sizer, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
self._list_box.itemSelectionChanged.connect( self.EventSelection )
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( hbox )
2013-03-15 02:38:12 +00:00
2016-05-18 20:07:14 +00:00
def _ActivatePage( self, key ):
( classname, args, kwargs ) = self._keys_to_proto_pages[ key ]
page = classname( *args, **kwargs )
2019-11-14 03:56:30 +00:00
page.setVisible( False )
2016-05-18 20:07:14 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( self._panel_sizer, page, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
2016-05-18 20:07:14 +00:00
self._keys_to_active_pages[ key ] = page
del self._keys_to_proto_pages[ key ]
def _GetIndex( self, key ):
2019-11-14 03:56:30 +00:00
for i in range( self._list_box.count() ):
2013-12-18 22:49:24 +00:00
2020-03-18 21:35:57 +00:00
i_key = self._list_box.item( i ).data( QC.Qt.UserRole )
2016-05-18 20:07:14 +00:00
if i_key == key:
2013-12-18 22:49:24 +00:00
2016-05-18 20:07:14 +00:00
return i
2013-12-18 22:49:24 +00:00
2019-11-14 03:56:30 +00:00
return -1
2016-07-06 21:13:15 +00:00
2013-03-15 02:38:12 +00:00
def _Select( self, selection ):
2019-11-14 03:56:30 +00:00
if selection == -1:
2016-05-18 20:07:14 +00:00
self._current_key = None
else:
2020-03-18 21:35:57 +00:00
self._current_key = self._list_box.item( selection ).data( QC.Qt.UserRole )
2016-05-18 20:07:14 +00:00
2013-03-23 17:57:29 +00:00
2019-11-14 03:56:30 +00:00
self._current_panel.setVisible( False )
self._list_box.blockSignals( True )
QP.ListWidgetSetSelection( self._list_box, selection )
2013-03-23 17:57:29 +00:00
2019-11-14 03:56:30 +00:00
self._list_box.blockSignals( False )
2013-03-23 17:57:29 +00:00
2019-11-14 03:56:30 +00:00
if selection == -1:
2016-05-18 20:07:14 +00:00
self._current_panel = self._empty_panel
2013-03-23 17:57:29 +00:00
else:
2013-03-15 02:38:12 +00:00
2016-05-18 20:07:14 +00:00
if self._current_key in self._keys_to_proto_pages:
2013-03-23 17:57:29 +00:00
2016-05-18 20:07:14 +00:00
self._ActivatePage( self._current_key )
2013-03-15 02:38:12 +00:00
2016-05-18 20:07:14 +00:00
self._current_panel = self._keys_to_active_pages[ self._current_key ]
2013-03-23 17:57:29 +00:00
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
self._current_panel.show()
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
self.update()
2013-03-15 02:38:12 +00:00
2016-05-18 20:07:14 +00:00
def AddPage( self, display_name, key, page, select = False ):
2019-11-14 03:56:30 +00:00
if self._GetIndex( key ) != -1:
2016-05-18 20:07:14 +00:00
raise HydrusExceptions.NameException( 'That entry already exists!' )
2013-03-15 02:38:12 +00:00
2016-01-13 22:08:19 +00:00
if not isinstance( page, tuple ):
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
page.setVisible( False )
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( self._panel_sizer, page, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
2013-03-15 02:38:12 +00:00
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
# Could call QListWidget.sortItems() here instead of doing it manually
2016-05-25 21:54:03 +00:00
2019-11-14 03:56:30 +00:00
current_display_names = QP.ListWidgetGetStrings( self._list_box )
2016-05-25 21:54:03 +00:00
insertion_index = len( current_display_names )
for ( i, current_display_name ) in enumerate( current_display_names ):
2017-02-01 21:11:17 +00:00
if current_display_name > display_name:
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
insertion_index = i
2016-02-17 22:06:47 +00:00
2017-02-01 21:11:17 +00:00
break
2016-01-06 21:17:20 +00:00
2014-08-13 22:18:12 +00:00
2019-11-14 03:56:30 +00:00
item = QW.QListWidgetItem()
item.setText( display_name )
item.setData( QC.Qt.UserRole, key )
self._list_box.insertItem( insertion_index, item )
2017-02-01 21:11:17 +00:00
self._keys_to_active_pages[ key ] = page
2019-11-14 03:56:30 +00:00
if self._list_box.count() == 1:
2016-04-27 19:20:37 +00:00
2017-02-01 21:11:17 +00:00
self._Select( 0 )
elif select:
index = self._GetIndex( key )
self._Select( index )
2016-04-27 19:20:37 +00:00
2014-02-26 22:09:54 +00:00
2017-02-01 21:11:17 +00:00
def AddPageArgs( self, display_name, key, classname, args, kwargs ):
2013-07-24 20:26:00 +00:00
2019-11-14 03:56:30 +00:00
if self._GetIndex( key ) != -1:
2017-02-01 21:11:17 +00:00
raise HydrusExceptions.NameException( 'That entry already exists!' )
2013-08-14 20:21:49 +00:00
2019-11-14 03:56:30 +00:00
# Could call QListWidget.sortItems() here instead of doing it manually
2013-08-14 20:21:49 +00:00
2019-11-14 03:56:30 +00:00
current_display_names = QP.ListWidgetGetStrings( self._list_box )
2013-08-14 20:21:49 +00:00
2017-02-01 21:11:17 +00:00
insertion_index = len( current_display_names )
for ( i, current_display_name ) in enumerate( current_display_names ):
if current_display_name > display_name:
insertion_index = i
break
2019-11-14 03:56:30 +00:00
item = QW.QListWidgetItem()
item.setText( display_name )
item.setData( QC.Qt.UserRole, key )
self._list_box.insertItem( insertion_index, item )
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
self._keys_to_proto_pages[ key ] = ( classname, args, kwargs )
2014-02-26 22:09:54 +00:00
2019-11-14 03:56:30 +00:00
if self._list_box.count() == 1:
2017-02-01 21:11:17 +00:00
self._Select( 0 )
2014-02-26 22:09:54 +00:00
2013-07-31 21:26:38 +00:00
2017-02-01 21:11:17 +00:00
def DeleteAllPages( self ):
2016-01-06 21:17:20 +00:00
2019-11-14 03:56:30 +00:00
self._panel_sizer.removeWidget( self._empty_panel )
2016-03-16 22:19:14 +00:00
2019-11-14 03:56:30 +00:00
QP.ClearLayout( self._panel_sizer, delete_widgets=True )
2016-01-06 21:17:20 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( self._panel_sizer, self._empty_panel, CC.FLAGS_EXPAND_SIZER_BOTH_WAYS )
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
self._current_key = None
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
self._current_panel = self._empty_panel
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
self._keys_to_active_pages = {}
self._keys_to_proto_pages = {}
2016-01-06 21:17:20 +00:00
2019-11-14 03:56:30 +00:00
self._list_box.clear()
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
def DeleteCurrentPage( self ):
2013-07-31 21:26:38 +00:00
2019-11-14 03:56:30 +00:00
selection = QP.ListWidgetGetSelection( self._list_box )
2013-08-14 20:21:49 +00:00
2019-11-14 03:56:30 +00:00
if selection != -1:
2013-07-31 21:26:38 +00:00
2017-02-01 21:11:17 +00:00
key_to_delete = self._current_key
page_to_delete = self._current_panel
2013-07-31 21:26:38 +00:00
2017-02-01 21:11:17 +00:00
next_selection = selection + 1
previous_selection = selection - 1
2014-12-10 22:02:39 +00:00
2019-11-14 03:56:30 +00:00
if next_selection < self._list_box.count():
2017-02-01 21:11:17 +00:00
self._Select( next_selection )
elif previous_selection >= 0:
self._Select( previous_selection )
else:
2019-11-14 03:56:30 +00:00
self._Select( -1 )
2017-02-01 21:11:17 +00:00
2016-01-06 21:17:20 +00:00
2019-11-14 03:56:30 +00:00
self._panel_sizer.removeWidget( page_to_delete )
2013-07-31 21:26:38 +00:00
2019-11-14 03:56:30 +00:00
page_to_delete.deleteLater()
2013-07-31 21:26:38 +00:00
2017-02-01 21:11:17 +00:00
del self._keys_to_active_pages[ key_to_delete ]
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
QP.ListWidgetDelete( self._list_box, selection )
2015-02-03 20:40:21 +00:00
2017-02-01 21:11:17 +00:00
2019-11-14 03:56:30 +00:00
def EventSelection( self ):
2017-02-01 21:11:17 +00:00
2019-11-14 03:56:30 +00:00
selection = QP.ListWidgetGetSelection( self._list_box )
if selection != self._GetIndex( self._current_key ):
2017-02-01 21:11:17 +00:00
2019-11-14 03:56:30 +00:00
self._Select( selection )
2016-01-06 21:17:20 +00:00
2013-08-14 20:21:49 +00:00
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
def GetCurrentKey( self ):
2016-07-13 17:37:44 +00:00
2017-02-01 21:11:17 +00:00
return self._current_key
2016-07-13 17:37:44 +00:00
2017-02-01 21:11:17 +00:00
def GetCurrentPage( self ):
2015-10-28 21:29:05 +00:00
2017-02-01 21:11:17 +00:00
if self._current_panel == self._empty_panel:
return None
else:
return self._current_panel
2015-10-28 21:29:05 +00:00
2017-02-01 21:11:17 +00:00
def GetActivePages( self ):
2015-10-28 21:29:05 +00:00
2019-01-09 22:59:03 +00:00
return list(self._keys_to_active_pages.values())
2016-12-07 22:12:52 +00:00
2017-02-01 21:11:17 +00:00
def GetPage( self, key ):
2016-12-07 22:12:52 +00:00
2017-02-01 21:11:17 +00:00
if key in self._keys_to_proto_pages:
self._ActivatePage( key )
2015-10-28 21:29:05 +00:00
2017-02-01 21:11:17 +00:00
if key in self._keys_to_active_pages:
return self._keys_to_active_pages[ key ]
2013-07-24 20:26:00 +00:00
2017-02-01 21:11:17 +00:00
raise Exception( 'That page not found!' )
2013-08-14 20:21:49 +00:00
2017-02-01 21:11:17 +00:00
2017-03-22 22:38:15 +00:00
def GetPageCount( self ):
return len( self._keys_to_active_pages ) + len( self._keys_to_proto_pages )
2017-02-01 21:11:17 +00:00
def KeyExists( self, key ):
2015-02-03 20:40:21 +00:00
2017-02-01 21:11:17 +00:00
return key in self._keys_to_active_pages or key in self._keys_to_proto_pages
2014-10-29 21:39:01 +00:00
2017-02-01 21:11:17 +00:00
def Select( self, key ):
2015-12-09 23:16:41 +00:00
2017-02-01 21:11:17 +00:00
index = self._GetIndex( key )
2015-12-09 23:16:41 +00:00
2019-11-14 03:56:30 +00:00
if index != -1 and index != QP.ListWidgetGetSelection( self._list_box ) :
2020-03-04 22:12:53 +00:00
self._Select( index )
2015-12-09 23:16:41 +00:00
2017-02-01 21:11:17 +00:00
def SelectDown( self ):
2013-07-24 20:26:00 +00:00
2019-11-14 03:56:30 +00:00
current_selection = QP.ListWidgetGetSelection( self._list_box )
2017-02-01 21:11:17 +00:00
2019-11-14 03:56:30 +00:00
if current_selection != -1:
2016-12-21 22:30:54 +00:00
2019-11-14 03:56:30 +00:00
num_entries = self._list_box.count()
2016-12-21 22:30:54 +00:00
2017-02-01 21:11:17 +00:00
if current_selection == num_entries - 1: selection = 0
else: selection = current_selection + 1
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
if selection != current_selection:
self._Select( selection )
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
def SelectPage( self, page_to_select ):
2013-07-24 20:26:00 +00:00
2019-01-09 22:59:03 +00:00
for ( key, page ) in list(self._keys_to_active_pages.items()):
2016-01-06 21:17:20 +00:00
2017-02-01 21:11:17 +00:00
if page == page_to_select:
self._Select( self._GetIndex( key ) )
return
2016-01-06 21:17:20 +00:00
2013-07-24 20:26:00 +00:00
2015-02-03 20:40:21 +00:00
2017-02-01 21:11:17 +00:00
def SelectUp( self ):
2013-07-24 20:26:00 +00:00
2019-11-14 03:56:30 +00:00
current_selection = QP.ListWidgetGetSelection( self._list_box )
2015-10-28 21:29:05 +00:00
2019-11-14 03:56:30 +00:00
if current_selection != -1:
2017-02-01 21:11:17 +00:00
2019-11-14 03:56:30 +00:00
num_entries = self._list_box.count()
2017-02-01 21:11:17 +00:00
if current_selection == 0: selection = num_entries - 1
else: selection = current_selection - 1
2015-10-28 21:29:05 +00:00
2017-02-01 21:11:17 +00:00
if selection != current_selection:
self._Select( selection )
2015-10-28 21:29:05 +00:00
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
class NoneableSpinCtrl( QW.QWidget ):
valueChanged = QC.Signal()
2015-02-03 20:40:21 +00:00
2017-03-02 02:14:56 +00:00
def __init__( self, parent, message = '', none_phrase = 'no limit', min = 0, max = 1000000, unit = None, multiplier = 1, num_dimensions = 1 ):
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
QW.QWidget.__init__( self, parent )
2013-02-19 00:11:43 +00:00
2015-12-02 22:32:18 +00:00
self._unit = unit
2015-02-03 20:40:21 +00:00
self._multiplier = multiplier
2015-12-02 22:32:18 +00:00
self._num_dimensions = num_dimensions
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
self._checkbox = QW.QCheckBox( self )
self._checkbox.stateChanged.connect( self.EventCheckBox )
self._checkbox.setText( none_phrase )
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
self._one = QP.MakeQSpinBox( self, min=min, max=max )
2018-03-22 00:03:33 +00:00
2019-06-26 21:27:18 +00:00
width = ClientGUIFunctions.ConvertTextToPixelWidth( self._one, len( str( max ) ) + 5 )
2018-03-22 00:03:33 +00:00
2019-11-14 03:56:30 +00:00
self._one.setMaximumWidth( width )
2013-02-19 00:11:43 +00:00
2015-12-23 22:51:04 +00:00
if num_dimensions == 2:
2019-11-14 03:56:30 +00:00
self._two = QP.MakeQSpinBox( self, initial=0, min=min, max=max )
self._two.valueChanged.connect( self._HandleValueChanged )
2018-03-22 00:03:33 +00:00
2019-06-26 21:27:18 +00:00
width = ClientGUIFunctions.ConvertTextToPixelWidth( self._two, len( str( max ) ) + 5 )
2018-03-22 00:03:33 +00:00
2019-11-14 03:56:30 +00:00
self._two.setMinimumWidth( width )
2015-12-23 22:51:04 +00:00
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
hbox = QP.HBoxLayout( margin = 0 )
2013-02-19 00:11:43 +00:00
2015-07-15 20:28:26 +00:00
if len( message ) > 0:
2020-07-29 20:52:44 +00:00
QP.AddToLayout( hbox, BetterStaticText(self,message+': '), CC.FLAGS_CENTER_PERPENDICULAR )
2015-07-15 20:28:26 +00:00
2020-07-29 20:52:44 +00:00
QP.AddToLayout( hbox, self._one, CC.FLAGS_CENTER_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
if self._num_dimensions == 2:
2020-07-29 20:52:44 +00:00
QP.AddToLayout( hbox, BetterStaticText(self,'x'), CC.FLAGS_CENTER_PERPENDICULAR )
QP.AddToLayout( hbox, self._two, CC.FLAGS_CENTER_PERPENDICULAR )
2015-02-03 20:40:21 +00:00
2013-02-19 00:11:43 +00:00
2015-12-02 22:32:18 +00:00
if self._unit is not None:
2020-07-29 20:52:44 +00:00
QP.AddToLayout( hbox, BetterStaticText(self,self._unit), CC.FLAGS_CENTER_PERPENDICULAR )
2019-11-14 03:56:30 +00:00
2015-12-02 22:32:18 +00:00
2020-07-29 20:52:44 +00:00
QP.AddToLayout( hbox, self._checkbox, CC.FLAGS_CENTER_PERPENDICULAR )
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
hbox.addStretch( 1 )
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( hbox )
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
self._one.valueChanged.connect( self._HandleValueChanged )
self._checkbox.stateChanged.connect( self._HandleValueChanged )
2015-04-01 20:44:54 +00:00
2017-09-27 21:52:54 +00:00
2019-11-14 03:56:30 +00:00
def _HandleValueChanged( self, val ):
2017-09-27 21:52:54 +00:00
2019-11-14 03:56:30 +00:00
self.valueChanged.emit()
2019-11-14 03:56:30 +00:00
def EventCheckBox( self, state ):
2015-04-01 20:44:54 +00:00
2019-11-14 03:56:30 +00:00
if self._checkbox.isChecked():
2015-04-01 20:44:54 +00:00
2019-11-14 03:56:30 +00:00
self._one.setEnabled( False )
2018-04-11 22:30:40 +00:00
if self._num_dimensions == 2:
2019-11-14 03:56:30 +00:00
self._two.setEnabled( False )
2018-04-11 22:30:40 +00:00
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
else:
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
self._one.setEnabled( True )
2018-04-11 22:30:40 +00:00
if self._num_dimensions == 2:
2019-11-14 03:56:30 +00:00
self._two.setEnabled( True )
2018-04-11 22:30:40 +00:00
2013-02-19 00:11:43 +00:00
2015-02-03 20:40:21 +00:00
def GetValue( self ):
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
if self._checkbox.isChecked():
2017-10-18 19:41:25 +00:00
return None
2015-02-03 20:40:21 +00:00
else:
2017-10-18 19:41:25 +00:00
if self._num_dimensions == 2:
2019-11-14 03:56:30 +00:00
return ( self._one.value() * self._multiplier, self._two.value() * self._multiplier )
2017-10-18 19:41:25 +00:00
else:
2019-11-14 03:56:30 +00:00
return self._one.value() * self._multiplier
2017-10-18 19:41:25 +00:00
2015-02-03 20:40:21 +00:00
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
def setToolTip( self, text ):
2016-06-22 20:59:24 +00:00
2019-11-14 03:56:30 +00:00
QW.QWidget.setToolTip( self, text )
2016-06-22 20:59:24 +00:00
2019-11-14 03:56:30 +00:00
for c in self.children():
2016-06-22 20:59:24 +00:00
2019-11-14 03:56:30 +00:00
if isinstance( c, QW.QWidget ):
c.setToolTip( text )
2016-06-22 20:59:24 +00:00
2015-02-03 20:40:21 +00:00
def SetValue( self, value ):
2013-03-15 02:38:12 +00:00
2015-02-03 20:40:21 +00:00
if value is None:
2019-11-14 03:56:30 +00:00
self._checkbox.setChecked( True )
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
self._one.setEnabled( False )
if self._num_dimensions == 2: self._two.setEnabled( False )
2015-02-03 20:40:21 +00:00
else:
2019-11-14 03:56:30 +00:00
self._checkbox.setChecked( False )
2015-02-03 20:40:21 +00:00
if self._num_dimensions == 2:
2019-11-14 03:56:30 +00:00
self._two.setEnabled( True )
2015-02-03 20:40:21 +00:00
( value, y ) = value
2019-11-14 03:56:30 +00:00
self._two.setValue( y // self._multiplier )
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
self._one.setEnabled( True )
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
self._one.setValue( value // self._multiplier )
2015-02-03 20:40:21 +00:00
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
class NoneableTextCtrl( QW.QWidget ):
valueChanged = QC.Signal()
2017-10-18 19:41:25 +00:00
2018-10-03 21:00:15 +00:00
def __init__( self, parent, message = '', none_phrase = 'none' ):
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
QW.QWidget.__init__( self, parent )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
self._checkbox = QW.QCheckBox( self )
self._checkbox.stateChanged.connect( self.EventCheckBox )
self._checkbox.setText( none_phrase )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
self._text = QW.QLineEdit( self )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
hbox = QP.HBoxLayout( margin = 0 )
2017-10-18 19:41:25 +00:00
if len( message ) > 0:
2020-07-29 20:52:44 +00:00
QP.AddToLayout( hbox, BetterStaticText(self,message+': '), CC.FLAGS_CENTER_PERPENDICULAR )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( hbox, self._text, CC.FLAGS_EXPAND_BOTH_WAYS )
2020-07-29 20:52:44 +00:00
QP.AddToLayout( hbox, self._checkbox, CC.FLAGS_CENTER_PERPENDICULAR )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( hbox )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
self._checkbox.stateChanged.connect( self._HandleValueChanged )
self._text.textChanged.connect( self._HandleValueChanged )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
def _HandleValueChanged( self, val ):
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
self.valueChanged.emit()
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
def EventCheckBox( self, state ):
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
if self._checkbox.isChecked():
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
self._text.setEnabled( False )
2017-10-18 19:41:25 +00:00
else:
2019-11-14 03:56:30 +00:00
self._text.setEnabled( True )
2017-10-18 19:41:25 +00:00
def GetValue( self ):
2019-11-14 03:56:30 +00:00
if self._checkbox.isChecked():
2017-10-18 19:41:25 +00:00
return None
else:
2019-11-14 03:56:30 +00:00
return self._text.text()
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
def setToolTip( self, text ):
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
QW.QWidget.setToolTip( self, text )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
for c in self.children():
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
if isinstance( c, QW.QWidget ):
c.setToolTip( text )
2017-10-18 19:41:25 +00:00
def SetValue( self, value ):
if value is None:
2019-11-14 03:56:30 +00:00
self._checkbox.setChecked( True )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
self._text.setEnabled( False )
2017-10-18 19:41:25 +00:00
else:
2019-11-14 03:56:30 +00:00
self._checkbox.setChecked( False )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
self._text.setEnabled( True )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
self._text.setText( value )
2017-10-18 19:41:25 +00:00
2019-11-14 03:56:30 +00:00
class OnOffButton( QW.QPushButton ):
2013-03-15 02:38:12 +00:00
2020-05-20 21:36:02 +00:00
valueChanged = QC.Signal( bool )
def __init__( self, parent, on_label, off_label = None, start_on = True ):
2013-03-15 02:38:12 +00:00
2015-02-03 20:40:21 +00:00
if start_on: label = on_label
else: label = off_label
2013-03-15 02:38:12 +00:00
2019-11-14 03:56:30 +00:00
QW.QPushButton.__init__( self, parent )
QW.QPushButton.setText( self, label )
2013-03-15 02:38:12 +00:00
2020-02-26 22:28:52 +00:00
self.setObjectName( 'HydrusOnOffButton' )
2015-02-03 20:40:21 +00:00
self._on_label = on_label
2013-03-15 02:38:12 +00:00
2020-02-26 22:28:52 +00:00
if off_label is None:
self._off_label = on_label
else:
self._off_label = off_label
2013-09-18 17:23:30 +00:00
2020-02-26 22:28:52 +00:00
self.setProperty( 'hydrus_on', start_on )
2013-09-18 17:23:30 +00:00
2020-03-25 21:15:57 +00:00
self.clicked.connect( self.Flip )
2013-09-18 17:23:30 +00:00
2020-03-11 21:52:11 +00:00
def _SetValue( self, value ):
2013-09-18 17:23:30 +00:00
2020-03-11 21:52:11 +00:00
self.setProperty( 'hydrus_on', value )
2020-02-26 22:28:52 +00:00
2020-03-11 21:52:11 +00:00
if value:
2013-09-18 17:23:30 +00:00
2019-11-14 03:56:30 +00:00
self.setText( self._on_label )
2013-09-18 17:23:30 +00:00
2020-02-26 22:28:52 +00:00
else:
2014-02-12 23:09:38 +00:00
2020-02-26 22:28:52 +00:00
self.setText( self._off_label )
2014-02-12 23:09:38 +00:00
2013-02-19 00:11:43 +00:00
2020-05-20 21:36:02 +00:00
self.valueChanged.emit( value )
2020-02-26 22:28:52 +00:00
self.style().polish( self )
2013-02-19 00:11:43 +00:00
2020-03-25 21:15:57 +00:00
def Flip( self ):
2020-03-11 21:52:11 +00:00
new_value = not self.property( 'hydrus_on' )
self._SetValue( new_value )
def IsOn( self ):
return self.property( 'hydrus_on' )
def SetOnOff( self, value ):
self._SetValue( value )
2014-09-03 20:26:49 +00:00
2017-09-06 20:18:20 +00:00
class RegexButton( BetterButton ):
2015-02-03 20:40:21 +00:00
def __init__( self, parent ):
2013-07-24 20:26:00 +00:00
2017-09-06 20:18:20 +00:00
BetterButton.__init__( self, parent, 'regex shortcuts', self._ShowMenu )
2013-07-24 20:26:00 +00:00
2015-02-03 20:40:21 +00:00
2017-09-06 20:18:20 +00:00
def _ShowMenu( self ):
2013-11-06 18:22:07 +00:00
2019-11-14 03:56:30 +00:00
menu = QW.QMenu()
2013-07-24 20:26:00 +00:00
2017-09-06 20:18:20 +00:00
ClientGUIMenus.AppendMenuLabel( menu, 'click on a phrase to copy it to the clipboard' )
2013-07-24 20:26:00 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus.AppendSeparator( menu )
2014-03-12 22:08:23 +00:00
2019-11-14 03:56:30 +00:00
submenu = QW.QMenu( menu )
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus.AppendMenuItem( submenu, r'whitespace character - \s', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'\s' )
ClientGUIMenus.AppendMenuItem( submenu, r'number character - \d', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'\d' )
ClientGUIMenus.AppendMenuItem( submenu, r'alphanumeric or backspace character - \w', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'\w' )
ClientGUIMenus.AppendMenuItem( submenu, r'any character - .', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'.' )
ClientGUIMenus.AppendMenuItem( submenu, r'backslash character - \\', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'\\' )
ClientGUIMenus.AppendMenuItem( submenu, r'beginning of line - ^', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'^' )
ClientGUIMenus.AppendMenuItem( submenu, r'end of line - $', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'$' )
ClientGUIMenus.AppendMenuItem( submenu, 'any of these - [\u2026]', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '[\u2026]' )
ClientGUIMenus.AppendMenuItem( submenu, 'anything other than these - [^\u2026]', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '[^\u2026]' )
2015-02-03 20:40:21 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus.AppendSeparator( submenu )
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus.AppendMenuItem( submenu, r'0 or more matches, consuming as many as possible - *', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'*' )
ClientGUIMenus.AppendMenuItem( submenu, r'1 or more matches, consuming as many as possible - +', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'+' )
ClientGUIMenus.AppendMenuItem( submenu, r'0 or 1 matches, preferring 1 - ?', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'?' )
ClientGUIMenus.AppendMenuItem( submenu, r'0 or more matches, consuming as few as possible - *?', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'*?' )
ClientGUIMenus.AppendMenuItem( submenu, r'1 or more matches, consuming as few as possible - +?', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'+?' )
ClientGUIMenus.AppendMenuItem( submenu, r'0 or 1 matches, preferring 0 - ??', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'??' )
ClientGUIMenus.AppendMenuItem( submenu, r'exactly m matches - {m}', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'{m}' )
ClientGUIMenus.AppendMenuItem( submenu, r'm to n matches, consuming as many as possible - {m,n}', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'{m,n}' )
ClientGUIMenus.AppendMenuItem( submenu, r'm to n matches, consuming as few as possible - {m,n}?', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'{m,n}?' )
2015-02-03 20:40:21 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus.AppendSeparator( submenu )
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus.AppendMenuItem( submenu, 'the next characters are: (non-consuming) - (?=\u2026)', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '(?=\u2026)' )
ClientGUIMenus.AppendMenuItem( submenu, 'the next characters are not: (non-consuming) - (?!\u2026)', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '(?!\u2026)' )
ClientGUIMenus.AppendMenuItem( submenu, 'the previous characters are: (non-consuming) - (?<=\u2026)', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '(?<=\u2026)' )
ClientGUIMenus.AppendMenuItem( submenu, 'the previous characters are not: (non-consuming) - (?<!\u2026)', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '(?<!\u2026)' )
2015-02-03 20:40:21 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus.AppendSeparator( submenu )
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus.AppendMenuItem( submenu, r'0074 -> 74 - [1-9]+\d*', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', r'[1-9]+\d*' )
ClientGUIMenus.AppendMenuItem( submenu, r'filename - (?<=' + re.escape( os.path.sep ) + r')[^' + re.escape( os.path.sep ) + r']*?(?=\..*$)', 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', '(?<=' + re.escape( os.path.sep ) + r')[^' + re.escape( os.path.sep ) + r']*?(?=\..*$)' )
2015-09-23 21:21:02 +00:00
2017-09-06 20:18:20 +00:00
ClientGUIMenus.AppendMenu( menu, submenu, 'regex components' )
2015-09-23 21:21:02 +00:00
2019-11-14 03:56:30 +00:00
submenu = QW.QMenu( menu )
2015-09-23 21:21:02 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus.AppendMenuItem( submenu, 'manage favourites', 'manage some custom favourite phrases', self._ManageFavourites )
2015-09-23 21:21:02 +00:00
2017-03-15 20:13:04 +00:00
ClientGUIMenus.AppendSeparator( submenu )
2015-09-23 21:21:02 +00:00
2017-09-06 20:18:20 +00:00
for ( regex_phrase, description ) in HC.options[ 'regex_favourites' ]:
2019-12-11 23:18:37 +00:00
2019-11-14 03:56:30 +00:00
ClientGUIMenus.AppendMenuItem( submenu, description, 'copy this phrase to the clipboard', HG.client_controller.pub, 'clipboard', 'text', regex_phrase )
2015-09-23 21:21:02 +00:00
2015-02-03 20:40:21 +00:00
2017-09-06 20:18:20 +00:00
ClientGUIMenus.AppendMenu( menu, submenu, 'favourites' )
2015-02-03 20:40:21 +00:00
2020-03-04 22:12:53 +00:00
CGC.core().PopupMenu( self, menu )
2014-03-12 22:08:23 +00:00
2017-09-06 20:18:20 +00:00
def _ManageFavourites( self ):
2013-02-19 00:11:43 +00:00
2017-11-08 22:07:12 +00:00
regex_favourites = HC.options[ 'regex_favourites' ]
2013-02-19 00:11:43 +00:00
2020-04-29 21:44:12 +00:00
from hydrus.client.gui import ClientGUITopLevelWindowsPanels
2020-04-22 21:00:35 +00:00
from hydrus.client.gui import ClientGUIScrolledPanelsEdit
2020-03-04 22:12:53 +00:00
2020-04-29 21:44:12 +00:00
with ClientGUITopLevelWindowsPanels.DialogEdit( self, 'manage regex favourites' ) as dlg:
2015-09-23 21:21:02 +00:00
2017-11-08 22:07:12 +00:00
panel = ClientGUIScrolledPanelsEdit.EditRegexFavourites( dlg, regex_favourites )
dlg.SetPanel( panel )
2019-11-14 03:56:30 +00:00
if dlg.exec() == QW.QDialog.Accepted:
2017-11-08 22:07:12 +00:00
regex_favourites = panel.GetValue()
HC.options[ 'regex_favourites' ] = regex_favourites
HG.client_controller.Write( 'save_options', HC.options )
2015-09-23 21:21:02 +00:00
2013-02-19 00:11:43 +00:00
2019-11-14 03:56:30 +00:00
class StaticBox( QW.QFrame ):
2016-11-02 21:09:14 +00:00
2019-11-14 03:56:30 +00:00
def __init__( self, parent, title ):
2016-11-02 21:09:14 +00:00
2019-11-14 03:56:30 +00:00
QW.QFrame.__init__( self, parent )
2016-11-02 21:09:14 +00:00
2019-11-14 03:56:30 +00:00
self.setFrameStyle( QW.QFrame.Box | QW.QFrame.Raised )
self._spacer = QW.QSpacerItem( 0, 0, QW.QSizePolicy.Minimum, QW.QSizePolicy.MinimumExpanding )
2013-10-09 18:13:42 +00:00
2019-11-14 03:56:30 +00:00
self._sizer = QP.VBoxLayout()
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
normal_font = QW.QApplication.font()
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
normal_font_size = normal_font.pointSize()
normal_font_family = normal_font.family()
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
title_font = QG.QFont( normal_font_family, int( normal_font_size ), QG.QFont.Bold )
2015-02-03 20:40:21 +00:00
self._title_st = BetterStaticText( self, label = title )
self._title_st.setFont( title_font )
2015-02-03 20:40:21 +00:00
QP.AddToLayout( self._sizer, self._title_st, CC.FLAGS_CENTER )
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( self._sizer )
2015-02-03 20:40:21 +00:00
2019-11-14 03:56:30 +00:00
self.layout().addSpacerItem( self._spacer )
2013-10-09 18:13:42 +00:00
2019-11-14 03:56:30 +00:00
def Add( self, widget, flags = None ):
self.layout().removeItem( self._spacer )
2018-01-31 22:58:15 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( self._sizer, widget, flags )
self.layout().addSpacerItem( self._spacer )
2018-01-31 22:58:15 +00:00
2015-02-03 20:40:21 +00:00
def SetTitle( self, title ):
self._title_st.setText( title )
2017-09-27 21:52:54 +00:00
class RadioBox( StaticBox ):
def __init__( self, parent, title, choice_pairs, initial_index = None ):
StaticBox.__init__( self, parent, title )
self._indices_to_radio_buttons = {}
self._radio_buttons_to_data = {}
for ( index, ( text, data ) ) in enumerate( choice_pairs ):
2019-11-14 03:56:30 +00:00
radio_button = QW.QRadioButton( text, self )
2017-09-27 21:52:54 +00:00
2018-01-03 22:37:30 +00:00
self.Add( radio_button, CC.FLAGS_EXPAND_PERPENDICULAR )
2017-09-27 21:52:54 +00:00
self._indices_to_radio_buttons[ index ] = radio_button
self._radio_buttons_to_data[ radio_button ] = data
2019-11-14 03:56:30 +00:00
if initial_index is not None and initial_index in self._indices_to_radio_buttons: self._indices_to_radio_buttons[ initial_index ].setChecked( True )
2017-09-27 21:52:54 +00:00
def GetSelectedClientData( self ):
2019-01-09 22:59:03 +00:00
for radio_button in list(self._radio_buttons_to_data.keys()):
2017-09-27 21:52:54 +00:00
2019-11-14 03:56:30 +00:00
if radio_button.isDown(): return self._radio_buttons_to_data[ radio_button]
2017-09-27 21:52:54 +00:00
2017-11-29 21:48:23 +00:00
def SetSelection( self, index ):
2019-11-14 03:56:30 +00:00
self._indices_to_radio_buttons[ index ].setChecked( True )
2017-11-29 21:48:23 +00:00
2017-09-27 21:52:54 +00:00
2017-11-29 21:48:23 +00:00
def SetString( self, index, text ):
2019-11-14 03:56:30 +00:00
self._indices_to_radio_buttons[ index ].setText( text )
class TextCatchEnterEventFilter( QC.QObject ):
def __init__( self, parent, callable, *args, **kwargs ):
QC.QObject.__init__( self, parent )
self._callable = HydrusData.Call( callable, *args, **kwargs )
def eventFilter( self, watched, event ):
if event.type() == QC.QEvent.KeyPress and event.key() in ( QC.Qt.Key_Enter, QC.Qt.Key_Return ):
self._callable()
2020-02-12 22:50:37 +00:00
event.accept()
2019-11-14 03:56:30 +00:00
return True
return False
2017-11-29 21:48:23 +00:00
2017-09-27 21:52:54 +00:00
2019-11-14 03:56:30 +00:00
class TextAndGauge( QW.QWidget ):
2017-01-11 22:31:30 +00:00
def __init__( self, parent ):
2019-11-14 03:56:30 +00:00
QW.QWidget.__init__( self, parent )
2017-01-11 22:31:30 +00:00
2017-04-19 20:58:30 +00:00
self._st = BetterStaticText( self )
2017-01-11 22:31:30 +00:00
self._gauge = Gauge( self )
2019-11-14 03:56:30 +00:00
vbox = QP.VBoxLayout( margin = 0 )
2017-01-11 22:31:30 +00:00
2019-11-14 03:56:30 +00:00
QP.AddToLayout( vbox, self._st, CC.FLAGS_EXPAND_PERPENDICULAR )
QP.AddToLayout( vbox, self._gauge, CC.FLAGS_EXPAND_PERPENDICULAR )
2017-01-11 22:31:30 +00:00
2019-11-14 03:56:30 +00:00
self.setLayout( vbox )
2017-01-11 22:31:30 +00:00
2020-10-21 22:22:10 +00:00
def SetText( self, text ):
if not self or not QP.isValid( self ):
return
self._st.setText( text )
2017-01-11 22:31:30 +00:00
def SetValue( self, text, value, range ):
2019-11-14 03:56:30 +00:00
if not self or not QP.isValid( self ):
2017-11-29 21:48:23 +00:00
return
2019-11-14 03:56:30 +00:00
self._st.setText( text )
2017-01-11 22:31:30 +00:00
2017-07-12 20:03:45 +00:00
self._gauge.SetRange( range )
self._gauge.SetValue( value )
2017-01-11 22:31:30 +00:00