Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vmj-qt
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kulya
vmj-qt
Commits
6ddd6758
Commit
6ddd6758
authored
Jan 03, 2013
by
Dan Pascu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added StateButton and AccountState widgets
parent
211061de
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
476 additions
and
3 deletions
+476
-3
buttons.py
blink/widgets/buttons.py
+444
-3
state-available.svg
resources/icons/state-available.svg
+8
-0
state-away.svg
resources/icons/state-away.svg
+8
-0
state-busy.svg
resources/icons/state-busy.svg
+8
-0
state-invisible.svg
resources/icons/state-invisible.svg
+8
-0
No files found.
blink/widgets/buttons.py
View file @
6ddd6758
# Copyright (c) 2010 AG Projects. See LICENSE for details.
# Copyright (c) 2010 AG Projects. See LICENSE for details.
#
#
__all__
=
[
'ToolButton'
,
'ConferenceButton'
,
'StreamButton'
,
'SegmentButton'
,
'SingleSegment'
,
'LeftSegment'
,
'MiddleSegment'
,
'RightSegment'
,
'RecordButton'
,
'SwitchViewButton'
]
__all__
=
[
'ToolButton'
,
'ConferenceButton'
,
'StreamButton'
,
'SegmentButton'
,
'SingleSegment'
,
'LeftSegment'
,
'MiddleSegment'
,
'RightSegment'
,
'RecordButton'
,
'SwitchViewButton'
,
'StateButton'
,
'AccountState'
]
from
PyQt4.QtCore
import
QTimer
,
pyqtSignal
from
PyQt4.QtCore
import
Qt
,
QLineF
,
QPointF
,
QRectF
,
QSize
,
QTimer
,
pyqtSignal
,
pyqtSignature
from
PyQt4.QtGui
import
QAction
,
QIcon
,
QPushButton
,
QStyle
,
QStyleOptionToolButton
,
QStylePainter
,
QToolButton
from
PyQt4.QtGui
import
QAction
,
QBrush
,
QColor
,
QCommonStyle
,
QLinearGradient
,
QIcon
,
QMenu
,
QPainter
,
QPainterPath
,
QPalette
,
QPen
,
QPixmap
from
PyQt4.QtGui
import
QPolygonF
,
QPushButton
,
QStyle
,
QStyleOptionToolButton
,
QStylePainter
,
QToolButton
from
application.python.decorator
import
decorator
,
preserve_signature
from
blink.resources
import
Resources
from
blink.widgets.color
import
ColorScheme
,
ColorUtils
class
ToolButton
(
QToolButton
):
class
ToolButton
(
QToolButton
):
...
@@ -367,3 +373,438 @@ class SwitchViewButton(QPushButton):
...
@@ -367,3 +373,438 @@ class SwitchViewButton(QPushButton):
event
.
ignore
()
event
.
ignore
()
def
color_key
(
instance
,
color
):
return
color
.
rgba
()
def
color_ratio_key
(
instance
,
color
,
ratio
):
return
color
.
rgba
()
<<
32
|
int
(
ratio
*
512
)
def
background_color_key
(
instance
,
background
,
color
):
return
background
.
rgba
()
<<
32
|
color
.
rgba
()
@
decorator
def
cache_result
(
key_func
):
def
cache_results
(
function
):
@
preserve_signature
(
function
)
def
wrapper
(
*
args
,
**
kw
):
key
=
key_func
(
*
args
,
**
kw
)
try
:
return
wrapper
.
__cache__
[
key
]
except
KeyError
:
return
wrapper
.
__cache__
.
setdefault
(
key
,
function
(
*
args
,
**
kw
))
wrapper
.
__cache__
=
{}
return
wrapper
return
cache_results
class
StateButtonStyle
(
QCommonStyle
):
_contrast
=
0.3
_bgcontrast
=
min
(
1.0
,
0.9
*
_contrast
/
0.7
)
_pixel_metrics
=
{
QStyle
.
PM_MenuButtonIndicator
:
11
,
QStyle
.
PM_DefaultFrameWidth
:
3
,
QStyle
.
PM_ButtonMargin
:
1
,
QStyle
.
PM_ButtonShiftHorizontal
:
0
,
QStyle
.
PM_ButtonShiftVertical
:
0
,
QStyle
.
PM_ButtonIconSize
:
32
}
@
pyqtSignature
(
"polish(QWidget*)"
)
def
polish
(
self
,
widget
):
widget
.
setAttribute
(
Qt
.
WA_Hover
)
super
(
StateButtonStyle
,
self
)
.
polish
(
widget
)
def
pixelMetric
(
self
,
metric
,
option
=
None
,
widget
=
None
):
return
self
.
_pixel_metrics
[
metric
]
def
sizeFromContents
(
self
,
element
,
option
,
size
,
widget
=
None
):
if
element
==
QStyle
.
CT_ToolButton
:
return
self
.
toolButtonSizeFromContents
(
option
,
size
,
widget
)
else
:
return
super
(
StateButtonStyle
,
self
)
.
sizeFromContents
(
element
,
option
,
size
,
widget
)
def
toolButtonSizeFromContents
(
self
,
option
,
size
,
widget
):
# Make width >= height to avoid super-skiny buttons
margin
=
2
*
(
self
.
_pixel_metrics
[
QStyle
.
PM_DefaultFrameWidth
]
+
self
.
_pixel_metrics
[
QStyle
.
PM_ButtonMargin
])
if
option
.
features
&
QStyleOptionToolButton
.
MenuButtonPopup
:
margin_size
=
QSize
(
margin
+
1
,
margin
)
menu_width
=
self
.
_pixel_metrics
[
QStyle
.
PM_MenuButtonIndicator
]
else
:
margin_size
=
QSize
(
margin
,
margin
)
menu_width
=
0
if
size
.
width
()
-
menu_width
<
size
.
height
():
size
.
setWidth
(
size
.
height
()
+
menu_width
)
return
size
+
margin_size
def
drawComplexControl
(
self
,
control
,
option
,
painter
,
widget
=
None
):
if
control
==
QStyle
.
CC_ToolButton
:
painter
.
save
()
self
.
drawToolButtonComplexControl
(
option
,
painter
,
widget
)
painter
.
restore
()
else
:
super
(
StateButtonStyle
,
self
)
.
drawComplexControl
(
control
,
option
,
painter
,
widget
)
def
drawToolButtonComplexControl
(
self
,
option
,
painter
,
widget
):
button_color
=
option
.
palette
.
color
(
QPalette
.
Button
)
if
option
.
state
&
(
QStyle
.
State_On
|
QStyle
.
State_Sunken
):
self
.
drawToolButtonSunkenBezel
(
painter
,
QRectF
(
option
.
rect
)
.
adjusted
(
1
,
1
,
-
1
,
-
1
),
button_color
)
else
:
enabled
=
bool
(
option
.
state
&
QStyle
.
State_Enabled
)
hoover
=
enabled
and
bool
(
option
.
state
&
QStyle
.
State_MouseOver
)
has_focus
=
enabled
and
bool
(
option
.
state
&
QStyle
.
State_HasFocus
)
self
.
drawToolButtonBezel
(
painter
,
QRectF
(
option
.
rect
),
button_color
,
hoover
=
hoover
,
has_focus
=
has_focus
)
if
option
.
features
&
QStyleOptionToolButton
.
MenuButtonPopup
:
self
.
drawToolButtonMenuIndicator
(
option
,
painter
,
widget
)
self
.
drawToolButtonContent
(
option
,
painter
,
widget
)
def
drawToolButtonBezel
(
self
,
painter
,
rect
,
color
,
hoover
=
False
,
has_focus
=
False
):
painter
.
setRenderHint
(
QPainter
.
Antialiasing
,
True
)
painter
.
setPen
(
Qt
.
NoPen
)
glow_rect
=
rect
shadow_rect
=
rect
.
adjusted
(
1
,
1
,
-
1
,
-
1
)
border_rect
=
rect
.
adjusted
(
2
,
2
,
-
2
,
-
2
)
content_rect
=
rect
.
adjusted
(
3
,
3
,
-
3
,
-
3
)
focus_color
=
QColor
(
'#3aa7dd'
)
hoover_color
=
QColor
(
'#6ed6ff'
)
shadow_color
=
ColorScheme
.
shade
(
self
.
background_bottom_color
(
color
),
ColorScheme
.
ShadowShade
,
0.0
)
border_color_top
=
ColorScheme
.
shade
(
self
.
background_top_color
(
color
),
ColorScheme
.
LightShade
,
0.0
)
border_color_bottom
=
ColorScheme
.
shade
(
self
.
background_bottom_color
(
color
),
ColorScheme
.
MidlightShade
,
0.5
)
# glow
painter
.
setCompositionMode
(
QPainter
.
CompositionMode_SourceOver
)
blend
=
QLinearGradient
(
glow_rect
.
topLeft
(),
glow_rect
.
bottomLeft
())
if
hoover
:
blend
.
setColorAt
(
0.0
,
self
.
color_with_alpha
(
hoover_color
,
0x45
))
blend
.
setColorAt
(
0.9
,
self
.
color_with_alpha
(
hoover_color
,
0x45
))
blend
.
setColorAt
(
1.0
,
self
.
color_with_alpha
(
ColorUtils
.
mix
(
hoover_color
,
shadow_color
,
0.4
),
0x55
))
elif
has_focus
:
blend
.
setColorAt
(
0.0
,
self
.
color_with_alpha
(
focus_color
,
0x45
))
blend
.
setColorAt
(
0.9
,
self
.
color_with_alpha
(
focus_color
,
0x45
))
blend
.
setColorAt
(
1.0
,
self
.
color_with_alpha
(
ColorUtils
.
mix
(
focus_color
,
shadow_color
,
0.4
),
0x55
))
else
:
blend
.
setColorAt
(
0.0
,
Qt
.
transparent
)
# or @0.5
blend
.
setColorAt
(
0.9
,
self
.
color_with_alpha
(
shadow_color
,
0x10
))
#blend.setColorAt(1-4.0/glow_rect.height(), self.color_with_alpha(shadow_color, 0x10)) # this is for exactly 4 pixels from bottom
blend
.
setColorAt
(
1.0
,
self
.
color_with_alpha
(
shadow_color
,
0x30
))
# 0x25, 0x30 or 0x35
painter
.
setBrush
(
blend
)
painter
.
drawRoundedRect
(
glow_rect
,
5
,
5
)
# 5 or 6
# shadow
painter
.
setCompositionMode
(
QPainter
.
CompositionMode_SourceOver
)
if
hoover
:
painter
.
setBrush
(
hoover_color
)
elif
has_focus
:
painter
.
setBrush
(
focus_color
)
else
:
blend
=
QLinearGradient
(
shadow_rect
.
topLeft
(),
shadow_rect
.
bottomLeft
())
blend
.
setColorAt
(
0.00
,
self
.
color_with_alpha
(
shadow_color
,
0x10
))
blend
.
setColorAt
(
1.00
,
self
.
color_with_alpha
(
shadow_color
,
0x80
))
painter
.
setBrush
(
blend
)
painter
.
drawRoundedRect
(
shadow_rect
,
4
,
4
)
# 4 or 5
# border
painter
.
setCompositionMode
(
QPainter
.
CompositionMode_Source
)
blend
=
QLinearGradient
(
border_rect
.
topLeft
(),
border_rect
.
bottomLeft
())
blend
.
setColorAt
(
0.0
,
border_color_top
)
blend
.
setColorAt
(
1.0
,
border_color_bottom
)
painter
.
setBrush
(
blend
)
painter
.
drawRoundedRect
(
border_rect
,
4
,
4
)
# content
painter
.
setCompositionMode
(
QPainter
.
CompositionMode_Source
)
grad
=
QLinearGradient
(
content_rect
.
topLeft
(),
content_rect
.
bottomLeft
())
grad
.
setColorAt
(
0.0
,
self
.
background_top_color
(
color
))
grad
.
setColorAt
(
1.0
,
self
.
background_bottom_color
(
color
))
painter
.
setBrush
(
QBrush
(
grad
))
painter
.
drawRoundedRect
(
content_rect
,
4
,
4
)
def
drawToolButtonSunkenBezel
(
self
,
painter
,
rect
,
color
):
painter
.
setRenderHint
(
QPainter
.
Antialiasing
,
True
)
painter
.
setPen
(
Qt
.
NoPen
)
hole_rect
=
rect
.
adjusted
(
1
,
1
,
-
1
,
-
1
)
shadow_rect
=
rect
.
adjusted
(
2
,
2
,
-
2
,
-
2
)
content_rect
=
rect
.
adjusted
(
3
,
3
,
-
3
,
-
3
)
shade_color
=
ColorScheme
.
shade
(
self
.
background_bottom_color
(
color
),
ColorScheme
.
MidlightShade
,
0.5
)
shadow_color
=
ColorScheme
.
shade
(
self
.
background_bottom_color
(
color
),
ColorScheme
.
ShadowShade
,
0.0
)
if
self
.
calc_shadow_color
(
color
)
.
value
()
>
color
.
value
():
content_grad
=
QLinearGradient
(
0
,
content_rect
.
top
(),
0
,
content_rect
.
bottom
()
+
content_rect
.
height
()
*
0.2
)
content_grad
.
setColorAt
(
0.0
,
self
.
background_bottom_color
(
color
))
content_grad
.
setColorAt
(
1.0
,
self
.
background_top_color
(
color
))
else
:
content_grad
=
QLinearGradient
(
0
,
content_rect
.
top
()
-
content_rect
.
height
()
*
0.2
,
0
,
content_rect
.
bottom
())
content_grad
.
setColorAt
(
0.0
,
self
.
background_top_color
(
color
))
content_grad
.
setColorAt
(
1.0
,
self
.
background_bottom_color
(
color
))
# hole edge
painter
.
setCompositionMode
(
QPainter
.
CompositionMode_SourceOver
)
blend
=
QLinearGradient
(
hole_rect
.
topLeft
(),
hole_rect
.
bottomLeft
())
blend
.
setColorAt
(
0.0
,
self
.
color_with_alpha
(
shadow_color
,
0x80
))
blend
.
setColorAt
(
1.0
,
self
.
color_with_alpha
(
shadow_color
,
0x20
))
painter
.
setBrush
(
blend
)
painter
.
drawRoundedRect
(
hole_rect
,
4
,
4
)
# 4 or 5
# shadow
painter
.
setCompositionMode
(
QPainter
.
CompositionMode_Source
)
painter
.
setBrush
(
content_grad
)
painter
.
drawRoundedRect
(
shadow_rect
,
4
,
4
)
# 5 or 6
painter
.
setCompositionMode
(
QPainter
.
CompositionMode_SourceOver
)
blend
=
QLinearGradient
(
shadow_rect
.
topLeft
(),
shadow_rect
.
bottomLeft
())
blend
.
setColorAt
(
0.0
,
self
.
color_with_alpha
(
shadow_color
,
0x40
))
blend
.
setColorAt
(
0.1
,
self
.
color_with_alpha
(
shadow_color
,
0x07
))
blend
.
setColorAt
(
0.9
,
self
.
color_with_alpha
(
shadow_color
,
0x07
))
blend
.
setColorAt
(
1.0
,
shade_color
)
painter
.
setBrush
(
blend
)
painter
.
drawRoundedRect
(
shadow_rect
,
4
,
4
)
# 5 or 6
# content
painter
.
setCompositionMode
(
QPainter
.
CompositionMode_Source
)
painter
.
setBrush
(
content_grad
)
painter
.
drawRoundedRect
(
content_rect
,
4
,
4
)
def
drawToolButtonMenuIndicator
(
self
,
option
,
painter
,
widget
=
None
):
arrow_rect
=
self
.
proxy
()
.
subControlRect
(
QStyle
.
CC_ToolButton
,
option
,
QStyle
.
SC_ToolButtonMenu
,
widget
)
text_color
=
option
.
palette
.
color
(
QPalette
.
WindowText
if
option
.
state
&
QStyle
.
State_AutoRaise
else
QPalette
.
ButtonText
)
button_color
=
option
.
palette
.
color
(
QPalette
.
Button
)
background_color
=
self
.
background_color
(
button_color
,
0.5
)
painter
.
save
()
# draw separating vertical line
if
option
.
state
&
(
QStyle
.
State_On
|
QStyle
.
State_Sunken
):
top_offset
,
bottom_offset
=
4
,
3
else
:
top_offset
,
bottom_offset
=
2
,
2
if
option
.
direction
==
Qt
.
LeftToRight
:
separator_line
=
QLineF
(
arrow_rect
.
x
()
-
3
,
arrow_rect
.
top
()
+
top_offset
,
arrow_rect
.
x
()
-
3
,
arrow_rect
.
bottom
()
-
bottom_offset
)
else
:
separator_line
=
QLineF
(
arrow_rect
.
right
()
+
3
,
arrow_rect
.
top
()
+
top_offset
,
arrow_rect
.
right
()
+
3
,
arrow_rect
.
bottom
()
-
bottom_offset
)
light_gradient
=
QLinearGradient
(
separator_line
.
p1
(),
separator_line
.
p2
())
light_gradient
.
setColorAt
(
0.0
,
ColorScheme
.
shade
(
self
.
background_top_color
(
button_color
),
ColorScheme
.
LightShade
,
0.0
))
light_gradient
.
setColorAt
(
1.0
,
ColorScheme
.
shade
(
self
.
background_bottom_color
(
button_color
),
ColorScheme
.
MidlightShade
,
0.5
))
separator_color
=
ColorScheme
.
shade
(
self
.
background_bottom_color
(
button_color
),
ColorScheme
.
MidShade
,
0.0
)
painter
.
setRenderHint
(
QPainter
.
Antialiasing
,
False
)
painter
.
setPen
(
QPen
(
light_gradient
,
1
))
painter
.
drawLine
(
separator_line
.
translated
(
-
1
,
0
))
painter
.
drawLine
(
separator_line
.
translated
(
+
1
,
0
))
painter
.
setPen
(
QPen
(
separator_color
,
1
))
painter
.
drawLine
(
separator_line
)
# draw arrow
arrow
=
QPolygonF
([
QPointF
(
-
3
,
-
1.5
),
QPointF
(
0.5
,
2.5
),
QPointF
(
4
,
-
1.5
)])
if
option
.
direction
==
Qt
.
LeftToRight
:
arrow
.
translate
(
-
2
,
1
)
else
:
arrow
.
translate
(
+
2
,
1
)
pen_thickness
=
1.6
painter
.
setRenderHint
(
QPainter
.
Antialiasing
,
True
)
painter
.
translate
(
arrow_rect
.
center
())
painter
.
translate
(
0
,
+
1
)
painter
.
setPen
(
QPen
(
self
.
calc_light_color
(
background_color
),
pen_thickness
,
Qt
.
SolidLine
,
Qt
.
RoundCap
,
Qt
.
RoundJoin
))
painter
.
drawPolyline
(
arrow
)
painter
.
translate
(
0
,
-
1
)
painter
.
setPen
(
QPen
(
self
.
deco_color
(
background_color
,
text_color
),
pen_thickness
,
Qt
.
SolidLine
,
Qt
.
RoundCap
,
Qt
.
RoundJoin
))
painter
.
drawPolyline
(
arrow
)
painter
.
restore
()
def
drawToolButtonContent
(
self
,
option
,
painter
,
widget
):
if
option
.
state
&
QStyle
.
State_Enabled
:
pixmap
=
widget
.
pixmap
(
QIcon
.
Normal
)
else
:
pixmap
=
widget
.
pixmap
(
QIcon
.
Disabled
)
if
not
pixmap
.
isNull
():
margin
=
self
.
_pixel_metrics
[
QStyle
.
PM_DefaultFrameWidth
]
+
self
.
_pixel_metrics
[
QStyle
.
PM_ButtonMargin
]
if
option
.
features
&
QStyleOptionToolButton
.
MenuButtonPopup
and
option
.
direction
==
Qt
.
LeftToRight
:
right_offset
=
1
else
:
right_offset
=
0
content_rect
=
QRectF
(
self
.
proxy
()
.
subControlRect
(
QStyle
.
CC_ToolButton
,
option
,
QStyle
.
SC_ToolButton
,
widget
))
.
adjusted
(
margin
,
margin
,
-
margin
-
right_offset
,
-
margin
)
pixmap_rect
=
QRectF
(
pixmap
.
rect
())
pixmap_rect
.
moveCenter
(
content_rect
.
center
())
painter
.
setRenderHint
(
QPainter
.
Antialiasing
,
True
)
painter
.
setCompositionMode
(
QPainter
.
CompositionMode_SourceOver
)
painter
.
drawPixmap
(
pixmap_rect
.
topLeft
(),
pixmap
)
# Color helpers
@
cache_result
(
color_key
)
def
low_threshold
(
self
,
color
):
darker
=
ColorScheme
.
shade
(
color
,
ColorScheme
.
MidShade
,
0.5
)
return
ColorUtils
.
luma
(
darker
)
>
ColorUtils
.
luma
(
color
)
@
cache_result
(
color_key
)
def
high_threshold
(
self
,
color
):
lighter
=
ColorScheme
.
shade
(
color
,
ColorScheme
.
LightShade
,
0.5
)
return
ColorUtils
.
luma
(
lighter
)
<
ColorUtils
.
luma
(
color
)
@
cache_result
(
color_key
)
def
background_top_color
(
self
,
color
):
if
self
.
low_threshold
(
color
):
return
ColorScheme
.
shade
(
color
,
ColorScheme
.
MidlightShade
,
0.0
)
else
:
other_luma
=
ColorUtils
.
luma
(
ColorScheme
.
shade
(
color
,
ColorScheme
.
LightShade
,
0.0
))
color_luma
=
ColorUtils
.
luma
(
color
)
return
ColorUtils
.
shade
(
color
,
(
other_luma
-
color_luma
)
*
self
.
_bgcontrast
)
@
cache_result
(
color_key
)
def
background_bottom_color
(
self
,
color
):
if
self
.
low_threshold
(
color
):
return
ColorScheme
.
shade
(
color
,
ColorScheme
.
MidShade
,
0.0
)
else
:
other_luma
=
ColorUtils
.
luma
(
ColorScheme
.
shade
(
color
,
ColorScheme
.
MidShade
,
0.0
))
color_luma
=
ColorUtils
.
luma
(
color
)
return
ColorUtils
.
shade
(
color
,
(
other_luma
-
color_luma
)
*
self
.
_bgcontrast
)
@
cache_result
(
color_key
)
def
calc_light_color
(
self
,
color
):
if
self
.
high_threshold
(
color
):
return
color
else
:
return
ColorScheme
.
shade
(
color
,
ColorScheme
.
LightShade
,
self
.
_contrast
)
@
cache_result
(
color_key
)
def
calc_dark_color
(
self
,
color
):
if
self
.
low_threshold
(
color
):
return
ColorUtils
.
mix
(
self
.
calc_light_color
(
color
),
color
,
0.3
+
0.7
*
self
.
_contrast
)
else
:
return
ColorScheme
.
shade
(
color
,
ColorScheme
.
MidShade
,
self
.
_contrast
)
@
cache_result
(
color_key
)
def
calc_shadow_color
(
self
,
color
):
if
self
.
low_threshold
(
color
):
shadow_color
=
ColorUtils
.
mix
(
Qt
.
black
,
color
,
color
.
alphaF
())
else
:
shadow_color
=
ColorScheme
.
shade
(
ColorUtils
.
mix
(
Qt
.
black
,
color
,
color
.
alphaF
()),
ColorScheme
.
ShadowShade
,
self
.
_contrast
)
shadow_color
.
setAlpha
(
color
.
alpha
())
# make sure shadow color has the same alpha channel as the input
return
shadow_color
@
cache_result
(
color_ratio_key
)
def
background_color
(
self
,
color
,
ratio
):
if
ratio
<
0.5
:
return
ColorUtils
.
mix
(
self
.
background_top_color
(
color
),
color
,
2.0
*
ratio
)
else
:
return
ColorUtils
.
mix
(
color
,
self
.
background_bottom_color
(
color
),
2.0
*
ratio
-
1
)
@
cache_result
(
background_color_key
)
def
deco_color
(
self
,
background
,
color
):
return
ColorUtils
.
mix
(
background
,
color
,
0.4
+
0.8
*
self
.
_contrast
)
def
color_with_alpha
(
self
,
color
,
alpha
):
color
=
QColor
(
color
)
color
.
setAlpha
(
alpha
)
return
color
def
alpha_color
(
self
,
color
,
alpha
):
if
0.0
<=
alpha
<
1.0
:
color
.
setAlphaF
(
alpha
*
color
.
alphaF
())
return
color
class
StateButton
(
QToolButton
):
default_color
=
QColor
(
'#efedeb'
)
def
__init__
(
self
,
parent
=
None
):
super
(
StateButton
,
self
)
.
__init__
(
parent
)
self
.
setPopupMode
(
QToolButton
.
MenuButtonPopup
)
self
.
setToolButtonStyle
(
Qt
.
ToolButtonIconOnly
)
palette
=
self
.
palette
()
palette
.
setColor
(
QPalette
.
Button
,
self
.
default_color
)
self
.
setPalette
(
palette
)
self
.
setStyle
(
StateButtonStyle
())
def
pixmap
(
self
,
mode
=
QIcon
.
Normal
,
state
=
QIcon
.
Off
):
pixmap
=
self
.
icon
()
.
pixmap
(
self
.
iconSize
(),
mode
,
state
)
if
pixmap
.
isNull
():
return
pixmap
size
=
max
(
pixmap
.
width
(),
pixmap
.
height
())
offset_x
=
(
size
-
pixmap
.
width
())
/
2
offset_y
=
(
size
-
pixmap
.
height
())
/
2
new_pixmap
=
QPixmap
(
size
,
size
)
new_pixmap
.
fill
(
Qt
.
transparent
)
path
=
QPainterPath
()
path
.
addRoundedRect
(
0
,
0
,
size
,
size
,
3.7
,
3.7
)
painter
=
QPainter
(
new_pixmap
)
painter
.
setRenderHint
(
QPainter
.
Antialiasing
,
True
)
painter
.
setCompositionMode
(
QPainter
.
CompositionMode_SourceOver
)
painter
.
setClipPath
(
path
)
painter
.
drawPixmap
(
offset_x
,
offset_y
,
pixmap
)
painter
.
end
()
return
new_pixmap
class
PresenceState
(
object
):
def
__init__
(
self
,
name
,
color
,
icon
):
self
.
name
=
name
self
.
color
=
color
self
.
icon
=
icon
def
__repr__
(
self
):
return
self
.
name
class
AccountState
(
StateButton
):
Invisible
=
PresenceState
(
'Invisible'
,
'#efedeb'
,
Resources
.
get
(
'icons/state-invisible.svg'
))
Available
=
PresenceState
(
'Available'
,
'#00ff00'
,
Resources
.
get
(
'icons/state-available.svg'
))
Away
=
PresenceState
(
'Away'
,
'#ffff00'
,
Resources
.
get
(
'icons/state-away.svg'
))
Busy
=
PresenceState
(
'Busy'
,
'#ff0000'
,
Resources
.
get
(
'icons/state-busy.svg'
))
stateChanged
=
pyqtSignal
(
QAction
)
history_size
=
7
def
__init__
(
self
,
parent
=
None
):
super
(
AccountState
,
self
)
.
__init__
(
parent
)
menu
=
QMenu
(
self
)
for
state
in
(
self
.
Available
,
self
.
Away
,
self
.
Busy
,
self
.
Invisible
):
action
=
menu
.
addAction
(
QIcon
(
state
.
icon
),
state
.
name
)
action
.
state
=
state
action
.
note
=
None
menu
.
addSeparator
()
menu
.
triggered
.
connect
(
self
.
_SH_MenuTriggered
)
self
.
setMenu
(
menu
)
self
.
state
=
self
.
Invisible
def
_SH_MenuTriggered
(
self
,
action
):
if
hasattr
(
action
,
'state'
):
self
.
setState
(
action
.
state
,
action
.
note
)
self
.
stateChanged
.
emit
(
action
)
def
setState
(
self
,
state
,
note
=
None
):
self
.
state
=
state
palette
=
self
.
palette
()
palette
.
setColor
(
QPalette
.
Button
,
QColor
(
state
.
color
))
self
.
setPalette
(
palette
)
if
not
note
:
return
menu
=
self
.
menu
()
actions
=
menu
.
actions
()[
5
:]
try
:
action
=
next
(
action
for
action
in
actions
if
action
.
state
is
state
and
action
.
note
==
note
)
except
StopIteration
:
action
=
QAction
(
QIcon
(
state
.
icon
),
note
,
menu
)
if
len
(
actions
)
==
0
:
menu
.
addAction
(
action
)
else
:
if
len
(
actions
)
>=
self
.
history_size
:
menu
.
removeAction
(
actions
[
-
1
])
menu
.
insertAction
(
actions
[
0
],
action
)
action
.
state
=
state
action
.
note
=
note
else
:
if
action
is
not
actions
[
0
]:
menu
.
removeAction
(
action
)
menu
.
insertAction
(
actions
[
0
],
action
)
resources/icons/state-available.svg
0 → 100644
View file @
6ddd6758
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
version=
"1.1"
id=
"Layer_1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
x=
"0px"
y=
"0px"
width=
"16px"
height=
"16px"
viewBox=
"0 0 16 16"
enable-background=
"new 0 0 16 16"
xml:space=
"preserve"
>
<path
fill=
"#00FF00"
stroke=
"#00A000"
d=
"M15.5,8c0,2.453-1.357,4.44-3.033,4.44H3.534C1.857,12.44,0.5,10.453,0.5,8l0,0
c0-2.453,1.357-4.44,3.034-4.44h8.933C14.143,3.56,15.5,5.547,15.5,8L15.5,8z"
/>
</svg>
resources/icons/state-away.svg
0 → 100644
View file @
6ddd6758
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
version=
"1.1"
id=
"Layer_1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
x=
"0px"
y=
"0px"
width=
"16px"
height=
"16px"
viewBox=
"0 0 16 16"
enable-background=
"new 0 0 16 16"
xml:space=
"preserve"
>
<path
fill=
"#FFF000"
stroke=
"#D0A000"
d=
"M15.5,8c0,2.453-1.357,4.44-3.033,4.44H3.534C1.857,12.44,0.5,10.453,0.5,8l0,0
c0-2.453,1.357-4.44,3.034-4.44h8.933C14.143,3.56,15.5,5.547,15.5,8L15.5,8z"
/>
</svg>
resources/icons/state-busy.svg
0 → 100644
View file @
6ddd6758
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
version=
"1.1"
id=
"Layer_1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
x=
"0px"
y=
"0px"
width=
"16px"
height=
"16px"
viewBox=
"0 0 16 16"
enable-background=
"new 0 0 16 16"
xml:space=
"preserve"
>
<path
fill=
"#FF0000"
stroke=
"#800000"
d=
"M15.5,8c0,2.453-1.357,4.44-3.033,4.44H3.534C1.857,12.44,0.5,10.453,0.5,8l0,0
c0-2.453,1.357-4.44,3.034-4.44h8.933C14.143,3.56,15.5,5.547,15.5,8L15.5,8z"
/>
</svg>
resources/icons/state-invisible.svg
0 → 100644
View file @
6ddd6758
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
version=
"1.1"
id=
"Layer_1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
x=
"0px"
y=
"0px"
width=
"16px"
height=
"16px"
viewBox=
"0 0 16 16"
enable-background=
"new 0 0 16 16"
xml:space=
"preserve"
>
<path
fill=
"#D0D0D0"
stroke=
"#606060"
fill-opacity=
"1"
d=
"M15.5,8c0,2.453-1.357,4.44-3.033,4.44H3.534C1.857,12.44,0.5,10.453,0.5,8l0,0
c0-2.453,1.357-4.44,3.034-4.44h8.933C14.143,3.56,15.5,5.547,15.5,8L15.5,8z"
/>
</svg>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment