py: cam: Convert to PyQt6
diff mbox series

Message ID 20240812145034.190342-1-tomi.valkeinen@ideasonboard.com
State Accepted
Commit 15a51caae8811817f55af0a925915d8fa45ca7a4
Headers show
Series
  • py: cam: Convert to PyQt6
Related show

Commit Message

Tomi Valkeinen Aug. 12, 2024, 2:50 p.m. UTC
Perhaps it's time... Convert the py cam tool to PyQt6.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 src/py/cam/cam_qt.py   |  6 +++---
 src/py/cam/cam_qtgl.py | 12 ++++++------
 2 files changed, 9 insertions(+), 9 deletions(-)

Comments

Laurent Pinchart Aug. 12, 2024, 4:10 p.m. UTC | #1
Hi Tomi,

Thank you for the patch.

On Mon, Aug 12, 2024 at 05:50:34PM +0300, Tomi Valkeinen wrote:
> Perhaps it's time... Convert the py cam tool to PyQt6.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> ---
>  src/py/cam/cam_qt.py   |  6 +++---
>  src/py/cam/cam_qtgl.py | 12 ++++++------
>  2 files changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py
> index c1723b44..22d8c4da 100644
> --- a/src/py/cam/cam_qt.py
> +++ b/src/py/cam/cam_qt.py
> @@ -2,7 +2,7 @@
>  # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>  
>  from helpers import mfb_to_rgb
> -from PyQt5 import QtCore, QtGui, QtWidgets
> +from PyQt6 import QtCore, QtGui, QtWidgets
>  import libcamera as libcam
>  import libcamera.utils
>  import sys
> @@ -63,10 +63,10 @@ class QtRenderer:
>          self.buf_mmap_map = buf_mmap_map
>  
>      def run(self):
> -        camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Read)
> +        camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Type.Read)
>          camnotif.activated.connect(lambda _: self.readcam())
>  
> -        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Read)
> +        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Type.Read)

PyQt5 also defines the Read type in QtCore.QSocketNotifier.Type, so this
code is compatible with both Python versions.

>          keynotif.activated.connect(lambda _: self.readkey())
>  
>          print('Capturing...')
> diff --git a/src/py/cam/cam_qtgl.py b/src/py/cam/cam_qtgl.py
> index 6cfbd347..35b4b06b 100644
> --- a/src/py/cam/cam_qtgl.py
> +++ b/src/py/cam/cam_qtgl.py
> @@ -1,8 +1,8 @@
>  # SPDX-License-Identifier: GPL-2.0-or-later
>  # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>  
> -from PyQt5 import QtCore, QtWidgets
> -from PyQt5.QtCore import Qt
> +from PyQt6 import QtCore, QtWidgets
> +from PyQt6.QtCore import Qt
>  
>  import math
>  import os
> @@ -142,10 +142,10 @@ class QtRenderer:
>          self.window = window
>  
>      def run(self):
> -        camnotif = QtCore.QSocketNotifier(self.state.cm.event_fd, QtCore.QSocketNotifier.Read)
> +        camnotif = QtCore.QSocketNotifier(self.state.cm.event_fd, QtCore.QSocketNotifier.Type.Read)
>          camnotif.activated.connect(lambda _: self.readcam())
>  
> -        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Read)
> +        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Type.Read)
>          keynotif.activated.connect(lambda _: self.readkey())
>  
>          print('Capturing...')
> @@ -175,8 +175,8 @@ class MainWindow(QtWidgets.QWidget):
>      def __init__(self, state):
>          super().__init__()
>  
> -        self.setAttribute(Qt.WA_PaintOnScreen)
> -        self.setAttribute(Qt.WA_NativeWindow)
> +        self.setAttribute(Qt.WidgetAttribute.WA_PaintOnScreen)
> +        self.setAttribute(Qt.WidgetAttribute.WA_NativeWindow)

This works with PyQt5 too.

Should we try to keep Qt5 compatibility with

try:
    from PyQt6 import QtCore, QtWidgets
    from PyQt6.QtCore import Qt
except:
    from PyQt5 import QtCore, QtWidgets
    from PyQt5.QtCore import Qt

?

>  
>          self.state = state
>
Tomi Valkeinen Aug. 12, 2024, 4:23 p.m. UTC | #2
Hi,

On 12/08/2024 19:10, Laurent Pinchart wrote:
> Hi Tomi,
> 
> Thank you for the patch.
> 
> On Mon, Aug 12, 2024 at 05:50:34PM +0300, Tomi Valkeinen wrote:
>> Perhaps it's time... Convert the py cam tool to PyQt6.
>>
>> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>> ---
>>   src/py/cam/cam_qt.py   |  6 +++---
>>   src/py/cam/cam_qtgl.py | 12 ++++++------
>>   2 files changed, 9 insertions(+), 9 deletions(-)
>>
>> diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py
>> index c1723b44..22d8c4da 100644
>> --- a/src/py/cam/cam_qt.py
>> +++ b/src/py/cam/cam_qt.py
>> @@ -2,7 +2,7 @@
>>   # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>>   
>>   from helpers import mfb_to_rgb
>> -from PyQt5 import QtCore, QtGui, QtWidgets
>> +from PyQt6 import QtCore, QtGui, QtWidgets
>>   import libcamera as libcam
>>   import libcamera.utils
>>   import sys
>> @@ -63,10 +63,10 @@ class QtRenderer:
>>           self.buf_mmap_map = buf_mmap_map
>>   
>>       def run(self):
>> -        camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Read)
>> +        camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Type.Read)
>>           camnotif.activated.connect(lambda _: self.readcam())
>>   
>> -        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Read)
>> +        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Type.Read)
> 
> PyQt5 also defines the Read type in QtCore.QSocketNotifier.Type, so this
> code is compatible with both Python versions.
> 
>>           keynotif.activated.connect(lambda _: self.readkey())
>>   
>>           print('Capturing...')
>> diff --git a/src/py/cam/cam_qtgl.py b/src/py/cam/cam_qtgl.py
>> index 6cfbd347..35b4b06b 100644
>> --- a/src/py/cam/cam_qtgl.py
>> +++ b/src/py/cam/cam_qtgl.py
>> @@ -1,8 +1,8 @@
>>   # SPDX-License-Identifier: GPL-2.0-or-later
>>   # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
>>   
>> -from PyQt5 import QtCore, QtWidgets
>> -from PyQt5.QtCore import Qt
>> +from PyQt6 import QtCore, QtWidgets
>> +from PyQt6.QtCore import Qt
>>   
>>   import math
>>   import os
>> @@ -142,10 +142,10 @@ class QtRenderer:
>>           self.window = window
>>   
>>       def run(self):
>> -        camnotif = QtCore.QSocketNotifier(self.state.cm.event_fd, QtCore.QSocketNotifier.Read)
>> +        camnotif = QtCore.QSocketNotifier(self.state.cm.event_fd, QtCore.QSocketNotifier.Type.Read)
>>           camnotif.activated.connect(lambda _: self.readcam())
>>   
>> -        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Read)
>> +        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Type.Read)
>>           keynotif.activated.connect(lambda _: self.readkey())
>>   
>>           print('Capturing...')
>> @@ -175,8 +175,8 @@ class MainWindow(QtWidgets.QWidget):
>>       def __init__(self, state):
>>           super().__init__()
>>   
>> -        self.setAttribute(Qt.WA_PaintOnScreen)
>> -        self.setAttribute(Qt.WA_NativeWindow)
>> +        self.setAttribute(Qt.WidgetAttribute.WA_PaintOnScreen)
>> +        self.setAttribute(Qt.WidgetAttribute.WA_NativeWindow)
> 
> This works with PyQt5 too.
> 
> Should we try to keep Qt5 compatibility with
> 
> try:
>      from PyQt6 import QtCore, QtWidgets
>      from PyQt6.QtCore import Qt
> except:
>      from PyQt5 import QtCore, QtWidgets
>      from PyQt5.QtCore import Qt

Will someone maintain and test the Qt5 version? Does libcamera elsewhere 
support both Qt5 and Qt6?

I don't mind the few lines above, but I fear supporting Qt5 could easily 
become a hindrance for no benefit, as (afaiu) Qt5 is already end of 
life. Are there users out there who need cam.py and can't install Qt6?

  Tomi
Kieran Bingham Aug. 12, 2024, 4:29 p.m. UTC | #3
Quoting Laurent Pinchart (2024-08-12 17:10:52)
> Hi Tomi,
> 
> Thank you for the patch.
> 
> On Mon, Aug 12, 2024 at 05:50:34PM +0300, Tomi Valkeinen wrote:
> > Perhaps it's time... Convert the py cam tool to PyQt6.
> > 

I would probably say :

"""
QT5 is now end of life. The libcamera 'qcam' application has removed
support for QT5, and updated to QT6.

Update the python 'cam' QT implementation accordingly to QT6.

QT5 support is kept as backwards compatibilty if QT6 is not found.
"""

With the last sentence being dependant upon the question below :D


> > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> > ---
> >  src/py/cam/cam_qt.py   |  6 +++---
> >  src/py/cam/cam_qtgl.py | 12 ++++++------
> >  2 files changed, 9 insertions(+), 9 deletions(-)
> > 
> > diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py
> > index c1723b44..22d8c4da 100644
> > --- a/src/py/cam/cam_qt.py
> > +++ b/src/py/cam/cam_qt.py
> > @@ -2,7 +2,7 @@
> >  # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> >  
> >  from helpers import mfb_to_rgb
> > -from PyQt5 import QtCore, QtGui, QtWidgets
> > +from PyQt6 import QtCore, QtGui, QtWidgets
> >  import libcamera as libcam
> >  import libcamera.utils
> >  import sys
> > @@ -63,10 +63,10 @@ class QtRenderer:
> >          self.buf_mmap_map = buf_mmap_map
> >  
> >      def run(self):
> > -        camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Read)
> > +        camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Type.Read)
> >          camnotif.activated.connect(lambda _: self.readcam())
> >  
> > -        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Read)
> > +        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Type.Read)
> 
> PyQt5 also defines the Read type in QtCore.QSocketNotifier.Type, so this
> code is compatible with both Python versions.
> 
> >          keynotif.activated.connect(lambda _: self.readkey())
> >  
> >          print('Capturing...')
> > diff --git a/src/py/cam/cam_qtgl.py b/src/py/cam/cam_qtgl.py
> > index 6cfbd347..35b4b06b 100644
> > --- a/src/py/cam/cam_qtgl.py
> > +++ b/src/py/cam/cam_qtgl.py
> > @@ -1,8 +1,8 @@
> >  # SPDX-License-Identifier: GPL-2.0-or-later
> >  # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> >  
> > -from PyQt5 import QtCore, QtWidgets
> > -from PyQt5.QtCore import Qt
> > +from PyQt6 import QtCore, QtWidgets
> > +from PyQt6.QtCore import Qt
> >  
> >  import math
> >  import os
> > @@ -142,10 +142,10 @@ class QtRenderer:
> >          self.window = window
> >  
> >      def run(self):
> > -        camnotif = QtCore.QSocketNotifier(self.state.cm.event_fd, QtCore.QSocketNotifier.Read)
> > +        camnotif = QtCore.QSocketNotifier(self.state.cm.event_fd, QtCore.QSocketNotifier.Type.Read)
> >          camnotif.activated.connect(lambda _: self.readcam())
> >  
> > -        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Read)
> > +        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Type.Read)
> >          keynotif.activated.connect(lambda _: self.readkey())
> >  
> >          print('Capturing...')
> > @@ -175,8 +175,8 @@ class MainWindow(QtWidgets.QWidget):
> >      def __init__(self, state):
> >          super().__init__()
> >  
> > -        self.setAttribute(Qt.WA_PaintOnScreen)
> > -        self.setAttribute(Qt.WA_NativeWindow)
> > +        self.setAttribute(Qt.WidgetAttribute.WA_PaintOnScreen)
> > +        self.setAttribute(Qt.WidgetAttribute.WA_NativeWindow)
> 
> This works with PyQt5 too.
> 
> Should we try to keep Qt5 compatibility with
> 
> try:
>     from PyQt6 import QtCore, QtWidgets
>     from PyQt6.QtCore import Qt
> except:
>     from PyQt5 import QtCore, QtWidgets
>     from PyQt5.QtCore import Qt
> 
> ?

We've completely dropped QT5 from the list of requirements for qcam, and
only support QT6 for that now, so I don't think this is 'required'.

However - that's very "lightweight" to support Qt5.. so I don't object.


Anyway, definitely time to move this to QT6...

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

--
Kieran


> 
> >  
> >          self.state = state
> >  
> 
> -- 
> Regards,
> 
> Laurent Pinchart
Laurent Pinchart Aug. 12, 2024, 4:42 p.m. UTC | #4
On Mon, Aug 12, 2024 at 07:23:08PM +0300, Tomi Valkeinen wrote:
> On 12/08/2024 19:10, Laurent Pinchart wrote:
> > On Mon, Aug 12, 2024 at 05:50:34PM +0300, Tomi Valkeinen wrote:
> >> Perhaps it's time... Convert the py cam tool to PyQt6.
> >>
> >> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> >> ---
> >>   src/py/cam/cam_qt.py   |  6 +++---
> >>   src/py/cam/cam_qtgl.py | 12 ++++++------
> >>   2 files changed, 9 insertions(+), 9 deletions(-)
> >>
> >> diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py
> >> index c1723b44..22d8c4da 100644
> >> --- a/src/py/cam/cam_qt.py
> >> +++ b/src/py/cam/cam_qt.py
> >> @@ -2,7 +2,7 @@
> >>   # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> >>   
> >>   from helpers import mfb_to_rgb
> >> -from PyQt5 import QtCore, QtGui, QtWidgets
> >> +from PyQt6 import QtCore, QtGui, QtWidgets
> >>   import libcamera as libcam
> >>   import libcamera.utils
> >>   import sys
> >> @@ -63,10 +63,10 @@ class QtRenderer:
> >>           self.buf_mmap_map = buf_mmap_map
> >>   
> >>       def run(self):
> >> -        camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Read)
> >> +        camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Type.Read)
> >>           camnotif.activated.connect(lambda _: self.readcam())
> >>   
> >> -        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Read)
> >> +        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Type.Read)
> > 
> > PyQt5 also defines the Read type in QtCore.QSocketNotifier.Type, so this
> > code is compatible with both Python versions.
> > 
> >>           keynotif.activated.connect(lambda _: self.readkey())
> >>   
> >>           print('Capturing...')
> >> diff --git a/src/py/cam/cam_qtgl.py b/src/py/cam/cam_qtgl.py
> >> index 6cfbd347..35b4b06b 100644
> >> --- a/src/py/cam/cam_qtgl.py
> >> +++ b/src/py/cam/cam_qtgl.py
> >> @@ -1,8 +1,8 @@
> >>   # SPDX-License-Identifier: GPL-2.0-or-later
> >>   # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
> >>   
> >> -from PyQt5 import QtCore, QtWidgets
> >> -from PyQt5.QtCore import Qt
> >> +from PyQt6 import QtCore, QtWidgets
> >> +from PyQt6.QtCore import Qt
> >>   
> >>   import math
> >>   import os
> >> @@ -142,10 +142,10 @@ class QtRenderer:
> >>           self.window = window
> >>   
> >>       def run(self):
> >> -        camnotif = QtCore.QSocketNotifier(self.state.cm.event_fd, QtCore.QSocketNotifier.Read)
> >> +        camnotif = QtCore.QSocketNotifier(self.state.cm.event_fd, QtCore.QSocketNotifier.Type.Read)
> >>           camnotif.activated.connect(lambda _: self.readcam())
> >>   
> >> -        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Read)
> >> +        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Type.Read)
> >>           keynotif.activated.connect(lambda _: self.readkey())
> >>   
> >>           print('Capturing...')
> >> @@ -175,8 +175,8 @@ class MainWindow(QtWidgets.QWidget):
> >>       def __init__(self, state):
> >>           super().__init__()
> >>   
> >> -        self.setAttribute(Qt.WA_PaintOnScreen)
> >> -        self.setAttribute(Qt.WA_NativeWindow)
> >> +        self.setAttribute(Qt.WidgetAttribute.WA_PaintOnScreen)
> >> +        self.setAttribute(Qt.WidgetAttribute.WA_NativeWindow)
> > 
> > This works with PyQt5 too.
> > 
> > Should we try to keep Qt5 compatibility with
> > 
> > try:
> >      from PyQt6 import QtCore, QtWidgets
> >      from PyQt6.QtCore import Qt
> > except:
> >      from PyQt5 import QtCore, QtWidgets
> >      from PyQt5.QtCore import Qt
> 
> Will someone maintain and test the Qt5 version?

Quite unlikely.

> Does libcamera elsewhere support both Qt5 and Qt6?

I think qcam did a hard switch to Qt6.

> I don't mind the few lines above, but I fear supporting Qt5 could easily 
> become a hindrance for no benefit, as (afaiu) Qt5 is already end of 
> life. Are there users out there who need cam.py and can't install Qt6?

I don't want to maintain both versions. I was thinking it could be nice
for users to support both for a transition period, given how easy it is.
As soon as it becomes a burden, or even before that, we can drop Qt5
support. A warning message in the except path above would make sense to
warn users they should migrate.

This being said, given that qcam now requires Qt6, it may make even less
sense to support Qt5 in cam.py. I'll leave the decision to you, either
way,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Patch
diff mbox series

diff --git a/src/py/cam/cam_qt.py b/src/py/cam/cam_qt.py
index c1723b44..22d8c4da 100644
--- a/src/py/cam/cam_qt.py
+++ b/src/py/cam/cam_qt.py
@@ -2,7 +2,7 @@ 
 # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
 
 from helpers import mfb_to_rgb
-from PyQt5 import QtCore, QtGui, QtWidgets
+from PyQt6 import QtCore, QtGui, QtWidgets
 import libcamera as libcam
 import libcamera.utils
 import sys
@@ -63,10 +63,10 @@  class QtRenderer:
         self.buf_mmap_map = buf_mmap_map
 
     def run(self):
-        camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Read)
+        camnotif = QtCore.QSocketNotifier(self.cm.event_fd, QtCore.QSocketNotifier.Type.Read)
         camnotif.activated.connect(lambda _: self.readcam())
 
-        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Read)
+        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Type.Read)
         keynotif.activated.connect(lambda _: self.readkey())
 
         print('Capturing...')
diff --git a/src/py/cam/cam_qtgl.py b/src/py/cam/cam_qtgl.py
index 6cfbd347..35b4b06b 100644
--- a/src/py/cam/cam_qtgl.py
+++ b/src/py/cam/cam_qtgl.py
@@ -1,8 +1,8 @@ 
 # SPDX-License-Identifier: GPL-2.0-or-later
 # Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
 
-from PyQt5 import QtCore, QtWidgets
-from PyQt5.QtCore import Qt
+from PyQt6 import QtCore, QtWidgets
+from PyQt6.QtCore import Qt
 
 import math
 import os
@@ -142,10 +142,10 @@  class QtRenderer:
         self.window = window
 
     def run(self):
-        camnotif = QtCore.QSocketNotifier(self.state.cm.event_fd, QtCore.QSocketNotifier.Read)
+        camnotif = QtCore.QSocketNotifier(self.state.cm.event_fd, QtCore.QSocketNotifier.Type.Read)
         camnotif.activated.connect(lambda _: self.readcam())
 
-        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Read)
+        keynotif = QtCore.QSocketNotifier(sys.stdin.fileno(), QtCore.QSocketNotifier.Type.Read)
         keynotif.activated.connect(lambda _: self.readkey())
 
         print('Capturing...')
@@ -175,8 +175,8 @@  class MainWindow(QtWidgets.QWidget):
     def __init__(self, state):
         super().__init__()
 
-        self.setAttribute(Qt.WA_PaintOnScreen)
-        self.setAttribute(Qt.WA_NativeWindow)
+        self.setAttribute(Qt.WidgetAttribute.WA_PaintOnScreen)
+        self.setAttribute(Qt.WidgetAttribute.WA_NativeWindow)
 
         self.state = state