Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,25 @@ Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.1.0/).

## [Unreleased]

## [1.0.8] - 2026-10-07

ExplorerPro 1.0.8
• Cloud-Ordner und Windows-Verknüpfungen erscheinen wieder in der Dateiliste; lange Ordnernamen bleiben lesbar.
• Die Vorschau ist stabiler und lädt Dateien, die nur online verfügbar sind, nicht ungefragt herunter.
• Blacklist und Whitelist lassen sich bearbeiten sowie als TXT, CSV oder XLSX importieren und exportieren. Begriffe mit führendem „=“ bleiben im XLSX-Export erhalten.
• Die Spracheinstellung wirkt auf mehr Bedienelemente. Gespeicherte Kategorien werden beim Sprachwechsel nicht mehr verändert.
• Eigenschaften öffnen ohne automatische Inhaltsprüfung. Prüfsummen und Text-/Ordnerstatistik starten auf Wunsch; Ordnerabfragen laufen mit Zeitlimit. Unvollständige Statistiken sind gekennzeichnet.
• Mehrfachumbenennung, Löschbestätigung und das Beenden laufender Prüfsummen wurden robuster.

ExplorerPro 1.0.8
• Cloud folders and Windows shortcuts appear in the file list again; long folder names remain readable.
• Preview is more stable and does not automatically download online-only files.
• Edit and import/export privacy blacklists and whitelists as TXT, CSV or XLSX. XLSX exports preserve terms starting with '='.
• The language setting updates more controls. Switching languages no longer changes saved categories.
• Properties open without automatic content reads. Start checksums and text/folder statistics when needed; folder queries have a time limit and incomplete statistics are marked.
• More reliable batch renaming, deletion confirmation and checksum shutdown.


### Review & Fehlerbehebung: Cloud-Ordner, Vorschau, Datenschutz, Sprache (2026-10-06)
- **Cloud-Ordner sichtbar:** Unter Windows blendete die Dateiliste OneDrive-/Cloud-Platzhalter (Reparse-Points) und Verknüpfungen (`*.lnk`) aus; der Filter enthält jetzt `QDir.System`. Neue Seitenleisten-Gruppe **Cloud-Speicher** (OneDrive privat/geschäftlich, Dropbox, Google Drive, iCloud, Nextcloud u. a.; Windows-SyncRootManager nur lesend). Schnellzugriff-Einträge sind aufklappbar.
- **Ordnernamen statt „Ordner“:** Typ- und Datumsspalte nutzten `ResizeToContents` und konnten die Namensspalte auf wenige Pixel zusammendrücken. Feste, verstellbare Breiten; die Namensspalte behält mindestens 160 px, lange Namen werden mittig gekürzt.
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name: ExplorerPro
type: project-docs
profile: STANDARD
version: 1.0.7
version: 1.0.8
created: 2026-07-22
updated: 2026-09-26
reason_last_change: "T-20260926-912169808: Kontextmenü-Tags/Metadaten, Editor-Dirty-Flag (modificationChanged), qtbase-Übersetzung, 359 Tests"
Expand Down
15 changes: 3 additions & 12 deletions ExplorerPro.spec
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# -*- mode: python ; coding: utf-8 -*-

from pathlib import Path
import json
import os

project_root = Path.cwd()
src_dir = project_root / 'src'
Expand All @@ -25,18 +27,7 @@ a = Analysis(
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[
'IPython',
'black',
'blib2to3',
'cv2',
'matplotlib',
'notebook',
'pytest',
'scipy',
'sklearn',
'torch',
],
excludes=json.loads(os.environ["PYINSTALLER_EXCLUDES"]),
noarchive=False,
optimize=0,
)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
[![Umbrella: open--bricks](https://img.shields.io/badge/umbrella-open--bricks-blue.svg)](https://github.com/open-bricks)
[![Microsoft Store](https://img.shields.io/badge/Microsoft%20Store-Live-0078D7.svg?logo=windows)](https://apps.microsoft.com/detail/9P0X52WSHZ3Q)
[![LLM-Ready: llms.txt](https://img.shields.io/badge/LLM--Ready-llms.txt-success.svg)](llms.txt)
[![Version: 1.0.7](https://img.shields.io/badge/version-1.0.7-orange.svg)](CHANGELOG.md)
[![Version: 1.0.8](https://img.shields.io/badge/version-1.0.8-orange.svg)](CHANGELOG.md)
[![Last Checked](https://img.shields.io/badge/Last--Checked-2026--09--30-blue?style=flat-square)](CHANGELOG.md)

> [!NOTE]
Expand Down Expand Up @@ -64,7 +64,7 @@
<a id="hauptfunktionen"></a>
## 1. Features & Core Capabilities

The source version includes per-drive capacity bars in the folder sidebar, with used percentage and free/used/total space in GiB/TiB. Capacity requests run in the background; use **Refresh drive usage** to update them. Unavailable devices show an explanatory message. This addition is not yet part of a newly packaged release.
The source version includes per-drive capacity bars in the folder sidebar, with used percentage and free/used/total space in GiB/TiB. Capacity requests run in the background; use **Refresh drive usage** to update them. Unavailable devices show an explanatory message. This functionality is included in the 1.0.8 release package.

Standard operating system file managers are built for casual browsing and lack the heavy-lifting tools developers, researchers, and power users require daily. ExplorerPro addresses this gap by packaging pro-grade productivity utilities into a cohesive, responsive desktop interface with zero telemetry and 100% Local-First data isolation:

Expand Down
4 changes: 2 additions & 2 deletions README_de.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# ExplorerPro Suite

Der aktuelle Quellcode zeigt in der Ordner-Seitenleiste die Speicherbelegung je Laufwerk: Balken, Prozentanteil und freier/belegter/gesamter Speicher in GiB/TiB. Die Abfrage läuft im Hintergrund; **Laufwerksbelegung aktualisieren** erneuert die Werte. Nicht verfügbare Geräte werden verständlich gekennzeichnet. Diese Ergänzung ist noch nicht Bestandteil eines neu gebauten Releases.
Der aktuelle Quellcode zeigt in der Ordner-Seitenleiste die Speicherbelegung je Laufwerk: Balken, Prozentanteil und freier/belegter/gesamter Speicher in GiB/TiB. Die Abfrage läuft im Hintergrund; **Laufwerksbelegung aktualisieren** erneuert die Werte. Nicht verfügbare Geräte werden verständlich gekennzeichnet. Diese Funktion ist im Release-Paket 1.0.8 enthalten.

[English](README.md) | **[Deutsch](README_de.md)** | [Maschinenlesbarer Kontext (llms.txt)](llms.txt)

Expand All @@ -23,7 +23,7 @@ Der aktuelle Quellcode zeigt in der Ordner-Seitenleiste die Speicherbelegung je
[![Dachverband: open--bricks](https://img.shields.io/badge/Dachverband-open--bricks-blue.svg)](https://github.com/open-bricks)
[![Microsoft Store](https://img.shields.io/badge/Microsoft%20Store-Live-0078D7.svg?logo=windows)](https://apps.microsoft.com/detail/9P0X52WSHZ3Q)
[![LLM-Ready: llms.txt](https://img.shields.io/badge/LLM--Ready-llms.txt-success.svg)](llms.txt)
[![Version: 1.0.7](https://img.shields.io/badge/Version-1.0.7-orange.svg)](CHANGELOG.md)
[![Version: 1.0.8](https://img.shields.io/badge/Version-1.0.8-orange.svg)](CHANGELOG.md)
[![Stand](https://img.shields.io/badge/Stand-2026--09--30-blue?style=flat-square)](CHANGELOG.md)

> [!NOTE]
Expand Down
31 changes: 2 additions & 29 deletions build_exe.bat
Original file line number Diff line number Diff line change
@@ -1,34 +1,7 @@
@echo off
chcp 65001 >nul
setlocal

cd /d "%~dp0"

set "BUILD_ROOT=C:\_Local_DEV\codex_build\explorerpro"
set "WORK_PATH=%BUILD_ROOT%\work"

if not exist "%BUILD_ROOT%" mkdir "%BUILD_ROOT%"
if not exist "%WORK_PATH%" mkdir "%WORK_PATH%"

echo [INFO] Baue ExplorerPro.exe mit lokalem PyInstaller-Workpath...
python -m PyInstaller --clean --noconfirm --workpath "%WORK_PATH%" --distpath "%CD%\dist" ExplorerPro.spec
if errorlevel 1 (
echo [FEHLER] PyInstaller-Build fehlgeschlagen.
exit /b 1
)

if not exist "%CD%\dist\ExplorerPro\ExplorerPro.exe" (
echo [FEHLER] Erwartete EXE nicht gefunden: dist\ExplorerPro\ExplorerPro.exe
exit /b 1
)

for %%F in (LICENSE THIRD_PARTY_LICENSES.txt PRIVACY_POLICY.md SUPPORT.md) do (
copy /Y "%CD%\%%F" "%CD%\dist\ExplorerPro\%%F" >nul
if errorlevel 1 (
echo [FEHLER] Notice-Datei konnte nicht ins Bundle kopiert werden: %%F
exit /b 1
)
)

echo [OK] EXE erstellt: dist\ExplorerPro\ExplorerPro.exe
python scripts\build_release.py
if errorlevel 1 exit /b 1
endlocal
2 changes: 1 addition & 1 deletion llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ License: AGPL-3.0
Microsoft Store Identity: Geiger.ExplorerPro (Store-ID: 9P0X52WSHZ3Q)

Last-checked: 2026-09-30 (Previous: 2026-09-29)
Version: 1.0.7
Version: 1.0.8

## Search Phrases

Expand Down
8 changes: 8 additions & 0 deletions locales/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -8398,5 +8398,13 @@
"zh": "密码提示",
"ja": "パスワードの手がかり",
"ru": "Признаки паролей"
},
"Nur online verfügbar. Datei zuerst lokal verfügbar machen.": {
"de": "Nur online verfügbar. Datei zuerst lokal verfügbar machen.",
"en": "Available online only. Make the file available locally first.",
"es": "Disponible solo en línea. Haga que el archivo esté disponible localmente primero.",
"zh": "仅在线可用。请先将文件下载到本地。",
"ja": "オンラインでのみ利用可能です。先にファイルをローカルで利用できるようにしてください。",
"ru": "Доступно только онлайн. Сначала сделайте файл доступным локально."
}
}
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "explorerpro"
version = "1.0.7"
version = "1.0.8"
description = "Datei-Explorer-Suite mit Editor, PDF-Viewer und Datenanalyse"
authors = [{ name = "Lukas Geiger", email = "support@lukasgeiger.com" }]
requires-python = ">=3.10"
Expand Down
4 changes: 4 additions & 0 deletions releases/windowsstore/v1.0.8/release-notes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"de-de": "ExplorerPro 1.0.8\n• Cloud-Ordner und Windows-Verknüpfungen erscheinen wieder in der Dateiliste; lange Ordnernamen bleiben lesbar.\n• Die Vorschau ist stabiler und lädt Dateien, die nur online verfügbar sind, nicht ungefragt herunter.\n• Blacklist und Whitelist lassen sich bearbeiten sowie als TXT, CSV oder XLSX importieren und exportieren. Begriffe mit führendem „=“ bleiben im XLSX-Export erhalten.\n• Die Spracheinstellung wirkt auf mehr Bedienelemente. Gespeicherte Kategorien werden beim Sprachwechsel nicht mehr verändert.\n• Eigenschaften öffnen ohne automatische Inhaltsprüfung. Prüfsummen und Text-/Ordnerstatistik starten auf Wunsch; Ordnerabfragen laufen mit Zeitlimit. Unvollständige Statistiken sind gekennzeichnet.\n• Mehrfachumbenennung, Löschbestätigung und das Beenden laufender Prüfsummen wurden robuster.",
"en-us": "ExplorerPro 1.0.8\n• Cloud folders and Windows shortcuts appear in the file list again; long folder names remain readable.\n• Preview is more stable and does not automatically download online-only files.\n• Edit and import/export privacy blacklists and whitelists as TXT, CSV or XLSX. XLSX exports preserve terms starting with '='.\n• The language setting updates more controls. Switching languages no longer changes saved categories.\n• Properties open without automatic content reads. Start checksums and text/folder statistics when needed; folder queries have a time limit and incomplete statistics are marked.\n• More reliable batch renaming, deletion confirmation and checksum shutdown."
}
32 changes: 32 additions & 0 deletions scripts/build_release.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Build via the pipeline scanner and the same Python as PyInstaller."""
import json
import os
from pathlib import Path
import subprocess
import sys

root = Path(__file__).resolve().parents[1]
config = json.loads((root / "store_package.json").read_text(encoding="utf-8"))
app_name = config["app_name"]
tools_root = Path(os.environ.get("SOFTWARE_TOOLS_ROOT",
str(Path(os.environ.get("OneDrive", str(Path.home() / "OneDrive"))) / ".TOPICS" / ".SOFTWARE" / "_tools")))
scanner = tools_root / "build_exclude_scanner.py"
if not scanner.is_file():
raise SystemExit("Missing required pipeline scanner: " + str(scanner))
result = subprocess.run([sys.executable, str(scanner), "--project", str(root), "--emit", "json"],
check=True, capture_output=True, text=True, encoding="utf-8")
print(result.stderr, file=sys.stderr)
report = json.loads(result.stdout)
build_root = Path(os.environ.get("BUILD_ROOT", str(Path("C:/_Local_DEV/codex_build") / app_name.lower())))
build_root.mkdir(parents=True, exist_ok=True)
(build_root / "exclude-report.json").write_text(result.stdout, encoding="utf-8")
env = os.environ.copy()
env["PYINSTALLER_EXCLUDES"] = json.dumps(sorted(set(report["excludes"]) | {"pytest", "ruff", "PyInstaller"}))
subprocess.run([sys.executable, "-m", "PyInstaller", "--clean", "--noconfirm",
"--workpath", str(build_root / "work"), "--distpath", str(root / "dist"),
str(root / (app_name + ".spec"))], cwd=root, env=env, check=True)

# Notices must also be visible beside the EXE in the distributable Onedir folder.
import shutil
for notice in ("LICENSE", "THIRD_PARTY_LICENSES.txt", "PRIVACY_POLICY.md", "SUPPORT.md"):
shutil.copy2(root / notice, root / "dist" / app_name / notice)
69 changes: 69 additions & 0 deletions src/core/properties_details.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Bounded subprocess queries for properties, without Qt or GUI-thread reads."""
import json
import os
from pathlib import Path
from core.file_attributes import is_cloud_placeholder

MAX_ENTRIES = 100_000

def _folder_details(folder_path, max_files=MAX_ENTRIES):
files_count = dirs_count = total = 0
partial = False
def inaccessible(error):
nonlocal partial
partial = True
for root, dirs, files in os.walk(folder_path, followlinks=False, onerror=inaccessible):
dirs_count += len(dirs)
traversable = []
for name in dirs:
path = os.path.join(root, name)
if (os.path.islink(path) or getattr(os.path, "isjunction", lambda p: False)(path)
or is_cloud_placeholder(path)):
partial = True
else:
traversable.append(name)
dirs[:] = traversable
for name in files:
files_count += 1
try:
total += os.lstat(os.path.join(root, name)).st_size
except OSError:
partial = True
if files_count + dirs_count >= max_files:
partial = True
break
if files_count + dirs_count >= max_files:
partial = True
break
return {"files": files_count, "folders": dirs_count, "bytes": total, "partial": partial}

def calculate_folder_stats(folder_path, max_files=MAX_ENTRIES):
result = _folder_details(folder_path, max_files)
return result["files"], result["folders"], result["bytes"]

def query_details(kind, target):
if is_cloud_placeholder(target):
raise ValueError("Nur online verfügbar. Datei zuerst lokal verfügbar machen.")
if kind == "folder":
if not os.path.isdir(target):
raise NotADirectoryError(target)
return _folder_details(target)
if kind == "text":
# Bound the read even if the file grows after the metadata check.
with open(target, "rb") as handle:
raw = handle.read(5 * 1024 * 1024 + 1)
if len(raw) > 5 * 1024 * 1024:
raise ValueError("Datei > 5 MB")
text = raw.decode("utf-8", errors="ignore")
return {"lines": len(text.splitlines()), "words": len(text.split()), "chars": len(text)}
raise ValueError("Unknown properties query")

def details_query_main(kind, target, output):
try:
payload = {"result": query_details(kind, target)}
code = 0
except Exception as exc:
payload = {"error": str(exc)}
code = 1
Path(output).write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8")
return code
3 changes: 3 additions & 0 deletions src/core/ui_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ def translate_action(self, action: QAction) -> None:
action.setProperty(_RECORD, record)

def _translate_combo(self, combo: QComboBox, record: dict) -> bool:
# Editable choices are persisted user data, including catalog-like names.
if combo.isEditable():
return False
changed = False
blocked = combo.blockSignals(True)
try:
Expand Down
Loading
Loading