File indexing completed on 2024-05-12 16:40:54

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