diff options
Diffstat (limited to 'src')
41 files changed, 767 insertions, 138 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 624b30704..a914051ec 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,7 +6,7 @@ configure_file(config-nepomuk.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-nepomuk macro_bool_to_01(X11_Xrender_FOUND HAVE_XRENDER) configure_file(config-X11.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-X11.h ) -include_directories( ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} ) +include_directories( ${KACTIVITIES_INCLUDE_DIRS} ) if (Nepomuk_FOUND) # Yes, Soprano includes is what we need here @@ -132,6 +132,13 @@ set(dolphinpart_SRCS dolphinpart.cpp ) +# Add dolphinpart_ext.cpp conditionally, only with KDE > 4.9.1. +if (${KDE_VERSION} VERSION_GREATER "4.9.1") +set(dolphinpart_SRCS + ${dolphinpart_SRCS} + dolphinpart_ext.cpp) +endif (${KDE_VERSION} VERSION_GREATER "4.9.1") + kde4_add_plugin(dolphinpart ${dolphinpart_SRCS}) target_link_libraries(dolphinpart dolphinprivate konq ${KDE4_KPARTS_LIBS} ${KDE4_KFILE_LIBS}) @@ -235,6 +242,13 @@ if (Nepomuk_FOUND) ) endif (Nepomuk_FOUND) +if (KActivities_FOUND) + target_link_libraries( + kdeinit_dolphin + ${KACTIVITIES_LIBRARY} + ) +endif (KActivities_FOUND) + install(TARGETS kdeinit_dolphin ${INSTALL_TARGETS_DEFAULT_ARGS}) install(TARGETS dolphin ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/src/dolphinapplication.cpp b/src/dolphinapplication.cpp index 0cd51a454..8e83a8592 100644 --- a/src/dolphinapplication.cpp +++ b/src/dolphinapplication.cpp @@ -38,6 +38,16 @@ DolphinApplication::DolphinApplication() : KCmdLineArgs* args = KCmdLineArgs::parsedArgs(); + const int argsCount = args->count(); + + QList<KUrl> urls; + for (int i = 0; i < argsCount; ++i) { + const KUrl url = args->url(i); + if (url.isValid()) { + urls.append(url); + } + } + bool resetSplitSettings = false; if (args->isSet("split") && !GeneralSettings::splitView()) { // Dolphin should be opened with a split view although this is not @@ -45,31 +55,29 @@ DolphinApplication::DolphinApplication() : // all passed URLs have been opened. GeneralSettings::setSplitView(true); resetSplitSettings = true; - } - const int argsCount = args->count(); - if (argsCount > 0) { - QList<KUrl> urls; - for (int i = 0; i < argsCount; ++i) { - const KUrl url = args->url(i); - if (url.isValid()) { - urls.append(url); - } + // We need 2 URLs to open Dolphin in split view mode + if (urls.isEmpty()) { // No URL given - Open home URL in all two views + urls.append(GeneralSettings::homeUrl()); + urls.append(GeneralSettings::homeUrl()); + } else if (urls.length() == 1) { // Only 1 URL given - Open given URL in all two views + urls.append(urls.at(0)); } + } - if (!urls.isEmpty()) { - if (args->isSet("select")) { - m_mainWindow->openFiles(urls); - } else { - m_mainWindow->openDirectories(urls); - } + if (!urls.isEmpty()) { + if (args->isSet("select")) { + m_mainWindow->openFiles(urls); + } else { + m_mainWindow->openDirectories(urls); } } - args->clear(); if (resetSplitSettings) { GeneralSettings::setSplitView(false); } + + args->clear(); } DolphinApplication::~DolphinApplication() diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index f3d23d686..3bf3b3f55 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -1704,7 +1704,7 @@ void DolphinMainWindow::setupDockWidgets() connect(foldersPanel, SIGNAL(folderActivated(KUrl)), this, SLOT(changeUrl(KUrl))); connect(foldersPanel, SIGNAL(folderMiddleClicked(KUrl)), - this, SLOT(openNewActivatedTab(KUrl))); + this, SLOT(openNewTab(KUrl))); connect(foldersPanel, SIGNAL(errorMessage(QString)), this, SLOT(slotPanelErrorMessage(QString))); @@ -1756,13 +1756,15 @@ void DolphinMainWindow::setupDockWidgets() connect(placesPanel, SIGNAL(placeActivated(KUrl)), this, SLOT(changeUrl(KUrl))); connect(placesPanel, SIGNAL(placeMiddleClicked(KUrl)), - this, SLOT(openNewActivatedTab(KUrl))); + this, SLOT(openNewTab(KUrl))); connect(placesPanel, SIGNAL(errorMessage(QString)), this, SLOT(slotPanelErrorMessage(QString))); connect(this, SIGNAL(urlChanged(KUrl)), placesPanel, SLOT(setUrl(KUrl))); connect(placesDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotPlacesPanelVisibilityChanged(bool))); + connect(this, SIGNAL(settingsChanged()), + placesPanel, SLOT(readSettings())); // Add actions into the "Panels" menu KActionMenu* panelsMenu = new KActionMenu(i18nc("@action:inmenu View", "Panels"), this); @@ -1953,6 +1955,8 @@ void DolphinMainWindow::refreshViews() toggleSplitView(); } } + + emit settingsChanged(); } void DolphinMainWindow::clearStatusBar() diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h index ab79fb0e6..7da5801ff 100644 --- a/src/dolphinmainwindow.h +++ b/src/dolphinmainwindow.h @@ -151,6 +151,11 @@ signals: */ void requestItemInfo(const KFileItem& item); + /** + * Is emitted if the settings have been changed. + */ + void settingsChanged(); + protected: /** @see QWidget::showEvent() */ virtual void showEvent(QShowEvent* event); diff --git a/src/dolphinnewfilemenu.cpp b/src/dolphinnewfilemenu.cpp index 30d79c670..9d9baabe2 100644 --- a/src/dolphinnewfilemenu.cpp +++ b/src/dolphinnewfilemenu.cpp @@ -22,7 +22,6 @@ #include "dolphinmainwindow.h" #include "dolphinviewcontainer.h" -#include "statusbar/dolphinstatusbar.h" #include "views/dolphinnewfilemenuobserver.h" #include "views/dolphinview.h" diff --git a/src/dolphinpart.cpp b/src/dolphinpart.cpp index d1626e55d..ccc91fd7d 100644 --- a/src/dolphinpart.cpp +++ b/src/dolphinpart.cpp @@ -40,11 +40,18 @@ #include <KMenu> #include <KInputDialog> #include <KProtocolInfo> +#include <kdeversion.h> + +#if KDE_IS_VERSION(4, 9, 2) +#include "dolphinpart_ext.h" +#endif #include "views/dolphinview.h" #include "views/dolphinviewactionhandler.h" #include "views/dolphinnewfilemenuobserver.h" #include "views/dolphinremoteencoding.h" +#include "kitemviews/kfileitemmodel.h" +#include "kitemviews/private/kfileitemmodeldirlister.h" #include <QActionGroup> #include <QApplication> @@ -61,7 +68,6 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent, const QVariantL Q_UNUSED(args) setComponentData(DolphinPartFactory::componentData(), false); m_extension = new DolphinPartBrowserExtension(this); - new DolphinPartFileInfoExtension(this); // make sure that other apps using this part find Dolphin's view-file-columns icons KIconLoader::global()->addAppDir("dolphin"); @@ -116,6 +122,23 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent, const QVariantL connect(clipboard, SIGNAL(dataChanged()), this, SLOT(updatePasteAction())); + // Create file info and listing filter extensions. + // NOTE: Listing filter needs to be instantiated after the creation of the view. + new DolphinPartFileInfoExtension(this); + +#if KDE_IS_VERSION(4, 9, 2) + new DolphinPartListingFilterExtension(this); + + KDirLister* lister = m_view->m_model->m_dirLister; + if (lister) { + DolphinPartListingNotificationExtension* notifyExt = new DolphinPartListingNotificationExtension(this); + connect(lister, SIGNAL(newItems(KFileItemList)), notifyExt, SLOT(slotNewItems(KFileItemList))); + connect(lister, SIGNAL(itemsDeleted(KFileItemList)), notifyExt, SLOT(slotItemsDeleted(KFileItemList))); + } else { + kWarning() << "NULL KDirLister object! KParts::ListingNotificationExtension will NOT be supported"; + } +#endif + createActions(); m_actionHandler->updateViewActions(); slotSelectionChanged(KFileItemList()); // initially disable selection-dependent actions @@ -124,7 +147,6 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent, const QVariantL // (sort of spacial navigation) loadPlugins(this, this, componentData()); - } DolphinPart::~DolphinPart() @@ -554,7 +576,12 @@ void DolphinPart::createDirectory() void DolphinPart::setFilesToSelect(const KUrl::List& files) { + if (files.isEmpty()) { + return; + } + m_view->markUrlsAsSelected(files); + m_view->markUrlAsCurrent(files.at(0)); } //// diff --git a/src/dolphinpart_ext.cpp b/src/dolphinpart_ext.cpp new file mode 100644 index 000000000..e98c0648e --- /dev/null +++ b/src/dolphinpart_ext.cpp @@ -0,0 +1,107 @@ +/* This file is part of the KDE project + * Copyright (c) 2012 Dawit Alemayehu <[email protected]> + * + * 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 "dolphinpart_ext.h" + +#include "dolphinpart.h" +#include "views/dolphinview.h" + +#include <QVariant> + +#include <KFileItemList> + +DolphinPartListingFilterExtension::DolphinPartListingFilterExtension(DolphinPart* part) + : KParts::ListingFilterExtension(part) + , m_part(part) +{ +} + +KParts::ListingFilterExtension::FilterModes DolphinPartListingFilterExtension::supportedFilterModes() const +{ + return (KParts::ListingFilterExtension::MimeType | + KParts::ListingFilterExtension::SubString | + KParts::ListingFilterExtension::WildCard); +} + +bool DolphinPartListingFilterExtension::supportsMultipleFilters(KParts::ListingFilterExtension::FilterMode mode) const +{ + if (mode == KParts::ListingFilterExtension::MimeType) + return true; + + return false; +} + +QVariant DolphinPartListingFilterExtension::filter(KParts::ListingFilterExtension::FilterMode mode) const +{ + QVariant result; + + switch (mode) { + case KParts::ListingFilterExtension::MimeType: + result = m_part->view()->mimeTypeFilters(); + break; + case KParts::ListingFilterExtension::SubString: + case KParts::ListingFilterExtension::WildCard: + result = m_part->view()->nameFilter(); + break; + default: + break; + } + + return result; +} + +void DolphinPartListingFilterExtension::setFilter(KParts::ListingFilterExtension::FilterMode mode, const QVariant& filter) +{ + switch (mode) { + case KParts::ListingFilterExtension::MimeType: + m_part->view()->setMimeTypeFilters(filter.toStringList()); + break; + case KParts::ListingFilterExtension::SubString: + case KParts::ListingFilterExtension::WildCard: + m_part->view()->setNameFilter(filter.toString()); + break; + default: + break; + } +} + +//// + +DolphinPartListingNotificationExtension::DolphinPartListingNotificationExtension(DolphinPart* part) + : KParts::ListingNotificationExtension(part) +{ +} + +KParts::ListingNotificationExtension::NotificationEventTypes DolphinPartListingNotificationExtension::supportedNotificationEventTypes() const +{ + return (KParts::ListingNotificationExtension::ItemsAdded | + KParts::ListingNotificationExtension::ItemsDeleted); +} + +void DolphinPartListingNotificationExtension::slotNewItems(const KFileItemList& items) +{ + emit listingEvent(KParts::ListingNotificationExtension::ItemsAdded, items); +} + +void DolphinPartListingNotificationExtension::slotItemsDeleted(const KFileItemList& items) +{ + emit listingEvent(KParts::ListingNotificationExtension::ItemsDeleted, items); +} + +#include "dolphinpart_ext.moc" diff --git a/src/dolphinpart_ext.h b/src/dolphinpart_ext.h new file mode 100644 index 000000000..423e79efe --- /dev/null +++ b/src/dolphinpart_ext.h @@ -0,0 +1,56 @@ +/* This file is part of the KDE project + * Copyright (c) 2012 Dawit Alemayehu <[email protected]> + * + * 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 DOLPHINPART_EXT_H +#define DOLPHINPART_EXT_H + + +#include <kparts/listingextension.h> + +class DolphinPart; + +class DolphinPartListingFilterExtension : public KParts::ListingFilterExtension +{ + Q_OBJECT + +public: + DolphinPartListingFilterExtension(DolphinPart* part); + virtual FilterModes supportedFilterModes() const; + virtual bool supportsMultipleFilters(FilterMode mode) const; + virtual QVariant filter(FilterMode mode) const; + virtual void setFilter(FilterMode mode, const QVariant& filter); + +private: + DolphinPart* m_part; +}; + +class DolphinPartListingNotificationExtension : public KParts::ListingNotificationExtension +{ + Q_OBJECT + +public: + DolphinPartListingNotificationExtension(DolphinPart* part); + virtual NotificationEventTypes supportedNotificationEventTypes() const; + +public Q_SLOTS: + void slotNewItems(const KFileItemList&); + void slotItemsDeleted(const KFileItemList&); +}; + +#endif diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp index 31c82d606..8a566cffd 100644 --- a/src/dolphinviewcontainer.cpp +++ b/src/dolphinviewcontainer.cpp @@ -44,6 +44,10 @@ #include <KUrlNavigator> #include <KRun> +#ifdef KActivities_FOUND +#include <KActivities/ResourceInstance> +#endif + #include "dolphin_generalsettings.h" #include "filterbar/filterbar.h" #include "search/dolphinsearchbox.h" @@ -64,6 +68,9 @@ DolphinViewContainer::DolphinViewContainer(const KUrl& url, QWidget* parent) : m_statusBarTimer(0), m_statusBarTimestamp(), m_autoGrabFocus(true) +#ifdef KActivities_FOUND + , m_activityResourceInstance(0) +#endif { hide(); @@ -157,6 +164,14 @@ DolphinViewContainer::DolphinViewContainer(const KUrl& url, QWidget* parent) : m_topLayout->addWidget(m_statusBar); setSearchModeEnabled(isSearchUrl(url)); + + // Initialize kactivities resource instance + + #ifdef KActivities_FOUND + m_activityResourceInstance = new KActivities::ResourceInstance( + window()->winId(), url); + m_activityResourceInstance->setParent(this); + #endif } DolphinViewContainer::~DolphinViewContainer() @@ -172,6 +187,14 @@ void DolphinViewContainer::setActive(bool active) { m_urlNavigator->setActive(active); m_view->setActive(active); + + #ifdef KActivities_FOUND + if (active) { + m_activityResourceInstance->notifyFocusedIn(); + } else { + m_activityResourceInstance->notifyFocusedOut(); + } + #endif } bool DolphinViewContainer::isActive() const @@ -338,6 +361,10 @@ void DolphinViewContainer::setUrl(const KUrl& newUrl) if (newUrl != m_urlNavigator->locationUrl()) { m_urlNavigator->setLocationUrl(newUrl); } + + #ifdef KActivities_FOUND + m_activityResourceInstance->setUri(newUrl); + #endif } void DolphinViewContainer::setFilterBarVisible(bool visible) diff --git a/src/dolphinviewcontainer.h b/src/dolphinviewcontainer.h index fd52806d9..8a0309b0c 100644 --- a/src/dolphinviewcontainer.h +++ b/src/dolphinviewcontainer.h @@ -31,6 +31,13 @@ #include <QWidget> #include <views/dolphinview.h> +#include <config-apps.h> + +#ifdef KActivities_FOUND +namespace KActivities { + class ResourceInstance; +} +#endif class FilterBar; class KMessageWidget; @@ -308,6 +315,11 @@ private: QTimer* m_statusBarTimer; // Triggers a delayed update QElapsedTimer m_statusBarTimestamp; // Time in ms since last update bool m_autoGrabFocus; + +#ifdef KActivities_FOUND +private: + KActivities::ResourceInstance * m_activityResourceInstance; +#endif }; #endif // DOLPHINVIEWCONTAINER_H diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index f8302cfab..752bc9365 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -287,7 +287,7 @@ QString KFileItemModel::roleDescription(const QByteArray& role) const int count = 0; const RoleInfoMap* map = rolesInfoMap(count); for (int i = 0; i < count; ++i) { - description.insert(map[i].role, map[i].roleTranslation); + description.insert(map[i].role, i18nc(map[i].roleTranslationContext, map[i].roleTranslation)); } } @@ -508,46 +508,64 @@ void KFileItemModel::setNameFilter(const QString& nameFilter) { if (m_filter.pattern() != nameFilter) { dispatchPendingItemsToInsert(); - m_filter.setPattern(nameFilter); + applyFilters(); + } +} + +QString KFileItemModel::nameFilter() const +{ + return m_filter.pattern(); +} + +void KFileItemModel::setMimeTypeFilters(const QStringList& filters) +{ + if (m_filter.mimeTypes() != filters) { + dispatchPendingItemsToInsert(); + m_filter.setMimeTypes(filters); + applyFilters(); + } +} + +QStringList KFileItemModel::mimeTypeFilters() const +{ + return m_filter.mimeTypes(); +} + - // Check which shown items from m_itemData must get - // hidden and hence moved to m_filteredItems. - KFileItemList newFilteredItems; +void KFileItemModel::applyFilters() +{ + // Check which shown items from m_itemData must get + // hidden and hence moved to m_filteredItems. + KFileItemList newFilteredItems; - foreach (ItemData* itemData, m_itemData) { + foreach (ItemData* itemData, m_itemData) { + // Only filter non-expanded items as child items may never + // exist without a parent item + if (!itemData->values.value("isExpanded").toBool()) { if (!m_filter.matches(itemData->item)) { - // Only filter non-expanded items as child items may never - // exist without a parent item - if (!itemData->values.value("isExpanded").toBool()) { - newFilteredItems.append(itemData->item); - m_filteredItems.insert(itemData->item); - } + newFilteredItems.append(itemData->item); + m_filteredItems.insert(itemData->item); } } + } - removeItems(newFilteredItems); + removeItems(newFilteredItems); - // Check which hidden items from m_filteredItems should - // get visible again and hence removed from m_filteredItems. - KFileItemList newVisibleItems; + // Check which hidden items from m_filteredItems should + // get visible again and hence removed from m_filteredItems. + KFileItemList newVisibleItems; - QMutableSetIterator<KFileItem> it(m_filteredItems); - while (it.hasNext()) { - const KFileItem item = it.next(); - if (m_filter.matches(item)) { - newVisibleItems.append(item); - it.remove(); - } + QMutableSetIterator<KFileItem> it(m_filteredItems); + while (it.hasNext()) { + const KFileItem item = it.next(); + if (m_filter.matches(item)) { + newVisibleItems.append(item); + it.remove(); } - - insertItems(newVisibleItems); } -} -QString KFileItemModel::nameFilter() const -{ - return m_filter.pattern(); + insertItems(newVisibleItems); } QList<KFileItemModel::RoleInfo> KFileItemModel::rolesInformation() @@ -560,8 +578,15 @@ QList<KFileItemModel::RoleInfo> KFileItemModel::rolesInformation() if (map[i].roleType != NoRole) { RoleInfo info; info.role = map[i].role; - info.translation = map[i].roleTranslation; - info.group = map[i].groupTranslation; + info.translation = i18nc(map[i].roleTranslationContext, map[i].roleTranslation); + if (map[i].groupTranslation) { + info.group = i18nc(map[i].groupTranslationContext, map[i].groupTranslation); + } else { + // For top level roles, groupTranslation is 0. We must make sure that + // info.group is an empty string then because the code that generates + // menus tries to put the actions into sub menus otherwise. + info.group = QString(); + } info.requiresNepomuk = map[i].requiresNepomuk; info.requiresIndexer = map[i].requiresIndexer; rolesInfo.append(info); @@ -722,10 +747,10 @@ void KFileItemModel::slotNewItems(const KFileItemList& items) } } - if (m_filter.pattern().isEmpty()) { + if (!m_filter.hasSetFilters()) { m_pendingItemsToInsert.append(items); } else { - // The name-filter is active. Hide filtered items + // The name or type filter is active. Hide filtered items // before inserting them into the model and remember // the filtered items in m_filteredItems. KFileItemList filteredItems; diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index d9bebdf02..5bcebce24 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -179,6 +179,9 @@ public: void setNameFilter(const QString& nameFilter); QString nameFilter() const; + void setMimeTypeFilters(const QStringList& filters); + QStringList mimeTypeFilters() const; + struct RoleInfo { QByteArray role; QString translation; @@ -389,6 +392,11 @@ private: void emitSortProgress(int resolvedCount); /** + * Applies the filters set through @ref setNameFilter and @ref setMimeTypeFilters. + */ + void applyFilters(); + + /** * Maps the QByteArray-roles to RoleTypes and provides translation- and * group-contexts. */ @@ -467,6 +475,7 @@ private: friend class KFileItemModelRolesUpdater; // Accesses emitSortProgress() method friend class KFileItemModelTest; // For unit testing friend class KFileItemListViewTest; // For unit testing + friend class DolphinPart; // Accesses m_dirLister }; inline bool KFileItemModel::isChildItem(int index) const diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index c8e0094b5..c16488f9e 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -48,6 +48,8 @@ KItemListController::KItemListController(KItemModelBase* model, KItemListView* v m_selectionTogglePressed(false), m_clearSelectionIfItemsAreNotDragged(false), m_selectionBehavior(NoSelection), + m_autoActivationBehavior(ActivationAndExpansion), + m_mouseDoubleClickAction(ActivateItemOnly), m_model(0), m_view(0), m_selectionManager(new KItemListSelectionManager(this)), @@ -158,6 +160,26 @@ KItemListController::SelectionBehavior KItemListController::selectionBehavior() return m_selectionBehavior; } +void KItemListController::setAutoActivationBehavior(AutoActivationBehavior behavior) +{ + m_autoActivationBehavior = behavior; +} + +KItemListController::AutoActivationBehavior KItemListController::autoActivationBehavior() const +{ + return m_autoActivationBehavior; +} + +void KItemListController::setMouseDoubleClickAction(MouseDoubleClickAction action) +{ + m_mouseDoubleClickAction = action; +} + +KItemListController::MouseDoubleClickAction KItemListController::mouseDoubleClickAction() const +{ + return m_mouseDoubleClickAction; +} + void KItemListController::setAutoActivationDelay(int delay) { m_autoActivationTimer->setInterval(delay); @@ -468,11 +490,20 @@ void KItemListController::slotAutoActivationTimeout() return; } - if (m_model->supportsDropping(index)) { + /* m_view->isUnderMouse() fixes a bug in the Folder-View-Panel and in the + * Places-Panel. + * + * Bug: When you drag a file onto a Folder-View-Item or a Places-Item and + * then move away before the auto-activation timeout triggers, than the + * item still becomes activated/expanded. + * + * See Bug 293200 and 305783 + */ + if (m_model->supportsDropping(index) && m_view->isUnderMouse()) { if (m_view->supportsItemExpanding() && m_model->isExpandable(index)) { const bool expanded = m_model->isExpanded(index); m_model->setExpanded(index, !expanded); - } else { + } else if (m_autoActivationBehavior != ExpansionOnly) { emit itemActivated(index); } } @@ -745,6 +776,14 @@ bool KItemListController::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event, const QPointF pos = transform.map(event->pos()); const int index = m_view->itemAt(pos); + // Expand item if desired - See Bug 295573 + if (m_mouseDoubleClickAction != ActivateItemOnly) { + if (m_view && m_model && m_view->supportsItemExpanding() && m_model->isExpandable(index)) { + const bool expanded = m_model->isExpanded(index); + m_model->setExpanded(index, !expanded); + } + } + bool emitItemActivated = !m_singleClickActivation && (event->button() & Qt::LeftButton) && index >= 0 && index < m_model->count(); diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h index a88152622..235e4a9eb 100644 --- a/src/kitemviews/kitemlistcontroller.h +++ b/src/kitemviews/kitemlistcontroller.h @@ -64,6 +64,8 @@ class LIBDOLPHINPRIVATE_EXPORT KItemListController : public QObject Q_PROPERTY(KItemModelBase* model READ model WRITE setModel) Q_PROPERTY(KItemListView *view READ view WRITE setView) Q_PROPERTY(SelectionBehavior selectionBehavior READ selectionBehavior WRITE setSelectionBehavior) + Q_PROPERTY(AutoActivationBehavior autoActivationBehavior READ autoActivationBehavior WRITE setAutoActivationBehavior) + Q_PROPERTY(MouseDoubleClickAction mouseDoubleClickAction READ mouseDoubleClickAction WRITE setMouseDoubleClickAction) public: enum SelectionBehavior { @@ -72,6 +74,16 @@ public: MultiSelection }; + enum AutoActivationBehavior { + ActivationAndExpansion, + ExpansionOnly + }; + + enum MouseDoubleClickAction { + ActivateAndExpandItem, + ActivateItemOnly + }; + /** * @param model Model of the controller. The ownership is passed to the controller. * @param view View of the controller. The ownership is passed to the controller. @@ -91,6 +103,12 @@ public: void setSelectionBehavior(SelectionBehavior behavior); SelectionBehavior selectionBehavior() const; + void setAutoActivationBehavior(AutoActivationBehavior behavior); + AutoActivationBehavior autoActivationBehavior() const; + + void setMouseDoubleClickAction(MouseDoubleClickAction action); + MouseDoubleClickAction mouseDoubleClickAction() const; + /** * Sets the delay in milliseconds when dragging an object above an item * until the item gets activated automatically. A value of -1 indicates @@ -287,6 +305,8 @@ private: bool m_selectionTogglePressed; bool m_clearSelectionIfItemsAreNotDragged; SelectionBehavior m_selectionBehavior; + AutoActivationBehavior m_autoActivationBehavior; + MouseDoubleClickAction m_mouseDoubleClickAction; KItemModelBase* m_model; KItemListView* m_view; KItemListSelectionManager* m_selectionManager; diff --git a/src/kitemviews/kitemlistgroupheader.cpp b/src/kitemviews/kitemlistgroupheader.cpp index 576d20b88..17c95a97c 100644 --- a/src/kitemviews/kitemlistgroupheader.cpp +++ b/src/kitemviews/kitemlistgroupheader.cpp @@ -180,10 +180,10 @@ void KItemListGroupHeader::updateCache() // Calculate the role- and line-color. No alphablending is used for // performance reasons. - const QColor c1 = m_styleOption.palette.text().color(); - const QColor c2 = m_styleOption.palette.base().color(); + const QColor c1 = textColor(); + const QColor c2 = baseColor(); m_separatorColor = mixedColor(c1, c2, 10); - m_roleColor = mixedColor(c1, c2, 70); + m_roleColor = mixedColor(c1, c2, 60); const int padding = qMax(1, m_styleOption.padding); const int horizontalMargin = qMax(2, m_styleOption.horizontalMargin); @@ -211,4 +211,26 @@ QColor KItemListGroupHeader::mixedColor(const QColor& c1, const QColor& c2, int (c1.blue() * c1Percent + c2.blue() * c2Percent) / 100); } +QPalette::ColorRole KItemListGroupHeader::normalTextColorRole() const +{ + return QPalette::Text; +} + +QPalette::ColorRole KItemListGroupHeader::normalBaseColorRole() const +{ + return QPalette::Window; +} + +QColor KItemListGroupHeader::textColor() const +{ + const QPalette::ColorGroup group = isActiveWindow() ? QPalette::Active : QPalette::Inactive; + return styleOption().palette.color(group, normalTextColorRole()); +} + +QColor KItemListGroupHeader::baseColor() const +{ + const QPalette::ColorGroup group = isActiveWindow() ? QPalette::Active : QPalette::Inactive; + return styleOption().palette.color(group, normalBaseColorRole()); +} + #include "kitemlistgroupheader.moc" diff --git a/src/kitemviews/kitemlistgroupheader.h b/src/kitemviews/kitemlistgroupheader.h index e19ab4871..1e8ed2cca 100644 --- a/src/kitemviews/kitemlistgroupheader.h +++ b/src/kitemviews/kitemlistgroupheader.h @@ -104,11 +104,17 @@ protected: /** @reimp */ virtual void resizeEvent(QGraphicsSceneResizeEvent* event); + virtual QPalette::ColorRole normalTextColorRole() const; + virtual QPalette::ColorRole normalBaseColorRole() const; + private: void updateCache(); static QColor mixedColor(const QColor& c1, const QColor& c2, int c1Percent = 50); + QColor textColor() const; + QColor baseColor() const; + private: bool m_dirtyCache; QByteArray m_role; diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 69c5602c7..97c8a038b 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -68,6 +68,14 @@ QSizeF KStandardItemListWidgetInformant::itemSizeHint(int index, const KItemList const qreal maxWidth = itemWidth - 2 * option.padding; QTextLine line; + int emptyRolesCount = 0; + foreach (const QByteArray& role, view->visibleRoles()) { + const QString text = roleText(role, values); + if (role != "text" && role != "rating" && text.isEmpty()) { + emptyRolesCount++; + } + } + // Calculate the number of lines required for wrapping the name QTextOption textOption(Qt::AlignHCenter); textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); @@ -84,7 +92,7 @@ QSizeF KStandardItemListWidgetInformant::itemSizeHint(int index, const KItemList layout.endLayout(); // Add one line for each additional information - textHeight += additionalRolesCount * option.fontMetrics.lineSpacing(); + textHeight += (additionalRolesCount - emptyRolesCount) * option.fontMetrics.lineSpacing(); const qreal maxTextHeight = option.maxTextSize.height(); if (maxTextHeight > 0 && textHeight > maxTextHeight) { @@ -263,6 +271,16 @@ void KStandardItemListWidget::paint(QPainter* painter, const QStyleOptionGraphic painter->setFont(m_customizedFont); painter->setPen(m_isHidden ? m_additionalInfoTextColor : textColor()); const TextInfo* textInfo = m_textInfo.value("text"); + + if (!textInfo) { + // It seems that we can end up here even if m_textInfo does not contain + // the key "text", see bug 306167. According to triggerCacheRefreshing(), + // this can only happen if the index is negative. This can happen when + // the item is about to be removed, see KItemListView::slotItemsRemoved(). + // TODO: try to reproduce the crash and find a better fix. + return; + } + painter->drawStaticText(textInfo->pos, textInfo->staticText); bool clipAdditionalInfoBounds = false; @@ -464,7 +482,7 @@ QFont KStandardItemListWidget::customizedFont(const QFont& baseFont) const return baseFont; } -QPalette::ColorRole KStandardItemListWidget::normalTextColorPalette() const +QPalette::ColorRole KStandardItemListWidget::normalTextColorRole() const { return QPalette::Text; } @@ -485,8 +503,8 @@ QColor KStandardItemListWidget::textColor() const } const QPalette::ColorGroup group = isActiveWindow() ? QPalette::Active : QPalette::Inactive; - const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorPalette(); - return styleOption().palette.brush(group, role).color(); + const QPalette::ColorRole role = isSelected() ? QPalette::HighlightedText : normalTextColorRole(); + return styleOption().palette.color(group, role); } void KStandardItemListWidget::setOverlay(const QPixmap& overlay) @@ -594,6 +612,11 @@ void KStandardItemListWidget::editedRoleChanged(const QByteArray& current, const if (current.isEmpty() || !parent || current != "text") { if (m_roleEditor) { emit roleEditingCanceled(index(), current, data().value(current)); + + disconnect(m_roleEditor, SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)), + this, SLOT(slotRoleEditingCanceled(int,QByteArray,QVariant))); + disconnect(m_roleEditor, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)), + this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant))); m_roleEditor->deleteLater(); m_roleEditor = 0; } @@ -965,8 +988,17 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() qreal nameHeight = 0; QTextLine line; + int emptyRolesCount = 0; + foreach (const QByteArray& role, visibleRoles()) { + const QString text = roleText(role, values); + if (role != "text" && role != "rating" && text.isEmpty()) { + emptyRolesCount++; + } + } + const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0); - const int maxNameLines = (option.maxTextSize.height() / int(lineSpacing)) - additionalRolesCount; + const int maxNameLines = (option.maxTextSize.height() / int(lineSpacing)) - + (additionalRolesCount - emptyRolesCount); QTextLayout layout(nameTextInfo->staticText.text(), m_customizedFont); layout.setTextOption(nameTextInfo->staticText.textOption()); @@ -1000,7 +1032,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() nameTextInfo->staticText.setTextWidth(maxWidth); nameTextInfo->pos = QPointF(padding, widgetHeight - nameHeight - - additionalRolesCount * lineSpacing - + (additionalRolesCount - emptyRolesCount)* lineSpacing - padding); m_textRect = QRectF(padding + (maxWidth - nameWidth) / 2, nameTextInfo->pos.y(), @@ -1015,6 +1047,11 @@ void KStandardItemListWidget::updateIconsLayoutTextCache() } const QString text = roleText(role, values); + + if (role != "text" && role != "rating" && text.isEmpty()) { + continue; + } + TextInfo* textInfo = m_textInfo.value(role); textInfo->staticText.setText(text); @@ -1253,6 +1290,11 @@ void KStandardItemListWidget::closeRoleEditor() // to transfer the keyboard focus back to the KItemListContainer. scene()->views()[0]->parentWidget()->setFocus(); } + + disconnect(m_roleEditor, SIGNAL(roleEditingCanceled(int,QByteArray,QVariant)), + this, SLOT(slotRoleEditingCanceled(int,QByteArray,QVariant))); + disconnect(m_roleEditor, SIGNAL(roleEditingFinished(int,QByteArray,QVariant)), + this, SLOT(slotRoleEditingFinished(int,QByteArray,QVariant))); m_roleEditor->deleteLater(); m_roleEditor = 0; } diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h index 462d83d0f..787722ddd 100644 --- a/src/kitemviews/kstandarditemlistwidget.h +++ b/src/kitemviews/kstandarditemlistwidget.h @@ -120,7 +120,7 @@ protected: */ virtual QFont customizedFont(const QFont& baseFont) const; - virtual QPalette::ColorRole normalTextColorPalette() const; + virtual QPalette::ColorRole normalTextColorRole() const; void setTextColor(const QColor& color); QColor textColor() const; diff --git a/src/kitemviews/private/kfileitemmodelfilter.cpp b/src/kitemviews/private/kfileitemmodelfilter.cpp index 816d35634..2e320f2d9 100644 --- a/src/kitemviews/private/kfileitemmodelfilter.cpp +++ b/src/kitemviews/private/kfileitemmodelfilter.cpp @@ -23,6 +23,7 @@ #include <KFileItem> #include <QRegExp> + KFileItemModelFilter::KFileItemModelFilter() : m_useRegExp(false), m_regExp(0), @@ -61,11 +62,61 @@ QString KFileItemModelFilter::pattern() const return m_pattern; } +void KFileItemModelFilter::setMimeTypes(const QStringList& types) +{ + m_mimeTypes = types; +} + +QStringList KFileItemModelFilter::mimeTypes() const +{ + return m_mimeTypes; +} + +bool KFileItemModelFilter::hasSetFilters() const +{ + return (!m_pattern.isEmpty() || !m_mimeTypes.isEmpty()); +} + + bool KFileItemModelFilter::matches(const KFileItem& item) const { + const bool hasPatternFilter = !m_pattern.isEmpty(); + const bool hasMimeTypesFilter = !m_mimeTypes.isEmpty(); + + // If no filter is set, return true. + if (!hasPatternFilter && !hasMimeTypesFilter) { + return true; + } + + // If both filters are set, return true when both filters are matched + if (hasPatternFilter && hasMimeTypesFilter) { + return (matchesPattern(item) && matchesType(item)); + } + + // If only one filter is set, return true when that filter is matched + if (hasPatternFilter) { + return matchesPattern(item); + } + + return matchesType(item); +} + +bool KFileItemModelFilter::matchesPattern(const KFileItem& item) const +{ if (m_useRegExp) { return m_regExp->exactMatch(item.text()); } else { return item.text().toLower().contains(m_lowerCasePattern); } } + +bool KFileItemModelFilter::matchesType(const KFileItem& item) const +{ + foreach (const QString& mimeType, m_mimeTypes) { + if (item.mimetype() == mimeType) { + return true; + } + } + + return m_mimeTypes.isEmpty(); +} diff --git a/src/kitemviews/private/kfileitemmodelfilter.h b/src/kitemviews/private/kfileitemmodelfilter.h index 9bdf1fd95..e4fb0a2ee 100644 --- a/src/kitemviews/private/kfileitemmodelfilter.h +++ b/src/kitemviews/private/kfileitemmodelfilter.h @@ -22,7 +22,7 @@ #define KFILEITEMMODELFILTER_H #include <libdolphin_export.h> -#include <QString> +#include <QStringList> class KFileItem; class QRegExp; @@ -52,18 +52,41 @@ public: QString pattern() const; /** + * Set the list of mimetypes that are used for comparison with the + * item in KFileItemModelFilter::matchesMimeType. + */ + void setMimeTypes(const QStringList& types); + QStringList mimeTypes() const; + + /** + * @return True if either the pattern or mimetype filters has been set. + */ + bool hasSetFilters() const; + + /** * @return True if the item matches with the pattern defined by - * KFileItemModelFilter::setPattern(). + * @ref setPattern() or @ref setMimeTypes */ bool matches(const KFileItem& item) const; private: + /** + * @return True if item matches pattern set by @ref setPattern. + */ + bool matchesPattern(const KFileItem& item) const; + + /** + * @return True if item matches mimetypes set by @ref setMimeTypes. + */ + bool matchesType(const KFileItem& item) const; + bool m_useRegExp; // If true, m_regExp is used for filtering, // otherwise m_lowerCaseFilter is used. QRegExp* m_regExp; QString m_lowerCasePattern; // Lowercase version of m_filter for // faster comparison in matches(). - QString m_pattern; // Property set by setFilter(). + QString m_pattern; // Property set by setPattern(). + QStringList m_mimeTypes; // Property set by setMimeTypes() }; #endif diff --git a/src/kitemviews/private/knepomukrolesprovider.cpp b/src/kitemviews/private/knepomukrolesprovider.cpp index 0ae9b6bd3..b0e179807 100644 --- a/src/kitemviews/private/knepomukrolesprovider.cpp +++ b/src/kitemviews/private/knepomukrolesprovider.cpp @@ -108,13 +108,6 @@ QHash<QByteArray, QVariant> KNepomukRolesProvider::roleValues(const Nepomuk::Res } } - // Assure that empty values get replaced by "-" - foreach (const QByteArray& role, roles) { - if (m_roles.contains(role) && values.value(role).toString().isEmpty()) { - values.insert(role, QLatin1String("-")); - } - } - return values; } diff --git a/src/panels/folders/foldersitemlistwidget.cpp b/src/panels/folders/foldersitemlistwidget.cpp index 513059204..b4f9a5be8 100644 --- a/src/panels/folders/foldersitemlistwidget.cpp +++ b/src/panels/folders/foldersitemlistwidget.cpp @@ -28,7 +28,7 @@ FoldersItemListWidget::~FoldersItemListWidget() { } -QPalette::ColorRole FoldersItemListWidget::normalTextColorPalette() const +QPalette::ColorRole FoldersItemListWidget::normalTextColorRole() const { return QPalette::WindowText; } diff --git a/src/panels/folders/foldersitemlistwidget.h b/src/panels/folders/foldersitemlistwidget.h index fa7b143ae..08d41b829 100644 --- a/src/panels/folders/foldersitemlistwidget.h +++ b/src/panels/folders/foldersitemlistwidget.h @@ -34,7 +34,7 @@ public: virtual ~FoldersItemListWidget(); protected: - virtual QPalette::ColorRole normalTextColorPalette() const; + virtual QPalette::ColorRole normalTextColorRole() const; }; #endif diff --git a/src/panels/folders/folderspanel.cpp b/src/panels/folders/folderspanel.cpp index 0760200b6..13093fff6 100644 --- a/src/panels/folders/folderspanel.cpp +++ b/src/panels/folders/folderspanel.cpp @@ -140,6 +140,8 @@ void FoldersPanel::showEvent(QShowEvent* event) m_controller = new KItemListController(m_model, view, this); m_controller->setSelectionBehavior(KItemListController::SingleSelection); + m_controller->setAutoActivationBehavior(KItemListController::ExpansionOnly); + m_controller->setMouseDoubleClickAction(KItemListController::ActivateAndExpandItem); m_controller->setAutoActivationDelay(750); m_controller->setSingleClickActivation(true); diff --git a/src/panels/panel.cpp b/src/panels/panel.cpp index c2681ecfb..14b7c0230 100644 --- a/src/panels/panel.cpp +++ b/src/panels/panel.cpp @@ -71,4 +71,9 @@ void Panel::setUrl(const KUrl& url) } } +void Panel::readSettings() +{ + +} + #include "panel.moc" diff --git a/src/panels/panel.h b/src/panels/panel.h index 064e1f362..a0b25d6cc 100644 --- a/src/panels/panel.h +++ b/src/panels/panel.h @@ -60,6 +60,11 @@ public slots: */ void setUrl(const KUrl& url); + /** + * Refreshes the view to get synchronized with the settings. + */ + virtual void readSettings(); + protected: /** * Must be implemented by derived classes and is invoked when diff --git a/src/panels/places/placesitemlistgroupheader.cpp b/src/panels/places/placesitemlistgroupheader.cpp index 27d4c7917..ec7c4b18c 100644 --- a/src/panels/places/placesitemlistgroupheader.cpp +++ b/src/panels/places/placesitemlistgroupheader.cpp @@ -37,4 +37,9 @@ void PlacesItemListGroupHeader::paintSeparator(QPainter* painter, const QColor& Q_UNUSED(color); } +QPalette::ColorRole PlacesItemListGroupHeader::normalTextColorRole() const +{ + return QPalette::WindowText; +} + #include "placesitemlistgroupheader.moc" diff --git a/src/panels/places/placesitemlistgroupheader.h b/src/panels/places/placesitemlistgroupheader.h index fbcd116f1..1c2d5cc25 100644 --- a/src/panels/places/placesitemlistgroupheader.h +++ b/src/panels/places/placesitemlistgroupheader.h @@ -32,6 +32,8 @@ public: protected: virtual void paintSeparator(QPainter* painter, const QColor& color); + + virtual QPalette::ColorRole normalTextColorRole() const; }; #endif diff --git a/src/panels/places/placesitemlistwidget.cpp b/src/panels/places/placesitemlistwidget.cpp index 00f0fdab0..e33d1daf9 100644 --- a/src/panels/places/placesitemlistwidget.cpp +++ b/src/panels/places/placesitemlistwidget.cpp @@ -35,7 +35,7 @@ bool PlacesItemListWidget::isHidden() const return data().value("isHidden").toBool(); } -QPalette::ColorRole PlacesItemListWidget::normalTextColorPalette() const +QPalette::ColorRole PlacesItemListWidget::normalTextColorRole() const { return QPalette::WindowText; } diff --git a/src/panels/places/placesitemlistwidget.h b/src/panels/places/placesitemlistwidget.h index 93cd8f468..a2a88c1f0 100644 --- a/src/panels/places/placesitemlistwidget.h +++ b/src/panels/places/placesitemlistwidget.h @@ -36,7 +36,7 @@ public: protected: virtual bool isHidden() const; - virtual QPalette::ColorRole normalTextColorPalette() const; + virtual QPalette::ColorRole normalTextColorRole() const; }; #endif diff --git a/src/panels/places/placesitemmodel.cpp b/src/panels/places/placesitemmodel.cpp index 497901345..4770c6b10 100644 --- a/src/panels/places/placesitemmodel.cpp +++ b/src/panels/places/placesitemmodel.cpp @@ -54,7 +54,7 @@ #include <Nepomuk/ResourceManager> #include <Nepomuk/Query/ComparisonTerm> #include <Nepomuk/Query/LiteralTerm> - #include <Nepomuk/Query/Query> + #include <Nepomuk/Query/FileQuery> #include <Nepomuk/Query/ResourceTypeTerm> #include <Nepomuk/Vocabulary/NFO> #include <Nepomuk/Vocabulary/NIE> @@ -659,11 +659,22 @@ void PlacesItemModel::updateBookmarks() } if (!found) { - PlacesItem* item = new PlacesItem(newBookmark); - if (item->isHidden() && !m_hiddenItemsShown) { - m_bookmarkedItems.append(item); - } else { - appendItemToGroup(item); + const QString udi = newBookmark.metaDataItem("UDI"); + + /* + * See Bug 304878 + * Only add a new places item, if the item text is not empty + * and if the device is available. Fixes the strange behaviour - + * add a places item without text in the Places section - when you + * remove a device (e.g. a usb stick) without unmounting. + */ + if (udi.isEmpty() || Solid::Device(udi).isValid()) { + PlacesItem* item = new PlacesItem(newBookmark); + if (item->isHidden() && !m_hiddenItemsShown) { + m_bookmarkedItems.append(item); + } else { + appendItemToGroup(item); + } } } } @@ -885,8 +896,7 @@ void PlacesItemModel::createSystemBookmarks() Q_ASSERT(m_systemBookmarks.isEmpty()); Q_ASSERT(m_systemBookmarksIndexes.isEmpty()); - const QString timeLineIcon = "package_utility_time"; // TODO: Ask the Oxygen team to create - // a custom icon for the timeline-protocol + const QString timeLineIcon = "chronometer"; // Note: The context of the I18N_NOOP2 must be "KFile System Bookmarks". The real // i18nc call is done after reading the bookmark. The reason why the i18nc call is not @@ -1162,7 +1172,7 @@ KUrl PlacesItemModel::createSearchUrl(const KUrl& url) #ifdef HAVE_NEPOMUK KUrl PlacesItemModel::searchUrlForTerm(const Nepomuk::Query::Term& term) { - const Nepomuk::Query::Query query(term); + const Nepomuk::Query::FileQuery query(term); return query.toSearchUrl(); } #endif diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp index 429c5399a..e483f9b83 100644 --- a/src/panels/places/placespanel.cpp +++ b/src/panels/places/placespanel.cpp @@ -23,6 +23,8 @@ #include "placespanel.h" +#include "dolphin_generalsettings.h" + #include <KDebug> #include <KDirNotify> #include <KIcon> @@ -52,7 +54,10 @@ PlacesPanel::PlacesPanel(QWidget* parent) : m_controller(0), m_model(0), m_storageSetupFailedUrl(), - m_triggerStorageSetupButton() + m_triggerStorageSetupButton(), + m_itemDropEventIndex(-1), + m_itemDropEventMimeData(0), + m_itemDropEvent(0) { } @@ -62,9 +67,27 @@ PlacesPanel::~PlacesPanel() bool PlacesPanel::urlChanged() { + if (!url().isValid() || url().protocol().contains("search")) { + // Skip results shown by a search, as possible identical + // directory names are useless without parent-path information. + return false; + } + + if (m_controller) { + selectClosestItem(); + } + return true; } +void PlacesPanel::readSettings() +{ + if (m_controller) { + const int delay = GeneralSettings::autoExpandFolders() ? 750 : -1; + m_controller->setAutoActivationDelay(delay); + } +} + void PlacesPanel::showEvent(QShowEvent* event) { if (event->spontaneous()) { @@ -88,6 +111,9 @@ void PlacesPanel::showEvent(QShowEvent* event) m_controller = new KItemListController(m_model, view, this); m_controller->setSelectionBehavior(KItemListController::SingleSelection); m_controller->setSingleClickActivation(true); + + readSettings(); + connect(m_controller, SIGNAL(itemActivated(int)), this, SLOT(slotItemActivated(int))); connect(m_controller, SIGNAL(itemMiddleClicked(int)), this, SLOT(slotItemMiddleClicked(int))); connect(m_controller, SIGNAL(itemContextMenuRequested(int,QPointF)), this, SLOT(slotItemContextMenuRequested(int,QPointF))); @@ -258,6 +284,30 @@ void PlacesPanel::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* even return; } + if (m_model->storageSetupNeeded(index)) { + connect(m_model, SIGNAL(storageSetupDone(int,bool)), + this, SLOT(slotItemDropEventStorageSetupDone(int,bool))); + + m_itemDropEventIndex = index; + + // Make a full copy of the Mime-Data + m_itemDropEventMimeData = new QMimeData; + m_itemDropEventMimeData->setText(event->mimeData()->text()); + m_itemDropEventMimeData->setHtml(event->mimeData()->html()); + m_itemDropEventMimeData->setUrls(event->mimeData()->urls()); + m_itemDropEventMimeData->setImageData(event->mimeData()->imageData()); + m_itemDropEventMimeData->setColorData(event->mimeData()->colorData()); + + m_itemDropEvent = new QDropEvent(event->pos().toPoint(), + event->possibleActions(), + m_itemDropEventMimeData, + event->buttons(), + event->modifiers()); + + m_model->requestStorageSetup(index); + return; + } + KUrl destUrl = m_model->placesItem(index)->url(); QDropEvent dropEvent(event->pos().toPoint(), event->possibleActions(), @@ -268,6 +318,27 @@ void PlacesPanel::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* even DragAndDropHelper::dropUrls(KFileItem(), destUrl, &dropEvent); } +void PlacesPanel::slotItemDropEventStorageSetupDone(int index, bool success) +{ + disconnect(m_model, SIGNAL(storageSetupDone(int,bool)), + this, SLOT(slotItemDropEventStorageSetupDone(int,bool))); + + if ((index == m_itemDropEventIndex) && m_itemDropEvent && m_itemDropEventMimeData) { + if (success) { + KUrl destUrl = m_model->placesItem(index)->url(); + + DragAndDropHelper::dropUrls(KFileItem(), destUrl, m_itemDropEvent); + } + + delete m_itemDropEventMimeData; + delete m_itemDropEvent; + + m_itemDropEventIndex = -1; + m_itemDropEventMimeData = 0; + m_itemDropEvent = 0; + } +} + void PlacesPanel::slotAboveItemDropEvent(int index, QGraphicsSceneDragDropEvent* event) { m_model->dropMimeDataBefore(index, event->mimeData()); diff --git a/src/panels/places/placespanel.h b/src/panels/places/placespanel.h index 8a84e00a0..7951cdd9c 100644 --- a/src/panels/places/placespanel.h +++ b/src/panels/places/placespanel.h @@ -50,12 +50,16 @@ protected: virtual bool urlChanged(); virtual void showEvent(QShowEvent* event); +public slots: + virtual void readSettings(); + private slots: void slotItemActivated(int index); void slotItemMiddleClicked(int index); void slotItemContextMenuRequested(int index, const QPointF& pos); void slotViewContextMenuRequested(const QPointF& pos); void slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* event); + void slotItemDropEventStorageSetupDone(int index, bool success); void slotAboveItemDropEvent(int index, QGraphicsSceneDragDropEvent* event); void slotUrlsDropped(const KUrl& dest, QDropEvent* event, QWidget* parent); void slotTrashUpdated(KJob* job); @@ -80,6 +84,10 @@ private: KUrl m_storageSetupFailedUrl; Qt::MouseButton m_triggerStorageSetupButton; + + int m_itemDropEventIndex; + QMimeData* m_itemDropEventMimeData; + QDropEvent* m_itemDropEvent; }; #endif // PLACESPANEL_H diff --git a/src/panels/terminal/terminalpanel.cpp b/src/panels/terminal/terminalpanel.cpp index 889c07e45..f6d3a5981 100644 --- a/src/panels/terminal/terminalpanel.cpp +++ b/src/panels/terminal/terminalpanel.cpp @@ -159,6 +159,7 @@ void TerminalPanel::sendCdToTerminal(const QString& dir) } m_terminal->sendInput(" cd " + KShell::quoteArg(dir) + '\n'); + m_konsolePartCurrentDirectory = dir; if (m_clearTerminal) { m_terminal->sendInput(" clear\n"); diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp index 28f1f1af5..6f1c736b0 100644 --- a/src/search/dolphinsearchbox.cpp +++ b/src/search/dolphinsearchbox.cpp @@ -239,10 +239,9 @@ void DolphinSearchBox::slotReturnPressed(const QString& text) void DolphinSearchBox::slotFacetsButtonToggled() { - const bool visible = !m_facetsWidget->isVisible(); - m_facetsWidget->setVisible(visible); - SearchSettings::setShowFacetsWidget(visible); - updateFacetsToggleButtonIcon(); + const bool facetsIsVisible = !m_facetsWidget->isVisible(); + m_facetsWidget->setVisible(facetsIsVisible); + updateFacetsToggleButton(); } void DolphinSearchBox::slotFacetChanged() @@ -281,6 +280,7 @@ void DolphinSearchBox::saveSettings() { SearchSettings::setLocation(m_fromHereButton->isChecked() ? "FromHere" : "Everywhere"); SearchSettings::setWhat(m_fileNameButton->isChecked() ? "FileName" : "Content"); + SearchSettings::setShowFacetsWidget(m_facetsToggleButton->isChecked()); SearchSettings::self()->writeConfig(); } @@ -343,7 +343,8 @@ void DolphinSearchBox::init() // Create "Facets" widgets m_facetsToggleButton = new QToolButton(this); - m_facetsToggleButton->setAutoRaise(true); + m_facetsToggleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + initButton(m_facetsToggleButton); connect(m_facetsToggleButton, SIGNAL(clicked()), this, SLOT(slotFacetsButtonToggled())); m_facetsWidget = new DolphinFacetsWidget(this); @@ -390,7 +391,7 @@ void DolphinSearchBox::init() m_startSearchTimer->setInterval(1000); connect(m_startSearchTimer, SIGNAL(timeout()), this, SLOT(emitSearchRequest())); - updateFacetsToggleButtonIcon(); + updateFacetsToggleButton(); applyReadOnlyState(); } @@ -467,10 +468,12 @@ void DolphinSearchBox::applyReadOnlyState() } } -void DolphinSearchBox::updateFacetsToggleButtonIcon() +void DolphinSearchBox::updateFacetsToggleButton() { - const bool visible = SearchSettings::showFacetsWidget(); - m_facetsToggleButton->setIcon(KIcon(visible ? "list-remove" : "list-add")); + const bool facetsIsVisible = SearchSettings::showFacetsWidget(); + m_facetsToggleButton->setChecked(facetsIsVisible ? true : false); + m_facetsToggleButton->setIcon(KIcon(facetsIsVisible ? "arrow-up-double" : "arrow-down-double")); + m_facetsToggleButton->setText(facetsIsVisible ? i18nc("action:button", "Less Options") : i18nc("action:button", "More Options")); } #include "dolphinsearchbox.moc" diff --git a/src/search/dolphinsearchbox.h b/src/search/dolphinsearchbox.h index ee9987a38..f3cc535d6 100644 --- a/src/search/dolphinsearchbox.h +++ b/src/search/dolphinsearchbox.h @@ -133,8 +133,7 @@ private: void applyReadOnlyState(); - void updateFacetsToggleButtonIcon(); - + void updateFacetsToggleButton(); private: bool m_startedSearching; bool m_readOnly; diff --git a/src/settings/dolphin_generalsettings.kcfg b/src/settings/dolphin_generalsettings.kcfg index 9f261dc5f..050750199 100644 --- a/src/settings/dolphin_generalsettings.kcfg +++ b/src/settings/dolphin_generalsettings.kcfg @@ -52,6 +52,10 @@ <label>Ask for confirmation when closing windows with multiple tabs.</label> <default>true</default> </entry> + <entry name="RenameInline" type="Bool"> + <label>Rename inline</label> + <default>true</default> + </entry> <entry name="ShowSelectionToggle" type="Bool"> <label>Show selection toggle</label> <default>true</default> diff --git a/src/views/dolphinfileitemlistwidget.cpp b/src/views/dolphinfileitemlistwidget.cpp index 43030c634..33ee6a277 100644 --- a/src/views/dolphinfileitemlistwidget.cpp +++ b/src/views/dolphinfileitemlistwidget.cpp @@ -115,6 +115,8 @@ QPixmap DolphinFileItemListWidget::overlayForState(KVersionControlPlugin2::ItemV iconName = "vcs-conflicting"; break; case KVersionControlPlugin::UnversionedVersion: + case KVersionControlPlugin2::IgnoredVersion: + case KVersionControlPlugin2::MissingVersion: break; default: Q_ASSERT(false); diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index 233c7007a..05849729f 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -98,8 +98,8 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) : m_toolTipManager(0), m_selectionChangedTimer(0), m_currentItemUrl(), + m_scrollToCurrentItem(false), m_restoredContentsPosition(), - m_createdItemUrl(), m_selectedUrls(), m_versionControlObserver(0) { @@ -363,6 +363,7 @@ void DolphinView::markUrlsAsSelected(const QList<KUrl>& urls) void DolphinView::markUrlAsCurrent(const KUrl& url) { m_currentItemUrl = url; + m_scrollToCurrentItem = true; } void DolphinView::selectItems(const QRegExp& pattern, bool enabled) @@ -509,6 +510,16 @@ QString DolphinView::nameFilter() const return m_model->nameFilter(); } +void DolphinView::setMimeTypeFilters(const QStringList& filters) +{ + return m_model->setMimeTypeFilters(filters); +} + +QStringList DolphinView::mimeTypeFilters() const +{ + return m_model->mimeTypeFilters(); +} + QString DolphinView::statusBarText() const { QString summary; @@ -624,7 +635,7 @@ void DolphinView::renameSelectedItems() return; } - if (items.count() == 1) { + if (items.count() == 1 && GeneralSettings::renameInline()) { const int index = m_model->index(items.first()); m_view->editRole(index, "text"); } else { @@ -742,6 +753,20 @@ void DolphinView::hideEvent(QHideEvent* event) QWidget::hideEvent(event); } +bool DolphinView::event(QEvent* event) +{ + /* See Bug 297355 + * Dolphin leaves file preview tooltips open even when is not visible. + * + * Hide tool-tip when Dolphin loses focus. + */ + if (event->type() == QEvent::WindowDeactivate) { + hideToolTip(); + } + + return QWidget::event(event); +} + void DolphinView::activate() { setActive(true); @@ -1150,25 +1175,8 @@ QString DolphinView::viewPropertiesContext() const void DolphinView::observeCreatedItem(const KUrl& url) { - m_createdItemUrl = url; - connect(m_model, SIGNAL(directoryLoadingCompleted()), - this, SLOT(selectAndScrollToCreatedItem())); -} - -void DolphinView::selectAndScrollToCreatedItem() -{ - KItemListSelectionManager* selectionManager = m_container->controller()->selectionManager(); - const int index = m_model->index(m_createdItemUrl); - if (index != -1) { - selectionManager->setCurrentItem(index); - selectionManager->clearSelection(); - selectionManager->setSelected(index); - m_view->scrollToItem(index); - } - - disconnect(m_model, SIGNAL(directoryLoadingCompleted()), - this, SLOT(selectAndScrollToCreatedItem())); - m_createdItemUrl = KUrl(); + markUrlAsCurrent(url); + markUrlsAsSelected(QList<KUrl>() << url); } void DolphinView::slotDirectoryRedirection(const KUrl& oldUrl, const KUrl& newUrl) @@ -1186,6 +1194,12 @@ void DolphinView::updateViewState() const int currentIndex = m_model->index(m_currentItemUrl); if (currentIndex != -1) { selectionManager->setCurrentItem(currentIndex); + + // scroll to current item and reset the state + if (m_scrollToCurrentItem) { + m_view->scrollToItem(currentIndex); + m_scrollToCurrentItem = false; + } } else { selectionManager->setCurrentItem(0); } @@ -1329,6 +1343,10 @@ void DolphinView::slotVisibleRolesChangedByHeader(const QList<QByteArray>& curre void DolphinView::slotRoleEditingFinished(int index, const QByteArray& role, const QVariant& value) { + if (index < 0 || index >= m_model->count()) { + return; + } + if (role == "text") { const KFileItem oldItem = m_model->fileItem(index); const QString newName = value.toString(); diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h index 1ad4d6c82..7d8e8b76a 100644 --- a/src/views/dolphinview.h +++ b/src/views/dolphinview.h @@ -181,8 +181,8 @@ public: void markUrlsAsSelected(const QList<KUrl>& urls); /** - * Marks the item indicated by \p url as the current item after the - * directory DolphinView::url() has been loaded. + * Marks the item indicated by \p url to be scrolled to and as the + * current item after directory DolphinView::url() has been loaded. */ void markUrlAsCurrent(const KUrl& url); @@ -238,6 +238,14 @@ public: QString nameFilter() const; /** + * Filters the currently shown items by \a filters. All items + * whose content-type matches those given by the list of filters + * will be shown. + */ + void setMimeTypeFilters(const QStringList& filters); + QStringList mimeTypeFilters() const; + + /** * Returns a textual representation of the state of the current * folder or selected items, suitable for use in the status bar. */ @@ -524,6 +532,7 @@ protected: /** @reimp */ virtual void hideEvent(QHideEvent* event); + virtual bool event(QEvent* event); private slots: /** @@ -640,18 +649,10 @@ private slots: * Observes the item with the URL \a url. As soon as the directory * model indicates that the item is available, the item will * get selected and it is assured that the item stays visible. - * - * @see selectAndScrollToCreatedItem() */ void observeCreatedItem(const KUrl& url); /** - * Selects and scrolls to the item that got observed - * by observeCreatedItem(). - */ - void selectAndScrollToCreatedItem(); - - /** * Called when a redirection happens. * Testcase: fish://localhost */ @@ -754,8 +755,8 @@ private: QTimer* m_selectionChangedTimer; KUrl m_currentItemUrl; // Used for making the view to remember the current URL after F5 + bool m_scrollToCurrentItem; // Used for marking we need to scroll to current item or not QPoint m_restoredContentsPosition; - KUrl m_createdItemUrl; // URL for a new item that got created by the "Create New..." menu QList<KUrl> m_selectedUrls; // Used for making the view to remember selections after F5 @@ -764,6 +765,7 @@ private: // For unit tests friend class TestBase; friend class DolphinDetailsViewTest; + friend class DolphinPart; // Accesses m_model }; /// Allow using DolphinView::Mode in QVariant diff --git a/src/views/draganddrophelper.cpp b/src/views/draganddrophelper.cpp index 45e5076f6..f81d4d0bf 100644 --- a/src/views/draganddrophelper.cpp +++ b/src/views/draganddrophelper.cpp @@ -35,10 +35,13 @@ QString DragAndDropHelper::dropUrls(const KFileItem& destItem, const KUrl& destU } const QMimeData* mimeData = event->mimeData(); - if (mimeData->hasFormat("application/x-kde-dndextract")) { - const QString remoteDBusClient = mimeData->data("application/x-kde-dndextract"); - QDBusMessage message = QDBusMessage::createMethodCall(remoteDBusClient, "/DndExtract", - "org.kde.DndExtract", "extractSelectedFilesTo"); + if (mimeData->hasFormat("application/x-kde-ark-dndextract-service") && + mimeData->hasFormat("application/x-kde-ark-dndextract-path")) { + const QString remoteDBusClient = mimeData->data("application/x-kde-ark-dndextract-service"); + const QString remoteDBusPath = mimeData->data("application/x-kde-ark-dndextract-path"); + + QDBusMessage message = QDBusMessage::createMethodCall(remoteDBusClient, remoteDBusPath, + "org.kde.ark.DndExtract", "extractSelectedFilesTo"); message.setArguments(QVariantList() << destUrl.pathOrUrl()); QDBusConnection::sessionBus().call(message); } else if (!destItem.isNull() && (destItem.isDir() || destItem.isDesktopFile())) { |
