Implement rename and delete

This commit introduces the ability to rename or delete a light.
There is also a special icon for unreachable lights now.
pull/17/head
Micke Nordin 3年前
コミット 7cfe8049fc
署名者: micke
GPGキーID: 014B273D614BE877

@ -21,10 +21,15 @@ cd tinge
Requires a recent Python3 and pip3, most likely python >= 3.7. It is only tested with 3.9 on PostmarketOS on the PinePhone and on Debian Bullseye though.
## Screenshots
![Discover Bridge View](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/20210506_16h18m26s_grim.png)
![All Bridge View](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/20210506_14h48m15s_grim.png)
![All Group View](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/20210506_14h48m24s_grim.png)
![Single Group View, with Bed Light Off](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/20210506_14h48m30s_grim.png)
![Single Light Off](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/20210506_14h48m34s_grim.png)
![Single Light On](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/20210506_14h48m37s_grim.png)
![Single Group View, with Bed Light On](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/20210506_14h48m48s_grim.png)
![Discover Bridge View](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot1.png)
![All Bridge View](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot2.png)
![All Group View](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot3.png)
![Single Group View, with Some Lights Off, and Roof light unreachable](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot4.png)
![Single Light View, with Bed Lamp Off](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot5.png)
![Single Light View, with Bed Lamp On](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot6.png)
![Single Group View, with Bed Lamp On](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot7.png)
![Rename Bed lamp](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot8.png)
![Single Light View, with Bed Lamp renamed to Table lamp](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot9.png)
![Single Group View, with Bed Lamp renamed to Table lamp](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot10.png)
![Single Light View, with Table lamp Delete modal](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot11.png)
![Single Group View, with Table lamp Deleted](https://code.smolnet.org/micke/tinge/raw/branch/master/screenshots/scrot12.png)

@ -38,6 +38,7 @@ class Hui(wx.Frame):
super().__init__(*args, **kw)
self.m_on_icon: str = ''
self.m_off_icon: str = ''
self.m_unreachable_icon: str = ''
self.m_tinge: Tinge = Tinge()
self.m_bridges: list[HueBridge] = self.m_tinge.get_bridges()
self.cur_bridge: Union[None, HueBridge] = None
@ -114,6 +115,8 @@ class Hui(wx.Frame):
icon: str = self.m_off_icon
if light.is_on():
icon = self.m_on_icon
elif not light.is_reachable():
icon = self.m_unreachable_icon
toggle_btn: wx.Button = wx.Button(self.pnl, label=icon)
inner_sizer.Add(toggle_btn, 1, wx.EXPAND)
self.Bind(wx.EVT_BUTTON,
@ -145,6 +148,8 @@ class Hui(wx.Frame):
icon: str = self.m_off_icon
if is_on:
icon = self.m_on_icon
elif not light.is_reachable():
icon = self.m_unreachable_icon
toggle_btn: wx.Button = wx.Button(self.pnl, label=icon)
self.sizer.Add(toggle_btn, 0, wx.EXPAND)
self.Bind(wx.EVT_BUTTON,
@ -187,6 +192,30 @@ class Hui(wx.Frame):
self.sizer.Add(e_slider, 0, wx.EXPAND)
self.Bind(wx.EVT_SCROLL,
lambda event: self.set_saturation(event, light.get_id()), e_slider)
rename_btn: wx.Button = wx.Button(self.pnl, label="Rename")
self.sizer.Add(rename_btn, 0, wx.EXPAND)
self.Bind(wx.EVT_BUTTON,
lambda event, mlightid=lightid: self.rename_light_and_goto_light(mlightid),
rename_btn)
delete_btn: wx.Button = wx.Button(self.pnl, label="Delete")
self.sizer.Add(delete_btn, 0, wx.EXPAND)
self.Bind(wx.EVT_BUTTON,
lambda event, mlightid=lightid: self.delete_light_and_goto_group(mlightid),
delete_btn)
def delete_light_and_goto_group(self, lightid):
"""Combo call back for delete and goto group
Args:
lightid (int): The light id of the light to delete
"""
if self.get_ok_cancel_answer_from_modal("Are you sure you want to delete this light?"):
light: HueLight = self.cur_bridge.get_light_by_id(lightid)
light.delete()
self.cur_bridge.remove_light(light)
self.add_lights(self.cur_group.get_lights())
else:
self.add_single_light(lightid)
def discover_new_bridges(self):
"""Call back for button that is displayed if no bridges were found
@ -194,6 +223,34 @@ class Hui(wx.Frame):
self.m_tinge.discover_new_bridges()
self.add_bridges()
def get_ok_cancel_answer_from_modal(self, message: str) -> bool:
"""Display a message dialog and return ok or cancel
Args:
message (str): The message to display
Returns:
bool: The response from the user
"""
with wx.MessageDialog(self.pnl, message, style=wx.OK | wx.CANCEL | wx.CANCEL_DEFAULT) as dlg:
return dlg.ShowModal() == wx.ID_OK
def get_text_answer_from_modal(self, message: str, cap: str, val: str = "") -> str:
"""Display a text entry and return the content
Args:
message (str): The message to display
cap (str): The caption to display
val (str, optional): The default value to display, defaults to the empty string
Returns:
str: The response from the user
"""
with wx.TextEntryDialog(self.pnl, message, caption=cap, value=val) as dlg:
dlg.ShowModal()
answer: str = dlg.GetValue()
return answer
def goto_bridge(self, bridge: HueBridge):
"""Call back for a bridge button
@ -217,6 +274,17 @@ class Hui(wx.Frame):
self.cur_group = group
self.add_lights(group.get_lights())
def rename_light_and_goto_light(self, lightid):
"""Combo call back to rename a light and display that light again
Args:
lightid ([type]): The light id of the light to rename/display
"""
newname: str = self.get_text_answer_from_modal("Set new name", "New name:")
if newname:
self.cur_bridge.get_light_by_id(lightid).rename(newname)
self.add_single_light(lightid)
def set_brightness(self, event: wx.ScrollEvent, lightid: int):
"""Call back for brightness slider
@ -283,7 +351,7 @@ class Hui(wx.Frame):
"""Combo call back for toggle and goto group
Args:
lightid (int): The light id oof the light to toggle
lightid (int): The light id of the light to toggle
lights (list[HueLight]): The lights to display after toggle
"""
self.cur_bridge.get_light_by_id(lightid).toggle()

バイナリファイルは表示されません。

変更前

幅:  |  高さ:  |  サイズ: 77 KiB

バイナリファイルは表示されません。

変更前

幅:  |  高さ:  |  サイズ: 79 KiB

バイナリファイルは表示されません。

変更前

幅:  |  高さ:  |  サイズ: 28 KiB

バイナリファイルは表示されません。

変更前

幅:  |  高さ:  |  サイズ: 42 KiB

バイナリファイルは表示されません。

変更前

幅:  |  高さ:  |  サイズ: 79 KiB

変更前

幅:  |  高さ:  |  サイズ: 35 KiB

変更後

幅:  |  高さ:  |  サイズ: 35 KiB

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 64 KiB

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 60 KiB

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 58 KiB

変更前

幅:  |  高さ:  |  サイズ: 29 KiB

変更後

幅:  |  高さ:  |  サイズ: 29 KiB

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 73 KiB

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 64 KiB

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 34 KiB

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 46 KiB

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 64 KiB

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 78 KiB

バイナリファイルは表示されません。

変更後

幅:  |  高さ:  |  サイズ: 46 KiB

@ -190,3 +190,14 @@ class HueBridge:
str: The username
"""
return self.m_username
def remove_light(self, light: HueLight):
"""Remove a light from all groups and self
Args:
light (HueLight): The light to remove
"""
for group in self.m_groups:
group.remove_light(light)
self.m_lights.remove(light)

@ -142,6 +142,12 @@ class HueGroup:
on = True
return on
def remove_light(self, light: HueLight):
"""Remove a light
"""
if light in self.m_lights:
self.m_lights.remove(light)
def toggle(self):
"""Toggle all lights of the group
"""

@ -297,6 +297,14 @@ class HueLight:
"""
return self.get_sat() != -1
def delete(self):
"""Delete the light
"""
method: str = "DELETE"
path = "{}/lights/{}".format(self.m_parent_bridge_user, self.get_id())
make_request(self.m_parent_bridge_ip, path, method)
def get_brightness(self) -> int:
"""Get currrent brightness
@ -362,6 +370,18 @@ class HueLight:
"""
return self.get_state().is_reachable()
def rename(self, name):
"""Set the name of the light
Args:
name (str): The new name for the light
"""
method: str = "PUT"
payload = '{{"name":"{0}"}}'.format(name)
path = "{}/lights/{}".format(self.m_parent_bridge_user, self.get_id())
make_request(self.m_parent_bridge_ip, path, method, payload)
self.update_state()
def set_brightness(self, bri: int):
"""Set the brightness of the light
@ -431,3 +451,4 @@ class HueLight:
path: str = "{}/lights/{}".format(self.m_parent_bridge_user, self.m_id)
response = make_request(self.m_parent_bridge_ip, path)
self.m_state = HueLight.State(json.loads(response.text)['state'])
self.m_name = json.loads(response.text)['name']

読み込み中…
キャンセル
保存