kexi

KexiStartupFileDialog_win.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003-2004 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 
00025 #include "KexiStartupFileDialog.h"
00026 #include <kexiutils/utils.h>
00027 
00028 #include <kiconloader.h>
00029 #include <kdebug.h>
00030 #include <krecentdirs.h>
00031 
00032 #include <qobjectlist.h>
00033 #include <qlineedit.h>
00034 
00035 #include <win/win32_utils.h>
00036 
00038 class KexiStartupFileDialogBasePrivate
00039 {
00040     public:
00041         KexiStartupFileDialogBasePrivate()
00042         {}
00043         KFile::Mode mode;
00044         QString kde_filters;
00045         QStringList mimetypes;
00046 };
00047 
00048 KexiStartupFileDialogBase::KexiStartupFileDialogBase(
00049     const QString & dirName, const QString & filter, 
00050     QWidget * parent, const char * name, bool modal )
00051  : QFileDialog( realStartDir(dirName), filter, parent, name, modal )
00052  , d(new KexiStartupFileDialogBasePrivate())
00053 {
00054 //  QString _dirName = dirName;
00055     QString _dirName = dirPath();
00056     //make default 'My Documents' folder
00057 //TODO: store changes in the app's config file?
00058     if (_dirName.isEmpty())
00059         _dirName = KGlobalSettings::documentPath();
00060 
00061     init(_dirName, filter, parent);
00062 
00063     //find "OK" button
00064     QObjectList *l = queryList( "QPushButton", "OK", false );
00065     m_okBtn = dynamic_cast<QPushButton*>(l->first());
00066     delete l;
00067     l = queryList( "QLineEdit", "name/filter editor", false );
00068     m_lineEdit = dynamic_cast<QLineEdit*>(l->first());
00069     delete l;
00070 
00071     adjustSize();
00072 }
00073 
00074 KexiStartupFileDialogBase::~KexiStartupFileDialogBase()
00075 {
00076 }
00077 
00078 void KexiStartupFileDialogBase::init(const QString& startDir, const QString& filter, QWidget* widget)
00079 {
00080 //TODO    initStatic();
00081 //TODO    d = new KFileDialogPrivate();
00082 
00083 //(js)    d->boxLayout = 0;
00084 //TODO    d->keepLocation = false;
00085 //TODO    d->operationMode = Opening;
00086     setMode(KFile::File | KFile::ExistingOnly); //(js) default: open action
00087     setIcon( KGlobal::iconLoader()->loadIcon("fileopen", KIcon::Desktop) );
00088         setDir(QDir(startDir));
00089 //TODO    d->hasDefaultFilter = false;
00090 //TODO    d->hasView = false;
00091 //(js)    d->mainWidget = new QWidget( this, "KFileDialog::mainWidget");
00092 //(js)    setMainWidget( d->mainWidget );
00093 //(js)    d->okButton = new KPushButton( KStdGuiItem::ok(), d->mainWidget );
00094 //(js)    d->okButton->setDefault( true );
00095 //(js)    d->cancelButton = new KPushButton(KStdGuiItem::cancel(), d->mainWidget);
00096 //(js)    connect( d->okButton, SIGNAL( clicked() ), SLOT( slotOk() ));
00097 //(js)    connect( d->cancelButton, SIGNAL( clicked() ), SLOT( slotCancel() ));
00098 //(js)    d->customWidget = widget;
00099 //(js)    d->autoSelectExtCheckBox = 0; // delayed loading
00100 //TODO    d->autoSelectExtChecked = false;
00101 //(js)    d->urlBar = 0; // delayed loading
00102 //TODO    KConfig *config = KGlobal::config();
00103 //TODO    KConfigGroupSaver cs( config, ConfigGroup );
00104 //TODO    d->initializeSpeedbar = config->readBoolEntry( "Set speedbar defaults",
00105 //TODO                                                   true );
00106 //TODO    d->completionLock = false;
00107 
00108 //TODO    QtMsgHandler oldHandler = qInstallMsgHandler( silenceQToolBar );
00109 //TODO    toolbar = 0; //(js)
00110 //(js)    toolbar = new KToolBar( d->mainWidget, "KFileDialog::toolbar", true);
00111 //(js)    toolbar->setFlat(true);
00112 //TODO    qInstallMsgHandler( oldHandler );
00113 
00114 //(js)    d->pathCombo = new KURLComboBox( KURLComboBox::Directories, true,
00115 //(js)                                     toolbar, "path combo" );
00116 //(js)    QToolTip::add( d->pathCombo, i18n("Often used directories") );
00117 //(js)    QWhatsThis::add( d->pathCombo, "<qt>" + i18n("Commonly used locations are listed here. "
00118 //(js)                                                 "This includes standard locations, such as your home directory, as well as "
00119 //(js)                                                 "locations that have been visited recently.") + autocompletionWhatsThisText);
00120 /*
00121     KURL u;
00122     u.setPath( QDir::rootDirPath() );
00123     QString text = i18n("Root Directory: %1").arg( u.path() );
00124     d->pathCombo->addDefaultURL( u,
00125                                  KMimeType::pixmapForURL( u, 0, KIcon::Small ),
00126                                  text );
00127 
00128     u.setPath( QDir::homeDirPath() );
00129     text = i18n("Home Directory: %1").arg( u.path( +1 ) );
00130     d->pathCombo->addDefaultURL( u, KMimeType::pixmapForURL( u, 0, KIcon::Small ),
00131                                  text );
00132 
00133     KURL docPath;
00134     docPath.setPath( KGlobalSettings::documentPath() );
00135     if ( u.path(+1) != docPath.path(+1) ) {
00136         text = i18n("Documents: %1").arg( docPath.path( +1 ) );
00137         d->pathCombo->addDefaultURL( u,
00138                                      KMimeType::pixmapForURL( u, 0, KIcon::Small ),
00139                                      text );
00140     }
00141 
00142     u.setPath( KGlobalSettings::desktopPath() );
00143     text = i18n("Desktop: %1").arg( u.path( +1 ) );
00144     d->pathCombo->addDefaultURL( u,
00145                                  KMimeType::pixmapForURL( u, 0, KIcon::Small ),
00146                                  text );
00147 
00148     u.setPath( "/tmp" );
00149 
00150     d->url = getStartURL( startDir, d->fileClass );
00151     d->selection = d->url.url();
00152 
00153     // If local, check it exists. If not, go up until it exists.
00154     if ( d->url.isLocalFile() )
00155     {
00156         if ( !QFile::exists( d->url.path() ) )
00157         {
00158             d->url = d->url.upURL();
00159             QDir dir( d->url.path() );
00160             while ( !dir.exists() )
00161             {
00162                 d->url = d->url.upURL();
00163                 dir.setPath( d->url.path() );
00164             }
00165         }
00166     }
00167 
00168     ops = new KDirOperator(d->url, d->mainWidget, "KFileDialog::ops");
00169     ops->setOnlyDoubleClickSelectsFiles( true );
00170     connect(ops, SIGNAL(urlEntered(const KURL&)),
00171             SLOT(urlEntered(const KURL&)));
00172     connect(ops, SIGNAL(fileHighlighted(const KFileItem *)),
00173             SLOT(fileHighlighted(const KFileItem *)));
00174     connect(ops, SIGNAL(fileSelected(const KFileItem *)),
00175             SLOT(fileSelected(const KFileItem *)));
00176     connect(ops, SIGNAL(finishedLoading()),
00177             SLOT(slotLoadingFinished()));
00178 
00179     ops->setupMenu(KDirOperator::SortActions |
00180                    KDirOperator::FileActions |
00181                    KDirOperator::ViewActions);
00182     KActionCollection *coll = ops->actionCollection();
00183 
00184     // plug nav items into the toolbar
00185     coll->action( "up" )->plug( toolbar );
00186     coll->action( "up" )->setWhatsThis(i18n("<qt>Click this button to enter the parent directory.<p>"
00187                                             "For instance, if the current location is file:/home/%1 clicking this "
00188                                             "button will take you to file:/home.</qt>").arg(getlogin()));
00189     coll->action( "back" )->plug( toolbar );
00190     coll->action( "back" )->setWhatsThis(i18n("Click this button to move backwards one step in the browsing history."));
00191     coll->action( "forward" )->plug( toolbar );
00192     coll->action( "forward" )->setWhatsThis(i18n("Click this button to move forward one step in the browsing history."));
00193     coll->action( "reload" )->plug( toolbar );
00194     coll->action( "reload" )->setWhatsThis(i18n("Click this button to reload the contents of the current location."));
00195     coll->action( "mkdir" )->setShortcut(Key_F10);
00196     coll->action( "mkdir" )->plug( toolbar );
00197     coll->action( "mkdir" )->setWhatsThis(i18n("Click this button to create a new directory."));
00198 
00199     d->bookmarkHandler = new KFileBookmarkHandler( this );
00200     toolbar->insertButton(QString::fromLatin1("bookmark"),
00201                           (int)HOTLIST_BUTTON, true,
00202                           i18n("Bookmarks"));
00203     toolbar->getButton(HOTLIST_BUTTON)->setPopup( d->bookmarkHandler->menu(),
00204                                                   true);
00205     QWhatsThis::add(toolbar->getButton(HOTLIST_BUTTON),
00206                     i18n("<qt>This button allows you to bookmark specific locations. "
00207                          "Click on this button to open the bookmark menu where you may add, "
00208                          "edit or select a bookmark.<p>"
00209                          "These bookmarks are specific to the file dialog, but otherwise operate "
00210                          "like bookmarks elsewhere in KDE.</qt>"));
00211     connect( d->bookmarkHandler, SIGNAL( openURL( const QString& )),
00212              SLOT( enterURL( const QString& )));
00213 
00214     KToggleAction *showSidebarAction =
00215         new KToggleAction(i18n("Show Quick Access Navigation Panel"), Key_F9, coll,"toggleSpeedbar");
00216     connect( showSidebarAction, SIGNAL( toggled( bool ) ),
00217              SLOT( toggleSpeedbar( bool )) );
00218 
00219     KActionMenu *menu = new KActionMenu( i18n("Configure"), "configure", this, "extra menu" );
00220     menu->setWhatsThis(i18n("<qt>This is the configuration menu for the file dialog. "
00221                             "Various options can be accessed from this menu including: <ul>"
00222                             "<li>how files are sorted in the list</li>"
00223                             "<li>types of view, including icon and list</li>"
00224                             "<li>showing of hidden files</li>"
00225                             "<li>the Quick Access navigation panel</li>"
00226                             "<li>file previews</li>"
00227                             "<li>separating directories from files</li></ul></qt>"));
00228     menu->insert( coll->action( "sorting menu" ));
00229     menu->insert( coll->action( "separator" ));
00230     coll->action( "short view" )->setShortcut(Key_F6);
00231     menu->insert( coll->action( "short view" ));
00232     coll->action( "detailed view" )->setShortcut(Key_F7);
00233     menu->insert( coll->action( "detailed view" ));
00234     menu->insert( coll->action( "separator" ));
00235     coll->action( "show hidden" )->setShortcut(Key_F8);
00236     menu->insert( coll->action( "show hidden" ));
00237     menu->insert( showSidebarAction );
00238     coll->action( "preview" )->setShortcut(Key_F11);
00239     menu->insert( coll->action( "preview" ));
00240     coll->action( "separate dirs" )->setShortcut(Key_F12);
00241     menu->insert( coll->action( "separate dirs" ));
00242 
00243     menu->setDelayed( false );
00244     connect( menu->popupMenu(), SIGNAL( aboutToShow() ),
00245              ops, SLOT( updateSelectionDependentActions() ));
00246     menu->plug( toolbar );
00247 */
00248     /*
00249      * ugly little hack to have a 5 pixel space between the buttons
00250      * and the combo box
00251      */
00252 /*    QWidget *spacerWidget = new QWidget(toolbar);
00253 //(js)    spacerWidget->setMinimumWidth(spacingHint());
00254 //(js)    spacerWidget->setMaximumWidth(spacingHint());
00255     d->m_pathComboIndex = toolbar->insertWidget(-1, -1, spacerWidget);
00256     toolbar->insertWidget(PATH_COMBO, 0, d->pathCombo);
00257 
00258 
00259     toolbar->setItemAutoSized (PATH_COMBO);
00260     toolbar->setIconText(KToolBar::IconOnly);
00261     toolbar->setBarPos(KToolBar::Top);
00262     toolbar->setMovingEnabled(false);
00263     toolbar->adjustSize();
00264 
00265     d->pathCombo->setCompletionObject( ops->dirCompletionObject(), false );
00266 
00267     connect( d->pathCombo, SIGNAL( urlActivated( const KURL&  )),
00268              this,  SLOT( enterURL( const KURL& ) ));
00269     connect( d->pathCombo, SIGNAL( returnPressed( const QString&  )),
00270              this,  SLOT( enterURL( const QString& ) ));
00271     connect( d->pathCombo, SIGNAL(textChanged( const QString& )),
00272              SLOT( pathComboChanged( const QString& ) ));
00273     connect( d->pathCombo, SIGNAL( completion( const QString& )),
00274              SLOT( dirCompletion( const QString& )));
00275     connect( d->pathCombo, SIGNAL( textRotation(KCompletionBase::KeyBindingType) ),
00276              d->pathCombo, SLOT( rotateText(KCompletionBase::KeyBindingType) ));
00277 
00278     QString whatsThisText;
00279 
00280     // the Location label/edit
00281     d->locationLabel = new QLabel(i18n("&Location:"), d->mainWidget);
00282     locationEdit = new KURLComboBox(KURLComboBox::Files, true,
00283                                     d->mainWidget, "LocationEdit");
00284     updateLocationWhatsThis ();
00285     d->locationLabel->setBuddy(locationEdit);
00286 
00287     // to get the completionbox-signals connected:
00288     locationEdit->setHandleSignals( true );
00289     (void) locationEdit->completionBox();
00290 
00291     locationEdit->setFocus();
00292 //     locationEdit->setCompletionObject( new KURLCompletion() );
00293 //     locationEdit->setAutoDeleteCompletionObject( true );
00294     locationEdit->setCompletionObject( ops->completionObject(), false );
00295 
00296     connect( locationEdit, SIGNAL( returnPressed() ),
00297              this, SLOT( slotOk()));
00298     connect(locationEdit, SIGNAL( activated( const QString&  )),
00299             this,  SLOT( locationActivated( const QString& ) ));
00300     connect( locationEdit, SIGNAL( completion( const QString& )),
00301              SLOT( fileCompletion( const QString& )));
00302     connect( locationEdit, SIGNAL( textRotation(KCompletionBase::KeyBindingType) ),
00303              locationEdit, SLOT( rotateText(KCompletionBase::KeyBindingType) ));
00304 
00305     // the Filter label/edit
00306     whatsThisText = i18n("<qt>This is the filter to apply to the file list. "
00307                          "File names that do not match the filter will not be shown.<p>"
00308                          "You may select from one of the preset filters in the "
00309                          "drop down menu, or you may enter a custom filter "
00310                          "directly into the text area.<p>"
00311                          "Wildcards such as * and ? are allowed.</qt>");
00312     d->filterLabel = new QLabel(i18n("&Filter:"), d->mainWidget);
00313     QWhatsThis::add(d->filterLabel, whatsThisText);
00314     filterWidget = new KFileFilterCombo(d->mainWidget,
00315                                         "KFileDialog::filterwidget");
00316     QWhatsThis::add(filterWidget, whatsThisText);
00317     setFilter(filter);
00318     d->filterLabel->setBuddy(filterWidget);
00319     connect(filterWidget, SIGNAL(filterChanged()), SLOT(slotFilterChanged()));
00320 
00321     // the Automatically Select Extension checkbox
00322     // (the text, visibility etc. is set in updateAutoSelectExtension(), which is called by readConfig())
00323     d->autoSelectExtCheckBox = new QCheckBox (d->mainWidget);
00324     connect(d->autoSelectExtCheckBox, SIGNAL(clicked()), SLOT(slotAutoSelectExtClicked()));
00325 
00326     initGUI(); // activate GM
00327 
00328     readRecentFiles( config );
00329 
00330     adjustSize();
00331 
00332     // we set the completionLock to avoid entering pathComboChanged() when
00333     // inserting the list of URLs into the combo.
00334     d->completionLock = true;
00335     ops->setViewConfig( config, ConfigGroup );
00336     readConfig( config, ConfigGroup );
00337     setSelection(d->selection);
00338     d->completionLock = false;
00339     */
00340 }
00341 
00342 void KexiStartupFileDialogBase::clearFilter()
00343 {
00344     d->kde_filters = "";//(js)
00345     QFileDialog::setFilter(""); //(js);
00346 //todo    d->mimetypes.clear();
00347 //todo    d->hasDefaultFilter = false;
00348 
00349     updateAutoSelectExtension ();
00350 }
00351 
00352 KFile::Mode KexiStartupFileDialogBase::mode() const
00353 {
00354     return d->mode;
00355 }
00356 
00357 void KexiStartupFileDialogBase::setMode( KFile::Mode m )
00358 {
00359     //(js) translate mode for QFileDialog
00360     d->mode = m;
00361     QFileDialog::Mode qm = (QFileDialog::Mode)0;
00362     if (m & KFile::File) qm = Mode(qm | QFileDialog::AnyFile);
00363     else if (m & KFile::Directory) qm = Mode(qm | QFileDialog::DirectoryOnly);
00364     if (m & KFile::Files) qm = Mode(qm | QFileDialog::ExistingFiles);
00365     if (m & KFile::ExistingOnly) qm = Mode(qm | QFileDialog::ExistingFile);
00366     
00367     QFileDialog::setMode( qm );
00368 /*(js)    ops->setMode(m);
00369     if ( ops->dirOnlyMode() ) {
00370 //(js)        filterWidget->setDefaultFilter( i18n("*|All Directories") );
00371     }
00372     else {
00373 //(js)        filterWidget->setDefaultFilter( i18n("*|All Files") );
00374     }
00375 
00376     updateAutoSelectExtension ();*/
00377 }
00378 
00379 void KexiStartupFileDialogBase::setMode( unsigned int m )
00380 {
00381     setMode(static_cast<KFile::Mode>( m ));
00382 }
00383 
00384 void KexiStartupFileDialogBase::setOperationMode( KFileDialog::OperationMode mode )
00385 {
00386 //    d->operationMode = mode;
00387   //  d->keepLocation = (mode == Saving);
00388     if (mode == KFileDialog::Saving) {
00389       setMode( KFile::File );
00390       setIcon( KGlobal::iconLoader()->loadIcon("filesave", KIcon::Desktop) );
00391     }
00392 //(js)    filterWidget->setEditable( !d->hasDefaultFilter || mode != Saving );
00393 //(js)    d->okButton->setGuiItem( (mode == Saving) ? KStdGuiItem::save() : KStdGuiItem::ok() );
00394 //TODO    updateLocationWhatsThis ();
00395     updateAutoSelectExtension ();
00396 }
00397 
00398 QString KexiStartupFileDialogBase::currentFilter() const
00399 {
00400     //(js)filterWidget->currentFilter();
00401 
00402     //we need to convert Qt filter format to KDE format
00403     //Qt format: "some text (*.first *.second)" or "All (*)"
00404     //KDE format: "*.first *.second" or "*"
00405     QString f = selectedFilter();
00406     if (f.find('(')!=-1)
00407         f = f.mid(f.find('(')+1);
00408     if (f.mid(f.find(')')!=-1))
00409         f = f.left(f.find(')'));
00410     return f;
00411 }
00412 
00413 void KexiStartupFileDialogBase::setFilter(const QString& filter)
00414 {
00415     d->kde_filters = filter;
00416     int pos = d->kde_filters.find('/');
00417 
00418     // Check for an un-escaped '/', if found
00419     // interpret as a MIME filter.
00420 
00421     if (pos > 0 && filter[pos - 1] != '\\') {
00422         QStringList filters = QStringList::split( " ", d->kde_filters );
00423         setMimeFilter( filters );
00424         return;
00425     }
00426     QFileDialog::setFilters( convertKFileDialogFilterToQFileDialogFilter(filter) );
00427     //</js>
00428 //(js)    ops->clearFilter();
00429 //(js)    filterWidget->setFilter(copy);
00430 //(js)    ops->setNameFilter(filterWidget->currentFilter());
00431 //(js)    d->hasDefaultFilter = false;
00432 //(js)    filterWidget->setEditable( true );
00433 
00434     updateAutoSelectExtension ();
00435 }
00436 
00437 void KexiStartupFileDialogBase::setMimeFilter( const QStringList& mimeTypes,
00438                                  const QString& defaultType )
00439 {
00440     d->mimetypes = mimeTypes;
00441 //(js)    filterWidget->setMimeFilter( mimeTypes, defaultType );
00442 
00443 //(js)    QStringList types = QStringList::split(" ", filterWidget->currentFilter());
00444 //(js)    types.append( QString::fromLatin1( "inode/directory" ));
00445 //(js)    ops->clearFilter();
00446 //(js)    ops->setMimeFilter( types );
00447 //(js)    d->hasDefaultFilter = !defaultType.isEmpty();
00448 //(js)    filterWidget->setEditable( !d->hasDefaultFilter ||
00449 //(js)                               d->operationMode != Saving );
00450 
00451 //TODO    updateAutoSelectExtension ();
00452 }
00453 
00454 QString KexiStartupFileDialogBase::realStartDir(const QString& startDir)
00455 {
00456     if (!startDir.startsWith(":"))
00457         return startDir;
00458     QString recentDir; //dummy
00459     QString path( KFileDialog::getStartURL(startDir, recentDir).path() );
00460     if (path.isEmpty())
00461         return QString::null;
00462     QFileInfo fi(path);
00463     return fi.isDir() ? fi.absFilePath() : fi.dir(true).absPath();
00464 }
00465 
00466 void KexiStartupFileDialogBase::saveLastVisitedPath(const QString& path)
00467 {
00468     if (!m_lastVisitedPathsVariable.isEmpty()) {
00469         //save last visited dir path
00470 //      QString dir = QDir(path).absPath();
00471         QFileInfo fi(path);
00472         QString dir( fi.isDir() ? fi.absFilePath() : fi.dir(true).absPath() );
00473         if (!dir.isEmpty())
00474             KRecentDirs::add(m_lastVisitedPathsVariable, dir);
00475     }
00476 }
KDE Home | KDE Accessibility Home | Description of Access Keys