/src/libreoffice/svx/source/dialog/ClassificationDialog.cxx
Line | Count | Source |
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 | | |
11 | | #include <svx/ClassificationDialog.hxx> |
12 | | #include <svx/ClassificationCommon.hxx> |
13 | | |
14 | | #include <editeng/flditem.hxx> |
15 | | #include <editeng/eeitem.hxx> |
16 | | #include <editeng/section.hxx> |
17 | | #include <editeng/editobj.hxx> |
18 | | #include <editeng/wghtitem.hxx> |
19 | | #include <svl/itemset.hxx> |
20 | | #include <osl/file.hxx> |
21 | | #include <rtl/bootstrap.hxx> |
22 | | #include <config_folders.h> |
23 | | #include <tools/stream.hxx> |
24 | | #include <tools/XmlWriter.hxx> |
25 | | #include <tools/XmlWalker.hxx> |
26 | | #include <utility> |
27 | | #include <vcl/event.hxx> |
28 | | #include <vcl/svapp.hxx> |
29 | | #include <vcl/weld/Builder.hxx> |
30 | | #include <vcl/weld/Dialog.hxx> |
31 | | #include <vcl/weld/customweld.hxx> |
32 | | |
33 | | #include <officecfg/Office/Common.hxx> |
34 | | |
35 | | #include "ClassificationEditView.hxx" |
36 | | |
37 | | namespace svx { |
38 | | |
39 | | IMPL_STATIC_LINK(ClassificationDialog, KeyInput, const KeyEvent&, rKeyEvent, bool) |
40 | 0 | { |
41 | 0 | bool bTextIsFreeForm = officecfg::Office::Common::Classification::IntellectualPropertyTextInputIsFreeForm::get(); |
42 | |
|
43 | 0 | if (!bTextIsFreeForm) |
44 | 0 | { |
45 | | // Ignore key combination with modifier keys |
46 | 0 | if (rKeyEvent.GetKeyCode().IsMod3() |
47 | 0 | || rKeyEvent.GetKeyCode().IsMod2() |
48 | 0 | || rKeyEvent.GetKeyCode().IsMod1()) |
49 | 0 | { |
50 | 0 | return true; |
51 | 0 | } |
52 | | |
53 | 0 | switch (rKeyEvent.GetKeyCode().GetCode()) |
54 | 0 | { |
55 | | // Allowed characters |
56 | 0 | case KEY_BACKSPACE: |
57 | 0 | case KEY_DELETE: |
58 | 0 | case KEY_DIVIDE: |
59 | 0 | case KEY_SEMICOLON: |
60 | 0 | case KEY_SPACE: |
61 | 0 | return false; |
62 | | // Anything else is ignored |
63 | 0 | default: |
64 | 0 | return true; |
65 | 0 | } |
66 | 0 | } |
67 | | |
68 | 0 | return false; |
69 | 0 | } |
70 | | |
71 | | namespace { |
72 | | |
73 | | constexpr size_t RECENTLY_USED_LIMIT = 5; |
74 | | |
75 | | constexpr OUString constRecentlyUsedFileName(u"recentlyUsed.xml"_ustr); |
76 | | |
77 | | OUString lcl_getClassificationUserPath() |
78 | 0 | { |
79 | 0 | OUString sPath(u"${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/user/classification/"_ustr); |
80 | 0 | rtl::Bootstrap::expandMacros(sPath); |
81 | 0 | return sPath; |
82 | 0 | } |
83 | | |
84 | | const SvxFieldItem* findField(editeng::Section const & rSection) |
85 | 0 | { |
86 | 0 | for (SfxPoolItem const * pPool : rSection.maAttributes) |
87 | 0 | { |
88 | 0 | if (pPool->Which() == EE_FEATURE_FIELD) |
89 | 0 | return static_cast<const SvxFieldItem*>(pPool); |
90 | 0 | } |
91 | 0 | return nullptr; |
92 | 0 | } |
93 | | |
94 | | bool fileExists(OUString const & sFilename) |
95 | 0 | { |
96 | 0 | osl::File aFile(sFilename); |
97 | 0 | osl::FileBase::RC eRC = aFile.open(osl_File_OpenFlag_Read); |
98 | 0 | return osl::FileBase::E_None == eRC; |
99 | 0 | } |
100 | | |
101 | | bool stringToClassificationType(std::string_view rsType, svx::ClassificationType & reType) |
102 | 0 | { |
103 | 0 | if (rsType == "CATEGORY") |
104 | 0 | reType = svx::ClassificationType::CATEGORY; |
105 | 0 | else if (rsType == "INTELLECTUAL_PROPERTY_PART") |
106 | 0 | reType = svx::ClassificationType::INTELLECTUAL_PROPERTY_PART; |
107 | 0 | else if (rsType == "MARKING") |
108 | 0 | reType = svx::ClassificationType::MARKING; |
109 | 0 | else if (rsType == "PARAGRAPH") |
110 | 0 | reType = svx::ClassificationType::PARAGRAPH; |
111 | 0 | else if (rsType == "TEXT") |
112 | 0 | reType = svx::ClassificationType::TEXT; |
113 | 0 | else |
114 | 0 | return false; |
115 | 0 | return true; |
116 | 0 | } |
117 | | |
118 | | OUString classificationTypeToString(svx::ClassificationType const & reType) |
119 | 0 | { |
120 | 0 | switch(reType) |
121 | 0 | { |
122 | 0 | case svx::ClassificationType::CATEGORY: |
123 | 0 | return u"CATEGORY"_ustr; break; |
124 | 0 | case svx::ClassificationType::MARKING: |
125 | 0 | return u"MARKING"_ustr; break; |
126 | 0 | case svx::ClassificationType::TEXT: |
127 | 0 | return u"TEXT"_ustr; break; |
128 | 0 | case svx::ClassificationType::INTELLECTUAL_PROPERTY_PART: |
129 | 0 | return u"INTELLECTUAL_PROPERTY_PART"_ustr; break; |
130 | 0 | case svx::ClassificationType::PARAGRAPH: |
131 | 0 | return u"PARAGRAPH"_ustr; break; |
132 | 0 | } |
133 | 0 | return OUString(); |
134 | 0 | } |
135 | | |
136 | | void writeResultToXml(tools::XmlWriter & rXmlWriter, |
137 | | std::vector<ClassificationResult> const & rResultCollection) |
138 | 0 | { |
139 | 0 | for (ClassificationResult const & rResult : rResultCollection) |
140 | 0 | { |
141 | 0 | rXmlWriter.startElement("element"); |
142 | 0 | OUString sType = classificationTypeToString(rResult.meType); |
143 | 0 | rXmlWriter.attribute("type", sType); |
144 | 0 | rXmlWriter.startElement("string"); |
145 | 0 | rXmlWriter.content(rResult.msName); |
146 | 0 | rXmlWriter.endElement(); |
147 | 0 | rXmlWriter.startElement("abbreviatedString"); |
148 | 0 | rXmlWriter.content(rResult.msAbbreviatedName); |
149 | 0 | rXmlWriter.endElement(); |
150 | 0 | rXmlWriter.startElement("identifier"); |
151 | 0 | rXmlWriter.content(rResult.msIdentifier); |
152 | 0 | rXmlWriter.endElement(); |
153 | 0 | rXmlWriter.endElement(); |
154 | 0 | } |
155 | 0 | } |
156 | | |
157 | | } // end anonymous namespace |
158 | | |
159 | | ClassificationDialog::ClassificationDialog(weld::Window* pParent, const css::uno::Reference<css::document::XDocumentProperties>& rDocProps, |
160 | | const bool bPerParagraph, std::function<void()> aParagraphSignHandler) |
161 | 0 | : GenericDialogController(pParent, u"svx/ui/classificationdialog.ui"_ustr, u"AdvancedDocumentClassificationDialog"_ustr) |
162 | 0 | , maHelper(rDocProps) |
163 | 0 | , maInternationalHelper(rDocProps, /*bUseLocalizedPolicy*/ false) |
164 | 0 | , m_bPerParagraph(bPerParagraph) |
165 | 0 | , m_aParagraphSignHandler(std::move(aParagraphSignHandler)) |
166 | 0 | , m_nCurrentSelectedCategory(-1) |
167 | 0 | , m_xOkButton(m_xBuilder->weld_button(u"ok"_ustr)) |
168 | 0 | , m_xSignButton(m_xBuilder->weld_button(u"signButton"_ustr)) |
169 | 0 | , m_xToolBox(m_xBuilder->weld_toggle_button(u"toolbox"_ustr)) |
170 | 0 | , m_xRecentlyUsedListBox(m_xBuilder->weld_combo_box(u"recentlyUsedCB"_ustr)) |
171 | 0 | , m_xClassificationListBox(m_xBuilder->weld_combo_box(u"classificationCB"_ustr)) |
172 | 0 | , m_xInternationalClassificationListBox(m_xBuilder->weld_combo_box(u"internationalClassificationCB"_ustr)) |
173 | 0 | , m_xMarkingLabel(m_xBuilder->weld_label(u"markingLabel"_ustr)) |
174 | 0 | , m_xMarkingListBox(m_xBuilder->weld_tree_view(u"markingLB"_ustr)) |
175 | 0 | , m_xIntellectualPropertyPartListBox(m_xBuilder->weld_tree_view(u"intellectualPropertyPartLB"_ustr)) |
176 | 0 | , m_xIntellectualPropertyPartNumberListBox(m_xBuilder->weld_tree_view(u"intellectualPropertyPartNumberLB"_ustr)) |
177 | 0 | , m_xIntellectualPropertyPartAddButton(m_xBuilder->weld_button(u"intellectualPropertyPartAddButton"_ustr)) |
178 | 0 | , m_xIntellectualPropertyPartEdit(m_xBuilder->weld_entry(u"intellectualPropertyPartEntry"_ustr)) |
179 | 0 | , m_xIntellectualPropertyExpander(m_xBuilder->weld_expander(u"intellectualPropertyExpander"_ustr)) |
180 | 0 | , m_xEditWindow(new ClassificationEditView) |
181 | 0 | , m_xEditWindowWeld(new weld::CustomWeld(*m_xBuilder, u"classificationEditWindow"_ustr, *m_xEditWindow)) |
182 | 0 | { |
183 | 0 | m_xOkButton->connect_clicked(LINK(this, ClassificationDialog, OkHdl)); |
184 | 0 | m_xSignButton->connect_clicked(LINK(this, ClassificationDialog, ButtonClicked)); |
185 | 0 | m_xSignButton->set_visible(m_bPerParagraph); |
186 | |
|
187 | 0 | m_xIntellectualPropertyPartEdit->connect_key_press(LINK(this, ClassificationDialog, KeyInput)); |
188 | | |
189 | | // no need for BOLD if we do paragraph classification |
190 | 0 | if (m_bPerParagraph) |
191 | 0 | { |
192 | 0 | m_xToolBox->hide(); |
193 | 0 | } |
194 | 0 | else |
195 | 0 | { |
196 | 0 | m_xToolBox->connect_toggled(LINK(this, ClassificationDialog, SelectToolboxHdl)); |
197 | 0 | } |
198 | |
|
199 | 0 | m_xIntellectualPropertyPartAddButton->connect_clicked(LINK(this, ClassificationDialog, ButtonClicked)); |
200 | |
|
201 | 0 | m_xClassificationListBox->set_size_request(m_xClassificationListBox->get_approximate_digit_width() * 20, -1); |
202 | 0 | m_xClassificationListBox->connect_changed(LINK(this, ClassificationDialog, SelectClassificationHdl)); |
203 | 0 | for (const OUString& rName : maHelper.GetBACNames()) |
204 | 0 | m_xClassificationListBox->append_text(rName); |
205 | |
|
206 | 0 | m_xInternationalClassificationListBox->set_size_request(m_xInternationalClassificationListBox->get_approximate_digit_width() * 20, -1); |
207 | 0 | m_xInternationalClassificationListBox->connect_changed(LINK(this, ClassificationDialog, SelectClassificationHdl)); |
208 | 0 | for (const OUString& rName : maInternationalHelper.GetBACNames()) |
209 | 0 | m_xInternationalClassificationListBox->append_text(rName); |
210 | |
|
211 | 0 | if (!maHelper.GetMarkings().empty()) |
212 | 0 | { |
213 | 0 | m_xMarkingListBox->set_size_request(m_xMarkingListBox->get_approximate_digit_width() * 10, |
214 | 0 | m_xMarkingListBox->get_height_rows(4)); |
215 | 0 | m_xMarkingListBox->connect_item_activated( |
216 | 0 | LINK(this, ClassificationDialog, SelectMarkingHdl)); |
217 | |
|
218 | 0 | for (const OUString& rName : maHelper.GetMarkings()) |
219 | 0 | m_xMarkingListBox->append_text(rName); |
220 | 0 | } |
221 | 0 | else |
222 | 0 | { |
223 | 0 | m_xMarkingListBox->hide(); |
224 | 0 | m_xMarkingLabel->hide(); |
225 | 0 | } |
226 | |
|
227 | 0 | m_xIntellectualPropertyPartNumberListBox->set_size_request(m_xIntellectualPropertyPartNumberListBox->get_approximate_digit_width() * 10, |
228 | 0 | m_xIntellectualPropertyPartNumberListBox->get_height_rows(5)); |
229 | 0 | m_xIntellectualPropertyPartNumberListBox->connect_item_activated( |
230 | 0 | LINK(this, ClassificationDialog, SelectIPPartNumbersHdl)); |
231 | 0 | for (const OUString& rName : maHelper.GetIntellectualPropertyPartNumbers()) |
232 | 0 | m_xIntellectualPropertyPartNumberListBox->append_text(rName); |
233 | |
|
234 | 0 | m_xIntellectualPropertyPartNumberListBox->set_size_request(m_xIntellectualPropertyPartNumberListBox->get_approximate_digit_width() * 20, |
235 | 0 | m_xIntellectualPropertyPartListBox->get_height_rows(5)); |
236 | 0 | m_xIntellectualPropertyPartListBox->connect_item_activated( |
237 | 0 | LINK(this, ClassificationDialog, SelectIPPartHdl)); |
238 | 0 | for (const OUString& rName : maHelper.GetIntellectualPropertyParts()) |
239 | 0 | m_xIntellectualPropertyPartListBox->append_text(rName); |
240 | |
|
241 | 0 | m_xRecentlyUsedListBox->set_size_request(m_xRecentlyUsedListBox->get_approximate_digit_width() * 5, -1); |
242 | 0 | m_xRecentlyUsedListBox->connect_changed(LINK(this, ClassificationDialog, SelectRecentlyUsedHdl)); |
243 | |
|
244 | 0 | m_xIntellectualPropertyExpander->connect_expanded(LINK(this, ClassificationDialog, ExpandedHdl)); |
245 | 0 | if (officecfg::Office::Common::Classification::IntellectualPropertySectionExpanded::get()) |
246 | 0 | m_nAsyncExpandEvent = Application::PostUserEvent(LINK(this, ClassificationDialog, OnAsyncExpandHdl)); |
247 | 0 | else |
248 | 0 | m_nAsyncExpandEvent = nullptr; |
249 | |
|
250 | 0 | m_xEditWindow->SetModifyHdl(LINK(this, ClassificationDialog, EditWindowModifiedHdl)); |
251 | |
|
252 | 0 | readRecentlyUsed(); |
253 | 0 | toggleWidgetsDependingOnCategory(); |
254 | |
|
255 | 0 | int nNumber = 1; |
256 | 0 | if (m_aRecentlyUsedValuesCollection.empty()) |
257 | 0 | { |
258 | 0 | m_xRecentlyUsedListBox->set_sensitive(false); |
259 | 0 | } |
260 | 0 | else |
261 | 0 | { |
262 | 0 | for (std::vector<ClassificationResult> const & rResults : m_aRecentlyUsedValuesCollection) |
263 | 0 | { |
264 | 0 | OUString rContentRepresentation = svx::classification::convertClassificationResultToString(rResults); |
265 | 0 | OUString rDescription = OUString::number(nNumber) + ": " + rContentRepresentation; |
266 | 0 | nNumber++; |
267 | |
|
268 | 0 | m_xRecentlyUsedListBox->append_text(rDescription); |
269 | 0 | } |
270 | 0 | } |
271 | 0 | } |
272 | | |
273 | | //do it async so gtk has a chance to shrink it to best size, otherwise it's larger than min |
274 | | IMPL_LINK_NOARG(ClassificationDialog, OnAsyncExpandHdl, void*, void) |
275 | 0 | { |
276 | 0 | m_nAsyncExpandEvent = nullptr; |
277 | 0 | m_xIntellectualPropertyExpander->set_expanded(true); |
278 | 0 | } |
279 | | |
280 | | ClassificationDialog::~ClassificationDialog() |
281 | 0 | { |
282 | 0 | if (m_nAsyncExpandEvent) |
283 | 0 | Application::RemoveUserEvent(m_nAsyncExpandEvent); |
284 | 0 | } |
285 | | |
286 | | void ClassificationDialog::insertCategoryField(sal_Int32 nID) |
287 | 0 | { |
288 | 0 | const OUString aFullString = maHelper.GetBACNames()[nID]; |
289 | 0 | const OUString aAbbreviatedString = maHelper.GetAbbreviatedBACNames()[nID]; |
290 | 0 | const OUString aIdentifierString = maHelper.GetBACIdentifiers()[nID]; |
291 | 0 | insertField(ClassificationType::CATEGORY, aAbbreviatedString, aFullString, aIdentifierString); |
292 | 0 | } |
293 | | |
294 | | void ClassificationDialog::insertField(ClassificationType eType, OUString const & rString, OUString const & rFullString, OUString const & rIdentifier) |
295 | 0 | { |
296 | 0 | ClassificationField aField(eType, rString, rFullString, rIdentifier); |
297 | 0 | m_xEditWindow->InsertField(SvxFieldItem(aField, EE_FEATURE_FIELD)); |
298 | 0 | } |
299 | | |
300 | | void ClassificationDialog::setupValues(std::vector<ClassificationResult> && rInput) |
301 | 0 | { |
302 | 0 | m_aInitialValues = std::move(rInput); |
303 | 0 | readIn(m_aInitialValues); |
304 | 0 | } |
305 | | |
306 | | void ClassificationDialog::readRecentlyUsed() |
307 | 0 | { |
308 | 0 | OUString sPath = lcl_getClassificationUserPath(); |
309 | 0 | OUString sFilePath(sPath + constRecentlyUsedFileName); |
310 | |
|
311 | 0 | if (!fileExists(sFilePath)) |
312 | 0 | return; |
313 | | |
314 | 0 | SvFileStream aFileStream(sFilePath, StreamMode::READ); |
315 | 0 | tools::XmlWalker aWalker; |
316 | 0 | if (!aWalker.open(&aFileStream)) |
317 | 0 | return; |
318 | | |
319 | 0 | if (aWalker.name() != "recentlyUsedClassifications") |
320 | 0 | return; |
321 | | |
322 | 0 | aWalker.children(); |
323 | 0 | while (aWalker.isValid()) |
324 | 0 | { |
325 | 0 | if (aWalker.name() == "elementGroup") |
326 | 0 | { |
327 | 0 | std::vector<ClassificationResult> aResults; |
328 | |
|
329 | 0 | aWalker.children(); |
330 | |
|
331 | 0 | while (aWalker.isValid()) |
332 | 0 | { |
333 | 0 | if (aWalker.name() == "element") |
334 | 0 | { |
335 | 0 | svx::ClassificationType eType = svx::ClassificationType::TEXT; |
336 | 0 | OUString sString; |
337 | 0 | OUString sAbbreviatedString; |
338 | 0 | OUString sIdentifier; |
339 | | |
340 | | // Convert string to classification type, but continue only if |
341 | | // conversion was successful. |
342 | 0 | if (stringToClassificationType(aWalker.attribute("type"_ostr), eType)) |
343 | 0 | { |
344 | 0 | aWalker.children(); |
345 | |
|
346 | 0 | while (aWalker.isValid()) |
347 | 0 | { |
348 | 0 | if (aWalker.name() == "string") |
349 | 0 | { |
350 | 0 | sString = OStringToOUString(aWalker.content(), RTL_TEXTENCODING_UTF8); |
351 | 0 | } |
352 | 0 | else if (aWalker.name() == "abbreviatedString") |
353 | 0 | { |
354 | 0 | sAbbreviatedString = OStringToOUString(aWalker.content(), RTL_TEXTENCODING_UTF8); |
355 | 0 | } |
356 | 0 | else if (aWalker.name() == "identifier") |
357 | 0 | { |
358 | 0 | sIdentifier = OStringToOUString(aWalker.content(), RTL_TEXTENCODING_UTF8); |
359 | 0 | } |
360 | 0 | aWalker.next(); |
361 | 0 | } |
362 | 0 | aWalker.parent(); |
363 | |
|
364 | 0 | aResults.emplace_back(eType, sString, sAbbreviatedString, sIdentifier); |
365 | 0 | } |
366 | 0 | } |
367 | 0 | aWalker.next(); |
368 | 0 | } |
369 | 0 | aWalker.parent(); |
370 | 0 | m_aRecentlyUsedValuesCollection.push_back(std::move(aResults)); |
371 | 0 | } |
372 | 0 | aWalker.next(); |
373 | 0 | } |
374 | 0 | aWalker.parent(); |
375 | 0 | } |
376 | | |
377 | | void ClassificationDialog::writeRecentlyUsed() |
378 | 0 | { |
379 | 0 | OUString sPath = lcl_getClassificationUserPath(); |
380 | 0 | osl::Directory::createPath(sPath); |
381 | 0 | OUString sFilePath(sPath + constRecentlyUsedFileName); |
382 | |
|
383 | 0 | std::unique_ptr<SvStream> pStream; |
384 | 0 | pStream.reset(new SvFileStream(sFilePath, StreamMode::STD_READWRITE | StreamMode::TRUNC)); |
385 | |
|
386 | 0 | tools::XmlWriter aXmlWriter(pStream.get()); |
387 | |
|
388 | 0 | if (!aXmlWriter.startDocument()) |
389 | 0 | return; |
390 | | |
391 | 0 | aXmlWriter.startElement("recentlyUsedClassifications"); |
392 | |
|
393 | 0 | aXmlWriter.startElement("elementGroup"); |
394 | |
|
395 | 0 | writeResultToXml(aXmlWriter, getResult()); |
396 | |
|
397 | 0 | aXmlWriter.endElement(); |
398 | |
|
399 | 0 | if (m_aRecentlyUsedValuesCollection.size() >= RECENTLY_USED_LIMIT) |
400 | 0 | m_aRecentlyUsedValuesCollection.pop_back(); |
401 | |
|
402 | 0 | for (std::vector<ClassificationResult> const & rResultCollection : m_aRecentlyUsedValuesCollection) |
403 | 0 | { |
404 | 0 | aXmlWriter.startElement("elementGroup"); |
405 | |
|
406 | 0 | writeResultToXml(aXmlWriter, rResultCollection); |
407 | |
|
408 | 0 | aXmlWriter.endElement(); |
409 | 0 | } |
410 | |
|
411 | 0 | aXmlWriter.endElement(); |
412 | |
|
413 | 0 | aXmlWriter.endDocument(); |
414 | 0 | } |
415 | | |
416 | | void ClassificationDialog::readIn(std::vector<ClassificationResult> const & rInput) |
417 | 0 | { |
418 | 0 | sal_Int32 nParagraph = -1; |
419 | |
|
420 | 0 | for (ClassificationResult const & rClassificationResult : rInput) |
421 | 0 | { |
422 | |
|
423 | 0 | switch (rClassificationResult.meType) |
424 | 0 | { |
425 | 0 | case svx::ClassificationType::TEXT: |
426 | 0 | { |
427 | 0 | m_xEditWindow->getEditView().InsertText(rClassificationResult.msName); |
428 | 0 | } |
429 | 0 | break; |
430 | | |
431 | 0 | case svx::ClassificationType::CATEGORY: |
432 | 0 | { |
433 | 0 | OUString sName; |
434 | 0 | if (rClassificationResult.msName.isEmpty()) |
435 | 0 | sName = maHelper.GetBACNameForIdentifier(rClassificationResult.msIdentifier); |
436 | 0 | else |
437 | 0 | sName = rClassificationResult.msName; |
438 | |
|
439 | 0 | OUString sAbbreviatedName = rClassificationResult.msAbbreviatedName; |
440 | 0 | if (sAbbreviatedName.isEmpty()) |
441 | 0 | sAbbreviatedName = maHelper.GetAbbreviatedBACName(sName); |
442 | |
|
443 | 0 | m_xClassificationListBox->set_active_text(sName); |
444 | 0 | m_nCurrentSelectedCategory = m_xClassificationListBox->get_active(); |
445 | 0 | m_xInternationalClassificationListBox->set_active(m_xClassificationListBox->get_active()); |
446 | |
|
447 | 0 | insertField(rClassificationResult.meType, sAbbreviatedName, sName, rClassificationResult.msIdentifier); |
448 | 0 | } |
449 | 0 | break; |
450 | | |
451 | 0 | case svx::ClassificationType::MARKING: |
452 | 0 | { |
453 | 0 | m_xMarkingListBox->select_text(rClassificationResult.msName); |
454 | 0 | insertField(rClassificationResult.meType, rClassificationResult.msName, rClassificationResult.msName, rClassificationResult.msIdentifier); |
455 | 0 | } |
456 | 0 | break; |
457 | | |
458 | 0 | case svx::ClassificationType::INTELLECTUAL_PROPERTY_PART: |
459 | 0 | { |
460 | 0 | insertField(rClassificationResult.meType, rClassificationResult.msName, rClassificationResult.msName, rClassificationResult.msIdentifier); |
461 | 0 | } |
462 | 0 | break; |
463 | | |
464 | 0 | case svx::ClassificationType::PARAGRAPH: |
465 | 0 | { |
466 | 0 | nParagraph++; |
467 | |
|
468 | 0 | if (nParagraph != 0) |
469 | 0 | m_xEditWindow->getEditView().InsertParaBreak(); |
470 | | |
471 | | // Set paragraph font weight |
472 | 0 | FontWeight eWeight = (rClassificationResult.msName == "BOLD") ? WEIGHT_BOLD : WEIGHT_NORMAL; |
473 | |
|
474 | 0 | ClassificationEditEngine& rEdEngine = m_xEditWindow->getEditEngine(); |
475 | 0 | SfxItemSet aSet(rEdEngine.GetParaAttribs(nParagraph)); |
476 | 0 | aSet.Put(SvxWeightItem(eWeight, EE_CHAR_WEIGHT)); |
477 | 0 | rEdEngine.SetParaAttribs(nParagraph, aSet); |
478 | 0 | } |
479 | 0 | break; |
480 | | |
481 | 0 | default: |
482 | 0 | break; |
483 | 0 | } |
484 | 0 | } |
485 | 0 | toggleWidgetsDependingOnCategory(); |
486 | 0 | } |
487 | | |
488 | | void ClassificationDialog::toggleWidgetsDependingOnCategory() |
489 | 0 | { |
490 | 0 | const EditEngine& rEditEngine = m_xEditWindow->getEditEngine(); |
491 | |
|
492 | 0 | for (sal_Int32 nParagraph = 0; nParagraph < rEditEngine.GetParagraphCount(); ++nParagraph) |
493 | 0 | { |
494 | 0 | for (const EFieldInfo& rFieldInfo : rEditEngine.GetFieldInfo(nParagraph)) |
495 | 0 | { |
496 | 0 | if (rFieldInfo.pFieldItem) |
497 | 0 | { |
498 | 0 | const ClassificationField* pClassificationField = dynamic_cast<const ClassificationField*>(rFieldInfo.pFieldItem->GetField()); |
499 | 0 | if (pClassificationField && pClassificationField->meType == ClassificationType::CATEGORY) |
500 | 0 | { |
501 | 0 | m_xOkButton->set_sensitive(true); |
502 | 0 | return; |
503 | 0 | } |
504 | 0 | } |
505 | 0 | } |
506 | 0 | } |
507 | | |
508 | | // Category field in the text edit has been deleted, so reset the list boxes |
509 | 0 | m_xOkButton->set_sensitive(false); |
510 | 0 | m_xClassificationListBox->set_active(-1); |
511 | 0 | m_xInternationalClassificationListBox->set_active(-1); |
512 | 0 | } |
513 | | |
514 | | std::vector<ClassificationResult> ClassificationDialog::getResult() |
515 | 0 | { |
516 | 0 | std::vector<ClassificationResult> aClassificationResults; |
517 | |
|
518 | 0 | ClassificationEditEngine& rEdEngine = m_xEditWindow->getEditEngine(); |
519 | 0 | EditTextObject aEditText(rEdEngine.CreateTextObject()); |
520 | |
|
521 | 0 | sal_Int32 nCurrentParagraph = -1; |
522 | |
|
523 | 0 | std::vector<editeng::Section> aSections; |
524 | 0 | aEditText.GetAllSections(aSections); |
525 | 0 | for (editeng::Section const & rSection : aSections) |
526 | 0 | { |
527 | 0 | while (nCurrentParagraph < rSection.mnParagraph) |
528 | 0 | { |
529 | 0 | nCurrentParagraph++; |
530 | | |
531 | | // Get Weight of current paragraph |
532 | 0 | FontWeight eFontWeight = WEIGHT_NORMAL; |
533 | 0 | SfxItemSet aItemSet(rEdEngine.GetParaAttribs(nCurrentParagraph)); |
534 | 0 | if (const SfxPoolItem* pItem = aItemSet.GetItem(EE_CHAR_WEIGHT, false)) |
535 | 0 | { |
536 | 0 | const SvxWeightItem* pWeightItem = dynamic_cast<const SvxWeightItem*>(pItem); |
537 | 0 | if (pWeightItem && pWeightItem->GetWeight() == WEIGHT_BOLD) |
538 | 0 | eFontWeight = WEIGHT_BOLD; |
539 | 0 | } |
540 | | // Font weight to string |
541 | 0 | OUString sWeightProperty = u"NORMAL"_ustr; |
542 | 0 | if (eFontWeight == WEIGHT_BOLD) |
543 | 0 | sWeightProperty = "BOLD"; |
544 | | // Insert into collection |
545 | 0 | OUString sBlank; |
546 | 0 | aClassificationResults.emplace_back(ClassificationType::PARAGRAPH, sWeightProperty, sBlank, sBlank); |
547 | 0 | } |
548 | |
|
549 | 0 | const SvxFieldItem* pFieldItem = findField(rSection); |
550 | |
|
551 | 0 | ESelection aSelection(rSection.mnParagraph, rSection.mnStart, rSection.mnParagraph, rSection.mnEnd); |
552 | 0 | const OUString sDisplayString = rEdEngine.GetText(aSelection); |
553 | 0 | if (!sDisplayString.isEmpty()) |
554 | 0 | { |
555 | 0 | const ClassificationField* pClassificationField = pFieldItem ? dynamic_cast<const ClassificationField*>(pFieldItem->GetField()) : nullptr; |
556 | |
|
557 | 0 | if (pClassificationField) |
558 | 0 | { |
559 | 0 | aClassificationResults.emplace_back(pClassificationField->meType, pClassificationField->msFullClassName, |
560 | 0 | pClassificationField->msDescription, pClassificationField->msIdentifier); |
561 | 0 | } |
562 | 0 | else |
563 | 0 | { |
564 | 0 | aClassificationResults.emplace_back(ClassificationType::TEXT, sDisplayString, sDisplayString, OUString()); |
565 | 0 | } |
566 | 0 | } |
567 | 0 | } |
568 | |
|
569 | 0 | return aClassificationResults; |
570 | 0 | } |
571 | | |
572 | | IMPL_LINK(ClassificationDialog, SelectClassificationHdl, weld::ComboBox&, rBox, void) |
573 | 0 | { |
574 | 0 | const sal_Int32 nSelected = rBox.get_active(); |
575 | 0 | if (nSelected < 0 || m_nCurrentSelectedCategory == nSelected) |
576 | 0 | return; |
577 | | |
578 | 0 | EditTextObject aEditText(m_xEditWindow->getEditEngine().CreateTextObject()); |
579 | 0 | std::vector<editeng::Section> aSections; |
580 | 0 | aEditText.GetAllSections(aSections); |
581 | | |
582 | | // if we are replacing an existing field |
583 | 0 | bool bReplaceExisting = false; |
584 | | // selection of the existing field, which will be replaced |
585 | 0 | ESelection aExistingFieldSelection; |
586 | |
|
587 | 0 | for (editeng::Section const & rSection : aSections) |
588 | 0 | { |
589 | 0 | const SvxFieldItem* pFieldItem = findField(rSection); |
590 | 0 | if (pFieldItem) |
591 | 0 | { |
592 | 0 | const ClassificationField* pClassificationField = dynamic_cast<const ClassificationField*>(pFieldItem->GetField()); |
593 | 0 | if (pClassificationField && pClassificationField->meType == ClassificationType::CATEGORY) |
594 | 0 | { |
595 | 0 | aExistingFieldSelection = ESelection(rSection.mnParagraph, rSection.mnStart, |
596 | 0 | rSection.mnParagraph, rSection.mnEnd); |
597 | 0 | bReplaceExisting = true; |
598 | 0 | } |
599 | 0 | } |
600 | 0 | } |
601 | |
|
602 | 0 | if (bReplaceExisting) |
603 | 0 | m_xEditWindow->getEditView().SetSelection(aExistingFieldSelection); |
604 | |
|
605 | 0 | insertCategoryField(nSelected); |
606 | | |
607 | | // Change category to the new selection |
608 | 0 | m_xInternationalClassificationListBox->set_active(nSelected); |
609 | 0 | m_xClassificationListBox->set_active(nSelected); |
610 | 0 | m_nCurrentSelectedCategory = nSelected; |
611 | 0 | } |
612 | | |
613 | | IMPL_LINK_NOARG(ClassificationDialog, SelectMarkingHdl, const weld::TreeIter&, bool) |
614 | 0 | { |
615 | 0 | sal_Int32 nSelected = m_xMarkingListBox->get_selected_index(); |
616 | 0 | if (nSelected >= 0) |
617 | 0 | { |
618 | 0 | const OUString aString = maHelper.GetMarkings()[nSelected]; |
619 | 0 | insertField(ClassificationType::MARKING, aString, aString); |
620 | 0 | } |
621 | 0 | return true; |
622 | 0 | } |
623 | | |
624 | | IMPL_LINK_NOARG(ClassificationDialog, SelectIPPartNumbersHdl, const weld::TreeIter&, bool) |
625 | 0 | { |
626 | 0 | sal_Int32 nSelected = m_xIntellectualPropertyPartNumberListBox->get_selected_index(); |
627 | 0 | if (nSelected >= 0) |
628 | 0 | { |
629 | 0 | OUString sString = maHelper.GetIntellectualPropertyPartNumbers()[nSelected]; |
630 | 0 | m_xIntellectualPropertyPartEdit->replace_selection(sString); |
631 | 0 | m_xIntellectualPropertyPartEdit->grab_focus(); |
632 | 0 | } |
633 | 0 | return true; |
634 | 0 | } |
635 | | |
636 | | IMPL_LINK(ClassificationDialog, SelectRecentlyUsedHdl, weld::ComboBox&, rBox, void) |
637 | 0 | { |
638 | 0 | sal_Int32 nSelected = rBox.get_active(); |
639 | 0 | if (nSelected >= 0) |
640 | 0 | { |
641 | 0 | m_xEditWindow->getEditEngine().Clear(); |
642 | 0 | readIn(m_aRecentlyUsedValuesCollection[nSelected]); |
643 | 0 | } |
644 | 0 | } |
645 | | |
646 | | IMPL_LINK_NOARG(ClassificationDialog, SelectIPPartHdl, const weld::TreeIter&, bool) |
647 | 0 | { |
648 | 0 | const sal_Int32 nSelected = m_xIntellectualPropertyPartListBox->get_selected_index(); |
649 | 0 | if (nSelected >= 0) |
650 | 0 | { |
651 | 0 | const OUString sString = maHelper.GetIntellectualPropertyParts()[nSelected]; |
652 | 0 | m_xIntellectualPropertyPartEdit->replace_selection(sString); |
653 | 0 | m_xIntellectualPropertyPartEdit->grab_focus(); |
654 | 0 | } |
655 | 0 | return true; |
656 | 0 | } |
657 | | |
658 | | IMPL_LINK(ClassificationDialog, ButtonClicked, weld::Button&, rButton, void) |
659 | 0 | { |
660 | 0 | if (&rButton == m_xSignButton.get()) |
661 | 0 | { |
662 | 0 | m_aParagraphSignHandler(); |
663 | 0 | } |
664 | 0 | else if (&rButton == m_xIntellectualPropertyPartAddButton.get()) |
665 | 0 | { |
666 | 0 | const OUString sString = m_xIntellectualPropertyPartEdit->get_text(); |
667 | 0 | insertField(ClassificationType::INTELLECTUAL_PROPERTY_PART, sString, sString); |
668 | 0 | } |
669 | 0 | } |
670 | | |
671 | | IMPL_LINK_NOARG(ClassificationDialog, OkHdl, weld::Button&, void) |
672 | 0 | { |
673 | 0 | writeRecentlyUsed(); |
674 | 0 | m_xDialog->response(RET_OK); |
675 | 0 | } |
676 | | |
677 | | IMPL_LINK_NOARG(ClassificationDialog, SelectToolboxHdl, weld::Toggleable&, void) |
678 | 0 | { |
679 | 0 | m_xEditWindow->InvertSelectionWeight(); |
680 | 0 | } |
681 | | |
682 | | IMPL_LINK_NOARG(ClassificationDialog, EditWindowModifiedHdl, LinkParamNone*, void) |
683 | 0 | { |
684 | 0 | toggleWidgetsDependingOnCategory(); |
685 | 0 | } |
686 | | |
687 | | IMPL_STATIC_LINK(ClassificationDialog, ExpandedHdl, weld::Expander&, rExpander, void) |
688 | 0 | { |
689 | 0 | std::shared_ptr<comphelper::ConfigurationChanges> aConfigurationChanges(comphelper::ConfigurationChanges::create()); |
690 | 0 | officecfg::Office::Common::Classification::IntellectualPropertySectionExpanded::set(rExpander.get_expanded(), aConfigurationChanges); |
691 | 0 | aConfigurationChanges->commit(); |
692 | 0 | } |
693 | | |
694 | | } // end svx |
695 | | |
696 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |