Listener for a spreadsheet rename event

The Application Programming Interface and the OASIS Open Document Format

Listener for a spreadsheet rename event

Postby Ralf » Mon Oct 29, 2012 1:29 am

Hello,
is there an event listener in the UNO API which is fired when the user renames a calc spreadsheet interactively? I can't find one.

Regards
Ralf
LibreOffice 3.5 on Ubuntu 12.04
Ralf
 
Posts: 6
Joined: Mon Oct 29, 2012 1:07 am

Re: Listener for a spreadsheet rename event

Postby Charlie Young » Tue Oct 30, 2012 12:52 pm

Ralf wrote:Hello,
is there an event listener in the UNO API which is fired when the user renames a calc spreadsheet interactively? I can't find one.

Regards
Ralf


Do you mean rename the document, or rename a sheet within it?
Apache OpenOffice 4.1.1
Windows XP
User avatar
Charlie Young
Volunteer
 
Posts: 1559
Joined: Fri May 14, 2010 1:07 am

Re: Listener for a spreadsheet rename event

Postby Ralf » Tue Oct 30, 2012 5:33 pm

I ment a single sheet within the calc document.
LibreOffice 3.5 on Ubuntu 12.04
Ralf
 
Posts: 6
Joined: Mon Oct 29, 2012 1:07 am

Re: Listener for a spreadsheet rename event

Postby Charlie Young » Wed Oct 31, 2012 2:07 am

Ralf wrote:I ment a single sheet within the calc document.


I tried XPropertyChangeListener and XVetoableChangeListener, which looked promising, but I didn't have any luck there. An XModifyListener attached to the document is triggered by renaming a sheet, but by lots of other things as well, so that was a bust.

But, if undo is enabled, we can attach an XUndoManagerListener to ThisComponent.UndoManager, and then check newly added undo actions for "Rename Sheet."

Here I'm just displaying the old name and the new one. As usual, all the listener methods have to be implemented, even though I'm only using one of them for now.

Code: Select all   Expand viewCollapse view

Global oListener As Object
   
Sub SetupListener()
   Dim oDoc As Object
                     
      oDoc = ThisComponent
      oListener = createUnoListener("Undoer_", "com.sun.star.document.XUndoManagerListener")
      oDoc.UndoManager.addUndoManagerListener(oListener)
   
End Sub

Sub Undoer_undoActionAdded(oEvent)
   Dim oDoc As Object
   Dim oSheet As Object
   Dim UnDoMgr As Object
   Dim oldName As String
   Dim newName As String
   
   oDoc = ThisComponent
   oSheet = oDoc.CurrentController.ActiveSheet
   UnDoMgr = oDoc.getUndoManager()
   
   If UnDoMgr.getCurrentUndoActionTitle() = "Rename Sheet" Then
      UnDoMgr.removeUndoManagerListener(oListener)
      UnDoMgr.undo()
      oldName = oSheet.getName()
      UnDoMgr.redo()
      newName = oSheet.getName()
      MsgBox(oldName)
      MsgBox(newName)
      UnDoMgr.addUndoManagerListener(oListener)
   EndIf
   
End Sub

Sub Undoer_actionUndone(oEvent)
      
End Sub

Sub Undoer_actionRedone(oEvent)
      
End Sub

Sub Undoer_allActionsCleared(oEvent)
      
End Sub

Sub Undoer_cancelledContext(oEvent)
      
End Sub

Sub Undoer_disposing(oEvent)
      
End Sub

Sub Undoer_enteredContext(oEvent)
      
End Sub

Sub Undoer_enteredHiddenContext(oEvent)
   
End Sub

Sub Undoer_leftContext(oEvent)
   
End Sub

Sub Undoer_leftHiddenContext(oEvent)
   
End Sub

Sub Undoer_redoActionsCleared(oEvent)
   
End Sub

Sub Undoer_resetAll(oEvent)
      
End Sub

Sub ClearListener
   Dim oDoc As Object
   Dim UnDoMgr As Object
   oDoc = ThisComponent
   
   UnDoMgr = oDoc.getUndoManager()
   UnDoMgr.removeUndoManagerListener(oListener)
   
End Sub

Apache OpenOffice 4.1.1
Windows XP
User avatar
Charlie Young
Volunteer
 
Posts: 1559
Joined: Fri May 14, 2010 1:07 am

Re: Listener for a spreadsheet rename event

Postby Ralf » Wed Oct 31, 2012 3:28 pm

You remove the UndoManagerListener in Sub Undoer_undoActionAdded() just because you execute UnDoMgr.undo() to get oldName for the MsgBox. For a "normal" application, UnDoMgr.removeUndoManagerListener() would not be required.
Is that assumption correct?
LibreOffice 3.5 on Ubuntu 12.04
Ralf
 
Posts: 6
Joined: Mon Oct 29, 2012 1:07 am

Re: Listener for a spreadsheet rename event

Postby Charlie Young » Wed Oct 31, 2012 4:56 pm

Ralf wrote:You remove the UndoManagerListener in Sub Undoer_undoActionAdded() just because you execute UnDoMgr.undo() to get oldName for the MsgBox. For a "normal" application, UnDoMgr.removeUndoManagerListener() would not be required.
Is that assumption correct?


Nice catch. I put the remove then add back, in as a precaution, because I feared a race condition. I never bothered testing it without the remove/add, but now it seems it isn't required anyway. I don't think it hurts much, but if it isn't necessary, don't bother. Apparently the undo/redo doesn't add a new undoAction.
Apache OpenOffice 4.1.1
Windows XP
User avatar
Charlie Young
Volunteer
 
Posts: 1559
Joined: Fri May 14, 2010 1:07 am

Re: Listener for a spreadsheet rename event

Postby Ralf » Wed Oct 31, 2012 9:14 pm

Code: Select all   Expand viewCollapse view
If UnDoMgr.getCurrentUndoActionTitle() = "Rename Sheet" Then
  ...
EndIf

I like your proposal, Charlie!
There is still one issue left. You define the undo action title as "Rename Sheet". With my German installaton the title is defined as "Tabelle umbenennen". Is there a (UNO API internal) possibility to suppress the internationalization, and force English message strings?
LibreOffice 3.5 on Ubuntu 12.04
Ralf
 
Posts: 6
Joined: Mon Oct 29, 2012 1:07 am

Re: Listener for a spreadsheet rename event

Postby karolus » Thu Nov 01, 2012 12:16 am

Hallo Ralf

Warum änderst du nicht "Rename Sheet" zu "Tabelle umbenennen" ?
Why don't you change "_______''______" to "__________'''______" ?
Edit:Translate..
Karolus
Last edited by karolus on Mon Nov 05, 2012 11:43 pm, edited 1 time in total.
AOO4, Libreoffice 6.1 on Rasbian OS (on ARM)
User avatar
karolus
Volunteer
 
Posts: 869
Joined: Sat Jul 02, 2011 9:47 am

Re: Listener for a spreadsheet rename event

Postby Ralf » Thu Nov 01, 2012 12:50 am

Hello Karolus,

(Weil ich dieses Projekt auch Anderen zur Verfügung stellen werde. Zur Not kann ich entsprechende Derivate kompilieren, würde allerdings eine elegantere Lösung vorziehen.)

because I have planned to provide this code to others. I could compile a derivate for every language but I prefer an elegant solution.

Ralf
Last edited by Ralf on Tue Nov 06, 2012 3:40 pm, edited 1 time in total.
LibreOffice 3.5 on Ubuntu 12.04
Ralf
 
Posts: 6
Joined: Mon Oct 29, 2012 1:07 am

Re: Listener for a spreadsheet rename event

Postby Hagar Delest » Mon Nov 05, 2012 9:24 pm

Please remember that this is an English forum. Your discussion may be of interest for other users. You could at least give a translation in English.
Else, there is the German forum, you can make a thread over there and link to this one.
LibreOffice 7.0.5 on Xubuntu 21.04 and 7.0.5 portable on Windows 10
User avatar
Hagar Delest
Moderator
 
Posts: 29823
Joined: Sun Oct 07, 2007 9:07 pm
Location: France

Re: Listener for a spreadsheet rename event

Postby Ralf » Tue Nov 06, 2012 4:56 pm

Here is an other solution than using 'XUndoManagerListener' with its localised 'UndoManagerEvent.UndoActionTitle'.
This solution maintains a local variable 'Base::activeSheetName'. This variable is updated with every 'XActivationEventListener' event and it is evaluated with every 'XModifyListener' event to detect a sheet-rename. I think there is no big difference in using 'XUndoManagerListener' instead of 'XModifyListener', because they seem to fire mostly at the same occasions.

Here is an example code implementation in C++, I skipped the declaration sections.

Class Base connects to Office Calc or opens an instance of Calc, it instantiates and registers the required listeners, and provides the member functions to update local variable Base::activeSheetName:

Code: Select all   Expand viewCollapse view
Base::Base(OUString fileURL) :
    xActivationEventListener(static_cast<XActivationEventListener*>(new ActivationEventListener(this))),
    xModifyListener(static_cast<XModifyListener*>(new ModifyListener(this))),
    xUndoManagerListener(static_cast<XUndoManagerListener*>(new UndoManagerListener())),
    xComponentContext(bootstrap(), UNO_QUERY_THROW),
    xServiceManager(xComponentContext->getServiceManager(), UNO_QUERY_THROW),
    xDesktop(xServiceManager->createInstanceWithContext(OUString::createFromAscii("com.sun.star.frame.Desktop"), xComponentContext), UNO_QUERY_THROW),
    xComponentLoader(xDesktop, UNO_QUERY_THROW),
    xComponent(xComponentLoader->loadComponentFromURL(fileURL, OUString::createFromAscii("_blank"), 0, Sequence<PropertyValue>()), UNO_QUERY_THROW),
    xSpreadsheetDocument(xComponent, UNO_QUERY_THROW),
    xModel(xSpreadsheetDocument, UNO_QUERY_THROW),
    xSpreadsheetView(xModel->getCurrentController(), UNO_QUERY_THROW),
    xActivationBroadcaster(xSpreadsheetView, UNO_QUERY_THROW),
    xModifyBroadcaster(xSpreadsheetDocument, UNO_QUERY_THROW),
    xUndoManagerSupplier(xSpreadsheetDocument, UNO_QUERY_THROW)
{
    cout << "Constructor" << endl;
    xActivationBroadcaster->addActivationEventListener(xActivationEventListener);
    xModifyBroadcaster->addModifyListener(xModifyListener);
    xUndoManagerSupplier->getUndoManager()->addUndoManagerListener(xUndoManagerListener);
    activeSheet(xSpreadsheetView->getActiveSheet());
}

void Base::activeSheet(const Reference<XSpreadsheet>& sheet)
{
    xActiveSheet = sheet;
    Reference<XNamed> xNamed(sheet, UNO_QUERY_THROW);
    activeSheetName = xNamed->getName();
    cout << "Base::activeSheet: " << activeSheetName << endl;
}

void Base::renameSheet()
{
    Reference<XNamed> xNamed(xActiveSheet, UNO_QUERY_THROW);
    if (activeSheetName != xNamed->getName()) {
        cout << "Base::renameSheet: Old name: " << activeSheetName << " New name: " << xNamed->getName() << endl;
        activeSheetName = xNamed->getName();
    }
}


ActivationEventListener detects a change of the actve sheet and updates the active sheet in class Base accordingly:

Code: Select all   Expand viewCollapse view
ActivationEventListener::ActivationEventListener(Base* b)
{
    base = b;
    cout << "ActivationEventListener::ActivationEventListener: Constructor" << endl;
}

ActivationEventListener::~ActivationEventListener()
{
    cout << "ActivationEventListener::~ActivationEventListener: Destructor" << endl;
}

void SAL_CALL ActivationEventListener::activeSpreadsheetChanged(const ActivationEvent& event) throw (RuntimeException)
{
    cout << "ActivationEventListener::activeSpreadsheetChanged: " << "ActivationEvent" << endl;
    base->activeSheet(event.ActiveSheet);
}

void SAL_CALL ActivationEventListener::disposing(const EventObject& event) throw (RuntimeException)
{
    cout << "ActivationEventListener::disposing: " << "Object listened to will be disposed." << endl;
}


ModifyListener calls Base::renameSheet() with every invocation and lets class Base decide, whether this event was a sheet-rename or not:

Code: Select all   Expand viewCollapse view
ModifyListener::ModifyListener(Base* b)
{
    base = b;
    cout << "ModifyListener::ModifyListener: Constructor" << endl;
}

ModifyListener::~ModifyListener()
{
    cout << "ModifyListener::~ModifyListener: Destructor" << endl;
}

void SAL_CALL ModifyListener::modified(const EventObject& event) throw (RuntimeException)
{
    cout << "ModifyListener::modified: " << "EventObject" << endl;
    base->renameSheet();
}

void SAL_CALL ModifyListener::disposing(const EventObject& event) throw (RuntimeException)
{
    cout << "ModifyListener::disposing: " << "Object listened to will be disposed." << endl;
}
LibreOffice 3.5 on Ubuntu 12.04
Ralf
 
Posts: 6
Joined: Mon Oct 29, 2012 1:07 am


Return to UNO API and ODF

Who is online

Users browsing this forum: No registered users and 0 guests