hydrogen 1.2.6
SoundLibraryPropertiesDialog.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-2025 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 <QtGui>
24#include <QtWidgets>
25
26#include "../HydrogenApp.h"
27#include "../CommonStrings.h"
28
30#include "../InstrumentRack.h"
31#include "SoundLibraryPanel.h"
33#include <core/Hydrogen.h>
36
37namespace H2Core
38{
39
40SoundLibraryPropertiesDialog::SoundLibraryPropertiesDialog( QWidget* pParent, std::shared_ptr<Drumkit> pDrumkit, bool bDrumkitNameLocked )
41 : QDialog( pParent )
42 , m_pDrumkit( pDrumkit )
43 , m_bDrumkitNameLocked( bDrumkitNameLocked )
44 , m_sNewImagePath( "" )
45{
46 setObjectName( "SoundLibraryPropertiesDialog" );
47
48 setupUi( this );
49
50 // Show and enable maximize button. This is key when enlarging the
51 // application using a scaling factor and allows the OS to force its size
52 // beyond the minimum and make the scrollbars appear.
53 setWindowFlags( windowFlags() | Qt::CustomizeWindowHint |
54 Qt::WindowMinMaxButtonsHint );
55
56 auto pPref = Preferences::get_instance();
57 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
58
59 setWindowTitle( tr( "SoundLibrary Properties" ) );
60
61 setupLicenseComboBox( licenseComboBox );
62 connect( licenseComboBox, SIGNAL( currentIndexChanged( int ) ),
63 this, SLOT( licenseComboBoxChanged( int ) ) );
64 setupLicenseComboBox( imageLicenseComboBox );
65 connect( imageLicenseComboBox, SIGNAL( currentIndexChanged( int ) ),
66 this, SLOT( imageLicenseComboBoxChanged( int ) ) );
67
68 bool bDrumkitWritable = false;
69 //display the current drumkit infos into the qlineedit
70 if ( pDrumkit != nullptr ){
71
72 auto drumkitType = Filesystem::determineDrumkitType(
73 pDrumkit->get_path() );
74 if ( drumkitType == Filesystem::DrumkitType::User ||
76 bDrumkitWritable = true;
77 }
78
79 nameTxt->setText( pDrumkit->get_name() );
80
81 if ( bDrumkitNameLocked ) {
82 nameTxt->setIsActive( false );
83 nameTxt->setToolTip( tr( "Altering the name of a drumkit would result in the creation of a new one. To do so, you need to load the drumkit (if you haven't done so already) using right click > load and select Drumkits > Save As in the main menu" ) );
84 }
85
86 authorTxt->setText( QString( pDrumkit->get_author() ) );
87 infoTxt->append( QString( pDrumkit->get_info() ) );
88
89 License license = pDrumkit->get_license();
90 licenseComboBox->setCurrentIndex( static_cast<int>( license.getType() ) );
91 licenseStringTxt->setText( license.getLicenseString() );
92
93 imageText->setText( QString( pDrumkit->get_image() ) );
94
95 License imageLicense = pDrumkit->get_image_license();
96 imageLicenseComboBox->setCurrentIndex( static_cast<int>( imageLicense.getType() ) );
97 imageLicenseStringTxt->setText( imageLicense.getLicenseString() );
98 }
99
100 if ( licenseComboBox->currentIndex() == static_cast<int>( License::Unspecified ) ) {
101 licenseStringLbl->hide();
102 licenseStringTxt->hide();
103 }
104 if ( imageLicenseComboBox->currentIndex() == static_cast<int>( License::Unspecified ) ) {
105 imageLicenseStringLbl->hide();
106 imageLicenseStringTxt->hide();
107 }
108
109 licenseComboBox->setToolTip( pCommonStrings->getLicenseComboToolTip() );
110 licenseStringLbl->setText( pCommonStrings->getLicenseStringLbl() );
111 licenseStringTxt->setToolTip( pCommonStrings->getLicenseStringToolTip() );
112 imageLicenseComboBox->setToolTip( pCommonStrings->getLicenseComboToolTip() );
113 imageLicenseStringLbl->setText( pCommonStrings->getLicenseStringLbl() );
114 imageLicenseStringTxt->setToolTip( pCommonStrings->getLicenseStringToolTip() );
115
116 // In case the drumkit name is not locked/the dialog is used as
117 // "Save As" nothing needs to be disabled.
118 if ( ! bDrumkitWritable && bDrumkitNameLocked ) {
119 QString sToolTip = tr( "The current drumkit is read-only. Please use Drumkits > Save As in the main menu to create a new one first." );
120
121 // The drumkit is read-only. Thus we won't support altering
122 // any of its properties.
123 authorTxt->setIsActive( false );
124 authorTxt->setToolTip( sToolTip );
125 infoTxt->setEnabled( false );
126 infoTxt->setReadOnly( true );
127 infoTxt->setToolTip( sToolTip );
128 licenseComboBox->setIsActive( false );
129 licenseComboBox->setToolTip( sToolTip );
130 licenseStringTxt->setIsActive( false );
131 licenseStringTxt->setToolTip( sToolTip );
132 imageText->setIsActive( false );
133 imageText->setToolTip( sToolTip );
134 imageLicenseComboBox->setIsActive( false );
135 imageLicenseComboBox->setToolTip( sToolTip );
136 imageLicenseStringTxt->setIsActive( false );
137 imageLicenseStringTxt->setToolTip( sToolTip );
138 saveBtn->setIsActive( false );
139 saveBtn->setToolTip( sToolTip );
140 imageBrowsePushButton->setIsActive( false );
141 imageBrowsePushButton->setToolTip( sToolTip );
142
143 // Rather dirty fix to align the design of the QTextEdit to
144 // the coloring of our custom QLineEdits.
145 infoTxt->setStyleSheet( QString( "\
146QTextEdit { \
147 color: %1; \
148 background-color: %2; \
149}" )
150 .arg( pPref->getColorTheme()->m_windowTextColor.name() )
151 .arg( pPref->getColorTheme()->m_windowColor.name() ) );
152
153 }
154
155 saveBtn->setFixedFontSize( 12 );
156 saveBtn->setSize( QSize( 70, 23 ) );
157 saveBtn->setBorderRadius( 3 );
158 m_cancelBtn->setFixedFontSize( 12 );
159 m_cancelBtn->setSize( QSize( 70, 23 ) );
160 m_cancelBtn->setBorderRadius( 3 );
161 imageBrowsePushButton->setFixedFontSize( 12 );
162 imageBrowsePushButton->setBorderRadius( 3 );
163 imageBrowsePushButton->setSize( QSize( 70, 23 ) );
164
165 contentTable->setColumnCount( 4 );
166 contentTable->setHorizontalHeaderLabels( QStringList() <<
167 tr( "Instrument" ) <<
168 tr( "Component" ) <<
169 tr( "Sample" ) <<
170 tr( "License" ) );
171 contentTable->verticalHeader()->hide();
172 contentTable->horizontalHeader()->setStretchLastSection( true );
173
174 contentTable->setColumnWidth( 0, 160 );
175 contentTable->setColumnWidth( 1, 80 );
176 contentTable->setColumnWidth( 2, 210 );
177
179}
180
181
187
188
191{
192 if ( m_pDrumkit != nullptr &&
193 ! m_pDrumkit->get_image().isEmpty() ) {
194 QString sImage = m_pDrumkit->get_path() + "/" + m_pDrumkit->get_image();
195 updateImage( sImage );
196 }
197 else {
198 drumkitImageLabel->hide();
199 }
200}
201
204 auto pSong = H2Core::Hydrogen::get_instance()->getSong();
205
206 if ( m_pDrumkit == nullptr ){
207 return;
208 }
209
210 auto contentVector = m_pDrumkit->summarizeContent();
211
212 if ( contentVector.size() > 0 ) {
213 contentTable->show();
214 contentLabel->show();
215 contentTable->setRowCount( contentVector.size() );
216
217 int nFirstMismatchRow = -1;
218
219 for ( int ii = 0; ii < contentVector.size(); ++ ii ) {
220 const auto ccontent = contentVector[ ii ];
221
222 QLineEdit* pInstrumentItem = new QLineEdit( ccontent->m_sInstrumentName );
223 pInstrumentItem->setEnabled( false );
224 pInstrumentItem->setToolTip( ccontent->m_sInstrumentName );
225 QLineEdit* pComponentItem = new QLineEdit( ccontent->m_sComponentName );
226 pComponentItem->setEnabled( false );
227 pComponentItem->setToolTip( ccontent->m_sComponentName );
228 QLineEdit* pSampleItem = new QLineEdit( ccontent->m_sSampleName );
229 pSampleItem->setEnabled( false );
230 pSampleItem->setToolTip( ccontent->m_sSampleName );
231 QLineEdit* pLicenseItem =
232 new QLineEdit( ccontent->m_license.getLicenseString() );
233 pLicenseItem->setEnabled( false );
234 pLicenseItem->setToolTip( ccontent->m_license.getLicenseString() );
235
236 // In case of a license mismatch we highlight the row
237 if ( ccontent->m_license != m_pDrumkit->get_license() ) {
238 QString sRed = QString( "color: %1; background-color: %2" )
239 .arg( pPref->getColorTheme()->m_buttonRedColor.name() )
240 .arg( pPref->getColorTheme()->m_windowColor.name() );
241 pInstrumentItem->setStyleSheet( sRed );
242 pComponentItem->setStyleSheet( sRed );
243 pSampleItem->setStyleSheet( sRed );
244 pLicenseItem->setStyleSheet( sRed );
245
246 if ( nFirstMismatchRow == -1 ) {
247 nFirstMismatchRow = ii;
248 }
249 }
250
251 contentTable->setCellWidget( ii, 0, pInstrumentItem );
252 contentTable->setCellWidget( ii, 1, pComponentItem );
253 contentTable->setCellWidget( ii, 2, pSampleItem );
254 contentTable->setCellWidget( ii, 3, pLicenseItem );
255 }
256
257 // In case of a mismatch scroll into view
258 if ( nFirstMismatchRow != -1 ) {
259 contentTable->showRow( nFirstMismatchRow );
260 }
261 }
262 else {
263 contentTable->hide();
264 contentLabel->hide();
265 }
266}
267
269
270 licenseStringTxt->setText( License::LicenseTypeToQString(
271 static_cast<License::LicenseType>( licenseComboBox->currentIndex() ) ) );
272
273 if ( licenseComboBox->currentIndex() == static_cast<int>( License::Unspecified ) ) {
274 licenseStringLbl->hide();
275 licenseStringTxt->hide();
276 }
277 else {
278 licenseStringLbl->show();
279 licenseStringTxt->show();
280 }
281
283}
284
286
287 imageLicenseStringTxt->setText( License::LicenseTypeToQString(
288 static_cast<License::LicenseType>( imageLicenseComboBox->currentIndex() ) ) );
289
290 if ( imageLicenseComboBox->currentIndex() == static_cast<int>( License::Unspecified ) ) {
291 imageLicenseStringLbl->hide();
292 imageLicenseStringTxt->hide();
293 }
294 else {
295 imageLicenseStringLbl->show();
296 imageLicenseStringTxt->show();
297 }
298}
299
301{
302 QPixmap *pPixmap = new QPixmap ( filename );
303
304 // Check whether the loading worked.
305 if ( pPixmap->isNull() ) {
306 ERRORLOG( QString( "Unable to load pixmap from [%1]" ).arg( filename ) );
307 drumkitImageLabel->hide();
308 return;
309 }
310
311 // scale the image down to fit if required
312 int x = (int) drumkitImageLabel->size().width();
313 int y = drumkitImageLabel->size().height();
314 float labelAspect = (float) x / y;
315 float imageAspect = (float) pPixmap->width() / pPixmap->height();
316
317 if ( ( x < pPixmap->width() ) || ( y < pPixmap->height() ) )
318 {
319 if ( labelAspect >= imageAspect )
320 {
321 // image is taller or the same as label frame
322 *pPixmap = pPixmap->scaledToHeight( y );
323 }
324 else
325 {
326 // image is wider than label frame
327 *pPixmap = pPixmap->scaledToWidth( x );
328 }
329 }
330 drumkitImageLabel->setPixmap(*pPixmap);
331 drumkitImageLabel->show();
332
333}
334
336{
337 if ( m_pDrumkit == nullptr ) {
338 return;
339 }
340
341 // Try to get the drumkit directory and open file browser
342 QString sDrumkitDir = m_pDrumkit->get_path();
343
344 QString sFilePath = QFileDialog::getOpenFileName(
345 this, tr("Open Image"), sDrumkitDir,
346 tr("Image Files (*.png *.jpg *.jpeg)"), nullptr
347#if not defined(WIN32) and not defined(__APPLE__) // Linux
348 // See FileDialog.h for details
349 , QFileDialog::DontUseNativeDialog
350#endif
351 );
352
353 // If cancel was clicked just abort
354 if ( sFilePath == nullptr || sFilePath.isEmpty() ) {
355 return;
356 }
357
358 m_sNewImagePath = sFilePath;
359
360 QFileInfo fileInfo( sFilePath );
361 QString sFileName( fileInfo.fileName() );
362 imageText->setText( sFileName );
363
364 updateImage( sFilePath );
365}
366
368{
369 if ( m_pDrumkit == nullptr ) {
370 return;
371 }
372
373 auto pHydrogen = Hydrogen::get_instance();
374 auto pSong = pHydrogen->getSong();
375 auto pCommonStrings = HydrogenApp::get_instance()->getCommonStrings();
376
377 // Sanity checks.
378 //
379 // Check whether the license strings from the line edits comply to
380 // the license types selected in the combo boxes.
381 License licenseCheck( licenseStringTxt->text() );
382 if ( static_cast<int>(licenseCheck.getType()) != licenseComboBox->currentIndex() ) {
383 if ( QMessageBox::warning( this, "Hydrogen",
384 tr( "Specified drumkit License String does not comply with the license selected in the combo box." ),
385 QMessageBox::Ok | QMessageBox::Cancel,
386 QMessageBox::Cancel )
387 == QMessageBox::Cancel ) {
388 WARNINGLOG( QString( "Abort, since drumkit License String [%1] does not comply to selected License Type [%2]" )
389 .arg( licenseStringTxt->text() )
391 static_cast<License::LicenseType>(licenseComboBox->currentIndex()) ) ) );
392 return;
393 }
394 }
395 License imageLicenseCheck( imageLicenseStringTxt->text() );
396 if ( static_cast<int>(imageLicenseCheck.getType()) !=
397 imageLicenseComboBox->currentIndex() ) {
398 if ( QMessageBox::warning( this, "Hydrogen",
399 tr( "Specified image License String does not comply with the license selected in the combo box." ),
400 QMessageBox::Ok | QMessageBox::Cancel,
401 QMessageBox::Cancel )
402 == QMessageBox::Cancel ) {
403 WARNINGLOG( QString( "Abort, since drumkit image License String [%1] does not comply to selected License Type [%2]" )
404 .arg( imageLicenseStringTxt->text() )
406 static_cast<License::LicenseType>(imageLicenseComboBox->currentIndex()) ) ) );
407 return;
408 }
409 }
410
411 //check the name and set the drumkitinfo to current drumkit
412 if ( nameTxt->text().isEmpty() ){
413 QMessageBox::warning( this, "Hydrogen", tr( "The name of the drumkit must not be left empty" ) );
414 return;
415 }
416
417 QString sNewLicenseString( licenseStringTxt->text() );
418 if ( licenseComboBox->currentIndex() ==
419 static_cast<int>(License::Unspecified) ) {
420 sNewLicenseString = "";
421 }
422 License newLicense( sNewLicenseString );
423 newLicense.setCopyrightHolder( m_pDrumkit->get_author() );
424
425 QString sNewImageLicenseString( imageLicenseStringTxt->text() );
426 if ( imageLicenseComboBox->currentIndex() ==
427 static_cast<int>(License::Unspecified) ) {
428 sNewImageLicenseString = "";
429 }
430 License newImageLicense( sNewImageLicenseString );
431 newImageLicense.setCopyrightHolder( m_pDrumkit->get_author() );
432
433 const QString sOldPath = m_pDrumkit->get_path();
434 if ( m_pDrumkit->get_name() != nameTxt->text() ) {
435 m_pDrumkit->set_name( nameTxt->text() );
437 nameTxt->text() );
438 }
439 m_pDrumkit->set_author( authorTxt->text() );
440 m_pDrumkit->set_info( infoTxt->toHtml() );
441
442 // Only update the license in case it changed (in order to not
443 // overwrite an attribution).
444 if ( m_pDrumkit->get_license() != newLicense ) {
445 m_pDrumkit->set_license( newLicense );
446 }
447
449 ERRORLOG( "User cancelled dialog due to licensing issues." );
450 return;
451 }
452
453 // Will contain image which should be removed. To keep the previous image,
454 // this string should be empty.
455 QString sOldImagePath;
456 if ( imageText->text() != m_pDrumkit->get_image() ) {
457 int nRes = QMessageBox::information( this, "Hydrogen",
458 tr( "Delete previous drumkit image" )
459 .append( QString( " [%1]" ).arg( m_pDrumkit->get_image() ) ),
460 QMessageBox::Yes | QMessageBox::No );
461 if ( nRes == QMessageBox::Yes ) {
462 sOldImagePath = QString( "%1/%2" ).arg( sOldPath )
463 .arg( m_pDrumkit->get_image() );
464 }
465 m_pDrumkit->set_image( imageText->text() );
466 }
467
468 if ( m_pDrumkit->get_image_license() != newImageLicense ) {
469 m_pDrumkit->set_image_license( newImageLicense );
470 }
471
472 QApplication::setOverrideCursor(Qt::WaitCursor);
473
474 // Write new properties to disk.
475 if ( ! m_pDrumkit->save() ) {
476 QApplication::restoreOverrideCursor();
477 QMessageBox::information( this, "Hydrogen", tr ( "Saving of this drumkit failed."));
478 ERRORLOG( "Saving of this drumkit failed." );
479 return;
480 }
481
482 // Copy the selected image into the drumkit folder (in case a file outside
483 // of it was selected.)
484 if ( ! m_sNewImagePath.isEmpty() ) {
485 QFileInfo fileInfo( m_sNewImagePath );
486
487 if ( fileInfo.dir().absolutePath() != m_pDrumkit->get_path() ) {
488 INFOLOG( QString( "Copying [%1] into [%2]" ).arg( m_sNewImagePath )
489 .arg( m_pDrumkit->get_path() ) );
490 const QString sTargetPath =
491 QString( "%1/%2" ).arg( m_pDrumkit->get_path() )
492 .arg( fileInfo.fileName() );
493 // Logging is done in file_copy.
494 Filesystem::file_copy( m_sNewImagePath, sTargetPath, true, false );
495 }
496 }
497
498 if ( ! sOldImagePath.isEmpty() ) {
499 Filesystem::rm( sOldImagePath, false, false );
500 }
501
502 pHydrogen->getSoundLibraryDatabase()->updateDrumkits();
503
504 QApplication::restoreOverrideCursor();
505
506 accept();
507
508}
509
510}
#define INFOLOG(x)
Definition Object.h:240
#define WARNINGLOG(x)
Definition Object.h:241
#define ERRORLOG(x)
Definition Object.h:242
static bool file_copy(const QString &src, const QString &dst, bool overwrite=false, bool bSilent=false)
copy a source file to a destination
static DrumkitType determineDrumkitType(const QString &sPath)
static QString usr_drumkits_dir()
returns user drumkits path
static bool rm(const QString &path, bool recursive=false, bool bSilent=false)
remove a path
@ SessionReadWrite
Kit was loaded via a NSM session, OSC command, or CLI option, only persist for the current Hydrogen s...
Definition Filesystem.h:86
@ User
Kit was installed by the user, is automatically loaded, and most probably writable.
Definition Filesystem.h:78
std::shared_ptr< Song > getSong() const
Get the current song.
Definition Hydrogen.h:123
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:84
Wrapper class to help Hydrogen deal with the license information specified in a drumkit.
Definition License.h:48
LicenseType
A couple of recognized licenses.
Definition License.h:58
@ Unspecified
No license set yet.
Definition License.h:74
LicenseType getType() const
Definition License.h:143
void setCopyrightHolder(const QString &sCopyrightHolder)
Definition License.h:152
QString getLicenseString() const
Definition License.h:146
static QString LicenseTypeToQString(LicenseType license)
Definition License.h:155
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
SoundLibraryPropertiesDialog(QWidget *pParent, std::shared_ptr< Drumkit > pDrumkit, bool bDrumkitNameLocked)
void showEvent(QShowEvent *e) override
On showing the dialog (after layout sizes have been applied), load the drumkit image if any.
bool m_bDrumkitNameLocked
This dialog can be accessed both via SoundLibrary/MainForm > Drumkits -> Properties and MainForm > Dr...
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
std::shared_ptr< CommonStrings > getCommonStrings()
static bool checkDrumkitLicense(std::shared_ptr< H2Core::Drumkit > pDrumkit)
void setupLicenseComboBox(QComboBox *pComboBox)