Add Marathi autocorrect
[LibreOffice.git] / sw / source / ui / fldui / flddb.cxx
blob5762de3797439f17d3036aa164c6f4806e2dccde
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <swmodule.hxx>
21 #include <wrtsh.hxx>
22 #include <dbfld.hxx>
23 #include <doc.hxx>
25 #include "flddb.hxx"
26 #include <dbconfig.hxx>
27 #include <dbmgr.hxx>
28 #include <o3tl/string_view.hxx>
30 #define USER_DATA_VERSION_1 "1"
31 #define USER_DATA_VERSION USER_DATA_VERSION_1
33 SwFieldDBPage::SwFieldDBPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet *const pCoreSet)
34 : SwFieldPage(pPage, pController, u"modules/swriter/ui/flddbpage.ui"_ustr, u"FieldDbPage"_ustr, pCoreSet)
35 , m_nOldFormat(0)
36 , m_nOldSubType(0)
37 , m_xTypeLB(m_xBuilder->weld_tree_view(u"type"_ustr))
38 , m_xDatabaseTLB(new SwDBTreeList(m_xBuilder->weld_tree_view(u"select"_ustr)))
39 , m_xAddDBPB(m_xBuilder->weld_button(u"browse"_ustr))
40 , m_xCondition(m_xBuilder->weld_widget(u"condgroup"_ustr))
41 , m_xConditionED(new ConditionEdit<weld::Entry>(m_xBuilder->weld_entry(u"condition"_ustr)))
42 , m_xValue(m_xBuilder->weld_widget(u"recgroup"_ustr))
43 , m_xValueED(m_xBuilder->weld_entry(u"recnumber"_ustr))
44 , m_xDBFormatRB(m_xBuilder->weld_radio_button(u"fromdatabasecb"_ustr))
45 , m_xNewFormatRB(m_xBuilder->weld_radio_button(u"userdefinedcb"_ustr))
46 , m_xNumFormatLB(new NumFormatListBox(m_xBuilder->weld_combo_box(u"numformat"_ustr)))
47 , m_xFormatLB(m_xBuilder->weld_combo_box(u"format"_ustr))
48 , m_xFormat(m_xBuilder->weld_widget(u"formatframe"_ustr))
50 SetTypeSel(-1); //TODO
52 m_xTypeLB->make_sorted();
53 m_xFormatLB->make_sorted();
55 auto nWidth = m_xTypeLB->get_approximate_digit_width() * FIELD_COLUMN_WIDTH;
56 auto nHeight = m_xTypeLB->get_height_rows(10);
57 m_xTypeLB->set_size_request(nWidth, nHeight);
58 m_xDatabaseTLB->set_size_request(nWidth*2, nHeight);
60 m_xNumFormatLB->connect_changed(LINK(this, SwFieldDBPage, NumSelectHdl));
61 m_xDatabaseTLB->connect_changed(LINK(this, SwFieldDBPage, TreeSelectHdl));
62 m_xDatabaseTLB->connect_row_activated(LINK(this, SwFieldDBPage, TreeViewInsertHdl));
64 m_xValueED->connect_changed(LINK(this, SwFieldDBPage, ModifyHdl));
65 m_xAddDBPB->connect_clicked(LINK(this, SwFieldDBPage, AddDBHdl));
67 // uitests
68 m_xTypeLB->set_buildable_name(m_xTypeLB->get_buildable_name() + "-db");
69 m_xNumFormatLB->set_buildable_name(m_xNumFormatLB->get_buildable_name() + "-db");
70 m_xFormatLB->set_buildable_name(m_xFormatLB->get_buildable_name() + "-db");
73 SwFieldDBPage::~SwFieldDBPage()
75 // If we have no stored SwWrtShell, it means we didn't do anything useful - no need to revoke.
76 if (SwWrtShell* pSh = CheckAndGetWrtShell())
78 // This would cleanup in the case of cancelled dialog
79 SwDBManager* pDbManager = pSh->GetDoc()->GetDBManager();
80 if (pDbManager)
81 pDbManager->RevokeLastRegistrations();
85 // initialise TabPage
86 void SwFieldDBPage::Reset(const SfxItemSet*)
88 Init(); // general initialization
90 const sal_Int32 nOldPos = m_xTypeLB->get_selected_index();
91 m_xTypeLB->freeze();
92 m_sOldDBName = m_xDatabaseTLB->GetDBName(m_sOldTableName, m_sOldColumnName);
94 m_xTypeLB->clear();
96 if (!IsFieldEdit())
98 // initialise TypeListBox
99 const SwFieldGroupRgn& rRg = SwFieldMgr::GetGroupRange(IsFieldDlgHtmlMode(), GetGroup());
101 for(sal_uInt16 i = rRg.nStart; i < rRg.nEnd; ++i)
103 const SwFieldTypesEnum nTypeId = SwFieldMgr::GetTypeId(i);
104 m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)), SwFieldMgr::GetTypeStr(i));
107 else
109 const SwFieldTypesEnum nTypeId = GetCurField()->GetTypeId();
110 m_xTypeLB->append(OUString::number(static_cast<sal_uInt16>(nTypeId)),
111 SwFieldMgr::GetTypeStr(SwFieldMgr::GetPos(nTypeId)));
114 m_xTypeLB->thaw();
116 // select old Pos
117 if (GetTypeSel() != -1)
118 m_xTypeLB->select(GetTypeSel());
120 m_xFormatLB->clear();
122 const sal_uInt16 nSize = GetFieldMgr().GetFormatCount(SwFieldTypesEnum::DatabaseSetNumber, IsFieldDlgHtmlMode());
123 for( sal_uInt16 i = 0; i < nSize; ++i )
125 const sal_uInt16 nFormatId = GetFieldMgr().GetFormatId( SwFieldTypesEnum::DatabaseSetNumber, i );
126 OUString sId(OUString::number(nFormatId));
127 m_xFormatLB->append(sId, GetFieldMgr().GetFormatStr(SwFieldTypesEnum::DatabaseSetNumber, i));
128 if (SVX_NUM_ARABIC == nFormatId)
129 m_xFormatLB->set_active_id(sId);
132 if (!IsFieldEdit())
134 if (nOldPos != -1)
135 m_xTypeLB->select(nOldPos);
137 if (!m_sOldDBName.isEmpty())
139 m_xDatabaseTLB->Select(m_sOldDBName, m_sOldTableName, m_sOldColumnName);
141 else
143 if (SwWrtShell *pSh = CheckAndGetWrtShell())
145 SwDBData aTmp(pSh->GetDBData());
146 m_xDatabaseTLB->Select(aTmp.sDataSource, aTmp.sCommand, u"");
151 if( !IsRefresh() )
153 const OUString sUserData = GetUserData();
154 sal_Int32 nIdx{ 0 };
155 if (o3tl::equalsIgnoreAsciiCase(o3tl::getToken(sUserData, 0, ';', nIdx), u"" USER_DATA_VERSION_1))
157 const sal_uInt16 nVal = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(o3tl::getToken(sUserData, 0, ';', nIdx)));
158 if (nVal != USHRT_MAX)
160 for (sal_Int32 i = 0, nEntryCount = m_xTypeLB->n_children(); i < nEntryCount; ++i)
162 if (nVal == m_xTypeLB->get_id(i).toUInt32())
164 m_xTypeLB->select(i);
165 break;
171 TypeHdl(nullptr);
173 m_xTypeLB->connect_selection_changed(LINK(this, SwFieldDBPage, TypeListBoxHdl));
174 m_xTypeLB->connect_row_activated(LINK(this, SwFieldDBPage, TreeViewInsertHdl));
176 if (IsFieldEdit())
178 m_xConditionED->save_value();
179 m_xValueED->save_value();
180 m_sOldDBName = m_xDatabaseTLB->GetDBName(m_sOldTableName, m_sOldColumnName);
181 m_nOldFormat = GetCurField()->GetFormat();
182 m_nOldSubType = GetCurField()->GetSubType();
186 // SwFieldDBPage may ask for password to select current document's data source,
187 // so only do that when activating the page, not when dialog is creating all pages
188 bool SwFieldDBPage::DeferResetToFirstActivation() { return true; }
190 bool SwFieldDBPage::FillItemSet(SfxItemSet* )
192 OUString sTableName;
193 OUString sColumnName;
194 SwDBData aData;
195 sal_Bool bIsTable;
196 aData.sDataSource = m_xDatabaseTLB->GetDBName(sTableName, sColumnName, &bIsTable);
197 aData.sCommand = sTableName;
198 aData.nCommandType = bIsTable ? 0 : 1;
200 if (SwWrtShell *pSh = CheckAndGetWrtShell())
202 SwDBManager* pDbManager = pSh->GetDoc()->GetDBManager();
203 if (pDbManager)
204 pDbManager->CommitLastRegistrations();
206 if (aData.sDataSource.isEmpty())
207 aData = pSh->GetDBData();
210 if(!aData.sDataSource.isEmpty()) // without database no new field command
212 const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32());
213 sal_uInt32 nFormat = 0;
214 sal_uInt16 nSubType = 0;
216 OUString sDBName = aData.sDataSource
217 + OUStringChar(DB_DELIM)
218 + aData.sCommand
219 + OUStringChar(DB_DELIM)
220 + OUString::number(aData.nCommandType)
221 + OUStringChar(DB_DELIM);
222 if (!sColumnName.isEmpty())
224 sDBName += sColumnName + OUStringChar(DB_DELIM);
226 OUString aName = sDBName + m_xConditionED->get_text();
228 switch (nTypeId)
230 case SwFieldTypesEnum::Database:
231 nFormat = m_xNumFormatLB->GetFormat();
232 if (m_xNewFormatRB->get_sensitive() && m_xNewFormatRB->get_active())
233 nSubType = nsSwExtendedSubType::SUB_OWN_FMT;
234 aName = sDBName;
235 break;
237 case SwFieldTypesEnum::DatabaseSetNumber:
238 nFormat = m_xFormatLB->get_active_id().toUInt32();
239 break;
240 default: break;
243 const OUString aVal(m_xValueED->get_text());
244 OUString sTempTableName;
245 OUString sTempColumnName;
246 OUString sTempDBName = m_xDatabaseTLB->GetDBName(sTempTableName, sTempColumnName);
247 bool bDBListBoxChanged = m_sOldDBName != sTempDBName ||
248 m_sOldTableName != sTempTableName || m_sOldColumnName != sTempColumnName;
249 if (!IsFieldEdit() ||
250 m_xConditionED->get_value_changed_from_saved() ||
251 m_xValueED->get_saved_value() != aVal ||
252 bDBListBoxChanged ||
253 m_nOldFormat != nFormat || m_nOldSubType != nSubType)
255 InsertField( nTypeId, nSubType, aName, aVal, nFormat);
259 return false;
262 std::unique_ptr<SfxTabPage> SwFieldDBPage::Create( weld::Container* pPage, weld::DialogController* pController,
263 const SfxItemSet *const pAttrSet )
265 return std::make_unique<SwFieldDBPage>( pPage, pController, pAttrSet );
268 sal_uInt16 SwFieldDBPage::GetGroup()
270 return GRP_DB;
273 IMPL_LINK( SwFieldDBPage, TypeListBoxHdl, weld::TreeView&, rBox, void )
275 TypeHdl(&rBox);
278 void SwFieldDBPage::TypeHdl(const weld::TreeView* pBox)
280 // save old ListBoxPos
281 const sal_Int32 nOld = GetTypeSel();
283 // current ListBoxPos
284 SetTypeSel(m_xTypeLB->get_selected_index());
286 if (GetTypeSel() == -1)
288 SetTypeSel(0);
289 m_xTypeLB->select(0);
292 if (nOld == GetTypeSel())
293 return;
295 bool bCond = false, bSetNo = false, bFormat = false, bDBFormat = false;
296 const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32());
298 m_xDatabaseTLB->ShowColumns(nTypeId == SwFieldTypesEnum::Database);
300 if (IsFieldEdit())
302 SwDBData aData;
303 OUString sColumnName;
304 if (nTypeId == SwFieldTypesEnum::Database)
306 if (auto const*const pField = dynamic_cast<SwDBField*>(GetCurField()))
308 aData = pField->GetDBData();
309 sColumnName = static_cast<SwDBFieldType*>(GetCurField()->GetTyp())->GetColumnName();
312 else
314 if (auto *const pField = dynamic_cast<SwDBNameInfField*>(GetCurField()))
316 if(SwWrtShell *pSh = CheckAndGetWrtShell())
317 aData = pField->GetDBData(pSh->GetDoc());
320 m_xDatabaseTLB->Select(aData.sDataSource, aData.sCommand, sColumnName);
323 switch (nTypeId)
325 case SwFieldTypesEnum::Database:
327 bFormat = true;
328 bDBFormat = true;
329 m_xNumFormatLB->show();
330 m_xFormatLB->hide();
332 weld::Widget& rWidget = m_xNumFormatLB->get_widget();
333 rWidget.set_accessible_relation_labeled_by(m_xNewFormatRB.get());
335 if (pBox) // type was changed by user
336 m_xDBFormatRB->set_active(true);
338 if (IsFieldEdit())
340 if (GetCurField()->GetFormat() != 0 && GetCurField()->GetFormat() != SAL_MAX_UINT32)
341 m_xNumFormatLB->SetDefFormat(GetCurField()->GetFormat());
343 if (GetCurField()->GetSubType() & nsSwExtendedSubType::SUB_OWN_FMT)
344 m_xNewFormatRB->set_active(true);
345 else
346 m_xDBFormatRB->set_active(true);
348 break;
350 case SwFieldTypesEnum::DatabaseNumberSet:
351 bSetNo = true;
352 [[fallthrough]];
353 case SwFieldTypesEnum::DatabaseNextSet:
354 bCond = true;
355 if (IsFieldEdit())
357 m_xConditionED->set_text(GetCurField()->GetPar1());
358 m_xValueED->set_text(GetCurField()->GetPar2());
360 break;
362 case SwFieldTypesEnum::DatabaseName:
363 break;
365 case SwFieldTypesEnum::DatabaseSetNumber:
367 bFormat = true;
368 m_xNewFormatRB->set_active(true);
369 m_xNumFormatLB->hide();
370 m_xFormatLB->show();
372 m_xFormatLB->set_accessible_relation_labeled_by(m_xNewFormatRB.get());
374 if( IsFieldEdit() )
376 for (sal_Int32 nI = m_xFormatLB->get_count(); nI;)
378 if (GetCurField()->GetFormat() == m_xFormatLB->get_id(--nI).toUInt32())
380 m_xFormatLB->set_active( nI );
381 break;
385 break;
387 default: break;
390 m_xCondition->set_sensitive(bCond);
391 m_xValue->set_sensitive(bSetNo);
392 if (nTypeId != SwFieldTypesEnum::Database)
394 m_xDBFormatRB->set_sensitive(bDBFormat);
395 m_xNewFormatRB->set_sensitive(bDBFormat || bFormat);
396 m_xNumFormatLB->set_sensitive(bDBFormat);
397 m_xFormatLB->set_sensitive(bFormat);
399 m_xFormat->set_sensitive(bDBFormat || bFormat);
401 if (!IsFieldEdit())
403 m_xValueED->set_text(OUString());
404 if (bCond)
405 m_xConditionED->set_text(u"TRUE"_ustr);
406 else
407 m_xConditionED->set_text(OUString());
410 CheckInsert();
413 IMPL_LINK_NOARG(SwFieldDBPage, NumSelectHdl, weld::ComboBox&, void)
415 m_xNewFormatRB->set_active(true);
416 m_xNumFormatLB->CallSelectHdl();
419 void SwFieldDBPage::CheckInsert()
421 bool bInsert = true;
422 const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32());
424 std::unique_ptr<weld::TreeIter> xIter(m_xDatabaseTLB->make_iterator());
425 if (m_xDatabaseTLB->get_selected(xIter.get()))
427 bool bEntry = m_xDatabaseTLB->iter_parent(*xIter);
429 if (nTypeId == SwFieldTypesEnum::Database && bEntry)
430 bEntry = m_xDatabaseTLB->iter_parent(*xIter);
432 bInsert &= bEntry;
434 else
435 bInsert = false;
437 if (nTypeId == SwFieldTypesEnum::DatabaseNumberSet)
439 bool bHasValue = !m_xValueED->get_text().isEmpty();
441 bInsert &= bHasValue;
444 EnableInsert(bInsert, IsCurrentPage());
447 IMPL_LINK(SwFieldDBPage, TreeSelectHdl, weld::TreeView&, rBox, void)
449 std::unique_ptr<weld::TreeIter> xIter(rBox.make_iterator());
450 if (!rBox.get_selected(xIter.get()))
451 return;
453 const SwFieldTypesEnum nTypeId = static_cast<SwFieldTypesEnum>(m_xTypeLB->get_id(GetTypeSel()).toUInt32());
455 bool bEntry = m_xDatabaseTLB->iter_parent(*xIter);
457 if (nTypeId == SwFieldTypesEnum::Database && bEntry)
458 bEntry = m_xDatabaseTLB->iter_parent(*xIter);
460 CheckInsert();
462 if (nTypeId != SwFieldTypesEnum::Database)
463 return;
465 bool bNumFormat = false;
467 if (bEntry)
469 OUString sTableName;
470 OUString sColumnName;
471 sal_Bool bIsTable;
472 OUString sDBName = m_xDatabaseTLB->GetDBName(sTableName, sColumnName, &bIsTable);
473 bNumFormat = GetFieldMgr().IsDBNumeric(sDBName,
474 sTableName,
475 bIsTable,
476 sColumnName);
477 if (!IsFieldEdit())
478 m_xDBFormatRB->set_active(true);
481 m_xDBFormatRB->set_sensitive(bNumFormat);
482 m_xNewFormatRB->set_sensitive(bNumFormat);
483 m_xNumFormatLB->set_sensitive(bNumFormat);
484 m_xFormat->set_sensitive(bNumFormat);
487 IMPL_LINK_NOARG(SwFieldDBPage, AddDBHdl, weld::Button&, void)
489 if (SwWrtShell* pSh = CheckAndGetWrtShell())
491 OUString sNewDB
492 = SwDBManager::LoadAndRegisterDataSource(GetFrameWeld(), pSh->GetDoc()->GetDocShell());
493 if (!sNewDB.isEmpty())
495 m_xDatabaseTLB->AddDataSource(sNewDB);
500 // Modify
501 IMPL_LINK_NOARG(SwFieldDBPage, ModifyHdl, weld::Entry&, void)
503 CheckInsert();
506 void SwFieldDBPage::FillUserData()
508 const sal_Int32 nEntryPos = m_xTypeLB->get_selected_index();
509 const sal_uInt16 nTypeSel = ( -1 == nEntryPos )
510 ? USHRT_MAX : m_xTypeLB->get_id(nEntryPos).toUInt32();
511 SetUserData(USER_DATA_VERSION ";" + OUString::number( nTypeSel ));
514 void SwFieldDBPage::ActivateMailMergeAddress()
516 m_xTypeLB->select_id(OUString::number(static_cast<sal_uInt16>(SwFieldTypesEnum::Database)));
517 TypeListBoxHdl(*m_xTypeLB);
518 const SwDBData& rData = SwModule::get()->GetDBConfig()->GetAddressSource();
519 m_xDatabaseTLB->Select(rData.sDataSource, rData.sCommand, u"");
522 void SwFieldDBPage::SetWrtShell(SwWrtShell& rSh)
524 // We need to remember the shell to be able to call correct SwDBManager
525 SwFieldPage::SetWrtShell(&rSh);
526 m_xDatabaseTLB->SetWrtShell(rSh);
529 SwWrtShell* SwFieldDBPage::CheckAndGetWrtShell()
531 SwWrtShell* pSh = GetWrtShell();
532 if (!pSh)
534 pSh = ::GetActiveWrtShell();
535 if (pSh) // this is not guaranteed: e.g., activating print preview with dialog active
536 SetWrtShell(*pSh);
538 return pSh;
541 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */