1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2012 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 "Dialog_CueImport.h"
33 #include "Dialog_LogView.h"
34 #include "Thread_FileAnalyzer.h"
35 #include "Thread_FileAnalyzer_ST.h"
36 #include "Thread_MessageHandler.h"
37 #include "Model_MetaInfo.h"
38 #include "Model_Settings.h"
39 #include "Model_FileList.h"
40 #include "Model_FileSystem.h"
41 #include "WinSevenTaskbar.h"
42 #include "Registry_Decoder.h"
43 #include "ShellIntegration.h"
44 #include "CustomEventFilter.h"
47 #include <QMessageBox>
49 #include <QDesktopWidget>
51 #include <QFileDialog>
52 #include <QInputDialog>
53 #include <QFileSystemModel>
54 #include <QDesktopServices>
56 #include <QPlastiqueStyle>
57 #include <QCleanlooksStyle>
58 #include <QWindowsVistaStyle>
59 #include <QWindowsStyle>
61 #include <QDragEnterEvent>
65 #include <QProcessEnvironment>
66 #include <QCryptographicHash>
67 #include <QTranslator>
75 ////////////////////////////////////////////////////////////
77 ////////////////////////////////////////////////////////////
79 #define ABORT_IF_BUSY do \
81 if(m_banner->isVisible() || m_delayedFileTimer->isActive()) \
83 MessageBeep(MB_ICONEXCLAMATION); \
89 #define SET_TEXT_COLOR(WIDGET, COLOR) do \
91 QPalette _palette = WIDGET->palette(); \
92 _palette.setColor(QPalette::WindowText, (COLOR)); \
93 _palette.setColor(QPalette::Text, (COLOR)); \
94 WIDGET->setPalette(_palette); \
98 #define SET_FONT_BOLD(WIDGET,BOLD) do \
100 QFont _font = WIDGET->font(); \
101 _font.setBold(BOLD); \
102 WIDGET->setFont(_font); \
106 #define TEMP_HIDE_DROPBOX(CMD) do \
108 bool _dropBoxVisible = m_dropBox->isVisible(); \
109 if(_dropBoxVisible) m_dropBox->hide(); \
110 do { CMD } while(0); \
111 if(_dropBoxVisible) m_dropBox->show(); \
115 #define SET_MODEL(VIEW, MODEL) do \
117 QItemSelectionModel *_tmp = (VIEW)->selectionModel(); \
118 (VIEW)->setModel(MODEL); \
119 LAMEXP_DELETE(_tmp); \
123 #define SET_CHECKBOX_STATE(CHCKBX, STATE) do \
125 if((CHCKBX)->isChecked() != (STATE)) \
129 if((CHCKBX)->isChecked() != (STATE)) \
131 qWarning("Warning: Failed to set checkbox " #CHCKBX " state!"); \
136 #define TRIM_STRING_RIGHT(STR) do \
138 while((STR.length() > 0) && STR[STR.length()-1].isSpace()) STR.chop(1); \
142 #define LINK(URL) QString("<a href=\"%1\">%2</a>").arg(URL).arg(QString(URL).replace("-", "−"))
143 #define FSLINK(PATH) QString("<a href=\"file:///%1\">%2</a>").arg(PATH).arg(QString(PATH).replace("-", "−"))
144 #define USE_NATIVE_FILE_DIALOG (lamexp_themes_enabled() || ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) < QSysInfo::WV_XP))
145 #define CENTER_CURRENT_OUTPUT_FOLDER_DELAYED QTimer::singleShot(125, this, SLOT(centerOutputFolderModel()))
147 static const DWORD IDM_ABOUTBOX = 0xEFF0;
149 ////////////////////////////////////////////////////////////
151 ////////////////////////////////////////////////////////////
153 MainWindow::MainWindow(FileListModel *fileListModel, AudioFileModel *metaInfo, SettingsModel *settingsModel, QWidget *parent)
156 m_fileListModel(fileListModel),
157 m_metaData(metaInfo),
158 m_settings(settingsModel),
159 m_fileSystemModel(NULL),
160 m_neroEncoderAvailable(lamexp_check_tool("neroAacEnc.exe") && lamexp_check_tool("neroAacDec.exe") && lamexp_check_tool("neroAacTag.exe")),
161 m_fhgEncoderAvailable(lamexp_check_tool("fhgaacenc.exe") && lamexp_check_tool("enc_fhgaac.dll") && lamexp_check_tool("nsutil.dll") && lamexp_check_tool("libmp4v2.dll")),
162 m_qaacEncoderAvailable(lamexp_check_tool("qaac.exe") && lamexp_check_tool("libsoxrate.dll")),
164 m_firstTimeShown(true),
165 m_outputFolderViewCentering(false),
166 m_outputFolderViewInitCounter(0)
168 //Init the dialog, from the .ui file
170 setWindowFlags(windowFlags() ^ Qt::WindowMaximizeButtonHint);
172 //Register meta types
173 qRegisterMetaType<AudioFileModel>("AudioFileModel");
175 //Enabled main buttons
176 connect(buttonAbout, SIGNAL(clicked()), this, SLOT(aboutButtonClicked()));
177 connect(buttonStart, SIGNAL(clicked()), this, SLOT(encodeButtonClicked()));
178 connect(buttonQuit, SIGNAL(clicked()), this, SLOT(closeButtonClicked()));
181 tabWidget->setCurrentIndex(0);
182 connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabPageChanged(int)));
185 if(HMENU hMenu = ::GetSystemMenu(winId(), FALSE))
187 AppendMenuW(hMenu, MF_SEPARATOR, 0, 0);
188 AppendMenuW(hMenu, MF_STRING, IDM_ABOUTBOX, L"About...");
191 //--------------------------------
192 // Setup "Source" tab
193 //--------------------------------
195 sourceFileView->setModel(m_fileListModel);
196 sourceFileView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
197 sourceFileView->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
198 sourceFileView->setContextMenuPolicy(Qt::CustomContextMenu);
199 sourceFileView->viewport()->installEventFilter(this);
200 m_dropNoteLabel = new QLabel(sourceFileView);
201 m_dropNoteLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
202 SET_FONT_BOLD(m_dropNoteLabel, true);
203 SET_TEXT_COLOR(m_dropNoteLabel, Qt::darkGray);
204 m_sourceFilesContextMenu = new QMenu();
205 m_showDetailsContextAction = m_sourceFilesContextMenu->addAction(QIcon(":/icons/zoom.png"), "N/A");
206 m_previewContextAction = m_sourceFilesContextMenu->addAction(QIcon(":/icons/sound.png"), "N/A");
207 m_findFileContextAction = m_sourceFilesContextMenu->addAction(QIcon(":/icons/folder_go.png"), "N/A");
208 m_sourceFilesContextMenu->addSeparator();
209 m_exportCsvContextAction = m_sourceFilesContextMenu->addAction(QIcon(":/icons/table_save.png"), "N/A");
210 m_importCsvContextAction = m_sourceFilesContextMenu->addAction(QIcon(":/icons/folder_table.png"), "N/A");
211 SET_FONT_BOLD(m_showDetailsContextAction, true);
212 connect(buttonAddFiles, SIGNAL(clicked()), this, SLOT(addFilesButtonClicked()));
213 connect(buttonRemoveFile, SIGNAL(clicked()), this, SLOT(removeFileButtonClicked()));
214 connect(buttonClearFiles, SIGNAL(clicked()), this, SLOT(clearFilesButtonClicked()));
215 connect(buttonFileUp, SIGNAL(clicked()), this, SLOT(fileUpButtonClicked()));
216 connect(buttonFileDown, SIGNAL(clicked()), this, SLOT(fileDownButtonClicked()));
217 connect(buttonShowDetails, SIGNAL(clicked()), this, SLOT(showDetailsButtonClicked()));
218 connect(m_fileListModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(sourceModelChanged()));
219 connect(m_fileListModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(sourceModelChanged()));
220 connect(m_fileListModel, SIGNAL(modelReset()), this, SLOT(sourceModelChanged()));
221 connect(sourceFileView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(sourceFilesContextMenu(QPoint)));
222 connect(sourceFileView->verticalScrollBar(), SIGNAL(sliderMoved(int)), this, SLOT(sourceFilesScrollbarMoved(int)));
223 connect(sourceFileView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(sourceFilesScrollbarMoved(int)));
224 connect(m_showDetailsContextAction, SIGNAL(triggered(bool)), this, SLOT(showDetailsButtonClicked()));
225 connect(m_previewContextAction, SIGNAL(triggered(bool)), this, SLOT(previewContextActionTriggered()));
226 connect(m_findFileContextAction, SIGNAL(triggered(bool)), this, SLOT(findFileContextActionTriggered()));
227 connect(m_exportCsvContextAction, SIGNAL(triggered(bool)), this, SLOT(exportCsvContextActionTriggered()));
228 connect(m_importCsvContextAction, SIGNAL(triggered(bool)), this, SLOT(importCsvContextActionTriggered()));
230 //--------------------------------
231 // Setup "Output" tab
232 //--------------------------------
234 outputFolderView->setHeaderHidden(true);
235 outputFolderView->setAnimated(false);
236 outputFolderView->setMouseTracking(false);
237 outputFolderView->setContextMenuPolicy(Qt::CustomContextMenu);
238 outputFolderView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
240 m_evenFilterOutputFolderMouse = new CustomEventFilter;
241 outputFoldersEditorLabel->installEventFilter(m_evenFilterOutputFolderMouse);
242 outputFoldersFovoritesLabel->installEventFilter(m_evenFilterOutputFolderMouse);
243 outputFolderLabel->installEventFilter(m_evenFilterOutputFolderMouse);
245 m_evenFilterOutputFolderView = new CustomEventFilter;
246 outputFolderView->installEventFilter(m_evenFilterOutputFolderView);
248 SET_CHECKBOX_STATE(saveToSourceFolderCheckBox, m_settings->outputToSourceDir());
249 prependRelativePathCheckBox->setChecked(m_settings->prependRelativeSourcePath());
251 connect(outputFolderView, SIGNAL(clicked(QModelIndex)), this, SLOT(outputFolderViewClicked(QModelIndex)));
252 connect(outputFolderView, SIGNAL(activated(QModelIndex)), this, SLOT(outputFolderViewClicked(QModelIndex)));
253 connect(outputFolderView, SIGNAL(pressed(QModelIndex)), this, SLOT(outputFolderViewClicked(QModelIndex)));
254 connect(outputFolderView, SIGNAL(entered(QModelIndex)), this, SLOT(outputFolderViewMoved(QModelIndex)));
255 connect(outputFolderView, SIGNAL(expanded(QModelIndex)), this, SLOT(outputFolderItemExpanded(QModelIndex)));
256 connect(buttonMakeFolder, SIGNAL(clicked()), this, SLOT(makeFolderButtonClicked()));
257 connect(buttonGotoHome, SIGNAL(clicked()), SLOT(gotoHomeFolderButtonClicked()));
258 connect(buttonGotoDesktop, SIGNAL(clicked()), this, SLOT(gotoDesktopButtonClicked()));
259 connect(buttonGotoMusic, SIGNAL(clicked()), this, SLOT(gotoMusicFolderButtonClicked()));
260 connect(saveToSourceFolderCheckBox, SIGNAL(clicked()), this, SLOT(saveToSourceFolderChanged()));
261 connect(prependRelativePathCheckBox, SIGNAL(clicked()), this, SLOT(prependRelativePathChanged()));
262 connect(outputFolderEdit, SIGNAL(editingFinished()), this, SLOT(outputFolderEditFinished()));
263 connect(m_evenFilterOutputFolderMouse, SIGNAL(eventOccurred(QWidget*, QEvent*)), this, SLOT(outputFolderMouseEventOccurred(QWidget*, QEvent*)));
264 connect(m_evenFilterOutputFolderView, SIGNAL(eventOccurred(QWidget*, QEvent*)), this, SLOT(outputFolderViewEventOccurred(QWidget*, QEvent*)));
266 if(m_outputFolderContextMenu = new QMenu())
268 m_showFolderContextAction = m_outputFolderContextMenu->addAction(QIcon(":/icons/zoom.png"), "N/A");
269 m_refreshFolderContextAction = m_outputFolderContextMenu->addAction(QIcon(":/icons/arrow_refresh.png"), "N/A");
270 m_outputFolderContextMenu->setDefaultAction(m_showFolderContextAction);
271 connect(outputFolderView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(outputFolderContextMenu(QPoint)));
272 connect(m_showFolderContextAction, SIGNAL(triggered(bool)), this, SLOT(showFolderContextActionTriggered()));
273 connect(m_refreshFolderContextAction, SIGNAL(triggered(bool)), this, SLOT(refreshFolderContextActionTriggered()));
276 if(m_outputFolderFavoritesMenu = new QMenu())
278 m_addFavoriteFolderAction = m_outputFolderFavoritesMenu->addAction(QIcon(":/icons/add.png"), "N/A");
279 m_outputFolderFavoritesMenu->insertSeparator(m_addFavoriteFolderAction);
280 connect(m_addFavoriteFolderAction, SIGNAL(triggered(bool)), this, SLOT(addFavoriteFolderActionTriggered()));
283 outputFolderEdit->setVisible(false);
284 if(m_outputFolderNoteBox = new QLabel(outputFolderView))
286 m_outputFolderNoteBox->setAutoFillBackground(true);
287 m_outputFolderNoteBox->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
288 m_outputFolderNoteBox->setFrameShape(QFrame::StyledPanel);
289 SET_FONT_BOLD(m_outputFolderNoteBox, true);
290 m_outputFolderNoteBox->hide();
294 outputFolderViewClicked(QModelIndex());
297 //--------------------------------
298 // Setup "Meta Data" tab
299 //--------------------------------
301 m_metaInfoModel = new MetaInfoModel(m_metaData, 6);
302 m_metaInfoModel->clearData();
303 m_metaInfoModel->setData(m_metaInfoModel->index(4, 1), m_settings->metaInfoPosition());
304 metaDataView->setModel(m_metaInfoModel);
305 metaDataView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
306 metaDataView->verticalHeader()->hide();
307 metaDataView->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
308 SET_CHECKBOX_STATE(writeMetaDataCheckBox, m_settings->writeMetaTags());
309 generatePlaylistCheckBox->setChecked(m_settings->createPlaylist());
310 connect(buttonEditMeta, SIGNAL(clicked()), this, SLOT(editMetaButtonClicked()));
311 connect(buttonClearMeta, SIGNAL(clicked()), this, SLOT(clearMetaButtonClicked()));
312 connect(writeMetaDataCheckBox, SIGNAL(clicked()), this, SLOT(metaTagsEnabledChanged()));
313 connect(generatePlaylistCheckBox, SIGNAL(clicked()), this, SLOT(playlistEnabledChanged()));
315 //--------------------------------
316 //Setup "Compression" tab
317 //--------------------------------
319 m_encoderButtonGroup = new QButtonGroup(this);
320 m_encoderButtonGroup->addButton(radioButtonEncoderMP3, SettingsModel::MP3Encoder);
321 m_encoderButtonGroup->addButton(radioButtonEncoderVorbis, SettingsModel::VorbisEncoder);
322 m_encoderButtonGroup->addButton(radioButtonEncoderAAC, SettingsModel::AACEncoder);
323 m_encoderButtonGroup->addButton(radioButtonEncoderAC3, SettingsModel::AC3Encoder);
324 m_encoderButtonGroup->addButton(radioButtonEncoderFLAC, SettingsModel::FLACEncoder);
325 m_encoderButtonGroup->addButton(radioButtonEncoderOpus, SettingsModel::OpusEncoder);
326 m_encoderButtonGroup->addButton(radioButtonEncoderDCA, SettingsModel::DCAEncoder);
327 m_encoderButtonGroup->addButton(radioButtonEncoderPCM, SettingsModel::PCMEncoder);
329 m_modeButtonGroup = new QButtonGroup(this);
330 m_modeButtonGroup->addButton(radioButtonModeQuality, SettingsModel::VBRMode);
331 m_modeButtonGroup->addButton(radioButtonModeAverageBitrate, SettingsModel::ABRMode);
332 m_modeButtonGroup->addButton(radioButtonConstBitrate, SettingsModel::CBRMode);
334 radioButtonEncoderAAC->setEnabled(m_neroEncoderAvailable || m_fhgEncoderAvailable || m_qaacEncoderAvailable);
335 radioButtonEncoderMP3->setChecked(m_settings->compressionEncoder() == SettingsModel::MP3Encoder);
336 radioButtonEncoderVorbis->setChecked(m_settings->compressionEncoder() == SettingsModel::VorbisEncoder);
337 radioButtonEncoderAAC->setChecked((m_settings->compressionEncoder() == SettingsModel::AACEncoder) && (m_neroEncoderAvailable || m_fhgEncoderAvailable || m_qaacEncoderAvailable));
338 radioButtonEncoderAC3->setChecked(m_settings->compressionEncoder() == SettingsModel::AC3Encoder);
339 radioButtonEncoderFLAC->setChecked(m_settings->compressionEncoder() == SettingsModel::FLACEncoder);
340 radioButtonEncoderOpus->setChecked(m_settings->compressionEncoder() == SettingsModel::OpusEncoder);
341 radioButtonEncoderDCA->setChecked(m_settings->compressionEncoder() == SettingsModel::DCAEncoder);
342 radioButtonEncoderPCM->setChecked(m_settings->compressionEncoder() == SettingsModel::PCMEncoder);
343 radioButtonModeQuality->setChecked(m_settings->compressionRCMode() == SettingsModel::VBRMode);
344 radioButtonModeAverageBitrate->setChecked(m_settings->compressionRCMode() == SettingsModel::ABRMode);
345 radioButtonConstBitrate->setChecked(m_settings->compressionRCMode() == SettingsModel::CBRMode);
346 sliderBitrate->setValue(m_settings->compressionBitrate());
348 m_evenFilterCompressionTab = new CustomEventFilter();
349 labelCompressionHelp->installEventFilter(m_evenFilterCompressionTab);
351 connect(m_encoderButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(updateEncoder(int)));
352 connect(m_modeButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(updateRCMode(int)));
353 connect(m_evenFilterCompressionTab, SIGNAL(eventOccurred(QWidget*, QEvent*)), this, SLOT(compressionTabEventOccurred(QWidget*, QEvent*)));
354 connect(sliderBitrate, SIGNAL(valueChanged(int)), this, SLOT(updateBitrate(int)));
356 updateEncoder(m_encoderButtonGroup->checkedId());
358 //--------------------------------
359 //Setup "Advanced Options" tab
360 //--------------------------------
362 sliderLameAlgoQuality->setValue(m_settings->lameAlgoQuality());
363 if(m_settings->maximumInstances() > 0) sliderMaxInstances->setValue(m_settings->maximumInstances());
365 spinBoxBitrateManagementMin->setValue(m_settings->bitrateManagementMinRate());
366 spinBoxBitrateManagementMax->setValue(m_settings->bitrateManagementMaxRate());
367 spinBoxNormalizationFilter->setValue(static_cast<double>(m_settings->normalizationFilterMaxVolume()) / 100.0);
368 spinBoxToneAdjustBass->setValue(static_cast<double>(m_settings->toneAdjustBass()) / 100.0);
369 spinBoxToneAdjustTreble->setValue(static_cast<double>(m_settings->toneAdjustTreble()) / 100.0);
370 spinBoxAftenSearchSize->setValue(m_settings->aftenExponentSearchSize());
371 spinBoxOpusComplexity->setValue(m_settings->opusComplexity());
373 comboBoxMP3ChannelMode->setCurrentIndex(m_settings->lameChannelMode());
374 comboBoxSamplingRate->setCurrentIndex(m_settings->samplingRate());
375 comboBoxAACProfile->setCurrentIndex(m_settings->aacEncProfile());
376 comboBoxAftenCodingMode->setCurrentIndex(m_settings->aftenAudioCodingMode());
377 comboBoxAftenDRCMode->setCurrentIndex(m_settings->aftenDynamicRangeCompression());
378 comboBoxNormalizationMode->setCurrentIndex(m_settings->normalizationFilterEqualizationMode());
379 comboBoxOpusOptimize->setCurrentIndex(m_settings->opusOptimizeFor());
380 comboBoxOpusFramesize->setCurrentIndex(m_settings->opusFramesize());
382 SET_CHECKBOX_STATE(checkBoxBitrateManagement, m_settings->bitrateManagementEnabled());
383 SET_CHECKBOX_STATE(checkBoxNeroAAC2PassMode, m_settings->neroAACEnable2Pass());
384 SET_CHECKBOX_STATE(checkBoxAftenFastAllocation, m_settings->aftenFastBitAllocation());
385 SET_CHECKBOX_STATE(checkBoxNormalizationFilter, m_settings->normalizationFilterEnabled());
386 SET_CHECKBOX_STATE(checkBoxAutoDetectInstances, (m_settings->maximumInstances() < 1));
387 SET_CHECKBOX_STATE(checkBoxUseSystemTempFolder, !m_settings->customTempPathEnabled());
388 SET_CHECKBOX_STATE(checkBoxRenameOutput, m_settings->renameOutputFilesEnabled());
389 SET_CHECKBOX_STATE(checkBoxForceStereoDownmix, m_settings->forceStereoDownmix());
390 SET_CHECKBOX_STATE(checkBoxOpusExpAnalysis, m_settings->opusExpAnalysis());
391 checkBoxNeroAAC2PassMode->setEnabled(!(m_fhgEncoderAvailable || m_qaacEncoderAvailable));
393 lineEditCustomParamLAME->setText(m_settings->customParametersLAME());
394 lineEditCustomParamOggEnc->setText(m_settings->customParametersOggEnc());
395 lineEditCustomParamNeroAAC->setText(m_settings->customParametersAacEnc());
396 lineEditCustomParamFLAC->setText(m_settings->customParametersFLAC());
397 lineEditCustomParamAften->setText(m_settings->customParametersAften());
398 lineEditCustomParamOpus->setText(m_settings->customParametersOpus());
399 lineEditCustomTempFolder->setText(QDir::toNativeSeparators(m_settings->customTempPath()));
400 lineEditRenamePattern->setText(m_settings->renameOutputFilesPattern());
402 m_evenFilterCustumParamsHelp = new CustomEventFilter();
403 helpCustomParamLAME->installEventFilter(m_evenFilterCustumParamsHelp);
404 helpCustomParamOggEnc->installEventFilter(m_evenFilterCustumParamsHelp);
405 helpCustomParamNeroAAC->installEventFilter(m_evenFilterCustumParamsHelp);
406 helpCustomParamFLAC->installEventFilter(m_evenFilterCustumParamsHelp);
407 helpCustomParamAften->installEventFilter(m_evenFilterCustumParamsHelp);
408 helpCustomParamOpus->installEventFilter(m_evenFilterCustumParamsHelp);
410 connect(sliderLameAlgoQuality, SIGNAL(valueChanged(int)), this, SLOT(updateLameAlgoQuality(int)));
411 connect(checkBoxBitrateManagement, SIGNAL(clicked(bool)), this, SLOT(bitrateManagementEnabledChanged(bool)));
412 connect(spinBoxBitrateManagementMin, SIGNAL(valueChanged(int)), this, SLOT(bitrateManagementMinChanged(int)));
413 connect(spinBoxBitrateManagementMax, SIGNAL(valueChanged(int)), this, SLOT(bitrateManagementMaxChanged(int)));
414 connect(comboBoxMP3ChannelMode, SIGNAL(currentIndexChanged(int)), this, SLOT(channelModeChanged(int)));
415 connect(comboBoxSamplingRate, SIGNAL(currentIndexChanged(int)), this, SLOT(samplingRateChanged(int)));
416 connect(checkBoxNeroAAC2PassMode, SIGNAL(clicked(bool)), this, SLOT(neroAAC2PassChanged(bool)));
417 connect(comboBoxAACProfile, SIGNAL(currentIndexChanged(int)), this, SLOT(neroAACProfileChanged(int)));
418 connect(checkBoxNormalizationFilter, SIGNAL(clicked(bool)), this, SLOT(normalizationEnabledChanged(bool)));
419 connect(comboBoxAftenCodingMode, SIGNAL(currentIndexChanged(int)), this, SLOT(aftenCodingModeChanged(int)));
420 connect(comboBoxAftenDRCMode, SIGNAL(currentIndexChanged(int)), this, SLOT(aftenDRCModeChanged(int)));
421 connect(spinBoxAftenSearchSize, SIGNAL(valueChanged(int)), this, SLOT(aftenSearchSizeChanged(int)));
422 connect(checkBoxAftenFastAllocation, SIGNAL(clicked(bool)), this, SLOT(aftenFastAllocationChanged(bool)));
423 connect(spinBoxNormalizationFilter, SIGNAL(valueChanged(double)), this, SLOT(normalizationMaxVolumeChanged(double)));
424 connect(comboBoxNormalizationMode, SIGNAL(currentIndexChanged(int)), this, SLOT(normalizationModeChanged(int)));
425 connect(spinBoxToneAdjustBass, SIGNAL(valueChanged(double)), this, SLOT(toneAdjustBassChanged(double)));
426 connect(spinBoxToneAdjustTreble, SIGNAL(valueChanged(double)), this, SLOT(toneAdjustTrebleChanged(double)));
427 connect(buttonToneAdjustReset, SIGNAL(clicked()), this, SLOT(toneAdjustTrebleReset()));
428 connect(lineEditCustomParamLAME, SIGNAL(editingFinished()), this, SLOT(customParamsChanged()));
429 connect(lineEditCustomParamOggEnc, SIGNAL(editingFinished()), this, SLOT(customParamsChanged()));
430 connect(lineEditCustomParamNeroAAC, SIGNAL(editingFinished()), this, SLOT(customParamsChanged()));
431 connect(lineEditCustomParamFLAC, SIGNAL(editingFinished()), this, SLOT(customParamsChanged()));
432 connect(lineEditCustomParamAften, SIGNAL(editingFinished()), this, SLOT(customParamsChanged()));
433 connect(lineEditCustomParamOpus, SIGNAL(editingFinished()), this, SLOT(customParamsChanged()));
434 connect(sliderMaxInstances, SIGNAL(valueChanged(int)), this, SLOT(updateMaximumInstances(int)));
435 connect(checkBoxAutoDetectInstances, SIGNAL(clicked(bool)), this, SLOT(autoDetectInstancesChanged(bool)));
436 connect(buttonBrowseCustomTempFolder, SIGNAL(clicked()), this, SLOT(browseCustomTempFolderButtonClicked()));
437 connect(lineEditCustomTempFolder, SIGNAL(textChanged(QString)), this, SLOT(customTempFolderChanged(QString)));
438 connect(checkBoxUseSystemTempFolder, SIGNAL(clicked(bool)), this, SLOT(useCustomTempFolderChanged(bool)));
439 connect(buttonResetAdvancedOptions, SIGNAL(clicked()), this, SLOT(resetAdvancedOptionsButtonClicked()));
440 connect(checkBoxRenameOutput, SIGNAL(clicked(bool)), this, SLOT(renameOutputEnabledChanged(bool)));
441 connect(lineEditRenamePattern, SIGNAL(editingFinished()), this, SLOT(renameOutputPatternChanged()));
442 connect(lineEditRenamePattern, SIGNAL(textChanged(QString)), this, SLOT(renameOutputPatternChanged(QString)));
443 connect(labelShowRenameMacros, SIGNAL(linkActivated(QString)), this, SLOT(showRenameMacros(QString)));
444 connect(checkBoxForceStereoDownmix, SIGNAL(clicked(bool)), this, SLOT(forceStereoDownmixEnabledChanged(bool)));
445 connect(comboBoxOpusOptimize, SIGNAL(currentIndexChanged(int)), SLOT(opusSettingsChanged()));
446 connect(comboBoxOpusFramesize, SIGNAL(currentIndexChanged(int)), this, SLOT(opusSettingsChanged()));
447 connect(spinBoxOpusComplexity, SIGNAL(valueChanged(int)), this, SLOT(opusSettingsChanged()));
448 connect(checkBoxOpusExpAnalysis, SIGNAL(clicked(bool)), this, SLOT(opusSettingsChanged()));
449 connect(m_evenFilterCustumParamsHelp, SIGNAL(eventOccurred(QWidget*, QEvent*)), this, SLOT(customParamsHelpRequested(QWidget*, QEvent*)));
451 //--------------------------------
452 // Force initial GUI update
453 //--------------------------------
455 updateLameAlgoQuality(sliderLameAlgoQuality->value());
456 updateMaximumInstances(sliderMaxInstances->value());
457 toneAdjustTrebleChanged(spinBoxToneAdjustTreble->value());
458 toneAdjustBassChanged(spinBoxToneAdjustBass->value());
459 customParamsChanged();
461 //--------------------------------
462 // Initialize actions
463 //--------------------------------
465 //Activate file menu actions
466 actionOpenFolder->setData(QVariant::fromValue<bool>(false));
467 actionOpenFolderRecursively->setData(QVariant::fromValue<bool>(true));
468 connect(actionOpenFolder, SIGNAL(triggered()), this, SLOT(openFolderActionActivated()));
469 connect(actionOpenFolderRecursively, SIGNAL(triggered()), this, SLOT(openFolderActionActivated()));
471 //Activate view menu actions
472 m_tabActionGroup = new QActionGroup(this);
473 m_tabActionGroup->addAction(actionSourceFiles);
474 m_tabActionGroup->addAction(actionOutputDirectory);
475 m_tabActionGroup->addAction(actionCompression);
476 m_tabActionGroup->addAction(actionMetaData);
477 m_tabActionGroup->addAction(actionAdvancedOptions);
478 actionSourceFiles->setData(0);
479 actionOutputDirectory->setData(1);
480 actionMetaData->setData(2);
481 actionCompression->setData(3);
482 actionAdvancedOptions->setData(4);
483 actionSourceFiles->setChecked(true);
484 connect(m_tabActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(tabActionActivated(QAction*)));
486 //Activate style menu actions
487 m_styleActionGroup = new QActionGroup(this);
488 m_styleActionGroup->addAction(actionStylePlastique);
489 m_styleActionGroup->addAction(actionStyleCleanlooks);
490 m_styleActionGroup->addAction(actionStyleWindowsVista);
491 m_styleActionGroup->addAction(actionStyleWindowsXP);
492 m_styleActionGroup->addAction(actionStyleWindowsClassic);
493 actionStylePlastique->setData(0);
494 actionStyleCleanlooks->setData(1);
495 actionStyleWindowsVista->setData(2);
496 actionStyleWindowsXP->setData(3);
497 actionStyleWindowsClassic->setData(4);
498 actionStylePlastique->setChecked(true);
499 actionStyleWindowsXP->setEnabled((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_XP && lamexp_themes_enabled());
500 actionStyleWindowsVista->setEnabled((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_VISTA && lamexp_themes_enabled());
501 connect(m_styleActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(styleActionActivated(QAction*)));
502 styleActionActivated(NULL);
504 //Populate the language menu
505 m_languageActionGroup = new QActionGroup(this);
506 QStringList translations = lamexp_query_translations();
507 while(!translations.isEmpty())
509 QString langId = translations.takeFirst();
510 QAction *currentLanguage = new QAction(this);
511 currentLanguage->setData(langId);
512 currentLanguage->setText(lamexp_translation_name(langId));
513 currentLanguage->setIcon(QIcon(QString(":/flags/%1.png").arg(langId)));
514 currentLanguage->setCheckable(true);
515 currentLanguage->setChecked(false);
516 m_languageActionGroup->addAction(currentLanguage);
517 menuLanguage->insertAction(actionLoadTranslationFromFile, currentLanguage);
519 menuLanguage->insertSeparator(actionLoadTranslationFromFile);
520 connect(actionLoadTranslationFromFile, SIGNAL(triggered(bool)), this, SLOT(languageFromFileActionActivated(bool)));
521 connect(m_languageActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(languageActionActivated(QAction*)));
522 actionLoadTranslationFromFile->setChecked(false);
524 //Activate tools menu actions
525 actionDisableUpdateReminder->setChecked(!m_settings->autoUpdateEnabled());
526 actionDisableSounds->setChecked(!m_settings->soundsEnabled());
527 actionDisableNeroAacNotifications->setChecked(!m_settings->neroAacNotificationsEnabled());
528 actionDisableSlowStartupNotifications->setChecked(!m_settings->antivirNotificationsEnabled());
529 actionDisableShellIntegration->setChecked(!m_settings->shellIntegrationEnabled());
530 actionDisableShellIntegration->setDisabled(lamexp_portable_mode() && actionDisableShellIntegration->isChecked());
531 actionCheckForBetaUpdates->setChecked(m_settings->autoUpdateCheckBeta() || lamexp_version_demo());
532 actionCheckForBetaUpdates->setEnabled(!lamexp_version_demo());
533 actionHibernateComputer->setChecked(m_settings->hibernateComputer());
534 actionHibernateComputer->setEnabled(lamexp_is_hibernation_supported());
535 connect(actionDisableUpdateReminder, SIGNAL(triggered(bool)), this, SLOT(disableUpdateReminderActionTriggered(bool)));
536 connect(actionDisableSounds, SIGNAL(triggered(bool)), this, SLOT(disableSoundsActionTriggered(bool)));
537 connect(actionDisableNeroAacNotifications, SIGNAL(triggered(bool)), this, SLOT(disableNeroAacNotificationsActionTriggered(bool)));
538 connect(actionDisableSlowStartupNotifications, SIGNAL(triggered(bool)), this, SLOT(disableSlowStartupNotificationsActionTriggered(bool)));
539 connect(actionDisableShellIntegration, SIGNAL(triggered(bool)), this, SLOT(disableShellIntegrationActionTriggered(bool)));
540 connect(actionShowDropBoxWidget, SIGNAL(triggered(bool)), this, SLOT(showDropBoxWidgetActionTriggered(bool)));
541 connect(actionHibernateComputer, SIGNAL(triggered(bool)), this, SLOT(hibernateComputerActionTriggered(bool)));
542 connect(actionCheckForBetaUpdates, SIGNAL(triggered(bool)), this, SLOT(checkForBetaUpdatesActionTriggered(bool)));
543 connect(actionImportCueSheet, SIGNAL(triggered(bool)), this, SLOT(importCueSheetActionTriggered(bool)));
545 //Activate help menu actions
546 actionVisitHomepage->setData(QString::fromLatin1(lamexp_website_url()));
547 actionVisitSupport->setData(QString::fromLatin1(lamexp_support_url()));
548 actionDocumentFAQ->setData(QString("%1/FAQ.html").arg(QApplication::applicationDirPath()));
549 actionDocumentChangelog->setData(QString("%1/Changelog.html").arg(QApplication::applicationDirPath()));
550 actionDocumentTranslate->setData(QString("%1/Translate.html").arg(QApplication::applicationDirPath()));
551 connect(actionCheckUpdates, SIGNAL(triggered()), this, SLOT(checkUpdatesActionActivated()));
552 connect(actionVisitHomepage, SIGNAL(triggered()), this, SLOT(visitHomepageActionActivated()));
553 connect(actionVisitSupport, SIGNAL(triggered()), this, SLOT(visitHomepageActionActivated()));
554 connect(actionDocumentFAQ, SIGNAL(triggered()), this, SLOT(documentActionActivated()));
555 connect(actionDocumentChangelog, SIGNAL(triggered()), this, SLOT(documentActionActivated()));
556 connect(actionDocumentTranslate, SIGNAL(triggered()), this, SLOT(documentActionActivated()));
558 //--------------------------------
559 // Prepare to show window
560 //--------------------------------
562 //Center window in screen
563 QRect desktopRect = QApplication::desktop()->screenGeometry();
564 QRect thisRect = this->geometry();
565 move((desktopRect.width() - thisRect.width()) / 2, (desktopRect.height() - thisRect.height()) / 2);
566 setMinimumSize(thisRect.width(), thisRect.height());
569 m_banner = new WorkingBanner(this);
571 //Create DropBox widget
572 m_dropBox = new DropBox(this, m_fileListModel, m_settings);
573 connect(m_fileListModel, SIGNAL(modelReset()), m_dropBox, SLOT(modelChanged()));
574 connect(m_fileListModel, SIGNAL(rowsInserted(QModelIndex,int,int)), m_dropBox, SLOT(modelChanged()));
575 connect(m_fileListModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), m_dropBox, SLOT(modelChanged()));
576 connect(m_fileListModel, SIGNAL(rowAppended()), m_dropBox, SLOT(modelChanged()));
578 //Create message handler thread
579 m_messageHandler = new MessageHandlerThread();
580 m_delayedFileList = new QStringList();
581 m_delayedFileTimer = new QTimer();
582 m_delayedFileTimer->setSingleShot(true);
583 m_delayedFileTimer->setInterval(5000);
584 connect(m_messageHandler, SIGNAL(otherInstanceDetected()), this, SLOT(notifyOtherInstance()), Qt::QueuedConnection);
585 connect(m_messageHandler, SIGNAL(fileReceived(QString)), this, SLOT(addFileDelayed(QString)), Qt::QueuedConnection);
586 connect(m_messageHandler, SIGNAL(folderReceived(QString, bool)), this, SLOT(addFolderDelayed(QString, bool)), Qt::QueuedConnection);
587 connect(m_messageHandler, SIGNAL(killSignalReceived()), this, SLOT(close()), Qt::QueuedConnection);
588 connect(m_delayedFileTimer, SIGNAL(timeout()), this, SLOT(handleDelayedFiles()));
589 m_messageHandler->start();
592 initializeTranslation();
594 //Re-translate (make sure we translate once)
595 QEvent languageChangeEvent(QEvent::LanguageChange);
596 changeEvent(&languageChangeEvent);
599 this->setAcceptDrops(true);
602 ////////////////////////////////////////////////////////////
604 ////////////////////////////////////////////////////////////
606 MainWindow::~MainWindow(void)
608 //Stop message handler thread
609 if(m_messageHandler && m_messageHandler->isRunning())
611 m_messageHandler->stop();
612 if(!m_messageHandler->wait(2500))
614 m_messageHandler->terminate();
615 m_messageHandler->wait();
620 SET_MODEL(sourceFileView, NULL);
621 SET_MODEL(outputFolderView, NULL);
622 SET_MODEL(metaDataView, NULL);
625 LAMEXP_DELETE(m_tabActionGroup);
626 LAMEXP_DELETE(m_styleActionGroup);
627 LAMEXP_DELETE(m_languageActionGroup);
628 LAMEXP_DELETE(m_banner);
629 LAMEXP_DELETE(m_fileSystemModel);
630 LAMEXP_DELETE(m_messageHandler);
631 LAMEXP_DELETE(m_delayedFileList);
632 LAMEXP_DELETE(m_delayedFileTimer);
633 LAMEXP_DELETE(m_metaInfoModel);
634 LAMEXP_DELETE(m_encoderButtonGroup);
635 LAMEXP_DELETE(m_encoderButtonGroup);
636 LAMEXP_DELETE(m_sourceFilesContextMenu);
637 LAMEXP_DELETE(m_outputFolderFavoritesMenu);
638 LAMEXP_DELETE(m_outputFolderContextMenu);
639 LAMEXP_DELETE(m_dropBox);
640 LAMEXP_DELETE(m_evenFilterCustumParamsHelp);
641 LAMEXP_DELETE(m_evenFilterOutputFolderMouse);
642 LAMEXP_DELETE(m_evenFilterOutputFolderView);
643 LAMEXP_DELETE(m_evenFilterCompressionTab);
646 ////////////////////////////////////////////////////////////
648 ////////////////////////////////////////////////////////////
651 * Add file to source list
653 void MainWindow::addFiles(const QStringList &files)
660 tabWidget->setCurrentIndex(0);
662 FileAnalyzer *analyzer = new FileAnalyzer(files);
663 connect(analyzer, SIGNAL(fileSelected(QString)), m_banner, SLOT(setText(QString)), Qt::QueuedConnection);
664 connect(analyzer, SIGNAL(progressValChanged(unsigned int)), m_banner, SLOT(setProgressVal(unsigned int)), Qt::QueuedConnection);
665 connect(analyzer, SIGNAL(progressMaxChanged(unsigned int)), m_banner, SLOT(setProgressMax(unsigned int)), Qt::QueuedConnection);
666 connect(analyzer, SIGNAL(fileAnalyzed(AudioFileModel)), m_fileListModel, SLOT(addFile(AudioFileModel)), Qt::QueuedConnection);
667 connect(m_banner, SIGNAL(userAbort()), analyzer, SLOT(abortProcess()), Qt::DirectConnection);
671 m_fileListModel->setBlockUpdates(true);
672 QTime startTime = QTime::currentTime();
673 m_banner->show(tr("Adding file(s), please wait..."), analyzer);
674 //timeMT = startTime.secsTo(QTime::currentTime());
678 /* ignore any exceptions that may occur */
681 m_fileListModel->setBlockUpdates(false);
682 qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
683 sourceFileView->update();
684 qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
685 sourceFileView->scrollToBottom();
686 qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
688 if(analyzer->filesDenied())
690 QMessageBox::warning(this, tr("Access Denied"), QString("%1<br>%2").arg(NOBR(tr("%1 file(s) have been rejected, because read access was not granted!").arg(analyzer->filesDenied())), NOBR(tr("This usually means the file is locked by another process."))));
692 if(analyzer->filesDummyCDDA())
694 QMessageBox::warning(this, tr("CDDA Files"), QString("%1<br><br>%2<br>%3").arg(NOBR(tr("%1 file(s) have been rejected, because they are dummy CDDA files!").arg(analyzer->filesDummyCDDA())), NOBR(tr("Sorry, LameXP cannot extract audio tracks from an Audio-CD at present.")), NOBR(tr("We recommend using %1 for that purpose.").arg("<a href=\"http://www.exactaudiocopy.de/\">Exact Audio Copy</a>"))));
696 if(analyzer->filesCueSheet())
698 QMessageBox::warning(this, tr("Cue Sheet"), QString("%1<br>%2").arg(NOBR(tr("%1 file(s) have been rejected, because they appear to be Cue Sheet images!").arg(analyzer->filesCueSheet())), NOBR(tr("Please use LameXP's Cue Sheet wizard for importing Cue Sheet files."))));
700 if(analyzer->filesRejected())
702 QMessageBox::warning(this, tr("Files Rejected"), QString("%1<br>%2").arg(NOBR(tr("%1 file(s) have been rejected, because the file format could not be recognized!").arg(analyzer->filesRejected())), NOBR(tr("This usually means the file is damaged or the file format is not supported."))));
705 LAMEXP_DELETE(analyzer);
710 * Add folder to source list
712 void MainWindow::addFolder(const QString &path, bool recursive, bool delayed)
714 QFileInfoList folderInfoList;
715 folderInfoList << QFileInfo(path);
716 QStringList fileList;
718 m_banner->show(tr("Scanning folder(s) for files, please wait..."));
720 QApplication::processEvents();
721 GetAsyncKeyState(VK_ESCAPE);
723 while(!folderInfoList.isEmpty())
725 if(GetAsyncKeyState(VK_ESCAPE) & 0x0001)
727 MessageBeep(MB_ICONERROR);
728 qWarning("Operation cancelled by user!");
733 QDir currentDir(folderInfoList.takeFirst().canonicalFilePath());
734 QFileInfoList fileInfoList = currentDir.entryInfoList(QDir::Files | QDir::NoSymLinks);
736 while(!fileInfoList.isEmpty())
738 fileList << fileInfoList.takeFirst().canonicalFilePath();
741 QApplication::processEvents();
745 folderInfoList.append(currentDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks));
746 QApplication::processEvents();
751 QApplication::processEvents();
753 if(!fileList.isEmpty())
757 addFilesDelayed(fileList);
769 bool MainWindow::checkForUpdates(void)
771 bool bReadyToInstall = false;
773 UpdateDialog *updateDialog = new UpdateDialog(m_settings, this);
774 updateDialog->exec();
776 if(updateDialog->getSuccess())
778 m_settings->autoUpdateLastCheck(QDate::currentDate().toString(Qt::ISODate));
779 bReadyToInstall = updateDialog->updateReadyToInstall();
782 LAMEXP_DELETE(updateDialog);
783 return bReadyToInstall;
787 * Refresh list of favorites
789 void MainWindow::refreshFavorites(void)
791 QList<QAction*> folderList = m_outputFolderFavoritesMenu->actions();
792 QStringList favorites = m_settings->favoriteOutputFolders().split("|", QString::SkipEmptyParts);
793 while(favorites.count() > 6) favorites.removeFirst();
795 while(!folderList.isEmpty())
797 QAction *currentItem = folderList.takeFirst();
798 if(currentItem->isSeparator()) break;
799 m_outputFolderFavoritesMenu->removeAction(currentItem);
800 LAMEXP_DELETE(currentItem);
803 QAction *lastItem = m_outputFolderFavoritesMenu->actions().first();
805 while(!favorites.isEmpty())
807 QString path = favorites.takeLast();
808 if(QDir(path).exists())
810 QAction *action = new QAction(QIcon(":/icons/folder_go.png"), QDir::toNativeSeparators(path), this);
811 action->setData(path);
812 m_outputFolderFavoritesMenu->insertAction(lastItem, action);
813 connect(action, SIGNAL(triggered(bool)), this, SLOT(gotoFavoriteFolder()));
820 * Initilaize translation
822 void MainWindow::initializeTranslation(void)
824 bool translationLoaded = false;
826 //Try to load "external" translation file
827 if(!m_settings->currentLanguageFile().isEmpty())
829 const QString qmFilePath = QFileInfo(m_settings->currentLanguageFile()).canonicalFilePath();
830 if((!qmFilePath.isEmpty()) && QFileInfo(qmFilePath).exists() && QFileInfo(qmFilePath).isFile() && (QFileInfo(qmFilePath).suffix().compare("qm", Qt::CaseInsensitive) == 0))
832 if(lamexp_install_translator_from_file(qmFilePath))
834 QList<QAction*> actions = m_languageActionGroup->actions();
835 while(!actions.isEmpty()) actions.takeFirst()->setChecked(false);
836 actionLoadTranslationFromFile->setChecked(true);
837 translationLoaded = true;
842 //Try to load "built-in" translation file
843 if(!translationLoaded)
845 QList<QAction*> languageActions = m_languageActionGroup->actions();
846 while(!languageActions.isEmpty())
848 QAction *currentLanguage = languageActions.takeFirst();
849 if(currentLanguage->data().toString().compare(m_settings->currentLanguage(), Qt::CaseInsensitive) == 0)
851 currentLanguage->setChecked(true);
852 languageActionActivated(currentLanguage);
853 translationLoaded = true;
858 //Fallback to default translation
859 if(!translationLoaded)
861 QList<QAction*> languageActions = m_languageActionGroup->actions();
862 while(!languageActions.isEmpty())
864 QAction *currentLanguage = languageActions.takeFirst();
865 if(currentLanguage->data().toString().compare(LAMEXP_DEFAULT_LANGID, Qt::CaseInsensitive) == 0)
867 currentLanguage->setChecked(true);
868 languageActionActivated(currentLanguage);
869 translationLoaded = true;
874 //Make sure we loaded some translation
875 if(!translationLoaded)
877 qFatal("Failed to load any translation, this is NOT supposed to happen!");
881 ////////////////////////////////////////////////////////////
883 ////////////////////////////////////////////////////////////
886 * Window is about to be shown
888 void MainWindow::showEvent(QShowEvent *event)
891 m_dropNoteLabel->setGeometry(0, 0, sourceFileView->width(), sourceFileView->height());
892 sourceModelChanged();
894 if(!event->spontaneous())
896 tabWidget->setCurrentIndex(0);
901 m_firstTimeShown = false;
902 QTimer::singleShot(0, this, SLOT(windowShown()));
906 if(m_settings->dropBoxWidgetEnabled())
908 m_dropBox->setVisible(true);
914 * Re-translate the UI
916 void MainWindow::changeEvent(QEvent *e)
918 if(e->type() == QEvent::LanguageChange)
920 int comboBoxIndex[8];
922 //Backup combobox indices, as retranslateUi() resets
923 comboBoxIndex[0] = comboBoxMP3ChannelMode->currentIndex();
924 comboBoxIndex[1] = comboBoxSamplingRate->currentIndex();
925 comboBoxIndex[2] = comboBoxAACProfile->currentIndex();
926 comboBoxIndex[3] = comboBoxAftenCodingMode->currentIndex();
927 comboBoxIndex[4] = comboBoxAftenDRCMode->currentIndex();
928 comboBoxIndex[5] = comboBoxNormalizationMode->currentIndex();
929 comboBoxIndex[6] = comboBoxOpusOptimize->currentIndex();
930 comboBoxIndex[7] = comboBoxOpusFramesize->currentIndex();
932 //Re-translate from UIC
933 Ui::MainWindow::retranslateUi(this);
935 //Restore combobox indices
936 comboBoxMP3ChannelMode->setCurrentIndex(comboBoxIndex[0]);
937 comboBoxSamplingRate->setCurrentIndex(comboBoxIndex[1]);
938 comboBoxAACProfile->setCurrentIndex(comboBoxIndex[2]);
939 comboBoxAftenCodingMode->setCurrentIndex(comboBoxIndex[3]);
940 comboBoxAftenDRCMode->setCurrentIndex(comboBoxIndex[4]);
941 comboBoxNormalizationMode->setCurrentIndex(comboBoxIndex[5]);
942 comboBoxOpusOptimize->setCurrentIndex(comboBoxIndex[6]);
943 comboBoxOpusFramesize->setCurrentIndex(comboBoxIndex[7]);
945 //Update the window title
948 setWindowTitle(QString("%1 [!!! DEBUG BUILD !!!]").arg(windowTitle()));
950 else if(lamexp_version_demo())
952 setWindowTitle(QString("%1 [%2]").arg(windowTitle(), tr("DEMO VERSION")));
955 //Manually re-translate widgets that UIC doesn't handle
956 m_dropNoteLabel->setText(QString("» %1 «").arg(tr("You can drop in audio files here!")));
957 m_outputFolderNoteBox->setText(tr("Initializing directory outline, please be patient..."));
958 m_showDetailsContextAction->setText(tr("Show Details"));
959 m_previewContextAction->setText(tr("Open File in External Application"));
960 m_findFileContextAction->setText(tr("Browse File Location"));
961 m_showFolderContextAction->setText(tr("Browse Selected Folder"));
962 m_refreshFolderContextAction->setText(tr("Refresh Directory Outline"));
963 m_addFavoriteFolderAction->setText(tr("Bookmark Current Output Folder"));
964 m_exportCsvContextAction->setText(tr("Export Meta Tags to CSV File"));
965 m_importCsvContextAction->setText(tr("Import Meta Tags from CSV File"));
968 m_metaInfoModel->clearData();
969 m_metaInfoModel->setData(m_metaInfoModel->index(4, 1), m_settings->metaInfoPosition());
970 updateEncoder(m_settings->compressionEncoder());
971 updateLameAlgoQuality(sliderLameAlgoQuality->value());
972 updateMaximumInstances(sliderMaxInstances->value());
973 renameOutputPatternChanged(lineEditRenamePattern->text());
975 //Re-install shell integration
976 if(m_settings->shellIntegrationEnabled())
978 ShellIntegration::install();
981 //Translate system menu
982 if(HMENU hMenu = ::GetSystemMenu(winId(), FALSE))
984 ModifyMenu(hMenu, IDM_ABOUTBOX, MF_STRING | MF_BYCOMMAND, IDM_ABOUTBOX, QWCHAR(buttonAbout->text()));
987 //Force resize, if needed
988 tabPageChanged(tabWidget->currentIndex());
993 * File dragged over window
995 void MainWindow::dragEnterEvent(QDragEnterEvent *event)
997 QStringList formats = event->mimeData()->formats();
999 if(formats.contains("application/x-qt-windows-mime;value=\"FileNameW\"", Qt::CaseInsensitive) && formats.contains("text/uri-list", Qt::CaseInsensitive))
1001 event->acceptProposedAction();
1006 * File dropped onto window
1008 void MainWindow::dropEvent(QDropEvent *event)
1012 QStringList droppedFiles;
1013 QList<QUrl> urls = event->mimeData()->urls();
1015 while(!urls.isEmpty())
1017 QUrl currentUrl = urls.takeFirst();
1018 QFileInfo file(currentUrl.toLocalFile());
1025 qDebug("Dropped File: %s", file.canonicalFilePath().toUtf8().constData());
1026 droppedFiles << file.canonicalFilePath();
1031 qDebug("Dropped Folder: %s", file.canonicalFilePath().toUtf8().constData());
1032 QList<QFileInfo> list = QDir(file.canonicalFilePath()).entryInfoList(QDir::Files | QDir::NoSymLinks);
1033 if(list.count() > 0)
1035 for(int j = 0; j < list.count(); j++)
1037 droppedFiles << list.at(j).canonicalFilePath();
1042 list = QDir(file.canonicalFilePath()).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
1043 for(int j = 0; j < list.count(); j++)
1045 qDebug("Descending to Folder: %s", list.at(j).canonicalFilePath().toUtf8().constData());
1046 urls.prepend(QUrl::fromLocalFile(list.at(j).canonicalFilePath()));
1052 if(!droppedFiles.isEmpty())
1054 addFilesDelayed(droppedFiles, true);
1059 * Window tries to close
1061 void MainWindow::closeEvent(QCloseEvent *event)
1063 if(m_banner->isVisible() || m_delayedFileTimer->isActive())
1065 MessageBeep(MB_ICONEXCLAMATION);
1076 * Window was resized
1078 void MainWindow::resizeEvent(QResizeEvent *event)
1080 if(event) QMainWindow::resizeEvent(event);
1081 m_dropNoteLabel->setGeometry(0, 0, sourceFileView->width(), sourceFileView->height());
1083 if(QWidget *port = outputFolderView->viewport())
1085 m_outputFolderNoteBox->setGeometry(16, (port->height() - 64) / 2, port->width() - 32, 64);
1090 * Key press event filter
1092 void MainWindow::keyPressEvent(QKeyEvent *e)
1094 if(e->key() == Qt::Key_Delete)
1096 if(sourceFileView->isVisible())
1098 QTimer::singleShot(0, this, SLOT(removeFileButtonClicked()));
1103 if(e->modifiers().testFlag(Qt::ControlModifier) && (e->key() == Qt::Key_F5))
1105 initializeTranslation();
1106 MessageBeep(MB_ICONINFORMATION);
1110 if(e->key() == Qt::Key_F5)
1112 if(outputFolderView->isVisible())
1114 QTimer::singleShot(0, this, SLOT(refreshFolderContextActionTriggered()));
1119 QMainWindow::keyPressEvent(e);
1125 bool MainWindow::eventFilter(QObject *obj, QEvent *event)
1127 if(obj == m_fileSystemModel)
1129 if(QApplication::overrideCursor() == NULL)
1131 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1132 QTimer::singleShot(250, this, SLOT(restoreCursor()));
1136 return QMainWindow::eventFilter(obj, event);
1139 bool MainWindow::event(QEvent *e)
1143 case lamexp_event_queryendsession:
1144 qWarning("System is shutting down, main window prepares to close...");
1145 if(m_banner->isVisible()) m_banner->close();
1146 if(m_delayedFileTimer->isActive()) m_delayedFileTimer->stop();
1148 case lamexp_event_endsession:
1149 qWarning("System is shutting down, main window will close now...");
1154 QApplication::processEvents(QEventLoop::WaitForMoreEvents & QEventLoop::ExcludeUserInputEvents);
1157 m_fileListModel->clearFiles();
1159 case QEvent::MouseButtonPress:
1160 if(outputFolderEdit->isVisible())
1162 QTimer::singleShot(0, this, SLOT(outputFolderEditFinished()));
1165 return QMainWindow::event(e);
1169 bool MainWindow::winEvent(MSG *message, long *result)
1171 if((message->message == WM_SYSCOMMAND) && ((message->wParam & 0xFFF0) == IDM_ABOUTBOX))
1173 QTimer::singleShot(0, buttonAbout, SLOT(click()));
1177 return WinSevenTaskbar::handleWinEvent(message, result);
1180 ////////////////////////////////////////////////////////////
1182 ////////////////////////////////////////////////////////////
1184 // =========================================================
1185 // Show window slots
1186 // =========================================================
1191 void MainWindow::windowShown(void)
1193 const QStringList &arguments = lamexp_arguments(); //QApplication::arguments();
1196 bool firstRun = false;
1197 for(int i = 0; i < arguments.count(); i++)
1199 /*QMessageBox::information(this, QString::number(i), arguments[i]);*/
1200 if(!arguments[i].compare("--first-run", Qt::CaseInsensitive)) firstRun = true;
1204 if((m_settings->licenseAccepted() <= 0) || firstRun)
1206 int iAccepted = m_settings->licenseAccepted();
1208 if((iAccepted == 0) || firstRun)
1210 AboutDialog *about = new AboutDialog(m_settings, this, true);
1211 iAccepted = about->exec();
1212 if(iAccepted <= 0) iAccepted = -2;
1213 LAMEXP_DELETE(about);
1218 m_settings->licenseAccepted(++iAccepted);
1219 m_settings->syncNow();
1220 QApplication::processEvents();
1221 PlaySound(MAKEINTRESOURCE(IDR_WAVE_WHAMMY), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC);
1222 QMessageBox::critical(this, tr("License Declined"), tr("You have declined the license. Consequently the application will exit now!"), tr("Goodbye!"));
1223 QFileInfo uninstallerInfo = QFileInfo(QString("%1/Uninstall.exe").arg(QApplication::applicationDirPath()));
1224 if(uninstallerInfo.exists())
1226 QString uninstallerDir = uninstallerInfo.canonicalPath();
1227 QString uninstallerPath = uninstallerInfo.canonicalFilePath();
1228 for(int i = 0; i < 3; i++)
1230 HINSTANCE res = ShellExecuteW(reinterpret_cast<HWND>(this->winId()), L"open", QWCHAR(QDir::toNativeSeparators(uninstallerPath)), L"/Force", QWCHAR(QDir::toNativeSeparators(uninstallerDir)), SW_SHOWNORMAL);
1231 if(reinterpret_cast<int>(res) > 32) break;
1234 QApplication::quit();
1238 PlaySound(MAKEINTRESOURCE(IDR_WAVE_WOOHOO), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC);
1239 m_settings->licenseAccepted(1);
1240 m_settings->syncNow();
1241 if(lamexp_version_demo()) showAnnounceBox();
1244 //Check for expiration
1245 if(lamexp_version_demo())
1247 if(QDate::currentDate() >= lamexp_version_expires())
1249 qWarning("Binary has expired !!!");
1250 PlaySound(MAKEINTRESOURCE(IDR_WAVE_WHAMMY), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC);
1251 if(QMessageBox::warning(this, tr("LameXP - Expired"), QString("%1<br>%2").arg(NOBR(tr("This demo (pre-release) version of LameXP has expired at %1.").arg(lamexp_version_expires().toString(Qt::ISODate))), NOBR(tr("LameXP is free software and release versions won't expire."))), tr("Check for Updates"), tr("Exit Program")) == 0)
1255 QApplication::quit();
1260 //Slow startup indicator
1261 if(m_settings->slowStartup() && m_settings->antivirNotificationsEnabled())
1264 message += NOBR(tr("It seems that a bogus anti-virus software is slowing down the startup of LameXP.")).append("<br>");
1265 message += NOBR(tr("Please refer to the %1 document for details and solutions!")).arg("<a href=\"http://lamexp.sourceforge.net/doc/FAQ.html#df406578\">F.A.Q.</a>").append("<br>");
1266 if(QMessageBox::warning(this, tr("Slow Startup"), message, tr("Discard"), tr("Don't Show Again")) == 1)
1268 m_settings->antivirNotificationsEnabled(false);
1269 actionDisableSlowStartupNotifications->setChecked(!m_settings->antivirNotificationsEnabled());
1274 if(QDate::currentDate() >= lamexp_version_date().addYears(1))
1276 qWarning("Binary is more than a year old, time to update!");
1277 int ret = QMessageBox::warning(this, tr("Urgent Update"), NOBR(tr("Your version of LameXP is more than a year old. Time for an update!")), tr("Check for Updates"), tr("Exit Program"), tr("Ignore"));
1281 if(checkForUpdates())
1283 QApplication::quit();
1288 QApplication::quit();
1291 QEventLoop loop; QTimer::singleShot(7000, &loop, SLOT(quit()));
1292 PlaySound(MAKEINTRESOURCE(IDR_WAVE_WAITING), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC);
1293 m_banner->show(tr("Skipping update check this time, please be patient..."), &loop);
1297 else if(m_settings->autoUpdateEnabled())
1299 QDate lastUpdateCheck = QDate::fromString(m_settings->autoUpdateLastCheck(), Qt::ISODate);
1300 if(!firstRun && (!lastUpdateCheck.isValid() || QDate::currentDate() >= lastUpdateCheck.addDays(14)))
1302 if(QMessageBox::information(this, tr("Update Reminder"), NOBR(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)
1304 if(checkForUpdates())
1306 QApplication::quit();
1313 //Check for AAC support
1314 if(m_neroEncoderAvailable)
1316 if(m_settings->neroAacNotificationsEnabled())
1318 if(lamexp_tool_version("neroAacEnc.exe") < lamexp_toolver_neroaac())
1320 QString messageText;
1321 messageText += NOBR(tr("LameXP detected that your version of the Nero AAC encoder is outdated!")).append("<br>");
1322 messageText += NOBR(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")))).append("<br><br>");
1323 messageText += NOBR(tr("You can download the latest version of the Nero AAC encoder from the Nero website at:")).append("<br>");
1324 messageText += "<nobr><tt>" + LINK(AboutDialog::neroAacUrl) + "</tt></nobr><br><br>";
1325 messageText += NOBR(tr("(Hint: Please ignore the name of the downloaded ZIP file and check the included 'changelog.txt' instead!)")).append("<br>");
1326 QMessageBox::information(this, tr("AAC Encoder Outdated"), messageText);
1332 if(m_settings->neroAacNotificationsEnabled() && (!(m_fhgEncoderAvailable || m_qaacEncoderAvailable)))
1334 QString appPath = QDir(QCoreApplication::applicationDirPath()).canonicalPath();
1335 if(appPath.isEmpty()) appPath = QCoreApplication::applicationDirPath();
1336 QString messageText;
1337 messageText += NOBR(tr("The Nero AAC encoder could not be found. AAC encoding support will be disabled.")).append("<br>");
1338 messageText += NOBR(tr("Please put 'neroAacEnc.exe', 'neroAacDec.exe' and 'neroAacTag.exe' into the LameXP directory!")).append("<br><br>");
1339 messageText += NOBR(tr("Your LameXP directory is located here:")).append("<br>");
1340 messageText += QString("<nobr><tt>%1</tt></nobr><br><br>").arg(FSLINK(QDir::toNativeSeparators(appPath)));
1341 messageText += NOBR(tr("You can download the Nero AAC encoder for free from the official Nero website at:")).append("<br>");
1342 messageText += "<nobr><tt>" + LINK(AboutDialog::neroAacUrl) + "</tt></nobr><br>";
1343 if(QMessageBox::information(this, tr("AAC Support Disabled"), messageText, tr("Discard"), tr("Don't Show Again")) == 1)
1345 m_settings->neroAacNotificationsEnabled(false);
1346 actionDisableNeroAacNotifications->setChecked(!m_settings->neroAacNotificationsEnabled());
1351 //Add files from the command-line
1352 for(int i = 0; i < arguments.count() - 1; i++)
1354 QStringList addedFiles;
1355 if(!arguments[i].compare("--add", Qt::CaseInsensitive))
1357 QFileInfo currentFile(arguments[++i].trimmed());
1358 qDebug("Adding file from CLI: %s", currentFile.absoluteFilePath().toUtf8().constData());
1359 addedFiles.append(currentFile.absoluteFilePath());
1361 if(!addedFiles.isEmpty())
1363 addFilesDelayed(addedFiles);
1367 //Add folders from the command-line
1368 for(int i = 0; i < arguments.count() - 1; i++)
1370 if(!arguments[i].compare("--add-folder", Qt::CaseInsensitive))
1372 QFileInfo currentFile(arguments[++i].trimmed());
1373 qDebug("Adding folder from CLI: %s", currentFile.absoluteFilePath().toUtf8().constData());
1374 addFolder(currentFile.absoluteFilePath(), false, true);
1376 if(!arguments[i].compare("--add-recursive", Qt::CaseInsensitive))
1378 QFileInfo currentFile(arguments[++i].trimmed());
1379 qDebug("Adding folder recursively from CLI: %s", currentFile.absoluteFilePath().toUtf8().constData());
1380 addFolder(currentFile.absoluteFilePath(), true, true);
1384 //Enable shell integration
1385 if(m_settings->shellIntegrationEnabled())
1387 ShellIntegration::install();
1390 //Make DropBox visible
1391 if(m_settings->dropBoxWidgetEnabled())
1393 m_dropBox->setVisible(true);
1400 void MainWindow::showAnnounceBox(void)
1402 const unsigned int timeout = 8U;
1404 const QString announceText = QString("%1<br><br>%2<br><nobr><tt>%3</tt></nobr><br>").arg
1406 NOBR("We are still looking for LameXP translators!"),
1407 NOBR("If you are willing to translate LameXP to your language or to complete an existing translation, please refer to:"),
1408 LINK("http://lamexp.sourceforge.net/doc/Translate.html")
1411 QMessageBox *announceBox = new QMessageBox(QMessageBox::Warning, "We want you!", announceText, QMessageBox::NoButton, this);
1412 announceBox->setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
1413 announceBox->setIconPixmap(QIcon(":/images/Announcement.png").pixmap(64,79));
1415 QTimer *timers[timeout+1];
1416 QPushButton *buttons[timeout+1];
1418 for(unsigned int i = 0; i <= timeout; i++)
1420 QString text = (i > 0) ? QString("%1 (%2)").arg(tr("Discard"), QString::number(i)) : tr("Discard");
1421 buttons[i] = announceBox->addButton(text, (i > 0) ? QMessageBox::NoRole : QMessageBox::AcceptRole);
1424 for(unsigned int i = 0; i <= timeout; i++)
1426 buttons[i]->setEnabled(i == 0);
1427 buttons[i]->setVisible(i == timeout);
1430 for(unsigned int i = 0; i < timeout; i++)
1432 timers[i] = new QTimer(this);
1433 timers[i]->setSingleShot(true);
1434 timers[i]->setInterval(1000);
1435 connect(timers[i], SIGNAL(timeout()), buttons[i+1], SLOT(hide()));
1436 connect(timers[i], SIGNAL(timeout()), buttons[i], SLOT(show()));
1439 connect(timers[i], SIGNAL(timeout()), timers[i-1], SLOT(start()));
1443 timers[timeout-1]->start();
1444 announceBox->exec();
1446 for(unsigned int i = 0; i < timeout; i++)
1449 LAMEXP_DELETE(timers[i]);
1452 LAMEXP_DELETE(announceBox);
1455 // =========================================================
1456 // Main button solots
1457 // =========================================================
1462 void MainWindow::encodeButtonClicked(void)
1464 static const unsigned __int64 oneGigabyte = 1073741824ui64;
1465 static const unsigned __int64 minimumFreeDiskspaceMultiplier = 2ui64;
1466 static const char *writeTestBuffer = "LAMEXP_WRITE_TEST";
1470 if(m_fileListModel->rowCount() < 1)
1472 QMessageBox::warning(this, tr("LameXP"), NOBR(tr("You must add at least one file to the list before proceeding!")));
1473 tabWidget->setCurrentIndex(0);
1477 QString tempFolder = m_settings->customTempPathEnabled() ? m_settings->customTempPath() : lamexp_temp_folder2();
1478 if(!QFileInfo(tempFolder).exists() || !QFileInfo(tempFolder).isDir())
1480 if(QMessageBox::warning(this, tr("Not Found"), QString("%1<br><tt>%2</tt>").arg(NOBR(tr("Your currently selected TEMP folder does not exist anymore:")), NOBR(QDir::toNativeSeparators(tempFolder))), tr("Restore Default"), tr("Cancel")) == 0)
1482 SET_CHECKBOX_STATE(checkBoxUseSystemTempFolder, m_settings->customTempPathEnabledDefault());
1488 unsigned __int64 currentFreeDiskspace = lamexp_free_diskspace(tempFolder, &ok);
1490 if(ok && (currentFreeDiskspace < (oneGigabyte * minimumFreeDiskspaceMultiplier)))
1492 QStringList tempFolderParts = tempFolder.split("/", QString::SkipEmptyParts, Qt::CaseInsensitive);
1493 tempFolderParts.takeLast();
1494 if(m_settings->soundsEnabled()) PlaySound(MAKEINTRESOURCE(IDR_WAVE_WHAMMY), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC);
1495 QString lowDiskspaceMsg = QString("%1<br>%2<br><br>%3<br>%4<br>").arg
1497 NOBR(tr("There are less than %1 GB of free diskspace available on your system's TEMP folder.").arg(QString::number(minimumFreeDiskspaceMultiplier))),
1498 NOBR(tr("It is highly recommend to free up more diskspace before proceeding with the encode!")),
1499 NOBR(tr("Your TEMP folder is located at:")),
1500 QString("<nobr><tt>%1</tt></nobr>").arg(FSLINK(tempFolderParts.join("\\")))
1502 switch(QMessageBox::warning(this, tr("Low Diskspace Warning"), lowDiskspaceMsg, tr("Abort Encoding Process"), tr("Clean Disk Now"), tr("Ignore")))
1505 QProcess::startDetached(QString("%1/cleanmgr.exe").arg(lamexp_known_folder(lamexp_folder_systemfolder)), QStringList() << "/D" << tempFolderParts.first());
1510 QMessageBox::warning(this, tr("Low Diskspace"), NOBR(tr("You are proceeding with low diskspace. Problems might occur!")));
1515 switch(m_settings->compressionEncoder())
1517 case SettingsModel::MP3Encoder:
1518 case SettingsModel::VorbisEncoder:
1519 case SettingsModel::AACEncoder:
1520 case SettingsModel::AC3Encoder:
1521 case SettingsModel::FLACEncoder:
1522 case SettingsModel::OpusEncoder:
1523 case SettingsModel::DCAEncoder:
1524 case SettingsModel::PCMEncoder:
1527 QMessageBox::warning(this, tr("LameXP"), tr("Sorry, an unsupported encoder has been chosen!"));
1528 tabWidget->setCurrentIndex(3);
1532 if(!m_settings->outputToSourceDir())
1534 QFile writeTest(QString("%1/~%2.txt").arg(m_settings->outputDir(), lamexp_rand_str()));
1535 if(!(writeTest.open(QIODevice::ReadWrite) && (writeTest.write(writeTestBuffer) == strlen(writeTestBuffer))))
1537 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!")));
1538 tabWidget->setCurrentIndex(1);
1555 void MainWindow::aboutButtonClicked(void)
1561 AboutDialog *aboutBox = new AboutDialog(m_settings, this);
1563 LAMEXP_DELETE(aboutBox);
1570 void MainWindow::closeButtonClicked(void)
1576 // =========================================================
1578 // =========================================================
1583 void MainWindow::tabPageChanged(int idx)
1587 QList<QAction*> actions = m_tabActionGroup->actions();
1588 for(int i = 0; i < actions.count(); i++)
1591 int actionIndex = actions.at(i)->data().toInt(&ok);
1592 if(ok && actionIndex == idx)
1594 actions.at(i)->setChecked(true);
1598 int initialWidth = this->width();
1599 int maximumWidth = QApplication::desktop()->availableGeometry().width();
1601 //Make sure all tab headers are fully visible
1602 if(this->isVisible())
1604 int delta = tabWidget->sizeHint().width() - tabWidget->width();
1607 this->resize(qMin(this->width() + delta, maximumWidth), this->height());
1611 //Tab specific operations
1612 if(idx == tabWidget->indexOf(tabOptions) && scrollArea->widget() && this->isVisible())
1614 scrollArea->widget()->updateGeometry();
1615 scrollArea->viewport()->updateGeometry();
1616 qApp->processEvents();
1617 int delta = scrollArea->widget()->width() - scrollArea->viewport()->width();
1620 this->resize(qMin(this->width() + delta, maximumWidth), this->height());
1623 else if(idx == tabWidget->indexOf(tabSourceFiles))
1625 m_dropNoteLabel->setGeometry(0, 0, sourceFileView->width(), sourceFileView->height());
1627 else if(idx == tabWidget->indexOf(tabOutputDir))
1629 if(!m_fileSystemModel)
1631 QTimer::singleShot(125, this, SLOT(initOutputFolderModel()));
1635 CENTER_CURRENT_OUTPUT_FOLDER_DELAYED;
1639 //Center window around previous position
1640 if(initialWidth < this->width())
1642 QPoint prevPos = this->pos();
1643 int delta = (this->width() - initialWidth) >> 2;
1644 move(prevPos.x() - delta, prevPos.y());
1649 * Tab action triggered
1651 void MainWindow::tabActionActivated(QAction *action)
1653 if(action && action->data().isValid())
1656 int index = action->data().toInt(&ok);
1659 tabWidget->setCurrentIndex(index);
1664 // =========================================================
1666 // =========================================================
1669 * Style action triggered
1671 void MainWindow::styleActionActivated(QAction *action)
1673 //Change style setting
1674 if(action && action->data().isValid())
1677 int actionIndex = action->data().toInt(&ok);
1680 m_settings->interfaceStyle(actionIndex);
1684 //Set up the new style
1685 switch(m_settings->interfaceStyle())
1688 if(actionStyleCleanlooks->isEnabled())
1690 actionStyleCleanlooks->setChecked(true);
1691 QApplication::setStyle(new QCleanlooksStyle());
1695 if(actionStyleWindowsVista->isEnabled())
1697 actionStyleWindowsVista->setChecked(true);
1698 QApplication::setStyle(new QWindowsVistaStyle());
1702 if(actionStyleWindowsXP->isEnabled())
1704 actionStyleWindowsXP->setChecked(true);
1705 QApplication::setStyle(new QWindowsXPStyle());
1709 if(actionStyleWindowsClassic->isEnabled())
1711 actionStyleWindowsClassic->setChecked(true);
1712 QApplication::setStyle(new QWindowsStyle());
1716 actionStylePlastique->setChecked(true);
1717 QApplication::setStyle(new QPlastiqueStyle());
1721 //Force re-translate after style change
1722 if(QEvent *e = new QEvent(QEvent::LanguageChange))
1730 * Language action triggered
1732 void MainWindow::languageActionActivated(QAction *action)
1734 if(action->data().type() == QVariant::String)
1736 QString langId = action->data().toString();
1738 if(lamexp_install_translator(langId))
1740 action->setChecked(true);
1741 actionLoadTranslationFromFile->setChecked(false);
1742 m_settings->currentLanguage(langId);
1743 m_settings->currentLanguageFile(QString());
1749 * Load language from file action triggered
1751 void MainWindow::languageFromFileActionActivated(bool checked)
1753 QFileDialog dialog(this, tr("Load Translation"));
1754 dialog.setFileMode(QFileDialog::ExistingFile);
1755 dialog.setNameFilter(QString("%1 (*.qm)").arg(tr("Translation Files")));
1759 QStringList selectedFiles = dialog.selectedFiles();
1760 const QString qmFile = QFileInfo(selectedFiles.first()).canonicalFilePath();
1761 if(lamexp_install_translator_from_file(qmFile))
1763 QList<QAction*> actions = m_languageActionGroup->actions();
1764 while(!actions.isEmpty())
1766 actions.takeFirst()->setChecked(false);
1768 actionLoadTranslationFromFile->setChecked(true);
1769 m_settings->currentLanguageFile(qmFile);
1773 languageActionActivated(m_languageActionGroup->actions().first());
1778 // =========================================================
1780 // =========================================================
1783 * Disable update reminder action
1785 void MainWindow::disableUpdateReminderActionTriggered(bool checked)
1789 if(0 == QMessageBox::question(this, tr("Disable Update Reminder"), NOBR(tr("Do you really want to disable the update reminder?")), tr("Yes"), tr("No"), QString(), 1))
1791 QMessageBox::information(this, tr("Update Reminder"), QString("%1<br>%2").arg(NOBR(tr("The update reminder has been disabled.")), NOBR(tr("Please remember to check for updates at regular intervals!"))));
1792 m_settings->autoUpdateEnabled(false);
1796 m_settings->autoUpdateEnabled(true);
1801 QMessageBox::information(this, tr("Update Reminder"), NOBR(tr("The update reminder has been re-enabled.")));
1802 m_settings->autoUpdateEnabled(true);
1805 actionDisableUpdateReminder->setChecked(!m_settings->autoUpdateEnabled());
1809 * Disable sound effects action
1811 void MainWindow::disableSoundsActionTriggered(bool checked)
1815 if(0 == QMessageBox::question(this, tr("Disable Sound Effects"), NOBR(tr("Do you really want to disable all sound effects?")), tr("Yes"), tr("No"), QString(), 1))
1817 QMessageBox::information(this, tr("Sound Effects"), NOBR(tr("All sound effects have been disabled.")));
1818 m_settings->soundsEnabled(false);
1822 m_settings->soundsEnabled(true);
1827 QMessageBox::information(this, tr("Sound Effects"), NOBR(tr("The sound effects have been re-enabled.")));
1828 m_settings->soundsEnabled(true);
1831 actionDisableSounds->setChecked(!m_settings->soundsEnabled());
1835 * Disable Nero AAC encoder action
1837 void MainWindow::disableNeroAacNotificationsActionTriggered(bool checked)
1841 if(0 == QMessageBox::question(this, tr("Nero AAC Notifications"), NOBR(tr("Do you really want to disable all Nero AAC Encoder notifications?")), tr("Yes"), tr("No"), QString(), 1))
1843 QMessageBox::information(this, tr("Nero AAC Notifications"), NOBR(tr("All Nero AAC Encoder notifications have been disabled.")));
1844 m_settings->neroAacNotificationsEnabled(false);
1848 m_settings->neroAacNotificationsEnabled(true);
1853 QMessageBox::information(this, tr("Nero AAC Notifications"), NOBR(tr("The Nero AAC Encoder notifications have been re-enabled.")));
1854 m_settings->neroAacNotificationsEnabled(true);
1857 actionDisableNeroAacNotifications->setChecked(!m_settings->neroAacNotificationsEnabled());
1861 * Disable slow startup action
1863 void MainWindow::disableSlowStartupNotificationsActionTriggered(bool checked)
1867 if(0 == QMessageBox::question(this, tr("Slow Startup Notifications"), NOBR(tr("Do you really want to disable the slow startup notifications?")), tr("Yes"), tr("No"), QString(), 1))
1869 QMessageBox::information(this, tr("Slow Startup Notifications"), NOBR(tr("The slow startup notifications have been disabled.")));
1870 m_settings->antivirNotificationsEnabled(false);
1874 m_settings->antivirNotificationsEnabled(true);
1879 QMessageBox::information(this, tr("Slow Startup Notifications"), NOBR(tr("The slow startup notifications have been re-enabled.")));
1880 m_settings->antivirNotificationsEnabled(true);
1883 actionDisableSlowStartupNotifications->setChecked(!m_settings->antivirNotificationsEnabled());
1887 * Import a Cue Sheet file
1889 void MainWindow::importCueSheetActionTriggered(bool checked)
1898 QString selectedCueFile;
1900 if(USE_NATIVE_FILE_DIALOG)
1902 selectedCueFile = QFileDialog::getOpenFileName(this, tr("Open Cue Sheet"), m_settings->mostRecentInputPath(), QString("%1 (*.cue)").arg(tr("Cue Sheet File")));
1906 QFileDialog dialog(this, tr("Open Cue Sheet"));
1907 dialog.setFileMode(QFileDialog::ExistingFile);
1908 dialog.setNameFilter(QString("%1 (*.cue)").arg(tr("Cue Sheet File")));
1909 dialog.setDirectory(m_settings->mostRecentInputPath());
1912 selectedCueFile = dialog.selectedFiles().first();
1916 if(!selectedCueFile.isEmpty())
1918 m_settings->mostRecentInputPath(QFileInfo(selectedCueFile).canonicalPath());
1919 CueImportDialog *cueImporter = new CueImportDialog(this, m_fileListModel, selectedCueFile);
1920 result = cueImporter->exec();
1921 LAMEXP_DELETE(cueImporter);
1924 if(result != (-1)) break;
1930 * Show the "drop box" widget
1932 void MainWindow::showDropBoxWidgetActionTriggered(bool checked)
1934 m_settings->dropBoxWidgetEnabled(true);
1936 if(!m_dropBox->isVisible())
1941 lamexp_blink_window(m_dropBox);
1945 * Check for beta (pre-release) updates
1947 void MainWindow::checkForBetaUpdatesActionTriggered(bool checked)
1949 bool checkUpdatesNow = false;
1953 if(0 == QMessageBox::question(this, tr("Beta Updates"), NOBR(tr("Do you really want LameXP to check for Beta (pre-release) updates?")), tr("Yes"), tr("No"), QString(), 1))
1955 if(0 == QMessageBox::information(this, tr("Beta Updates"), NOBR(tr("LameXP will check for Beta (pre-release) updates from now on.")), tr("Check Now"), tr("Discard")))
1957 checkUpdatesNow = true;
1959 m_settings->autoUpdateCheckBeta(true);
1963 m_settings->autoUpdateCheckBeta(false);
1968 QMessageBox::information(this, tr("Beta Updates"), NOBR(tr("LameXP will <i>not</i> check for Beta (pre-release) updates from now on.")));
1969 m_settings->autoUpdateCheckBeta(false);
1972 actionCheckForBetaUpdates->setChecked(m_settings->autoUpdateCheckBeta());
1976 if(checkForUpdates())
1978 QApplication::quit();
1984 * Hibernate computer action
1986 void MainWindow::hibernateComputerActionTriggered(bool checked)
1990 if(0 == QMessageBox::question(this, tr("Hibernate Computer"), NOBR(tr("Do you really want the computer to be hibernated on shutdown?")), tr("Yes"), tr("No"), QString(), 1))
1992 QMessageBox::information(this, tr("Hibernate Computer"), NOBR(tr("LameXP will hibernate the computer on shutdown from now on.")));
1993 m_settings->hibernateComputer(true);
1997 m_settings->hibernateComputer(false);
2002 QMessageBox::information(this, tr("Hibernate Computer"), NOBR(tr("LameXP will <i>not</i> hibernate the computer on shutdown from now on.")));
2003 m_settings->hibernateComputer(false);
2006 actionHibernateComputer->setChecked(m_settings->hibernateComputer());
2010 * Disable shell integration action
2012 void MainWindow::disableShellIntegrationActionTriggered(bool checked)
2016 if(0 == QMessageBox::question(this, tr("Shell Integration"), NOBR(tr("Do you really want to disable the LameXP shell integration?")), tr("Yes"), tr("No"), QString(), 1))
2018 ShellIntegration::remove();
2019 QMessageBox::information(this, tr("Shell Integration"), NOBR(tr("The LameXP shell integration has been disabled.")));
2020 m_settings->shellIntegrationEnabled(false);
2024 m_settings->shellIntegrationEnabled(true);
2029 ShellIntegration::install();
2030 QMessageBox::information(this, tr("Shell Integration"), NOBR(tr("The LameXP shell integration has been re-enabled.")));
2031 m_settings->shellIntegrationEnabled(true);
2034 actionDisableShellIntegration->setChecked(!m_settings->shellIntegrationEnabled());
2036 if(lamexp_portable_mode() && actionDisableShellIntegration->isChecked())
2038 actionDisableShellIntegration->setEnabled(false);
2042 // =========================================================
2044 // =========================================================
2047 * Visit homepage action
2049 void MainWindow::visitHomepageActionActivated(void)
2051 if(QAction *action = dynamic_cast<QAction*>(QObject::sender()))
2053 if(action->data().isValid() && (action->data().type() == QVariant::String))
2055 QDesktopServices::openUrl(QUrl(action->data().toString()));
2063 void MainWindow::documentActionActivated(void)
2065 if(QAction *action = dynamic_cast<QAction*>(QObject::sender()))
2067 if(action->data().isValid() && (action->data().type() == QVariant::String))
2069 QFileInfo document(action->data().toString());
2070 QFileInfo resource(QString(":/doc/%1.html").arg(document.baseName()));
2071 if(document.exists() && document.isFile() && (document.size() == resource.size()))
2073 QDesktopServices::openUrl(QUrl::fromLocalFile(document.canonicalFilePath()));
2077 QFile source(resource.filePath());
2078 QFile output(QString("%1/%2.%3.html").arg(lamexp_temp_folder2(), document.baseName(), lamexp_rand_str().left(8)));
2079 if(source.open(QIODevice::ReadOnly) && output.open(QIODevice::ReadWrite))
2081 output.write(source.readAll());
2082 action->setData(output.fileName());
2085 QDesktopServices::openUrl(QUrl::fromLocalFile(output.fileName()));
2093 * Check for updates action
2095 void MainWindow::checkUpdatesActionActivated(void)
2102 bFlag = checkForUpdates();
2107 QApplication::quit();
2111 // =========================================================
2112 // Source file slots
2113 // =========================================================
2116 * Add file(s) button
2118 void MainWindow::addFilesButtonClicked(void)
2124 if(USE_NATIVE_FILE_DIALOG)
2126 QStringList fileTypeFilters = DecoderRegistry::getSupportedTypes();
2127 QStringList selectedFiles = QFileDialog::getOpenFileNames(this, tr("Add file(s)"), m_settings->mostRecentInputPath(), fileTypeFilters.join(";;"));
2128 if(!selectedFiles.isEmpty())
2130 m_settings->mostRecentInputPath(QFileInfo(selectedFiles.first()).canonicalPath());
2131 addFiles(selectedFiles);
2136 QFileDialog dialog(this, tr("Add file(s)"));
2137 QStringList fileTypeFilters = DecoderRegistry::getSupportedTypes();
2138 dialog.setFileMode(QFileDialog::ExistingFiles);
2139 dialog.setNameFilter(fileTypeFilters.join(";;"));
2140 dialog.setDirectory(m_settings->mostRecentInputPath());
2143 QStringList selectedFiles = dialog.selectedFiles();
2144 if(!selectedFiles.isEmpty())
2146 m_settings->mostRecentInputPath(QFileInfo(selectedFiles.first()).canonicalPath());
2147 addFiles(selectedFiles);
2155 * Open folder action
2157 void MainWindow::openFolderActionActivated(void)
2160 QString selectedFolder;
2162 if(QAction *action = dynamic_cast<QAction*>(QObject::sender()))
2166 if(USE_NATIVE_FILE_DIALOG)
2168 selectedFolder = QFileDialog::getExistingDirectory(this, tr("Add Folder"), m_settings->mostRecentInputPath());
2172 QFileDialog dialog(this, tr("Add Folder"));
2173 dialog.setFileMode(QFileDialog::DirectoryOnly);
2174 dialog.setDirectory(m_settings->mostRecentInputPath());
2177 selectedFolder = dialog.selectedFiles().first();
2181 if(!selectedFolder.isEmpty())
2183 m_settings->mostRecentInputPath(QDir(selectedFolder).canonicalPath());
2184 addFolder(selectedFolder, action->data().toBool());
2191 * Remove file button
2193 void MainWindow::removeFileButtonClicked(void)
2195 if(sourceFileView->currentIndex().isValid())
2197 int iRow = sourceFileView->currentIndex().row();
2198 m_fileListModel->removeFile(sourceFileView->currentIndex());
2199 sourceFileView->selectRow(iRow < m_fileListModel->rowCount() ? iRow : m_fileListModel->rowCount()-1);
2204 * Clear files button
2206 void MainWindow::clearFilesButtonClicked(void)
2208 m_fileListModel->clearFiles();
2212 * Move file up button
2214 void MainWindow::fileUpButtonClicked(void)
2216 if(sourceFileView->currentIndex().isValid())
2218 int iRow = sourceFileView->currentIndex().row() - 1;
2219 m_fileListModel->moveFile(sourceFileView->currentIndex(), -1);
2220 sourceFileView->selectRow(iRow >= 0 ? iRow : 0);
2225 * Move file down button
2227 void MainWindow::fileDownButtonClicked(void)
2229 if(sourceFileView->currentIndex().isValid())
2231 int iRow = sourceFileView->currentIndex().row() + 1;
2232 m_fileListModel->moveFile(sourceFileView->currentIndex(), 1);
2233 sourceFileView->selectRow(iRow < m_fileListModel->rowCount() ? iRow : m_fileListModel->rowCount()-1);
2238 * Show details button
2240 void MainWindow::showDetailsButtonClicked(void)
2245 MetaInfoDialog *metaInfoDialog = new MetaInfoDialog(this);
2246 QModelIndex index = sourceFileView->currentIndex();
2248 while(index.isValid())
2252 index = m_fileListModel->index(index.row() + 1, index.column());
2253 sourceFileView->selectRow(index.row());
2257 index = m_fileListModel->index(index.row() - 1, index.column());
2258 sourceFileView->selectRow(index.row());
2261 AudioFileModel &file = (*m_fileListModel)[index];
2264 iResult = metaInfoDialog->exec(file, index.row() > 0, index.row() < m_fileListModel->rowCount() - 1);
2267 if(iResult == INT_MAX)
2269 m_metaInfoModel->assignInfoFrom(file);
2270 tabWidget->setCurrentIndex(tabWidget->indexOf(tabMetaData));
2277 LAMEXP_DELETE(metaInfoDialog);
2278 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
2279 sourceFilesScrollbarMoved(0);
2283 * Show context menu for source files
2285 void MainWindow::sourceFilesContextMenu(const QPoint &pos)
2287 QAbstractScrollArea *scrollArea = dynamic_cast<QAbstractScrollArea*>(QObject::sender());
2288 QWidget *sender = scrollArea ? scrollArea->viewport() : dynamic_cast<QWidget*>(QObject::sender());
2292 if(pos.x() <= sender->width() && pos.y() <= sender->height() && pos.x() >= 0 && pos.y() >= 0)
2294 m_sourceFilesContextMenu->popup(sender->mapToGlobal(pos));
2300 * Scrollbar of source files moved
2302 void MainWindow::sourceFilesScrollbarMoved(int)
2304 sourceFileView->resizeColumnToContents(0);
2308 * Open selected file in external player
2310 void MainWindow::previewContextActionTriggered(void)
2312 const static char *appNames[3] = {"smplayer_portable.exe", "smplayer.exe", "mplayer.exe"};
2313 const static wchar_t *registryKey = L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{DB9E4EAB-2717-499F-8D56-4CC8A644AB60}";
2315 QModelIndex index = sourceFileView->currentIndex();
2316 if(!index.isValid())
2321 QString mplayerPath;
2322 HKEY registryKeyHandle;
2324 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE, registryKey, 0, KEY_READ, ®istryKeyHandle) == ERROR_SUCCESS)
2326 wchar_t Buffer[4096];
2327 DWORD BuffSize = sizeof(wchar_t*) * 4096;
2328 if(RegQueryValueExW(registryKeyHandle, L"InstallLocation", 0, 0, reinterpret_cast<BYTE*>(Buffer), &BuffSize) == ERROR_SUCCESS)
2330 mplayerPath = QString::fromUtf16(reinterpret_cast<const unsigned short*>(Buffer));
2334 if(!mplayerPath.isEmpty())
2336 QDir mplayerDir(mplayerPath);
2337 if(mplayerDir.exists())
2339 for(int i = 0; i < 3; i++)
2341 if(mplayerDir.exists(appNames[i]))
2343 QProcess::startDetached(mplayerDir.absoluteFilePath(appNames[i]), QStringList() << QDir::toNativeSeparators(m_fileListModel->getFile(index).filePath()));
2350 QDesktopServices::openUrl(QString("file:///").append(m_fileListModel->getFile(index).filePath()));
2354 * Find selected file in explorer
2356 void MainWindow::findFileContextActionTriggered(void)
2358 QModelIndex index = sourceFileView->currentIndex();
2361 QString systemRootPath;
2363 QDir systemRoot(lamexp_known_folder(lamexp_folder_systemfolder));
2364 if(systemRoot.exists() && systemRoot.cdUp())
2366 systemRootPath = systemRoot.canonicalPath();
2369 if(!systemRootPath.isEmpty())
2371 QFileInfo explorer(QString("%1/explorer.exe").arg(systemRootPath));
2372 if(explorer.exists() && explorer.isFile())
2374 QProcess::execute(explorer.canonicalFilePath(), QStringList() << "/select," << QDir::toNativeSeparators(m_fileListModel->getFile(index).filePath()));
2380 qWarning("SystemRoot directory could not be detected!");
2386 * Add all pending files
2388 void MainWindow::handleDelayedFiles(void)
2390 m_delayedFileTimer->stop();
2392 if(m_delayedFileList->isEmpty())
2397 if(m_banner->isVisible())
2399 m_delayedFileTimer->start(5000);
2403 QStringList selectedFiles;
2404 tabWidget->setCurrentIndex(0);
2406 while(!m_delayedFileList->isEmpty())
2408 QFileInfo currentFile = QFileInfo(m_delayedFileList->takeFirst());
2409 if(!currentFile.exists() || !currentFile.isFile())
2413 selectedFiles << currentFile.canonicalFilePath();
2416 addFiles(selectedFiles);
2420 * Export Meta tags to CSV file
2422 void MainWindow::exportCsvContextActionTriggered(void)
2426 QString selectedCsvFile;
2428 if(USE_NATIVE_FILE_DIALOG)
2430 selectedCsvFile = QFileDialog::getSaveFileName(this, tr("Save CSV file"), m_settings->mostRecentInputPath(), QString("%1 (*.csv)").arg(tr("CSV File")));
2434 QFileDialog dialog(this, tr("Save CSV file"));
2435 dialog.setFileMode(QFileDialog::AnyFile);
2436 dialog.setAcceptMode(QFileDialog::AcceptSave);
2437 dialog.setNameFilter(QString("%1 (*.csv)").arg(tr("CSV File")));
2438 dialog.setDirectory(m_settings->mostRecentInputPath());
2441 selectedCsvFile = dialog.selectedFiles().first();
2445 if(!selectedCsvFile.isEmpty())
2447 m_settings->mostRecentInputPath(QFileInfo(selectedCsvFile).canonicalPath());
2448 switch(m_fileListModel->exportToCsv(selectedCsvFile))
2450 case FileListModel::CsvError_NoTags:
2451 QMessageBox::critical(this, tr("CSV Export"), NOBR(tr("Sorry, there are no meta tags that can be exported!")));
2453 case FileListModel::CsvError_FileOpen:
2454 QMessageBox::critical(this, tr("CSV Export"), NOBR(tr("Sorry, failed to open CSV file for writing!")));
2456 case FileListModel::CsvError_FileWrite:
2457 QMessageBox::critical(this, tr("CSV Export"), NOBR(tr("Sorry, failed to write to the CSV file!")));
2459 case FileListModel::CsvError_OK:
2460 QMessageBox::information(this, tr("CSV Export"), NOBR(tr("The CSV files was created successfully!")));
2463 qWarning("exportToCsv: Unknown return code!");
2471 * Import Meta tags from CSV file
2473 void MainWindow::importCsvContextActionTriggered(void)
2477 QString selectedCsvFile;
2479 if(USE_NATIVE_FILE_DIALOG)
2481 selectedCsvFile = QFileDialog::getOpenFileName(this, tr("Open CSV file"), m_settings->mostRecentInputPath(), QString("%1 (*.csv)").arg(tr("CSV File")));
2485 QFileDialog dialog(this, tr("Open CSV file"));
2486 dialog.setFileMode(QFileDialog::ExistingFile);
2487 dialog.setNameFilter(QString("%1 (*.csv)").arg(tr("CSV File")));
2488 dialog.setDirectory(m_settings->mostRecentInputPath());
2491 selectedCsvFile = dialog.selectedFiles().first();
2495 if(!selectedCsvFile.isEmpty())
2497 m_settings->mostRecentInputPath(QFileInfo(selectedCsvFile).canonicalPath());
2498 switch(m_fileListModel->importFromCsv(this, selectedCsvFile))
2500 case FileListModel::CsvError_FileOpen:
2501 QMessageBox::critical(this, tr("CSV Import"), NOBR(tr("Sorry, failed to open CSV file for reading!")));
2503 case FileListModel::CsvError_FileRead:
2504 QMessageBox::critical(this, tr("CSV Import"), NOBR(tr("Sorry, failed to read from the CSV file!")));
2506 case FileListModel::CsvError_NoTags:
2507 QMessageBox::critical(this, tr("CSV Import"), NOBR(tr("Sorry, the CSV file does not contain any known fields!")));
2509 case FileListModel::CsvError_Incomplete:
2510 QMessageBox::warning(this, tr("CSV Import"), NOBR(tr("CSV file is incomplete. Not all files were updated!")));
2512 case FileListModel::CsvError_OK:
2513 QMessageBox::information(this, tr("CSV Import"), NOBR(tr("The CSV files was imported successfully!")));
2515 case FileListModel::CsvError_Aborted:
2516 /* User aborted, ignore! */
2519 qWarning("exportToCsv: Unknown return code!");
2526 * Show or hide Drag'n'Drop notice after model reset
2528 void MainWindow::sourceModelChanged(void)
2530 m_dropNoteLabel->setVisible(m_fileListModel->rowCount() <= 0);
2533 // =========================================================
2534 // Output folder slots
2535 // =========================================================
2538 * Output folder changed (mouse clicked)
2540 void MainWindow::outputFolderViewClicked(const QModelIndex &index)
2542 if(index.isValid() && (outputFolderView->currentIndex() != index))
2544 outputFolderView->setCurrentIndex(index);
2547 if(m_fileSystemModel && index.isValid())
2549 QString selectedDir = m_fileSystemModel->filePath(index);
2550 if(selectedDir.length() < 3) selectedDir.append(QDir::separator());
2551 outputFolderLabel->setText(QDir::toNativeSeparators(selectedDir));
2552 m_settings->outputDir(selectedDir);
2556 outputFolderLabel->setText(QDir::toNativeSeparators(m_settings->outputDir()));
2561 * Output folder changed (mouse moved)
2563 void MainWindow::outputFolderViewMoved(const QModelIndex &index)
2565 if(QApplication::mouseButtons() & Qt::LeftButton)
2567 outputFolderViewClicked(index);
2572 * Goto desktop button
2574 void MainWindow::gotoDesktopButtonClicked(void)
2576 if(!m_fileSystemModel)
2578 qWarning("File system model not initialized yet!");
2582 QString desktopPath = QDesktopServices::storageLocation(QDesktopServices::DesktopLocation);
2584 if(!desktopPath.isEmpty() && QDir(desktopPath).exists())
2586 outputFolderView->setCurrentIndex(m_fileSystemModel->index(desktopPath));
2587 outputFolderViewClicked(outputFolderView->currentIndex());
2588 CENTER_CURRENT_OUTPUT_FOLDER_DELAYED;
2592 buttonGotoDesktop->setEnabled(false);
2597 * Goto home folder button
2599 void MainWindow::gotoHomeFolderButtonClicked(void)
2601 if(!m_fileSystemModel)
2603 qWarning("File system model not initialized yet!");
2607 QString homePath = QDesktopServices::storageLocation(QDesktopServices::HomeLocation);
2609 if(!homePath.isEmpty() && QDir(homePath).exists())
2611 outputFolderView->setCurrentIndex(m_fileSystemModel->index(homePath));
2612 outputFolderViewClicked(outputFolderView->currentIndex());
2613 CENTER_CURRENT_OUTPUT_FOLDER_DELAYED;
2617 buttonGotoHome->setEnabled(false);
2622 * Goto music folder button
2624 void MainWindow::gotoMusicFolderButtonClicked(void)
2626 if(!m_fileSystemModel)
2628 qWarning("File system model not initialized yet!");
2632 QString musicPath = QDesktopServices::storageLocation(QDesktopServices::MusicLocation);
2634 if(!musicPath.isEmpty() && QDir(musicPath).exists())
2636 outputFolderView->setCurrentIndex(m_fileSystemModel->index(musicPath));
2637 outputFolderViewClicked(outputFolderView->currentIndex());
2638 CENTER_CURRENT_OUTPUT_FOLDER_DELAYED;
2642 buttonGotoMusic->setEnabled(false);
2647 * Goto music favorite output folder
2649 void MainWindow::gotoFavoriteFolder(void)
2651 if(!m_fileSystemModel)
2653 qWarning("File system model not initialized yet!");
2657 QAction *item = dynamic_cast<QAction*>(QObject::sender());
2661 QDir path(item->data().toString());
2664 outputFolderView->setCurrentIndex(m_fileSystemModel->index(path.canonicalPath()));
2665 outputFolderViewClicked(outputFolderView->currentIndex());
2666 CENTER_CURRENT_OUTPUT_FOLDER_DELAYED;
2670 MessageBeep(MB_ICONERROR);
2671 m_outputFolderFavoritesMenu->removeAction(item);
2672 item->deleteLater();
2678 * Make folder button
2680 void MainWindow::makeFolderButtonClicked(void)
2684 if(!m_fileSystemModel)
2686 qWarning("File system model not initialized yet!");
2690 QDir basePath(m_fileSystemModel->fileInfo(outputFolderView->currentIndex()).absoluteFilePath());
2691 QString suggestedName = tr("New Folder");
2693 if(!m_metaData->fileArtist().isEmpty() && !m_metaData->fileAlbum().isEmpty())
2695 suggestedName = QString("%1 - %2").arg(m_metaData->fileArtist(), m_metaData->fileAlbum());
2697 else if(!m_metaData->fileArtist().isEmpty())
2699 suggestedName = m_metaData->fileArtist();
2701 else if(!m_metaData->fileAlbum().isEmpty())
2703 suggestedName = m_metaData->fileAlbum();
2707 for(int i = 0; i < m_fileListModel->rowCount(); i++)
2709 AudioFileModel audioFile = m_fileListModel->getFile(m_fileListModel->index(i, 0));
2710 if(!audioFile.fileAlbum().isEmpty() || !audioFile.fileArtist().isEmpty())
2712 if(!audioFile.fileArtist().isEmpty() && !audioFile.fileAlbum().isEmpty())
2714 suggestedName = QString("%1 - %2").arg(audioFile.fileArtist(), audioFile.fileAlbum());
2716 else if(!audioFile.fileArtist().isEmpty())
2718 suggestedName = audioFile.fileArtist();
2720 else if(!audioFile.fileAlbum().isEmpty())
2722 suggestedName = audioFile.fileAlbum();
2729 suggestedName = lamexp_clean_filename(suggestedName);
2733 bool bApplied = false;
2734 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();
2738 folderName = lamexp_clean_filepath(folderName.simplified());
2740 if(folderName.isEmpty())
2742 MessageBeep(MB_ICONERROR);
2747 QString newFolder = folderName;
2749 while(basePath.exists(newFolder))
2751 newFolder = QString(folderName).append(QString().sprintf(" (%d)", ++i));
2754 if(basePath.mkpath(newFolder))
2756 QDir createdDir = basePath;
2757 if(createdDir.cd(newFolder))
2759 QModelIndex newIndex = m_fileSystemModel->index(createdDir.canonicalPath());
2760 outputFolderView->setCurrentIndex(newIndex);
2761 outputFolderViewClicked(newIndex);
2762 CENTER_CURRENT_OUTPUT_FOLDER_DELAYED;
2767 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!")));
2775 * Output to source dir changed
2777 void MainWindow::saveToSourceFolderChanged(void)
2779 m_settings->outputToSourceDir(saveToSourceFolderCheckBox->isChecked());
2783 * Prepend relative source file path to output file name changed
2785 void MainWindow::prependRelativePathChanged(void)
2787 m_settings->prependRelativeSourcePath(prependRelativePathCheckBox->isChecked());
2791 * Show context menu for output folder
2793 void MainWindow::outputFolderContextMenu(const QPoint &pos)
2795 QAbstractScrollArea *scrollArea = dynamic_cast<QAbstractScrollArea*>(QObject::sender());
2796 QWidget *sender = scrollArea ? scrollArea->viewport() : dynamic_cast<QWidget*>(QObject::sender());
2798 if(pos.x() <= sender->width() && pos.y() <= sender->height() && pos.x() >= 0 && pos.y() >= 0)
2800 m_outputFolderContextMenu->popup(sender->mapToGlobal(pos));
2805 * Show selected folder in explorer
2807 void MainWindow::showFolderContextActionTriggered(void)
2809 if(!m_fileSystemModel)
2811 qWarning("File system model not initialized yet!");
2815 QString path = QDir::toNativeSeparators(m_fileSystemModel->filePath(outputFolderView->currentIndex()));
2816 if(!path.endsWith(QDir::separator())) path.append(QDir::separator());
2817 ShellExecuteW(reinterpret_cast<HWND>(this->winId()), L"explore", QWCHAR(path), NULL, NULL, SW_SHOW);
2821 * Refresh the directory outline
2823 void MainWindow::refreshFolderContextActionTriggered(void)
2825 //force re-initialization
2826 QTimer::singleShot(0, this, SLOT(initOutputFolderModel()));
2830 * Add current folder to favorites
2832 void MainWindow::addFavoriteFolderActionTriggered(void)
2834 QString path = m_fileSystemModel->filePath(outputFolderView->currentIndex());
2835 QStringList favorites = m_settings->favoriteOutputFolders().split("|", QString::SkipEmptyParts);
2837 if(!favorites.contains(path, Qt::CaseInsensitive))
2839 favorites.append(path);
2840 while(favorites.count() > 6) favorites.removeFirst();
2844 MessageBeep(MB_ICONWARNING);
2847 m_settings->favoriteOutputFolders(favorites.join("|"));
2852 * Output folder edit finished
2854 void MainWindow::outputFolderEditFinished(void)
2856 if(outputFolderEdit->isHidden())
2858 return; //Not currently in edit mode!
2863 QString text = QDir::fromNativeSeparators(outputFolderEdit->text().trimmed());
2864 while(text.startsWith('"') || text.startsWith('/')) text = text.right(text.length() - 1).trimmed();
2865 while(text.endsWith('"') || text.endsWith('/')) text = text.left(text.length() - 1).trimmed();
2867 static const char *str = "?*<>|\"";
2868 for(size_t i = 0; str[i]; i++) text.replace(str[i], "_");
2870 if(!((text.length() >= 2) && text.at(0).isLetter() && text.at(1) == QChar(':')))
2872 text = QString("%1/%2").arg(QDir::fromNativeSeparators(outputFolderLabel->text()), text);
2875 if(text.length() == 2) text += "/"; /* "X:" => "X:/" */
2877 while(text.length() > 2)
2879 QFileInfo info(text);
2880 if(info.exists() && info.isDir())
2882 QModelIndex index = m_fileSystemModel->index(QFileInfo(info.canonicalFilePath()).absoluteFilePath());
2886 outputFolderView->setCurrentIndex(index);
2887 outputFolderViewClicked(index);
2891 else if(info.exists() && info.isFile())
2893 QModelIndex index = m_fileSystemModel->index(QFileInfo(info.canonicalPath()).absoluteFilePath());
2897 outputFolderView->setCurrentIndex(index);
2898 outputFolderViewClicked(index);
2903 text = text.left(text.length() - 1).trimmed();
2906 outputFolderEdit->setVisible(false);
2907 outputFolderLabel->setVisible(true);
2908 outputFolderView->setEnabled(true);
2910 if(!ok) MessageBeep(MB_ICONERROR);
2911 CENTER_CURRENT_OUTPUT_FOLDER_DELAYED;
2915 * Initialize file system model
2917 void MainWindow::initOutputFolderModel(void)
2919 if(m_outputFolderNoteBox->isHidden())
2921 m_outputFolderNoteBox->show();
2922 m_outputFolderNoteBox->repaint();
2923 m_outputFolderViewInitCounter = 4;
2925 if(m_fileSystemModel)
2927 SET_MODEL(outputFolderView, NULL);
2928 LAMEXP_DELETE(m_fileSystemModel);
2929 outputFolderView->repaint();
2932 if(m_fileSystemModel = new QFileSystemModelEx())
2934 m_fileSystemModel->installEventFilter(this);
2935 connect(m_fileSystemModel, SIGNAL(directoryLoaded(QString)), this, SLOT(outputFolderDirectoryLoaded(QString)));
2936 connect(m_fileSystemModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(outputFolderRowsInserted(QModelIndex,int,int)));
2938 SET_MODEL(outputFolderView, m_fileSystemModel);
2939 outputFolderView->header()->setStretchLastSection(true);
2940 outputFolderView->header()->hideSection(1);
2941 outputFolderView->header()->hideSection(2);
2942 outputFolderView->header()->hideSection(3);
2944 m_fileSystemModel->setRootPath("");
2945 QModelIndex index = m_fileSystemModel->index(m_settings->outputDir());
2946 if(index.isValid()) outputFolderView->setCurrentIndex(index);
2947 outputFolderViewClicked(outputFolderView->currentIndex());
2950 CENTER_CURRENT_OUTPUT_FOLDER_DELAYED;
2951 QTimer::singleShot(125, this, SLOT(initOutputFolderModel_doAsync()));
2956 * Initialize file system model (do NOT call this one directly!)
2958 void MainWindow::initOutputFolderModel_doAsync(void)
2960 if(m_outputFolderViewInitCounter > 0)
2962 m_outputFolderViewInitCounter--;
2963 QTimer::singleShot(125, this, SLOT(initOutputFolderModel_doAsync()));
2967 QTimer::singleShot(125, m_outputFolderNoteBox, SLOT(hide()));
2968 outputFolderView->setFocus();
2973 * Center current folder in view
2975 void MainWindow::centerOutputFolderModel(void)
2977 if(outputFolderView->isVisible())
2979 centerOutputFolderModel_doAsync();
2980 QTimer::singleShot(125, this, SLOT(centerOutputFolderModel_doAsync()));
2985 * Center current folder in view (do NOT call this one directly!)
2987 void MainWindow::centerOutputFolderModel_doAsync(void)
2989 if(outputFolderView->isVisible())
2991 m_outputFolderViewCentering = true;
2992 const QModelIndex index = outputFolderView->currentIndex();
2993 outputFolderView->scrollTo(index, QAbstractItemView::PositionAtCenter);
2994 outputFolderView->setFocus();
2999 * File system model asynchronously loaded a dir
3001 void MainWindow::outputFolderDirectoryLoaded(const QString &path)
3003 if(m_outputFolderViewCentering)
3005 CENTER_CURRENT_OUTPUT_FOLDER_DELAYED;
3010 * File system model inserted new items
3012 void MainWindow::outputFolderRowsInserted(const QModelIndex &parent, int start, int end)
3014 if(m_outputFolderViewCentering)
3016 CENTER_CURRENT_OUTPUT_FOLDER_DELAYED;
3021 * Directory view item was expanded by user
3023 void MainWindow::outputFolderItemExpanded(const QModelIndex &item)
3025 //We need to stop centering as soon as the user has expanded an item manually!
3026 m_outputFolderViewCentering = false;
3030 * View event for output folder control occurred
3032 void MainWindow::outputFolderViewEventOccurred(QWidget *sender, QEvent *event)
3034 switch(event->type())
3038 case QEvent::KeyPress:
3039 case QEvent::KeyRelease:
3040 case QEvent::FocusIn:
3041 case QEvent::FocusOut:
3042 case QEvent::TouchEnd:
3043 outputFolderViewClicked(outputFolderView->currentIndex());
3049 * Mouse event for output folder control occurred
3051 void MainWindow::outputFolderMouseEventOccurred(QWidget *sender, QEvent *event)
3053 QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event);
3054 QPoint pos = (mouseEvent) ? mouseEvent->pos() : QPoint();
3056 if(sender == outputFolderLabel)
3058 switch(event->type())
3060 case QEvent::MouseButtonPress:
3061 if(mouseEvent && (mouseEvent->button() == Qt::LeftButton))
3063 QString path = outputFolderLabel->text();
3064 if(!path.endsWith(QDir::separator())) path.append(QDir::separator());
3065 ShellExecuteW(reinterpret_cast<HWND>(this->winId()), L"explore", QWCHAR(path), NULL, NULL, SW_SHOW);
3069 outputFolderLabel->setForegroundRole(QPalette::Link);
3072 outputFolderLabel->setForegroundRole(QPalette::WindowText);
3076 else if(sender == outputFoldersFovoritesLabel)
3078 switch(event->type())
3081 outputFoldersFovoritesLabel->setFrameShadow(QFrame::Raised);
3083 case QEvent::MouseButtonPress:
3084 outputFoldersFovoritesLabel->setFrameShadow(QFrame::Sunken);
3086 case QEvent::MouseButtonRelease:
3087 outputFoldersFovoritesLabel->setFrameShadow(QFrame::Raised);
3090 if(pos.x() <= sender->width() && pos.y() <= sender->height() && pos.x() >= 0 && pos.y() >= 0 && mouseEvent->button() != Qt::MidButton)
3092 if(outputFolderView->isEnabled())
3094 m_outputFolderFavoritesMenu->popup(sender->mapToGlobal(pos));
3100 outputFoldersFovoritesLabel->setFrameShadow(QFrame::Plain);
3104 else if(sender == outputFoldersEditorLabel)
3106 switch(event->type())
3109 outputFoldersEditorLabel->setFrameShadow(QFrame::Raised);
3111 case QEvent::MouseButtonPress:
3112 outputFoldersEditorLabel->setFrameShadow(QFrame::Sunken);
3114 case QEvent::MouseButtonRelease:
3115 outputFoldersEditorLabel->setFrameShadow(QFrame::Raised);
3118 if(pos.x() <= sender->width() && pos.y() <= sender->height() && pos.x() >= 0 && pos.y() >= 0 && mouseEvent->button() != Qt::MidButton)
3120 if(outputFolderView->isEnabled())
3122 outputFolderView->setEnabled(false);
3123 outputFolderLabel->setVisible(false);
3124 outputFolderEdit->setVisible(true);
3125 outputFolderEdit->setText(outputFolderLabel->text());
3126 outputFolderEdit->selectAll();
3127 outputFolderEdit->setFocus();
3133 outputFoldersEditorLabel->setFrameShadow(QFrame::Plain);
3139 // =========================================================
3140 // Metadata tab slots
3141 // =========================================================
3144 * Edit meta button clicked
3146 void MainWindow::editMetaButtonClicked(void)
3150 const QModelIndex index = metaDataView->currentIndex();
3154 m_metaInfoModel->editItem(index, this);
3156 if(index.row() == 4)
3158 m_settings->metaInfoPosition(m_metaData->filePosition());
3164 * Reset meta button clicked
3166 void MainWindow::clearMetaButtonClicked(void)
3169 m_metaInfoModel->clearData();
3173 * Meta tags enabled changed
3175 void MainWindow::metaTagsEnabledChanged(void)
3177 m_settings->writeMetaTags(writeMetaDataCheckBox->isChecked());
3181 * Playlist enabled changed
3183 void MainWindow::playlistEnabledChanged(void)
3185 m_settings->createPlaylist(generatePlaylistCheckBox->isChecked());
3188 // =========================================================
3189 // Compression tab slots
3190 // =========================================================
3195 void MainWindow::updateEncoder(int id)
3197 m_settings->compressionEncoder(id);
3199 switch(m_settings->compressionEncoder())
3201 case SettingsModel::VorbisEncoder:
3202 radioButtonModeQuality->setEnabled(true);
3203 radioButtonModeAverageBitrate->setEnabled(true);
3204 radioButtonConstBitrate->setEnabled(false);
3205 if(radioButtonConstBitrate->isChecked()) radioButtonModeQuality->setChecked(true);
3206 sliderBitrate->setEnabled(true);
3208 case SettingsModel::AC3Encoder:
3209 radioButtonModeQuality->setEnabled(true);
3210 radioButtonModeQuality->setChecked(true);
3211 radioButtonModeAverageBitrate->setEnabled(false);
3212 radioButtonConstBitrate->setEnabled(true);
3213 sliderBitrate->setEnabled(true);
3215 case SettingsModel::FLACEncoder:
3216 radioButtonModeQuality->setEnabled(false);
3217 radioButtonModeQuality->setChecked(true);
3218 radioButtonModeAverageBitrate->setEnabled(false);
3219 radioButtonConstBitrate->setEnabled(false);
3220 sliderBitrate->setEnabled(true);
3222 case SettingsModel::PCMEncoder:
3223 radioButtonModeQuality->setEnabled(false);
3224 radioButtonModeQuality->setChecked(true);
3225 radioButtonModeAverageBitrate->setEnabled(false);
3226 radioButtonConstBitrate->setEnabled(false);
3227 sliderBitrate->setEnabled(false);
3229 case SettingsModel::AACEncoder:
3230 radioButtonModeQuality->setEnabled(true);
3231 radioButtonModeAverageBitrate->setEnabled(!m_fhgEncoderAvailable);
3232 if(m_fhgEncoderAvailable && radioButtonModeAverageBitrate->isChecked()) radioButtonConstBitrate->setChecked(true);
3233 radioButtonConstBitrate->setEnabled(true);
3234 sliderBitrate->setEnabled(true);
3236 case SettingsModel::DCAEncoder:
3237 radioButtonModeQuality->setEnabled(false);
3238 radioButtonModeAverageBitrate->setEnabled(false);
3239 radioButtonConstBitrate->setEnabled(true);
3240 radioButtonConstBitrate->setChecked(true);
3241 sliderBitrate->setEnabled(true);
3244 radioButtonModeQuality->setEnabled(true);
3245 radioButtonModeAverageBitrate->setEnabled(true);
3246 radioButtonConstBitrate->setEnabled(true);
3247 sliderBitrate->setEnabled(true);
3251 if(m_settings->compressionEncoder() == SettingsModel::AACEncoder)
3253 const QString encoderName = m_qaacEncoderAvailable ? tr("QAAC (Apple)") : (m_fhgEncoderAvailable ? tr("FHG AAC (Winamp)") : (m_neroEncoderAvailable ? tr("Nero AAC") : tr("Not available!")));
3254 labelEncoderInfo->setVisible(true);
3255 labelEncoderInfo->setText(tr("Current AAC Encoder: %1").arg(encoderName));
3259 labelEncoderInfo->setVisible(false);
3262 updateRCMode(m_modeButtonGroup->checkedId());
3266 * Update rate-control mode
3268 void MainWindow::updateRCMode(int id)
3270 m_settings->compressionRCMode(id);
3272 switch(m_settings->compressionEncoder())
3274 case SettingsModel::MP3Encoder:
3275 switch(m_settings->compressionRCMode())
3277 case SettingsModel::VBRMode:
3278 sliderBitrate->setMinimum(0);
3279 sliderBitrate->setMaximum(9);
3282 sliderBitrate->setMinimum(0);
3283 sliderBitrate->setMaximum(13);
3287 case SettingsModel::VorbisEncoder:
3288 switch(m_settings->compressionRCMode())
3290 case SettingsModel::VBRMode:
3291 sliderBitrate->setMinimum(-2);
3292 sliderBitrate->setMaximum(10);
3295 sliderBitrate->setMinimum(4);
3296 sliderBitrate->setMaximum(63);
3300 case SettingsModel::AC3Encoder:
3301 switch(m_settings->compressionRCMode())
3303 case SettingsModel::VBRMode:
3304 sliderBitrate->setMinimum(0);
3305 sliderBitrate->setMaximum(16);
3308 sliderBitrate->setMinimum(0);
3309 sliderBitrate->setMaximum(18);
3313 case SettingsModel::AACEncoder:
3314 switch(m_settings->compressionRCMode())
3316 case SettingsModel::VBRMode:
3317 sliderBitrate->setMinimum(0);
3318 sliderBitrate->setMaximum(20);
3321 sliderBitrate->setMinimum(4);
3322 sliderBitrate->setMaximum(63);
3326 case SettingsModel::FLACEncoder:
3327 sliderBitrate->setMinimum(0);
3328 sliderBitrate->setMaximum(8);
3330 case SettingsModel::OpusEncoder:
3331 sliderBitrate->setMinimum(1);
3332 sliderBitrate->setMaximum(32);
3334 case SettingsModel::DCAEncoder:
3335 sliderBitrate->setMinimum(1);
3336 sliderBitrate->setMaximum(128);
3338 case SettingsModel::PCMEncoder:
3339 sliderBitrate->setMinimum(0);
3340 sliderBitrate->setMaximum(2);
3341 sliderBitrate->setValue(1);
3344 sliderBitrate->setMinimum(0);
3345 sliderBitrate->setMaximum(0);
3349 updateBitrate(sliderBitrate->value());
3355 void MainWindow::updateBitrate(int value)
3357 m_settings->compressionBitrate(value);
3359 switch(m_settings->compressionRCMode())
3361 case SettingsModel::VBRMode:
3362 switch(m_settings->compressionEncoder())
3364 case SettingsModel::MP3Encoder:
3365 labelBitrate->setText(tr("Quality Level %1").arg(9 - value));
3367 case SettingsModel::VorbisEncoder:
3368 labelBitrate->setText(tr("Quality Level %1").arg(value));
3370 case SettingsModel::AACEncoder:
3371 labelBitrate->setText(tr("Quality Level %1").arg(QString().sprintf("%.2f", static_cast<double>(value * 5) / 100.0)));
3373 case SettingsModel::FLACEncoder:
3374 labelBitrate->setText(tr("Compression %1").arg(value));
3376 case SettingsModel::OpusEncoder:
3377 labelBitrate->setText(QString("≈ %1 kbps").arg(qMin(500, value * 8)));
3379 case SettingsModel::AC3Encoder:
3380 labelBitrate->setText(tr("Quality Level %1").arg(qMin(1024, qMax(0, value * 64))));
3382 case SettingsModel::PCMEncoder:
3383 labelBitrate->setText(tr("Uncompressed"));
3386 labelBitrate->setText(QString::number(value));
3390 case SettingsModel::ABRMode:
3391 switch(m_settings->compressionEncoder())
3393 case SettingsModel::MP3Encoder:
3394 labelBitrate->setText(QString("≈ %1 kbps").arg(SettingsModel::mp3Bitrates[value]));
3396 case SettingsModel::FLACEncoder:
3397 labelBitrate->setText(tr("Compression %1").arg(value));
3399 case SettingsModel::AC3Encoder:
3400 labelBitrate->setText(QString("≈ %1 kbps").arg(SettingsModel::ac3Bitrates[value]));
3402 case SettingsModel::PCMEncoder:
3403 labelBitrate->setText(tr("Uncompressed"));
3406 labelBitrate->setText(QString("≈ %1 kbps").arg(qMin(500, value * 8)));
3411 switch(m_settings->compressionEncoder())
3413 case SettingsModel::MP3Encoder:
3414 labelBitrate->setText(QString("%1 kbps").arg(SettingsModel::mp3Bitrates[value]));
3416 case SettingsModel::FLACEncoder:
3417 labelBitrate->setText(tr("Compression %1").arg(value));
3419 case SettingsModel::AC3Encoder:
3420 labelBitrate->setText(QString("%1 kbps").arg(SettingsModel::ac3Bitrates[value]));
3422 case SettingsModel::DCAEncoder:
3423 labelBitrate->setText(QString("%1 kbps").arg(value * 32));
3425 case SettingsModel::PCMEncoder:
3426 labelBitrate->setText(tr("Uncompressed"));
3429 labelBitrate->setText(QString("%1 kbps").arg(qMin(500, value * 8)));
3437 * Event for compression tab occurred
3439 void MainWindow::compressionTabEventOccurred(QWidget *sender, QEvent *event)
3441 static const QUrl helpUrl("http://lamexp.sourceforge.net/doc/FAQ.html#054010d9");
3443 if((sender == labelCompressionHelp) && (event->type() == QEvent::MouseButtonPress))
3445 QDesktopServices::openUrl(helpUrl);
3449 // =========================================================
3450 // Advanced option slots
3451 // =========================================================
3454 * Lame algorithm quality changed
3456 void MainWindow::updateLameAlgoQuality(int value)
3463 text = tr("Best Quality (Very Slow)");
3466 text = tr("High Quality (Recommended)");
3469 text = tr("Average Quality (Default)");
3472 text = tr("Low Quality (Fast)");
3475 text = tr("Poor Quality (Very Fast)");
3481 m_settings->lameAlgoQuality(value);
3482 labelLameAlgoQuality->setText(text);
3485 bool warning = (value == 0), notice = (value == 4);
3486 labelLameAlgoQualityWarning->setVisible(warning);
3487 labelLameAlgoQualityWarningIcon->setVisible(warning);
3488 labelLameAlgoQualityNotice->setVisible(notice);
3489 labelLameAlgoQualityNoticeIcon->setVisible(notice);
3490 labelLameAlgoQualitySpacer->setVisible(warning || notice);
3494 * Bitrate management endabled/disabled
3496 void MainWindow::bitrateManagementEnabledChanged(bool checked)
3498 m_settings->bitrateManagementEnabled(checked);
3502 * Minimum bitrate has changed
3504 void MainWindow::bitrateManagementMinChanged(int value)
3506 if(value > spinBoxBitrateManagementMax->value())
3508 spinBoxBitrateManagementMin->setValue(spinBoxBitrateManagementMax->value());
3509 m_settings->bitrateManagementMinRate(spinBoxBitrateManagementMax->value());
3513 m_settings->bitrateManagementMinRate(value);
3518 * Maximum bitrate has changed
3520 void MainWindow::bitrateManagementMaxChanged(int value)
3522 if(value < spinBoxBitrateManagementMin->value())
3524 spinBoxBitrateManagementMax->setValue(spinBoxBitrateManagementMin->value());
3525 m_settings->bitrateManagementMaxRate(spinBoxBitrateManagementMin->value());
3529 m_settings->bitrateManagementMaxRate(value);
3534 * Channel mode has changed
3536 void MainWindow::channelModeChanged(int value)
3538 if(value >= 0) m_settings->lameChannelMode(value);
3542 * Sampling rate has changed
3544 void MainWindow::samplingRateChanged(int value)
3546 if(value >= 0) m_settings->samplingRate(value);
3550 * Nero AAC 2-Pass mode changed
3552 void MainWindow::neroAAC2PassChanged(bool checked)
3554 m_settings->neroAACEnable2Pass(checked);
3558 * Nero AAC profile mode changed
3560 void MainWindow::neroAACProfileChanged(int value)
3562 if(value >= 0) m_settings->aacEncProfile(value);
3566 * Aften audio coding mode changed
3568 void MainWindow::aftenCodingModeChanged(int value)
3570 if(value >= 0) m_settings->aftenAudioCodingMode(value);
3574 * Aften DRC mode changed
3576 void MainWindow::aftenDRCModeChanged(int value)
3578 if(value >= 0) m_settings->aftenDynamicRangeCompression(value);
3582 * Aften exponent search size changed
3584 void MainWindow::aftenSearchSizeChanged(int value)
3586 if(value >= 0) m_settings->aftenExponentSearchSize(value);
3590 * Aften fast bit allocation changed
3592 void MainWindow::aftenFastAllocationChanged(bool checked)
3594 m_settings->aftenFastBitAllocation(checked);
3599 * Opus encoder settings changed
3601 void MainWindow::opusSettingsChanged(void)
3603 m_settings->opusOptimizeFor(comboBoxOpusOptimize->currentIndex());
3604 m_settings->opusFramesize(comboBoxOpusFramesize->currentIndex());
3605 m_settings->opusComplexity(spinBoxOpusComplexity->value());
3606 m_settings->opusExpAnalysis(checkBoxOpusExpAnalysis->isChecked());
3610 * Normalization filter enabled changed
3612 void MainWindow::normalizationEnabledChanged(bool checked)
3614 m_settings->normalizationFilterEnabled(checked);
3618 * Normalization max. volume changed
3620 void MainWindow::normalizationMaxVolumeChanged(double value)
3622 m_settings->normalizationFilterMaxVolume(static_cast<int>(value * 100.0));
3626 * Normalization equalization mode changed
3628 void MainWindow::normalizationModeChanged(int mode)
3630 m_settings->normalizationFilterEqualizationMode(mode);
3634 * Tone adjustment has changed (Bass)
3636 void MainWindow::toneAdjustBassChanged(double value)
3638 m_settings->toneAdjustBass(static_cast<int>(value * 100.0));
3639 spinBoxToneAdjustBass->setPrefix((value > 0) ? "+" : QString());
3643 * Tone adjustment has changed (Treble)
3645 void MainWindow::toneAdjustTrebleChanged(double value)
3647 m_settings->toneAdjustTreble(static_cast<int>(value * 100.0));
3648 spinBoxToneAdjustTreble->setPrefix((value > 0) ? "+" : QString());
3652 * Tone adjustment has been reset
3654 void MainWindow::toneAdjustTrebleReset(void)
3656 spinBoxToneAdjustBass->setValue(m_settings->toneAdjustBassDefault());
3657 spinBoxToneAdjustTreble->setValue(m_settings->toneAdjustTrebleDefault());
3658 toneAdjustBassChanged(spinBoxToneAdjustBass->value());
3659 toneAdjustTrebleChanged(spinBoxToneAdjustTreble->value());
3663 * Custom encoder parameters changed
3665 void MainWindow::customParamsChanged(void)
3667 lineEditCustomParamLAME->setText(lineEditCustomParamLAME->text().simplified());
3668 lineEditCustomParamOggEnc->setText(lineEditCustomParamOggEnc->text().simplified());
3669 lineEditCustomParamNeroAAC->setText(lineEditCustomParamNeroAAC->text().simplified());
3670 lineEditCustomParamFLAC->setText(lineEditCustomParamFLAC->text().simplified());
3671 lineEditCustomParamAften->setText(lineEditCustomParamAften->text().simplified());
3672 lineEditCustomParamOpus->setText(lineEditCustomParamOpus->text().simplified());
3674 bool customParamsUsed = false;
3675 if(!lineEditCustomParamLAME->text().isEmpty()) customParamsUsed = true;
3676 if(!lineEditCustomParamOggEnc->text().isEmpty()) customParamsUsed = true;
3677 if(!lineEditCustomParamNeroAAC->text().isEmpty()) customParamsUsed = true;
3678 if(!lineEditCustomParamFLAC->text().isEmpty()) customParamsUsed = true;
3679 if(!lineEditCustomParamAften->text().isEmpty()) customParamsUsed = true;
3680 if(!lineEditCustomParamOpus->text().isEmpty()) customParamsUsed = true;
3682 labelCustomParamsIcon->setVisible(customParamsUsed);
3683 labelCustomParamsText->setVisible(customParamsUsed);
3684 labelCustomParamsSpacer->setVisible(customParamsUsed);
3686 m_settings->customParametersLAME(lineEditCustomParamLAME->text());
3687 m_settings->customParametersOggEnc(lineEditCustomParamOggEnc->text());
3688 m_settings->customParametersAacEnc(lineEditCustomParamNeroAAC->text());
3689 m_settings->customParametersFLAC(lineEditCustomParamFLAC->text());
3690 m_settings->customParametersAften(lineEditCustomParamAften->text());
3691 m_settings->customParametersOpus(lineEditCustomParamOpus->text());
3695 * Rename output files enabled changed
3697 void MainWindow::renameOutputEnabledChanged(bool checked)
3699 m_settings->renameOutputFilesEnabled(checked);
3703 * Rename output files patterm changed
3705 void MainWindow::renameOutputPatternChanged(void)
3707 QString temp = lineEditRenamePattern->text().simplified();
3708 lineEditRenamePattern->setText(temp.isEmpty() ? m_settings->renameOutputFilesPatternDefault() : temp);
3709 m_settings->renameOutputFilesPattern(lineEditRenamePattern->text());
3713 * Rename output files patterm changed
3715 void MainWindow::renameOutputPatternChanged(const QString &text)
3717 QString pattern(text.simplified());
3719 pattern.replace("<BaseName>", "The_White_Stripes_-_Fell_In_Love_With_A_Girl", Qt::CaseInsensitive);
3720 pattern.replace("<TrackNo>", "04", Qt::CaseInsensitive);
3721 pattern.replace("<Title>", "Fell In Love With A Girl", Qt::CaseInsensitive);
3722 pattern.replace("<Artist>", "The White Stripes", Qt::CaseInsensitive);
3723 pattern.replace("<Album>", "White Blood Cells", Qt::CaseInsensitive);
3724 pattern.replace("<Year>", "2001", Qt::CaseInsensitive);
3725 pattern.replace("<Comment>", "Encoded by LameXP", Qt::CaseInsensitive);
3727 if(pattern.compare(lamexp_clean_filename(pattern)))
3729 if(lineEditRenamePattern->palette().color(QPalette::Text) != Qt::red)
3731 MessageBeep(MB_ICONERROR);
3732 SET_TEXT_COLOR(lineEditRenamePattern, Qt::red);
3737 if(lineEditRenamePattern->palette().color(QPalette::Text) != Qt::black)
3739 MessageBeep(MB_ICONINFORMATION);
3740 SET_TEXT_COLOR(lineEditRenamePattern, Qt::black);
3744 labelRanameExample->setText(lamexp_clean_filename(pattern));
3748 * Show list of rename macros
3750 void MainWindow::showRenameMacros(const QString &text)
3752 if(text.compare("reset", Qt::CaseInsensitive) == 0)
3754 lineEditRenamePattern->setText(m_settings->renameOutputFilesPatternDefault());
3758 const QString format = QString("<tr><td><tt><%1></tt></td><td> </td><td>%2</td></tr>");
3760 QString message = QString("<table>");
3761 message += QString(format).arg("BaseName", tr("File name without extension"));
3762 message += QString(format).arg("TrackNo", tr("Track number with leading zero"));
3763 message += QString(format).arg("Title", tr("Track title"));
3764 message += QString(format).arg("Artist", tr("Artist name"));
3765 message += QString(format).arg("Album", tr("Album name"));
3766 message += QString(format).arg("Year", tr("Year with (at least) four digits"));
3767 message += QString(format).arg("Comment", tr("Comment"));
3768 message += "</table><br><br>";
3769 message += QString("%1<br>").arg(tr("Characters forbidden in file names:"));
3770 message += "<b><tt>\\ / : * ? < > |<br>";
3772 QMessageBox::information(this, tr("Rename Macros"), message, tr("Discard"));
3775 void MainWindow::forceStereoDownmixEnabledChanged(bool checked)
3777 m_settings->forceStereoDownmix(checked);
3781 * Maximum number of instances changed
3783 void MainWindow::updateMaximumInstances(int value)
3785 labelMaxInstances->setText(tr("%1 Instance(s)").arg(QString::number(value)));
3786 m_settings->maximumInstances(checkBoxAutoDetectInstances->isChecked() ? NULL : value);
3790 * Auto-detect number of instances
3792 void MainWindow::autoDetectInstancesChanged(bool checked)
3794 m_settings->maximumInstances(checked ? NULL : sliderMaxInstances->value());
3798 * Browse for custom TEMP folder button clicked
3800 void MainWindow::browseCustomTempFolderButtonClicked(void)
3802 QString newTempFolder;
3804 if(USE_NATIVE_FILE_DIALOG)
3806 newTempFolder = QFileDialog::getExistingDirectory(this, QString(), m_settings->customTempPath());
3810 QFileDialog dialog(this);
3811 dialog.setFileMode(QFileDialog::DirectoryOnly);
3812 dialog.setDirectory(m_settings->customTempPath());
3815 newTempFolder = dialog.selectedFiles().first();
3819 if(!newTempFolder.isEmpty())
3821 QFile writeTest(QString("%1/~%2.tmp").arg(newTempFolder, lamexp_rand_str()));
3822 if(writeTest.open(QIODevice::ReadWrite))
3825 lineEditCustomTempFolder->setText(QDir::toNativeSeparators(newTempFolder));
3829 QMessageBox::warning(this, tr("Access Denied"), tr("Cannot write to the selected directory. Please choose another directory!"));
3835 * Custom TEMP folder changed
3837 void MainWindow::customTempFolderChanged(const QString &text)
3839 m_settings->customTempPath(QDir::fromNativeSeparators(text));
3843 * Use custom TEMP folder option changed
3845 void MainWindow::useCustomTempFolderChanged(bool checked)
3847 m_settings->customTempPathEnabled(!checked);
3851 * Help for custom parameters was requested
3853 void MainWindow::customParamsHelpRequested(QWidget *obj, QEvent *event)
3855 if(event->type() != QEvent::MouseButtonRelease)
3860 if(QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event))
3862 QPoint pos = mouseEvent->pos();
3863 if(!(pos.x() <= obj->width() && pos.y() <= obj->height() && pos.x() >= 0 && pos.y() >= 0 && mouseEvent->button() != Qt::MidButton))
3869 if(obj == helpCustomParamLAME) showCustomParamsHelpScreen("lame.exe", "--longhelp");
3870 else if(obj == helpCustomParamOggEnc) showCustomParamsHelpScreen("oggenc2.exe", "--help");
3871 else if(obj == helpCustomParamNeroAAC)
3873 if(m_qaacEncoderAvailable) showCustomParamsHelpScreen("qaac.exe", "--help");
3874 else if(m_fhgEncoderAvailable) showCustomParamsHelpScreen("fhgaacenc.exe", "");
3875 else if(m_neroEncoderAvailable) showCustomParamsHelpScreen("neroAacEnc.exe", "-help");
3876 else MessageBeep(MB_ICONERROR);
3878 else if(obj == helpCustomParamFLAC) showCustomParamsHelpScreen("flac.exe", "--help");
3879 else if(obj == helpCustomParamAften) showCustomParamsHelpScreen("aften.exe", "-h");
3880 else if(obj == helpCustomParamOpus) showCustomParamsHelpScreen("opusenc_std.exe", "--help");
3881 else MessageBeep(MB_ICONERROR);
3885 * Show help for custom parameters
3887 void MainWindow::showCustomParamsHelpScreen(const QString &toolName, const QString &command)
3889 const QString binary = lamexp_lookup_tool(toolName);
3890 if(binary.isEmpty())
3892 MessageBeep(MB_ICONERROR);
3893 qWarning("customParamsHelpRequested: Binary could not be found!");
3897 QProcess *process = new QProcess();
3898 process->setProcessChannelMode(QProcess::MergedChannels);
3899 process->setReadChannel(QProcess::StandardOutput);
3900 process->start(binary, command.isEmpty() ? QStringList() : QStringList() << command);
3901 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
3903 if(process->waitForStarted(15000))
3905 qApp->processEvents();
3906 process->waitForFinished(15000);
3909 if(process->state() != QProcess::NotRunning)
3912 process->waitForFinished(-1);
3915 qApp->restoreOverrideCursor();
3916 QStringList output; bool spaceFlag = true;
3918 while(process->canReadLine())
3920 QString temp = QString::fromUtf8(process->readLine());
3921 TRIM_STRING_RIGHT(temp);
3924 if(!spaceFlag) { output << temp; spaceFlag = true; }
3928 output << temp; spaceFlag = false;
3932 LAMEXP_DELETE(process);
3934 if(output.count() < 1)
3936 qWarning("Empty output, cannot show help screen!");
3937 MessageBeep(MB_ICONERROR);
3940 LogViewDialog *dialog = new LogViewDialog(this);
3941 TEMP_HIDE_DROPBOX( dialog->exec(output); );
3942 LAMEXP_DELETE(dialog);
3946 * Reset all advanced options to their defaults
3948 void MainWindow::resetAdvancedOptionsButtonClicked(void)
3950 sliderLameAlgoQuality->setValue(m_settings->lameAlgoQualityDefault());
3951 spinBoxBitrateManagementMin->setValue(m_settings->bitrateManagementMinRateDefault());
3952 spinBoxBitrateManagementMax->setValue(m_settings->bitrateManagementMaxRateDefault());
3953 spinBoxNormalizationFilter->setValue(static_cast<double>(m_settings->normalizationFilterMaxVolumeDefault()) / 100.0);
3954 spinBoxToneAdjustBass->setValue(static_cast<double>(m_settings->toneAdjustBassDefault()) / 100.0);
3955 spinBoxToneAdjustTreble->setValue(static_cast<double>(m_settings->toneAdjustTrebleDefault()) / 100.0);
3956 spinBoxAftenSearchSize->setValue(m_settings->aftenExponentSearchSizeDefault());
3957 spinBoxOpusComplexity->setValue(m_settings->opusComplexityDefault());
3958 comboBoxMP3ChannelMode->setCurrentIndex(m_settings->lameChannelModeDefault());
3959 comboBoxSamplingRate->setCurrentIndex(m_settings->samplingRateDefault());
3960 comboBoxAACProfile->setCurrentIndex(m_settings->aacEncProfileDefault());
3961 comboBoxAftenCodingMode->setCurrentIndex(m_settings->aftenAudioCodingModeDefault());
3962 comboBoxAftenDRCMode->setCurrentIndex(m_settings->aftenDynamicRangeCompressionDefault());
3963 comboBoxNormalizationMode->setCurrentIndex(m_settings->normalizationFilterEqualizationModeDefault());
3964 comboBoxOpusOptimize->setCurrentIndex(m_settings->opusOptimizeForDefault());
3965 comboBoxOpusFramesize->setCurrentIndex(m_settings->opusFramesizeDefault());
3966 SET_CHECKBOX_STATE(checkBoxBitrateManagement, m_settings->bitrateManagementEnabledDefault());
3967 SET_CHECKBOX_STATE(checkBoxNeroAAC2PassMode, m_settings->neroAACEnable2PassDefault());
3968 SET_CHECKBOX_STATE(checkBoxNormalizationFilter, m_settings->normalizationFilterEnabledDefault());
3969 SET_CHECKBOX_STATE(checkBoxAutoDetectInstances, (m_settings->maximumInstancesDefault() < 1));
3970 SET_CHECKBOX_STATE(checkBoxUseSystemTempFolder, !m_settings->customTempPathEnabledDefault());
3971 SET_CHECKBOX_STATE(checkBoxAftenFastAllocation, m_settings->aftenFastBitAllocationDefault());
3972 SET_CHECKBOX_STATE(checkBoxRenameOutput, m_settings->renameOutputFilesEnabledDefault());
3973 SET_CHECKBOX_STATE(checkBoxForceStereoDownmix, m_settings->forceStereoDownmixDefault());
3974 SET_CHECKBOX_STATE(checkBoxOpusExpAnalysis, m_settings->opusExpAnalysisDefault());
3975 lineEditCustomParamLAME->setText(m_settings->customParametersLAMEDefault());
3976 lineEditCustomParamOggEnc->setText(m_settings->customParametersOggEncDefault());
3977 lineEditCustomParamNeroAAC->setText(m_settings->customParametersAacEncDefault());
3978 lineEditCustomParamFLAC->setText(m_settings->customParametersFLACDefault());
3979 lineEditCustomParamOpus->setText(m_settings->customParametersFLACDefault());
3980 lineEditCustomTempFolder->setText(QDir::toNativeSeparators(m_settings->customTempPathDefault()));
3981 lineEditRenamePattern->setText(m_settings->renameOutputFilesPatternDefault());
3982 customParamsChanged();
3983 scrollArea->verticalScrollBar()->setValue(0);
3986 // =========================================================
3987 // Multi-instance handling slots
3988 // =========================================================
3991 * Other instance detected
3993 void MainWindow::notifyOtherInstance(void)
3995 if(!m_banner->isVisible())
3997 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);
4003 * Add file from another instance
4005 void MainWindow::addFileDelayed(const QString &filePath, bool tryASAP)
4007 if(tryASAP && !m_delayedFileTimer->isActive())
4009 qDebug("Received file: %s", filePath.toUtf8().constData());
4010 m_delayedFileList->append(filePath);
4011 QTimer::singleShot(0, this, SLOT(handleDelayedFiles()));
4014 m_delayedFileTimer->stop();
4015 qDebug("Received file: %s", filePath.toUtf8().constData());
4016 m_delayedFileList->append(filePath);
4017 m_delayedFileTimer->start(5000);
4021 * Add files from another instance
4023 void MainWindow::addFilesDelayed(const QStringList &filePaths, bool tryASAP)
4025 if(tryASAP && !m_delayedFileTimer->isActive())
4027 qDebug("Received %d file(s).", filePaths.count());
4028 m_delayedFileList->append(filePaths);
4029 QTimer::singleShot(0, this, SLOT(handleDelayedFiles()));
4033 m_delayedFileTimer->stop();
4034 qDebug("Received %d file(s).", filePaths.count());
4035 m_delayedFileList->append(filePaths);
4036 m_delayedFileTimer->start(5000);
4041 * Add folder from another instance
4043 void MainWindow::addFolderDelayed(const QString &folderPath, bool recursive)
4045 if(!m_banner->isVisible())
4047 addFolder(folderPath, recursive, true);
4051 // =========================================================
4053 // =========================================================
4056 * Restore the override cursor
4058 void MainWindow::restoreCursor(void)
4060 QApplication::restoreOverrideCursor();