hydrogen 1.2.3
ShotList.cpp
Go to the documentation of this file.
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 * Copyright(c) 2008-2024 The hydrogen development team [hydrogen-devel@lists.sourceforge.net]
5 *
6 * http://www.hydrogen-music.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY, without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses
20 *
21 */
22
23#include <core/Hydrogen.h>
24#include <core/EventQueue.h>
25
26#include "ShotList.h"
27#include "HydrogenApp.h"
28
29ShotList::ShotList( QString sShotsFilename ) {
30 QFile shots( sShotsFilename );
31 m_nNextShot = 0;
32
33 if ( ! shots.open( QIODevice::ReadOnly ) ) {
34 ___ERRORLOG( QString( "Cannot open shot list file '%1' " ).arg( shots.fileName() ) );
35 return;
36 }
37 while (! shots.atEnd() ) {
38 m_shots << shots.readLine();
39 }
40
42}
43
44ShotList::ShotList( QStringList shots ) {
45 m_shots = shots;
46
48}
49
51 if ( auto pHydrogenApp = HydrogenApp::get_instance() ) {
52 pHydrogenApp->removeEventListener( this );
53 }
54}
55
56QWidget *ShotList::findWidgetInheriting( QObject *pObject, QString &sName ) {
57 if ( pObject->inherits( sName.toLocal8Bit().data() ) ) {
58 return dynamic_cast< QWidget *>( pObject );
59 }
60 for ( QObject *pC : pObject->children() ) {
61 QWidget *pW = findWidgetInheriting( pC, sName );
62 if ( pW ) {
63 return pW;
64 }
65 }
66 return nullptr;
67}
68
69QWidget *ShotList::findWidget( QString &sName ) {
70 for ( QWidget * pTop : QApplication::topLevelWidgets() ) {
71
72 QWidget *pWidget = pTop->findChild< QWidget *>( sName );
73 if ( !pWidget && pTop->objectName() == sName ) {
74 pWidget = dynamic_cast< QWidget *>( pTop );
75 }
76 if ( !pWidget ) {
77 pWidget = findWidgetInheriting( pTop, sName );
78 }
79 if ( pWidget ) {
80 return pWidget;
81 }
82 }
83 return nullptr;
84}
85
86void ShotList::shoot( QString s ) {
87 ___INFOLOG( QString( "Taking shot: %1" ).arg( s.trimmed() ) );
88 QStringList words = s.trimmed().split( QRegExp( "\\s+" ) );
89 if ( s.size() == 0 ) {
90 return;
91 }
92 QString sCmd = words[ 0 ];
93
94 if ( sCmd.startsWith( "#" ) || sCmd == "" ) {
95 // Empty line or "#" to start a comment
96 } else if ( sCmd.compare( "fin", Qt::CaseInsensitive) == 0 ) {
97 // Finish the shot list and quit Hydrogen
98
99 // Since the shot lists do also toggle some buttons that mark
100 // the overall song modified, we need to discard the flag in
101 // order to avoid a popup dialog.
103
104 QTimer::singleShot( 1, QApplication::instance(), &QApplication::closeAllWindows );
105 } else if ( sCmd.compare( "dump", Qt::CaseInsensitive) == 0 ) {
106 // Dump object tree for debugging
107 for ( QWidget *pTop : QApplication::topLevelWidgets() ) {
108 pTop->dumpObjectTree();
109 }
110 } else if ( sCmd.compare( "grab", Qt::CaseInsensitive ) == 0 ) {
111
112 if ( words.size() < 2 ) {
113 ___ERRORLOG( QString( "Syntax: grab <widget> [as <filename>] [size w d] [offset x y ]." ) );
114 } else {
115 words.pop_front();
116 QString sWidgetName = words[0];
117 words.pop_front();
118 QRect rect( 0, 0, -1, -1 );
119 QString sFileName = QString( "%1.png" ).arg( sWidgetName );
120 while ( !words.empty() ) {
121 if ( words[0] == "as" ) {
122 words.pop_front();
123 if ( words.size() < 1 ) {
124 ___ERRORLOG( QString( "Syntax: grab ... as <filename>" ) );
125 } else {
126 sFileName = words[0];
127 words.pop_front();
128 }
129 } else if ( words[0] == "size" ) {
130 words.pop_front();
131 if ( words.size() < 2 ) {
132 ___ERRORLOG( QString( "Syntax: grab ... size <width> <height>" ) );
133 } else {
134 rect.setWidth( words[0].toInt() );
135 rect.setHeight( words[1].toInt() );
136 words.pop_front();
137 words.pop_front();
138 }
139 } else if ( words[0] == "offset" ) {
140 words.pop_front();
141 if ( words.size() < 2 ) {
142 ___ERRORLOG( QString( "Syntax: grab ... offset <width> <height>" ) );
143 } else {
144 rect.setX( words[0].toInt() );
145 rect.setY( words[1].toInt() );
146 words.pop_front();
147 words.pop_front();
148 }
149 } else {
150 ___ERRORLOG( QString( "Syntax: grab <widget> [as <filename>] [size w d] [offset x y ]."
151 " Unexpected '%1'" ).arg( words[0] ) );
152 break;
153 }
154 }
155
156 QWidget *pWidget = findWidget( sWidgetName );
157 if ( pWidget ) {
158 QPixmap p = pWidget->grab();
159 QRect oldRect = rect;
160 // Scale 'rect' up to match device pixels of pixmap
161 rect = QRect( rect.topLeft() * p.devicePixelRatio(),
162 rect.size() * p.devicePixelRatio() );
163 if ( rect.width() <= 0 ) {
164 rect.setWidth( p.rect().width() );
165 }
166 if ( rect.height() <= 0 ) {
167 rect.setHeight( p.rect().height() );
168 }
169 QRect grabRect = rect.intersected( p.rect() );
170 p.copy( grabRect ).save( sFileName );
171 ___INFOLOG( QString( "Saved grabbed widget %1" ).arg( sFileName ) );
172 } else {
173 ___ERRORLOG( QString( "Couldn't find widget named '%1' to grab" ).arg( sWidgetName ) );
174 }
175 }
176
177 } else if ( sCmd.compare( "slot", Qt::CaseInsensitive ) == 0 ) {
178
179 if ( words.size() >= 3 ) {
180 QString sWidgetName = words[ 1 ];
181 QString sMethodName = words[ 2 ];
182 QWidget *pWidget = findWidget( sWidgetName );
183
184 if ( pWidget ) {
185 ___INFOLOG( QString( "Invoking '%1' on '%2'" ).arg( sMethodName, sWidgetName ) );
186 bool bSuccess = false;
187 switch ( words.size() ) {
188 case 3:
189 bSuccess = QMetaObject::invokeMethod( pWidget, sMethodName.toLocal8Bit().data(), Qt::DirectConnection );
190 break;
191 case 4:
192 bSuccess = QMetaObject::invokeMethod( pWidget, sMethodName.toLocal8Bit().data(), Qt::DirectConnection,
193 Arg( words[3] ) );
194 break;
195 case 5:
196 bSuccess = QMetaObject::invokeMethod( pWidget, sMethodName.toLocal8Bit().data(), Qt::DirectConnection,
197 Arg( words[3] ), Arg( words[4] ) );
198 break;
199 case 6:
200 bSuccess = QMetaObject::invokeMethod( pWidget, sMethodName.toLocal8Bit().data(), Qt::DirectConnection,
201 Arg( words[3] ), Arg( words[4] ), Arg( words[5] ) );
202 break;
203 default:
204 ___ERRORLOG( "Unsupported number of arguments in %0" );
205 }
206
207 if ( !bSuccess ) {
208 ___ERRORLOG( QString( "Couldn't invoke '%1' on '%2'" )
209 .arg( sMethodName, sWidgetName ) );
210 } else {
211 ___INFOLOG( "OK" );
212 }
213 } else {
214 ___ERRORLOG( QString( "Couldn't find widget named '%1' to invoke '%2' on" )
215 .arg( sWidgetName, sMethodName ) );
216 }
217 } else {
218 ___ERRORLOG( QString( "Syntax: slot <widget> <method> [args]" ) );
219 }
220 } else {
221 ___ERRORLOG( QString("Unknown command '%1'").arg( sCmd ) );
222 }
223}
224
226 m_nNextShot = 0;
227 if ( m_shots.size() != 0 ) {
228 nextShot();
229 }
230}
231
233 QMetaObject::invokeMethod( this, "nextShot", Qt::QueuedConnection );
234}
235
236void ShotList::nextShot( void ) {
237 if ( ( m_nNextShot + 1) < m_shots.size() ) {
239 }
240 shoot( m_shots[ m_nNextShot++ ] );
241}
#define ___INFOLOG(x)
Definition Object.h:255
#define ___ERRORLOG(x)
Definition Object.h:257
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
Definition EventQueue.h:224
void push_event(const EventType type, const int nValue)
Queues the next event into the EventQueue.
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
void setIsModified(bool bIsModified)
Wrapper around Song::setIsModified() that checks whether a song is set.
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
Buffer for construction of Q_ARGs.
Definition ShotList.h:59
void nextShotEvent() override
Definition ShotList.cpp:232
QStringList m_shots
Definition ShotList.h:91
ShotList(QStringList shots)
Definition ShotList.cpp:44
void shoot()
Definition ShotList.cpp:225
void nextShot(void)
Definition ShotList.cpp:236
int m_nNextShot
Definition ShotList.h:92
static QWidget * findWidget(QString &sName)
Find a widget by name.
Definition ShotList.cpp:69
static QWidget * findWidgetInheriting(QObject *pObject, QString &sName)
Find a widget which inherits the named class.
Definition ShotList.cpp:56
@ EVENT_NEXT_SHOT
Definition EventQueue.h:177