# ~ FILTER_PDF = '/org.openoffice.Office.Common/Filter/PDF/Export/' # ~ If location="document" Then # ~ sp = ThisComponent.getScriptProvider() class LOWriter(LODocument): def create_chart(self, tipo, cursor=None): cursor = cursor or self.selection.cursor.getEnd() chart = LOChart(None, tipo) chart.cursor = cursor chart.doc = self return chart # ~ f = doc.createInstance('com.sun.star.text.TextFrame') # ~ f.setSize(Size(10000, 500)) class LOBase(object): TYPES = { str: 'setString', int: 'setInt', float: 'setFloat', bool: 'setBoolean', Date: 'setDate', Time: 'setTime', DateTime: 'setTimestamp', } # ~ setArray # ~ setBinaryStream # ~ setBlob # ~ setByte # ~ setBytes # ~ setCharacterStream # ~ setClob # ~ setNull # ~ setObject # ~ setObjectNull # ~ setObjectWithInfo # ~ setPropertyValue # ~ setRef def __init__(self, name, path='', **kwargs): self._name = name self._path = path self._dbc = create_instance('com.sun.star.sdb.DatabaseContext') if path: path_url = _path_url(path) db = self._dbc.createInstance() db.URL = 'sdbc:embedded:firebird' db.DatabaseDocument.storeAsURL(path_url, ()) if not self.exists: self._dbc.registerDatabaseLocation(name, path_url) else: if name.startswith('odbc:'): self._con = self._odbc(name, kwargs) else: db = self._dbc.getByName(name) self.path = _path_system(self._dbc.getDatabaseLocation(name)) self._con = db.getConnection('', '') if self._con is None: msg = 'Not connected to: {}'.format(name) else: msg = 'Connected to: {}'.format(name) debug(msg) def _odbc(self, name, kwargs): dm = create_instance('com.sun.star.sdbc.DriverManager') args = dict_to_property(kwargs) try: con = dm.getConnectionWithInfo('sdbc:{}'.format(name), args) return con except Exception as e: error(str(e)) return None @property def obj(self): return self._obj @property def name(self): return self._name @property def connection(self): return self._con @property def path(self): return self._path @path.setter def path(self, value): self._path = value @property def exists(self): return self._dbc.hasRegisteredDatabase(self.name) @classmethod def register(self, path, name): if not self._dbc.hasRegisteredDatabase(name): self._dbc.registerDatabaseLocation(name, _path_url(path)) return def revoke(self, name): self._dbc.revokeDatabaseLocation(name) return True def save(self): # ~ self._db.connection.commit() # ~ self._db.connection.getTables().refresh() # ~ oDisp.executeDispatch(oFrame,".uno:DBRefreshTables", "", 0, Array()) self._obj.DatabaseDocument.store() self.refresh() return def close(self): self._con.close() return def refresh(self): self._con.getTables().refresh() return def get_tables(self): tables = self._con.getTables() tables = [tables.getByIndex(i) for i in range(tables.Count)] return tables def cursor(self, sql, params): cursor = self._con.prepareStatement(sql) for i, v in enumerate(params, 1): if not type(v) in self.TYPES: error('Type not support') debug((i, type(v), v, self.TYPES[type(v)])) getattr(cursor, self.TYPES[type(v)])(i, v) return cursor def execute(self, sql, params): debug(sql) if params: cursor = self.cursor(sql, params) cursor.execute() else: cursor = self._con.createStatement() cursor.execute(sql) # ~ resulset = cursor.executeQuery(sql) # ~ rows = cursor.executeUpdate(sql) self.save() return cursor class EventsModify(EventsListenerBase, XModifyListener): def __init__(self, controller): super().__init__(controller) def modified(self, event): event_name = '{}_modified'.format(event.Source.Name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) return class EventsKeyWindow(EventsListenerBase, XKeyListener): """ event.KeyChar event.KeyCode event.KeyFunc event.Modifiers """ def __init__(self, cls): super().__init__(cls.events, cls.name) self._cls = cls def keyPressed(self, event): pass def keyReleased(self, event): event_name = '{}_key_released'.format(self._cls.name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) else: if event.KeyFunc == QUIT and hasattr(self._cls, 'close'): self._cls.close() return class EventsWindow(EventsListenerBase, XTopWindowListener, XWindowListener): def __init__(self, cls): self._cls = cls super().__init__(cls.events, cls.name, cls._window) def windowOpened(self, event): event_name = '{}_opened'.format(self._name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) return def windowActivated(self, event): control_name = '{}_activated'.format(event.Source.Model.Name) if hasattr(self._controller, control_name): getattr(self._controller, control_name)(event) return def windowDeactivated(self, event): control_name = '{}_deactivated'.format(event.Source.Model.Name) if hasattr(self._controller, control_name): getattr(self._controller, control_name)(event) return def windowMinimized(self, event): pass def windowNormalized(self, event): pass def windowClosing(self, event): if self._window: control_name = 'window_closing' else: control_name = '{}_closing'.format(event.Source.Model.Name) if hasattr(self._controller, control_name): getattr(self._controller, control_name)(event) # ~ else: # ~ if not self._modal and not self._block: # ~ event.Source.Visible = False return def windowClosed(self, event): control_name = '{}_closed'.format(event.Source.Model.Name) if hasattr(self._controller, control_name): getattr(self._controller, control_name)(event) return # ~ XWindowListener def windowResized(self, event): sb = self._cls._subcont sb.setPosSize(0, 0, event.Width, event.Height, SIZE) event_name = '{}_resized'.format(self._name) if hasattr(self._controller, event_name): getattr(self._controller, event_name)(event) return def windowMoved(self, event): pass def windowShown(self, event): pass def windowHidden(self, event): pass class WriterTableRange(ObjectBase): def __init__(self, obj, index, table_name): self._index = index self._table_name = table_name super().__init__(obj) self._is_cell = hasattr(self.obj, 'CellName') def __getitem__(self, key): obj = super().__getitem__(key) return WriterTableRange(obj, key, self._table_name) @property def value(self): return self.obj.String @value.setter def value(self, value): self.obj.String = value @property def data(self): return self.obj.getDataArray() @data.setter def data(self, values): if isinstance(values, list): values = tuple(values) self.obj.setDataArray(values) @property def rows(self): return len(self.data) @property def columns(self): return len(self.data[0]) @property def name(self): if self._is_cell: name = '{}.{}'.format(self._table_name, self.obj.CellName) elif isinstance(self._index, str): name = '{}.{}'.format(self._table_name, self._index) else: c1 = self.obj[0,0].CellName c2 = self.obj[self.rows-1,self.columns-1].CellName name = '{}.{}:{}'.format(self._table_name, c1, c2) return name def get_cell(self, *index): return self[index] def get_column(self, index=0, start=1): return self[start:self.rows,index:index+1] def get_series(self): class Serie(): pass series = [] for i in range(self.columns): serie = Serie() serie.label = self.get_cell(0,i).name serie.data = self.get_column(i).data serie.values = self.get_column(i).name series.append(serie) return series class ChartFormat(object): def __call__(self, obj): for k, v in self.__dict__.items(): if hasattr(obj, k): setattr(obj, k, v) class LOChart(object): BASE = 'com.sun.star.chart.{}Diagram' def __init__(self, obj, tipo=''): self._obj = obj self._type = tipo self._name = '' self._table = None self._data = () self._data_series = () self._cell = None self._cursor = None self._doc = None self._title = ChartFormat() self._subtitle = ChartFormat() self._legend = ChartFormat() self._xaxistitle = ChartFormat() self._yaxistitle = ChartFormat() self._xaxis = ChartFormat() self._yaxis = ChartFormat() self._xmaingrid = ChartFormat() self._ymaingrid = ChartFormat() self._xhelpgrid = ChartFormat() self._yhelpgrid = ChartFormat() self._area = ChartFormat() self._wall = ChartFormat() self._dim3d = False self._series = () self._labels = () return def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.insert() @property def obj(self): return self._obj @obj.setter def obj(self, value): self._obj = value @property def name(self): return self._name @name.setter def name(self, value): self._name = value @property def type(self): return self._type @type.setter def type(self, value): self._type = value @property def table(self): return self._table @table.setter def table(self, value): self._table = value @property def data(self): return self._data @data.setter def data(self, value): self._data = value @property def cell(self): return self._cell @cell.setter def cell(self, value): self._cell = value self.doc = value.doc @property def cursor(self): return self._cursor @cursor.setter def cursor(self, value): self._cursor = value @property def doc(self): return self._doc @doc.setter def doc(self, value): self._doc = value @property def width(self): return self._width @width.setter def width(self, value): self._width = value @property def height(self): return self._height @height.setter def height(self, value): self._height = value @property def title(self): return self._title @property def subtitle(self): return self._subtitle @property def legend(self): return self._legend @property def xaxistitle(self): return self._xaxistitle @property def yaxistitle(self): return self._yaxistitle @property def xaxis(self): return self._xaxis @property def yaxis(self): return self._yaxis @property def xmaingrid(self): return self._xmaingrid @property def ymaingrid(self): return self._ymaingrid @property def xhelpgrid(self): return self._xhelpgrid @property def yhelpgrid(self): return self._yhelpgrid @property def area(self): return self._area @property def wall(self): return self._wall @property def dim3d(self): return self._dim3d @dim3d.setter def dim3d(self, value): self._dim3d = value @property def series(self): return self._series @series.setter def series(self, value): self._series = value @property def data_series(self): return self._series @data_series.setter def data_series(self, value): self._data_series = value @property def labels(self): return self._labels @labels.setter def labels(self, value): self._labels = value def _add_series_writer(self, chart): dp = self.doc.create_instance('com.sun.star.chart2.data.DataProvider') chart.attachDataProvider(dp) chart_type = chart.getFirstDiagram().getCoordinateSystems()[0].getChartTypes()[0] self._data_series = self.table[self.data].get_series() series = [self._create_serie(dp, s) for s in self._data_series[1:]] chart_type.setDataSeries(tuple(series)) chart_data = chart.getData() chart_data.ComplexRowDescriptions = self._data_series[0].data return def _get_series(self): rango = self._data_series class Serie(): pass series = [] for i in range(0, rango.columns, 2): serie = Serie() serie.label = rango[0, i+1].name serie.xvalues = rango.get_column(i).name serie.values = rango.get_column(i+1).name series.append(serie) return series def _add_series_calc(self, chart): dp = self.doc.create_instance('com.sun.star.chart2.data.DataProvider') chart.attachDataProvider(dp) chart_type = chart.getFirstDiagram().getCoordinateSystems()[0].getChartTypes()[0] series = self._get_series() series = [self._create_serie(dp, s) for s in series] chart_type.setDataSeries(tuple(series)) return def _create_serie(self, dp, data): serie = create_instance('com.sun.star.chart2.DataSeries') rango = data.values is_x = hasattr(data, 'xvalues') if is_x: xrango = data.xvalues rango_label = data.label lds = create_instance('com.sun.star.chart2.data.LabeledDataSequence') values = self._create_data(dp, rango, 'values-y') lds.setValues(values) if data.label: label = self._create_data(dp, rango_label, '') lds.setLabel(label) xlds = () if is_x: xlds = create_instance('com.sun.star.chart2.data.LabeledDataSequence') values = self._create_data(dp, xrango, 'values-x') xlds.setValues(values) if is_x: serie.setData((lds, xlds)) else: serie.setData((lds,)) return serie def _create_data(self, dp, rango, role): data = dp.createDataSequenceByRangeRepresentation(rango) if not data is None: data.Role = role return data def _from_calc(self): ps = self.cell.ps ps.Width = self.width ps.Height = self.height charts = self.cell.charts data = () if self.data: data = (self.data.address,) charts.addNewByName(self.name, ps, data, True, True) self.obj = charts.getByName(self.name) chart = self.obj.getEmbeddedObject() chart.setDiagram(chart.createInstance(self.BASE.format(self.type))) if not self.data: self._add_series_calc(chart) return chart def _from_writer(self): obj = self.doc.create_instance('com.sun.star.text.TextEmbeddedObject') obj.setPropertyValue('CLSID', '12DCAE26-281F-416F-a234-c3086127382e') obj.Name = self.name obj.setSize(Size(self.width, self.height)) self.doc.insert_content(self.cursor, obj) self.obj = obj chart = obj.getEmbeddedObject() tipo = self.type if self.type == 'Column': tipo = 'Bar' chart.Diagram.Vertical = True chart.setDiagram(chart.createInstance(self.BASE.format(tipo))) chart.DataSourceLabelsInFirstColumn = True if isinstance(self.data, str): self._add_series_writer(chart) else: chart_data = chart.getData() labels = [r[0] for r in self.data] data = [(r[1],) for r in self.data] chart_data.setData(data) chart_data.RowDescriptions = labels # ~ Bug if tipo == 'Pie': chart.setDiagram(chart.createInstance(self.BASE.format('Bar'))) chart.setDiagram(chart.createInstance(self.BASE.format('Pie'))) return chart def insert(self): if not self.cell is None: chart = self._from_calc() elif not self.cursor is None: chart = self._from_writer() diagram = chart.Diagram if self.type == 'Bar': diagram.Vertical = True if hasattr(self.title, 'String'): chart.HasMainTitle = True self.title(chart.Title) if hasattr(self.subtitle, 'String'): chart.HasSubTitle = True self.subtitle(chart.SubTitle) if self.legend.__dict__: chart.HasLegend = True self.legend(chart.Legend) if self.xaxistitle.__dict__: diagram.HasXAxisTitle = True self.xaxistitle(diagram.XAxisTitle) if self.yaxistitle.__dict__: diagram.HasYAxisTitle = True self.yaxistitle(diagram.YAxisTitle) if self.dim3d: diagram.Dim3D = True if self.series: data_series = chart.getFirstDiagram( ).getCoordinateSystems( )[0].getChartTypes()[0].DataSeries for i, serie in enumerate(data_series): for k, v in self.series[i].items(): if hasattr(serie, k): setattr(serie, k, v) return self class LODialog(object): def _get_type_control(self, name): types = { 'stardiv.Toolkit.UnoFixedTextControl': 'label', 'stardiv.Toolkit.UnoFixedHyperlinkControl': 'link', 'stardiv.Toolkit.UnoEditControl': 'text', 'stardiv.Toolkit.UnoButtonControl': 'button', 'stardiv.Toolkit.UnoListBoxControl': 'listbox', 'stardiv.Toolkit.UnoRoadmapControl': 'roadmap', 'stardiv.Toolkit.UnoMultiPageControl': 'pages', } return types[name] def _init_controls(self): for control in self.obj.getControls(): tipo = self._get_type_control(control.ImplementationName) name = control.Model.Name control = get_custom_class(tipo, control) setattr(self, name, control) return class LOWindow(object): EMPTY = b""" """ def __init__(self, **kwargs): self._events = None self._menu = None self._container = None self._id_extension = '' self._obj = self._create(kwargs) @property def id_extension(self): return self._id_extension @id_extension.setter def id_extension(self, value): global ID_EXTENSION ID_EXTENSION = value self._id_extension = value def _get_base_control(self, tipo): services = { 'label': 'com.sun.star.awt.UnoControlFixedText', 'button': 'com.sun.star.awt.UnoControlButton', 'text': 'com.sun.star.awt.UnoControlEdit', 'listbox': 'com.sun.star.awt.UnoControlListBox', 'link': 'com.sun.star.awt.UnoControlFixedHyperlink', 'roadmap': 'com.sun.star.awt.UnoControlRoadmap', 'image': 'com.sun.star.awt.UnoControlImageControl', 'groupbox': 'com.sun.star.awt.UnoControlGroupBox', 'radio': 'com.sun.star.awt.UnoControlRadioButton', 'tree': 'com.sun.star.awt.tree.TreeControl', 'grid': 'com.sun.star.awt.grid.UnoControlGrid', 'tab': 'com.sun.star.awt.tab.UnoControlTabPage', } return services[tipo] def _special_properties(self, tipo, properties): columns = properties.pop('Columns', ()) if tipo == 'grid': properties['ColumnModel'] = self._set_column_model(columns) elif tipo == 'button' and 'ImageURL' in properties: properties['ImageURL'] = _set_image_url( properties['ImageURL'], self.id_extension) elif tipo == 'roadmap': if not 'Height' in properties: properties['Height'] = self.height if 'Title' in properties: properties['Text'] = properties.pop('Title') elif tipo == 'tab': if not 'Width' in properties: properties['Width'] = self.width - 20 if not 'Height' in properties: properties['Height'] = self.height - 20 return properties def add_control(self, properties): tipo = properties.pop('Type').lower() root = properties.pop('Root', '') sheets = properties.pop('Sheets', ()) properties = self._special_properties(tipo, properties) model = self._subcont.Model.createInstance(get_control_model(tipo)) set_properties(model, properties) name = properties['Name'] self._subcont.Model.insertByName(name, model) control = self._subcont.getControl(name) add_listeners(self.events, control, name) control = get_custom_class(tipo, control) if tipo == 'tree' and root: control.root = root elif tipo == 'tab' and sheets: control.sheets = sheets control.events = self.events setattr(self, name, control) return def _add_listeners(self, control=None): if self.events is None: return controller = EventsWindow(self) self._window.addTopWindowListener(controller) self._window.addWindowListener(controller) self._container.addKeyListener(EventsKeyWindow(self)) return @property def name(self): return self._title.lower().replace(' ', '_') @property def width(self): return self._container.Size.Width @property def height(self): return self._container.Size.Height # ~ Export ok def merge_zip(target, zips): try: with zipfile.ZipFile(target, 'w', compression=zipfile.ZIP_DEFLATED) as t: for path in zips: with zipfile.ZipFile(path, compression=zipfile.ZIP_DEFLATED) as s: for name in s.namelist(): t.writestr(name, s.open(name).read()) except Exception as e: error(e) return False return True # ~ Export ok def format(template, data): """ https://pyformat.info/ """ if isinstance(data, (str, int, float)): return template.format(data) if isinstance(data, (Time, Date, DateTime)): return template.format(_to_date(data)) if isinstance(data, tuple) and isinstance(data[0], tuple): data = {r[0]: _to_date(r[1]) for r in data} return template.format(**data) data = [_to_date(v) for v in data] result = template.format(*data) return result