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