def copy_selection_access_string(self): """Copys access_string to selection to the clipboard An access string is Python code to reference the selection If there is no selection then a reference to the current cell is copied """ selection = self.get_selection() if not selection: cursor = self.grid.actions.cursor selection = Selection([], [], [], [], [tuple(cursor[:2])]) shape = self.grid.code_array.shape tab = self.grid.current_table access_string = selection.get_access_string(shape, tab) # Copy access string to clipboard self.grid.main_window.clipboard.set_clipboard(access_string) # Display copy operation and access string in status bar statustext = _("Cell reference copied to clipboard: {access_string}") statustext = statustext.format(access_string=access_string) post_command_event(self.main_window, self.StatusBarMsg, text=statustext)
def _adjust_merge_area(self, attrs, insertion_point, no_to_insert, axis): """Returns an updated merge area Parameters ---------- attrs: Dict \tCell attribute dictionary that shall be adjusted insertion_point: Integer \tPont on axis, before which insertion takes place no_to_insert: Integer >= 0 \tNumber of rows/cols/tabs that shall be inserted axis: Integer in range(2) \tSpecifies number of dimension, i.e. 0 == row, 1 == col """ assert axis in range(2) if "merge_area" not in attrs or attrs["merge_area"] is None: return top, left, bottom, right = attrs["merge_area"] selection = Selection([(top, left)], [(bottom, right)], [], [], []) selection.insert(insertion_point, no_to_insert, axis) __top, __left = selection.block_tl[0] __bottom, __right = selection.block_br[0] # Adjust merge area if it is beyond the grid shape rows, cols, tabs = self.shape if __top < 0 or __bottom >= rows or __left < 0 or __right >= cols: attrs["merge_area"] = None else: attrs["merge_area"] = __top, __left, __bottom, __right
def merge(self, merge_area, tab): """Merges top left cell with all cells until bottom_right""" top, left, bottom, right = merge_area cursor = self.grid.actions.cursor top_left_code = self.code_array((top, left, cursor[2])) selection = Selection([(top, left)], [(bottom, right)], [], [], []) # Check if the merge area overlaps another merge area error_msg = _("Overlapping merge area at {} prevents merge.") for row in xrange(top, bottom + 1): for col in xrange(left, right + 1): key = row, col, tab if self.code_array.cell_attributes[key]["merge_area"]: post_command_event(self.main_window, self.StatusBarMsg, text=error_msg.format(str(key))) return self.delete_selection(selection) self.set_code((top, left, cursor[2]), top_left_code) attr = {"merge_area": merge_area, "locked": True} self._set_cell_attr(selection, tab, attr) tl_selection = Selection([], [], [], [], [(top, left)]) attr = {"locked": False} self._set_cell_attr(tl_selection, tab, attr)
def set_border_attr(self, attr, value, borders): """Sets border attribute by adjusting selection to borders Parameters ---------- attr: String in ["borderwidth", "bordercolor"] \tBorder attribute that shall be changed value: wx.Colour or Integer \tAttribute value dependent on attribute type borders: Iterable over "top", "bottom", "left", "right", "inner" \tSpecifies to which borders of the selection the attr is applied """ selection = self.grid.selection if not selection: selection.cells.append(self.grid.actions.cursor[:2]) # determine selection for core cells and selection for border cells # Then apply according to inner and outer # A cell is inner iif it is not at the edge of the selection bbox if "inner" in borders: if "top" in borders: adj_selection = selection + (-1, 0) self.set_attr(attr + "_bottom", value, adj_selection) if "bottom" in borders: self.set_attr(attr + "_bottom", value) if "left" in borders: adj_selection = selection + (0, -1) self.set_attr(attr + "_right", value, adj_selection) if "right" in borders: self.set_attr(attr + "_right", value) else: # Adjust selection so that only bounding box edge is in selection bbox_tl, bbox_lr = selection.get_bbox() if "top" in borders: adj_selection = Selection([bbox_tl], [(bbox_tl[0], bbox_lr[1]) ], [], [], []) + (-1, 0) self.set_attr(attr + "_bottom", value, adj_selection) if "bottom" in borders: adj_selection = Selection([(bbox_lr[0], bbox_tl[1])], [bbox_lr], [], [], []) self.set_attr(attr + "_bottom", value, adj_selection) if "left" in borders: adj_selection = Selection([bbox_tl], [(bbox_lr[0], bbox_tl[1]) ], [], [], []) + (0, -1) self.set_attr(attr + "_right", value, adj_selection) if "right" in borders: adj_selection = Selection([(bbox_tl[0], bbox_lr[1])], [bbox_lr], [], [], []) self.set_attr(attr + "_right", value, adj_selection)
def _adjust_merge_area(self, attrs, insertion_point, no_to_insert, axis): """Returns an updated merge area :param attrs: Cell attribute dictionary that shall be adjusted :type attrs: dict :param insertion_point: Point on axis before insertion takes place :type insertion_point: int :param no_to_insert: Number of rows/cols/tabs that shall be inserted :type no_to_insert: int, >=0 :param axis: Specifies number of dimension, i.e. 0 == row, 1 == col :type axis: int in range(2) """ assert axis in range(2) if "merge_area" not in attrs or attrs["merge_area"] is None: return top, left, bottom, right = attrs["merge_area"] selection = Selection([(top, left)], [(bottom, right)], [], [], []) selection.insert(insertion_point, no_to_insert, axis) __top, __left = selection.block_tl[0] __bottom, __right = selection.block_br[0] # Adjust merge area if it is beyond the grid shape rows, cols, tabs = self.shape if __top < 0 and __bottom < 0 or __top >= rows and __bottom >= rows or\ __left < 0 and __right < 0 or __left >= cols and __right >= cols: return if __top < 0: __top = 0 if __top >= rows: __top = rows - 1 if __bottom < 0: __bottom = 0 if __bottom >= rows: __bottom = rows - 1 if __left < 0: __left = 0 if __left >= cols: __left = cols - 1 if __right < 0: __right = 0 if __right >= cols: __right = cols - 1 return __top, __left, __bottom, __right
def test_getitem(self): """Test __getitem__""" selection_1 = Selection([(2, 2)], [(4, 5)], [55], [55, 66], [(34, 56)]) selection_2 = Selection([], [], [], [], [(32, 53), (34, 56)]) self.cell_attr.append((selection_1, 0, {"testattr": 3})) self.cell_attr.append((selection_2, 0, {"testattr": 2})) assert self.cell_attr[32, 53, 0]["testattr"] == 2 assert self.cell_attr[2, 2, 0]["testattr"] == 3
def redo(self): # Store content of deleted columns self.old_col_widths = copy(self.model.code_array.col_widths) self.old_cell_attributes = copy(self.model.code_array.cell_attributes) self.old_code = {} columns = list(range(self.first, self.last + 1)) selection = Selection([], [], [], columns, []) for key in selection.cell_generator(self.model.shape, self.grid.table): self.old_code[key] = self.model.code_array(key) with self.model.removing_columns(self.index, self.first, self.last): self.model.removeColumns(self.column, self.count) self.grid.table_choice.on_table_changed(self.grid.current)
def redo(self): # Store content of deleted rows self.old_row_heights = copy(self.model.code_array.row_heights) self.old_cell_attributes = copy(self.model.code_array.cell_attributes) self.old_code = {} rows = list(range(self.first, self.last + 1)) selection = Selection([], [], rows, [], []) for key in selection.cell_generator(self.model.shape, self.grid.table): self.old_code[key] = self.model.code_array(key) with self.model.removing_rows(self.index, self.first, self.last): self.model.removeRows(self.row, self.count) self.grid.table_choice.on_table_changed(self.grid.current)
def test_refresh_selected_frozen_cells(self): """Unit test for refresh_selected_frozen_cells""" cell = (0, 0, 0) code1 = "1" code2 = "2" self.grid.actions.cursor = cell # Fill cell self.grid.code_array[cell] = code1 assert self.grid.code_array[cell] == 1 # Freeze cell self.grid.actions.cursor = cell self.grid.current_table = cell[2] self.grid.actions.change_frozen_attr() res = self.grid.code_array.frozen_cache[repr(cell)] assert res == eval(code1) # Change cell code self.grid.code_array[cell] = code2 assert self.grid.code_array[cell] == 1 # Refresh cell selection = Selection([], [], [], [], [cell[:2]]) self.grid.actions.refresh_selected_frozen_cells(selection=selection) assert self.grid.code_array[cell] == 2
def change_frozen_attr(self): """Changes frozen state of cell if there is no selection""" # Selections are not supported if self.grid.selection: statustext = _("Freezing selections is not supported.") post_command_event(self.main_window, self.StatusBarMsg, text=statustext) cursor = self.grid.actions.cursor frozen = self.grid.code_array.cell_attributes[cursor]["frozen"] if frozen: # We have an frozen cell that has to be unfrozen # Delete frozen cache content self.grid.code_array.frozen_cache.pop(repr(cursor)) else: # We have an non-frozen cell that has to be frozen # Add frozen cache content res_obj = self.grid.code_array[cursor] self.grid.code_array.frozen_cache[repr(cursor)] = res_obj # Set the new frozen state / code selection = Selection([], [], [], [], [cursor[:2]]) self.set_attr("frozen", not frozen, selection=selection)
def merge(self, merge_area, tab): """Merges top left cell with all cells until bottom_right""" top, left, bottom, right = merge_area selection = Selection([(top, left)], [(bottom, right)], [], [], []) attr = {"merge_area": merge_area} self._set_cell_attr(selection, tab, attr)
def unmerge(self, unmerge_area, tab): """Unmerges all cells in unmerge_area""" top, left, bottom, right = unmerge_area selection = Selection([(top, left)], [(bottom, right)], [], [], []) attr = {"merge_area": None, "locked": False} self._set_cell_attr(selection, tab, attr)
def _code_convert_1_2(self, key, code): """Converts chart and image code from v1.0 to v2.0""" def get_image_code(image_data, width, height): """Returns code string for v2.0""" image_buffer_tpl = 'bz2.decompress(base64.b85decode({data}))' image_array_tpl = 'numpy.frombuffer({buffer}, dtype="uint8")' image_matrix_tpl = '{array}.reshape({height}, {width}, 3)' image_buffer = image_buffer_tpl.format(data=image_data) image_array = image_array_tpl.format(buffer=image_buffer) image_matrix = image_matrix_tpl.format(array=image_array, height=height, width=width) return image_matrix start_str = "bz2.decompress(base64.b64decode('" size_start_str = "wx.ImageFromData(" if size_start_str in code and start_str in code: size_start = code.index(size_start_str) + len(size_start_str) size_str_list = code[size_start:].split(",")[:2] width, height = tuple(map(int, size_str_list)) # We have a cell that displays a bitmap data_start = code.index(start_str) + len(start_str) data_stop = code.find("'", data_start) enc_data = bytes(code[data_start:data_stop], encoding='utf-8') compressed_image_data = b64decode(enc_data) reenc_data = b85encode(compressed_image_data) code = get_image_code(repr(reenc_data), width, height) selection = Selection([], [], [], [], [(key[0], key[1])]) tab = key[2] attrs = {"renderer": "image"} self.cell_attributes_postfixes.append((selection, tab, attrs)) elif "charts.ChartFigure(" in code: # We have a matplotlib figure selection = Selection([], [], [], [], [(key[0], key[1])]) tab = key[2] attrs = {"renderer": "matplotlib"} self.cell_attributes_postfixes.append((selection, tab, attrs)) return code
def test_get_merging_cell(self): """Test get_merging_cell""" selection_1 = Selection([], [], [], [], [(2, 2)]) selection_2 = Selection([], [], [], [], [(3, 2)]) self.cell_attr.append((selection_1, 0, {"merge_area": (2, 2, 5, 5)})) self.cell_attr.append((selection_2, 0, {"merge_area": (3, 2, 9, 9)})) self.cell_attr.append((selection_1, 1, {"merge_area": (2, 2, 9, 9)})) # Cell 1. 1, 0 is not merged assert self.cell_attr.get_merging_cell((1, 1, 0)) is None # Cell 3. 3, 0 is merged to cell 3, 2, 0 assert self.cell_attr.get_merging_cell((3, 3, 0)) == (3, 2, 0) # Cell 2. 2, 0 is merged to cell 2, 2, 0 assert self.cell_attr.get_merging_cell((2, 2, 0)) == (2, 2, 0)
def OnTimer(self, event): """Update all frozen cells because of timer call""" self.timer_updating = True shape = self.grid.code_array.shape[:2] selection = Selection([(0, 0)], [(shape)], [], [], []) self.grid.actions.refresh_selected_frozen_cells(selection) self.grid.ForceRefresh()
def format_paste_format(self): """Pastes cell formats Pasting starts at cursor or at top left bbox corner """ clipboard = QApplication.clipboard() mime_data = clipboard.mimeData() grid = self.main_window.grid model = grid.model row, column, table = grid.current if "application/x-pyspread-cell-attributes" not in mime_data.formats(): return cas_data = mime_data.data("application/x-pyspread-cell-attributes") cas_data_str = str(cas_data, encoding='utf-8') cas = literal_eval(cas_data_str) assert isinstance(cas, list) tabu_attrs = "merge_area", "renderer", "frozen" description_tpl = "Paste format for selections {}" description = description_tpl.format([ca[0] for ca in cas]) for selection_params, attrs in cas: if not any(tabu_attr in attrs for tabu_attr in tabu_attrs): selection = Selection(*selection_params) shifted_selection = selection.shifted(row, column) new_cell_attribute = shifted_selection, table, attrs selected_idx = [] for key in shifted_selection.cell_generator(model.shape): selected_idx.append(model.index(*key)) command = CommandSetCellFormat(new_cell_attribute, model, grid.currentIndex(), selected_idx, description) self.main_window.undo_stack.push(command)
def _pys2attributes_10(self, line): """Updates attributes in code_array - for save file version 1.0""" splitline = self._split_tidy(line) selection_data = list(map(ast.literal_eval, splitline[:5])) selection = Selection(*selection_data) tab = int(splitline[5]) attrs = {} old_merged_cells = {} for col, ele in enumerate(splitline[6:]): if not (col % 2): # Odd entries are keys key = ast.literal_eval(ele) else: # Even cols are values value = ast.literal_eval(ele) # Convert old wx color values and merged cells key_, value_ = self._attr_convert_1to2(key, value) if key_ is None and value_ is not None: # We have a merged cell old_merged_cells[value_[:2]] = value_ try: attrs.pop("merge_area") except KeyError: pass attrs[key_] = value_ self.code_array.cell_attributes.append((selection, tab, attrs)) for key in old_merged_cells: selection = Selection([], [], [], [], [key]) attrs = {"merge_area": old_merged_cells[key]} self.code_array.cell_attributes.append((selection, tab, attrs)) old_merged_cells.clear()
def redo(self): row, column, table = current = self.current # Remove and store frozen cache content self.res_obj = self.model.code_array.frozen_cache.pop(repr(current)) # Remove the frozen state selection = Selection([], [], [], [], [(row, column)]) attr = selection, table, {"frozen": False} self.model.setData([], attr, Qt.DecorationRole) self.model.dataChanged.emit(QModelIndex(), QModelIndex())
def test_append(self): """Test append""" selection = Selection([], [], [], [], [(23, 12)]) table = 0 attr = {"angle": 0.2} self.cell_attr.append((selection, table, attr)) # Check if 1 item - the actual action has been added assert not self.cell_attr._attr_cache
def redo(self): row, column, table = self.current # Add frozen cache content res_obj = self.model.code_array[self.current] self.model.code_array.frozen_cache[repr(self.current)] = res_obj # Set the frozen state selection = Selection([], [], [], [], [(row, column)]) attr = selection, table, {"frozen": True} self.model.setData([], attr, Qt.DecorationRole) self.model.dataChanged.emit(QModelIndex(), QModelIndex())
def test_clear(self): """Tests empty_grid method""" # Set up self.grid self.grid.code_array[(0, 0, 0)] = "'Test1'" self.grid.code_array[(3, 1, 1)] = "'Test2'" self.grid.actions.set_col_width(1, 23) self.grid.actions.set_col_width(0, 233) self.grid.actions.set_row_height(0, 0) selection = Selection([], [], [], [], [(0, 0)]) self.grid.actions.set_attr("bgcolor", wx.RED, selection) self.grid.actions.set_attr("frozen", "print 'Testcode'", selection) # Clear self.grid self.grid.actions.clear() # Code content assert self.grid.code_array((0, 0, 0)) is None assert self.grid.code_array((3, 1, 1)) is None assert list(self.grid.code_array[:2, 0, 0]) == [None, None] # Cell attributes cell_attributes = self.grid.code_array.cell_attributes assert cell_attributes == [] # Row heights and column widths row_heights = self.grid.code_array.row_heights assert len(row_heights) == 0 col_widths = self.grid.code_array.col_widths assert len(col_widths) == 0 # Undo and redo undolist = self.grid.code_array.unredo.undolist redolist = self.grid.code_array.unredo.redolist assert undolist == [] assert redolist == [] # Caches # Clear self.grid again because lookup is added in resultcache self.grid.actions.clear() result_cache = self.grid.code_array.result_cache assert len(result_cache) == 0
def undo(self): row, column, table = self.key selection = Selection([], [], [], [], [(row, column)]) ca = selection, table, {"button_cell": self.text} self.grid.model.setData([self.index], ca, Qt.DecorationRole) if table == self.grid.table: # Only add widget if we are in the right table button = CellButton(self.text, self.grid, self.key) self.grid.setIndexWidget(self.index, button) self.grid.widget_indices.append(self.index) self.grid.model.dataChanged.emit(self.index, self.index)
def test_get_new_cell_attr_state(self, cell, attr, before, next): """Unit test for get_new_cell_attr_state""" self.grid.actions.cursor = cell self.grid.current_table = cell[2] selection = Selection([], [], [], [], [cell[:2]]) self.grid.actions.set_attr(attr, before, selection) res = self.grid.actions.get_new_cell_attr_state(cell, attr) assert res == next
def test_undoable_append(self): """Test undoable_append""" selection = Selection([], [], [], [], [(23, 12)]) table = 0 attr = {"angle": 0.2} self.cell_attr.undoable_append((selection, table, attr)) # Check if 2 items - the actual action and the marker - have been added assert len(self.cell_attr.unredo.undolist) == 2 assert len(self.cell_attr.unredo.redolist) == 0 assert not self.cell_attr._attr_cache
def test_adjust_cell_attributes(self, inspoint, noins, axis, src, target): """Unit test for _adjust_cell_attributes""" row, col, tab = src val = {"angle": 0.2} attrs = [(Selection([], [], [], [], [(row, col)]), tab, val)] self.data_array._set_cell_attributes(attrs) self.data_array._adjust_cell_attributes(inspoint, noins, axis) for key in val: assert self.data_array.cell_attributes[target][key] == val[key]
def undo(self): if self.index not in self.grid.widget_indices: return row, column, table = self.key selection = Selection([], [], [], [], [(row, column)]) ca = selection, table, {"button_cell": False} self.grid.model.setData([self.index], ca, Qt.DecorationRole) if table == self.grid.table: # Only remove widget if we are in the right table self.grid.setIndexWidget(self.index, None) self.grid.widget_indices.remove(self.index) self.grid.model.dataChanged.emit(self.index, self.index)
def _get_adjusted_merge_area(self, attrs, insertion_point, no_to_insert, axis): """Returns updated merge area Parameters ---------- attrs: Dict \tCell attribute dictionary that shall be adjusted insertion_point: Integer \tPont on axis, before which insertion takes place no_to_insert: Integer >= 0 \tNumber of rows/cols/tabs that shall be inserted axis: Integer in range(2) \tSpecifies number of dimension, i.e. 0 == row, 1 == col """ assert axis in range(2) if "merge_area" not in attrs or attrs["merge_area"] is None: return top, left, bottom, right = attrs["merge_area"] selection = Selection([(top, left)], [(bottom, right)], [], [], []) selection.insert(insertion_point, no_to_insert, axis) __top, __left = selection.block_tl[0] __bottom, __right = selection.block_br[0] # Adjust merge area if it is beyond the grid shape rows, cols, tabs = self.shape if __top < 0 or __bottom >= rows or __left < 0 or __right >= cols: return None else: return __top, __left, __bottom, __right
def get_selection(self): """Returns selected cells in grid as Selection object""" # GetSelectedCells: individual cells selected by ctrl-clicking # GetSelectedRows: rows selected by clicking on the labels # GetSelectedCols: cols selected by clicking on the labels # GetSelectionBlockTopLeft # GetSelectionBlockBottomRight: For blocks selected by dragging # across the grid cells. block_top_left = self.grid.GetSelectionBlockTopLeft() block_bottom_right = self.grid.GetSelectionBlockBottomRight() rows = self.grid.GetSelectedRows() cols = self.grid.GetSelectedCols() cells = self.grid.GetSelectedCells() return Selection(block_top_left, block_bottom_right, rows, cols, cells)
def test_get_xfstyle(self, key, sec_key, subsec_key, style_key, val, easyxf): """Test _get_xfstyle method""" row, col, tab = key pys_style = {style_key: val} dict_grid = self.code_array.dict_grid selection = Selection([], [], [], [], [(row, col)]) dict_grid.cell_attributes.append((selection, tab, pys_style)) xfstyle = self.xls_in._get_xfstyle([], key) style = xlwt.easyxf(easyxf) assert getattr(getattr(xfstyle, sec_key), subsec_key) == \ getattr(getattr(style, sec_key), subsec_key)
def _update_video_volume_cell_attributes(self, key): """Updates the panel cell attrutes of a panel cell""" try: video_cell_panel = self.grid_renderer.video_cells[key] except KeyError: return old_video_volume = self.code_array.cell_attributes[key]["video_volume"] new_video_volume = video_cell_panel.volume if old_video_volume == new_video_volume: return selection = Selection([], [], [], [], [key]) self.actions.set_attr("video_volume", new_video_volume, selection, mark_unredo=False)
def test_adjust_cell_attributes(self, inspoint, noins, axis, src, target): """Unit test for _adjust_cell_attributes""" row, col, tab = src val = {"angle": 0.2} attrs = [(Selection([], [], [], [], [(row, col)]), tab, val)] self.data_array._set_cell_attributes(attrs) self.data_array._adjust_cell_attributes(inspoint, noins, axis) if target is None: for key in val: # Should be at default value cell_attributes = self.data_array.cell_attributes default_ca = cell_attributes.default_cell_attributes[key] assert cell_attributes[src][key] == default_ca else: for key in val: assert self.data_array.cell_attributes[target][key] == val[key]
class TestSelection(object): """Unit tests for Selection""" def setup_method(self, method): """Creates selection""" self.selection = Selection([], [], [], [], [(32, 53), (34, 56)]) self.SelectionCls = grid_actions.Selection def test_nonzero(self): """Unit test for __nonzero__""" pass def test_repr(self): """Unit test for __repr__""" assert str(self.selection) == \ "Selection([], [], [], [], [(32, 53), (34, 56)])" def test_eq(self): """Unit test for __eq__""" pass def test_contains(self): """Unit test for __contains__ Used in: ele in selection""" assert (32, 53) in self.selection assert not (23, 34534534) in self.selection # Test block selection selection = self.SelectionCls([(4, 5)], [(100, 200)], [], [], []) cells_in_selection = ((i, j) for i in xrange(4, 100, 5) for j in xrange(5, 200, 5)) for cell in cells_in_selection: assert cell in selection cells_not_in_selection = \ [(0, 0), (0, 1), (1, 0), (1, 1), (4, 4), (3, 5), (100, 201), (101, 200), (101, 201), (10**10, 10**10), [0, 0]] for cell in cells_not_in_selection: assert cell not in selection # Test row selection # Test column selection # Test cell selection def test_insert(self): """Unit test for insert""" pass def test_get_bbox(self): """Unit test for get_bbox""" assert self.selection.get_bbox() == ((32, 53), (34, 56)) sel_tl, sel_br = [(4, 5)], [(100, 200)] selection = self.SelectionCls(sel_tl, sel_br, [], [], []) bbox_tl, bbox_br = selection.get_bbox() assert bbox_tl == sel_tl[0] assert bbox_br == sel_br[0]
def _adjust_cell_attributes(self, insertion_point, no_to_insert, axis, tab=None, cell_attrs=None, mark_unredo=True): """Adjusts cell attributes on insertion/deletion""" if mark_unredo: self.unredo.mark() old_cell_attrs = self.cell_attributes[:] if axis < 2: # Adjust selections if cell_attrs is None: cell_attrs = [] for key in self.cell_attributes: selection, table, value = key if tab is None or tab == table: new_sel = copy(selection) new_val = copy(value) new_sel.insert(insertion_point, no_to_insert, axis) # Update merge area if present if "merge_area" in value: top, left, bottom, right = value["merge_area"] ma_sel = Selection([(top, left)], [(bottom, right)], [], [], []) ma_sel.insert(insertion_point, no_to_insert, axis) __top, __left = ma_sel.block_tl[0] __bottom, __right = ma_sel.block_br[0] new_val["merge_area"] = \ __top, __left, __bottom, __right cell_attrs.append((new_sel, table, new_val)) self.cell_attributes[:] = cell_attrs self.cell_attributes._attr_cache.clear() elif axis == 2: # Adjust tabs new_tabs = [] for selection, old_tab, value in self.cell_attributes: if old_tab > insertion_point and \ (tab is None or tab == old_tab): new_tabs.append((selection, old_tab + no_to_insert, value)) else: new_tabs.append(None) for i, sel_tab_val in enumerate(new_tabs): if sel_tab_val is not None: self.dict_grid.cell_attributes.set_item(i, sel_tab_val) self.cell_attributes._attr_cache.clear() else: raise ValueError("Axis must be in [0, 1, 2]") undo_operation = (self._adjust_cell_attributes, [insertion_point, -no_to_insert, axis, tab, old_cell_attrs, mark_unredo]) redo_operation = (self._adjust_cell_attributes, [insertion_point, no_to_insert, axis, tab, cell_attrs, mark_unredo]) self.unredo.append(undo_operation, redo_operation) if mark_unredo: self.unredo.mark()
def setup_method(self, method): """Creates selection""" self.selection = Selection([], [], [], [], [(32, 53), (34, 56)]) self.SelectionCls = grid_actions.Selection
def _xls2attributes(self, worksheet, tab): """Updates attributes in code_array""" # Merged cells for top, bottom, left, right in worksheet.merged_cells: attrs = {"merge_area": (top, left, bottom - 1, right - 1)} selection = Selection([(top, left)], [(bottom - 1, right - 1)], [], [], []) self.code_array.cell_attributes.append((selection, tab, attrs)) # Which cell comprise which format ids xf2cell = dict((xfid, []) for xfid in xrange(self.workbook.xfcount)) rows, cols = worksheet.nrows, worksheet.ncols for row, col in product(xrange(rows), xrange(cols)): xfid = worksheet.cell_xf_index(row, col) xf2cell[xfid].append((row, col)) for xfid, xf in enumerate(self.workbook.xf_list): selection = Selection([], [], [], [], xf2cell[xfid]) selection_above = selection.shifted(-1, 0) selection_left = selection.shifted(0, -1) attributes = {} # Alignment xfalign2justification = { 0: "left", 1: "left", 2: "center", 3: "right", 4: "left", 5: "left", 6: "center", 7: "left", } xfalign2vertical_align = { 0: "top", 1: "middle", 2: "bottom", 3: "middle", 4: "middle", } def xfrotation2angle(xfrotation): """Returns angle from xlrotatation""" # angle is counterclockwise if 0 <= xfrotation <= 90: return xfrotation elif 90 < xfrotation <= 180: return - (xfrotation - 90) return 0 try: attributes["justification"] = \ xfalign2justification[xf.alignment.hor_align] attributes["vertical_align"] = \ xfalign2vertical_align[xf.alignment.vert_align] attributes["angle"] = \ xfrotation2angle(xf.alignment.rotation) except AttributeError: pass # Background if xf.background.fill_pattern == 1: color_idx = xf.background.pattern_colour_index color = self.idx2colour(color_idx) attributes["bgcolor"] = color.GetRGB() # Border __border_line_style2width = { 0: 1, 1: 1, 2: 4, 5: 7, } def constant_factory(value): return repeat(value).next border_line_style2width = defaultdict(constant_factory(1)) border_line_style2width.update(__border_line_style2width) bottom_color_idx = xf.border.bottom_colour_index if bottom_color_idx in self.workbook.colour_map and \ self.workbook.colour_map[bottom_color_idx] is not None: bottom_color = self.idx2colour(bottom_color_idx) attributes["bordercolor_bottom"] = bottom_color.GetRGB() right_color_idx = xf.border.right_colour_index if right_color_idx in self.workbook.colour_map and \ self.workbook.colour_map[right_color_idx] is not None: right_color = self.idx2colour(right_color_idx) attributes["bordercolor_right"] = right_color.GetRGB() bottom_width = border_line_style2width[xf.border.bottom_line_style] attributes["borderwidth_bottom"] = bottom_width right_width = border_line_style2width[xf.border.right_line_style] attributes["borderwidth_right"] = right_width # Font font = self.workbook.font_list[xf.font_index] attributes["textfont"] = font.name attributes["pointsize"] = font.height / 20.0 fontweight = wx.BOLD if font.weight == 700 else wx.NORMAL attributes["fontweight"] = fontweight if font.italic: attributes["fontstyle"] = wx.ITALIC if font.colour_index in self.workbook.colour_map and \ self.workbook.colour_map[font.colour_index] is not None: attributes["textcolor"] = \ self.idx2colour(font.colour_index).GetRGB() if font.underline_type: attributes["underline"] = True if font.struck_out: attributes["strikethrough"] = True # Handle top cells' top borders attributes_above = {} top_width = border_line_style2width[xf.border.top_line_style] if top_width != 1: attributes_above["borderwidth_bottom"] = top_width top_color_idx = xf.border.top_colour_index if top_color_idx in self.workbook.colour_map and \ self.workbook.colour_map[top_color_idx] is not None: top_color = self.idx2colour(top_color_idx) attributes_above["bordercolor_bottom"] = top_color.GetRGB() # Handle leftmost cells' left borders attributes_left = {} left_width = border_line_style2width[xf.border.left_line_style] if left_width != 1: attributes_left["borderwidth_right"] = left_width left_color_idx = xf.border.left_colour_index if left_color_idx in self.workbook.colour_map and \ self.workbook.colour_map[left_color_idx] is not None: left_color = self.idx2colour(left_color_idx) attributes_above["bordercolor_right"] = left_color.GetRGB() if attributes_above: self._cell_attribute_append(selection_above, tab, attributes_above) if attributes_left: self._cell_attribute_append(selection_left, tab, attributes_left) if attributes: self._cell_attribute_append(selection, tab, attributes)