📄 sidemenu.cpp
字号:
#include "sidemenu.h"#include "fontchooser.h"#include "style.h"#include <qapplication.h>#include <qbitmap.h>#include <qpainter.h>#include <assert.h>#include <stdio.h>#include <qgfx_qws.h>using namespace archos;class SideMenuEntry { public: SideMenuEntry(); SideMenuEntry(int id, int vis, const QString &label, const QString &icon_name); int id; QString label; QPixmap icon; bool visible;};SideMenuEntry::SideMenuEntry() : id(0) , visible(true){}SideMenuEntry::SideMenuEntry(int pid, int vis, const QString &plabel, const QString &icon_name) : id(pid) , label(plabel) , icon(AStyle::iconpath + icon_name + ".png") , visible(vis){}//--------------------------------///*! @class SideMenu sidemenu.h @brief A custom, nonhierarchical menu that matches the menu on coming Archos products in style.*//*! @brief Creates a SideMenu object @param itemcnt The maximum number of entries the menu will be able to hold @param parent The parent widget @param parent The name of the menu*/SideMenu::SideMenu(int itemcnt, QWidget *parent, const char *name) : QWidget( parent, name, QWidget::WStyle_Customize | QWidget::WStyle_NoBorder | WRepaintNoErase | QWidget::WStyle_StaysOnTop) , m_entries(new SideMenuEntry[itemcnt]) , m_cnt(itemcnt) , m_selpos(0) , m_visible_entries(0) , m_trigger(false){ QString path = AStyle::iconpath + Screen::prefix(); menu_key_icon = QPixmap(path + "general/key_menu.png"); m_label_mask = QPixmap(path + "general/label_mask.png"); setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum)); qApp->installEventFilter(this); m_labels= new SideMenuLabels(this); connect(&m_hideTimer, SIGNAL(timeout()), this, SLOT(hide()));}SideMenu::~SideMenu(){ delete[] m_entries; delete m_labels;}void SideMenu::showMenuAndLabels(){ show(); m_labels->show(); m_hideTimer.stop();}void SideMenu::strobeHideTimer(){ if (m_hideTimer.isActive()) { m_hideTimer.start(timeoutInterval); }}void SideMenu::hide(){ m_labels->hide(); m_hideTimer.stop(); QWidget::hide(); emit hideOn();}/*! @brief Sets the data for an entry at a given position @param index index of the entry to create or modify @param visible whether the entry is displayed or visible @param id identifyer of the entry (which will be reported by entryActivated() ) @param label textual representation of the entry @param label file name of the icon (a .png suffix will be appended and the file is expected to be relative to AStyle::iconpath)*/void SideMenu::setEntry(int index, int visible, int id, const QString &label, const QString &icon_name) { assert(index < m_cnt); m_entries[index]= SideMenuEntry(id, visible, label, icon_name); if (visible) m_visible_entries++; polish(); update();}/*! @brief Shows or hides an entry at a given position @param index index of the entry @param visible whether the entry should be visible*/void SideMenu::setEntryVisible(int index, bool visible){ if (m_entries[index].visible != visible) { if (visible) { m_visible_entries++; } else { if (m_selpos == index) { qWarning("we just hide m_selpos!"); m_selpos = 0; m_labels->setSelection(0); } m_visible_entries--; } m_entries[index].visible = visible; polish(); update(); }}/*! @brief Selects the entry at the given position @param index index of the entry to select*/void SideMenu::setSelection(int index) { if(index < 0 || index >= m_cnt) return; if(index != m_selpos) { m_selpos = index; update(); }}int SideMenu::visibleEntries() const { return m_visible_entries;}void SideMenu::showEvent(QShowEvent*){ qApp->installEventFilter(this); m_hideTimer.start(timeoutInterval);}void SideMenu::hideEvent(QHideEvent*){ qApp->removeEventFilter(this);}void SideMenu::polish(){ if(backgroundPixmap() == NULL) { QBitmap mask(size()); { QPainter p(&mask); paintButtonsMask(&p); } setMask(mask); }}QSize SideMenu::sizeHint() const{ return QSize( menu_key_icon.width(), m_entries[0].icon.height()* m_visible_entries + menu_key_icon.height() );}void SideMenu::paintEvent(QPaintEvent*) { QPainter p(this); paintButtons(&p);}void SideMenu::paintButtonsMask(QPainter *p){ int yofs = yOffset(); int iconh= m_label_mask.height(); int num_visible = 0; for(int i= 0; i < m_cnt; i++) { if (!m_entries[i].visible) continue; p->drawPixmap(width() - menu_key_icon.width(), yofs + num_visible * iconh, m_label_mask); num_visible++; } p->drawPixmap(width() - menu_key_icon.width(), yofs + num_visible * iconh, menu_key_icon);}void SideMenu::paintButtons(QPainter *p){ int yofs = yOffset(); int iconh= m_entries[0].icon.height(); int num_visible = 0; for(int i= 0; i < m_cnt; i++) { if (!m_entries[i].visible) continue; p->drawPixmap(width() - menu_key_icon.width(), yofs + num_visible * iconh, m_entries[i].icon); num_visible++; } p->drawPixmap(width() - menu_key_icon.width(), yofs + num_visible * iconh, menu_key_icon);}void SideMenu::selectLastEntry() { int pos = visiblePosToPos(m_visible_entries - 1); setSelection(pos); m_labels->setSelection(pos);}void SideMenu::mousePressEvent(QMouseEvent * e){ if ( keyIconArea(e->y()) ) { if ( m_labels->isVisible() ) { m_labels->hide(); } else { m_labels->show(); m_hideTimer.stop(); } } else { int iconh = m_entries[0].icon.height(); int icon_pos_clicked = (e->y() - yOffset()) / iconh; int pos = visiblePosToPos(icon_pos_clicked); if ( m_selpos == pos && m_labels->isVisible() ) { m_trigger = true; } setSelection(pos); m_labels->setSelection(pos); m_labels->show(); m_hideTimer.stop(); }}void SideMenu::mouseReleaseEvent(QMouseEvent *e){ if ( m_trigger ) { m_trigger = false; m_labels->hide(); m_hideTimer.start(timeoutInterval); if (e->y() > yOffset() && !keyIconArea(e->y()) && e->x() > - (m_labels->sizeHint().width())) { emit entryActivated(m_entries[m_selpos].id); } }}bool SideMenu::keyIconArea(int y){ return y > yOffset() + m_entries[0].icon.height() * m_visible_entries;}void SideMenu::mouseMoveEvent ( QMouseEvent *e){ if (e->y() < yOffset() || keyIconArea(e->y()) || e->x() < - m_labels->sizeHint().width()) return; int iconh = m_entries[0].icon.height(); int icon_pos_clicked = (e->y() - yOffset()) / iconh; int pos = visiblePosToPos(icon_pos_clicked); if (pos != m_selpos) { m_trigger = false; m_selpos = pos; m_labels->setSelection(pos); update(); }}bool SideMenu::eventFilter(QObject*, QEvent *evt) { if(evt->type() == QEvent::KeyRelease) { if(!isVisible()) return false; if(((QKeyEvent*) evt)->key() == Key_F1) { if(m_labels->isHidden()) { m_labels->show(); m_hideTimer.stop(); return true; } } } return false;}int SideMenu::visiblePosToPos(int vpos) const{ int pos; for(pos = 0; pos < m_cnt; pos++) { if (!m_entries[pos].visible) continue; if (vpos-- == 0) break; } return pos;}void SideMenu::hideLabels(){ m_trigger = false; m_labels->hide(); m_hideTimer.start(SideMenu::timeoutInterval);}int SideMenu::posToVisiblePos(int pos) const{ int res = 0; for (int i = 0; i < pos; i++) { if (m_entries[i].visible) res++; } return res;}int SideMenu::timeoutInterval = 5000;//--------------------------------//SideMenuLabels::SideMenuLabels(SideMenu *menu) : QWidget(NULL, "menu labels", QWidget::WStyle_Customize | QWidget::WStyle_NoBorder | QWidget::WStyle_StaysOnTop) , m_entries(menu->m_entries) , m_menu(menu) , m_selpos(-1) , m_trigger(false){ setBackgroundMode(NoBackground); QFont font = qApp->font(); if (Screen::mode() == wqvga) { font.setPointSize(16); } else if (Screen::mode() == wvga) { font.setPointSize(22); } else if (Screen::mode() == qvga) { font.setPointSize(14); } else { // tv font.setPointSize(18); } setFont(font);}void SideMenuLabels::setSelection(int pos){ if(pos < 0 || pos >= m_menu->m_cnt) return; if(pos != m_selpos) { m_selpos = pos; update(); }}void SideMenuLabels::updateMask(){ // create mask QBitmap mask(size()); { QPainter p(&mask); AStyle::get()->drawPanel(&p, rect()); } setMask(mask);}int SideMenuLabels::lineHeight() const{ if (m_menu->m_visible_entries == 0) return sizeHint().height(); return sizeHint().height()/ m_menu->m_visible_entries;}QRect SideMenuLabels::selectionArea() const{ int lineh = lineHeight(); int pos_visible = m_menu->posToVisiblePos(m_selpos); int y_pos = 2 + pos_visible * (lineh + 1) + 1; QRect textr(2, y_pos, width() - 14, lineh); QPainter p(this); QRect r(p.boundingRect(textr, AlignVCenter | AlignRight, m_entries[m_selpos].label)); return QRect(r.x() - 4, y_pos, r.width() + 8, lineh);}void SideMenuLabels::polish(){ updateMask();}void SideMenuLabels::showEvent(QShowEvent*){ // position on screen int dw = qt_screen->width(); int dh = qt_screen->height(); int ww = sizeHint().width(); int wh = sizeHint().height(); setGeometry(dw - m_menu->width() - ww - 2, dh - m_menu->sizeHint().height() - 1, ww, wh + 1); if (m_selpos == -1) setSelection(0); updateMask();}void SideMenuLabels::paintEvent(QPaintEvent *evt){ QRect area(evt->rect()); // draw double buffered QPixmap pix(area.size()); { QPainter p(&pix, this); p.translate(-area.x(), -area.y()); AStyle::get()->drawPanel(&p, rect()); AStyle::get()->drawSelection(&p, selectionArea()); drawLabels(&p); } QPainter p(this); p.drawPixmap(area.topLeft(), pix);}void SideMenuLabels::drawLabels(QPainter *p) const{ if(m_menu->m_visible_entries == 0) return; int ypos= 2; int lineh = lineHeight(); for(int i = 0; i < m_menu->m_cnt; i++) { if(m_entries[i].visible) { p->setPen(i == m_selpos ? colorGroup().highlightedText() : colorGroup().text()); QRect textr(2, ypos, width() - 14, lineh - 1); p->drawText(textr, AlignVCenter | AlignRight, m_entries[i].label); ypos+= lineh + 1; } }}QSize SideMenuLabels::sizeHint() const{ QFontMetrics fm(font()); int w = 0; for(int i= 0; i < m_menu->m_cnt; i++) { if (m_entries[i].visible) w= QMAX(w, fm.width(m_entries[i].label)); } return QSize( w + 26, m_menu->sizeHint().height() - m_menu->menu_key_icon.height() - 1 );}bool SideMenuLabels::event(QEvent* e){ bool handled = false; if (e->type() == QEvent::KeyRelease || (e->type() == QEvent::KeyPress && ((QKeyEvent*)e)->isAutoRepeat()) ) { QKeyEvent* keyEvent = (QKeyEvent*)e; switch(keyEvent->key()) { case Key_F1 : case Key_F2 : m_menu->m_hideTimer.start(SideMenu::timeoutInterval); hide(); handled = true; break; case Key_Up : { int vpos = m_menu->posToVisiblePos(m_selpos); vpos--; if(vpos < 0) vpos = m_menu->m_visible_entries - 1; int pos = m_menu->visiblePosToPos(vpos); m_menu->setSelection(pos); setSelection(pos); handled = true; break; } case Key_Down : { int vpos = m_menu->posToVisiblePos(m_selpos); vpos++; if(vpos >= m_menu->m_visible_entries) vpos = 0; int pos = m_menu->visiblePosToPos(vpos); m_menu->setSelection(pos); setSelection(pos); handled = true; break; } case Key_Return : qWarning("selected entry %i", m_selpos); m_menu->m_hideTimer.start(SideMenu::timeoutInterval); hide(); m_menu->emit entryActivated(m_entries[m_selpos].id); handled = true; break; } } if (!handled) return QWidget::event(e); return true;}void SideMenuLabels::mousePressEvent(QMouseEvent * e){ m_menu->m_hideTimer.stop(); int pos = m_menu->visiblePosToPos(e->y() / lineHeight()); if ( m_selpos == pos ) { m_trigger = true; } m_menu->setSelection(pos); setSelection(pos);}void SideMenuLabels::mouseReleaseEvent(QMouseEvent *e){ if ( m_trigger ) { m_trigger = false; QRect r = rect(); hide(); if(r.contains(e->x(), e->y())) m_menu->emit entryActivated(m_entries[m_selpos].id); m_menu->m_hideTimer.start(SideMenu::timeoutInterval); }}void SideMenuLabels::mouseMoveEvent(QMouseEvent *e){ if (e->x() < 0 || e->y() < 0 || e->y() > height()) return; int pos = m_menu->visiblePosToPos(e->y() / lineHeight()); if(pos != m_selpos) { m_trigger = false; setSelection(pos); m_menu->setSelection(pos); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -