/* * Copyright (c) 2015 Erik Botö (erik.boto@gmail.com) * * 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., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "TrainBottom.h" #include "TrainSidebar.h" #include #include #include #include #include #include TrainBottom::TrainBottom(TrainSidebar *trainSidebar, QWidget *parent) : QWidget(parent), m_trainSidebar(trainSidebar) { // Control buttons QHBoxLayout *toolbuttons = new QHBoxLayout; toolbuttons->setSpacing(0); toolbuttons->setContentsMargins(0,0,0,0); QIcon connectButtonIcon(":images/oxygen/power-off.png"); m_connectButton = new QPushButton(connectButtonIcon, "", this); m_connectButton->setFocusPolicy(Qt::NoFocus); m_connectButton->setIconSize(QSize(64,64)); m_connectButton->setAutoFillBackground(false); m_connectButton->setAutoDefault(false); m_connectButton->setFlat(true); m_connectButton->setStyleSheet("background-color: rgba( 255, 255, 255, 0% ); border: 0px;"); m_connectButton->setAutoRepeat(true); m_connectButton->setAutoRepeatDelay(200); #if QT_VERSION > 0x050400 m_connectButton->setShortcut(Qt::Key_MediaPrevious); #endif toolbuttons->addWidget(m_connectButton); QIcon rewIcon(":images/oxygen/rewind.png"); m_rewindButton = new QPushButton(rewIcon, "", this); m_rewindButton->setFocusPolicy(Qt::NoFocus); m_rewindButton->setIconSize(QSize(64,64)); m_rewindButton->setAutoFillBackground(false); m_rewindButton->setAutoDefault(false); m_rewindButton->setFlat(true); m_rewindButton->setStyleSheet("background-color: rgba( 255, 255, 255, 0% ); border: 0px;"); m_rewindButton->setAutoRepeat(true); m_rewindButton->setAutoRepeatDelay(200); #if QT_VERSION > 0x050400 m_rewindButton->setShortcut(Qt::Key_MediaPrevious); #endif toolbuttons->addWidget(m_rewindButton); QIcon stopIcon(":images/oxygen/stop.png"); m_stopButton = new QPushButton(stopIcon, "", this); m_stopButton->setFocusPolicy(Qt::NoFocus); m_stopButton->setIconSize(QSize(64,64)); m_stopButton->setAutoFillBackground(false); m_stopButton->setAutoDefault(false); m_stopButton->setFlat(true); m_stopButton->setStyleSheet("background-color: rgba( 255, 255, 255, 0% ); border: 0px;"); #if QT_VERSION > 0x050400 m_stopButton->setShortcut(Qt::Key_MediaStop); #endif toolbuttons->addWidget(m_stopButton); QIcon playIcon(":images/oxygen/play.png"); m_playButton = new QPushButton(playIcon, "", this); m_playButton->setFocusPolicy(Qt::NoFocus); m_playButton->setIconSize(QSize(64,64)); m_playButton->setAutoFillBackground(false); m_playButton->setAutoDefault(false); m_playButton->setFlat(true); m_playButton->setStyleSheet("background-color: rgba( 255, 255, 255, 0% ); border: 0px;"); m_playButton->setShortcut(Qt::Key_MediaTogglePlayPause); toolbuttons->addWidget(m_playButton); QIcon fwdIcon(":images/oxygen/ffwd.png"); m_forwardButton = new QPushButton(fwdIcon, "", this); m_forwardButton->setFocusPolicy(Qt::NoFocus); m_forwardButton->setIconSize(QSize(64,64)); m_forwardButton->setAutoFillBackground(false); m_forwardButton->setAutoDefault(false); m_forwardButton->setFlat(true); m_forwardButton->setStyleSheet("background-color: rgba( 255, 255, 255, 0% ); border: 0px;"); m_forwardButton->setAutoRepeat(true); m_forwardButton->setAutoRepeatDelay(200); #if QT_VERSION > 0x050400 m_forwardButton->setShortcut(Qt::Key_MediaNext); #endif toolbuttons->addWidget(m_forwardButton); QIcon lapIcon(":images/oxygen/lap.png"); m_lapButton = new QPushButton(lapIcon, "", this); m_lapButton->setFocusPolicy(Qt::NoFocus); m_lapButton->setIconSize(QSize(64,64)); m_lapButton->setAutoFillBackground(false); m_lapButton->setAutoDefault(false); m_lapButton->setFlat(true); m_lapButton->setStyleSheet("background-color: rgba( 255, 255, 255, 0% ); border: 0px;"); #if QT_VERSION > 0x050400 m_lapButton->setShortcut(Qt::Key_0); #endif toolbuttons->addWidget(m_lapButton); QIcon calIcon(":images/oxygen/cal.png"); cal = new QPushButton(calIcon, "", this); cal->setFocusPolicy(Qt::NoFocus); cal->setIconSize(QSize(64,64)); cal->setAutoFillBackground(false); cal->setAutoDefault(false); cal->setFlat(true); cal->setStyleSheet("background-color: rgba( 255, 255, 255, 0% ); border: 0px;"); #if QT_VERSION > 0x050400 cal->setShortcut(Qt::Key_C); #endif toolbuttons->addWidget(cal); QIcon upIcon(":images/oxygen/up.png"); loadUp = new QPushButton(upIcon, "", this); loadUp->setFocusPolicy(Qt::NoFocus); loadUp->setIconSize(QSize(64,64)); loadUp->setAutoFillBackground(false); loadUp->setAutoDefault(false); loadUp->setFlat(true); loadUp->setAutoRepeat(true); loadUp->setAutoRepeatInterval(50); loadUp->setStyleSheet("background-color: rgba( 255, 255, 255, 0% ); border: 0px;"); #if QT_VERSION > 0x050400 loadUp->setShortcut(Qt::Key_Plus); #endif toolbuttons->addWidget(loadUp); QIcon downIcon(":images/oxygen/down.png"); loadDown = new QPushButton(downIcon, "", this); loadDown->setFocusPolicy(Qt::NoFocus); loadDown->setIconSize(QSize(64,64)); loadDown->setAutoFillBackground(false); loadDown->setAutoDefault(false); loadDown->setFlat(true); loadDown->setAutoRepeat(true); loadDown->setAutoRepeatInterval(50); loadDown->setStyleSheet("background-color: rgba( 255, 255, 255, 0% ); border: 0px;"); #if QT_VERSION > 0x050400 loadDown->setShortcut(Qt::Key_Minus); #endif toolbuttons->addWidget(loadDown); intensitySlider = new QSlider(Qt::Vertical, this); intensitySlider->setAutoFillBackground(false); intensitySlider->setFocusPolicy(Qt::NoFocus); intensitySlider->setMinimum(75); intensitySlider->setMaximum(125); intensitySlider->setValue(100); toolbuttons->addWidget(intensitySlider); // notification area QHBoxLayout *notifications = new QHBoxLayout(); notifications->setSpacing(0); notifications->setContentsMargins(0,0,0,0); notificationText = new QPlainTextEdit(); notifications->addWidget(notificationText); QFont font("Monospace"); font.setStyleHint(QFont::TypeWriter); font.setBold(1); font.setPointSize(14); notificationText->setFont(font); notificationText->setStyleSheet("QPlainTextEdit {background-color: black; color: red}"); notificationText->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); notificationText->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); notificationText->setTextInteractionFlags(Qt::NoTextInteraction); notificationText->setLineWrapMode(QPlainTextEdit::NoWrap); //QCheckBox *hideOnIdle = new QCheckBox(tr("Auto Hide"), this); //intensityControlLayout->addWidget(hideOnIdle); QHBoxLayout *allControlsLayout = new QHBoxLayout(); allControlsLayout->addLayout(toolbuttons); allControlsLayout->addLayout(notifications); connect(m_playButton, SIGNAL(clicked()), m_trainSidebar, SLOT(Start())); connect(m_rewindButton, SIGNAL(clicked()), m_trainSidebar, SLOT(Rewind())); connect(m_forwardButton, SIGNAL(clicked()), m_trainSidebar, SLOT(FFwd())); connect(m_lapButton, SIGNAL(clicked()), m_trainSidebar, SLOT(newLap())); connect(m_stopButton, SIGNAL(clicked()), m_trainSidebar, SLOT(Stop())); connect(m_trainSidebar->context, SIGNAL(start()), this, SLOT(updatePlayButtonIcon())); connect(m_trainSidebar->context, SIGNAL(pause()), this, SLOT(updatePlayButtonIcon())); connect(m_trainSidebar->context, SIGNAL(unpause()), this, SLOT(updatePlayButtonIcon())); connect(m_trainSidebar->context, SIGNAL(stop()), this, SLOT(updatePlayButtonIcon())); //connect(hideOnIdle, SIGNAL(stateChanged(int)), this, SLOT(autoHideCheckboxChanged(int))); connect(m_trainSidebar, SIGNAL(statusChanged(int)), this, SLOT(statusChanged(int))); connect(m_connectButton, SIGNAL(released()), m_trainSidebar, SLOT(toggleConnect())); connect(cal, SIGNAL(clicked()), m_trainSidebar, SLOT(Calibrate())); connect(loadUp, SIGNAL(clicked()), m_trainSidebar, SLOT(Higher())); connect(loadDown, SIGNAL(clicked()), m_trainSidebar, SLOT(Lower())); connect(intensitySlider, SIGNAL(valueChanged(int)), m_trainSidebar, SLOT(adjustIntensity(int))); connect(m_trainSidebar, SIGNAL(intensityChanged(int)), intensitySlider, SLOT(setValue(int))); connect(m_trainSidebar, SIGNAL(setNotification(QString, int)), this, SLOT(setNotification(QString, int))); connect(m_trainSidebar, SIGNAL(clearNotification(void)), this, SLOT(clearNotification(void))); this->setContentsMargins(0,0,0,0); this->setFocusPolicy(Qt::NoFocus); this->setAutoFillBackground(false); this->setStyleSheet("background-color: rgba( 255, 255, 255, 0% ); border: 0px;"); this->setLayout(allControlsLayout); this->installEventFilter(trainSidebar); // Ensure the bottom bar is sized to show 3 lines of notification text // but don't allow it to crop the buttons if smaller font is used.. int buttonHeight = m_connectButton->sizeHint().height(); int notificationHeight = 3 * notificationText->fontMetrics().lineSpacing(); int contentHeight = qMax(buttonHeight, notificationHeight); int layoutMargins = allControlsLayout->contentsMargins().top() + allControlsLayout->contentsMargins().bottom(); // Adding an extra quarter line looks more symmetrical int extra = notificationHeight / 12; this->setFixedHeight(contentHeight + layoutMargins + extra); //qDebug() << "Button height" << buttonHeight; //qDebug() << "Notification line spacing" << notificationText->fontMetrics().lineSpacing(); //qDebug() << "bottombar margins:" << this->contentsMargins(); //qDebug() << "- allControlsLayout margins:" << allControlsLayout->contentsMargins(); //qDebug() << " - toolbuttons margins:" << toolbuttons->contentsMargins(); //qDebug() << " - notifications margins:" << notifications->contentsMargins(); //qDebug() << " - notificationText margins:" << notificationText->contentsMargins(); //notificationText->setPlainText("LINE1\nLINE2\nLINE3"); // Create a timer for notifications, but don't start yet notificationTimer = new QTimer(this); connect(notificationTimer, SIGNAL(timeout()), SLOT(clearNotification())); } void TrainBottom::updatePlayButtonIcon() { static QIcon playIcon(":images/oxygen/play.png"); static QIcon pauseIcon(":images/oxygen/pause.png"); if (m_trainSidebar->currentStatus() & RT_PAUSED) { m_playButton->setIcon(playIcon); } else if (m_trainSidebar->currentStatus() & RT_RUNNING) { m_playButton->setIcon(pauseIcon); } else // Not running or paused means stopped { m_playButton->setIcon(playIcon); } } void TrainBottom::autoHideCheckboxChanged(int state) { emit autoHideChanged(state == Qt::Checked); } void TrainBottom::statusChanged(int status) { static QIcon connectedIcon(":images/oxygen/power-on.png"); static QIcon disconnectedIcon(":images/oxygen/power-off.png"); // not yet connected if ((status&RT_CONNECTED) == 0) { m_connectButton->setIcon(disconnectedIcon); m_connectButton->setEnabled(true); m_playButton->setEnabled(false); m_stopButton->setEnabled(false); m_forwardButton->setEnabled(false); m_rewindButton->setEnabled(false); m_lapButton->setEnabled(false); cal->setEnabled(false); loadUp->setEnabled(false); loadDown->setEnabled(false); intensitySlider->setEnabled(false); return; } // connected, but not running if ((status&RT_CONNECTED) && ((status&RT_RUNNING) == 0)) { m_connectButton->setIcon(connectedIcon); m_connectButton->setEnabled(true); m_playButton->setEnabled(true); m_stopButton->setEnabled(false); m_forwardButton->setEnabled(false); m_rewindButton->setEnabled(false); m_lapButton->setEnabled(false); cal->setEnabled(false); loadUp->setEnabled(false); loadDown->setEnabled(false); intensitySlider->setEnabled(false); return; } // paused - important to check for paused before running if (status&RT_PAUSED) { m_connectButton->setIcon(connectedIcon); m_connectButton->setEnabled(false); m_playButton->setEnabled(true); m_stopButton->setEnabled(true); m_forwardButton->setEnabled(false); m_rewindButton->setEnabled(false); m_lapButton->setEnabled(false); cal->setEnabled(false); loadUp->setEnabled(false); loadDown->setEnabled(false); intensitySlider->setEnabled(false); return; } // running & calibrating if ((status&RT_CALIBRATING) && (status&RT_RUNNING)) { m_connectButton->setIcon(connectedIcon); m_connectButton->setEnabled(false); m_playButton->setEnabled(false); m_stopButton->setEnabled(true); m_forwardButton->setEnabled(false); m_rewindButton->setEnabled(false); m_lapButton->setEnabled(false); cal->setEnabled(true); loadUp->setEnabled(false); loadDown->setEnabled(false); intensitySlider->setEnabled(false); return; } // running if (status&RT_RUNNING) { m_connectButton->setIcon(connectedIcon); m_connectButton->setEnabled(false); m_playButton->setEnabled(true); m_stopButton->setEnabled(true); m_forwardButton->setEnabled(true); m_rewindButton->setEnabled(true); m_lapButton->setEnabled(true); cal->setEnabled(true); loadUp->setEnabled(true); loadDown->setEnabled(true); intensitySlider->setEnabled(true); return; } } void TrainBottom::setNotification(QString msg, int timeout) { if (timeout > 0) { notificationTimer->setInterval(timeout * 1000); notificationTimer->setSingleShot(true); notificationTimer->start(); } else { // stop any running timer notificationTimer->stop(); } notificationText->clear(); notificationText->setPlainText(msg); } void TrainBottom::clearNotification(void) { notificationText->clear(); }