Age | Commit message (Collapse) | Author |
|
These are just locals, except for IniLnge which is set once in the
ctor and is then immutable
Change-Id: I0d8ac0c3ca729003a3575dea39b2746dfc53b4bc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164173
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
|
|
Change-Id: I09dea90e3e3f3fd0a4047b989329a027f788f695
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164148
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
|
|
Change-Id: I2c8ad9999adc406dc850c59b48e49681099dc054
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164147
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
|
|
so fold it into the ctor
Change-Id: If063143ef47a8ab293edf3896fb51079d0e0284f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164144
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
|
|
Like this since 2016 with 3a0abd3019ec3ca29b8f1378cdb32ebf741e6306
add SvxSearchItem::GetWildcard() SetWildcard()
Change-Id: Id988a6e58488af6b1f274a318e9d1f52c7a8b169
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163876
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
Tested-by: Jenkins
|
|
With ItemInfoPackages we now can have a buffered, static
global translation table from SlotIDs to WhichIDs since
the ItemInfoStatic used already contains all the needed
information.
Register that in registerItemInfoPackage at the Pool and
use it for lookup. That speeds up the lookup from O(n)
to O(1). Since that lookup is used in UI and UNO API
implementations this has positive effect on load/safe,
but also all interactive stuff in the whole office.
NOTE: I tried to use a merged version of that translation
table in the parent pool, but this shows double SlotIDs,
what is no wonder since that's what those are used for:
To get different WhichIDs for a SlotID in Item handling.
This *might* prevent getting rid of the chanined Pools
at all - sadly. The returned WhichID directly depends
on which Pool the function(s) GetWhichIDFromSlotID and
GetTrueWhichIDFromSlotID are called.
NOTE: Very strange is that the parameter 'bDeep' in that
functions is *not* passed down to the call to the
secondary Pool - probably an error, but risky to fix,
that may change already the behaviour :-(
Change-Id: Iea77ffad0f6a5401ab74fea0bbfc2589c66680ea
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163597
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
Change-Id: I51585f1c15984a066262023184f668662853d20f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163556
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
...instead of regular blank
Do not modify other blanks (thousand separator, fraction separator)
Change-Id: I82f8023a4e55d8091545191dee55a88aba25dbdd
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161737
Tested-by: Jenkins
Reviewed-by: Laurent Balland <laurent.balland@mailo.fr>
|
|
Change-Id: Ie18f18655e4ee9ca70580b540678003a12b0465d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163458
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
Secured usage of FontList in SvxFontListItem
usage (a test)
Change-Id: I412a7681b3ece4e5d3751165d4b566ccdf5b2da9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163257
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
Driving forward the Item reworks I now take the
ItemPool in focus: It now does not hold any items
anymore and should be renamed to something like
ItemInfoProvider/ItemHelper, since it's main purpose
is to provide the Defaults for the Item functionality.
There is that SfxItemInfo, only a struct and bundling
SlotID and ItemFlags. There are also the DefaultItems,
just handled as ptrs in an array. It is/was always
error-prone to keep these in sync. Remember that it's
also necessary for the order to not only being sorted
but being increments of one with no gaps allowed in
the WhichIDs to which the Items are bound.
I now bundled that to a new class ItemInfo that joins
WhichID, SlotID, ItemFlags and the default Item. This
is a pure virtual base class, it comes in three
derivations:
(1) ItemInfoStatic:
This is supposed to be global static and hosts the
Item in a std::unique_ptr to ensure cleanup. It is
designed to be constructed once during runtime and
being shared globally. It allows the ItemPtr to be
nullptr to mark as non-static (if initial static is
not possible for some reason) but still offers the
needed data. Most cases (95%+) are of that case.
The contained Item is owned by that instance. The
flag isStaticDefault() is set at the Item.
(2) ItemInfoDynamic:
This is supposed to be used for cases where the Item
cannot be static: Mainly for SfxSetItem (that needs
a Pool itself in the contained SfxItemSet, so lifetime
is bound to that Pool), but other cases showed up in
the transition. These instances live while the Pool
lives and get destructed when the Pool goes down.
Also uses std::unique_ptr for the Item instance for
as much automated cleanup as possible, the contained
Item is owned by that instance, the instance by the
Pool. The flag isDynamicDefault() is set at the Item.
(3) ItemInfoUser:
This is used for UserDefaults that can be set for
every ItemInfo entry to 'overshadow' the default
from the 'outside'. It uses a regular Item and
the central access methods implCreateItemEntry/
implCleanupItemEntry to manage the Item instance,
thus works like a SfxPoolItemHolder. The Item
instance can be globally shared and re-used even
when the Pool goes down. Instances belong to the
Pool and are cleaned up when the Pool goes down.
This Item does not need any further flag to be
set.
The ItemInfos are organized using a class
called ItemInfoPackage:
This bundles groups of ItemInfoStatic to
functional instances. There are derivations/
implementations of this e.g. for Writer ItemPool
bundling all the needed defaults for Writer,
similar for draw/impress, Calc and other usages.
These ItemInfoPackage can be 'registered' at an
ItemPool using it's method registerItemInfoPackage.
This does all the needed stuff to setup that
group of ItemInfos at the Pool (It even sets
internal vars First/LastWhich, that info can just
be derived from the buildup ItemInfo Ptrs).
The ItemInfoPackage has methods 'size()' and
'getItemInfo(index) to allow looping over it
and deliver the infos the Pool needs. The
(forced, pure virtual) overloads of getItemInfo
in the specific implementations check for the
ItemPtr being nullptr and create a exclusive
incarnation of ItemInfoDynamic for the Pool if
needed, returning that. The Pool owns the
ItemInfoDynamic incarnations and uses the
ItemInfoStatic directly. On shutdown it cleans
up the ItemInfoDynamic as needed.
The ItemInfoUser is used by the Pool when a
UserDefault is set/used: for SetUserDefaultItem,
GetUserDefaultItem, ResetUserDefaultItem. It
is not held in a 2nd list, but directly in the
list of ItemInfo'ptrs: To keep track of this
an unordered_map is used that helds the original
ItemInfo associated with the WhichID. That way
no two lookups (as before) are needed to get the
current Pool's default for any WhichID.
The derivations of ItemInfoPackage are
encapsulated and just allow access to an
ItemInfoPackage& with a single method as
return value. All use a static local instance
of a std::array<ItemInfoStatic, FIXED_SIZE>
which constructs all ItemInfoStatic and the
static Item instances - if already possible.
Sometimes it is necessary to overload the
constructor to set some static instances
for Items later than the lib init. These are
also just marked with nullptr as Item instance.
Some need to overload getItemInfo to complete
instances of ItemInfoStatic, if needed, or
create and deliver instances of ItemInfoDynamic.
The registerItemInfoPackage also offers a
optional lambda callback: there were two cases
where local data from the Pool was needed to
incarnate the item - just add that to the
call to registerItemInfoPackage if needed,
see examples in the adapted code.
For the re-use of Items this means that now
in SfxItemSet/SfxPoolItemHolder *true* static
Items can and will be used without RefCount
directly and globally. This is also the case
for dynamic Items, with the exception of
differing Pools for SfxSetItems which cannot
be done.
Future:
That design is already prepared to allow
solving that Pool-chaining problem: currently
there are master/sub-pools and all accesses
have to traverse that structure before even
doing anything.
For the future the idea is more to 'compose'
a Pool by registering ItemInfoPackages, e.g.
for Writer pool you may start with SfxItemPool,
register the writer-specific ItemInfoPackage,
then the one for DrawingLayer (if needed) and
the one for EditEngine.
It should also be possible to get to smaller
granularities of that packages. Ideas for
new ones will emerge. We might also think
about composing Pools which can e.g. run Writer
and Chart, so allowing to use Chart *without*
OLE stuff in Writer - just ideas...
More changes:
- Adapted all stuff, cleaned up old stuff/
definitions
- Removed FreezeIdRanges, that can be done
once per Pool on-demand (and cannot be
forgotten to be called)
- Merged XOutdevItemPool with SdrItemPool
and offered a ItemInfoPackage which joins
both needed sets of Items
- All the cleanup hassle with Pools and
defaults cleaned up
- Adapted all access methods of the pool
to use that new stuff. Pool chaining
currently stays, but I use a central
method 'getTargetPool' instead of
recursive calling to get the correct
Pool for the action
Change-Id: I2b8d3d4c3cc80b1d0d0b3c0f4bd90d7656b4bab7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/163157
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
... everywhere it is used to generate material for encryption.
Change-Id: Id3390376bb2f3a5fa1bbfd735850fce886ef7db2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162873
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
|
|
Sorted out some methods at ItemPool which process
Defaults to make more clear what is going on and
what which method is doing.
Change-Id: I2568d3e03d0a56a14b6fe4e04521e1a8e22c000b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162643
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
DER rules say that BOOLEAN values are either FALSE (0x00)
or TRUE (0xff)
Change-Id: I59f57557fbc4d6447e0d8e994b04adda1ee8c1a9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162597
Tested-by: Noel Grandin <noel.grandin@collabora.co.uk>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
|
|
Obsoleted by commit 2484de6728bd11bb7949003d112f1ece2223c7a1 (Remove
non-const Sequence::begin()/end() in internal code, 2021-10-15) and
commit fb3c04bd1930eedacd406874e1a285d62bbf27d9 (Drop non-const
Sequence::operator[] in internal code, 2021-11-05).
Change-Id: Idbafef5d34c0d4771cbbf75b9db9712e504164cd
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162640
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
|
|
Change-Id: Ibdfbb8c6492d18989d587230db674a7ff2546150
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162574
Tested-by: Julien Nabet <serval2412@yahoo.fr>
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
|
|
Change-Id: I99f9730e573f06e53516d0d775df1b276ff83a90
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162573
Tested-by: Julien Nabet <serval2412@yahoo.fr>
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
|
|
Change-Id: I49afb3957c5633f82431408402bead2a9b0328a7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162572
Tested-by: Julien Nabet <serval2412@yahoo.fr>
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
|
|
Change-Id: I12f0cbbc1523a7451281ef501b51b56010105dfd
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162570
Tested-by: Julien Nabet <serval2412@yahoo.fr>
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
|
|
Change-Id: Idb09d903b97ca9697ac473b46ae85b2205be128a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162569
Tested-by: Julien Nabet <serval2412@yahoo.fr>
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
|
|
Change-Id: Ia769e28fa1180c40f0e25763485a7b468d1f8f94
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162568
Tested-by: Julien Nabet <serval2412@yahoo.fr>
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
|
|
Unfortunately I had overseen something with derived
classes, but it came now up on CI ASan/UBsan build
with a failing UnitTest - thanks to pointing me at
it.
The ItemInstanceManager at the SfxPoolItems are now
no longer static but constructed instances returned
on-demand.
Also added checks to really use an incarnated/
registered one *only* for that derivation and made
sure this is now correctly supported.
Had to change again, using createItemInstanceManager
to always create instances was less effective than
intended, back to getItemInstanceManager & static
instances in the Item implementations. Also added
some stuff to implCreateItemEntry/implCleanupItemEntry
to be more effective, e.g. direct handling of
slot stuff in latter one. Also some more asserts
and comments. Slot stuff is now handled without
RefCounting, takes some write accesses away...
Change-Id: I6cd69556b416510b5b23549dd042ff3ba155559d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162521
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
As addition to tdf#158605 I have added a
global default mechanism to support global
sharing of Item instances. It's automated
and complements the existing one, see one
of the last commits. All in all there are
now the following possibilities to support
this for individual Item derivations:
(1) Do nothing: In that case, if the Item
is shareable, the new mechanism will kick
in: It will start sharing the Item globally,
but not immediately: After a defined amount
of allowed non-shared ocurrences (look for
NUMBER_OF_UNSHARED_INSTANCES) an instance
of the default ItemInstanceManager, a
DefaultItemInstanceManager, will be incarnated
and used. NOTE: Mixing shared/unshared
instances is not a problem (we might even
implement a kind of 're-hash' when this
kicks in, but is not really needded).
(2) Overload getItemInstanceManager for
SfxPoolItem in a class derived from
SfxPoolItem and...
(2a) Return a static incarnation of
DefaultItemInstanceManager to immediately
start global sharing of that Item derivation.
(2b) Implement and return your own
implementation and static incarnation of
ItemInstanceManager to do something better/
faster that the default implementation can#
do. Example: SvxFontItem, uses hashing.
The NUMBER_OF_UNSHARED_INSTANCES is currently
at (50) which gives a decent relationship
bewteen no global sharing (speed) and memory
needs. Not sharing is faster (that access to
'find' an equal item is spared which might be
costly), sharing again needs less memory.
There are two supported ENVVARs to use:
(a) SVL_DISABLE_ITEM_INSTANCE_MANAGER:
This disables the mechanism of global Item
sharing completely. This can be used to test/
check speed/memory needs compared with using
it, but also may come in handy to check if
evtl. errors/resgrressions have to do with
it.
(b) SVL_SHARE_ITEMS_GLOBALLY_INSTANTLY:
This internally forces the
NUMBER_OF_UNSHARED_INSTANCES to be ignored
and start sharing ALL Item derivations
instantly.
Change-Id: I40d9c5f228f0bcbf239f2ce0a02d423054240570
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162478
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
Change-Id: Ieaba8db5df426ed30aca7366a86ee4fb11e03a44
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162480
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
|
|
The task shows that the commit including the Item
paradigm change has follow-ups: It now does no
longer try to share Items as much as possible
(detailed reasons in that commit). Mainly for speed
reasons since that sharing was done before by
(mostly) linearly searching in existing instances
registered at one Pool, using the operator== of the
SfxPoolItems. That costs runtime.
There is somewhere a sweet-spot between memory and
runtime: the number of Items allocated and the time
spent to share them more effectively. This task shows
- despite being a non-real-world document - that
for extremes like this putting work in sharing is
still needed.
But there are possibilities to combine both: If we
can implement solutions that do not need much time
to ideintify an aleady existing instance we will get
the best of both worlds.
As explained already in that change, if we would
need that again, then on a better base. Thus I drove
forward ITEM changes to a state where we are now able
to share Items globally in the office - not per pool
but for all ItemSets/ItemHolders and thus all Apps/
Models/opened documents.
NOTE: This currently needs to include the WhichID
that is included in the Item, so cannot share pure
Item-data (as the old usage did too). This does not
need to stay that way: If you think about it, the
association between WhichID and Pool/Holder is
defined in Pool/Holder, so theoretically the Item
does not need to contain the WhichID. This will
be hard to do due too many places in the code that
use the WhichID stored at the Item.
To support that I added an ItemInstanceManager with
a simple interface (find/add/remove) and it's usage
in the two central Item-existance managing methods
implCreateItemEntry/implCleanupItemEntry. The
interface is pure virtual and all methods private,
only the mentioned managing methods are allowed to
access these. Also added a virtual method to
SfxPoolItem called getItemInstanceManager() that
can be implemented by Items that want to support
that.
Also added a default implementation of
ItemInstanceManager called DefaultItemInstanceManager
that uses linear search using operator== from the
Item that can be used/added to every Item easily.
It works for all Items and does in principle what
the former implementation does. It is intended as
simple/fast fallback.
I also added a statistic element to measure the most
used non-RefCounted Items on an Office-run, this
will be printed at office shutdown using SAL_LOG
and the 'svl.items' flag.
I then checked all Items that were used in this
error/bug scenario that used an extensive number
of incarnations and added an ItemInstanceManager
for these.
For SvxFontItem I added one that creates a hash and
thus needs not to search for instances at all, with
the caveat that the WhichID needs to be included.
Thus the hash is not at the Item, but only in the
ItemInstanceManager implementation.
For SfxBoolItem I implemented one that hashes using
the WhichID and holding both possible states in an
associated std::pair, true and false, thus the
SfxBoolItem is identified fast and only two instances
per WhichID exist (when used in Pool/Holder).
For 11 other Items I just added using the standard
implementation, DefaultItemInstanceManager. Of
course the more we optimize the better it will get.
For all Items where I added that mechanism I also
added ASSERT_CHANGE_REFCOUNTED_ITEM to all write
calls/methods for that Item. It asserts when the
RefCounted Item is to be changed. This should be
done in all write accesses to Items, but we have
ca. 500 derivations.
NOTE: There was *one* place I found where that
was already done -> was alredy seen as problem,
but not really adressed.
Despite this example file is not representative,
it is still a start to init this new instance
re-use of Items.
I am already thinking about doing that globally,
depending on the usage number (maybe combined with
sizeof(item)). There is no argument to not even
change strategy at runtime when a specific number
of incarnations of one Item derivation is reached,
but this is not part of this fix.
Change-Id: Ie56cf40e0341f98dcbf29cf5c06368316829415e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162402
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
An instance of SfxVoidItem(0) was used to signal
the SfxItemState::DISABLED. This was done not only
using WhichID == 0, but using isVoidItem() at the
SfxPoolItem. Unfortunately this mixes up with usages
of SfxVoidItems, mostly for UI stuff/Slots.
This also means that all the time an SfxVoidItem
had to be cloned/delete when when added/removed
from ItemSet or ItemHolder. Much more action than
e.g. for INVALID_POOL_ITEM which we already use
by havong just a simple ptr to a single static
instance of an Item. Disabled should do the same
thing.
Unfortunately also the functionality was mixed
with non-SfxItemState::DISABLED purposes and these
were very hard to be separated.
But the current solution works now after some
quirks doing that. It even oes no more need the
isVoidItem() flag at the SfxPoolItem.
Change-Id: I99f03db144f541ae4ea35f3775b3b3d58a375a81
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162414
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
After some experiments I now can remove
DirectPutItemInPool and DirectRemoveItemFromPool.
With the changes done before it is now possible to
get rid of this 'compromize'. Now there are no
more Items held at the 'Pool' which now can be
developed in the direction of ssth like
'SfxItemSupport' - what it really is.
Some of the last usages of DirectPutItemInPool were
in SvxAreaTabDialog::SavePalettes(), so I tried to
trigger those cases with using LO and calling that
Dialog in all situations I could possibly think
about, but it was never used.
Then I added asserts and run a UnitTests in the apps,
also no luck. Thus I would guess these are not used.
These put changed stuff from the Dialog 'directly' to
the Pool (what is not really supported and is a hint
for a 'compromize' that some functionality did not
find/want to use the right spot in the model to save
and hold that data). Thus it *would* be accessible
using the SurrogateMechanism at the Pool (which is
also a 'compromize', see some of my other commits),
but I also found no hints at places where that is
done.
Thus I decided to create this change and let's see
if that asserts ever get triggered in the builds
or tests.
Indeed did not trigger. I checked what other places
do which use SfxObjectShell::Current() when they get
no DocShell: Most avoid doing something, but none
puts stuff to the Pool, so I go one step further
and do what other places do: warn and return. Also
simplified SvxAreaTabDialog::SavePalettes() as then
feasible.
Change-Id: I1c351eac4ada26288a56a69d57008a09f2d19121
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162340
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
It is used in SC, DirectPut* in Pool, fetched using
Surrogates, all bad. Only to transport data over the
Pool, may not even need to be an Item.
Trying to solve/losen that gordian knot, looks good.
Is now a normal data holder class, could find a good
parent for it that the Dialog and the instances
setting up/using that Dialog can use.
Forgot to reset that data instance in one place, but
also checked in-between a version that still used the
Item to excluse that the Poolis the same, but the
ScTabViewShell does change. FOund an error with
SfxPoolItemHolder when reseting, also changed.
Change-Id: I1c99d675d1cc3d21205c3e2df78d4b52a696e7ee
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162313
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
Change-Id: I26d745efecc29fe28e32dfc6b6a2ebe3c3bfd2e7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162329
Tested-by: Jenkins
Reviewed-by: Taichi Haradaguchi <20001722@ymail.ne.jp>
|
|
ItemSurrogates are a possibility to iterate over
all SfxPoolItems associated with a WhichID at a
ItemPool to collect or change data.
It is in general not a good idea: the correct action
would be to iterate over the model data and change/
adapt/collect data on the Items of the type
in question. This is because the *assumtion* that you
iteate over all the Items associated with a document
model is *not* correct:
The ItemPool of the model is used for various ItemSets,
e.g. Dialogs/Sidebar and others, so you might get Items
not only from the DocumentModel but from elsewhere.
You might even get Items from *other* models, so
changing these might have unpredictable effects (!)
It is clear to me that this mechanism is more convenient
that iterating over the document models, and it might
have been invented due to this and then used in more
and maore cases. There should be a lambda/callback-based
mechanism in every document model to do this. Until then
we have to live with this 'compromize'. There are over
100 usages currrently, so no way to easily replace this.
For those reasons I changed this to be more safe: There
are two methods to do this now:
1: iterateItemSurrogates to allow read/write access. I
identified six places where that mechanism was used
to change SfxPoolItems, with the use of const_cast.
This now offers a lambda/callback mechanism and the
needed data in a helper (SurrogateData). Internally
it iterates over ItemSets and ItmHolders registered
and thus associated with the Pool. Changing an Item
means to set a changed Item at the Pool/replace the
holder.
2: GetItemSurrogates/FindItemSurrogate to allow
read-only iteration (2nd one with filter). This
collects the Items in a vector that you provide over
which you can then iterate. Do *not* use const_cast
and change the Item when using this (!)
Note that mechanism (2) pe-filters the Items so that
you get each only once: Of couse one Item can be set
in more than one ItemSet/Holder (but also in more than
one model). This filtering is not possible for (1), you
have to evtl. do the same replace action for the same
item, but this is the only way to not change Items that
are associated wth another model.
Note that (2) could also be changed to a lambda/callback
mechanism similar to (1), but there are too many places
that would beed to be adapted. That would have the
advantage to not need to pre-collect the candidates in a
first run.
Also removed/replaced FindItemSurrogate with using
GetItemSurrogates and locally filtering with that needle.
That also made me remove/cleanup CollectSurrogates, it's
only used in one place now.
Change-Id: I0fe2f51f4fca45e1e5aea032cb96bb77b4567f4d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162254
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
The ::Put methods at SfxItemSet had an extra WhichID
parameter that was not really documented, but I would
guess often asked why it exists: An extra WhichID, just
called 'nWhich' (which makes things NOT clearer). That
is 'strange' since the Item given to be put already
internally has a WhichID, so why a 2nd one?
If you were really interested and read all that code
(no, no comments on that anywhere) you might know
that this a kind of 'Target-WhichID' under which
the Item shall be put to the ItemSet. Since this
is unclear for most people it is even dangerous and
explains why so many code places just hand over the
WhichID requsted from the Item that already gets
handed over.
To make it short: I removed that. For the 19 places
where this was really needed I added a new method
besides ::Put called ::PutAsTargetWhich that takes that
extra WhichID (now called TargetWhich) and takes the
needed actions. These are quite some because that may
be combined with the bPassingOwnership flag, see new
SfxItemSet::PutImplAsTargetWhich method.
This makes usage of ItemSets/Items less dangerous. It
also simplifies and thus makes safer the central helpers
implCreateItemEntry/implCleanupItemEntry which have some
less cases to handle.
Debugged the failing UnitTests showed that there is
an incarnate Item != SfxVoidItem that causes problems.
I checked for errors in the change, but no luck.
Afterr some time I found out that a ::Clone
implementation caused the problem: These need to
also copy the WichID of the original, but the
SfxFrameItem failed to do so. This did not cause
problems in the former version because
implCreateItemEntry was designed to set a missing/
different WhichID.
I corrected that in SfxFrameItem, also removed not
needed costructor that caused that. Also added a
SAL_WARN and a correction in implCreateItemEntry.
I could have added an assert (did so for running
local UnitTests), but should be enough.
NOTE: When hunting for Items except SfxVoidItem
that get crerated using a WhichID '0' i learned
that this indeed happens: There are some (5) calls
to SfxRequest::SetReturnValue that incarnate an
SfxBoolItem with WhichID '0' (ZERO). This is not
good and I think about how to change that...
Change-Id: I9854a14cdc42d1cc19c7b9df65ce74147d680825
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162124
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
Change-Id: Ic65f4cff636d67d94cb0cafc4f75f3bb57190c99
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161976
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
Tested-by: Jenkins
|
|
Currently a Pool-Attribute (in SfxItemInfo), but should
be a SfxPoolItem property. Originally 'moved' from old
'poolable' used as hint. I identified needs more general
and moved it to where it belongs.
Also reworked SfxItemInfo to no longer have/support
single bollean flags, but a FlagVariable and defined
SFX_ITEMINFOFLAG_* entries to access these, that will
make future changes easier without having to change
all palces where these get defined over and over again.
Added CheckItemInfoFlag for gereral access to that flag
and e.g. NeedsSurrogateSupport to directly check for
the SFX_ITEMINFOFLAG_SUPPORT_SURROGATE flag as syntactical
sugar, that makes the intention clear.
Change-Id: I09c238c7c5b7f721b657d7b0a44dbc8d14e02528
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161982
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
Change-Id: I49ab7a48e74055264037d6930692fdae8be6d3ee
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162022
Tested-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
|
|
... and detect overflow to result in text instead of 00:00 input loss.
Change-Id: Ib2b9f16ab6c3c2963c5a2058c27366219f090096
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161977
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
|
|
The issue is that the flag RegisteredAtPool
at the SfxPoolItem is Pool-dependent: It marks that
the Item is registeres at *one* Pool/Model. This
makes it Pool-dependent. Due to this there is no way
to share Items that need to be registered globally/
in multiple Pools/Models what is one of the goals
for optimal sharing.
We can also not live without having access to all
Items associated with the Pool, due to mechanisms
in place like the Surrogate stuff.
This again is used for two purposes:
(1) Access all Items associated with one Pool/Model,
at least that is the assumption. This is not valid
since it gets corrupted with a single ItemSet/Holder
used that does not host model data, e.g. an open
Dialog or the Sidebar (or...). But works in
principle.
(2) Access extra-Items that are held nowhere and
are created using DirectPutItemInPool, e.g. infos
for a Dialog. These would need a instance/place to
host them, the Pool is (ab)used for that.
Both are 'compromizes' (to not use a more bad word)
and should not exist. (1) should iterate over the
Model and do actions. There are even places that
use (1) to *change* Items, by casting them to
non-const, even RefCounted ones, so having no control
over what all might be changed doing so. Since we
talk about ca. 100+ places there is no way to get
away from this - I can imagine how this happened:
The 'poolable' attr traditionally needed for the old
binary format was one day 'used' to not need to
iterate over the Model, an API was added to access
and this usage was copied. Sigh..
It is even used when ODF is loaded: E.g. the
FillStyle is imported from XML, interpreted, and
put into an ItemSet. Then it gets set at the
XShape using UNO API and a *name* -> that name and
the Surrogate mechanism is used to find and set the
FillStyle at the Model Object. The FillStyle could
probably just be set using UNO API and the data
directly.
The association between Model/Pool and Item is
created by the object hosting the Item, these are
ItemSets and ItemHolders. Thus it is possible to
register these at the Pool. This allows to iterate
and collect the Items associated with the Pool
and keep the Surrogate mechanism alive.
This is the main change done here. It limits
the registrations to Items for which (at the Pool)
the NeedsPoolRegistration is set, also
Item-independent. Speed is okay, I saw no big
changes in my tests here. The registration is
just pointers, no ownership or RefCounting needed
here.
The advantage is that Items get closer to be
shared office-wide, they can be referenced by
multiple ItemSets (RefCnt) associated with
different Pools/Models.
NOTE: This is not true for SfxSetItems, these are
and will stay Pool-dependent due to their need
to a Pool in the contained ItemSet.
Note that we have ca. six deivations of SfxSetItem,
but ca. 500+ Item derivations, so not too bad.
For the usages of Surrogates to change existing,
RefCounted Items: These can now at least be
changed - if they show up to be problematic - to
iterate over the registered ItemSets and change
Items there the correct way: Set a changed one
at the ItemSet. That also allows Objects to
*react* on ItemChanges, there is no way to do
that with the existing 'compromize'...
UnitTests show that this already works well for
SC and SD, but SW has still some issues. I will
put this to gerrit now, but there will be
additional work.
A involved problem is the current DefaultItem
handling and the state the Pool implementation
is in. E.g. StaticDefaults are not really static,
Pools hard-delete the DefaultItems (forcing the
RefCnt to zero to not have the destructor
complain) and other quirks. Looking at that
right now, hoping to get this change done without
having to change that too much.
I thought about adapting PoolItemTest to this,
but it is only related to DirectPutItemInPool
which is mostly gone and hopefully completely
soon.
Nonetheless I adapted that mechanism to use a
list of SfxPoolItemHolder at the Pool. That makes
it safe and abandons the need for indirect
garbage collection removal at the Pool.
Change-Id: Ib47f21dafa989202930919eace5f7e9c5632ce96
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161896
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
Update sal_uLong to sal_Int32 for nKey variable. Signed 32 bit variables
have been used for similar variables within numfmuno.cxx and
numfmuno.hxx
Change-Id: Iabb15fe70fec9b28f675d6a63a6a36b1fd91439f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161822
Tested-by: Jenkins
Tested-by: Ilmari Lauhakangas <ilmari.lauhakangas@libreoffice.org>
Reviewed-by: Ilmari Lauhakangas <ilmari.lauhakangas@libreoffice.org>
|
|
At first it seemd that sal_uInt16 may be sufficient for storing possible
values. But as elsewhere unsigned 32 bit variables are used for such
purpose, sal_uInt32 is used which allows having more space for bigger values.
Change-Id: Ic2834ffc0fcabad91175aba3753e832dc1807fbe
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151006
Tested-by: Jenkins
Reviewed-by: Hossein <hossein@libreoffice.org>
|
|
Change-Id: I173c42583c03c41d8cd98424ba672cce10081e4e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161487
Tested-by: Jenkins
Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
|
|
Change-Id: Iaf83db0631ca0041915ccb61335cf2fc2a2142f3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161447
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
|
|
and try something a bit more generic
Change-Id: I1d8256576cd02f0a589df350ba7b53059dd586a5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161250
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
|
|
ScPatternAttr is traditionally derived from SfxPoolItem
(or better: SfxSetItem) and held in the ScDocumentPool
as Item.
This is only because of 'using' the 'poolable'
functionality of the Item/ItemSet/ItemPool mechanism.
Lots of hacks were added to sc and Item/ItemSet/
ItemPool to make that 'work' which shows already that
this relationship is not optimal.
It uses DirectPutItemInPool/DirectRemoveItemFromPool
to do so, also with massive overhead to do that (and
with not much success). The RefCnt in the SfxPoolItem
that is used for this never worked reliably, so the
SfxItemPool was (ab)used as garbage collector (all
Items added and never removed get deleted at last
for good when the Pool goes down). For this reasons
and to be able to further get ItemSets modernized
I changed this. I did two big changes here:
(1) No longer derive ScPatternAttr from SfxItemSet/
SfxSetItem, no longer hold as SfxPoolItem
(2) Add tooling to reliably control the lifetime of
ScPatternAttr instances and ther uniqueness/
reusage for memory reasons
It is now a regular non-derived class. The SfxItemSet
formally derived from SfxSetItem is now a member. The
RefCnt is now also a member (so independent from
size/data type of SfxPoolItem). All in all it's pretty
much the same size as before.
To support handling it I created a CellAttributeHelper
that is at/owned by ScDocument and takes over tooling
to handle the ScPatternAttr. It supports to guarantee
the uniqueness of incarnated ScPatternAttr instances for
a ScDocument by providing helpers like registerAndCheck
and doUnregister. It hosts the default CellAttribute/
ScPatternAttr. That default handling was anyways not
using the standard default-handling of Items/Pools.
I adapted whole SC to use that mainly by replacing calls
to DirectPutItemInPool with registerAndCheck and
DirectRemoveItemFromPool with doUnregister, BUT: This
was not sufficient, the RefCnt kept to be broken.
For that reason I decided to also do (2) in this change:
I added a CellAttributeHolder that owns/regulates the
lifetime of a single ScPatternAttr. Originally it also
contained the CellAttributeHolder, but after some
thoughts I decided that this is not needed - if there
is no ScPatternAttr set, no CellAttributeHolder is
needed for safe cleanup at destruction of the helper.
So I moved/added the CellAttributeHolder to ScPatternAttr
where it belongs more naturally anyways. The big plus is
that CellAttributeHolder is just one ptr, so not bigger
than having a simple ScPatternAttr*. That way, e.g.
ScAttrEntry in ScAttrArray did not 'grow' at all. In
principle all places where a ScPatternAttr* is used can
now be replaced by using a CellAttributeHolder, except
for construction. It is capable to be initialized with
either ScPatternAttr instances from the heap (it creates
a copy that then gets RefCounted) or allocated (it
supports ownership change at construction time).
Note that ScAttrEntry started to get more a C++ class
in that change, it has a constructor. I did not change
the SCROW member, but that should also be done.
Also made registerAndCheck/doUnregister private in
CellAttributeHelper and exclusively used by
CellAttributeHolder. That way the RefCnt works, and a
lot of code gets much simpler (check ScItemPoolCache,
it's now straightforward) and safer and ~ScPatternAttr()
uses now a hard
assert(!isRegistered());
which shows that RefCnt works now (the 1st time?).
There can be done more (see ToDo section below) but I
myself will concentrate on getting ItemSets forward.
This decoupling makes both involved mechanisms more safe,
less complex and more stable. It also opens up
possibilities to further optimize ScPatternAttr in SC
without further hacking Item/ItemSet/ItemPool stuff.
NOTE: ScPatternAttr *should* be renamed to 'CellAttribute'
which describes what it is. The experiencd devs may know
what it does, but it is a hindrance for understanding for
attacting new devs. I already used now names like
CellAttributeHelper/CellAttributeHolder etc., but
abstained from renaming ScPatternAttr, see ToDo list below.
SfxItemSet discussion:
ScPatternAttr still contains a SfxItemSet, or better, a
SfxSetItem. For that reason it still depends on access to
an SfxItemPool (so there is acces in CellAttributeHelper).
This is in principle not needed - no Item (in the range
[ATTR_PATTERN_START .. ATTR_PATTERN_END]) needs that.
In principle ScPatternAttr could now do it's own handling
of those needed Items, however this might be done (linear
array, hash-by-WhichID, ...). The Items get translated
to and from this to the rest of the office anyways.
Note that *merging* of SfxItemSets is *still* needed what
means to have WhichID slots in SfxItemState::DONTCARE,
see note in ScPatternAttr::ScPatternAttr about that. And
there is also the Surrogates stuff which would have to be
checked.
The other extreme is to use SfxItemSet *more*, e.g. directly
derive from SfxItemSet what would make stuff easier, maybe
even get back to using the 'regular' Items like all office,
I doubt that that would be much slower, so why...?
Also possible is to remove that range of Items exclusively
used by ScPatternAttr from ScDocumentPool *completely* and
create an own Pool for them, owned by CellAttributeHelper.
That Pool might even be static global, so all SC Docs could
share all those Items - maybe even the ScPatternAttr
themselves (except the default per document). That would
remove the dependency of ScPatternAttr from a Pool
completely.
ToDo-List:
- rename ScPatternAttr to CellAttribute or similar
- use SfxItemSetFixed with range [ATTR_PATTERN_START
.. ATTR_PATTERN_END] instead of regular SfxItemSet
(if the copy-construtor works now...?)
- maybe create own/separate Pool for exclusive Items
- make ScAttrEntry more a C++ class by moving SCROW
to the private section, add get/set methods and
adapt SC
Had to add some more usages of CellAttributeHolder
to the SC Sort mechanism, there were situations where
the sorted ScPatternAttr were replaced in the Table,
but the 'sorted' ones were just ScPatternAttr*, thus
deleting the valid ones in the Table already. Using
CellAttributeHolder makes this safe, too.
Added a small, one-entry cache to CellAttributeHelper
to buffer the last found buffered ScPattrnAttr. It
has a HitRate of ca. 5-6% and brings the UnitTest
testSheetCellRangeProperties from 0m48,710s to
0m37,556s. Not too massive, but erery bit counts :-)
Also shows that after that change optimizations in
the now split functionality is possible and easy.
Change-Id: I268a7b2a943ce5ddfe3c75b5e648c0f6b0cedb85
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161244
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
and
cid#1559872 Uninitialized scalar field
Change-Id: Iaea583d63cd1f0a1b68c60adb57c8c1db9a26a9c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161292
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
|
|
and
cid#1545468 COPY_INSTEAD_OF_MOVE
cid#1545446 COPY_INSTEAD_OF_MOVE
cid#1545435 COPY_INSTEAD_OF_MOVE
cid#1545419 COPY_INSTEAD_OF_MOVE
cid#1545415 COPY_INSTEAD_OF_MOVE
cid#1545410 COPY_INSTEAD_OF_MOVE
cid#1545390 COPY_INSTEAD_OF_MOVE
cid#1545384 COPY_INSTEAD_OF_MOVE
cid#1545374 COPY_INSTEAD_OF_MOVE
cid#1545371 COPY_INSTEAD_OF_MOVE
cid#1545368 COPY_INSTEAD_OF_MOVE
cid#1545366 COPY_INSTEAD_OF_MOVE
cid#1545335 COPY_INSTEAD_OF_MOVE
cid#1545331 COPY_INSTEAD_OF_MOVE
cid#1545327 COPY_INSTEAD_OF_MOVE
cid#1545308 COPY_INSTEAD_OF_MOVE
cid#1545280 COPY_INSTEAD_OF_MOVE
cid#1545199 COPY_INSTEAD_OF_MOVE
Change-Id: If05a13125b05ccd93d34d0eced566e7b3b58aaef
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161256
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
|
|
etc, since:
commit e9e3576ada06d53de12efed041fb309fe5388e01
Date: Thu Dec 21 22:49:27 2023 +0100
svl: fix build with --enable-debug
Change-Id: I1c3c82f0f1674cb46fa6a36d5f9f5cc4435ebef1
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161241
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
|
|
and
cid#1546492 COPY_INSTEAD_OF_MOVE
cid#1546468 COPY_INSTEAD_OF_MOVE
cid#1546431 COPY_INSTEAD_OF_MOVE
cid#1546382 COPY_INSTEAD_OF_MOVE
cid#1546350 COPY_INSTEAD_OF_MOVE
cid#1546336 COPY_INSTEAD_OF_MOVE
cid#1546314 COPY_INSTEAD_OF_MOVE
cid#1546152 COPY_INSTEAD_OF_MOVE
cid#1546094 COPY_INSTEAD_OF_MOVE
cid#1546077 COPY_INSTEAD_OF_MOVE
cid#1546047 COPY_INSTEAD_OF_MOVE
cid#1545213 COPY_INSTEAD_OF_MOVE
Change-Id: Ia51df9f9cbde755db4d2685e34f22676ed5eceff
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161141
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
|
|
Change-Id: I61077392776c6bc28410c29586fd8de85347b936
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161143
Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
Tested-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
|
|
There are some CrashReports in 7.6 which have
DeleteItemOnIdle on the stack, but there is nothing
reproducable. So I took a look...
I first thought it's a MCGR regression, due to classes
on the stack. But the Item involved is just random, can
happen with any Item.
Then I thought it may have to do with ITEM refactorings,
but it happens with DeleteItemOnIdle involved, so also
not the case. I already saw DeleteItemOnIdle when doing
these and qualified as 'hack' in the way. already
It is only on Windows and DeleteItemOnIdle is involved.
This again (took a deeper look now) is an old hack to
keep an SfxPoolItem 'alive' for some 'time'. For that,
it triggers an async reschedule which then deletes the
Item when being called. If the Item will be used after
that is pure coincidence - seems to work in most cases.
It seems as if for Windows the timing slightly changed
for some scenarios, so a reschedule is too early. This
can happen with this hack anytime.
DeleteItemOnIdle is used in scenarios where SfxPoolItem*
is e.g. returned, but is *not* anchored, so e.g. not
member of an SfxItemSet. Or in short: Lifetime is not
safe.
DeleteItemOnIdle exists since 1st import, but was
changed to AsyncEvent ca. 4 months ago (see
57145acf9ec47c23e307b7a5c0029d21d937cc35), so that may
have caused it. It is possible that these errors happen
on Windows since then. Before something more complicated
was used to delete it late, but surely also not really
safe.
Due to ITEM refactor I have the knowledge/tooling to
solve this. It will not be a 1-5 lines fix, but it is
a hack and in the way for further ITEM refactor anyways.
What we have nowadays is a SfxPoolItemHolder -> it's
like an SfxItemSet for a single Item. It safely holds/
controls the lifetime of an SfxPoolItem. It is already
used in quite some places. It helps to solve many hacks,
also the ones putting Items directly to the Pool - due
to there never was an alternative for that. In principle
the ItemPool/ItemSet/Item paradigm was never complete
without SfxPoolItemHolder.
Thus I started to fix that (and remove that hack for
good, sooo many changes over the years, sigh), but as
said is not straightforward. Will have to change
retvals of involved stuff to SfxPoolItemHolder - it's
just two pointers and designed to be copied (one is a
Pool, needed to cleanup when destructing).
CopyConstruct/destroy just counts the RefCnt up/down,
so cheap.
1st version compiling, let's check on gerrit...
Corrected one error in QueryState for securitypage, also
added some security features/asserts.
Change-Id: Ida49fd35ca88ead84b11d93e18b978cb9e395090
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161083
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
|
|
Change-Id: I167f6ea5d740b5a53cd02a9b865e65ff980a8877
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160922
Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
Tested-by: Jenkins
|
|
which flushes out the fact that, previously, when
SfxItemSetFixed was being copied, we were not
actually taking advantage of the "internal" memory,
and were actually allocating a separate block of memory,
like a "normal" SfxItemSet.
Change-Id: I6a8073c58b464d53bfd2a54cf1dd27a3f2cb3df7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160377
Tested-by: Noel Grandin <noel.grandin@collabora.co.uk>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
|