File indexing completed on 2024-05-12 03:55:46
0001 /* vi: ts=8 sts=4 sw=4 0002 0003 This file is part of the KDE project, module kfile. 0004 SPDX-FileCopyrightText: 2000 Geert Jansen <jansen@kde.org> 0005 SPDX-FileCopyrightText: 2000 Kurt Granroth <granroth@kde.org> 0006 SPDX-FileCopyrightText: 1997 Christoph Neerfeld <chris@kde.org> 0007 SPDX-FileCopyrightText: 2002 Carsten Pfeiffer <pfeiffer@kde.org> 0008 SPDX-FileCopyrightText: 2021 Kai Uwe Broulik <kde@broulik.de> 0009 0010 SPDX-License-Identifier: LGPL-2.0-only 0011 */ 0012 0013 #include "kicondialog.h" 0014 #include "kicondialog_p.h" 0015 #include "kicondialogmodel_p.h" 0016 0017 #include <KLazyLocalizedString> 0018 #include <KLocalizedString> 0019 #include <KStandardAction> 0020 0021 #include <QAbstractListModel> 0022 #include <QApplication> 0023 #include <QComboBox> 0024 #include <QDialogButtonBox> 0025 #include <QFileInfo> 0026 #include <QGraphicsOpacityEffect> 0027 #include <QLabel> 0028 #include <QList> 0029 #include <QPainter> 0030 #include <QScrollBar> 0031 #include <QStandardItemModel> // for manipulatig QComboBox 0032 #include <QStandardPaths> 0033 #include <QSvgRenderer> 0034 0035 #include <algorithm> 0036 #include <math.h> 0037 0038 static const int s_edgePad = 3; 0039 0040 KIconDialogModel::KIconDialogModel(KIconLoader *loader, QObject *parent) 0041 : QAbstractListModel(parent) 0042 , m_loader(loader) 0043 { 0044 } 0045 0046 KIconDialogModel::~KIconDialogModel() = default; 0047 0048 qreal KIconDialogModel::devicePixelRatio() const 0049 { 0050 return m_dpr; 0051 } 0052 0053 void KIconDialogModel::setDevicePixelRatio(qreal dpr) 0054 { 0055 m_dpr = dpr; 0056 } 0057 0058 QSize KIconDialogModel::iconSize() const 0059 { 0060 return m_iconSize; 0061 } 0062 0063 void KIconDialogModel::setIconSize(const QSize &iconSize) 0064 { 0065 m_iconSize = iconSize; 0066 } 0067 0068 void KIconDialogModel::load(const QStringList &paths) 0069 { 0070 beginResetModel(); 0071 0072 m_data.clear(); 0073 m_data.reserve(paths.count()); 0074 0075 for (const QString &path : paths) { 0076 const QFileInfo fi(path); 0077 0078 KIconDialogModelData item; 0079 item.name = fi.completeBaseName(); 0080 item.path = path; 0081 // pixmap is created on demand 0082 0083 m_data.append(item); 0084 } 0085 0086 endResetModel(); 0087 } 0088 0089 int KIconDialogModel::rowCount(const QModelIndex &parent) const 0090 { 0091 if (parent.isValid()) { 0092 return 0; 0093 } 0094 return m_data.count(); 0095 } 0096 0097 QVariant KIconDialogModel::data(const QModelIndex &index, int role) const 0098 { 0099 if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid)) { 0100 return QVariant(); 0101 } 0102 0103 const auto &item = m_data.at(index.row()); 0104 0105 switch (role) { 0106 case Qt::DisplayRole: 0107 return item.name; 0108 case Qt::DecorationRole: 0109 if (item.pixmap.isNull()) { 0110 const_cast<KIconDialogModel *>(this)->loadPixmap(index); 0111 } 0112 return item.pixmap; 0113 case Qt::ToolTipRole: 0114 return item.name; 0115 case PathRole: 0116 return item.path; 0117 } 0118 0119 return QVariant(); 0120 } 0121 0122 void KIconDialogModel::loadPixmap(const QModelIndex &index) 0123 { 0124 Q_ASSERT(index.isValid()); 0125 0126 auto &item = m_data[index.row()]; 0127 Q_ASSERT(item.pixmap.isNull()); 0128 0129 const auto dpr = devicePixelRatio(); 0130 0131 item.pixmap = m_loader->loadScaledIcon(item.path, KIconLoader::Desktop, dpr, iconSize(), KIconLoader::DefaultState, {}, nullptr, true); 0132 item.pixmap.setDevicePixelRatio(dpr); 0133 } 0134 0135 /** 0136 * Qt allocates very little horizontal space for the icon name, 0137 * even if the gridSize width is large. This delegate allocates 0138 * the gridSize width (minus some padding) for the icon and icon name. 0139 */ 0140 class KIconCanvasDelegate : public QAbstractItemDelegate 0141 { 0142 Q_OBJECT 0143 public: 0144 KIconCanvasDelegate(QListView *parent, QAbstractItemDelegate *defaultDelegate); 0145 ~KIconCanvasDelegate() override 0146 { 0147 } 0148 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; 0149 QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; 0150 0151 private: 0152 QAbstractItemDelegate *m_defaultDelegate = nullptr; 0153 }; 0154 0155 KIconCanvasDelegate::KIconCanvasDelegate(QListView *parent, QAbstractItemDelegate *defaultDelegate) 0156 : QAbstractItemDelegate(parent) 0157 { 0158 m_defaultDelegate = defaultDelegate; 0159 } 0160 0161 void KIconCanvasDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 0162 { 0163 auto *canvas = static_cast<QListView *>(parent()); 0164 const int gridWidth = canvas->gridSize().width(); 0165 QStyleOptionViewItem newOption = option; 0166 newOption.displayAlignment = Qt::AlignHCenter | Qt::AlignTop; 0167 newOption.features.setFlag(QStyleOptionViewItem::WrapText); 0168 // Manipulate the width available. 0169 newOption.rect.setX((option.rect.x() / gridWidth) * gridWidth + s_edgePad); 0170 newOption.rect.setY(option.rect.y() + s_edgePad); 0171 newOption.rect.setWidth(gridWidth - 2 * s_edgePad); 0172 newOption.rect.setHeight(option.rect.height() - 2 * s_edgePad); 0173 m_defaultDelegate->paint(painter, newOption, index); 0174 } 0175 0176 QSize KIconCanvasDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 0177 { 0178 auto *canvas = static_cast<QListView *>(parent()); 0179 0180 // TODO can we set wrap text and display alignment somewhere globally? 0181 QStyleOptionViewItem newOption = option; 0182 newOption.displayAlignment = Qt::AlignHCenter | Qt::AlignTop; 0183 newOption.features.setFlag(QStyleOptionViewItem::WrapText); 0184 0185 QSize size = m_defaultDelegate->sizeHint(newOption, index); 0186 const int gridWidth = canvas->gridSize().width(); 0187 const int gridHeight = canvas->gridSize().height(); 0188 size.setWidth(gridWidth - 2 * s_edgePad); 0189 size.setHeight(gridHeight - 2 * s_edgePad); 0190 QFontMetrics metrics(option.font); 0191 size.setHeight(gridHeight + metrics.height() * 3); 0192 return size; 0193 } 0194 0195 KIconDialogPrivate::KIconDialogPrivate(KIconDialog *qq) 0196 : q(qq) 0197 , mpLoader(KIconLoader::global()) 0198 , model(new KIconDialogModel(mpLoader, qq)) 0199 , proxyModel(new QSortFilterProxyModel(qq)) 0200 { 0201 proxyModel->setSourceModel(model); 0202 proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); 0203 } 0204 0205 /* 0206 * KIconDialog: Dialog for selecting icons. Both system and user 0207 * specified icons can be chosen. 0208 */ 0209 0210 KIconDialog::KIconDialog(QWidget *parent) 0211 : QDialog(parent) 0212 , d(new KIconDialogPrivate(this)) 0213 { 0214 setModal(true); 0215 0216 d->init(); 0217 } 0218 0219 void KIconDialogPrivate::init() 0220 { 0221 mGroupOrSize = KIconLoader::Desktop; 0222 mContext = KIconLoader::Any; 0223 0224 ui.setupUi(q); 0225 0226 auto updatePlaceholder = [this] { 0227 updatePlaceholderLabel(); 0228 }; 0229 QObject::connect(proxyModel, &QSortFilterProxyModel::modelReset, q, updatePlaceholder); 0230 QObject::connect(proxyModel, &QSortFilterProxyModel::rowsInserted, q, updatePlaceholder); 0231 QObject::connect(proxyModel, &QSortFilterProxyModel::rowsRemoved, q, updatePlaceholder); 0232 0233 QAction *findAction = KStandardAction::find(ui.searchLine, qOverload<>(&QWidget::setFocus), q); 0234 q->addAction(findAction); 0235 0236 QObject::connect(ui.searchLine, &QLineEdit::textChanged, proxyModel, &QSortFilterProxyModel::setFilterFixedString); 0237 0238 static const KLazyLocalizedString context_text[] = { 0239 kli18n("All"), 0240 kli18n("Actions"), 0241 kli18n("Applications"), 0242 kli18n("Categories"), 0243 kli18n("Devices"), 0244 kli18n("Emblems"), 0245 kli18n("Emotes"), 0246 kli18n("Mimetypes"), 0247 kli18n("Places"), 0248 kli18n("Status"), 0249 }; 0250 static const KIconLoader::Context context_id[] = { 0251 KIconLoader::Any, 0252 KIconLoader::Action, 0253 KIconLoader::Application, 0254 KIconLoader::Category, 0255 KIconLoader::Device, 0256 KIconLoader::Emblem, 0257 KIconLoader::Emote, 0258 KIconLoader::MimeType, 0259 KIconLoader::Place, 0260 KIconLoader::StatusIcon, 0261 }; 0262 const int cnt = sizeof(context_text) / sizeof(context_text[0]); 0263 for (int i = 0; i < cnt; ++i) { 0264 if (mpLoader->hasContext(context_id[i])) { 0265 ui.contextCombo->addItem(context_text[i].toString(), context_id[i]); 0266 if (i == 0) { 0267 ui.contextCombo->insertSeparator(i + 1); 0268 } 0269 } 0270 } 0271 ui.contextCombo->insertSeparator(ui.contextCombo->count()); 0272 ui.contextCombo->addItem(i18nc("Other icons", "Other")); 0273 ui.contextCombo->setMaxVisibleItems(ui.contextCombo->count()); 0274 ui.contextCombo->setFixedSize(ui.contextCombo->sizeHint()); 0275 0276 QObject::connect(ui.contextCombo, qOverload<int>(&QComboBox::activated), q, [this]() { 0277 const auto currentData = ui.contextCombo->currentData(); 0278 if (currentData.isValid()) { 0279 mContext = static_cast<KIconLoader::Context>(ui.contextCombo->currentData().toInt()); 0280 } else { 0281 mContext = static_cast<KIconLoader::Context>(-1); 0282 } 0283 showIcons(); 0284 }); 0285 0286 auto *delegate = new KIconCanvasDelegate(ui.canvas, ui.canvas->itemDelegate()); 0287 ui.canvas->setItemDelegate(delegate); 0288 0289 ui.canvas->setModel(proxyModel); 0290 0291 QObject::connect(ui.canvas, &QAbstractItemView::activated, q, [this]() { 0292 custom.clear(); 0293 q->slotOk(); 0294 }); 0295 0296 // You can't just stack widgets on top of each other in Qt Designer 0297 auto *placeholderLayout = new QVBoxLayout(ui.canvas); 0298 0299 placeholderLabel = new QLabel(); 0300 QFont placeholderLabelFont; 0301 // To match the size of a level 2 Heading/KTitleWidget 0302 placeholderLabelFont.setPointSize(qRound(placeholderLabelFont.pointSize() * 1.3)); 0303 placeholderLabel->setFont(placeholderLabelFont); 0304 placeholderLabel->setTextInteractionFlags(Qt::NoTextInteraction); 0305 placeholderLabel->setWordWrap(true); 0306 placeholderLabel->setAlignment(Qt::AlignCenter); 0307 0308 // Match opacity of QML placeholder label component 0309 auto *effect = new QGraphicsOpacityEffect(placeholderLabel); 0310 effect->setOpacity(0.5); 0311 placeholderLabel->setGraphicsEffect(effect); 0312 0313 updatePlaceholderLabel(); 0314 0315 placeholderLayout->addWidget(placeholderLabel); 0316 placeholderLayout->setAlignment(placeholderLabel, Qt::AlignCenter); 0317 0318 // TODO I bet there is a KStandardAction for that? 0319 browseButton = new QPushButton(QIcon::fromTheme(QStringLiteral("folder-open")), i18n("Browse…")); 0320 // TODO does this have implicatons? I just want the "Browse" button on the left side :) 0321 ui.buttonBox->addButton(browseButton, QDialogButtonBox::HelpRole); 0322 QObject::connect(browseButton, &QPushButton::clicked, q, [this] { 0323 browse(); 0324 }); 0325 0326 QObject::connect(ui.buttonBox, &QDialogButtonBox::accepted, q, &KIconDialog::slotOk); 0327 QObject::connect(ui.buttonBox, &QDialogButtonBox::rejected, q, &QDialog::reject); 0328 0329 q->adjustSize(); 0330 } 0331 0332 KIconDialog::~KIconDialog() = default; 0333 0334 static bool sortByFileName(const QString &path1, const QString &path2) 0335 { 0336 const QString fileName1 = path1.mid(path1.lastIndexOf(QLatin1Char('/')) + 1); 0337 const QString fileName2 = path2.mid(path2.lastIndexOf(QLatin1Char('/')) + 1); 0338 return QString::compare(fileName1, fileName2, Qt::CaseInsensitive) < 0; 0339 } 0340 0341 void KIconDialogPrivate::showIcons() 0342 { 0343 QStringList filelist; 0344 if (isSystemIconsContext()) { 0345 if (m_bStrictIconSize) { 0346 filelist = mpLoader->queryIcons(mGroupOrSize, mContext); 0347 } else { 0348 filelist = mpLoader->queryIconsByContext(mGroupOrSize, mContext); 0349 } 0350 } else if (!customLocation.isEmpty()) { 0351 filelist = mpLoader->queryIconsByDir(customLocation); 0352 } else { 0353 // List PNG files found directly in the kiconload search paths. 0354 const QStringList pngNameFilter(QStringLiteral("*.png")); 0355 for (const QString &relDir : KIconLoader::global()->searchPaths()) { 0356 const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, relDir, QStandardPaths::LocateDirectory); 0357 for (const QString &dir : dirs) { 0358 const auto files = QDir(dir).entryList(pngNameFilter); 0359 for (const QString &fileName : files) { 0360 filelist << dir + QLatin1Char('/') + fileName; 0361 } 0362 } 0363 } 0364 } 0365 0366 std::sort(filelist.begin(), filelist.end(), sortByFileName); 0367 0368 // The KIconCanvas has uniformItemSizes set which really expects 0369 // all added icons to be the same size, otherwise weirdness ensues :) 0370 // Ensure all SVGs are scaled to the desired size and that as few icons 0371 // need to be padded as possible by specifying a sensible size. 0372 if (mGroupOrSize < -1) { 0373 // mGroupOrSize can be -1 if NoGroup is chosen. 0374 // Explicit size. 0375 ui.canvas->setIconSize(QSize(-mGroupOrSize, -mGroupOrSize)); 0376 } else { 0377 // Icon group. 0378 int groupSize = mpLoader->currentSize(static_cast<KIconLoader::Group>(mGroupOrSize)); 0379 ui.canvas->setIconSize(QSize(groupSize, groupSize)); 0380 } 0381 0382 // Try to make room for three lines of text... 0383 QFontMetrics metrics(ui.canvas->font()); 0384 const int frameHMargin = ui.canvas->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, ui.canvas) + 1; 0385 const int lineCount = 3; 0386 ui.canvas->setGridSize(QSize(100, ui.canvas->iconSize().height() + lineCount * metrics.height() + 3 * frameHMargin)); 0387 0388 // Set a minimum size of 6x3 icons 0389 const int columnCount = 6; 0390 const int rowCount = 3; 0391 QStyleOption opt; 0392 opt.initFrom(ui.canvas); 0393 int width = columnCount * ui.canvas->gridSize().width(); 0394 width += ui.canvas->verticalScrollBar()->sizeHint().width() + 1; 0395 width += 2 * ui.canvas->frameWidth(); 0396 if (ui.canvas->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, ui.canvas)) { 0397 width += ui.canvas->style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, ui.canvas); 0398 } 0399 int height = rowCount * ui.canvas->gridSize().height() + 1; 0400 height += 2 * ui.canvas->frameWidth(); 0401 0402 ui.canvas->setMinimumSize(QSize(width, height)); 0403 0404 model->setIconSize(ui.canvas->iconSize()); 0405 model->setDevicePixelRatio(q->devicePixelRatioF()); 0406 model->load(filelist); 0407 0408 if (!pendingSelectedIcon.isEmpty()) { 0409 selectIcon(pendingSelectedIcon); 0410 pendingSelectedIcon.clear(); 0411 } 0412 } 0413 0414 bool KIconDialogPrivate::selectIcon(const QString &iconName) 0415 { 0416 for (int i = 0; i < proxyModel->rowCount(); ++i) { 0417 const QModelIndex idx = proxyModel->index(i, 0); 0418 0419 QString name = idx.data(KIconDialogModel::PathRole).toString(); 0420 if (!name.isEmpty() && isSystemIconsContext()) { 0421 const QFileInfo fi(name); 0422 name = fi.completeBaseName(); 0423 } 0424 0425 if (iconName == name) { 0426 ui.canvas->setCurrentIndex(idx); 0427 return true; 0428 } 0429 } 0430 0431 return false; 0432 } 0433 0434 void KIconDialog::setStrictIconSize(bool b) 0435 { 0436 d->m_bStrictIconSize = b; 0437 } 0438 0439 bool KIconDialog::strictIconSize() const 0440 { 0441 return d->m_bStrictIconSize; 0442 } 0443 0444 void KIconDialog::setIconSize(int size) 0445 { 0446 // see KIconLoader, if you think this is weird 0447 if (size == 0) { 0448 d->mGroupOrSize = KIconLoader::Desktop; // default Group 0449 } else { 0450 d->mGroupOrSize = -size; // yes, KIconLoader::queryIconsByContext is weird 0451 } 0452 } 0453 0454 int KIconDialog::iconSize() const 0455 { 0456 // 0 or any other value ==> mGroupOrSize is a group, so we return 0 0457 return (d->mGroupOrSize < 0) ? -d->mGroupOrSize : 0; 0458 } 0459 0460 void KIconDialog::setSelectedIcon(const QString &iconName) 0461 { 0462 // TODO Update live when dialog is already open 0463 d->pendingSelectedIcon = iconName; 0464 } 0465 0466 void KIconDialog::setup(KIconLoader::Group group, KIconLoader::Context context, bool strictIconSize, int iconSize, bool user, bool lockUser, bool lockCustomDir) 0467 { 0468 d->m_bStrictIconSize = strictIconSize; 0469 d->m_bLockUser = lockUser; 0470 d->m_bLockCustomDir = lockCustomDir; 0471 if (iconSize == 0) { 0472 if (group == KIconLoader::NoGroup) { 0473 // NoGroup has numeric value -1, which should 0474 // not really be used with KIconLoader::queryIcons*(...); 0475 // pick a proper group. 0476 d->mGroupOrSize = KIconLoader::Small; 0477 } else { 0478 d->mGroupOrSize = group; 0479 } 0480 } else { 0481 d->mGroupOrSize = -iconSize; 0482 } 0483 0484 if (user) { 0485 d->ui.contextCombo->setCurrentIndex(d->ui.contextCombo->count() - 1); 0486 } else { 0487 d->setContext(context); 0488 } 0489 0490 d->ui.contextCombo->setEnabled(!user || !lockUser); 0491 0492 // Disable "Other" entry when user is locked 0493 auto *model = qobject_cast<QStandardItemModel *>(d->ui.contextCombo->model()); 0494 auto *otherItem = model->item(model->rowCount() - 1); 0495 auto flags = otherItem->flags(); 0496 flags.setFlag(Qt::ItemIsEnabled, !lockUser); 0497 otherItem->setFlags(flags); 0498 0499 // Only allow browsing when explicitly allowed and user icons are allowed 0500 // An app may not expect a path when asking only about system icons 0501 d->browseButton->setVisible(!lockCustomDir && (!user || !lockUser)); 0502 } 0503 0504 void KIconDialogPrivate::setContext(KIconLoader::Context context) 0505 { 0506 mContext = context; 0507 const int index = ui.contextCombo->findData(context); 0508 if (index > -1) { 0509 ui.contextCombo->setCurrentIndex(index); 0510 } 0511 } 0512 0513 void KIconDialogPrivate::updatePlaceholderLabel() 0514 { 0515 if (proxyModel->rowCount() > 0) { 0516 placeholderLabel->hide(); 0517 return; 0518 } 0519 0520 if (!ui.searchLine->text().isEmpty()) { 0521 placeholderLabel->setText(i18n("No icons matching the search")); 0522 } else { 0523 placeholderLabel->setText(i18n("No icons in this category")); 0524 } 0525 0526 placeholderLabel->show(); 0527 } 0528 0529 void KIconDialog::setCustomLocation(const QString &location) 0530 { 0531 d->customLocation = location; 0532 } 0533 0534 QString KIconDialog::openDialog() 0535 { 0536 if (exec() == Accepted) { 0537 if (!d->custom.isEmpty()) { 0538 return d->custom; 0539 } 0540 0541 const QString name = d->ui.canvas->currentIndex().data(KIconDialogModel::PathRole).toString(); 0542 if (name.isEmpty() || !d->ui.contextCombo->currentData().isValid()) { 0543 return name; 0544 } 0545 0546 QFileInfo fi(name); 0547 return fi.completeBaseName(); 0548 } 0549 0550 return QString(); 0551 } 0552 0553 void KIconDialog::showDialog() 0554 { 0555 setModal(false); 0556 show(); 0557 } 0558 0559 void KIconDialog::slotOk() 0560 { 0561 QString name; 0562 if (!d->custom.isEmpty()) { 0563 name = d->custom; 0564 } else { 0565 name = d->ui.canvas->currentIndex().data(KIconDialogModel::PathRole).toString(); 0566 if (!name.isEmpty() && d->isSystemIconsContext()) { 0567 const QFileInfo fi(name); 0568 name = fi.completeBaseName(); 0569 } 0570 } 0571 0572 Q_EMIT newIconName(name); 0573 QDialog::accept(); 0574 } 0575 0576 void KIconDialog::showEvent(QShowEvent *event) 0577 { 0578 QDialog::showEvent(event); 0579 d->showIcons(); 0580 d->ui.searchLine->setFocus(); 0581 } 0582 0583 QString KIconDialog::getIcon(KIconLoader::Group group, 0584 KIconLoader::Context context, 0585 bool strictIconSize, 0586 int iconSize, 0587 bool user, 0588 QWidget *parent, 0589 const QString &title) 0590 { 0591 KIconDialog dlg(parent); 0592 dlg.setup(group, context, strictIconSize, iconSize, user); 0593 if (!title.isEmpty()) { 0594 dlg.setWindowTitle(title); 0595 } 0596 0597 return dlg.openDialog(); 0598 } 0599 0600 void KIconDialogPrivate::browse() 0601 { 0602 if (browseDialog) { 0603 browseDialog.data()->show(); 0604 browseDialog.data()->raise(); 0605 return; 0606 } 0607 0608 // Create a file dialog to select an ICO, PNG, XPM or SVG file, 0609 // with the image previewer shown. 0610 QFileDialog *dlg = new QFileDialog(q, i18n("Select Icon"), QString(), i18n("*.ico *.png *.xpm *.svg *.svgz|Icon Files (*.ico *.png *.xpm *.svg *.svgz)")); 0611 // TODO This was deliberately modal before, why? Or just because "window modal" wasn't a thing? 0612 dlg->setWindowModality(Qt::WindowModal); 0613 dlg->setFileMode(QFileDialog::ExistingFile); 0614 QObject::connect(dlg, &QFileDialog::fileSelected, q, [this](const QString &path) { 0615 if (!path.isEmpty()) { 0616 custom = path; 0617 if (isSystemIconsContext()) { 0618 customLocation = QFileInfo(custom).absolutePath(); 0619 } 0620 q->slotOk(); 0621 } 0622 }); 0623 browseDialog = dlg; 0624 dlg->show(); 0625 } 0626 0627 bool KIconDialogPrivate::isSystemIconsContext() const 0628 { 0629 return ui.contextCombo->currentData().isValid(); 0630 } 0631 0632 #include "kicondialog.moc" 0633 #include "moc_kicondialog.cpp" 0634 #include "moc_kicondialogmodel_p.cpp"