35 #include <qt_windows.h> 44 bool ReadValue (HKEY hKey,
const QString& valueName, QString& result)
47 if (ERROR_SUCCESS == RegQueryValueExW (hKey,
48 valueName.toStdWString ().c_str (),
54 std::vector<wchar_t> buff (buffSize /
sizeof (
wchar_t));
55 if (ERROR_SUCCESS == RegQueryValueExW (hKey,
56 valueName.toStdWString ().c_str (),
59 reinterpret_cast<LPBYTE
> (&buff [0]),
62 result = QString::fromWCharArray (buff.data ());
69 bool ReadDefaultValue (
const QString& fullKey, QString& result)
73 if (ERROR_SUCCESS != RegOpenKeyW (HKEY_CLASSES_ROOT,
74 fullKey.toStdWString ().c_str (),
80 DWORD type { REG_SZ };
82 if (ERROR_SUCCESS == RegQueryValueExW (hKey,
89 std::vector<wchar_t> buff (buffSize /
sizeof (
wchar_t));
90 if (ERROR_SUCCESS == RegQueryValueExW (hKey,
94 reinterpret_cast<LPBYTE> (&buff [0]),
97 result = QString::fromWCharArray (buff.data ());
99 if (REG_EXPAND_SZ == type)
101 buffSize = ExpandEnvironmentStringsW (result.toStdWString ().c_str (),
nullptr, 0);
102 buff.resize (buffSize);
103 if (!ExpandEnvironmentStringsW (result.toStdWString ().c_str (), &buff [0], buffSize))
107 result = QString::fromWCharArray (buff.data ());
118 DWORD maxSubkeyLen {};
120 if (ERROR_SUCCESS != RegQueryInfoKeyW (hKey,
133 qDebug () << Q_FUNC_INFO
134 <<
"RegQueryInfoKeyW failed.";
139 std::vector<wchar_t> keyName (maxSubkeyLen + 1);
140 for (DWORD i = 0; i < subKeys; ++i)
142 if (ERROR_SUCCESS != RegEnumKeyW (hKey,
149 result.append (QString::fromWCharArray (keyName.data ()));
154 QHash<QString, QString> ParseMimeDatabase ()
158 static const QString kDatabaseKey {
"Mime\\Database\\Content Type" };
159 if (ERROR_SUCCESS != RegOpenKeyW (HKEY_CLASSES_ROOT,
160 kDatabaseKey.toStdWString ().c_str (),
165 if (!GetSubkeyNames (hKey, mimes))
173 QHash<QString, QString> result;
174 for (
const QString& mime : mimes)
176 static const QString kFormat {
"Mime\\Database\\Content Type\\%1" };
177 static const QString kExtension {
"Extension" };
178 static const QChar kDot {
'.'};
180 const QString fullKeyPath = kFormat.arg (mime);
182 if (ERROR_SUCCESS != RegOpenKeyW (HKEY_CLASSES_ROOT,
183 fullKeyPath.toStdWString ().c_str (),
188 if (ReadValue (hKey, kExtension, ext) && !ext.isEmpty ())
190 if (ext.at (0) == kDot)
192 result.insert (ext, mime);
198 if (ERROR_SUCCESS != RegOpenKeyW (HKEY_CLASSES_ROOT,
204 if (!GetSubkeyNames (hKey, extensions))
211 static const QString kValueContentType {
"Content Type" };
212 for (
int i = 0; i < extensions.count (); ++i)
214 static const auto prefix = QChar {
'.'};
215 if (!extensions.at (i).startsWith (prefix))
218 extensions [i].remove (0, 1);
220 if (result.contains (extensions.at (i)))
223 if (ERROR_SUCCESS != RegOpenKeyW (HKEY_CLASSES_ROOT,
224 QString {
".%1" }.arg (extensions.at (i)).toStdWString ().c_str (),
229 if (ReadValue (hKey, kValueContentType, mime) && !mime.isEmpty ())
230 result.insert (extensions.at (i), mime);
238 class ExtensionsDataImpl::Details
254 : Extension2Mime_ { ParseMimeDatabase () }
256 for (
auto it = Extension2Mime_.constBegin (); it != Extension2Mime_.constEnd (); ++it)
257 Mime2Extension_.insertMulti (it.value (), it.key ());
262 return Extension2Mime_.value (extension);
267 return Mime2Extension_.values (mime).first ();
272 QMutexLocker lock { &IconsLock_ };
273 if (Extension2Icon_.contains (extension))
274 return Extension2Icon_.value (extension);
277 static const QString kKeyDefaultIcon {
"DefaultIcon" };
278 static const QChar kDot {
'.' };
279 static const QChar kComma {
',' };
281 const QString dottedExt = kDot + extension;
282 QString defIconKey = dottedExt +
"\\" + kKeyDefaultIcon;
285 if (!ReadDefaultValue (defIconKey, defIconPath))
288 if (ReadDefaultValue (dottedExt, defaultType))
290 defIconKey = defaultType +
"\\" + kKeyDefaultIcon;
291 ReadDefaultValue (defIconKey, defIconPath);
295 if (defIconPath.isEmpty ())
298 const QStringList parts = defIconPath.split (kComma);
299 if (2 != parts.count ())
302 QString path = parts.at (0);
303 path.replace (
"\"", {});
305 const UINT index = parts.count () > 1 ? parts.at (1).toUInt () : 0;
306 const HICON hIcon = ExtractIconW (GetModuleHandle (
nullptr), path.toStdWString ().c_str (), index);
311 QPixmap pixmap { QPixmap::fromWinHICON (hIcon) };
312 if (!pixmap.isNull ())
313 icon.addPixmap (pixmap);
319 Extension2Icon_.insert (extension, icon);
332 return Details_->Extension2Mime_;
337 const auto& lowerExtension = extension.toLower ();
338 return Details_->GetExtensionIcon (lowerExtension);
343 const auto& ext = Details_->ExtensionByMime (mime);
347 return Details_->GetExtensionIcon (ext);
QHash< QString, QIcon > Extension2Icon_
detail::ScopeGuard< F > MakeScopeGuard(const F &f)
Returns an object performing passed function on scope exit.
QString ExtensionByMime(const QString &mime) const
QIcon GetExtensionIcon(const QString &extension)
const QHash< QString, QString > & GetMimeDatabase() const
QMultiHash< QString, QString > Mime2Extension_
const QHash< QString, QString > Extension2Mime_
QString MimeByExtension(const QString &extension) const
QIcon GetExtIcon(const QString &extension) const
QIcon GetMimeIcon(const QString &mime) const