File indexing completed on 2024-05-19 12:55:40

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003-2018 Jarosław Staniek <staniek@kde.org>
0003 
0004    This library 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 library 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 library; see the file COPYING.LIB.  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 "KexiFileWidget.h"
0021 #include <kexi_global.h>
0022 #include <core/kexi.h>
0023 #include <core/KexiMainWindowIface.h>
0024 #include <core/KexiMigrateManagerInterface.h>
0025 #include <kexiutils/utils.h>
0026 
0027 #include <KDbDriver>
0028 #include <KDbUtils>
0029 
0030 #include <KActionCollection>
0031 #include <KDirOperator>
0032 #include <KFile>
0033 #include <KFileFilterCombo>
0034 #include <KLocalizedString>
0035 #include <KMessageBox>
0036 #include <KUrlComboBox>
0037 
0038 #include <QAction>
0039 #include <QApplication>
0040 #include <QDebug>
0041 #include <QEvent>
0042 #include <QFileDialog>
0043 #include <QKeyEvent>
0044 #include <QLineEdit>
0045 #include <QLocale>
0046 #include <QMimeDatabase>
0047 #include <QMimeType>
0048 #include <QPushButton>
0049 
0050 //! @internal
0051 class Q_DECL_HIDDEN KexiFileWidget::Private
0052 {
0053 public:
0054     Private()
0055     {
0056     }
0057     QUrl selectedUrl;
0058 };
0059 
0060 //------------------
0061 
0062 static QUrl startDirWithFileName(const QUrl &startDirOrVariable, const QString &fileName)
0063 {
0064     QUrl result = startDirOrVariable;
0065     if (!fileName.isEmpty()) {
0066         result.setPath(result.path() + '/' + fileName);
0067     }
0068     return result;
0069 }
0070 
0071 KexiFileWidget::KexiFileWidget(const QUrl &startDirOrVariable, KexiFileFilters::Mode mode,
0072                                const QString &fileName, QWidget *parent)
0073     : KFileWidget(startDirWithFileName(startDirOrVariable, fileName), parent)
0074     , KexiFileWidgetInterface(startDirOrVariable, fileName)
0075     , d(new Private)
0076 {
0077     setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
0078     QAction *previewAction = dirOperator()->actionCollection()->action("preview");
0079     if (previewAction) {
0080         previewAction->setChecked(false);
0081     }
0082     setFocusProxy(locationEdit());
0083     connect(this, &KFileWidget::fileHighlighted, this, &KexiFileWidget::slotFileHighlighted);
0084     setMode(mode);
0085 }
0086 
0087 KexiFileWidget::KexiFileWidget(const QUrl &startDirOrVariable, KexiFileFilters::Mode mode,
0088                                QWidget *parent)
0089     : KexiFileWidget(startDirOrVariable, mode, QString(), parent)
0090 {
0091 }
0092 
0093 KexiFileWidget::~KexiFileWidget()
0094 {
0095     done();
0096 #if 0
0097     qDebug() << d->recentDirClass;
0098     if (!d->recentDirClass.isEmpty()) {
0099         QString hf = highlightedFile();
0100         QUrl dir;
0101         if (hf.isEmpty()) {
0102             dir = baseUrl();
0103         }
0104         else {
0105             QFileInfo fi(hf);
0106             QString dirStr = fi.isDir() ? fi.absoluteFilePath() : fi.dir().absolutePath();
0107             dir = QUrl::fromLocalFile(dirStr);
0108         }
0109         //qDebug() << dir;
0110         //qDebug() << highlightedFile();
0111         if (!dir.isEmpty())
0112             KRecentDirs::add(d->recentDirClass, dir.path());
0113     }
0114 #endif
0115     delete d;
0116 }
0117 
0118 void KexiFileWidget::slotFileHighlighted(const QUrl& url)
0119 {
0120     //qDebug() << url;
0121     d->selectedUrl = url;
0122     emit fileSelected(selectedFile());
0123 }
0124 
0125 void KexiFileWidget::slotFileSelected(const QUrl& url)
0126 {
0127     Q_UNUSED(url)
0128     //qDebug() << url;
0129     emit fileSelected(selectedFile());
0130 }
0131 
0132 void KexiFileWidget::setMode(KexiFileFilters::Mode mode)
0133 {
0134     KexiFileWidgetInterface::setMode(mode);
0135 }
0136 
0137 void KexiFileWidget::updateFilters()
0138 {
0139     if (filtersUpdated())
0140         return;
0141     setFiltersUpdated(true);
0142     clearFilter();
0143     filters()->setDefaultFilter(filterWidget()->defaultFilter());
0144     KexiFileFiltersFormat format;
0145     format.type = KexiFileFiltersFormat::Type::KDE;
0146     setFilter(filters()->toString(format));
0147 
0148     if (filters()->mode() == KexiFileFilters::Opening || filters()->mode() == KexiFileFilters::CustomOpening) {
0149         KFileWidget::setMode(KFile::ExistingOnly | KFile::LocalOnly | KFile::File);
0150         setOperationMode(KFileWidget::Opening);
0151     } else {
0152         KFileWidget::setMode(KFile::LocalOnly | KFile::File);
0153         setOperationMode(KFileWidget::Saving);
0154     }
0155 }
0156 
0157 void KexiFileWidget::showEvent(QShowEvent * event)
0158 {
0159     setFiltersUpdated(false);
0160     updateFilters();
0161     KFileWidget::showEvent(event);
0162 }
0163 
0164 /*TODO
0165 QString KexiFileWidget::selectedFile() const
0166 {
0167 #ifdef Q_OS_WIN
0168 // QString path = selectedFile();
0169   //js @todo
0170 // qDebug() << "selectedFile() ==" << path << "'" << url().fileName() << "'" << m_lineEdit->text();
0171   QString path = dir()->absolutePath();
0172   if (!path.endsWith('/') && !path.endsWith("\\"))
0173     path.append("/");
0174   path += m_lineEdit->text();
0175 // QString path = QFileInfo(selectedFile()).dirPath(true) + "/" + m_lineEdit->text();
0176 #else
0177 // QString path = locationEdit->currentText().trimmed(); //url.path().trimmed(); that does not work, if the full path is not in the location edit !!!!!
0178   QString path( KFileWidget::selectedFile() );
0179   qDebug() << "prev selectedFile() ==" << path;
0180   qDebug() << "locationEdit ==" << locationEdit()->currentText().trimmed();
0181   //make sure user-entered path is acceped:
0182 //! @todo KEXI3 setSelection( locationEdit()->currentText().trimmed() );
0183 // path = KFileWidget::selectedFile();
0184   path = locationEdit()->currentText().trimmed();
0185   qDebug() << "selectedFile() ==" << path;
0186 
0187 #endif
0188 
0189   if (!currentFilter().isEmpty()) {
0190     if (d->mode & SavingFileBasedDB) {
0191       const QStringList filters( currentFilter().split(' ') );
0192       qDebug()<< "filter ==" << filters;
0193       QString ext( QFileInfo(path).suffix() );
0194       bool hasExtension = false;
0195       foreach (const QString& filter, filters) {
0196         const QString f( filter.trimmed() );
0197         hasExtension = !f.mid(2).isEmpty() && ext==f.mid(2);
0198         if (hasExtension)
0199           break;
0200       }
0201       if (!hasExtension) {
0202         //no extension: add one
0203         QString defaultExtension( d->defaultExtension );
0204         if (defaultExtension.isEmpty())
0205           defaultExtension = filters.first().trimmed().mid(2); //first one
0206         path += (QString(".")+defaultExtension);
0207         qDebug() << "KexiFileWidget::checkURL(): append extension," << path;
0208       }
0209     }
0210   }
0211   qDebug() << "KexiFileWidget::currentFileName() ==" << path;
0212   return path;
0213 }
0214 */
0215 
0216 QString KexiFileWidget::selectedFile() const
0217 {
0218     return d->selectedUrl.toLocalFile();
0219 }
0220 
0221 QString KexiFileWidget::highlightedFile() const
0222 {
0223     return d->selectedUrl.toLocalFile();
0224 }
0225 
0226 void KexiFileWidget::setSelectedFile(const QString &name)
0227 {
0228     d->selectedUrl = QUrl::fromLocalFile(name);
0229 }
0230 
0231 QString KexiFileWidget::currentDir() const
0232 {
0233     return KFileWidget::baseUrl().toLocalFile();
0234 }
0235 
0236 void KexiFileWidget::applyEnteredFileName()
0237 {
0238     const QString enteredFileName(locationEdit()->lineEdit()->text());
0239     if (enteredFileName.isEmpty()) {
0240         return;
0241     }
0242     //qDebug() << enteredFileName;
0243     //qDebug() << locationEdit()->urls();
0244     //qDebug() << currentDir();
0245 
0246     setSelectedFile(currentDir());
0247     // FIXME: find first...
0248     if (QDir::isAbsolutePath(enteredFileName)) {
0249         setSelectedFile(enteredFileName);
0250     } else {
0251         setSelectedFile(currentDir() + enteredFileName);
0252     }
0253 }
0254 
0255 QStringList KexiFileWidget::currentFilters() const
0256 {
0257     return currentFilter().split(QLatin1Char(' '));
0258 }
0259 
0260 void KexiFileWidget::accept()
0261 {
0262     //qDebug();
0263     KFileWidget::accept();
0264 // qDebug() << selectedFile();
0265 
0266 // locationEdit->setFocus();
0267 // QKeyEvent ev(QEvent::KeyPress, Qt::Key_Enter, '\n', 0);
0268 // QApplication::sendEvent(locationEdit, &ev);
0269 // QApplication::postEvent(locationEdit, &ev);
0270 
0271 // qDebug() << "KexiFileWidget::accept() m_lastUrl ==" << m_lastUrl.path();
0272 // if (m_lastUrl.path()==currentURL().path()) {//(js) to prevent more multiple kjob signals (I do not know why this is)
0273     /*
0274       if (d->lastFileName==selectedFile()) {//(js) to prevent more multiple kjob signals (I do not know why this is)
0275     //  m_lastUrl=QUrl();
0276         d->lastFileName.clear();
0277         qDebug() << "d->lastFileName==selectedFile()";
0278     #ifdef Q_OS_WIN
0279         return;
0280     #endif
0281       }
0282       qDebug() << "KexiFileWidget::accept(): path =" << selectedFile();
0283       if ( checkSelectedFile() ) {
0284         emit accepted();
0285       }
0286       d->lastFileName = selectedFile();
0287 
0288     #ifdef Q_OS_WIN
0289       saveLastVisitedPath(d->lastFileName);
0290     #endif*/
0291 }
0292 
0293 void KexiFileWidget::reject()
0294 {
0295     //qDebug();
0296     emit rejected();
0297 }
0298 
0299 #if 0 // TODO?
0300 void KexiFileWidget::setLocationText(const QString& text)
0301 {
0302     locationEdit()->setUrl(QUrl(text));
0303     /*
0304     #ifdef Q_OS_WIN
0305       //js @todo
0306       setSelection(fn);
0307     #else
0308       setSelection(fn);
0309     // locationEdit->setCurrentText(fn);
0310     // locationEdit->lineEdit()->setEdited( true );
0311     // setSelection(fn);
0312     #endif*/
0313 }
0314 #endif
0315 
0316 void KexiFileWidget::focusInEvent(QFocusEvent *event)
0317 {
0318     Q_UNUSED(event)
0319     locationEdit()->setFocus();
0320 }
0321 
0322 /*bool KexiFileWidget::eventFilter ( QObject * watched, QEvent * e )
0323 {
0324   //filter-out ESC key
0325   if (e->type()==QEvent::KeyPress && static_cast<QKeyEvent*>(e)->key()==Qt::Key_Escape
0326    && static_cast<QKeyEvent*>(e)->state()==Qt::NoButton) {
0327     static_cast<QKeyEvent*>(e)->accept();
0328     emit rejected();
0329     return true;
0330   }
0331   return KexiFileWidgetBase::eventFilter(watched,e);
0332 } */
0333 
0334 void KexiFileWidget::setWidgetFrame(bool set)
0335 {
0336     Q_UNUSED(set)
0337 }