⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qmmainwindow.cpp

📁 可以播放MP3,wma等文件格式的播放器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* qmmainwindow.cpp * * $Id: qmmainwindow.cpp,v 1.209.2.1 2002/09/23 19:26:51 kyllingstad Exp $ * * Apollo sound player: http://www.apolloplayer.org * Copyright(C) 2000-2002 Apollo Team.  See CREDITS file. * * 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; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. * * The GNU General Public License is also available online at: * * http://www.gnu.org/copyleft/gpl.html */#include "qmmainwindow.h"#include "message.h"#include "qmaccelmanager.h"#include "qmbrowser.h"#include "qmconfig.h"#include "qmcontrolbar.h"#include "qmmarkdialog.h"#include "qmmarkmanager.h"#include "qmminibuffer.h"#include "qmnullplayer.h"#include "qmpixmapsupplier.h"#include "qmplayfirst.h"#include "qmplaylist.h"#include "qmpositionbar.h"#include "qmremotecontrol.h"#include "qmrecoverymanager.h"#include "qmsongitem.h"#include "qmstatusbar.h"#include "qmvolumebar.h"#include "qmsystray.h"#include "version.h"#ifdef ENABLE_MPG123#include "qmmpg123player.h"#endif // ENABLE_MPG123#ifdef ENABLE_MAD#include "qmmadplayer.h"#endif // ENABLE_MAD#ifdef ENABLE_XMP#include "qmxmpplayer.h"#endif // ENABLE_XMP#include <iostream>#include <time.h>#include <cassert>#include <qaccel.h>#include <qapplication.h>#include <qdir.h>#include <qfile.h>#include <qfileinfo.h>#include <qfont.h>#include <qheader.h>#include <qlayout.h>#include <qlineedit.h>#include <qlistview.h>#include <qmainwindow.h>#include <qmessagebox.h>#include <qpixmap.h>#include <qsplitter.h>#include <qstatusbar.h>#include <qwidgetstack.h>#include <qtextview.h>#include <qpalette.h>/* Disables false warning in Visual Studio about dynamic_cast */#ifdef _WS_WIN_#pragma warning(disable: 4541)#endif/*!  \file qmmainwindow.cpp  The main Apollo window - control center for the whole app. *//*!  \class QmMainWindow qmmainwindow.h  \brief The main Apollo window - control center for the whole app.  The main window is where it's all at.  Most communication within apollo  goes through QmMainWindow, providing loose coupling among the different  parts.*/const bool QmMainWindow::debug;const unsigned int QmMainWindow::MESSAGE_LOG_SIZE;/*!  Constructs a new Apollo main window.*/QmMainWindow::QmMainWindow(    QWidget *parent,    const char *name)    : QMainWindow(parent, name),      m_pPlayer(0),      m_ContinueHerep(false),      m_pContinueHere(0),      m_ContinuePlayList(""),      m_ContinueSong(""),	  m_State( QmMainWindow::Ready ),	  m_PlayState( QmMainWindow::Stopped ),	  m_StopClicked( false ),      m_Randomp( false ),	  m_Loopp( false ),	  m_pMarkDialog(0),	  m_Position( QmMainWindow::LeftBrowser ){    setCaption("Apollo");	assert(mainwin == 0);     mainwin = this;	// needs to get initialized before any status messages are emitted ...	m_pMiniBuffer = new QmMiniBuffer(this);	m_pMiniBuffer->setHorizontalStretchable(true);    QmConfig *conf = QmConfig::instance();    conf->load();//    qDebug( "Pos: j" );	QFont font;    if ( conf->has( "font", "name" ) )    {        QString fontname = conf->getString( "font", "name" );        if (!fontname.isEmpty())            font.setFamily(fontname);    }    if ( conf->has( "font", "size" ) )    {        int size = conf->getInt( "font", "size" );        if (size)            font.setPointSize(size);    }    if ( conf->has( "font", "weight" ) )    {        int weight = conf->getInt( "font", "weight" );        if (weight)            font.setWeight(weight);    }    if ( conf->has( "font", "italic" ) )    {        bool italic;        conf->get( "font", "italic", italic );        font.setItalic(italic);    }//    qDebug( "Pos: k" );	qApp->setFont(font, true);	QmAccelManager::instance();		startPlayer();	    QmPixmapSupplier *sup = QmPixmapSupplier::instance();    setIcon( sup->pixmap( "icons-apollo-mini" ) );    resize( conf->getRect( "main-window", "geometry" ).size() );    move( conf->getRect( "main-window", "geometry" ).topLeft() );    m_pControlBar = new QmControlBar(this, "control-bar");	addToolBar(m_pControlBar);	    m_pStatusBar = new QmStatusBar(this, m_pPlayer);	addToolBar(m_pStatusBar, Top, true); 	m_pListBrowserSplitter = new QSplitter(this);    	m_pBrowser = new QmBrowser(this, m_pListBrowserSplitter);	// The use of layout below is somewhat unusual, but perfectly legal and	// given as an example in the Qt documentation (Layout overview documentation).	// We want a 1 pixel border around the playlist, and the only practical way I	// know how to do that is by using a layout and set spacing in it.  The problem	// is that we have a splitter which needs to be the parent.  A layout is not	// a widget, but letting the splitter be the parent of both the layout and the	// the playlist doesn't work (very well).	//	// The solution is as given below.	//	// Note that the holder, m_pHolder, is now the widget connected to the splitter	// and it is this widget that needs to be moved with the splitter functions.    // update: there is now two holders connected to a splitter connected to the    // splitter.    m_pListsSplitter = new QSplitter(m_pListBrowserSplitter);    m_pListsSplitter->setOrientation(Vertical);    m_pPlayFirstHolder = new QWidget(m_pListsSplitter);    m_pPlayFirst = new QmPlayFirst(m_pPlayFirstHolder, "PlayFirst");	m_pPlayFirst->initMenu();    m_pPlayFirst->addColumn(tr("PlayFirst: play these before going on"), 300);    m_pPlayFirst->addColumn(tr("Length"), 50);    m_pPlayFirst->setColumnAlignment(1, AlignRight);    m_pPlayFirst->setColumnWidthMode(1, QListView::Maximum);    m_pPlayFirst->setAllColumnsShowFocus(true); 	m_pPlayFirst->setRootIsDecorated(false);    m_pPlayFirst->setItemMargin(3); 	m_pPlayFirst->setSorting(-1);	QPalette pfp(QColor(238, 232, 170)); // pale golden rod (maybe it should be colorGroup().base())	pfp.setColor(QColorGroup::Base, colorGroup().background());	m_pPlayFirst->setPalette(pfp);	QVBoxLayout *templayout = new QVBoxLayout(m_pPlayFirstHolder, 1);	templayout->addWidget(m_pPlayFirst);    m_pPlayFirstHolder->hide();	    m_pPlayListHolder = new QWidget(m_pListsSplitter);     m_pPlayList = new QmPlayList( m_pPlayListHolder, "playlist" );	m_pPlayList->initMenu();    connect(m_pMiniBuffer, SIGNAL(search(const QString&)), m_pPlayList, SLOT(search(const QString&)));    	m_pPlayList->enableSelfSave(QmConfig::instance()->configPath() + "playlist.xml");    m_pPlayList->addColumn(tr("Name"), 300);    m_pPlayList->addColumn(tr("Length"), 50);    m_pPlayList->setColumnAlignment(1, AlignRight);    m_pPlayList->setColumnWidthMode(1, QListView::Maximum);    m_pPlayList->setAllColumnsShowFocus(true);	m_pPlayList->setRootIsDecorated(false);    m_pPlayList->setItemMargin(3);	m_pPlayList->setSorting(-1);	templayout = new QVBoxLayout(m_pPlayListHolder, 1);	templayout->addWidget(m_pPlayList);    QValueList<int> widths;    widths.append( conf->getInt( "main-window", "browser-width" ) );    widths.append( conf->getInt( "main-window", "playlist-width" ) );    m_pListBrowserSplitter->setSizes( widths );    	setCentralWidget(m_pListBrowserSplitter);    connect(m_pPlayList, SIGNAL(doubleClicked(QListViewItem*)),			this, SLOT(selected(QListViewItem*)));    connect(m_pPlayList, SIGNAL(returnPressed(QListViewItem*)),			this, SLOT(selected(QListViewItem*)));    connect(m_pPlayList, SIGNAL(currentChanged(QListViewItem*)),			this, SLOT(current(QListViewItem*)));// rk: why commented out?//    connect(m_pPlayList, SIGNAL(statusUpdate(const QString &)),//            this, SLOT(statusUpdate(const QString &)));    connect(m_pPlayer, SIGNAL(secondsCount(int)), this, SLOT(updateSongLength(int)));    connect(m_pPlayer, SIGNAL(bitrate(int)), this, SLOT(updateBitrate(int)));    m_pPositionBar = new QmPositionBar(this, m_pStatusBar, m_pPlayer);	addToolBar(m_pPositionBar, Bottom);	m_pVolumeBar = new QmVolumeBar(this, m_pStatusBar);	addToolBar(m_pVolumeBar, Bottom);	QObject::connect(QmMarkManager::instance(), SIGNAL(songRemoved()), this, SLOT(updateItems()));	    m_pVolumeBar->updateVolume( false );    m_pControlBar->updateWidgets();    m_pControlBar->updateControls();    m_pPlayList->setFocus();    m_pStatusBar->showMessage( tr( "Welcome to Apollo!" ) );	int browser_position;	conf->get("main-window", "browser-position", browser_position);	setBrowserPosition(static_cast<QmMainWindow::BrowserPosition>(browser_position));		int show_browser;	conf->get("main-window", "show-browser", show_browser);	if (show_browser == 0)		hideBrowser();	else		showBrowser();    widths.clear();    widths.append( conf->getInt( "main-window", "playfirst-height" ) );    widths.append( conf->getInt( "main-window", "playlist-height" ) );    m_pListsSplitter->setSizes( widths );	int full_browser;	conf->get("main-window", "full-browser", full_browser);	if (full_browser == 0) 		m_pListsSplitter->show();	else		m_pListsSplitter->hide();	// rk: delayed to get it at the bottom - is there a better way?	addToolBar(m_pMiniBuffer, Bottom, true);    QAccel *accel = new QAccel(this);    accel->connectItem(accel->insertItem(CTRL + Key_F),                       m_pMiniBuffer,                       SLOT(activateSearch()));	m_pRemoteControl = new QmRemoteControl();	if (!m_pRemoteControl->setup_ctrlsocket())		statusUpdate(new Message(Message::Error, "Remote control start failed"));// 	if(full_browser == 0)// 		m_pHolder->show();// 	else// 		m_pHolder->hide();	m_pPlayerMessage = new QTextView;	m_pPlayerMessage->setCaption(tr("Apollo - Player messages"));}/*!  Destructs the main window.  Window position, size etc. will be  saved.*/QmMainWindow::~QmMainWindow(){    saveState();	delete m_pPlayer;    QmConfig::instance()->save();    for(std::deque<Message*>::iterator it = m_Messages.begin(); it != m_Messages.end(); it++)    {        delete *it;    }}/*!  Access point to the main window.  \todo Replace with instance() (singleton pattern); consistent with the   rest of the code.  rk: IMHO the singleton pattern as described in the   gang of four book doesn't apply, or rather none of the benefits apply,   it only makes the code look uglier.  Without it there is nothing.*/QmMainWindow *QmMainWindow::mainwin = 0;/*!  Adds a directory, mp3 or playlist to the playlist  If it's a mp3 and \a playFirst is true, it adds it to playfirst as well.    \return true iff successful*/boolQmMainWindow::playListAdd(    const QString &filename,    bool playFirst){	QFileInfo info(filename);	if (!info.exists())		return false;		if (info.isDir())		m_pPlayList->appendDir(filename);	else if (info.isFile())	{		if (info.extension(false).lower() == "mp3") {			m_pPlayList->appendSong(filename);			if (playFirst)				m_pPlayFirst->append(filename);		}		else			m_pPlayList->appendList(filename);	}	else		return false;	return true;}/*!  Appends directory (path) \a filename to the play list*/voidQmMainWindow::playListAppendDir(    const QString &filename){    m_pPlayList->appendDir(filename);    m_pControlBar->updateControls();	}/*!  Adds directory (path) \a filename to the beginning of the play list */voidQmMainWindow::playListPrependDir(    const QString &filename){    m_pPlayList->prependDir(filename);    m_pControlBar->updateControls(); }/*!  Appends a song to the play list */voidQmMainWindow::playListAppendFile(    const QString &filename){	m_pPlayList->appendSong(filename);    m_pControlBar->updateControls(); }/*!  Appends playlist file (path) \a filename to the play list*/voidQmMainWindow::playListAppendList(    const QString &filename){    m_pPlayList->appendList(filename);	m_pControlBar->updateControls();}/*!  Prepends play list file (path) \a filename to the play list */voidQmMainWindow::playListPrependList(    const QString &filename){    m_pPlayList->prependList(filename);	m_pControlBar->updateControls();}/*!  \bug should put in event queue if Busy:*/voidQmMainWindow::addFilesDialog(){	m_pControlBar->addFiles(); }voidQmMainWindow::configDialog(){	m_pControlBar->openConfigDialog();}voidQmMainWindow::toggleCompactWindow(){	m_pControlBar->toggleCompactWindow();}voidQmMainWindow::showAbout(){	m_pControlBar->about();}/*!  Saves playlist, as m3u if the names ends with ".m3u", else in apollo format.*/voidQmMainWindow::savePlayList(    const QString &filename){    if (filename.findRev(".m3u", -1, false) == static_cast<int>(filename.length()) - 4)        m_pPlayList->saveAsM3u(filename);	else		m_pPlayList->saveAsXml(filename); }/*!  \return wheter the play list is empty */boolQmMainWindow::playListIsEmpty() const{    return m_pPlayList->isEmpty();}/*!  \return a pointer to the QmSongItem of the currently playing song*/QmSongItem*QmMainWindow::playingSong() {    return m_pPlayList->currentSong();}/*!  \return a pointer to the QmSongItem for the song at position \a index in  the currently active playlist, as counted by a depth-first traversal of  non-bad songs. */QmSongItem*QmMainWindow::song(    int index){	return activePlayList()->song(index);}/*!  \return wheter the play list is at the last position.  Undefined for empty play lists.*/boolQmMainWindow::playListAtEnd() const{    return m_pPlayList->atEnd();}/*!  \return wheter the play list is at the first position.  Undefined for empty play lists.*/boolQmMainWindow::playListAtBeginning() const{    return m_pPlayList->atBeginning();}/*!  Updates the playlist widget, used to toggle packed mode.  \todo Find proper way.*/voidQmMainWindow::updatePlayList() const{// m_pPlayList->reconfigureItems(); m_pPlayFirst->reconfigureItems();/*! \todo find the proper way to do this. */    m_pPlayList->setFont(m_pPlayList->font());    m_pPlayFirst->setFont(m_pPlayFirst->font());}/*!  Update status message with msg (currently just display in bottom status bar)  \todo implement show-message-log (dump to a text area widget for example).*/voidQmMainWindow::statusUpdate(    Message *msg){	if(msg == 0)		m_pMiniBuffer->clear();    else    {		if (msg->type() != Message::Update)		{			m_Messages.push_back(msg);			if (m_Messages.size() > MESSAGE_LOG_SIZE)			{				delete m_Messages.front();				m_Messages.pop_front();			}		}		m_pMiniBuffer->message(msg->message());		qApp->processEvents();	}}/*!  \todo rk: this is bogus: PlayFirst is hidden when it's playing the last song.  and visible when it's not yet played a song*/QmPlayList*QmMainWindow::activePlayList(){	// m_pPlayFirst->isEmpty() is no good eihter	return m_pPlayFirstHolder->isVisible() ? m_pPlayFirst : m_pPlayList;}/*!  Does what's needed to ContinueHere - just shared code between play() and next()  \return whether it was successful*/boolQmMainWindow::tryContinueHere(){	m_ContinueHerep = false;	m_pContinueHere = dynamic_cast<QmSongItem*>(m_pContinueHere);	bool ret = true;	if (m_pContinueHere)		selected(m_pContinueHere, m_pPlayList);	else	{		/*! \todo make this configurable */		m_pPlayList->clear();		m_pPlayList->appendList(m_ContinuePlayList);		if ((m_pContinueHere = m_pPlayList->findSong(m_ContinueSong)))			selected(m_pContinueHere, m_pPlayList);		else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -