/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * 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 #include #include #include #include // role used for the ID in the QStandardItem constexpr int ROLE_ID = Qt::UserRole + 1000; // Property used to store the supported roles for each of the columns const char* const PROPERTY_COLUMN_ROLES = "column-roles"; QtInstanceTreeView::QtInstanceTreeView(QTreeView* pTreeView) : QtInstanceWidget(pTreeView) , m_pTreeView(pTreeView) { assert(m_pTreeView); m_pModel = qobject_cast(m_pTreeView->model()); assert(m_pModel && "tree view doesn't have expected QSortFilterProxyModel set"); m_pSourceModel = qobject_cast(m_pModel->sourceModel()); assert(m_pSourceModel && "proxy model doesn't have expected source model"); m_pSelectionModel = m_pTreeView->selectionModel(); assert(m_pSelectionModel); m_pColumnRoles = columnRoles(*pTreeView); assert(m_pColumnRoles.size() == m_pModel->columnCount() && "column count doesn't match"); connect(m_pTreeView, &QTreeView::activated, this, &QtInstanceTreeView::handleActivated); connect(m_pSelectionModel, &QItemSelectionModel::selectionChanged, this, &QtInstanceTreeView::handleSelectionChanged); connect(m_pModel, &QSortFilterProxyModel::dataChanged, this, &QtInstanceTreeView::handleDataChanged); assert(m_pTreeView->viewport()); m_pTreeView->viewport()->installEventFilter(this); } void QtInstanceTreeView::do_insert(const weld::TreeIter* pParent, int nPos, const OUString* pStr, const OUString* pId, const OUString* pIconName, VirtualDevice* pImageSurface, bool bChildrenOnDemand, weld::TreeIter* pRet) { assert(!bChildrenOnDemand && "Not implemented yet"); // avoid -Werror=unused-parameter for release build (void)bChildrenOnDemand; SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { const QModelIndex aParentIndex = pParent ? static_cast(pParent)->modelIndex() : QModelIndex(); if (nPos == -1) nPos = m_pModel->rowCount(aParentIndex); m_pModel->insertRow(nPos, aParentIndex); // ensure parent has same column count as top-level if (aParentIndex.isValid() && m_pModel->columnCount(aParentIndex) == 0) m_pModel->insertColumns(0, m_pModel->columnCount(), aParentIndex); const QModelIndex aIndex = modelIndex(nPos, 0, aParentIndex); QStandardItem* pItem = itemFromIndex(aIndex); if (pStr) set_text(treeIter(nPos, aParentIndex), *pStr); if (pId) pItem->setData(toQString(*pId), ROLE_ID); if (pIconName && !pIconName->isEmpty()) pItem->setIcon(loadQPixmapIcon(*pIconName)); else if (pImageSurface) pItem->setIcon(toQPixmap(*pImageSurface)); if (m_bExtraToggleButtonsEnabled) { // avoid triggering signal_toggled via QtInstanceTreeView::handleDataChanged for new item QSignalBlocker aSignalBlocker(m_pModel); itemFromIndex(toggleButtonModelIndex(QtInstanceTreeIter(aIndex)))->setCheckable(true); } if (pRet) static_cast(pRet)->setModelIndex(aIndex); }); } void QtInstanceTreeView::do_insert_separator(int, const OUString&) { assert(false && "Not implemented yet"); } OUString QtInstanceTreeView::get_selected_text() const { SolarMutexGuard g; OUString sText; GetQtInstance().RunInMainThread([&] { const QModelIndexList aSelectedIndexes = m_pSelectionModel->selectedIndexes(); if (aSelectedIndexes.empty()) return; sText = toOUString(itemFromIndex(aSelectedIndexes.first())->text()); }); return sText; } OUString QtInstanceTreeView::get_selected_id() const { SolarMutexGuard g; OUString sId; GetQtInstance().RunInMainThread([&] { const QModelIndexList aSelectedIndexes = m_pSelectionModel->selectedIndexes(); if (aSelectedIndexes.empty()) return; QVariant aIdData = aSelectedIndexes.first().data(ROLE_ID); if (aIdData.canConvert()) sId = toOUString(aIdData.toString()); }); return sId; } void QtInstanceTreeView::enable_toggle_buttons(weld::ColumnToggleType) { assert(m_pModel->rowCount() == 0 && "Must be called before inserting any data"); m_bExtraToggleButtonsEnabled = true; m_pTreeView->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); } void QtInstanceTreeView::set_clicks_to_toggle(int) { assert(false && "Not implemented yet"); } int QtInstanceTreeView::get_selected_index() const { SolarMutexGuard g; int nIndex = -1; GetQtInstance().RunInMainThread([&] { const QModelIndexList aSelectedIndexes = m_pSelectionModel->selectedIndexes(); if (aSelectedIndexes.empty()) return; nIndex = aSelectedIndexes.first().row(); }); return nIndex; } void QtInstanceTreeView::do_select(int nPos) { do_select(treeIter(nPos)); } void QtInstanceTreeView::do_unselect(int nPos) { do_unselect(treeIter(nPos)); } void QtInstanceTreeView::do_remove(int nPos) { do_remove(treeIter(nPos)); } OUString QtInstanceTreeView::get_text(int nRow, int nCol) const { return get_text(treeIter(nRow), nCol); } void QtInstanceTreeView::set_text(int nRow, const OUString& rText, int nCol) { set_text(treeIter(nRow), rText, nCol); } void QtInstanceTreeView::set_sensitive(int nRow, bool bSensitive, int nCol) { set_sensitive(treeIter(nRow), bSensitive, nCol); } bool QtInstanceTreeView::get_sensitive(int nRow, int nCol) const { return get_sensitive(treeIter(nRow), nCol); } void QtInstanceTreeView::set_id(int nRow, const OUString& rId) { set_id(treeIter(nRow), rId); } void QtInstanceTreeView::set_toggle(int nRow, TriState eState, int nCol) { set_toggle(treeIter(nRow), eState, nCol); } TriState QtInstanceTreeView::get_toggle(int nRow, int nCol) const { return get_toggle(treeIter(nRow), nCol); } void QtInstanceTreeView::set_image(int nRow, const OUString& rImage, int nCol) { set_image(treeIter(nRow), rImage, nCol); } void QtInstanceTreeView::set_image(int nRow, VirtualDevice& rImage, int nCol) { set_image(treeIter(nRow), rImage, nCol); } void QtInstanceTreeView::set_image(int nRow, const css::uno::Reference& rImage, int nCol) { set_image(treeIter(nRow), rImage, nCol); } void QtInstanceTreeView::set_text_emphasis(int nRow, bool bOn, int nCol) { return set_text_emphasis(treeIter(nRow), bOn, nCol); } bool QtInstanceTreeView::get_text_emphasis(int nRow, int nCol) const { return get_text_emphasis(treeIter(nRow), nCol); } void QtInstanceTreeView::set_text_align(int nRow, double fAlign, int nCol) { return set_text_align(treeIter(nRow), fAlign, nCol); } void QtInstanceTreeView::swap(int nPos1, int nPos2) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { const bool bPos1Selected = m_pSelectionModel->isRowSelected(nPos1); const bool bPos2Selected = m_pSelectionModel->isRowSelected(nPos2); const int nSourceModelPos1 = m_pModel->mapToSource(modelIndex(nPos1)).row(); const int nSourceModelPos2 = m_pModel->mapToSource(modelIndex(nPos2)).row(); const int nMin = std::min(nSourceModelPos1, nSourceModelPos2); const int nMax = std::max(nSourceModelPos1, nSourceModelPos2); QList aMaxRow = m_pSourceModel->takeRow(nMax); QList aMinRow = m_pSourceModel->takeRow(nMin); m_pSourceModel->insertRow(nMin, aMaxRow); m_pSourceModel->insertRow(nMax, aMinRow); // restore selection if (bPos1Selected) select(m_pModel->mapFromSource(m_pSourceModel->index(nSourceModelPos2, 0)).row()); if (bPos2Selected) select(m_pModel->mapFromSource(m_pSourceModel->index(nSourceModelPos1, 0)).row()); }); } std::vector QtInstanceTreeView::get_selected_rows() const { SolarMutexGuard g; std::vector aSelectedRows; GetQtInstance().RunInMainThread([&] { const QModelIndexList aSelectionIndexes = m_pSelectionModel->selectedRows(); for (const QModelIndex& aIndex : aSelectionIndexes) aSelectedRows.push_back(aIndex.row()); }); return aSelectedRows; } void QtInstanceTreeView::set_font_color(int nPos, const Color& rColor) { set_font_color(treeIter(nPos), rColor); } void QtInstanceTreeView::do_scroll_to_row(int nRow) { scroll_to_row(treeIter(nRow)); } bool QtInstanceTreeView::is_selected(int nPos) const { return is_selected(treeIter(nPos)); } int QtInstanceTreeView::get_cursor_index() const { SolarMutexGuard g; int nIndex = -1; GetQtInstance().RunInMainThread([&] { const QModelIndex aCurrentIndex = m_pSelectionModel->currentIndex(); if (aCurrentIndex.isValid()) nIndex = aCurrentIndex.row(); }); return nIndex; } void QtInstanceTreeView::do_set_cursor(int nPos) { do_set_cursor(treeIter(nPos)); } int QtInstanceTreeView::find_text(const OUString& rText) const { SolarMutexGuard g; int nIndex = -1; GetQtInstance().RunInMainThread([&] { // search in underlying QStandardItemModel and map index const QList aItems = m_pSourceModel->findItems(toQString(rText)); if (!aItems.empty()) nIndex = m_pModel->mapFromSource(aItems.at(0)->index()).row(); }); return nIndex; } OUString QtInstanceTreeView::get_id(int nPos) const { return get_id(treeIter(nPos)); } int QtInstanceTreeView::find_id(const OUString& rId) const { SolarMutexGuard g; int nIndex = -1; GetQtInstance().RunInMainThread([&] { for (int i = 0; i < m_pModel->rowCount(); i++) { if (get_id(i) == rId) { nIndex = i; return; } } }); return nIndex; } std::unique_ptr QtInstanceTreeView::make_iterator(const weld::TreeIter* pOrig) const { const QModelIndex aIndex = pOrig ? modelIndex(*pOrig) : QModelIndex(); return std::make_unique(aIndex); } void QtInstanceTreeView::copy_iterator(const weld::TreeIter& rSource, weld::TreeIter& rDest) const { const QModelIndex aModelIndex = static_cast(rSource).modelIndex(); static_cast(rDest).setModelIndex(aModelIndex); } bool QtInstanceTreeView::get_selected(weld::TreeIter* pIter) const { SolarMutexGuard g; bool bHasSelection = false; GetQtInstance().RunInMainThread([&] { const QModelIndexList aSelectedIndexes = m_pSelectionModel->selectedIndexes(); if (aSelectedIndexes.empty()) return; bHasSelection = true; if (pIter) static_cast(pIter)->setModelIndex(aSelectedIndexes.first()); }); return bHasSelection; } bool QtInstanceTreeView::get_cursor(weld::TreeIter* pIter) const { SolarMutexGuard g; bool bRet = false; GetQtInstance().RunInMainThread([&] { const QModelIndex aCurrentIndex = m_pTreeView->currentIndex(); QtInstanceTreeIter* pQtIter = static_cast(pIter); if (pQtIter) pQtIter->setModelIndex(aCurrentIndex); bRet = aCurrentIndex.isValid(); }); return bRet; } void QtInstanceTreeView::do_set_cursor(const weld::TreeIter& rIter) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { m_pTreeView->setCurrentIndex(modelIndex(rIter)); }); } bool QtInstanceTreeView::get_iter_first(weld::TreeIter& rIter) const { QtInstanceTreeIter& rQtIter = static_cast(rIter); const QModelIndex aIndex = modelIndex(0); rQtIter.setModelIndex(aIndex); return aIndex.isValid(); } bool QtInstanceTreeView::iter_next_sibling(weld::TreeIter& rIter) const { QtInstanceTreeIter& rQtIter = static_cast(rIter); const QModelIndex aIndex = rQtIter.modelIndex(); const QModelIndex aSiblingIndex = m_pModel->sibling(aIndex.row() + 1, 0, aIndex); rQtIter.setModelIndex(aSiblingIndex); return aSiblingIndex.isValid(); } bool QtInstanceTreeView::iter_previous_sibling(weld::TreeIter& rIter) const { QtInstanceTreeIter& rQtIter = static_cast(rIter); const QModelIndex aIndex = rQtIter.modelIndex(); const QModelIndex aSiblingIndex = m_pModel->sibling(aIndex.row() - 1, 0, aIndex); rQtIter.setModelIndex(aSiblingIndex); return aSiblingIndex.isValid(); } bool QtInstanceTreeView::iter_next(weld::TreeIter& rIter) const { QtInstanceTreeIter& rQtIter = static_cast(rIter); QModelIndex aIndex = rQtIter.modelIndex(); if (m_pModel->hasChildren(aIndex)) { rQtIter.setModelIndex(modelIndex(0, 0, aIndex)); return true; } while (aIndex.isValid()) { const QModelIndex aSiblingIndex = m_pModel->sibling(aIndex.row() + 1, 0, aIndex); if (aSiblingIndex.isValid()) { rQtIter.setModelIndex(aSiblingIndex); return true; } aIndex = aIndex.parent(); } return false; } bool QtInstanceTreeView::iter_previous(weld::TreeIter&) const { assert(false && "Not implemented yet"); return false; } bool QtInstanceTreeView::iter_children(weld::TreeIter& rIter) const { QtInstanceTreeIter& rQtIter = static_cast(rIter); const QModelIndex aChildIndex = m_pModel->index(0, 0, rQtIter.modelIndex()); rQtIter.setModelIndex(aChildIndex); return aChildIndex.isValid(); } bool QtInstanceTreeView::iter_parent(weld::TreeIter& rIter) const { QtInstanceTreeIter& rQtIter = static_cast(rIter); const QModelIndex aParentIndex = rQtIter.modelIndex().parent(); rQtIter.setModelIndex(aParentIndex); return aParentIndex.isValid(); } int QtInstanceTreeView::get_iter_depth(const weld::TreeIter& rIter) const { const QtInstanceTreeIter& rQtIter = static_cast(rIter); int nDepth = 0; QModelIndex aParentIndex = rQtIter.modelIndex().parent(); while (aParentIndex.isValid()) { nDepth++; aParentIndex = aParentIndex.parent(); } return nDepth; } int QtInstanceTreeView::get_iter_index_in_parent(const weld::TreeIter& rIter) const { SolarMutexGuard g; int nIndex; GetQtInstance().RunInMainThread([&] { const QModelIndex aIndex = modelIndex(rIter); nIndex = aIndex.row(); }); return nIndex; } int QtInstanceTreeView::iter_compare(const weld::TreeIter&, const weld::TreeIter&) const { assert(false && "Not implemented yet"); return 0; } bool QtInstanceTreeView::iter_has_child(const weld::TreeIter& rIter) const { const QtInstanceTreeIter& rQtIter = static_cast(rIter); return m_pModel->hasChildren(rQtIter.modelIndex()); } int QtInstanceTreeView::iter_n_children(const weld::TreeIter& rIter) const { const QtInstanceTreeIter& rQtIter = static_cast(rIter); return m_pModel->rowCount(rQtIter.modelIndex()); } void QtInstanceTreeView::do_remove(const weld::TreeIter& rIter) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { const QModelIndex aIndex = modelIndex(rIter); m_pModel->removeRow(aIndex.row(), aIndex.parent()); }); } void QtInstanceTreeView::do_select(const weld::TreeIter& rIter) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { QItemSelectionModel::SelectionFlags eFlags = QItemSelectionModel::Select | QItemSelectionModel::Rows; if (m_pTreeView->selectionMode() == QAbstractItemView::SingleSelection) eFlags |= QItemSelectionModel::Clear; m_pSelectionModel->select(modelIndex(rIter), eFlags); }); } void QtInstanceTreeView::do_unselect(const weld::TreeIter& rIter) { SolarMutexGuard g; GetQtInstance().RunInMainThread( [&] { m_pSelectionModel->select(modelIndex(rIter), QItemSelectionModel::Deselect); }); } void QtInstanceTreeView::set_extra_row_indent(const weld::TreeIter&, int) { assert(false && "Not implemented yet"); } void QtInstanceTreeView::set_text(const weld::TreeIter& rIter, const OUString& rStr, int nCol) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { const QModelIndex aIndex = nCol == -1 ? firstTextColumnModelIndex(rIter) : modelIndex(rIter, nCol); m_pModel->setData(aIndex, toQString(rStr)); }); } void QtInstanceTreeView::set_sensitive(const weld::TreeIter& rIter, bool bSensitive, int nCol) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { // column index -1 means "all columns" if (nCol == -1) { for (int i = 0; i < m_pModel->columnCount(); ++i) set_sensitive(rIter, bSensitive, i); return; } QStandardItem* pItem = itemFromIndex(modelIndex(rIter, nCol)); if (pItem) { if (bSensitive) pItem->setFlags(pItem->flags() | Qt::ItemIsEnabled); else pItem->setFlags(pItem->flags() & ~Qt::ItemIsEnabled); } }); } bool QtInstanceTreeView::get_sensitive(const weld::TreeIter& rIter, int nCol) const { SolarMutexGuard g; bool bSensitive = false; GetQtInstance().RunInMainThread([&] { QStandardItem* pItem = itemFromIndex(modelIndex(rIter, nCol)); if (pItem) bSensitive = pItem->flags() & Qt::ItemIsEnabled; }); return bSensitive; } void QtInstanceTreeView::set_text_emphasis(const weld::TreeIter&, bool, int) { assert(false && "Not implemented yet"); } bool QtInstanceTreeView::get_text_emphasis(const weld::TreeIter&, int) const { assert(false && "Not implemented yet"); return false; } void QtInstanceTreeView::set_text_align(const weld::TreeIter&, double, int) { assert(false && "Not implemented yet"); } void QtInstanceTreeView::set_toggle(const weld::TreeIter& rIter, TriState eState, int nCol) { SolarMutexGuard g; assert((nCol != 0 || !m_bExtraToggleButtonsEnabled) && "Column 0 is already used by \"expander toggle\" using special index -1"); GetQtInstance().RunInMainThread([&] { QModelIndex aIndex = nCol == -1 ? toggleButtonModelIndex(rIter) : modelIndex(rIter, nCol); itemFromIndex(aIndex)->setCheckState(toQtCheckState(eState)); }); } TriState QtInstanceTreeView::get_toggle(const weld::TreeIter& rIter, int nCol) const { SolarMutexGuard g; assert((nCol != 0 || !m_bExtraToggleButtonsEnabled) && "Column 0 is already used by \"expander toggle\" using special index -1"); TriState eState = TRISTATE_INDET; GetQtInstance().RunInMainThread([&] { QModelIndex aIndex = nCol == -1 ? toggleButtonModelIndex(rIter) : modelIndex(rIter, nCol); eState = toVclTriState(itemFromIndex(aIndex)->checkState()); }); return eState; } OUString QtInstanceTreeView::get_text(const weld::TreeIter& rIter, int nCol) const { SolarMutexGuard g; OUString sText; GetQtInstance().RunInMainThread([&] { const QModelIndex aIndex = nCol == -1 ? firstTextColumnModelIndex(rIter) : modelIndex(rIter, nCol); const QVariant aData = m_pModel->data(aIndex); if (aData.canConvert()) sText = toOUString(aData.toString()); }); return sText; } void QtInstanceTreeView::set_id(const weld::TreeIter& rIter, const OUString& rId) { SolarMutexGuard g; GetQtInstance().RunInMainThread( [&] { m_pModel->setData(modelIndex(rIter), toQString(rId), ROLE_ID); }); } OUString QtInstanceTreeView::get_id(const weld::TreeIter& rIter) const { SolarMutexGuard g; OUString sId; GetQtInstance().RunInMainThread([&] { QVariant aRoleData = m_pModel->data(modelIndex(rIter), ROLE_ID); if (aRoleData.canConvert()) sId = toOUString(aRoleData.toString()); }); return sId; } void QtInstanceTreeView::set_image(const weld::TreeIter& rIter, const OUString& rImage, int nCol) { if (rImage.isEmpty()) return; setImage(rIter, loadQPixmapIcon(rImage), nCol); } void QtInstanceTreeView::set_image(const weld::TreeIter& rIter, VirtualDevice& rImage, int nCol) { setImage(rIter, toQPixmap(rImage), nCol); } void QtInstanceTreeView::set_image(const weld::TreeIter& rIter, const css::uno::Reference& rImage, int nCol) { setImage(rIter, toQPixmap(rImage), nCol); } void QtInstanceTreeView::set_font_color(const weld::TreeIter& rIter, const Color& rColor) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { for (int nCol = 0; nCol < m_pModel->columnCount(); nCol++) { QModelIndex aIndex = modelIndex(rIter, nCol); m_pModel->setData(aIndex, QBrush(toQColor(rColor)), Qt::ForegroundRole); } }); } void QtInstanceTreeView::do_scroll_to_row(const weld::TreeIter& rIter) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { m_pTreeView->scrollTo(modelIndex(rIter)); }); } bool QtInstanceTreeView::is_selected(const weld::TreeIter& rIter) const { SolarMutexGuard g; bool bSelected = false; GetQtInstance().RunInMainThread( [&] { bSelected = m_pSelectionModel->isSelected(modelIndex(rIter)); }); return bSelected; } void QtInstanceTreeView::move_subtree(weld::TreeIter&, const weld::TreeIter*, int) { assert(false && "Not implemented yet"); } void QtInstanceTreeView::all_foreach(const std::function& func) { QtInstanceTreeIter aIter({}); if (get_iter_first(aIter)) { do { if (func(aIter)) return; } while (iter_next(aIter)); } } void QtInstanceTreeView::selected_foreach(const std::function& func) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { QModelIndexList aSelectionIndexes = m_pSelectionModel->selectedRows(); for (QModelIndex& aIndex : aSelectionIndexes) { QtInstanceTreeIter aIter(aIndex); if (func(aIter)) return; } }); } void QtInstanceTreeView::visible_foreach(const std::function&) { assert(false && "Not implemented yet"); } void QtInstanceTreeView::bulk_insert_for_each( int nSourceCount, const std::function& func, const weld::TreeIter* pParent, const std::vector* pFixedWidths, bool) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { // clear existing children const QModelIndex aParentIndex = pParent ? modelIndex(*pParent) : QModelIndex(); const int nRows = m_pModel->rowCount(aParentIndex); if (nRows > 0) m_pModel->removeRows(0, nRows, aParentIndex); // insert new rows m_pModel->insertRows(0, nSourceCount, aParentIndex); // call function for each row for (int nRow = 0; nRow < nSourceCount; nRow++) { QtInstanceTreeIter aIter = treeIter(nRow, aParentIndex); func(aIter, nRow); } // set column widths if (pFixedWidths) set_column_fixed_widths(*pFixedWidths); }); } bool QtInstanceTreeView::get_row_expanded(const weld::TreeIter& rIter) const { SolarMutexGuard g; bool bExpanded = false; GetQtInstance().RunInMainThread( [&] { bExpanded = m_pTreeView->isExpanded(modelIndex(rIter)); }); return bExpanded; } void QtInstanceTreeView::expand_row(const weld::TreeIter& rIter) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { m_pTreeView->expand(modelIndex(rIter)); }); } void QtInstanceTreeView::collapse_row(const weld::TreeIter& rIter) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { m_pTreeView->collapse(modelIndex(rIter)); }); } void QtInstanceTreeView::do_set_children_on_demand(const weld::TreeIter&, bool) { assert(false && "Not implemented yet"); } bool QtInstanceTreeView::get_children_on_demand(const weld::TreeIter&) const { assert(false && "Not implemented yet"); return false; } void QtInstanceTreeView::set_show_expanders(bool) { assert(false && "Not implemented yet"); } void QtInstanceTreeView::start_editing(const weld::TreeIter&) { assert(false && "Not implemented yet"); } void QtInstanceTreeView::end_editing() { assert(false && "Not implemented yet"); } void QtInstanceTreeView::enable_drag_source(rtl::Reference&, sal_uInt8) { assert(false && "Not implemented yet"); } void QtInstanceTreeView::select_all() { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { m_pTreeView->selectAll(); }); } void QtInstanceTreeView::unselect_all() { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { m_pTreeView->clearSelection(); }); } int QtInstanceTreeView::n_children() const { SolarMutexGuard g; int nChildCount; GetQtInstance().RunInMainThread([&] { const QModelIndex aRootIndex = m_pModel->mapFromSource(m_pSourceModel->invisibleRootItem()->index()); nChildCount = m_pModel->rowCount(aRootIndex); }); return nChildCount; } void QtInstanceTreeView::make_sorted() { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { m_pTreeView->setSortingEnabled(true); // sort by first column m_pModel->sort(0); }); } void QtInstanceTreeView::make_unsorted() { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { m_pTreeView->setSortingEnabled(false); m_pModel->sort(-1); }); } bool QtInstanceTreeView::get_sort_order() const { SolarMutexGuard g; bool bAscending = true; GetQtInstance().RunInMainThread( [&] { bAscending = m_pModel->sortOrder() == Qt::AscendingOrder; }); return bAscending; } void QtInstanceTreeView::set_sort_order(bool bAscending) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { const Qt::SortOrder eOrder = bAscending ? Qt::AscendingOrder : Qt::DescendingOrder; m_pModel->sort(m_pModel->sortColumn(), eOrder); }); } void QtInstanceTreeView::set_sort_indicator(TriState, int) { assert(false && "Not implemented yet"); } TriState QtInstanceTreeView::get_sort_indicator(int) const { assert(false && "Not implemented yet"); return TRISTATE_INDET; } int QtInstanceTreeView::get_sort_column() const { SolarMutexGuard g; int nSortColumn = 0; GetQtInstance().RunInMainThread([&] { nSortColumn = m_pModel->sortColumn(); }); return nSortColumn; } void QtInstanceTreeView::set_sort_column(int nColumn) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { m_pModel->sort(nColumn); }); } void QtInstanceTreeView::do_clear() { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { // don't use QStandardItemModel::clear, as that would remove header data as well m_pModel->removeRows(0, m_pModel->rowCount()); }); } int QtInstanceTreeView::get_height_rows(int) const { SAL_WARN("vcl.qt", "QtInstanceTreeView::get_height_rows just returns 0 for now"); return 0; } void QtInstanceTreeView::columns_autosize() { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { for (int i = 0; i < m_pModel->columnCount(); i++) m_pTreeView->resizeColumnToContents(i); }); } void QtInstanceTreeView::set_column_fixed_widths(const std::vector& rWidths) { SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { assert(rWidths.size() <= o3tl::make_unsigned(m_pModel->columnCount())); for (size_t i = 0; i < rWidths.size(); ++i) m_pTreeView->setColumnWidth(i, rWidths.at(i)); }); } void QtInstanceTreeView::set_column_editables(const std::vector&) { assert(false && "Not implemented yet"); } int QtInstanceTreeView::get_column_width(int nCol) const { SolarMutexGuard g; int nWidth = 0; GetQtInstance().RunInMainThread([&] { nWidth = m_pTreeView->columnWidth(nCol); }); return nWidth; } void QtInstanceTreeView::set_centered_column(int) { assert(false && "Not implemented yet"); } OUString QtInstanceTreeView::get_column_title(int nColumn) const { SolarMutexGuard g; OUString sTitle; GetQtInstance().RunInMainThread([&] { const QVariant aVariant = m_pModel->headerData(nColumn, Qt::Horizontal); assert(aVariant.isValid() && aVariant.canConvert()); sTitle = toOUString(aVariant.toString()); }); return sTitle; } void QtInstanceTreeView::set_column_title(int nColumn, const OUString& rTitle) { SolarMutexGuard g; GetQtInstance().RunInMainThread( [&] { m_pModel->setHeaderData(nColumn, Qt::Horizontal, toQString(rTitle)); }); } void QtInstanceTreeView::set_selection_mode(SelectionMode eMode) { SolarMutexGuard g; GetQtInstance().RunInMainThread( [&] { m_pTreeView->setSelectionMode(mapSelectionMode(eMode)); }); } int QtInstanceTreeView::count_selected_rows() const { return get_selected_rows().size(); } void QtInstanceTreeView::do_remove_selection() { assert(false && "Not implemented yet"); } bool QtInstanceTreeView::changed_by_hover() const { assert(false && "Not implemented yet"); return false; } void QtInstanceTreeView::vadjustment_set_value(int) { assert(false && "Not implemented yet"); } int QtInstanceTreeView::vadjustment_get_value() const { assert(false && "Not implemented yet"); return -1; } void QtInstanceTreeView::set_column_custom_renderer(int, bool) { assert(false && "Not implemented yet"); } void QtInstanceTreeView::queue_draw() { assert(false && "Not implemented yet"); } bool QtInstanceTreeView::get_dest_row_at_pos(const Point&, weld::TreeIter*, bool, bool) { assert(false && "Not implemented yet"); return false; } void QtInstanceTreeView::unset_drag_dest_row() { assert(false && "Not implemented yet"); } tools::Rectangle QtInstanceTreeView::get_row_area(const weld::TreeIter&) const { assert(false && "Not implemented yet"); return tools::Rectangle(); } weld::TreeView* QtInstanceTreeView::get_drag_source() const { assert(false && "Not implemented yet"); return nullptr; } QAbstractItemView::SelectionMode QtInstanceTreeView::mapSelectionMode(SelectionMode eMode) { switch (eMode) { case SelectionMode::NONE: return QAbstractItemView::NoSelection; case SelectionMode::Single: return QAbstractItemView::SingleSelection; case SelectionMode::Range: return QAbstractItemView::ContiguousSelection; case SelectionMode::Multiple: return QAbstractItemView::ExtendedSelection; default: assert(false && "unhandled selection mode"); return QAbstractItemView::SingleSelection; } } QList> QtInstanceTreeView::columnRoles(QTreeView& rTreeView) { QVariant aVariant = rTreeView.property(PROPERTY_COLUMN_ROLES); if (aVariant.isValid()) { assert(aVariant.canConvert>>()); return aVariant.value>>(); } return {}; } void QtInstanceTreeView::setColumnRoles(QTreeView& rTreeView, const QList>& rDataRoles) { rTreeView.setProperty(PROPERTY_COLUMN_ROLES, QVariant::fromValue(rDataRoles)); } bool QtInstanceTreeView::eventFilter(QObject* pObject, QEvent* pEvent) { if (pEvent->type() == QEvent::ToolTip && pObject == m_pTreeView->viewport()) return handleViewPortToolTipEvent(static_cast(*pEvent)); return QtInstanceWidget::eventFilter(pObject, pEvent); } QModelIndex QtInstanceTreeView::modelIndex(int nRow, int nCol, const QModelIndex& rParentIndex) const { return modelIndex(treeIter(nRow, rParentIndex), nCol); } QModelIndex QtInstanceTreeView::modelIndex(const weld::TreeIter& rIter, int nCol) const { QModelIndex aModelIndex = static_cast(rIter).modelIndex(); return m_pModel->index(aModelIndex.row(), nCol, aModelIndex.parent()); } QtInstanceTreeIter QtInstanceTreeView::treeIter(int nRow, const QModelIndex& rParentIndex) const { return QtInstanceTreeIter(m_pModel->index(nRow, 0, rParentIndex)); } QStandardItem* QtInstanceTreeView::itemFromIndex(const QModelIndex& rIndex) const { const QModelIndex aSourceIndex = m_pModel->mapToSource(rIndex); return m_pSourceModel->itemFromIndex(aSourceIndex); } QModelIndex QtInstanceTreeView::toggleButtonModelIndex(const weld::TreeIter& rIter) const { assert(m_bExtraToggleButtonsEnabled && "Special toggle buttons are not enabled"); const QModelIndex aIndex = modelIndex(rIter); // Special toggle buttons are always in the first column return m_pModel->index(aIndex.row(), 0, aIndex.parent()); } QModelIndex QtInstanceTreeView::firstTextColumnModelIndex(const weld::TreeIter& rIter) const { for (qsizetype i = 0; i < m_pColumnRoles.size(); i++) { if (m_pColumnRoles.at(i).contains(Qt::DisplayRole)) return modelIndex(rIter, i); } assert(false && "No text column found"); return QModelIndex(); } void QtInstanceTreeView::setImage(const weld::TreeIter& rIter, const QPixmap& rPixmap, int nCol) { // set the "expander image" for the Qt::DecorationRole in the first column // It can still contain additional data (like text) for other roles, but not // another image. If that turns out to be problematic, another solution needs // to be found. if (nCol == -1) nCol = 0; SolarMutexGuard g; GetQtInstance().RunInMainThread([&] { QModelIndex aIndex = modelIndex(rIter, nCol); m_pModel->setData(aIndex, rPixmap, Qt::DecorationRole); }); } bool QtInstanceTreeView::handleViewPortToolTipEvent(const QHelpEvent& rHelpEvent) { QModelIndex aIndex = m_pTreeView->indexAt(rHelpEvent.pos()); if (!aIndex.isValid()) return false; SolarMutexGuard g; const QtInstanceTreeIter aIter(aIndex); const OUString sToolTip = signal_query_tooltip(aIter); if (sToolTip.isEmpty()) return false; QToolTip::showText(rHelpEvent.globalPos(), toRichTextTooltip(sToolTip), m_pTreeView, m_pTreeView->visualRect(aIndex)); return true; } void QtInstanceTreeView::handleActivated() { SolarMutexGuard g; signal_row_activated(); } void QtInstanceTreeView::handleDataChanged(const QModelIndex& rTopLeft, const QModelIndex& rBottomRight, const QVector& rRoles) { SolarMutexGuard g; // only notify about check state changes if (!rRoles.contains(Qt::CheckStateRole)) return; assert(rTopLeft == rBottomRight && "Case of multiple changes not implemented yet"); (void)rBottomRight; int nColIndex = rTopLeft.column(); if (m_bExtraToggleButtonsEnabled && nColIndex == 0) // use special index of -1 for the "expander toggle" nColIndex = -1; signal_toggled(iter_col(QtInstanceTreeIter(rTopLeft), nColIndex)); } void QtInstanceTreeView::handleSelectionChanged() { SolarMutexGuard g; signal_selection_changed(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */