Projects
Multimedia
qmp3gain
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 9
View file
qmp3gain.changes
Changed
@@ -1,4 +1,17 @@ ------------------------------------------------------------------- +Fri Jan 26 15:30:35 UTC 2024 - Carsten Ziepke <kieltux@gmail.com> + +- Update to version 0.9.4 + * Feature: Column widths of tableView are stored in config + * Feature: String columns of tableView got tooltips + * Fix: Adding file using drag&drop which failed with more dots + in the filename + * Fix: Crash due to missing values in case of backend abort + * Fix: Crash on showing context menu of tableView without any row +- Run spec-cleaner +- Use fdupes macro + +------------------------------------------------------------------- Sun Feb 11 19:33:09 UTC 2018 - aloisio@gmx.com - Initial package (0.9.0)
View file
qmp3gain.spec
Changed
@@ -1,7 +1,7 @@ # # spec file for package qmp3gain # -# Copyright (c) 2018 Packman Team <packman@links2linux.de> +# Copyright (c) 2024 Packman Team <packman@links2linux.de> # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,20 +17,21 @@ Name: qmp3gain -Version: 0.9.3 +Version: 0.9.4 Release: 0 Summary: Qt frontend for mp3gain -License: GPL-2.0+ +License: GPL-2.0-or-later Group: Productivity/Multimedia/Sound/Editors and Convertors URL: https://qmp3gain.sourceforge.io -Source0: %name-%version.tar.xz +Source0: %{name}-%{version}.tar.xz +BuildRequires: fdupes BuildRequires: pkgconfig +BuildRequires: sqlite3 BuildRequires: update-desktop-files BuildRequires: pkgconfig(Qt5Help) BuildRequires: pkgconfig(Qt5Multimedia) BuildRequires: pkgconfig(Qt5Widgets) BuildRequires: pkgconfig(Qt5Xml) -BuildRequires: sqlite3 Requires: mp3gain Supplements: mp3gain @@ -55,7 +56,7 @@ TimeStamp="${date}" LastRegisterTime="${date}.123" %qmake5_install -install -D -m0644 resources/linux/icons/hicolor/256x256/qmp3gain.png %buildroot%_datadir/pixmaps/%name.png +install -D -m0644 resources/linux/icons/hicolor/256x256/qmp3gain.png %{buildroot}%{_datadir}/pixmaps/%{name}.png %suse_update_desktop_file -r %{name} Qt AudioVideo AudioVideoEditing %find_lang %{name} --with-qt @@ -78,8 +79,9 @@ touch -d "@${ts}" * . fi +%fdupes %{buildroot}%{_datadir} + %files -%defattr(-,root,root) %license LICENSE.txt %{_bindir}/%{name} %dir %{_datadir}/%{name}
View file
_service
Changed
@@ -1,7 +1,7 @@ <services> <service name="tar_scm" mode="disabled"> <param name="filename">qmp3gain</param> - <param name="revision">95b26089e80ca1e2aa0b43136e8f153f4f6d0538</param> + <param name="revision">8952ec2f8a7b837b29c05171bf501418bda9038d</param> <param name="scm">git</param> <param name="submodules">disable</param> <param name="url">https://git.code.sf.net/p/qmp3gain/code</param>
View file
qmp3gain-0.9.3.tar.xz/.gitignore -> qmp3gain-0.9.4.tar.xz/.gitignore
Changed
@@ -59,7 +59,9 @@ # QtCreator local machine specific files for imported projects *creator.user* +# Qt others *_qmlcache.qrc +.qmake.stash # Others .*.swp
View file
qmp3gain-0.9.3.tar.xz/CHANGES.md -> qmp3gain-0.9.4.tar.xz/CHANGES.md
Changed
@@ -1,5 +1,15 @@ ## Changes +### Version 0.9.4 + +* Feature: Column widths of tableView are stored in config +* Feature: String columns of tableView got tooltips +* Fix: Adding file using drag&drop which failed with more dots in the filename +* Fix: Crash due to missing values in case of backend abort +* Fix: Crash on showing context menu of tableView without any row +* Fix: Retrieval of current played media filename was buggy (Windows) +* Fix: Launched AppImage could not play MP3 file (Linux) + ### Version 0.9.3 * Fix: Help/Contents did not work from AppImage (Linux)
View file
qmp3gain-0.9.3.tar.xz/INSTALL.md -> qmp3gain-0.9.4.tar.xz/INSTALL.md
Changed
@@ -4,8 +4,8 @@ Download latest AppImage file of QMP3Gain. Make it executable and run. - chmod u+x qmp3gain-0.9.3-linux-x64.AppImage - ./qmp3gain-0.9.3-linux-x64.AppImage + chmod u+x qmp3gain-0.9.4-linux-x64.AppImage + ./qmp3gain-0.9.4-linux-x64.AppImage Linux installer does not contain required mp3gain backend, which must be installed separately. Unless you know how to install it, check the verbose Linux guide(#verbose-linux-guide). @@ -20,17 +20,17 @@ git clone git://qmp3gain.git.sourceforge.net/gitroot/qmp3gain/qmp3gain cd qmp3gain qmake - make + make -j Don't be surprised if the build runs into failure. Probably some dependencies are missing for the successful compilation. In this case check the proper verbose guide out! -### Verbose guide on Linux (Ubuntu 18.04) {#verbose-linux-guide} +### Verbose guide on Linux (Ubuntu 22.04) {#verbose-linux-guide} -1. Install QT SDK (at least v5.9 is required). +1. Install QT SDK (at least v5.15.2 is required). Check it out on https://www.qt.io and https://wiki.qt.io/Install_Qt_5_on_Ubuntu for more info. - sudo apt install qt5-default + sudo apt install qtbase5-dev Or if you want to actively work on the (fork of the) project install QT Creator IDE with its QT dependencies at once. @@ -76,31 +76,30 @@ sudo make uninstall -6. To generate all files for a later installation bundle. +6. Create AppImage installation bundle file which can be run individually in itself by end users. - make deploy - - At first the required dependency must be downloaded and made it executable. +6.1. At first the required dependencies must be downloaded and made them executable. - sudo wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" -O /usr/local/bin/linuxdeployqt - sudo chmod a+x /usr/local/bin/linuxdeployqt - - The generated files are stored in the `dist` directory. + sudo wget -q -c "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" -O /usr/local/bin/linuxdeploy + sudo chmod a+x /usr/local/bin/linuxdeploy + + sudo wget -q -c "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage" -O /usr/local/bin/linuxdeploy-plugin-qt + sudo chmod a+x /usr/local/bin/linuxdeploy-plugin-qt + + sudo wget -q -c "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gstreamer/master/linuxdeploy-plugin-gstreamer.sh" -O /usr/local/bin/linuxdeploy-plugin-gstreamer.sh + sudo chmod a+x /usr/local/bin/linuxdeploy-plugin-gstreamer.sh + +6.2. Dependency linuxdeploy-plugin-gstreamer.sh needs the fllowing package - Important note: this target uses linuxdeployqt(https://github.com/probonopd/linuxdeployqt) which is a great tool to export all (Qt and other) dependencies of the application. Because linuxdeployqt (normally) cannot be run on systems newer than the oldest Ubuntu LTS release, the build must be done on that. If creation of installer is not among your goals, inside installer/installer.pri add `-unsupported-allow-new-glibc` option to `DEPLOY_OPTIONS`. For more info check https://github.com/probonopd/linuxdeployqt/issues/340 + apt-get install patchelf -7. To create AppImage installation bundle file which can be run individually in itself by end users. +6.3. Create AppImage installation bundle file. - make installer - - At first the required dependency must be downloaded and made it executable. - - sudo wget -c "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" -O /usr/local/bin/appimagetool - sudo chmod a+x /usr/local/bin/appimagetool + make deploy - The generated installer file is stored in the `bin` directory. Noted that this `installer` target invokes `deploy` one. + The generated AppDir files are stored in the `dist` directory. The generated AppImage file is stored in the `bin` directory. -8. Unified `README.md` markdown file can be created from different md files scattered in the project. +7. Unified `README.md` markdown file can be created from different md files scattered in the project. make docs @@ -116,13 +115,13 @@ ### Verbose guide on Windows (10) -1. Install QT SDK (at least v5.9 is required) +1. Install QT SDK (at least v5.15.2 is required) - It can be installed from https://www.qt.io/offline-installers + It can be installed from https://www.qt.io/download-open-source using online installer. After QT installation, usually I make a symbolic link from `mingw32-make.exe` file to `make.exe` to ease my work, eg. - cd c:\ProgramFiles\Qt\Qt5.12.11\Tools\mingw730_64\bin + cd c:\ProgramFiles\Qt\Qt5.15.2\Tools\mingw810_64\bin mklink make.exe mingw32-make.exe If you already have a make executable from another developer tool, forget the symbolic link and use original `mingw32-make` instead of "make" later.) @@ -136,7 +135,7 @@ Launch a "Qt command prompt" from the new menu item, and in the downloaded qmp3gain build folder use the following commands: qmake - make + make -j 4. Install mp3gain backend @@ -159,19 +158,13 @@ sudo make uninstall -7. To generate all files for a later installation bundle. +7. Generate files for installation bundle and create installer bundle file which can be run individually in itself by end users. make deploy - The generated files are stored in the `dist` directory. - -8. To create installer bundle file which can be run individually in itself by end users. - - make installer - - The generated installer exe file is stored in the `bin` directory. Noted that this `installer` target invokes `deploy` one. + The generated work files are stored in the `dist` directory but the installer exe file is stored in the `bin` directory. - Remember to copy `mp3gain.exe` into `bin` folder before runnung this target. It is supposed that the Windows installer contains the backend. + Remember to copy `mp3gain.exe` into `bin` folder before running this target. It is supposed that the Windows installer contains the backend. 9. Unified `README.md` markdown file can be created from different md files scattered in the project.
View file
qmp3gain-0.9.3.tar.xz/config.pri -> qmp3gain-0.9.4.tar.xz/config.pri
Changed
@@ -1,14 +1,11 @@ unix|win32: else:error(Only Unix and Windows platforms are supported. Create a new ticket if you want Mac support.) -#!versionAtLeast(QT_VERSION, 5.9.0):error("Use at least Qt version 5.9.0") # versionAtLeast function exists only from 5.10 -if(lessThan(QT_MAJOR_VERSION, 5) | equals(QT_MAJOR_VERSION, 5):lessThan(QT_MINOR_VERSION, 9)) { - error("Use at least Qt version 5.9") -} +!versionAtLeast(QT_VERSION, 5.15.2):error("Use at least Qt version 5.15.2") # application version APP_MAJOR_VER = 0 APP_MINOR_VER = 9 -APP_SUBMINOR_VER = 3 +APP_SUBMINOR_VER = 4 APP_VERSION = "$${APP_MAJOR_VER}.$${APP_MINOR_VER}.$${APP_SUBMINOR_VER}" ROOT = $$shell_path($$PWD) # absolute path containing this file
View file
qmp3gain-0.9.3.tar.xz/docker-compose.yml -> qmp3gain-0.9.4.tar.xz/docker-compose.yml
Changed
@@ -17,8 +17,10 @@ tty: true # docker run -t environment: DISPLAY: + PULSE_SERVER: unix:/run/user/${USER_ID:-0}/pulse/native volumes: - $HOME/.Xauthority:/root/.Xauthority + - /run/user/${USER_ID:-0}/pulse/native:/run/user/${USER_ID:-0}/pulse/native - .:/home/zematix/qmp3gain test: @@ -36,6 +38,8 @@ tty: true # docker run -t environment: DISPLAY: + PULSE_SERVER: unix:/run/user/${USER_ID:-0}/pulse/native volumes: - $HOME/.Xauthority:/root/.Xauthority + - /run/user/${USER_ID:-0}/pulse/native:/run/user/${USER_ID:-0}/pulse/native - .:/home/zematix/qmp3gain
View file
qmp3gain-0.9.3.tar.xz/docker/README.md -> qmp3gain-0.9.4.tar.xz/docker/README.md
Changed
@@ -12,6 +12,8 @@ * build * test +Both images based on the oldest still-supported Ubuntu LTS version. If the application is built on that, the resulting binaries should be able to run on newer (but not older) systems (Ubuntu and other distributions). If compatibilty with as many target systems as possible is not an issue for you, for example building the application in your up-to-date local system on your own, it can be also feasible without the docker containers. + ### Usage Start a terminal and change your current/working directory to the qmp3gain root folder. All commands bellow must be launched from there. @@ -46,5 +48,5 @@ docker-compose build -and start the containers in detached mode again. +and start the containers in detached mode again if you want.
View file
qmp3gain-0.9.3.tar.xz/docker/build/Dockerfile -> qmp3gain-0.9.4.tar.xz/docker/build/Dockerfile
Changed
@@ -1,22 +1,40 @@ +## Build image creator of qmap3gain app FROM ubuntu:18.04 +ENV DEBIAN_FRONTEND=noninteractive +ENV PATH="$PATH:/usr/local/Qt-5.15.3/bin" +ENV LD_LIBRARY_PATH="/usr/local/Qt-5.15.3/lib:${LD_LIBRARY_PATH}" ## values should be overwitten in local .env file ARG USER_ID=1001 ARG GROUP_ID=100 -## install fuse (for linuxdeployqt), mp3gain, qt5 and wget +## install fuse (for creating qmp3gain AppImage), mp3gain, gstreamer and qt5 RUN set -x; \ apt-get update &&\ apt-get install -y software-properties-common &&\ add-apt-repository -y ppa:sicklylife/qtgain &&\ apt-get update &&\ - apt-get install -y fuse mp3gain qt5-default qtmultimedia5-dev qttools5-dev wget sudo &&\ - wget -q -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" -O /usr/local/bin/linuxdeployqt &&\ - chmod a+x /usr/local/bin/linuxdeployqt &&\ - wget -q -c "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" -O /usr/local/bin/appimagetool &&\ - chmod a+x /usr/local/bin/appimagetool &&\ + apt-get install -y sudo fuse mp3gain wget &&\ + apt-get install -y build-essential libgl1-mesa-dev libfontconfig1-dev libfreetype6-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libxcb-cursor-dev libxcb-glx0-dev libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-util-dev libxcb-xinerama0-dev libxcb-xkb-dev libxkbcommon-dev libxkbcommon-x11-dev &&\ + apt-get install -y libasound2-dev libcups2-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-good gstreamer1.0-plugins-bad &&\ + wget -q -c "https://download.qt.io/archive/qt/5.15/5.15.3/single/qt-everywhere-opensource-src-5.15.3.tar.xz" -O /tmp/qt-everywhere-opensource-src-5.15.3.tar.xz &&\ + cd /tmp &&\ + tar -xf qt-everywhere-opensource-src-5.15.3.tar.xz &&\ + rm -f qt-everywhere-opensource-src-5.15.3.tar.xz &&\ + cd qt-everywhere-src-5.15.3 &&\ + ./configure -opensource -confirm-license -release -no-opengl -nomake examples -nomake tests &&\ + make -j $(nproc) &&\ + make install &&\ + rm -rf /tmp/qt-everywhere-src-5.15.3 &&\ + wget -q -c "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" -O /usr/local/bin/linuxdeploy &&\ + chmod a+x /usr/local/bin/linuxdeploy &&\ + wget -q -c "https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage" -O /usr/local/bin/linuxdeploy-plugin-qt &&\ + chmod a+x /usr/local/bin/linuxdeploy-plugin-qt &&\ + wget -q -c "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gstreamer/master/linuxdeploy-plugin-gstreamer.sh" -O /usr/local/bin/linuxdeploy-plugin-gstreamer.sh &&\ + chmod a+x /usr/local/bin/linuxdeploy-plugin-gstreamer.sh &&\ + apt-get install -y patchelf &&\ rm -rf /var/lib/apt/lists/* - + ## create working user and its group RUN set -x; \ if ${USER_ID:-0} -ne 0 && ${GROUP_ID:-0} -ne 0 ; then \ @@ -27,7 +45,7 @@ fi &&\ groupadd -f -g ${GROUP_ID} zematix &&\ useradd -l -u ${USER_ID} -g zematix zematix &&\ - echo "zematix:zematix" | chpasswd && adduser zematix sudo &&\ + echo "zematix:zematix" | chpasswd && adduser zematix sudo && adduser zematix audio &&\ install -d -m 0755 -o zematix -g zematix /home/zematix \ ;fi
View file
qmp3gain-0.9.3.tar.xz/docker/test/Dockerfile -> qmp3gain-0.9.4.tar.xz/docker/test/Dockerfile
Changed
@@ -1,16 +1,19 @@ +## Test image creator of qmp3gain app FROM ubuntu:18.04 +ENV DEBIAN_FRONTEND=noninteractive ## values should be overwitten in local .env file ARG USER_ID=1001 ARG GROUP_ID=100 -## install fuse (for running qmp3gain AppImage) and mp3gain +## install fuse (for running AppImage), mp3gain and some essential application dependencies RUN set -x; \ apt-get update &&\ apt-get install -y software-properties-common &&\ add-apt-repository -y ppa:sicklylife/qtgain &&\ apt-get update &&\ - apt-get install -y fuse libgl1 libharfbuzz0b libfontconfig1 libsm6 mp3gain sudo &&\ + apt-get install -y sudo fuse mp3gain &&\ + apt-get install -y libgl1 libharfbuzz0b libfontconfig1 libsm6 pulseaudio &&\ rm -rf /var/lib/apt/lists/* ## create working user and its group @@ -23,7 +26,7 @@ fi &&\ groupadd -f -g ${GROUP_ID} zematix &&\ useradd -l -u ${USER_ID} -g zematix zematix &&\ - echo "zematix:zematix" | chpasswd && adduser zematix sudo &&\ + echo "zematix:zematix" | chpasswd && adduser zematix sudo && adduser zematix audio &&\ install -d -m 0755 -o zematix -g zematix /home/zematix \ ;fi @@ -31,7 +34,7 @@ RUN set -x; \ mkdir -p /home/zematix/qmp3gain && \ chown -hR zematix:zematix /home/zematix/qmp3gain - + USER zematix WORKDIR /home/zematix/qmp3gain
View file
qmp3gain-0.9.3.tar.xz/help/html/MP3Gain.htm -> qmp3gain-0.9.4.tar.xz/help/html/MP3Gain.htm
Changed
@@ -14,11 +14,11 @@ <center> <h2 style="text-align: center">QMP3Gain</h2> -<h4>version 0.9.1</h4> +<h4>version 0.9.4</h4> <h4><img src="MP3Gain.gif"></h4> -<h4>Copyright © 2009-2021 by Zsolt Branyiczky</h4> +<h4>Copyright © 2009-2023 by Zsolt Branyiczky</h4> </body>
View file
qmp3gain-0.9.3.tar.xz/help/qmp3gain.qhp -> qmp3gain-0.9.4.tar.xz/help/qmp3gain.qhp
Changed
@@ -1,14 +1,14 @@ <?xml version="1.0" encoding="UTF-8"?> <QtHelpProject version="1.0"> - <namespace>zematix.hu.qmp3gain.0.9.0</namespace> + <namespace>zematix.hu.qmp3gain.0.9.4</namespace> <virtualFolder>help</virtualFolder> - <customFilter name="QMP3Gain 0.9.0"> + <customFilter name="QMP3Gain 0.9.4"> <filterAttribute>qmp3gain</filterAttribute> - <filterAttribute>0.9.3</filterAttribute> + <filterAttribute>0.9.4</filterAttribute> </customFilter> <filterSection> <filterAttribute>qmp3gain</filterAttribute> - <filterAttribute>0.9.3</filterAttribute> + <filterAttribute>0.9.4</filterAttribute> <toc> <section title="QMP3Gain Help" ref="html/MP3Gain.htm"> <section title="Overview" ref="html/Overview.htm"/>
View file
qmp3gain-0.9.3.tar.xz/installer/config/config.xml -> qmp3gain-0.9.4.tar.xz/installer/config/config.xml
Changed
@@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <Installer> <Name>QMP3Gain</Name> - <Version>0.9.1</Version> + <Version>0.9.4</Version> <Title>QMP3Gain</Title> <Publisher>Zematix</Publisher> <ProductUrl>https://sourceforge.net/projects/qmp3gain/</ProductUrl>
View file
qmp3gain-0.9.3.tar.xz/installer/installer.pri -> qmp3gain-0.9.4.tar.xz/installer/installer.pri
Changed
@@ -8,10 +8,6 @@ DEBDIR = $$shell_path($$ROOT/deb) INSTALLERDIR = $$shell_path($$PWD) -unix { - DEPLOY_OPTIONS = "-no-translations -no-copy-copyright-files -bundle-non-qt-libs" - #DEPLOY_OPTIONS = "-no-translations -no-copy-copyright-files -bundle-non-qt-libs -unsupported-allow-new-glibc" # discoured use to run on latest systems - just for test purpose -} win32 { DEPLOY_OPTIONS = "--no-svg --no-system-d3d-compiler --no-opengl --no-angle --no-opengl-sw --no-translations" } @@ -23,7 +19,6 @@ mkdir -p $${DEPLOYDIR}/usr/bin &&\ cp $$ROOT/bin/qmp3gain $${DEPLOYDIR}/usr/bin &&\ mkdir -p $${DEPLOYDIR}/usr/share &&\ - cp -r $$ROOT/resources/linux/* $${DEPLOYDIR}/usr/share &&\ mkdir -p $${DEPLOYDIR}/usr/share/$${TARGET}/resources/sounds &&\ cp -r $$ROOT/resources/sounds/* $${DEPLOYDIR}/usr/share/$${TARGET}/resources/sounds &&\ mkdir -p $${DEPLOYDIR}/usr/share/$${TARGET}/help &&\ @@ -32,39 +27,31 @@ cp $$QT_INSTALL_BINS/assistant $${DEPLOYDIR}/usr/bin &&\ mkdir -p $${DEPLOYDIR}/usr/share/$${TARGET}/translations &&\ cp $$ROOT/translations/qmp3gain_*.qm $${DEPLOYDIR}/usr/share/$${TARGET}/translations &&\ - linuxdeployqt $${DEPLOYDIR}/usr/share/applications/$${TARGET}.desktop $${DEPLOY_OPTIONS} -executable=$${DEPLOYDIR}/usr/bin/assistant -extra-plugins=printsupport,sqldrivers + linuxdeploy --appdir $${DEPLOYDIR} -i $$ROOT/resources/linux/icons/hicolor/256x256/$${TARGET}.png --icon-filename=qmp3gain -d $$ROOT/resources/linux/applications/$${TARGET}.desktop --plugin qt --plugin gstreamer --output appimage &&\ + mv $$ROOT/QMP3Gain-x86_64.AppImage $$ROOT/bin/$${TARGET}-$${APP_VERSION}-linux-x64.AppImage } win32 { - deploy.commands = windeployqt $${DEPLOY_OPTIONS} --qthelp --printsupport --sql --dir $${DEPLOYDIR} $${DESTDIR}//$${TARGET}.exe & \ - copy $${DESTDIR}\\$${TARGET}.exe $${DEPLOYDIR} & \ - if not exist $${DESTDIR}\\mp3gain.exe ( echo "Backend mp3gain.exe must copied into $$DESTDIR" ) $$escape_expand(\n\t) \ - copy $${DESTDIR}\\mp3gain.exe $${DEPLOYDIR} && \ - xcopy /s /y $$ROOT\resources\sounds $${DEPLOYDIR}\\resources\sounds\ & \ - if not exist $${DEPLOYDIR}\\help ( mkdir $${DEPLOYDIR}\\help ) $$escape_expand(\n\t) \ - copy $$ROOT\help\qmp3gain.qhc $${DEPLOYDIR}\\help & \ - copy $$ROOT\help\qmp3gain.qch $${DEPLOYDIR}\\help & \ - copy $$shell_path($$QT_INSTALL_BINS\assistant.exe) $${DEPLOYDIR} & \ - if not exist $${DEPLOYDIR}\\translations ( mkdir $${DEPLOYDIR}\\translations ) $$escape_expand(\n\t) \ - copy $$ROOT\translations\qmp3gain_*.qm $${DEPLOYDIR}\\translations + deploy.commands = @if not exist $${DESTDIR}\\mp3gain.exe ( echo "Backend mp3gain.exe must copied into $$DESTDIR" ) $$escape_expand(\n\t) \ + @if not exist $${DESTDIR}\\mp3gain.exe ( exit 1 ) $$escape_expand(\n\t) \ + if exist $${DEPLOYDIR} ( rmdir /s /q $${DEPLOYDIR} ) $$escape_expand(\n\t) \ + mkdir $${DEPLOYDIR}\main\data & \ + copy $${DESTDIR}\\mp3gain.exe $${DEPLOYDIR}\main\data && \ + windeployqt $${DEPLOY_OPTIONS} --qthelp --printsupport --sql --dir $${DEPLOYDIR}\main\data $${DESTDIR}//$${TARGET}.exe & \ + copy $${DESTDIR}\\$${TARGET}.exe $${DEPLOYDIR}\main\data & \ + xcopy /s /y $$ROOT\resources\sounds $${DEPLOYDIR}\\main\\data\\resources\sounds\ & \ + if not exist $${DEPLOYDIR}\\main\\data\\help ( mkdir $${DEPLOYDIR}\\main\\data\\help ) $$escape_expand(\n\t) \ + copy $$ROOT\help\qmp3gain.qhc $${DEPLOYDIR}\\main\\data\\help & \ + copy $$ROOT\help\qmp3gain.qch $${DEPLOYDIR}\\main\\data\\help & \ + copy $$shell_path($$QT_INSTALL_BINS\assistant.exe) $${DEPLOYDIR}\\main\\data & \ + if not exist $${DEPLOYDIR}\\main\\data\\\translations ( mkdir $${DEPLOYDIR}\\main\\data\\translations ) $$escape_expand(\n\t) \ + copy $$ROOT\translations\qmp3gain_*.qm $${DEPLOYDIR}\\main\\data\\translations & \ + xcopy /s /y $$INSTALLERDIR\packages\main\meta $${DEPLOYDIR}\main\meta\ & \ + lrelease $${DEPLOYDIR}\main\meta\hu.ts & \ + binarycreator --offline-only -c $${INSTALLERDIR}\config\config.xml -p $${DEPLOYDIR} $${DESTDIR}\qmp3gain-$${APP_VERSION}-win-x64-installer.exe } QMAKE_EXTRA_TARGETS += deploy unix { - installer.commands = appimagetool $${DEPLOYDIR} bin/$${TARGET}-$${APP_VERSION}-linux-x64.AppImage -} -win32 { - installer.commands = \ - move $${DEPLOYDIR} $${INSTALLERDIR}\packages\main\ & \ - if exist $${INSTALLERDIR}\packages\main\data ( rmdir /s /q $${INSTALLERDIR}\packages\main\data ) $$escape_expand(\n\t) \ - rename $${INSTALLERDIR}\packages\main\dist data & \ - lrelease $${INSTALLERDIR}\packages\main\meta\hu.ts & \ - binarycreator --offline-only -c $${INSTALLERDIR}\config\config.xml -p $${INSTALLERDIR}\packages $${DESTDIR}\qmp3gain-$${APP_VERSION}-win-x64-installer.exe & \ - if exist $${INSTALLERDIR}\packages\main\data ( rmdir /s /q $${INSTALLERDIR}\packages\main\data ) -} -installer.depends = deploy -QMAKE_EXTRA_TARGETS += installer - -unix { deb.commands = \ mkdir -p $${DEBDIR}/usr/bin &&\ cp $$ROOT/bin/qmp3gain $${DEBDIR}/usr/bin &&\ @@ -82,7 +69,7 @@ cd $$INSTALLERDIR && mv DEBIAN debian && dpkg-shlibdeps $$ROOT/bin/qmp3gain && mv debian DEBIAN && cd $$ROOT &&\ dpkg-deb --build --root-owner-group $$DEBDIR &&\ rm -f $$INSTALLERDIR/DEBIAN/substvars &&\ - mv deb.deb bin/$${TARGET}-$${APP_VERSION}-linux-x64.deb + mv deb.deb $$ROOT/bin/$${TARGET}-$${APP_VERSION}-linux-x64.deb } QMAKE_EXTRA_TARGETS += deb @@ -92,7 +79,6 @@ win32 { extradistclean.commands = \ if exist $${DEPLOYDIR} ( rmdir /s /q $${DEPLOYDIR} ) $$escape_expand(\n\t) \ - if exist $${INSTALLERDIR}\packages\main\data ( rmdir /s /q $${INSTALLERDIR}\packages\main\data ) } distclean.depends = extradistclean QMAKE_EXTRA_TARGETS += distclean extradistclean
View file
qmp3gain-0.9.3.tar.xz/installer/packages/main/meta/package.xml -> qmp3gain-0.9.4.tar.xz/installer/packages/main/meta/package.xml
Changed
@@ -4,9 +4,10 @@ <DisplayName xml:lang="hu_HU">Főkomponens</DisplayName> <Description>Install QMP3Gain application. It contains a single component.</Description> <Description xml:lang="hu">QMP3Gain alkalmazás telepítése. Mindössze egyetlen komponenst tartalmaz.</Description> - <Version>0.9.1</Version> + <Description xml:lang="it">Installa l'applicazione QMP3Gain. Contiene un solo componente.</Description> + <Version>0.9.4</Version> <Name>main</Name> - <ReleaseDate>2021-09-10</ReleaseDate> + <ReleaseDate>2023-12-27</ReleaseDate> <ForcedInstallation>true</ForcedInstallation> <Licenses> <License name="GNU General Public License" file="LICENSE.txt" />
View file
qmp3gain-0.9.3.tar.xz/src/aboutdialog.cpp -> qmp3gain-0.9.4.tar.xz/src/aboutdialog.cpp
Changed
@@ -7,35 +7,35 @@ AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent) { - setupUi(this); - - MainWindow* mainWindow = qobject_cast<MainWindow*>(this->parent()); - setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); - - // english makes translationLabel invisible - translationLabel->setVisible(false); - //translationVerticalSpacer->setVisible(false); - - // set appTitle, e.g. "%1 (GUI)" -> "QMP3Gain (GUI)" - appTitleLabel->setText(appTitleLabel->text().arg(MainWindow::getAppTitle())); - - // add appVersion to label, e.g. "Version %1" -> "Version 1.3.4" - appVersionLabel->setText(appVersionLabel->text().arg(MainWindow::getAppVersion())); - - // add backEnd to label - QFileInfo fi(mainWindow->getBackEnd()); - backEndLabel->setText(backEndLabel->text().arg(fi.baseName())); - - // add backEndVersion to label - backEndVersionLabel->setText(backEndVersionLabel->text().arg(mainWindow->getBackEndVersion())); - - latestAppVersionAtLabel->setText(latestAppVersionAtLabel->text().arg(MainWindow::getAppTitle())); + setupUi(this); + + MainWindow* mainWindow = qobject_cast<MainWindow*>(this->parent()); + setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); + + // english makes translationLabel invisible + translationLabel->setVisible(false); + //translationVerticalSpacer->setVisible(false); + + // set appTitle, e.g. "%1 (GUI)" -> "QMP3Gain (GUI)" + appTitleLabel->setText(appTitleLabel->text().arg(MainWindow::getAppTitle())); + + // add appVersion to label, e.g. "Version %1" -> "Version 1.3.4" + appVersionLabel->setText(appVersionLabel->text().arg(MainWindow::getAppVersion())); + + // add backEnd to label + QFileInfo fi(mainWindow->getBackEnd()); + backEndLabel->setText(backEndLabel->text().arg(fi.baseName())); + + // add backEndVersion to label + backEndVersionLabel->setText(backEndVersionLabel->text().arg(mainWindow->getBackEndVersion())); + + latestAppVersionAtLabel->setText(latestAppVersionAtLabel->text().arg(MainWindow::getAppTitle())); } void AboutDialog::on_donationButton_clicked() { - // modal dialog - DonationDialog donationDialog(this); - if (donationDialog.exec()) { - this->accept(); - } + // modal dialog + DonationDialog donationDialog(this); + if (donationDialog.exec()) { + this->accept(); + } }
View file
qmp3gain-0.9.3.tar.xz/src/aboutdialog.h -> qmp3gain-0.9.4.tar.xz/src/aboutdialog.h
Changed
@@ -13,7 +13,7 @@ AboutDialog(QWidget *parent = 0); private slots: - void on_donationButton_clicked(); + void on_donationButton_clicked(); }; #endif
View file
qmp3gain-0.9.3.tar.xz/src/advancedoptionsdialog.cpp -> qmp3gain-0.9.4.tar.xz/src/advancedoptionsdialog.cpp
Changed
@@ -4,78 +4,78 @@ AdvancedOptionsDialog::AdvancedOptionsDialog(QWidget *parent) : QDialog(parent) { - setupUi(this); - - setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); + setupUi(this); - // fill fields vector with checkable control elements - { - fields << checkBox_Maximizing; - fields << horizontalSlider_logBackendDepth; - fields << horizontalSlider_logTraceDepth; - fields << checkBox_ShowHiddenFields; - fields << spinBox_beepAfter; - fields << checkBox_UseNoTempFiles; - fields << checkBox_ShowNoFileProgress; - fields << radioButton_threadRealtime; - fields << radioButton_threadHigh; - fields << radioButton_threadNormal; - fields << radioButton_threadIdle; - } - - MainWindow* mainWindow = qobject_cast<MainWindow*>(this->parent()); - readSettings(mainWindow->getSettings()); - - isAccepted = false; - horizontalSlider_logBackendDepth_origValue = horizontalSlider_logBackendDepth->value(); - horizontalSlider_logTraceDepth_origValue = horizontalSlider_logTraceDepth->value(); - spinBox_beepAfter_origValue = spinBox_beepAfter->value(); - } + setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); + + // fill fields vector with checkable control elements + { + fields << checkBox_Maximizing; + fields << horizontalSlider_logBackendDepth; + fields << horizontalSlider_logTraceDepth; + fields << checkBox_ShowHiddenFields; + fields << spinBox_beepAfter; + fields << checkBox_UseNoTempFiles; + fields << checkBox_ShowNoFileProgress; + fields << radioButton_threadRealtime; + fields << radioButton_threadHigh; + fields << radioButton_threadNormal; + fields << radioButton_threadIdle; + } + + MainWindow* mainWindow = qobject_cast<MainWindow*>(this->parent()); + readSettings(mainWindow->getSettings()); + + isAccepted = false; + horizontalSlider_logBackendDepth_origValue = horizontalSlider_logBackendDepth->value(); + horizontalSlider_logTraceDepth_origValue = horizontalSlider_logTraceDepth->value(); + spinBox_beepAfter_origValue = spinBox_beepAfter->value(); +} AdvancedOptionsDialog::~AdvancedOptionsDialog(){ - if (isAccepted){ - MainWindow* mainWindow = qobject_cast<MainWindow*>(this->parent()); - writeSettings(mainWindow->getSettings()); - if (horizontalSlider_logBackendDepth->value() != horizontalSlider_logBackendDepth_origValue){ - mainWindow->actionLogBackend->setChecked(horizontalSlider_logBackendDepth->value() > 0); - } - if (horizontalSlider_logTraceDepth->value() != horizontalSlider_logTraceDepth_origValue){ - mainWindow->actionLogTrace->setChecked(horizontalSlider_logTraceDepth->value() > 0); - } - } + if (isAccepted){ + MainWindow* mainWindow = qobject_cast<MainWindow*>(this->parent()); + writeSettings(mainWindow->getSettings()); + if (horizontalSlider_logBackendDepth->value() != horizontalSlider_logBackendDepth_origValue){ + mainWindow->actionLogBackend->setChecked(horizontalSlider_logBackendDepth->value() > 0); + } + if (horizontalSlider_logTraceDepth->value() != horizontalSlider_logTraceDepth_origValue){ + mainWindow->actionLogTrace->setChecked(horizontalSlider_logTraceDepth->value() > 0); + } + } } void AdvancedOptionsDialog::readSettings(QSettings *settings){ - settings->beginGroup("advancedOptionsDialog"); - for (int i=0; i<fields.count(); i++){ - if (fieldsi->objectName().startsWith("horizontalSlider")) - (qobject_cast<QSlider*>(fieldsi))->setValue(settings->value(fieldsi->objectName(), (qobject_cast<QSlider*>(fieldsi))->value()).toInt()); - if (fieldsi->objectName().startsWith("spinBox")) - (qobject_cast<QSpinBox*>(fieldsi))->setValue(settings->value(fieldsi->objectName(), (qobject_cast<QSpinBox*>(fieldsi))->value()).toInt()); - else if (fieldsi->objectName().startsWith("checkBox")) - (qobject_cast<QCheckBox*>(fieldsi))->setChecked(settings->value(fieldsi->objectName(), (qobject_cast<QCheckBox*>(fieldsi))->isChecked()).toBool()); - else if (fieldsi->objectName().startsWith("radioButton")) - (qobject_cast<QRadioButton*>(fieldsi))->setChecked(settings->value(fieldsi->objectName(), (qobject_cast<QRadioButton*>(fieldsi))->isChecked()).toBool()); - } - settings->endGroup(); + settings->beginGroup("advancedOptionsDialog"); + for (int i=0; i<fields.count(); i++){ + if (fieldsi->objectName().startsWith("horizontalSlider")) + (qobject_cast<QSlider*>(fieldsi))->setValue(settings->value(fieldsi->objectName(), (qobject_cast<QSlider*>(fieldsi))->value()).toInt()); + if (fieldsi->objectName().startsWith("spinBox")) + (qobject_cast<QSpinBox*>(fieldsi))->setValue(settings->value(fieldsi->objectName(), (qobject_cast<QSpinBox*>(fieldsi))->value()).toInt()); + else if (fieldsi->objectName().startsWith("checkBox")) + (qobject_cast<QCheckBox*>(fieldsi))->setChecked(settings->value(fieldsi->objectName(), (qobject_cast<QCheckBox*>(fieldsi))->isChecked()).toBool()); + else if (fieldsi->objectName().startsWith("radioButton")) + (qobject_cast<QRadioButton*>(fieldsi))->setChecked(settings->value(fieldsi->objectName(), (qobject_cast<QRadioButton*>(fieldsi))->isChecked()).toBool()); + } + settings->endGroup(); } void AdvancedOptionsDialog::writeSettings(QSettings *settings){ - settings->beginGroup("advancedOptionsDialog"); - for (int i=0; i<fields.count(); i++){ - if (fieldsi->objectName().startsWith("horizontalSlider")) - settings->setValue(fieldsi->objectName(), (qobject_cast<QSlider*>(fieldsi))->value()); - if (fieldsi->objectName().startsWith("spinBox")) - settings->setValue(fieldsi->objectName(), (qobject_cast<QSpinBox*>(fieldsi))->value()); - else if (fieldsi->objectName().startsWith("checkBox")) - settings->setValue(fieldsi->objectName(), (qobject_cast<QCheckBox*>(fieldsi))->isChecked()); - else if (fieldsi->objectName().startsWith("radioButton")) - settings->setValue(fieldsi->objectName(), (qobject_cast<QRadioButton*>(fieldsi))->isChecked()); - } - settings->endGroup(); + settings->beginGroup("advancedOptionsDialog"); + for (int i=0; i<fields.count(); i++){ + if (fieldsi->objectName().startsWith("horizontalSlider")) + settings->setValue(fieldsi->objectName(), (qobject_cast<QSlider*>(fieldsi))->value()); + if (fieldsi->objectName().startsWith("spinBox")) + settings->setValue(fieldsi->objectName(), (qobject_cast<QSpinBox*>(fieldsi))->value()); + else if (fieldsi->objectName().startsWith("checkBox")) + settings->setValue(fieldsi->objectName(), (qobject_cast<QCheckBox*>(fieldsi))->isChecked()); + else if (fieldsi->objectName().startsWith("radioButton")) + settings->setValue(fieldsi->objectName(), (qobject_cast<QRadioButton*>(fieldsi))->isChecked()); + } + settings->endGroup(); } void AdvancedOptionsDialog::accept(){ - isAccepted = true; - return QDialog::accept(); + isAccepted = true; + return QDialog::accept(); }
View file
qmp3gain-0.9.3.tar.xz/src/advancedoptionsdialog.h -> qmp3gain-0.9.4.tar.xz/src/advancedoptionsdialog.h
Changed
@@ -11,20 +11,20 @@ Q_OBJECT public: - AdvancedOptionsDialog(QWidget *parent = 0); - ~AdvancedOptionsDialog(); + AdvancedOptionsDialog(QWidget *parent = 0); + ~AdvancedOptionsDialog(); private: - bool isAccepted; - int horizontalSlider_logBackendDepth_origValue; - int horizontalSlider_logTraceDepth_origValue; - int spinBox_beepAfter_origValue; - QVector<QObject*> fields; - void readSettings(QSettings *settings); - void writeSettings(QSettings *settings); + bool isAccepted; + int horizontalSlider_logBackendDepth_origValue; + int horizontalSlider_logTraceDepth_origValue; + int spinBox_beepAfter_origValue; + QVector<QObject*> fields; + void readSettings(QSettings *settings); + void writeSettings(QSettings *settings); private slots: - void accept(); + void accept(); }; #endif
View file
qmp3gain-0.9.3.tar.xz/src/backenddialog.cpp -> qmp3gain-0.9.4.tar.xz/src/backenddialog.cpp
Changed
@@ -5,65 +5,65 @@ BackEndDialog::BackEndDialog(QWidget *parent) : QDialog(parent) { - setupUi(this); + setupUi(this); - mainWindow = qobject_cast<MainWindow*>(this->parent()); - setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); + mainWindow = qobject_cast<MainWindow*>(this->parent()); + setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); - label_Status_Orig = label_Status->text(); - label_Version_Orig = label_Version->text(); + label_Status_Orig = label_Status->text(); + label_Version_Orig = label_Version->text(); - lineEdit_fileName->setText(mainWindow->getBackEndFileName()); - refreshStatusAndVersion(true); - - isAccepted = false; + lineEdit_fileName->setText(mainWindow->getBackEndFileName()); + refreshStatusAndVersion(true); + + isAccepted = false; } BackEndDialog::~BackEndDialog(){ - if (isAccepted){ - mainWindow->setBackEndFileName(lineEdit_fileName->text()); + if (isAccepted){ + mainWindow->setBackEndFileName(lineEdit_fileName->text()); QString version = label_Version->text().remove(QRegExp("^.*: ")); // "Version: 1.6.2" -> "1.6.2" mainWindow->setBackEndVersion(version); - } + } } void BackEndDialog::refreshStatusAndVersion(bool isInit){ - bool isStatusOk = false; - QString status = "<b><font color=red>"+tr("invalid")+"</font></b>"; - QString version = ""; - QString backEndVersion = isInit ? mainWindow->getBackEndVersion() : mainWindow->findBackEndVersionByProcess(lineEdit_fileName->text()); - if (backEndVersion.isEmpty()){ - status = "<b><font color=red>"+tr("invalid (not found)")+"</font></b>"; - } - else if(!mainWindow->isBackEndAvailable(backEndVersion)) - { - status = "<b><font color=red>"+tr("invalid (%1 or later required)").arg(mainWindow->getRequiredBackEndVersion())+"</font></b>"; - version = backEndVersion; - } - else{ - status = "<b><font color=green>"+tr("ok")+"</font></b>"; - isStatusOk = true; - version = backEndVersion; - } - label_Status->setText(label_Status_Orig.arg(status)); - label_Version->setText(label_Version_Orig.arg(version)); - buttonBox->button(QDialogButtonBox::Ok)->setEnabled(isStatusOk); + bool isStatusOk = false; + QString status = "<b><font color=red>"+tr("invalid")+"</font></b>"; + QString version = ""; + QString backEndVersion = isInit ? mainWindow->getBackEndVersion() : mainWindow->findBackEndVersionByProcess(lineEdit_fileName->text()); + if (backEndVersion.isEmpty()){ + status = "<b><font color=red>"+tr("invalid (not found)")+"</font></b>"; + } + else if(!mainWindow->isBackEndAvailable(backEndVersion)) + { + status = "<b><font color=red>"+tr("invalid (%1 or later required)").arg(mainWindow->getRequiredBackEndVersion())+"</font></b>"; + version = backEndVersion; + } + else{ + status = "<b><font color=green>"+tr("ok")+"</font></b>"; + isStatusOk = true; + version = backEndVersion; + } + label_Status->setText(label_Status_Orig.arg(status)); + label_Version->setText(label_Version_Orig.arg(version)); + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(isStatusOk); } void BackEndDialog::accept(){ - isAccepted = true; - return QDialog::accept(); + isAccepted = true; + return QDialog::accept(); } void BackEndDialog::on_toolButton_fileName_clicked(){ - QString fileName = QFileDialog::getOpenFileName(this, tr("Select back end mp3gain executable file"), - lineEdit_fileName->text(), QString()); - if (!fileName.isEmpty()){ - lineEdit_fileName->setText(fileName); - refreshStatusAndVersion(false); - } + QString fileName = QFileDialog::getOpenFileName(this, tr("Select back end mp3gain executable file"), + lineEdit_fileName->text(), QString()); + if (!fileName.isEmpty()){ + lineEdit_fileName->setText(fileName); + refreshStatusAndVersion(false); + } } void BackEndDialog::on_lineEdit_fileName_editingFinished(){ - refreshStatusAndVersion(false); + refreshStatusAndVersion(false); }
View file
qmp3gain-0.9.3.tar.xz/src/backenddialog.h -> qmp3gain-0.9.4.tar.xz/src/backenddialog.h
Changed
@@ -11,20 +11,20 @@ Q_OBJECT public: - BackEndDialog(QWidget *parent = 0); - ~BackEndDialog(); + BackEndDialog(QWidget *parent = 0); + ~BackEndDialog(); private: - bool isAccepted; - void refreshStatusAndVersion(bool isInit); - MainWindow* mainWindow; - QString label_Status_Orig; - QString label_Version_Orig; + bool isAccepted; + void refreshStatusAndVersion(bool isInit); + MainWindow* mainWindow; + QString label_Status_Orig; + QString label_Version_Orig; private slots: - void accept(); - void on_toolButton_fileName_clicked(); - void on_lineEdit_fileName_editingFinished(); + void accept(); + void on_toolButton_fileName_clicked(); + void on_lineEdit_fileName_editingFinished(); }; #endif
View file
qmp3gain-0.9.3.tar.xz/src/constantgainchangedialog.cpp -> qmp3gain-0.9.4.tar.xz/src/constantgainchangedialog.cpp
Changed
@@ -3,41 +3,41 @@ #include "mymessagebox.h" ConstantGainChangeDialog::ConstantGainChangeDialog(QWidget *parent) - : QDialog(parent) + : QDialog(parent) { - setupUi(this); + setupUi(this); - setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); + setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); - connect(horizontalSlider_constGainChange, SIGNAL(valueChanged(int)), this, SLOT(updateLineEdit_constGainChange(int))); - connect(groupBox_onlyOneChannel, SIGNAL(toggled(bool)), this, SLOT(groupBox_onlyOneChannel_toggled(bool))); + connect(horizontalSlider_constGainChange, SIGNAL(valueChanged(int)), this, SLOT(updateLineEdit_constGainChange(int))); + connect(groupBox_onlyOneChannel, SIGNAL(toggled(bool)), this, SLOT(groupBox_onlyOneChannel_toggled(bool))); - updateLineEdit_constGainChange(horizontalSlider_constGainChange->value()); + updateLineEdit_constGainChange(horizontalSlider_constGainChange->value()); } ConstantGainChangeDialog::~ConstantGainChangeDialog(){ } void ConstantGainChangeDialog::updateLineEdit_constGainChange(int value){ - lineEdit_constGainChange->setText(QString("%1").arg((double)value*1.5, 0, 'f', 1)); - buttonBox->button(QDialogButtonBox::Ok)->setEnabled(value!=0); + lineEdit_constGainChange->setText(QString("%1").arg((double)value*1.5, 0, 'f', 1)); + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(value!=0); } void ConstantGainChangeDialog::groupBox_onlyOneChannel_toggled(bool isOn){ - if (isOn){ - MainWindow* mainWindow = qobject_cast<MainWindow*>(this->parent()); - mainWindow->getSettings()->beginGroup("logOptionsDialog"); - bool isConfirmSuppressed = mainWindow->getSettings()->value("groupBox_onlyOneChannel_ConfirmSuppressed", false).toBool(); - if (!isConfirmSuppressed){ - MyMessageBox::warning(this, MainWindow::getAppTitle()+QString(" - ")+tr("Warning"), - tr("This function will only work if the mp3 is encoded as " - "stereo or dual channel, NOT joint-stereo or mono."), - tr("Don't show this warning again"), - isConfirmSuppressed); - if (isConfirmSuppressed){ - mainWindow->getSettings()->setValue("groupBox_onlyOneChannel_ConfirmSuppressed", true); - } - } - mainWindow->getSettings()->endGroup(); - } + if (isOn){ + MainWindow* mainWindow = qobject_cast<MainWindow*>(this->parent()); + mainWindow->getSettings()->beginGroup("logOptionsDialog"); + bool isConfirmSuppressed = mainWindow->getSettings()->value("groupBox_onlyOneChannel_ConfirmSuppressed", false).toBool(); + if (!isConfirmSuppressed){ + MyMessageBox::warning(this, MainWindow::getAppTitle()+QString(" - ")+tr("Warning"), + tr("This function will only work if the mp3 is encoded as " + "stereo or dual channel, NOT joint-stereo or mono."), + tr("Don't show this warning again"), + isConfirmSuppressed); + if (isConfirmSuppressed){ + mainWindow->getSettings()->setValue("groupBox_onlyOneChannel_ConfirmSuppressed", true); + } + } + mainWindow->getSettings()->endGroup(); + } }
View file
qmp3gain-0.9.3.tar.xz/src/constantgainchangedialog.h -> qmp3gain-0.9.4.tar.xz/src/constantgainchangedialog.h
Changed
@@ -14,8 +14,8 @@ ~ConstantGainChangeDialog(); private slots: - void updateLineEdit_constGainChange(int value); - void groupBox_onlyOneChannel_toggled(bool isOn); + void updateLineEdit_constGainChange(int value); + void groupBox_onlyOneChannel_toggled(bool isOn); }; #endif // CONSTANTGAINCHANGEDIALOG_H
View file
qmp3gain-0.9.3.tar.xz/src/disclaimerdialog.cpp -> qmp3gain-0.9.4.tar.xz/src/disclaimerdialog.cpp
Changed
@@ -4,7 +4,7 @@ DisclaimerDialog::DisclaimerDialog(QWidget *parent) : QDialog(parent) { - setupUi(this); - - setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); + setupUi(this); + + setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); }
View file
qmp3gain-0.9.3.tar.xz/src/donationdialog.cpp -> qmp3gain-0.9.4.tar.xz/src/donationdialog.cpp
Changed
@@ -6,8 +6,8 @@ DonationDialog::DonationDialog(QWidget *parent) : QDialog(parent) { - setupUi(this); - setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); + setupUi(this); + setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); } void DonationDialog::on_donationButton_clicked() {
View file
qmp3gain-0.9.3.tar.xz/src/donationdialog.h -> qmp3gain-0.9.4.tar.xz/src/donationdialog.h
Changed
@@ -10,10 +10,10 @@ Q_OBJECT public: - DonationDialog(QWidget *parent = 0); + DonationDialog(QWidget *parent = 0); private slots: - void on_donationButton_clicked(); + void on_donationButton_clicked(); }; #endif
View file
qmp3gain-0.9.3.tar.xz/src/doubleprogressbar.cpp -> qmp3gain-0.9.4.tar.xz/src/doubleprogressbar.cpp
Changed
@@ -1,18 +1,18 @@ #include "doubleprogressbar.h" DoubleProgressBar::DoubleProgressBar(QWidget *parent): QProgressBar(parent) { - this->dValue = (double)this->value(); - connect(this, SIGNAL(valueChanged(int)), this, SLOT(setDoubleValue(int))); + this->dValue = (double)this->value(); + connect(this, SIGNAL(valueChanged(int)), this, SLOT(setDoubleValue(int))); } DoubleProgressBar::~DoubleProgressBar() { } void DoubleProgressBar::setDoubleValue(double doubleValue) { - this->dValue = doubleValue; - this->setValue((int)doubleValue); + this->dValue = doubleValue; + this->setValue((int)doubleValue); } void DoubleProgressBar::setDoubleValue(int value) { - setDoubleValue((double)value); + setDoubleValue((double)value); }
View file
qmp3gain-0.9.3.tar.xz/src/doubleprogressbar.h -> qmp3gain-0.9.4.tar.xz/src/doubleprogressbar.h
Changed
@@ -4,17 +4,17 @@ #include <QProgressBar> class DoubleProgressBar: public QProgressBar { - Q_OBJECT + Q_OBJECT public: - DoubleProgressBar(QWidget *parent = 0); - virtual ~DoubleProgressBar(); - inline double doubleValue() const { return dValue; } + DoubleProgressBar(QWidget *parent = 0); + virtual ~DoubleProgressBar(); + inline double doubleValue() const { return dValue; } public slots: - void setDoubleValue(double doubleValue); - void setDoubleValue(int value); + void setDoubleValue(double doubleValue); + void setDoubleValue(int value); private: - double dValue; + double dValue; }; #endif /* DOUBLEPROGRESSBAR_H_ */
View file
qmp3gain-0.9.3.tar.xz/src/logoptionsdialog.cpp -> qmp3gain-0.9.4.tar.xz/src/logoptionsdialog.cpp
Changed
@@ -7,99 +7,99 @@ LogOptionsDialog::LogOptionsDialog(QWidget *parent) : QDialog(parent) { - setupUi(this); - - mainWindow = qobject_cast<MainWindow*>(this->parent()); - setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); - readSettings(mainWindow->getSettings()); - - lineEdit_logFile->setText(mainWindow->getFileLog() ? mainWindow->getFileLog()->fileName() : QString()); + setupUi(this); - isAccepted = false; + mainWindow = qobject_cast<MainWindow*>(this->parent()); + setWindowTitle(windowTitle().arg(MainWindow::getAppTitle())); + readSettings(mainWindow->getSettings()); + + lineEdit_logFile->setText(mainWindow->getFileLog() ? mainWindow->getFileLog()->fileName() : QString()); + + isAccepted = false; } LogOptionsDialog::~LogOptionsDialog(){ - if (isAccepted){ - writeSettings(mainWindow->getSettings()); - } + if (isAccepted){ + writeSettings(mainWindow->getSettings()); + } } void LogOptionsDialog::readSettings(QSettings *settings){ - settings->beginGroup("logOptionsDialog"); - //lineEdit_logFile->setText(settings->value("lineEdit_logFile").toString()); - settings->endGroup(); + settings->beginGroup("logOptionsDialog"); + //lineEdit_logFile->setText(settings->value("lineEdit_logFile").toString()); + settings->endGroup(); } void LogOptionsDialog::writeSettings(QSettings *settings){ - settings->beginGroup("logOptionsDialog"); - //settings->setValue("lineEdit_logFile", lineEdit_logFile->text()); - settings->endGroup(); + settings->beginGroup("logOptionsDialog"); + //settings->setValue("lineEdit_logFile", lineEdit_logFile->text()); + settings->endGroup(); } void LogOptionsDialog::openFileDialog(QLineEdit *lineEdit){ - QFileDialog dialog(this, tr("Add log file(s)"), QString() /* directory */); - QString fileName = lineEdit->text(); - if (QFile::exists(fileName)){ - dialog.selectFile(fileName); - } - QStringList filters; - filters << "Log files (*.log)" << "Text files (*.txt)" << "Any files (*)"; - dialog.setNameFilters(filters); - QStringList fileNames; - if (dialog.exec()){ - fileNames = dialog.selectedFiles(); - if (!fileNames.isEmpty()){ - QString fileName = fileNames.at(0); - lineEdit->setText(fileName); - } - } + QFileDialog dialog(this, tr("Add log file(s)"), QString() /* directory */); + QString fileName = lineEdit->text(); + if (QFile::exists(fileName)){ + dialog.selectFile(fileName); + } + QStringList filters; + filters << "Log files (*.log)" << "Text files (*.txt)" << "Any files (*)"; + dialog.setNameFilters(filters); + QStringList fileNames; + if (dialog.exec()){ + fileNames = dialog.selectedFiles(); + if (!fileNames.isEmpty()){ + QString fileName = fileNames.at(0); + lineEdit->setText(fileName); + } + } } void LogOptionsDialog::accept(){ - QPointer<QFile> fileLogActual = mainWindow->getFileLog(); - QPointer<QFile> fileLog; - bool isToBeClosed = false; - bool hasNewLog = false; - if (!lineEdit_logFile->text().isEmpty()){ - fileLog = new QFile(lineEdit_logFile->text()); - if (!fileLog->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)){ - QMessageBox::critical(this, MainWindow::getAppTitle(), - tr("Cannot write log file: %1").arg(fileLog->fileName())); - delete fileLog; - return; - } - else{ - isToBeClosed = true; - hasNewLog = true; - } - } - else{ - isToBeClosed = true; - } - if (isToBeClosed){ - if (fileLogActual){ - if (fileLogActual->isOpen()) - fileLogActual->close(); - delete fileLogActual; - } - } - if (hasNewLog){ - mainWindow->setFileLog(fileLog); - } - isAccepted = true; - return QDialog::accept(); + QPointer<QFile> fileLogActual = mainWindow->getFileLog(); + QPointer<QFile> fileLog; + bool isToBeClosed = false; + bool hasNewLog = false; + if (!lineEdit_logFile->text().isEmpty()){ + fileLog = new QFile(lineEdit_logFile->text()); + if (!fileLog->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)){ + QMessageBox::critical(this, MainWindow::getAppTitle(), + tr("Cannot write log file: %1").arg(fileLog->fileName())); + delete fileLog; + return; + } + else{ + isToBeClosed = true; + hasNewLog = true; + } + } + else{ + isToBeClosed = true; + } + if (isToBeClosed){ + if (fileLogActual){ + if (fileLogActual->isOpen()) + fileLogActual->close(); + delete fileLogActual; + } + } + if (hasNewLog){ + mainWindow->setFileLog(fileLog); + } + isAccepted = true; + return QDialog::accept(); } void LogOptionsDialog::on_toolButton_logFile_clicked(){ - openFileDialog(lineEdit_logFile); + openFileDialog(lineEdit_logFile); } void LogOptionsDialog::on_buttonBox_clicked(QAbstractButton * button){ - if (button == buttonBox->button(QDialogButtonBox::Reset)){ - lineEdit_logFile->clear(); - } - else if (button == buttonBox->button(QDialogButtonBox::RestoreDefaults)){ - QString fileName = QDir::homePath()+"/"+MainWindow::getAppTitle().toLower()+".log"; - lineEdit_logFile->setText(fileName); - } + if (button == buttonBox->button(QDialogButtonBox::Reset)){ + lineEdit_logFile->clear(); + } + else if (button == buttonBox->button(QDialogButtonBox::RestoreDefaults)){ + QString fileName = QDir::homePath()+"/"+MainWindow::getAppTitle().toLower()+".log"; + lineEdit_logFile->setText(fileName); + } }
View file
qmp3gain-0.9.3.tar.xz/src/logoptionsdialog.h -> qmp3gain-0.9.4.tar.xz/src/logoptionsdialog.h
Changed
@@ -12,20 +12,20 @@ Q_OBJECT public: - LogOptionsDialog(QWidget *parent = 0); - ~LogOptionsDialog(); + LogOptionsDialog(QWidget *parent = 0); + ~LogOptionsDialog(); private: - bool isAccepted; - void readSettings(QSettings *settings); - void writeSettings(QSettings *settings); - void openFileDialog(QLineEdit *lineEdit); - MainWindow* mainWindow; + bool isAccepted; + void readSettings(QSettings *settings); + void writeSettings(QSettings *settings); + void openFileDialog(QLineEdit *lineEdit); + MainWindow* mainWindow; private slots: - void accept(); - void on_toolButton_logFile_clicked(); - void on_buttonBox_clicked(QAbstractButton * button); + void accept(); + void on_toolButton_logFile_clicked(); + void on_buttonBox_clicked(QAbstractButton * button); }; #endif
View file
qmp3gain-0.9.3.tar.xz/src/main.cpp -> qmp3gain-0.9.4.tar.xz/src/main.cpp
Changed
@@ -5,18 +5,18 @@ int main(int argc, char *argv) { - QApplication app(argc, argv); - QStringList argumentList = app.arguments(); - argumentList.removeFirst(); - if (!argumentList.isEmpty()) - return 0; - MainWindow mainWin; - app.setApplicationName(mainWin.getAppTitle()); - mainWin.switchLanguage(); - mainWin.show(); - if (!mainWin.isBackEndAvailable()){ - mainWin.showNoBackEndVersion(true); - } - return app.exec(); + QApplication app(argc, argv); + QStringList argumentList = app.arguments(); + argumentList.removeFirst(); + if (!argumentList.isEmpty()) + return 0; + MainWindow mainWin; + app.setApplicationName(mainWin.getAppTitle()); + mainWin.switchLanguage(); + mainWin.show(); + if (!mainWin.isBackEndAvailable()){ + mainWin.showNoBackEndVersion(true); + } + return app.exec(); }
View file
qmp3gain-0.9.3.tar.xz/src/mainwindow.cpp -> qmp3gain-0.9.4.tar.xz/src/mainwindow.cpp
Changed
@@ -4,6 +4,7 @@ #include <QSound> #include <QtXml> #include <QMimeData> +#include <QClipboard> #include "mainwindow.h" #include "aboutdialog.h" @@ -36,257 +37,258 @@ const QString MainWindow::requiredBackEndVersion = "1.5.2"; MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent) + : QMainWindow(parent) { - backEndFileName = ""; // if it is set then this one is used instead of backEndFixed - isCancelled = false; - lastAddedIndices = QModelIndexList(); - menuLanguageActionGroup = new QActionGroup(this); - enabledGUI = false; + backEndFileName = ""; // if it is set then this one is used instead of backEndFixed + isCancelled = false; + lastAddedIndices = QModelIndexList(); + menuLanguageActionGroup = new QActionGroup(this); + enabledGUI = false; - appTranslator = new QTranslator(this); - qApp->installTranslator(appTranslator); + appTranslator = new QTranslator(this); + qApp->installTranslator(appTranslator); setAcceptDrops(true); - setupUi(this); + setupUi(this); - // add context menu for tableView - connect(tableView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showContextMenuForWidget(const QPoint &))); - // modified default dB value - connect(doubleSpinBox_targetNormalValue, SIGNAL(valueChanged(double)), this, SLOT(updateModelRowsByNewTargetNormalValue(double))); - - createLanguageMenu(); - - // fill actions vector with checkable menu items - { - // Options - actions << actionAlways_on_Top; - actions << actionWork_on_Selected_files_only; - actions << actionAdd_Subfolders; - actions << actionPreserve_file_date_time; - actions << actionNo_check_for_Layer_I_or_II; - actions << actionDon_t_clip_when_doing_track_gain; - // Options/Tags - actions << actionIgnore_do_not_read_or_write_tags; - actions << actionRe_calculate_do_not_read_tags; - actions << actionDon_t_check_adding_files; - actions << actionRemove_Tags_from_files; - // Options/Logs - actions << actionLogDock; - actions << actionLogOpenAutomaticallyPanel; - // Options/Logs/Output Type - actions << actionLogError; - actions << actionLogAnalysis; - actions << actionLogChange; - actions << actionLogBackend; - actions << actionLogTrace; - // Options/Logs/Timestamp - actions << actionLogTimestampToFile; - actions << actionLogTimestampToPanel; - // Options/Toolbar - actions << actionBig; - actions << actionSmall; - actions << actionText_only; - actions << actionNone; - // Options/Filename_Display - actions << actionShow_Path_slash_File; - actions << actionShow_File_only; - actions << actionShow_Path_at_File; - // Options - actions << actionMinimize_to_tray; - actions << actionBeep_when_finished; - } - - // fill logOutputTypes with action - checkbox pairs - logOutputTypes.insert(actionLogError, checkBox_logError); - logOutputTypes.insert(actionLogAnalysis, checkBox_logAnalysis); - logOutputTypes.insert(actionLogChange, checkBox_logChange); - logOutputTypes.insert(actionLogBackend, checkBox_logBackend); - - // persist parameters - settings = new QSettings("Zematix", appTitle); - readSettings(); - - // manage backEndVersion and backEndFileName - backEndVersion = findBackEndVersionByProcess(); - if (backEndVersion.isEmpty() && !backEndFileName.isEmpty()){ - backEndFileName = ""; - backEndVersion = findBackEndVersionByProcess(); - } - - // to resize toolbar icons later - iconDefaultSize = toolBar->iconSize(); - - // this array is a must to enable translations of buttons of QDialogButtonBox - static const char *QDialogButtonBox_strings = { - // QDialogButtonBox buttons must be set in our translation file - QT_TRANSLATE_NOOP("QDialogButtonBox", "OK"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Open"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Save"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Cancel"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Close"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Discard"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Apply"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Reset"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Restore Defaults"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Help"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Save All"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "&Yes"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Yes to &All"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "&No"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "N&o to All"), - - QT_TRANSLATE_NOOP("QDialogButtonBox", "Abort"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Retry"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Ignore"), - - QT_TRANSLATE_NOOP("QDialogButtonBox", "Don't Save"), - QT_TRANSLATE_NOOP("QDialogButtonBox", "Close without Saving") - }; - - // model and view columns for table containing files - static const char * _modelHeaderLabels = { - QT_TR_NOOP("Path/File"), - QT_TR_NOOP("Path"), - QT_TR_NOOP("File"), - QT_TR_NOOP("Volume"), - QT_TR_NOOP("Max Amplitude"), // hidden - QT_TR_NOOP("clipping"), - QT_TR_NOOP("Track Gain"), - QT_TR_NOOP("dBGain"), // hidden - QT_TR_NOOP("clip(Track)"), - QT_TR_NOOP("Max Noclip Gain"), - QT_TR_NOOP("Album Volume"), - QT_TR_NOOP("Album Max Amplitude"), // hidden (in fact this field is never used) - QT_TR_NOOP("Album Gain"), - QT_TR_NOOP("Album dBGain"), // hidden - QT_TR_NOOP("clip(Album)"), - 0 - }; - modelHeaderLabels = _modelHeaderLabels; - for (int i = 0; modelHeaderLabelsi; ++i){ - modelHeaderList << modelHeaderLabelsi; - } - model = new QStandardItemModel; - model->setHorizontalHeaderLabels(modelHeaderList); // translated later - tableView->setModel(model); - tableView->setSelectionBehavior(QAbstractItemView::SelectRows); - int widthPathFile = tableView->columnWidth(modelHeaderList.indexOf("Path/File"))*2; - int widthPath = tableView->columnWidth(modelHeaderList.indexOf("Path"))*2; - int widthFile = tableView->columnWidth(modelHeaderList.indexOf("File"))*2; - tableView->resizeColumnsToContents(); - tableView->setColumnWidth(modelHeaderList.indexOf("Path/File"), widthPathFile); - tableView->setColumnWidth(modelHeaderList.indexOf("Path"), widthPath); - tableView->setColumnWidth(modelHeaderList.indexOf("File"), widthFile); - - // store default widths of tableView - QList<QVariant> widths; // QList<int> - for (int i=0; i<tableView->model()->columnCount(); i++){ - widths.append(QVariant(tableView->columnWidth(i))); - } - tableView->setProperty("columnWidths", QVariant(widths)); - - // initialize operationMap - // contains operationId and a list with passes in percents - operationMap.insert("add_file", QList<int>() << 100); - operationMap.insert("add_file, analysis", QList<int>() << 30 << 70); - operationMap.insert("add_folder", QList<int>() << 100); - operationMap.insert("add_folder, analysis", QList<int>() << 30 << 70); - operationMap.insert("track_analysis", QList<int>() << 100); - operationMap.insert("album_analysis", QList<int>() << 80 << 20); - operationMap.insert("max_no_clip_analysis", QList<int>() << 100); - operationMap.insert("clear_analysis", QList<int>() << 100); - operationMap.insert("track_gain", QList<int>() << 100); - operationMap.insert("album_gain", QList<int>() << 100); - operationMap.insert("constant_gain", QList<int>() << 100); - operationMap.insert("max_no_clip_gain_for_each_file", QList<int>() << 50 << 50); - operationMap.insert("max_no_clip_gain_for_album", QList<int>() << 50 << 50); - operationMap.insert("undo_gain_changes", QList<int>() << 100); + // add context menu for tableView + connect(tableView, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(showContextMenuForWidget(const QPoint &))); + // modified default dB value + connect(doubleSpinBox_targetNormalValue, SIGNAL(valueChanged(double)), this, SLOT(updateModelRowsByNewTargetNormalValue(double))); + + createLanguageMenu(); + + // fill actions vector with checkable menu items + { + // Options + actions << actionAlways_on_Top; + actions << actionWork_on_Selected_files_only; + actions << actionAdd_Subfolders; + actions << actionPreserve_file_date_time; + actions << actionNo_check_for_Layer_I_or_II; + actions << actionDon_t_clip_when_doing_track_gain; + // Options/Tags + actions << actionIgnore_do_not_read_or_write_tags; + actions << actionRe_calculate_do_not_read_tags; + actions << actionDon_t_check_adding_files; + actions << actionRemove_Tags_from_files; + // Options/Logs + actions << actionLogDock; + actions << actionLogOpenAutomaticallyPanel; + // Options/Logs/Output Type + actions << actionLogError; + actions << actionLogAnalysis; + actions << actionLogChange; + actions << actionLogBackend; + actions << actionLogTrace; + // Options/Logs/Timestamp + actions << actionLogTimestampToFile; + actions << actionLogTimestampToPanel; + // Options/Toolbar + actions << actionBig; + actions << actionSmall; + actions << actionText_only; + actions << actionNone; + // Options/Filename_Display + actions << actionShow_Path_slash_File; + actions << actionShow_File_only; + actions << actionShow_Path_at_File; + // Options + actions << actionMinimize_to_tray; + actions << actionBeep_when_finished; + } + + // fill logOutputTypes with action - checkbox pairs + logOutputTypes.insert(actionLogError, checkBox_logError); + logOutputTypes.insert(actionLogAnalysis, checkBox_logAnalysis); + logOutputTypes.insert(actionLogChange, checkBox_logChange); + logOutputTypes.insert(actionLogBackend, checkBox_logBackend); + + // persist parameters + settings = new QSettings("Zematix", appTitle); + readSettings(); + + // manage backEndVersion and backEndFileName + backEndVersion = findBackEndVersionByProcess(); + if (backEndVersion.isEmpty() && !backEndFileName.isEmpty()){ + backEndFileName = ""; + backEndVersion = findBackEndVersionByProcess(); + } + + // to resize toolbar icons later + iconDefaultSize = toolBar->iconSize(); + + // this array is a must to enable translations of buttons of QDialogButtonBox + static const char *QDialogButtonBox_strings = { + // QDialogButtonBox buttons must be set in our translation file + QT_TRANSLATE_NOOP("QDialogButtonBox", "OK"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Open"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Save"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Cancel"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Close"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Discard"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Apply"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Reset"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Restore Defaults"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Help"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Save All"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "&Yes"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Yes to &All"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "&No"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "N&o to All"), + + QT_TRANSLATE_NOOP("QDialogButtonBox", "Abort"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Retry"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Ignore"), + + QT_TRANSLATE_NOOP("QDialogButtonBox", "Don't Save"), + QT_TRANSLATE_NOOP("QDialogButtonBox", "Close without Saving") + }; + + // model and view columns for table containing files + static const char * _modelHeaderLabels = { + QT_TR_NOOP("Path/File"), + QT_TR_NOOP("Path"), + QT_TR_NOOP("File"), + QT_TR_NOOP("Volume"), + QT_TR_NOOP("Max Amplitude"), // hidden + QT_TR_NOOP("clipping"), + QT_TR_NOOP("Track Gain"), + QT_TR_NOOP("dBGain"), // hidden + QT_TR_NOOP("clip(Track)"), + QT_TR_NOOP("Max Noclip Gain"), + QT_TR_NOOP("Album Volume"), + QT_TR_NOOP("Album Max Amplitude"), // hidden (in fact this field is never used) + QT_TR_NOOP("Album Gain"), + QT_TR_NOOP("Album dBGain"), // hidden + QT_TR_NOOP("clip(Album)"), + 0 + }; + modelHeaderLabels = _modelHeaderLabels; + for (int i = 0; modelHeaderLabelsi; ++i){ + modelHeaderList << modelHeaderLabelsi; + } + model = new QStandardItemModel; + model->setHorizontalHeaderLabels(modelHeaderList); // translated later + tableView->setModel(model); + tableView->setSelectionBehavior(QAbstractItemView::SelectRows); + + QList<QVariant> widths = settings->value("columnWidths").toList(); // QList<int> + if (widths.isEmpty()){ + // store column widths of tableView as default + for (int i=0; i<tableView->model()->columnCount(); i++){ + widths.append(QVariant(tableView->columnWidth(i))); + } + tableView->setProperty("columnWidths", QVariant(widths)); + } + else{ + // set column widths from earlier retrieved readSettings method + for (int i=0; i<widths.size(); i++){ + tableView->setColumnWidth(i, widths.at(i).toInt()); + } + } + + // initialize operationMap + // contains operationId and a list with passes in percents + operationMap.insert("add_file", QList<int>() << 100); + operationMap.insert("add_file, analysis", QList<int>() << 30 << 70); + operationMap.insert("add_folder", QList<int>() << 100); + operationMap.insert("add_folder, analysis", QList<int>() << 30 << 70); + operationMap.insert("track_analysis", QList<int>() << 100); + operationMap.insert("album_analysis", QList<int>() << 80 << 20); + operationMap.insert("max_no_clip_analysis", QList<int>() << 100); + operationMap.insert("clear_analysis", QList<int>() << 100); + operationMap.insert("track_gain", QList<int>() << 100); + operationMap.insert("album_gain", QList<int>() << 100); + operationMap.insert("constant_gain", QList<int>() << 100); + operationMap.insert("max_no_clip_gain_for_each_file", QList<int>() << 50 << 50); + operationMap.insert("max_no_clip_gain_for_album", QList<int>() << 50 << 50); + operationMap.insert("undo_gain_changes", QList<int>() << 100); - // init beepSound - on_actionBeep_when_finished_toggled(settings->value("actionBeep_when_finished", false).toBool()); + // init beepSound + on_actionBeep_when_finished_toggled(settings->value("actionBeep_when_finished", false).toBool()); - createStatusBar(); + createStatusBar(); - refreshUi(); - refreshGUI(); + refreshUi(); + refreshGUI(); } MainWindow::~MainWindow(){ - // writesettings() cannot be used here due to on_logDockWidget_visibilityChanged - delete appTranslator; - delete menuLanguageActionGroup; - delete settings; - delete model; - delete beepSound; - - delete trayIcon; - delete restoreTrayAction; - delete quitTrayAction; + // writeSettings() cannot be used here due to on_logDockWidget_visibilityChanged + delete appTranslator; + delete menuLanguageActionGroup; + delete settings; + delete model; + delete beepSound; + + delete trayIcon; + delete restoreTrayAction; + delete quitTrayAction; - delete actionPlay_mp3_file; - delete mediaPlayer; + delete actionPlay_mp3_file; + delete mediaPlayer; } long MainWindow::getVersionNumber(const QString & versionString) { - if (versionString.isEmpty()) - return 0; + if (versionString.isEmpty()) + return 0; - long major = 0; - long minor = 0; - long subminor = 0; - QRegExp rx("(?:^)(\\d+)(?:\\.)(\\d+)(?:\\.)(\\d+)(?:$)"); - int pos = rx.indexIn(versionString); - if (pos > -1) { - major = rx.cap(1).toInt(); - minor = rx.cap(2).toInt(); - subminor = rx.cap(3).toInt(); - } + long major = 0; + long minor = 0; + long subminor = 0; + QRegExp rx("(?:^)(\\d+)(?:\\.)(\\d+)(?:\\.)(\\d+)(?:$)"); + int pos = rx.indexIn(versionString); + if (pos > -1) { + major = rx.cap(1).toInt(); + minor = rx.cap(2).toInt(); + subminor = rx.cap(3).toInt(); + } - return major*1000000+minor*1000+subminor; + return major*1000000+minor*1000+subminor; } void MainWindow::closeEvent(QCloseEvent *event) { - if (true /*okToContinue()*/) { - writeSettings(); // moving this call into the destructor is not an option - event->accept(); - } else { - event->ignore(); - } + if (true /*okToContinue()*/) { + writeSettings(); // moving this call into the destructor is not an option + event->accept(); + } else { + event->ignore(); + } } void MainWindow::changeEvent (QEvent *event) { - QWidget *parentWidget = new QWidget(0, Qt::Window); - bool isEventProcessed = false; + QWidget *parentWidget = new QWidget(0, Qt::Window); + bool isEventProcessed = false; - switch (event->type()) { - case QEvent::WindowStateChange: { - if (isMinimized()){ - if (actionMinimize_to_tray->isChecked()){ - if (!trayIcon) - createTrayIcon(); - - if (trayIcon){ - mainGeometry = saveGeometry(); - setParent(parentWidget, Qt::SubWindow); // removing from taskbar in Windows - trayIcon->show(); - event->ignore(); - isEventProcessed = true; - } - } - } - break; - } - default: - ; - } + switch (event->type()) { + case QEvent::WindowStateChange: { + if (isMinimized()){ + if (actionMinimize_to_tray->isChecked()){ + if (!trayIcon) + createTrayIcon(); + + if (trayIcon){ + mainGeometry = saveGeometry(); + setParent(parentWidget, Qt::SubWindow); // removing from taskbar in Windows + trayIcon->show(); + event->ignore(); + isEventProcessed = true; + } + } + } + break; + } + default: + ; + } - if (!isEventProcessed) - event->accept(); + if (!isEventProcessed) + event->accept(); } void MainWindow::dragEnterEvent(QDragEnterEvent *event) @@ -308,7 +310,7 @@ if (fileInfo.isDir()) { addFolder(fileName); } - else if (fileInfo.isFile() && fileInfo.completeSuffix().toLower() == "mp3") { + else if (fileInfo.isFile() && fileInfo.suffix().toLower() == "mp3") { list.append(fileName); } } @@ -319,106 +321,106 @@ void MainWindow::createStatusBar() { - messageLabel = new QLabel; - messageLabel->setIndent(3); + messageLabel = new QLabel; + messageLabel->setIndent(3); - modelRowCountLabel = new QLabel(" 0 "); - modelRowCountLabel->setAlignment(Qt::AlignHCenter); - modelRowCountLabel->setMinimumSize(modelRowCountLabel->sizeHint()); - modelRowCountLabel->setToolTip(tr("Number of files in the list")); - - statusBar()->addWidget(messageLabel, 1); - statusBar()->addWidget(modelRowCountLabel); - - connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(updateStatusBar())); - connect(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(updateStatusBar())); + modelRowCountLabel = new QLabel(" 0 "); + modelRowCountLabel->setAlignment(Qt::AlignHCenter); + modelRowCountLabel->setMinimumSize(modelRowCountLabel->sizeHint()); + modelRowCountLabel->setToolTip(tr("Number of files in the list")); + + statusBar()->addWidget(messageLabel, 1); + statusBar()->addWidget(modelRowCountLabel); + + connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)), + this, SLOT(updateStatusBar())); + connect(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), + this, SLOT(updateStatusBar())); - updateStatusBar(); + updateStatusBar(); } void MainWindow::updateStatusBar(){ - modelRowCountLabel->setText(QString(" %1 ").arg(model->rowCount())); + modelRowCountLabel->setText(QString(" %1 ").arg(model->rowCount())); } void MainWindow::updateStatusBar(const QString & msg){ - messageLabel->setText(msg); - updateStatusBar(); + messageLabel->setText(msg); + updateStatusBar(); } void MainWindow::createTrayIcon() { - if (QSystemTrayIcon::isSystemTrayAvailable()){ - QIcon icon; - icon.addFile(QString::fromUtf8(":/images/icon.png"), QSize(), QIcon::Normal, QIcon::Off); - - // create tray actions - restoreTrayAction = new QAction(tr("&Restore"), this); - connect(restoreTrayAction, SIGNAL(triggered()), this, SLOT(trayHide())); - - quitTrayAction = new QAction(tr("&Quit"), this); - quitTrayAction->setShortcut(QKeySequence(tr("Ctrl+Q", "SystemTrayIcon|Quit"))); - connect(quitTrayAction, SIGNAL(triggered()), qApp, SLOT(quit())); - - // create tray menu - QMenu *trayIconMenu = new QMenu(this); - - QWidget *widget; - QVBoxLayout *verticalLayout; - QHBoxLayout *horizontalLayout; - QLabel *label; - QLabel *label_2; - QSpacerItem *horizontalSpacer; - - widget = new QWidget(); - widget->setObjectName(QString::fromUtf8("widget")); - verticalLayout = new QVBoxLayout(widget); - verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); - horizontalLayout = new QHBoxLayout(); - horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); - label = new QLabel(widget); - label->setObjectName(QString::fromUtf8("label")); - label->setPixmap(QPixmap(QString::fromUtf8(":/images/icon.png"))); - label->setMaximumSize(16, 16); - label->setScaledContents(true); - - horizontalLayout->addWidget(label); - - label_2 = new QLabel(widget); - label_2->setObjectName(QString::fromUtf8("label_2")); - label_2->setText(QString("<b>"+this->appTitle)+"</b>"); - label_2->setAlignment(Qt::AlignCenter); - - horizontalLayout->addWidget(label_2); - - horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - horizontalLayout->addItem(horizontalSpacer); - - verticalLayout->addLayout(horizontalLayout); - - - QWidgetAction* titleAction = new QWidgetAction(this); - titleAction->setDefaultWidget(widget); - - trayIconMenu->addAction(titleAction); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(restoreTrayAction); - trayIconMenu->addAction(quitTrayAction); - - // create tray icon - trayIcon = new QSystemTrayIcon(this); - trayIcon->setContextMenu(trayIconMenu); - - trayIcon->setIcon(icon); - trayIcon->setToolTip(tr("No operation running")); - - connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), - this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); - } - else{ - writeLog(tr("Minimize to tray option is checked and tray icon should be created but system tray is unavailable"), LOGTYPE_TRACE); - } + if (QSystemTrayIcon::isSystemTrayAvailable()){ + QIcon icon; + icon.addFile(QString::fromUtf8(":/images/icon.png"), QSize(), QIcon::Normal, QIcon::Off); + + // create tray actions + restoreTrayAction = new QAction(tr("&Restore"), this); + connect(restoreTrayAction, SIGNAL(triggered()), this, SLOT(trayHide())); + + quitTrayAction = new QAction(tr("&Quit"), this); + quitTrayAction->setShortcut(QKeySequence(tr("Ctrl+Q", "SystemTrayIcon|Quit"))); + connect(quitTrayAction, SIGNAL(triggered()), qApp, SLOT(quit())); + + // create tray menu + QMenu *trayIconMenu = new QMenu(this); + + QWidget *widget; + QVBoxLayout *verticalLayout; + QHBoxLayout *horizontalLayout; + QLabel *label; + QLabel *label_2; + QSpacerItem *horizontalSpacer; + + widget = new QWidget(); + widget->setObjectName(QString::fromUtf8("widget")); + verticalLayout = new QVBoxLayout(widget); + verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); + horizontalLayout = new QHBoxLayout(); + horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); + label = new QLabel(widget); + label->setObjectName(QString::fromUtf8("label")); + label->setPixmap(QPixmap(QString::fromUtf8(":/images/icon.png"))); + label->setMaximumSize(16, 16); + label->setScaledContents(true); + + horizontalLayout->addWidget(label); + + label_2 = new QLabel(widget); + label_2->setObjectName(QString::fromUtf8("label_2")); + label_2->setText(QString("<b>"+this->appTitle)+"</b>"); + label_2->setAlignment(Qt::AlignCenter); + + horizontalLayout->addWidget(label_2); + + horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + horizontalLayout->addItem(horizontalSpacer); + + verticalLayout->addLayout(horizontalLayout); + + + QWidgetAction* titleAction = new QWidgetAction(this); + titleAction->setDefaultWidget(widget); + + trayIconMenu->addAction(titleAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(restoreTrayAction); + trayIconMenu->addAction(quitTrayAction); + + // create tray icon + trayIcon = new QSystemTrayIcon(this); + trayIcon->setContextMenu(trayIconMenu); + + trayIcon->setIcon(icon); + trayIcon->setToolTip(tr("No operation running")); + + connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); + } + else{ + writeLog(tr("Minimize to tray option is checked and tray icon should be created but system tray is unavailable"), LOGTYPE_TRACE); + } } @@ -447,8 +449,11 @@ QList<QStandardItem *> found = model->findItems(fileNames.at(i), Qt::MatchExactly, 0); if (found.count()>0) continue; QStandardItem *item0 = new QStandardItem(fi.absoluteFilePath()); + item0->setToolTip(fi.absoluteFilePath()); QStandardItem *item1 = new QStandardItem(fi.absolutePath()); + item1->setToolTip(fi.absolutePath()); QStandardItem *item2 = new QStandardItem(fi.fileName()); + item2->setToolTip(fi.fileName()); model->appendRow(QList<QStandardItem *>() << item0 << item1 << item2); QModelIndex index = model->indexFromItem(item0); if (index.isValid()){ @@ -491,10 +496,8 @@ } int pass = 1; - //tableView->hide(); if (getMP3FilesByFolder(dir, 0, (double)passes.at(pass-1))==-1) throw(-1); - //tableView->show(); lastAddedFolder = dir; if (!actionDon_t_check_adding_files->isChecked() && !lastAddedIndices.isEmpty()){ @@ -511,1996 +514,2049 @@ } void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason reason){ - switch (reason) { - case QSystemTrayIcon::Trigger: - case QSystemTrayIcon::DoubleClick: - trayHide(); - break; - case QSystemTrayIcon::MiddleClick: - trayShowMessage(); - break; - default: - ; - } + switch (reason) { + case QSystemTrayIcon::Trigger: + case QSystemTrayIcon::DoubleClick: + trayHide(); + break; + case QSystemTrayIcon::MiddleClick: + trayShowMessage(); + break; + default: + ; + } } void MainWindow::trayShowMessage() { - if (QSystemTrayIcon::supportsMessages()){ - QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::MessageIcon(QSystemTrayIcon::Information); - trayIcon->showMessage(appTitle, tr("Lossless volume modification of MP3 files"), icon, 5000); - } - else{ - writeLog(tr("System tray does not support balloon messages"), LOGTYPE_TRACE); - } + if (QSystemTrayIcon::supportsMessages()){ + QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::MessageIcon(QSystemTrayIcon::Information); + trayIcon->showMessage(appTitle, tr("Lossless volume modification of MP3 files"), icon, 5000); + } + else{ + writeLog(tr("System tray does not support balloon messages"), LOGTYPE_TRACE); + } } void MainWindow::trayHide() { - setParent(0, Qt::Window); - restoreGeometry(mainGeometry); - showNormal(); - trayIcon->hide(); + setParent(0, Qt::Window); + restoreGeometry(mainGeometry); + showNormal(); + trayIcon->hide(); } void MainWindow::handleMediaPlayerError(QMediaPlayer::Error error) { - QString playedFileName = mediaPlayer->currentMedia().canonicalUrl().url(); + QString playedFileName = mediaPlayer->currentMedia().request().url().toLocalFile(); - writeLog(QString("Playing of %1 went into failure because \"%2\"").arg(playedFileName).arg(mediaPlayer->errorString()), LOGTYPE_ERROR); - QMessageBox::critical(this, appTitle+" - "+tr("Fatal Error"), tr("Playing of %1 went into failure").arg(playedFileName)); + writeLog(QString("Playing of %1 went into failure because \"%2\"").arg(playedFileName).arg(mediaPlayer->errorString()), LOGTYPE_ERROR); + QMessageBox::critical(this, appTitle+" - "+tr("Fatal Error"), tr("Playing of %1 went into failure").arg(playedFileName)); } // contextmenu: Play mp3 file void MainWindow::playMP3File(){ - try { - QModelIndexList indices = getModelIndices(); - if (indices.isEmpty()) throw(0); - - QStringList args; - args << "-s" << "d"; // delete stored tag info (no other processing) - args << getArgumentsByOptions(); - - QModelIndex index = indices.last(); - int row = model->itemFromIndex(index)->row(); - QStandardItem *item = getItem(row, "Path/File"); - QString fileName = item->text(); - writeLog(fileName, LOGTYPE_TRACE); - - bool isToBeStopped = false; - if (mediaPlayer) { - if (mediaPlayer->state()==QMediaPlayer::State::PlayingState) { - QString playedFileName = mediaPlayer->currentMedia().canonicalUrl().path(); - if (fileName==playedFileName){ - isToBeStopped = true; - } - } - delete mediaPlayer; - } - if (!isToBeStopped) { - mediaPlayer = new QMediaPlayer; - connect(mediaPlayer, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), =(QMediaPlayer::Error error){ handleMediaPlayerError(error); }); - mediaPlayer->setMedia(QUrl::fromLocalFile(fileName)); - mediaPlayer->play(); - } - throw(0); - } - catch (int e){ - } + try { + QModelIndexList indices = getModelIndices(); + if (indices.isEmpty()) throw(0); + + QStringList args; + args << "-s" << "d"; // delete stored tag info (no other processing) + args << getArgumentsByOptions(); + + QModelIndex index = indices.last(); + int row = model->itemFromIndex(index)->row(); + QStandardItem *item = getItem(row, "Path/File"); + QString fileName = item->text(); + writeLog(fileName, LOGTYPE_TRACE); + + bool isToBeStopped = false; + if (mediaPlayer) { + if (mediaPlayer->state()==QMediaPlayer::State::PlayingState) { + QString playedFileName = mediaPlayer->currentMedia().request().url().toLocalFile(); + if (fileName==playedFileName){ + isToBeStopped = true; + } + } + delete mediaPlayer; + } + if (!isToBeStopped) { + mediaPlayer = new QMediaPlayer; + connect(mediaPlayer, QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), =(QMediaPlayer::Error error){ handleMediaPlayerError(error); }); + mediaPlayer->setMedia(QUrl::fromLocalFile(fileName)); + mediaPlayer->play(); + } + throw(0); + } + catch (int e){ + } } void MainWindow::on_cancelButton_clicked() { - isCancelled = true; - writeLog(QString("isCancelled := true"), LOGTYPE_TRACE); + isCancelled = true; + writeLog(QString("isCancelled := true"), LOGTYPE_TRACE); } +/** + * Clears the log content + */ void MainWindow::on_clearLogButton_clicked() { - try { - bool isConfirmSuppressed = settings->value("clearLogs_ConfirmSuppressed", false).toBool(); - if (!isConfirmSuppressed){ - int r = MyMessageBox::question(this, appTitle+" - "+tr("Clear Logs?"), - tr("This will clear all log results.\n" - "Are you sure?"), - tr("Don't ask me again"), - isConfirmSuppressed, - QMessageBox::Yes | QMessageBox::No, - QMessageBox::No); - operationTime.restart(); - if (r == QMessageBox::No) { - throw(0); - } - if (isConfirmSuppressed){ - settings->setValue("clearLogs_ConfirmSuppressed", true); - } - } - - this->logPlainTextEdit->clear(); - throw(0); - } - catch (int e){ - } + try { + bool isConfirmSuppressed = settings->value("clearLogs_ConfirmSuppressed", false).toBool(); + if (!isConfirmSuppressed){ + int r = MyMessageBox::question(this, appTitle+" - "+tr("Clear Logs?"), + tr("This will clear all log results.\n" + "Are you sure?"), + tr("Don't ask me again"), + isConfirmSuppressed, + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No); + elapsedTimer.restart(); + if (r == QMessageBox::No) { + throw(0); + } + if (isConfirmSuppressed){ + settings->setValue("clearLogs_ConfirmSuppressed", true); + } + } + + this->logPlainTextEdit->clear(); + throw(0); + } + catch (int e){ + } +} + +/** + * Copies the log content into the clipboard + */ +void MainWindow::on_copyLogButton_clicked() +{ + QClipboard *clipboard = QGuiApplication::clipboard(); + clipboard->setText(this->logPlainTextEdit->toPlainText()); } void MainWindow::on_logDockWidget_visibilityChanged(bool visible) { - actionLogDock->setChecked(visible); + actionLogDock->setChecked(visible); } QDir MainWindow::directoryOf(const QString &subdir) { - QDir dir(QApplication::applicationDirPath()); + QDir dir(QApplication::applicationDirPath()); #if defined(Q_OS_WIN) - //if (dir.dirName().toLower() == "debug" || dir.dirName().toLower() == "release") - if (dir.dirName().toLower() == "bin") - dir.cdUp(); + //if (dir.dirName().toLower() == "debug" || dir.dirName().toLower() == "release") + if (dir.dirName().toLower() == "bin") + dir.cdUp(); #elif defined(Q_OS_MAC) - if (dir.dirName() == "MacOS") { - dir.cdUp(); - dir.cdUp(); - dir.cdUp(); - } + if (dir.dirName() == "MacOS") { + dir.cdUp(); + dir.cdUp(); + dir.cdUp(); + } #else //if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) - QRegExp rx("^(.*)/usr/bin$"); - if (dir.absolutePath().toLower() == "/usr/bin") - dir.cd("/usr/share/qmp3gain"); - else if (rx.indexIn(dir.absolutePath()) != -1) { // // running from linux appImage results for example /tmp/.mount_qmp3gaCQ7xne/usr/bin - QString prePath = rx.cap(1); - dir.cd(prePath + "/usr/share/qmp3gain"); - } - else if (dir.dirName().toLower() == "bin") - dir.cdUp(); + QRegExp rx("^(.*)/usr/bin$"); + if (dir.absolutePath().toLower() == "/usr/bin") + dir.cd("/usr/share/qmp3gain"); + else if (rx.indexIn(dir.absolutePath()) != -1) { // // running from linux appImage results for example /tmp/.mount_qmp3gaCQ7xne/usr/bin + QString prePath = rx.cap(1); + dir.cd(prePath + "/usr/share/qmp3gain"); + } + else if (dir.dirName().toLower() == "bin") + dir.cdUp(); #endif - dir.cd(subdir); - return dir; + dir.cd(subdir); + return dir; } void MainWindow::switchLanguage(QAction *action) { - QString locale(""); + QString locale(""); + + if (!action) { + locale = settings->value("locale", QLocale::system().name()).toString(); + }else{ + locale = action->data().toString(); + } + + QString qmPath = directoryOf("translations").absolutePath(); + QString qmFile = appTitle.toLower() + QString("_") + locale; + QString qmPathFile = qmPath+"/"+qmFile+".qm"; + + bool isLoaded = appTranslator->load(qmFile, qmPath); + if (isLoaded) { + writeLog(tr("Translation file %1 is loaded").arg(qmPathFile), LOGTYPE_TRACE); + settings->setValue("locale", locale); + // search for the action belongs to our locale + foreach(QAction *a, menuLanguageActionGroup->actions()) { + if (a->data().toString() == locale) { + a->setChecked(true); + writeLog(tr("%1 locale is used").arg(locale), LOGTYPE_TRACE); + break; + } + } + } + else{ + if (locale==defaultLocale) + writeLog(tr("No translation file is necessary"), LOGTYPE_TRACE); + else + writeLog(tr("Translation file %1 cannot be found, %2 locale is refused").arg(qmPathFile).arg(locale), LOGTYPE_ERROR); + + settings->setValue("locale", defaultLocale); + actionDefault_Language->setChecked(true); + writeLog(tr("Default %1 locale is used").arg(defaultLocale), LOGTYPE_TRACE); + } - if (!action) { - locale = settings->value("locale", QLocale::system().name()).toString(); - }else{ - locale = action->data().toString(); - } - - QString qmPath = directoryOf("translations").absolutePath(); - QString qmFile = appTitle.toLower() + QString("_") + locale; - QString qmPathFile = qmPath+"/"+qmFile+".qm"; - - bool isLoaded = appTranslator->load(qmFile, qmPath); - if (isLoaded) { - writeLog(tr("Translation file %1 is loaded").arg(qmPathFile), LOGTYPE_TRACE); - settings->setValue("locale", locale); - // search for the action belongs to our locale - foreach(QAction *a, menuLanguageActionGroup->actions()) { - if (a->data().toString() == locale) { - a->setChecked(true); - writeLog(tr("%1 locale is used").arg(locale), LOGTYPE_TRACE); - break; - } - } - } - else{ - if (locale==defaultLocale) - writeLog(tr("No translation file is necessary"), LOGTYPE_TRACE); - else - writeLog(tr("Translation file %1 cannot be found, %2 locale is refused").arg(qmPathFile).arg(locale), LOGTYPE_ERROR); - - settings->setValue("locale", defaultLocale); - actionDefault_Language->setChecked(true); - writeLog(tr("Default %1 locale is used").arg(defaultLocale), LOGTYPE_TRACE); - } - - retranslateUi(this); - refreshUi(); - refreshGUI(); + retranslateUi(this); + refreshUi(); + refreshGUI(); } void MainWindow::createLanguageMenu() { - // fist menu item: actionDefault_Language "Original (English)" - actionDefault_Language->setData(defaultLocale); - menuLanguageActionGroup->addAction(actionDefault_Language); - - connect(menuLanguageActionGroup, SIGNAL(triggered(QAction *)), this, SLOT(switchLanguage(QAction *))); - - QDir qmDir = directoryOf("translations"); - QStringList fileNames = qmDir.entryList(QStringList(appTitle.toLower()+"_*.qm")); - QRegExp rx("^" + appTitle.toLower() + "_(.*)\\.qm$"); - QList<QAction*> actions; - - foreach (QString fileName, fileNames) { - rx.indexIn(fileName); // get locale - QString locale = rx.cap(1); - - QTranslator translator; - translator.load(fileName, qmDir.absolutePath()); - - //: Translate it to your language in your language. For example for Italian translation it is Italiano. - QString language = translator.translate("MainWindow", "Language"); - - QAction* action = new QAction(language, this); - action->setCheckable(true); - action->setData(locale); - - actions.append(action); - } - - // sort actions list by its text (containing translated language) property - auto compare = (QAction* a , QAction* b) - { - return (a->text()) < (b->text()); - }; - std::sort(actions.begin(), actions.end(), compare); - - foreach (QAction* action, actions) { - menuLanguage->addAction(action); - menuLanguageActionGroup->addAction(action); - } + // fist menu item: actionDefault_Language "Original (English)" + actionDefault_Language->setData(defaultLocale); + menuLanguageActionGroup->addAction(actionDefault_Language); + + connect(menuLanguageActionGroup, SIGNAL(triggered(QAction *)), this, SLOT(switchLanguage(QAction *))); + + QDir qmDir = directoryOf("translations"); + QStringList fileNames = qmDir.entryList(QStringList(appTitle.toLower()+"_*.qm")); + QRegExp rx("^" + appTitle.toLower() + "_(.*)\\.qm$"); + QList<QAction*> actions; + + foreach (QString fileName, fileNames) { + rx.indexIn(fileName); // get locale + QString locale = rx.cap(1); + + QTranslator translator; + translator.load(fileName, qmDir.absolutePath()); + + //: Translate it to your language in your language. For example for Italian translation it is Italiano. + QString language = translator.translate("MainWindow", "Language"); + + QAction* action = new QAction(language, this); + action->setCheckable(true); + action->setData(locale); + + actions.append(action); + } + + // sort actions list by its text (containing translated language) property + auto compare = (QAction* a , QAction* b) + { + return (a->text()) < (b->text()); + }; + std::sort(actions.begin(), actions.end(), compare); + + foreach (QAction* action, actions) { + menuLanguage->addAction(action); + menuLanguageActionGroup->addAction(action); + } } void MainWindow::writeSettings() { - settings->setValue("geometry", saveGeometry()); - settings->setValue("state", saveState()); + settings->setValue("geometry", saveGeometry()); + settings->setValue("state", saveState()); + + settings->setValue("doubleSpinBox_targetNormalValue", doubleSpinBox_targetNormalValue->value()); + + // action elements + foreach (QAction* action, actions) { + settings->setValue(action->objectName(), action->isChecked()); + } - settings->setValue("doubleSpinBox_targetNormalValue", doubleSpinBox_targetNormalValue->value()); + if (lastAddedFolder==".") + settings->remove("lastAddedFolder"); + else + settings->setValue("lastAddedFolder", lastAddedFolder); + + if (!backEndFileName.isEmpty()) + settings->setValue("backEndFileName", backEndFileName); + else + settings->remove("backEndFileName"); + + if (fileLog && !fileLog->fileName().isEmpty()) + settings->setValue("logFileName", fileLog->fileName()); + else + settings->remove("logFileName"); + + if (fileLog){ + if (fileLog->isOpen()) + fileLog->close(); + delete fileLog; + } - // action elements - foreach (QAction* action, actions) { - settings->setValue(action->objectName(), action->isChecked()); - } - - if (lastAddedFolder==".") - settings->remove("lastAddedFolder"); - else - settings->setValue("lastAddedFolder", lastAddedFolder); - - if (!backEndFileName.isEmpty()) - settings->setValue("backEndFileName", backEndFileName); - else - settings->remove("backEndFileName"); - - if (fileLog && !fileLog->fileName().isEmpty()) - settings->setValue("logFileName", fileLog->fileName()); - else - settings->remove("logFileName"); - - if (fileLog){ - if (fileLog->isOpen()) - fileLog->close(); - delete fileLog; - } + // store column widths of tableView + QList<QVariant> widths; // QList<int> + for (int i=0; i<tableView->model()->columnCount(); i++){ + bool isColumnHidden = tableView->isColumnHidden(i); // columnWidth is zero if the column is hidden + if (isColumnHidden) { + tableView->setColumnHidden(i, false); + } + widths.append(QVariant(tableView->columnWidth(i))); + if (isColumnHidden) { + tableView->setColumnHidden(i, isColumnHidden); + } + } + settings->setValue("columnWidths", QVariant(widths)); } void MainWindow::readSettings() { - restoreGeometry(settings->value("geometry").toByteArray()); - restoreState(settings->value("state").toByteArray()); + restoreGeometry(settings->value("geometry").toByteArray()); + restoreState(settings->value("state").toByteArray()); + + doubleSpinBox_targetNormalValue->setValue(settings->value("doubleSpinBox_targetNormalValue", defaultNormalTargetValue).toDouble()); + + // action elements + foreach (QAction* action, actions) { + action->setChecked(settings->value(action->objectName(), action->isChecked()).toBool()); + } + + // log checkboxes + foreach(QAction *action, logOutputTypes.keys()) { + QCheckBox *cb = logOutputTypes.value(action); + cb->setChecked(settings->value(action->objectName(), action->isChecked()).toBool()); + } - doubleSpinBox_targetNormalValue->setValue(settings->value("doubleSpinBox_targetNormalValue", defaultNormalTargetValue).toDouble()); + lastAddedFolder = settings->value("lastAddedFolder", ".").toString(); + QFileInfo fi(lastAddedFolder); + if (!fi.exists()) lastAddedFolder = "."; + + backEndFileName = settings->value("backEndFileName", "").toString(); + + QString logFileName = settings->value("logFileName", "").toString(); + if (!logFileName.isEmpty()){ + fileLog = new QFile(logFileName); + if (!fileLog->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)){ + QMessageBox::critical(this, appTitle, + tr("Cannot write log file: %1").arg(fileLog->fileName())); + elapsedTimer.restart(); + delete fileLog; + } + } - // action elements - foreach (QAction* action, actions) { - action->setChecked(settings->value(action->objectName(), action->isChecked()).toBool()); - } - - // log checkboxes - foreach(QAction *action, logOutputTypes.keys()) { - QCheckBox *cb = logOutputTypes.value(action); - cb->setChecked(settings->value(action->objectName(), action->isChecked()).toBool()); - } - - lastAddedFolder = settings->value("lastAddedFolder", ".").toString(); - QFileInfo fi(lastAddedFolder); - if (!fi.exists()) lastAddedFolder = "."; - - backEndFileName = settings->value("backEndFileName", "").toString(); - - QString logFileName = settings->value("logFileName", "").toString(); - if (!logFileName.isEmpty()){ - fileLog = new QFile(logFileName); - if (!fileLog->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)){ - QMessageBox::critical(this, appTitle, - tr("Cannot write log file: %1").arg(fileLog->fileName())); - operationTime.restart(); - delete fileLog; - } - } + QList<QVariant> widths = settings->value("columnWidths").toList(); // QList<int> + if (!widths.isEmpty()){ + tableView->setProperty("columnWidths", QVariant(widths)); + } } void MainWindow::refreshUi(){ - if (windowTitle().contains("%1")){ - setWindowTitle(windowTitle().arg(appTitle)); - } - - // explanation: labelTargetNormalValue->text() = "dB (default %1)" - labelTargetNormalValue->setText(QString(labelTargetNormalValue->text()).arg(defaultNormalTargetValue, 0, 'f', 1)); - - QStringList modelTranslatedHeaderList; - for ( int i = 0; modelHeaderLabelsi; ++i ) { - modelTranslatedHeaderList << tr(modelHeaderLabelsi); - } - model->setHorizontalHeaderLabels(modelTranslatedHeaderList); + if (windowTitle().contains("%1")){ + setWindowTitle(windowTitle().arg(appTitle)); + } + + // explanation: labelTargetNormalValue->text() = "dB (default %1)" + labelTargetNormalValue->setText(QString(labelTargetNormalValue->text()).arg(defaultNormalTargetValue, 0, 'f', 1)); + + QStringList modelTranslatedHeaderList; + for ( int i = 0; modelHeaderLabelsi; ++i ) { + modelTranslatedHeaderList << tr(modelHeaderLabelsi); + } + model->setHorizontalHeaderLabels(modelTranslatedHeaderList); } void MainWindow::enableGUI(){ - // enable complete GUI except cancelButton and tableView - menubar->setEnabled(true); - toolBar->setEnabled(true); - doubleSpinBox_targetNormalValue->setEnabled(true); - cancelButton->setEnabled(false); - isCancelled = false; - isPopupErrorSuppressed = QVariant(); - isOpenLogPanelQuestionSuppressed = QVariant(); - setProgress(QVariant(0), QVariant(0)); - updateStatusBar(""); - - //logDockWidget - clearLogButton->setEnabled(true); - groupBox_logCheckboxes->setEnabled(true); - - int spinBox_beepAfter = settings->value("advancedOptionsDialog/spinBox_beepAfter", 0).toInt(); - int elapsedTime = operationTime.elapsed()/1000; // ms -> second - if (actionBeep_when_finished->isChecked() && elapsedTime>=spinBox_beepAfter){ - if (beepSound) - beepSound->play(); - else - QApplication::beep(); - } + // enable complete GUI except cancelButton and tableView + menubar->setEnabled(true); + toolBar->setEnabled(true); + doubleSpinBox_targetNormalValue->setEnabled(true); + cancelButton->setEnabled(false); + isCancelled = false; + isPopupErrorSuppressed = QVariant(); + isOpenLogPanelQuestionSuppressed = QVariant(); + setProgress(QVariant(0), QVariant(0)); + updateStatusBar(""); + + //logDockWidget + clearLogButton->setEnabled(true); + copyLogButton->setEnabled(true); + groupBox_logCheckboxes->setEnabled(true); + + int spinBox_beepAfter = settings->value("advancedOptionsDialog/spinBox_beepAfter", 0).toInt(); + int elapsedTime = elapsedTimer.elapsed()/1000; // ms -> second + if (actionBeep_when_finished->isChecked() && elapsedTime>=spinBox_beepAfter){ + if (beepSound) + beepSound->play(); + else + QApplication::beep(); + } - this->enabledGUI = true; + this->enabledGUI = true; } void MainWindow::disableGUI(){ - // disable complete GUI except cancelButton and tableView - menubar->setEnabled(false); - toolBar->setEnabled(false); - doubleSpinBox_targetNormalValue->setEnabled(false); - cancelButton->setEnabled(true); - isCancelled = false; - isPopupErrorSuppressed = QVariant(); - isOpenLogPanelQuestionSuppressed = QVariant(); - setProgress(QVariant(0), QVariant(0)); - - //logDockWidget - clearLogButton->setEnabled(false); - groupBox_logCheckboxes->setEnabled(false); + // disable complete GUI except cancelButton and tableView + menubar->setEnabled(false); + toolBar->setEnabled(false); + doubleSpinBox_targetNormalValue->setEnabled(false); + cancelButton->setEnabled(true); + isCancelled = false; + isPopupErrorSuppressed = QVariant(); + isOpenLogPanelQuestionSuppressed = QVariant(); + setProgress(QVariant(0), QVariant(0)); + + //logDockWidget + clearLogButton->setEnabled(false); + copyLogButton->setEnabled(false); + groupBox_logCheckboxes->setEnabled(false); - // stop played mp3 - delete mediaPlayer; + // stop played mp3 + delete mediaPlayer; - this->enabledGUI = false; - operationTime.start(); + this->enabledGUI = false; + elapsedTimer.start(); } void MainWindow::refreshGUI() { - // show/hide some columns - if (actionShow_Path_slash_File->isChecked()) { - tableView->setColumnHidden(modelHeaderList.indexOf("Path/File"), false); - tableView->setColumnHidden(modelHeaderList.indexOf("Path"), true); - tableView->setColumnHidden(modelHeaderList.indexOf("File"), true); - } else if (actionShow_File_only->isChecked()) { - tableView->setColumnHidden(modelHeaderList.indexOf("Path/File"), true); - tableView->setColumnHidden(modelHeaderList.indexOf("Path"), true); - tableView->setColumnHidden(modelHeaderList.indexOf("File"), false); - } else if (actionShow_Path_at_File->isChecked()) { - tableView->setColumnHidden(modelHeaderList.indexOf("Path/File"), true); - tableView->setColumnHidden(modelHeaderList.indexOf("Path"), false); - tableView->setColumnHidden(modelHeaderList.indexOf("File"), false); - } - // these columns are always hidden - bool checkBox_ShowHiddenFields = settings->value("advancedOptionsDialog/checkBox_ShowHiddenFields", false).toBool(); - tableView->setColumnHidden(modelHeaderList.indexOf("Max Amplitude"), !checkBox_ShowHiddenFields); - tableView->setColumnHidden(modelHeaderList.indexOf("Album Max Amplitude"), !checkBox_ShowHiddenFields); - tableView->setColumnHidden(modelHeaderList.indexOf("dBGain"), !checkBox_ShowHiddenFields); - tableView->setColumnHidden(modelHeaderList.indexOf("Album dBGain"), !checkBox_ShowHiddenFields); - - // toolbar visualization - if (actionBig->isChecked()) { - toolBar->setVisible(true); - toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); - toolBar->setIconSize(iconDefaultSize); - }else if (actionSmall->isChecked()) { - toolBar->setVisible(true); - toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); - toolBar->setIconSize(iconDefaultSize/2.0); - }else if (actionText_only->isChecked()) { - toolBar->setVisible(true); - toolBar->setToolButtonStyle(Qt::ToolButtonTextOnly); - }else if (actionNone->isChecked()) { - toolBar->setVisible(false); - } - - // log frame - logDockWidget->setVisible(actionLogDock->isChecked()); - - settings->beginGroup("advancedOptionsDialog"); - - bool checkBox_Maximizing = settings->value("checkBox_Maximizing", false).toBool(); - tableView->setColumnHidden(modelHeaderList.indexOf("Max Noclip Gain"), !checkBox_Maximizing); - - bool checkBox_ShowNoFileProgress = settings->value("checkBox_ShowNoFileProgress", false).toBool(); - label_FileProgress->setVisible(!checkBox_ShowNoFileProgress); - progressBar_File->setVisible(!checkBox_ShowNoFileProgress); - - bool isLogBackendEnabled = settings->value("horizontalSlider_logBackendDepth", 0).toInt() > 0; - checkBox_logBackend->setVisible(isLogBackendEnabled); + // show/hide some columns + if (actionShow_Path_slash_File->isChecked()) { + tableView->setColumnHidden(modelHeaderList.indexOf("Path/File"), false); + tableView->setColumnHidden(modelHeaderList.indexOf("Path"), true); + tableView->setColumnHidden(modelHeaderList.indexOf("File"), true); + } else if (actionShow_File_only->isChecked()) { + tableView->setColumnHidden(modelHeaderList.indexOf("Path/File"), true); + tableView->setColumnHidden(modelHeaderList.indexOf("Path"), true); + tableView->setColumnHidden(modelHeaderList.indexOf("File"), false); + } else if (actionShow_Path_at_File->isChecked()) { + tableView->setColumnHidden(modelHeaderList.indexOf("Path/File"), true); + tableView->setColumnHidden(modelHeaderList.indexOf("Path"), false); + tableView->setColumnHidden(modelHeaderList.indexOf("File"), false); + } + // these columns are always hidden + bool checkBox_ShowHiddenFields = settings->value("advancedOptionsDialog/checkBox_ShowHiddenFields", false).toBool(); + tableView->setColumnHidden(modelHeaderList.indexOf("Max Amplitude"), !checkBox_ShowHiddenFields); + tableView->setColumnHidden(modelHeaderList.indexOf("Album Max Amplitude"), !checkBox_ShowHiddenFields); + tableView->setColumnHidden(modelHeaderList.indexOf("dBGain"), !checkBox_ShowHiddenFields); + tableView->setColumnHidden(modelHeaderList.indexOf("Album dBGain"), !checkBox_ShowHiddenFields); + + // toolbar visualization + if (actionBig->isChecked()) { + toolBar->setVisible(true); + toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); + toolBar->setIconSize(iconDefaultSize); + }else if (actionSmall->isChecked()) { + toolBar->setVisible(true); + toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly); + toolBar->setIconSize(iconDefaultSize/2.0); + }else if (actionText_only->isChecked()) { + toolBar->setVisible(true); + toolBar->setToolButtonStyle(Qt::ToolButtonTextOnly); + }else if (actionNone->isChecked()) { + toolBar->setVisible(false); + } + + // log frame + logDockWidget->setVisible(actionLogDock->isChecked()); + + settings->beginGroup("advancedOptionsDialog"); + + bool checkBox_Maximizing = settings->value("checkBox_Maximizing", false).toBool(); + tableView->setColumnHidden(modelHeaderList.indexOf("Max Noclip Gain"), !checkBox_Maximizing); + + bool checkBox_ShowNoFileProgress = settings->value("checkBox_ShowNoFileProgress", false).toBool(); + label_FileProgress->setVisible(!checkBox_ShowNoFileProgress); + progressBar_File->setVisible(!checkBox_ShowNoFileProgress); - bool isLogTraceEnabled = settings->value("horizontalSlider_logTraceDepth", 0).toInt() > 0; - checkBox_logTrace->setVisible(isLogTraceEnabled); + bool isLogBackendEnabled = settings->value("horizontalSlider_logBackendDepth", 0).toInt() > 0; + checkBox_logBackend->setVisible(isLogBackendEnabled); - settings->endGroup(); + bool isLogTraceEnabled = settings->value("horizontalSlider_logTraceDepth", 0).toInt() > 0; + checkBox_logTrace->setVisible(isLogTraceEnabled); - refreshMenu(); + settings->endGroup(); + + refreshMenu(); } void MainWindow::refreshMenu(){ - bool isBackEndAvailable = this->isBackEndAvailable(); - bool listEmpty = model->rowCount()==0; + bool isBackEndAvailable = this->isBackEndAvailable(); + bool listEmpty = model->rowCount()==0; - // some options might be not used - if (!QSystemTrayIcon::isSystemTrayAvailable()) - actionMinimize_to_tray->setEnabled(false); - - actionLoad_Analysis_results->setEnabled(isBackEndAvailable); - actionSave_Analysis_results->setEnabled(!listEmpty); - actionAdd_Files->setEnabled(isBackEndAvailable); - actionAdd_Folder->setEnabled(isBackEndAvailable); - actionSelect_All_Files->setEnabled(!listEmpty); - actionSelect_No_Files->setEnabled(!listEmpty); - actionInvert_selection->setEnabled(!listEmpty); - actionClear_Selected_Files->setEnabled(!listEmpty); - actionClear_All_files->setEnabled(!listEmpty); - actionTrack_Analysis->setEnabled(isBackEndAvailable && !listEmpty); - actionAlbum_Analysis->setEnabled(isBackEndAvailable && !listEmpty); - actionClear_Analysis->setEnabled(isBackEndAvailable && !listEmpty); - actionTrack_Gain->setEnabled(isBackEndAvailable && !listEmpty); - actionAlbum_Gain->setEnabled(isBackEndAvailable && !listEmpty); - actionConstant_Gain->setEnabled(isBackEndAvailable && !listEmpty); - actionUndo_Gain_changes->setEnabled(isBackEndAvailable && !listEmpty); - actionRemove_Tags_from_files->setEnabled(isBackEndAvailable && !listEmpty); - - // some items are visible only if Options/Advanced/Maximizing checkbox is on - bool maximizing = settings->value("advancedOptionsDialog/checkBox_Maximizing", false).toBool(); - actionMax_No_clip_Analysis->setEnabled(isBackEndAvailable && !listEmpty && maximizing); - actionMax_No_clip_Analysis->setVisible(isBackEndAvailable && maximizing); - actionMax_No_clip_Gain_for_Each_file->setEnabled(isBackEndAvailable && !listEmpty && maximizing); - actionMax_No_clip_Gain_for_Each_file->setVisible(isBackEndAvailable && maximizing); - actionMax_No_clip_Gain_for_Album->setEnabled(isBackEndAvailable && !listEmpty && maximizing); - actionMax_No_clip_Gain_for_Album->setVisible(isBackEndAvailable && maximizing); - - bool isLogBackendEnabled = settings->value("advancedOptionsDialog/horizontalSlider_logBackendDepth", 0).toInt() > 0; - actionLogBackend->setVisible(isLogBackendEnabled); - bool isLogTraceEnabled = settings->value("advancedOptionsDialog/horizontalSlider_logTraceDepth", 0).toInt() > 0; - actionLogTrace->setVisible(isLogTraceEnabled); + // some options might be not used + if (!QSystemTrayIcon::isSystemTrayAvailable()) + actionMinimize_to_tray->setEnabled(false); + + actionLoad_Analysis_results->setEnabled(isBackEndAvailable); + actionSave_Analysis_results->setEnabled(!listEmpty); + actionAdd_Files->setEnabled(isBackEndAvailable); + actionAdd_Folder->setEnabled(isBackEndAvailable); + actionSelect_All_Files->setEnabled(!listEmpty); + actionSelect_No_Files->setEnabled(!listEmpty); + actionInvert_selection->setEnabled(!listEmpty); + actionClear_Selected_Files->setEnabled(!listEmpty); + actionClear_All_files->setEnabled(!listEmpty); + actionTrack_Analysis->setEnabled(isBackEndAvailable && !listEmpty); + actionAlbum_Analysis->setEnabled(isBackEndAvailable && !listEmpty); + actionClear_Analysis->setEnabled(isBackEndAvailable && !listEmpty); + actionTrack_Gain->setEnabled(isBackEndAvailable && !listEmpty); + actionAlbum_Gain->setEnabled(isBackEndAvailable && !listEmpty); + actionConstant_Gain->setEnabled(isBackEndAvailable && !listEmpty); + actionUndo_Gain_changes->setEnabled(isBackEndAvailable && !listEmpty); + actionRemove_Tags_from_files->setEnabled(isBackEndAvailable && !listEmpty); + + // some items are visible only if Options/Advanced/Maximizing checkbox is on + bool maximizing = settings->value("advancedOptionsDialog/checkBox_Maximizing", false).toBool(); + actionMax_No_clip_Analysis->setEnabled(isBackEndAvailable && !listEmpty && maximizing); + actionMax_No_clip_Analysis->setVisible(isBackEndAvailable && maximizing); + actionMax_No_clip_Gain_for_Each_file->setEnabled(isBackEndAvailable && !listEmpty && maximizing); + actionMax_No_clip_Gain_for_Each_file->setVisible(isBackEndAvailable && maximizing); + actionMax_No_clip_Gain_for_Album->setEnabled(isBackEndAvailable && !listEmpty && maximizing); + actionMax_No_clip_Gain_for_Album->setVisible(isBackEndAvailable && maximizing); + + bool isLogBackendEnabled = settings->value("advancedOptionsDialog/horizontalSlider_logBackendDepth", 0).toInt() > 0; + actionLogBackend->setVisible(isLogBackendEnabled); + bool isLogTraceEnabled = settings->value("advancedOptionsDialog/horizontalSlider_logTraceDepth", 0).toInt() > 0; + actionLogTrace->setVisible(isLogTraceEnabled); } QStringList MainWindow::getArgumentsByOptions(){ - QStringList args; + QStringList args; - // output is a database-friendly tab-delimited list - args << "-o"; + // output is a database-friendly tab-delimited list + args << "-o"; - // ignore clipping warning when applying gain - args << "-c"; + // ignore clipping warning when applying gain + args << "-c"; - if (doubleSpinBox_targetNormalValue->value()!=defaultNormalTargetValue){ - // -d <n> - modify suggested dB gain by floating-point n - args << "-d" << QString("%1").arg(doubleSpinBox_targetNormalValue->value()-defaultNormalTargetValue, 0, 'f', 1); - } - if (actionPreserve_file_date_time->isChecked()){ - // p - Preserve original file timestamp - args << "-p"; - } - if (actionNo_check_for_Layer_I_or_II->isChecked()){ - // -f - Force mp3gain to assume input file is an MPEG 2 Layer III file - // (i.e. don't check for mis-named Layer I or Layer II files) - args << "-f"; - } - if (actionDon_t_clip_when_doing_track_gain->isChecked()){ - // -k - automatically lower Track/Album gain to not clip audio - args << "-k"; - } - if (actionIgnore_do_not_read_or_write_tags->isChecked()){ - // -s s - skip (ignore) stored tag info (do not read or write tags) - args << "-s" << "s"; - } - if (actionRe_calculate_do_not_read_tags->isChecked()){ - // -s r - force re-calculation (do not read tag info) - args << "-s" << "r"; - } - if (!settings->value("advancedOptionsDialog/checkBox_UseNoTempFiles", false).toBool()){ - // -t - writes modified data to temp file, then deletes original - // instead of modifying bytes in original file - args << "-t"; - } + if (doubleSpinBox_targetNormalValue->value()!=defaultNormalTargetValue){ + // -d <n> - modify suggested dB gain by floating-point n + args << "-d" << QString("%1").arg(doubleSpinBox_targetNormalValue->value()-defaultNormalTargetValue, 0, 'f', 1); + } + if (actionPreserve_file_date_time->isChecked()){ + // p - Preserve original file timestamp + args << "-p"; + } + if (actionNo_check_for_Layer_I_or_II->isChecked()){ + // -f - Force mp3gain to assume input file is an MPEG 2 Layer III file + // (i.e. don't check for mis-named Layer I or Layer II files) + args << "-f"; + } + if (actionDon_t_clip_when_doing_track_gain->isChecked()){ + // -k - automatically lower Track/Album gain to not clip audio + args << "-k"; + } + if (actionIgnore_do_not_read_or_write_tags->isChecked()){ + // -s s - skip (ignore) stored tag info (do not read or write tags) + args << "-s" << "s"; + } + if (actionRe_calculate_do_not_read_tags->isChecked()){ + // -s r - force re-calculation (do not read tag info) + args << "-s" << "r"; + } + if (!settings->value("advancedOptionsDialog/checkBox_UseNoTempFiles", false).toBool()){ + // -t - writes modified data to temp file, then deletes original + // instead of modifying bytes in original file + args << "-t"; + } - return args; + return args; } void MainWindow::setProgress(QVariant progressFile, QVariant progressTotal){ - if (!progressFile.isNull()){ - bool isValid; - double value = progressFile.toDouble(&isValid); - if (isValid){ - progressBar_File->setValue(value); - writeLog(QString("progressFile: %1%").arg(progressBar_File->value()), LOGTYPE_TRACE); - } - } - if (!progressTotal.isNull()){ - bool isValid; - double value = progressTotal.toDouble(&isValid); - if (isValid){ - progressBar_Total->setValue(value); - if (trayIcon){ - if (value!=0) - trayIcon->setToolTip(tr("Work in progress: %1%").arg(progressBar_Total->value())); - else - trayIcon->setToolTip(tr("No operation running")); - } - writeLog(QString("progressTotal: %1%").arg(progressBar_Total->value()), LOGTYPE_TRACE); - } - }else{ - if (trayIcon) - trayIcon->setToolTip(tr("No operation running")); - } + if (!progressFile.isNull()){ + bool isValid; + double value = progressFile.toDouble(&isValid); + if (isValid){ + progressBar_File->setValue(value); + writeLog(QString("progressFile: %1%").arg(progressBar_File->value()), LOGTYPE_TRACE); + } + } + if (!progressTotal.isNull()){ + bool isValid; + double value = progressTotal.toDouble(&isValid); + if (isValid){ + progressBar_Total->setValue(value); + if (trayIcon){ + if (value!=0) + trayIcon->setToolTip(tr("Work in progress: %1%").arg(progressBar_Total->value())); + else + trayIcon->setToolTip(tr("No operation running")); + } + writeLog(QString("progressTotal: %1%").arg(progressBar_Total->value()), LOGTYPE_TRACE); + } + }else{ + if (trayIcon) + trayIcon->setToolTip(tr("No operation running")); + } } int MainWindow::getMP3FilesByFolder(const QString & dir, const int level, const double passSlice){ - try { - QDir qdir(dir); - QFileInfoList fileInfoList = qdir.entryInfoList ( QStringList() << "*.mp3", QDir::Files, QDir::NoSort ); - QFileInfoList dirInfoList; - if (actionAdd_Subfolders->isChecked()){ - dirInfoList = qdir.entryInfoList ( QStringList(), QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDir::NoSort ); - } - double startProgress = progressBar_Total->doubleValue(); - - for (int i = 0; i < fileInfoList.size(); ++i) { - if (level==0){ - setProgress(QVariant(), - QVariant(startProgress+passSlice*(((double)(i+1))/(fileInfoList.size()+(actionAdd_Subfolders->isChecked() ? dirInfoList.size() : 0))))); - qApp->processEvents(QEventLoop::AllEvents); - if (isCancelled) throw(-1); - } - QFileInfo fi(fileInfoList.at(i)); - // check that actual filename is already stored in model - QList<QStandardItem *> found = model->findItems(fi.absoluteFilePath(), Qt::MatchExactly, 0); - if (found.count()>0) continue; - QStandardItem *item0 = new QStandardItem(fi.absoluteFilePath()); - QStandardItem *item1 = new QStandardItem(fi.absolutePath()); - QStandardItem *item2 = new QStandardItem(fi.fileName()); - model->appendRow(QList<QStandardItem *>() << item0 << item1 << item2); - QModelIndex index = model->indexFromItem(item0); - if (index.isValid()){ - lastAddedIndices.append(index); - } - } - - if (actionAdd_Subfolders->isChecked()){ - for (int i = 0; i < dirInfoList.size(); ++i) { - if (level==0){ - setProgress(QVariant(), - QVariant(startProgress+passSlice*(((double)(fileInfoList.size()+i+1))/(fileInfoList.size()+dirInfoList.size())))); - qApp->processEvents(QEventLoop::AllEvents); - if (isCancelled) throw(-1); - } - QFileInfo fi(dirInfoList.at(i)); - getMP3FilesByFolder(fi.absoluteFilePath(), level+1); - } - } - throw(0); - } - catch (int e){ - return e; - } - return 0; + try { + QDir qdir(dir); + QFileInfoList fileInfoList = qdir.entryInfoList ( QStringList() << "*.mp3", QDir::Files, QDir::NoSort ); + QFileInfoList dirInfoList; + if (actionAdd_Subfolders->isChecked()){ + dirInfoList = qdir.entryInfoList ( QStringList(), QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDir::NoSort ); + } + double startProgress = progressBar_Total->doubleValue(); + + for (int i = 0; i < fileInfoList.size(); ++i) { + if (level==0){ + setProgress(QVariant(), + QVariant(startProgress+passSlice*(((double)(i+1))/(fileInfoList.size()+(actionAdd_Subfolders->isChecked() ? dirInfoList.size() : 0))))); + qApp->processEvents(QEventLoop::AllEvents); + if (isCancelled) throw(-1); + } + QFileInfo fi(fileInfoList.at(i)); + // check that actual filename is already stored in model + QList<QStandardItem *> found = model->findItems(fi.absoluteFilePath(), Qt::MatchExactly, 0); + if (found.count()>0) continue; + QStandardItem *item0 = new QStandardItem(fi.absoluteFilePath()); + QStandardItem *item1 = new QStandardItem(fi.absolutePath()); + QStandardItem *item2 = new QStandardItem(fi.fileName()); + model->appendRow(QList<QStandardItem *>() << item0 << item1 << item2); + QModelIndex index = model->indexFromItem(item0); + if (index.isValid()){ + lastAddedIndices.append(index); + } + } + + if (actionAdd_Subfolders->isChecked()){ + for (int i = 0; i < dirInfoList.size(); ++i) { + if (level==0){ + setProgress(QVariant(), + QVariant(startProgress+passSlice*(((double)(fileInfoList.size()+i+1))/(fileInfoList.size()+dirInfoList.size())))); + qApp->processEvents(QEventLoop::AllEvents); + if (isCancelled) throw(-1); + } + QFileInfo fi(dirInfoList.at(i)); + getMP3FilesByFolder(fi.absoluteFilePath(), level+1); + } + } + throw(0); + } + catch (int e){ + return e; + } + return 0; } QString MainWindow::getItemText(int row, const QString & column) { - QStandardItem *item = getItem(row, column); - return item ? item->text() : QString(); + QStandardItem *item = getItem(row, column); + return item ? item->text() : QString(); } QVariant MainWindow::getItemValue(int row, const QString & column) { - QStandardItem *item = getItem(row, column); - return item ? item->data() : QVariant(); + QStandardItem *item = getItem(row, column); + return item ? item->data() : QVariant(); } void MainWindow::setItem(int row, QString column, QVariant value) { - QStandardItem *item = getItem(row, column); + QStandardItem *item = getItem(row, column); - if (value.type()==QVariant::Double){ - QString valueStr = value.isNull() ? QString() : QString("%1").arg(value.toDouble(), 0, 'f', 1); - if (item){ - if (!value.isNull()){ - item->setText(valueStr); - item->setData(value); - }else{ - item->setData(0); // before item delete to enable automatic model/view refresh - delete item; - } - }else{ - if (!value.isNull()){ - item = new QStandardItem(valueStr); - item->setData(value); - model->setItem(row, modelHeaderList.indexOf(column), item); - }else{ - // no creation - } - } - }else if (value.type()==QVariant::Bool){ - QString trueStr = tr("Y", "Yes flag in some clipping fields of the file list"); - QString falseStr = tr("", "No flag in some clipping fields of the file list"); - if (item){ - if (!value.isNull()){ - item->setText(value.toBool() ? trueStr : falseStr); - item->setData(value); - }else{ - item->setData(0); // before item delete to enable automatic model/view refresh - delete item; - } - }else{ - if (!value.isNull()){ - item = new QStandardItem(value.toBool() ? trueStr : falseStr); - item->setData(value); - model->setItem(row, modelHeaderList.indexOf(column), item); - }else{ - // no creation - } - } - }else{ - return; // error - } + if (value.type()==QVariant::Double){ + QString valueStr = value.isNull() ? QString() : QString("%1").arg(value.toDouble(), 0, 'f', 1); + if (item){ + if (!value.isNull()){ + item->setText(valueStr); + item->setData(value); + }else{ + item->setData(0); // before item delete to enable automatic model/view refresh + delete item; + } + }else{ + if (!value.isNull()){ + item = new QStandardItem(valueStr); + item->setData(value); + model->setItem(row, modelHeaderList.indexOf(column), item); + }else{ + // no creation + } + } + }else if (value.type()==QVariant::Bool){ + QString trueStr = tr("Y", "Yes flag in some clipping fields of the file list"); + QString falseStr = tr("", "No flag in some clipping fields of the file list"); + if (item){ + if (!value.isNull()){ + item->setText(value.toBool() ? trueStr : falseStr); + item->setData(value); + }else{ + item->setData(0); // before item delete to enable automatic model/view refresh + delete item; + } + }else{ + if (!value.isNull()){ + item = new QStandardItem(value.toBool() ? trueStr : falseStr); + item->setData(value); + model->setItem(row, modelHeaderList.indexOf(column), item); + }else{ + // no creation + } + } + }else{ + return; // error + } } void MainWindow::writeLog(const QString & msg, LogType logType, int level, LogOption logOption) { - bool isLogChecked = false; - int storedLevel; - QString styleSheet; - QString txtMsg = msg; - QString htmlMsg = msg; - - switch (logType) { - case LOGTYPE_ERROR: - styleSheet = this->checkBox_logError->styleSheet(); - if (this->checkBox_logError->isChecked()) - isLogChecked = true; - break; - case LOGTYPE_ANALYSIS: - styleSheet = this->checkBox_logAnalysis->styleSheet(); - if (this->checkBox_logAnalysis->isChecked()) - isLogChecked = true; - break; - case LOGTYPE_CHANGE: - styleSheet = this->checkBox_logChange->styleSheet(); - if (this->checkBox_logChange->isChecked()) - isLogChecked = true; - break; - case LOGTYPE_BACKEND: - storedLevel = settings->value("advancedOptionsDialog/horizontalSlider_logBackendDepth", 0).toInt(); - if (storedLevel >= level){ - styleSheet = this->checkBox_logBackend->styleSheet(); - if (this->checkBox_logBackend->isChecked()) - isLogChecked = true; - } - break; - case LOGTYPE_TRACE: - storedLevel = settings->value("advancedOptionsDialog/horizontalSlider_logTraceDepth", 0).toInt(); - if (storedLevel >= level){ - styleSheet = this->checkBox_logTrace->styleSheet(); - if (this->checkBox_logTrace->isChecked()) - isLogChecked = true; - } - break; - default: - break; - } - if (isLogChecked) { - if (actionLogTimestampToFile->isChecked()){ - txtMsg = QString("%1\t%2").arg(QDateTime::currentDateTime().toString(Qt::DefaultLocaleShortDate /*QString("dd/MM/yyyy hh:mm:ss")*/)).arg(msg); - } - if (actionLogTimestampToPanel->isChecked()){ - htmlMsg = QString("%1\t%2").arg(QDateTime::currentDateTime().toString(Qt::DefaultLocaleShortDate /*QString("dd/MM/yyyy hh:mm:ss")*/)).arg(msg); - } - - if (logOption & LOGOPTION_BOLD){ - htmlMsg = QString("<b>%1</b>").arg(htmlMsg); - } - - QRegExp rx("(?:color: *)(\\w+)"); - QString colorName; - if (rx.indexIn(styleSheet) > -1) { - colorName = rx.cap(1); - } - if (!colorName.isEmpty()) - htmlMsg = QString("<font color=\"%1\">%2</font>").arg(colorName).arg(htmlMsg); - - if (fileLog && fileLog->isOpen()){ - QTextStream out(fileLog); - out << txtMsg << "\n"; - } - this->logPlainTextEdit->appendHtml(htmlMsg); - } + bool isLogChecked = false; + int storedLevel; + QString styleSheet; + QString txtMsg = msg; + QString htmlMsg = msg; + + switch (logType) { + case LOGTYPE_ERROR: + styleSheet = this->checkBox_logError->styleSheet(); + if (this->checkBox_logError->isChecked()) + isLogChecked = true; + break; + case LOGTYPE_ANALYSIS: + styleSheet = this->checkBox_logAnalysis->styleSheet(); + if (this->checkBox_logAnalysis->isChecked()) + isLogChecked = true; + break; + case LOGTYPE_CHANGE: + styleSheet = this->checkBox_logChange->styleSheet(); + if (this->checkBox_logChange->isChecked()) + isLogChecked = true; + break; + case LOGTYPE_BACKEND: + storedLevel = settings->value("advancedOptionsDialog/horizontalSlider_logBackendDepth", 0).toInt(); + if (storedLevel >= level){ + styleSheet = this->checkBox_logBackend->styleSheet(); + if (this->checkBox_logBackend->isChecked()) + isLogChecked = true; + } + break; + case LOGTYPE_TRACE: + storedLevel = settings->value("advancedOptionsDialog/horizontalSlider_logTraceDepth", 0).toInt(); + if (storedLevel >= level){ + styleSheet = this->checkBox_logTrace->styleSheet(); + if (this->checkBox_logTrace->isChecked()) + isLogChecked = true; + } + break; + default: + break; + } + if (isLogChecked) { + if (actionLogTimestampToFile->isChecked()){ + txtMsg = QString("%1\t%2").arg(QDateTime::currentDateTime().toString(Qt::ISODateWithMs)).arg(msg); + } + if (actionLogTimestampToPanel->isChecked()){ + htmlMsg = QString("%1\t%2").arg(QDateTime::currentDateTime().toString(Qt::ISODateWithMs)).arg(msg); + } + + if (logOption & LOGOPTION_BOLD){ + htmlMsg = QString("<b>%1</b>").arg(htmlMsg); + } + + QRegExp rx("(?:color: *)(\\w+)"); + QString colorName; + if (rx.indexIn(styleSheet) > -1) { + colorName = rx.cap(1); + } + if (!colorName.isEmpty()) + htmlMsg = QString("<font color=\"%1\">%2</font>").arg(colorName).arg(htmlMsg); + + if (fileLog && fileLog->isOpen()){ + QTextStream out(fileLog); + out << txtMsg << "\n"; + } + this->logPlainTextEdit->appendHtml(htmlMsg); + } } void MainWindow::updateModelRowByAnalysisTrack(QString fileName, int mp3Gain, double dBGain, double maxAmplitude, bool maxNoclipGain, bool isLog){ - QList<QStandardItem *> found = model->findItems(fileName, Qt::MatchExactly, 0); - if (found.count()==0) return; - QModelIndex modelIndex = model->item(found0->row())->index(); - updateModelRowByAnalysisTrack(modelIndex, mp3Gain, dBGain, maxAmplitude, maxNoclipGain, isLog); + QList<QStandardItem *> found = model->findItems(fileName, Qt::MatchExactly, 0); + if (found.count()==0) return; + QModelIndex modelIndex = model->item(found0->row())->index(); + updateModelRowByAnalysisTrack(modelIndex, mp3Gain, dBGain, maxAmplitude, maxNoclipGain, isLog); } void MainWindow::updateModelRowByAnalysisTrack(QModelIndex modelIndex, int mp3Gain, double dBGain, double maxAmplitude, bool maxNoclipGain, bool isLog){ - int row = modelIndex.row(); - double gainValue = mp3Gain*DB; // dBGain - QStandardItem *item = 0; - - if (!maxNoclipGain){ - setItem(row, "Volume", QVariant(doubleSpinBox_targetNormalValue->value()-dBGain)); - } - - setItem(row, "Max Amplitude", QVariant(maxAmplitude)); - bool clipping = maxAmplitude>32767.0; - setItem(row, "clipping", QVariant(clipping)); - - if (!maxNoclipGain){ - setItem(row, "Track Gain", QVariant(gainValue)); - setItem(row, "dBGain", QVariant(dBGain)); - - bool clippingTrack = maxAmplitude*pow(2.0, round(gainValue/DB)/4.0)>32767.0; - setItem(row, "clip(Track)", QVariant(clippingTrack)); - } - - int mp3GainNoClip = (int)floor((15.0-log10(maxAmplitude)/log10(2.0))*4.0); - setItem(row, "Max Noclip Gain", QVariant(mp3GainNoClip*DB)); - - // finally set line color to red if clipping is set - QStringList columns = QStringList() << "Path/File" << "Path" << "File"; - foreach (QString element, columns){ - QStandardItem *item = getItem(row, element); - item->setForeground(QBrush(QColor(0,0,0))); - } - item = getItem(row, "clipping"); - QStandardItem *item1 = getItem(row, "clip(Track)"); - if ((item && item->data().toBool()) || (item1 && item1->data().toBool())){ - if (item) item->setForeground(QBrush(QColor(255,0,0))); - if (item1) item1->setForeground(QBrush(QColor(255,0,0))); - foreach (QString element, columns){ - QStandardItem *item = getItem(row, element); - item->setForeground(QBrush(QColor(255,0,0))); - } - } - - if (isLog) { - QString trace; - trace += QString("%1\t").arg(getItemText(row, "Path/File")); - trace += QString("TrackdB: %1\t").arg(getItemValue(row, "dBGain").toString()); - trace += QString("MaxAmp: %1").arg(getItemValue(row, "Max Amplitude").toString()); - writeLog(trace, LOGTYPE_ANALYSIS); - } + int row = modelIndex.row(); + double gainValue = mp3Gain*DB; // dBGain + QStandardItem *item = 0; + + if (!maxNoclipGain){ + setItem(row, "Volume", QVariant(doubleSpinBox_targetNormalValue->value()-dBGain)); + } + + setItem(row, "Max Amplitude", QVariant(maxAmplitude)); + bool clipping = maxAmplitude>32767.0; + setItem(row, "clipping", QVariant(clipping)); + + if (!maxNoclipGain){ + setItem(row, "Track Gain", QVariant(gainValue)); + setItem(row, "dBGain", QVariant(dBGain)); + + bool clippingTrack = maxAmplitude*pow(2.0, round(gainValue/DB)/4.0)>32767.0; + setItem(row, "clip(Track)", QVariant(clippingTrack)); + } + + int mp3GainNoClip = (int)floor((15.0-log10(maxAmplitude)/log10(2.0))*4.0); + setItem(row, "Max Noclip Gain", QVariant(mp3GainNoClip*DB)); + + // finally set line color to red if clipping is set + QStringList columns = QStringList() << "Path/File" << "Path" << "File"; + foreach (QString element, columns){ + QStandardItem *item = getItem(row, element); + item->setForeground(QBrush(QColor(0,0,0))); + } + item = getItem(row, "clipping"); + QStandardItem *item1 = getItem(row, "clip(Track)"); + if ((item && item->data().toBool()) || (item1 && item1->data().toBool())){ + if (item) item->setForeground(QBrush(QColor(255,0,0))); + if (item1) item1->setForeground(QBrush(QColor(255,0,0))); + foreach (QString element, columns){ + QStandardItem *item = getItem(row, element); + item->setForeground(QBrush(QColor(255,0,0))); + } + } + + if (isLog) { + QString trace; + trace += QString("%1\t").arg(getItemText(row, "Path/File")); + trace += QString("TrackdB: %1\t").arg(getItemValue(row, "dBGain").toString()); + trace += QString("MaxAmp: %1").arg(getItemValue(row, "Max Amplitude").toString()); + writeLog(trace, LOGTYPE_ANALYSIS); + } } void MainWindow::updateModelRowsByAnalysisAlbum(bool isAlbum, QString fileName, int mp3Gain, double dBGain, /*double*/ QVariant maxAmplitude, bool isLog){ - QList<QStandardItem *> found = model->findItems(fileName, Qt::MatchExactly, 0); - if (found.count()==0) return; - QModelIndex modelIndex = model->item(found0->row())->index(); - updateModelRowsByAnalysisAlbum(isAlbum, QModelIndexList() << modelIndex, mp3Gain, dBGain, maxAmplitude, isLog); + QList<QStandardItem *> found = model->findItems(fileName, Qt::MatchExactly, 0); + if (found.count()==0) return; + QModelIndex modelIndex = model->item(found0->row())->index(); + updateModelRowsByAnalysisAlbum(isAlbum, QModelIndexList() << modelIndex, mp3Gain, dBGain, maxAmplitude, isLog); } void MainWindow::updateModelRowsByAnalysisAlbum(bool isAlbum, QModelIndexList indices, int mp3Gain, double dBGain, /*double*/ QVariant maxAmplitude, bool isLog){ - foreach(QModelIndex index, indices) { - int row = model->itemFromIndex(index)->row(); + foreach(QModelIndex index, indices) { + int row = model->itemFromIndex(index)->row(); + + if (isAlbum){ + setItem(row, "Album Volume", QVariant(doubleSpinBox_targetNormalValue->value()-dBGain)); + setItem(row, "Album Max Amplitude", maxAmplitude); + + double gainValue = mp3Gain*DB; // dBGain + setItem(row, "Album Gain", QVariant(gainValue)); + setItem(row, "Album dBGain", QVariant(dBGain)); + + // track's max amplitude must be checked, not the album's one + QStandardItem *item = getItem(row, "Max Amplitude"); + if (item){ + double trackMaxAmplitude = item->data().toDouble(); // get Max Amplitude value + bool clippingAlbum = trackMaxAmplitude*pow(2.0, round(gainValue/DB)/4.0)>32767.0; + setItem(row, "clip(Album)", QVariant(clippingAlbum)); + } + } + + // set line color to red if clipping is set + QStringList columns = QStringList() << "Path/File" << "Path" << "File"; + foreach (QString element, columns){ + QStandardItem *item = getItem(row, element); + item->setForeground(QBrush(QColor(0,0,0))); + } + QStandardItem *item = getItem(row, "clipping"); + QStandardItem *item1 = getItem(row, "clip(Track)"); + QStandardItem *item2 = getItem(row, "clip(Album)"); + if ((item && item->data().toBool()) || (item1 && item1->data().toBool()) || (item2 && item2->data().toBool())){ + if (item) item->setForeground(QBrush(QColor(255,0,0))); + if (item1) item1->setForeground(QBrush(QColor(255,0,0))); + if (item2) item2->setForeground(QBrush(QColor(255,0,0))); + foreach (QString element, columns){ + QStandardItem *item = getItem(row, element); + item->setForeground(QBrush(QColor(255,0,0))); + } + } - if (isAlbum){ - setItem(row, "Album Volume", QVariant(doubleSpinBox_targetNormalValue->value()-dBGain)); - setItem(row, "Album Max Amplitude", maxAmplitude); - - double gainValue = mp3Gain*DB; // dBGain - setItem(row, "Album Gain", QVariant(gainValue)); - setItem(row, "Album dBGain", QVariant(dBGain)); - - // track's max amplitude must be checked, not the album's one - QStandardItem *item = getItem(row, "Max Amplitude"); - double trackMaxAmplitude = item->data().toDouble(); // get Max Amplitude value - bool clippingAlbum = trackMaxAmplitude*pow(2.0, round(gainValue/DB)/4.0)>32767.0; - setItem(row, "clip(Album)", QVariant(clippingAlbum)); - } - - // set line color to red if clipping is set - QStringList columns = QStringList() << "Path/File" << "Path" << "File"; - foreach (QString element, columns){ - QStandardItem *item = getItem(row, element); - item->setForeground(QBrush(QColor(0,0,0))); - } - QStandardItem *item = getItem(row, "clipping"); - QStandardItem *item1 = getItem(row, "clip(Track)"); - QStandardItem *item2 = getItem(row, "clip(Album)"); - if ((item && item->data().toBool()) || (item1 && item1->data().toBool()) || (item2 && item2->data().toBool())){ - if (item) item->setForeground(QBrush(QColor(255,0,0))); - if (item1) item1->setForeground(QBrush(QColor(255,0,0))); - if (item2) item2->setForeground(QBrush(QColor(255,0,0))); - foreach (QString element, columns){ - QStandardItem *item = getItem(row, element); - item->setForeground(QBrush(QColor(255,0,0))); - } - } - - if (isLog) { - QString trace; - trace += QString("%1\t").arg(getItemText(row, "Path/File")); - trace += QString("AlbumdB: %1").arg(getItemValue(row, "Album dBGain").toString()); - //trace += QString("AlbumMaxAmp: %1").arg(getItemValue(row, "Album Max Amplitude").toString()); - writeLog(trace, LOGTYPE_ANALYSIS); - } - } + if (isLog) { + QString trace; + trace += QString("%1\t").arg(getItemText(row, "Path/File")); + trace += QString("AlbumdB: %1").arg(getItemValue(row, "Album dBGain").toString()); + //trace += QString("AlbumMaxAmp: %1").arg(getItemValue(row, "Album Max Amplitude").toString()); + writeLog(trace, LOGTYPE_ANALYSIS); + } + } } QModelIndexList MainWindow::getModelIndices(){ - QModelIndexList indices; - bool isFromContextMenu = sender() && sender()->property("calledFromContextMenu").toBool(); + QModelIndexList indices; + bool isFromContextMenu = sender() && sender()->property("calledFromContextMenu").toBool(); - if (isFromContextMenu || actionWork_on_Selected_files_only->isChecked()){ - QItemSelectionModel *selectionModel = tableView->selectionModel(); - indices = selectionModel->selectedRows(modelHeaderList.indexOf("Path/File")); - }else{ - for (int row=0; row<model->rowCount(); row++){ - indices << getItemIndex(row, "Path/File"); - } - } - return indices; + if (isFromContextMenu || actionWork_on_Selected_files_only->isChecked()){ + QItemSelectionModel *selectionModel = tableView->selectionModel(); + indices = selectionModel->selectedRows(modelHeaderList.indexOf("Path/File")); + }else{ + for (int row=0; row<model->rowCount(); row++){ + indices << getItemIndex(row, "Path/File"); + } + } + return indices; } +/** + * Process backend output line searching for possible errors + * + * @param input Output line from backend + * @return the found error if exists otherwise ERRTYPE_NONE + */ MainWindow::ErrType MainWindow::hasError(const QString & input) { - ErrType errType = ERRTYPE_NONE; - QString logMsg, popupMsg; + ErrType errType = ERRTYPE_NONE; + QString logMsg, popupMsg; - try { - QRegExp rx; + try { + QRegExp rx; + + if (input.startsWith("Note:")) { + throw(ERRTYPE_NONE); + } - if (input.contains("Error analyzing further samples (max time reached)")) { - logMsg = tr("Error analyzing further samples (max time reached)"); - popupMsg = logMsg; - throw(ERRTYPE_ANALYSING_MAX_TIME_REACHED); - } - - rx.setPattern("Cancelled processing of (.*)"); - if (rx.indexIn(input) != -1) { - QString fileName = rx.cap(1); - logMsg = tr("Cancelled processing of %1").arg(fileName); - popupMsg = logMsg; - throw(ERRTYPE_CANCELLED_PROCESSING); - } - - // QRegExp("Cancelled processing\.\n(.*) is probably corrupted now\." - if (input == "Cancelled processing.") { - throw(ERRTYPE_SUPPRESSED); - } - rx.setPattern("(.*) is probably corrupted now\\."); - if (rx.indexIn(input) != -1) { - QString fileName = rx.cap(1); - logMsg = tr("Cancelled processing.") + - " " + - tr("%1 is probably corrupted now.").arg(fileName); - popupMsg = logMsg; - throw(ERRTYPE_CANCELLED_PROCESSING_CORRUPT); - } - - rx.setPattern("(.*): Can't adjust single channel for mono or joint stereo"); - if (rx.indexIn(input) != -1) { - QString fileName = rx.cap(1); - logMsg = tr("%1 is not a stereo or dual-channel mp3").arg(fileName); - popupMsg = logMsg; - throw(ERRTYPE_CANNOT_ADJUST_SINGLE_CHANNEL); - } - - rx.setPattern("Can't find any valid MP3 frames in file (.*)"); - if (rx.indexIn(input) != -1) { - QString fileName = rx.cap(1); - logMsg = tr("Error while analyzing: %1").arg(tr("Can't find any valid MP3 frames in file %1").arg(fileName)); - popupMsg = logMsg; - throw(ERRTYPE_CANNOT_FIND_MP3_FRAME); - } - - rx.setPattern("Can't open (.*) for temp writing"); - if (rx.indexIn(input) != -1) { - QString fileName = rx.cap(1); - logMsg = tr("Can't open %1 for temp writing").arg(fileName); - popupMsg = logMsg; - throw(ERRTYPE_CANNOT_MAKE_TMP); - } - - rx.setPattern("Can't open (.*) for modifying"); - if (rx.indexIn(input) != -1) { - QString fileName = rx.cap(1); - logMsg = tr("Can't modify file %1").arg(fileName); - popupMsg = logMsg; - throw(ERRTYPE_CANNOT_MODIFY_FILE); - } - - rx.setPattern("Error analyzing (.*)\\. This mp3 has some very corrupt data\\."); - if (rx.indexIn(input) != -1) { - QString fileName = rx.cap(1); - logMsg = tr("Error analyzing %1.").arg(fileName) + - " " + - tr("This mp3 has some very corrupt data."); - popupMsg = logMsg; - throw(ERRTYPE_CORRUPT_MP3); - } - - rx.setPattern("(.*) is an MPEG Layer I file, not a layer III file"); - if (rx.indexIn(input) != -1) { - QString fileName = rx.cap(1); - logMsg = tr("%1 is an MPEG Layer I file, not a layer III file").arg(fileName); - popupMsg = logMsg; - throw(ERRTYPE_FILEFORMAT_NOTSUPPORTED); - } - - rx.setPattern("(.*) is an MPEG Layer II file, not a layer III file"); - if (rx.indexIn(input) != -1) { - QString fileName = rx.cap(1); - logMsg = tr("%1 is an MPEG Layer II file, not a layer III file").arg(fileName); - popupMsg = logMsg; - throw(ERRTYPE_FILEFORMAT_NOTSUPPORTED); - } - - rx.setPattern("(.*) is free format (not currently supported)"); - if (rx.indexIn(input) != -1) { - QString fileName = rx.cap(1); - logMsg = tr("%1 is free format (not currently supported)").arg(fileName); - popupMsg = logMsg; - throw(ERRTYPE_FILEFORMAT_NOTSUPPORTED); - } - - //QRegExp("Problem re-naming (.*) to (.*)\nThe mp3 was correctly modified, but you will need to re-name (.*) to (.*) yourself\."); - rx.setPattern("Problem re-naming (.*) to (.*)"); - if (rx.indexIn(input) != -1) { - QString outFileName = rx.cap(1); - QString fileName = rx.cap(2); - logMsg = tr("Problem re-naming %1 to %2.").arg(outFileName).arg(fileName) + - " " + - tr("The mp3 was correctly modified, but you will need to re-name it yourself."); - popupMsg = logMsg; - throw(ERRTYPE_RENAME_TMP); - } - rx.setPattern("The mp3 was correctly modified, but you will need to re-name (.*) to (.*) yourself\\."); - if (rx.indexIn(input) != -1) { - //QString outFileName = rx.cap(1); - //QString fileName = rx.cap(2); - throw(ERRTYPE_SUPPRESSED); - } - - //QRegExp("Not enough temp space on disk to modify (.*)\nEither free some space, or do not use \"temp file\" option"); - rx.setPattern("Not enough temp space on disk to modify (.*)"); - if (rx.indexIn(input) != -1) { - QString fileName = rx.cap(1); - logMsg = tr("Not enough temp space on disk to modify %1.").arg(fileName) + - " " + - tr("Either clear space on disk, or go to \"Options->Advanced...\" and check the \"Do not use Temp files\" box."); - popupMsg = logMsg; - throw(ERRTYPE_NOT_ENOUGH_TEMP_SPACE); - } - if (input == "Either free some space, or do not use \"temp file\" option") { - throw(ERRTYPE_SUPPRESSED); - } - } - catch (ErrType e){ - errType = e; - - if (errType!=ERRTYPE_NONE && errType!=ERRTYPE_SUPPRESSED){ - if (!logMsg.isEmpty()){ - if (logDockWidget->isVisible() && actionLogError->isChecked()){ - // popupMsg omitted, error is only displayed in opened log panel - popupMsg = QString(); - } - else{ - if (!actionLogOpenAutomaticallyPanel->isChecked()){ - bool isConfirmSuppressed = (!isOpenLogPanelQuestionSuppressed.isNull() && isOpenLogPanelQuestionSuppressed.toBool()) - || (settings->contains("openLogPanelForErrorAnswer")); - int r = QMessageBox::NoButton; - if (isConfirmSuppressed){ - if (settings->contains("openLogPanelForErrorAnswer")){ - r = settings->value("openLogPanelForErrorAnswer").toBool() ? QMessageBox::Yes : QMessageBox::No; - } - } - else{ - r = MyMessageBox::question(this, appTitle+" - "+tr("Open Log Panel?"), - tr("Would you like to display the errors in an opening log panel instead of seeing pop-up messages?"), - tr("Don't ask me again"), - isConfirmSuppressed, - QMessageBox::Yes | QMessageBox::No, - QMessageBox::Yes); - operationTime.restart(); - if (isConfirmSuppressed){ - settings->setValue("openLogPanelForErrorAnswer", r==QMessageBox::Yes); - } - isOpenLogPanelQuestionSuppressed = true; - } - if (r == QMessageBox::Yes) - actionLogOpenAutomaticallyPanel->setChecked(true); - } - if (actionLogOpenAutomaticallyPanel->isChecked()){ - // open log panel and set error log checbox, popupMsg can be omitted - if (!logDockWidget->isVisible()) - logDockWidget->setVisible(true); - if (!actionLogError->isChecked()) - actionLogError->setChecked(true); - popupMsg = QString(); - } - - } - } - - if (!logMsg.isEmpty()) - writeLog(logMsg, LOGTYPE_ERROR); - - if (!popupMsg.isEmpty()){ - bool isConfirmSuppressed = !isPopupErrorSuppressed.isNull() && isPopupErrorSuppressed.toBool(); - if (!isConfirmSuppressed) { - MyMessageBox::critical(this, appTitle+" - "+tr("Error"), - popupMsg, - tr("Don't bother me again with error messages"), - isConfirmSuppressed, - QMessageBox::Close); - operationTime.restart(); - if (isConfirmSuppressed){ - isPopupErrorSuppressed = QVariant(true); - } - } - } - } - } + if (input.contains("Error analyzing further samples (max time reached)")) { + logMsg = tr("Error analyzing further samples (max time reached)"); + popupMsg = logMsg; + throw(ERRTYPE_ANALYSING_MAX_TIME_REACHED); + } - return errType; + rx.setPattern("Cancelled processing of (.*)"); + if (rx.indexIn(input) != -1) { + QString fileName = rx.cap(1); + logMsg = tr("Cancelled processing of %1").arg(fileName); + popupMsg = logMsg; + throw(ERRTYPE_CANCELLED_PROCESSING); + } + + // QRegExp("Cancelled processing\.\n(.*) is probably corrupted now\." + if (input == "Cancelled processing.") { + throw(ERRTYPE_SUPPRESSED); + } + rx.setPattern("(.*) is probably corrupted now\\."); + if (rx.indexIn(input) != -1) { + QString fileName = rx.cap(1); + logMsg = tr("Cancelled processing.") + + " " + + tr("%1 is probably corrupted now.").arg(fileName); + popupMsg = logMsg; + throw(ERRTYPE_CANCELLED_PROCESSING_CORRUPT); + } + + rx.setPattern("(.*): Can't adjust single channel for mono or joint stereo"); + if (rx.indexIn(input) != -1) { + QString fileName = rx.cap(1); + logMsg = tr("%1 is not a stereo or dual-channel mp3").arg(fileName); + popupMsg = logMsg; + throw(ERRTYPE_CANNOT_ADJUST_SINGLE_CHANNEL); + } + + rx.setPattern("Can't find any valid MP3 frames in file (.*)"); + if (rx.indexIn(input) != -1) { + QString fileName = rx.cap(1); + logMsg = tr("Error while analyzing: %1").arg(tr("Can't find any valid MP3 frames in file %1").arg(fileName)); + popupMsg = logMsg; + throw(ERRTYPE_CANNOT_FIND_MP3_FRAME); + } + + rx.setPattern("Can't open (.*) for temp writing"); + if (rx.indexIn(input) != -1) { + QString fileName = rx.cap(1); + logMsg = tr("Can't open %1 for temp writing").arg(fileName); + popupMsg = logMsg; + throw(ERRTYPE_CANNOT_MAKE_TMP); + } + + rx.setPattern("Can't open (.*) for modifying"); + if (rx.indexIn(input) != -1) { + QString fileName = rx.cap(1); + logMsg = tr("Can't modify file %1").arg(fileName); + popupMsg = logMsg; + throw(ERRTYPE_CANNOT_MODIFY_FILE); + } + + rx.setPattern("Error analyzing (.*)\\. This mp3 has some very corrupt data\\."); + if (rx.indexIn(input) != -1) { + QString fileName = rx.cap(1); + logMsg = tr("Error analyzing %1.").arg(fileName) + + " " + + tr("This mp3 has some very corrupt data."); + popupMsg = logMsg; + throw(ERRTYPE_CORRUPT_MP3); + } + + rx.setPattern("(.*) is an MPEG Layer I file, not a layer III file"); + if (rx.indexIn(input) != -1) { + QString fileName = rx.cap(1); + logMsg = tr("%1 is an MPEG Layer I file, not a layer III file").arg(fileName); + popupMsg = logMsg; + throw(ERRTYPE_FILEFORMAT_NOTSUPPORTED); + } + + rx.setPattern("(.*) is an MPEG Layer II file, not a layer III file"); + if (rx.indexIn(input) != -1) { + QString fileName = rx.cap(1); + logMsg = tr("%1 is an MPEG Layer II file, not a layer III file").arg(fileName); + popupMsg = logMsg; + throw(ERRTYPE_FILEFORMAT_NOTSUPPORTED); + } + + rx.setPattern("(.*) is free format (not currently supported)"); + if (rx.indexIn(input) != -1) { + QString fileName = rx.cap(1); + logMsg = tr("%1 is free format (not currently supported)").arg(fileName); + popupMsg = logMsg; + throw(ERRTYPE_FILEFORMAT_NOTSUPPORTED); + } + + //QRegExp("Problem re-naming (.*) to (.*)\nThe mp3 was correctly modified, but you will need to re-name (.*) to (.*) yourself\."); + rx.setPattern("Problem re-naming (.*) to (.*)"); + if (rx.indexIn(input) != -1) { + QString outFileName = rx.cap(1); + QString fileName = rx.cap(2); + logMsg = tr("Problem re-naming %1 to %2.").arg(outFileName).arg(fileName) + + " " + + tr("The mp3 was correctly modified, but you will need to re-name it yourself."); + popupMsg = logMsg; + throw(ERRTYPE_RENAME_TMP); + } + rx.setPattern("The mp3 was correctly modified, but you will need to re-name (.*) to (.*) yourself\\."); + if (rx.indexIn(input) != -1) { + //QString outFileName = rx.cap(1); + //QString fileName = rx.cap(2); + throw(ERRTYPE_SUPPRESSED); + } + + //QRegExp("Not enough temp space on disk to modify (.*)\nEither free some space, or do not use \"temp file\" option"); + rx.setPattern("Not enough temp space on disk to modify (.*)"); + if (rx.indexIn(input) != -1) { + QString fileName = rx.cap(1); + logMsg = tr("Not enough temp space on disk to modify %1.").arg(fileName) + + " " + + tr("Either clear space on disk, or go to \"Options->Advanced...\" and check the \"Do not use Temp files\" box."); + popupMsg = logMsg; + throw(ERRTYPE_NOT_ENOUGH_TEMP_SPACE); + } + if (input == "Either free some space, or do not use \"temp file\" option") { + throw(ERRTYPE_SUPPRESSED); + } + + rx.setPattern("Failed to decode MPEG frame: Error reading the stream. \\(code (\\d+)\\)"); + if (rx.indexIn(input) != -1) { + QString code = rx.cap(1); + logMsg = tr("Failed to decode MPEG frame: Error reading the stream. (code %1)").arg(code); + popupMsg = logMsg; + throw(ERRTYPE_CANNOT_DECODE_FRAME); + } + } + catch (ErrType e){ + errType = e; + + if (errType!=ERRTYPE_NONE && errType!=ERRTYPE_SUPPRESSED){ + if (!logMsg.isEmpty()){ + if (logDockWidget->isVisible() && actionLogError->isChecked()){ + // popupMsg omitted, error is only displayed in opened log panel + popupMsg = QString(); + } + else{ + if (!actionLogOpenAutomaticallyPanel->isChecked()){ + bool isConfirmSuppressed = (!isOpenLogPanelQuestionSuppressed.isNull() && isOpenLogPanelQuestionSuppressed.toBool()) + || (settings->contains("openLogPanelForErrorAnswer")); + int r = QMessageBox::NoButton; + if (isConfirmSuppressed){ + if (settings->contains("openLogPanelForErrorAnswer")){ + r = settings->value("openLogPanelForErrorAnswer").toBool() ? QMessageBox::Yes : QMessageBox::No; + } + } + else{ + r = MyMessageBox::question(this, appTitle+" - "+tr("Open Log Panel?"), + tr("Would you like to display the errors in an opening log panel instead of seeing pop-up messages?"), + tr("Don't ask me again"), + isConfirmSuppressed, + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes); + elapsedTimer.restart(); + if (isConfirmSuppressed){ + settings->setValue("openLogPanelForErrorAnswer", r==QMessageBox::Yes); + } + isOpenLogPanelQuestionSuppressed = true; + } + if (r == QMessageBox::Yes) + actionLogOpenAutomaticallyPanel->setChecked(true); + } + if (actionLogOpenAutomaticallyPanel->isChecked()){ + // open log panel and set error log checbox, popupMsg can be omitted + if (!logDockWidget->isVisible()) + logDockWidget->setVisible(true); + if (!actionLogError->isChecked()) + actionLogError->setChecked(true); + popupMsg = QString(); + } + + } + } + + if (!logMsg.isEmpty()) + writeLog(logMsg, LOGTYPE_ERROR); + + if (!popupMsg.isEmpty()){ + bool isConfirmSuppressed = !isPopupErrorSuppressed.isNull() && isPopupErrorSuppressed.toBool(); + if (!isConfirmSuppressed) { + MyMessageBox::critical(this, appTitle+" - "+tr("Error"), + popupMsg, + tr("Don't bother me again with error messages"), + isConfirmSuppressed, + QMessageBox::Close); + elapsedTimer.restart(); + if (isConfirmSuppressed){ + isPopupErrorSuppressed = QVariant(true); + } + } + } + } + } + + return errType; } int MainWindow::runAnalysis(QModelIndexList indices, bool isAlbum, bool isMaxNoclip, bool isOnlyWithStoredTagInfo, double passSlice){ - QProcess process; - double startProgress = progressBar_Total->doubleValue(); + QProcess process; + double startProgress = progressBar_Total->doubleValue(); + + try { + if (startProgress==0.0 && passSlice==100.0) disableGUI(); + if (indices.isEmpty()) throw(0); + + int total_index = 0; + + QStringList argOptions; + + if (isOnlyWithStoredTagInfo){ + // -s c - only check stored tag info (no other processing) + argOptions << "-s" << "c"; + } + if (!isAlbum){ + // -e - make analysis without album stuff + argOptions << "-e"; + } + argOptions << getArgumentsByOptions(); + + QMultiHash<QString, QModelIndex> indexByPath; + + if (isAlbum){ + // in album mode a process can start only the files belong to their parent path + // irreversed order is used in iterator trying to keep later the original order + //foreach(QModelIndex index, indices) { + QListIterator<QModelIndex> indicesIterator(indices); + indicesIterator.toBack(); + while (indicesIterator.hasPrevious()){ + QModelIndex index = indicesIterator.previous(); + int row = model->itemFromIndex(index)->row(); + QString pathName = getItemText(row, "Path"); + indexByPath.insert(pathName, index); + } + } + else{ + indexByPath.insert("dummyPath", QModelIndex()); + } + + foreach(QString pathName, indexByPath.uniqueKeys()){ + QModelIndexList indicesByProcess = isAlbum ? indexByPath.values(pathName) : indices; + QStringList argFiles; + + foreach(QModelIndex index, indicesByProcess) { + int row = model->itemFromIndex(index)->row(); + QString fileName = getItemText(row, "Path/File"); + argFiles << fileName; + } + + QStringList args = QStringList() << argOptions << argFiles; + process.setProcessChannelMode(QProcess::MergedChannels); + QString trace = QString("%1 %2").arg(this->getBackEnd()).arg(args.join(" ")); + writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); + + process.start(this->getBackEnd(), args); + + if (!process.waitForStarted()){ + showNoBackEndVersion(); + throw(1); + } + + /* + expected analysis output is a tab separated table, last row contains album info in album mode + >mp3gain -o "D:/Users/Brazso/music/test_mp3/Wes - Midiwa boi.mp3" + File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain + 3% 2562925 bytes analyzed\r (only if not analysis tag info is stored) + 6% 2562925 bytes analyzed\r (only if not analysis tag info is stored) + 9% 2562925 bytes analyzed\r (only if not analysis tag info is stored) + 13% 2562925 bytes analyzed\r (only if not analysis tag info is stored) + ... + 94% 2562925 bytes analyzed\r (only if not analysis tag info is stored) + 97% 2562925 bytes analyzed\r (only if not analysis tag info is stored) + D:/Users/Brazso/music/test_mp3/Wes - Midiwa boi.mp3 0 0.500000 18759.831058 188 111 + "Album" 0 0.500000 18759.831058 188 111 (only in album mode) + */ + + enum resultColumns { File, MP3_gain, dB_gain, Max_Amplitude, Max_global_gain, Min_global_gain, enumMax }; + enum resultColumnsEx { Album_MP3_gain = enumMax, Album_dB_gain, Album_Max_Amplitude, Album_Max_global_gain, Album_Min_global_gain, enumMaxEx }; + + for (bool isAfterLast = false, isWaitForReadyRead = false; + (isWaitForReadyRead = process.waitForReadyRead(-1)) || !isAfterLast; + isAfterLast = !isWaitForReadyRead ) { + + QByteArray newData = process.readAll(); + QString result = QString::fromLocal8Bit(newData); + + QTextStream in(&result); + do { + Line line; + line.content = in.readLine(); + if (line.content.isNull() || line.content.isEmpty()) + continue; + + QStringList lines = line.content.split(QChar('\r'), Qt::SkipEmptyParts); + foreach (line.content, lines){ + if (line.content.trimmed().isEmpty()){ + continue; + } + + writeLog(line.content, LOGTYPE_BACKEND, line.content.endsWith("bytes analyzed") ? 2 : 1); + bool isNextIndex = false; + line.errType = hasError(line.content); + + if (line.errType){ + line.type = LINETYPE_ERROR; + if (line.errType!=ERRTYPE_SUPPRESSED){ + isNextIndex = true; // for the time being all errors increase the iterator + } + } + else if (line.content.endsWith("bytes analyzed")){ // optional + line.type = LINETYPE_ANALYSIS; + // single track: " 23% of 2650308 bytes analyzed" + // more tracks: "1/2 7% of 2650308 bytes analyzed" + int percent = 0; + int actFileNumber = 1; + QRegExp rx("(?:^)(?:\\(\\d+)(?:/)(\\d+)(?:\\))?(?: *)(\\d+)(?:% of )(\\d+)(?: bytes analyzed$)"); + int pos = rx.indexIn(line.content); + if (pos > -1) { + actFileNumber = rx.cap(1).isEmpty() ? 1 : rx.cap(1).toInt(); + //int totalFileNumber = rx.cap(2).isEmpty() ? 1 : rx.cap(2).toInt(); + percent = rx.cap(3).toInt(); + //long fileSize = rx.cap(4).toLong(); + } + if (percent>100) percent=100; // some bug from the back end + setProgress(QVariant(percent), + QVariant(startProgress+passSlice*((total_index+percent/100.0)/indices.size()))); + updateStatusBar(QString("Analyzing %1").arg(argFiles.at(actFileNumber-1))); + } + else { + QStringList tokens = line.content.split(QChar('\t')); + + bool isIgnore = true; + if (tokens.size()!=(!isOnlyWithStoredTagInfo ? (int)enumMax : (int)enumMaxEx)) + ; + else if (tokensFile=="File") + line.type = LINETYPE_FILE_HEADER; + else + isIgnore = false; + + if (!isIgnore){ + double mp3Gain = 0, dbGain = 0, maxAmplitude = 0; + bool isConvertOk = true; + if (isConvertOk) + mp3Gain = tokensMP3_gain.toInt(&isConvertOk); + if (isConvertOk) + dbGain = tokensdB_gain.toDouble(&isConvertOk); + if (isConvertOk) + maxAmplitude = tokensMax_Amplitude.toDouble(&isConvertOk); + if (!isConvertOk) { + if (isOnlyWithStoredTagInfo){ + // we may get NA values here in the tokens + line.type = LINETYPE_ERROR; + line.errType=ERRTYPE_SUPPRESSED; + } + else{ + line.type = LINETYPE_ERROR; + line.errType=ERRTYPE_CANNOT_FIND_MP3_FRAME; + QString msg = QString("%1 %2").arg(tr("Error while analyzing in file")).arg(tokensFile); + writeLog(msg, LOGTYPE_ERROR); + } + }else{ + updateStatusBar(QString("Analyzing %1").arg(tokensFile)); + } + + if (!isOnlyWithStoredTagInfo && tokensFile=="\"Album\""){ // contains album info + line.type = LINETYPE_FILE_ALBUM; + if (!line.errType) + updateModelRowsByAnalysisAlbum(isAlbum, indicesByProcess, mp3Gain, dbGain, QVariant(maxAmplitude), /*isLog =*/ true); + }else{ + if (!line.errType) { + if (isOnlyWithStoredTagInfo){ + double dbGainDiff = doubleSpinBox_targetNormalValue->value()-defaultNormalTargetValue; + dbGain += dbGainDiff; + mp3Gain = (int)round(dbGain/DB); + } + updateModelRowByAnalysisTrack(tokensFile, mp3Gain, dbGain, maxAmplitude, isMaxNoclip, + /*isLog =*/ !isOnlyWithStoredTagInfo); + if (isOnlyWithStoredTagInfo){ + bool hasAlbumInfo = true; + int albumMp3Gain(tokensAlbum_MP3_gain.toInt(&isConvertOk)); + hasAlbumInfo &= isConvertOk; + double albumDbGain = tokensAlbum_dB_gain.toDouble(&isConvertOk); + hasAlbumInfo &= isConvertOk; + double albumMaxAmplitude = tokensAlbum_Max_Amplitude.toDouble(&isConvertOk); + hasAlbumInfo &= isConvertOk; + if (hasAlbumInfo){ + QList<QStandardItem *> found = model->findItems(tokensFile, Qt::MatchExactly, 0); + if (found.count()>0) { + QModelIndex index = model->indexFromItem(found.at(0)); + updateModelRowsByAnalysisAlbum(isAlbum, QModelIndexList() << index, albumMp3Gain, albumDbGain, QVariant(albumMaxAmplitude)); + } + } + } + } + isNextIndex = true; + } + } + } + + if (isNextIndex){ + total_index++; + setProgress(QVariant(0), + QVariant(startProgress+passSlice*(((double)total_index)/indices.size()))); + } + + qApp->processEvents(QEventLoop::AllEvents); + if (isCancelled) throw(-1); + } + } while (!in.atEnd()); + } + } - try { - if (startProgress==0.0 && passSlice==100.0) disableGUI(); - if (indices.isEmpty()) throw(0); - - int total_index = 0; - - QStringList argOptions; - - if (isOnlyWithStoredTagInfo){ - // -s c - only check stored tag info (no other processing) - argOptions << "-s" << "c"; - } - if (!isAlbum){ - // -e - make analysis without album stuff - argOptions << "-e"; - } - argOptions << getArgumentsByOptions(); - - QMultiHash<QString, QModelIndex> indexByPath; - - if (isAlbum){ - // in album mode a process can start only the files belong to their parent path - // irreversed order is used in iterator trying to keep later the original order - //foreach(QModelIndex index, indices) { - QListIterator<QModelIndex> indicesIterator(indices); - indicesIterator.toBack(); - while (indicesIterator.hasPrevious()){ - QModelIndex index = indicesIterator.previous(); - int row = model->itemFromIndex(index)->row(); - QString pathName = getItemText(row, "Path"); - indexByPath.insert(pathName, index); - } - } - else{ - indexByPath.insert("dummyPath", QModelIndex()); - } - - foreach(QString pathName, indexByPath.uniqueKeys()){ - QModelIndexList indicesByProcess = isAlbum ? indexByPath.values(pathName) : indices; - QStringList argFiles; - - foreach(QModelIndex index, indicesByProcess) { - int row = model->itemFromIndex(index)->row(); - QString fileName = getItemText(row, "Path/File"); - argFiles << fileName; - } - - QStringList args = QStringList() << argOptions << argFiles; - process.setProcessChannelMode(QProcess::MergedChannels); - QString trace = QString("%1 %2").arg(this->getBackEnd()).arg(args.join(" ")); - writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); - - process.start(this->getBackEnd(), args); - - if (!process.waitForStarted()){ - showNoBackEndVersion(); - throw(1); - } - - /* - expected analysis output is a tab separated table, last row contains album info in album mode - >mp3gain -o "D:/Users/Brazso/music/test_mp3/Wes - Midiwa boi.mp3" - File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain - 3% 2562925 bytes analyzed\r (only if not analysis tag info is stored) - 6% 2562925 bytes analyzed\r (only if not analysis tag info is stored) - 9% 2562925 bytes analyzed\r (only if not analysis tag info is stored) - 13% 2562925 bytes analyzed\r (only if not analysis tag info is stored) - ... - 94% 2562925 bytes analyzed\r (only if not analysis tag info is stored) - 97% 2562925 bytes analyzed\r (only if not analysis tag info is stored) - D:/Users/Brazso/music/test_mp3/Wes - Midiwa boi.mp3 0 0.500000 18759.831058 188 111 - "Album" 0 0.500000 18759.831058 188 111 (only in album mode) - */ - - enum resultColumns { File, MP3_gain, dB_gain, Max_Amplitude, Max_global_gain, Min_global_gain, enumMax }; - enum resultColumnsEx { Album_MP3_gain = enumMax, Album_dB_gain, Album_Max_Amplitude, Album_Max_global_gain, Album_Min_global_gain, enumMaxEx }; - - for (bool isAfterLast = false, isWaitForReadyRead = false; - (isWaitForReadyRead = process.waitForReadyRead(-1)) || !isAfterLast; - isAfterLast = !isWaitForReadyRead ) { - - QByteArray newData = process.readAll(); - QString result = QString::fromLocal8Bit(newData); - - QTextStream in(&result); - do { - Line line; - line.content = in.readLine(); - if (line.content==QString::null || line.content.isEmpty()) - continue; - - QStringList lines = line.content.split(QChar('\r'), QString::SkipEmptyParts); - foreach (line.content, lines){ - if (line.content.trimmed().isEmpty()){ - continue; - } - - writeLog(line.content, LOGTYPE_BACKEND, line.content.endsWith("bytes analyzed") ? 2 : 1); - bool isNextIndex = false; - line.errType = hasError(line.content); - - if (line.errType){ - line.type = LINETYPE_ERROR; - if (line.errType!=ERRTYPE_SUPPRESSED){ - isNextIndex = true; // for the time being all errors increase the iterator - } - } - else if (line.content.endsWith("bytes analyzed")){ // optional - line.type = LINETYPE_ANALYSIS; - // single track: " 23% of 2650308 bytes analyzed" - // more tracks: "1/2 7% of 2650308 bytes analyzed" - int percent = 0; - int actFileNumber = 1; - QRegExp rx("(?:^)(?:\\(\\d+)(?:/)(\\d+)(?:\\))?(?: *)(\\d+)(?:% of )(\\d+)(?: bytes analyzed$)"); - int pos = rx.indexIn(line.content); - if (pos > -1) { - actFileNumber = rx.cap(1).isEmpty() ? 1 : rx.cap(1).toInt(); - //int totalFileNumber = rx.cap(2).isEmpty() ? 1 : rx.cap(2).toInt(); - percent = rx.cap(3).toInt(); - //long fileSize = rx.cap(4).toLong(); - } - if (percent>100) percent=100; // some bug from the back end - setProgress(QVariant(percent), - QVariant(startProgress+passSlice*((total_index+percent/100.0)/indices.size()))); - updateStatusBar(QString("Analyzing %1").arg(argFiles.at(actFileNumber-1))); - } - else { - QStringList tokens = line.content.split(QChar('\t')); - - bool isIgnore = true; - if (tokens.size()!=(!isOnlyWithStoredTagInfo ? (int)enumMax : (int)enumMaxEx)) - ; - else if (tokensFile=="File") - line.type = LINETYPE_FILE_HEADER; - else - isIgnore = false; - - if (!isIgnore){ - double mp3Gain = 0, dbGain = 0, maxAmplitude = 0; - bool isConvertOk = true; - if (isConvertOk) - mp3Gain = tokensMP3_gain.toInt(&isConvertOk); - if (isConvertOk) - dbGain = tokensdB_gain.toDouble(&isConvertOk); - if (isConvertOk) - maxAmplitude = tokensMax_Amplitude.toDouble(&isConvertOk); - if (!isConvertOk) { - if (isOnlyWithStoredTagInfo){ - // we may get NA values here in the tokens - line.type = LINETYPE_ERROR; - line.errType=ERRTYPE_SUPPRESSED; - } - else{ - line.type = LINETYPE_ERROR; - line.errType=ERRTYPE_CANNOT_FIND_MP3_FRAME; - QString msg = QString("%1 %2").arg(tr("Error while analyzing in file")).arg(tokensFile); - writeLog(msg, LOGTYPE_ERROR); - } - }else{ - updateStatusBar(QString("Analyzing %1").arg(tokensFile)); - } - - if (!isOnlyWithStoredTagInfo && tokensFile=="\"Album\""){ // contains album info - line.type = LINETYPE_FILE_ALBUM; - if (!line.errType) - updateModelRowsByAnalysisAlbum(isAlbum, indicesByProcess, mp3Gain, dbGain, QVariant(maxAmplitude), /*isLog =*/ true); - }else{ - if (!line.errType) { - if (isOnlyWithStoredTagInfo){ - double dbGainDiff = doubleSpinBox_targetNormalValue->value()-defaultNormalTargetValue; - dbGain += dbGainDiff; - mp3Gain = (int)round(dbGain/DB); - } - updateModelRowByAnalysisTrack(tokensFile, mp3Gain, dbGain, maxAmplitude, isMaxNoclip, - /*isLog =*/ !isOnlyWithStoredTagInfo); - if (isOnlyWithStoredTagInfo){ - bool hasAlbumInfo = true; - int albumMp3Gain(tokensAlbum_MP3_gain.toInt(&isConvertOk)); - hasAlbumInfo &= isConvertOk; - double albumDbGain = tokensAlbum_dB_gain.toDouble(&isConvertOk); - hasAlbumInfo &= isConvertOk; - double albumMaxAmplitude = tokensAlbum_Max_Amplitude.toDouble(&isConvertOk); - hasAlbumInfo &= isConvertOk; - if (hasAlbumInfo){ - QList<QStandardItem *> found = model->findItems(tokensFile, Qt::MatchExactly, 0); - if (found.count()>0) { - QModelIndex index = model->indexFromItem(found.at(0)); - updateModelRowsByAnalysisAlbum(isAlbum, QModelIndexList() << index, albumMp3Gain, albumDbGain, QVariant(albumMaxAmplitude)); - } - } - } - } - isNextIndex = true; - } - } - } - - if (isNextIndex){ - total_index++; - setProgress(QVariant(0), - QVariant(startProgress+passSlice*(((double)total_index)/indices.size()))); - } - - qApp->processEvents(QEventLoop::AllEvents); - if (isCancelled) throw(-1); - } - } while (!in.atEnd()); - } - } - - throw(0); - } - catch (int e){ - if (process.state()==QProcess::Starting || process.state()==QProcess::Running){ - process.kill(); - } - setProgress(QVariant(0), QVariant()); - if (startProgress==0.0 && passSlice==100.0){ - enableGUI(); - } - return e; - } - return 0; + throw(0); + } + catch (int e){ + if (process.state()==QProcess::Starting || process.state()==QProcess::Running){ + process.kill(); + } + setProgress(QVariant(0), QVariant()); + if (startProgress==0.0 && passSlice==100.0){ + enableGUI(); + } + return e; + } + return 0; } // refresh track fields of a tableView row by mp3Gain track change void MainWindow::updateModelRowByMP3GainTrack(QString fileName, int mp3Gain, bool isAlbumErase){ - double dBGain = mp3Gain*DB; - double gainValue = isAlbumErase ? dBGain : 0.0; - QList<QStandardItem *> found = model->findItems(fileName, Qt::MatchExactly, 0); - if (found.count()==0) return; - int row = found.at(0)->row(); - QStandardItem *item = 0; - - item = getItem(row, "Volume"); - if (item && !item->data().isNull()) - setItem(row, "Volume", QVariant(item->data().toDouble()+gainValue)); - - QVariant newMaxAmplitude = QVariant(); // double - item = getItem(row, "Max Amplitude"); - if (item && !item->data().isNull()){ - double maxAmplitude = item->data().toDouble(); - newMaxAmplitude = QVariant(maxAmplitude*pow(2.0, round(gainValue/DB)/4.0)); - setItem(row, "Max Amplitude", newMaxAmplitude); - } - - // depends on "Max Amplitude" field - if (!newMaxAmplitude.isNull()){ - item = getItem(row, "clipping"); - if (item && !item->data().isNull()){ - bool clipping = newMaxAmplitude.toDouble()>32767.0; - setItem(row, "clipping", QVariant(clipping)); - } - } - - QVariant newGainValue = QVariant(); // double - item = getItem(row, "Track Gain"); - if (item && !item->data().isNull()){ - newGainValue = QVariant(item->data().toDouble()-dBGain); - setItem(row, "Track Gain", newGainValue); - } - - item = getItem(row, "dBGain"); - if (item && !item->data().isNull()){ - double newdBGain = item->data().toDouble()-dBGain; - setItem(row, "dBGain", QVariant(newdBGain)); - } - - // depends on "Max Amplitude" and "Track Gain" fields - if (!newMaxAmplitude.isNull() && !newGainValue.isNull()){ - item = getItem(row, "clip(Track)"); - if (item && !item->data().isNull()){ - bool clippingTrack = newMaxAmplitude.toDouble()*pow(2.0, round(newGainValue.toDouble()/DB)/4.0)>32767.0; - setItem(row, "clip(Track)", QVariant(clippingTrack)); - } - } - - // depends on "Max Amplitude" field - if (!newMaxAmplitude.isNull()){ - item = getItem(row, "Max Noclip Gain"); - if (item && !item->data().isNull()){ - int mp3GainNoClip = (int)floor((15.0-log10(newMaxAmplitude.toDouble())/log10(2.0))*4.0); - setItem(row, "Max Noclip Gain", QVariant(mp3GainNoClip*DB)); - } - } - - if (isAlbumErase){ - // Album fields cannot be recalculated, so they must be deleted - QStringList columns = QStringList() << "Album Volume" << "Album Max Amplitude" - << "Album Gain" << "Album dBGain" << "clip(Album)"; - foreach (QString element, columns){ - item = getItem(row, element); - if (item){ - item->setData(0); // before item delete to enable automatic model/view refresh - delete item; - } - } - } - - // finally set line color to red if clipping is set - QStringList columns = QStringList() << "Path/File" << "Path" << "File"; - foreach (QString element, columns){ - QStandardItem *item = getItem(row, element); - item->setForeground(QBrush(QColor(0,0,0))); - } - item = getItem(row, "clipping"); - QStandardItem *item1 = getItem(row, "clip(Track)"); - if ((item && item->data().toBool()) || (item1 && item1->data().toBool())){ - if (item) item->setForeground(QBrush(QColor(255,0,0))); - if (item1) item1->setForeground(QBrush(QColor(255,0,0))); - foreach (QString element, columns){ - QStandardItem *item = getItem(row, element); - item->setForeground(QBrush(QColor(255,0,0))); - } - } - - // log - if (mp3Gain!=0) { - QString trace; - trace += QString("%1\t").arg(getItemText(row, "Path/File")); - trace += QString("%1").arg(dBGain); - writeLog(trace, LOGTYPE_CHANGE); - } + double dBGain = mp3Gain*DB; + double gainValue = isAlbumErase ? dBGain : 0.0; + QList<QStandardItem *> found = model->findItems(fileName, Qt::MatchExactly, 0); + if (found.count()==0) return; + int row = found.at(0)->row(); + QStandardItem *item = 0; + + item = getItem(row, "Volume"); + if (item && !item->data().isNull()) + setItem(row, "Volume", QVariant(item->data().toDouble()+gainValue)); + + QVariant newMaxAmplitude = QVariant(); // double + item = getItem(row, "Max Amplitude"); + if (item && !item->data().isNull()){ + double maxAmplitude = item->data().toDouble(); + newMaxAmplitude = QVariant(maxAmplitude*pow(2.0, round(gainValue/DB)/4.0)); + setItem(row, "Max Amplitude", newMaxAmplitude); + } + + // depends on "Max Amplitude" field + if (!newMaxAmplitude.isNull()){ + item = getItem(row, "clipping"); + if (item && !item->data().isNull()){ + bool clipping = newMaxAmplitude.toDouble()>32767.0; + setItem(row, "clipping", QVariant(clipping)); + } + } + + QVariant newGainValue = QVariant(); // double + item = getItem(row, "Track Gain"); + if (item && !item->data().isNull()){ + newGainValue = QVariant(item->data().toDouble()-dBGain); + setItem(row, "Track Gain", newGainValue); + } + + item = getItem(row, "dBGain"); + if (item && !item->data().isNull()){ + double newdBGain = item->data().toDouble()-dBGain; + setItem(row, "dBGain", QVariant(newdBGain)); + } + + // depends on "Max Amplitude" and "Track Gain" fields + if (!newMaxAmplitude.isNull() && !newGainValue.isNull()){ + item = getItem(row, "clip(Track)"); + if (item && !item->data().isNull()){ + bool clippingTrack = newMaxAmplitude.toDouble()*pow(2.0, round(newGainValue.toDouble()/DB)/4.0)>32767.0; + setItem(row, "clip(Track)", QVariant(clippingTrack)); + } + } + + // depends on "Max Amplitude" field + if (!newMaxAmplitude.isNull()){ + item = getItem(row, "Max Noclip Gain"); + if (item && !item->data().isNull()){ + int mp3GainNoClip = (int)floor((15.0-log10(newMaxAmplitude.toDouble())/log10(2.0))*4.0); + setItem(row, "Max Noclip Gain", QVariant(mp3GainNoClip*DB)); + } + } + + if (isAlbumErase){ + // Album fields cannot be recalculated, so they must be deleted + QStringList columns = QStringList() << "Album Volume" << "Album Max Amplitude" + << "Album Gain" << "Album dBGain" << "clip(Album)"; + foreach (QString element, columns){ + item = getItem(row, element); + if (item){ + item->setData(0); // before item delete to enable automatic model/view refresh + delete item; + } + } + } + + // finally set line color to red if clipping is set + QStringList columns = QStringList() << "Path/File" << "Path" << "File"; + foreach (QString element, columns){ + QStandardItem *item = getItem(row, element); + item->setForeground(QBrush(QColor(0,0,0))); + } + item = getItem(row, "clipping"); + QStandardItem *item1 = getItem(row, "clip(Track)"); + if ((item && item->data().toBool()) || (item1 && item1->data().toBool())){ + if (item) item->setForeground(QBrush(QColor(255,0,0))); + if (item1) item1->setForeground(QBrush(QColor(255,0,0))); + foreach (QString element, columns){ + QStandardItem *item = getItem(row, element); + item->setForeground(QBrush(QColor(255,0,0))); + } + } + + // log + if (mp3Gain!=0) { + QString trace; + trace += QString("%1\t").arg(getItemText(row, "Path/File")); + trace += QString("%1").arg(dBGain); + writeLog(trace, LOGTYPE_CHANGE); + } } // refresh fields of tableView by mp3Gain album change void MainWindow::updateModelRowsByMP3GainAlbum(QString fileName, int mp3Gain, bool isTrackModifiable){ - QList<QStandardItem *> found = model->findItems(fileName, Qt::MatchExactly, 0); - if (found.count()==0) return; - QModelIndex modelIndex = model->item(found0->row())->index(); - updateModelRowsByMP3GainAlbum(QModelIndexList() << modelIndex, mp3Gain, isTrackModifiable); + QList<QStandardItem *> found = model->findItems(fileName, Qt::MatchExactly, 0); + if (found.count()==0) return; + QModelIndex modelIndex = model->item(found0->row())->index(); + updateModelRowsByMP3GainAlbum(QModelIndexList() << modelIndex, mp3Gain, isTrackModifiable); } // refresh fields of tableView by mp3Gain album change void MainWindow::updateModelRowsByMP3GainAlbum(QModelIndexList indices, int mp3Gain, bool isTrackModifiable){ - double dBGain = mp3Gain*DB; - double gainValue = isTrackModifiable ? dBGain : 0.0; - QStandardItem *item = 0; - - foreach(QModelIndex index, indices) { - int row = model->itemFromIndex(index)->row(); - - if (isTrackModifiable){ - item = getItem(row, "Volume"); - if (item && !item->data().isNull()){ - setItem(row, "Volume", QVariant(item->data().toDouble()+gainValue)); - } - - QVariant newMaxAmplitude = QVariant(); // double - item = getItem(row, "Max Amplitude"); - if (item && !item->data().isNull()){ - double maxAmplitude = item->data().toDouble(); - newMaxAmplitude = QVariant(maxAmplitude*pow(2.0, round(gainValue/DB)/4.0)); - setItem(row, "Max Amplitude", QVariant(newMaxAmplitude)); - } - - // depends on "Max Amplitude" field - if (!newMaxAmplitude.isNull()){ - item = getItem(row, "clipping"); - if (item && !item->data().isNull()){ - bool clipping = newMaxAmplitude.toDouble()>32767.0; - setItem(row, "clipping", QVariant(clipping)); - } - } - - QVariant newGainValue = QVariant(); // double - item = getItem(row, "Track Gain"); - if (item && !item->data().isNull()){ - double newGainValue = item->data().toDouble()-gainValue; // or dBGain ? - setItem(row, "Track Gain", QVariant(newGainValue)); - } - - item = getItem(row, "dBGain"); - if (item && !item->data().isNull()){ - double newdBGain = item->data().toDouble()-gainValue; // or dBGain ? - setItem(row, "dBGain", QVariant(newdBGain)); - } - - // depends on "Max Amplitude" and "Track Gain" fields - if (!newMaxAmplitude.isNull() && !newGainValue.isNull()){ - item = getItem(row, "clip(Track)"); - if (item && !item->data().isNull()){ - bool clippingTrack = newMaxAmplitude.toDouble()*pow(2.0, round(newGainValue.toDouble()/DB)/4.0)>32767.0; - setItem(row, "clip(Track)", QVariant(clippingTrack)); - } - } - - // depends on "Max Amplitude" field - if (!newMaxAmplitude.isNull()){ - item = getItem(row, "Max Noclip Gain"); - if (item && !item->data().isNull()){ - int mp3GainNoClip = (int)floor((15.0-log10(newMaxAmplitude.toDouble())/log10(2.0))*4.0); - setItem(row, "Max Noclip Gain", mp3GainNoClip*DB); - } - } - } - - item = getItem(row, "Album Volume"); - if (item && !item->data().isNull()){ - //QString value = QString("%1").arg(doubleSpinBox_targetNormalValue->value()-tokensdB_gain.toDouble(), 0, 'f', 1); - setItem(row, "Album Volume", QVariant(item->data().toDouble()+gainValue)); - } - - item = getItem(row, "Album Max Amplitude"); - if (item && !item->data().isNull()){ - double maxAlbumAmplitude = item->data().toDouble(); - double newMaxAlbumAmplitude = maxAlbumAmplitude*pow(2.0, round(gainValue/DB)/4.0); - setItem(row, "Album Max Amplitude", QVariant(newMaxAlbumAmplitude)); - } - - QVariant newGainValue = QVariant(); // double - item = getItem(row, "Album Gain"); - if (item && !item->data().isNull()){ - newGainValue = QVariant(item->data().toDouble()-dBGain); - setItem(row, "Album Gain", QVariant(newGainValue)); - } - - item = getItem(row, "Album dBGain"); - if (item && !item->data().isNull()){ - double newAlbumDBGain = item->data().toDouble()-dBGain; - setItem(row, "Album dBGain", QVariant(newAlbumDBGain)); - } - - // depends on "Max Amplitude" and "Track Gain" fields - if (!newGainValue.isNull()){ - item = getItem(row, "Max Amplitude"); - if (item && !item->data().isNull()){ - double maxAmplitude = item->data().toDouble(); - double newMaxAmplitude = maxAmplitude*pow(2.0, round(gainValue/DB)/4.0); - bool clippingTrack = newMaxAmplitude*pow(2.0, round(newGainValue.toDouble()/DB)/4.0)>32767.0; - setItem(row, "clip(Album)", QVariant(clippingTrack)); - } - } - - // finally set line color to red if clipping is set - QStringList columns = QStringList() << "Path/File" << "Path" << "File"; - foreach (QString element, columns){ - QStandardItem *item = getItem(row, element); - item->setForeground(QBrush(QColor(0,0,0))); - } - item = getItem(row, "clipping"); - QStandardItem *item1 = getItem(row, "clip(Track)"); - QStandardItem *item2 = getItem(row, "clip(Album)"); - if ((item && item->data().toBool()) || (item1 && item1->data().toBool()) || (item2 && item2->data().toBool())){ - if (item) item->setForeground(QBrush(QColor(255,0,0))); - if (item1) item1->setForeground(QBrush(QColor(255,0,0))); - if (item2) item2->setForeground(QBrush(QColor(255,0,0))); - foreach (QString element, columns){ - QStandardItem *item = getItem(row, element); - item->setForeground(QBrush(QColor(255,0,0))); - } - } - - // log - if (mp3Gain!=0) { - QString trace; - trace += QString("%1\t").arg(getItemText(row, "Path/File")); - trace += QString("%1").arg(dBGain); - writeLog(trace, LOGTYPE_CHANGE); - } - } + double dBGain = mp3Gain*DB; + double gainValue = isTrackModifiable ? dBGain : 0.0; + QStandardItem *item = 0; + + foreach(QModelIndex index, indices) { + int row = model->itemFromIndex(index)->row(); + + if (isTrackModifiable){ + item = getItem(row, "Volume"); + if (item && !item->data().isNull()){ + setItem(row, "Volume", QVariant(item->data().toDouble()+gainValue)); + } + + QVariant newMaxAmplitude = QVariant(); // double + item = getItem(row, "Max Amplitude"); + if (item && !item->data().isNull()){ + double maxAmplitude = item->data().toDouble(); + newMaxAmplitude = QVariant(maxAmplitude*pow(2.0, round(gainValue/DB)/4.0)); + setItem(row, "Max Amplitude", QVariant(newMaxAmplitude)); + } + + // depends on "Max Amplitude" field + if (!newMaxAmplitude.isNull()){ + item = getItem(row, "clipping"); + if (item && !item->data().isNull()){ + bool clipping = newMaxAmplitude.toDouble()>32767.0; + setItem(row, "clipping", QVariant(clipping)); + } + } + + QVariant newGainValue = QVariant(); // double + item = getItem(row, "Track Gain"); + if (item && !item->data().isNull()){ + double newGainValue = item->data().toDouble()-gainValue; // or dBGain ? + setItem(row, "Track Gain", QVariant(newGainValue)); + } + + item = getItem(row, "dBGain"); + if (item && !item->data().isNull()){ + double newdBGain = item->data().toDouble()-gainValue; // or dBGain ? + setItem(row, "dBGain", QVariant(newdBGain)); + } + + // depends on "Max Amplitude" and "Track Gain" fields + if (!newMaxAmplitude.isNull() && !newGainValue.isNull()){ + item = getItem(row, "clip(Track)"); + if (item && !item->data().isNull()){ + bool clippingTrack = newMaxAmplitude.toDouble()*pow(2.0, round(newGainValue.toDouble()/DB)/4.0)>32767.0; + setItem(row, "clip(Track)", QVariant(clippingTrack)); + } + } + + // depends on "Max Amplitude" field + if (!newMaxAmplitude.isNull()){ + item = getItem(row, "Max Noclip Gain"); + if (item && !item->data().isNull()){ + int mp3GainNoClip = (int)floor((15.0-log10(newMaxAmplitude.toDouble())/log10(2.0))*4.0); + setItem(row, "Max Noclip Gain", mp3GainNoClip*DB); + } + } + } + + item = getItem(row, "Album Volume"); + if (item && !item->data().isNull()){ + //QString value = QString("%1").arg(doubleSpinBox_targetNormalValue->value()-tokensdB_gain.toDouble(), 0, 'f', 1); + setItem(row, "Album Volume", QVariant(item->data().toDouble()+gainValue)); + } + + item = getItem(row, "Album Max Amplitude"); + if (item && !item->data().isNull()){ + double maxAlbumAmplitude = item->data().toDouble(); + double newMaxAlbumAmplitude = maxAlbumAmplitude*pow(2.0, round(gainValue/DB)/4.0); + setItem(row, "Album Max Amplitude", QVariant(newMaxAlbumAmplitude)); + } + + QVariant newGainValue = QVariant(); // double + item = getItem(row, "Album Gain"); + if (item && !item->data().isNull()){ + newGainValue = QVariant(item->data().toDouble()-dBGain); + setItem(row, "Album Gain", QVariant(newGainValue)); + } + + item = getItem(row, "Album dBGain"); + if (item && !item->data().isNull()){ + double newAlbumDBGain = item->data().toDouble()-dBGain; + setItem(row, "Album dBGain", QVariant(newAlbumDBGain)); + } + + // depends on "Max Amplitude" and "Track Gain" fields + if (!newGainValue.isNull()){ + item = getItem(row, "Max Amplitude"); + if (item && !item->data().isNull()){ + double maxAmplitude = item->data().toDouble(); + double newMaxAmplitude = maxAmplitude*pow(2.0, round(gainValue/DB)/4.0); + bool clippingTrack = newMaxAmplitude*pow(2.0, round(newGainValue.toDouble()/DB)/4.0)>32767.0; + setItem(row, "clip(Album)", QVariant(clippingTrack)); + } + } + + // finally set line color to red if clipping is set + QStringList columns = QStringList() << "Path/File" << "Path" << "File"; + foreach (QString element, columns){ + QStandardItem *item = getItem(row, element); + item->setForeground(QBrush(QColor(0,0,0))); + } + item = getItem(row, "clipping"); + QStandardItem *item1 = getItem(row, "clip(Track)"); + QStandardItem *item2 = getItem(row, "clip(Album)"); + if ((item && item->data().toBool()) || (item1 && item1->data().toBool()) || (item2 && item2->data().toBool())){ + if (item) item->setForeground(QBrush(QColor(255,0,0))); + if (item1) item1->setForeground(QBrush(QColor(255,0,0))); + if (item2) item2->setForeground(QBrush(QColor(255,0,0))); + foreach (QString element, columns){ + QStandardItem *item = getItem(row, element); + item->setForeground(QBrush(QColor(255,0,0))); + } + } + + // log + if (mp3Gain!=0) { + QString trace; + trace += QString("%1\t").arg(getItemText(row, "Path/File")); + trace += QString("%1").arg(dBGain); + writeLog(trace, LOGTYPE_CHANGE); + } + } } void MainWindow::runGain(QModelIndexList indices, bool isAlbum, double passSlice){ - QProcess process; - double startProgress = progressBar_Total->doubleValue(); + QProcess process; + double startProgress = progressBar_Total->doubleValue(); + + try { + if (startProgress==0.0 && passSlice==100.0) disableGUI(); + if (indices.isEmpty()) throw(0); + + int total_index = 0; + + QStringList argOptions; - try { - if (startProgress==0.0 && passSlice==100.0) disableGUI(); - if (indices.isEmpty()) throw(0); - - int total_index = 0; - - QStringList argOptions; - - if (isAlbum){ - argOptions << "-a"; // apply Album gain automatically - }else{ - argOptions << "-r"; // apply Track gain automatically (all files set to equal loudness) - } - argOptions << getArgumentsByOptions(); - - QMultiHash<QString, QModelIndex> indexByPath; - - if (isAlbum){ - // in album mode a process can start only the files belong to their parent path - // irreversed order is used in iterator trying to keep later the original order - QListIterator<QModelIndex> indicesIterator(indices); - indicesIterator.toBack(); - while (indicesIterator.hasPrevious()){ - QModelIndex index = indicesIterator.previous(); - int row = model->itemFromIndex(index)->row(); - QString pathName = getItemText(row, "Path"); - indexByPath.insert(pathName, index); - } - } - else{ - indexByPath.insert("dummyPath", QModelIndex()); - } - - foreach(QString pathName, indexByPath.uniqueKeys()){ - QModelIndexList indicesByProcess = isAlbum ? indexByPath.values(pathName) : indices; - QStringList argFiles; - - foreach(QModelIndex index, indicesByProcess) { - int row = model->itemFromIndex(index)->row(); - QString fileName = getItemText(row, "Path/File"); - argFiles << fileName; - } - - QStringList args = QStringList() << argOptions << argFiles; - process.setProcessChannelMode(QProcess::MergedChannels); - QString trace = QString("%1 %2").arg(this->getBackEnd()).arg(args.join(" ")); - writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); - - process.start(this->getBackEnd(), args); - - if (!process.waitForStarted()){ - showNoBackEndVersion(); - throw(1); - } - - /* - new file at track mode: - - line==...bytes analyzed && (prevLine!=...bytes analyzed && prevLine!='File...') - line==filename && (prevLine!=...bytes analyzed && prevLine!='File...') - - new file at album mode - - line==...bytes analyzed && (prevLine!=...bytes analyzed && prevLine!='File...') - line==filename && (prevLine!=...bytes analyzed && prevLine!='File...') - - line='Applying mp3 gain change...' && prevLine==...bytes written - */ - - /* - track mode: expected undo output is a tab separated table, integer value is the mp3 gain (* 1.5 = real db gain) - >mp3gain -r -o "2Pac - California Love.mp3" "2Pac - Changes.mp3" - File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain - 1/2 1% of 6848512 bytes analyzed\r (analysis is optional, if no tag is found) - 1/2 3% of 6848512 bytes analyzed\r - ... - 1/2 98% of 6848512 bytes analyzed\r - /home/brazso/work/audio/2Pac - California Love.mp3 -7 -10.330000 44325.970901 189 126 - Applying mp3 gain change of -7 to /home/brazso/work/audio/2Pac - California Love.mp3... - 1% of 6848512 bytes written\r (writing is optional, if not 0 gain change is found) - 3% of 6848512 bytes written\r - ... - 98% of 6848512 bytes written\r - 2/2 1% of 6465618 bytes analyzed\r - ... - 2/2 98% of 6465618 bytes analyzed - /home/brazso/work/audio/2Pac - Changes.mp3 0 0.290000 16758.632575 182 99 - No changes to /home/brazso/work/audio/2Pac - Changes.mp3 are necessary - ...but tag needs update: Writing tag information for /home/brazso/work/audio/2Pac - Changes.mp3 - */ - - /* - album mode: expected undo output is a tab separated table, integer value is the mp3 gain (* 1.5 = real db gain) - >mp3gain -a -o "2Pac - California Love.mp3" "2Pac - Changes.mp3" - File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain - 1/2 1% of 6848834 bytes analyzed\r (analysis is optional, if no tag is found!) - 1/2 3% of 6848834 bytes analyzed\r - ... - 1/2 98% of 6848834 bytes analyzed\r - /home/brazso/work/audio/2Pac - California Love.mp3 -7 -10.330000 44325.970901 189 126 - 2/2 1% of 6465618 bytes analyzed - ... - 2/2 98% of 6465618 bytes analyzed - /home/brazso/work/audio/2Pac - Changes.mp3 -5 -7.230000 39858.970192 187 104 - "Album" -6 -9.200000 44325.961728 189 104 - ( "-c" argument makes this warning and confirmation question out ) - WARNING: /home/brazso/work/audio/2Pac - California Love.mp3 may clip with mp3 gain change -6 - Make change? y/n - Applying mp3 gain change of -6 to /home/brazso/work/audio/2Pac - California Love.mp3... - 1% of 6848834 bytes written (writing is optional, if not 0 gain change is found) - ... - 98% of 6848834 bytes written - Applying mp3 gain change of -6 to /home/brazso/work/audio/2Pac - Changes.mp3... - 1% of 6465618 bytes written (writing is optional, if not 0 gain change is found) - ... - 98% of 6465618 bytes written - */ - enum resultColumns { File, MP3_gain, dB_gain, Max_Amplitude, Max_global_gain, Min_global_gain, enumMax }; - QList<int> passes = QList<int>() << 90 << 10; // analysis, gain (in track mode) - bool hasAnalysis = false; - QStringList tokens; - Line prevLine; - - for (bool isAfterLast = false, isWaitForReadyRead = false; - (isWaitForReadyRead = process.waitForReadyRead(-1)) || !isAfterLast; - isAfterLast = !isWaitForReadyRead ) { - - QByteArray newData = process.readAll(); - QString result = QString::fromLocal8Bit(newData); - - QTextStream in(&result); - do { - Line line; - line.content = in.readLine(); - if (line.content==QString::null || line.content.isEmpty()) - continue; - - QStringList lines = line.content.split(QChar('\r'), QString::SkipEmptyParts); - foreach (line.content, lines){ - if (line.content.trimmed().isEmpty()){ - continue; - } - - writeLog(line.content, LOGTYPE_BACKEND, line.content.endsWith("bytes analyzed") || line.content.endsWith("bytes written") ? 2 : 1); - bool isNextIndex = false; - line.errType = hasError(line.content); - - if (line.errType){ - line.type = LINETYPE_ERROR; - if (line.errType!=ERRTYPE_SUPPRESSED){ - hasAnalysis = false; - isNextIndex = true; // for the time being all errors increase the iterator - } - } - else if (line.content.endsWith("bytes analyzed")){ // optional - line.type = LINETYPE_ANALYSIS; - // single track: " 5% of 2650308 bytes analyzed" - // more tracks: "1/2 13% of 2650308 bytes analyzed" - if (prevLine.type!=LINETYPE_ANALYSIS && prevLine.type!=LINETYPE_FILE_HEADER){ - //isNextIndex = true; - total_index++; - } - int percent = 0; - int actFileNumber = 1; - QRegExp rx("(?:^)(?:\\(\\d+)(?:/)(\\d+)(?:\\))?(?: *)(\\d+)(?:% of )(\\d+)(?: bytes analyzed$)"); - int pos = rx.indexIn(line.content); - if (pos > -1) { - actFileNumber = rx.cap(1).isEmpty() ? 1 : rx.cap(1).toInt(); - //int totalFileNumber = rx.cap(2).isEmpty() ? 1 : rx.cap(2).toInt(); - percent = rx.cap(3).toInt(); - //long fileSize = rx.cap(4).toLong(); - } - if (percent>100) percent=100; // some bug from the back end - if (!isAlbum) - percent = (int)round(percent*passes0/100.0); - setProgress(QVariant(percent), - QVariant(startProgress+passSlice*(((total_index+percent/100.0))/(indices.size()*(isAlbum ? 2 : 1))))); - updateStatusBar(QString("Analyzing %1").arg(argFiles.at(actFileNumber-1))); - } - else if (line.content.endsWith("bytes written")){ - line.type = LINETYPE_WRITTEN; - // " 43% of 2650308 bytes written" - int percent = 0; - QRegExp rx("(?:^ *)(\\d+)(?:% of )(\\d+)(?: bytes written$)"); - int pos = rx.indexIn(line.content); - if (pos > -1) { - percent = rx.cap(1).toInt(); - //long fileSize = rx.cap(2).toLong(); - } - if (percent>100) percent=100; // some bug from the back end - if (!isAlbum && hasAnalysis) - percent = (int)(passes0+round(percent*passes1/100.0)); - setProgress(QVariant(percent), - QVariant(startProgress+passSlice*(((total_index+percent/100.0))/(indices.size()*(isAlbum ? 2 : 1))))); - double gainValue = tokensMP3_gain.toInt()*DB; // dBGain - updateStatusBar(QString("Applying gain of %1 dB to %2").arg(gainValue, 0, 'f', 1).arg(tokensFile)); - } - // Applying mp3 gain change of -5 to /home/brazso/work/audio/2Pac - Changes.mp3... - // No changes to /home/brazso/work/audio/Alizee - Lolita.mp3 are necessary - else if ( line.content.startsWith("Applying mp3 gain change of ") || - line.content.startsWith("No changes to ") ){ - line.type = LINETYPE_APPLY_GAIN; - if (!isAlbum){ - bool isConvertOk; - double gainValue = tokensMP3_gain.toInt(&isConvertOk)*DB; // dBGain - if (isConvertOk){ - QString msg; - if (gainValue==0) - msg = tr("No changes to %1").arg(tokensFile); - else - msg = tr("Applying gain of %1 dB to %2").arg(gainValue, 0, 'f', 1).arg(tokensFile); - updateStatusBar(msg); - } - updateModelRowByAnalysisTrack(tokensFile, tokensMP3_gain.toInt(), tokensdB_gain.toDouble(), tokensMax_Amplitude.toDouble(), /*maxNoclipGain=*/ false, /*isLog=*/ true); - updateModelRowByMP3GainTrack(tokensFile, tokensMP3_gain.toInt()); - } else { - QString fileName; - QRegExp rx("(?:^Applying mp3 gain change of )(-?\\d+)(?: to )(.*)(?:\\.\\.\\.$)"); - int pos = rx.indexIn(line.content); - if (pos > -1) { - QStringList list = rx.capturedTexts(); - writeLog(list.join(" "), LOGTYPE_TRACE); - if (list.size()==3){ - fileName = rx.cap(2); - int mp3Gain = rx.cap(1).toInt(); - double gainValue = mp3Gain*DB; // dBGain - updateStatusBar(tr("Applying gain of %1 dB to %2").arg(gainValue, 0, 'f', 1).arg(fileName)); - } - }else{ - rx.setPattern("(?:^No changes to )(.*)(?: are necessary$)"); - pos = rx.indexIn(line.content); - if (pos > -1) { - QStringList list = rx.capturedTexts(); - writeLog(list.join(" "), LOGTYPE_TRACE); - if (list.size()==2){ - fileName = rx.cap(1); - updateStatusBar(tr("No changes to %1").arg(fileName)); - } - } - } - updateModelRowsByAnalysisAlbum(isAlbum, fileName, tokensMP3_gain.toInt(), tokensdB_gain.toDouble(), QVariant(tokensMax_Amplitude.toDouble()), /*isLog=*/ true); - updateModelRowsByMP3GainAlbum(fileName, tokensMP3_gain.toInt()); - } - if (prevLine.type==LINETYPE_WRITTEN || prevLine.type==LINETYPE_APPLY_GAIN || prevLine.type==LINETYPE_FILE_ALBUM){ - isNextIndex = true; - } - } - else { - QStringList tmpTokens = line.content.split(QChar('\t')); - if (tmpTokens.size()==enumMax){ - if (tmpTokensFile=="File"){ - line.type = LINETYPE_FILE_HEADER; - } - else{ - line.type = LINETYPE_FILE_CONTENT; - tokens = tmpTokens; - if (!isAlbum){ - hasAnalysis = prevLine.type==LINETYPE_ANALYSIS; - }else{ - if (tokensFile=="\"Album\""){ - line.type = LINETYPE_FILE_ALBUM; - }else{ - bool isConvertOk; - double gainValue = tokensMP3_gain.toInt(&isConvertOk)*DB; // dBGain - if (isConvertOk){ - QString msg; - if (gainValue==0) - msg = tr("No changes to %1").arg(tokensFile); - else - msg = tr("Applying gain of %1 dB to %2").arg(gainValue, 0, 'f', 1).arg(tokensFile); - updateStatusBar(msg); - } - updateModelRowByAnalysisTrack(tokensFile, tokensMP3_gain.toInt(), tokensdB_gain.toDouble(), tokensMax_Amplitude.toDouble(), /*maxNoclipGain=*/ false,/*isLog=*/ true); - } - } - if (line.type == LINETYPE_FILE_CONTENT){ - if (prevLine.type!=LINETYPE_ANALYSIS && prevLine.type!=LINETYPE_FILE_HEADER){ - isNextIndex = true; - } - } - } - } - } - if (isNextIndex){ - total_index++; - setProgress(QVariant(0), - QVariant(startProgress+passSlice*(((double)total_index)/(indices.size()*(isAlbum ? 2 : 1))))); - } - - qApp->processEvents(QEventLoop::AllEvents); - if (isCancelled) throw(-1); - prevLine = line; - } // foreach - } while (!in.atEnd()); - } - } - - throw(0); - } - catch (int e){ - if (process.state()==QProcess::Starting || process.state()==QProcess::Running){ - process.kill(); - } - setProgress(QVariant(0), QVariant()); - if (startProgress==0.0 && passSlice==100.0){ - enableGUI(); - } - } + if (isAlbum){ + argOptions << "-a"; // apply Album gain automatically + }else{ + argOptions << "-r"; // apply Track gain automatically (all files set to equal loudness) + } + argOptions << getArgumentsByOptions(); + + QMultiHash<QString, QModelIndex> indexByPath; + + if (isAlbum){ + // in album mode a process can start only the files belong to their parent path + // irreversed order is used in iterator trying to keep later the original order + QListIterator<QModelIndex> indicesIterator(indices); + indicesIterator.toBack(); + while (indicesIterator.hasPrevious()){ + QModelIndex index = indicesIterator.previous(); + int row = model->itemFromIndex(index)->row(); + QString pathName = getItemText(row, "Path"); + indexByPath.insert(pathName, index); + } + } + else{ + indexByPath.insert("dummyPath", QModelIndex()); + } + + foreach(QString pathName, indexByPath.uniqueKeys()){ + QModelIndexList indicesByProcess = isAlbum ? indexByPath.values(pathName) : indices; + QStringList argFiles; + + foreach(QModelIndex index, indicesByProcess) { + int row = model->itemFromIndex(index)->row(); + QString fileName = getItemText(row, "Path/File"); + argFiles << fileName; + } + + QStringList args = QStringList() << argOptions << argFiles; + process.setProcessChannelMode(QProcess::MergedChannels); + QString trace = QString("%1 %2").arg(this->getBackEnd()).arg(args.join(" ")); + writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); + + process.start(this->getBackEnd(), args); + + if (!process.waitForStarted()){ + showNoBackEndVersion(); + throw(1); + } + + /* + new file at track mode: + + line==...bytes analyzed && (prevLine!=...bytes analyzed && prevLine!='File...') + line==filename && (prevLine!=...bytes analyzed && prevLine!='File...') + + new file at album mode + + line==...bytes analyzed && (prevLine!=...bytes analyzed && prevLine!='File...') + line==filename && (prevLine!=...bytes analyzed && prevLine!='File...') + + line='Applying mp3 gain change...' && prevLine==...bytes written + */ + + /* + track mode: expected undo output is a tab separated table, integer value is the mp3 gain (* 1.5 = real db gain) + >mp3gain -r -o "2Pac - California Love.mp3" "2Pac - Changes.mp3" + File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain + 1/2 1% of 6848512 bytes analyzed\r (analysis is optional, if no tag is found) + 1/2 3% of 6848512 bytes analyzed\r + ... + 1/2 98% of 6848512 bytes analyzed\r + /home/brazso/work/audio/2Pac - California Love.mp3 -7 -10.330000 44325.970901 189 126 + Applying mp3 gain change of -7 to /home/brazso/work/audio/2Pac - California Love.mp3... + 1% of 6848512 bytes written\r (writing is optional, if not 0 gain change is found) + 3% of 6848512 bytes written\r + ... + 98% of 6848512 bytes written\r + 2/2 1% of 6465618 bytes analyzed\r + ... + 2/2 98% of 6465618 bytes analyzed + /home/brazso/work/audio/2Pac - Changes.mp3 0 0.290000 16758.632575 182 99 + No changes to /home/brazso/work/audio/2Pac - Changes.mp3 are necessary + ...but tag needs update: Writing tag information for /home/brazso/work/audio/2Pac - Changes.mp3 + */ + + /* + album mode: expected undo output is a tab separated table, integer value is the mp3 gain (* 1.5 = real db gain) + >mp3gain -a -o "2Pac - California Love.mp3" "2Pac - Changes.mp3" + File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain + 1/2 1% of 6848834 bytes analyzed\r (analysis is optional, if no tag is found!) + 1/2 3% of 6848834 bytes analyzed\r + ... + 1/2 98% of 6848834 bytes analyzed\r + /home/brazso/work/audio/2Pac - California Love.mp3 -7 -10.330000 44325.970901 189 126 + 2/2 1% of 6465618 bytes analyzed + ... + 2/2 98% of 6465618 bytes analyzed + /home/brazso/work/audio/2Pac - Changes.mp3 -5 -7.230000 39858.970192 187 104 + "Album" -6 -9.200000 44325.961728 189 104 + ( "-c" argument makes this warning and confirmation question out ) + WARNING: /home/brazso/work/audio/2Pac - California Love.mp3 may clip with mp3 gain change -6 + Make change? y/n + Applying mp3 gain change of -6 to /home/brazso/work/audio/2Pac - California Love.mp3... + 1% of 6848834 bytes written (writing is optional, if not 0 gain change is found) + ... + 98% of 6848834 bytes written + Applying mp3 gain change of -6 to /home/brazso/work/audio/2Pac - Changes.mp3... + 1% of 6465618 bytes written (writing is optional, if not 0 gain change is found) + ... + 98% of 6465618 bytes written + */ + enum resultColumns { File, MP3_gain, dB_gain, Max_Amplitude, Max_global_gain, Min_global_gain, enumMax }; + QList<int> passes = QList<int>() << 90 << 10; // analysis, gain (in track mode) + bool hasAnalysis = false; + QStringList tokens; + Line prevLine; + + for (bool isAfterLast = false, isWaitForReadyRead = false; + (isWaitForReadyRead = process.waitForReadyRead(-1)) || !isAfterLast; + isAfterLast = !isWaitForReadyRead ) { + + QByteArray newData = process.readAll(); + QString result = QString::fromLocal8Bit(newData); + + QTextStream in(&result); + do { + Line line; + line.content = in.readLine(); + if (line.content.isNull() || line.content.isEmpty()) + continue; + + QStringList lines = line.content.split(QChar('\r'), Qt::SkipEmptyParts); + foreach (line.content, lines){ + if (line.content.trimmed().isEmpty()){ + continue; + } + + writeLog(line.content, LOGTYPE_BACKEND, line.content.endsWith("bytes analyzed") || line.content.endsWith("bytes written") ? 2 : 1); + bool isNextIndex = false; + line.errType = hasError(line.content); + + if (line.errType){ + line.type = LINETYPE_ERROR; + if (line.errType!=ERRTYPE_SUPPRESSED){ + hasAnalysis = false; + isNextIndex = true; // for the time being all errors increase the iterator + } + } + else if (line.content.endsWith("bytes analyzed")){ // optional + line.type = LINETYPE_ANALYSIS; + // single track: " 5% of 2650308 bytes analyzed" + // more tracks: "1/2 13% of 2650308 bytes analyzed" + if (prevLine.type!=LINETYPE_ANALYSIS && prevLine.type!=LINETYPE_FILE_HEADER){ + //isNextIndex = true; + total_index++; + } + int percent = 0; + int actFileNumber = 1; + QRegExp rx("(?:^)(?:\\(\\d+)(?:/)(\\d+)(?:\\))?(?: *)(\\d+)(?:% of )(\\d+)(?: bytes analyzed$)"); + int pos = rx.indexIn(line.content); + if (pos > -1) { + actFileNumber = rx.cap(1).isEmpty() ? 1 : rx.cap(1).toInt(); + //int totalFileNumber = rx.cap(2).isEmpty() ? 1 : rx.cap(2).toInt(); + percent = rx.cap(3).toInt(); + //long fileSize = rx.cap(4).toLong(); + } + if (percent>100) percent=100; // some bug from the back end + if (!isAlbum) + percent = (int)round(percent*passes0/100.0); + setProgress(QVariant(percent), + QVariant(startProgress+passSlice*(((total_index+percent/100.0))/(indices.size()*(isAlbum ? 2 : 1))))); + updateStatusBar(QString("Analyzing %1").arg(argFiles.at(actFileNumber-1))); + } + else if (line.content.endsWith("bytes written")){ + line.type = LINETYPE_WRITTEN; + // " 43% of 2650308 bytes written" + int percent = 0; + QRegExp rx("(?:^ *)(\\d+)(?:% of )(\\d+)(?: bytes written$)"); + int pos = rx.indexIn(line.content); + if (pos > -1) { + percent = rx.cap(1).toInt(); + //long fileSize = rx.cap(2).toLong(); + } + if (percent>100) percent=100; // some bug from the back end + if (!isAlbum && hasAnalysis) + percent = (int)(passes0+round(percent*passes1/100.0)); + setProgress(QVariant(percent), + QVariant(startProgress+passSlice*(((total_index+percent/100.0))/(indices.size()*(isAlbum ? 2 : 1))))); + double gainValue = tokensMP3_gain.toInt()*DB; // dBGain + updateStatusBar(QString("Applying gain of %1 dB to %2").arg(gainValue, 0, 'f', 1).arg(tokensFile)); + } + // Applying mp3 gain change of -5 to /home/brazso/work/audio/2Pac - Changes.mp3... + // No changes to /home/brazso/work/audio/Alizee - Lolita.mp3 are necessary + else if ( line.content.startsWith("Applying mp3 gain change of ") || + line.content.startsWith("No changes to ") ){ + line.type = LINETYPE_APPLY_GAIN; + if (!isAlbum){ + bool isConvertOk; + double gainValue = tokensMP3_gain.toInt(&isConvertOk)*DB; // dBGain + if (isConvertOk){ + QString msg; + if (gainValue==0) + msg = tr("No changes to %1").arg(tokensFile); + else + msg = tr("Applying gain of %1 dB to %2").arg(gainValue, 0, 'f', 1).arg(tokensFile); + updateStatusBar(msg); + } + updateModelRowByAnalysisTrack(tokensFile, tokensMP3_gain.toInt(), tokensdB_gain.toDouble(), tokensMax_Amplitude.toDouble(), /*maxNoclipGain=*/ false, /*isLog=*/ true); + updateModelRowByMP3GainTrack(tokensFile, tokensMP3_gain.toInt()); + } else { + QString fileName; + QRegExp rx("(?:^Applying mp3 gain change of )(-?\\d+)(?: to )(.*)(?:\\.\\.\\.$)"); + int pos = rx.indexIn(line.content); + if (pos > -1) { + QStringList list = rx.capturedTexts(); + writeLog(list.join(" "), LOGTYPE_TRACE); + if (list.size()==3){ + fileName = rx.cap(2); + int mp3Gain = rx.cap(1).toInt(); + double gainValue = mp3Gain*DB; // dBGain + updateStatusBar(tr("Applying gain of %1 dB to %2").arg(gainValue, 0, 'f', 1).arg(fileName)); + } + }else{ + rx.setPattern("(?:^No changes to )(.*)(?: are necessary$)"); + pos = rx.indexIn(line.content); + if (pos > -1) { + QStringList list = rx.capturedTexts(); + writeLog(list.join(" "), LOGTYPE_TRACE); + if (list.size()==2){ + fileName = rx.cap(1); + updateStatusBar(tr("No changes to %1").arg(fileName)); + } + } + } + updateModelRowsByAnalysisAlbum(isAlbum, fileName, tokensMP3_gain.toInt(), tokensdB_gain.toDouble(), QVariant(tokensMax_Amplitude.toDouble()), /*isLog=*/ true); + updateModelRowsByMP3GainAlbum(fileName, tokensMP3_gain.toInt()); + } + if (prevLine.type==LINETYPE_WRITTEN || prevLine.type==LINETYPE_APPLY_GAIN || prevLine.type==LINETYPE_FILE_ALBUM){ + isNextIndex = true; + } + } + else { + QStringList tmpTokens = line.content.split(QChar('\t')); + if (tmpTokens.size()==enumMax){ + if (tmpTokensFile=="File"){ + line.type = LINETYPE_FILE_HEADER; + } + else{ + line.type = LINETYPE_FILE_CONTENT; + tokens = tmpTokens; + if (!isAlbum){ + hasAnalysis = prevLine.type==LINETYPE_ANALYSIS; + }else{ + if (tokensFile=="\"Album\""){ + line.type = LINETYPE_FILE_ALBUM; + }else{ + bool isConvertOk; + double gainValue = tokensMP3_gain.toInt(&isConvertOk)*DB; // dBGain + if (isConvertOk){ + QString msg; + if (gainValue==0) + msg = tr("No changes to %1").arg(tokensFile); + else + msg = tr("Applying gain of %1 dB to %2").arg(gainValue, 0, 'f', 1).arg(tokensFile); + updateStatusBar(msg); + } + updateModelRowByAnalysisTrack(tokensFile, tokensMP3_gain.toInt(), tokensdB_gain.toDouble(), tokensMax_Amplitude.toDouble(), /*maxNoclipGain=*/ false,/*isLog=*/ true); + } + } + if (line.type == LINETYPE_FILE_CONTENT){ + if (prevLine.type!=LINETYPE_ANALYSIS && prevLine.type!=LINETYPE_FILE_HEADER){ + isNextIndex = true; + } + } + } + } + } + if (isNextIndex){ + total_index++; + setProgress(QVariant(0), + QVariant(startProgress+passSlice*(((double)total_index)/(indices.size()*(isAlbum ? 2 : 1))))); + } + + qApp->processEvents(QEventLoop::AllEvents); + if (isCancelled) throw(-1); + prevLine = line; + } // foreach + } while (!in.atEnd()); + } + } + + throw(0); + } + catch (int e){ + if (process.state()==QProcess::Starting || process.state()==QProcess::Running){ + process.kill(); + } + setProgress(QVariant(0), QVariant()); + if (startProgress==0.0 && passSlice==100.0){ + enableGUI(); + } + } } void MainWindow::runConstantGain(QModelIndexList indices, int mp3Gain, bool isLeft, bool isRight, double passSlice){ - QProcess process; - double startProgress = progressBar_Total->doubleValue(); + QProcess process; + double startProgress = progressBar_Total->doubleValue(); + + try { + if (startProgress==0.0 && passSlice==100.0) disableGUI(); + if (indices.isEmpty() || mp3Gain==0) throw(0); - try { - if (startProgress==0.0 && passSlice==100.0) disableGUI(); - if (indices.isEmpty() || mp3Gain==0) throw(0); - - QStringList args; - if (isLeft && isRight){ - args << "-g" << QString("%1").arg(mp3Gain); // apply gain i to mp3 without doing any analysis - }else if(isLeft && !isRight){ - args << "-l" << "0" << QString("%1").arg(mp3Gain); // apply gain i to channel 0 (left channel) of mp3 without doing any analysis (ONLY works for STEREO mp3s, not Joint Stereo mp3s) - }else if(!isLeft && isRight){ - args << "-l" << "1" << QString("%1").arg(mp3Gain); // apply gain i to channel 1 (right channel) of mp3 without doing any analysis (ONLY works for STEREO mp3s, not Joint Stereo mp3s) - }else{ - throw(1); - } - args << getArgumentsByOptions(); - - foreach(QModelIndex index, indices) { - int row = model->itemFromIndex(index)->row(); - QStandardItem *item = getItem(row, "Path/File"); - QString fileName = item->text(); - args << fileName; - } - - process.setProcessChannelMode(QProcess::MergedChannels); - QString trace = QString("%1 %2").arg(this->getBackEnd()).arg(args.join(" ")); - writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); - - process.start(this->getBackEnd(), args); - - if (!process.waitForStarted()){ - showNoBackEndVersion(); - throw(1); - } - - /* 2 channels mode, everything goes to SE - D:\Users\Brazso\music\test_mp3>mp3gain -o -g 1 "Arash - Boro Boro.mp3" "Austin Powers - Theme Song.mp3" - File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain - Applying gain change of 1 to Arash - Boro Boro.mp3... - 1% of 10532812 bytes written - 3% of 10532812 bytes written - ... - 99% of 10532812 bytes written - done - Applying gain change of 1 to Austin Powers - Theme Song.mp3... - 2% of 6503689 bytes written - 5% of 6503689 bytes written - ... - 97% of 6503689 bytes written - done - */ - - /* 1 channel mode - D:\Users\Brazso\music\test_mp3>mp3gain -o -l 0 1 "Arash - Boro Boro.mp3" "Austin Powers - Theme Song.mp3" - File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain - SE:Applying gain change of 1 to CHANNEL 0 of Arash - Boro Boro.mp3... - SO:Arash - Boro Boro.mp3: Can't adjust single channel for mono or joint stereo - SE:Applying gain change of 1 to CHANNEL 0 of Austin Powers - Theme Song.mp3... - SO:Austin Powers - Theme Song.mp3: Can't adjust single channel for mono or joint stereo - */ - - enum resultColumns { File, MP3_gain, dB_gain, Max_Amplitude, Max_global_gain, Min_global_gain, enumMax }; - int total_index = 0; - - for (bool isAfterLast = false, isWaitForReadyRead = false; - (isWaitForReadyRead = process.waitForReadyRead(-1)) || !isAfterLast; - isAfterLast = !isWaitForReadyRead ) { - - QByteArray newData = process.readAll(); - QString result = QString::fromLocal8Bit(newData); - - QTextStream in(&result); - do { - Line line; - line.content = in.readLine(); - if (line.content==QString::null || line.content.isEmpty()) - continue; - - QStringList lines = line.content.split(QChar('\r'), QString::SkipEmptyParts); - foreach (line.content, lines){ - if (line.content.trimmed().isEmpty()){ - continue; - } - - writeLog(line.content, LOGTYPE_BACKEND, line.content.endsWith("bytes analyzed") ? 2 : 1); - bool isNextIndex = false; - line.errType = hasError(line.content); - - if (line.errType){ - line.type = LINETYPE_ERROR; - if (line.errType!=ERRTYPE_SUPPRESSED){ - isNextIndex = true; // for the time being all errors increase the iterator - } - } - else if (line.content.endsWith("bytes written")){ - line.type = LINETYPE_WRITTEN; - // " 43% of 2650308 bytes written" - int percent = 0; - QRegExp rx("(?:^ *)(\\d+)(?:% of )(\\d+)(?: bytes written$)"); - int pos = rx.indexIn(line.content); - if (pos > -1) { - percent = rx.cap(1).toInt(); - //long fileSize = rx.cap(2).toLong(); - } - if (percent>100) percent=100; // some bug from the back end - setProgress(QVariant(percent), - QVariant(startProgress+passSlice*(((total_index+percent/100.0))/indices.size()))); - } - else if (line.content=="done"){ - isNextIndex = true; - } - else{ - QStringList tokens = line.content.split(QChar('\t')); - - if (tokens.size()==enumMax && tokensFile=="File"){ - line.type = LINETYPE_FILE_HEADER; - } - else{ - QRegExp rx("(?:Applying gain change of )(-?\\d+)(?: to )(.*)(?:\\.\\.\\.)"); - if (!(isLeft && isRight)){ - rx=QRegExp("(?:Applying gain change of )(-?\\d+)(?: to CHANNEL \\d of )(.*)(?:\\.\\.\\.)"); - } - int pos = rx.indexIn(line.content); - if (pos > -1) { - line.type = LINETYPE_APPLY_GAIN; - QStringList list = rx.capturedTexts(); - if (list.size()==3){ - QString fileName = rx.cap(2); - int mp3Gain = rx.cap(1).toInt(); - updateModelRowByMP3GainTrack(fileName, mp3Gain); - } - }else{ - // error message? - } - } - } - if (isNextIndex){ - total_index++; - setProgress(QVariant(), - QVariant(startProgress+passSlice*(((double)total_index)/indices.size()))); - } - - qApp->processEvents(QEventLoop::AllEvents); - if (isCancelled) throw(-1); - } - } while (!in.atEnd()); - } - - throw(0); - } - catch (int e){ - if (process.state()==QProcess::Starting || process.state()==QProcess::Running){ - process.kill(); - } - setProgress(QVariant(0), QVariant()); - if (startProgress==0.0 && passSlice==100.0){ - enableGUI(); - } - } + QStringList args; + if (isLeft && isRight){ + args << "-g" << QString("%1").arg(mp3Gain); // apply gain i to mp3 without doing any analysis + }else if(isLeft && !isRight){ + args << "-l" << "0" << QString("%1").arg(mp3Gain); // apply gain i to channel 0 (left channel) of mp3 without doing any analysis (ONLY works for STEREO mp3s, not Joint Stereo mp3s) + }else if(!isLeft && isRight){ + args << "-l" << "1" << QString("%1").arg(mp3Gain); // apply gain i to channel 1 (right channel) of mp3 without doing any analysis (ONLY works for STEREO mp3s, not Joint Stereo mp3s) + }else{ + throw(1); + } + args << getArgumentsByOptions(); + + foreach(QModelIndex index, indices) { + int row = model->itemFromIndex(index)->row(); + QStandardItem *item = getItem(row, "Path/File"); + QString fileName = item->text(); + args << fileName; + } + + process.setProcessChannelMode(QProcess::MergedChannels); + QString trace = QString("%1 %2").arg(this->getBackEnd()).arg(args.join(" ")); + writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); + + process.start(this->getBackEnd(), args); + + if (!process.waitForStarted()){ + showNoBackEndVersion(); + throw(1); + } + + /* 2 channels mode, everything goes to SE + D:\Users\Brazso\music\test_mp3>mp3gain -o -g 1 "Arash - Boro Boro.mp3" "Austin Powers - Theme Song.mp3" + File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain + Applying gain change of 1 to Arash - Boro Boro.mp3... + 1% of 10532812 bytes written + 3% of 10532812 bytes written + ... + 99% of 10532812 bytes written + done + Applying gain change of 1 to Austin Powers - Theme Song.mp3... + 2% of 6503689 bytes written + 5% of 6503689 bytes written + ... + 97% of 6503689 bytes written + done + */ + + /* 1 channel mode + D:\Users\Brazso\music\test_mp3>mp3gain -o -l 0 1 "Arash - Boro Boro.mp3" "Austin Powers - Theme Song.mp3" + File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain + SE:Applying gain change of 1 to CHANNEL 0 of Arash - Boro Boro.mp3... + SO:Arash - Boro Boro.mp3: Can't adjust single channel for mono or joint stereo + SE:Applying gain change of 1 to CHANNEL 0 of Austin Powers - Theme Song.mp3... + SO:Austin Powers - Theme Song.mp3: Can't adjust single channel for mono or joint stereo + */ + + enum resultColumns { File, MP3_gain, dB_gain, Max_Amplitude, Max_global_gain, Min_global_gain, enumMax }; + int total_index = 0; + + for (bool isAfterLast = false, isWaitForReadyRead = false; + (isWaitForReadyRead = process.waitForReadyRead(-1)) || !isAfterLast; + isAfterLast = !isWaitForReadyRead ) { + + QByteArray newData = process.readAll(); + QString result = QString::fromLocal8Bit(newData); + + QTextStream in(&result); + do { + Line line; + line.content = in.readLine(); + if (line.content.isNull() || line.content.isEmpty()) + continue; + + QStringList lines = line.content.split(QChar('\r'), Qt::SkipEmptyParts); + foreach (line.content, lines){ + if (line.content.trimmed().isEmpty()){ + continue; + } + + writeLog(line.content, LOGTYPE_BACKEND, line.content.endsWith("bytes analyzed") ? 2 : 1); + bool isNextIndex = false; + line.errType = hasError(line.content); + + if (line.errType){ + line.type = LINETYPE_ERROR; + if (line.errType!=ERRTYPE_SUPPRESSED){ + isNextIndex = true; // for the time being all errors increase the iterator + } + } + else if (line.content.endsWith("bytes written")){ + line.type = LINETYPE_WRITTEN; + // " 43% of 2650308 bytes written" + int percent = 0; + QRegExp rx("(?:^ *)(\\d+)(?:% of )(\\d+)(?: bytes written$)"); + int pos = rx.indexIn(line.content); + if (pos > -1) { + percent = rx.cap(1).toInt(); + //long fileSize = rx.cap(2).toLong(); + } + if (percent>100) percent=100; // some bug from the back end + setProgress(QVariant(percent), + QVariant(startProgress+passSlice*(((total_index+percent/100.0))/indices.size()))); + } + else if (line.content=="done"){ + isNextIndex = true; + } + else{ + QStringList tokens = line.content.split(QChar('\t')); + + if (tokens.size()==enumMax && tokensFile=="File"){ + line.type = LINETYPE_FILE_HEADER; + } + else{ + QRegExp rx("(?:Applying gain change of )(-?\\d+)(?: to )(.*)(?:\\.\\.\\.)"); + if (!(isLeft && isRight)){ + rx=QRegExp("(?:Applying gain change of )(-?\\d+)(?: to CHANNEL \\d of )(.*)(?:\\.\\.\\.)"); + } + int pos = rx.indexIn(line.content); + if (pos > -1) { + line.type = LINETYPE_APPLY_GAIN; + QStringList list = rx.capturedTexts(); + if (list.size()==3){ + QString fileName = rx.cap(2); + int mp3Gain = rx.cap(1).toInt(); + updateModelRowByMP3GainTrack(fileName, mp3Gain); + } + }else{ + // error message? + } + } + } + if (isNextIndex){ + total_index++; + setProgress(QVariant(), + QVariant(startProgress+passSlice*(((double)total_index)/indices.size()))); + } + + qApp->processEvents(QEventLoop::AllEvents); + if (isCancelled) throw(-1); + } + } while (!in.atEnd()); + } + + throw(0); + } + catch (int e){ + if (process.state()==QProcess::Starting || process.state()==QProcess::Running){ + process.kill(); + } + setProgress(QVariant(0), QVariant()); + if (startProgress==0.0 && passSlice==100.0){ + enableGUI(); + } + } } // ----- @@ -2508,1247 +2564,1254 @@ // ----- void MainWindow::showContextMenuForWidget(const QPoint &pos){ - QStandardItem *item = getItem(tableView->currentIndex().row(), "Path/File"); - QString fileName = item->text(); - writeLog(fileName, LOGTYPE_TRACE); - - // create context menu for tableView - QMenu contextMenu(this); - bool checkBox_Maximizing = settings->value("checkBox_Maximizing", false).toBool(); - - // unfortunately original actions cannot be used, because we must know - // that the sender object is from contextMenu or MainWindow - QVector<QAction*> actions; - actions << actionTrack_Analysis; - actions << actionAlbum_Analysis; - if (checkBox_Maximizing){ - actions << actionMax_No_clip_Analysis; - } - actions << 0; - actions << actionClear_Analysis; - actions << 0; - actions << actionTrack_Gain; - actions << actionAlbum_Gain; - actions << actionConstant_Gain; - if (checkBox_Maximizing){ - actions << actionMax_No_clip_Gain_for_Each_file; - actions << actionMax_No_clip_Gain_for_Album; - } - actions << 0; - actions << actionUndo_Gain_changes; - actions << 0; - actions << actionRemove_Tags_from_files; - - if (!actionPlay_mp3_file){ - actionPlay_mp3_file = new QAction(this); - connect(actionPlay_mp3_file, SIGNAL(triggered()), this, SLOT(playMP3File())); - } - bool isToBeStopped = false; - if (mediaPlayer && mediaPlayer->state()==QMediaPlayer::State::PlayingState){ - QString playedFileName = mediaPlayer->currentMedia().canonicalUrl().path(); - - if (fileName==playedFileName){ - isToBeStopped = true; - } - } - actionPlay_mp3_file->setText(!isToBeStopped ? tr("&Play mp3 file") : tr("Stop &playing mp3 file")); - - actions << 0; - actions << actionPlay_mp3_file; - - foreach (QAction* action, actions){ - if (action){ - contextMenu.addAction(action); - action->setProperty("calledFromContextMenu", true); - }else{ - contextMenu.addSeparator(); - } - } - - contextMenu.exec(QCursor::pos()); - - foreach (QAction* action, actions){ - if (action){ - action->setProperty("calledFromContextMenu", false); - } - } + QStandardItem *item = getItem(tableView->currentIndex().row(), "Path/File"); + if (!item) { + return; + } + QString fileName = item->text(); + writeLog(fileName, LOGTYPE_TRACE); + + // create context menu for tableView + QMenu contextMenu(this); + bool checkBox_Maximizing = settings->value("checkBox_Maximizing", false).toBool(); + + // unfortunately original actions cannot be used, because we must know + // that the sender object is from contextMenu or MainWindow + QVector<QAction*> actions; + actions << actionTrack_Analysis; + actions << actionAlbum_Analysis; + if (checkBox_Maximizing){ + actions << actionMax_No_clip_Analysis; + } + actions << 0; + actions << actionClear_Analysis; + actions << 0; + actions << actionTrack_Gain; + actions << actionAlbum_Gain; + actions << actionConstant_Gain; + if (checkBox_Maximizing){ + actions << actionMax_No_clip_Gain_for_Each_file; + actions << actionMax_No_clip_Gain_for_Album; + } + actions << 0; + actions << actionUndo_Gain_changes; + actions << 0; + actions << actionRemove_Tags_from_files; + + if (!actionPlay_mp3_file){ + actionPlay_mp3_file = new QAction(this); + connect(actionPlay_mp3_file, SIGNAL(triggered()), this, SLOT(playMP3File())); + } + bool isToBeStopped = false; + if (mediaPlayer && mediaPlayer->state()==QMediaPlayer::State::PlayingState){ + QString playedFileName = mediaPlayer->currentMedia().request().url().toLocalFile(); + + if (fileName==playedFileName){ + isToBeStopped = true; + } + } + actionPlay_mp3_file->setText(!isToBeStopped ? tr("&Play mp3 file") : tr("Stop &playing mp3 file")); + + actions << 0; + actions << actionPlay_mp3_file; + + foreach (QAction* action, actions){ + if (action){ + contextMenu.addAction(action); + action->setProperty("calledFromContextMenu", true); + }else{ + contextMenu.addSeparator(); + } + } + + contextMenu.exec(QCursor::pos()); + + foreach (QAction* action, actions){ + if (action){ + action->setProperty("calledFromContextMenu", false); + } + } } // process called once in this order, the first existing one gains: // !backEndFileName: this->backEndFileName, this->backEndFixed // backEndFileName: backEndFileName, this->backEndFixed QString MainWindow::findBackEndVersionByProcess(const QString & backEndFileName){ - QString result(""); + QString result(""); + + try{ + QProcess process; + QString backEnd = !backEndFileName.isNull() ? (!backEndFileName.isEmpty() ? backEndFileName : this->getBackEndFixed()) : this->getBackEnd(); + QStringList args = QStringList() << "-v"; - try{ - QProcess process; - QString backEnd = !backEndFileName.isNull() ? (!backEndFileName.isEmpty() ? backEndFileName : this->getBackEndFixed()) : this->getBackEnd(); - QStringList args = QStringList() << "-v"; - - process.setProcessChannelMode(QProcess::MergedChannels); - QString trace = QString("%1 %2").arg(backEnd).arg(args.join(" ")); - writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); - - process.start(backEnd, args); - - if (!process.waitForStarted()){ - throw(1); - } - - if (!process.waitForFinished(1000)) throw(1); - - QByteArray newData = process.readAll(); - // expected result #1: mp3gain version 1.4.6<line end> - // expected result #2: C:\Program Files\MP3Gain\mp3gain.exe version 1.4.6<line end> - result = QString::fromLocal8Bit(newData); - writeLog(result, LOGTYPE_BACKEND); - result = result.simplified(); // removing <line end> - int index = result.indexOf(QRegExp(" version ")); - if (index == -1) - throw(1); - result = result.mid(index); - result = result.section(' ', 2, 2); // getting pure version - - throw(0); - } - catch (int e){ - } + process.setProcessChannelMode(QProcess::MergedChannels); + QString trace = QString("%1 %2").arg(backEnd).arg(args.join(" ")); + writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); - return result; + process.start(backEnd, args); + + if (!process.waitForStarted()){ + throw(1); + } + + if (!process.waitForFinished(1000)) throw(1); + + QByteArray newData = process.readAll(); + // expected result #1: mp3gain version 1.4.6<line end> + // expected result #2: C:\Program Files\MP3Gain\mp3gain.exe version 1.4.6<line end> + result = QString::fromLocal8Bit(newData); + writeLog(result, LOGTYPE_BACKEND); + result = result.simplified(); // removing <line end> + int index = result.indexOf(QRegExp(" version ")); + if (index == -1) + throw(1); + result = result.mid(index); + result = result.section(' ', 2, 2); // getting pure version + + throw(0); + } + catch (int e){ + } + + return result; } void MainWindow::showNoBackEndVersion(bool isStartBackEndDialog){ - QString msg = tr("MP3Gain back end cannot be found.\n" - "Please make it available!"); - if (isStartBackEndDialog){ - if (!backEndVersion.isEmpty()){ - msg = tr("Required MP3Gain back end version is %1 or later, but only %2 is found.\n" - "Please make a newer version available!").arg(this->requiredBackEndVersion).arg(backEndVersion); - } - QMessageBox::warning(this, appTitle, msg); - operationTime.restart(); - on_actionBack_end_triggered(); - }else{ - QMessageBox::critical(this, appTitle, msg); - operationTime.restart(); - } + QString msg = tr("MP3Gain back end cannot be found.\n" + "Please make it available!"); + if (isStartBackEndDialog){ + if (!backEndVersion.isEmpty()){ + msg = tr("Required MP3Gain back end version is %1 or later, but only %2 is found.\n" + "Please make a newer version available!").arg(this->requiredBackEndVersion).arg(backEndVersion); + } + QMessageBox::warning(this, appTitle, msg); + elapsedTimer.restart(); + on_actionBack_end_triggered(); + }else{ + QMessageBox::critical(this, appTitle, msg); + elapsedTimer.restart(); + } } void MainWindow::updateModelRowsByNewTargetNormalValue(double newTargetNormalValue){ - static double oldTargetNormalValue = settings->value("doubleSpinBox_targetNormalValue", defaultNormalTargetValue).toDouble(); - if (oldTargetNormalValue!=newTargetNormalValue){ - int mp3Gain, oldMp3Gain, newMp3Gain; - double albumVolume = 0.0; - QModelIndexList indices; - - // Tracks - for (int row=0; row<model->rowCount(); row++){ - QStandardItem* item = getItem(row, "Volume"); - if (item){ - double volume = item->data().toDouble(); - oldMp3Gain = (int)round((oldTargetNormalValue - volume)/DB); - newMp3Gain = (int)round((newTargetNormalValue - volume)/DB); - mp3Gain = oldMp3Gain-newMp3Gain; - if (mp3Gain!=0){ - updateModelRowByMP3GainTrack(getItemText(row, "Path/File"), mp3Gain, false); - } - item = getItem(row, "Album Volume"); - if (item){ - albumVolume = item->data().toDouble(); - indices << getItemIndex(row, "Path/File"); - } - } - } - - // Album - oldMp3Gain = (int)round((oldTargetNormalValue - albumVolume)/DB); - newMp3Gain = (int)round((newTargetNormalValue - albumVolume)/DB); - mp3Gain = oldMp3Gain-newMp3Gain; - updateModelRowsByMP3GainAlbum(indices, mp3Gain, false); + static double oldTargetNormalValue = settings->value("doubleSpinBox_targetNormalValue", defaultNormalTargetValue).toDouble(); + if (oldTargetNormalValue!=newTargetNormalValue){ + int mp3Gain, oldMp3Gain, newMp3Gain; + double albumVolume = 0.0; + QModelIndexList indices; + + // Tracks + for (int row=0; row<model->rowCount(); row++){ + QStandardItem* item = getItem(row, "Volume"); + if (item){ + double volume = item->data().toDouble(); + oldMp3Gain = (int)round((oldTargetNormalValue - volume)/DB); + newMp3Gain = (int)round((newTargetNormalValue - volume)/DB); + mp3Gain = oldMp3Gain-newMp3Gain; + if (mp3Gain!=0){ + updateModelRowByMP3GainTrack(getItemText(row, "Path/File"), mp3Gain, false); + } + item = getItem(row, "Album Volume"); + if (item){ + albumVolume = item->data().toDouble(); + indices << getItemIndex(row, "Path/File"); + } + } + } + + // Album + oldMp3Gain = (int)round((oldTargetNormalValue - albumVolume)/DB); + newMp3Gain = (int)round((newTargetNormalValue - albumVolume)/DB); + mp3Gain = oldMp3Gain-newMp3Gain; + updateModelRowsByMP3GainAlbum(indices, mp3Gain, false); - oldTargetNormalValue = newTargetNormalValue; - } + oldTargetNormalValue = newTargetNormalValue; + } } // menu: File/Load_Analysis_results void MainWindow::on_actionLoad_Analysis_results_triggered(){ - QString fileMainName = QFileDialog::getOpenFileName(this, tr("Open analysis file"), lastAddedFolder, tr("Comma-separated files (*.m3g *.csv);;XML files (*.xml)")); - if (fileMainName.isEmpty()) return; + QString fileMainName = QFileDialog::getOpenFileName(this, tr("Open analysis file"), lastAddedFolder, tr("Comma-separated files (*.m3g *.csv);;XML files (*.xml)")); + if (fileMainName.isEmpty()) return; - QFile fileMain; - QTextStream inFileMain; - QDomDocument docMain; - QDomElement rootElement; - QDomElement fileElement; + QFile fileMain; + QTextStream inFileMain; + QDomDocument docMain; + QDomElement rootElement; + QDomElement fileElement; - try{ - QFileInfo fi(fileMainName); + try{ + QFileInfo fi(fileMainName); bool isXML = fi.suffix().toLower() == "xml"; - fileMain.setFileName(fileMainName); - if (!isXML){ - if (!fileMain.open(QIODevice::ReadOnly)) { - throw(-1); - } - inFileMain.setDevice(&fileMain); - } - else - { - QString errorMsg; - int errorLine; - int errorColumn; - if (!docMain.setContent(&fileMain, true, &errorMsg, &errorLine, - &errorColumn)) { - QMessageBox::warning(0, tr("DOM Parser"), - tr("Parse error at line %1, column %2:\n%3") - .arg(errorLine) - .arg(errorColumn) - .arg(errorMsg)); - operationTime.restart(); - throw -1; - } - rootElement = docMain.documentElement(); - if (rootElement.tagName() != "root") - throw -1; - fileElement = rootElement.firstChildElement("file"); - } - - bool isYesToAll_FileExist = false; - bool isNoToAll_FileExist = false; - bool isYesToAll_FileLastModified = false; - bool isNoToAll_FileLastModified = false; - bool isYesToAll_FileSize = false; - bool isNoToAll_FileSize = false; - - while ( (!isXML && !inFileMain.atEnd()) || (isXML && !fileElement.isNull()) ) { - bool isAnalysisIgnored = false; - bool isConvertOk; - - // fields of file from analysis file - QString fieldPath; - QString fieldFile; - QDateTime fieldFileLastModified; - qint64 fieldFileSize = 0; - QVariant fieldMaxAmplitude(QVariant::Double); - QVariant fieldDBGain(QVariant::Double); - QVariant fieldAlbumDBGain(QVariant::Double); - - if (!isXML) { - QString line = inFileMain.readLine(); - QStringList fields = line.split(','); - if (fields.size()!=7) - throw(-1); - - fieldPath = fields0; - fieldPath.remove(QRegExp("^\"")).remove(QRegExp("\"$")); - - fieldFile = fields1; - fieldFile.remove(QRegExp("^\"")).remove(QRegExp("\"$")); - - QString value = fields2; - value.remove(QRegExp("^#")).remove(QRegExp("#$")); - fieldFileLastModified = QDateTime::fromString(value, "yyyy-MM-dd hh:mm:ss"); - - fieldFileSize = fields3.toLongLong(&isConvertOk); - - double doubleValue = fields4.toDouble(&isConvertOk); - if (isConvertOk) - fieldMaxAmplitude = QVariant(doubleValue); - - doubleValue = fields5.toDouble(&isConvertOk); - if (isConvertOk) - fieldDBGain = QVariant(doubleValue); - - doubleValue = fields6.toDouble(&isConvertOk); - if (isConvertOk) - fieldAlbumDBGain = QVariant(doubleValue); - } - else /* isXML */ { - QDomElement fieldElement = fileElement.firstChildElement(); - while (!fieldElement.isNull()) { - if (fieldElement.tagName()=="path") { - fieldPath = fieldElement.text(); - } - else if (fieldElement.tagName()=="file") { - fieldFile = fieldElement.text(); - } - else if (fieldElement.tagName()=="file_last_modified") { - fieldFileLastModified = QDateTime::fromString(fieldElement.text(), "yyyy-MM-dd hh:mm:ss"); - } - else if (fieldElement.tagName()=="file_size") { - fieldFileSize = fieldElement.text().toLongLong(&isConvertOk); - } - else if (fieldElement.tagName()=="max_amplitude") { - double doubleValue = fieldElement.text().toDouble(&isConvertOk); - if (isConvertOk) - fieldMaxAmplitude = QVariant(doubleValue); - } - else if (fieldElement.tagName()=="db_gain") { - double doubleValue = fieldElement.text().toDouble(&isConvertOk); - if (isConvertOk) - fieldDBGain = QVariant(doubleValue); - } - else if (fieldElement.tagName()=="album_db_gain") { - double doubleValue = fieldElement.text().toDouble(&isConvertOk); - if (isConvertOk) - fieldAlbumDBGain = QVariant(doubleValue); - } - fieldElement = fieldElement.nextSiblingElement(); - } - fileElement = fileElement.nextSiblingElement("file"); - } - - QString fileName = fieldPath + "/" + fieldFile; - fi = QFileInfo(fileName); - if (!fi.exists()){ - continue; - } - - if (!isAnalysisIgnored && fi.lastModified()!=fieldFileLastModified){ - if (isNoToAll_FileLastModified){ - isAnalysisIgnored = true; - } - else if (!isYesToAll_FileLastModified){ - QString text = tr("File may have been modified after analysis was saved:\n" - "%1\n" - "Load saved analysis results anyhow?").arg(fileName); - int button = QMessageBox::warning(this, appTitle, text, - QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel, - QMessageBox::Yes); - operationTime.restart(); - - if (button==QMessageBox::YesToAll){ - isYesToAll_FileLastModified = true; - } - else if (button==QMessageBox::No){ - isAnalysisIgnored = true; - } - else if (button==QMessageBox::NoToAll){ - isAnalysisIgnored = true; - isNoToAll_FileLastModified = true; - } - else if (button==QMessageBox::Cancel){ - break; - } - } - } - - if (!isAnalysisIgnored && fi.size()!=fieldFileSize){ - if (isNoToAll_FileSize){ - isAnalysisIgnored = true; - } - else if (!isYesToAll_FileSize){ - QString text = tr("File size changed after analysis was saved:\n" - "%1\n" - "Load saved analysis results anyhow?").arg(fileName); - int button = QMessageBox::warning(this, appTitle, text, - QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel, - QMessageBox::Yes); - operationTime.restart(); - - if (button==QMessageBox::YesToAll){ - isYesToAll_FileSize = true; - } - else if (button==QMessageBox::No){ - //continue; - isAnalysisIgnored = true; - } - else if (button==QMessageBox::NoToAll){ - isAnalysisIgnored = true; - isNoToAll_FileSize = true; - } - else if (button==QMessageBox::Cancel){ - break; - } - } - } - - QList<QStandardItem *> found = model->findItems(fileName, Qt::MatchExactly, 0); - bool isNew = found.count()==0; - int row = -1; - if (!isNew){ - if (isNoToAll_FileExist){ - isAnalysisIgnored = true; - } - if (false && !isYesToAll_FileExist){ // TODO: perhaps it should be activated in general settings - QString text = tr("File already exists in list:\n" - "%1\n" - "Load saved analysis results anyhow?").arg(fileName); - int button = QMessageBox::warning(this, appTitle, text, - QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel, - QMessageBox::Yes); - operationTime.restart(); - - if (button==QMessageBox::YesToAll){ - isYesToAll_FileExist = true; - } - else if (button==QMessageBox::No){ - isAnalysisIgnored = true; - } - else if (button==QMessageBox::NoToAll){ - isAnalysisIgnored = true; - isNoToAll_FileExist = true; - } - else if (button==QMessageBox::Cancel){ - break; - } - } - row = found.at(0)->row(); - }else{ - // new row/file - QStandardItem *item0 = new QStandardItem(fileName); - QStandardItem *item1 = new QStandardItem(fieldPath); - QStandardItem *item2 = new QStandardItem(fieldFile); - model->appendRow(QList<QStandardItem *>() << item0 << item1 << item2); - row = model->indexFromItem(item0).row(); - } - - if (isAnalysisIgnored) - continue; - - // load analyis result for file - if (!fieldDBGain.isNull()) { - int mp3Gain = (int)round(fieldDBGain.toDouble()/DB); - updateModelRowByAnalysisTrack(fileName, mp3Gain, fieldDBGain.toDouble(), fieldMaxAmplitude.toDouble()); - if (!fieldAlbumDBGain.isNull()) { - int mp3AlbumGain = (int)round(fieldAlbumDBGain.toDouble()/DB); - updateModelRowsByAnalysisAlbum(true, QModelIndexList() << model->item(row)->index(), - mp3AlbumGain, fieldAlbumDBGain.toDouble()); - } - } - - } // while - - throw(0); - } - catch (int e){ - if (fileMain.isOpen()) - fileMain.close(); - } + fileMain.setFileName(fileMainName); + if (!isXML){ + if (!fileMain.open(QIODevice::ReadOnly)) { + throw(-1); + } + inFileMain.setDevice(&fileMain); + } + else + { + QString errorMsg; + int errorLine; + int errorColumn; + if (!docMain.setContent(&fileMain, true, &errorMsg, &errorLine, + &errorColumn)) { + QMessageBox::warning(0, tr("DOM Parser"), + tr("Parse error at line %1, column %2:\n%3") + .arg(errorLine) + .arg(errorColumn) + .arg(errorMsg)); + elapsedTimer.restart(); + throw -1; + } + rootElement = docMain.documentElement(); + if (rootElement.tagName() != "root") + throw -1; + fileElement = rootElement.firstChildElement("file"); + } + + bool isYesToAll_FileExist = false; + bool isNoToAll_FileExist = false; + bool isYesToAll_FileLastModified = false; + bool isNoToAll_FileLastModified = false; + bool isYesToAll_FileSize = false; + bool isNoToAll_FileSize = false; + + while ( (!isXML && !inFileMain.atEnd()) || (isXML && !fileElement.isNull()) ) { + bool isAnalysisIgnored = false; + bool isConvertOk; + + // fields of file from analysis file + QString fieldPath; + QString fieldFile; + QDateTime fieldFileLastModified; + qint64 fieldFileSize = 0; + QVariant fieldMaxAmplitude(QVariant::Double); + QVariant fieldDBGain(QVariant::Double); + QVariant fieldAlbumDBGain(QVariant::Double); + + if (!isXML) { + QString line = inFileMain.readLine(); + QStringList fields = line.split(','); + if (fields.size()!=7) + throw(-1); + + fieldPath = fields0; + fieldPath.remove(QRegExp("^\"")).remove(QRegExp("\"$")); + + fieldFile = fields1; + fieldFile.remove(QRegExp("^\"")).remove(QRegExp("\"$")); + + QString value = fields2; + value.remove(QRegExp("^#")).remove(QRegExp("#$")); + fieldFileLastModified = QDateTime::fromString(value, "yyyy-MM-dd hh:mm:ss"); + + fieldFileSize = fields3.toLongLong(&isConvertOk); + + double doubleValue = fields4.toDouble(&isConvertOk); + if (isConvertOk) + fieldMaxAmplitude = QVariant(doubleValue); + + doubleValue = fields5.toDouble(&isConvertOk); + if (isConvertOk) + fieldDBGain = QVariant(doubleValue); + + doubleValue = fields6.toDouble(&isConvertOk); + if (isConvertOk) + fieldAlbumDBGain = QVariant(doubleValue); + } + else /* isXML */ { + QDomElement fieldElement = fileElement.firstChildElement(); + while (!fieldElement.isNull()) { + if (fieldElement.tagName()=="path") { + fieldPath = fieldElement.text(); + } + else if (fieldElement.tagName()=="file") { + fieldFile = fieldElement.text(); + } + else if (fieldElement.tagName()=="file_last_modified") { + fieldFileLastModified = QDateTime::fromString(fieldElement.text(), "yyyy-MM-dd hh:mm:ss"); + } + else if (fieldElement.tagName()=="file_size") { + fieldFileSize = fieldElement.text().toLongLong(&isConvertOk); + } + else if (fieldElement.tagName()=="max_amplitude") { + double doubleValue = fieldElement.text().toDouble(&isConvertOk); + if (isConvertOk) + fieldMaxAmplitude = QVariant(doubleValue); + } + else if (fieldElement.tagName()=="db_gain") { + double doubleValue = fieldElement.text().toDouble(&isConvertOk); + if (isConvertOk) + fieldDBGain = QVariant(doubleValue); + } + else if (fieldElement.tagName()=="album_db_gain") { + double doubleValue = fieldElement.text().toDouble(&isConvertOk); + if (isConvertOk) + fieldAlbumDBGain = QVariant(doubleValue); + } + fieldElement = fieldElement.nextSiblingElement(); + } + fileElement = fileElement.nextSiblingElement("file"); + } + + QString fileName = fieldPath + "/" + fieldFile; + fi = QFileInfo(fileName); + if (!fi.exists()){ + continue; + } + + if (!isAnalysisIgnored && fi.lastModified()!=fieldFileLastModified){ + if (isNoToAll_FileLastModified){ + isAnalysisIgnored = true; + } + else if (!isYesToAll_FileLastModified){ + QString text = tr("File may have been modified after analysis was saved:\n" + "%1\n" + "Load saved analysis results anyhow?").arg(fileName); + int button = QMessageBox::warning(this, appTitle, text, + QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel, + QMessageBox::Yes); + elapsedTimer.restart(); + + if (button==QMessageBox::YesToAll){ + isYesToAll_FileLastModified = true; + } + else if (button==QMessageBox::No){ + isAnalysisIgnored = true; + } + else if (button==QMessageBox::NoToAll){ + isAnalysisIgnored = true; + isNoToAll_FileLastModified = true; + } + else if (button==QMessageBox::Cancel){ + break; + } + } + } + + if (!isAnalysisIgnored && fi.size()!=fieldFileSize){ + if (isNoToAll_FileSize){ + isAnalysisIgnored = true; + } + else if (!isYesToAll_FileSize){ + QString text = tr("File size changed after analysis was saved:\n" + "%1\n" + "Load saved analysis results anyhow?").arg(fileName); + int button = QMessageBox::warning(this, appTitle, text, + QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel, + QMessageBox::Yes); + elapsedTimer.restart(); + + if (button==QMessageBox::YesToAll){ + isYesToAll_FileSize = true; + } + else if (button==QMessageBox::No){ + //continue; + isAnalysisIgnored = true; + } + else if (button==QMessageBox::NoToAll){ + isAnalysisIgnored = true; + isNoToAll_FileSize = true; + } + else if (button==QMessageBox::Cancel){ + break; + } + } + } + + QList<QStandardItem *> found = model->findItems(fileName, Qt::MatchExactly, 0); + bool isNew = found.count()==0; + int row = -1; + if (!isNew){ + if (isNoToAll_FileExist){ + isAnalysisIgnored = true; + } + if (false && !isYesToAll_FileExist){ // TODO: perhaps it should be activated in general settings + QString text = tr("File already exists in list:\n" + "%1\n" + "Load saved analysis results anyhow?").arg(fileName); + int button = QMessageBox::warning(this, appTitle, text, + QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel, + QMessageBox::Yes); + elapsedTimer.restart(); + + if (button==QMessageBox::YesToAll){ + isYesToAll_FileExist = true; + } + else if (button==QMessageBox::No){ + isAnalysisIgnored = true; + } + else if (button==QMessageBox::NoToAll){ + isAnalysisIgnored = true; + isNoToAll_FileExist = true; + } + else if (button==QMessageBox::Cancel){ + break; + } + } + row = found.at(0)->row(); + }else{ + // new row/file + QStandardItem *item0 = new QStandardItem(fileName); + QStandardItem *item1 = new QStandardItem(fieldPath); + QStandardItem *item2 = new QStandardItem(fieldFile); + model->appendRow(QList<QStandardItem *>() << item0 << item1 << item2); + row = model->indexFromItem(item0).row(); + } + + if (isAnalysisIgnored) + continue; + + // load analyis result for file + if (!fieldDBGain.isNull()) { + int mp3Gain = (int)round(fieldDBGain.toDouble()/DB); + updateModelRowByAnalysisTrack(fileName, mp3Gain, fieldDBGain.toDouble(), fieldMaxAmplitude.toDouble()); + if (!fieldAlbumDBGain.isNull()) { + int mp3AlbumGain = (int)round(fieldAlbumDBGain.toDouble()/DB); + updateModelRowsByAnalysisAlbum(true, QModelIndexList() << model->item(row)->index(), + mp3AlbumGain, fieldAlbumDBGain.toDouble()); + } + } + + } // while + + throw(0); + } + catch (int e){ + if (fileMain.isOpen()) + fileMain.close(); + } } // menu: File/Save_Analysis_results void MainWindow::on_actionSave_Analysis_results_triggered(){ - QString fileMainName = QFileDialog::getSaveFileName(this, tr("Save analysis file"), lastAddedFolder, tr("Comma-separated files (*.m3g *.csv);;XML files (*.xml)")); - if (fileMainName.isEmpty()) return; + QString fileMainName = QFileDialog::getSaveFileName(this, tr("Save analysis file"), lastAddedFolder, tr("Comma-separated files (*.m3g *.csv);;XML files (*.xml)")); + if (fileMainName.isEmpty()) return; - QFile fileMain; - try{ - QFileInfo fi(fileMainName); - if (fi.suffix().isEmpty()) fileMainName += ".m3g"; + QFile fileMain; + try{ + QFileInfo fi(fileMainName); + if (fi.suffix().isEmpty()) fileMainName += ".m3g"; bool isXML = fi.suffix().toLower() == "xml"; - fileMain.setFileName(fileMainName); - if (!fileMain.open(QIODevice::WriteOnly)) { - throw(-1); - } - - QTextStream out(&fileMain); - QModelIndexList indices = getModelIndices(); - - if (isXML) - out << "<root>" << endl; - foreach(QModelIndex index, indices) { - int row = model->itemFromIndex(index)->row(); - QStandardItem *item = 0; - - if (isXML) - out << "\t<file>" << endl; - - item = getItem(row, "Path"); - if (item){ - if (isXML) - out << "\t\t<path>" << item->text().toHtmlEscaped() << "</path>" << endl; - else - out << "\"" << item->text() << "\"" << ","; - } - item = getItem(row, "File"); - if (item){ - if (isXML) - out << "\t\t<file>" << item->text().toHtmlEscaped() << "</file>" << endl; - else - out << "\"" << item->text() << "\"" << ","; - } - item = getItem(row, "Path/File"); - if (item) { - QFileInfo fi(item->text()); - QDateTime dateTime = fi.lastModified(); - if (isXML) - out << "\t\t<file_last_modified>" << dateTime.toString("yyyy-MM-dd hh:mm:ss").toHtmlEscaped() << "</file_last_modified>" << endl; - else - out << "#" << dateTime.toString("yyyy-MM-dd hh:mm:ss") << "#" << ","; - if (isXML) - out << "\t\t<file_size>" << fi.size() << "</file_size>" << endl; - else - out << fi.size() << ","; - } - item = getItem(row, "Max Amplitude"); - if (item){ - double maxAmplitude = item->data().toDouble(); - QString maxAmplitudeStr = QString("%1").arg(maxAmplitude, 0, 'f', 3); - if (isXML) - out << "\t\t<max_amplitude>" << maxAmplitudeStr.toHtmlEscaped() << "</max_amplitude>" << endl; - else - out << maxAmplitudeStr << ","; - } - item = getItem(row, "dBGain"); - if (item){ - double dBGain = item->data().toDouble(); - QString dBGainStr = QString("%1").arg(dBGain, 0, 'f', 3); - if (isXML) - out << "\t\t<db_gain>" << dBGainStr.toHtmlEscaped() << "</db_gain>" << endl; - else - out << dBGainStr << ","; - } - item = getItem(row, "Album dBGain"); - if (item){ - double AlbumdBGain = item->data().toDouble(); - QString AlbumdBGainStr = QString("%1").arg(AlbumdBGain, 0, 'f', 3); - if (isXML) - out << "\t\t<album_db_gain>" << AlbumdBGainStr.toHtmlEscaped() << "</album_db_gain>" << endl; - else - out << AlbumdBGainStr; - } - if (isXML) - out << "\t</file>" << endl; - else - out << endl; - } - if (isXML) - out << "</root>" << endl; - - throw(0); - } - catch (int e){ - if (fileMain.isOpen()) - fileMain.close(); - } + fileMain.setFileName(fileMainName); + if (!fileMain.open(QIODevice::WriteOnly)) { + throw(-1); + } + + QTextStream out(&fileMain); + QModelIndexList indices = getModelIndices(); + + if (isXML) + out << "<root>" << Qt::endl; + foreach(QModelIndex index, indices) { + int row = model->itemFromIndex(index)->row(); + QStandardItem *item = 0; + + if (isXML) + out << "\t<file>" << Qt::endl; + + item = getItem(row, "Path"); + if (item){ + if (isXML) + out << "\t\t<path>" << item->text().toHtmlEscaped() << "</path>" << Qt::endl; + else + out << "\"" << item->text() << "\"" << ","; + } + item = getItem(row, "File"); + if (item){ + if (isXML) + out << "\t\t<file>" << item->text().toHtmlEscaped() << "</file>" << Qt::endl; + else + out << "\"" << item->text() << "\"" << ","; + } + item = getItem(row, "Path/File"); + if (item) { + QFileInfo fi(item->text()); + QDateTime dateTime = fi.lastModified(); + if (isXML) + out << "\t\t<file_last_modified>" << dateTime.toString("yyyy-MM-dd hh:mm:ss").toHtmlEscaped() << "</file_last_modified>" << Qt::endl; + else + out << "#" << dateTime.toString("yyyy-MM-dd hh:mm:ss") << "#" << ","; + if (isXML) + out << "\t\t<file_size>" << fi.size() << "</file_size>" << Qt::endl; + else + out << fi.size() << ","; + } + item = getItem(row, "Max Amplitude"); + if (item){ + double maxAmplitude = item->data().toDouble(); + QString maxAmplitudeStr = QString("%1").arg(maxAmplitude, 0, 'f', 3); + if (isXML) + out << "\t\t<max_amplitude>" << maxAmplitudeStr.toHtmlEscaped() << "</max_amplitude>" << Qt::endl; + else + out << maxAmplitudeStr << ","; + } + item = getItem(row, "dBGain"); + if (item){ + double dBGain = item->data().toDouble(); + QString dBGainStr = QString("%1").arg(dBGain, 0, 'f', 3); + if (isXML) + out << "\t\t<db_gain>" << dBGainStr.toHtmlEscaped() << "</db_gain>" << Qt::endl; + else + out << dBGainStr << ","; + } + item = getItem(row, "Album dBGain"); + if (item){ + double AlbumdBGain = item->data().toDouble(); + QString AlbumdBGainStr = QString("%1").arg(AlbumdBGain, 0, 'f', 3); + if (isXML) + out << "\t\t<album_db_gain>" << AlbumdBGainStr.toHtmlEscaped() << "</album_db_gain>" << Qt::endl; + else + out << AlbumdBGainStr; + } + if (isXML) + out << "\t</file>" << Qt::endl; + else + out << Qt::endl; + } + if (isXML) + out << "</root>" << Qt::endl; + + throw(0); + } + catch (int e){ + if (fileMain.isOpen()) + fileMain.close(); + } } // menu: File/Add_files void MainWindow::on_actionAdd_Files_triggered(){ - QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Add MP3 file(s)"), lastAddedFolder, tr("MP3 files (*.mp3)")); + QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Add MP3 file(s)"), lastAddedFolder, tr("MP3 files (*.mp3)")); addFiles(fileNames); } // enlist model with mp3 files of folder (it may be recursive) // menu: File/Add_folder void MainWindow::on_actionAdd_Folder_triggered(){ - QString dir = QFileDialog::getExistingDirectory(this, tr("Add Directory"), lastAddedFolder, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + QString dir = QFileDialog::getExistingDirectory(this, tr("Add Directory"), lastAddedFolder, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); addFolder(dir); } // menu: File/Select_all_files void MainWindow::on_actionSelect_All_Files_triggered(){ - tableView->selectAll(); + tableView->selectAll(); } // menu: File/Select_no_files void MainWindow::on_actionSelect_No_Files_triggered(){ - tableView->clearSelection(); + tableView->clearSelection(); } // menu: File/Invert_selection void MainWindow::on_actionInvert_selection_triggered(){ - QItemSelectionModel *selectionModel = tableView->selectionModel(); - QModelIndex topLeft = model->index(0, 0); - QModelIndex bottomRight = model->index(model->rowCount()-1, model->columnCount()-1); - QItemSelection selection(topLeft, bottomRight); - selectionModel->select(selection, QItemSelectionModel::Toggle); + QItemSelectionModel *selectionModel = tableView->selectionModel(); + QModelIndex topLeft = model->index(0, 0); + QModelIndex bottomRight = model->index(model->rowCount()-1, model->columnCount()-1); + QItemSelection selection(topLeft, bottomRight); + selectionModel->select(selection, QItemSelectionModel::Toggle); } // menu: File/Clear_selected_files void MainWindow::on_actionClear_Selected_Files_triggered(){ - double startProgress = progressBar_Total->doubleValue(); - const double passSlice = 100; + double startProgress = progressBar_Total->doubleValue(); + const double passSlice = 100; - try { - if (startProgress==0.0 && passSlice==100.0) disableGUI(); - QItemSelectionModel *selectionModel = tableView->selectionModel(); - QModelIndexList indices = selectionModel->selectedRows(); - if (indices.isEmpty()) throw(0); - - // index.row() is not updated if an element is deleted from the model - // therefore the rows must be deleted from the higher to the lower positions - QList<int> list; - foreach(QModelIndex index, indices) { - list.append(index.row()); - } - qSort(list.begin(), list.end(), qGreater<int>()); // inverse sort - - for (int i = 0; i < list.size(); ++i){ - model->removeRow(listi); - setProgress(QVariant(), QVariant(i+1)); - qApp->processEvents(QEventLoop::ExcludeUserInputEvents); - if (isCancelled) throw(-1); - } - - refreshMenu(); - - throw(0); - } - catch (int e){ - if (startProgress==0.0 && passSlice==100.0){ - enableGUI(); - } - } + try { + if (startProgress==0.0 && passSlice==100.0) disableGUI(); + QItemSelectionModel *selectionModel = tableView->selectionModel(); + QModelIndexList indices = selectionModel->selectedRows(); + if (indices.isEmpty()) throw(0); + + // index.row() is not updated if an element is deleted from the model + // therefore the rows must be deleted from the higher to the lower positions + QList<int> list; + foreach(QModelIndex index, indices) { + list.append(index.row()); + } + std::sort(list.begin(), list.end(), std::greater<int>()); + + for (int i = 0; i < list.size(); ++i){ + model->removeRow(listi); + setProgress(QVariant(), QVariant(i+1)); + qApp->processEvents(QEventLoop::ExcludeUserInputEvents); + if (isCancelled) throw(-1); + } + + refreshMenu(); + + throw(0); + } + catch (int e){ + if (startProgress==0.0 && passSlice==100.0){ + enableGUI(); + } + } } // menu: File/Clear_all_files void MainWindow::on_actionClear_All_files_triggered(){ - model->removeRows(0, model->rowCount()); - refreshMenu(); + model->removeRows(0, model->rowCount()); + refreshMenu(); } // menu: Analysis/Track_analysis void MainWindow::on_actionTrack_Analysis_triggered(){ - updateStatusBar(tr("Track analysis started...")); - runAnalysis(getModelIndices(), false, false); - updateStatusBar(""); + updateStatusBar(tr("Track analysis started...")); + runAnalysis(getModelIndices(), false, false); + updateStatusBar(""); } // menu: Analysis/Album_analysis void MainWindow::on_actionAlbum_Analysis_triggered(){ - runAnalysis(getModelIndices(), true, false); + runAnalysis(getModelIndices(), true, false); } // menu: Analysis/Max No-clip Analysis void MainWindow::on_actionMax_No_clip_Analysis_triggered(){ - runAnalysis(getModelIndices(), false, true); + runAnalysis(getModelIndices(), false, true); } // menu: Analysis/Clear_analysis void MainWindow::on_actionClear_Analysis_triggered(){ - double startProgress = progressBar_Total->doubleValue(); - const double passSlice = 100.0; + double startProgress = progressBar_Total->doubleValue(); + const double passSlice = 100.0; - try { - if (startProgress==0.0 && passSlice==100.0) disableGUI(); - QModelIndexList indices = getModelIndices(); - if (indices.isEmpty()) throw(0); - - bool isConfirmSuppressed = settings->value("clearAnalysis_ConfirmSuppressed", false).toBool(); - if (!isConfirmSuppressed){ - int r = MyMessageBox::question(this, appTitle+" - "+tr("Clear Analysis?"), - tr("This will clear all analysis results.\n" - "Are you sure?"), - tr("Don't ask me again"), - isConfirmSuppressed, - QMessageBox::Yes | QMessageBox::No, - QMessageBox::No); - operationTime.restart(); - if (r == QMessageBox::No) { - throw(0); - } - if (isConfirmSuppressed){ - settings->setValue("clearAnalysis_ConfirmSuppressed", true); - } - } - - for (int i = 0; i<indices.size(); i++) { - int row = model->itemFromIndex(indices.at(i))->row(); - - // columns to be get rid of their colors - QStringList columns = QStringList() << "Path/File" << "Path" << "File"; - foreach (QString element, columns){ - QStandardItem *item = getItem(row, element); - item->setForeground(QBrush(QColor(0,0,0))); - } - // columns to be deleted - columns = QStringList() << "Volume" << "Max Amplitude" << "clipping" - << "Track Gain" << "dBGain" << "clip(Track)" - << "Max Noclip Gain"<< "Album Volume" << "Album Max Amplitude" - << "Album Gain" << "Album dBGain" << "clip(Album)"; - foreach (QString element, columns){ - QStandardItem *item = getItem(row, element); - if (item) { - item->setData(0); // before item delete to enable automatic model/view refresh - delete item; - } - } - - setProgress(QVariant(), - QVariant(startProgress+passSlice*(((double)(i+1))/indices.size()))); - qApp->processEvents(QEventLoop::AllEvents); - if (isCancelled) throw(-1); - } - throw(0); - } - catch (int e){ - if (startProgress==0.0 && passSlice==100.0){ - enableGUI(); - } - } + try { + if (startProgress==0.0 && passSlice==100.0) disableGUI(); + QModelIndexList indices = getModelIndices(); + if (indices.isEmpty()) throw(0); + + bool isConfirmSuppressed = settings->value("clearAnalysis_ConfirmSuppressed", false).toBool(); + if (!isConfirmSuppressed){ + int r = MyMessageBox::question(this, appTitle+" - "+tr("Clear Analysis?"), + tr("This will clear all analysis results.\n" + "Are you sure?"), + tr("Don't ask me again"), + isConfirmSuppressed, + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No); + elapsedTimer.restart(); + if (r == QMessageBox::No) { + throw(0); + } + if (isConfirmSuppressed){ + settings->setValue("clearAnalysis_ConfirmSuppressed", true); + } + } + + for (int i = 0; i<indices.size(); i++) { + int row = model->itemFromIndex(indices.at(i))->row(); + + // columns to be get rid of their colors + QStringList columns = QStringList() << "Path/File" << "Path" << "File"; + foreach (QString element, columns){ + QStandardItem *item = getItem(row, element); + item->setForeground(QBrush(QColor(0,0,0))); + } + // columns to be deleted + columns = QStringList() << "Volume" << "Max Amplitude" << "clipping" + << "Track Gain" << "dBGain" << "clip(Track)" + << "Max Noclip Gain"<< "Album Volume" << "Album Max Amplitude" + << "Album Gain" << "Album dBGain" << "clip(Album)"; + foreach (QString element, columns){ + QStandardItem *item = getItem(row, element); + if (item) { + item->setData(0); // before item delete to enable automatic model/view refresh + delete item; + } + } + + setProgress(QVariant(), + QVariant(startProgress+passSlice*(((double)(i+1))/indices.size()))); + qApp->processEvents(QEventLoop::AllEvents); + if (isCancelled) throw(-1); + } + throw(0); + } + catch (int e){ + if (startProgress==0.0 && passSlice==100.0){ + enableGUI(); + } + } } // menu: Modify_gain/Track_gain void MainWindow::on_actionTrack_Gain_triggered(){ - runGain(getModelIndices(), false); + runGain(getModelIndices(), false); } // menu: Modify_gain/Album_gain void MainWindow::on_actionAlbum_Gain_triggered(){ - runGain(getModelIndices(), true); + runGain(getModelIndices(), true); } // menu: Modify_gain/Constant_gain void MainWindow::on_actionConstant_Gain_triggered(){ - try { - QModelIndexList indices = getModelIndices(); - if (indices.isEmpty()) throw(0); - - ConstantGainChangeDialog dialog(this); - if (!dialog.exec()) throw(0); - - int mp3Gain = dialog.horizontalSlider_constGainChange->value(); - if (mp3Gain!=0){ - bool channelLeft = !dialog.groupBox_onlyOneChannel->isChecked() || dialog.radioButton_channelLeft->isChecked(); - bool channelRight = !dialog.groupBox_onlyOneChannel->isChecked() || dialog.radioButton_channelRight->isChecked(); - runConstantGain(indices, mp3Gain, channelLeft, channelRight); - } - throw(0); - } - catch (int e){ - } + try { + QModelIndexList indices = getModelIndices(); + if (indices.isEmpty()) throw(0); + + ConstantGainChangeDialog dialog(this); + if (!dialog.exec()) throw(0); + + int mp3Gain = dialog.horizontalSlider_constGainChange->value(); + if (mp3Gain!=0){ + bool channelLeft = !dialog.groupBox_onlyOneChannel->isChecked() || dialog.radioButton_channelLeft->isChecked(); + bool channelRight = !dialog.groupBox_onlyOneChannel->isChecked() || dialog.radioButton_channelRight->isChecked(); + runConstantGain(indices, mp3Gain, channelLeft, channelRight); + } + throw(0); + } + catch (int e){ + } } // menu: Modify_gain/Max No-clip Gain for Each file // Description: This function is rather slow, because mp3gain backend // must be called on each mp3 file one by one. void MainWindow::on_actionMax_No_clip_Gain_for_Each_file_triggered(){ - double startProgress = progressBar_Total->doubleValue(); - const double passSlice = 100.0; + double startProgress = progressBar_Total->doubleValue(); + const double passSlice = 100.0; - try { - if (startProgress==0.0 && passSlice==100.0) disableGUI(); - QModelIndexList indices = getModelIndices(); - if (indices.isEmpty()) throw(0); - - // calculate passes - QList<int> passes = operationMap"max_no_clip_gain_for_each_file"; - - // pass #1 - runAnalysis(indices, false, true, false, passes.at(0)); - - foreach(QModelIndex index, indices) { - int row = model->itemFromIndex(index)->row(); - QStandardItem *item = getItem(row, "Max Noclip Gain"); - int maxNoclipGain = (int)round(item->data().toDouble()/DB); - if (maxNoclipGain!=0){ - // pass #2(,3,...) - runConstantGain(QModelIndexList() << index, maxNoclipGain, true, true, passes.at(1)/indices.size()); - } - } - throw(0); - } - catch (int e){ - if (startProgress==0.0 && passSlice==100.0){ - enableGUI(); - } - } + try { + if (startProgress==0.0 && passSlice==100.0) disableGUI(); + QModelIndexList indices = getModelIndices(); + if (indices.isEmpty()) throw(0); + + // calculate passes + QList<int> passes = operationMap"max_no_clip_gain_for_each_file"; + + // pass #1 + runAnalysis(indices, false, true, false, passes.at(0)); + + foreach(QModelIndex index, indices) { + int row = model->itemFromIndex(index)->row(); + QStandardItem *item = getItem(row, "Max Noclip Gain"); + if (item){ + int maxNoclipGain = (int)round(item->data().toDouble()/DB); + if (maxNoclipGain!=0){ + // pass #2(,3,...) + runConstantGain(QModelIndexList() << index, maxNoclipGain, true, true, passes.at(1)/indices.size()); + } + } + } + throw(0); + } + catch (int e){ + if (startProgress==0.0 && passSlice==100.0){ + enableGUI(); + } + } } // menu: Modify_gain/Max No-clip Gain for Album void MainWindow::on_actionMax_No_clip_Gain_for_Album_triggered(){ - double startProgress = progressBar_Total->doubleValue(); - const double passSlice = 100.0; + double startProgress = progressBar_Total->doubleValue(); + const double passSlice = 100.0; - try { - if (startProgress==0.0 && passSlice==100.0) disableGUI(); - QModelIndexList indices = getModelIndices(); - if (indices.isEmpty()) throw(0); - - // calculate passes - QList<int> passes = operationMap"max_no_clip_gain_for_album"; - - // pass #1 - runAnalysis(indices, false, true, false, passes.at(0)); - - int minMaxNoclipGain = INT_MAX; - foreach(QModelIndex index, indices) { - int row = model->itemFromIndex(index)->row(); - QStandardItem *item = getItem(row, "Max Noclip Gain"); - int maxNoclipGain = (int)round(item->data().toDouble()/DB); - if (maxNoclipGain<minMaxNoclipGain){ - minMaxNoclipGain = maxNoclipGain; - } - } - - if (minMaxNoclipGain!=INT_MAX && minMaxNoclipGain!=0.0){ - // pass #2 - runConstantGain(indices, minMaxNoclipGain, true, true, (double)passes.at(1)); - } - - throw(0); - } - catch (int e){ - if (startProgress==0.0 && passSlice==100.0){ - enableGUI(); - } - } + try { + if (startProgress==0.0 && passSlice==100.0) disableGUI(); + QModelIndexList indices = getModelIndices(); + if (indices.isEmpty()) throw(0); + + // calculate passes + QList<int> passes = operationMap"max_no_clip_gain_for_album"; + + // pass #1 + runAnalysis(indices, false, true, false, passes.at(0)); + + int minMaxNoclipGain = INT_MAX; + foreach(QModelIndex index, indices) { + int row = model->itemFromIndex(index)->row(); + QStandardItem *item = getItem(row, "Max Noclip Gain"); + if (item){ + int maxNoclipGain = (int)round(item->data().toDouble()/DB); + if (maxNoclipGain<minMaxNoclipGain){ + minMaxNoclipGain = maxNoclipGain; + } + } + } + + if (minMaxNoclipGain!=INT_MAX && minMaxNoclipGain!=0){ + // pass #2 + runConstantGain(indices, minMaxNoclipGain, true, true, (double)passes.at(1)); + } + + throw(0); + } + catch (int e){ + if (startProgress==0.0 && passSlice==100.0){ + enableGUI(); + } + } } // menu: Modify_gain/Undo_gain_changes void MainWindow::on_actionUndo_Gain_changes_triggered(){ - QProcess process; - double startProgress = progressBar_Total->doubleValue(); - const double passSlice = 100.0; - - try { - if (startProgress==0.0 && passSlice==100.0) disableGUI(); - QModelIndexList indices = getModelIndices(); - if (indices.isEmpty()) throw(0); - - QStringList args; - args << "-u"; // undo changes made by mp3gain (based on stored tag info) - args << getArgumentsByOptions(); - - foreach(QModelIndex index, indices) { - int row = model->itemFromIndex(index)->row(); - QStandardItem *item = getItem(row, "Path/File"); - QString fileName = item->text(); - args << fileName; - } - - process.setProcessChannelMode(QProcess::MergedChannels); - QString trace = QString("%1 %2").arg(this->getBackEnd()).arg(args.join(" ")); - writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); - - process.start(this->getBackEnd(), args); - - if (!process.waitForStarted()){ - showNoBackEndVersion(); - throw(1); - } - - // File left global_gain change right global_gain change - /* - expected undo output is a tab separated table, integer value is the mp3 gain (* 1.5 = real db gain) - D:\Users\Brazso\music\test_mp3>mp3gain -u -o "Arash - Boro Boro.mp3" "Austin Powers - Theme Song.mp3" - File left global_gain change right global_gain change - Arash - Boro Boro.mp3 7 7 - 1% of 10533134 bytes written (optional, if not 0 gain is found) - 3% of 10533134 bytes written - ... - 99% of 10533134 bytes written - Austin Powers - Theme Song.mp3 0 0 - 2% of 6504011 bytes written (optional, if not 0 gain is found) - 5% of 6504011 bytes written - ... - 97% of 6504011 bytes written - */ - enum resultColumns { File, left_global_gain_change, right_global_gain_change, enumMax }; - int total_index = 0; - Line prevLine; - - for (bool isAfterLast = false, isWaitForReadyRead = false; - (isWaitForReadyRead = process.waitForReadyRead(-1)) || !isAfterLast; - isAfterLast = !isWaitForReadyRead ) { - - QByteArray newData = process.readAllStandardOutput(); - QString result = QString::fromLocal8Bit(newData); - - QTextStream in(&result); - do { - Line line; - line.content = in.readLine(); - if (line.content==QString::null || line.content.isEmpty()) - continue; - - QStringList lines = line.content.split(QChar('\r'), QString::SkipEmptyParts); - foreach (line.content, lines){ - if (line.content.trimmed().isEmpty()){ - continue; - } - - writeLog(line.content, LOGTYPE_BACKEND, line.content.endsWith("bytes written") ? 2 : 1); - bool isNextIndex = false; - line.errType = hasError(line.content); - - if (line.errType){ - line.type = LINETYPE_ERROR; - if (line.errType!=ERRTYPE_SUPPRESSED){ - isNextIndex = true; // for the time being all errors increase the iterator - } - } - else if (line.content.endsWith("bytes written")){ - line.type = LINETYPE_WRITTEN; - // " 12% of 7260121 bytes written" - int percent = 0; - QRegExp rx("(?:^ *)(\\d+)(?:% of )(\\d+)(?: bytes written$)"); - int pos = rx.indexIn(line.content); - if (pos > -1) { - percent = rx.cap(1).toInt(); - //long fileSize = rx.cap(2).toLong(); - } - if (percent>100) percent=100; // some bug from the back end - setProgress(QVariant(percent), - QVariant(startProgress+passSlice*(((total_index+percent/100.0))/indices.size()))); - } - else{ - QStringList tokens = line.content.split(QChar('\t')); - - if (tokens.size()==enumMax){ - if (tokensFile=="File"){ - line.type = LINETYPE_FILE_HEADER; - } - else{ - line.type = LINETYPE_FILE_CONTENT; - updateModelRowByMP3GainTrack(tokensFile, (tokensleft_global_gain_change.toInt()+tokensright_global_gain_change.toInt())/2); - if (prevLine.type!=LINETYPE_FILE_HEADER && !prevLine.errType) - isNextIndex = true; - } - } - } - - if (isNextIndex){ - total_index++; - setProgress(QVariant(), - QVariant(startProgress+passSlice*(((double)total_index)/indices.size()))); - } - - qApp->processEvents(QEventLoop::AllEvents); - if (isCancelled) throw(-1); - prevLine = line; - } // foreach - } while (!in.atEnd()); - } - throw(0); - } - catch (int e){ - if (process.state()==QProcess::Starting || process.state()==QProcess::Running){ - process.kill(); - } - setProgress(QVariant(0), QVariant()); - if (startProgress==0.0 && passSlice==100.0){ - enableGUI(); - } - } + QProcess process; + double startProgress = progressBar_Total->doubleValue(); + const double passSlice = 100.0; + + try { + if (startProgress==0.0 && passSlice==100.0) disableGUI(); + QModelIndexList indices = getModelIndices(); + if (indices.isEmpty()) throw(0); + + QStringList args; + args << "-u"; // undo changes made by mp3gain (based on stored tag info) + args << getArgumentsByOptions(); + + foreach(QModelIndex index, indices) { + int row = model->itemFromIndex(index)->row(); + QStandardItem *item = getItem(row, "Path/File"); + QString fileName = item->text(); + args << fileName; + } + + process.setProcessChannelMode(QProcess::MergedChannels); + QString trace = QString("%1 %2").arg(this->getBackEnd()).arg(args.join(" ")); + writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); + + process.start(this->getBackEnd(), args); + + if (!process.waitForStarted()){ + showNoBackEndVersion(); + throw(1); + } + + // File left global_gain change right global_gain change + /* + expected undo output is a tab separated table, integer value is the mp3 gain (* 1.5 = real db gain) + D:\Users\Brazso\music\test_mp3>mp3gain -u -o "Arash - Boro Boro.mp3" "Austin Powers - Theme Song.mp3" + File left global_gain change right global_gain change + Arash - Boro Boro.mp3 7 7 + 1% of 10533134 bytes written (optional, if not 0 gain is found) + 3% of 10533134 bytes written + ... + 99% of 10533134 bytes written + Austin Powers - Theme Song.mp3 0 0 + 2% of 6504011 bytes written (optional, if not 0 gain is found) + 5% of 6504011 bytes written + ... + 97% of 6504011 bytes written + */ + enum resultColumns { File, left_global_gain_change, right_global_gain_change, enumMax }; + int total_index = 0; + Line prevLine; + + for (bool isAfterLast = false, isWaitForReadyRead = false; + (isWaitForReadyRead = process.waitForReadyRead(-1)) || !isAfterLast; + isAfterLast = !isWaitForReadyRead ) { + + QByteArray newData = process.readAllStandardOutput(); + QString result = QString::fromLocal8Bit(newData); + + QTextStream in(&result); + do { + Line line; + line.content = in.readLine(); + if (line.content.isNull() || line.content.isEmpty()) + continue; + + QStringList lines = line.content.split(QChar('\r'), Qt::SkipEmptyParts); + foreach (line.content, lines){ + if (line.content.trimmed().isEmpty()){ + continue; + } + + writeLog(line.content, LOGTYPE_BACKEND, line.content.endsWith("bytes written") ? 2 : 1); + bool isNextIndex = false; + line.errType = hasError(line.content); + + if (line.errType){ + line.type = LINETYPE_ERROR; + if (line.errType!=ERRTYPE_SUPPRESSED){ + isNextIndex = true; // for the time being all errors increase the iterator + } + } + else if (line.content.endsWith("bytes written")){ + line.type = LINETYPE_WRITTEN; + // " 12% of 7260121 bytes written" + int percent = 0; + QRegExp rx("(?:^ *)(\\d+)(?:% of )(\\d+)(?: bytes written$)"); + int pos = rx.indexIn(line.content); + if (pos > -1) { + percent = rx.cap(1).toInt(); + //long fileSize = rx.cap(2).toLong(); + } + if (percent>100) percent=100; // some bug from the back end + setProgress(QVariant(percent), + QVariant(startProgress+passSlice*(((total_index+percent/100.0))/indices.size()))); + } + else{ + QStringList tokens = line.content.split(QChar('\t')); + + if (tokens.size()==enumMax){ + if (tokensFile=="File"){ + line.type = LINETYPE_FILE_HEADER; + } + else{ + line.type = LINETYPE_FILE_CONTENT; + updateModelRowByMP3GainTrack(tokensFile, (tokensleft_global_gain_change.toInt()+tokensright_global_gain_change.toInt())/2); + if (prevLine.type!=LINETYPE_FILE_HEADER && !prevLine.errType) + isNextIndex = true; + } + } + } + + if (isNextIndex){ + total_index++; + setProgress(QVariant(), + QVariant(startProgress+passSlice*(((double)total_index)/indices.size()))); + } + + qApp->processEvents(QEventLoop::AllEvents); + if (isCancelled) throw(-1); + prevLine = line; + } // foreach + } while (!in.atEnd()); + } + throw(0); + } + catch (int e){ + if (process.state()==QProcess::Starting || process.state()==QProcess::Running){ + process.kill(); + } + setProgress(QVariant(0), QVariant()); + if (startProgress==0.0 && passSlice==100.0){ + enableGUI(); + } + } } // menu: Options/Always_on_Top void MainWindow::on_actionAlways_on_Top_toggled(bool checked){ - Qt::WindowFlags flags = this->windowFlags(); - if (checked){ - flags |= Qt::WindowStaysOnTopHint; - } - else{ - flags &= ~Qt::WindowStaysOnTopHint; - } - this->setWindowFlags(flags); - this->show(); + Qt::WindowFlags flags = this->windowFlags(); + if (checked){ + flags |= Qt::WindowStaysOnTopHint; + } + else{ + flags &= ~Qt::WindowStaysOnTopHint; + } + this->setWindowFlags(flags); + this->show(); } // menu: Options/Tags/Remove_Tags_from_files void MainWindow::on_actionRemove_Tags_from_files_triggered(){ - QProcess process; - double startProgress = progressBar_Total->doubleValue(); - const double passSlice = 100.0; - - try { - if (startProgress==0.0 && passSlice==100.0) disableGUI(); - QModelIndexList indices = getModelIndices(); - if (indices.isEmpty()) throw(0); - - QStringList args; - args << "-s" << "d"; // delete stored tag info (no other processing) - args << getArgumentsByOptions(); - - foreach(QModelIndex index, indices) { - int row = model->itemFromIndex(index)->row(); - QStandardItem *item = getItem(row, "Path/File"); - QString fileName = item->text(); - args << fileName; - } - - process.setProcessChannelMode(QProcess::MergedChannels); - QString trace = QString("%1 %2").arg(this->getBackEnd()).arg(args.join(" ")); - writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); - - process.start(this->getBackEnd(), args); - - if (!process.waitForStarted()){ - showNoBackEndVersion(); - throw(1); - } - - /* - expected output is a tab separated table, where only the first column (File) is filled - File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain - 2Pac - California Love.mp3 NA NA NA NA NA - 2Pac - Changes.mp3 NA NA NA NA NA - */ - - enum resultColumns { File, MP3_gain, dB_gain, Max_Amplitude, Max_global_gain, Min_global_gain, enumMax }; - - int total_index = 0; - - for (bool isAfterLast = false, isWaitForReadyRead = false; - (isWaitForReadyRead = process.waitForReadyRead(-1)) || !isAfterLast; - isAfterLast = !isWaitForReadyRead ) { - - QByteArray newData = process.readAll(); - QString result = QString::fromLocal8Bit(newData); - - QTextStream in(&result); - do { - Line line; - line.content = in.readLine(); - if (line.content==QString::null || line.content.isEmpty()) - continue; - - QStringList lines = line.content.split(QChar('\r'), QString::SkipEmptyParts); - foreach (line.content, lines){ - if (line.content.trimmed().isEmpty()){ - continue; - } - - writeLog(line.content, LOGTYPE_BACKEND); - bool isNextIndex = false; - line.errType = hasError(line.content); - - if (line.errType){ - line.type = LINETYPE_ERROR; - if (line.errType!=ERRTYPE_SUPPRESSED){ - isNextIndex = true; // for the time being all errors increase the iterator - } - } - else{ - QStringList tokens = line.content.split(QChar('\t')); - if (tokens.size()==enumMax){ - if (tokensFile=="File") - line.type = LINETYPE_FILE_HEADER; - else{ - line.type = LINETYPE_FILE_CONTENT; - isNextIndex = true; - } - } - } - - if (isNextIndex){ - total_index++; - setProgress(QVariant(), - QVariant(startProgress+passSlice*(((double)total_index)/indices.size()))); - } - - qApp->processEvents(QEventLoop::AllEvents); - if (isCancelled) throw(-1); - } - } while (!in.atEnd()); - } - - throw(0); - } - catch (int e){ - if (process.state()==QProcess::Starting || process.state()==QProcess::Running){ - process.kill(); - } - if (startProgress==0.0 && passSlice==100.0){ - enableGUI(); - } - } + QProcess process; + double startProgress = progressBar_Total->doubleValue(); + const double passSlice = 100.0; + + try { + if (startProgress==0.0 && passSlice==100.0) disableGUI(); + QModelIndexList indices = getModelIndices(); + if (indices.isEmpty()) throw(0); + + QStringList args; + args << "-s" << "d"; // delete stored tag info (no other processing) + args << getArgumentsByOptions(); + + foreach(QModelIndex index, indices) { + int row = model->itemFromIndex(index)->row(); + QStandardItem *item = getItem(row, "Path/File"); + QString fileName = item->text(); + args << fileName; + } + + process.setProcessChannelMode(QProcess::MergedChannels); + QString trace = QString("%1 %2").arg(this->getBackEnd()).arg(args.join(" ")); + writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); + + process.start(this->getBackEnd(), args); + + if (!process.waitForStarted()){ + showNoBackEndVersion(); + throw(1); + } + + /* + expected output is a tab separated table, where only the first column (File) is filled + File MP3 gain dB gain Max Amplitude Max global_gain Min global_gain + 2Pac - California Love.mp3 NA NA NA NA NA + 2Pac - Changes.mp3 NA NA NA NA NA + */ + + enum resultColumns { File, MP3_gain, dB_gain, Max_Amplitude, Max_global_gain, Min_global_gain, enumMax }; + + int total_index = 0; + + for (bool isAfterLast = false, isWaitForReadyRead = false; + (isWaitForReadyRead = process.waitForReadyRead(-1)) || !isAfterLast; + isAfterLast = !isWaitForReadyRead ) { + + QByteArray newData = process.readAll(); + QString result = QString::fromLocal8Bit(newData); + + QTextStream in(&result); + do { + Line line; + line.content = in.readLine(); + if (line.content.isNull() || line.content.isEmpty()) + continue; + + QStringList lines = line.content.split(QChar('\r'), Qt::SkipEmptyParts); + foreach (line.content, lines){ + if (line.content.trimmed().isEmpty()){ + continue; + } + + writeLog(line.content, LOGTYPE_BACKEND); + bool isNextIndex = false; + line.errType = hasError(line.content); + + if (line.errType){ + line.type = LINETYPE_ERROR; + if (line.errType!=ERRTYPE_SUPPRESSED){ + isNextIndex = true; // for the time being all errors increase the iterator + } + } + else{ + QStringList tokens = line.content.split(QChar('\t')); + if (tokens.size()==enumMax){ + if (tokensFile=="File") + line.type = LINETYPE_FILE_HEADER; + else{ + line.type = LINETYPE_FILE_CONTENT; + isNextIndex = true; + } + } + } + + if (isNextIndex){ + total_index++; + setProgress(QVariant(), + QVariant(startProgress+passSlice*(((double)total_index)/indices.size()))); + } + + qApp->processEvents(QEventLoop::AllEvents); + if (isCancelled) throw(-1); + } + } while (!in.atEnd()); + } + + throw(0); + } + catch (int e){ + if (process.state()==QProcess::Starting || process.state()==QProcess::Running){ + process.kill(); + } + if (startProgress==0.0 && passSlice==100.0){ + enableGUI(); + } + } } // menu: Options/Logs/File... void MainWindow::on_actionLogFile_triggered(){ - // modal dialog - LogOptionsDialog dialog(this); - if (dialog.exec()) { - } + // modal dialog + LogOptionsDialog dialog(this); + if (dialog.exec()) { + } } // menu: Options/Logs/Panel void MainWindow::on_actionLogDock_triggered(){ - refreshGUI(); + refreshGUI(); } // menu: Options/Toolbar/ void MainWindow::on_actionBig_triggered(){ - actionSmall->setChecked(false); - actionText_only->setChecked(false); - actionNone->setChecked(false); - refreshGUI(); + actionSmall->setChecked(false); + actionText_only->setChecked(false); + actionNone->setChecked(false); + refreshGUI(); } void MainWindow::on_actionSmall_triggered(){ - actionBig->setChecked(false); - actionText_only->setChecked(false); - actionNone->setChecked(false); - refreshGUI(); + actionBig->setChecked(false); + actionText_only->setChecked(false); + actionNone->setChecked(false); + refreshGUI(); } void MainWindow::on_actionText_only_triggered(){ - actionBig->setChecked(false); - actionSmall->setChecked(false); - actionNone->setChecked(false); - refreshGUI(); + actionBig->setChecked(false); + actionSmall->setChecked(false); + actionNone->setChecked(false); + refreshGUI(); } void MainWindow::on_actionNone_triggered(){ - actionBig->setChecked(false); - actionSmall->setChecked(false); - actionText_only->setChecked(false); - refreshGUI(); + actionBig->setChecked(false); + actionSmall->setChecked(false); + actionText_only->setChecked(false); + refreshGUI(); } // menu: Options/Filename_Display/ void MainWindow::on_actionShow_Path_slash_File_triggered(){ - actionShow_File_only->setChecked(false); - actionShow_Path_at_File->setChecked(false); - refreshGUI(); + actionShow_File_only->setChecked(false); + actionShow_Path_at_File->setChecked(false); + refreshGUI(); } void MainWindow::on_actionShow_File_only_triggered(){ - actionShow_Path_slash_File->setChecked(false); - actionShow_Path_at_File->setChecked(false); - refreshGUI(); + actionShow_Path_slash_File->setChecked(false); + actionShow_Path_at_File->setChecked(false); + refreshGUI(); } void MainWindow::on_actionShow_Path_at_File_triggered(){ - actionShow_Path_slash_File->setChecked(false); - actionShow_File_only->setChecked(false); - refreshGUI(); + actionShow_Path_slash_File->setChecked(false); + actionShow_File_only->setChecked(false); + refreshGUI(); } // menu: Options/Beep when finished void MainWindow::on_actionBeep_when_finished_toggled(bool checked){ - if (checked){ - QString resourcePath = directoryOf("resources/sounds").absolutePath(); - QString beepFile(resourcePath+"/"+"beep.wav"); - if (QFileInfo(beepFile).exists()) - beepSound = new QSound(beepFile); - else - writeLog(tr("Beep %1 file cannot be found").arg(beepFile), LOGTYPE_ERROR); - } - else{ - delete beepSound; - } + if (checked){ + QString resourcePath = directoryOf("resources/sounds").absolutePath(); + QString beepFile(resourcePath+"/"+"beep.wav"); + if (QFileInfo(beepFile).exists()) + beepSound = new QSound(beepFile); + else + writeLog(tr("Beep %1 file cannot be found").arg(beepFile), LOGTYPE_ERROR); + } + else{ + delete beepSound; + } } // menu: Options/Reset "Warning" messages void MainWindow::on_actionReset_warning_messages_triggered(){ - settings->setValue("clearAnalysis_ConfirmSuppressed", false); - settings->setValue("clearLogs_ConfirmSuppressed", false); - settings->setValue("constantGainChangeDialog/groupBox_onlyOneChannel_ConfirmSuppressed", false); - settings->remove("openLogPanelForErrorAnswer"); + settings->setValue("clearAnalysis_ConfirmSuppressed", false); + settings->setValue("clearLogs_ConfirmSuppressed", false); + settings->setValue("constantGainChangeDialog/groupBox_onlyOneChannel_ConfirmSuppressed", false); + settings->remove("openLogPanelForErrorAnswer"); } // menu: Options/Reset Default Column Widths void MainWindow::on_actionReset_default_column_widths_triggered(){ - // restore default widths of tableView - QList<QVariant> widths = tableView->property("columnWidths").toList(); // QList<int> - for (int i=0; i<tableView->model()->columnCount(); i++){ - tableView->setColumnWidth(i, widths.at(i).toInt()); - } + // restore default widths of tableView + QList<QVariant> widths = tableView->property("columnWidths").toList(); // QList<int> + for (int i=0; i<tableView->model()->columnCount(); i++){ + tableView->setColumnWidth(i, widths.at(i).toInt()); + } } // menu: Options/Resize column widths to contents void MainWindow::on_actionResize_column_widths_by_content_triggered(){ - tableView->resizeColumnsToContents(); + tableView->resizeColumnsToContents(); } // menu: Options/Back end... void MainWindow::on_actionBack_end_triggered(){ - // modal dialog - BackEndDialog dialog(this); - if (dialog.exec()) { - } + // modal dialog + BackEndDialog dialog(this); + if (dialog.exec()) { + } } // menu: Options/Advanced... void MainWindow::on_actionAdvanced_triggered(){ - // modal dialog - AdvancedOptionsDialog* dialog = new AdvancedOptionsDialog(this); - if (dialog->exec()){ - } - delete dialog; // call destructor directly to store options before refreshGUI - refreshGUI(); + // modal dialog + AdvancedOptionsDialog* dialog = new AdvancedOptionsDialog(this); + if (dialog->exec()){ + } + delete dialog; // call destructor directly to store options before refreshGUI + refreshGUI(); } // menu: Help/Contents void MainWindow::on_actionContents_triggered(){ - QProcess* process = new QProcess(); // launched assistant should be still running after this method terminates - try { - QStringList args; - QString app; + QProcess* process = new QProcess(); // launched assistant should be still running after this method terminates + try { + QStringList args; + QString app; #if defined(Q_OS_WIN) - app += QLatin1String("assistant.exe"); + app += QLatin1String("assistant.exe"); #elif defined(Q_OS_MAC) - app += QLatin1String("Assistant.app/Contents/MacOS/Assistant"); + app += QLatin1String("Assistant.app/Contents/MacOS/Assistant"); #else //defined(Q_OS_LINUX) || defined(Q_OS_UNIX) - app += QLatin1String("assistant"); + app += QLatin1String("assistant"); #endif - QFileInfo fi(app); - if (!fi.exists()){ - app = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator() + app; - } - QString locale = settings->value("locale", QLocale::system().name()).toString(); - - fi.setFile(directoryOf("help").absolutePath(), "qmp3gain_"+locale+".qhc"); - if (!fi.exists()){ - if (locale!=defaultLocale){ - writeLog(tr("Help file %1 cannot be found").arg(fi.absoluteFilePath()), LOGTYPE_TRACE); - } - fi.setFile(directoryOf("help").absolutePath(), "qmp3gain.qhc"); - } - if (fi.exists()){ - args << QLatin1String("-collectionFile") - << fi.absoluteFilePath().toLatin1() - << QLatin1String("-enableRemoteControl"); - writeLog(tr("Help file %1 is used").arg(fi.absoluteFilePath()), LOGTYPE_TRACE); - QString trace = QString("%1 %2").arg(app).arg(args.join(" ")); - writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); - - connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), - =(int exitCode, QProcess::ExitStatus exitStatus){ - if (exitCode != 0 || exitStatus != QProcess::NormalExit) { - //writeLog(QString("exitCode: %1, exitStatus: %2").arg(exitCode).arg(exitStatus), LOGTYPE_TRACE); - QString result = QString::fromLocal8Bit(process->readAllStandardError()); - if (!result.isEmpty()) { - writeLog(result, LOGTYPE_ERROR); - } - } - delete process; - }); - process->start(app, args); - if (!process->waitForStarted()) { - throw(1); - } - //process->waitForFinished(500); - /*QString result = QString::fromLocal8Bit(process->readAllStandardError()); - if (!result.isEmpty()) { - writeLog(result, LOGTYPE_ERROR); - throw(1); - }*/ - //if (process->exitStatus() != QProcess::NormalExit || process->exitCode() != 0) { - // writeLog("Error", LOGTYPE_ERROR); - //} - } - else{ - writeLog(tr("Help file %1 cannot be found").arg(fi.absoluteFilePath()), LOGTYPE_ERROR); - throw(1); - } - } - catch (int e){ - if (process->state()==QProcess::Starting || process->state()==QProcess::Running){ - process->kill(); - } - delete process; - } + QFileInfo fi(app); + if (!fi.exists()){ + app = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator() + app; + } + QString locale = settings->value("locale", QLocale::system().name()).toString(); + + fi.setFile(directoryOf("help").absolutePath(), "qmp3gain_"+locale+".qhc"); + if (!fi.exists()){ + if (locale!=defaultLocale){ + writeLog(tr("Help file %1 cannot be found").arg(fi.absoluteFilePath()), LOGTYPE_TRACE); + } + fi.setFile(directoryOf("help").absolutePath(), "qmp3gain.qhc"); + } + if (fi.exists()){ + args << QLatin1String("-collectionFile") + << fi.absoluteFilePath().toLatin1() + << QLatin1String("-enableRemoteControl"); + writeLog(tr("Help file %1 is used").arg(fi.absoluteFilePath()), LOGTYPE_TRACE); + QString trace = QString("%1 %2").arg(app).arg(args.join(" ")); + writeLog(trace, LOGTYPE_BACKEND, 1, LOGOPTION_BOLD); + + connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), + =(int exitCode, QProcess::ExitStatus exitStatus){ + if (exitCode != 0 || exitStatus != QProcess::NormalExit) { + //writeLog(QString("exitCode: %1, exitStatus: %2").arg(exitCode).arg(exitStatus), LOGTYPE_TRACE); + QString result = QString::fromLocal8Bit(process->readAllStandardError()); + if (!result.isEmpty()) { + writeLog(result, LOGTYPE_ERROR); + } + } + delete process; + }); + process->start(app, args); + if (!process->waitForStarted()) { + throw(1); + } + //process->waitForFinished(500); + /*QString result = QString::fromLocal8Bit(process->readAllStandardError()); + if (!result.isEmpty()) { + writeLog(result, LOGTYPE_ERROR); + throw(1); + }*/ + //if (process->exitStatus() != QProcess::NormalExit || process->exitCode() != 0) { + // writeLog("Error", LOGTYPE_ERROR); + //} + } + else{ + writeLog(tr("Help file %1 cannot be found").arg(fi.absoluteFilePath()), LOGTYPE_ERROR); + throw(1); + } + } + catch (int e){ + if (process->state()==QProcess::Starting || process->state()==QProcess::Running){ + process->kill(); + } + delete process; + } } // menu: Help/Disclaimer void MainWindow::on_actionDisclaimer_triggered(){ - // modal dialog - DisclaimerDialog dialog(this); - if (dialog.exec()) { - } + // modal dialog + DisclaimerDialog dialog(this); + if (dialog.exec()) { + } } // menu: Help/About void MainWindow::on_actionAbout_triggered(){ - // modal dialog - AboutDialog aboutDialog(this); - if (aboutDialog.exec()) { - } + // modal dialog + AboutDialog aboutDialog(this); + if (aboutDialog.exec()) { + } }
View file
qmp3gain-0.9.3.tar.xz/src/mainwindow.h -> qmp3gain-0.9.4.tar.xz/src/mainwindow.h
Changed
@@ -12,7 +12,7 @@ #include <QPointer> #include <QSound> #include <QSystemTrayIcon> -#include <QTime> +#include <QElapsedTimer> #include <QMediaPlayer> #include "ui_mainwindow.h" @@ -23,270 +23,272 @@ public: MainWindow(QWidget *parent = 0); - ~MainWindow(); - inline QPointer<QSettings> getSettings() { return settings; } - inline static const QString & getAppTitle() { return appTitle; } - inline static const QString & getAppVersion() { return appVersion; } - inline const QString & getBackEnd() { return backEndFileName.isEmpty() ? backEndFixed : backEndFileName; } - inline static const QString & getBackEndFixed() { return backEndFixed; } - inline static const QString & getDonationUrl() { return donationUrl; } - inline static const QString & getRequiredBackEndVersion() { return requiredBackEndVersion; } - inline QString & getBackEndFileName() { return backEndFileName; } - inline void setBackEndFileName(const QString & backEndFileName) { this->backEndFileName = backEndFileName; } - inline QString & getBackEndVersion() { return backEndVersion; } - inline void setBackEndVersion(const QString & backEndVersion) { this->backEndVersion = backEndVersion; } - inline bool isBackEndAvailable(const QString & backEndVersion = QString()) { return getVersionNumber(!backEndVersion.isEmpty() ? backEndVersion : this->backEndVersion)>=getVersionNumber(this->requiredBackEndVersion); } - inline QPointer<QFile> getFileLog() { return fileLog; } - inline void setFileLog(QPointer<QFile> fileLog) { this->fileLog = fileLog; } - inline QStandardItem* getItem(int row, const QString & column) { return model->item(row, modelHeaderList.indexOf(column)); } - inline QModelIndex getItemIndex(int row, const QString & column) { return model->index(row, modelHeaderList.indexOf(column)); } - long getVersionNumber(const QString & versionString); - void showNoBackEndVersion(bool isStartBackEndDialog = false); - QString findBackEndVersionByProcess(const QString & backEndFileName = QString()); - enum LogType { LOGTYPE_ERROR, LOGTYPE_ANALYSIS, LOGTYPE_CHANGE, LOGTYPE_BACKEND, LOGTYPE_TRACE }; - enum LogOptionFlag { LOGOPTION_NONE = 0x0000, LOGOPTION_BOLD = 0x0001 }; - Q_DECLARE_FLAGS(LogOption, LogOptionFlag) - enum ErrType { ERRTYPE_NONE = 0, - ERRTYPE_ANALYSING_MAX_TIME_REACHED, - ERRTYPE_CANCELLED_PROCESSING, - ERRTYPE_CANCELLED_PROCESSING_CORRUPT, - ERRTYPE_CANNOT_ADJUST_SINGLE_CHANNEL, - ERRTYPE_CANNOT_FIND_MP3_FRAME, - ERRTYPE_CANNOT_MAKE_TMP, - ERRTYPE_CANNOT_MODIFY_FILE, - ERRTYPE_CORRUPT_MP3, - ERRTYPE_FILEFORMAT_NOTSUPPORTED, - ERRTYPE_RENAME_TMP, - ERRTYPE_NOT_ENOUGH_TEMP_SPACE, - ERRTYPE_SUPPRESSED /* pseudo, usually part of another error */ }; - /* - enum OpType { OPTYPE_ADD_FILE, OPTYPE_ADD_FOLDER, OPTYPE_ALBUM_ANALYSIS, - OPTYPE_ALBUM_GAIN, OPTYPE_ANALYSIS, OPTYPE_CLEAR_ANALYSIS, - OPTYPE_CONSTANT_GAIN, OPTYPE_MAX_NO_CLIP_ANALYSIS, - OPTYPE_MAX_NO_CLIP_GAIN_FOR_EACH_FILE, OPTYPE_MAX_NO_CLIP_GAIN_FOR_ALBUM, - OPTYPE_TRACK_ANALYSIS, OPTYPE_TRACK_GAIN, OPTYPE_UNDO_GAIN_CHANGES }; - */ - enum LineType { LINETYPE_UNDEFINED = 0, - LINETYPE_ERROR, - LINETYPE_ANALYSIS, - LINETYPE_WRITTEN, - LINETYPE_APPLY_GAIN, - LINETYPE_FILE_HEADER, - LINETYPE_FILE_ALBUM, - LINETYPE_FILE_CONTENT }; - struct Line - { - QString content; - LineType type; - ErrType errType; - - Line() : content(QString()), type(LINETYPE_UNDEFINED), errType(ERRTYPE_NONE) - { - } - }; + ~MainWindow(); + inline QPointer<QSettings> getSettings() { return settings; } + inline static const QString & getAppTitle() { return appTitle; } + inline static const QString & getAppVersion() { return appVersion; } + inline const QString & getBackEnd() { return backEndFileName.isEmpty() ? backEndFixed : backEndFileName; } + inline static const QString & getBackEndFixed() { return backEndFixed; } + inline static const QString & getDonationUrl() { return donationUrl; } + inline static const QString & getRequiredBackEndVersion() { return requiredBackEndVersion; } + inline QString & getBackEndFileName() { return backEndFileName; } + inline void setBackEndFileName(const QString & backEndFileName) { this->backEndFileName = backEndFileName; } + inline QString & getBackEndVersion() { return backEndVersion; } + inline void setBackEndVersion(const QString & backEndVersion) { this->backEndVersion = backEndVersion; } + inline bool isBackEndAvailable(const QString & backEndVersion = QString()) { return getVersionNumber(!backEndVersion.isEmpty() ? backEndVersion : this->backEndVersion)>=getVersionNumber(this->requiredBackEndVersion); } + inline QPointer<QFile> getFileLog() { return fileLog; } + inline void setFileLog(QPointer<QFile> fileLog) { this->fileLog = fileLog; } + inline QStandardItem* getItem(int row, const QString & column) { return model->item(row, modelHeaderList.indexOf(column)); } + inline QModelIndex getItemIndex(int row, const QString & column) { return model->index(row, modelHeaderList.indexOf(column)); } + long getVersionNumber(const QString & versionString); + void showNoBackEndVersion(bool isStartBackEndDialog = false); + QString findBackEndVersionByProcess(const QString & backEndFileName = QString()); + enum LogType { LOGTYPE_ERROR, LOGTYPE_ANALYSIS, LOGTYPE_CHANGE, LOGTYPE_BACKEND, LOGTYPE_TRACE }; + enum LogOptionFlag { LOGOPTION_NONE = 0x0000, LOGOPTION_BOLD = 0x0001 }; + Q_DECLARE_FLAGS(LogOption, LogOptionFlag) + enum ErrType { ERRTYPE_NONE = 0, + ERRTYPE_ANALYSING_MAX_TIME_REACHED, + ERRTYPE_CANCELLED_PROCESSING, + ERRTYPE_CANCELLED_PROCESSING_CORRUPT, + ERRTYPE_CANNOT_ADJUST_SINGLE_CHANNEL, + ERRTYPE_CANNOT_DECODE_FRAME, + ERRTYPE_CANNOT_FIND_MP3_FRAME, + ERRTYPE_CANNOT_MAKE_TMP, + ERRTYPE_CANNOT_MODIFY_FILE, + ERRTYPE_CORRUPT_MP3, + ERRTYPE_FILEFORMAT_NOTSUPPORTED, + ERRTYPE_RENAME_TMP, + ERRTYPE_NOT_ENOUGH_TEMP_SPACE, + ERRTYPE_SUPPRESSED /* pseudo, usually part of another error */ }; + /* + enum OpType { OPTYPE_ADD_FILE, OPTYPE_ADD_FOLDER, OPTYPE_ALBUM_ANALYSIS, + OPTYPE_ALBUM_GAIN, OPTYPE_ANALYSIS, OPTYPE_CLEAR_ANALYSIS, + OPTYPE_CONSTANT_GAIN, OPTYPE_MAX_NO_CLIP_ANALYSIS, + OPTYPE_MAX_NO_CLIP_GAIN_FOR_EACH_FILE, OPTYPE_MAX_NO_CLIP_GAIN_FOR_ALBUM, + OPTYPE_TRACK_ANALYSIS, OPTYPE_TRACK_GAIN, OPTYPE_UNDO_GAIN_CHANGES }; + */ + enum LineType { LINETYPE_UNDEFINED = 0, + LINETYPE_ERROR, + LINETYPE_ANALYSIS, + LINETYPE_WRITTEN, + LINETYPE_APPLY_GAIN, + LINETYPE_FILE_HEADER, + LINETYPE_FILE_ALBUM, + LINETYPE_FILE_CONTENT }; + struct Line + { + QString content; + LineType type; + ErrType errType; + + Line() : content(QString()), type(LINETYPE_UNDEFINED), errType(ERRTYPE_NONE) + { + } + }; public slots: - void switchLanguage(QAction *action = 0); + void switchLanguage(QAction *action = 0); protected: void closeEvent(QCloseEvent *event); - void changeEvent (QEvent *event); + void changeEvent (QEvent *event); void dragEnterEvent(QDragEnterEvent *event); void dropEvent(QDropEvent *event); - void createStatusBar(); + void createStatusBar(); private: - QPointer<QTranslator> appTranslator; - QPointer<QActionGroup> menuLanguageActionGroup; - QMap<QString, QList<int> > operationMap; - QVector<QAction*> actions; - QMap<QAction*, QCheckBox*> logOutputTypes; - QPointer<QSettings> settings; - QString lastAddedFolder; - QModelIndexList lastAddedIndices; - const char ** modelHeaderLabels; - QStringList modelHeaderList; // contains column labels (always in english) of model header - QPointer<QStandardItemModel> model; - const static QString appTitle; - const static QString appVersion; - const static QString backEndFixed; - const static QString donationUrl; - const static QString requiredBackEndVersion; - QString backEndFileName; - QString backEndVersion; - bool backEndAvailable; - const static double defaultNormalTargetValue; - const static QString defaultLocale; - const static double DB; - QSize iconDefaultSize; - bool isCancelled; - bool enabledGUI; - QVariant isPopupErrorSuppressed; // bool, exists just inside a function - QVariant isOpenLogPanelQuestionSuppressed; // bool, exists just inside a function - QPointer<QFile> fileLog; - QPointer<QLabel> messageLabel; - QPointer<QLabel> modelRowCountLabel; - QPointer<QSound> beepSound; - QTime operationTime; - QByteArray mainGeometry; - - QPointer<QAction> restoreTrayAction; - QPointer<QAction> quitTrayAction; - QPointer<QSystemTrayIcon> trayIcon; - QPointer<QAction> actionPlay_mp3_file; // exists only in context menu + QPointer<QTranslator> appTranslator; + QPointer<QActionGroup> menuLanguageActionGroup; + QMap<QString, QList<int> > operationMap; + QVector<QAction*> actions; + QMap<QAction*, QCheckBox*> logOutputTypes; + QPointer<QSettings> settings; + QString lastAddedFolder; + QModelIndexList lastAddedIndices; + const char ** modelHeaderLabels; + QStringList modelHeaderList; // contains column labels (always in english) of model header + QPointer<QStandardItemModel> model; + const static QString appTitle; + const static QString appVersion; + const static QString backEndFixed; + const static QString donationUrl; + const static QString requiredBackEndVersion; + QString backEndFileName; + QString backEndVersion; + bool backEndAvailable; + const static double defaultNormalTargetValue; + const static QString defaultLocale; + const static double DB; + QSize iconDefaultSize; + bool isCancelled; + bool enabledGUI; + QVariant isPopupErrorSuppressed; // bool, exists just inside a function + QVariant isOpenLogPanelQuestionSuppressed; // bool, exists just inside a function + QPointer<QFile> fileLog; + QPointer<QLabel> messageLabel; + QPointer<QLabel> modelRowCountLabel; + QPointer<QSound> beepSound; + QElapsedTimer elapsedTimer; + QByteArray mainGeometry; + + QPointer<QAction> restoreTrayAction; + QPointer<QAction> quitTrayAction; + QPointer<QSystemTrayIcon> trayIcon; + QPointer<QAction> actionPlay_mp3_file; // exists only in context menu QPointer<QMediaPlayer> mediaPlayer; - bool okToContinue(); - QDir directoryOf(const QString &subdir); - void createLanguageMenu(); - void writeSettings(); - void readSettings(); - void setProgress(QVariant progressFile, QVariant progressTotal); - int getMP3FilesByFolder(const QString & dir, const int level, const double passSlice = 100.0); - void refreshUi(); - void enableGUI(); - void disableGUI(); - void refreshGUI(); - void refreshMenu(); - QStringList getArgumentsByOptions(); - QString getItemText(int row, const QString & column); - QVariant getItemValue(int row, const QString & column); - void setItem(int row, QString column, QVariant value); - void writeLog(const QString & msg, LogType logType, int level = 1, LogOption logOption = LOGOPTION_NONE); - void updateModelRowByAnalysisTrack(QString fileName, int mp3Gain, double dBGain, double maxAmplitude, bool maxNoclipGain = false, bool isLog = false); - void updateModelRowByAnalysisTrack(QModelIndex modelIndex, int mp3Gain, double dBGain, double maxAmplitude, bool maxNoclipGain = false, bool isLog = false); - void updateModelRowsByAnalysisAlbum(bool isAlbum, QString fileName, int mp3Gain, double dBGain, /*double*/ QVariant maxAmplitude = QVariant(QVariant::Double), bool isLog = false); - void updateModelRowsByAnalysisAlbum(bool isAlbum, QModelIndexList indexes, int mp3Gain, double dBGain, /*double*/ QVariant maxAmplitude = QVariant(QVariant::Double), bool isLog = false); - QModelIndexList getModelIndices(); - ErrType hasError(const QString & line); - int runAnalysis(QModelIndexList indices, bool isAlbum = false, bool isMaxNoclip = false, bool isOnLastAddedFiles = false, double passSlice = 100.0); - void updateModelRowByMP3GainTrack(QString fileName, int mp3Gain, bool isAlbumErase = true); - void updateModelRowsByMP3GainAlbum(QString fileName, int mp3Gain, bool isTrackModifiable = true); - void updateModelRowsByMP3GainAlbum(QModelIndexList indices, int mp3Gain, bool isTrackModifiable = true); - void runGain(QModelIndexList indices, bool isAlbum = false, double passSlice = 100.0); - void runConstantGain(QModelIndexList indices, int mp3gain, bool isLeft, bool isRight, double passSlice = 100.0); - void updateStatusBar(const QString & msg); - void createTrayIcon(); + bool okToContinue(); + QDir directoryOf(const QString &subdir); + void createLanguageMenu(); + void writeSettings(); + void readSettings(); + void setProgress(QVariant progressFile, QVariant progressTotal); + int getMP3FilesByFolder(const QString & dir, const int level, const double passSlice = 100.0); + void refreshUi(); + void enableGUI(); + void disableGUI(); + void refreshGUI(); + void refreshMenu(); + QStringList getArgumentsByOptions(); + QString getItemText(int row, const QString & column); + QVariant getItemValue(int row, const QString & column); + void setItem(int row, QString column, QVariant value); + void writeLog(const QString & msg, LogType logType, int level = 1, LogOption logOption = LOGOPTION_NONE); + void updateModelRowByAnalysisTrack(QString fileName, int mp3Gain, double dBGain, double maxAmplitude, bool maxNoclipGain = false, bool isLog = false); + void updateModelRowByAnalysisTrack(QModelIndex modelIndex, int mp3Gain, double dBGain, double maxAmplitude, bool maxNoclipGain = false, bool isLog = false); + void updateModelRowsByAnalysisAlbum(bool isAlbum, QString fileName, int mp3Gain, double dBGain, /*double*/ QVariant maxAmplitude = QVariant(QVariant::Double), bool isLog = false); + void updateModelRowsByAnalysisAlbum(bool isAlbum, QModelIndexList indexes, int mp3Gain, double dBGain, /*double*/ QVariant maxAmplitude = QVariant(QVariant::Double), bool isLog = false); + QModelIndexList getModelIndices(); + ErrType hasError(const QString & line); + int runAnalysis(QModelIndexList indices, bool isAlbum = false, bool isMaxNoclip = false, bool isOnLastAddedFiles = false, double passSlice = 100.0); + void updateModelRowByMP3GainTrack(QString fileName, int mp3Gain, bool isAlbumErase = true); + void updateModelRowsByMP3GainAlbum(QString fileName, int mp3Gain, bool isTrackModifiable = true); + void updateModelRowsByMP3GainAlbum(QModelIndexList indices, int mp3Gain, bool isTrackModifiable = true); + void runGain(QModelIndexList indices, bool isAlbum = false, double passSlice = 100.0); + void runConstantGain(QModelIndexList indices, int mp3gain, bool isLeft, bool isRight, double passSlice = 100.0); + void updateStatusBar(const QString & msg); + void createTrayIcon(); void addFiles(const QStringList& fileNames); void addFolder(const QString& dir); private slots: - void showContextMenuForWidget(const QPoint &pos); - void updateModelRowsByNewTargetNormalValue(double newTargetNormalValue); - void updateStatusBar(); - void trayIconActivated(QSystemTrayIcon::ActivationReason reason); - void trayShowMessage(); - void trayHide(); + void showContextMenuForWidget(const QPoint &pos); + void updateModelRowsByNewTargetNormalValue(double newTargetNormalValue); + void updateStatusBar(); + void trayIconActivated(QSystemTrayIcon::ActivationReason reason); + void trayShowMessage(); + void trayHide(); void handleMediaPlayerError(QMediaPlayer::Error error); - void playMP3File(); // contextmenu item + void playMP3File(); // contextmenu item - void on_cancelButton_clicked(); - void on_clearLogButton_clicked(); - void on_logDockWidget_visibilityChanged(bool visible); + void on_cancelButton_clicked(); + void on_clearLogButton_clicked(); + void on_copyLogButton_clicked(); + void on_logDockWidget_visibilityChanged(bool visible); - // menu: File/Load_Analysis_results - void on_actionLoad_Analysis_results_triggered(); + // menu: File/Load_Analysis_results + void on_actionLoad_Analysis_results_triggered(); - // menu: File/Save_Analysis_results - void on_actionSave_Analysis_results_triggered(); + // menu: File/Save_Analysis_results + void on_actionSave_Analysis_results_triggered(); - // menu: File/Add_files - void on_actionAdd_Files_triggered(); + // menu: File/Add_files + void on_actionAdd_Files_triggered(); - // menu: File/Add_folder - void on_actionAdd_Folder_triggered(); + // menu: File/Add_folder + void on_actionAdd_Folder_triggered(); - // menu: File/Select_all_files - void on_actionSelect_All_Files_triggered(); + // menu: File/Select_all_files + void on_actionSelect_All_Files_triggered(); - // menu: File/Select_no_files - void on_actionSelect_No_Files_triggered(); + // menu: File/Select_no_files + void on_actionSelect_No_Files_triggered(); - // menu: File/Invert_selection - void on_actionInvert_selection_triggered(); + // menu: File/Invert_selection + void on_actionInvert_selection_triggered(); - // menu: File/Clear_selected_files - void on_actionClear_Selected_Files_triggered(); + // menu: File/Clear_selected_files + void on_actionClear_Selected_Files_triggered(); - // menu: File/Clear_all_files - void on_actionClear_All_files_triggered(); + // menu: File/Clear_all_files + void on_actionClear_All_files_triggered(); - // menu: Analysis/Track_analysis - void on_actionTrack_Analysis_triggered(); + // menu: Analysis/Track_analysis + void on_actionTrack_Analysis_triggered(); - // menu: Analysis/Album_analysis - void on_actionAlbum_Analysis_triggered(); + // menu: Analysis/Album_analysis + void on_actionAlbum_Analysis_triggered(); - // menu: Analysis/Max No-clip Analysis - void on_actionMax_No_clip_Analysis_triggered(); + // menu: Analysis/Max No-clip Analysis + void on_actionMax_No_clip_Analysis_triggered(); - // menu: Analysis/Clear_analysis - void on_actionClear_Analysis_triggered(); + // menu: Analysis/Clear_analysis + void on_actionClear_Analysis_triggered(); - // menu: Modify_gain/Track_gain - void on_actionTrack_Gain_triggered(); + // menu: Modify_gain/Track_gain + void on_actionTrack_Gain_triggered(); - // menu: Modify_gain/Album_gain - void on_actionAlbum_Gain_triggered(); + // menu: Modify_gain/Album_gain + void on_actionAlbum_Gain_triggered(); - // menu: Modify_gain/Constant_gain - void on_actionConstant_Gain_triggered(); + // menu: Modify_gain/Constant_gain + void on_actionConstant_Gain_triggered(); - // menu: Modify_gain/Max No-clip Gain for Each file - void on_actionMax_No_clip_Gain_for_Each_file_triggered(); + // menu: Modify_gain/Max No-clip Gain for Each file + void on_actionMax_No_clip_Gain_for_Each_file_triggered(); - // menu: Modify_gain/Max No-clip Gain for Album - void on_actionMax_No_clip_Gain_for_Album_triggered(); + // menu: Modify_gain/Max No-clip Gain for Album + void on_actionMax_No_clip_Gain_for_Album_triggered(); - // menu: Modify_gain/Undo_gain_changes - void on_actionUndo_Gain_changes_triggered(); + // menu: Modify_gain/Undo_gain_changes + void on_actionUndo_Gain_changes_triggered(); - // menu: Options/Always_on_Top - void on_actionAlways_on_Top_toggled(bool checked); + // menu: Options/Always_on_Top + void on_actionAlways_on_Top_toggled(bool checked); - // menu: Options/Tags/Remove_Tags_from_files - void on_actionRemove_Tags_from_files_triggered(); + // menu: Options/Tags/Remove_Tags_from_files + void on_actionRemove_Tags_from_files_triggered(); - // menu: Options/Logs/File... - void on_actionLogFile_triggered(); + // menu: Options/Logs/File... + void on_actionLogFile_triggered(); - // menu: Options/Logs/Panel - void on_actionLogDock_triggered(); + // menu: Options/Logs/Panel + void on_actionLogDock_triggered(); - // menu: Options/Toolbar/ - void on_actionBig_triggered(); - void on_actionSmall_triggered(); - void on_actionText_only_triggered(); - void on_actionNone_triggered(); + // menu: Options/Toolbar/ + void on_actionBig_triggered(); + void on_actionSmall_triggered(); + void on_actionText_only_triggered(); + void on_actionNone_triggered(); - // menu: Options/Filename_Display/ - void on_actionShow_Path_slash_File_triggered(); - void on_actionShow_File_only_triggered(); - void on_actionShow_Path_at_File_triggered(); + // menu: Options/Filename_Display/ + void on_actionShow_Path_slash_File_triggered(); + void on_actionShow_File_only_triggered(); + void on_actionShow_Path_at_File_triggered(); - // menu: Options/Beep when finished - void on_actionBeep_when_finished_toggled(bool checked); + // menu: Options/Beep when finished + void on_actionBeep_when_finished_toggled(bool checked); - // menu: Options/Reset "Warning" messages - void on_actionReset_warning_messages_triggered(); + // menu: Options/Reset "Warning" messages + void on_actionReset_warning_messages_triggered(); - // menu: Options/Reset Default Column Widths - void on_actionReset_default_column_widths_triggered(); + // menu: Options/Reset Default Column Widths + void on_actionReset_default_column_widths_triggered(); - // menu: Options/Resize column widths by content - void on_actionResize_column_widths_by_content_triggered(); + // menu: Options/Resize column widths by content + void on_actionResize_column_widths_by_content_triggered(); - // menu: Options/Back end... - void on_actionBack_end_triggered(); + // menu: Options/Back end... + void on_actionBack_end_triggered(); - // menu: Options/Advanced... - void on_actionAdvanced_triggered(); + // menu: Options/Advanced... + void on_actionAdvanced_triggered(); - // menu: Help/About - void on_actionContents_triggered(); - void on_actionDisclaimer_triggered(); - void on_actionAbout_triggered(); + // menu: Help/About + void on_actionContents_triggered(); + void on_actionDisclaimer_triggered(); + void on_actionAbout_triggered(); }; Q_DECLARE_OPERATORS_FOR_FLAGS(MainWindow::LogOption)
View file
qmp3gain-0.9.3.tar.xz/src/mainwindow.ui -> qmp3gain-0.9.4.tar.xz/src/mainwindow.ui
Changed
@@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>732</width> - <height>477</height> + <height>512</height> </rect> </property> <property name="windowTitle"> @@ -162,7 +162,7 @@ <x>0</x> <y>0</y> <width>732</width> - <height>21</height> + <height>30</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -367,12 +367,25 @@ <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> <widget class="QToolButton" name="clearLogButton"> + <property name="toolTip"> + <string>Clear logs</string> + </property> <property name="text"> <string extracomment="Log output clear button">Clear</string> </property> </widget> </item> <item> + <widget class="QToolButton" name="copyLogButton"> + <property name="toolTip"> + <string>Copy logs to clipboard</string> + </property> + <property name="text"> + <string>Copy</string> + </property> + </widget> + </item> + <item> <spacer name="horizontalSpacer_2"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -870,6 +883,9 @@ <property name="checkable"> <bool>true</bool> </property> + <property name="checked"> + <bool>true</bool> + </property> <property name="text"> <string>No check for Layer I or II</string> </property> @@ -1275,22 +1291,6 @@ </resources> <connections> <connection> - <sender>actionLogError</sender> - <signal>toggled(bool)</signal> - <receiver>checkBox_logError</receiver> - <slot>setChecked(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>-1</x> - <y>-1</y> - </hint> - <hint type="destinationlabel"> - <x>274</x> - <y>324</y> - </hint> - </hints> - </connection> - <connection> <sender>actionLogAnalysis</sender> <signal>toggled(bool)</signal> <receiver>checkBox_logAnalysis</receiver> @@ -1387,22 +1387,6 @@ </hints> </connection> <connection> - <sender>checkBox_logError</sender> - <signal>toggled(bool)</signal> - <receiver>actionLogError</receiver> - <slot>setChecked(bool)</slot> - <hints> - <hint type="sourcelabel"> - <x>274</x> - <y>324</y> - </hint> - <hint type="destinationlabel"> - <x>-1</x> - <y>-1</y> - </hint> - </hints> - </connection> - <connection> <sender>actionQuit</sender> <signal>triggered()</signal> <receiver>MainWindow</receiver> @@ -1450,5 +1434,37 @@ </hint> </hints> </connection> + <connection> + <sender>actionLogError</sender> + <signal>toggled(bool)</signal> + <receiver>checkBox_logError</receiver> + <slot>setChecked(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>274</x> + <y>324</y> + </hint> + </hints> + </connection> + <connection> + <sender>checkBox_logError</sender> + <signal>toggled(bool)</signal> + <receiver>actionLogError</receiver> + <slot>setChecked(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>274</x> + <y>324</y> + </hint> + <hint type="destinationlabel"> + <x>-1</x> + <y>-1</y> + </hint> + </hints> + </connection> </connections> </ui>
View file
qmp3gain-0.9.3.tar.xz/src/mymessagebox.cpp -> qmp3gain-0.9.4.tar.xz/src/mymessagebox.cpp
Changed
@@ -9,45 +9,45 @@ } QMessageBox::StandardButton MyMessageBox::messageBox ( QMessageBox::Icon icon, QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirmSuppressed, StandardButtons buttons, QMessageBox::StandardButton defaultButton){ - QMessageBox msgBox(parent); - msgBox.setWindowTitle(title); - msgBox.setText(text); - //msgBox.setInformativeText("Do you want to save your changes?"); - msgBox.setStandardButtons(buttons); - msgBox.setDefaultButton(defaultButton); - msgBox.setIcon(icon); - QCheckBox* checkBox = 0; - - if (!isConfirmSuppressed && !confirmText.isEmpty()){ - QGridLayout* grid = qobject_cast<QGridLayout*>(msgBox.layout()); - if (grid){ - checkBox = new QCheckBox(confirmText); - grid->addWidget(checkBox, grid->rowCount()-2, 0, 1, grid->columnCount()); - } - } - - if (msgBox.exec() == -1) - return QMessageBox::Cancel; - - if (checkBox){ - isConfirmSuppressed = checkBox->isChecked(); - } - - return msgBox.standardButton(msgBox.clickedButton()); + QMessageBox msgBox(parent); + msgBox.setWindowTitle(title); + msgBox.setText(text); + //msgBox.setInformativeText("Do you want to save your changes?"); + msgBox.setStandardButtons(buttons); + msgBox.setDefaultButton(defaultButton); + msgBox.setIcon(icon); + QCheckBox* checkBox = 0; + + if (!isConfirmSuppressed && !confirmText.isEmpty()){ + QGridLayout* grid = qobject_cast<QGridLayout*>(msgBox.layout()); + if (grid){ + checkBox = new QCheckBox(confirmText); + grid->addWidget(checkBox, grid->rowCount()-2, 0, 1, grid->columnCount()); + } + } + + if (msgBox.exec() == -1) + return QMessageBox::Cancel; + + if (checkBox){ + isConfirmSuppressed = checkBox->isChecked(); + } + + return msgBox.standardButton(msgBox.clickedButton()); } QMessageBox::StandardButton MyMessageBox::critical ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirmSuppressed, StandardButtons buttons, QMessageBox::StandardButton defaultButton){ - return messageBox(QMessageBox::Critical, parent, title, text, confirmText, isConfirmSuppressed, buttons, defaultButton); + return messageBox(QMessageBox::Critical, parent, title, text, confirmText, isConfirmSuppressed, buttons, defaultButton); } QMessageBox::StandardButton MyMessageBox::information ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirmSuppressed, StandardButtons buttons, QMessageBox::StandardButton defaultButton){ - return messageBox(QMessageBox::Information, parent, title, text, confirmText, isConfirmSuppressed, buttons, defaultButton); + return messageBox(QMessageBox::Information, parent, title, text, confirmText, isConfirmSuppressed, buttons, defaultButton); } QMessageBox::StandardButton MyMessageBox::question ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirmSuppressed, StandardButtons buttons, QMessageBox::StandardButton defaultButton){ - return messageBox(QMessageBox::Question, parent, title, text, confirmText, isConfirmSuppressed, buttons, defaultButton); + return messageBox(QMessageBox::Question, parent, title, text, confirmText, isConfirmSuppressed, buttons, defaultButton); } QMessageBox::StandardButton MyMessageBox::warning ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirmSuppressed, StandardButtons buttons, QMessageBox::StandardButton defaultButton){ - return messageBox(QMessageBox::Warning, parent, title, text, confirmText, isConfirmSuppressed, buttons, defaultButton); + return messageBox(QMessageBox::Warning, parent, title, text, confirmText, isConfirmSuppressed, buttons, defaultButton); }
View file
qmp3gain-0.9.3.tar.xz/src/mymessagebox.h -> qmp3gain-0.9.4.tar.xz/src/mymessagebox.h
Changed
@@ -5,16 +5,16 @@ class MyMessageBox: public QMessageBox { public: - MyMessageBox(); - virtual ~MyMessageBox(); + MyMessageBox(); + virtual ~MyMessageBox(); - static QMessageBox::StandardButton critical ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirm, StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton); - static QMessageBox::StandardButton information ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirm, StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton); - static QMessageBox::StandardButton question ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirm, StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton); - static QMessageBox::StandardButton warning ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirm, StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton); + static QMessageBox::StandardButton critical ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirm, StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton); + static QMessageBox::StandardButton information ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirm, StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton); + static QMessageBox::StandardButton question ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirm, StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton); + static QMessageBox::StandardButton warning ( QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirm, StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton); private: - static QMessageBox::StandardButton messageBox ( QMessageBox::Icon icon, QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirmSuppressed, StandardButtons buttons, QMessageBox::StandardButton defaultButton); + static QMessageBox::StandardButton messageBox ( QMessageBox::Icon icon, QWidget * parent, const QString & title, const QString & text, const QString & confirmText, bool & isConfirmSuppressed, StandardButtons buttons, QMessageBox::StandardButton defaultButton); }; #endif /* MYMESSAGEBOX_H_ */
View file
qmp3gain-0.9.3.tar.xz/translations/README.md -> qmp3gain-0.9.4.tar.xz/translations/README.md
Changed
@@ -6,17 +6,19 @@ To add a new language: -1. Run `cd translations` (change to the directory of this file) +1. Run `cd translations` to change the directory -2. Run `make ts-untranslated` +2. Run `qmake` if Makefile does not exist yet in the folder -3. Rename generated `qmp3gain_untranslated.ts` to `qmp3gain_<lang>.ts` +3. Run `make ts-untranslated` to create a skeleton translation file -4. Run `qmake` +4. Rename generated `qmp3gain_untranslated.ts` to `qmp3gain_<lang>.ts` -5. Do your translation. Take a look at the existing translation files if you are unfamiliar to the structure of ts translation files. Remember to use UTF-8 encoding in your editor! Just run `make` and start the application whenever you want to test it. In the application menu your language must be enlisted among the existing ones. +5. Run `qmake` to update Makefile with a new `make-ts<lang>` target -6. If you want to publish your finished translation, which is highly welcomed, just create a new feature request ticket and attach your `qmp3gain_<lang>.ts` there. Thanks for your contribution! +6. Do your translation. Take a look at the existing translation files if you are unfamiliar to the structure of ts translation files. Remember to use UTF-8 encoding in your editor! Just run `make` and start the application whenever you want to test it. In the application menu your language must be enlisted among the existing ones. -To update an existing translation, just run `make ts-<lang>` instead of steps 2) to 4). +7. If you want to publish your finished translation, which is highly welcomed, just create a new feature request ticket and attach your `qmp3gain_<lang>.ts` there. Thanks for your contribution! + +To update an already existing translation, just run `make ts-<lang>` instead of steps 3) to 5).
View file
qmp3gain-0.9.3.tar.xz/translations/qmp3gain_hu.ts -> qmp3gain-0.9.4.tar.xz/translations/qmp3gain_hu.ts
Changed
@@ -1,76 +1,61 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> -<TS version="2.0" language="hu_HU" sourcelanguage="en_US"> +<TS version="2.1" language="hu_HU" sourcelanguage="en_US"> <context> <name>AboutDialog</name> <message> - <location filename="../src/aboutdialog.ui" line="14"/> <source>%1 - About</source> <translation>%1 - Névjegy</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="69"/> <source>Back end (%1)</source> <translation>Kiszolgáló oldal (%1)</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="103"/> <source>%1 (GUI)</source> <translation>%1 (felület)</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="167"/> <source>Latest version of %1 at</source> <translation>%1 legújabb verziója</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="206"/> <source>Latest version of back end at</source> <translation>Kiszolgáló oldali program (és az eredeti felület) legújabb verziója</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="245"/> <source>Contact the author, Zsolt Branyiczky at</source> <translation>A szerző, Branyiczky Zsolt elérhetősége</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="288"/> <source>The back end makes use of a modified version of mpglib. The original version of mpglib can be found at</source> <translation>A kiszolgáló oldal lehetővé teszi az mpglib módosított változatának használatát. Az mpglib eredeti verziója</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="394"/> <source>Send a donation to the author</source> <translation>Adomány küldése a szerzőnek</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="400"/> <source>Donation</source> <translation>Adományoz</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="420"/> <source>Close</source> <translation>Bezárás</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="76"/> - <location filename="../src/aboutdialog.ui" line="96"/> <source>Version %1</source> <translation>%1 verzió</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="125"/> <source>Performs ReplayGain analysis of MP3 files. For more information about ReplayGain, go to</source> <translation>ReplayGain algoritmus végzi az MP3 fájlok elemzését. Részletes ReplayGain információ</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="330"/> <source>Thanks to Marc Heubeck for making the control buttons look nicer, to Bill MacEachern for making the Help file more profession, and to Glen Swer for the MP3Gain back end (and original GUI).</source> <translation>Köszönet Marc Heubeck-nek a szebb kezelőgombokért, Bill MacEachern-nek a tökéletesebb súgó fájlért, és Glan Swer-nek a MP3Gain háttér oldali kiszolgáló programért és az eredeti felületért.</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="365"/> <source>English translation: Your Name</source> <translation>Magyar fordítás: Herczeg József Tamás</translation> </message> @@ -78,151 +63,120 @@ <context> <name>AdvancedOptionsDialog</name> <message> - <location filename="../src/advancedoptionsdialog.ui" line="28"/> <source>Thread Priority</source> <translation>Szálprioritás</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="44"/> <source>Realtime</source> <translation>Valós idejű</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="55"/> <source>High</source> <translation>Magas</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="65"/> <source>Normal</source> <translation>Normál</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="78"/> <source>Idle</source> <translation>Üresjárat</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="162"/> <source>Performance</source> <translation>Teljesítmény</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="14"/> <source>%1 - Advanced Options</source> <translation>%1 - Speciális beállítások</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="25"/> <source>This adjusts what priority the program has in using your computer's resources</source> <translation>Beállítható a program prioritása, azaz szabályozható mekkora számítógép erőforrásokat használjon az alkalmazás</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="40"/> <source>Applicaton has maximum priority of the computer's resource. Its usage is not recommended.</source> <translation>Az alkalmazás a szémítógép erőforrásaiból maximumot kap, használata nem javasolt.</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="51"/> <source>Applicaton has high priority of the computer's resource. Its usage might be not recommended</source> <translation>Az alkalmazás a számítőgép errőforrásaiból igen nagy részt kap, használata többnyire nem javasolt.</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="62"/> <source>Applicaton has normal priority of the computer's resource</source> <translation>Az alkalmazás a számítőgép errőforrásaiból átlagos részt kap.</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="75"/> <source>Applicaton has slight priority of the computer's resource</source> <translation>Az alkalmazás a számítőgép errőforrásaiból csekély részt kap.</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="96"/> <source>Extra features</source> <translation>Extra tulajdonságok</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="105"/> <source>New analysis and gain functions can be activated</source> <translation>Új elemzés és erősítés funkciók aktiválhatók</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="115"/> <source>Show "Max Amplitude" and dBGain fields in the list</source> <translation>Megjeleníti a "Max Amplitudó" és dBErősítés mezőket a listában</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="121"/> <source>Show hidden fields</source> <translation>Rejtett mezők megjelenítése</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="133"/> <source>Beep after</source> <translation>Hangjelzés</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="140"/> <source>Makes beep sound if the opeartion takes more time in seconds than this value</source> <translation>Hangjelzést ad a művelet végén, ha az tovább tart, mint az itt megadott másodperc érték</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="150"/> <source>seconds</source> <translation>másodperc múlva</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="168"/> <source>Gain modifications can be done directly in the files</source> <translation>Erősítés módosítások végrehajthatók direktben a fájlokon</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="171"/> <source>Do not use Temp files</source> <translation>Ideiglenes fájlok használata nélkül</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="178"/> <source>File progress bar can be switch off</source> <translation>Fájl feldogozás folyamat kijelzésének kikapcsolása</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="181"/> <source>Do not show file progress</source> <translation>Ne látszódjon a fájl feldolgozás folyamata</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="195"/> <source>Extra output log</source> <translation>Extra kimeneti naplózás</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="284"/> - <location filename="../src/advancedoptionsdialog.ui" line="300"/> <source>Sets the depth of the trace, it's mostly for possible bug hunting</source> <translation>Beállítja a nyomkövetési szint mélységét, többnyire hibakeresésre szolgál</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="216"/> <source>Back end log depth</source> <translation>Háttér oldal naplózásának szintje</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="223"/> - <location filename="../src/advancedoptionsdialog.ui" line="254"/> <source>Sets the depth of communication with the MP3Gain back end</source> <translation>Beállítja a MP3Gain kommunikáció naplózásának a szintjét</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="277"/> <source>Trace log depth</source> <translation>Felület oldal naplózásának szintje</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="108"/> <source>Enable "Maximizing" features</source> <translation>"Maximalizálás" funkció engedélyezése</translation> </message> @@ -230,47 +184,38 @@ <context> <name>BackEndDialog</name> <message> - <location filename="../src/backenddialog.ui" line="14"/> <source>%1 - Specify back end</source> <translation>%1 - Háttér kiszolgáló megadása</translation> </message> <message> - <location filename="../src/backenddialog.ui" line="22"/> <source>Back end:</source> <translation>Háttér kiszolgáló:</translation> </message> <message> - <location filename="../src/backenddialog.ui" line="58"/> <source>Status: %1</source> <translation>Státusz: %1</translation> </message> <message> - <location filename="../src/backenddialog.ui" line="51"/> <source>Version: %1</source> <translation>Verzió: %1</translation> </message> <message> - <location filename="../src/backenddialog.cpp" line="58"/> <source>invalid</source> <translation>érvénytelen</translation> </message> <message> - <location filename="../src/backenddialog.cpp" line="62"/> <source>invalid (not found)</source> <translation>érvénytelen (nem található)</translation> </message> <message> - <location filename="../src/backenddialog.cpp" line="66"/> <source>invalid (%1 or later required)</source> <translation>érvénytelen (legalább %1 szükséges)</translation> </message> <message> - <location filename="../src/backenddialog.cpp" line="70"/> <source>ok</source> <translation>rendben</translation> </message> <message> - <location filename="../src/backenddialog.cpp" line="85"/> <source>Select back end mp3gain executable file</source> <translation>Válassza ki a háttér oldali mp3gain végrehajtható fájlt</translation> </message> @@ -278,47 +223,38 @@ <context> <name>ConstantGainChangeDialog</name> <message> - <location filename="../src/constantgainchangedialog.cpp" line="34"/> <source>Warning</source> <translation>Figyelmeztetés</translation> </message> <message> - <location filename="../src/constantgainchangedialog.cpp" line="35"/> <source>This function will only work if the mp3 is encoded as stereo or dual channel, NOT joint-stereo or mono.</source> <translation>Ez a funkció csak akkor működik, ha az mp3 fájl sztereó vagy dual-channel módban kódolt, nem pedig joint-stereo vagy monó módban.</translation> </message> <message> - <location filename="../src/constantgainchangedialog.cpp" line="37"/> <source>Don't show this warning again</source> <translation>Ne mutassa ismét ezt a figyelmeztetést</translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="14"/> <source>%1 - Constant Gain Change</source> <translation>%1 - Állandó erősítés változtatás</translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="28"/> <source>Select gain change to apply to all files</source> <translation>Állítsa be az összes fájlra alkalmazandó erősítést</translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="87"/> <source>dB</source> <translation></translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="124"/> <source>Apply to only one channel</source> <translation>Alkalmazás csak egy csatornára</translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="136"/> <source>Channel 1 (left)</source> <translation>1. csatorna (bal)</translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="146"/> <source>Channel 2 (right)</source> <translation>2. csatorna (jobb)</translation> </message> @@ -326,17 +262,14 @@ <context> <name>DisclaimerDialog</name> <message> - <location filename="../src/disclaimerdialog.ui" line="14"/> <source>%1 - DISCLAIMER</source> <translation>%1 - NYILATKOZAT</translation> </message> <message> - <location filename="../src/disclaimerdialog.ui" line="20"/> <source>DISCLAIMER</source> <translation>NYILATKOZAT</translation> </message> <message> - <location filename="../src/disclaimerdialog.ui" line="26"/> <source>This software and all the accompanying files are provided "as is" and without any warranties expressed or implied including but not limited to implied warranties of merchantability and fitness for a particular purpose. In no event will the author be liable for any damages whatsoever (including without limitations, damages for loss of business profits, business interruptions, loss of business information, or any other pecuniary loss) arising out of the use or inability to use this product.</source> <translation>Jelen szoftver és a kísérőfájlok "ahogy van" terjesztésűek, semmiféle kijelentett vagy burkolt garancia nélkül, beleértve, de kivételes célból nem korlátozva az értékesíthetőség és megfelelés burkolt garanciájára. @@ -346,27 +279,22 @@ <context> <name>DonationDialog</name> <message> - <location filename="../src/donationdialog.ui" line="14"/> <source>%1 - Donation</source> <translation>%1 - Adományozás</translation> </message> <message> - <location filename="../src/donationdialog.ui" line="20"/> <source>This program is completely freeware. There are no time limits, restrictions, disabled features, or anything like that. I wrote this program just because I wanted to, and if other people find it useful that's fine with me.</source> <translation>Ez a program teljesen igyenes (freeware). Nincsenek idő limitek, kikapcsolt funkciók vagy bármi ehhez hasonló. A programot saját akaratomból írtam, és ha más hasznosnak találja annak nagyon örülök.</translation> </message> <message> - <location filename="../src/donationdialog.ui" line="33"/> <source>BUT, if you feel like contributing something you can either donate money through PayPal (including the option to pay by credit card) by clicking on the "Donate" button, or e-mail me at this address to make other arrangements:</source> <translation>DE, ha úgy érzi szeretne hozzájárulni a fejlesztő költségeihez, adományozhat PayPal-on keresztül (beleérte a lehetőségét a bank kártyás fizetésnek) az "Adományozás" nyomógombbal, vagy csak küldjön egy email-t részemre, hogy más fizetési módot beszélhessünk meg.</translation> </message> <message> - <location filename="../src/donationdialog.ui" line="93"/> <source>Again, let me emphasize that this is COMPLETELY optional. You have full rights to use this program forever whether or not you make a donation.</source> <translation>Ismételten engedje meg hogy kihangsúlyozzam, az adományozás teljesen opcionális. A program teljeskörűen és örökre használható függetlenül az adományozástól.</translation> </message> <message> - <location filename="../src/donationdialog.ui" line="134"/> <source>Close</source> <translation>Bezárás</translation> </message> @@ -374,22 +302,18 @@ <context> <name>LogOptionsDialog</name> <message> - <location filename="../src/logoptionsdialog.cpp" line="64"/> <source>Add log file(s)</source> <translation>Napló fájl(ok) hozzáadása</translation> </message> <message> - <location filename="../src/logoptionsdialog.cpp" line="91"/> <source>Cannot write log file: %1</source> <translation>Naplózó %1 fájl nem írható</translation> </message> <message> - <location filename="../src/logoptionsdialog.ui" line="14"/> <source>%1 - Log Options</source> <translation>%1 - Naplózás beállítások</translation> </message> <message> - <location filename="../src/logoptionsdialog.ui" line="22"/> <source>Log file:</source> <translation>Naplozó fájl:</translation> </message> @@ -397,169 +321,132 @@ <context> <name>MainWindow</name> <message> - <location filename="../src/mainwindow.cpp" line="1321"/> <source>Error analyzing further samples (max time reached)</source> <translation>Hiva merült fel a minták további elemzésében (idő túllépés)</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1329"/> <source>Cancelled processing of %1</source> <translation>%1 feldolgozása megszakítva</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1341"/> <source>Cancelled processing.</source> <translation>Feldolgozás megszakítva.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1343"/> <source>%1 is probably corrupted now.</source> <translation>%1 valószínűleg korrupt mostanra.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1351"/> <source>%1 is not a stereo or dual-channel mp3</source> <translation>%1 nem sztereó vagy dupla-csatornás mp3</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1359"/> <source>Error while analyzing: %1</source> <translation>Hiba merült fel %1 elemzése közben</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1359"/> <source>Can't find any valid MP3 frames in file %1</source> <translation>Nem található valódi MP3 minta a %1 fájlban</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1367"/> <source>Can't open %1 for temp writing</source> <translation>%1 nem megnyitható ideiglenes írásra</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1375"/> <source>Can't modify file %1</source> <translation>%1 fájl nem módosítható</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1383"/> <source>Error analyzing %1.</source> <translation>Hiba merült %1 elemzésében.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1385"/> <source>This mp3 has some very corrupt data.</source> <translation>Ez az mp3 nagyon korrupt.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1393"/> <source>%1 is an MPEG Layer I file, not a layer III file</source> <translation>%1 egy MPEG I-es rétegű fájl, nem pedig III-as</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1401"/> <source>%1 is an MPEG Layer II file, not a layer III file</source> <translation>%1 egy MPEG II-es rétegű fájl, nem pedig III-as</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1409"/> <source>%1 is free format (not currently supported)</source> <translation>%1 szabad formátumú (jelenleg nem támogatott)</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1433"/> <source>Problem re-naming %1 to %2.</source> <translation>Hiba merült fel %1 átnevezésében %2-re.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1435"/> <source>The mp3 was correctly modified, but you will need to re-name it yourself.</source> <translation>Az mp3 megfelelően módosult, azonban a fájlt át kell nevezni manuálisan.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1450"/> <source>Not enough temp space on disk to modify %1.</source> <translation>Nincs elegenő ideiglenes hely a lemezen %1 módosítására.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1452"/> <source>Either clear space on disk, or go to "Options->Advanced..." and check the "Do not use Temp files" box.</source> <translation>Törölni kell a lemezről, vagy a haladó beállításokban meg kell jelölni a "Ideiglenes fájlok nélkül" kapcsolót.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1480"/> <source>Open Log Panel?</source> <translation>Naplózó felület megnyitása?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1481"/> <source>Would you like to display the errors in an opening log panel instead of seeing pop-up messages?</source> <translation>Szeretné megjeleníteni a hibákat egy megnyíló naplózó felületen, ahelyett hogy egyenként jönnének fel az üzenetek?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1515"/> <source>Don't bother me again with error messages</source> <translation>Ne zavarjon ismét hibaüzenetekkel</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1692"/> <source>Error while analyzing in file</source> <translation>Hiba merült fel a fájl elemzése közben</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2217"/> - <location filename="../src/mainwindow.cpp" line="2245"/> - <location filename="../src/mainwindow.cpp" line="2284"/> <source>No changes to %1</source> <translation>Nincs változás %1 fájlban</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2219"/> - <location filename="../src/mainwindow.cpp" line="2235"/> - <location filename="../src/mainwindow.cpp" line="2286"/> <source>Applying gain of %1 dB to %2</source> <translation>Erősítés végrehajtása %1 dB értékről %2 értékre</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2545"/> <source>&Play mp3 file</source> <translation>M&p3 fájl lejátszása</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2545"/> <source>Stop &playing mp3 file</source> <translation>M&p3 fájl lejátszásának megállítása</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2585"/> <source>Could not open donation URL</source> - <translation>Adományozáshoz vezető URL nem megnyitható</translation> + <translation type="vanished">Adományozáshoz vezető URL nem megnyitható</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2694"/> <source>Open analysis file</source> <translation>Elemzési fájl megnyitása</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2694"/> - <location filename="../src/mainwindow.cpp" line="2961"/> <source>Comma-separated files (*.m3g *.csv);;XML files (*.xml)</source> <translation>Vesszővel elválasztott fájlok (*.m3g *.csv);;XML fájlok (*.xml)</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2724"/> <source>DOM Parser</source> <translation>DOM elemző</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2725"/> <source>Parse error at line %1, column %2: %3</source> <translation>Elemzési hiba %1 sorban, %2 oszlopban: %3</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2837"/> <source>File may have been modified after analysis was saved: %1 Load saved analysis results anyhow?</source> @@ -567,7 +454,6 @@ Töltse be a korábbi analízis eredményeket mégis?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2868"/> <source>File size changed after analysis was saved: %1 Load saved analysis results anyhow?</source> @@ -576,7 +462,6 @@ Töltse be az analízis eredményeket mégis?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2902"/> <source>File already exists in list: %1 Load saved analysis results anyhow?</source> @@ -585,1127 +470,899 @@ Töltse be az analízis eredményeket mégis?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2961"/> <source>Save analysis file</source> <translation>Elemzési fájl mentése</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3063"/> <source>Add MP3 file(s)</source> <translation>MP3 fájl(ok) hozzáadása</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3063"/> <source>MP3 files (*.mp3)</source> <translation>MPS fájlok (*.mp3)</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3120"/> <source>Add Directory</source> <translation>Mappa hozzáadása</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3217"/> <source>Track analysis started...</source> <translation>Sáv elemzés megkezdődött...</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3244"/> <source>Clear Analysis?</source> <translation>Elemzés törlése?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3744"/> <source>Beep %1 file cannot be found</source> <translation>Hangjelzés %1 fájl nem található</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3747"/> <source>QSound is unavailable, QApplication::beep() will be used instead</source> - <translation>QSound nem használható, QApplication::beep() kerül használatba</translation> + <translation type="vanished">QSound nem használható, QApplication::beep() kerül használatba</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3818"/> - <location filename="../src/mainwindow.cpp" line="3835"/> <source>Help file %1 cannot be found</source> <translation>Súgó %1 fájl nem található</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3826"/> <source>Help file %1 is used</source> <translation>Súgó %1 fájl használatban van</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3245"/> <source>This will clear all analysis results. Are you sure?</source> <translation>Törölni fogja az összes jelenlegi elemzési eredményt. Biztos benne?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="562"/> <source>This will clear all log results. Are you sure?</source> <translation>Törölni fogja az összes eddigi naplózást. Biztos benne?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="564"/> - <location filename="../src/mainwindow.cpp" line="1482"/> - <location filename="../src/mainwindow.cpp" line="3247"/> <source>Don't ask me again</source> <translation>Ne kérdezzen meg újra</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="45"/> <source>Target "Normal" Volume:</source> <translation>Cél "normál" hangerő:</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="71"/> <source>dB (default %1)</source> <translation>dB (alapértelmezett %1)</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="136"/> <source>Cancel</source> <translation>Mégse</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="119"/> <source>File progress</source> <translation>Fájl folyamat</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="143"/> <source>Total progress</source> <translation>Teljes folyamat</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="170"/> <source>&File</source> <translation>&Fájl</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="189"/> <source>&Analysis</source> <translation>&Elemzés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="199"/> <source>&Modify Gain</source> <translation>Erősítés &módosítása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="211"/> <source>&Options</source> <translation>&Beállítások</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="215"/> <source>Tags</source> <translation>Címkék</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="228"/> - <location filename="../src/mainwindow.ui" line="322"/> <source>Toolbar</source> <translation>Eszköztár</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="240"/> <source>Filename Display</source> <translation>Fájlnév megjelenítés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="248"/> - <location filename="../src/mainwindow.ui" line="357"/> <source>Logs</source> <translation>Naplózások</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="252"/> <source>Output Type</source> <translation>Kimenet típusa</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="262"/> <source>Timestamp</source> <translation>Időbélyeg</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="299"/> <source>&Language</source> <translation>&Nyelv</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="305"/> <source>&Help</source> <translation>&Súgó</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="371"/> <source>Clear</source> <extracomment>Log output clear button</extracomment> <translation>Törlés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="397"/> - <location filename="../src/mainwindow.ui" line="400"/> <source>Errors</source> <translation>Hibák</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="403"/> <source>QCheckBox { color: red }</source> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="406"/> - <location filename="../src/mainwindow.ui" line="1173"/> - <location filename="../src/mainwindow.ui" line="1240"/> - <location filename="../src/mainwindow.cpp" line="1513"/> <source>Error</source> <translation>Hiba</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="416"/> - <location filename="../src/mainwindow.ui" line="419"/> <source>Analysis results</source> <translation>Elemzés eredmények</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="422"/> <source>QCheckBox { color: green }</source> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="425"/> - <location filename="../src/mainwindow.ui" line="1181"/> <source>Analysis</source> <translation>Elemzés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="435"/> - <location filename="../src/mainwindow.ui" line="438"/> <source>Gain changes</source> <translation>Erősítés változások</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="441"/> <source>QCheckBox { color: blue }</source> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="444"/> - <location filename="../src/mainwindow.ui" line="1189"/> <source>Change</source> <translation>Változtatás</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="454"/> - <location filename="../src/mainwindow.ui" line="457"/> <source>Back end output</source> <translation>Háttér oldal kimenete</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="460"/> <source>QCheckBox { color: black }</source> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="463"/> - <location filename="../src/mainwindow.ui" line="1197"/> <source>Back end</source> <translation>Háttér oldal</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="473"/> - <location filename="../src/mainwindow.ui" line="476"/> <source>Trace output</source> <translation>Nyomkövetés kimenete</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="482"/> - <location filename="../src/mainwindow.ui" line="1262"/> <source>Trace</source> <translation>Nyomkövetés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="529"/> <source>Load Analysis results</source> <translation>Elemzési eredmények betöltése</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="540"/> <source>Save Analysis results</source> <translation>Elemzési eredmények mentése</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="552"/> - <location filename="../src/mainwindow.ui" line="555"/> <source>Add mp3 file(s) to the list</source> <translation>MP3 fájl(ok) felvétele a listára</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="558"/> <source>Ctrl+F</source> <extracomment>File|Add_files</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="570"/> - <location filename="../src/mainwindow.ui" line="573"/> <source>Add all mp3 files in a folder</source> <translation>Egy mappában lévő összes MP3 fájl hozzáadása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="576"/> <source>Ctrl+D</source> <extracomment>File|Add_folder</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="587"/> <source>Ctrl+A</source> <extracomment>File|Select_all_files</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="598"/> <source>Ctrl+N</source> <extracomment>File|Select_no_files</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="609"/> <source>Ctrl+V</source> <extracomment>File|Invert_selection</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="621"/> <source>Clear selected file(s)</source> <translation>Kijelölt fájl(ok) törlése</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="624"/> <source>Clear File(s)</source> <translation>Fájl(ok) törlése</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="627"/> - <location filename="../src/mainwindow.ui" line="630"/> <source>Remove selected files(s) from list</source> <translation>Kijelölt fájl(ok) eltávolítása a listáról</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="642"/> <source>Clear All files</source> <translation>Minden fájl törlése</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="645"/> <source>Clear All</source> <translation>Minden törlése</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="648"/> - <location filename="../src/mainwindow.ui" line="651"/> <source>Remove all files from list</source> <translation>Összes fájl eltávolítása a listáról</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="680"/> <source>Do Replay Gain analysis on files</source> <translation>Replay Gain elemzés végrehajtása fájlokon</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="689"/> <source>Ctrl+T</source> <extracomment>Analysis|Track_analysis</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="707"/> <source>Do Replay Gain analysis on files as an album</source> <translation>Replay Gain elemzés végrehajtása a fájlokon, mint albumok elemein</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="710"/> <source>Analyze each file in the Album as part of a whole and then list details about the files</source> <translation>Elemez minden egyes fájlt az albumban, mint az egész részét, majd listázza a részleteket a fájlokról</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="716"/> <source>Ctrl+U</source> <extracomment>Analysis|Album_analysis</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="748"/> - <location filename="../src/mainwindow.ui" line="751"/> - <location filename="../src/mainwindow.cpp" line="158"/> <source>Track Gain</source> <translation>Sáv erősítés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="757"/> <source>Ctrl+G</source> <extracomment>Modify_gain|Track_gain</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="775"/> - <location filename="../src/mainwindow.cpp" line="164"/> <source>Album Gain</source> <translation>Album erősítés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="781"/> <source>Ctrl+B</source> <extracomment>Modify_gain|Album_gain</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="799"/> - <location filename="../src/mainwindow.ui" line="802"/> <source>Constant Gain</source> <translation>Állandó erősítés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="808"/> <source>Ctrl+O</source> <extracomment>Modify_gain|Constant_gain</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="827"/> <source>Always on Top</source> <translation>Mindig felül látható</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="838"/> <source>Work on Selected files only</source> <translation>Csak a kijelölt fájlok feldolgozása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="852"/> <source>Add Subfolders</source> <translation>Almappák hozzáadása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="863"/> <source>Preserve file date/time</source> <translation>Fájl dátum/idő megtartása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="874"/> <source>No check for Layer I or II</source> <translation>Nincs réteg I vagy II vizsgálat</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="885"/> <source>Don't clip when doing Track Gain</source> <translation>Sáv erősítésekor nincs vágás</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="896"/> <source>Minimize to Tray</source> <translation>Ikonként a tálcán</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="907"/> <source>Beep when finished</source> <translation>Hangjelzés befejezéskor</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="915"/> <source>Reset Default Column Widths</source> <translation>Oszlopszélességek alaphelyzetbe állítása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="923"/> <source>Reset "Warning" messages</source> <translation>Figyelmeztetések visszaállítása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="942"/> <source>Ignore (do not read or write tags)</source> <translation>Kihagyás (nincs címke olvasás vagy írás)</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="953"/> <source>Big</source> <translation>Nagy</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="967"/> <source>Show Path/File</source> <translation>Útvonal/fájl látszik</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="999"/> <source>Ctrl+M</source> <extracomment>Analysis|Max_no-clip_analysis</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1022"/> <source>Ctrl+X</source> <extracomment>Modify_gain|Max_no-clip_gain_for_each_file</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1045"/> <source>Ctrl+L</source> <extracomment>Modify_gain|Max_no-clip_gain_for_album</extracomment> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1056"/> <source>Re-calculate (do not read tags)</source> <translation>Újraszámolás (nincs címke olvasás)</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1064"/> <source>Don't check while adding files</source> <translation>Átvizsgálás mellőzése fájl hozzáadásnál</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1075"/> <source>Remove Tags from files</source> <translation>Címkék eltávolítása fájlokból</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1086"/> <source>Small</source> <translation>Kicsi</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1097"/> <source>Text only</source> <translation>Csak szöveg</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1108"/> <source>None</source> <translation>Nincs</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1119"/> <source>Show File only</source> <translation>Csak fájl látszik</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1130"/> <source>Show Path && File</source> <translation>Útvonal és fájl látszik</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1013"/> - <location filename="../src/mainwindow.ui" line="1016"/> <source>This will change the gain on each mp3 file so that it is as loud as possible without clipping.</source> <translation>Megváltoztatja az erősséget minden egyes mp3 fájlon olyan hangosra, hogy még épp ne legyen vágás.</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="549"/> <source>Add &File(s)</source> <translation>&Fájl(ok) hozzáadása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="567"/> <source>Add Fol&der</source> <translation>&Mappa hozzáadása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="584"/> <source>Select &All Files</source> <translation>Mi&nden fájl kijelölése</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="595"/> <source>Select &No Files</source> <translation>Kijelölés meg&szüntetése</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="606"/> <source>In&vert selection</source> <translation>Kijelölés meg&fordítása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="656"/> - <location filename="../src/mainwindow.cpp" line="374"/> <source>&Quit</source> <translation>&Kilépés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="659"/> <source>Ctrl+Q</source> <extracomment>File|Quit</extracomment> <translation>Ctrl+K</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="677"/> <source>&Track Analysis</source> <translation>&Sáv elemzés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="683"/> <source>Analyze each file individually and then list details of the files</source> <translation>Elemez minden egyes fájlt egyenként, majd listázza a fájlok részleteit</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="704"/> <source>Alb&um Analysis</source> <translation>Al&bum elemzés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="724"/> <source>&Clear Analysis</source> <translation>Elemzés &törlése</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="727"/> <source>Clear the analysis results in the file list</source> <translation>Törli az elemzés eredményeket a fájl listából</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="745"/> <source>Track &Gain</source> <translation>Sáv &erősítés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="754"/> <source>Volume-correct all files listed in the File List to match the Target Volume</source> <translation>Hangerő módosítása az összes fájlon a listában, hogy egyenként megegyezzenek a cél hangerővel</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="772"/> <source>Al&bum Gain</source> <translation>Al&bum erősítés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="778"/> <source>Volume-correct all files listed in the File List so that the overall album volume matches the Target Volume</source> <translation>Hangerő módosítás az összes fájlnak a listában, hogy az átlagos album hangerő megegyezzen a cél hangerővel</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="796"/> <source>&Constant Gain</source> <translation>&Állandó erősítés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="805"/> <source>Absolute gain change of all files listed in the File List</source> <translation>Abszolút erősítés változtatás az összes listázott fájlban</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="816"/> <source>&Undo Gain changes</source> <translation>Erősítés változtatások &visszaállítása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="819"/> <source>Undo all gain changes to the mp3 files in the list</source> <translation>Visszaállítja az erősítés változtatásokat a lista mp3 fájljaiban</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="830"/> <source>MP3Gain window will always stay on top of other windows</source> <translation>Az alkalmazás ablaka mindig a többi ablak felett fog tartózkodni</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="841"/> <source>Only those files that are currently selected will be operated on</source> <translation>Csak az aktuálisan kijelölt fájlokon fognak a műveletek végrehajtódni</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="855"/> <source>When you Add a Folder, all of the mp3s in all of the folders inside the selected folder will be added to the list</source> <translation>Mappa hozzáadásakor, a kiválasztott mappa alatti összes mappának az összes mp3 fájlja hozzáadódik a listához</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="866"/> <source>Changed files will keep their original timestamp</source> <translation>Megváltoztatott fájlok megtartják az eredeti időbélyegüket</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="877"/> <source>Forces mp3Gain to skip the safety check, allowing you to change the gain on these mis-identified files</source> <translation>Kényszeríti az alkalmazást, hogy mellőze a biztonsági ellenőrzést, lehetőve téve az erősítést a rosszul azonosított fájlokon</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="888"/> <source>When you do Track Gain, if the suggested Track gain will cause clipping then MP3Gain will apply the maximum non-clipping gain instead</source> <translation>Sáv erősítéskor, ha a javasolt erősítés vágást okozna, akkor az alkalmazás inkább a maximális, még vágást nem okozó, erősítést alkalmazza</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="899"/> <source>When you minimize the MP3Gain window it will appear as an icon in the system tray notification area</source> <translation>Az alkalmazás ablakának minimalizálásakor, a rendszer tálcán megjelenik egy, az alkalmazás reprezentáló, ikon</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="910"/> <source>MP3Gain will make a default beep sound when it finishes a task</source> <translation>Az alkalmazás hangjelzést ad miután befejezett egy műveletet</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="918"/> <source>Reset the column positions & sizes to their default settings</source> <translation>Visszaállítja az oszlop pozíciókat és méreteket az eredeti beállításokra</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="926"/> <source>Makes earlier suppressed warning and questions messages start popping up again</source> <translation>A korábban kikapcsolt figyelmezetés és kérdés üzenetek ismét megjelennek felugró dialógus ablakban</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="931"/> <source>&Advanced...</source> <translation>&Speciális...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="934"/> <source>Allows you to modify some extra features</source> <translation>Lehetővé teszi pár extra tulajdonság módosítását</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="956"/> <source>Modify the look of the toolbar to Big size</source> <translation>Módosítja az eszköztár méretét Nagyra</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="970"/> <source>Path/File are displayed in a single column of the File List</source> <translation>Útvonal/Fájl megjelenítés a fájl lista egyetlen oszlopába történik</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="975"/> <source>&Contents</source> <translation>&Tartalomjegyzék</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="980"/> <source>&Disclaimer...</source> <translation>N&yilatkozat...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="985"/> <source>&About...</source> <translation>&Névjegy...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="993"/> <source>&Max No-clip Analysis</source> <translation>&Max Vágásmentes Elemzés</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="996"/> <source>Find only the peak amplitudes of each of the mp3s in the list without spending any extra time</source> <translation>Keresse csak a csúcs amplitúdókat minden egyes mp3 fájlnak a listában minimális idő felhasználással</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1010"/> <source>Ma&x No-clip Gain for Each file</source> <translation>Ma&x Vágásmentes Erősítés fájlonként</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1019"/> <source>Change the gain on each mp3 file so that it is as loud as possible without clipping</source> <translation>Megváltoztatja az erősítést minden egyes mp3 fájlon olyan mértékben, hogy még épp ne legyen vágás</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1033"/> <source>Max No-c&lip Gain for Album</source> <translation>Max Vágásmentes Erősítés A&lbumra</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1036"/> - <location filename="../src/mainwindow.ui" line="1039"/> <source>This will look at each folder in the file list, find the single maximum gain which will not cause any clipping in any of the mp3s in the folder, and then apply that single gain change to all the mp3s in the folder.</source> <translation>A fájl lista minden elemére keres egyetlen olyan erősítési értéket, amely még nem okoz vágást egyetlen mp3 fájlnál sem, majd alkalmazza ezt az erősítést a teljes listára.</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1042"/> <source>Look at each folder in the file list, find the single maximum gain which will not cause any clipping in any of the mp3s in the folder, and then apply that single gain change to all the mp3s in the folder</source> <translation>Benéz minden egyes mappába a fájl listában, megkeresi azt az egyetlen maximális erősítést, amely még nem okoz vágást egyik mp3 fájlban sem a mappában, majd alkalmazza ezt az erősítést a mappa összes mp3 fájljára</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1089"/> <source>Modify the look of the toolbar to Small size</source> <translation>Módosítja az eszköztára méretét Kicsire</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1100"/> <source>Modify the look of the toolbar to Text format only</source> <translation>Módosítja az eszköztár megjelenését Szöveg módra</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1111"/> <source>Switch off the toolbar</source> <translation>Kikapcsolja az eszköztárat</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1122"/> <source>Only File without Path are displayed in the File List</source> <translation>Csak Fájlok, Útvonal nélkül, jelenítődnek meg a fájl listában</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1133"/> <source>Path and File are displayed in separated columns of the File List</source> <translation>Mind az Útvonal, mind a Fájl megjelenítődik külön oszlopokban a fájl listában</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1138"/> <source>Resize column widths by content</source> <translation>Oszlopszélességek újraigazítása tartalomtól függően</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1141"/> <source>Modify the column sizes to have enough space for their content</source> <translation>Módosítja az oszlop méreteket, hogy az aktuális tartalom elférjen bennük</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1149"/> <source>&Original (English)</source> <translation>&Eredeti angol</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1154"/> <source>&Back end...</source> <translation>&Háttér kiszolgáló oldal...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1157"/> <source>Set the location of the back end mp3gain</source> <translation>Beállítja az elérhetőségét a háttér oldali mp3gain fájlnak</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1162"/> <source>File...</source> <translation>Fájl...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1165"/> <source>Set the output log file</source> <translation>Naplózás kimeneti fájljának beállítása</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1208"/> <source>To File</source> <translation>Fájlba</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1211"/> <source>Each line in the log has a timestamp</source> <translation>Minden egyes sor a naplózásban kap egy időbélyeget</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1219"/> <source>To Panel</source> <translation>Panelba</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1227"/> <source>Automatically opened if error</source> <translation>Automatikusan megnyitódik hiba esetén</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1235"/> <source>Panel</source> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1248"/> <source>Open automatically panel</source> <translation>Automatikusan megnyitódik a panel</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1251"/> - <location filename="../src/mainwindow.ui" line="1254"/> <source>Log panel is automaticaly opened if error occurs</source> <translation>Naplózó panel automatikusan megnyitódik hiba esetén</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="674"/> <source>Language</source> <extracomment>Translate it to your language in your language. For example for Italian translation it is Italiano.</extracomment> <translation>Magyar</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="152"/> <source>Path/File</source> <translation>Útvonal/Fájl</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="153"/> <source>Path</source> <translation>Útvonal</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="154"/> <source>File</source> <translation>Fájl</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="155"/> <source>Volume</source> <translation>Hangerő</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="156"/> <source>Max Amplitude</source> <translation>Max Amplitúdó</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="157"/> <source>clipping</source> <translation>vágás</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="159"/> <source>dBGain</source> <translation>dBErősítés</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="161"/> <source>Max Noclip Gain</source> <translation>Max. vágás nélküli erősítés</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="162"/> <source>Album Volume</source> <translation>Album hangerő</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="163"/> <source>Album Max Amplitude</source> <translation>Album Max Amplitudó</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="165"/> <source>Album dBGain</source> <translation>Album dBErősítés</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="166"/> <source>clip(Album)</source> <translation>vágás(Album)</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="337"/> <source>Number of files in the list</source> <translation>Fájlok száma a listában</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="371"/> <source>&Restore</source> <translation>&Visszahelyezés</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="375"/> <source>Ctrl+Q</source> <comment>SystemTrayIcon|Quit</comment> <translation>Ctrl+K</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="434"/> - <location filename="../src/mainwindow.cpp" line="998"/> - <location filename="../src/mainwindow.cpp" line="1004"/> <source>No operation running</source> <translation>Inaktív, nem fut művelet</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="440"/> <source>Minimize to tray option is checked and tray icon should be created but system tray is unavailable</source> <translation>Ikonként tálcára opció meg van jelölve, így a tálca ikont létre kellene hozni, azonban a rendszer tálca nem elérhető</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="463"/> <source>Lossless volume modification of MP3 files</source> <translation>Veszteségnélküli hangerő módosítása MP3 fájloknak</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="466"/> <source>System tray does not support balloon messages</source> <translation>Rendszer tálca nem támogatja a léggömb üzeneteket</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="485"/> <source>Fatal Error</source> <translation>Súlyos hiba</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="486"/> <source>Playing of %1 went into failure</source> <translation>%1 lejátszása hibával végződött</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="561"/> <source>Clear Logs?</source> <translation>Naplózások törlése?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="628"/> <source>Translation file %1 is loaded</source> <translation>Fordítási %1 fájl betöltve</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="634"/> <source>%1 locale is used</source> <translation>%1 lokál használatban</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="641"/> <source>No translation file is necessary</source> <translation>Fordítási fáljra nincs szükség</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="643"/> <source>Translation file %1 cannot be found, %2 locale is refused</source> <translation>Fordítási %1 fájl nem található, %2 lokál visszautasítva</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="647"/> <source>Default %1 locale is used</source> <translation>Alap %1 lokál használatban</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="756"/> <source>Cannot write log file: %1</source> <translation>Nem írhato a naplózó %1 fájl</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="996"/> <source>Work in progress: %1%</source> <translation>Munka folyamatban: %1%</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1092"/> <source>Y</source> <comment>Yes flag in some clipping fields of the file list</comment> <translation>I</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2640"/> <source>MP3Gain back end cannot be found. Please make it available!</source> <translation>Kiszolgáló oldali MP3Gain program nem található. Kérem tegye elérhetővé!</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2644"/> <source>Required MP3Gain back end version is %1 or later, but only %2 is found. Please make a newer version available!</source> <translation>Kiszolgáló oldali Mp3Gain programból legalább %1 verzió szükséges, de csak %2 található meg. Kérem tegyen elérhetőve egy újabb verziót!</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="160"/> <source>clip(Track)</source> <translation>vágás(Sáv)</translation> </message> + <message> + <source>Clear logs</source> + <translation>Naplózások törlése</translation> + </message> + <message> + <source>Copy logs to clipboard</source> + <translation>Naplózások vágólapra másolása</translation> + </message> + <message> + <source>Copy</source> + <translation>Másolás</translation> + </message> + <message> + <source>Failed to decode MPEG frame: Error reading the stream. (code %1)</source> + <translation>Nem sikerült dekódolni az MPEG-frame-et: Hiba történt az adatfolyam olvasása közben. (kód %1)</translation> + </message> </context> <context> <name>QDialogButtonBox</name> <message> - <location filename="../src/mainwindow.cpp" line="126"/> <source>OK</source> <translation></translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="127"/> <source>Open</source> <translation>Megnyitás</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="128"/> <source>Save</source> <translation>Mentés</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="129"/> <source>Cancel</source> <translation>Mégse</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="130"/> <source>Close</source> <translation>Bezárás</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="131"/> <source>Discard</source> <translation>Eldob</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="132"/> <source>Apply</source> <translation>Alkalmazza</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="133"/> <source>Reset</source> <translation>Visszaállítás</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="134"/> <source>Restore Defaults</source> <translation>Alapértelemezett beállítások visszaállítása</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="135"/> <source>Help</source> <translation>Súgó</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="136"/> <source>Save All</source> <translation>Az összes mentése</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="137"/> <source>&Yes</source> <translation>&Igen</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="138"/> <source>Yes to &All</source> <translation>Igen az &összesre</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="139"/> <source>&No</source> <translation>&Nem</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="140"/> <source>N&o to All</source> <translation>&Nem az összesre</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="142"/> <source>Abort</source> <translation>Megszakítás</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="143"/> <source>Retry</source> <translation>Újra próbálkozás</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="144"/> <source>Ignore</source> <translation>Mellőzés</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="146"/> <source>Don't Save</source> <translation>Ne mentse</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="147"/> <source>Close without Saving</source> <translation>Bezárás mentés nélkül</translation> </message>
View file
qmp3gain-0.9.3.tar.xz/translations/qmp3gain_it.ts -> qmp3gain-0.9.4.tar.xz/translations/qmp3gain_it.ts
Changed
@@ -4,73 +4,58 @@ <context> <name>AboutDialog</name> <message> - <location filename="../src/aboutdialog.ui" line="14"/> <source>%1 - About</source> <translation>%1 - Informazioni</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="69"/> <source>Back end (%1)</source> <translation>Back end (%1)</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="103"/> <source>%1 (GUI)</source> <translation>%1 (GUI)</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="167"/> <source>Latest version of %1 at</source> <translation>Ultima versione di %1 a</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="206"/> <source>Latest version of back end at</source> <translation>Ultima versione del backend a</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="245"/> <source>Contact the author, Zsolt Branyiczky at</source> <translation>Contatta l'autore, Zsolt Branyiczky a</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="288"/> <source>The back end makes use of a modified version of mpglib. The original version of mpglib can be found at</source> <translation>Il backend fa uso di una versione modificata di mpglib. La versione originale di mpglib può essere trovata su</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="394"/> <source>Send a donation to the author</source> <translation>Invia una donazione all'autore</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="400"/> <source>Donation</source> <translation>Donazione</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="420"/> <source>Close</source> <translation>Chiudi</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="76"/> - <location filename="../src/aboutdialog.ui" line="96"/> <source>Version %1</source> <translation>Versione %1</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="125"/> <source>Performs ReplayGain analysis of MP3 files. For more information about ReplayGain, go to</source> <translation>Esegue l'analisi ReplayGain dei file MP3. Per maggiori informazioni su ReplayGain, vai a</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="330"/> <source>Thanks to Marc Heubeck for making the control buttons look nicer, to Bill MacEachern for making the Help file more profession, and to Glen Swer for the MP3Gain back end (and original GUI).</source> <translation>Grazie a Marc Heubeck per aver reso i pulsanti di controllo più belli, a Bill MacEachern per aver reso il file di aiuto più professionale e a Glen Swer per il backend MP3Gain (e la GUI originale).</translation> </message> <message> - <location filename="../src/aboutdialog.ui" line="365"/> <source>English translation: Your Name</source> <translation>Traduzione in italiano: e.tabeta «e.tabeta@yahoo.it»</translation> </message> @@ -78,153 +63,122 @@ <context> <name>AdvancedOptionsDialog</name> <message> - <location filename="../src/advancedoptionsdialog.ui" line="28"/> <source>Thread Priority</source> <translation>Priorità del compito</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="44"/> <source>Realtime</source> <translation>In tempo reale</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="55"/> <source>High</source> <translation>Alta</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="65"/> <source>Normal</source> <translation>Normale</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="78"/> <source>Idle</source> <translation>Inattiva</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="162"/> <source>Performance</source> <translation>Prestazioni</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="14"/> <source>%1 - Advanced Options</source> <translation>%1 - Opzioni avanzate</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="25"/> <source>This adjusts what priority the program has in using your computer's resources</source> <translation>Questo regola la priorità che il programma ha nell'usare le risorse del tuo computer</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="40"/> <source>Applicaton has maximum priority of the computer's resource. Its usage is not recommended.</source> <translation>L'applicazione ha la priorità massima della risorsa del computer. Il suo utilizzo non è raccomandato.</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="51"/> <source>Applicaton has high priority of the computer's resource. Its usage might be not recommended</source> <translation>L'applicazione ha la priorità alta della risorsa del computer. Il suo utilizzo potrebbe non essere raccomandato</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="62"/> <source>Applicaton has normal priority of the computer's resource</source> <translation>L'applicazione ha la priorità normale delle risorse del computer</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="75"/> <source>Applicaton has slight priority of the computer's resource</source> <translation>L'applicazione ha una leggera priorità sulle risorse del computer</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="96"/> <source>Extra features</source> <translation>Caratteristiche extra</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="105"/> <source>New analysis and gain functions can be activated</source> <translation>È possibile attivare nuove funzioni di analisi e guadagno</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="115"/> <source>Show "Max Amplitude" and dBGain fields in the list</source> <translation>Mostra i campi "Ampiezza max" e dBGain nell'elenco</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="121"/> <source>Show hidden fields</source> <translation>Mostra i campi nascosti</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="133"/> <source>Beep after</source> <translation>Beep dopo</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="140"/> <source>Makes beep sound if the opeartion takes more time in seconds than this value</source> <translation>Emette un segnale acustico se l'operazione richiede più tempo in secondi di questo valore</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="150"/> <source>seconds</source> <translation>secondi</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="168"/> <source>Gain modifications can be done directly in the files</source> <translation>Le modifiche al guadagno possono essere eseguite direttamente nei file</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="171"/> <source>Do not use Temp files</source> <translation>Non usare i file temporanei</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="178"/> <source>File progress bar can be switch off</source> <translation>La barra di avanzamento del file può essere disattivata</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="181"/> <source>Do not show file progress</source> <translation>Non mostrare l'avanzamento del file</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="195"/> <source>Extra output log</source> <translation>Registro di uscita extra</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="284"/> - <location filename="../src/advancedoptionsdialog.ui" line="300"/> <source>Sets the depth of the trace, it's mostly for possible bug hunting</source> <translation>Imposta la profondità della traccia, è principalmente per una possibile caccia agli errori</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="216"/> <source>Back end log depth</source> <translation>Profondità registro di backend</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="223"/> - <location filename="../src/advancedoptionsdialog.ui" line="254"/> <source>Sets the depth of communication with the MP3Gain back end</source> <translation>Imposta la profondità della comunicazione con il back-end MP3Gain</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="277"/> <source>Trace log depth</source> <translation>Profondità registro traccia</translation> </message> <message> - <location filename="../src/advancedoptionsdialog.ui" line="108"/> <source>Enable "Maximizing" features</source> <translation>Abilita la caratteristica "Massimizza"</translation> </message> @@ -232,47 +186,38 @@ <context> <name>BackEndDialog</name> <message> - <location filename="../src/backenddialog.ui" line="14"/> <source>%1 - Specify back end</source> <translation>%1 - Specifica backend</translation> </message> <message> - <location filename="../src/backenddialog.ui" line="22"/> <source>Back end:</source> <translation>Backend:</translation> </message> <message> - <location filename="../src/backenddialog.ui" line="58"/> <source>Status: %1</source> <translation>Stato: %1</translation> </message> <message> - <location filename="../src/backenddialog.ui" line="51"/> <source>Version: %1</source> <translation>Versione: %1</translation> </message> <message> - <location filename="../src/backenddialog.cpp" line="58"/> <source>invalid</source> <translation>non valido</translation> </message> <message> - <location filename="../src/backenddialog.cpp" line="62"/> <source>invalid (not found)</source> <translation>non valido (non trovato)</translation> </message> <message> - <location filename="../src/backenddialog.cpp" line="66"/> <source>invalid (%1 or later required)</source> <translation>non valido (%1 o successivo richiesto)</translation> </message> <message> - <location filename="../src/backenddialog.cpp" line="70"/> <source>ok</source> <translation>ok</translation> </message> <message> - <location filename="../src/backenddialog.cpp" line="85"/> <source>Select back end mp3gain executable file</source> <translation>Seleziona il file eseguibile di backend mp3gain</translation> </message> @@ -280,47 +225,38 @@ <context> <name>ConstantGainChangeDialog</name> <message> - <location filename="../src/constantgainchangedialog.cpp" line="34"/> <source>Warning</source> <translation>Attenzione</translation> </message> <message> - <location filename="../src/constantgainchangedialog.cpp" line="35"/> <source>This function will only work if the mp3 is encoded as stereo or dual channel, NOT joint-stereo or mono.</source> <translation>Questa funzione lavorerà solo se l'mp3 è codificato come stereo o in doppio canale, NON joint-stereo o mono.</translation> </message> <message> - <location filename="../src/constantgainchangedialog.cpp" line="37"/> <source>Don't show this warning again</source> <translation>Non mostrare più questo avviso</translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="14"/> <source>%1 - Constant Gain Change</source> <translation>%1 - Modifica guadagno costante</translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="28"/> <source>Select gain change to apply to all files</source> <translation>Seleziona la modifica del guadagno da applicare a tutti i file</translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="87"/> <source>dB</source> <translation>dB</translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="124"/> <source>Apply to only one channel</source> <translation>Applica solo ad un canale</translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="136"/> <source>Channel 1 (left)</source> <translation>Canale 1 (sinistra)</translation> </message> <message> - <location filename="../src/constantgainchangedialog.ui" line="146"/> <source>Channel 2 (right)</source> <translation>Canale 2 (destra)</translation> </message> @@ -328,17 +264,14 @@ <context> <name>DisclaimerDialog</name> <message> - <location filename="../src/disclaimerdialog.ui" line="14"/> <source>%1 - DISCLAIMER</source> <translation>%1 - CONDIZIONI DI UTILIZZO</translation> </message> <message> - <location filename="../src/disclaimerdialog.ui" line="20"/> <source>DISCLAIMER</source> <translation>LEGGERE ATTENTAMENTE</translation> </message> <message> - <location filename="../src/disclaimerdialog.ui" line="26"/> <source>This software and all the accompanying files are provided "as is" and without any warranties expressed or implied including but not limited to implied warranties of merchantability and fitness for a particular purpose. In no event will the author be liable for any damages whatsoever (including without limitations, damages for loss of business profits, business interruptions, loss of business information, or any other pecuniary loss) arising out of the use or inability to use this product.</source> <translation>Questo software e tutti i file allegati sono forniti "così come sono" e senza alcuna garanzia espressa o implicita, incluse ma non limitate a garanzie implicite di commerciabilità e idoneità per uno scopo particolare. @@ -348,27 +281,22 @@ <context> <name>DonationDialog</name> <message> - <location filename="../src/donationdialog.ui" line="14"/> <source>%1 - Donation</source> <translation>%1 - Donazione</translation> </message> <message> - <location filename="../src/donationdialog.ui" line="20"/> <source>This program is completely freeware. There are no time limits, restrictions, disabled features, or anything like that. I wrote this program just because I wanted to, and if other people find it useful that's fine with me.</source> <translation>Questo programma è completamente gratuito. Non ci sono limiti di tempo, restrizioni, funzionalità disabilitate o cose del genere. Ho scritto questo programma solo perché volevo, e se altre persone lo trovano utile per me va bene.</translation> </message> <message> - <location filename="../src/donationdialog.ui" line="33"/> <source>BUT, if you feel like contributing something you can either donate money through PayPal (including the option to pay by credit card) by clicking on the "Donate" button, or e-mail me at this address to make other arrangements:</source> <translation>MA, se hai voglia di contribuire con qualcosa, puoi donare denaro tramite PayPal (inclusa l'opzione di pagamento con carta di credito) facendo clic sul pulsante "Dona", o inviarmi un'e-mail a questo indirizzo per prendere altri accordi:</translation> </message> <message> - <location filename="../src/donationdialog.ui" line="93"/> <source>Again, let me emphasize that this is COMPLETELY optional. You have full rights to use this program forever whether or not you make a donation.</source> <translation>Ancora una volta, lasciatemi sottolineare che questo è COMPLETAMENTE facoltativo. Hai tutti i diritti per utilizzare questo programma per sempre, indipendentemente dal fatto che tu effettui una donazione.</translation> </message> <message> - <location filename="../src/donationdialog.ui" line="134"/> <source>Close</source> <translation>Chiudi</translation> </message> @@ -376,22 +304,18 @@ <context> <name>LogOptionsDialog</name> <message> - <location filename="../src/logoptionsdialog.cpp" line="64"/> <source>Add log file(s)</source> <translation>Aggiungi i file di registro</translation> </message> <message> - <location filename="../src/logoptionsdialog.cpp" line="91"/> <source>Cannot write log file: %1</source> <translation>Impossibile scrivere il file di regsitro: %1</translation> </message> <message> - <location filename="../src/logoptionsdialog.ui" line="14"/> <source>%1 - Log Options</source> <translation>%1 - Opzioni registro</translation> </message> <message> - <location filename="../src/logoptionsdialog.ui" line="22"/> <source>Log file:</source> <translation>File di registro:</translation> </message> @@ -399,169 +323,132 @@ <context> <name>MainWindow</name> <message> - <location filename="../src/mainwindow.cpp" line="1321"/> <source>Error analyzing further samples (max time reached)</source> <translation>Errore nell'analisi di ulteriori campioni (tempo max raggiunto)</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1329"/> <source>Cancelled processing of %1</source> <translation>Elaborazione annullata di %1</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1341"/> <source>Cancelled processing.</source> <translation>Elaborazione annullata.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1343"/> <source>%1 is probably corrupted now.</source> <translation>%1 ora è probabilmente danneggiato.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1351"/> <source>%1 is not a stereo or dual-channel mp3</source> <translation>%1 non è un mp3 stereo o a doppio canale</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1359"/> <source>Error while analyzing: %1</source> <translation>Errore durante l'analisi: %1</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1359"/> <source>Can't find any valid MP3 frames in file %1</source> <translation>Impossibile trovare fotogrammi MP3 validi nel file %1</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1367"/> <source>Can't open %1 for temp writing</source> <translation>Impossibile aprire %1 per la scrittura temporanea</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1375"/> <source>Can't modify file %1</source> <translation>Impossibile modificare il file %1</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1383"/> <source>Error analyzing %1.</source> <translation>Errore nell'analisi di %1.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1385"/> <source>This mp3 has some very corrupt data.</source> <translation>Questo mp3 ha alcuni dati molto corrotti.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1393"/> <source>%1 is an MPEG Layer I file, not a layer III file</source> <translation>%1 è un file MPEG Layer I, non è un file Layer III</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1401"/> <source>%1 is an MPEG Layer II file, not a layer III file</source> <translation>%1 è un file MPEG Layer II, non è un file Layer III</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1409"/> <source>%1 is free format (not currently supported)</source> <translation>%1 è un formato libero (non attualmente supportato)</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1433"/> <source>Problem re-naming %1 to %2.</source> <translation>Problema di rinomina di %1 in %2.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1435"/> <source>The mp3 was correctly modified, but you will need to re-name it yourself.</source> <translation>L'mp3 è stato modificato correttamente, ma dovrai rinominarlo tu stesso.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1450"/> <source>Not enough temp space on disk to modify %1.</source> <translation>Spazio temporaneo su disco insufficiente per modificare %1.</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1452"/> <source>Either clear space on disk, or go to "Options->Advanced..." and check the "Do not use Temp files" box.</source> <translation>Libera spazio sul disco o vai su "Opzioni->Avanzate ..." e seleziona la casella "Non utilizzare file temporanei".</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1480"/> <source>Open Log Panel?</source> <translation>Aprire il pannello di registro?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1481"/> <source>Would you like to display the errors in an opening log panel instead of seeing pop-up messages?</source> <translation>Vuoi visualizzare gli errori aprendo un pannello di registro invece di vedere messaggi pop-up?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1515"/> <source>Don't bother me again with error messages</source> <translation>Non disturbarmi più con i messaggi di errore</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1692"/> <source>Error while analyzing in file</source> <translation>Errore durante l'analisi nel file</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2217"/> - <location filename="../src/mainwindow.cpp" line="2245"/> - <location filename="../src/mainwindow.cpp" line="2284"/> <source>No changes to %1</source> <translation>Nessuna modifica a %1</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2219"/> - <location filename="../src/mainwindow.cpp" line="2235"/> - <location filename="../src/mainwindow.cpp" line="2286"/> <source>Applying gain of %1 dB to %2</source> <translation>Sto applicando un guadagno di %1 dB a %2</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2545"/> <source>&Play mp3 file</source> <translation>Ri&produci file mp3</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2545"/> <source>Stop &playing mp3 file</source> <translation>Ferma ri&produzione del file mp3</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2585"/> <source>Could not open donation URL</source> - <translation>Impossibile aprire l'URL per la donazione</translation> + <translation type="vanished">Impossibile aprire l'URL per la donazione</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2694"/> <source>Open analysis file</source> <translation>Apri file di analisi</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2694"/> - <location filename="../src/mainwindow.cpp" line="2961"/> <source>Comma-separated files (*.m3g *.csv);;XML files (*.xml)</source> <translation>File separati da virgole (*.m3g *.csv);;XML files (*.xml)</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2724"/> <source>DOM Parser</source> <translation>Analizzatore DOM</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2725"/> <source>Parse error at line %1, column %2: %3</source> <translation>Errore di analisi alla riga %1, colonna %2: %3</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2837"/> <source>File may have been modified after analysis was saved: %1 Load saved analysis results anyhow?</source> @@ -570,7 +457,6 @@ Caricare comunque i risultati dell'analisi salvati?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2868"/> <source>File size changed after analysis was saved: %1 Load saved analysis results anyhow?</source> @@ -579,7 +465,6 @@ Caricare comunque i risultati dell'analisi salvati?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2902"/> <source>File already exists in list: %1 Load saved analysis results anyhow?</source> @@ -588,1128 +473,900 @@ Caricare comunque i risultati dell'analisi salvati?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2961"/> <source>Save analysis file</source> <translation>Salva il file di analisi</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3063"/> <source>Add MP3 file(s)</source> <translation>Aggiungi i file MP3</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3063"/> <source>MP3 files (*.mp3)</source> <translation>File MP3 (*.mp3)</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3120"/> <source>Add Directory</source> <translation>Aggiungi cartella</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3217"/> <source>Track analysis started...</source> <translation>Avviata l'analisi della traccia ...</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3244"/> <source>Clear Analysis?</source> <translation>Pulire l'analisi?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3744"/> <source>Beep %1 file cannot be found</source> <translation>Segnale acustico %1 file non trovato</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3747"/> <source>QSound is unavailable, QApplication::beep() will be used instead</source> - <translation>QSound non è disponibile; verrà invece utilizzato QApplication::beep()</translation> + <translation type="vanished">QSound non è disponibile; verrà invece utilizzato QApplication::beep()</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3818"/> - <location filename="../src/mainwindow.cpp" line="3835"/> <source>Help file %1 cannot be found</source> <translation>Impossibile trovare il file della guida %1</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3826"/> <source>Help file %1 is used</source> <translation>Viene utilizzato il file della guida %1</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="3245"/> <source>This will clear all analysis results. Are you sure?</source> <translation>Questo cancellerà tutti i risultati dell'analisi. Sei sicuro?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="562"/> <source>This will clear all log results. Are you sure?</source> <translation>Questo cancellerà tutti i risultati del registro. Sei sicuro?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="564"/> - <location filename="../src/mainwindow.cpp" line="1482"/> - <location filename="../src/mainwindow.cpp" line="3247"/> <source>Don't ask me again</source> <translation>Non chiedermelo più</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="45"/> <source>Target "Normal" Volume:</source> <translation>Volume "normale" di destinazione:</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="71"/> <source>dB (default %1)</source> <translation>dB (predefinito: %1)</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="136"/> <source>Cancel</source> <translation>Cancella</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="119"/> <source>File progress</source> <translation>Progresso file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="143"/> <source>Total progress</source> <translation>Progresso totale</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="170"/> <source>&File</source> <translation>&File</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="189"/> <source>&Analysis</source> <translation>&Analisi</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="199"/> <source>&Modify Gain</source> <translation>&Modifica guadagno</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="211"/> <source>&Options</source> <translation>&Opzioni</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="215"/> <source>Tags</source> <translation>Etichette</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="228"/> - <location filename="../src/mainwindow.ui" line="322"/> <source>Toolbar</source> <translation>Barra degli strumenti</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="240"/> <source>Filename Display</source> <translation>Visualizza nome file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="248"/> - <location filename="../src/mainwindow.ui" line="357"/> <source>Logs</source> <translation>Registri</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="252"/> <source>Output Type</source> <translation>Tipo di uscita</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="262"/> <source>Timestamp</source> <translation>Data/ora</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="299"/> <source>&Language</source> <translation>&Lingua</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="305"/> <source>&Help</source> <translation>A&iuto</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="371"/> <source>Clear</source> <extracomment>Log output clear button</extracomment> <translatorcomment>tasto pulizia del registro di uscita</translatorcomment> <translation>Pulisci</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="397"/> - <location filename="../src/mainwindow.ui" line="400"/> <source>Errors</source> <translation>Errori</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="403"/> <source>QCheckBox { color: red }</source> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="406"/> - <location filename="../src/mainwindow.ui" line="1173"/> - <location filename="../src/mainwindow.ui" line="1240"/> - <location filename="../src/mainwindow.cpp" line="1513"/> <source>Error</source> <translation>Errore</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="416"/> - <location filename="../src/mainwindow.ui" line="419"/> <source>Analysis results</source> <translation>Esiti analisi</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="422"/> <source>QCheckBox { color: green }</source> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="425"/> - <location filename="../src/mainwindow.ui" line="1181"/> <source>Analysis</source> <translation>Analisi</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="435"/> - <location filename="../src/mainwindow.ui" line="438"/> <source>Gain changes</source> <translation>Modifiche guadagno</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="441"/> <source>QCheckBox { color: blue }</source> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="444"/> - <location filename="../src/mainwindow.ui" line="1189"/> <source>Change</source> <translation>Cambia</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="454"/> - <location filename="../src/mainwindow.ui" line="457"/> <source>Back end output</source> <translation>Backend di uscita</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="460"/> <source>QCheckBox { color: black }</source> <translation></translation> </message> <message> - <location filename="../src/mainwindow.ui" line="463"/> - <location filename="../src/mainwindow.ui" line="1197"/> <source>Back end</source> <translation>Backend</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="473"/> - <location filename="../src/mainwindow.ui" line="476"/> <source>Trace output</source> <translation>Uscita traccia</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="482"/> - <location filename="../src/mainwindow.ui" line="1262"/> <source>Trace</source> <translation>Traccia</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="529"/> <source>Load Analysis results</source> <translation>Carica risultati dell'analisi</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="540"/> <source>Save Analysis results</source> <translation>Salva risultati dell'analisi</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="552"/> - <location filename="../src/mainwindow.ui" line="555"/> <source>Add mp3 file(s) to the list</source> <translation>Aggiungi file mp3 alla lista</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="558"/> <source>Ctrl+F</source> <extracomment>File|Add_files</extracomment> <translation>Ctrl+F</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="570"/> - <location filename="../src/mainwindow.ui" line="573"/> <source>Add all mp3 files in a folder</source> <translation>Aggiungi tutti i file mp3 in una cartella</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="576"/> <source>Ctrl+D</source> <extracomment>File|Add_folder</extracomment> <translation>Ctrl+D</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="587"/> <source>Ctrl+A</source> <extracomment>File|Select_all_files</extracomment> <translation>Ctrl+A</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="598"/> <source>Ctrl+N</source> <extracomment>File|Select_no_files</extracomment> <translation>Ctrl+N</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="609"/> <source>Ctrl+V</source> <extracomment>File|Invert_selection</extracomment> <translation>Ctrl+V</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="621"/> <source>Clear selected file(s)</source> <translation>Pulisci file selezionati</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="624"/> <source>Clear File(s)</source> <translation>Pulisci i file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="627"/> - <location filename="../src/mainwindow.ui" line="630"/> <source>Remove selected files(s) from list</source> <translation>Rimuovi i file selezionati dall'elenco</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="642"/> <source>Clear All files</source> <translation>Pulisci tutti i file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="645"/> <source>Clear All</source> <translation>Pulisci tutto</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="648"/> - <location filename="../src/mainwindow.ui" line="651"/> <source>Remove all files from list</source> <translation>Rimuovi tutti i file dalla lista</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="680"/> <source>Do Replay Gain analysis on files</source> <translation>Esegui l'analisi del guadagno di riproduzione sui file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="689"/> <source>Ctrl+T</source> <extracomment>Analysis|Track_analysis</extracomment> <translation>Ctrl+T</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="707"/> <source>Do Replay Gain analysis on files as an album</source> <translation>Esegui l'analisi del guadagno di riproduzione sui file come un album</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="710"/> <source>Analyze each file in the Album as part of a whole and then list details about the files</source> <translation>Analizza ogni file nell'album come parte di un tutto e poi elenca i dettagli sui file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="716"/> <source>Ctrl+U</source> <extracomment>Analysis|Album_analysis</extracomment> <translation>Ctrl+U</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="748"/> - <location filename="../src/mainwindow.ui" line="751"/> - <location filename="../src/mainwindow.cpp" line="158"/> <source>Track Gain</source> <translation>Guadagno traccia</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="757"/> <source>Ctrl+G</source> <extracomment>Modify_gain|Track_gain</extracomment> <translation>Ctrl+G</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="775"/> - <location filename="../src/mainwindow.cpp" line="164"/> <source>Album Gain</source> <translation>Guadagno album</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="781"/> <source>Ctrl+B</source> <extracomment>Modify_gain|Album_gain</extracomment> <translation>Ctrl+B</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="799"/> - <location filename="../src/mainwindow.ui" line="802"/> <source>Constant Gain</source> <translation>Guadagno costante</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="808"/> <source>Ctrl+O</source> <extracomment>Modify_gain|Constant_gain</extracomment> <translation>Ctrl+O</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="827"/> <source>Always on Top</source> <translation>Sempre in primo piano</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="838"/> <source>Work on Selected files only</source> <translation>Lavora solo sui file selezionati</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="852"/> <source>Add Subfolders</source> <translation>Aggiungi le sotto-cartelle</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="863"/> <source>Preserve file date/time</source> <translation>Conserva la data/ora del file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="874"/> <source>No check for Layer I or II</source> <translation>Nessun controllo per Layer I o II</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="885"/> <source>Don't clip when doing Track Gain</source> <translation>Non tagliare quando si esegue il guadagno della traccia</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="896"/> <source>Minimize to Tray</source> <translation>Riduci nell'area di sistema</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="907"/> <source>Beep when finished</source> <translation>Beep quando finito</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="915"/> <source>Reset Default Column Widths</source> <translation>Ripristina larghezze predefinite delle colonne</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="923"/> <source>Reset "Warning" messages</source> <translation>Resetta i messaggi di "Avvertimento"</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="942"/> <source>Ignore (do not read or write tags)</source> <translation>Ignora (non leggere o scrivere le etichette)</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="953"/> <source>Big</source> <translation>Grande</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="967"/> <source>Show Path/File</source> <translation>Mostra percorso/file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="999"/> <source>Ctrl+M</source> <extracomment>Analysis|Max_no-clip_analysis</extracomment> <translation>Ctrl+M</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1022"/> <source>Ctrl+X</source> <extracomment>Modify_gain|Max_no-clip_gain_for_each_file</extracomment> <translation>Ctrl+X</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1045"/> <source>Ctrl+L</source> <extracomment>Modify_gain|Max_no-clip_gain_for_album</extracomment> <translation>Ctrl+L</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1056"/> <source>Re-calculate (do not read tags)</source> <translation>Ricalcola (non leggere le etichette)</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1064"/> <source>Don't check while adding files</source> <translation>Non controllare durante l'aggiunta di file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1075"/> <source>Remove Tags from files</source> <translation>Rimuovi le etichette dai file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1086"/> <source>Small</source> <translation>Piccolo</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1097"/> <source>Text only</source> <translation>Solo testo</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1108"/> <source>None</source> <translation>Nessuno</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1119"/> <source>Show File only</source> <translation>Mostra solo il file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1130"/> <source>Show Path && File</source> <translation>Mostra Percorso && File</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1013"/> - <location filename="../src/mainwindow.ui" line="1016"/> <source>This will change the gain on each mp3 file so that it is as loud as possible without clipping.</source> <translation>Questo cambierà il guadagno su ogni file mp3 in modo che sia il più alto possibile senza clipping.</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="549"/> <source>Add &File(s)</source> <translation>Aggiungi i &file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="567"/> <source>Add Fol&der</source> <translation>Aggiungi car&tella</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="584"/> <source>Select &All Files</source> <translation>Selezion&a tutti i file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="595"/> <source>Select &No Files</source> <translation>&Non selezionare file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="606"/> <source>In&vert selection</source> <translation>In&verti selezione</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="656"/> - <location filename="../src/mainwindow.cpp" line="374"/> <source>&Quit</source> <translation>&Chiudi</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="659"/> <source>Ctrl+Q</source> <extracomment>File|Quit</extracomment> <translation>Ctrl+Q</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="677"/> <source>&Track Analysis</source> <translation>Analisi &traccia</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="683"/> <source>Analyze each file individually and then list details of the files</source> <translation>Analizza ogni file individualmente e poi elenca i dettagli dei file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="704"/> <source>Alb&um Analysis</source> <translation>Analisi al&bum</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="724"/> <source>&Clear Analysis</source> <translation>Pulisci &analisi</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="727"/> <source>Clear the analysis results in the file list</source> <translation>Cancella i risultati dell'analisi nell'elenco dei file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="745"/> <source>Track &Gain</source> <translation>&Guadagno traccia</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="754"/> <source>Volume-correct all files listed in the File List to match the Target Volume</source> <translation>Corregge il volume di tutti i file elencati nell'elenco dei file in modo che corrispondano al volume di destinazione</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="772"/> <source>Al&bum Gain</source> <translation>Guadagno al&bum</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="778"/> <source>Volume-correct all files listed in the File List so that the overall album volume matches the Target Volume</source> <translation>Corregge il volume di tutti i file elencati nell'elenco dei file in modo che il volume complessivo dell'album corrisponda al volume di destinazione</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="796"/> <source>&Constant Gain</source> <translation>Guadagno &costante</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="805"/> <source>Absolute gain change of all files listed in the File List</source> <translation>Cambio di guadagno assoluto di tutti i file elencati nell'elenco dei file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="816"/> <source>&Undo Gain changes</source> <translation>Ann&ulla modifiche gudagno</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="819"/> <source>Undo all gain changes to the mp3 files in the list</source> <translation>Annulla tutte le modifiche di guadagno ai file mp3 nell'elenco</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="830"/> <source>MP3Gain window will always stay on top of other windows</source> <translation>La finestra MP3Gain rimarrà sempre in primo piano rispetto alle altre finestre</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="841"/> <source>Only those files that are currently selected will be operated on</source> <translation>Verranno utilizzati solo i file attualmente selezionati</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="855"/> <source>When you Add a Folder, all of the mp3s in all of the folders inside the selected folder will be added to the list</source> <translation>Quando aggiungi una cartella, tutti gli mp3 in tutte le cartelle all'interno della cartella selezionata verranno aggiunti all'elenco</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="866"/> <source>Changed files will keep their original timestamp</source> <translation>I file modificati manterranno la loro data/ora originale</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="877"/> <source>Forces mp3Gain to skip the safety check, allowing you to change the gain on these mis-identified files</source> <translation>Forza mp3Gain a saltare il controllo di sicurezza, consentendoti di modificare il guadagno su questi file identificati erroneamente</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="888"/> <source>When you do Track Gain, if the suggested Track gain will cause clipping then MP3Gain will apply the maximum non-clipping gain instead</source> <translation>Quando si esegue il guadagno della traccia, se il guadagno della traccia suggerito causerà il clipping, MP3Gain applicherà invece il guadagno massimo non tagliato</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="899"/> <source>When you minimize the MP3Gain window it will appear as an icon in the system tray notification area</source> <translation>Quando riduci a icona la finestra MP3Gain, apparirà come un'icona nell'area di notifica della barra delle applicazioni</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="910"/> <source>MP3Gain will make a default beep sound when it finishes a task</source> <translation>MP3Gain emetterà un segnale acustico predefinito quando termina un'attività</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="918"/> <source>Reset the column positions & sizes to their default settings</source> <translation>Ripristina le posizioni e le dimensioni delle colonne alle impostazioni predefinite</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="926"/> <source>Makes earlier suppressed warning and questions messages start popping up again</source> <translation>Fa riapparire i messaggi di avviso e domande soppressi in precedenza</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="931"/> <source>&Advanced...</source> <translation>&Avanzato ...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="934"/> <source>Allows you to modify some extra features</source> <translation>Consente di modificare alcune funzionalità extra</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="956"/> <source>Modify the look of the toolbar to Big size</source> <translation>Modifica l'aspetto della barra degli strumenti (dimensione grande)</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="970"/> <source>Path/File are displayed in a single column of the File List</source> <translation>Percorso/File vengono visualizzati in una singola colonna dell'Elenco file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="975"/> <source>&Contents</source> <translation>&Contenuti</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="980"/> <source>&Disclaimer...</source> <translation>A&vvertenza ...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="985"/> <source>&About...</source> <translation>&Informazioni ...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="993"/> <source>&Max No-clip Analysis</source> <translation>Analisi &max senza clip</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="996"/> <source>Find only the peak amplitudes of each of the mp3s in the list without spending any extra time</source> <translation>Trova solo le ampiezze di picco di ciascuno degli mp3 nell'elenco senza spendere altro tempo</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1010"/> <source>Ma&x No-clip Gain for Each file</source> <translation>Guadagno ma&x No-clip per ogni file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1019"/> <source>Change the gain on each mp3 file so that it is as loud as possible without clipping</source> <translation>Cambia il guadagno su ogni file mp3 in modo che sia il più alto possibile senza clipping</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1033"/> <source>Max No-c&lip Gain for Album</source> <translation>Guadagno max No-c&lip per album</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1036"/> - <location filename="../src/mainwindow.ui" line="1039"/> <source>This will look at each folder in the file list, find the single maximum gain which will not cause any clipping in any of the mp3s in the folder, and then apply that single gain change to all the mp3s in the folder.</source> <translation>Questo esaminerà ogni cartella nell'elenco dei file, troverà il singolo guadagno massimo che non causerà alcun ritaglio in nessuno degli mp3 nella cartella e quindi applicherà quella singola modifica del guadagno a tutti gli mp3 nella cartella.</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1042"/> <source>Look at each folder in the file list, find the single maximum gain which will not cause any clipping in any of the mp3s in the folder, and then apply that single gain change to all the mp3s in the folder</source> <translation>Guarda ogni cartella nell'elenco dei file, trova il singolo guadagno massimo che non causerà alcun ritaglio in nessuno degli mp3 nella cartella, quindi applica quella singola modifica del guadagno a tutti gli mp3 nella cartella</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1089"/> <source>Modify the look of the toolbar to Small size</source> <translation>Modifica l'aspetto della barra degli strumenti (dimensione piccola)</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1100"/> <source>Modify the look of the toolbar to Text format only</source> <translation>Modifica l'aspetto della barra degli strumenti (solo formato testo)</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1111"/> <source>Switch off the toolbar</source> <translation>Spegni la barra degli strumenti</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1122"/> <source>Only File without Path are displayed in the File List</source> <translation>Nell'elenco dei file vengono visualizzati solo i file senza percorso</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1133"/> <source>Path and File are displayed in separated columns of the File List</source> <translation>Percorso e File sono visualizzati in colonne separate dell'Elenco file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1138"/> <source>Resize column widths by content</source> <translation>Ridimensiona le larghezze delle colonne in base al contenuto</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1141"/> <source>Modify the column sizes to have enough space for their content</source> <translation>Modifica le dimensioni delle colonne per avere spazio sufficiente per il loro contenuto</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1149"/> <source>&Original (English)</source> <translation>&Originale (Inglese)</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1154"/> <source>&Back end...</source> <translation>&Backend ...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1157"/> <source>Set the location of the back end mp3gain</source> <translation>Imposta la posizione del backend mp3gain</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1162"/> <source>File...</source> <translation>File ...</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1165"/> <source>Set the output log file</source> <translation>Imposta il file di registro di uscita</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1208"/> <source>To File</source> <translation>Nel file</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1211"/> <source>Each line in the log has a timestamp</source> <translation>Ogni riga nel registro ha una data/ora</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1219"/> <source>To Panel</source> <translation>Nel pannello</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1227"/> <source>Automatically opened if error</source> <translation>Aperto automaticamente in caso di errore</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1235"/> <source>Panel</source> <translation>Pannello</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1248"/> <source>Open automatically panel</source> <translation>Apri automaticamente il pannello</translation> </message> <message> - <location filename="../src/mainwindow.ui" line="1251"/> - <location filename="../src/mainwindow.ui" line="1254"/> <source>Log panel is automaticaly opened if error occurs</source> <translation>Il pannello di registro viene aperto automaticamente se si verifica un errore</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="674"/> <source>Language</source> <extracomment>Translate it to your language in your language. For example for Italian translation it is Italiano.</extracomment> <translation>Italiano</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="152"/> <source>Path/File</source> <translation>Percorso/file</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="153"/> <source>Path</source> <translation>Percorso</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="154"/> <source>File</source> <translation>File</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="155"/> <source>Volume</source> <translation>Volume</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="156"/> <source>Max Amplitude</source> <translation>Ampiezza max</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="157"/> <source>clipping</source> <translation>clipping</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="159"/> <source>dBGain</source> <translation>Guadagno dB</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="161"/> <source>Max Noclip Gain</source> <translation>Guadagno Noclip max</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="162"/> <source>Album Volume</source> <translation>Volume album</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="163"/> <source>Album Max Amplitude</source> <translation>Ampiezza max album</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="165"/> <source>Album dBGain</source> <translation>Guadagno dB album</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="166"/> <source>clip(Album)</source> <translation>clip (Album)</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="337"/> <source>Number of files in the list</source> <translation>Numero di file nella lista</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="371"/> <source>&Restore</source> <translation>&Ripristina</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="375"/> <source>Ctrl+Q</source> <comment>SystemTrayIcon|Quit</comment> <translation>Ctrl+Q</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="434"/> - <location filename="../src/mainwindow.cpp" line="998"/> - <location filename="../src/mainwindow.cpp" line="1004"/> <source>No operation running</source> <translation>Nessuna operazione in corso</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="440"/> <source>Minimize to tray option is checked and tray icon should be created but system tray is unavailable</source> <translation>L'opzione Riduci a icona nella barra delle applicazioni è selezionata e l'icona della barra delle applicazioni dovrebbe essere creata ma la barra delle applicazioni non è disponibile</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="463"/> <source>Lossless volume modification of MP3 files</source> <translation>Modifica del volume senza perdita di file MP3</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="466"/> <source>System tray does not support balloon messages</source> <translation>La barra delle applicazioni non supporta i messaggi a fumetto</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="485"/> <source>Fatal Error</source> <translation>Errore fatale</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="486"/> <source>Playing of %1 went into failure</source> <translation>La riproduzione di %1 è fallita</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="561"/> <source>Clear Logs?</source> <translation>Pulire i registri?</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="628"/> <source>Translation file %1 is loaded</source> <translation>Il file di traduzione %1 è caricato</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="634"/> <source>%1 locale is used</source> <translation>Viene utilizzata %1 locale</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="641"/> <source>No translation file is necessary</source> <translation>Non è necessario alcun file di traduzione</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="643"/> <source>Translation file %1 cannot be found, %2 locale is refused</source> <translation>Impossibile trovare il file di traduzione %1, l'impostazione locale %2 è rifiutata</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="647"/> <source>Default %1 locale is used</source> <translation>Viene usata la localizzazione predefinita %1</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="756"/> <source>Cannot write log file: %1</source> <translation>Impossibile scrivere il file di registro: %1</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="996"/> <source>Work in progress: %1%</source> <translation>Lavoro in progresso: %1%</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="1092"/> <source>Y</source> <comment>Yes flag in some clipping fields of the file list</comment> <translation>Y</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2640"/> <source>MP3Gain back end cannot be found. Please make it available!</source> <translation>Impossibile trovare il backend di MP3Gain. Si prega di renderlo disponibile!</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="2644"/> <source>Required MP3Gain back end version is %1 or later, but only %2 is found. Please make a newer version available!</source> <translation>La versione backend di MP3Gain richiesta è %1 o successiva, ma viene trovata solo %2. Si prega di rendere disponibile una versione più recente!</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="160"/> <source>clip(Track)</source> <translation>clip (Traccia)</translation> </message> + <message> + <source>Clear logs</source> + <translation>Pulire i registri</translation> + </message> + <message> + <source>Copy logs to clipboard</source> + <translation>Copia i registri negli appunti</translation> + </message> + <message> + <source>Copy</source> + <translation>Copia</translation> + </message> + <message> + <source>Failed to decode MPEG frame: Error reading the stream. (code %1)</source> + <translation>Impossibile decodificare il frame MPEG: errore durante la lettura del flusso. (codice %1)</translation> + </message> </context> <context> <name>QDialogButtonBox</name> <message> - <location filename="../src/mainwindow.cpp" line="126"/> <source>OK</source> <translation>OK</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="127"/> <source>Open</source> <translation>Apri</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="128"/> <source>Save</source> <translation>Salva</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="129"/> <source>Cancel</source> <translation>Cancella</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="130"/> <source>Close</source> <translation>Chiudi</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="131"/> <source>Discard</source> <translation>Scarta</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="132"/> <source>Apply</source> <translation>Applica</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="133"/> <source>Reset</source> <translation>Resetta</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="134"/> <source>Restore Defaults</source> <translation>Valori predefiniti</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="135"/> <source>Help</source> <translation>Aiuto</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="136"/> <source>Save All</source> <translation>Salva tutto</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="137"/> <source>&Yes</source> <translation>&Si</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="138"/> <source>Yes to &All</source> <translation>Si, a tutt&i</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="139"/> <source>&No</source> <translation>&No</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="140"/> <source>N&o to All</source> <translation>&Non a tutti</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="142"/> <source>Abort</source> <translation>Annulla</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="143"/> <source>Retry</source> <translation>Riprova</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="144"/> <source>Ignore</source> <translation>Ignora</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="146"/> <source>Don't Save</source> <translation>Non salvare</translation> </message> <message> - <location filename="../src/mainwindow.cpp" line="147"/> <source>Close without Saving</source> <translation>Chiudi senza salvare</translation> </message>
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.