diff --git a/src/appchooserdialog.cpp b/src/appchooserdialog.cpp index 8fc888f..b14a5f9 100644 --- a/src/appchooserdialog.cpp +++ b/src/appchooserdialog.cpp @@ -1,166 +1,180 @@ /* * Copyright © 2017-2018 Red Hat, Inc * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * * Authors: * Jan Grulich */ #include "appchooserdialog.h" #include "appchooserdialogitem.h" #include #include #include #include #include #include #include #include #include +#include #include #include Q_LOGGING_CATEGORY(XdgDesktopPortalKdeAppChooserDialog, "xdp-kde-app-chooser-dialog") AppChooserDialog::AppChooserDialog(const QStringList &choices, const QString &defaultApp, const QString &fileName, QDialog *parent, Qt::WindowFlags flags) : QDialog(parent, flags) , m_choices(choices) , m_defaultApp(defaultApp) { setMinimumWidth(640); + setMaximumHeight(480); QVBoxLayout *vboxLayout = new QVBoxLayout(this); vboxLayout->setSpacing(20); vboxLayout->setMargin(20); QLabel *label = new QLabel(this); label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); label->setScaledContents(true); label->setWordWrap(true); label->setText(i18n("Select application to open \"%1\". Other applications are available in Discover.", fileName)); label->setOpenExternalLinks(false); connect(label, &QLabel::linkActivated, this, [] () { KProcess::startDetached(QStringLiteral("plasma-discover")); }); vboxLayout->addWidget(label); - m_gridLayout = new QGridLayout(); + QWidget *appsWidget = new QWidget(this); + QScrollArea *scrollArea = new QScrollArea(this); + scrollArea->setFrameShape(QFrame::NoFrame); + scrollArea->setWidget(appsWidget); + scrollArea->setWidgetResizable(true); + + // FIXME: workaround scrollarea sizing, set minimum height to make sure at least two rows are visible + if (choices.count() > 3) { + scrollArea->setMinimumHeight(200); + } + + m_gridLayout = new QGridLayout; + appsWidget->setLayout(m_gridLayout); QTimer::singleShot(0, this, &AppChooserDialog::addDialogItems); - vboxLayout->addLayout(m_gridLayout); + vboxLayout->addWidget(scrollArea); setLayout(vboxLayout); setWindowTitle(i18n("Open with")); } AppChooserDialog::~AppChooserDialog() { delete m_gridLayout; } void AppChooserDialog::updateChoices(const QStringList &choices) { bool changed = false; // Check if we will be adding something for (const QString &choice : choices) { if (!m_choices.contains(choice)) { changed = true; m_choices << choice; } } // Check if we will be removing something for (const QString &choice : m_choices) { if (!choices.contains(choice)) { changed = true; m_choices.removeAll(choice); } } // If something changed, clear the layout and add the items again if (changed) { int rowCount = m_gridLayout->rowCount(); int columnCount = m_gridLayout->columnCount(); for (int i = 0; i < rowCount; ++i) { for (int j = 0; j < columnCount; ++j) { QLayoutItem *item = m_gridLayout->itemAtPosition(i, j); if (item) { QWidget *widget = item->widget(); if (widget) { m_gridLayout->removeWidget(widget); widget->deleteLater(); } } } } addDialogItems(); } } QString AppChooserDialog::selectedApplication() const { if (m_selectedApplication.isEmpty()) { return m_defaultApp; } return m_selectedApplication; } void AppChooserDialog::addDialogItems() { int i = 0, j = 0; for (const QString &choice : m_choices) { const QString desktopFile = choice + QStringLiteral(".desktop"); const QStringList desktopFilesLocations = QStandardPaths::locateAll(QStandardPaths::ApplicationsLocation, desktopFile, QStandardPaths::LocateFile); for (const QString &desktopFile : desktopFilesLocations) { QString applicationIcon; QString applicationName; QSettings settings(desktopFile, QSettings::IniFormat); settings.beginGroup(QStringLiteral("Desktop Entry")); if (settings.contains(QStringLiteral("X-GNOME-FullName"))) { applicationName = settings.value(QStringLiteral("X-GNOME-FullName")).toString(); } else { applicationName = settings.value(QStringLiteral("Name")).toString(); } applicationIcon = settings.value(QStringLiteral("Icon")).toString(); AppChooserDialogItem *item = new AppChooserDialogItem(applicationName, applicationIcon, choice, this); m_gridLayout->addWidget(item, i, j++, Qt::AlignHCenter); connect(item, &AppChooserDialogItem::clicked, this, [this] (const QString &selectedApplication) { m_selectedApplication = selectedApplication; QDialog::accept(); }); if (choice == m_defaultApp) { item->setDown(true); item->setChecked(true); } if (j == 3) { i++; j = 0; } } } } diff --git a/src/appchooserdialogitem.cpp b/src/appchooserdialogitem.cpp index d01327f..1ce3249 100644 --- a/src/appchooserdialogitem.cpp +++ b/src/appchooserdialogitem.cpp @@ -1,67 +1,68 @@ /* * Copyright © 2018 Red Hat, Inc * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * * Authors: * Jan Grulich */ #include "appchooserdialogitem.h" #include #include #include #include AppChooserDialogItem::AppChooserDialogItem(const QString &applicationName, const QString &icon, const QString &applicationExec, QWidget *parent) : QToolButton(parent) , m_applicationName(applicationExec) { setAutoRaise(true); setAutoExclusive(true); setStyleSheet(QStringLiteral("text-align: center")); setIcon(QIcon::fromTheme(icon)); setIconSize(QSize(64, 64)); setCheckable(true); + setFixedHeight(100); setFixedWidth(150); setToolButtonStyle(Qt::ToolButtonTextUnderIcon); QFontMetrics metrics(font()); QString elidedText = metrics.elidedText(applicationName, Qt::ElideRight, 128); setText(elidedText); connect(this, &QToolButton::toggled, this, [this] (bool toggled) { if (!toggled) { setDown(false); } }); } AppChooserDialogItem::~AppChooserDialogItem() { } QString AppChooserDialogItem::applicationName() const { return m_applicationName; } void AppChooserDialogItem::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { Q_EMIT clicked(m_applicationName); } }