Hello Tycho,

Is there any way we can use the group's info() cmd to output this
> information?
>

Yeah... I have this bad habit of putting __str__'s everywhere.
and using __repr__'s as shorter versions of __str__'s.
I didn't intended them to crawl into the patch. =)
I think you were looking into the first version,
where they are blooming in all their beauty.


Ideally, I'd like to require layouts to implement the serialization
> themselves, so that all this code has to do is call .serialize() or
> something, and all the stack layout code can live in
> /libqtile/layouts/stack.py and nowhere else.
>
> > +                for indx in range(group.layout.num_stacks):
>
> Is it possible to pickle the layouts themselves? I'm not sure how well
> this would work, but it seems like you might not have to do all the
> work you're doing below if you just pickle the layout.
>

I can make .serialize(). That's a clearly cleaner way of doing things.

Pickling layouts themselves was my first thought, but then it didn't quite
work,
so I decided to conform to the existing solution of enumeration everything.
I can look why I couldn't pickle them and try to fix it.
It's indeed seems to be an easier way once it's working.


We need a licensing header on this file if we want to include it in
> tree; distro packaging requires this sort of thing.
>

Yup, there's another version of this code with License.
With regards to this, it might not be necessary to use Ordered Sets if
layouts can be pickled.
However if something goes wrong, my other thought was is to use X11
identifiers for windows to keep track who is who.
Which might be messier, but, anyways, that's too early to talk about it.

Thanks a lot for your input!
Eliza



On Thu, Mar 26, 2015 at 12:14 AM, Tycho Andersen <[email protected]> wrote:

> Hi Eliza,
>
> On Tue, Mar 24, 2015 at 10:36:33PM -0700, Eliza Guseva wrote:
> >
> > >
> > > Ok, great! We have lots of other bugs and oddities, so I'm sure we can
> > > find something :)
> > >
> >
> > I've started filing an application for the D-bus project.
> > However it turned out that for Python Foundation a patch is a
> requirement.
> > So I pushed it a little further and made an experimental fix or the
> layout
> > issue  #372 for the case of stacks
>
> Thanks for taking a look!
>
> > I applied it for the commit 989f0f8534ee2e34e14b8cb02920c861d053d49c
> > And it worked. It has an issue: the windows order is being saved, but
> qtile
> > redraws the correct order sometimes only on-click.
> > Maybe it's due to the method I used, maybe something else.
> > I used OrderedSet class, wich is under MIT license, from here:
> > http://code.activestate.com/recipes/576694-orderedset/
> >
> >
> > I pulled the lateset commit from qtile/qtile in order to test my fix on
> the
> > newer version
> > I've got a message error, when tried to change layouts:
> > ERROR handle_KeyPress:854 KB command error nextlayout: No such command.
>
> Yes, this is due to some deprecated stuff that we (finally) removed;
> it should be next_layout.
>
> > Please apply my patch to 989f0f8534ee2e34e14b8cb02920c861d053d49c
>
> Some comments on the patch below.
>
> Tycho
>
> > diff --git a/libqtile/group.py b/libqtile/group.py
> > index 2203260..82b1d01 100644
> > --- a/libqtile/group.py
> > +++ b/libqtile/group.py
> > @@ -30,6 +30,7 @@ import contextlib
> >  import xcffib
> >  import xcffib.xproto
> >
> > +from . import ordered_set
> >  from . import command
> >  from . import hook
> >  from . import window
> > @@ -45,7 +46,7 @@ class _Group(command.CommandObject):
> >      def __init__(self, name, layout=None):
> >          self.name = name
> >          self.customLayout = layout  # will be set on _configure
> > -        self.windows = set()
> > +        self.windows = ordered_set.OrderedSet([])
> >          self.qtile = None
> >          self.layouts = []
> >          self.floating_layout = None
> > @@ -62,14 +63,37 @@ class _Group(command.CommandObject):
> >          self.screen = None
> >          self.currentLayout = 0
> >          self.focusHistory = []
> > -        self.windows = set()
> > +        self.windows = ordered_set.OrderedSet([])
> >          self.qtile = qtile
> >          self.layouts = [i.clone(self) for i in layouts]
> >          self.floating_layout = floating_layout.clone(self)
> >          if self.customLayout is not None:
> >              self.layout = self.customLayout
> >              self.customLayout = None
> > -
> > +
> > +    def __str__(self):
> > +        output = 'Group named '+str(self.name)
> > +        try:
> > +            output+= ' at the screen '+str(self.screen.index)+'\n'
> > +        except:
> > +            output+= ' at the UNKNOWN screen\n'
> > +        output+='and my attributes are:\n'
> > +        for item in self.__dict__:
> > +            if not (self.__dict__[item] == None):
> > +                output+=('  '+item+'\t'+repr(self.__dict__[item])+'\n')
> > +            else:
> > +                output+=('  '+item)+':\t being
> '+str(self.__dict__[item])+'!\n'
>
> Is there any way we can use the group's info() cmd to output this
> information?
>
> > +        return output
> > +
> > +    def __repr__(self):
>
> __repr__ is supposed to be some python code that could be executed to
> reconstruct the object. The string generated by this doesn't look to
> be valid python, so we should probably just get rid of this method or
> roll it into __str__/info somehow.
>
> > +        output = 'Group named '+str(self.name)
> > +        try:
> > +            output+= ' at the screen '+str(self.screen.index)+'\n'
> > +        except:
> > +            output+= ' at the UNKNOWN screen\n'
> > +        return output
> > +
> >      @property
> >      def currentWindow(self):
> >          try:
> > diff --git a/libqtile/ordered_set.py b/libqtile/ordered_set.py
> > new file mode 100644
> > index 0000000..e2e4156
> > --- /dev/null
> > +++ b/libqtile/ordered_set.py
>
> We need a licensing header on this file if we want to include it in
> tree; distro packaging requires this sort of thing.
>
> > @@ -0,0 +1,67 @@
> > +import collections
> > +
> > +class OrderedSet(collections.MutableSet):
> > +
> > +    def __init__(self, iterable=None):
> > +        self.end = end = []
> > +        end += [None, end, end]         # sentinel node for doubly
> linked list
> > +        self.map = {}                   # key --> [key, prev, next]
> > +        if iterable is not None:
> > +            self |= iterable
> > +
> > +    def __len__(self):
> > +        return len(self.map)
> > +
> > +    def __contains__(self, key):
> > +        return key in self.map
> > +
> > +    def add(self, key):
> > +        if key not in self.map:
> > +            end = self.end
> > +            curr = end[1]
> > +            curr[2] = end[1] = self.map[key] = [key, curr, end]
> > +
> > +    def discard(self, key):
> > +        if key in self.map:
> > +            key, prev, next = self.map.pop(key)
> > +            prev[2] = next
> > +            next[1] = prev
> > +
> > +    def __iter__(self):
> > +        end = self.end
> > +        curr = end[2]
> > +        while curr is not end:
> > +            yield curr[0]
> > +            curr = curr[2]
> > +
> > +    def __reversed__(self):
> > +        end = self.end
> > +        curr = end[1]
> > +        while curr is not end:
> > +            yield curr[0]
> > +            curr = curr[1]
> > +
> > +    def pop(self, last=True):
> > +        if not self:
> > +            raise KeyError('set is empty')
> > +        key = self.end[1][0] if last else self.end[2][0]
> > +        self.discard(key)
> > +        return key
> > +
> > +    def __repr__(self):
> > +        if not self:
> > +            return '%s()' % (self.__class__.__name__,)
> > +        return '%s(%r)' % (self.__class__.__name__, list(self))
> > +
> > +    def __eq__(self, other):
> > +        if isinstance(other, OrderedSet):
> > +            return len(self) == len(other) and list(self) == list(other)
> > +        return set(self) == set(other)
> > +
> > +
> > +if __name__ == '__main__':
> > +    s = OrderedSet('abracadaba')
> > +    t = OrderedSet('simsalabim')
> > +    print(s | t)
> > +    print(s & t)
> > +    print(s - t)
> > \ No newline at end of file
> > diff --git a/libqtile/state.py b/libqtile/state.py
> > index 5438f38..0b750a1 100644
> > --- a/libqtile/state.py
> > +++ b/libqtile/state.py
> > @@ -31,22 +31,59 @@ class QtileState(object):
> >          # configurations.
> >          self.groups = {}
> >          self.screens = {}
> > -
> > +        self.layouts ={}
> > +        self.windows={}
> > +        _windows = {}
> >          for group in qtile.groups:
> > +            #try:
>
> It would be good if we could get rid of all commented out/debugging
> code from the final version of the patch.
>
> > +            self.windows[group.name]=str(group.windows)
> > +            _windows[group.name]=list(group.windows)
> >              self.groups[group.name] = group.layout.name
> > +            qtile.log.info('current layout:\n'+str(group.layout))
> > +            self.layouts[group.name] = {}
> > +            #qtile.log.info(str(
> > +            if group.layout.name == 'stack':
>
> Ideally, I'd like to require layouts to implement the serialization
> themselves, so that all this code has to do is call .serialize() or
> something, and all the stack layout code can live in
> /libqtile/layouts/stack.py and nowhere else.
>
> > +                for indx in range(group.layout.num_stacks):
>
> Is it possible to pickle the layouts themselves? I'm not sure how well
> this would work, but it seems like you might not have to do all the
> work you're doing below if you just pickle the layout.
>
> > +                    currStack = group.layout.stacks[indx]
> > +                    qtile.log.info('indx '+str(indx)+' group.name
> '+str(group.name))
> > +                    self.layouts[group.name][indx]=([],)
> > +                    if not currStack.lst==[]:
> > +                        windowList=[]
> > +                        for window in currStack.lst:
> > +                            qtile.log.info(str(window))
> > +                            windowList.append(
> > +                                _windows[group.name].index(window))
> > +                        currentWindow=\
> > +                            _windows[group.name].index(currStack.cw)
> > +                        self.layouts[group.name
> ][indx]=(windowList,currentWindow)
> > +
> >          for index, screen in enumerate(qtile.screens):
> >              self.screens[index] = screen.group.name
> > -
> > +
> > +    def __str__(self):
> > +        str1= 'My state is:\n'
> > +        str1+='Groups:\t'+str(self.groups)+'\n'
> > +        str1+='Screens:\t'+str(self.screens)+'\n'
> > +        str1+='Stack Layouts:\t'+str(self.layouts)+'\n'
> > +        str1+='Windows:\t'+str(self.windows)+'\n'
> > +        return str1
> > +
> > +    def __repr__(self):
> > +        return self.__str__()
>
> Same thought here about __repr__ vs __str__.
>
> > +
> >      def apply(self, qtile):
> >          """
> >              Rearrange the windows in the specified Qtile object
> according to
> >              this QtileState.
> >          """
> > +        qtile.log.info(str(self))
> >          for (group, layout) in self.groups.items():
> >              try:
> >                  qtile.groupMap[group].layout = layout
> > +
> >              except KeyError:
> >                  pass  # group missing
> > +
> >
> >          for (screen, group) in self.screens.items():
> >              try:
> > @@ -54,3 +91,18 @@ class QtileState(object):
> >                  qtile.screens[screen].setGroup(group)
> >              except (KeyError, IndexError):
> >                  pass  # group or screen missing
> > +
> > +        for (group, layout) in self.layouts.items():
> > +            currGroup = qtile.groupMap[group]
> > +            _windows = list(currGroup.windows)
> > +            for stackNum in layout.keys():
> > +                currLayout = currGroup.layouts[currGroup.currentLayout]
> > +                qtile.log.info(str(currLayout))
> > +                if currLayout.name == 'stack':
> > +                    for indx in range(currLayout.num_stacks):
> > +                        currStack = currLayout.stacks[indx]
> > +                        currStack.lst = [_windows[i] for i in
> layout[indx][0]]
> > +                        currStack.current = layout[indx][1]
> > +        stateAgain = QtileState(qtile)
> > +        qtile.log.info(self)
> > +        qtile.log.info(stateAgain)
> > \ No newline at end of file
>
> --
> You received this message because you are subscribed to the Google Groups
> "qtile-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"qtile-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to