Mixxx
|
00001 /*************************************************************************** 00002 wpushbutton.cpp - description 00003 ------------------- 00004 begin : Fri Jun 21 2002 00005 copyright : (C) 2002 by Tue & Ken Haste Andersen 00006 email : haste@diku.dk 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include "wpushbutton.h" 00019 #include "wpixmapstore.h" 00020 #include "controlobject.h" 00021 #include "controlpushbutton.h" 00022 //Added by qt3to4: 00023 #include <QPixmap> 00024 #include <QtDebug> 00025 #include <QMouseEvent> 00026 #include <QPaintEvent> 00027 00028 WPushButton::WPushButton(QWidget * parent) : WWidget(parent) 00029 { 00030 m_pPixmaps = 0; 00031 m_pPixmapBack = 0; 00032 setStates(0); 00033 //setBackgroundMode(Qt::NoBackground); //obsolete? removal doesn't seem to change anything on the GUI --kousu 2009/03 00034 } 00035 00036 WPushButton::~WPushButton() 00037 { 00038 for (int i = 0; i < 2*m_iNoStates; i++) { 00039 WPixmapStore::deletePixmap(m_pPixmaps[i]); 00040 } 00041 00042 delete [] m_pPixmaps; 00043 00044 WPixmapStore::deletePixmap(m_pPixmapBack); 00045 } 00046 00047 void WPushButton::setup(QDomNode node) 00048 { 00049 // Number of states 00050 int iNumStates = selectNodeInt(node, "NumberStates"); 00051 setStates(iNumStates); 00052 00053 // Set background pixmap if available 00054 if (!selectNode(node, "BackPath").isNull()) 00055 setPixmapBackground(getPath(selectNodeQString(node, "BackPath"))); 00056 00057 // Load pixmaps for associated states 00058 QDomNode state = selectNode(node, "State"); 00059 while (!state.isNull()) 00060 { 00061 if (state.isElement() && state.nodeName() == "State") 00062 { 00063 setPixmap(selectNodeInt(state, "Number"), true, getPath(selectNodeQString(state, "Pressed"))); 00064 setPixmap(selectNodeInt(state, "Number"), false, getPath(selectNodeQString(state, "Unpressed"))); 00065 } 00066 state = state.nextSibling(); 00067 } 00068 00069 m_bLeftClickForcePush = false; 00070 if (selectNodeQString(node, "LeftClickIsPushButton").contains("true", Qt::CaseInsensitive)) 00071 m_bLeftClickForcePush = true; 00072 00073 m_bRightClickForcePush = false; 00074 if (selectNodeQString(node, "RightClickIsPushButton").contains("true", Qt::CaseInsensitive)) 00075 m_bRightClickForcePush = true; 00076 00077 //-------- 00078 //This next big block allows each ControlPushButton to know whether or not it's 00079 //a "toggle" button. 00080 00081 // For each connection 00082 QDomNode con = selectNode(node, "Connection"); 00083 while (!con.isNull()) 00084 { 00085 // Get ConfigKey 00086 QString key = selectNodeQString(con, "ConfigKey"); 00087 00088 ConfigKey configKey; 00089 configKey.group = key.left(key.indexOf(",")); 00090 configKey.item = key.mid(key.indexOf(",")+1); 00091 00092 //Find out if we're a push button... 00093 if (node.nodeName() == "PushButton") 00094 { 00095 ControlPushButton* p = dynamic_cast<ControlPushButton*>( 00096 ControlObject::getControl(configKey)); 00097 00098 if (p == NULL) { 00099 // A NULL here either means that this control is not a 00100 // ControlPushButton or it does not exist. This logic is 00101 // specific to push-buttons, so skip it either way. 00102 con = con.nextSibling(); 00103 continue; 00104 } 00105 00106 bool isLeftButton = false; 00107 bool isRightButton = false; 00108 if (!selectNode(con, "ButtonState").isNull()) 00109 { 00110 if (selectNodeQString(con, "ButtonState").contains("LeftButton", Qt::CaseInsensitive)) { 00111 isLeftButton = true; 00112 } 00113 else if (selectNodeQString(con, "ButtonState").contains("RightButton", Qt::CaseInsensitive)) { 00114 isRightButton = true; 00115 } 00116 } 00117 00118 // If we have 2 states, tell my controlpushbutton object that we're 00119 // a toggle button. Only set the control as a toggle button if it 00120 // has not been forced to remain a push button by the 00121 // Right/LeftClickIsPushButton directive above. Do this by checking 00122 // whether this control is mapped to the RightButton or LeftButton 00123 // and check it against the value of m_bLeft/RightClickForcePush. We 00124 // have to handle the case where no ButtonState is provided for the 00125 // control. If no button is provided, then we have to assume the 00126 // connected control should be a toggle. 00127 00128 //bool setAsToggleButton = iNumStates == 2 && 00129 // ((!isLeftButton && !isRightButton) || 00130 // ( (isLeftButton && !m_bLeftClickForcePush) || 00131 // (isRightButton && !m_bRightClickForcePush) ) ); 00132 00133 // if (setAsToggleButton) 00134 // p->setToggleButton(true); 00135 00136 // BJW: Removed this so that buttons that are hardcoded as toggle in the source 00137 // don't get overridden if a skin fails to set them to 2-state. Buttons still 00138 // default to non-toggle otherwise. 00139 // else 00140 // p->setToggleButton(false); 00141 } 00142 00143 con = con.nextSibling(); 00144 } 00145 00146 //End of toggle button stuff. 00147 //-------- 00148 } 00149 00150 void WPushButton::setStates(int iStates) 00151 { 00152 m_iNoStates = iStates; 00153 m_fValue = 0.; 00154 m_bPressed = false; 00155 00156 // If pixmap array is already allocated, delete it 00157 delete [] m_pPixmaps; 00158 m_pPixmaps = NULL; 00159 00160 if (iStates>0) 00161 { 00162 m_pPixmaps = new QPixmap*[2*m_iNoStates]; 00163 for (int i=0; i<2*m_iNoStates; ++i) 00164 m_pPixmaps[i] = 0; 00165 } 00166 } 00167 00168 void WPushButton::setPixmap(int iState, bool bPressed, const QString &filename) 00169 { 00170 int pixIdx = (iState*2)+bPressed; 00171 m_pPixmaps[pixIdx] = WPixmapStore::getPixmap(filename); 00172 if (!m_pPixmaps[pixIdx]) 00173 qDebug() << "WPushButton: Error loading pixmap:" << filename; 00174 00175 // Set size of widget equal to pixmap size 00176 setFixedSize(m_pPixmaps[pixIdx]->size()); 00177 } 00178 00179 void WPushButton::setPixmapBackground(const QString &filename) 00180 { 00181 // Load background pixmap 00182 m_pPixmapBack = WPixmapStore::getPixmap(filename); 00183 if (!m_pPixmapBack) 00184 qDebug() << "WPushButton: Error loading background pixmap:" << filename; 00185 } 00186 00187 void WPushButton::setValue(double v) 00188 { 00189 m_fValue = v; 00190 00191 if (m_iNoStates==1) 00192 { 00193 if (m_fValue==1.) 00194 m_bPressed = true; 00195 else 00196 m_bPressed = false; 00197 } 00198 00199 update(); 00200 } 00201 00202 void WPushButton::paintEvent(QPaintEvent *) 00203 { 00204 if (m_iNoStates>0) 00205 { 00206 int idx = (((int)m_fValue%m_iNoStates)*2)+m_bPressed; 00207 if (m_pPixmaps[idx]) 00208 { 00209 QPainter p(this); 00210 if(m_pPixmapBack) p.drawPixmap(0, 0, *m_pPixmapBack); 00211 p.drawPixmap(0, 0, *m_pPixmaps[idx]); 00212 } 00213 } 00214 } 00215 00216 void WPushButton::mousePressEvent(QMouseEvent * e) 00217 { 00218 m_bPressed = true; 00219 00220 bool leftClick = e->button() == Qt::LeftButton; 00221 bool rightClick = e->button() == Qt::RightButton; 00222 00223 // The value to emit. 00224 double emitValue = m_fValue; 00225 00226 // Calculate new state if it is a one state button 00227 if (m_iNoStates == 1) { 00228 m_fValue = emitValue = (m_fValue == 0.0f) ? 1.0f : 0.0f; 00229 } 00230 // Update state on press if it is a n-state button and not a pushbutton 00231 else if (leftClick) { 00232 if (m_bLeftClickForcePush) { 00233 emitValue = 1.0f; 00234 } else { 00235 m_fValue = emitValue = (int)(m_fValue+1.)%m_iNoStates; 00236 } 00237 } 00238 00239 // Do not allow right-clicks to change the state of the button. This is how 00240 // Mixxx <1.8.0 worked so keep it that way. For a multi-state button, really 00241 // only one click type (left/right) should be able to change the state. One 00242 // problem with this is that you can get the button out of sync with its 00243 // underlying control. For example the PFL buttons on Jus's skins could get 00244 // out of sync with the button state. rryan 9/2010 00245 00246 // else if (rightClick) { 00247 // if (m_bRightClickForcePush) { 00248 // emitValue = 1.0f; 00249 // } else { 00250 // m_fValue = emitValue = (int)(m_fValue+1.)%m_iNoStates; 00251 // } 00252 // } 00253 00254 if (leftClick) { 00255 emit(valueChangedLeftDown(emitValue)); 00256 } else if (rightClick) { 00257 emit(valueChangedRightDown(emitValue)); 00258 } 00259 00260 update(); 00261 } 00262 00263 void WPushButton::focusOutEvent(QFocusEvent* e) { 00264 m_bPressed = false; 00265 update(); 00266 } 00267 00268 void WPushButton::mouseReleaseEvent(QMouseEvent * e) 00269 { 00270 m_bPressed = false; 00271 00272 bool leftClick = e->button() == Qt::LeftButton; 00273 bool rightClick = e->button() == Qt::RightButton; 00274 00275 // The value to emit 00276 double emitValue = m_fValue; 00277 00278 // Update state if it is a one state button. 00279 if (m_iNoStates==1) // && e->button()==Qt::LeftButton) 00280 { 00281 m_fValue = emitValue = (m_fValue == 0.0f) ? 1.0f : 0.0f; 00282 } else if ((leftClick && m_bLeftClickForcePush) || (rightClick && m_bRightClickForcePush)) { 00283 emitValue = 0.0f; 00284 } 00285 00286 if (leftClick) { 00287 emit(valueChangedLeftUp(emitValue)); 00288 } else if (rightClick) { 00289 emit(valueChangedRightUp(emitValue)); 00290 } 00291 00292 update(); 00293 }