1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2011 LoRd_MuldeR <MuldeR2@GMX.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
22 #include "Dialog_MainWindow.h"
27 #include "Dialog_WorkingBanner.h"
28 #include "Dialog_MetaInfo.h"
29 #include "Dialog_About.h"
30 #include "Dialog_Update.h"
31 #include "Dialog_DropBox.h"
32 #include "Thread_FileAnalyzer.h"
33 #include "Thread_MessageHandler.h"
34 #include "Model_MetaInfo.h"
35 #include "Model_Settings.h"
36 #include "Model_FileList.h"
37 #include "Model_FileSystem.h"
38 #include "WinSevenTaskbar.h"
39 #include "Registry_Decoder.h"
42 #include <QMessageBox>
44 #include <QDesktopWidget>
46 #include <QFileDialog>
47 #include <QInputDialog>
48 #include <QFileSystemModel>
49 #include <QDesktopServices>
51 #include <QPlastiqueStyle>
52 #include <QCleanlooksStyle>
53 #include <QWindowsVistaStyle>
54 #include <QWindowsStyle>
56 #include <QDragEnterEvent>
57 #include <QWindowsMime>
60 #include <QProcessEnvironment>
61 #include <QCryptographicHash>
62 #include <QTranslator>
70 #define ABORT_IF_BUSY if(m_banner->isVisible() || m_delayedFileTimer->isActive()) { MessageBeep(MB_ICONEXCLAMATION); return; }
71 #define SET_TEXT_COLOR(WIDGET,COLOR) { QPalette _palette = WIDGET->palette(); _palette.setColor(QPalette::WindowText, COLOR); WIDGET->setPalette(_palette); }
72 #define SET_FONT_BOLD(WIDGET,BOLD) { QFont _font = WIDGET->font(); _font.setBold(BOLD); WIDGET->setFont(_font); }
73 #define FLASH_WINDOW(WND) { FLASHWINFO flashInfo; memset(&flashInfo, 0, sizeof(FLASHWINFO)); flashInfo.cbSize = sizeof(FLASHWINFO); flashInfo.dwFlags = FLASHW_ALL; flashInfo.uCount = 12; flashInfo.dwTimeout = 125; flashInfo.hwnd = WND->winId(); FlashWindowEx(&flashInfo); }
74 #define LINK(URL) QString("<a href=\"%1\">%2</a>").arg(URL).arg(URL)
75 #define TEMP_HIDE_DROPBOX(CMD) { bool __dropBoxVisible = m_dropBox->isVisible(); if(__dropBoxVisible) m_dropBox->hide(); CMD; if(__dropBoxVisible) m_dropBox->show(); }
78 //class Index: public QObjectUserData
81 // Index(int index) { m_index = index; }
82 // int value(void) { return m_index; }
87 ////////////////////////////////////////////////////////////
89 ////////////////////////////////////////////////////////////
91 MainWindow::MainWindow(FileListModel
*fileListModel
, AudioFileModel
*metaInfo
, SettingsModel
*settingsModel
, QWidget
*parent
)
94 m_fileListModel(fileListModel
),
96 m_settings(settingsModel
),
98 m_firstTimeShown(true)
100 //Init the dialog, from the .ui file
102 setWindowFlags(windowFlags() ^ Qt::WindowMaximizeButtonHint
);
104 //Register meta types
105 qRegisterMetaType
<AudioFileModel
>("AudioFileModel");
107 //Enabled main buttons
108 connect(buttonAbout
, SIGNAL(clicked()), this, SLOT(aboutButtonClicked()));
109 connect(buttonStart
, SIGNAL(clicked()), this, SLOT(encodeButtonClicked()));
110 connect(buttonQuit
, SIGNAL(clicked()), this, SLOT(closeButtonClicked()));
113 tabWidget
->setCurrentIndex(0);
114 connect(tabWidget
, SIGNAL(currentChanged(int)), this, SLOT(tabPageChanged(int)));
117 sourceFileView
->setModel(m_fileListModel
);
118 sourceFileView
->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents
);
119 sourceFileView
->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents
);
120 sourceFileView
->setContextMenuPolicy(Qt::CustomContextMenu
);
121 m_dropNoteLabel
= new QLabel(sourceFileView
);
122 m_dropNoteLabel
->setAlignment(Qt::AlignHCenter
| Qt::AlignVCenter
);
123 SET_FONT_BOLD(m_dropNoteLabel
, true);
124 SET_TEXT_COLOR(m_dropNoteLabel
, Qt::darkGray
);
125 m_sourceFilesContextMenu
= new QMenu();
126 m_showDetailsContextAction
= m_sourceFilesContextMenu
->addAction(QIcon(":/icons/zoom.png"), "N/A");
127 m_previewContextAction
= m_sourceFilesContextMenu
->addAction(QIcon(":/icons/sound.png"), "N/A");
128 m_findFileContextAction
= m_sourceFilesContextMenu
->addAction(QIcon(":/icons/folder_go.png"), "N/A");
129 SET_FONT_BOLD(m_showDetailsContextAction
, true);
130 connect(buttonAddFiles
, SIGNAL(clicked()), this, SLOT(addFilesButtonClicked()));
131 connect(buttonRemoveFile
, SIGNAL(clicked()), this, SLOT(removeFileButtonClicked()));
132 connect(buttonClearFiles
, SIGNAL(clicked()), this, SLOT(clearFilesButtonClicked()));
133 connect(buttonFileUp
, SIGNAL(clicked()), this, SLOT(fileUpButtonClicked()));
134 connect(buttonFileDown
, SIGNAL(clicked()), this, SLOT(fileDownButtonClicked()));
135 connect(buttonShowDetails
, SIGNAL(clicked()), this, SLOT(showDetailsButtonClicked()));
136 connect(m_fileListModel
, SIGNAL(rowsInserted(QModelIndex
,int,int)), this, SLOT(sourceModelChanged()));
137 connect(m_fileListModel
, SIGNAL(rowsRemoved(QModelIndex
,int,int)), this, SLOT(sourceModelChanged()));
138 connect(m_fileListModel
, SIGNAL(modelReset()), this, SLOT(sourceModelChanged()));
139 connect(sourceFileView
, SIGNAL(customContextMenuRequested(QPoint
)), this, SLOT(sourceFilesContextMenu(QPoint
)));
140 connect(m_showDetailsContextAction
, SIGNAL(triggered(bool)), this, SLOT(showDetailsButtonClicked()));
141 connect(m_previewContextAction
, SIGNAL(triggered(bool)), this, SLOT(previewContextActionTriggered()));
142 connect(m_findFileContextAction
, SIGNAL(triggered(bool)), this, SLOT(findFileContextActionTriggered()));
145 m_fileSystemModel
= new QFileSystemModelEx();
146 m_fileSystemModel
->setRootPath(m_fileSystemModel
->rootPath());
147 m_fileSystemModel
->installEventFilter(this);
148 outputFolderView
->setModel(m_fileSystemModel
);
149 outputFolderView
->header()->setStretchLastSection(true);
150 outputFolderView
->header()->hideSection(1);
151 outputFolderView
->header()->hideSection(2);
152 outputFolderView
->header()->hideSection(3);
153 outputFolderView
->setHeaderHidden(true);
154 outputFolderView
->setAnimated(true);
155 outputFolderView
->setMouseTracking(false);
156 outputFolderView
->setContextMenuPolicy(Qt::CustomContextMenu
);
157 while(saveToSourceFolderCheckBox
->isChecked() != m_settings
->outputToSourceDir()) saveToSourceFolderCheckBox
->click();
158 prependRelativePathCheckBox
->setChecked(m_settings
->prependRelativeSourcePath());
159 connect(outputFolderView
, SIGNAL(clicked(QModelIndex
)), this, SLOT(outputFolderViewClicked(QModelIndex
)));
160 connect(outputFolderView
, SIGNAL(activated(QModelIndex
)), this, SLOT(outputFolderViewClicked(QModelIndex
)));
161 connect(outputFolderView
, SIGNAL(pressed(QModelIndex
)), this, SLOT(outputFolderViewClicked(QModelIndex
)));
162 connect(outputFolderView
, SIGNAL(entered(QModelIndex
)), this, SLOT(outputFolderViewMoved(QModelIndex
)));
163 outputFolderView
->setCurrentIndex(m_fileSystemModel
->index(m_settings
->outputDir()));
164 outputFolderViewClicked(outputFolderView
->currentIndex());
165 connect(buttonMakeFolder
, SIGNAL(clicked()), this, SLOT(makeFolderButtonClicked()));
166 connect(buttonGotoHome
, SIGNAL(clicked()), SLOT(gotoHomeFolderButtonClicked()));
167 connect(buttonGotoDesktop
, SIGNAL(clicked()), this, SLOT(gotoDesktopButtonClicked()));
168 connect(buttonGotoMusic
, SIGNAL(clicked()), this, SLOT(gotoMusicFolderButtonClicked()));
169 connect(saveToSourceFolderCheckBox
, SIGNAL(clicked()), this, SLOT(saveToSourceFolderChanged()));
170 connect(prependRelativePathCheckBox
, SIGNAL(clicked()), this, SLOT(prependRelativePathChanged()));
171 m_outputFolderContextMenu
= new QMenu();
172 m_showFolderContextAction
= m_outputFolderContextMenu
->addAction(QIcon(":/icons/zoom.png"), "N/A");
173 connect(outputFolderView
, SIGNAL(customContextMenuRequested(QPoint
)), this, SLOT(outputFolderContextMenu(QPoint
)));
174 connect(m_showFolderContextAction
, SIGNAL(triggered(bool)), this, SLOT(showFolderContextActionTriggered()));
175 outputFolderLabel
->installEventFilter(this);
177 //Setup "Meta Data" tab
178 m_metaInfoModel
= new MetaInfoModel(m_metaData
, 6);
179 m_metaInfoModel
->clearData();
180 metaDataView
->setModel(m_metaInfoModel
);
181 metaDataView
->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents
);
182 metaDataView
->verticalHeader()->hide();
183 metaDataView
->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents
);
184 while(writeMetaDataCheckBox
->isChecked() != m_settings
->writeMetaTags()) writeMetaDataCheckBox
->click();
185 generatePlaylistCheckBox
->setChecked(m_settings
->createPlaylist());
186 connect(buttonEditMeta
, SIGNAL(clicked()), this, SLOT(editMetaButtonClicked()));
187 connect(buttonClearMeta
, SIGNAL(clicked()), this, SLOT(clearMetaButtonClicked()));
188 connect(writeMetaDataCheckBox
, SIGNAL(clicked()), this, SLOT(metaTagsEnabledChanged()));
189 connect(generatePlaylistCheckBox
, SIGNAL(clicked()), this, SLOT(playlistEnabledChanged()));
191 //Setup "Compression" tab
192 m_encoderButtonGroup
= new QButtonGroup(this);
193 m_encoderButtonGroup
->addButton(radioButtonEncoderMP3
, SettingsModel::MP3Encoder
);
194 m_encoderButtonGroup
->addButton(radioButtonEncoderVorbis
, SettingsModel::VorbisEncoder
);
195 m_encoderButtonGroup
->addButton(radioButtonEncoderAAC
, SettingsModel::AACEncoder
);
196 m_encoderButtonGroup
->addButton(radioButtonEncoderFLAC
, SettingsModel::FLACEncoder
);
197 m_encoderButtonGroup
->addButton(radioButtonEncoderPCM
, SettingsModel::PCMEncoder
);
198 m_modeButtonGroup
= new QButtonGroup(this);
199 m_modeButtonGroup
->addButton(radioButtonModeQuality
, SettingsModel::VBRMode
);
200 m_modeButtonGroup
->addButton(radioButtonModeAverageBitrate
, SettingsModel::ABRMode
);
201 m_modeButtonGroup
->addButton(radioButtonConstBitrate
, SettingsModel::CBRMode
);
202 radioButtonEncoderMP3
->setChecked(m_settings
->compressionEncoder() == SettingsModel::MP3Encoder
);
203 radioButtonEncoderVorbis
->setChecked(m_settings
->compressionEncoder() == SettingsModel::VorbisEncoder
);
204 radioButtonEncoderAAC
->setChecked(m_settings
->compressionEncoder() == SettingsModel::AACEncoder
);
205 radioButtonEncoderFLAC
->setChecked(m_settings
->compressionEncoder() == SettingsModel::FLACEncoder
);
206 radioButtonEncoderPCM
->setChecked(m_settings
->compressionEncoder() == SettingsModel::PCMEncoder
);
207 radioButtonModeQuality
->setChecked(m_settings
->compressionRCMode() == SettingsModel::VBRMode
);
208 radioButtonModeAverageBitrate
->setChecked(m_settings
->compressionRCMode() == SettingsModel::ABRMode
);
209 radioButtonConstBitrate
->setChecked(m_settings
->compressionRCMode() == SettingsModel::CBRMode
);
210 sliderBitrate
->setValue(m_settings
->compressionBitrate());
211 connect(m_encoderButtonGroup
, SIGNAL(buttonClicked(int)), this, SLOT(updateEncoder(int)));
212 connect(m_modeButtonGroup
, SIGNAL(buttonClicked(int)), this, SLOT(updateRCMode(int)));
213 connect(sliderBitrate
, SIGNAL(valueChanged(int)), this, SLOT(updateBitrate(int)));
214 updateEncoder(m_encoderButtonGroup
->checkedId());
216 //Setup "Advanced Options" tab
217 sliderLameAlgoQuality
->setValue(m_settings
->lameAlgoQuality());
218 spinBoxBitrateManagementMin
->setValue(m_settings
->bitrateManagementMinRate());
219 spinBoxBitrateManagementMax
->setValue(m_settings
->bitrateManagementMaxRate());
220 spinBoxNormalizationFilter
->setValue(static_cast<double>(m_settings
->normalizationFilterMaxVolume()) / 100.0);
221 comboBoxMP3ChannelMode
->setCurrentIndex(m_settings
->lameChannelMode());
222 comboBoxSamplingRate
->setCurrentIndex(m_settings
->samplingRate());
223 comboBoxNeroAACProfile
->setCurrentIndex(m_settings
->neroAACProfile());
224 while(checkBoxBitrateManagement
->isChecked() != m_settings
->bitrateManagementEnabled()) checkBoxBitrateManagement
->click();
225 while(checkBoxNeroAAC2PassMode
->isChecked() != m_settings
->neroAACEnable2Pass()) checkBoxNeroAAC2PassMode
->click();
226 while(checkBoxNormalizationFilter
->isChecked() != m_settings
->normalizationFilterEnabled()) checkBoxNormalizationFilter
->click();
227 connect(sliderLameAlgoQuality
, SIGNAL(valueChanged(int)), this, SLOT(updateLameAlgoQuality(int)));
228 connect(checkBoxBitrateManagement
, SIGNAL(clicked(bool)), this, SLOT(bitrateManagementEnabledChanged(bool)));
229 connect(spinBoxBitrateManagementMin
, SIGNAL(valueChanged(int)), this, SLOT(bitrateManagementMinChanged(int)));
230 connect(spinBoxBitrateManagementMax
, SIGNAL(valueChanged(int)), this, SLOT(bitrateManagementMaxChanged(int)));
231 connect(comboBoxMP3ChannelMode
, SIGNAL(currentIndexChanged(int)), this, SLOT(channelModeChanged(int)));
232 connect(comboBoxSamplingRate
, SIGNAL(currentIndexChanged(int)), this, SLOT(samplingRateChanged(int)));
233 connect(checkBoxNeroAAC2PassMode
, SIGNAL(clicked(bool)), this, SLOT(neroAAC2PassChanged(bool)));
234 connect(comboBoxNeroAACProfile
, SIGNAL(currentIndexChanged(int)), this, SLOT(neroAACProfileChanged(int)));
235 connect(checkBoxNormalizationFilter
, SIGNAL(clicked(bool)), this, SLOT(normalizationEnabledChanged(bool)));
236 connect(spinBoxNormalizationFilter
, SIGNAL(valueChanged(double)), this, SLOT(normalizationMaxVolumeChanged(double)));
237 connect(buttonResetAdvancedOptions
, SIGNAL(clicked()), this, SLOT(resetAdvancedOptionsButtonClicked()));
238 updateLameAlgoQuality(sliderLameAlgoQuality
->value());
240 //Activate file menu actions
241 connect(actionOpenFolder
, SIGNAL(triggered()), this, SLOT(openFolderActionActivated()));
243 //Activate view menu actions
244 m_tabActionGroup
= new QActionGroup(this);
245 m_tabActionGroup
->addAction(actionSourceFiles
);
246 m_tabActionGroup
->addAction(actionOutputDirectory
);
247 m_tabActionGroup
->addAction(actionCompression
);
248 m_tabActionGroup
->addAction(actionMetaData
);
249 m_tabActionGroup
->addAction(actionAdvancedOptions
);
250 actionSourceFiles
->setData(0);
251 actionOutputDirectory
->setData(1);
252 actionMetaData
->setData(2);
253 actionCompression
->setData(3);
254 actionAdvancedOptions
->setData(4);
255 actionSourceFiles
->setChecked(true);
256 connect(m_tabActionGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(tabActionActivated(QAction
*)));
258 //Activate style menu actions
259 m_styleActionGroup
= new QActionGroup(this);
260 m_styleActionGroup
->addAction(actionStylePlastique
);
261 m_styleActionGroup
->addAction(actionStyleCleanlooks
);
262 m_styleActionGroup
->addAction(actionStyleWindowsVista
);
263 m_styleActionGroup
->addAction(actionStyleWindowsXP
);
264 m_styleActionGroup
->addAction(actionStyleWindowsClassic
);
265 actionStylePlastique
->setData(0);
266 actionStyleCleanlooks
->setData(1);
267 actionStyleWindowsVista
->setData(2);
268 actionStyleWindowsXP
->setData(3);
269 actionStyleWindowsClassic
->setData(4);
270 actionStylePlastique
->setChecked(true);
271 actionStyleWindowsXP
->setEnabled((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based
) >= QSysInfo::WV_XP
&& lamexp_themes_enabled());
272 actionStyleWindowsVista
->setEnabled((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based
) >= QSysInfo::WV_VISTA
&& lamexp_themes_enabled());
273 connect(m_styleActionGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(styleActionActivated(QAction
*)));
274 styleActionActivated(NULL
);
276 //Populate the language menu
277 m_languageActionGroup
= new QActionGroup(this);
278 QStringList translations
= lamexp_query_translations();
279 while(!translations
.isEmpty())
281 QString langId
= translations
.takeFirst();
282 QAction
*currentLanguage
= new QAction(this);
283 currentLanguage
->setData(langId
);
284 currentLanguage
->setText(lamexp_translation_name(langId
));
285 currentLanguage
->setIcon(QIcon(QString(":/flags/%1.png").arg(langId
)));
286 currentLanguage
->setCheckable(true);
287 m_languageActionGroup
->addAction(currentLanguage
);
288 menuLanguage
->insertAction(actionLoadTranslationFromFile
, currentLanguage
);
290 menuLanguage
->insertSeparator(actionLoadTranslationFromFile
);
291 connect(actionLoadTranslationFromFile
, SIGNAL(triggered(bool)), this, SLOT(languageFromFileActionActivated(bool)));
292 connect(m_languageActionGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(languageActionActivated(QAction
*)));
294 //Activate tools menu actions
295 actionDisableUpdateReminder
->setChecked(!m_settings
->autoUpdateEnabled());
296 actionDisableSounds
->setChecked(!m_settings
->soundsEnabled());
297 actionDisableNeroAacNotifications
->setChecked(!m_settings
->neroAacNotificationsEnabled());
298 actionDisableWmaDecoderNotifications
->setChecked(!m_settings
->wmaDecoderNotificationsEnabled());
299 connect(actionDisableUpdateReminder
, SIGNAL(triggered(bool)), this, SLOT(disableUpdateReminderActionTriggered(bool)));
300 connect(actionDisableSounds
, SIGNAL(triggered(bool)), this, SLOT(disableSoundsActionTriggered(bool)));
301 connect(actionInstallWMADecoder
, SIGNAL(triggered(bool)), this, SLOT(installWMADecoderActionTriggered(bool)));
302 connect(actionDisableNeroAacNotifications
, SIGNAL(triggered(bool)), this, SLOT(disableNeroAacNotificationsActionTriggered(bool)));
303 connect(actionDisableWmaDecoderNotifications
, SIGNAL(triggered(bool)), this, SLOT(disableWmaDecoderNotificationsActionTriggered(bool)));
304 connect(actionShowDropBoxWidget
, SIGNAL(triggered(bool)), this, SLOT(showDropBoxWidgetActionTriggered(bool)));
306 //Activate help menu actions
307 connect(actionCheckUpdates
, SIGNAL(triggered()), this, SLOT(checkUpdatesActionActivated()));
308 connect(actionVisitHomepage
, SIGNAL(triggered()), this, SLOT(visitHomepageActionActivated()));
310 //Center window in screen
311 QRect desktopRect
= QApplication::desktop()->screenGeometry();
312 QRect thisRect
= this->geometry();
313 move((desktopRect
.width() - thisRect
.width()) / 2, (desktopRect
.height() - thisRect
.height()) / 2);
314 setMinimumSize(thisRect
.width(), thisRect
.height());
317 m_banner
= new WorkingBanner(this);
319 //Create DropBox widget
320 m_dropBox
= new DropBox(this, m_fileListModel
, m_settings
);
321 connect(m_fileListModel
, SIGNAL(modelReset()), m_dropBox
, SLOT(modelChanged()));
322 connect(m_fileListModel
, SIGNAL(rowsInserted(QModelIndex
,int,int)), m_dropBox
, SLOT(modelChanged()));
323 connect(m_fileListModel
, SIGNAL(rowsRemoved(QModelIndex
,int,int)), m_dropBox
, SLOT(modelChanged()));
325 //Create message handler thread
326 m_messageHandler
= new MessageHandlerThread();
327 m_delayedFileList
= new QStringList();
328 m_delayedFileTimer
= new QTimer();
329 connect(m_messageHandler
, SIGNAL(otherInstanceDetected()), this, SLOT(notifyOtherInstance()), Qt::QueuedConnection
);
330 connect(m_messageHandler
, SIGNAL(fileReceived(QString
)), this, SLOT(addFileDelayed(QString
)), Qt::QueuedConnection
);
331 connect(m_messageHandler
, SIGNAL(killSignalReceived()), this, SLOT(close()), Qt::QueuedConnection
);
332 connect(m_delayedFileTimer
, SIGNAL(timeout()), this, SLOT(handleDelayedFiles()));
333 m_messageHandler
->start();
335 //Load translation file
336 QList
<QAction
*> languageActions
= m_languageActionGroup
->actions();
337 while(!languageActions
.isEmpty())
339 QAction
*currentLanguage
= languageActions
.takeFirst();
340 if(currentLanguage
->data().toString().compare(m_settings
->currentLanguage(), Qt::CaseInsensitive
) == 0)
342 currentLanguage
->setChecked(true);
343 languageActionActivated(currentLanguage
);
347 //Re-translate (make sure we translate once)
348 QEvent
languageChangeEvent(QEvent::LanguageChange
);
349 changeEvent(&languageChangeEvent
);
352 this->setAcceptDrops(true);
355 ////////////////////////////////////////////////////////////
357 ////////////////////////////////////////////////////////////
359 MainWindow::~MainWindow(void)
361 //Stop message handler thread
362 if(m_messageHandler
&& m_messageHandler
->isRunning())
364 m_messageHandler
->stop();
365 if(!m_messageHandler
->wait(10000))
367 m_messageHandler
->terminate();
368 m_messageHandler
->wait();
373 sourceFileView
->setModel(NULL
);
374 metaDataView
->setModel(NULL
);
377 LAMEXP_DELETE(m_tabActionGroup
);
378 LAMEXP_DELETE(m_styleActionGroup
);
379 LAMEXP_DELETE(m_languageActionGroup
);
380 LAMEXP_DELETE(m_banner
);
381 LAMEXP_DELETE(m_fileSystemModel
);
382 LAMEXP_DELETE(m_messageHandler
);
383 LAMEXP_DELETE(m_delayedFileList
);
384 LAMEXP_DELETE(m_delayedFileTimer
);
385 LAMEXP_DELETE(m_metaInfoModel
);
386 LAMEXP_DELETE(m_encoderButtonGroup
);
387 LAMEXP_DELETE(m_encoderButtonGroup
);
388 LAMEXP_DELETE(m_sourceFilesContextMenu
);
389 LAMEXP_DELETE(m_dropBox
);
393 ////////////////////////////////////////////////////////////
395 ////////////////////////////////////////////////////////////
398 * Add file to source list
400 void MainWindow::addFiles(const QStringList
&files
)
407 tabWidget
->setCurrentIndex(0);
409 FileAnalyzer
*analyzer
= new FileAnalyzer(files
);
410 connect(analyzer
, SIGNAL(fileSelected(QString
)), m_banner
, SLOT(setText(QString
)), Qt::QueuedConnection
);
411 connect(analyzer
, SIGNAL(fileAnalyzed(AudioFileModel
)), m_fileListModel
, SLOT(addFile(AudioFileModel
)), Qt::QueuedConnection
);
413 m_banner
->show(tr("Adding file(s), please wait..."), analyzer
);
415 if(analyzer
->filesDenied())
417 QMessageBox::warning(this, tr("Access Denied"), QString("<nobr>%1<br>%2</nobr>").arg(tr("%1 file(s) have been rejected, because read access was not granted!").arg(analyzer
->filesDenied()), tr("This usually means the file is locked by another process.")));
419 if(analyzer
->filesRejected())
421 QMessageBox::warning(this, tr("Files Rejected"), QString("<nobr>%1<br>%2</nobr>").arg(tr("%1 file(s) have been rejected, because the file format could not be recognized!").arg(analyzer
->filesRejected()), tr("This usually means the file is damaged or the file format is not supported.")));
424 LAMEXP_DELETE(analyzer
);
425 sourceFileView
->scrollToBottom();
429 ////////////////////////////////////////////////////////////
431 ////////////////////////////////////////////////////////////
434 * Window is about to be shown
436 void MainWindow::showEvent(QShowEvent
*event
)
439 m_dropNoteLabel
->setGeometry(0, 0, sourceFileView
->width(), sourceFileView
->height());
440 sourceModelChanged();
441 tabWidget
->setCurrentIndex(0);
445 m_firstTimeShown
= false;
446 QTimer::singleShot(0, this, SLOT(windowShown()));
450 if(m_settings
->dropBoxWidgetEnabled())
452 m_dropBox
->setVisible(true);
458 * Re-translate the UI
460 void MainWindow::changeEvent(QEvent
*e
)
462 if(e
->type() == QEvent::LanguageChange
)
464 int comboBoxIndex
[3];
466 //Backup combobox indices
467 comboBoxIndex
[0] = comboBoxMP3ChannelMode
->currentIndex();
468 comboBoxIndex
[1] = comboBoxSamplingRate
->currentIndex();
469 comboBoxIndex
[2] = comboBoxNeroAACProfile
->currentIndex();
471 //Re.translate from UIC
472 Ui::MainWindow::retranslateUi(this);
474 //Restore combobox indices
475 comboBoxMP3ChannelMode
->setCurrentIndex(comboBoxIndex
[0]);
476 comboBoxSamplingRate
->setCurrentIndex(comboBoxIndex
[1]);
477 comboBoxNeroAACProfile
->setCurrentIndex(comboBoxIndex
[2]);
479 if(lamexp_version_demo())
481 setWindowTitle(QString("%1 [%2]").arg(windowTitle(), tr("DEMO VERSION")));
484 //Manual re-translate
485 m_dropNoteLabel
->setText(QString("» %1 «").arg(tr("You can drop in audio files here!")));
486 m_showDetailsContextAction
->setText(tr("Show Details"));
487 m_previewContextAction
->setText(tr("Open File in External Application"));
488 m_findFileContextAction
->setText(tr("Browse File Location"));
489 m_showFolderContextAction
->setText(tr("Browse Selected Folder"));
492 m_metaInfoModel
->clearData();
493 updateEncoder(m_settings
->compressionEncoder());
494 updateLameAlgoQuality(sliderLameAlgoQuality
->value());
499 * File dragged over window
501 void MainWindow::dragEnterEvent(QDragEnterEvent
*event
)
503 QStringList formats
= event
->mimeData()->formats();
505 if(formats
.contains("application/x-qt-windows-mime;value=\"FileNameW\"", Qt::CaseInsensitive
) && formats
.contains("text/uri-list", Qt::CaseInsensitive
))
507 event
->acceptProposedAction();
512 * File dropped onto window
514 void MainWindow::dropEvent(QDropEvent
*event
)
518 QStringList droppedFiles
;
519 const QList
<QUrl
> urls
= event
->mimeData()->urls();
521 for(int i
= 0; i
< urls
.count(); i
++)
523 QFileInfo
file(urls
.at(i
).toLocalFile());
530 droppedFiles
<< file
.canonicalFilePath();
535 QList
<QFileInfo
> list
= QDir(file
.canonicalFilePath()).entryInfoList(QDir::Files
);
536 for(int j
= 0; j
< list
.count(); j
++)
538 droppedFiles
<< list
.at(j
).canonicalFilePath();
543 addFiles(droppedFiles
);
547 * Window tries to close
549 void MainWindow::closeEvent(QCloseEvent
*event
)
551 if(m_banner
->isVisible() || m_delayedFileTimer
->isActive())
553 MessageBeep(MB_ICONEXCLAMATION
);
566 void MainWindow::resizeEvent(QResizeEvent
*event
)
568 QMainWindow::resizeEvent(event
);
569 m_dropNoteLabel
->setGeometry(0, 0, sourceFileView
->width(), sourceFileView
->height());
575 bool MainWindow::eventFilter(QObject
*obj
, QEvent
*event
)
577 if(obj
== m_fileSystemModel
&& QApplication::overrideCursor() == NULL
)
579 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor
));
580 QTimer::singleShot(250, this, SLOT(restoreCursor()));
582 else if(obj
== outputFolderLabel
)
584 switch(event
->type())
586 case QEvent::MouseButtonPress
:
587 if(dynamic_cast<QMouseEvent
*>(event
)->button() == Qt::LeftButton
)
589 QDesktopServices::openUrl(QString("file:///%1").arg(outputFolderLabel
->text()));
593 outputFolderLabel
->setForegroundRole(QPalette::Link
);
596 outputFolderLabel
->setForegroundRole(QPalette::WindowText
);
603 ////////////////////////////////////////////////////////////
605 ////////////////////////////////////////////////////////////
610 void MainWindow::windowShown(void)
612 QStringList arguments
= QApplication::arguments();
615 if(m_settings
->licenseAccepted() <= 0)
619 if(m_settings
->licenseAccepted() == 0)
621 AboutDialog
*about
= new AboutDialog(m_settings
, this, true);
622 iAccepted
= about
->exec();
623 LAMEXP_DELETE(about
);
628 m_settings
->licenseAccepted(-1);
629 QApplication::processEvents();
630 PlaySound(MAKEINTRESOURCE(IDR_WAVE_WHAMMY
), GetModuleHandle(NULL
), SND_RESOURCE
| SND_SYNC
);
631 QMessageBox::critical(this, tr("License Declined"), tr("You have declined the license. Consequently the application will exit now!"), tr("Goodbye!"));
632 QProcess::startDetached(QString("%1/Uninstall.exe").arg(QApplication::applicationDirPath()), QStringList());
633 QApplication::quit();
637 PlaySound(MAKEINTRESOURCE(IDR_WAVE_WOOHOO
), GetModuleHandle(NULL
), SND_RESOURCE
| SND_SYNC
);
638 m_settings
->licenseAccepted(1);
641 //Check for expiration
642 if(lamexp_version_demo())
644 if(QDate::currentDate() >= lamexp_version_expires())
646 qWarning("Binary has expired !!!");
647 PlaySound(MAKEINTRESOURCE(IDR_WAVE_WHAMMY
), GetModuleHandle(NULL
), SND_RESOURCE
| SND_SYNC
);
648 if(QMessageBox::warning(this, tr("LameXP - Expired"), QString("<nobr>%1<br>%2</nobr>").arg(tr("This demo (pre-release) version of LameXP has expired at %1.").arg(lamexp_version_expires().toString(Qt::ISODate
)), tr("LameXP is free software and release versions won't expire.")), tr("Check for Updates"), tr("Exit Program")) == 0)
650 checkUpdatesActionActivated();
652 QApplication::quit();
658 if(QDate::currentDate() >= lamexp_version_date().addYears(1))
660 qWarning("Binary is more than a year old, time to update!");
661 if(QMessageBox::warning(this, tr("Urgent Update"), QString("<nobr>%1</nobr>").arg(tr("Your version of LameXP is more than a year old. Time for an update!")), tr("Check for Updates"), tr("Exit Program")) == 0)
663 checkUpdatesActionActivated();
667 QApplication::quit();
671 else if(m_settings
->autoUpdateEnabled())
673 QDate lastUpdateCheck
= QDate::fromString(m_settings
->autoUpdateLastCheck(), Qt::ISODate
);
674 if(!lastUpdateCheck
.isValid() || QDate::currentDate() >= lastUpdateCheck
.addDays(14))
676 if(QMessageBox::information(this, tr("Update Reminder"), QString("<nobr>%1</nobr>").arg(lastUpdateCheck
.isValid() ? tr("Your last update check was more than 14 days ago. Check for updates now?") : tr("Your did not check for LameXP updates yet. Check for updates now?")), tr("Check for Updates"), tr("Postpone")) == 0)
678 checkUpdatesActionActivated();
683 //Check for AAC support
684 if(m_settings
->neroAacNotificationsEnabled())
686 if(lamexp_check_tool("neroAacEnc.exe") && lamexp_check_tool("neroAacDec.exe") && lamexp_check_tool("neroAacTag.exe"))
688 if(lamexp_tool_version("neroAacEnc.exe") < lamexp_toolver_neroaac())
691 messageText
+= QString("<nobr>%1<br>").arg(tr("LameXP detected that your version of the Nero AAC encoder is outdated!"));
692 messageText
+= QString("%1<br><br>").arg(tr("The current version available is %1 (or later), but you still have version %2 installed.").arg(lamexp_version2string("?.?.?.?", lamexp_toolver_neroaac(), tr("n/a")), lamexp_version2string("?.?.?.?", lamexp_tool_version("neroAacEnc.exe"), tr("n/a"))));
693 messageText
+= QString("%1<br>").arg(tr("You can download the latest version of the Nero AAC encoder from the Nero website at:"));
694 messageText
+= "<b>" + LINK(AboutDialog::neroAacUrl
) + "</b><br></nobr>";
695 QMessageBox::information(this, tr("AAC Encoder Outdated"), messageText
);
700 radioButtonEncoderAAC
->setEnabled(false);
701 QString appPath
= QDir(QCoreApplication::applicationDirPath()).canonicalPath();
702 if(appPath
.isEmpty()) appPath
= QCoreApplication::applicationDirPath();
704 messageText
+= QString("<nobr>%1<br>").arg(tr("The Nero AAC encoder could not be found. AAC encoding support will be disabled."));
705 messageText
+= QString("%1<br><br>").arg(tr("Please put 'neroAacEnc.exe', 'neroAacDec.exe' and 'neroAacTag.exe' into the LameXP directory!"));
706 messageText
+= QString("%1<br>").arg(tr("Your LameXP directory is located here:"));
707 messageText
+= QString("<i><nobr><a href=\"file:///%1\">%1</a></nobr></i><br><br>").arg(QDir::toNativeSeparators(appPath
));
708 messageText
+= QString("%1<br>").arg(tr("You can download the Nero AAC encoder for free from the official Nero website at:"));
709 messageText
+= "<b>" + LINK(AboutDialog::neroAacUrl
) + "</b><br></nobr>";
710 QMessageBox::information(this, tr("AAC Support Disabled"), messageText
);
714 //Check for WMA support
715 if(m_settings
->wmaDecoderNotificationsEnabled())
717 if(!lamexp_check_tool("wmawav.exe"))
720 messageText
+= QString("<nobr>%1<br>").arg(tr("LameXP has detected that the WMA File Decoder component is not currently installed on your system."));
721 messageText
+= QString("%1</nobr>").arg(tr("You won't be able to process WMA files as input unless the WMA File Decoder component is installed!"));
722 QMessageBox::information(this, tr("WMA Decoder Missing"), messageText
);
723 installWMADecoderActionTriggered(rand() % 2);
727 //Add files from the command-line
728 for(int i
= 0; i
< arguments
.count() - 1; i
++)
730 if(!arguments
[i
].compare("--add", Qt::CaseInsensitive
))
732 QFileInfo
currentFile(arguments
[++i
].trimmed());
733 qDebug("Adding file from CLI: %s", currentFile
.canonicalFilePath().toUtf8().constData());
734 m_delayedFileList
->append(currentFile
.canonicalFilePath());
738 //Start delayed files timer
739 if(!m_delayedFileList
->isEmpty() && !m_delayedFileTimer
->isActive())
741 m_delayedFileTimer
->start(5000);
744 //Make DropBox visible
745 if(m_settings
->dropBoxWidgetEnabled())
747 m_dropBox
->setVisible(true);
754 void MainWindow::aboutButtonClicked(void)
760 AboutDialog
*aboutBox
= new AboutDialog(m_settings
, this);
762 LAMEXP_DELETE(aboutBox
);
769 void MainWindow::encodeButtonClicked(void)
771 static const __int64 oneGigabyte
= 1073741824;
772 static const __int64 minimumFreeDiskspaceMultiplier
= 2;
776 if(m_fileListModel
->rowCount() < 1)
778 QMessageBox::warning(this, tr("LameXP"), QString("<nobr>%1</nobr>").arg(tr("You must add at least one file to the list before proceeding!")));
779 tabWidget
->setCurrentIndex(0);
783 __int64 currentFreeDiskspace
= lamexp_free_diskspace(lamexp_temp_folder());
785 if(currentFreeDiskspace
< (oneGigabyte
* minimumFreeDiskspaceMultiplier
))
787 QStringList tempFolderParts
= lamexp_temp_folder().split("/", QString::SkipEmptyParts
, Qt::CaseInsensitive
);
788 tempFolderParts
.takeLast();
789 if(m_settings
->soundsEnabled()) PlaySound(MAKEINTRESOURCE(IDR_WAVE_WHAMMY
), GetModuleHandle(NULL
), SND_RESOURCE
| SND_SYNC
);
790 switch(QMessageBox::warning(this, tr("Low Diskspace Warning"), QString("<nobr>%1</nobr><br><nobr>%2</nobr><br><br>%3").arg(tr("There are less than %1 GB of free diskspace available on your system's TEMP folder.").arg(QString::number(minimumFreeDiskspaceMultiplier
)), tr("It is highly recommend to free up more diskspace before proceeding with the encode!"), tr("Your TEMP folder is located at:")).append("<br><nobr><i><a href=\"file:///%3\">%3</a></i></nobr><br>").arg(tempFolderParts
.join("\\")), tr("Abort Encoding Process"), tr("Clean Disk Now"), tr("Ignore")))
793 QProcess::startDetached(QString("%1/cleanmgr.exe").arg(lamexp_known_folder(lamexp_folder_systemfolder
)), QStringList() << "/D" << tempFolderParts
.first());
798 QMessageBox::warning(this, tr("Low Diskspace"), tr("You are proceeding with low diskspace. Problems might occur!"));
803 switch(m_settings
->compressionEncoder())
805 case SettingsModel::MP3Encoder
:
806 case SettingsModel::VorbisEncoder
:
807 case SettingsModel::AACEncoder
:
808 case SettingsModel::FLACEncoder
:
809 case SettingsModel::PCMEncoder
:
812 QMessageBox::warning(this, tr("LameXP"), tr("Sorry, an unsupported encoder has been chosen!"));
813 tabWidget
->setCurrentIndex(3);
817 if(!m_settings
->outputToSourceDir())
819 QFile
writeTest(QString("%1/~%2.txt").arg(m_settings
->outputDir(), QUuid::createUuid().toString()));
820 if(!writeTest
.open(QIODevice::ReadWrite
))
822 QMessageBox::warning(this, tr("LameXP"), QString("%1<br><nobr>%2</nobr><br><br>%3").arg(tr("Cannot write to the selected output directory."), m_settings
->outputDir(), tr("Please choose a different directory!")));
823 tabWidget
->setCurrentIndex(1);
840 void MainWindow::closeButtonClicked(void)
849 void MainWindow::addFilesButtonClicked(void)
855 if(lamexp_themes_enabled())
857 QStringList fileTypeFilters
= DecoderRegistry::getSupportedTypes();
858 QStringList selectedFiles
= QFileDialog::getOpenFileNames(this, tr("Add file(s)"), QString(), fileTypeFilters
.join(";;"));
859 if(!selectedFiles
.isEmpty())
861 addFiles(selectedFiles
);
866 QFileDialog
dialog(this, tr("Add file(s)"));
867 QStringList fileTypeFilters
= DecoderRegistry::getSupportedTypes();
868 dialog
.setFileMode(QFileDialog::ExistingFiles
);
869 dialog
.setNameFilter(fileTypeFilters
.join(";;"));
872 QStringList selectedFiles
= dialog
.selectedFiles();
873 addFiles(selectedFiles
);
882 void MainWindow::openFolderActionActivated(void)
885 QString selectedFolder
;
889 if(lamexp_themes_enabled())
891 selectedFolder
= QFileDialog::getExistingDirectory(this, tr("Add folder"), QDesktopServices::storageLocation(QDesktopServices::MusicLocation
));
895 QFileDialog
dialog(this, tr("Add folder"));
896 dialog
.setFileMode(QFileDialog::DirectoryOnly
);
897 dialog
.setDirectory(QDesktopServices::storageLocation(QDesktopServices::MusicLocation
));
900 selectedFolder
= dialog
.selectedFiles().first();
904 if(!selectedFolder
.isEmpty())
906 QDir
sourceDir(selectedFolder
);
907 QFileInfoList fileInfoList
= sourceDir
.entryInfoList(QDir::Files
);
908 QStringList fileList
;
910 while(!fileInfoList
.isEmpty())
912 fileList
<< fileInfoList
.takeFirst().canonicalFilePath();
923 void MainWindow::removeFileButtonClicked(void)
925 if(sourceFileView
->currentIndex().isValid())
927 int iRow
= sourceFileView
->currentIndex().row();
928 m_fileListModel
->removeFile(sourceFileView
->currentIndex());
929 sourceFileView
->selectRow(iRow
< m_fileListModel
->rowCount() ? iRow
: m_fileListModel
->rowCount()-1);
936 void MainWindow::clearFilesButtonClicked(void)
938 m_fileListModel
->clearFiles();
942 * Move file up button
944 void MainWindow::fileUpButtonClicked(void)
946 if(sourceFileView
->currentIndex().isValid())
948 int iRow
= sourceFileView
->currentIndex().row() - 1;
949 m_fileListModel
->moveFile(sourceFileView
->currentIndex(), -1);
950 sourceFileView
->selectRow(iRow
>= 0 ? iRow
: 0);
955 * Move file down button
957 void MainWindow::fileDownButtonClicked(void)
959 if(sourceFileView
->currentIndex().isValid())
961 int iRow
= sourceFileView
->currentIndex().row() + 1;
962 m_fileListModel
->moveFile(sourceFileView
->currentIndex(), 1);
963 sourceFileView
->selectRow(iRow
< m_fileListModel
->rowCount() ? iRow
: m_fileListModel
->rowCount()-1);
968 * Show details button
970 void MainWindow::showDetailsButtonClicked(void)
975 MetaInfoDialog
*metaInfoDialog
= new MetaInfoDialog(this);
976 QModelIndex index
= sourceFileView
->currentIndex();
978 while(index
.isValid())
982 index
= m_fileListModel
->index(index
.row() + 1, index
.column());
983 sourceFileView
->selectRow(index
.row());
987 index
= m_fileListModel
->index(index
.row() - 1, index
.column());
988 sourceFileView
->selectRow(index
.row());
991 AudioFileModel
&file
= (*m_fileListModel
)[index
];
992 iResult
= metaInfoDialog
->exec(file
, index
.row() > 0, index
.row() < m_fileListModel
->rowCount() - 1);
997 LAMEXP_DELETE(metaInfoDialog
);
1003 void MainWindow::tabPageChanged(int idx
)
1005 QList
<QAction
*> actions
= m_tabActionGroup
->actions();
1006 for(int i
= 0; i
< actions
.count(); i
++)
1009 int actionIndex
= actions
.at(i
)->data().toInt(&ok
);
1010 if(ok
&& actionIndex
== idx
)
1012 actions
.at(i
)->setChecked(true);
1018 * Tab action triggered
1020 void MainWindow::tabActionActivated(QAction
*action
)
1022 if(action
&& action
->data().isValid())
1025 int index
= action
->data().toInt(&ok
);
1028 tabWidget
->setCurrentIndex(index
);
1034 * Style action triggered
1036 void MainWindow::styleActionActivated(QAction
*action
)
1038 if(action
&& action
->data().isValid())
1041 int actionIndex
= action
->data().toInt(&ok
);
1042 m_settings
->interfaceStyle(actionIndex
);
1045 switch(m_settings
->interfaceStyle())
1048 if(actionStyleCleanlooks
->isEnabled())
1050 actionStyleCleanlooks
->setChecked(true);
1051 QApplication::setStyle(new QCleanlooksStyle());
1055 if(actionStyleWindowsVista
->isEnabled())
1057 actionStyleWindowsVista
->setChecked(true);
1058 QApplication::setStyle(new QWindowsVistaStyle());
1062 if(actionStyleWindowsXP
->isEnabled())
1064 actionStyleWindowsXP
->setChecked(true);
1065 QApplication::setStyle(new QWindowsXPStyle());
1069 if(actionStyleWindowsClassic
->isEnabled())
1071 actionStyleWindowsClassic
->setChecked(true);
1072 QApplication::setStyle(new QWindowsStyle());
1076 actionStylePlastique
->setChecked(true);
1077 QApplication::setStyle(new QPlastiqueStyle());
1083 * Language action triggered
1085 void MainWindow::languageActionActivated(QAction
*action
)
1087 if(action
->data().type() == QVariant::String
)
1089 QString langId
= action
->data().toString();
1091 if(lamexp_install_translator(langId
))
1093 action
->setChecked(true);
1094 m_settings
->currentLanguage(langId
);
1100 * Load language from file action triggered
1102 void MainWindow::languageFromFileActionActivated(bool checked
)
1104 QFileDialog
dialog(this, tr("Load Translation"));
1105 dialog
.setFileMode(QFileDialog::ExistingFile
);
1106 dialog
.setNameFilter(QString("%1 (*.qm)").arg(tr("Translation Files")));
1110 QStringList selectedFiles
= dialog
.selectedFiles();
1111 if(lamexp_install_translator_from_file(selectedFiles
.first()))
1113 QList
<QAction
*> actions
= m_languageActionGroup
->actions();
1114 while(!actions
.isEmpty())
1116 actions
.takeFirst()->setChecked(false);
1121 languageActionActivated(m_languageActionGroup
->actions().first());
1127 * Output folder changed (mouse clicked)
1129 void MainWindow::outputFolderViewClicked(const QModelIndex
&index
)
1131 if(outputFolderView
->currentIndex() != index
)
1133 outputFolderView
->setCurrentIndex(index
);
1135 QString selectedDir
= m_fileSystemModel
->filePath(index
);
1136 if(selectedDir
.length() < 3) selectedDir
.append(QDir::separator());
1137 outputFolderLabel
->setText(QDir::toNativeSeparators(selectedDir
));
1138 m_settings
->outputDir(selectedDir
);
1142 * Output folder changed (mouse moved)
1144 void MainWindow::outputFolderViewMoved(const QModelIndex
&index
)
1146 if(QApplication::mouseButtons() & Qt::LeftButton
)
1148 outputFolderViewClicked(index
);
1153 * Goto desktop button
1155 void MainWindow::gotoDesktopButtonClicked(void)
1157 QString desktopPath
= QDesktopServices::storageLocation(QDesktopServices::DesktopLocation
);
1159 if(!desktopPath
.isEmpty() && QDir(desktopPath
).exists())
1161 outputFolderView
->setCurrentIndex(m_fileSystemModel
->index(desktopPath
));
1162 outputFolderViewClicked(outputFolderView
->currentIndex());
1163 outputFolderView
->setFocus();
1167 buttonGotoDesktop
->setEnabled(false);
1172 * Goto home folder button
1174 void MainWindow::gotoHomeFolderButtonClicked(void)
1176 QString homePath
= QDesktopServices::storageLocation(QDesktopServices::HomeLocation
);
1178 if(!homePath
.isEmpty() && QDir(homePath
).exists())
1180 outputFolderView
->setCurrentIndex(m_fileSystemModel
->index(homePath
));
1181 outputFolderViewClicked(outputFolderView
->currentIndex());
1182 outputFolderView
->setFocus();
1186 buttonGotoHome
->setEnabled(false);
1191 * Goto music folder button
1193 void MainWindow::gotoMusicFolderButtonClicked(void)
1195 QString musicPath
= QDesktopServices::storageLocation(QDesktopServices::MusicLocation
);
1197 if(!musicPath
.isEmpty() && QDir(musicPath
).exists())
1199 outputFolderView
->setCurrentIndex(m_fileSystemModel
->index(musicPath
));
1200 outputFolderViewClicked(outputFolderView
->currentIndex());
1201 outputFolderView
->setFocus();
1205 buttonGotoMusic
->setEnabled(false);
1210 * Make folder button
1212 void MainWindow::makeFolderButtonClicked(void)
1216 QDir
basePath(m_fileSystemModel
->fileInfo(outputFolderView
->currentIndex()).absoluteFilePath());
1217 QString suggestedName
= tr("New Folder");
1219 if(!m_metaData
->fileArtist().isEmpty() && !m_metaData
->fileAlbum().isEmpty())
1221 suggestedName
= QString("%1 - %2").arg(m_metaData
->fileArtist(), m_metaData
->fileAlbum());
1223 else if(!m_metaData
->fileArtist().isEmpty())
1225 suggestedName
= m_metaData
->fileArtist();
1227 else if(!m_metaData
->fileAlbum().isEmpty())
1229 suggestedName
= m_metaData
->fileAlbum();
1233 for(int i
= 0; i
< m_fileListModel
->rowCount(); i
++)
1235 AudioFileModel audioFile
= m_fileListModel
->getFile(m_fileListModel
->index(i
, 0));
1236 if(!audioFile
.fileAlbum().isEmpty() || !audioFile
.fileArtist().isEmpty())
1238 if(!audioFile
.fileArtist().isEmpty() && !audioFile
.fileAlbum().isEmpty())
1240 suggestedName
= QString("%1 - %2").arg(audioFile
.fileArtist(), audioFile
.fileAlbum());
1242 else if(!audioFile
.fileArtist().isEmpty())
1244 suggestedName
= audioFile
.fileArtist();
1246 else if(!audioFile
.fileAlbum().isEmpty())
1248 suggestedName
= audioFile
.fileAlbum();
1257 bool bApplied
= false;
1258 QString folderName
= QInputDialog::getText(this, tr("New Folder"), tr("Enter the name of the new folder:").leftJustified(96, ' '), QLineEdit::Normal
, suggestedName
, &bApplied
, Qt::WindowStaysOnTopHint
).simplified();
1262 folderName
.remove(":", Qt::CaseInsensitive
);
1263 folderName
.remove("/", Qt::CaseInsensitive
);
1264 folderName
.remove("\\", Qt::CaseInsensitive
);
1265 folderName
.remove("?", Qt::CaseInsensitive
);
1266 folderName
.remove("*", Qt::CaseInsensitive
);
1267 folderName
.remove("<", Qt::CaseInsensitive
);
1268 folderName
.remove(">", Qt::CaseInsensitive
);
1270 folderName
= folderName
.simplified();
1272 if(folderName
.isEmpty())
1274 MessageBeep(MB_ICONERROR
);
1279 QString newFolder
= folderName
;
1281 while(basePath
.exists(newFolder
))
1283 newFolder
= QString(folderName
).append(QString().sprintf(" (%d)", ++i
));
1286 if(basePath
.mkdir(newFolder
))
1288 QDir createdDir
= basePath
;
1289 if(createdDir
.cd(newFolder
))
1291 outputFolderView
->setCurrentIndex(m_fileSystemModel
->index(createdDir
.canonicalPath()));
1292 outputFolderViewClicked(outputFolderView
->currentIndex());
1293 outputFolderView
->setFocus();
1298 QMessageBox::warning(this, tr("Failed to create folder"), QString("%1<br><nobr>%2</nobr><br><br>%3").arg(tr("The new folder could not be created:"), basePath
.absoluteFilePath(newFolder
), tr("Drive is read-only or insufficient access rights!")));
1306 * Edit meta button clicked
1308 void MainWindow::editMetaButtonClicked(void)
1311 m_metaInfoModel
->editItem(metaDataView
->currentIndex(), this);
1315 * Reset meta button clicked
1317 void MainWindow::clearMetaButtonClicked(void)
1320 m_metaInfoModel
->clearData();
1324 * Visit homepage action
1326 void MainWindow::visitHomepageActionActivated(void)
1328 QDesktopServices::openUrl(QUrl("http://mulder.dummwiedeutsch.de/"));
1332 * Check for updates action
1334 void MainWindow::checkUpdatesActionActivated(void)
1340 UpdateDialog
*updateDialog
= new UpdateDialog(m_settings
, this);
1341 updateDialog
->exec();
1342 if(updateDialog
->getSuccess())
1344 m_settings
->autoUpdateLastCheck(QDate::currentDate().toString(Qt::ISODate
));
1346 LAMEXP_DELETE(updateDialog
);
1351 * Other instance detected
1353 void MainWindow::notifyOtherInstance(void)
1355 if(!m_banner
->isVisible())
1357 QMessageBox
msgBox(QMessageBox::Warning
, tr("Already Running"), tr("LameXP is already running, please use the running instance!"), QMessageBox::NoButton
, this, Qt::Dialog
| Qt::MSWindowsFixedSizeDialogHint
| Qt::WindowStaysOnTopHint
);
1363 * Add file from another instance
1365 void MainWindow::addFileDelayed(const QString
&filePath
)
1367 m_delayedFileTimer
->stop();
1368 qDebug("Received file: %s", filePath
.toUtf8().constData());
1369 m_delayedFileList
->append(filePath
);
1370 m_delayedFileTimer
->start(5000);
1374 * Add all pending files
1376 void MainWindow::handleDelayedFiles(void)
1378 if(m_banner
->isVisible())
1383 m_delayedFileTimer
->stop();
1384 if(m_delayedFileList
->isEmpty())
1389 QStringList selectedFiles
;
1390 tabWidget
->setCurrentIndex(0);
1392 while(!m_delayedFileList
->isEmpty())
1394 QFileInfo currentFile
= QFileInfo(m_delayedFileList
->takeFirst());
1395 if(!currentFile
.exists())
1399 if(currentFile
.isFile())
1401 selectedFiles
<< currentFile
.canonicalFilePath();
1404 if(currentFile
.isDir())
1406 QList
<QFileInfo
> list
= QDir(currentFile
.canonicalFilePath()).entryInfoList(QDir::Files
);
1407 for(int j
= 0; j
< list
.count(); j
++)
1409 selectedFiles
<< list
.at(j
).canonicalFilePath();
1414 addFiles(selectedFiles
);
1420 void MainWindow::updateEncoder(int id
)
1422 m_settings
->compressionEncoder(id
);
1424 switch(m_settings
->compressionEncoder())
1426 case SettingsModel::VorbisEncoder
:
1427 radioButtonModeQuality
->setEnabled(true);
1428 radioButtonModeAverageBitrate
->setEnabled(true);
1429 radioButtonConstBitrate
->setEnabled(false);
1430 if(radioButtonConstBitrate
->isChecked()) radioButtonModeQuality
->setChecked(true);
1431 sliderBitrate
->setEnabled(true);
1433 case SettingsModel::FLACEncoder
:
1434 radioButtonModeQuality
->setEnabled(false);
1435 radioButtonModeQuality
->setChecked(true);
1436 radioButtonModeAverageBitrate
->setEnabled(false);
1437 radioButtonConstBitrate
->setEnabled(false);
1438 sliderBitrate
->setEnabled(true);
1440 case SettingsModel::PCMEncoder
:
1441 radioButtonModeQuality
->setEnabled(false);
1442 radioButtonModeQuality
->setChecked(true);
1443 radioButtonModeAverageBitrate
->setEnabled(false);
1444 radioButtonConstBitrate
->setEnabled(false);
1445 sliderBitrate
->setEnabled(false);
1448 radioButtonModeQuality
->setEnabled(true);
1449 radioButtonModeAverageBitrate
->setEnabled(true);
1450 radioButtonConstBitrate
->setEnabled(true);
1451 sliderBitrate
->setEnabled(true);
1455 updateRCMode(m_modeButtonGroup
->checkedId());
1459 * Update rate-control mode
1461 void MainWindow::updateRCMode(int id
)
1463 m_settings
->compressionRCMode(id
);
1465 switch(m_settings
->compressionEncoder())
1467 case SettingsModel::MP3Encoder
:
1468 switch(m_settings
->compressionRCMode())
1470 case SettingsModel::VBRMode
:
1471 sliderBitrate
->setMinimum(0);
1472 sliderBitrate
->setMaximum(9);
1475 sliderBitrate
->setMinimum(0);
1476 sliderBitrate
->setMaximum(13);
1480 case SettingsModel::VorbisEncoder
:
1481 switch(m_settings
->compressionRCMode())
1483 case SettingsModel::VBRMode
:
1484 sliderBitrate
->setMinimum(-2);
1485 sliderBitrate
->setMaximum(10);
1488 sliderBitrate
->setMinimum(4);
1489 sliderBitrate
->setMaximum(63);
1493 case SettingsModel::AACEncoder
:
1494 switch(m_settings
->compressionRCMode())
1496 case SettingsModel::VBRMode
:
1497 sliderBitrate
->setMinimum(0);
1498 sliderBitrate
->setMaximum(20);
1501 sliderBitrate
->setMinimum(4);
1502 sliderBitrate
->setMaximum(63);
1506 case SettingsModel::FLACEncoder
:
1507 sliderBitrate
->setMinimum(0);
1508 sliderBitrate
->setMaximum(8);
1510 case SettingsModel::PCMEncoder
:
1511 sliderBitrate
->setMinimum(0);
1512 sliderBitrate
->setMaximum(2);
1513 sliderBitrate
->setValue(1);
1516 sliderBitrate
->setMinimum(0);
1517 sliderBitrate
->setMaximum(0);
1521 updateBitrate(sliderBitrate
->value());
1527 void MainWindow::updateBitrate(int value
)
1529 m_settings
->compressionBitrate(value
);
1531 switch(m_settings
->compressionRCMode())
1533 case SettingsModel::VBRMode
:
1534 switch(m_settings
->compressionEncoder())
1536 case SettingsModel::MP3Encoder
:
1537 labelBitrate
->setText(tr("Quality Level %1").arg(9 - value
));
1539 case SettingsModel::VorbisEncoder
:
1540 labelBitrate
->setText(tr("Quality Level %1").arg(value
));
1542 case SettingsModel::AACEncoder
:
1543 labelBitrate
->setText(tr("Quality Level %1").arg(QString().sprintf("%.2f", static_cast<double>(value
* 5) / 100.0)));
1545 case SettingsModel::FLACEncoder
:
1546 labelBitrate
->setText(tr("Compression %1").arg(value
));
1548 case SettingsModel::PCMEncoder
:
1549 labelBitrate
->setText(tr("Uncompressed"));
1552 labelBitrate
->setText(QString::number(value
));
1556 case SettingsModel::ABRMode
:
1557 switch(m_settings
->compressionEncoder())
1559 case SettingsModel::MP3Encoder
:
1560 labelBitrate
->setText(QString("≈ %1 kbps").arg(SettingsModel::mp3Bitrates
[value
]));
1562 case SettingsModel::FLACEncoder
:
1563 labelBitrate
->setText(tr("Compression %1").arg(value
));
1565 case SettingsModel::PCMEncoder
:
1566 labelBitrate
->setText(tr("Uncompressed"));
1569 labelBitrate
->setText(QString("≈ %1 kbps").arg(min(500, value
* 8)));
1574 switch(m_settings
->compressionEncoder())
1576 case SettingsModel::MP3Encoder
:
1577 labelBitrate
->setText(QString("%1 kbps").arg(SettingsModel::mp3Bitrates
[value
]));
1579 case SettingsModel::FLACEncoder
:
1580 labelBitrate
->setText(tr("Compression %1").arg(value
));
1582 case SettingsModel::PCMEncoder
:
1583 labelBitrate
->setText(tr("Uncompressed"));
1586 labelBitrate
->setText(QString("%1 kbps").arg(min(500, value
* 8)));
1595 * Lame algorithm quality changed
1597 void MainWindow::updateLameAlgoQuality(int value
)
1604 text
= tr("Best Quality (Very Slow)");
1607 text
= tr("High Quality (Recommended)");
1610 text
= tr("Average Quality (Default)");
1613 text
= tr("Low Quality (Fast)");
1616 text
= tr("Poor Quality (Very Fast)");
1622 m_settings
->lameAlgoQuality(value
);
1623 labelLameAlgoQuality
->setText(text
);
1628 * Bitrate management endabled/disabled
1630 void MainWindow::bitrateManagementEnabledChanged(bool checked
)
1632 m_settings
->bitrateManagementEnabled(checked
);
1636 * Minimum bitrate has changed
1638 void MainWindow::bitrateManagementMinChanged(int value
)
1640 if(value
> spinBoxBitrateManagementMax
->value())
1642 spinBoxBitrateManagementMin
->setValue(spinBoxBitrateManagementMax
->value());
1643 m_settings
->bitrateManagementMinRate(spinBoxBitrateManagementMax
->value());
1647 m_settings
->bitrateManagementMinRate(value
);
1652 * Maximum bitrate has changed
1654 void MainWindow::bitrateManagementMaxChanged(int value
)
1656 if(value
< spinBoxBitrateManagementMin
->value())
1658 spinBoxBitrateManagementMax
->setValue(spinBoxBitrateManagementMin
->value());
1659 m_settings
->bitrateManagementMaxRate(spinBoxBitrateManagementMin
->value());
1663 m_settings
->bitrateManagementMaxRate(value
);
1668 * Channel mode has changed
1670 void MainWindow::channelModeChanged(int value
)
1672 if(value
>= 0) m_settings
->lameChannelMode(value
);
1676 * Sampling rate has changed
1678 void MainWindow::samplingRateChanged(int value
)
1680 if(value
>= 0) m_settings
->samplingRate(value
);
1684 * Nero AAC 2-Pass mode changed
1686 void MainWindow::neroAAC2PassChanged(bool checked
)
1688 m_settings
->neroAACEnable2Pass(checked
);
1692 * Nero AAC profile mode changed
1694 void MainWindow::neroAACProfileChanged(int value
)
1696 if(value
>= 0) m_settings
->neroAACProfile(value
);
1700 * Normalization filter enabled changed
1702 void MainWindow::normalizationEnabledChanged(bool checked
)
1704 m_settings
->normalizationFilterEnabled(checked
);
1708 * Normalization max. volume changed
1710 void MainWindow::normalizationMaxVolumeChanged(double value
)
1712 m_settings
->normalizationFilterMaxVolume(static_cast<int>(value
* 100.0));
1716 * Reset all advanced options to their defaults
1718 void MainWindow::resetAdvancedOptionsButtonClicked()
1720 sliderLameAlgoQuality
->setValue(m_settings
->lameAlgoQualityDefault());
1721 spinBoxBitrateManagementMin
->setValue(m_settings
->bitrateManagementMinRateDefault());
1722 spinBoxBitrateManagementMax
->setValue(m_settings
->bitrateManagementMaxRateDefault());
1723 spinBoxNormalizationFilter
->setValue(static_cast<double>(m_settings
->normalizationFilterMaxVolumeDefault()) / 100.0);
1724 comboBoxMP3ChannelMode
->setCurrentIndex(m_settings
->lameChannelModeDefault());
1725 comboBoxSamplingRate
->setCurrentIndex(m_settings
->samplingRateDefault());
1726 comboBoxNeroAACProfile
->setCurrentIndex(m_settings
->neroAACProfileDefault());
1727 while(checkBoxBitrateManagement
->isChecked() != m_settings
->bitrateManagementEnabledDefault()) checkBoxBitrateManagement
->click();
1728 while(checkBoxNeroAAC2PassMode
->isChecked() != m_settings
->neroAACEnable2PassDefault()) checkBoxNeroAAC2PassMode
->click();
1729 while(checkBoxNormalizationFilter
->isChecked() != m_settings
->normalizationFilterEnabledDefault()) checkBoxNormalizationFilter
->click();
1730 scrollArea
->verticalScrollBar()->setValue(0);
1736 void MainWindow::sourceModelChanged(void)
1738 m_dropNoteLabel
->setVisible(m_fileListModel
->rowCount() <= 0);
1742 * Meta tags enabled changed
1744 void MainWindow::metaTagsEnabledChanged(void)
1746 m_settings
->writeMetaTags(writeMetaDataCheckBox
->isChecked());
1750 * Playlist enabled changed
1752 void MainWindow::playlistEnabledChanged(void)
1754 m_settings
->createPlaylist(generatePlaylistCheckBox
->isChecked());
1758 * Output to source dir changed
1760 void MainWindow::saveToSourceFolderChanged(void)
1762 m_settings
->outputToSourceDir(saveToSourceFolderCheckBox
->isChecked());
1766 * Prepend relative source file path to output file name changed
1768 void MainWindow::prependRelativePathChanged(void)
1770 m_settings
->prependRelativeSourcePath(prependRelativePathCheckBox
->isChecked());
1775 * Restore the override cursor
1777 void MainWindow::restoreCursor(void)
1779 QApplication::restoreOverrideCursor();
1783 * Show context menu for source files
1785 void MainWindow::sourceFilesContextMenu(const QPoint
&pos
)
1787 if(pos
.x() <= sourceFileView
->width() && pos
.y() <= sourceFileView
->height() && pos
.x() >= 0 && pos
.y() >= 0)
1789 m_sourceFilesContextMenu
->popup(sourceFileView
->mapToGlobal(pos
));
1794 * Open selected file in external player
1796 void MainWindow::previewContextActionTriggered(void)
1798 const static char *appNames
[3] = {"smplayer_portable.exe", "smplayer.exe", "mplayer.exe"};
1799 const static wchar_t *registryKey
= L
"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{DB9E4EAB-2717-499F-8D56-4CC8A644AB60}";
1801 QModelIndex index
= sourceFileView
->currentIndex();
1802 if(!index
.isValid())
1807 QString mplayerPath
;
1808 HKEY registryKeyHandle
;
1810 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE
, registryKey
, 0, KEY_READ
, ®istryKeyHandle
) == ERROR_SUCCESS
)
1812 wchar_t Buffer
[4096];
1813 DWORD BuffSize
= sizeof(wchar_t*) * 4096;
1814 if(RegQueryValueExW(registryKeyHandle
, L
"InstallLocation", 0, 0, reinterpret_cast<BYTE
*>(Buffer
), &BuffSize
) == ERROR_SUCCESS
)
1816 mplayerPath
= QString::fromUtf16(reinterpret_cast<const unsigned short*>(Buffer
));
1820 if(!mplayerPath
.isEmpty())
1822 QDir
mplayerDir(mplayerPath
);
1823 if(mplayerDir
.exists())
1825 for(int i
= 0; i
< 3; i
++)
1827 if(mplayerDir
.exists(appNames
[i
]))
1829 QProcess::startDetached(mplayerDir
.absoluteFilePath(appNames
[i
]), QStringList() << QDir::toNativeSeparators(m_fileListModel
->getFile(index
).filePath()));
1836 QDesktopServices::openUrl(QString("file:///").append(m_fileListModel
->getFile(index
).filePath()));
1840 * Find selected file in explorer
1842 void MainWindow::findFileContextActionTriggered(void)
1844 QModelIndex index
= sourceFileView
->currentIndex();
1847 QString systemRootPath
;
1849 QDir
systemRoot(lamexp_known_folder(lamexp_folder_systemfolder
));
1850 if(systemRoot
.exists() && systemRoot
.cdUp())
1852 systemRootPath
= systemRoot
.canonicalPath();
1855 if(!systemRootPath
.isEmpty())
1857 QFileInfo
explorer(QString("%1/explorer.exe").arg(systemRootPath
));
1858 if(explorer
.exists() && explorer
.isFile())
1860 QProcess::execute(explorer
.canonicalFilePath(), QStringList() << "/select," << QDir::toNativeSeparators(m_fileListModel
->getFile(index
).filePath()));
1866 qWarning("SystemRoot directory could not be detected!");
1872 * Show context menu for output folder
1874 void MainWindow::outputFolderContextMenu(const QPoint
&pos
)
1877 if(pos
.x() <= outputFolderView
->width() && pos
.y() <= outputFolderView
->height() && pos
.x() >= 0 && pos
.y() >= 0)
1879 m_outputFolderContextMenu
->popup(outputFolderView
->mapToGlobal(pos
));
1884 * Show selected folder in explorer
1886 void MainWindow::showFolderContextActionTriggered(void)
1888 QDesktopServices::openUrl(QUrl::fromLocalFile(m_fileSystemModel
->filePath(outputFolderView
->currentIndex())));
1892 * Disable update reminder action
1894 void MainWindow::disableUpdateReminderActionTriggered(bool checked
)
1898 if(0 == QMessageBox::question(this, tr("Disable Update Reminder"), tr("Do you really want to disable the update reminder?"), tr("Yes"), tr("No"), QString(), 1))
1900 QMessageBox::information(this, tr("Update Reminder"), QString("%1<br>%2").arg(tr("The update reminder has been disabled."), tr("Please remember to check for updates at regular intervals!")));
1901 m_settings
->autoUpdateEnabled(false);
1905 m_settings
->autoUpdateEnabled(true);
1910 QMessageBox::information(this, tr("Update Reminder"), tr("The update reminder has been re-enabled."));
1911 m_settings
->autoUpdateEnabled(true);
1914 actionDisableUpdateReminder
->setChecked(!m_settings
->autoUpdateEnabled());
1918 * Disable sound effects action
1920 void MainWindow::disableSoundsActionTriggered(bool checked
)
1924 if(0 == QMessageBox::question(this, tr("Disable Sound Effects"), tr("Do you really want to disable all sound effects?"), tr("Yes"), tr("No"), QString(), 1))
1926 QMessageBox::information(this, tr("Sound Effects"), tr("All sound effects have been disabled."));
1927 m_settings
->soundsEnabled(false);
1931 m_settings
->soundsEnabled(true);
1936 QMessageBox::information(this, tr("Sound Effects"), tr("The sound effects have been re-enabled."));
1937 m_settings
->soundsEnabled(true);
1940 actionDisableSounds
->setChecked(!m_settings
->soundsEnabled());
1944 * Disable Nero AAC encoder action
1946 void MainWindow::disableNeroAacNotificationsActionTriggered(bool checked
)
1950 if(0 == QMessageBox::question(this, tr("Nero AAC Notifications"), tr("Do you really want to disable all Nero AAC Encoder notifications?"), tr("Yes"), tr("No"), QString(), 1))
1952 QMessageBox::information(this, tr("Nero AAC Notifications"), tr("All Nero AAC Encoder notifications have been disabled."));
1953 m_settings
->neroAacNotificationsEnabled(false);
1957 m_settings
->neroAacNotificationsEnabled(true);
1962 QMessageBox::information(this, tr("Nero AAC Notifications"), tr("The Nero AAC Encoder notifications have been re-enabled."));
1963 m_settings
->neroAacNotificationsEnabled(true);
1966 actionDisableNeroAacNotifications
->setChecked(!m_settings
->neroAacNotificationsEnabled());
1970 * Disable WMA Decoder component action
1972 void MainWindow::disableWmaDecoderNotificationsActionTriggered(bool checked
)
1976 if(0 == QMessageBox::question(this, tr("WMA Decoder Notifications"), tr("Do you really want to disable all WMA Decoder notifications?"), tr("Yes"), tr("No"), QString(), 1))
1978 QMessageBox::information(this, tr("WMA Decoder Notifications"), tr("All WMA Decoder notifications have been disabled."));
1979 m_settings
->wmaDecoderNotificationsEnabled(false);
1983 m_settings
->wmaDecoderNotificationsEnabled(true);
1988 QMessageBox::information(this, tr("WMA Decoder Notifications"), tr("The WMA Decoder notifications have been re-enabled."));
1989 m_settings
->wmaDecoderNotificationsEnabled(true);
1992 actionDisableWmaDecoderNotifications
->setChecked(!m_settings
->wmaDecoderNotificationsEnabled());
1996 * Download and install WMA Decoder component
1998 void MainWindow::installWMADecoderActionTriggered(bool checked
)
2000 static const char *download_url
= "http://www.nch.com.au/components/wmawav.exe";
2001 static const char *download_hash
= "52a3b0e6690faf3f830c336d3c0eadfb7a4e9bc6";
2003 if(QMessageBox::question(this, tr("Install WMA Decoder"), tr("Do you want to download and install the WMA File Decoder component now?"), tr("Download && Install"), tr("Cancel")) != 0)
2008 QString binaryWGet
= lamexp_lookup_tool("wget.exe");
2009 QString binaryElevator
= lamexp_lookup_tool("elevator.exe");
2011 if(binaryWGet
.isEmpty() || binaryElevator
.isEmpty())
2013 throw "Required binary is not available!";
2018 QString setupFile
= QString("%1/%2.exe").arg(lamexp_temp_folder(), lamexp_rand_str());
2021 process
.setWorkingDirectory(QFileInfo(setupFile
).absolutePath());
2024 connect(&process
, SIGNAL(error(QProcess::ProcessError
)), &loop
, SLOT(quit()));
2025 connect(&process
, SIGNAL(finished(int, QProcess::ExitStatus
)), &loop
, SLOT(quit()));
2027 process
.start(binaryWGet
, QStringList() << "-O" << QFileInfo(setupFile
).fileName() << download_url
);
2028 m_banner
->show(tr("Downloading WMA Decoder Setup, please wait..."), &loop
);
2030 if(process
.exitCode() != 0 || QFileInfo(setupFile
).size() < 10240)
2032 QFile::remove(setupFile
);
2033 if(QMessageBox::critical(this, tr("Download Failed"), tr("Failed to download the WMA Decoder setup. Check your internet connection!"), tr("Try Again"), tr("Cancel")) == 0)
2040 QFile
setupFileContent(setupFile
);
2041 QCryptographicHash
setupFileHash(QCryptographicHash::Sha1
);
2043 setupFileContent
.open(QIODevice::ReadOnly
);
2044 if(setupFileContent
.isOpen() && setupFileContent
.isReadable())
2046 setupFileHash
.addData(setupFileContent
.readAll());
2047 setupFileContent
.close();
2050 if(_stricmp(setupFileHash
.result().toHex().constData(), download_hash
))
2052 qWarning("Hash miscompare:\n Expected %s\n Detected %s\n", download_hash
, setupFileHash
.result().toHex().constData());
2053 QFile::remove(setupFile
);
2054 if(QMessageBox::critical(this, tr("Download Failed"), tr("The download seems to be corrupted. Please try again!"), tr("Try Again"), tr("Cancel")) == 0)
2061 QApplication::setOverrideCursor(Qt::WaitCursor
);
2062 process
.start(binaryElevator
, QStringList() << QString("/exec=%1").arg(setupFile
));
2063 loop
.exec(QEventLoop::ExcludeUserInputEvents
);
2064 QFile::remove(setupFile
);
2065 QApplication::restoreOverrideCursor();
2067 if(QMessageBox::information(this, tr("WMA Decoder"), tr("The WMA File Decoder has been installed. Please restart LameXP now!"), tr("Quit LameXP"), tr("Postpone")) == 0)
2069 QApplication::quit();
2075 void MainWindow::showDropBoxWidgetActionTriggered(bool checked
)
2077 m_settings
->dropBoxWidgetEnabled(true);
2079 if(!m_dropBox
->isVisible())
2084 FLASH_WINDOW(m_dropBox
);