From 0e59d6f9a266b326b4320f7ab4216b375c12088f Mon Sep 17 00:00:00 2001 From: lordmulder Date: Sat, 29 Jan 2011 00:40:29 +0100 Subject: [PATCH] Second part of LameXP shell integration. We can now remove the shell integration again. Also installing/removing the shell integration was moved into a separate thread in order to speed-up the startup. --- etc/Translation/Blank.ts | 94 +++++++++------ etc/Translation/LameXP_DE.ts | 30 ++++- etc/Translation/LameXP_ES.ts | 22 +++- etc/Translation/LameXP_FR.ts | 22 +++- etc/Translation/LameXP_IT.ts | 22 +++- gui/MainWindow.ui | 13 +- res/localization/LameXP_DE.qm | Bin 48737 -> 49670 bytes src/Config.h | 2 +- src/Dialog_MainWindow.cpp | 217 ++++++++++++++++++++-------------- src/Dialog_MainWindow.h | 2 + src/Model_Settings.cpp | 4 +- src/Model_Settings.h | 21 ++-- src/ShellIntegration.cpp | 151 +++++++++++++++++++++-- src/ShellIntegration.h | 21 +++- 14 files changed, 460 insertions(+), 161 deletions(-) diff --git a/etc/Translation/Blank.ts b/etc/Translation/Blank.ts index d699a261..a39d4146 100644 --- a/etc/Translation/Blank.ts +++ b/etc/Translation/Blank.ts @@ -677,6 +677,10 @@ Encode! + + Disable Shell Integration + + Adding file(s), please wait... @@ -705,6 +709,46 @@ This usually means the file is damaged or the file format is not supported. + + Downloading WMA Decoder Setup, please wait... + + + + Download Failed + + + + Failed to download the WMA Decoder setup. Check your internet connection! + + + + Try Again + + + + Cancel + + + + The download seems to be corrupted. Please try again! + + + + WMA Decoder + + + + The WMA File Decoder has been installed. Please restart LameXP now! + + + + Quit LameXP + + + + Postpone + + DEMO VERSION @@ -773,10 +817,6 @@ Your did not check for LameXP updates yet. Check for updates now? - - Postpone - - LameXP detected that your version of the Nero AAC encoder is outdated! @@ -825,10 +865,18 @@ You won't be able to process WMA files as input unless the WMA File Decoder component is installed! + + Do you want to download and install the WMA File Decoder component now? + + WMA Decoder Missing + + Download && Install + + LameXP @@ -1034,47 +1082,19 @@ - Do you want to download and install the WMA File Decoder component now? + Shell Integration - Download && Install + Do you really want to disable the LameXP shell integration? - Cancel + The LameXP shell integration has been disabled. - Downloading WMA Decoder Setup, please wait... - - - - Download Failed - - - - Failed to download the WMA Decoder setup. Check your internet connection! - - - - Try Again - - - - The download seems to be corrupted. Please try again! - - - - WMA Decoder - - - - The WMA File Decoder has been installed. Please restart LameXP now! - - - - Quit LameXP + The LameXP shell integration has been re-enabled. @@ -1443,7 +1463,7 @@ - Convert this file with LameXP v4 + Convert this file with LameXP v%1 diff --git a/etc/Translation/LameXP_DE.ts b/etc/Translation/LameXP_DE.ts index 1ef42c37..c874dc0b 100644 --- a/etc/Translation/LameXP_DE.ts +++ b/etc/Translation/LameXP_DE.ts @@ -672,7 +672,7 @@ Do you really want to disable the update reminder? - Wollen Sie die Update Erinnerung wirklich deaktivieren? + Sind Sie sicher, dass Sie die Update-Erinnerung jetzt deaktivieren möchten? Update Reminder @@ -684,7 +684,7 @@ Do you really want to disable all sound effects? - Wollen Sie wirklich alle Sound-Effekte deaktivieren? + Sind Sie sicher, dass Sie alle Sound-Effekte deaktivieren möchten? Sound Effects @@ -720,7 +720,7 @@ Do you really want to disable all WMA Decoder notifications? - Möchten Sie wirklich alle WMA Dekodierer Meldungen deaktivieren? + Sind Sie sicher, dass Sie alle WMA Dekodierer Meldungen deaktivieren möchten? All WMA Decoder notifications have been disabled. @@ -1078,6 +1078,26 @@ Adjust Bass (dB): Bass-Regler (dB): + + Disable Shell Integration + Shell-Integration Deaktivieren + + + Shell Integration + Shell-Integration + + + Do you really want to disable the LameXP shell integration? + Sind Sie sicher, dass Sie die LameXP Shell-Integration jetzt deaktivieren möchten? + + + The LameXP shell integration has been disabled. + Die LameXP Shell-Integration wurde deaktiviert. + + + The LameXP shell integration has been re-enabled. + Die LameXP Shell-Integration wurde wieder aktiviert. + MetaInfo @@ -1444,8 +1464,8 @@ LameXP Audio-Datei - Convert this file with LameXP v4 - Diese Datei mit LameXP v4 umwandeln + Convert this file with LameXP v%1 + Datei mit LameXP v%1 umwandeln diff --git a/etc/Translation/LameXP_ES.ts b/etc/Translation/LameXP_ES.ts index 5920701e..4597cff7 100644 --- a/etc/Translation/LameXP_ES.ts +++ b/etc/Translation/LameXP_ES.ts @@ -1078,6 +1078,26 @@ Adjust Bass (dB): + + Disable Shell Integration + + + + Shell Integration + + + + Do you really want to disable the LameXP shell integration? + + + + The LameXP shell integration has been disabled. + + + + The LameXP shell integration has been re-enabled. + + MetaInfo @@ -1444,7 +1464,7 @@ - Convert this file with LameXP v4 + Convert this file with LameXP v%1 diff --git a/etc/Translation/LameXP_FR.ts b/etc/Translation/LameXP_FR.ts index 1cfe3a11..c68bed1b 100644 --- a/etc/Translation/LameXP_FR.ts +++ b/etc/Translation/LameXP_FR.ts @@ -1080,6 +1080,26 @@ Votre dossier TEMP est situé ici: Adjust Bass (dB): + + Disable Shell Integration + + + + Shell Integration + + + + Do you really want to disable the LameXP shell integration? + + + + The LameXP shell integration has been disabled. + + + + The LameXP shell integration has been re-enabled. + + MetaInfo @@ -1446,7 +1466,7 @@ Votre dossier TEMP est situé ici: - Convert this file with LameXP v4 + Convert this file with LameXP v%1 diff --git a/etc/Translation/LameXP_IT.ts b/etc/Translation/LameXP_IT.ts index 21268b61..8e699b8e 100644 --- a/etc/Translation/LameXP_IT.ts +++ b/etc/Translation/LameXP_IT.ts @@ -1078,6 +1078,26 @@ Adjust Bass (dB): + + Disable Shell Integration + + + + Shell Integration + + + + Do you really want to disable the LameXP shell integration? + + + + The LameXP shell integration has been disabled. + + + + The LameXP shell integration has been re-enabled. + + MetaInfo @@ -1444,7 +1464,7 @@ - Convert this file with LameXP v4 + Convert this file with LameXP v%1 diff --git a/gui/MainWindow.ui b/gui/MainWindow.ui index 62c9af30..78b9fb86 100644 --- a/gui/MainWindow.ui +++ b/gui/MainWindow.ui @@ -985,7 +985,7 @@ 0 0 - 604 + 602 609 @@ -2200,6 +2200,7 @@ + @@ -2439,6 +2440,14 @@ Encode! + + + true + + + Disable Shell Integration + + @@ -2482,6 +2491,8 @@ + + diff --git a/res/localization/LameXP_DE.qm b/res/localization/LameXP_DE.qm index ab83b1e3e398abf5aac8f3a492446a73f5f30ec3..cd1c12c78eade73e096ddc770f1042ae0fc4aab5 100644 GIT binary patch delta 3613 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 E1JT9`KL7v# delta 2935 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 yRgu~ewpF(xCyA?~qKD3rc)`<%2").arg(URL).arg(URL) #define TEMP_HIDE_DROPBOX(CMD) { bool __dropBoxVisible = m_dropBox->isVisible(); if(__dropBoxVisible) m_dropBox->hide(); CMD; if(__dropBoxVisible) m_dropBox->show(); } -//Helper class -//class Index: public QObjectUserData -//{ -//public: -// Index(int index) { m_index = index; } -// int value(void) { return m_index; } -//private: -// int m_index; -//}; - //////////////////////////////////////////////////////////// // Constructor //////////////////////////////////////////////////////////// @@ -304,11 +294,14 @@ MainWindow::MainWindow(FileListModel *fileListModel, AudioFileModel *metaInfo, S actionDisableSounds->setChecked(!m_settings->soundsEnabled()); actionDisableNeroAacNotifications->setChecked(!m_settings->neroAacNotificationsEnabled()); actionDisableWmaDecoderNotifications->setChecked(!m_settings->wmaDecoderNotificationsEnabled()); + actionDisableShellIntegration->setChecked(!m_settings->shellIntegrationEnabled()); + actionDisableShellIntegration->setVisible(!lamexp_portable_mode()); connect(actionDisableUpdateReminder, SIGNAL(triggered(bool)), this, SLOT(disableUpdateReminderActionTriggered(bool))); connect(actionDisableSounds, SIGNAL(triggered(bool)), this, SLOT(disableSoundsActionTriggered(bool))); connect(actionInstallWMADecoder, SIGNAL(triggered(bool)), this, SLOT(installWMADecoderActionTriggered(bool))); connect(actionDisableNeroAacNotifications, SIGNAL(triggered(bool)), this, SLOT(disableNeroAacNotificationsActionTriggered(bool))); connect(actionDisableWmaDecoderNotifications, SIGNAL(triggered(bool)), this, SLOT(disableWmaDecoderNotificationsActionTriggered(bool))); + connect(actionDisableShellIntegration, SIGNAL(triggered(bool)), this, SLOT(disableShellIntegrationActionTriggered(bool))); connect(actionShowDropBoxWidget, SIGNAL(triggered(bool)), this, SLOT(showDropBoxWidgetActionTriggered(bool))); //Activate help menu actions @@ -395,7 +388,6 @@ MainWindow::~MainWindow(void) LAMEXP_DELETE(m_encoderButtonGroup); LAMEXP_DELETE(m_sourceFilesContextMenu); LAMEXP_DELETE(m_dropBox); - } //////////////////////////////////////////////////////////// @@ -434,6 +426,81 @@ void MainWindow::addFiles(const QStringList &files) m_banner->close(); } +/* + * Download and install WMA Decoder component + */ +void MainWindow::installWMADecoder(void) +{ + static const char *download_url = "http://www.nch.com.au/components/wmawav.exe"; + static const char *download_hash = "52a3b0e6690faf3f830c336d3c0eadfb7a4e9bc6"; + + QString binaryWGet = lamexp_lookup_tool("wget.exe"); + QString binaryElevator = lamexp_lookup_tool("elevator.exe"); + + if(binaryWGet.isEmpty() || binaryElevator.isEmpty()) + { + throw "Required binary is not available!"; + } + + while(true) + { + QString setupFile = QString("%1/%2.exe").arg(lamexp_temp_folder(), lamexp_rand_str()); + + QProcess process; + process.setWorkingDirectory(QFileInfo(setupFile).absolutePath()); + + QEventLoop loop; + connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit())); + connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), &loop, SLOT(quit())); + + process.start(binaryWGet, QStringList() << "-O" << QFileInfo(setupFile).fileName() << download_url); + m_banner->show(tr("Downloading WMA Decoder Setup, please wait..."), &loop); + + if(process.exitCode() != 0 || QFileInfo(setupFile).size() < 10240) + { + QFile::remove(setupFile); + if(QMessageBox::critical(this, tr("Download Failed"), tr("Failed to download the WMA Decoder setup. Check your internet connection!"), tr("Try Again"), tr("Cancel")) == 0) + { + continue; + } + return; + } + + QFile setupFileContent(setupFile); + QCryptographicHash setupFileHash(QCryptographicHash::Sha1); + + setupFileContent.open(QIODevice::ReadOnly); + if(setupFileContent.isOpen() && setupFileContent.isReadable()) + { + setupFileHash.addData(setupFileContent.readAll()); + setupFileContent.close(); + } + + if(_stricmp(setupFileHash.result().toHex().constData(), download_hash)) + { + qWarning("Hash miscompare:\n Expected %s\n Detected %s\n", download_hash, setupFileHash.result().toHex().constData()); + QFile::remove(setupFile); + if(QMessageBox::critical(this, tr("Download Failed"), tr("The download seems to be corrupted. Please try again!"), tr("Try Again"), tr("Cancel")) == 0) + { + continue; + } + return; + } + + QApplication::setOverrideCursor(Qt::WaitCursor); + process.start(binaryElevator, QStringList() << QString("/exec=%1").arg(setupFile)); + loop.exec(QEventLoop::ExcludeUserInputEvents); + QFile::remove(setupFile); + QApplication::restoreOverrideCursor(); + + if(QMessageBox::information(this, tr("WMA Decoder"), tr("The WMA File Decoder has been installed. Please restart LameXP now!"), tr("Quit LameXP"), tr("Postpone")) == 0) + { + QApplication::quit(); + } + break; + } +} + //////////////////////////////////////////////////////////// // EVENTS //////////////////////////////////////////////////////////// @@ -500,6 +567,11 @@ void MainWindow::changeEvent(QEvent *e) m_metaInfoModel->clearData(); updateEncoder(m_settings->compressionEncoder()); updateLameAlgoQuality(sliderLameAlgoQuality->value()); + + if(m_settings->shellIntegrationEnabled()) + { + ShellIntegration::install(); + } } } @@ -726,16 +798,15 @@ void MainWindow::windowShown(void) { QString messageText; messageText += QString("%1
").arg(tr("LameXP has detected that the WMA File Decoder component is not currently installed on your system.")); - messageText += QString("%1
").arg(tr("You won't be able to process WMA files as input unless the WMA File Decoder component is installed!")); - QMessageBox::information(this, tr("WMA Decoder Missing"), messageText); - installWMADecoderActionTriggered(rand() % 2); + messageText += QString("%1

").arg(tr("You won't be able to process WMA files as input unless the WMA File Decoder component is installed!")); + messageText += QString("%1").arg(tr("Do you want to download and install the WMA File Decoder component now?")); + if(QMessageBox::information(this, tr("WMA Decoder Missing"), messageText, tr("Download && Install"), tr("Postpone")) == 0) + { + installWMADecoder(); + } } } - // !!! -- TEST -- !!! - ShellIntegration::install(); - // !!! -- TEST -- !!! - //Add files from the command-line for(int i = 0; i < arguments.count() - 1; i++) { @@ -753,6 +824,12 @@ void MainWindow::windowShown(void) m_delayedFileTimer->start(5000); } + //Enable shell integration + if(m_settings->shellIntegrationEnabled()) + { + ShellIntegration::install(); + } + //Make DropBox visible if(m_settings->dropBoxWidgetEnabled()) { @@ -2040,81 +2117,15 @@ void MainWindow::disableWmaDecoderNotificationsActionTriggered(bool checked) */ void MainWindow::installWMADecoderActionTriggered(bool checked) { - static const char *download_url = "http://www.nch.com.au/components/wmawav.exe"; - static const char *download_hash = "52a3b0e6690faf3f830c336d3c0eadfb7a4e9bc6"; - - if(QMessageBox::question(this, tr("Install WMA Decoder"), tr("Do you want to download and install the WMA File Decoder component now?"), tr("Download && Install"), tr("Cancel")) != 0) + if(QMessageBox::question(this, tr("Install WMA Decoder"), tr("Do you want to download and install the WMA File Decoder component now?"), tr("Download && Install"), tr("Cancel")) == 0) { - return; - } - - QString binaryWGet = lamexp_lookup_tool("wget.exe"); - QString binaryElevator = lamexp_lookup_tool("elevator.exe"); - - if(binaryWGet.isEmpty() || binaryElevator.isEmpty()) - { - throw "Required binary is not available!"; - } - - while(true) - { - QString setupFile = QString("%1/%2.exe").arg(lamexp_temp_folder(), lamexp_rand_str()); - - QProcess process; - process.setWorkingDirectory(QFileInfo(setupFile).absolutePath()); - - QEventLoop loop; - connect(&process, SIGNAL(error(QProcess::ProcessError)), &loop, SLOT(quit())); - connect(&process, SIGNAL(finished(int, QProcess::ExitStatus)), &loop, SLOT(quit())); - - process.start(binaryWGet, QStringList() << "-O" << QFileInfo(setupFile).fileName() << download_url); - m_banner->show(tr("Downloading WMA Decoder Setup, please wait..."), &loop); - - if(process.exitCode() != 0 || QFileInfo(setupFile).size() < 10240) - { - QFile::remove(setupFile); - if(QMessageBox::critical(this, tr("Download Failed"), tr("Failed to download the WMA Decoder setup. Check your internet connection!"), tr("Try Again"), tr("Cancel")) == 0) - { - continue; - } - return; - } - - QFile setupFileContent(setupFile); - QCryptographicHash setupFileHash(QCryptographicHash::Sha1); - - setupFileContent.open(QIODevice::ReadOnly); - if(setupFileContent.isOpen() && setupFileContent.isReadable()) - { - setupFileHash.addData(setupFileContent.readAll()); - setupFileContent.close(); - } - - if(_stricmp(setupFileHash.result().toHex().constData(), download_hash)) - { - qWarning("Hash miscompare:\n Expected %s\n Detected %s\n", download_hash, setupFileHash.result().toHex().constData()); - QFile::remove(setupFile); - if(QMessageBox::critical(this, tr("Download Failed"), tr("The download seems to be corrupted. Please try again!"), tr("Try Again"), tr("Cancel")) == 0) - { - continue; - } - return; - } - - QApplication::setOverrideCursor(Qt::WaitCursor); - process.start(binaryElevator, QStringList() << QString("/exec=%1").arg(setupFile)); - loop.exec(QEventLoop::ExcludeUserInputEvents); - QFile::remove(setupFile); - QApplication::restoreOverrideCursor(); - - if(QMessageBox::information(this, tr("WMA Decoder"), tr("The WMA File Decoder has been installed. Please restart LameXP now!"), tr("Quit LameXP"), tr("Postpone")) == 0) - { - QApplication::quit(); - } - break; + installWMADecoder(); } } +/* + * Show the "drop box" widget + */ void MainWindow::showDropBoxWidgetActionTriggered(bool checked) { m_settings->dropBoxWidgetEnabled(true); @@ -2126,3 +2137,31 @@ void MainWindow::showDropBoxWidgetActionTriggered(bool checked) FLASH_WINDOW(m_dropBox); } + +/* + * Disable shell integration action + */ +void MainWindow::disableShellIntegrationActionTriggered(bool checked) +{ + if(checked) + { + if(0 == QMessageBox::question(this, tr("Shell Integration"), tr("Do you really want to disable the LameXP shell integration?"), tr("Yes"), tr("No"), QString(), 1)) + { + ShellIntegration::remove(); + QMessageBox::information(this, tr("Shell Integration"), tr("The LameXP shell integration has been disabled.")); + m_settings->shellIntegrationEnabled(false); + } + else + { + m_settings->shellIntegrationEnabled(true); + } + } + else + { + ShellIntegration::install(); + QMessageBox::information(this, tr("Shell Integration"), tr("The LameXP shell integration has been re-enabled.")); + m_settings->shellIntegrationEnabled(true); + } + + actionDisableShellIntegration->setChecked(!m_settings->shellIntegrationEnabled()); +} diff --git a/src/Dialog_MainWindow.h b/src/Dialog_MainWindow.h index 669074cf..2088b50a 100644 --- a/src/Dialog_MainWindow.h +++ b/src/Dialog_MainWindow.h @@ -110,6 +110,7 @@ private slots: void disableNeroAacNotificationsActionTriggered(bool checked); void disableWmaDecoderNotificationsActionTriggered(bool checked); void showDropBoxWidgetActionTriggered(bool checked); + void disableShellIntegrationActionTriggered(bool); protected: void showEvent(QShowEvent *event); @@ -122,6 +123,7 @@ protected: private: void addFiles(const QStringList &files); + void installWMADecoder(void); bool m_accepted; bool m_firstTimeShown; diff --git a/src/Model_Settings.cpp b/src/Model_Settings.cpp index d29b6114..d5dfdfee 100644 --- a/src/Model_Settings.cpp +++ b/src/Model_Settings.cpp @@ -50,6 +50,7 @@ static const char *g_settingsId_soundsEnabled = "Flags/EnableSounds"; static const char *g_settingsId_neroAacNotificationsEnabled = "Flags/EnableNeroAacNotifications"; static const char *g_settingsId_wmaDecoderNotificationsEnabled = "Flags/EnableWmaDecoderNotifications"; static const char *g_settingsId_dropBoxWidgetEnabled = "Flags/EnableDropBoxWidget"; +static const char *g_settingsId_shellIntegrationEnabled = "Flags/EnableShellIntegration"; static const char *g_settingsId_currentLanguage = "Localization/Language"; static const char *g_settingsId_lameAlgoQuality = "AdvancedOptions/LAME/AlgorithmQuality"; static const char *g_settingsId_lameChannelMode = "AdvancedOptions/LAME/ChannelMode"; @@ -218,7 +219,8 @@ MAKE_OPTION3(soundsEnabled, true) MAKE_OPTION3(neroAacNotificationsEnabled, true) MAKE_OPTION3(wmaDecoderNotificationsEnabled, true) MAKE_OPTION3(dropBoxWidgetEnabled, true) -MAKE_OPTION2(currentLanguage, defaultLanguage()); +MAKE_OPTION3(shellIntegrationEnabled, !lamexp_portable_mode()) +MAKE_OPTION2(currentLanguage, defaultLanguage()) MAKE_OPTION1(lameAlgoQuality, 3) MAKE_OPTION1(lameChannelMode, 0); MAKE_OPTION3(bitrateManagementEnabled, false) diff --git a/src/Model_Settings.h b/src/Model_Settings.h index f395bad2..81aa925c 100644 --- a/src/Model_Settings.h +++ b/src/Model_Settings.h @@ -79,22 +79,23 @@ public: MAKE_OPTION_DEC2(autoUpdateLastCheck); MAKE_OPTION_DEC3(autoUpdateEnabled); MAKE_OPTION_DEC3(soundsEnabled); - MAKE_OPTION_DEC3(neroAacNotificationsEnabled) - MAKE_OPTION_DEC3(wmaDecoderNotificationsEnabled) - MAKE_OPTION_DEC3(dropBoxWidgetEnabled) + MAKE_OPTION_DEC3(neroAacNotificationsEnabled); + MAKE_OPTION_DEC3(wmaDecoderNotificationsEnabled); + MAKE_OPTION_DEC3(dropBoxWidgetEnabled); + MAKE_OPTION_DEC3(shellIntegrationEnabled); MAKE_OPTION_DEC2(currentLanguage); MAKE_OPTION_DEC1(lameAlgoQuality); MAKE_OPTION_DEC1(lameChannelMode); MAKE_OPTION_DEC3(bitrateManagementEnabled); MAKE_OPTION_DEC1(bitrateManagementMinRate); MAKE_OPTION_DEC1(bitrateManagementMaxRate); - MAKE_OPTION_DEC1(samplingRate) - MAKE_OPTION_DEC3(neroAACEnable2Pass) - MAKE_OPTION_DEC1(neroAACProfile) - MAKE_OPTION_DEC3(normalizationFilterEnabled) - MAKE_OPTION_DEC1(normalizationFilterMaxVolume) - MAKE_OPTION_DEC1(toneAdjustBass) - MAKE_OPTION_DEC1(toneAdjustTreble) + MAKE_OPTION_DEC1(samplingRate); + MAKE_OPTION_DEC3(neroAACEnable2Pass); + MAKE_OPTION_DEC1(neroAACProfile); + MAKE_OPTION_DEC3(normalizationFilterEnabled); + MAKE_OPTION_DEC1(normalizationFilterMaxVolume); + MAKE_OPTION_DEC1(toneAdjustBass); + MAKE_OPTION_DEC1(toneAdjustTreble); //Misc void validate(void); diff --git a/src/ShellIntegration.cpp b/src/ShellIntegration.cpp index f05c4548..30cfabef 100644 --- a/src/ShellIntegration.cpp +++ b/src/ShellIntegration.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -39,29 +40,74 @@ static const char *g_lamexpShellAction = "ConvertWithLameXP"; static const char *g_lamexpFileType = "LameXP.SupportedAudioFile"; +//Mutex +QMutex ShellIntegration::m_mutex; + +//Macros +#define REG_WRITE_STRING(KEY, STR) RegSetKeyValue(key, NULL, NULL, REG_SZ, QWCHAR(STR), (STR.size() + 1) * sizeof(wchar_t)) + +//////////////////////////////////////////////////////////// +// Constructor +//////////////////////////////////////////////////////////// + +ShellIntegration::ShellIntegration(bool install) +: + QThread(), + m_install(install) +{ +} + +ShellIntegration::~ShellIntegration(void) +{ +} + //////////////////////////////////////////////////////////// // Public Functions //////////////////////////////////////////////////////////// -void ShellIntegration::install(void) +void ShellIntegration::install(bool async) { - HKEY key = NULL; + //Install asynchronously + if(async) + { + ShellIntegration *shellIntegration = new ShellIntegration(true); + connect(shellIntegration, SIGNAL(finished()), shellIntegration, SLOT(deleteLater())); + shellIntegration->start(); + return; + } + + //Serialize + QMutexLocker lock(&m_mutex); + //Registry key + HKEY key = NULL; + + //Init some consts const QString lamexpFileType(g_lamexpFileType); const QString lamexpFileInfo(tr("Audio File supported by LameXP")); - const QString lamexpShellText(tr("Convert this file with LameXP v4")); + const QString lamexpShellText(tr("Convert this file with LameXP v%1").arg(QString().sprintf("%d.%02d", lamexp_version_major(), lamexp_version_minor()))); const QString lamexpShellCommand = QString("\"%1\" --add \"%2\"").arg(QDir::toNativeSeparators(QFileInfo(QApplication::applicationFilePath()).canonicalFilePath()), "%1"); const QString lamexpShellAction(g_lamexpShellAction); //Register the LameXP file type if(RegCreateKeyEx(HKEY_CURRENT_USER, QWCHAR(QString("Software\\Classes\\%1").arg(lamexpFileType)), NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) { - RegSetKeyValue(key, NULL, NULL, REG_SZ, QWCHAR(lamexpFileInfo), (lamexpFileInfo.size() + 1) * sizeof(wchar_t)); + REG_WRITE_STRING(key, lamexpFileInfo); RegCloseKey(key); } if(RegCreateKeyEx(HKEY_CURRENT_USER, QWCHAR(QString("Software\\Classes\\%1\\shell").arg(lamexpFileType)), NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) { - RegSetKeyValue(key, NULL, NULL, REG_SZ, QWCHAR(lamexpShellAction), (lamexpShellAction.size() + 1) * sizeof(wchar_t)); + REG_WRITE_STRING(key, lamexpShellAction); + RegCloseKey(key); + } + if(RegCreateKeyEx(HKEY_CURRENT_USER, QWCHAR(QString("Software\\Classes\\%1\\shell\\%2").arg(lamexpFileType, lamexpShellAction)), NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) + { + REG_WRITE_STRING(key, lamexpShellText); + RegCloseKey(key); + } + if(RegCreateKeyEx(HKEY_CURRENT_USER, QWCHAR(QString("Software\\Classes\\%1\\shell\\%2\\command").arg(lamexpFileType, lamexpShellAction)), NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) + { + REG_WRITE_STRING(key, lamexpShellCommand); RegCloseKey(key); } @@ -75,13 +121,13 @@ void ShellIntegration::install(void) if(RegCreateKeyEx(HKEY_CURRENT_USER, QWCHAR(QString("Software\\Classes\\%1\\shell\\%2").arg(currentType, lamexpShellAction)), NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) { - RegSetKeyValue(key, NULL, NULL, REG_SZ, QWCHAR(lamexpShellText), (lamexpShellText.size() + 1) * sizeof(wchar_t)); + REG_WRITE_STRING(key, lamexpShellText); RegCloseKey(key); } if(RegCreateKeyEx(HKEY_CURRENT_USER, QWCHAR(QString("Software\\Classes\\%1\\shell\\%2\\command").arg(currentType, lamexpShellAction)), NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) { - RegSetKeyValue(key, NULL, NULL, REG_SZ, QWCHAR(lamexpShellCommand), (lamexpShellCommand.size() + 1) * sizeof(wchar_t)); + REG_WRITE_STRING(key, lamexpShellCommand); RegCloseKey(key); } } @@ -93,9 +139,55 @@ void ShellIntegration::install(void) delete types; } -void ShellIntegration::remove(void) +void ShellIntegration::remove(bool async) { - qDebug("Sorry, not implemented yet :-["); + //Remove asynchronously + if(async) + { + ShellIntegration *shellIntegration = new ShellIntegration(false); + connect(shellIntegration, SIGNAL(finished()), shellIntegration, SLOT(deleteLater())); + shellIntegration->start(); + return; + } + + //Serialize + QMutexLocker lock(&m_mutex); + + //Init some consts + const QString lamexpFileType(g_lamexpFileType); + const QString lamexpShellAction(g_lamexpShellAction); + + //Initialization + HKEY key = NULL; + QStringList fileTypes; + + //Find all registered file types + if(RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", NULL, KEY_ENUMERATE_SUB_KEYS ,&key) == ERROR_SUCCESS) + { + wchar_t name[256]; + + for(DWORD i = 0; true; i++) + { + DWORD size = 256; + if(RegEnumKeyEx(key, i, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) + { + fileTypes << QString::fromUtf16(reinterpret_cast(name)); + continue; + } + break; + } + } + + //Remove shell action from all file types + while(!fileTypes.isEmpty()) + { + SHDeleteKey(HKEY_CURRENT_USER, QWCHAR(QString("Software\\Classes\\%1\\shell\\%2").arg(fileTypes.takeFirst(), lamexpShellAction))); + } + + //Unregister LameXP file type + SHDeleteKey(HKEY_CURRENT_USER, QWCHAR(QString("Software\\Classes\\%1").arg(lamexpFileType))); + + //Shell notification SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); } @@ -131,7 +223,6 @@ QStringList *ShellIntegration::detectTypes(const QString &lamexpFileType, const while(!extensions.isEmpty()) { QString currentExt = extensions.takeFirst(); - SHDeleteKey(HKEY_CURRENT_USER, QWCHAR(QString("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\%1").arg(currentExt))); if(RegOpenKeyEx(HKEY_CLASSES_ROOT, QWCHAR(currentExt), NULL, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { @@ -160,6 +251,46 @@ QStringList *ShellIntegration::detectTypes(const QString &lamexpFileType, const RegCloseKey(key); } } + + if(RegOpenKeyEx(HKEY_CURRENT_USER, QWCHAR(QString("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\%1\\UserChoice").arg(currentExt)), NULL, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) + { + wchar_t data[256]; + DWORD dataLen = 256 * sizeof(wchar_t); + DWORD type = NULL; + + if(RegQueryValueEx(key, L"Progid", NULL, &type, reinterpret_cast(data), &dataLen) == ERROR_SUCCESS) + { + if((type == REG_SZ) || (type == REG_EXPAND_SZ)) + { + QString currentType = QString::fromUtf16(reinterpret_cast(data)); + if((currentType.compare(lamexpFileType, Qt::CaseInsensitive) != 0) && !nativeTypes->contains(currentType, Qt::CaseInsensitive)) + { + nativeTypes->append(currentType); + } + } + } + RegCloseKey(key); + } + + if(RegOpenKeyEx(HKEY_CURRENT_USER, QWCHAR(QString("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\%1\\OpenWithProgids").arg(currentExt)), NULL, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) + { + wchar_t name[256]; + for(DWORD i = 0; true; i++) + { + DWORD size = 256; + if(RegEnumValue(key, i, name, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) + { + QString currentType = QString::fromUtf16(reinterpret_cast(name)); + if((currentType.compare(lamexpFileType, Qt::CaseInsensitive) != 0) && !nativeTypes->contains(currentType, Qt::CaseInsensitive)) + { + nativeTypes->append(currentType); + } + continue; + } + break; + } + RegCloseKey(key); + } } return nativeTypes; diff --git a/src/ShellIntegration.h b/src/ShellIntegration.h index c902cf23..79464063 100644 --- a/src/ShellIntegration.h +++ b/src/ShellIntegration.h @@ -21,19 +21,32 @@ #pragma once -#include +#include +#include class QString; class QStringList; -class ShellIntegration : public QObject +class ShellIntegration : public QThread { Q_OBJECT public: - static void install(void); - static void remove(void); + static void install(bool async = true); + static void remove(bool async = true); + +protected: + void run() + { + if(m_install) install(false); else remove(false); + } private: + ShellIntegration(bool install = true); + ~ShellIntegration(void); + static QStringList *detectTypes(const QString &lamexpFileType, const QString &lamexpShellAction); + static QMutex m_mutex; + + bool m_install; };