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 replace(self, findpos, find_string, replace_string): """Replaces occurrences of find_string with replace_string at findpos and marks content as changed Parameters ---------- findpos: 3-Tuple of Integer \tPosition in grid that shall be replaced find_string: String \tString to be overwritten in the cell replace_string: String \tString to be used for replacement """ # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) old_code = self.grid.code_array(findpos) new_code = old_code.replace(find_string, replace_string) self.grid.code_array[findpos] = new_code self.grid.actions.cursor = findpos statustext = _("Replaced {old} with {new} in cell {key}.") statustext = statustext.format(old=old_code, new=new_code, key=findpos) post_command_event(self.main_window, self.StatusBarMsg, text=statustext)
def replace_all(self, findpositions, find_string, replace_string): """Replaces occurrences of find_string with replace_string at findpos and marks content as changed Parameters ---------- findpositions: List of 3-Tuple of Integer \tPositions in grid that shall be replaced find_string: String \tString to be overwritten in the cell replace_string: String \tString to be used for replacement """ # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) for findpos in findpositions: old_code = self.grid.code_array(findpos) new_code = old_code.replace(find_string, replace_string) self.grid.code_array[findpos] = new_code statustext = _("Replaced {no_cells} cells.") statustext = statustext.format(no_cells=len(findpositions)) post_command_event(self.main_window, self.StatusBarMsg, text=statustext) self.grid.ForceRefresh()
def switch_to_table(self, event): """Switches grid to table Parameters ---------- event.newtable: Integer \tTable that the grid is switched to """ newtable = event.newtable no_tabs = self.grid.code_array.shape[2] - 1 if 0 <= newtable <= no_tabs: self.grid.current_table = newtable # Change value of entry_line and table choice post_command_event(self.main_window, self.TableChangedMsg, table=newtable) # Reset row heights and column widths by zooming self.zoom()
def set_cursor(self, value): """Changes the grid cursor cell. Parameters ---------- value: 2-tuple or 3-tuple of String \trow, col, tab or row, col for target cursor position """ if len(value) == 3: self.grid._last_selected_cell = row, col, tab = value if tab != self.cursor[2]: post_command_event(self.main_window, self.GridActionTableSwitchMsg, newtable=tab) if is_gtk(): wx.Yield() else: row, col = value self.grid._last_selected_cell = row, col, self.grid.current_table if not (row is None and col is None): self.grid.MakeCellVisible(row, col) self.grid.SetGridCursor(row, col)
def OnInit(self): """Init class that is automatically run on __init__""" # Get command line options and arguments self.get_cmd_args() # Initialize the prerequisitions to construct the main window InitAllImageHandlers() # Main window creation from src.gui._main_window import MainWindow self.main_window = MainWindow(None, title="pyspread") ## Set dimensions ## Initialize file loading via event # Create GPG key if not present from src.lib.gpg import genkey genkey() # Show application window self.SetTopWindow(self.main_window) self.main_window.Show() # Load filename if provided if self.filepath is not None: post_command_event(self.main_window, self.GridActionOpenMsg, attr={"filepath": self.filepath}) self.main_window.filepath = self.filepath return True
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 progress_status(self): """Displays progress in statusbar""" if self.line % self.freq == 0: text = self.statustext.format(nele=self.line, totalele=self.total_lines) if self.main_window.grid.actions.pasting: try: post_command_event(self.main_window, self.main_window.StatusBarMsg, text=text) except TypeError: # The main window does not exist any more pass else: # Write directly to the status bar because the event queue # is not emptied during file access self.main_window.GetStatusBar().SetStatusText(text) # Now wait for the statusbar update to be written on screen if is_gtk(): try: wx.Yield() except: pass self.line += 1
def OnMacroListLoad(self, event): """Macro list load event handler""" # Get filepath from user wildcards = get_filetypes2wildcards(["py", "all"]).values() wildcard = "|".join(wildcards) message = _("Choose macro file.") style = wx.OPEN filepath, filterindex = \ self.interfaces.get_filepath_findex_from_user(wildcard, message, style) if filepath is None: return # Enter safe mode because macro file could be harmful post_command_event(self.main_window, self.main_window.SafeModeEntryMsg) # Load macros from file self.main_window.actions.open_macros(filepath) event.Skip()
def zoom(self, zoom=None): """Zooms to zoom factor""" status = True if zoom is None: zoom = self.grid.grid_renderer.zoom status = False # Zoom factor for grid content self.grid.grid_renderer.zoom = zoom # Zoom grid labels self._zoom_labels(zoom) # Zoom rows and columns self._zoom_rows(zoom) self._zoom_cols(zoom) self.grid.ForceRefresh() if status: statustext = _(u"Zoomed to {0:.2f}.").format(zoom) post_command_event(self.main_window, self.StatusBarMsg, text=statustext)
def OnApply(self, event): """Event handler for Apply button""" post_command_event(self.parent, self.MacroReplaceMsg, macros=self.macros) post_command_event(self.parent, self.MacroExecuteMsg) event.Skip()
def switch_to_table(self, event): """Switches grid to table Parameters ---------- event.newtable: Integer \tTable that the grid is switched to """ newtable = event.newtable no_tabs = self.grid.code_array.shape[2] - 1 if 0 <= newtable <= no_tabs: self.grid.current_table = newtable self.main_window.table_choice.SetMax(newtable + 1) self.main_window.table_choice.SetValue(newtable) # Reset row heights and column widths by zooming self.zoom() statustext = _("Switched to table {}.").format(newtable) post_command_event(self.main_window, self.StatusBarMsg, text=statustext)
def sign_file(self, filepath): """Signs file if possible""" signature = sign(filepath) if signature is None: statustext = _('Error signing file. File is not signed.') try: post_command_event(self.main_window, self.StatusBarMsg, text=statustext) except TypeError: # The main window does not exist any more pass return signfile = open(filepath + '.sig', 'wb') signfile.write(signature) signfile.close() # Statustext differs if a save has occurred if self.code_array.safe_mode: statustext = _('File saved and signed') else: statustext = _('File signed') try: post_command_event(self.main_window, self.StatusBarMsg, text=statustext) except TypeError: # The main window does not exist any more pass
def import_file(self, filepath, filterindex): """Imports external file Parameters ---------- filepath: String \tPath of import file filterindex: Integer \tIndex for type of file, 0: csv, 1: tab-delimited text file """ # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg) if filterindex == 0: # CSV import option choice return self._import_csv(filepath) elif filterindex == 1: # TXT import option choice return self._import_txt(filepath) else: msg = _("Unknown import choice {choice}.") msg = msg.format(choice=filterindex) short_msg = _('Error reading CSV file') self.main_window.interfaces.display_warning(msg, short_msg)
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 write(self, iterable): """Writes values from iterable into CSV file""" io_error_text = _("Error writing to file {filepath}.") io_error_text = io_error_text.format(filepath=self.path) try: with open(self.path, "wb") as csvfile: csv_writer = csv.writer(csvfile, self.dialect) for line in iterable: csv_writer.writerow( list(encode_gen(line, encoding=self.encoding))) except IOError: txt = \ _("Error opening file {filepath}.").format(filepath=self.path) try: post_command_event(self.main_window, self.StatusBarMsg, text=txt) except TypeError: # The main window does not exist any more pass return False
def paste(self, tl_key, data, freq=None): """Pastes data into grid, marks grid changed If no selection is present, data is pasted starting with current cell If a selection is present, data is pasted fully if the selection is smaller. If the selection is larger then data is duplicated. Parameters ---------- ul_key: Tuple \key of top left cell of paste area data: iterable of iterables where inner iterable returns string \tThe outer iterable represents rows freq: Integer, defaults to None \tStatus message frequency """ # Get selection bounding box selection = self.get_selection() # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) if selection: # There is a selection. Paste into it self.paste_to_selection(selection, data, freq=freq) else: # There is no selection. Paste from top left cell. self.paste_to_current_cell(tl_key, data, freq=freq)
def save_macros(self, filepath, macros): """Saves macros to file Parameters ---------- filepath: String \tPath to macro file macros: String \tMacro code """ io_error_text = _("Error writing to file {filepath}.") io_error_text = io_error_text.format(filepath=filepath) try: with open(filepath, "w") as macro_outfile: macro_outfile.write(macros) except IOError: txt = _("Error opening file {filepath}.").format(filepath=filepath) try: post_command_event(self.main_window, self.StatusBarMsg, text=txt) except TypeError: # The main window does not exist any more pass wx.EndBusyCursor() return False
def _set_cell_attr(self, selection, table, attr): """Sets cell attr for key cell and mark grid content as changed Parameters ---------- attr: dict \tContains cell attribute keys \tkeys in ["borderwidth_bottom", "borderwidth_right", \t"bordercolor_bottom", "bordercolor_right", \t"bgcolor", "textfont", \t"pointsize", "fontweight", "fontstyle", "textcolor", "underline", \t"strikethrough", "angle", "column-width", "row-height", \t"vertical_align", "justification", "frozen", "merge_area"] """ # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) if selection is not None: cell_attributes = self.code_array.cell_attributes cell_attributes.undoable_append((selection, table, attr), mark_unredo=False)
def redo(self): """Calls redo in model.code_array.unredo, marks content as changed""" # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) self.grid.code_array.unredo.redo()
def delete_cols(self, col, no_cols=1): """Deletes no_cols column and marks grid as changed""" # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) self.code_array.delete(col, no_cols, axis=1)
def delete_rows(self, row, no_rows=1): """Deletes no_rows rows and marks grid as changed""" # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) self.code_array.delete(row, no_rows, axis=0)
def execute_macros(self): """Executes macros and marks grid as changed""" # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) self.grid.code_array.execute_macros()
def __init__(self, main_window, path): self.main_window = main_window try: self.infile = open(path, "r") except IOError: statustext = "Error opening file " + path + "." post_command_event(self.main_window, self.StatusBarMsg, text=statustext) self.infile = None
def _abort_paste(self): """Aborts import""" statustext = _("Paste aborted.") post_command_event(self.main_window, self.StatusBarMsg, text=statustext) self.pasting = False self.need_abort = False
def _set_properties(self): """Setup title, icon, size, scale, statusbar, main grid""" self.set_icon(icons["PyspreadLogo"]) # Without minimum size, initial size is minimum size in wxGTK self.minSizeSet = False # Leave save mode post_command_event(self, self.SafeModeExitMsg)
def _show_final_paste_message(self, tl_key, no_pasted_cells): """Show actually pasted number of cells""" plural = "" if no_pasted_cells == 1 else _("s") statustext = _("{ncells} cell{plural} pasted at cell {topleft}").\ format(ncells=no_pasted_cells, plural=plural, topleft=tl_key) post_command_event(self.main_window, self.StatusBarMsg, text=statustext)
def __init__(self, main_window, path): self.main_window = main_window try: self.infile = open(path) except IOError: statustext = "Error opening file " + path + "." post_command_event(self.main_window, self.StatusBarMsg, text=statustext) self.infile = None
def _is_aborted(self, cycle, statustext, total_elements=None, freq=None): """Displays progress and returns True if abort Parameters ---------- cycle: Integer \tThe current operation cycle statustext: String \tLeft text in statusbar to be displayed total_elements: Integer: \tThe number of elements that have to be processed freq: Integer, defaults to None \tNo. operations between two abort possibilities, 1000 if None """ if total_elements is None: statustext += _("{nele} elements processed. Press <Esc> to abort.") else: statustext += _("{nele} of {totalele} elements processed. " "Press <Esc> to abort.") if freq is None: show_msg = False freq = 1000 else: show_msg = True # Show progress in statusbar each freq (1000) cells if cycle % freq == 0: if show_msg: text = statustext.format(nele=cycle, totalele=total_elements) try: post_command_event(self.main_window, self.StatusBarMsg, text=text) except TypeError: # The main window does not exist any more pass # Now wait for the statusbar update to be written on screen if is_gtk(): try: wx.Yield() except: pass # Abort if we have to if self.need_abort: # We have to abort` return True # Continue return False
def execute_macros(self): """Executes macros and marks grid as changed""" # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg) (result, err) = self.grid.code_array.execute_macros() # Post event to macro dialog post_command_event(self.main_window, self.MacroErrorMsg, msg=result, err=err)
def set_col_width(self, col, width): """Sets column width and marks grid as changed""" # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) tab = self.grid.current_table self.code_array.set_col_width(col, tab, width) self.grid.SetColSize(col, width)
def set_row_height(self, row, height): """Sets row height and marks grid as changed""" # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) tab = self.grid.current_table self.code_array.set_row_height(row, tab, height) self.grid.SetRowSize(row, height)
def leave_safe_mode(self): """Leaves safe mode""" self.code_array.safe_mode = False # Clear result cache self.code_array.result_cache.clear() # Execute macros self.main_window.actions.execute_macros() post_command_event(self.main_window, self.SafeModeExitMsg)
def Draw(self, grid, attr, dc, rect, row, col, isSelected): """Draws the cell border and content using pycairo""" key = row, col, grid.current_table # If cell is merge draw the merging cell if invisibile if grid.code_array.cell_attributes[key]["merge_area"]: key = self.get_merging_cell(grid, key) drawn_rect = self._get_drawn_rect(grid, key, rect) if drawn_rect is None: return cell_cache_key = self._get_draw_cache_key(grid, key, drawn_rect, isSelected) mdc = wx.MemoryDC() if vlc is not None and key in self.video_cells and \ grid.code_array.cell_attributes[key]["panel_cell"]: # Update video position of previously created video panel self.video_cells[key].SetClientRect(drawn_rect) elif cell_cache_key in self.cell_cache: mdc.SelectObject(self.cell_cache[cell_cache_key]) else: code = grid.code_array(key) if vlc is not None and code is not None and \ grid.code_array.cell_attributes[key]["panel_cell"]: try: # A panel is to be displayed panel_cls = grid.code_array[key] # Assert that we have a subclass of a wxPanel that we # can instantiate assert issubclass(panel_cls, wx.Panel) video_panel = panel_cls(grid) video_panel.SetClientRect(drawn_rect) # Register video cell self.video_cells[key] = video_panel return except Exception, err: # Someting is wrong with the panel to be displayed post_command_event(grid.main_window, self.StatusBarMsg, text=unicode(err)) bmp = self._get_cairo_bmp(mdc, key, drawn_rect, isSelected, grid._view_frozen) else:
def _is_aborted(self, cycle, statustext, total_elements=None, freq=None): """Displays progress and returns True if abort Parameters ---------- cycle: Integer \tThe current operation cycle statustext: String \tLeft text in statusbar to be displayed total_elements: Integer: \tThe number of elements that have to be processed freq: Integer, defaults to None \tNo. operations between two abort possibilities, 1000 if None """ if total_elements is None: statustext += _("{nele} elements processed. Press <Esc> to abort.") else: statustext += _("{nele} of {totalele} elements processed. " "Press <Esc> to abort.") if freq is None: show_msg = False freq = 1000 else: show_msg = True # Show progress in statusbar each freq (1000) cells if cycle % freq == 0: if show_msg: text = statustext.format(nele=cycle, totalele=total_elements) try: post_command_event(self.main_window, self.StatusBarMsg, text=text) except TypeError: # The main window does not exist any more pass # Now wait for the statusbar update to be written on screen if is_gtk(): wx.Yield() # Abort if we have to if self.need_abort: # We have to abort` return True # Continue return False
def save(self, event): """Saves a file that is specified in event.attr Parameters ---------- event.attr: Dict \tkey filepath contains file path of file to be saved """ filepath = event.attr["filepath"] try: filetype = event.attr["filetype"] except KeyError: filetype = "pys" Interface = self.type2interface[filetype] io_error_text = _("Error writing to file {filepath}.") io_error_text = io_error_text.format(filepath=filepath) # Set state to file saving self.saving = True # Make sure that old save file does not get lost on abort save tmpfile = filepath + "~" try: wx.BeginBusyCursor() self.grid.Disable() if filetype == "pys": with Bz2AOpen(tmpfile, "wb", main_window=self.main_window) \ as outfile: try: interface = Interface(self.grid.code_array, outfile) interface.from_code_array() except ValueError, err: post_command_event(self.main_window, self.StatusBarMsg, text=err) elif filetype == "xls": workbook = xlwt.Workbook() interface = Interface(self.grid.code_array, workbook) interface.from_code_array() workbook.save(tmpfile)
def approve(self, filepath): """Sets safe mode if signature missing of invalid""" try: signature_valid = self.validate_signature(filepath) except ValueError: # GPG is not installed signature_valid = False if signature_valid: self.leave_safe_mode() post_command_event(self.main_window, self.SafeModeExitMsg) statustext = _("Valid signature found. File is trusted.") post_command_event(self.main_window, self.StatusBarMsg, text=statustext) else: self.enter_safe_mode() post_command_event(self.main_window, self.SafeModeEntryMsg) statustext = \ _("File is not properly signed. Safe mode " "activated. Select File -> Approve to leave safe mode.") post_command_event(self.main_window, self.StatusBarMsg, text=statustext)
def write(self, *args, **kwargs): """Write that shows progress in statusbar for each <freq> cells""" self.progress_status() # Check abortes state and raise StopIteration if aborted if self.aborted: statustext = _("File saving aborted.") post_command_event(self.main_window, self.main_window.StatusBarMsg, text=statustext) return False return self.parent_cls.write(self, *args, **kwargs)
def next(self): """Next that shows progress in statusbar for each <freq> cells""" self.progress_status() # Check abortes state and raise StopIteration if aborted if self.aborted: statustext = _("File loading aborted.") post_command_event(self.main_window, self.main_window.StatusBarMsg, text=statustext) raise StopIteration return self.parent_cls.next(self)
def insert_cols(self, col, no_cols=1): """Adds no_cols columns before col, appends if col > maxcols and marks grid as changed """ # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) tab = self.grid.current_table self.code_array.insert(col, no_cols, axis=1, tab=tab)
def OnClearGlobals(self, event): """Clear globals event handler""" msg = _("Deleting globals and reloading modules cannot be undone." " Proceed?") short_msg = _("Really delete globals and modules?") choice = self.main_window.interfaces.get_warning_choice(msg, short_msg) if choice: self.main_window.grid.actions.clear_globals_reload_modules() statustext = _("Globals cleared and base modules reloaded.") post_command_event(self.main_window, self.main_window.StatusBarMsg, text=statustext)
def insert_rows(self, row, no_rows=1): """Adds no_rows rows before row, appends if row > maxrows and marks grid as changed """ # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) tab = self.grid.current_table self.code_array.insert(row, no_rows, axis=0, tab=tab)
def change_grid_shape(self, shape): """Grid shape change event handler, marks content as changed""" # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) self.grid.code_array.shape = shape # Update TableChoiceIntCtrl post_command_event(self.main_window, self.ResizeGridMsg, shape=shape) # Clear caches self.code_array.unredo.reset() self.code_array.result_cache.clear()
def OnInit(self): """Init class that is automatically run on __init__""" # Get command line options and arguments cmdp = Commandlineparser() options, filename = cmdp.parse() kwargs = {"title": "pyspread", "S": self.S} # Store command line input in config if no file is provided if filename is None: kwargs["dimensions"] = options.dimensions # Main window creation from src.gui._main_window import MainWindow self.main_window = MainWindow(None, **kwargs) # Initialize file loading via event if options.new_gpgkey: # Create GPG key if not present try: from src.lib.gpg import genkey self.config["gpg_key_fingerprint"] = repr("") genkey() except ImportError: pass except ValueError: # python-gnupg is installed but gnupg is not installed pass # Show application window self.SetTopWindow(self.main_window) self.main_window.Show() # Load filename if provided if filename is not None: post_command_event(self.main_window, self.GridActionOpenMsg, attr={"filepath": filename}) self.main_window.filepath = filename return True
def on_mouse_over(self, key): """Displays cell code of cell key in status bar""" def split_lines(string, line_length=80): """Returns string that is split into lines of length line_length""" result = u"" line = 0 while len(string) > line_length * line: line_start = line * line_length result += string[line_start:line_start + line_length] result += '\n' line += 1 return result[:-1] row, col, tab = key if (row, col) != self.prev_rowcol and row >= 0 and col >= 0: self.prev_rowcol[:] = [row, col] max_result_length = int(config["max_result_length"]) table = self.grid.GetTable() hinttext = table.GetSource(row, col, tab)[:max_result_length] if hinttext is None: hinttext = '' post_command_event(self.main_window, self.StatusBarMsg, text=hinttext) cell_res = self.grid.code_array[row, col, tab] if cell_res is None: self.grid.SetToolTip(None) return try: cell_res_str = unicode(cell_res) except UnicodeEncodeError: cell_res_str = unicode(cell_res, encoding='utf-8') if len(cell_res_str) > max_result_length: cell_res_str = cell_res_str[:max_result_length] + ' [...]' self.grid.SetToolTipString(split_lines(cell_res_str))
def delete_cols(self, col, no_cols=1): """Deletes no_cols column and marks grid as changed""" # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) tab = self.grid.current_table try: self.code_array.delete(col, no_cols, axis=1, tab=tab) except ValueError, err: post_command_event(self.main_window, self.StatusBarMsg, text=err.message)
def insert_tabs(self, tab, no_tabs=1): """Adds no_tabs tabs before table, appends if tab > maxtabs and marks grid as changed """ # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) self.code_array.insert(tab, no_tabs, axis=2) # Update TableChoiceIntCtrl shape = self.grid.code_array.shape post_command_event(self.main_window, self.ResizeGridMsg, shape=shape)
def save_macros(self, filepath, macros): """Saves macros to file Parameters ---------- filepath: String \tPath to macro file macros: String \tMacro code """ io_error_text = _("Error writing to file {filepath}.") io_error_text = io_error_text.format(filepath=filepath) # Make sure that old macro file does not get lost on abort save tmpfile = filepath + "~" try: wx.BeginBusyCursor() self.main_window.grid.Disable() with open(tmpfile, "w") as macro_outfile: macro_outfile.write(macros) # Move save file from temp file to filepath try: os.rename(tmpfile, filepath) except OSError: # No tmp file present pass except IOError: try: post_command_event(self.main_window, self.StatusBarMsg, text=io_error_text) except TypeError: # The main window does not exist any more pass return False finally: self.main_window.grid.Enable() wx.EndBusyCursor()
def set_code(self, key, code, mark_unredo=True): """Sets code of cell key, marks grid as changed""" old_code = self.grid.code_array(key) try: old_code = unicode(old_code, encoding="utf-8") except TypeError: pass if not (old_code is None and not code) and code != old_code: # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) # Set cell code self.grid.code_array.__setitem__(key, code, mark_unredo=mark_unredo)
def clear(self, shape=None): """Empties grid and sets shape to shape Clears all attributes, row heights, column withs and frozen states. Empties undo/redo list and caches. Empties globals. Properties ---------- shape: 3-tuple of Integer, defaults to None \tTarget shape of grid after clearing all content. \tShape unchanged if None """ # Without setting this explicitly, the cursor is set too late self.grid.actions.cursor = 0, 0, 0 self.grid.current_table = 0 post_command_event(self.main_window.grid, self.GotoCellMsg, key=(0, 0, 0)) # Clear cells self.code_array.dict_grid.clear() # Clear attributes del self.code_array.dict_grid.cell_attributes[:] if shape is not None: # Set shape self.code_array.shape = shape # Clear row heights and column widths self.code_array.row_heights.clear() self.code_array.col_widths.clear() # Clear caches self.code_array.unredo.reset() self.code_array.result_cache.clear() # Clear globals self.code_array.clear_globals() self.code_array.reload_modules()
def OnContentChanged(self, event): """Titlebar star adjustment event handler""" self.main_window.grid.update_attribute_toolbar() title = self.main_window.GetTitle() if undo.stack().haschanged(): # Put * in front of title if title[:2] != "* ": new_title = "* " + title post_command_event(self.main_window, self.main_window.TitleMsg, text=new_title) elif title[:2] == "* ": # Remove * in front of title new_title = title[2:] post_command_event(self.main_window, self.main_window.TitleMsg, text=new_title)
def delete_selection(self): """Deletes selected cells, marks content as changed""" # Mark content as changed post_command_event(self.main_window, self.ContentChangedMsg, changed=True) selection = self.get_selection() current_table = self.grid.current_table for row, col, tab in self.grid.code_array.dict_grid.keys(): if tab == current_table and (row, col) in selection: self.grid.actions.delete_cell((row, col, tab), mark_unredo=False) self.grid.code_array.unredo.mark() self.grid.code_array.result_cache.clear()
def OnTextColorDialog(self, event): """Event handler for launching text color dialog""" dlg = wx.ColourDialog(self.main_window) # Ensure the full colour dialog is displayed, # not the abbreviated version. dlg.GetColourData().SetChooseFull(True) if dlg.ShowModal() == wx.ID_OK: # Fetch color data data = dlg.GetColourData() color = data.GetColour().GetRGB() post_command_event(self.main_window, self.main_window.TextColorMsg, color=color) dlg.Destroy()
def _show_final_overflow_message(self, row_overflow, col_overflow): """Displays overflow message after import in statusbar""" if row_overflow and col_overflow: overflow_cause = _("rows and columns") elif row_overflow: overflow_cause = _("rows") elif col_overflow: overflow_cause = _("columns") else: raise AssertionError(_("Import cell overflow missing")) statustext = \ _("The imported data did not fit into the grid {cause}. " "It has been truncated. Use a larger grid for full import.").\ format(cause=overflow_cause) post_command_event(self.main_window, self.StatusBarMsg, text=statustext)
def OnInit(self): """Init class that is automatically run on __init__""" # Get command line options and arguments self.get_cmd_args() # Initialize the prerequisitions to construct the main window wx.InitAllImageHandlers() # Main window creation from src.gui._main_window import MainWindow self.main_window = MainWindow(None, title="pyspread", S=self.S) ## Initialize file loading via event # Create GPG key if not present try: from src.lib.gpg import genkey genkey() except ImportError: pass except ValueError: # python-gnupg is installed but gnupg is not insatlled pass # Show application window self.SetTopWindow(self.main_window) self.main_window.Show() # Load filename if provided if self.filepath is not None: post_command_event(self.main_window, self.GridActionOpenMsg, attr={"filepath": self.filepath}) self.main_window.filepath = self.filepath return True