summaryrefslogtreecommitdiffstats
path: root/sfx2/source/control/listview.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sfx2/source/control/listview.cxx
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sfx2/source/control/listview.cxx')
-rw-r--r--sfx2/source/control/listview.cxx443
1 files changed, 443 insertions, 0 deletions
diff --git a/sfx2/source/control/listview.cxx b/sfx2/source/control/listview.cxx
new file mode 100644
index 000000000..a53e85d71
--- /dev/null
+++ b/sfx2/source/control/listview.cxx
@@ -0,0 +1,443 @@
+/* -*- 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/.
+ */
+
+#include <sfx2/listview.hxx>
+
+#include <sfx2/sfxresid.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/datetime.hxx>
+#include <sfx2/strings.hrc>
+#include <osl/file.hxx>
+#include <osl/time.h>
+#include <comphelper/fileurl.hxx>
+
+#include <svtools/svtresid.hxx>
+#include <svtools/strings.hrc>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/collatorwrapper.hxx>
+#include <unotools/syslocale.hxx>
+#include <unotools/intlwrapper.hxx>
+#include <tools/wintypes.hxx>
+
+#include <bitmaps.hlst>
+#include <rtl/math.hxx>
+
+#include <sfx2/templatelocalview.hxx>
+
+#define COLUMN_IMG_ISDEFAULT 0
+#define COLUMN_NAME 1
+#define COLUMN_CATEGORY 2
+#define COLUMN_APPLICATION 3
+#define COLUMN_MODIFIED 4
+#define COLUMN_SIZE 5
+#define NUMBER_OF_COLUMNS 6
+
+static sal_uInt64 getFileSize(const OUString& rURL);
+static sal_uInt32 getFileModifyTime(const OUString& rURL);
+static OUString getDisplayFileSize(const OUString& rURL);
+static OUString getDisplayFileModifyTime(const OUString& rURL);
+static OUString getApplication(std::u16string_view rURL);
+
+ListView::ListView(std::unique_ptr<weld::TreeView> xTreeView)
+ : mxTreeView(std::move(xTreeView))
+ , mnSortColumn(-2)
+{
+ auto nDigitWidth = mxTreeView->get_approximate_digit_width();
+ std::vector<int> aWidths{
+ static_cast<int>(nDigitWidth * 5), /* Icon Column */
+ static_cast<int>(nDigitWidth * 24), /* Name Column */
+ static_cast<int>(nDigitWidth * 22), /* Category Column */
+ static_cast<int>(nDigitWidth * 15), /* Application Column */
+ static_cast<int>(nDigitWidth * 18) /* Modify Column */
+ };
+
+ mxTreeView->set_column_fixed_widths(aWidths);
+ mxTreeView->set_selection_mode(SelectionMode::Multiple);
+ mxTreeView->connect_query_tooltip(LINK(this, ListView, QueryTooltipHdl));
+}
+ListView::~ListView() {}
+
+void ListView::AppendItem(const OUString& rId, const OUString& rTitle, const OUString& rSubtitle,
+ const OUString& rPath, bool bDefault)
+{
+ INetURLObject aUrl(rPath, INetProtocol::File);
+ OUString sPath = aUrl.getFSysPath(FSysStyle::Detect);
+
+ std::unique_ptr<ListViewItem> pItem(new ListViewItem);
+ pItem->maId = rId;
+ pItem->maTitle = rTitle;
+ pItem->maSubtitle = rSubtitle;
+ pItem->maApplication = getApplication(rPath);
+ pItem->maPath = rPath;
+ pItem->mbDefault = bDefault;
+ pItem->mnModify = getFileModifyTime(rPath);
+ pItem->mnSize = getFileSize(rPath);
+ pItem->maDisplayModify = getDisplayFileModifyTime(rPath);
+ pItem->maDisplaySize = getDisplayFileSize(rPath);
+ pItem->maDisplayPath = sPath;
+
+ OUString sImage("");
+ if (pItem->mbDefault)
+ sImage = BMP_DEFAULT;
+
+ AppendRow(sImage, pItem->maTitle, pItem->maSubtitle, pItem->maApplication,
+ pItem->maDisplayModify, pItem->maDisplaySize, pItem->maId);
+
+ mListViewItems.push_back(std::move(pItem));
+}
+
+void ListView::AppendRow(const OUString& rImage, const OUString& rTitle, const OUString& rSubtitle,
+ const OUString& rApplication, const OUString& rModify,
+ const OUString& rSize, const OUString& rId)
+{
+ std::unique_ptr<weld::TreeIter> xIter(mxTreeView->make_iterator());
+ mxTreeView->append(xIter.get());
+ mxTreeView->set_image(*xIter, rImage, COLUMN_IMG_ISDEFAULT);
+ mxTreeView->set_text(*xIter, rTitle, COLUMN_NAME);
+ mxTreeView->set_text(*xIter, rSubtitle, COLUMN_CATEGORY);
+ mxTreeView->set_text(*xIter, rApplication, COLUMN_APPLICATION);
+ mxTreeView->set_text(*xIter, rModify, COLUMN_MODIFIED);
+ mxTreeView->set_text(*xIter, rSize, COLUMN_SIZE);
+ mxTreeView->set_id(*xIter, rId);
+}
+
+void ListView::UpdateRow(int nIndex, const OUString& rImage, const OUString& rTitle,
+ const OUString& rSubtitle, const OUString& rApplication,
+ const OUString& rModify, const OUString& rSize, const OUString& rId)
+{
+ mxTreeView->set_image(nIndex, rImage, COLUMN_IMG_ISDEFAULT);
+ mxTreeView->set_text(nIndex, rTitle, COLUMN_NAME);
+ mxTreeView->set_text(nIndex, rSubtitle, COLUMN_CATEGORY);
+ mxTreeView->set_text(nIndex, rApplication, COLUMN_APPLICATION);
+ mxTreeView->set_text(nIndex, rModify, COLUMN_MODIFIED);
+ mxTreeView->set_text(nIndex, rSize, COLUMN_SIZE);
+ mxTreeView->set_id(nIndex, rId);
+}
+
+void ListView::ReloadRows()
+{
+ OUString sCursorId = get_id(get_cursor_index());
+ mxTreeView->clear();
+ for (const auto& pItem : mListViewItems)
+ {
+ OUString sImage("");
+ if (pItem->mbDefault)
+ sImage = BMP_DEFAULT;
+ AppendRow(sImage, pItem->maTitle, pItem->maSubtitle, pItem->maApplication,
+ pItem->maDisplayModify, pItem->maDisplaySize, pItem->maId);
+ }
+ unselect_all();
+ if (!sCursorId.isEmpty())
+ {
+ select_id(sCursorId);
+ set_cursor(get_selected_index());
+ }
+}
+
+bool ListView::UpdateRows()
+{
+ if (static_cast<int>(mListViewItems.size()) != mxTreeView->n_children())
+ return false;
+ OUString sCursorId = get_id(get_cursor_index());
+ int nIndex = 0;
+ for (const auto& pItem : mListViewItems)
+ {
+ OUString sImage("");
+ if (pItem->mbDefault)
+ sImage = BMP_DEFAULT;
+ UpdateRow(nIndex, sImage, pItem->maTitle, pItem->maSubtitle, pItem->maApplication,
+ pItem->maDisplayModify, pItem->maDisplaySize, pItem->maId);
+ ++nIndex;
+ }
+ unselect_all();
+ if (!sCursorId.isEmpty())
+ {
+ select_id(sCursorId);
+ set_cursor(get_selected_index());
+ }
+ return true;
+}
+
+IMPL_LINK(ListView, ColumnClickedHdl, const int, col, void)
+{
+ if (col <= 0 || col > NUMBER_OF_COLUMNS)
+ return;
+
+ if (mnSortColumn >= 0 && mnSortColumn != col)
+ mxTreeView->set_sort_indicator(TriState::TRISTATE_INDET, mnSortColumn);
+
+ mxTreeView->set_sort_indicator((mxTreeView->get_sort_indicator(col) == TriState::TRISTATE_TRUE
+ ? TriState::TRISTATE_FALSE
+ : TriState::TRISTATE_TRUE),
+ col);
+ sortColumn(col);
+}
+
+void ListView::sortColumn(const int col)
+{
+ if (col <= 0 || col > NUMBER_OF_COLUMNS)
+ return;
+
+ bool isAscending = mxTreeView->get_sort_indicator(col) != TriState::TRISTATE_FALSE;
+
+ auto comp = [&](std::unique_ptr<ListViewItem> const& pItemA,
+ std::unique_ptr<ListViewItem> const& pItemB) {
+ sal_Int32 res = 0;
+ IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag());
+ const CollatorWrapper* pCollatorWrapper = aIntlWrapper.getCollator();
+ switch (col)
+ {
+ case COLUMN_NAME:
+ {
+ OUString sNameA = pItemA->maTitle;
+ OUString sNameB = pItemB->maTitle;
+ res = pCollatorWrapper->compareString(sNameA, sNameB);
+ }
+ break;
+ case COLUMN_CATEGORY:
+ {
+ OUString sCategoryA = pItemA->maSubtitle;
+ OUString sCategoryB = pItemB->maSubtitle;
+ res = pCollatorWrapper->compareString(sCategoryA, sCategoryB);
+ }
+ break;
+ case COLUMN_MODIFIED:
+ {
+ sal_uInt32 nModA, nModB;
+ nModA = pItemA->mnModify;
+ nModB = pItemB->mnModify;
+
+ if (nModA < nModB)
+ res = -1;
+ else if (nModA > nModB)
+ res = 1;
+ }
+ break;
+ case COLUMN_SIZE:
+ {
+ sal_uInt64 nSizeA, nSizeB;
+ nSizeA = pItemA->mnSize;
+ nSizeB = pItemB->mnSize;
+
+ if (nSizeA < nSizeB)
+ res = -1;
+ else if (nSizeA > nSizeB)
+ res = 1;
+ }
+ break;
+ case COLUMN_APPLICATION:
+ {
+ OUString sPathA = pItemA->maApplication;
+ OUString sPathB = pItemB->maApplication;
+ res = pCollatorWrapper->compareString(sPathA, sPathB);
+ }
+ break;
+ }
+ return isAscending ? (res > 0) : (res < 0);
+ };
+ std::stable_sort(mListViewItems.begin(), mListViewItems.end(), comp);
+
+ if (!UpdateRows())
+ ReloadRows();
+ mnSortColumn = col;
+}
+
+void ListView::sort() { sortColumn(mnSortColumn); }
+
+void ListView::refreshDefaultColumn()
+{
+ for (const auto& pItem : mListViewItems)
+ {
+ bool bDefault = TemplateLocalView::IsDefaultTemplate(pItem->maPath);
+ if (pItem->mbDefault != bDefault)
+ {
+ pItem->mbDefault = bDefault;
+ OUString sImage("");
+ if (bDefault)
+ sImage = BMP_DEFAULT;
+ mxTreeView->set_image(mxTreeView->find_id(pItem->maId), sImage, COLUMN_IMG_ISDEFAULT);
+ }
+ }
+}
+
+void ListView::rename(const OUString& rId, const OUString& rTitle)
+{
+ mxTreeView->set_text(mxTreeView->find_id(rId), rTitle, COLUMN_NAME);
+ for (const auto& pItem : mListViewItems)
+ if (pItem->maId == rId)
+ {
+ pItem->maTitle = rTitle;
+ break;
+ }
+}
+
+void ListView::clearListView()
+{
+ mxTreeView->clear();
+ mListViewItems.clear();
+}
+
+IMPL_LINK(ListView, QueryTooltipHdl, const weld::TreeIter&, rIter, OUString)
+{
+ OUString sId = mxTreeView->get_id(rIter);
+ for (const auto& pItem : mListViewItems)
+ {
+ if (pItem->maId == sId)
+ return pItem->maDisplayPath;
+ }
+ return OUString();
+}
+
+sal_uInt16 ListView::get_nId(int pos) const
+{
+ return static_cast<sal_uInt16>(mxTreeView->get_id(pos).toInt32());
+}
+
+static sal_uInt32 getFileModifyTime(const OUString& rURL)
+{
+ sal_uInt32 nModify = 0;
+ if (!comphelper::isFileUrl(rURL))
+ return nModify;
+
+ osl::DirectoryItem aItem;
+ if (osl::DirectoryItem::get(rURL, aItem) != osl::DirectoryItem::E_None)
+ return nModify;
+
+ osl::FileStatus aStatus(osl_FileStatus_Mask_ModifyTime);
+ if (aItem.getFileStatus(aStatus) != osl::DirectoryItem::E_None)
+ return nModify;
+
+ TimeValue systemTimeValue = aStatus.getModifyTime();
+
+ nModify = systemTimeValue.Seconds;
+ return nModify;
+}
+static OUString getDisplayFileModifyTime(const OUString& rURL)
+{
+ if (!comphelper::isFileUrl(rURL))
+ return OUString();
+
+ osl::DirectoryItem aItem;
+ if (osl::DirectoryItem::get(rURL, aItem) != osl::DirectoryItem::E_None)
+ return OUString();
+
+ osl::FileStatus aStatus(osl_FileStatus_Mask_ModifyTime);
+ if (aItem.getFileStatus(aStatus) != osl::DirectoryItem::E_None)
+ return OUString();
+
+ TimeValue systemTimeValue = aStatus.getModifyTime();
+ if (systemTimeValue.Seconds == 0)
+ return OUString();
+ TimeValue localTimeValue;
+ osl_getLocalTimeFromSystemTime(&systemTimeValue, &localTimeValue);
+ const SvtSysLocale aSysLocale;
+ const LocaleDataWrapper& rLocaleWrapper = aSysLocale.GetLocaleData();
+ DateTime aDateTime = DateTime::CreateFromUnixTime(localTimeValue.Seconds);
+ OUString aDisplayDateTime
+ = rLocaleWrapper.getDate(aDateTime) + ", " + rLocaleWrapper.getTime(aDateTime, false);
+ return aDisplayDateTime;
+}
+
+static OUString getDisplayFileSize(const OUString& rURL)
+{
+ if (!comphelper::isFileUrl(rURL))
+ return OUString();
+
+ osl::DirectoryItem aItem;
+ if (osl::DirectoryItem::get(rURL, aItem) != osl::DirectoryItem::E_None)
+ return OUString();
+
+ osl::FileStatus aStatus(osl_FileStatus_Mask_FileSize);
+ if (aItem.getFileStatus(aStatus) != osl::DirectoryItem::E_None)
+ return OUString();
+
+ sal_uInt64 nSize = aStatus.getFileSize();
+ double fSize(static_cast<double>(nSize));
+ sal_uInt32 nDec;
+
+ sal_uInt64 nMega = 1024 * 1024;
+ sal_uInt64 nGiga = nMega * 1024;
+
+ OUString aUnitStr(' ');
+
+ if (nSize < 10000)
+ {
+ aUnitStr += SvtResId(STR_SVT_BYTES);
+ nDec = 0;
+ }
+ else if (nSize < nMega)
+ {
+ fSize /= 1024;
+ aUnitStr += SvtResId(STR_SVT_KB);
+ nDec = 1;
+ }
+ else if (nSize < nGiga)
+ {
+ fSize /= nMega;
+ aUnitStr += SvtResId(STR_SVT_MB);
+ nDec = 2;
+ }
+ else
+ {
+ fSize /= nGiga;
+ aUnitStr += SvtResId(STR_SVT_GB);
+ nDec = 3;
+ }
+
+ OUString aSizeStr(
+ ::rtl::math::doubleToUString(fSize, rtl_math_StringFormat_F, nDec,
+ SvtSysLocale().GetLocaleData().getNumDecimalSep()[0]));
+ aSizeStr += aUnitStr;
+
+ return aSizeStr;
+}
+
+static sal_uInt64 getFileSize(const OUString& rURL)
+{
+ sal_uInt64 nSize = 0;
+ if (!comphelper::isFileUrl(rURL))
+ return nSize;
+
+ osl::DirectoryItem aItem;
+ if (osl::DirectoryItem::get(rURL, aItem) != osl::DirectoryItem::E_None)
+ return nSize;
+
+ osl::FileStatus aStatus(osl_FileStatus_Mask_FileSize);
+ if (aItem.getFileStatus(aStatus) != osl::DirectoryItem::E_None)
+ return nSize;
+
+ nSize = aStatus.getFileSize();
+ return nSize;
+}
+
+static OUString getApplication(std::u16string_view rURL)
+{
+ INetURLObject aUrl(rURL);
+ OUString aExt = aUrl.getExtension();
+
+ if (aExt == "ott" || aExt == "stw" || aExt == "oth" || aExt == "dot" || aExt == "dotx")
+ {
+ return SfxResId(STR_DOCUMENT);
+ }
+ else if (aExt == "ots" || aExt == "stc" || aExt == "xlt" || aExt == "xltm" || aExt == "xltx")
+ {
+ return SfxResId(STR_SPREADSHEET);
+ }
+ else if (aExt == "otp" || aExt == "sti" || aExt == "pot" || aExt == "potm" || aExt == "potx")
+ {
+ return SfxResId(STR_PRESENTATION);
+ }
+ else if (aExt == "otg" || aExt == "std")
+ {
+ return SfxResId(STR_DRAWING);
+ }
+ return OUString();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */