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 }