]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/tagcloud/tagcloud.cpp
assure that no expensive operations are done when the Information Panel has been...
[dolphin.git] / src / tagcloud / tagcloud.cpp
index 8fe5cba891980b0497e791131f2b293ce0ab96a4..2afd62e3b7ef8778e2863065d2d1a7c75323b6c8 100644 (file)
@@ -131,7 +131,7 @@ public:
           hoverTag( 0 ),
           cachedHfwWidth( -1 ),
           m_parent( parent ) {
-        newTagNode.text = i18n( "New Tag..." );
+        newTagNode.text = i18nc( "@label", "New Tag..." );
     }
 
     int maxFontSize;
@@ -204,7 +204,7 @@ int Nepomuk::TagCloud::Private::calculateWeight( const Nepomuk::Tag& tag )
     Soprano::QueryResultIterator it
         = ResourceManager::instance()->mainModel()->executeQuery( QString( "select ?r where { ?r <%1> <%2> . }" )
                                                                   .arg( Soprano::Vocabulary::NAO::hasTag().toString() )
-                                                                  .arg( tag.resourceUri().toString() ),
+                                                                  .arg( QString::fromAscii( tag.resourceUri().toEncoded() ) ),
                                                                   Soprano::Query::QueryLanguageSparql );
     int w = 0;
     while ( it.next() ) {
@@ -281,10 +281,6 @@ void Nepomuk::TagCloud::Private::sortNodes()
 
 void Nepomuk::TagCloud::Private::rebuildCloud()
 {
-    if ( nodes.isEmpty() && !newTagButtonEnabled ) {
-        return;
-    }
-
     // - Always try to be quadratic
     // - Always prefer to expand horizontally
     // - If we cannot fit everything into m_parent->contentsRect(), zoom
@@ -297,7 +293,7 @@ void Nepomuk::TagCloud::Private::rebuildCloud()
     // initialize the nodes' sizes
     // ----------------------------------------------
     for ( QList<TagNode>::iterator it = nodes.begin();
-              it != nodes.end(); ++it ) {
+          it != nodes.end(); ++it ) {
         TagNode& node = *it;
         node.rect = QFontMetrics( node.font ).boundingRect( node.text );
     }
@@ -309,154 +305,156 @@ void Nepomuk::TagCloud::Private::rebuildCloud()
     // and position the nodes
     // ----------------------------------------------
     rows.clear();
-    if ( 0 ) { // FIXME: make it configurable
-        QRect lineRect;
-        QRect totalRect;
-        QList<TagNode*> row;
-        for ( QList<TagNode>::iterator it = nodes.begin();
-              it != nodes.end(); /* We do increment it below */ ) {
-            TagNode& node = *it;
+    if ( !nodes.isEmpty() || newTagButtonEnabled ) {
+        if ( 0 ) { // FIXME: make it configurable
+            QRect lineRect;
+            QRect totalRect;
+            QList<TagNode*> row;
+            for ( QList<TagNode>::iterator it = nodes.begin();
+                  it != nodes.end(); /* We do increment it below */ ) {
+                TagNode& node = *it;
+
+                int usedSpacing = row.isEmpty() ? 0 : s_hSpacing;
+                if ( lineRect.width() + usedSpacing + node.rect.width() <= contentsRect.width() ) {
+                    node.rect.moveBottomLeft( QPoint( lineRect.right() + usedSpacing, lineRect.bottom() ) );
+                    QRect newLineRect = lineRect.united( node.rect );
+                    newLineRect.moveTopLeft( lineRect.topLeft() );
+                    lineRect = newLineRect;
+                    row.append( &node );
+
+                    // update all other nodes in this line
+                    Q_FOREACH( TagNode* n, row ) {
+                        n->rect.moveBottom( lineRect.bottom() - ( lineRect.height() - n->rect.height() )/2 );
+                    }
 
-            int usedSpacing = row.isEmpty() ? 0 : s_hSpacing;
-            if ( lineRect.width() + usedSpacing + node.rect.width() <= contentsRect.width() ) {
-                node.rect.moveBottomLeft( QPoint( lineRect.right() + usedSpacing, lineRect.bottom() ) );
-                QRect newLineRect = lineRect.united( node.rect );
-                newLineRect.moveTopLeft( lineRect.topLeft() );
-                lineRect = newLineRect;
-                row.append( &node );
-
-                // update all other nodes in this line
-                Q_FOREACH( TagNode* n, row ) {
-                    n->rect.moveBottom( lineRect.bottom() - ( lineRect.height() - n->rect.height() )/2 );
+                    ++it;
+                }
+                else {
+                    rows.append( row );
+                    row.clear();
+                    int newLineTop = lineRect.bottom() + s_vSpacing;
+                    lineRect = QRect();
+                    lineRect.moveTop( newLineTop );
                 }
-
-                ++it;
-            }
-            else {
-                rows.append( row );
-                row.clear();
-                int newLineTop = lineRect.bottom() + s_vSpacing;
-                lineRect = QRect();
-                lineRect.moveTop( newLineTop );
             }
+            rows.append( row );
         }
-        rows.append( row );
-    }
-    else {
-        // initialize first row
-        rows.append( QList<TagNode*>() );
-        for ( QList<TagNode>::iterator it = nodes.begin();
-              it != nodes.end(); ++it ) {
-            TagNode& node = *it;
-            rows.first().append( &node );
-        }
-        if ( newTagButtonEnabled ) {
-            rows.first().append( &newTagNode );
-        }
+        else {
+            // initialize first row
+            rows.append( QList<TagNode*>() );
+            for ( QList<TagNode>::iterator it = nodes.begin();
+                  it != nodes.end(); ++it ) {
+                TagNode& node = *it;
+                rows.first().append( &node );
+            }
+            if ( newTagButtonEnabled ) {
+                rows.first().append( &newTagNode );
+            }
 
-        // calculate the rows
-        QList<QList<TagNode*> > bestRows( rows );
-        QSize size( rowLength( rows.first() ), rowHeight( rows.first() ) );
-        QSize bestSize( size );
-        while ( ( size.height() < size.width() ||
-                  size.width() > contentsRect.width() ) &&
-                size.height() <= contentsRect.height() ) {
-            // find the longest row
-            int maxRow = 0;
-            int maxLen = 0;
-            for ( int i = 0; i < rows.count(); ++i ) {
-                int rowLen = rowLength( rows[i] );
-                if ( rowLen > maxLen ) {
-                    maxLen = rowLen;
-                    maxRow = i;
+            // calculate the rows
+            QList<QList<TagNode*> > bestRows( rows );
+            QSize size( rowLength( rows.first() ), rowHeight( rows.first() ) );
+            QSize bestSize( size );
+            while ( ( size.height() < size.width() ||
+                      size.width() > contentsRect.width() ) &&
+                    size.height() <= contentsRect.height() ) {
+                // find the longest row
+                int maxRow = 0;
+                int maxLen = 0;
+                for ( int i = 0; i < rows.count(); ++i ) {
+                    int rowLen = rowLength( rows[i] );
+                    if ( rowLen > maxLen ) {
+                        maxLen = rowLen;
+                        maxRow = i;
+                    }
                 }
-            }
 
-            // move the last item from the longest row to the next row
-            TagNode* node = rows[maxRow].takeLast();
-            if ( rows.count() <= maxRow+1 ) {
-                rows.append( QList<TagNode*>() );
-            }
-            rows[maxRow+1].prepend( node );
+                // move the last item from the longest row to the next row
+                TagNode* node = rows[maxRow].takeLast();
+                if ( rows.count() <= maxRow+1 ) {
+                    rows.append( QList<TagNode*>() );
+                }
+                rows[maxRow+1].prepend( node );
 
-            // update the size
-            size = cloudSize( rows );
+                // update the size
+                size = cloudSize( rows );
 
-            if ( size.width() < bestSize.width() &&
-                 ( size.width() > size.height()  ||
-                   bestSize.width() > contentsRect.width() ) &&
-                 size.height() <= contentsRect.height() ) {
-                bestSize = size;
-                bestRows = rows;
+                if ( size.width() < bestSize.width() &&
+                     ( size.width() > size.height()  ||
+                       bestSize.width() > contentsRect.width() ) &&
+                     size.height() <= contentsRect.height() ) {
+                    bestSize = size;
+                    bestRows = rows;
+                }
+            }
+            rows = bestRows;
+
+            // position the tags
+            int y = 0;
+            for ( QList<QList<TagNode*> >::iterator rowIt = rows.begin(); rowIt != rows.end(); ++rowIt ) {
+                QList<TagNode*>& row = *rowIt;
+                int h = rowHeight( row );
+                int x = 0;
+                Q_FOREACH( TagNode* node, row ) {
+                    node->rect.moveTop( y + ( h - node->rect.height() )/2 );
+                    node->rect.moveLeft( x );
+                    x += s_hSpacing + node->rect.width();
+                }
+                y += h + s_vSpacing;
             }
         }
-        rows = bestRows;
 
-        // position the tags
-        int y = 0;
-        for ( QList<QList<TagNode*> >::iterator rowIt = rows.begin(); rowIt != rows.end(); ++rowIt ) {
-            QList<TagNode*>& row = *rowIt;
-            int h = rowHeight( row );
-            int x = 0;
-            Q_FOREACH( TagNode* node, row ) {
-                node->rect.moveTop( y + ( h - node->rect.height() )/2 );
-                node->rect.moveLeft( x );
-                x += s_hSpacing + node->rect.width();
+
+        // let's see if we have to zoom
+        // ----------------------------------------------
+        zoomMatrix = QMatrix();
+        int w = contentsRect.width();
+        if ( zoomEnabled ) {
+            for ( QList<QList<TagNode*> >::iterator rowIt = rows.begin(); rowIt != rows.end(); ++rowIt ) {
+                QList<TagNode*>& row = *rowIt;
+                w = qMax( w, row.last()->rect.right() );
+            }
+            if ( w > contentsRect.width() ) {
+                double zoomFactor = ( double )contentsRect.width() / ( double )w;
+                zoomMatrix.scale( zoomFactor, zoomFactor );
             }
-            y += h + s_vSpacing;
         }
-    }
-
 
-    // let's see if we have to zoom
-    // ----------------------------------------------
-    zoomMatrix = QMatrix();
-    int w = contentsRect.width();
-    if ( zoomEnabled ) {
+        // force horizontal alignment
+        // ----------------------------------------------
         for ( QList<QList<TagNode*> >::iterator rowIt = rows.begin(); rowIt != rows.end(); ++rowIt ) {
             QList<TagNode*>& row = *rowIt;
-            w = qMax( w, row.last()->rect.right() );
-        }
-        if ( w > contentsRect.width() ) {
-            double zoomFactor = ( double )contentsRect.width() / ( double )w;
-            zoomMatrix.scale( zoomFactor, zoomFactor );
-        }
-    }
-
-    // force horizontal alignment
-    // ----------------------------------------------
-    for ( QList<QList<TagNode*> >::iterator rowIt = rows.begin(); rowIt != rows.end(); ++rowIt ) {
-        QList<TagNode*>& row = *rowIt;
-        int space = /*contentsRect.right()*/w - row.last()->rect.right();
-        if ( alignment & ( Qt::AlignRight|Qt::AlignHCenter ) ) {
-            Q_FOREACH( TagNode* node, row ) {
-                node->rect.moveLeft( node->rect.left() + ( alignment & Qt::AlignRight ? space : space/2 ) );
+            int space = /*contentsRect.right()*/w - row.last()->rect.right();
+            if ( alignment & ( Qt::AlignRight|Qt::AlignHCenter ) ) {
+                Q_FOREACH( TagNode* node, row ) {
+                    node->rect.moveLeft( node->rect.left() + ( alignment & Qt::AlignRight ? space : space/2 ) );
+                }
             }
-        }
-        else if ( alignment & Qt::AlignJustify && row.count() > 1 ) {
-            space /= ( row.count()-1 );
-            int i = 0;
-            Q_FOREACH( TagNode* node, row ) {
-                node->rect.moveLeft( node->rect.left() + ( space * i++ ) );
+            else if ( alignment & Qt::AlignJustify && row.count() > 1 ) {
+                space /= ( row.count()-1 );
+                int i = 0;
+                Q_FOREACH( TagNode* node, row ) {
+                    node->rect.moveLeft( node->rect.left() + ( space * i++ ) );
+                }
             }
         }
-    }
 
-    // force vertical alignment
-    // ----------------------------------------------
-    int verticalSpace = contentsRect.bottom() - rows.last().first()->rect.bottom();
-    if ( alignment & ( Qt::AlignBottom|Qt::AlignVCenter ) ) {
-        for ( QList<QList<TagNode*> >::iterator rowIt = rows.begin(); rowIt != rows.end(); ++rowIt ) {
-            Q_FOREACH( TagNode* node, *rowIt ) {
-                node->rect.moveTop( node->rect.top() + ( alignment & Qt::AlignBottom ? verticalSpace : verticalSpace/2 ) );
+        // force vertical alignment
+        // ----------------------------------------------
+        int verticalSpace = contentsRect.bottom() - rows.last().first()->rect.bottom();
+        if ( alignment & ( Qt::AlignBottom|Qt::AlignVCenter ) ) {
+            for ( QList<QList<TagNode*> >::iterator rowIt = rows.begin(); rowIt != rows.end(); ++rowIt ) {
+                Q_FOREACH( TagNode* node, *rowIt ) {
+                    node->rect.moveTop( node->rect.top() + ( alignment & Qt::AlignBottom ? verticalSpace : verticalSpace/2 ) );
+                }
             }
         }
-    }
 
-    for( QList<TagNode>::iterator it = nodes.begin(); it != nodes.end(); ++it ) {
-        it->zoomedRect = zoomMatrix.mapRect( it->rect );
+        for( QList<TagNode>::iterator it = nodes.begin(); it != nodes.end(); ++it ) {
+            it->zoomedRect = zoomMatrix.mapRect( it->rect );
+        }
+        newTagNode.zoomedRect = zoomMatrix.mapRect( newTagNode.rect );
     }
-    newTagNode.zoomedRect = zoomMatrix.mapRect( newTagNode.rect );
 
     m_parent->updateGeometry();
     m_parent->update();
@@ -466,7 +464,8 @@ void Nepomuk::TagCloud::Private::rebuildCloud()
 // binary search in row
 TagNode* Nepomuk::TagCloud::Private::findTagInRow( const QList<TagNode*>& row, const QPoint& pos )
 {
-    int x = row.count() * pos.x() / m_parent->width();
+    int x = m_parent->width() ? row.count() * pos.x() / m_parent->width() : 0;
+
     int i = 0;
     while ( 1 ) {
         if ( x-i >= 0 && x-i < row.count() && row[x-i]->zoomedRect.contains( pos ) ) {
@@ -487,7 +486,7 @@ TagNode* Nepomuk::TagCloud::Private::findTagInRow( const QList<TagNode*>& row, c
 // binary search in cloud
 TagNode* Nepomuk::TagCloud::Private::tagAt( const QPoint& pos )
 {
-    int y = rows.count() * pos.y() / m_parent->height();
+    int y = m_parent->height() ? rows.count() * pos.y() / m_parent->height() : 0;
 
     int i = 0;
     while ( 1 ) {
@@ -613,6 +612,7 @@ void Nepomuk::TagCloud::setZoomEnabled( bool zoom )
 
 void Nepomuk::TagCloud::setContextMenuEnabled( bool enabled )
 {
+    Q_UNUSED(enabled);
 }
 
 
@@ -651,7 +651,7 @@ void Nepomuk::TagCloud::showTags( const QList<Tag>& tags )
     d->showAllTags = false;
     d->invalidateCachedValues();
     d->nodes.clear();
-    Q_FOREACH( Tag tag, tags ) {
+    Q_FOREACH( const Tag &tag, tags ) {
         TagNode node;
         node.tag = tag;
         node.weight = d->calculateWeight( tag );
@@ -732,10 +732,11 @@ QSize Nepomuk::TagCloud::sizeHint() const
 
 QSize Nepomuk::TagCloud::minimumSizeHint() const
 {
+    return QFrame::minimumSizeHint();
     // If we have tags d->rebuildCloud() has been called at least once,
     // thus, we have proper rects (i.e. needed sizes)
     if ( d->nodes.isEmpty() && !d->newTagButtonEnabled ) {
-        return QSize( fontMetrics().width( i18n( "No Tags" ) ), fontMetrics().height() );
+        return QSize( fontMetrics().width( i18nc( "@label Indicator when no tags defined", "No Tags" ) ), fontMetrics().height() );
     }
     else {
         QSize size;
@@ -778,6 +779,7 @@ int Nepomuk::TagCloud::heightForWidth( int contentsWidth ) const
         bool newRow = true;
         int rowW = 0;
         int rowH = 0;
+        int maxW = 0;
         for ( int i = 0; i < allNodes.count(); ++i ) {
             int w = rowW;
             if ( !newRow ) {
@@ -797,6 +799,7 @@ int Nepomuk::TagCloud::heightForWidth( int contentsWidth ) const
                 rowH = allNodes[i]->rect.height();
                 rowW = allNodes[i]->rect.width();
             }
+            maxW = qMax( maxW, rowW );
         }
         if ( rowH > 0 ) {
             h += s_vSpacing + rowH;
@@ -804,6 +807,11 @@ int Nepomuk::TagCloud::heightForWidth( int contentsWidth ) const
 
         d->cachedHfwWidth = contentsWidth;
         d->cachedHfwHeight = h;
+
+        // zooming
+        if ( maxW > contentsWidth ) {
+            d->cachedHfwHeight = d->cachedHfwHeight * contentsWidth / maxW;
+        }
     }
 
     return d->cachedHfwHeight + frameWidth()*2;
@@ -829,46 +837,41 @@ void Nepomuk::TagCloud::paintEvent( QPaintEvent* e )
     QPainter p( this );
     QRegion paintRegion = e->region();
 
-    if ( d->nodes.isEmpty() && !d->newTagButtonEnabled ) {
-        p.drawText( contentsRect(), d->alignment, i18n( "No Tags" ) );
-    }
-    else {
-        p.save();
-        p.setMatrix( d->zoomMatrix );
+    p.save();
+    p.setMatrix( d->zoomMatrix );
 
-        for ( QList<TagNode>::iterator it = d->nodes.begin();
-              it != d->nodes.end(); ++it ) {
-            TagNode& node = *it;
-
-            if ( paintRegion.contains( node.zoomedRect ) ) {
-                p.setFont( node.font );
+    for ( QList<TagNode>::iterator it = d->nodes.begin();
+          it != d->nodes.end(); ++it ) {
+        TagNode& node = *it;
 
-                if ( &node == d->hoverTag ) {
-                    p.setPen( hoverTextBrush.brush( this ).color() );
-                }
-                else if ( d->selectionEnabled && node.selected ) {
-                    p.setPen( activeTextBrush.brush( this ).color() );
-                }
-                else {
-                    p.setPen( normalTextBrush.brush( this ).color() );
-                }
-                p.drawText( node.rect, Qt::AlignCenter, node.text );
-            }
-        }
+        if ( paintRegion.contains( node.zoomedRect ) ) {
+            p.setFont( node.font );
 
-        if ( d->newTagButtonEnabled ) {
-            p.setFont( d->newTagNode.font );
-            if ( &d->newTagNode == d->hoverTag ) {
+            if ( &node == d->hoverTag ) {
                 p.setPen( hoverTextBrush.brush( this ).color() );
             }
+            else if ( d->selectionEnabled && node.selected ) {
+                p.setPen( activeTextBrush.brush( this ).color() );
+            }
             else {
                 p.setPen( normalTextBrush.brush( this ).color() );
             }
-            p.drawText( d->newTagNode.rect, Qt::AlignCenter, d->customNewTagAction ? d->customNewTagAction->text() : d->newTagNode.text );
+            p.drawText( node.rect, Qt::AlignCenter, node.text );
         }
+    }
 
-        p.restore();
+    if ( d->newTagButtonEnabled ) {
+        p.setFont( d->newTagNode.font );
+        if ( &d->newTagNode == d->hoverTag ) {
+            p.setPen( hoverTextBrush.brush( this ).color() );
+        }
+        else {
+            p.setPen( normalTextBrush.brush( this ).color() );
+        }
+        p.drawText( d->newTagNode.rect, Qt::AlignCenter, d->customNewTagAction ? d->customNewTagAction->text() : d->newTagNode.text );
     }
+
+    p.restore();
 }