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