/* -*- 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 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { class Default: public cppu::WeakImplHelper< css::lang::XServiceInfo, css::beans::XPropertySet > { public: Default() {} Default(const Default&) = delete; Default& operator=(const Default&) = delete; private: virtual ~Default() override {} virtual OUString SAL_CALL getImplementationName() override { return "com.sun.star.comp.configuration.backend.DesktopBackend"; } virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override { return ServiceName == getSupportedServiceNames()[0]; } virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override { return { "com.sun.star.configuration.backend.DesktopBackend" }; } virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override { return css::uno::Reference< css::beans::XPropertySetInfo >(); } virtual void SAL_CALL setPropertyValue( OUString const &, css::uno::Any const &) override; virtual css::uno::Any SAL_CALL getPropertyValue( OUString const & PropertyName) override; virtual void SAL_CALL addPropertyChangeListener( OUString const &, css::uno::Reference< css::beans::XPropertyChangeListener > const &) override {} virtual void SAL_CALL removePropertyChangeListener( OUString const &, css::uno::Reference< css::beans::XPropertyChangeListener > const &) override {} virtual void SAL_CALL addVetoableChangeListener( OUString const &, css::uno::Reference< css::beans::XVetoableChangeListener > const &) override {} virtual void SAL_CALL removeVetoableChangeListener( OUString const &, css::uno::Reference< css::beans::XVetoableChangeListener > const &) override {} }; void Default::setPropertyValue(OUString const &, css::uno::Any const &) { throw css::lang::IllegalArgumentException( "setPropertyValue not supported", getXWeak(), -1); } OUString xdg_user_dir_lookup (const char *type, bool bAllowHomeDir) { size_t nLenType = strlen(type); char *config_home; char *p; bool bError = false; osl::Security aSecurity; oslFileHandle handle; OUString aHomeDirURL; OUString aDocumentsDirURL; OUString aConfigFileURL; OUStringBuffer aUserDirBuf; if (!aSecurity.getHomeDir( aHomeDirURL ) ) { osl::FileBase::getFileURLFromSystemPath("/tmp", aDocumentsDirURL); return aDocumentsDirURL; } config_home = getenv ("XDG_CONFIG_HOME"); if (config_home == nullptr || config_home[0] == 0) { aConfigFileURL = aHomeDirURL + "/.config/user-dirs.dirs"; } else { aConfigFileURL = OUString::createFromAscii(config_home) + "/user-dirs.dirs"; } if(osl_File_E_None == osl_openFile(aConfigFileURL.pData, &handle, osl_File_OpenFlag_Read)) { rtl::ByteSequence seq; while (osl_File_E_None == osl_readLine(handle , reinterpret_cast(&seq))) { int relative = 0; int len = seq.getLength(); seq.realloc(len + 1); seq[len] = 0; p = reinterpret_cast(seq.getArray()); while (*p == ' ' || *p == '\t') p++; if (strncmp (p, "XDG_", 4) != 0) continue; p += 4; if (strncmp (p, OString(type, nLenType).toAsciiUpperCase().getStr(), nLenType) != 0) continue; p += nLenType; if (strncmp (p, "_DIR", 4) != 0) continue; p += 4; while (*p == ' ' || *p == '\t') p++; if (*p != '=') continue; p++; while (*p == ' ' || *p == '\t') p++; if (*p != '"') continue; p++; if (strncmp (p, "$HOME/", 6) == 0) { p += 6; relative = 1; } else if (*p != '/') continue; if (relative) { aUserDirBuf = aHomeDirURL + "/"; } else { aUserDirBuf.truncate(); } while (*p && *p != '"') { if ((*p == '\\') && (*(p+1) != 0)) p++; aUserDirBuf.append(static_cast(*p++)); } }//end of while osl_closeFile(handle); } else bError = true; if (aUserDirBuf.getLength()>0 && !bError) { aDocumentsDirURL = aUserDirBuf.makeStringAndClear(); if ( bAllowHomeDir || (aDocumentsDirURL != aHomeDirURL && aDocumentsDirURL != Concat2View(aHomeDirURL + "/")) ) { osl::Directory aDocumentsDir( aDocumentsDirURL ); if( osl::FileBase::E_None == aDocumentsDir.open() ) return aDocumentsDirURL; } } /* Use fallbacks historical compatibility if nothing else exists */ return aHomeDirURL + "/" + OUString::createFromAscii(type); } css::uno::Any xdgDirectoryIfExists(char const * type, bool bAllowHomeDir) { auto url = xdg_user_dir_lookup(type, bAllowHomeDir); return css::uno::Any( osl::Directory(url).open() == osl::FileBase::E_None ? css::beans::Optional(true, css::uno::Any(url)) : css::beans::Optional(false, css::uno::Any())); } css::uno::Any Default::getPropertyValue(OUString const & PropertyName) { if (PropertyName == "TemplatePathVariable") { // Never pick up the HOME directory as the default location of user's templates return xdgDirectoryIfExists("Templates", false); } if (PropertyName == "WorkPathVariable") { return xdgDirectoryIfExists("Documents", true); } if ( PropertyName == "EnableATToolSupport" || PropertyName == "ExternalMailer" || PropertyName == "SourceViewFontHeight" || PropertyName == "SourceViewFontName" || PropertyName == "ooInetFTPProxyName" || PropertyName == "ooInetFTPProxyPort" || PropertyName == "ooInetHTTPProxyName" || PropertyName == "ooInetHTTPProxyPort" || PropertyName == "ooInetHTTPSProxyName" || PropertyName == "ooInetHTTPSProxyPort" || PropertyName == "ooInetNoProxy" || PropertyName == "ooInetProxyType" || PropertyName == "givenname" || PropertyName == "sn" ) { return css::uno::Any(css::beans::Optional< css::uno::Any >()); } throw css::beans::UnknownPropertyException( PropertyName, getXWeak()); } css::uno::Reference< css::uno::XInterface > createBackend( css::uno::Reference< css::uno::XComponentContext > const & context, OUString const & name) { try { return css::uno::Reference< css::lang::XMultiComponentFactory >( context->getServiceManager(), css::uno::UNO_SET_THROW)-> createInstanceWithContext(name, context); } catch (css::uno::RuntimeException &) { // Assuming these exceptions are real errors: throw; } catch (const css::uno::Exception &) { // Assuming these exceptions indicate that the service is not installed: TOOLS_WARN_EXCEPTION("shell", "createInstance(" << name << ") failed"); return css::uno::Reference< css::uno::XInterface >(); } } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* shell_DesktopBackend_get_implementation( css::uno::XComponentContext* context , css::uno::Sequence const&) { OUString desktop; css::uno::Reference< css::uno::XCurrentContext > current( css::uno::getCurrentContext()); if (current.is()) { current->getValueByName("system.desktop-environment") >>= desktop; } // Fall back to the default if the specific backend is not available: css::uno::Reference< css::uno::XInterface > backend; if (desktop == "PLASMA5") backend = createBackend(context, "com.sun.star.configuration.backend.KF5Backend"); if (!backend) backend = getXWeak(new Default); backend->acquire(); return backend.get(); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ assert_fail_base assert.c 94 0x7f0838632418 6 __assert_fail assert.c 103 0x7f0838642592 7 ImplDbgTestSolarMutex dbggui.cxx 35 0x7f082fa2dd3e 8 DbgTestSolarMutex debug.cxx 54 0x7f0837b2bec0 9 vcl::WindowOutputDevice::AcquireGraphics window.cxx 822 0x7f082f306276 10 OutputDevice::IsNativeControlSupported nativecontrols.cxx 139 0x7f082f584492 11 vcl::Window::IsNativeControlSupported window3.cxx 77 0x7f082f2fd8b9 12 Dialog::ImplInitSettings dialog.cxx 524 0x7f082f167189 13 Dialog::ImplInitDialog dialog.cxx 495 0x7f082f167086 14 Dialog::Dialog dialog.cxx 586 0x7f082f167d92 15 MessageDialog::MessageDialog layout.cxx 2521 0x7f082f1df4a6 16 VclPtr<MessageDialog>::Create<vcl::Window *&, long&> vclptr.hxx 129 0x7f082f0e8fa6 17 VclBuilder::makeObject builder.cxx 1605 0x7f082f0c5326 18 VclBuilder::insertObject builder.cxx 2454 0x7f082f0d09eb 19 WidgetBuilder<vcl::Window, VclPtr<vcl::Window>>::handleObject widgetbuilder.hxx 213 0x7f082f145937 20 WidgetBuilder<vcl::Window, VclPtr<vcl::Window>>::handleChild widgetbuilder.hxx 107 0x7f082f0f13ce 21 WidgetBuilder<vcl::Window, VclPtr<vcl::Window>>::processUIFile widgetbuilder.hxx 49 0x7f082f0e1b78 22 VclBuilder::VclBuilder builder.cxx 520 0x7f082f0ba596 23 SalInstanceBuilder::SalInstanceBuilder salvtables.cxx 7088 0x7f082fa7b318 24 std::make_unique<SalInstanceBuilder, vcl::Window *&, rtl::OUString const&, rtl::OUString const&> unique_ptr.h 1077 0x7f082fa99ef9 25 SalInstance::CreateBuilder salvtables.cxx 7470 0x7f082fa7f468 26 QtInstance::CreateBuilder QtInstance.cxx 843 0x7f08254e89e5 27 non-virtual thunk to QtInstance::CreateBuilder(weld::Widget *, rtl::OUString const&, rtl::OUString const&) 0x7f08254e8a4c 28 Application::CreateBuilder builder.cxx 198 0x7f082f0b7f02 29 weld::MessageDialogController::MessageDialogController weldutils.cxx 65 0x7f082fb52635 30 (anonymous namespace)::HelpManualMessage::HelpManualMessage sfxhelp.cxx 958 0x7f0834939fb0 31 SfxHelp::Start_Impl sfxhelp.cxx 1283 0x7f08349369ec 32 SfxHelp::Start sfxhelp.cxx 642 0x7f08349389fe 33 TipOfTheDayDialog::OnLinkClick tipofthedaydlg.cxx 261 0x7f07b37ebb64 34 TipOfTheDayDialog::LinkStubOnLinkClick tipofthedaydlg.cxx 251 0x7f07b37eb99d 35 Link<weld::LinkButton&, bool>::Call link.hxx 111 0x7f082552dc26 36 weld::LinkButton::signal_activate_link weld.hxx 1688 0x7f082552d95c 37 QtInstanceLinkButton::linkActivated QtInstanceLinkButton.cxx 58 0x7f082552ba6d 38 QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, QtPrivate::List<QString const&>, void, void (QtInstanceLinkButton:: *)(QString const&)>::call(void (QtInstanceLinkButton:: *)(QString const&), QtInstanceLinkButton *, void * *)::{lambda()#1}::operator()() const qobjectdefs_impl.h 127 0x7f082552e074 39 QtPrivate::FunctorCallBase::call_internal<void, QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, QtPrivate::List<QString const&>, void, void (QtInstanceLinkButton:: *)(QString const&)>::call(void (QtInstanceLinkButton:: *)(QString const&), QtInstanceLinkButton *, void * *)::{lambda()#1}>(void * *, QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, QtPrivate::List<QString const&>, void, void (QtInstanceLinkButton:: *)(QString const&)>::call(void (QtInstanceLinkButton:: *)(QString const&), QtInstanceLinkButton *, void * *)::{lambda()#1}&&) qobjectdefs_impl.h 65 0x7f082552df99 40 QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, QtPrivate::List<QString const&>, void, void (QtInstanceLinkButton:: *)(QString const&)>::call qobjectdefs_impl.h 126 0x7f082552ded3 41 QtPrivate::FunctionPointer<void (QtInstanceLinkButton:: *)(QString const&)>::call<QtPrivate::List<QString const&>, void> qobjectdefs_impl.h 174 0x7f082552de4d 42 QtPrivate::QCallableObject<void (QtInstanceLinkButton:: *)(QString const&), QtPrivate::List<QString const&>, void>::impl qobjectdefs_impl.h 545 0x7f082552dd76 43 QtPrivate::QSlotObjectBase::call qobjectdefs_impl.h 461 0x7f082465ab72 44 doActivate<false> qobject.cpp 4127 0x7f0824718ee4 45 QMetaObject::activate qobject.cpp 4187 0x7f082470eb83 46 QLabel::linkActivated moc_qlabel.cpp 386 0x7f08228ddb72 47 QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, QtPrivate::List<QString const&>, void, void (QLabel:: *)(QString const&)>::call(void (QLabel:: *)(QString const&), QLabel *, void * *)::{lambda()#1}::operator()() const qobjectdefs_impl.h 127 0x7f08228e29a8 48 QtPrivate::FunctorCallBase::call_internal<void, QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, QtPrivate::List<QString const&>, void, void (QLabel:: *)(QString const&)>::call(void (QLabel:: *)(QString const&), QLabel *, void * *)::{lambda()#1}>(void * *, QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, QtPrivate::List<QString const&>, void, void (QLabel:: *)(QString const&)>::call(void (QLabel:: *)(QString const&), QLabel *, void * *)::{lambda()#1}&&) qobjectdefs_impl.h 65 0x7f08228e291d 49 QtPrivate::FunctorCall<std::integer_sequence<unsigned long, 0ul>, QtPrivate::List<QString const&>, void, void (QLabel:: *)(QString const&)>::call qobjectdefs_impl.h 126 0x7f08228e28d7 50 QtPrivate::FunctionPointer<void (QLabel:: *)(QString const&)>::call<QtPrivate::List<QString const&>, void> qobjectdefs_impl.h 174 0x7f08228e2841 51 QtPrivate::QCallableObject<void (QLabel:: *)(QString const&), QtPrivate::List<QString const&>, void>::impl qobjectdefs_impl.h 545 0x7f08228e276b 52 QtPrivate::QSlotObjectBase::call qobjectdefs_impl.h 461 0x7f082465ab72 53 doActivate<false> qobject.cpp 4127 0x7f0824718ee4 54 QMetaObject::activate qobject.cpp 4187 0x7f082470eb83 55 QWidgetTextControl::linkActivated moc_qwidgettextcontrol_p.cpp 806 0x7f0822a5a415 56 QWidgetTextControlPrivate::activateLinkUnderCursor qwidgettextcontrol.cpp 2962 0x7f0822a544c1 57 QWidgetTextControlPrivate::keyPressEvent qwidgettextcontrol.cpp 1242 0x7f0822a50454 58 QWidgetTextControl::processEvent qwidgettextcontrol.cpp 1024 0x7f0822a4f23b 59 QWidgetTextControl::processEvent qwidgettextcontrol.cpp 984 0x7f0822a4f0c1 60 QLabelPrivate::sendControlEvent qlabel.cpp 1557 0x7f08228db3c4 61 QLabel::keyPressEvent qlabel.cpp 912 0x7f08228db7fe [...] Change-Id: I20f11ff2e7c00e65098bd7fb39afefdc4a622138 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176175 Reviewed-by: Michael Weghorn <m.weghorn@posteo.de> Tested-by: Jenkins tdf#130857 qt weld: Make link buttons focusable + handle activation 2024-10-26T11:20:29+00:00 Michael Weghorn m.weghorn@posteo.de 2024-10-25T21:36:49+00:00 ec59d5aec570887758236d8955e620d7bbb34d33 Set the text interaction flags [1] for the QLabel used for hyperlinks so that the links can be highlighted and activated using mouse and keyboard. Connect to the QLabel::linkActivated signal that gets emitted when a link gets activated, and call signal_activate_link in response. If that returns false, open the URL using QDesktopServices::openUrl instead. Another way to only support opening the URL using QDesktopServices::openUrl automatically would be to set the `openExternalLinks` property [2], but IIUC, the custom activation handler should have priority. With this in place, when opening the "Help" -> "About LibreOfficeDev" dialog in a WIP branch adding "cui/ui/aboutdialog.ui" to the list of .ui files in QtInstanceBuilder::IsUIFileSupported, the tab order now includes the hyperlinks in the dialog, and pressing Enter while one is focused, or clicking on one of them opens them in the browser when using the qt6 VCL plugin. [1] https://doc.qt.io/qt-6/qlabel.html#textInteractionFlags-prop [2] https://doc.qt.io/qt-6/qlabel.html#openExternalLinks-prop Change-Id: I4e3cbca6d01a652a1038b9750ee9049e1c7491be Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175670 Reviewed-by: Michael Weghorn <m.weghorn@posteo.de> Tested-by: Jenkins
Set the text interaction flags [1] for the QLabel used for
hyperlinks so that the links can be highlighted and activated
using mouse and keyboard.

Connect to the QLabel::linkActivated signal that gets emitted
when a link gets activated, and call signal_activate_link
in response. If that returns false, open the URL using
QDesktopServices::openUrl instead.

Another way to only support opening the URL using
QDesktopServices::openUrl automatically would be
to set the `openExternalLinks` property [2], but
IIUC, the custom activation handler should have
priority.

With this in place, when opening the "Help" -> "About LibreOfficeDev"
dialog in a WIP branch adding "cui/ui/aboutdialog.ui" to the list
of .ui files in QtInstanceBuilder::IsUIFileSupported, the tab
order now includes the hyperlinks in the dialog, and pressing
Enter while one is focused, or clicking on one of them opens them
in the browser when using the qt6 VCL plugin.

[1] https://doc.qt.io/qt-6/qlabel.html#textInteractionFlags-prop
[2] https://doc.qt.io/qt-6/qlabel.html#openExternalLinks-prop

Change-Id: I4e3cbca6d01a652a1038b9750ee9049e1c7491be
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175670
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins
tdf#130857 qt weld: Add a QtInstanceLinkButton 2024-10-26T11:11:19+00:00 Michael Weghorn m.weghorn@posteo.de 2024-10-25T18:41:48+00:00 0846977a2280824006fb1620706cc785802336e3 Add a new QtInstanceLinkButton class that is the weld::LinkButton implementing using a native Qt widget. QLabel can be used to display a hyperlink, as it supports the HTML syntax for the text, so using , QLabel myLabel; myLabel.setText(QLatin1String("<a href=\"https://www.libreoffice.org">LibreOffice Website</a>")); can be used to let the QLabel handle a hyperlink. To make it simple to set this as needed for a QLabel, implement a new QLabel subclass called QtHyperlinkLabel that provides convenient getters and setters to set the displayed text and the link target, and takes care of setting the QLabel text based on that as needed. Implement QtInstanceLinkButton using an instance of that class as the widget and create an instance of that class in QtBuilder when encountering a "GtkLinkButton" object while processing a .ui file and evaluate the "label" and "uri" properties. Change-Id: I71d28b6e5e3cbd110ec5b3d1232d55e9d2bb8a1b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175656 Reviewed-by: Michael Weghorn <m.weghorn@posteo.de> Tested-by: Jenkins
Add a new QtInstanceLinkButton class that is
the weld::LinkButton implementing using a native
Qt widget.

QLabel can be used to display a hyperlink, as it
supports the HTML syntax for the text, so using ,

    QLabel myLabel;
    myLabel.setText(QLatin1String("<a href=\"https://www.libreoffice.org">LibreOffice Website</a>"));

can be used to let the QLabel handle a hyperlink.

To make it simple to set this as needed for a QLabel,
implement a new QLabel subclass called QtHyperlinkLabel
that provides convenient getters and setters to set
the displayed text and the link target, and takes
care of setting the QLabel text based on that as needed.

Implement QtInstanceLinkButton using an instance
of that class as the widget and create an instance of
that class in QtBuilder when encountering a "GtkLinkButton"
object while processing a .ui file and evaluate
the "label" and "uri" properties.

Change-Id: I71d28b6e5e3cbd110ec5b3d1232d55e9d2bb8a1b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175656
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Tested-by: Jenkins