+ const auto modifiers = QGuiApplication::keyboardModifiers();
+
+ if (indexes.count() > 5) {
+ QString question = i18np("Are you sure you want to open 1 item?", "Are you sure you want to open %1 items?", indexes.count());
+ const int answer = KMessageBox::warningContinueCancel(
+ this,
+ question,
+ {},
+ KGuiItem(i18ncp("@action:button", "Open %1 Item", "Open %1 Items", indexes.count()), QStringLiteral("document-open")),
+ KStandardGuiItem::cancel(),
+ QStringLiteral("ConfirmOpenManyFolders"));
+ if (answer != KMessageBox::PrimaryAction && answer != KMessageBox::Continue) {
+ return;
+ }
+ }
+
+ KFileItemList items;
+ items.reserve(indexes.count());
+
+ for (int index : indexes) {
+ KFileItem item = m_model->fileItem(index);
+ const QUrl &url = openItemAsFolderUrl(item);
+
+ if (!url.isEmpty()) {
+ // Open folders in new tabs or in new windows depending on the modifier
+ // The ctrl+shift behavior is ignored because we are handling multiple items
+ // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+ if (modifiers & Qt::ShiftModifier && !(modifiers & Qt::ControlModifier)) {
+ Q_EMIT windowRequested(url);
+ } else {
+ Q_EMIT tabRequested(url);
+ }
+ } else {
+ items.append(item);
+ }
+ }
+
+ if (items.count() == 1) {
+ Q_EMIT itemActivated(items.first());
+ } else if (items.count() > 1) {
+ Q_EMIT itemsActivated(items);
+ }
+}
+
+void DolphinView::slotItemMiddleClicked(int index)
+{
+ const KFileItem &item = m_model->fileItem(index);
+ const QUrl &url = openItemAsFolderUrl(item, GeneralSettings::browseThroughArchives());
+ const auto modifiers = QGuiApplication::keyboardModifiers();
+ if (!url.isEmpty()) {
+ // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+ if (modifiers & Qt::ShiftModifier) {
+ Q_EMIT activeTabRequested(url);
+ } else {
+ Q_EMIT tabRequested(url);
+ }
+ } else if (isTabsForFilesEnabled()) {
+ // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+ if (modifiers & Qt::ShiftModifier) {
+ Q_EMIT activeTabRequested(item.url());
+ } else {
+ Q_EMIT tabRequested(item.url());
+ }
+ } else {
+ Q_EMIT fileMiddleClickActivated(item);
+ }
+}
+
+void DolphinView::slotItemContextMenuRequested(int index, const QPointF &pos)
+{
+ // Force emit of a selection changed signal before we request the
+ // context menu, to update the edit-actions first. (See Bug 294013)
+ if (m_selectionChangedTimer->isActive()) {
+ emitSelectionChangedSignal();
+ }
+ if (m_twoClicksRenamingTimer->isActive()) {
+ abortTwoClicksRenaming();
+ }
+
+ const KFileItem item = m_model->fileItem(index);
+ Q_EMIT requestContextMenu(pos.toPoint(), item, selectedItems(), url());
+}
+
+void DolphinView::slotViewContextMenuRequested(const QPointF &pos)
+{
+ Q_EMIT requestContextMenu(pos.toPoint(), KFileItem(), selectedItems(), url());
+}
+
+void DolphinView::slotHeaderContextMenuRequested(const QPointF &pos)
+{
+ ViewProperties props(viewPropertiesUrl());
+
+ QPointer<QMenu> menu = new QMenu(this);
+
+ KItemListView *view = m_container->controller()->view();
+ const QList<QByteArray> visibleRolesSet = view->visibleRoles();
+
+ bool indexingEnabled = false;
+#if HAVE_BALOO
+ Baloo::IndexerConfig config;
+ indexingEnabled = config.fileIndexingEnabled();
+#endif
+
+ QString groupName;
+ QMenu *groupMenu = nullptr;
+
+ // Add all roles to the menu that can be shown or hidden by the user
+ const QList<KFileItemModel::RoleInfo> rolesInfo = KFileItemModel::rolesInformation();
+ for (const KFileItemModel::RoleInfo &info : rolesInfo) {
+ if (info.role == "text") {
+ // It should not be possible to hide the "text" role
+ continue;
+ }
+
+ const QString text = m_model->roleDescription(info.role);
+ QAction *action = nullptr;
+ if (info.group.isEmpty()) {
+ action = menu->addAction(text);
+ } else {
+ if (!groupMenu || info.group != groupName) {
+ groupName = info.group;
+ groupMenu = menu->addMenu(groupName);
+ }
+
+ action = groupMenu->addAction(text);
+ }
+
+ action->setCheckable(true);
+ action->setChecked(visibleRolesSet.contains(info.role));
+ action->setData(info.role);
+ action->setToolTip(info.tooltip);
+
+ const bool enable = (!info.requiresBaloo && !info.requiresIndexer) || (info.requiresBaloo) || (info.requiresIndexer && indexingEnabled);
+ action->setEnabled(enable);
+ }
+
+ menu->addSeparator();
+
+ QActionGroup *widthsGroup = new QActionGroup(menu);
+ const bool autoColumnWidths = props.headerColumnWidths().isEmpty();
+
+ QAction *toggleSidePaddingAction = menu->addAction(i18nc("@action:inmenu", "Side Padding"));
+ toggleSidePaddingAction->setCheckable(true);
+ toggleSidePaddingAction->setChecked(layoutDirection() == Qt::LeftToRight ? view->header()->leftPadding() > 0 : view->header()->rightPadding() > 0);
+
+ QAction *autoAdjustWidthsAction = menu->addAction(i18nc("@action:inmenu", "Automatic Column Widths"));
+ autoAdjustWidthsAction->setCheckable(true);
+ autoAdjustWidthsAction->setChecked(autoColumnWidths);
+ autoAdjustWidthsAction->setActionGroup(widthsGroup);
+
+ QAction *customWidthsAction = menu->addAction(i18nc("@action:inmenu", "Custom Column Widths"));
+ customWidthsAction->setCheckable(true);
+ customWidthsAction->setChecked(!autoColumnWidths);
+ customWidthsAction->setActionGroup(widthsGroup);
+
+ QAction *action = menu->exec(pos.toPoint());
+ if (menu && action) {
+ KItemListHeader *header = view->header();
+
+ if (action == autoAdjustWidthsAction) {
+ // Clear the column-widths from the viewproperties and turn on
+ // the automatic resizing of the columns
+ props.setHeaderColumnWidths(QList<int>());
+ header->setAutomaticColumnResizing(true);
+ } else if (action == customWidthsAction) {
+ // Apply the current column-widths as custom column-widths and turn
+ // off the automatic resizing of the columns
+ QList<int> columnWidths;
+ const auto visibleRoles = view->visibleRoles();
+ columnWidths.reserve(visibleRoles.count());
+ for (const QByteArray &role : visibleRoles) {
+ columnWidths.append(header->columnWidth(role));
+ }
+ props.setHeaderColumnWidths(columnWidths);
+ header->setAutomaticColumnResizing(false);
+ } else if (action == toggleSidePaddingAction) {
+ if (toggleSidePaddingAction->isChecked()) {
+ header->setSidePadding(20, 20);
+ } else {
+ header->setSidePadding(0, 0);
+ }
+ } else {
+ // Show or hide the selected role
+ const QByteArray selectedRole = action->data().toByteArray();
+
+ QList<QByteArray> visibleRoles = view->visibleRoles();
+ if (action->isChecked()) {
+ visibleRoles.append(selectedRole);
+ } else {
+ visibleRoles.removeOne(selectedRole);
+ }
+
+ view->setVisibleRoles(visibleRoles);
+ props.setVisibleRoles(visibleRoles);
+
+ QList<int> columnWidths;
+ if (!header->automaticColumnResizing()) {
+ const auto visibleRoles = view->visibleRoles();
+ columnWidths.reserve(visibleRoles.count());
+ for (const QByteArray &role : visibleRoles) {
+ columnWidths.append(header->columnWidth(role));
+ }
+ }
+ props.setHeaderColumnWidths(columnWidths);
+ }
+ }
+
+ delete menu;
+}
+
+void DolphinView::slotHeaderColumnWidthChangeFinished(const QByteArray &role, qreal current)
+{
+ const QList<QByteArray> visibleRoles = m_view->visibleRoles();
+
+ ViewProperties props(viewPropertiesUrl());
+ QList<int> columnWidths = props.headerColumnWidths();
+ if (columnWidths.count() != visibleRoles.count()) {
+ columnWidths.clear();
+ columnWidths.reserve(visibleRoles.count());
+ const KItemListHeader *header = m_view->header();
+ for (const QByteArray &role : visibleRoles) {
+ const int width = header->columnWidth(role);
+ columnWidths.append(width);
+ }
+ }
+
+ const int roleIndex = visibleRoles.indexOf(role);
+ Q_ASSERT(roleIndex >= 0 && roleIndex < columnWidths.count());
+ columnWidths[roleIndex] = current;
+
+ props.setHeaderColumnWidths(columnWidths);
+}
+
+void DolphinView::slotSidePaddingWidthChanged(qreal leftPaddingWidth, qreal rightPaddingWidth)
+{
+ ViewProperties props(viewPropertiesUrl());
+ DetailsModeSettings::setLeftPadding(int(leftPaddingWidth));
+ DetailsModeSettings::setRightPadding(int(rightPaddingWidth));
+ m_view->writeSettings();
+}
+
+void DolphinView::slotItemHovered(int index)
+{
+ const KFileItem item = m_model->fileItem(index);
+
+ if (GeneralSettings::showToolTips() && !m_dragging) {
+ QRectF itemRect = m_container->controller()->view()->itemContextRect(index);