📄 nlistview.cpp
字号:
#include "nlistview.h"#include "animrect.h"#include "style.h"//#include <qtopia/global.h>#include <qapplication.h>#include <qimage.h>#include <qlineedit.h>#include <qtimer.h>#include <qvaluelist.h>#include <assert.h>#include <ctype.h>#include <stdio.h>/*! @internal @brief Draws image b on top of image a and returns the resulting image. Note: Both images should be of the same size. Only the smaller dimensions of both images are taken into account.*/QImage blendIcons(const QImage &p_a, const QImage &p_b) { QImage a= p_a.convertDepth(32); QImage b= p_b.convertDepth(32); int w= QMIN(a.width(), b.width()); int h= QMIN(a.height(), b.height()); for(int y= 0; y < h; y++) { uint *dpix= (uint*) a.scanLine(y); uint *spix= (uint*) b.scanLine(y); for(int x= 0; x < w; x++) { if((spix[x] & 0xFF000000) == 0xFF000000) dpix[x]= spix[x]; } } return a;}/*! @internal @brief Crops a string by replacing character in the middle with an ellipsis (...) .*/QString fitString(const QFontMetrics &fm, QString s, int len) { static int pw= fm.width("..."); static int mw= fm.width('m'); if(fm.width(s) > len) { int dif= fm.width(s) + pw - len; s= s.left(4) + "..." + s.right(s.length() - 4 - dif/ mw); while(fm.width(s) > len && s.length() > 8) s= s.left(7) + s.right(s.length() - 8); } return s;}//-------------------------------------------------------///*! @internal @class NListSource @brief Abstract base class for data sources that provide information for a NListView.*//*! @fn void NListSource::count() const @brief Returns the total number of entries to be displayed by the list.*//*! @fn void NListSource::icon(uint index) const @brief Returns the icon to be displayed on the left of an entry. @param index Position of the entry the icon is aked for.*//*! @fn void NListSource::text(uint index, uint col) const @brief Returns the text to be displayed for an entry. @param index Position of the entry the text is asked for. @param col Column the text is asked for.*//*! @fn void NListSource::indent(uint index) const @brief Returns the amount of pixels the entry should be indented. @param index Position of the entry the text is asked for.*//*! @fn void NListSource::itemCountChanged(uint cnt) @brief Signals that the number of entries to be displayed in the list has changed.*//*! @fn void NListSource::itemsChanged(uint start, uint span) @brief Signals that entries have changed, and should be updated. @param start Position of the first entry that has changed. @param span Number of entries that have changed.*//*! @brief Constructs a new source for a NListView. @note This is an abstract base class, and you will only ever instantiate derived classes. @param parent The parent object, which will take ownership of this object. @param name The name of the object.*/NListSource::NListSource(QObject *parent, const char *name) : QObject(parent, name) {}NListSource::~NListSource() {}//-------------------------------------------------------//class NListViewData { public: int* colwidths; uint colcnt; QTimer anim_timer; QPixmap anim_pix, bgnd_pix; AnimRect animr; int anim_offset, anim_delta; bool anim_prepared; NListViewData::NListViewData() : colwidths(new int[1]) , colcnt(1) , anim_offset(0) , anim_delta(0) , anim_prepared(false) { colwidths[0]= -1; } NListViewData::~NListViewData() { delete[] colwidths; }};//-------------------------------------------------------///*! @internal @class NListView @brief A widget for displaying a list described by a NListSource. The view supports multiple columns, multiple selection and editing of its entries.*//*! @fn NListView::selected(uint index) @brief Signals that a new entry has been selected. @param index Position of the entry that was selected.*//*! @fn NListView::activated(uint index) @brief Signals that an entry was activated. @param index Position of the entry that was activated.*//*! @fn NListView::selectionEdited(const QString &newtext) @brief Signals that the user has finished editing the selected entry. @param newtext The text that the first column was changed to.*//*! @fn NListView::resizedContents(int width, int height) @brief Signals that the contents were resized. @note This is provided so that an ALeftScrollBar can be updated.*//*! @fn NListView(NListSource *src, QWidget *parent, const char *name) @brief Constructs a new list view. @param src The source for the data to be displayed. @param parent The parent object, which will take ownership of this object. @paramname The name of the object.*/NListView::NListView(NListSource *src, QWidget *parent, const char *name) : QScrollView(parent, name, WResizeNoErase) , m_ledit(NULL) , m_selpos(0) , m_selcnt(1) , m_item_height(18) , m_tapped_index(0) , m_tapped_border(true) , m(new NListViewData()) , m_src(NULL) { setSource(src); m_item_height= QFontMetrics(font()).lineSpacing() + 3; if(m_item_height% 3 != 0) m_item_height= (m_item_height/ 3 + 1)* 3; setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); setFocusPolicy(StrongFocus); setHScrollBarMode(AlwaysOff); viewport()->setBackgroundMode(NoBackground); verticalScrollBar()->setLineStep(m_item_height); setFrameStyle(NoFrame);// connect(&m->anim_timer, SIGNAL(timeout()), this, SLOT(animateSelection()));}NListView::~NListView() { delete m;}/*! @brief Returns the source of the data displayed by the list view.*/NListSource* NListView::source() { return m_src;}/*! @brief Sets a new source to be displayed by the list view. @note The old source will not be deleted. It is owned by its parent object.*/void NListView::setSource(NListSource *src) { assert(src != NULL); if(m_src != NULL) { disconnect( m_src, SIGNAL(itemsChanged(uint, uint)), this, SLOT(onItemsChanged(uint, uint)) ); disconnect( m_src, SIGNAL(itemCountChanged(uint)), this, SLOT(onItemCountChanged(uint)) ); } m_src= src; connect( m_src, SIGNAL(itemsChanged(uint, uint)), this, SLOT(onItemsChanged(uint, uint)) ); connect( m_src, SIGNAL(itemCountChanged(uint)), this, SLOT(onItemCountChanged(uint)) ); onItemCountChanged(m_src->count());}/*! @brief Returns the number of columns being displayed.*/uint NListView::columns() const { return m->colcnt;}/*! @brief Sets the number of columns to be displayed. @note Make sure to set the width of newly displayed columns using setColumnWidth() .*/void NListView::setColumns(uint cnt) { assert(cnt > 0); if(cnt > 0) { int *ncols= new int[cnt]; for(uint i= 0; i < cnt; i++) { if(i < m->colcnt) { ncols[i]= m->colwidths[i]; } else { ncols[i]= 0; } } delete[] m->colwidths; m->colwidths= ncols; m->colcnt= cnt; updateContents(0, 0, contentsWidth(), contentsHeight()); }}/*! @brief Returns the width of a column. @note The width of the first column gets adjusted to the width of the widget. Other columns need to be given a fixed width using setColumnWidth() . @param col The number of the column the width is asked for.*/int NListView::columnWidth(uint col) const { assert(col < m->colcnt); int res= 0; if(col == 0) { res= visibleWidth(); // remove width of further cols for(uint i= 1; i < m->colcnt; i++) res-= m->colwidths[i]; } else if(col < m->colcnt) { res= m->colwidths[col]; } return res;}/*! @brief Sets the width of a column. The width of the first column gets adjusted to the width of the widget. Only further columns will accept a fixed width. @param col Number identifying the column to be changed (must be > 1). @param pixelwidth The fixed width the column should be displayed at in pixels.*/void NListView::setColumnWidth(uint col, int pixelwidth) { assert(col > 0 && col < m->colcnt); if(col > 0 && col < m->colcnt) { m->colwidths[col]= pixelwidth; updateContents(0, 0, contentsWidth(), contentsHeight()); }}/*! @brief Selects all entries in the list.*/void NListView::selectAll() { setSelection(0, m_src->count());}/*! @brief Selects the first item displaying the given text in its first column. If no matching entry was found, the entry that would be next will be selected. @return Whether a matching entry was found.*/bool NListView::select(const QString &text) { int best= m_src->count() - 1; QString name= text.upper(); for(uint i= 0; i < m_src->count(); i++) { int res= m_src->text(i).upper().compare(name); if(res == 0) { setSelection(i); return true; } else if(res > 0) { if(int(i) < best) best= i; } } setSelection(best); return false;}/*! @brief Sets the selected entries. @param pos The first entry to be selected. @param cnt The number of entries to be selected. @param ensure_visible Whether the contents should be scrolled to expose the newly selected entries. @param update Whether the contents repainted as necessary.*/void NListView::setSelection(int pos, int cnt, bool ensure_visible, bool update) { m->anim_timer.stop(); m->anim_prepared= false; restrictRange(pos, cnt); // update display QPainter p(this); QRect oldarea= selectionArea(&p); uint olpos= m_selpos; uint olcnt= m_selcnt; m_selpos= pos; m_selcnt= cnt; m->animr.set(oldarea, selectionArea(&p), 1); if(update) { repaintContents(areaFor(olpos, olcnt)); if(ensure_visible) ensureSelectionVisible(); updateContents(areaFor(m_selpos, m_selcnt)); } if(m_selcnt > 0) { QTimer::singleShot(400, this, SLOT(prepareAnimation())); emit selected(m_selpos); }}/*! @brief Returns the position of the first selected entry. @param cnt A pointer to a variable the number of selected entries will be written to or NULL.*/uint NListView::selection(uint *cnt) const { if(cnt != NULL) *cnt= m_selcnt; return m_selpos;}/*! @brief Creates a list containing the strings displayed in the first columns of all selected widgets.*/QStringList NListView::selectionList() { QStringList res; for(uint i= 0; i < m_selcnt; i++) res+= m_src->text(m_selpos + i); return res;}/*! @brief Lets the user edit the first column of the selected entry. A selectionEdited() signal will be emitted after the user has edited the entry.*/void NListView::editSelection() { if(m_src->count() <= 0) return; // create edit widget if necessary if(m_ledit == NULL) { m_ledit= new QLineEdit(viewport(), "edit_widget"); m_ledit->setFont(QFont("Courier", font().pointSize(), QFont::Bold)); m_ledit->installEventFilter(this); } // set the default text m_ledit->setText(m_src->text(m_selpos)); m_ledit->setSelection(0, m_ledit->text().length());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -