Using getSelection() within XModifyListener not working

Java, C++, C#, Delphi, ??? - Using the UNO bridges

Using getSelection() within XModifyListener not working

Postby kwalcock » Fri Nov 20, 2015 8:29 pm

When my document is modified, I want to find out what is selected so that I can better figure out exactly what had been modified. I have a C++ program with a SAL_IMPLEMENT_MAIN_WITH_ARGS that tries to do this. It is extracted and simplified from the extension that is being built. I note the environment because I can't seem to achieve the same effect using a macro within OpenOffice.

I can call getSelection() directly from my code, but if I make a modify listener and call getSelection() after the event is broadcast, Write hangs. It never returns to my code from the listener. I think this is a bug in OpenOffice, but if anyone can refute that, I'd be glad to hear it. Here's the code:
Code: Select all   Expand viewCollapse view
/******************************************************************************
Header
******************************************************************************/
// $Header$
/******************************************************************************
Include others
******************************************************************************/
#include "sdkBeg.hpp"
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/frame/XDesktop.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/lang/EventObject.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XMultiComponentFactory.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/text/XTextDocument.hpp>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/util/XModifiable.hpp>
#include <com/sun/star/util/XModifyListener.hpp>
#include <com/sun/star/view/XSelectionSupplier.hpp>

#include <cppuhelper/bootstrap.hxx>
#include <cppuhelper/implbase1.hxx>

#include <sal/main.h> // Required for this to be a free-standing executable.
#include "sdkEnd.hpp"

#include <iostream>
/******************************************************************************
Using
******************************************************************************/
using namespace com::sun::star::beans;
using namespace com::sun::star::container;
using namespace com::sun::star::frame;
using namespace com::sun::star::lang;
using namespace com::sun::star::text;
using namespace com::sun::star::uno;
using namespace com::sun::star::util;
using namespace com::sun::star::view;
/******************************************************************************
ModifyBug
******************************************************************************/
class ModifyBug: public cppu::WeakImplHelper1<com::sun::star::util::XModifyListener> {
   protected:
      Reference<XComponent> savedXComponent; // needed for testing listener

      virtual void SAL_CALL modified(const com::sun::star::lang::EventObject& event)
            throw (com::sun::star::uno::RuntimeException);
      virtual void SAL_CALL disposing(const com::sun::star::lang::EventObject& event)
            throw (com::sun::star::uno::RuntimeException);

      Reference<XComponentContext> newXComponentContext();
      Reference<XInterface> newDesktop(Reference<XComponentContext> xComponentContext);
      Reference<XTextDocument> newXTextDocument(Reference<XInterface> desktop);

   public:
      ModifyBug() {
      }

      void run();
};

void SAL_CALL ModifyBug::disposing(const com::sun::star::lang::EventObject& event)
      throw (com::sun::star::uno::RuntimeException) {
   // TODO: remove listener
}

void getSelections(Reference<XComponent> xComponent) {
   Reference<XModel> xModel(xComponent, UNO_QUERY);
   Reference<XController> xController = xModel->getCurrentController();
   Reference<XSelectionSupplier> xSelectionSupplier(xController, UNO_QUERY);

   xSelectionSupplier->getSelection(); // Including this like makes it hang!
}

void SAL_CALL ModifyBug::modified(const com::sun::star::lang::EventObject& event)
      throw (com::sun::star::uno::RuntimeException) {
   getSelections(savedXComponent);
}

Reference<XComponentContext> ModifyBug::newXComponentContext() {
   Reference<XComponentContext> xComponentContext(cppu::bootstrap());

   return xComponentContext;
}

Reference<XInterface> ModifyBug::newDesktop(Reference<XComponentContext> xComponentContext) {
   Reference<XMultiComponentFactory> xMultiComponentFactory(xComponentContext->getServiceManager(), UNO_QUERY);
   Reference<XInterface> desktop = xMultiComponentFactory->createInstanceWithContext(
         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")), xComponentContext);

   return desktop;
}

Reference<XTextDocument> ModifyBug::newXTextDocument(Reference<XInterface> desktop) {
   Reference<XComponentLoader> xComponentLoader(desktop, UNO_QUERY);
   Reference<XComponent> document = xComponentLoader->loadComponentFromURL(
         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/swriter")),
         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, Sequence<PropertyValue>());
   Reference<XTextDocument> xTextDocument(document, UNO_QUERY);

   return xTextDocument;
}

void ModifyBug::run() {
   try {
      Reference<XComponentContext> xComponentContext = newXComponentContext();
      Reference<XInterface> desktop = newDesktop(xComponentContext);
      Reference<XDesktop> xDesktop(desktop, UNO_QUERY);

      {
         Reference<XTextDocument> xTextDocument = newXTextDocument(desktop);
         Reference<XText> xText = xTextDocument->getText();
         Reference<XComponent> xComponent(xTextDocument, UNO_QUERY);
         Reference<XModifiable> xModifiable(xComponent, UNO_QUERY);
         Reference<XModifyBroadcaster> xModifyBroadcaster(xComponent, UNO_QUERY);

         savedXComponent = xComponent;
         xModifyBroadcaster->addModifyListener(this);

         getSelections(savedXComponent); // It (getSelection) can be called directly
         getSelections(savedXComponent); // and repeatedly

         xText->setString(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("hello"))); // It can _not_ be called indirectly
         xModifiable->setModified(sal_True); // It can't be called indirectly like this, either.

         xModifyBroadcaster->removeModifyListener(this);
         savedXComponent = Reference<XComponent>();
         xTextDocument->dispose();
      }
      xDesktop->terminate();
   }
   catch (...) {
      std::cerr << "Exception..." << std::endl;
   }
}

SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
   ModifyBug modifyBug;
   
   modifyBug.run();
   return 0;
}
/*****************************************************************************/
Last edited by RoryOF on Fri Nov 20, 2015 8:55 pm, edited 1 time in total.
Reason: Added [code] tags. [RoryOF, Moderator]
Apache OpenOffice 4.0.1
Windows, Linux, MacOS
kwalcock
 
Posts: 24
Joined: Thu Oct 09, 2014 11:54 am

Return to External Programs

Who is online

Users browsing this forum: No registered users and 2 guests