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

📄 qmlistview.cpp

📁 可以播放MP3,wma等文件格式的播放器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* qmlistview.cpp * * $Id: qmlistview.cpp,v 1.46.2.3 2002/10/11 06:39:03 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 "qmlistview.h"#include "qmlistviewitem.h"#include "qmmainwindow.h"#include "message.h"#include <iostream>#include <qdom.h>#include <qdragobject.h>#include <qheader.h>#include <qpoint.h>#include <qtextstream.h>#include <qtimer.h>#include "qmdropindicator.h"#include "qmdiritem.h"/* Disables false warning in Visual Studio about dynamic_cast */#ifdef _WS_WIN_#pragma warning(disable: 4541)#endif/*!  \file qmlistview.cpp  Enhanced list view with drag'n drop support.*//*!  \class QmListView qmlistview.h  \brief Enhanced list view with drag'n drop support.  This class is an extension to QListView.  It adds features to QListView  that can be useful to list views, such as reorganizability.  With this class,  the user can rearrange the order of the items through drag'n drop operations.  This class supports persistent storage.  By calling save(), the listview will  be written in XML form.  If you plan to use the class for persistent storage,  you should give the object a name!  The name of the object will be included in  the XML output.  If the name is 'foo', the output will be as follows:  \verbatim  <apollo-foo>  ...  </apollo-foo>  \endverbatim  In order for the save functionality to work, all items in the listview must  either be QmListViewItem objects.  \sa QmDropIndicator, QmListViewItem*//*!  Creates a new listview.  \a parent and \a name is passed to the QListView  constructor.*/QmListView::QmListView(    QWidget *parent,    const char *name)	: QListView(parent, name),	  m_Reorganizable(false){	m_pDropIndicator = new QmDropIndicator(viewport());	m_pDropIndicator->hide();    m_pScrollTimer = new QTimer( this, "ScrollTimer" );    connect( m_pScrollTimer, SIGNAL( timeout() ),             this, SLOT( slotScrollView() ) );}QmListView::~QmListView() {}/*!  This function will find the listview item at the position \a pos.  The header will be taken into account (unlike QListView::itemAt()).    \return The item at \a pos, or null if none.*/QListViewItem*QmListView::at(	const QPoint &pos) const{	int xpos = pos.x();	int ypos = pos.y() - header()->height() - itemMargin();	return itemAt( QPoint(xpos, ypos) );}/*!  Calculates the position (upper left corner) the drop indicator should have  according to the mouse position \a pos.  The y position is calculated like this:  If the mouse is over the upper half of an item, the position calculated will  be in between the item above and the one the mouse is over.  If the mouse is  over the lower half of an item, the position calculated will be in between  the item below and the one the mouse is over.  The x position is calculated like this:  The depth of the item will indicate the x position.  This will make the  drop indicator left aligned at the depth where the item will be inserted.  Ugly hack:  This function will also set m_pItemAbove, which is the one we will use as  to determine where to insert the dropped item(s).  \return The indicator position.  \todo This code isn't very pretty, and neither is its usage.  Refactor. */QPointQmListView::indicatorPos(	const QPoint &pos){	if( ! m_Reorganizable)		return QPoint(0, 0);		QListViewItem *item = at(pos);    m_InsertPos = Below;	if(item == 0)	{		// Check wether the mouse is below the last item in the list view.		QListViewItem *l = lastItem();		// If the list is empty, place drop indicator at the top				if(l == 0)			return QPoint(0, 0);		int ypos = l->itemPos() + l->height();		if(pos.y() >= ypos)        {            m_pItemAbove  = lastChild();			return QPoint(0, ypos);        }		else			return QPoint(0, 0);	}		int depth;	int itemypos = itemPos(item);	int ypos 	 = pos.y() - header()->height() - itemMargin() + contentsY();    m_pItemAbove = item;	// Is the mouse on the bottom half of the item?		if(ypos > itemypos + (item->height() / 2))	{		// Yes.  That means that the indicator will be shown		// below this item, which again means that this item		// is the item above the drop position.				m_pItemAbove  = item;		depth 		  = item->depth();				itemypos 	 += item->height();		if(isFolder(item))        {            m_InsertPos = Child;			depth++;        }	}	else	{		// No.  That means that the indicator will be shown		// above this item, which again means that this item		// is the item below the drop position.        // An simple implementation of previousSibling(), this is needed        // since QListViewItem does not have one.        QListViewItem *cur = item->parent();        QListViewItem *above = 0;        if ( !cur )            cur = firstChild();        else            cur = cur->firstChild();        while ( cur && cur != item )        {            above = cur;            cur = cur->nextSibling();        }        // If we found a previous sibling use it, if not use the parent item.        if ( above )            m_pItemAbove = above;        else            m_pItemAbove = item->parent();		if(m_pItemAbove)			depth = m_pItemAbove->depth();		else			depth = 0;		if(m_pItemAbove == item->itemAbove() && isFolder(m_pItemAbove))        {            m_InsertPos = Child;            depth++;        }	}	int	itemxpos = depth * (16 + itemMargin());		return QPoint(itemxpos, itemypos);}/*!  Called when a drag is in progress and the mouse enters the widgets and  whenever it moves within the widget.  This function will show a drop indicator in between the lines where the  dragged items may be dropped.  The function will make sure the drop is  legal.  \sa isDroppable()  \todo Refactor; see indicatorPos().*/boolQmListView::canDecode(QDragMoveEvent *e){	return QTextDrag::canDecode(e);}voidQmListView::dragEnterEvent(QDragEnterEvent *event){	event->accept(canDecode(event));	addChild(m_pDropIndicator);	}/*!  Hides the drop indicator and stops auto-scrolling (if active). */voidQmListView::dragLeaveEvent(	QDragLeaveEvent *e){	stopDragging();	QListView::dragLeaveEvent(e);}// void// QmListView::dragLeaveEvent(QDragLeaveEvent *event)// {// 	stopDragging();// }voidQmListView::dragMoveEvent(	QDragMoveEvent *e){	if( ! m_Reorganizable)		return;		if( canDecode(e) )	{		// It's the right format.  Make sure the item above is not a child		// of the one we're moving.		indicatorPos(e->pos()); // nasty hack;  this function will update m_pItemAbove used below:		QListViewItem *item = m_pItemAbove;		// Check whether the dragged items are droppable beneath the given		// item.  If item is null (i.e. is at top), the items are droppable.				if( ! isDroppable(item))		{			e->ignore();			m_pDropIndicator->hide();		}		else		{            /// \todo Can this be removed safely?// 			if(item)// 			{// 				e->accept(); // 				m_pDropIndicator->show();// 				QPoint pos = indicatorPos(e->pos());// 				int indicatorwidth = header()->sectionSize(0) - pos.x();// 				m_pDropIndicator->setFixedWidth(indicatorwidth);	// 				moveChild(m_pDropIndicator, pos.x(), pos.y());// 			}            e->accept();            moveIndicator( e->pos() );            QPoint relpos( e->pos().x(), e->pos().y() - header()->height() );            if ( atTopMargin( relpos ) || atBottomMargin( relpos ) )            {                m_DragPos = relpos;                m_PointerPos = e->pos();                if ( !m_pScrollTimer->isActive() )                    m_pScrollTimer->start( 1000/(10), false );            }            else                m_pScrollTimer->stop();		}	}}/*!  Takes care of drop events.  If the drop is accepted, the item(s) will be inserted at drop position  as indicated by the drop indicator given in dragMoveEvent().  \todo Currently only drops from items within the list itself are supported. */voidQmListView::dropEvent(	QDropEvent *e){	if( ! m_Reorganizable)		return;    QString text;    if( QTextDrag::decode(e, text) )	{		if( e->source() == this )		{			e->acceptAction();			// We are to move items within the playlist.			QList<QListViewItem> *selected = selectedItems();			QListIterator<QListViewItem> it(*selected);						for(it.toFirst(); it.current(); ++it)			{				reposition(it.current(), m_pItemAbove);				m_pItemAbove = it.current();			}						delete selected;		}    }	stopDragging();}/*!  Start a drag operation.  Creates the necessary drag object, starts the drag  as a 'Move' and activates the drop indicator as used in dragMoveEvent().  \sa stopDragging()  \todo Replace QTextDrag with QUriDrag or something. */voidQmListView::startDragging(){	if( ! m_Reorganizable)		return;    m_pScrollTimer->stop();	// Just put some dummy text in	QDragObject *d = new QTextDrag( "<Apollo Playlist Drag'n Drop>", this );	d->dragMove();	addChild(m_pDropIndicator);		// Note: d is NOT to be deleted.  Will be handeled by Qt.}/*!  Stop the drag operation.  Disables the drop indicator as started through  startDragging().  \sa startDragging()*/voidQmListView::stopDragging(){	if( ! m_Reorganizable)		return;		m_pDropIndicator->hide();	removeChild(m_pDropIndicator);	if (m_pScrollTimer->isActive())		m_pScrollTimer->stop();}/*!  Record the position of where the left mouse button was clicked.  This will  be used to determine when a drag is to be started, i.e. when there's a  sufficient move from where the left mouse button was first clicked.  \sa contentsMouseMoveEvent()*/voidQmListView::contentsMousePressEvent(	QMouseEvent *e){	QListView::contentsMousePressEvent(e);	if(e->button() & LeftButton)		m_Click = e->pos();}/*!  Activates a drag action if the left mouse button is pressed and  the movement threshold is large enough.  \sa contentsMousePressEvent()*/voidQmListView::contentsMouseMoveEvent(	QMouseEvent *e){	if( ! m_Reorganizable)		return;		if(e->state() & LeftButton)	{		QPoint vector = e->pos() - m_Click;		if(vector.manhattanLength() > DRAG_THRESHOLD)		{			if(hasSelectedItems())				startDragging();		}	}}/*!  Moves the item \a moveitem to be positioned below \a itemabove.  If \a itemabove  is zero, \a moveitem will be made the top-most item in the list.  The items can be anywhere within the list.  It does not have the  limits of QListView::moveItem() and friends.  \sa take(), insertBelow()*/voidQmListView::reposition(	QListViewItem *moveitem,	QListViewItem *itemabove){	CHECK_PTR(moveitem);	take(moveitem);	insertBelow(moveitem, itemabove);}/*!  Takes the item \a item out of the list regardless of its position.  This function does not have the limits of QListView::takeItem().  \sa insertBelow() */voidQmListView::take(	QListViewItem *item){	CHECK_PTR(item);		QListViewItem *parent = item->parent();		if(parent)		parent->takeItem(item);	else		takeItem(item);	}/*!  Inserts \a insertitem below \a itemabove.  If \a itemabove is null,  \a insertitem will become a "root" item.  \a insertitem will also  become a "root" item if \a itemabove has no parent.  Make sure to take() the item first.  \warning Do not attempt to insert a (parent) item as a child to itself.  \sa take(), isDroppable()*/void

⌨️ 快捷键说明

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