📄 thumbnailview_p.cpp
字号:
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS. All rights reserved.**** This file is part of the Qtopia Environment.** ** 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.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** 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.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "thumbnailview_p.h"#include "image.h"#include <qtopia/qpeapplication.h>#ifdef QTOPIA_PHONE#include <qtopia/contextbar.h>#endif#include <cmath>#include <qpixmap.h>#include <qpixmapcache.h>#include <qstring.h>#include <qfileinfo.h>#define DEFAULT_THUMBNAIL_SIZE 65ThumbnailItem::ThumbnailItem( QIconView* parent, const QString& description, const QString& file, int s, ThumbnailServer* ts ) : QIconViewItem( parent, description ){ init( file, s, ts );} ThumbnailItem::ThumbnailItem( QIconView* parent, QIconViewItem* after, const QString& description, const QString& file, int s, ThumbnailServer* ts ) : QIconViewItem( parent, after, description ){ init( file, s, ts );}void ThumbnailItem::init( const QString& file, int s, ThumbnailServer* ts ){ _size = s; _loaded = false; loading = false; thumbnail_server = ts; // Store filename in key setKey( file ); // If image currently in cache, load from cache QString key = "_" + file + QFileInfo(file).lastModified().toString() + QString::number(size()); key = key.replace( QRegExp(" "), "_" ); QPixmap image; if ( QPixmapCache::find(key, image) ) setPixmap( image );}void ThumbnailItem::setPixmap( const QPixmap& pix ){ _loaded = true; QIconViewItem::setPixmap( pix, true, false ); iconView()->arrangeItemsInGrid( false ); iconView()->viewport()->update();} void ThumbnailItem::paintItem( QPainter* p, const QColorGroup& cg ){ if( !_loaded && !loading ) { loading = true; thumbnail_server->load( this ); } QIconViewItem::paintItem( p, cg );}ThumbnailServer::ThumbnailServer( QObject* parent, const char* name ) : QObject( parent, name ), running( false ){ connect( &load_timer, SIGNAL( timeout() ), this, SLOT( loadFront() ) );}void ThumbnailServer::load( ThumbnailItem* item ){#define PAUSE 75 // Enqueue thumbnail item queue.enqueue( item ); // If load timer not started, start timer if( !running ) { running = true; load_timer.start( PAUSE, true ); }} void ThumbnailServer::loadFront(){ // Remove all items from front of queue that are not visible bool item_visible = false; while( !queue.isEmpty() && !item_visible ) { ThumbnailItem *item = queue.head(); // If item visible, set item visible // Otherwise, remove from queue QScrollView *view = item->iconView(); QRect viewport( view->contentsX(), view->contentsY(), view->visibleWidth(), view->visibleHeight() ); if( item->intersects( viewport ) ) item_visible = true; else queue.dequeue()->reload(); } // If queue is not empty, dequeue and load item if( !queue.isEmpty() ) { ThumbnailItem *item = queue.dequeue(); if ( !item->loaded() ) { // If image currently in cache, load from cache // Otherwise, load image into cache QFileInfo file_info(item->key()); QString key = "_" + item->key() + file_info.lastModified().toString() + QString::number(item->size()); key = key.replace( QRegExp(" "), "_" ); QPixmap image; if ( !QPixmapCache::find(key, image) ) { image.convertFromImage(Image::loadScaled(item->key(), item->size(), item->size())); QPixmapCache::insert(key, image); } item->setPixmap( image ); } } // If queue is not empty, start timer if( !queue.isEmpty() ) { load_timer.start( PAUSE, true ); } else { running = false; load_timer.stop(); }}void IconView::showEvent( QShowEvent* e ){ QIconView::showEvent( e ); // Ensure current selection is visible ensureItemVisible( currentItem() );}ThumbnailView::ThumbnailView( QWidget* parent, const char* name, WFlags f ) : QVBox( parent, name, f ), thumbnail_size( DEFAULT_THUMBNAIL_SIZE ){ thumbnail_server = new ThumbnailServer( this ); // Construct icon view icon_view = new IconView( this ); icon_view->setHScrollBarMode( QScrollView::AlwaysOff ); icon_view->setItemsMovable( false ); icon_view->setWordWrapIconText( false ); icon_view->setResizeMode( QIconView::Adjust ); icon_view->setMaxItemWidth( thumbnail_size ); connect( icon_view, SIGNAL( currentChanged( QIconViewItem* ) ), this, SLOT( currentChanged( QIconViewItem* ) ) ); connect( icon_view, SIGNAL( mouseButtonClicked( int, QIconViewItem*, const QPoint& ) ), this, SLOT( clicked( int, QIconViewItem*, const QPoint& ) ) ); #ifndef QTOPIA_PHONE // Enable stylus press events QPEApplication::setStylusOperation( icon_view->viewport(), QPEApplication::RightOnHold ); connect( icon_view, SIGNAL( mouseButtonPressed( int, QIconViewItem*, const QPoint& ) ), this, SLOT( pressed( int, QIconViewItem*, const QPoint& ) ) );#endif // Filter key events before passing to icon view icon_view->installEventFilter( this ); // Give icon view control setFocusProxy( icon_view );}void ThumbnailView::setThumbnailSize( int maxSide ){ // If new size not equal to current, update size and resize thumbnails if( maxSide != thumbnail_size ) { thumbnail_size = maxSide; icon_view->setMaxItemWidth( thumbnail_size ); // Reload thumbnails in view thumbnail_server->clear(); icon_view->setMaxItemWidth( thumbnail_size ); ThumbnailItem *item; for( item = static_cast< ThumbnailItem* >( icon_view->firstItem() ); item; item = static_cast< ThumbnailItem* >( item->nextItem() ) ) item->resize( thumbnail_size ); icon_view->viewport()->update(); }}void ThumbnailView::insert( const DocLnk& image ){ // Insert image into view sorted by user visible name // Find first item in view with name greater than image name QIconViewItem* item = findGE( image ); // If item exists, insert image before item // Otherwise, append image to view if( item ) { item = item->prevItem(); if( item ) new ThumbnailItem( icon_view, item, image.name(), image.file(), thumbnail_size, thumbnail_server ); else { item = icon_view->firstItem(); // Insert image after first item new ThumbnailItem( icon_view, item, image.name(), image.file(), thumbnail_size, thumbnail_server ); // Swap first and second items in view icon_view->takeItem( item ); icon_view->insertItem( item, icon_view->firstItem() ); } } else new ThumbnailItem( icon_view, image.name(), image.file(), thumbnail_size, thumbnail_server );}void ThumbnailView::update( const DocLnk& image ){ QIconViewItem* item = find( image ); // Disable changed singnals disconnect( icon_view, SIGNAL( currentChanged( QIconViewItem* ) ), this, SLOT( currentChanged( QIconViewItem* ) ) ); // Update image name and thumbnail item->setText( image.name() ); static_cast< ThumbnailItem* > ( item )->reload(); // Remove image from view icon_view->takeItem( item ); // Insert image into view sorted by user visible name QIconViewItem* p = findGE( image ); // If image exists with name >= image to be updated, insert before image // Otherwise, append image to view if( p ) { p = p->prevItem(); if( p ) icon_view->insertItem( item, p ); else { p = icon_view->firstItem(); icon_view->insertItem( item, p ); icon_view->takeItem( p ); icon_view->insertItem( p, item ); } } else icon_view->insertItem( item, p ); item->setSelected( true ); icon_view->ensureItemVisible( item ); // Enable changed signals connect( icon_view, SIGNAL( currentChanged( QIconViewItem* ) ), this, SLOT( currentChanged( QIconViewItem* ) ) );}void ThumbnailView::remove( const DocLnk& image ){ // Disable changed singnals disconnect( icon_view, SIGNAL( currentChanged( QIconViewItem* ) ), this, SLOT( currentChanged( QIconViewItem* ) ) ); // Remove image from view QIconViewItem *item = find( image ); delete item; // Enable changed signals connect( icon_view, SIGNAL( currentChanged( QIconViewItem* ) ), this, SLOT( currentChanged( QIconViewItem* ) ) );}void ThumbnailView::clear(){ // Remove all pending thumbnails from thumbnail server thumbnail_server->clear(); // Remove all images from view icon_view->clear();}void ThumbnailView::setHighlighedImage( const DocLnk& image ){ // Disable changed singnals disconnect( icon_view, SIGNAL( currentChanged( QIconViewItem* ) ), this, SLOT( currentChanged( QIconViewItem* ) ) ); // Highlight image and make sure image is visable QIconViewItem *item = find( image ); icon_view->setSelected( item, true ); icon_view->ensureItemVisible( item ); // Enable changed signals connect( icon_view, SIGNAL( currentChanged( QIconViewItem* ) ), this, SLOT( currentChanged( QIconViewItem* ) ) );}void ThumbnailView::currentChanged( QIconViewItem* item ){ if( item ) { // Make currently highlighted image current in collection DocLnk image; image.setFile( item->key() ); emit currentChanged( image ); }}void ThumbnailView::clicked( int button, QIconViewItem* item, const QPoint& ){ // If left button clicked on thumbnail, emit selected if( item && button == Qt::LeftButton ) emit selected();}void ThumbnailView::pressed( int button, QIconViewItem* item, const QPoint& pos ){ // If right button pressed on thumbnail, emit held if( item && button == Qt::RightButton ) emit held( pos );}bool ThumbnailView::eventFilter( QObject*, QEvent* e ){ if( e->type() == QEvent::KeyPress ) { switch( ( static_cast< QKeyEvent* > ( e ) )->key() ) { // If select key, emit select signal#ifdef QTOPIA_PHONE case Qt::Key_Select:#endif case Qt::Key_Enter: emit selected(); return true; } } return false;}QIconViewItem* ThumbnailView::find( const DocLnk& image ){ QIconViewItem *item; for( item = icon_view->firstItem(); item && item->key() != image.file(); item = item->nextItem() ); return item;}QIconViewItem* ThumbnailView::findGE( const DocLnk& image ){ QIconViewItem *item; for( item = icon_view->firstItem(); item && item->text().lower().compare( image.name().lower() ) < 0; item = item->nextItem() ); return item;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -