dbaccess/source/ui/dlg/sqlmessage.cxx |  276 ++++++++++++++++------------------
 include/vcl/qt/QtUtils.hxx            |   13 +
 vcl/qt5/QtBuilder.cxx                 |   20 --
 vcl/qt5/QtInstanceBuilder.cxx         |    1 
 4 files changed, 151 insertions(+), 159 deletions(-)

New commits:
commit 687007afca9a8ad261f1990de38736cec35868d0
Author:     Michael Weghorn <[email protected]>
AuthorDate: Fri Feb 20 14:18:02 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Sat Feb 21 02:32:53 2026 +0100

    dbaccess: Drop extra indentation level in sqlmessage.cxx
    
    Drop the extra indentation for the code in the first
    anonymous namespace at the top of the source file, to
    be consistent with the rest.
    
    clang-format the newly (un)indented code.
    
    Change-Id: I35b165698fce3151b4ec8f16cfab3c96b08ca9c4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199859
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/dbaccess/source/ui/dlg/sqlmessage.cxx 
b/dbaccess/source/ui/dlg/sqlmessage.cxx
index e49633b6a204..29bb20cd75bb 100644
--- a/dbaccess/source/ui/dlg/sqlmessage.cxx
+++ b/dbaccess/source/ui/dlg/sqlmessage.cxx
@@ -51,61 +51,54 @@ namespace dbaui
 
 namespace
 {
-    class ImageProvider
+class ImageProvider
+{
+private:
+    OUString m_defaultImageID;
+
+public:
+    explicit ImageProvider(OUString defaultImageID)
+        : m_defaultImageID(std::move(defaultImageID))
     {
-    private:
-        OUString m_defaultImageID;
+    }
 
-    public:
-        explicit ImageProvider(OUString defaultImageID)
-            : m_defaultImageID(std::move(defaultImageID))
-        {
-        }
+    const OUString& getImage() const { return m_defaultImageID; }
+};
 
-        const OUString& getImage() const
-        {
-            return m_defaultImageID;
-        }
-    };
+class LabelProvider
+{
+private:
+    OUString m_label;
 
-    class LabelProvider
+public:
+    explicit LabelProvider(TranslateId labelResourceID)
+        : m_label(DBA_RES(labelResourceID))
     {
-    private:
-        OUString  m_label;
-    public:
-        explicit LabelProvider(TranslateId labelResourceID)
-            : m_label(DBA_RES(labelResourceID))
-        {
-        }
+    }
 
-        const OUString& getLabel() const
-        {
-            return m_label;
-        }
-    };
+    const OUString& getLabel() const { return m_label; }
+};
+
+class ProviderFactory
+{
+private:
+    mutable std::shared_ptr<ImageProvider> m_pErrorImage;
+    mutable std::shared_ptr<ImageProvider> m_pWarningsImage;
+    mutable std::shared_ptr<ImageProvider> m_pInfoImage;
+    mutable std::shared_ptr<LabelProvider> m_pErrorLabel;
+    mutable std::shared_ptr<LabelProvider> m_pWarningsLabel;
+    mutable std::shared_ptr<LabelProvider> m_pInfoLabel;
 
-    class ProviderFactory
+public:
+    ProviderFactory() {}
+
+    std::shared_ptr<ImageProvider> const& 
getImageProvider(SQLExceptionInfo::TYPE _eType) const
     {
-    private:
-        mutable std::shared_ptr< ImageProvider >   m_pErrorImage;
-        mutable std::shared_ptr< ImageProvider >   m_pWarningsImage;
-        mutable std::shared_ptr< ImageProvider >   m_pInfoImage;
-        mutable std::shared_ptr< LabelProvider >   m_pErrorLabel;
-        mutable std::shared_ptr< LabelProvider >   m_pWarningsLabel;
-        mutable std::shared_ptr< LabelProvider >   m_pInfoLabel;
-
-    public:
-        ProviderFactory()
-        {
-        }
+        std::shared_ptr<ImageProvider>* ppProvider(&m_pErrorImage);
+        OUString sNormalImageID(u"dialog-error"_ustr);
 
-        std::shared_ptr< ImageProvider > const & getImageProvider( 
SQLExceptionInfo::TYPE _eType ) const
+        switch (_eType)
         {
-            std::shared_ptr< ImageProvider >* ppProvider( &m_pErrorImage );
-            OUString sNormalImageID(u"dialog-error"_ustr);
-
-            switch ( _eType )
-            {
             case SQLExceptionInfo::TYPE::SQLWarning:
                 ppProvider = &m_pWarningsImage;
                 sNormalImageID = "dialog-warning";
@@ -118,20 +111,21 @@ namespace
 
             default:
                 break;
-            }
-
-            if ( !ppProvider->get() )
-                (*ppProvider) = 
std::make_shared<ImageProvider>(sNormalImageID);
-            return *ppProvider;
         }
 
-        std::shared_ptr< LabelProvider > const & getLabelProvider( 
SQLExceptionInfo::TYPE _eType, bool _bSubLabel ) const
-        {
-            std::shared_ptr< LabelProvider >* ppProvider( &m_pErrorLabel );
-            TranslateId pLabelID( STR_EXCEPTION_ERROR );
+        if (!ppProvider->get())
+            (*ppProvider) = std::make_shared<ImageProvider>(sNormalImageID);
+        return *ppProvider;
+    }
 
-            switch ( _eType )
-            {
+    std::shared_ptr<LabelProvider> const& 
getLabelProvider(SQLExceptionInfo::TYPE _eType,
+                                                           bool _bSubLabel) 
const
+    {
+        std::shared_ptr<LabelProvider>* ppProvider(&m_pErrorLabel);
+        TranslateId pLabelID(STR_EXCEPTION_ERROR);
+
+        switch (_eType)
+        {
             case SQLExceptionInfo::TYPE::SQLWarning:
                 ppProvider = &m_pWarningsLabel;
                 pLabelID = STR_EXCEPTION_WARNING;
@@ -143,117 +137,121 @@ namespace
                 break;
             default:
                 break;
-            }
-
-            if ( !ppProvider->get() )
-                (*ppProvider) = std::make_shared<LabelProvider>( pLabelID );
-            return *ppProvider;
         }
 
-    };
-
-    /// a stripped version of the SQLException, packed for displaying
-    struct ExceptionDisplayInfo
-    {
-        SQLExceptionInfo::TYPE                  eType;
+        if (!ppProvider->get())
+            (*ppProvider) = std::make_shared<LabelProvider>(pLabelID);
+        return *ppProvider;
+    }
+};
 
-        std::shared_ptr< ImageProvider >        pImageProvider;
-        std::shared_ptr< LabelProvider >        pLabelProvider;
+/// a stripped version of the SQLException, packed for displaying
+struct ExceptionDisplayInfo
+{
+    SQLExceptionInfo::TYPE eType;
 
-        bool                                    bSubEntry;
+    std::shared_ptr<ImageProvider> pImageProvider;
+    std::shared_ptr<LabelProvider> pLabelProvider;
 
-        OUString                                sMessage;
-        OUString                                sSQLState;
-        OUString                                sErrorCode;
+    bool bSubEntry;
 
-        ExceptionDisplayInfo() : eType( SQLExceptionInfo::TYPE::Undefined ), 
bSubEntry( false ) { }
-        explicit ExceptionDisplayInfo( SQLExceptionInfo::TYPE _eType ) : 
eType( _eType ), bSubEntry( false ) { }
-    };
+    OUString sMessage;
+    OUString sSQLState;
+    OUString sErrorCode;
 
-    bool lcl_hasDetails( const ExceptionDisplayInfo& _displayInfo )
+    ExceptionDisplayInfo()
+        : eType(SQLExceptionInfo::TYPE::Undefined)
+        , bSubEntry(false)
     {
-        return  ( !_displayInfo.sErrorCode.isEmpty() )
-                ||  (   !_displayInfo.sSQLState.isEmpty()
-                    &&  _displayInfo.sSQLState != "S1000"
-                    );
     }
+    explicit ExceptionDisplayInfo(SQLExceptionInfo::TYPE _eType)
+        : eType(_eType)
+        , bSubEntry(false)
+    {
+    }
+};
 
-    typedef std::vector< ExceptionDisplayInfo >   ExceptionDisplayChain;
+bool lcl_hasDetails(const ExceptionDisplayInfo& _displayInfo)
+{
+    return (!_displayInfo.sErrorCode.isEmpty())
+           || (!_displayInfo.sSQLState.isEmpty() && _displayInfo.sSQLState != 
"S1000");
+}
 
-    /// strips the [OOoBase] vendor identifier from the given error message, 
if applicable
-    OUString lcl_stripOOoBaseVendor( const OUString& _rErrorMessage )
-    {
-        OUString sErrorMessage( _rErrorMessage );
+typedef std::vector<ExceptionDisplayInfo> ExceptionDisplayChain;
 
-        const OUString sVendorIdentifier( 
::connectivity::SQLError::getMessagePrefix() );
-        if ( sErrorMessage.startsWith( sVendorIdentifier ) )
-        {
-            // characters to strip
-            sal_Int32 nStripLen( sVendorIdentifier.getLength() );
-            // usually, there should be a whitespace between the vendor and 
the real message
-            while   (   ( sErrorMessage.getLength() > nStripLen )
-                    &&  ( sErrorMessage[nStripLen] == ' ' )
-                    )
-                    ++nStripLen;
-            sErrorMessage = sErrorMessage.copy( nStripLen );
-        }
+/// strips the [OOoBase] vendor identifier from the given error message, if 
applicable
+OUString lcl_stripOOoBaseVendor(const OUString& _rErrorMessage)
+{
+    OUString sErrorMessage(_rErrorMessage);
 
-        return sErrorMessage;
+    const OUString 
sVendorIdentifier(::connectivity::SQLError::getMessagePrefix());
+    if (sErrorMessage.startsWith(sVendorIdentifier))
+    {
+        // characters to strip
+        sal_Int32 nStripLen(sVendorIdentifier.getLength());
+        // usually, there should be a whitespace between the vendor and the 
real message
+        while ((sErrorMessage.getLength() > nStripLen) && 
(sErrorMessage[nStripLen] == ' '))
+            ++nStripLen;
+        sErrorMessage = sErrorMessage.copy(nStripLen);
     }
 
-    void lcl_buildExceptionChain( const SQLExceptionInfo& _rErrorInfo, const 
ProviderFactory& _rFactory, ExceptionDisplayChain& _out_rChain )
-    {
-        ExceptionDisplayChain().swap(_out_rChain);
+    return sErrorMessage;
+}
 
-        SQLExceptionIteratorHelper iter( _rErrorInfo );
-        while ( iter.hasMoreElements() )
-        {
-            // current chain element
-            SQLExceptionInfo aCurrentElement;
-            iter.next( aCurrentElement );
+void lcl_buildExceptionChain(const SQLExceptionInfo& _rErrorInfo, const 
ProviderFactory& _rFactory,
+                             ExceptionDisplayChain& _out_rChain)
+{
+    ExceptionDisplayChain().swap(_out_rChain);
 
-            const SQLException* pCurrentError = aCurrentElement;
-            assert(pCurrentError && "lcl_buildExceptionChain: iterator 
failure!");
-                // hasMoreElements should not have returned <TRUE/> in this 
case
+    SQLExceptionIteratorHelper iter(_rErrorInfo);
+    while (iter.hasMoreElements())
+    {
+        // current chain element
+        SQLExceptionInfo aCurrentElement;
+        iter.next(aCurrentElement);
 
-            ExceptionDisplayInfo aDisplayInfo( aCurrentElement.getType() );
+        const SQLException* pCurrentError = aCurrentElement;
+        assert(pCurrentError && "lcl_buildExceptionChain: iterator failure!");
+        // hasMoreElements should not have returned <TRUE/> in this case
 
-            aDisplayInfo.sMessage = pCurrentError->Message.trim();
-            aDisplayInfo.sSQLState = pCurrentError->SQLState;
-            if ( pCurrentError->ErrorCode )
-                aDisplayInfo.sErrorCode = OUString::number( 
pCurrentError->ErrorCode );
+        ExceptionDisplayInfo aDisplayInfo(aCurrentElement.getType());
 
-            if  (   aDisplayInfo.sMessage.isEmpty()
-                &&  !lcl_hasDetails( aDisplayInfo )
-                )
-            {
-                OSL_FAIL( "lcl_buildExceptionChain: useless exception: no 
state, no error code, no message!" );
-                continue;
-            }
+        aDisplayInfo.sMessage = pCurrentError->Message.trim();
+        aDisplayInfo.sSQLState = pCurrentError->SQLState;
+        if (pCurrentError->ErrorCode)
+            aDisplayInfo.sErrorCode = 
OUString::number(pCurrentError->ErrorCode);
+
+        if (aDisplayInfo.sMessage.isEmpty() && !lcl_hasDetails(aDisplayInfo))
+        {
+            OSL_FAIL(
+                "lcl_buildExceptionChain: useless exception: no state, no 
error code, no message!");
+            continue;
+        }
 
-            aDisplayInfo.pImageProvider = _rFactory.getImageProvider( 
aCurrentElement.getType() );
-            aDisplayInfo.pLabelProvider = _rFactory.getLabelProvider( 
aCurrentElement.getType(), false );
+        aDisplayInfo.pImageProvider = 
_rFactory.getImageProvider(aCurrentElement.getType());
+        aDisplayInfo.pLabelProvider = 
_rFactory.getLabelProvider(aCurrentElement.getType(), false);
 
-            _out_rChain.push_back(std::move(aDisplayInfo));
+        _out_rChain.push_back(std::move(aDisplayInfo));
 
-            if ( aCurrentElement.getType() == 
SQLExceptionInfo::TYPE::SQLContext )
+        if (aCurrentElement.getType() == SQLExceptionInfo::TYPE::SQLContext)
+        {
+            const SQLContext* pContext = aCurrentElement;
+            if (!pContext->Details.isEmpty())
             {
-                const SQLContext* pContext = aCurrentElement;
-                if ( !pContext->Details.isEmpty() )
-                {
-                    ExceptionDisplayInfo aSubInfo( aCurrentElement.getType() );
-
-                    aSubInfo.sMessage = pContext->Details;
-                    aSubInfo.pImageProvider = _rFactory.getImageProvider( 
aCurrentElement.getType() );
-                    aSubInfo.pLabelProvider = _rFactory.getLabelProvider( 
aCurrentElement.getType(), true );
-                    aSubInfo.bSubEntry = true;
-
-                    _out_rChain.push_back(std::move(aSubInfo));
-                }
+                ExceptionDisplayInfo aSubInfo(aCurrentElement.getType());
+
+                aSubInfo.sMessage = pContext->Details;
+                aSubInfo.pImageProvider = 
_rFactory.getImageProvider(aCurrentElement.getType());
+                aSubInfo.pLabelProvider
+                    = _rFactory.getLabelProvider(aCurrentElement.getType(), 
true);
+                aSubInfo.bSubEntry = true;
+
+                _out_rChain.push_back(std::move(aSubInfo));
             }
         }
     }
 }
+}
 
 namespace {
 
commit 5f83cc9a31a0fe2c972f89d6708012126214f590
Author:     Michael Weghorn <[email protected]>
AuthorDate: Fri Feb 20 13:53:38 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Sat Feb 21 02:32:46 2026 +0100

    tdf#130857 qt weld: Support SQL Exception dialog
    
    This means that native Qt widgets are used for that dialog
    now when using the qt5 or qt6 VCL plugin and starting LO with
    environment variable SAL_VCL_QT_USE_WELDED_WIDGETS=1 set.
    
    The dialog can be triggered like this:
    
    * start Writer
    * enable "View" -> "Toolbars" -> "Mail Merge"
    * press the "Address Book Source" toolbar button
    * press the "Assign" button in the dialog
    * in the "Address Book Data Source Wizard" dialog that shows up,
      select "Thunderbird" and press "Next" button
    * in the dialog showing an error message that shows up,
      press the "More" button
    
    Change-Id: Iee094a83b739abefe4f36c117289fe3c81c77b0f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199858
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/vcl/qt5/QtInstanceBuilder.cxx b/vcl/qt5/QtInstanceBuilder.cxx
index aa7932d9a78f..9582a3e23b72 100644
--- a/vcl/qt5/QtInstanceBuilder.cxx
+++ b/vcl/qt5/QtInstanceBuilder.cxx
@@ -124,6 +124,7 @@ constexpr auto SUPPORTED_UI_FILES = 
frozen::make_unordered_set<std::u16string_vi
     u"dbaccess/ui/fielddialog.ui",
     u"dbaccess/ui/queryfilterdialog.ui",
     u"dbaccess/ui/savedialog.ui",
+    u"dbaccess/ui/sqlexception.ui",
     u"dbaccess/ui/tabledesignsavemodifieddialog.ui",
     u"desktop/ui/installforalldialog.ui",
     u"desktop/ui/showlicensedialog.ui",
commit 59fee5976e846b2287a5ff0c07bdcd65a9bd2ea8
Author:     Michael Weghorn <[email protected]>
AuthorDate: Fri Feb 20 13:49:26 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Sat Feb 21 02:32:40 2026 +0100

    tdf#130857 qt weld: Move logic to load LO or stock icon to loadQPixmapIcon
    
    The "GtkImage" case in QtBuilder::makeObject has logic to either
    load a LO icon or use a system/stock icon from a Qt icon theme.
    
    Don't implement the logic there, but in the loadQPixmapIcon
    helper instead, and use that one in two more places.
    
    This also prepares for an upcoming commit to support
    the SQL error dialog where "dialog-error" etc. are
    used for icon names (see dbaccess/source/ui/dlg/sqlmessage.cxx)
    and it's expected that stock icons are used for those.
    (For the vcl/SalInstance* case, those are handled
    specially in createImage in vcl/source/app/salvtables.cxx .)
    
    Without this commit, upcoming
    
        Change-Id: Iee094a83b739abefe4f36c117289fe3c81c77b0f
        Author: Michael Weghorn <[email protected]>
        Date:   Fri Feb 20 13:53:38 2026 +0100
    
            tdf#130857 qt weld: Support SQL Exception dialog
    
    would trigger this assert:
    
        soffice.bin: .../include/vcl/qt/QtUtils.hxx:50: QPixmap toQPixmap(const 
Bitmap &): Assertion `!aPixmap.isNull() && "Failed to create icon pixmap"' 
failed.
    
    Change-Id: I086b368493267455187e0c3cff3c79520f5a7b50
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199857
    Reviewed-by: Michael Weghorn <[email protected]>
    Tested-by: Jenkins

diff --git a/include/vcl/qt/QtUtils.hxx b/include/vcl/qt/QtUtils.hxx
index 1a48601cab3d..feee3b3d747f 100644
--- a/include/vcl/qt/QtUtils.hxx
+++ b/include/vcl/qt/QtUtils.hxx
@@ -26,7 +26,10 @@
 #include <vcl/outdev.hxx>
 
 #include <QtCore/QString>
+#include <QtGui/QIcon>
 #include <QtGui/QPixmap>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QStyle>
 
 inline QString toQString(const OUString& rStr)
 {
@@ -69,8 +72,14 @@ inline QPixmap toQPixmap(const OutputDevice& rDevice)
 
 inline QPixmap loadQPixmapIcon(const OUString& rIconName)
 {
-    Bitmap aIcon(rIconName);
-    return toQPixmap(aIcon);
+    const Bitmap aBitmap(rIconName);
+    if (!aBitmap.IsEmpty())
+        return toQPixmap(aBitmap);
+
+    const QIcon aIcon = QIcon::fromTheme(toQString(rIconName));
+    assert(!aIcon.isNull() && "No icon found for that icon name");
+    const int nIconSize = 
QApplication::style()->pixelMetric(QStyle::PM_ButtonIconSize);
+    return aIcon.pixmap(nIconSize);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qt5/QtBuilder.cxx b/vcl/qt5/QtBuilder.cxx
index c038a986bdbd..064d86bfb41c 100644
--- a/vcl/qt5/QtBuilder.cxx
+++ b/vcl/qt5/QtBuilder.cxx
@@ -279,20 +279,7 @@ QObject* QtBuilder::makeObject(QObject* pParent, 
std::u16string_view sName, std:
         QLabel* pLabel = new QLabel(pParentWidget);
         const OUString sIconName = extractIconName(rMap);
         if (!sIconName.isEmpty())
-        {
-            const Image aImage = loadThemeImage(sIconName);
-            if (!aImage.GetBitmap().IsEmpty())
-            {
-                pLabel->setPixmap(toQPixmap(aImage));
-            }
-            else
-            {
-                const QIcon aIcon = QIcon::fromTheme(toQString(sIconName));
-                assert(!aIcon.isNull() && "No icon found for that icon name");
-                const int nIconSize = 
QApplication::style()->pixelMetric(QStyle::PM_ButtonIconSize);
-                pLabel->setPixmap(aIcon.pixmap(nIconSize));
-            }
-        }
+            pLabel->setPixmap(loadQPixmapIcon(sIconName));
         pObject = pLabel;
     }
     else if (sName == u"GtkLabel")
@@ -412,10 +399,7 @@ QObject* QtBuilder::makeObject(QObject* pParent, 
std::u16string_view sName, std:
         QToolButton* pToolButton = new QToolButton(pParentWidget);
         const OUString sIconName = extractIconName(rMap);
         if (!sIconName.isEmpty())
-        {
-            const Image aImage = loadThemeImage(sIconName);
-            pToolButton->setIcon(toQPixmap(aImage));
-        }
+            pToolButton->setIcon(loadQPixmapIcon(sIconName));
         pToolButton->setText(toQString(extractLabel(rMap)));
         pToolButton->setCheckable(sName == u"GtkRadioToolButton"
                                   || sName == u"GtkToggleToolButton");

Reply via email to