LibreOffice Module unotools (master) 1
dynamicmenuoptions.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 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <o3tl/string_view.hxx>
24#include <tools/debug.hxx>
27#include <com/sun/star/uno/Any.hxx>
28#include <com/sun/star/uno/Sequence.hxx>
29
30#include <vector>
31#include <algorithm>
32#include <string_view>
33
34using namespace ::com::sun::star::uno;
35using namespace ::com::sun::star::beans;
36
37constexpr OUStringLiteral DYNAMICMENU_PROPERTYNAME_URL = u"URL";
38constexpr OUStringLiteral DYNAMICMENU_PROPERTYNAME_TITLE = u"Title";
39constexpr OUStringLiteral DYNAMICMENU_PROPERTYNAME_IMAGEIDENTIFIER = u"ImageIdentifier";
40constexpr OUStringLiteral DYNAMICMENU_PROPERTYNAME_TARGETNAME = u"TargetName";
41
42constexpr OUStringLiteral PATHDELIMITER = u"/";
43
44constexpr OUStringLiteral SETNODE_NEWMENU = u"New";
45constexpr OUStringLiteral SETNODE_WIZARDMENU = u"Wizard";
46
47#define PROPERTYNAME_URL DYNAMICMENU_PROPERTYNAME_URL
48#define PROPERTYNAME_TITLE DYNAMICMENU_PROPERTYNAME_TITLE
49#define PROPERTYNAME_IMAGEIDENTIFIER DYNAMICMENU_PROPERTYNAME_IMAGEIDENTIFIER
50#define PROPERTYNAME_TARGETNAME DYNAMICMENU_PROPERTYNAME_TARGETNAME
51
52#define PROPERTYCOUNT 4
53
54constexpr std::u16string_view PATHPREFIX_SETUP = u"m";
55
56namespace
57{
58/*-****************************************************************************************************************
59 @descr support simple menu structures and operations on it
60****************************************************************************************************************-*/
61struct SvtDynMenu
62{
63 // append setup written menu entry
64 // Don't touch name of entry. It was defined by setup and must be the same every time!
65 // Look for double menu entries here too... may be some separator items are superfluous...
66 void AppendSetupEntry( const SvtDynMenuEntry& rEntry )
67 {
68 if( lSetupEntries.empty() || lSetupEntries.rbegin()->sURL != rEntry.sURL )
69 lSetupEntries.push_back( rEntry );
70 }
71
72 // convert internal list to external format
73 // for using it on right menus really
74 // Notice: We build a property list with 4 entries and set it on result list then.
75 // Separator entries will be packed in another way then normal entries! We define
76 // special string "sSeparator" to perform too ...
77 std::vector< SvtDynMenuEntry > GetList() const
78 {
79 sal_Int32 nSetupCount = static_cast<sal_Int32>(lSetupEntries.size());
80 sal_Int32 nUserCount = static_cast<sal_Int32>(lUserEntries.size());
81 sal_Int32 nStep = 0;
82 std::vector< SvtDynMenuEntry > lResult ( nSetupCount+nUserCount );
83 OUString sSeparator ( "private:separator" );
84
85 for( const auto& pList : {&lSetupEntries, &lUserEntries} )
86 {
87 for( const auto& rItem : *pList )
88 {
89 SvtDynMenuEntry entry;
90 if( rItem.sURL == sSeparator )
91 {
92 entry.sURL = sSeparator;
93 }
94 else
95 {
96 entry = rItem;
97 }
98 lResult[nStep] = entry;
99 ++nStep;
100 }
101 }
102 return lResult;
103 }
104
105private:
106 std::vector< SvtDynMenuEntry > lSetupEntries;
107 std::vector< SvtDynMenuEntry > lUserEntries;
108};
109
110}
111
113{
114
116 css::uno::Reference<css::container::XHierarchicalNameAccess> const & xHierarchyAccess,
117 sal_uInt32& nNewCount, sal_uInt32& nWizardCount );
118
119std::vector< SvtDynMenuEntry > GetMenu( EDynamicMenuType eMenu )
120{
121 SvtDynMenu aNewMenu;
122 SvtDynMenu aWizardMenu;
123
124 Reference<css::container::XHierarchicalNameAccess> xHierarchyAccess = utl::ConfigManager::acquireTree(u"Office.Common/Menus/");
125
126 // Get names and values of all accessible menu entries and fill internal structures.
127 // See impl_GetPropertyNames() for further information.
128 sal_uInt32 nNewCount = 0;
129 sal_uInt32 nWizardCount = 0;
130 Sequence< OUString > lNames = lcl_GetPropertyNames ( xHierarchyAccess, nNewCount ,
131 nWizardCount );
132 Sequence< Any > lValues = utl::ConfigItem::GetProperties( xHierarchyAccess, lNames, /*bAllLocales*/false );
133
134 // Safe impossible cases.
135 // We need values from ALL configuration keys.
136 // Follow assignment use order of values in relation to our list of key names!
137 DBG_ASSERT( !(lNames.getLength()!=lValues.getLength()), "SvtDynamicMenuOptions_Impl::SvtDynamicMenuOptions_Impl()\nI miss some values of configuration keys!\n" );
138
139 // Copy values from list in right order to our internal member.
140 // Attention: List for names and values have an internal construction pattern!
141
142 // first "New" menu ...
143 // Name Value
144 // /New/1/URL "private:factory/swriter"
145 // /New/1/Title "New Writer Document"
146 // /New/1/ImageIdentifier "icon_writer"
147 // /New/1/TargetName "_blank"
148
149 // /New/2/URL "private:factory/scalc"
150 // /New/2/Title "New Calc Document"
151 // /New/2/ImageIdentifier "icon_calc"
152 // /New/2/TargetName "_blank"
153
154 // second "Wizard" menu ...
155 // /Wizard/1/URL "file://b"
156 // /Wizard/1/Title "PaintSomething"
157 // /Wizard/1/ImageIdentifier "icon_?"
158 // /Wizard/1/TargetName "_self"
159
160 // ... and so on ...
161
162 sal_uInt32 nItem = 0;
163 sal_uInt32 nPosition = 0;
164
165 // Get names/values for new menu.
166 // 4 subkeys for every item!
167 for( nItem=0; nItem<nNewCount; ++nItem )
168 {
169 SvtDynMenuEntry aItem;
170 lValues[nPosition] >>= aItem.sURL;
171 ++nPosition;
172 lValues[nPosition] >>= aItem.sTitle;
173 ++nPosition;
174 lValues[nPosition] >>= aItem.sImageIdentifier;
175 ++nPosition;
176 lValues[nPosition] >>= aItem.sTargetName;
177 ++nPosition;
178 aNewMenu.AppendSetupEntry( aItem );
179 }
180
181 // Attention: Don't reset nPosition here!
182
183 // Get names/values for wizard menu.
184 // 4 subkeys for every item!
185 for( nItem=0; nItem<nWizardCount; ++nItem )
186 {
187 SvtDynMenuEntry aItem;
188 lValues[nPosition] >>= aItem.sURL;
189 ++nPosition;
190 lValues[nPosition] >>= aItem.sTitle;
191 ++nPosition;
192 lValues[nPosition] >>= aItem.sImageIdentifier;
193 ++nPosition;
194 lValues[nPosition] >>= aItem.sTargetName;
195 ++nPosition;
196 aWizardMenu.AppendSetupEntry( aItem );
197 }
198
199 std::vector< SvtDynMenuEntry > lReturn;
200 switch( eMenu )
201 {
203 lReturn = aNewMenu.GetList();
204 break;
205
207 lReturn = aWizardMenu.GetList();
208 break;
209 }
210 return lReturn;
211}
212
213static void lcl_SortAndExpandPropertyNames( const Sequence< OUString >& lSource,
214 Sequence< OUString >& lDestination, std::u16string_view sSetNode );
215
216/*-****************************************************************************************************
217 @short return list of key names of our configuration management which represent our module tree
218 @descr This method returns the current list of key names! We need it to get needed values from our
219 configuration management and support dynamical menu item lists!
220 @param "nNewCount" , returns count of menu entries for "new"
221 @param "nWizardCount" , returns count of menu entries for "wizard"
222 @return A list of configuration key names is returned.
223*//*-*****************************************************************************************************/
225 css::uno::Reference<css::container::XHierarchicalNameAccess> const & xHierarchyAccess,
226 sal_uInt32& nNewCount, sal_uInt32& nWizardCount )
227{
228 // First get ALL names of current existing list items in configuration!
231
232 // Get information about list counts ...
233 nNewCount = lNewItems.getLength();
234 nWizardCount = lWizardItems.getLength();
235
236 // Sort and expand all three list to result list ...
237 Sequence< OUString > lProperties;
238 lcl_SortAndExpandPropertyNames( lNewItems , lProperties, SETNODE_NEWMENU );
239 lcl_SortAndExpandPropertyNames( lWizardItems , lProperties, SETNODE_WIZARDMENU );
240
241 // Return result.
242 return lProperties;
243}
244
245/*-****************************************************************************************************
246 @short sort given source list and expand it for all well known properties to destination
247 @descr We must support sets of entries with count inside the name .. but some of them could be missing!
248 e.g. s1-s2-s3-s0-u1-s6-u5-u7
249 Then we must sort it by name and expand it to the follow one:
250 sSetNode/s0/URL
251 sSetNode/s0/Title
252 sSetNode/s0/...
253 sSetNode/s1/URL
254 sSetNode/s1/Title
255 sSetNode/s1/...
256 ...
257 sSetNode/s6/URL
258 sSetNode/s6/Title
259 sSetNode/s6/...
260 sSetNode/u1/URL
261 sSetNode/u1/Title
262 sSetNode/u1/...
263 ...
264 sSetNode/u7/URL
265 sSetNode/u7/Title
266 sSetNode/u7/...
267 Rules: We start with all setup written entries names "sx" and x=[0..n].
268 Then we handle all "ux" items. Inside these blocks we sort it ascending by number.
269
270 @attention We add these expanded list to the end of given "lDestination" list!
271 So we must start on "lDestination.getLength()".
272 Reallocation of memory of destination list is done by us!
273
274 @seealso method impl_GetPropertyNames()
275
276 @param "lSource" , original list (e.g. [m1-m2-m3-m6-m0] )
277 @param "lDestination" , destination of operation
278 @param "sSetNode" , name of configuration set to build complete path
279 @return A list of configuration key names is returned.
280*//*-*****************************************************************************************************/
281
283 Sequence< OUString >& lDestination ,
284 std::u16string_view sSetNode )
285{
286 struct CountWithPrefixSort
287 {
288 bool operator() ( std::u16string_view s1, std::u16string_view s2 ) const
289 {
290 // Get order numbers from entry name without prefix.
291 // e.g. "m10" => 10
292 // "m5" => 5
293 sal_Int32 n1 = o3tl::toInt32(s1.substr( 1 ));
294 sal_Int32 n2 = o3tl::toInt32(s2.substr( 1 ));
295 // MUST be in [0,1] ... because it's a difference between
296 // insert-positions of given entries in sorted list!
297 return( n1<n2 );
298 }
299 };
300 struct SelectByPrefix
301 {
302 bool operator() ( std::u16string_view s ) const
303 {
304 // Prefer setup written entries by check first letter of given string. It must be a "s".
306 }
307 };
308
309 std::vector< OUString > lTemp;
310 sal_Int32 nSourceCount = lSource.getLength();
311 sal_Int32 nDestinationStep = lDestination.getLength(); // start on end of current list ...!
312
313 lDestination.realloc( (nSourceCount*PROPERTYCOUNT)+nDestinationStep ); // get enough memory for copy operations after nDestination ...
314 auto plDestination = lDestination.getArray();
315
316 // Copy all items to temp. vector to use fast sort operations :-)
317 lTemp.insert( lTemp.end(), lSource.begin(), lSource.end() );
318
319 // Sort all entries by number ...
320 std::stable_sort( lTemp.begin(), lTemp.end(), CountWithPrefixSort() );
321 // and split into setup & user written entries!
322 std::stable_partition( lTemp.begin(), lTemp.end(), SelectByPrefix() );
323
324 // Copy sorted entries to destination and expand every item with
325 // 4 supported sub properties.
326 for( const auto& rItem : lTemp )
327 {
328 OUString sFixPath(OUString::Concat(sSetNode) + PATHDELIMITER + rItem + PATHDELIMITER);
329 plDestination[nDestinationStep++] = sFixPath + PROPERTYNAME_URL;
330 plDestination[nDestinationStep++] = sFixPath + PROPERTYNAME_TITLE;
331 plDestination[nDestinationStep++] = sFixPath + PROPERTYNAME_IMAGEIDENTIFIER;
332 plDestination[nDestinationStep++] = sFixPath + PROPERTYNAME_TARGETNAME;
333 }
334}
335
336
337} // namespace SvtDynamicMenuOptions
338
339/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Sequence< css::uno::Any > GetProperties(const css::uno::Sequence< OUString > &rNames)
css::uno::Sequence< OUString > GetNodeNames(const OUString &rNode)
Definition: configitem.cxx:685
static SAL_DLLPRIVATE css::uno::Reference< css::container::XHierarchicalNameAccess > acquireTree(utl::ConfigItem const &item)
Definition: configmgr.cxx:117
#define DBG_ASSERT(sCon, aError)
float u
#define PROPERTYNAME_URL
#define PROPERTYCOUNT
#define PROPERTYNAME_TITLE
#define PROPERTYNAME_TARGETNAME
constexpr OUStringLiteral PATHDELIMITER
constexpr OUStringLiteral SETNODE_NEWMENU
constexpr std::u16string_view PATHPREFIX_SETUP
constexpr OUStringLiteral SETNODE_WIZARDMENU
constexpr OUStringLiteral DYNAMICMENU_PROPERTYNAME_IMAGEIDENTIFIER
constexpr OUStringLiteral DYNAMICMENU_PROPERTYNAME_URL
constexpr OUStringLiteral DYNAMICMENU_PROPERTYNAME_TITLE
#define PROPERTYNAME_IMAGEIDENTIFIER
constexpr OUStringLiteral DYNAMICMENU_PROPERTYNAME_TARGETNAME
EDynamicMenuType
int n2
int n1
static Sequence< OUString > lcl_GetPropertyNames(css::uno::Reference< css::container::XHierarchicalNameAccess > const &xHierarchyAccess, sal_uInt32 &nNewCount, sal_uInt32 &nWizardCount)
std::vector< SvtDynMenuEntry > GetMenu(EDynamicMenuType eMenu)
static void lcl_SortAndExpandPropertyNames(const Sequence< OUString > &lSource, Sequence< OUString > &lDestination, std::u16string_view sSetNode)
std::vector< HistoryItem > GetList(EHistoryType eHistory)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept