Commit 7bd8db5c authored by Jan Grulich's avatar Jan Grulich
Browse files

Improve app chooser dialog

parent 5b930a73
......@@ -8,6 +8,7 @@ set(xdg_desktop_portal_kde_SRCS
accessdialog.cpp
appchooser.cpp
appchooserdialog.cpp
appchooserdialogitem.cpp
desktopportal.cpp
email.cpp
filechooser.cpp
......@@ -31,7 +32,6 @@ endif()
ki18n_wrap_ui(xdg_desktop_portal_kde_SRCS
accessdialog.ui
appchooserdialog.ui
)
add_executable(xdg-desktop-portal-kde ${xdg_desktop_portal_kde_SRCS})
......
......@@ -56,11 +56,7 @@ uint AppChooserPortal::ChooseApplication(const QDBusObjectPath &handle,
latestChoice = options.value(QLatin1String("last_choice")).toString();
}
AppChooserDialog *appDialog = new AppChooserDialog(choices);
if (!latestChoice.isEmpty()) {
appDialog->setSelectedApplication(latestChoice);
}
AppChooserDialog *appDialog = new AppChooserDialog(choices, latestChoice, options.value(QLatin1String("filename")).toString());
if (appDialog->exec()) {
results.insert(QLatin1String("choice"), appDialog->selectedApplication());
......
......@@ -19,26 +19,50 @@
*/
#include "appchooserdialog.h"
#include "ui_appchooserdialog.h"
#include "appchooserdialogitem.h"
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QVBoxLayout>
#include <QLabel>
#include <QLoggingCategory>
#include <KLocalizedString>
#include <QSettings>
#include <QStandardPaths>
#include <QPushButton>
#include <KProcess>
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeAppChooserDialog, "xdp-kde-app-chooser-dialog")
AppChooserDialog::AppChooserDialog(const QStringList &choices, QDialog *parent, Qt::WindowFlags flags)
AppChooserDialog::AppChooserDialog(const QStringList &choices, const QString &defaultApp, const QString &fileName, QDialog *parent, Qt::WindowFlags flags)
: QDialog(parent, flags)
, m_dialog(new Ui::AppChooserDialog)
, m_choices(choices)
{
m_dialog->setupUi(this);
setMinimumWidth(640);
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 <a href=#discover><span style=\"text-decoration: underline\">Discover</span></a>.", fileName));
label->setOpenExternalLinks(false);
connect(label, &QLabel::linkActivated, this, [] () {
KProcess::startDetached("plasma-discover");
});
vboxLayout->addWidget(label);
QGridLayout *gridLayout = new QGridLayout();
Q_FOREACH (const QString &choice, m_choices) {
int i = 0, j = 0;
foreach (const QString &choice, choices) {
const QString desktopFile = choice + QLatin1String(".desktop");
const QStringList desktopFilesLocations = QStandardPaths::locateAll(QStandardPaths::ApplicationsLocation, desktopFile, QStandardPaths::LocateFile);
Q_FOREACH (const QString desktopFile, desktopFilesLocations) {
foreach (const QString desktopFile, desktopFilesLocations) {
QString applicationIcon;
QString applicationName;
QSettings settings(desktopFile, QSettings::IniFormat);
......@@ -50,51 +74,42 @@ AppChooserDialog::AppChooserDialog(const QStringList &choices, QDialog *parent,
}
applicationIcon = settings.value(QLatin1String("Icon")).toString();
QListWidgetItem *widgetItem = new QListWidgetItem(m_dialog->appView);
widgetItem->setData(Qt::UserRole, QVariant::fromValue(choice));
// FIXME GTK icons will work only with Qt 5.7
widgetItem->setIcon(QIcon::fromTheme(applicationIcon));
widgetItem->setText(applicationName);
AppChooserDialogItem *item = new AppChooserDialogItem(applicationName, applicationIcon, choice);
gridLayout->addWidget(item, i, j++, Qt::AlignHCenter);
connect(item, &AppChooserDialogItem::doubleClicked, this, [this] (const QString &selectedApplication) {
m_selectedApplication = selectedApplication;
QDialog::accept();
});
if (choice == defaultApp) {
item->setDown(true);
item->setChecked(true);
}
if (j == 3) {
i++;
j = 0;
}
}
}
connect(m_dialog->buttonBox, &QDialogButtonBox::accepted, this, &AppChooserDialog::accept);
connect(m_dialog->buttonBox, &QDialogButtonBox::rejected, this, &AppChooserDialog::reject);
connect(m_dialog->appView, &QListWidget::itemDoubleClicked, this, &AppChooserDialog::accept);
connect(m_dialog->searchEdit, &QLineEdit::textChanged, this, &AppChooserDialog::searchTextChanged);
vboxLayout->addLayout(gridLayout);
m_dialog->buttonBox->button(QDialogButtonBox::Ok)->setText(i18n("Select"));
setWindowTitle(i18n("Select application"));
}
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, this);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
AppChooserDialog::~AppChooserDialog()
{
delete m_dialog;
}
vboxLayout->addWidget(buttonBox, 0, Qt::AlignBottom | Qt::AlignRight);
QString AppChooserDialog::selectedApplication() const
{
return m_dialog->appView->currentItem()->data(Qt::UserRole).toString();
setLayout(vboxLayout);
setWindowTitle(i18n("Open with"));
}
void AppChooserDialog::setSelectedApplication(const QString &applicationName)
AppChooserDialog::~AppChooserDialog()
{
for (int i = 0; i < m_dialog->appView->count(); i++) {
QListWidgetItem *widgetItem = m_dialog->appView->item(i);
if (widgetItem->data(Qt::UserRole).toString() == applicationName) {
m_dialog->appView->setCurrentItem(widgetItem, QItemSelectionModel::Select);
}
}
}
void AppChooserDialog::searchTextChanged(const QString &text)
QString AppChooserDialog::selectedApplication() const
{
for (int i = 0; i < m_dialog->appView->count(); i++) {
QListWidgetItem *widgetItem = m_dialog->appView->item(i);
if (text.isEmpty()) {
widgetItem->setHidden(false);
} else {
widgetItem->setHidden(!widgetItem->text().toLower().contains(text.toLower()));
}
}
return m_selectedApplication;
}
......@@ -24,27 +24,17 @@
#include <QAbstractListModel>
#include <QDialog>
namespace Ui
{
class AppChooserDialog;
}
class AppChooserDialog : public QDialog
{
Q_OBJECT
public:
AppChooserDialog(const QStringList &choices, QDialog *parent = nullptr, Qt::WindowFlags flags = 0);
AppChooserDialog(const QStringList &choices, const QString &defaultApp, const QString &fileName, QDialog *parent = nullptr, Qt::WindowFlags flags = 0);
~AppChooserDialog();
QString selectedApplication() const;
void setSelectedApplication(const QString &applicationName);
public Q_SLOTS:
void searchTextChanged(const QString &text);
private:
Ui::AppChooserDialog * m_dialog;
QStringList m_choices;
QString m_selectedApplication;
};
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AppChooserDialog</class>
<widget class="QDialog" name="AppChooserDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="searchLabel">
<property name="text">
<string>Search</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="searchEdit"/>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QListWidget" name="appView">
<property name="iconSize">
<size>
<width>48</width>
<height>48</height>
</size>
</property>
<property name="uniformItemSizes">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
/*
* 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 <http://www.gnu.org/licenses/>.
*
* Authors:
* Jan Grulich <jgrulich@redhat.com>
*/
#include "appchooserdialogitem.h"
#include <QMouseEvent>
#include <QFontMetrics>
#include <QVBoxLayout>
#include <QDebug>
AppChooserDialogItem::AppChooserDialogItem(const QString &applicationName, const QString &icon, const QString &applicationExec, QToolButton *parent)
: QToolButton(parent)
, m_applicationName(applicationExec)
{
setAutoRaise(true);
setAutoExclusive(true);
setStyleSheet(QLatin1String("text-align: center"));
setIcon(QIcon::fromTheme(icon));
setIconSize(QSize(64, 64));
setCheckable(true);
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::mouseDoubleClickEvent(QMouseEvent *event)
{
Q_EMIT doubleClicked(m_applicationName);
QToolButton::mouseDoubleClickEvent(event);
}
void AppChooserDialogItem::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
setDown(true);
setChecked(true);
}
}
void AppChooserDialogItem::mouseReleaseEvent(QMouseEvent *event)
{
event->ignore();
}
/*
* 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 <http://www.gnu.org/licenses/>.
*
* Authors:
* Jan Grulich <jgrulich@redhat.com>
*/
#ifndef XDG_DESKTOP_PORTAL_KDE_APPCHOOSER_DIALOG_ITEM_H
#define XDG_DESKTOP_PORTAL_KDE_APPCHOOSER_DIALOG_ITEM_H
class QMouseEvent;
#include <QToolButton>
class AppChooserDialogItem : public QToolButton
{
Q_OBJECT
public:
AppChooserDialogItem(const QString &applicationName, const QString &icon, const QString &applicationExec, QToolButton *parent = nullptr);
~AppChooserDialogItem();
QString applicationName() const;
virtual void mouseDoubleClickEvent(QMouseEvent * event) override;
virtual void mousePressEvent(QMouseEvent * event) override;
virtual void mouseReleaseEvent(QMouseEvent * event) override;
Q_SIGNALS:
void doubleClicked(const QString &applicationName);
private:
QString m_applicationName;
};
#endif // XDG_DESKTOP_PORTAL_KDE_APPCHOOSER_DIALOG_ITEM_H
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment