reorder.py 4.68 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 84 85 86 87 88 89 90 91 92
def parse_config(config):
    result = {}
    for option in config.options('reorder'):
        if not option.isdecimal():
            continue
        pos = int(option)
        if pos in result or pos <= 0:
            return

        typ, name = config.get(option, default=':').split(':', maxsplit=1)
93
        if typ not in TEXT_TO_TAB:
mathieui's avatar
mathieui committed
94
            return
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 139 140 141 142 143 144

    @command_args_parser.ignored
    def command_reorder(self):
        """
        /reorder
        """
        self.core.go_to_roster()
        self.core.current_tab_nb = 0

        tabs_spec = parse_config(self.config)
        if not tabs_spec:
            return self.api.information('Invalid reorder config', 'Error')

        old_tabs = self.core.tabs[1:]
        roster = self.core.tabs[0]

145 146
        create_gaps = config.get('create_gaps')

mathieui's avatar
mathieui committed
147 148 149
        new_tabs = []
        last = 0
        for pos in sorted(tabs_spec):
150
            if create_gaps and pos > last + 1:
151
                new_tabs += [tabs.GapTab(self.core) for i in range(pos - last)]
mathieui's avatar
mathieui committed
152 153 154 155 156 157 158
            cls, name = tabs_spec[pos]
            tab = self.core.get_tab_by_name(name, typ=cls)
            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')
159 160
                if create_gaps:
                    new_tabs.append(tabs.GapTab(self.core))
mathieui's avatar
mathieui committed
161 162 163 164 165 166 167 168 169 170 171 172
            last = pos

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

        self.core.tabs.clear()
        self.core.tabs.append(roster)
        self.core.tabs += new_tabs

        self.core.refresh_window()