root/trunk/gui/src/SongEditor/SongEditor.cpp @ 285

Revision 285, 38.1 KB (checked in by wolke, 5 years ago)

code cleanup

Line 
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 *
5 * http://www.hydrogen-music.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY, without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 *
21 */
22
23#include <QtGui>
24
25#include <assert.h>
26#include <algorithm>
27
28#include <hydrogen/Song.h>
29#include <hydrogen/hydrogen.h>
30#include <hydrogen/Preferences.h>
31#include <hydrogen/Pattern.h>
32#include <hydrogen/audio_engine.h>
33#include <hydrogen/event_queue.h>
34using namespace H2Core;
35
36
37#include "SongEditor.h"
38#include "SongEditorPanel.h"
39#include "../PatternEditor/PatternEditorPanel.h"
40#include "../HydrogenApp.h"
41#include "../InstrumentRack.h"
42#include "../widgets/Button.h"
43#include "../PatternFillDialog.h"
44#include "../PatternPropertiesDialog.h"
45#include "../SongPropertiesDialog.h"
46#include "../Skin.h"
47#include <hydrogen/LocalFileMng.h>
48
49
50SongEditor::SongEditor( QWidget *parent )
51 : QWidget( parent )
52 , Object( "SongEditor" )
53 , m_bSequenceChanged( true )
54 , m_bIsMoving( false )
55 , m_bShowLasso( false )
56{
57        setAttribute(Qt::WA_NoBackground);
58        setFocusPolicy (Qt::StrongFocus);
59
60        m_nGridWidth = 16;
61        m_nGridHeight = 18;
62
63        int m_nInitialWidth = 10 + m_nMaxPatternSequence * m_nGridWidth;
64        int m_nInitialHeight = 10;
65
66        this->resize( QSize(m_nInitialWidth, m_nInitialHeight) );
67
68        createBackground();     // create m_backgroundPixmap pixmap
69
70        update();
71}
72
73
74
75SongEditor::~SongEditor()
76{
77}
78
79
80
81int SongEditor::getGridWidth ()
82{
83        return m_nGridWidth;
84}
85
86
87
88void SongEditor::setGridWidth( uint width )
89{
90        if ( ( SONG_EDITOR_MIN_GRID_WIDTH <= width ) && ( SONG_EDITOR_MAX_GRID_WIDTH >= width ) ) {
91                m_nGridWidth = width;
92                this->resize ( 10 + m_nMaxPatternSequence * m_nGridWidth, height() );
93        }
94}
95
96
97
98void SongEditor::keyPressEvent ( QKeyEvent * ev )
99{
100        Hydrogen *pEngine = Hydrogen::get_instance();
101        PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
102        vector<PatternList*>* pColumns = pEngine->getSong()->get_pattern_group_vector();
103
104        if ( ev->key() == Qt::Key_Delete ) {
105                if ( m_selectedCells.size() != 0 ) {
106                        AudioEngine::get_instance()->lock( "SongEditor::keyPressEvent" );
107                        // delete all selected cells
108                        for ( uint i = 0; i < m_selectedCells.size(); i++ ) {
109                                QPoint cell = m_selectedCells[ i ];
110                                PatternList* pColumn = (*pColumns)[ cell.x() ];
111                                pColumn->del(pPatternList->get( cell.y() ) );
112                        }
113                        AudioEngine::get_instance()->unlock();
114
115                        m_selectedCells.clear();
116                        m_bSequenceChanged = true;
117                        update();
118                }
119                return;
120        }
121
122        ev->ignore();
123}
124
125
126
127void SongEditor::mousePressEvent( QMouseEvent *ev )
128{
129        if ( ev->x() < 10 ) {
130                return;
131        }
132        WARNINGLOG( "editor-pressed" );
133
134        int nRow = ev->y() / m_nGridHeight;
135        int nColumn = ( (int)ev->x() - 10 ) / (int)m_nGridWidth;
136
137        if ( ev->modifiers() == Qt::ControlModifier ) {
138                INFOLOG( "[mousePressEvent] CTRL pressed!" );
139                m_bIsCtrlPressed = true;
140        }
141        else {
142                m_bIsCtrlPressed = false;
143        }
144
145        Hydrogen *pEngine = Hydrogen::get_instance();
146        Song *pSong = pEngine->getSong();
147        PatternList *pPatternList = pSong->get_pattern_list();
148
149        // don't lock the audio driver before checking that...
150        if ( nRow >= (int)pPatternList->get_size() || nRow < 0 || nColumn < 0 ) { return; }
151        AudioEngine::get_instance()->lock( "SongEditor::mousePressEvent" );
152
153
154        SongEditorActionMode actionMode = HydrogenApp::getInstance()->getSongEditorPanel()->getActionMode();
155        if ( actionMode == SELECT_ACTION ) {
156
157                bool bOverExistingPattern = false;
158                for ( uint i = 0; i < m_selectedCells.size(); i++ ) {
159                        QPoint cell = m_selectedCells[ i ];
160                        if ( cell.x() == nColumn && cell.y() == nRow ) {
161                                bOverExistingPattern = true;
162                                break;
163                        }
164                }
165
166                if ( bOverExistingPattern ) {
167                        // MOVE PATTERNS
168//                      INFOLOG( "[mousePressEvent] Move patterns" );
169                        m_bIsMoving = true;
170                        m_bShowLasso = false;
171                        m_movingCells = m_selectedCells;
172
173                        m_clickPoint.setX( nColumn );
174                        m_clickPoint.setY( nRow );
175                }
176                else {
177//                      INFOLOG( "[mousePressEvent] Select patterns" );
178                        // select patterns
179                        m_bShowLasso = true;
180                        m_lasso.setCoords( ev->x(), ev->y(), ev->x(), ev->y() );
181                        setCursor( QCursor( Qt::CrossCursor ) );
182                        m_selectedCells.clear();
183                        m_selectedCells.push_back( QPoint( nColumn, nRow ) );
184                }
185        }
186        else if ( actionMode == DRAW_ACTION ) {
187                H2Core::Pattern *pPattern = pPatternList->get( nRow );
188                vector<PatternList*> *pColumns = pSong->get_pattern_group_vector();     // E' la lista di "colonne" di pattern
189                if ( nColumn < (int)pColumns->size() ) {
190                        PatternList *pColumn = ( *pColumns )[ nColumn ];
191
192                        bool bFound = false;
193                        unsigned nColumnIndex = 0;
194                        for ( nColumnIndex = 0; nColumnIndex < pColumn->get_size(); nColumnIndex++) {
195                                if ( pColumn->get( nColumnIndex ) == pPattern ) { // il pattern e' gia presente
196                                        bFound = true;
197                                        break;
198                                }
199                        }
200
201                        if ( bFound ) {
202                                // DELETE PATTERN
203//                              INFOLOG( "[mousePressEvent] delete pattern" );
204                                pColumn->del( nColumnIndex );
205
206                                // elimino le colonne vuote
207                                for ( int i = pColumns->size() - 1; i >= 0; i-- ) {
208                                        PatternList *pColumn = ( *pColumns )[ i ];
209                                        if ( pColumn->get_size() == 0 ) {
210                                                pColumns->erase( pColumns->begin() + i );
211                                                delete pColumn;
212                                        }
213                                        else {
214                                                break;
215                                        }
216                                }
217                        }
218                        else {
219                                if ( nColumn < (int)pColumns->size() ) {
220                                        // ADD PATTERN
221//                                      INFOLOG( "[mousePressEvent] add pattern" );
222                                        m_selectedCells.clear();
223                                        pColumn->add( pPattern );
224                                }
225                        }
226                }
227                else {
228                        // ADD PATTERN (with spaces..)
229                        m_selectedCells.clear();
230                        int nSpaces = nColumn - pColumns->size();
231//                      INFOLOG( "[mousePressEvent] add pattern (with " + to_string( nSpaces ) + " spaces)" );
232
233                        PatternList *pColumn = new PatternList();
234                        pColumns->push_back( pColumn );
235
236                        for ( int i = 0; i < nSpaces; i++ ) {
237                                pColumn = new PatternList();
238                                pColumns->push_back( pColumn );
239                        }
240                        pColumn->add( pPattern );
241                }
242                pSong->__is_modified = true;
243        }
244
245        AudioEngine::get_instance()->unlock();
246
247        // update
248        m_bSequenceChanged = true;
249        update();
250}
251
252
253
254void SongEditor::mouseMoveEvent(QMouseEvent *ev)
255{
256        int nRow = ev->y() / m_nGridHeight;
257        int nColumn = ( (int)ev->x() - 10 ) / (int)m_nGridWidth;
258        PatternList *pPatternList = Hydrogen::get_instance()->getSong()->get_pattern_list();
259        vector<PatternList*>* pColumns = Hydrogen::get_instance()->getSong()->get_pattern_group_vector();
260
261        if ( m_bIsMoving ) {
262//              WARNINGLOG( "[mouseMoveEvent] Move patterns not implemented yet" );
263
264                int nRowDiff = nRow  - m_clickPoint.y();
265                int nColumnDiff = nColumn - m_clickPoint.x();
266
267//              INFOLOG( "[mouseMoveEvent] row diff: "+ to_string( nRowDiff ) );
268//              INFOLOG( "[mouseMoveEvent] col diff: "+ to_string( nColumnDiff ) );
269
270                for ( int i = 0; i < (int)m_movingCells.size(); i++ ) {
271                        QPoint cell = m_movingCells[ i ];
272                        m_movingCells[ i ].setX( m_selectedCells[ i ].x() + nColumnDiff );
273                        m_movingCells[ i ].setY( m_selectedCells[ i ].y() + nRowDiff );
274                }
275
276                m_bSequenceChanged = true;
277                update();
278                return;
279        }
280
281        if ( m_bShowLasso ) {
282                // SELECTION
283                setCursor( QCursor( Qt::CrossCursor ) );
284                int x = ev->x();
285                int y = ev->y();
286                if ( x < 0 ) {
287                        x = 0;
288                }
289                if ( y < 0 ) {
290                        y = 0;
291                }
292                m_lasso.setBottomRight( QPoint( x, y ) );
293
294                // aggiorno la lista di celle selezionate
295                m_selectedCells.clear();
296
297                int nStartColumn = (int)( ( m_lasso.left() - 10.0 ) / m_nGridWidth );
298                int nEndColumn = nColumn;
299                if ( nStartColumn > nEndColumn ) {
300                        int nTemp = nEndColumn;
301                        nEndColumn = nStartColumn;
302                        nStartColumn = nTemp;
303                }
304
305                int nStartRow = m_lasso.top() / m_nGridHeight;
306                int nEndRow = nRow;
307                if ( nStartRow > nEndRow ) {
308                        int nTemp = nEndRow;
309                        nEndRow = nStartRow;
310                        nStartRow = nTemp;
311                }
312
313                for ( int nRow = nStartRow; nRow <= nEndRow; nRow++ ) {
314                        for ( int nCol = nStartColumn; nCol <= nEndColumn; nCol++ ) {
315                                if ( nRow >= (int)pPatternList->get_size() || nRow < 0 || nCol < 0 ) {
316                                        return;
317                                }
318                                H2Core::Pattern *pPattern = pPatternList->get( nRow );
319
320                                if ( nCol < (int)pColumns->size() ) {
321                                        PatternList *pColumn = ( *pColumns )[ nCol ];
322
323                                        for ( uint i = 0; i < pColumn->get_size(); i++) {
324                                                if ( pColumn->get(i) == pPattern ) { // esiste un pattern in questa posizione
325                                                        m_selectedCells.push_back( QPoint( nCol, nRow ) );
326                                                }
327                                        }
328                                }
329                        }
330                }
331
332                m_bSequenceChanged = true;
333                update();
334        }
335
336}
337
338
339
340void SongEditor::mouseReleaseEvent( QMouseEvent *ev )
341{
342        UNUSED( ev );
343//      INFOLOG( "[mouseReleaseEvent]" );
344
345        Hydrogen *pEngine = Hydrogen::get_instance();
346
347        PatternList *pPatternList = pEngine->getSong()->get_pattern_list();
348        vector<PatternList*>* pColumns = pEngine->getSong()->get_pattern_group_vector();
349
350        if ( m_bIsMoving ) {    // fine dello spostamento dei pattern
351                AudioEngine::get_instance()->lock( "SongEditor::mouseReleaseEvent" );
352                // create the new patterns
353                for ( uint i = 0; i < m_movingCells.size(); i++ ) {
354                        QPoint cell = m_movingCells[ i ];
355                        if ( cell.x() < 0 || cell.y() < 0 || cell.y() >= (int)pPatternList->get_size() ) {
356                                // skip
357                                continue;
358                        }
359                        // aggiungo un pattern per volta
360                        PatternList* pColumn = NULL;
361                        if ( cell.x() < (int)pColumns->size() ) {
362                                pColumn = (*pColumns)[ cell.x() ];
363                        }
364                        else {
365                                // creo dei patternlist vuoti
366                                int nSpaces = cell.x() - pColumns->size();
367                                for ( int i = 0; i <= nSpaces; i++ ) {
368                                        pColumn = new PatternList();
369                                        pColumns->push_back( pColumn );
370                                }
371                        }
372                        pColumn->add( pPatternList->get( cell.y() ) );
373                }
374
375                if ( m_bIsCtrlPressed ) {       // COPY
376                }
377                else {  // MOVE
378                        // remove the old patterns
379                        for ( uint i = 0; i < m_selectedCells.size(); i++ ) {
380                                QPoint cell = m_selectedCells[ i ];
381                                PatternList* pColumn = NULL;
382                                if ( cell.x() < (int)pColumns->size() ) {
383                                        pColumn = (*pColumns)[ cell.x() ];
384                                }
385                                else {
386                                        pColumn = new PatternList();
387                                        pColumns->push_back( pColumn );
388                                }
389                                pColumn->del(pPatternList->get( cell.y() ) );
390                        }
391                }
392
393                // remove the empty patternlist at the end of the song
394                for ( int i = pColumns->size() - 1; i != 0 ; i-- ) {
395                        PatternList *pList = (*pColumns)[ i ];
396                        int nSize = pList->get_size();
397                        if ( nSize == 0 ) {
398                                pColumns->erase( pColumns->begin() + i );
399                                delete pList;
400                        }
401                        else {
402                                break;
403                        }
404                }
405
406
407                pEngine->getSong()->__is_modified = true;
408                AudioEngine::get_instance()->unlock();
409
410                m_bIsMoving = false;
411                m_movingCells.clear();
412                m_selectedCells.clear();
413        }
414
415        setCursor( QCursor( Qt::ArrowCursor ) );
416
417        m_bShowLasso = false;
418        m_bSequenceChanged = true;
419        m_bIsCtrlPressed = false;
420        update();
421}
422
423
424
425void SongEditor::paintEvent( QPaintEvent *ev )
426{
427/*      INFOLOG(
428                        "[paintEvent] x: " + to_string( ev->rect().x() ) +
429                        " y: " + to_string( ev->rect().y() ) +
430                        " w: " + to_string( ev->rect().width() ) +
431                        " h: " + to_string( ev->rect().height() )
432        );
433*/
434
435        // ridisegno tutto solo se sono cambiate le note
436        if (m_bSequenceChanged) {
437                m_bSequenceChanged = false;
438                drawSequence();
439        }
440
441        QPainter painter(this);
442        painter.drawPixmap( ev->rect(), *m_pSequencePixmap, ev->rect() );
443
444        if ( m_bShowLasso ) {
445                QPen pen( Qt::white );
446                pen.setStyle( Qt::DotLine );
447                painter.setPen( pen );
448                painter.drawRect( m_lasso );
449        }
450}
451
452
453
454void SongEditor::createBackground()
455{
456        UIStyle *pStyle = Preferences::getInstance()->getDefaultUIStyle();
457        QColor backgroundColor( pStyle->m_songEditor_backgroundColor.getRed(), pStyle->m_songEditor_backgroundColor.getGreen(), pStyle->m_songEditor_backgroundColor.getBlue() );
458        QColor alternateRowColor( pStyle->m_songEditor_alternateRowColor.getRed(), pStyle->m_songEditor_alternateRowColor.getGreen(), pStyle->m_songEditor_alternateRowColor.getBlue() );
459        QColor linesColor( pStyle->m_songEditor_lineColor.getRed(), pStyle->m_songEditor_lineColor.getGreen(), pStyle->m_songEditor_lineColor.getBlue() );
460
461        Hydrogen *pEngine = Hydrogen::get_instance();
462        Song *pSong = pEngine->getSong();
463
464        uint nPatterns = pSong->get_pattern_list()->get_size();
465
466        static int nOldHeight = -1;
467        int nNewHeight = m_nGridHeight * nPatterns;
468
469        if (nOldHeight != nNewHeight) {
470                // cambiamento di dimensioni...
471                if (nNewHeight == 0) {
472                        nNewHeight = 1; // the pixmap should not be empty
473                }
474
475                m_pBackgroundPixmap = new QPixmap( width(), nNewHeight );       // initialize the pixmap
476                m_pSequencePixmap = new QPixmap( width(), nNewHeight ); // initialize the pixmap
477                this->resize( QSize( width(), nNewHeight ) );
478        }
479
480        m_pBackgroundPixmap->fill( alternateRowColor );
481
482        QPainter p( m_pBackgroundPixmap );
483        p.setPen( linesColor );
484
485/*      // sfondo per celle scure (alternato)
486        for (uint i = 0; i < nPatterns; i++) {
487                if ( ( i % 2) != 0) {
488                        uint y = m_nGridHeight * i;
489                        p.fillRect ( 0, y, m_nMaxPatternSequence * m_nGridWidth, 2, backgroundColor );
490                        p.fillRect ( 0, y + 2, m_nMaxPatternSequence * m_nGridWidth, m_nGridHeight - 4, alternateRowColor );
491                        p.fillRect ( 0, y + m_nGridHeight - 2, m_nMaxPatternSequence * m_nGridWidth, 2, backgroundColor );
492                }
493        }
494*/
495        // celle...
496        p.setPen( linesColor );
497
498        // vertical lines
499        for (uint i = 0; i < m_nMaxPatternSequence + 1; i++) {
500                uint x = 10 + i * m_nGridWidth;
501                int x1 = x;
502                int x2 = x + m_nGridWidth;
503
504                p.drawLine( x1, 0, x1, m_nGridHeight * nPatterns );
505                p.drawLine( x2, 0, x2, m_nGridHeight * nPatterns );
506        }
507
508        p.setPen( linesColor );
509        // horizontal lines
510        for (uint i = 0; i < nPatterns; i++) {
511                uint y = m_nGridHeight * i;
512
513                int y1 = y + 2;
514                int y2 = y + m_nGridHeight - 2;
515
516                p.drawLine( 0, y1, (m_nMaxPatternSequence * m_nGridWidth), y1 );
517                p.drawLine( 0, y2, (m_nMaxPatternSequence * m_nGridWidth), y2 );
518        }
519
520
521        p.setPen( backgroundColor );
522        // horizontal lines (erase..)
523        for (uint i = 0; i < nPatterns + 1; i++) {
524                uint y = m_nGridHeight * i;
525
526                p.fillRect( 0, y, m_nMaxPatternSequence * m_nGridWidth, 2, backgroundColor );
527                p.drawLine( 0, y + m_nGridHeight - 1, m_nMaxPatternSequence * m_nGridWidth, y + m_nGridHeight - 1 );
528        }
529
530        //~ celle
531        m_bSequenceChanged = true;
532}
533
534void SongEditor::cleanUp(){
535
536        delete m_pBackgroundPixmap;
537        delete m_pSequencePixmap;
538}
539
540void SongEditor::drawSequence()
541{
542        QPainter p;
543        p.begin( m_pSequencePixmap );
544        p.drawPixmap( rect(), *m_pBackgroundPixmap, rect() );
545        p.end();
546
547        Song* song = Hydrogen::get_instance()->getSong();
548        PatternList *patList = song->get_pattern_list();
549        vector<PatternList*>* pColumns = song->get_pattern_group_vector();
550        uint listLength = patList->get_size();
551        for (uint i = 0; i < pColumns->size(); i++) {
552                PatternList* pColumn = (*pColumns)[ i ];
553
554                for (uint nPat = 0; nPat < pColumn->get_size(); ++nPat) {
555                        H2Core::Pattern *pat = pColumn->get( nPat );
556
557                        int position = -1;
558                        // find the position in pattern list
559                        for (uint j = 0; j < listLength; j++) {
560                                H2Core::Pattern *pat2 = patList->get( j );
561                                if (pat == pat2) {
562                                        position = j;
563                                        break;
564                                }
565                        }
566                        if (position == -1) {
567                                WARNINGLOG( "[drawSequence] position == -1, group = " + to_string( i ) );
568                        }
569                        drawPattern( i, position );
570                }
571        }
572
573        // Moving cells
574        p.begin( m_pSequencePixmap );
575//      p.setRasterOp( Qt::XorROP );
576
577// comix: this composition mode seems to be not available on Mac
578        p.setCompositionMode( QPainter::CompositionMode_Xor );
579        QPen pen( Qt::gray );
580        pen.setStyle( Qt::DotLine );
581        p.setPen( pen );
582        for ( uint i = 0; i < m_movingCells.size(); i++ ) {
583                int x = 10 + m_nGridWidth * ( m_movingCells[ i ] ).x();
584                int y = m_nGridHeight * ( m_movingCells[ i ] ).y();
585
586                QColor patternColor;
587                patternColor.setRgb( 255, 255, 255 );
588                p.fillRect( x + 2, y + 4, m_nGridWidth - 3, m_nGridHeight - 7, patternColor );
589        }
590
591}
592
593
594
595void SongEditor::drawPattern( int pos, int number )
596{
597        Preferences *pref = Preferences::getInstance();
598        UIStyle *pStyle = pref->getDefaultUIStyle();
599        QPainter p( m_pSequencePixmap );
600        QColor patternColor( pStyle->m_songEditor_pattern1Color.getRed(), pStyle->m_songEditor_pattern1Color.getGreen(), pStyle->m_songEditor_pattern1Color.getBlue() );
601
602        bool bIsSelected = false;
603        for ( uint i = 0; i < m_selectedCells.size(); i++ ) {
604                QPoint point = m_selectedCells[ i ];
605                if ( point.x() == pos && point.y() == number ) {
606                        bIsSelected = true;
607                        break;
608                }
609        }
610
611        if ( bIsSelected ) {
612                patternColor = patternColor.dark( 130 );
613        }
614
615        int x = 10 + m_nGridWidth * pos;
616        int y = m_nGridHeight * number;
617
618//      p.setPen( patternColor.light( 120 ) );  // willie - For the bevel - haven't yet figured how it's supposed to work...
619        p.fillRect( x + 1, y + 3, m_nGridWidth - 1, m_nGridHeight - 5, patternColor );
620}
621
622
623
624
625
626// :::::::::::::::::::
627
628
629
630
631
632SongEditorPatternList::SongEditorPatternList( QWidget *parent )
633 : QWidget( parent )
634 , Object( "SongEditorPatternList" )
635 , EventListener()
636 , m_pBackgroundPixmap( NULL )
637{
638        m_nWidth = 200;
639        m_nGridHeight = 18;
640        setAttribute(Qt::WA_NoBackground);
641       
642        patternBeingEdited = NULL;
643       
644        line = new QLineEdit( "Inline Pattern Name", this );
645        line->setFrame( false );
646        line->hide();
647        connect( line, SIGNAL(editingFinished()), this, SLOT(inlineEditingFinished()) );
648        connect( line, SIGNAL(returnPressed()), this, SLOT(inlineEditingEntered()) );
649
650        this->resize( m_nWidth, m_nInitialHeight );
651
652        m_labelBackgroundLight.load( Skin::getImagePath() + "/songEditor/songEditorLabelBG.png" );
653        m_labelBackgroundDark.load( Skin::getImagePath() + "/songEditor/songEditorLabelABG.png" );
654        m_labelBackgroundSelected.load( Skin::getImagePath() + "/songEditor/songEditorLabelSBG.png" );
655        m_playingPattern_on_Pixmap.load( Skin::getImagePath() + "/songEditor/playingPattern_on.png" );
656        m_playingPattern_off_Pixmap.load( Skin::getImagePath() + "/songEditor/playingPattern_off.png" );
657
658        m_pPatternPopup = new QMenu( this );
659        m_pPatternPopup->addAction( trUtf8("Edit"),  this, SLOT( patternPopup_edit() ) );
660        m_pPatternPopup->addAction( trUtf8("Copy"),  this, SLOT( patternPopup_copy() ) );
661        m_pPatternPopup->addAction( trUtf8("Delete"),  this, SLOT( patternPopup_delete() ) );
662        m_pPatternPopup->addAction( trUtf8("Fill/Clear ..."),  this, SLOT( patternPopup_fill() ) );
663        m_pPatternPopup->addAction( trUtf8("Properties"),  this, SLOT( patternPopup_properties() ) );
664        m_pPatternPopup->addAction( trUtf8("Load Pattern"),  this, SLOT( patternPopup_load() ) );
665        m_pPatternPopup->addAction( trUtf8("Save Pattern"),  this, SLOT( patternPopup_save() ) );
666
667        HydrogenApp::getInstance()->addEventListener( this );
668
669        createBackground();
670        update();
671}
672
673
674
675SongEditorPatternList::~SongEditorPatternList()
676{
677}
678
679
680void SongEditorPatternList::patternChangedEvent() {
681        createBackground();
682        update();
683}
684
685
686/// Single click, select the next pattern
687void SongEditorPatternList::mousePressEvent( QMouseEvent *ev )
688{
689        int row = (ev->y() / m_nGridHeight);
690
691        Hydrogen *engine = Hydrogen::get_instance();
692        Song *song = engine->getSong();
693        PatternList *patternList = song->get_pattern_list();
694
695        if ( row >= (int)patternList->get_size() ) {
696                return;
697        }
698
699        if ( ev->button() == Qt::MidButton || ev->modifiers() == Qt::ControlModifier && ev->button() == Qt::RightButton || ev->modifiers() == Qt::ControlModifier && ev->button() == Qt::LeftButton ){
700                togglePattern( row );
701        } else {
702                engine->setSelectedPatternNumber( row );
703                if (ev->button() == Qt::RightButton)  {
704        /*
705                        if ( song->getMode() == Song::PATTERN_MODE ) {
706       
707                                PatternList *pCurrentPatternList = engine->getCurrentPatternList();
708                                if ( pCurrentPatternList->get_size() == 0 ) {
709                                        // nessun pattern e' attivo. seleziono subito questo.
710                                        pCurrentPatternList->add( patternList->get( row ) );
711                                }
712                                else {
713                                        engine->setNextPattern( row );
714                                }
715                        }
716        */
717                        m_pPatternPopup->popup( QPoint( ev->globalX(), ev->globalY() ) );
718                }
719        }
720
721        createBackground();
722        update();
723}
724
725
726///
727/// Start/stop playing a pattern in "pattern mode"
728///
729void SongEditorPatternList::togglePattern( int row ) {
730
731        Hydrogen *engine = Hydrogen::get_instance();
732/*      Song *song = engine->getSong();
733        PatternList *patternList = song->get_pattern_list();*/
734
735//      PatternList *pCurrentPatternList = engine->getCurrentPatternList();
736
737//      bool isPatternPlaying = false;
738        engine->sequencer_setNextPattern( row, false, true );
739
740//      for ( uint i = 0; i < pCurrentPatternList->get_size(); ++i ) {
741//              if ( pCurrentPatternList->get( i ) == patternList->get( row ) ) {
742//                      // the pattern is already playing, stop it!
743//                      isPatternPlaying = true;
744//                      break;
745//              }
746//      }
747//
748//      if ( isPatternPlaying ) {
749//              //pCurrentPatternList->del( patternList->get( row ) );
750//              engine->sequencer_setNextPattern( row, false, true );   // remove from the playing pattern list
751//      }
752//      else {
753//              // the pattern is not playing, add it to the list
754//              //pCurrentPatternList->add( patternList->get( row ) );
755//              engine->sequencer_setNextPattern( row, true, false );   // add to the playing pattern list
756//      }
757
758        createBackground();
759        update();
760}
761
762
763void SongEditorPatternList::mouseDoubleClickEvent( QMouseEvent *ev )
764{
765        int row = (ev->y() / m_nGridHeight);
766        inlineEditPatternName( row );
767}
768
769void SongEditorPatternList::inlineEditPatternName( int row )
770{
771        Hydrogen *engine = Hydrogen::get_instance();
772        Song *song = engine->getSong();
773        PatternList *patternList = song->get_pattern_list();
774
775        if ( row >= (int)patternList->get_size() ) {
776                return;
777        }
778        patternBeingEdited = patternList->get( row );
779        line->setGeometry( 23, row * m_nGridHeight , m_nWidth - 23, m_nGridHeight  );
780        line->setText( patternBeingEdited->get_name() );
781        line->selectAll();
782        line->show();
783        line->setFocus();
784}
785
786void SongEditorPatternList::inlineEditingEntered()
787{
788        assert( patternBeingEdited != NULL );
789        if ( PatternPropertiesDialog::nameCheck( line->text() ) )
790        {
791                patternBeingEdited->set_name( line->text() );
792                Hydrogen::get_instance()->getSong()->__is_modified = true;
793                EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 );
794                createBackground();
795                update();
796        }
797//      patternBeingEdited = NULL;
798}
799
800
801void SongEditorPatternList::inlineEditingFinished()
802{
803        patternBeingEdited = NULL;
804        line->hide();
805}
806
807
808void SongEditorPatternList::paintEvent( QPaintEvent *ev )
809{
810        QPainter painter(this);
811        painter.drawPixmap( ev->rect(), *m_pBackgroundPixmap, ev->rect() );
812}
813
814
815
816void SongEditorPatternList::updateEditor()
817{
818        if(!isVisible()) {
819                return;
820        }
821
822        update();
823}
824
825
826
827void SongEditorPatternList::createBackground()
828{
829        Preferences *pref = Preferences::getInstance();
830        UIStyle *pStyle = pref->getDefaultUIStyle();
831        QColor textColor( pStyle->m_songEditor_textColor.getRed(), pStyle->m_songEditor_textColor.getGreen(), pStyle->m_songEditor_textColor.getBlue() );
832
833        QString family = pref->getApplicationFontFamily();
834        int size = pref->getApplicationFontPointSize();
835        QFont textFont( family, size );
836
837        QFont boldTextFont( textFont);
838        boldTextFont.setPointSize(10);
839        boldTextFont.setBold( true );
840
841        Hydrogen *pEngine = Hydrogen::get_instance();
842        Song *pSong = pEngine->getSong();
843        int nPatterns = pSong->get_pattern_list()->get_size();
844        int nSelectedPattern = pEngine->getSelectedPatternNumber();
845
846        static int oldHeight = -1;
847        int newHeight = m_nGridHeight * nPatterns;
848
849        if (oldHeight != newHeight) {
850                if (newHeight == 0) {
851                        newHeight = 1;  // the pixmap should not be empty
852                }
853                delete m_pBackgroundPixmap;
854                m_pBackgroundPixmap = new QPixmap( m_nWidth, newHeight );       // initialize the pixmap
855                this->resize( m_nWidth, newHeight );
856        }
857        m_pBackgroundPixmap->fill( Qt::black );
858
859        QPainter p( m_pBackgroundPixmap );
860        p.setFont( boldTextFont );
861
862        for ( int i = 0; i < nPatterns; i++ ) {
863                uint y = m_nGridHeight * i;
864                if ( i == nSelectedPattern ) {
865                        p.drawPixmap( QPoint( 0, y ), m_labelBackgroundSelected );
866                }
867                else {
868                        if ( ( i % 2) == 0 ) {
869                                p.drawPixmap( QPoint( 0, y ), m_labelBackgroundDark );
870                        }
871                        else {
872                                p.drawPixmap( QPoint( 0, y ), m_labelBackgroundLight );
873                        }
874                }
875        }
876
877        PatternList *pCurrentPatternList = pEngine->getCurrentPatternList();
878
879        /// paint the foreground (pattern name etc.)
880        for ( int i = 0; i < nPatterns; i++ ) {
881                H2Core::Pattern *pPattern = pSong->get_pattern_list()->get(i);
882                //uint y = m_nGridHeight * i;
883
884                // Text
885                bool bNext = false, bActive = false;
886/*              for (uint j = 0; j < pCurrentPatternList->get_size(); j++) {
887                        if ( pPattern == pCurrentPatternList->get(j) ) {
888                                bActive = true;
889                                break;
890                        }
891                }*/
892                if ( pCurrentPatternList->index_of( pPattern ) != -1 ) bActive = true;
893                if ( pEngine->getNextPatterns()->index_of( pPattern ) != -1 ) bNext = true;
894
895                if ( i == nSelectedPattern ) {
896                        p.setPen( QColor( 0,0,0 ) );
897                }
898                else {
899                        p.setPen( textColor );
900                }
901
902                uint text_y = i * m_nGridHeight;
903                if ( bNext ) {
904                        p.drawPixmap( QPoint( 5, text_y + 3 ), m_playingPattern_off_Pixmap );
905                }
906                else if (bActive) {
907//                      p.drawText( 5, text_y - 1 - m_nGridHeight, m_nWidth - 25, m_nGridHeight + 2, Qt::AlignVCenter, ">" );
908               
909                        //mark active pattern with triangular
910                        if( ! pref->patternModePlaysSelected() ){
911                                p.drawPixmap( QPoint( 5, text_y + 3 ), m_playingPattern_on_Pixmap );
912                        }
913                }
914
915
916                p.drawText( 25, text_y - 1, m_nWidth - 25, m_nGridHeight + 2, Qt::AlignVCenter, pPattern->get_name() );
917        }
918
919}
920
921
922
923void SongEditorPatternList::patternPopup_load()
924{
925
926        Hydrogen *engine = Hydrogen::get_instance();
927        int tmpselectedpatternpos = engine->getSelectedPatternNumber();
928        Song *song = engine->getSong();
929        PatternList *pPatternList = song->get_pattern_list();
930        Instrument *instr = song->get_instrument_list()->get( 0 );
931        assert( instr );
932       
933        QString sDrumkitDir = Preferences::getInstance()->getDataDirectory() + "drumkits/" + instr->get_drumkit_name();
934       
935        QDir dirPattern( sDrumkitDir + "/Pattern" );
936        QFileDialog *fd = new QFileDialog(this);
937        fd->setFileMode(QFileDialog::ExistingFile);
938        fd->setFilter( trUtf8("Hydrogen Song (*.h2pattern)") );
939        fd->setDirectory(dirPattern );
940
941        fd->setWindowTitle( trUtf8( "Open Pattern" ) );
942
943        QString filename = "";
944        if (fd->exec() == QDialog::Accepted) {
945                filename = fd->selectedFiles().first();
946        }
947        else
948        {
949                return;
950        }
951
952        LocalFileMng mng;
953        LocalFileMng fileMng;
954        Pattern* err = fileMng.loadPattern( filename );
955        if ( err == 0 ) {
956                _ERRORLOG( "Error loading the pattern" );
957        }else{
958                H2Core::Pattern *pNewPattern = err;
959                pPatternList->add( pNewPattern );
960                song->__is_modified = true;
961                createBackground();
962                update();
963        }
964
965        int listsize = pPatternList->get_size();
966        engine->setSelectedPatternNumber( listsize -1 );
967        Pattern *pTemp = pPatternList->get( engine->getSelectedPatternNumber() );
968        pPatternList->replace( pPatternList->get( tmpselectedpatternpos ), listsize -1);
969        pPatternList->replace( pTemp, tmpselectedpatternpos );
970        listsize = pPatternList->get_size();
971        engine->setSelectedPatternNumber( listsize -1 );
972        patternPopup_delete();
973        engine->setSelectedPatternNumber( tmpselectedpatternpos );
974        HydrogenApp::getInstance()->getSongEditorPanel()->updateAll();
975
976}
977
978
979
980void SongEditorPatternList::patternPopup_save()
981{       
982        Hydrogen *engine = Hydrogen::get_instance();
983        int nSelectedPattern = engine->getSelectedPatternNumber();
984        Song *song = engine->getSong();
985        Pattern *pat = song->get_pattern_list()->get( nSelectedPattern );
986
987        QString patternname = pat->get_name();
988        QString realpatternname = patternname;
989
990        LocalFileMng fileMng;
991        int err = fileMng.savePattern( song , nSelectedPattern, patternname, realpatternname, 1 );
992        if ( err != 0 ) {
993                _ERRORLOG( "Error saving the pattern" );
994        }
995
996#ifdef WIN32
997        Sleep ( 10 );
998#else
999        usleep ( 10000 );
1000#endif
1001        HydrogenApp::getInstance()->getInstrumentRack()->getSoundLibraryPanel()->updateDrumkitList();
1002}
1003
1004
1005
1006void SongEditorPatternList::patternPopup_edit()
1007{
1008        HydrogenApp::getInstance()->getPatternEditorPanel()->show();
1009        HydrogenApp::getInstance()->getPatternEditorPanel()->setFocus();
1010}
1011
1012
1013
1014void SongEditorPatternList::patternPopup_properties()
1015{
1016        Hydrogen *engine = Hydrogen::get_instance();
1017        Song *song = engine->getSong();
1018        PatternList *patternList = song->get_pattern_list();
1019
1020        int nSelectedPattern = engine->getSelectedPatternNumber();
1021        H2Core::Pattern *pattern = patternList->get( nSelectedPattern );
1022
1023        PatternPropertiesDialog *dialog = new PatternPropertiesDialog(this, pattern);
1024        if (dialog->exec() == QDialog::Accepted) {
1025//              Hydrogen *engine = Hydrogen::get_instance();
1026//              Song *song = engine->getSong();
1027                song->__is_modified = true;
1028                EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 );
1029                createBackground();
1030                update();
1031        }
1032        delete dialog;
1033        dialog = NULL;
1034}
1035
1036
1037
1038void SongEditorPatternList::patternPopup_delete()
1039{
1040        Hydrogen *pEngine = Hydrogen::get_instance();
1041
1042//      int state = engine->getState();
1043//      // per ora non lascio possibile la cancellazione del pattern durante l'esecuzione
1044//      // da togliere quando correggo il bug
1045//         if (state == PLAYING) {
1046//                 QMessageBox::information( this, "Hydrogen", trUtf8("Can't delete the pattern while the audio engine is playing"));
1047//                 return;
1048//         }
1049
1050        if ( pEngine->getSong()->get_mode() == Song::PATTERN_MODE ) {
1051                pEngine->sequencer_setNextPattern( -1, false, false );  // reimposto il prossimo pattern a NULL, altrimenti viene scelto quello che sto distruggendo ora...
1052        }
1053
1054//      pEngine->sequencer_stop();
1055
1056// "lock engine" I am not sure, but think this is unnecessarily. -wolke-
1057//      AudioEngine::get_instance()->lock( "SongEditorPatternList::patternPopup_delete" );
1058
1059        Song *song = pEngine->getSong();
1060        PatternList *pSongPatternList = song->get_pattern_list();
1061
1062        H2Core::Pattern *pattern = pSongPatternList->get( pEngine->getSelectedPatternNumber() );
1063        INFOLOG( "[patternPopup_delete] Delete pattern: " + pattern->get_name() + " @" + to_string( (long)pattern ) );
1064        pSongPatternList->del(pattern);
1065
1066        vector<PatternList*> *patternGroupVect = song->get_pattern_group_vector();
1067
1068        uint i = 0;
1069        while (i < patternGroupVect->size() ) {
1070                PatternList *list = (*patternGroupVect)[i];
1071
1072                uint j = 0;
1073                while ( j < list->get_size() ) {
1074                        H2Core::Pattern *pOldPattern = list->get( j );
1075                        if (pOldPattern == pattern ) {
1076                                list->del( j );
1077                                continue;
1078                        }
1079                        j++;
1080                }
1081//              for (uint j = 0; j < list->get_size(); j++) {
1082//                      Pattern *pOldPattern = list->get( j );
1083//                      if (pOldPattern == pattern ) {
1084//                              list->del( j );
1085//                      }
1086//              }
1087
1088/*              if (list->get_size() == 0 ) {
1089                        patternGroupVect->erase( patternGroupVect->begin() + i );
1090                        delete list;
1091                        list = NULL;
1092                }
1093                else {
1094*/                      i++;
1095//              }
1096        }
1097
1098
1099        PatternList *list = pEngine->getCurrentPatternList();
1100        list->del( pattern );
1101        // se esiste, seleziono il primo pattern
1102        if ( pSongPatternList->get_size() > 0 ) {
1103                H2Core::Pattern *pFirstPattern = pSongPatternList->get( 0 );
1104                list->add( pFirstPattern );
1105                // Cambio due volte...cosi' il pattern editor viene costretto ad aggiornarsi
1106                pEngine->setSelectedPatternNumber( -1 );
1107                pEngine->setSelectedPatternNumber( 0 );
1108        }
1109        else {
1110                // there's no patterns..
1111                pEngine->setSelectedPatternNumber( -1 );        // cosi' il pattern editor viene costretto ad aggiornarsi
1112        }
1113
1114        delete pattern;
1115
1116        song->__is_modified = true;
1117
1118// "unlock" I am not sure, but think this is unnecessarily. -wolke-
1119//      AudioEngine::get_instance()->unlock();
1120
1121        ( HydrogenApp::getInstance() )->getSongEditorPanel()->updateAll();
1122}
1123
1124
1125
1126void SongEditorPatternList::patternPopup_copy()
1127{
1128        Hydrogen *pEngine = Hydrogen::get_instance();
1129        Song *pSong = pEngine->getSong();
1130        PatternList *pPatternList = pSong->get_pattern_list();
1131        int nSelectedPattern = pEngine->getSelectedPatternNumber();
1132        H2Core::Pattern *pPattern = pPatternList->get( nSelectedPattern );
1133
1134        H2Core::Pattern *pNewPattern = pPattern->copy();
1135        pPatternList->add( pNewPattern );
1136
1137        // rename the copied pattern
1138        PatternPropertiesDialog *dialog = new PatternPropertiesDialog( this, pNewPattern );
1139        if ( dialog->exec() == QDialog::Accepted ) {
1140                pSong->__is_modified = true;
1141                pEngine->setSelectedPatternNumber(pPatternList->get_size() - 1);        // select the last pattern (the copied one)
1142                if (pSong->get_mode() == Song::PATTERN_MODE) {
1143                        pEngine->sequencer_setNextPattern( pPatternList->get_size() - 1, false, false );        // select the last pattern (the new copied pattern)
1144                }
1145        }
1146        else {
1147                pPatternList->del( pNewPattern );
1148                delete pNewPattern;
1149        }
1150        delete dialog;
1151
1152        HydrogenApp::getInstance()->getSongEditorPanel()->updateAll();
1153}
1154
1155void SongEditorPatternList::patternPopup_fill()
1156{
1157        Hydrogen *pEngine = Hydrogen::get_instance();
1158        int nSelectedPattern = pEngine->getSelectedPatternNumber();
1159        FillRange range;
1160        PatternFillDialog *dialog = new PatternFillDialog( this, &range );
1161        SongEditorPanel *pSEPanel = HydrogenApp::getInstance()->getSongEditorPanel();
1162
1163
1164        // use a PatternFillDialog to get the range and mode data
1165        if ( dialog->exec() == QDialog::Accepted ) {
1166                fillRangeWithPattern(&range, nSelectedPattern);
1167                pSEPanel->updateAll();
1168        }
1169
1170        delete dialog;
1171
1172}
1173
1174
1175void SongEditorPatternList::fillRangeWithPattern(FillRange* pRange, int nPattern)
1176{
1177        Hydrogen *pEngine = Hydrogen::get_instance();
1178        AudioEngine::get_instance()->lock( "SongEditorPatternList::fillRangeWithPattern" );
1179
1180
1181        Song *pSong = pEngine->getSong();
1182        PatternList *pPatternList = pSong->get_pattern_list();
1183        H2Core::Pattern *pPattern = pPatternList->get( nPattern );
1184        vector<PatternList*> *pColumns = pSong->get_pattern_group_vector();     // E' la lista di "colonne" di pattern
1185        PatternList *pColumn;
1186
1187        int nColumn, nColumnIndex;
1188        bool bHasPattern = false;
1189        int fromVal = pRange->fromVal - 1;
1190        int toVal   = pRange->toVal;
1191
1192
1193
1194        // Add patternlists to PatternGroupVector as necessary
1195
1196        int nDelta = toVal - pColumns->size() + 1;
1197
1198        for ( int i = 0; i < nDelta; i++ ) {
1199                pColumn = new PatternList();
1200                pColumns->push_back( pColumn );
1201        }
1202
1203
1204        // Fill or Clear each cell in range
1205
1206        for ( nColumn = fromVal; nColumn < toVal; nColumn++ ) {
1207
1208                // expand Pattern
1209                pColumn = ( *pColumns )[ nColumn ];
1210
1211                bHasPattern = false;
1212
1213                // check whether the pattern (and column) already exists
1214                for ( nColumnIndex = 0; pColumn && nColumnIndex < (int)pColumn->get_size(); nColumnIndex++) {
1215
1216                        if ( pColumn->get( nColumnIndex ) == pPattern ) {
1217                                bHasPattern = true;
1218                                break;
1219                        }
1220                }
1221
1222                if ( pRange->bInsert && !bHasPattern ) {       //fill
1223                        pColumn->add( pPattern);
1224                }
1225                else if ( !pRange->bInsert && bHasPattern ) {  // clear
1226                        pColumn->del( pPattern);
1227                }
1228        }
1229
1230                // remove all the empty patternlists at the end of the song
1231                for ( int i = pColumns->size() - 1; i != 0 ; i-- ) {
1232                        PatternList *pList = (*pColumns)[ i ];
1233                        int nSize = pList->get_size();
1234                        if ( nSize == 0 ) {
1235                                pColumns->erase( pColumns->begin() + i );
1236                                delete pList;
1237                        }
1238                        else {
1239                                break;
1240                        }
1241                }
1242        AudioEngine::get_instance()->unlock();
1243
1244
1245        // Update
1246        pSong->__is_modified = true;
1247}
1248
1249
1250// ::::::::::::::::::::::::::
1251
1252
1253
1254SongEditorPositionRuler::SongEditorPositionRuler( QWidget *parent )
1255 : QWidget( parent )
1256 , Object( "SongEditorPositionRuler" )
1257{
1258        setAttribute(Qt::WA_NoBackground);
1259
1260        m_nGridWidth = 16;
1261
1262        resize( m_nInitialWidth, m_nHeight );
1263        setFixedHeight( m_nHeight );
1264
1265        m_pBackgroundPixmap = new QPixmap( m_nInitialWidth, m_nHeight );        // initialize the pixmap
1266
1267        createBackground();     // create m_backgroundPixmap pixmap
1268
1269        // create tick position pixmap
1270        bool ok = m_tickPositionPixmap.load( Skin::getImagePath() + "/patternEditor/tickPosition.png" );
1271        if( ok == false ){
1272                ERRORLOG( "Error loading pixmap" );
1273        }
1274
1275        update();
1276
1277        m_pTimer = new QTimer(this);
1278        connect(m_pTimer, SIGNAL(timeout()), this, SLOT(updatePosition()));
1279        m_pTimer->start(200);
1280}
1281
1282
1283
1284SongEditorPositionRuler::~SongEditorPositionRuler() {
1285        m_pTimer->stop();
1286}
1287
1288
1289uint SongEditorPositionRuler::getGridWidth()
1290{
1291        return m_nGridWidth;
1292}
1293
1294void SongEditorPositionRuler::setGridWidth( uint width )
1295{
1296        if ( SONG_EDITOR_MIN_GRID_WIDTH <= width && SONG_EDITOR_MAX_GRID_WIDTH >= width )
1297        {
1298                m_nGridWidth = width;
1299                createBackground ();
1300        }
1301}
1302
1303
1304void SongEditorPositionRuler::createBackground()
1305{
1306        UIStyle *pStyle = Preferences::getInstance()->getDefaultUIStyle();
1307        QColor backgroundColor( pStyle->m_songEditor_backgroundColor.getRed(), pStyle->m_songEditor_backgroundColor.getGreen(), pStyle->m_songEditor_backgroundColor.getBlue() );
1308        QColor textColor( pStyle->m_songEditor_textColor.getRed(), pStyle->m_songEditor_textColor.getGreen(), pStyle->m_songEditor_textColor.getBlue() );
1309        QColor alternateRowColor( pStyle->m_songEditor_alternateRowColor.getRed(), pStyle->m_songEditor_alternateRowColor.getGreen(), pStyle->m_songEditor_alternateRowColor.getBlue() );
1310
1311        m_pBackgroundPixmap->fill( backgroundColor );
1312
1313        Preferences *pref = Preferences::getInstance();
1314        QString family = pref->getApplicationFontFamily();
1315        int size = pref->getApplicationFontPointSize();
1316        QFont font( family, size );
1317
1318        QPainter p( m_pBackgroundPixmap );
1319        p.setFont( font );
1320
1321        char tmp[10];
1322        for (uint i = 0; i < m_nMaxPatternSequence + 1; i++) {
1323                uint x = 10 + i * m_nGridWidth;
1324                if ( (i % 4) == 0 ) {
1325                        p.setPen( textColor );
1326                        sprintf( tmp, "%d", i + 1 );
1327                        p.drawText( x - m_nGridWidth, 0, m_nGridWidth * 2, height(), Qt::AlignCenter, tmp );
1328                }
1329                else {
1330                        p.setPen( textColor );
1331                        p.drawLine( x, 10, x, m_nHeight - 10 );
1332                }
1333        }
1334
1335        p.setPen( QColor(35, 39, 51) );
1336        p.drawLine( 0, 0, width(), 0 );
1337
1338        p.fillRect ( 0, height() - 3, width(), 2, alternateRowColor );
1339
1340}
1341
1342
1343
1344void SongEditorPositionRuler::mouseMoveEvent(QMouseEvent *ev)
1345{
1346        mousePressEvent( ev );
1347}
1348
1349
1350
1351void SongEditorPositionRuler::mousePressEvent( QMouseEvent *ev )
1352{
1353        int column = (ev->x() / m_nGridWidth);
1354
1355        if ( column >= (int)Hydrogen::get_instance()->getSong()->get_pattern_group_vector()->size() ) {
1356                return;
1357        }
1358       
1359        // disabling son relocates while in pattern mode as it causes weird behaviour. (jakob lund)
1360        if ( Hydrogen::get_instance()->getSong()->get_mode() == Song::PATTERN_MODE ) {
1361                return;
1362        }
1363
1364        int nPatternPos = Hydrogen::get_instance()->getPatternPos();
1365        if ( nPatternPos != column ) {
1366                Hydrogen::get_instance()->setPatternPos( column );
1367                update();
1368        }
1369}
1370
1371
1372
1373void SongEditorPositionRuler::paintEvent( QPaintEvent *ev )
1374{
1375        if (!isVisible()) {
1376                return;
1377        }
1378
1379        static float fOldPosition = -1000;
1380        float fPos = Hydrogen::get_instance()->getPatternPos();
1381
1382        if ( Hydrogen::get_instance()->getCurrentPatternList()->get_size() != 0 ) {
1383                H2Core::Pattern *pPattern = Hydrogen::get_instance()->getCurrentPatternList()->get( 0 );
1384                fPos += (float)Hydrogen::get_instance()->getTickPosition() / (float)pPattern->get_lenght();
1385        }
1386        else {
1387                // nessun pattern, uso la grandezza di default
1388                fPos += (float)Hydrogen::get_instance()->getTickPosition() / (float)MAX_NOTES;
1389        }
1390
1391        if ( fOldPosition != fPos ) {
1392                fOldPosition = fPos;
1393        }
1394
1395        if ( Hydrogen::get_instance()->getSong()->get_mode() == Song::PATTERN_MODE ) {
1396                fPos = -1;
1397        }
1398
1399        QPainter painter(this);
1400        painter.drawPixmap( ev->rect(), *m_pBackgroundPixmap, ev->rect() );
1401
1402        if (fPos != -1) {
1403                uint x = (int)( 10 + fPos * m_nGridWidth - 11 / 2 );
1404                painter.drawPixmap( QRect( x, height() / 2, 11, 8), m_tickPositionPixmap, QRect(0, 0, 11, 8) );
1405        }
1406}
1407
1408
1409
1410void SongEditorPositionRuler::updatePosition()
1411{
1412        update();
1413}
1414
1415
Note: See TracBrowser for help on using the browser.