hydrus/hydrus/client/gui/ClientGUIFunctions.py

323 lines
7.8 KiB
Python
Raw Normal View History

2019-09-11 21:51:09 +00:00
import collections
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
2020-12-09 22:18:48 +00:00
from hydrus.core import HydrusText
2020-04-22 21:00:35 +00:00
from hydrus.client.gui import QtPorting as QP
2019-06-26 21:27:18 +00:00
2020-02-26 22:28:52 +00:00
def ClientToScreen( win: QW.QWidget, pos: QC.QPoint ) -> QC.QPoint:
2019-06-26 21:27:18 +00:00
2019-12-11 23:18:37 +00:00
tlw = win.window()
2019-11-14 03:56:30 +00:00
if ( win.isVisible() and tlw.isVisible() ) or True:
2019-06-26 21:27:18 +00:00
2019-11-14 03:56:30 +00:00
return win.mapToGlobal( pos )
2019-06-26 21:27:18 +00:00
else:
2019-11-14 03:56:30 +00:00
return QC.QPoint( 50, 50 )
2019-06-26 21:27:18 +00:00
MAGIC_TEXT_PADDING = 1.1
2020-05-20 21:36:02 +00:00
def ColourIsBright( colour: QG.QColor ):
it_is_bright = colour.valueF() > 0.75
return it_is_bright
def ColourIsGreyish( colour: QG.QColor ):
it_is_greyish = colour.hsvSaturationF() < 0.12
return it_is_greyish
2021-04-14 21:54:17 +00:00
def ConvertPixelsToTextWidth( window, pixels, round_down = False ):
2020-07-15 20:52:09 +00:00
twenty_chars_in_pixels = int( window.fontMetrics().boundingRect( 20 * 'x' ).width() * MAGIC_TEXT_PADDING )
one_char_in_pixels = twenty_chars_in_pixels / 20
2021-04-14 21:54:17 +00:00
if round_down:
return int( pixels // one_char_in_pixels )
else:
return round( pixels / one_char_in_pixels )
2020-07-15 20:52:09 +00:00
2019-06-26 21:27:18 +00:00
def ConvertTextToPixels( window, char_dimensions ):
( char_cols, char_rows ) = char_dimensions
2019-11-14 03:56:30 +00:00
return ( int( window.fontMetrics().boundingRect( char_cols * 'x' ).width() * MAGIC_TEXT_PADDING ), int( char_rows * window.fontMetrics().height() * MAGIC_TEXT_PADDING ) )
2019-06-26 21:27:18 +00:00
def ConvertTextToPixelWidth( window, char_cols ):
2019-11-14 03:56:30 +00:00
return int( window.fontMetrics().boundingRect( char_cols * 'x' ).width() * MAGIC_TEXT_PADDING )
2019-06-26 21:27:18 +00:00
2020-02-26 22:28:52 +00:00
def DialogIsOpen():
tlws = QW.QApplication.topLevelWidgets()
for tlw in tlws:
if isinstance( tlw, QP.Dialog ) and tlw.isModal():
return True
return False
2020-12-02 22:04:38 +00:00
def DrawText( painter, x, y, text ):
( boundingRect, text ) = GetTextSizeFromPainter( painter, text )
painter.drawText( QC.QRectF( x, y, boundingRect.width(), boundingRect.height() ), text )
2020-05-20 21:36:02 +00:00
def EscapeMnemonics( s: str ):
return s.replace( "&", "&&" )
def GetDifferentLighterDarkerColour( colour, intensity = 3 ):
new_hue = colour.hsvHueF()
2020-04-22 21:00:35 +00:00
2020-05-20 21:36:02 +00:00
if new_hue == -1: # completely achromatic
new_hue = 0.5
else:
new_hue = ( new_hue + 0.33 ) % 1.0
new_saturation = colour.hsvSaturationF()
if ColourIsGreyish( colour ):
new_saturation = 0.2
new_colour = QG.QColor.fromHsvF( new_hue, new_saturation, colour.valueF(), colour.alphaF() )
return GetLighterDarkerColour( new_colour, intensity )
2020-04-22 21:00:35 +00:00
2020-04-29 21:44:12 +00:00
def GetDisplayPosition( window ):
return QW.QApplication.desktop().availableGeometry( window ).topLeft()
def GetDisplaySize( window ):
return QW.QApplication.desktop().availableGeometry( window ).size()
2020-05-20 21:36:02 +00:00
def GetLighterDarkerColour( colour, intensity = 3 ):
if intensity is None or intensity == 0:
return colour
# darker/lighter works by multiplying value, so when it is closer to 0, lmao
breddy_darg_made = 0.25
if colour.value() < breddy_darg_made:
colour = QG.QColor.fromHslF( colour.hsvHueF(), colour.hsvSaturationF(), breddy_darg_made, colour.alphaF() )
qt_intensity = 100 + ( 20 * intensity )
if ColourIsBright( colour ):
return colour.darker( qt_intensity )
else:
return colour.lighter( qt_intensity )
2020-04-29 21:44:12 +00:00
def GetMouseScreen():
return QW.QApplication.screenAt( QG.QCursor.pos() )
2020-12-02 22:04:38 +00:00
def GetTextSizeFromPainter( painter: QG.QPainter, text: str ):
try:
text_size = painter.fontMetrics().size( QC.Qt.TextSingleLine, text )
except ValueError:
from hydrus.client.metadata import ClientTags
if not ClientTags.have_shown_invalid_tag_warning:
from hydrus.core import HydrusData
HydrusData.ShowText( 'Hey, I think hydrus stumbled across an invalid tag! Please run _database->check and repair->fix invalid tags_ immediately, or you may get errors!' )
2020-12-09 22:18:48 +00:00
bad_text = repr( text )
bad_text = HydrusText.ElideText( bad_text, 24 )
HydrusData.ShowText( 'The bad text was: {}'.format( bad_text ) )
2020-12-02 22:04:38 +00:00
ClientTags.have_shown_invalid_tag_warning = True
text = '*****INVALID, UNDISPLAYABLE TAG, RUN DATABASE REPAIR NOW*****'
text_size = painter.fontMetrics().size( QC.Qt.TextSingleLine, text )
return ( text_size, text )
2019-12-11 23:18:37 +00:00
def GetTLWParents( widget ):
2019-06-26 21:27:18 +00:00
2019-12-11 23:18:37 +00:00
widget_tlw = widget.window()
2019-06-26 21:27:18 +00:00
2019-12-11 23:18:37 +00:00
parent_tlws = []
2019-06-26 21:27:18 +00:00
2019-12-11 23:18:37 +00:00
parent = widget_tlw.parentWidget()
2019-06-26 21:27:18 +00:00
while parent is not None:
2019-12-11 23:18:37 +00:00
parent_tlw = parent.window()
2019-06-26 21:27:18 +00:00
2019-12-11 23:18:37 +00:00
parent_tlws.append( parent_tlw )
parent = parent_tlw.parentWidget()
2019-06-26 21:27:18 +00:00
2019-12-11 23:18:37 +00:00
return parent_tlws
2019-06-26 21:27:18 +00:00
2019-11-14 03:56:30 +00:00
def IsQtAncestor( child, ancestor, through_tlws = False ):
2019-06-26 21:27:18 +00:00
2019-07-17 22:10:19 +00:00
if child == ancestor:
return True
2019-06-26 21:27:18 +00:00
parent = child
if through_tlws:
while not parent is None:
if parent == ancestor:
return True
2019-11-14 03:56:30 +00:00
parent = parent.parentWidget()
2019-06-26 21:27:18 +00:00
else:
2019-11-14 03:56:30 +00:00
# only works within window
return ancestor.isAncestorOf( child )
2019-06-26 21:27:18 +00:00
return False
2020-04-29 21:44:12 +00:00
def MouseIsOnMyDisplay( window ):
window_handle = window.window().windowHandle()
if window_handle is None:
return False
window_screen = window_handle.screen()
mouse_screen = GetMouseScreen()
return mouse_screen is window_screen
2019-06-26 21:27:18 +00:00
def NotebookScreenToHitTest( notebook, screen_position ):
2019-12-05 05:29:32 +00:00
tab_pos = notebook.tabBar().mapFromGlobal( screen_position )
2019-06-26 21:27:18 +00:00
2019-12-05 05:29:32 +00:00
return notebook.tabBar().tabAt( tab_pos )
2019-06-26 21:27:18 +00:00
def SetBitmapButtonBitmap( button, bitmap ):
2019-11-14 03:56:30 +00:00
# old wx stuff, but still basically relevant
2019-06-26 21:27:18 +00:00
# the button's bitmap, retrieved via GetBitmap, is not the same as the one we gave it!
# hence testing bitmap vs that won't work to save time on an update loop, so we'll just save it here custom
2019-11-14 03:56:30 +00:00
# this isn't a big memory deal for our purposes since they are small and mostly if not all from the GlobalPixmaps library so shared anyway
2019-06-26 21:27:18 +00:00
if hasattr( button, 'last_bitmap' ):
if button.last_bitmap == bitmap:
return
2019-11-14 03:56:30 +00:00
button.setIcon( QG.QIcon( bitmap ) )
button.setIconSize( bitmap.size() )
2019-06-26 21:27:18 +00:00
button.last_bitmap = bitmap
2019-12-11 23:18:37 +00:00
def TLWIsActive( window ):
2019-06-26 21:27:18 +00:00
2019-11-20 23:10:46 +00:00
return window.window() == QW.QApplication.activeWindow()
2019-06-26 21:27:18 +00:00
2019-12-11 23:18:37 +00:00
def TLWOrChildIsActive( win ):
current_focus_tlw = QW.QApplication.activeWindow()
if current_focus_tlw is None:
return False
if current_focus_tlw == win:
return True
if win in GetTLWParents( current_focus_tlw ):
return True
return False
def WidgetOrAnyTLWChildHasFocus( window ):
2019-06-26 21:27:18 +00:00
2019-11-20 23:10:46 +00:00
active_window = QW.QApplication.activeWindow()
2019-11-14 03:56:30 +00:00
2019-11-20 23:10:46 +00:00
if window == active_window:
2019-06-26 21:27:18 +00:00
2019-11-20 23:10:46 +00:00
return True
2019-06-26 21:27:18 +00:00
2019-11-20 23:10:46 +00:00
widget = QW.QApplication.focusWidget()
2019-11-14 03:56:30 +00:00
2019-11-20 23:10:46 +00:00
if widget is None:
2019-12-11 23:18:37 +00:00
# take active window in lieu of focus, if it is unavailable
2019-11-20 23:10:46 +00:00
widget = active_window
2019-06-26 21:27:18 +00:00
2019-11-20 23:10:46 +00:00
while widget is not None:
2019-06-26 21:27:18 +00:00
2019-11-20 23:10:46 +00:00
if widget == window:
2019-06-26 21:27:18 +00:00
return True
2019-11-20 23:10:46 +00:00
widget = widget.parentWidget()
2019-06-26 21:27:18 +00:00
return False