Rivendellaudio/lib/rdpanel_button.cpp
Fred Gleason d0c232eef1 2020-03-18 Fred Gleason <fredg@paravelsystems.com>
* Fixed a regression in rdairplay(1) that caused two events to be
	started by a single spacebar tap if a SoundPanel event had been
	played previously.
2020-03-18 13:39:42 -04:00

560 lines
11 KiB
C++

// rdpanel_button.cpp
//
// The SoundPanel Button for RDAirPlay.
//
// (C) Copyright 2002-2019 Fred Gleason <fredg@paravelsystems.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include <qpainter.h>
#include <rdcartdrag.h>
#include <rdconf.h>
#include "rdpanel_button.h"
RDPanelButton::RDPanelButton(int row,int col,RDStation *station,bool flash,
QWidget *parent)
: RDPushButton(parent)
{
button_row=row;
button_col=col;
button_station=station;
button_parent=parent;
button_flash=flash;
button_flash_state=false;
button_hook_mode=false;
button_move_count=-1;
button_allow_drags=false;
clear();
setFocusPolicy(Qt::NoFocus);
}
void RDPanelButton::clear()
{
setText("");
setOutputText("");
button_color=Qt::lightGray;
button_default_color=Qt::lightGray;
setCart(0);
button_deck=-1;
button_output=-1;
button_play_deck=NULL;
button_start_time=QTime();
button_end_time=QTime();
button_active_length=0;
button_length[0]=0;
button_length[1]=0;
button_secs=-1;
button_flashing=false;
button_flash_state=false;
button_state=false;
button_start_source=RDLogLine::StartUnknown;
button_pause_when_finished=false;
button_duck_volume=0;
}
QString RDPanelButton::text() const
{
return button_text;
}
void RDPanelButton::setText(const QString &text)
{
button_text=text;
WriteKeycap(-1);
}
QString RDPanelButton::outputText() const
{
return button_output_text;
}
void RDPanelButton::setOutputText(const QString &text)
{
button_output_text=text;
}
bool RDPanelButton::state() const
{
return button_state;
}
void RDPanelButton::setState(bool state)
{
button_state=state;
}
QColor RDPanelButton::defaultColor() const
{
return button_default_color;
}
void RDPanelButton::setDefaultColor(QColor color)
{
if(color==button_default_color) {
return;
}
button_default_color=color;
if(playDeck()==NULL) {
setColor(color);
}
}
RDLogLine::StartSource RDPanelButton::startSource() const
{
return button_start_source;
}
void RDPanelButton::setStartSource(RDLogLine::StartSource src)
{
button_start_source=src;
}
void RDPanelButton::setColor(QColor color)
{
if(color==button_color) {
return;
}
button_color=color;
if(button_flash) {
if(color==button_parent->backgroundColor()) {
button_flashing=false;
}
else {
button_flashing=true;
}
}
WriteKeycap(button_secs);
}
unsigned RDPanelButton::cart() const
{
return button_cart;
}
void RDPanelButton::setCart(unsigned cart)
{
button_cart=cart;
}
QString RDPanelButton::cutName() const
{
return button_cutname;
}
void RDPanelButton::setCutName(const QString &name)
{
button_cutname=name;
}
int RDPanelButton::deck() const
{
return button_deck;
}
void RDPanelButton::setDeck(int deck)
{
button_deck=deck;
}
RDPlayDeck *RDPanelButton::playDeck() const
{
return button_play_deck;
}
void RDPanelButton::setPlayDeck(RDPlayDeck *deck)
{
button_play_deck=deck;
}
QTime RDPanelButton::startTime() const
{
return button_start_time;
}
void RDPanelButton::setStartTime(QTime time)
{
button_start_time=time;
button_end_time=button_start_time.addMSecs(button_active_length);
}
bool RDPanelButton::hookMode() const
{
return button_hook_mode;
}
void RDPanelButton::setHookMode(bool state)
{
button_hook_mode=state;
}
int RDPanelButton::output() const
{
return button_output;
}
void RDPanelButton::setOutput(int outnum)
{
button_output=outnum;
}
int RDPanelButton::length(bool hookmode) const
{
return button_length[hookmode];
}
void RDPanelButton::setLength(bool hookmode, int msecs)
{
button_length[hookmode]=msecs;
}
void RDPanelButton::setActiveLength(int msecs)
{
button_active_length=msecs;
button_end_time=button_start_time.addMSecs(button_active_length);
if((button_start_time.isNull())&&(button_cart!=0)) {
WriteKeycap(-1);
}
}
void RDPanelButton::reset()
{
if(button_length[button_hook_mode]>0) {
setActiveLength(button_length[button_hook_mode]);
}
else {
setActiveLength(button_length[0]);
}
button_start_time=QTime();
button_end_time=QTime();
setColor(button_default_color);
if(button_cart!=0) {
WriteKeycap(-1);
}
setDeck(-1);
button_play_deck=NULL;
}
bool RDPanelButton::pauseWhenFinished() const
{
return button_pause_when_finished;
}
void RDPanelButton::setPauseWhenFinished(bool pause_when_finished)
{
button_pause_when_finished=pause_when_finished;
}
void RDPanelButton::resetCounter()
{
WriteKeycap(-1);
}
void RDPanelButton::setAllowDrags(bool state)
{
button_allow_drags=state;
}
void RDPanelButton::setDuckVolume(int level)
{
button_duck_volume=level;
}
int RDPanelButton::duckVolume() const
{
return button_duck_volume;
}
void RDPanelButton::tickClock()
{
int secs;
QTime current_time=
QTime::currentTime().addMSecs(button_station->timeOffset());
if((button_start_time.isNull())||(current_time>button_end_time)||
((secs=current_time.secsTo(button_end_time))==button_secs)) {
return;
}
button_secs=secs;
WriteKeycap(secs);
}
void RDPanelButton::flashButton(bool state)
{
if(state==button_flash_state) {
return;
}
button_flash_state=state;
if(button_flashing&&button_state) {
WriteKeycap(button_secs);
}
}
void RDPanelButton::keyPressEvent(QKeyEvent *e)
{
QWidget::keyPressEvent(e);
}
void RDPanelButton::keyReleaseEvent(QKeyEvent *e)
{
QWidget::keyReleaseEvent(e);
}
void RDPanelButton::mousePressEvent(QMouseEvent *e)
{
button_move_count=10;
QPushButton::mousePressEvent(e);
}
void RDPanelButton::mouseMoveEvent(QMouseEvent *e)
{
button_move_count--;
if(button_move_count==0) {
QPushButton::mouseReleaseEvent(e);
if(button_allow_drags) {
RDCartDrag *d=new RDCartDrag(button_cart,button_text,button_color,this);
d->dragCopy();
}
}
}
void RDPanelButton::mouseReleaseEvent(QMouseEvent *e)
{
button_move_count=-1;
QPushButton::mouseReleaseEvent(e);
}
void RDPanelButton::dragEnterEvent(QDragEnterEvent *e)
{
e->accept(RDCartDrag::canDecode(e)&&button_allow_drags&&
((button_play_deck==NULL)||(button_play_deck->state()==RDPlayDeck::Stopped)));
}
void RDPanelButton::dropEvent(QDropEvent *e)
{
unsigned cartnum;
QColor color;
QString title;
if(RDCartDrag::decode(e,&cartnum,&color,&title)) {
emit cartDropped(button_row,button_col,cartnum,color,title);
}
}
void RDPanelButton::WriteKeycap(int secs)
{
QString text=button_text;
QPixmap *pix=new QPixmap(size().width()-2,size().height()-2);
QPainter *p=new QPainter(pix);
if(button_state) {
if(button_flash) {
if(button_flash_state) {
p->fillRect(0,0,size().width()-2,size().height()-2,button_color);
p->setPen(RDGetTextColor(button_color));
}
else {
p->fillRect(0,0,size().width()-2,size().height()-2,button_default_color);
p->setPen(RDGetTextColor(button_default_color));
}
}
else {
p->fillRect(0,0,size().width()-2,size().height()-2,button_color);
p->setPen(RDGetTextColor(button_color));
}
}
else {
p->fillRect(0,0,size().width()-2,size().height()-2,button_color);
p->setPen(RDGetTextColor(button_color));
}
//
// Button Title
//
QFontMetrics m(buttonFont());
p->setFont(buttonFont());
p->drawText(RDPANEL_BUTTON_MARGIN,m.lineSpacing(),
GetNextLine(&text,m,size().width()-2-3*RDPANEL_BUTTON_MARGIN));
p->drawText(RDPANEL_BUTTON_MARGIN,2*m.lineSpacing(),
GetNextLine(&text,m,size().width()-2-3*RDPANEL_BUTTON_MARGIN));
p->drawText(RDPANEL_BUTTON_MARGIN,3*m.lineSpacing(),
GetNextLine(&text,m,size().width()-2-3*RDPANEL_BUTTON_MARGIN));
//
// Time Field & Output Text
//
if(!button_text.isEmpty()) {
if(secs<0) {
p->setFont(smallTimerFont());
if(button_pause_when_finished) {
p->drawText(RDPANEL_BUTTON_MARGIN,size().height()-2-RDPANEL_BUTTON_MARGIN,"Finished");
}
else {
if(button_active_length>=0) {
p->drawText(RDPANEL_BUTTON_MARGIN,size().height()-2-
RDPANEL_BUTTON_MARGIN,
RDGetTimeLength(button_active_length+1000,true,false));
}
else {
p->drawText(RDPANEL_BUTTON_MARGIN,size().height()-2-
RDPANEL_BUTTON_MARGIN,tr("No Audio"));
}
}
}
else {
if(secs>8) {
p->drawText(RDPANEL_BUTTON_MARGIN,size().height()-2-RDPANEL_BUTTON_MARGIN,
RDGetTimeLength(1000*(secs+1),true,false));
}
else {
p->setFont(timerFont());
QString secstr=QString().sprintf(":%d",secs+1);
p->drawText(RDPANEL_BUTTON_MARGIN,size().height()-2-RDPANEL_BUTTON_MARGIN,secstr);
}
p->setFont(bannerFont());
QFontMetrics om(timerFont());
p->drawText(size().width()-2-om.width(button_output_text)-
RDPANEL_BUTTON_MARGIN,
size().height()-2-RDPANEL_BUTTON_MARGIN,button_output_text);
}
}
p->end();
setPixmap(*pix);
delete p;
delete pix;
update();
}
QString RDPanelButton::WrapText(QString text,int *lines)
{
QFontMetrics fm(font());
QString str;
QString residue = text;
bool space_found=false;
int l;
*lines=0;
if(!text.isEmpty()) {
while(!residue.isEmpty()) {
space_found=false;
for(int i=(int)residue.length();i>=0;i--) {
if((i==((int)residue.length()))||(residue.at(i).isSpace())) {
if(fm.boundingRect(residue.left(i)).width()<=width()-6) {
space_found=true;
if(!str.isEmpty()) {
str+="\n";
if(++*lines==3) {
return str;
}
}
str+=residue.left(i);
if(i==(int)residue.length()) {
return str;
}
residue=residue.right(residue.length()-i-1);
}
}
}
if(!space_found) {
l=residue.length();
for(int i=l;i>=0;i--) {
if(fm.boundingRect(residue.left(i)).width()<=(width()-6)) {
if(!str.isEmpty()) {
str+="\n";
if(++*lines==3) {
return str;
}
}
str+=residue.left(i);
if(i==(int)residue.length()) {
return str;
}
residue=residue.right(residue.length()-i-1);
}
}
}
}
}
return text;
}
QString RDPanelButton::GetNextLine(QString *str,const QFontMetrics &m,int len)
{
QString ret;
for(int i=0;i<str->length();i++) {
if(m.width(str->left(i))>len) {
int l=i;
while((!str->at(l--).isSpace())&&(l>=0));
if(l>0) {
ret=str->left(l+1);
*str=str->right(str->length()-l-1).stripWhiteSpace();
return ret;
}
}
}
ret=*str;
*str="";
return ret;
}