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"
40 #include "ShellIntegration.h"
43 #include <QMessageBox>
45 #include <QDesktopWidget>
47 #include <QFileDialog>
48 #include <QInputDialog>
49 #include <QFileSystemModel>
50 #include <QDesktopServices>
52 #include <QPlastiqueStyle>
53 #include <QCleanlooksStyle>
54 #include <QWindowsVistaStyle>
55 #include <QWindowsStyle>
57 #include <QDragEnterEvent>
58 #include <QWindowsMime>
61 #include <QProcessEnvironment>
62 #include <QCryptographicHash>
63 #include <QTranslator>
71 #define ABORT_IF_BUSY if(m_banner->isVisible() || m_delayedFileTimer->isActive()) { MessageBeep(MB_ICONEXCLAMATION); return; }
72 #define SET_TEXT_COLOR(WIDGET,COLOR) { QPalette _palette = WIDGET->palette(); _palette.setColor(QPalette::WindowText, COLOR); WIDGET->setPalette(_palette); }
73 #define SET_FONT_BOLD(WIDGET,BOLD) { QFont _font = WIDGET->font(); _font.setBold(BOLD); WIDGET->setFont(_font); }
74 #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); }
75 #define LINK(URL) QString("<a href=\"%1\">%2</a>").arg(URL).arg(URL)
76 #define TEMP_HIDE_DROPBOX(CMD) { bool __dropBoxVisible = m_dropBox->isVisible(); if(__dropBoxVisible) m_dropBox->hide(); CMD; if(__dropBoxVisible) m_dropBox->show(); }
78 ////////////////////////////////////////////////////////////
80 ////////////////////////////////////////////////////////////
82 MainWindow::MainWindow(FileListModel
*fileListModel
, AudioFileModel
*metaInfo
, SettingsModel
*settingsModel
, QWidget
*parent
)
85 m_fileListModel(fileListModel
),
87 m_settings(settingsModel
),
89 m_firstTimeShown(true)
91 //Init the dialog, from the .ui file
93 setWindowFlags(windowFlags() ^ Qt::WindowMaximizeButtonHint
);
96 qRegisterMetaType
<AudioFileModel
>("AudioFileModel");
98 //Enabled main buttons
99 connect(buttonAbout
, SIGNAL(clicked()), this, SLOT(aboutButtonClicked()));
100 connect(buttonStart
, SIGNAL(clicked()), this, SLOT(encodeButtonClicked()));
101 connect(buttonQuit
, SIGNAL(clicked()), this, SLOT(closeButtonClicked()));
104 tabWidget
->setCurrentIndex(0);
105 connect(tabWidget
, SIGNAL(currentChanged(int)), this, SLOT(tabPageChanged(int)));
108 sourceFileView
->setModel(m_fileListModel
);
109 sourceFileView
->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents
);
110 sourceFileView
->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents
);
111 sourceFileView
->setContextMenuPolicy(Qt::CustomContextMenu
);
112 m_dropNoteLabel
= new QLabel(sourceFileView
);
113 m_dropNoteLabel
->setAlignment(Qt::AlignHCenter
| Qt::AlignVCenter
);
114 SET_FONT_BOLD(m_dropNoteLabel
, true);
115 SET_TEXT_COLOR(m_dropNoteLabel
, Qt::darkGray
);
116 m_sourceFilesContextMenu
= new QMenu();
117 m_showDetailsContextAction
= m_sourceFilesContextMenu
->addAction(QIcon(":/icons/zoom.png"), "N/A");
118 m_previewContextAction
= m_sourceFilesContextMenu
->addAction(QIcon(":/icons/sound.png"), "N/A");
119 m_findFileContextAction
= m_sourceFilesContextMenu
->addAction(QIcon(":/icons/folder_go.png"), "N/A");
120 SET_FONT_BOLD(m_showDetailsContextAction
, true);
121 connect(buttonAddFiles
, SIGNAL(clicked()), this, SLOT(addFilesButtonClicked()));
122 connect(buttonRemoveFile
, SIGNAL(clicked()), this, SLOT(removeFileButtonClicked()));
123 connect(buttonClearFiles
, SIGNAL(clicked()), this, SLOT(clearFilesButtonClicked()));
124 connect(buttonFileUp
, SIGNAL(clicked()), this, SLOT(fileUpButtonClicked()));
125 connect(buttonFileDown
, SIGNAL(clicked()), this, SLOT(fileDownButtonClicked()));
126 connect(buttonShowDetails
, SIGNAL(clicked()), this, SLOT(showDetailsButtonClicked()));
127 connect(m_fileListModel
, SIGNAL(rowsInserted(QModelIndex
,int,int)), this, SLOT(sourceModelChanged()));
128 connect(m_fileListModel
, SIGNAL(rowsRemoved(QModelIndex
,int,int)), this, SLOT(sourceModelChanged()));
129 connect(m_fileListModel
, SIGNAL(modelReset()), this, SLOT(sourceModelChanged()));
130 connect(sourceFileView
, SIGNAL(customContextMenuRequested(QPoint
)), this, SLOT(sourceFilesContextMenu(QPoint
)));
131 connect(m_showDetailsContextAction
, SIGNAL(triggered(bool)), this, SLOT(showDetailsButtonClicked()));
132 connect(m_previewContextAction
, SIGNAL(triggered(bool)), this, SLOT(previewContextActionTriggered()));
133 connect(m_findFileContextAction
, SIGNAL(triggered(bool)), this, SLOT(findFileContextActionTriggered()));
136 m_fileSystemModel
= new QFileSystemModelEx();
137 m_fileSystemModel
->setRootPath(m_fileSystemModel
->rootPath());
138 m_fileSystemModel
->installEventFilter(this);
139 outputFolderView
->setModel(m_fileSystemModel
);
140 outputFolderView
->header()->setStretchLastSection(true);
141 outputFolderView
->header()->hideSection(1);
142 outputFolderView
->header()->hideSection(2);
143 outputFolderView
->header()->hideSection(3);
144 outputFolderView
->setHeaderHidden(true);
145 outputFolderView
->setAnimated(true);
146 outputFolderView
->setMouseTracking(false);
147 outputFolderView
->setContextMenuPolicy(Qt::CustomContextMenu
);
148 while(saveToSourceFolderCheckBox
->isChecked() != m_settings
->outputToSourceDir()) saveToSourceFolderCheckBox
->click();
149 prependRelativePathCheckBox
->setChecked(m_settings
->prependRelativeSourcePath());
150 connect(outputFolderView
, SIGNAL(clicked(QModelIndex
)), this, SLOT(outputFolderViewClicked(QModelIndex
)));
151 connect(outputFolderView
, SIGNAL(activated(QModelIndex
)), this, SLOT(outputFolderViewClicked(QModelIndex
)));
152 connect(outputFolderView
, SIGNAL(pressed(QModelIndex
)), this, SLOT(outputFolderViewClicked(QModelIndex
)));
153 connect(outputFolderView
, SIGNAL(entered(QModelIndex
)), this, SLOT(outputFolderViewMoved(QModelIndex
)));
154 outputFolderView
->setCurrentIndex(m_fileSystemModel
->index(m_settings
->outputDir()));
155 outputFolderViewClicked(outputFolderView
->currentIndex());
156 connect(buttonMakeFolder
, SIGNAL(clicked()), this, SLOT(makeFolderButtonClicked()));
157 connect(buttonGotoHome
, SIGNAL(clicked()), SLOT(gotoHomeFolderButtonClicked()));
158 connect(buttonGotoDesktop
, SIGNAL(clicked()), this, SLOT(gotoDesktopButtonClicked()));
159 connect(buttonGotoMusic
, SIGNAL(clicked()), this, SLOT(gotoMusicFolderButtonClicked()));
160 connect(saveToSourceFolderCheckBox
, SIGNAL(clicked()), this, SLOT(saveToSourceFolderChanged()));
161 connect(prependRelativePathCheckBox
, SIGNAL(clicked()), this, SLOT(prependRelativePathChanged()));
162 m_outputFolderContextMenu
= new QMenu();
163 m_showFolderContextAction
= m_outputFolderContextMenu
->addAction(QIcon(":/icons/zoom.png"), "N/A");
164 connect(outputFolderView
, SIGNAL(customContextMenuRequested(QPoint
)), this, SLOT(outputFolderContextMenu(QPoint
)));
165 connect(m_showFolderContextAction
, SIGNAL(triggered(bool)), this, SLOT(showFolderContextActionTriggered()));
166 outputFolderLabel
->installEventFilter(this);
168 //Setup "Meta Data" tab
169 m_metaInfoModel
= new MetaInfoModel(m_metaData
, 6);
170 m_metaInfoModel
->clearData();
171 metaDataView
->setModel(m_metaInfoModel
);
172 metaDataView
->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents
);
173 metaDataView
->verticalHeader()->hide();
174 metaDataView
->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents
);
175 while(writeMetaDataCheckBox
->isChecked() != m_settings
->writeMetaTags()) writeMetaDataCheckBox
->click();
176 generatePlaylistCheckBox
->setChecked(m_settings
->createPlaylist());
177 connect(buttonEditMeta
, SIGNAL(clicked()), this, SLOT(editMetaButtonClicked()));
178 connect(buttonClearMeta
, SIGNAL(clicked()), this, SLOT(clearMetaButtonClicked()));
179 connect(writeMetaDataCheckBox
, SIGNAL(clicked()), this, SLOT(metaTagsEnabledChanged()));
180 connect(generatePlaylistCheckBox
, SIGNAL(clicked()), this, SLOT(playlistEnabledChanged()));
182 //Setup "Compression" tab
183 m_encoderButtonGroup
= new QButtonGroup(this);
184 m_encoderButtonGroup
->addButton(radioButtonEncoderMP3
, SettingsModel::MP3Encoder
);
185 m_encoderButtonGroup
->addButton(radioButtonEncoderVorbis
, SettingsModel::VorbisEncoder
);
186 m_encoderButtonGroup
->addButton(radioButtonEncoderAAC
, SettingsModel::AACEncoder
);
187 m_encoderButtonGroup
->addButton(radioButtonEncoderFLAC
, SettingsModel::FLACEncoder
);
188 m_encoderButtonGroup
->addButton(radioButtonEncoderPCM
, SettingsModel::PCMEncoder
);
189 m_modeButtonGroup
= new QButtonGroup(this);
190 m_modeButtonGroup
->addButton(radioButtonModeQuality
, SettingsModel::VBRMode
);
191 m_modeButtonGroup
->addButton(radioButtonModeAverageBitrate
, SettingsModel::ABRMode
);
192 m_modeButtonGroup
->addButton(radioButtonConstBitrate
, SettingsModel::CBRMode
);
193 radioButtonEncoderMP3
->setChecked(m_settings
->compressionEncoder() == SettingsModel::MP3Encoder
);
194 radioButtonEncoderVorbis
->setChecked(m_settings
->compressionEncoder() == SettingsModel::VorbisEncoder
);
195 radioButtonEncoderAAC
->setChecked(m_settings
->compressionEncoder() == SettingsModel::AACEncoder
);
196 radioButtonEncoderFLAC
->setChecked(m_settings
->compressionEncoder() == SettingsModel::FLACEncoder
);
197 radioButtonEncoderPCM
->setChecked(m_settings
->compressionEncoder() == SettingsModel::PCMEncoder
);
198 radioButtonModeQuality
->setChecked(m_settings
->compressionRCMode() == SettingsModel::VBRMode
);
199 radioButtonModeAverageBitrate
->setChecked(m_settings
->compressionRCMode() == SettingsModel::ABRMode
);
200 radioButtonConstBitrate
->setChecked(m_settings
->compressionRCMode() == SettingsModel::CBRMode
);
201 sliderBitrate
->setValue(m_settings
->compressionBitrate());
202 connect(m_encoderButtonGroup
, SIGNAL(buttonClicked(int)), this, SLOT(updateEncoder(int)));
203 connect(m_modeButtonGroup
, SIGNAL(buttonClicked(int)), this, SLOT(updateRCMode(int)));
204 connect(sliderBitrate
, SIGNAL(valueChanged(int)), this, SLOT(updateBitrate(int)));
205 updateEncoder(m_encoderButtonGroup
->checkedId());
207 //Setup "Advanced Options" tab
208 sliderLameAlgoQuality
->setValue(m_settings
->lameAlgoQuality());
209 spinBoxBitrateManagementMin
->setValue(m_settings
->bitrateManagementMinRate());
210 spinBoxBitrateManagementMax
->setValue(m_settings
->bitrateManagementMaxRate());
211 spinBoxNormalizationFilter
->setValue(static_cast<double>(m_settings
->normalizationFilterMaxVolume()) / 100.0);
212 spinBoxToneAdjustBass
->setValue(static_cast<double>(m_settings
->toneAdjustBass()) / 100.0);
213 spinBoxToneAdjustTreble
->setValue(static_cast<double>(m_settings
->toneAdjustTreble()) / 100.0);
214 comboBoxMP3ChannelMode
->setCurrentIndex(m_settings
->lameChannelMode());
215 comboBoxSamplingRate
->setCurrentIndex(m_settings
->samplingRate());
216 comboBoxNeroAACProfile
->setCurrentIndex(m_settings
->neroAACProfile());
217 while(checkBoxBitrateManagement
->isChecked() != m_settings
->bitrateManagementEnabled()) checkBoxBitrateManagement
->click();
218 while(checkBoxNeroAAC2PassMode
->isChecked() != m_settings
->neroAACEnable2Pass()) checkBoxNeroAAC2PassMode
->click();
219 while(checkBoxNormalizationFilter
->isChecked() != m_settings
->normalizationFilterEnabled()) checkBoxNormalizationFilter
->click();
220 connect(sliderLameAlgoQuality
, SIGNAL(valueChanged(int)), this, SLOT(updateLameAlgoQuality(int)));
221 connect(checkBoxBitrateManagement
, SIGNAL(clicked(bool)), this, SLOT(bitrateManagementEnabledChanged(bool)));
222 connect(spinBoxBitrateManagementMin
, SIGNAL(valueChanged(int)), this, SLOT(bitrateManagementMinChanged(int)));
223 connect(spinBoxBitrateManagementMax
, SIGNAL(valueChanged(int)), this, SLOT(bitrateManagementMaxChanged(int)));
224 connect(comboBoxMP3ChannelMode
, SIGNAL(currentIndexChanged(int)), this, SLOT(channelModeChanged(int)));
225 connect(comboBoxSamplingRate
, SIGNAL(currentIndexChanged(int)), this, SLOT(samplingRateChanged(int)));
226 connect(checkBoxNeroAAC2PassMode
, SIGNAL(clicked(bool)), this, SLOT(neroAAC2PassChanged(bool)));
227 connect(comboBoxNeroAACProfile
, SIGNAL(currentIndexChanged(int)), this, SLOT(neroAACProfileChanged(int)));
228 connect(checkBoxNormalizationFilter
, SIGNAL(clicked(bool)), this, SLOT(normalizationEnabledChanged(bool)));
229 connect(spinBoxNormalizationFilter
, SIGNAL(valueChanged(double)), this, SLOT(normalizationMaxVolumeChanged(double)));
230 connect(spinBoxToneAdjustBass
, SIGNAL(valueChanged(double)), this, SLOT(toneAdjustBassChanged(double)));
231 connect(spinBoxToneAdjustTreble
, SIGNAL(valueChanged(double)), this, SLOT(toneAdjustTrebleChanged(double)));
232 connect(buttonToneAdjustReset
, SIGNAL(clicked()), this, SLOT(toneAdjustTrebleReset()));
233 connect(buttonResetAdvancedOptions
, SIGNAL(clicked()), this, SLOT(resetAdvancedOptionsButtonClicked()));
234 updateLameAlgoQuality(sliderLameAlgoQuality
->value());
235 toneAdjustTrebleChanged(spinBoxToneAdjustTreble
->value());
236 toneAdjustBassChanged(spinBoxToneAdjustBass
->value());
238 //Activate file menu actions
239 connect(actionOpenFolder
, SIGNAL(triggered()), this, SLOT(openFolderActionActivated()));
241 //Activate view menu actions
242 m_tabActionGroup
= new QActionGroup(this);
243 m_tabActionGroup
->addAction(actionSourceFiles
);
244 m_tabActionGroup
->addAction(actionOutputDirectory
);
245 m_tabActionGroup
->addAction(actionCompression
);
246 m_tabActionGroup
->addAction(actionMetaData
);
247 m_tabActionGroup
->addAction(actionAdvancedOptions
);
248 actionSourceFiles
->setData(0);
249 actionOutputDirectory
->setData(1);
250 actionMetaData
->setData(2);
251 actionCompression
->setData(3);
252 actionAdvancedOptions
->setData(4);
253 actionSourceFiles
->setChecked(true);
254 connect(m_tabActionGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(tabActionActivated(QAction
*)));
256 //Activate style menu actions
257 m_styleActionGroup
= new QActionGroup(this);
258 m_styleActionGroup
->addAction(actionStylePlastique
);
259 m_styleActionGroup
->addAction(actionStyleCleanlooks
);
260 m_styleActionGroup
->addAction(actionStyleWindowsVista
);
261 m_styleActionGroup
->addAction(actionStyleWindowsXP
);
262 m_styleActionGroup
->addAction(actionStyleWindowsClassic
);
263 actionStylePlastique
->setData(0);
264 actionStyleCleanlooks
->setData(1);
265 actionStyleWindowsVista
->setData(2);
266 actionStyleWindowsXP
->setData(3);
267 actionStyleWindowsClassic
->setData(4);
268 actionStylePlastique
->setChecked(true);
269 actionStyleWindowsXP
->setEnabled((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based
) >= QSysInfo::WV_XP
&& lamexp_themes_enabled());
270 actionStyleWindowsVista
->setEnabled((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based
) >= QSysInfo::WV_VISTA
&& lamexp_themes_enabled());
271 connect(m_styleActionGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(styleActionActivated(QAction
*)));
272 styleActionActivated(NULL
);
274 //Populate the language menu
275 m_languageActionGroup
= new QActionGroup(this);
276 QStringList translations
= lamexp_query_translations();
277 while(!translations
.isEmpty())
279 QString langId
= translations
.takeFirst();
280 QAction
*currentLanguage
= new QAction(this);
281 currentLanguage
->setData(langId
);
282 currentLanguage
->setText(lamexp_translation_name(langId
));
283 currentLanguage
->setIcon(QIcon(QString(":/flags/%1.png").arg(langId
)));
284 currentLanguage
->setCheckable(true);
285 m_languageActionGroup
->addAction(currentLanguage
);
286 menuLanguage
->insertAction(actionLoadTranslationFromFile
, currentLanguage
);
288 menuLanguage
->insertSeparator(actionLoadTranslationFromFile
);
289 connect(actionLoadTranslationFromFile
, SIGNAL(triggered(bool)), this, SLOT(languageFromFileActionActivated(bool)));
290 connect(m_languageActionGroup
, SIGNAL(triggered(QAction
*)), this, SLOT(languageActionActivated(QAction
*)));
292 //Activate tools menu actions
293 actionDisableUpdateReminder
->setChecked(!m_settings
->autoUpdateEnabled());
294 actionDisableSounds
->setChecked(!m_settings
->soundsEnabled());
295 actionDisableNeroAacNotifications
->setChecked(!m_settings
->neroAacNotificationsEnabled());
296 actionDisableWmaDecoderNotifications
->setChecked(!m_settings
->wmaDecoderNotificationsEnabled());
297 actionDisableShellIntegration
->setChecked(!m_settings
->shellIntegrationEnabled());
298 actionDisableShellIntegration
->setDisabled(lamexp_portable_mode() && actionDisableShellIntegration
->isChecked());
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(actionDisableShellIntegration
, SIGNAL(triggered(bool)), this, SLOT(disableShellIntegrationActionTriggered(bool)));
305 connect(actionShowDropBoxWidget
, SIGNAL(triggered(bool)), this, SLOT(showDropBoxWidgetActionTriggered(bool)));
307 //Activate help menu actions
308 connect(actionCheckUpdates
, SIGNAL(triggered()), this, SLOT(checkUpdatesActionActivated()));
309 connect(actionVisitHomepage
, SIGNAL(triggered()), this, SLOT(visitHomepageActionActivated()));
311 //Center window in screen
312 QRect desktopRect
= QApplication::desktop()->screenGeometry();
313 QRect thisRect
= this->geometry();
314 move((desktopRect
.width() - thisRect
.width()) / 2, (desktopRect
.height() - thisRect
.height()) / 2);
315 setMinimumSize(thisRect
.width(), thisRect
.height());
318 m_banner
= new WorkingBanner(this);
320 //Create DropBox widget
321 m_dropBox
= new DropBox(this, m_fileListModel
, m_settings
);
322 connect(m_fileListModel
, SIGNAL(modelReset()), m_dropBox
, SLOT(modelChanged()));
323 connect(m_fileListModel
, SIGNAL(rowsInserted(QModelIndex
,int,int)), m_dropBox
, SLOT(modelChanged()));
324 connect(m_fileListModel
, SIGNAL(rowsRemoved(QModelIndex
,int,int)), m_dropBox
, SLOT(modelChanged()));
326 //Create message handler thread
327 m_messageHandler
= new MessageHandlerThread();
328 m_delayedFileList
= new QStringList();
329 m_delayedFileTimer
= new QTimer();
330 connect(m_messageHandler
, SIGNAL(otherInstanceDetected()), this, SLOT(notifyOtherInstance()), Qt::QueuedConnection
);
331 connect(m_messageHandler
, SIGNAL(fileReceived(QString
)), this, SLOT(addFileDelayed(QString
)), Qt::QueuedConnection
);
332 connect(m_messageHandler
, SIGNAL(killSignalReceived()), this, SLOT(close()), Qt::QueuedConnection
);
333 connect(m_delayedFileTimer
, SIGNAL(timeout()), this, SLOT(handleDelayedFiles()));
334 m_messageHandler
->start();
336 //Load translation file
337 QList
<QAction
*> languageActions
= m_languageActionGroup
->actions();
338 while(!languageActions
.isEmpty())
340 QAction
*currentLanguage
= languageActions
.takeFirst();
341 if(currentLanguage
->data().toString().compare(m_settings
->currentLanguage(), Qt::CaseInsensitive
) == 0)
343 currentLanguage
->setChecked(true);
344 languageActionActivated(currentLanguage
);
348 //Re-translate (make sure we translate once)
349 QEvent
languageChangeEvent(QEvent::LanguageChange
);
350 changeEvent(&languageChangeEvent
);
353 this->setAcceptDrops(true);
356 ////////////////////////////////////////////////////////////
358 ////////////////////////////////////////////////////////////
360 MainWindow::~MainWindow(void)
362 //Stop message handler thread
363 if(m_messageHandler
&& m_messageHandler
->isRunning())
365 m_messageHandler
->stop();
366 if(!m_messageHandler
->wait(10000))
368 m_messageHandler
->terminate();
369 m_messageHandler
->wait();
374 sourceFileView
->setModel(NULL
);
375 metaDataView
->setModel(NULL
);
378 LAMEXP_DELETE(m_tabActionGroup
);
379 LAMEXP_DELETE(m_styleActionGroup
);
380 LAMEXP_DELETE(m_languageActionGroup
);
381 LAMEXP_DELETE(m_banner
);
382 LAMEXP_DELETE(m_fileSystemModel
);
383 LAMEXP_DELETE(m_messageHandler
);
384 LAMEXP_DELETE(m_delayedFileList
);
385 LAMEXP_DELETE(m_delayedFileTimer
);
386 LAMEXP_DELETE(m_metaInfoModel
);
387 LAMEXP_DELETE(m_encoderButtonGroup
);
388 LAMEXP_DELETE(m_encoderButtonGroup
);
389 LAMEXP_DELETE(m_sourceFilesContextMenu
);
390 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();
430 * Download and install WMA Decoder component
432 void MainWindow::installWMADecoder(void)
434 static const char *download_url
= "http://www.nch.com.au/components/wmawav.exe";
435 static const char *download_hash
= "52a3b0e6690faf3f830c336d3c0eadfb7a4e9bc6";
437 QString binaryWGet
= lamexp_lookup_tool("wget.exe");
438 QString binaryElevator
= lamexp_lookup_tool("elevator.exe");
440 if(binaryWGet
.isEmpty() || binaryElevator
.isEmpty())
442 throw "Required binary is not available!";
447 QString setupFile
= QString("%1/%2.exe").arg(lamexp_temp_folder(), lamexp_rand_str());
450 process
.setWorkingDirectory(QFileInfo(setupFile
).absolutePath());
453 connect(&process
, SIGNAL(error(QProcess::ProcessError
)), &loop
, SLOT(quit()));
454 connect(&process
, SIGNAL(finished(int, QProcess::ExitStatus
)), &loop
, SLOT(quit()));
456 process
.start(binaryWGet
, QStringList() << "-O" << QFileInfo(setupFile
).fileName() << download_url
);
457 m_banner
->show(tr("Downloading WMA Decoder Setup, please wait..."), &loop
);
459 if(process
.exitCode() != 0 || QFileInfo(setupFile
).size() < 10240)
461 QFile::remove(setupFile
);
462 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)
469 QFile
setupFileContent(setupFile
);
470 QCryptographicHash
setupFileHash(QCryptographicHash::Sha1
);
472 setupFileContent
.open(QIODevice::ReadOnly
);
473 if(setupFileContent
.isOpen() && setupFileContent
.isReadable())
475 setupFileHash
.addData(setupFileContent
.readAll());
476 setupFileContent
.close();
479 if(_stricmp(setupFileHash
.result().toHex().constData(), download_hash
))
481 qWarning("Hash miscompare:\n Expected %s\n Detected %s\n", download_hash
, setupFileHash
.result().toHex().constData());
482 QFile::remove(setupFile
);
483 if(QMessageBox::critical(this, tr("Download Failed"), tr("The download seems to be corrupted. Please try again!"), tr("Try Again"), tr("Cancel")) == 0)
490 QApplication::setOverrideCursor(Qt::WaitCursor
);
491 process
.start(binaryElevator
, QStringList() << QString("/exec=%1").arg(setupFile
));
492 loop
.exec(QEventLoop::ExcludeUserInputEvents
);
493 QFile::remove(setupFile
);
494 QApplication::restoreOverrideCursor();
496 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)
498 QApplication::quit();
504 ////////////////////////////////////////////////////////////
506 ////////////////////////////////////////////////////////////
509 * Window is about to be shown
511 void MainWindow::showEvent(QShowEvent
*event
)
514 m_dropNoteLabel
->setGeometry(0, 0, sourceFileView
->width(), sourceFileView
->height());
515 sourceModelChanged();
516 tabWidget
->setCurrentIndex(0);
520 m_firstTimeShown
= false;
521 QTimer::singleShot(0, this, SLOT(windowShown()));
525 if(m_settings
->dropBoxWidgetEnabled())
527 m_dropBox
->setVisible(true);
533 * Re-translate the UI
535 void MainWindow::changeEvent(QEvent
*e
)
537 if(e
->type() == QEvent::LanguageChange
)
539 int comboBoxIndex
[3];
541 //Backup combobox indices
542 comboBoxIndex
[0] = comboBoxMP3ChannelMode
->currentIndex();
543 comboBoxIndex
[1] = comboBoxSamplingRate
->currentIndex();
544 comboBoxIndex
[2] = comboBoxNeroAACProfile
->currentIndex();
546 //Re.translate from UIC
547 Ui::MainWindow::retranslateUi(this);
549 //Restore combobox indices
550 comboBoxMP3ChannelMode
->setCurrentIndex(comboBoxIndex
[0]);
551 comboBoxSamplingRate
->setCurrentIndex(comboBoxIndex
[1]);
552 comboBoxNeroAACProfile
->setCurrentIndex(comboBoxIndex
[2]);
554 if(lamexp_version_demo())
556 setWindowTitle(QString("%1 [%2]").arg(windowTitle(), tr("DEMO VERSION")));
559 //Manual re-translate
560 m_dropNoteLabel
->setText(QString("» %1 «").arg(tr("You can drop in audio files here!")));
561 m_showDetailsContextAction
->setText(tr("Show Details"));
562 m_previewContextAction
->setText(tr("Open File in External Application"));
563 m_findFileContextAction
->setText(tr("Browse File Location"));
564 m_showFolderContextAction
->setText(tr("Browse Selected Folder"));
567 m_metaInfoModel
->clearData();
568 updateEncoder(m_settings
->compressionEncoder());
569 updateLameAlgoQuality(sliderLameAlgoQuality
->value());
571 if(m_settings
->shellIntegrationEnabled())
573 ShellIntegration::install();
579 * File dragged over window
581 void MainWindow::dragEnterEvent(QDragEnterEvent
*event
)
583 QStringList formats
= event
->mimeData()->formats();
585 if(formats
.contains("application/x-qt-windows-mime;value=\"FileNameW\"", Qt::CaseInsensitive
) && formats
.contains("text/uri-list", Qt::CaseInsensitive
))
587 event
->acceptProposedAction();
592 * File dropped onto window
594 void MainWindow::dropEvent(QDropEvent
*event
)
598 QStringList droppedFiles
;
599 const QList
<QUrl
> urls
= event
->mimeData()->urls();
601 for(int i
= 0; i
< urls
.count(); i
++)
603 QFileInfo
file(urls
.at(i
).toLocalFile());
610 droppedFiles
<< file
.canonicalFilePath();
615 QList
<QFileInfo
> list
= QDir(file
.canonicalFilePath()).entryInfoList(QDir::Files
);
616 for(int j
= 0; j
< list
.count(); j
++)
618 droppedFiles
<< list
.at(j
).canonicalFilePath();
623 addFiles(droppedFiles
);
627 * Window tries to close
629 void MainWindow::closeEvent(QCloseEvent
*event
)
631 if(m_banner
->isVisible() || m_delayedFileTimer
->isActive())
633 MessageBeep(MB_ICONEXCLAMATION
);
646 void MainWindow::resizeEvent(QResizeEvent
*event
)
648 QMainWindow::resizeEvent(event
);
649 m_dropNoteLabel
->setGeometry(0, 0, sourceFileView
->width(), sourceFileView
->height());
655 bool MainWindow::eventFilter(QObject
*obj
, QEvent
*event
)
657 if(obj
== m_fileSystemModel
&& QApplication::overrideCursor() == NULL
)
659 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor
));
660 QTimer::singleShot(250, this, SLOT(restoreCursor()));
662 else if(obj
== outputFolderLabel
)
664 switch(event
->type())
666 case QEvent::MouseButtonPress
:
667 if(dynamic_cast<QMouseEvent
*>(event
)->button() == Qt::LeftButton
)
669 QDesktopServices::openUrl(QString("file:///%1").arg(outputFolderLabel
->text()));
673 outputFolderLabel
->setForegroundRole(QPalette::Link
);
676 outputFolderLabel
->setForegroundRole(QPalette::WindowText
);
683 ////////////////////////////////////////////////////////////
685 ////////////////////////////////////////////////////////////
690 void MainWindow::windowShown(void)
692 QStringList arguments
= QApplication::arguments();
695 if(m_settings
->licenseAccepted() <= 0)
699 if(m_settings
->licenseAccepted() == 0)
701 AboutDialog
*about
= new AboutDialog(m_settings
, this, true);
702 iAccepted
= about
->exec();
703 LAMEXP_DELETE(about
);
708 m_settings
->licenseAccepted(-1);
709 QApplication::processEvents();
710 PlaySound(MAKEINTRESOURCE(IDR_WAVE_WHAMMY
), GetModuleHandle(NULL
), SND_RESOURCE
| SND_SYNC
);
711 QMessageBox::critical(this, tr("License Declined"), tr("You have declined the license. Consequently the application will exit now!"), tr("Goodbye!"));
712 QProcess::startDetached(QString("%1/Uninstall.exe").arg(QApplication::applicationDirPath()), QStringList());
713 QApplication::quit();
717 PlaySound(MAKEINTRESOURCE(IDR_WAVE_WOOHOO
), GetModuleHandle(NULL
), SND_RESOURCE
| SND_SYNC
);
718 m_settings
->licenseAccepted(1);
721 //Check for expiration
722 if(lamexp_version_demo())
724 if(QDate::currentDate() >= lamexp_version_expires())
726 qWarning("Binary has expired !!!");
727 PlaySound(MAKEINTRESOURCE(IDR_WAVE_WHAMMY
), GetModuleHandle(NULL
), SND_RESOURCE
| SND_SYNC
);
728 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)
730 checkUpdatesActionActivated();
732 QApplication::quit();
738 if(QDate::currentDate() >= lamexp_version_date().addYears(1))
740 qWarning("Binary is more than a year old, time to update!");
741 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)
743 checkUpdatesActionActivated();
747 QApplication::quit();
751 else if(m_settings
->autoUpdateEnabled())
753 QDate lastUpdateCheck
= QDate::fromString(m_settings
->autoUpdateLastCheck(), Qt::ISODate
);
754 if(!lastUpdateCheck
.isValid() || QDate::currentDate() >= lastUpdateCheck
.addDays(14))
756 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)
758 checkUpdatesActionActivated();
763 //Check for AAC support
764 if(m_settings
->neroAacNotificationsEnabled())
766 if(lamexp_check_tool("neroAacEnc.exe") && lamexp_check_tool("neroAacDec.exe") && lamexp_check_tool("neroAacTag.exe"))
768 if(lamexp_tool_version("neroAacEnc.exe") < lamexp_toolver_neroaac())
771 messageText
+= QString("<nobr>%1<br>").arg(tr("LameXP detected that your version of the Nero AAC encoder is outdated!"));
772 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"))));
773 messageText
+= QString("%1<br>").arg(tr("You can download the latest version of the Nero AAC encoder from the Nero website at:"));
774 messageText
+= "<tt>" + LINK(AboutDialog::neroAacUrl
) + "</tt><br></nobr>";
775 QMessageBox::information(this, tr("AAC Encoder Outdated"), messageText
);
780 radioButtonEncoderAAC
->setEnabled(false);
781 QString appPath
= QDir(QCoreApplication::applicationDirPath()).canonicalPath();
782 if(appPath
.isEmpty()) appPath
= QCoreApplication::applicationDirPath();
784 messageText
+= QString("<nobr>%1<br>").arg(tr("The Nero AAC encoder could not be found. AAC encoding support will be disabled."));
785 messageText
+= QString("%1<br><br>").arg(tr("Please put 'neroAacEnc.exe', 'neroAacDec.exe' and 'neroAacTag.exe' into the LameXP directory!"));
786 messageText
+= QString("%1<br>").arg(tr("Your LameXP directory is located here:"));
787 messageText
+= QString("<i><nobr><a href=\"file:///%1\">%1</a></nobr></i><br><br>").arg(QDir::toNativeSeparators(appPath
));
788 messageText
+= QString("%1<br>").arg(tr("You can download the Nero AAC encoder for free from the official Nero website at:"));
789 messageText
+= "<tt>" + LINK(AboutDialog::neroAacUrl
) + "</tt><br></nobr>";
790 QMessageBox::information(this, tr("AAC Support Disabled"), messageText
);
794 //Check for WMA support
795 if(m_settings
->wmaDecoderNotificationsEnabled())
797 if(!lamexp_check_tool("wmawav.exe"))
800 messageText
+= QString("<nobr>%1<br>").arg(tr("LameXP has detected that the WMA File Decoder component is not currently installed on your system."));
801 messageText
+= QString("%1<br><br>").arg(tr("You won't be able to process WMA files as input unless the WMA File Decoder component is installed!"));
802 messageText
+= QString("%1</nobr>").arg(tr("Do you want to download and install the WMA File Decoder component now?"));
803 if(QMessageBox::information(this, tr("WMA Decoder Missing"), messageText
, tr("Download && Install"), tr("Postpone")) == 0)
810 //Add files from the command-line
811 for(int i
= 0; i
< arguments
.count() - 1; i
++)
813 if(!arguments
[i
].compare("--add", Qt::CaseInsensitive
))
815 QFileInfo
currentFile(arguments
[++i
].trimmed());
816 qDebug("Adding file from CLI: %s", currentFile
.canonicalFilePath().toUtf8().constData());
817 m_delayedFileList
->append(currentFile
.canonicalFilePath());
821 //Start delayed files timer
822 if(!m_delayedFileList
->isEmpty() && !m_delayedFileTimer
->isActive())
824 m_delayedFileTimer
->start(5000);
827 //Enable shell integration
828 if(m_settings
->shellIntegrationEnabled())
830 ShellIntegration::install();
833 //Make DropBox visible
834 if(m_settings
->dropBoxWidgetEnabled())
836 m_dropBox
->setVisible(true);
843 void MainWindow::aboutButtonClicked(void)
849 AboutDialog
*aboutBox
= new AboutDialog(m_settings
, this);
851 LAMEXP_DELETE(aboutBox
);
858 void MainWindow::encodeButtonClicked(void)
860 static const __int64 oneGigabyte
= 1073741824;
861 static const __int64 minimumFreeDiskspaceMultiplier
= 2;
865 if(m_fileListModel
->rowCount() < 1)
867 QMessageBox::warning(this, tr("LameXP"), QString("<nobr>%1</nobr>").arg(tr("You must add at least one file to the list before proceeding!")));
868 tabWidget
->setCurrentIndex(0);
872 __int64 currentFreeDiskspace
= lamexp_free_diskspace(lamexp_temp_folder());
874 if(currentFreeDiskspace
< (oneGigabyte
* minimumFreeDiskspaceMultiplier
))
876 QStringList tempFolderParts
= lamexp_temp_folder().split("/", QString::SkipEmptyParts
, Qt::CaseInsensitive
);
877 tempFolderParts
.takeLast();
878 if(m_settings
->soundsEnabled()) PlaySound(MAKEINTRESOURCE(IDR_WAVE_WHAMMY
), GetModuleHandle(NULL
), SND_RESOURCE
| SND_SYNC
);
879 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")))
882 QProcess::startDetached(QString("%1/cleanmgr.exe").arg(lamexp_known_folder(lamexp_folder_systemfolder
)), QStringList() << "/D" << tempFolderParts
.first());
887 QMessageBox::warning(this, tr("Low Diskspace"), tr("You are proceeding with low diskspace. Problems might occur!"));
892 switch(m_settings
->compressionEncoder())
894 case SettingsModel::MP3Encoder
:
895 case SettingsModel::VorbisEncoder
:
896 case SettingsModel::AACEncoder
:
897 case SettingsModel::FLACEncoder
:
898 case SettingsModel::PCMEncoder
:
901 QMessageBox::warning(this, tr("LameXP"), tr("Sorry, an unsupported encoder has been chosen!"));
902 tabWidget
->setCurrentIndex(3);
906 if(!m_settings
->outputToSourceDir())
908 QFile
writeTest(QString("%1/~%2.txt").arg(m_settings
->outputDir(), QUuid::createUuid().toString()));
909 if(!writeTest
.open(QIODevice::ReadWrite
))
911 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!")));
912 tabWidget
->setCurrentIndex(1);
929 void MainWindow::closeButtonClicked(void)
938 void MainWindow::addFilesButtonClicked(void)
944 if(lamexp_themes_enabled())
946 QStringList fileTypeFilters
= DecoderRegistry::getSupportedTypes();
947 QStringList selectedFiles
= QFileDialog::getOpenFileNames(this, tr("Add file(s)"), QString(), fileTypeFilters
.join(";;"));
948 if(!selectedFiles
.isEmpty())
950 addFiles(selectedFiles
);
955 QFileDialog
dialog(this, tr("Add file(s)"));
956 QStringList fileTypeFilters
= DecoderRegistry::getSupportedTypes();
957 dialog
.setFileMode(QFileDialog::ExistingFiles
);
958 dialog
.setNameFilter(fileTypeFilters
.join(";;"));
961 QStringList selectedFiles
= dialog
.selectedFiles();
962 addFiles(selectedFiles
);
971 void MainWindow::openFolderActionActivated(void)
974 QString selectedFolder
;
978 if(lamexp_themes_enabled())
980 selectedFolder
= QFileDialog::getExistingDirectory(this, tr("Add folder"), QDesktopServices::storageLocation(QDesktopServices::MusicLocation
));
984 QFileDialog
dialog(this, tr("Add folder"));
985 dialog
.setFileMode(QFileDialog::DirectoryOnly
);
986 dialog
.setDirectory(QDesktopServices::storageLocation(QDesktopServices::MusicLocation
));
989 selectedFolder
= dialog
.selectedFiles().first();
993 if(!selectedFolder
.isEmpty())
995 QDir
sourceDir(selectedFolder
);
996 QFileInfoList fileInfoList
= sourceDir
.entryInfoList(QDir::Files
);
997 QStringList fileList
;
999 while(!fileInfoList
.isEmpty())
1001 fileList
<< fileInfoList
.takeFirst().canonicalFilePath();
1010 * Remove file button
1012 void MainWindow::removeFileButtonClicked(void)
1014 if(sourceFileView
->currentIndex().isValid())
1016 int iRow
= sourceFileView
->currentIndex().row();
1017 m_fileListModel
->removeFile(sourceFileView
->currentIndex());
1018 sourceFileView
->selectRow(iRow
< m_fileListModel
->rowCount() ? iRow
: m_fileListModel
->rowCount()-1);
1023 * Clear files button
1025 void MainWindow::clearFilesButtonClicked(void)
1027 m_fileListModel
->clearFiles();
1031 * Move file up button
1033 void MainWindow::fileUpButtonClicked(void)
1035 if(sourceFileView
->currentIndex().isValid())
1037 int iRow
= sourceFileView
->currentIndex().row() - 1;
1038 m_fileListModel
->moveFile(sourceFileView
->currentIndex(), -1);
1039 sourceFileView
->selectRow(iRow
>= 0 ? iRow
: 0);
1044 * Move file down button
1046 void MainWindow::fileDownButtonClicked(void)
1048 if(sourceFileView
->currentIndex().isValid())
1050 int iRow
= sourceFileView
->currentIndex().row() + 1;
1051 m_fileListModel
->moveFile(sourceFileView
->currentIndex(), 1);
1052 sourceFileView
->selectRow(iRow
< m_fileListModel
->rowCount() ? iRow
: m_fileListModel
->rowCount()-1);
1057 * Show details button
1059 void MainWindow::showDetailsButtonClicked(void)
1064 MetaInfoDialog
*metaInfoDialog
= new MetaInfoDialog(this);
1065 QModelIndex index
= sourceFileView
->currentIndex();
1067 while(index
.isValid())
1071 index
= m_fileListModel
->index(index
.row() + 1, index
.column());
1072 sourceFileView
->selectRow(index
.row());
1076 index
= m_fileListModel
->index(index
.row() - 1, index
.column());
1077 sourceFileView
->selectRow(index
.row());
1080 AudioFileModel
&file
= (*m_fileListModel
)[index
];
1081 iResult
= metaInfoDialog
->exec(file
, index
.row() > 0, index
.row() < m_fileListModel
->rowCount() - 1);
1086 LAMEXP_DELETE(metaInfoDialog
);
1092 void MainWindow::tabPageChanged(int idx
)
1094 QList
<QAction
*> actions
= m_tabActionGroup
->actions();
1095 for(int i
= 0; i
< actions
.count(); i
++)
1098 int actionIndex
= actions
.at(i
)->data().toInt(&ok
);
1099 if(ok
&& actionIndex
== idx
)
1101 actions
.at(i
)->setChecked(true);
1107 * Tab action triggered
1109 void MainWindow::tabActionActivated(QAction
*action
)
1111 if(action
&& action
->data().isValid())
1114 int index
= action
->data().toInt(&ok
);
1117 tabWidget
->setCurrentIndex(index
);
1123 * Style action triggered
1125 void MainWindow::styleActionActivated(QAction
*action
)
1127 if(action
&& action
->data().isValid())
1130 int actionIndex
= action
->data().toInt(&ok
);
1131 m_settings
->interfaceStyle(actionIndex
);
1134 switch(m_settings
->interfaceStyle())
1137 if(actionStyleCleanlooks
->isEnabled())
1139 actionStyleCleanlooks
->setChecked(true);
1140 QApplication::setStyle(new QCleanlooksStyle());
1144 if(actionStyleWindowsVista
->isEnabled())
1146 actionStyleWindowsVista
->setChecked(true);
1147 QApplication::setStyle(new QWindowsVistaStyle());
1151 if(actionStyleWindowsXP
->isEnabled())
1153 actionStyleWindowsXP
->setChecked(true);
1154 QApplication::setStyle(new QWindowsXPStyle());
1158 if(actionStyleWindowsClassic
->isEnabled())
1160 actionStyleWindowsClassic
->setChecked(true);
1161 QApplication::setStyle(new QWindowsStyle());
1165 actionStylePlastique
->setChecked(true);
1166 QApplication::setStyle(new QPlastiqueStyle());
1172 * Language action triggered
1174 void MainWindow::languageActionActivated(QAction
*action
)
1176 if(action
->data().type() == QVariant::String
)
1178 QString langId
= action
->data().toString();
1180 if(lamexp_install_translator(langId
))
1182 action
->setChecked(true);
1183 m_settings
->currentLanguage(langId
);
1189 * Load language from file action triggered
1191 void MainWindow::languageFromFileActionActivated(bool checked
)
1193 QFileDialog
dialog(this, tr("Load Translation"));
1194 dialog
.setFileMode(QFileDialog::ExistingFile
);
1195 dialog
.setNameFilter(QString("%1 (*.qm)").arg(tr("Translation Files")));
1199 QStringList selectedFiles
= dialog
.selectedFiles();
1200 if(lamexp_install_translator_from_file(selectedFiles
.first()))
1202 QList
<QAction
*> actions
= m_languageActionGroup
->actions();
1203 while(!actions
.isEmpty())
1205 actions
.takeFirst()->setChecked(false);
1210 languageActionActivated(m_languageActionGroup
->actions().first());
1216 * Output folder changed (mouse clicked)
1218 void MainWindow::outputFolderViewClicked(const QModelIndex
&index
)
1220 if(outputFolderView
->currentIndex() != index
)
1222 outputFolderView
->setCurrentIndex(index
);
1224 QString selectedDir
= m_fileSystemModel
->filePath(index
);
1225 if(selectedDir
.length() < 3) selectedDir
.append(QDir::separator());
1226 outputFolderLabel
->setText(QDir::toNativeSeparators(selectedDir
));
1227 m_settings
->outputDir(selectedDir
);
1231 * Output folder changed (mouse moved)
1233 void MainWindow::outputFolderViewMoved(const QModelIndex
&index
)
1235 if(QApplication::mouseButtons() & Qt::LeftButton
)
1237 outputFolderViewClicked(index
);
1242 * Goto desktop button
1244 void MainWindow::gotoDesktopButtonClicked(void)
1246 QString desktopPath
= QDesktopServices::storageLocation(QDesktopServices::DesktopLocation
);
1248 if(!desktopPath
.isEmpty() && QDir(desktopPath
).exists())
1250 outputFolderView
->setCurrentIndex(m_fileSystemModel
->index(desktopPath
));
1251 outputFolderViewClicked(outputFolderView
->currentIndex());
1252 outputFolderView
->setFocus();
1256 buttonGotoDesktop
->setEnabled(false);
1261 * Goto home folder button
1263 void MainWindow::gotoHomeFolderButtonClicked(void)
1265 QString homePath
= QDesktopServices::storageLocation(QDesktopServices::HomeLocation
);
1267 if(!homePath
.isEmpty() && QDir(homePath
).exists())
1269 outputFolderView
->setCurrentIndex(m_fileSystemModel
->index(homePath
));
1270 outputFolderViewClicked(outputFolderView
->currentIndex());
1271 outputFolderView
->setFocus();
1275 buttonGotoHome
->setEnabled(false);
1280 * Goto music folder button
1282 void MainWindow::gotoMusicFolderButtonClicked(void)
1284 QString musicPath
= QDesktopServices::storageLocation(QDesktopServices::MusicLocation
);
1286 if(!musicPath
.isEmpty() && QDir(musicPath
).exists())
1288 outputFolderView
->setCurrentIndex(m_fileSystemModel
->index(musicPath
));
1289 outputFolderViewClicked(outputFolderView
->currentIndex());
1290 outputFolderView
->setFocus();
1294 buttonGotoMusic
->setEnabled(false);
1299 * Make folder button
1301 void MainWindow::makeFolderButtonClicked(void)
1305 QDir
basePath(m_fileSystemModel
->fileInfo(outputFolderView
->currentIndex()).absoluteFilePath());
1306 QString suggestedName
= tr("New Folder");
1308 if(!m_metaData
->fileArtist().isEmpty() && !m_metaData
->fileAlbum().isEmpty())
1310 suggestedName
= QString("%1 - %2").arg(m_metaData
->fileArtist(), m_metaData
->fileAlbum());
1312 else if(!m_metaData
->fileArtist().isEmpty())
1314 suggestedName
= m_metaData
->fileArtist();
1316 else if(!m_metaData
->fileAlbum().isEmpty())
1318 suggestedName
= m_metaData
->fileAlbum();
1322 for(int i
= 0; i
< m_fileListModel
->rowCount(); i
++)
1324 AudioFileModel audioFile
= m_fileListModel
->getFile(m_fileListModel
->index(i
, 0));
1325 if(!audioFile
.fileAlbum().isEmpty() || !audioFile
.fileArtist().isEmpty())
1327 if(!audioFile
.fileArtist().isEmpty() && !audioFile
.fileAlbum().isEmpty())
1329 suggestedName
= QString("%1 - %2").arg(audioFile
.fileArtist(), audioFile
.fileAlbum());
1331 else if(!audioFile
.fileArtist().isEmpty())
1333 suggestedName
= audioFile
.fileArtist();
1335 else if(!audioFile
.fileAlbum().isEmpty())
1337 suggestedName
= audioFile
.fileAlbum();
1346 bool bApplied
= false;
1347 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();
1351 folderName
.remove(":", Qt::CaseInsensitive
);
1352 folderName
.remove("/", Qt::CaseInsensitive
);
1353 folderName
.remove("\\", Qt::CaseInsensitive
);
1354 folderName
.remove("?", Qt::CaseInsensitive
);
1355 folderName
.remove("*", Qt::CaseInsensitive
);
1356 folderName
.remove("<", Qt::CaseInsensitive
);
1357 folderName
.remove(">", Qt::CaseInsensitive
);
1359 folderName
= folderName
.simplified();
1361 if(folderName
.isEmpty())
1363 MessageBeep(MB_ICONERROR
);
1368 QString newFolder
= folderName
;
1370 while(basePath
.exists(newFolder
))
1372 newFolder
= QString(folderName
).append(QString().sprintf(" (%d)", ++i
));
1375 if(basePath
.mkdir(newFolder
))
1377 QDir createdDir
= basePath
;
1378 if(createdDir
.cd(newFolder
))
1380 outputFolderView
->setCurrentIndex(m_fileSystemModel
->index(createdDir
.canonicalPath()));
1381 outputFolderViewClicked(outputFolderView
->currentIndex());
1382 outputFolderView
->setFocus();
1387 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!")));
1395 * Edit meta button clicked
1397 void MainWindow::editMetaButtonClicked(void)
1400 m_metaInfoModel
->editItem(metaDataView
->currentIndex(), this);
1404 * Reset meta button clicked
1406 void MainWindow::clearMetaButtonClicked(void)
1409 m_metaInfoModel
->clearData();
1413 * Visit homepage action
1415 void MainWindow::visitHomepageActionActivated(void)
1417 QDesktopServices::openUrl(QUrl("http://mulder.dummwiedeutsch.de/"));
1421 * Check for updates action
1423 void MainWindow::checkUpdatesActionActivated(void)
1429 UpdateDialog
*updateDialog
= new UpdateDialog(m_settings
, this);
1430 updateDialog
->exec();
1431 if(updateDialog
->getSuccess())
1433 m_settings
->autoUpdateLastCheck(QDate::currentDate().toString(Qt::ISODate
));
1435 LAMEXP_DELETE(updateDialog
);
1440 * Other instance detected
1442 void MainWindow::notifyOtherInstance(void)
1444 if(!m_banner
->isVisible())
1446 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
);
1452 * Add file from another instance
1454 void MainWindow::addFileDelayed(const QString
&filePath
)
1456 m_delayedFileTimer
->stop();
1457 qDebug("Received file: %s", filePath
.toUtf8().constData());
1458 m_delayedFileList
->append(filePath
);
1459 m_delayedFileTimer
->start(5000);
1463 * Add all pending files
1465 void MainWindow::handleDelayedFiles(void)
1467 if(m_banner
->isVisible())
1472 m_delayedFileTimer
->stop();
1473 if(m_delayedFileList
->isEmpty())
1478 QStringList selectedFiles
;
1479 tabWidget
->setCurrentIndex(0);
1481 while(!m_delayedFileList
->isEmpty())
1483 QFileInfo currentFile
= QFileInfo(m_delayedFileList
->takeFirst());
1484 if(!currentFile
.exists())
1488 if(currentFile
.isFile())
1490 selectedFiles
<< currentFile
.canonicalFilePath();
1493 if(currentFile
.isDir())
1495 QList
<QFileInfo
> list
= QDir(currentFile
.canonicalFilePath()).entryInfoList(QDir::Files
);
1496 for(int j
= 0; j
< list
.count(); j
++)
1498 selectedFiles
<< list
.at(j
).canonicalFilePath();
1503 addFiles(selectedFiles
);
1509 void MainWindow::updateEncoder(int id
)
1511 m_settings
->compressionEncoder(id
);
1513 switch(m_settings
->compressionEncoder())
1515 case SettingsModel::VorbisEncoder
:
1516 radioButtonModeQuality
->setEnabled(true);
1517 radioButtonModeAverageBitrate
->setEnabled(true);
1518 radioButtonConstBitrate
->setEnabled(false);
1519 if(radioButtonConstBitrate
->isChecked()) radioButtonModeQuality
->setChecked(true);
1520 sliderBitrate
->setEnabled(true);
1522 case SettingsModel::FLACEncoder
:
1523 radioButtonModeQuality
->setEnabled(false);
1524 radioButtonModeQuality
->setChecked(true);
1525 radioButtonModeAverageBitrate
->setEnabled(false);
1526 radioButtonConstBitrate
->setEnabled(false);
1527 sliderBitrate
->setEnabled(true);
1529 case SettingsModel::PCMEncoder
:
1530 radioButtonModeQuality
->setEnabled(false);
1531 radioButtonModeQuality
->setChecked(true);
1532 radioButtonModeAverageBitrate
->setEnabled(false);
1533 radioButtonConstBitrate
->setEnabled(false);
1534 sliderBitrate
->setEnabled(false);
1537 radioButtonModeQuality
->setEnabled(true);
1538 radioButtonModeAverageBitrate
->setEnabled(true);
1539 radioButtonConstBitrate
->setEnabled(true);
1540 sliderBitrate
->setEnabled(true);
1544 updateRCMode(m_modeButtonGroup
->checkedId());
1548 * Update rate-control mode
1550 void MainWindow::updateRCMode(int id
)
1552 m_settings
->compressionRCMode(id
);
1554 switch(m_settings
->compressionEncoder())
1556 case SettingsModel::MP3Encoder
:
1557 switch(m_settings
->compressionRCMode())
1559 case SettingsModel::VBRMode
:
1560 sliderBitrate
->setMinimum(0);
1561 sliderBitrate
->setMaximum(9);
1564 sliderBitrate
->setMinimum(0);
1565 sliderBitrate
->setMaximum(13);
1569 case SettingsModel::VorbisEncoder
:
1570 switch(m_settings
->compressionRCMode())
1572 case SettingsModel::VBRMode
:
1573 sliderBitrate
->setMinimum(-2);
1574 sliderBitrate
->setMaximum(10);
1577 sliderBitrate
->setMinimum(4);
1578 sliderBitrate
->setMaximum(63);
1582 case SettingsModel::AACEncoder
:
1583 switch(m_settings
->compressionRCMode())
1585 case SettingsModel::VBRMode
:
1586 sliderBitrate
->setMinimum(0);
1587 sliderBitrate
->setMaximum(20);
1590 sliderBitrate
->setMinimum(4);
1591 sliderBitrate
->setMaximum(63);
1595 case SettingsModel::FLACEncoder
:
1596 sliderBitrate
->setMinimum(0);
1597 sliderBitrate
->setMaximum(8);
1599 case SettingsModel::PCMEncoder
:
1600 sliderBitrate
->setMinimum(0);
1601 sliderBitrate
->setMaximum(2);
1602 sliderBitrate
->setValue(1);
1605 sliderBitrate
->setMinimum(0);
1606 sliderBitrate
->setMaximum(0);
1610 updateBitrate(sliderBitrate
->value());
1616 void MainWindow::updateBitrate(int value
)
1618 m_settings
->compressionBitrate(value
);
1620 switch(m_settings
->compressionRCMode())
1622 case SettingsModel::VBRMode
:
1623 switch(m_settings
->compressionEncoder())
1625 case SettingsModel::MP3Encoder
:
1626 labelBitrate
->setText(tr("Quality Level %1").arg(9 - value
));
1628 case SettingsModel::VorbisEncoder
:
1629 labelBitrate
->setText(tr("Quality Level %1").arg(value
));
1631 case SettingsModel::AACEncoder
:
1632 labelBitrate
->setText(tr("Quality Level %1").arg(QString().sprintf("%.2f", static_cast<double>(value
* 5) / 100.0)));
1634 case SettingsModel::FLACEncoder
:
1635 labelBitrate
->setText(tr("Compression %1").arg(value
));
1637 case SettingsModel::PCMEncoder
:
1638 labelBitrate
->setText(tr("Uncompressed"));
1641 labelBitrate
->setText(QString::number(value
));
1645 case SettingsModel::ABRMode
:
1646 switch(m_settings
->compressionEncoder())
1648 case SettingsModel::MP3Encoder
:
1649 labelBitrate
->setText(QString("≈ %1 kbps").arg(SettingsModel::mp3Bitrates
[value
]));
1651 case SettingsModel::FLACEncoder
:
1652 labelBitrate
->setText(tr("Compression %1").arg(value
));
1654 case SettingsModel::PCMEncoder
:
1655 labelBitrate
->setText(tr("Uncompressed"));
1658 labelBitrate
->setText(QString("≈ %1 kbps").arg(min(500, value
* 8)));
1663 switch(m_settings
->compressionEncoder())
1665 case SettingsModel::MP3Encoder
:
1666 labelBitrate
->setText(QString("%1 kbps").arg(SettingsModel::mp3Bitrates
[value
]));
1668 case SettingsModel::FLACEncoder
:
1669 labelBitrate
->setText(tr("Compression %1").arg(value
));
1671 case SettingsModel::PCMEncoder
:
1672 labelBitrate
->setText(tr("Uncompressed"));
1675 labelBitrate
->setText(QString("%1 kbps").arg(min(500, value
* 8)));
1684 * Lame algorithm quality changed
1686 void MainWindow::updateLameAlgoQuality(int value
)
1693 text
= tr("Best Quality (Very Slow)");
1696 text
= tr("High Quality (Recommended)");
1699 text
= tr("Average Quality (Default)");
1702 text
= tr("Low Quality (Fast)");
1705 text
= tr("Poor Quality (Very Fast)");
1711 m_settings
->lameAlgoQuality(value
);
1712 labelLameAlgoQuality
->setText(text
);
1717 * Bitrate management endabled/disabled
1719 void MainWindow::bitrateManagementEnabledChanged(bool checked
)
1721 m_settings
->bitrateManagementEnabled(checked
);
1725 * Minimum bitrate has changed
1727 void MainWindow::bitrateManagementMinChanged(int value
)
1729 if(value
> spinBoxBitrateManagementMax
->value())
1731 spinBoxBitrateManagementMin
->setValue(spinBoxBitrateManagementMax
->value());
1732 m_settings
->bitrateManagementMinRate(spinBoxBitrateManagementMax
->value());
1736 m_settings
->bitrateManagementMinRate(value
);
1741 * Maximum bitrate has changed
1743 void MainWindow::bitrateManagementMaxChanged(int value
)
1745 if(value
< spinBoxBitrateManagementMin
->value())
1747 spinBoxBitrateManagementMax
->setValue(spinBoxBitrateManagementMin
->value());
1748 m_settings
->bitrateManagementMaxRate(spinBoxBitrateManagementMin
->value());
1752 m_settings
->bitrateManagementMaxRate(value
);
1757 * Channel mode has changed
1759 void MainWindow::channelModeChanged(int value
)
1761 if(value
>= 0) m_settings
->lameChannelMode(value
);
1765 * Sampling rate has changed
1767 void MainWindow::samplingRateChanged(int value
)
1769 if(value
>= 0) m_settings
->samplingRate(value
);
1773 * Nero AAC 2-Pass mode changed
1775 void MainWindow::neroAAC2PassChanged(bool checked
)
1777 m_settings
->neroAACEnable2Pass(checked
);
1781 * Nero AAC profile mode changed
1783 void MainWindow::neroAACProfileChanged(int value
)
1785 if(value
>= 0) m_settings
->neroAACProfile(value
);
1789 * Normalization filter enabled changed
1791 void MainWindow::normalizationEnabledChanged(bool checked
)
1793 m_settings
->normalizationFilterEnabled(checked
);
1797 * Normalization max. volume changed
1799 void MainWindow::normalizationMaxVolumeChanged(double value
)
1801 m_settings
->normalizationFilterMaxVolume(static_cast<int>(value
* 100.0));
1805 * Tone adjustment has changed (Bass)
1807 void MainWindow::toneAdjustBassChanged(double value
)
1809 m_settings
->toneAdjustBass(static_cast<int>(value
* 100.0));
1810 spinBoxToneAdjustBass
->setPrefix((value
> 0) ? "+" : QString());
1814 * Tone adjustment has changed (Treble)
1816 void MainWindow::toneAdjustTrebleChanged(double value
)
1818 m_settings
->toneAdjustTreble(static_cast<int>(value
* 100.0));
1819 spinBoxToneAdjustTreble
->setPrefix((value
> 0) ? "+" : QString());
1823 * Tone adjustment has been reset
1825 void MainWindow::toneAdjustTrebleReset()
1827 spinBoxToneAdjustBass
->setValue(m_settings
->toneAdjustBassDefault());
1828 spinBoxToneAdjustTreble
->setValue(m_settings
->toneAdjustTrebleDefault());
1829 toneAdjustBassChanged(spinBoxToneAdjustBass
->value());
1830 toneAdjustTrebleChanged(spinBoxToneAdjustTreble
->value());
1834 * Reset all advanced options to their defaults
1836 void MainWindow::resetAdvancedOptionsButtonClicked()
1838 sliderLameAlgoQuality
->setValue(m_settings
->lameAlgoQualityDefault());
1839 spinBoxBitrateManagementMin
->setValue(m_settings
->bitrateManagementMinRateDefault());
1840 spinBoxBitrateManagementMax
->setValue(m_settings
->bitrateManagementMaxRateDefault());
1841 spinBoxNormalizationFilter
->setValue(static_cast<double>(m_settings
->normalizationFilterMaxVolumeDefault()) / 100.0);
1842 spinBoxToneAdjustBass
->setValue(static_cast<double>(m_settings
->toneAdjustBassDefault()) / 100.0);
1843 spinBoxToneAdjustTreble
->setValue(static_cast<double>(m_settings
->toneAdjustTrebleDefault()) / 100.0);
1844 comboBoxMP3ChannelMode
->setCurrentIndex(m_settings
->lameChannelModeDefault());
1845 comboBoxSamplingRate
->setCurrentIndex(m_settings
->samplingRateDefault());
1846 comboBoxNeroAACProfile
->setCurrentIndex(m_settings
->neroAACProfileDefault());
1847 while(checkBoxBitrateManagement
->isChecked() != m_settings
->bitrateManagementEnabledDefault()) checkBoxBitrateManagement
->click();
1848 while(checkBoxNeroAAC2PassMode
->isChecked() != m_settings
->neroAACEnable2PassDefault()) checkBoxNeroAAC2PassMode
->click();
1849 while(checkBoxNormalizationFilter
->isChecked() != m_settings
->normalizationFilterEnabledDefault()) checkBoxNormalizationFilter
->click();
1850 scrollArea
->verticalScrollBar()->setValue(0);
1856 void MainWindow::sourceModelChanged(void)
1858 m_dropNoteLabel
->setVisible(m_fileListModel
->rowCount() <= 0);
1862 * Meta tags enabled changed
1864 void MainWindow::metaTagsEnabledChanged(void)
1866 m_settings
->writeMetaTags(writeMetaDataCheckBox
->isChecked());
1870 * Playlist enabled changed
1872 void MainWindow::playlistEnabledChanged(void)
1874 m_settings
->createPlaylist(generatePlaylistCheckBox
->isChecked());
1878 * Output to source dir changed
1880 void MainWindow::saveToSourceFolderChanged(void)
1882 m_settings
->outputToSourceDir(saveToSourceFolderCheckBox
->isChecked());
1886 * Prepend relative source file path to output file name changed
1888 void MainWindow::prependRelativePathChanged(void)
1890 m_settings
->prependRelativeSourcePath(prependRelativePathCheckBox
->isChecked());
1895 * Restore the override cursor
1897 void MainWindow::restoreCursor(void)
1899 QApplication::restoreOverrideCursor();
1903 * Show context menu for source files
1905 void MainWindow::sourceFilesContextMenu(const QPoint
&pos
)
1907 if(pos
.x() <= sourceFileView
->width() && pos
.y() <= sourceFileView
->height() && pos
.x() >= 0 && pos
.y() >= 0)
1909 m_sourceFilesContextMenu
->popup(sourceFileView
->mapToGlobal(pos
));
1914 * Open selected file in external player
1916 void MainWindow::previewContextActionTriggered(void)
1918 const static char *appNames
[3] = {"smplayer_portable.exe", "smplayer.exe", "mplayer.exe"};
1919 const static wchar_t *registryKey
= L
"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{DB9E4EAB-2717-499F-8D56-4CC8A644AB60}";
1921 QModelIndex index
= sourceFileView
->currentIndex();
1922 if(!index
.isValid())
1927 QString mplayerPath
;
1928 HKEY registryKeyHandle
;
1930 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE
, registryKey
, 0, KEY_READ
, ®istryKeyHandle
) == ERROR_SUCCESS
)
1932 wchar_t Buffer
[4096];
1933 DWORD BuffSize
= sizeof(wchar_t*) * 4096;
1934 if(RegQueryValueExW(registryKeyHandle
, L
"InstallLocation", 0, 0, reinterpret_cast<BYTE
*>(Buffer
), &BuffSize
) == ERROR_SUCCESS
)
1936 mplayerPath
= QString::fromUtf16(reinterpret_cast<const unsigned short*>(Buffer
));
1940 if(!mplayerPath
.isEmpty())
1942 QDir
mplayerDir(mplayerPath
);
1943 if(mplayerDir
.exists())
1945 for(int i
= 0; i
< 3; i
++)
1947 if(mplayerDir
.exists(appNames
[i
]))
1949 QProcess::startDetached(mplayerDir
.absoluteFilePath(appNames
[i
]), QStringList() << QDir::toNativeSeparators(m_fileListModel
->getFile(index
).filePath()));
1956 QDesktopServices::openUrl(QString("file:///").append(m_fileListModel
->getFile(index
).filePath()));
1960 * Find selected file in explorer
1962 void MainWindow::findFileContextActionTriggered(void)
1964 QModelIndex index
= sourceFileView
->currentIndex();
1967 QString systemRootPath
;
1969 QDir
systemRoot(lamexp_known_folder(lamexp_folder_systemfolder
));
1970 if(systemRoot
.exists() && systemRoot
.cdUp())
1972 systemRootPath
= systemRoot
.canonicalPath();
1975 if(!systemRootPath
.isEmpty())
1977 QFileInfo
explorer(QString("%1/explorer.exe").arg(systemRootPath
));
1978 if(explorer
.exists() && explorer
.isFile())
1980 QProcess::execute(explorer
.canonicalFilePath(), QStringList() << "/select," << QDir::toNativeSeparators(m_fileListModel
->getFile(index
).filePath()));
1986 qWarning("SystemRoot directory could not be detected!");
1992 * Show context menu for output folder
1994 void MainWindow::outputFolderContextMenu(const QPoint
&pos
)
1997 if(pos
.x() <= outputFolderView
->width() && pos
.y() <= outputFolderView
->height() && pos
.x() >= 0 && pos
.y() >= 0)
1999 m_outputFolderContextMenu
->popup(outputFolderView
->mapToGlobal(pos
));
2004 * Show selected folder in explorer
2006 void MainWindow::showFolderContextActionTriggered(void)
2008 QDesktopServices::openUrl(QUrl::fromLocalFile(m_fileSystemModel
->filePath(outputFolderView
->currentIndex())));
2012 * Disable update reminder action
2014 void MainWindow::disableUpdateReminderActionTriggered(bool checked
)
2018 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))
2020 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!")));
2021 m_settings
->autoUpdateEnabled(false);
2025 m_settings
->autoUpdateEnabled(true);
2030 QMessageBox::information(this, tr("Update Reminder"), tr("The update reminder has been re-enabled."));
2031 m_settings
->autoUpdateEnabled(true);
2034 actionDisableUpdateReminder
->setChecked(!m_settings
->autoUpdateEnabled());
2038 * Disable sound effects action
2040 void MainWindow::disableSoundsActionTriggered(bool checked
)
2044 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))
2046 QMessageBox::information(this, tr("Sound Effects"), tr("All sound effects have been disabled."));
2047 m_settings
->soundsEnabled(false);
2051 m_settings
->soundsEnabled(true);
2056 QMessageBox::information(this, tr("Sound Effects"), tr("The sound effects have been re-enabled."));
2057 m_settings
->soundsEnabled(true);
2060 actionDisableSounds
->setChecked(!m_settings
->soundsEnabled());
2064 * Disable Nero AAC encoder action
2066 void MainWindow::disableNeroAacNotificationsActionTriggered(bool checked
)
2070 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))
2072 QMessageBox::information(this, tr("Nero AAC Notifications"), tr("All Nero AAC Encoder notifications have been disabled."));
2073 m_settings
->neroAacNotificationsEnabled(false);
2077 m_settings
->neroAacNotificationsEnabled(true);
2082 QMessageBox::information(this, tr("Nero AAC Notifications"), tr("The Nero AAC Encoder notifications have been re-enabled."));
2083 m_settings
->neroAacNotificationsEnabled(true);
2086 actionDisableNeroAacNotifications
->setChecked(!m_settings
->neroAacNotificationsEnabled());
2090 * Disable WMA Decoder component action
2092 void MainWindow::disableWmaDecoderNotificationsActionTriggered(bool checked
)
2096 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))
2098 QMessageBox::information(this, tr("WMA Decoder Notifications"), tr("All WMA Decoder notifications have been disabled."));
2099 m_settings
->wmaDecoderNotificationsEnabled(false);
2103 m_settings
->wmaDecoderNotificationsEnabled(true);
2108 QMessageBox::information(this, tr("WMA Decoder Notifications"), tr("The WMA Decoder notifications have been re-enabled."));
2109 m_settings
->wmaDecoderNotificationsEnabled(true);
2112 actionDisableWmaDecoderNotifications
->setChecked(!m_settings
->wmaDecoderNotificationsEnabled());
2116 * Download and install WMA Decoder component
2118 void MainWindow::installWMADecoderActionTriggered(bool checked
)
2120 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)
2122 installWMADecoder();
2127 * Show the "drop box" widget
2129 void MainWindow::showDropBoxWidgetActionTriggered(bool checked
)
2131 m_settings
->dropBoxWidgetEnabled(true);
2133 if(!m_dropBox
->isVisible())
2138 FLASH_WINDOW(m_dropBox
);
2142 * Disable shell integration action
2144 void MainWindow::disableShellIntegrationActionTriggered(bool checked
)
2148 if(0 == QMessageBox::question(this, tr("Shell Integration"), tr("Do you really want to disable the LameXP shell integration?"), tr("Yes"), tr("No"), QString(), 1))
2150 ShellIntegration::remove();
2151 QMessageBox::information(this, tr("Shell Integration"), tr("The LameXP shell integration has been disabled."));
2152 m_settings
->shellIntegrationEnabled(false);
2156 m_settings
->shellIntegrationEnabled(true);
2161 ShellIntegration::install();
2162 QMessageBox::information(this, tr("Shell Integration"), tr("The LameXP shell integration has been re-enabled."));
2163 m_settings
->shellIntegrationEnabled(true);
2166 actionDisableShellIntegration
->setChecked(!m_settings
->shellIntegrationEnabled());
2168 if(lamexp_portable_mode() && actionDisableShellIntegration
->isChecked())
2170 actionDisableShellIntegration
->setEnabled(false);