/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
void SvtMatchContext_Impl::execute( )
{
doExecute();
aLink.Call( this );
}
// This method is called via AsynchronLink, so it has the SolarMutex and // calling solar code ( VCL ... ) is safe. It is called when the thread is // terminated ( finished work or stopped ). Cancelling the thread via // Cancellable does not discard the information gained so far, it // inserts all collected completions into the listbox.
IMPL_LINK_NOARG( SvtMatchContext_Impl, Select_Impl, void*, void )
{ // avoid recursion through cancel button
{
std::scoped_lock g(mutex_); if (stopped_) { // Completion was stopped, no display: return;
}
}
// insert all completed strings into the listbox
pBox->clear();
for (autoconst& completion : aCompletions)
{ // convert the file into a URL
OUString sURL;
osl::FileBase::getFileURLFromSystemPath(completion, sURL); // note: if this doesn't work, we're not interested in: we're checking the // untouched sCompletion then
if ( ::std::none_of( pBox->pImpl->m_aFilters.begin(),
pBox->pImpl->m_aFilters.end(),
FilterMatch( sUpperURL ) ) )
{ // this URL is not allowed continue;
}
}
pBox->append_text(completion);
}
pBox->EnableAutocomplete(!bNoSelection);
// transfer string lists to listbox and forget them
pBox->pImpl->aURLs = aURLs;
pBox->pImpl->aCompletions = aCompletions;
aURLs.clear();
aCompletions.clear();
// the box has this control as a member so we have to set that member // to zero before deleting ourself.
pBox->pCtx.clear();
}
// for pure home paths ( ~username ) the '.' at the end of rMatch // means that it points to root catalog // this is done only for file contents since home paths parsing is useful only for them if ( bPureHomePath && rMatch == "file:///." )
{ // a home that refers to /
// matching is always done case insensitive, but completion will be case sensitive and case preserving
aTitle = aTitle.toAsciiLowerCase();
if (
!nMatchLen ||
(bExectMatch && aMatchName == aTitle) ||
(!bExectMatch && aTitle.startsWith(aMatchName))
)
{ // all names fit if matchstring is empty
INetURLObject aObj( aURL );
sal_Unicode aDelimiter = '/'; if ( bSmart ) // when parsing is done "smart", the delimiter must be "guessed"
aObj.getFSysPath( static_cast<FSysStyle>(FSysStyle::Detect & ~FSysStyle::Vos), &aDelimiter );
if ( bIsFolder )
aObj.setFinalSlash();
// get the last name of the URL
OUString aMatch = aObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
OUString aInput( aText ); if ( nMatchLen )
{ if (aText.endsWith(".") || bPureHomePath)
{ // if a "special folder" URL was typed, don't touch the user input
aMatch = aMatch.copy( nMatchLen );
} else
{ // make the user input case preserving
DBG_ASSERT( aInput.getLength() >= nMatchLen, "Suspicious Matching!" );
aInput = aInput.copy( 0, aInput.getLength() - nMatchLen );
}
}
aInput += aMatch;
// folders should get a final slash automatically if ( bIsFolder )
aInput += OUStringChar(aDelimiter);
void SvtMatchContext_Impl::doExecute()
{
::osl::MutexGuard aGuard( theSvtMatchContextMutex() );
{ // have we been stopped while we were waiting for the mutex?
std::scoped_lock g(mutex_); if (stopped_) { return;
}
}
// Reset match lists
aCompletions.clear();
aURLs.clear();
// check for input if ( aText.isEmpty() ) return;
if( aText.indexOf( '*' ) != -1 || aText.indexOf( '?' ) != -1 ) // no autocompletion for wildcards return;
// if the user input is a valid URL, go on with it // otherwise it could be parsed smart with a predefined smart protocol // ( or if this is not set with the protocol of a predefined base URL ) if( eProt == INetProtocol::NotValid || eProt == eSmartProt || (eSmartProt == INetProtocol::NotValid && eProt == eBaseProt) )
{ // not stopped yet ? if( schedule() )
{ if ( eProt == INetProtocol::NotValid )
aMatch = SvtURLBox::ParseSmart( aText, pBox->aBaseURL ); else
aMatch = aText; if ( !aMatch.isEmpty() )
{
INetURLObject aURLObject( aMatch );
OUString aMainURL( aURLObject.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); // Disable autocompletion for anything but the (local) file // system (for which access is hopefully fast), as the logic of // how SvtMatchContext_Impl is used requires this code to run to // completion before further user input is processed, and even // SvtMatchContext_Impl::Stop does not guarantee a speedy // return: if ( !aMainURL.isEmpty()
&& aURLObject.GetProtocol() == INetProtocol::File )
{ // if text input is a directory, it must be part of the match list! Until then it is scanned bool folder = false; if (aURLObject.hasFinalSlash()) { try { const css::uno::Reference< css::uno::XComponentContext >&
ctx(comphelper::getProcessComponentContext());
css::uno::Reference<
css::ucb::XUniversalContentBroker > ucb(
css::ucb::UniversalContentBroker::create(
ctx));
css::uno::Sequence< css::beans::Property > prop{
{ /* Name */ u"IsFolder"_ustr, /* Handle */ -1, /* Type */ cppu::UnoType< bool >::get(), /* Attributes */ {} }
};
css::uno::Any res;
css::uno::Reference< css::ucb::XCommandProcessor >
proc(
ucb->queryContent(
ucb->createContentIdentifier(aMainURL)),
css::uno::UNO_QUERY_THROW);
css::uno::Reference< css::ucb::XCommandProcessor2 >
proc2(proc, css::uno::UNO_QUERY);
sal_Int32 id = proc->createCommandIdentifier(); try {
{
std::scoped_lock g(mutex_);
processor_ = proc;
commandId_ = id;
}
res = proc->execute(
css::ucb::Command(
u"getPropertyValues"_ustr, -1,
css::uno::Any(prop)),
id,
css::uno::Reference<
css::ucb::XCommandEnvironment >());
} catch (...) { if (proc2.is()) { try {
proc2->releaseCommandIdentifier(id);
} catch (css::uno::RuntimeException &) {
TOOLS_WARN_EXCEPTION("svtools.control", "ignoring");
}
} throw;
} if (proc2.is()) {
proc2->releaseCommandIdentifier(id);
}
{
std::scoped_lock g(mutex_);
processor_.clear(); // At least the neon-based WebDAV UCP does not // properly support aborting commands, so return // anyway now if an abort request had been // ignored and the command execution only // returned "successfully" after some timeout: if (stopped_) { return;
}
}
css::uno::Reference< css::sdbc::XRow > row(
res, css::uno::UNO_QUERY_THROW);
folder = row->getBoolean(1) && !row->wasNull();
} catch (css::uno::Exception &) {
TOOLS_WARN_EXCEPTION("svtools.control", "ignoring"); return;
}
} if (folder)
Insert( aText, aMatch ); else // otherwise the parent folder will be taken
aURLObject.removeSegment();
// scan directory and insert all matches
ReadFolder( aURLObject.GetMainURL( INetURLObject::DecodeMechanism::NONE ), aMatch, eProt == INetProtocol::NotValid );
}
}
}
}
if ( bOnlyDirectories ) // don't scan history picklist if only directories are allowed, picklist contains only files return;
// in case the whole path is just "~" then there should // be no trailing slash at the end if( aText.getLength() == 1 )
bTrailingSlash = false;
} else
{ // covers "~username" and "~username/..." cases
sal_Int32 nNameEnd = aText.indexOf( '/' );
OUString aUserName = aText.copy( 1, ( nNameEnd != -1 ) ? nNameEnd : ( aText.getLength() - 1 ) );
// if a base URL is set the string may be parsed relative if( aText.startsWith( "/" ) )
{ // text starting with slashes means absolute file URLs
OUString aTemp = INetURLObject::GetScheme( eBaseProt );
// file URL must be correctly encoded!
OUString aTextURL = INetURLObject::encode( aText, INetURLObject::PART_FPATH,
INetURLObject::EncodeMechanism::All );
aTemp += aTextURL;
// HRO: I suppose this hack should only be done for Windows !!!??? #ifdef _WIN32 // HRO: INetURLObject::smatRel2Abs does not recognize '\\' as a relative path // but in case of "\\\\" INetURLObject is right - this is an absolute path !
aSmart = aSmart.copy(1);
} #endif // base URL must be a directory !
aObj.setFinalSlash();
// take base URL and append current input bool bWasAbsolute = false; #ifdef UNX // encode file URL correctly
aSmart = INetURLObject::encode( aSmart, INetURLObject::PART_FPATH, INetURLObject::EncodeMechanism::All ); #endif
INetURLObject aTmp( aObj.smartRel2Abs( aSmart, bWasAbsolute ) );
if ( aText.endsWith(".") ) // INetURLObject appends a final slash for the directories "." and "..", this is a bug! // Remove it as a workaround
aTmp.removeFinalSlash(); if ( !aTmp.HasError() && aTmp.GetProtocol() != INetProtocol::NotValid )
aMatch = aTmp.GetMainURL( INetURLObject::DecodeMechanism::NONE );
}
} else
{
OUString aTmpMatch;
osl::FileBase::getFileURLFromSystemPath( aText, aTmpMatch );
aMatch = aTmpMatch;
}
IMPL_LINK_NOARG(SvtURLBox, ChangedHdl, weld::ComboBox&, void)
{
aChangeHdl.Call(*m_xWidget);
aChangedIdle.Start(); //launch this to happen on idle after cursor position will have been set
}
OUString SvtURLBox::GetURL()
{ // wait for end of autocompletion
::osl::MutexGuard aGuard( theSvtMatchContextMutex() );
OUString aText(m_xWidget->get_active_text()); if (MatchesPlaceHolder(aText)) return aPlaceHolder;
// try to get the right case preserving URL from the list of URLs for(std::vector<OUString>::iterator i = pImpl->aCompletions.begin(), j = pImpl->aURLs.begin(); i != pImpl->aCompletions.end() && j != pImpl->aURLs.end(); ++i, ++j)
{ if((*i) == aText) return *j;
}
#ifdef _WIN32 // erase trailing spaces on Windows since they are invalid on this OS and // most of the time they are inserted by accident via copy / paste
aText = comphelper::string::stripEnd(aText, ' '); if ( aText.isEmpty() ) return aText; // #i9739# #endif
if ( aObj.GetProtocol() == INetProtocol::NotValid )
{
OUString aName = ParseSmart( aText, aBaseURL );
aObj.SetURL(aName);
OUString aURL( aObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); if ( aURL.isEmpty() ) // aText itself is invalid, and even together with aBaseURL, it could not // made valid -> no chance return aText;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.