diff --git a/ThumbnailView/Delegate.cpp b/ThumbnailView/Delegate.cpp index 18c33f35..c8689f1d 100644 --- a/ThumbnailView/Delegate.cpp +++ b/ThumbnailView/Delegate.cpp @@ -1,288 +1,287 @@ -/* Copyright (C) 2003-2010 Jesper K. Pedersen +/* Copyright (C) 2003-2019 The KPhotoAlbum Development Team 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Delegate.h" -#include "Utilities/Util.h" #include "Settings/SettingsData.h" #include "ThumbnailWidget.h" #include "CellGeometry.h" #include #include "ThumbnailModel.h" #include ThumbnailView::Delegate::Delegate(ThumbnailFactory* factory , QObject *parent) :QStyledItemDelegate(parent), ThumbnailComponent( factory ) { } void ThumbnailView::Delegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { paintCellBackground( painter, option.rect ); if ( widget()->isGridResizing()) return; if ( index.data( Qt::DecorationRole ).value().isNull() ) return; paintCellPixmap( painter, option, index ); paintCellText( painter, option, index ); } void ThumbnailView::Delegate::paintCellBackground( QPainter* painter, const QRect& rect ) const { painter->fillRect( rect, QColor(Settings::SettingsData::instance()->backgroundColor()) ); if (widget()->isGridResizing() || Settings::SettingsData::instance()->thumbnailDisplayGrid()) { - painter->setPen( Utilities::contrastColor( Settings::SettingsData::instance()->backgroundColor() ) ); + painter->setPen( contrastColor( Settings::SettingsData::instance()->backgroundColor() ) ); // left and right of frame painter->drawLine( rect.right(), rect.top(), rect.right(), rect.bottom() ); // bottom line painter->drawLine( rect.left(), rect.bottom(), rect.right(), rect.bottom() ); } } void ThumbnailView::Delegate::paintCellPixmap( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { const QPixmap pixmap = index.data( Qt::DecorationRole ).value(); const QRect pixmapRect = cellGeometryInfo()->iconGeometry( pixmap ).translated(option.rect.topLeft()); paintBoundingRect( painter, pixmapRect, index ); painter->drawPixmap( pixmapRect, pixmap ); paintVideoInfo(painter, pixmapRect, index ); paintDropIndicator( painter, option.rect, index ); paintStackedIndicator(painter, pixmapRect, index); // Paint transparent pixels over the widget for selection. const QItemSelectionModel *selectionModel = widget()->selectionModel(); if ( selectionModel->isSelected( index ) ) painter->fillRect( option.rect, QColor(58,98,134, 127) ); else if ( selectionModel->hasSelection() && selectionModel->currentIndex() == index ) painter->fillRect( option.rect, QColor(58,98,134, 127) ); } void ThumbnailView::Delegate::paintVideoInfo(QPainter *painter, const QRect& pixmapRect, const QModelIndex &index) const { DB::ImageInfoPtr imageInfo = model()->imageAt(index.row()).info(); if (!imageInfo || imageInfo->mediaType() != DB::Video ) return; const QString text = videoLengthText(imageInfo); const QRect metricsRect = painter->fontMetrics().boundingRect(text); const int margin = 3; const QRect textRect = QRect(pixmapRect.right()-metricsRect.width()-margin, pixmapRect.bottom()-metricsRect.height()-margin, metricsRect.width(), metricsRect.height()); const QRect backgroundRect = textRect.adjusted(-margin,-margin, margin, margin); if ( backgroundRect.width() > pixmapRect.width()/2 ) { // Don't show the time if the box would fill more than half the thumbnail return; } painter->save(); painter->fillRect(backgroundRect, QBrush( QColor(0,0,0,128))); painter->setPen(Qt::white); painter->drawText(textRect, text); painter->restore(); } void ThumbnailView::Delegate::paintCellText( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { // Optimization based on result from KCacheGrind if ( !Settings::SettingsData::instance()->displayLabels() && !Settings::SettingsData::instance()->displayCategories() ) return; DB::FileName fileName = model()->imageAt( index.row() ); if ( fileName.isNull() ) return; QString title = index.data( Qt::DisplayRole ).value(); QRect rect = cellGeometryInfo()->cellTextGeometry(); - painter->setPen( Utilities::contrastColor( Settings::SettingsData::instance()->backgroundColor() ) ); + painter->setPen( contrastColor( Settings::SettingsData::instance()->backgroundColor() ) ); //Qt::TextWordWrap just in case, if the text's width is wider than the cell's width painter->drawText( rect.translated( option.rect.topLeft() ), Qt::AlignCenter | Qt::TextWordWrap, title ); } QSize ThumbnailView::Delegate::sizeHint( const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/ ) const { return cellGeometryInfo()->cellSize(); } /** This will paint the pixels around the thumbnail, which gives it a 3D effect, and also which indicates current image and selection state. The colors are fetched from looking at the Gwenview. I tried to see if I could figure out from the code how it was drawn, but failed at doing so. */ void ThumbnailView::Delegate::paintBoundingRect( QPainter* painter, const QRect& pixmapRect, const QModelIndex& index ) const { QRect rect = pixmapRect; rect.adjust(-5,-5,4,4); for ( int i = 4; i >= 0; --i ) { QColor color; if ( widget()->selectionModel()->isSelected( index ) ) { static QColor selectionColors[] = { QColor(58,98,134), QColor(96,161,221), QColor(93,165,228), QColor(132,186,237), QColor(62,95,128)}; color = selectionColors[i]; } #if 0 // This code doesn't work very well with the QListView, for some odd reason, it often leaves a highlighted thumbnail behind // 9 Aug. 2010 11:33 -- Jesper K. Pedersen else if ( widget()->indexUnderCursor() == index ) { static QColor hoverColors[] = { QColor(46,99,152), QColor(121,136,151), QColor(121,136,151), QColor(126,145,163), QColor(109,126,142)}; color = hoverColors[i]; } #endif else { // Originally I just painted the outline using drawRect, but that turned out to be a huge bottleneck. // The code was therefore converted to fillRect, which was much faster. // This code was complicted from that, as I previously drew the // rects from insite out, but with fillRect that doesn't work, // and I thefore had to rewrite the code to draw the rects from // outside in. // I now had to calculate the destination color myself, rather // than rely on drawing with a transparent color on top of the // background. // 12 Aug. 2010 17:38 -- Jesper K. Pedersen const QColor foreground = Qt::black; const QColor backround = QColor(Settings::SettingsData::instance()->backgroundColor()); double alpha = (0.5 - 0.1*i); double inverseAlpha = 1 - alpha; color = QColor( foreground.red() * alpha + backround.red() * inverseAlpha, foreground.green() * alpha + backround.green() * inverseAlpha, foreground.blue() * alpha + backround.blue() * inverseAlpha ); } QPen pen( color ); painter->setPen(pen); painter->fillRect(rect, QBrush( color ) ); rect.adjust(1,1,-1,-1 ); } } static DB::StackID getStackId(const DB::FileName& fileName) { return fileName.info()->stackId(); } void ThumbnailView::Delegate::paintStackedIndicator( QPainter* painter, const QRect &pixmapRect, const QModelIndex& index ) const { DB::ImageInfoPtr imageInfo = model()->imageAt(index.row()).info(); if (!imageInfo || !imageInfo->isStacked()) return; const QRect cellRect = widget()->visualRect( index ); // Calculate the three points for the bottom most/right most lines int leftX = cellRect.left(); int rightX = cellRect.right() + 5; // 5 for the 3D effect if ( isFirst( index.row() ) ) leftX = pixmapRect.left() + pixmapRect.width()/2; if ( isLast( index.row() ) ) rightX = pixmapRect.right(); QPoint bottomLeftPoint( leftX, pixmapRect.bottom() ); QPoint bottomRightPoint( rightX, pixmapRect.bottom() ); QPoint topPoint = isLast( index.row() ) ? QPoint( rightX, pixmapRect.top() + pixmapRect.height()/2 ) : QPoint(); // Paint the lines. painter->save(); for ( int i=0; i < 8; ++i ) { painter->setPen( QPen(i % 2 == 0 ? Qt::black : Qt::white) ); painter->drawLine(bottomLeftPoint,bottomRightPoint); if ( topPoint != QPoint() ) { painter->drawLine( bottomRightPoint, topPoint ); topPoint -= QPoint(1,1); } bottomLeftPoint -= QPoint( isFirst( index.row()) ? 1 : 0, 1 ); bottomRightPoint -= QPoint( isLast( index.row()) ? 1 : 0, 1); } painter->restore(); } bool ThumbnailView::Delegate::isFirst( int row ) const { const DB::StackID curId = getStackId(model()->imageAt(row)); return !model()->isItemInExpandedStack(curId) || row == 0 || getStackId(model()->imageAt(row-1)) != curId; } bool ThumbnailView::Delegate::isLast( int row ) const { const DB::StackID curId = getStackId(model()->imageAt(row)); return !model()->isItemInExpandedStack(curId) || row == model()->imageCount() -1 || getStackId(model()->imageAt(row+1)) != curId; } QString ThumbnailView::Delegate::videoLengthText(const DB::ImageInfoPtr &imageInfo) const { const int length = imageInfo->videoLength(); if ( length < 0 ) return i18nc("No video length could be determined, so we just display 'video' instead of the video length.","video"); const int hours = length/60/60; const int minutes = (length/60)%60; const int secs = length % 60; QString res; if (hours > 0) res = QString::number(hours) + QLatin1String(":"); if (minutes < 10 && hours > 0) res += QLatin1String("0"); res += QString::number(minutes); res += QLatin1String(":"); if (secs < 10) res += QLatin1String("0"); res += QString::number(secs); return res; } void ThumbnailView::Delegate::paintDropIndicator( QPainter* painter, const QRect& rect, const QModelIndex& index ) const { const DB::FileName fileName = model()->imageAt( index.row() ); if ( model()->leftDropItem() == fileName ) painter->fillRect( rect.left(), rect.top(), 3, rect.height(), QBrush( Qt::red ) ); else if ( model()->rightDropItem() == fileName ) painter->fillRect( rect.right() -2, rect.top(), 3, rect.height(), QBrush( Qt::red ) ); } // vi:expandtab:tabstop=4 shiftwidth=4: diff --git a/ThumbnailView/ThumbnailWidget.cpp b/ThumbnailView/ThumbnailWidget.cpp index 9ee5628e..28199c3c 100644 --- a/ThumbnailView/ThumbnailWidget.cpp +++ b/ThumbnailView/ThumbnailWidget.cpp @@ -1,435 +1,442 @@ -/* Copyright (C) 2003-2018 Jesper K. Pedersen +/* Copyright (C) 2003-2019 The KPhotoAlbum Development Team 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "ThumbnailWidget.h" #include #include #include "Delegate.h" #include "ThumbnailDND.h" #include "KeyboardEventHandler.h" #include "ThumbnailFactory.h" #include "ThumbnailModel.h" #include "CellGeometry.h" #include #include #include #include #include #include "Browser/BrowserWidget.h" #include "DB/ImageDB.h" #include "DB/ImageInfoPtr.h" #include "Settings/SettingsData.h" -#include "Utilities/Util.h" #include "SelectionMaintainer.h" /** * \class ThumbnailView::ThumbnailWidget * This is the widget which shows the thumbnails. * * In previous versions this was implemented using a QIconView, but there * simply was too many problems, so after years of tears and pains I * rewrote it. */ ThumbnailView::ThumbnailWidget::ThumbnailWidget( ThumbnailFactory* factory) :QListView(), ThumbnailComponent( factory ), m_isSettingDate(false), m_gridResizeInteraction( factory ), m_wheelResizing( false ), m_externallyResizing( false ), m_selectionInteraction( factory ), m_mouseTrackingHandler( factory ), m_mouseHandler( &m_mouseTrackingHandler ), m_dndHandler( new ThumbnailDND( factory ) ), m_pressOnStackIndicator( false ), m_keyboardHandler( new KeyboardEventHandler( factory ) ), m_videoThumbnailCycler( new VideoThumbnailCycler(model()) ) { setModel( ThumbnailComponent::model() ); setResizeMode( QListView::Adjust ); setViewMode( QListView::IconMode ); setUniformItemSizes(true); setSelectionMode( QAbstractItemView::ExtendedSelection ); // It beats me why I need to set mouse tracking on both, but without it doesn't work. viewport()->setMouseTracking( true ); setMouseTracking( true ); connect( selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(scheduleDateChangeSignal()) ); viewport()->setAcceptDrops( true ); setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOn ); setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); connect(&m_mouseTrackingHandler, &MouseTrackingInteraction::fileIdUnderCursorChanged, this, &ThumbnailWidget::fileIdUnderCursorChanged); connect(m_keyboardHandler, &KeyboardEventHandler::showSelection, this, &ThumbnailWidget::showSelection); updatePalette(); setItemDelegate( new Delegate(factory, this) ); connect( selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(emitSelectionChangedSignal()) ); setDragEnabled(false); // We run our own dragging, so disable QListView's version. connect( verticalScrollBar(), SIGNAL(valueChanged(int)), model(), SLOT(updateVisibleRowInfo()) ); setupDateChangeTimer(); } bool ThumbnailView::ThumbnailWidget::isGridResizing() const { return m_mouseHandler->isResizingGrid() || m_wheelResizing || m_externallyResizing; } void ThumbnailView::ThumbnailWidget::keyPressEvent( QKeyEvent* event ) { if ( !m_keyboardHandler->keyPressEvent( event ) ) QListView::keyPressEvent( event ); } void ThumbnailView::ThumbnailWidget::keyReleaseEvent( QKeyEvent* event ) { const bool propagate = m_keyboardHandler->keyReleaseEvent( event ); if ( propagate ) QListView::keyReleaseEvent(event); } bool ThumbnailView::ThumbnailWidget::isMouseOverStackIndicator( const QPoint& point ) { // first check if image is stack, if not return. DB::ImageInfoPtr imageInfo = mediaIdUnderCursor().info(); if (!imageInfo) return false; if (!imageInfo->isStacked()) return false; const QModelIndex index = indexUnderCursor(); const QRect itemRect = visualRect( index ); const QPixmap pixmap = index.data( Qt::DecorationRole ).value(); if ( pixmap.isNull() ) return false; const QRect pixmapRect = cellGeometryInfo()->iconGeometry( pixmap ).translated( itemRect.topLeft() ); const QRect blackOutRect = pixmapRect.adjusted( 0,0, -10, -10 ); return pixmapRect.contains(point) && !blackOutRect.contains( point ); } static bool isMouseResizeGesture( QMouseEvent* event ) { return (event->button() & Qt::MidButton) || ((event->modifiers() & Qt::ControlModifier) && (event->modifiers() & Qt::AltModifier)); } void ThumbnailView::ThumbnailWidget::mousePressEvent( QMouseEvent* event ) { if ( (!(event->modifiers() & ( Qt::ControlModifier | Qt::ShiftModifier ) )) && isMouseOverStackIndicator( event->pos() ) ) { model()->toggleStackExpansion(mediaIdUnderCursor()); m_pressOnStackIndicator = true; return; } if ( isMouseResizeGesture( event ) ) m_mouseHandler = &m_gridResizeInteraction; else m_mouseHandler = &m_selectionInteraction; if ( !m_mouseHandler->mousePressEvent( event ) ) QListView::mousePressEvent( event ); if (event->button() & Qt::RightButton) //get out of selection mode if this is a right click m_mouseHandler = &m_mouseTrackingHandler; } void ThumbnailView::ThumbnailWidget::mouseMoveEvent( QMouseEvent* event ) { if ( m_pressOnStackIndicator ) return; if ( !m_mouseHandler->mouseMoveEvent( event ) ) QListView::mouseMoveEvent( event ); } void ThumbnailView::ThumbnailWidget::mouseReleaseEvent( QMouseEvent* event ) { if ( m_pressOnStackIndicator ) { m_pressOnStackIndicator = false; return; } if ( !m_mouseHandler->mouseReleaseEvent( event ) ) QListView::mouseReleaseEvent( event ); m_mouseHandler = &m_mouseTrackingHandler; } void ThumbnailView::ThumbnailWidget::mouseDoubleClickEvent( QMouseEvent * event ) { if ( isMouseOverStackIndicator( event->pos() ) ) { model()->toggleStackExpansion(mediaIdUnderCursor()); m_pressOnStackIndicator = true; } else if ( !( event->modifiers() & Qt::ControlModifier ) ) { DB::FileName id = mediaIdUnderCursor(); if ( !id.isNull() ) emit showImage( id ); } } void ThumbnailView::ThumbnailWidget::wheelEvent( QWheelEvent* event ) { if ( event->modifiers() & Qt::ControlModifier ) { event->setAccepted(true); if ( !m_wheelResizing) m_gridResizeInteraction.enterGridResizingMode(); m_wheelResizing = true; model()->beginResetModel(); const int delta = -event->delta() / 20; static int _minimum_ = Settings::SettingsData::instance()->minimumThumbnailSize(); Settings::SettingsData::instance()->setActualThumbnailSize( qMax( _minimum_, Settings::SettingsData::instance()->actualThumbnailSize() + delta ) ); cellGeometryInfo()->calculateCellSize(); model()->endResetModel(); } else { int delta = event->delta() / 5; QWheelEvent newevent = QWheelEvent(event->pos(), delta, event->buttons(), nullptr); QListView::wheelEvent(&newevent); } } void ThumbnailView::ThumbnailWidget::emitDateChange() { if ( m_isSettingDate ) return; int row = currentIndex().row(); if (row == -1) return; DB::FileName fileName = model()->imageAt( row ); if ( fileName.isNull() ) return; static QDateTime lastDate; QDateTime date = fileName.info()->date().start(); if ( date != lastDate ) { lastDate = date; if ( date.date().year() != 1900 ) emit currentDateChanged( date ); } } /** * scroll to the date specified with the parameter date. * The boolean includeRanges tells whether we accept range matches or not. */ void ThumbnailView::ThumbnailWidget::gotoDate( const DB::ImageDate& date, bool includeRanges ) { m_isSettingDate = true; DB::FileName candidate = DB::ImageDB::instance() ->findFirstItemInRange(model()->imageList(ViewOrder), date, includeRanges); if ( !candidate.isNull() ) setCurrentItem( candidate ); m_isSettingDate = false; } void ThumbnailView::ThumbnailWidget::setExternallyResizing( bool state ) { m_externallyResizing = state; } void ThumbnailView::ThumbnailWidget::reload(SelectionUpdateMethod method ) { SelectionMaintainer maintainer( this, model()); ThumbnailComponent::model()->beginResetModel(); cellGeometryInfo()->flushCache(); updatePalette(); ThumbnailComponent::model()->endResetModel(); if ( method == ClearSelection ) maintainer.disable(); } DB::FileName ThumbnailView::ThumbnailWidget::mediaIdUnderCursor() const { const QModelIndex index = indexUnderCursor(); if ( index.isValid() ) return model()->imageAt(index.row()); else return DB::FileName(); } QModelIndex ThumbnailView::ThumbnailWidget::indexUnderCursor() const { return indexAt( mapFromGlobal( QCursor::pos() ) ); } void ThumbnailView::ThumbnailWidget::dragMoveEvent( QDragMoveEvent* event ) { m_dndHandler->contentsDragMoveEvent(event); } void ThumbnailView::ThumbnailWidget::dragLeaveEvent( QDragLeaveEvent* event ) { m_dndHandler->contentsDragLeaveEvent( event ); } void ThumbnailView::ThumbnailWidget::dropEvent( QDropEvent* event ) { m_dndHandler->contentsDropEvent( event ); } void ThumbnailView::ThumbnailWidget::dragEnterEvent( QDragEnterEvent * event ) { m_dndHandler->contentsDragEnterEvent( event ); } void ThumbnailView::ThumbnailWidget::setCurrentItem( const DB::FileName& fileName ) { if ( fileName.isNull() ) return; const int row = model()->indexOf(fileName); setCurrentIndex( QListView::model()->index( row, 0 ) ); } DB::FileName ThumbnailView::ThumbnailWidget::currentItem() const { if ( !currentIndex().isValid() ) return DB::FileName(); return model()->imageAt( currentIndex().row()); } void ThumbnailView::ThumbnailWidget::updatePalette() { QPalette pal = palette(); pal.setBrush( QPalette::Base, QColor(Settings::SettingsData::instance()->backgroundColor()) ); - pal.setBrush( QPalette::Text, Utilities::contrastColor( QColor(Settings::SettingsData::instance()->backgroundColor() ) ) ); + pal.setBrush( QPalette::Text, contrastColor( QColor(Settings::SettingsData::instance()->backgroundColor() ) ) ); setPalette( pal ); } int ThumbnailView::ThumbnailWidget::cellWidth() const { return visualRect( QListView::model()->index(0,0) ).size().width(); } void ThumbnailView::ThumbnailWidget::emitSelectionChangedSignal() { emit selectionCountChanged( selection( ExpandCollapsedStacks ).size() ); } void ThumbnailView::ThumbnailWidget::scheduleDateChangeSignal() { m_dateChangedTimer->start(200); } /** * During profiling, I found that emitting the dateChanged signal was * rather expensive, so now I delay that signal, so it is only emitted 200 * msec after the scroll, which means it will not be emitted when the user * holds down, say the page down key for scrolling. */ void ThumbnailView::ThumbnailWidget::setupDateChangeTimer() { m_dateChangedTimer = new QTimer(this); m_dateChangedTimer->setSingleShot(true); connect(m_dateChangedTimer, &QTimer::timeout, this, &ThumbnailWidget::emitDateChange); } void ThumbnailView::ThumbnailWidget::showEvent( QShowEvent* event ) { model()->updateVisibleRowInfo(); QListView::showEvent( event ); } DB::FileNameList ThumbnailView::ThumbnailWidget::selection( ThumbnailView::SelectionMode mode ) const { DB::FileNameList res; Q_FOREACH(const QModelIndex& index, selectedIndexes()) { DB::FileName currFileName = model()->imageAt(index.row()); bool includeAllStacks = false; switch ( mode ) { case IncludeAllStacks: includeAllStacks = true; /* FALLTHROUGH */ case ExpandCollapsedStacks: { // if the selected image belongs to a collapsed thread, // imply that all images in the stack are selected: DB::ImageInfoPtr imageInfo = currFileName.info(); if ( imageInfo && imageInfo->isStacked() && ( includeAllStacks || ! model()->isItemInExpandedStack( imageInfo->stackId() ) ) ) { // add all images in the same stack res.append(DB::ImageDB::instance()->getStackFor(currFileName)); } else res.append(currFileName); } break; case NoExpandCollapsedStacks: res.append(currFileName); break; } } return res; } bool ThumbnailView::ThumbnailWidget::isSelected( const DB::FileName& fileName ) const { return selection( NoExpandCollapsedStacks ).indexOf(fileName) != -1; } /** This very specific method will make the item specified by id selected, if there only are one item selected. This is used from the Viewer when you start it without a selection, and are going forward or backward. */ void ThumbnailView::ThumbnailWidget::changeSingleSelection(const DB::FileName& fileName) { if ( selection( NoExpandCollapsedStacks ).size() == 1 ) { QItemSelectionModel* selection = selectionModel(); selection->select( model()->fileNameToIndex(fileName), QItemSelectionModel::ClearAndSelect ); setCurrentItem(fileName); } } void ThumbnailView::ThumbnailWidget::select(const DB::FileNameList& items ) { Q_FOREACH( const DB::FileName& fileName, items ) selectionModel()->select(model()->fileNameToIndex(fileName), QItemSelectionModel::Select); } bool ThumbnailView::ThumbnailWidget::isItemUnderCursorSelected() const { return widget()->selection(ExpandCollapsedStacks).contains(mediaIdUnderCursor()); } +QColor ThumbnailView::contrastColor(const QColor &color) +{ + if ( color.red() < 127 && color.green() < 127 && color.blue() < 127 ) + return Qt::white; + else + return Qt::black; +} + // vi:expandtab:tabstop=4 shiftwidth=4: diff --git a/ThumbnailView/ThumbnailWidget.h b/ThumbnailView/ThumbnailWidget.h index 60921777..a4bf84bf 100644 --- a/ThumbnailView/ThumbnailWidget.h +++ b/ThumbnailView/ThumbnailWidget.h @@ -1,153 +1,154 @@ -/* Copyright (C) 2003-2010 Jesper K. Pedersen +/* Copyright (C) 2003-2019 The KPhotoAlbum Development Team 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef THUMBNAILVIEW_THUMBNAILWIDGET_H #define THUMBNAILVIEW_THUMBNAILWIDGET_H #include #include "ThumbnailComponent.h" #include "GridResizeInteraction.h" #include "MouseTrackingInteraction.h" #include "SelectionInteraction.h" #include "ThumbnailView/enums.h" #include #include "VideoThumbnailCycler.h" class QTimer; class QDateTime; namespace DB { class ImageDate; class Id; class FileNameList;} namespace ThumbnailView { class ThumbnailPainter; class CellGeometry; class ThumbnailModel; class ThumbnailFactory; class KeyboardEventHandler; class ThumbnailDND; class ThumbnailWidget : public QListView, private ThumbnailComponent { Q_OBJECT public: explicit ThumbnailWidget( ThumbnailFactory* factory ); void reload( SelectionUpdateMethod method ); DB::FileName mediaIdUnderCursor() const; QModelIndex indexUnderCursor() const; bool isMouseOverStackIndicator( const QPoint& point ); bool isGridResizing() const; void setCurrentItem( const DB::FileName& fileName ); DB::FileName currentItem() const; void changeSingleSelection(const DB::FileName& fileName); // Misc int cellWidth() const; void showEvent( QShowEvent* ) override; DB::FileNameList selection( ThumbnailView::SelectionMode mode ) const; bool isSelected( const DB::FileName& id ) const; void select( const DB::FileNameList& ); bool isItemUnderCursorSelected() const; public slots: void gotoDate( const DB::ImageDate& date, bool includeRanges ); /** * @brief setExternallyResizing * Used by the GridResizeSlider to indicate that the grid is being resized. * @param state true, if the grid is being resized by an external widget, false if not */ void setExternallyResizing( bool state ); signals: void showImage( const DB::FileName& id ); void showSelection(); void fileIdUnderCursorChanged( const DB::FileName& id ); void currentDateChanged( const QDateTime& ); void selectionCountChanged(int numberOfItemsSelected ); protected: // event handlers void keyPressEvent( QKeyEvent* ) override; void keyReleaseEvent( QKeyEvent* ) override; void mousePressEvent( QMouseEvent* ) override; void mouseMoveEvent( QMouseEvent* ) override; void mouseReleaseEvent( QMouseEvent* ) override; void mouseDoubleClickEvent ( QMouseEvent* ) override; void wheelEvent( QWheelEvent* ) override; // Drag and drop void dragEnterEvent ( QDragEnterEvent * event ) override; void dragMoveEvent ( QDragMoveEvent * ) override; void dragLeaveEvent ( QDragLeaveEvent * ) override; void dropEvent ( QDropEvent * ) override; private slots: void emitDateChange(); void scheduleDateChangeSignal(); void emitSelectionChangedSignal(); private: friend class GridResizeInteraction; inline ThumbnailModel* model() { return ThumbnailComponent::model(); } inline const ThumbnailModel* model() const { return ThumbnailComponent::model(); } void updatePalette(); void setupDateChangeTimer(); /** * When the user selects a date on the date bar the thumbnail view will * position itself accordingly. As a consequence, the thumbnail view * is telling the date bar which date it moved to. This is all fine * except for the fact that the date selected in the date bar, may be * for an image which is in the middle of a line, while the date * emitted from the thumbnail view is for the top most image in * the view (that is the first image on the line), which results in a * different cell being selected in the date bar, than what the user * selected. * Therefore we need this variable to disable the emission of the date * change while setting the date. */ bool m_isSettingDate; GridResizeInteraction m_gridResizeInteraction; bool m_wheelResizing; bool m_externallyResizing; SelectionInteraction m_selectionInteraction; MouseTrackingInteraction m_mouseTrackingHandler; MouseInteraction* m_mouseHandler; ThumbnailDND* m_dndHandler; bool m_pressOnStackIndicator; QTimer* m_dateChangedTimer; friend class SelectionInteraction; friend class KeyboardEventHandler; friend class ThumbnailDND; friend class ThumbnailModel; KeyboardEventHandler* m_keyboardHandler; QScopedPointer m_videoThumbnailCycler; }; +QColor contrastColor( const QColor &color); } #endif /* THUMBNAILVIEW_THUMBNAILWIDGET_H */ // vi:expandtab:tabstop=4 shiftwidth=4: diff --git a/Utilities/Util.cpp b/Utilities/Util.cpp index 42533f54..dbd914e4 100644 --- a/Utilities/Util.cpp +++ b/Utilities/Util.cpp @@ -1,61 +1,52 @@ -/* Copyright (C) 2003-2010 Jesper K. Pedersen +/* Copyright (C) 2003-2019 The KPhotoAlbum Development Team 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "Util.h" #include #include extern "C" { #include } bool Utilities::copy( const QString& from, const QString& to ) { if ( QFileInfo(to).exists()) QDir().remove(to); return QFile::copy(from,to); } bool Utilities::makeHardLink( const QString& from, const QString& to ) { if (link(from.toLocal8Bit().constData(), to.toLocal8Bit().constData()) != 0) return false; else return true; } bool Utilities::makeSymbolicLink( const QString& from, const QString& to ) { if (symlink(from.toLocal8Bit().constData(), to.toLocal8Bit().constData()) != 0) return false; else return true; } - -QColor Utilities::contrastColor( const QColor& col ) -{ - if ( col.red() < 127 && col.green() < 127 && col.blue() < 127 ) - return Qt::white; - else - return Qt::black; -} - // vi:expandtab:tabstop=4 shiftwidth=4: diff --git a/Utilities/Util.h b/Utilities/Util.h index fd9c290b..55e7a245 100644 --- a/Utilities/Util.h +++ b/Utilities/Util.h @@ -1,38 +1,36 @@ -/* Copyright (C) 2003-2010 Jesper K. Pedersen +/* Copyright (C) 2003-2019 The KPhotoAlbum Development Team 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef UTIL_H #define UTIL_H #include #include namespace Utilities { bool copy( const QString& from, const QString& to ); bool makeSymbolicLink( const QString& from, const QString& to ); bool makeHardLink( const QString& from, const QString& to ); -QColor contrastColor( const QColor& ); - } #endif /* UTIL_H */ // vi:expandtab:tabstop=4 shiftwidth=4: