ofz#44991 keep paragraph's that failed to load until import is complete
[LibreOffice.git] / sfx2 / source / view / classificationcontroller.cxx
blob9493a77ff314c21de889faa59934afbc54be8d44
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <cppuhelper/implbase.hxx>
11 #include <svtools/toolboxcontroller.hxx>
12 #include <com/sun/star/lang/XServiceInfo.hpp>
13 #include <com/sun/star/document/XDocumentProperties.hpp>
15 #include <com/sun/star/uno/XComponentContext.hpp>
16 #include <com/sun/star/frame/XFrame.hpp>
18 #include <toolkit/helper/vclunohelper.hxx>
19 #include <vcl/InterimItemWindow.hxx>
20 #include <sfx2/classificationhelper.hxx>
21 #include <sfx2/objsh.hxx>
22 #include <sfx2/strings.hrc>
23 #include <sfx2/sfxresid.hxx>
24 #include <vcl/event.hxx>
25 #include <vcl/toolbox.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/vclptr.hxx>
28 #include <vcl/weld.hxx>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <comphelper/propertysequence.hxx>
32 #include <comphelper/dispatchcommand.hxx>
33 #include <comphelper/configurationlistener.hxx>
35 using namespace com::sun::star;
37 namespace sfx2
40 namespace {
42 class ClassificationCategoriesController;
46 using ClassificationPropertyListenerBase = comphelper::ConfigurationListenerProperty<OUString>;
48 namespace {
50 /// Listens to configuration changes, so no restart is needed after setting the classification path.
51 class ClassificationPropertyListener : public ClassificationPropertyListenerBase
53 ClassificationCategoriesController& m_rController;
55 public:
56 ClassificationPropertyListener(const rtl::Reference<comphelper::ConfigurationListener>& xListener, ClassificationCategoriesController& rController);
57 void setProperty(const uno::Any& rProperty) override;
62 using ClassificationCategoriesControllerBase = cppu::ImplInheritanceHelper<svt::ToolboxController, lang::XServiceInfo>;
64 namespace {
66 class ClassificationControl;
68 /// Controller for .uno:ClassificationApply.
69 class ClassificationCategoriesController : public ClassificationCategoriesControllerBase
71 VclPtr<ClassificationControl> m_pClassification;
72 rtl::Reference<comphelper::ConfigurationListener> m_xListener;
73 ClassificationPropertyListener m_aPropertyListener;
75 DECL_LINK(SelectHdl, weld::ComboBox&, void);
77 public:
78 explicit ClassificationCategoriesController(const uno::Reference<uno::XComponentContext>& rContext);
80 // XServiceInfo
81 OUString SAL_CALL getImplementationName() override;
82 sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override;
83 uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
85 // XComponent
86 void SAL_CALL dispose() override;
88 // XToolbarController
89 uno::Reference<awt::XWindow> SAL_CALL createItemWindow(const uno::Reference<awt::XWindow>& rParent) override;
91 // XStatusListener
92 void SAL_CALL statusChanged(const frame::FeatureStateEvent& rEvent) override;
94 void removeEntries();
97 /// Classification control is the parent of all widgets that belongs to ClassificationCategoriesController.
98 class SAL_WARN_UNUSED ClassificationControl final : public InterimItemWindow
100 std::unique_ptr<weld::Label> m_xLabel;
101 std::unique_ptr<weld::ComboBox> m_xCategory;
103 DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
105 void SetOptimalSize();
106 void DataChanged(const DataChangedEvent& rEvent) override;
108 public:
109 explicit ClassificationControl(vcl::Window* pParent);
110 ~ClassificationControl() override;
111 void dispose() override;
112 weld::ComboBox& getCategory()
114 return *m_xCategory;
116 void set_sensitive(bool bSensitive)
118 Enable(bSensitive);
119 m_xContainer->set_sensitive(bSensitive);
121 static sfx::ClassificationCreationOrigin getExistingClassificationOrigin();
122 void toggleInteractivityOnOrigin();
123 void setCategoryStateFromPolicy(const SfxClassificationHelper & rHelper);
126 OUString const & getCategoryType()
128 return SfxClassificationHelper::policyTypeToString(SfxClassificationHelper::getPolicyType());
131 } // end anonymous namespace
133 ClassificationPropertyListener::ClassificationPropertyListener(const rtl::Reference<comphelper::ConfigurationListener>& xListener, ClassificationCategoriesController& rController)
134 : ClassificationPropertyListenerBase(xListener, "WritePath")
135 , m_rController(rController)
139 void ClassificationPropertyListener::setProperty(const uno::Any& /*rProperty*/)
141 // So that its gets re-filled with entries from the new policy.
142 m_rController.removeEntries();
145 ClassificationCategoriesController::ClassificationCategoriesController(const uno::Reference<uno::XComponentContext>& rContext)
146 : ClassificationCategoriesControllerBase(rContext, uno::Reference<frame::XFrame>(), OUString(".uno:ClassificationApply"))
147 , m_pClassification(nullptr)
148 , m_xListener(new comphelper::ConfigurationListener("/org.openoffice.Office.Paths/Paths/Classification"))
149 , m_aPropertyListener(m_xListener, *this)
154 OUString ClassificationCategoriesController::getImplementationName()
156 return "com.sun.star.comp.sfx2.ClassificationCategoriesController";
159 sal_Bool ClassificationCategoriesController::supportsService(const OUString& rServiceName)
161 return cppu::supportsService(this, rServiceName);
164 uno::Sequence<OUString> ClassificationCategoriesController::getSupportedServiceNames()
166 return { "com.sun.star.frame.ToolbarController" };
169 void ClassificationCategoriesController::dispose()
171 SolarMutexGuard aSolarMutexGuard;
173 svt::ToolboxController::dispose();
174 m_pClassification.disposeAndClear();
175 m_aPropertyListener.dispose();
176 m_xListener->dispose();
179 uno::Reference<awt::XWindow> ClassificationCategoriesController::createItemWindow(const uno::Reference<awt::XWindow>& rParent)
181 VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(rParent);
182 auto pToolbar = dynamic_cast<ToolBox*>(pParent.get());
183 if (pToolbar)
185 m_pClassification = VclPtr<ClassificationControl>::Create(pToolbar);
186 m_pClassification->getCategory().connect_changed(LINK(this, ClassificationCategoriesController, SelectHdl));
187 m_pClassification->Show();
190 return VCLUnoHelper::GetInterface(m_pClassification);
193 IMPL_LINK(ClassificationCategoriesController, SelectHdl, weld::ComboBox&, rCategory, void)
195 m_pClassification->toggleInteractivityOnOrigin();
197 if (ClassificationControl::getExistingClassificationOrigin() == sfx::ClassificationCreationOrigin::MANUAL)
199 SfxObjectShell* pObjectShell = SfxObjectShell::Current();
200 if (!pObjectShell)
201 return;
202 SfxClassificationHelper aHelper(pObjectShell->getDocProperties());
203 m_pClassification->setCategoryStateFromPolicy(aHelper);
205 else
207 OUString aEntry = rCategory.get_active_text();
209 const OUString& aType = getCategoryType();
210 uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence({
211 {"Name", uno::makeAny(aEntry)},
212 {"Type", uno::makeAny(aType)},
213 }));
214 comphelper::dispatchCommand(".uno:ClassificationApply", aPropertyValues);
218 void ClassificationCategoriesController::statusChanged(const frame::FeatureStateEvent& /*rEvent*/)
220 if (!m_pClassification)
221 return;
223 SfxObjectShell* pObjectShell = SfxObjectShell::Current();
224 if (!pObjectShell)
225 return;
227 SfxClassificationHelper aHelper(pObjectShell->getDocProperties());
229 //toggle if the pop-up is enabled/disabled
230 m_pClassification->toggleInteractivityOnOrigin();
232 // check if classification was set via the advanced dialog
233 if (ClassificationControl::getExistingClassificationOrigin() != sfx::ClassificationCreationOrigin::MANUAL)
235 weld::ComboBox& rCategories = m_pClassification->getCategory();
236 if (rCategories.get_count() == 0)
238 std::vector<OUString> aNames = aHelper.GetBACNames();
239 for (const OUString& rName : aNames)
240 rCategories.append_text(rName);
244 // Restore state based on the doc. model.
245 m_pClassification->setCategoryStateFromPolicy(aHelper);
249 void ClassificationCategoriesController::removeEntries()
251 m_pClassification->getCategory().clear();
254 ClassificationControl::ClassificationControl(vcl::Window* pParent)
255 : InterimItemWindow(pParent, "sfx/ui/classificationbox.ui", "ClassificationBox")
256 , m_xLabel(m_xBuilder->weld_label("label"))
257 , m_xCategory(m_xBuilder->weld_combo_box("combobox"))
259 InitControlBase(m_xCategory.get());
261 m_xCategory->connect_key_press(LINK(this, ClassificationControl, KeyInputHdl));
263 // WB_NOLABEL means here that the control won't be replaced with a label
264 // when it wouldn't fit the available space.
265 SetStyle(GetStyle() | WB_DIALOGCONTROL | WB_NOLABEL);
267 OUString aText;
268 switch (SfxClassificationHelper::getPolicyType())
270 case SfxClassificationPolicyType::IntellectualProperty:
271 aText = SfxResId(STR_CLASSIFIED_INTELLECTUAL_PROPERTY);
272 break;
273 case SfxClassificationPolicyType::NationalSecurity:
274 aText = SfxResId(STR_CLASSIFIED_NATIONAL_SECURITY);
275 break;
276 case SfxClassificationPolicyType::ExportControl:
277 aText = SfxResId(STR_CLASSIFIED_EXPORT_CONTROL);
278 break;
281 m_xLabel->set_label(aText);
283 // Same as SvxColorDockingWindow.
284 const Size aLogicalAttrSize(150, 0);
285 Size aSize(LogicToPixel(aLogicalAttrSize, MapMode(MapUnit::MapAppFont)));
286 m_xCategory->set_size_request(aSize.Width() - m_xLabel->get_preferred_size().Width(), -1);
288 SetOptimalSize();
291 IMPL_LINK(ClassificationControl, KeyInputHdl, const KeyEvent&, rKEvt, bool)
293 return ChildKeyInput(rKEvt);
296 ClassificationControl::~ClassificationControl()
298 disposeOnce();
301 void ClassificationControl::dispose()
303 m_xLabel.reset();
304 m_xCategory.reset();
305 InterimItemWindow::dispose();
308 void ClassificationControl::SetOptimalSize()
310 SetSizePixel(get_preferred_size());
313 void ClassificationControl::DataChanged(const DataChangedEvent& rEvent)
315 if ((rEvent.GetType() == DataChangedEventType::SETTINGS) && (rEvent.GetFlags() & AllSettingsFlags::STYLE))
316 SetOptimalSize();
318 toggleInteractivityOnOrigin();
320 InterimItemWindow::DataChanged(rEvent);
323 sfx::ClassificationCreationOrigin ClassificationControl::getExistingClassificationOrigin()
325 SfxObjectShell* pObjectShell = SfxObjectShell::Current();
326 if (!pObjectShell)
327 return sfx::ClassificationCreationOrigin::NONE;
329 uno::Reference<document::XDocumentProperties> xDocumentProperties = pObjectShell->getDocProperties();
330 uno::Reference<beans::XPropertyContainer> xPropertyContainer = xDocumentProperties->getUserDefinedProperties();
332 sfx::ClassificationKeyCreator aKeyCreator(SfxClassificationHelper::getPolicyType());
333 return sfx::getCreationOriginProperty(xPropertyContainer, aKeyCreator);
336 void ClassificationControl::toggleInteractivityOnOrigin()
338 if (getExistingClassificationOrigin() == sfx::ClassificationCreationOrigin::MANUAL)
340 set_sensitive(false);
342 else
344 set_sensitive(true);
348 void ClassificationControl::setCategoryStateFromPolicy(const SfxClassificationHelper & rHelper)
350 const OUString& rCategoryName = rHelper.GetBACName(SfxClassificationHelper::getPolicyType());
351 if (!rCategoryName.isEmpty())
353 getCategory().set_active_text(rCategoryName);
357 } // namespace sfx2
359 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* com_sun_star_sfx2_ClassificationCategoriesController_get_implementation(uno::XComponentContext* pContext, const uno::Sequence<uno::Any>&)
361 return cppu::acquire(new sfx2::ClassificationCategoriesController(pContext));
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */