示例#1
0
def test_empty():
    app = wx.App()
    wx.Log.SetLogLevel(0)

    defaultImage = '../test/images/new.png'
    cache = ImageListCache(defaultImage)

    imageList = cache.getImageList()
    assert imageList.GetImageCount() == 1
    assert cache.getDefaultImageId() == 0
示例#2
0
def test_empty():
    app = wx.App()
    wx.Log.SetLogLevel(0)

    defaultImage = 'testdata/images/new.png'
    cache = ImageListCache(defaultImage)

    imageList = cache.getImageList()
    assert imageList.GetImageCount() == 1
    assert cache.getDefaultImageId() == 0
示例#3
0
def test_error_invalid_file():
    '''
    Try add invalid file (not image)
    '''
    app = wx.App()
    wx.Log.SetLogLevel(0)

    defaultImage = 'testdata/images/new.png'
    cache = ImageListCache(defaultImage)

    index = cache.add('testdata/images/invalid.png')

    imageList = cache.getImageList()
    assert index == 0
    assert imageList.GetImageCount() == 1
示例#4
0
def test_error_not_exists():
    '''
    Try add file which not exists
    '''
    app = wx.App()
    wx.Log.SetLogLevel(0)

    defaultImage = 'testdata/images/new.png'
    cache = ImageListCache(defaultImage)

    index = cache.add('testdata/images/not_exists.png')

    imageList = cache.getImageList()
    assert index == 0
    assert imageList.GetImageCount() == 1
示例#5
0
def test_single():
    '''
    Add single image to empty ImageList
    '''
    app = wx.App()
    wx.Log.SetLogLevel(0)

    defaultImage = 'testdata/images/new.png'
    cache = ImageListCache(defaultImage)

    index = cache.add('testdata/images/16x16.png')

    imageList = cache.getImageList()
    assert index == 1
    assert imageList.GetImageCount() == 2
示例#6
0
def test_error_invalid_file():
    '''
    Try add invalid file (not image)
    '''
    app = wx.App()
    wx.Log.SetLogLevel(0)

    defaultImage = '../test/images/new.png'
    cache = ImageListCache(defaultImage)

    index = cache.add('../test/images/invalid.png')

    imageList = cache.getImageList()
    assert index == 0
    assert imageList.GetImageCount() == 1
示例#7
0
def test_error_not_exists():
    '''
    Try add file which not exists
    '''
    app = wx.App()
    wx.Log.SetLogLevel(0)

    defaultImage = '../test/images/new.png'
    cache = ImageListCache(defaultImage)

    index = cache.add('../test/images/not_exists.png')

    imageList = cache.getImageList()
    assert index == 0
    assert imageList.GetImageCount() == 1
示例#8
0
def test_single():
    '''
    Add single image to empty ImageList
    '''
    app = wx.App()
    wx.Log.SetLogLevel(0)

    defaultImage = '../test/images/new.png'
    cache = ImageListCache(defaultImage)

    index = cache.add('../test/images/16x16.png')

    imageList = cache.getImageList()
    assert index == 1
    assert imageList.GetImageCount() == 2
示例#9
0
def test_duplicate():
    '''
    Add duplicate image to empty ImageList
    '''
    app = wx.App()
    wx.Log.SetLogLevel(0)

    defaultImage = '../test/images/new.png'
    cache = ImageListCache(defaultImage)

    cache.add('../test/images/16x16.png')
    index = cache.add('../test/images/16x16.png')

    imageList = cache.getImageList()
    assert index == 1
    assert imageList.GetImageCount() == 2
示例#10
0
class PageList(wx.Panel):
    def __init__(self, parent: wx.Window):
        super().__init__(parent)
        self._columns = []                     # type: List[BaseColumn]
        self._pages = []                       # type: List[outwiker.core.tree.WikiPage]
        self._defaultIcon = getBuiltinImagePath("page.png")
        self._imageList = ImageListCache(self._defaultIcon)

        self._propagationLevel = 15
        self.SetBackgroundColour(wx.Colour(255, 255, 255))

        self._sizer = wx.FlexGridSizer(cols=1)
        self._sizer.AddGrowableCol(0)
        self._sizer.AddGrowableRow(0)

        self._listCtrl = ULC.UltimateListCtrl(
            self,
            agwStyle=ULC.ULC_REPORT | ULC.ULC_SINGLE_SEL | ULC.ULC_VRULES | ULC.ULC_HRULES | ULC.ULC_SHOW_TOOLTIPS | ULC.ULC_NO_HIGHLIGHT
        )

        self._listCtrl.Bind(ULC.EVT_LIST_ITEM_HYPERLINK,
                            handler=self._onPageClick)
        self._listCtrl.Bind(ULC.EVT_LIST_COL_CLICK,
                            handler=self._onColClick)
        self._listCtrl.SetHyperTextNewColour(wx.BLUE)
        self._listCtrl.SetHyperTextVisitedColour(wx.BLUE)
        self._listCtrl.AssignImageList(self._imageList.getImageList(),
                                       wx.IMAGE_LIST_SMALL)

        self._sizer.Add(self._listCtrl, flag=wx.EXPAND)
        self.SetSizer(self._sizer)

    @property
    def listCtrl(self):
        return self._listCtrl

    @property
    def imageList(self):
        return self._imageList

    @property
    def _visibleColumns(self):
        return [col for col in self._columns if col.visible]

    def _onPageClick(self, event):
        item = event.GetItem()
        pageData = item.GetPyData()
        if pageData:
            page = pageData.page
            assert page is not None
            event = PageClickEvent(page=page)
            event.ResumePropagation(self._propagationLevel)
            wx.PostEvent(self, event)

    def _onColClick(self, event):
        self.sortByColumn(event.GetColumn())

    def sortByColumn(self, col_index: int):
        for n, column in enumerate(self._visibleColumns):
            if n != col_index:
                column.set_sort_type(BaseColumn.SORT_NONE, self._listCtrl)

        column = self._visibleColumns[col_index]
        if column.sort_type == BaseColumn.SORT_NORMAL:
            column.set_sort_type(BaseColumn.SORT_INVERSE, self._listCtrl)
        else:
            column.set_sort_type(BaseColumn.SORT_NORMAL, self._listCtrl)

        if column.sort_type == BaseColumn.SORT_INVERSE:
            self._listCtrl.SortItems(column.sortFunctionInverse)
        else:
            self._listCtrl.SortItems(column.sortFunction)

    def clear(self):
        """
        Удалить все элементы из списка
        """
        self._listCtrl.ClearAll()

    def _createColumns(self):
        for n, column in enumerate(self._visibleColumns):
            column.insertColumn(self._listCtrl, n)

    def setPageList(self, pages):
        """
        pages - список страниц, отображаемый в списке
        """
        self._pages = pages
        self._updatePageList()

    def setColumns(self, columns: List[BaseColumn]):
        self._columns = columns
        self._updatePageList()

    def _updatePageList(self):
        self._listCtrl.Freeze()
        self.clear()
        self._createColumns()
        self._fillPageList()
        self._listCtrl.Thaw()

    def _fillPageList(self):
        for page in self._pages:
            items = [column.getCellContent(page)
                     for column
                     in self._visibleColumns]
            item_index = self._listCtrl.Append(items)
            for n, column in enumerate(self._visibleColumns):
                column.setCellProperties(self, item_index, n, page)

            data = PageData(page)
            self._listCtrl.SetItemPyData(item_index, data)

    def updateColumnsWidth(self):
        n = 0
        for col in self._columns:
            if not col.visible:
                continue

            col.width = self._listCtrl.GetColumnWidth(n)
            n += 1

    def getColumns(self) -> List[BaseColumn]:
        return self._columns
示例#11
0
class PageList(wx.Panel):
    def __init__(self, parent: wx.Window):
        super().__init__(parent)
        self._columns = []                     # type: List[BaseColumn]
        self._pages = []
        self._defaultIcon = os.path.join(getImagesDir(), "page.png")
        self._imageList = ImageListCache(self._defaultIcon)

        self._propagationLevel = 15
        self.SetBackgroundColour(wx.Colour(255, 255, 255))

        self._sizer = wx.FlexGridSizer(cols=1)
        self._sizer.AddGrowableCol(0)
        self._sizer.AddGrowableRow(0)

        self._listCtrl = ULC.UltimateListCtrl(
            self,
            agwStyle=ULC.ULC_REPORT | ULC.ULC_SINGLE_SEL | ULC.ULC_VRULES | ULC.ULC_HRULES | ULC.ULC_SHOW_TOOLTIPS | ULC.ULC_NO_HIGHLIGHT
        )

        self._listCtrl.Bind(ULC.EVT_LIST_ITEM_HYPERLINK,
                            handler=self._onPageClick)
        self._listCtrl.Bind(ULC.EVT_LIST_COL_CLICK,
                            handler=self._onColClick)
        self._listCtrl.SetHyperTextNewColour(wx.BLUE)
        self._listCtrl.SetHyperTextVisitedColour(wx.BLUE)
        self._listCtrl.AssignImageList(self._imageList.getImageList(),
                                       wx.IMAGE_LIST_SMALL)

        self._sizer.Add(self._listCtrl, flag=wx.EXPAND)
        self.SetSizer(self._sizer)

    @property
    def listCtrl(self):
        return self._listCtrl

    @property
    def imageList(self):
        return self._imageList

    @property
    def _visibleColumns(self):
        return [col for col in self._columns if col.visible]

    def _onPageClick(self, event):
        item = event.GetItem()
        pageData = item.GetPyData()
        if pageData:
            page = pageData.page
            assert page is not None
            event = PageClickEvent(page=page)
            event.ResumePropagation(self._propagationLevel)
            wx.PostEvent(self, event)

    def _onColClick(self, event):
        self.sortByColumn(event.GetColumn())

    def sortByColumn(self, col_index: int):
        for n, column in enumerate(self._visibleColumns):
            if n != col_index:
                column.set_sort_type(BaseColumn.SORT_NONE, self._listCtrl)

        column = self._visibleColumns[col_index]
        if column.sort_type == BaseColumn.SORT_NORMAL:
            column.set_sort_type(BaseColumn.SORT_INVERSE, self._listCtrl)
        else:
            column.set_sort_type(BaseColumn.SORT_NORMAL, self._listCtrl)

        if column.sort_type == BaseColumn.SORT_INVERSE:
            self._listCtrl.SortItems(column.sortFunctionInverse)
        else:
            self._listCtrl.SortItems(column.sortFunction)

    def clear(self):
        """
        Удалить все элементы из списка
        """
        self._listCtrl.ClearAll()

    def _createColumns(self):
        for n, column in enumerate(self._visibleColumns):
            column.insertColumn(self._listCtrl, n)

    def setPageList(self, pages):
        """
        pages - список страниц, отображаемый в списке
        """
        self._pages = pages
        self._updatePageList()

    def setColumns(self, columns: List[BaseColumn]):
        self._columns = columns
        self._updatePageList()

    def _updatePageList(self):
        self._listCtrl.Freeze()
        self.clear()
        self._createColumns()
        self._fillPageList()
        self._listCtrl.Thaw()

    def _fillPageList(self):
        for page in self._pages:
            items = [column.getCellContent(page)
                     for column
                     in self._visibleColumns]
            item_index = self._listCtrl.Append(items)
            for n, column in enumerate(self._visibleColumns):
                column.setCellProperties(self, item_index, n, page)

            data = PageData(page)
            self._listCtrl.SetItemPyData(item_index, data)

    def updateColumnsWidth(self):
        n = 0
        for col in self._columns:
            if not col.visible:
                continue

            col.width = self._listCtrl.GetColumnWidth(n)
            n += 1

    def getColumns(self) -> List[BaseColumn]:
        return self._columns
示例#12
0
class NotesTreeCtrl(wx.TreeCtrl):
    def __init__(self, parent: wx.Window):
        treeStyle = (wx.TR_HAS_BUTTONS | wx.TR_EDIT_LABELS | wx.SUNKEN_BORDER)
        super().__init__(parent, style=treeStyle)

        self.defaultIcon = getBuiltinImagePath('page.png')
        self.iconHeight = ICON_HEIGHT

        # Картинки для дерева
        self._iconsCache = ImageListCache(self.defaultIcon)
        self.AssignImageList(self._iconsCache.getImageList())

        # Кеш для страниц, чтобы было проще искать элемент дерева по странице
        # Словарь. Ключ - страница, значение - элемент дерева wx.TreeItemId
        self._pageCache = {}

        # Имя опции для сохранения развернутости страницы
        self.pageOptionExpand = 'Expand'

        self.Bind(wx.EVT_CLOSE, self.__onClose)

    def __onClose(self, event):
        self._iconsCache.clear()

    def treeUpdate(self, rootPage):
        """
        Обновить дерево
        """
        self.DeleteAllItems()
        self._iconsCache.clear()

        # Ключ - страница, значение - экземпляр класса TreeItemId
        self._pageCache = {}

        if rootPage is not None:
            rootname = os.path.basename(rootPage.path)
            rootItem = self.AddRoot(
                rootname,
                data=rootPage,
                image=self._iconsCache.getDefaultImageId())

            self._pageCache[rootPage] = rootItem
            self.__mountItem(rootItem, rootPage)
            self.appendChildren(rootPage)

            self.selectedPage = rootPage.selectedPage
            self.expand(rootPage)

    def appendChildren(self, parentPage):
        """
        Добавить детей в дерево
        parentPage - родительская страница, куда добавляем дочерние страницы
        """
        grandParentExpanded = self.__getItemExpandState(parentPage.parent)

        if grandParentExpanded:
            for child in parentPage.children:
                if child not in self._pageCache:
                    self.insertChild(child)

        if self.__getPageExpandState(parentPage):
            self.expand(parentPage)

    def __mountItem(self, treeitem, page):
        """
        Оформить элемент дерева в зависимости от настроек страницы
        (например, пометить только для чтения)
        """
        if page.readonly:
            font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
            font.SetStyle(wx.FONTSTYLE_ITALIC)
            self.SetItemFont(treeitem, font)

    def insertChild(self, childPage):
        """
        Вставить одну дочерниюю страницу (childPage) в ветвь
        """
        parentItem = self.getTreeItem(childPage.parent)
        assert parentItem is not None

        item = self.InsertItem(parentItem,
                               childPage.order,
                               childPage.display_title,
                               data=childPage)

        self.SetItemImage(item, self.__loadIcon(childPage))

        self._pageCache[childPage] = item
        self.__mountItem(item, childPage)
        self.appendChildren(childPage)

        return item

    def removePageItem(self, page):
        """
        Удалить элемент, соответствующий странице и все его дочерние страницы
        """
        for child in page.children:
            self.removePageItem(child)

        item = self.getTreeItem(page)
        if item is not None:
            del self._pageCache[page]
            self.Delete(item)

    def __loadIcon(self, page):
        """
        Добавляет иконку страницы в ImageList и возвращает ее идентификатор.
        Если иконки нет, то возвращает идентификатор иконки по умолчанию
        """
        icon = page.icon

        if not icon:
            return self._iconsCache.getDefaultImageId()

        icon = os.path.abspath(icon)
        imageId = self._iconsCache.add(icon)

        if imageId is None:
            imageId = self._iconsCache.getDefaultImageId()

        return imageId

    def updateIcon(self, page):
        if page not in self._pageCache:
            # Если нет этой страницы в дереве, то не важно,
            # изменилась иконка или нет
            return

        icon_id = self.__loadIcon(page)
        self.SetItemImage(self._pageCache[page], icon_id)

    def __getItemExpandState(self, page):
        """
        Проверить, раскрыт ли элемент в дереве для страницы page
        """
        if page is None:
            return True

        if page.parent is None:
            return True

        return self.IsExpanded(self._pageCache[page])

    def __getPageExpandState(self, page):
        """
        Проверить состояние "раскрытости" страницы
        """
        if page is None:
            return True

        if page.parent is None:
            return True

        page_registry = page.root.registry.get_page_registry(page)
        expanded = page_registry.getbool(self.pageOptionExpand, default=False)

        return expanded

    def getTreeItem(self, page: 'outwiker.core.tree.WikiPage') -> Optional[wx.TreeItemId]:
        """
        Получить элемент дерева по странице.
        Если для страницы не создан элемент дерева, возвращается None
        """
        return self._pageCache.get(page)

    def expandToPage(self, page):
        """
        Развернуть ветви до того уровня, чтобы появился элемент для page
        """
        # Список родительских страниц, которые нужно добавить в дерево
        pages = []
        currentPage = page.parent
        while currentPage is not None:
            pages.append(currentPage)
            currentPage = currentPage.parent

        pages.reverse()
        for page in pages:
            self.expand(page)

    def expand(self, page):
        item = self.getTreeItem(page)
        if item is not None:
            self.Expand(item)

    def createPage(self, newpage):
        if newpage.parent in self._pageCache:
            self.insertChild(newpage)

            assert newpage in self._pageCache
            item = self._pageCache[newpage]
            assert item.IsOk()

            self.expand(newpage)

    @property
    def selectedPage(self):
        page = None

        item = self.GetSelection()
        if item.IsOk():
            page = self.GetItemData(item)

            # Проверка того, что выбрали не корневой элемент
            if page.parent is None:
                page = None

        return page

    @selectedPage.setter
    def selectedPage(self, newSelPage):
        if newSelPage is None:
            item = self.GetRootItem()
        else:
            self.expandToPage(newSelPage)
            item = self.getTreeItem(newSelPage)

        if item is not None:
            self.SelectItem(item)