tdf#85976 [RFE] Add a "Remove Duplicate Records" command
Add a "Remove Duplicate Records" entry under Calc > menu Data to remove duplicate records from a rectangular selection of cells in Calc. Change-Id: Ic8340d7f1e19461ef3666fd2ef65294b73577d5c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160685 Reviewed-by: Heiko Tietze <heiko.tietze@documentfoundation.org> Tested-by: Jenkins
This commit is contained in:
parent
b8368ad96e
commit
29fd68bb68
16 changed files with 1062 additions and 1 deletions
|
@ -684,7 +684,8 @@ class SvxZoomItem;
|
|||
#define FN_PARAM_4 (FN_PARAM+63)
|
||||
#define FN_PARAM_5 (FN_PARAM+64)
|
||||
#define FN_PARAM_6 (FN_PARAM+65)
|
||||
#define FN_NOUPDATE TypedWhichId<SfxBoolItem>(FN_PARAM+66)
|
||||
#define FN_PARAM_7 (FN_PARAM+66)
|
||||
#define FN_NOUPDATE TypedWhichId<SfxBoolItem>(FN_PARAM+67)
|
||||
#define FN_FAX (SID_SW_START + 28) /* Fax */
|
||||
|
||||
#define SID_KEYFUNC_START (SID_SC_START + 521)
|
||||
|
|
|
@ -1378,6 +1378,14 @@
|
|||
<value>1</value>
|
||||
</prop>
|
||||
</node>
|
||||
<node oor:name=".uno:HandleDuplicateRecords" oor:op="replace">
|
||||
<prop oor:name="Label" oor:type="xs:string">
|
||||
<value xml:lang="en-US">Duplicate Records...</value>
|
||||
</prop>
|
||||
<prop oor:name="Properties" oor:type="xs:int">
|
||||
<value>1</value>
|
||||
</prop>
|
||||
</node>
|
||||
<node oor:name=".uno:ViewColumnRowHighlighting" oor:op="replace">
|
||||
<prop oor:name="Label" oor:type="xs:string">
|
||||
<value xml:lang="en-US">Column/Row Highlighting</value>
|
||||
|
|
|
@ -1791,6 +1791,36 @@
|
|||
<info>
|
||||
<desc>Contains miscellaneous settings.</desc>
|
||||
</info>
|
||||
<group oor:name="HandleDuplicateRecords">
|
||||
<info>
|
||||
<desc>Defines the settings for 'handle duplicate records' dialog.</desc>
|
||||
<label>Handle duplicate records settings</label>
|
||||
</info>
|
||||
<prop oor:name="DataIncludesHeaders" oor:type="xs:boolean" oor:nillable="false">
|
||||
<!-- UIHints: Data - Duplicate Records... -->
|
||||
<info>
|
||||
<desc>Indicates whether selected data includes headers in the 'handle duplicate records' dialog.</desc>
|
||||
<label>Data includes row/column headers</label>
|
||||
</info>
|
||||
<value>false</value>
|
||||
</prop>
|
||||
<prop oor:name="RemoveDuplicateRows" oor:type="xs:boolean" oor:nillable="false">
|
||||
<!-- UIHints: Data - Duplicate Records... -->
|
||||
<info>
|
||||
<desc>Indicates whether to remove rows, or columns in the 'handle duplicate records' dialog.</desc>
|
||||
<label>Data includes row/column headers</label>
|
||||
</info>
|
||||
<value>false</value>
|
||||
</prop>
|
||||
<prop oor:name="RemoveRecords" oor:type="xs:boolean" oor:nillable="false">
|
||||
<!-- UIHints: Data - Duplicate Records... -->
|
||||
<info>
|
||||
<desc>Indicates whether to select or remove records in the 'handle duplicate records' dialog.</desc>
|
||||
<label>Select or remove</label>
|
||||
</info>
|
||||
<value>true</value>
|
||||
</prop>
|
||||
</group>
|
||||
<group oor:name="DefaultObjectSize">
|
||||
<info>
|
||||
<desc>Defines the default size of newly created objects using CTRL-Return or CTRL-Click at an object creating Button.</desc>
|
||||
|
|
|
@ -499,6 +499,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
|
|||
sc/source/ui/miscdlgs/onlyactivesheetsaveddlg \
|
||||
sc/source/ui/miscdlgs/optsolver \
|
||||
sc/source/ui/miscdlgs/protectiondlg \
|
||||
sc/source/ui/miscdlgs/duplicaterecordsdlg \
|
||||
sc/source/ui/miscdlgs/redcom \
|
||||
sc/source/ui/miscdlgs/retypepassdlg \
|
||||
sc/source/ui/miscdlgs/sharedocdlg \
|
||||
|
|
|
@ -95,6 +95,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/scalc,\
|
|||
sc/uiconfig/scalc/ui/autoformattable \
|
||||
sc/uiconfig/scalc/ui/autosum \
|
||||
sc/uiconfig/scalc/ui/cellprotectionpage \
|
||||
sc/uiconfig/scalc/ui/duplicaterecordsdlg \
|
||||
sc/uiconfig/scalc/ui/changesourcedialog \
|
||||
sc/uiconfig/scalc/ui/chardialog \
|
||||
sc/uiconfig/scalc/ui/checkwarningdialog \
|
||||
|
|
|
@ -277,6 +277,7 @@ class SvxZoomSliderItem;
|
|||
|
||||
#define FID_TOGGLEINPUTLINE TypedWhichId<SfxBoolItem>(VIEW_MENU_START + 1)
|
||||
#define FID_TOGGLEHEADERS (VIEW_MENU_START + 2)
|
||||
#define FID_HANDLEDUPLICATERECORDS (VIEW_MENU_START + 3)
|
||||
#define FID_SCALE TypedWhichId<SvxZoomItem>(VIEW_MENU_START + 4)
|
||||
#define FID_TOGGLESYNTAX (VIEW_MENU_START + 5)
|
||||
#define FID_TOGGLECOLROWHIGHLIGHTING (VIEW_MENU_START + 6)
|
||||
|
|
|
@ -437,6 +437,10 @@
|
|||
#define STR_CONDITION_THISYEAR NC_("STR_CONDITION_THISYEAR", "date is in this year")
|
||||
#define STR_CONDITION_LASTYEAR NC_("STR_CONDITION_LASTYEAR", "date is in last year")
|
||||
#define STR_CONDITION_NEXTYEAR NC_("STR_CONDITION_NEXTYEAR", "date is in next year")
|
||||
#define STR_DUPLICATERECORDSDLG_WARNING NC_("STR_DUPLICATERECORDS_WARNING", "Warning!")
|
||||
#define STR_DUPLICATERECORDSDLG_NODATAFOUND NC_("STR_DUPLICATERECORDS_NODATAFOUND", "No data found to operate on.")
|
||||
#define STR_DUPLICATERECORDS_DATACONATINSROWHEADERS NC_("STR_DUPLICATERECORDS_DATACONATINSROWHEADERS", "Data contains row headers")
|
||||
#define STR_DUPLICATERECORDS_DATACONATINSCOLUMNHEADERS NC_("STR_DUPLICATERECORDS_DATACONATINSCOLUMNHEADERS", "Data contains column headers")
|
||||
|
||||
|
||||
#define STR_CONTENT_WITH_UNKNOWN_ENCRYPTION NC_("STR_CONTENT_WITH_UNKNOWN_ENCRYPTION", "Document contains DRM content that is encrypted with an unknown encryption method. Only the un-encrypted content will be shown.")
|
||||
|
|
|
@ -6054,6 +6054,32 @@ SfxBoolItem ViewValueHighlighting FID_TOGGLESYNTAX
|
|||
GroupId = SfxGroupId::View;
|
||||
]
|
||||
|
||||
SfxBoolItem HandleDuplicateRecords FID_HANDLEDUPLICATERECORDS
|
||||
(
|
||||
SfxBoolItem Remove FID_HANDLEDUPLICATERECORDS,
|
||||
SfxBoolItem IncludesHeaders FN_PARAM_1,
|
||||
SfxBoolItem DuplicateRows FN_PARAM_2,
|
||||
SfxInt32Item StartColumn FN_PARAM_3,
|
||||
SfxInt32Item StartRow FN_PARAM_4,
|
||||
SfxInt32Item EndColumn FN_PARAM_5,
|
||||
SfxInt32Item EndRow FN_PARAM_6,
|
||||
SfxInt32Item TabNo FN_PARAM_7
|
||||
)
|
||||
[
|
||||
AutoUpdate = FALSE,
|
||||
FastCall = FALSE,
|
||||
ReadOnlyDoc = TRUE,
|
||||
Toggle = FALSE,
|
||||
Container = FALSE,
|
||||
RecordAbsolute = FALSE,
|
||||
RecordPerSet;
|
||||
|
||||
|
||||
AccelConfig = TRUE,
|
||||
MenuConfig = TRUE,
|
||||
ToolBoxConfig = TRUE,
|
||||
GroupId = SfxGroupId::View;
|
||||
]
|
||||
SfxBoolItem ViewColumnRowHighlighting FID_TOGGLECOLROWHIGHLIGHTING
|
||||
|
||||
[
|
||||
|
|
|
@ -174,6 +174,7 @@ interface TableEditView
|
|||
|
||||
FID_SCALESTATUS [ ExecMethod = Execute; StateMethod = GetState; ]
|
||||
FID_TOGGLESYNTAX [ ExecMethod = Execute; StateMethod = GetState; ]
|
||||
FID_HANDLEDUPLICATERECORDS [ ExecMethod = Execute; StateMethod = GetState; ]
|
||||
FID_TOGGLECOLROWHIGHLIGHTING [ ExecMethod = Execute; StateMethod = GetState; ]
|
||||
FID_TOGGLEHEADERS [ ExecMethod = Execute; StateMethod = GetState; ]
|
||||
FID_TOGGLEFORMULA [ ExecMethod = Execute; StateMethod = GetState; ]
|
||||
|
|
75
sc/source/ui/inc/duplicaterecordsdlg.hxx
Normal file
75
sc/source/ui/inc/duplicaterecordsdlg.hxx
Normal file
|
@ -0,0 +1,75 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "viewdata.hxx"
|
||||
#include <vcl/weld.hxx>
|
||||
|
||||
using namespace css;
|
||||
|
||||
struct DuplicatesResponse
|
||||
{
|
||||
std::vector<int> vEntries;
|
||||
bool bRemove; // false ==> Select
|
||||
bool bIncludesHeaders;
|
||||
bool bDuplicatRows; // false ==> DuplicateColumns
|
||||
};
|
||||
|
||||
class ScDuplicateRecordsDlg : public weld::GenericDialogController
|
||||
{
|
||||
public:
|
||||
ScDuplicateRecordsDlg() = delete;
|
||||
explicit ScDuplicateRecordsDlg(weld::Window* pParent,
|
||||
css::uno::Sequence<uno::Sequence<uno::Any>>& rData,
|
||||
ScViewData& rViewData, ScRange& aRange);
|
||||
virtual ~ScDuplicateRecordsDlg() override;
|
||||
|
||||
DuplicatesResponse GetDialogData() { return maResponse; };
|
||||
|
||||
private:
|
||||
void Init();
|
||||
void Okay();
|
||||
void SetDialogData(bool bToggle);
|
||||
std::unique_ptr<weld::CheckButton> m_xIncludesHeaders;
|
||||
std::unique_ptr<weld::RadioButton> m_xRadioRow;
|
||||
std::unique_ptr<weld::RadioButton> m_xRadioColumn;
|
||||
std::unique_ptr<weld::RadioButton> m_xRadioSelect;
|
||||
std::unique_ptr<weld::RadioButton> m_xRadioRemove;
|
||||
std::unique_ptr<weld::TreeView> m_xCheckList;
|
||||
std::unique_ptr<weld::CheckButton> m_xAllChkBtn;
|
||||
|
||||
std::unique_ptr<weld::Button> m_xOkBtn;
|
||||
std::unique_ptr<weld::Button> m_xHelpBtn;
|
||||
|
||||
uno::Sequence<uno::Sequence<uno::Any>>& mrCellData;
|
||||
ScRange& mrRange;
|
||||
ScViewData& mrViewData;
|
||||
DuplicatesResponse maResponse;
|
||||
|
||||
void InsertEntry(const OUString& rTxt, bool bToggle);
|
||||
|
||||
DECL_LINK(OrientationHdl, weld::Toggleable&, void);
|
||||
DECL_LINK(HeaderCkbHdl, weld::Toggleable&, void);
|
||||
DECL_LINK(OkHdl, weld::Button&, void);
|
||||
DECL_LINK(AllCheckBtnHdl, weld::Toggleable&, void);
|
||||
DECL_LINK(RecordsChkHdl, const weld::TreeView::iter_col&, void);
|
||||
};
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
|
@ -31,6 +31,7 @@
|
|||
#include <shellids.hxx>
|
||||
#include <tabprotection.hxx>
|
||||
#include <com/sun/star/ui/dialogs/DialogClosedEvent.hpp>
|
||||
#include <com/sun/star/sheet/XSpreadsheet.hpp>
|
||||
#include <dragdata.hxx>
|
||||
|
||||
#include <memory>
|
||||
|
@ -267,6 +268,13 @@ public:
|
|||
SC_DLLPUBLIC bool IsRefInputMode() const;
|
||||
void ExecuteInputDirect();
|
||||
|
||||
void HandleDuplicateRecords(css::uno::Reference<css::sheet::XSpreadsheet> ActiveSheet,
|
||||
const css::table::CellRangeAddress& aRange, bool bRemove,
|
||||
bool bIncludesHeaders, bool bDuplicateRows,
|
||||
const std::vector<int>& rSelectedEntries);
|
||||
css::uno::Reference<css::sheet::XSpreadsheet> GetRangeWithSheet(css::table::CellRangeAddress& rRangeData, bool& bHasData, bool bHasUnoArguments);
|
||||
void ExtendSingleSelection(css::table::CellRangeAddress& rRangeData);
|
||||
|
||||
const ScInputHandler* GetInputHandler() const { return mpInputHandler.get(); }
|
||||
ScInputHandler* GetInputHandler() { return mpInputHandler.get(); }
|
||||
SC_DLLPUBLIC const OUString* GetEditString() const;
|
||||
|
|
214
sc/source/ui/miscdlgs/duplicaterecordsdlg.cxx
Normal file
214
sc/source/ui/miscdlgs/duplicaterecordsdlg.cxx
Normal file
|
@ -0,0 +1,214 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* This file incorporates work covered by the following license notice:
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
||||
*/
|
||||
|
||||
#include <scresid.hxx>
|
||||
#include <dbdata.hxx>
|
||||
#include <cellvalue.hxx>
|
||||
#include <duplicaterecordsdlg.hxx>
|
||||
#include <string>
|
||||
#include <strings.hrc>
|
||||
#include <tabprotection.hxx>
|
||||
#include <gridwin.hxx>
|
||||
#include <vector>
|
||||
#include <officecfg/Office/Calc.hxx>
|
||||
|
||||
ScDuplicateRecordsDlg::ScDuplicateRecordsDlg(weld::Window* pParent,
|
||||
css::uno::Sequence<uno::Sequence<uno::Any>>& rData,
|
||||
ScViewData& rViewData, ScRange& rRange)
|
||||
: weld::GenericDialogController(pParent, "modules/scalc/ui/duplicaterecordsdlg.ui",
|
||||
"DuplicateRecordsDialog")
|
||||
, m_xIncludesHeaders(m_xBuilder->weld_check_button("includesheaders"))
|
||||
, m_xRadioRow(m_xBuilder->weld_radio_button("row"))
|
||||
, m_xRadioColumn(m_xBuilder->weld_radio_button("column"))
|
||||
, m_xRadioSelect(m_xBuilder->weld_radio_button("select"))
|
||||
, m_xRadioRemove(m_xBuilder->weld_radio_button("remove"))
|
||||
, m_xCheckList(m_xBuilder->weld_tree_view("checklist"))
|
||||
, m_xAllChkBtn(m_xBuilder->weld_check_button("allcheckbtn"))
|
||||
, m_xOkBtn(m_xBuilder->weld_button("okaybtn"))
|
||||
, m_xHelpBtn(m_xBuilder->weld_button("helpbutton"))
|
||||
, mrCellData(rData)
|
||||
, mrRange(rRange)
|
||||
, mrViewData(rViewData)
|
||||
{
|
||||
m_xCheckList->enable_toggle_buttons(weld::ColumnToggleType::Check);
|
||||
m_xCheckList->connect_toggled(LINK(this, ScDuplicateRecordsDlg, RecordsChkHdl));
|
||||
Init();
|
||||
}
|
||||
|
||||
ScDuplicateRecordsDlg::~ScDuplicateRecordsDlg()
|
||||
{
|
||||
auto pChange(comphelper::ConfigurationChanges::create());
|
||||
officecfg::Office::Calc::Misc::HandleDuplicateRecords::RemoveDuplicateRows::set(
|
||||
m_xRadioRow->get_active(), pChange);
|
||||
pChange->commit();
|
||||
|
||||
officecfg::Office::Calc::Misc::HandleDuplicateRecords::DataIncludesHeaders::set(
|
||||
m_xIncludesHeaders->get_active(), pChange);
|
||||
pChange->commit();
|
||||
|
||||
officecfg::Office::Calc::Misc::HandleDuplicateRecords::RemoveRecords::set(
|
||||
m_xRadioRemove->get_active(), pChange);
|
||||
pChange->commit();
|
||||
}
|
||||
|
||||
void ScDuplicateRecordsDlg::SetDialogData(bool bToggle)
|
||||
{
|
||||
m_xCheckList->freeze();
|
||||
m_xCheckList->clear();
|
||||
|
||||
if (m_xRadioRow->get_active())
|
||||
{
|
||||
if (m_xIncludesHeaders->get_active())
|
||||
{
|
||||
// insert the first row's contents
|
||||
ScRefCellValue aCell;
|
||||
for (SCCOL i = mrRange.aStart.Col(); i <= mrRange.aEnd.Col(); ++i)
|
||||
{
|
||||
aCell.assign(mrViewData.GetDocument(),
|
||||
ScAddress{ i, mrRange.aStart.Row(), mrRange.aStart.Tab() });
|
||||
InsertEntry(aCell.getString(&mrViewData.GetDocument()), bToggle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = mrRange.aStart.Col(); i <= mrRange.aEnd.Col(); ++i)
|
||||
{
|
||||
OUString aStr(ScAddress(i, 0, mrViewData.GetTabNo())
|
||||
.Format(ScRefFlags::COL_VALID, &mrViewData.GetDocument()));
|
||||
InsertEntry(aStr, bToggle);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// insert row names
|
||||
if (m_xIncludesHeaders->get_active())
|
||||
{
|
||||
ScRefCellValue aCell;
|
||||
for (SCROW i = mrRange.aStart.Row(); i <= mrRange.aEnd.Row(); ++i)
|
||||
{
|
||||
aCell.assign(mrViewData.GetDocument(),
|
||||
ScAddress{ mrRange.aStart.Col(), i, mrRange.aStart.Tab() });
|
||||
InsertEntry(aCell.getString(&mrViewData.GetDocument()), bToggle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = mrRange.aStart.Row() + 1; i <= mrRange.aEnd.Row() + 1; ++i)
|
||||
{
|
||||
std::string aStr = std::to_string(i);
|
||||
InsertEntry(rtl::OUString::fromUtf8(aStr), bToggle);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_xCheckList->thaw();
|
||||
}
|
||||
|
||||
void ScDuplicateRecordsDlg::InsertEntry(const OUString& rTxt, bool bToggle)
|
||||
{
|
||||
m_xCheckList->append();
|
||||
const int nRow = m_xCheckList->n_children() - 1;
|
||||
m_xCheckList->set_toggle(nRow, bToggle ? TRISTATE_TRUE : TRISTATE_FALSE);
|
||||
m_xCheckList->set_text(nRow, rTxt, 0);
|
||||
m_xCheckList->set_sensitive(m_xAllChkBtn->get_state() != TRISTATE_TRUE);
|
||||
}
|
||||
|
||||
void ScDuplicateRecordsDlg::Init()
|
||||
{
|
||||
m_xIncludesHeaders->connect_toggled(LINK(this, ScDuplicateRecordsDlg, HeaderCkbHdl));
|
||||
m_xRadioRow->connect_toggled(LINK(this, ScDuplicateRecordsDlg, OrientationHdl));
|
||||
// m_xRadioColumn->connect_toggled(LINK(this, ScDuplicateRecordsDlg, OrientationHdl));
|
||||
m_xOkBtn->connect_clicked(LINK(this, ScDuplicateRecordsDlg, OkHdl));
|
||||
m_xAllChkBtn->connect_toggled(LINK(this, ScDuplicateRecordsDlg, AllCheckBtnHdl));
|
||||
|
||||
// defaults (find duplicate rows | data doesn't include headers)
|
||||
m_xRadioRow->set_active(
|
||||
officecfg::Office::Calc::Misc::HandleDuplicateRecords::RemoveDuplicateRows::get());
|
||||
m_xRadioColumn->set_active(
|
||||
!officecfg::Office::Calc::Misc::HandleDuplicateRecords::RemoveDuplicateRows::get());
|
||||
m_xIncludesHeaders->set_active(
|
||||
officecfg::Office::Calc::Misc::HandleDuplicateRecords::DataIncludesHeaders::get());
|
||||
m_xRadioRemove->set_active(
|
||||
officecfg::Office::Calc::Misc::HandleDuplicateRecords::RemoveRecords::get());
|
||||
m_xRadioSelect->set_active(
|
||||
!officecfg::Office::Calc::Misc::HandleDuplicateRecords::RemoveRecords::get());
|
||||
|
||||
const OUString aHeaderLabel = m_xRadioRow->get_active()
|
||||
? ScResId(STR_DUPLICATERECORDS_DATACONATINSROWHEADERS)
|
||||
: ScResId(STR_DUPLICATERECORDS_DATACONATINSCOLUMNHEADERS);
|
||||
m_xIncludesHeaders->set_label(aHeaderLabel);
|
||||
|
||||
m_xAllChkBtn->set_state(TRISTATE_FALSE);
|
||||
SetDialogData(true);
|
||||
}
|
||||
|
||||
IMPL_LINK_NOARG(ScDuplicateRecordsDlg, OrientationHdl, weld::Toggleable&, void)
|
||||
{
|
||||
const OUString aHeaderLabel = m_xRadioRow->get_active()
|
||||
? ScResId(STR_DUPLICATERECORDS_DATACONATINSROWHEADERS)
|
||||
: ScResId(STR_DUPLICATERECORDS_DATACONATINSCOLUMNHEADERS);
|
||||
m_xIncludesHeaders->set_label(aHeaderLabel);
|
||||
SetDialogData(true);
|
||||
}
|
||||
|
||||
IMPL_LINK_NOARG(ScDuplicateRecordsDlg, HeaderCkbHdl, weld::Toggleable&, void)
|
||||
{
|
||||
SetDialogData(true);
|
||||
}
|
||||
|
||||
IMPL_LINK_NOARG(ScDuplicateRecordsDlg, RecordsChkHdl, const weld::TreeView::iter_col&, void)
|
||||
{
|
||||
int nRet = 0;
|
||||
int nTotalCount = 0;
|
||||
|
||||
m_xCheckList->all_foreach([this, &nRet, &nTotalCount](weld::TreeIter& rEntry) {
|
||||
++nTotalCount;
|
||||
if (m_xCheckList->get_toggle(rEntry) == TRISTATE_TRUE)
|
||||
++nRet;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (nRet == nTotalCount)
|
||||
m_xAllChkBtn->set_state(TRISTATE_TRUE);
|
||||
else
|
||||
m_xAllChkBtn->set_state(TRISTATE_FALSE);
|
||||
}
|
||||
|
||||
IMPL_LINK_NOARG(ScDuplicateRecordsDlg, AllCheckBtnHdl, weld::Toggleable&, void)
|
||||
{
|
||||
SetDialogData(true);
|
||||
}
|
||||
|
||||
IMPL_LINK_NOARG(ScDuplicateRecordsDlg, OkHdl, weld::Button&, void)
|
||||
{
|
||||
maResponse.bRemove = m_xRadioRemove->get_active();
|
||||
maResponse.bDuplicatRows = m_xRadioRow->get_active();
|
||||
maResponse.bIncludesHeaders = m_xIncludesHeaders->get_active();
|
||||
int nCount = (maResponse.bDuplicatRows ? mrCellData[0].size() : mrCellData.size());
|
||||
|
||||
for (int i = 0; i < nCount; ++i)
|
||||
{
|
||||
if (m_xCheckList->get_toggle(i))
|
||||
maResponse.vEntries.push_back(i);
|
||||
}
|
||||
|
||||
m_xDialog->response(RET_OK);
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
|
@ -45,6 +45,7 @@
|
|||
#include <reffact.hxx>
|
||||
#include <tabprotection.hxx>
|
||||
#include <protectiondlg.hxx>
|
||||
#include <duplicaterecordsdlg.hxx>
|
||||
#include <markdata.hxx>
|
||||
|
||||
#include <svl/ilstitem.hxx>
|
||||
|
@ -54,6 +55,8 @@
|
|||
#include <svx/svxdlg.hxx>
|
||||
#include <comphelper/lok.hxx>
|
||||
#include <comphelper/string.hxx>
|
||||
#include <com/sun/star/uno/Reference.h>
|
||||
#include <com/sun/star/sheet/XCellRangeData.hpp>
|
||||
#include <sfx2/lokhelper.hxx>
|
||||
#include <scabstdlg.hxx>
|
||||
#include <officecfg/Office/Calc.hxx>
|
||||
|
@ -809,6 +812,115 @@ void ScTabViewShell::Execute( SfxRequest& rReq )
|
|||
rReq.Done();
|
||||
}
|
||||
break;
|
||||
case FID_HANDLEDUPLICATERECORDS:
|
||||
{
|
||||
using namespace com::sun::star;
|
||||
table::CellRangeAddress aCellRange;
|
||||
uno::Reference<sheet::XSpreadsheet> xActiveSheet;
|
||||
DuplicatesResponse aResponse;
|
||||
bool bHasData = true;
|
||||
|
||||
if (pReqArgs)
|
||||
{
|
||||
const SfxPoolItem* pItem;
|
||||
|
||||
if (pReqArgs->HasItem(FID_HANDLEDUPLICATERECORDS, &pItem))
|
||||
aResponse.bRemove = static_cast<const SfxBoolItem*>(pItem)->GetValue();
|
||||
if (pReqArgs->HasItem(FN_PARAM_1, &pItem))
|
||||
aResponse.bIncludesHeaders = static_cast<const SfxBoolItem*>(pItem)->GetValue();
|
||||
if (pReqArgs->HasItem(FN_PARAM_2, &pItem))
|
||||
aResponse.bDuplicatRows = static_cast<const SfxBoolItem*>(pItem)->GetValue();
|
||||
if (pReqArgs->HasItem(FN_PARAM_3, &pItem))
|
||||
aCellRange.StartColumn = static_cast<const SfxInt32Item*>(pItem)->GetValue();
|
||||
if (pReqArgs->HasItem(FN_PARAM_4, &pItem))
|
||||
aCellRange.StartRow = static_cast<const SfxInt32Item*>(pItem)->GetValue();
|
||||
if (pReqArgs->HasItem(FN_PARAM_5, &pItem))
|
||||
aCellRange.EndColumn = static_cast<const SfxInt32Item*>(pItem)->GetValue();
|
||||
if (pReqArgs->HasItem(FN_PARAM_6, &pItem))
|
||||
aCellRange.EndRow = static_cast<const SfxInt32Item*>(pItem)->GetValue();
|
||||
if (pReqArgs->HasItem(FN_PARAM_7, &pItem))
|
||||
aCellRange.Sheet = static_cast<const SfxInt32Item*>(pItem)->GetValue();
|
||||
|
||||
// check for the tab range here
|
||||
if (aCellRange.StartColumn < 0 || aCellRange.StartRow < 0
|
||||
|| aCellRange.EndColumn < 0 || aCellRange.EndRow < 0
|
||||
|| aCellRange.StartRow > aCellRange.EndRow
|
||||
|| aCellRange.StartColumn > aCellRange.EndColumn || aCellRange.Sheet < 0
|
||||
|| aCellRange.Sheet >= GetViewData().GetDocument().GetTableCount())
|
||||
{
|
||||
rReq.Done();
|
||||
break;
|
||||
}
|
||||
xActiveSheet = GetViewData().GetViewShell()->GetRangeWithSheet(aCellRange,
|
||||
bHasData, true);
|
||||
if (!bHasData)
|
||||
{
|
||||
rReq.Done();
|
||||
break;
|
||||
}
|
||||
int nLenEntries
|
||||
= (aResponse.bDuplicatRows ? aCellRange.EndColumn - aCellRange.StartColumn
|
||||
: aCellRange.EndRow - aCellRange.StartRow);
|
||||
for (int i = 0; i <= nLenEntries; ++i)
|
||||
aResponse.vEntries.push_back(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
xActiveSheet = GetViewData().GetViewShell()->GetRangeWithSheet(aCellRange,
|
||||
bHasData, false);
|
||||
if (bHasData)
|
||||
{
|
||||
if (!GetViewData().GetMarkData().IsMarked())
|
||||
GetViewData().GetViewShell()->ExtendSingleSelection(aCellRange);
|
||||
|
||||
uno::Reference<frame::XModel> xModel(GetViewData().GetDocShell()->GetModel());
|
||||
uno::Reference<sheet::XSheetCellRange> xSheetRange(
|
||||
xActiveSheet->getCellRangeByPosition(
|
||||
aCellRange.StartColumn, aCellRange.StartRow, aCellRange.EndColumn,
|
||||
aCellRange.EndRow),
|
||||
uno::UNO_QUERY);
|
||||
|
||||
ScRange aRange(ScAddress(aCellRange.StartColumn, aCellRange.StartRow,
|
||||
GetViewData().GetTabNo()),
|
||||
ScAddress(aCellRange.EndColumn, aCellRange.EndRow,
|
||||
GetViewData().GetTabNo()));
|
||||
|
||||
uno::Reference<sheet::XCellRangeData> xCellRangeData(xSheetRange,
|
||||
uno::UNO_QUERY);
|
||||
uno::Sequence<uno::Sequence<uno::Any>> aDataArray
|
||||
= xCellRangeData->getDataArray();
|
||||
|
||||
ScDuplicateRecordsDlg aDlg(GetFrameWeld(), aDataArray, GetViewData(), aRange);
|
||||
|
||||
bHasData = aDlg.run();
|
||||
if (bHasData)
|
||||
aResponse = aDlg.GetDialogData();
|
||||
else
|
||||
{
|
||||
rReq.Done();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::unique_ptr<weld::MessageDialog> aDialog(
|
||||
Application::CreateMessageDialog(GetFrameWeld(),
|
||||
VclMessageType::Warning,
|
||||
VclButtonsType::Ok,
|
||||
ScResId(STR_DUPLICATERECORDSDLG_NODATAFOUND)));
|
||||
aDialog->set_title(ScResId(STR_DUPLICATERECORDSDLG_WARNING));
|
||||
aDialog->run();
|
||||
}
|
||||
}
|
||||
|
||||
if (bHasData)
|
||||
GetViewData().GetViewShell()->HandleDuplicateRecords(
|
||||
xActiveSheet, aCellRange, aResponse.bRemove, aResponse.bIncludesHeaders,
|
||||
aResponse.bDuplicatRows, aResponse.vEntries);
|
||||
|
||||
rReq.Done();
|
||||
}
|
||||
break;
|
||||
case FID_TOGGLECOLROWHIGHLIGHTING:
|
||||
{
|
||||
bool bNewVal = !officecfg::Office::Calc::Content::Display::ColumnRowHighlighting::get();
|
||||
|
|
|
@ -80,6 +80,9 @@
|
|||
|
||||
#include <com/sun/star/document/XDocumentProperties.hpp>
|
||||
#include <com/sun/star/configuration/theDefaultProvider.hpp>
|
||||
#include <com/sun/star/sheet/XCellRangeMovement.hpp>
|
||||
#include <com/sun/star/sheet/XCellRangeData.hpp>
|
||||
#include <com/sun/star/sheet/XCellRangeAddressable.hpp>
|
||||
#include <comphelper/processfactory.hxx>
|
||||
#include <sfx2/lokhelper.hxx>
|
||||
#include <comphelper/flagguard.hxx>
|
||||
|
@ -1775,6 +1778,242 @@ ScViewOptiChangesListener::ScViewOptiChangesListener(ScTabViewShell& rViewShell)
|
|||
m_xColorSchemeChangesNotifier->addChangesListener(this);
|
||||
}
|
||||
|
||||
static void lcl_RemoveCells(uno::Reference<sheet::XSpreadsheet>& rSheet, sal_uInt16 nSheet,
|
||||
sal_uInt32 nStartColumn, sal_uInt32 nStartRow, sal_uInt32 nEndColumn,
|
||||
sal_uInt32 nEndRow, bool bRows)
|
||||
{
|
||||
table::CellRangeAddress aCellRange(nSheet, nStartColumn, nStartRow, nEndColumn, nEndRow);
|
||||
uno::Reference<sheet::XCellRangeMovement> xCRM(rSheet, uno::UNO_QUERY);
|
||||
|
||||
if (xCRM.is())
|
||||
{
|
||||
if (bRows)
|
||||
xCRM->removeRange(aCellRange, sheet::CellDeleteMode_UP);
|
||||
else
|
||||
xCRM->removeRange(aCellRange, sheet::CellDeleteMode_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
/* For rows (bool bRows), I am passing reference to already existing sequence, and comparing the required
|
||||
* columns, whereas for columns, I am creating a sequence for each, with only the checked entries
|
||||
* in the dialog.
|
||||
*/
|
||||
static bool lcl_CheckInArray(std::vector<uno::Sequence<uno::Any>>& nUniqueRecords,
|
||||
const uno::Sequence<uno::Any>& nCurrentRecord,
|
||||
const std::vector<int>& rSelectedEntries, bool bRows)
|
||||
{
|
||||
for (size_t m = 0; m < nUniqueRecords.size(); ++m)
|
||||
{
|
||||
bool bIsDuplicate = true;
|
||||
for (size_t n = 0; n < rSelectedEntries.size(); ++n)
|
||||
{
|
||||
// when the first different element is found
|
||||
int nColumn = (bRows ? rSelectedEntries[n] : n);
|
||||
if (nUniqueRecords[m][nColumn] != (bRows ? nCurrentRecord[rSelectedEntries[n]] : nCurrentRecord[n]))
|
||||
{
|
||||
bIsDuplicate = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bIsDuplicate)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uno::Reference<css::sheet::XSpreadsheet> ScTabViewShell::GetRangeWithSheet(css::table::CellRangeAddress& rRangeData, bool& bHasData, bool bHasUnoArguments)
|
||||
{
|
||||
// get spreadsheet document model & controller
|
||||
uno::Reference<frame::XModel> xModel(GetViewData().GetDocShell()->GetModel());
|
||||
uno::Reference<frame::XController> xController(xModel->getCurrentController());
|
||||
|
||||
// spreadsheet's extension of com.sun.star.frame.Controller service
|
||||
uno::Reference<sheet::XSpreadsheetView> SpreadsheetDocument(xController, uno::UNO_QUERY);
|
||||
uno::Reference<sheet::XSpreadsheet> ActiveSheet = SpreadsheetDocument->getActiveSheet();
|
||||
|
||||
if (!bHasUnoArguments)
|
||||
{
|
||||
// get the selection supplier, extract selection in XSheetCellRange
|
||||
uno::Reference<view::XSelectionSupplier> xSelectionSupplier(SpreadsheetDocument, uno::UNO_QUERY);
|
||||
uno::Any Selection = xSelectionSupplier->getSelection();
|
||||
uno::Reference<sheet::XSheetCellRange> SelectedCellRange;
|
||||
Selection >>= SelectedCellRange;
|
||||
|
||||
// Get the Selected Range Address.
|
||||
uno::Reference<sheet::XCellRangeAddressable> xAddressable( SelectedCellRange, uno::UNO_QUERY);
|
||||
if (xAddressable.is())
|
||||
rRangeData = xAddressable->getRangeAddress();
|
||||
else
|
||||
{
|
||||
bHasData = false;
|
||||
return ActiveSheet;
|
||||
}
|
||||
}
|
||||
|
||||
SCCOL nStartColumn = rRangeData.StartColumn;
|
||||
SCCOL nEndColumn = rRangeData.EndColumn;
|
||||
SCROW nStartRow = rRangeData.StartRow;
|
||||
SCROW nEndRow = rRangeData.EndRow;
|
||||
|
||||
// shrink to inersection of data and selection. If no intersection ==> return
|
||||
bHasData = GetViewData().GetDocument().ShrinkToDataArea(rRangeData.Sheet, nStartColumn, nStartRow, nEndColumn, nEndRow);
|
||||
|
||||
rRangeData.StartColumn = nStartColumn;
|
||||
rRangeData.StartRow = nStartRow;
|
||||
rRangeData.EndColumn = nEndColumn;
|
||||
rRangeData.EndRow = nEndRow;
|
||||
|
||||
return ActiveSheet;
|
||||
}
|
||||
|
||||
void ScTabViewShell::ExtendSingleSelection(css::table::CellRangeAddress& rRangeData)
|
||||
{
|
||||
SCCOL aStartCol(rRangeData.StartColumn);
|
||||
SCCOL aEndCol(rRangeData.EndColumn);
|
||||
SCROW aStartRow(rRangeData.StartRow);
|
||||
SCROW aEndRow(rRangeData.EndRow);
|
||||
|
||||
GetViewData().GetDocument().GetDataArea(rRangeData.Sheet, aStartCol, aStartRow, aEndCol,
|
||||
aEndRow, true, false);
|
||||
MarkRange(ScRange(ScAddress(aStartCol, aStartRow, rRangeData.Sheet),
|
||||
ScAddress(aEndCol, aEndRow, rRangeData.Sheet)));
|
||||
|
||||
rRangeData.StartRow = aStartRow;
|
||||
rRangeData.StartColumn = aStartCol;
|
||||
rRangeData.EndRow = aEndRow;
|
||||
rRangeData.EndColumn = aEndCol;
|
||||
}
|
||||
|
||||
/* bool bRemove == false ==> highlight duplicate rows */
|
||||
void ScTabViewShell::HandleDuplicateRecords(css::uno::Reference<css::sheet::XSpreadsheet> ActiveSheet,
|
||||
const css::table::CellRangeAddress& aRange, bool bRemove,
|
||||
bool bIncludesHeaders, bool bDuplicateRows,
|
||||
const std::vector<int>& rSelectedEntries)
|
||||
{
|
||||
if (rSelectedEntries.size() == 0)
|
||||
{
|
||||
Unmark();
|
||||
return;
|
||||
}
|
||||
|
||||
uno::Reference<frame::XModel> xModel(GetViewData().GetDocShell()->GetModel());
|
||||
uno::Reference<sheet::XSheetCellRange> xSheetRange(
|
||||
ActiveSheet->getCellRangeByPosition(aRange.StartColumn, aRange.StartRow, aRange.EndColumn, aRange.EndRow),
|
||||
uno::UNO_QUERY);
|
||||
|
||||
|
||||
uno::Reference<sheet::XCellRangeData> xCellRangeData(xSheetRange, uno::UNO_QUERY);
|
||||
uno::Sequence<uno::Sequence<uno::Any>> aDataArray = xCellRangeData->getDataArray();
|
||||
|
||||
uno::Reference< document::XUndoManagerSupplier > xUndoManager( xModel, uno::UNO_QUERY );
|
||||
uno::Reference<document::XActionLockable> xLockable(xModel, uno::UNO_QUERY);
|
||||
|
||||
uno::Reference<sheet::XCalculatable> xCalculatable(xModel, uno::UNO_QUERY);
|
||||
bool bAutoCalc = xCalculatable->isAutomaticCalculationEnabled();
|
||||
|
||||
comphelper::ScopeGuard aUndoContextGaurd(
|
||||
[&xUndoManager, &xLockable, &xModel, &xCalculatable, &bAutoCalc, &bRemove] {
|
||||
xUndoManager->getUndoManager()->leaveUndoContext();
|
||||
if (bRemove)
|
||||
xCalculatable->enableAutomaticCalculation(bAutoCalc);
|
||||
xLockable->removeActionLock();
|
||||
if (xModel->hasControllersLocked())
|
||||
xModel->unlockControllers();
|
||||
});
|
||||
|
||||
xModel->lockControllers();
|
||||
xLockable->addActionLock();
|
||||
if (bRemove)
|
||||
xCalculatable->enableAutomaticCalculation(true);
|
||||
xUndoManager->getUndoManager()->enterUndoContext("HandleDuplicateRecords");
|
||||
|
||||
bool nModifier = false; // modifier key pressed?
|
||||
bool bNoDuplicatesForSelection = true;
|
||||
|
||||
if (bDuplicateRows)
|
||||
{
|
||||
std::vector<uno::Sequence<uno::Any>> aUnionArray;
|
||||
sal_uInt32 nRow = bIncludesHeaders ? 1 : 0;
|
||||
sal_uInt32 lRows = aDataArray.getLength();
|
||||
sal_uInt32 nDeleteCount = 0;
|
||||
|
||||
while (nRow < lRows)
|
||||
{
|
||||
if (lcl_CheckInArray(aUnionArray, aDataArray[nRow], rSelectedEntries, true))
|
||||
{
|
||||
if (bRemove)
|
||||
{
|
||||
lcl_RemoveCells(ActiveSheet, aRange.Sheet, aRange.StartColumn,
|
||||
aRange.StartRow + nRow - nDeleteCount, aRange.EndColumn,
|
||||
aRange.StartRow + nRow - nDeleteCount, true);
|
||||
++nDeleteCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int nCol = aRange.StartColumn; nCol <= aRange.EndColumn; ++nCol)
|
||||
{
|
||||
bNoDuplicatesForSelection = false;
|
||||
DoneBlockMode( nModifier );
|
||||
nModifier = true;
|
||||
InitBlockMode( nCol, aRange.StartRow + nRow, aRange.Sheet, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aUnionArray.push_back(aDataArray[nRow]);
|
||||
}
|
||||
++nRow;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<uno::Sequence<uno::Any>> aUnionArray;
|
||||
sal_uInt32 nDeleteCount = 0;
|
||||
sal_uInt32 nColumn = bIncludesHeaders ? 1 : 0;
|
||||
sal_uInt32 lColumns = aDataArray[0].getLength();
|
||||
|
||||
while (nColumn < lColumns)
|
||||
{
|
||||
uno::Sequence<uno::Any> aSeq;
|
||||
aSeq.realloc(rSelectedEntries.size());
|
||||
for (size_t i = 0; i < rSelectedEntries.size(); ++i)
|
||||
aSeq.getArray()[i] = aDataArray[rSelectedEntries[i]][nColumn];
|
||||
|
||||
if (lcl_CheckInArray(aUnionArray, aSeq, rSelectedEntries, false))
|
||||
{
|
||||
if (bRemove)
|
||||
{
|
||||
lcl_RemoveCells(ActiveSheet, aRange.Sheet,
|
||||
aRange.StartColumn + nColumn - nDeleteCount, aRange.StartRow,
|
||||
aRange.StartColumn + nColumn - nDeleteCount, aRange.EndRow, false);
|
||||
++nDeleteCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int nRow = aRange.StartRow; nRow <= aRange.EndRow; ++nRow)
|
||||
{
|
||||
bNoDuplicatesForSelection = false;
|
||||
DoneBlockMode( nModifier );
|
||||
nModifier = true;
|
||||
InitBlockMode( aRange.StartColumn + nColumn, nRow, aRange.Sheet, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aUnionArray.push_back(aSeq);
|
||||
}
|
||||
++nColumn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (bNoDuplicatesForSelection && !bRemove)
|
||||
Unmark();
|
||||
}
|
||||
|
||||
ScTabViewShell::ScTabViewShell( SfxViewFrame& rViewFrame,
|
||||
SfxViewShell* pOldSh ) :
|
||||
SfxViewShell(rViewFrame, SfxViewShellFlags::HAS_PRINTOPTIONS),
|
||||
|
|
|
@ -604,6 +604,7 @@
|
|||
<menu:menuitem menu:id=".uno:DataFilterHideAutoFilter"/>
|
||||
</menu:menupopup>
|
||||
</menu:menu>
|
||||
<menu:menuitem menu:id=".uno:HandleDuplicateRecords"/>
|
||||
<menu:menuseparator/>
|
||||
<menu:menuitem menu:id=".uno:DefineDBName"/>
|
||||
<menu:menuitem menu:id=".uno:SelectDB"/>
|
||||
|
|
339
sc/uiconfig/scalc/ui/duplicaterecordsdlg.ui
Normal file
339
sc/uiconfig/scalc/ui/duplicaterecordsdlg.ui
Normal file
|
@ -0,0 +1,339 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.40.0 -->
|
||||
<interface domain="sc">
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkTreeStore" id="liststore1">
|
||||
<columns>
|
||||
<!-- column-name check1 -->
|
||||
<column type="gboolean"/>
|
||||
<!-- column-name text -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name id -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name checkvis1 -->
|
||||
<column type="gboolean"/>
|
||||
<!-- column-name checktri1 -->
|
||||
<column type="gboolean"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkDialog" id="DuplicateRecordsDialog">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="border-width">6</property>
|
||||
<property name="title" translatable="yes" context="duplicaterecordsdialog|duplicaterecordsdialog">Handle Duplicate Records</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="type-hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="layout-style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="helpbutton">
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|helpbutton">_Help</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="use-underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
<property name="secondary">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="okaybtn">
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|okaybtn">_Okay</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="use-underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="cancelbtn">
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|cancelbtn">Ca_ncel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="use-underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<!-- n-columns=2 n-rows=5 -->
|
||||
<object class="GtkGrid" id="grid1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="row-spacing">6</property>
|
||||
<property name="column-spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="orientation">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|orientation">Orientation:</property>
|
||||
<property name="mnemonic-widget">row</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="header">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|header">Hea_der:</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="mnemonic-widget">includesheaders</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="action">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|action">Action:</property>
|
||||
<property name="mnemonic-widget">select</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="width-request">280</property>
|
||||
<property name="height-request">140</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="margin-top">2</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="checklist">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="hexpand">False</property>
|
||||
<property name="model">liststore1</property>
|
||||
<property name="headers-visible">False</property>
|
||||
<property name="headers-clickable">False</property>
|
||||
<property name="search-column">0</property>
|
||||
<property name="show-expanders">False</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="treeviewcolumn4">
|
||||
<property name="sizing">fixed</property>
|
||||
<property name="title" translatable="yes" context="duplicaterecordsdialog|treeviewcolumn4">All</property>
|
||||
<property name="clickable">True</property>
|
||||
<property name="alignment">0.5</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererToggle" id="cellrenderer5"/>
|
||||
<attributes>
|
||||
<attribute name="visible">3</attribute>
|
||||
<attribute name="active">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="treeviewcolumn5">
|
||||
<property name="resizable">True</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="title" translatable="yes" context="duplicaterecordsdialog|treeviewcolumn5">Row/Column</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="cellrenderer4"/>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="row">
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|row">By _Row</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="column">
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|column">By _Column</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
<property name="group">row</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="box2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="select">
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|select">_Select</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioButton" id="remove">
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|remove">R_emove</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="active">True</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
<property name="group">select</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="includesheaders">
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|includesheaders">Data contains row/col headers</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="items">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|items">Items:</property>
|
||||
<property name="mnemonic-widget">allcheckbtn</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="allcheckbtn">
|
||||
<property name="label" translatable="yes" context="duplicaterecordsdialog|allcheckbtn">_All</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">False</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="draw-indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">1</property>
|
||||
<property name="top-attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-11">helpbutton</action-widget>
|
||||
<action-widget response="-5">okaybtn</action-widget>
|
||||
<action-widget response="-6">cancelbtn</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
Loading…
Reference in a new issue