X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/a24c1fce8234dc0ad0116aecc06c7151bcdd1cee..5d9a7d1ad376912ac75a6853485fd8e299754d9a:/src/dolphindetailsview.cpp diff --git a/src/dolphindetailsview.cpp b/src/dolphindetailsview.cpp index 590e3c7d8..55851dc95 100644 --- a/src/dolphindetailsview.cpp +++ b/src/dolphindetailsview.cpp @@ -24,13 +24,16 @@ #include "dolphincontroller.h" #include "dolphinsettings.h" #include "dolphinsortfilterproxymodel.h" +#include "draganddrophelper.h" #include "viewproperties.h" #include "dolphin_detailsmodesettings.h" +#include #include #include +#include #include #include #include @@ -41,6 +44,7 @@ DolphinDetailsView::DolphinDetailsView(QWidget* parent, DolphinController* controller) : QTreeView(parent), m_controller(controller), + m_clearAdditionalInfo(false), m_dragging(false), m_showElasticBand(false), m_elasticBandOrigin(), @@ -82,10 +86,10 @@ DolphinDetailsView::DolphinDetailsView(QWidget* parent, DolphinController* contr // RETURN-key in keyPressEvent(). if (KGlobalSettings::singleClick()) { connect(this, SIGNAL(clicked(const QModelIndex&)), - this, SLOT(slotItemActivated(const QModelIndex&))); + this, SLOT(triggerItem(const QModelIndex&))); } else { connect(this, SIGNAL(doubleClicked(const QModelIndex&)), - this, SLOT(slotItemActivated(const QModelIndex&))); + this, SLOT(triggerItem(const QModelIndex&))); } connect(this, SIGNAL(entered(const QModelIndex&)), this, SLOT(slotEntered(const QModelIndex&))); @@ -95,6 +99,8 @@ DolphinDetailsView::DolphinDetailsView(QWidget* parent, DolphinController* contr this, SLOT(zoomIn())); connect(controller, SIGNAL(zoomOut()), this, SLOT(zoomOut())); + connect(controller->dolphinView(), SIGNAL(additionalInfoChanged(const KFileItemDelegate::InformationList&)), + this, SLOT(updateColumnVisibility())); // apply the details mode settings to the widget const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings(); @@ -108,10 +114,18 @@ DolphinDetailsView::DolphinDetailsView(QWidget* parent, DolphinController* contr m_viewOptions.font = font; m_viewOptions.showDecorationSelected = true; - setVerticalScrollMode(QListView::ScrollPerPixel); - setHorizontalScrollMode(QListView::ScrollPerPixel); +// TODO: Remove this check when 4.3.2 is released and KDE requires it... this +// check avoids a division by zero happening on versions before 4.3.1. +// Right now KDE in theory can be shipped with Qt 4.3.0 and above. +// ereslibre +#if (QT_VERSION >= QT_VERSION_CHECK(4, 3, 2) || defined(QT_KDE_QT_COPY)) + setVerticalScrollMode(QTreeView::ScrollPerPixel); + setHorizontalScrollMode(QTreeView::ScrollPerPixel); +#endif updateDecorationSize(); + + setFocus(); } DolphinDetailsView::~DolphinDetailsView() @@ -121,46 +135,27 @@ DolphinDetailsView::~DolphinDetailsView() bool DolphinDetailsView::event(QEvent* event) { if (event->type() == QEvent::Polish) { - // Assure that by respecting the available width that: - // - the 'Name' column is stretched as large as possible - // - the remaining columns are as small as possible QHeaderView* headerView = header(); - headerView->setStretchLastSection(false); - headerView->setResizeMode(QHeaderView::ResizeToContents); - headerView->setResizeMode(0, QHeaderView::Stretch); + headerView->setResizeMode(QHeaderView::Fixed); headerView->setMovable(false); - // hide columns if this is indicated by the settings - const DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings(); - Q_ASSERT(settings != 0); - if (!settings->showDate()) { - hideColumn(DolphinModel::ModifiedTime); - } - - if (!settings->showPermissions()) { - hideColumn(DolphinModel::Permissions); - } - - if (!settings->showOwner()) { - hideColumn(DolphinModel::Owner); - } - - if (!settings->showGroup()) { - hideColumn(DolphinModel::Group); - } - - if (!settings->showType()) { - hideColumn(DolphinModel::Type); - } + updateColumnVisibility(); hideColumn(DolphinModel::Rating); hideColumn(DolphinModel::Tags); } +// TODO: Remove this check when 4.3.2 is released and KDE requires it... this +// check avoids a division by zero happening on versions before 4.3.1. +// Right now KDE in theory can be shipped with Qt 4.3.0 and above. +// ereslibre +#if (QT_VERSION >= QT_VERSION_CHECK(4, 3, 2) || defined(QT_KDE_QT_COPY)) else if (event->type() == QEvent::UpdateRequest) { - // A wheel movement will scroll 4 items - if (model()->rowCount()) + // a wheel movement will scroll 4 items + if (model()->rowCount() > 0) { verticalScrollBar()->setSingleStep((sizeHintForRow(0) / 3) * 4); + } } +#endif return QTreeView::event(event); } @@ -178,7 +173,7 @@ void DolphinDetailsView::contextMenuEvent(QContextMenuEvent* event) void DolphinDetailsView::mousePressEvent(QMouseEvent* event) { - m_controller->triggerActivation(); + m_controller->requestActivation(); QTreeView::mousePressEvent(event); @@ -218,6 +213,11 @@ void DolphinDetailsView::mouseReleaseEvent(QMouseEvent* event) } } +void DolphinDetailsView::startDrag(Qt::DropActions supportedActions) +{ + DragAndDropHelper::startDrag(this, supportedActions); +} + void DolphinDetailsView::dragEnterEvent(QDragEnterEvent* event) { if (event->mimeData()->hasUrls()) { @@ -251,7 +251,12 @@ void DolphinDetailsView::dragMoveEvent(QDragMoveEvent* event) m_dragging = false; } else { m_dragging = true; - m_dropRect = visualRect(index); + const KFileItem item = itemForIndex(index); + if (!item.isNull() && item.isDir()) { + m_dropRect = visualRect(index); + } else { + m_dropRect.setSize(QSize()); // set as invalid + } setDirtyRegion(m_dropRect); } } @@ -261,10 +266,14 @@ void DolphinDetailsView::dropEvent(QDropEvent* event) const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); if (!urls.isEmpty()) { event->acceptProposedAction(); + const QModelIndex index = indexAt(event->pos()); + KFileItem item; + if (index.isValid() && (index.column() == DolphinModel::Name)) { + item = itemForIndex(index); + } m_controller->indicateDroppedUrls(urls, m_controller->url(), - indexAt(event->pos()), - event->source()); + item); } QTreeView::dropEvent(event); m_dragging = false; @@ -292,7 +301,7 @@ void DolphinDetailsView::paintEvent(QPaintEvent* event) // TODO: remove this code when the issue #160611 is solved in Qt 4.4 if (m_dragging) { const QBrush& brush = m_viewOptions.palette.brush(QPalette::Normal, QPalette::Highlight); - DolphinController::drawHoverIndication(viewport(), m_dropRect, brush); + DragAndDropHelper::drawHoverIndication(viewport(), m_dropRect, brush); } } @@ -302,45 +311,32 @@ void DolphinDetailsView::keyPressEvent(QKeyEvent* event) const QItemSelectionModel* selModel = selectionModel(); const QModelIndex currentIndex = selModel->currentIndex(); - const bool triggerItem = currentIndex.isValid() - && (event->key() == Qt::Key_Return) - && (selModel->selectedIndexes().count() <= 1); - if (triggerItem) { - m_controller->triggerItem(currentIndex); + const bool trigger = currentIndex.isValid() + && (event->key() == Qt::Key_Return) + && (selModel->selectedIndexes().count() <= 1); + if (trigger) { + triggerItem(currentIndex); } } void DolphinDetailsView::resizeEvent(QResizeEvent* event) { QTreeView::resizeEvent(event); + resizeColumns(); +} - // assure that the width of the name-column does not get too small - const int minWidth = 120; - QHeaderView* headerView = header(); - bool useFixedWidth = (headerView->sectionSize(KDirModel::Name) <= minWidth) - && (headerView->resizeMode(0) != QHeaderView::Fixed); - if (useFixedWidth) { - // the current width of the name-column is too small, hence - // use a fixed size - headerView->setResizeMode(QHeaderView::Fixed); - headerView->setResizeMode(0, QHeaderView::Fixed); - headerView->resizeSection(KDirModel::Name, minWidth); - } else if (headerView->resizeMode(0) != QHeaderView::Stretch) { - // check whether there is enough available viewport width - // to automatically resize the columns - const int availableWidth = viewport()->width(); - - int headerWidth = 0; - const int count = headerView->count(); - for (int i = 0; i < count; ++i) { - headerWidth += headerView->sectionSize(i); - } - - if (headerWidth < availableWidth) { - headerView->setResizeMode(QHeaderView::ResizeToContents); - headerView->setResizeMode(0, QHeaderView::Stretch); - } +void DolphinDetailsView::closeEvent(QCloseEvent* event) +{ + if (m_clearAdditionalInfo) { + disconnect(m_controller->dolphinView(), SIGNAL(additionalInfoChanged(const KFileItemDelegate::InformationList&)), + this, SLOT(updateColumnVisibility())); + + KFileItemDelegate::InformationList info; + info.append(KFileItemDelegate::NoInformation); + m_controller->indicateAdditionalInfoChange(info); + m_clearAdditionalInfo = false; } + QTreeView::closeEvent(event); } void DolphinDetailsView::setSortIndicatorSection(DolphinView::Sorting sorting) @@ -370,7 +366,7 @@ void DolphinDetailsView::slotEntered(const QModelIndex& index) const QPoint pos = viewport()->mapFromGlobal(QCursor::pos()); const int nameColumnWidth = header()->sectionSize(DolphinModel::Name); if (pos.x() < nameColumnWidth) { - m_controller->emitItemEntered(index); + m_controller->emitItemEntered(itemForIndex(index)); } else { m_controller->emitViewportEntered(); @@ -386,6 +382,13 @@ void DolphinDetailsView::updateElasticBand() setDirtyRegion(dirtyRegion); } +QRect DolphinDetailsView::elasticBandRect() const +{ + const QPoint pos(contentsPos()); + const QPoint topLeft(m_elasticBandOrigin.x() - pos.x(), m_elasticBandOrigin.y() - pos.y()); + return QRect(topLeft, m_elasticBandDestination).normalized(); +} + void DolphinDetailsView::zoomIn() { if (isZoomInPossible()) { @@ -412,13 +415,14 @@ void DolphinDetailsView::zoomOut() } } -void DolphinDetailsView::slotItemActivated(const QModelIndex& index) +void DolphinDetailsView::triggerItem(const QModelIndex& index) { + const KFileItem item = itemForIndex(index); if (index.isValid() && (index.column() == KDirModel::Name)) { - m_controller->triggerItem(index); + m_controller->triggerItem(item); } else { clearSelection(); - m_controller->emitItemEntered(index); + m_controller->emitItemEntered(item); } } @@ -428,7 +432,7 @@ void DolphinDetailsView::configureColumns(const QPoint& pos) popup.addTitle(i18nc("@title:menu", "Columns")); QHeaderView* headerView = header(); - for (int i = DolphinModel::ModifiedTime; i <= DolphinModel::Type; ++i) { + for (int i = DolphinModel::Size; i <= DolphinModel::Type; ++i) { const int logicalIndex = headerView->logicalIndex(i); const QString text = model()->headerData(i, Qt::Horizontal).toString(); QAction* action = popup.addAction(text); @@ -440,29 +444,53 @@ void DolphinDetailsView::configureColumns(const QPoint& pos) QAction* activatedAction = popup.exec(header()->mapToGlobal(pos)); if (activatedAction != 0) { const bool show = activatedAction->isChecked(); - DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings(); - Q_ASSERT(settings != 0); - - // remember the changed column visibility in the settings const int columnIndex = activatedAction->data().toInt(); - switch (columnIndex) { - case DolphinModel::ModifiedTime: settings->setShowDate(show); break; - case DolphinModel::Permissions: settings->setShowPermissions(show); break; - case DolphinModel::Owner: settings->setShowOwner(show); break; - case DolphinModel::Group: settings->setShowGroup(show); break; - case DolphinModel::Type: settings->setShowType(show); break; - default: break; - } - // apply the changed column visibility + KFileItemDelegate::InformationList list = m_controller->dolphinView()->additionalInfo(); + const KFileItemDelegate::Information info = infoForColumn(columnIndex); if (show) { - showColumn(columnIndex); + Q_ASSERT(!list.contains(info)); + list.append(info); } else { - hideColumn(columnIndex); + Q_ASSERT(list.contains(info)); + const int index = list.indexOf(info); + list.removeAt(index); } + + m_controller->indicateAdditionalInfoChange(list); + setColumnHidden(columnIndex, !show); } } +void DolphinDetailsView::updateColumnVisibility() +{ + KFileItemDelegate::InformationList list = m_controller->dolphinView()->additionalInfo(); + const bool useDefaultColumns = !isVisible() && + (list.isEmpty() || + list.contains(KFileItemDelegate::NoInformation)); + if (useDefaultColumns) { + // Using the details view without any additional information (-> additional column) + // makes no sense and leads to a usability problem as no viewport area is available + // anymore. Hence as fallback provide at least a size and date column. + list.clear(); + list.append(KFileItemDelegate::Size); + list.append(KFileItemDelegate::ModificationTime); + m_controller->indicateAdditionalInfoChange(list); + m_clearAdditionalInfo = true; + } + + for (int i = DolphinModel::Size; i <= DolphinModel::Type; ++i) { + const KFileItemDelegate::Information info = infoForColumn(i); + const bool hide = !list.contains(info); + if (isColumnHidden(i) != hide) { + setColumnHidden(i, hide); + m_clearAdditionalInfo = false; + } + } + + resizeColumns(); +} + bool DolphinDetailsView::isZoomInPossible() const { DetailsModeSettings* settings = DolphinSettings::instance().detailsModeSettings(); @@ -505,16 +533,65 @@ QPoint DolphinDetailsView::contentsPos() const return QPoint(0, y); } -QRect DolphinDetailsView::elasticBandRect() const +KFileItem DolphinDetailsView::itemForIndex(const QModelIndex& index) const { - const QPoint pos(contentsPos()); - const QPoint topLeft(m_elasticBandOrigin.x() - pos.x(), m_elasticBandOrigin.y() - pos.y()); - return QRect(topLeft, m_elasticBandDestination).normalized(); + QAbstractProxyModel* proxyModel = static_cast(model()); + KDirModel* dirModel = static_cast(proxyModel->sourceModel()); + const QModelIndex dirIndex = proxyModel->mapToSource(index); + return dirModel->itemForIndex(dirIndex); +} + +KFileItemDelegate::Information DolphinDetailsView::infoForColumn(int columnIndex) const +{ + KFileItemDelegate::Information info = KFileItemDelegate::NoInformation; + + switch (columnIndex) { + case DolphinModel::Size: info = KFileItemDelegate::Size; break; + case DolphinModel::ModifiedTime: info = KFileItemDelegate::ModificationTime; break; + case DolphinModel::Permissions: info = KFileItemDelegate::Permissions; break; + case DolphinModel::Owner: info = KFileItemDelegate::Owner; break; + case DolphinModel::Group: info = KFileItemDelegate::OwnerAndGroup; break; + case DolphinModel::Type: info = KFileItemDelegate::FriendlyMimeType; break; + default: break; + } + + return info; } -static bool isValidNameIndex(const QModelIndex& index) +void DolphinDetailsView::resizeColumns() { - return index.isValid() && (index.column() == KDirModel::Name); + // Using the resize mode QHeaderView::ResizeToContents is too slow (it takes + // around 3 seconds for each (!) resize operation when having > 10000 items). + // This gets a problem especially when opening large directories, where several + // resize operations are received for showing the currently available items during + // loading (the application hangs around 20 seconds when loading > 10000 items). + + QHeaderView* headerView = header(); + QFontMetrics fontMetrics(viewport()->font()); + + int columnWidth[KDirModel::ColumnCount]; + columnWidth[KDirModel::Size] = fontMetrics.width("00000 Items"); + columnWidth[KDirModel::ModifiedTime] = fontMetrics.width("0000-00-00 00:00"); + columnWidth[KDirModel::Permissions] = fontMetrics.width("xxxxxxxxxx"); + columnWidth[KDirModel::Owner] = fontMetrics.width("xxxxxxxxxx"); + columnWidth[KDirModel::Group] = fontMetrics.width("xxxxxxxxxx"); + columnWidth[KDirModel::Type] = fontMetrics.width("XXXX Xxxxxxx"); + + int requiredWidth = 0; + for (int i = KDirModel::Size; i <= KDirModel::Type; ++i) { + if (!isColumnHidden(i)) { + columnWidth[i] += 20; // provide a default gap + requiredWidth += columnWidth[i]; + headerView->resizeSection(i, columnWidth[i]); + } + } + + // resize the name column in a way that the whole available width is used + columnWidth[KDirModel::Name] = viewport()->width() - requiredWidth; + if (columnWidth[KDirModel::Name] < 120) { + columnWidth[KDirModel::Name] = 120; + } + headerView->resizeSection(KDirModel::Name, columnWidth[KDirModel::Name]); } #include "dolphindetailsview.moc"