/* This file is part of the KDE project Copyright (C) 2001,2002 Carsten Pfeiffer 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 #include #include #include #include #include #include #include #include #include #include #include #include "loader.h" #include "mrml_creator.h" #include "mrml_view.h" using namespace KMrml; MrmlView::MrmlView( TQWidget *parent, const char *name ) : TQScrollView( parent, name ) { setStaticBackground( true ); setResizePolicy( Manual ); setHScrollBarMode( AlwaysOff ); enableClipper( true ); // ### test this m_items.setAutoDelete( true ); connect( Loader::self(), TQT_SIGNAL( finished(const KURL&, const TQByteArray&)), TQT_SLOT( slotDownloadFinished( const KURL&, const TQByteArray& ))); m_timer = new TQTimer( this ); connect( m_timer, TQT_SIGNAL( timeout() ), TQT_SLOT( slotLayout() )); // we need a pixmap to be shown when no thumbnail is available for a // query result image TQLabel l( i18n( "No thumbnail available" ), 0L ); l.setFixedSize( 80, 80 ); l.setAlignment( WordBreak | AlignCenter ); // l.setFrameStyle( TQLabel::Box | TQLabel::Plain ); // l.setLineWidth( 1 ); l.setPaletteBackgroundColor( TQt::white ); l.setPaletteForegroundColor( TQt::black ); m_unavailablePixmap = TQPixmap::grabWidget( &l ); } MrmlView::~MrmlView() { } MrmlViewItem * MrmlView::addItem( const KURL& url, const KURL& thumbURL, const TQString& similarity ) { bool ok; double value = similarity.toDouble( &ok ); if ( !ok || value < 0.05 ) return 0L; return addItem( url, thumbURL, value ); } MrmlViewItem * MrmlView::addItem( const KURL& url, const KURL& thumbURL, double similarity ) { if ( !url.isValid() ) { tqWarning( "MrmlPart: received malformed URL from query: %s", url.prettyURL().isNull() ? "(null)" : url.prettyURL().latin1() ); return 0L; } // tqDebug("** url: %s", thumbURL.url().latin1()); MrmlViewItem *item = new MrmlViewItem( url, thumbURL, similarity, this ); TQPixmap *pixmap = getPixmap( thumbURL ); if ( pixmap ) item->setPixmap( *pixmap ); m_items.append( item ); m_timer->start( 0, true ); return item; } void MrmlView::addRelevanceToQuery( TQDomDocument& document, TQDomElement& parent ) { TQPtrListIterator it( m_items ); for( ; it.current(); ++it ) { it.current()->createRelevanceElement( document, parent ); } } void MrmlView::clear() { m_items.clear(); // items are deleted and removed from scrollview setContentsPos( 0, 0 ); } TQPixmap * MrmlView::getPixmap( const KURL& url ) { TQString u = url.url(); TQPixmap *pix = m_pixmapCache.find( u ); if ( pix ) return pix; if ( url.isLocalFile() ) { TQPixmap p; if ( !p.load( url.path() ) ) p = m_unavailablePixmap; m_pixmapCache.insert( u, p ); return m_pixmapCache.find( u ); } else { // remote url, download with TDEIO Loader::self()->requestDownload( url ); } return 0L; } void MrmlView::slotDownloadFinished( const KURL& url, const TQByteArray& data ) { TQPtrListIterator it( m_items ); for( ; it.current(); ++it ) { MrmlViewItem *item = it.current(); if ( item->thumbURL() == url ) { TQPixmap p; if ( data.isEmpty() || !p.loadFromData( data ) ) p = m_unavailablePixmap; m_pixmapCache.insert( url.url(), p ); item->setPixmap( p ); slotLayout(); return; } } } void MrmlView::stopDownloads() { Loader *loader = Loader::self(); TQPtrListIterator it( m_items ); for( ; it.current(); ++it ) { MrmlViewItem *item = it.current(); if ( !item->hasRemotePixmap() ) loader->removeDownload( item->url() ); } } void MrmlView::slotLayout() { int itemWidth = 0; TQPtrListIterator it( m_items ); for ( ; it.current(); ++it ) { itemWidth = TQMAX( itemWidth, it.current()->sizeHint().width() ); } if ( itemWidth == 0 ) return; uint itemsPerRow = visibleWidth() / itemWidth; int margin = (visibleWidth() - (itemsPerRow * itemWidth)) / 2; int rowHeight = 0; uint item = 0; uint y = 5; // pointing to the first item of a row TQPtrListIterator rowIt( m_items ); for ( it.toFirst(); it.current(); ++it ) { if ( item >= itemsPerRow ) { item = 0; y += rowHeight; rowHeight = 0; } if ( item == 0 ) rowIt = it; rowHeight = TQMAX( rowHeight, it.current()->sizeHint().height() ); addChild( it.current(), margin + item * itemWidth, y ); it.current()->show(); item++; // resize all items of the current row so they all have the same size if ( item >= itemsPerRow || it.atLast() ) { for ( uint i = 0; (i < itemsPerRow && rowIt.current()); i++ ) { rowIt.current()->resize( itemWidth, rowHeight ); ++rowIt; } } } resizeContents( visibleWidth(), y + rowHeight ); } void MrmlView::resizeEvent( TQResizeEvent *e ) { int oldW = visibleWidth(); TQScrollView::resizeEvent( e ); if ( visibleWidth() != oldW ) slotLayout(); } void MrmlView::saveState( TQDataStream& stream ) { stream << m_items.count(); TQPtrListIterator it( m_items ); for( ; it.current(); ++it ) { stream << *it.current(); } } void MrmlView::restoreState( TQDataStream& stream ) { stopDownloads(); clear(); int count; stream >> count; KURL url, thumbURL; double similarity; TQ_UINT32 relevance; MrmlViewItem *item; for ( int i = 0; i < count; i++ ) { stream >> url; stream >> thumbURL; stream >> similarity; stream >> relevance; item = addItem( url, thumbURL, similarity ); if ( item ) item->setRelevance( (MrmlViewItem::Relevance) relevance ); } } TQDataStream& KMrml::operator<<( TQDataStream& stream, const KMrml::MrmlViewItem& item ) { return stream << item.url() << item.thumbURL() << item.similarity() << static_cast( item.relevance() ); } /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// MrmlViewItem::MrmlViewItem( const KURL& url, const KURL& thumbURL, double similarity, MrmlView *view, const char *name ) : TQFrame( view->viewport() , name ), m_view( view ), m_url( url ), m_thumbURL( thumbURL ), similarityFullWidth( 120 ), // ### m_hasRemotePixmap( false ) { if ( m_similarity != -1 ) m_similarity = TQMAX( 0.0, TQMIN( 1.0, similarity )); setFrameStyle( Panel | Sunken ); setMouseTracking( true ); m_combo = new KComboBox( this ); TQToolTip::add( m_combo, i18n("You can refine queries by giving feedback about the current result and pressing the Search button again.") ); m_combo->insertItem( i18n("Relevant"), Relevant ); m_combo->insertItem( i18n("Neutral"), Neutral ); m_combo->insertItem( i18n("Irrelevant"), Irrelevant ); m_combo->adjustSize(); m_combo->setCurrentItem( Neutral ); /* if ( similarity > -1 ) TQToolTip::add( this, TQString::fromLatin1("%1
%1
") .arg( url ) .arg(i18n("Similarity: %1").arg( TQString::number(similarity)))); else TQToolTip::add( this, TQString::fromLatin1("%1").arg( url ) ); */ setMinimumSize( 130, 130 ); // ### } MrmlViewItem::~MrmlViewItem() { } void MrmlViewItem::setPixmap( const TQPixmap& pix ) { if ( !m_url.isLocalFile() ) m_hasRemotePixmap = true; m_pixmap = pix; adjustSize(); update(); } void MrmlViewItem::paintEvent( TQPaintEvent *e ) { TQFrame::paintEvent( e ); if ( !m_pixmap.isNull() ) { bitBlt( this, pixmapX(), pixmapY(), &m_pixmap, 0, 0, m_pixmap.width(), m_pixmap.height(), CopyROP ); } if ( m_similarity >= 0 ) { TQPainter p( this ); TQPen pen( colorGroup().highlight(), 1, TQPen::SolidLine ); p.setPen( pen ); int x = margin; int y = m_combo->y() - similarityHeight - 2; int w = (int) (similarityFullWidth * m_similarity); int h = similarityHeight; p.drawRect( x, y, similarityFullWidth, h ); p.fillRect( x, y, w, h, colorGroup().highlight() ); } } void MrmlViewItem::resizeEvent( TQResizeEvent *e ) { TQFrame::resizeEvent( e ); int y = height() - m_combo->height() - margin; m_combo->move( width()/2 - m_combo->width()/2, y ); } TQSize MrmlViewItem::sizeHint() const { int w = TQMAX( TQMAX(minimumHeight(), m_combo->width()), m_pixmap.width() ); w += 2 * margin; int h = m_pixmap.isNull() ? margin : margin + spacing + m_pixmap.height(); h += (m_similarity > -1) ? similarityHeight + spacing : 0; h += m_combo->height() + margin; return TQSize( w, h ); } void MrmlViewItem::mousePressEvent( TQMouseEvent *e ) { TQFrame::mousePressEvent( e ); pressedPos.setX( 0 ); pressedPos.setY( 0 ); if ( e->button() == Qt::LeftButton || e->button() == Qt::MidButton ) { if ( hitsPixmap( e->pos() ) ) pressedPos = e->pos(); } else if ( e->button() == Qt::RightButton && hitsPixmap( e->pos() ) ) emit view()->activated( m_url, e->button() ); } void MrmlViewItem::mouseMoveEvent( TQMouseEvent *e ) { if ( hitsPixmap( e->pos() ) ) { if ( !ownCursor() ) { // nice hacklet :) setCursor( KCursor::handCursor() ); emit view()->onItem( m_url ); } } else { if ( ownCursor() ) { unsetCursor(); emit view()->onItem( KURL() ); } } if ( (e->state() & Qt::LeftButton) && !pressedPos.isNull() ) { TQPoint dist = e->pos() - pressedPos; if ( dist.manhattanLength() > TDEGlobalSettings::dndEventDelay() ) { // start drag here KURL::List urls; // ### support multiple files? urls.append( m_url ); KURLDrag *drag = new KURLDrag( urls, this ); drag->setPixmap( KMimeType::pixmapForURL( m_url ) ); drag->drag(); } } } void MrmlViewItem::mouseReleaseEvent( TQMouseEvent *e ) { if ( hitsPixmap( e->pos() )) { TQPoint dist = e->pos() - pressedPos; if ( dist.manhattanLength() < TDEGlobalSettings::dndEventDelay() ) { emit view()->activated( m_url, e->button() ); } } } bool MrmlViewItem::hitsPixmap( const TQPoint& pos ) const { if ( m_pixmap.isNull() ) return false; if ( pos.x() > pixmapX() && pos.x() < pixmapX() + m_pixmap.width() && pos.y() > pixmapY() && pos.y() < pixmapY() + m_pixmap.height() ) return true; return false; } void MrmlViewItem::createRelevanceElement( TQDomDocument& document, TQDomElement& parent ) { int rel = m_combo->currentItem(); if ( rel == Neutral ) return; MrmlCreator::createRelevanceElement( document, parent, m_url.url(), (rel == Relevant) ? MrmlCreator::Relevant : MrmlCreator::Irrelevant ); } MrmlViewItem::Relevance MrmlViewItem::relevance() const { return (Relevance) m_combo->currentItem(); } void MrmlViewItem::setRelevance( Relevance relevance ) { m_combo->setCurrentItem( relevance ); } /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// int MrmlViewItemList::compareItems( TQPtrCollection::Item item1, TQPtrCollection::Item item2 ) { double s1 = (static_cast( item1 ))->similarity(); double s2 = (static_cast( item2 ))->similarity(); if ( s1 < s2 ) return 1; else if ( s1 > s2 ) return -1; else return 0; } #include "mrml_view.moc"