statistics.cpp
来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 1,049 行 · 第 1/3 页
CPP
1,049 行
/*************************************************************************** * copyright : (C) 2005-2006 Seb Ruiz <me@sebruiz.net> * **************************************************************************//*************************************************************************** * * * 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. * * * ***************************************************************************/#include "amarok.h" //foreach macro#include "browserToolBar.h" //search toolbar#include "clicklineedit.h"#include "collectiondb.h"#include "debug.h"#include "playlist.h"#include "statistics.h"#include "tagdialog.h" //showContextMenu()#include <kapplication.h>#include <kdeversion.h> //KDE_VERSION ifndefs. Remove this once we reach a kde 4 dep#include <kiconloader.h>#include <klocale.h>#include <kmultipledrag.h> //startDrag()#include <kpopupmenu.h>#include <kstringhandler.h> //paintCell#include <ktoolbarbutton.h> //ctor#include <kurldrag.h> //startDrag()#include <kwin.h>#include <qcolor.h>#include <qdatetime.h>#include <qheader.h>#include <qpainter.h>#include <qpen.h>#include <qpixmap.h>#include <qsimplerichtext.h>#include <qtimer.h>#include <qtooltip.h>#include <qvbox.h>///////////////////////////////////////////////////////////////////////////////////////////// CLASS Statistics//////////////////////////////////////////////////////////////////////////////////////////Statistics *Statistics::s_instance = 0;Statistics::Statistics( QWidget *parent, const char *name ) : KDialogBase( KDialogBase::Swallow, 0, parent, name, false, 0, Close ) , m_timer( new QTimer( this ) ){ s_instance = this; // Gives the window a small title bar, and skips a taskbar entry KWin::setType( winId(), NET::Utility ); KWin::setState( winId(), NET::SkipTaskbar ); kapp->setTopWidget( this ); setCaption( kapp->makeStdCaption( i18n("Collection Statistics") ) ); setInitialSize( QSize( 400, 550 ) ); QVBox *mainBox = new QVBox( this ); setMainWidget( mainBox ); QVBox *box = new QVBox( mainWidget() ); box->setSpacing( 5 ); { //<Search LineEdit> KToolBar *bar = new Browser::ToolBar( box ); bar->setIconSize( 22, false ); //looks more sensible bar->setFlat( true ); //removes the ugly frame bar->setMovingEnabled( false ); //removes the ugly frame QWidget *button = new KToolBarButton( "locationbar_erase", 1, bar ); m_lineEdit = new ClickLineEdit( i18n( "Enter search terms here" ), bar ); bar->setStretchableWidget( m_lineEdit ); m_lineEdit->setFrame( QFrame::Sunken ); m_lineEdit->installEventFilter( this ); //we intercept keyEvents connect( button, SIGNAL( clicked() ) , m_lineEdit , SLOT( clear() ) ); connect( m_timer, SIGNAL( timeout() ) , SLOT( slotSetFilter() ) ); connect( m_lineEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotSetFilterTimeout() ) ); connect( m_lineEdit, SIGNAL( returnPressed() ) , SLOT( slotSetFilter() ) ); QToolTip::add( button, i18n( "Clear search field" ) ); } //</Search LineEdit> m_listView = new StatisticsList( box );}Statistics::~Statistics(){ s_instance = 0;}voidStatistics::slotSetFilterTimeout() //SLOT{ m_timer->start( 280, true ); //stops the timer for us first}voidStatistics::slotSetFilter() //SLOT{ m_timer->stop(); m_listView->setFilter( m_lineEdit->text() ); if( m_listView->childCount() > 1 ) m_listView->renderView(); else m_listView->refreshView();}///////////////////////////////////////////////////////////////////////////////////////////// CLASS StatisticsList//////////////////////////////////////////////////////////////////////////////////////////StatisticsList::StatisticsList( QWidget *parent, const char *name ) : KListView( parent, name ) , m_currentItem( 0 ) , m_expanded( false ){ header()->hide(); addColumn( i18n("Name") ); setResizeMode( QListView::LastColumn ); setSelectionMode( QListView::Extended ); setSorting( -1 ); setAcceptDrops( false ); setDragEnabled( true ); connect( this, SIGNAL( onItem( QListViewItem*) ), SLOT( startHover( QListViewItem* ) ) ); connect( this, SIGNAL( onViewport() ), SLOT( clearHover() ) ); connect( this, SIGNAL( clicked( QListViewItem*) ), SLOT( itemClicked( QListViewItem* ) ) ); connect( this, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint &, int ) ), this, SLOT( showContextMenu( QListViewItem *, const QPoint &, int ) ) ); if( CollectionDB::instance()->isEmpty() ) return; renderView();}voidStatisticsList::startDrag(){ // there is only one item ever selected in this tool. maybe this needs to change DEBUG_FUNC_INFO KURL::List list; KMultipleDrag *drag = new KMultipleDrag( this ); QListViewItemIterator it( this, QListViewItemIterator::Selected ); StatisticsDetailedItem *item = dynamic_cast<StatisticsDetailedItem*>(*it); if ( !item ) return; if( item->itemType() == StatisticsDetailedItem::TRACK ) { list += KURL::fromPathOrURL( item->url() ); drag->addDragObject( new KURLDrag( list, viewport() ) ); drag->setPixmap( CollectionDB::createDragPixmap(list), QPoint( CollectionDB::DRAGPIXMAP_OFFSET_X, CollectionDB::DRAGPIXMAP_OFFSET_Y ) ); } else { QTextDrag *textdrag = new QTextDrag( '\n' + item->getSQL(), 0 ); textdrag->setSubtype( "amarok-sql" ); drag->addDragObject( textdrag ); drag->setPixmap( CollectionDB::createDragPixmapFromSQL( item->getSQL() ), QPoint( CollectionDB::DRAGPIXMAP_OFFSET_X, CollectionDB::DRAGPIXMAP_OFFSET_Y ) ); } clearSelection(); drag->dragCopy();}voidStatisticsList::refreshView(){ if( m_expanded ) { if( !firstChild() ) { error() << "Statistics: uh oh, no first child!" << endl; return; } while( firstChild()->firstChild() ) delete firstChild()->firstChild(); expandInformation( static_cast<StatisticsItem*>(firstChild()), true /*refresh*/ ); } else renderView();}voidStatisticsList::renderView(){ m_expanded = false; //ensure cleanliness - this function is not just called from the ctor, but also when returning to the initial display while( firstChild() ) delete firstChild(); m_currentItem = 0; QueryBuilder qb; QStringList a; qb.clear(); qb.addReturnFunctionValue( QueryBuilder::funcCount, QueryBuilder::tabSong, QueryBuilder::valURL ); qb.setOptions( QueryBuilder::optRemoveDuplicates ); a = qb.run(); m_trackItem = new StatisticsItem( i18n("Favorite Tracks"), this, 0 ); m_trackItem->setSubtext( i18n("%n track", "%n tracks", a[0].toInt()) ); qb.clear(); qb.addReturnFunctionValue( QueryBuilder::funcSum, QueryBuilder::tabStats, QueryBuilder::valPlayCounter ); a = qb.run(); m_mostplayedItem = new StatisticsItem( i18n("Most Played Tracks"), this, m_trackItem ); m_mostplayedItem->setSubtext( i18n("%n play", "%n plays", a[0].toInt()) ); qb.clear(); //qb.addReturnFunctionValue( QueryBuilder::funcCount, QueryBuilder::tabArtist, QueryBuilder::valID ); //qb.setOptions( QueryBuilder::optRemoveDuplicates ); //a = qb.run(); qb.setOptions( QueryBuilder::optRemoveDuplicates ); qb.addReturnValue( QueryBuilder::tabSong, QueryBuilder::valArtistID ); //I can't get the correct value w/o using a subquery, and querybuilder doesn't support those a = QString::number( qb.run().count() ); m_artistItem = new StatisticsItem( i18n("Favorite Artists"), this, m_mostplayedItem ); m_artistItem->setSubtext( i18n("%n artist", "%n artists", a[0].toInt()) ); qb.clear(); //qb.addReturnFunctionValue( QueryBuilder::funcCount, QueryBuilder::tabAlbum, QueryBuilder::valID ); //qb.setOptions( QueryBuilder::optRemoveDuplicates ); //a = qb.run(); qb.setOptions( QueryBuilder::optRemoveDuplicates ); qb.addReturnValue( QueryBuilder::tabSong, QueryBuilder::valAlbumID ); //I can't get the correct value w/o using a subquery, and querybuilder doesn't support those a = QString::number( qb.run().count() ); m_albumItem = new StatisticsItem( i18n("Favorite Albums"), this, m_artistItem ); m_albumItem->setSubtext( i18n("%n album", "%n albums", a[0].toInt()) ); qb.clear(); //qb.addReturnFunctionValue( QueryBuilder::funcCount, QueryBuilder::tabGenre, QueryBuilder::valID ); //qb.setOptions( QueryBuilder::optRemoveDuplicates ); //a = qb.run(); qb.setOptions( QueryBuilder::optRemoveDuplicates ); qb.addReturnValue( QueryBuilder::tabSong, QueryBuilder::valGenreID ); //I can't get the correct value w/o using a subquery, and querybuilder doesn't support those a = QString::number( qb.run().count() ); m_genreItem = new StatisticsItem( i18n("Favorite Genres"), this, m_albumItem ); m_genreItem->setSubtext( i18n("%n genre", "%n genres", a[0].toInt()) ); qb.clear(); qb.addReturnFunctionValue( QueryBuilder::funcMin, QueryBuilder::tabStats, QueryBuilder::valCreateDate ); qb.setOptions( QueryBuilder::optRemoveDuplicates ); a = qb.run(); QDateTime firstPlay = QDateTime::currentDateTime(); if ( a[0].toUInt() ) firstPlay.setTime_t( a[0].toUInt() ); m_newestItem = new StatisticsItem( i18n("Newest Items"), this, m_genreItem ); m_newestItem->setSubtext( i18n("First played %1").arg( Amarok::verboseTimeSince( firstPlay ) ) ); m_trackItem ->setIcon( Amarok::icon("track") ); m_mostplayedItem->setIcon( Amarok::icon("mostplayed") ); m_artistItem ->setIcon( Amarok::icon("artist") ); m_albumItem ->setIcon( Amarok::icon("album") ); m_genreItem ->setIcon( Amarok::icon("favourite_genres") ); m_newestItem ->setIcon( Amarok::icon("clock") );}voidStatisticsList::itemClicked( QListViewItem *item ) //SLOT{ if( !item ) return; if( item->depth() != 0 ) //not very flexible, *shrug* return; #define item static_cast<StatisticsItem*>(item) if( item->isExpanded() ) { renderView(); return; } expandInformation( item ); item->setOpen( true ); #undef item}voidStatisticsList::expandInformation( StatisticsItem *item, bool refresh ){ m_expanded = true; KLocale *locale = new KLocale( "locale" ); QueryBuilder qb; StatisticsDetailedItem *m_last = 0; uint c = 1; if( item == m_trackItem ) { if( !refresh ) { delete m_newestItem; delete m_genreItem; delete m_albumItem; delete m_artistItem; delete m_mostplayedItem; } qb.addReturnValue( QueryBuilder::tabSong, QueryBuilder::valTitle ); qb.addReturnValue( QueryBuilder::tabArtist, QueryBuilder::valName ); qb.addReturnValue( QueryBuilder::tabSong, QueryBuilder::valURL ); qb.addReturnValue( QueryBuilder::tabStats, QueryBuilder::valScore ); qb.addReturnValue( QueryBuilder::tabStats, QueryBuilder::valRating ); qb.addNumericFilter( QueryBuilder::tabStats, QueryBuilder::valForFavoriteSorting(), "0", QueryBuilder::modeGreater ); qb.setGoogleFilter( QueryBuilder::tabSong | QueryBuilder::tabArtist, m_filter ); qb.sortByFavorite(); qb.setLimit( 0, 50 ); QStringList fave = qb.run(); for( uint i=0; i < fave.count(); i += qb.countReturnValues() ) { QString name = i18n("%1. %2 - %3").arg( QString::number(c), fave[i].isEmpty() ? i18n( "Unknown" ) : fave[i], fave[i+1].isEmpty() ? i18n( "Unknown" ) : fave[i+1]); QString score = locale->formatNumber( fave[i+3].toDouble(), 0 );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?