diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3a0474fb..25c7dc8d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,18 +14,22 @@ jobs: strategy: matrix: include: - - runner: 'ubuntu-18.04' + - runner: 'ubuntu-20.04' qtVersion: '5.15.2' - - runner: 'macOS-11' + - runner: 'ubuntu-20.04' + qtVersion: '5.9' + skipPlugins: 'true' + - runner: 'macos-latest' qtVersion: '6.2.2' - - runner: 'macOS-10.15' - qtVersion: '5.12.12' + qtModules: 'qtimageformats' + - runner: 'macos-latest' + qtVersion: '5.15.2' osSuffix: '_legacy' - skipHardPlugins: 'true' - runner: 'windows-2019' qtVersion: '6.2.2' qtArch: 'win64_msvc2019_64' osSuffix: '_64' + qtModules: 'qtimageformats' - runner: 'windows-2019' qtVersion: '5.15.2' qtArch: 'win32_msvc2019' @@ -51,20 +55,24 @@ jobs: version: ${{ matrix.qtVersion }} arch: ${{ matrix.qtArch }} cache: true + modules: ${{ matrix.qtModules }} - name: Build qView shell: pwsh - run: ci/scripts/build.ps1 + run: dist/scripts/build.ps1 - name: Deploy qView shell: pwsh run: | + if ("${{ matrix.skipPlugins }}" -ne "true") { + Invoke-Expression "& 'dist/scripts/download-plugins.ps1'" + } if ($IsWindows) { - Invoke-Expression "& 'ci/scripts/windeployqt.ps1' ${{ env.buildNumString }}" + Invoke-Expression "& 'dist/scripts/windeployqt.ps1' ${{ env.buildNumString }}" } elseif ($IsMacOS) { - bash ci/scripts/macdeploy.sh ${{ env.buildNumString }} + bash dist/scripts/macdeploy.sh ${{ env.buildNumString }} } else { - bash ci/scripts/linuxdeployqt.sh ${{ env.buildNumString }} + bash dist/scripts/linuxdeployqt.sh ${{ env.buildNumString }} } - name: 'Upload Artifact' diff --git a/dist/linux/com.interversehq.qView.appdata.xml b/dist/linux/com.interversehq.qView.appdata.xml index e02b310d..8d18f359 100644 --- a/dist/linux/com.interversehq.qView.appdata.xml +++ b/dist/linux/com.interversehq.qView.appdata.xml @@ -28,6 +28,8 @@ + + diff --git a/dist/linux/debian/changelog b/dist/linux/debian/changelog index 75fd2bea..7f4e0954 100644 --- a/dist/linux/debian/changelog +++ b/dist/linux/debian/changelog @@ -1,5 +1,5 @@ -qview (5.0-5) bionic; urgency=low +qview (6.1-1) bionic; urgency=low - * Fix not requiring qtbase5-dev-tools + * Initial release - -- jurplel Fri, 14 Jan 2022 20:44:22 -0500 \ No newline at end of file + -- jurplel Tue, 15 Aug 2023 20:26:07 -0400 diff --git a/dist/linux/debian/control b/dist/linux/debian/control index 002a9688..b8cf3793 100644 --- a/dist/linux/debian/control +++ b/dist/linux/debian/control @@ -2,13 +2,13 @@ Source: qview Section: graphics Priority: optional Maintainer: jurplel -Build-Depends: debhelper (>= 11), qtbase5-dev (>= 5.9), qtbase5-dev-tools (>= 5.9), qt5-qmake (>= 5.9), qttools5-dev-tools (>= 5.9) +Build-Depends: debhelper (>= 11), qtbase5-dev (>= 5.9), qtbase5-dev-tools (>= 5.9), qt5-qmake (>= 5.9), qttools5-dev-tools (>= 5.9), libqt5x11extras5-dev (>= 5.9) Standards-Version: 4.1.3 Homepage: https://interversehq.com/qview Package: qview Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libqt5widgets5 (>= 5.9), libqt5network5 (>= 5.9), libqt5concurrent5 (>= 5.9) +Depends: ${shlibs:Depends}, ${misc:Depends}, libqt5widgets5 (>= 5.9), libqt5network5 (>= 5.9), libqt5concurrent5 (>= 5.9), libqt5x11extras5 (>= 5.9) Recommends: qt5-image-formats-plugins (>= 5.9), libqt5svg5 (>= 5.9) Suggests: qt-heif-image-plugin (>= 0.3.3), kimageformats (>= 5.38.0) Description: Practical and minimal image viewer diff --git a/dist/linux/debian/control_bionic b/dist/linux/debian/control_bionic index edf2af17..da3aedb1 100644 --- a/dist/linux/debian/control_bionic +++ b/dist/linux/debian/control_bionic @@ -2,13 +2,13 @@ Source: qview Section: graphics Priority: optional Maintainer: jurplel -Build-Depends: debhelper (>= 11), qt5-default (>= 5.9), qttools5-dev-tools (>= 5.9) +Build-Depends: debhelper (>= 11), qt5-default (>= 5.9), qttools5-dev-tools (>= 5.9), libqt5x11extras5-dev (>= 5.9) Standards-Version: 4.1.3 Homepage: https://interversehq.com/qview Package: qview Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, libqt5widgets5 (>= 5.9), libqt5network5 (>= 5.9), libqt5concurrent5 (>= 5.9) +Depends: ${shlibs:Depends}, ${misc:Depends}, libqt5widgets5 (>= 5.9), libqt5network5 (>= 5.9), libqt5concurrent5 (>= 5.9), libqt5x11extras5 (>= 5.9) Recommends: qt5-image-formats-plugins (>= 5.9), libqt5svg5 (>= 5.9) Suggests: qt-heif-image-plugin (>= 0.3.3), kimageformats (>= 5.38.0) Description: Practical and minimal image viewer diff --git a/dist/linux/rpm/qview.spec b/dist/linux/rpm/qview.spec index 79570476..8d21eb05 100644 --- a/dist/linux/rpm/qview.spec +++ b/dist/linux/rpm/qview.spec @@ -1,5 +1,5 @@ Name: qview -Version: 5.0 +Version: 6.1 Release: 1 Summary: Practical and minimal image viewer @@ -12,6 +12,7 @@ BuildRequires: pkgconfig BuildRequires: pkgconfig(Qt5Concurrent) >= 5.9 BuildRequires: pkgconfig(Qt5Widgets) >= 5.9 BuildRequires: pkgconfig(Qt5Network) >= 5.9 +BuildRequires: pkgconfig(Qt5X11Extras) >= 5.9 %description @@ -42,4 +43,4 @@ cp dist/linux/com.interversehq.qView.appdata.xml %{buildroot}/usr/share/metainfo %license LICENSE %doc README.md -%changelog \ No newline at end of file +%changelog diff --git a/dist/mac/Info_legacy.plist b/dist/mac/Info_legacy.plist deleted file mode 100644 index 13c8c885..00000000 --- a/dist/mac/Info_legacy.plist +++ /dev/null @@ -1,62 +0,0 @@ - - - - - CFBundleExecutable - @EXECUTABLE@ - CFBundleName - qView - CFBundleGetInfoString - @SHORT_VERSION@ - CFBundleIconFile - @ICON@ - CFBundleIdentifier - @BUNDLEIDENTIFIER@ - CFBundlePackageType - APPL - CFBundleSignature - @TYPEINFO@ - LSMinimumSystemVersion - 10.10 - NSPrincipalClass - NSApplication - CFBundleShortVersionString - @SHORT_VERSION@ - CFBundleDocumentTypes - - - CFBundleTypeExtensions - - bmp - cur - gif - icns - ico - jpeg - jpg - jpe - jfi - jfif - pbm - pgm - png - ppm - svg - svgz - tif - tiff - wbmp - webp - xbm - xpm - - CFBundleTypeRole - Viewer - - - NSSupportsAutomaticGraphicsSwitching - - NSHighResolutionCapable - - - diff --git a/ci/scripts/build.ps1 b/dist/scripts/build.ps1 old mode 100644 new mode 100755 similarity index 87% rename from ci/scripts/build.ps1 rename to dist/scripts/build.ps1 index a5ea25ba..1b06dbf6 --- a/ci/scripts/build.ps1 +++ b/dist/scripts/build.ps1 @@ -1,4 +1,4 @@ -#!/usr/bin/pwsh +#!/usr/bin/env pwsh param ( @@ -6,7 +6,7 @@ param ) if ($IsWindows) { - ci/scripts/vcvars.ps1 + dist/scripts/vcvars.ps1 } if ((qmake --version -split '\n')[1][17] -eq '6') { @@ -20,4 +20,4 @@ if ($IsWindows) { nmake } else { make -} \ No newline at end of file +} diff --git a/dist/scripts/download-plugins.ps1 b/dist/scripts/download-plugins.ps1 new file mode 100755 index 00000000..3db10226 --- /dev/null +++ b/dist/scripts/download-plugins.ps1 @@ -0,0 +1,111 @@ +#!/usr/bin/env pwsh + +# This script will download binary plugins from the kimageformats-binaries repository using Github's API. + +$pluginNames = "qtapng", "kimageformats" + +$qtVersion = ((qmake --version -split '\n')[1] -split ' ')[3] +Write-Host "Detected Qt Version $qtVersion" + +# Qt version availability and runner names are assumed. +if ($IsWindows) { + $imageName = "windows-2019" +} elseif ($IsMacOS) { + $imageName = "macos-latest" +} else { + $imageName = "ubuntu-20.04" +} + +$binaryBaseUrl = "https://github.com/jurplel/kimageformats-binaries/releases/download/cont" + +if ($pluginNames.count -eq 0) { + Write-Host "the pluginNames array is empty." +} + +foreach ($pluginName in $pluginNames) { + $arch = If (-not $env:arch -or $env:arch -eq '') { "" } Else { "-$env:arch" } + $artifactName = "$pluginName-$imageName-$qtVersion$arch.zip" + $downloadUrl = "$binaryBaseUrl/$artifactName" + + Write-Host "Downloading $downloadUrl" + Invoke-WebRequest -URI $downloadUrl -OutFile $artifactName + Expand-Archive $artifactName -DestinationPath $pluginName + Remove-Item $artifactName +} + + +if ($IsWindows) { + $out_frm = "bin/" + $out_imf = "bin/imageformats" +} elseif ($IsMacOS) { + $out_frm = "bin/qView.app/Contents/Frameworks" + $out_imf = "bin/qView.app/Contents/PlugIns/imageformats" +} else { + $out_frm = "bin/appdir/usr/lib" + $out_imf = "bin/appdir/usr/plugins/imageformats" +} + +New-Item -Type Directory -Path "$out_frm" -ErrorAction SilentlyContinue +New-Item -Type Directory -Path "$out_imf" -ErrorAction SilentlyContinue + +# Copy QtApng +if ($pluginNames -contains 'qtapng') { + if ($IsWindows) { + cp qtapng/QtApng/plugins/imageformats/qapng.dll "$out_imf/" + } elseif ($IsMacOS) { + cp qtapng/QtApng/plugins/imageformats/libqapng.dylib "$out_imf/" + } else { + cp qtapng/QtApng/plugins/imageformats/libqapng.so "$out_imf/" + } +} + +if ($pluginNames -contains 'kimageformats') { + if ($IsWindows) { + mv kimageformats/kimageformats/output/kimg_*.dll "$out_imf/" + # Copy karchive + if (Test-Path -Path kimageformats/kimageformats/output/KF5Archive.dll -PathType Leaf) { + cp kimageformats/kimageformats/output/zlib1.dll "$out_frm/" + cp kimageformats/kimageformats/output/KF5Archive.dll "$out_frm/" + } + # copy avif stuff + if (Test-Path -Path kimageformats/kimageformats/output/avif.dll -PathType Leaf) { + cp kimageformats/kimageformats/output/avif.dll "$out_frm/" + cp kimageformats/kimageformats/output/aom.dll "$out_frm/" + } + # copy heif stuff + if (Test-Path -Path kimageformats/kimageformats/output/heif.dll -PathType Leaf) { + cp kimageformats/kimageformats/output/heif.dll "$out_frm/" + cp kimageformats/kimageformats/output/de265.dll "$out_frm/" + cp kimageformats/kimageformats/output/libx265.dll "$out_frm/" + } + # copy raw stuff + if (Test-Path -Path kimageformats/kimageformats/output/raw.dll -PathType Leaf) { + cp kimageformats/kimageformats/output/zlib1.dll "$out_frm/" + cp kimageformats/kimageformats/output/raw.dll "$out_frm/" + cp kimageformats/kimageformats/output/lcms2.dll "$out_frm/" + } + # copy jxl stuff + if (Test-Path -Path kimageformats/kimageformats/output/jxl.dll -PathType Leaf) { + cp kimageformats/kimageformats/output/jxl.dll "$out_frm/" + cp kimageformats/kimageformats/output/jxl_threads.dll "$out_frm/" + cp kimageformats/kimageformats/output/hwy.dll "$out_frm/" + cp kimageformats/kimageformats/output/brotlicommon.dll "$out_frm/" + cp kimageformats/kimageformats/output/brotlidec.dll "$out_frm/" + cp kimageformats/kimageformats/output/brotlienc.dll "$out_frm/" + } + # copy jxl stuff + if (Test-Path -Path kimageformats/kimageformats/output/OpenEXR-3_1.dll -PathType Leaf) { + cp kimageformats/kimageformats/output/zlib1.dll "$out_frm/" + cp kimageformats/kimageformats/output/OpenEXR-3_1.dll "$out_frm/" + cp kimageformats/kimageformats/output/Imath-3_1.dll "$out_frm/" + cp kimageformats/kimageformats/output/IlmThread-3_1.dll "$out_frm/" + cp kimageformats/kimageformats/output/Iex-3_1.dll "$out_frm/" + } + } elseif ($IsMacOS) { + cp kimageformats/kimageformats/output/*.so "$out_imf/" + cp kimageformats/kimageformats/output/libKF5Archive.5.dylib "$out_frm/" + } else { + cp kimageformats/kimageformats/output/kimg_*.so "$out_imf/" + cp kimageformats/kimageformats/output/libKF5Archive.so.5 "$out_frm/" + } +} diff --git a/ci/scripts/innomake.ps1 b/dist/scripts/innomake.ps1 old mode 100644 new mode 100755 similarity index 100% rename from ci/scripts/innomake.ps1 rename to dist/scripts/innomake.ps1 diff --git a/ci/scripts/linuxdeployqt.sh b/dist/scripts/linuxdeployqt.sh old mode 100644 new mode 100755 similarity index 100% rename from ci/scripts/linuxdeployqt.sh rename to dist/scripts/linuxdeployqt.sh diff --git a/ci/scripts/macdeploy.sh b/dist/scripts/macdeploy.sh old mode 100644 new mode 100755 similarity index 100% rename from ci/scripts/macdeploy.sh rename to dist/scripts/macdeploy.sh diff --git a/ci/scripts/vcvars.ps1 b/dist/scripts/vcvars.ps1 old mode 100644 new mode 100755 similarity index 100% rename from ci/scripts/vcvars.ps1 rename to dist/scripts/vcvars.ps1 diff --git a/ci/scripts/windeployqt.ps1 b/dist/scripts/windeployqt.ps1 old mode 100644 new mode 100755 similarity index 63% rename from ci/scripts/windeployqt.ps1 rename to dist/scripts/windeployqt.ps1 index 91343c4d..474e9fb6 --- a/ci/scripts/windeployqt.ps1 +++ b/dist/scripts/windeployqt.ps1 @@ -5,7 +5,7 @@ param # Download and extract openssl $ProgressPreference = 'SilentlyContinue' -Invoke-WebRequest https://mirror.firedaemon.com/OpenSSL/openssl-1.1.1q.zip -O openssl.zip +Invoke-WebRequest https://www.firedaemon.com/download-firedaemon-openssl-1-zip -O openssl.zip 7z x -y .\openssl.zip # Check if "arch" environment variable is win32 @@ -21,10 +21,11 @@ if ($env:arch.substring(3, 2) -eq '32') { # Run windeployqt which should be in path windeployqt bin/qView.exe --no-compiler-runtime -# Do renaming-y stuff -mv bin\qView.exe "bin\qView-nightly-$NightlyVersion.exe" -# Call innomake if we are not building a nightly version (no version passed) -if ($NightlyVersion -ne '') { - & "ci/scripts/innomake.ps1" -} \ No newline at end of file +if ($NightlyVersion -eq '') { + # Call innomake if we are not building a nightly version (no version passed) + & "dist/scripts/innomake.ps1" +} else { + # Do renaming-y stuff otherwise + mv bin\qView.exe "bin\qView-nightly-$NightlyVersion.exe" +} diff --git a/dist/win/qView32.iss b/dist/win/qView32.iss index a57b8dd6..5de11d42 100755 --- a/dist/win/qView32.iss +++ b/dist/win/qView32.iss @@ -4,8 +4,8 @@ #define MyAppExeName "qView.exe" ; Update these when building -#define MyAppVersion "5.0" -#define MyAppYear "2022" +#define MyAppVersion "6.1" +#define MyAppYear "2023" [Setup] AppId={{A6A9BAAB-C59E-4EAB-ACE1-3EEDE3031880} diff --git a/dist/win/qView64.iss b/dist/win/qView64.iss index eca72e11..00eb766d 100755 --- a/dist/win/qView64.iss +++ b/dist/win/qView64.iss @@ -4,8 +4,8 @@ #define MyAppExeName "qView.exe" ; Update these when building -#define MyAppVersion "5.0" -#define MyAppYear "2022" +#define MyAppVersion "6.1" +#define MyAppYear "2023" [Setup] AppId={{A6A9BAAB-C59E-4EAB-ACE1-3EEDE3031880} diff --git a/i18n/qview_de.ts b/i18n/qview_de.ts index 2d923366..6a3a87d2 100644 --- a/i18n/qview_de.ts +++ b/i18n/qview_de.ts @@ -376,17 +376,18 @@ Can't delete %1: No write permission or file is read-only. - + %1 kann nicht gelöscht werden: +Keine Schreibberechtigung oder Datei ist schreibgeschützt. Are you sure you want to move %1 to the Trash? - + Sind Sie sicher, dass Sie %1 in den Papierkorb verschieben wollen? Are you sure you want to move %1 to the Recycle Bin? - + Sind Sie sicher, dass Sie %1 in den Papierkorb verschieben möchten? @@ -414,18 +415,20 @@ No write permission or file is read-only. This program was compiled with an old version of Qt and this feature is not available. If you see this message, please report a bug! - + Dieses Programm wurde mit einer alten Version von Qt kompiliert und diese Funktion ist nicht verfügbar. +Wenn Sie diese Meldung sehen, melden Sie diesen Fehler bitte! Can't undo deletion of %1: No write permission or file is read-only. - + Löschung von %1 kann nicht rückgängig gemacht werden: +Keine Schreibberechtigung oder Datei ist schreibgeschützt. Failed undoing deletion of %1. - + Das Wiederherstellen von %1 ist fehlgeschlagen. Rename... @@ -858,7 +861,7 @@ No write permission or file is read-only. &Quit on last window closed - + Schließen, wenn letztes Fenster geschlossen wurde @@ -1092,17 +1095,17 @@ No write permission or file is read-only. Move Back - + Zurück Do Nothing - + Nichts tun Move Forward - + Weiter @@ -1112,7 +1115,7 @@ No write permission or file is read-only. &Ask before deleting files - + Vor dem Löschen von Dateien fragen @@ -1163,13 +1166,15 @@ No write permission or file is read-only. Could not rename %1: No write permission or file is read-only. - + Konnte %1 nicht umbenennen: +Keine Schreibberechtigung oder Datei ist schreibgeschützt. Could not rename %1: (Check that all characters are valid) - + Konnte %1 nicht umbenennen: +(Prüfen Sie, ob alle Zeichen gültig sind) diff --git a/i18n/qview_es.ts b/i18n/qview_es.ts index fcf68ef6..054de3bd 100644 --- a/i18n/qview_es.ts +++ b/i18n/qview_es.ts @@ -41,7 +41,7 @@ Open &Recent - &Recientes + Abrir &recientes @@ -58,7 +58,7 @@ &Quit - &Cerrar + &Salir @@ -79,7 +79,7 @@ Open &URL... - Abrir &ubicación... + Abrir un &URL... @@ -107,12 +107,12 @@ Show in &Finder Open containing folder on macOS - Mostrar en &finder + Mostrar en el &Finder Show File &Info - &Propiedades del archivo + &Información del archivo @@ -132,7 +132,7 @@ &Undo Delete - &Deshacer borrado + &Deshacer el borrado @@ -162,17 +162,17 @@ Reset &Zoom - Restablecer el &zoom + Res&tablecer la vista Ori&ginal Size - Tamaño ori&ginal + &Tamaño original Rotate &Right - Girar a la de&recha + Girar a la &derecha @@ -182,7 +182,7 @@ &Mirror - &Reflejar + Re&flejar @@ -197,12 +197,12 @@ &First File - P&rimer archivo + &Primer archivo Previous Fi&le - &Archivo anterior + Archivo a&nterior @@ -212,48 +212,48 @@ Las&t File - &Último archivo + Úl&timo archivo Save Frame &As... - Gu&ardar cuadro como... + &Guardar el fotograma como... Pa&use - Pa&usar + &Pausar &Next Frame - Fotograma &siguiente + &Fotograma siguiente &Decrease Speed - &Reducir velocidad + &Reducir la velocidad &Reset Speed - &Restablecer Velocidad + Res&tablecer la velocidad &Increase Speed - &Aumentar velocidad + &Aumentar la velocidad Start S&lideshow - Iniciar &presentación + &Iniciar la presentación Option&s This is for the options dialog on windows - Opcione&s + &Opciones @@ -270,7 +270,7 @@ &About - &Acerca + &Acerca de @@ -281,13 +281,13 @@ &Welcome - &Bienvenido + &Bienvenida Clear &Menu This is for clearing the recents menu - Limpiar &Menu + &Borrar la lista @@ -299,13 +299,13 @@ Choose another app Open with other program for windows - Escoger otra aplicación + Elegir otra aplicación Other... Open with other program for macos - Otro... + Otra... @@ -313,12 +313,12 @@ Exit F&ull Screen - Salir P&antalla Completa + Salir del &modo a pantalla completa Enter F&ull Screen - Entrar P&antalla Completa + &Modo a pantalla completa @@ -339,12 +339,12 @@ Error: URL is invalid - Error: URL no válida + Error: URL no válido Downloading image... - Descargando imagen... + Descargando la imagen... @@ -355,7 +355,7 @@ Open URL... - Abrir URL... + Abrir un URL... @@ -365,18 +365,18 @@ Error: Invalid image - Error: Imagen invalida + Error: Imagen no válida URL of a supported image file: - URL de archivo de imagen compatible: + URL de un archivo de imagen compatible: Can't delete %1: No write permission or file is read-only. - No se puede eliminar %1: + No se puede borrar %1: No se tiene permiso de escritura o el archivo es de solo lectura. @@ -387,7 +387,7 @@ No se tiene permiso de escritura o el archivo es de solo lectura. Are you sure you want to move %1 to the Recycle Bin? - ¿Seguro que quiere mover %1 a la Papelera de Reciclaje? + ¿Seguro que quiere mover %1 a la papelera de reciclaje? @@ -408,27 +408,27 @@ No se tiene permiso de escritura o el archivo es de solo lectura. Not Supported - No Compatible + No compatible This program was compiled with an old version of Qt and this feature is not available. If you see this message, please report a bug! - Este programa fue compilado con una versión antigua de Qt y esta característica no esta disponible. -Si usted ve este mensaje, por favor reporte el error! + Este programa se ha compilado con una versión obsoleta de Qt y esta función no está disponible. +Si ve este mensaje, ¡informe de un error! Can't undo deletion of %1: No write permission or file is read-only. - No se puede restablecer la eliminación de %1: -No se tienen permisos de escritura o el archivo es de solo lectura. + No se puede deshacer el borrado de %1: +No tiene permiso de escritura o el archivo es de solo lectura. Failed undoing deletion of %1. - Fallo al restablecer eliminación de %1. + Error al deshacer el borrado de %1. Rename... @@ -441,12 +441,12 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Save Frame As... - Guardar Fotograma Como... + Guardar el fotograma como... Res&ume - Rean&udar + Contin&uar @@ -456,12 +456,12 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Start S&lideshow - &Iniciar presentación + &Iniciar una presentación Stop S&lideshow - &Detener presentación + &Detener la presentación @@ -492,7 +492,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. The file to open. - Archivo a abrir. + El archivo que se abrirá. @@ -500,7 +500,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. About qView - Sobre qView + Acerca de qView @@ -510,12 +510,12 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Nightly %1 - Nightly%1 + Nocturna %1 Built with Qt %1 (%2)<br>Source code available under GPLv3 on <a style="color: #03A9F4; text-decoration:none;" href="https://github.com/jurplel/qView">GitHub</a><br>Icon glyph created by Guilhem from the Noun Project<br>Copyright © %3 jurplel and qView contributors - Creado con Qt %1 (%2)<br>Código fuente disponible bajo GPLv3 en <a style="color: #03A9F4; text-decoration:none;" href="https://github.com/jurplel/qView">GitHub</a><br>Icono creado por Guilhem del proyecto Noun Project<br>Copyright © %3 contribuidores jurplel y qView + Creado con Qt %1 (%2)<br>Código fuente disponible con la GPLv3 en <a style="color: #03A9F4; text-decoration:none;" href="https://github.com/jurplel/qView">GitHub</a><br>Icono creado por Guilhem del Noun Project<br>Copyright © %3 jurplel y colaboradores de qView @@ -526,17 +526,17 @@ No se tienen permisos de escritura o el archivo es de solo lectura. %1 update available %1 is a version number e.g. "4.0 update available" - %1 actualización disponible + Disponible la actualización %1 No updates available - No hay nuevas actualizaciones + No hay actualizaciones disponibles Error checking for updates - Error buscando actualizaciones + Error al comprobar las actualizaciones @@ -548,7 +548,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Supported Images - Imágenes Compatibles + Imágenes compatibles @@ -566,7 +566,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. (default) - (predeterminado) + (por defecto) @@ -580,8 +580,8 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Error occurred opening "%3": %2 (Error %1) - Error abriendo "%3": -%2 (Error %1) + Error al abrir «%3»: +%2 (error %1) @@ -636,7 +636,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Aspect Ratio: - Escala: + Relación de aspecto: @@ -664,7 +664,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Choose Application - Escoger aplicación + Elegir una aplicación @@ -674,7 +674,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Education - Educativos + Educación @@ -709,7 +709,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Settings - Ajustes + Configuración @@ -742,12 +742,12 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Back&ground color: - &Color de fondo: + &Color del fondo: Changes the amount of information displayed in the titlebar - Cambia la información mostrada en la barra del titulo + Cambia la información que se muestra en la barra de título @@ -757,28 +757,28 @@ No se tienen permisos de escritura o el archivo es de solo lectura. &Basic - &Basico + &Básico &Minimal - &Minimalista + &Mínimo &Practical - &Practico + &Práctico &Verbose - &Informativo + &Detallado Control when the window should resize to fit the image's actual size - Controla cuando la ventana cambia de tamaño para acomodarse a la de la imagen + Controla cuándo la ventana debe ajustarse al tamaño de la imagen @@ -793,7 +793,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. When launching - Al ejecutarse + Al inicio @@ -808,7 +808,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Control the minimum size that the window should reach when matching the image's actual size - Controla el tamaño mínimo que la ventana debe alcanzar cuando se alcanza el tamaño de imagen real + Controla el tamaño mínimo de la ventana al ajustarse al tamaño de la imagen @@ -820,7 +820,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Control the maximum size that the window should reach when matching the image's actual size - Controla el tamaño máximo que la ventana debe alcanzar cuando se alcanza el tamaño de imagen real + Controla el tamaño máximo de la ventana al ajustarse al tamaño de la imagen @@ -830,27 +830,27 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Choose whether or not the titlebar should always be dark regardless of your chosen macOS appearance - Elige si la barra de titulo deberá o no ser siempre obscura sin importar la apariencia elegida en los ajustes de macOS + Elija si la barra de título debe ser siempre oscura, independientemente de la apariencia de macOS &Titlebar always dark - &Barra de título siempre obscura + Barra de &título siempre obscura Show menubar - Mostrar barra de menú + Mostrar la barra de menú Choose whether or not to display the titlebar text while in fullscreen - Elegir si la barra de título se despliegue o no en pantalla completa + Elija si se muestra el texto de la barra de título a pantalla completa Show titlebar text in fullscreen - Mostrar texto de la barra de título en pantalla completa + Mostrar el texto de la barra de título a pantalla completa @@ -865,89 +865,89 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Scaling: - Escala: + Escalado: Turn this off to see individual pixels - Apaga esto para ver pixeles individuales + Desmarque para ver píxeles individuales &Bilinear filtering - Filtrado &bilineal + &Filtrado bilineal Images appear aliased (having jagged edges) without this, but it is faster - Las imágenes aparecen pixeladas (bordes escalonados) sin esto, pero es mas rápido + Sin esta opción las imágenes aparecen con bordes dentados, pero es más rápido &Image scaling - &Escala de imagen + Escalado de la &imagen Choose whether or not the image continues to be scaled when zooming above the window size (can be laggier with large images) - Controla si la imagen continua escalándose o no cuando el acercamiento sobrepasa el tamaño de la ventana (puede actuar lento con imágenes grandes) + Elija si se sigue escalando la imagen al ampliarla por encima del tamaño de la ventana (puede ser más lento con imágenes grandes) &Scaling above window size - &Escalar sobre el tamaño de ventana + &Escalar por encima del tamaño de la ventana The amount to zoom every scroll wheel click - La cantidad de acercamiento que da cada paso de desplazamiento + La variación de la ampliación con cada clic de la rueda de desplazamiento Zoom amount: - Cantidad de acercamiento: + Variación de la ampliación: Choose whether scrolling zooms or moves the image (alternative can be accessed at any time by holding ctrl/cmd) - + Elija si el desplazamiento amplía o mueve la imagen (se puede acceder a la alternativa pulsando Ctrl/Cmd) Scrolling &zooms - + &Ampliar con el desplazamiento Stop the image from going past its actual size when resizing the window - you can still zoom past it though - + Evita que la imagen sobrepase su tamaño real al redimensionar la ventana, aunque aún se pueda ampliar Image resizes &past actual size - + &Redimensionar la imagen por encima de su tamaño real Ignores select sides of an image when fitting to window (some sides will extend beyond the window boundaries) - + Ignora los lados seleccionados de una imagen al ajustarla a la ventana (algún lado se extenderá más allá del borde de la ventana) Fit whole image - + Ajustar la imagen completa Fit height - Ajustar a la altura + Ajustar la altura Fit width - Ajustar a la anchura + Ajustar la anchura @@ -957,17 +957,17 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Choose whether or not zooming in and out above 100% zoom will zoom towards the cursor - + Elija si se se ampliará o reducirá la imagen hacia el cursor al superar el 100% de ampliación Zoom &towards cursor - + Ampliar &hacia el cursor Miscellaneous - + Miscelánea @@ -997,7 +997,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Random - Aleatoriamente + Al azar @@ -1033,17 +1033,17 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Extended - + Extendida Controls whether or not qView should go back to the first item after reaching the end of a folder - + Controla si qView debe retornar al primer elemento después de llegar al final de una carpeta &Loop through folders - + &Recorrer las carpetas en bucle @@ -1073,13 +1073,13 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Save &recent files - Guardar archivos &recientes + &Guardar los archivos recientes &Update notifications on startup The notifications are for new qView releases - + &Notificaciones de actualización al inicio @@ -1089,22 +1089,22 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Move Back - + Retroceder Do Nothing - + No hacer nada Move Forward - + Avanzar After deletion: - + Después de borrar: @@ -1115,7 +1115,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Shortcuts - + Accesos rápidos @@ -1148,7 +1148,7 @@ No se tienen permisos de escritura o el archivo es de solo lectura. File name: - Nombre de archivo: + Nombre del archivo: @@ -1160,13 +1160,15 @@ No se tienen permisos de escritura o el archivo es de solo lectura. Could not rename %1: No write permission or file is read-only. - + No se ha podido cambiar el nombre de %1: +No tiene permiso de escritura o el archivo es de solo lectura. Could not rename %1: (Check that all characters are valid) - + No se ha podido cambiar el nombre de %1: +(Compruebe que todos los caracteres sean válidos) @@ -1174,17 +1176,17 @@ No write permission or file is read-only. Modify Shortcuts - + Modificar accesos rápidos Shortcut Already Used - + Acceso rápido en uso "%1" is already bound to "%2" - «%1» ya está asociado con «%2» + «%1» ya está asociado a «%2» @@ -1193,22 +1195,22 @@ No write permission or file is read-only. Welcome - Bienvenido + Bienvenida &Enable update notifications on startup - + &Activar las notificaciones de actualización al inicio Thank you for downloading qView.<br>Here's a few tips to get you started: - + Gracias por descargar qView.<br>Aquí tiene algunos consejos para empezar: <ul><li>Right click to access the main menu</li><li>Drag the image to reposition it</li><li>Scroll to zoom in and out</li><li>Use arrow keys to switch files</li></ul> - + <ul><li>Haga clic derecho para acceder al menú principal</li><li>Arrastre la imagen para recolocarla</li><li>Use el desplazamiento para ampliarla o reducirla</li><li>Use las teclas de flecha para cambiar de archivo</li></ul> @@ -1221,17 +1223,17 @@ No write permission or file is read-only. Open URL - Abrir URL + Abrir un URL Open Containing Folder - + Abrir la carpeta contenedora Show in Explorer - + Mostrar en el explorador @@ -1251,7 +1253,7 @@ No write permission or file is read-only. Undo Delete - Deshacer borrado + Deshacer el borrado @@ -1311,7 +1313,7 @@ No write permission or file is read-only. Reset Zoom - Reiniciar la ampliación + Restablecer la vista @@ -1321,12 +1323,12 @@ No write permission or file is read-only. Rotate Right - Rotar hacia la derecha + Girar a la derecha Rotate Left - Rotar hacia la izquierda + Girar a la izquierda @@ -1336,7 +1338,7 @@ No write permission or file is read-only. Flip - Invertir + Voltear @@ -1346,7 +1348,7 @@ No write permission or file is read-only. Save Frame As - Guardar Fotograma Como + Guardar un fotograma como @@ -1356,17 +1358,17 @@ No write permission or file is read-only. Next Frame - Siguiente fotograma + Fotograma siguiente Decrease Speed - Disminuir la velocidad + Reducir la velocidad Reset Speed - Reiniciar la velocidad + Restablecer la velocidad @@ -1376,7 +1378,7 @@ No write permission or file is read-only. Toggle Slideshow - Activar/Desactivar Presentacion + Activar/desactivar una presentación @@ -1386,12 +1388,12 @@ No write permission or file is read-only. Preferences - Preferencias + Configuración New Window - Nueva ventana + Ventana nueva @@ -1445,7 +1447,7 @@ No write permission or file is read-only. Update notifications on startup have been disabled. You can reenable them in the options dialog. - Notificaciones de actualizaciones al inicio han sido desactivadas. + Se han desactivado las notificaciones de actualización al inicio. Es posible reactivarlas en el dialogo de opciones. diff --git a/i18n/qview_hu.ts b/i18n/qview_hu.ts new file mode 100644 index 00000000..d1fd77b7 --- /dev/null +++ b/i18n/qview_hu.ts @@ -0,0 +1,1442 @@ + + + + + ActionManager + + + Window + Ablak + + + + &File + &Fájl + + + + &Edit + &Szerkesztés + + + + &Go + &Ugrás + + + + &View + &Nézet + + + + &Tools + &Eszközök + + + + &Help + Sú&gó + + + + Open &Recent + Nem&rég megnyitottak + + + + + + Empty + Üres + + + + Open With + Megnyitás programban + + + + &Quit + &Kilépés + + + + Exit + The quit action is called "Exit" on windows + Kilépés + + + + New Window + Új ablak + + + + &Open... + &Megnyitás... + + + + Open &URL... + &URL megnyitása... + + + + Close Window + Ablak bezárása + + + + Close All + Close all windows, that is + Összes bezárása + + + + Open Containing &Folder + Fájlt tartalmazó ma&ppa megnyitása + + + + Show in E&xplorer + Open containing folder on windows + Mutatás az &Intézőben + + + + Show in &Finder + Open containing folder on macOS + Mutatás a &Keresőben + + + + Show File &Info + Fájlin&fók mutatása + + + + &Move to Trash + Áthelyezés a &lomtárba + + + + &Delete + &Törlés + + + + &Restore from Trash + &Helyreállítás a lomtárból + + + + &Undo Delete + Törlés &visszavonása + + + + &Copy + Más&olás + + + + &Paste + &Beillesztés + + + + R&ename... + Átn&evezés... + + + + Zoom &In + Nag&yítás + + + + Zoom &Out + Ki&csinyítés + + + + Reset &Zoom + &Zoom helyreállítása + + + + Ori&ginal Size + Ere&deti méret + + + + Rotate &Right + Elforgatás &jobbra + + + + Rotate &Left + Elforgatás &balra + + + + &Mirror + Tü&krözött nézet + + + + &Flip + Fe&jjel lefelé nézet + + + + Enter F&ull Screen + Belé&pés a teljes-képernyős módba + + + + &First File + Első f&ájlra + + + + Previous Fi&le + El&őző fájlra + + + + &Next File + K&övetkező fájlra + + + + Las&t File + Utols&ó fájlra + + + + Save Frame &As... + K&épkocka mentése másként... + + + + Pa&use + Megáll&ítás + + + + &Next Frame + &Következő képkocka + + + + &Decrease Speed + &Sebesség csökkentése + + + + &Reset Speed + Sebesség &alapértékre állítása + + + + &Increase Speed + Sebesség &növelése + + + + Start S&lideshow + &Diavetítés indítása + + + + Option&s + This is for the options dialog on windows + Beállítá&sok + + + + Preference&s + This is for the options dialog on non-mac unix platforms + Tulajdon&ságok + + + + Preference&s... + This is for the options dialog on mac + Tulajdon&ságok... + + + + &About + Név&jegy + + + + &About qView + This is for the about dialog on mac + &A qView névjegye + + + + &Welcome + &Üdvözlő ablak + + + + Clear &Menu + This is for clearing the recents menu + &Lista törlése + + + + Other Application... + Open with other program for unix non-mac + Megnyitás másik programmal... + + + + Choose another app + Open with other program for windows + Másik program választása + + + + Other... + Open with other program for macos + Másik program... + + + + MainWindow + + + Exit F&ull Screen + Kilépés a teljes-képe&rnyős módból + + + + Enter F&ull Screen + Belé&pés a teljes-képernyős módba + + + + Empty + Üres + + + + + + + + + + Error + Hiba + + + + Error: URL is invalid + Hiba: Érvénytelen URL + + + + Downloading image... + Képek letöltése... + + + + Cancel + Mégse + + + + + Open URL... + URL megnyitása... + + + + Error + Hiba + + + + Error: Invalid image + Hiba: Érvénytelen képfájl + + + + URL of a supported image file: + Egy támogatott képfájl URL-címe: + + + + Can't delete %1: +No write permission or file is read-only. + Nem lehet törölni a(z) %1: fájlt! +Nincs írási jogosultságod vagy a fájl írásvédett. + + + + Are you sure you want to move %1 to the Trash? + Biztosan a lomtárba akarod helyezni a(z) %1 fájlt? + + + + Are you sure you want to move %1 to the Recycle Bin? + Biztosan a lomtárba akarod helyezni a(z) %1 fájlt? + + + + Delete + Törlés + + + + Do not ask again + Ne kérdezze többször + + + + Can't delete %1. + Nem lehet törölni a(z) %1 fájlt. + + + + + Not Supported + Nem támogatott formátum + + + + + This program was compiled with an old version of Qt and this feature is not available. +If you see this message, please report a bug! + Ez a program a Qt egy korábbi verzióját használja, ezért ez a szolgáltatás nem elérhető. +Ha a fenti üzenet fogadna bármikor, kérlek küldj hibajelentést! + + + + Can't undo deletion of %1: +No write permission or file is read-only. + Nem lehet visszavonni a(z) %1: fájl törlését! +Nincs írási jogosultságod vagy a fájl csak olvasható. + + + + Failed undoing deletion of %1. + Sikertelen a(z) %1 fájl törlésének visszavonása. + + + + Save Frame As... + Képkocka mentése mint... + + + + Res&ume + Diavetítés &folytatása + + + + Pause + Megállítás + + + + Start S&lideshow + Dia&vetítés indítása + + + + Stop S&lideshow + Diavetítés megs&zakítása + + + + OpenWith + + + All Applications (*.app) + Minden program (*.app) + + + + Programs (*.exe *.pif *.com *.bat *.cmd) + Programok (*.exe *.pif *.com *.bat *.cmd) + + + + All Files (*) + Minden fájl (*) + + + + QObject + + + file + fájl + + + + The file to open. + A megnyitandó fájl. + + + + QVAboutDialog + + + About qView + A qView névjegye + + + + version %1 + %1 verzió + + + + Nightly %1 + Nightly %1 + + + + Built with Qt %1 (%2)<br>Source code available under GPLv3 on <a style="color: #03A9F4; text-decoration:none;" href="https://github.com/jurplel/qView">GitHub</a><br>Icon glyph created by Guilhem from the Noun Project<br>Copyright © %3 jurplel and qView contributors + A program a Qt %1 verziójával készült (%2)<br>A forráskód GPLv3 licenc alatt elérhető <a style="color: #03A9F4; text-decoration:none;" href="https://github.com/jurplel/qView">GitHub</a>-on<br>Az ikonokat/jelképeket Guilhem készítette a Noun Project keretében<br>Minden jog fenntartva %3 jurplel és a qView hozzájáruló felé + + + + Checking for updates... + Frissítések ellenőrzése... + + + + %1 update available + %1 is a version number e.g. "4.0 update available" + A(z) %1 verziójú frissítés elérhetővé vált + + + + No updates available + Jelenleg nincsenek frissítések + + + + Error checking for updates + Hiba a frissítések ellenőrzése során + + + + QVApplication + + + Supported Images + Támogatott fájlformátumok + + + + All Files + Minden fájl + + + + Open... + Megnyitás... + + + + QVCocoaFunctions + + + (default) + (alapértelmezett) + + + + QVGraphicsView + + + Error + Hiba + + + + Error occurred opening "%3": +%2 (Error %1) + Hiba lépett fel a "%3" fájl megnyitása közben: +%2 (hiba %1) + + + + QVInfoDialog + + + File Info + Fájlinfó + + + + Name: + Név: + + + + + + + + + + + error + hiba + + + + Type: + Típus: + + + + Location: + Hely: + + + + Size: + Méret: + + + + Modified: + Módosítva: + + + + Dimensions: + Méretek: + + + + Aspect Ratio: + Képarány: + + + + Frames: + Képkockák száma: + + + + Refresh + Frissítés + + + + %1 (%2 bytes) + %1 (%2 bájt) + + + + %1 x %2 (%3 MP) + %1 x %2 (%3 megapixel) + + + + QVOpenWithDialog + + + Choose Application + Alkalmazás kiválasztása + + + + Development + Fejlesztés + + + + Education + Oktatás + + + + Games + Játékok + + + + Graphics + Grafika + + + + Internet + Internet + + + + Multimedia + Multimédia + + + + Office + Iroda + + + + Science + Tudomány + + + + Settings + Beállítások + + + + System + Rendszer + + + + Utilities + Felhasználói programok + + + + Other + Egyéb + + + + QVOptionsDialog + + + Options + Beállítások + + + + Window + Ablak + + + + Back&ground color: + &Háttér színe: + + + + Changes the amount of information displayed in the titlebar + A címsorban megjelenítendő információk mennyisége + + + + Titlebar text: + Címsorban lévő szöveg: + + + + &Basic + &Alapvető + + + + &Minimal + &Minimális + + + + &Practical + &Praktikus + + + + &Verbose + &Beszédes + + + + + Control when the window should resize to fit the image's actual size + Szabályozható, hogy az programablak mérete mikor változzon meg a kép tényleges méretéhez képest + + + + Window matches image size: + Az ablak kövesse a kép méretét: + + + + Never + Soha + + + + When launching + A program indításakor + + + + When opening images + Képfájlok megnyitásakor + + + + Minimum size: + Minimális ablakméret: + + + + Control the minimum size that the window should reach when matching the image's actual size + Az ablak minimális mérete, melyet az ablaknak el kell érnie a kép tényleges méretéhez igazodva + + + + + % of screen size + % a képernyő méretéhez viszonyítva + + + + + Control the maximum size that the window should reach when matching the image's actual size + Az ablak maximális mérete, melyet az ablaknak el kell érnie a kép tényleges méretéhez igazodva + + + + Maximum size: + Maximális ablakméret: + + + + Choose whether or not the titlebar should always be dark regardless of your chosen macOS appearance + Válaszd ki, hogy a címsor mindig sötét legyen-e, függetlenül a macOS-ben beállított megjelenéstől + + + + &Titlebar always dark + A &címsor mindig legyen sötét megjelenítésű + + + + Show menubar + Menüsor megjelenítése + + + + Choose whether or not to display the titlebar text while in fullscreen + Válaszd ki, hogy teljes-képernyős megjelenítés esetén a címsor szövege megjelenjen, vagy mégsem + + + + Show titlebar text in fullscreen + Címsor szövegének mutatása teljes-képernyős módban + + + + &Quit on last window closed + Kilépés az &utolsó ablak bezárásakor + + + + Image + Képfájl + + + + Scaling: + Méretezés: + + + + Turn this off to see individual pixels + A különálló pixelek megjelenítéséhez kapcsold be ezt + + + + &Bilinear filtering + &Bilineáris szűrő + + + + Images appear aliased (having jagged edges) without this, but it is faster + A képek megjelenítésénél lépcsőzetesség (szaggatott élek) alakul ki, azonban felgyorsul a kirajzolás + + + + &Image scaling + &Kép felskálázása + + + + Choose whether or not the image continues to be scaled when zooming above the window size (can be laggier with large images) + Válaszd ki, hogy a kép továbbra is skálázva maradjon-e, ha az ablakméreten túl nagyítottál (nagy képeknél magasabb lehet a késleltetés) + + + + &Scaling above window size + &Skálázás megtartása az ablak mérettől függetlenül + + + + + The amount to zoom every scroll wheel click + A zoomolás százalékos mértéke minden egyes görgetésnél + + + + Zoom amount: + Zoomolás mértéke: + + + + Choose whether scrolling zooms or moves the image (alternative can be accessed at any time by holding ctrl/cmd) + Válaszd ki, hogy az egérgörgővel zoomoljon vagy elmozdítsa az adott képet (alternatívaként elérhető a ctrl/cmd nyomva tartásával) + + + + Scrolling &zooms + Egérgörgővel történő &zoomolás + + + + Stop the image from going past its actual size when resizing the window - you can still zoom past it though + A beállítás kikapcsolásával, a megjelenített képfájl igazodik a megjelenítőablak méretéhez - a zoomolás továbbra is lehetséges + + + + Image resizes &past actual size + A kép aktuális mérete &kövesse az ablak méretét + + + + + Ignores select sides of an image when fitting to window (some sides will extend beyond the window boundaries) + Figyelmen kívül hagyja a kép kiválasztott oldalait az ablakhoz történő illesztéskor (egyes oldalak túlnyúlnak az ablak határain) + + + + Fit whole image + A teljes kép igazodjon + + + + Fit height + A kép magassága igazodjon + + + + Fit width + A kép szélessége igazodjon + + + + On window resize: + Az ablak átméretezésekkor: + + + + Choose whether or not zooming in and out above 100% zoom will zoom towards the cursor + Válaszd ki, hogy 100%-os nagyítás feletti zoomolás esetén az egérkurzor körül történjen a zoomolás + + + + Zoom &towards cursor + Zoomolás az &egérkurzor körül + + + + Miscellaneous + További beállítások + + + + Sort files by: + Fájlok rendezése: + + + + Name + Név + + + + Last Modified + Utolsó módosítás + + + + Size + Méret + + + + Type + Típus + + + + Random + Véletlenszerű + + + + A&scending + &Növekvő + + + + D&escending + &Csökkenő + + + + + Controls the amount of images preloaded + Az előretöltött képek mennyiségét lehet szabályozni + + + + Preloading: + Képek előtöltése: + + + + Disabled + Kikapcsolva + + + + Adjacent + Szomszédos fájlok + + + + Extended + Kivőbített + + + + Controls whether or not qView should go back to the first item after reaching the end of a folder + Megadható, hogy a qView menjen-e vissza az első elemhez, miután elérte a mappa utolsó elemét + + + + &Loop through folders + &Könyvtárak körbejárása + + + + Slideshow direction: + Diavetítés feldolgozási sorrendje: + + + + Forward + Előremenő + + + + Backward + Hátramenő + + + + Slideshow timer: + Diavetítés időzítése: + + + + sec + másodperc + + + + Save &recent files + Nem&rég megnyitott fájlok mentése + + + + &Update notifications on startup + The notifications are for new qView releases + Elérhető &frissítések megjelenítése a program indulásakor + + + + Language: + Nyelv: + + + + Move Back + Lépés eggyel hátra + + + + Do Nothing + Semmit se csináljon + + + + Move Forward + Lépés eggyel előre + + + + After deletion: + Egy képfájl törlése után: + + + + &Ask before deleting files + Kérjen &a program megerősítést a törlés előtt + + + + + Shortcuts + Billentyűkombinációk + + + + Action + Végrehajtandó cselekvés + + + + System Language + Rendszer nyelve + + + + Restart Required + A program újraindítása szükséges + + + + You must restart qView to change the language. + A qView nyelvezetének átváltásához újra kell indítanod a programot. + + + + QVRenameDialog + + + Rename... + Átnevezés... + + + + File name: + Fájl neve: + + + + + Error + Hiba + + + + Could not rename %1: +No write permission or file is read-only. + Nem lehet átnevezni a(z) %1 fájlt: +Nincs írási jogosultságod vagy a fájl csak olvasható. + + + + Could not rename %1: +(Check that all characters are valid) + Nem lehet átnevezni a(z) %1 fájlt: +(Ellenőrizd, hogy érvényes karaktereket adtál-e meg) + + + + QVShortcutDialog + + + Modify Shortcuts + Billentyűkombinációk módosítása + + + + Shortcut Already Used + A billentyűkombináció már használatban van + + + + "%1" is already bound to "%2" + "%1" már hozzá van rendelve a(z) "%2"-hoz + + + + QVWelcomeDialog + + + + Welcome + Üdvözlőablak + + + + &Enable update notifications on startup + &Frissítési értesítések engedélyezése indításkor + + + + Thank you for downloading qView.<br>Here's a few tips to get you started: + Köszönjük, hogy letöltötted a qView-ot!<br>Itt van pár tipp a kezdéshez: + + + + <ul><li>Right click to access the main menu</li><li>Drag the image to reposition it</li><li>Scroll to zoom in and out</li><li>Use arrow keys to switch files</li></ul> + <ul><li>Jobb kattintással hozzáférhetsz a főmenühöz</li><li>Húzd be a képet, hogy újraigazítsd</li><li>Az egérgörgővel nagyíthatsz és kicsinyíthetsz</li><li>Használd a kurzort a fájlok közti tallózáshoz</li></ul> + + + + ShortcutManager + + + Open + Megnyitás + + + + Open URL + URL megnyitása + + + + Open Containing Folder + Fájlt tartalmazó mappa megnyitása + + + + Show in Explorer + Mutatás a böngészőben + + + + Show in Finder + Mutatás a keresőben + + + + Show File Info + Fájlinfók mutatása + + + + Restore from Trash + Helyreállítás a Lomtárból + + + + Undo Delete + Törlés visszavonása + + + + Copy + Másolás + + + + Paste + Beillesztés + + + + Rename + Átnevezés + + + + Move to Trash + Áthelyezés a Lomtárba + + + + Delete + Törlés + + + + First File + Ugrás az első fájlra + + + + Previous File + Ugrás az előző fájlra + + + + Next File + Ugrás a következő fájlra + + + + Last File + Ugrás az utolsó fájlra + + + + Zoom In + Nagyítás + + + + Zoom Out + Kicsinyítés + + + + Reset Zoom + Zoomolás alaphelyzetbe állítása + + + + Original Size + Helyreállítás az eredeti méretre + + + + Rotate Right + Forgatás jobbra + + + + Rotate Left + Forgatás balra + + + + Mirror + Tükrözés + + + + Flip + Beforgatás fejjel lefelé + + + + Full Screen + Teljes-képernyő + + + + Save Frame As + Képkocka mentése másként + + + + Pause + Megállít + + + + Next Frame + Következő képkocka + + + + Decrease Speed + Sebesség csökkentése + + + + Reset Speed + Sebesség alaphelyzetbe állítása + + + + Increase Speed + Sebesség növelése + + + + Toggle Slideshow + Diavetítés bekapcsolása + + + + Options + Beállítások + + + + Preferences + Tulajdonságok + + + + New Window + Új ablak + + + + Close Window + Ablak bezárása + + + + Close All + Mind bezárása + + + + Quit + Kilépés + + + + Exit + Kilépés + + + + UpdateChecker + + + Download + Letöltés + + + + qView Update Available + Elérhető egy qView frissítés + + + + qView %1 is available to download. + A qView %1 letöltése elérhetővé vált. + + + + &Disable Update Checking + &Frissítés-ellenőrzés kikapcsolása + + + + qView Update Checking Disabled + A qView frissítés-ellenőrzése ki van kapcsolva + + + + Update notifications on startup have been disabled. +You can reenable them in the options dialog. + Az indításkor érkező frissítési értesítések letiltásra kerültek. +A beállításoknál újra engedélyezheted őket. + + + diff --git a/i18n/qview_id.ts b/i18n/qview_id.ts new file mode 100644 index 00000000..606c4da8 --- /dev/null +++ b/i18n/qview_id.ts @@ -0,0 +1,1439 @@ + + + + + ActionManager + + + Window + Jendela + + + + &File + &Berkas + + + + &Edit + &Sunting + + + + &Go + &Go + + + + &View + &Tampilkan + + + + &Tools + &Peralatan + + + + &Help + &Bantuan + + + + Open &Recent + Buka &Terakhir + + + + + + Empty + Kosong + + + + Open With + Buka Dengan + + + + &Quit + &Keluar + + + + Exit + The quit action is called "Exit" on windows + Keluar + + + + New Window + Jendela Baru + + + + &Open... + &Buka... + + + + Open &URL... + Buka &URL... + + + + Close Window + Tutup Jendela + + + + Close All + Close all windows, that is + Tutup Semua + + + + Open Containing &Folder + Buka isi &Folder + + + + Show in E&xplorer + Open containing folder on windows + Tampilkan di E&xplorer + + + + Show in &Finder + Open containing folder on macOS + Tampilkan di &Finder + + + + Show File &Info + Tampilkan File &Info + + + + &Move to Trash + &Pindah ke Tempat Sampah + + + + &Delete + &Hapus + + + + &Restore from Trash + &Pulihkan dari Sampah + + + + &Undo Delete + &Batalkan penghapusan + + + + &Copy + &Salin + + + + &Paste + &Tempel + + + + R&ename... + U&bah nama... + + + + Zoom &In + Perbe &sar + + + + Zoom &Out + Perke &cil + + + + Reset &Zoom + Setel Ulang &Zoom + + + + Ori&ginal Size + Ori&ginal Ukuran + + + + Rotate &Right + Putar &Kanan + + + + Rotate &Left + Putar &Kiri + + + + &Mirror + &Cermin + + + + &Flip + &Balik + + + + Enter F&ull Screen + Ganti ke L&ayar Penuh + + + + &First File + &File Pertama + + + + Previous Fi&le + Fi&le Sebelumnya + + + + &Next File + &File Berikutnya + + + + Las&t File + File Ter&akhir + + + + Save Frame &As... + Simpan Bingkai &Sebagai... + + + + Pa&use + Je&da + + + + &Next Frame + &Bingkai Berikutnya + + + + &Decrease Speed + &Kurangi Kecepatan + + + + &Reset Speed + &Reset Kecepatan + + + + &Increase Speed + &Tingkatkan Kecepatan + + + + Start S&lideshow + Mulai S&lideshow + + + + Option&s + This is for the options dialog on windows + Opsi + + + + Preference&s + This is for the options dialog on non-mac unix platforms + Preferensi + + + + Preference&s... + This is for the options dialog on mac + Preferensi... + + + + &About + Tentang + + + + &About qView + This is for the about dialog on mac + Tentang qView + + + + &Welcome + &Selamat Datang + + + + Clear &Menu + This is for clearing the recents menu + Hapus &Menu + + + + Other Application... + Open with other program for unix non-mac + Aplikasi Lain... + + + + Choose another app + Open with other program for windows + Pilih aplikasi lain + + + + Other... + Open with other program for macos + Lainnya... + + + + MainWindow + + + Exit F&ull Screen + Keluar dari Tampilan Penuh + + + + Enter F&ull Screen + Masuk ke Tampilan Penuh + + + + Empty + Kosong + + + + + + + + + + Error + Kesalahan + + + + Error: URL is invalid + Kesalahan: URL tidak valid + + + + Downloading image... + Mengunduh gambar... + + + + Cancel + Batal + + + + + Open URL... + Buka URL... + + + + Error + Kesalahan + + + + Error: Invalid image + Kesalahan: Gambar tidak valid + + + + URL of a supported image file: + URL untuk gambar yang didukung: + + + + Can't delete %1: +No write permission or file is read-only. + Tidak dapat menghapus %1: +Tidak ada izin atau gambar hanya bisa dibaca (read-only). + + + + Are you sure you want to move %1 to the Trash? + Apakah Anda yakin untuk memindahkan %1 ke Tempat Sampah? + + + + Are you sure you want to move %1 to the Recycle Bin? + Apakah Anda yakin untuk memindahkan %1 ke Tempat Sampah? + + + + Delete + Hapus + + + + Do not ask again + Jangan tanya lagi + + + + Can't delete %1. + Tidak dapat menghapus %1. + + + + + Not Supported + Tidak Didukung + + + + + This program was compiled with an old version of Qt and this feature is not available. +If you see this message, please report a bug! + Program ini dikompilasi dengan versi lama Qt dan fitur ini tidak tersedia. +Kalau kamu melihat pesan ini, tolong laporkan bug! + + + + Can't undo deletion of %1: +No write permission or file is read-only. + Tidak dapat mengembalikan penghapusan %1: +Tidak ada izin tulis atau berkas hanya dapat dibaca (read-only). + + + + Failed undoing deletion of %1. + + + + + Save Frame As... + + + + + Res&ume + Lanjutkan + + + + Pause + Jeda + + + + Start S&lideshow + Mulai tampilan S&lide + + + + Stop S&lideshow + Hentikan tampilan S&lide + + + + OpenWith + + + All Applications (*.app) + Semua Aplikasi (*.app) + + + + Programs (*.exe *.pif *.com *.bat *.cmd) + Program (*.exe *.pif *.com *.bat *.cmd) + + + + All Files (*) + Semua Berkas (*) + + + + QObject + + + file + berkas + + + + The file to open. + Berkas untuk dibuka. + + + + QVAboutDialog + + + About qView + Tentang qView + + + + version %1 + versi %1 + + + + Nightly %1 + NIghtly %1 + + + + Built with Qt %1 (%2)<br>Source code available under GPLv3 on <a style="color: #03A9F4; text-decoration:none;" href="https://github.com/jurplel/qView">GitHub</a><br>Icon glyph created by Guilhem from the Noun Project<br>Copyright © %3 jurplel and qView contributors + Dibuat dengan Qt %1 (%2)<br>Kode sumber tersedia dengan lisensi GPLv3 via <a style="color: #03A9F4; text-decoration:none;" href="https://github.com/jurplel/qView">GitHub</a><br>Simbol ikon dibuat oleh Guilhem dari Noun Project<br>Hak Cipta © %3 jurplel dan kontributor qView + + + + Checking for updates... + Memeriksa pembaharuan... + + + + %1 update available + %1 is a version number e.g. "4.0 update available" + Pembaharuan ke v%1 tersedia + + + + No updates available + Tidak ada pembaharuan tersedia + + + + Error checking for updates + Kesalahan pengecekan pembaruan + + + + QVApplication + + + Supported Images + Format Gambar Didukung + + + + All Files + Semua Berkas + + + + Open... + Buka... + + + + QVCocoaFunctions + + + (default) + (asali) + + + + QVGraphicsView + + + Error + Kesalahan + + + + Error occurred opening "%3": +%2 (Error %1) + Kesalahan membuka "%3" +%2 (Kesalahan %1) + + + + QVInfoDialog + + + File Info + Info Berkas + + + + Name: + Nama: + + + + + + + + + + + error + kesalahan + + + + Type: + Tipe: + + + + Location: + Lokasi: + + + + Size: + Ukuran: + + + + Modified: + Modifikasi: + + + + Dimensions: + Dimensi: + + + + Aspect Ratio: + Rasio Aspek: + + + + Frames: + + + + + Refresh + Segarkan + + + + %1 (%2 bytes) + %1 (%2 bita) + + + + %1 x %2 (%3 MP) + %1 x %2 (%3 MP) + + + + QVOpenWithDialog + + + Choose Application + Pilih Aplikasi + + + + Development + Pengembangan + + + + Education + Edukasi + + + + Games + Permainan + + + + Graphics + Grafik + + + + Internet + Internet + + + + Multimedia + Multimedia + + + + Office + Kantor + + + + Science + Sains + + + + Settings + Pengaturan + + + + System + Sistem + + + + Utilities + Utilitas + + + + Other + Lainnya + + + + QVOptionsDialog + + + Options + Opsi + + + + Window + Jendela + + + + Back&ground color: + Warna latar belakan&g: + + + + Changes the amount of information displayed in the titlebar + Ubah informasi yang ditampilkan di bar judul + + + + Titlebar text: + Teks bar judul: + + + + &Basic + Dasar + + + + &Minimal + &Minimal + + + + &Practical + &Praktikal + + + + &Verbose + + + + + + Control when the window should resize to fit the image's actual size + Kontrol ketika jendela harus menyesuaikan dengan ukuran asli gambar + + + + Window matches image size: + Jendela sesuai ukuran gambar: + + + + Never + Jangan pernah + + + + When launching + Ketika memulai + + + + When opening images + Ketika membuka gambar + + + + Minimum size: + Ukuran minimum: + + + + Control the minimum size that the window should reach when matching the image's actual size + + + + + + % of screen size + % dari ukuran layar + + + + + Control the maximum size that the window should reach when matching the image's actual size + + + + + Maximum size: + Ukuran maksimum: + + + + Choose whether or not the titlebar should always be dark regardless of your chosen macOS appearance + + + + + &Titlebar always dark + Bar judul selalu gelap + + + + Show menubar + Tampilkan bar menu + + + + Choose whether or not to display the titlebar text while in fullscreen + + + + + Show titlebar text in fullscreen + + + + + &Quit on last window closed + + + + + Image + + + + + Scaling: + + + + + Turn this off to see individual pixels + + + + + &Bilinear filtering + + + + + Images appear aliased (having jagged edges) without this, but it is faster + + + + + &Image scaling + + + + + Choose whether or not the image continues to be scaled when zooming above the window size (can be laggier with large images) + + + + + &Scaling above window size + + + + + + The amount to zoom every scroll wheel click + + + + + Zoom amount: + + + + + Choose whether scrolling zooms or moves the image (alternative can be accessed at any time by holding ctrl/cmd) + + + + + Scrolling &zooms + + + + + Stop the image from going past its actual size when resizing the window - you can still zoom past it though + + + + + Image resizes &past actual size + + + + + + Ignores select sides of an image when fitting to window (some sides will extend beyond the window boundaries) + + + + + Fit whole image + + + + + Fit height + + + + + Fit width + + + + + On window resize: + + + + + Choose whether or not zooming in and out above 100% zoom will zoom towards the cursor + + + + + Zoom &towards cursor + + + + + Miscellaneous + + + + + Sort files by: + + + + + Name + + + + + Last Modified + + + + + Size + + + + + Type + + + + + Random + + + + + A&scending + + + + + D&escending + + + + + + Controls the amount of images preloaded + + + + + Preloading: + + + + + Disabled + + + + + Adjacent + + + + + Extended + + + + + Controls whether or not qView should go back to the first item after reaching the end of a folder + + + + + &Loop through folders + + + + + Slideshow direction: + + + + + Forward + + + + + Backward + + + + + Slideshow timer: + + + + + sec + + + + + Save &recent files + + + + + &Update notifications on startup + The notifications are for new qView releases + + + + + Language: + + + + + Move Back + + + + + Do Nothing + + + + + Move Forward + + + + + After deletion: + + + + + &Ask before deleting files + + + + + + Shortcuts + + + + + Action + + + + + System Language + + + + + Restart Required + + + + + You must restart qView to change the language. + + + + + QVRenameDialog + + + Rename... + + + + + File name: + + + + + + Error + + + + + Could not rename %1: +No write permission or file is read-only. + + + + + Could not rename %1: +(Check that all characters are valid) + + + + + QVShortcutDialog + + + Modify Shortcuts + + + + + Shortcut Already Used + + + + + "%1" is already bound to "%2" + + + + + QVWelcomeDialog + + + + Welcome + + + + + &Enable update notifications on startup + + + + + Thank you for downloading qView.<br>Here's a few tips to get you started: + + + + + <ul><li>Right click to access the main menu</li><li>Drag the image to reposition it</li><li>Scroll to zoom in and out</li><li>Use arrow keys to switch files</li></ul> + + + + + ShortcutManager + + + Open + + + + + Open URL + + + + + Open Containing Folder + + + + + Show in Explorer + + + + + Show in Finder + + + + + Show File Info + + + + + Restore from Trash + + + + + Undo Delete + + + + + Copy + + + + + Paste + + + + + Rename + + + + + Move to Trash + + + + + Delete + + + + + First File + + + + + Previous File + + + + + Next File + + + + + Last File + + + + + Zoom In + + + + + Zoom Out + + + + + Reset Zoom + + + + + Original Size + + + + + Rotate Right + + + + + Rotate Left + + + + + Mirror + + + + + Flip + + + + + Full Screen + + + + + Save Frame As + + + + + Pause + + + + + Next Frame + + + + + Decrease Speed + + + + + Reset Speed + + + + + Increase Speed + + + + + Toggle Slideshow + + + + + Options + + + + + Preferences + + + + + New Window + + + + + Close Window + + + + + Close All + + + + + Quit + + + + + Exit + + + + + UpdateChecker + + + Download + + + + + qView Update Available + Pembaharuan qView Tersedia + + + + qView %1 is available to download. + qView %1 tersedia untuk diunduh. + + + + &Disable Update Checking + + + + + qView Update Checking Disabled + + + + + Update notifications on startup have been disabled. +You can reenable them in the options dialog. + + + + diff --git a/i18n/qview_it.ts b/i18n/qview_it.ts index 1f7e9d6d..7971b279 100644 --- a/i18n/qview_it.ts +++ b/i18n/qview_it.ts @@ -95,7 +95,7 @@ Open Containing &Folder - Apri &cartella contenente + Apri il contenuto della &cartella @@ -382,76 +382,78 @@ Mancanza di permessi di scrittura oppure file a sola lettura. Are you sure you want to move %1 to the Trash? - + Sei sicuro di voler spostare %1 nel cestino? Are you sure you want to move %1 to the Recycle Bin? - + Sei sicuro di voler spostare %1 nel Cestino? Delete - + Elimina Do not ask again - + Non chiedere di nuovo Can't delete %1. - + Impossibile eliminare %1. Not Supported - + Non supportato This program was compiled with an old version of Qt and this feature is not available. If you see this message, please report a bug! - + Questo programma è stato compilato con una vecchia versione di Qt e questa funzione non è disponibile. +Se vedi questo messaggio, per favore segnala un bug! Can't undo deletion of %1: No write permission or file is read-only. - + Impossibile annullare l'eliminazione di %1: +Nessun permesso di scrittura o il file è di sola lettura. Failed undoing deletion of %1. - + Impossibile annullare l'eliminazione di %1. Save Frame As... - + Salva fotogramma come... Res&ume - + Ricomincia Pause - + Pausa Start S&lideshow - + Avvia Presentazione Stop S&lideshow - + Ferma presentazione @@ -459,17 +461,17 @@ No write permission or file is read-only. All Applications (*.app) - + Tutte le applicazioni (*.app) Programs (*.exe *.pif *.com *.bat *.cmd) - + Programmi (*.exe *.pif *.com *.bat *.cmd) All Files (*) - + Tutti i file (*) @@ -477,12 +479,12 @@ No write permission or file is read-only. file - + file The file to open. - + Il file da aprire. @@ -490,43 +492,43 @@ No write permission or file is read-only. About qView - + Informazioni su qView version %1 - + versione %1 Nightly %1 - + Notturna %1 Built with Qt %1 (%2)<br>Source code available under GPLv3 on <a style="color: #03A9F4; text-decoration:none;" href="https://github.com/jurplel/qView">GitHub</a><br>Icon glyph created by Guilhem from the Noun Project<br>Copyright © %3 jurplel and qView contributors - + Costruito con Qt %1 (%2)<br>Codice sorgente disponibile sotto GPLv3 su <a style="color: #03A9F4; text-decoration:none;" href="https://github.com/jurpplel/qView">GitHub</a><br>Icona glifo creata da Guilhem dal progetto Noun<br>Copyright © %3 contributori di jurpel e qView Checking for updates... - + Verifica aggiornamenti... %1 update available %1 is a version number e.g. "4.0 update available" - + %1 aggiornamento disponibile No updates available - + Nessun aggiornamento disponibile Error checking for updates - + Errori durante il controllo degli aggiornamenti @@ -534,12 +536,12 @@ No write permission or file is read-only. Supported Images - + Immagini supportate All Files - + Tutti i file @@ -552,7 +554,7 @@ No write permission or file is read-only. (default) - + (predefinito) @@ -566,7 +568,8 @@ No write permission or file is read-only. Error occurred opening "%3": %2 (Error %1) - + Errore durante l'apertura di "%3": +%2 (errore %1) @@ -574,12 +577,12 @@ No write permission or file is read-only. File Info - + Informazione sul file Name: - + Nome: @@ -591,57 +594,57 @@ No write permission or file is read-only. error - + errore Type: - + Tipo: Location: - + Posizione: Size: - + Dimensione: Modified: - + Modificato: Dimensions: - + Dimensioni: Aspect Ratio: - + Proporzioni: Frames: - + Fotogrammi: Refresh - + Aggiorna %1 (%2 bytes) - + %1 (%2 byte) %1 x %2 (%3 MP) - + %1 x %2 (%3 MP) @@ -649,67 +652,67 @@ No write permission or file is read-only. Choose Application - + Scegli applicazione Development - + Sviluppo Education - + Istruzione Games - + Giochi Graphics - + Grafica Internet - + Internet Multimedia - + Multimedia Office - + Ufficio Science - + Scienze Settings - + Impostazioni System - + Sistema Utilities - + Utilità Other - + Altro @@ -717,410 +720,410 @@ No write permission or file is read-only. Options - + Opzioni Window - + Finestra Back&ground color: - + Colore di sfondo: Changes the amount of information displayed in the titlebar - + Modifica la quantità di informazioni visualizzate nella barra del titolo Titlebar text: - + Testo della barra del titolo: &Basic - + &Basico &Minimal - + &Minimale &Practical - + &Pratico &Verbose - + &Prolisso Control when the window should resize to fit the image's actual size - + Controlla quando la finestra deve essere ridimensionata per adattarsi alle dimensioni effettive dell'immagine Window matches image size: - + La finestra corrisponde alla dimensione dell'immagine: Never - + Mai When launching - + Quando si avvia When opening images - + All'apertura delle immagini Minimum size: - + Dimensione minima: Control the minimum size that the window should reach when matching the image's actual size - + Controlla la dimensione minima che la finestra deve raggiungere quando corrisponde alla dimensione effettiva dell'immagine % of screen size - + % delle dimensioni dello schermo Control the maximum size that the window should reach when matching the image's actual size - + Controlla la dimensione massima che la finestra dovrebbe raggiungere quando corrisponde alla dimensione effettiva dell'immagine Maximum size: - + Dimensione massima: Choose whether or not the titlebar should always be dark regardless of your chosen macOS appearance - + Scegli se la barra del titolo deve essere sempre scura, indipendentemente dall'aspetto macOS scelto &Titlebar always dark - + &Barra del titolo sempre scura Show menubar - + Mostra la barra del menu Choose whether or not to display the titlebar text while in fullscreen - + Scegli se visualizzare o meno il testo della barra del titolo a schermo intero Show titlebar text in fullscreen - + Mostra il testo della barra del titolo a schermo intero &Quit on last window closed - + &Esci all'ultima finestra chiusa Image - + Immagine Scaling: - + Ridimensionamento: Turn this off to see individual pixels - + Disattiva questa opzione per vedere i singoli pixel &Bilinear filtering - + &Filtraggio bilineare Images appear aliased (having jagged edges) without this, but it is faster - + Le immagini appaiono distorte (con bordi frastagliati) senza questo, ma è più veloce &Image scaling - + &Ridimensionamento immagine Choose whether or not the image continues to be scaled when zooming above the window size (can be laggier with large images) - + Scegli se l'immagine continua a essere ridimensionata o meno quando si esegue lo zoom sopra la dimensione della finestra (può essere più lento con immagini di grandi dimensioni) &Scaling above window size - + &Ridimensionamento sopra la dimensione della finestra The amount to zoom every scroll wheel click - + La quantità di zoom per ogni clic della rotella di scorrimento Zoom amount: - + Quantità di ingrandimento: Choose whether scrolling zooms or moves the image (alternative can be accessed at any time by holding ctrl/cmd) - + Scegli se lo scorrimento ingrandisce o sposta l'immagine (è possibile accedere in alternativa in qualsiasi momento tenendo premuto ctrl/cmd) Scrolling &zooms - + Scorrimento &zoom Stop the image from going past its actual size when resizing the window - you can still zoom past it though - + Impedisci all'immagine di superare la sua dimensione effettiva durante il ridimensionamento della finestra: puoi comunque eseguire lo zoom Image resizes &past actual size - + L'immagine si ridimensiona &supera le dimensioni effettive Ignores select sides of an image when fitting to window (some sides will extend beyond the window boundaries) - + Ignora i lati selezionati di un'immagine durante l'adattamento alla finestra (alcuni lati si estenderanno oltre i limiti della finestra) Fit whole image - + Adatta l'intera immagine Fit height - + Adatta altezza Fit width - + Adatta larghezza On window resize: - + Al ridimensionamento della finestra: Choose whether or not zooming in and out above 100% zoom will zoom towards the cursor - + Scegli se lo zoom in avanti e indietro oltre il 100% verrà eseguito in direzione del cursore Zoom &towards cursor - + Zoom &verso il cursore Miscellaneous - + Varie Sort files by: - + Ordina i file per: Name - + Nome Last Modified - + Ultima modifica Size - + Dimensione Type - + Tipo Random - + A caso A&scending - + A&scendente D&escending - + D&iscendente Controls the amount of images preloaded - + Controlla la quantità di immagini precaricate Preloading: - + Precaricamento: Disabled - + Disabilitato Adjacent - + Adiacente Extended - + Esteso Controls whether or not qView should go back to the first item after reaching the end of a folder - + Controlla se qView deve tornare al primo elemento dopo aver raggiunto la fine di una cartella &Loop through folders - + &Esegui il ciclo delle cartelle Slideshow direction: - + Direzione della presentazione: Forward - + Avanti Backward - + Indietro Slideshow timer: - + Timer presentazione: sec - + sec Save &recent files - + Salva &file recenti &Update notifications on startup The notifications are for new qView releases - + &Aggiorna le notifiche all'avvio Language: - + Lingua: Move Back - + Sposta indietro Do Nothing - + Non fare nulla Move Forward - + Sposta avanti After deletion: - + Dopo la cancellazione: &Ask before deleting files - + &Chiedi prima di eliminare i file Shortcuts - + Scorciatoie Action - + Azione System Language - + Lingua di sistema Restart Required - + Riavvio richiesto You must restart qView to change the language. - + È necessario riavviare qView per cambiare la lingua. @@ -1128,30 +1131,32 @@ No write permission or file is read-only. Rename... - + Rinomina... File name: - + Nome file: Error - + Errore Could not rename %1: No write permission or file is read-only. - + Impossibile rinominare %1: +Nessun permesso di scrittura o il file è di sola lettura. Could not rename %1: (Check that all characters are valid) - + Impossibile rinominare %1: +(Controlla che tutti i caratteri siano validi) @@ -1159,17 +1164,17 @@ No write permission or file is read-only. Modify Shortcuts - + Modifica scorciatoie Shortcut Already Used - + Scorciatoia già utilizzata "%1" is already bound to "%2" - + "%1" è già associato a "%2" @@ -1178,22 +1183,22 @@ No write permission or file is read-only. Welcome - + Benvenuti &Enable update notifications on startup - + &Abilita le notifiche di aggiornamento all'avvio Thank you for downloading qView.<br>Here's a few tips to get you started: - + Grazie per aver scaricato qView.<br>Ecco alcuni suggerimenti per iniziare: <ul><li>Right click to access the main menu</li><li>Drag the image to reposition it</li><li>Scroll to zoom in and out</li><li>Use arrow keys to switch files</li></ul> - + <ul><li>Fai clic con il pulsante destro del mouse per accedere al menu principale</li><li>Trascina l'immagine per riposizionarla</li><li>Scorri per ingrandire e ridurre</li><li>Utilizza i tasti freccia per cambia file</li></ul> @@ -1201,202 +1206,202 @@ No write permission or file is read-only. Open - + Apri Open URL - + Apri URL Open Containing Folder - + Apri contenuto della cartella Show in Explorer - + Mostra in Explorer Show in Finder - + Mostra in Finder Show File Info - + Mostra informazioni sul file Restore from Trash - + Ripristina dal Cestino Undo Delete - + Annulla eliminazione Copy - + Copia Paste - + Incolla Rename - + Rinomina Move to Trash - + Sposta nel Cestino Delete - + Elimina First File - + Primo file Previous File - + File precedente Next File - + File successivo Last File - + Ultimo file Zoom In - + Zoom avanti Zoom Out - + Zoom indietro Reset Zoom - + Ripristina zoom Original Size - + Dimensione originale Rotate Right - + Ruota a destra Rotate Left - + Ruota a sinistra Mirror - + Specchia Flip - + Capovolgi Full Screen - + Schermo intero Save Frame As - + Salva fotogramma come Pause - + Pausa Next Frame - + Prossimo fotogramma Decrease Speed - + Diminuisci velocità Reset Speed - + Reimposta la velocità Increase Speed - + Aumenta la velocità Toggle Slideshow - + Attiva/disattiva presentazione Options - + Opzioni Preferences - + Preferenze New Window - + Nuova finestra Close Window - + Chiudi finestra Close All - + Chiudi tutto Quit - + Esci Exit - + Esci @@ -1404,33 +1409,34 @@ No write permission or file is read-only. Download - + Download qView Update Available - + qView aggiornamento disponibile qView %1 is available to download. - + qView %1 è disponibile per il download. &Disable Update Checking - + &Disattiva controllo aggiornamenti qView Update Checking Disabled - + qView Controllo aggiornamenti disabilitato Update notifications on startup have been disabled. You can reenable them in the options dialog. - + Le notifiche di aggiornamento all'avvio sono state disabilitate. +Puoi riattivarle nella finestra di dialogo delle opzioni. diff --git a/i18n/qview_ko.ts b/i18n/qview_ko.ts index e1a1ce49..f5bbe332 100644 --- a/i18n/qview_ko.ts +++ b/i18n/qview_ko.ts @@ -53,7 +53,7 @@ Open With - + 다음으로 열기 @@ -117,22 +117,22 @@ &Move to Trash - + 휴지통으로 이동(&M) &Delete - + 삭제(&D) &Restore from Trash - + 휴지통에서 복구하기(&R) &Undo Delete - + 삭제 되돌리기(&U) @@ -293,19 +293,19 @@ Other Application... Open with other program for unix non-mac - + 다른 응용프로그램... Choose another app Open with other program for windows - + 다른 앱 선택 Other... Open with other program for macos - + 그 외... @@ -323,7 +323,7 @@ Empty - 없음 + 비어 있음 @@ -376,56 +376,59 @@ Can't delete %1: No write permission or file is read-only. - + %1 삭제 불가: +권한이 없거나 읽기 전용 파일입니다. Are you sure you want to move %1 to the Trash? - + %1 파일을 휴지통으로 이동하시겠습니까? Are you sure you want to move %1 to the Recycle Bin? - + %1 파일을 휴지통으로 이동하시겠습니까? Delete - + 삭제 Do not ask again - + 더이상 묻지 않기 Can't delete %1. - + %1 삭제 불가. Not Supported - + 지원되지 않음 This program was compiled with an old version of Qt and this feature is not available. If you see this message, please report a bug! - + 오래된 Qt 버전으로 프로그램이 컴파일돼 기능을 사용할 수 없습니다. +이 메시지를 본다면 버그로 제보해주세요! Can't undo deletion of %1: No write permission or file is read-only. - + %1 파일 삭제를 되돌릴 수 없음: +권한이 없거나 읽기 전용 파일입니다. Failed undoing deletion of %1. - + %1 파일의 복구에 실패했습니다. Rename... @@ -472,17 +475,17 @@ No write permission or file is read-only. All Applications (*.app) - + 모든 애플리케이션(*.app) Programs (*.exe *.pif *.com *.bat *.cmd) - + 프로그램 (*.exe *.pif *.com *.bat *.cmd) All Files (*) - + 모든 파일(*) @@ -551,7 +554,7 @@ No write permission or file is read-only. Supported Images - + 지원되는 이미지 @@ -569,7 +572,7 @@ No write permission or file is read-only. (default) - + (기본) @@ -667,67 +670,67 @@ No write permission or file is read-only. Choose Application - + 애플리케이션 선택 Development - + 개발 Education - + 교육 Games - + 게임 Graphics - + 그래픽 Internet - + 인터넷 Multimedia - + 멀티미디어 Office - + 오피스 Science - + 과학 Settings - + 환경설정 System - + 시스템 Utilities - + 유틸리티 Other - + 그 외 @@ -735,7 +738,7 @@ No write permission or file is read-only. Options - 환경설정 + 옵션 @@ -858,7 +861,7 @@ No write permission or file is read-only. &Quit on last window closed - + 마지막 창을 닫을 때 종료(&Q) @@ -1092,27 +1095,27 @@ No write permission or file is read-only. Move Back - + 이전으로 Do Nothing - + 아무것도 하지 않음 Move Forward - + 다음으로 After deletion: - + 삭제 후: &Ask before deleting files - + 파일을 삭제하기 전에 묻기(&A) @@ -1146,30 +1149,32 @@ No write permission or file is read-only. Rename... - 이름변경... + 이름 변경... File name: - 파일 이름: + 파일 이름: Error - 오류 + 오류 Could not rename %1: No write permission or file is read-only. - + %1 파일 이름을 변경할 수 없음: +권한이 없거나 읽기 전용 파일입니다. Could not rename %1: (Check that all characters are valid) - + %1 파일 이름을 변경할 수 없음: +(문자열이 올바른지 확인) @@ -1249,12 +1254,12 @@ No write permission or file is read-only. Restore from Trash - + 휴지통에서 복구하기 Undo Delete - + 삭제 되돌리기 @@ -1274,12 +1279,12 @@ No write permission or file is read-only. Move to Trash - + 휴지통으로 이동 Delete - + 삭제 diff --git a/i18n/qview_nb_NO.ts b/i18n/qview_nb_NO.ts index 1c60c76f..45964fa7 100644 --- a/i18n/qview_nb_NO.ts +++ b/i18n/qview_nb_NO.ts @@ -74,12 +74,12 @@ &Open... - &Åpne… + &Åpne … Open &URL... - Åpne &nettadresse… + Åpne &nettadresse … @@ -147,7 +147,7 @@ R&ename... - &Gi nytt navn… + &Gi nytt navn … @@ -217,7 +217,7 @@ Save Frame &As... - Lagre ramme &som… + Lagre ramme &som … @@ -265,7 +265,7 @@ Preference&s... This is for the options dialog on mac - &Innstillinge&r… + &Innstillinge&r … @@ -344,7 +344,7 @@ Downloading image... - Laster ned bilde… + Laster ned bilde … @@ -355,7 +355,7 @@ Open URL... - Åpne nettadresse… + Åpne nettadresse … @@ -447,7 +447,7 @@ Ingen skrivetilgang, eller så er filen skrivebeskyttet. Save Frame As... - Lagre ramme som… + Lagre ramme som … @@ -526,7 +526,7 @@ Ingen skrivetilgang, eller så er filen skrivebeskyttet. Checking for updates... - Se etter nye versjoner… + Se etter nye versjoner … @@ -564,7 +564,7 @@ Ingen skrivetilgang, eller så er filen skrivebeskyttet. Open... - Åpne… + Åpne … @@ -1149,7 +1149,7 @@ Ingen skrivetilgang, eller så er filen skrivebeskyttet. Rename... - Gi nytt navn… + Gi nytt navn … diff --git a/i18n/qview_ru.ts b/i18n/qview_ru.ts index 1d7baa86..d64490c5 100644 --- a/i18n/qview_ru.ts +++ b/i18n/qview_ru.ts @@ -387,7 +387,7 @@ No write permission or file is read-only. Are you sure you want to move %1 to the Recycle Bin? - Вы уверены, что хотите переместить %1 в корзину? + Вы уверены, что хотите переместить %1 в Recycle Bin? diff --git a/i18n/qview_uk.ts b/i18n/qview_uk.ts index 2e15777a..1cd03ee5 100644 --- a/i18n/qview_uk.ts +++ b/i18n/qview_uk.ts @@ -6,306 +6,306 @@ Window - + Вікно &File - + Файл &Edit - + Редагувати &Go - + Вперед &View - + Переглянути &Tools - + Інструменти &Help - + Допомога Open &Recent - + Відкрити останні Empty - + Порожньо Open With - + Відкрити за допомогою &Quit - + Вийти Exit The quit action is called "Exit" on windows - + Вийти New Window - + Нове вікно &Open... - + Відкрити... Open &URL... - + Відкрити URL... Close Window - + Закрити вікно Close All Close all windows, that is - + Закрити всі Open Containing &Folder - + Відкрити цільову папку Show in E&xplorer Open containing folder on windows - + Показати в Провіднику Show in &Finder Open containing folder on macOS - + Показати в Пошуку Show File &Info - + Показати інформацію про файл &Move to Trash - + Перемістити в кошик &Delete - + Видалити &Restore from Trash - + Відновити з кошика &Undo Delete - + Скасувати видалення &Copy - + Копіювати &Paste - + Вставити R&ename... - + Перейменувати... Zoom &In - + Збільшити Zoom &Out - + Зменшити Reset &Zoom - + Скидання та масштабування Ori&ginal Size - + Орієнтовний розмір Rotate &Right - + Повернути праворуч Rotate &Left - + Повернути ліворуч &Mirror - + Віддзеркалити &Flip - + Перевернути Enter F&ull Screen - + Перейти у повноекранний режим &First File - + Перший файл Previous Fi&le - + Попередній файл &Next File - + Наступний файл Las&t File - + Останній файл Save Frame &As... - + Зберегти кадр як... Pa&use - + Призупинити &Next Frame - + Наступний кадр &Decrease Speed - + Зменшити швидкість &Reset Speed - + Скинути швидкість &Increase Speed - + Збільшити швидкість Start S&lideshow - + Почати слайд-шоу Option&s This is for the options dialog on windows - + Параметри Preference&s This is for the options dialog on non-mac unix platforms - + Налаштування Preference&s... This is for the options dialog on mac - + Налаштування та... &About - + Про застосунок &About qView This is for the about dialog on mac - + Про qView &Welcome - + Ласкаво просимо Clear &Menu This is for clearing the recents menu - + Очистити меню Other Application... Open with other program for unix non-mac - + Інший застосунок... Choose another app Open with other program for windows - + Оберіть інший застосунок Other... Open with other program for macos - + Інше... @@ -313,17 +313,17 @@ Exit F&ull Screen - + Вийти з повноекранного режиму Enter F&ull Screen - + Перейти у повноекранний режим Empty - + Порожньо @@ -334,123 +334,126 @@ Error - + Помилка Error: URL is invalid - + Помилка: URL-адреса невірна Downloading image... - + Завантажити зображення... Cancel - + Скасувати Open URL... - + Відкрити URL... Error - + Помилка Error: Invalid image - + Помилка: недійсне зображення URL of a supported image file: - + URL-адреса підтримуваного файлу зображення: Can't delete %1: No write permission or file is read-only. - + Не вдається видалити %1: +Немає дозволу на запис або файл доступний тільки для читання. Are you sure you want to move %1 to the Trash? - + Ви дійсно хочете перемістити %1 до Корзини? Are you sure you want to move %1 to the Recycle Bin? - + Ви впевнені, що хочете перемістити %1 до Кошика? Delete - + Видалити Do not ask again - + Більше не питайте Can't delete %1. - + Неможливо видалити %1. Not Supported - + Не підтримується This program was compiled with an old version of Qt and this feature is not available. If you see this message, please report a bug! - + Ця програма була скомпільована зі старою версією Qt, і ця функція недоступна. +Якщо ви бачите це повідомлення, повідомте про помилку! Can't undo deletion of %1: No write permission or file is read-only. - + Неможливо скасувати видалення %1: +Немає дозволу на запис або файл доступний тільки для читання. Failed undoing deletion of %1. - + Не вдалося скасувати видалення %1. Save Frame As... - + Зберегти кадр як... Res&ume - + Відновити Pause - + Пауза Start S&lideshow - + Почати слайд-шоу Stop S&lideshow - + Зупинити слайд-шоу @@ -458,17 +461,17 @@ No write permission or file is read-only. All Applications (*.app) - + Всі застосунки (*.app) Programs (*.exe *.pif *.com *.bat *.cmd) - + Програми (*.exe *.pif *.com *.bat *.cmd) All Files (*) - + Всі файли (*) @@ -476,12 +479,12 @@ No write permission or file is read-only. file - + файл The file to open. - + Файл для відкриття. @@ -489,43 +492,43 @@ No write permission or file is read-only. About qView - + Про qView version %1 - + версія %1 Nightly %1 - + Нічний %1 Built with Qt %1 (%2)<br>Source code available under GPLv3 on <a style="color: #03A9F4; text-decoration:none;" href="https://github.com/jurplel/qView">GitHub</a><br>Icon glyph created by Guilhem from the Noun Project<br>Copyright © %3 jurplel and qView contributors - + Створено за допомогою Qt %1 (%2)<br>Вихідний код доступний під GPLv3 на <a style="color: #03A9F4; text-decoration:none;" href="https://github.com/jurplel/qView">GitHub</a><br> Значок гліф , створений Гільхемом із проєкту Noun<br>Авторське право © %3 співавтори jurplel і qView Checking for updates... - + Перевірка наявності оновлень... %1 update available %1 is a version number e.g. "4.0 update available" - + %1 оновлення доступне No updates available - + Немає оновлень Error checking for updates - + Помилка перевірки оновлень @@ -533,17 +536,17 @@ No write permission or file is read-only. Supported Images - + Підтримувані зображення All Files - + Всі файли Open... - + Відкрити... @@ -551,7 +554,7 @@ No write permission or file is read-only. (default) - + (за замовчуванням) @@ -559,13 +562,14 @@ No write permission or file is read-only. Error - + Помилка Error occurred opening "%3": %2 (Error %1) - + Виникла помилка при відкритті "%3": +%2 (Помилка %1) @@ -573,12 +577,12 @@ No write permission or file is read-only. File Info - + Інформація про файл Name: - + Ім'я: @@ -590,57 +594,57 @@ No write permission or file is read-only. error - + помилка Type: - + Тип: Location: - + Місцезнаходження: Size: - + Розмір: Modified: - + Змінено: Dimensions: - + Розміри: Aspect Ratio: - + Співвідношення сторін: Frames: - + Кадри: Refresh - + Оновити %1 (%2 bytes) - + %1 (%2 байт) %1 x %2 (%3 MP) - + %1 x %2 (%3 МР) @@ -648,67 +652,67 @@ No write permission or file is read-only. Choose Application - + Оберіть застосунок Development - + Розробка Education - + Освіта Games - + Ігри Graphics - + Графіка Internet - + Інтернет Multimedia - + Мультимедіа Office - + Офіс Science - + Наука Settings - + Налаштування System - + Система Utilities - + Утиліти Other - + Інше @@ -716,410 +720,410 @@ No write permission or file is read-only. Options - + Опції Window - + Вікно Back&ground color: - + Колір фону: Changes the amount of information displayed in the titlebar - + Зміна обсягу інформації, що відображається в рядку заголовка Titlebar text: - + Текст заголовка: &Basic - + Основний &Minimal - + Мінімальний &Practical - + Практичний &Verbose - + Багатослівний Control when the window should resize to fit the image's actual size - + Керування тим, коли вікно повинно змінювати розмір відповідно до реального розміру зображення Window matches image size: - + Вікно відповідає розміру зображення: Never - + Ніколи When launching - + При запуску When opening images - + При відкритті зображень Minimum size: - + Мінімальний розмір: Control the minimum size that the window should reach when matching the image's actual size - + Керування мінімальним розміром, якого повинно досягати вікно при відповідності фактичного розміру зображення % of screen size - + % від розміру екрану Control the maximum size that the window should reach when matching the image's actual size - + Керування максимальним розміром, якого повинно досягати вікно при відповідності реальному розміру зображення Maximum size: - + Максимальний розмір: Choose whether or not the titlebar should always be dark regardless of your chosen macOS appearance - + Виберіть, чи повинен рядок заголовка завжди бути темним, незалежно від обраного вами зовнішнього вигляду macOS &Titlebar always dark - + &Титульний рядок завжди темний Show menubar - + Показати меню Choose whether or not to display the titlebar text while in fullscreen - + Виберіть, чи відображати текст заголовка в повноекранному режимі Show titlebar text in fullscreen - + Показати текст заголовка на весь екран &Quit on last window closed - + Вихід при закритті останнього вікна Image - + Зображення Scaling: - + Масштабування: Turn this off to see individual pixels - + Вимкніть, щоб побачити окремі пікселі &Bilinear filtering - + Білінійна фільтрація Images appear aliased (having jagged edges) without this, but it is faster - + Зображення виглядають аліасними (з нерівними краями) і без цього, але так швидше &Image scaling - + Масштабування зображення Choose whether or not the image continues to be scaled when zooming above the window size (can be laggier with large images) - + Виберіть, чи продовжувати масштабування зображення при збільшенні понад розмір вікна (може бути повільніше з великими зображеннями) &Scaling above window size - + &Масштабування за розміром вікна The amount to zoom every scroll wheel click - + Величина масштабування при кожному натисканні колеса прокрутки Zoom amount: - + Збільшити масштаб: Choose whether scrolling zooms or moves the image (alternative can be accessed at any time by holding ctrl/cmd) - + Виберіть, чи буде прокрутка масштабувати або переміщати зображення (альтернативний варіант доступний в будь-який час, утримуючи ctrl/cmd) Scrolling &zooms - + Прокрутка та масштабування Stop the image from going past its actual size when resizing the window - you can still zoom past it though - + Зупиніть вихід зображення за межі його фактичного розміру при зміні розміру вікна - ви все ще можете збільшити його розмір Image resizes &past actual size - + Зображення змінює розміри та вставляє фактичний розмір Ignores select sides of an image when fitting to window (some sides will extend beyond the window boundaries) - + Ігнорує вибрані сторони зображення при підгонці до вікна (деякі сторони будуть виходити за межі вікна) Fit whole image - + Підійде для всього зображення Fit height - + За висотою Fit width - + За шириною On window resize: - + При зміні розміру вікна: Choose whether or not zooming in and out above 100% zoom will zoom towards the cursor - + Виберіть, чи буде збільшення та зменшення масштабу понад 100% збільшуватись у напрямку до курсору Zoom &towards cursor - + Масштабування у напрямку курсору Miscellaneous - + Різне Sort files by: - + Сортування файлів по: Name - + Ім'я Last Modified - + Остання зміна Size - + Розмір Type - + Тип Random - + Випадково A&scending - + За зростанням D&escending - + За спаданням Controls the amount of images preloaded - + Контролює кількість попередньо завантажених зображень Preloading: - + Попереднє завантаження: Disabled - + Вимкнено Adjacent - + Прилеглі Extended - + Розширені Controls whether or not qView should go back to the first item after reaching the end of a folder - + Контролює, чи повинен qView повертатися до першого елемента після досягнення кінця папки &Loop through folders - + Циклічне переключення між папками Slideshow direction: - + Напрямок слайд-шоу: Forward - + Вперед Backward - + Назад Slideshow timer: - + Таймер слайд-шоу: sec - + сек Save &recent files - + Зберегти та відновити файли &Update notifications on startup The notifications are for new qView releases - + Оновлення повідомлень при запуску Language: - + Мова: Move Back - + Повернутися назад Do Nothing - + Нічого не робити Move Forward - + Рухатися вперед After deletion: - + Після видалення: &Ask before deleting files - + Запитайте перед видаленням файлів Shortcuts - + Комбінація клавіш Action - + Дія System Language - + Мова системи Restart Required - + Потрібен перезапуск You must restart qView to change the language. - + Щоб змінити мову, необхідно перезапустити qView. @@ -1127,30 +1131,32 @@ No write permission or file is read-only. Rename... - + Перейменувати... File name: - + Ім'я файлу: Error - + Помилка Could not rename %1: No write permission or file is read-only. - + Не вдалося перейменувати %1: +Немає дозволу на запис або файл доступний тільки для читання. Could not rename %1: (Check that all characters are valid) - + Не вдалося перейменувати %1: +(Перевірте, чи всі символи правильні) @@ -1158,17 +1164,17 @@ No write permission or file is read-only. Modify Shortcuts - + Зміна комбінацій клавіш Shortcut Already Used - + Комбінація клавіш, які вже використовуються "%1" is already bound to "%2" - + "%1" вже прив'язаний до "%2" @@ -1177,22 +1183,22 @@ No write permission or file is read-only. Welcome - + Ласкаво Просимо &Enable update notifications on startup - + Увімкнути сповіщення про оновлення при запуску Thank you for downloading qView.<br>Here's a few tips to get you started: - + Дякуємо, що завантажили qView. <br> Ось декілька порад, які допоможуть вам розпочати роботу: <ul><li>Right click to access the main menu</li><li>Drag the image to reposition it</li><li>Scroll to zoom in and out</li><li>Use arrow keys to switch files</li></ul> - + <ul><li>Клацніть правою кнопкою миші для доступу до головного меню</li><li>Перетягніть зображення, щоб змінити його положення</li><li>Прокрутіть, щоб збільшити або зменшити масштаб</li><li>Використовуйте клавіші зі стрілками для перемикання файлів</li></ul> @@ -1200,202 +1206,202 @@ No write permission or file is read-only. Open - + Відкрити Open URL - + Відкрийте URL-адресу Open Containing Folder - + Відкрити вміст папки Show in Explorer - + Показати в провіднику Show in Finder - + Показати в Пошуку Show File Info - + Показати інформацію про файл Restore from Trash - + Відновити з Корзини Undo Delete - + Скасувати видалення Copy - + Копіювати Paste - + Вставити Rename - + Перейменувати Move to Trash - + Перемістити в Корзину Delete - + Видалити First File - + Перший файл Previous File - + Попередній файл Next File - + Наступний файл Last File - + Останній файл Zoom In - + Збільшити Zoom Out - + Зменшити Reset Zoom - + Скидання масштабу Original Size - + Орієнтовний розмір Rotate Right - + Повернути праворуч Rotate Left - + Повернути ліворуч Mirror - + Віддзеркалити Flip - + Перевернути Full Screen - + На весь екран Save Frame As - + Зберегти кадр як Pause - + Пауза Next Frame - + Наступний кадр Decrease Speed - + Зменшити швидкість Reset Speed - + Скинути швидкість Increase Speed - + Збільшити швидкість Toggle Slideshow - + Перемкнути слайд-шоу Options - + Опції Preferences - + Налаштування New Window - + Нове вікно Close Window - + Закрити вікно Close All - + Закрити все Quit - + Вийти Exit - + Вийти @@ -1403,33 +1409,34 @@ No write permission or file is read-only. Download - + Зааантаження qView Update Available - + Доступне оновлення qView qView %1 is available to download. - + qView %1 доступний для завантаження. &Disable Update Checking - + Вимкнути перевірку оновлень qView Update Checking Disabled - + Перевірку оновлень qView вимкнено Update notifications on startup have been disabled. You can reenable them in the options dialog. - + Сповіщення про оновлення при запуску вимкнено. +Ви можете ввімкнути їх у діалоговому вікні параметрів. diff --git a/i18n/qview_zh_Hant.ts b/i18n/qview_zh_Hant.ts index 48f2bbed..f4ba33b6 100644 --- a/i18n/qview_zh_Hant.ts +++ b/i18n/qview_zh_Hant.ts @@ -628,7 +628,7 @@ No write permission or file is read-only. Frames: - 幅: + 幅數: diff --git a/qView.pro b/qView.pro index 1c9f4d05..0e3223f5 100644 --- a/qView.pro +++ b/qView.pro @@ -1,7 +1,5 @@ -# this file is windows-1251 encoded! - TARGET = qView -VERSION = 5.0 +VERSION = 6.1 QT += core gui network widgets @@ -42,13 +40,13 @@ win32 { # To build without win32: qmake CONFIG+=NO_WIN32 !CONFIG(NO_WIN32) { - LIBS += -lshell32 -luser32 -lole32 -lshlwapi + LIBS += -lshell32 -luser32 -lole32 -lshlwapi -lgdi32 DEFINES += WIN32_LOADED message("Linked to win32 api") } RC_ICONS = "dist/win/qView.ico" - QMAKE_TARGET_COPYRIGHT = "Copyright \\251 2022 jurplel and qView contributors" + QMAKE_TARGET_COPYRIGHT = "Copyright \\251 2023 jurplel and qView contributors" QMAKE_TARGET_DESCRIPTION = "qView" } @@ -64,16 +62,27 @@ macx { } QMAKE_TARGET_BUNDLE_PREFIX = "com.interversehq" - # Special info.plist for qt 5.9 on mac - equals(QT_MAJOR_VERSION, 5):lessThan(QT_MINOR_VERSION, 10) { - QMAKE_INFO_PLIST = "dist/mac/Info_legacy.plist" + QMAKE_INFO_PLIST = "dist/mac/Info.plist" + # Older icon for qt 5 on mac + lessThan(QT_MAJOR_VERSION, 6) { ICON = "dist/mac/qView_legacy.icns" } else { - QMAKE_INFO_PLIST = "dist/mac/Info.plist" ICON = "dist/mac/qView.icns" } } +# Linux specific stuff +linux { + !CONFIG(NO_X11) { + LIBS += -lX11 + DEFINES += X11_LOADED + + equals(QT_MAJOR_VERSION, 5) { + QT += x11extras + } + } +} + # Stuff for make install # To use a custom prefix: qmake PREFIX=/usr # An environment variable will also work: PREFIX=/usr qmake diff --git a/src/actionmanager.cpp b/src/actionmanager.cpp index 08cfee5a..0f9ca93e 100644 --- a/src/actionmanager.cpp +++ b/src/actionmanager.cpp @@ -178,6 +178,7 @@ QMenuBar *ActionManager::buildMenuBar(QWidget *parent) addCloneOfAction(fileMenu, "open"); addCloneOfAction(fileMenu, "openurl"); fileMenu->addMenu(buildRecentsMenu(true, fileMenu)); + addCloneOfAction(fileMenu, "reloadfile"); fileMenu->addSeparator(); #ifdef Q_OS_MACOS fileMenu->addSeparator(); @@ -588,6 +589,8 @@ void ActionManager::actionTriggered(QAction *triggeredAction, MainWindow *releva relevantWindow->openWith(openWithItem); } else if (key == "openurl") { relevantWindow->pickUrl(); + } else if (key == "reloadfile") { + relevantWindow->reloadFile(); } else if (key == "opencontainingfolder") { relevantWindow->openContainingFolder(); } else if (key == "showfileinfo") { @@ -667,6 +670,10 @@ void ActionManager::initializeActionLibrary() auto *openUrlAction = new QAction(QIcon::fromTheme("document-open-remote", QIcon::fromTheme("folder-remote")), tr("Open &URL...")); actionLibrary.insert("openurl", openUrlAction); + auto *reloadFileAction = new QAction(QIcon::fromTheme("view-refresh"), tr("Re&load File")); + reloadFileAction->setData({"disable"}); + actionLibrary.insert("reloadfile", reloadFileAction); + auto *closeWindowAction = new QAction(QIcon::fromTheme("window-close"), tr("Close Window")); actionLibrary.insert("closewindow", closeWindowAction); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index dd63e080..2bfd14e3 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -44,7 +44,7 @@ MainWindow::MainWindow(QWidget *parent) : justLaunchedWithImage = false; storedWindowState = Qt::WindowNoState; - // Initialize graphicsview + // Initialize graphicsviewkDefaultBufferAlignment graphicsView = new QVGraphicsView(this); centralWidget()->layout()->addWidget(graphicsView); @@ -323,7 +323,8 @@ void MainWindow::fileChanged() populateOpenWithTimer->start(); disableActions(); - refreshProperties(); + if (info->isVisible()) + refreshProperties(); buildWindowTitle(); setWindowSize(); } @@ -453,7 +454,7 @@ void MainWindow::buildWindowTitle() } case 2: { - newString = QString::number(graphicsView->getCurrentScale() * 100.0, 'f', 1) + "%"; + newString = QString::number(graphicsView->getZoomLevel() * 100.0, 'f', 1) + "%"; newString += " - " + QString::number(getCurrentFileDetails().loadedIndexInFolder+1); newString += "/" + QString::number(getCurrentFileDetails().folderFileInfoList.count()); newString += " - " + getCurrentFileDetails().fileInfo.fileName(); @@ -461,7 +462,7 @@ void MainWindow::buildWindowTitle() } case 3: { - newString = QString::number(graphicsView->getCurrentScale() * 100.0, 'f', 1) + "%"; + newString = QString::number(graphicsView->getZoomLevel() * 100.0, 'f', 1) + "%"; newString += " - " + QString::number(getCurrentFileDetails().loadedIndexInFolder+1); newString += "/" + QString::number(getCurrentFileDetails().folderFileInfoList.count()); newString += " - " + getCurrentFileDetails().fileInfo.fileName(); @@ -508,13 +509,8 @@ void MainWindow::setWindowSize() qreal minWindowResizedPercentage = qvApp->getSettingsManager().getInteger("minwindowresizedpercentage")/100.0; qreal maxWindowResizedPercentage = qvApp->getSettingsManager().getInteger("maxwindowresizedpercentage")/100.0; - - QSize imageSize = graphicsView->getEffectiveOriginalSize().toSize(); - imageSize -= QSize(4, 4); - - // Try to grab the current screen - QScreen *currentScreen = screenAt(geometry().center()); + QScreen *currentScreen = screenContaining(frameGeometry()); // makeshift validity check bool screenValid = QGuiApplication::screens().contains(currentScreen); @@ -522,56 +518,64 @@ void MainWindow::setWindowSize() if (!screenValid) currentScreen = QGuiApplication::screens().at(0); + QSize extraWidgetsSize { 0, 0 }; + + if (menuBar()->isVisible()) + extraWidgetsSize.rheight() += menuBar()->height(); + + int titlebarOverlap = 0; +#ifdef COCOA_LOADED + // To account for fullsizecontentview on mac + titlebarOverlap = QVCocoaFunctions::getObscuredHeight(window()->windowHandle()); +#endif + if (titlebarOverlap != 0) + extraWidgetsSize.rheight() += titlebarOverlap; + + const QSize windowFrameSize = frameGeometry().size() - geometry().size(); + const QSize hardLimitSize = currentScreen->availableSize() - windowFrameSize - extraWidgetsSize; const QSize screenSize = currentScreen->size(); + const QSize minWindowSize = (screenSize * minWindowResizedPercentage).boundedTo(hardLimitSize); + const QSize maxWindowSize = (screenSize * maxWindowResizedPercentage).boundedTo(hardLimitSize); + const QSizeF imageSize = graphicsView->getEffectiveOriginalSize(); + const int fitOverscan = graphicsView->getFitOverscan(); + const QSize fitOverscanSize = QSize(fitOverscan * 2, fitOverscan * 2); - const QSize minWindowSize = screenSize * minWindowResizedPercentage; - const QSize maxWindowSize = screenSize * maxWindowResizedPercentage; + QSize targetSize = imageSize.toSize() - fitOverscanSize; - if (imageSize.width() < minWindowSize.width() && imageSize.height() < minWindowSize.height()) - { - imageSize.scale(minWindowSize, Qt::KeepAspectRatio); - } - else if (imageSize.width() > maxWindowSize.width() || imageSize.height() > maxWindowSize.height()) + if (targetSize.width() > maxWindowSize.width() || targetSize.height() > maxWindowSize.height()) { - imageSize.scale(maxWindowSize, Qt::KeepAspectRatio); + const QSizeF viewSize = maxWindowSize + fitOverscanSize; + const qreal fitRatio = qMin(viewSize.width() / imageSize.width(), viewSize.height() / imageSize.height()); + targetSize = (imageSize * fitRatio).toSize() - fitOverscanSize; } - // Windows reports the wrong minimum width, so we constrain the image size relative to the dpi to stop weirdness with tiny images -#ifdef Q_OS_WIN - auto minimumImageSize = QSize(qRound(logicalDpiX()*1.5), logicalDpiY()/2); - if (imageSize.boundedTo(minimumImageSize) == imageSize) - imageSize = minimumImageSize; -#endif - - // Adjust image size for fullsizecontentview on mac -#ifdef COCOA_LOADED - int obscuredHeight = QVCocoaFunctions::getObscuredHeight(window()->windowHandle()); - imageSize.setHeight(imageSize.height() + obscuredHeight); -#endif - - if (menuBar()->isVisible()) - imageSize.setHeight(imageSize.height() + menuBar()->height()); + targetSize = targetSize.expandedTo(minWindowSize).boundedTo(maxWindowSize); // Match center after new geometry // This is smoother than a single geometry set for some reason QRect oldRect = geometry(); - resize(imageSize); + resize(targetSize + extraWidgetsSize); QRect newRect = geometry(); newRect.moveCenter(oldRect.center()); - // Ensure titlebar is not above the top of the screen - const int titlebarHeight = QApplication::style()->pixelMetric(QStyle::PM_TitleBarHeight); - const int topOfScreen = currentScreen->availableGeometry().y(); - - if (newRect.y() < (topOfScreen + titlebarHeight)) - newRect.setY(topOfScreen + titlebarHeight); + // Ensure titlebar is not above or below the available screen area + const QRect availableScreenRect = currentScreen->availableGeometry(); + const int topFrameHeight = geometry().top() - frameGeometry().top(); + const int windowMinY = availableScreenRect.top() + topFrameHeight; + const int windowMaxY = availableScreenRect.top() + availableScreenRect.height() - titlebarOverlap; + if (newRect.top() < windowMinY) + newRect.moveTop(windowMinY); + if (newRect.top() > windowMaxY) + newRect.moveTop(windowMaxY); setGeometry(newRect); } -// literally just copy pasted from Qt source code to maintain compatibility with 5.9 (although i've edited it now) -QScreen *MainWindow::screenAt(const QPoint &point) +// Initially copied from Qt source code (QGuiApplication::screenAt) and then customized +QScreen *MainWindow::screenContaining(const QRect &rect) { + QScreen *bestScreen = nullptr; + int bestScreenArea = 0; QVarLengthArray visitedScreens; const auto screens = QGuiApplication::screens(); for (const QScreen *screen : screens) { @@ -580,12 +584,16 @@ QScreen *MainWindow::screenAt(const QPoint &point) // The virtual siblings include the screen itself, so iterate directly const auto siblings = screen->virtualSiblings(); for (QScreen *sibling : siblings) { - if (sibling->geometry().contains(point)) - return sibling; + const QRect intersect = sibling->geometry().intersected(rect); + const int area = intersect.width() * intersect.height(); + if (area > bestScreenArea) { + bestScreen = sibling; + bestScreenArea = area; + } visitedScreens.append(sibling); } } - return nullptr; + return bestScreen; } bool MainWindow::getIsPixmapLoaded() const @@ -682,6 +690,11 @@ void MainWindow::pickUrl() inputDialog->open(); } +void MainWindow::reloadFile() +{ + graphicsView->reloadFile(); +} + void MainWindow::openWith(const OpenWith::OpenWithItem &openWithItem) { OpenWith::openWith(getCurrentFileDetails().fileInfo.absoluteFilePath(), openWithItem); @@ -1109,7 +1122,6 @@ void MainWindow::toggleFullScreen() if (windowState() == Qt::WindowFullScreen) { setWindowState(storedWindowState); - setWindowSize(); } else { diff --git a/src/mainwindow.h b/src/mainwindow.h index 9f5bdc5a..371c4c29 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -43,7 +43,7 @@ class MainWindow : public QMainWindow void setJustLaunchedWithImage(bool value); - QScreen *screenAt(const QPoint &point); + QScreen *screenContaining(const QRect &rect); void openRecent(int i); @@ -51,6 +51,8 @@ class MainWindow : public QMainWindow void pickUrl(); + void reloadFile(); + void openContainingFolder(); void openWith(const OpenWith::OpenWithItem &exec); diff --git a/src/qvaboutdialog.cpp b/src/qvaboutdialog.cpp index f8ebbb9a..cca75682 100644 --- a/src/qvaboutdialog.cpp +++ b/src/qvaboutdialog.cpp @@ -63,7 +63,7 @@ QVAboutDialog::QVAboutDialog(double givenLatestVersionNum, QWidget *parent) : R"(Source code available under GPLv3 on GitHub
)" "Icon glyph created by Guilhem from the Noun Project
" "Copyright © %3 jurplel and qView contributors") - .arg(QT_VERSION_STR, QSysInfo::buildCpuArchitecture(), "2018-2022"); + .arg(QT_VERSION_STR, QSysInfo::buildCpuArchitecture(), "2018-2023"); ui->infoLabel2->setFont(font4); ui->infoLabel2->setText(labelText2); diff --git a/src/qvapplication.cpp b/src/qvapplication.cpp index f4f589c4..e4369e29 100644 --- a/src/qvapplication.cpp +++ b/src/qvapplication.cpp @@ -222,38 +222,6 @@ void QVApplication::recentsMenuUpdated() #endif } -qint64 QVApplication::getPreviouslyRecordedFileSize(const QString &fileName) -{ - auto previouslyRecordedFileSizePtr = previouslyRecordedFileSizes.object(fileName); - qint64 previouslyRecordedFileSize = 0; - - if (previouslyRecordedFileSizePtr) - previouslyRecordedFileSize = *previouslyRecordedFileSizePtr; - - return previouslyRecordedFileSize; -} - -void QVApplication::setPreviouslyRecordedFileSize(const QString &fileName, long long *fileSize) -{ - previouslyRecordedFileSizes.insert(fileName, fileSize); -} - -QSize QVApplication::getPreviouslyRecordedImageSize(const QString &fileName) -{ - auto previouslyRecordedImageSizePtr = previouslyRecordedImageSizes.object(fileName); - QSize previouslyRecordedImageSize = QSize(); - - if (previouslyRecordedImageSizePtr) - previouslyRecordedImageSize = *previouslyRecordedImageSizePtr; - - return previouslyRecordedImageSize; -} - -void QVApplication::setPreviouslyRecordedImageSize(const QString &fileName, QSize *imageSize) -{ - previouslyRecordedImageSizes.insert(fileName, imageSize); -} - void QVApplication::addToLastActiveWindows(MainWindow *window) { if (!window) @@ -386,14 +354,13 @@ void QVApplication::defineFilterLists() if (fileExtension == ".jpg") { filterList << "*.jpe" << "*.jfi" << "*.jfif"; - filterString += "*.jpe *.jfi *.jfif"; + filterString += "*.jpe *.jfi *.jfif "; fileExtensionList << ".jpe" << ".jfi" << ".jfif"; } } filterString.chop(1); filterString += ")"; - // Build mime type list const auto &byteArrayMimeTypes = QImageReader::supportedMimeTypes(); mimeTypeNameList.reserve(byteArrayMimeTypes.size()-1); diff --git a/src/qvapplication.h b/src/qvapplication.h index 499938ca..0ec37d5b 100644 --- a/src/qvapplication.h +++ b/src/qvapplication.h @@ -47,14 +47,6 @@ class QVApplication : public QApplication void recentsMenuUpdated(); - qint64 getPreviouslyRecordedFileSize(const QString &fileName); - - void setPreviouslyRecordedFileSize(const QString &fileName, long long *fileSize); - - QSize getPreviouslyRecordedImageSize(const QString &fileName); - - void setPreviouslyRecordedImageSize(const QString &fileName, QSize *imageSize); - void addToLastActiveWindows(MainWindow *window); void deleteFromLastActiveWindows(MainWindow *window); @@ -93,9 +85,6 @@ class QVApplication : public QApplication QMenuBar *menuBar; - QCache previouslyRecordedFileSizes; - QCache previouslyRecordedImageSizes; - QStringList filterList; QStringList nameFilterList; QStringList fileExtensionList; diff --git a/src/qvcocoafunctions.h b/src/qvcocoafunctions.h index 0583bedf..9b27c79f 100644 --- a/src/qvcocoafunctions.h +++ b/src/qvcocoafunctions.h @@ -30,6 +30,8 @@ class QVCocoaFunctions static QList getOpenWithItems(const QString &filePath); static QString deleteFile(const QString &filePath); + + static QByteArray getIccProfileForWindow(const QWindow *window); }; #endif // QVCOCOAFUNCTIONS_H diff --git a/src/qvcocoafunctions.mm b/src/qvcocoafunctions.mm index 81150477..7807c63b 100644 --- a/src/qvcocoafunctions.mm +++ b/src/qvcocoafunctions.mm @@ -219,3 +219,18 @@ static void fixNativeMenuEccentricities(QMenu *menu, NSMenu *nativeMenu) return QString::fromNSString(resultUrl.absoluteString); } + +QByteArray QVCocoaFunctions::getIccProfileForWindow(const QWindow *window) +{ + NSView *view = reinterpret_cast(window->winId()); + NSColorSpace *nsColorSpace = view.window.colorSpace; + if (nsColorSpace) + { + NSData *iccProfileData = nsColorSpace.ICCProfileData; + if (iccProfileData) + { + return QByteArray::fromNSData(iccProfileData); + } + } + return {}; +} diff --git a/src/qvgraphicsview.cpp b/src/qvgraphicsview.cpp index ca34da50..53262a9e 100644 --- a/src/qvgraphicsview.cpp +++ b/src/qvgraphicsview.cpp @@ -39,23 +39,25 @@ QVGraphicsView::QVGraphicsView(QWidget *parent) : QGraphicsView(parent) isConstrainedPositioningEnabled = false; isConstrainedSmallCenteringEnabled = true; cropMode = 0; - scaleFactor = 1.25; + zoomMultiplier = 1.25; // Initialize other variables + fitOverscan = 0; resizeResetsZoom = true; navResetsZoom = true; - currentScale = 1.0; - appliedScaleAdjustment = 1.0; + zoomLevel = 1.0; + appliedDpiAdjustment = 1.0; + appliedExpensiveScaleZoomLevel = 0.0; lastZoomEventPos = QPoint(-1, -1); lastZoomRoundingError = QPointF(); scrollHelper = new ScrollHelper(this, [this](ScrollHelper::Parameters &p) { - p.ContentRect = getContentRect().toRect(); - p.UsableViewportRect = getUsableViewportRect(); - p.ShouldConstrain = isConstrainedPositioningEnabled; - p.ShouldCenter = isConstrainedSmallCenteringEnabled; + p.contentRect = getContentRect().toRect(); + p.usableViewportRect = getUsableViewportRect(); + p.shouldConstrain = isConstrainedPositioningEnabled; + p.shouldCenter = isConstrainedSmallCenteringEnabled; }); connect(&imageCore, &QVImageCore::animatedFrameChanged, this, &QVGraphicsView::animatedFrameChanged); @@ -65,7 +67,7 @@ QVGraphicsView::QVGraphicsView(QWidget *parent) : QGraphicsView(parent) expensiveScaleTimer = new QTimer(this); expensiveScaleTimer->setSingleShot(true); expensiveScaleTimer->setInterval(50); - connect(expensiveScaleTimer, &QTimer::timeout, this, [this]{scaleExpensively();}); + connect(expensiveScaleTimer, &QTimer::timeout, this, [this]{applyExpensiveScaling();}); constrainBoundsTimer = new QTimer(this); constrainBoundsTimer->setSingleShot(true); @@ -102,7 +104,7 @@ void QVGraphicsView::paintEvent(QPaintEvent *event) { // This is the most reliable place to detect DPI changes. QWindow::screenChanged() // doesn't detect when the DPI is changed on the current monitor, for example. - handleScaleAdjustmentChange(); + handleDpiAdjustmentChange(); QGraphicsView::paintEvent(event); } @@ -186,7 +188,7 @@ bool QVGraphicsView::event(QEvent *event) if (changeFlags & QPinchGesture::ScaleFactorChanged) { const QPoint hotPoint = mapFromGlobal(pinchGesture->hotSpot().toPoint()); - zoom(pinchGesture->scaleFactor(), hotPoint); + zoomRelative(pinchGesture->scaleFactor(), hotPoint); } // Fun rotation stuff maybe later @@ -232,17 +234,39 @@ void QVGraphicsView::wheelEvent(QWheelEvent *event) const int yDelta = event->angleDelta().y(); const qreal yScale = 120.0; - if (yDelta == 0) + if (yDelta == 0 || !getCurrentFileDetails().isPixmapLoaded) return; const qreal fractionalWheelClicks = qFabs(yDelta) / yScale; - const qreal zoomAmountPerWheelClick = scaleFactor - 1.0; + const qreal zoomAmountPerWheelClick = zoomMultiplier - 1.0; qreal zoomFactor = 1.0 + (fractionalWheelClicks * zoomAmountPerWheelClick); if (yDelta < 0) zoomFactor = qPow(zoomFactor, -1); - zoom(zoomFactor, eventPos); + zoomRelative(zoomFactor, eventPos); +} + +void QVGraphicsView::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down || event->key() == Qt::Key_Left || event->key() == Qt::Key_Right) + { + // Normally the arrow keys are assigned to shortcuts, but in case they aren't or + // get passed through due to modifier keys, handle it here instead of letting the + // base class do it to ensure any bounds constraints are enforced. + const int stepDown = verticalScrollBar()->singleStep(); + const int stepRight = horizontalScrollBar()->singleStep() * (isRightToLeft() ? -1 : 1); + QPoint delta {}; + if (event->key() == Qt::Key_Up) delta.ry() -= stepDown; + if (event->key() == Qt::Key_Down) delta.ry() += stepDown; + if (event->key() == Qt::Key_Left) delta.rx() -= stepRight; + if (event->key() == Qt::Key_Right) delta.rx() += stepRight; + scrollHelper->move(delta); + constrainBoundsTimer->start(); + return; + } + + QGraphicsView::keyPressEvent(event); } // Functions @@ -287,12 +311,20 @@ void QVGraphicsView::loadFile(const QString &fileName) imageCore.loadFile(fileName); } +void QVGraphicsView::reloadFile() +{ + if (!getCurrentFileDetails().isPixmapLoaded) + return; + + imageCore.loadFile(getCurrentFileDetails().fileInfo.absoluteFilePath(), true); +} + void QVGraphicsView::postLoad() { scrollHelper->cancelAnimation(); // Set the pixmap to the new image and reset the transform's scale to a known value - makeUnscaled(); + removeExpensiveScaling(); if (navResetsZoom) zoomToFit(); @@ -308,24 +340,26 @@ void QVGraphicsView::postLoad() void QVGraphicsView::zoomIn(const QPoint &pos) { - zoom(scaleFactor, pos); + zoomRelative(zoomMultiplier, pos); } void QVGraphicsView::zoomOut(const QPoint &pos) { - zoom(qPow(scaleFactor, -1), pos); + zoomRelative(qPow(zoomMultiplier, -1), pos); } -void QVGraphicsView::zoom(qreal scaleFactor, const QPoint &pos) +void QVGraphicsView::zoomRelative(qreal relativeLevel, const QPoint &pos) { - //don't zoom too far out, dude - currentScale *= scaleFactor; - if (currentScale >= 500 || currentScale <= 0.01) - { - currentScale *= qPow(scaleFactor, -1); + const qreal absoluteLevel = zoomLevel * relativeLevel; + + if (absoluteLevel >= 500 || absoluteLevel <= 0.01) return; - } + zoomAbsolute(absoluteLevel, pos); +} + +void QVGraphicsView::zoomAbsolute(const qreal absoluteLevel, const QPoint &pos) +{ if (pos != lastZoomEventPos) { lastZoomEventPos = pos; @@ -333,7 +367,18 @@ void QVGraphicsView::zoom(qreal scaleFactor, const QPoint &pos) } const QPointF scenePos = mapToScene(pos) - lastZoomRoundingError; - scale(scaleFactor, scaleFactor); + if (appliedExpensiveScaleZoomLevel != 0.0) + { + const qreal baseTransformScale = 1.0 / devicePixelRatioF(); + const qreal relativeLevel = absoluteLevel / appliedExpensiveScaleZoomLevel; + setTransformScale(baseTransformScale * relativeLevel); + } + else + { + setTransformScale(absoluteLevel * appliedDpiAdjustment); + } + zoomLevel = absoluteLevel; + scrollHelper->cancelAnimation(); // If we have a point to zoom towards and cursor zooming is enabled/applicable @@ -355,11 +400,6 @@ void QVGraphicsView::zoom(qreal scaleFactor, const QPoint &pos) emitZoomLevelChangedTimer->start(); } -void QVGraphicsView::setZoomLevel(qreal absoluteScaleFactor) -{ - zoom(absoluteScaleFactor / currentScale); -} - bool QVGraphicsView::getResizeResetsZoom() const { return resizeResetsZoom; @@ -390,7 +430,7 @@ void QVGraphicsView::setNavResetsZoom(bool value) emit navResetsZoomChanged(); } -void QVGraphicsView::scaleExpensively() +void QVGraphicsView::applyExpensiveScaling() { if (!isScalingEnabled || !getCurrentFileDetails().isPixmapLoaded) return; @@ -399,36 +439,38 @@ void QVGraphicsView::scaleExpensively() if (getContentToViewportRatio() > (isScalingTwoEnabled ? 3.0 : 1.00001)) { // Return to original size - makeUnscaled(); + removeExpensiveScaling(); return; } // Calculate scaled resolution - qreal scaleAdjustment = getScaleAdjustment(); - const QSizeF mappedSize = QSizeF(getCurrentFileDetails().loadedPixmapSize) * currentScale * scaleAdjustment * devicePixelRatioF(); + const qreal dpiAdjustment = getDpiAdjustment(); + const QSizeF mappedSize = QSizeF(getCurrentFileDetails().loadedPixmapSize) * zoomLevel * dpiAdjustment * devicePixelRatioF(); // Set image to scaled version loadedPixmapItem->setPixmap(imageCore.scaleExpensively(mappedSize)); // Set appropriate scale factor - qreal targetScale = 1.0 / devicePixelRatioF(); - setTransform(getTransformWithNoScaling().scale(targetScale, targetScale)); - appliedScaleAdjustment = scaleAdjustment; + const qreal newTransformScale = 1.0 / devicePixelRatioF(); + setTransformScale(newTransformScale); + appliedDpiAdjustment = dpiAdjustment; + appliedExpensiveScaleZoomLevel = zoomLevel; } -void QVGraphicsView::makeUnscaled() +void QVGraphicsView::removeExpensiveScaling() { // Return to original size if (getCurrentFileDetails().isMovieLoaded) loadedPixmapItem->setPixmap(getLoadedMovie().currentPixmap()); - else if (getCurrentFileDetails().isPixmapLoaded) + else loadedPixmapItem->setPixmap(getLoadedPixmap()); // Set appropriate scale factor - qreal scaleAdjustment = getScaleAdjustment(); - qreal targetScale = currentScale * scaleAdjustment; - setTransform(getTransformWithNoScaling().scale(targetScale, targetScale)); - appliedScaleAdjustment = scaleAdjustment; + const qreal dpiAdjustment = getDpiAdjustment(); + const qreal newTransformScale = zoomLevel * dpiAdjustment; + setTransformScale(newTransformScale); + appliedDpiAdjustment = dpiAdjustment; + appliedExpensiveScaleZoomLevel = 0.0; } void QVGraphicsView::animatedFrameChanged(QRect rect) @@ -437,7 +479,7 @@ void QVGraphicsView::animatedFrameChanged(QRect rect) if (isScalingEnabled) { - scaleExpensively(); + applyExpensiveScaling(); } else { @@ -451,7 +493,7 @@ void QVGraphicsView::zoomToFit() return; QSizeF effectiveImageSize = getEffectiveOriginalSize(); - QSizeF viewSize = getUsableViewportRect(true).size(); + QSize viewSize = getUsableViewportRect(true).size(); if (viewSize.isEmpty()) return; @@ -461,32 +503,70 @@ void QVGraphicsView::zoomToFit() qreal targetRatio; + // Each mode will check if the rounded image size already produces the desired fit, + // in which case we can use exactly 1.0 to avoid unnecessary scaling + switch (cropMode) { // should be enum tbh case 1: // only take into account height - targetRatio = fitYRatio; + if (qRound(effectiveImageSize.height()) == viewSize.height()) + targetRatio = 1.0; + else + targetRatio = fitYRatio; break; case 2: // only take into account width - targetRatio = fitXRatio; + if (qRound(effectiveImageSize.width()) == viewSize.width()) + targetRatio = 1.0; + else + targetRatio = fitXRatio; break; default: - targetRatio = qMin(fitXRatio, fitYRatio); + if ((qRound(effectiveImageSize.height()) == viewSize.height() && qRound(effectiveImageSize.width()) <= viewSize.width()) || + (qRound(effectiveImageSize.width()) == viewSize.width() && qRound(effectiveImageSize.height()) <= viewSize.height())) + { + targetRatio = 1.0; + } + else + { + QSize xRatioSize = (effectiveImageSize * fitXRatio * devicePixelRatioF()).toSize(); + QSize yRatioSize = (effectiveImageSize * fitYRatio * devicePixelRatioF()).toSize(); + QSize maxSize = (QSizeF(viewSize) * devicePixelRatioF()).toSize(); + // If the fit ratios are extremely close, it's possible that both are sufficient to + // contain the image, but one results in the opposing dimension getting rounded down + // to just under the view size, so use the larger of the two ratios in that case. + if (xRatioSize.boundedTo(maxSize) == xRatioSize && yRatioSize.boundedTo(maxSize) == yRatioSize) + targetRatio = qMax(fitXRatio, fitYRatio); + else + targetRatio = qMin(fitXRatio, fitYRatio); + } break; } if (targetRatio > 1.0 && !isPastActualSizeEnabled) targetRatio = 1.0; - setZoomLevel(targetRatio); + zoomAbsolute(targetRatio); } void QVGraphicsView::originalSize() { - setZoomLevel(1.0); + zoomAbsolute(1.0); } void QVGraphicsView::centerImage() { - centerOn(loadedPixmapItem); + const QRect viewRect = getUsableViewportRect(); + const QRect contentRect = getContentRect().toRect(); + const int hOffset = isRightToLeft() ? + horizontalScrollBar()->minimum() + horizontalScrollBar()->maximum() - contentRect.left() : + contentRect.left(); + const int vOffset = contentRect.top() - viewRect.top(); + const int hOverflow = contentRect.width() - viewRect.width(); + const int vOverflow = contentRect.height() - viewRect.height(); + + horizontalScrollBar()->setValue(hOffset + (hOverflow / (isRightToLeft() ? -2 : 2))); + verticalScrollBar()->setValue(vOffset + (vOverflow / 2)); + + scrollHelper->cancelAnimation(); } void QVGraphicsView::goToFile(const GoToFileMode &mode, int index) @@ -585,42 +665,9 @@ void QVGraphicsView::goToFile(const GoToFileMode &mode, int index) loadFile(nextImageFilePath); } -void QVGraphicsView::centerOn(const QPointF &pos) -{ - QRect targetRect = getUsableViewportRect(); - QPointF viewPoint = transform().map(pos); - - if (isRightToLeft()) - { - qint64 horizontal = 0; - horizontal += horizontalScrollBar()->minimum(); - horizontal += horizontalScrollBar()->maximum(); - horizontal -= int(viewPoint.x() - (targetRect.width() / 2.0)); - horizontalScrollBar()->setValue(horizontal); - } - else - { - horizontalScrollBar()->setValue(int(viewPoint.x() - (targetRect.width() / 2.0))); - } - - verticalScrollBar()->setValue(int(viewPoint.y() - targetRect.top() - (targetRect.height() / 2.0))); - - scrollHelper->cancelAnimation(); -} - -void QVGraphicsView::centerOn(qreal x, qreal y) -{ - centerOn(QPointF(x, y)); -} - -void QVGraphicsView::centerOn(const QGraphicsItem *item) -{ - centerOn(item->sceneBoundingRect().center()); -} - QSizeF QVGraphicsView::getEffectiveOriginalSize() const { - return getTransformWithNoScaling().mapRect(QRectF(QPoint(), getCurrentFileDetails().loadedPixmapSize)).size() * getScaleAdjustment(); + return getTransformWithNoScaling().mapRect(QRectF(QPoint(), getCurrentFileDetails().loadedPixmapSize)).size() * getDpiAdjustment(); } QRectF QVGraphicsView::getContentRect() const @@ -628,7 +675,7 @@ QRectF QVGraphicsView::getContentRect() const return transform().mapRect(loadedPixmapItem->boundingRect()); } -QRect QVGraphicsView::getUsableViewportRect(bool addMargin) const +QRect QVGraphicsView::getUsableViewportRect(bool addOverscan) const { #ifdef COCOA_LOADED int obscuredHeight = QVCocoaFunctions::getObscuredHeight(window()->windowHandle()); @@ -637,8 +684,8 @@ QRect QVGraphicsView::getUsableViewportRect(bool addMargin) const #endif QRect rect = viewport()->rect(); rect.setTop(obscuredHeight); - if (addMargin) - rect.adjust(MARGIN, MARGIN, -MARGIN, -MARGIN); + if (addOverscan) + rect.adjust(-fitOverscan, -fitOverscan, fitOverscan, fitOverscan); return rect; } @@ -649,23 +696,41 @@ qreal QVGraphicsView::getContentToViewportRatio() const return qMax(contentSize.width() / viewportSize.width(), contentSize.height() / viewportSize.height()); } +void QVGraphicsView::setTransformScale(qreal value) +{ +#ifdef Q_OS_WIN + // On Windows, the positioning of scaled pixels seems to follow a floor rule rather + // than rounding, so increase the scale just a hair to cover rounding errors in case + // the desired scale was targeting an integer pixel boundary. + value *= 1.0 + std::numeric_limits::epsilon(); +#endif + setTransform(getTransformWithNoScaling().scale(value, value)); +} + QTransform QVGraphicsView::getTransformWithNoScaling() const { - QRectF unityRect = transform().mapRect(QRectF(0, 0, 1, 1)); - return transform().scale(1.0 / unityRect.width(), 1.0 / unityRect.height()); + const QTransform t = transform(); + // Only intended to handle combinations of scaling, mirroring, flipping, and rotation + // in increments of 90 degrees. A seemingly simpler approach would be to scale the + // transform by the inverse of its scale factor, but the resulting scale factor may + // not exactly equal 1 due to floating point rounding errors. + if (t.type() == QTransform::TxRotate) + return { 0, t.m12() < 0 ? -1.0 : 1.0, t.m21() < 0 ? -1.0 : 1.0, 0, 0, 0 }; + else + return { t.m11() < 0 ? -1.0 : 1.0, 0, 0, t.m22() < 0 ? -1.0 : 1.0, 0, 0 }; } -qreal QVGraphicsView::getScaleAdjustment() const +qreal QVGraphicsView::getDpiAdjustment() const { return isOneToOnePixelSizingEnabled ? 1.0 / devicePixelRatioF() : 1.0; } -void QVGraphicsView::handleScaleAdjustmentChange() +void QVGraphicsView::handleDpiAdjustmentChange() { - if (appliedScaleAdjustment == getScaleAdjustment()) + if (appliedDpiAdjustment == getDpiAdjustment()) return; - makeUnscaled(); + removeExpensiveScaling(); if (resizeResetsZoom) zoomToFit(); @@ -715,7 +780,7 @@ void QVGraphicsView::settingsUpdated() if (isScalingEnabled) expensiveScaleTimer->start(); else - makeUnscaled(); + removeExpensiveScaling(); //scaling2 if (!isScalingEnabled) @@ -727,7 +792,7 @@ void QVGraphicsView::settingsUpdated() cropMode = settingsManager.getInteger("cropmode"); //scalefactor - scaleFactor = settingsManager.getInteger("scalefactor")*0.01+1; + zoomMultiplier = 1.0 + (settingsManager.getInteger("scalefactor") / 100.0); //resize past actual size isPastActualSizeEnabled = settingsManager.getBoolean("pastactualsizeenabled"); @@ -752,7 +817,7 @@ void QVGraphicsView::settingsUpdated() // End of settings variables - handleScaleAdjustmentChange(); + handleDpiAdjustmentChange(); if (resizeResetsZoom) zoomToFit(); diff --git a/src/qvgraphicsview.h b/src/qvgraphicsview.h index ee9a24ac..cf69fced 100644 --- a/src/qvgraphicsview.h +++ b/src/qvgraphicsview.h @@ -32,13 +32,15 @@ class QVGraphicsView : public QGraphicsView void loadMimeData(const QMimeData *mimeData); void loadFile(const QString &fileName); + void reloadFile(); + void zoomIn(const QPoint &pos = QPoint(-1, -1)); void zoomOut(const QPoint &pos = QPoint(-1, -1)); - void zoom(qreal scaleFactor, const QPoint &pos = QPoint(-1, -1)); + void zoomRelative(const qreal relativeLevel, const QPoint &pos = QPoint(-1, -1)); - void setZoomLevel(qreal absoluteScaleFactor); + void zoomAbsolute(const qreal absoluteLevel, const QPoint &pos = QPoint(-1, -1)); bool getResizeResetsZoom() const; void setResizeResetsZoom(bool value); @@ -46,8 +48,8 @@ class QVGraphicsView : public QGraphicsView bool getNavResetsZoom() const; void setNavResetsZoom(bool value); - void scaleExpensively(); - void makeUnscaled(); + void applyExpensiveScaling(); + void removeExpensiveScaling(); void zoomToFit(); void originalSize(); @@ -69,7 +71,9 @@ class QVGraphicsView : public QGraphicsView const QVImageCore::FileDetails& getCurrentFileDetails() const { return imageCore.getCurrentFileDetails(); } const QPixmap& getLoadedPixmap() const { return imageCore.getLoadedPixmap(); } const QMovie& getLoadedMovie() const { return imageCore.getLoadedMovie(); } - qreal getCurrentScale() const { return currentScale; } + qreal getZoomLevel() const { return zoomLevel; } + + int getFitOverscan() const { return fitOverscan; } signals: void cancelSlideshow(); @@ -103,25 +107,23 @@ class QVGraphicsView : public QGraphicsView void mouseMoveEvent(QMouseEvent *event) override; - bool event(QEvent *event) override; - - void centerOn(const QPointF &pos); + void keyPressEvent(QKeyEvent *event) override; - void centerOn(qreal x, qreal y); - - void centerOn(const QGraphicsItem *item); + bool event(QEvent *event) override; QRectF getContentRect() const; - QRect getUsableViewportRect(bool addMargin = false) const; + QRect getUsableViewportRect(bool addOverscan = false) const; qreal getContentToViewportRatio() const; + void setTransformScale(qreal absoluteScale); + QTransform getTransformWithNoScaling() const; - qreal getScaleAdjustment() const; + qreal getDpiAdjustment() const; - void handleScaleAdjustmentChange(); + void handleDpiAdjustmentChange(); private slots: void animatedFrameChanged(QRect rect); @@ -139,6 +141,7 @@ private slots: bool isScalingEnabled; bool isScalingTwoEnabled; bool isPastActualSizeEnabled; + int fitOverscan; bool isScrollZoomsEnabled; bool isLoopFoldersEnabled; bool isCursorZoomEnabled; @@ -146,18 +149,17 @@ private slots: bool isConstrainedPositioningEnabled; bool isConstrainedSmallCenteringEnabled; int cropMode; - qreal scaleFactor; - - const int MARGIN = -2; + qreal zoomMultiplier; bool resizeResetsZoom; bool navResetsZoom; - qreal currentScale; - qreal appliedScaleAdjustment; + qreal zoomLevel; + qreal appliedDpiAdjustment; + qreal appliedExpensiveScaleZoomLevel; QPoint lastZoomEventPos; QPointF lastZoomRoundingError; - QVImageCore imageCore; + QVImageCore imageCore { this }; QTimer *expensiveScaleTimer; QTimer *constrainBoundsTimer; diff --git a/src/qvimagecore.cpp b/src/qvimagecore.cpp index 24fa9514..9806c149 100644 --- a/src/qvimagecore.cpp +++ b/src/qvimagecore.cpp @@ -1,5 +1,8 @@ #include "qvimagecore.h" #include "qvapplication.h" +#include "qvwin32functions.h" +#include "qvcocoafunctions.h" +#include "qvlinuxx11functions.h" #include #include #include @@ -11,8 +14,7 @@ #include #include -QCache QVImageCore::pixmapCache; - +QCache QVImageCore::pixmapCache; QVImageCore::QVImageCore(QObject *parent) : QObject(parent) { @@ -26,6 +28,7 @@ QVImageCore::QVImageCore(QObject *parent) : QObject(parent) sortMode = 0; sortDescending = false; allowMimeContentDetection = false; + colorSpaceConversion = 1; randomSortSeed = 0; @@ -62,7 +65,7 @@ QVImageCore::QVImageCore(QObject *parent) : QObject(parent) settingsUpdated(); } -void QVImageCore::loadFile(const QString &fileName) +void QVImageCore::loadFile(const QString &fileName, bool isReloading) { if (waitingOnLoad) { @@ -95,34 +98,28 @@ void QVImageCore::loadFile(const QString &fileName) currentFileDetails.isLoadRequested = true; waitingOnLoad = true; + QColorSpace targetColorSpace = getTargetColorSpace(); + QString cacheKey = getPixmapCacheKey(sanitaryFileName, fileInfo.size(), targetColorSpace); //check if cached already before loading the long way - auto previouslyRecordedFileSize = qvApp->getPreviouslyRecordedFileSize(sanitaryFileName); - auto *cachedPixmap = QVImageCore::pixmapCache.take(sanitaryFileName); - if (cachedPixmap != nullptr && - !cachedPixmap->isNull() && - previouslyRecordedFileSize == fileInfo.size()) + auto *cachedData = isReloading ? nullptr : QVImageCore::pixmapCache.take(cacheKey); + if (cachedData != nullptr) { - QSize previouslyRecordedImageSize = qvApp->getPreviouslyRecordedImageSize(sanitaryFileName); - ReadData readData = { - *cachedPixmap, - fileInfo, - previouslyRecordedImageSize - }; + ReadData readData = *cachedData; + delete cachedData; loadPixmap(readData); } else { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - loadFutureWatcher.setFuture(QtConcurrent::run(this, &QVImageCore::readFile, sanitaryFileName, false)); + loadFutureWatcher.setFuture(QtConcurrent::run(this, &QVImageCore::readFile, sanitaryFileName, targetColorSpace, false)); #else - loadFutureWatcher.setFuture(QtConcurrent::run(&QVImageCore::readFile, this, sanitaryFileName, false)); + loadFutureWatcher.setFuture(QtConcurrent::run(&QVImageCore::readFile, this, sanitaryFileName, targetColorSpace, false)); #endif } - delete cachedPixmap; } -QVImageCore::ReadData QVImageCore::readFile(const QString &fileName, bool forCache) +QVImageCore::ReadData QVImageCore::readFile(const QString &fileName, const QColorSpace &targetColorSpace, bool forCache) { QImageReader imageReader; imageReader.setDecideFormatFromContent(true); @@ -130,32 +127,46 @@ QVImageCore::ReadData QVImageCore::readFile(const QString &fileName, bool forCac imageReader.setFileName(fileName); - QPixmap readPixmap; + QImage readImage; if (imageReader.format() == "svg" || imageReader.format() == "svgz") { // Render vectors into a high resolution QIcon icon; icon.addFile(fileName); - readPixmap = icon.pixmap(largestDimension); + readImage = icon.pixmap(largestDimension).toImage(); // If this fails, try reading the normal way so that a proper error message is given - if (readPixmap.isNull()) - readPixmap = QPixmap::fromImageReader(&imageReader); + if (readImage.isNull()) + readImage = imageReader.read(); } else { - readPixmap = QPixmap::fromImageReader(&imageReader); + readImage = imageReader.read(); } +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + // Assume image is sRGB if it doesn't specify + if (!readImage.colorSpace().isValid()) + readImage.setColorSpace(QColorSpace::SRgb); + + // Convert image color space if we have a target that's different + if (targetColorSpace.isValid() && readImage.colorSpace() != targetColorSpace) + readImage.convertToColorSpace(targetColorSpace); +#endif + + QPixmap readPixmap = QPixmap::fromImage(readImage); + QFileInfo fileInfo(fileName); ReadData readData = { readPixmap, - QFileInfo(fileName), + fileInfo.absoluteFilePath(), + fileInfo.size(), imageReader.size(), + targetColorSpace }; // Only error out when not loading for cache if (readPixmap.isNull() && !forCache) { - emit readError(imageReader.error(), imageReader.errorString(), readData.fileInfo.fileName()); + emit readError(imageReader.error(), imageReader.errorString(), fileInfo.fileName()); } return readData; @@ -164,7 +175,7 @@ QVImageCore::ReadData QVImageCore::readFile(const QString &fileName, bool forCac void QVImageCore::loadPixmap(const ReadData &readData) { // Do this first so we can keep folder info even when loading errored files - currentFileDetails.fileInfo = readData.fileInfo; + currentFileDetails.fileInfo = QFileInfo(readData.absoluteFilePath); currentFileDetails.updateLoadedIndexInFolder(); if (currentFileDetails.loadedIndexInFolder == -1) updateFolderInfo(); @@ -179,7 +190,7 @@ void QVImageCore::loadPixmap(const ReadData &readData) // Set file details currentFileDetails.isPixmapLoaded = true; - currentFileDetails.baseImageSize = readData.size; + currentFileDetails.baseImageSize = readData.imageSize; currentFileDetails.loadedPixmapSize = loadedPixmap.size(); if (currentFileDetails.baseImageSize == QSize(-1, -1)) { @@ -201,13 +212,15 @@ void QVImageCore::loadPixmap(const ReadData &readData) loadedMovie.setFileName(currentFileDetails.fileInfo.absoluteFilePath()); } - currentFileDetails.isMovieLoaded = loadedMovie.isValid() && loadedMovie.frameCount() != 1; - - if (currentFileDetails.isMovieLoaded) + if (loadedMovie.isValid() && loadedMovie.frameCount() != 1) loadedMovie.start(); - else if (auto device = loadedMovie.device()) - device->close(); + currentFileDetails.isMovieLoaded = loadedMovie.state() == QMovie::Running; + + if (!currentFileDetails.isMovieLoaded) + if (auto device = loadedMovie.device()) + device->close(); + currentFileDetails.timeSinceLoaded.start(); emit fileChanged(); @@ -261,7 +274,7 @@ QList QVImageCore::getCompatibleFiles(const QString } } QString mimeType; - if (!matched || sortMode == 3) + if (!matched || sortMode == 4) { mimeType = mimeDb.mimeTypeForFile(absoluteFilePath, mimeMatchMode).name(); matched |= mimeTypes.contains(mimeType); @@ -272,8 +285,13 @@ QList QVImageCore::getCompatibleFiles(const QString absoluteFilePath, fileName, sortMode == 1 ? fileInfo.lastModified().toMSecsSinceEpoch() : 0, - sortMode == 2 ? fileInfo.size() : 0, - sortMode == 3 ? mimeType : QString() +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + sortMode == 2 ? fileInfo.birthTime().toMSecsSinceEpoch() : 0, +#else + sortMode == 2 ? fileInfo.created().toMSecsSinceEpoch() : 0, +#endif + sortMode == 3 ? fileInfo.size() : 0, + sortMode == 4 ? mimeType : QString() }); } } @@ -294,7 +312,7 @@ void QVImageCore::updateFolderInfo(QString dirPath) currentFileDetails.folderFileInfoList = getCompatibleFiles(dirPath); - QPair dirInfo = {dirPath, + QPair dirInfo = {dirPath, currentFileDetails.folderFileInfoList.count()}; // If the current folder changed since the last image, assign a new seed for random sorting if (lastDirInfo != dirInfo) @@ -319,7 +337,7 @@ void QVImageCore::updateFolderInfo(QString dirPath) return collator.compare(file1.fileName, file2.fileName) < 0; }); } - else if (sortMode == 1) // last modified + else if (sortMode == 1) // date modified { std::sort(currentFileDetails.folderFileInfoList.begin(), currentFileDetails.folderFileInfoList.end(), @@ -331,7 +349,20 @@ void QVImageCore::updateFolderInfo(QString dirPath) return file1.lastModified > file2.lastModified; }); } - else if (sortMode == 2) // size + else if (sortMode == 2) // date created + { + std::sort(currentFileDetails.folderFileInfoList.begin(), + currentFileDetails.folderFileInfoList.end(), + [this](const CompatibleFile &file1, const CompatibleFile &file2) + { + if (sortDescending) + return file1.lastCreated < file2.lastCreated; + else + return file1.lastCreated > file2.lastCreated; + }); + + } + else if (sortMode == 3) // size { std::sort(currentFileDetails.folderFileInfoList.begin(), currentFileDetails.folderFileInfoList.end(), @@ -343,7 +374,7 @@ void QVImageCore::updateFolderInfo(QString dirPath) return file1.size > file2.size; }); } - else if (sortMode == 3) // type + else if (sortMode == 4) // type { QCollator collator; std::sort(currentFileDetails.folderFileInfoList.begin(), @@ -356,7 +387,7 @@ void QVImageCore::updateFolderInfo(QString dirPath) return collator.compare(file1.mimeType, file2.mimeType) < 0; }); } - else if (sortMode == 4) // Random + else if (sortMode == 5) // Random { std::shuffle(currentFileDetails.folderFileInfoList.begin(), currentFileDetails.folderFileInfoList.end(), std::default_random_engine(randomSortSeed)); } @@ -373,6 +404,8 @@ void QVImageCore::requestCaching() return; } + QColorSpace targetColorSpace = getTargetColorSpace(); + int preloadingDistance = 1; if (preloadingMode > 1) @@ -404,19 +437,21 @@ void QVImageCore::requestCaching() QString filePath = currentFileDetails.folderFileInfoList[index].absoluteFilePath; filesToPreload.append(filePath); - requestCachingFile(filePath); + requestCachingFile(filePath, targetColorSpace); } lastFilesPreloaded = filesToPreload; } -void QVImageCore::requestCachingFile(const QString &filePath) +void QVImageCore::requestCachingFile(const QString &filePath, const QColorSpace &targetColorSpace) { + QFile imgFile(filePath); + QString cacheKey = getPixmapCacheKey(filePath, imgFile.size(), targetColorSpace); + //check if image is already loaded or requested - if (QVImageCore::pixmapCache.contains(filePath) || lastFilesPreloaded.contains(filePath)) + if (QVImageCore::pixmapCache.contains(cacheKey) || lastFilesPreloaded.contains(filePath)) return; - QFile imgFile(filePath); if (imgFile.size()/1024 > QVImageCore::pixmapCache.maxCost()/2) return; @@ -427,9 +462,9 @@ void QVImageCore::requestCachingFile(const QString &filePath) }); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - cacheFutureWatcher->setFuture(QtConcurrent::run(this, &QVImageCore::readFile, filePath, true)); + cacheFutureWatcher->setFuture(QtConcurrent::run(this, &QVImageCore::readFile, filePath, targetColorSpace, true)); #else - cacheFutureWatcher->setFuture(QtConcurrent::run(&QVImageCore::readFile, this, filePath, true)); + cacheFutureWatcher->setFuture(QtConcurrent::run(&QVImageCore::readFile, this, filePath, targetColorSpace, true)); #endif } @@ -438,12 +473,56 @@ void QVImageCore::addToCache(const ReadData &readData) if (readData.pixmap.isNull()) return; + QString cacheKey = getPixmapCacheKey(readData.absoluteFilePath, readData.fileSize, readData.targetColorSpace); + qint64 pixmapMemoryBytes = static_cast(readData.pixmap.width()) * readData.pixmap.height() * readData.pixmap.depth() / 8; - auto fileSize = readData.fileInfo.size(); - QVImageCore::pixmapCache.insert(readData.fileInfo.absoluteFilePath(), new QPixmap(readData.pixmap), fileSize/1024); + QVImageCore::pixmapCache.insert(cacheKey, new ReadData(readData), qMax(pixmapMemoryBytes / 1024, 1LL)); +} - qvApp->setPreviouslyRecordedFileSize(readData.fileInfo.absoluteFilePath(), new qint64(fileSize)); - qvApp->setPreviouslyRecordedImageSize(readData.fileInfo.absoluteFilePath(), new QSize(readData.size)); +QString QVImageCore::getPixmapCacheKey(const QString &absoluteFilePath, const qint64 &fileSize, const QColorSpace &targetColorSpace) +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QString targetColorSpaceHash = QCryptographicHash::hash(targetColorSpace.iccProfile(), QCryptographicHash::Md5).toHex(); +#else + QString targetColorSpaceHash = ""; +#endif + return absoluteFilePath + "\n" + QString::number(fileSize) + "\n" + targetColorSpaceHash; +} + +QColorSpace QVImageCore::getTargetColorSpace() const +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + return + colorSpaceConversion == 1 ? detectDisplayColorSpace() : + colorSpaceConversion == 2 ? QColorSpace::SRgb : + colorSpaceConversion == 3 ? QColorSpace::DisplayP3 : + QColorSpace(); +#else + return {}; +#endif +} + +QColorSpace QVImageCore::detectDisplayColorSpace() const +{ +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QWindow *window = static_cast(parent())->window()->windowHandle(); + + QByteArray profileData; +#ifdef WIN32_LOADED + profileData = QVWin32Functions::getIccProfileForWindow(window); +#endif +#ifdef COCOA_LOADED + profileData = QVCocoaFunctions::getIccProfileForWindow(window); +#endif +#ifdef X11_LOADED + profileData = QVLinuxX11Functions::getIccProfileForWindow(window); +#endif + + if (!profileData.isEmpty()) + return QColorSpace::fromIccProfile(profileData); +#endif + + return {}; } void QVImageCore::jumpToNextFrame() @@ -470,19 +549,11 @@ void QVImageCore::setSpeed(int desiredSpeed) loadedMovie.setSpeed(desiredSpeed); } -QPixmap QVImageCore::scaleExpensively(const int desiredWidth, const int desiredHeight) -{ - return scaleExpensively(QSizeF(desiredWidth, desiredHeight)); -} - QPixmap QVImageCore::scaleExpensively(const QSizeF desiredSize) { if (!currentFileDetails.isPixmapLoaded) return QPixmap(); - QSize size = QSize(loadedPixmap.width(), loadedPixmap.height()); - size.scale(desiredSize.toSize(), Qt::KeepAspectRatio); - // Get the current frame of the animation if this is an animation QPixmap relevantPixmap; if (!currentFileDetails.isMovieLoaded) @@ -501,7 +572,11 @@ QPixmap QVImageCore::scaleExpensively(const QSizeF desiredSize) return relevantPixmap; } - return relevantPixmap.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);; + QSize size = desiredSize.toSize(); + size.rwidth() = qMax(size.width(), 1); + size.rheight() = qMax(size.height(), 1); + + return relevantPixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } @@ -538,16 +613,29 @@ void QVImageCore::settingsUpdated() //update folder info to reflect new settings (e.g. sort order) updateFolderInfo(); + + bool changedImagePreprocessing = false; + + //colorspaceconversion + if (colorSpaceConversion != settingsManager.getInteger("colorspaceconversion")) + { + colorSpaceConversion = settingsManager.getInteger("colorspaceconversion"); + changedImagePreprocessing = true; + } + + if (changedImagePreprocessing && currentFileDetails.isPixmapLoaded) + loadFile(currentFileDetails.fileInfo.absoluteFilePath()); } void QVImageCore::FileDetails::updateLoadedIndexInFolder() { - const QString targetPath = fileInfo.absoluteFilePath(); + const QString targetPath = fileInfo.absoluteFilePath().normalized(QString::NormalizationForm_D); for (int i = 0; i < folderFileInfoList.length(); i++) { // Compare absoluteFilePath first because it's way faster, but double-check with // QFileInfo::operator== because it respects file system case sensitivity rules - if (folderFileInfoList[i].absoluteFilePath.compare(targetPath, Qt::CaseInsensitive) == 0 && + QString candidatePath = folderFileInfoList[i].absoluteFilePath.normalized(QString::NormalizationForm_D); + if (candidatePath.compare(targetPath, Qt::CaseInsensitive) == 0 && QFileInfo(folderFileInfoList[i].absoluteFilePath) == fileInfo) { loadedIndexInFolder = i; diff --git a/src/qvimagecore.h b/src/qvimagecore.h index 56e5d365..845f6d8c 100644 --- a/src/qvimagecore.h +++ b/src/qvimagecore.h @@ -11,6 +11,12 @@ #include #include +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) +#include +#else +typedef QString QColorSpace; +#endif + class QVImageCore : public QObject { Q_OBJECT @@ -23,6 +29,7 @@ class QVImageCore : public QObject // Only populated if needed for sorting qint64 lastModified; + qint64 lastCreated; qint64 size; QString mimeType; }; @@ -45,21 +52,26 @@ class QVImageCore : public QObject struct ReadData { QPixmap pixmap; - QFileInfo fileInfo; - QSize size; + QString absoluteFilePath; + qint64 fileSize; + QSize imageSize; + QColorSpace targetColorSpace; }; explicit QVImageCore(QObject *parent = nullptr); - void loadFile(const QString &fileName); - ReadData readFile(const QString &fileName, bool forCache); + void loadFile(const QString &fileName, bool isReloading = false); + ReadData readFile(const QString &fileName, const QColorSpace &targetColorSpace, bool forCache); void loadPixmap(const ReadData &readData); void closeImage(); QList getCompatibleFiles(const QString &dirPath) const; void updateFolderInfo(QString dirPath = QString()); void requestCaching(); - void requestCachingFile(const QString &filePath); + void requestCachingFile(const QString &filePath, const QColorSpace &targetColorSpace); void addToCache(const ReadData &readImageAndFileInfo); + static QString getPixmapCacheKey(const QString &absoluteFilePath, const qint64 &fileSize, const QColorSpace &targetColorSpace); + QColorSpace getTargetColorSpace() const; + QColorSpace detectDisplayColorSpace() const; void settingsUpdated(); @@ -67,7 +79,6 @@ class QVImageCore : public QObject void setPaused(bool desiredState); void setSpeed(int desiredSpeed); - QPixmap scaleExpensively(const int desiredWidth, const int desiredHeight); QPixmap scaleExpensively(const QSizeF desiredSize); //returned const reference is read-only @@ -95,10 +106,11 @@ class QVImageCore : public QObject int sortMode; bool sortDescending; bool allowMimeContentDetection; + int colorSpaceConversion; - static QCache pixmapCache; + static QCache pixmapCache; - QPair lastDirInfo; + QPair lastDirInfo; unsigned randomSortSeed; QStringList lastFilesPreloaded; diff --git a/src/qvinfodialog.cpp b/src/qvinfodialog.cpp index b445119b..63aca2a2 100644 --- a/src/qvinfodialog.cpp +++ b/src/qvinfodialog.cpp @@ -2,6 +2,7 @@ #include "ui_qvinfodialog.h" #include #include +#include static int getGcd (int a, int b) { return (b == 0) ? a : getGcd(b, a%b); @@ -31,8 +32,20 @@ void QVInfoDialog::setInfo(const QFileInfo &value, const int &value2, const int width = value2; height = value3; frameCount = value4; - updateInfo(); - window()->adjustSize(); + + // If the dialog is visible, it means we've just navigated to a new image. Instead of running + // updateInfo immediately, add it to the event queue. This is a workaround for a (Windows-specific?) + // delay when calling adjustSize on the window if the font contains certain characters (e.g. Chinese) + // the first time that happens for a given font. At least on Windows, by making the work happen later + // in the event loop, it allows the main window to repaint first, giving the appearance of better + // responsiveness. If the dialog is not visible, however, it means we're preparing to display for an + // image already opened. In this case there is no urgency to repaint the main window, and we need to + // process the updates here synchronously to avoid the caller showing the dialog before it's ready + // (i.e. to avoid showing outdated info or placeholder text). + if (isVisible()) + QTimer::singleShot(0, this, &QVInfoDialog::updateInfo); + else + updateInfo(); } void QVInfoDialog::updateInfo() @@ -63,4 +76,5 @@ void QVInfoDialog::updateInfo() ui->framesLabel2->hide(); ui->framesLabel->hide(); } + window()->adjustSize(); } diff --git a/src/qvlinuxx11functions.cpp b/src/qvlinuxx11functions.cpp new file mode 100644 index 00000000..5c257418 --- /dev/null +++ b/src/qvlinuxx11functions.cpp @@ -0,0 +1,61 @@ +#include "qvlinuxx11functions.h" +#include +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#include +#endif +#include +#include + +namespace X11Helper +{ + Display* getDisplay() + { +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + if (QX11Info::isPlatformX11()) + return QX11Info::display(); + return nullptr; +#else + if (const auto x11App = qGuiApp->nativeInterface()) + return x11App->display(); + return nullptr; +#endif + } +} + +QByteArray QVLinuxX11Functions::getIccProfileForWindow(const QWindow *window) +{ + Q_UNUSED(window); // Unused for now; not sure how to handle multiple monitors + QByteArray result; + Display *display = X11Helper::getDisplay(); + if (display) + { + Atom iccProfileAtom = XInternAtom(display, "_ICC_PROFILE", True); + if (iccProfileAtom != None) + { + Atom type; + int format; + unsigned long size; + unsigned long size_left; + unsigned char *data; + int status = XGetWindowProperty( + display, + DefaultRootWindow(display), + iccProfileAtom, + 0, + INT_MAX, + False, + XA_CARDINAL, + &type, + &format, + &size, + &size_left, + &data); + if (status == Success && data) + { + result = QByteArray(reinterpret_cast(data), size); + XFree(data); + } + } + } + return result; +} diff --git a/src/qvlinuxx11functions.h b/src/qvlinuxx11functions.h new file mode 100644 index 00000000..efe35579 --- /dev/null +++ b/src/qvlinuxx11functions.h @@ -0,0 +1,13 @@ +#ifndef QVLINUXX11FUNCTIONS_H +#define QVLINUXX11FUNCTIONS_H + +#include + +class QVLinuxX11Functions +{ +public: + static QByteArray getIccProfileForWindow(const QWindow *window); +}; + +#endif // QVLINUXX11FUNCTIONS_H + diff --git a/src/qvoptionsdialog.cpp b/src/qvoptionsdialog.cpp index dfe098fd..fdb77db3 100644 --- a/src/qvoptionsdialog.cpp +++ b/src/qvoptionsdialog.cpp @@ -58,7 +58,14 @@ QVOptionsDialog::QVOptionsDialog(QWidget *parent) : ui->langComboLabel->hide(); #endif +// Hide color space conversion below 5.14, which is when color space support was introduced +#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0)) + ui->colorSpaceConversionComboBox->hide(); + ui->colorSpaceConversionLabel->hide(); +#endif + syncSettings(false, true); + connect(ui->windowResizeComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &QVOptionsDialog::windowResizeComboBoxCurrentIndexChanged); connect(ui->langComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, &QVOptionsDialog::languageComboBoxCurrentIndexChanged); syncShortcuts(); updateButtonBox(); @@ -131,17 +138,7 @@ void QVOptionsDialog::syncSettings(bool defaults, bool makeConnections) ui->titlebarRadioButton2, ui->titlebarRadioButton3}, "titlebarmode", defaults, makeConnections); // windowresizemode syncComboBox(ui->windowResizeComboBox, "windowresizemode", defaults, makeConnections); - if (ui->windowResizeComboBox->currentIndex() == 0) { - ui->minWindowResizeLabel->setEnabled(false); - ui->minWindowResizeSpinBox->setEnabled(false); - ui->maxWindowResizeLabel->setEnabled(false); - ui->maxWindowResizeSpinBox->setEnabled(false); - } else { - ui->minWindowResizeLabel->setEnabled(true); - ui->minWindowResizeSpinBox->setEnabled(true); - ui->maxWindowResizeLabel->setEnabled(true); - ui->maxWindowResizeSpinBox->setEnabled(true); - } + windowResizeComboBoxCurrentIndexChanged(ui->windowResizeComboBox->currentIndex()); // minwindowresizedpercentage syncSpinBox(ui->minWindowResizeSpinBox, "minwindowresizedpercentage", defaults, makeConnections); // maxwindowresizedperecentage @@ -184,6 +181,8 @@ void QVOptionsDialog::syncSettings(bool defaults, bool makeConnections) ui->constrainCentersSmallImageCheckbox->setEnabled(false); // constraincentersmallimage syncCheckbox(ui->constrainCentersSmallImageCheckbox, "constraincentersmallimage", defaults, makeConnections); + // colorspaceconversion + syncComboBox(ui->colorSpaceConversionComboBox, "colorspaceconversion", defaults, makeConnections); // language syncComboBoxData(ui->langComboBox, "language", defaults, makeConnections); // sortmode @@ -448,20 +447,11 @@ void QVOptionsDialog::scalingCheckboxStateChanged(int arg1) void QVOptionsDialog::windowResizeComboBoxCurrentIndexChanged(int index) { - if (index == 0) - { - ui->minWindowResizeLabel->setEnabled(false); - ui->minWindowResizeSpinBox->setEnabled(false); - ui->maxWindowResizeLabel->setEnabled(false); - ui->maxWindowResizeSpinBox->setEnabled(false); - } - else - { - ui->minWindowResizeLabel->setEnabled(true); - ui->minWindowResizeSpinBox->setEnabled(true); - ui->maxWindowResizeLabel->setEnabled(true); - ui->maxWindowResizeSpinBox->setEnabled(true); - } + bool enableRelatedControls = index != 0; + ui->minWindowResizeLabel->setEnabled(enableRelatedControls); + ui->minWindowResizeSpinBox->setEnabled(enableRelatedControls); + ui->maxWindowResizeLabel->setEnabled(enableRelatedControls); + ui->maxWindowResizeSpinBox->setEnabled(enableRelatedControls); } void QVOptionsDialog::constrainImagePositionCheckboxStateChanged(int arg1) diff --git a/src/qvoptionsdialog.ui b/src/qvoptionsdialog.ui index 5c405bf9..788b1b60 100644 --- a/src/qvoptionsdialog.ui +++ b/src/qvoptionsdialog.ui @@ -5,6 +5,14 @@ Qt::NonModal + + + 0 + 0 + 497 + 558 + + Settings @@ -15,7 +23,7 @@ Qt::NoFocus - 1 + 2 @@ -473,6 +481,56 @@ + + + + Qt::Horizontal + + + + 40 + 5 + + + + + + + + Color space conversion: + + + + + + + + 0 + 0 + + + + + Disabled + + + + + Auto-detect + + + + + sRGB + + + + + Display P3 + + + + @@ -506,7 +564,12 @@ - Last Modified + Date Modified + + + + + Date Created diff --git a/src/qvwin32functions.cpp b/src/qvwin32functions.cpp index 72b8f157..33c2b1a5 100644 --- a/src/qvwin32functions.cpp +++ b/src/qvwin32functions.cpp @@ -2,6 +2,7 @@ #include "ShlObj_core.h" #include "winuser.h" +#include "wingdi.h" #include "Objbase.h" #include "appmodel.h" #include "Shlwapi.h" @@ -143,3 +144,27 @@ void QVWin32Functions::showOpenWithDialog(const QString &filePath, const QWindow if (!SUCCEEDED(SHOpenWithDialog(winId, &info))) qDebug() << "Failed launching open with dialog"; } + +QByteArray QVWin32Functions::getIccProfileForWindow(const QWindow *window) +{ + QByteArray result; + const HWND hWnd = reinterpret_cast(window->winId()); + const HDC hDC = GetDC(hWnd); + if (hDC) + { + WCHAR profilePathBuff[MAX_PATH]; + DWORD profilePathSize = MAX_PATH; + if (GetICMProfileW(hDC, &profilePathSize, profilePathBuff)) + { + QString profilePath = QString::fromWCharArray(profilePathBuff); + QFile file(profilePath); + if (file.open(QIODevice::ReadOnly)) + { + result = file.readAll(); + file.close(); + } + } + ReleaseDC(hWnd, hDC); + } + return result; +} diff --git a/src/qvwin32functions.h b/src/qvwin32functions.h index 3ce75ee2..86faf78a 100644 --- a/src/qvwin32functions.h +++ b/src/qvwin32functions.h @@ -14,6 +14,7 @@ class QVWin32Functions static void showOpenWithDialog(const QString &filePath, const QWindow *parent); + static QByteArray getIccProfileForWindow(const QWindow *window); }; #endif // QVWIN32FUNCTIONS_H diff --git a/src/scrollhelper.cpp b/src/scrollhelper.cpp index 930aace0..661a927d 100644 --- a/src/scrollhelper.cpp +++ b/src/scrollhelper.cpp @@ -19,7 +19,7 @@ void ScrollHelper::move(QPointF delta) { Parameters p; getParametersCallback(p); - if (!p.ContentRect.isValid() || !p.UsableViewportRect.isValid()) + if (!p.contentRect.isValid() || !p.usableViewportRect.isValid()) { overscrollDistance = {}; return; @@ -27,25 +27,27 @@ void ScrollHelper::move(QPointF delta) bool isRightToLeft = hScrollBar->isRightToLeft(); int hMin, hMax, vMin, vMax; calculateScrollRange( - p.ContentRect.width(), - p.UsableViewportRect.width(), - (p.ContentRect.left() * (isRightToLeft ? -1 : 1)) - (isRightToLeft ? p.ContentRect.width() : 0), - p.ShouldCenter, + p.contentRect.width(), + p.usableViewportRect.width(), + isRightToLeft ? + hScrollBar->minimum() + hScrollBar->maximum() + p.usableViewportRect.width() - p.contentRect.left() - p.contentRect.width() : + p.contentRect.left(), + p.shouldCenter, hMin, hMax ); calculateScrollRange( - p.ContentRect.height(), - p.UsableViewportRect.height(), - p.ContentRect.top() - p.UsableViewportRect.top(), - p.ShouldCenter, + p.contentRect.height(), + p.usableViewportRect.height(), + p.contentRect.top() - p.usableViewportRect.top(), + p.shouldCenter, vMin, vMax ); QPointF scrollLocation = QPointF(hScrollBar->value(), vScrollBar->value()) + lastMoveRoundingError; qreal scrollDeltaX = delta.x(); qreal scrollDeltaY = delta.y(); - if (p.ShouldConstrain) + if (p.shouldConstrain) { scrollDeltaX = calculateScrollDelta(scrollLocation.x(), hMin, hMax, scrollDeltaX); scrollDeltaY = calculateScrollDelta(scrollLocation.y(), vMin, vMax, scrollDeltaY); @@ -55,12 +57,12 @@ void ScrollHelper::move(QPointF delta) int scrollValueY = qRound(scrollLocation.y()); lastMoveRoundingError = QPointF(scrollLocation.x() - scrollValueX, scrollLocation.y() - scrollValueY); int overscrollDistanceX = - p.ShouldConstrain && scrollValueX < hMin ? scrollValueX - hMin : - p.ShouldConstrain && scrollValueX > hMax ? scrollValueX - hMax : + p.shouldConstrain && scrollValueX < hMin ? scrollValueX - hMin : + p.shouldConstrain && scrollValueX > hMax ? scrollValueX - hMax : 0; int overscrollDistanceY = - p.ShouldConstrain && scrollValueY < vMin ? scrollValueY - vMin : - p.ShouldConstrain && scrollValueY > vMax ? scrollValueY - vMax : + p.shouldConstrain && scrollValueY < vMin ? scrollValueY - vMin : + p.shouldConstrain && scrollValueY > vMax ? scrollValueY - vMax : 0; overscrollDistance = QPoint(overscrollDistanceX, overscrollDistanceY); hScrollBar->setValue(scrollValueX); diff --git a/src/scrollhelper.h b/src/scrollhelper.h index 5cb68d57..65bd0b1d 100644 --- a/src/scrollhelper.h +++ b/src/scrollhelper.h @@ -1,6 +1,7 @@ #ifndef SCROLLHELPER_H #define SCROLLHELPER_H +#include #include #include #include @@ -12,10 +13,10 @@ class ScrollHelper : public QObject public: struct Parameters { - QRect ContentRect; - QRect UsableViewportRect; - bool ShouldConstrain; - bool ShouldCenter; + QRect contentRect; + QRect usableViewportRect; + bool shouldConstrain; + bool shouldCenter; }; typedef std::function GetParametersCallback; diff --git a/src/settingsmanager.cpp b/src/settingsmanager.cpp index a04903dc..d22e3feb 100644 --- a/src/settingsmanager.cpp +++ b/src/settingsmanager.cpp @@ -174,6 +174,7 @@ void SettingsManager::initializeSettingsLibrary() settingsLibrary.insert("pastactualsizeenabled", {true, {}}); settingsLibrary.insert("constrainimageposition", {false, {}}); settingsLibrary.insert("constraincentersmallimage", {true, {}}); + settingsLibrary.insert("colorspaceconversion", {1, {}}); // Miscellaneous settingsLibrary.insert("language", {"system", {}}); settingsLibrary.insert("sortmode", {0, {}}); diff --git a/src/shortcutmanager.cpp b/src/shortcutmanager.cpp index 9eb76692..41c9be1a 100644 --- a/src/shortcutmanager.cpp +++ b/src/shortcutmanager.cpp @@ -44,6 +44,7 @@ void ShortcutManager::initializeShortcutsList() { shortcutsList.append({tr("Open"), "open", keyBindingsToStringList(QKeySequence::Open), {}}); shortcutsList.append({tr("Open URL"), "openurl", QStringList(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_O).toString()), {}}); + shortcutsList.append({tr("Reload File"), "reloadfile", keyBindingsToStringList(QKeySequence::Refresh), {}}); shortcutsList.append({tr("Open Containing Folder"), "opencontainingfolder", {}, {}}); //Sets open containing folder action name to platform-appropriate alternative #ifdef Q_OS_WIN @@ -58,7 +59,10 @@ void ShortcutManager::initializeShortcutsList() #endif shortcutsList.append({tr("Copy"), "copy", keyBindingsToStringList(QKeySequence::Copy), {}}); shortcutsList.append({tr("Paste"), "paste", keyBindingsToStringList(QKeySequence::Paste), {}}); - shortcutsList.append({tr("Rename"), "rename", QStringList({QKeySequence(Qt::Key_F2).toString(), QKeySequence(Qt::CTRL | Qt::Key_R).toString()}), {}}); + shortcutsList.append({tr("Rename"), "rename", QStringList(QKeySequence(Qt::Key_F2).toString()), {}}); + // ctrl+r for renaming, unless it conflicts with refresh (i.e. reload file) + if (!QKeySequence::keyBindings(QKeySequence::Refresh).contains(QKeySequence(Qt::CTRL | Qt::Key_R))) + shortcutsList.last().defaultShortcuts << QKeySequence(Qt::CTRL | Qt::Key_R).toString(); // cmd+enter for renaming, mac-style shortcutsList.last().defaultShortcuts.prepend(QKeySequence(Qt::CTRL | Qt::Key_Return).toString()); diff --git a/src/src.pri b/src/src.pri index 0ad1b15d..42a85047 100644 --- a/src/src.pri +++ b/src/src.pri @@ -19,6 +19,7 @@ SOURCES += \ macx:!CONFIG(NO_COCOA):SOURCES += $$PWD/qvcocoafunctions.mm win32:!CONFIG(NO_WIN32):SOURCES += $$PWD/qvwin32functions.cpp +linux:!CONFIG(NO_X11):SOURCES += $$PWD/qvlinuxx11functions.cpp HEADERS += \ $$PWD/mainwindow.h \ @@ -40,6 +41,7 @@ HEADERS += \ macx:!CONFIG(NO_COCOA):HEADERS += $$PWD/qvcocoafunctions.h win32:!CONFIG(NO_WIN32):HEADERS += $$PWD/qvwin32functions.h +linux:!CONFIG(NO_X11):HEADERS += $$PWD/qvlinuxx11functions.h FORMS += \ $$PWD/mainwindow.ui \