diff --git a/KDE4PORTING.html b/KDE4PORTING.html
index 91a5f422cb..e4ed2ebf5f 100644
--- a/KDE4PORTING.html
+++ b/KDE4PORTING.html
@@ -1,2941 +1,2959 @@
Guide to Porting Applications to KDE 4.0
Porting Applications to KDE 4.0
Note
All modules should build from /trunk/KDE/kdelibs; there is no snapshot branch any longer. Major changes happen on Mondays (in any timezone) so expect rapid changes during that time. Things should be generally stable otherwise, but this is the development area, so there are no guarantees.
Deprecated classed that have been renamed to e.g. K3Foo are in kde3support.
This document contains the changes you have to apply to programs written for
KDE 3.x when you want to port them to KDE 4.0.
-As a start you should have a look at doc/html/porting4.html in the Qt package,
+As a start you should have a look at doc/html/porting4.html in the Qt package,
or this page online.
To start with the porting, you can run "qt3to4 -strict list_of_files"
followed by kdesdk/scripts/qt4/adapt-to-qt4-api.pl and kdesdk/scripts/qt4/adapt-to-kde4-api.pl
-
The "const char *name" arguments in the constructors of QObject derived classes
have been removed. Use setObjectName() instead if the object name is really necessary.
- The define KDE_DEPRECATED must be used now at the start of the declaration
(but still after an eventual "static", "inline" or "virtual" keyword).
KDE_DEPRECATED does not work with constructors, use KDE_CONSTRUCTOR_DEPRECATED
instead.
NOTE: kdefx is still being discussed. The following text represents "the
current plan" to the best of my knowledge, and is being provided to inform the
developement community. Future-tense text is not set in stone. -- mwoehlke
kdefx is slated for removal if possible. If the list of replacements doesn't
help, and you are not the only user of a particular function, please raise the
issue on k-c-d. Include what
function you are using and who else is using it. If you are the only user,
you should copy the required code to your application.
- KStyle moved to kdeui
- KCPUInfo is removed (for now it is just not exported, but in the future will probably go away entirely).
Use Solid::Processor instead.
- Qt has gradients now, please use them if you can
- kdrawutils.h is gone.
- If you already ported your code to KDE4, your code now has a copy of whatever kdrawutil code you were using.
- If you haven't ported your code yet, you get to find a copy of what you need in svn's revision history (or in branches/3.5).
- KPixmapSplitter is going to be removed. Use instead this code, courtesy of Matt Newell:
QRect getFlowedRect(int index, const QSize &itemSize,
int layoutWidth, int h_spacing, int v_spacing)
{
// NOTE: if using h_spacing, depending on your use you might want to replace
// layoutWidth with (layoutWidth + h_spacing)
int itemsPerRow = layoutWidth / (itemSize.width() + h_spacing);
return QRect( QPoint( (index % itemsPerRow) * (itemSize.width() + h_spacing),
(index / itemsPerRow) * (itemSize.height() + v_spacing) ),
itemSize );
}
KPixmap
Removed. Use QPixmap instead.
- kuniqueapp.h => kuniqueapplication.h
- klargefile.h => kde_file.h
- kcatalogue.h => kcatalog.h
- kaccelmanager.h => kacceleratormanager.h
- kprocctrl.h => k3protocolcontroller.h
- KInstance was renamed to KComponentData
- KGlobalAccel moved to kdeui
- KGlobalSettings moved to kdeui
- KIconLoaded moved to kdeui
- KSessionManaged renamed to KSessionManager and moved to kdeui
- KShortcut moved to kdeui
KAboutData
- KAboutData::setTranslator needs different parameters now.
(Please see the corresponding Doxygen comment for the current state.)
- new catalogName parameter to constructor can be null or empty, then appName is used as catalog name
- all setter methods return object reference, so they can be chained to avoid repeating object name (eg. for addAuthor(), addCredits(), etc.)
I18N_NOOPs in general replaced with KLocalizedString, produced by ki18n()/ki18nc() calls,
or just KLocalizedString() if wanted empty.
See also the I18N section below.
KAccel
Removed. Replaced by the new KAction/QAction framework.
See KActionCollection::setAssociatedWidget() if you need the old KAccel widget-binding behavior.
KAccelAction
- Removed. Replaced by the new KAction/QAction framework.
- [Old note] KDE3 supported 3 modifier key shortcuts and 4 modifier key (3+META) shortcuts, because earlier versions of Qt3 didn't
support a META modifier/WIN key. This is changed, so now all shortcuts can be 4 modifier key. All instances of
shortcut3 and shortcut4 have been reduced just to "shortcut".
- [Old note] The constructor, init(), and insert() functions now only take only KShortcut "default" argument instead of two
- [Old note] Removed shortcutDefault3() and shortcutDefault4(). Use shortcutDefault() instead
KAccelBase
Removed. Replaced by the new KAction/QAction framework.
KApplication
- Moved to kdeui. This means no change for GUI applications.
For text-based applications, you should consider switching to QCoreApplication + KComponentData.
There are two cases:
- Command-line argument parsing needed: use KCmdLineArgs as usual and then
QCoreApplication app( KCmdLineArgs::qtArgc(), KCmdLineArgs::qtArgv() );
- No command-line argument parsing needed: simply create a KComponentData (with &aboutData or just a name),
and then use
QCoreApplication app( argc, argv );
- Of course if you don't create a KApplication, then you should turn any "kapp->" into "qApp->" in the
rest of the code.
- KApplication does not inherit KInstance/KComponentData anymore. The KComponentData object is
available through KGlobal::mainComponent() (if KApplication is the first object to create a
KComponentData object, but everything else probably is a bug).
- caption() was moved to KGlobal; you can now use it if you don't have a KApplication object
- makeStdCaption() was moved to KDialog::makeStandardCaption()
- isRestored() should now use qApp->isSessionRestored().
- keyboardMouseState() has been removed, its functionality is now provided by QApplication::keyboardModifiers() and QApplication::mouseButtons()
- random() has been moved to the KRandom class
- For using the kiosk restriction/authorization system you have to use the functions provided in KAuthorized.
- invoke* functions have been moved to ktoolinvocation. there are static methods invoke*, if you want to use slots as before connect to the invoke* slots of KToolInvocation::self()
- startService*, kdeinitExec* have been moved to KToolInvocation
- static void addCmdLineOptions(); has moved to KCmdLineArgs::addStdCmdLineOptions
- getDisplay() has been removed, its functionality is now provided by QX11Info::display()
- cut(), copy(), paste(), clear() and selectAll() were moved to KStandardAction. Rather then creating a copy action and connecting it to kapp just use the KStandardAction::copy
- guiEnabled() was removed, use QApplication::type() instead.
- ref()/deref() was moved to KGlobal (as static methods)
- geometryArgument was removed, please use:
QString geometry;
KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
if (args && args->isSet("geometry"))
geometry = args->getOption("geometry");
- installSigpipeHandler() was removed.
- propagateSessionManager(), requestShutDown() methods and associated ShutdownConfirm, ShutdownType and ShutdownMode enums have been moved into the kworkspace library (which is found in kdebase/workspace/lib); the methods are static functions in KWorkspace namespace.
- The shutDown() signal has been removed, use QApplication's signal aboutToQuit()
- enableStyles(), disableStyles(), and the constructor argument has been removed.
- installKDEPropertyMap has been moved into k3sqlpropertymap.h and renamed to kInstallKDEPropertyMap. It can be used to keep old c
ode that uses the Q3Data* classes working.For new code, use User in the meta object to determine which Q_PROPERTY to use for any widget.
const QMetaObject *metaObject = widget->metaObject();
for (int i = 0; i < metaObject->propertyCount(); ++i) {
const QMetaProperty metaProperty = metaObject->property(i);
if (metaProperty.isUser()) {
QString propertyToUse = metaProperty.name();
break;
}
}
- caption() has moved to KComponentData
- makeStdCaption(const QString&, bool, bool) has moved to KDialog and changed signature to makeStdCaption(const QString&, CaptionFlags)
- addKipcEventMask() is unneeded now, and the signals like settingsChanged(), fontChanged() etc. with enums SettingsCategory have moved to KGlobalSettings::self() which is now a QObject
KAudioPlayer
Removed, use now Phonon::AudioPlayer
KCatalogue
Renamed to KCatalog. Method name parts with "catalogue" have been renamed to use "catalog" instead.
KCharsets
- KCharsets::codecForName cannot use glibc's i18n data anymore.
(Note: this feature was new in KDE 3.5 but never publicly announced.)
- The user-visible encoding names are now mostly upper-case
(instead of being always lower-case).
- KCharsets::languageForEncoding should be replaced
by KCharsets::descriptionForEncoding. The function KCharsets::languageForEncoding is planned to be removed before the release of KDE4.
- The status of the encoding UTF-7 is not guaranteed to be kept, as Qt
does not support this encoding.
- TODO: see which member functions can be removed. The functions handling entites are planned to be moved out of the class KCharsets.
KCodecs
- All methods using a QCString removed. The methods use QByteArray now.
- Header renamed to kcodecs.h
KConfigBackend
- Removed filename(), use fileName()
KSimpleConfig
This class was removed. It was a very thin wrapper around KConfig and should
be replaced.
- If you use an absolute path, just change KSimpleConfig with KConfig - there was
no difference between uses of them for KDE3 either.
- If you want just the local file to open replace KSimpleConfig("file") with
KConfig("file", KConfig::OnlyLocal);
KConfig
- setGroup is deprecated as it creates state. Used group(QString) to receive
a KConfigGroup object or create a KConfigGroup object yourself:
KConfig *config = KGlobal::config();
config->setGroup("Group");
config->writeEntry("Key", 0);
should be rewritten as
KConfigGroup config = KGlobal::config()->group("Group");
config.writeEntry("Key", 0);
- setDesktopGroup is gone. Use KDesktopFile (and its desktopGroup() method) if
you want to read .desktop files - or use group("Desktop Entry") instead
- It's no longer necessary to specify a KConfig object is read-only - they are always
unless you use change it
- The KConfig constructors were changed to receive flags instead of boolean values, i.e.
- KConfig("file", false /* read-write */, false /* no globals */); becomes
KConfig("file", KConfig::NoGlobals); (note the read-write flag is gone)
- KConfig("file", true);becomes KConfig("file");
KConfigBase
KConfigGroupSaver
The class KConfigGroupSaver has been removed, instead use KConfigGroup. The
difference is a KConfigGroupSaver object directly affects the config object it
is acting on, while a KConfigGroup object only ensures the entries read or
written through it are in the correct group.
Instead of:
KConfig *config = KGlobal::config();
KConfigGroupSaver saver(config, "group name");
...
config->readXXX("entry name");
should be rewritten as:
KConfigGroup cg = KGlobal::config()->group("group name");
...
cg.readXXX("entry name");
KCmdLineArgs
- static void init(int _argc, char **_argv, const char *_appname, const char *_description, const char *_version, bool noKApp = false) KDE_DEPRECATED; -> static void init(int _argc, char **_argv, const QByteArray &appname, const QByteArray &catalog, const KLocalizedString &programName, const QByteArray &version, const KLocalizedString &description = KLocalizedString(), StdCmdLineArgs stdargs=StdCmdLineArgs(CmdLineArgQt|CmdLineArgKDE)));
- noKApp parameter is gone, instead: Q_FLAGS(StdCmdLineArgs)
- new catalog parameter can be null or empty, then appname is used as catalog name
- KLocalizedString objects produced by ki18n()/ki18nc() calls (instead of previous I18N_NOOPs), or just KLocalizedString() if needed empty
- static void usage(const QString &error) -> static void usageError(const QString &error)
KCmdLineOptions
Now a proper class, instead of statically initialized struct. Use add() method for adding options (option syntax same as before); add() returns object reference, so calls can be chained to avoid repeating variable name all the way.
- value based class using shared data: In KDE4 don't work with pointers to KComponentData anymore.
Internally it is reference counted and the data deleted when the last reference goes out of scope.
- config() returns a KSharedConfigPtr
- sharedConfig() was removed in favour of config()
- iconLoader() was moved to KApplication
- newIconLoader() was moved to KApplication
KDesktopFile
- QString filename() const -> QString fileName() const
- more standards compliant. See
Desktop Entry Spec
- .kdelnk files are no longer supported, rename to .desktop.
- deprecated header [KDE Desktop Entry], change to [Desktop Entry], using desktopGroup()
- type FSDev is no longer supported, change to FSDevice
- Same as in KConfig: the use of readEntry() or writeEntry() on a KDesktopFile should
be replaced by readEntry/writeEntry on a KConfigGroup. By default the desktopGroup() of
the KDesktopFile was used, otherwise use group("another_group").
KExtendedSocket
This class has been removed. See below on KNetwork::K*Socket.
KFilterDev
- device() -> createDevice() to indicate that you must delete the device afterwards.
KGlobal
- "int kasciistricmp( const char *str1, const char *str2 )" has been moved into kascii.h
- "KIconLoader* iconLoader()" has been moved to KIconLoader::global()
- instance() renamed to mainComponent()
- activeInstance() renamed to activeComponent()
- setActiveInstance() renamed to setActiveComponent()
- static members _locale, _instance and so on are private now, if you want to get or set the
KLocale use locale()/setLocale()/hasLocale() and if you want to know whether a mainComponent is set use
hasMainComponent()
- config() returns a KSharedConfig::Ptr now instead of KConfig*
- sharedConfig() has been removed in favour of config()
KIcon
Deprecated and renamed to K3Icon; replacement is KIcon in kdeui.
Note: at the moment you have to keep using K3Icon as a namespace for states, groups, and contexts though.
KInstance
Renamed to KComponentData
KIPC
Removed. Use KGlobalSettings::self()->emitChange() instead of KIPC::sendMessageAll().
KKey
Removed. Use plain ints as the Qt key code instead.
- When replacing KKey(QKeyEvent*), you need to OR the event->key() and event->modifiers() to get the replacement.
- The QtWIN enum has been removed. Use Qt::META or Qt::MetaModifier instead.
- modFlagLabel() was removed, use either KKeyServer::modToStringUser(), or QKeySequence(Qt::yourmodifier).toString()
KKeyNative
Removed. Use plain ints as the Qt key code instead.
KKeySequence
Removed. Use QKeySequence instead.
Note that QKeySequence expects multiple shortcuts to be separated by ", " (i.e. a comma then a space) in converting from text.
KLibLoader
- use KPluginLoader or KService::createInstance instead whenever possible
- The resolve(const char* name) and symbol(const char* name) methods were merged and renamed to resolveSymbol
- bool hasSymbol was removed, use resolveFunction instead
- resolveFunction( const char* name ) was added which returns not a void* but a KLibrary::void_function_ptr which can be used as a void* would in boolean tests and for making subsequent function calls.
KLibFactory
- renamed to KPluginFactory
- create methods take a QVariantList instead of QStringList
KGenericFactory
- use K_PLUGIN_FACTORY macro instead: this will require to change your plugin constructor from QStringList to QVariantList
- instead of K_EXPORT_COMPONENT_FACTORY use K_EXPORT_PLUGIN (defined with KPluginLoader) which adds Qt and kdelibs version information that KPluginLoader uses to check the validity of the plugin.
KLocale
- QString formatNumber(const QString &numStr) const -> QString formatNumber(const QString &numStr, bool round=true, int precision=2) const;
- bool weekStartsMonday() const -> int weekStartDay() const
- QString monthName(int i, bool shortName = false) const -> QString KCalendarSystem::monthName (int month, int year, bool shortName = false) const = 0; or QString KCalendarSystem::monthName (const QDate & date, bool shortName = false ) const = 0;
- QString weekDayName(int i, bool shortName = false) const -> calendar()->weekDayName
- QString monthNamePossessive(int i, bool shortName = false) const -> calendar()->monthNamePossessive()
- void setWeekStartsMonday(bool start) -> setWeekStartDay
- QString formatDate(const QDate&, bool shortFormat = false) const -> QString formatDate(const QDate&, DateFormat = LongDate) const
- QString formatDateTime(const QDateTime&, bool shortFormat = true, bool includeSecs = false) const -> QString formatDateTime(const QDateTime&, DateFormat = ShortDate, bool includeSecs = false) const
- languages() -> languageList()
- formatMoney(const QString &numStr) -> QString formatMoney(double num, const QString & currency = QString::null, int digits = -1) const;
- charset() -> gone
- setCharset() -> gone
- removeCatalogue was renamed to removeCatalog
- QStringList languagesTwoAlpha() -> QStringList languageList()
- QStringList allLanguagesTwoAlpha() -> QStringList allLanguagesList()
- QStringList allCountriesTwoAlpha() -> QStringList allCountriesList()
- QString twoAlphaToLanguageName(const QString &language) -> QString languageCodeToName(const QString &language)
- QString twoAlphaToCountryName(const QString &country) -> QString countryCodeToName(const QString &country)
See also the I18N section below.
KMacroExpander
- KMacroExpander now takes a QHash and not a QMap
KMimeSourceFactory
KMimeSourceFactory was automatically instanciated by KApplication which allowed the use of "icon:name" in Qt richtext.
Q3MimeSourceFactory being in Qt3Support, and this feature being very rarely used, K3MimeSourceFactory isn't instanciated
automatically anymore, you need to call K3MimeSourceFactory::install() in your main if you still depend on this feature.
KNetwork::KIpAddress
Removed. Use QHostAddress instead.
KNetwork::KResolver
Removed. If you need to resolve a hostname, use QHostInfo from QtNetwork.
KNetwork::KSocketAddress and KNetwork::KInetSocketAddress
Removed. Use QHostAddress and an integer (a quint16_t) to store the port number.
KNetwork::KUnixSocketAddress
Removed. Simply use a QString to represent the path or identifier. See the documentation on KLocalSocket.
KNetwork::K*Socket
- All of these classes are deprecated. Use the QTcpSocket,
QUdpSocket and QTcpServer equivalents from QtNetwork.
- When porting, use KSocketFactory when creating any sockets that
are used to communicate with remote hosts (that is, anything that is
not "localhost"). Examples follow:
Connecting to a remote host:
Old code:
QString host;
int port;
KBufferedSocket *socket = new KBufferedSocket(parent);
if (!socket->connect(host, QString::number(port))) {
// error happened
// deal with it
}
connect(socket, SIGNAL(connected(KResolverEntry)), SLOT(socketConnected()));
connect(socket, SIGNAL(gotError(int)), SLOT(socketError(int)));
New code:
QString protocol;
QString host;
int port;
QUrl url(QString("%1://%2:%3").arg(prototocol, host).arg(port));
QTcpSocket *socket = KSocketFactory::connectToHost(protocol, host, port, parent);
// alternatively:
// QTcpSocket *socket = KSocketFactory::connectToHost(url, parent);
connect(socket, SIGNAL(connected()), SLOT(socketConnected()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError), SLOT(QAbstractSocket::SocketError)));
Opening a socket for receiving remote connections:
Old code:
int port;
KServerSocket *ss = new KServerSocket(QString::number(port), parent);
connect(ss, SIGNAL(readyAccept()), this, SLOT(slotReadyAccept()));
connect(ss, SIGNAL(gotError(int)), this, SLOT(slotSocketError(int)));
ss->listen();
New code:
QString protocol;
int port;
QTcpServer *ts = KSocketFactory::listen(protocol, QHostAddress::Any, port, parent);
connect(ts, SIGNAL(newConnection()), this, SLOT(slotReadyAccept()));
- Caveat: all member functions in QTcpSocket
are asynchronous and buffered. There's no equivalent
"blocking" mode for QTcpSocket. If you need an action to complete,
you have to use waitForReadyRead and flush
(or waitForBytesWritten) in the socket object. If you need
to wait for a connection to be established,
use KSocketFactory::synchronousConnectToHost.
KNotifyClient
Replaced by KNotification. The API is quite similar, but the config file need to be updated. See KNotification documentation
KProcess
Deprecated and renamed to K3Process, header is k3process.h. Use QProcess instead.
- setExecutable() was removed in favor of using operator <<
- getPid() was removed for just pid()
KProcCtrl
Deprecated and renamed to K3ProcessController, header is k3processcontroller.h.
KProcIO
Deprecated and renamed to K3ProcIO, header is k3procio.h.
KRegExp
Removed. Use QRegExp instead.
KRFCDate
This class has been deprecated by KDateTime. It has been renamed K3RFCDate and moved to the libkde3support. The following method changes make porting easy:
- KRFCDate::parseDate( string ) becomes KDateTime::fromString( string, KDateTime::RFCDate).toTime_t();
- KRFCDate::parseDateISO8601( string ) becomes KDateTime::fromString( string ).toTime_t();
- KRFCDate::localUTCOffset() becomes KDateTime::Spec::LocalZone().utcOffset / 60. Note that the KRFCDate version returned minutes while KDateTime returns seconds.
KSaveFile
- KSaveFile has been modified from its KDE 3.x behavior to allow for new backup methods:
- KSaveFile::backupFile() will use the backup behavior specified in KConfig.
- KSaveFile::simpleBackupFile() will emulate the KDE 3.x behavior
- KSaveFile::numberedBackupFile() will create a numbered set of backup files (default: 10)
- KSaveFile::rcsBackupFile() will use rcs to maintain the backup file
- KSaveFile now derives from QFile so you can use it just like you would use a normal QFile. The close() function has been renamed to finalize(). Use the error() and errorString() functions to check for errors instead of status().
- KSaveFile::close() is now KSaveFile::finalize()
- You must call KSaveFile::open() to create the file.
KShortcutDialog
Removed, see KKeySequenceWidget/KShortcutWidget.
KShortcutList and derivatives
Removed - no longer needed. Saving and loading of shortcuts is now performed in KActionCollection, KGlobalAccel, and KStandardShortcut.
KSortableValueList
- Has been ported to QList, renamed to KSortableList and the header is ksortablelist.h
KStandardDirs
- boolean values as parameters for recursive, unique and checking for executability in the following methods were changed to instead take SearchOptions flags for improved code readability:
- calcResourceHash
- findAllResources
- findResource
- findExe
- findAllExe
- Removed deprecated methods
- Removed WhatThis, use WhatsThis
- shortcutDefault3() and shortcutDefault4() have been removed, use shortcutDefault() instead
KStaticDeleter
Either use K3StaticDeleter or port to the K_GLOBAL_STATIC macro.
KStdAccel
Renamed to KStandardShortcut
KStringHandler
- static QString ljust( const QString &text , int width ) -> QString::leftJustified
- static QString rjust( const QString &text , int width ) -> QString::rightJustified
- matchFilename -> matchFileName
- static QString word( const QString &text , int pos ) -> QString::section
- ::randomString() has been moved to KRandom::randomString()
- ::lPixelSqueeze( text, fm, width ) -> fm.elidedText( text, Qt::ElideLeft, width )
- ::cPixelSqueeze( text, fm, width ) -> fm.elidedText( text, Qt::ElideMiddle, width )
- ::rPixelSqueeze( text, fm, width ) -> fm.elidedText( text, Qt::ElideRight, width )
KTempDir
- existing() was removed, use exists() instead
- setAutoDelete() renamed to setAutoRemove()
- The default for setAutoRemove() is now true instead of false
- qDir() was removed as it was unused
KTempFile
Deprecated and renamed to K3TempFile. Use KTemporaryFile instead.
When porting old KTempFile calls to KTemporaryFile, you need to remember that KTempFile by default will not automatically remove the fileonce the object is destroyed, but KTemporaryFile will! You also need to call open() in order to actually create the file.
KURL
- Renamed to KUrl, but a typedef is available for source compatibility
- KUrl inherits QUrl now, but the API offered by KUrl is mostly unchanged
- filename() has been removed, use fileName() instead
- isMalformed -> !isValid()
- prettyURL(0,KUrl::StripFileProtocol) -> pathOrURL()
- fromPathOrURL() is deprecated, use the KUrl(str) constructor which now accepts both paths and urls
- htmlURL() had to be removed, please use Qt::escape(url.prettyURL()) now, with #include <QTextDocument>.
This requires libQtGui, which is why it can't be in KUrl anymore.
- url(0,106) or any other use of the 'mib enum' for encoding has been removed. QUrl is UTF8 based, and the world is becoming more and more utf8 based as well, the old encoding hacks inside urls should disappear.
- Runtime behavior change: port() used to return 0 if no port was specified. It now returns -1 in that case, or you can use port(defaultPort) to set what it should return if no port was specified.
- adjustPath(), path(), encodedPathAndQuery() , url() , prettyUrl() was taking a int argument for handling trailing slash that has been replaced by an enum AdjustPathOption (0 => KUrl::LeaveTrailingSlash, 1 => KUrl::AddTrailingSlash, -1 => KUrl::RemoveTrailingSlash).
- cleanPath(), queryItems(), fileName(), directory(), equals() now take a QFlags argument instead of boolean
- *URL* renamed to *Url*:
- hasSubURL() -> hasSubUrl()
- prettyURL() -> prettyUrl()
- pathOrURL() -> pathOrUrl()
- upURL() -> upUrl()
- isRelativeURL() -> isRelativeUrl()
- relativeURL() -> relativeUrl()
KURLDrag
This class has been moved to kde3support. Use KUrl::populateMimeData() and
KUrl::List::populateMimeData() in the drag/copy side,
and the static methods KUrl::List::canDecode() and KUrl::List::fromMimeData()
in the drop/paste side.
- Example: Replace
KURL::List uriList;
if ( KURLDrag::canDecode(e) && KURLDrag::decode( e, uriList ) ) {
by KUrl::List uriList = KUrl::List::fromMimeData( e->mimeData() );
if ( !uriList.isEmpty() ) {
KVMAllocator
Removed, as it was unused.
KWin
This class has been merged with KWinModule into class KWindowSystem (in kdeui).
- appStarted() removed, use KStartupInfo::appStarted() instead
- info(WId win) removed, use windowInfo() instead
- struct Info was removed, use WindowInfo instead
KWinModule
This class has been merged with KWinModule into class KWindowSystem (in kdeui).
Don't create instances, use static functions and KWindowSystem::self() for connecting to signals.
- Functions related to systemtray have been removed. They worked only with the obsolete
KDE systray mechanism.
- stackingOrder() no longer returns a reference to a list. Make a copy of the value first if using iterators.
KWin::WindowInfo
This class has been renamed KWindowInfo and moved to its own header: KWindowInfo or kwindowinfo.h. This class is not to be confused with KWindowInfo in KDE3 which was a small utility class to display message in the window icon and title. KWindowInfo represents the windowing system information for a give window, such as its geometry, desktop positioning, type, name, etc.
locate
- locate() and locateLocal() moved into the namespace KStandardDirs
NETRootInfo
- NETRootInfo(Display *display, Window supportWindow, const char *wmName,unsigned long properties, int screen = -1, bool doActivate = true) ->
NETRootInfo(Display *display, Window supportWindow, const char *wmName,
const unsigned long properties[], int properties_size,
int screen = -1, bool doActivate = true); old properties is the first element of the new array
- unsigned long supported() -> const unsigned long* supportedProperties() const;
- unsigned long properties() const -> gone
- WindowType windowType() -> WindowType windowType( unsigned long supported_types ) const;
- kactionclasses.h went away, use the several kxxxaction.h instead
- kanimwidget.h was renamed to kanimatedbutton.h to reflect the class name
- kcolordlg.h went away, use kcolordialog.h
- kcolorbtn.h went away, use kcolorbutton.h
- kdatapik.h went away, use kdatepicker.h
- kdualcolorbtn.h went away, use kdualcolorbutton.h
- KLanguageButton (and therefore klanguagebutton.h) was removed due to licensing issues (GPLv2, which is not allowed in kdelibs)
- klistbox.h was renamed to klistwidget.h to reflect the class name
- kpassdlg.h went away, use kpassworddialog.h
- kxmlgui.h went away, use kxmlguifactory.h
- kfontcombo.h went away, use QFontComboBox
- libkwalletclient (which used to provide the KWallet class) has been merged with kdeui
- system color scheme accessors in kglobalsettings.h are deprecated, use kcolorscheme.h
- KPalette was renamed to KColorCollection
- KPaletteTable was renamed to KColorTable
KAboutContainer
Deprecated and renamed to K3AboutContainer. Use KAboutApplicationDialog or KAboutKdeDialog directly.
- KAboutContainer constructor int args have been replaced by Qt::Alignment
- addTitle int args replaced by Qt::Alignment
- addImage int args replaced by Qt::Alignment
KAboutContributor
Deprecated and renamed to K3AboutContributor. Use KAboutApplicationDialog or KAboutKdeDialog directly.
- void setURL( const QString& ) -> void setUrl( const QString& )
- QString getName( void ) const -> QString name() const
- QString getEmail( void ) const -> QString email() const
- QString getURL( void ) const -> QString url() const
- QString getWork( void ) const -> QString work() const
- signal void openURL() -> void openUrl()
KAboutDialog
Deprecated and renamed to K3AboutDialog. Use KAboutApplicationDialog or KAboutKdeDialog directly.
KAboutWidget
Deprecated and renamed to K3AboutWidget. Use KAboutApplicationDialog or KAboutKdeDialog directly.
- signal void openURL() -> void openUrl()
- void openURLSlot() -> void openUrlSlot()
Making KAction a subclass of QAction (actually QWidgetAction) brings KDE more into line with the Qt way of creating user interfaces, improves accessibility, and removes code duplication.
QAction in Qt4 is a true first-class citizen - all QWidgets now have a list of associated actions, and QToolBar, QMenu etc. all use this list directly to show the graphical items (widgets, entries in the menu, etc). This has replaced all usage of integers as "id"s. There is also a new QEvent (QActionEvent), and the corresponding virtual protected function in QWidget, actionEvent().
- KAction is now a subclass of QWidgetAction.
- Don't use setIconSet() anymore, use setIcon(KIcon(iconName)) instead
- activated(), activated(int) signals deprecated - use triggered() signal instead
- activate() is now trigger(), as in QAction
- there is a replacement for activation providing keyboard + mouse states, see triggered(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) [currently buggy]
- plugAccel(), unplugAccel(), kaccelCount() removed - they have no use now (accelerator management is inside Qt)
- itemId(), getToolButtonID() removed - actions no longer have ids, basically the QAction* is its replacement
- setGroup() / group() removed - use QActionGroup instead (setActionGroup() / actionGroup())
- ActivationReason has been removed (not supported by Qt). For a surrogate, you can connect to QMenu::triggered(QAction*), QToolBar::actionTriggered(QAction*), etc.
- setters are no longer slots; where they were used as such, an intermediary will be required
- New feature from Qt: statusTip() / setStatusTip(). Usually this will be the same as the tooltip. It appears in the status bar whenever the action is hovered in a QMenu. A porting convenience is being investigated for automatic toolTip() -> statusTip(), but the best solution is to set both.
- New feature: globalShortcut() and globalShortcutAllowed(). Automatically communicates with KGlobalAccel to register a global shortcut (i.e. one that does not need the application to have focus to be activated).
- setShortcut() now defaults to setting the default shortcut as well (as it was by far the most common use case). To just set the custom shortcut, use setShortcut(myShortcut, KAction::CustomShortcut)
- Renamed "Custom" shortcuts to "Active" shortcuts.
- Added setShortcut(QKeySequence &) to explicitly override QAction::setShortcut.
- Functions in KActionCollection or KXMLGUIFactory for example don't take or return KAction pointers
anymore but instead operate on QAction pointers. If you get compilation errors with code like the
following then just replace KAction with QAction:
QAction *a = actionCollection()->action("foo");
...
Also if you get errors about KAction being an unknown type it is often enough to forward declare
KAction in your header file.
- plug() -> QWidget::addAction()
- unplug() -> QWidget::removeAction()
- isPlugged() -> !action->associatedWidgets().isEmpty()
- containerCount() -> action->associatedWidgets().count()
- container(int i) -> action->associatedWidgets().value(i)
- hasIcon() -> !action->icon().isNull()
- setIconName(string) -> setIcon(KIcon(string))
- unplugAll() -> Rarely needed, but if you are sure that you need it replace it with the following
code:
foreach (QWidget *w, action->associatedWidgets())
w->removeAction(action);
- The KAction constructors changed completely. The constructors taking various action properties,
a pointer to an acion collection and the name of the action have been removed. The new pattern is to
create the actions like regular QObjects with a parent (owner). Then you set various properties using
setText, setIcon, etc. . As a last step the action can be added to the action collection with a name.
KAction *a = new KAction(this);
a->setText(i18n("I am ported"));
a->setIcon(KIcon("shiny"));
a->setShortcut(Qt::ControlModifier + Qt::Key_A);
actionCollection - > addAction("name_of_the_action", a);
KActionCollection additional provides convenience overloads for creating named KAction objects or
standard actions (KStandardAction). For example:
QAction *a = actionCollection -> addAction("action_name");
a->setText(i18n("I have been ported, too"));
connect(a, SIGNAL(triggered()), this, SLOT(portedToKde4()));
actionCollection -> addAction(KStandardAction::Copy, this, SLOT(copy()))
KActionCollection
- constructor (QWidget* watch, ..) and setWidget() replaced by {set|add|remove}AssociatedWidget() - allows actions to respond to matching key presses on a widget level (basically a convenience method to have all actions in the collection added to the associated widget(s) and their shortcut scopes set to Qt::WidgetShortcut).
- *AutoConnectShortcuts removed - irrelevant
- *accel() removed - irrelevant (KAccel no longer handles key presses)
- New functions setConfigGroup(), setConfigGlobal(), configGroup(), configIsGlobal() - the action collection now stores the group whether the config is global. referenced in readSettings() / writeSettings()
- readShortcutSettings() and writeShortcutSettings() renamed without the "Shortcut". Set the configGroup() with setConfigGroup() either prior to each call, or (preferably) at the creation time of the action collection.
- {set}HighlightingEnabled(), {connect|disconnect}Highlight() removed - highlighting is always enabled now
- actionHighlighted(), actionStatusText(), clearStatusText() removed - use QAction::setStatusTip() as a replacement. QStatusBars belonging to QMainWindow automatically get the statusTip() applied to them when they are moused over in a QMenu, via a QStatusTipEvent.
- groups() removed (now using QActionGroups) - see actionGroups() (and actionsWithoutGroup()) for replacement
- actions( const QString& group ) removed - use actionGroups() instead, and then QActionGroup::actions()
- action(const char* name, const char* className) removed: action(const QString& name), actions(const QString& name), actionOfType<Class>(const QString& name), actionsOfType<Class>(const QString& name) are the replacements
- insert(KAction *) -> addAction(const QString &name, QAction *action)
- remove(KAction *) -> removeAction(QAction *action)
- take(KAction *) -> takeAction(QAction *action)
KActionSelector
- Q3ListBox -> QListWidget
- selectedListBox -> selectedListWidget
- availableListBox -> availableListWidget
KActionSeparator
Used to be renamed to KSeparatorAction. KSeparatorAction/KActionSeparator is dead now. Just create a QAction object and call setSeparator(true); on it.
Note: you need to create multiple separator actions if you want to insert multiple separators into a widget, unlike with KDE3.
-
KActiveLabel
Deprecated and renamed to K3ActiveLabel. Use QLabel instead.
- Use QLabel::setOpenExternalLinks(true) for labels with hyperlinks.
- Use QLabel::setTextInteractionFlags(Qt::TextSelectableByMouse|Qt::TextSelectableByKeyboard) for labels whose text should be selectable by user.
- Inherits from KTextBrowser instead of Q3TextBrowser
- You don't need anymore to disconnect the linkClicked signal to handle manually link, use KTextBrowser::setNotifyClick(true)
- linkClicked -> KTextBrowser::urlClick
- Now a subclass of QToolButton, acts in a much more standard fashion
- size(), setSize() replaced by iconSize(), setIconSize()
- Call updateIcons() whenever you change the iconSize() (the setter is non-virtual :( )
KAnimWidget
Renamed to KAnimatedButton
KAuthIcon
Removed since it was not used.
KBugReport
- void updateURL() -> void updateUrl()
KButtonBox
Deprecated and renamed to K3ButtonBox. Use KDialogButtonBox instead. Add the role parameter to the addButton function. Or check if it can't be achieved using KDialog.
KCharSelectTable
Removed from public API. Use KCharSelect.
KCharSelect
- Cleaned up constructor, removed char, font and table arguments. The concept of showing tables isn't used any more and all functions/signals are removed. There is no need for a replacement.
- highlighted()/focusItemChanged()/activated() -> currentCharChanged(QChar)
- doubleClicked() -> charSelected(QChar)
- setFont()/font() -> setCurrentFont()/currentFont()
- fontChanged() -> currentFontChanged()
- QFont is used for fonts instead of a QString containg the font face.
- setChar()/chr() -> setCurrentChar()/currentChar()
- enableFontCombo(), enableTableSpinBox(), isFontComboEnabled() and isTableSpinBoxEnabled() are removed.
KColorCells
- KColorCells now inherits from QTableWidget instead of Q3GridView.
- numCells() has been replaced by count().
- getSelected() has been replaced by selectedIndex().
- The parameters of the colorSelected() and colorDoubleClicked() signals now include both the index of the color which
was selected and the color itself as arguments
- nrColors() was renamed to count()
- colorName() was renamed to name()
- getPaletteList() was renamed to installedCollections()
- color(int), name(int) and name(const QColor&) have been made const
KColorDrag
Deprecated and renamed to K3ColorDrag. Use QMimeData directly instead or KColorMimeData, which most closely resembles KColorDrag
KColorScheme
New class that provides access to system-wide, user configurable color roles.
Like QPalette, the return type is now QBrush instead of QColor.
As of 4.0 the brushes are solid colors, but this may change in the future.
Warning: KDE4 is trying really hard to abandon the notion that
the active palette == the inactive palette (because this is really helpful for
the oxygen windeco which does not use "traditional" windeco colors, and because
for various reasons kwin can't be entirely responsible for the effect). When
porting to KDE4, you will need to take this into consideration. The new class
KStatefulBrush has been added to help with this, as well as the adjustForeground
and adjustBackground methods of KColorScheme.
There are lots of bugs as a result of this; some in applications, and at
least a few in Qt. Please report application bugs to the appropriate maintainer
or list, and general (i.e. occurring in many/all applications) bugs to
k-c-d.
See the KColorScheme documentation for further information.
- palette() was renamed to name()
- slot setPalette() was renamed to slot setColors()
KComboBox
- void setURLDropsEnabled() -> void setUrlDropsEnabled()
- bool isURLDropsEnabled() -> bool urlDropsEnabled()
- void setEditURL() -> void setEditUrl()
- void addURL( ... ) -> void addUrl( ... )
- void insertURL( ... ) -> void insertUrl( ... )
- void changeURL( ... ) -> void changeUrl( ... )
KCommand
Deprecated and renamed to K3Command, header is k3command.h.
KCommandHistory
Deprecated and renamed to K3CommandHistory, header is k3command.h.
KCompletion
- enableSounds() was removed, use setSoundsEnabled()
- disableSounds() was removed, use setSoundsEnabled()
- isSoundsEnabled() -> soundsEnabled()
KConfigDialog
KContextMenuManager
- KContextMenuManager::insert() :
Old code:
KContextMenuManager::insert(widget, menu);
New code:
widget->setContextMenuPolicy(Qt::ActionsContextMenu);
widget->addActions(menu->actions());
- Otherwise consider handling the context menu in a contextMenuEvent() handler, which Qt
calls automatically on a right-mouse-button click or on activation by the context menu key.
There's no need to do anything in mousePressEvent/mouseReleaseEvent/keyPressEvent.
KCursor
- KCursor is now a QCursor, allowing for loading of non-standard icons from themes
- The static methods for loading various cursor types are gone, just use QCursor( Qt::CursorShape ) directly instead
KDatePicker
- signal void dateChanged(QDate); was replaced by void dateChanged( const QDate&);
- signal void dateEntered(QDate); was replaced by void dateEntered( const QDate&);
- signal void dateSelected(QDate); was replaced by void dateSelected( const QDate&)
- changed the order of the constructor's parameter
- removed getData() method. Use date() instead
- removed protected slot void selectWeekClicked()
KDateTable
- signal void dateChanged(QDate); was replaced by void dateChanged(const QDate&);
- changed the order of the constructor's parameter
- removed getData() method. Use date() instead
KDateWidget
- signal void changed(QDate); was changed by void changed(const QDate&)
KDialog
- Simplified ctor.
The following ctor
KDialog dlg( parent, i18n("my caption"), modal, Ok | Cancel | User1, Ok, false, i18n("Share File"))
should be rewritten as
KDialog dlg( parent );
dlg.setCaption( i18n("my caption") );
dlg.setModal( modal );
dlg.setButtons( Ok | Cancel | User1 );
dlg.setButtonGuiItem( User1, i18n("Share File") );
dlg.setDefaultButton( Ok );
dlg.showButtonSeparator( false );
- setButtonMask() -> setButtons() and setButtonGuiItem()
- setButtonBoxOrientation() -> setButtonsOrientation()
- setButtonOKText, setButtonApplyText , setButtonCancelText -> setButtonText( ButtonCode, const QString& )
- setDetails() -> setDetailsWidgetVisible()
- don't overide anymore slotFoo(). You now need to connect to FooClicked signal.
Or reimplement accept() and reject() to intercept the Ok and Cancel button
- enableButtonOK -> enableButtonOk (lower case 'k')
- enableButtonSeparator -> showButtonSeparator
KDialogBase
Deprecated. Use KDialog or KPageDialog instead.
- If the KDialogBase is Swallow or Plain mode you should replace it with KDialog, for
all other modes use KPageDialog
Replace
QWidget *page = plainPage();
with
QWidget *page = new QWidget( this );
setMainWidget( page );
All makeXXXMainWidget() methods can be replaced by the following schema:
KVBox *mainWidget = makeVBoxMainWidget();
replace with
KVBox *mainWidget = new KVBox( this );
setMainWidget( mainWidget );
- If you use a KPageDialog, the following steps must be taken...
Replace ctor
KDialogBase dlg( Tabbed, 0, parent, name, modal, i18n( "my caption" ), ... )
with
KPageDialog dlg( parent );
dlg.setFaceType( KPageDialog::Tabbed );
dlg.setObjectName( name );
dlg.setModal( modal );
dlg.setCaption( i18n( "my caption" ) );
...
All addXXXPage() methods can be replaced by the following schema:
KVBox *page = addVBoxPage( i18n( "My Title" ), i18n( "My Header" ), QPixmap( "image" ) );
replace with
KVBox *page = new KVBox();
KPageWidgetItem *item = addPage( page, i18n( "My Title" ) );
item->setHeader( i18n( "My Header" ) );
item->setIcon( KIcon( "image" ) );
KDockWindow
This class is obsolete and is provided for compatibility only. Use KSystemTrayIcon instead.
KDualColorButton
Removed since it was not used.
KEdit
- The signal gotUrlDrop was removed, nobody used it, and it's easy to do in the application
if needed (see the KURLDrag section)
KEditListBox
- void insertStrList(const QStrList* list, int index=-1) and void insertStrList(const QStrList& list, int index=-1) have been deprecated, use QStringList or const char** instead
KEditToolbar
- KEditToolbar is now KEditToolBar
- The static setDefaultToolBar was renamed to setGlobalDefaultToolBar
- The constructors have been simplified to take either a KActionCollection* or a KXMLGUIFactory*, depending on whether the app is using XMLGUI or not. To set a non-default resource file in the KActionCollection* case, call setResourceFile.
KEditToolbarWidget
- KEditToolbar is now KEditToolBarWidget
- The constructors have been simplified to take either a KActionCollection* and a parent widget or just a parent widget. The latter is for use with XMLGUI. Before being shown, the new load() methods should be called. These allow for populating the widget before being shown but after construction, which is useful when allowing the resource file to be changed as in KEditToolBar.
KFind
- The constructors have been simplified to take an optional parent. Other parameters must be set by using the API directly, e.g. setHasSelection and setSearch.
- The options argument in the constructor is now an enumerated flag of type KFind::Options.
- resetCounts() was renamed to resetMatchCount().
- The Options flags from KReplace were added to the Options enumeration of KFind.
KFontChooser
- Was in kfontdialog.h, but was moved to it's own header, so now either do #include <KFontChooser> or #include <kfontchooser.h>
- The KFontChooser constructors now take a set of flags to determine how it is displayed, which replaces the numerous bools used previously. The following mappings from the bools in KDE3 and the enum in KDE4 are as follows:
- 3rd parameter onlyFixed -> FixedFontsOnly
- 5th parameter makeFrame -> DisplayFrame
- 7th parameter diff -> ShowDifferences
KFontDialog
- The KFontDialog constructor now takes a set of flags to determine how it is displayed, which replaces the numerous bools used previously. The following mappings from the bools in KDE3 and the enum in KDE4 are as follows:
- 3rd parameter onlyFixed -> KFontChooser::FixedFontsOnly
- 5th parameter makeFrame -> KFontChooser::DisplayFrame
- 7th parameter diff -> KFontChooser::ShowDifferences
- The second argument for getFontDiff() is now a reference to a KFontChooser::FontDiffFlags instead of an int.
KGlobalAccel
- Moved from kdecore.
- bool useFourModifierKeys() has been removed (we always use four modifier keys now).
- Now a singleton
- You shouldn't need to access this class much... just use setGlobalShortcut() in KAction.
KGlobalSettings
- Moved from kdecore.
- KGlobalSettings is now a QObject so can emit signals like kdisplayPaletteChanged() instead of KApplication
- deprecated "static QString trashPath()" has been removed. use KIO::trash instead
- Accessing system colors via KGlobalSettings is deprecated; use an appropriately constructed KColorScheme instead.
See the KGlobalSettings documentation or kglobalsettings.h for specific replacement suggestions.
KGradientSelector
- Reversed the value range, if orientation is horizontal. Now minimum is on the left and maximum on the right side.
KGuiItem
- Don't use setIconSet anymore, use setIcon instead, there is no compatibility class or function
KHistoryCombo
Renamed to KHistoryComboBox.
- Was in kcombobox.h, but was moved to it's own header, so now do #include <khistorycombobox.h>
KHSSelector
- Renamed to KHueSaturationSelector, moved to kxyselector.h
KIcon
- New class (old one renamed to K3Icon)
- Thin wrapper around QIcon which creates a KIconEngine corresponding to the kde named icon
KIconLoader
- Moved from kdecore and is now a QObject.
- Deprecated loadIconSet(), DesktopIconSet(), BarIconSet(), SmallIconSet(), UserIconSet(): use KIcon(name) or KIcon(name,instance->iconLoader()) instead.
Note that this can change slightly the look of the icon in some cases: for instance if code was calling setIcon(BarIconSet())
on a pushbutton, it meant the icon was loaded at toolbar size and then resized down.
With KIcon(name), the small icon is picked up instead, which might look different, but this is the correct behavior.
These deprecated methods were also altered to not take a KComponentData (KInstance* in KDE3), which was an optional parameter in KDE3.
- the State parameter was used to be both define the state of the icon one of a limited number of overlays. Overlays are now a separate parameter, a QStringList, containing the names of icons to overlay. The new overlays parameter now follows the state parameter.
KInputDialog
- static QString KInputDialog::text( const QString &caption,...) was replaced by QString KInputDialog::getText( const QString &caption,...)
KIntNumInput, KDoubleNumInput, KDoubleSpinBox
- Qt::Alignment for label alignment instead of int
- setMinValue(min) -> setMinimum(min) / minValue() -> minimum()
- setMaxValue(min) -> setMaximum(min) / maxValue() -> maximum()
KJanusWidget
Deprecated. Use KPageWidget instead.
KKeyButton
Removed. Use either KKeySequenceWidget or KShortcutWidget. Use KShortcutWidget only if you really want two possible shortcuts. Both don't pop up a modal dialog.
KKeyChooser
Renamed to KShortcutsEditor.
KKeyDialog
Renamed to KShortcutsDialog.
KLed
- int ensureRoundLed() -> virtual int ledWidth() const
- virtual void paintRound() -> virtual void paintRaised()
KLineEdit
- void cursorAtEnd() removed, use QLineEdit::end(false) instead
- unused protected slots removed: void slotAboutToShow() and void slotCancelled()
- void setEnableSqueezedText( bool enable ) -> void setSqueezedTextEnabled( bool enable )
- void setURLDropsEnabled() -> void setUrlDropsEnabled()
- bool isURLDropsEnabled() -> bool urlDropsEnabled()
- void setURL() -> void setUrl()
KLineEditDlg
Was deprecated, has been removed. Use KInputDialog instead.
KListAction
Removed; as per comments, did not add anything to KSelectAction.
KListBox
Deprecated and renamed to K3ListBox. Use KListWidget (based on the QListWidget class).
KListView
Deprecated and renamed to K3ListView.
There is no direct KDE replacement for this class yet.
Either use KListWidget for list-based widgets or QTreeWidget for tree-based
widgets. Note that only QTreeWidget supports headers.
KListViewSearchLine
Deprecated and renamed to K3ListViewSearchLine.
You should port from K3ListView to QTreeWidget and then use
KTreeWidgetSearchLine instead.
KMacroCommand
Deprecated and renamed to to K3MacroCommand, header is k3command.h.
KMainWindow
- getMemberList() was replaced by memberList() and memberList was renamed to mMemberList and made it private
- sizeForCentralWidgetSize(QSize size) returned the size the main window should have so that the central widget will be of size. You normally don't need this, the recommended way to achieve a certain central widget size is as follows.
* Override sizeHint() in the central widget so that it returns the desired size.
* Call updateGeometry() in the central widget whenever the desired size changes. This ensures that the new sizeHint() is properly propagated to any parent layout.
* Now call adjustSize() in the main window to resize the main window such that the central widget will become the desired size.
- Ported to QMainWindow
- accel() removed - KAccel no longer needed
- If you need XmlGui functions from KMainWindow you may want to use KXmlGuiWindow instead of KMainWindow.
KMainWindowInterface
- functionsDynamic() now returns a DCOPCStringList
- function processDynamic arguments uses DCOPCString instead of QCString :
bool processDynamic(const DCOPCString &fun, const QByteArray &data, DCOPCString& replyType, QByteArray &replyData);
- actions() now returns a DCOPCString
KMenu (was KPopupMenu)
- indexes replaced by QAction*
- title, titlePixmap, and changeTitle removed - use QAction::text(), QAction::icon(), QAction::setText() and QAction::setIcon
- contextMenuFocusItem changed to contextMenuFocusAction in line with the change from indexes to actions
KMessageBox
- Where applicable, the static functions now take an additional argument to specify the cancel button. Since a default argument is provided, this will affect your code only, if you specified dontAskAgainName and/or options. In those cases, adding an additional parameter KStandardGuiItem::cancel() leads to the old behavior. The following functions are affected (omitting function arguments in the list): questionYesNoCancel(), questionYesNoCancelWId(), warningContinueCancel(), warningContinueCancelWId(),
warningContinueCancelList(), warningContinueCancelListWId(), warningYesNoCancel(), warningYesNoCancelWId(), warningYesNoCancelList(), warningYesNoCancelListWId(), messageBox(), messageBoxWId().
KNamedCommand
Deprecated and renamed to K3NamedCommand, header is k3command.h.
KPalette
KPaletteTable
KPassivePopup
- clicked single now emits a const QPoint reference
KPasswordEdit
Deprecated and renamed to K3PasswordEdit. Use KLineEdit, with KLineEdit::setPasswordMode(true).
KPasswordDialog
Deprecated and renamed to K3PasswordDialog.
- asking for a new password -> KNewPasswordDialog
- password() return QString
- getPassword() gone, use the following code instead
-
+
+
+
KPasswordDialog dlg(parent);
dlg.setPrompt( prompt );
dlg.setWindowTitle( caption );
if( dlg.exec() != QDialog::Accepted )
return;
use( dlg.password() );
-
KPixmapIO
Removed. Use QPixmap.toImage() and QPixmap::fromImage().
KPixmapRegionSelecorDialog
- getSelectedRegion was changed to selectedRegion
- getSelectedImage was changed to selectedImage
KPopupMenu
Renamed to KMenu.
KPopupTitle
Removed; QMenu doesn't accept widgets, and QAction allows specification of font, icon etc... and gradients / background pixmaps weren't even working in KDE3. You can use KMenu::addTitle() instead, which creates QAction.
KProgress
Removed. Use QProgressBar instead.
- advance(int offset) -> setValue(value()+offset)
- QProgressBar has changed a lot in Qt4 ( setTotalSteps(totalSteps) -> setRange(0, totalSteps), setProgress -> setValue, percentageChanged -> valueChanged ). For more details see QProgressBar class reference.
KProgressDialog
- #include <kprogressdialog.h> instead of #include <kprogress.h>
- progressBar() is a now QProgressBar instead of a KProgressBar -> See KProgress API changes
- setLabel(const QString &) renamed to setLabelText(const QString &)
KPushButton
- Don't use setIconSet anymore, use setIcon instead, there is no compatibility class or function
KRadioAction
Removed. Use KAction (or KToggleAction if you need different text/icons for the selected state) instead, in combination with an exclusive QActionGroup
KRecentFilesAction
- clearURLList() removed, use clear() instead
- *URL* -> *Url* as per KDE naming policy
- the maxItem property is now an int (was a uint) (affects all accessors methods)
KRootPixmap
Removed since it was not used.
KSelectAction
- now allows for combo box or button with popup menu when inserted to a toolbar
- popupMenu() removed, use menu() instead
- {set|}removeAmpersandsInCombo() removed - was deprecated
KSeparator
- KSeparator now uses Qt::Vertical and Qt::Horizontal rather then QFrame's HFrame and VFrame.
KSessionManager
Moved from kdecore, renamed from KSessionManaged, and moved to it's own header: ksessionmanager.h or KSessionManager
KSharedPixmap
Removed since is was not used.
KShortcut
- Moved from kdecore.
- Now reentrant
- Only uses QKeySequences now
- Removed list semantics; remove() still has somewhat list-like behavior.
- Introduced "primary" and "alternate" shortcuts to replace the arbitrary list of shortcuts
- Removed casting operators
- Removed operator< and operator>
- Added a qHash(const KShortcut &) function so you can use QHash with KShortcut instead of QMap
- remove() -> removeAll()
- toList() -> Not needed anymore since KShortcut inherits QList<QKeySequence>
- toStringInternal() -> You shouldn't be using this! But use toString() instead
- Added new constructor parameter: ActionTypes types. Allows you to filter the types of actions shown in the dialog.
- Removed all functions dealing with old classes KShortcutList, KGlobalAccel (kde3 version)
- Global shortcut conflict checking functions moved to KGlobalAccel.
- Standard shortcuts checking functions were removed.
See also KShortcutsDialog.
- Changed from edit/commit semantics to edit in-place/revert semantics. The old way didn't work in corner cases, the new way is quite a bit less complicated internally, and such cases only appear if a user opens multiple KKeyDialogs at the same time, which nobody does intentionally.
- Rewritten. It was hard to read, which stood in the way of future changes/improvements.
- Uses a new GUI layout.
- removed KDE2 deprecated functions
- Added new constructor parameter: KKeyChooser::ActionTypes types. Allows you to filter the types of actions shown in the dialog.
KStatusBar
- The unused BarStatus enum was removed.
- The 'permanent' bool has been removed in favor of more explicit naming.
insertItem(text,id,true) -> insertPermanentItem(text,id),
insertFixedItem(text,id,true) -> insertPermanentFixedItem(text,id)
KStdAction
Renamed to KStandardAction, header is kstandardaction.h.
- showToolbar() methods have been removed, see KMainWindow::setStandardToolBarMenuEnabled()
KStdGuiItem
Renamed to KStandardGuiItem, header is kstandardguiitem.h.
- The StdItem enum was renamed to StandardItem
KSyntaxHighlighter
- Use K3SyntaxHighlighter because it used Q3TextEdit or use KSyntaxHighlighter when your application will use QTextEdit
KSystemTray
Renamed to KSystemTrayIcon for consistency with its actual purpose and naming in Qt (QSystemTrayIcon).
- Is now a subclass of QSystemTrayIcon and not QLabel. Therefore it is not a widget anymore. Otherwise, it behaves the same as in KDE3 when it comes to managing a parent window's visibility and providing an action collection to display in the context menu.
KTabBar
- colors, close buttons on individual tabs not working at the moment
- The old insertTab and removeTab have been removed, use addTab / insertTab / removeTab from QTabBar instead (uses indices, not QTab*s)
KTabCtl
Removed. Use QTabWidget.
KTextBrowser
- Inherits from QTextBrowser instead of Q3TextBrowser
KTextEdit
- void highLightWord() -> void highlightWord()
KTimeWidget
Removed. Use QTimeEdit.
KTimezoneWidget
Renamed to KTimeZoneWidget.
KToggleAction
- setExclusiveGroup() / exclusiveGroup() removed, use setActionGroup() and QActionGroup::setExclusive() for exclusivity (imitates the deleted KRadioAction class)
- in comparison with KAction, adds setCheckedState() and sets this action to checkable
KToggleFullScreenAction
- Simplified constructor
Replace
KToggleFullScreenAction( const KShortcut &cut, const QObject* receiver, const char* slot,
KActionCollection* parent, QWidget* window, const QString& name )
with
KToggleFullScreenAction( QWidget* window, KActionCollection* parent, const QString& name )
See KAction how to port the other arguments.
KToolBar
- Ported to QToolBar
- IconText, iconText(), setIconText() replaced by QToolBar::toolButtonStyle() et. al.
- BarPosition, barPos(), setBarPos() replaced by Qt::ToolBarArea settings in QMainWindow; Unmanaged, Floating, and Flat are no longer supported (use QDockWidget if you need floating toolbars)
- fullSize(), setFullSize() removed as now handled in QMainWindow - add or insert a tool bar break before (not needed for the first toolbar) and after the toolbar using QMainWindow::{add|insert}ToolBarBreak() to have the toolbar take up all available horizontal space
- iconSize(), setIconSize() now a QToolBar property, and a QSize instead of an int - convenience function setIconDimensions() takes an int instead
- insert*() and all associated item-manipulation methods removed - all done through actions now. Compatibility layer possible however so far I haven't found the functions to be used much in KDE programs (mostly it's taken care of by xmlgui instead)
- flat(), setFlat() replaced by movable(), setMovable() (old "flat" concept equivalent to not movable)
- layout-related methods removed (done by QToolBar's layout)
- alignItemRight() removed (as above), replacement is to add a KToolBarSpacerAction before the action you want to be aligned right (or if you have a custom action already, just create a container widget and insert a QSpacerItem on the left of your custom widget (see KonqLogoAction in kdebase/konqueror/konq_actions.cc)
- enum BarStatus and bool enable(BarStatus stat) have been
removed
- void enableMoving(bool flag) and void enableFloating (bool
flag) have been removed in favor of setMovingEnabled(bool)
- int maxHeight()/int maxWidth() removed in favor of
maximumHeight()/maximumWidth()
- void setMaxHeight (int h) and void setMaxWidth (int dw)
removed in favor of setMaximumHeight()/setMaximumWidth()
- void setEnableContextMenu(bool enable = true) -> void setContextMenuEnabled(bool enable = true)
KToolBarButton
Removed. Done by QToolButton now.
KToolBarLabelAction
- Simplified constructors:
Replace
KToolBarLabelAction( const QString &text,
const KShortcut &cut,
const QObject *receiver, const char *slot,
KActionCollection *parent, const QString& name )
with
KToolBarLabelAction( const QString &text,
KActionCollection *parent, const QString& name )
and
KToolBarLabelAction( QAction *buddy, const QString &text,
const KShortcut &cut,
const QObject *receiver, const char *slot,
KActionCollection *parent, const QString& name )
with
KToolBarLabelAction( QAction *buddy, const QString &text,
KActionCollection *parent, const QString& name )
See KAction for how to port the other arguments.
KToolBarRadioGroup
Removed. Done by QToolButton now.
KToolBarSeparator
Removed. Use QAction::setSeparator().
KUndoRedoAction
Deprecated and renamed to K3UndoRedoAction, header is k3command.h.
KURLLabel
- renamed to KUrlLabel
- void setAltPixmap() -> void setAlternatePixmap()
- QPixmap* altPixmap() -> QPixmap* alternatePixmap()
- void setGlow() -> void setGlowEnabled()
- void setFloat() -> void setFloatEnabled()
- void setURL() -> void setUrl()
- signal: void enteredURL( ... ) -> void enteredUrl( ... )
- signal: void leftURL( ... ) -> void leftUrl( ... )
- signal: void leftClickedURL( ... ) -> void leftClickedUrl( ... )
- signal: void rightClickedURL( ... ) -> void rightClickedUrl( ... )
- signal: void middleClickedURL( ... ) -> void middleClickedUrl( ... )
KValueSelector
Renamed to KColorValueSelector, moved to kcolorvalueselector.h
KWidgetAction
Removed. Use KAction or QWidgetAction and utilise its widget-setting capabilities.
KWindowListMenu
Moved to libkworkspace in kdebase
KWizard
Deprecated and renamed to K3Wizard. Use KAssistantDialog.
KAbstractFileWidget
- void setPreviewWidget(const KPreviewWidgetBase *w) -> void setPreviewWidget(KPreviewWidgetBase *w)
KArchive/KTar/KZip/KAr
- All sizes and file offsets now use qint64 (similar to QIODevice)
- The API has changed for subclasses: there is a KArchive constructor that takes a filename, and which provides KSaveFile support automatically, writeDir is doWriteDir, prepareWriting is doPrepareWriting etc.
- API changes for users of the class: isOpened() was renamed to isOpen(),
doneWriting() to finishWriting(), and the order of the arguments for writeFile() is more usual:
data comes before size.
- KTarDirectory -> KArchiveDirectory
- KTarFile -> KArchiveFile
- KTarEntry -> KArchiveEntry
- KTarGz -> KTar
KBookmark classes
- KBookmarkDrag class has been moved to kde3support. Use KBookmark::populateMimeData() and
KBookmark::List::populateMimeData() in the drag/copy side,
and the static methods KBookmark::List::canDecode() and KBookmark::List::fromMimeData()
in the drop/paste side.
- KBookmarkMenu constructor is much simpler. It always creates a toplevel menu, which makes the parameter isRoot and parentAddress superfluous. KBookmarkOwner now governs wheter to show a "Add Bookmark" Menu Entry, thus the constructor parameter add is gone.
- KBookmarkMenu and KBookmarkBar no longer emits openBookmark(), override KBookmarkOwner::openBookmark() instead.
- KBookmarkOwner::openBookmarkURL() was replaced by KBookmarkOwner::openBookmark()
- KExtendBookmarkOwner functionality was integrated into KBookmarkOwner. (And the API is more regular now.)
- KBookmarkMenu::slotBookmarksChanged() and KBookmarkMenu::fillBookmarkMenu() are no longer public. Both had comments, that they shouldn't be used anyway.
- KBookmarkMannager::managerForFile() requires a DBus Name as the second parameter.
KDEDesktopMimeType class
- All the static methods have been moved to KDesktopFileActions, in kdesktopfileactions.h
KDirLister class
- The constructor argument is now a separate setter, so: KDirLister(false) -> KDirLister(); KDirLister(true) -> KDirLister() + setDelayedMimeTypes(true). On the other hand, KDirLister being a QObject, it takes a QObject* parent argument.
+- KDirLister uses KFileItem by value now:
+
+ - KFileItem* rootItem() const -> KFileItem rootItem() const
+ - KFileItem* findByUrl( const KUrl& url ) const -> KFileItem findByUrl( const KUrl& url ) const
+ - KFileItem* findByName( const QString& name ) const -> KFileItem* findByName( const QString& name ) const
+ - bool matchesFilter( const KFileItem* ) const -> bool matchesFilter( const KFileItem& ) const
+ - bool matchesMimeFilter( const KFileItem* ) const -> bool matchesMimeFilter( const KFileItem& ) const
+
+
+- The following signals have changed:
+
+ - void deleteItem( KFileItem *_fileItem ) -> void deleteItem( const KFileItem &fileItem )
+ - void refreshItems( const KFileItemList &items ) -> void refreshItems( const QList<QPair<KFileItem, KFileItem>> &entries)
+
+
KDiskFreeSp class
- Renamed to KDiskFreeSpace, moved to kdiskfreespace.h
KDESasl class
- This class is removed due to its inflexiblity, use cyrus-sasl or the upcoming QCA SASL implementation
KDirSelectDialog
- KDirSelectDialog moved to libkfile. If you were only using the static method selectDirectory, you can use KFileDialog::getExistingDirectory (for local files, i.e. if the second argument was true), or KFileDialog::getExistingDirectoryUrl
KFileDialog,KDirSelectDialog,KUrlRequesterDlg,KCustomMenuEditor,KUrlBarItemDialog
- are KDialogBases no more, now they are a KDialogs
- no more name and modal parameters in the constructors
KFileDialog, KFileView, KDirOperator
- instead of KConfig* + QString group everywhere KConfigGroup is used now
KFileDialog
KFileIconView, KFileDetailView, KFileTreeView, KFileTreeViewItem
- All renamed to K3File* since they are based upon K3IconView and K3ListView
- No replacement yet, apart from the more low-level KDirModel
- Those classes have all moved to a new library, libkfile. You need to link to ${KDE4_KFILE_LIBS} to keep using those classes.
KFileItemList
KFileMetaInfo
KFileMetaInfo has a new API and a new implementation. The change moves the emphasis away from mimetypes and groups of metadata to individual properties of files. These properties are still called KFileMetaInfoItem. The no longer belong to a group; they belong to the KFileMetaInfo object. The class KFileMetaInfoGroup is only there to group the items. Each KFileMetaInfoItem now has a member called PredicateProperties. This term comes from RDF. It determines the type of the item. This type encompasses the key (a URI), a name in the current locale, a description in the current locale, a type and a QValidator.
KFileOpenWithHandler
- This class has been removed, it was just a workaround for a dependency problem,
just remove any instance of it.
KFilePlugin
This class has been replaced by Strigi analyzers and KFileWritePlugin. The Strigi analyzer should be installed in the directory lib/strigi to be picked up. Introspection provided by the factories that are defined in the plugin helps in determining when a particular analyzer will be used.
Strigi analyzer have the advantage that they are faster then KFilePlugins. In addition, having one mechanism for extracting metadata from files saves code and more importantly ensures consistency between the display of metadata and the ablility to search in it. Another advantage is that the way the metadata are described matches well with the methods employed in the semantic desktop, in particular Nepomuk.
How to convert a KFilePlugin?
If your KFilePlugin only reads from files, it is easiest. Then you have to write only a Strigi analyzer. Depending on the way you read the data from the file it is best to write either a StreamThroughAnalyzer or a StreamEndAnalyzer. How to make the decision is explained in the link above. When your analyzer is ready you have to decide where to put it. You can put it in the same place as the KFilePlugin was or, if there are little or no dependencies in your analyzer, you can put it in kdesupport/strigi/src/streamindexer. The latter option has the advantage that you do not have to add the code for loading a plugin.
When you have write functionality in your plugin, you must implement KFileWritePlugin and place the code for writing the file in there. The details of how to do this are not entirely clear at the moment as is explained in the entry for KFileWritePlugin.
KFileWritePlugin
The write functionality of the class KFilePlugin is now handled by KFileWritePlugin. A global instance of this class that is attached to a KFileMetaInfoItem can be used to write back changes that were made to a files' metadata.
The mechanism by which these global instances are tied to KFileMetaDataItems is not yet finished. The implementation of will go into kio/kio/kfilemetainfo.cpp.
KIconButton
- signal void iconChanged(QString); replaced by void iconChanged(const QString &);
KIconDialog
- signal void newIconName(QString); replaced by void newIconName(const QString &);
KImageIO classes
- The KImageIO plugins are converted to Qt's imageformat plugins. The KImageIO class
now a lightweight version to query the installed plugins without actually loading them.
- .kimgio files are converted to .desktop files, and contains regular KDE services,
with ServiceType as QImageIOPlugins
- KImageIO::registerFormats() removed, simply remove this from your code
- Instead of mimeType(filename), you should use KMimeType
- Instead of canRead() and canWrite() you can use types(mode).contains(typename)
KIO:: global methods
- KIO::convertSizeFromKB is now KIO::convertSizeFromKiB since it takes a value in KiB (1 KiB = 1024 B)
- KIO::findDeviceMountPoint() has been replaced with KMountPoint::currentMountPoints() and findByDevice()
- KIO::findPathMountPoint() has been replaced with KMountPoint::currentMountPoints() and findByPath()
- KIO::probably_slow_mounted() has been replaced with KMountPoint::currentMountPoints(), findByPath(), and probablySlow()
- KIO::testFileSystemFlag() has been replaced with KMountPoint::testFileSystemFlag() (use KMountPoint::currentMountPoints().findByPath())
KIO::Job
- For Job subclasses: removeSubjob doesn't terminate the parent job anymore, add
if ( !hasSubjobs() ) emitResult();
to emulate the old behavior that.
- subjobs is now private. This means you should replace subjobs.remove(job) with removeSubjob(job),
and subjobs.isEmpty() with !hasSubjobs()
job->showErrorDialog(QWidget*)
becomes job->ui()->showErrorMessage()
. The parent QWidget should be set immediately after creating the job by job->ui()->setWindow(QWidget*)
job->setAutoErrorHandlingEnabled(bool,QWidget*)
becomes job->ui()->setAutoErrorHandlingEnabled(bool)
job->isAutoErrorHandlingEnabled()
becomes job->ui()->isAutoErrorHandlingEnabled()
job->setAutoWarningHandlingEnabled(bool)
becomes job->ui()->setAutoWarningHandlingEnabled(bool)
job->isAutoWarningHandlingEnabled()
becomes job->ui()->isAutoWarningHandlingEnabled()
job->setWindow(QWidget*)
becomes job->ui()->setWindow(QWidget*)
job->window()
becomes job->ui()->window()
job->setInteractive( false )
becomes job->setUiDelegate( 0 )
- Also note that you must now include <kio/copyjob.h> if you use KIO::copy, KIO::move or KIO::trash,
and you must include <kio/deletejob.h> if you use KIO::del.
- For Job subclasses, there's no showProgressInfo flag in the constructor anymore. You should use KIO::getJobTracker()->registerJob(job) instead.
KIO::UDSEntry
- UDSEntry is now a hash instead of a list. (NOT ANYMORE!!! NOT EVEN A HASH) Use the methods stringValue()
and numberValue() to retrieve fields directly, no loop is needed anymore.
See the UDSEntry documentation for code examples.
- Also note that UDSEntryListConstIterator is now UDSEntryList::ConstIterator;
see the UDSEntryList documentation for a full code example of iterating through
a listDir result.
- For kioslaves: replace every three lines like
atom.m_uds = KIO::UDS_SIZE;
atom.m_long = buff.st_size;
entry.append( atom );
with the line entry.insert( KIO::UDSEntry::UDS_SIZE, buff.st_size );
KIO::RenameDialog
- KIO::RenameDlg was renamed to KIO::RenameDialog and the header moved from renamedlg.h to renamedialog.h
- void b0Pressed() renamed to void cancelPressed()
- void b1Pressed() renamed to void renamePressed()
- void b2Pressed() renamed to void skipPressed()
- void b3Pressed() renamed to void autoSkipPressed()
- void b4Pressed() renamed to void overwritePressed()
- void b5Pressed() renamed to void overwriteAllPressed()
- void b6Pressed() renamed to void resumePressed()
- void b7Pressed() renamed to void resumeAllPressed()
- void b8Pressed() renamed to void suggestNewNamePressed()
KIO::RenameDialogPlugin
- RenameDlgPlugin was renamed to KIO::RenameDialogPlugin and the header moved from renamedlgplugin.h to renamedialogplugin.h
- The ServiceType was changed from RenameDlg/Plugin to RenameDialog/Plugin. Make sure to update your .desktop fiel
KIO::PasswordDialog
- KIO::PassDlg was renamed to KIO::PasswordDialog and the header moved from passdlg.h to passworddialog.h
KIO::PreviewJob
- KIO::PreviewJob works with KFileItems by value rather than by pointer, now that KFileItem is refcounted.
- The two signals changed accordingly:
- gotPreview(const KFileItem*, const QPixmap&) -> gotPreview(const KFileItem&, const QPixmap&)
- failed(const KFileItem*) -> failed(const KFileItem&
- In the slots connected to those signals, don't compare KFileItem pointers! If you need to find the KFileItem
in a list, compare the url() of the items in the list with the url() of the item passed to the slot.
KIO::SkipDialog
- KIO::SkipDlg was renamed to KIO::SkipDialog and the header moved from skipdlg.h to skipdialog.h
KIO::Observer
- openPassDlg was renamed to openPasswordDialog
- open_RenameDlg to open_RenameDialog
- open_SkipDlg to open_SkipDialog
KIO::SlaveBase
- openPassDlg was renamed to openPasswordDialog
KMimeMagic
- The KMimeMagic class is gone. Use the KMimeType API instead:
- KMimeMagic::self()->findFileType(path) -> KMimeType::findByPath(path) (preferred) or KMimeType::findByFileContent(path) (if only the content should be considered, but this isn't always reliable)
- KMimeMagic::self()->findBufferType(data) -> KMimeType::findByContent(data)
- KMimeMagic::self()->findBufferFileType(data,name) -> KMimeType::findByNameAndContent(name,data)
- .. and replace result->mimeType() with mime->name().
KMimeType
- KMimeType::pixmap() has been deprecated (for core/gui separation), use icon() or icon(url)
and KIconLoader::loadMimeTypeIcon with that icon name.
- KMimeType::pixmapForURL -> KIO::pixmapForURL
- KMimeType::comment(KUrl,bool) -> KIO::comment(KUrl)
- KMimeType::diagnoseFileName has been replaced with KMimeType::extractKnownExtension which returns the extension only, not the pattern
- KMimeType::mimeType(someName) now behaves like KServiceType::serviceType(someName), i.e. it returns 0 if that name doesn't exist,
instead of returning the application/octet-stream mimetype. Test for null!
- iconForURL has been deprecated, will possibly be removed for KDE 4.0 final, use iconNameForURL instead
- KMimeType::findFormatByFileContent has been removed. Use KMimeType::isBinaryData instead.
KMimeTypeResolver
- The previous KMimeTypeResolver has been renamed to K3MimeTypeResolver.
- A new KMimeTypeResolver must be used together with a KDirModel.
KOpenWithDlg
- Has been renamed to KOpenWithDialog. Use #include <kopenwithdialog.h>
KPropertiesDialog
- Doesn't have autoShow support in its constructors anymore, but still has autodelete behavior.
- Ensure any new is followed by show or exec. Or use KPropertiesDialog::showDialog where possible.
- The header file was renamed from kpropsdlg.h to kpropertiesdialog.h
- The ServiceType was renamed from KPropsDlg/Plugin to KPropertiesDialog/Plugin. Make sure to update your .desktop files
KPropertiesDialogPlugin
- KPropsPage or KPropsDlgPlugin was renamed to KPropertiesDialogPlugin
- The header file was renamed from kpropsdlg.h to kpropertiesdialog.h
KProtocolInfo
- Many static methods have been moved to KProtocolManager (which is in kio)
so that kprotocolinfo itself could be moved to kdecore:
- KProtocolInfo::supportsListing(url or protocol) -> KProtocolManager::supportsListing(url)
- KProtocolInfo::supportsReading(url or protocol) -> KProtocolManager::supportsReading(url)
- KProtocolInfo::supportsDeleting(url or protocol) -> KProtocolManager::supportsDeleting(url)
- etc.
- The deprecated methods taking a QString protocol as input have been removed, make sure
to pass a KUrl to most methods instead.
KRun
- the constructor needs a second parameter (a widget) now
KURLBar
KURLComboBox
- Renamed to KUrlComboBox
- All usage of QPixmap has been replaced by usage of QIcon
- getPixmap() --> getIcon()
KURLCompletion
- Renamed to KUrlCompletion
KURLPixmapProvider
- Renamed to KUrlPixmapProvider
KURLRequester
- renamed to KUrlRequester
- setCaption is gone, use setWindowTitle instead
- Renamed setURL() to setUrl(), per KDE naming policy
- Ported to use KUrl instead of QString. Thus, the constructors, setUrl(), url(), and urlChanged() all use KUrl.
- Removed showLocalProtocol() and setShowLocalProtocol(); this is now always false (the user never sees file:///)
KService
- KService was moved to libkdecore
- KService::rebuildKSycoca -> KBuildSycocaProgressDialog::rebuildKSycoca
- KService::pixmap was removed due to icon support being moved to libkdeui. Instead use KService::icon() and KIconLoader directly. Usually you can simply use the KIconLoader returned by KApplication::iconLoader() for this.
KServiceType
- KServiceType::offers() -> KServiceTypeTrader::self()->query()
- The behavior of KServiceType::serviceType() has changed: it now only returns real service types, and no more mimetypes. For mimetypes, use KMimeType::mimeType().
- Similarly, allServiceTypes() only returns real service types, no more mimetypes.
KServiceTypeProfile
- This class has been moved to kservicetypeprofile.h and is mostly internal now. Use KServiceTypeTrader or KMimeTypeTrader instead.
- KServiceTypeProfile::preferredService is now KMimeTypeTrader::self()->preferredService or KServiceTypeTrader::self()->preferredService
- KServiceTypeProfile::offers is now KMimeTypeTrader::self()->query or KServiceTypeTrader::self()->query
KTrader
- KTrader has been split up into two classes: KServiceTypeTrader and KMimeTypeTrader.
- So KTrader::query() should be ported to KMimeTypeTrader::query() when it's about mimetypes
(finding the application or part for a given mimetype), and to KServiceTypeTrader::query() when
it's about pure service types (plugins, kcmodules, etc.)
- In other terms, KTrader::query(1 or 2 args) -> KServiceTypeTrader::query and
KTrader::query(4 args but the last one was always QString::null) -> KMimeTypeTrader::query
- In both cases, query() now returns KService::List instead of an OfferList, adjust the type of the variable
- Constraints like "'RenameDlg/Plugin' in ServiceTypes" should be turned into
KMimeTypeTrader::self()->query(mimetype,"RenameDlg/Plugin")
PasswordDialog
- void setEnableUserField( bool enable, bool=false ) removed use setUsernameReadOnly( !enable )
UIServer
- QByteArray openPassDlg( const KIO::AuthInfo >info ); removed. Use KIO::PasswordDialog::getNameAndPassword
BrowserExtension
-- The following signals have changed:
+- The following signals have changed:
- openUrlRequest(const KUrl &, const KParts::URLArgs&) -> openUrlRequestDelayed(const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments&)
- openUrlRequestDelayed(const KUrl &, const KParts::URLArgs&) -> openUrlRequestDelayed(const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments&)
- The two createNewWindow signals have been merged into a single one: createNewWindow(url, args, browserArgs [, windowArgs, &part] )
- The two popupMenu signals which had URLArgs, now have OpenUrlArguments and BrowserArguments separated as well
+
- Because of the URLArgs split, make sure to replace BrowserExtension::setUrlArgs with BrowserExtension::setBrowserArguments + part->setArguments
BrowserHostExtension
-- The following virtal methods have changed:
+- The following virtal methods have changed:
- openURLInFrame(const KUrl &, const KParts::URLArgs&) -> openUrlInFrame(const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments&)
+
BrowserRun
- The constructor now takes args and browserArgs, see KParts::Part
- All the protected members have been turned into methods
- BrowserRun::isExecutable obsoleted by KRun::isExecutable
- suggestedFilename -> suggestedFileName
ComponentFactory
- createInstanceFromFactory is now KPluginFactory::create<T>
- createInstanceFromLibrary is now KLibLoader::createInstance<T>
- createInstanceFromService is now KService::createInstance<T>
- createInstanceFromQuery is now KServiceTypeTrader::createInstanceFromQuery<T>
- All the error codes like KParts::ComponentFactory::ErrNoServiceFound have moved to KLibLoader
KParts::URLArgs
-- URLArgs has been splitted into OpenUrlArguments and BrowserArguments.
+- URLArgs has been splitted into OpenUrlArguments and BrowserArguments.
- URLArgs.reload -> OpenUrlArguments.reload()/setReload()
- URLArgs.xOffset -> OpenUrlArguments.xOffset()/setXOffset()
- URLArgs.yOffset -> OpenUrlArguments.yOffset()/setYOffset()
- URLArgs.serviceType -> OpenUrlArguments.mimeType()/setMimeType()
- URLArgs.metaData() -> OpenUrlArguments.metaData()
- For anything else (docState, frameName, postData, setDoPost, setContentType etc.): URLArgs -> BrowserArguments
- - The BrowserArguments are still set and retrieved from the BrowserExtension, however the OpenUrlArguments are simply stored in KParts::ReadOnlyPart. So for instance:
+
+- The BrowserArguments are still set and retrieved from the BrowserExtension, however the OpenUrlArguments are simply stored in KParts::ReadOnlyPart. So for instance:
- m_extension-> urlArgs().xOffset -> arguments().xOffset()
+
- The class KDEDModule is now part of libkdecore so that kded modules can link without undefined symbols.
A number of apparently unused methods in KDEDModule have been commented out, contact
kde-core-devel if you need those after all.
- Note that the signature for the create_xyz() call has changed, simply remove all arguments from it,
and from your kded module's constructor
KSpell
- All of the features of KSpell and KSpell2 have been moved to Sonnet
- The KSpell2's initialization procedure of:
KSpell2::Loader::Ptr loader = KSpell2::Loader::openLoader();
KSpell2::Speller *speller = loader->createSpeller("en_US");
if (speller) {
if (speller->isMisspelled("word")) {
//do something
}
}
has been replaced with:
Sonnet:Speller speller("en_US");
if (speller.isMisspelled("word")) {
//do something
}
- The configuration class of KSpell2 (KSpell2::Settings) have been
folded back into Sonnet::Speller.
- Sonnet doesn't automatically overwrite configuration anymore. To
save and restore setting from a KConfig file one has to use
Sonnet::Speller::save(KConfig *config);
Sonnet::Speller::restore(KConfig *config);
methods.
- KSpell2::Filter has been temporarily removed from the public api.
Proper text segmentation api is planned for KDE 4.1
DomainBrowser
- Recursive browsing feature has been removed removed
- Constructor that takes list of domains and does not use configuration has been removed
- It is now possible to search for browsing or publishing domains
ServiceBase
- Service properties are stored in QMap<QString,QByteArray> instead of QMap<QString,QString>.
- This class is not used to pass domains or service types anymore
ServiceBrowser
- Browsing multiple types or multiple domains at once has been removed
- In KDE3 ServiceBrowser created with default constructor (for example ServiceBrowser("_http._tcp") ) browsed all configured domains. Now it only browses default one. To browse other domains create more ServiceBrowser objects
- It is now possible to specify subtype to narrow searching scope (for example "anon" for only anonymous FTP servers)
- Browsing for service types is now done using new class ServiceTypeBrowser
RemoteService
- Creating RemoteService from URL or DNS label is no longer supported
PublicService
- Optional list of subtypes can be passed to constructor.
- Encoding service into URL is no longer supported
Query
- This class has been merged into ServiceBrowser
KUrlRequesterDialog
- KUrlRequesterDlg was renamed to KUrlRequesterDialog
- The header was renamed from kurlrequesterdlg.h to kurlrequesterdialog.h
KDirOperator
- KFileView* view() const -> QAbstractItemView* view() const
- void setView(KFileView *view) -> void setView(QAbstractItemView *view)
- const KFileItemList* selectedItems() const -> QList<KFileItem> selectedItems() const
- KFileView* createView(QWidget *parent, KFile::FileView view) -> QAbstractItemView* createView(QWidget *parent, KFile::FileView view)
- QWidget* viewWidget() const; has been removed, use QAbstractItemView* view() instead.
- void setPreviewWidget(const QWidget *w) -> void setPreviewWidget(KPreviewWidgetBase *w)
- KIO::DeleteJob* del(const KFileItemList& items, QWidget *parent,
bool ask = true, bool showProgress = true) -> KIO::DeleteJob* del(const QList<KFileItem>& items, QWidget *parent = 0,
bool ask = true, bool showProgress = true)
- KIO::DeleteJob* del(const KFileItemList& items, bool ask = true, bool showProgress = true) has been removed. Use del(...)
with parent parameter instead.
- KIO::CopyJob* trash(const KFileItemList& items, QWidget *parent,
bool ask = true, bool showProgress = true) -> KIO::CopyJob* trash(const QList<KFileItem>& items, QWidget *parent,
bool ask = true, bool showProgress = true)
KFileWidget
- void setPreviewWidget(const KPreviewWidgetBase *w) -> void setPreviewWidget(KPreviewWidgetBase *w)
- The Button enum in KCModule only contains the Help, Default and Apply
values. The other buttons are not optional. If your KCM specified the button
flags just remove everything except those three.
- The functions setRootOnlyMsg, rootOnlyMsg, setUseRootOnlyMsg and
useRootOnlyMsg have been renamed to
setRootOnlyMessage, rootOnlyMessage, setUseRootOnlyMessage and
useRootOnlyMessage.
- KCModules need to have Type=Service and ServiceTypes=KCModule in the
.desktop file now - was Type=Application before
- KCModules that should show up in KControl or kcmshell --list need to have
X-KDE-ParentApp=kcontrol or kinfocenter
- If the KCModule should be used by kcminit you have to add KCModuleInit to
ServiceTypes (i.e. ServiceTypes=KCModule,KCModuleInit then)
- The kcm_ prefix in X-KDE-Library is now optional (in KDE3 the
X-KDE-Library value was automatically prefixed with kcm_)
- If the kcminit code is in a different lib than the other KCM code the
X-KDE-Init-Library was used. The library name has to be prefixed with kcminit_
now, but the prefix is optional in the .desktop file.
- The kcminit symbol now has to be prefixed with kcminit_ (in the code). The
rest of the symbol name is specified with X-KDE-Init-Symbol (was X-KDE-Init
before).
- It is now possible to use multiple K_EXPORT_GENERIC_FACTORY calls in one
library. The first parameter to the macro has to be the same as
X-KDE-FactoryName then.
- KCModule does no longer take a name argument, but directly a KInstance (having the correct
name for the translations to work.
- The X-KDE-RunAsRoot and X-KDE-IsHiddenByDefault keys are removed.
- KCModules will not be embedded running with root privileges anymore.
Instead the GUI code will run with user privileges as every other KCM. Only in
order to write or call programs should the KCM elevate its privileges.
- KDockWidgets -> kde3support K3DockWidget
- KParts::DockWindow -> kde3support KParts::DockWindow3
- KMDI* --> kdeSupport K3MDI*
libkmid
- Moved to kdemultimedia, where (at the moment) it is only used by kmid.
libkscreensaver
- Moved to kdebase/workspace/kscreensaver
Messages.sh files
Instead of the "messages" target of the Makefile.am files,
KDE4 uses now Bash scripts with Messages.sh file names.
The Perl script branches/work/l10n-kde4/scripts/conversion/Makefile2Messages.pl
can be used as an half-automatic conversion. (Please verify the result!)
rc.cpp file
The rc.cpp is now always generated. It is mandatory to have it as
parameter of the $XGETTEXT if you are using the class KAboutData and if
you are not explicitly setting KAboutData::setTranslator.
Gettext 0.16.1
Scripty uses
xgettext 0.16.1
for extracting
messages out of the source code. This is a huge step from the former xgettext 0.10.35-kde
used in KDE3.
Important changes:
- If you define your own keywords (-k parameter of xgettext), you probably
need to adapt them, as xgettext does not automatically know about the
1, 2 or 3 parameter versions.
- You cannot have two similar messages, one being a normal message and
the other being the singular form of a plural-form message. For Gettext, this is
the same message and therefore this creates problems. (Note: there is not
any similar problem with contexts.)
Translator Comments
Translator comments are a feature that already existed in KDE3, but which
was seldom used.
- Translator comment are code comments before a i18n call. To avoid
extracting comments that are of little interest for translators, translator
comemnts must start with // i18n: or /* i18n: to mark such comments.
(Note: translator comments starting with TRANSLATORS (all upper case), as it is Gettext's habit are not supported by KDE4.)
- As in Gettext 0.16.1, contexts are supposed to be short, please consider
using a translator comment instead of a context to give long hints to translators.
// i18n: this is a test sentence
i18n("The quick brown fox jumps over the lazy dog");
i18n calls
The basic call, a message without arguments, context or plural, remains as is:
i18n("Just plain info");
If there are arguments, arg
methods are no longer used to substitute the placeholders. Instead, arguments are added to the call:
i18n("%1 has scored %2", playerName, score);
Arguments can be of several integer types, double
, QString
, QChar
(and perhaps more in the future).
Context call now has a different name, i18nc
, and takes arguments in the same way:
i18nc("Player name - score", "%1 - %2", playerName, score);
Plural call is renamed to i18np
and does away with %n
placeholder, all being numbered instead:
i18np("One image in album %2", "%1 images in album %2", n, albumName);
The plural form is decided by first integer-valued argument.
There is one new call variant, the context-plural call:
i18ncp("Personal file", "One file", "%1 files", n);
i18n*
calls are realized as templates, and so will take at most some finite number of arguments.
Notes on placeholder substitution:
- Placeholders are substituted in one pass, so no need to worry about argument itself containing a placeholder.
- All same-numbered placeholders are substituted with same argument. This is in contrast to what single-argument
arg
methods of QString
do.
- Placeholders directly index arguments: they should be numbered from 1 upwards, without gaps in the sequence so that each argument is indexed. The exception is plural-deciding argument in plural call, where it is allowed to drop its placeholder in either singular or plural form.
Sometimes you might need old-style syntax for argument substitution. For example, when there are many arguments, or, more importantly, when it is convenient to defer substitution of arguments. This is possible using new ki18n
call, with subs
methods for argument substitution and toString
method for finalization:
KLocalizedString ks = ki18n("The Foo-machine reported: %1");
case (fooErrCode) {
ERR_OXI: ks.subs(i18n("Out of oxidizer")); break;
ERR_HYD: ks.subs(i18n("Out of hydrazine")); break;
ERR_PIL: ks.subs(i18n("Out of pilots")); break;
default: ks.subs(i18n("Unknown catastrophe"));
}
QString scream = ks.toString();
Note that ki18n
returns object of type KLocalizedString
, hence the toString
method for conversion to plain QString
. The ki18n
call should be used rarely; the previous example can as well be rewritten to:
QString problem;
case (fooErrCode) {
ERR_OXI: problem = i18n("Out of oxidizer"); break;
...
}
QString scream = i18n("The Foo-machine reported: %1", problem);
Another case when you might want to use ki18n
is if you want to format arguments. subs
methods can take formatting arguments, similar to those of arg
methods in QString
. You should never use methods other than subs
to format numbers in localized messages:
i18n("Rounds: %1", myNumberFormat(n, 8)); // bad, number not localized
ki18n("Rounds: %1").subs(n, 8).toString(); // good, number is localized
There is a context, plural and context-plural variant of ki18n
as well:
ki18nc("No function", "None").toString();
ki18np("One file found", "%1 files found").subs(n).toString();
ki18ncp("Personal file", "One file", "%1 files").subs(n).toString();
If you need translation using locale (KLocale object) other than the default, you can use overloaded toString
method which takes pointer to locale object (this replaces KLocale::translate(...)
from KDE3):
KLocale *myLocale;
...
ki18n("Welcome").toString(myLocale);
There is a script for semi-automatic conversion of KDE 3 code, i18nk34conv.pl
in branches/work/kde4-l10n/scripts/conversion/
. It will convert most of the calls automatically, and mark the places that need manual review. There is also the script i18ncheckarg.pl
in branches/work/kde4-l10n/scripts
, which will check whether placeholders and arguments match. Use it to catch and correct deferred substitutions (like in the examples above). Both these scripts you can just run without any arguments in top directory of your sources (but you can also specify paths or filenames as arguments). Do not run conversion script twice on same sources!
KSSLCertDialog
- KSSLCertDlg was renamed to KSSLCertDialog. The header was renamed to ksslcertdialog.h
KSSLInfoDialog
- KSSLInfoDlg was renamed to KSSLInfoDialog
- ksslinfodlg.h was moved to ksslinfodialog.h
KDE 4 switched to the XDG mime types, thus the names for some mime types have changed.
The following list contains the renamings from the KDE mime types to the XDG ones.
Notes:
- (alias) means that the old KDE mime type is an alias in the corresponding XDG mime type, so the conversion is not strictly needed (although suggested)
-
+
Old KDE mime type |
XDG mime type |
application/chm |
application/x-chm |
application/fits |
image/x-fits |
application/java |
application/x-java |
application/mathml+xml |
text/mathml |
application/msexcel |
application/vnd.ms-excel (alias) |
application/mspowerpoint |
application/vnd.ms-powerpoint (alias) |
application/ms-tnef |
application/vnd.ms-tnef |
application/pgp |
application/pgp-encrypted (alias) |
application/vnd.ms-asf |
video/x-ms-asf |
application/vnd.ms-word |
application/msword (alias) |
application/vnd.palm |
application/x-palm-database (alias) |
application/vnd.stardivision.writer-global |
application/vnd.stardivision.writer |
application/vnd.sun.xml.base |
application/vnd.oasis.opendocument.database |
application/vnd.sun.xml.writer.master |
application/vnd.sun.xml.writer.global |
application/wordperfect |
application/vnd.wordperfect (alias) |
application/x-7z |
application/x-7z-compressed |
application/x-afm |
application/x-font-afm |
application/x-applixgraphics |
image/x-applix-graphics |
application/x-applixspread |
application/x-applix-spreadsheet |
application/x-applixword |
application/x-applix-word |
application/x-bz2dvi |
application/x-bzdvi |
application/x-bzip2 |
application/x-bzip (alias) |
application/x-dbase |
application/x-dbf (alias) |
application/x-font-ghostscript |
application/x-font-type1 |
application/x-font-ttc |
application/x-font-ttf |
application/x-gettext |
text/x-gettext-translation (*.po)
text/x-gettext-translation-template (*.pot) |
application/x-hancomword |
application/x-hwp |
application/x-iso |
application/x-cd-image |
application/x-jar |
application/x-java-archive (alias) |
application/x-javascript |
application/javascript (alias) |
application/x-msaccess |
application/vnd.ms-access (alias) |
application/x-msdos-program |
application/x-ms-dos-executable |
application/x-msmetafile |
image/x-wmf |
application/x-ogg |
application/ogg |
application/x-perl-module |
application/x-perl |
application/x-python |
text/x-python |
application/x-rar-compressed |
application/x-rar |
application/x-tbz |
application/x-bzip-compressed-tar |
application/x-tgz |
application/x-compressed-tar |
application/x-troff |
text/troff (alias) |
application/x-zip |
application/zip |
application/x-zip-compressed |
application/zip (alias) |
application/xml-dtd |
text/x-dtd |
audio/mpegurl |
audio/x-mpegurl (alias) |
audio/x-midi |
audio/midi (alias) |
audio/x-mp3 |
audio/mpeg (alias) |
audio/x-oggflac |
audio/x-flac+ogg |
audio/x-pn-realaudio |
audio/vnd.rn-realaudio (alias) |
audio/x-speex |
audio/x-speex+ogg |
audio/x-vorbis |
audio/x-vorbis+ogg |
audio/vorbis |
audio/x-vorbis+ogg |
image/fits |
image/x-fits |
image/jp2 |
image/jpeg2000 |
image/jpg |
image/jpeg |
image/pjpeg |
image/jpeg (alias) |
image/svg-xml |
image/svg+xml |
image/svg+xml |
image/svg+xml (*.svg)
image/svg+xml-compressed (*.svgz) |
image/x-bmp |
image/bmp |
image/x-djvu |
image/vnd.djvu (alias) |
image/x-portable-greymap |
image/x-portable-graymap |
image/x-raw |
image/x-dcraw (general mime type)
Specific mime types (all subclasses of image/x-dcraw):
image/x-panasonic-raw (*.raw)
image/x-kodak-dcr (*.dcr)
image/x-adobe-dng (*.dng)
image/x-canon-crw (*.crw *.cr2)
image/x-nikon-nef (*.nef)
image/x-minolta-mrw (*.mrw)
image/x-kodak-k25 (*.k25)
image/x-kodak-kdc (*.kdc)
image/x-olympus-orf (*.orf)
image/x-pentax-pef (*.pef)
image/x-fuji-raf (*.raf)
image/x-sony-sr2 (*.sr2)
image/x-sony-srf (*.srf)
image/x-sigma-x3f (*.x3f)
other extensions that were part of image/x-raw: image/x-kde-raw
|
image/x-targa |
image/x-tga |
image/x-vnd.adobe.photoshop |
image/x-psd |
image/x-xbm |
image/x-xbitmap |
image/x-xcf-gimp |
image/x-xcf |
image/x-xpm |
image/x-xpixmap |
text/docbook |
application/docbook+xml |
text/javascript |
application/javascript (alias) |
text/rss |
application/rss+xml (alias) |
text/rtf |
application/rtf |
text/x-csv |
text/csv |
text/x-diff |
text/x-patch |
text/x-latex |
text/x-tex |
text/xml |
application/xml (alias) |
text/x-mswinurl |
application/x-mswinurl |
text/x-vcalendar |
text/calendar (alias) |
text/x-vcard |
text/directory (alias) |
text/x-xslt |
application/xslt+xml |
video/avi |
video/x-msvideo |
video/x-ogm |
video/x-ogm+ogg |
video/x-theora |
video/x-theora+ogg |
General
KNewStuff is replaced with KNewStuff2. The API for applications has changed
completely, as the library is a rewrite and not an update.
Do not inherit from any class, use only KNS::Engine.
All application-specific properties especially about what to do with
downloaded files are configured in *.knsrc files; have a look at
knewstuff/doc/porting.txt and knewstuff/doc/tutorial.txt.
Upload
Download
DCOP has been replaced with D-Bus.
Help with porting from DCOP to D-Bus can be found at
http://techbase.kde.org/Development/Tutorials/Porting_to_D-Bus
diff --git a/kfile/k3filetreeview.cpp b/kfile/k3filetreeview.cpp
index 632685690a..b20e1125ed 100644
--- a/kfile/k3filetreeview.cpp
+++ b/kfile/k3filetreeview.cpp
@@ -1,679 +1,679 @@
/* This file is part of the KDEproject
Copyright (C) 2000 David Faure
2000 Carsten Pfeiffer
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "k3filetreeview.h"
#include "kfiletreebranch.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
K3FileTreeView::K3FileTreeView( QWidget *parent )
: K3ListView( parent ),
m_wantOpenFolderPixmaps( true )
{
setDragEnabled(true);
setSelectionModeExt( K3ListView::Single );
m_animationTimer = new QTimer( this );
connect( m_animationTimer, SIGNAL( timeout() ),
this, SLOT( slotAnimation() ) );
m_currentBeforeDropItem = 0;
m_dropItem = 0;
m_autoOpenTimer = new QTimer( this );
connect( m_autoOpenTimer, SIGNAL( timeout() ),
this, SLOT( slotAutoOpenFolder() ) );
/* The executed-Slot only opens a path, while the expanded-Slot populates it */
connect( this, SIGNAL( executed( Q3ListViewItem * ) ),
this, SLOT( slotExecuted( Q3ListViewItem * ) ) );
connect( this, SIGNAL( expanded ( Q3ListViewItem *) ),
this, SLOT( slotExpanded( Q3ListViewItem *) ));
connect( this, SIGNAL( collapsed( Q3ListViewItem *) ),
this, SLOT( slotCollapsed( Q3ListViewItem* )));
/* connections from the konqtree widget */
connect( this, SIGNAL( selectionChanged() ),
this, SLOT( slotSelectionChanged() ) );
connect( this, SIGNAL( onItem( Q3ListViewItem * )),
this, SLOT( slotOnItem( Q3ListViewItem * ) ) );
connect( this, SIGNAL(itemRenamed(Q3ListViewItem*, const QString &, int)),
this, SLOT(slotItemRenamed(Q3ListViewItem*, const QString &, int)));
m_bDrag = false;
m_branches.setAutoDelete( true );
m_openFolderPixmap = DesktopIcon( "folder-open",K3Icon::SizeSmall,K3Icon::ActiveState );
}
K3FileTreeView::~K3FileTreeView()
{
// we must make sure that the KFileTreeViewItems are deleted _before_ the
// branches are deleted. Otherwise, the KFileItems would be destroyed
// and the KFileTreeViewItems had dangling pointers to them.
hide();
clear();
m_branches.clear(); // finally delete the branches and KFileItems
}
bool K3FileTreeView::isValidItem( Q3ListViewItem *item)
{
if (!item)
return false;
Q3PtrList lst;
Q3ListViewItemIterator it( this );
while ( it.current() )
{
if ( it.current() == item )
return true;
++it;
}
return false;
}
void K3FileTreeView::contentsDragEnterEvent( QDragEnterEvent *ev )
{
if ( ! acceptDrag( ev ) )
{
ev->ignore();
return;
}
ev->acceptProposedAction();
m_currentBeforeDropItem = selectedItem();
Q3ListViewItem *item = itemAt( contentsToViewport( ev->pos() ) );
if( item )
{
m_dropItem = item;
m_autoOpenTimer->start( KFileView::autoOpenDelay() );
}
else
{
m_dropItem = 0;
}
}
void K3FileTreeView::contentsDragMoveEvent( QDragMoveEvent *e )
{
if( ! acceptDrag( e ) )
{
e->ignore();
return;
}
e->acceptProposedAction();
Q3ListViewItem *afterme;
Q3ListViewItem *parent;
findDrop( e->pos(), parent, afterme );
// "afterme" is 0 when aiming at a directory itself
Q3ListViewItem *item = afterme ? afterme : parent;
if( item && item->isSelectable() )
{
setSelected( item, true );
if( item != m_dropItem ) {
m_autoOpenTimer->stop();
m_dropItem = item;
m_autoOpenTimer->start( KFileView::autoOpenDelay() );
}
}
else
{
m_autoOpenTimer->stop();
m_dropItem = 0;
}
}
void K3FileTreeView::contentsDragLeaveEvent( QDragLeaveEvent * )
{
// Restore the current item to what it was before the dragging (#17070)
if ( isValidItem(m_currentBeforeDropItem) )
{
setSelected( m_currentBeforeDropItem, true );
ensureItemVisible( m_currentBeforeDropItem );
}
else if ( isValidItem(m_dropItem) )
setSelected( m_dropItem, false ); // no item selected
m_currentBeforeDropItem = 0;
m_dropItem = 0;
}
void K3FileTreeView::contentsDropEvent( QDropEvent *e )
{
m_autoOpenTimer->stop();
m_dropItem = 0;
kDebug(250) << "contentsDropEvent !";
if( ! acceptDrag( e ) ) {
e->ignore();
return;
}
e->acceptProposedAction();
Q3ListViewItem *afterme;
Q3ListViewItem *parent;
findDrop(e->pos(), parent, afterme);
//kDebug(250) << " parent=" << (parent?parent->text(0):QString())
// << " afterme=" << (afterme?afterme->text(0):QString()) << endl;
if (e->source() == viewport() && itemsMovable())
movableDropEvent(parent, afterme);
else
{
emit dropped(e, afterme);
emit dropped(this, e, afterme);
emit dropped(e, parent, afterme);
emit dropped(this, e, parent, afterme);
KUrl::List urls = KUrl::List::fromMimeData( e->mimeData() );
if ( urls.isEmpty() )
return;
emit dropped( this, e, urls );
KUrl parentURL;
if( parent )
parentURL = static_cast(parent)->url();
else
// can happen when dropping above the root item
// Should we choose the first branch in such a case ??
return;
emit dropped( urls, parentURL );
emit dropped( this , e, urls, parentURL );
}
}
bool K3FileTreeView::acceptDrag(QDropEvent* e ) const
{
bool ancestOK= acceptDrops();
// kDebug(250) << "Do accept drops: " << ancestOK;
ancestOK = ancestOK && itemsMovable();
// kDebug(250) << "acceptDrag: " << ancestOK;
// kDebug(250) << "canDecode: " << KUrl::List::canDecode(e->mimeData());
// kDebug(250) << "action: " << e->action();
/* K3ListView::acceptDrag(e); */
/* this is what K3ListView does:
* acceptDrops() && itemsMovable() && (e->source()==viewport());
* ask acceptDrops and itemsMovable, but not the third
*/
return ancestOK && KUrl::List::canDecode( e->mimeData() ) &&
// Why this test? All DnDs are one of those AFAIK (DF)
( e->dropAction() == Qt::CopyAction
|| e->dropAction() == Qt::MoveAction
|| e->dropAction() == Qt::LinkAction );
}
Q3DragObject * K3FileTreeView::dragObject()
{
KUrl::List urls;
const QList fileList = selectedItems();
for (int i = 0; i < fileList.size(); ++i)
{
urls.append( static_cast(fileList.at(i))->url() );
}
QPoint hotspot;
QPixmap pixmap;
if( urls.count() > 1 ){
pixmap = DesktopIcon( "kmultiple", 16 );
}
if( pixmap.isNull() )
- pixmap = currentKFileTreeViewItem()->fileItem()->pixmap( 16 );
+ pixmap = currentKFileTreeViewItem()->fileItem().pixmap( 16 );
hotspot.setX( pixmap.width() / 2 );
hotspot.setY( pixmap.height() / 2 );
#if 0 // there is no more kurldrag, this should use urls.setInMimeData( mimeData ) instead
Q3DragObject* dragObject = new KUrlDrag( urls, this );
if( dragObject )
dragObject->setPixmap( pixmap, hotspot );
return dragObject;
#endif
return 0;
}
void K3FileTreeView::slotCollapsed( Q3ListViewItem *item )
{
K3FileTreeViewItem *kftvi = static_cast(item);
kDebug(250) << "hit slotCollapsed";
if( kftvi && kftvi->isDir())
{
item->setPixmap( 0, itemIcon(kftvi));
}
}
void K3FileTreeView::slotExpanded( Q3ListViewItem *item )
{
kDebug(250) << "slotExpanded here !";
if( ! item ) return;
K3FileTreeViewItem *it = static_cast(item);
KFileTreeBranch *branch = it->branch();
/* Start the animation for the branch object */
if( it->isDir() && branch && item->childCount() == 0 )
{
/* check here if the branch really needs to be populated again */
kDebug(250 ) << "starting to open " << it->url().prettyUrl();
startAnimation( it );
bool branchAnswer = branch->populate( it->url(), it );
kDebug(250) << "Branches answer: " << branchAnswer;
if( ! branchAnswer )
{
kDebug(250) << "ERR: Could not populate!";
stopAnimation( it );
}
}
/* set a pixmap 'open folder' */
if( it->isDir() && isOpen( item ) )
{
kDebug(250)<< "Setting open Pixmap";
item->setPixmap( 0, itemIcon( it )); // 0, m_openFolderPixmap );
}
}
void K3FileTreeView::slotExecuted( Q3ListViewItem *item )
{
if ( !item )
return;
/* This opens the dir and causes the Expanded-slot to be called,
* which strolls through the children.
*/
if( static_cast(item)->isDir())
{
item->setOpen( !item->isOpen() );
}
}
void K3FileTreeView::slotAutoOpenFolder()
{
m_autoOpenTimer->stop();
if ( !isValidItem(m_dropItem) || m_dropItem->isOpen() )
return;
m_dropItem->setOpen( true );
m_dropItem->repaint();
}
void K3FileTreeView::slotSelectionChanged()
{
if ( !m_dropItem ) // don't do this while the dragmove thing
{
}
}
KFileTreeBranch* K3FileTreeView::addBranch( const KUrl &path, const QString& name,
bool showHidden )
{
const QPixmap& folderPix = KIconLoader::global()->loadMimeTypeIcon( KMimeType::mimeType("inode/directory")->iconName(),
K3Icon::Desktop, K3Icon::SizeSmall );
return addBranch( path, name, folderPix, showHidden);
}
KFileTreeBranch* K3FileTreeView::addBranch( const KUrl &path, const QString& name,
const QPixmap& pix, bool showHidden )
{
kDebug(250) << "adding another root " << path.prettyUrl();
/* Open a new branch */
KFileTreeBranch *newBranch = new KFileTreeBranch( this, path, name, pix,
showHidden );
return addBranch(newBranch);
}
KFileTreeBranch *K3FileTreeView::addBranch(KFileTreeBranch *newBranch)
{
connect( newBranch, SIGNAL(populateFinished( K3FileTreeViewItem* )),
this, SLOT( slotPopulateFinished( K3FileTreeViewItem* )));
connect( newBranch, SIGNAL( newTreeViewItems( KFileTreeBranch*,
const K3FileTreeViewItemList& )),
this, SLOT( slotNewTreeViewItems( KFileTreeBranch*,
const K3FileTreeViewItemList& )));
m_branches.append( newBranch );
return( newBranch );
}
KFileTreeBranch *K3FileTreeView::branch( const QString& searchName )
{
KFileTreeBranch *branch = 0;
Q3PtrListIterator it( m_branches );
while ( (branch = it.current()) != 0 ) {
++it;
QString bname = branch->name();
kDebug(250) << "This is the branches name: " << bname;
if( bname == searchName )
{
kDebug(250) << "Found branch " << bname << " and return ptr";
return( branch );
}
}
return ( 0L );
}
KFileTreeBranchList& K3FileTreeView::branches()
{
return( m_branches );
}
bool K3FileTreeView::removeBranch( KFileTreeBranch *branch )
{
if(m_branches.contains(branch))
{
delete (branch->root());
m_branches.remove( branch );
return true;
}
else
{
return false;
}
}
void K3FileTreeView::setDirOnlyMode( KFileTreeBranch* branch, bool bom )
{
if( branch )
{
branch->setDirOnlyMode( bom );
}
}
void K3FileTreeView::slotPopulateFinished( K3FileTreeViewItem *it )
{
if( it && it->isDir())
stopAnimation( it );
}
void K3FileTreeView::slotNewTreeViewItems( KFileTreeBranch* branch, const K3FileTreeViewItemList& itemList )
{
if( ! branch ) return;
kDebug(250) << "hitting slotNewTreeViewItems";
/* Sometimes it happens that new items should become selected, i.e. if the user
* creates a new dir, he probably wants it to be selected. This can not be done
* right after creating the directory or file, because it takes some time until
* the item appears here in the treeview. Thus, the creation code sets the member
* m_neUrlToSelect to the required url. If this url appears here, the item becomes
* selected and the member nextUrlToSelect will be cleared.
*/
if( ! m_nextUrlToSelect.isEmpty() )
{
K3FileTreeViewItemListIterator it( itemList );
bool end = false;
for( ; !end && it.current(); ++it )
{
KUrl url = (*it)->url();
if( m_nextUrlToSelect.equals(url, KUrl::CompareWithoutTrailingSlash )) // ignore trailing / on dirs
{
setCurrentItem( static_cast(*it) );
m_nextUrlToSelect = KUrl();
end = true;
}
}
}
}
QPixmap K3FileTreeView::itemIcon( K3FileTreeViewItem *item, int gap ) const
{
QPixmap pix;
kDebug(250) << "Setting icon for column " << gap;
if( item )
{
/* Check if it is a branch root */
KFileTreeBranch *brnch = item->branch();
if( item == brnch->root() )
{
pix = brnch->pixmap();
if( m_wantOpenFolderPixmaps && brnch->root()->isOpen() )
{
pix = brnch->openPixmap();
}
}
else
{
// TODO: different modes, user Pixmaps ?
- pix = item->fileItem()->pixmap( K3Icon::SizeSmall ); // , K3Icon::DefaultState);
+ pix = item->fileItem().pixmap( K3Icon::SizeSmall ); // , K3Icon::DefaultState);
/* Only if it is a dir and the user wants open dir pixmap and it is open,
* change the fileitem's pixmap to the open folder pixmap. */
if( item->isDir() && m_wantOpenFolderPixmaps )
{
if( isOpen( static_cast(item)))
pix = m_openFolderPixmap;
}
}
}
return pix;
}
void K3FileTreeView::slotAnimation()
{
MapCurrentOpeningFolders::Iterator it = m_mapCurrentOpeningFolders.begin();
MapCurrentOpeningFolders::Iterator end = m_mapCurrentOpeningFolders.end();
for (; it != end;)
{
K3FileTreeViewItem *item = it.key();
if (!isValidItem(item))
{
++it;
m_mapCurrentOpeningFolders.remove(item);
continue;
}
uint & iconNumber = it.value().iconNumber;
QString icon = QString::fromLatin1( it.value().iconBaseName ).append( QString::number( iconNumber ) );
// kDebug(250) << "Loading icon " << icon;
item->setPixmap( 0, DesktopIcon( icon,K3Icon::SizeSmall,K3Icon::ActiveState )); // KFileTreeViewFactory::instance() ) );
iconNumber++;
if ( iconNumber > it.value().iconCount )
iconNumber = 1;
++it;
}
}
void K3FileTreeView::startAnimation( K3FileTreeViewItem * item, const char * iconBaseName, uint iconCount )
{
/* TODO: allow specific icons */
if( ! item )
{
kDebug(250) << " startAnimation Got called without valid item !";
return;
}
m_mapCurrentOpeningFolders.insert( item,
AnimationInfo( iconBaseName,
iconCount,
itemIcon(item, 0) ) );
if ( !m_animationTimer->isActive() )
m_animationTimer->start( 50 );
}
void K3FileTreeView::stopAnimation( K3FileTreeViewItem * item )
{
if( ! item ) return;
kDebug(250) << "Stoping Animation !";
MapCurrentOpeningFolders::Iterator it = m_mapCurrentOpeningFolders.find(item);
if ( it != m_mapCurrentOpeningFolders.end() )
{
if( item->isDir() && isOpen( item) )
{
kDebug(250) << "Setting folder open pixmap !";
item->setPixmap( 0, itemIcon( item ));
}
else
{
item->setPixmap( 0, it.value().originalPixmap );
}
m_mapCurrentOpeningFolders.remove( item );
}
else
{
if( item )
kDebug(250)<< "StopAnimation - could not find item " << item->url().prettyUrl();
else
kDebug(250)<< "StopAnimation - item is zero !";
}
if (m_mapCurrentOpeningFolders.isEmpty())
m_animationTimer->stop();
}
K3FileTreeViewItem * K3FileTreeView::currentKFileTreeViewItem() const
{
return static_cast( selectedItem() );
}
KUrl K3FileTreeView::currentUrl() const
{
K3FileTreeViewItem *item = currentKFileTreeViewItem();
if ( item )
return currentKFileTreeViewItem()->url();
else
return KUrl();
}
void K3FileTreeView::slotOnItem( Q3ListViewItem *item )
{
K3FileTreeViewItem *i = static_cast( item );
if( i )
{
const KUrl url = i->url();
if ( url.isLocalFile() )
emit onItem( url.path() );
else
emit onItem( url.prettyUrl() );
}
}
void K3FileTreeView::slotItemRenamed(Q3ListViewItem* item, const QString &name, int col)
{
(void) item;
kDebug(250) << "Do not bother: " << name << col;
}
K3FileTreeViewItem *K3FileTreeView::findItem( const QString& branchName, const QString& relUrl )
{
KFileTreeBranch *br = branch( branchName );
return( findItem( br, relUrl ));
}
K3FileTreeViewItem *K3FileTreeView::findItem( KFileTreeBranch* brnch, const QString& relUrl )
{
K3FileTreeViewItem *ret = 0;
if( brnch )
{
KUrl url = brnch->rootUrl();
if( ! relUrl.isEmpty() && QDir::isRelativePath(relUrl) )
{
QString partUrl( relUrl );
if( partUrl.endsWith('/'))
partUrl.truncate( relUrl.length()-1 );
url.addPath( partUrl );
kDebug(250) << "assembled complete dir string " << url.prettyUrl();
- KFileItem *fi = brnch->findByUrl( url );
- if( fi )
+ KFileItem fi = brnch->findByUrl( url );
+ if( !fi.isNull() )
{
ret =
const_cast(
- static_cast(fi->extraData(brnch)));
+ static_cast(fi.extraData(brnch)));
kDebug(250) << "Found item !" <root();
}
}
return( ret );
}
bool K3FileTreeView::showFolderOpenPixmap() const
{
return m_wantOpenFolderPixmaps;
}
void K3FileTreeView::setShowFolderOpenPixmap( bool showIt )
{
m_wantOpenFolderPixmaps = showIt;
}
void K3FileTreeView::slotSetNextUrlToSelect( const KUrl &url )
{
m_nextUrlToSelect = url;
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
#include "k3filetreeview.moc"
diff --git a/kfile/k3filetreeviewitem.cpp b/kfile/k3filetreeviewitem.cpp
index 310714707b..c5c4bc912b 100644
--- a/kfile/k3filetreeviewitem.cpp
+++ b/kfile/k3filetreeviewitem.cpp
@@ -1,83 +1,86 @@
/* This file is part of the KDEproject
Copyright (C) 2000 David Faure
2000 Carsten Pfeiffer
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "k3filetreeviewitem.h"
#include
#include
#include
/* --- K3FileTreeViewItem --- */
/*
*/
K3FileTreeViewItem::K3FileTreeViewItem( K3FileTreeViewItem *parent,
- KFileItem* item,
+ const KFileItem &item,
KFileTreeBranch *brnch )
: K3ListViewItem( parent ),
m_kfileitem( item ),
m_branch( brnch ),
m_wasListed(false)
{
- setPixmap(0, item->pixmap( K3Icon::SizeSmall ));
- setText( 0, item->text());
+ setPixmap(0, item.pixmap( K3Icon::SizeSmall ));
+ setText( 0, item.text());
+ m_kfileitem.setExtraData( m_branch, this );
}
K3FileTreeViewItem::K3FileTreeViewItem( K3FileTreeView* parent,
- KFileItem* item,
+ const KFileItem &item,
KFileTreeBranch *brnch )
:K3ListViewItem( (Q3ListView*)parent ),
m_kfileitem(item ),
m_branch( brnch ),
m_wasListed(false)
{
- setPixmap(0, item->pixmap( K3Icon::SizeSmall ));
- setText( 0, item->text());
+ setPixmap(0, item.pixmap( K3Icon::SizeSmall ));
+ setText( 0, item.text());
+
+ m_kfileitem.setExtraData( m_branch, this );
}
K3FileTreeViewItem::~K3FileTreeViewItem()
{
- if ( m_kfileitem )
- m_kfileitem->removeExtraData( m_branch );
+ if ( !m_kfileitem.isNull() )
+ m_kfileitem.removeExtraData( m_branch );
}
bool K3FileTreeViewItem::alreadyListed() const
{
return m_wasListed;
}
void K3FileTreeViewItem::setListed( bool wasListed )
{
m_wasListed = wasListed;
}
KUrl K3FileTreeViewItem::url() const
{
- return m_kfileitem ? m_kfileitem->url() : KUrl();
+ return !m_kfileitem.isNull() ? m_kfileitem.url() : KUrl();
}
QString K3FileTreeViewItem::path() const
{
- return m_kfileitem ? m_kfileitem->url().path() : QString();
+ return !m_kfileitem.isNull() ? m_kfileitem.url().path() : QString();
}
bool K3FileTreeViewItem::isDir() const
{
- return m_kfileitem ? m_kfileitem->isDir() : false;
+ return !m_kfileitem.isNull() ? m_kfileitem.isDir() : false;
}
diff --git a/kfile/k3filetreeviewitem.h b/kfile/k3filetreeviewitem.h
index 4fc930d555..9ec8f0e383 100644
--- a/kfile/k3filetreeviewitem.h
+++ b/kfile/k3filetreeviewitem.h
@@ -1,107 +1,107 @@
/* This file is part of the KDE project
Copyright (C) 2000 David Faure
2000 Carsten Pfeiffer
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef kfile_tree_view_item_h
#define kfile_tree_view_item_h
#include "kfile_export.h"
#include
#include
#include
#include
#include
#include
class KUrl;
class K3FileTreeView;
class KFileTreeBranch;
/**
* An item for a K3FileTreeView that knows about its own KFileItem.
*/
class KFILE_EXPORT K3FileTreeViewItem : public K3ListViewItem
{
public:
- K3FileTreeViewItem( K3FileTreeViewItem*, KFileItem*, KFileTreeBranch * );
- K3FileTreeViewItem( K3FileTreeView*, KFileItem*, KFileTreeBranch * );
+ K3FileTreeViewItem( K3FileTreeViewItem*, const KFileItem&, KFileTreeBranch * );
+ K3FileTreeViewItem( K3FileTreeView*, const KFileItem&, KFileTreeBranch * );
~K3FileTreeViewItem();
/**
* @return the KFileTreeBranch the item is sorted in.
*/
KFileTreeBranch* branch() const { return m_branch; }
/**
* @return the KFileItem the viewitem is representing.
*/
- KFileItem *fileItem() const { return m_kfileitem; }
+ KFileItem fileItem() const { return m_kfileitem; }
/**
* @return the path of the item.
*/
QString path() const;
/**
* @return the items KUrl
*/
KUrl url() const;
/**
* @return if the item represents a directory
*/
bool isDir() const;
/**
* @return if this directory was already seen by a KDirLister.
*/
bool alreadyListed() const;
/**
* set the flag if the directory was already listed.
*/
void setListed( bool wasListed );
protected:
private:
- KFileItem *m_kfileitem;
+ KFileItem m_kfileitem;
KFileTreeBranch *m_branch;
bool m_wasListed;
class K3FileTreeViewItemPrivate;
K3FileTreeViewItemPrivate *d;
};
/**
* List of KFileTreeViewItems
*/
typedef Q3PtrList K3FileTreeViewItemList;
/**
* Iterator for KFileTreeViewItemList
*/
typedef Q3PtrListIterator K3FileTreeViewItemListIterator;
#endif
diff --git a/kfile/kdiroperator.cpp b/kfile/kdiroperator.cpp
index 9c5ecf7eff..43778dd9a7 100644
--- a/kfile/kdiroperator.cpp
+++ b/kfile/kdiroperator.cpp
@@ -1,2092 +1,2086 @@
/* This file is part of the KDE libraries
Copyright (C) 1999,2000 Stephan Kulow
1999,2000,2001,2002,2003 Carsten Pfeiffer
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kdiroperator.h"
#include "kdirmodel.h"
#include "kdirsortfilterproxymodel.h"
#include "kfileview.h"
#include "kfileitem.h"
#include "kfilemetapreview.h"
#include "kpreviewwidgetbase.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
-template class QHash;
+template class QHash;
/**
* Default icon view for KDirOperator using
* custom view options.
*/
class DirOperatorIconView : public QListView
{
public:
DirOperatorIconView(QWidget *parent = 0);
virtual ~DirOperatorIconView();
protected:
virtual QStyleOptionViewItem viewOptions() const;
virtual void mousePressEvent(QMouseEvent *event);
private:
QStyleOptionViewItem m_viewOptions;
};
DirOperatorIconView::DirOperatorIconView(QWidget *parent) :
QListView(parent)
{
setViewMode(QListView::IconMode);
setFlow(QListView::TopToBottom);
setResizeMode(QListView::Adjust);
setSpacing(KDialog::spacingHint());
setMovement(QListView::Static);
m_viewOptions = QListView::viewOptions();
m_viewOptions.showDecorationSelected = true;
m_viewOptions.decorationPosition = QStyleOptionViewItem::Left;
m_viewOptions.displayAlignment = Qt::AlignLeft | Qt::AlignVCenter;
m_viewOptions.decorationSize = QSize(K3Icon::SizeSmall, K3Icon::SizeSmall);
QFontMetrics metrics(m_viewOptions.font);
const int fontHeight = metrics.height();
setGridSize(QSize(fontHeight * 10, fontHeight + 4));
}
DirOperatorIconView::~DirOperatorIconView()
{
}
QStyleOptionViewItem DirOperatorIconView::viewOptions() const
{
return m_viewOptions;
}
void DirOperatorIconView::mousePressEvent(QMouseEvent *event)
{
if (!indexAt(event->pos()).isValid()) {
const Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
if (!(modifier & Qt::ShiftModifier) && !(modifier & Qt::ControlModifier)) {
clearSelection();
}
}
QListView::mousePressEvent(event);
}
/**
* Default detail view for KDirOperator using
* custom resizing options and columns.
*/
class DirOperatorDetailView : public QTreeView
{
public:
DirOperatorDetailView(QWidget *parent = 0);
virtual ~DirOperatorDetailView();
protected:
virtual bool event(QEvent *event);
virtual void resizeEvent(QResizeEvent* event);
};
DirOperatorDetailView::DirOperatorDetailView(QWidget *parent) :
QTreeView(parent)
{
setRootIsDecorated(false);
setSortingEnabled(true);
setUniformRowHeights(true);
setSelectionBehavior(QAbstractItemView::SelectRows);
}
DirOperatorDetailView::~DirOperatorDetailView()
{
}
bool DirOperatorDetailView::event(QEvent *event)
{
if (event->type() == QEvent::Polish) {
// Assure that by respecting the available width that:
// - the 'Name' column is stretched as large as possible
// - the remaining columns are as small as possible
QHeaderView *headerView = header();
headerView->setStretchLastSection(false);
headerView->setResizeMode(QHeaderView::ResizeToContents);
headerView->setResizeMode(0, QHeaderView::Stretch);
// hide columns
hideColumn(KDirModel::Permissions);
hideColumn(KDirModel::Owner);
hideColumn(KDirModel::Group);
}
return QTreeView::event(event);
}
void DirOperatorDetailView::resizeEvent(QResizeEvent* event)
{
QTreeView::resizeEvent(event);
// assure that the width of the name-column does not get too small
const int minWidth = 120;
QHeaderView* headerView = header();
bool useFixedWidth = (headerView->sectionSize(KDirModel::Name) <= minWidth)
&& (headerView->resizeMode(0) != QHeaderView::Fixed);
if (useFixedWidth) {
// the current width of the name-column is too small, hence
// use a fixed size
headerView->setResizeMode(QHeaderView::Fixed);
headerView->setResizeMode(0, QHeaderView::Fixed);
headerView->resizeSection(KDirModel::Name, minWidth);
} else if (headerView->resizeMode(0) != QHeaderView::Stretch) {
// check whether there is enough available viewport width
// to automatically resize the columns
const int availableWidth = viewport()->width();
int headerWidth = 0;
const int count = headerView->count();
for (int i = 0; i < count; ++i) {
headerWidth += headerView->sectionSize(i);
}
if (headerWidth < availableWidth) {
headerView->setResizeMode(QHeaderView::ResizeToContents);
headerView->setResizeMode(0, QHeaderView::Stretch);
}
}
}
class KDirOperator::KDirOperatorPrivate
{
public:
KDirOperatorPrivate();
~KDirOperatorPrivate();
QStack backStack; ///< Contains all URLs you can reach with the back button.
QStack forwardStack; ///< Contains all URLs you can reach with the forward button.
KDirLister *dirLister;
KUrl currUrl;
KCompletion completion;
KCompletion dirCompletion;
bool completeListDirty;
QDir::SortFlags sorting;
QSplitter *splitter;
QAbstractItemView *itemView;
KDirModel *dirModel;
KDirSortFilterProxyModel *proxyModel;
KFileItemList pendingMimeTypes;
// the enum KFile::FileView as an int
int viewKind;
int defaultView;
KFile::Modes mode;
QProgressBar *progressBar;
KPreviewWidgetBase *preview;
QTimer *previewTimer;
KUrl previewUrl;
int previewWidth;
bool leftButtonPressed;
bool dirHighlighting;
bool onlyDoubleClickSelectsFiles;
QString lastURL; // used for highlighting a directory on cdUp
QTimer *progressDelayTimer;
int dropOptions;
KActionMenu *actionMenu;
KActionCollection *actionCollection;
KConfigGroup *configGroup;
};
KDirOperator::KDirOperatorPrivate::KDirOperatorPrivate() :
dirLister(0),
splitter(0),
itemView(0),
dirModel(0),
proxyModel(0),
progressBar(0),
preview(0),
previewTimer(0),
previewUrl(),
previewWidth(0),
leftButtonPressed(false),
dirHighlighting(false),
onlyDoubleClickSelectsFiles(false),
progressDelayTimer(0),
dropOptions(0),
actionMenu(0),
actionCollection(0),
configGroup(0)
{
}
KDirOperator::KDirOperatorPrivate::~KDirOperatorPrivate()
{
delete itemView;
// TODO:
// if (configGroup) {
// itemView->writeConfig(configGroup);
// }
qDeleteAll(backStack);
qDeleteAll(forwardStack);
delete preview;
delete dirLister;
delete configGroup;
delete progressDelayTimer;
}
KDirOperator::KDirOperator(const KUrl& _url, QWidget *parent) :
QWidget(parent),
d(new KDirOperatorPrivate)
{
d->splitter = new QSplitter(this);
d->splitter->setChildrenCollapsible(false);
connect(d->splitter, SIGNAL(splitterMoved(int, int)),
this, SLOT(slotSplitterMoved(int, int)));
d->preview = 0;
d->previewTimer = new QTimer(this);
d->previewTimer->setSingleShot(true);
connect(d->previewTimer, SIGNAL(timeout()),
this, SLOT(showPreview()));
d->mode = KFile::File;
d->viewKind = KFile::Simple;
d->sorting = QDir::Name | QDir::DirsFirst;
if (_url.isEmpty()) { // no dir specified -> current dir
QString strPath = QDir::currentPath();
strPath.append(QChar('/'));
d->currUrl = KUrl();
d->currUrl.setProtocol(QLatin1String("file"));
d->currUrl.setPath(strPath);
} else {
d->currUrl = _url;
if (d->currUrl.protocol().isEmpty())
d->currUrl.setProtocol(QLatin1String("file"));
d->currUrl.addPath("/"); // make sure we have a trailing slash!
}
setDirLister(new KDirLister());
connect(&d->completion, SIGNAL(match(const QString&)),
SLOT(slotCompletionMatch(const QString&)));
d->progressBar = new QProgressBar(this);
d->progressBar->setObjectName("d->progressBar");
d->progressBar->adjustSize();
d->progressBar->move(2, height() - d->progressBar->height() - 2);
d->progressDelayTimer = new QTimer(this);
d->progressDelayTimer->setObjectName(QLatin1String("d->progressBar delay timer"));
connect(d->progressDelayTimer, SIGNAL(timeout()),
SLOT(slotShowProgress()));
d->completeListDirty = false;
// action stuff
setupActions();
setupMenu();
setFocusPolicy(Qt::WheelFocus);
}
KDirOperator::~KDirOperator()
{
resetCursor();
delete d;
}
void KDirOperator::setSorting(QDir::SortFlags spec)
{
d->sorting = spec;
triggerSorting();
updateSortActions();
}
QDir::SortFlags KDirOperator::sorting() const
{
return d->sorting;
}
bool KDirOperator::isRoot() const
{
return url().path() == QString(QLatin1Char('/'));
}
KDirLister *KDirOperator::dirLister() const
{
return d->dirLister;
}
void KDirOperator::resetCursor()
{
QApplication::restoreOverrideCursor();
d->progressBar->hide();
}
void KDirOperator::sortByName()
{
d->actionCollection->action("by name")->setChecked(true);
}
void KDirOperator::sortBySize()
{
d->actionCollection->action("by size")->setChecked(true);
}
void KDirOperator::sortByDate()
{
d->actionCollection->action("by date")->setChecked(true);
}
void KDirOperator::sortByType()
{
d->actionCollection->action("by type")->setChecked(true);
}
void KDirOperator::sortReversed()
{
QAction* action = d->actionCollection->action("descending");
action->setChecked(!action->isChecked());
}
void KDirOperator::toggleDirsFirst()
{
// TODO: not offered yet
}
void KDirOperator::toggleIgnoreCase()
{
if (d->proxyModel != 0) {
Qt::CaseSensitivity cs = d->proxyModel->sortCaseSensitivity();
cs = (cs == Qt::CaseSensitive) ? Qt::CaseInsensitive : Qt::CaseSensitive;
d->proxyModel->setSortCaseSensitivity(cs);
}
}
void KDirOperator::updateSelectionDependentActions()
{
const bool hasSelection = (d->itemView != 0) &&
d->itemView->selectionModel()->hasSelection();
d->actionCollection->action("trash")->setEnabled(hasSelection);
d->actionCollection->action("delete")->setEnabled(hasSelection);
d->actionCollection->action("properties")->setEnabled(hasSelection);
}
void KDirOperator::setPreviewWidget(KPreviewWidgetBase *w)
{
const bool showPreview = (w != 0);
if (showPreview) {
d->viewKind = (d->viewKind | KFile::PreviewContents);
} else {
d->viewKind = (d->viewKind & ~KFile::PreviewContents);
}
delete d->preview;
d->preview = w;
KToggleAction *previewAction = static_cast(d->actionCollection->action("preview"));
previewAction->setEnabled(showPreview);
previewAction->setChecked(showPreview);
setView(static_cast(d->viewKind));
}
QList KDirOperator::selectedItems() const
{
QList itemList;
if (d->itemView == 0) {
return itemList;
}
const QItemSelection selection = d->proxyModel->mapSelectionToSource(d->itemView->selectionModel()->selection());
const QModelIndexList indexList = selection.indexes();
foreach(QModelIndex index, indexList) {
KFileItem item = d->dirModel->itemForIndex(index);
if (!item.isNull()) {
itemList.append(item);
}
}
return itemList;
}
-bool KDirOperator::isSelected(const KFileItem *item) const
+bool KDirOperator::isSelected(const KFileItem &item) const
{
- if ((item == 0) || (d->itemView == 0)) {
+ if ((item.isNull()) || (d->itemView == 0)) {
return false;
}
- const QModelIndex dirIndex = d->dirModel->indexForItem(*item);
+ const QModelIndex dirIndex = d->dirModel->indexForItem(item);
const QModelIndex proxyIndex = d->proxyModel->mapFromSource(dirIndex);
return d->itemView->selectionModel()->isSelected(proxyIndex);
}
int KDirOperator::numDirs() const
{
return (d->dirLister == 0) ? 0 : d->dirLister->directories().count();
}
int KDirOperator::numFiles() const
{
return (d->dirLister == 0) ? 0 : d->dirLister->items().count() - numDirs();
}
KCompletion * KDirOperator::completionObject() const
{
return const_cast(&d->completion);
}
KCompletion *KDirOperator::dirCompletionObject() const
{
return const_cast(&d->dirCompletion);
}
KActionCollection * KDirOperator::actionCollection() const
{
return d->actionCollection;
}
void KDirOperator::slotDetailedView()
{
KFile::FileView view = static_cast((d->viewKind & ~KFile::Simple) | KFile::Detail);
setView(view);
}
void KDirOperator::slotSimpleView()
{
KFile::FileView view = static_cast((d->viewKind & ~KFile::Detail) | KFile::Simple);
setView(view);
}
void KDirOperator::slotToggleHidden(bool show)
{
d->dirLister->setShowingDotFiles(show);
updateDir();
assureVisibleSelection();
}
void KDirOperator::togglePreview(bool on)
{
if (on) {
d->viewKind = d->viewKind | KFile::PreviewContents;
if (d->preview == 0) {
d->preview = new KFileMetaPreview(this);
d->actionCollection->action("preview")->setChecked(true);
d->splitter->addWidget(d->preview);
}
d->preview->show();
QMetaObject::invokeMethod(this, "assureVisibleSelection", Qt::QueuedConnection);
if (d->itemView != 0) {
const QModelIndex index = d->itemView->selectionModel()->currentIndex();
if (index.isValid()) {
triggerPreview(index);
}
}
} else if (d->preview != 0) {
d->viewKind = d->viewKind & ~KFile::PreviewContents;
d->preview->hide();
d->previewTimer->stop();
}
}
void KDirOperator::slotSortByName()
{
d->sorting = QDir::Name;
d->actionCollection->action("by name")->setChecked(true);
triggerSorting();
}
void KDirOperator::slotSortBySize()
{
d->sorting = (d->sorting & ~QDir::SortByMask) | QDir::Size;
d->actionCollection->action("by size")->setChecked(true);
triggerSorting();
}
void KDirOperator::slotSortByDate()
{
d->sorting = (d->sorting & ~QDir::SortByMask) | QDir::Time;
d->actionCollection->action("by date")->setChecked(true);
triggerSorting();
}
void KDirOperator::slotSortByType()
{
d->sorting = (d->sorting & ~QDir::SortByMask) | QDir::Type;
d->actionCollection->action("by type")->setChecked(true);
triggerSorting();
}
void KDirOperator::slotSortReversed()
{
if (d->sorting & QDir::Reversed) {
d->sorting = d->sorting & ~QDir::Reversed;
d->actionCollection->action("descending")->setChecked(false);
} else {
d->sorting = d->sorting | QDir::Reversed;
d->actionCollection->action("descending")->setChecked(true);
}
triggerSorting();
}
void KDirOperator::slotToggleDirsFirst()
{
// TODO: port to Qt4's QAbstractItemView
/*if ( !d->fileView )
return;
QDir::SortFlags sorting = d->fileView->sorting();
if ( !KFile::isSortDirsFirst( sorting ) )
d->fileView->setSorting( sorting | QDir::DirsFirst );
else
d->fileView->setSorting( sorting & ~QDir::DirsFirst );
d->sorting = d->fileView->sorting();*/
}
void KDirOperator::slotToggleIgnoreCase()
{
// TODO: port to Qt4's QAbstractItemView
/*if ( !d->fileView )
return;
QDir::SortFlags sorting = d->fileView->sorting();
if ( !KFile::isSortCaseInsensitive( sorting ) )
d->fileView->setSorting( sorting | QDir::IgnoreCase );
else
d->fileView->setSorting( sorting & ~QDir::IgnoreCase );
d->sorting = d->fileView->sorting();*/
}
void KDirOperator::mkdir()
{
bool ok;
QString where = url().pathOrUrl();
QString name = i18n("New Folder");
#ifdef Q_WS_WIN
if (url().isLocalFile() && QFileInfo(url().toLocalFile() + name).exists())
#else
if (url().isLocalFile() && QFileInfo(url().path(KUrl::AddTrailingSlash) + name).exists())
#endif
name = KIO::RenameDialog::suggestName(url(), name);
QString folder = KInputDialog::getText(i18n("New Folder"),
i18n("Create new folder in:\n%1" , where),
name, &ok, this);
if (ok)
mkdir(KIO::encodeFileName(folder), true);
}
bool KDirOperator::mkdir(const QString& directory, bool enterDirectory)
{
// Creates "directory", relative to the current directory (d->currUrl).
// The given path may contain any number directories, existant or not.
// They will all be created, if possible.
bool writeOk = false;
bool exists = false;
KUrl url(d->currUrl);
QStringList dirs = directory.split(QDir::separator(), QString::SkipEmptyParts);
QStringList::ConstIterator it = dirs.begin();
for (; it != dirs.end(); ++it) {
url.addPath(*it);
exists = KIO::NetAccess::exists(url, KIO::NetAccess::DestinationSide, 0);
writeOk = !exists && KIO::NetAccess::mkdir(url, topLevelWidget());
}
if (exists) { // url was already existant
KMessageBox::sorry(d->itemView, i18n("A file or folder named %1 already exists.", url.pathOrUrl()));
enterDirectory = false;
} else if (!writeOk) {
KMessageBox::sorry(d->itemView, i18n("You do not have permission to "
"create that folder."));
} else if (enterDirectory) {
setUrl(url, true);
}
return writeOk;
}
KIO::DeleteJob * KDirOperator::del(const QList& items,
QWidget *parent,
bool ask, bool showProgress)
{
if (items.isEmpty()) {
KMessageBox::information(parent,
i18n("You did not select a file to delete."),
i18n("Nothing to Delete"));
return 0L;
}
if (parent == 0) {
parent = this;
}
KUrl::List urls;
QStringList files;
foreach (const KFileItem item, items) {
const KUrl url = item.url();
urls.append(url);
files.append(url.pathOrUrl());
}
bool doIt = !ask;
if (ask) {
int ret;
if (items.count() == 1) {
ret = KMessageBox::warningContinueCancel(parent,
i18n("Do you really want to delete\n '%1'?" ,
files.first()),
i18n("Delete File"),
KStandardGuiItem::del(),
KStandardGuiItem::cancel(), "AskForDelete");
} else
ret = KMessageBox::warningContinueCancelList(parent,
i18np("Do you really want to delete this item?", "Do you really want to delete these %1 items?", items.count()),
files,
i18n("Delete Files"),
KStandardGuiItem::del(),
KStandardGuiItem::cancel(), "AskForDelete");
doIt = (ret == KMessageBox::Continue);
}
if (doIt) {
KIO::DeleteJob *job = KIO::del(urls, false, showProgress);
job->ui()->setWindow(topLevelWidget());
job->ui()->setAutoErrorHandlingEnabled(true);
return job;
}
return 0L;
}
void KDirOperator::deleteSelected()
{
const QList list = selectedItems();
if (!list.isEmpty()) {
del(list, this);
}
}
KIO::CopyJob * KDirOperator::trash(const QList& items,
QWidget *parent,
bool ask, bool showProgress)
{
if (items.isEmpty()) {
KMessageBox::information(parent,
i18n("You did not select a file to trash."),
i18n("Nothing to Trash"));
return 0L;
}
KUrl::List urls;
QStringList files;
foreach (const KFileItem item, items) {
const KUrl url = item.url();
urls.append(url);
files.append(url.pathOrUrl());
}
bool doIt = !ask;
if (ask) {
int ret;
if (items.count() == 1) {
ret = KMessageBox::warningContinueCancel(parent,
i18n("Do you really want to trash\n '%1'?" ,
files.first()),
i18n("Trash File"),
KGuiItem(i18nc("to trash", "&Trash"), "edit-trash"),
KStandardGuiItem::cancel(), "AskForTrash");
} else
ret = KMessageBox::warningContinueCancelList(parent,
i18np("translators: not called for n == 1", "Do you really want to trash these %1 items?", items.count()),
files,
i18n("Trash Files"),
KGuiItem(i18nc("to trash", "&Trash"), "edit-trash"),
KStandardGuiItem::cancel(), "AskForTrash");
doIt = (ret == KMessageBox::Continue);
}
if (doIt) {
KIO::CopyJob *job = KIO::trash(urls, showProgress);
job->ui()->setWindow(topLevelWidget());
job->ui()->setAutoErrorHandlingEnabled(true);
return job;
}
return 0L;
}
void KDirOperator::trashSelected()
{
if (d->itemView == 0) {
return;
}
if (QApplication::keyboardModifiers() & Qt::ShiftModifier) {
deleteSelected();
return;
}
const QList list = selectedItems();
if (!list.isEmpty()) {
trash(list, this);
}
}
void KDirOperator::close()
{
resetCursor();
d->pendingMimeTypes.clear();
d->completion.clear();
d->dirCompletion.clear();
d->completeListDirty = true;
d->dirLister->stop();
}
void KDirOperator::checkPath(const QString &, bool /*takeFiles*/) // SLOT
{
#if 0
// copy the argument in a temporary string
QString text = _txt;
// it's unlikely to happen, that at the beginning are spaces, but
// for the end, it happens quite often, I guess.
text = text.trimmed();
// if the argument is no URL (the check is quite fragil) and it's
// no absolute path, we add the current directory to get a correct url
if (text.find(':') < 0 && text[0] != '/')
text.insert(0, d->currUrl);
// in case we have a selection defined and someone patched the file-
// name, we check, if the end of the new name is changed.
if (!selection.isNull()) {
int position = text.lastIndexOf('/');
ASSERT(position >= 0); // we already inserted the current d->dirLister in case
QString filename = text.mid(position + 1, text.length());
if (filename != selection)
selection = QString();
}
KUrl u(text); // I have to take care of entered URLs
bool filenameEntered = false;
if (u.isLocalFile()) {
// the empty path is kind of a hack
KFileItem i("", u.toLocalFile());
if (i.isDir())
setUrl(text, true);
else {
if (takeFiles)
if (acceptOnlyExisting && !i.isFile())
warning("you entered an invalid URL");
else
filenameEntered = true;
}
} else
setUrl(text, true);
if (filenameEntered) {
filename_ = u.url();
emit fileSelected(filename_);
QApplication::restoreOverrideCursor();
accept();
}
#endif
kDebug(kfile_area) << "TODO KDirOperator::checkPath()";
}
void KDirOperator::setUrl(const KUrl& _newurl, bool clearforward)
{
KUrl newurl;
if (!_newurl.isValid())
newurl.setPath(QDir::homePath());
else
newurl = _newurl;
#ifdef Q_WS_WIN
QString pathstr = newurl.toLocalFile();
#else
QString pathstr = newurl.path(KUrl::AddTrailingSlash);
#endif
newurl.setPath(pathstr);
// already set
if (newurl.equals(d->currUrl, KUrl::CompareWithoutTrailingSlash))
return;
if (!isReadable(newurl)) {
// maybe newurl is a file? check its parent directory
newurl.cd(QLatin1String(".."));
if (!isReadable(newurl)) {
resetCursor();
KMessageBox::error(d->itemView,
i18n("The specified folder does not exist "
"or was not readable."));
return;
}
}
if (clearforward) {
// autodelete should remove this one
d->backStack.push(new KUrl(d->currUrl));
qDeleteAll(d->forwardStack);
d->forwardStack.clear();
}
d->lastURL = d->currUrl.url(KUrl::RemoveTrailingSlash);
d->currUrl = newurl;
pathChanged();
emit urlEntered(newurl);
// enable/disable actions
QAction* forwardAction = d->actionCollection->action("forward");
forwardAction->setEnabled(!d->forwardStack.isEmpty());
QAction* backAction = d->actionCollection->action("back");
backAction->setEnabled(!d->backStack.isEmpty());
QAction* upAction = d->actionCollection->action("up");
upAction->setEnabled(!isRoot());
openUrl(newurl);
}
void KDirOperator::updateDir()
{
d->dirLister->emitChanges();
}
void KDirOperator::rereadDir()
{
pathChanged();
openUrl(d->currUrl, false, true);
}
bool KDirOperator::openUrl(const KUrl& url, bool keep, bool reload)
{
bool result = d->dirLister->openUrl(url, keep, reload);
if (!result) // in that case, neither completed() nor canceled() will be emitted by KDL
slotCanceled();
return result;
}
int KDirOperator::sortColumn() const
{
int column = KDirModel::Name;
if (KFile::isSortByDate(d->sorting)) {
column = KDirModel::ModifiedTime;
} else if (KFile::isSortBySize(d->sorting)) {
column = KDirModel::Size;
} else if (KFile::isSortByType(d->sorting)) {
column = KDirModel::Type;
} else {
Q_ASSERT(KFile::isSortByName(d->sorting));
}
return column;
}
Qt::SortOrder KDirOperator::sortOrder() const
{
return (d->sorting & QDir::Reversed) ? Qt::DescendingOrder :
Qt::AscendingOrder;
}
void KDirOperator::triggerSorting()
{
d->proxyModel->sort(sortColumn(), sortOrder());
// TODO: The headers from QTreeView don't take care about a sorting
// change of the proxy model hence they must be updated the manually.
// This is done here by a qobject_cast, but it would be nicer to:
// - provide a signal 'sortingChanged()'
// - connect DirOperatorDetailView() with this signal and update the
// header internally
QTreeView* treeView = qobject_cast(d->itemView);
if (treeView != 0) {
QHeaderView* headerView = treeView->header();
headerView->setSortIndicator(sortColumn(), sortOrder());
}
assureVisibleSelection();
}
// Protected
void KDirOperator::pathChanged()
{
if (d->itemView == 0)
return;
d->pendingMimeTypes.clear();
//d->fileView->clear(); TODO
d->completion.clear();
d->dirCompletion.clear();
// it may be, that we weren't ready at this time
QApplication::restoreOverrideCursor();
// when KIO::Job emits finished, the slot will restore the cursor
QApplication::setOverrideCursor(Qt::WaitCursor);
if (!isReadable(d->currUrl)) {
KMessageBox::error(d->itemView,
i18n("The specified folder does not exist "
"or was not readable."));
if (d->backStack.isEmpty())
home();
else
back();
}
}
void KDirOperator::slotRedirected(const KUrl& newURL)
{
d->currUrl = newURL;
d->pendingMimeTypes.clear();
d->completion.clear();
d->dirCompletion.clear();
d->completeListDirty = true;
emit urlEntered(newURL);
}
// Code pinched from kfm then hacked
void KDirOperator::back()
{
if (d->backStack.isEmpty())
return;
d->forwardStack.push(new KUrl(d->currUrl));
KUrl *s = d->backStack.pop();
setUrl(*s, false);
delete s;
}
// Code pinched from kfm then hacked
void KDirOperator::forward()
{
if (d->forwardStack.isEmpty())
return;
d->backStack.push(new KUrl(d->currUrl));
KUrl *s = d->forwardStack.pop();
setUrl(*s, false);
delete s;
}
KUrl KDirOperator::url() const
{
return d->currUrl;
}
void KDirOperator::cdUp()
{
KUrl tmp(d->currUrl);
tmp.cd(QLatin1String(".."));
setUrl(tmp, true);
}
void KDirOperator::home()
{
KUrl u;
u.setPath(QDir::homePath());
setUrl(u, true);
}
void KDirOperator::clearFilter()
{
d->dirLister->setNameFilter(QString());
d->dirLister->clearMimeFilter();
checkPreviewSupport();
}
void KDirOperator::setNameFilter(const QString& filter)
{
d->dirLister->setNameFilter(filter);
checkPreviewSupport();
}
QString KDirOperator::nameFilter() const
{
return d->dirLister->nameFilter();
}
void KDirOperator::setMimeFilter(const QStringList& mimetypes)
{
d->dirLister->setMimeFilter(mimetypes);
checkPreviewSupport();
}
QStringList KDirOperator::mimeFilter() const
{
return d->dirLister->mimeFilters();
}
bool KDirOperator::checkPreviewSupport()
{
KToggleAction *previewAction = static_cast(d->actionCollection->action("preview"));
bool hasPreviewSupport = false;
KConfigGroup cg(KGlobal::config(), ConfigGroup);
if (cg.readEntry("Show Default Preview", true))
hasPreviewSupport = checkPreviewInternal();
previewAction->setEnabled(hasPreviewSupport);
return hasPreviewSupport;
}
void KDirOperator::activatedMenu(const KFileItem &item, const QPoint &pos)
{
Q_UNUSED(item);
setupMenu();
updateSelectionDependentActions();
d->actionMenu->menu()->exec(pos);
}
bool KDirOperator::checkPreviewInternal() const
{
QStringList supported = KIO::PreviewJob::supportedMimeTypes();
// no preview support for directories?
if (dirOnlyMode() && supported.indexOf("inode/directory") == -1)
return false;
QStringList mimeTypes = d->dirLister->mimeFilters();
QStringList nameFilter = d->dirLister->nameFilter().split(" ", QString::SkipEmptyParts);
if (mimeTypes.isEmpty() && nameFilter.isEmpty() && !supported.isEmpty())
return true;
else {
QRegExp r;
r.setPatternSyntax(QRegExp::Wildcard); // the "mimetype" can be "image/*"
if (!mimeTypes.isEmpty()) {
QStringList::Iterator it = supported.begin();
for (; it != supported.end(); ++it) {
r.setPattern(*it);
QStringList result = mimeTypes.filter(r);
if (!result.isEmpty()) { // matches! -> we want previews
return true;
}
}
}
if (!nameFilter.isEmpty()) {
// find the mimetypes of all the filter-patterns
QStringList::const_iterator it1 = nameFilter.begin();
for (; it1 != nameFilter.end(); ++it1) {
if ((*it1) == "*") {
return true;
}
KMimeType::Ptr mt = KMimeType::findByPath(*it1, 0, true /*fast mode, no file contents exist*/);
if (!mt)
continue;
QString mime = mt->name();
// the "mimetypes" we get from the PreviewJob can be "image/*"
// so we need to check in wildcard mode
QStringList::Iterator it2 = supported.begin();
for (; it2 != supported.end(); ++it2) {
r.setPattern(*it2);
if (r.indexIn(mime) != -1) {
return true;
}
}
}
}
}
return false;
}
QAbstractItemView* KDirOperator::createView(QWidget* parent, KFile::FileView viewKind)
{
QAbstractItemView *itemView = 0;
if (KFile::isDetailView(viewKind)) {
DirOperatorDetailView *detailView = new DirOperatorDetailView(parent);
connect(detailView->header(), SIGNAL(sortIndicatorChanged (int, Qt::SortOrder)),
this, SLOT(synchronizeSortingState(int, Qt::SortOrder)));
itemView = detailView;
} else {
itemView = new DirOperatorIconView(parent);
}
return itemView;
}
void KDirOperator::setAcceptDrops(bool b)
{
// TODO:
//if (d->fileView)
// d->fileView->widget()->setAcceptDrops(b);
QWidget::setAcceptDrops(b);
}
void KDirOperator::setDropOptions(int options)
{
d->dropOptions = options;
// TODO:
//if (d->fileView)
// d->fileView->setDropOptions(options);
}
void KDirOperator::setView(KFile::FileView viewKind)
{
bool preview = (KFile::isPreviewInfo(viewKind) || KFile::isPreviewContents(viewKind));
if (viewKind == KFile::Default) {
if (KFile::isDetailView((KFile::FileView)d->defaultView)) {
viewKind = KFile::Detail;
} else {
viewKind = KFile::Simple;
}
const KFile::FileView defaultViewKind = static_cast(d->defaultView);
preview = (KFile::isPreviewInfo(defaultViewKind) || KFile::isPreviewContents(defaultViewKind))
&& d->actionCollection->action("preview")->isEnabled();
}
d->viewKind = static_cast(viewKind);
viewKind = static_cast(d->viewKind);
QAbstractItemView *newView = createView(this, viewKind);
setView(newView);
togglePreview(preview);
}
QAbstractItemView * KDirOperator::view() const
{
return d->itemView;
}
KFile::Modes KDirOperator::mode() const
{
return d->mode;
}
void KDirOperator::setMode(KFile::Modes mode)
{
if (d->mode == mode)
return;
d->mode = mode;
d->dirLister->setDirOnlyMode(dirOnlyMode());
// reset the view with the different mode
setView(static_cast(d->viewKind));
}
void KDirOperator::setView(QAbstractItemView *view)
{
if (view == d->itemView) {
return;
}
// TODO: do a real timer and restart it after that
d->pendingMimeTypes.clear();
const bool listDir = (d->itemView == 0);
if (d->mode & KFile::Files) {
view->setSelectionMode(QAbstractItemView::ExtendedSelection);
} else {
view->setSelectionMode(QAbstractItemView::SingleSelection);
}
QItemSelectionModel *selectionModel = 0;
if ((d->itemView != 0) && d->itemView->selectionModel()->hasSelection()) {
// remember the selection of the current item view and apply this selection
// to the new view later
const QItemSelection selection = d->itemView->selectionModel()->selection();
selectionModel = new QItemSelectionModel(d->proxyModel, this);
selectionModel->select(selection, QItemSelectionModel::Select);
}
delete d->itemView;
d->itemView = view;
d->itemView->setModel(d->proxyModel);
KFileItemDelegate *delegate = new KFileItemDelegate(d->itemView);
d->itemView->setItemDelegate(delegate);
d->itemView->viewport()->setAttribute(Qt::WA_Hover);
d->itemView->setContextMenuPolicy(Qt::CustomContextMenu);
d->itemView->setMouseTracking(true);
//d->itemView->setDropOptions(d->dropOptions);
connect(d->itemView, SIGNAL(pressed(const QModelIndex&)),
this, SLOT(slotPressed(const QModelIndex&)));
connect(d->itemView, SIGNAL(clicked(const QModelIndex&)),
this, SLOT(slotClicked(const QModelIndex&)));
connect(d->itemView, SIGNAL(doubleClicked(const QModelIndex&)),
this, SLOT(slotDoubleClicked(const QModelIndex&)));
connect(d->itemView, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(openContextMenu(const QPoint&)));
connect(d->itemView, SIGNAL(entered(const QModelIndex&)),
this, SLOT(triggerPreview(const QModelIndex&)));
connect(d->itemView, SIGNAL(viewportEntered()),
this, SLOT(cancelPreview()));
// assure that the sorting state d->sorting matches with the current action
const bool descending = d->actionCollection->action("descending")->isChecked();
if (!descending && d->sorting & QDir::Reversed) {
d->sorting = d->sorting & ~QDir::Reversed;
} else if (descending && !(d->sorting & QDir::Reversed)) {
d->sorting = d->sorting | QDir::Reversed;
}
triggerSorting();
updateViewActions();
d->splitter->insertWidget(0, d->itemView);
d->splitter->resize(size());
d->itemView->show();
if (listDir) {
QApplication::setOverrideCursor(Qt::WaitCursor);
openUrl(d->currUrl);
}
if (selectionModel != 0) {
d->itemView->setSelectionModel(selectionModel);
QMetaObject::invokeMethod(this, "assureVisibleSelection", Qt::QueuedConnection);
}
emit viewChanged(view);
}
void KDirOperator::setDirLister(KDirLister *lister)
{
if (lister == d->dirLister) // sanity check
return;
delete d->dirModel;
d->dirModel = 0;
delete d->proxyModel;
d->proxyModel = 0;
delete d->dirLister;
d->dirLister = lister;
d->dirModel = new KDirModel();
d->dirModel->setDirLister(d->dirLister);
d->dirModel->setDropsAllowed(KDirModel::DropOnDirectory);
d->proxyModel = new KDirSortFilterProxyModel(this);
d->proxyModel->setSourceModel(d->dirModel);
d->dirLister->setAutoUpdate(true);
d->dirLister->setDelayedMimeTypes(true);
QWidget* mainWidget = topLevelWidget();
d->dirLister->setMainWindow(mainWidget);
kDebug(kfile_area) << "mainWidget=" << mainWidget;
connect(d->dirLister, SIGNAL(percent(int)),
SLOT(slotProgress(int)));
connect(d->dirLister, SIGNAL(started(const KUrl&)), SLOT(slotStarted()));
connect(d->dirLister, SIGNAL(completed()), SLOT(slotIOFinished()));
connect(d->dirLister, SIGNAL(canceled()), SLOT(slotCanceled()));
connect(d->dirLister, SIGNAL(redirection(const KUrl&)),
SLOT(slotRedirected(const KUrl&)));
}
-void KDirOperator::selectDir(const KFileItem *item)
+void KDirOperator::selectDir(const KFileItem &item)
{
- setUrl(item->url(), true);
+ setUrl(item.url(), true);
}
-void KDirOperator::selectFile(const KFileItem *item)
+void KDirOperator::selectFile(const KFileItem &item)
{
QApplication::restoreOverrideCursor();
emit fileSelected(item);
}
-void KDirOperator::highlightFile(const KFileItem *item)
+void KDirOperator::highlightFile(const KFileItem &item)
{
- Q_ASSERT(item != 0);
+ Q_ASSERT(!item.isNull());
if (d->preview != 0) {
- d->preview->showPreview(item->url());
+ d->preview->showPreview(item.url());
}
emit fileHighlighted(item);
}
void KDirOperator::setCurrentItem(const QString& filename)
{
if (d->itemView == 0) {
return;
}
- const KFileItem *item = 0;
+ KFileItem item;
if ( !filename.isNull() ) {
item = d->dirLister->findByName(filename);
}
QItemSelectionModel *selModel = d->itemView->selectionModel();
selModel->clear();
- if (item != 0) {
- const QModelIndex dirIndex = d->dirModel->indexForItem(*item);
+ if (!item.isNull()) {
+ const QModelIndex dirIndex = d->dirModel->indexForItem(item);
const QModelIndex proxyIndex = d->proxyModel->mapFromSource(dirIndex);
selModel->setCurrentIndex(proxyIndex, QItemSelectionModel::Select);
selModel->select(proxyIndex, QItemSelectionModel::Select);
assureVisibleSelection();
}
}
QString KDirOperator::makeCompletion(const QString& string)
{
if (string.isEmpty()) {
d->itemView->selectionModel()->clear();
return QString();
}
prepareCompletionObjects();
return d->completion.makeCompletion(string);
}
QString KDirOperator::makeDirCompletion(const QString& string)
{
if (string.isEmpty()) {
d->itemView->selectionModel()->clear();
return QString();
}
prepareCompletionObjects();
return d->dirCompletion.makeCompletion(string);
}
void KDirOperator::prepareCompletionObjects()
{
if (d->itemView == 0) {
return;
}
if (d->completeListDirty) { // create the list of all possible completions
const KFileItemList itemList = d->dirLister->items();
- foreach (const KFileItem *item, itemList) {
- d->completion.addItem(item->name());
- if (item->isDir()) {
- d->dirCompletion.addItem(item->name());
+ foreach (const KFileItem item, itemList) {
+ d->completion.addItem(item.name());
+ if (item.isDir()) {
+ d->dirCompletion.addItem(item.name());
}
}
d->completeListDirty = false;
}
}
void KDirOperator::slotCompletionMatch(const QString& match)
{
setCurrentItem(match);
emit completion(match);
}
void KDirOperator::setupActions()
{
d->actionCollection = new KActionCollection(this);
d->actionCollection->setObjectName("KDirOperator::actionCollection");
d->actionCollection->setAssociatedWidget(topLevelWidget());
d->actionMenu = new KActionMenu(i18n("Menu"), this);
d->actionCollection->addAction("popupMenu", d->actionMenu);
QAction* upAction = d->actionCollection->addAction(KStandardAction::Up, "up", this, SLOT(cdUp()));
upAction->setText(i18n("Parent Folder"));
d->actionCollection->addAction(KStandardAction::Back, "back", this, SLOT(back()));
d->actionCollection->addAction(KStandardAction::Forward, "forward", this, SLOT(forward()));
QAction* homeAction = d->actionCollection->addAction(KStandardAction::Home, "home", this, SLOT(home()));
homeAction->setText(i18n("Home Folder"));
QAction* reloadAction = d->actionCollection->addAction(KStandardAction::Redisplay, "reload", this, SLOT(rereadDir()));
reloadAction->setText(i18n("Reload"));
reloadAction->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::Reload));
QAction* mkdirAction = new KAction(i18n("New Folder..."), this);
d->actionCollection->addAction("mkdir", mkdirAction);
mkdirAction->setIcon(KIcon(QLatin1String("folder-new")));
connect(mkdirAction, SIGNAL(triggered(bool)), this, SLOT(mkdir()));
KAction* trash = new KAction(i18n("Move to Trash"), this);
d->actionCollection->addAction("trash", trash);
trash->setIcon(KIcon("edit-trash"));
trash->setShortcuts(KShortcut(Qt::Key_Delete));
connect(trash, SIGNAL(triggered(bool)), SLOT(trashSelected()));
KAction* action = new KAction(i18n("Delete"), this);
d->actionCollection->addAction("delete", action);
action->setIcon(KIcon("edit-delete"));
action->setShortcuts(KShortcut(Qt::SHIFT + Qt::Key_Delete));
connect(action, SIGNAL(triggered(bool)), this, SLOT(deleteSelected()));
// the sort menu actions
KActionMenu *sortMenu = new KActionMenu(i18n("Sorting"), this);
d->actionCollection->addAction("sorting menu", sortMenu);
KToggleAction *byNameAction = new KToggleAction(i18n("By Name"), this);
d->actionCollection->addAction("by name", byNameAction);
connect(byNameAction, SIGNAL(triggered(bool)), this, SLOT(slotSortByName()));
KToggleAction *bySizeAction = new KToggleAction(i18n("By Size"), this);
d->actionCollection->addAction("by size", bySizeAction);
connect(bySizeAction, SIGNAL(triggered(bool)), this, SLOT(slotSortBySize()));
KToggleAction *byDateAction = new KToggleAction(i18n("By Date"), this);
d->actionCollection->addAction("by date", byDateAction);
connect(byDateAction, SIGNAL(triggered(bool)), this, SLOT(slotSortByDate()));
KToggleAction *byTypeAction = new KToggleAction(i18n("By Type"), this);
d->actionCollection->addAction("by type", byTypeAction);
connect(byTypeAction, SIGNAL(triggered(bool)), this, SLOT(slotSortByType()));
KToggleAction *descendingAction = new KToggleAction(i18n("Descending"), this);
d->actionCollection->addAction("descending", descendingAction);
connect(descendingAction, SIGNAL(triggered(bool)), this, SLOT(slotSortReversed()));
QActionGroup* sortGroup = new QActionGroup(this);
byNameAction->setActionGroup(sortGroup);
bySizeAction->setActionGroup(sortGroup);
byDateAction->setActionGroup(sortGroup);
byTypeAction->setActionGroup(sortGroup);
KToggleAction *shortAction = new KToggleAction(i18n("Short View"), this);
d->actionCollection->addAction("short view", shortAction);
shortAction->setIcon(KIcon(QLatin1String("fileview-multicolumn")));
connect(shortAction, SIGNAL(activated()), SLOT(slotSimpleView()));
KToggleAction *detailedAction = new KToggleAction(i18n("Detailed View"), this);
d->actionCollection->addAction("detailed view", detailedAction);
detailedAction->setIcon(KIcon(QLatin1String("fileview-detailed")));
connect(detailedAction, SIGNAL(activated()), SLOT(slotDetailedView()));
QActionGroup* viewGroup = new QActionGroup(this);
shortAction->setActionGroup(viewGroup);
detailedAction->setActionGroup(viewGroup);
KToggleAction *showHiddenAction = new KToggleAction(i18n("Show Hidden Files"), this);
d->actionCollection->addAction("show hidden", showHiddenAction);
connect(showHiddenAction, SIGNAL(toggled(bool)), SLOT(slotToggleHidden(bool)));
KToggleAction *previewAction = new KToggleAction(i18n("Show Preview"), this);
d->actionCollection->addAction("preview", previewAction);
previewAction->setIcon(KIcon("thumbnail-show"));
connect(previewAction, SIGNAL(toggled(bool)),
SLOT(togglePreview(bool)));
action = new KAction(i18n("Properties"), this);
d->actionCollection->addAction("properties", action);
action->setShortcut(KShortcut(Qt::ALT + Qt::Key_Return));
connect(action, SIGNAL(triggered(bool)), this, SLOT(slotProperties()));
// the view menu actions
KActionMenu* viewMenu = new KActionMenu(i18n("&View"), this);
d->actionCollection->addAction("view menu", viewMenu);
viewMenu->addAction(shortAction);
viewMenu->addAction(detailedAction);
// TODO: QAbstractItemView does not offer an action collection. Provide
// an interface to add a custom action collection.
}
void KDirOperator::setupMenu()
{
setupMenu(SortActions | ViewActions | FileActions);
}
void KDirOperator::setupMenu(int whichActions)
{
// first fill the submenus (sort and view)
KActionMenu *sortMenu = static_cast(d->actionCollection->action("sorting menu"));
sortMenu->menu()->clear();
sortMenu->addAction(d->actionCollection->action("by name"));
sortMenu->addAction(d->actionCollection->action("by size"));
sortMenu->addAction(d->actionCollection->action("by date"));
sortMenu->addAction(d->actionCollection->action("by type"));
sortMenu->addSeparator();
sortMenu->addAction(d->actionCollection->action("descending"));
// now plug everything into the popupmenu
d->actionMenu->menu()->clear();
if (whichActions & NavActions) {
d->actionMenu->addAction(d->actionCollection->action("up"));
d->actionMenu->addAction(d->actionCollection->action("back"));
d->actionMenu->addAction(d->actionCollection->action("forward"));
d->actionMenu->addAction(d->actionCollection->action("home"));
d->actionMenu->addSeparator();
}
if (whichActions & FileActions) {
d->actionMenu->addAction(d->actionCollection->action("mkdir"));
if (d->currUrl.isLocalFile() && !(QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
d->actionMenu->addAction(d->actionCollection->action("trash"));
}
KConfigGroup cg(KGlobal::config(), QLatin1String("KDE"));
const bool del = !d->currUrl.isLocalFile() ||
(QApplication::keyboardModifiers() & Qt::ShiftModifier) ||
cg.readEntry("ShowDeleteCommand", false);
if (del) {
d->actionMenu->addAction(d->actionCollection->action("delete"));
}
d->actionMenu->addSeparator();
}
if (whichActions & SortActions) {
d->actionMenu->addAction(sortMenu);
if (!(whichActions & ViewActions)) {
d->actionMenu->addSeparator();
}
}
if (whichActions & ViewActions) {
d->actionMenu->addAction(d->actionCollection->action("view menu"));
d->actionMenu->addSeparator();
}
if (whichActions & FileActions) {
d->actionMenu->addAction(d->actionCollection->action("properties"));
}
}
void KDirOperator::updateSortActions()
{
if (KFile::isSortByName(d->sorting)) {
d->actionCollection->action("by name")->setChecked(true);
} else if (KFile::isSortByDate(d->sorting)) {
d->actionCollection->action("by date")->setChecked(true);
} else if (KFile::isSortBySize(d->sorting)) {
d->actionCollection->action("by size")->setChecked(true);
} else if (KFile::isSortByType(d->sorting)) {
d->actionCollection->action("by type")->setChecked(true);
}
d->actionCollection->action("descending")->setChecked(d->sorting & QDir::Reversed);
}
void KDirOperator::updateViewActions()
{
KFile::FileView fv = static_cast(d->viewKind);
//QAction *separateDirs = d->actionCollection->action("separate dirs");
//separateDirs->setChecked(KFile::isSeparateDirs(fv) &&
// separateDirs->isEnabled());
d->actionCollection->action("short view")->setChecked(KFile::isSimpleView(fv));
d->actionCollection->action("detailed view")->setChecked(KFile::isDetailView(fv));
}
void KDirOperator::readConfig(const KConfigGroup& configGroup)
{
d->defaultView = 0;
QDir::SortFlags sorting = QDir::Name;
QString viewStyle = configGroup.readEntry("View Style", "Simple");
if (viewStyle == QLatin1String("Detail")) {
d->defaultView |= KFile::Detail;
} else {
d->defaultView |= KFile::Simple;
}
//if (configGroup.readEntry(QLatin1String("Separate Directories"),
// DefaultMixDirsAndFiles)) {
// d->defaultView |= KFile::SeparateDirs;
//}
if (configGroup.readEntry(QLatin1String("Show Preview"), false)) {
d->defaultView |= KFile::PreviewContents;
}
d->previewWidth = configGroup.readEntry(QLatin1String("Preview Width"), 100);
if (configGroup.readEntry(QLatin1String("Sort directories first"),
DefaultDirsFirst)) {
sorting |= QDir::DirsFirst;
}
QString name = QLatin1String("Name");
QString sortBy = configGroup.readEntry(QLatin1String("Sort by"), name);
if (sortBy == name) {
sorting |= QDir::Name;
} else if (sortBy == QLatin1String("Size")) {
sorting |= QDir::Size;
} else if (sortBy == QLatin1String("Date")) {
sorting |= QDir::Time;
} else if (sortBy == QLatin1String("Type")) {
sorting |= QDir::Type;
}
d->sorting = sorting;
setSorting(d->sorting);
if (configGroup.readEntry(QLatin1String("Show hidden files"),
DefaultShowHidden)) {
d->actionCollection->action("show hidden")->setChecked(true);
d->dirLister->setShowingDotFiles(true);
}
const bool descending = configGroup.readEntry(QLatin1String("Sort reversed"),
DefaultSortReversed);
d->actionCollection->action("descending")->setChecked(descending);
if (descending) {
d->sorting = d->sorting | QDir::Reversed;
}
}
void KDirOperator::writeConfig(KConfigGroup& configGroup)
{
QString sortBy = QLatin1String("Name");
if (KFile::isSortBySize(d->sorting)) {
sortBy = QLatin1String("Size");
} else if (KFile::isSortByDate(d->sorting)) {
sortBy = QLatin1String("Date");
} else if (KFile::isSortByType(d->sorting)) {
sortBy = QLatin1String("Type");
}
configGroup.writeEntry(QLatin1String("Sort by"), sortBy);
configGroup.writeEntry(QLatin1String("Sort reversed"),
d->actionCollection->action("descending")->isChecked());
// don't save the preview when an application specific preview is in use.
bool appSpecificPreview = false;
if (d->preview) {
KFileMetaPreview *tmp = dynamic_cast(d->preview);
appSpecificPreview = (tmp == 0);
}
if (!appSpecificPreview) {
KToggleAction *previewAction = static_cast(d->actionCollection->action("preview"));
if (previewAction->isEnabled()) {
bool hasPreview = previewAction->isChecked();
configGroup.writeEntry(QLatin1String("Show Preview"), hasPreview);
if (hasPreview) {
// remember the width of the preview widget
QList sizes = d->splitter->sizes();
Q_ASSERT(sizes.count() == 2);
configGroup.writeEntry(QLatin1String("Preview Width"), sizes[1]);
}
}
}
configGroup.writeEntry(QLatin1String("Show hidden files"),
d->actionCollection->action("show hidden")->isChecked());
KFile::FileView fv = static_cast(d->viewKind);
QString style;
if (KFile::isDetailView(fv))
style = QLatin1String("Detail");
else if (KFile::isSimpleView(fv))
style = QLatin1String("Simple");
configGroup.writeEntry(QLatin1String("View Style"), style);
}
void KDirOperator::resizeEvent(QResizeEvent *)
{
// resize the splitter and assure that the width of
// the preview widget is restored
QList sizes = d->splitter->sizes();
const bool hasPreview = (sizes.count() == 2);
const bool restorePreviewWidth = hasPreview && (d->previewWidth != sizes[1]);
d->splitter->resize(size());
sizes = d->splitter->sizes();
if (restorePreviewWidth) {
const int availableWidth = sizes[0] + sizes[1];
sizes[0] = availableWidth - d->previewWidth;
sizes[1] = d->previewWidth;
d->splitter->setSizes(sizes);
}
if (hasPreview) {
d->previewWidth = sizes[1];
}
if (d->progressBar->parent() == this) {
// might be reparented into a statusbar
d->progressBar->move(2, height() - d->progressBar->height() - 2);
}
}
void KDirOperator::setOnlyDoubleClickSelectsFiles(bool enable)
{
d->onlyDoubleClickSelectsFiles = enable;
// TODO: port to Qt4's QAbstractItemModel
//if (d->itemView != 0) {
// d->itemView->setOnlyDoubleClickSelectsFiles(enable);
//}
}
bool KDirOperator::onlyDoubleClickSelectsFiles() const
{
return d->onlyDoubleClickSelectsFiles;
}
void KDirOperator::slotStarted()
{
d->progressBar->setValue(0);
// delay showing the progressbar for one second
d->progressDelayTimer->setSingleShot(true);
d->progressDelayTimer->start(1000);
}
void KDirOperator::slotShowProgress()
{
d->progressBar->raise();
d->progressBar->show();
QApplication::flush();
}
void KDirOperator::slotProgress(int percent)
{
d->progressBar->setValue(percent);
// we have to redraw this as fast as possible
if (d->progressBar->isVisible())
QApplication::flush();
}
void KDirOperator::slotIOFinished()
{
d->progressDelayTimer->stop();
slotProgress(100);
d->progressBar->hide();
emit finishedLoading();
resetCursor();
}
void KDirOperator::slotCanceled()
{
emit finishedLoading();
resetCursor();
}
QProgressBar * KDirOperator::progressBar() const
{
return d->progressBar;
}
void KDirOperator::clearHistory()
{
qDeleteAll(d->backStack);
d->backStack.clear();
d->actionCollection->action("back")->setEnabled(false);
qDeleteAll(d->forwardStack);
d->forwardStack.clear();
d->actionCollection->action("forward")->setEnabled(false);
}
void KDirOperator::slotViewActionAdded(KAction *action)
{
KActionMenu* viewMenu = static_cast(d->actionCollection->action("view menu"));
viewMenu->addAction(action);
}
void KDirOperator::slotViewActionRemoved(KAction *action)
{
KActionMenu* viewMenu = static_cast(d->actionCollection->action("view menu"));
viewMenu->removeAction(action);
}
void KDirOperator::setEnableDirHighlighting(bool enable)
{
d->dirHighlighting = enable;
}
bool KDirOperator::dirHighlighting() const
{
return d->dirHighlighting;
}
bool KDirOperator::dirOnlyMode() const
{
return dirOnlyMode(d->mode);
}
bool KDirOperator::dirOnlyMode(uint mode)
{
return ((mode & KFile::Directory) &&
(mode & (KFile::File | KFile::Files)) == 0);
}
void KDirOperator::slotProperties()
{
if (d->itemView == 0) {
return;
}
const QList list = selectedItems();
if (!list.isEmpty()) {
- // TODO: KPropertiesDialog still uses pointer-based KFileItemList
- KFileItemList itemPtrList;
- foreach (KFileItem item, list) {
- itemPtrList << &item;
- }
-
- KPropertiesDialog dialog(itemPtrList, this);
+ KPropertiesDialog dialog(list, this);
dialog.exec();
}
}
void KDirOperator::slotPressed(const QModelIndex& index)
{
Q_UNUSED(index);
// Remember whether the left mouse button has been pressed, to prevent
// that a right-click on an item opens an item (see slotClicked(),
// slotDoubleClicked() and openContextMenu()).
d->leftButtonPressed = (QApplication::mouseButtons() & Qt::LeftButton);
}
void KDirOperator::slotClicked(const QModelIndex& index)
{
if (!d->leftButtonPressed) {
return;
}
const QModelIndex dirIndex = d->proxyModel->mapToSource(index);
KFileItem item = d->dirModel->itemForIndex(dirIndex);
if (item.isDir()) {
if (KGlobalSettings::singleClick()) {
- selectDir(&item);
+ selectDir(item);
} else {
- highlightFile(&item);
+ highlightFile(item);
}
} else {
- highlightFile(&item);
+ highlightFile(item);
}
}
void KDirOperator::slotDoubleClicked(const QModelIndex& index)
{
if (!d->leftButtonPressed) {
return;
}
const QModelIndex dirIndex = d->proxyModel->mapToSource(index);
KFileItem item = d->dirModel->itemForIndex(dirIndex);
if (item.isDir()) {
- selectDir(&item);
+ selectDir(item);
} else {
- selectFile(&item);
+ selectFile(item);
}
}
void KDirOperator::openContextMenu(const QPoint& pos)
{
d->leftButtonPressed = false;
const QModelIndex proxyIndex = d->itemView->indexAt(pos);
const QModelIndex dirIndex = d->proxyModel->mapToSource(proxyIndex);
KFileItem item = d->dirModel->itemForIndex(dirIndex);
activatedMenu(item, QCursor::pos());
}
void KDirOperator::triggerPreview(const QModelIndex& index)
{
if ((d->preview != 0) && index.isValid() && (index.column() == KDirModel::Name)) {
const QModelIndex dirIndex = d->proxyModel->mapToSource(index);
const KFileItem item = d->dirModel->itemForIndex(dirIndex);
if (!item.isDir()) {
d->previewUrl = item.url();
d->previewTimer->start(300);
}
}
}
void KDirOperator::cancelPreview()
{
d->previewTimer->stop();
}
void KDirOperator::showPreview()
{
if (d->preview != 0) {
d->preview->showPreview(d->previewUrl);
}
}
void KDirOperator::slotSplitterMoved(int pos, int index)
{
Q_UNUSED(pos);
Q_UNUSED(index);
const QList sizes = d->splitter->sizes();
if (sizes.count() == 2) {
// remember the width of the preview widget (see KDirOperator::resizeEvent())
d->previewWidth = sizes[1];
}
}
void KDirOperator::assureVisibleSelection()
{
if (d->itemView == 0) {
return;
}
QItemSelectionModel* selModel = d->itemView->selectionModel();
if (selModel->hasSelection()) {
const QModelIndexList list = selModel->selection().indexes();
const QModelIndex index = list.first();
d->itemView->scrollTo(index);
triggerPreview(index);
}
}
void KDirOperator::synchronizeSortingState(int logicalIndex, Qt::SortOrder order)
{
switch (logicalIndex) {
case KDirModel::Name: sortByName(); break;
case KDirModel::Size: sortBySize(); break;
case KDirModel::ModifiedTime: sortByDate(); break;
case KDirModel::Type: sortByType(); break;
}
const bool descending = d->actionCollection->action("descending")->isChecked();
const bool reverseSorting = ((order == Qt::Ascending) && descending) ||
((order == Qt::Descending) && !descending);
if (reverseSorting) {
sortReversed();
}
d->proxyModel->sort(sortColumn(), sortOrder());
QMetaObject::invokeMethod(this, "assureVisibleSelection", Qt::QueuedConnection);
}
void KDirOperator::setViewConfig(KConfigGroup& configGroup)
{
delete d->configGroup;
d->configGroup = new KConfigGroup(configGroup);
}
KConfigGroup* KDirOperator::viewConfigGroup() const
{
return d->configGroup;
}
void KDirOperator::setShowHiddenFiles(bool s)
{
d->actionCollection->action("show hidden")->setChecked(s);
}
bool KDirOperator::showHiddenFiles() const
{
return d->actionCollection->action("show hidden")->isChecked();
}
// ### temporary code
#include
bool KDirOperator::isReadable(const KUrl& url)
{
if (!url.isLocalFile())
return true; // what else can we say?
KDE_struct_stat buf;
#ifdef Q_WS_WIN
QString ts = url.toLocalFile();
#else
QString ts = url.path(KUrl::AddTrailingSlash);
#endif
bool readable = (KDE_stat(QFile::encodeName(ts), &buf) == 0);
if (readable) { // further checks
DIR *test;
test = opendir(QFile::encodeName(ts)); // we do it just to test here
readable = (test != 0);
if (test)
closedir(test);
}
return readable;
}
#include "kdiroperator.moc"
diff --git a/kfile/kdiroperator.h b/kfile/kdiroperator.h
index a3ba296c6a..48c4f12a26 100644
--- a/kfile/kdiroperator.h
+++ b/kfile/kdiroperator.h
@@ -1,864 +1,863 @@
// -*- c++ -*-
/* This file is part of the KDE libraries
Copyright (C) 1999 Stephan Kulow
2000,2001 Carsten Pfeiffer
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KDIROPERATOR_H_
#define KDIROPERATOR_H_
#include
#include
#include
#include
#include
#include
#include
#include
class QAbstractItemView;
class QModelIndex;
class QProgressBar;
class KAction;
class KActionMenu;
class KDirLister;
class KDirModel;
class KDirSortFilterProxyModel;
class KPreviewWidgetBase;
class KToggleAction;
namespace KIO
{
class CopyJob;
class DeleteJob;
}
/**
* This widget works as a network transparent filebrowser. You specify a URL
* to display and this url will be loaded via KDirLister. The user can
* browse through directories, highlight and select files, delete or rename
* files.
*
* It supports different views, e.g. a detailed view (see KFileDetailView),
* a simple icon view (see KFileIconView), a combination of two views,
* separating directories and files ( KCombiView).
*
* Additionally, a preview view is available (see KFilePreview), which can
* show either a simple or detailed view and additionally a preview widget
* (see setPreviewWidget()). KImageFilePreview is one implementation
* of a preview widget, that displays previews for all supported filetypes
* utilizing KIO::PreviewJob.
*
* Currently, those classes don't support Drag&Drop out of the box -- there
* you have to use your own view-classes. You can use some DnD-aware views
* from Bj�n Sahlstr� until they will be integrated
* into this library. See http://devel-home.kde.org/~pfeiffer/DnD-classes.tar.gz
*
* This widget is the one used in the KFileDialog.
*
* Basic usage is like this:
* \code
* KDirOperator *op = new KDirOperator( KUrl( "file:/home/gis" ), this );
* // some signals you might be interested in
* connect(op, SIGNAL(urlEntered(const KUrl&)),
* SLOT(urlEntered(const KUrl&)));
- * connect(op, SIGNAL(fileHighlighted(const KFileItem *)),
- * SLOT(fileHighlighted(const KFileItem *)));
- * connect(op, SIGNAL(fileSelected(const KFileItem *)),
- * SLOT(fileSelected(const KFileItem *)));
+ * connect(op, SIGNAL(fileHighlighted(const KFileItem &)),
+ * SLOT(fileHighlighted(const KFileItem &)));
+ * connect(op, SIGNAL(fileSelected(const KFileItem &)),
+ * SLOT(fileSelected(const KFileItem &)));
* connect(op, SIGNAL(finishedLoading()),
* SLOT(slotLoadingFinished()));
*
* KConfigGroup grp(KGlobal::config(),"Your KDiroperator ConfigGroup" );
* op->readConfig( &grp);
* op->setView(KFile::Default);
* \endcode
*
* This will create a childwidget of 'this' showing the directory contents
* of /home/gis in the default-view. The view is determined by the readConfig()
* call, which will read the KDirOperator settings, the user left your program
* with (and which you saved with op->writeConfig()).
*
* @short A widget for displaying files and browsing directories.
* @author Stephan Kulow , Carsten Pfeiffer
*/
class KFILE_EXPORT KDirOperator : public QWidget
{
Q_OBJECT
public:
/**
* The various action types. These values can be or'd together
*/
enum ActionType
{
SortActions = 1,
ViewActions = 2,
NavActions = 4,
FileActions = 8,
AllActions = 15
};
/**
* Constructs the KDirOperator with no initial view. As the views are
* configurable, call readConfig() to load the user's configuration
* and then setView to explicitly set a view.
*
* This constructor doesn't start loading the url, setView will do it.
*/
explicit KDirOperator(const KUrl& urlName = KUrl(),
QWidget *parent = 0);
/**
* Destroys the KDirOperator.
*/
virtual ~KDirOperator();
/**
* Enables/disables showing hidden files.
*/
virtual void setShowHiddenFiles(bool s);
/**
* @returns true when hidden files are shown or false otherwise.
*/
bool showHiddenFiles() const;
/**
* Stops loading immediately. You don't need to call this, usually.
*/
void close();
/**
* Sets a filter like "*.cpp *.h *.o". Only files matching that filter
* will be shown.
*
* @see KDirLister::setNameFilter
* @see nameFilter
*/
void setNameFilter(const QString& filter);
/**
* @returns the current namefilter.
* @see setNameFilter
*/
QString nameFilter() const;
/**
* Sets a list of mimetypes as filter. Only files of those mimetypes
* will be shown.
*
* Example:
* \code
* QStringList filter;
* filter << "text/html" << "image/png" << "inode/directory";
* dirOperator->setMimefilter( filter );
* \endcode
*
* Node: Without the mimetype inode/directory, only files would be shown.
* Call updateDir() to apply it.
*
* @see KDirLister::setMimeFilter
* @see mimeFilter
*/
void setMimeFilter(const QStringList& mimetypes);
/**
* @returns the current mime filter.
*/
QStringList mimeFilter() const;
/**
* Clears both the namefilter and mimetype filter, so that all files and
* directories will be shown. Call updateDir() to apply it.
*
* @see setMimeFilter
* @see setNameFilter
*/
void clearFilter();
/**
* @returns the current url
*/
KUrl url() const;
/**
* Sets a new url to list.
* @param clearforward specifies whether the "forward" history should be cleared.
* @param url the URL to set
*/
virtual void setUrl(const KUrl& url, bool clearforward);
/**
* Clears the current selection and attempts to set @p filename
* the current file. filename is just the name, no path or url.
*/
void setCurrentItem(const QString& filename);
/**
* Sets a new KFileView to be used for showing and browsing files.
* Note: this will read the current url() to fill the view.
*
* @see KFileView
* @see KFileIconView
* @see KFileDetailView
* @see KCombiView
* @see view
*/
virtual void setView(QAbstractItemView *view);
/**
* @returns the currently used view.
* @see setView
*/
QAbstractItemView* view() const;
/**
* Sets one of the predefined fileviews.
* @see KFile::FileView
*/
virtual void setView(KFile::FileView viewKind);
/**
* Sets the way to sort files and directories.
*/
void setSorting(QDir::SortFlags);
/**
* @returns the current way of sorting files and directories
*/
QDir::SortFlags sorting() const;
/**
* @returns true if we are displaying the root directory of the current url
*/
bool isRoot() const;
/**
* @returns the object listing the directory
*/
KDirLister* dirLister() const;
/**
* @returns the progress widget, that is shown during directory listing.
* You can for example reparent() it to put it into a statusbar.
*/
QProgressBar* progressBar() const;
/**
* Sets the listing/selection mode for the views, an OR'ed combination of
* @li File
* @li Directory
* @li Files
* @li ExistingOnly
* @li LocalOnly
*
* You cannot mix File and Files of course, as the former means
* single-selection mode, the latter multi-selection.
*/
virtual void setMode(KFile::Modes m);
/**
* @returns the listing/selection mode.
*/
KFile::Modes mode() const;
/**
* Sets a preview-widget to be shown next to the file-view.
* The ownership of @p w is transferred to KDirOperator, so don't
* delete it yourself!
*/
virtual void setPreviewWidget(KPreviewWidgetBase *w);
/**
* @returns a list of all currently selected items. If there is no view,
* or there are no selected items, an empty list is returned.
*/
QList selectedItems() const;
/**
* @returns true if @p item is currently selected, or false otherwise.
*/
- // ### KDE5: change 'const KFileItem *item' to 'const KFileItem& item'
- bool isSelected(const KFileItem *item) const;
+ bool isSelected(const KFileItem &item) const;
/**
* @returns the number of directories in the currently listed url.
* Returns 0 if there is no view.
*/
int numDirs() const;
/**
* @returns the number of files in the currently listed url.
* Returns 0 if there is no view.
*/
int numFiles() const;
/**
* @returns a KCompletion object, containing all filenames and
* directories of the current directory/URL.
* You can use it to insert it into a KLineEdit or KComboBox
* Note: it will only contain files, after prepareCompletionObjects()
* has been called. It will be implicitly called from makeCompletion()
* or makeDirCompletion()
*/
KCompletion* completionObject() const;
/**
* @returns a KCompletion object, containing only all directories of the
* current directory/URL.
* You can use it to insert it into a KLineEdit or KComboBox
* Note: it will only contain directories, after
* prepareCompletionObjects() has been called. It will be implicitly
* called from makeCompletion() or makeDirCompletion()
*/
KCompletion* dirCompletionObject() const;
/**
* an accessor to a collection of all available Actions. The actions
* are static, they will be there all the time (no need to connect to
* the signals KActionCollection::inserted() or removed().
*
* There are the following actions:
*
* @li popupMenu : an ActionMenu presenting a popupmenu with all actions
* @li up : changes to the parent directory
* @li back : goes back to the previous directory
* @li forward : goes forward in the history
* @li home : changes to the user's home directory
* @li reload : reloads the current directory
* @li mkdir : opens a dialog box to create a directory
* @li delete : deletes the selected files/directories
* @li sorting menu : an ActionMenu containing all sort-options
* @li by name : sorts by name
* @li by size : sorts by size
* @li by date : sorts by date
* @li by type : sorts by type
* @li descending : reverses the sort order
* @li view menu : an ActionMenu containing all actions concerning the view
* @li short view : shows a simple fileview
* @li detailed view : shows a detailed fileview (dates, permissions ,...)
* @li show hidden : shows hidden files
* @li preview : shows a preview next to the fileview
* @li properties : shows a KPropertiesDialog for the selected files
*
* The short and detailed view are in an exclusive group. The sort-by
* actions are in an exclusive group as well. Also the "separate dirs",
* "preview" and "single" actions are in an exclusive group.
*
* You can e.g. use
* \code
* actionCollection()->action( "up" )->plug( someToolBar );
* \endcode
* to add a button into a toolbar, which makes the dirOperator change to
* its parent directory.
*
* @returns all available Actions
*/
KActionCollection* actionCollection() const;
/**
* Sets the config object and the to be used group in KDirOperator. This
* will be used to store the view's configuration via
* KFileView::writeConfig() (and for KFileView::readConfig()).
* If you don't set this, the views cannot save and restore their
* configuration.
*
* Usually you call this right after KDirOperator creation so that the view
* instantiation can make use of it already.
*
* Note that KDirOperator does NOT take ownership of that object (typically
* it's KGlobal::config() anyway.
*
* You must not delete the KConfig or KConfigGroup object (and master config object) before
* either deleting the KDirOperator or calling setViewConfig(0); or something like that
*
* @see viewConfig
* @see viewConfigGroup
*/
virtual void setViewConfig(KConfigGroup& configGroup);
/*
* @returns the group set by setViewConfig configuration.
*/
KConfigGroup* viewConfigGroup() const;
/**
* Reads the default settings for a view, i.e. the default KFile::FileView.
* Also reads the sorting and whether hidden files should be shown.
* Note: the default view will not be set - you have to call
* \code
* setView( KFile::Default )
* \endcode
* to apply it.
*
* @see setView
* @see setViewConfig
* @see writeConfig
*/
virtual void readConfig(const KConfigGroup& configGroup);
/**
* Saves the current settings like sorting, simple or detailed view.
*
* @see readConfig
* @see setViewConfig
*/
virtual void writeConfig(KConfigGroup& configGroup);
/**
* This is a KFileDialog specific hack: we want to select directories with
* single click, but not files. But as a generic class, we have to be able
* to select files on single click as well.
*
* This gives us the opportunity to do both.
*
* The default is false, set it to true if you don't want files selected
* with single click.
*/
void setOnlyDoubleClickSelectsFiles(bool enable);
/**
* @returns whether files (not directories) should only be select()ed by
* double-clicks.
* @see setOnlyDoubleClickSelectsFiles
*/
bool onlyDoubleClickSelectsFiles() const;
/**
* Creates the given directory/url. If it is a relative path,
* it will be completed with the current directory.
* If enterDirectory is true, the directory will be entered after a
* successful operation. If unsuccessful, a messagebox will be presented
* to the user.
* @returns true if the directory could be created.
*/
virtual bool mkdir(const QString& directory, bool enterDirectory = true);
/**
* Starts and returns a KIO::DeleteJob to delete the given @p items.
*
* @param items the list of items to be deleted
* @param parent the parent widget used for the confirmation dialog
* @param ask specifies whether a confirmation dialog should be shown
* @param showProgress passed to the DeleteJob to show a progress dialog
*/
virtual KIO::DeleteJob* del(const QList& items, QWidget *parent = 0,
bool ask = true, bool showProgress = true);
/**
* Clears the forward and backward history.
*/
void clearHistory();
/**
* When going up in the directory hierarchy, KDirOperator can highlight
* the directory that was just left.
*
* I.e. when you go from /home/gis/src to /home/gis, the item "src" will
* be made the current item.
*
* Default is off.
*/
virtual void setEnableDirHighlighting(bool enable);
/**
* @returns whether the last directory will be made the current item
* when going up in the directory hierarchy.
*
* Default is false.
*/
bool dirHighlighting() const;
/**
* @returns true if we are in directory-only mode, that is, no files are
* shown.
*/
bool dirOnlyMode() const;
static bool dirOnlyMode(uint mode);
/**
* Sets up the action menu.
* @param whichActions is an value of OR'd ActionTypes that controls which actions to show in the action menu
*/
void setupMenu(int whichActions);
/**
* Reimplemented - allow dropping of files if @p b is true
* @param b true if the widget should allow dropping of files
*/
virtual void setAcceptDrops(bool b);
/**
* Sets the options for dropping files.
* @see KFileView::DropOptions
*/
virtual void setDropOptions(int options);
/**
* Starts and returns a KIO::CopyJob to trash the given @p items.
*
* @param items the list of items to be trashed
* @param parent the parent widget used for the confirmation dialog
* @param ask specifies whether a confirmation dialog should be shown
* @param showProgress passed to the CopyJob to show a progress dialog
*/
virtual KIO::CopyJob* trash(const QList& items, QWidget *parent,
bool ask = true, bool showProgress = true);
protected:
/**
* A view factory for creating predefined fileviews. Called internally by setView,
* but you can also call it directly. Reimplement this if you depend on self defined fileviews.
* @param parent is the QWidget to be set as parent
* @param viewKind is the predefined view to be set, note: this can be several ones OR:ed together
* @returns the created KFileView
* @see KFile::FileView
* @see setView
*/
virtual QAbstractItemView* createView(QWidget *parent, KFile::FileView viewKind);
/**
* Sets a custom KDirLister to list directories.
*/
virtual void setDirLister(KDirLister *lister);
virtual void resizeEvent(QResizeEvent *event);
/**
* Sets up all the actions. Called from the constructor, you usually
* better not call this.
*/
void setupActions();
/**
* Updates the sorting-related actions to comply with the current sorting
* @see sorting
*/
void updateSortActions();
/**
* Updates the view-related actions to comply with the current
* KFile::FileView
*/
void updateViewActions();
/**
* Sets up the context-menu with all the necessary actions. Called from the
* constructor, you usually don't need to call this.
*/
void setupMenu();
/**
* Synchronizes the completion objects with the entries of the
* currently listed url.
*
* Automatically called from makeCompletion() and
* makeDirCompletion()
*/
void prepareCompletionObjects();
/**
* Checks if there support from KIO::PreviewJob for the currently
* shown files, taking mimeFilter() and nameFilter() into account
* Enables/disables the preview-action accordingly.
*/
bool checkPreviewSupport();
/**
* Called upon right-click to activate the popupmenu.
*/
virtual void activatedMenu(const KFileItem &item, const QPoint &pos);
public Q_SLOTS:
/**
* Goes one step back in the history and opens that url.
*/
virtual void back();
/**
* Goes one step forward in the history and opens that url.
*/
virtual void forward();
/**
* Enters the home directory.
*/
virtual void home();
/**
* Goes one directory up from the current url.
*/
virtual void cdUp();
/**
* to update the view after changing the settings
*/
void updateDir();
/**
* Re-reads the current url.
*/
virtual void rereadDir();
/**
* Opens a dialog to create a new directory.
*/
virtual void mkdir();
/**
* Deletes the currently selected files/directories.
*/
virtual void deleteSelected();
/**
* Enables/disables actions that are selection dependent. Call this e.g.
* when you are about to show a popup menu using some of KDirOperators
* actions.
*/
void updateSelectionDependentActions();
/**
* Tries to complete the given string (only completes files).
*/
QString makeCompletion(const QString&);
/**
* Tries to complete the given string (only completes directores).
*/
QString makeDirCompletion(const QString&);
/**
* Trashes the currently selected files/directories.
*
* This function used to take activation reason and keyboard modifiers,
* in order to call deleteSelected() if the user wanted to delete.
* Instead, call deleteSelected().
*
* FIXME KAction Port: link deleteSelected() up correctly
*/
virtual void trashSelected();
protected Q_SLOTS:
/**
* Restores the normal cursor after showing the busy-cursor. Also hides
* the progressbar.
*/
void resetCursor();
/**
* Called after setUrl() to load the directory, update the history,
* etc.
*/
void pathChanged();
/**
* Enters the directory specified by the given @p item.
*/
- virtual void selectDir(const KFileItem *item);
+ virtual void selectDir(const KFileItem &item);
/**
* Emits fileSelected( item )
*/
- void selectFile(const KFileItem *item);
+ void selectFile(const KFileItem &item);
/**
* Emits fileHighlighted(item)
*/
- void highlightFile(const KFileItem *item);
+ void highlightFile(const KFileItem &item);
/**
* Changes sorting to sort by name
*/
void sortByName();
/**
* Changes sorting to sort by size
*/
void sortBySize();
/**
* Changes sorting to sort by date
*/
void sortByDate();
/**
* Changes sorting to sort by date
*/
void sortByType();
/**
* Changes sorting to reverse sorting
*/
void sortReversed();
/**
* Toggles showing directories first / having them sorted like files.
*/
void toggleDirsFirst();
/**
* Toggles case sensitive / case insensitive sorting
*/
void toggleIgnoreCase();
/**
* Tries to make the given @p match as current item in the view and emits
* completion( match )
*/
void slotCompletionMatch(const QString &match);
Q_SIGNALS:
void urlEntered(const KUrl&);
void updateInformation(int files, int dirs);
void completion(const QString&);
void finishedLoading();
/**
* Emitted whenever the current fileview is changed, either by an explicit
* call to setView() or by the user selecting a different view thru
* the GUI.
*/
void viewChanged(QAbstractItemView *newView);
/**
* Emitted when a file is highlighted or generally the selection changes in
* multiselection mode. In the latter case, @p item is 0L. You can access
* the selected items with selectedItems().
*/
- void fileHighlighted(const KFileItem *item);
- void dirActivated(const KFileItem *item);
- void fileSelected(const KFileItem *item);
+ void fileHighlighted(const KFileItem &item);
+ void dirActivated(const KFileItem &item);
+ void fileSelected(const KFileItem &item);
/**
* Emitted when files are dropped. Dropping files is disabled by
* default. You need to enable it with setAcceptDrops()
* @param item the item on which the drop occurred or 0.
* @param event the drop event itself.
* @param urls the urls that where dropped.
*/
- void dropped(const KFileItem *item, QDropEvent *event, const KUrl::List &urls);
+ void dropped(const KFileItem &item, QDropEvent *event, const KUrl::List &urls);
private:
/**
* Checks whether we preview support is available for the current
* mimetype/namefilter
*/
bool checkPreviewInternal() const;
/**
* takes action on the new location. If it's a directory, change
* into it, if it's a file, correct the name, etc.
*/
void checkPath(const QString &txt, bool takeFiles = false);
bool openUrl(const KUrl &url, bool keep = false, bool reload = false);
/**
* Returns the column used by KDirModel dependent from d->sortOrder.
*/
int sortColumn() const;
/**
* Returns the sort order dependent from d->sortOrder.
*/
Qt::SortOrder sortOrder() const;
/**
* Sorts the model depending from d->sorting and emits
* the signal sortingChanged(). It is assured that the
* selected item stays visible.
*/
void triggerSorting();
private Q_SLOTS:
/**
* @internal
*/
void slotDetailedView();
void slotSimpleView();
void slotToggleHidden(bool);
void togglePreview(bool on);
void slotSortByName();
void slotSortBySize();
void slotSortByDate();
void slotSortByType();
void slotSortReversed();
void slotToggleDirsFirst();
void slotToggleIgnoreCase();
void slotStarted();
void slotProgress(int);
void slotShowProgress();
void slotIOFinished();
void slotCanceled();
void slotRedirected(const KUrl&);
void slotViewActionAdded(KAction *);
void slotViewActionRemoved(KAction *);
void slotProperties();
void slotPressed(const QModelIndex &index);
void slotClicked(const QModelIndex &index);
void slotDoubleClicked(const QModelIndex &index);
void openContextMenu(const QPoint &pos);
/**
* Triggers a delayed preview of the item \a index.
* @see KDirOperator::cancelPreview()
* @see KDirOperator::showPreview()
*/
void triggerPreview(const QModelIndex& index);
/**
* Cancels a pending preview (see also KDirOperator::triggerPreview()).
*/
void cancelPreview();
/**
* Tells the preview widget to show the preview for the last
* highlighted/selected URL.
*/
void showPreview();
void slotSplitterMoved(int pos, int index);
/**
* Assures that the selection remains visible for
* the current view. This method should get invoked whenever
* the view or the layout has been changed.
*/
void assureVisibleSelection();
/**
* Synchronizes the sorting actions with the current
* state of the sorting.
*/
void synchronizeSortingState(int logicalIndex, Qt::SortOrder order);
private:
static bool isReadable(const KUrl &url);
private:
class KDirOperatorPrivate;
KDirOperatorPrivate* const d;
};
#endif
diff --git a/kfile/kfiletreebranch.cpp b/kfile/kfiletreebranch.cpp
index 783b89f663..ed51d4124d 100644
--- a/kfile/kfiletreebranch.cpp
+++ b/kfile/kfiletreebranch.cpp
@@ -1,570 +1,570 @@
/* This file is part of the KDEproject
Copyright (C) 2000 David Faure
2000 Carsten Pfeiffer
2002 Klaas Freitag
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kfiletreebranch.h"
#include
#include
#include
#include
#include
#include
#include
/* --- K3FileTreeViewToplevelItem --- */
KFileTreeBranch::KFileTreeBranch( K3FileTreeView *parent, const KUrl& url,
const QString& name,
const QPixmap& pix, bool showHidden,
K3FileTreeViewItem *branchRoot )
: KDirLister(),
m_root( branchRoot ),
m_startURL( url ),
m_name ( name ),
m_rootIcon( pix ),
m_openRootIcon( pix ),
m_recurseChildren(true),
m_showExtensions(true)
{
kDebug( 250) << "Creating branch for url " << url.prettyUrl();
/* if non exists, create one */
if( ! branchRoot )
{
m_root = new K3FileTreeViewItem( parent,
- new KFileItem( url, "inode/directory",
+ KFileItem( url, "inode/directory",
S_IFDIR ),
this );
}
m_root->setExpandable( true );
m_root->setPixmap( 0, pix );
m_root->setText( 0, name );
setShowingDotFiles( showHidden );
- connect( this, SIGNAL( refreshItems(const KFileItemList&)),
- this, SLOT ( slotRefreshItems( const KFileItemList& )));
+ connect( this, SIGNAL( refreshItems(const QList >&)),
+ this, SLOT ( slotRefreshItems( const QList >& )));
connect( this, SIGNAL( newItems(const KFileItemList&)),
this, SLOT ( addItems( const KFileItemList& )));
connect( this, SIGNAL( completed(const KUrl& )),
this, SLOT(slCompleted(const KUrl&)));
connect( this, SIGNAL( started( const KUrl& )),
this, SLOT( slotListerStarted( const KUrl& )));
- connect( this, SIGNAL( deleteItem( KFileItem* )),
- this, SLOT( slotDeleteItem( KFileItem* )));
+ connect( this, SIGNAL( deleteItem( const KFileItem& )),
+ this, SLOT( slotDeleteItem( const KFileItem& )));
connect( this, SIGNAL( canceled(const KUrl&) ),
this, SLOT( slotCanceled(const KUrl&) ));
connect( this, SIGNAL( clear()),
this, SLOT( slotDirlisterClear()));
connect( this, SIGNAL( clear(const KUrl&)),
this, SLOT( slotDirlisterClearUrl(const KUrl&)));
connect( this, SIGNAL( redirection( const KUrl& , const KUrl& ) ),
this, SLOT( slotRedirect( const KUrl&, const KUrl& )));
m_openChildrenURLs.append( url );
}
KUrl KFileTreeBranch::rootUrl() const
{
return( m_startURL );
}
void KFileTreeBranch::setRoot( K3FileTreeViewItem *r )
{
m_root = r;
}
K3FileTreeViewItem *KFileTreeBranch::root( )
{
return( m_root );
}
QString KFileTreeBranch::name() const
{
return( m_name );
}
void KFileTreeBranch::setName( const QString n )
{
m_name = n;
}
QPixmap KFileTreeBranch::pixmap() const
{
return m_rootIcon;
}
QPixmap KFileTreeBranch::openPixmap() const
{
return m_openRootIcon;
}
void KFileTreeBranch::setOpen( bool setopen )
{
if ( root() ) {
root()->setOpen( setopen );
}
}
void KFileTreeBranch::setOpenPixmap( const QPixmap& pix )
{
m_openRootIcon = pix;
if( root()->isOpen())
{
root()->setPixmap( 0, pix );
}
}
void KFileTreeBranch::slotListerStarted( const KUrl &url )
{
/* set the parent correct if it is zero. */
kDebug( 250) << "Starting to list " << url.prettyUrl();
}
-K3FileTreeViewItem* KFileTreeBranch::treeItemForFileItem(KFileItem *it)
+K3FileTreeViewItem* KFileTreeBranch::treeItemForFileItem(const KFileItem &it)
{
return
const_cast(
- static_cast(it->extraData(this)));
+ static_cast(it.extraData(this)));
}
-K3FileTreeViewItem *KFileTreeBranch::parentKFTVItem( KFileItem *item )
+K3FileTreeViewItem *KFileTreeBranch::parentKFTVItem( const KFileItem &item )
{
K3FileTreeViewItem *parent = 0;
- if( ! item ) return 0;
+ if( item.isNull() ) return 0;
/* If it is a directory, check, if it exists in the dict. If not, go one up
* and check again.
*/
- KUrl url = item->url();
+ KUrl url = item.url();
// kDebug(250) << "Item's url is " << url.prettyUrl();
KUrl dirUrl( url );
dirUrl.setFileName( QString() );
// kDebug(250) << "Directory url is " << dirUrl.prettyUrl();
parent = findTVIByUrl( dirUrl );
// kDebug(250) << "Returning as parent item <" << parent << ">";
return( parent );
}
-void KFileTreeBranch::slotRefreshItems( const KFileItemList& list )
+void KFileTreeBranch::slotRefreshItems( const QList > &list )
{
kDebug(250) << "Refreshing " << list.count() << " items !";
- KFileItemList::const_iterator kit = list.begin();
- const KFileItemList::const_iterator kend = list.end();
- for ( ; kit != kend; ++kit )
+ for ( int i = 0; i < list.count(); ++i )
{
- K3FileTreeViewItem *item = findTVIByUrl((*kit)->url());
+ const KFileItem fileItem = list[ i ].second;
+
+ K3FileTreeViewItem *item = findTVIByUrl(fileItem.url());
if (item) {
- item->setPixmap(0, item->fileItem()->pixmap( K3Icon::SizeSmall ));
- item->setText( 0, item->fileItem()->text());
+ item->setPixmap(0, item->fileItem().pixmap( K3Icon::SizeSmall ));
+ item->setText( 0, item->fileItem().text());
}
}
}
void KFileTreeBranch::addItems( const KFileItemList& list )
{
kDebug(250) << "Adding " << list.count() << " items !";
K3FileTreeViewItemList treeViewItList;
K3FileTreeViewItem *parentItem = 0;
KFileItemList::const_iterator kit = list.begin();
const KFileItemList::const_iterator kend = list.end();
for ( ; kit != kend; ++kit )
{
- KFileItem* currItem = *kit;
+ KFileItem currItem = *kit;
parentItem = parentKFTVItem( currItem );
/* Only create a new K3FileTreeViewItem if it does not yet exist */
K3FileTreeViewItem *newKFTVI = treeItemForFileItem(currItem);
if( ! newKFTVI )
{
newKFTVI = createTreeViewItem( parentItem, currItem );
if (!newKFTVI)
{
// TODO: Don't fail if parentItem == 0
continue;
}
- currItem->setExtraData( this, newKFTVI );
+ currItem.setExtraData( this, newKFTVI );
/* Cut off the file extension in case it is not a directory */
- if( !m_showExtensions && !currItem->isDir() ) /* Need to cut the extension */
+ if( !m_showExtensions && !currItem.isDir() ) /* Need to cut the extension */
{
- QString name = currItem->text();
+ QString name = currItem.text();
int mPoint = name.lastIndexOf( '.' );
if( mPoint > 0 )
name = name.left( mPoint );
newKFTVI->setText( 0, name );
}
}
/* Now try to find out if there are children for dirs in the treeview */
/* This stats a directory on the local file system and checks the */
/* hardlink entry in the stat-buf. This works only for local directories. */
- if( dirOnlyMode() && !m_recurseChildren && currItem->isLocalFile( ) && currItem->isDir() )
+ if( dirOnlyMode() && !m_recurseChildren && currItem.isLocalFile( ) && currItem.isDir() )
{
- KUrl url = currItem->url();
+ KUrl url = currItem.url();
QString filename = url.directory( KUrl::ObeyTrailingSlash ) + url.fileName();
/* do the stat trick of Carsten. The problem is, that the hardlink
* count only contains directory links. Thus, this method only seem
* to work in dir-only mode */
kDebug(250) << "Doing stat on " << filename;
KDE_struct_stat statBuf;
if( KDE_stat( QFile::encodeName( filename ), &statBuf ) == 0 )
{
int hardLinks = statBuf.st_nlink; /* Count of dirs */
kDebug(250) << "stat succeeded, hardlinks: " << hardLinks;
// If the link count is > 2, the directory likely has subdirs. If it's < 2
// it's something weird like a mounted SMB share. In that case we don't know
// if there are subdirs, thus show it as expandable.
if( hardLinks != 2 )
{
newKFTVI->setExpandable(true);
}
else
{
newKFTVI->setExpandable(false);
}
if( hardLinks >= 2 ) // "Normal" directory with subdirs
{
kDebug(250) << "Emitting for " << url.prettyUrl();
emit( directoryChildCount( newKFTVI, hardLinks-2)); // parentItem, hardLinks-1 ));
}
}
else
{
kDebug(250) << "stat of " << filename << " failed !";
}
}
treeViewItList.append( newKFTVI );
}
emit newTreeViewItems( this, treeViewItList );
}
K3FileTreeViewItem* KFileTreeBranch::createTreeViewItem( K3FileTreeViewItem *parent,
- KFileItem *fileItem )
+ const KFileItem &fileItem )
{
K3FileTreeViewItem *tvi = 0;
- if( parent && fileItem )
+ if( parent && !fileItem.isNull() )
{
tvi = new K3FileTreeViewItem( parent,
fileItem,
this );
}
else
{
kDebug(250) << "createTreeViewItem: Have no parent";
}
return( tvi );
}
void KFileTreeBranch::setChildRecurse( bool t )
{
m_recurseChildren = t;
if( t == false )
m_openChildrenURLs.clear();
}
bool KFileTreeBranch::childRecurse()
{
return m_recurseChildren;
}
void KFileTreeBranch::setShowExtensions( bool visible )
{
m_showExtensions = visible;
}
bool KFileTreeBranch::showExtensions( ) const
{
return( m_showExtensions );
}
/*
* The signal that tells that a directory was deleted may arrive before the signal
* for its children arrive. Thus, we must walk through the children of a dir and
* remove them before removing the dir itself.
*/
-void KFileTreeBranch::slotDeleteItem( KFileItem *it )
+void KFileTreeBranch::slotDeleteItem( const KFileItem &it )
{
- if( !it ) return;
- kDebug(250) << "Slot Delete Item hitted for " << it->url().prettyUrl();
+ if( it.isNull() ) return;
+ kDebug(250) << "Slot Delete Item hitted for " << it.url().prettyUrl();
K3FileTreeViewItem *kfti = treeItemForFileItem(it);
if( kfti )
{
kDebug( 250 ) << "Child count: " << kfti->childCount();
if( kfti->childCount() > 0 )
{
K3FileTreeViewItem *child = static_cast(kfti->firstChild());
while( child )
{
kDebug(250) << "Calling child to be deleted !";
K3FileTreeViewItem *nextChild = static_cast(child->nextSibling());
slotDeleteItem( child->fileItem());
child = nextChild;
}
}
kDebug(250) << "Found corresponding K3FileTreeViewItem";
- if( m_lastFoundURL.equals(it->url(), KUrl::CompareWithoutTrailingSlash ))
+ if( m_lastFoundURL.equals(it.url(), KUrl::CompareWithoutTrailingSlash ))
{
m_lastFoundURL = KUrl();
m_lastFoundItem = 0L;
}
delete( kfti );
}
else
{
kDebug(250) << "Error: kfiletreeviewitem: "<< kfti;
}
}
void KFileTreeBranch::slotCanceled( const KUrl& url )
{
// ### anything else to do?
// remove the url from the childrento-recurse-list
m_openChildrenURLs.removeAll( url);
// stop animations etc.
K3FileTreeViewItem *item = findTVIByUrl(url);
if (!item) return; // Uh oh...
emit populateFinished(item);
}
void KFileTreeBranch::slotDirlisterClear()
{
kDebug(250)<< "*** Clear all !";
/* this slots needs to clear all listed items, but NOT the root item */
if( m_root )
deleteChildrenOf( m_root );
}
void KFileTreeBranch::slotDirlisterClearUrl( const KUrl& url )
{
kDebug(250)<< "*** Clear for URL !" << url.prettyUrl();
- KFileItem *item = findByUrl( url );
- if( item )
+ const KFileItem item = findByUrl( url );
+ if( !item.isNull() )
{
K3FileTreeViewItem *ftvi = treeItemForFileItem(item);
deleteChildrenOf( ftvi );
}
}
void KFileTreeBranch::deleteChildrenOf( Q3ListViewItem *parent )
{
// for some strange reason, slotDirlisterClearURL() sometimes calls us
// with a 0L parent.
if ( !parent )
return;
while ( parent->firstChild() )
delete parent->firstChild();
}
void KFileTreeBranch::slotRedirect( const KUrl& oldUrl, const KUrl&newUrl )
{
if( oldUrl.equals( m_startURL, KUrl::CompareWithoutTrailingSlash ))
{
m_startURL = newUrl;
}
}
K3FileTreeViewItem* KFileTreeBranch::findTVIByUrl( const KUrl& url )
{
K3FileTreeViewItem *resultItem = 0;
if( m_startURL.equals(url, KUrl::CompareWithoutTrailingSlash) )
{
kDebug(250) << "findByURL: Returning root as a parent !";
resultItem = m_root;
}
else if( m_lastFoundURL.equals( url, KUrl::CompareWithoutTrailingSlash ))
{
kDebug(250) << "findByURL: Returning from lastFoundURL!";
resultItem = m_lastFoundItem;
}
else
{
kDebug(250) << "findByURL: searching by dirlister: " << url.url();
- KFileItem *it = findByUrl( url );
+ const KFileItem it = findByUrl( url );
- if( it )
+ if( !it.isNull() )
{
resultItem = treeItemForFileItem(it);
m_lastFoundItem = resultItem;
m_lastFoundURL = url;
}
}
return( resultItem );
}
void KFileTreeBranch::slCompleted( const KUrl& url )
{
kDebug(250) << "SlotCompleted hit for " << url.prettyUrl();
K3FileTreeViewItem *currParent = findTVIByUrl( url );
if( ! currParent ) return;
kDebug(250) << "current parent " << currParent << " is already listed: "
<< currParent->alreadyListed() << endl;
emit( populateFinished(currParent));
emit( directoryChildCount(currParent, currParent->childCount()));
/* This is a walk through the children of the last populated directory.
* Here we start the dirlister on every child of the dir and wait for its
* finish. When it has finished, we go to the next child.
* This must be done for non local file systems in dirOnly- and Full-Mode
* and for local file systems only in full mode, because the stat trick
* (see addItem-Method) does only work for dirs, not for files in the directory.
*/
/* Set bit that the parent dir was listed completely */
currParent->setListed(true);
kDebug(250) << "recurseChildren: " << m_recurseChildren;
kDebug(250) << "isLocalFile: " << m_startURL.isLocalFile();
kDebug(250) << "dirOnlyMode: " << dirOnlyMode();
if( m_recurseChildren && (!m_startURL.isLocalFile() || ! dirOnlyMode()) )
{
bool wantRecurseUrl = false;
/* look if the url is in the list for url to recurse */
for ( KUrl::List::Iterator it = m_openChildrenURLs.begin();
it != m_openChildrenURLs.end(); ++it )
{
/* it is only interesting that the url _is_in_ the list. */
if( (*it).equals( url, KUrl::CompareWithoutTrailingSlash ) )
wantRecurseUrl = true;
}
K3FileTreeViewItem *nextChild = 0;
kDebug(250) << "Recursing " << url.prettyUrl() << "? " << wantRecurseUrl;
if( wantRecurseUrl && currParent )
{
/* now walk again through the tree and populate the children to get +-signs */
/* This is the starting point. The visible folder has finished,
processing the children has not yet started */
nextChild = static_cast
(static_cast(currParent)->firstChild());
if( ! nextChild )
{
/* This happens if there is no child at all */
kDebug( 250 ) << "No children to recuse";
}
/* Since we have listed the children to recurse, we can remove the entry
* in the list of the URLs to see the children.
*/
m_openChildrenURLs.removeAll(url);
}
if( nextChild ) /* This implies that idx > -1 */
{
/* Next child is defined. We start a dirlister job on every child item
* which is a directory to find out how much children are in the child
* of the last opened dir
*/
/* Skip non directory entries */
while( nextChild )
{
if( nextChild->isDir() && ! nextChild->alreadyListed())
{
- KFileItem *kfi = nextChild->fileItem();
- if( kfi && kfi->isReadable())
+ const KFileItem kfi = nextChild->fileItem();
+ if( !kfi.isNull() && kfi.isReadable())
{
- KUrl recurseUrl = kfi->url();
+ KUrl recurseUrl = kfi.url();
kDebug(250) << "Starting to recurse NOW " << recurseUrl.prettyUrl();
openUrl( recurseUrl, true );
}
}
nextChild = static_cast(nextChild->nextSibling());
// kDebug(250) << "Next child " << m_nextChild;
}
}
}
else
{
kDebug(250) << "skipping to recurse in complete-slot";
}
}
/* This slot is called when a treeviewitem is expanded in the gui */
bool KFileTreeBranch::populate( const KUrl& url, K3FileTreeViewItem *currItem )
{
bool ret = false;
if( ! currItem )
return ret;
kDebug(250) << "Populating <" << url.prettyUrl() << ">";
/* Add this url to the list of urls to recurse for children */
if( m_recurseChildren )
{
m_openChildrenURLs.append( url );
kDebug(250) << "Appending to list " << url.prettyUrl();
}
if( ! currItem->alreadyListed() )
{
/* start the lister */
ret = openUrl( url, true );
}
else
{
kDebug(250) << "Children already existing in treeview!";
slCompleted( url );
ret = true;
}
return ret;
}
#include "kfiletreebranch.moc"
diff --git a/kfile/kfiletreebranch.h b/kfile/kfiletreebranch.h
index b47355f90c..66b9b0b4c8 100644
--- a/kfile/kfiletreebranch.h
+++ b/kfile/kfiletreebranch.h
@@ -1,240 +1,240 @@
/* This file is part of the KDE project
Copyright (C) 2000 David Faure
2000 Carsten Pfeiffer
2001 Klaas Freitag
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef kfile_tree_branch_h
#define kfile_tree_branch_h
class QColorGroup;
#include
#include
#include
#include
#include
#include
class KUrl;
class K3FileTreeView;
/**
* This is the branch class of the K3FileTreeView, which represents one
* branch in the treeview. Every branch has a root which is an url. The branch
* lists the files under the root. Every branch uses its own dirlister and can
* have its own filter etc.
*
* @short Branch object for K3FileTreeView object.
*
*/
class KFILE_EXPORT KFileTreeBranch : public KDirLister
{
Q_OBJECT
public:
/**
* constructs a branch for K3FileTreeView. Does not yet start to list it.
* @param url start url of the branch.
* @param name the name of the branch, which is displayed in the first column of the treeview.
* @param pix is a pixmap to display as an icon of the branch.
* @param showHidden flag to make hidden files visible or not.
* @param branchRoot is the K3FileTreeViewItem to use as the root of the
* branch, with the default 0 meaning to let KFileTreeBranch create
* it for you.
*/
KFileTreeBranch( K3FileTreeView*, const KUrl& url, const QString& name,
const QPixmap& pix, bool showHidden = false,
K3FileTreeViewItem *branchRoot = 0 );
/**
* @returns the root url of the branch.
*/
KUrl rootUrl() const;
/**
* sets a K3FileTreeViewItem as root widget for the branch.
* That must be created outside of the branch. All KFileTreeViewItems
* the branch is allocating will become children of that object.
* @param r the K3FileTreeViewItem to become the root item.
*/
virtual void setRoot( K3FileTreeViewItem *r );
/**
* @returns the root item.
*/
K3FileTreeViewItem *root( );
/**
* @returns the name of the branch.
*/
QString name() const;
/**
* sets the name of the branch.
*/
virtual void setName( const QString n );
/*
* returns the current root item pixmap set in the constructor. The root
* item pixmap defaults to the icon for directories.
* @see openPixmap()
*/
QPixmap pixmap() const;
/*
* returns the current root item pixmap set by setOpenPixmap()
* which is displayed if the branch is expanded.
* The root item pixmap defaults to the icon for directories.
* @see pixmap()
* Note that it depends on K3FileTreeView::showFolderOpenPximap weather
* open pixmap are displayed or not.
*/
QPixmap openPixmap() const;
/**
* @returns whether the items in the branch show their file extensions in the
* tree or not. See setShowExtensions for more information.
*/
bool showExtensions( ) const;
/**
* sets the root of the branch open or closed.
*/
void setOpen( bool setopen = true );
/**
* sets if children recursion is wanted or not. If this is switched off, the
* child directories of a just opened directory are not listed internally.
* That means that it can not be determined if the sub directories are
* expandable or not. If this is switched off there will be no call to
* setExpandable.
* @param t set to true to switch on child recursion
*/
void setChildRecurse( bool t=true );
/**
* @returns if child recursion is on or off.
* @see setChildRecurse
*/
bool childRecurse();
public Q_SLOTS:
/**
* populates a branch. This method must be called after a branch was added
* to a K3FileTreeView using method addBranch.
* @param url is the url of the root item where the branch starts.
* @param currItem is the current parent.
*/
virtual bool populate( const KUrl &url, K3FileTreeViewItem* currItem );
/**
* sets printing of the file extensions on or off. If you pass false to this
* slot, all items of this branch will not show their file extensions in the
* tree.
* @param visible flags if the extensions should be visible or not.
*/
virtual void setShowExtensions( bool visible = true );
void setOpenPixmap( const QPixmap& pix );
protected:
/**
* allocates a K3FileTreeViewItem for the branch
* for new items.
*/
virtual K3FileTreeViewItem *createTreeViewItem( K3FileTreeViewItem *parent,
- KFileItem *fileItem );
+ const KFileItem &fileItem );
public:
/**
* find the according K3FileTreeViewItem by an url
*/
virtual K3FileTreeViewItem *findTVIByUrl( const KUrl& );
Q_SIGNALS:
/**
* emitted with the item of a directory which was finished to populate
*/
void populateFinished( K3FileTreeViewItem * );
/**
* emitted with a list of new or updated K3FileTreeViewItem which were
* found in a branch. Note that this signal is emitted very often and may slow
* down the performance of the treeview !
*/
void newTreeViewItems( KFileTreeBranch*, const K3FileTreeViewItemList& );
/**
* emitted with the exact count of children for a directory.
*/
void directoryChildCount( K3FileTreeViewItem* item, int count );
private Q_SLOTS:
- void slotRefreshItems( const KFileItemList& );
+ void slotRefreshItems( const QList >& );
void addItems( const KFileItemList& );
void slCompleted( const KUrl& );
void slotCanceled( const KUrl& );
void slotListerStarted( const KUrl& );
- void slotDeleteItem( KFileItem* );
+ void slotDeleteItem( const KFileItem& );
void slotDirlisterClear();
void slotDirlisterClearUrl( const KUrl& url );
void slotRedirect( const KUrl& oldUrl, const KUrl&newUrl );
private:
- K3FileTreeViewItem *parentKFTVItem( KFileItem *item );
+ K3FileTreeViewItem *parentKFTVItem( const KFileItem &item );
static void deleteChildrenOf( Q3ListViewItem *parent );
- K3FileTreeViewItem* treeItemForFileItem(KFileItem *it);
+ K3FileTreeViewItem* treeItemForFileItem(const KFileItem &it);
K3FileTreeViewItem *m_root;
KUrl m_startURL;
QString m_name;
QPixmap m_rootIcon;
QPixmap m_openRootIcon;
/* this list holds the url's which children are opened. */
KUrl::List m_openChildrenURLs;
/* The next two members are used for caching purposes in findTVIByURL. */
KUrl m_lastFoundURL;
K3FileTreeViewItem *m_lastFoundItem;
bool m_recurseChildren :1;
bool m_showExtensions :1;
private:
class KFileTreeBranchPrivate;
KFileTreeBranchPrivate *d;
};
/**
* List of KFileTreeBranches
*/
typedef Q3PtrList KFileTreeBranchList;
/**
* Iterator for KFileTreeBranchLists
*/
typedef Q3PtrListIterator KFileTreeBranchIterator;
#endif
diff --git a/kfile/kfileview.cpp b/kfile/kfileview.cpp
index 4d45e02a70..3405ef7818 100644
--- a/kfile/kfileview.cpp
+++ b/kfile/kfileview.cpp
@@ -1,464 +1,448 @@
/* This file is part of the KDE libraries
Copyright (C) 1998 Stephan Kulow
1998 Daniel Grana
2001 Carsten Pfeiffer
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kfileview.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef Unsorted // the "I hate X.h" modus
#undef Unsorted
#endif
QDir::SortFlags KFileView::defaultSortFlags = (QDir::Name | QDir::IgnoreCase | QDir::DirsFirst);
class KFileView::KFileViewPrivate
{
public:
KFileViewPrivate()
{
actions = 0;
dropOptions = 0;
}
~KFileViewPrivate()
{
if( actions ) {
actions->clear(); // so that the removed() signal is emitted!
delete actions;
}
}
QPointer actions;
int dropOptions;
};
KFileView::KFileView()
:d(new KFileViewPrivate())
{
m_sorting = KFileView::defaultSortFlags;
sig = new KFileViewSignaler();
sig->setObjectName("view-signaller");
- m_selectedList = 0L;
filesNumber = 0;
dirsNumber = 0;
view_mode = All;
selection_mode = KFile::Single;
m_viewName = i18n("Unknown View");
myOnlyDoubleClickSelectsFiles = false;
}
KFileView::~KFileView()
{
delete d;
delete sig;
- delete m_selectedList;
}
void KFileView::setParentView(KFileView *parent)
{
if ( parent ) { // pass all signals right to our parent
- QObject::connect(sig, SIGNAL( activatedMenu(const KFileItem *,
+ QObject::connect(sig, SIGNAL( activatedMenu(const KFileItem &,
const QPoint& ) ),
- parent->sig, SIGNAL( activatedMenu(const KFileItem *,
+ parent->sig, SIGNAL( activatedMenu(const KFileItem &,
const QPoint& )));
- QObject::connect(sig, SIGNAL( dirActivated(const KFileItem *)),
- parent->sig, SIGNAL( dirActivated(const KFileItem*)));
- QObject::connect(sig, SIGNAL( fileSelected(const KFileItem *)),
- parent->sig, SIGNAL( fileSelected(const KFileItem*)));
- QObject::connect(sig, SIGNAL( fileHighlighted(const KFileItem *) ),
- parent->sig,SIGNAL(fileHighlighted(const KFileItem*)));
+ QObject::connect(sig, SIGNAL( dirActivated(const KFileItem &)),
+ parent->sig, SIGNAL( dirActivated(const KFileItem&)));
+ QObject::connect(sig, SIGNAL( fileSelected(const KFileItem &)),
+ parent->sig, SIGNAL( fileSelected(const KFileItem&)));
+ QObject::connect(sig, SIGNAL( fileHighlighted(const KFileItem &) ),
+ parent->sig,SIGNAL(fileHighlighted(const KFileItem&)));
QObject::connect(sig, SIGNAL( sortingChanged( QDir::SortFlags ) ),
parent->sig, SIGNAL(sortingChanged( QDir::SortFlags)));
- QObject::connect(sig, SIGNAL( dropped(const KFileItem *, QDropEvent*, const KUrl::List&) ),
- parent->sig, SIGNAL(dropped(const KFileItem *, QDropEvent*, const KUrl::List&)));
+ QObject::connect(sig, SIGNAL( dropped(const KFileItem &, QDropEvent*, const KUrl::List&) ),
+ parent->sig, SIGNAL(dropped(const KFileItem &, QDropEvent*, const KUrl::List&)));
}
}
-bool KFileView::updateNumbers(const KFileItem *i)
+bool KFileView::updateNumbers(const KFileItem &i)
{
- if (!( viewMode() & Files ) && i->isFile())
+ if (!( viewMode() & Files ) && i.isFile())
return false;
- if (!( viewMode() & Directories ) && i->isDir())
+ if (!( viewMode() & Directories ) && i.isDir())
return false;
- if (i->isDir())
+ if (i.isDir())
dirsNumber++;
else
filesNumber++;
return true;
}
// filter out files if we're in directory mode and count files/directories
// and insert into the view
void KFileView::addItemList(const KFileItemList& list)
{
KFileItemList::const_iterator kit = list.begin();
const KFileItemList::const_iterator kend = list.end();
for ( ; kit != kend; ++kit ) {
- KFileItem *item = *kit;
+ const KFileItem item = *kit;
if (!updateNumbers(item))
continue;
insertItem(item);
}
}
-void KFileView::insertItem( KFileItem * )
+void KFileView::insertItem( const KFileItem& )
{
}
QDir::SortFlags KFileView::sorting() const
{
return m_sorting;
}
void KFileView::setSorting(QDir::SortFlags new_sort)
{
m_sorting = new_sort;
}
void KFileView::clear()
{
- m_itemList.clear();
filesNumber = 0;
dirsNumber = 0;
clearView();
}
bool KFileView::isReversed() const
{
return (m_sorting & QDir::Reversed);
}
void KFileView::sortReversed()
{
int spec = sorting();
setSorting( QDir::SortFlags( spec ^ QDir::Reversed ) );
}
uint KFileView::count() const
{
return filesNumber + dirsNumber;
}
uint KFileView::numFiles() const
{
return filesNumber;
}
uint KFileView::numDirs() const
{
return dirsNumber;
}
#if 0
int KFileView::compareItems(const KFileItem *fi1, const KFileItem *fi2) const
{
static const QString &dirup = KGlobal::staticQString("..");
bool bigger = true;
bool keepFirst = false;
bool dirsFirst = ((m_sorting & QDir::DirsFirst) == QDir::DirsFirst);
if (fi1 == fi2)
return 0;
// .. is always bigger, independent of the sort criteria
if ( fi1->name() == dirup ) {
bigger = false;
keepFirst = dirsFirst;
}
else if ( fi2->name() == dirup ) {
bigger = true;
keepFirst = dirsFirst;
}
else {
if ( fi1->isDir() != fi2->isDir() && dirsFirst ) {
bigger = fi2->isDir();
keepFirst = true;
}
else {
QDir::SortFlags sort = static_cast(m_sorting & QDir::SortByMask);
//if (fi1->isDir() || fi2->isDir())
// sort = static_cast(KFileView::defaultSortSpec & QDir::SortByMask);
switch (sort) {
case QDir::Name:
default:
sort_by_name:
if ( (m_sorting & QDir::IgnoreCase) == QDir::IgnoreCase )
bigger = (fi1->name( true ) > fi2->name( true ));
else
bigger = (fi1->name() > fi2->name());
break;
case QDir::Time:
{
time_t t1 = fi1->time( KIO::UDSEntry::UDS_MODIFICATION_TIME );
time_t t2 = fi2->time( KIO::UDSEntry::UDS_MODIFICATION_TIME );
if ( t1 != t2 ) {
bigger = (t1 > t2);
break;
}
// Sort by name if both items have the same timestamp.
// Don't honor the reverse flag tho.
else {
keepFirst = true;
goto sort_by_name;
}
}
case QDir::Size:
{
KIO::filesize_t s1 = fi1->size();
KIO::filesize_t s2 = fi2->size();
if ( s1 != s2 ) {
bigger = (s1 > s2);
break;
}
// Sort by name if both items have the same size.
// Don't honor the reverse flag tho.
else {
keepFirst = true;
goto sort_by_name;
}
}
case QDir::Unsorted:
bigger = true; // nothing
break;
}
}
}
if (reversed && !keepFirst ) // don't reverse dirs to the end!
bigger = !bigger;
return (bigger ? 1 : -1);
}
#endif
void KFileView::updateView(bool)
{
widget()->repaint();
}
-void KFileView::updateView(const KFileItem *)
+void KFileView::updateView(const KFileItem &)
{
}
void KFileView::setCurrentItem(const QString &filename )
{
if (!filename.isNull()) {
- KFileItem *item;
- for ( (item = firstFileItem()); item; item = nextItem( item ) ) {
- if (item->name() == filename) {
+ KFileItem item;
+ for ( (item = firstFileItem()); !item.isNull(); item = nextItem( item ) ) {
+ if (item.name() == filename) {
setCurrentItem( item );
return;
}
}
}
kDebug(kfile_area) << "setCurrentItem: no match found: " << filename;
}
-// KDE4 TODO: remove pointer, return by value
-// KDE4 TODO: remove m_itemList
-const KFileItemList * KFileView::items() const
+KFileItemList KFileView::items() const
{
- KFileItem *item = 0L;
+ KFileItemList list;
- // only ever use m_itemList in this method!
- m_itemList.clear();
- for ( (item = firstFileItem()); item; item = nextItem( item ) )
- m_itemList.append( item );
+ for ( KFileItem item = firstFileItem(); !item.isNull(); item = nextItem( item ) )
+ list.append( item );
- return &m_itemList;
+ return list;
}
void KFileView::setOnlyDoubleClickSelectsFiles( bool enable ) {
myOnlyDoubleClickSelectsFiles = enable;
}
bool KFileView::onlyDoubleClickSelectsFiles() const {
return myOnlyDoubleClickSelectsFiles;
}
-const KFileItemList * KFileView::selectedItems() const
+KFileItemList KFileView::selectedItems() const
{
- if ( !m_selectedList )
- m_selectedList = new KFileItemList;
+ KFileItemList list;
- m_selectedList->clear();
-
- KFileItem *item;
- for ( (item = firstFileItem()); item; item = nextItem( item ) ) {
+ for ( KFileItem item = firstFileItem(); !item.isNull(); item = nextItem( item ) ) {
if ( isSelected( item ) )
- m_selectedList->append( item );
+ list.append( item );
}
- return m_selectedList;
+ return list;
}
void KFileView::selectAll()
{
if (selection_mode == KFile::NoSelection || selection_mode== KFile::Single)
return;
- KFileItem *item = 0L;
- for ( (item = firstFileItem()); item; item = nextItem( item ) )
+ for ( KFileItem item = firstFileItem(); !item.isNull(); item = nextItem( item ) )
setSelected( item, true );
}
void KFileView::invertSelection()
{
- KFileItem *item = 0L;
- for ( (item = firstFileItem()); item; item = nextItem( item ) )
+ for ( KFileItem item = firstFileItem(); !item.isNull(); item = nextItem( item ) )
setSelected( item, !isSelected( item ) );
}
void KFileView::setSelectionMode( KFile::SelectionMode sm )
{
selection_mode = sm;
}
KFile::SelectionMode KFileView::selectionMode() const
{
return selection_mode;
}
void KFileView::setViewMode( KFileView::ViewMode vm )
{
view_mode = vm;
}
KFileView::ViewMode KFileView::viewMode() const
{
return view_mode;
}
QString KFileView::viewName() const
{
return m_viewName;
}
void KFileView::setViewName( const QString& name )
{
m_viewName = name;
}
-void KFileView::removeItem( const KFileItem *item )
+void KFileView::removeItem( const KFileItem &item )
{
- if ( !item )
- return;
+ if ( item.isNull() )
+ return;
- if ( item->isDir() )
+ if ( item.isDir() )
dirsNumber--;
else
filesNumber--;
-
- if ( m_selectedList )
- m_selectedList->removeAll( const_cast( item ) );
}
void KFileView::listingCompleted()
{
// empty default impl.
}
KActionCollection * KFileView::actionCollection() const
{
if ( !d->actions ) {
d->actions = new KActionCollection( widget() );
d->actions->setObjectName( "KFileView::d->actions" );
}
return d->actions;
}
KFileViewSignaler * KFileView::signaler() const
{
return sig;
}
void KFileView::readConfig( KConfigGroup *)
{
}
void KFileView::writeConfig( KConfigGroup *)
{
}
QString KFileView::sortingKey( const QString& value, bool isDir, QDir::SortFlags SortFlags )
{
bool reverse = SortFlags & QDir::Reversed;
bool dirsFirst = SortFlags & QDir::DirsFirst;
char start = (isDir && dirsFirst) ? (reverse ? '2' : '0') : '1';
QString result = (SortFlags & QDir::IgnoreCase) ? value.toLower() : value;
return result.prepend( QLatin1Char(start) );
}
QString KFileView::sortingKey( KIO::filesize_t value, bool isDir, QDir::SortFlags SortFlags)
{
bool reverse = SortFlags & QDir::Reversed;
bool dirsFirst = SortFlags & QDir::DirsFirst;
char start = (isDir && dirsFirst) ? (reverse ? '2' : '0') : '1';
return KIO::number( value ).rightJustified( 24, '0' ).prepend( QLatin1Char(start) );
}
void KFileView::setDropOptions(int options)
{
d->dropOptions = options;
}
int KFileView::dropOptions()
{
return d->dropOptions;
}
int KFileView::autoOpenDelay()
{
return (QApplication::startDragTime() * 3) / 2;
}
#include "kfileview.moc"
diff --git a/kfile/kfileview.h b/kfile/kfileview.h
index 0368eee7fb..0ad31885ac 100644
--- a/kfile/kfileview.h
+++ b/kfile/kfileview.h
@@ -1,432 +1,427 @@
// -*- c++ -*-
/* This file is part of the KDE libraries
Copyright (C) 1997 Stephan Kulow
Copyright (C) 2001 Carsten Pfeiffer
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KFILEVIEW_H
#define KFILEVIEW_H
class QPoint;
class QWidget;
class QDropEvent;
class KActionCollection;
#include "kfile_export.h"
#include "kfileitem.h"
#include "kfile.h"
/**
* internal class to make easier to use signals possible
* @internal
**/
class KFILE_EXPORT KFileViewSignaler : public QObject
{
Q_OBJECT
public:
/**
* Call this method when an item is selected (depends on single click /
* double click configuration). Emits the appropriate signal.
**/
- void activate( const KFileItem *item ) {
- if ( item->isDir() )
+ void activate( const KFileItem &item ) {
+ if ( item.isDir() )
dirActivated( item );
else
fileSelected( item );
}
/**
* emits the highlighted signal for item. Call this in your view class
* whenever the selection changes.
*/
- void highlightFile(const KFileItem *i) { fileHighlighted(i); }
+ void highlightFile(const KFileItem &i) { fileHighlighted(i); }
- void activateMenu( const KFileItem *i, const QPoint& pos ) {
+ void activateMenu( const KFileItem &i, const QPoint& pos ) {
activatedMenu( i, pos );
}
void changeSorting( QDir::SortFlags sorting ) {
sortingChanged( sorting );
}
- void dropURLs(const KFileItem *i, QDropEvent*e, const KUrl::List&urls) {
+ void dropURLs(const KFileItem &i, QDropEvent*e, const KUrl::List&urls) {
dropped(i, e, urls);
}
Q_SIGNALS:
- void dirActivated(const KFileItem*);
+ void dirActivated(const KFileItem&);
void sortingChanged( QDir::SortFlags );
/**
* the item maybe be 0L, indicating that we're in multiselection mode and
* the selection has changed.
*/
- void fileHighlighted(const KFileItem*);
- void fileSelected(const KFileItem*);
- void activatedMenu( const KFileItem *i, const QPoint& );
- void dropped(const KFileItem *, QDropEvent*, const KUrl::List&);
+ void fileHighlighted(const KFileItem&);
+ void fileSelected(const KFileItem&);
+ void activatedMenu( const KFileItem &i, const QPoint& );
+ void dropped(const KFileItem &, QDropEvent*, const KUrl::List&);
};
/**
* This class defines an interface to all file views. Its intent is
* to allow to switch the view of the files in the selector very easily.
* It defines some pure virtual functions, that must be implemented to
* make a file view working.
*
* Since this class is not a widget, but it's meant to be added to other
* widgets, its most important function is widget. This should return
* a pointer to the implemented widget.
*
* @short A base class for views of the KDE file selector
* @author Stephan Kulow
**/
class KFILE_EXPORT KFileView {
public:
KFileView();
/**
* Destructor
*/
virtual ~KFileView();
/**
* inserts a list of items.
**/
void addItemList(const KFileItemList &list);
/**
* a pure virtual function to get a QWidget, that can be added to
* other widgets. This function is needed to make it possible for
* derived classes to derive from other widgets.
**/
virtual QWidget *widget() = 0;
/**
* ### As const-method, to be fixed in 3.0
*/
QWidget *widget() const { return const_cast(this)->widget(); }
/**
* Sets @p filename the current item in the view, if available.
*/
void setCurrentItem( const QString &filename );
/**
* Reimplement this to set @p item the current item in the view, e.g.
* the item having focus.
*/
- virtual void setCurrentItem( const KFileItem *item ) = 0;
+ virtual void setCurrentItem( const KFileItem &item ) = 0;
/**
* @returns the "current" KFileItem, e.g. where the cursor is.
- * Returns 0L when there is no current item (e.g. in an empty view).
+ * Returns an null file item when there is no current item (e.g. in an empty view).
* Subclasses have to implement this.
*/
- virtual KFileItem *currentFileItem() const = 0;
+ virtual KFileItem currentFileItem() const = 0;
/**
* Clears the view and all item lists.
*/
virtual void clear();
/**
* does a repaint of the view.
*
* The default implementation calls
* \code
* widget()->repaint(f)
* \endcode
**/
virtual void updateView(bool f = true);
- virtual void updateView(const KFileItem*);
+ virtual void updateView(const KFileItem&);
/**
* Removes an item from the list; has to be implemented by the view.
* Call KFileView::removeItem( item ) after removing it.
*/
- virtual void removeItem(const KFileItem *item);
+ virtual void removeItem(const KFileItem &item);
/**
* This hook is called when all items of the currently listed directory
* are listed and inserted into the view, i.e. there won't come any new
* items anymore.
*/
virtual void listingCompleted();
/**
* Returns the sorting order of the internal list. Newly added files
* are added through this sorting.
*/
QDir::SortFlags sorting() const;
/**
* Sets the sorting order of the view.
*
* Default is QDir::Name | QDir::IgnoreCase | QDir::DirsFirst
* Override this in your subclass and sort accordingly (usually by
* setting the sorting-key for every item and telling QIconView
* or QListView to sort.
*
* A view may choose to use a different sorting than QDir::Name, Time
* or Size. E.g. to sort by mimetype or any possible string. Set the
* sorting to QDir::Unsorted for that and do the rest internally.
*
* @see sortingKey
*/
virtual void setSorting(QDir::SortFlags sort);
/**
* Tells whether the current items are in reversed order (shortcut to
* sorting() & QDir::Reversed).
*/
bool isReversed() const;
void sortReversed();
/**
* @returns the number of dirs and files
**/
uint count() const;
/**
* @returns the number of files.
**/
uint numFiles() const;
/**
* @returns the number of directories
**/
uint numDirs() const;
virtual void setSelectionMode( KFile::SelectionMode sm );
virtual KFile::SelectionMode selectionMode() const;
enum ViewMode {
Files = 1,
Directories = 2,
All = Files | Directories
};
virtual void setViewMode( ViewMode vm );
virtual ViewMode viewMode() const;
/**
* @returns the localized name of the view, which could be displayed
* somewhere, e.g. in a menu, where the user can choose between views.
* @see setViewName
*/
QString viewName() const;
/**
* Sets the name of the view, which could be displayed somewhere.
* E.g. "Image Preview".
*/
void setViewName( const QString& name );
virtual void setParentView(KFileView *parent);
/**
* The derived view must implement this function to add
* the file in the widget.
*
* Make sure to call this implementation, i.e.
* KFileView::insertItem( i );
*
*/
- virtual void insertItem( KFileItem *i);
+ virtual void insertItem( const KFileItem &i);
/**
* pure virtual function, that should be implemented to clear
* the view. At this moment the list is already empty
**/
virtual void clearView() = 0;
/**
* pure virtual function, that should be implemented to make item i
* visible, i.e. by scrolling the view appropriately.
*/
- virtual void ensureItemVisible( const KFileItem *i ) = 0;
+ virtual void ensureItemVisible( const KFileItem &i ) = 0;
/**
* Clears any selection, unhighlights everything. Must be implemented by
* the view.
*/
virtual void clearSelection() = 0;
/**
* Selects all items. You may want to override this, if you can implement
* it more efficiently than calling setSelected() with every item.
* This works only in Multiselection mode of course.
*/
virtual void selectAll();
/**
* Inverts the current selection, i.e. selects all items, that were up to
* now not selected and deselects the other.
*/
virtual void invertSelection();
/**
* Tells the view that it should highlight the item.
* This function must be implemented by the view.
**/
- virtual void setSelected(const KFileItem *, bool enable) = 0;
+ virtual void setSelected(const KFileItem &, bool enable) = 0;
/**
* @returns whether the given item is currently selected.
* Must be implemented by the view.
*/
- virtual bool isSelected( const KFileItem * ) const = 0;
+ virtual bool isSelected( const KFileItem & ) const = 0;
/**
* @returns all currently highlighted items.
*/
- const KFileItemList * selectedItems() const;
+ KFileItemList selectedItems() const;
/**
* @returns all items currently available in the current sort-order
*/
- const KFileItemList * items() const;
+ KFileItemList items() const;
- virtual KFileItem * firstFileItem() const = 0;
- virtual KFileItem * nextItem( const KFileItem * ) const = 0;
- virtual KFileItem * prevItem( const KFileItem * ) const = 0;
+ virtual KFileItem firstFileItem() const = 0;
+ virtual KFileItem nextItem( const KFileItem & ) const = 0;
+ virtual KFileItem prevItem( const KFileItem & ) const = 0;
/**
* This is a KFileDialog specific hack: we want to select directories with
* single click, but not files. But as a generic class, we have to be able
* to select files on single click as well.
*
* This gives us the opportunity to do both.
*
* Every view has to decide when to call select( item ) when a file was
* single-clicked, based on onlyDoubleClickSelectsFiles().
*/
void setOnlyDoubleClickSelectsFiles( bool enable );
/**
* @returns whether files (not directories) should only be select()ed by
* double-clicks.
* @see setOnlyDoubleClickSelectsFiles
*/
bool onlyDoubleClickSelectsFiles() const;
/**
* increases the number of dirs and files.
* @returns true if the item fits the view mode
*/
- bool updateNumbers(const KFileItem *i);
+ bool updateNumbers(const KFileItem &i);
/**
* @returns the view-specific action-collection. Every view should
* add its actions here (if it has any) to make them available to
* e.g. the KDirOperator's popup-menu.
*/
virtual KActionCollection * actionCollection() const;
KFileViewSignaler * signaler() const;
virtual void readConfig( KConfigGroup *);
virtual void writeConfig( KConfigGroup *);
/**
* Various options for drag and drop support.
* These values can be or'd together.
* @li @p AutoOpenDirs Automatically open directory after hovering above it
* for a short while while dragging.
*/
enum DropOptions {
AutoOpenDirs = 1
};
/**
* Specify DND options. See DropOptions for details.
* All options are disabled by default.
*/
virtual void setDropOptions(int options);
/**
* Returns the DND options in effect.
* See DropOptions for details.
*/
int dropOptions();
/**
* This method calculates a QString from the given parameters, that is
* suitable for sorting with e.g. QIconView or QListView. Their
* Item-classes usually have a setKey( const QString& ) method or a virtual
* method QString key() that is used for sorting.
*
* @param value Any string that should be used as sort criterion
* @param isDir Tells whether the key is computed for an item representing
* a directory (directories are usually sorted before files)
* @param SortFlags An ORed combination of QDir::SortFlag flags.
* Currently, the values IgnoreCase, Reversed and
* DirsFirst are taken into account.
*/
static QString sortingKey( const QString& value, bool isDir, QDir::SortFlags SortFlags);
/**
* An overloaded method that takes not a QString, but a number as sort
* criterion. You can use this for file-sizes or dates/times for example.
* If you use a time_t, you need to cast that to KIO::filesize_t because
* of ambiguity problems.
*/
static QString sortingKey( KIO::filesize_t value, bool isDir,QDir::SortFlags SortFlags);
/**
* @internal
* delay before auto opening a directory
*/
static int autoOpenDelay();
protected:
/**
* @internal
* class to distribute the signals
**/
KFileViewSignaler *sig;
private:
static QDir::SortFlags defaultSortFlags;
QDir::SortFlags m_sorting;
QString m_viewName;
/**
* counters
**/
uint filesNumber;
uint dirsNumber;
ViewMode view_mode;
KFile::SelectionMode selection_mode;
- // never use! It's only guaranteed to contain valid items in the items()
- // method!
- mutable KFileItemList m_itemList;
-
- mutable KFileItemList *m_selectedList;
bool myOnlyDoubleClickSelectsFiles;
private:
class KFileViewPrivate;
KFileViewPrivate* const d;
};
#endif // KFILEINFOLISTWIDGET_H
diff --git a/kfile/kfilewidget.cpp b/kfile/kfilewidget.cpp
index 586fdc85bc..a5cfe1c46c 100644
--- a/kfile/kfilewidget.cpp
+++ b/kfile/kfilewidget.cpp
@@ -1,2123 +1,2123 @@
// -*- c++ -*-
/* This file is part of the KDE libraries
Copyright (C) 1997, 1998 Richard Moore
1998 Stephan Kulow
1998 Daniel Grana
1999,2000,2001,2002,2003 Carsten Pfeiffer
2003 Clarence Dang
2007 David Faure
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kfilewidget.h"
#include "kfileplacesview.h"
#include "kfileplacesmodel.h"
#include "kfilebookmarkhandler.h"
#include "kurlcombobox.h"
#include "kurlnavigator.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
class KFileWidgetPrivate
{
public:
KFileWidgetPrivate( KFileWidget* q )
: boxLayout(0),
labeledCustomWidget(0),
bottomCustomWidget(0),
inAccept(false),
q(q)
{
}
void updateLocationWhatsThis();
void updateAutoSelectExtension();
void initSpeedbar();
void initGUI();
void readConfig(const KConfigGroup &configGroup);
void writeConfig(KConfigGroup &configGroup);
void setNonExtSelection();
void setLocationText(const QString&);
void appendExtension(KUrl &url);
void updateLocationEditExtension(const QString &);
void updateFilter();
KUrl::List& parseSelectedUrls();
/**
* Parses the string "line" for files. If line doesn't contain any ", the
* whole line will be interpreted as one file. If the number of " is odd,
* an empty list will be returned. Otherwise, all items enclosed in " "
* will be returned as correct urls.
*/
KUrl::List tokenize(const QString& line) const;
/**
* Reads the recent used files and inserts them into the location combobox
*/
void readRecentFiles( KConfig * );
/**
* Saves the entries from the location combobox.
*/
void saveRecentFiles( KConfig * );
/**
* called when an item is highlighted/selected in multiselection mode.
* handles setting the locationEdit.
*/
void multiSelectionChanged();
/**
* Returns the URL which represents the directory of \a url. If
* \a url already is a directory, then just \a url is returned.
*/
KUrl directoryUrl(const KUrl& url) const;
// the last selected url
KUrl url;
// the selected filenames in multiselection mode -- FIXME
QString filenames;
// the name of the filename set by setSelection
QString selection;
// now following all kind of widgets, that I need to rebuild
// the geometry management
QBoxLayout *boxLayout;
QGridLayout *lafBox;
QVBoxLayout *vbox;
QLabel *locationLabel;
// @deprecated remove in KDE4 -- err, remove what?
QLabel *filterLabel;
KUrlNavigator *urlNavigator;
KPushButton *okButton, *cancelButton;
KFilePlacesView *placesView;
QSplitter *placesViewSplitter;
QWidget *labeledCustomWidget;
QWidget *bottomCustomWidget;
// Automatically Select Extension stuff
QCheckBox *autoSelectExtCheckBox;
bool autoSelectExtChecked; // whether or not the _user_ has checked the above box
QString extension; // current extension for this filter
QList statJobs;
KUrl::List urlList; //the list of selected urls
QStringList mimetypes; //the list of possible mimetypes to save as
// indicates if the location edit should be kept or cleared when changing
// directories
bool keepLocation;
// the KDirOperators view is set in KFileWidget::show(), so to avoid
// setting it again and again, we have this nice little boolean :)
bool hasView;
bool hasDefaultFilter; // necessary for the operationMode
bool autoDirectoryFollowing;
bool inAccept; // true between beginning and end of accept()
KFileWidget::OperationMode operationMode;
// The file class used for KRecentDirs
QString fileClass;
KFileBookmarkHandler *bookmarkHandler;
KActionMenu* bookmarkButton;
KConfigGroup *viewConfigGroup;
KToolBar *toolbar;
KUrlComboBox *locationEdit;
KDirOperator *ops;
KFileFilterCombo *filterWidget;
KFileWidget* q;
};
K_GLOBAL_STATIC(KUrl, lastDirectory) // to set the start path
static const char autocompletionWhatsThisText[] = I18N_NOOP("While typing in the text area, you may be presented "
"with possible matches. "
"This feature can be controlled by clicking with the right mouse button "
"and selecting a preferred mode from the Text Completion menu.") "";
KFileWidget::KFileWidget( const KUrl& startDir, QWidget *parent )
: QWidget(parent), KAbstractFileWidget(), d(new KFileWidgetPrivate(this))
{
// TODO move most of this code for the KFileWidgetPrivate constructor
d->keepLocation = false;
d->operationMode = Opening;
d->bookmarkHandler = 0;
d->hasDefaultFilter = false;
d->hasView = false;
d->okButton = new KPushButton(KStandardGuiItem::ok(), this);
d->okButton->setDefault( true );
d->cancelButton = new KPushButton(KStandardGuiItem::cancel(), this);
// The dialog shows them
d->okButton->hide();
d->cancelButton->hide();
d->autoSelectExtCheckBox = 0; // delayed loading
d->autoSelectExtChecked = false;
d->placesView = 0; // delayed loading
d->toolbar = new KToolBar(this, true);
d->toolbar->setObjectName("KFileWidget::toolbar");
d->toolbar->setMovable(false);
KFilePlacesModel *model = new KFilePlacesModel(this);
d->urlNavigator = new KUrlNavigator(model, d->directoryUrl(startDir), d->toolbar);
d->urlNavigator->setPlacesSelectorVisible(false);
KUrl u;
QString text;
KUrlComboBox *pathCombo = d->urlNavigator->editor();
#ifdef Q_WS_WIN
foreach( const QFileInfo &drive,QFSFileEngine::drives() )
{
u.setPath( drive.filePath() );
text = i18n("Drive: %1", u.toLocalFile() );
pathCombo->addDefaultUrl( u,
KIO::pixmapForUrl( u, 0, K3Icon::Small ),
text );
}
#else
u.setPath( QDir::rootPath() );
text = i18n("Root Folder: %1", u.toLocalFile() );
pathCombo->addDefaultUrl( u,
KIO::pixmapForUrl( u, 0, K3Icon::Small ),
text );
#endif
u.setPath( QDir::homePath() );
text = i18n("Home Folder: %1", u.path( KUrl::AddTrailingSlash ) );
pathCombo->addDefaultUrl( u, KIO::pixmapForUrl( u, 0, K3Icon::Small ),
text );
KUrl docPath;
docPath.setPath( KGlobalSettings::documentPath() );
if ( (u.path(KUrl::AddTrailingSlash) != docPath.path(KUrl::AddTrailingSlash)) &&
QDir(docPath.path(KUrl::AddTrailingSlash)).exists() )
{
text = i18n("Documents: %1", docPath.path( KUrl::AddTrailingSlash ) );
pathCombo->addDefaultUrl( docPath,
KIO::pixmapForUrl( docPath, 0, K3Icon::Small ),
text );
}
u.setPath( KGlobalSettings::desktopPath() );
text = i18n("Desktop: %1", u.path( KUrl::AddTrailingSlash ) );
pathCombo->addDefaultUrl( u,
KIO::pixmapForUrl( u, 0, K3Icon::Small ),
text );
d->url = getStartUrl( startDir, d->fileClass );
d->selection = d->url.url();
// If local, check it exists. If not, go up until it exists.
if ( d->url.isLocalFile() )
{
if ( !QFile::exists( d->url.toLocalFile() ) )
{
d->url = d->url.upUrl();
QDir dir( d->url.toLocalFile() );
while ( !dir.exists() )
{
d->url = d->url.upUrl();
dir.setPath( d->url.toLocalFile() );
}
}
}
d->ops = new KDirOperator(d->url, this );
d->ops->setObjectName( "KFileWidget::ops" );
d->ops->setOnlyDoubleClickSelectsFiles( true );
connect(d->ops, SIGNAL(urlEntered(const KUrl&)),
SLOT(urlEntered(const KUrl&)));
- connect(d->ops, SIGNAL(fileHighlighted(const KFileItem *)),
- SLOT(fileHighlighted(const KFileItem *)));
- connect(d->ops, SIGNAL(fileSelected(const KFileItem *)),
- SLOT(fileSelected(const KFileItem *)));
+ connect(d->ops, SIGNAL(fileHighlighted(const KFileItem &)),
+ SLOT(fileHighlighted(const KFileItem &)));
+ connect(d->ops, SIGNAL(fileSelected(const KFileItem &)),
+ SLOT(fileSelected(const KFileItem &)));
connect(d->ops, SIGNAL(finishedLoading()),
SLOT(slotLoadingFinished()));
d->ops->setupMenu(KDirOperator::SortActions |
KDirOperator::FileActions |
KDirOperator::ViewActions);
KActionCollection *coll = d->ops->actionCollection();
// add nav items to the toolbar
//
// NOTE: The order of the button icons here differs from that
// found in the file manager and web browser, but has been discussed
// and agreed upon on the kde-core-devel mailing list:
//
// http://lists.kde.org/?l=kde-core-devel&m=116888382514090&w=2
//
d->toolbar->addAction( coll->action( "up" ) );
coll->action( "up" )->setWhatsThis(i18n("Click this button to enter the parent folder.
"
"For instance, if the current location is file:/home/%1 clicking this "
"button will take you to file:/home.", KUser().loginName() ));
d->toolbar->addAction( coll->action( "back" ) );
coll->action( "back" )->setWhatsThis(i18n("Click this button to move backwards one step in the browsing history."));
d->toolbar->addAction( coll->action( "forward" ) );
coll->action( "forward" )->setWhatsThis(i18n("Click this button to move forward one step in the browsing history."));
d->toolbar->addAction( coll->action( "reload" ) );
coll->action( "reload" )->setWhatsThis(i18n("Click this button to reload the contents of the current location."));
coll->action( "mkdir" )->setShortcut( QKeySequence(Qt::Key_F10) );
d->toolbar->addAction( coll->action( "mkdir" ) );
coll->action( "mkdir" )->setWhatsThis(i18n("Click this button to create a new folder."));
KToggleAction *showSidebarAction =
new KToggleAction(i18n("Show Places Navigation Panel"), this);
coll->addAction("toggleSpeedbar", showSidebarAction);
showSidebarAction->setShortcut( QKeySequence(Qt::Key_F9) );
connect( showSidebarAction, SIGNAL( toggled( bool ) ),
SLOT( toggleSpeedbar( bool )) );
KToggleAction *showBookmarksAction =
new KToggleAction(i18n("Show Bookmarks"), this);
coll->addAction("toggleBookmarks", showBookmarksAction);
connect( showBookmarksAction, SIGNAL( toggled( bool ) ),
SLOT( toggleBookmarks( bool )) );
KActionMenu *menu = new KActionMenu( KIcon("configure"), i18n("Options"), this);
coll->addAction("extra menu", menu);
menu->setWhatsThis(i18n("This is the preferences menu for the file dialog. "
"Various options can be accessed from this menu including: "
"- how files are sorted in the list
"
"- types of view, including icon and list
"
"- showing of hidden files
"
"- the Places navigation panel
"
"- file previews
"
"- separating folders from files
"));
menu->addAction( coll->action( "sorting menu" ));
menu->addSeparator();
coll->action( "short view" )->setShortcut( QKeySequence(Qt::Key_F6) );
menu->addAction( coll->action( "short view" ));
coll->action( "detailed view" )->setShortcut( QKeySequence(Qt::Key_F7) );
menu->addAction( coll->action( "detailed view" ));
menu->addSeparator();
coll->action( "show hidden" )->setShortcut( QKeySequence(Qt::Key_F8) );
menu->addAction( coll->action( "show hidden" ));
menu->addAction( showSidebarAction );
menu->addAction( showBookmarksAction );
coll->action( "preview" )->setShortcut( QKeySequence(Qt::Key_F11) );
menu->addAction( coll->action( "preview" ));
menu->setDelayed( false );
connect( menu->menu(), SIGNAL( aboutToShow() ),
d->ops, SLOT( updateSelectionDependentActions() ));
d->toolbar->addAction( menu );
d->toolbar->addWidget(d->urlNavigator);
// FIXME KAction port - add capability
//d->toolbar->setItemAutoSized (PATH_COMBO);
d->toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly);
d->toolbar->setMovable(false);
KUrlCompletion *pathCompletionObj = new KUrlCompletion( KUrlCompletion::DirCompletion );
pathCombo->setCompletionObject( pathCompletionObj );
pathCombo->setAutoDeleteCompletionObject( true );
connect( d->urlNavigator, SIGNAL( urlChanged( const KUrl& )),
this, SLOT( enterUrl( const KUrl& ) ));
QString whatsThisText;
// the Location label/edit
d->locationLabel = new QLabel(i18n("&Location:"), this);
d->locationEdit = new KUrlComboBox(KUrlComboBox::Files, true, this);
connect( d->locationEdit, SIGNAL( textChanged( const QString& ) ),
SLOT( slotLocationChanged( const QString& )) );
d->updateLocationWhatsThis();
d->locationLabel->setBuddy(d->locationEdit);
d->locationEdit->setFocus();
KUrlCompletion *fileCompletionObj = new KUrlCompletion( KUrlCompletion::FileCompletion );
QString dir = d->url.url(KUrl::AddTrailingSlash);
d->urlNavigator->setUrl( d->directoryUrl( dir ) );
fileCompletionObj->setDir( dir );
d->locationEdit->setCompletionObject( fileCompletionObj );
d->locationEdit->setAutoDeleteCompletionObject( true );
connect( fileCompletionObj, SIGNAL( match( const QString& ) ),
SLOT( fileCompletion( const QString& )) );
connect(d->locationEdit, SIGNAL( returnPressed( const QString& )),
this, SLOT( locationAccepted( const QString& ) ));
// the Filter label/edit
whatsThisText = i18n("This is the filter to apply to the file list. "
"File names that do not match the filter will not be shown."
"You may select from one of the preset filters in the "
"drop down menu, or you may enter a custom filter "
"directly into the text area.
"
"Wildcards such as * and ? are allowed.
");
d->filterLabel = new QLabel(i18n("&Filter:"), this);
d->filterLabel->setWhatsThis(whatsThisText);
d->filterWidget = new KFileFilterCombo(this);
d->filterWidget->setWhatsThis(whatsThisText);
d->filterLabel->setBuddy(d->filterWidget);
connect(d->filterWidget, SIGNAL(filterChanged()), SLOT(slotFilterChanged()));
// the Automatically Select Extension checkbox
// (the text, visibility etc. is set in updateAutoSelectExtension(), which is called by readConfig())
d->autoSelectExtCheckBox = new QCheckBox (this);
d->autoSelectExtCheckBox->setStyleSheet(QString("QCheckBox { spacing-top: %1px; }").arg(KDialog::spacingHint()));
connect(d->autoSelectExtCheckBox, SIGNAL(clicked()), SLOT(slotAutoSelectExtClicked()));
d->initGUI(); // activate GM
KSharedConfig::Ptr config = KGlobal::config();
d->readRecentFiles(config.data());
d->viewConfigGroup=new KConfigGroup(config,ConfigGroup);
d->ops->setViewConfig(*d->viewConfigGroup);
d->readConfig(* d->viewConfigGroup);
setSelection(d->selection);
}
KFileWidget::~KFileWidget()
{
KSharedConfig::Ptr config = KGlobal::config();
config->sync();
delete d->bookmarkHandler; // Should be deleted before ops!
delete d->ops;
delete d->viewConfigGroup;
delete d;
}
void KFileWidget::setLocationLabel(const QString& text)
{
d->locationLabel->setText(text);
}
void KFileWidget::setFilter(const QString& filter)
{
int pos = filter.indexOf('/');
// Check for an un-escaped '/', if found
// interpret as a MIME filter.
if (pos > 0 && filter[pos - 1] != '\\') {
QStringList filters = filter.split(" ", QString::SkipEmptyParts); //QStringList::split( " ", filter );
setMimeFilter( filters );
return;
}
// Strip the escape characters from
// escaped '/' characters.
QString copy (filter);
for (pos = 0; (pos = copy.indexOf("\\/", pos)) != -1; ++pos)
copy.remove(pos, 1);
d->ops->clearFilter();
d->filterWidget->setFilter(copy);
d->ops->setNameFilter(d->filterWidget->currentFilter());
d->hasDefaultFilter = false;
d->filterWidget->setEditable( true );
d->updateAutoSelectExtension ();
}
QString KFileWidget::currentFilter() const
{
return d->filterWidget->currentFilter();
}
void KFileWidget::setMimeFilter( const QStringList& mimeTypes,
const QString& defaultType )
{
d->mimetypes = mimeTypes;
d->filterWidget->setMimeFilter( mimeTypes, defaultType );
QStringList types = d->filterWidget->currentFilter().split(" ",QString::SkipEmptyParts); //QStringList::split(" ", d->filterWidget->currentFilter());
types.append( QLatin1String( "inode/directory" ));
d->ops->clearFilter();
d->ops->setMimeFilter( types );
d->hasDefaultFilter = !defaultType.isEmpty();
d->filterWidget->setEditable( !d->hasDefaultFilter ||
d->operationMode != Saving );
d->updateAutoSelectExtension ();
}
void KFileWidget::clearFilter()
{
d->mimetypes.clear();
d->filterWidget->setFilter( QString() );
d->ops->clearFilter();
d->hasDefaultFilter = false;
d->filterWidget->setEditable( true );
d->updateAutoSelectExtension ();
}
QString KFileWidget::currentMimeFilter() const
{
int i = d->filterWidget->currentIndex();
if (d->filterWidget->showsAllTypes())
i--;
if ((i >= 0) && (i < (int) d->mimetypes.count()))
return d->mimetypes[i];
return QString(); // The "all types" item has no mimetype
}
KMimeType::Ptr KFileWidget::currentFilterMimeType()
{
return KMimeType::mimeType( currentMimeFilter() );
}
void KFileWidget::setPreviewWidget(KPreviewWidgetBase *w) {
d->ops->setPreviewWidget(w);
d->ops->clearHistory();
d->hasView = true;
}
KUrl KFileWidget::getCompleteUrl(const QString &_url)
{
QString url = KShell::tildeExpand(_url);
KUrl u;
if ( KUrl::isRelativeUrl(url) ) // only a full URL isn't relative. Even /path is.
{
if (!url.isEmpty() && !QDir::isRelativePath(url) ) // absolute path
u.setPath( url );
else
{
u = d->ops->url();
u.addPath( url ); // works for filenames and relative paths
u.cleanPath(); // fix "dir/.."
}
}
else // complete URL
u = url;
return u;
}
// Called by KFileDialog
void KFileWidget::slotOk()
{
kDebug(kfile_area) << "slotOk\n";
// a list of all selected files/directories (if any)
// can only be used if the user didn't type any filenames/urls himself
const QList items = d->ops->selectedItems();
if ( (mode() & KFile::Directory) != KFile::Directory ) {
if ( d->locationEdit->currentText().trimmed().isEmpty() ) {
if (items.isEmpty() )
{
QString msg;
if ( d->operationMode == Saving )
msg = i18n("Please specify the filename to save to.");
else
msg = i18n("Please select the file to open.");
KMessageBox::information(this, msg);
return;
}
// weird case: the location edit is empty, but there are
// highlighted files
else {
bool multi = (mode() & KFile::Files) != 0;
QString endQuote = QLatin1String("\" ");
QString name, files;
foreach (KFileItem fileItem, items) {
name = fileItem.name();
if ( multi ) {
name.prepend( QLatin1Char( '"' ) );
name.append( endQuote );
}
files.append( name );
}
d->setLocationText( files );
return;
}
}
}
bool dirOnly = d->ops->dirOnlyMode();
// we can use our kfileitems, no need to parse anything
if ( !d->locationEdit->lineEdit()->isModified() &&
!(items.isEmpty() && !dirOnly) ) {
d->urlList.clear();
d->filenames.clear();
if ( dirOnly ) {
d->url = d->ops->url();
}
else {
if ( !(mode() & KFile::Files) ) {// single selection
d->url = items.first().url();
}
else { // multi (dirs and/or files)
d->url = d->ops->url();
KUrl::List urlList;
foreach (KFileItem item, items) {
urlList.append(item.url());
}
d->urlList = urlList;
}
}
KUrl url = KIO::NetAccess::mostLocalUrl(d->url,topLevelWidget());
if ( (mode() & KFile::LocalOnly) == KFile::LocalOnly &&
!url.isLocalFile() ) {
// ### after message freeze, add message for directories!
KMessageBox::sorry( this,
i18n("You can only select local files."),
i18n("Remote Files Not Accepted") );
return;
}
d->url = url;
emit accepted();
return;
}
KUrl selectedUrl;
if ( (mode() & KFile::Files) == KFile::Files ) {// multiselection mode
QString locationText = d->locationEdit->currentText();
if ( locationText.contains( '/' )) {
// relative path? -> prepend the current directory
KUrl u( d->ops->url(), KShell::tildeExpand(locationText));
if ( u.isValid() )
selectedUrl = u;
else
selectedUrl = d->ops->url();
}
else // simple filename -> just use the current URL
selectedUrl = d->ops->url();
}
else {
selectedUrl = getCompleteUrl(d->locationEdit->currentText());
// appendExtension() may change selectedUrl
d->appendExtension (selectedUrl);
}
if ( !selectedUrl.isValid() ) {
KMessageBox::sorry( this, i18n("%1\ndoes not appear to be a valid URL.\n", d->url.url()), i18n("Invalid URL") );
return;
}
KUrl url = KIO::NetAccess::mostLocalUrl(selectedUrl,topLevelWidget());
if ( (mode() & KFile::LocalOnly) == KFile::LocalOnly &&
!url.isLocalFile() ) {
KMessageBox::sorry( this,
i18n("You can only select local files."),
i18n("Remote Files Not Accepted") );
return;
}
d->url = url;
// d->url is a correct URL now
if ( (mode() & KFile::Directory) == KFile::Directory ) {
kDebug(kfile_area) << "Directory";
bool done = true;
if ( d->url.isLocalFile() ) {
if ( d->locationEdit->currentText().trimmed().isEmpty() ) {
QFileInfo info( d->url.toLocalFile() );
if ( info.isDir() ) {
d->filenames.clear();
d->urlList.clear();
d->urlList.append( d->url );
emit accepted();
}
else if (!info.exists() && (mode() & KFile::File) != KFile::File) {
// directory doesn't exist, create and enter it
if ( d->ops->mkdir( d->url.url(), true ))
return;
else
emit accepted();
}
else { // d->url is not a directory,
// maybe we are in File(s) | Directory mode
if ( (mode() & KFile::File) == KFile::File ||
(mode() & KFile::Files) == KFile::Files )
done = false;
}
}
else // Directory mode, with file[s]/dir[s] selected
{
if ( mode() & KFile::ExistingOnly )
{
if ( d->ops->dirOnlyMode() )
{
KUrl fullURL(d->url, d->locationEdit->currentText());
if ( QFile::exists( fullURL.toLocalFile() ) )
{
d->url = fullURL;
d->filenames.clear();
d->urlList.clear();
emit accepted();
return;
}
else // doesn't exist -> reject
return;
}
}
d->filenames = d->locationEdit->currentText();
emit accepted(); // what can we do?
}
}
else { // FIXME: remote directory, should we allow that?
// qDebug( "**** Selected remote directory: %s", d->url.url().toLatin1().constData());
d->filenames.clear();
d->urlList.clear();
d->urlList.append( d->url );
if ( mode() & KFile::ExistingOnly )
done = false;
else
emit accepted();
}
if ( done )
return;
}
if (!KAuthorized::authorizeUrlAction("open", KUrl(), d->url))
{
QString msg = KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, d->url.prettyUrl());
KMessageBox::error( this, msg);
return;
}
KIO::StatJob *job = 0L;
d->statJobs.clear();
d->filenames = KShell::tildeExpand(d->locationEdit->currentText());
if ( (mode() & KFile::Files) == KFile::Files &&
!d->locationEdit->currentText().contains( '/' )) {
kDebug(kfile_area) << "Files\n";
KUrl::List list = d->parseSelectedUrls();
for ( KUrl::List::ConstIterator it = list.begin();
it != list.end(); ++it )
{
if (!KAuthorized::authorizeUrlAction("open", KUrl(), *it))
{
QString msg = KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, (*it).prettyUrl());
KMessageBox::error( this, msg);
return;
}
}
for ( KUrl::List::ConstIterator it = list.begin();
it != list.end(); ++it )
{
job = KIO::stat( *it, !(*it).isLocalFile() );
job->ui()->setWindow (topLevelWidget());
KIO::Scheduler::scheduleJob( job );
d->statJobs.append( job );
connect( job, SIGNAL( result(KJob *) ),
SLOT( slotStatResult( KJob *) ));
}
return;
}
job = KIO::stat(d->url,!d->url.isLocalFile());
job->ui()->setWindow (topLevelWidget());
d->statJobs.append( job );
connect(job, SIGNAL(result(KJob*)), SLOT(slotStatResult(KJob*)));
}
// FIXME : count all errors and show messagebox when d->statJobs.count() == 0
// in case of an error, we cancel the whole operation (clear d->statJobs and
// don't call accept)
void KFileWidget::slotStatResult(KJob* job)
{
kDebug(kfile_area) << "slotStatResult";
KIO::StatJob *sJob = static_cast( job );
if ( !d->statJobs.removeAll( sJob ) ) {
return;
}
int count = d->statJobs.count();
// errors mean in general, the location is no directory ;/
// Can we be sure that it is exististant at all? (pfeiffer)
if (sJob->error() && count == 0 && !d->ops->dirOnlyMode())
{
emit accepted();
return;
}
KIO::UDSEntry t = sJob->statResult();
if (t.isDir())
{
if ( d->ops->dirOnlyMode() )
{
d->filenames.clear();
d->urlList.clear();
emit accepted();
}
else // in File[s] mode, directory means error -> cd into it
{
if ( count == 0 ) {
d->locationEdit->clearEditText();
d->locationEdit->lineEdit()->setModified( false );
setUrl( sJob->url() );
}
}
d->statJobs.clear();
return;
}
else if ( d->ops->dirOnlyMode() )
{
return; // ### error message?
}
kDebug(kfile_area) << "filename " << sJob->url().url();
if ( count == 0 )
emit accepted();
}
void KFileWidget::accept()
{
d->inAccept = true; // parseSelectedUrls() checks that
*lastDirectory = d->ops->url();
if (!d->fileClass.isEmpty())
KRecentDirs::add(d->fileClass, d->ops->url().url());
// clear the topmost item, we insert it as full path later on as item 1
d->locationEdit->setItemText( 0, QString() );
KUrl::List list = selectedUrls();
QList::const_iterator it = list.begin();
for ( ; it != list.end(); ++it ) {
const KUrl& url = *it;
// we strip the last slash (-1) because KUrlComboBox does that as well
// when operating in file-mode. If we wouldn't , dupe-finding wouldn't
// work.
QString file = url.isLocalFile() ? url.path(KUrl::RemoveTrailingSlash) : url.prettyUrl(KUrl::RemoveTrailingSlash);
// remove dupes
for ( int i = 1; i < d->locationEdit->count(); i++ ) {
if ( d->locationEdit->itemText( i ) == file ) {
d->locationEdit->removeItem( i-- );
break;
}
}
d->locationEdit->insertItem( 1,file);
}
KSharedConfig::Ptr config = KGlobal::config();
config->setForceGlobal( true );
KConfigGroup grp(config,ConfigGroup);
d->writeConfig(grp);
config->setForceGlobal( false );
d->saveRecentFiles(config.data());
config->sync();
addToRecentDocuments();
if ( (mode() & KFile::Files) != KFile::Files ) // single selection
emit fileSelected(d->url.url());
d->ops->close();
}
-void KFileWidget::fileHighlighted(const KFileItem *i)
+void KFileWidget::fileHighlighted(const KFileItem &i)
{
- if (i && i->isDir())
+ if (!i.isNull() && i.isDir())
return;
if ( (d->ops->mode() & KFile::Files) != KFile::Files ) {
- if ( !i )
+ if ( i.isNull() )
return;
- d->url = i->url();
+ d->url = i.url();
if ( !d->locationEdit->hasFocus() ) { // don't disturb while editing
- d->setLocationText( i->name() );
+ d->setLocationText( i.name() );
}
emit fileHighlighted(d->url.url());
}
else {
d->multiSelectionChanged();
emit selectionChanged();
}
}
-void KFileWidget::fileSelected(const KFileItem *i)
+void KFileWidget::fileSelected(const KFileItem &i)
{
- if (i && i->isDir())
+ if (!i.isNull() && i.isDir())
return;
if ( (d->ops->mode() & KFile::Files) != KFile::Files ) {
- if ( !i )
+ if ( i.isNull() )
return;
- d->url = i->url();
- d->setLocationText( i->name() );
+ d->url = i.url();
+ d->setLocationText( i.name() );
}
else {
d->multiSelectionChanged();
emit selectionChanged();
}
slotOk();
}
// I know it's slow to always iterate thru the whole filelist
// (d->ops->selectedItems()), but what can we do?
void KFileWidgetPrivate::multiSelectionChanged()
{
if ( locationEdit->hasFocus() ) // don't disturb
return;
locationEdit->lineEdit()->setModified( false );
const QList list = ops->selectedItems();
if ( list.isEmpty() ) {
locationEdit->clearEditText();
return;
}
static const QString &begin = KGlobal::staticQString(" \"");
QString text;
foreach (KFileItem fileItem, list) {
text.append( begin ).append( fileItem.name() ).append( QLatin1Char( '"' ) );
}
setLocationText( text.trimmed() );
}
KUrl KFileWidgetPrivate::directoryUrl(const KUrl& url) const
{
KFileItem item(S_IFDIR, KFileItem::Unknown, url);
item.refresh();
return item.isDir() ? url : url.upUrl();
}
void KFileWidgetPrivate::setLocationText( const QString& text )
{
// setCurrentItem() will cause textChanged() being emitted,
// so slotLocationChanged() will be called. Make sure we don't clear
// the KDirOperator's view-selection in there
QObject::disconnect( locationEdit, SIGNAL( textChanged( const QString& ) ),
q, SLOT( slotLocationChanged( const QString& ) ) );
locationEdit->setCurrentIndex( 0 );
QObject::connect( locationEdit, SIGNAL( textChanged( const QString& ) ),
q, SLOT( slotLocationChanged( const QString& )) );
locationEdit->setEditText( text );
// don't change selection when user has clicked on an item
if ( operationMode == KFileWidget::Saving && !locationEdit->isVisible())
setNonExtSelection();
}
void KFileWidgetPrivate::updateLocationWhatsThis()
{
QString whatsThisText;
if (operationMode == KFileWidget::Saving)
{
whatsThisText = "" + i18n("This is the name to save the file as.") +
i18n (autocompletionWhatsThisText);
}
else if (ops->mode() & KFile::Files)
{
whatsThisText = "" + i18n("This is the list of files to open. More than "
"one file can be specified by listing several "
"files, separated by spaces.") +
i18n (autocompletionWhatsThisText);
}
else
{
whatsThisText = "" + i18n("This is the name of the file to open.") +
i18n (autocompletionWhatsThisText);
}
locationLabel->setWhatsThis(whatsThisText);
locationEdit->setWhatsThis(whatsThisText);
}
void KFileWidgetPrivate::initSpeedbar()
{
placesView = new KFilePlacesView( q );
placesView->setModel(new KFilePlacesModel(placesView));
placesView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
placesView->setObjectName( QLatin1String( "url bar" ) );
QObject::connect( placesView, SIGNAL( urlChanged( const KUrl& )),
q, SLOT( enterUrl( const KUrl& )) );
// need to set the current url of the urlbar manually (not via urlEntered()
// here, because the initial url of KDirOperator might be the same as the
// one that will be set later (and then urlEntered() won't be emitted).
// ### REMOVE THIS when KDirOperator's initial URL (in the c'tor) is gone.
placesView->setUrl( url );
placesViewSplitter->insertWidget( 0, placesView );
}
void KFileWidgetPrivate::initGUI()
{
delete boxLayout; // deletes all sub layouts
boxLayout = new QVBoxLayout( q);
boxLayout->setMargin(0); // no additional margin to the already existing
boxLayout->setSpacing(0);
boxLayout->addWidget(toolbar, 0, Qt::AlignTop);
placesViewSplitter = new QSplitter(q);
placesViewSplitter->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
placesViewSplitter->setChildrenCollapsible(false);
boxLayout->addWidget(placesViewSplitter);
vbox = new QVBoxLayout();
vbox->setMargin(0);
QWidget *vboxWidget = new QWidget();
vboxWidget->setLayout(vbox);
placesViewSplitter->insertWidget(0, vboxWidget);
vbox->addWidget(ops, 4);
vbox->addSpacing(KDialog::spacingHint());
lafBox = new QGridLayout();
// The default minimum width of the location editor and the filter widget
// is so huge, that it is no possible for the user to adjust the width
// of the speedbar, hence it will be reduced.
locationEdit->setMinimumWidth(40);
filterWidget->setMinimumWidth(40);
lafBox->setSpacing(KDialog::spacingHint());
lafBox->addWidget(locationLabel, 0, 0, Qt::AlignVCenter);
lafBox->addWidget(locationEdit, 0, 1, Qt::AlignVCenter);
lafBox->addWidget(okButton, 0, 2, Qt::AlignVCenter);
lafBox->addWidget(filterLabel, 1, 0, Qt::AlignVCenter);
lafBox->addWidget(filterWidget, 1, 1, Qt::AlignVCenter);
lafBox->addWidget(cancelButton, 1, 2, Qt::AlignVCenter);
lafBox->setColumnStretch(1, 4);
vbox->addLayout(lafBox);
// add the Automatically Select Extension checkbox
vbox->addWidget(autoSelectExtCheckBox);
q->setTabOrder(ops, autoSelectExtCheckBox);
q->setTabOrder(autoSelectExtCheckBox, locationEdit);
q->setTabOrder(locationEdit, filterWidget);
q->setTabOrder(filterWidget, okButton);
q->setTabOrder(okButton, cancelButton);
q->setTabOrder(cancelButton, urlNavigator);
q->setTabOrder(urlNavigator, ops);
q->setTabOrder(cancelButton, urlNavigator);
q->setTabOrder(urlNavigator, ops);
}
void KFileWidget::slotFilterChanged()
{
QString filter = d->filterWidget->currentFilter();
d->ops->clearFilter();
if ( filter.indexOf( '/' ) > -1 ) {
QStringList types = filter.split(" ",QString::SkipEmptyParts); //QStringList::split( " ", filter );
types.prepend( "inode/directory" );
d->ops->setMimeFilter( types );
}
else
d->ops->setNameFilter( filter );
d->ops->updateDir();
d->updateAutoSelectExtension();
emit filterChanged( filter );
}
void KFileWidget::setUrl(const KUrl& url, bool clearforward)
{
d->selection.clear();
d->ops->setUrl( url, clearforward);
}
// Protected
void KFileWidget::urlEntered(const KUrl& url)
{
QString filename = d->locationEdit->currentText();
d->selection.clear();
KUrlComboBox* pathCombo = d->urlNavigator->editor();
if ( pathCombo->count() != 0 ) { // little hack
pathCombo->setUrl( url );
}
bool blocked = d->locationEdit->blockSignals( true );
d->locationEdit->setCurrentIndex( 0 );
if ( d->keepLocation )
d->locationEdit->setEditText( filename );
d->locationEdit->blockSignals( blocked );
d->urlNavigator->setUrl( d->directoryUrl( url ) );
QString dir = url.url(KUrl::AddTrailingSlash);
static_cast( d->locationEdit->completionObject() )->setDir( dir );
if ( d->placesView )
d->placesView->setUrl( url );
}
void KFileWidget::locationAccepted( const QString& url )
{
setSelection( url );
slotOk();
}
void KFileWidget::enterUrl( const KUrl& url )
{
setUrl( url );
}
void KFileWidget::enterUrl( const QString& url )
{
setUrl( KUrl( KUrlCompletion::replacedPath( url, true, true )) );
}
void KFileWidget::setSelection(const QString& url)
{
kDebug(kfile_area) << "setSelection " << url;
if (url.isEmpty()) {
d->selection.clear();
return;
}
KUrl u = getCompleteUrl(url);
if (!u.isValid()) { // if it still is
kWarning() << url << " is not a correct argument for setSelection!";
return;
}
// Honor protocols that do not support directory listing
if (!KProtocolManager::supportsListing(u))
return;
/* we strip the first / from the path to avoid file://usr which means
* / on host usr
*/
KFileItem i(KFileItem::Unknown, KFileItem::Unknown, u, true );
// KFileItem i(u.path());
kDebug(kfile_area) << "KFileItem " << u.path() << " " << i.isDir() << " " << u.isLocalFile() << " " << QFile::exists( u.path() );
if ( i.isDir() && u.isLocalFile() && QFile::exists( u.path() ) ) {
// trust isDir() only if the file is
// local (we cannot stat non-local urls) and if it exists!
// (as KFileItem does not check if the file exists or not
// -> the statbuffer is undefined -> isDir() is unreliable) (Simon)
setUrl(u, true);
}
else {
QString filename = u.url();
int sep = filename.lastIndexOf('/');
if (sep >= 0) { // there is a / in it
KUrl dir(u);
dir.setQuery( QString() );
dir.setFileName( QString() );
setUrl(dir, true );
// filename must be decoded, or "name with space" would become
// "name%20with%20space", so we use KUrl::fileName()
filename = u.fileName();
kDebug(kfile_area) << "filename " << filename;
d->selection = filename;
d->setLocationText( filename );
// tell the line edit that it has been edited
// otherwise we won't know this was set by the user
// and it will be ignored if there has been an
// auto completion. this caused bugs where automcompletion
// would start, the user would pick something from the
// history and then hit Ok only to get the autocompleted
// selection. OOD->OPS.
d->locationEdit->lineEdit()->setModified( true );
}
d->url = d->ops->url();
d->url.addPath(filename);
}
}
void KFileWidget::slotLoadingFinished()
{
if ( !d->selection.isNull() )
d->ops->setCurrentItem( d->selection );
}
void KFileWidget::fileCompletion( const QString& match )
{
if ( match.isEmpty() && d->ops->view() )
d->ops->view()->clearSelection();
else
d->ops->setCurrentItem( match );
}
void KFileWidget::slotLocationChanged( const QString& text )
{
if ( text.isEmpty() && d->ops->view() )
d->ops->view()->clearSelection();
d->updateFilter();
}
KUrl KFileWidget::selectedUrl() const
{
if ( d->inAccept )
return d->url;
else
return KUrl();
}
KUrl::List KFileWidget::selectedUrls() const
{
KUrl::List list;
if ( d->inAccept ) {
if ( (d->ops->mode() & KFile::Files) == KFile::Files )
list = d->parseSelectedUrls();
else
list.append( d->url );
}
return list;
}
KUrl::List& KFileWidgetPrivate::parseSelectedUrls()
{
if ( filenames.isEmpty() ) {
return urlList;
}
urlList.clear();
if ( filenames.contains( '/' )) { // assume _one_ absolute filename
static const QString &prot = KGlobal::staticQString(":/");
KUrl u;
if ( filenames.indexOf( prot ) != -1 )
u = filenames;
else
u.setPath( filenames );
if ( u.isValid() )
urlList.append( u );
else
KMessageBox::error( q,
i18n("The chosen filenames do not\n"
"appear to be valid."),
i18n("Invalid Filenames") );
}
else
urlList = tokenize( filenames );
filenames.clear(); // indicate that we parsed that one
return urlList;
}
// FIXME: current implementation drawback: a filename can't contain quotes
KUrl::List KFileWidgetPrivate::tokenize( const QString& line ) const
{
KUrl::List urls;
KUrl u( ops->url() );
QString name;
const int count = line.count( QLatin1Char( '"' ) );
if ( count == 0 ) { // no " " -> assume one single file
u.setFileName( line );
if ( u.isValid() )
urls.append( u );
return urls;
}
if ( (count % 2) == 1 ) { // odd number of " -> error
KMessageBox::sorry(q, i18n("The requested filenames\n"
"%1\n"
"do not appear to be valid;\n"
"make sure every filename is enclosed in double quotes.", line),
i18n("Filename Error"));
return urls;
}
int start = 0;
int index1 = -1, index2 = -1;
while ( true ) {
index1 = line.indexOf( '"', start );
index2 = line.indexOf( '"', index1 + 1 );
if ( index1 < 0 )
break;
// get everything between the " "
name = line.mid( index1 + 1, index2 - index1 - 1 );
u.setFileName( name );
if ( u.isValid() )
urls.append( u );
start = index2 + 1;
}
return urls;
}
QString KFileWidget::selectedFile() const
{
if ( d->inAccept ) {
const KUrl url = KIO::NetAccess::mostLocalUrl(d->url,topLevelWidget());
if (url.isLocalFile())
return url.path();
else {
KMessageBox::sorry( const_cast(this),
i18n("You can only select local files."),
i18n("Remote Files Not Accepted") );
}
}
return QString();
}
QStringList KFileWidget::selectedFiles() const
{
QStringList list;
if ( d->inAccept ) {
if ( (d->ops->mode() & KFile::Files) == KFile::Files ) {
KUrl::List urls = d->parseSelectedUrls();
QList::const_iterator it = urls.begin();
while ( it != urls.end() ) {
KUrl url = KIO::NetAccess::mostLocalUrl(*it,topLevelWidget());
if ( url.isLocalFile() )
list.append( url.path() );
++it;
}
}
else { // single-selection mode
if ( d->url.isLocalFile() )
list.append( d->url.path() );
}
}
return list;
}
KUrl KFileWidget::baseUrl() const
{
return d->ops->url();
}
void KFileWidget::showEvent(QShowEvent* event)
{
if ( !d->hasView ) { // delayed view-creation
d->ops->setView(KFile::Default);
d->ops->view()->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
d->ops->view()->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
d->hasView = true;
}
d->ops->clearHistory();
QList sizes = d->placesViewSplitter->sizes();
if (sizes.count() == 2) {
// restore width of speedbar
KConfigGroup configGroup( KGlobal::config(), ConfigGroup );
const int speedbarWidth = configGroup.readEntry( SpeedbarWidth, 100 );
const int availableWidth = sizes[0] + sizes[1];
sizes[0] = speedbarWidth;
sizes[1] = availableWidth - speedbarWidth;
d->placesViewSplitter->setSizes( sizes );
}
QWidget::showEvent(event);
}
void KFileWidget::setMode( KFile::Modes m )
{
d->ops->setMode(m);
if ( d->ops->dirOnlyMode() ) {
d->filterWidget->setDefaultFilter( i18n("*|All Folders") );
}
else {
d->filterWidget->setDefaultFilter( i18n("*|All Files") );
}
d->updateAutoSelectExtension();
}
KFile::Modes KFileWidget::mode() const
{
return d->ops->mode();
}
void KFileWidgetPrivate::readConfig( const KConfigGroup &configGroup)
{
ops->readConfig(configGroup);
KUrlComboBox *combo = urlNavigator->editor();
combo->setUrls( configGroup.readPathListEntry( RecentURLs ), KUrlComboBox::RemoveTop );
combo->setMaxItems( configGroup.readEntry( RecentURLsNumber,
DefaultRecentURLsNumber ) );
combo->setUrl( ops->url() );
autoDirectoryFollowing = configGroup.readEntry( AutoDirectoryFollowing,
DefaultDirectoryFollowing );
KGlobalSettings::Completion cm = (KGlobalSettings::Completion)
configGroup.readEntry( PathComboCompletionMode,
static_cast( KGlobalSettings::completionMode() ) );
if ( cm != KGlobalSettings::completionMode() )
combo->setCompletionMode( cm );
cm = (KGlobalSettings::Completion)
configGroup.readEntry( LocationComboCompletionMode,
static_cast( KGlobalSettings::completionMode() ) );
if ( cm != KGlobalSettings::completionMode() )
locationEdit->setCompletionMode( cm );
// show or don't show the speedbar
q->toggleSpeedbar( configGroup.readEntry( ShowSpeedbar, true ) );
// show or don't show the bookmarks
q->toggleBookmarks( configGroup.readEntry(ShowBookmarks, false) );
// does the user want Automatically Select Extension?
autoSelectExtChecked = configGroup.readEntry (AutoSelectExtChecked, DefaultAutoSelectExtChecked);
updateAutoSelectExtension();
// should the URL navigator use the breadcrumb navigation?
urlNavigator->setUrlEditable( !configGroup.readEntry(BreadcrumbNavigation, true) );
int w1 = q->minimumSize().width();
int w2 = toolbar->sizeHint().width() + 10;
if (w1 < w2)
q->setMinimumWidth(w2);
//restoreDialogSize( d->fileWidget->viewConfigGroup() );
}
void KFileWidgetPrivate::writeConfig(KConfigGroup &configGroup)
{
KUrlComboBox *pathCombo = urlNavigator->editor();
configGroup.writePathEntry( RecentURLs, pathCombo->urls() );
//saveDialogSize( configGroup, KConfigBase::Persistent | KConfigBase::Global );
configGroup.writeEntry( PathComboCompletionMode, static_cast(pathCombo->completionMode()) );
configGroup.writeEntry( LocationComboCompletionMode, static_cast(locationEdit->completionMode()) );
const bool showSpeedbar = placesView && !placesView->isHidden();
configGroup.writeEntry( ShowSpeedbar, showSpeedbar );
if (showSpeedbar) {
QList sizes = placesViewSplitter->sizes();
Q_ASSERT( sizes.count() > 0 );
configGroup.writeEntry( SpeedbarWidth, sizes[0] );
}
configGroup.writeEntry( ShowSpeedbar, placesView && !placesView->isHidden() );
configGroup.writeEntry( ShowBookmarks, bookmarkHandler != 0 );
configGroup.writeEntry( AutoSelectExtChecked, autoSelectExtChecked );
configGroup.writeEntry( BreadcrumbNavigation, !urlNavigator->isUrlEditable() );
ops->writeConfig(configGroup);
}
void KFileWidgetPrivate::readRecentFiles( KConfig *kc )
{
KConfigGroup cg( kc, ConfigGroup );
locationEdit->setMaxItems( cg.readEntry( RecentFilesNumber,
DefaultRecentURLsNumber ) );
locationEdit->setUrls( cg.readPathListEntry( RecentFiles ),
KUrlComboBox::RemoveBottom );
locationEdit->insertItem(0, QString()); // dummy item without pixmap
locationEdit->setCurrentIndex( 0 );
}
void KFileWidgetPrivate::saveRecentFiles( KConfig *kc )
{
KConfigGroup cg(kc, ConfigGroup );
cg.writePathEntry( RecentFiles, locationEdit->urls() );
}
KPushButton * KFileWidget::okButton() const
{
return d->okButton;
}
KPushButton * KFileWidget::cancelButton() const
{
return d->cancelButton;
}
// Called by KFileDialog
void KFileWidget::slotCancel()
{
d->ops->close();
KSharedConfig::Ptr config = KGlobal::config();
config->setForceGlobal( true );
KConfigGroup grp(config,ConfigGroup);
d->writeConfig(grp);
config->setForceGlobal( false );
}
void KFileWidget::setKeepLocation( bool keep )
{
d->keepLocation = keep;
}
bool KFileWidget::keepsLocation() const
{
return d->keepLocation;
}
void KFileWidget::setOperationMode( OperationMode mode )
{
d->operationMode = mode;
d->keepLocation = (mode == Saving);
d->filterWidget->setEditable( !d->hasDefaultFilter || mode != Saving );
if ( mode == Opening )
// don't use KStandardGuiItem::open() here which has trailing ellipsis!
d->okButton->setGuiItem( KGuiItem( i18n( "&Open" ), "document-open") );
else if ( mode == Saving ) {
d->okButton->setGuiItem( KStandardGuiItem::save() );
d->setNonExtSelection();
}
else
d->okButton->setGuiItem( KStandardGuiItem::ok() );
d->updateLocationWhatsThis();
d->updateAutoSelectExtension();
}
KFileWidget::OperationMode KFileWidget::operationMode() const
{
return d->operationMode;
}
void KFileWidget::slotAutoSelectExtClicked()
{
kDebug (kfile_area) << "slotAutoSelectExtClicked(): "
<< d->autoSelectExtCheckBox->isChecked() << endl;
// whether the _user_ wants it on/off
d->autoSelectExtChecked = d->autoSelectExtCheckBox->isChecked();
// update the current filename's extension
d->updateLocationEditExtension (d->extension /* extension hasn't changed */);
}
static QString getExtensionFromPatternList(const QStringList &patternList)
{
QString ret;
kDebug (kfile_area) << "\tgetExtension " << patternList;
QStringList::ConstIterator patternListEnd = patternList.end();
for (QStringList::ConstIterator it = patternList.begin();
it != patternListEnd;
++it)
{
kDebug (kfile_area) << "\t\ttry: \'" << (*it) << "\'";
// is this pattern like "*.BMP" rather than useless things like:
//
// README
// *.
// *.*
// *.JP*G
// *.JP?
if ((*it).startsWith ("*.") &&
(*it).length() > 2 &&
(*it).indexOf('*', 2) < 0 && (*it).indexOf ('?', 2) < 0)
{
ret = (*it).mid (1);
break;
}
}
return ret;
}
static QString stripUndisplayable (const QString &string)
{
QString ret = string;
ret.remove (':');
ret.remove ('&');
return ret;
}
//QString KFileWidget::currentFilterExtension()
//{
// return d->extension;
//}
void KFileWidgetPrivate::updateAutoSelectExtension()
{
if (!autoSelectExtCheckBox) return;
//
// Figure out an extension for the Automatically Select Extension thing
// (some Windows users apparently don't know what to do when confronted
// with a text file called "COPYING" but do know what to do with
// COPYING.txt ...)
//
kDebug (kfile_area) << "Figure out an extension: ";
QString lastExtension = extension;
extension.clear();
// Automatically Select Extension is only valid if the user is _saving_ a _file_
if ((operationMode == KFileWidget::Saving) && (ops->mode() & KFile::File))
{
//
// Get an extension from the filter
//
QString filter = filterWidget->currentFilter();
if (!filter.isEmpty())
{
// e.g. "*.cpp"
if (filter.indexOf ('/') < 0)
{
extension = getExtensionFromPatternList (filter.split(" ",QString::SkipEmptyParts)/*QStringList::split (" ", filter)*/).toLower();
kDebug (kfile_area) << "\tsetFilter-style: pattern ext=\'"
<< extension << "\'" << endl;
}
// e.g. "text/html"
else
{
KMimeType::Ptr mime = KMimeType::mimeType (filter);
if (mime)
{
// first try X-KDE-NativeExtension
QString nativeExtension = mime->property ("X-KDE-NativeExtension").toString();
if (!nativeExtension.isEmpty() && nativeExtension.at (0) == '.')
{
extension = nativeExtension.toLower();
kDebug (kfile_area) << "\tsetMimeFilter-style: native ext=\'"
<< extension << "\'" << endl;
}
// no X-KDE-NativeExtension
if (extension.isEmpty())
{
extension = getExtensionFromPatternList (mime->patterns()).toLower();
kDebug (kfile_area) << "\tsetMimeFilter-style: pattern ext=\'"
<< extension << "\'" << endl;
}
}
}
}
//
// GUI: checkbox
//
QString whatsThisExtension;
if (!extension.isEmpty())
{
// remember: sync any changes to the string with below
autoSelectExtCheckBox->setText (i18n ("Automatically select filename e&xtension (%1)", extension));
whatsThisExtension = i18n ("the extension %1", extension);
autoSelectExtCheckBox->setEnabled (true);
autoSelectExtCheckBox->setChecked (autoSelectExtChecked);
}
else
{
// remember: sync any changes to the string with above
autoSelectExtCheckBox->setText (i18n ("Automatically select filename e&xtension"));
whatsThisExtension = i18n ("a suitable extension");
autoSelectExtCheckBox->setChecked (false);
autoSelectExtCheckBox->setEnabled (false);
}
const QString locationLabelText = stripUndisplayable (locationLabel->text());
const QString filterLabelText = stripUndisplayable (filterLabel->text());
autoSelectExtCheckBox->setWhatsThis( "" +
i18n (
"This option enables some convenient features for "
"saving files with extensions:
"
""
"