reorder.py 4.59 KB
Newer Older
mathieui's avatar
mathieui committed
1 2 3 4 5 6 7 8 9 10 11 12 13
"""
``reorder`` plugin: Reorder the tabs according to a layout

Commands
--------

.. glossary::

    /reorder
        **Usage:** ``/reorder``

        Reorder the tabs according to the configuration.

14 15 16 17
    /save_order
        **Usage:** ``/save_order``

        Save the current tab order to the configuration.
mathieui's avatar
mathieui committed
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

Configuration
-------------

The configuration file must contain a section ``[reorder]`` and each option
must be formatted like ``[tab number] = [tab type]:[tab name]``.

For example:

.. code-block:: ini

    [reorder]
    1 = muc:toto@conference.example.com
    2 = muc:example@muc.example.im
    3 = dynamic:robert@example.org

The ``[tab number]`` must be at least ``1``; if the range is not entirely
covered, e.g.:

.. code-block:: ini

    [reorder]
    1 = muc:toto@conference.example.com
    3 = dynamic:robert@example.org

Poezio will insert gaps between the tabs in order to keep the specified
numbering (so in this case, there will be a tab 1, a tab 3, but no tab 2).


The ``[tab type]`` must be one of:

- ``muc`` (for multi-user chats)
- ``private`` (for chats with a specific user inside a multi-user chat)
- ``dynamic`` (for normal, dynamic conversations tabs)
- ``static`` (for conversations with a specific resource)

And finally, the ``[tab name]`` must be:

- For a type ``muc``, the bare JID of the room
- For a type ``private``, the full JID of the user (room JID with the username as a resource)
- For a type ``dynamic``, the bare JID of the contact
- For a type ``static``, the full JID of the contact
"""
61

62 63
from poezio import tabs
from poezio.decorators import command_args_parser
64
from poezio.plugin import BasePlugin
65
from poezio.config import config
mathieui's avatar
mathieui committed
66

67
TEXT_TO_TAB = {
mathieui's avatar
mathieui committed
68 69 70 71 72 73 74
    'muc': tabs.MucTab,
    'private': tabs.PrivateTab,
    'dynamic': tabs.DynamicConversationTab,
    'static': tabs.StaticConversationTab,
    'empty': tabs.GapTab
}

75 76 77 78 79 80 81 82
TAB_TO_TEXT = {
    tabs.MucTab: 'muc',
    tabs.DynamicConversationTab: 'dynamic',
    tabs.PrivateTab: 'private',
    tabs.StaticConversationTab: 'static',
    tabs.GapTab: 'empty'
}

mathieui's avatar
mathieui committed
83
def parse_config(tab_config):
mathieui's avatar
mathieui committed
84
    result = {}
mathieui's avatar
mathieui committed
85
    for option in tab_config.options('reorder'):
mathieui's avatar
mathieui committed
86 87 88 89
        if not option.isdecimal():
            continue
        pos = int(option)
        if pos in result or pos <= 0:
mathieui's avatar
mathieui committed
90
            return None
mathieui's avatar
mathieui committed
91

mathieui's avatar
mathieui committed
92
        typ, name = tab_config.get(option, default=':').split(':', maxsplit=1)
93
        if typ not in TEXT_TO_TAB:
mathieui's avatar
mathieui committed
94
            return None
95
        result[pos] = (TEXT_TO_TAB[typ], name)
mathieui's avatar
mathieui committed
96 97 98

    return result

99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
def check_tab(tab):
    for cls, rep in TAB_TO_TEXT.items():
        if isinstance(tab, cls):
            return rep
    return ''

def parse_runtime_tablist(tablist):
    props = []
    i = 0
    for tab in tablist[1:]:
        i += 1
        result = check_tab(tab)
        if result:
            props.append((i, '%s:%s' % (result, tab.name)))
    return props

mathieui's avatar
mathieui committed
115 116 117
class Plugin(BasePlugin):
    def init(self):
        self.api.add_command('reorder', self.command_reorder,
mathieui's avatar
mathieui committed
118 119
                             help='Reorder all tabs using the pre-defined'
                                  ' layout from the configuration file.')
120 121 122 123 124 125 126 127 128
        self.api.add_command('save_order', self.command_save_order,
                             help='Save the current tab layout')

    @command_args_parser.ignored
    def command_save_order(self):
        conf = parse_runtime_tablist(self.core.tabs)
        for key, value in conf:
            self.config.set(key, value)
        self.api.information('Tab order saved', 'Info')
mathieui's avatar
mathieui committed
129 130 131 132 133 134 135 136 137 138

    @command_args_parser.ignored
    def command_reorder(self):
        """
        /reorder
        """
        tabs_spec = parse_config(self.config)
        if not tabs_spec:
            return self.api.information('Invalid reorder config', 'Error')

mathieui's avatar
mathieui committed
139 140
        old_tabs = self.core.tabs.get_tabs()
        roster = old_tabs.pop(0)
mathieui's avatar
mathieui committed
141

142 143
        create_gaps = config.get('create_gaps')

mathieui's avatar
mathieui committed
144
        new_tabs = [roster]
mathieui's avatar
mathieui committed
145 146
        last = 0
        for pos in sorted(tabs_spec):
147
            if create_gaps and pos > last + 1:
mathieui's avatar
mathieui committed
148
                new_tabs += [tabs.GapTab(self.core) for i in range(pos - last - 1)]
mathieui's avatar
mathieui committed
149
            cls, name = tabs_spec[pos]
mathieui's avatar
mathieui committed
150
            tab = self.core.tabs.by_name_and_class(name, cls=cls)
mathieui's avatar
mathieui committed
151 152 153 154 155
            if tab and tab in old_tabs:
                new_tabs.append(tab)
                old_tabs.remove(tab)
            else:
                self.api.information('Tab %s not found' % name, 'Warning')
156 157
                if create_gaps:
                    new_tabs.append(tabs.GapTab(self.core))
mathieui's avatar
mathieui committed
158 159 160 161 162 163
            last = pos

        for tab in old_tabs:
            if tab:
                new_tabs.append(tab)

mathieui's avatar
mathieui committed
164
        self.core.tabs.replace_tabs(new_tabs)
mathieui's avatar
mathieui committed
165
        self.core.refresh_window()