Factorize all the view-related action handling to DolphinViewActionHandler, to remove code duplication between mainwindow and part, and to remove my code-splitting with the static createFooAction methods in the view.
svn path=/trunk/KDE/kdebase/apps/; revision=773572
add_subdirectory( pics )
add_subdirectory( tests )
+macro_optional_find_package(Soprano)
+
include_directories( ${KDE4_INCLUDE_DIR} ${QT_INCLUDES} ${BLITZ_INCLUDES} )
if (Soprano_FOUND)
include_directories( ${SOPRANO_INCLUDE_DIR} )
dolphiniconsview.cpp
dolphincolumnview.cpp
dolphincolumnwidget.cpp
+ dolphindropcontroller.cpp
+ dolphinsortfilterproxymodel.cpp
draganddrophelper.cpp
- kcategorizedview.cpp
- kcategorydrawer.cpp
dolphinmodel.cpp
dolphinsettings.cpp
dolphincategorydrawer.cpp
- viewproperties.cpp
- dolphinsortfilterproxymodel.cpp
- renamedialog.cpp
dolphinview.cpp
dolphinviewactionhandler.cpp
+ iconmanager.cpp
ratingpainter.cpp
- dolphindropcontroller.cpp
+ renamedialog.cpp
+ selectiontoggle.cpp
+ selectionmanager.cpp
+ viewproperties.cpp
)
kde4_add_kcfg_files(dolphinprivate_LIB_SRCS
dolphinstatusbar.cpp
dolphindirlister.cpp
dolphincontextmenu.cpp
+ dolphinfileplacesview.cpp
dolphinsettingsdialog.cpp
draganddrophelper.cpp
filterbar.cpp
pixmapviewer.cpp
settingspagebase.cpp
sidebarpage.cpp
+ startupsettingspage.cpp
statusbarspaceinfo.cpp
statusbarmessagelabel.cpp
terminalsidebarpage.cpp
Name=Dolphin
Name[ar]=الدولفين
Name[hi]=डॉल्फ़िन
+Name[kn]=ಡಾಲ್ಫಿನ್
Name[ne]=डल्फिन
Name[pa]=ਡਾਲਫਿਨ
Name[sr]=Делфин
GenericName[da]=Filhåndtering
GenericName[de]=Dateimanager
GenericName[el]=Διαχειριστής αρχείων
+GenericName[eo]=Dosieradministrilo
GenericName[es]=Gestor de archivos
GenericName[et]=Failihaldur
GenericName[eu]=Fitxategi kudeatzailea
GenericName[ja]=ファイルマネージャ
GenericName[kk]=Файл менеджері
GenericName[km]=កម្មវិធីគ្រប់គ្រងឯកសារ
+GenericName[kn]=ಕಡತ ವ್ಯವಸ್ಥಾಪಕ
GenericName[ko]=파일 관리자
GenericName[ku]=Rêveberê Pelan
GenericName[lv]=Failu pārvaldnieks
GenericName[pl]=Menedżer plików
GenericName[pt]=Gestor de Ficheiros
GenericName[pt_BR]=Gerenciador de Arquivos
+GenericName[ro]=Manager de fişiere
GenericName[ru]=Файловый менеджер
GenericName[se]=Fiilagieđahalli
GenericName[sl]=Upravitelj datotek
<label context="@label">Should the view properties used for all directories</label>
<default>false</default>
</entry>
+ <entry name="BrowseThroughArchives" type="Bool">
+ <label context="@label">Browse through archives</label>
+ <default>false</default>
+ </entry>
+ <entry name="ShowSelectionToggle" type="Bool">
+ <label context="@label">Show selection toggle</label>
+ <default>true</default>
+ </entry>
<entry name="ViewPropsTimestamp" type="DateTime" >
<label context="@label">Timestamp since when the view properties are valid</label>
</entry>
void DolphinCategoryDrawer::drawCategory(const QModelIndex &index, int sortRole,
const QStyleOption &option, QPainter *painter) const
{
+ Q_UNUSED(sortRole);
+
QRect starRect = option.rect;
int iconSize = KIconLoader::global()->currentSize(KIconLoader::Small);
#ifndef DOLPHINCATEGORYDRAWER_H
#define DOLPHINCATEGORYDRAWER_H
-#include "kcategorydrawer.h"
+#include <kcategorydrawer.h>
#include <QStyleOption>
#include <QModelIndex>
{
ColumnModeSettings* settings = DolphinSettings::instance().columnModeSettings();
const int iconSize = settings->iconSize();
+ const QSize size(iconSize, iconSize);
+ setIconSize(size);
foreach (QObject* object, viewport()->children()) {
if (object->inherits("QListView")) {
DolphinColumnWidget* widget = static_cast<DolphinColumnWidget*>(object);
- widget->setDecorationSize(QSize(iconSize, iconSize));
+ widget->setDecorationSize(size);
}
}
m_active = active;
// dim the background of the viewport
- QPalette palette;
- palette.setColor(viewport()->backgroundRole(), QColor(0, 0, 0, 0));
+ const QPalette::ColorRole role = viewport()->backgroundRole();
+ QColor background = viewport()->palette().color(role);
+ background.setAlpha(0); // make background transparent
+
+ QPalette palette = viewport()->palette();
+ palette.setColor(role, background);
viewport()->setPalette(palette);
foreach (DolphinColumnWidget* column, m_columns) {
} else {
m_animation->setFrameRange(-m_contentX, -newContentX);
}
- if(m_animation->state() != QTimeLine::Running)
+ if (m_animation->state() != QTimeLine::Running) {
m_animation->start();
+ }
} else if (x < 0) {
const int newContentX = m_contentX - x;
if (isRightToLeft()) {
} else {
m_animation->setFrameRange(-m_contentX, -newContentX);
}
- if(m_animation->state() != QTimeLine::Running)
+ if (m_animation->state() != QTimeLine::Running) {
m_animation->start();
+ }
}
}
#include "dolphinsortfilterproxymodel.h"
#include "dolphinsettings.h"
#include "dolphin_columnmodesettings.h"
+#include "dolphin_generalsettings.h"
#include "draganddrophelper.h"
+#include "selectionmanager.h"
#include <kcolorscheme.h>
#include <kdirlister.h>
#include <kmimetyperesolver.h>
#include <konqmimedata.h>
+#include "iconmanager.h"
+
#include <QApplication>
#include <QClipboard>
#include <QPainter>
const KUrl& url) :
QListView(parent),
m_active(true),
- m_showPreview(false),
m_view(columnView),
m_url(url),
m_childUrl(),
m_dirLister(0),
m_dolphinModel(0),
m_proxyModel(0),
- m_previewJob(0),
+ m_iconManager(0),
m_dragging(false),
m_dropRect()
{
m_font.setBold(settings->boldFont());
const int iconSize = settings->iconSize();
- m_decorationSize = QSize(iconSize, iconSize);
+ setDecorationSize(QSize(iconSize, iconSize));
KFileItemDelegate* delegate = new KFileItemDelegate(this);
setItemDelegate(delegate);
m_dirLister->setDelayedMimeTypes(true);
const bool showHiddenFiles = m_view->m_controller->dolphinView()->showHiddenFiles();
m_dirLister->setShowingDotFiles(showHiddenFiles);
- connect(m_dirLister, SIGNAL(newItems(const KFileItemList&)),
- this, SLOT(generatePreviews(const KFileItemList&)));
m_dolphinModel = new DolphinModel(this);
m_dolphinModel->setDirLister(m_dirLister);
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
setModel(m_proxyModel);
+ const bool useSelManager = KGlobalSettings::singleClick() &&
+ DolphinSettings::instance().generalSettings()->showSelectionToggle();
+ if (useSelManager) {
+ SelectionManager* selManager = new SelectionManager(this);
+ connect(selManager, SIGNAL(selectionChanged()),
+ this, SLOT(requestActivation()));
+ connect(m_view->m_controller, SIGNAL(urlChanged(const KUrl&)),
+ selManager, SLOT(reset()));
+}
new KMimeTypeResolver(this, m_dolphinModel);
+ m_iconManager = new IconManager(this, m_proxyModel);
+ m_iconManager->setShowPreview(m_view->m_controller->dolphinView()->showPreview());
m_dirLister->openUrl(url, KDirLister::NoFlags);
}
delete m_dolphinModel;
m_dolphinModel = 0;
m_dirLister = 0; // deleted by m_dolphinModel
-
- if (m_previewJob != 0) {
- m_previewJob->kill();
- m_previewJob = 0;
- }
}
void DolphinColumnWidget::setDecorationSize(const QSize& size)
{
+ setIconSize(size);
m_decorationSize = size;
doItemsLayout();
}
void DolphinColumnWidget::setShowPreview(bool show)
{
- if (show != m_showPreview) {
- m_dirLister->stop();
- m_dirLister->openUrl(m_url, KDirLister::Reload);
- }
+ m_iconManager->setShowPreview(show);
+
+ m_dirLister->stop();
+ m_dirLister->openUrl(m_url, KDirLister::Reload);
}
void DolphinColumnWidget::updateBackground()
{
- QColor color = KColorScheme(QPalette::Active, KColorScheme::View).background().color();
- if (!m_active || !m_view->m_active) {
- color.setAlpha(150);
- }
+ // TODO: The alpha-value 150 is copied from DolphinView::setActive(). When
+ // cleaning up the cut-indication of DolphinColumnWidget with the code from
+ // DolphinView a common helper-class should be available which can be shared
+ // by all view implementations -> no hardcoded value anymore
+ const QPalette::ColorRole role = viewport()->backgroundRole();
+ QColor color = viewport()->palette().color(role);
+ color.setAlpha((m_active && m_view->m_active) ? 255 : 150);
+
QPalette palette = viewport()->palette();
- palette.setColor(viewport()->backgroundRole(), color);
+ palette.setColor(role, color);
viewport()->setPalette(palette);
update();
void DolphinColumnWidget::mousePressEvent(QMouseEvent* event)
{
- m_view->m_controller->requestActivation();
- if (!m_active) {
- m_view->requestActivation(this);
- m_view->m_controller->triggerUrlChangeRequest(m_url);
- }
-
+ requestActivation();
QListView::mousePressEvent(event);
}
m_view->m_controller->triggerItem(item);
}
-void DolphinColumnWidget::generatePreviews(const KFileItemList& items)
-{
- // TODO: same implementation as in DolphinView; create helper class
- // for generatePreviews(), showPreview() and isCutItem()
-
- if (m_view->m_controller->dolphinView()->showPreview()) {
- if (m_previewJob != 0) {
- m_previewJob->kill();
- m_previewJob = 0;
- }
-
- m_previewJob = KIO::filePreview(items, 128);
- connect(m_previewJob, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
- this, SLOT(replaceIcon(const KFileItem&, const QPixmap&)));
- connect(m_previewJob, SIGNAL(finished(KJob*)),
- this, SLOT(slotPreviewJobFinished(KJob*)));
- }
-}
-
-void DolphinColumnWidget::replaceIcon(const KFileItem& item, const QPixmap& pixmap)
-{
- // TODO: same implementation as in DolphinView; create helper class
- // for generatePreviews(), showPreview() and isCutItem()
-
- Q_ASSERT(!item.isNull());
- const bool showPreview = m_view->m_controller->dolphinView()->showPreview();
- if (!showPreview || (item.url().directory() != m_dirLister->url().path())) {
- // the preview job is still working on items of an older URL, hence
- // the item is not part of the directory model anymore
- return;
- }
-
- const QModelIndex idx = m_dolphinModel->indexForItem(item);
- if (idx.isValid() && (idx.column() == 0)) {
- const QMimeData* mimeData = QApplication::clipboard()->mimeData();
- if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(item)) {
- KIconEffect iconEffect;
- const QPixmap cutPixmap = iconEffect.apply(pixmap, KIconLoader::Desktop, KIconLoader::DisabledState);
- m_dolphinModel->setData(idx, QIcon(cutPixmap), Qt::DecorationRole);
- } else {
- m_dolphinModel->setData(idx, QIcon(pixmap), Qt::DecorationRole);
- }
- }
-}
-
void DolphinColumnWidget::slotEntered(const QModelIndex& index)
{
const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
m_view->m_controller->emitItemEntered(item);
}
-void DolphinColumnWidget::slotPreviewJobFinished(KJob* job)
+void DolphinColumnWidget::requestActivation()
{
- Q_ASSERT(job == m_previewJob);
- m_previewJob = 0;
+ m_view->m_controller->requestActivation();
+ if (!m_active) {
+ m_view->requestActivation(this);
+ m_view->m_controller->triggerUrlChangeRequest(m_url);
+ selectionModel()->clear();
+ }
}
void DolphinColumnWidget::activate()
this, SLOT(triggerItem(const QModelIndex&)));
}
+ if (selectionModel() && selectionModel()->currentIndex().isValid())
+ selectionModel()->setCurrentIndex(selectionModel()->currentIndex(), QItemSelectionModel::SelectCurrent);
+
updateBackground();
}
this, SLOT(triggerItem(const QModelIndex&)));
}
+ const QModelIndex current = selectionModel()->currentIndex();
selectionModel()->clear();
+ selectionModel()->setCurrentIndex(current, QItemSelectionModel::NoUpdate);
updateBackground();
}
-bool DolphinColumnWidget::isCutItem(const KFileItem& item) const
-{
- // TODO: same implementation as in DolphinView; create helper class
- // for generatePreviews(), showPreview() and isCutItem()
-
- const QMimeData* mimeData = QApplication::clipboard()->mimeData();
- const KUrl::List cutUrls = KUrl::List::fromMimeData(mimeData);
-
- const KUrl& itemUrl = item.url();
- KUrl::List::const_iterator it = cutUrls.begin();
- const KUrl::List::const_iterator end = cutUrls.end();
- while (it != end) {
- if (*it == itemUrl) {
- return true;
- }
- ++it;
- }
-
- return false;
-}
-
KFileItem DolphinColumnWidget::itemForIndex(const QModelIndex& index) const
{
const QModelIndex dirIndex = m_proxyModel->mapToSource(index);
class DolphinColumnView;
class DolphinModel;
class DolphinSortFilterProxyModel;
+class IconManager;
class KDirLister;
class KJob;
class KFileItem;
class KFileItemList;
class QPixmap;
-namespace KIO
-{
- class PreviewJob;
-}
/**
* Represents one column inside the DolphinColumnView and has been
*/
void triggerItem(const QModelIndex& index);
- /**
- * Generates a preview image for each file item in \a items.
- * The current preview settings (maximum size, 'Show Preview' menu)
- * are respected.
- */
- void generatePreviews(const KFileItemList& items);
-
- /**
- * Replaces the icon of the item \a item by the preview pixmap
- * \a pixmap.
- */
- void replaceIcon(const KFileItem& item, const QPixmap& pixmap);
-
void slotEntered(const QModelIndex& index);
- /**
- * Is invoked when the preview job has been finished and
- * set m_previewJob to 0.
- */
- void slotPreviewJobFinished(KJob* job);
+ void requestActivation();
private:
/** Used by DolphinColumnWidget::setActive(). */
/** Used by DolphinColumnWidget::setActive(). */
void deactivate();
- /**
- * Returns true, if the item \a item has been cut into
- * the clipboard.
- */
- bool isCutItem(const KFileItem& item) const;
-
KFileItem itemForIndex(const QModelIndex& index) const;
private:
bool m_active;
- bool m_showPreview;
DolphinColumnView* m_view;
KUrl m_url; // URL of the directory that is shown
KUrl m_childUrl; // URL of the next column that is shown
DolphinModel* m_dolphinModel;
DolphinSortFilterProxyModel* m_proxyModel;
- KIO::PreviewJob* m_previewJob;
+ IconManager* m_iconManager;
bool m_dragging; // TODO: remove this property when the issue #160611 is solved in Qt 4.4
QRect m_dropRect; // TODO: remove this property when the issue #160611 is solved in Qt 4.4
popup->addMenu(newMenu->menu());
popup->addSeparator();
- QAction* pasteAction = m_mainWindow->actionCollection()->action(KStandardAction::stdName(KStandardAction::Paste));
+ QAction* pasteAction = m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::Paste));
popup->addAction(pasteAction);
// setup 'View Mode' menu
const KActionCollection* collection = m_mainWindow->actionCollection();
// insert 'Cut', 'Copy' and 'Paste'
- QAction* cutAction = collection->action(KStandardAction::stdName(KStandardAction::Cut));
- QAction* copyAction = collection->action(KStandardAction::stdName(KStandardAction::Copy));
- QAction* pasteAction = collection->action(KStandardAction::stdName(KStandardAction::Paste));
+ QAction* cutAction = collection->action(KStandardAction::name(KStandardAction::Cut));
+ QAction* copyAction = collection->action(KStandardAction::name(KStandardAction::Copy));
+ QAction* pasteAction = collection->action(KStandardAction::name(KStandardAction::Paste));
popup->addAction(cutAction);
popup->addAction(copyAction);
#include "dolphinsettings.h"
#include "dolphinsortfilterproxymodel.h"
#include "draganddrophelper.h"
+#include "selectionmanager.h"
#include "viewproperties.h"
#include "dolphin_detailsmodesettings.h"
+#include "dolphin_generalsettings.h"
#include <kdirmodel.h>
#include <klocale.h>
DolphinDetailsView::DolphinDetailsView(QWidget* parent, DolphinController* controller) :
QTreeView(parent),
+ m_autoResize(true),
m_controller(controller),
m_font(),
m_decorationSize(),
headerView->setContextMenuPolicy(Qt::CustomContextMenu);
connect(headerView, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(configureColumns(const QPoint&)));
+ connect(headerView, SIGNAL(sectionResized(int, int, int)),
+ this, SLOT(slotHeaderSectionResized(int, int, int)));
+ connect(headerView, SIGNAL(sectionHandleDoubleClicked(int)),
+ this, SLOT(disableAutoResizing()));
connect(parent, SIGNAL(sortingChanged(DolphinView::Sorting)),
this, SLOT(setSortIndicatorSection(DolphinView::Sorting)));
if (KGlobalSettings::singleClick()) {
connect(this, SIGNAL(clicked(const QModelIndex&)),
this, SLOT(triggerItem(const QModelIndex&)));
+ if (DolphinSettings::instance().generalSettings()->showSelectionToggle()) {
+ SelectionManager* selManager = new SelectionManager(this);
+ connect(selManager, SIGNAL(selectionChanged()),
+ this, SLOT(requestActivation()));
+ connect(m_controller, SIGNAL(urlChanged(const KUrl&)),
+ selManager, SLOT(reset()));
+ }
} else {
connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
this, SLOT(triggerItem(const QModelIndex&)));
void DolphinDetailsView::resizeEvent(QResizeEvent* event)
{
QTreeView::resizeEvent(event);
-
- // TODO: There seems to be no easy way to find out whether the resize event
- // has been triggered because of resizing the window or by adjusting the column-width
- // by a left mouse-click (the columns should only be resized automatically when the window
- // size is adjusted). The following workaround works well, but it should be
- // considered solving this in a more transparent way.
- if (!(QApplication::mouseButtons() & Qt::LeftButton)) {
+ if (m_autoResize) {
resizeColumns();
}
}
resizeColumns();
}
+void DolphinDetailsView::slotHeaderSectionResized(int logicalIndex, int oldSize, int newSize)
+{
+ Q_UNUSED(logicalIndex);
+ Q_UNUSED(oldSize);
+ Q_UNUSED(newSize);
+ if (QApplication::mouseButtons() & Qt::LeftButton) {
+ disableAutoResizing();
+ }
+}
+
+void DolphinDetailsView::disableAutoResizing()
+{
+ m_autoResize = false;
+}
+
+void DolphinDetailsView::requestActivation()
+{
+ m_controller->requestActivation();
+}
+
bool DolphinDetailsView::isZoomInPossible() const
{
DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
{
DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings();
const int iconSize = settings->iconSize();
+ setIconSize(QSize(iconSize, iconSize));
m_decorationSize = QSize(iconSize, iconSize);
m_controller->setZoomInPossible(isZoomInPossible());
void updateColumnVisibility();
+ /**
+ * Disables the automatical resizing of columns, if the user has resized the columns
+ * with the mouse.
+ */
+ void slotHeaderSectionResized(int logicalIndex, int oldSize, int newSize);
+
+ /**
+ * Disables the automatical resizing of the columns. Per default all columns
+ * are resized to use the maximum available width of the view as good as possible.
+ */
+ void disableAutoResizing();
+
+ void requestActivation();
+
private:
bool isZoomInPossible() const;
bool isZoomOutPossible() const;
void resizeColumns();
private:
+ bool m_autoResize; // if true, the columns are resized automatically to the available width
+
DolphinController* m_controller;
QFont m_font;
kDebug() << "Source" << urls;
kDebug() << "Destination:" << destination;
+ if (destination.protocol() == "trash") {
+ KonqOperations::del(m_parentWidget, KonqOperations::TRASH, urls);
+ return;
+ }
+
Qt::DropAction action = Qt::CopyAction;
Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
const bool shiftPressed = modifier & Qt::ShiftModifier;
const bool controlPressed = modifier & Qt::ControlModifier;
const bool altPressed = modifier & Qt::AltModifier;
- if (shiftPressed && controlPressed) {
- // shortcut for 'Link Here' is used
+ if ((shiftPressed && controlPressed) || altPressed) {
action = Qt::LinkAction;
- } else if (shiftPressed) {
- // shortcut for 'Move Here' is used
- action = Qt::MoveAction;
} else if (controlPressed) {
- // shortcut for 'Copy Here' is used
action = Qt::CopyAction;
- } else if (altPressed) {
- // shortcut for 'Link Here' is used
- action = Qt::LinkAction;
+ } else if (shiftPressed) {
+ action = Qt::MoveAction;
} else {
// open a context menu which offers the following actions:
// - Move Here
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Peter Penz <peter.penz@gmx.at> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "dolphinfileplacesview.h"
+#include "dolphindropcontroller.h"
+#include <konq_operations.h>
+
+DolphinFilePlacesView::DolphinFilePlacesView(QWidget* parent) :
+ KFilePlacesView(parent)
+{
+ setDropOnPlaceEnabled(true);
+ connect(this, SIGNAL(urlsDropped(const KUrl&, QDropEvent*, QWidget*)),
+ this, SLOT(slotUrlsDropped(const KUrl&, QDropEvent*, QWidget*)));
+}
+
+DolphinFilePlacesView::~DolphinFilePlacesView()
+{
+}
+
+void DolphinFilePlacesView::slotUrlsDropped(const KUrl& dest, QDropEvent* event, QWidget* parent)
+{
+ const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
+
+ DolphinDropController dropController(parent);
+ // forward doingOperation signal up to the mainwindow
+ connect(&dropController, SIGNAL(doingOperation(KonqFileUndoManager::CommandType)),
+ this, SIGNAL(doingOperation(KonqFileUndoManager::CommandType)));
+ dropController.dropUrls(urls, dest);
+}
+
+#include "dolphinfileplacesview.moc"
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Peter Penz <peter.penz@gmx.at> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef DOLPHINFILEPLACESVIEW_H
+#define DOLPHINFILEPLACESVIEW_H
+
+#include <kfileplacesview.h>
+
+/**
+ * @brief Combines bookmarks and mounted devices as list which is
+ * embedded as panel.
+ */
+class DolphinFilePlacesView : public KFilePlacesView
+{
+ Q_OBJECT
+
+public:
+ DolphinFilePlacesView(QWidget* parent);
+ virtual ~DolphinFilePlacesView();
+
+private slots:
+ void slotUrlsDropped(const KUrl& dest, QDropEvent* event, QWidget* parent);
+};
+
+#endif // DOLPHINFILEPLACESVIEW_H
#include "dolphincontroller.h"
#include "dolphinsettings.h"
#include "dolphin_iconsmodesettings.h"
+#include "dolphin_generalsettings.h"
#include "draganddrophelper.h"
+#include "selectionmanager.h"
#include <kcategorizedsortfilterproxymodel.h>
#include <kdialog.h>
#include <QApplication>
#include <QPainter>
#include <QPoint>
+#include <QScrollBar>
DolphinIconsView::DolphinIconsView(QWidget* parent, DolphinController* controller) :
KCategorizedView(parent),
if (KGlobalSettings::singleClick()) {
connect(this, SIGNAL(clicked(const QModelIndex&)),
this, SLOT(triggerItem(const QModelIndex&)));
+ if (DolphinSettings::instance().generalSettings()->showSelectionToggle()) {
+ SelectionManager* selManager = new SelectionManager(this);
+ connect(selManager, SIGNAL(selectionChanged()),
+ this, SLOT(requestActivation()));
+ connect(m_controller, SIGNAL(urlChanged(const KUrl&)),
+ selManager, SLOT(reset()));
+ }
} else {
connect(this, SIGNAL(doubleClicked(const QModelIndex&)),
this, SLOT(triggerItem(const QModelIndex&)));
}
}
+void DolphinIconsView::wheelEvent(QWheelEvent* event)
+{
+ KCategorizedView::wheelEvent(event);
+
+ if ((event->modifiers() & Qt::ControlModifier) == Qt::ControlModifier) {
+ int d = event->delta();
+ if (d > 0) {
+ zoomIn();
+ } else if (d < 0) {
+ zoomOut();
+ }
+ } else {
+ // if the icons are aligned left to right, the vertical wheel event should
+ // be applied to the horizontal scrollbar
+ const IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
+ const bool scrollHorizontal = (event->orientation() == Qt::Vertical) &&
+ (settings->arrangement() == QListView::LeftToRight);
+ if (scrollHorizontal) {
+ QWheelEvent horizEvent(event->pos(),
+ event->delta(),
+ event->buttons(),
+ event->modifiers(),
+ Qt::Horizontal);
+ QApplication::sendEvent(horizontalScrollBar(), &horizEvent);
+ }
+ }
+}
+
void DolphinIconsView::triggerItem(const QModelIndex& index)
{
m_controller->triggerItem(itemForIndex(index));
}
}
+void DolphinIconsView::requestActivation()
+{
+ m_controller->requestActivation();
+}
+
bool DolphinIconsView::isZoomInPossible() const
{
IconsModeSettings* settings = DolphinSettings::instance().iconsModeSettings();
size = previewSize;
}
+ setIconSize(QSize(size, size));
Q_ASSERT(additionalInfoCount >= 0);
itemHeight += additionalInfoCount * m_font.pointSize() * 2;
virtual void dropEvent(QDropEvent* event);
virtual void paintEvent(QPaintEvent* event);
virtual void keyPressEvent(QKeyEvent* event);
+ virtual void wheelEvent(QWheelEvent* event);
private slots:
void triggerItem(const QModelIndex& index);
void slotAdditionalInfoChanged();
void zoomIn();
void zoomOut();
+ void requestActivation();
private:
bool isZoomInPossible() const;
#include <config-nepomuk.h>
#include "dolphinapplication.h"
+#include "dolphinfileplacesview.h"
#include "dolphinnewmenu.h"
#include "dolphinsettings.h"
#include "dolphinsettingsdialog.h"
#include "mainwindowadaptor.h"
#include "terminalsidebarpage.h"
#include "treeviewsidebarpage.h"
-#include "kurlnavigator.h"
#include "viewpropertiesdialog.h"
#include "viewproperties.h"
-#include "kfileplacesmodel.h"
-#include "kfileplacesview.h"
#include "dolphin_generalsettings.h"
#include "dolphin_iconsmodesettings.h"
#include <kdesktopfile.h>
#include <kdeversion.h>
#include <kfiledialog.h>
+#include <kfileplacesmodel.h>
#include <kglobal.h>
#include <kicon.h>
#include <kiconloader.h>
#include <kmenu.h>
#include <kmenubar.h>
#include <kmessagebox.h>
+#include <kurlnavigator.h>
#include <konqmimedata.h>
#include <kpropertiesdialog.h>
#include <kprotocolinfo.h>
}
}
+void DolphinMainWindow::slotEditableStateChanged(bool editable)
+{
+ KToggleAction* editableLocationAction =
+ static_cast<KToggleAction*>(actionCollection()->action("editable_location"));
+ editableLocationAction->setChecked(editable);
+}
+
void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection)
{
updateEditActions();
void DolphinMainWindow::slotUndoAvailable(bool available)
{
- QAction* undoAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Undo));
+ QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo));
if (undoAction != 0) {
undoAction->setEnabled(available);
}
void DolphinMainWindow::slotUndoTextChanged(const QString& text)
{
- QAction* undoAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Undo));
+ QAction* undoAction = actionCollection()->action(KStandardAction::name(KStandardAction::Undo));
if (undoAction != 0) {
undoAction->setText(text);
}
void DolphinMainWindow::updatePasteAction()
{
- QAction* pasteAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Paste));
+ QAction* pasteAction = actionCollection()->action(KStandardAction::name(KStandardAction::Paste));
if (pasteAction == 0) {
return;
}
SLOT(undo()),
actionCollection());
- //Need to remove shift+del from cut action, else the shortcut for deletejob
- //doesn't work
+ // need to remove shift+del from cut action, else the shortcut for deletejob
+ // doesn't work
KAction* cut = KStandardAction::cut(this, SLOT(cut()), actionCollection());
KShortcut cutShortcut = cut->shortcut();
cutShortcut.remove(Qt::SHIFT + Qt::Key_Delete, KShortcut::KeepEmpty);
stop->setIcon(KIcon("process-stop"));
connect(stop, SIGNAL(triggered()), this, SLOT(stopLoading()));
- // TODO: the URL navigator must emit a signal if the editable state has been
- // changed, so that the corresponding showFullLocation action is updated. Also
- // the naming "Show full Location" is currently confusing...
+ // TODO: the naming "Show full Location" is currently confusing...
KToggleAction* showFullLocation = actionCollection()->add<KToggleAction>("editable_location");
showFullLocation->setText(i18nc("@action:inmenu Navigation Bar", "Show Full Location"));
showFullLocation->setShortcut(Qt::CTRL | Qt::Key_L);
QDockWidget* placesDock = new QDockWidget(i18nc("@title:window", "Places"));
placesDock->setObjectName("placesDock");
placesDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
- KFilePlacesView* placesView = new KFilePlacesView(placesDock);
+
+ DolphinFilePlacesView* placesView = new DolphinFilePlacesView(placesDock);
placesDock->setWidget(placesView);
placesView->setModel(DolphinSettings::instance().placesModel());
placesView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
void DolphinMainWindow::updateGoActions()
{
- QAction* goUpAction = actionCollection()->action(KStandardAction::stdName(KStandardAction::Up));
+ QAction* goUpAction = actionCollection()->action(KStandardAction::name(KStandardAction::Up));
const KUrl& currentUrl = m_activeViewContainer->url();
goUpAction->setEnabled(currentUrl.upUrl() != currentUrl);
}
this, SLOT(changeUrl(const KUrl&)));
connect(navigator, SIGNAL(historyChanged()),
this, SLOT(slotHistoryChanged()));
+ connect(navigator, SIGNAL(editableStateChanged(bool)),
+ this, SLOT(slotEditableStateChanged(bool)));
}
void DolphinMainWindow::updateSplitAction()
void toggleFilterBarVisibility(bool show);
/**
- * Toggles between edit and brose mode of the navigation bar.
+ * Toggles between edit and browse mode of the navigation bar.
*/
void toggleEditLocation();
/** Updates the state of the 'Sort by' actions. */
void slotSortingChanged(DolphinView::Sorting sorting);
+ /** Updates the state of the 'Show Full Location' action. */
+ void slotEditableStateChanged(bool editable);
+
/**
* Updates the state of the 'Edit' menu actions and emits
* the signal selectionChanged().
}
case KDirModel::ModifiedTime: {
- KDateTime modifiedTime;
- modifiedTime.setTime_t(item.time(KIO::UDSEntry::UDS_MODIFICATION_TIME));
+ KDateTime modifiedTime = item.time(KFileItem::ModificationTime);
modifiedTime = modifiedTime.toLocalZone();
retString = modifiedTime.toString(i18nc("Prints out the month and year: %B is full month name in current locale, and %Y is full year number", "%B, %Y"));
}
case KDirModel::ModifiedTime: {
- KDateTime modifiedTime;
- modifiedTime.setTime_t(item.time(KIO::UDSEntry::UDS_MODIFICATION_TIME));
+ KDateTime modifiedTime = item.time(KFileItem::ModificationTime);
modifiedTime = modifiedTime.toLocalZone();
retVariant = -(modifiedTime.date().year() * 100 + modifiedTime.date().month());
Name[da]=Dolphin-Part
Name[de]=Dolphin-Komponente
Name[el]=Τμήμα Dolphin
+Name[eo]=Komponanto de Dolphin
Name[es]=Part Dolphin
Name[et]=Dolphini komponent
Name[fi]=Dolphin osa
Name[ja]=Dolphin パート
Name[kk]=Dolphin бөлшегі
Name[km]=ផ្នែករបស់ Dolphin
+Name[kn]=ಡಾಲ್ಫಿನ್ ಭಾಗ
Name[ko]=Dolphin 부분
Name[ku]=Parçeyê Bibîne
Name[lv]=Dolphin daļa
Name[pl]=Moduł Dophina
Name[pt]=Componente do Dolphin
Name[pt_BR]=Componente Dolphin
+Name[ro]=Componentă Dolphin
Name[ru]=Встраиваемый компонент Dolphin
Name[se]=Dolphin-oassi
Name[sl]=Del Dolphin
Name[sr]=Делфин део
Name[sr@latin]=Dolphin deo
Name[sv]=Dolphin-delprogram
+Name[ta]=டால்பினின் பகுதி
Name[tg]=Қисми Dolphin
Name[tr]=Dolphin Parçacığı
Name[uk]=Компонент Дельфіна
</Menu>
<Menu name="view">
<Menu name="sort">
- <text context="@title:menu">Sort by</text>
+ <text context="@title:menu">Sort By</text>
<Action name="sort_by_name" />
<Action name="sort_by_size" />
<Action name="sort_by_date" />
#include "dolphinapplication.h"
#include "dolphinmainwindow.h"
#include "generalsettingspage.h"
+#include "startupsettingspage.h"
#include "viewsettingspage.h"
#include <klocale.h>
#include <kicon.h>
DolphinSettingsDialog::DolphinSettingsDialog(DolphinMainWindow* mainWindow) :
- KPageDialog(mainWindow)
+ KPageDialog(mainWindow),
+ m_startupSettingsPage(0),
+ m_generalSettingsPage(0),
+ m_viewSettingsPage(0)
+
{
const QSize minSize = minimumSize();
setMinimumSize(QSize(512, minSize.height()));
setButtons(Ok | Apply | Cancel | Default);
setDefaultButton(Ok);
- m_generalSettingsPage = new GeneralSettingsPage(mainWindow, this);
- KPageWidgetItem* generalSettingsFrame = addPage(m_generalSettingsPage,
- i18nc("@title:group", "General"));
- generalSettingsFrame->setIcon(KIcon("system-run"));
+ m_startupSettingsPage = new StartupSettingsPage(mainWindow, this);
+ KPageWidgetItem* startupSettingsFrame = addPage(m_startupSettingsPage,
+ i18nc("@title:group", "Startup"));
+ startupSettingsFrame->setIcon(KIcon("go-home"));
m_viewSettingsPage = new ViewSettingsPage(mainWindow, this);
KPageWidgetItem* viewSettingsFrame = addPage(m_viewSettingsPage,
i18nc("@title:group", "View Modes"));
viewSettingsFrame->setIcon(KIcon("view-choose"));
+ m_generalSettingsPage = new GeneralSettingsPage(mainWindow, this);
+ KPageWidgetItem* generalSettingsFrame = addPage(m_generalSettingsPage,
+ i18nc("@title:group", "General"));
+ generalSettingsFrame->setIcon(KIcon("system-run"));
+
const KConfigGroup dialogConfig(KSharedConfig::openConfig("dolphinrc"), "SettingsDialog");
restoreDialogSize(dialogConfig);
}
void DolphinSettingsDialog::applySettings()
{
+ m_startupSettingsPage->applySettings();
m_generalSettingsPage->applySettings();
m_viewSettingsPage->applySettings();
DolphinApplication::app()->refreshMainWindows();
void DolphinSettingsDialog::restoreDefaults()
{
+ m_startupSettingsPage->restoreDefaults();
m_generalSettingsPage->restoreDefaults();
m_viewSettingsPage->restoreDefaults();
DolphinApplication::app()->refreshMainWindows();
#define DOLPHINSETTINGSDIALOG_H
#include <kpagedialog.h>
+
class GeneralSettingsPage;
+class StartupSettingsPage;
class ViewSettingsPage;
class DolphinMainWindow;
/**
* @brief Settings dialog for Dolphin.
*
- * Contains the pages for general settings and view settings.
+ * Contains the pages for startup settings, general settings and view settings.
*
* @author Peter Penz <peter.penz@gmx.at>
*/
void restoreDefaults();
private:
+ StartupSettingsPage* m_startupSettingsPage;
GeneralSettingsPage* m_generalSettingsPage;
ViewSettingsPage* m_viewSettingsPage;
};
<Action name="columns" />
</Menu>
<Menu name="sort">
- <text context="@title:menu">Sort by</text>
+ <text context="@title:menu">Sort By</text>
<Action name="sort_by_name" />
<Action name="sort_by_size" />
<Action name="sort_by_date" />
#include <kcolorscheme.h>
#include <kdirlister.h>
#include <kfileitemdelegate.h>
-#include <klocale.h>
#include <kiconeffect.h>
+#include <klocale.h>
#include <kio/deletejob.h>
#include <kio/netaccess.h>
#include <kio/previewjob.h>
#include <kjob.h>
#include <kmenu.h>
#include <kmimetyperesolver.h>
-#include <konqmimedata.h>
#include <konq_operations.h>
+#include <konqmimedata.h>
#include <ktoggleaction.h>
#include <kurl.h>
#include "dolphinsortfilterproxymodel.h"
#include "dolphindetailsview.h"
#include "dolphiniconsview.h"
-#include "renamedialog.h"
-#include "viewproperties.h"
#include "dolphinsettings.h"
#include "dolphin_generalsettings.h"
+#include "iconmanager.h"
+#include "renamedialog.h"
+#include "viewproperties.h"
DolphinView::DolphinView(QWidget* parent,
const KUrl& url,
m_dolphinModel(dolphinModel),
m_dirLister(dirLister),
m_proxyModel(proxyModel),
- m_previewJob(0)
+ m_iconManager(0)
{
setFocusPolicy(Qt::StrongFocus);
m_topLayout = new QVBoxLayout(this);
m_topLayout->setSpacing(0);
m_topLayout->setMargin(0);
- QClipboard* clipboard = QApplication::clipboard();
- connect(clipboard, SIGNAL(dataChanged()),
- this, SLOT(updateCutItems()));
-
connect(m_dirLister, SIGNAL(completed()),
this, SLOT(updateCutItems()));
- connect(m_dirLister, SIGNAL(newItems(const KFileItemList&)),
- this, SLOT(generatePreviews(const KFileItemList&)));
m_controller = new DolphinController(this);
m_controller->setUrl(url);
DolphinView::~DolphinView()
{
- if (m_previewJob != 0) {
- m_previewJob->kill();
- m_previewJob = 0;
- }
}
const KUrl& DolphinView::url() const
m_mode = mode;
- if (isColumnViewActive()) {
- // When changing the mode in the column view, it makes sense
- // to go back to the root URL of the column view automatically.
- // Otherwise there it would not be possible to turn off the column view
- // without focusing the first column.
- const KUrl root = rootUrl();
- setUrl(root);
- m_controller->setUrl(root);
- }
-
deleteView();
const KUrl viewPropsUrl = viewPropertiesUrl();
props.setShowPreview(show);
m_showPreview = show;
-
+ m_iconManager->setShowPreview(show);
emit showPreviewChanged();
loadDirectory(viewPropsUrl, true);
void DolphinView::zoomIn()
{
m_controller->triggerZoomIn();
+ reload();
}
void DolphinView::zoomOut()
{
m_controller->triggerZoomOut();
+ reload();
}
bool DolphinView::isZoomInPossible() const
emit itemTriggered(item); // caught by DolphinViewContainer or DolphinPart
}
-void DolphinView::generatePreviews(const KFileItemList& items)
-{
- if (m_controller->dolphinView()->showPreview()) {
- if (m_previewJob != 0) {
- m_previewJob->kill();
- m_previewJob = 0;
- }
-
- m_previewJob = KIO::filePreview(items, 128);
- connect(m_previewJob, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
- this, SLOT(replaceIcon(const KFileItem&, const QPixmap&)));
- connect(m_previewJob, SIGNAL(finished(KJob*)),
- this, SLOT(slotPreviewJobFinished(KJob*)));
- }
-}
-
-void DolphinView::replaceIcon(const KFileItem& item, const QPixmap& pixmap)
-{
- Q_ASSERT(!item.isNull());
- if (!m_showPreview || (item.url().directory() != m_dirLister->url().path())) {
- // the preview has been deactivated in the meanwhile or the preview
- // job is still working on items of an older URL, hence
- // the item is not part of the directory model anymore
- return;
- }
-
- const QModelIndex idx = m_dolphinModel->indexForItem(item);
- if (idx.isValid() && (idx.column() == 0)) {
- const QMimeData* mimeData = QApplication::clipboard()->mimeData();
- if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(item)) {
- KIconEffect iconEffect;
- const QPixmap cutPixmap = iconEffect.apply(pixmap, KIconLoader::Desktop, KIconLoader::DisabledState);
- m_dolphinModel->setData(idx, QIcon(cutPixmap), Qt::DecorationRole);
- } else {
- m_dolphinModel->setData(idx, QIcon(pixmap), Qt::DecorationRole);
- }
- }
-}
-
void DolphinView::emitSelectionChangedSignal()
{
emit selectionChanged(DolphinView::selectedItems());
return;
}
- m_cutItemsCache.clear();
m_loadingDirectory = true;
m_dirLister->stop();
const bool showPreview = props.showPreview();
if (showPreview != m_showPreview) {
m_showPreview = showPreview;
+ m_iconManager->setShowPreview(showPreview);
emit showPreviewChanged();
}
}
}
}
-void DolphinView::updateCutItems()
-{
- // restore the icons of all previously selected items to the
- // original state...
- QList<CutItem>::const_iterator it = m_cutItemsCache.begin();
- QList<CutItem>::const_iterator end = m_cutItemsCache.end();
- while (it != end) {
- const QModelIndex index = m_dolphinModel->indexForUrl((*it).url);
- if (index.isValid()) {
- m_dolphinModel->setData(index, QIcon((*it).pixmap), Qt::DecorationRole);
- }
- ++it;
- }
- m_cutItemsCache.clear();
-
- // ... and apply an item effect to all currently cut items
- applyCutItemEffect();
-}
-
void DolphinView::showHoverInformation(const KFileItem& item)
{
if (hasSelection() || !m_active) {
}
}
-
void DolphinView::createView()
{
deleteView();
view->setSelectionMode(QAbstractItemView::ExtendedSelection);
new KMimeTypeResolver(view, m_dolphinModel);
+ m_iconManager = new IconManager(view, m_proxyModel);
+ m_iconManager->setShowPreview(m_showPreview);
+
m_topLayout->insertWidget(1, view);
connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
m_detailsView = 0;
m_columnView = 0;
m_fileItemDelegate = 0;
+ m_iconManager = 0;
}
}
return false;
}
-void DolphinView::applyCutItemEffect()
-{
- const QMimeData* mimeData = QApplication::clipboard()->mimeData();
- if (!KonqMimeData::decodeIsCutSelection(mimeData)) {
- return;
- }
-
- KFileItemList items(m_dirLister->items());
- KFileItemList::const_iterator it = items.begin();
- const KFileItemList::const_iterator end = items.end();
- while (it != end) {
- const KFileItem item = *it;
- if (isCutItem(item)) {
- const QModelIndex index = m_dolphinModel->indexForItem(item);
- const QVariant value = m_dolphinModel->data(index, Qt::DecorationRole);
- if (value.type() == QVariant::Icon) {
- const QIcon icon(qvariant_cast<QIcon>(value));
- QPixmap pixmap = icon.pixmap(128, 128);
-
- // remember current pixmap for the item to be able
- // to restore it when other items get cut
- CutItem cutItem;
- cutItem.url = item.url();
- cutItem.pixmap = pixmap;
- m_cutItemsCache.append(cutItem);
-
- // apply icon effect to the cut item
- KIconEffect iconEffect;
- pixmap = iconEffect.apply(pixmap, KIconLoader::Desktop, KIconLoader::DisabledState);
- m_dolphinModel->setData(index, QIcon(pixmap), Qt::DecorationRole);
- }
- }
- ++it;
- }
-}
-
KToggleAction* DolphinView::iconsModeAction(KActionCollection* actionCollection)
{
KToggleAction* iconsView = actionCollection->add<KToggleAction>("icons");
Q_ASSERT(newName.contains('#'));
// iterate through all selected items and rename them...
- const int replaceIndex = newName.indexOf('#');
- Q_ASSERT(replaceIndex >= 0);
int index = 1;
-
- KFileItemList::const_iterator it = items.begin();
- const KFileItemList::const_iterator end = items.end();
- while (it != end) {
- const KUrl& oldUrl = (*it).url();
+ foreach (KFileItem item, items) {
+ const KUrl& oldUrl = item.url();
QString number;
number.setNum(index++);
- QString name(newName);
- name.replace(replaceIndex, 1, number);
+ QString name = newName;
+ name.replace('#', number);
if (oldUrl.fileName() != name) {
KUrl newUrl = oldUrl;
KonqOperations::rename(this, oldUrl, newUrl);
emit doingOperation(KonqFileUndoManager::RENAME);
}
- ++it;
}
}
} else {
}
}
-void DolphinView::slotPreviewJobFinished(KJob* job)
-{
- Q_ASSERT(job == m_previewJob);
- m_previewJob = 0;
-}
-
void DolphinView::cutSelectedItems()
{
QMimeData* mimeData = new QMimeData();
#include <QWidget>
class QActionGroup;
-class KAction;
-class KToggleAction;
class DolphinController;
-class KDirLister;
-class KFileItemDelegate;
-class KUrl;
-class DolphinModel;
class DolphinColumnView;
class DolphinDetailsView;
class DolphinIconsView;
class DolphinMainWindow;
+class DolphinModel;
class DolphinSortFilterProxyModel;
+class IconManager;
+class KAction;
+class KActionCollection;
+class KDirLister;
+class KFileItemDelegate;
+class KUrl;
+class KToggleAction;
class QModelIndex;
class ViewProperties;
-namespace KIO
-{
- class PreviewJob;
-}
/**
* @short Represents a view for the directory content.
*/
void triggerItem(const KFileItem& index);
- /**
- * Generates a preview image for each file item in \a items.
- * The current preview settings (maximum size, 'Show Preview' menu)
- * are respected.
- */
- void generatePreviews(const KFileItemList& items);
-
- /**
- * Replaces the icon of the item \a item by the preview pixmap
- * \a pixmap.
- */
- void replaceIcon(const KFileItem& item, const QPixmap& pixmap);
-
void emitSelectionChangedSignal();
/**
*/
void emitContentsMoved();
- /** Applies an item effect to all cut items of the clipboard. */
- void updateCutItems();
-
/**
* Updates the status bar to show hover information for the
* item \a item. If currently other items are selected,
*/
void slotDeleteFileFinished(KJob* job);
- /**
- * Is invoked when the preview job has been finished and
- * set m_previewJob to 0.
- */
- void slotPreviewJobFinished(KJob* job);
-
private:
void loadDirectory(const KUrl& url, bool reload = false);
*/
bool isCutItem(const KFileItem& item) const;
- /** Applies an item effect to all cut items. */
- void applyCutItemEffect();
-
/**
* Returns true, if the ColumnView is activated. As the column view
* requires some special handling for iterating through directories,
}
private:
- /**
- * Remembers the original pixmap for an item before
- * the cut effect is applied.
- */
- struct CutItem
- {
- KUrl url;
- QPixmap pixmap;
- };
-
bool m_active;
bool m_showPreview;
bool m_loadingDirectory;
KDirLister* m_dirLister;
DolphinSortFilterProxyModel* m_proxyModel;
- KIO::PreviewJob* m_previewJob;
-
- QList<CutItem> m_cutItemsCache;
+ IconManager* m_iconManager;
KUrl m_rootUrl;
};
if (item.isDir()) {
m_view->setUrl(url);
- } else if (item.isFile() && url.isLocalFile()) {
- // allow to browse through ZIP and tar files
- // TODO: make this configurable for Dolphin in KDE 4.1
+ return;
+ }
+ const GeneralSettings* settings = DolphinSettings::instance().generalSettings();
+ const bool browseThroughArchives = settings->browseThroughArchives() &&
+ item.isFile() && url.isLocalFile();
+ if (browseThroughArchives) {
KMimeType::Ptr mime = item.mimeTypePtr();
// Don't use mime->is("application/zip"), as this would
if (mime->name() == "application/zip") {
url.setProtocol("zip");
m_view->setUrl(url);
- } else if (mime->is("application/x-tar") ||
- mime->is("application/x-tarz") ||
- mime->is("application/x-bzip-compressed-tar") ||
- mime->is("application/x-compressed-tar") ||
- mime->is("application/x-tzo")) {
+ return;
+ }
+
+ if (mime->is("application/x-tar") ||
+ mime->is("application/x-tarz") ||
+ mime->is("application/x-bzip-compressed-tar") ||
+ mime->is("application/x-compressed-tar") ||
+ mime->is("application/x-tzo")) {
url.setProtocol("tar");
m_view->setUrl(url);
- } else {
- item.run();
+ return;
}
- } else {
- item.run();
}
+
+ item.run();
}
#include "dolphinviewcontainer.moc"
#include "generalsettingspage.h"
#include "dolphinsettings.h"
-#include "dolphinmainwindow.h"
-#include "dolphinview.h"
-#include "dolphinviewcontainer.h"
#include "dolphin_generalsettings.h"
#include <kdialog.h>
-#include <kfiledialog.h>
#include <klocale.h>
#include <kvbox.h>
#include <QCheckBox>
#include <QGroupBox>
#include <QLabel>
-#include <QLineEdit>
-#include <QPushButton>
-#include <QRadioButton>
+#include <QVBoxLayout>
GeneralSettingsPage::GeneralSettingsPage(DolphinMainWindow* mainWin, QWidget* parent) :
SettingsPageBase(parent),
- m_mainWindow(mainWin),
- m_homeUrl(0),
- m_splitView(0),
- m_editableUrl(0),
- m_filterBar(0),
m_showDeleteCommand(0),
m_confirmMoveToTrash(0),
- m_confirmDelete(0)
+ m_confirmDelete(0),
+ m_browseThroughArchives(0)
{
+ Q_UNUSED(mainWin);
+
const int spacing = KDialog::spacingHint();
QVBoxLayout* topLayout = new QVBoxLayout(this);
KVBox* vBox = new KVBox(this);
vBox->setSpacing(spacing);
- // create 'Home URL' editor
- QGroupBox* homeBox = new QGroupBox(i18nc("@title:group", "Home Folder"), vBox);
-
- KHBox* homeUrlBox = new KHBox(homeBox);
- homeUrlBox->setSpacing(spacing);
-
- new QLabel(i18nc("@label:textbox", "Location:"), homeUrlBox);
- m_homeUrl = new QLineEdit(homeUrlBox);
-
- QPushButton* selectHomeUrlButton = new QPushButton(KIcon("folder-open"), QString(), homeUrlBox);
- connect(selectHomeUrlButton, SIGNAL(clicked()),
- this, SLOT(selectHomeUrl()));
-
- KHBox* buttonBox = new KHBox(homeBox);
- buttonBox->setSpacing(spacing);
-
- QPushButton* useCurrentButton = new QPushButton(i18nc("@action:button", "Use Current Location"), buttonBox);
- connect(useCurrentButton, SIGNAL(clicked()),
- this, SLOT(useCurrentLocation()));
- QPushButton* useDefaultButton = new QPushButton(i18nc("@action:button", "Use Default Location"), buttonBox);
- connect(useDefaultButton, SIGNAL(clicked()),
- this, SLOT(useDefaultLocation()));
-
- QVBoxLayout* homeBoxLayout = new QVBoxLayout(homeBox);
- homeBoxLayout->addWidget(homeUrlBox);
- homeBoxLayout->addWidget(buttonBox);
-
- QGroupBox* startBox = new QGroupBox(i18nc("@title:group", "Startup Settings"), vBox);
-
- // create 'Split view', 'Editable location' and 'Filter bar' checkboxes
- m_splitView = new QCheckBox(i18nc("@option:check Startup Settings", "Split view mode"), startBox);
- m_editableUrl = new QCheckBox(i18nc("@option:check Startup Settings", "Editable location bar"), startBox);
- m_filterBar = new QCheckBox(i18nc("@option:check Startup Settings", "Show filter bar"),startBox);
-
- QVBoxLayout* startBoxLayout = new QVBoxLayout(startBox);
- startBoxLayout->addWidget(m_splitView);
- startBoxLayout->addWidget(m_editableUrl);
- startBoxLayout->addWidget(m_filterBar);
-
// create 'Ask Confirmation For' group
QGroupBox* confirmBox = new QGroupBox(i18nc("@title:group", "Ask For Confirmation When"), vBox);
m_confirmMoveToTrash = new QCheckBox(i18nc("@option:check Ask for Confirmation When",
// create 'Show the command 'Delete' in context menu' checkbox
m_showDeleteCommand = new QCheckBox(i18nc("@option:check", "Show 'Delete' command in context menu"), vBox);
+ m_browseThroughArchives = new QCheckBox(i18nc("option:check", "Browse through archives"), vBox);
+
// Add a dummy widget with no restriction regarding
// a vertical resizing. This assures that the dialog layout
// is not stretched vertically.
{
GeneralSettings* settings = DolphinSettings::instance().generalSettings();
- const KUrl url(m_homeUrl->text());
- KFileItem fileItem(S_IFDIR, KFileItem::Unknown, url);
- if (url.isValid() && fileItem.isDir()) {
- settings->setHomeUrl(url.prettyUrl());
- }
-
- settings->setSplitView(m_splitView->isChecked());
- settings->setEditableUrl(m_editableUrl->isChecked());
- settings->setFilterBar(m_filterBar->isChecked());
-
KSharedConfig::Ptr konqConfig = KSharedConfig::openConfig("konquerorrc", KConfig::IncludeGlobals);
KConfigGroup trashConfig(konqConfig, "Trash");
trashConfig.writeEntry("ConfirmTrash", m_confirmMoveToTrash->isChecked());
KConfigGroup kdeConfig(KGlobal::config(), "KDE");
kdeConfig.writeEntry("ShowDeleteCommand", m_showDeleteCommand->isChecked());
kdeConfig.sync();
+
+ settings->setBrowseThroughArchives(m_browseThroughArchives->isChecked());
}
void GeneralSettingsPage::restoreDefaults()
loadSettings();
}
-void GeneralSettingsPage::selectHomeUrl()
-{
- const QString homeUrl(m_homeUrl->text());
- KUrl url(KFileDialog::getExistingDirectoryUrl(homeUrl));
- if (!url.isEmpty()) {
- m_homeUrl->setText(url.prettyUrl());
- }
-}
-
-void GeneralSettingsPage::useCurrentLocation()
-{
- const DolphinView* view = m_mainWindow->activeViewContainer()->view();
- m_homeUrl->setText(view->url().prettyUrl());
-}
-
-void GeneralSettingsPage::useDefaultLocation()
-{
- m_homeUrl->setText("file://" + QDir::homePath());
-}
-
void GeneralSettingsPage::loadSettings()
{
- GeneralSettings* settings = DolphinSettings::instance().generalSettings();
- m_homeUrl->setText(settings->homeUrl());
- m_splitView->setChecked(settings->splitView());
- m_editableUrl->setChecked(settings->editableUrl());
- m_filterBar->setChecked(settings->filterBar());
-
KSharedConfig::Ptr konqConfig = KSharedConfig::openConfig("konquerorrc", KConfig::IncludeGlobals);
const KConfigGroup trashConfig(konqConfig, "Trash");
m_confirmMoveToTrash->setChecked(trashConfig.readEntry("ConfirmTrash", false));
const KConfigGroup kdeConfig(KGlobal::config(), "KDE");
m_showDeleteCommand->setChecked(kdeConfig.readEntry("ShowDeleteCommand", false));
+
+ GeneralSettings* settings = DolphinSettings::instance().generalSettings();
+ m_browseThroughArchives->setChecked(settings->browseThroughArchives());
}
#include "generalsettingspage.moc"
/**
* @brief Page for the 'General' settings of the Dolphin settings dialog.
- *
- * The general settings allow to set the home URL and to configure the
- * state of the view mode, split mode and the filter bar when starting Dolphin.
*/
class GeneralSettingsPage : public SettingsPageBase
{
/** @see SettingsPageBase::restoreDefaults() */
virtual void restoreDefaults();
-private slots:
- void selectHomeUrl();
- void useCurrentLocation();
- void useDefaultLocation();
-
private:
void loadSettings();
private:
- DolphinMainWindow* m_mainWindow;
- QLineEdit* m_homeUrl;
-
- QCheckBox* m_splitView;
- QCheckBox* m_editableUrl;
- QCheckBox* m_filterBar;
-
QCheckBox* m_showDeleteCommand;
QCheckBox* m_confirmMoveToTrash;
QCheckBox* m_confirmDelete;
+
+ QCheckBox* m_browseThroughArchives;
};
#endif
m_globalProps(0),
m_maxPreviewSize(0),
m_spinBox(0),
- m_useFileThumbnails(0)
+ m_useFileThumbnails(0),
+ m_showSelectionToggle(0)
{
const int spacing = KDialog::spacingHint();
const int margin = KDialog::marginHint();
KHBox* vBox = new KHBox(previewBox);
vBox->setSpacing(spacing);
- QLabel* maxFileSize = new QLabel(i18nc("@label:slider", "Maximum file size:"), vBox);
+ new QLabel(i18nc("@label:slider", "Maximum file size:"), vBox);
m_maxPreviewSize = new QSlider(Qt::Horizontal, vBox);
m_spinBox = new QSpinBox(vBox);
previewBoxLayout->addWidget(vBox);
previewBoxLayout->addWidget(m_useFileThumbnails);
+ m_showSelectionToggle = new QCheckBox(i18nc("option:check", "Show selection toggle"), this);
+
// Add a dummy widget with no restriction regarding
// a vertical resizing. This assures that the dialog layout
// is not stretched vertically.
m_useFileThumbnails->isChecked(),
KConfigBase::Normal | KConfigBase::Global);
globalConfig.sync();
+
+ settings->setShowSelectionToggle(m_showSelectionToggle->isChecked());
}
void GeneralViewSettingsPage::restoreDefaults()
m_maxPreviewSize->setTickPosition(QSlider::TicksBelow);
KConfigGroup globalConfig(KGlobal::config(), "PreviewSettings");
+ // TODO: The default value of 5 MB must match with the default value inside
+ // kdelibs/kio/kio/previewjob.cpp. Maybe a static getter method in PreviewJob
+ // should be added for getting the default size?
const int maxByteSize = globalConfig.readEntry("MaximumSize", 5 * 1024 * 1024 /* 5 MB */);
int maxMByteSize = maxByteSize / (1024 * 1024);
if (maxMByteSize < 1) {
const bool useFileThumbnails = globalConfig.readEntry("UseFileThumbnails", true);
m_useFileThumbnails->setChecked(useFileThumbnails);
+
+ m_showSelectionToggle->setChecked(settings->showSelectionToggle());
}
#include "generalviewsettingspage.moc"
QSlider* m_maxPreviewSize;
QSpinBox* m_spinBox;
QCheckBox* m_useFileThumbnails;
+ QCheckBox* m_showSelectionToggle;
};
#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Peter Penz <peter.penz@gmx.at> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "iconmanager.h"
+
+#include "dolphinmodel.h"
+#include "dolphinsortfilterproxymodel.h"
+
+#include <kiconeffect.h>
+#include <kio/previewjob.h>
+#include <kdebug.h>
+#include <kdirlister.h>
+#include <konqmimedata.h>
+
+#include <QApplication>
+#include <QAbstractItemView>
+#include <QClipboard>
+#include <QColor>
+#include <QIcon>
+
+IconManager::IconManager(QAbstractItemView* parent, DolphinSortFilterProxyModel* model) :
+ QObject(parent),
+ m_showPreview(false),
+ m_view(parent),
+ m_previewJobs(),
+ m_dolphinModel(0),
+ m_proxyModel(model),
+ m_cutItemsCache()
+{
+ Q_ASSERT(m_view->iconSize().isValid()); // each view must provide its current icon size
+
+ m_dolphinModel = static_cast<DolphinModel*>(m_proxyModel->sourceModel());
+ connect(m_dolphinModel->dirLister(), SIGNAL(newItems(const KFileItemList&)),
+ this, SLOT(updateIcons(const KFileItemList&)));
+
+ QClipboard* clipboard = QApplication::clipboard();
+ connect(clipboard, SIGNAL(dataChanged()),
+ this, SLOT(updateCutItems()));
+}
+
+IconManager::~IconManager()
+{
+ foreach (KJob* job, m_previewJobs) {
+ Q_ASSERT(job != 0);
+ job->kill();
+ }
+ m_previewJobs.clear();
+}
+
+
+void IconManager::setShowPreview(bool show)
+{
+ if (m_showPreview != show) {
+ m_showPreview = show;
+ m_cutItemsCache.clear();
+ updateCutItems();
+ }
+}
+
+void IconManager::updateIcons(const KFileItemList& items)
+{
+ // make the icons of all hidden files semitransparent
+ foreach (KFileItem item, items) {
+ if (item.isHidden()) {
+ applyHiddenItemEffect(item);
+ }
+ }
+
+ if (!m_showPreview) {
+ return;
+ }
+
+ // generate previews
+ const QRect visibleArea = m_view->viewport()->rect();
+
+ // Order the items in a way that the preview for the visible items
+ // is generated first, as this improves the feeled performance a lot.
+ KFileItemList orderedItems;
+ foreach (KFileItem item, items) {
+ const QModelIndex dirIndex = m_dolphinModel->indexForItem(item);
+ const QModelIndex proxyIndex = m_proxyModel->mapFromSource(dirIndex);
+ const QRect itemRect = m_view->visualRect(proxyIndex);
+ if (itemRect.intersects(visibleArea)) {
+ orderedItems.insert(0, item);
+ } else {
+ orderedItems.append(item);
+ }
+ }
+
+ const QSize size = m_view->iconSize();
+ KIO::PreviewJob* job = KIO::filePreview(orderedItems, size.width(), size.height());
+ connect(job, SIGNAL(gotPreview(const KFileItem&, const QPixmap&)),
+ this, SLOT(replaceIcon(const KFileItem&, const QPixmap&)));
+ connect(job, SIGNAL(finished(KJob*)),
+ this, SLOT(slotPreviewJobFinished(KJob*)));
+
+ m_previewJobs.append(job);
+}
+
+void IconManager::replaceIcon(const KFileItem& item, const QPixmap& pixmap)
+{
+ Q_ASSERT(!item.isNull());
+ KDirLister* dirLister = m_dolphinModel->dirLister();
+ if (!m_showPreview || (item.url().directory() != dirLister->url().path())) {
+ // the preview has been canceled in the meanwhile or the preview
+ // job is still working on items of an older URL, hence
+ // the item is not part of the directory model anymore
+ return;
+ }
+
+ const QModelIndex idx = m_dolphinModel->indexForItem(item);
+ if (idx.isValid() && (idx.column() == 0)) {
+ QPixmap icon = pixmap;
+ if (item.isHidden()) {
+ if (!icon.hasAlpha()) {
+ // the semitransparent operation requires having an alpha mask
+ QPixmap alphaMask(icon.width(), icon.height());
+ alphaMask.fill();
+ icon.setAlphaChannel(alphaMask);
+ }
+ KIconEffect::semiTransparent(icon);
+ }
+
+ const QMimeData* mimeData = QApplication::clipboard()->mimeData();
+ if (KonqMimeData::decodeIsCutSelection(mimeData) && isCutItem(item)) {
+ KIconEffect iconEffect;
+ icon = iconEffect.apply(icon, KIconLoader::Desktop, KIconLoader::DisabledState);
+ m_dolphinModel->setData(idx, QIcon(icon), Qt::DecorationRole);
+ } else {
+ m_dolphinModel->setData(idx, QIcon(icon), Qt::DecorationRole);
+ }
+ }
+}
+
+void IconManager::slotPreviewJobFinished(KJob* job)
+{
+ const int index = m_previewJobs.indexOf(job);
+ m_previewJobs.removeAt(index);
+}
+
+void IconManager::updateCutItems()
+{
+ // restore the icons of all previously selected items to the
+ // original state...
+ foreach (CutItem cutItem, m_cutItemsCache) {
+ const QModelIndex index = m_dolphinModel->indexForUrl(cutItem.url);
+ if (index.isValid()) {
+ m_dolphinModel->setData(index, QIcon(cutItem.pixmap), Qt::DecorationRole);
+ }
+ }
+ m_cutItemsCache.clear();
+
+ // ... and apply an item effect to all currently cut items
+ applyCutItemEffect();
+}
+
+bool IconManager::isCutItem(const KFileItem& item) const
+{
+ const QMimeData* mimeData = QApplication::clipboard()->mimeData();
+ const KUrl::List cutUrls = KUrl::List::fromMimeData(mimeData);
+
+ const KUrl& itemUrl = item.url();
+ foreach (KUrl url, cutUrls) {
+ if (url == itemUrl) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void IconManager::applyCutItemEffect()
+{
+ const QMimeData* mimeData = QApplication::clipboard()->mimeData();
+ if (!KonqMimeData::decodeIsCutSelection(mimeData)) {
+ return;
+ }
+
+ const KFileItemList items(m_dolphinModel->dirLister()->items());
+ foreach (KFileItem item, items) {
+ if (isCutItem(item)) {
+ const QModelIndex index = m_dolphinModel->indexForItem(item);
+ const QVariant value = m_dolphinModel->data(index, Qt::DecorationRole);
+ if (value.type() == QVariant::Icon) {
+ const QIcon icon(qvariant_cast<QIcon>(value));
+ QPixmap pixmap = icon.pixmap(m_view->iconSize());
+
+ // remember current pixmap for the item to be able
+ // to restore it when other items get cut
+ CutItem cutItem;
+ cutItem.url = item.url();
+ cutItem.pixmap = pixmap;
+ m_cutItemsCache.append(cutItem);
+
+ // apply icon effect to the cut item
+ KIconEffect iconEffect;
+ pixmap = iconEffect.apply(pixmap, KIconLoader::Desktop, KIconLoader::DisabledState);
+ m_dolphinModel->setData(index, QIcon(pixmap), Qt::DecorationRole);
+ }
+ }
+ }
+}
+
+void IconManager::applyHiddenItemEffect(const KFileItem& hiddenItem)
+{
+ const QModelIndex index = m_dolphinModel->indexForItem(hiddenItem);
+ const QVariant value = m_dolphinModel->data(index, Qt::DecorationRole);
+ if (value.type() == QVariant::Icon) {
+ const QIcon icon(qvariant_cast<QIcon>(value));
+ QPixmap pixmap = icon.pixmap(m_view->iconSize());
+ KIconEffect::semiTransparent(pixmap);
+ m_dolphinModel->setData(index, QIcon(pixmap), Qt::DecorationRole);
+ }
+}
+
+#include "iconmanager.moc"
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Peter Penz <peter.penz@gmx.at> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef ICONMANAGER_H
+#define ICONMANAGER_H
+
+#include <kfileitem.h>
+#include <kurl.h>
+
+#include <QList>
+#include <QObject>
+#include <QPixmap>
+
+class DolphinModel;
+class DolphinSortFilterProxyModel;
+class KJob;
+class QAbstractItemView;
+
+/**
+ * @brief Manages the icon state of a directory model.
+ *
+ * Per default a preview is generated for each item.
+ * Additionally the clipboard is checked for cut items.
+ * The icon state for cut items gets dimmed automatically.
+ */
+class IconManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ IconManager(QAbstractItemView* parent, DolphinSortFilterProxyModel* model);
+ virtual ~IconManager();
+ void setShowPreview(bool show);
+ bool showPreview() const;
+
+private slots:
+ /**
+ * Updates the icons of for each item in \a items by making hidden
+ * items semitransparent and generating previews. The current preview
+ * settings (maximum size, 'Show Preview' menu) are respected.
+ */
+ void updateIcons(const KFileItemList& items);
+
+ /**
+ * Replaces the icon of the item \a item by the preview pixmap
+ * \a pixmap.
+ */
+ void replaceIcon(const KFileItem& item, const QPixmap& pixmap);
+
+ /**
+ * Is invoked when the preview job has been finished and
+ * set m_previewJob to 0.
+ */
+ void slotPreviewJobFinished(KJob* job);
+
+ /** Synchronizes the item icon with the clipboard of cut items. */
+ void updateCutItems();
+
+private:
+ /**
+ * Returns true, if the item \a item has been cut into
+ * the clipboard.
+ */
+ bool isCutItem(const KFileItem& item) const;
+
+ /** Applies an item effect to all cut items. */
+ void applyCutItemEffect();
+
+ /** Applies an item effect to the hidden item \a hiddenItem. */
+ void applyHiddenItemEffect(const KFileItem& hiddenItem);
+
+private:
+ /**
+ * Remembers the original pixmap for an item before
+ * the cut effect is applied.
+ */
+ struct CutItem
+ {
+ KUrl url;
+ QPixmap pixmap;
+ };
+
+ bool m_showPreview;
+
+ QAbstractItemView* m_view;
+ QList<KJob*> m_previewJobs;
+ DolphinModel* m_dolphinModel;
+ DolphinSortFilterProxyModel* m_proxyModel;
+
+ QList<CutItem> m_cutItemsCache;
+};
+
+inline bool IconManager::showPreview() const
+{
+ return m_showPreview;
+}
+
+#endif
// preview
m_preview = new PixmapViewer(this);
m_preview->setMinimumWidth(KIconLoader::SizeEnormous);
- m_preview->setFixedHeight(KIconLoader::SizeEnormous);
+ m_preview->setMinimumHeight(KIconLoader::SizeEnormous);
// name
m_nameLabel = new QLabel(this);
const int maxWidth = event->size().width() - KDialog::spacingHint() * 4;
m_nameLabel->setMaximumWidth(maxWidth);
m_infoLabel->setMaximumWidth(maxWidth);
+
+ // try to increase the preview as large as possible
+ m_preview->setSizeHint(QSize(maxWidth, maxWidth));
+ m_urlCandidate = m_shownUrl; // reset the URL candidate if a resizing is done
+ m_timer->start(TimerDelay);
+
SidebarPage::resizeEvent(event);
}
KIconLoader iconLoader;
QPixmap icon = iconLoader.loadIcon("system-run",
KIconLoader::NoGroup,
- KIconLoader::SizeEnormous);
+ m_preview->width());
m_preview->setPixmap(icon);
m_nameLabel->setText(i18ncp("@info", "%1 item selected", "%1 items selected", selectedItems.count()));
} else if (!applyPlace(file)) {
KIO::PreviewJob* job = KIO::filePreview(list,
m_preview->width(),
- KIconLoader::SizeEnormous,
+ m_preview->height(),
0,
0,
true,
+++ /dev/null
-/**
- * This file is part of the KDE project
- * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
- *
- * 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 "kcategorizedview.h"
-#include "kcategorizedview_p.h"
-
-#include <math.h> // trunc on C99 compliant systems
-#include <kdefakes.h> // trunc for not C99 compliant systems
-
-#include <QPainter>
-#include <QScrollBar>
-#include <QPaintEvent>
-
-#include <kstyle.h>
-
-#include "kcategorydrawer.h"
-#include "kcategorizedsortfilterproxymodel.h"
-
-// By defining DOLPHIN_DRAGANDDROP the custom drag and drop implementation of
-// KCategorizedView is bypassed to have a consistent drag and drop look for all
-// views. Hopefully transparent pixmaps for drag objects will be supported in
-// Qt 4.4, so that this workaround can be skipped.
-#define DOLPHIN_DRAGANDDROP
-
-KCategorizedView::Private::Private(KCategorizedView *listView)
- : listView(listView)
- , categoryDrawer(0)
- , biggestItemSize(QSize(0, 0))
- , mouseButtonPressed(false)
- , rightMouseButtonPressed(false)
- , isDragging(false)
- , dragLeftViewport(false)
- , proxyModel(0)
-{
-}
-
-KCategorizedView::Private::~Private()
-{
-}
-
-const QModelIndexList &KCategorizedView::Private::intersectionSet(const QRect &rect)
-{
- QModelIndex index;
- QRect indexVisualRect;
-
- intersectedIndexes.clear();
-
- int itemHeight;
-
- if (listView->gridSize().isEmpty())
- {
- itemHeight = biggestItemSize.height();
- }
- else
- {
- itemHeight = listView->gridSize().height();
- }
-
- // Lets find out where we should start
- int top = proxyModel->rowCount() - 1;
- int bottom = 0;
- int middle = (top + bottom) / 2;
- while (bottom <= top)
- {
- middle = (top + bottom) / 2;
-
- index = proxyModel->index(middle, 0);
- indexVisualRect = visualRect(index);
- // We need the whole height (not only the visualRect). This will help us to update
- // all needed indexes correctly (ereslibre)
- indexVisualRect.setHeight(indexVisualRect.height() + (itemHeight - indexVisualRect.height()));
-
- if (qMax(indexVisualRect.topLeft().y(),
- indexVisualRect.bottomRight().y()) < qMin(rect.topLeft().y(),
- rect.bottomRight().y()))
- {
- bottom = middle + 1;
- }
- else
- {
- top = middle - 1;
- }
- }
-
- for (int i = middle; i < proxyModel->rowCount(); i++)
- {
- index = proxyModel->index(i, 0);
- indexVisualRect = visualRect(index);
-
- if (rect.intersects(indexVisualRect))
- intersectedIndexes.append(index);
-
- // If we passed next item, stop searching for hits
- if (qMax(rect.bottomRight().y(), rect.topLeft().y()) <
- qMin(indexVisualRect.topLeft().y(),
- indexVisualRect.bottomRight().y()))
- break;
- }
-
- return intersectedIndexes;
-}
-
-QRect KCategorizedView::Private::visualRectInViewport(const QModelIndex &index) const
-{
- if (!index.isValid())
- return QRect();
-
- QString curCategory = elementsInfo[index.row()].category;
-
- QRect retRect;
-
- if (listView->layoutDirection() == Qt::LeftToRight)
- {
- retRect = QRect(listView->spacing(), listView->spacing() * 2 +
- categoryDrawer->categoryHeight(index, listView->viewOptions()), 0, 0);
- }
- else
- {
- retRect = QRect(listView->viewport()->width() - listView->spacing(), listView->spacing() * 2 +
- categoryDrawer->categoryHeight(index, listView->viewOptions()), 0, 0);
- }
-
- int viewportWidth = listView->viewport()->width() - listView->spacing();
-
- int itemHeight;
- int itemWidth;
-
- if (listView->gridSize().isEmpty())
- {
- itemHeight = biggestItemSize.height();
- itemWidth = biggestItemSize.width();
- }
- else
- {
- itemHeight = listView->gridSize().height();
- itemWidth = listView->gridSize().width();
- }
-
- int itemWidthPlusSeparation = listView->spacing() + itemWidth;
- int elementsPerRow = viewportWidth / itemWidthPlusSeparation;
- if (!elementsPerRow)
- elementsPerRow++;
-
- int column = elementsInfo[index.row()].relativeOffsetToCategory % elementsPerRow;
- int row = elementsInfo[index.row()].relativeOffsetToCategory / elementsPerRow;
-
- if (listView->layoutDirection() == Qt::LeftToRight)
- {
- retRect.setLeft(retRect.left() + column * listView->spacing() +
- column * itemWidth);
- }
- else
- {
- retRect.setLeft(retRect.right() - column * listView->spacing() -
- column * itemWidth - itemWidth);
-
- retRect.setRight(retRect.right() - column * listView->spacing() -
- column * itemWidth);
- }
-
- foreach (const QString &category, categories)
- {
- if (category == curCategory)
- break;
-
- float rows = (float) ((float) categoriesIndexes[category].count() /
- (float) elementsPerRow);
-
- int rowsInt = categoriesIndexes[category].count() / elementsPerRow;
-
- if (rows - trunc(rows)) rowsInt++;
-
- retRect.setTop(retRect.top() +
- (rowsInt * itemHeight) +
- categoryDrawer->categoryHeight(index, listView->viewOptions()) +
- listView->spacing() * 2);
-
- if (listView->gridSize().isEmpty())
- {
- retRect.setTop(retRect.top() +
- (rowsInt * listView->spacing()));
- }
- }
-
- if (listView->gridSize().isEmpty())
- {
- retRect.setTop(retRect.top() + row * listView->spacing() +
- (row * itemHeight));
- }
- else
- {
- retRect.setTop(retRect.top() + (row * itemHeight));
- }
-
- retRect.setWidth(itemWidth);
-
- QModelIndex heightIndex = proxyModel->index(index.row(), 0);
- if (listView->gridSize().isEmpty())
- {
- retRect.setHeight(listView->sizeHintForIndex(heightIndex).height());
- }
- else
- {
- retRect.setHeight(qMin(listView->sizeHintForIndex(heightIndex).height(),
- listView->gridSize().height()));
- }
-
- return retRect;
-}
-
-QRect KCategorizedView::Private::visualCategoryRectInViewport(const QString &category)
- const
-{
- QRect retRect(listView->spacing(),
- listView->spacing(),
- listView->viewport()->width() - listView->spacing() * 2,
- 0);
-
- if (!proxyModel->rowCount() || !categories.contains(category))
- return QRect();
-
- QModelIndex index = proxyModel->index(0, 0, QModelIndex());
-
- int viewportWidth = listView->viewport()->width() - listView->spacing();
-
- int itemHeight;
- int itemWidth;
-
- if (listView->gridSize().isEmpty())
- {
- itemHeight = biggestItemSize.height();
- itemWidth = biggestItemSize.width();
- }
- else
- {
- itemHeight = listView->gridSize().height();
- itemWidth = listView->gridSize().width();
- }
-
- int itemWidthPlusSeparation = listView->spacing() + itemWidth;
- int elementsPerRow = viewportWidth / itemWidthPlusSeparation;
-
- if (!elementsPerRow)
- elementsPerRow++;
-
- foreach (const QString &itCategory, categories)
- {
- if (itCategory == category)
- break;
-
- float rows = (float) ((float) categoriesIndexes[itCategory].count() /
- (float) elementsPerRow);
- int rowsInt = categoriesIndexes[itCategory].count() / elementsPerRow;
-
- if (rows - trunc(rows)) rowsInt++;
-
- retRect.setTop(retRect.top() +
- (rowsInt * itemHeight) +
- categoryDrawer->categoryHeight(index, listView->viewOptions()) +
- listView->spacing() * 2);
-
- if (listView->gridSize().isEmpty())
- {
- retRect.setTop(retRect.top() +
- (rowsInt * listView->spacing()));
- }
- }
-
- retRect.setHeight(categoryDrawer->categoryHeight(index, listView->viewOptions()));
-
- return retRect;
-}
-
-// We're sure elementsPosition doesn't contain index
-const QRect &KCategorizedView::Private::cacheIndex(const QModelIndex &index)
-{
- QRect rect = visualRectInViewport(index);
- elementsPosition[index.row()] = rect;
-
- return elementsPosition[index.row()];
-}
-
-// We're sure categoriesPosition doesn't contain category
-const QRect &KCategorizedView::Private::cacheCategory(const QString &category)
-{
- QRect rect = visualCategoryRectInViewport(category);
- categoriesPosition[category] = rect;
-
- return categoriesPosition[category];
-}
-
-const QRect &KCategorizedView::Private::cachedRectIndex(const QModelIndex &index)
-{
- if (elementsPosition.contains(index.row())) // If we have it cached
- { // return it
- return elementsPosition[index.row()];
- }
- else // Otherwise, cache it
- { // and return it
- return cacheIndex(index);
- }
-}
-
-const QRect &KCategorizedView::Private::cachedRectCategory(const QString &category)
-{
- if (categoriesPosition.contains(category)) // If we have it cached
- { // return it
- return categoriesPosition[category];
- }
- else // Otherwise, cache it and
- { // return it
- return cacheCategory(category);
- }
-}
-
-QRect KCategorizedView::Private::visualRect(const QModelIndex &index)
-{
- QRect retRect = cachedRectIndex(index);
- int dx = -listView->horizontalOffset();
- int dy = -listView->verticalOffset();
- retRect.adjust(dx, dy, dx, dy);
-
- return retRect;
-}
-
-QRect KCategorizedView::Private::categoryVisualRect(const QString &category)
-{
- QRect retRect = cachedRectCategory(category);
- int dx = -listView->horizontalOffset();
- int dy = -listView->verticalOffset();
- retRect.adjust(dx, dy, dx, dy);
-
- return retRect;
-}
-
-void KCategorizedView::Private::drawNewCategory(const QModelIndex &index,
- int sortRole,
- const QStyleOption &option,
- QPainter *painter)
-{
- if (!index.isValid())
- {
- return;
- }
-
- QStyleOption optionCopy = option;
- const QString category = proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
-
- optionCopy.state &= ~QStyle::State_Selected;
-
- if ((listView->selectionMode() != SingleSelection) && (listView->selectionMode() != NoSelection)) {
- if ((category == hoveredCategory) && !mouseButtonPressed)
- {
- optionCopy.state |= QStyle::State_MouseOver;
- }
- else if ((category == hoveredCategory) && mouseButtonPressed)
- {
- QPoint initialPressPosition = listView->viewport()->mapFromGlobal(QCursor::pos());
- initialPressPosition.setY(initialPressPosition.y() + listView->verticalOffset());
- initialPressPosition.setX(initialPressPosition.x() + listView->horizontalOffset());
-
- if (initialPressPosition == this->initialPressPosition)
- {
- optionCopy.state |= QStyle::State_Selected;
- }
- }
- }
-
- categoryDrawer->drawCategory(index,
- sortRole,
- optionCopy,
- painter);
-}
-
-
-void KCategorizedView::Private::updateScrollbars()
-{
- // find the last index in the last category
- QModelIndex lastIndex = categoriesIndexes.isEmpty() ? QModelIndex() : categoriesIndexes[categories.last()].last();
-
- int lastItemBottom = cachedRectIndex(lastIndex).top() +
- listView->spacing() + (listView->gridSize().isEmpty() ? biggestItemSize.height() : listView->gridSize().height()) - listView->viewport()->height();
-
- listView->horizontalScrollBar()->setRange(0, 0);
-
- listView->verticalScrollBar()->setSingleStep(listView->viewport()->height() / 10);
- listView->verticalScrollBar()->setPageStep(listView->viewport()->height());
- listView->verticalScrollBar()->setRange(0, lastItemBottom);
-}
-
-void KCategorizedView::Private::drawDraggedItems(QPainter *painter)
-{
- QStyleOptionViewItemV3 option = listView->viewOptions();
- option.state &= ~QStyle::State_MouseOver;
- foreach (const QModelIndex &index, listView->selectionModel()->selectedIndexes())
- {
- const int dx = mousePosition.x() - initialPressPosition.x() + listView->horizontalOffset();
- const int dy = mousePosition.y() - initialPressPosition.y() + listView->verticalOffset();
-
- option.rect = visualRect(index);
- option.rect.adjust(dx, dy, dx, dy);
-
- if (option.rect.intersects(listView->viewport()->rect()))
- {
- listView->itemDelegate(index)->paint(painter, option, index);
- }
- }
-}
-
-void KCategorizedView::Private::layoutChanged(bool forceItemReload)
-{
- if ((listView->viewMode() == KCategorizedView::IconMode) && proxyModel &&
- categoryDrawer && proxyModel->isCategorizedModel() &&
- ((forceItemReload ||
- (modelSortRole != proxyModel->sortRole()) ||
- (modelSortColumn != proxyModel->sortColumn()) ||
- (modelSortOrder != proxyModel->sortOrder()) ||
- (modelLastRowCount != proxyModel->rowCount()) ||
- (modelCategorized != proxyModel->isCategorizedModel()))))
- {
- // Force the view to update all elements
- listView->rowsInsertedArtifficial(QModelIndex(), 0, proxyModel->rowCount() - 1);
-
- if (!forceItemReload)
- {
- modelSortRole = proxyModel->sortRole();
- modelSortColumn = proxyModel->sortColumn();
- modelSortOrder = proxyModel->sortOrder();
- modelLastRowCount = proxyModel->rowCount();
- modelCategorized = proxyModel->isCategorizedModel();
- }
- }
- else if ((listView->viewMode() == KCategorizedView::IconMode) && proxyModel &&
- categoryDrawer && proxyModel->isCategorizedModel())
- {
- updateScrollbars();
- }
-}
-
-void KCategorizedView::Private::drawDraggedItems()
-{
- QRect rectToUpdate;
- QRect currentRect;
- foreach (const QModelIndex &index, listView->selectionModel()->selectedIndexes())
- {
- int dx = mousePosition.x() - initialPressPosition.x() + listView->horizontalOffset();
- int dy = mousePosition.y() - initialPressPosition.y() + listView->verticalOffset();
-
- currentRect = visualRect(index);
- currentRect.adjust(dx, dy, dx, dy);
-
- if (currentRect.intersects(listView->viewport()->rect()))
- {
- rectToUpdate = rectToUpdate.united(currentRect);
- }
- }
-
- listView->viewport()->update(lastDraggedItemsRect.united(rectToUpdate));
-
- lastDraggedItemsRect = rectToUpdate;
-}
-
-
-//==============================================================================
-
-
-KCategorizedView::KCategorizedView(QWidget *parent)
- : QListView(parent)
- , d(new Private(this))
-{
-}
-
-KCategorizedView::~KCategorizedView()
-{
- delete d;
-}
-
-void KCategorizedView::setGridSize(const QSize &size)
-{
- QListView::setGridSize(size);
-
- d->layoutChanged(true);
-}
-
-void KCategorizedView::setModel(QAbstractItemModel *model)
-{
- d->lastSelection = QItemSelection();
- d->forcedSelectionPosition = 0;
- d->elementsInfo.clear();
- d->elementsPosition.clear();
- d->categoriesIndexes.clear();
- d->categoriesPosition.clear();
- d->categories.clear();
- d->intersectedIndexes.clear();
- d->modelIndexList.clear();
- d->hovered = QModelIndex();
- d->mouseButtonPressed = false;
- d->rightMouseButtonPressed = false;
-
- if (d->proxyModel)
- {
- QObject::disconnect(d->proxyModel,
- SIGNAL(layoutChanged()),
- this, SLOT(slotLayoutChanged()));
-
- QObject::disconnect(d->proxyModel,
- SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(slotLayoutChanged()));
-
- QObject::disconnect(d->proxyModel,
- SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
- }
-
- QListView::setModel(model);
-
- d->proxyModel = dynamic_cast<KCategorizedSortFilterProxyModel*>(model);
-
- if (d->proxyModel)
- {
- d->modelSortRole = d->proxyModel->sortRole();
- d->modelSortColumn = d->proxyModel->sortColumn();
- d->modelSortOrder = d->proxyModel->sortOrder();
- d->modelLastRowCount = d->proxyModel->rowCount();
- d->modelCategorized = d->proxyModel->isCategorizedModel();
-
- QObject::connect(d->proxyModel,
- SIGNAL(layoutChanged()),
- this, SLOT(slotLayoutChanged()));
-
- QObject::connect(d->proxyModel,
- SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(slotLayoutChanged()));
-
- QObject::connect(d->proxyModel,
- SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
-
- if (d->proxyModel->rowCount())
- {
- d->layoutChanged(true);
- }
- }
- else
- {
- d->modelCategorized = false;
- }
-}
-
-QRect KCategorizedView::visualRect(const QModelIndex &index) const
-{
- if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
- {
- return QListView::visualRect(index);
- }
-
- if (!qobject_cast<const QSortFilterProxyModel*>(index.model()))
- {
- return d->visualRect(d->proxyModel->mapFromSource(index));
- }
-
- return d->visualRect(index);
-}
-
-KCategoryDrawer *KCategorizedView::categoryDrawer() const
-{
- return d->categoryDrawer;
-}
-
-void KCategorizedView::setCategoryDrawer(KCategoryDrawer *categoryDrawer)
-{
- d->lastSelection = QItemSelection();
- d->forcedSelectionPosition = 0;
- d->elementsInfo.clear();
- d->elementsPosition.clear();
- d->categoriesIndexes.clear();
- d->categoriesPosition.clear();
- d->categories.clear();
- d->intersectedIndexes.clear();
- d->modelIndexList.clear();
- d->hovered = QModelIndex();
- d->mouseButtonPressed = false;
- d->rightMouseButtonPressed = false;
-
- if (!categoryDrawer && d->proxyModel)
- {
- QObject::disconnect(d->proxyModel,
- SIGNAL(layoutChanged()),
- this, SLOT(slotLayoutChanged()));
-
- QObject::disconnect(d->proxyModel,
- SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(slotLayoutChanged()));
-
- QObject::disconnect(d->proxyModel,
- SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
- }
- else if (categoryDrawer && d->proxyModel)
- {
- QObject::connect(d->proxyModel,
- SIGNAL(layoutChanged()),
- this, SLOT(slotLayoutChanged()));
-
- QObject::connect(d->proxyModel,
- SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(slotLayoutChanged()));
-
- QObject::connect(d->proxyModel,
- SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)));
- }
-
- d->categoryDrawer = categoryDrawer;
-
- if (categoryDrawer)
- {
- if (d->proxyModel)
- {
- if (d->proxyModel->rowCount())
- {
- d->layoutChanged(true);
- }
- }
- }
- else
- {
- updateGeometries();
- }
-}
-
-QModelIndex KCategorizedView::indexAt(const QPoint &point) const
-{
- if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
- {
- return QListView::indexAt(point);
- }
-
- QModelIndex index;
-
- QModelIndexList item = d->intersectionSet(QRect(point, point));
-
- if (item.count() == 1)
- {
- index = item[0];
- }
-
- return index;
-}
-
-void KCategorizedView::reset()
-{
- QListView::reset();
-
- d->lastSelection = QItemSelection();
- d->forcedSelectionPosition = 0;
- d->elementsInfo.clear();
- d->elementsPosition.clear();
- d->categoriesIndexes.clear();
- d->categoriesPosition.clear();
- d->categories.clear();
- d->intersectedIndexes.clear();
- d->modelIndexList.clear();
- d->hovered = QModelIndex();
- d->biggestItemSize = QSize(0, 0);
- d->mouseButtonPressed = false;
- d->rightMouseButtonPressed = false;
-}
-
-void KCategorizedView::paintEvent(QPaintEvent *event)
-{
- if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
- {
- QListView::paintEvent(event);
- return;
- }
-
- QStyleOptionViewItemV3 option = viewOptions();
- option.widget = this;
- if (wordWrap())
- {
- option.features |= QStyleOptionViewItemV2::WrapText;
- }
-
- QPainter painter(viewport());
- QRect area = event->rect();
- const bool focus = (hasFocus() || viewport()->hasFocus()) &&
- currentIndex().isValid();
- const QStyle::State state = option.state;
- const bool enabled = (state & QStyle::State_Enabled) != 0;
-
- painter.save();
-
- QModelIndexList dirtyIndexes = d->intersectionSet(area);
- foreach (const QModelIndex &index, dirtyIndexes)
- {
- option.state = state;
- option.rect = visualRect(index);
-
- if (selectionModel() && selectionModel()->isSelected(index))
- {
- option.state |= QStyle::State_Selected;
- }
-
- if (enabled)
- {
- QPalette::ColorGroup cg;
- if ((d->proxyModel->flags(index) & Qt::ItemIsEnabled) == 0)
- {
- option.state &= ~QStyle::State_Enabled;
- cg = QPalette::Disabled;
- }
- else
- {
- cg = QPalette::Normal;
- }
- option.palette.setCurrentColorGroup(cg);
- }
-
- if (focus && currentIndex() == index)
- {
- option.state |= QStyle::State_HasFocus;
- if (this->state() == EditingState)
- option.state |= QStyle::State_Editing;
- }
-
- // we are only interested to give the mouse over feedback when no
- // dragging is happening (ereslibre)
- if ((index == d->hovered) && !d->mouseButtonPressed &&
- (this->state() == QAbstractItemView::NoState))
- option.state |= QStyle::State_MouseOver;
- else
- option.state &= ~QStyle::State_MouseOver;
-
- itemDelegate(index)->paint(&painter, option, index);
- }
-
- // Redraw categories
- QStyleOptionViewItem otherOption;
- bool intersectedInThePast = false;
- foreach (const QString &category, d->categories)
- {
- otherOption = option;
- otherOption.rect = d->categoryVisualRect(category);
- otherOption.state &= ~QStyle::State_MouseOver;
-
- if (otherOption.rect.intersects(area))
- {
- intersectedInThePast = true;
-
- QModelIndex indexToDraw = d->proxyModel->index(d->categoriesIndexes[category][0].row(), d->proxyModel->sortColumn());
-
- d->drawNewCategory(indexToDraw,
- d->proxyModel->sortRole(), otherOption, &painter);
- }
- else if (intersectedInThePast)
- {
- break; // the visible area has been finished, we don't need to keep asking, the rest won't intersect
- // this is doable because we know that categories are correctly ordered on the list
- }
- }
-
- if ((selectionMode() != SingleSelection) && (selectionMode() != NoSelection))
- {
- if (d->mouseButtonPressed && !d->isDragging)
- {
- QPoint start, end, initialPressPosition;
-
- initialPressPosition = d->initialPressPosition;
-
- initialPressPosition.setY(initialPressPosition.y() - verticalOffset());
- initialPressPosition.setX(initialPressPosition.x() - horizontalOffset());
-
- if (d->initialPressPosition.x() > d->mousePosition.x() ||
- d->initialPressPosition.y() > d->mousePosition.y())
- {
- start = d->mousePosition;
- end = initialPressPosition;
- }
- else
- {
- start = initialPressPosition;
- end = d->mousePosition;
- }
-
- QStyleOptionRubberBand yetAnotherOption;
- yetAnotherOption.initFrom(this);
- yetAnotherOption.shape = QRubberBand::Rectangle;
- yetAnotherOption.opaque = false;
- yetAnotherOption.rect = QRect(start, end).intersected(viewport()->rect().adjusted(-16, -16, 16, 16));
- painter.save();
- style()->drawControl(QStyle::CE_RubberBand, &yetAnotherOption, &painter);
- painter.restore();
- }
- }
-
- if (d->isDragging && !d->dragLeftViewport)
- {
- painter.setOpacity(0.5);
- d->drawDraggedItems(&painter);
- }
-
- painter.restore();
-}
-
-void KCategorizedView::resizeEvent(QResizeEvent *event)
-{
- QListView::resizeEvent(event);
-
- // Clear the items positions cache
- d->elementsPosition.clear();
- d->categoriesPosition.clear();
- d->forcedSelectionPosition = 0;
-
- if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
- {
- return;
- }
-
- d->updateScrollbars();
-}
-
-void KCategorizedView::setSelection(const QRect &rect,
- QItemSelectionModel::SelectionFlags flags)
-{
- if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
- {
- QListView::setSelection(rect, flags);
- return;
- }
-
- if (!flags)
- return;
-
- if (flags & QItemSelectionModel::Clear)
- {
- selectionModel()->clear();
- d->lastSelection.clear();
- }
-
- QModelIndexList dirtyIndexes = d->intersectionSet(rect);
-
- // no items affected, just leave
- if (!dirtyIndexes.count())
- {
- selectionModel()->select(d->lastSelection, QItemSelectionModel::SelectCurrent);
-
- return;
- }
-
- QModelIndex topLeft;
- QModelIndex bottomRight;
-
- if (d->mouseButtonPressed || d->rightMouseButtonPressed) // selection with click + drag
- {
- QItemSelection selection;
-
- QModelIndex prev = dirtyIndexes[0];
- QModelIndex first = prev;
- foreach (const QModelIndex &index, dirtyIndexes)
- {
- // we have a different interval. non-contiguous items
- if ((index.row() - prev.row()) > 1) {
- selection << QItemSelectionRange(first, prev);
-
- first = index;
- }
-
- prev = index;
- }
-
- selection << QItemSelectionRange(first, prev);
-
- if (flags & QItemSelectionModel::Current)
- {
- if (rect.topLeft() == rect.bottomRight())
- {
- selectionModel()->setCurrentIndex(indexAt(rect.topLeft()), QItemSelectionModel::NoUpdate);
- }
-
- selection.merge(d->lastSelection, flags);
- }
- else
- {
- selection.merge(selectionModel()->selection(), flags);
-
- selectionModel()->select(selection, QItemSelectionModel::SelectCurrent);
-
- return;
- }
-
- selectionModel()->select(selection, flags);
- }
- else // selection with click + keyboard keys
- {
- QModelIndex topLeftIndex = indexAt(QPoint(rect.topLeft().x(),
- rect.topLeft().y()));
- QModelIndex bottomRightIndex = indexAt(QPoint(rect.bottomRight().x(),
- rect.bottomRight().y()));
-
- // keyboard selection comes "upside down". Let's normalize it
- if (topLeftIndex.row() > bottomRightIndex.row())
- {
- QModelIndex auxIndex = topLeftIndex;
- topLeftIndex = bottomRightIndex;
- bottomRightIndex = auxIndex;
- }
-
- int viewportWidth = viewport()->width() - spacing();
- int itemWidth;
-
- if (gridSize().isEmpty())
- {
- itemWidth = d->biggestItemSize.width();
- }
- else
- {
- itemWidth = gridSize().width();
- }
-
- int itemWidthPlusSeparation = spacing() + itemWidth;
- int elementsPerRow = viewportWidth / itemWidthPlusSeparation;
- if (!elementsPerRow)
- elementsPerRow++;
-
- QModelIndexList theoricDirty(dirtyIndexes);
- dirtyIndexes.clear();
- int first = model()->rowCount();
- int last = 0;
-
- foreach (const QModelIndex &index, theoricDirty)
- {
- if ((index.row() < first) &&
- ((((topLeftIndex.row() / elementsPerRow) == (index.row() / elementsPerRow)) &&
- ((topLeftIndex.row() % elementsPerRow) <= (index.row() % elementsPerRow))) ||
- (topLeftIndex.row() / elementsPerRow) != (index.row() / elementsPerRow)))
- {
- first = index.row();
- topLeft = index;
- }
-
- if ((index.row() > last) &&
- ((((bottomRightIndex.row() / elementsPerRow) == (index.row() / elementsPerRow)) &&
- ((bottomRightIndex.row() % elementsPerRow) >= (index.row() % elementsPerRow))) ||
- (bottomRightIndex.row() / elementsPerRow) != (index.row() / elementsPerRow)))
- {
- last = index.row();
- bottomRight = index;
- }
- }
-
- for (int i = first; i <= last; i++)
- {
- dirtyIndexes << model()->index(i, theoricDirty[0].column(), theoricDirty[0].parent());
- }
-
- QItemSelection selection(topLeft, bottomRight);
-
- selectionModel()->select(selection, flags);
- }
-}
-
-void KCategorizedView::mouseMoveEvent(QMouseEvent *event)
-{
- QListView::mouseMoveEvent(event);
-
- if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
- {
- return;
- }
-
- QModelIndexList item = d->intersectionSet(QRect(event->pos(), event->pos()));
-
- if (item.count() == 1)
- {
- d->hovered = item[0];
- }
- else
- {
- d->hovered = QModelIndex();
- }
-
- const QString previousHoveredCategory = d->hoveredCategory;
-
- d->mousePosition = event->pos();
- d->hoveredCategory = QString();
-
- // Redraw categories
- foreach (const QString &category, d->categories)
- {
- if (d->categoryVisualRect(category).intersects(QRect(event->pos(), event->pos())))
- {
- d->hoveredCategory = category;
- viewport()->update(d->categoryVisualRect(category));
- }
- else if ((category == previousHoveredCategory) &&
- (!d->categoryVisualRect(previousHoveredCategory).intersects(QRect(event->pos(), event->pos()))))
- {
- viewport()->update(d->categoryVisualRect(category));
- }
- }
-
- QRect rect;
- if (d->mouseButtonPressed && !d->isDragging)
- {
- QPoint start, end, initialPressPosition;
-
- initialPressPosition = d->initialPressPosition;
-
- initialPressPosition.setY(initialPressPosition.y() - verticalOffset());
- initialPressPosition.setX(initialPressPosition.x() - horizontalOffset());
-
- if (d->initialPressPosition.x() > d->mousePosition.x() ||
- d->initialPressPosition.y() > d->mousePosition.y())
- {
- start = d->mousePosition;
- end = initialPressPosition;
- }
- else
- {
- start = initialPressPosition;
- end = d->mousePosition;
- }
-
- rect = QRect(start, end).adjusted(-16, -16, 16, 16);
- rect = rect.united(QRect(start, end).adjusted(16, 16, -16, -16)).intersected(viewport()->rect());
-
- viewport()->update(rect);
- }
-}
-
-void KCategorizedView::mousePressEvent(QMouseEvent *event)
-{
- d->dragLeftViewport = false;
-
- if (event->button() == Qt::LeftButton)
- {
- d->mouseButtonPressed = true;
-
- d->initialPressPosition = event->pos();
- d->initialPressPosition.setY(d->initialPressPosition.y() +
- verticalOffset());
- d->initialPressPosition.setX(d->initialPressPosition.x() +
- horizontalOffset());
- }
- else if (event->button() == Qt::RightButton)
- {
- d->rightMouseButtonPressed = true;
- }
-
- QListView::mousePressEvent(event);
-
- d->lastSelection = selectionModel()->selection();
-
- viewport()->update(d->categoryVisualRect(d->hoveredCategory));
-}
-
-void KCategorizedView::mouseReleaseEvent(QMouseEvent *event)
-{
- d->mouseButtonPressed = false;
- d->rightMouseButtonPressed = false;
-
- QListView::mouseReleaseEvent(event);
-
- if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
- {
- return;
- }
-
- QPoint initialPressPosition = viewport()->mapFromGlobal(QCursor::pos());
- initialPressPosition.setY(initialPressPosition.y() + verticalOffset());
- initialPressPosition.setX(initialPressPosition.x() + horizontalOffset());
-
- if ((selectionMode() != SingleSelection) && (selectionMode() != NoSelection) &&
- (initialPressPosition == d->initialPressPosition))
- {
- foreach(const QString &category, d->categories)
- {
- if (d->categoryVisualRect(category).contains(event->pos()))
- {
- QItemSelection selection = selectionModel()->selection();
- QModelIndexList indexList = d->categoriesIndexes[category];
-
- foreach (const QModelIndex &index, indexList)
- {
- QModelIndex selectIndex = index.model()->index(index.row(), 0);
-
- selection << QItemSelectionRange(selectIndex);
- }
-
- selectionModel()->select(selection, QItemSelectionModel::SelectCurrent);
-
- break;
- }
- }
- }
-
- QRect rect;
- if (!d->isDragging)
- {
- QPoint start, end, initialPressPosition;
-
- initialPressPosition = d->initialPressPosition;
-
- initialPressPosition.setY(initialPressPosition.y() - verticalOffset());
- initialPressPosition.setX(initialPressPosition.x() - horizontalOffset());
-
- if (d->initialPressPosition.x() > d->mousePosition.x() ||
- d->initialPressPosition.y() > d->mousePosition.y())
- {
- start = d->mousePosition;
- end = initialPressPosition;
- }
- else
- {
- start = initialPressPosition;
- end = d->mousePosition;
- }
-
- rect = QRect(start, end).adjusted(-16, -16, 16, 16);
- rect = rect.united(QRect(start, end).adjusted(16, 16, -16, -16)).intersected(viewport()->rect());
-
- viewport()->update(rect);
- }
-
- if (d->hovered.isValid())
- viewport()->update(visualRect(d->hovered));
- else if (!d->hoveredCategory.isEmpty())
- viewport()->update(d->categoryVisualRect(d->hoveredCategory));
-}
-
-void KCategorizedView::leaveEvent(QEvent *event)
-{
- d->hovered = QModelIndex();
- d->hoveredCategory = QString();
-
- QListView::leaveEvent(event);
-}
-
-void KCategorizedView::startDrag(Qt::DropActions supportedActions)
-{
- // FIXME: QAbstractItemView does far better here since it sets the
- // pixmap of selected icons to the dragging cursor, but it sets a non
- // ARGB window so it is no transparent. Use QAbstractItemView when
- // this is fixed on Qt.
- // QAbstractItemView::startDrag(supportedActions);
-#if !defined(DOLPHIN_DRAGANDDROP)
- QListView::startDrag(supportedActions);
-#endif
-
- d->isDragging = false;
- d->mouseButtonPressed = false;
- d->rightMouseButtonPressed = false;
-
- viewport()->update(d->lastDraggedItemsRect);
-}
-
-void KCategorizedView::dragMoveEvent(QDragMoveEvent *event)
-{
- d->mousePosition = event->pos();
-
- if (d->mouseButtonPressed)
- {
- d->isDragging = true;
- }
- else
- {
- d->isDragging = false;
- }
-
- d->dragLeftViewport = false;
-
-#if defined(DOLPHIN_DRAGANDDROP)
- QAbstractItemView::dragMoveEvent(event);
-#else
- QListView::dragMoveEvent(event);
-#endif
-
- if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
- {
- return;
- }
-
- d->drawDraggedItems();
-}
-
-void KCategorizedView::dragLeaveEvent(QDragLeaveEvent *event)
-{
- d->dragLeftViewport = true;
-
-#if defined(DOLPHIN_DRAGANDDROP)
- QAbstractItemView::dragLeaveEvent(event);
-#else
- QListView::dragLeaveEvent(event);
-#endif
-}
-
-void KCategorizedView::dropEvent(QDropEvent *event)
-{
-#if defined(DOLPHIN_DRAGANDDROP)
- QAbstractItemView::dropEvent(event);
-#else
- QListView::dropEvent(event);
-#endif
-}
-
-QModelIndex KCategorizedView::moveCursor(CursorAction cursorAction,
- Qt::KeyboardModifiers modifiers)
-{
- if ((viewMode() != KCategorizedView::IconMode) ||
- !d->proxyModel ||
- !d->categoryDrawer ||
- d->categories.isEmpty() ||
- !d->proxyModel->isCategorizedModel()
- )
- {
- return QListView::moveCursor(cursorAction, modifiers);
- }
-
- int viewportWidth = viewport()->width() - spacing();
- int itemWidth;
-
- if (gridSize().isEmpty())
- {
- itemWidth = d->biggestItemSize.width();
- }
- else
- {
- itemWidth = gridSize().width();
- }
-
- int itemWidthPlusSeparation = spacing() + itemWidth;
- int elementsPerRow = viewportWidth / itemWidthPlusSeparation;
- if (!elementsPerRow)
- elementsPerRow++;
-
- QModelIndex current = selectionModel()->currentIndex();
-
- if (!current.isValid())
- {
- if (cursorAction == MoveEnd)
- {
- current = model()->index(model()->rowCount() - 1, 0, QModelIndex());
- d->forcedSelectionPosition = d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow;
- }
- else
- {
- current = model()->index(0, 0, QModelIndex());
- d->forcedSelectionPosition = 0;
- }
-
- return current;
- }
- else if (!current.isValid())
- {
- return QModelIndex();
- }
-
- QString lastCategory = d->categories.first();
- QString theCategory = d->categories.first();
- QString afterCategory = d->categories.first();
-
- bool hasToBreak = false;
- foreach (const QString &category, d->categories)
- {
- if (hasToBreak)
- {
- afterCategory = category;
-
- break;
- }
-
- if (category == d->elementsInfo[current.row()].category)
- {
- theCategory = category;
-
- hasToBreak = true;
- }
-
- if (!hasToBreak)
- {
- lastCategory = category;
- }
- }
-
- switch (cursorAction)
- {
- case QAbstractItemView::MoveUp: {
- if (d->elementsInfo[current.row()].relativeOffsetToCategory >= elementsPerRow)
- {
- int indexToMove = current.row();
- indexToMove -= qMin(((d->elementsInfo[current.row()].relativeOffsetToCategory) + d->forcedSelectionPosition), elementsPerRow - d->forcedSelectionPosition + (d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow));
-
- return d->proxyModel->index(indexToMove, 0);
- }
- else
- {
- int lastCategoryLastRow = (d->categoriesIndexes[lastCategory].count() - 1) % elementsPerRow;
- int indexToMove = current.row() - d->elementsInfo[current.row()].relativeOffsetToCategory;
-
- if (d->forcedSelectionPosition >= lastCategoryLastRow)
- {
- indexToMove -= 1;
- }
- else
- {
- indexToMove -= qMin((lastCategoryLastRow - d->forcedSelectionPosition + 1), d->forcedSelectionPosition + elementsPerRow + 1);
- }
-
- return d->proxyModel->index(indexToMove, 0);
- }
- }
-
- case QAbstractItemView::MoveDown: {
- if (d->elementsInfo[current.row()].relativeOffsetToCategory < (d->categoriesIndexes[theCategory].count() - 1 - ((d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow)))
- {
- int indexToMove = current.row();
- indexToMove += qMin(elementsPerRow, d->categoriesIndexes[theCategory].count() - 1 - d->elementsInfo[current.row()].relativeOffsetToCategory);
-
- return d->proxyModel->index(indexToMove, 0);
- }
- else
- {
- int afterCategoryLastRow = qMin(elementsPerRow, d->categoriesIndexes[afterCategory].count());
- int indexToMove = current.row() + (d->categoriesIndexes[theCategory].count() - d->elementsInfo[current.row()].relativeOffsetToCategory);
-
- if (d->forcedSelectionPosition >= afterCategoryLastRow)
- {
- indexToMove += afterCategoryLastRow - 1;
- }
- else
- {
- indexToMove += qMin(d->forcedSelectionPosition, elementsPerRow);
- }
-
- return d->proxyModel->index(indexToMove, 0);
- }
- }
-
- case QAbstractItemView::MoveLeft:
- if (layoutDirection() == Qt::RightToLeft)
- {
- if (!(d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow))
- return current;
-
- d->forcedSelectionPosition = d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow;
-
-#if 0 //follow qt view behavior. lateral movements won't change visual row
- if (d->forcedSelectionPosition < 0)
- d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
-#endif
-
- return d->proxyModel->index(current.row() + 1, 0);
- }
-
- if (!(d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow))
- return current;
-
- d->forcedSelectionPosition = d->elementsInfo[current.row() - 1].relativeOffsetToCategory % elementsPerRow;
-
-#if 0 //follow qt view behavior. lateral movements won't change visual row
- if (d->forcedSelectionPosition < 0)
- d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
-#endif
-
- return d->proxyModel->index(current.row() - 1, 0);
-
- case QAbstractItemView::MoveRight:
- if (layoutDirection() == Qt::RightToLeft)
- {
- if (!(d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow))
- return current;
-
- d->forcedSelectionPosition = d->elementsInfo[current.row() - 1].relativeOffsetToCategory % elementsPerRow;
-
-#if 0 //follow qt view behavior. lateral movements won't change visual row
- if (d->forcedSelectionPosition < 0)
- d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
-#endif
-
- return d->proxyModel->index(current.row() - 1, 0);
- }
-
- if (!(d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow))
- return current;
-
- d->forcedSelectionPosition = d->elementsInfo[current.row() + 1].relativeOffsetToCategory % elementsPerRow;
-
-#if 0 //follow qt view behavior. lateral movements won't change visual row
- if (d->forcedSelectionPosition < 0)
- d->forcedSelectionPosition = (d->categoriesIndexes[theCategory].count() - 1) % elementsPerRow;
-#endif
-
- return d->proxyModel->index(current.row() + 1, 0);
-
- default:
- break;
- }
-
- return QListView::moveCursor(cursorAction, modifiers);
-}
-
-void KCategorizedView::rowsInserted(const QModelIndex &parent,
- int start,
- int end)
-{
- QListView::rowsInserted(parent, start, end);
-
- if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
- {
- d->forcedSelectionPosition = 0;
- d->elementsInfo.clear();
- d->elementsPosition.clear();
- d->categoriesIndexes.clear();
- d->categoriesPosition.clear();
- d->categories.clear();
- d->intersectedIndexes.clear();
- d->modelIndexList.clear();
- d->hovered = QModelIndex();
- d->biggestItemSize = QSize(0, 0);
- d->mouseButtonPressed = false;
- d->rightMouseButtonPressed = false;
-
- return;
- }
-
- rowsInsertedArtifficial(parent, start, end);
-}
-
-void KCategorizedView::rowsInsertedArtifficial(const QModelIndex &parent,
- int start,
- int end)
-{
- Q_UNUSED(parent);
-
- d->forcedSelectionPosition = 0;
- d->elementsInfo.clear();
- d->elementsPosition.clear();
- d->categoriesIndexes.clear();
- d->categoriesPosition.clear();
- d->categories.clear();
- d->intersectedIndexes.clear();
- d->modelIndexList.clear();
- d->hovered = QModelIndex();
- d->biggestItemSize = QSize(0, 0);
- d->mouseButtonPressed = false;
- d->rightMouseButtonPressed = false;
-
- if (start > end || end < 0 || start < 0 || !d->proxyModel->rowCount())
- {
- return;
- }
-
- // Add all elements mapped to the source model and explore categories
- QString prevCategory = d->proxyModel->data(d->proxyModel->index(0, d->proxyModel->sortColumn()), KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
- QString lastCategory = prevCategory;
- QModelIndexList modelIndexList;
- struct Private::ElementInfo elementInfo;
- int offset = -1;
- for (int k = 0; k < d->proxyModel->rowCount(); ++k)
- {
- QModelIndex index = d->proxyModel->index(k, d->proxyModel->sortColumn());
- QModelIndex indexSize = d->proxyModel->index(k, 0);
-
- d->biggestItemSize = QSize(qMax(sizeHintForIndex(indexSize).width(),
- d->biggestItemSize.width()),
- qMax(sizeHintForIndex(indexSize).height(),
- d->biggestItemSize.height()));
-
- d->modelIndexList << index;
-
- lastCategory = d->proxyModel->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
-
- elementInfo.category = lastCategory;
-
- if (prevCategory != lastCategory)
- {
- offset = 0;
- d->categoriesIndexes.insert(prevCategory, modelIndexList);
- d->categories << prevCategory;
- modelIndexList.clear();
- }
- else
- {
- offset++;
- }
-
- elementInfo.relativeOffsetToCategory = offset;
-
- modelIndexList << index;
- prevCategory = lastCategory;
-
- d->elementsInfo.insert(index.row(), elementInfo);
- }
-
- d->categoriesIndexes.insert(prevCategory, modelIndexList);
- d->categories << prevCategory;
-
- d->updateScrollbars();
-
- // FIXME: We need to safely save the last selection. This is on my TODO
- // list (ereslibre).
- selectionModel()->clear();
-}
-
-void KCategorizedView::rowsRemoved(const QModelIndex &parent,
- int start,
- int end)
-{
- if ((viewMode() == KCategorizedView::IconMode) && d->proxyModel &&
- d->categoryDrawer && d->proxyModel->isCategorizedModel())
- {
- // Force the view to update all elements
- rowsInsertedArtifficial(QModelIndex(), 0, d->proxyModel->rowCount() - 1);
- }
-}
-
-void KCategorizedView::updateGeometries()
-{
- if ((viewMode() != KCategorizedView::IconMode) || !d->proxyModel ||
- !d->categoryDrawer || !d->proxyModel->isCategorizedModel())
- {
- QListView::updateGeometries();
- return;
- }
-
- // Avoid QListView::updateGeometries(), since it will try to set another
- // range to our scroll bars, what we don't want (ereslibre)
- QAbstractItemView::updateGeometries();
-}
-
-void KCategorizedView::slotLayoutChanged()
-{
- d->layoutChanged();
-}
-
-void KCategorizedView::currentChanged(const QModelIndex ¤t,
- const QModelIndex &previous)
-{
- // We need to update the forcedSelectionPosition property in order to correctly
- // navigate after with keyboard using up & down keys
-
- int viewportWidth = viewport()->width() - spacing();
-
- int itemHeight;
- int itemWidth;
-
- if (gridSize().isEmpty())
- {
- itemHeight = d->biggestItemSize.height();
- itemWidth = d->biggestItemSize.width();
- }
- else
- {
- itemHeight = gridSize().height();
- itemWidth = gridSize().width();
- }
-
- int itemWidthPlusSeparation = spacing() + itemWidth;
- int elementsPerRow = viewportWidth / itemWidthPlusSeparation;
- if (!elementsPerRow)
- elementsPerRow++;
-
- if (d->mouseButtonPressed || d->rightMouseButtonPressed)
- d->forcedSelectionPosition = d->elementsInfo[current.row()].relativeOffsetToCategory % elementsPerRow;
-
- QListView::currentChanged(current, previous);
-}
-
-#include "kcategorizedview.moc"
+++ /dev/null
-/**
- * This file is part of the KDE project
- * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
- *
- * 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 KCATEGORIZEDVIEW_H
-#define KCATEGORIZEDVIEW_H
-
-#include <QtGui/QListView>
-
-#include <libdolphin_export.h>
-
-class KCategoryDrawer;
-
-/**
- * @short Item view for listing items
- *
- * KCategorizedView allows you to use it as it were a QListView. You can add an
- * itemCategorizer to it, so your items became categorized depending on the
- * KItemCategorizer inherited class rules.
- *
- * @see KItemCategorizer, KSortFilterProxyModel
- *
- * @author Rafael Fernández López <ereslibre@kde.org>
- */
-class LIBDOLPHINPRIVATE_EXPORT KCategorizedView
- : public QListView
-{
- Q_OBJECT
-
-public:
- KCategorizedView(QWidget *parent = 0);
-
- ~KCategorizedView();
-
- virtual void setModel(QAbstractItemModel *model);
-
- void setGridSize(const QSize &size);
-
- virtual QRect visualRect(const QModelIndex &index) const;
-
- KCategoryDrawer *categoryDrawer() const;
-
- void setCategoryDrawer(KCategoryDrawer *categoryDrawer);
-
- virtual QModelIndex indexAt(const QPoint &point) const;
-
-public Q_SLOTS:
- virtual void reset();
-
-protected:
- virtual void paintEvent(QPaintEvent *event);
-
- virtual void resizeEvent(QResizeEvent *event);
-
- virtual void setSelection(const QRect &rect,
- QItemSelectionModel::SelectionFlags flags);
-
- virtual void mouseMoveEvent(QMouseEvent *event);
-
- virtual void mousePressEvent(QMouseEvent *event);
-
- virtual void mouseReleaseEvent(QMouseEvent *event);
-
- virtual void leaveEvent(QEvent *event);
-
- virtual void startDrag(Qt::DropActions supportedActions);
-
- virtual void dragMoveEvent(QDragMoveEvent *event);
-
- virtual void dragLeaveEvent(QDragLeaveEvent *event);
-
- virtual void dropEvent(QDropEvent *event);
-
- virtual QModelIndex moveCursor(CursorAction cursorAction,
- Qt::KeyboardModifiers modifiers);
-
-protected Q_SLOTS:
- virtual void rowsInserted(const QModelIndex &parent,
- int start,
- int end);
-
- virtual void rowsInsertedArtifficial(const QModelIndex &parent,
- int start,
- int end);
-
- virtual void rowsRemoved(const QModelIndex &parent,
- int start,
- int end);
-
- virtual void updateGeometries();
-
- virtual void slotLayoutChanged();
-
- virtual void currentChanged(const QModelIndex ¤t,
- const QModelIndex &previous);
-
-
-private:
- class Private;
- Private *d;
-};
-
-#endif // KCATEGORIZEDVIEW_H
+++ /dev/null
-/**
- * This file is part of the KDE project
- * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
- *
- * 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 KCATEGORIZEDVIEW_P_H
-#define KCATEGORIZEDVIEW_P_H
-
-class KCategorizedSortFilterProxyModel;
-class KCategoryDrawer;
-
-/**
- * @internal
- */
-class KCategorizedView::Private
-{
-public:
- Private(KCategorizedView *listView);
- ~Private();
-
-
- // Methods
-
- /**
- * Returns the list of items that intersects with @p rect
- */
- const QModelIndexList &intersectionSet(const QRect &rect);
-
- /**
- * Gets the item rect in the viewport for @p index
- */
- QRect visualRectInViewport(const QModelIndex &index) const;
-
- /**
- * Returns the category rect in the viewport for @p category
- */
- QRect visualCategoryRectInViewport(const QString &category) const;
-
- /**
- * Caches and returns the rect that corresponds to @p index
- */
- const QRect &cacheIndex(const QModelIndex &index);
-
- /**
- * Caches and returns the rect that corresponds to @p category
- */
- const QRect &cacheCategory(const QString &category);
-
- /**
- * Returns the rect that corresponds to @p index
- * @note If the rect is not cached, it becomes cached
- */
- const QRect &cachedRectIndex(const QModelIndex &index);
-
- /**
- * Returns the rect that corresponds to @p category
- * @note If the rect is not cached, it becomes cached
- */
- const QRect &cachedRectCategory(const QString &category);
-
- /**
- * Returns the visual rect (taking in count x and y offsets) for @p index
- * @note If the rect is not cached, it becomes cached
- */
- QRect visualRect(const QModelIndex &index);
-
- /**
- * Returns the visual rect (taking in count x and y offsets) for @p category
- * @note If the rect is not cached, it becomes cached
- */
- QRect categoryVisualRect(const QString &category);
-
- /**
- * This method will draw a new category represented by index
- * @param index on the rect specified by @p option.rect, with
- * painter @p painter
- */
- void drawNewCategory(const QModelIndex &index,
- int sortRole,
- const QStyleOption &option,
- QPainter *painter);
-
- /**
- * This method will update scrollbars ranges. Called when our model changes
- * or when the view is resized
- */
- void updateScrollbars();
-
- /**
- * This method will draw dragged items in the painting operation
- */
- void drawDraggedItems(QPainter *painter);
-
- /**
- * This method will determine which rect needs to be updated because of a
- * dragging operation
- */
- void drawDraggedItems();
-
- void layoutChanged(bool forceItemReload = false);
-
-
- // Attributes
-
- struct ElementInfo
- {
- QString category;
- int relativeOffsetToCategory;
- };
-
- // Basic data
- KCategorizedView *listView;
- KCategoryDrawer *categoryDrawer;
- QSize biggestItemSize;
-
- // Behavior data
- bool mouseButtonPressed;
- bool rightMouseButtonPressed;
- bool isDragging;
- bool dragLeftViewport;
- QModelIndex hovered;
- QString hoveredCategory;
- QPoint initialPressPosition;
- QPoint mousePosition;
- int forcedSelectionPosition;
-
- // Cache data
- // We cannot merge some of them into structs because it would affect
- // performance
- QHash<int, struct ElementInfo> elementsInfo;
- QHash<int, QRect> elementsPosition;
- QHash<QString, QModelIndexList> categoriesIndexes;
- QHash<QString, QRect> categoriesPosition;
- QStringList categories;
- QModelIndexList intersectedIndexes;
- QRect lastDraggedItemsRect;
- int modelSortRole;
- int modelSortColumn;
- int modelLastRowCount;
- bool modelCategorized;
- Qt::SortOrder modelSortOrder;
- QItemSelection lastSelection;
-
- // Attributes for speed reasons
- KCategorizedSortFilterProxyModel *proxyModel;
- QModelIndexList modelIndexList;
-};
-
-#endif // KCATEGORIZEDVIEW_P_H
+++ /dev/null
-/**
- * This file is part of the KDE project
- * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
- *
- * 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 "kcategorydrawer.h"
-
-#include <QPainter>
-#include <QStyleOption>
-
-#include <kiconloader.h>
-#include <kcategorizedsortfilterproxymodel.h>
-
-KCategoryDrawer::KCategoryDrawer()
-{
-}
-
-KCategoryDrawer::~KCategoryDrawer()
-{
-}
-
-void KCategoryDrawer::drawCategory(const QModelIndex &index,
- int /*sortRole*/,
- const QStyleOption &option,
- QPainter *painter) const
-{
- const QString category = index.model()->data(index, KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
-
- QColor color;
-
- if (option.state & QStyle::State_Selected)
- {
- color = option.palette.color(QPalette::HighlightedText);
- }
- else
- {
- color = option.palette.color(QPalette::Text);
- }
-
- painter->save();
- painter->setRenderHint(QPainter::Antialiasing);
-
- if (option.state & QStyle::State_Selected)
- {
- QColor selected = option.palette.color(QPalette::Highlight);
-
- QLinearGradient gradient(option.rect.topLeft(),
- option.rect.bottomRight());
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 0
- : 1, selected);
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 1
- : 0, Qt::transparent);
-
- painter->fillRect(option.rect, gradient);
- }
- else if (option.state & QStyle::State_MouseOver)
- {
- QColor hover = option.palette.color(QPalette::Highlight).light();
- hover.setAlpha(88);
-
- QLinearGradient gradient(option.rect.topLeft(),
- option.rect.bottomRight());
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 0
- : 1, hover);
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 1
- : 0, Qt::transparent);
-
- painter->fillRect(option.rect, gradient);
- }
-
- QFont painterFont = painter->font();
- painterFont.setWeight(QFont::Bold);
- QFontMetrics metrics(painterFont);
- painter->setFont(painterFont);
-
- QRect lineRect(option.rect.left(),
- option.rect.bottom() - 1,
- option.rect.width(),
- 1);
-
- QLinearGradient gradient(option.rect.topLeft(),
- option.rect.bottomRight());
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 0
- : 1, color);
- gradient.setColorAt(option.direction == Qt::LeftToRight ? 1
- : 0, Qt::transparent);
-
- painter->fillRect(lineRect, gradient);
-
- painter->setPen(color);
-
- painter->drawText(option.rect, Qt::AlignVCenter | Qt::AlignLeft,
- metrics.elidedText(category, Qt::ElideRight, option.rect.width()));
-
- painter->restore();
-}
-
-int KCategoryDrawer::categoryHeight(const QModelIndex &index, const QStyleOption &option) const
-{
- Q_UNUSED(index);
-
- return option.fontMetrics.height() + 4 /* 3 separator; 1 gradient */;
-}
+++ /dev/null
-/**
- * This file is part of the KDE project
- * Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
- *
- * 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 KCATEGORYDRAWER_H
-#define KCATEGORYDRAWER_H
-
-#include <libdolphin_export.h>
-
-class QPainter;
-class QModelIndex;
-class QStyleOption;
-
-class LIBDOLPHINPRIVATE_EXPORT KCategoryDrawer
-{
-public:
- KCategoryDrawer();
-
- virtual ~KCategoryDrawer();
-
- /**
- * This method purpose is to draw a category represented by the given
- * @param index with the given @param sortRole sorting role
- *
- * @note This method will be called one time per category, always with the
- * first element in that category
- */
- virtual void drawCategory(const QModelIndex &index,
- int sortRole,
- const QStyleOption &option,
- QPainter *painter) const;
-
- virtual int categoryHeight(const QModelIndex &index, const QStyleOption &option) const;
-};
-
-#endif // KCATEGORYDRAWER_H
{
KAboutData about("dolphin", 0,
ki18nc("@title", "Dolphin"),
- "1.0.1",
+ "1.0.99",
ki18nc("@title", "File Manager"),
KAboutData::License_GPL,
ki18nc("@info:credit", "(C) 2006, 2007 Peter Penz"));
#include <kiconloader.h>
+#include <QLayout>
#include <QPainter>
#include <QPixmap>
#include <QKeyEvent>
PixmapViewer::PixmapViewer(QWidget* parent, Transition transition) :
QWidget(parent),
m_transition(transition),
- m_animationStep(0)
+ m_animationStep(0),
+ m_sizeHint()
{
setMinimumWidth(KIconLoader::SizeEnormous);
setMinimumHeight(KIconLoader::SizeEnormous);
}
}
+void PixmapViewer::setSizeHint(const QSize& size)
+{
+ m_sizeHint = size;
+ if ((parentWidget() != 0) && (parentWidget()->layout() != 0)) {
+ parentWidget()->layout()->activate();
+ }
+}
+
+QSize PixmapViewer::sizeHint() const
+{
+ return m_sizeHint;
+}
+
void PixmapViewer::paintEvent(QPaintEvent* event)
{
QWidget::paintEvent(event);
void setPixmap(const QPixmap& pixmap);
const QPixmap& pixmap() const;
+ /**
+ * Sets the size hint to \a size and triggers a relayout
+ * of the parent widget. Per default no size hint is given.
+ */
+ void setSizeHint(const QSize& size);
+ virtual QSize sizeHint() const;
+
protected:
virtual void paintEvent(QPaintEvent* event);
QTimeLine m_animation;
Transition m_transition;
int m_animationStep;
+ QSize m_sizeHint;
};
inline const QPixmap& PixmapViewer::pixmap() const
if (m_newName.isEmpty()) {
m_errorString = i18nc("@info:status",
"The new name is empty. A name with at least one character must be entered.");
- } else if (!m_renameOneItem && m_newName.count('#') != 1) {
+ } else if (!m_renameOneItem && (m_newName.count('#') == 0)) {
m_newName.truncate(0);
- m_errorString = i18nc("@info:status", "The name must contain exactly one # character.");
+ m_errorString = i18nc("@info:status", "The name must contain at least one # character.");
}
}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Peter Penz <peter.penz@gmx.at> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "selectionmanager.h"
+
+#include "dolphinmodel.h"
+#include "selectiontoggle.h"
+#include <kdirmodel.h>
+#include <kiconeffect.h>
+
+#include <QAbstractButton>
+#include <QAbstractItemView>
+#include <QAbstractProxyModel>
+#include <QModelIndex>
+#include <QPainter>
+#include <QPaintEvent>
+#include <QRect>
+#include <QTimeLine>
+
+SelectionManager::SelectionManager(QAbstractItemView* parent) :
+ QObject(parent),
+ m_view(parent),
+ m_toggle(0)
+{
+ connect(parent, SIGNAL(entered(const QModelIndex&)),
+ this, SLOT(slotEntered(const QModelIndex&)));
+ connect(parent, SIGNAL(viewportEntered()),
+ this, SLOT(slotViewportEntered()));
+ m_toggle = new SelectionToggle(m_view->viewport());
+ m_toggle->setCheckable(true);
+ m_toggle->hide();
+ connect(m_toggle, SIGNAL(clicked(bool)),
+ this, SLOT(setItemSelected(bool)));
+}
+
+SelectionManager::~SelectionManager()
+{
+}
+
+void SelectionManager::reset()
+{
+ m_toggle->reset();
+}
+
+void SelectionManager::slotEntered(const QModelIndex& index)
+{
+ m_toggle->hide();
+ if (index.isValid() && (index.column() == DolphinModel::Name)) {
+ m_toggle->setFileItem(itemForIndex(index));
+
+ connect(m_view->model(), SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
+ this, SLOT(slotRowsRemoved(const QModelIndex&, int, int)));
+
+ const QRect rect = m_view->visualRect(index);
+
+ const int gap = 2;
+ const int x = rect.left() + gap;
+ const int y = rect.top() + gap;
+ m_toggle->move(QPoint(x, y));
+
+ QItemSelectionModel* selModel = m_view->selectionModel();
+ m_toggle->setChecked(selModel->isSelected(index));
+ m_toggle->show();
+ } else {
+ m_toggle->setFileItem(KFileItem());
+ disconnect(m_view->model(), SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
+ this, SLOT(slotRowsRemoved(const QModelIndex&, int, int)));
+ }
+}
+
+void SelectionManager::slotViewportEntered()
+{
+ m_toggle->hide();
+}
+
+void SelectionManager::setItemSelected(bool selected)
+{
+ emit selectionChanged();
+ Q_ASSERT(!m_toggle->fileItem().isNull());
+
+ const QModelIndex index = indexForItem(m_toggle->fileItem());
+ if (index.isValid()) {
+ QItemSelectionModel* selModel = m_view->selectionModel();
+ if (selected) {
+ selModel->select(index, QItemSelectionModel::Select);
+ } else {
+ selModel->select(index, QItemSelectionModel::Deselect);
+ }
+ }
+}
+
+void SelectionManager::slotRowsRemoved(const QModelIndex& parent, int start, int end)
+{
+ Q_UNUSED(parent);
+ Q_UNUSED(start);
+ Q_UNUSED(end);
+ m_toggle->hide();
+}
+
+KFileItem SelectionManager::itemForIndex(const QModelIndex& index) const
+{
+ QAbstractProxyModel* proxyModel = static_cast<QAbstractProxyModel*>(m_view->model());
+ KDirModel* dirModel = static_cast<KDirModel*>(proxyModel->sourceModel());
+ const QModelIndex dirIndex = proxyModel->mapToSource(index);
+ return dirModel->itemForIndex(dirIndex);
+}
+
+const QModelIndex SelectionManager::indexForItem(const KFileItem& item) const
+{
+ QAbstractProxyModel* proxyModel = static_cast<QAbstractProxyModel*>(m_view->model());
+ KDirModel* dirModel = static_cast<KDirModel*>(proxyModel->sourceModel());
+ const QModelIndex dirIndex = dirModel->indexForItem(item);
+ return proxyModel->mapFromSource(dirIndex);
+}
+
+#include "selectionmanager.moc"
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Peter Penz <peter.penz@gmx.at> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef SELECTIONMANAGER_H
+#define SELECTIONMANAGER_H
+
+#include <kfileitem.h>
+
+#include <QObject>
+
+class DolphinSortFilterProxyModel;
+class QAbstractItemView;
+class QModelIndex;
+class QAbstractButton;
+class SelectionToggle;
+
+/**
+ * @brief Allows to select and deselect items for the single-click mode.
+ *
+ * Whenever an item is hovered by the mouse, a toggle button is shown
+ * which allows to select/deselect the current item.
+ */
+class SelectionManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ SelectionManager(QAbstractItemView* parent);
+ virtual ~SelectionManager();
+
+public slots:
+ /**
+ * Resets the selection manager so that the toggle button gets
+ * invisible.
+ */
+ void reset();
+
+signals:
+ /** Is emitted if the selection has been changed by the toggle button. */
+ void selectionChanged();
+
+private slots:
+ void slotEntered(const QModelIndex& index);
+ void slotViewportEntered();
+ void setItemSelected(bool selected);
+ void slotRowsRemoved(const QModelIndex& parent, int start, int end);
+
+private:
+ KFileItem itemForIndex(const QModelIndex& index) const;
+ const QModelIndex indexForItem(const KFileItem& item) const;
+
+private:
+ QAbstractItemView* m_view;
+ SelectionToggle* m_toggle;
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Peter Penz <peter.penz@gmx.at> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "selectiontoggle.h"
+
+#include <kicon.h>
+#include <kiconloader.h>
+#include <kiconeffect.h>
+
+#include <QPainter>
+#include <QPaintEvent>
+#include <QRect>
+#include <QTimer>
+#include <QTimeLine>
+
+SelectionToggle::SelectionToggle(QWidget* parent) :
+ QAbstractButton(parent),
+ m_isHovered(false),
+ m_fadingValue(0),
+ m_icon(),
+ m_fadingTimeLine(0)
+{
+ parent->installEventFilter(this);
+ resize(sizeHint());
+ m_icon = KIconLoader::global()->loadIcon("dialog-ok",
+ KIconLoader::NoGroup,
+ KIconLoader::SizeSmall);
+}
+
+SelectionToggle::~SelectionToggle()
+{
+}
+
+QSize SelectionToggle::sizeHint() const
+{
+ return QSize(16, 16);
+}
+
+void SelectionToggle::reset()
+{
+ m_item = KFileItem();
+ hide();
+}
+
+void SelectionToggle::setFileItem(const KFileItem& item)
+{
+ m_item = item;
+ if (!item.isNull()) {
+ startFading();
+ }
+}
+
+KFileItem SelectionToggle::fileItem() const
+{
+ return m_item;
+}
+
+void SelectionToggle::setVisible(bool visible)
+{
+ QAbstractButton::setVisible(visible);
+
+ stopFading();
+ if (visible) {
+ startFading();
+ }
+
+}
+
+bool SelectionToggle::eventFilter(QObject* obj, QEvent* event)
+{
+ if ((obj == parent()) && (event->type() == QEvent::Leave)) {
+ hide();
+ }
+ return QAbstractButton::eventFilter(obj, event);
+}
+
+void SelectionToggle::enterEvent(QEvent* event)
+{
+ QAbstractButton::enterEvent(event);
+
+ // if the mouse cursor is above the selection toggle, display
+ // it immediately without fading timer
+ m_isHovered = true;
+ if (m_fadingTimeLine != 0) {
+ m_fadingTimeLine->stop();
+ }
+ m_fadingValue = 255;
+ update();
+}
+
+void SelectionToggle::leaveEvent(QEvent* event)
+{
+ QAbstractButton::leaveEvent(event);
+ m_isHovered = false;
+ update();
+}
+
+void SelectionToggle::paintEvent(QPaintEvent* event)
+{
+ QPainter painter(this);
+ painter.setClipRect(event->rect());
+
+ if (m_isHovered) {
+ KIconEffect iconEffect;
+ QPixmap activeIcon = iconEffect.apply(m_icon, KIconLoader::Desktop, KIconLoader::ActiveState);
+ painter.drawPixmap(0, 0, activeIcon);
+ } else {
+ if (m_fadingValue < 255) {
+ // apply an alpha mask respecting the fading value to the icon
+ QPixmap icon = m_icon;
+ QPixmap alphaMask(icon.width(), icon.height());
+ const QColor color(m_fadingValue, m_fadingValue, m_fadingValue);
+ alphaMask.fill(color);
+ icon.setAlphaChannel(alphaMask);
+ painter.drawPixmap(0, 0, icon);
+ } else {
+ // no fading is required
+ painter.drawPixmap(0, 0, m_icon);
+ }
+ }
+}
+
+void SelectionToggle::setFadingValue(int value)
+{
+ m_fadingValue = value;
+ if (m_fadingValue >= 255) {
+ Q_ASSERT(m_fadingTimeLine != 0);
+ m_fadingTimeLine->stop();
+ }
+ update();
+}
+
+void SelectionToggle::startFading()
+{
+ Q_ASSERT(m_fadingTimeLine == 0);
+
+ m_fadingTimeLine = new QTimeLine(2000, this);
+ connect(m_fadingTimeLine, SIGNAL(frameChanged(int)),
+ this, SLOT(setFadingValue(int)));
+ m_fadingTimeLine->setFrameRange(0, 255);
+ m_fadingTimeLine->start();
+ m_fadingValue = 0;
+}
+
+void SelectionToggle::stopFading()
+{
+ if (m_fadingTimeLine != 0) {
+ m_fadingTimeLine->stop();
+ delete m_fadingTimeLine;
+ m_fadingTimeLine = 0;
+ }
+ m_fadingValue = 0;
+}
+
+#include "selectiontoggle.moc"
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Peter Penz <peter.penz@gmx.at> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef SELECTIONTOGGLE_H
+#define SELECTIONTOGGLE_H
+
+#include <kfileitem.h>
+
+#include <QAbstractButton>
+#include <QPixmap>
+
+class QTimeLine;
+
+/**
+ * @brief Toggle button for changing the selection of an hovered item.
+ *
+ * The toggle button is visually invisible until it is displayed at least
+ * for one second.
+ *
+ * @see SelectionManager
+ */
+class SelectionToggle : public QAbstractButton
+{
+ Q_OBJECT
+
+public:
+ explicit SelectionToggle(QWidget* parent);
+ virtual ~SelectionToggle();
+ virtual QSize sizeHint() const;
+
+ /**
+ * Resets the selection toggle so that it is hidden and stays
+ * visually invisible for at least one second after it is shown again.
+ */
+ void reset();
+
+ void setFileItem(const KFileItem& item);
+ KFileItem fileItem() const;
+
+public slots:
+ virtual void setVisible(bool visible);
+
+protected:
+ virtual bool eventFilter(QObject* obj, QEvent* event);
+ virtual void enterEvent(QEvent* event);
+ virtual void leaveEvent(QEvent* event);
+ virtual void paintEvent(QPaintEvent* event);
+
+private slots:
+ /**
+ * Sets the alpha value for the fading animation and is
+ * connected with m_fadingTimeLine.
+ */
+ void setFadingValue(int value);
+
+private:
+ void startFading();
+ void stopFading();
+
+private:
+ bool m_isHovered;
+ int m_fadingValue;
+ QPixmap m_icon;
+ QTimeLine* m_fadingTimeLine;
+ KFileItem m_item;
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Peter Penz <peter.penz@gmx.at> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "startupsettingspage.h"
+
+#include "dolphinsettings.h"
+#include "dolphinmainwindow.h"
+#include "dolphinview.h"
+#include "dolphinviewcontainer.h"
+
+#include "dolphin_generalsettings.h"
+
+#include <kdialog.h>
+#include <kfiledialog.h>
+#include <klocale.h>
+#include <kvbox.h>
+
+#include <QCheckBox>
+#include <QGroupBox>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QRadioButton>
+
+StartupSettingsPage::StartupSettingsPage(DolphinMainWindow* mainWin, QWidget* parent) :
+ SettingsPageBase(parent),
+ m_mainWindow(mainWin),
+ m_homeUrl(0),
+ m_splitView(0),
+ m_editableUrl(0),
+ m_filterBar(0)
+{
+ const int spacing = KDialog::spacingHint();
+
+ QVBoxLayout* topLayout = new QVBoxLayout(this);
+ KVBox* vBox = new KVBox(this);
+ vBox->setSpacing(spacing);
+
+ // create 'Home URL' editor
+ QGroupBox* homeBox = new QGroupBox(i18nc("@title:group", "Home Folder"), vBox);
+
+ KHBox* homeUrlBox = new KHBox(homeBox);
+ homeUrlBox->setSpacing(spacing);
+
+ new QLabel(i18nc("@label:textbox", "Location:"), homeUrlBox);
+ m_homeUrl = new QLineEdit(homeUrlBox);
+
+ QPushButton* selectHomeUrlButton = new QPushButton(KIcon("folder-open"), QString(), homeUrlBox);
+ connect(selectHomeUrlButton, SIGNAL(clicked()),
+ this, SLOT(selectHomeUrl()));
+
+ KHBox* buttonBox = new KHBox(homeBox);
+ buttonBox->setSpacing(spacing);
+
+ QPushButton* useCurrentButton = new QPushButton(i18nc("@action:button", "Use Current Location"), buttonBox);
+ connect(useCurrentButton, SIGNAL(clicked()),
+ this, SLOT(useCurrentLocation()));
+ QPushButton* useDefaultButton = new QPushButton(i18nc("@action:button", "Use Default Location"), buttonBox);
+ connect(useDefaultButton, SIGNAL(clicked()),
+ this, SLOT(useDefaultLocation()));
+
+ QVBoxLayout* homeBoxLayout = new QVBoxLayout(homeBox);
+ homeBoxLayout->addWidget(homeUrlBox);
+ homeBoxLayout->addWidget(buttonBox);
+
+ // create 'Split view', 'Editable location' and 'Filter bar' checkboxes
+ m_splitView = new QCheckBox(i18nc("@option:check Startup Settings", "Split view mode"), vBox);
+ m_editableUrl = new QCheckBox(i18nc("@option:check Startup Settings", "Editable location bar"), vBox);
+ m_filterBar = new QCheckBox(i18nc("@option:check Startup Settings", "Show filter bar"), vBox);
+
+ // Add a dummy widget with no restriction regarding
+ // a vertical resizing. This assures that the dialog layout
+ // is not stretched vertically.
+ new QWidget(vBox);
+
+ topLayout->addWidget(vBox);
+
+ loadSettings();
+}
+
+StartupSettingsPage::~StartupSettingsPage()
+{
+}
+
+void StartupSettingsPage::applySettings()
+{
+ GeneralSettings* settings = DolphinSettings::instance().generalSettings();
+
+ const KUrl url(m_homeUrl->text());
+ KFileItem fileItem(S_IFDIR, KFileItem::Unknown, url);
+ if (url.isValid() && fileItem.isDir()) {
+ settings->setHomeUrl(url.prettyUrl());
+ }
+
+ settings->setSplitView(m_splitView->isChecked());
+ settings->setEditableUrl(m_editableUrl->isChecked());
+ settings->setFilterBar(m_filterBar->isChecked());
+}
+
+void StartupSettingsPage::restoreDefaults()
+{
+ GeneralSettings* settings = DolphinSettings::instance().generalSettings();
+ settings->setDefaults();
+ loadSettings();
+}
+
+void StartupSettingsPage::selectHomeUrl()
+{
+ const QString homeUrl = m_homeUrl->text();
+ KUrl url = KFileDialog::getExistingDirectoryUrl(homeUrl);
+ if (!url.isEmpty()) {
+ m_homeUrl->setText(url.prettyUrl());
+ }
+}
+
+void StartupSettingsPage::useCurrentLocation()
+{
+ const DolphinView* view = m_mainWindow->activeViewContainer()->view();
+ m_homeUrl->setText(view->url().prettyUrl());
+}
+
+void StartupSettingsPage::useDefaultLocation()
+{
+ m_homeUrl->setText("file://" + QDir::homePath());
+}
+
+void StartupSettingsPage::loadSettings()
+{
+ GeneralSettings* settings = DolphinSettings::instance().generalSettings();
+ m_homeUrl->setText(settings->homeUrl());
+ m_splitView->setChecked(settings->splitView());
+ m_editableUrl->setChecked(settings->editableUrl());
+ m_filterBar->setChecked(settings->filterBar());
+}
+
+#include "startupsettingspage.moc"
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Peter Penz <peter.penz@gmx.at> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+#ifndef STARTUPSETTINGSPAGE_H
+#define STARTUPSETTINGSPAGE_H
+
+#include <settingspagebase.h>
+
+class DolphinMainWindow;
+class QLineEdit;
+class QCheckBox;
+
+/**
+ * @brief Page for the 'Startup' settings of the Dolphin settings dialog.
+ *
+ * The startup settings allow to set the home URL and to configure the
+ * state of the view mode, split mode and the filter bar when starting Dolphin.
+ */
+class StartupSettingsPage : public SettingsPageBase
+{
+ Q_OBJECT
+
+public:
+ StartupSettingsPage(DolphinMainWindow* mainWindow, QWidget* parent);
+ virtual ~StartupSettingsPage();
+
+ /** @see SettingsPageBase::applySettings() */
+ virtual void applySettings();
+
+ /** @see SettingsPageBase::restoreDefaults() */
+ virtual void restoreDefaults();
+
+private slots:
+ void selectHomeUrl();
+ void useCurrentLocation();
+ void useDefaultLocation();
+
+private:
+ void loadSettings();
+
+private:
+ DolphinMainWindow* m_mainWindow;
+ QLineEdit* m_homeUrl;
+
+ QCheckBox* m_splitView;
+ QCheckBox* m_editableUrl;
+ QCheckBox* m_filterBar;
+};
+
+#endif
propsBox = new QGroupBox(i18nc("@title:group", "Properties"), main);
}
- QLabel* viewModeLabel = new QLabel(i18nc("@label:listbox", "View mode:"), propsBox);
- m_viewMode = new QComboBox(propsBox);
+ QWidget* propsGrid = new QWidget();
+
+ QLabel* viewModeLabel = new QLabel(i18nc("@label:listbox", "View mode:"), propsGrid);
+ m_viewMode = new QComboBox(propsGrid);
m_viewMode->addItem(KIcon("view-list-icons"), i18nc("@item:inlistbox", "Icons"));
m_viewMode->addItem(KIcon("view-list-details"), i18nc("@item:inlistbox", "Details"));
m_viewMode->addItem(KIcon("view-file-columns"), i18nc("@item:inlistbox", "Column"));
- QLabel* sortingLabel = new QLabel(i18nc("@label:listbox", "Sorting:"), propsBox);
- QWidget* sortingBox = new QWidget(propsBox);
+ QLabel* sortingLabel = new QLabel(i18nc("@label:listbox", "Sorting:"), propsGrid);
+ QWidget* sortingBox = new QWidget(propsGrid);
m_sortOrder = new QComboBox(sortingBox);
m_sortOrder->addItem(i18nc("@item:inlistbox", "Ascending"));
// m_sorting->addItem(i18nc("@item:inlistbox Sort", "By Tags"));
// }
#endif
+ m_showPreview = new QCheckBox(i18nc("@option:check", "Show preview"), propsBox);
+ m_showInGroups = new QCheckBox(i18nc("@option:check", "Show in groups"), propsBox);
+ m_showHiddenFiles = new QCheckBox(i18nc("@option:check", "Show hidden files"), propsBox);
+
+ m_additionalInfo = new QPushButton(i18nc("@action:button", "Additional Information"), propsBox);
QHBoxLayout* sortingLayout = new QHBoxLayout();
sortingLayout->setMargin(0);
sortingLayout->addWidget(m_sorting);
sortingBox->setLayout(sortingLayout);
- m_showPreview = new QCheckBox(i18nc("@option:check", "Show preview"), propsBox);
- m_showInGroups = new QCheckBox(i18nc("@option:check", "Show in Groups"), propsBox);
- m_showHiddenFiles = new QCheckBox(i18nc("@option:check", "Show hidden files"), propsBox);
+ QGridLayout* propsGridLayout = new QGridLayout(propsGrid);
+ propsGridLayout->addWidget(viewModeLabel, 0, 0);
+ propsGridLayout->addWidget(m_viewMode, 0, 1);
+ propsGridLayout->addWidget(sortingLabel, 1, 0);
+ propsGridLayout->addWidget(sortingBox, 1, 1);
- m_additionalInfo = new QPushButton(i18nc("@action:button", "Additional Information"), propsBox);
- connect(m_additionalInfo, SIGNAL(clicked()),
- this, SLOT(configureAdditionalInfo()));
-
- QGridLayout* propsBoxLayout = new QGridLayout(propsBox);
- propsBoxLayout->addWidget(viewModeLabel, 0, 0);
- propsBoxLayout->addWidget(m_viewMode, 0, 1);
- propsBoxLayout->addWidget(sortingLabel, 1, 0);
- propsBoxLayout->addWidget(sortingBox, 1, 1);
- propsBoxLayout->addWidget(m_showPreview, 2, 0);
- propsBoxLayout->addWidget(m_showInGroups, 3, 0);
- propsBoxLayout->addWidget(m_showHiddenFiles, 4, 0);
- propsBoxLayout->addWidget(m_additionalInfo, 5, 0);
+ QVBoxLayout* propsBoxLayout = new QVBoxLayout(propsBox);
+ propsBoxLayout->addWidget(propsGrid);
+ propsBoxLayout->addWidget(m_showPreview);
+ propsBoxLayout->addWidget(m_showInGroups);
+ propsBoxLayout->addWidget(m_showHiddenFiles);
+ propsBoxLayout->addWidget(m_additionalInfo);
topLayout->addWidget(propsBox);
this, SLOT(slotSortingChanged(int)));
connect(m_sortOrder, SIGNAL(activated(int)),
this, SLOT(slotSortOrderChanged(int)));
- connect(m_additionalInfo, SIGNAL(activated(int)),
- this, SLOT(slotAdditionalInfoChanged(int)));
+ connect(m_additionalInfo, SIGNAL(clicked()),
+ this, SLOT(configureAdditionalInfo()));
connect(m_showPreview, SIGNAL(clicked()),
this, SLOT(slotShowPreviewChanged()));
connect(m_showInGroups, SIGNAL(clicked()),