Copy from and to

This commit is contained in:
Mauricio Baeza 2019-10-10 00:07:45 -05:00
parent 3813ba9d87
commit aa905e19f3
1 changed files with 516 additions and 40 deletions

View File

@ -60,11 +60,14 @@ import mailbox
import uno
import unohelper
from com.sun.star.util import Time, Date, DateTime
from com.sun.star.beans import PropertyValue
from com.sun.star.beans import PropertyValue, NamedValue
from com.sun.star.awt import MessageBoxButtons as MSG_BUTTONS
from com.sun.star.awt.MessageBoxResults import YES
from com.sun.star.awt.PosSize import POSSIZE, SIZE
from com.sun.star.awt import Size, Point
from com.sun.star.awt import Rectangle
from com.sun.star.awt import KeyEvent
from com.sun.star.awt.KeyFunction import QUIT
from com.sun.star.datatransfer import XTransferable, DataFlavor
from com.sun.star.table.CellContentType import EMPTY, VALUE, TEXT, FORMULA
@ -73,7 +76,12 @@ from com.sun.star.text.TextContentAnchorType import AS_CHARACTER
from com.sun.star.lang import XEventListener
from com.sun.star.awt import XActionListener
from com.sun.star.awt import XMouseListener
from com.sun.star.awt import XMouseMotionListener
from com.sun.star.util import XModifyListener
from com.sun.star.awt import XTopWindowListener
from com.sun.star.awt import XWindowListener
from com.sun.star.awt import XMenuListener
from com.sun.star.awt import XKeyListener
try:
from fernet import Fernet, InvalidToken
@ -696,6 +704,12 @@ class LOCalc(LODocument):
index = [s.Name for s in self._sheets if s.CodeName == index][0] or index
return LOCalcSheet(self._sheets[index], self)
def __setitem__(self, key, value):
self._sheets[key] = value
def __contains__(self, item):
return item in self.obj.Sheets
@property
def active(self):
return LOCalcSheet(self._cc.getActiveSheet(), self)
@ -729,7 +743,12 @@ class LOCalc(LODocument):
obj = self.obj.getStyleFamilies()['CellStyles']
return LOCellStyles(obj)
def insert(self, name, pos):
def create(self):
return self.obj.createInstance('com.sun.star.sheet.Spreadsheet')
def insert(self, name, pos=-1):
# ~ sheet = obj.createInstance('com.sun.star.sheet.Spreadsheet')
# ~ obj.Sheets['New'] = sheet
index = pos
if pos < 0:
index = self._sheets.Count + pos + 1
@ -741,6 +760,12 @@ class LOCalc(LODocument):
name = n
return LOCalcSheet(self._sheets[name], self)
def move(self, name, pos=-1):
return self.sheets.move(name, pos)
def remove(self, name):
return self.sheets.remove(name)
def copy(self, source='', target='', pos=-1):
index = pos
if pos < 0:
@ -763,7 +788,7 @@ class LOCalc(LODocument):
return LOCalcSheet(self._sheets[index], self)
def copy_from(self, doc, source, target, pos):
def copy_from(self, doc, source='', target='', pos=-1):
index = pos
if pos < 0:
index = self._sheets.Count + pos + 1
@ -876,6 +901,12 @@ class LOCalcSheet(object):
def __getitem__(self, index):
return LOCellRange(self.obj[index], self.doc)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
pass
def _init_values(self):
self._events = None
@ -905,6 +936,31 @@ class LOCalcSheet(object):
self.doc.activate(self.obj)
return
@property
def visible(self):
return self.obj.IsVisible
@visible.setter
def visible(self, value):
self.obj.IsVisible = value
@property
def password(self):
return ''
@visible.setter
def password(self, value):
self.obj.protect(value)
def unprotect(self, value):
try:
self.obj.unprotect(value)
return True
except:
pass
return False
def get_cursor(self, cell):
return self.obj.createCursorByRange(cell)
@property
def events(self):
return self._events
@ -1171,7 +1227,7 @@ class LOCellRange(object):
def __enter__(self):
return self
def __exit__(self, *args):
def __exit__(self, exc_type, exc_value, traceback):
pass
def __getitem__(self, index):
@ -1240,19 +1296,72 @@ class LOCellRange(object):
values = tuple(values)
self.obj.setDataArray(values)
@property
def formula(self):
return self.obj.getFormulaArray()
@formula.setter
def formula(self, values):
if isinstance(values, list):
values = tuple(values)
self.obj.setFormulaArray(values)
@property
def columns(self):
return self._obj.Columns.Count
@property
def rows(self):
return self._obj.Rows.Count
def to_size(self, rows, cols):
cursor = self.sheet.get_cursor(self.obj[0,0])
cursor.collapseToSize(cols, rows)
return LOCellRange(self.sheet[cursor.AbsoluteName].obj, self.doc)
def copy_from(self, rango):
data = rango
if isinstance(rango, LOCellRange):
data = rango.data
rows = len(data)
cols = len(data[0])
self.to_size(rows, cols).data = data
return
def copy_to(self, cell, formula=False):
rango = cell.to_size(self.rows, self.columns)
if formula:
rango.formula = self.data
else:
rango.data = self.data
return
def offset(self, row=1, col=0):
ra = self.obj.getRangeAddress()
col = ra.EndColumn + col
row = ra.EndRow + row
return LOCellRange(self.sheet[row, col], self.doc)
return LOCellRange(self.sheet[row, col].obj, self.doc)
@property
def next_cell(self):
a = self.current_region.address
if hasattr(a, 'StartColumn'):
col = a.StartColumn
else:
col = a.Column
if hasattr(a, 'EndRow'):
row = a.EndRow + 1
else:
row = a.Row + 1
return LOCellRange(self.sheet[row, col].obj, self.doc)
@property
def sheet(self):
return self.obj.Spreadsheet
return LOCalcSheet(self.obj.Spreadsheet, self.doc)
@property
def draw_page(self):
return self.sheet.getDrawPage()
return self.sheet.obj.getDrawPage()
@property
def name(self):
@ -1270,9 +1379,23 @@ class LOCellRange(object):
@property
def current_region(self):
cursor = self.sheet.createCursorByRange(self.obj[0,0])
cursor = self.sheet.get_cursor(self.obj[0,0])
cursor.collapseToCurrentRegion()
return LOCellRange(self.sheet[cursor.AbsoluteName], self.doc)
return LOCellRange(self.sheet[cursor.AbsoluteName].obj, self.doc)
@property
def visible(self):
cursor = self.sheet.get_cursor(self.obj)
rangos = [LOCellRange(self.sheet[r.AbsoluteName].obj, self.doc)
for r in cursor.queryVisibleCells()]
return tuple(rangos)
@property
def empty(self):
cursor = self.sheet.get_cursor(self.obj)
rangos = [LOCellRange(self.sheet[r.AbsoluteName].obj, self.doc)
for r in cursor.queryEmptyCells()]
return tuple(rangos)
@property
def cell_style(self):
@ -1308,7 +1431,7 @@ class LOCellRange(object):
address = rango.address
else:
address = rango.getRangeAddress()
cursor = self.sheet.createCursorByRange(self.obj)
cursor = self.sheet.get_cursor(self.obj)
result = cursor.queryIntersection(address)
return bool(result.Count)
@ -1316,11 +1439,16 @@ class LOCellRange(object):
self.obj.fillAuto(0, source)
return
def clear(self, what=31):
self.obj.clearContents(what)
return
class EventsListenerBase(unohelper.Base, XEventListener):
def __init__(self, controller, window=None):
def __init__(self, controller, name, window=None):
self._controller = controller
self._name = name
self._window = window
def disposing(self, event):
@ -1331,25 +1459,23 @@ class EventsListenerBase(unohelper.Base, XEventListener):
class EventsButton(EventsListenerBase, XActionListener):
def __init__(self, controller):
super().__init__(controller)
def __init__(self, controller, name):
super().__init__(controller, name)
def actionPerformed(self, event):
name = event.Source.Model.Name
event_name = '{}_action'.format(name)
event_name = '{}_action'.format(self._name)
if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(event)
return
class EventsMouse(EventsListenerBase, XMouseListener):
class EventsMouse(EventsListenerBase, XMouseListener, XMouseMotionListener):
def __init__(self, controller):
super().__init__(controller)
def __init__(self, controller, name):
super().__init__(controller, name)
def mousePressed(self, event):
name = event.Source.Model.Name
event_name = '{}_click'.format(name)
event_name = '{}_click'.format(self._name)
if event.ClickCount == 2:
event_name = '{}_double_click'.format(name)
if hasattr(self._controller, event_name):
@ -1365,6 +1491,13 @@ class EventsMouse(EventsListenerBase, XMouseListener):
def mouseExited(self, event):
pass
# ~ XMouseMotionListener
def mouseMoved(self, event):
pass
def mouseDragged(self, event):
pass
class EventsMouseGrid(EventsMouse):
selected = False
@ -1406,6 +1539,125 @@ class EventsModify(EventsListenerBase, XModifyListener):
return
class EventsKey(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._container.getControl('subcontainer')
# ~ 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 EventsMenu(EventsListenerBase, XMenuListener):
def __init__(self, controller):
super().__init__(controller, '')
def itemHighlighted(self, event):
pass
@catch_exception
def itemSelected(self, event):
name = event.Source.getCommand(event.MenuId)
if name.startswith('menu'):
event_name = '{}_selected'.format(name)
else:
event_name = 'menu_{}_selected'.format(name)
if hasattr(self._controller, event_name):
getattr(self._controller, event_name)(event)
return
def itemActivated(self, event):
return
def itemDeactivated(self, event):
return
class UnoBaseObject(object):
def __init__(self, obj):
@ -1429,19 +1681,39 @@ class UnoBaseObject(object):
def parent(self):
return self.obj.getContext()
def _get_possize(self, name):
ps = self.obj.getPosSize()
return getattr(ps, name)
def _set_possize(self, name, value):
ps = self.obj.getPosSize()
setattr(ps, name, value)
self.obj.setPosSize(ps.X, ps.Y, ps.Width, ps.Height, POSSIZE)
return
@property
def x(self):
return self.model.PositionX
if hasattr(self.model, 'PositionX'):
return self.model.PositionX
return self._get_possize('X')
@x.setter
def x(self, value):
self.model.PositionX = value
if hasattr(self.model, 'PositionX'):
self.model.PositionX = value
else:
self._set_possize('X', value)
@property
def y(self):
return self.model.PositionY
if hasattr(self.model, 'PositionY'):
return self.model.PositionY
return self._get_possize('Y')
@y.setter
def y(self, value):
self.model.PositionY = value
if hasattr(self.model, 'PositionY'):
self.model.PositionY = value
else:
self._set_possize('Y', value)
@property
def width(self):
@ -1452,7 +1724,10 @@ class UnoBaseObject(object):
@property
def height(self):
return self._model.Height
if hasattr(self._model, 'Height'):
return self._model.Height
ps = self.obj.getPosSize()
return ps.Height
@height.setter
def height(self, value):
self._model.Height = value
@ -1699,9 +1974,45 @@ class UnoGrid(UnoBaseObject):
return
def get_custom_class(tipo, obj):
classes = {
'label': UnoLabel,
'button': UnoButton,
'text': UnoText,
'listbox': UnoListBox,
'grid': UnoGrid,
# ~ 'link': UnoLink,
# ~ 'tab': UnoTab,
# ~ 'roadmap': UnoRoadmap,
# ~ 'image': UnoImage,
# ~ 'radio': UnoRadio,
# ~ 'groupbox': UnoGroupBox,
# ~ 'tree': UnoTree,
}
return classes[tipo](obj)
def add_listeners(events, control, name=''):
listeners = {
'addActionListener': EventsButton,
'addMouseListener': EventsMouse,
}
if hasattr(control, 'obj'):
control = contro.obj
is_grid = control.ImplementationName == 'stardiv.Toolkit.GridControl'
for key, value in listeners.items():
if hasattr(control, key):
if is_grid and key == 'addMouseListener':
control.addMouseListener(EventsMouseGrid(events))
continue
getattr(control, key)(listeners[key](events, name))
return
class LODialog(object):
def __init__(self, properties):
def __init__(self, **properties):
self._obj = self._create(properties)
self._init_values()
@ -1799,13 +2110,13 @@ class LODialog(object):
}
return services[control]
def _get_custom_class(self, tipo, obj):
classes = {
'label': UnoLabel,
'button': UnoButton,
'text': UnoText,
'listbox': UnoListBox,
'grid': UnoGrid,
# ~ def _get_custom_class(self, tipo, obj):
# ~ classes = {
# ~ 'label': UnoLabel,
# ~ 'button': UnoButton,
# ~ 'text': UnoText,
# ~ 'listbox': UnoListBox,
# ~ 'grid': UnoGrid,
# ~ 'link': UnoLink,
# ~ 'tab': UnoTab,
# ~ 'roadmap': UnoRoadmap,
@ -1813,8 +2124,8 @@ class LODialog(object):
# ~ 'radio': UnoRadio,
# ~ 'groupbox': UnoGroupBox,
# ~ 'tree': UnoTree,
}
return classes[tipo](obj)
# ~ }
# ~ return classes[tipo](obj)
def _set_column_model(self, columns):
#~ https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1awt_1_1grid_1_1XGridColumn.html
@ -1846,12 +2157,174 @@ class LODialog(object):
set_properties(model, properties)
name = properties['Name']
self.model.insertByName(name, model)
control = self._get_custom_class(tipo, self.obj.getControl(name))
self._add_listeners(control)
control = self.obj.getControl(name)
add_listeners(self.events, control, name)
control = get_custom_class(tipo, control)
setattr(self, name, control)
return
class LOWindow(object):
def __init__(self, **kwargs):
self._events = None
self._menu = None
self._container = None
self._obj = self._create(kwargs)
def _create(self, properties):
ps = (
properties.get('X', 0),
properties.get('Y', 0),
properties.get('Width', 500),
properties.get('Height', 500),
)
self._title = properties.get('Title', TITLE)
self._create_frame(ps)
self._create_container(ps)
# ~ self._create_splitter(ps)
return
def _create_frame(self, ps):
service = 'com.sun.star.frame.TaskCreator'
tc = create_instance(service, True)
self._frame = tc.createInstanceWithArguments((
NamedValue('FrameName', 'EasyMacroWin'),
NamedValue('PosSize', Rectangle(*ps)),
))
self._window = self._frame.getContainerWindow()
self._toolkit = self._window.getToolkit()
desktop = get_desktop()
self._frame.setCreator(desktop)
desktop.getFrames().append(self._frame)
self._frame.Title = self._title
return
def _create_container(self, ps):
# ~ toolkit = self._window.getToolkit()
service = 'com.sun.star.awt.UnoControlContainer'
self._container = create_instance(service, True)
service = 'com.sun.star.awt.UnoControlContainerModel'
model = create_instance(service, True)
model.BackgroundColor = get_color(225, 225, 225)
self._container.setModel(model)
self._container.createPeer(self._toolkit, self._window)
self._container.setPosSize(*ps, POSSIZE)
self._frame.setComponent(self._container, None)
return
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',
}
return services[tipo]
def add_control(self, properties):
tipo = properties.pop('Type').lower()
base = self._get_base_control(tipo)
obj = create_instance(base, True)
model = create_instance('{}Model'.format(base), True)
set_properties(model, properties)
obj.setModel(model)
x = properties.get('X', 5)
y = properties.get('Y', 5)
w = properties.get('Width', 200)
h = properties.get('Height', 25)
obj.setPosSize(x, y, w, h, POSSIZE)
name = properties['Name']
self._container.addControl(name, obj)
add_listeners(self.events, obj, name)
control = get_custom_class(tipo, obj)
setattr(self, name, control)
return
def _create_popupmenu(self, menus):
menu = create_instance('com.sun.star.awt.PopupMenu', True)
for i, m in enumerate(menus):
label = m['label']
cmd = m.get('event', '')
if not cmd:
cmd = label.lower().replace(' ', '_')
if label == '-':
menu.insertSeparator(i)
else:
menu.insertItem(i, label, m.get('style', 0), i)
menu.setCommand(i, cmd)
# ~ menu.setItemImage(i, path?, True)
menu.addMenuListener(EventsMenu(self.events))
return menu
def _create_menu(self, menus):
#~ https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1awt_1_1XMenu.html
#~ nItemId specifies the ID of the menu item to be inserted.
#~ aText specifies the label of the menu item.
#~ nItemStyle 0 = Standard, CHECKABLE = 1, RADIOCHECK = 2, AUTOCHECK = 4
#~ nItemPos specifies the position where the menu item will be inserted.
self._menu = create_instance('com.sun.star.awt.MenuBar', True)
for i, m in enumerate(menus):
self._menu.insertItem(i, m['label'], m.get('style', 0), i)
cmd = m['label'].lower().replace(' ', '_')
self._menu.setCommand(i, cmd)
submenu = self._create_popupmenu(m['submenu'])
self._menu.setPopupMenu(i, submenu)
self._window.setMenuBar(self._menu)
return
def add_menu(self, menus):
self._create_menu(menus)
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(EventsKey(self))
return
@property
def name(self):
return self._title.lower().replace(' ', '_')
@property
def events(self):
return self._events
@events.setter
def events(self, value):
self._events = value
self._add_listeners()
@property
def width(self):
return self._container.Size.Width
@property
def height(self):
return self._container.Size.Height
def open(self):
self._window.setVisible(True)
return
def close(self):
self._window.setMenuBar(None)
self._window.dispose()
self._frame.close(True)
return
# ~ Python >= 3.7
# ~ def __getattr__(name):
@ -1935,7 +2408,7 @@ def active_cell():
def create_dialog(properties):
return LODialog(properties)
return LODialog(**properties)
# ~ Export ok
@ -2095,7 +2568,7 @@ def inputbox(message, default='', title=TITLE, echochar=''):
'Width': 200,
'Height': 80,
}
dlg = LODialog(args)
dlg = LODialog(**args)
dlg.events = ControllersInput(dlg)
args = {
@ -2974,7 +3447,7 @@ class SmtpServer(object):
def __enter__(self):
return self
def __exit__(self, *args):
def __exit__(self, exc_type, exc_value, traceback):
self.close()
@property
@ -3109,6 +3582,9 @@ def server_smtp_test(config):
return server.error
def create_window(kwargs):
return LOWindow(**kwargs)
class LIBOServer(object):
HOST = 'localhost'