LibreOffice Module sfx2 (master) 1
autoredactdialog.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include <autoredactdialog.hxx>
11
13#include <sfx2/sfxresid.hxx>
14#include <sfx2/strings.hrc>
15
16#include <osl/file.hxx>
17#include <sal/log.hxx>
18#include <vcl/svapp.hxx>
19#include <vcl/weld.hxx>
21#include <o3tl/string_view.hxx>
22
23#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
24
25#include <boost/property_tree/json_parser.hpp>
26
27constexpr OUStringLiteral FILEDIALOG_FILTER_JSON = u"*.json";
28
29int TargetsTable::GetRowByTargetName(std::u16string_view sName)
30{
31 for (int i = 0, nCount = m_xControl->n_children(); i < nCount; ++i)
32 {
33 RedactionTarget* pTarget = weld::fromId<RedactionTarget*>(m_xControl->get_id(i));
34 if (pTarget->sName == sName)
35 {
36 return i;
37 }
38 }
39 return -1;
40}
41
42TargetsTable::TargetsTable(std::unique_ptr<weld::TreeView> xControl)
43 : m_xControl(std::move(xControl))
44{
45 m_xControl->set_size_request(555, 250);
46 std::vector<int> aWidths{ 100, 50, 200, 105, 105 };
47 m_xControl->set_column_fixed_widths(aWidths);
48 m_xControl->set_selection_mode(SelectionMode::Multiple);
49}
50
51namespace
52{
53OUString getTypeName(RedactionTargetType nType)
54{
55 OUString sTypeName(SfxResId(STR_REDACTION_TARGET_TYPE_UNKNOWN));
56
57 switch (nType)
58 {
60 sTypeName = SfxResId(STR_REDACTION_TARGET_TYPE_TEXT);
61 break;
63 sTypeName = SfxResId(STR_REDACTION_TARGET_TYPE_REGEX);
64 break;
66 sTypeName = SfxResId(STR_REDACTION_TARGET_TYPE_PREDEF);
67 break;
69 sTypeName = SfxResId(STR_REDACTION_TARGET_TYPE_UNKNOWN);
70 break;
71 }
72
73 return sTypeName;
74}
75
77OUString getTypeID(RedactionTargetType nType)
78{
79 OUString sTypeID("unknown");
80
81 switch (nType)
82 {
84 sTypeID = "text";
85 break;
87 sTypeID = "regex";
88 break;
90 sTypeID = "predefined";
91 break;
93 sTypeID = "unknown";
94 break;
95 }
96
97 return sTypeID;
98}
99}
100
102{
103 if (!pTarget)
104 {
105 SAL_WARN("sfx.doc", "pTarget is null in TargetsTable::InsertTarget()");
106 return;
107 }
108
109 // Check if the name is empty or invalid (clashing with another entry's name)
110 if (pTarget->sName.isEmpty() || GetRowByTargetName(pTarget->sName) != -1)
111 {
112 pTarget->sName = GetNameProposal();
113 }
114
115 OUString sContent = pTarget->sContent;
116
118 {
119 //selection_num;selection_name
120 sContent = sContent.getToken(1, ';');
121 }
122
123 // Add to the end
124 int nRow = m_xControl->n_children();
125 m_xControl->append(weld::toId(pTarget), pTarget->sName);
126 m_xControl->set_text(nRow, getTypeName(pTarget->sType), 1);
127 m_xControl->set_text(nRow, sContent, 2);
128 m_xControl->set_text(
129 nRow, pTarget->bCaseSensitive ? SfxResId(STR_REDACTION_YES) : SfxResId(STR_REDACTION_NO),
130 3);
131 m_xControl->set_text(
132 nRow, pTarget->bWholeWords ? SfxResId(STR_REDACTION_YES) : SfxResId(STR_REDACTION_NO), 4);
133}
134
136{
137 int nEntry = GetRowByTargetName(sName);
138 if (nEntry == -1)
139 return nullptr;
140
141 return weld::fromId<RedactionTarget*>(m_xControl->get_id(nEntry));
142}
143
145{
146 OUString sDefaultTargetName(SfxResId(STR_REDACTION_TARGET));
147 sal_Int32 nHighestTargetId = 0;
148 for (int i = 0, nCount = m_xControl->n_children(); i < nCount; ++i)
149 {
150 RedactionTarget* pTarget = weld::fromId<RedactionTarget*>(m_xControl->get_id(i));
151 const OUString& sName = pTarget->sName;
152 sal_Int32 nIndex = 0;
153 if (o3tl::getToken(sName, 0, ' ', nIndex) == sDefaultTargetName)
154 {
155 sal_Int32 nCurrTargetId = o3tl::toInt32(o3tl::getToken(sName, 0, ' ', nIndex));
156 nHighestTargetId = std::max<sal_Int32>(nHighestTargetId, nCurrTargetId);
157 }
158 }
159 return sDefaultTargetName + " " + OUString::number(nHighestTargetId + 1);
160}
161
162void TargetsTable::setRowData(int nRowIndex, const RedactionTarget* pTarget)
163{
164 OUString sContent = pTarget->sContent;
165
167 {
168 //selection_num;selection_name
169 sContent = sContent.getToken(1, ';');
170 }
171
172 m_xControl->set_text(nRowIndex, pTarget->sName, 0);
173 m_xControl->set_text(nRowIndex, getTypeName(pTarget->sType), 1);
174 m_xControl->set_text(nRowIndex, sContent, 2);
175 m_xControl->set_text(
176 nRowIndex,
177 pTarget->bCaseSensitive ? SfxResId(STR_REDACTION_YES) : SfxResId(STR_REDACTION_NO), 3);
178 m_xControl->set_text(
179 nRowIndex, pTarget->bWholeWords ? SfxResId(STR_REDACTION_YES) : SfxResId(STR_REDACTION_NO),
180 4);
181}
182
184{
185 //Load a targets list from a previously saved file (a json file?)
186 // ask for filename, where we should load the new config data from
187 StartFileDialog(StartFileDialogType::Open, SfxResId(STR_REDACTION_LOAD_TARGETS));
188}
189
191{
192 //Allow saving the targets into a file
193 StartFileDialog(StartFileDialogType::SaveAs, SfxResId(STR_REDACTION_SAVE_TARGETS));
194}
195
197{
198 // Open the Add Target dialog, create a new target and insert into the targets vector and the listbox
199 SfxAddTargetDialog aAddTargetDialog(getDialog(), m_aTargetsBox.GetNameProposal());
200
201 bool bIncomplete;
202 do
203 {
204 bIncomplete = false;
205
206 if (aAddTargetDialog.run() != RET_OK)
207 return;
208
209 if (aAddTargetDialog.getName().isEmpty()
211 || aAddTargetDialog.getContent().isEmpty())
212 {
213 bIncomplete = true;
214 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
215 getDialog(), VclMessageType::Warning, VclButtonsType::Ok,
216 SfxResId(STR_REDACTION_FIELDS_REQUIRED)));
217 xBox->run();
218 }
219 else if (m_aTargetsBox.GetTargetByName(aAddTargetDialog.getName()))
220 {
221 bIncomplete = true;
222 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
223 getDialog(), VclMessageType::Warning, VclButtonsType::Ok,
224 SfxResId(STR_REDACTION_TARGET_NAME_CLASH)));
225 xBox->run();
226 }
227
228 } while (bIncomplete);
229
230 //Alright, we now have everything we need to construct a new target
231 RedactionTarget* redactiontarget = new RedactionTarget(
232 { aAddTargetDialog.getName(), aAddTargetDialog.getType(), aAddTargetDialog.getContent(),
233 aAddTargetDialog.isCaseSensitive(), aAddTargetDialog.isWholeWords(), 0 });
234
235 // Only the visual/display part
236 m_aTargetsBox.InsertTarget(redactiontarget);
237
238 // Actually add to the targets vector
239 if (m_aTargetsBox.GetTargetByName(redactiontarget->sName))
240 m_aTableTargets.emplace_back(redactiontarget, redactiontarget->sName);
241 else
242 {
243 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
244 getDialog(), VclMessageType::Warning, VclButtonsType::Ok,
245 SfxResId(STR_REDACTION_TARGET_ADD_ERROR)));
246 xBox->run();
247 delete redactiontarget;
248 }
249}
250
252{
253 sal_Int32 nSelectedRow = m_aTargetsBox.get_selected_index();
254
255 // No selection, nothing to edit
256 if (nSelectedRow < 0)
257 return;
258
259 // Only one entry should be selected for editing
260 if (m_aTargetsBox.get_selected_rows().size() > 1)
261 {
262 //Warn the user about multiple selections
263 std::unique_ptr<weld::MessageDialog> xBox(
264 Application::CreateMessageDialog(getDialog(), VclMessageType::Error, VclButtonsType::Ok,
265 SfxResId(STR_REDACTION_MULTI_EDIT)));
266 xBox->run();
267 return;
268 }
269
270 // Get the redaction target to be edited
271 RedactionTarget* pTarget = weld::fromId<RedactionTarget*>(m_aTargetsBox.get_id(nSelectedRow));
272
273 // Construct and run the edit target dialog
274 SfxAddTargetDialog aEditTargetDialog(getDialog(), pTarget->sName, pTarget->sType,
275 pTarget->sContent, pTarget->bCaseSensitive,
276 pTarget->bWholeWords);
277
278 bool bIncomplete;
279 do
280 {
281 bIncomplete = false;
282
283 if (aEditTargetDialog.run() != RET_OK)
284 return;
285
286 if (aEditTargetDialog.getName().isEmpty()
288 || aEditTargetDialog.getContent().isEmpty())
289 {
290 bIncomplete = true;
291 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
292 getDialog(), VclMessageType::Warning, VclButtonsType::Ok,
293 SfxResId(STR_REDACTION_FIELDS_REQUIRED)));
294 xBox->run();
295 }
296 else if (aEditTargetDialog.getName() != pTarget->sName
297 && m_aTargetsBox.GetTargetByName(aEditTargetDialog.getName()))
298 {
299 bIncomplete = true;
300 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
301 getDialog(), VclMessageType::Warning, VclButtonsType::Ok,
302 SfxResId(STR_REDACTION_TARGET_NAME_CLASH)));
303 xBox->run();
304 }
305
306 } while (bIncomplete);
307
308 // Update the redaction target
309 pTarget->sName = aEditTargetDialog.getName();
310 pTarget->sType = aEditTargetDialog.getType();
311 pTarget->sContent = aEditTargetDialog.getContent();
312 pTarget->bCaseSensitive = aEditTargetDialog.isCaseSensitive();
313 pTarget->bWholeWords = aEditTargetDialog.isWholeWords();
314
315 // And sync the targets box row with the actual target data
316 m_aTargetsBox.setRowData(nSelectedRow, pTarget);
317}
319{
320 if (m_xEditBtn->get_sensitive())
321 m_xEditBtn->clicked();
322 return true;
323}
325{
326 std::vector<int> aSelectedRows = m_aTargetsBox.get_selected_rows();
327
328 //No selection, so nothing to delete
329 if (aSelectedRows.empty())
330 return;
331
332 if (aSelectedRows.size() > 1)
333 {
334 OUString sMsg(SfxResId(STR_REDACTION_MULTI_DELETE)
335 .replaceFirst("$(TARGETSCOUNT)", OUString::number(aSelectedRows.size())));
336 //Warn the user about multiple deletions
337 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
338 getDialog(), VclMessageType::Question, VclButtonsType::OkCancel, sMsg));
339 if (xBox->run() == RET_CANCEL)
340 return;
341 }
342
343 // After each delete, the indexes of the following items decrease by one.
344 int delta = 0;
345 for (const auto& i : aSelectedRows)
346 {
347 m_aTableTargets.erase(m_aTableTargets.begin() + (i - delta));
348 m_aTargetsBox.remove(i - delta++);
349 }
350}
351
352namespace
353{
354boost::property_tree::ptree redactionTargetToJSON(const RedactionTarget* pTarget)
355{
356 boost::property_tree::ptree aNode;
357 aNode.put("sName", pTarget->sName.toUtf8().getStr());
358 aNode.put("eType", pTarget->sType);
359 aNode.put("sContent", pTarget->sContent.toUtf8().getStr());
360 aNode.put("bWholeWords", pTarget->bWholeWords);
361 aNode.put("bCaseSensitive", pTarget->bCaseSensitive);
362 aNode.put("nID", pTarget->nID);
363
364 return aNode;
365}
366
367std::unique_ptr<RedactionTarget>
368JSONtoRedactionTarget(const boost::property_tree::ptree::value_type& rValue)
369{
370 OUString sName = OUString::fromUtf8(rValue.second.get<std::string>("sName"));
372 = static_cast<RedactionTargetType>(atoi(rValue.second.get<std::string>("eType").c_str()));
373 OUString sContent = OUString::fromUtf8(rValue.second.get<std::string>("sContent"));
374 bool bCaseSensitive
375 = OUString::fromUtf8(rValue.second.get<std::string>("bCaseSensitive")).toBoolean();
376 bool bWholeWords
377 = OUString::fromUtf8(rValue.second.get<std::string>("bWholeWords")).toBoolean();
378 sal_uInt32 nID = atoi(rValue.second.get<std::string>("nID").c_str());
379
380 return std::unique_ptr<RedactionTarget>(
381 new RedactionTarget{ sName, eType, sContent, bCaseSensitive, bWholeWords, nID });
382}
383}
384
386{
387 assert(m_pFileDlg);
388
389 OUString sTargetsFile;
390 if (ERRCODE_NONE == m_pFileDlg->GetError())
391 sTargetsFile = m_pFileDlg->GetPath();
392
393 if (sTargetsFile.isEmpty())
394 return;
395
396 OUString sSysPath;
397 osl::File::getSystemPathFromFileURL(sTargetsFile, sSysPath);
398 sTargetsFile = sSysPath;
399
400 weld::WaitObject aWaitObject(getDialog());
401
402 try
403 {
404 // Create path string, and read JSON from file
405 std::string sPathStr(OUStringToOString(sTargetsFile, RTL_TEXTENCODING_UTF8));
406
407 boost::property_tree::ptree aTargetsJSON;
408
409 boost::property_tree::read_json(sPathStr, aTargetsJSON);
410
411 // Clear the dialog
412 clearTargets();
413
414 // Recreate & add the targets to the dialog
415 for (const boost::property_tree::ptree::value_type& rValue :
416 aTargetsJSON.get_child("RedactionTargets"))
417 {
418 addTarget(JSONtoRedactionTarget(rValue));
419 }
420 }
421 catch (css::uno::Exception& e)
422 {
423 SAL_WARN("sfx.doc",
424 "Exception caught while trying to load the targets JSON from file: " << e.Message);
425 return;
426 //TODO: Warn the user with a message box
427 }
428}
429
431{
432 assert(m_pFileDlg);
433
434 OUString sTargetsFile;
435 if (ERRCODE_NONE == m_pFileDlg->GetError())
436 sTargetsFile = m_pFileDlg->GetPath();
437
438 if (sTargetsFile.isEmpty())
439 return;
440
441 OUString sSysPath;
442 osl::File::getSystemPathFromFileURL(sTargetsFile, sSysPath);
443 sTargetsFile = sSysPath;
444
445 weld::WaitObject aWaitObject(getDialog());
446
447 try
448 {
449 // Put the targets into a JSON array
450 boost::property_tree::ptree aTargetsArray;
451 for (const auto& targetPair : m_aTableTargets)
452 {
453 aTargetsArray.push_back(
454 std::make_pair("", redactionTargetToJSON(targetPair.first.get())));
455 }
456
457 // Build the JSON tree
458 boost::property_tree::ptree aTargetsTree;
459 aTargetsTree.add_child("RedactionTargets", aTargetsArray);
460
461 // Create path string, and write JSON to file
462 std::string sPathStr(OUStringToOString(sTargetsFile, RTL_TEXTENCODING_UTF8));
463
464 boost::property_tree::write_json(sPathStr, aTargetsTree);
465 }
466 catch (css::uno::Exception& e)
467 {
468 SAL_WARN("sfx.doc",
469 "Exception caught while trying to save the targets JSON to file: " << e.Message);
470 return;
471 //TODO: Warn the user with a message box
472 }
473}
474
476{
477 OUString aFilterAllStr(SfxResId(STR_SFX_FILTERNAME_ALL));
478 OUString aFilterJsonStr(SfxResId(STR_REDACTION_JSON_FILE_FILTER));
479
480 bool bSave = nType == StartFileDialogType::SaveAs;
481 short nDialogType = bSave ? css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION
482 : css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE;
484
485 m_pFileDlg->SetTitle(rTitle);
486 m_pFileDlg->AddFilter(aFilterAllStr, FILEDIALOG_FILTER_ALL);
487 m_pFileDlg->AddFilter(aFilterJsonStr, FILEDIALOG_FILTER_JSON);
488 m_pFileDlg->SetCurrentFilter(aFilterJsonStr);
489
491 = bSave ? LINK(this, SfxAutoRedactDialog, SaveHdl)
492 : LINK(this, SfxAutoRedactDialog, LoadHdl);
494 m_pFileDlg->StartExecuteModal(aDlgClosedLink);
495}
496
497void SfxAutoRedactDialog::addTarget(std::unique_ptr<RedactionTarget> pTarget)
498{
499 // Only the visual/display part
500 m_aTargetsBox.InsertTarget(pTarget.get());
501
502 // Actually add to the targets vector
503 auto name = pTarget->sName;
505 m_aTableTargets.emplace_back(std::move(pTarget), name);
506 else
507 {
508 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(
509 getDialog(), VclMessageType::Warning, VclButtonsType::Ok,
510 SfxResId(STR_REDACTION_TARGET_ADD_ERROR)));
511 xBox->run();
512 }
513}
514
516{
517 // Clear the targets box
519
520 // Clear the targets vector
521 m_aTableTargets.clear();
522}
523
525 : SfxDialogController(pParent, "sfx/ui/autoredactdialog.ui", "AutoRedactDialog")
526 , m_bIsValidState(true)
527 , m_bTargetsCopied(false)
528 , m_aTargetsBox(m_xBuilder->weld_tree_view("targets"))
529 , m_xLoadBtn(m_xBuilder->weld_button("btnLoadTargets"))
530 , m_xSaveBtn(m_xBuilder->weld_button("btnSaveTargets"))
531 , m_xAddBtn(m_xBuilder->weld_button("add"))
532 , m_xEditBtn(m_xBuilder->weld_button("edit"))
533 , m_xDeleteBtn(m_xBuilder->weld_button("delete"))
534{
535 // Can be used to remember the last set of redaction targets?
536 OUString sExtraData;
537 SvtViewOptions aDlgOpt(EViewType::Dialog, m_xDialog->get_help_id());
538
539 if (aDlgOpt.Exists())
540 {
541 css::uno::Any aUserItem = aDlgOpt.GetUserItem("UserItem");
542 aUserItem >>= sExtraData;
543 }
544
545 // update the targets configuration if necessary
546 if (!sExtraData.isEmpty())
547 {
548 weld::WaitObject aWaitCursor(m_xDialog.get());
549
550 try
551 {
552 // Create path string, and read JSON from file
553 boost::property_tree::ptree aTargetsJSON;
554 std::stringstream aStream(std::string(sExtraData.toUtf8()));
555
556 boost::property_tree::read_json(aStream, aTargetsJSON);
557
558 // Recreate & add the targets to the dialog
559 for (const boost::property_tree::ptree::value_type& rValue :
560 aTargetsJSON.get_child("RedactionTargets"))
561 {
562 addTarget(JSONtoRedactionTarget(rValue));
563 }
564 }
565 catch (css::uno::Exception& e)
566 {
567 SAL_WARN("sfx.doc",
568 "Exception caught while trying to load the last dialog state: " << e.Message);
569 return;
570 //TODO: Warn the user with a message box
571 }
572 }
573
574 // Handler connections
575 m_xLoadBtn->connect_clicked(LINK(this, SfxAutoRedactDialog, Load));
576 m_xSaveBtn->connect_clicked(LINK(this, SfxAutoRedactDialog, Save));
577 m_xAddBtn->connect_clicked(LINK(this, SfxAutoRedactDialog, AddHdl));
578 m_xEditBtn->connect_clicked(LINK(this, SfxAutoRedactDialog, EditHdl));
579 m_xDeleteBtn->connect_clicked(LINK(this, SfxAutoRedactDialog, DeleteHdl));
581}
582
584{
585 if (m_aTableTargets.empty())
586 {
587 // Clear the dialog data
588 SvtViewOptions aDlgOpt(EViewType::Dialog, m_xDialog->get_help_id());
589 aDlgOpt.Delete();
590 return;
591 }
592
593 try
594 {
595 // Put the targets into a JSON array
596 boost::property_tree::ptree aTargetsArray;
597 for (const auto& targetPair : m_aTableTargets)
598 {
599 aTargetsArray.push_back(
600 std::make_pair("", redactionTargetToJSON(targetPair.first.get())));
601 }
602
603 // Build the JSON tree
604 boost::property_tree::ptree aTargetsTree;
605 aTargetsTree.add_child("RedactionTargets", aTargetsArray);
606 std::stringstream aStream;
607
608 boost::property_tree::write_json(aStream, aTargetsTree, false);
609
610 OUString sUserDataStr(OUString::fromUtf8(aStream.str()));
611
612 // Store the dialog data
613 SvtViewOptions aDlgOpt(EViewType::Dialog, m_xDialog->get_help_id());
614 aDlgOpt.SetUserItem("UserItem", css::uno::Any(sUserDataStr));
615
616 if (!m_bTargetsCopied)
617 clearTargets();
618 }
619 catch (css::uno::Exception& e)
620 {
621 SAL_WARN("sfx.doc",
622 "Exception caught while trying to store the dialog state: " << e.Message);
623 return;
624 //TODO: Warn the user with a message box
625 }
626}
627
629{
630 //TODO: Add also some validity checks?
631 if (m_aTableTargets.empty())
632 return false;
633
634 return true;
635}
636
637bool SfxAutoRedactDialog::getTargets(std::vector<std::pair<RedactionTarget, OUString>>& r_aTargets)
638{
639 if (m_aTableTargets.empty())
640 return true;
641
642 for (auto const& rPair : m_aTableTargets)
643 r_aTargets.push_back({ *rPair.first, rPair.second });
644 m_bTargetsCopied = true;
645 return true;
646}
647
649{
650 if (m_xType->get_active_id() == "predefined")
651 {
652 // Hide the usual content widgets
653 // We will just set the id as content
654 // And handle with proper regex in the SfxRedactionHelper
655 m_xLabelContent->set_sensitive(false);
656 m_xLabelContent->set_visible(false);
657 m_xContent->set_sensitive(false);
658 m_xContent->set_visible(false);
659 m_xWholeWords->set_sensitive(false);
660 m_xWholeWords->set_visible(false);
661 m_xCaseSensitive->set_sensitive(false);
662 m_xCaseSensitive->set_visible(false);
663
664 // And show the predefined targets
665 m_xLabelPredefContent->set_sensitive(true);
666 m_xLabelPredefContent->set_visible(true);
667 m_xPredefContent->set_sensitive(true);
668 m_xPredefContent->set_visible(true);
669 }
670 else
671 {
672 m_xLabelPredefContent->set_sensitive(false);
673 m_xLabelPredefContent->set_visible(false);
674 m_xPredefContent->set_sensitive(false);
675 m_xPredefContent->set_visible(false);
676
677 m_xLabelContent->set_sensitive(true);
678 m_xLabelContent->set_visible(true);
679 m_xContent->set_sensitive(true);
680 m_xContent->set_visible(true);
681 m_xWholeWords->set_sensitive(true);
682 m_xWholeWords->set_visible(true);
683 m_xCaseSensitive->set_sensitive(true);
684 m_xCaseSensitive->set_visible(true);
685 }
686}
687
689 : GenericDialogController(pParent, "sfx/ui/addtargetdialog.ui", "AddTargetDialog")
690 , m_xName(m_xBuilder->weld_entry("name"))
691 , m_xType(m_xBuilder->weld_combo_box("type"))
692 , m_xLabelContent(m_xBuilder->weld_label("label_content"))
693 , m_xContent(m_xBuilder->weld_entry("content"))
694 , m_xLabelPredefContent(m_xBuilder->weld_label("label_content_predef"))
695 , m_xPredefContent(m_xBuilder->weld_combo_box("content_predef"))
696 , m_xCaseSensitive(m_xBuilder->weld_check_button("checkboxCaseSensitive"))
697 , m_xWholeWords(m_xBuilder->weld_check_button("checkboxWholeWords"))
698{
699 m_xName->set_text(rName);
700 m_xName->select_region(0, rName.getLength());
701
702 m_xType->connect_changed(LINK(this, SfxAddTargetDialog, SelectTypeHdl));
703}
704
706 const RedactionTargetType& eTargetType,
707 const OUString& sContent, bool bCaseSensitive,
708 bool bWholeWords)
709 : GenericDialogController(pParent, "sfx/ui/addtargetdialog.ui", "AddTargetDialog")
710 , m_xName(m_xBuilder->weld_entry("name"))
711 , m_xType(m_xBuilder->weld_combo_box("type"))
712 , m_xLabelContent(m_xBuilder->weld_label("label_content"))
713 , m_xContent(m_xBuilder->weld_entry("content"))
714 , m_xLabelPredefContent(m_xBuilder->weld_label("label_content_predef"))
715 , m_xPredefContent(m_xBuilder->weld_combo_box("content_predef"))
716 , m_xCaseSensitive(m_xBuilder->weld_check_button("checkboxCaseSensitive"))
717 , m_xWholeWords(m_xBuilder->weld_check_button("checkboxWholeWords"))
718{
719 m_xName->set_text(sName);
720 m_xName->select_region(0, sName.getLength());
721
722 m_xType->set_active_id(getTypeID(eTargetType));
723 m_xType->connect_changed(LINK(this, SfxAddTargetDialog, SelectTypeHdl));
724
726 {
727 SelectTypeHdl(*m_xPredefContent);
728 m_xPredefContent->set_active(o3tl::toInt32(o3tl::getToken(sContent, 0, ';')));
729 }
730 else
731 {
732 m_xContent->set_text(sContent);
733 }
734
735 m_xCaseSensitive->set_active(bCaseSensitive);
736 m_xWholeWords->set_active(bWholeWords);
737
738 set_title(SfxResId(STR_REDACTION_EDIT_TARGET));
739}
740
742{
743 OUString sTypeID = m_xType->get_active_id();
744
745 if (sTypeID == "text")
747 else if (sTypeID == "regex")
749 else if (sTypeID == "predefined")
751 else
753}
754
756{
757 if (m_xType->get_active_id() == "predefined")
758 {
759 return OUString(OUString::number(m_xPredefContent->get_active()) + ";"
760 + m_xPredefContent->get_active_text());
761 }
762
763 return m_xContent->get_text();
764}
765
766/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
uno::Reference< ucb::XContent > m_xContent
StartFileDialogType
IMPL_LINK_NOARG(SfxAutoRedactDialog, Load, weld::Button &, void)
constexpr OUStringLiteral FILEDIALOG_FILTER_JSON
RedactionTargetType
@ REDACTION_TARGET_UNKNOWN
@ REDACTION_TARGET_REGEX
@ REDACTION_TARGET_TEXT
@ REDACTION_TARGET_PREDEFINED
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
std::unique_ptr< weld::CheckButton > m_xCaseSensitive
std::unique_ptr< weld::Entry > m_xContent
std::unique_ptr< weld::ComboBox > m_xType
OUString getContent() const
RedactionTargetType getType() const
SfxAddTargetDialog(weld::Window *pWindow, const OUString &rName)
std::unique_ptr< weld::ComboBox > m_xPredefContent
OUString getName() const
bool isCaseSensitive() const
std::unique_ptr< weld::Entry > m_xName
std::unique_ptr< weld::CheckButton > m_xWholeWords
std::unique_ptr< sfx2::FileDialogHelper > m_pFileDlg
void addTarget(std::unique_ptr< RedactionTarget > pTarget)
Carry out proper addition both to the targets box, and to the tabletargets vector.
std::vector< std::pair< std::unique_ptr< RedactionTarget >, OUString > > m_aTableTargets
void clearTargets()
Clear all targets both visually and from the targets vector.
std::unique_ptr< weld::Button > m_xEditBtn
std::unique_ptr< weld::Button > m_xSaveBtn
virtual ~SfxAutoRedactDialog() override
bool hasTargets() const
Check if the dialog has any valid redaction targets.
std::unique_ptr< weld::Button > m_xDeleteBtn
SfxAutoRedactDialog(weld::Window *pParent)
void StartFileDialog(StartFileDialogType nType, const OUString &rTitle)
bool getTargets(std::vector< std::pair< RedactionTarget, OUString > > &r_aTargets)
Copies targets vector Does a shallow copy.
std::unique_ptr< weld::Button > m_xAddBtn
std::unique_ptr< weld::Button > m_xLoadBtn
css::uno::Any GetUserItem(const OUString &sName) const
void SetUserItem(const OUString &sName, const css::uno::Any &aValue)
bool Exists() const
void connect_row_activated(const Link< weld::TreeView &, bool > &rLink)
std::unique_ptr< weld::TreeView > m_xControl
int GetRowByTargetName(std::u16string_view sName)
OUString GetNameProposal() const
void setRowData(int nRowIndex, const RedactionTarget *pTarget)
void InsertTarget(RedactionTarget *pTarget)
RedactionTarget * GetTargetByName(std::u16string_view sName)
TargetsTable(std::unique_ptr< weld::TreeView > xControl)
virtual short run()
void set_title(const OUString &rTitle)
virtual Dialog * getDialog() override
std::shared_ptr< weld::Dialog > m_xDialog
int nCount
float u
#define ERRCODE_NONE
constexpr OUStringLiteral FILEDIALOG_FILTER_ALL
DocumentType eType
OUString sName
const char * name
sal_Int32 nIndex
#define SAL_WARN(area, stream)
rtl::OUString getTypeName(rtl::OUString const &rEnvDcp)
int i
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
OUString toId(const void *pValue)
QPRO_FUNC_TYPE nType
OUString SfxResId(TranslateId aId)
Definition: sfxresid.cxx:22
Keeps information for a single redaction target.
RedactionTargetType sType
RET_OK
RET_CANCEL
Reference< XControl > m_xControl