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 <core_resource.hxx>
21 #include <FieldDescControl.hxx>
22 #include <FieldControls.hxx>
23 #include <comphelper/diagnose_ex.hxx>
24 #include <TableDesignHelpBar.hxx>
25 #include <vcl/svapp.hxx>
26 #include <FieldDescriptions.hxx>
27 #include <svl/numuno.hxx>
28 #include <vcl/transfer.hxx>
29 #include <com/sun/star/sdbc/ColumnValue.hpp>
30 #include <com/sun/star/util/NumberFormat.hpp>
31 #include <com/sun/star/util/XNumberFormatPreviewer.hpp>
32 #include <com/sun/star/util/XNumberFormatTypes.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <QEnumTypes.hxx>
35 #include <helpids.h>
36 #include <connectivity/dbtools.hxx>
37 #include <connectivity/dbconversion.hxx>
38 #include <comphelper/numbers.hxx>
39 #include <comphelper/types.hxx>
40 #include <UITools.hxx>
41 #include <strings.hrc>
42 #include <osl/diagnose.h>
43 
44 using namespace dbaui;
45 using namespace dbtools;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::beans;
48 using namespace ::com::sun::star::lang;
49 using namespace ::com::sun::star::sdbc;
50 using namespace ::com::sun::star::util;
51 
52 namespace
53 {
lcl_HideAndDeleteControl(short & _nPos,std::unique_ptr<T1> & _pControl,std::unique_ptr<T2> & _pControlText)54     template< typename T1, typename T2> void lcl_HideAndDeleteControl(short& _nPos,std::unique_ptr<T1>& _pControl, std::unique_ptr<T2>& _pControlText)
55     {
56         if ( _pControl )
57         {
58             --_nPos;
59             _pControl->hide();
60             _pControlText->hide();
61             _pControl.reset();
62             _pControlText.reset();
63         }
64     }
65 }
66 
OFieldDescControl(weld::Container * pPage,OTableDesignHelpBar * pHelpBar)67 OFieldDescControl::OFieldDescControl(weld::Container* pPage, OTableDesignHelpBar* pHelpBar)
68     : m_xBuilder(Application::CreateBuilder(pPage, u"dbaccess/ui/fielddescpage.ui"_ustr))
69     , m_xContainer(m_xBuilder->weld_container(u"FieldDescPage"_ustr))
70     , m_pHelp( pHelpBar )
71     , m_pLastFocusWindow(nullptr)
72     , m_pActFocusWindow(nullptr)
73     , m_nPos(-1)
74     , aYes(DBA_RES(STR_VALUE_YES))
75     , aNo(DBA_RES(STR_VALUE_NO))
76     , m_nEditWidth(50)
77     , pActFieldDescr(nullptr)
78 {
79     if (m_pHelp)
80         m_pHelp->connect_focus_out(LINK(this, OFieldDescControl, HelpFocusOut));
81 }
82 
~OFieldDescControl()83 OFieldDescControl::~OFieldDescControl()
84 {
85     dispose();
86 }
87 
dispose()88 void OFieldDescControl::dispose()
89 {
90     // Destroy children
91     DeactivateAggregate( tpDefault );
92     DeactivateAggregate( tpRequired );
93     DeactivateAggregate( tpTextLen );
94     DeactivateAggregate( tpNumType );
95     DeactivateAggregate( tpScale );
96     DeactivateAggregate( tpLength );
97     DeactivateAggregate( tpFormat );
98     DeactivateAggregate( tpAutoIncrement );
99     DeactivateAggregate( tpBoolDefault );
100     DeactivateAggregate( tpColumnName );
101     DeactivateAggregate( tpType );
102     DeactivateAggregate( tpAutoIncrementValue );
103     m_pHelp = nullptr;
104     m_pLastFocusWindow = nullptr;
105     m_pActFocusWindow = nullptr;
106     m_xDefaultText.reset();
107     m_xRequiredText.reset();
108     m_xAutoIncrementText.reset();
109     m_xTextLenText.reset();
110     m_xNumTypeText.reset();
111     m_xLengthText.reset();
112     m_xScaleText.reset();
113     m_xFormatText.reset();
114     m_xBoolDefaultText.reset();
115     m_xColumnNameText.reset();
116     m_xTypeText.reset();
117     m_xAutoIncrementValueText.reset();
118     m_xRequired.reset();
119     m_xNumType.reset();
120     m_xAutoIncrement.reset();
121     m_xDefault.reset();
122     m_xTextLen.reset();
123     m_xLength.reset();
124     m_xScale.reset();
125     m_xFormatSample.reset();
126     m_xBoolDefault.reset();
127     m_xColumnName.reset();
128     m_xType.reset();
129     m_xAutoIncrementValue.reset();
130     m_xFormat.reset();
131     m_xContainer.reset();
132     m_xBuilder.reset();
133 }
134 
BoolStringPersistent(std::u16string_view rUIString) const135 OUString OFieldDescControl::BoolStringPersistent(std::u16string_view rUIString) const
136 {
137     if (rUIString == aNo)
138         return OUString('0');
139     if (rUIString == aYes)
140         return OUString('1');
141     return OUString();
142 }
143 
BoolStringUI(const OUString & rPersistentString) const144 OUString OFieldDescControl::BoolStringUI(const OUString& rPersistentString) const
145 {
146     // Older versions may store a language dependent string as a default
147     if (rPersistentString == aYes || rPersistentString == aNo)
148         return rPersistentString;
149 
150     if (rPersistentString == "0")
151         return aNo;
152     if (rPersistentString == "1")
153         return aYes;
154 
155     return DBA_RES(STR_VALUE_NONE);
156 }
157 
Init()158 void OFieldDescControl::Init()
159 {
160     Reference< css::util::XNumberFormatter > xFormatter = GetFormatter();
161     ::dbaui::setEvalDateFormatForFormatter(xFormatter);
162 }
163 
SetReadOnly(bool bReadOnly)164 void OFieldDescControl::SetReadOnly( bool bReadOnly )
165 {
166     // Enable/disable Controls
167     struct final
168     {
169         OWidgetBase * aggregate;
170         weld::Widget * text;
171     } const aggregates[] = {
172         {m_xRequired.get(), m_xRequiredText.get()}
173         , {m_xNumType.get(), m_xNumTypeText.get()}
174         , {m_xAutoIncrement.get(), m_xAutoIncrementText.get()}
175         , {m_xDefault.get(), m_xDefaultText.get()}
176         , {m_xTextLen.get(), m_xTextLenText.get()}
177         , {m_xLength.get(), m_xLengthText.get()}
178         , {m_xScale.get(), m_xScaleText.get()}
179         , {m_xColumnName.get(), m_xColumnNameText.get()}
180         , {m_xType.get(), m_xTypeText.get()}
181         , {m_xAutoIncrementValue.get(), m_xAutoIncrementValueText.get()}};
182 
183     for (auto const & aggregate: aggregates)
184     {
185         if (aggregate.text)
186             aggregate.text->set_sensitive(!bReadOnly);
187         if (aggregate.aggregate)
188             aggregate.aggregate->set_sensitive(!bReadOnly);
189     }
190 
191     if (m_xFormat)
192     {
193         assert(m_xFormatText);
194         m_xFormat->set_sensitive(!bReadOnly);
195         m_xFormatText->set_sensitive(!bReadOnly);
196     }
197 }
198 
SetControlText(sal_uInt16 nControlId,const OUString & rText)199 void OFieldDescControl::SetControlText( sal_uInt16 nControlId, const OUString& rText )
200 {
201     // Set the Controls' texts
202     switch( nControlId )
203     {
204         case FIELD_PROPERTY_BOOL_DEFAULT:
205             if (m_xBoolDefault)
206             {
207                 OUString sOld = m_xBoolDefault->get_active_text();
208                 m_xBoolDefault->set_active_text(rText);
209                 if (sOld != rText)
210                     ChangeHdl(m_xBoolDefault->GetComboBox());
211             }
212             break;
213         case FIELD_PROPERTY_DEFAULT:
214             if (m_xDefault)
215             {
216                 m_xDefault->set_text(rText);
217                 UpdateFormatSample(pActFieldDescr);
218             }
219             break;
220 
221         case FIELD_PROPERTY_REQUIRED:
222             if (m_xRequired)
223                 m_xRequired->set_active_text(rText);
224             break;
225 
226         case FIELD_PROPERTY_TEXTLEN:
227             if (m_xTextLen)
228                 m_xTextLen->set_text(rText);
229             break;
230 
231         case FIELD_PROPERTY_NUMTYPE:
232             if (m_xNumType)
233                 m_xNumType->set_active_text(rText);
234             break;
235 
236         case FIELD_PROPERTY_AUTOINC:
237             if (m_xAutoIncrement)
238             {
239                 OUString sOld = m_xAutoIncrement->get_active_text();
240                 m_xAutoIncrement->set_active_text(rText);
241                 if (sOld != rText)
242                     ChangeHdl(m_xAutoIncrement->GetComboBox());
243             }
244             break;
245 
246         case FIELD_PROPERTY_LENGTH:
247             if (m_xLength)
248                 m_xLength->set_text(rText);
249             break;
250 
251         case FIELD_PROPERTY_SCALE:
252             if (m_xScale)
253                 m_xScale->set_text(rText);
254             break;
255 
256         case FIELD_PROPERTY_FORMAT:
257             if (pActFieldDescr)
258                 UpdateFormatSample(pActFieldDescr);
259             break;
260         case FIELD_PROPERTY_COLUMNNAME:
261             if (m_xColumnName)
262                 m_xColumnName->set_text(rText);
263             break;
264         case FIELD_PROPERTY_TYPE:
265             if (m_xType)
266                 m_xType->set_active_text(rText);
267             break;
268         case FIELD_PROPERTY_AUTOINCREMENT:
269             if (m_xAutoIncrementValue)
270                 m_xAutoIncrementValue->set_text(rText);
271             break;
272     }
273 }
274 
IMPL_LINK_NOARG(OFieldDescControl,FormatClickHdl,weld::Button &,void)275 IMPL_LINK_NOARG(OFieldDescControl, FormatClickHdl, weld::Button&, void)
276 {
277     // Create temporary Column, which is used for data exchange with Dialog
278     if( !pActFieldDescr )
279         return;
280 
281     sal_Int32 nOldFormatKey(pActFieldDescr->GetFormatKey());
282     SvxCellHorJustify rOldJustify = pActFieldDescr->GetHorJustify();
283     Reference< XNumberFormatsSupplier >  xSupplier = GetFormatter()->getNumberFormatsSupplier();
284     SvNumberFormatsSupplierObj* pSupplierImpl = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>( xSupplier );
285     if (!pSupplierImpl)
286         return;
287 
288     SvNumberFormatter* pFormatter = pSupplierImpl->GetNumberFormatter();
289     if(!::dbaui::callColumnFormatDialog(m_xContainer.get(),pFormatter,pActFieldDescr->GetType(),nOldFormatKey,rOldJustify,true))
290         return;
291 
292     bool bModified = false;
293     if(nOldFormatKey != pActFieldDescr->GetFormatKey())
294     {
295         pActFieldDescr->SetFormatKey( nOldFormatKey );
296         bModified = true;
297     }
298     if(rOldJustify != pActFieldDescr->GetHorJustify())
299     {
300         pActFieldDescr->SetHorJustify( rOldJustify );
301         bModified = true;
302     }
303 
304     if(bModified)
305     {
306         SetModified(true);
307         UpdateFormatSample(pActFieldDescr);
308     }
309 }
310 
SetModified(bool)311 void OFieldDescControl::SetModified(bool /*bModified*/)
312 {
313 }
314 
IMPL_LINK(OFieldDescControl,ChangeHdl,weld::ComboBox &,rListBox,void)315 IMPL_LINK(OFieldDescControl, ChangeHdl, weld::ComboBox&, rListBox, void)
316 {
317     if (!pActFieldDescr)
318         return;
319 
320     if (rListBox.get_value_changed_from_saved())
321         SetModified(true);
322 
323     // Special treatment for Bool fields
324     if (m_xRequired && &rListBox == m_xRequired->GetWidget() && m_xBoolDefault)
325     {
326         // If m_xRequired = sal_True then the sal_Bool field must NOT contain <<none>>
327         OUString sDef = BoolStringUI(::comphelper::getString(pActFieldDescr->GetControlDefault()));
328 
329         if (m_xRequired->get_active() == 0) // Yes
330         {
331             m_xBoolDefault->remove_text(DBA_RES(STR_VALUE_NONE));
332             if (sDef != aYes && sDef != aNo)
333                 m_xBoolDefault->set_active(1);  // No as a default
334             else
335                 m_xBoolDefault->set_active_text(sDef);
336         }
337         else if (m_xBoolDefault->get_count() < 3)
338         {
339             m_xBoolDefault->append_text(DBA_RES(STR_VALUE_NONE));
340             m_xBoolDefault->set_active_text(sDef);
341         }
342     }
343 
344     // A special treatment only for AutoIncrement
345     if (m_xAutoIncrement && &rListBox == m_xAutoIncrement->GetWidget())
346     {
347         if (rListBox.get_active() == 1)
348         { // no
349             DeactivateAggregate( tpAutoIncrementValue );
350             if(pActFieldDescr->IsPrimaryKey())
351                 DeactivateAggregate( tpRequired );
352             else if( pActFieldDescr->getTypeInfo()->bNullable )
353             {
354                 ActivateAggregate( tpRequired );
355                 if (m_xRequired)
356                 {
357                     if( pActFieldDescr->IsNullable() )
358                         m_xRequired->set_active(1); // no
359                     else
360                         m_xRequired->set_active(0); // yes
361                 }
362             }
363             ActivateAggregate( tpDefault );
364         }
365         else
366         {
367             DeactivateAggregate( tpRequired );
368             DeactivateAggregate( tpDefault );
369             ActivateAggregate( tpAutoIncrementValue );
370         }
371     }
372 
373     if (m_xType && &rListBox == m_xType->GetWidget())
374     {
375         TOTypeInfoSP pTypeInfo = getTypeInfo(m_xType->get_active());
376         pActFieldDescr->FillFromTypeInfo(pTypeInfo,true,false); // SetType(pTypeInfo);
377 
378         DisplayData(pActFieldDescr);
379         CellModified(-1, m_xType->GetPos());
380     }
381 }
382 
ActivateAggregate(EControlType eType)383 void OFieldDescControl::ActivateAggregate( EControlType eType )
384 {
385     // Create Controls
386     switch( eType )
387     {
388     case tpDefault:
389         if (m_xDefault)
390             return;
391         m_nPos++;
392         m_xDefaultText = m_xBuilder->weld_label(u"DefaultValueText"_ustr);
393         m_xDefaultText->show();
394         m_xDefault = std::make_unique<OPropEditCtrl>(
395                 m_xBuilder->weld_entry(u"DefaultValue"_ustr), STR_HELP_DEFAULT_VALUE, FIELD_PROPERTY_DEFAULT);
396         InitializeControl(m_xDefault->GetWidget(),HID_TAB_ENT_DEFAULT);
397         m_xDefault->show();
398         break;
399     case tpAutoIncrementValue:
400         if (m_xAutoIncrementValue || !isAutoIncrementValueEnabled())
401             return;
402         m_nPos++;
403         m_xAutoIncrementValueText = m_xBuilder->weld_label(u"AutoIncrementValueText"_ustr);
404         m_xAutoIncrementValueText->show();
405         m_xAutoIncrementValue = std::make_unique<OPropEditCtrl>(
406                 m_xBuilder->weld_spin_button(u"AutoIncrementValue"_ustr), STR_HELP_AUTOINCREMENT_VALUE,
407                 FIELD_PROPERTY_AUTOINCREMENT);
408         m_xAutoIncrementValue->set_text( getAutoIncrementValue() );
409         InitializeControl(m_xAutoIncrementValue->GetWidget(),HID_TAB_AUTOINCREMENTVALUE);
410         m_xAutoIncrementValue->show();
411         break;
412 
413     case tpRequired:
414     {
415         if (m_xRequired)
416             return;
417         Reference< XDatabaseMetaData> xMetaData = getMetaData();
418 
419         if(xMetaData.is() && xMetaData->supportsNonNullableColumns())
420         {
421             m_nPos++;
422             m_xRequiredText = m_xBuilder->weld_label(u"RequiredText"_ustr);
423             m_xRequiredText->show();
424             m_xRequired = std::make_unique<OPropListBoxCtrl>(
425                     m_xBuilder->weld_combo_box(u"Required"_ustr), STR_HELP_AUTOINCREMENT_VALUE,
426                     FIELD_PROPERTY_AUTOINCREMENT);
427             m_xRequired->append_text(aYes);
428             m_xRequired->append_text(aNo);
429             m_xRequired->set_active(1);
430 
431             InitializeControl(m_xRequired.get(),HID_TAB_ENT_REQUIRED, true);
432             m_xRequired->show();
433         }
434     }
435     break;
436     case tpAutoIncrement:
437     {
438         if (m_xAutoIncrement)
439             return;
440         m_nPos++;
441         m_xAutoIncrementText = m_xBuilder->weld_label(u"AutoIncrementText"_ustr);
442         m_xAutoIncrementText->show();
443         m_xAutoIncrement = std::make_unique<OPropListBoxCtrl>(
444                 m_xBuilder->weld_combo_box(u"AutoIncrement"_ustr), STR_HELP_AUTOINCREMENT,
445                 FIELD_PROPERTY_AUTOINC);
446         m_xAutoIncrement->append_text(aYes);
447         m_xAutoIncrement->append_text(aNo);
448         m_xAutoIncrement->set_active(0);
449         InitializeControl(m_xAutoIncrement.get(),HID_TAB_ENT_AUTOINCREMENT, true);
450         m_xAutoIncrement->show();
451     }
452     break;
453     case tpTextLen:
454         if (m_xTextLen)
455             return;
456         m_nPos++;
457         m_xTextLenText = m_xBuilder->weld_label(u"TextLengthText"_ustr);
458         m_xTextLenText->show();
459         m_xTextLen = CreateNumericControl(u"TextLength"_ustr, STR_HELP_TEXT_LENGTH, FIELD_PROPERTY_TEXTLEN,HID_TAB_ENT_TEXT_LEN);
460         break;
461 
462     case tpType:
463         if (m_xType)
464             return;
465         m_nPos++;
466         m_xTypeText = m_xBuilder->weld_label(u"TypeText"_ustr);
467         m_xTypeText->show();
468         m_xType = std::make_unique<OPropListBoxCtrl>(
469                 m_xBuilder->weld_combo_box(u"Type"_ustr), STR_HELP_AUTOINCREMENT, FIELD_PROPERTY_TYPE);
470         {
471             const OTypeInfoMap* pTypeInfo = getTypeInfo();
472             for (auto const& elem : *pTypeInfo)
473                 m_xType->append_text(elem.second->aUIName);
474         }
475         m_xType->set_active(0);
476         InitializeControl(m_xType.get(),HID_TAB_ENT_TYPE, true);
477         m_xType->show();
478         break;
479     case tpColumnName:
480         if (m_xColumnName)
481             return;
482         m_nPos++;
483         {
484             sal_Int32 nMax(0);
485             OUString aTmpString;
486             try
487             {
488                 Reference< XDatabaseMetaData> xMetaData = getMetaData();
489                 if ( xMetaData.is() )
490                 {
491                     nMax =  xMetaData->getMaxColumnNameLength();
492                     aTmpString = xMetaData->getExtraNameCharacters();
493                 }
494             }
495             catch (const Exception&)
496             {
497                 DBG_UNHANDLED_EXCEPTION("dbaccess");
498             }
499             m_xColumnNameText = m_xBuilder->weld_label(u"ColumnNameText"_ustr);
500             m_xColumnNameText->show();
501             m_xColumnName = std::make_unique<OPropColumnEditCtrl>(
502                     m_xBuilder->weld_entry(u"ColumnName"_ustr), aTmpString,
503                     STR_HELP_DEFAULT_VALUE, FIELD_PROPERTY_COLUMNNAME);
504             m_xColumnName->set_max_length(nMax);
505             m_xColumnName->setCheck( isSQL92CheckEnabled(getConnection()) );
506         }
507 
508         InitializeControl(m_xColumnName->GetWidget(),HID_TAB_ENT_COLUMNNAME);
509         m_xColumnName->show();
510         break;
511     case tpNumType:
512         if (m_xNumType)
513             return;
514         m_nPos++;
515         m_xNumTypeText = m_xBuilder->weld_label(u"NumTypeText"_ustr);
516         m_xNumTypeText->show();
517         m_xNumType = std::make_unique<OPropListBoxCtrl>(
518                 m_xBuilder->weld_combo_box(u"NumType"_ustr), STR_HELP_NUMERIC_TYPE, FIELD_PROPERTY_NUMTYPE);
519         m_xNumType->append_text(u"Byte"_ustr);
520         m_xNumType->append_text(u"SmallInt"_ustr);
521         m_xNumType->append_text(u"Integer"_ustr);
522         m_xNumType->append_text(u"Single"_ustr);
523         m_xNumType->append_text(u"Double"_ustr);
524         m_xNumType->set_active(2);
525         InitializeControl(m_xNumType.get(),HID_TAB_ENT_NUMTYP, true);
526         m_xNumType->show();
527         break;
528 
529     case tpLength:
530         if (m_xLength)
531             return;
532         m_nPos++;
533         m_xLengthText = m_xBuilder->weld_label(u"LengthText"_ustr);
534         m_xLengthText->show();
535         m_xLength = CreateNumericControl(u"Length"_ustr, STR_HELP_LENGTH, FIELD_PROPERTY_LENGTH,HID_TAB_ENT_LEN);
536         break;
537 
538     case tpScale:
539         if (m_xScale)
540             return;
541         m_nPos++;
542         m_xScaleText = m_xBuilder->weld_label(u"ScaleText"_ustr);
543         m_xScaleText->show();
544         m_xScale = CreateNumericControl(u"Scale"_ustr, STR_HELP_SCALE, FIELD_PROPERTY_SCALE,HID_TAB_ENT_SCALE);
545         break;
546 
547     case tpFormat:
548         if (!m_xFormat)
549         {
550             m_nPos++;
551             m_xFormatText = m_xBuilder->weld_label(u"FormatTextText"_ustr);
552             m_xFormatText->show();
553 
554             m_xFormatSample = std::make_unique<OPropEditCtrl>(
555                     m_xBuilder->weld_entry(u"FormatText"_ustr), STR_HELP_FORMAT_CODE, -1);
556             m_xFormatSample->set_editable(false);
557             m_xFormatSample->set_sensitive(false);
558             InitializeControl(m_xFormatSample->GetWidget(),HID_TAB_ENT_FORMAT_SAMPLE);
559             m_xFormatSample->show();
560 
561             m_xFormat = m_xBuilder->weld_button(u"FormatButton"_ustr);
562             m_xFormat->connect_clicked( LINK( this, OFieldDescControl, FormatClickHdl ) );
563             InitializeControl(m_xFormat.get(),HID_TAB_ENT_FORMAT);
564             m_xFormat->show();
565         }
566 
567         UpdateFormatSample(pActFieldDescr);
568         break;
569     case tpBoolDefault:
570         if (m_xBoolDefault)
571             return;
572 
573         m_nPos++;
574         m_xBoolDefaultText = m_xBuilder->weld_label(u"BoolDefaultText"_ustr);
575         m_xBoolDefaultText->show();
576         m_xBoolDefault = std::make_unique<OPropListBoxCtrl>(
577                 m_xBuilder->weld_combo_box(u"BoolDefault"_ustr), STR_HELP_BOOL_DEFAULT,
578                 FIELD_PROPERTY_BOOL_DEFAULT);
579         m_xBoolDefault->append_text(DBA_RES(STR_VALUE_NONE));
580         m_xBoolDefault->append_text(aYes);
581         m_xBoolDefault->append_text(aNo);
582         InitializeControl(m_xBoolDefault->GetWidget(),HID_TAB_ENT_BOOL_DEFAULT);
583         m_xBoolDefault->show();
584         break;
585     }
586 }
587 
InitializeControl(OPropListBoxCtrl * _pControl,const OUString & _sHelpId,bool _bAddChangeHandler)588 void OFieldDescControl::InitializeControl(OPropListBoxCtrl* _pControl,const OUString& _sHelpId,bool _bAddChangeHandler)
589 {
590     if ( _bAddChangeHandler )
591         _pControl->GetComboBox().connect_changed(LINK(this,OFieldDescControl,ChangeHdl));
592 
593     InitializeControl(_pControl->GetWidget(), _sHelpId);
594 }
595 
InitializeControl(weld::Widget * pControl,const OUString & _sHelpId)596 void OFieldDescControl::InitializeControl(weld::Widget* pControl,const OUString& _sHelpId)
597 {
598     pControl->set_help_id(_sHelpId);
599     pControl->connect_focus_in(LINK(this, OFieldDescControl, OnControlFocusGot));
600     pControl->connect_focus_out(LINK(this, OFieldDescControl, OnControlFocusLost));
601 
602     if (dynamic_cast<weld::Entry*>(pControl))
603     {
604         int nWidthRequest = Application::GetDefaultDevice()->LogicToPixel(Size(m_nEditWidth, 0), MapMode(MapUnit::MapAppFont)).Width();
605         pControl->set_size_request(nWidthRequest, -1);
606     }
607 }
608 
CreateNumericControl(const OUString & rId,TranslateId pHelpId,short _nProperty,const OUString & _sHelpId)609 std::unique_ptr<OPropNumericEditCtrl> OFieldDescControl::CreateNumericControl(const OUString& rId, TranslateId pHelpId, short _nProperty, const OUString& _sHelpId)
610 {
611     auto xControl = std::make_unique<OPropNumericEditCtrl>(
612             m_xBuilder->weld_spin_button(rId), pHelpId, _nProperty);
613     xControl->set_digits(0);
614     xControl->set_range(0, 0x7FFFFFFF);   // Should be changed outside, if needed
615     xControl->show();
616 
617     InitializeControl(xControl->GetWidget(),_sHelpId);
618 
619     return xControl;
620 }
621 
DeactivateAggregate(EControlType eType)622 void OFieldDescControl::DeactivateAggregate( EControlType eType )
623 {
624     m_pLastFocusWindow = nullptr;
625     // Destroy Controls
626     switch( eType )
627     {
628     case tpDefault:
629         lcl_HideAndDeleteControl(m_nPos,m_xDefault,m_xDefaultText);
630         break;
631 
632     case tpAutoIncrementValue:
633         lcl_HideAndDeleteControl(m_nPos,m_xAutoIncrementValue,m_xAutoIncrementValueText);
634         break;
635 
636     case tpColumnName:
637         lcl_HideAndDeleteControl(m_nPos,m_xColumnName,m_xColumnNameText);
638         break;
639 
640     case tpType:
641         lcl_HideAndDeleteControl(m_nPos,m_xType,m_xTypeText);
642         break;
643 
644     case tpAutoIncrement:
645         lcl_HideAndDeleteControl(m_nPos,m_xAutoIncrement,m_xAutoIncrementText);
646         break;
647 
648     case tpRequired:
649         lcl_HideAndDeleteControl(m_nPos,m_xRequired,m_xRequiredText);
650         break;
651 
652     case tpTextLen:
653         lcl_HideAndDeleteControl(m_nPos,m_xTextLen,m_xTextLenText);
654         break;
655 
656     case tpNumType:
657         lcl_HideAndDeleteControl(m_nPos,m_xNumType,m_xNumTypeText);
658         break;
659 
660     case tpLength:
661         lcl_HideAndDeleteControl(m_nPos,m_xLength,m_xLengthText);
662         break;
663 
664     case tpScale:
665         lcl_HideAndDeleteControl(m_nPos,m_xScale,m_xScaleText);
666         break;
667 
668     case tpFormat:
669         // TODO: we have to check if we have to increment m_nPos again
670         lcl_HideAndDeleteControl(m_nPos,m_xFormat,m_xFormatText);
671         if (m_xFormatSample)
672         {
673             m_xFormatSample->hide();
674             m_xFormatSample.reset();
675         }
676         break;
677     case tpBoolDefault:
678         lcl_HideAndDeleteControl(m_nPos,m_xBoolDefault,m_xBoolDefaultText);
679         break;
680     }
681 }
682 
DisplayData(OFieldDescription * pFieldDescr)683 void OFieldDescControl::DisplayData(OFieldDescription* pFieldDescr )
684 {
685     pActFieldDescr = pFieldDescr;
686     if(!pFieldDescr)
687     {
688         if (m_pHelp)
689             m_pHelp->SetHelpText( OUString() );
690         DeactivateAggregate( tpDefault );
691         DeactivateAggregate( tpRequired );
692         DeactivateAggregate( tpTextLen );
693         DeactivateAggregate( tpNumType );
694         DeactivateAggregate( tpScale );
695         DeactivateAggregate( tpLength );
696         DeactivateAggregate( tpFormat );
697         DeactivateAggregate( tpAutoIncrement );
698         DeactivateAggregate( tpBoolDefault );
699         DeactivateAggregate( tpColumnName );
700         DeactivateAggregate( tpType );
701         DeactivateAggregate( tpAutoIncrementValue );
702         m_pPreviousType = TOTypeInfoSP();
703         // Reset the saved focus' pointer
704         m_pLastFocusWindow = nullptr;
705         return;
706     }
707 
708     TOTypeInfoSP pFieldType(pFieldDescr->getTypeInfo());
709 
710     ActivateAggregate( tpColumnName );
711     ActivateAggregate( tpType );
712 
713     OSL_ENSURE(pFieldType,"We need a type information here!");
714     // If the type has changed, substitute Controls
715     if( m_pPreviousType != pFieldType )
716     {
717         // Reset the saved focus' pointer
718         m_pLastFocusWindow = nullptr;
719 
720         // Controls, which must NOT be displayed again
721         DeactivateAggregate( tpNumType );
722 
723         // determine which controls we should show and which not
724 
725         // 1. the required control
726         if ( pFieldType->bNullable )
727             ActivateAggregate( tpRequired );
728         else
729             DeactivateAggregate( tpRequired );
730 
731         // 2. the autoincrement
732         if ( pFieldType->bAutoIncrement )
733         {
734             DeactivateAggregate( tpRequired );
735             DeactivateAggregate( tpDefault );
736             ActivateAggregate( tpAutoIncrement );
737             ActivateAggregate( tpAutoIncrementValue );
738         }
739         else
740         {
741             DeactivateAggregate( tpAutoIncrement );
742             DeactivateAggregate( tpAutoIncrementValue );
743             if(pFieldType->bNullable)
744                 ActivateAggregate( tpRequired );
745             else
746                 DeactivateAggregate( tpRequired );
747             ActivateAggregate( tpDefault );
748         }
749         // 3. the scale and precision
750         if (pFieldType->nPrecision)
751         {
752             ActivateAggregate( tpLength );
753             m_xLength->set_max(std::max<sal_Int32>(pFieldType->nPrecision,pFieldDescr->GetPrecision()));
754             m_xLength->set_editable(!pFieldType->aCreateParams.isEmpty());
755         }
756         else
757             DeactivateAggregate( tpLength );
758 
759         if (pFieldType->nMaximumScale)
760         {
761             ActivateAggregate( tpScale );
762             m_xScale->set_range(pFieldType->nMinimumScale,
763                                 std::max<sal_Int32>(pFieldType->nMaximumScale,pFieldDescr->GetScale()));
764             m_xScale->set_editable(!pFieldType->aCreateParams.isEmpty() && pFieldType->aCreateParams != "PRECISION");
765         }
766         else
767             DeactivateAggregate( tpScale );
768 
769         // and now look for type specific things
770         switch( pFieldType->nType )
771         {
772             case DataType::CHAR:
773             case DataType::VARCHAR:
774             case DataType::LONGVARCHAR:
775                 DeactivateAggregate( tpLength );
776                 DeactivateAggregate( tpBoolDefault );
777 
778                 ActivateAggregate( tpDefault );
779                 ActivateAggregate( tpFormat );
780                 if (pFieldType->nPrecision)
781                 {
782                     ActivateAggregate( tpTextLen );
783                     m_xTextLen->set_max(std::max<sal_Int32>(pFieldType->nPrecision,pFieldDescr->GetPrecision()));
784                     m_xTextLen->set_editable(!pFieldType->aCreateParams.isEmpty());
785                 }
786                 else
787                     DeactivateAggregate( tpTextLen );
788                 break;
789             case DataType::DATE:
790             case DataType::TIME:
791             case DataType::TIMESTAMP:
792             case DataType::TIME_WITH_TIMEZONE:
793             case DataType::TIMESTAMP_WITH_TIMEZONE:
794                 DeactivateAggregate( tpLength ); // we don't need a length for date types
795                 DeactivateAggregate( tpTextLen );
796                 DeactivateAggregate( tpBoolDefault );
797 
798                 ActivateAggregate( tpDefault );
799                 ActivateAggregate( tpFormat );
800                 break;
801             case DataType::BIT:
802                 if ( !pFieldType->aCreateParams.isEmpty() )
803                 {
804                     DeactivateAggregate( tpFormat );
805                     DeactivateAggregate( tpTextLen );
806                     DeactivateAggregate( tpBoolDefault );
807                     break;
808                 }
809                 [[fallthrough]];
810             case DataType::BOOLEAN:
811                 DeactivateAggregate( tpTextLen );
812                 DeactivateAggregate( tpFormat );
813                 DeactivateAggregate( tpDefault );
814 
815                 ActivateAggregate( tpBoolDefault );
816                 break;
817             case DataType::DECIMAL:
818             case DataType::NUMERIC:
819             case DataType::BIGINT:
820             case DataType::FLOAT:
821             case DataType::DOUBLE:
822             case DataType::TINYINT:
823             case DataType::SMALLINT:
824             case DataType::INTEGER:
825             case DataType::REAL:
826                 DeactivateAggregate( tpTextLen );
827                 DeactivateAggregate( tpBoolDefault );
828 
829                 ActivateAggregate( tpFormat );
830                 break;
831             case DataType::BINARY:
832             case DataType::VARBINARY:
833                 DeactivateAggregate( tpDefault );
834                 DeactivateAggregate( tpRequired );
835                 DeactivateAggregate( tpTextLen );
836                 DeactivateAggregate( tpBoolDefault );
837 
838                 ActivateAggregate( tpFormat );
839                 break;
840             case DataType::LONGVARBINARY:
841             case DataType::SQLNULL:
842             case DataType::OBJECT:
843             case DataType::DISTINCT:
844             case DataType::STRUCT:
845             case DataType::ARRAY:
846             case DataType::BLOB:
847             case DataType::CLOB:
848             case DataType::REF:
849             case DataType::OTHER:
850                 DeactivateAggregate( tpFormat );
851                 DeactivateAggregate( tpTextLen );
852                 DeactivateAggregate( tpBoolDefault );
853 
854                 break;
855             default:
856                 OSL_FAIL("Unknown type");
857         }
858         m_pPreviousType = pFieldType;
859     }
860 
861     if (pFieldDescr->IsPrimaryKey())
862     {
863         DeactivateAggregate(tpRequired);
864     }
865     else if (!m_xAutoIncrement && pFieldType)
866     {
867         if (pFieldType->bNullable)
868             ActivateAggregate(tpRequired);
869         else
870             DeactivateAggregate(tpRequired);
871     }
872     // Initialize Controls
873     if (m_xAutoIncrement)
874     {
875         if ( pFieldDescr->IsAutoIncrement() )
876         {
877             m_xAutoIncrement->set_active(0); // yes
878             ActivateAggregate( tpAutoIncrementValue );
879             if (m_xAutoIncrementValue)
880                 m_xAutoIncrementValue->set_text(pFieldDescr->GetAutoIncrementValue());
881             DeactivateAggregate( tpRequired );
882             DeactivateAggregate( tpDefault );
883         }
884         else
885         {
886             // disable autoincrement value because it should only be visible when autoincrement is to true
887             DeactivateAggregate( tpAutoIncrementValue );
888             m_xAutoIncrement->set_active(1);        // no
889             ActivateAggregate( tpDefault );
890             // Affects pRequired
891             if(!pFieldDescr->IsPrimaryKey())
892                 ActivateAggregate( tpRequired );
893         }
894     }
895 
896     if (m_xDefault)
897     {
898         m_xDefault->set_text(getControlDefault(pFieldDescr));
899         m_xDefault->save_value();
900     }
901 
902     if (m_xBoolDefault)
903     {
904         // If m_xRequired = sal_True then the sal_Bool field must NOT contain <<none>>
905         OUString sValue;
906         pFieldDescr->GetControlDefault() >>= sValue;
907         OUString sDef = BoolStringUI(sValue);
908 
909         // Make sure that <<none>> is only present if the field can be NULL
910         if ( ( pFieldType && !pFieldType->bNullable ) || !pFieldDescr->IsNullable() )
911         {
912             pFieldDescr->SetIsNullable(ColumnValue::NO_NULLS); // The type says so
913 
914             m_xBoolDefault->remove_text(DBA_RES(STR_VALUE_NONE));
915             if ( sDef != aYes && sDef != aNo )
916                 m_xBoolDefault->set_active(1);  // No as a default
917             else
918                 m_xBoolDefault->set_active_text(sDef);
919 
920             pFieldDescr->SetControlDefault(Any(BoolStringPersistent(m_xBoolDefault->get_active_text())));
921         }
922         else if (m_xBoolDefault->get_count() < 3)
923         {
924             m_xBoolDefault->append_text(DBA_RES(STR_VALUE_NONE));
925             m_xBoolDefault->set_active_text(sDef);
926         }
927         else
928             m_xBoolDefault->set_active_text(sDef);
929     }
930 
931     if (m_xRequired)
932     {
933         if( pFieldDescr->IsNullable() )
934             m_xRequired->set_active(1); // no
935         else
936             m_xRequired->set_active(0); // yes
937     }
938 
939     if (m_xTextLen)
940     {
941         m_xTextLen->set_text(OUString::number(pFieldDescr->GetPrecision()));
942         m_xTextLen->save_value();
943     }
944 
945     if( m_xNumType )
946     {
947         OSL_FAIL("OFieldDescControl::DisplayData: invalid num type!");
948     }
949 
950     if (m_xLength)
951         m_xLength->set_text(OUString::number(pFieldDescr->GetPrecision()));
952 
953     if (m_xScale)
954         m_xScale->set_text(OUString::number(pFieldDescr->GetScale()));
955 
956     if (m_xFormat)
957         UpdateFormatSample(pFieldDescr);
958 
959     if (m_xColumnName)
960         m_xColumnName->set_text(pFieldDescr->GetName());
961 
962     if (m_xType)
963     {
964         sal_Int32 nPos = pFieldType ? m_xType->find_text(pFieldDescr->getTypeInfo()->aUIName) : -1;
965         if (nPos == -1)
966         {
967             const OTypeInfoMap* pMap = getTypeInfo();
968             OTypeInfoMap::const_iterator aIter = pMap->find(pFieldType ? pFieldDescr->getTypeInfo()->nType : pFieldDescr->GetType());
969             if(aIter == pMap->end() && !pMap->empty())
970             {
971                 aIter = pMap->begin();
972                 if(pFieldDescr->GetPrecision() > aIter->second->nPrecision)
973                     pFieldDescr->SetPrecision(aIter->second->nPrecision);
974                 if(pFieldDescr->GetScale() > aIter->second->nMaximumScale)
975                     pFieldDescr->SetScale(0);
976                 if(!aIter->second->bNullable && pFieldDescr->IsNullable())
977                     pFieldDescr->SetIsNullable(ColumnValue::NO_NULLS);
978                 if(!aIter->second->bAutoIncrement && pFieldDescr->IsAutoIncrement())
979                     pFieldDescr->SetAutoIncrement(false);
980             }
981             if ( aIter != pMap->end() )
982             {
983                 pFieldDescr->SetType(aIter->second);
984             }
985         }
986         m_xType->set_active_text(pFieldDescr->getTypeInfo()->aUIName);
987     }
988 
989     // Enable/disable Controls
990     bool bRead(IsReadOnly());
991 
992     SetReadOnly( bRead );
993 }
994 
IMPL_LINK(OFieldDescControl,OnControlFocusGot,weld::Widget &,rControl,void)995 IMPL_LINK(OFieldDescControl, OnControlFocusGot, weld::Widget&, rControl, void )
996 {
997     OUString strHelpText;
998 
999     if (m_xTextLen && &rControl == m_xTextLen->GetWidget())
1000     {
1001         m_xTextLen->save_value();
1002         strHelpText = m_xTextLen->GetHelp();
1003     }
1004     else if (m_xLength && &rControl == m_xLength->GetWidget())
1005     {
1006         m_xLength->save_value();
1007         strHelpText = m_xLength->GetHelp();
1008     }
1009     else if (m_xScale && &rControl == m_xScale->GetWidget())
1010     {
1011         m_xScale->save_value();
1012         strHelpText = m_xScale->GetHelp();
1013     }
1014     else if (m_xColumnName && &rControl == m_xColumnName->GetWidget())
1015     {
1016         m_xColumnName->save_value();
1017         strHelpText = m_xColumnName->GetHelp();
1018     }
1019     else if (m_xDefault && &rControl == m_xDefault->GetWidget())
1020     {
1021         m_xDefault->save_value();
1022         strHelpText = m_xDefault->GetHelp();
1023     }
1024     else if (m_xFormatSample && &rControl == m_xFormatSample->GetWidget())
1025     {
1026         m_xFormatSample->save_value();
1027         strHelpText = m_xFormatSample->GetHelp();
1028     }
1029     else if (m_xAutoIncrementValue && &rControl == m_xAutoIncrementValue->GetWidget())
1030     {
1031         m_xAutoIncrementValue->save_value();
1032         strHelpText = m_xAutoIncrementValue->GetHelp();
1033     }
1034     else if (m_xRequired && &rControl == m_xRequired->GetWidget())
1035     {
1036         m_xRequired->save_value();
1037         strHelpText = m_xRequired->GetHelp();
1038     }
1039     else if (m_xNumType && &rControl == m_xNumType->GetWidget())
1040     {
1041         m_xNumType->save_value();
1042         strHelpText = m_xNumType->GetHelp();
1043     }
1044     else if (m_xAutoIncrement && &rControl == m_xAutoIncrement->GetWidget())
1045     {
1046         m_xAutoIncrement->save_value();
1047         strHelpText = m_xAutoIncrement->GetHelp();
1048     }
1049     else if (m_xBoolDefault && &rControl == m_xBoolDefault->GetWidget())
1050     {
1051         m_xBoolDefault->save_value();
1052         strHelpText = m_xBoolDefault->GetHelp();
1053     }
1054     else if (m_xType && &rControl == m_xType->GetWidget())
1055     {
1056         m_xType->save_value();
1057         strHelpText = m_xType->GetHelp();
1058     }
1059     else if (m_xFormat && &rControl == m_xFormat.get())
1060         strHelpText = DBA_RES(STR_HELP_FORMAT_BUTTON);
1061 
1062     if (!strHelpText.isEmpty() && m_pHelp)
1063         m_pHelp->SetHelpText(strHelpText);
1064 
1065     m_pActFocusWindow = &rControl;
1066 
1067     m_aControlFocusIn.Call(rControl);
1068 }
1069 
IMPL_LINK(OFieldDescControl,OnControlFocusLost,weld::Widget &,rControl,void)1070 IMPL_LINK(OFieldDescControl, OnControlFocusLost, weld::Widget&, rControl, void )
1071 {
1072     if (m_xLength && &rControl == m_xLength->GetWidget() && m_xLength->get_value_changed_from_saved())
1073         CellModified(-1, m_xLength->GetPos());
1074     else if (m_xTextLen && &rControl == m_xTextLen->GetWidget() && m_xTextLen->get_value_changed_from_saved())
1075         CellModified(-1, m_xTextLen->GetPos());
1076     else if (m_xScale && &rControl == m_xScale->GetWidget() && m_xScale->get_value_changed_from_saved())
1077         CellModified(-1, m_xScale->GetPos());
1078     else if (m_xColumnName && &rControl == m_xColumnName->GetWidget() && m_xColumnName->get_value_changed_from_saved())
1079         CellModified(-1, m_xColumnName->GetPos());
1080     else if (m_xDefault && &rControl == m_xDefault->GetWidget() && m_xDefault->get_value_changed_from_saved())
1081         CellModified(-1, m_xDefault->GetPos());
1082     else if (m_xFormatSample && &rControl == m_xFormatSample->GetWidget() && m_xFormatSample->get_value_changed_from_saved())
1083         CellModified(-1, m_xFormatSample->GetPos());
1084     else if (m_xAutoIncrementValue && &rControl == m_xAutoIncrementValue->GetWidget() && m_xAutoIncrementValue->get_value_changed_from_saved())
1085         CellModified(-1, m_xAutoIncrementValue->GetPos());
1086     else if (m_xRequired && &rControl == m_xRequired->GetWidget() && m_xRequired->get_value_changed_from_saved())
1087         CellModified(-1, m_xRequired->GetPos());
1088     else if (m_xNumType && &rControl == m_xNumType->GetWidget() && m_xNumType->get_value_changed_from_saved())
1089         CellModified(-1, m_xNumType->GetPos());
1090     else if (m_xAutoIncrement && &rControl == m_xAutoIncrement->GetWidget() && m_xAutoIncrement->get_value_changed_from_saved())
1091         CellModified(-1, m_xAutoIncrement->GetPos());
1092     else if (m_xBoolDefault && &rControl == m_xBoolDefault->GetWidget() && m_xBoolDefault->get_value_changed_from_saved())
1093         CellModified(-1, m_xBoolDefault->GetPos());
1094     else if (m_xType && &rControl == m_xType->GetWidget() && m_xType->get_value_changed_from_saved())
1095         CellModified(-1, m_xType->GetPos());
1096     else if (m_xDefault && &rControl == m_xDefault->GetWidget())
1097         UpdateFormatSample(pActFieldDescr);
1098 
1099     implFocusLost(&rControl);
1100 }
1101 
SaveData(OFieldDescription * pFieldDescr)1102 void OFieldDescControl::SaveData( OFieldDescription* pFieldDescr )
1103 {
1104     if( !pFieldDescr )
1105         return;
1106 
1107     // Read out Controls
1108     OUString sDefault;
1109     if (m_xDefault)
1110     {
1111         // tdf#138409 take the control default in the UI Locale format, e.g. 12,34 and return a string
1112         // suitable as the database default, e.g. 12.34
1113         sDefault = CanonicalizeToControlDefault(pFieldDescr, m_xDefault->get_text());
1114     }
1115     else if (m_xBoolDefault)
1116     {
1117         sDefault = BoolStringPersistent(m_xBoolDefault->get_active_text());
1118     }
1119 
1120     if ( !sDefault.isEmpty() )
1121         pFieldDescr->SetControlDefault(Any(sDefault));
1122     else
1123         pFieldDescr->SetControlDefault(Any());
1124 
1125     if((m_xRequired && m_xRequired->get_active() == 0) || pFieldDescr->IsPrimaryKey() || (m_xBoolDefault && m_xBoolDefault->get_count() == 2))  // yes
1126         pFieldDescr->SetIsNullable( ColumnValue::NO_NULLS );
1127     else
1128         pFieldDescr->SetIsNullable( ColumnValue::NULLABLE );
1129 
1130     if (m_xAutoIncrement)
1131         pFieldDescr->SetAutoIncrement(m_xAutoIncrement->get_active() == 0);
1132 
1133     if( m_xTextLen )
1134         pFieldDescr->SetPrecision( static_cast<sal_Int32>(m_xTextLen->get_value()) );
1135     else if (m_xLength)
1136         pFieldDescr->SetPrecision( static_cast<sal_Int32>(m_xLength->get_value()) );
1137     if (m_xScale)
1138         pFieldDescr->SetScale( static_cast<sal_Int32>(m_xScale->get_value()) );
1139 
1140     if (m_xColumnName)
1141         pFieldDescr->SetName(m_xColumnName->get_text());
1142 
1143     if (m_xAutoIncrementValue && isAutoIncrementValueEnabled())
1144         pFieldDescr->SetAutoIncrementValue(m_xAutoIncrementValue->get_text());
1145 }
1146 
UpdateFormatSample(OFieldDescription const * pFieldDescr)1147 void OFieldDescControl::UpdateFormatSample(OFieldDescription const * pFieldDescr)
1148 {
1149     if (pFieldDescr && m_xFormatSample)
1150         m_xFormatSample->set_text(getControlDefault(pFieldDescr,false));
1151 }
1152 
GrabFocus()1153 void OFieldDescControl::GrabFocus()
1154 {
1155     m_xContainer->grab_focus();
1156 
1157     // Set the Focus to the Control that has been active last
1158     if (m_pLastFocusWindow)
1159     {
1160         m_pLastFocusWindow->grab_focus();
1161         m_pLastFocusWindow = nullptr;
1162     }
1163 }
1164 
implFocusLost(weld::Widget * _pWhich)1165 void OFieldDescControl::implFocusLost(weld::Widget* _pWhich)
1166 {
1167     // Remember the active Control
1168     if (!m_pLastFocusWindow)
1169         m_pLastFocusWindow = _pWhich;
1170 
1171     // Reset HelpText
1172     if (m_pHelp && !m_pHelp->HasFocus())
1173         m_pHelp->SetHelpText( OUString() );
1174 }
1175 
IMPL_LINK_NOARG(OFieldDescControl,HelpFocusOut,weld::Widget &,void)1176 IMPL_LINK_NOARG(OFieldDescControl, HelpFocusOut, weld::Widget&, void)
1177 {
1178     m_pHelp->SetHelpText(OUString());
1179 }
1180 
IsFocusInEditableWidget() const1181 bool OFieldDescControl::IsFocusInEditableWidget() const
1182 {
1183     if (m_xDefault && m_pActFocusWindow == m_xDefault->GetWidget())
1184         return true;
1185     if (m_xFormatSample && m_pActFocusWindow == m_xFormatSample->GetWidget())
1186         return true;
1187     if (m_xTextLen && m_pActFocusWindow == m_xTextLen->GetWidget())
1188         return true;
1189     if (m_xLength && m_pActFocusWindow == m_xLength->GetWidget())
1190         return true;
1191     if (m_xScale && m_pActFocusWindow == m_xScale->GetWidget())
1192         return true;
1193     if (m_xColumnName && m_pActFocusWindow == m_xColumnName->GetWidget())
1194         return true;
1195     if (m_xAutoIncrementValue && m_pActFocusWindow == m_xAutoIncrementValue->GetWidget())
1196         return true;
1197     return false;
1198 }
1199 
HasChildPathFocus() const1200 bool OFieldDescControl::HasChildPathFocus() const
1201 {
1202     return m_xContainer && m_xContainer->has_child_focus();
1203 }
1204 
isCopyAllowed()1205 bool OFieldDescControl::isCopyAllowed()
1206 {
1207     int nStartPos, nEndPos;
1208     bool bAllowed = (m_pActFocusWindow != nullptr) && IsFocusInEditableWidget() &&
1209                         dynamic_cast<weld::Entry&>(*m_pActFocusWindow).get_selection_bounds(nStartPos, nEndPos);
1210     return bAllowed;
1211 }
1212 
isCutAllowed()1213 bool OFieldDescControl::isCutAllowed()
1214 {
1215     int nStartPos, nEndPos;
1216     bool bAllowed = (m_pActFocusWindow != nullptr) && IsFocusInEditableWidget() &&
1217                         dynamic_cast<weld::Entry&>(*m_pActFocusWindow).get_selection_bounds(nStartPos, nEndPos);
1218     return bAllowed;
1219 }
1220 
isPasteAllowed()1221 bool OFieldDescControl::isPasteAllowed()
1222 {
1223     bool bAllowed = (m_pActFocusWindow != nullptr) && IsFocusInEditableWidget();
1224     if ( bAllowed )
1225     {
1226         TransferableDataHelper aTransferData(TransferableDataHelper::CreateFromClipboard(m_pActFocusWindow->get_clipboard()));
1227         bAllowed = aTransferData.HasFormat(SotClipboardFormatId::STRING);
1228     }
1229     return bAllowed;
1230 }
1231 
cut()1232 void OFieldDescControl::cut()
1233 {
1234     if (isCutAllowed())
1235         dynamic_cast<weld::Entry&>(*m_pActFocusWindow).cut_clipboard();
1236 }
1237 
copy()1238 void OFieldDescControl::copy()
1239 {
1240     if (isCopyAllowed()) // this only checks if the focus window is valid
1241         dynamic_cast<weld::Entry&>(*m_pActFocusWindow).copy_clipboard();
1242 }
1243 
paste()1244 void OFieldDescControl::paste()
1245 {
1246     if (m_pActFocusWindow) // this only checks if the focus window is valid
1247         dynamic_cast<weld::Entry&>(*m_pActFocusWindow).paste_clipboard();
1248 }
1249 
isTextFormat(const OFieldDescription * _pFieldDescr,sal_uInt32 & _nFormatKey) const1250 bool OFieldDescControl::isTextFormat(const OFieldDescription* _pFieldDescr, sal_uInt32& _nFormatKey) const
1251 {
1252     _nFormatKey = _pFieldDescr->GetFormatKey();
1253     bool bTextFormat = true;
1254 
1255     try
1256     {
1257         if (!_nFormatKey)
1258         {
1259             Reference< css::util::XNumberFormatTypes> xNumberTypes(GetFormatter()->getNumberFormatsSupplier()->getNumberFormats(),UNO_QUERY);
1260             OSL_ENSURE(xNumberTypes.is(),"XNumberFormatTypes is null!");
1261 
1262             _nFormatKey = ::dbtools::getDefaultNumberFormat( _pFieldDescr->GetType(),
1263                 _pFieldDescr->GetScale(),
1264                 _pFieldDescr->IsCurrency(),
1265                 xNumberTypes,
1266                 GetLocale());
1267         }
1268         sal_Int32 nNumberFormat = ::comphelper::getNumberFormatType(GetFormatter(),_nFormatKey);
1269         bTextFormat = (nNumberFormat == css::util::NumberFormat::TEXT);
1270     }
1271     catch(const Exception&)
1272     {
1273 
1274     }
1275 
1276     return bTextFormat;
1277 }
1278 
getControlDefault(const OFieldDescription * _pFieldDescr,bool _bCheck) const1279 OUString OFieldDescControl::getControlDefault( const OFieldDescription* _pFieldDescr, bool _bCheck) const
1280 {
1281     OUString sDefault;
1282     bool bCheck = !_bCheck || _pFieldDescr->GetControlDefault().hasValue();
1283     if ( bCheck )
1284     {
1285         try
1286         {
1287             double nValue = 0.0;
1288             sal_uInt32 nFormatKey;
1289             bool bTextFormat = isTextFormat(_pFieldDescr,nFormatKey);
1290             if ( _pFieldDescr->GetControlDefault() >>= sDefault )
1291             {
1292                 if ( !bTextFormat )
1293                 {
1294                     if ( !sDefault.isEmpty() )
1295                     {
1296                         try
1297                         {
1298                             nValue = GetFormatter()->convertStringToNumber(nFormatKey,sDefault);
1299                         }
1300                         catch(const Exception&)
1301                         {
1302                             return OUString(); // return empty string for format example
1303                         }
1304                     }
1305                 }
1306             }
1307             else
1308                 _pFieldDescr->GetControlDefault() >>= nValue;
1309 
1310             Reference< css::util::XNumberFormatter> xNumberFormatter = GetFormatter();
1311             Reference<XPropertySet> xFormSet = xNumberFormatter->getNumberFormatsSupplier()->getNumberFormats()->getByKey(nFormatKey);
1312             OSL_ENSURE(xFormSet.is(),"XPropertySet is null!");
1313             OUString sFormat;
1314             xFormSet->getPropertyValue(u"FormatString"_ustr) >>= sFormat;
1315 
1316             if ( !bTextFormat )
1317             {
1318                 Locale aLocale;
1319                 ::comphelper::getNumberFormatProperty(xNumberFormatter,nFormatKey,u"Locale"_ustr) >>= aLocale;
1320 
1321                 sal_Int32 nNumberFormat = ::comphelper::getNumberFormatType(xNumberFormatter,nFormatKey);
1322                 if(     (nNumberFormat & css::util::NumberFormat::DATE)    == css::util::NumberFormat::DATE
1323                     || (nNumberFormat & css::util::NumberFormat::DATETIME) == css::util::NumberFormat::DATETIME )
1324                 {
1325                     nValue = DBTypeConversion::toNullDate(DBTypeConversion::getNULLDate(xNumberFormatter->getNumberFormatsSupplier()),nValue);
1326                 }
1327 
1328                 Reference< css::util::XNumberFormatPreviewer> xPreviewer(xNumberFormatter,UNO_QUERY);
1329                 OSL_ENSURE(xPreviewer.is(),"XNumberFormatPreviewer is null!");
1330                 sDefault = xPreviewer->convertNumberToPreviewString(sFormat,nValue,aLocale,true);
1331             }
1332             else if ( !(_bCheck && sDefault.isEmpty()) )
1333                 sDefault = xNumberFormatter->formatString(nFormatKey, sDefault.isEmpty() ? sFormat : sDefault);
1334         }
1335         catch(const Exception&)
1336         {
1337 
1338         }
1339     }
1340 
1341     return sDefault;
1342 }
1343 
1344 // tdf#138409 intended to be effectively the reverse of getControlDefault to
1345 // turn a user's possibly 12,34 format into 12.34 format for numerical types
CanonicalizeToControlDefault(const OFieldDescription * pFieldDescr,const OUString & rDefault) const1346 OUString OFieldDescControl::CanonicalizeToControlDefault(const OFieldDescription* pFieldDescr, const OUString& rDefault) const
1347 {
1348     if (rDefault.isEmpty())
1349         return rDefault;
1350 
1351     bool bIsNumericalType = false;
1352     switch (pFieldDescr->GetType())
1353     {
1354         case DataType::TINYINT:
1355         case DataType::SMALLINT:
1356         case DataType::INTEGER:
1357         case DataType::BIGINT:
1358         case DataType::FLOAT:
1359         case DataType::REAL:
1360         case DataType::DOUBLE:
1361         case DataType::NUMERIC:
1362         case DataType::DECIMAL:
1363             bIsNumericalType = true;
1364             break;
1365     }
1366 
1367     if (!bIsNumericalType)
1368         return rDefault;
1369 
1370     try
1371     {
1372         sal_uInt32 nFormatKey;
1373         bool bTextFormat = isTextFormat(pFieldDescr, nFormatKey);
1374         if (bTextFormat)
1375             return rDefault;
1376         double nValue = GetFormatter()->convertStringToNumber(nFormatKey, rDefault);
1377         return OUString::number(nValue);
1378     }
1379     catch(const Exception&)
1380     {
1381     }
1382 
1383     return rDefault;
1384 }
1385 
1386 
1387 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1388