KDE/kdelibs

Jaroslaw Staniek js at iidea.pl
Tue Apr 8 19:26:49 CEST 2008


SVN commit 794821 by staniek:

A set of fixes for improving experience of file dialogs, mostly on Windows
+ some fixes for handling urls

KFileWidget:
- check whether a string contains protocol part more carefully because c:/ is
an absolute path, not a protocol
   (static containsProtocolSection()), so we assume the protocol has at least
two characters before ":/"
- enclose locationEdit->currentText() with QDir::fromNativeSeparators() and
add .trimmed() to cover more cases in conditions
- slotOk(): add code for handling accepting using OK button when directory
path is entered and directories are not acceptable result of the file widget:
cd to that directory then; in particuar it is now possible to enter C:\ or /
and press OK to change to the root dir on windows (or linux, respectively)

KUrlCompletion:
- construct the path more carefully because cwd can already end with '/', e.g.
it can be "c:/"

KUrl:
- KUrl::equals() and ::urlcmp(): make comparison of local urls
case-insensitive on Windows
- KUrl::hasSubUrl() some more optimizations

(reviewed)

CCMAIL:kde-windows at kde.org



 M  +52 -20    kdecore/io/kurl.cpp  
 M  +59 -17    kfile/kfilewidget.cpp  
 M  +7 -1      kio/kio/kurlcompletion.cpp  


--- trunk/KDE/kdelibs/kdecore/io/kurl.cpp #794820:794821
@@ -526,7 +526,11 @@
   {
     QString path1 = path((options & CompareWithoutTrailingSlash) ? RemoveTrailingSlash : LeaveTrailingSlash);
     QString path2 = _u.path((options & CompareWithoutTrailingSlash) ? RemoveTrailingSlash : LeaveTrailingSlash);
+#ifdef Q_WS_WIN
+    if ( isLocalFile() && _u.isLocalFile() && 0 != QString::compare( path1, path2, Qt::CaseInsensitive ) )
+#else
     if ( path1 != path2 )
+#endif
       return false;
 
     if ( scheme() == _u.scheme() &&
@@ -776,12 +780,14 @@
   return trailingSlash( trailing, QUrl::toLocalFile() );
 }
 
-bool KUrl::isLocalFile() const
+inline static bool hasSubUrl( const QUrl& url );
+
+static inline bool isLocalFile( const QUrl& url )
 {
-  if ( ( scheme() != QLatin1String("file") ) || hasSubUrl() )
+  if ( ( url.scheme() != QLatin1String("file") ) || hasSubUrl( url ) )
      return false;
 
-  if (host().isEmpty() || (host() == QLatin1String("localhost")))
+  if (url.host().isEmpty() || (url.host() == QLatin1String("localhost")))
      return true;
 
   char hostname[ 256 ];
@@ -792,9 +798,14 @@
   for(char *p = hostname; *p; p++)
      *p = tolower(*p);
 
-  return (host() == QString::fromLatin1( hostname ));
+  return (url.host() == QString::fromLatin1( hostname ));
 }
 
+bool KUrl::isLocalFile() const
+{
+  return ::isLocalFile( *this );
+}
+
 void KUrl::setFileEncoding(const QString &encoding)
 {
   if (!isLocalFile())
@@ -849,32 +860,49 @@
   return QString();
 }
 
-bool KUrl::hasSubUrl() const
+inline static bool hasSubUrl( const QUrl& url )
 {
   // The isValid call triggers QUrlPrivate::validate which needs the full encoded url,
   // all this takes too much time for isLocalFile()
-  if ( scheme().isEmpty() /*|| !isValid()*/ )
+  if ( url.scheme().isEmpty() /*|| !isValid()*/ )
     return false;
-  const QString ref = fragment();
+  const QByteArray ref( url.fragment().toLatin1() );
   if (ref.isEmpty())
      return false;
-  if (ref.startsWith("gzip:"))
+  switch ( ref.data()[0] ) {
+  case 'g':
+    if ( ref.startsWith("gzip:") )
+      return true;
+    break;
+  case 'b':
+    if ( ref.startsWith("bzip:") || ref.startsWith("bzip2:") )
+      return true;
+    break;
+  case 't':
+    if ( ref.startsWith("tar:") )
+      return true;
+    break;
+  case 'a':
+    if ( ref.startsWith("ar:") )
+      return true;
+    break;
+  case 'z':
+    if ( ref.startsWith("zip:") )
+      return true;
+    break;
+  default:
+    break;
+  }
+  if ( url.scheme() == "error" ) // anything that starts with error: has suburls
      return true;
-  if (ref.startsWith("bzip:"))
-     return true;
-  if (ref.startsWith("bzip2:"))
-     return true;
-  if (ref.startsWith("tar:"))
-     return true;
-  if (ref.startsWith("ar:"))
-     return true;
-  if (ref.startsWith("zip:"))
-     return true;
-  if ( scheme() == "error" ) // anything that starts with error: has suburls
-     return true;
   return false;
 }
 
+bool KUrl::hasSubUrl() const
+{
+  return ::hasSubUrl( *this );
+}
+
 QString KUrl::url( AdjustPathOption trailing ) const
 {
   if ( trailing == AddTrailingSlash && !path().endsWith( QLatin1Char('/') ) ) {
@@ -1443,6 +1471,10 @@
         options |= QUrl::StripTrailingSlash;
     if ( _options & KUrl::CompareWithoutFragment )
         options |= QUrl::RemoveFragment;
+#ifdef Q_WS_WIN
+    if ( ::isLocalFile( u1 ) && ::isLocalFile( u2 ) )
+      return 0 == QString::compare( u1.toString( options ), u2.toString( options ), Qt::CaseInsensitive );
+#endif
     return u1.toString( options ) == u2.toString( options );
 
 #if 0
--- trunk/KDE/kdelibs/kfile/kfilewidget.cpp #794820:794821
@@ -134,6 +134,8 @@
 
     void addToRecentDocuments();
 
+    QString locationEditCurrentText() const;
+
     // the last selected url
     KUrl url;
 
@@ -207,6 +209,30 @@
                                                   "This feature can be controlled by clicking with the right mouse button "
                                                   "and selecting a preferred mode from the <b>Text Completion</b> menu.")  "</qt>";
 
+// returns true if the string contains "<a>:/" sequence, where <a> is at least 2 alpha chars
+static bool containsProtocolSection( const QString& string )
+{
+    int len = string.length();
+    static const char prot[] = ":/";
+    for (int i=0; i < len;) {
+        i = string.indexOf( QLatin1String(prot), i );
+        if (i == -1)
+            return false;
+        int j=i-1;
+        for (; j >= 0; j--) {
+            const QChar& ch( string[j] );
+            if (ch.toAscii() == 0 || !ch.isLetter())
+                break;
+            if (ch.isSpace() && (i-j-1) >= 2)
+                return true;
+        }
+        if (j < 0 && i >= 2)
+            return true; // at least two letters before ":/"
+        i += 3; // skip : and / and one char
+    }
+    return false;
+}
+
 KFileWidget::KFileWidget( const KUrl& startDir, QWidget *parent )
     : QWidget(parent), KAbstractFileWidget(), d(new KFileWidgetPrivate(this))
 {
@@ -576,8 +602,10 @@
     // can only be used if the user didn't type any filenames/urls himself
     const KFileItemList items = d->ops->selectedItems();
 
+    const QString locationEditCurrentText( d->locationEditCurrentText() );
+
     if ( (mode() & KFile::Directory) != KFile::Directory ) {
-        if ( d->locationEdit->currentText().trimmed().isEmpty() ) {
+        if ( locationEditCurrentText.isEmpty() ) {
             // allow directory navigation by entering a path and pressing
             // enter, by simply returning we will browse the new path
             if (items.isEmpty())
@@ -648,10 +676,9 @@
     KUrl selectedUrl;
 
     if ( (mode() & KFile::Files) == KFile::Files ) {// multiselection mode
-        QString locationText = d->locationEdit->currentText();
-        if ( locationText.contains( '/' )) {
+        if ( d->locationEditCurrentText().contains( '/' ) ) {
             // relative path? -> prepend the current directory
-            KUrl u( d->ops->url(), KShell::tildeExpand(locationText));
+            KUrl u( d->ops->url(), KShell::tildeExpand( locationEditCurrentText ));
             if ( u.isValid() )
                 selectedUrl = u;
             else
@@ -662,7 +689,7 @@
     }
 
     else {
-        selectedUrl = d->getCompleteUrl(d->locationEdit->currentText());
+        selectedUrl = d->getCompleteUrl( locationEditCurrentText );
 
         // appendExtension() may change selectedUrl
         d->appendExtension (selectedUrl);
@@ -690,7 +717,7 @@
         kDebug(kfile_area) << "Directory";
         bool done = true;
         if ( d->url.isLocalFile() ) {
-            if ( d->locationEdit->currentText().trimmed().isEmpty() ) {
+            if ( locationEditCurrentText.isEmpty() ) {
                 QFileInfo info( d->url.toLocalFile() );
                 if ( info.isDir() ) {
                     d->filenames.clear();
@@ -718,7 +745,7 @@
                 {
                     if ( d->ops->dirOnlyMode() )
                     {
-                        KUrl fullURL(d->url, d->locationEdit->currentText());
+                        KUrl fullURL(d->url, locationEditCurrentText);
                         if ( QFile::exists( fullURL.toLocalFile() ) )
                         {
                             d->url = fullURL;
@@ -732,7 +759,7 @@
                     }
                 }
 
-                d->filenames = d->locationEdit->currentText();
+                d->filenames = locationEditCurrentText;
                 emit accepted(); // what can we do?
             }
 
@@ -752,6 +779,17 @@
         if ( done )
             return;
     }
+    else { // we don't want dir
+        KUrl::List urls = d->tokenize( locationEditCurrentText );
+        if ( urls.count()==1 && urls.first().isLocalFile() ) {
+            QFileInfo info( urls.first().toLocalFile() );
+            if ( info.isDir() && this->selectedUrl().isValid() && !this->selectedUrl().equals( urls.first(), KUrl::CompareWithoutTrailingSlash ) ) {
+                setSelection( info.absolutePath() );
+                slotOk();
+                return;
+            }
+        }
+    }
 
     if (!KAuthorized::authorizeUrlAction("open", KUrl(), d->url))
     {
@@ -762,10 +800,10 @@
 
     KIO::StatJob *job = 0L;
     d->statJobs.clear();
-    d->filenames = KShell::tildeExpand(d->locationEdit->currentText());
+    d->filenames = KShell::tildeExpand( locationEditCurrentText );
 
     if ( (mode() & KFile::Files) == KFile::Files &&
-         !d->locationEdit->currentText().contains( '/' )) {
+         !d->locationEditCurrentText().contains( '/' ) ) {
         kDebug(kfile_area) << "Files\n";
         KUrl::List list = d->parseSelectedUrls();
         for ( KUrl::List::ConstIterator it = list.begin();
@@ -1129,7 +1167,7 @@
 // Protected
 void KFileWidgetPrivate::_k_urlEntered(const KUrl& url)
 {
-    QString filename = locationEdit->currentText();
+    QString filename = locationEditCurrentText();
     selection.clear();
 
     KUrlComboBox* pathCombo = urlNavigator->editor();
@@ -1289,9 +1327,8 @@
 
     urlList.clear();
     if ( filenames.contains( '/' )) { // assume _one_ absolute filename
-        static const QString &prot = KGlobal::staticQString(":/");
         KUrl u;
-        if ( filenames.indexOf( prot ) != -1 )
+        if ( containsProtocolSection( filenames ) )
             u = filenames;
         else
             u.setPath( filenames );
@@ -1786,7 +1823,7 @@
     if (!autoSelectExtCheckBox->isChecked() || extension.isEmpty())
         return;
 
-    QString urlStr = locationEdit->currentText();
+    QString urlStr = locationEditCurrentText();
     if (urlStr.isEmpty())
         return;
 
@@ -1834,7 +1871,7 @@
 
         // add extension
         const QString newText = urlStr.left (fileNameOffset) + fileName + extension;
-        if ( newText != locationEdit->currentText() )
+        if ( newText != locationEditCurrentText() )
         {
             locationEdit->setItemText(locationEdit->currentIndex(),urlStr.left (fileNameOffset) + fileName + extension);
             locationEdit->lineEdit()->setModified (true);
@@ -1847,7 +1884,7 @@
 void KFileWidgetPrivate::updateFilter()
 {
     if ((operationMode == KFileWidget::Saving) && (ops->mode() & KFile::File) ) {
-        const QString urlStr = locationEdit->currentText();
+        const QString urlStr = locationEditCurrentText();
         if (urlStr.isEmpty())
             return;
 
@@ -2090,7 +2127,7 @@
 void KFileWidgetPrivate::setNonExtSelection()
 {
     // Enhanced rename: Don't highlight the file extension.
-    QString filename = locationEdit->currentText().trimmed();
+    QString filename = locationEditCurrentText();
     QString extension = KMimeType::extractKnownExtension( filename );
 
     if ( !extension.isEmpty() )
@@ -2146,4 +2183,9 @@
     Q_UNUSED(data);
 }
 
+QString KFileWidgetPrivate::locationEditCurrentText() const
+{
+    return QDir::fromNativeSeparators(locationEdit->currentText().trimmed());
+}
+
 #include "kfilewidget.moc"
--- trunk/KDE/kdelibs/kio/kio/kurlcompletion.cpp #794820:794821
@@ -955,7 +955,13 @@
 	}
 	else if ( !cwd.isEmpty() ) {
 		// current directory
-		dirList.append( cwd + QLatin1Char('/') + directory );
+		QString dirToAdd = cwd;
+		if ( !directory.isEmpty() ) {
+			if ( !cwd.endsWith('/') )
+				dirToAdd.append( QLatin1Char('/') );
+			dirToAdd.append( directory );
+		}
+		dirList.append( dirToAdd );
 	}
 
 	// No hidden files unless the user types "."


More information about the Kde-windows mailing list