kexi

KexiStartupFileDialog.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003-2005 Jaroslaw Staniek <js@iidea.pl>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "KexiStartupFileDialog.h"
00021 
00022 #include <kexidb/driver.h>
00023 #include <core/kexi.h>
00024 #include <kexiutils/utils.h>
00025 
00026 #include <qlayout.h>
00027 #include <qobjectlist.h>
00028 #include <qpushbutton.h>
00029 #include <qapplication.h>
00030 
00031 #include <kmessagebox.h>
00032 #include <klocale.h>
00033 #include <kdebug.h>
00034 #include <kmimetype.h>
00035 #include <kfile.h>
00036 #include <kurlcombobox.h>
00037 
00038 KexiStartupFileDialog::KexiStartupFileDialog(
00039         const QString& startDirOrVariable, int mode,
00040         QWidget *parent, const char *name)
00041     :  KexiStartupFileDialogBase(startDirOrVariable, "", parent, name, 0)
00042     , m_confirmOverwrites(true)
00043     , m_filtersUpdated(false)
00044 {
00045     setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
00046     setMode( mode );
00047     
00048     QPoint point( 0, 0 );
00049     reparent( parentWidget(), point );
00050 
00051     if (layout())
00052         layout()->setMargin(0);
00053     setMinimumHeight(100);
00054     setSizeGripEnabled ( false );
00055 
00056     //dirty hack to customize filedialog view:
00057     {
00058         QObjectList *l = queryList( "QPushButton" );
00059         QObjectListIt it( *l );
00060         QObject *obj;
00061         while ( (obj = it.current()) != 0 ) {
00062             ++it;
00063             static_cast<QPushButton*>(obj)->hide();
00064         }
00065         delete l;
00066     }
00067     {
00068         QObjectList *l = queryList("QWidget");
00069         QObjectListIt it( *l );
00070         QObject *obj;
00071         while ( (obj = it.current()) != 0 ) {
00072             ++it;
00073             static_cast<QWidget*>(obj)->installEventFilter(this);
00074         }
00075         delete l;
00076     }   
00077     
00078 #ifdef Q_WS_WIN
00079     if (startDirOrVariable.startsWith(":"))
00080         m_lastVisitedPathsVariable = startDirOrVariable; //store for later use
00081 #else
00082     toggleSpeedbar(false);
00083     setFocusProxy( locationEdit );//locationWidget() );
00084 #endif
00085 }
00086 
00087 KexiStartupFileDialog::~KexiStartupFileDialog()
00088 {
00089 #ifdef Q_WS_WIN
00090     saveLastVisitedPath(currentFileName());
00091 #endif
00092 }
00093 
00094 void KexiStartupFileDialog::setMode(int mode)
00095 {
00096     //delayed
00097     m_mode = mode;
00098     m_filtersUpdated = false;
00099 }
00100 
00101 QStringList KexiStartupFileDialog::additionalFilters() const
00102 {
00103     return m_additionalMimeTypes;
00104 }
00105 
00106 void KexiStartupFileDialog::setAdditionalFilters(const QStringList &mimeTypes)
00107 {
00108     //delayed
00109     m_additionalMimeTypes = mimeTypes;
00110     m_filtersUpdated = false;
00111 }
00112 
00113 QStringList KexiStartupFileDialog::excludedFilters() const
00114 {
00115     return m_excludedMimeTypes;
00116 }
00117 
00118 void KexiStartupFileDialog::setExcludedFilters(const QStringList &mimeTypes)
00119 {
00120     //delayed
00121     m_excludedMimeTypes = mimeTypes;
00122     m_filtersUpdated = false;
00123 }
00124 
00125 void KexiStartupFileDialog::updateFilters()
00126 {
00127     if (m_filtersUpdated)
00128         return;
00129     m_filtersUpdated = true;
00130 
00131     m_lastFileName = QString::null;
00132 //  m_lastUrl = KURL();
00133 
00134     clearFilter();
00135     
00136     QString filter;
00137     KMimeType::Ptr mime;
00138     QStringList allfilters;
00139 
00140     const bool normalOpeningMode = m_mode & Opening && !(m_mode & Custom);
00141     const bool normalSavingMode = m_mode & SavingFileBasedDB && !(m_mode & Custom);
00142 
00143     if (normalOpeningMode || normalSavingMode) {
00144         mime = KMimeType::mimeType( KexiDB::Driver::defaultFileBasedDriverMimeType() );
00145         if (mime && m_excludedMimeTypes.find(mime->name())==m_excludedMimeTypes.end()) {
00146             filter += KexiUtils::fileDialogFilterString(mime);
00147             allfilters += mime->patterns();
00148         }
00149     }
00150     if (normalOpeningMode || m_mode & SavingServerBasedDB) {
00151         mime = KMimeType::mimeType("application/x-kexiproject-shortcut");
00152         if (mime && m_excludedMimeTypes.find(mime->name())==m_excludedMimeTypes.end()) {
00153             filter += KexiUtils::fileDialogFilterString(mime);
00154             allfilters += mime->patterns();
00155         }
00156     }
00157     if (normalOpeningMode || m_mode & SavingServerBasedDB) {
00158         mime = KMimeType::mimeType("application/x-kexi-connectiondata");
00159         if (mime && m_excludedMimeTypes.find(mime->name())==m_excludedMimeTypes.end()) {
00160             filter += KexiUtils::fileDialogFilterString(mime);
00161             allfilters += mime->patterns();
00162         }
00163     }
00164 
00166     if (normalOpeningMode) {
00167         mime = KMimeType::mimeType("application/x-msaccess");
00168         if (mime && m_excludedMimeTypes.find(mime->name())==m_excludedMimeTypes.end()) {
00169             filter += KexiUtils::fileDialogFilterString(mime);
00170             allfilters += mime->patterns();
00171         }
00172     }
00173 
00174     foreach (QStringList::ConstIterator, it, m_additionalMimeTypes) {
00175         if (*it == "all/allfiles")
00176             continue;
00177         if (m_excludedMimeTypes.find(*it)!=m_excludedMimeTypes.end())
00178             continue;
00179         filter += KexiUtils::fileDialogFilterString(*it);
00180         mime = KMimeType::mimeType(*it);
00181         allfilters += mime->patterns();
00182     }
00183 
00184     if (m_excludedMimeTypes.find("all/allfiles")==m_excludedMimeTypes.end())
00185         filter += KexiUtils::fileDialogFilterString("all/allfiles");
00186 //  mime = KMimeType::mimeType("all/allfiles");
00187 //  if (mime) {
00188 //      filter += QString(mime->patterns().isEmpty() ? "*" : mime->patterns().join(" ")) 
00189 //          + "|" + mime->comment()+ " (*)\n";
00190 //  }
00191     //remove duplicates made because upper- and lower-case extenstions are used:
00192     QStringList allfiltersUnique;
00193     QDict<char> uniqueDict(499, false);
00194     foreach (QStringList::ConstIterator, it, allfilters) {
00195 //      kdDebug() << *it << endl;
00196         uniqueDict.insert(*it, (char*)1);
00197     }
00198     foreach_dict (QDictIterator<char>, it, uniqueDict) {
00199         allfiltersUnique += it.currentKey();
00200     }
00201     allfiltersUnique.sort();
00202     
00203     if (allfiltersUnique.count()>1) {//prepend "all supoported files" entry
00204         filter.prepend(allfilters.join(" ")+"|" + i18n("All Supported Files")
00205             +" ("+allfiltersUnique.join(" ")+")\n");
00206     }
00207     
00208     if (filter.right(1)=="\n")
00209         filter.truncate(filter.length()-1);
00210     setFilter(filter);
00211     
00212     if (m_mode & Opening) {
00213         KexiStartupFileDialogBase::setMode( KFile::ExistingOnly | KFile::LocalOnly | KFile::File );
00214         setOperationMode( KFileDialog::Opening );
00215     } else {
00216         KexiStartupFileDialogBase::setMode( KFile::LocalOnly | KFile::File );
00217         setOperationMode( KFileDialog::Saving );
00218     }
00219 }
00220 
00221 void KexiStartupFileDialog::show()
00222 {
00223     m_filtersUpdated = false;
00224     updateFilters();
00225     KexiStartupFileDialogBase::show();
00226 }
00227 
00228 //KURL KexiStartupFileDialog::currentURL()
00229 QString KexiStartupFileDialog::currentFileName()
00230 {
00231     setResult( QDialog::Accepted ); // selectedURL tests for it
00232     
00233 #ifdef Q_WS_WIN
00234 //  QString path = selectedFile();
00235     //js @todo
00236 //  kdDebug() << "selectedFile() == " << path << " '" << url().fileName() << "' " << m_lineEdit->text() << endl;
00237     QString path = dir()->absPath();
00238     if (!path.endsWith("/") && !path.endsWith("\\"))
00239         path.append("/");
00240   path += m_lineEdit->text();
00241 //  QString path = QFileInfo(selectedFile()).dirPath(true) + "/" + m_lineEdit->text();
00242 #else
00243 //  QString path = locationEdit->currentText().stripWhiteSpace(); //url.path().stripWhiteSpace(); that does not work, if the full path is not in the location edit !!!!!
00244     QString path=KexiStartupFileDialogBase::selectedURL().path();
00245     kdDebug() << "prev selectedURL() == " << path <<endl;
00246     kdDebug() << "locationEdit == " << locationEdit->currentText().stripWhiteSpace() <<endl;
00247     //make sure user-entered path is acceped:
00248     setSelection( locationEdit->currentText().stripWhiteSpace() );
00249     
00250     path=KexiStartupFileDialogBase::selectedURL().path();
00251     kdDebug() << "selectedURL() == " << path <<endl;
00252     
00253 #endif
00254     
00255     if (!currentFilter().isEmpty()) {
00256         if (m_mode & SavingFileBasedDB) {
00257             QStringList filters = QStringList::split(" ", currentFilter()); //.first().stripWhiteSpace();
00258             kdDebug()<< " filter == " << filters << endl;
00259             QString ext = QFileInfo(path).extension(false);
00260             bool hasExtension = false;
00261             for (QStringList::ConstIterator filterIt = filters.constBegin(); 
00262                 filterIt != filters.constEnd() && !hasExtension; ++filterIt)
00263             {
00264                 QString f( (*filterIt).stripWhiteSpace() );
00265                 hasExtension = !f.mid(2).isEmpty() && ext==f.mid(2);
00266             }
00267             if (!hasExtension) {
00268                 //no extension: add one
00269                 QString defaultExtension( m_defaultExtension );
00270                 if (defaultExtension.isEmpty())
00271                     defaultExtension = filters.first().stripWhiteSpace().mid(2); //first one
00272                 path+=(QString(".")+defaultExtension);
00273                 kdDebug() << "KexiStartupFileDialog::checkURL(): append extension, " << path << endl;
00274                 setSelection( path );
00275             }
00276         }
00277     }
00278     kdDebug() << "KexiStartupFileDialog::currentFileName() == " << path <<endl;
00279     return path;
00280 //  return KFileDialog::selectedURL();
00281 }
00282 
00283 //bool KexiStartupFileDialog::checkURL()
00284 bool KexiStartupFileDialog::checkFileName()
00285 {
00286 //  KURL url = currentURL();
00287 //  QString path = url.path().stripWhiteSpace();
00288     QString path = currentFileName().stripWhiteSpace();
00289     
00290 //  if (url.fileName().stripWhiteSpace().isEmpty()) {
00291     if (path.isEmpty()) {
00292         KMessageBox::error( this, i18n( "Enter a filename." ));
00293         return false;
00294     }
00295     
00296     kdDebug() << "KexiStartupFileDialog::checkURL() path: " << path  << endl;
00297 //  kdDebug() << "KexiStartupFileDialog::checkURL() fname: " << url.fileName() << endl;
00298 //todo  if ( url.isLocalFile() ) {
00299         QFileInfo fi(path);
00300         if (mode() & KFile::ExistingOnly) {
00301             if ( !fi.exists() ) {
00302                 KMessageBox::error( this, "<qt>"+i18n( "The file \"%1\" does not exist." )
00303                     .arg( QDir::convertSeparators(path) ) );
00304                 return false;
00305             }
00306             else if (mode() & KFile::File) {
00307                 if (!fi.isFile()) {
00308                     KMessageBox::error( this, "<qt>"+i18n( "Enter a filename." ) );
00309                     return false;
00310                 }
00311                 else if (!fi.isReadable()) {
00312                     KMessageBox::error( this, "<qt>"+i18n( "The file \"%1\" is not readable." )
00313                         .arg( QDir::convertSeparators(path) ) );
00314                     return false;
00315                 }
00316             }
00317         }
00318         else if (m_confirmOverwrites && fi.exists()) {
00319             if (KMessageBox::Yes!=KMessageBox::warningYesNo( this, i18n( "The file \"%1\" already exists.\n"
00320             "Do you want to overwrite it?").arg( QDir::convertSeparators(path) ), QString::null, i18n("Overwrite"), KStdGuiItem::cancel() )) {
00321                 return false;
00322             }
00323         }
00324 //  }
00325     return true;
00326 }
00327 
00328 void KexiStartupFileDialog::accept()
00329 {
00330 //  locationEdit->setFocus();
00331 //  QKeyEvent ev(QEvent::KeyPress, Qt::Key_Enter, '\n', 0);
00332 //  QApplication::sendEvent(locationEdit, &ev);
00333 //  QApplication::postEvent(locationEdit, &ev);
00334     
00335 //  kdDebug() << "KexiStartupFileDialog::accept() m_lastUrl == " << m_lastUrl.path() << endl;
00336 //  if (m_lastUrl.path()==currentURL().path()) {//(js) to prevent more multiple kjob signals (I do not know why this is)
00337     if (m_lastFileName==currentFileName()) {//(js) to prevent more multiple kjob signals (I do not know why this is)
00338 //      m_lastUrl=KURL();
00339         m_lastFileName=QString::null;
00340         kdDebug() << "m_lastFileName==currentFileName()" << endl;
00341 #ifdef Q_WS_WIN
00342         return;
00343 #endif
00344     }
00345 //  kdDebug() << "KexiStartupFileDialog::accept(): url = " << currentURL().path() << " " << endl;
00346     kdDebug() << "KexiStartupFileDialog::accept(): path = " << currentFileName() << endl;
00347 //  if ( checkURL() ) {
00348     if ( checkFileName() ) {
00349         emit accepted();
00350     }
00351 //  else {
00352 //      m_lastUrl = KURL();
00353 //  }
00354 //  m_lastUrl = currentURL();
00355     m_lastFileName = currentFileName();
00356 
00357 #ifdef Q_WS_WIN
00358     saveLastVisitedPath(m_lastFileName);
00359 #endif
00360 }
00361 
00362 void KexiStartupFileDialog::reject()
00363 {
00364     kdDebug() << "KexiStartupFileDialog: reject!" << endl;
00365     emit rejected();
00366 }
00367 
00368 /*#ifndef Q_WS_WIN
00369 KURLComboBox *KexiStartupFileDialog::locationWidget() const
00370 {
00371     return locationEdit;
00372 }
00373 #endif
00374 */
00375 
00376 void KexiStartupFileDialog::setLocationText(const QString& fn)
00377 {
00378 #ifdef Q_WS_WIN
00379     //js @todo
00380     setSelection(fn);
00381 #else
00382     setSelection(fn);
00383 //  locationEdit->setCurrentText(fn);
00384 //  locationEdit->lineEdit()->setEdited( true );
00385 //  setSelection(fn);
00386 #endif
00387 }
00388 
00389 void KexiStartupFileDialog::setFocus()
00390 {
00391 #ifdef Q_WS_WIN
00392     m_lineEdit->setFocus();
00393 #else
00394     locationEdit->setFocus();
00395 #endif
00396 }
00397 
00398 bool KexiStartupFileDialog::eventFilter ( QObject * watched, QEvent * e )
00399 {
00400     //filter-out ESC key
00401     if (e->type()==QEvent::KeyPress && static_cast<QKeyEvent*>(e)->key()==Qt::Key_Escape
00402      && static_cast<QKeyEvent*>(e)->state()==Qt::NoButton) {
00403         static_cast<QKeyEvent*>(e)->accept();
00404         emit rejected();
00405         return true;
00406     }
00407     return KexiStartupFileDialogBase::eventFilter(watched,e);
00408 } 
00409 
00410 #include "KexiStartupFileDialog.moc"
00411 
KDE Home | KDE Accessibility Home | Description of Access Keys