diff options
Diffstat (limited to 'vcl/unx/kde')
-rw-r--r-- | vcl/unx/kde/FPServiceInfo.hxx | 47 | ||||
-rw-r--r-- | vcl/unx/kde/UnxCommandThread.cxx | 314 | ||||
-rw-r--r-- | vcl/unx/kde/UnxCommandThread.hxx | 135 | ||||
-rw-r--r-- | vcl/unx/kde/UnxFilePicker.cxx | 943 | ||||
-rw-r--r-- | vcl/unx/kde/UnxFilePicker.hxx | 188 | ||||
-rw-r--r-- | vcl/unx/kde/UnxNotifyThread.cxx | 115 | ||||
-rw-r--r-- | vcl/unx/kde/UnxNotifyThread.hxx | 89 | ||||
-rw-r--r-- | vcl/unx/kde/fpicker/Makefile | 35 | ||||
-rw-r--r-- | vcl/unx/kde/fpicker/kdecommandthread.cxx | 181 | ||||
-rw-r--r-- | vcl/unx/kde/fpicker/kdecommandthread.hxx | 97 | ||||
-rw-r--r-- | vcl/unx/kde/fpicker/kdefilepicker.cxx | 734 | ||||
-rw-r--r-- | vcl/unx/kde/fpicker/kdefilepicker.hxx | 127 | ||||
-rw-r--r-- | vcl/unx/kde/fpicker/kdefpmain.cxx | 94 | ||||
-rw-r--r-- | vcl/unx/kde/fpicker/kdemodalityfilter.cxx | 69 | ||||
-rw-r--r-- | vcl/unx/kde/fpicker/kdemodalityfilter.hxx | 48 | ||||
-rw-r--r-- | vcl/unx/kde/salnativewidgets-kde.cxx | 10 |
16 files changed, 3225 insertions, 1 deletions
diff --git a/vcl/unx/kde/FPServiceInfo.hxx b/vcl/unx/kde/FPServiceInfo.hxx new file mode 100644 index 000000000000..9e4cbf1ac44d --- /dev/null +++ b/vcl/unx/kde/FPServiceInfo.hxx @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _FPSERVICEINFO_HXX_ +#define _FPSERVICEINFO_HXX_ + +// the service names +#define FILE_PICKER_SERVICE_NAME "com.sun.star.ui.dialogs.KDEFilePicker" + +// the implementation names +#define FILE_PICKER_IMPL_NAME "com.sun.star.ui.dialogs.UnxFilePicker" + +// the registry key names +// a key under which this service will be registered, +// Format: -> "/ImplName/UNO/SERVICES/ServiceName" +// <Implementation-Name></UNO/SERVICES/><Service-Name> +#define FILE_PICKER_REGKEY_NAME "/com.sun.star.ui.dialogs.UnxFilePicker/UNO/SERVICES/com.sun.star.ui.dialogs.KDEFilePicker" + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/UnxCommandThread.cxx b/vcl/unx/kde/UnxCommandThread.cxx new file mode 100644 index 000000000000..8f7ee3d0c21c --- /dev/null +++ b/vcl/unx/kde/UnxCommandThread.cxx @@ -0,0 +1,314 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <UnxCommandThread.hxx> +#include <UnxNotifyThread.hxx> + +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> + +#include <unistd.h> +#include <string.h> +#include <iostream> + +using namespace ::com::sun::star; + +////////////////////////////////////////////////////////////////////////// +// UnxFilePickerCommandThread +////////////////////////////////////////////////////////////////////////// + +UnxFilePickerCommandThread::UnxFilePickerCommandThread( UnxFilePickerNotifyThread *pNotifyThread, int nReadFD ) + : m_pNotifyThread( pNotifyThread ), + m_nReadFD( nReadFD ) +{ +} + +UnxFilePickerCommandThread::~UnxFilePickerCommandThread() +{ +} + +sal_Bool SAL_CALL UnxFilePickerCommandThread::result() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_aResult; +} + +::rtl::OUString SAL_CALL UnxFilePickerCommandThread::getCurrentFilter() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_aGetCurrentFilter; +} + +::rtl::OUString SAL_CALL UnxFilePickerCommandThread::getDirectory() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_aGetDirectory; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL UnxFilePickerCommandThread::getFiles() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + sal_Int32 nSize = m_aGetFiles.size(); + uno::Sequence< ::rtl::OUString > aFiles( ( nSize > 1 )? nSize + 1: nSize ); + + if ( nSize == 1 ) + aFiles[0] = m_aGetFiles.front(); + else if ( nSize > 1 ) + { + // First entry in the sequence must be the dirname, the others are the + // filenames, so we have to rearrange the list... + + ::rtl::OUString aFront = m_aGetFiles.front(); + sal_Int32 nLastSlash = aFront.lastIndexOf( '/' ); + + aFiles[0] = ( nLastSlash >= 0 )? aFront.copy( 0, nLastSlash ): ::rtl::OUString(); + ++nLastSlash; + + sal_Int32 nIdx = 1; + for ( ::std::list< ::rtl::OUString >::const_iterator it = m_aGetFiles.begin(); + it != m_aGetFiles.end(); ++it, ++nIdx ) + { + sal_Int32 nLength = (*it).getLength() - nLastSlash; + aFiles[nIdx] = ( nLength >= 0 )? (*it).copy( nLastSlash, nLength ): ::rtl::OUString(); + } + } + + return aFiles; +} + +uno::Any SAL_CALL UnxFilePickerCommandThread::getValue() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_aGetValue; +} + +void SAL_CALL UnxFilePickerCommandThread::run() +{ + if ( m_nReadFD < 0 ) + return; + + sal_Int32 nBufferSize = 1024; // 1 is for testing, 1024 for real use + sal_Char *pBuffer = new sal_Char[nBufferSize]; + sal_Char *pBufferEnd = pBuffer + nBufferSize; + + sal_Char *pWhereToRead = pBuffer; + sal_Char *pEntryBegin = pBuffer; + sal_Int32 nBytesRead = 0; + sal_Bool bShouldExit = sal_False; + while ( !bShouldExit && ( nBytesRead = read( m_nReadFD, pWhereToRead, pBufferEnd - pWhereToRead ) ) > 0 ) + { + sal_Bool bFoundNL = sal_False; + sal_Char *pWhereToReadEnd = pWhereToRead + nBytesRead; + sal_Char *pEntryEnd = pWhereToRead; + do { + for ( ; pEntryEnd < pWhereToReadEnd && *pEntryEnd != '\n'; ++pEntryEnd ) + ; + + if ( pEntryEnd < pWhereToReadEnd ) + { + bFoundNL = sal_True; + *pEntryEnd = 0; + + if ( strcmp( pEntryBegin, "exited" ) == 0 ) + bShouldExit = sal_True; + else + handleCommand( ::rtl::OUString( pEntryBegin, pEntryEnd - pEntryBegin, RTL_TEXTENCODING_UTF8 )/*, bQuit*/ ); + + pEntryBegin = pEntryEnd + 1; + } + } while ( pEntryEnd < pWhereToReadEnd ); + + if ( bFoundNL ) + { + if ( pEntryBegin < pBufferEnd ) + memmove( pBuffer, pEntryBegin, pWhereToReadEnd - pEntryBegin ); + } + else + { + // enlarge the buffer size + nBufferSize *= 2; + sal_Char *pNewBuffer = new sal_Char[nBufferSize]; + if ( pEntryBegin < pBufferEnd ) + memmove( pNewBuffer, pEntryBegin, pWhereToReadEnd - pEntryBegin ); + + delete[] pBuffer; + pBuffer = pNewBuffer; + pBufferEnd = pBuffer + nBufferSize; + } + + pWhereToRead = pBuffer + ( pWhereToReadEnd - pEntryBegin ); + pEntryBegin = pBuffer; + } +} + +void SAL_CALL UnxFilePickerCommandThread::handleCommand( const ::rtl::OUString &rCommand ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + +#if OSL_DEBUG_LEVEL > 0 + ::std::cerr << "UnxFilePicker received: \"" << + OUStringToOString( rCommand, RTL_TEXTENCODING_ASCII_US ).getStr() << "\"" << ::std::endl; +#endif + + ::std::list< ::rtl::OUString > aList = tokenize( rCommand ); + + if ( aList.empty() ) + return; + + ::rtl::OUString aCommandName = aList.front(); + aList.pop_front(); + + if ( aCommandName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "accept" ) ) ) + { + m_aResult = sal_True; + m_aExecCondition.set(); + } + else if ( aCommandName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "reject" ) ) ) + { + m_aResult = sal_False; + m_aExecCondition.set(); + } + else if ( aCommandName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "fileSelectionChanged" ) ) ) + { + if ( m_pNotifyThread ) + m_pNotifyThread->fileSelectionChanged(); + } + else if ( aCommandName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "files" ) ) ) + { + m_aGetFiles = aList; + m_aGetFilesCondition.set(); + } + else if ( aCommandName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "value" ) ) ) + { + ::rtl::OUString aType; + if ( !aList.empty() ) + { + aType = aList.front(); + aList.pop_front(); + } + + if ( aType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "bool" ) ) ) + { + sal_Bool bValue = !aList.empty() && aList.front().equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("true")); + + m_aGetValue <<= bValue; + m_aGetValueCondition.set(); + } + else if ( aType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "int" ) ) ) + { + sal_Int32 nValue = 0; + if ( !aList.empty() ) + nValue = aList.front().toInt32(); + + m_aGetValue <<= nValue; + m_aGetValueCondition.set(); + } + else if ( aType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "string" ) ) ) + { + ::rtl::OUString aValue; + if ( !aList.empty() ) + aValue = aList.front(); + + m_aGetValue <<= aValue; + m_aGetValueCondition.set(); + } + else if ( aType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "stringList" ) ) ) + { + uno::Sequence< ::rtl::OUString > aSequence( aList.size() ); + sal_Int32 nIdx = 0; + for ( ::std::list< ::rtl::OUString >::const_iterator it = aList.begin(); it != aList.end(); ++it, ++nIdx ) + aSequence[nIdx] = (*it); + + m_aGetValue <<= aSequence; + m_aGetValueCondition.set(); + } + else + { + m_aGetValue = uno::Any(); + m_aGetValueCondition.set(); + } + } + else if ( aCommandName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "currentFilter" ) ) ) + { + m_aGetCurrentFilter = aList.empty()? ::rtl::OUString(): aList.front(); + m_aGetCurrentFilterCondition.set(); + } + else if ( aCommandName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "currentDirectory" ) ) ) + { + m_aGetDirectory = aList.empty()? ::rtl::OUString(): aList.front(); + m_aGetDirectoryCondition.set(); + } + else + { +#if OSL_DEBUG_LEVEL > 0 + ::std::cerr << "Unrecognized command: " + << OUStringToOString( aCommandName, RTL_TEXTENCODING_ASCII_US ).getStr() << "\"" << ::std::endl; +#endif + } +} + +::std::list< ::rtl::OUString > SAL_CALL UnxFilePickerCommandThread::tokenize( const ::rtl::OUString &rCommand ) +{ + ::std::list< ::rtl::OUString > aList; + ::rtl::OUStringBuffer aBuffer( 1024 ); + + const sal_Unicode *pUnicode = rCommand.getStr(); + const sal_Unicode *pEnd = pUnicode + rCommand.getLength(); + sal_Bool bQuoted = sal_False; + + for ( ; pUnicode != pEnd; ++pUnicode ) + { + if ( *pUnicode == '\\' ) + { + ++pUnicode; + if ( pUnicode != pEnd ) + { + if ( *pUnicode == 'n' ) + aBuffer.appendAscii( "\n", 1 ); + else + aBuffer.append( *pUnicode ); + } + } + else if ( *pUnicode == '"' ) + bQuoted = !bQuoted; + else if ( *pUnicode == ' ' && !bQuoted ) + aList.push_back( aBuffer.makeStringAndClear() ); + else + aBuffer.append( *pUnicode ); + } + aList.push_back( aBuffer.makeStringAndClear() ); + + return aList; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/UnxCommandThread.hxx b/vcl/unx/kde/UnxCommandThread.hxx new file mode 100644 index 000000000000..b8c6aaaaf97c --- /dev/null +++ b/vcl/unx/kde/UnxCommandThread.hxx @@ -0,0 +1,135 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _UNXCOMMANDTHREAD_HXX_ +#define _UNXCOMMANDTHREAD_HXX_ + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> + +#include <osl/conditn.hxx> +#include <osl/mutex.hxx> +#include <osl/thread.hxx> +#include <rtl/ustring.hxx> + +#include <vcl/svapp.hxx> + +#include <list> + +class UnxFilePickerNotifyThread; + +/** Synchronization for the 'thread-less' version of the fpicker. + + Something like osl::Condition, but calls Application::Yield() while in + wait(). +*/ +class YieldingCondition +{ + ::osl::Mutex m_aMutex; + bool m_bValue; + + bool get() + { + ::osl::MutexGuard aGuard( m_aMutex ); + return m_bValue; + } + +public: + YieldingCondition() { reset(); } + + void reset() + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_bValue = false; + } + + void set() + { + ::osl::MutexGuard aGuard( m_aMutex ); + m_bValue = true; + } + + void wait() + { + while ( !get() ) + Application::Yield(); + } +}; + +class UnxFilePickerCommandThread : public ::osl::Thread +{ +protected: + UnxFilePickerNotifyThread *m_pNotifyThread; + int m_nReadFD; + + ::osl::Mutex m_aMutex; + + YieldingCondition m_aExecCondition; + sal_Bool m_aResult; + + ::osl::Condition m_aGetCurrentFilterCondition; + ::rtl::OUString m_aGetCurrentFilter; + + ::osl::Condition m_aGetDirectoryCondition; + ::rtl::OUString m_aGetDirectory; + + ::osl::Condition m_aGetFilesCondition; + ::std::list< ::rtl::OUString > m_aGetFiles; + + ::osl::Condition m_aGetValueCondition; + ::com::sun::star::uno::Any m_aGetValue; + +public: + UnxFilePickerCommandThread( UnxFilePickerNotifyThread *pNotifyThread, int nReadFD ); + ~UnxFilePickerCommandThread(); + + YieldingCondition& SAL_CALL execCondition() { return m_aExecCondition; } + sal_Bool SAL_CALL result(); + + ::osl::Condition& SAL_CALL getCurrentFilterCondition() { return m_aGetCurrentFilterCondition; } + ::rtl::OUString SAL_CALL getCurrentFilter(); + + ::osl::Condition& SAL_CALL getDirectoryCondition() { return m_aGetDirectoryCondition; } + ::rtl::OUString SAL_CALL getDirectory(); + + ::osl::Condition& SAL_CALL getFilesCondition() { return m_aGetFilesCondition; } + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles(); + + ::osl::Condition& SAL_CALL getValueCondition() { return m_aGetValueCondition; } + ::com::sun::star::uno::Any SAL_CALL getValue(); + +protected: + virtual void SAL_CALL run(); + + virtual void SAL_CALL handleCommand( const ::rtl::OUString &rCommand/*, sal_Bool &rQuit*/ ); + ::std::list< ::rtl::OUString > SAL_CALL tokenize( const ::rtl::OUString &rCommand ); +}; + +#endif // _UNXCOMMANDTHREAD_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/UnxFilePicker.cxx b/vcl/unx/kde/UnxFilePicker.cxx new file mode 100644 index 000000000000..1a30913d1797 --- /dev/null +++ b/vcl/unx/kde/UnxFilePicker.cxx @@ -0,0 +1,943 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ControlActions.hpp> + +#include <FPServiceInfo.hxx> + +#include <cppuhelper/interfacecontainer.h> +#include <osl/diagnose.h> +#include <osl/file.hxx> +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/bootstrap.hxx> +#include <tools/resmgr.hxx> + +#include <svtools/svtools.hrc> +#include <UnxFilePicker.hxx> +#include <UnxCommandThread.hxx> +#include <UnxNotifyThread.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/sysdata.hxx> +#include <vcl/syswin.hxx> +#include <vcl/window.hxx> + +#include <sys/wait.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> + +#include <iostream> + +using namespace ::com::sun::star; + +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::ui::dialogs::TemplateDescription; + +////////////////////////////////////////////////////////////////////////// +// helper functions +////////////////////////////////////////////////////////////////////////// + +namespace +{ + // controling event notifications + const bool STARTUP_SUSPENDED = true; + const bool STARTUP_ALIVE = false; + + uno::Sequence<rtl::OUString> SAL_CALL FilePicker_getSupportedServiceNames() + { + uno::Sequence<rtl::OUString> aRet(3); + aRet[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.FilePicker")); + aRet[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.SystemFilePicker")); + aRet[2] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ui.dialogs.KDEFilePicker")); + return aRet; + } +} + +////////////////////////////////////////////////////////////////////////// +// UnxFilePicker +////////////////////////////////////////////////////////////////////////// + +UnxFilePicker::UnxFilePicker( const uno::Reference<uno::XComponentContext>& ) + : cppu::WeakComponentImplHelper9< + XFilterManager, + XFilterGroupManager, + XFilePickerControlAccess, + XFilePickerNotifier, +// TODO XFilePreview, + XFilePicker2, + lang::XInitialization, + util::XCancellable, + lang::XEventListener, + lang::XServiceInfo>( m_rbHelperMtx ), + m_nFilePickerPid( -1 ), + m_nFilePickerWrite( -1 ), + m_nFilePickerRead( -1 ), + m_pNotifyThread( NULL ), + m_pCommandThread( NULL ), + m_pResMgr( ResMgr::CreateResMgr("fps_office") ) +{ +} + +UnxFilePicker::~UnxFilePicker() +{ + if ( m_nFilePickerPid > 0 ) + { + sendCommand( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "exit" )) ); + waitpid( m_nFilePickerPid, NULL, 0 ); + } + + if ( m_pCommandThread ) + { + m_pCommandThread->join(); + + delete m_pCommandThread, m_pCommandThread = NULL; + } + + if ( m_pNotifyThread ) + { + m_pNotifyThread->exit(); + + m_pNotifyThread->join(); + + delete m_pNotifyThread, m_pNotifyThread = NULL; + } + + if ( m_nFilePickerWrite >= 0 ) + close( m_nFilePickerWrite ); + + if ( m_nFilePickerRead >= 0 ) + close( m_nFilePickerRead ); + + delete m_pResMgr, m_pResMgr = NULL; +} + +void SAL_CALL UnxFilePicker::addFilePickerListener( const uno::Reference<XFilePickerListener>& xListener ) + throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pNotifyThread ); + osl::MutexGuard aGuard( m_aMutex ); + + m_pNotifyThread->addFilePickerListener( xListener ); +} + +void SAL_CALL UnxFilePicker::removeFilePickerListener( const uno::Reference<XFilePickerListener>& xListener ) + throw( uno::RuntimeException ) +{ + OSL_ASSERT( m_pNotifyThread ); + osl::MutexGuard aGuard( m_aMutex ); + + m_pNotifyThread->removeFilePickerListener( xListener ); +} + +void SAL_CALL UnxFilePicker::setTitle( const rtl::OUString &rTitle ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setTitle " ); + appendEscaped( aBuffer, rTitle ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +sal_Int16 SAL_CALL UnxFilePicker::execute() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + + // this is _not_ an osl::Condition, see i#93366 + m_pCommandThread->execCondition().reset(); + + sendCommand( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "exec" ) )); + + m_pCommandThread->execCondition().wait(); + + return m_pCommandThread->result(); +} + +void SAL_CALL UnxFilePicker::setMultiSelectionMode( sal_Bool bMode ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString aString = bMode? + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "setMultiSelection true" )): + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "setMultiSelection false" )); + + sendCommand( aString ); +} + +void SAL_CALL UnxFilePicker::setDefaultName( const ::rtl::OUString &rName ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setDefaultName " ); + appendEscaped( aBuffer, rName ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +void SAL_CALL UnxFilePicker::setDisplayDirectory( const rtl::OUString &rDirectory ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setDirectory " ); + appendEscaped( aBuffer, rDirectory ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +rtl::OUString SAL_CALL UnxFilePicker::getDisplayDirectory() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + sendCommand( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "getDirectory" )), + m_pCommandThread->getDirectoryCondition() ); + + return m_pCommandThread->getDirectory(); +} + +uno::Sequence< ::rtl::OUString > SAL_CALL UnxFilePicker::getFiles() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + sendCommand( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "getFiles" )), + m_pCommandThread->getFilesCondition() ); + + return m_pCommandThread->getFiles(); +} + +void SAL_CALL UnxFilePicker::appendFilter( const ::rtl::OUString &rTitle, const ::rtl::OUString &rFilter ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "appendFilter " ); + appendEscaped( aBuffer, rTitle ); + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, rFilter ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +void SAL_CALL UnxFilePicker::setCurrentFilter( const rtl::OUString &rTitle ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setCurrentFilter " ); + appendEscaped( aBuffer, rTitle ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +rtl::OUString SAL_CALL UnxFilePicker::getCurrentFilter() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + sendCommand( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "getCurrentFilter" )), + m_pCommandThread->getCurrentFilterCondition() ); + + return m_pCommandThread->getCurrentFilter(); +} + +void SAL_CALL UnxFilePicker::appendFilterGroup( const rtl::OUString &rGroupTitle, const uno::Sequence<beans::StringPair> &rFilters ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "appendFilterGroup " ); + appendEscaped( aBuffer, rGroupTitle ); + + for ( sal_Int32 i = 0; i < rFilters.getLength(); ++i ) + { + beans::StringPair aPair = rFilters[i]; + + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, aPair.First ); + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, aPair.Second ); + } + + sendCommand( aBuffer.makeStringAndClear() ); +} + +void SAL_CALL UnxFilePicker::setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const uno::Any &rValue ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString aType; + ::rtl::OUString aAction; + sal_Int32 nTitleId; + + if ( controlIdInfo( nControlId, aType, nTitleId ) && controlActionInfo( nControlAction, aAction ) ) + { + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setValue " ); + aBuffer.append( static_cast< sal_Int32 >( nControlId ) ); + aBuffer.appendAscii( " ", 1 ); + aBuffer.append( aAction ); + + if ( aType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "checkbox" ) ) ) + { + sal_Bool bControlValue; + if ( ( rValue >>= bControlValue ) && bControlValue ) + aBuffer.appendAscii( " true" ); + else + aBuffer.appendAscii( " false" ); + } + else if ( aType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "listbox" ) ) ) + { + switch ( nControlAction ) + { + case ControlActions::ADD_ITEM: + case ControlActions::SET_HELP_URL: + { + ::rtl::OUString aString; + if ( rValue >>= aString ) + { + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, aString ); + } + } + break; + + case ControlActions::ADD_ITEMS: + { + uno::Sequence< ::rtl::OUString > aSequence; + if ( rValue >>= aSequence ) + { + for ( sal_Int32 nIdx = 0; nIdx < aSequence.getLength(); ++nIdx ) + { + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, aSequence[nIdx] ); + } + + } + } + break; + + case ControlActions::DELETE_ITEM: + case ControlActions::SET_SELECT_ITEM: + { + sal_Int32 nInt; + if ( rValue >>= nInt ) + { + aBuffer.appendAscii( " ", 1 ); + aBuffer.append( nInt ); + } + } + break; + + default: + // nothing + break; + } + } + // TODO else if push button... + + sendCommand( aBuffer.makeStringAndClear() ); + } +} + +uno::Any SAL_CALL UnxFilePicker::getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUString aAction; + + if ( controlActionInfo( nControlAction, aAction ) ) + { + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "getValue " ); + aBuffer.append( static_cast< sal_Int32 >( nControlId ) ); + aBuffer.appendAscii( " ", 1 ); + aBuffer.append( aAction ); + + sendCommand( aBuffer.makeStringAndClear(), + m_pCommandThread->getValueCondition() ); + + return m_pCommandThread->getValue(); + } + + return uno::Any(); +} + +void SAL_CALL UnxFilePicker::enableControl( sal_Int16 nControlId, sal_Bool bEnable ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "enableControl " ); + aBuffer.append( static_cast< sal_Int32 >( nControlId ) ); + aBuffer.appendAscii( bEnable? " true": " false" ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +void SAL_CALL UnxFilePicker::setLabel( sal_Int16 nControlId, const ::rtl::OUString &rLabel ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "setLabel " ); + aBuffer.append( static_cast< sal_Int32 >( nControlId ) ); + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, rLabel ); + + sendCommand( aBuffer.makeStringAndClear() ); +} + +rtl::OUString SAL_CALL UnxFilePicker::getLabel(sal_Int16 /*nControlId*/) + throw ( uno::RuntimeException ) +{ + // FIXME getLabel() is not yet implemented + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + // TODO return m_pImpl->getLabel(nControlId); + return ::rtl::OUString(); +} + +/* TODO +uno::Sequence<sal_Int16> SAL_CALL UnxFilePicker::getSupportedImageFormats() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->getSupportedImageFormats(); +} + +sal_Int32 SAL_CALL UnxFilePicker::getTargetColorDepth() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->getTargetColorDepth(); +} + +sal_Int32 SAL_CALL UnxFilePicker::getAvailableWidth() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->getAvailableWidth(); +} + +sal_Int32 SAL_CALL UnxFilePicker::getAvailableHeight() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->getAvailableHeight(); +} + +void SAL_CALL UnxFilePicker::setImage( sal_Int16 aImageFormat, const uno::Any &rImage ) + throw( lang::IllegalArgumentException, uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + m_pImpl->setImage( aImageFormat, aImage ); +} + +sal_Bool SAL_CALL UnxFilePicker::setShowState( sal_Bool bShowState ) + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->setShowState( bShowState ); +} + +sal_Bool SAL_CALL UnxFilePicker::getShowState() + throw( uno::RuntimeException ) +{ + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + return m_pImpl->getShowState(); +} +*/ + +void SAL_CALL UnxFilePicker::initialize( const uno::Sequence<uno::Any> &rArguments ) + throw( uno::Exception, uno::RuntimeException ) +{ + initFilePicker(); + + // parameter checking + uno::Any aAny; + if ( 0 == rArguments.getLength( ) ) + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "no arguments" )), + static_cast< XFilePicker2* >( this ), 1 ); + + aAny = rArguments[0]; + + if ( ( aAny.getValueType() != ::getCppuType( (sal_Int16*)0 ) ) && ( aAny.getValueType() != ::getCppuType( (sal_Int8*)0 ) ) ) + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "invalid argument type" )), + static_cast< XFilePicker2* >( this ), 1 ); + + sal_Int16 templateId = -1; + aAny >>= templateId; + + ::rtl::OUString aTypeOpen(RTL_CONSTASCII_USTRINGPARAM( "setType \"open\"" )); + ::rtl::OUString aTypeSaveAs(RTL_CONSTASCII_USTRINGPARAM( "setType \"save\"" )); + + switch ( templateId ) + { + case FILEOPEN_SIMPLE: + sendCommand( aTypeOpen ); + break; + + case FILESAVE_SIMPLE: + sendCommand( aTypeSaveAs ); + break; + + case FILESAVE_AUTOEXTENSION_PASSWORD: + sendCommand( aTypeSaveAs ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD ); + break; + + case FILESAVE_AUTOEXTENSION_PASSWORD_FILTEROPTIONS: + sendCommand( aTypeSaveAs ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_PASSWORD ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS ); + break; + + case FILESAVE_AUTOEXTENSION_SELECTION: + sendCommand( aTypeSaveAs ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_SELECTION ); + break; + + case FILESAVE_AUTOEXTENSION_TEMPLATE: + sendCommand( aTypeSaveAs ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + sendAppendControlCommand( ExtendedFilePickerElementIds::LISTBOX_TEMPLATE ); + break; + + case FILEOPEN_LINK_PREVIEW_IMAGE_TEMPLATE: + sendCommand( aTypeOpen ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_LINK ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW ); + sendAppendControlCommand( ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE ); + break; + + case FILEOPEN_PLAY: + sendCommand( aTypeOpen ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::PUSHBUTTON_PLAY ); + break; + + case FILEOPEN_READONLY_VERSION: + sendCommand( aTypeOpen ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_READONLY ); + sendAppendControlCommand( ExtendedFilePickerElementIds::LISTBOX_VERSION ); + break; + + case FILEOPEN_LINK_PREVIEW: + sendCommand( aTypeOpen ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_LINK ); + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_PREVIEW ); + break; + + case FILESAVE_AUTOEXTENSION: + sendCommand( aTypeSaveAs ); + + sendAppendControlCommand( ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION ); + break; + + default: + throw lang::IllegalArgumentException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "Unknown template" )), + static_cast< XFilePicker2* >( this ), + 1 ); + } +} + +void SAL_CALL UnxFilePicker::cancel() + throw ( uno::RuntimeException ) +{ + // FIXME cancel() is not implemented + checkFilePicker(); + ::osl::MutexGuard aGuard( m_aMutex ); + + // TODO m_pImpl->cancel(); +} + +void SAL_CALL UnxFilePicker::disposing( const lang::EventObject &rEvent ) + throw( uno::RuntimeException ) +{ + uno::Reference<XFilePickerListener> xFilePickerListener( rEvent.Source, uno::UNO_QUERY ); + + if ( xFilePickerListener.is() ) + removeFilePickerListener( xFilePickerListener ); +} + +rtl::OUString SAL_CALL UnxFilePicker::getImplementationName() + throw( uno::RuntimeException ) +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( FILE_PICKER_IMPL_NAME )); +} + +sal_Bool SAL_CALL UnxFilePicker::supportsService( const rtl::OUString& ServiceName ) + throw( uno::RuntimeException ) +{ + uno::Sequence< ::rtl::OUString > SupportedServicesNames = FilePicker_getSupportedServiceNames(); + + for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; ) + { + if ( SupportedServicesNames[n].compareTo( ServiceName ) == 0 ) + return sal_True; + } + + return sal_False; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL UnxFilePicker::getSupportedServiceNames() + throw( uno::RuntimeException ) +{ + return FilePicker_getSupportedServiceNames(); +} + +void UnxFilePicker::initFilePicker() +{ + int aFiledesStdin[2], aFiledesStdout[2]; + if ( pipe( aFiledesStdin ) < 0 || pipe( aFiledesStdout ) < 0 ) + return; + + m_nFilePickerPid = fork(); + if ( m_nFilePickerPid < 0 ) + return; + + if ( m_nFilePickerPid == 0 ) + { + // Child... + close( aFiledesStdin[1] ); // write end of the pipe + dup2( aFiledesStdin[0], 0 ); + close( aFiledesStdin[0] ); + + close( aFiledesStdout[0] ); // read end of the pipe + dup2( aFiledesStdout[1], 1 ); + close( aFiledesStdout[1] ); + +#if OSL_DEBUG_LEVEL == 0 + int nRedirect = open( "/dev/null", O_WRONLY ); + if( nRedirect != -1 ) + { + dup2( nRedirect, 2 ); + } +#endif + + // The executable name + rtl::OUString helperurl( RTL_CONSTASCII_USTRINGPARAM("${ORIGIN}/kdefilepicker")); + rtl::Bootstrap::expandMacros( helperurl ); + rtl::OUString helperpath; + osl::FileBase::getSystemPathFromFileURL( helperurl, helperpath ); + rtl::OString helper( rtl::OUStringToOString( helperpath, osl_getThreadTextEncoding())); + + // ID of the main window + const int nIdLen = 20; + char pWinId[nIdLen] = "0"; + + // TODO pass here the real parent (not possible for system dialogs + // yet), and default to GetDefDialogParent() only when the real parent + // is NULL + Window *pParentWin = Application::GetDefDialogParent(); + if ( pParentWin ) + { + const SystemEnvData* pSysData = ((SystemWindow *)pParentWin)->GetSystemData(); + if ( pSysData ) + { + snprintf( pWinId, nIdLen, "%ld", pSysData->aWindow ); // unx only + pWinId[nIdLen-1] = 0; + } + } + + // Execute the fpicker implementation + execlp( helper.getStr(), helper.getStr(), "--winid", pWinId, NULL ); + + // Error, finish the child + exit( -1 ); + } + + // Parent continues + close( aFiledesStdin[0] ); + m_nFilePickerWrite = aFiledesStdin[1]; + + close( aFiledesStdout[1] ); + m_nFilePickerRead = aFiledesStdout[0]; + + // Create the notify thread + if ( !m_pNotifyThread ) + m_pNotifyThread = new UnxFilePickerNotifyThread( this ); + + // Create the command thread + if ( !m_pCommandThread ) + m_pCommandThread = new UnxFilePickerCommandThread( m_pNotifyThread, m_nFilePickerRead ); + + // Start the threads + m_pNotifyThread->create(); + m_pCommandThread->create(); + + return; +} + +void UnxFilePicker::checkFilePicker() throw( ::com::sun::star::uno::RuntimeException ) +{ + if ( m_nFilePickerPid > 0 ) + { + // TODO check if external file picker is runnning + } + else + { + throw uno::RuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "the external file picker does not run" )), + *this ); + } +} + +void UnxFilePicker::sendCommand( const ::rtl::OUString &rCommand ) +{ + if ( m_nFilePickerWrite < 0 ) + return; + + ::rtl::OString aUtfString = OUStringToOString( rCommand + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "\n" )), RTL_TEXTENCODING_UTF8 ); + +#if OSL_DEBUG_LEVEL > 0 + ::std::cerr << "UnxFilePicker sent: \"" << aUtfString.getStr() << "\"" << ::std::endl; +#endif + + write( m_nFilePickerWrite, aUtfString.getStr(), aUtfString.getLength() ); +} + +void UnxFilePicker::sendCommand( const ::rtl::OUString &rCommand, ::osl::Condition &rCondition ) +{ + rCondition.reset(); + + sendCommand( rCommand ); + + rCondition.wait(); +} + +void UnxFilePicker::appendEscaped( ::rtl::OUStringBuffer &rBuffer, const ::rtl::OUString &rString ) +{ + const sal_Unicode *pUnicode = rString.getStr(); + const sal_Unicode *pEnd = pUnicode + rString.getLength(); + + rBuffer.appendAscii( "\"" , 1 ); + + for ( ; pUnicode != pEnd; ++pUnicode ) + { + if ( *pUnicode == '\\' ) + rBuffer.appendAscii( "\\\\", 2 ); + else if ( *pUnicode == '"' ) + rBuffer.appendAscii( "\\\"", 2 ); + else if ( *pUnicode == '\n' ) + rBuffer.appendAscii( "\\n", 2 ); + else + rBuffer.append( *pUnicode ); + } + + rBuffer.appendAscii( "\"", 1 ); +} + +sal_Bool UnxFilePicker::controlIdInfo( sal_Int16 nControlId, ::rtl::OUString &rType, sal_Int32 &rTitleId ) +{ + typedef struct { + sal_Int16 nId; + const ::rtl::OUString *pType; + sal_Int32 nTitle; + } ElementToName; + + const ::rtl::OUString aCheckBox( RTL_CONSTASCII_USTRINGPARAM( "checkbox" ) ); + const ::rtl::OUString aControl( RTL_CONSTASCII_USTRINGPARAM( "control" ) ); + const ::rtl::OUString aEdit( RTL_CONSTASCII_USTRINGPARAM( "edit" ) ); + const ::rtl::OUString aLabel( RTL_CONSTASCII_USTRINGPARAM( "label" ) ); + const ::rtl::OUString aListBox( RTL_CONSTASCII_USTRINGPARAM( "listbox" ) ); + const ::rtl::OUString aPushButton( RTL_CONSTASCII_USTRINGPARAM( "pushbutton" ) ); + + const ElementToName *pPtr; + const ElementToName pArray[] = + { + { CommonFilePickerElementIds::PUSHBUTTON_OK, &aPushButton, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::PUSHBUTTON_CANCEL, &aPushButton, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::LISTBOX_FILTER, &aListBox, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::CONTROL_FILEVIEW, &aControl, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::EDIT_FILEURL, &aEdit, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::LISTBOX_FILTER_LABEL, &aLabel, 0/*FIXME?*/ }, + { CommonFilePickerElementIds::EDIT_FILEURL_LABEL, &aLabel, 0/*FIXME?*/ }, + + { ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, &aCheckBox, STR_SVT_FILEPICKER_AUTO_EXTENSION }, + { ExtendedFilePickerElementIds::CHECKBOX_PASSWORD, &aCheckBox, STR_SVT_FILEPICKER_PASSWORD }, + { ExtendedFilePickerElementIds::CHECKBOX_FILTEROPTIONS, &aCheckBox, STR_SVT_FILEPICKER_FILTER_OPTIONS }, + { ExtendedFilePickerElementIds::CHECKBOX_READONLY, &aCheckBox, STR_SVT_FILEPICKER_READONLY }, + { ExtendedFilePickerElementIds::CHECKBOX_LINK, &aCheckBox, STR_SVT_FILEPICKER_INSERT_AS_LINK }, + { ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, &aCheckBox, STR_SVT_FILEPICKER_SHOW_PREVIEW }, + { ExtendedFilePickerElementIds::PUSHBUTTON_PLAY, &aPushButton, STR_SVT_FILEPICKER_PLAY }, + { ExtendedFilePickerElementIds::LISTBOX_VERSION, &aListBox, STR_SVT_FILEPICKER_VERSION }, + { ExtendedFilePickerElementIds::LISTBOX_TEMPLATE, &aListBox, STR_SVT_FILEPICKER_TEMPLATES }, + { ExtendedFilePickerElementIds::LISTBOX_IMAGE_TEMPLATE, &aListBox, STR_SVT_FILEPICKER_IMAGE_TEMPLATE }, + { ExtendedFilePickerElementIds::CHECKBOX_SELECTION, &aCheckBox, STR_SVT_FILEPICKER_SELECTION }, + { 0, 0, 0 } + }; + + for ( pPtr = pArray; pPtr->nId && ( pPtr->nId != nControlId ); ++pPtr ) + ; + + if ( pPtr->nId == nControlId ) + { + rType = *(pPtr->pType); + rTitleId = pPtr->nTitle; + + return sal_True; + } + + return sal_False; +} + +sal_Bool UnxFilePicker::controlActionInfo( sal_Int16 nControlAction, ::rtl::OUString &rType ) +{ + typedef struct { + sal_Int16 nId; + const ::rtl::OUString pType; + } ElementToName; + + const ElementToName *pPtr; + const ElementToName pArray[] = + { + { ControlActions::ADD_ITEM, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "addItem" ) ) }, + { ControlActions::ADD_ITEMS, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "addItems" ) ) }, + { ControlActions::DELETE_ITEM, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "deleteItem" ) ) }, + { ControlActions::DELETE_ITEMS, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "deleteItems" ) ) }, + { ControlActions::SET_SELECT_ITEM, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setSelectedItem" ) ) }, + { ControlActions::GET_ITEMS, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getItems" ) ) }, + { ControlActions::GET_SELECTED_ITEM, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getSelectedItem" ) ) }, + { ControlActions::GET_SELECTED_ITEM_INDEX, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getSelectedItemIndex" ) ) }, + { ControlActions::SET_HELP_URL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setHelpURL" ) ) }, + { ControlActions::GET_HELP_URL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getHelpURL" ) ) }, + { 0, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "noAction" ) ) } + }; + + for ( pPtr = pArray; pPtr->nId && ( pPtr->nId != nControlAction ); ++pPtr ) + ; + + rType = pPtr->pType; + + return sal_True; +} + +void UnxFilePicker::sendAppendControlCommand( sal_Int16 nControlId ) +{ + ::rtl::OUString aType; + sal_Int32 nTitleId; + + if ( controlIdInfo( nControlId, aType, nTitleId ) ) + { + ::rtl::OUStringBuffer aBuffer( 1024 ); + + aBuffer.appendAscii( "appendControl " ); + aBuffer.append( static_cast< sal_Int32 >( nControlId ) ); + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, aType ); + aBuffer.appendAscii( " ", 1 ); + appendEscaped( aBuffer, m_pResMgr? String( ResId( nTitleId, *m_pResMgr ) ): String() ); + + sendCommand( aBuffer.makeStringAndClear() ); + } +} + +uno::Sequence< ::rtl::OUString > SAL_CALL UnxFilePicker::getSelectedFiles() + throw( uno::RuntimeException ) +{ + return getFiles(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/UnxFilePicker.hxx b/vcl/unx/kde/UnxFilePicker.hxx new file mode 100644 index 000000000000..2dc50a8ec739 --- /dev/null +++ b/vcl/unx/kde/UnxFilePicker.hxx @@ -0,0 +1,188 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _UNXFILEPICKER_HXX_ +#define _UNXFILEPICKER_HXX_ + +#include <cppuhelper/compbase9.hxx> +#include <osl/conditn.hxx> +#include <osl/mutex.hxx> +#include <rtl/ustrbuf.hxx> + +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerNotifier.hpp> +#include <com/sun/star/ui/dialogs/XFilterManager.hpp> +#include <com/sun/star/ui/dialogs/XFilterGroupManager.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/XFilePreview.hpp> +#include <com/sun/star/ui/dialogs/XFilePicker2.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/util/XCancellable.hpp> + +#include <list> + +class UnxFilePickerCommandThread; +class UnxFilePickerNotifyThread; +class ResMgr; + +class UnxFilePickerDummy +{ +protected: + osl::Mutex m_aMutex; + osl::Mutex m_rbHelperMtx; +}; + +class UnxFilePicker : + public UnxFilePickerDummy, + public cppu::WeakComponentImplHelper9< + ::com::sun::star::ui::dialogs::XFilterManager, + ::com::sun::star::ui::dialogs::XFilterGroupManager, + ::com::sun::star::ui::dialogs::XFilePickerControlAccess, + ::com::sun::star::ui::dialogs::XFilePickerNotifier, + ::com::sun::star::ui::dialogs::XFilePicker2, +// TODO ::com::sun::star::ui::dialogs::XFilePreview, + ::com::sun::star::lang::XInitialization, + ::com::sun::star::util::XCancellable, + ::com::sun::star::lang::XEventListener, + ::com::sun::star::lang::XServiceInfo > +{ +protected: + + pid_t m_nFilePickerPid; + int m_nFilePickerWrite; // (kde|...)filepicker gets it as stdin + int m_nFilePickerRead; // (kde|...)filepicker gets it as stdout + + UnxFilePickerNotifyThread *m_pNotifyThread; + UnxFilePickerCommandThread *m_pCommandThread; + + ResMgr *m_pResMgr; + +public: + UnxFilePicker( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& ); + virtual ~UnxFilePicker(); + + // XComponent + + using cppu::WeakComponentImplHelperBase::disposing; + + // XFilePickerNotifier + + virtual void SAL_CALL addFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) throw( ::com::sun::star::uno::RuntimeException ); + + // XExecutableDialog functions + + virtual void SAL_CALL setTitle( const ::rtl::OUString &rTitle ) throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Int16 SAL_CALL execute() throw( ::com::sun::star::uno::RuntimeException ); + + // XFilePicker functions + + virtual void SAL_CALL setMultiSelectionMode( sal_Bool bMode ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setDefaultName( const ::rtl::OUString &rName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setDisplayDirectory( const ::rtl::OUString &rDirectory ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getDisplayDirectory() throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getFiles() throw( ::com::sun::star::uno::RuntimeException ); + + // XFilterManager functions + + virtual void SAL_CALL appendFilter( const ::rtl::OUString &rTitle, const ::rtl::OUString &rFilter ) throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setCurrentFilter( const ::rtl::OUString &rTitle ) throw( ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException ); + virtual ::rtl::OUString SAL_CALL getCurrentFilter() throw( ::com::sun::star::uno::RuntimeException ); + + // XFilterGroupManager functions + + virtual void SAL_CALL appendFilterGroup( const ::rtl::OUString &rGroupTitle, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::StringPair > &rFilters ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + // XFilePickerControlAccess functions + + virtual void SAL_CALL setValue( sal_Int16 nControlId, sal_Int16 nControlAction, const ::com::sun::star::uno::Any &rValue ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getValue( sal_Int16 nControlId, sal_Int16 nControlAction ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL enableControl( sal_Int16 nControlId, sal_Bool bEnable ) throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL setLabel( sal_Int16 nControlId, const ::rtl::OUString &rLabel ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getLabel( sal_Int16 nControlId ) throw (::com::sun::star::uno::RuntimeException); + + /* TODO XFilePreview + + virtual ::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL getSupportedImageFormats( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getTargetColorDepth( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAvailableWidth( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAvailableHeight( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setImage( sal_Int16 aImageFormat, const ::com::sun::star::uno::Any &rImage ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setShowState( sal_Bool bShowState ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL getShowState( ) throw (::com::sun::star::uno::RuntimeException); + */ + + // XFilePicker2 + + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSelectedFiles() + throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > &rArguments ) throw( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException ); + + // XCancellable + + virtual void SAL_CALL cancel( ) throw( ::com::sun::star::uno::RuntimeException ); + + // XEventListener + + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject &rEvent ) throw( ::com::sun::star::uno::RuntimeException ); + + // XServiceInfo + + virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString &rServiceName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ); + +private: + // prevent copy and assignment + UnxFilePicker( const UnxFilePicker& ); + UnxFilePicker& operator=( const UnxFilePicker& ); + +protected: + void initFilePicker(); + void checkFilePicker() throw( ::com::sun::star::uno::RuntimeException ); + + // Async sendCommand + void sendCommand( const ::rtl::OUString &rCommand ); + // Synchronized sendCommand + void sendCommand( const ::rtl::OUString &rCommand, ::osl::Condition &rCondition ); + void appendEscaped( ::rtl::OUStringBuffer &rBuffer, const ::rtl::OUString &rString ); + +private: + sal_Bool controlIdInfo( sal_Int16 nControlId, ::rtl::OUString &rType, sal_Int32 &rTitleId ); + sal_Bool controlActionInfo( sal_Int16 nControlId, ::rtl::OUString &rType ); + void sendAppendControlCommand( sal_Int16 nControlId ); +}; + +#endif // _UNXFILEPICKER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/UnxNotifyThread.cxx b/vcl/unx/kde/UnxNotifyThread.cxx new file mode 100644 index 000000000000..a97fdfc24fae --- /dev/null +++ b/vcl/unx/kde/UnxNotifyThread.cxx @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <UnxNotifyThread.hxx> +#include <UnxFilePicker.hxx> + +using namespace ::com::sun::star; + +////////////////////////////////////////////////////////////////////////// +// UnxFilePickerNotifyThread +////////////////////////////////////////////////////////////////////////// + +UnxFilePickerNotifyThread::UnxFilePickerNotifyThread( UnxFilePicker *pUnxFilePicker ) + : m_pUnxFilePicker( pUnxFilePicker ), + m_bExit( sal_False ), + m_eNotifyType( Nothing ), + m_nControlId( 0 ) +{ +} + +void SAL_CALL UnxFilePickerNotifyThread::addFilePickerListener( const uno::Reference< ui::dialogs::XFilePickerListener >& xListener ) + throw( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xListener = xListener; +} + +void SAL_CALL UnxFilePickerNotifyThread::removeFilePickerListener( const uno::Reference< ui::dialogs::XFilePickerListener >& /*xListener*/ ) + throw( uno::RuntimeException ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_xListener.clear(); +} + +void SAL_CALL UnxFilePickerNotifyThread::exit() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_bExit = sal_True; + + m_aExitCondition.reset(); + m_aNotifyCondition.set(); + + m_aExitCondition.wait(); +} + +void SAL_CALL UnxFilePickerNotifyThread::fileSelectionChanged() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + m_eNotifyType = FileSelectionChanged; + m_nControlId = 0; + + m_aNotifyCondition.set(); +} + +void SAL_CALL UnxFilePickerNotifyThread::run() +{ + do { + m_aNotifyCondition.reset(); + m_aNotifyCondition.wait(); + + if ( m_xListener.is() && m_pUnxFilePicker ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + ui::dialogs::FilePickerEvent aEvent( *m_pUnxFilePicker, m_nControlId ); + + switch ( m_eNotifyType ) + { + case FileSelectionChanged: + m_xListener->fileSelectionChanged( aEvent ); + break; + + // TODO More to come... + + default: + // nothing + break; + } + } + } while ( !m_bExit ); + + m_aExitCondition.set(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/UnxNotifyThread.hxx b/vcl/unx/kde/UnxNotifyThread.hxx new file mode 100644 index 000000000000..b60d7b475871 --- /dev/null +++ b/vcl/unx/kde/UnxNotifyThread.hxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _UNXNOTIFYTHREAD_HXX_ +#define _UNXNOTIFYTHREAD_HXX_ + +#include <com/sun/star/ui/dialogs/XFilePickerListener.hpp> +#include <com/sun/star/uno/Reference.hxx> + +#include <osl/conditn.hxx> +#include <osl/mutex.hxx> +#include <osl/thread.hxx> + +class UnxFilePicker; + +class UnxFilePickerNotifyThread : public ::osl::Thread +{ +protected: + enum NotifyType + { + Nothing = 0, + FileSelectionChanged + // TODO More to come... + }; + + UnxFilePicker *m_pUnxFilePicker; + + ::osl::Mutex m_aMutex; + + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener > m_xListener; + + sal_Bool m_bExit; + ::osl::Condition m_aExitCondition; + + NotifyType m_eNotifyType; + ::osl::Condition m_aNotifyCondition; + sal_Int16 m_nControlId; + +public: + UnxFilePickerNotifyThread( UnxFilePicker *pUnxFilePicker ); + + virtual void SAL_CALL addFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + virtual void SAL_CALL removeFilePickerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XFilePickerListener >& xListener ) + throw( ::com::sun::star::uno::RuntimeException ); + + void SAL_CALL exit(); + + void SAL_CALL fileSelectionChanged(); + /* TODO + void SAL_CALL directoryChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + rtl::OUString SAL_CALL helpRequested( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ) const; + void SAL_CALL controlStateChanged( ::com::sun::star::ui::dialogs::FilePickerEvent aEvent ); + void SAL_CALL dialogSizeChanged( ); + */ + +protected: + virtual void SAL_CALL run(); +}; + +#endif // _UNXNOTIFYTHREAD_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/fpicker/Makefile b/vcl/unx/kde/fpicker/Makefile new file mode 100644 index 000000000000..b7ba64946ba8 --- /dev/null +++ b/vcl/unx/kde/fpicker/Makefile @@ -0,0 +1,35 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# Version: MPL 1.1 / GPLv3+ / LGPLv3+ +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License or as specified alternatively below. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# Major Contributor(s): +# Copyright (C) 2010 Red Hat, Inc., David Tardon <dtardon@redhat.com> +# (initial developer) +# +# All Rights Reserved. +# +# For minor contributions see the git repository. +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 3 or later (the "GPLv3+"), or +# the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), +# in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable +# instead of those above. + +kdefilepicker.moc.cxx : $(SRCDIR)/fpicker/source/unx/kde/kdefilepicker.hxx + $(MOC) -o $@ $< + +.DEFAULT_GOAL := all +.PHONY : all +all : kdefilepicker.moc.cxx + +# vim:set shiftwidth=4 tabstop=4 noexpandtab: diff --git a/vcl/unx/kde/fpicker/kdecommandthread.cxx b/vcl/unx/kde/fpicker/kdecommandthread.cxx new file mode 100644 index 000000000000..b68ddb0030c4 --- /dev/null +++ b/vcl/unx/kde/fpicker/kdecommandthread.cxx @@ -0,0 +1,181 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <cstddef> + +#include <kdecommandthread.hxx> + +#include <qstringlist.h> + +#include <kapplication.h> + +#if OSL_DEBUG_LEVEL > 1 +#include <iostream> +#endif + +////////////////////////////////////////////////////////////////////////// +// CommandEvent +////////////////////////////////////////////////////////////////////////// + +KDECommandEvent::KDECommandEvent( const QString &qCommand, QStringList *pStringList ) + : QCustomEvent( TypeId, pStringList ), + m_eCommand( Unknown ) +{ + struct { + const char *pName; + CommandEventType eType; + } *pIdx, pMapping[] = + { + { "appendControl", AppendControl }, + { "enableControl", EnableControl }, + { "getValue", GetValue }, + { "setValue", SetValue }, + { "appendFilter", AppendFilter }, + { "appendFilterGroup", AppendFilterGroup }, + { "getCurrentFilter", GetCurrentFilter }, + { "setCurrentFilter", SetCurrentFilter }, + { "getDirectory", GetDirectory }, + { "setDirectory", SetDirectory }, + { "getFiles", GetFiles }, + { "setTitle", SetTitle }, + { "setType", SetType }, + { "setDefaultName", SetDefaultName }, + { "setMultiSelection", SetMultiSelection }, + { "exec", Exec }, + { 0, Unknown } + }; + + for ( pIdx = pMapping; pIdx->pName && qCommand != pIdx->pName; ++pIdx ) + ; + + m_eCommand = pIdx->eType; +} + +////////////////////////////////////////////////////////////////////////// +// CommandThread +////////////////////////////////////////////////////////////////////////// + +KDECommandThread::KDECommandThread( QWidget *pObject ) + : m_pObject( pObject ) +{ +} + +KDECommandThread::~KDECommandThread() +{ +} + +void KDECommandThread::run() +{ + QTextIStream qStream( stdin ); + qStream.setEncoding( QTextStream::UnicodeUTF8 ); + + QString qLine; + bool bQuit = false; + while ( !bQuit && !qStream.atEnd() ) + { + qLine = qStream.readLine(); + handleCommand( qLine, bQuit ); + } +} + +void KDECommandThread::handleCommand( const QString &rString, bool &bQuit ) +{ + QMutexLocker qMutexLocker( &m_aMutex ); + +#if OSL_DEBUG_LEVEL > 1 + ::std::cerr << "kdefilepicker received: " << rString.latin1() << ::std::endl; +#endif + + bQuit = false; + QStringList *pTokens = tokenize( rString ); + + if ( !pTokens ) + return; + if ( pTokens->empty() ) + { + delete pTokens, pTokens = NULL; + return; + } + + QString qCommand = pTokens->front(); + pTokens->pop_front(); + + if ( qCommand == "exit" ) + { + bQuit = true; + kapp->exit(); + kapp->wakeUpGuiThread(); + } + else + kapp->postEvent( m_pObject, new KDECommandEvent( qCommand, pTokens ) ); +} + +QStringList* KDECommandThread::tokenize( const QString &rString ) +{ + // Commands look like: + // command arg1 arg2 arg3 ... + // Args may be enclosed in '"', if they contain spaces. + + QStringList *pList = new QStringList(); + + QString qBuffer; + qBuffer.reserve( 1024 ); + + const QChar *pUnicode = rString.unicode(); + const QChar *pEnd = pUnicode + rString.length(); + bool bQuoted = false; + + for ( ; pUnicode != pEnd; ++pUnicode ) + { + if ( *pUnicode == '\\' ) + { + ++pUnicode; + if ( pUnicode != pEnd ) + { + if ( *pUnicode == 'n' ) + qBuffer.append( '\n' ); + else + qBuffer.append( *pUnicode ); + } + } + else if ( *pUnicode == '"' ) + bQuoted = !bQuoted; + else if ( *pUnicode == ' ' && !bQuoted ) + { + pList->push_back( qBuffer ); + qBuffer.setLength( 0 ); + } + else + qBuffer.append( *pUnicode ); + } + pList->push_back( qBuffer ); + + return pList; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/fpicker/kdecommandthread.hxx b/vcl/unx/kde/fpicker/kdecommandthread.hxx new file mode 100644 index 000000000000..7486bf9192f6 --- /dev/null +++ b/vcl/unx/kde/fpicker/kdecommandthread.hxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _KDECOMMANDTHREAD_HXX_ +#define _KDECOMMANDTHREAD_HXX_ + +#include <qevent.h> +#include <qmutex.h> +#include <qthread.h> + +class KDECommandEvent : public QCustomEvent +{ +public: + enum CommandEventType { + Unknown = 0, + + AppendControl, + EnableControl, + GetValue, + SetValue, + + AppendFilter, + AppendFilterGroup, + UpdateFilters, + GetCurrentFilter, + SetCurrentFilter, + + GetDirectory, + SetDirectory, + + GetFiles, + + SetTitle, + SetType, + SetDefaultName, + SetMultiSelection, + + Exec + }; + static const QEvent::Type TypeId = (QEvent::Type) ( (int) QEvent::User + 42 /*random magic value*/ ); + +protected: + CommandEventType m_eCommand; + +public: + KDECommandEvent( const QString &qCommand, QStringList *pStringList ); + + CommandEventType command() const { return m_eCommand; } + QStringList* stringList() { return static_cast< QStringList* >( data() ); } +}; + +class KDECommandThread : public QThread +{ +protected: + QObject *m_pObject; + + QMutex m_aMutex; + +public: + KDECommandThread( QWidget *pObject ); + virtual ~KDECommandThread(); + + virtual void run(); + +protected: + void handleCommand( const QString &rString, bool &bQuit ); + QStringList* tokenize( const QString &rString ); +}; + +#endif // _KDECOMMANDTHREAD_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/fpicker/kdefilepicker.cxx b/vcl/unx/kde/fpicker/kdefilepicker.cxx new file mode 100644 index 000000000000..779a34d894d0 --- /dev/null +++ b/vcl/unx/kde/fpicker/kdefilepicker.cxx @@ -0,0 +1,734 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <cstddef> + +#include <kdecommandthread.hxx> +#include <kdefilepicker.hxx> + +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qgrid.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qobjectlist.h> +#include <qpushbutton.h> +#include <qregexp.h> +#include <qvbox.h> + +#ifdef QT_NO_EMIT +#define emit +#endif + +#include <kdeversion.h> +#include <kdiroperator.h> +#include <kfiledialog.h> +#include <kfilefiltercombo.h> +#include <kio/netaccess.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <ktempfile.h> + +#include <algorithm> +#include <iostream> + +////////////////////////////////////////////////////////////////////////// +// KDEFileDialog +////////////////////////////////////////////////////////////////////////// + +KDEFileDialog::KDEFileDialog( const QString &startDir, const QString &filter, + QWidget *parent, const char *name ) + : KFileDialog( startDir, filter, parent, name, true, m_pCustomWidget = new QVBox() ), + m_pCombosAndButtons( new QHBox( m_pCustomWidget ) ), + m_pLabels( new QVBox( m_pCombosAndButtons ) ), + m_pComboBoxes( new QVBox( m_pCombosAndButtons ) ), + m_pPushButtons( new QVBox( m_pCombosAndButtons ) ), + m_pCheckBoxes( new QGrid( 2, m_pCustomWidget ) ), + m_bIsSave( false ), + m_bIsExecuting( false ), + m_bCanNotifySelection( true ) +{ + connect( this, SIGNAL( fileHighlighted( const QString & ) ), + this, SLOT( fileHighlightedCommand( const QString & ) ) ); + + connect( this, SIGNAL( selectionChanged() ), + this, SLOT( selectionChangedCommand() ) ); + + m_pCustomWidget->setSpacing( KDialog::spacingHint() ); + m_pCombosAndButtons->setSpacing( KDialog::spacingHint() ); + + updateCustomWidgetLayout(); +} + +KDEFileDialog::~KDEFileDialog() +{ +} + +void KDEFileDialog::resizeEvent( QResizeEvent *pEvent ) +{ + KFileDialog::resizeEvent( pEvent ); + + updateCustomWidgetLayout(); +} + +void KDEFileDialog::showEvent( QShowEvent *pEvent ) +{ + KFileDialog::showEvent( pEvent ); + + updateCustomWidgetLayout(); +} + +void KDEFileDialog::updateCustomWidgetLayout() +{ + QPoint qReferencePoint = filterWidget->mapTo( this, QPoint( 0, 0 ) ); + QPoint qCustomPoint = m_pCustomWidget->mapTo( this, QPoint( 0, 0 ) ); + + int nLeft = qReferencePoint.x() - qCustomPoint.x(); + int nRight = m_pCustomWidget->width() - filterWidget->width() - nLeft; + + nLeft -= KDialog::spacingHint(); + nRight -= KDialog::spacingHint(); + m_pLabels->setFixedWidth( ( nLeft > 0 )? nLeft: 80 ); + // FIXME The following call sets the width of m_pPushButtons all right, + // but it also increases the width of m_pComboBoxes rapidly. Can we do + // anything about it? + m_pPushButtons->setFixedWidth( ( nRight > 0 )? nRight: 100 ); +} + +void KDEFileDialog::customEvent( QCustomEvent *pEvent ) +{ + if ( pEvent && pEvent->type() == KDECommandEvent::TypeId ) + { + KDECommandEvent *pCommandEvent = static_cast< KDECommandEvent* >( pEvent ); + QStringList *pStringList = pCommandEvent->stringList(); + + int nListSize = -1; + if ( pStringList ) + nListSize = pStringList->size(); + + switch ( pCommandEvent->command() ) + { + case KDECommandEvent::AppendControl: + if ( nListSize >= 3 ) + { + appendControl( (*pStringList)[0], (*pStringList)[1], (*pStringList)[2] ); + } + break; + case KDECommandEvent::EnableControl: + if ( nListSize >= 2 ) + { + enableControl( (*pStringList)[0], (*pStringList)[1] ); + } + break; + case KDECommandEvent::GetValue: + if ( nListSize >= 2 ) + { + getValue( (*pStringList)[0], (*pStringList)[1] ); + } + break; + case KDECommandEvent::SetValue: + if ( nListSize >= 2 ) + { + QStringList qStringList = (*pStringList); + qStringList.pop_front(); + qStringList.pop_front(); + + setValue( (*pStringList)[0], (*pStringList)[1], qStringList ); + } + break; + case KDECommandEvent::AppendFilter: + if ( nListSize >= 2 ) + { + appendFilter( (*pStringList)[0], (*pStringList)[1] ); + + // update the filters widget + setFilter( filters() ); + } + break; + case KDECommandEvent::AppendFilterGroup: + if ( nListSize >= 1 ) + { + QStringList::const_iterator it = pStringList->begin(); + ++it; // We ignore the filter group name + + while ( it != pStringList->end() ) + { + QString qTitle = *it; + ++it; + if ( it != pStringList->end() ) + { + appendFilter( qTitle, (*it) ); + ++it; + } + } + + // update the filters widget + setFilter( filters() ); + } + break; + case KDECommandEvent::GetCurrentFilter: + { + QString qCurrentFilter = filterWidget->currentText(); + sendCommand( "currentFilter " + escapeString( qCurrentFilter ) ); + } + break; + case KDECommandEvent::SetCurrentFilter: + if ( nListSize >= 1 ) + { + static_cast< KDEFileFilterComboHack* >( filterWidget )->setCurrentFilter( pStringList->front() ); + } + break; + case KDECommandEvent::GetDirectory: + { + QString qDirectory = baseURL().url(); + if ( qDirectory.startsWith( "file:/" ) && qDirectory.mid( 6, 1 ) != "/" ) + qDirectory.replace( "file:/", "file:///" ); + sendCommand( "currentDirectory " + escapeString( qDirectory ) ); + } + break; + case KDECommandEvent::SetDirectory: + if ( nListSize >= 1 ) + { + setURL( pStringList->front() ); + } + break; + case KDECommandEvent::GetFiles: + { + QString qString; + qString.reserve( 1024 ); + + qString.append( "files" ); + + if ( result() == QDialog::Accepted ) + { + KURL::List qList( selectedURLs() ); + for ( KURL::List::const_iterator it = qList.begin(); it != qList.end(); ++it ) + appendURL( qString, (*it) ); + } + else + { + // we have to return the selected files anyway + const KFileItemList *pItems = ops->selectedItems(); + for ( KFileItemListIterator it( *pItems ); it.current(); ++it ) + appendURL( qString, (*it)->url() ); + } + + sendCommand( qString ); + setCanNotifySelection( true ); + } + break; + case KDECommandEvent::SetTitle: + if ( nListSize >= 1 ) + { + setCaption( pStringList->front() ); + } + break; + case KDECommandEvent::SetType: + if ( nListSize >= 1 ) + { + QString qType( pStringList->front() ); + if ( qType == "open" ) + { + setIsSave( false ); + setCaption( i18n( "Open" ) ); + } + else if ( qType == "save" ) + { + setIsSave( true ); + setCaption( i18n( "Save As" ) ); + } + } + break; + case KDECommandEvent::SetDefaultName: + if ( nListSize >= 1 ) + { + setKeepLocation( true ); + setSelection( pStringList->front() ); + } + break; + case KDECommandEvent::SetMultiSelection: + if ( nListSize >= 1 ) + { + if ( pStringList->front() == "true" ) + setMode( KFile::Files ); + else + setMode( KFile::File ); + } + break; + case KDECommandEvent::Exec: + { + filterWidget->setEditable( false ); + setIsExecuting( true ); + bool bCanExit = false; + do { + setCanNotifySelection( true ); + exec(); + + KURL qLocalSelectedURL = mostLocalURL( selectedURL() ); + QString qProtocol( qLocalSelectedURL.protocol() ); + + if ( isSave() && result() == QDialog::Accepted ) + { + if ( qProtocol == "file" ) + { + QString qFileName( addExtension( qLocalSelectedURL.path() ) ); + bCanExit = + !QFile::exists( qFileName ) || + ( KMessageBox::warningYesNo( 0, + i18n( "A file named \"%1\" already exists. " + "Are you sure you want to overwrite it?" ).arg( qFileName ), + i18n( "Overwrite File?" ), + i18n( "Overwrite" ), KStdGuiItem::cancel() ) == KMessageBox::Yes ); + } + else if ( !isSupportedProtocol( qProtocol ) ) + { + KMessageBox::sorry( 0, + i18n( "Saving using protocol \"%1\" is not supported." ).arg( qProtocol ) ); + bCanExit = false; + } + else + bCanExit = true; + } + else if ( !isSave() && result() == QDialog::Accepted && !isSupportedProtocol( qProtocol ) ) + { + KMessageBox::information( 0, + i18n( "Protocol \"%1\" is supported only partially. " + "Local copy of the file will be created." ).arg( qProtocol ) ); + bCanExit = true; + } + else + bCanExit = true; + } while ( !bCanExit ); + setIsExecuting( false ); + + if ( result() == QDialog::Accepted ) + sendCommand( "accept" ); + else + sendCommand( "reject" ); + } + break; + default: + break; + } + + // FIXME Some cleanup of pEvent? delete something, etc.? + } +} + +void KDEFileDialog::appendControl( const QString &rId, const QString &rType, const QString &rTitle ) +{ + QString qLabel( rTitle ); + qLabel.replace( '~', '&' ); + + if ( rType == "checkbox" ) + { + QCheckBox *pCheckBox = new QCheckBox( qLabel, m_pCheckBoxes, rId.utf8() ); + + pCheckBox->setEnabled( true ); + pCheckBox->setChecked( false ); + } + else if ( rType == "listbox" ) + { + QLabel *pComboLabel = new QLabel( qLabel, m_pLabels ); + QComboBox *pComboBox = new QComboBox( m_pComboBoxes, rId.utf8() ); + + pComboLabel->setBuddy( pComboBox ); + pComboBox->setEnabled( true ); + } + else if ( rType == "pushbutton" ) + { + QPushButton *pPushButton = new QPushButton( qLabel, m_pPushButtons, rId.utf8() ); + pPushButton->setEnabled( true ); + } +} + +QWidget* KDEFileDialog::findControl( const QString &rId ) const +{ + QObjectList *pList = m_pCustomWidget->queryList(); + QCString qName( rId.utf8() ); + QObjectList::const_iterator it = pList->begin(); + + for ( ; it != pList->end() && qName != (*it)->name(); ++it ) + ; + + QWidget *pWidget = NULL; + if ( it != pList->end() ) + pWidget = static_cast< QWidget* >( *it ); + + delete pList; + + return pWidget; +} + +void KDEFileDialog::enableControl( const QString &rId, const QString &rValue ) +{ + QWidget *pWidget = findControl( rId ); + + if ( pWidget ) + pWidget->setEnabled( rValue.lower() == "true" ); +} + +void KDEFileDialog::getValue( const QString &rId, const QString &rAction ) +{ + QWidget *pWidget = findControl( rId ); + QString qString; + qString.reserve( 1024 ); + qString.append( "value" ); + + if ( pWidget ) + { + QCString qClassName = pWidget->className(); + if ( qClassName == "QCheckBox" ) + { + QCheckBox *pCheckBox = static_cast< QCheckBox* >( pWidget ); + + if ( pCheckBox->isChecked() ) + qString.append( " bool true" ); + else + qString.append( " bool false" ); + } + else if ( qClassName == "QComboBox" ) + { + QComboBox *pComboBox = static_cast< QComboBox* >( pWidget ); + if ( rAction == "getItems" ) + { + qString.append( " stringList" ); + for ( int nIdx = 0; nIdx < pComboBox->count(); ++nIdx ) + { + qString.append( ' ' ); + appendEscaped( qString, pComboBox->text( nIdx ) ); + } + } + else if ( rAction == "getSelectedItem" ) + { + qString.append( " string " ); + appendEscaped( qString, pComboBox->currentText() ); + } + else if ( rAction == "getSelectedItemIndex" ) + { + qString.append( " int " ); + qString.append( QString().setNum( pComboBox->currentItem() ) ); + } + // TODO getHelpURL + } + // TODO push button + } + + sendCommand( qString ); +} + +void KDEFileDialog::setValue( const QString &rId, const QString &rAction, const QStringList &rValue ) +{ + QWidget *pWidget = findControl( rId ); + + if ( pWidget ) + { + QCString qClassName = pWidget->className(); + if ( qClassName == "QCheckBox" ) + { + QCheckBox *pCheckBox = static_cast< QCheckBox* >( pWidget ); + + bool bValue = ( !rValue.isEmpty() ) && ( rValue.front().lower() == "true" ); + pCheckBox->setChecked( bValue ); + } + else if ( qClassName == "QComboBox" ) + { + QComboBox *pComboBox = static_cast< QComboBox* >( pWidget ); + if ( rAction == "addItem" ) + { + if ( !rValue.isEmpty() ) + pComboBox->insertItem( rValue.front() ); + } + else if ( rAction == "addItems" ) + { + pComboBox->insertStringList( rValue ); + } + else if ( rAction == "deleteItem" ) + { + if ( !rValue.isEmpty() ) + pComboBox->removeItem( rValue.front().toInt() ); + } + else if ( rAction == "deleteItems" ) + { + pComboBox->clear(); + } + else if ( rAction == "setSelectedItem" ) + { + if ( !rValue.isEmpty() ) + pComboBox->setCurrentItem( rValue.front().toInt() ); + } + // FIXME setHelpURL is ignored + } + // TODO push button + } +} + +void KDEFileDialog::appendFilter( const QString &rTitle, const QString &rFilter ) +{ + // Filters are separated by ';' + QString qFilter( rFilter ); + qFilter.replace( QChar( ';' ), QChar( ' ' ) ).replace( "*.*", "*" ); + + // Workaround for too wide <All formats> (*.bmp;...) entry + QString qTitle( rTitle ); + qTitle.replace( QRegExp( "^<([^>]*)> \\(.*" ), "<\\1>" ); + + m_aFilters.push_back( qMakePair( qTitle, qFilter ) ); +} + +QString KDEFileDialog::filters() const +{ + QString qString, qTmp; + bool bFirstFilter = true; + + for ( FilterList::const_iterator it = m_aFilters.begin(); it != m_aFilters.end(); ++it ) + { + if ( bFirstFilter ) + bFirstFilter = false; + else + qString.append( '\n' ); + + qString.append( (*it).second ); + qString.append( '|' ); + + qTmp = (*it).first; + qString.append( qTmp.replace( '/', "\\/" ) ); + } + + return qString; +} + +QString KDEFileDialog::addExtension( const QString &rFileName ) const +{ + if ( !isSave() ) + return rFileName; + + QString qExtension; + + QWidget *pExtensionWidget = findControl( "100" ); // CHECKBOX_AUTOEXTENSION + QCheckBox *pExtensionCB = pExtensionWidget? static_cast< QCheckBox* >( pExtensionWidget->qt_cast( "QCheckBox" ) ): NULL; + if ( pExtensionCB && pExtensionCB->isChecked() ) + { + // FIXME: qFilter can be a MIME; we ignore it now... + QStringList qFilterList = QStringList::split( " ", currentFilter() ); + for ( QStringList::const_iterator it = qFilterList.begin(); + qExtension.isEmpty() && it != qFilterList.end(); + ++it ) + { + int nUnwanted = (*it).findRev( '*' ); + if ( nUnwanted < 0 ) + nUnwanted = (*it).findRev( '?' ); + else + nUnwanted = ::std::max( nUnwanted, (*it).find( '?', nUnwanted ) ); + + int nIdx = (*it).find( '.', ::std::max( nUnwanted, 0 ) ); + if ( nIdx >= 0 ) + qExtension = (*it).mid( nIdx ).lower(); + } + } + + if ( qExtension.isEmpty() || qExtension == "." || rFileName.endsWith( qExtension ) ) + return rFileName; + else + return rFileName + qExtension; +} + +bool KDEFileDialog::isSupportedProtocol( const QString &rProtocol ) const +{ + // TODO Get this information directly from OOo + const char * pOOoProtocols[] = { "", "smb", "ftp", "http", "file", "mailto", + "vnd.sun.star.webdav", "news", "private", "vnd.sun.star.help", + "https", "slot", "macro", "javascript", "imap", "pop3", "data", + "cid", "out", "vnd.sun.star.wfs", "vnd.sun.star.hier", "vim", + ".uno", ".component", "vnd.sun.star.pkg", "ldap", "db", + "vnd.sun.star.cmd", "vnd.sun.star.script", "vnd.sun.star.odma", + "telnet", + NULL }; + + for ( const char **pIndex = pOOoProtocols; *pIndex != NULL; ++pIndex ) + { + if ( rProtocol == *pIndex ) + return true; + } + + // TODO gnome-vfs bits here + + return false; +} + +KURL KDEFileDialog::mostLocalURL( const KURL &rURL ) const +{ +#if KDE_IS_VERSION(3,5,0) + KURL qMostLocalURL( KIO::NetAccess::mostLocalURL( rURL, const_cast<KDEFileDialog*>( this ) ) ); + if ( qMostLocalURL.isLocalFile() ) + return qMostLocalURL; + else + { + // Terrible hack to get even non-existing media:// files right + qMostLocalURL.cd( ".." ); + KURL qMostLocalPath( KIO::NetAccess::mostLocalURL( qMostLocalURL, const_cast<KDEFileDialog*>( this ) ) ); + if ( qMostLocalPath.isLocalFile() ) + { + qMostLocalPath.addPath( rURL.fileName() ); + return qMostLocalPath; + } + } +#endif + + return rURL; +} + +QString KDEFileDialog::localCopy( const QString &rFileName ) const +{ + // 106 == MIB enum for UTF-8 + KURL qLocalURL = mostLocalURL( KURL( rFileName, 106 ) ); + if ( qLocalURL.isLocalFile() ) + return qLocalURL.url(); + + int nExtensionPos = rFileName.findRev( '/' ); + if ( nExtensionPos >= 0 ) + nExtensionPos = rFileName.find( '.', nExtensionPos ); + else + nExtensionPos = rFileName.find( '.' ); + + KTempFile qTempFile( QString::null, ( nExtensionPos < 0 )? QString(): rFileName.mid( nExtensionPos ) ); + KURL qDestURL; + qDestURL.setPath( qTempFile.name() ); + + if ( !KIO::NetAccess::file_copy( rFileName, qDestURL, 0600, true, false, NULL ) ) + { + KMessageBox::error( 0, KIO::NetAccess::lastErrorString() ); + return QString::null; + } + + return qDestURL.url(); +} + +void KDEFileDialog::fileHighlightedCommand( const QString & ) +{ + if ( canNotifySelection() ) + { + sendCommand( "fileSelectionChanged" ); + setCanNotifySelection( false ); + } +} + +void KDEFileDialog::selectionChangedCommand() +{ + if ( canNotifySelection() ) + { + sendCommand( "fileSelectionChanged" ); + setCanNotifySelection( false ); + } +} + +void KDEFileDialog::sendCommand( const QString &rCommand ) +{ +#if OSL_DEBUG_LEVEL > 1 + ::std::cerr << "kdefilepicker sent: " << rCommand.latin1() << ::std::endl; +#endif + + //m_aOutputStream << rCommand << endl; + ::std::cout << rCommand.utf8() << ::std::endl; +} + +void KDEFileDialog::appendURL( QString &rBuffer, const KURL &rURL ) +{ + // From Martin Kretzschmar: + // file:///path/to/test%E0.odt is not a valid URL from OOo's point of + // view. (?Most modern parts of?) OOo assume(s) that the URL contains only + // ASCII characters (which test%E0.odt does) and is UTF-8 after unescaping + // (which file:///path/test%E0.odt is not). + // Cf. the comment in sal/inc/osl/file.h. + // 106 == MIB enum for UTF-8 + QString qUrlStr = addExtension( rURL.url( 0, 106 ) ); + + if ( !isExecuting() && !isSupportedProtocol( rURL.protocol() ) ) + qUrlStr = localCopy( qUrlStr ); + + if ( qUrlStr.startsWith( "file:/" ) && qUrlStr.mid( 6, 1 ) != "/" ) + qUrlStr.replace( "file:/", "file:///" ); + + rBuffer.append( " " ); + if ( !qUrlStr.isEmpty() ) + appendEscaped( rBuffer, qUrlStr ); +} + +void KDEFileDialog::appendEscaped( QString &rBuffer, const QString &rString ) +{ + const QChar *pUnicode = rString.unicode(); + const QChar *pEnd = pUnicode + rString.length(); + + rBuffer.append( '"' ); + for ( ; pUnicode != pEnd; ++pUnicode ) + { + if ( *pUnicode == '\\' ) + rBuffer.append( "\\\\" ); + else if ( *pUnicode == '"' ) + rBuffer.append( "\\\"" ); + else if ( *pUnicode == '\n' ) + rBuffer.append( "\\\n" ); + else + rBuffer.append( *pUnicode ); + } + rBuffer.append( '"' ); +} + +QString KDEFileDialog::escapeString( const QString &rString ) +{ + QString qString; + qString.reserve( 2*rString.length() + 2 ); // every char escaped + quotes + + appendEscaped( qString, rString ); + + return qString; +} + + +void KDEFileFilterComboHack::setCurrentFilter( const QString& filter ) +{ + setCurrentText( filter ); + filterChanged(); + + // Workaround for 'Filter name (*.blah)' vs. 'Filter name' + if ( currentText() != text( currentItem() ) ) + { + int nItem = 0; + for ( ; nItem < count() && !text( nItem ).startsWith( filter ); ++nItem ); + + if ( nItem < count() ) + setCurrentItem( nItem ); + else + setCurrentItem( 0 ); + + filterChanged(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/fpicker/kdefilepicker.hxx b/vcl/unx/kde/fpicker/kdefilepicker.hxx new file mode 100644 index 000000000000..4d545ebc76ca --- /dev/null +++ b/vcl/unx/kde/fpicker/kdefilepicker.hxx @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _KDEFILEPICKER_HXX_ +#define _KDEFILEPICKER_HXX_ + +#include <cstddef> + +#include <kfiledialog.h> +#include <kfilefiltercombo.h> + +class QGrid; +class QHBox; +class QVBox; + +class KDEFileDialog : public KFileDialog +{ + Q_OBJECT + +protected: + typedef QPair< QString, QString > FilterEntry; + typedef QValueList< FilterEntry > FilterList; + + QVBox *m_pCustomWidget; + QHBox *m_pCombosAndButtons; + + QVBox *m_pLabels; + QVBox *m_pComboBoxes; + QVBox *m_pPushButtons; + + QGrid *m_pCheckBoxes; + + FilterList m_aFilters; + + /** Are we a "Save As" dialog? + * + * We cannot use KFileDialog::setOperationMode() here, because then + * it automatically adds an "Automatically select filename extension" + * check box, and completely destroys the dialog's layout + * (custom list boxes are under this check box, which looks ugly). + */ + bool m_bIsSave; + bool m_bIsExecuting; + + bool m_bCanNotifySelection; + +public: + KDEFileDialog( const QString &startDir, const QString &filter, + QWidget *parent, const char *name ); + virtual ~KDEFileDialog(); + +protected: + virtual void resizeEvent( QResizeEvent *pEvent ); + virtual void showEvent( QShowEvent *pEvent ); + void updateCustomWidgetLayout(); + + virtual void customEvent( QCustomEvent *pEvent ); + +protected: + void appendControl( const QString &rId, const QString &rType, const QString &rTitle ); + QWidget* findControl( const QString &rId ) const; + void enableControl( const QString &rId, const QString &rValue ); + void getValue( const QString &rId, const QString &rAction ); + void setValue( const QString &rId, const QString &rAction, const QStringList &rValue ); + + void appendFilter( const QString &rTitle, const QString &rFilter ); + QString filters() const; + QString addExtension( const QString &rFileName ) const; + + void setIsSave( bool bIsSave ) { m_bIsSave = bIsSave; } + bool isSave( void ) const { return m_bIsSave; } + + void setIsExecuting( bool bIsExecuting ) { m_bIsExecuting = bIsExecuting; } + bool isExecuting( void ) const { return m_bIsExecuting; } + + bool isSupportedProtocol( const QString &rProtocol ) const; + KURL mostLocalURL( const KURL &rURL ) const; + QString localCopy( const QString &rFileName ) const; + + void setCanNotifySelection( bool bCanNotifySelection ) { m_bCanNotifySelection = bCanNotifySelection; } + bool canNotifySelection( void ) const { return m_bCanNotifySelection; } + +protected slots: + void fileHighlightedCommand( const QString & ); + void selectionChangedCommand(); + +protected: + void sendCommand( const QString &rCommand ); + void appendURL( QString &rBuffer, const KURL &rURL ); + void appendEscaped( QString &rBuffer, const QString &rString ); + QString escapeString( const QString &rString ); +}; + +class KDEFileFilterComboHack : public KFileFilterCombo +{ +public: + void setCurrentFilter( const QString& filter ); +}; + +#endif // _KDEFILEPICKER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/fpicker/kdefpmain.cxx b/vcl/unx/kde/fpicker/kdefpmain.cxx new file mode 100644 index 000000000000..be4022664014 --- /dev/null +++ b/vcl/unx/kde/fpicker/kdefpmain.cxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <cstddef> + +#include <kdemodalityfilter.hxx> +#include <kdefilepicker.hxx> +#include <kdecommandthread.hxx> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> + +#include <iostream> +#include <stdlib.h> + +////////////////////////////////////////////////////////////////////////// +// Main +////////////////////////////////////////////////////////////////////////// + +static KCmdLineOptions sOptions[] = +{ + { "winid <argument>", I18N_NOOP("Window ID to which is the fpicker modal"), "0" }, + KCmdLineLastOption +}; + +int main( int argc, char* argv[] ) +{ + // we fake the name of the application to have "LibreOffice" in the + // title + KAboutData qAboutData( "kdefilepicker", I18N_NOOP( "LibreOffice" ), + "0.1", I18N_NOOP( "kdefilepicker is an implementation of the KDE file dialog for LibreOffice." ), + KAboutData::License_LGPL, + "(c) 2004, Jan Holesovsky" ); + qAboutData.addAuthor( "Jan Holesovsky", I18N_NOOP("Original author and current maintainer"), "kendy@openoffice.org" ); + + // Let the user see that this does something... + ::std::cerr << "kdefilepicker, an implementation of KDE file dialog for OOo." << ::std::endl + << "Type 'exit' and press Enter to finish." << ::std::endl; + + KCmdLineArgs::addCmdLineOptions( sOptions ); + KCmdLineArgs::init( argc, argv, &qAboutData ); + + KLocale::setMainCatalogue( "kdialog" ); + + KApplication kApplication; + + // Setup the modality + KCmdLineArgs *pArgs = KCmdLineArgs::parsedArgs(); + long nWinId = atol( pArgs->getOption( "winid" ) ); + pArgs->clear(); + + KDEModalityFilter qModalityFilter( nWinId ); + + KDEFileDialog aFileDialog( NULL, QString(), NULL, "kdefiledialog" ); + + KDECommandThread qCommandThread( &aFileDialog ); + qCommandThread.start(); + + kApplication.exec(); + + qCommandThread.wait(); + + ::std::cout << "exited" << ::std::endl; + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/fpicker/kdemodalityfilter.cxx b/vcl/unx/kde/fpicker/kdemodalityfilter.cxx new file mode 100644 index 000000000000..5aeddb0a80a6 --- /dev/null +++ b/vcl/unx/kde/fpicker/kdemodalityfilter.cxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <cstddef> + +#include <kdemodalityfilter.hxx> + +#include <kapplication.h> +#include <kdialogbase.h> + +#include <netwm.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +////////////////////////////////////////////////////////////////////////// +// Modality filter +////////////////////////////////////////////////////////////////////////// + +KDEModalityFilter::KDEModalityFilter( WId nWinId ) + : m_nWinId( nWinId ) +{ + kapp->installEventFilter( this ); +} + +KDEModalityFilter::~KDEModalityFilter() +{ + kapp->removeEventFilter( this ); +} + +bool KDEModalityFilter::eventFilter( QObject *pObject, QEvent *pEvent ) +{ + if ( pObject->isWidgetType() && pEvent->type() == QEvent::Show ) + { + KDialogBase* pDlg = ::qt_cast< KDialogBase* >( pObject ); + if ( pDlg != NULL && m_nWinId != 0 ) + { + XSetTransientForHint( qt_xdisplay(), pDlg->winId(), m_nWinId ); + m_nWinId = 0; + } + } + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/fpicker/kdemodalityfilter.hxx b/vcl/unx/kde/fpicker/kdemodalityfilter.hxx new file mode 100644 index 000000000000..8635694a39e1 --- /dev/null +++ b/vcl/unx/kde/fpicker/kdemodalityfilter.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2010 Novell, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _KDEMODALITYFILTER_HXX_ +#define _KDEMODALITYFILTER_HXX_ + +#include <qobject.h> + +class KDEModalityFilter : public QObject +{ +private: + WId m_nWinId; + +public: + KDEModalityFilter( WId nWinId ); + virtual ~KDEModalityFilter(); + + virtual bool eventFilter( QObject *pObject, QEvent *pEvent ); +}; + +#endif // _KDEMODALITYFILTER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/kde/salnativewidgets-kde.cxx b/vcl/unx/kde/salnativewidgets-kde.cxx index adee91e73a32..0376e94a8ab4 100644 --- a/vcl/unx/kde/salnativewidgets-kde.cxx +++ b/vcl/unx/kde/salnativewidgets-kde.cxx @@ -29,6 +29,7 @@ #define _SV_SALNATIVEWIDGETS_KDE_CXX #include <unx/kde/kde_headers.h> +#include "UnxFilePicker.hxx" #include <unx/salunx.h> #include <unx/saldata.hxx> @@ -41,7 +42,7 @@ #include <vcl/vclenum.hxx> #include <rtl/ustrbuf.hxx> - +using namespace ::com::sun::star; using namespace ::rtl; /** Cached native widgets. @@ -2055,6 +2056,13 @@ KDESalInstance::CreateFrame( SalFrame *pParent, sal_uLong nStyle ) return new KDESalFrame( pParent, nStyle ); } +uno::Reference< ui::dialogs::XFilePicker2 > KDESalInstance::createFilePicker( + const uno::Reference< uno::XComponentContext >& xMSF ) +{ + return uno::Reference< ui::dialogs::XFilePicker2 >( + new UnxFilePicker( xMSF ) ); +} + // ----------------------------------------------------------------------- // KDESalData pieces // ----------------------------------------------------------------------- |