libreoffice/include/vcl/builderbase.hxx

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

172 lines
5.8 KiB
C++
Raw Normal View History

/* -*- 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/.
*/
#pragma once
#include <config_options.h>
#include <vcl/dllapi.h>
#include <vcl/image.hxx>
#include <vcl/EnumContext.hxx>
#include <com/sun/star/uno/Exception.hpp>
#include <map>
#include <vector>
namespace xmlreader
{
class XmlReader;
}
struct ComboBoxTextItem
{
OUString m_sItem;
OUString m_sId;
ComboBoxTextItem(OUString sItem, OUString sId)
: m_sItem(std::move(sItem))
, m_sId(std::move(sId))
{
}
};
tdf#130857 qt weld: Implement QtBuilder + use it for first msg dialog This implements an initial QtBuilder, which is used by QtInstanceBuilder to create weld::Widget instances using native Qt widgets. This tries to be close to the VCL implementation (VclBuilder). The selected approach is based on Caolán's suggestion in [1] to rework VclBuilder to have overridable methods for widgets creation. This way, we can have common code for the UI parser but the function for widget creation is different. Qt equivalents for Gtk's widget classes in the .ui files: * GtkMessageDialog -> QMessageBox * GtkBox -> QLayout (can be QVBoxLayout/QHBoxLayout based on property in .ui file) * GtkButtonBox -> QDialogButtonBox * GtkButton -> QPushButton As QMessageBox already comes with a layout and a QDialogButtonBox, don't create new ones, but return the existing ones in QtBuilder::makeObject. This commit implements initial support for the above-mentioned widget types and adds the first message dialog to the list of supported .ui files in QtInstanceBuilder::IsUIFileSupported, so a native QMessageBox is used for it now, unless environment variable SAL_VCL_QT_NO_WELDED_WIDGETS is set when starting LibreOffice. The dialog ("modules/swriter/ui/inforeadonlydialog.ui") gets shown when taking the following steps: * start Writer * type "hello world" * select text * "Insert" -> "Section" * tick the "Protect" checkbox in the "Write Protection" section * close dialog via "Insert" button * try to type in the protected section The dialog can be dismissed using the default "OK" button. (Handling for response codes for buttons is not implemented yet, which will be needed when welding dialogs that have multiple buttons resulting in different behavior depending on what button gets clicked.) This change was originally submitted as a WIP change as part of Omkar Acharekar's Outreachy project "Implement Qt/KDE Frameworks theming using native Qt widgets" (see [2]), then further refined by Michael Weghorn. [1] https://lists.freedesktop.org/archives/libreoffice/2023-December/091288.html [2] https://lists.freedesktop.org/archives/libreoffice/2023-December/091281.html Co-authored-by: Michael Weghorn <m.weghorn@posteo.de> Change-Id: I6dd010a2138c245dc1e6d83dd08123898e9d9048 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161831 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-09-25 09:48:09 +02:00
class VCL_DLLPUBLIC BuilderBase
{
public:
typedef std::map<OUString, OUString> stringmap;
typedef std::map<OUString, std::pair<OUString, OUString>> accelmap;
typedef stringmap Adjustment;
typedef stringmap TextBuffer;
static OUString extractActionName(stringmap& rMap);
static sal_Int32 extractActive(stringmap& rMap);
static bool extractResizable(stringmap& rMap);
static VclButtonsType mapGtkToVclButtonsType(std::u16string_view sGtkButtons);
protected:
BuilderBase(std::u16string_view sUIDir, const OUString& rUIFile, bool bLegacy);
tdf#130857 refactor VclBuilder: Extract template base class Refactor `VclBuilder` by extracting the `handleChild` method and moving it into a new template base class `WidgetBuilder`, so both `VclBuilder` and an upcoming `QtBuilder` (see [1]) can share the common logic to parse the .ui file and override the virtual methods like `applyPackingProperties`, `tweakInsertedChild` etc. to handle toolkit specific cases, as mentioned as one potential approach in Caolán's email [2]. The new class has 2 template parameters `Widget` and `WidgetPtr` to account for the fact that `VclBuilder` doesn't just use `vcl::Window*`, but there's a specific class, `VclPtr`. As the inline comments say, more refactoring will be needed to abstract the current `VclBuilder` implementations of various methods from the `vcl::Window` specifics and make them reusable for other subclasses as well, but this commit is a start. The idea is to allow for incrementally refactoring aspects relevant for specific .ui files/features rather than having to refactor everything and implement support for all widget types at once, see also commit 9b3a2996e710fee11145dcbbe38a6f1e6f646ec8 Author: OmkarAcharekar <omkaracharekar12@gmail.com> Date: Wed Sep 18 09:35:09 2024 +0200 tdf#130857 qt weld: Add QtInstanceBuilder skeleton which adds an initially empty list of .ui files that should be handled by the upcoming Qt-based implementation. [1] https://gerrit.libreoffice.org/c/core/+/161831 [2] https://lists.freedesktop.org/archives/libreoffice/2023-December/091288.html Co-authored-by: Michael Weghorn <m.weghorn@posteo.de> Change-Id: I2d81cc6dd54d796b549357a4444b95627661c623 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163103 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-09-20 13:33:01 +02:00
virtual ~BuilderBase() = default;
struct ListStore
{
typedef std::vector<OUString> row;
std::vector<row> m_aEntries;
};
struct SizeGroup
{
std::vector<OUString> m_aWidgets;
stringmap m_aProperties;
SizeGroup() {}
};
struct StringPair
{
OUString m_sID;
OUString m_sValue;
StringPair(OUString sId, OUString sValue)
: m_sID(std::move(sId))
, m_sValue(std::move(sValue))
{
}
};
typedef StringPair MnemonicWidgetMap;
typedef StringPair RadioButtonGroupMap;
static void collectPangoAttribute(xmlreader::XmlReader& reader, stringmap& rMap);
static void collectAtkRelationAttribute(xmlreader::XmlReader& reader, stringmap& rMap);
static void collectAtkRoleAttribute(xmlreader::XmlReader& reader, stringmap& rMap);
static void collectAccelerator(xmlreader::XmlReader& reader, accelmap& rMap);
stringmap collectPackingProperties(xmlreader::XmlReader& reader);
void collectProperty(xmlreader::XmlReader& rReader, stringmap& rMap) const;
static OUString extractGroup(stringmap& rMap);
static bool extractHeadersVisible(stringmap& rMap);
static bool extractEntry(stringmap& rMap);
static OUString extractIconName(stringmap& rMap);
static OUString extractLabel(stringmap& rMap);
static OUString extractPopupMenu(stringmap& rMap);
static bool extractShowExpanders(stringmap& rMap);
static OUString extractTitle(stringmap& rMap);
static OUString extractTooltipText(stringmap& rMap);
static bool extractVisible(stringmap& rMap);
void extractClassAndIdAndCustomProperty(xmlreader::XmlReader& reader, OUString& rClass,
OUString& rId, OUString& rCustomProperty);
static Image loadThemeImage(const OUString& rFileName);
void handleActionWidget(xmlreader::XmlReader& reader);
void handleInterfaceDomain(xmlreader::XmlReader& rReader);
static bool isToolbarItemClass(std::u16string_view sClass);
static std::vector<vcl::EnumContext::Context> handleStyle(xmlreader::XmlReader& reader,
int& nPriority);
static OUString getStyleClass(xmlreader::XmlReader& reader);
static bool hasOrientationVertical(stringmap& rMap);
const OUString& getUIFileUrl() { return m_sUIFileUrl; }
const OUString& getHelpRoot() { return m_sHelpRoot; }
bool isLegacy() { return m_bLegacy; }
const std::locale& getResLocale() const;
const std::vector<SizeGroup>& getSizeGroups() const;
void extractMnemonicWidget(const OUString& id, stringmap& rMap);
const std::vector<MnemonicWidgetMap>& getMnemonicWidgetMaps() const;
void extractRadioButtonGroup(const OUString& id, stringmap& rVec);
const std::vector<RadioButtonGroupMap>& getRadioButtonGroupMaps() const;
OUString finalizeValue(const OString& rContext, const OString& rValue,
const bool bTranslate) const;
stringmap handleAtkObject(xmlreader::XmlReader& reader) const;
std::vector<ComboBoxTextItem> handleItems(xmlreader::XmlReader& reader) const;
void handleListStore(xmlreader::XmlReader& reader, const OUString& rID,
std::u16string_view rClass);
void handleRow(xmlreader::XmlReader& reader, const OUString& rID);
void addAdjustment(const OUString& sID, const Adjustment& rAdjustment);
const Adjustment* get_adjustment_by_name(const OUString& sID) const;
void addTextBuffer(const OUString& sID, const TextBuffer& rTextBuffer);
const TextBuffer* get_buffer_by_name(const OUString& sID) const;
const ListStore* get_model_by_name(const OUString& sID) const;
virtual void set_response(const OUString& rId, int nResponse) = 0;
void handleSizeGroup(xmlreader::XmlReader& reader);
virtual void resetParserState();
static void reportException(const css::uno::Exception& rExcept);
private:
struct ParserState
{
std::locale m_aResLocale;
std::map<OUString, ListStore> m_aModels;
std::vector<SizeGroup> m_aSizeGroups;
std::map<OUString, Adjustment> m_aAdjustments;
std::map<OUString, TextBuffer> m_aTextBuffers;
std::vector<MnemonicWidgetMap> m_aMnemonicWidgetMaps;
std::vector<RadioButtonGroupMap> m_aRadioButtonGroupMaps;
};
std::unique_ptr<ParserState> m_pParserState;
OUString m_sUIFileUrl;
OUString m_sHelpRoot;
bool m_bLegacy;
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */