summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAshod Nakashian <ashod.nakashian@collabora.co.uk>2022-12-23 13:02:57 -0500
committerAndras Timar <andras.timar@collabora.com>2023-01-29 13:22:28 +0000
commite2d646665c4cb4c7eeb0a73cb5f460838589bef0 (patch)
tree42987bdec2a8e09af3b6cf70ad2b244c01d92136
parente3e259d551c0c8b7c106191f2c258e5929db1b29 (diff)
lok: support per-user timezone
This adds support for user-specific timezone. When none is provided during loading, the system default is used. Signed-off-by: Ashod Nakashian <ashod.nakashian@collabora.co.uk> Change-Id: Ie863450687eb82bc475268a09c9112e9fd50020f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144816 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Jan Holesovsky <kendy@collabora.com> (cherry picked from commit abaf8c0af1c6c7fe01276fdf2ae62419c7b0f654) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146211 Tested-by: Jenkins Reviewed-by: Andras Timar <andras.timar@collabora.com>
-rw-r--r--comphelper/source/misc/lok.cxx19
-rw-r--r--desktop/qa/desktop_lib/test_desktop_lib.cxx4
-rw-r--r--desktop/source/lib/init.cxx49
-rw-r--r--include/LibreOfficeKit/LibreOfficeKit.h3
-rw-r--r--include/LibreOfficeKit/LibreOfficeKit.hxx11
-rw-r--r--include/comphelper/lok.hxx3
-rw-r--r--include/sfx2/lokhelper.hxx11
-rw-r--r--include/sfx2/viewsh.hxx17
-rw-r--r--sc/source/ui/view/viewfun6.cxx19
-rw-r--r--sfx2/source/view/lokhelper.cxx42
-rw-r--r--sfx2/source/view/viewsh.cxx4
11 files changed, 181 insertions, 1 deletions
diff --git a/comphelper/source/misc/lok.cxx b/comphelper/source/misc/lok.cxx
index b11bf4e83582..1f07cd2614eb 100644
--- a/comphelper/source/misc/lok.cxx
+++ b/comphelper/source/misc/lok.cxx
@@ -8,6 +8,7 @@
*/
#include <comphelper/lok.hxx>
+#include <osl/process.h>
#include <i18nlangtag/languagetag.hxx>
#include <sal/log.hxx>
@@ -255,6 +256,24 @@ bool isAllowlistedLanguage(const OUString& lang)
#endif
}
+void setTimezone(bool isSet, const OUString& rTimezone)
+{
+ if (isSet)
+ {
+ // Set the given timezone, even if empty.
+ osl_setEnvironment(OUString("TZ").pData, rTimezone.pData);
+ }
+ else
+ {
+ // Unset and empty aren't the same.
+ // When unset, it means default to the system configured timezone.
+ osl_clearEnvironment(OUString("TZ").pData);
+ }
+
+ // Update the timezone data.
+ ::tzset();
+}
+
static void (*pStatusIndicatorCallback)(void *data, statusIndicatorCallbackType type, int percent, const char* pText)(nullptr);
static void *pStatusIndicatorCallbackData(nullptr);
diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index 98c734c8190a..a5560dd6be8d 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -3629,10 +3629,12 @@ void DesktopLOKTest::testABI()
CPPUNIT_ASSERT_EQUAL(documentClassOffset(65), offsetof(struct _LibreOfficeKitDocumentClass, getSelectionTypeAndText));
CPPUNIT_ASSERT_EQUAL(documentClassOffset(66), offsetof(struct _LibreOfficeKitDocumentClass, getDataArea));
CPPUNIT_ASSERT_EQUAL(documentClassOffset(67), offsetof(struct _LibreOfficeKitDocumentClass, getEditMode));
+ CPPUNIT_ASSERT_EQUAL(documentClassOffset(68),
+ offsetof(struct _LibreOfficeKitDocumentClass, setViewTimezone));
// Extending is fine, update this, and add new assert for the offsetof the
// new method
- CPPUNIT_ASSERT_EQUAL(documentClassOffset(68), sizeof(struct _LibreOfficeKitDocumentClass));
+ CPPUNIT_ASSERT_EQUAL(documentClassOffset(69), sizeof(struct _LibreOfficeKitDocumentClass));
}
CPPUNIT_TEST_SUITE_REGISTRATION(DesktopLOKTest);
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 97d74bc4682d..db9a9632e4c3 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -7,6 +7,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+#include <sfx2/lokhelper.hxx>
#include <config_buildconfig.h>
#include <config_features.h>
@@ -1203,6 +1204,8 @@ static bool doc_renderSearchResult(LibreOfficeKitDocument* pThis,
static void doc_sendContentControlEvent(LibreOfficeKitDocument* pThis, const char* pArguments);
+static void doc_setViewTimezone(LibreOfficeKitDocument* pThis, int nId, const char* timezone);
+
} // extern "C"
namespace {
@@ -1353,6 +1356,8 @@ LibLODocument_Impl::LibLODocument_Impl(uno::Reference <css::lang::XComponent> xC
m_pDocumentClass->sendContentControlEvent = doc_sendContentControlEvent;
+ m_pDocumentClass->setViewTimezone = doc_setViewTimezone;
+
gDocumentClass = m_pDocumentClass;
}
pClass = m_pDocumentClass.get();
@@ -2600,6 +2605,27 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis,
SvNumberFormatter::resetTheCurrencyTable();
}
+ // Set the timezone, if not empty.
+ const OUString aTimezone = extractParameter(aOptions, u"Timezone");
+ if (!aTimezone.isEmpty())
+ {
+ SfxLokHelper::setDefaultTimezone(true, aTimezone);
+ }
+ else
+ {
+ // Default to the TZ envar, if set.
+ const char* tz = ::getenv("TZ");
+ if (tz)
+ {
+ SfxLokHelper::setDefaultTimezone(true,
+ OStringToOUString(tz, RTL_TEXTENCODING_UTF8));
+ }
+ else
+ {
+ SfxLokHelper::setDefaultTimezone(false, OUString());
+ }
+ }
+
const OUString aDeviceFormFactor = extractParameter(aOptions, u"DeviceFormFactor");
SfxLokHelper::setDeviceFormFactor(aDeviceFormFactor);
@@ -6598,6 +6624,22 @@ static void doc_sendContentControlEvent(LibreOfficeKitDocument* pThis, const cha
pDoc->executeContentControlEvent(aMap);
}
+static void doc_setViewTimezone(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis*/, int nId,
+ const char* pTimezone)
+{
+ comphelper::ProfileZone aZone("doc_setViewTimezone");
+
+ SolarMutexGuard aGuard;
+ SetLastExceptionMsg();
+
+ // Leave the default if we get a null timezone.
+ if (pTimezone)
+ {
+ OUString sTimezone = OStringToOUString(pTimezone, RTL_TEXTENCODING_UTF8);
+ SfxLokHelper::setViewTimezone(nId, true, sTimezone);
+ }
+}
+
static char* lo_getError (LibreOfficeKit *pThis)
{
comphelper::ProfileZone aZone("lo_getError");
@@ -7065,8 +7107,15 @@ static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const char
comphelper::ProfileZone aZone("lok-init");
if (eStage == PRE_INIT)
+ {
rtl_alloc_preInit(true);
+ // Set the default timezone to the TZ envar, if set.
+ const char* tz = ::getenv("TZ");
+ SfxLokHelper::setDefaultTimezone(!!tz, tz ? OStringToOUString(tz, RTL_TEXTENCODING_UTF8)
+ : OUString());
+ }
+
if (eStage != SECOND_INIT)
comphelper::LibreOfficeKit::setActive();
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 61a68f632209..74c2100ab18c 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -493,6 +493,9 @@ struct _LibreOfficeKitDocumentClass
/// @see lok::Document::getEditMode().
int (*getEditMode) (LibreOfficeKitDocument* pThis);
+ /// @see lok::Document::setViewTimezone().
+ void (*setViewTimezone) (LibreOfficeKitDocument* pThis, int nId, const char* timezone);
+
#endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
};
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index d70e4eb44d39..2ac398edd497 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -875,6 +875,17 @@ public:
mpDoc->pClass->sendContentControlEvent(mpDoc, pArguments);
}
+ /**
+ * Set the timezone of the window with the specified nId.
+ *
+ * @param nId a view ID, returned by createView().
+ * @param timezone a timezone in the tzfile(5) format (e.g. Pacific/Auckland).
+ */
+ void setViewTimezone(int nId, const char* timezone)
+ {
+ mpDoc->pClass->setViewTimezone(mpDoc, nId, timezone);
+ }
+
#endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
};
diff --git a/include/comphelper/lok.hxx b/include/comphelper/lok.hxx
index 66784e8e4892..4cfdb70a09d3 100644
--- a/include/comphelper/lok.hxx
+++ b/include/comphelper/lok.hxx
@@ -102,6 +102,9 @@ COMPHELPER_DLLPUBLIC const LanguageTag& getLanguageTag();
/// If the language name should be used for this LOK instance.
COMPHELPER_DLLPUBLIC bool isAllowlistedLanguage(const OUString& lang);
+/// Update the current LOK's timezone.
+COMPHELPER_DLLPUBLIC void setTimezone(bool isSet, const OUString& rTimezone);
+
// Status indicator handling. Even if in theory there could be several status indicators active at
// the same time, in practice there is only one at a time, so we don't handle any identification of
// status indicator in this API.
diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx
index c3b05b7927e5..90ddd52d01a4 100644
--- a/include/sfx2/lokhelper.hxx
+++ b/include/sfx2/lokhelper.hxx
@@ -91,6 +91,17 @@ public:
/// Set the device form factor that should be used for a new view.
static void setDeviceFormFactor(std::u16string_view rDeviceFormFactor);
+ /// Set timezone of the given view.
+ /// @isSet true to use @rTimezone, even if it's empty. Otherwise, no timezone.
+ /// @rTimezone the value to set (which could be empty).
+ static void setDefaultTimezone(bool isSet, const OUString& rTimezone);
+ /// Get timezone of the given view. See @setDefaultTimezone.
+ static std::pair<bool, OUString> getDefaultTimezone();
+ /// Set the timezone of the given view.
+ static void setViewTimezone(int nId, bool isSet, const OUString& rTimezone);
+ /// Get the timezone of the given view.
+ static std::pair<bool, OUString> getViewTimezone(int nId);
+
/// Iterate over any view shell, except pThisViewShell, passing it to the f function.
template<typename ViewShellType, typename FunctionType>
static void forEachOtherView(ViewShellType* pThisViewShell, FunctionType f);
diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx
index 8efa98a13e4f..a948f0f5baea 100644
--- a/include/sfx2/viewsh.hxx
+++ b/include/sfx2/viewsh.hxx
@@ -171,6 +171,8 @@ friend class SfxPrinterController;
LanguageTag maLOKLocale;
LOKDeviceFormFactor maLOKDeviceFormFactor;
std::unordered_set<OUString> mvLOKBlockedCommandList;
+ OUString maLOKTimezone;
+ bool maLOKIsTimezoneSet;
/// Used to set the DocId at construction time. See SetCurrentDocId.
static ViewShellDocId mnCurrentDocId;
@@ -403,6 +405,21 @@ public:
/// Get the LibreOfficeKit language of this view.
const LanguageTag& GetLOKLanguageTag() const { return maLOKLanguageTag; }
+ /// Get the LibreOfficeKit timezone of this view. See @SetLOKTimezone.
+ std::pair<bool, OUString> GetLOKTimezone() const
+ {
+ return { maLOKIsTimezoneSet, maLOKTimezone };
+ }
+
+ /// Set the LibreOfficeKit timezone of this view.
+ /// @isSet true to use @rTimezone, even if it's empty. Otherwise, no timezone.
+ /// @rTimezone the value to set (which could be empty).
+ void SetLOKTimezone(bool isSet, const OUString& rTimezone)
+ {
+ maLOKIsTimezoneSet = isSet;
+ maLOKTimezone = rTimezone;
+ }
+
/// Set the LibreOfficeKit locale of this view.
void SetLOKLocale(const OUString& rBcp47LanguageTag);
/// Get the LibreOfficeKit locale of this view.
diff --git a/sc/source/ui/view/viewfun6.cxx b/sc/source/ui/view/viewfun6.cxx
index 160ee6ce5882..2a68f730b9bf 100644
--- a/sc/source/ui/view/viewfun6.cxx
+++ b/sc/source/ui/view/viewfun6.cxx
@@ -21,6 +21,7 @@
#include <svx/svdocapt.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
+#include <sfx2/lokhelper.hxx>
#include <svl/stritem.hxx>
#include <svl/numformat.hxx>
#include <svl/zforlist.hxx>
@@ -47,6 +48,7 @@
#include <tabvwsh.hxx>
#include <scmod.hxx>
#include <postit.hxx>
+#include <comphelper/scopeguard.hxx>
#include <vector>
@@ -286,6 +288,23 @@ void ScViewFunc::InsertCurrentTime(SvNumFormatType nReqFmt, const OUString& rUnd
const SvNumFormatType nCurNumFormatType = (pCurNumFormatEntry ?
pCurNumFormatEntry->GetMaskedType() : SvNumFormatType::UNDEFINED);
+ const int nView(comphelper::LibreOfficeKit::isActive() ? SfxLokHelper::getView() : -1);
+ if (nView >= 0)
+ {
+ const auto [isTimezoneSet, aTimezone] = SfxLokHelper::getViewTimezone(nView);
+ comphelper::LibreOfficeKit::setTimezone(isTimezoneSet, aTimezone);
+ }
+
+ comphelper::ScopeGuard aAutoUserTimezone(
+ [nView]()
+ {
+ if (nView >= 0)
+ {
+ const auto [isTimezoneSet, aTimezone] = SfxLokHelper::getDefaultTimezone();
+ comphelper::LibreOfficeKit::setTimezone(isTimezoneSet, aTimezone);
+ }
+ });
+
if (bInputMode)
{
double fVal = 0.0;
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index 794dcc00b300..53c2abace8b5 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -76,6 +76,8 @@ namespace
LanguageTag g_defaultLanguageTag("en-US", true);
LanguageTag g_loadLanguageTag("en-US", true); //< The language used to load.
LOKDeviceFormFactor g_deviceFormFactor = LOKDeviceFormFactor::UNKNOWN;
+bool g_isDefaultTimezoneSet = false;
+OUString g_DefaultTimezone;
}
int SfxLokHelper::createView(SfxViewFrame* pViewFrame, ViewShellDocId docId)
@@ -339,6 +341,46 @@ void SfxLokHelper::setDeviceFormFactor(std::u16string_view rDeviceFormFactor)
g_deviceFormFactor = LOKDeviceFormFactor::UNKNOWN;
}
+void SfxLokHelper::setDefaultTimezone(bool isSet, const OUString& rTimezone)
+{
+ g_isDefaultTimezoneSet = isSet;
+ g_DefaultTimezone = rTimezone;
+}
+
+std::pair<bool, OUString> SfxLokHelper::getDefaultTimezone()
+{
+ return { g_isDefaultTimezoneSet, g_DefaultTimezone };
+}
+
+void SfxLokHelper::setViewTimezone(int nId, bool isSet, const OUString& rTimezone)
+{
+ std::vector<SfxViewShell*>& rViewArr = SfxGetpApp()->GetViewShells_Impl();
+
+ for (SfxViewShell* pViewShell : rViewArr)
+ {
+ if (pViewShell->GetViewShellId() == ViewShellId(nId))
+ {
+ pViewShell->SetLOKTimezone(isSet, rTimezone);
+ return;
+ }
+ }
+}
+
+std::pair<bool, OUString> SfxLokHelper::getViewTimezone(int nId)
+{
+ std::vector<SfxViewShell*>& rViewArr = SfxGetpApp()->GetViewShells_Impl();
+
+ for (SfxViewShell* pViewShell : rViewArr)
+ {
+ if (pViewShell->GetViewShellId() == ViewShellId(nId))
+ {
+ return pViewShell->GetLOKTimezone();
+ }
+ }
+
+ return {};
+}
+
/*
* Used for putting a whole JSON string into a string value
* e.g { key: "{JSON}" }
diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx
index 1d494878a0a2..cd4ffe676f2b 100644
--- a/sfx2/source/view/viewsh.cxx
+++ b/sfx2/source/view/viewsh.cxx
@@ -1083,6 +1083,10 @@ SfxViewShell::SfxViewShell
maLOKLanguageTag = SfxLokHelper::getDefaultLanguage();
maLOKLocale = SfxLokHelper::getDefaultLanguage();
+ const auto [isTimezoneSet, aTimezone] = SfxLokHelper::getDefaultTimezone();
+ maLOKIsTimezoneSet = isTimezoneSet;
+ maLOKTimezone = aTimezone;
+
maLOKDeviceFormFactor = SfxLokHelper::getDeviceFormFactor();
vcl::Window* pFrameWin = pViewFrame->GetWindow().GetFrameWindow();