|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2006 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 "dolphindetailsview.h"
|
|
|
|
|
|
|
|
#include <kurldrag.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqobjectlist.h>
|
|
|
|
#include <tqheader.h>
|
|
|
|
#include <tqclipboard.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tdeglobalsettings.h>
|
|
|
|
#include <tqscrollbar.h>
|
|
|
|
#include <tqcursor.h>
|
|
|
|
#include <tqstyle.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "dolphinview.h"
|
|
|
|
#include "viewproperties.h"
|
|
|
|
#include "dolphin.h"
|
|
|
|
#include "kiconeffect.h"
|
|
|
|
#include "dolphinsettings.h"
|
|
|
|
#include "dolphinstatusbar.h"
|
|
|
|
#include "dolphindetailsviewsettings.h"
|
|
|
|
|
|
|
|
DolphinDetailsView::DolphinDetailsView(DolphinView* parent) :
|
|
|
|
KFileDetailView(parent, 0),
|
|
|
|
m_dolphinView(parent),
|
|
|
|
m_resizeTimer(0),
|
|
|
|
m_scrollTimer(0),
|
|
|
|
m_rubber(0)
|
|
|
|
{
|
|
|
|
m_resizeTimer = new TQTimer(this);
|
|
|
|
connect(m_resizeTimer, TQT_SIGNAL(timeout()),
|
|
|
|
this, TQT_SLOT(updateColumnsWidth()));
|
|
|
|
|
|
|
|
setAcceptDrops(true);
|
|
|
|
setSelectionMode(KFile::Extended);
|
|
|
|
setHScrollBarMode(TQScrollView::AlwaysOff);
|
|
|
|
|
|
|
|
setColumnAlignment(SizeColumn, TQt::AlignRight);
|
|
|
|
for (int i = DateColumn; i <= GroupColumn; ++i) {
|
|
|
|
setColumnAlignment(i, TQt::AlignHCenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
Dolphin& dolphin = Dolphin::mainWin();
|
|
|
|
|
|
|
|
connect(this, TQT_SIGNAL(onItem(TQListViewItem*)),
|
|
|
|
this, TQT_SLOT(slotOnItem(TQListViewItem*)));
|
|
|
|
connect(this, TQT_SIGNAL(onViewport()),
|
|
|
|
this, TQT_SLOT(slotOnViewport()));
|
|
|
|
connect(this, TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint&, int)),
|
|
|
|
this, TQT_SLOT(slotContextMenuRequested(TQListViewItem*, const TQPoint&, int)));
|
|
|
|
connect(this, TQT_SIGNAL(selectionChanged()),
|
|
|
|
&dolphin, TQT_SLOT(slotSelectionChanged()));
|
|
|
|
connect(&dolphin, TQT_SIGNAL(activeViewChanged()),
|
|
|
|
this, TQT_SLOT(slotActivationUpdate()));
|
|
|
|
connect(this, TQT_SIGNAL(itemRenamed(TQListViewItem*, const TQString&, int)),
|
|
|
|
this, TQT_SLOT(slotItemRenamed(TQListViewItem*, const TQString&, int)));
|
|
|
|
connect(this, TQT_SIGNAL(dropped(TQDropEvent*, const KURL::List&, const KURL&)),
|
|
|
|
parent, TQT_SLOT(slotURLListDropped(TQDropEvent*, const KURL::List&, const KURL&)));
|
|
|
|
|
|
|
|
TQClipboard* clipboard = TQApplication::clipboard();
|
|
|
|
connect(clipboard, TQT_SIGNAL(dataChanged()),
|
|
|
|
this, TQT_SLOT(slotUpdateDisabledItems()));
|
|
|
|
|
|
|
|
TQHeader* viewHeader = header();
|
|
|
|
viewHeader->setResizeEnabled(false);
|
|
|
|
viewHeader->setMovingEnabled(false);
|
|
|
|
connect(viewHeader, TQT_SIGNAL(clicked(int)),
|
|
|
|
this, TQT_SLOT(slotHeaderClicked(int)));
|
|
|
|
|
|
|
|
setMouseTracking(true);
|
|
|
|
setDefaultRenameAction(TQListView::Accept);
|
|
|
|
|
|
|
|
refreshSettings();
|
|
|
|
}
|
|
|
|
|
|
|
|
DolphinDetailsView::~DolphinDetailsView()
|
|
|
|
{
|
|
|
|
delete m_rubber;
|
|
|
|
m_rubber = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::beginItemUpdates()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::endItemUpdates()
|
|
|
|
{
|
|
|
|
updateDisabledItems();
|
|
|
|
|
|
|
|
// Restore the current item. Use the information stored in the history if
|
|
|
|
// available. Otherwise use the first item as current item.
|
|
|
|
|
|
|
|
const KFileListViewItem* item = static_cast<const KFileListViewItem*>(firstChild());
|
|
|
|
if (item != 0) {
|
|
|
|
setCurrentItem(item->fileInfo());
|
|
|
|
}
|
|
|
|
|
|
|
|
int index = 0;
|
|
|
|
const TQValueList<URLNavigator::HistoryElem> history = m_dolphinView->urlHistory(index);
|
|
|
|
if (!history.isEmpty()) {
|
|
|
|
KFileView* fileView = static_cast<KFileView*>(this);
|
|
|
|
fileView->setCurrentItem(history[index].currentFileName());
|
|
|
|
setContentsPos(history[index].contentsX(), history[index].contentsY());
|
|
|
|
}
|
|
|
|
|
|
|
|
updateColumnsWidth();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::insertItem(KFileItem* fileItem)
|
|
|
|
{
|
|
|
|
KFileView::insertItem(fileItem);
|
|
|
|
|
|
|
|
DolphinListViewItem* item = new DolphinListViewItem(static_cast<TQListView*>(this), fileItem);
|
|
|
|
|
|
|
|
TQDir::SortSpec spec = KFileView::sorting();
|
|
|
|
if (spec & TQDir::Time) {
|
|
|
|
item->setKey(sortingKey(fileItem->time(TDEIO::UDS_MODIFICATION_TIME),
|
|
|
|
fileItem->isDir(),
|
|
|
|
spec));
|
|
|
|
}
|
|
|
|
else if (spec & TQDir::Size) {
|
|
|
|
item->setKey(sortingKey(fileItem->size(), fileItem->isDir(), spec));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
item->setKey(sortingKey(fileItem->text(), fileItem->isDir(), spec));
|
|
|
|
}
|
|
|
|
|
|
|
|
fileItem->setExtraData(this, item);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DolphinDetailsView::isOnFilename(const TQListViewItem* item, const TQPoint& pos) const
|
|
|
|
{
|
|
|
|
const TQPoint absPos(mapToGlobal(TQPoint(0, 0)));
|
|
|
|
return (pos.x() - absPos.x()) <= filenameWidth(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::refreshSettings()
|
|
|
|
{
|
|
|
|
const DolphinDetailsViewSettings* settings = DolphinSettings::instance().detailsView();
|
|
|
|
assert(settings != 0);
|
|
|
|
|
|
|
|
for (int i = DolphinDetailsView::GroupColumn; i >= DolphinDetailsView::NameColumn; --i) {
|
|
|
|
if (!settings->isColumnEnabled(i)) {
|
|
|
|
removeColumn(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQFont adjustedFont(font());
|
|
|
|
adjustedFont.setFamily(settings->fontFamily());
|
|
|
|
adjustedFont.setPointSize(settings->fontSize());
|
|
|
|
setFont(adjustedFont);
|
|
|
|
|
|
|
|
updateView(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::zoomIn()
|
|
|
|
{
|
|
|
|
if (isZoomInPossible()) {
|
|
|
|
DolphinDetailsViewSettings* settings = DolphinSettings::instance().detailsView();
|
|
|
|
switch (settings->iconSize()) {
|
|
|
|
case TDEIcon::SizeSmall: settings->setIconSize(TDEIcon::SizeMedium); break;
|
|
|
|
case TDEIcon::SizeMedium: settings->setIconSize(TDEIcon::SizeLarge); break;
|
|
|
|
default: assert(false); break;
|
|
|
|
}
|
|
|
|
ItemEffectsManager::zoomIn();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::zoomOut()
|
|
|
|
{
|
|
|
|
if (isZoomOutPossible()) {
|
|
|
|
DolphinDetailsViewSettings* settings = DolphinSettings::instance().detailsView();
|
|
|
|
switch (settings->iconSize()) {
|
|
|
|
case TDEIcon::SizeLarge: settings->setIconSize(TDEIcon::SizeMedium); break;
|
|
|
|
case TDEIcon::SizeMedium: settings->setIconSize(TDEIcon::SizeSmall); break;
|
|
|
|
default: assert(false); break;
|
|
|
|
}
|
|
|
|
ItemEffectsManager::zoomOut();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DolphinDetailsView::isZoomInPossible() const
|
|
|
|
{
|
|
|
|
DolphinDetailsViewSettings* settings = DolphinSettings::instance().detailsView();
|
|
|
|
return settings->iconSize() < TDEIcon::SizeLarge;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DolphinDetailsView::isZoomOutPossible() const
|
|
|
|
{
|
|
|
|
DolphinDetailsViewSettings* settings = DolphinSettings::instance().detailsView();
|
|
|
|
return settings->iconSize() > TDEIcon::SizeSmall;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::resizeContents(int width, int height)
|
|
|
|
{
|
|
|
|
KFileDetailView::resizeContents(width, height);
|
|
|
|
|
|
|
|
// When loading several 1000 items a punch of resize events
|
|
|
|
// drops in. As updating the column width is a quite expensive
|
|
|
|
// operation, this operation will be postponed until there is
|
|
|
|
// no resize event for at least 50 milliseconds.
|
|
|
|
m_resizeTimer->stop();
|
|
|
|
m_resizeTimer->start(50, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::slotOnItem(TQListViewItem* item)
|
|
|
|
{
|
|
|
|
if (isOnFilename(item, TQCursor::pos())) {
|
|
|
|
activateItem(item);
|
|
|
|
KFileItem* fileItem = static_cast<KFileListViewItem*>(item)->fileInfo();
|
|
|
|
m_dolphinView->requestItemInfo(fileItem->url());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
resetActivatedItem();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::slotOnViewport()
|
|
|
|
{
|
|
|
|
resetActivatedItem();
|
|
|
|
m_dolphinView->requestItemInfo(KURL());
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::setContextPixmap(void* context,
|
|
|
|
const TQPixmap& pixmap)
|
|
|
|
{
|
|
|
|
reinterpret_cast<KFileListViewItem*>(context)->setPixmap(0, pixmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQPixmap* DolphinDetailsView::contextPixmap(void* context)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<KFileListViewItem*>(context)->pixmap(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void* DolphinDetailsView::firstContext()
|
|
|
|
{
|
|
|
|
return reinterpret_cast<void*>(firstChild());
|
|
|
|
}
|
|
|
|
|
|
|
|
void* DolphinDetailsView::nextContext(void* context)
|
|
|
|
{
|
|
|
|
KFileListViewItem* listViewItem = reinterpret_cast<KFileListViewItem*>(context);
|
|
|
|
return reinterpret_cast<void*>(listViewItem->nextSibling());
|
|
|
|
}
|
|
|
|
|
|
|
|
KFileItem* DolphinDetailsView::contextFileInfo(void* context)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<KFileListViewItem*>(context)->fileInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DolphinDetailsView::contentsDragMoveEvent(TQDragMoveEvent* event)
|
|
|
|
{
|
|
|
|
KFileDetailView::contentsDragMoveEvent(event);
|
|
|
|
|
|
|
|
// If a dragging is done above a directory, show the icon as 'active' for
|
|
|
|
// a visual feedback
|
|
|
|
KFileListViewItem* item = static_cast<KFileListViewItem*>(itemAt(event->pos()));
|
|
|
|
|
|
|
|
bool showActive = false;
|
|
|
|
if (item != 0) {
|
|
|
|
const KFileItem* fileInfo = item->fileInfo();
|
|
|
|
showActive = (fileInfo != 0) && fileInfo->isDir();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (showActive) {
|
|
|
|
slotOnItem(item);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
slotOnViewport();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::resizeEvent(TQResizeEvent* event)
|
|
|
|
{
|
|
|
|
KFileDetailView::resizeEvent(event);
|
|
|
|
|
|
|
|
// When loading several 1000 items a punch of resize events
|
|
|
|
// drops in. As updating the column width is a quite expensive
|
|
|
|
// operation, this operation will be postponed until there is
|
|
|
|
// no resize event for at least 50 milliseconds.
|
|
|
|
m_resizeTimer->stop();
|
|
|
|
m_resizeTimer->start(50, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DolphinDetailsView::acceptDrag(TQDropEvent* event) const
|
|
|
|
{
|
|
|
|
bool accept = KURLDrag::canDecode(event) &&
|
|
|
|
(event->action() == TQDropEvent::Copy ||
|
|
|
|
event->action() == TQDropEvent::Move ||
|
|
|
|
event->action() == TQDropEvent::Link);
|
|
|
|
if (accept) {
|
|
|
|
if (static_cast<const TQWidget*>(event->source()) == this) {
|
|
|
|
KFileListViewItem* item = static_cast<KFileListViewItem*>(itemAt(event->pos()));
|
|
|
|
accept = (item != 0);
|
|
|
|
if (accept) {
|
|
|
|
KFileItem* fileItem = item->fileInfo();
|
|
|
|
accept = fileItem->isDir();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return accept;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::contentsDropEvent(TQDropEvent* event)
|
|
|
|
{
|
|
|
|
// KFileDetailView::contentsDropEvent does not care whether the mouse
|
|
|
|
// cursor is above a filename or not, the destination URL is always
|
|
|
|
// the URL of the item. This is fixed here in a way that the destination
|
|
|
|
// URL is only the URL of the item if the cursor is above the filename.
|
|
|
|
const TQPoint pos(TQCursor::pos());
|
|
|
|
const TQPoint viewportPos(viewport()->mapToGlobal(TQPoint(0, 0)));
|
|
|
|
TQListViewItem* item = itemAt(TQPoint(pos.x() - viewportPos.x(), pos.y() - viewportPos.y()));
|
|
|
|
if ((item == 0) || ((item != 0) && isOnFilename(item, pos))) {
|
|
|
|
// dropping is done on the viewport or directly above a filename
|
|
|
|
KFileDetailView::contentsDropEvent(event);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dropping is done above an item, but the mouse cursor is not above the file name.
|
|
|
|
// In this case the signals of the base implementation will be blocked and send
|
|
|
|
// in a corrected manner afterwards.
|
|
|
|
assert(item != 0);
|
|
|
|
const bool block = signalsBlocked();
|
|
|
|
blockSignals(true);
|
|
|
|
KFileDetailView::contentsDropEvent(event);
|
|
|
|
blockSignals(block);
|
|
|
|
|
|
|
|
if (!acceptDrag(event)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
emit dropped(event, 0);
|
|
|
|
KURL::List urls;
|
|
|
|
if (KURLDrag::decode(event, urls) && !urls.isEmpty()) {
|
|
|
|
emit dropped(event, urls, KURL());
|
|
|
|
sig->dropURLs(0, event, urls);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::contentsMousePressEvent(TQMouseEvent* event)
|
|
|
|
{
|
|
|
|
if (m_rubber != 0) {
|
|
|
|
drawRubber();
|
|
|
|
delete m_rubber;
|
|
|
|
m_rubber = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Swallow the base implementation of the mouse press event
|
|
|
|
// if the mouse cursor is not above the filename. This prevents
|
|
|
|
// that the item gets selected and simulates an equal usability
|
|
|
|
// like in the icon view.
|
|
|
|
const TQPoint pos(TQCursor::pos());
|
|
|
|
const TQPoint viewportPos(viewport()->mapToGlobal(TQPoint(0, 0)));
|
|
|
|
TQListViewItem* item = itemAt(TQPoint(pos.x() - viewportPos.x(), pos.y() - viewportPos.y()));
|
|
|
|
if ((item != 0) && isOnFilename(item, pos)) {
|
|
|
|
KFileDetailView::contentsMousePressEvent(event);
|
|
|
|
}
|
|
|
|
else if (event->button() == Qt::LeftButton) {
|
|
|
|
const ButtonState keyboardState = TDEApplication::keyboardMouseState();
|
|
|
|
const bool isSelectionActive = (keyboardState & ShiftButton) ||
|
|
|
|
(keyboardState & ControlButton);
|
|
|
|
if (!isSelectionActive) {
|
|
|
|
clearSelection();
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(m_rubber == 0);
|
|
|
|
m_rubber = new TQRect(event->x(), event->y(), 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
resetActivatedItem();
|
|
|
|
emit signalRequestActivation();
|
|
|
|
|
|
|
|
m_dolphinView->statusBar()->clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::contentsMouseMoveEvent(TQMouseEvent* event)
|
|
|
|
{
|
|
|
|
if (m_rubber != 0) {
|
|
|
|
slotAutoScroll();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
KFileDetailView::contentsMouseMoveEvent(event);
|
|
|
|
|
|
|
|
const TQPoint& pos = event->globalPos();
|
|
|
|
const TQPoint viewportPos = viewport()->mapToGlobal(TQPoint(0, 0));
|
|
|
|
TQListViewItem* item = itemAt(TQPoint(pos.x() - viewportPos.x(), pos.y() - viewportPos.y()));
|
|
|
|
if ((item != 0) && isOnFilename(item, pos)) {
|
|
|
|
activateItem(item);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
resetActivatedItem();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::contentsMouseReleaseEvent(TQMouseEvent* event)
|
|
|
|
{
|
|
|
|
if (m_rubber != 0) {
|
|
|
|
drawRubber();
|
|
|
|
delete m_rubber;
|
|
|
|
m_rubber = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_scrollTimer != 0) {
|
|
|
|
disconnect(m_scrollTimer, TQT_SIGNAL(timeout()),
|
|
|
|
this, TQT_SLOT(slotAutoScroll()));
|
|
|
|
m_scrollTimer->stop();
|
|
|
|
delete m_scrollTimer;
|
|
|
|
m_scrollTimer = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
KFileDetailView::contentsMouseReleaseEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::paintEmptyArea(TQPainter* painter, const TQRect& rect)
|
|
|
|
{
|
|
|
|
if (m_dolphinView->isActive()) {
|
|
|
|
KFileDetailView::paintEmptyArea(painter, rect);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const TQBrush brush(colorGroup().background());
|
|
|
|
painter->fillRect(rect, brush);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::drawRubber()
|
|
|
|
{
|
|
|
|
// Parts of the following code have been taken
|
|
|
|
// from the class KonqBaseListViewWidget located in
|
|
|
|
// konqueror/listview/konq_listviewwidget.h of Konqueror.
|
|
|
|
// (Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
|
|
|
|
// 2001, 2002, 2004 Michael Brade <brade@kde.org>)
|
|
|
|
if (m_rubber == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQPainter p;
|
|
|
|
p.begin(viewport());
|
|
|
|
p.setRasterOp(NotROP);
|
|
|
|
p.setPen(TQPen(color0, 1));
|
|
|
|
p.setBrush(NoBrush);
|
|
|
|
|
|
|
|
TQPoint point(m_rubber->x(), m_rubber->y());
|
|
|
|
point = contentsToViewport(point);
|
|
|
|
style().tqdrawPrimitive(TQStyle::PE_FocusRect, &p,
|
|
|
|
TQRect(point.x(), point.y(), m_rubber->width(), m_rubber->height()),
|
|
|
|
colorGroup(), TQStyle::Style_Default, colorGroup().base());
|
|
|
|
p.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::viewportPaintEvent(TQPaintEvent* paintEvent)
|
|
|
|
{
|
|
|
|
drawRubber();
|
|
|
|
KFileDetailView::viewportPaintEvent(paintEvent);
|
|
|
|
drawRubber();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::leaveEvent(TQEvent* event)
|
|
|
|
{
|
|
|
|
KFileDetailView::leaveEvent(event);
|
|
|
|
slotOnViewport();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::slotActivationUpdate()
|
|
|
|
{
|
|
|
|
update();
|
|
|
|
|
|
|
|
// TODO: there must be a simpler way to say
|
|
|
|
// "update all children"
|
|
|
|
const TQObjectList list = childrenListObject();
|
|
|
|
if (list.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQObjectListIterator it(list);
|
|
|
|
TQObject* object = 0;
|
|
|
|
while ((object = it.current()) != 0) {
|
|
|
|
if (object->inherits(TQWIDGET_OBJECT_NAME_STRING)) {
|
|
|
|
TQWidget* widget = TQT_TQWIDGET(object);
|
|
|
|
widget->update();
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::slotContextMenuRequested(TQListViewItem* item,
|
|
|
|
const TQPoint& pos,
|
|
|
|
int /* col */)
|
|
|
|
{
|
|
|
|
KFileItem* fileInfo = 0;
|
|
|
|
if ((item != 0) && isOnFilename(item, pos)) {
|
|
|
|
fileInfo = static_cast<KFileListViewItem*>(item)->fileInfo();
|
|
|
|
}
|
|
|
|
m_dolphinView->openContextMenu(fileInfo, pos);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::slotUpdateDisabledItems()
|
|
|
|
{
|
|
|
|
updateDisabledItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::slotAutoScroll()
|
|
|
|
{
|
|
|
|
// Parts of the following code have been taken
|
|
|
|
// from the class KonqBaseListViewWidget located in
|
|
|
|
// konqueror/listview/konq_listviewwidget.h of Konqueror.
|
|
|
|
// (Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
|
|
|
|
// 2001, 2002, 2004 Michael Brade <brade@kde.org>)
|
|
|
|
|
|
|
|
const TQPoint pos(viewport()->mapFromGlobal(TQCursor::pos()));
|
|
|
|
const TQPoint vc(viewportToContents(pos));
|
|
|
|
|
|
|
|
if (vc == m_rubber->bottomRight()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drawRubber();
|
|
|
|
|
|
|
|
m_rubber->setBottomRight(vc);
|
|
|
|
|
|
|
|
TQListViewItem* item = itemAt(TQPoint(0,0));
|
|
|
|
|
|
|
|
const bool block = signalsBlocked();
|
|
|
|
blockSignals(true);
|
|
|
|
|
|
|
|
const TQRect rubber(m_rubber->normalize());
|
|
|
|
const int bottom = contentsY() + visibleHeight() - 1;
|
|
|
|
|
|
|
|
// select all items which intersect with the rubber, deselect all others
|
|
|
|
bool bottomReached = false;
|
|
|
|
while ((item != 0) && !bottomReached) {
|
|
|
|
TQRect rect(itemRect(item));
|
|
|
|
rect.setWidth(filenameWidth(item));
|
|
|
|
rect = TQRect(viewportToContents(rect.topLeft()),
|
|
|
|
viewportToContents(rect.bottomRight()));
|
|
|
|
if (rect.isValid() && (rect.top() <= bottom)) {
|
|
|
|
const KFileItem* fileItem = static_cast<KFileListViewItem*>(item)->fileInfo();
|
|
|
|
setSelected(fileItem, rect.intersects(rubber));
|
|
|
|
item = item->itemBelow();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bottomReached = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
blockSignals(block);
|
|
|
|
emit selectionChanged();
|
|
|
|
|
|
|
|
drawRubber();
|
|
|
|
|
|
|
|
// scroll the viewport if the top or bottom margin is reached
|
|
|
|
const int scrollMargin = 40;
|
|
|
|
ensureVisible(vc.x(), vc.y(), scrollMargin, scrollMargin);
|
|
|
|
const bool scroll = !TQRect(scrollMargin,
|
|
|
|
scrollMargin,
|
|
|
|
viewport()->width() - 2 * scrollMargin,
|
|
|
|
viewport()->height() - 2 * scrollMargin).contains(pos);
|
|
|
|
if (scroll) {
|
|
|
|
if (m_scrollTimer == 0) {
|
|
|
|
m_scrollTimer = new TQTimer( this );
|
|
|
|
connect(m_scrollTimer, TQT_SIGNAL(timeout()),
|
|
|
|
this, TQT_SLOT(slotAutoScroll()));
|
|
|
|
m_scrollTimer->start(100, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (m_scrollTimer != 0) {
|
|
|
|
disconnect(m_scrollTimer, TQT_SIGNAL(timeout()),
|
|
|
|
this, TQT_SLOT(slotAutoScroll()));
|
|
|
|
m_scrollTimer->stop();
|
|
|
|
delete m_scrollTimer;
|
|
|
|
m_scrollTimer = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::updateColumnsWidth()
|
|
|
|
{
|
|
|
|
const int columnCount = columns();
|
|
|
|
int requiredWidth = 0;
|
|
|
|
for (int i = 1; i < columnCount; ++i) {
|
|
|
|
// When a directory contains no items, a minimum width for
|
|
|
|
// the column must be available, so that the header is readable.
|
|
|
|
// TODO: use header data instead of the hardcoded 64 value...
|
|
|
|
int columnWidth = 64;
|
|
|
|
TQFontMetrics fontMetrics(font());
|
|
|
|
for (TQListViewItem* item = firstChild(); item != 0; item = item->nextSibling()) {
|
|
|
|
const int width = item->width(fontMetrics, this, i);
|
|
|
|
if (width > columnWidth) {
|
|
|
|
columnWidth = width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
columnWidth += 16; // add custom margin
|
|
|
|
setColumnWidth(i, columnWidth);
|
|
|
|
requiredWidth += columnWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
// resize the first column in a way that the
|
|
|
|
// whole available width is used
|
|
|
|
int firstColumnWidth = visibleWidth() - requiredWidth;
|
|
|
|
if (firstColumnWidth < 128) {
|
|
|
|
firstColumnWidth = 128;
|
|
|
|
}
|
|
|
|
setColumnWidth(0, firstColumnWidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::slotItemRenamed(TQListViewItem* item,
|
|
|
|
const TQString& name,
|
|
|
|
int /* column */)
|
|
|
|
{
|
|
|
|
KFileItem* fileInfo = static_cast<KFileListViewItem*>(item)->fileInfo();
|
|
|
|
m_dolphinView->rename(KURL(fileInfo->url()), name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::slotHeaderClicked(int /* section */)
|
|
|
|
{
|
|
|
|
// The sorting has already been changed in TQListView if this slot is
|
|
|
|
// invoked, but Dolphin was not informed about this (no signal is available
|
|
|
|
// which indicates a change of the sorting). This is bypassed by changing
|
|
|
|
// the sorting and sort order to a temporary other value and readjust it again.
|
|
|
|
const int column = sortColumn();
|
|
|
|
if (column <= DateColumn) {
|
|
|
|
DolphinView::Sorting sorting = DolphinView::SortByName;
|
|
|
|
switch (column) {
|
|
|
|
case SizeColumn: sorting = DolphinView::SortBySize; break;
|
|
|
|
case DateColumn: sorting = DolphinView::SortByDate; break;
|
|
|
|
case NameColumn:
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQt::SortOrder currSortOrder = sortOrder();
|
|
|
|
|
|
|
|
// temporary adjust the sorting and sort order to different values...
|
|
|
|
const DolphinView::Sorting tempSorting = (sorting == DolphinView::SortByName) ?
|
|
|
|
DolphinView::SortBySize :
|
|
|
|
DolphinView::SortByName;
|
|
|
|
m_dolphinView->setSorting(tempSorting);
|
|
|
|
const TQt::SortOrder tempSortOrder = (currSortOrder == TQt::Ascending) ?
|
|
|
|
TQt::Descending : TQt::Ascending;
|
|
|
|
m_dolphinView->setSortOrder(tempSortOrder);
|
|
|
|
|
|
|
|
// ... so that setting them again results in storing the new setting.
|
|
|
|
m_dolphinView->setSorting(sorting);
|
|
|
|
m_dolphinView->setSortOrder(currSortOrder);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DolphinDetailsView::DolphinListViewItem::DolphinListViewItem(TQListView* parent,
|
|
|
|
KFileItem* fileItem) :
|
|
|
|
KFileListViewItem(parent, fileItem)
|
|
|
|
{
|
|
|
|
const int iconSize = DolphinSettings::instance().detailsView()->iconSize();
|
|
|
|
KFileItem* info = fileInfo();
|
|
|
|
setPixmap(DolphinDetailsView::NameColumn, info->pixmap(iconSize));
|
|
|
|
|
|
|
|
// The base class KFileListViewItem represents the column 'Size' only as byte values.
|
|
|
|
// Adjust those values in a way that a mapping to GBytes, MBytes, KBytes and Bytes
|
|
|
|
// is done. As the file size for directories is useless (only the size of the directory i-node
|
|
|
|
// is given), it is removed completely.
|
|
|
|
if (fileItem->isDir()) {
|
|
|
|
setText(SizeColumn, " - ");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
TQString sizeText(TDEIO::convertSize(fileItem->size()));
|
|
|
|
sizeText.append(" ");
|
|
|
|
setText(SizeColumn, sizeText);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dolphin allows to remove specific columns, but the base class KFileListViewItem
|
|
|
|
// is not aware about this (or at least the class KFileDetailView does not react on
|
|
|
|
// TQListView::remove()). Therefore the columns are rearranged here.
|
|
|
|
const DolphinDetailsViewSettings* settings = DolphinSettings::instance().detailsView();
|
|
|
|
assert(settings != 0);
|
|
|
|
|
|
|
|
int column_idx = DateColumn; // the columns for 'name' and 'size' cannot get removed
|
|
|
|
for (int i = DolphinDetailsView::DateColumn; i <= DolphinDetailsView::GroupColumn; ++i) {
|
|
|
|
if (column_idx < i) {
|
|
|
|
setText(column_idx, text(i));
|
|
|
|
}
|
|
|
|
if (settings->isColumnEnabled(i)) {
|
|
|
|
++column_idx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DolphinDetailsView::DolphinListViewItem::~DolphinListViewItem()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::DolphinListViewItem::paintCell(TQPainter* painter,
|
|
|
|
const TQColorGroup& colorGroup,
|
|
|
|
int column,
|
|
|
|
int cellWidth,
|
|
|
|
int alignment)
|
|
|
|
{
|
|
|
|
const TQListView* view = listView();
|
|
|
|
const bool isActive = TQT_BASE_OBJECT(view->parent()) == TQT_BASE_OBJECT(Dolphin::mainWin().activeView());
|
|
|
|
if (isSelected()) {
|
|
|
|
// Per default the selection is drawn above the whole width of the item. As a consistent
|
|
|
|
// behavior with the icon view is wanted, only the the column containing the file name
|
|
|
|
// should be shown as selected.
|
|
|
|
TQColorGroup defaultColorGroup(colorGroup);
|
|
|
|
const TQColor highlightColor(isActive ? backgroundColor(column) : view->colorGroup().background());
|
|
|
|
defaultColorGroup.setColor(TQColorGroup::Highlight , highlightColor);
|
|
|
|
defaultColorGroup.setColor(TQColorGroup::HighlightedText, colorGroup.color(TQColorGroup::Text));
|
|
|
|
KFileListViewItem::paintCell(painter, defaultColorGroup, column, cellWidth, alignment);
|
|
|
|
|
|
|
|
if (column == 0) {
|
|
|
|
// draw the selection only on the first column
|
|
|
|
TQListView* parent = listView();
|
|
|
|
const int itemWidth = width(parent->fontMetrics(), parent, 0);
|
|
|
|
if (isActive) {
|
|
|
|
KFileListViewItem::paintCell(painter, colorGroup, column, itemWidth, alignment);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
TQListViewItem::paintCell(painter, colorGroup, column, itemWidth, alignment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (isActive) {
|
|
|
|
KFileListViewItem::paintCell(painter, colorGroup, column, cellWidth, alignment);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
TQListViewItem::paintCell(painter, colorGroup, column, cellWidth, alignment);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (column < listView()->columns() - 1) {
|
|
|
|
// draw a separator between columns
|
|
|
|
painter->setPen(TDEGlobalSettings::buttonBackground());
|
|
|
|
painter->drawLine(cellWidth - 1, 0, cellWidth - 1, height() - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DolphinDetailsView::DolphinListViewItem::paintFocus(TQPainter* painter,
|
|
|
|
const TQColorGroup& colorGroup,
|
|
|
|
const TQRect& rect)
|
|
|
|
{
|
|
|
|
// draw the focus consistently with the selection (see implementation notes
|
|
|
|
// in DolphinListViewItem::paintCell)
|
|
|
|
TQListView* parent = listView();
|
|
|
|
int visibleWidth = width(parent->fontMetrics(), parent, 0);
|
|
|
|
const int colWidth = parent->columnWidth(0);
|
|
|
|
if (visibleWidth > colWidth) {
|
|
|
|
visibleWidth = colWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQRect focusRect(rect);
|
|
|
|
focusRect.setWidth(visibleWidth);
|
|
|
|
|
|
|
|
KFileListViewItem::paintFocus(painter, colorGroup, focusRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
int DolphinDetailsView::filenameWidth(const TQListViewItem* item) const
|
|
|
|
{
|
|
|
|
assert(item != 0);
|
|
|
|
|
|
|
|
int visibleWidth = item->width(fontMetrics(), this, 0);
|
|
|
|
const int colWidth = columnWidth(0);
|
|
|
|
if (visibleWidth > colWidth) {
|
|
|
|
visibleWidth = colWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
return visibleWidth;
|
|
|
|
}
|
|
|
|
#include "dolphindetailsview.moc"
|