diff --git a/examples/corelib/CMakeLists.txt b/examples/corelib/CMakeLists.txt index 38a883b4ea7..856e1f30294 100644 --- a/examples/corelib/CMakeLists.txt +++ b/examples/corelib/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory(mimetypes) add_subdirectory(serialization) add_subdirectory(tools) add_subdirectory(platform) +add_subdirectory(time) if(QT_FEATURE_thread) add_subdirectory(threads) endif() diff --git a/examples/corelib/corelib.pro b/examples/corelib/corelib.pro index 625957ca1a6..d921ae9ed37 100644 --- a/examples/corelib/corelib.pro +++ b/examples/corelib/corelib.pro @@ -6,6 +6,7 @@ SUBDIRS = \ mimetypes \ serialization \ tools \ - platform + platform \ + time qtConfig(thread): SUBDIRS += threads diff --git a/examples/corelib/time/CMakeLists.txt b/examples/corelib/time/CMakeLists.txt new file mode 100644 index 00000000000..32b93e9ecfa --- /dev/null +++ b/examples/corelib/time/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +add_subdirectory(calendarbackendplugin) diff --git a/examples/corelib/time/calendarbackendplugin/CMakeLists.txt b/examples/corelib/time/calendarbackendplugin/CMakeLists.txt new file mode 100644 index 00000000000..7aa4a18a1e5 --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.5) +project(JulianGregorianCalendar VERSION 0.1 LANGUAGES CXX) + +find_package(Qt6 REQUIRED COMPONENTS Core) + +qt_standard_project_setup() + +add_subdirectory(plugin) +add_subdirectory(application) + +install(TARGETS calendarPlugin JulianGregorianCalendar + BUNDLE DESTINATION . + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +qt_generate_deploy_app_script( + TARGET calendarPlugin + OUTPUT_SCRIPT deploy_script + NO_UNSUPPORTED_PLATFORM_ERROR +) +install(SCRIPT ${deploy_script}) + +qt_generate_deploy_app_script( + TARGET JulianGregorianCalendar + OUTPUT_SCRIPT deploy_script + NO_UNSUPPORTED_PLATFORM_ERROR +) +install(SCRIPT ${deploy_script}) diff --git a/examples/corelib/time/calendarbackendplugin/application/CMakeLists.txt b/examples/corelib/time/calendarbackendplugin/application/CMakeLists.txt new file mode 100644 index 00000000000..3cd4ffe430c --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/application/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.5) +project(JulianGregorianCalendar VERSION 0.1 LANGUAGES CXX) + +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Core) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Core) + +qt_standard_project_setup() + +include_directories(../common/) + +qt_add_executable(JulianGregorianCalendar + ../common/calendarBackendInterface.h + main.cpp +) + +target_link_libraries(JulianGregorianCalendar + PRIVATE + Qt::Widgets + Qt::Core +) diff --git a/examples/corelib/time/calendarbackendplugin/application/application.pro b/examples/corelib/time/calendarbackendplugin/application/application.pro new file mode 100644 index 00000000000..c6a268c9a05 --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/application/application.pro @@ -0,0 +1,11 @@ +TEMPLATE = app +TARGET = application +INCLUDEPATH += . \ + ../common/ +QT += core core-private widgets + +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/datetime/calendarbackendplugin/application +INSTALLS += target + +SOURCES += main.cpp +HEADERS += ../common/calendarBackendInterface.h diff --git a/examples/corelib/time/calendarbackendplugin/application/main.cpp b/examples/corelib/time/calendarbackendplugin/application/main.cpp new file mode 100644 index 00000000000..e270bb194b2 --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/application/main.cpp @@ -0,0 +1,59 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "calendarBackendInterface.h" + +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + QCoreApplication::setApplicationName("JulianGregorianCalendar"); + QCommandLineParser parser; + parser.setApplicationDescription("Calendar Backend Plugin Example"); + parser.addHelpOption(); + parser.addPositionalArgument("date; names", + "Date of transition between " + "Julian and Gregorian calendars " + "as string in the format 'yyyy-MM-dd;'. Optionally, user can " + "provide names for the calendar separated with ';'"); + parser.process(a); + const QStringList args = parser.positionalArguments(); + if (args.isEmpty()) + parser.showHelp(1); + if (args.at(0).isEmpty()) + parser.showHelp(1); +//![0] + QPluginLoader loader; + loader.setFileName("../plugin/calendarPlugin"); + loader.load(); + if (!loader.isLoaded()) + return 1; + auto *myplugin = qobject_cast(loader.instance()); +//![0] +//![1] + const auto cid = myplugin->loadCalendar(args.at(0)); + if (!cid.isValid()) { + qWarning() << "Invalid ID"; + parser.showHelp(1); + } + const QCalendar calendar(cid); +//![1] +//![2] + QCalendarWidget widget; + widget.setCalendar(calendar); + widget.show(); + QCalendar::YearMonthDay when = { 1582, 10, 4 }; + QCalendar julian = QCalendar(QCalendar::System::Julian); + auto got = QDate::fromString(args.at(0).left(10), u"yyyy-MM-dd", julian); + if (got.isValid()) + when = julian.partsFromDate(got); + widget.setCurrentPage(when.year, when.month); +//![2] + return a.exec(); +} diff --git a/examples/corelib/time/calendarbackendplugin/calendarbackendplugin.pro b/examples/corelib/time/calendarbackendplugin/calendarbackendplugin.pro new file mode 100644 index 00000000000..abfca31aead --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/calendarbackendplugin.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +SUBDIRS += plugin \ + application diff --git a/examples/corelib/time/calendarbackendplugin/common/calendarBackendInterface.h b/examples/corelib/time/calendarbackendplugin/common/calendarBackendInterface.h new file mode 100644 index 00000000000..194bd22714f --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/common/calendarBackendInterface.h @@ -0,0 +1,27 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef CALENDARINTERFACE_H +#define CALENDARINTERFACE_H + +#include +#include + +//![0] +class RequestedCalendarInterface +{ +public: + RequestedCalendarInterface() = default; + virtual QCalendar::SystemId loadCalendar(QAnyStringView requested) = 0; + virtual ~RequestedCalendarInterface() = default; +}; +//![0] +QT_BEGIN_NAMESPACE +//![1] +#define RequestedCalendarInterface_iid \ +"org.qt-project.Qt.Examples.CalendarBackend.RequestedCalendarInterface/1.0" +Q_DECLARE_INTERFACE(RequestedCalendarInterface, RequestedCalendarInterface_iid) +//![1] +QT_END_NAMESPACE + +#endif // CALENDARINTERFACE_H diff --git a/examples/corelib/time/calendarbackendplugin/doc/images/calendarwindow_transition.png b/examples/corelib/time/calendarbackendplugin/doc/images/calendarwindow_transition.png new file mode 100644 index 00000000000..eb5e2ba0c86 Binary files /dev/null and b/examples/corelib/time/calendarbackendplugin/doc/images/calendarwindow_transition.png differ diff --git a/examples/corelib/time/calendarbackendplugin/doc/src/calendarbackendplugin.qdoc b/examples/corelib/time/calendarbackendplugin/doc/src/calendarbackendplugin.qdoc new file mode 100644 index 00000000000..b715ccd28ad --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/doc/src/calendarbackendplugin.qdoc @@ -0,0 +1,186 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \example time/calendarbackendplugin + \title Calendar Backend Plugin Example + \examplecategory {Data Processing & I/O} + \ingroup examples-time + \brief QCalendar example illustrating user-supplied custom calendars. + + \image calendarwindow_transition.png + + \section1 Introduction + + There are numerous different calendar systems in use around the globe. + Qt has built-in support for some of them (see \l{QCalendar::}{System}), + but can't provide general support due to their high number. + Additional calendar systems can be provided by implementing a + custom QCalendarBackend, which is a private API. + + This example demonstrates how to write a custom calendar backend + and how to use the low-level plugin API to extend an application + to user-selectable calendars. + Many countries transitioned from the Julian to the Gregorian calendar + at some point in their history, and this custom calendar backend will + implement the respective calendar as an example. The custom backend + is compiled into a plugin and loaded at runtime by the main application. + The exact transition date, different for various regions, is provided + as a string to the plugin and can be determined by the user. + + \section1 Calendar backend + + The calendar backend class must inherit from \c QCalendarBackend and implement its + pure virtual functions in a \c thread-safe way. It may also override + some other virtual functions as needed. + + \section2 Example implementation + + This example inherits from the already existing \c QRomanCalendar, + which in turn inherits from the \c QCalendarBackend and implements some of + its virtual functions. + It's constructive to do this because the transition calendar shares, + with both Julian and Gregorian calendars, parts provided by the Roman calendar. + + Here is the class declaration of \c JulianGregorianCalendar: + + \snippet time/calendarbackendplugin/plugin/calendarbackend.h 0 + + The \c QDate passed to the constructor - \a endJulian - is the date of the last day + of the Julian calendar. The calendar will automatically calculate the shift for a given + year, e.g in 1582, 10 days were omitted, but in 1700, 12 days had to be omitted. + The calendar backend is registered under \a name and a calendar instance can be + created using that name. The class only overrides functions where the two calendars + it combines differ from the Roman base. It has instances of the Julian and Gregorian + calendars to which these functions can delegate. + + \section2 Julian Day conversions + + \c dateToJulianDay(int year, int month, int day, qint64 *jd) computes the Julian + day number corresponding to the specified \a year, \a month and \a day. + Returns \c true and sets \a jd if there is such a date in this calendar; otherwise, + returns \c false. + + \snippet time/calendarbackendplugin/plugin/calendarbackend.cpp 0 + + \c julianDayToDate(qint64 jd) computes year, month and day in this calendar for the given + Julian day number, \a jd. If the given day falls outside this calendar's scope, + the return value for \c isValid() is \c false. In this example, if the given date + falls in the gap jumped over by the transition from Julian to Gregorian calendar, + it is out of scope. + + \snippet time/calendarbackendplugin/plugin/calendarbackend.cpp 1 + + \section2 Locale support + + A calendar may, in general, have its own naming of months of the year + and days of the week. These must be suitably localized to be intelligible + to all users. By default the backend baseclass takes care of week day + names for us, which is entirely sufficient for these Julian/Gregorian + transition calendars. + + Although a backend can directly override the month naming methods, the + baseclass version of these can be customized by implementing + \c localeMonthData() and \c localeMonthIndexData() to provide tables + of localized month names. Since the Julian and Gregorian + calendars use the same month naming, they inherit that customization + from a common base, \c QRomanCalendar. This also means the custom + calendar can use the same names, again by inheriting from that base. + This takes care of localization. + + \sa QCalendarWidget, QCalendar, QDate, QLocale + + \section1 Plugin + + Qt applications can be extended through plugins. This requires the application to + detect and load plugins using \l{QPluginLoader}. + + \section2 Writing a plugin + + To write a plugin, the first thing that has to be done is to + create a pure virtual class that defines the interface between + plugin and application. + + In this example the following interface was used: + + \snippet time/calendarbackendplugin/common/calendarBackendInterface.h 0 + + and register it in the Qt meta-object system: + + \snippet time/calendarbackendplugin/common/calendarBackendInterface.h 1 + + \l{::}{Q_DECLARE_INTERFACE()} macro is used to associate the + \c ClassName (here: \c RequestedCalendarInterface) with the defined + \c Identifier (here: \c RequestedCalendarInterface_iid). The \c Identifier + must be unique. This interface can be implemented by plugins that load + other calendars, interpreting \c loadCalendar()'s string parameter in + various ways. It isn't limited to this particular plugin that will be implemented + using it, so it has a generic name, not one specific to this particular backend. + + Then a plugin class that inherits from \l{QObject} and from the interface is created. + + \snippet time/calendarbackendplugin/plugin/calendarplugin.h 0 + + \l{::}{Q_PLUGIN_METADATA()} and \l{QObject::}{Q_INTERFACES()} + are being used to declare meta data that was also declared + in the interface class and to tell Qt which interface the class implements. + + \sa QtPlugin + + This plugin instantiates and registers a custom calendar backend which + can in turn be used to instantiate \l{QCalendar} by the application at + any point. + + Qt Plugins are stored in a single shared library (a DLL) and \l{QPluginLoader} + is used for detecting and dynamically loading the plugin file (for more + see \l{How to Create Qt Plugins}). + + \section2 Loading the plugin + + \l{QPluginLoader} checks if the plugin's version of Qt + is the same as that of the application and + provides direct access to a Qt plugin. + + Here is the use of \l QPluginLoader in the example: + + \snippet time/calendarbackendplugin/application/main.cpp 0 + + First, an instance of a QPluginLoader object needs to be initialized. Next, + it has to be specified which plugin to load by passing a DLL file name to + \l{QPluginLoader::}{setFileName()}. Then, by using \l{QPluginLoader::}{load()}, + the plugin file is dynamically loaded. At the end, a call to \l{QObject::}{qobject_cast()} + tests whether a plugin implements a given interface. \l{QObject::}{qobject_cast()} + uses \l{QPluginLoader::}{instance()} to access the root component in the plugin. + If the plugin has been loaded correctly, its functions should be available. + + \sa QPluginLoader + + \section2 Instantiating the backend + + In this example there is only one function in the plugin. \c loadCalendar() + is responsible for registering the custom calendar backend in + \c QCalendarRegistry with given date of the transition and names. + + \snippet time/calendarbackendplugin/plugin/calendarplugin.cpp 0 + + String argument for \c loadCalendar() is supplied by the user via command + line arguments. Then, the date of transition from the Julian calendar to + the Gregorian is extracted by splitting the given string. + After validation, a custom backend object is created. + The backend must be registered before it can be used in \l{QCalendar}, + using the \c registerCustomBackend() method. + Once a backend is registered, a QCalendar can be instantiated with + the respective \l{QCalendar::}{SystemId} or \c name. + + Here is the use of \c loadCalendar in the \c main: + + \snippet time/calendarbackendplugin/application/main.cpp 1 + + \section2 Extending QCalendarWidget + + By creating a \l{QCalendar} instance with a specific calendar as a backend, + it is possible to provide \l{QCalendarWidget} with that backend and + visualize it. + + \snippet time/calendarbackendplugin/application/main.cpp 2 +*/ diff --git a/examples/corelib/time/calendarbackendplugin/plugin/CMakeLists.txt b/examples/corelib/time/calendarbackendplugin/plugin/CMakeLists.txt new file mode 100644 index 00000000000..bac4118b8f5 --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/plugin/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +cmake_minimum_required(VERSION 3.5) +project(calendarPlugin VERSION 0.1 LANGUAGES CXX) + +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Core) +find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Core) + +qt_standard_project_setup() + +include_directories(../common/) + +qt_add_library(calendarPlugin SHARED + ../common/calendarBackendInterface.h + calendarplugin.h + calendarplugin.cpp + calendarbackend.cpp + calendarbackend.h +) + +target_link_libraries(calendarPlugin + PRIVATE + Qt::Widgets + Qt::Core + Qt::CorePrivate +) diff --git a/examples/corelib/time/calendarbackendplugin/plugin/calendarbackend.cpp b/examples/corelib/time/calendarbackendplugin/plugin/calendarbackend.cpp new file mode 100644 index 00000000000..fbf95349321 --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/plugin/calendarbackend.cpp @@ -0,0 +1,103 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "calendarbackend.h" + +#include + +JulianGregorianCalendar::JulianGregorianCalendar(QDate endJulian, QAnyStringView name = {}) + : m_julianUntil(julian.partsFromDate(endJulian)), + m_gregorianSince(gregorian.partsFromDate(endJulian.addDays(1))), + m_name(name.isEmpty() + ? endJulian.toString(u"Julian until yyyy-MM-dd", julian) + : name.toString()) +{ + Q_ASSERT_X(m_julianUntil.year < m_gregorianSince.year + || (m_julianUntil.year == m_gregorianSince.year + && (m_julianUntil.month < m_gregorianSince.month + || (m_julianUntil.month == m_gregorianSince.month + && m_julianUntil.day < m_gregorianSince.day))), + "JulianGregorianCalendar::JulianGregorianCalendar()", + "Perversely early date for Julian-to-Gregorian transition"); +} + +QString JulianGregorianCalendar::name() const +{ + return QStringLiteral("JulianGregorian"); +} + +int JulianGregorianCalendar::daysInMonth(int month, int year) const +{ + if (year == QCalendar::Unspecified) + return QRomanCalendar::daysInMonth(month, year); + if (year < m_julianUntil.year + || (year == m_julianUntil.year && month < m_julianUntil.month)) { + return julian.daysInMonth(month, year); + } + if ((year > m_gregorianSince.year) + || (year == m_gregorianSince.year && month > m_gregorianSince.month)) { + return gregorian.daysInMonth(month, year); + } + if (m_julianUntil.year == m_gregorianSince.year) { + Q_ASSERT(year == m_julianUntil.year); + if (m_julianUntil.month == m_gregorianSince.month) { + Q_ASSERT(month == m_julianUntil.month); + return QRomanCalendar::daysInMonth(month, year) + + m_julianUntil.day - m_gregorianSince.day + 1; + } + } + if (year == m_julianUntil.year && month == m_julianUntil.month) + return m_julianUntil.day; + if (year == m_gregorianSince.year && month == m_gregorianSince.month) + return gregorian.daysInMonth(month, year) + 1 - m_gregorianSince.day; + Q_ASSERT(year > 3900); + return 0; +} + +bool JulianGregorianCalendar::isLeapYear(int year) const +{ + if (year < m_julianUntil.year + || (year == m_julianUntil.year + && (m_julianUntil.month > 2 + || (m_julianUntil.month == 2 && m_julianUntil.day == 29)))) { + return julian.isLeapYear(year); + } + return gregorian.isLeapYear(year); +} +//![0] +bool JulianGregorianCalendar::dateToJulianDay(int year, int month, int day, qint64 *jd) const +{ + if (year == m_julianUntil.year && month == m_julianUntil.month) { + if (m_julianUntil.day < day && day < m_gregorianSince.day) { + // Requested date is in the gap skipped over by the transition. + *jd = 0; + return false; + } + } + QDate givenDate = gregorian.dateFromParts(year, month, day); + QDate julianUntil = julian.dateFromParts(m_julianUntil); + if (givenDate > julianUntil) { + *jd = givenDate.toJulianDay(); + return true; + } + *jd = julian.dateFromParts(year, month, day).toJulianDay(); + return true; +} +//![0] +//![1] +QCalendar::YearMonthDay JulianGregorianCalendar::julianDayToDate(qint64 jd) const +{ + const qint64 jdForChange = julian.dateFromParts(m_julianUntil).toJulianDay(); + if (jdForChange < jd) { + QCalendar gregorian(QCalendar::System::Gregorian); + QDate date = QDate::fromJulianDay(jd); + return gregorian.partsFromDate(date); + } else if (jd <= jdForChange) { + QCalendar julian(QCalendar::System::Julian); + QDate date = QDate::fromJulianDay(jd); + return julian.partsFromDate(date); + } + return QCalendar::YearMonthDay(QCalendar::Unspecified, QCalendar::Unspecified, + QCalendar::Unspecified); +} +//![1] diff --git a/examples/corelib/time/calendarbackendplugin/plugin/calendarbackend.h b/examples/corelib/time/calendarbackendplugin/plugin/calendarbackend.h new file mode 100644 index 00000000000..5b565c794c3 --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/plugin/calendarbackend.h @@ -0,0 +1,29 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef CALENDARBACKEND_H +#define CALENDARBACKEND_H + +#include "private/qromancalendar_p.h" +#include "qdatetime.h" + +#include +//![0] +class JulianGregorianCalendar : public QRomanCalendar +{ +public: + JulianGregorianCalendar(QDate endJulian, QAnyStringView name); + QString name() const override; + int daysInMonth(int month, int year = QCalendar::Unspecified) const override; + bool isLeapYear(int year) const override; + bool dateToJulianDay(int year, int month, int day, qint64 *jd) const override; + QCalendar::YearMonthDay julianDayToDate(qint64 jd) const override; +private: + static inline const QCalendar julian = QCalendar(QCalendar::System::Julian); + static inline const QCalendar gregorian = QCalendar(QCalendar::System::Gregorian); + QCalendar::YearMonthDay m_julianUntil; + QCalendar::YearMonthDay m_gregorianSince; + QString m_name; +}; +//![0] +#endif // CALENDARBACKEND_H diff --git a/examples/corelib/time/calendarbackendplugin/plugin/calendarplugin.cpp b/examples/corelib/time/calendarbackendplugin/plugin/calendarplugin.cpp new file mode 100644 index 00000000000..462493bf0dd --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/plugin/calendarplugin.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "calendarplugin.h" + +JulianGregorianPlugin::JulianGregorianPlugin() +{ +} +//![0] +QCalendar::SystemId JulianGregorianPlugin::loadCalendar(QAnyStringView request) +{ + Q_ASSERT(!request.isEmpty()); + QStringList names = request.toString().split(u';'); + if (names.size() < 1) + return {}; + QString dateString = names.takeFirst(); + auto date = QDate::fromString(dateString, u"yyyy-MM-dd", + QCalendar(QCalendar::System::Julian)); + if (!date.isValid()) + return {}; + QString primary = names.isEmpty() ? + QString::fromStdU16String(u"Julian until ") + dateString : names[0]; + auto backend = new JulianGregorianCalendar(date, primary); + names.emplaceFront(backend->name()); + auto cid = backend->registerCustomBackend(names); + return cid; +} + +JulianGregorianPlugin::~JulianGregorianPlugin() +{ +} +//![0] diff --git a/examples/corelib/time/calendarbackendplugin/plugin/calendarplugin.h b/examples/corelib/time/calendarbackendplugin/plugin/calendarplugin.h new file mode 100644 index 00000000000..0d5c9cf2158 --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/plugin/calendarplugin.h @@ -0,0 +1,25 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef CALENDARPLUGIN_H +#define CALENDARPLUGIN_H + +#include "calendarbackend.h" +#include "calendarBackendInterface.h" + +#include +//![0] +class JulianGregorianPlugin : public QObject, public RequestedCalendarInterface +{ + Q_OBJECT + Q_INTERFACES(RequestedCalendarInterface) + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples." + "CalendarBackend." + "RequestedCalendarInterface/1.0") +public: + JulianGregorianPlugin(); + QCalendar::SystemId loadCalendar(QAnyStringView request) override; + ~JulianGregorianPlugin(); +}; +//![0] +#endif // CALENDARPLUGIN_H diff --git a/examples/corelib/time/calendarbackendplugin/plugin/plugin.pro b/examples/corelib/time/calendarbackendplugin/plugin/plugin.pro new file mode 100644 index 00000000000..6a5f814e858 --- /dev/null +++ b/examples/corelib/time/calendarbackendplugin/plugin/plugin.pro @@ -0,0 +1,11 @@ +TEMPLATE = lib +TARGET = calendarPlugin +INCLUDEPATH += . \ + ../common/ +QT += core core-private widgets + +HEADERS += calendarbackend.h calendarplugin.h +SOURCES += calendarbackend.cpp calendarplugin.cpp + +target.path = $$[QT_INSTALL_EXAMPLES]/corelib/datetime/calendarbackendplugin/plugin +INSTALLS += target diff --git a/examples/corelib/time/time.pro b/examples/corelib/time/time.pro new file mode 100644 index 00000000000..4d24416e345 --- /dev/null +++ b/examples/corelib/time/time.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +CONFIG += no_docs_target + +SUBDIRS = calendarbackendplugin