File indexing completed on 2024-05-12 16:40:54
0001 /* This file is part of the KDE project 0002 Copyright (C) 2016-2018 Jarosław Staniek <staniek@kde.org> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this program; see the file COPYING. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "KexiFileRequester.h" 0021 #include <KexiFileFilters.h> 0022 #include <kexiutils/utils.h> 0023 #include <KexiIcon.h> 0024 0025 #include <KFileFilterCombo> 0026 #include <KLineEdit> 0027 #include <KLocalizedString> 0028 #include <KUrlComboBox> 0029 #include <KUrlCompletion> 0030 #include <KMessageBox> 0031 0032 #include <QDateTime> 0033 #include <QDebug> 0034 #include <QFileDialog> 0035 #include <QFileInfo> 0036 #include <QFileSystemModel> 0037 #include <QHeaderView> 0038 #include <QLabel> 0039 #include <QMimeDatabase> 0040 #include <QPushButton> 0041 #include <QRegExp> 0042 #include <QSettings> 0043 #include <QStandardPaths> 0044 #include <QTreeView> 0045 #include <QVBoxLayout> 0046 0047 #include <functional> 0048 0049 namespace { 0050 enum KexiFileSystemModelColumnIds { 0051 NameColumnId, 0052 LastModifiedColumnId 0053 }; 0054 } 0055 0056 //! A model for KexiFileRequester 0057 class KexiFileSystemModel : public QFileSystemModel 0058 { 0059 Q_OBJECT 0060 public: 0061 explicit KexiFileSystemModel(QObject *parent = nullptr) 0062 : QFileSystemModel(parent) 0063 { 0064 } 0065 0066 int columnCount(const QModelIndex &parent = QModelIndex()) const override 0067 { 0068 Q_UNUSED(parent) 0069 return LastModifiedColumnId + 1; 0070 } 0071 0072 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override 0073 { 0074 const int col = index.column(); 0075 if (col == NameColumnId) { 0076 switch (role) { 0077 case Qt::DecorationRole: { 0078 if (isDir(index)) { 0079 return koIcon("folder"); 0080 } else { 0081 return QIcon::fromTheme(m_mimeDb.mimeTypeForFile(filePath(index)).iconName()); 0082 } 0083 } 0084 default: break; 0085 } 0086 return QFileSystemModel::data(index, role); 0087 } else if (col == LastModifiedColumnId) { 0088 const QWidget *parentWidget = qobject_cast<QWidget*>(QObject::parent()); 0089 switch (role) { 0090 case Qt::DisplayRole: 0091 return parentWidget->locale().toString(QFileSystemModel::lastModified(index), 0092 QLocale::ShortFormat); 0093 default: 0094 break; 0095 } 0096 } 0097 return QVariant(); 0098 } 0099 0100 Qt::ItemFlags flags(const QModelIndex& index) const override { 0101 Q_UNUSED(index) 0102 return Qt::ItemIsSelectable | Qt::ItemIsEnabled; 0103 } 0104 0105 private: 0106 QMimeDatabase m_mimeDb; 0107 }; 0108 0109 //! @internal 0110 class KexiUrlCompletion : public KUrlCompletion 0111 { 0112 public: 0113 explicit KexiUrlCompletion(QList<QRegExp *> *filterRegExps, QList<QMimeType> *filterMimeTypes) 0114 : KUrlCompletion(KUrlCompletion::FileCompletion) 0115 , m_filterRegExps(filterRegExps) 0116 , m_filterMimeTypes(filterMimeTypes) 0117 { 0118 } 0119 0120 using KUrlCompletion::postProcessMatches; 0121 0122 //! Reimplemented to match the filter 0123 void postProcessMatches(QStringList *matches) const override 0124 { 0125 for (QStringList::Iterator matchIt = matches->begin(); 0126 matchIt != matches->end();) 0127 { 0128 if (fileMatchesFilter(*matchIt)) { 0129 ++matchIt; 0130 } else { 0131 matchIt = matches->erase(matchIt); 0132 } 0133 } 0134 } 0135 0136 private: 0137 /** 0138 * @return @c true if @a fileName matches the current regular expression as well as the mime types 0139 * 0140 * The mime type matching allows to overcome issues with patterns such as *.doc being used 0141 * for text/plain mime types but really belonging to application/msword mime type. 0142 */ 0143 bool fileMatchesFilter(const QString &fileName) const 0144 { 0145 bool found = false; 0146 for (QRegExp *regexp : *m_filterRegExps) { 0147 if (regexp->exactMatch(fileName)) { 0148 found = true; 0149 break; 0150 } 0151 } 0152 if (!found) { 0153 return false; 0154 } 0155 const QMimeType mimeType(m_mimeDb.mimeTypeForFile(fileName)); 0156 qDebug() << mimeType; 0157 int i = m_filterMimeTypes->indexOf(mimeType); 0158 return i >= 0; 0159 } 0160 0161 const QList<QRegExp*> * const m_filterRegExps; 0162 const QList<QMimeType> * const m_filterMimeTypes; 0163 QMimeDatabase m_mimeDb; 0164 }; 0165 0166 //! @internal 0167 class Q_DECL_HIDDEN KexiFileRequester::Private : public QObject 0168 { 0169 Q_OBJECT 0170 public: 0171 Private(KexiFileRequester *r) : q(r) 0172 { 0173 } 0174 0175 ~Private() 0176 { 0177 qDeleteAll(filterRegExps); 0178 } 0179 0180 static QString urlToPath(const QUrl &url) 0181 { 0182 QString filePath = QDir::toNativeSeparators(url.path(QUrl::RemoveScheme | QUrl::PreferLocalFile | QUrl::StripTrailingSlash)); 0183 #ifdef Q_OS_WIN 0184 if (filePath.startsWith('\\')) { 0185 filePath = filePath.mid(1); 0186 } else if (filePath.startsWith("file:\\")) { 0187 filePath = filePath.mid(6); 0188 } 0189 #endif 0190 return filePath; 0191 } 0192 0193 public Q_SLOTS: 0194 void updateUrl(const QUrl &url) 0195 { 0196 updateFileName(urlToPath(url)); 0197 } 0198 0199 void updateFileName(const QString &filePath) 0200 { 0201 const QFileInfo fileInfo(filePath); 0202 QString dirPath; 0203 if (fileInfo.isDir()) { 0204 dirPath = fileInfo.absoluteFilePath(); 0205 } else { 0206 dirPath = fileInfo.absolutePath(); 0207 } 0208 dirPath = QDir::toNativeSeparators(dirPath); 0209 if (filePath.isEmpty()) { // display Windows Explorer's "Computer" folder name for the top level 0210 #ifdef Q_OS_WIN 0211 QString computerNameString = QSettings( 0212 "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\" 0213 "CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0214 QSettings::NativeFormat).value("Default").toString(); 0215 if (computerNameString.isEmpty()) { 0216 computerNameString = xi18n("Computer"); 0217 } 0218 urlLabel->setText(computerNameString); 0219 folderIcon->setPixmap(koSmallIcon("computer")); 0220 upButton->setEnabled(false); 0221 #else 0222 urlLabel->setText("/"); 0223 folderIcon->setPixmap(koSmallIcon("folder")); 0224 upButton->setEnabled(false); 0225 #endif 0226 } else { 0227 urlLabel->setText(dirPath); 0228 folderIcon->setPixmap(koSmallIcon("folder")); 0229 upButton->setEnabled(filePath != "/"); 0230 } 0231 if (model->rootPath() != dirPath) { 0232 model->setRootPath(dirPath); 0233 list->setRootIndex(model->index(dirPath)); 0234 list->resizeColumnToContents(LastModifiedColumnId); 0235 urlCompletion->setDir(QUrl::fromLocalFile(dirPath)); 0236 } 0237 if (!fileInfo.isDir()) { 0238 list->clearSelection(); 0239 const QModelIndex fileIndex = model->index(filePath); 0240 list->scrollTo(fileIndex); 0241 list->selectionModel()->select(fileIndex, QItemSelectionModel::ClearAndSelect); 0242 /*qWarning() << model->rootPath() << fileIndex.isValid() << model->filePath(fileIndex) 0243 << model->fileName(fileIndex) << list->selectionModel()->selection().isEmpty() 0244 << q->filters()->isExistingFileRequired();*/ 0245 const QString newText(QFileInfo(filePath).fileName()); 0246 if (newText != locationEdit->lineEdit()->text()) { 0247 KexiUtils::BoolBlocker guard(&locationEditTextChangedEnabled, false); 0248 locationEdit->lineEdit()->setText(newText); 0249 } 0250 } 0251 } 0252 0253 void itemClicked(const QModelIndex &index) 0254 { 0255 handleItem(index, std::bind(&KexiFileRequester::fileHighlighted, q, std::placeholders::_1), 0256 true); 0257 if (activateItemsOnSingleClick) { 0258 handleItem(index, std::bind(&KexiFileRequester::fileSelected, q, std::placeholders::_1), 0259 false); 0260 } 0261 } 0262 0263 void itemActivated(const QModelIndex &index) 0264 { 0265 if (!activateItemsOnSingleClick) { 0266 handleItem(index, std::bind(&KexiFileRequester::fileSelected, q, std::placeholders::_1), 0267 true); 0268 } 0269 } 0270 0271 void upButtonClicked() 0272 { 0273 QString dirPath(urlLabel->text()); 0274 QDir dir(dirPath); 0275 if (dirPath.isEmpty() || !dir.cdUp()) { 0276 updateFileName(QString()); 0277 } else { 0278 updateFileName(dir.absolutePath()); 0279 } 0280 //! @todo update button enable flag 0281 } 0282 0283 void selectUrlButtonClicked() 0284 { 0285 QUrl dirUrl; 0286 #ifdef Q_OS_WIN 0287 if (!upButton->isEnabled()) { // Computer folder, see https://doc.qt.io/qt-5/qfiledialog.html#setDirectoryUrl 0288 dirUrl = QUrl("clsid:0AC0837C-BBF8-452A-850D-79D08E667CA7"); 0289 } 0290 #else 0291 if (false) { 0292 } 0293 #endif 0294 else { 0295 dirUrl = QUrl::fromLocalFile(urlLabel->text()); 0296 } 0297 QUrl selectedUrl = QFileDialog::getExistingDirectoryUrl(q, QString(), dirUrl); 0298 if (selectedUrl.isLocalFile()) { 0299 updateFileName(selectedUrl.toLocalFile()); 0300 } 0301 } 0302 0303 void locationEditTextChanged(const QString &text) 0304 { 0305 if (!locationEditTextChangedEnabled) { 0306 return; 0307 } 0308 locationEdit->lineEdit()->setModified(true); 0309 if (text.isEmpty()) { 0310 list->clearSelection(); 0311 } 0312 QFileInfo info(model->rootPath() + '/' + text); 0313 if (info.isFile() && model->rootDirectory().exists(text)) { 0314 updateFileName(model->rootDirectory().absoluteFilePath(text)); // select file 0315 } else if (q->filters()->isExistingFileRequired()) { 0316 updateFileName(model->rootPath()); // only dir, unselect file 0317 } else { 0318 updateFileName(info.absoluteFilePath()); // only dir, unselect file 0319 } 0320 } 0321 0322 void locationEditReturnPressed() 0323 { 0324 QString text(locationEdit->lineEdit()->text()); 0325 if (text.isEmpty()) { 0326 return; 0327 } 0328 if (text == QStringLiteral("~")) { 0329 text = QDir::homePath(); 0330 } else if (text.startsWith(QStringLiteral("~/"))) { 0331 text = QDir::home().absoluteFilePath(text.mid(2)); 0332 } 0333 if (QDir::isAbsolutePath(text)) { 0334 QFileInfo info(text); 0335 if (!info.isReadable()) { 0336 return; 0337 } 0338 if (info.isDir()) { // jump to absolute dir and clear the editor 0339 updateFileName(info.canonicalFilePath()); 0340 locationEdit->lineEdit()->clear(); 0341 } else { // jump to absolute dir and select the file in it 0342 updateFileName(info.dir().canonicalPath()); 0343 locationEdit->lineEdit()->setText(info.fileName()); 0344 locationEditReturnPressed(); 0345 } 0346 } else { // relative path 0347 QFileInfo info(model->rootPath() + '/' + text); 0348 if (info.isReadable() && info.isDir()) { // jump to relative dir and clear the editor 0349 updateFileName(info.canonicalFilePath()); 0350 locationEdit->lineEdit()->clear(); 0351 } else { // emit the file selection 0352 //not needed - preselected: updateFileName(text); 0353 emit q->fileSelected(q->selectedFile()); 0354 } 0355 } 0356 } 0357 0358 void slotFilterComboChanged() 0359 { 0360 const QStringList patterns = filterCombo->currentFilter().split(' '); 0361 //qDebug() << patterns; 0362 model->setNameFilters(patterns); 0363 qDeleteAll(filterRegExps); 0364 filterRegExps.clear(); 0365 for (const QString &pattern : patterns) { 0366 filterRegExps.append(new QRegExp(pattern, Qt::CaseInsensitive, QRegExp::Wildcard)); 0367 } 0368 } 0369 0370 //! @todo added to display select filename, still does not work 0371 void directoryLoaded() 0372 { 0373 if (!list->selectionModel()->selectedIndexes().isEmpty()) { 0374 list->scrollTo(list->selectionModel()->selectedIndexes().first()); 0375 } 0376 } 0377 0378 private: 0379 void handleItem(const QModelIndex &index, std::function<void(const QString&)> sig, bool silent) 0380 { 0381 const QString filePath(model->filePath(index)); 0382 if (model->isDir(index)) { 0383 QFileInfo info(filePath); 0384 if (info.isReadable()) { 0385 updateFileName(filePath); 0386 } else { 0387 if (silent) { 0388 KMessageBox::error(q, 0389 xi18n("Could not enter directory <filename>%1</filename>.", 0390 QDir::toNativeSeparators(info.absoluteFilePath()))); 0391 } 0392 } 0393 } else { 0394 emit sig(filePath); 0395 } 0396 } 0397 0398 public: 0399 KexiFileRequester* const q; 0400 QPushButton *upButton; 0401 QLabel *folderIcon; 0402 QLabel *urlLabel; 0403 QPushButton *selectUrlButton; 0404 KexiFileSystemModel *model; 0405 QTreeView *list; 0406 bool activateItemsOnSingleClick; 0407 KUrlComboBox *locationEdit; 0408 KexiUrlCompletion *urlCompletion; 0409 KFileFilterCombo *filterCombo; 0410 QList<QRegExp*> filterRegExps; //!< Regular expression for the completer in the URL box 0411 QList<QMimeType> filterMimeTypes; 0412 bool locationEditTextChangedEnabled = true; 0413 }; 0414 0415 KexiFileRequester::KexiFileRequester(const QUrl &fileOrVariable, KexiFileFilters::Mode mode, 0416 const QString &fileName, QWidget *parent) 0417 : QWidget(parent), KexiFileWidgetInterface(fileOrVariable, fileName), d(new Private(this)) 0418 { 0419 init(); 0420 const QString actualFileName = Private::urlToPath(startUrl()); 0421 setMode(mode); 0422 d->updateFileName(actualFileName); // note: we had to call it after setMode(), not before 0423 } 0424 0425 KexiFileRequester::KexiFileRequester(const QUrl &fileOrVariable, KexiFileFilters::Mode mode, 0426 QWidget *parent) 0427 : KexiFileRequester(fileOrVariable, mode, QString(), parent) 0428 { 0429 } 0430 0431 KexiFileRequester::KexiFileRequester(const QString &selectedFileName, KexiFileFilters::Mode mode, 0432 QWidget *parent) 0433 : QWidget(parent) 0434 , KexiFileWidgetInterface(QUrl(selectedFileName), QString()) 0435 , d(new Private(this)) 0436 { 0437 init(); 0438 setMode(mode); 0439 d->updateFileName(selectedFileName); // note: we had to call it after setMode(), not before 0440 } 0441 0442 KexiFileRequester::~KexiFileRequester() 0443 { 0444 const QString startDir(d->urlLabel->text()); 0445 addRecentDir(startDir); 0446 delete d; 0447 } 0448 0449 void KexiFileRequester::init() 0450 { 0451 // [^] [Dir ][..] 0452 // [ files list ] 0453 // [ location ] 0454 // [ filter combo ] 0455 QVBoxLayout *lyr = new QVBoxLayout(this); 0456 setContentsMargins(QMargins()); 0457 lyr->setContentsMargins(QMargins()); 0458 QHBoxLayout *urlLyr = new QHBoxLayout; 0459 urlLyr->setContentsMargins(QMargins()); 0460 lyr->addLayout(urlLyr); 0461 0462 d->upButton = new QPushButton; 0463 d->upButton->setFocusPolicy(Qt::NoFocus); 0464 d->upButton->setIcon(koIcon("go-up")); 0465 d->upButton->setToolTip(xi18n("Go to parent directory")); 0466 d->upButton->setFlat(true); 0467 connect(d->upButton, &QPushButton::clicked, d, &KexiFileRequester::Private::upButtonClicked); 0468 urlLyr->addWidget(d->upButton); 0469 0470 d->folderIcon = new QLabel; 0471 urlLyr->addWidget(d->folderIcon); 0472 0473 d->urlLabel = new QLabel; 0474 d->urlLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); 0475 d->urlLabel->setWordWrap(true); 0476 d->urlLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); 0477 urlLyr->addWidget(d->urlLabel, 1); 0478 0479 d->selectUrlButton = new QPushButton; 0480 d->selectUrlButton->setFocusPolicy(Qt::NoFocus); 0481 d->selectUrlButton->setIcon(koIcon("folder")); 0482 d->selectUrlButton->setToolTip(xi18n("Select directory")); 0483 d->selectUrlButton->setFlat(true); 0484 connect(d->selectUrlButton, &QPushButton::clicked, d, &KexiFileRequester::Private::selectUrlButtonClicked); 0485 urlLyr->addWidget(d->selectUrlButton); 0486 0487 d->list = new QTreeView; 0488 d->activateItemsOnSingleClick = KexiUtils::activateItemsOnSingleClick(d->list); 0489 connect(d->list, &QTreeView::clicked, d, &KexiFileRequester::Private::itemClicked); 0490 connect(d->list, &QTreeView::activated, d, &KexiFileRequester::Private::itemActivated); 0491 d->list->setRootIsDecorated(false); 0492 d->list->setItemsExpandable(false); 0493 d->list->header()->hide(); 0494 lyr->addWidget(d->list); 0495 d->model = new KexiFileSystemModel(d->list); 0496 d->model->setNameFilterDisables(false); 0497 connect(d->model, &QFileSystemModel::directoryLoaded, d, &Private::directoryLoaded); 0498 0499 d->list->setModel(d->model); 0500 d->list->header()->setStretchLastSection(false); 0501 d->list->header()->setSectionResizeMode(NameColumnId, QHeaderView::Stretch); 0502 d->list->header()->setSectionResizeMode(LastModifiedColumnId, QHeaderView::ResizeToContents); 0503 0504 QGridLayout *bottomLyr = new QGridLayout; 0505 lyr->addLayout(bottomLyr); 0506 0507 QLabel *locationLabel = new QLabel(xi18n("Name:")); 0508 bottomLyr->addWidget(locationLabel, 0, 0, Qt::AlignVCenter | Qt::AlignRight); 0509 d->locationEdit = new KUrlComboBox(KUrlComboBox::Files, true); 0510 setFocusProxy(d->locationEdit); 0511 d->locationEdit->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); 0512 connect(d->locationEdit, &KUrlComboBox::editTextChanged, d, 0513 &KexiFileRequester::Private::locationEditTextChanged); 0514 #if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) 0515 connect(d->locationEdit, QOverload<>::of(&KUrlComboBox::returnPressed), 0516 d, &Private::locationEditReturnPressed); 0517 #else 0518 connect(d->locationEdit, static_cast<void (KUrlComboBox::*)()>(&KUrlComboBox::returnPressed), 0519 d, &Private::locationEditReturnPressed); 0520 #endif 0521 d->urlCompletion = new KexiUrlCompletion(&d->filterRegExps, &d->filterMimeTypes); 0522 d->locationEdit->setCompletionObject(d->urlCompletion); 0523 d->locationEdit->setAutoDeleteCompletionObject(true); 0524 d->locationEdit->lineEdit()->setClearButtonEnabled(true); 0525 locationLabel->setBuddy(d->locationEdit); 0526 bottomLyr->addWidget(d->locationEdit, 0, 1, Qt::AlignVCenter); 0527 0528 QLabel *filterLabel = new QLabel(xi18n("Filter:")); 0529 bottomLyr->addWidget(filterLabel, 1, 0, Qt::AlignVCenter | Qt::AlignRight); 0530 d->filterCombo = new KFileFilterCombo; 0531 connect(d->filterCombo, &KFileFilterCombo::filterChanged, 0532 d, &Private::slotFilterComboChanged); 0533 filterLabel->setBuddy(d->filterCombo); 0534 bottomLyr->addWidget(d->filterCombo, 1, 1, Qt::AlignVCenter); 0535 } 0536 0537 QString KexiFileRequester::selectedFile() const 0538 { 0539 const QModelIndexList list(d->list->selectionModel()->selectedIndexes()); 0540 if (list.isEmpty() || d->model->isDir(list.first())) { // no file selection but try entered filename 0541 const QString text(d->locationEdit->lineEdit()->text().trimmed()); 0542 if (!text.isEmpty() && !filters()->isExistingFileRequired()) { 0543 const QFileInfo info(currentDir() + '/' + text); 0544 if (info.isNativePath()) { 0545 return info.absoluteFilePath(); 0546 } 0547 } 0548 return QString(); 0549 } 0550 if (d->model->isDir(list.first())) { 0551 return QString(); 0552 } 0553 return d->model->filePath(list.first()); 0554 } 0555 0556 QString KexiFileRequester::highlightedFile() const 0557 { 0558 return selectedFile(); 0559 } 0560 0561 QString KexiFileRequester::currentDir() const 0562 { 0563 return d->model->rootPath(); 0564 } 0565 0566 void KexiFileRequester::setSelectedFile(const QString &name) 0567 { 0568 d->updateFileName(name); 0569 } 0570 0571 void KexiFileRequester::updateFilters() 0572 { 0573 // Update filters for the file model, filename completion and the filter combo 0574 const QStringList patterns = filters()->allGlobPatterns(); 0575 if (patterns != d->model->nameFilters()) { 0576 d->model->setNameFilters(patterns); 0577 qDeleteAll(d->filterRegExps); 0578 d->filterRegExps.clear(); 0579 for (const QString &pattern : patterns) { 0580 d->filterRegExps.append(new QRegExp(pattern, Qt::CaseInsensitive, QRegExp::Wildcard)); 0581 } 0582 d->filterMimeTypes = filters()->mimeTypes(); 0583 KexiFileFiltersFormat format; 0584 format.type = KexiFileFiltersFormat::Type::KDE; 0585 format.addAllFiles = true; 0586 d->filterCombo->setFilter(filters()->toString(format)); 0587 } 0588 } 0589 0590 void KexiFileRequester::setWidgetFrame(bool set) 0591 { 0592 d->list->setFrameShape(set ? QFrame::StyledPanel : QFrame::NoFrame); 0593 d->list->setLineWidth(set ? 1 : 0); 0594 } 0595 0596 void KexiFileRequester::applyEnteredFileName() 0597 { 0598 } 0599 0600 QStringList KexiFileRequester::currentFilters() const 0601 { 0602 return QStringList(); 0603 } 0604 0605 void KexiFileRequester::showEvent(QShowEvent *event) 0606 { 0607 setFiltersUpdated(false); 0608 updateFilters(); 0609 QWidget::showEvent(event); 0610 } 0611 0612 #include "KexiFileRequester.moc"