LibreOffice Module test (master) 1
lokcallback.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include <test/lokcallback.hxx>
11
12#include <LibreOfficeKit/LibreOfficeKitEnums.h>
13#include <rtl/strbuf.hxx>
14#include <tools/gen.hxx>
15#include <comphelper/lok.hxx>
16#include <sfx2/viewsh.hxx>
17
18TestLokCallbackWrapper::TestLokCallbackWrapper(LibreOfficeKitCallback callback, void* data)
19 : Idle("TestLokCallbackWrapper flush timer")
20 , m_callback(callback)
21 , m_data(data)
22{
23 // Flushing timer needs to run with the lowest priority, so that all pending tasks
24 // such as invalidations are processed before it.
25 SetPriority(TaskPriority::LOWEST);
26}
27
29{
30 m_viewId = -1;
31 m_updatedTypes.clear();
33}
34
36{
37 if (!IsActive())
38 Start();
39}
40
41constexpr int NO_VIEWID = -1;
42
43inline void TestLokCallbackWrapper::callCallback(int nType, const char* pPayload, int nViewId)
44{
45 discardUpdatedTypes(nType, nViewId);
46 m_callback(nType, pPayload, m_data);
47 startTimer();
48}
49
50void TestLokCallbackWrapper::libreOfficeKitViewCallback(int nType, const char* pPayload)
51{
52 callCallback(nType, pPayload, NO_VIEWID);
53}
54
56 int nViewId)
57{
58 callCallback(nType, pPayload, nViewId);
59}
60
62 const tools::Rectangle* pRect, int nPart, int nMode)
63{
64 OStringBuffer buf(64);
65 if (pRect)
66 buf.append(pRect->toString());
67 else
68 buf.append("EMPTY");
70 {
71 buf.append(", ");
72 buf.append(static_cast<sal_Int32>(nPart));
73 buf.append(", ");
74 buf.append(static_cast<sal_Int32>(nMode));
75 }
76 callCallback(LOK_CALLBACK_INVALIDATE_TILES, buf.makeStringAndClear().getStr(), NO_VIEWID);
77}
78
79// TODO This is probably a pointless code duplication with CallbackFlushHandler,
80// and using this in unittests also means that CallbackFlushHandler does not get
81// tested as thoroughly as it could. On the other hand, this class is simpler,
82// so debugging those unittests should also be simpler. The proper solution
83// is presumably this class using CallbackFlushHandler internally by default,
84// but having an option to use this simpler code when needed.
85
87{
88 if (std::find(m_updatedTypes.begin(), m_updatedTypes.end(), nType) == m_updatedTypes.end())
89 {
90 m_updatedTypes.push_back(nType);
91 startTimer();
92 }
93}
94
96 int nSourceViewId)
97{
98 const PerViewIdData data{ nType, nViewId, nSourceViewId };
100 // The source view doesn't matter for uniqueness, just keep the latest one.
101 auto it = std::find_if(l.begin(), l.end(), [data](const PerViewIdData& other) {
102 return data.type == other.type && data.viewId == other.viewId;
103 });
104 if (it != l.end())
105 *it = data;
106 else
107 l.push_back(data);
108 startTimer();
109}
110
112{
113 // Invoke() will call flushPendingLOKInvalidateTiles().
114 startTimer();
115}
116
118{
119 // If a callback is called directly with an event, drop the updated flag for it, since
120 // the direct event replaces it.
121 for (auto it = m_updatedTypes.begin(); it != m_updatedTypes.end();)
122 {
123 if (*it == nType)
124 it = m_updatedTypes.erase(it);
125 else
126 ++it;
127 }
128 // If we do not have a specific view id, drop flag for all views.
129 bool allViewIds = false;
130 if (nViewId < 0)
131 allViewIds = true;
132 if (nType == LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR
134 allViewIds = true;
135 for (auto it = m_updatedTypesPerViewId.begin(); it != m_updatedTypesPerViewId.end();)
136 {
137 if (it->type == nType && (allViewIds || it->viewId == nViewId))
138 it = m_updatedTypesPerViewId.erase(it);
139 else
140 ++it;
141 }
142}
143
145{
146 if (m_updatedTypes.empty() && m_updatedTypesPerViewId.empty())
147 return;
148 // Ask for payloads of all the pending types that need updating, and call the generic callback with that data.
149 assert(m_viewId >= 0);
150 SfxViewShell* viewShell = SfxViewShell::GetFirst(false, [this](const SfxViewShell* shell) {
151 return shell->GetViewShellId().get() == m_viewId;
152 });
153 assert(viewShell != nullptr);
154 // First move data to local structures, so that callbacks don't possibly modify it.
155 std::vector<int> updatedTypes;
156 std::swap(updatedTypes, m_updatedTypes);
157 std::vector<PerViewIdData> updatedTypesPerViewId;
158 std::swap(updatedTypesPerViewId, m_updatedTypesPerViewId);
159
160 for (int type : updatedTypes)
161 {
162 std::optional<OString> payload = viewShell->getLOKPayload(type, m_viewId);
163 if (payload)
164 libreOfficeKitViewCallback(type, payload->getStr());
165 }
166 for (const PerViewIdData& data : updatedTypesPerViewId)
167 {
168 viewShell = SfxViewShell::GetFirst(false, [data](const SfxViewShell* shell) {
169 return shell->GetViewShellId().get() == data.sourceViewId;
170 });
171 assert(viewShell != nullptr);
172 std::optional<OString> payload = viewShell->getLOKPayload(data.type, data.viewId);
173 if (payload)
174 libreOfficeKitViewCallbackWithViewId(data.type, payload->getStr(), data.viewId);
175 }
176}
177
179{
180 // Timer timeout, flush any possibly pending data.
181 for (SfxViewShell* viewShell = SfxViewShell::GetFirst(false); viewShell != nullptr;
182 viewShell = SfxViewShell::GetNext(*viewShell, false))
183 {
184 viewShell->flushPendingLOKInvalidateTiles();
185 }
186 flushLOKData();
187}
188
189/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void Start(bool bStartTimer=true) override
static SAL_WARN_UNUSED_RESULT SfxViewShell * GetNext(const SfxViewShell &rPrev, bool bOnlyVisible=true, const std::function< bool(const SfxViewShell *)> &isViewShell=nullptr)
static SAL_WARN_UNUSED_RESULT SfxViewShell * GetFirst(bool bOnlyVisible=true, const std::function< bool(const SfxViewShell *)> &isViewShell=nullptr)
virtual std::optional< OString > getLOKPayload(int nType, int nViewId) const
bool IsActive() const
void SetPriority(TaskPriority ePriority)
virtual void libreOfficeKitViewUpdatedCallback(int nType) override
Definition: lokcallback.cxx:86
virtual void libreOfficeKitViewUpdatedCallbackPerViewId(int nType, int nViewId, int nSourceViewId) override
Definition: lokcallback.cxx:95
void discardUpdatedTypes(int nType, int nViewId)
virtual void libreOfficeKitViewCallbackWithViewId(int nType, const char *pPayload, int nViewId) override
Definition: lokcallback.cxx:55
virtual void Invoke() override
virtual void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle *pRect, int nPart, int nMode) override
Definition: lokcallback.cxx:61
std::vector< int > m_updatedTypes
Definition: lokcallback.hxx:55
virtual void libreOfficeKitViewCallback(int nType, const char *pPayload) override
Definition: lokcallback.cxx:50
TestLokCallbackWrapper(LibreOfficeKitCallback callback, void *data)
Definition: lokcallback.cxx:18
void callCallback(int nType, const char *pPayload, int nViewId)
Definition: lokcallback.cxx:43
LibreOfficeKitCallback m_callback
Definition: lokcallback.hxx:52
void clear()
Discard all possibly still held events.
Definition: lokcallback.cxx:28
virtual void libreOfficeKitViewAddPendingInvalidateTiles() override
std::vector< PerViewIdData > m_updatedTypesPerViewId
Definition: lokcallback.hxx:62
rtl::OString toString() const
constexpr int NO_VIEWID
Definition: lokcallback.cxx:41
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
QPRO_FUNC_TYPE nType
ResultType type