Mercurial > libervia-web
diff browser_side/panels.py @ 195:dd27072d8ae0
browser side: widgets refactoring:
- moved base widgets in a base_widget module
- widgets class now register themselves their Drag/Drop type
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 04 Mar 2013 23:01:57 +0100 |
parents | 6198be95a39c |
children | 39311c7dad77 |
line wrap: on
line diff
--- a/browser_side/panels.py Mon Mar 04 00:19:03 2013 +0100 +++ b/browser_side/panels.py Mon Mar 04 23:01:57 2013 +0100 @@ -24,24 +24,17 @@ from pyjamas.ui.AbsolutePanel import AbsolutePanel from pyjamas.ui.VerticalPanel import VerticalPanel from pyjamas.ui.HorizontalPanel import HorizontalPanel -from pyjamas.ui.ScrollPanel import ScrollPanel -from pyjamas.ui.TabPanel import TabPanel from pyjamas.ui.HTMLPanel import HTMLPanel -from pyjamas.ui.FlexTable import FlexTable from pyjamas.ui.Frame import Frame from pyjamas.ui.TextArea import TextArea -from pyjamas.ui.TextBox import TextBox from pyjamas.ui.Label import Label from pyjamas.ui.Button import Button from pyjamas.ui.HTML import HTML from pyjamas.ui.Image import Image -from pyjamas.ui.DropWidget import DropWidget from pyjamas.ui.ClickListener import ClickHandler from pyjamas.ui.KeyboardListener import KEY_ENTER from pyjamas.ui.MouseListener import MouseHandler -from pyjamas.ui import HasAlignment from pyjamas.Timer import Timer -from pyjamas import Window from pyjamas import DOM from card_game import CardPanel from radiocol import RadioColPanel @@ -51,314 +44,10 @@ from datetime import datetime from time import time import dialog +import base_widget +from pyjamas import Window from __pyjamas__ import doc -class DropCell(DropWidget): - """Cell in the middle grid which replace itself with the dropped widget on DnD""" - - def __init__(self, host): - DropWidget.__init__(self) - self.host = host - self.setStyleName('dropCell') - - def onDragEnter(self, event): - self.addStyleName('dragover') - DOM.eventPreventDefault(event) - - def onDragLeave(self, event): - if event.clientX <= self.getAbsoluteLeft() or event.clientY <= self.getAbsoluteTop() or\ - event.clientX >= self.getAbsoluteLeft() + self.getOffsetWidth()-1 or event.clientY >= self.getAbsoluteTop() + self.getOffsetHeight()-1: - #We check that we are inside widget's box, and we don't remove the style in this case because - #if the mouse is over a widget inside the DropWidget, if will leave the DropWidget, and we - #don't want that - self.removeStyleName('dragover') - - def onDragOver(self, event): - DOM.eventPreventDefault(event) - - def _getCellAndRow(self, grid, event): - """Return cell and row index where the event is occuring""" - cell = grid.getEventTargetCell(event) - row = DOM.getParent(cell) - return (row.rowIndex, cell.cellIndex) - - - def onDrop(self, event): - dt = event.dataTransfer - #'text', 'text/plain', and 'Text' are equivalent. - try: - item, item_type = dt.getData("text/plain").split('\n') #Workaround for webkit, only text/plain seems to be managed - if item_type and item_type[-1] == '\0': #Workaround for what looks like a pyjamas bug: the \0 should not be there, and - item_type = item_type[:-1] # .strip('\0') and .replace('\0','') don't work. TODO: check this and fill a bug report - #item_type = dt.getData("type") - print "message: %s" % item - print "type: %s" % item_type - except: - print "no message found" - item=' ' - item_type = None - DOM.eventPreventDefault(event) - if item_type=="GROUP": - _new_panel = MicroblogPanel(self.host, [item]) - _new_panel.setAcceptedGroup(item) - self.host.FillMicroblogPanel(_new_panel) - self.host.bridge.call('getMassiveLastMblogs', _new_panel.massiveInsert, 'GROUP', [item], 10) - elif item_type=="CONTACT": - _contact = JID(item) - self.host.contact_panel.setContactMessageWaiting(_contact.bare, False) - _new_panel = ChatPanel(self.host, _contact) - _new_panel.historyPrint() - elif item_type=="CONTACT_TITLE": - _new_panel = MicroblogPanel(self.host, []) - self.host.FillMicroblogPanel(_new_panel) - self.host.bridge.call('getMassiveLastMblogs', _new_panel.massiveInsert, 'ALL', [], 10) - else: - return False - if isinstance(self, LiberviaWidget): - self.host.unregisterWidget(self) - self.onQuit() - if not isinstance(_new_panel, LiberviaWidget): - print ('WARNING: droping an object which is not a class of LiberviaWidget') - _flextable = self.getParent() - _widgetspanel = _flextable.getParent().getParent() - row_idx, cell_idx = self._getCellAndRow(_flextable, event) - if self.host.getSelected == self: - self.host.setSelected(None) - _widgetspanel.changeWidget(row_idx, cell_idx, _new_panel) - """_unempty_panels = filter(lambda wid:not isinstance(wid,EmptyWidget),list(_flextable)) - _width = 90/float(len(_unempty_panels) or 1) - #now we resize all the cell of the column - for panel in _unempty_panels: - td_elt = panel.getElement().parentNode - DOM.setStyleAttribute(td_elt, "width", "%s%%" % _width)""" - #FIXME: delete object ? Check the right way with pyjamas - -class LiberviaWidget(DropCell, VerticalPanel, ClickHandler): - """Libervia's widget which can replace itself with a dropped widget on DnD""" - - def __init__(self, host, title='', selectable=False): - """Init the widget - @param host: SatWebFrontend object - @param title: title show in the header of the widget - @param selectable: True is widget can be selected by user""" - VerticalPanel.__init__(self) - DropCell.__init__(self, host) - ClickHandler.__init__(self) - self.__selectable = selectable - self.__title_id = HTMLPanel.createUniqueId() - self.__setting_button_id = HTMLPanel.createUniqueId() - self.__close_button_id = HTMLPanel.createUniqueId() - header = AbsolutePanel() - self.__title = Label(title) - self.__title.setStyleName('widgetHeader_title') - header.add(self.__title) - button_group_wrapper = SimplePanel() - button_group_wrapper.setStyleName('widgetHeader_buttonsWrapper') - button_group = HorizontalPanel() - button_group.setStyleName('widgetHeader_buttonGroup') - setting_button = Image("media/icons/misc/settings.png") - setting_button.setStyleName('widgetHeader_settingButton') - setting_button.addClickListener(self.onSetting) - close_button = Image("media/icons/misc/close.png") - close_button.setStyleName('widgetHeader_closeButton') - close_button.addClickListener(self.onClose) - button_group.add(setting_button) - button_group.add(close_button) - button_group_wrapper.setWidget(button_group) - header.add(button_group_wrapper) - self.add(header) - header.addStyleName('widgetHeader') - self.setSize('100%', '100%') - self.addStyleName('widget') - if self.__selectable: - self.addClickListener(self) - self.host.registerWidget(self) - - def _getWidgetsPanel(self): - current = self - while current is not None and current.__class__ != WidgetsPanel: - current = current.getParent() - if current is None: - print "Error: can't find WidgetsPanel" - return current - - def onClick(self, sender): - self.host.setSelected(self) - - def onClose(self, sender): - """ Called when the close button is pushed """ - _widgetspanel = self._getWidgetsPanel() - _widgetspanel.removeWidget(self) - self.onQuit() - - def onQuit(self): - """ Called when the widget is actually ending """ - pass - - def onSetting(self, sender): - widpanel = self._getWidgetsPanel() - row, col = widpanel.getIndex(self) - body = VerticalPanel() - - #colspan & rowspan - colspan = widpanel.getColSpan(row, col) - rowspan = widpanel.getRowSpan(row, col) - def onColSpanChange(value): - widpanel.setColSpan(row, col, value) - def onRowSpanChange(value): - widpanel.setRowSpan(row, col, value) - colspan_setter = dialog.IntSetter("Columns span", colspan) - colspan_setter.addValueChangeListener(onColSpanChange) - colspan_setter.setWidth('100%') - rowspan_setter = dialog.IntSetter("Rows span", rowspan) - rowspan_setter.addValueChangeListener(onRowSpanChange) - rowspan_setter.setWidth('100%') - body.add(colspan_setter) - body.add(rowspan_setter) - - #size - width_str = self.getWidth() - if width_str.endswith('px'): - width=int(width_str[:-2]) - else: - width = 0 - height_str = self.getHeight() - if height_str.endswith('px'): - height=int(height_str[:-2]) - else: - height = 0 - def onWidthChange(value): - if not value: - self.setWidth('100%') - else: - self.setWidth('%dpx' % value) - def onHeightChange(value): - if not value: - self.setHeight('100%') - else: - self.setHeight('%dpx' % value) - width_setter = dialog.IntSetter("width (0=auto)", width) - width_setter.addValueChangeListener(onWidthChange) - width_setter.setWidth('100%') - height_setter = dialog.IntSetter("height (0=auto)", height) - height_setter.addValueChangeListener(onHeightChange) - height_setter.setHeight('100%') - body.add(width_setter) - body.add(height_setter) - - #reset - def onReset(sender): - colspan_setter.setValue(1) - rowspan_setter.setValue(1) - width_setter.setValue(0) - height_setter.setValue(0) - - reset_bt = Button("Reset", onReset) - body.add(reset_bt) - body.setCellHorizontalAlignment(reset_bt, HasAlignment.ALIGN_CENTER) - - _dialog = dialog.GenericDialog("Widget setting", body) - _dialog.show() - - def setTitle(self, text): - """change the title in the header of the widget - @param text: text of the new title""" - self.__title.setText(text) - - def isSelectable(self): - return self.__selectable - - def setSelectable(self, selectable): - if not self.__selectable: - try: - self.removeClickListener(self) - except ValueError: - pass - if self.selectable and not self in self._clickListeners: - self.addClickListener(self) - self.__selectable = selectable - - def setWidget(self, widget, scrollable=True): - """Set the widget that will be in the body of the LiberviaWidget - @param widget: widget to put in the body - @param scrollable: if true, the widget will be in a ScrollPanelWrapper""" - if scrollable: - _scrollpanelwrapper = ScrollPanelWrapper() - _scrollpanelwrapper.setStyleName('widgetBody') - _scrollpanelwrapper.setWidget(widget) - body_wid = _scrollpanelwrapper - else: - body_wid = widget - self.add(body_wid) - self.setCellHeight(body_wid, '100%') - - def doDetachChildren(self): - #We need to force the use of a panel subclass method here, - #for the same reason as doAttachChildren - VerticalPanel.doDetachChildren(self) - - def doAttachChildren(self): - #We need to force the use of a panel subclass method here, else - #the event will not propagate to children - VerticalPanel.doAttachChildren(self) - -class ScrollPanelWrapper(SimplePanel): - """Scroll Panel like component, wich use the full available space - to work around percent size issue, it use some of the ideas found - here: http://code.google.com/p/google-web-toolkit/issues/detail?id=316 - specially in code given at comment #46, thanks to Stefan Bachert""" - - def __init__(self, *args, **kwargs): - SimplePanel.__init__(self) - self.spanel = ScrollPanel(*args, **kwargs) - SimplePanel.setWidget(self, self.spanel) - DOM.setStyleAttribute(self.getElement(), "position", "relative") - DOM.setStyleAttribute(self.getElement(), "top", "0px") - DOM.setStyleAttribute(self.getElement(), "left", "0px") - DOM.setStyleAttribute(self.getElement(), "width", "100%") - DOM.setStyleAttribute(self.getElement(), "height", "100%") - DOM.setStyleAttribute(self.spanel.getElement(), "position", "absolute") - DOM.setStyleAttribute(self.spanel.getElement(), "width", "100%") - DOM.setStyleAttribute(self.spanel.getElement(), "height", "100%") - - def setWidget(self, widget): - self.spanel.setWidget(widget) - - def setScrollPosition(self, position): - self.spanel.setScrollPosition(position) - - def scrollToBottom(self): - self.setScrollPosition(self.spanel.getElement().scrollHeight) - -class EmptyWidget(DropCell, SimplePanel): - """Empty dropable panel""" - - def __init__(self, host): - SimplePanel.__init__(self) - DropCell.__init__(self, host) - #self.setWidget(HTML('')) - self.setSize('100%','100%') - -class BorderWidget(EmptyWidget): - def __init__(self, host): - EmptyWidget.__init__(self, host) - self.addStyleName('borderPanel') - -class LeftBorderWidget(BorderWidget): - def __init__(self, host): - BorderWidget.__init__(self, host) - self.addStyleName('leftBorderWidget') - -class RightBorderWidget(BorderWidget): - def __init__(self, host): - BorderWidget.__init__(self, host) - self.addStyleName('rightBorderWidget') - -class BottomBorderWidget(BorderWidget): - def __init__(self, host): - BorderWidget.__init__(self, host) - self.addStyleName('bottomBorderWidget') - class UniBoxPanel(SimplePanel): """Panel containing the UniBox""" @@ -549,14 +238,14 @@ self.avatar.setUrl(new_avatar) -class MicroblogPanel(LiberviaWidget): +class MicroblogPanel(base_widget.LiberviaWidget): def __init__(self, host, accepted_groups): """Panel used to show microblog @param accepted_groups: groups displayed in this panel, if empty, show all microblogs from all contacts """ - LiberviaWidget.__init__(self, host, ", ".join(accepted_groups)) - #ScrollPanelWrapper.__init__(self) + base_widget.LiberviaWidget.__init__(self, host, ", ".join(accepted_groups)) + #base_widget.ScrollPanelWrapper.__init__(self) #DropCell.__init__(self) self.accepted_groups = accepted_groups self.entries = {} @@ -564,6 +253,26 @@ self.vpanel.setStyleName('microblogPanel') self.setWidget(self.vpanel) + @classmethod + def registerClass(cls): + base_widget.LiberviaWidget.addDropKey("GROUP", cls.onDropCreateGroup) + base_widget.LiberviaWidget.addDropKey("CONTACT_TITLE", cls.onDropCreateMeta) + + @classmethod + def onDropCreateGroup(cls, host, item): + _new_panel = MicroblogPanel(host, [item]) #XXX: pyjamas doesn't support use of cls directly + _new_panel.setAcceptedGroup(item) + host.FillMicroblogPanel(_new_panel) + host.bridge.call('getMassiveLastMblogs', _new_panel.massiveInsert, 'GROUP', [item], 10) + return _new_panel + + @classmethod + def onDropCreateMeta(cls, host, item): + _new_panel = MicroblogPanel(host, []) #XXX: pyjamas doesn't support use of cls directly + host.FillMicroblogPanel(_new_panel) + host.bridge.call('getMassiveLastMblogs', _new_panel.massiveInsert, 'ALL', [], 10) + return _new_panel + def accept_all(self): return not self.accepted_groups #we accept every microblog only if we are not filtering by groups @@ -704,14 +413,14 @@ self.occupants_list.clear() AbsolutePanel.clear(self) -class ChatPanel(LiberviaWidget): +class ChatPanel(base_widget.LiberviaWidget): def __init__(self, host, target, type_='one2one'): """Panel used for conversation (one 2 one or group chat) @param host: SatWebFrontend instance @param target: entity (JID) with who we have a conversation (contact's jid for one 2 one chat, or MUC room) @param type: one2one for simple conversation, group for MUC""" - LiberviaWidget.__init__(self, host, target.bare, selectable = True) + base_widget.LiberviaWidget.__init__(self, host, target.bare, selectable = True) self.vpanel = VerticalPanel() self.vpanel.setSize('100%','100%') self.type = type_ @@ -730,7 +439,7 @@ self.__body.add(chat_area) self.content = AbsolutePanel() self.content.setStyleName('chatContent') - self.content_scroll = ScrollPanelWrapper(self.content) + self.content_scroll = base_widget.ScrollPanelWrapper(self.content) chat_area.add(self.content_scroll) chat_area.setCellWidth(self.content_scroll, '100%') self.vpanel.add(self.__body) @@ -740,15 +449,27 @@ """def doDetachChildren(self): #We need to force the use of a panel subclass method here, #for the same reason as doAttachChildren - ScrollPanelWrapper.doDetachChildren(self) + base_widget.ScrollPanelWrapper.doDetachChildren(self) def doAttachChildren(self): #We need to force the use of a panel subclass method here, else #the event will not propagate to children - ScrollPanelWrapper.doAttachChildren(self)""" + base_widget.ScrollPanelWrapper.doAttachChildren(self)""" + + @classmethod + def registerClass(cls): + base_widget.LiberviaWidget.addDropKey("CONTACT", cls.onDropCreate) + + @classmethod + def onDropCreate(cls, host, item): + _contact = JID(item) + host.contact_panel.setContactMessageWaiting(_contact.bare, False) + _new_panel = ChatPanel(host, _contact) #XXX: pyjamas doesn't seems to support creating with cls directly + _new_panel.historyPrint() + return _new_panel def onQuit(self): - LiberviaWidget.onQuit(self) + base_widget.LiberviaWidget.onQuit(self) if self.type == 'group': self.host.bridge.call('mucLeave', None, self.target.bare) @@ -833,14 +554,14 @@ elif game_type=="RadioCol": return self.radiocol_panel -class WebPanel(LiberviaWidget): +class WebPanel(base_widget.LiberviaWidget): """ (mini)browser like widget """ def __init__(self, host, url=None): """ @param host: SatWebFrontend instance """ - LiberviaWidget.__init__(self, host) + base_widget.LiberviaWidget.__init__(self, host) self._vpanel = VerticalPanel() self._vpanel.setSize('100%', '100%') self._url = dialog.ExtTextBox(enter_cb = self.onUrlClick) @@ -864,143 +585,6 @@ def onUrlClick(self, sender): self._frame.setUrl(self._url.getText()) -class WidgetsPanel(ScrollPanelWrapper): - - def __init__(self, host, locked = False): - ScrollPanelWrapper.__init__(self) - self.setSize('100%', '100%') - self.host = host - self.locked = locked #if True: tab will not be removed when there are no more widgets inside - self.selected = None - self.flextable = FlexTable() - self.flextable.setSize('100%','100%') - self.setWidget(self.flextable) - self.setStyleName('widgetsPanel') - _bottom = BottomBorderWidget(self.host) - self.flextable.setWidget(0, 0, _bottom) #There will be always an Empty widget on the last row, - #dropping a widget there will add a new row - td_elt = _bottom.getElement().parentNode - DOM.setStyleAttribute(td_elt, "height", "1px") #needed so the cell adapt to the size of the border (specially in webkit) - self._max_cols = 1 #give the maximum number of columns i a raw - - def isLocked(self): - return self.locked - - def changeWidget(self, row, col, wid): - """Change the widget in the given location, add row or columns when necessary""" - print "changing widget:", wid, row, col - last_row = max(0, self.flextable.getRowCount()-1) - try: - prev_wid = self.flextable.getWidget(row, col) - except: - print "ERROR: Trying to change an unexisting widget !" - return - - - cellFormatter = self.flextable.getFlexCellFormatter() - - if isinstance(prev_wid, BorderWidget): - #We are on a border, we must create a row and/or columns - print "BORDER WIDGET" - prev_wid.removeStyleName('dragover') - - if isinstance(prev_wid, BottomBorderWidget): - #We are on the bottom border, we create a new row - self.flextable.insertRow(last_row) - self.flextable.setWidget(last_row, 0, LeftBorderWidget(self.host)) - self.flextable.setWidget(last_row, 1, wid) - self.flextable.setWidget(last_row, 2, RightBorderWidget(self.host)) - cellFormatter.setHorizontalAlignment(last_row, 2, HasAlignment.ALIGN_RIGHT) - row = last_row - - elif isinstance(prev_wid, LeftBorderWidget): - if col!=0: - print "ERROR: LeftBorderWidget must be on the first column !" - return - self.flextable.insertCell(row, col+1) - self.flextable.setWidget(row, 1, wid) - - elif isinstance(prev_wid, RightBorderWidget): - if col!=self.flextable.getCellCount(row)-1: - print "ERROR: RightBorderWidget must be on the last column !" - return - self.flextable.insertCell(row, col) - self.flextable.setWidget(row, col, wid) - - else: - prev_wid.removeFromParent() - self.flextable.setWidget(row, col, wid) - - _max_cols = max(self._max_cols, self.flextable.getCellCount(row)) - if _max_cols != self._max_cols: - self._max_cols = _max_cols - self._sizesAdjust() - - def _sizesAdjust(self): - cellFormatter = self.flextable.getFlexCellFormatter() - width = 100.0/max(1, self._max_cols-2) #we don't count the borders - - for row_idx in xrange(self.flextable.getRowCount()): - for col_idx in xrange(self.flextable.getCellCount(row_idx)): - _widget = self.flextable.getWidget(row_idx, col_idx) - if not isinstance(_widget, BorderWidget): - td_elt = _widget.getElement().parentNode - DOM.setStyleAttribute(td_elt, "width", "%.2f%%" % width) - - last_row = max(0, self.flextable.getRowCount()-1) - cellFormatter.setColSpan(last_row, 0, self._max_cols) - - def addWidget(self, wid): - """Add a widget to a new cell on the next to last row""" - last_row = max(0, self.flextable.getRowCount()-1) - print "putting widget %s at %d, %d" % (wid, last_row, 0) - self.changeWidget(last_row, 0, wid) - - def removeWidget(self, wid): - """Remove a widget and the cell where it is""" - _row, _col = self.flextable.getIndex(wid) - self.flextable.remove(wid) - self.flextable.removeCell(_row, _col) - if self.flextable.getCellCount(_row) == 2: #we have only the borders left, we remove the row - self.flextable.removeRow(_row) - _max_cols = 1 - for row_idx in xrange(self.flextable.getRowCount()): - _max_cols = max(_max_cols, self.flextable.getCellCount(row_idx)) - if _max_cols != self._max_cols: - self._max_cols = _max_cols - self._sizesAdjust() - current = self - - blank_page = not [wid for wid in self.flextable if isinstance(wid, LiberviaWidget)] # do we still have widgets on the page ? - - if blank_page and not self.isLocked(): - #we now notice the MainTabPanel that the WidgetsPanel is empty and need to be removed - while current is not None: - if isinstance(current, MainTabPanel): - current.onWidgetPanelRemove(self) - return - current = current.getParent() - print "Error: no MainTabPanel found !" - - def getIndex(self, wid): - return self.flextable.getIndex(wid) - - def getColSpan(self, row, col): - cellFormatter = self.flextable.getFlexCellFormatter() - return cellFormatter.getColSpan(row, col) - - def setColSpan(self, row, col, value): - cellFormatter = self.flextable.getFlexCellFormatter() - return cellFormatter.setColSpan(row, col, value) - - def getRowSpan(self, row, col): - cellFormatter = self.flextable.getFlexCellFormatter() - return cellFormatter.getRowSpan(row, col) - - def setRowSpan(self, row, col, value): - cellFormatter = self.flextable.getFlexCellFormatter() - return cellFormatter.setRowSpan(row, col, value) - class ContactTabPanel(HorizontalPanel): """ TabPanel with a contacts list which can be hidden """ @@ -1012,7 +596,7 @@ contacts_switch.addStyleName('contactsSwitch') self._left.add(contacts_switch) self._left.add(self.host.contact_panel) - self._right = WidgetsPanel(host) + self._right = base_widget.WidgetsPanel(host) self._right.setWidth('100%') self._right.setHeight('100%') self.add(self._left) @@ -1024,50 +608,6 @@ print "main addWidget", wid self._right.addWidget(wid) -class MainTabPanel(TabPanel): - - def __init__(self, host): - TabPanel.__init__(self) - self.host=host - self.tabBar.setVisible(False) - self.setStyleName('liberviaTabPanel') - self.addStyleName('mainTabPanel') - Window.addWindowResizeListener(self) - - def getCurrentPanel(self): - """ Get the panel of the currently selected tab """ - return self.deck.visibleWidget - - def onWindowResized(self, width, height): - tab_panel_elt = self.getElement() - _elts = doc().getElementsByClassName('gwt-TabBar') - if not _elts.length: - print ("ERROR: no TabBar found, it should exist !") - tab_bar_h = 0 - else: - tab_bar_h = _elts.item(0).offsetHeight - ideal_height = height - DOM.getAbsoluteTop(tab_panel_elt) - tab_bar_h - 5 - ideal_width = width - DOM.getAbsoluteLeft(tab_panel_elt) - 5 - self.setWidth("%s%s" % (ideal_width, "px")); - self.setHeight("%s%s" % (ideal_height, "px")); - - def add(self, widget, tabText=None, asHTML=False): - TabPanel.add(self, widget, tabText, asHTML) - if self.getWidgetCount()>1: - self.tabBar.setVisible(True) - self.host.resize() - - def onWidgetPanelRemove(self, panel): - """ Called when a child WidgetsPanel is empty and need to be removed """ - self.remove(panel) - widgets_count = self.getWidgetCount() - if widgets_count == 1: - self.tabBar.setVisible(False) - self.host.resize() - self.selectTab(0) - else: - self.selectTab(widgets_count - 1) - class MainPanel(AbsolutePanel): def __init__(self, host): @@ -1092,8 +632,8 @@ _contacts.add(self.host.contact_panel) #tabs - self.tab_panel = MainTabPanel(host) - self.discuss_panel = WidgetsPanel(self.host, locked=True) + self.tab_panel = base_widget.MainTabPanel(host) + self.discuss_panel = base_widget.WidgetsPanel(self.host, locked=True) self.tab_panel.add(self.discuss_panel, "Discussions") self.tab_panel.selectTab(0)