You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lxqt-config-packaging/lxqt-config-file-associations/applicationchooser.cpp

195 lines
6.9 KiB

/* BEGIN_COMMON_COPYRIGHT_HEADER
* (c)LGPL2+
*
* LXQt - a lightweight, Qt based, desktop toolset
* http://razor-qt.org
*
* Copyright: 2013 Christian Surlykke
*
* This program or library 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.1 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, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* END_COMMON_COPYRIGHT_HEADER */
#include <QDialogButtonBox>
#include <QPushButton>
#include <QSettings>
#include <QString>
#include <QDebug>
#include <QMimeDatabase>
#include <QTimer>
#include <XdgDesktopFile>
#include "applicationchooser.h"
Q_DECLARE_METATYPE(XdgDesktopFile*)
ApplicationChooser::ApplicationChooser(const XdgMimeType& mimeInfo, bool showUseAlwaysCheckBox)
{
m_MimeInfo = mimeInfo;
m_CurrentDefaultApplication = XdgDesktopFileCache::getDefaultApp(m_MimeInfo.name());
widget.setupUi(this);
widget.mimetypeIconLabel->setPixmap(m_MimeInfo.icon().pixmap(widget.mimetypeIconLabel->size()));
widget.mimetypeLabel->setText(m_MimeInfo.comment());
widget.alwaysUseCheckBox->setVisible(showUseAlwaysCheckBox);
widget.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
}
ApplicationChooser::~ApplicationChooser()
{
}
int ApplicationChooser::exec()
{
show();
fillApplicationListWidget();
return QDialog::exec();
}
bool lessThan(XdgDesktopFile* a, XdgDesktopFile* b)
{
return a && b && a->name().toLower() < b->name().toLower();
}
void ApplicationChooser::updateAllIcons() {
// loading all icons is very time-consuming...
QCoreApplication::processEvents();
QTreeWidget* tree = widget.applicationTreeWidget;
int updated = 0;
int top_n = tree->topLevelItemCount();
for(int top_i = 0; top_i < top_n; ++top_i) {
QTreeWidgetItem* parent = tree->topLevelItem(top_i);
int n = parent->childCount();
for(int i = 0; i < n; ++i) {
QTreeWidgetItem* item = parent->child(i);
XdgDesktopFile* desktopFile = item->data(0, 32).value<XdgDesktopFile*>();
if(Q_LIKELY(desktopFile != NULL && !desktopFile->icon().isNull())) {
item->setIcon(0, desktopFile->icon());
++updated;
if(updated % 8 == 0) // update the UI in batch is more efficient
QCoreApplication::processEvents();
}
}
}
QCoreApplication::processEvents();
QApplication::restoreOverrideCursor();
}
void ApplicationChooser::fillApplicationListWidget()
{
widget.applicationTreeWidget->clear();
QSet<XdgDesktopFile*> addedApps;
QList<XdgDesktopFile*> applicationsThatHandleThisMimetype = XdgDesktopFileCache::getApps(m_MimeInfo.name());
QList<XdgDesktopFile*> otherApplications;
QStringList mimetypes;
mimetypes << m_MimeInfo.name() << m_MimeInfo.allAncestors();
// Adding all apps takes some time. Make the user aware by setting the
// cursor to Wait.
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
QMimeDatabase db;
foreach(const QString& mts, mimetypes) {
QMimeType mt = db.mimeTypeForName(mts);
QString heading;
heading = mt.name() == QLatin1String("application/octet-stream") ?
tr("Other applications") :
tr("Applications that handle %1").arg(mt.comment());
QList<XdgDesktopFile*> applications;
applications = mt.name() == QLatin1String("application/octet-stream") ?
XdgDesktopFileCache::getAllFiles() :
XdgDesktopFileCache::getApps(mt.name());
qSort(applications.begin(), applications.end(), lessThan);
QTreeWidgetItem* headingItem = new QTreeWidgetItem(widget.applicationTreeWidget);
headingItem->setExpanded(true);
headingItem->setFlags(Qt::ItemIsEnabled);
headingItem->setText(0, heading);
headingItem->setSizeHint(0, QSize(0, 25));
addApplicationsToApplicationListWidget(headingItem, applications, addedApps);
}
connect(widget.applicationTreeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(selectionChanged()));
widget.applicationTreeWidget->setFocus();
if (!applicationsThatHandleThisMimetype.isEmpty()) {
widget.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
}
// delay icon update for faster loading
QTimer::singleShot(0, this, SLOT(updateAllIcons()));
}
void ApplicationChooser::addApplicationsToApplicationListWidget(QTreeWidgetItem* parent,
QList<XdgDesktopFile*> applications,
QSet<XdgDesktopFile*>& alreadyAdded)
{
QIcon placeHolderIcon = QIcon::fromTheme("application-x-executable");
if (applications.isEmpty())
{
QTreeWidgetItem* noAppsFoundItem = new QTreeWidgetItem(parent);
noAppsFoundItem->setText(0, tr("No applications found"));
noAppsFoundItem->setFlags(0);
QFont font = noAppsFoundItem->font(0);
font.setStyle(QFont::StyleItalic);
noAppsFoundItem->setFont(0, font);
}
else
{
// Insert applications in the listwidget, skipping already added applications
foreach (XdgDesktopFile* desktopFile, applications)
{
if (alreadyAdded.contains(desktopFile))
continue;
// Only applications
if (desktopFile->type() != XdgDesktopFile::ApplicationType)
continue;
QTreeWidgetItem *item = new QTreeWidgetItem(parent);
item->setIcon(0, placeHolderIcon);
item->setText(0, desktopFile->name());
item->setData(0, 32, QVariant::fromValue<XdgDesktopFile*>(desktopFile));
if (desktopFile == m_CurrentDefaultApplication)
{
widget.applicationTreeWidget->setCurrentItem(item);
}
alreadyAdded.insert(desktopFile);
}
}
}
void ApplicationChooser::selectionChanged()
{
widget.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
QTreeWidgetItem* newItem = widget.applicationTreeWidget->currentItem();
if (newItem && newItem->data(0, 32).value<XdgDesktopFile*>())
{
widget.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
m_CurrentDefaultApplication = newItem->data(0, 32).value<XdgDesktopFile*>();
}
}