# StorageIQ

StorageIQ is a modern Windows disk space analyzer built with Python and PySide6.

It scans drives or folders, summarizes storage usage, shows largest folders and files, groups usage by file type, and stores scan history in SQLite. File removal is intentionally limited to the Windows Recycle Bin and always requires confirmation.

Current release: **1.6.0**

## Features

- Scan full drives or custom folders
- Dashboard with polished storage, free space, scanned file/folder, and cleanup summary cards
- Storage Explorer interactive treemap with drill-down, breadcrumbs, search, filters, and detail actions
- Sortable largest folders and largest files views
- Global search with file category filters
- File type analysis chart with percentages and color legend
- AI Cleanup Advisor with rule-based, safety-first cleanup recommendations
- Duplicate Finder with staged size/hash detection and safe Recycle Bin cleanup
- Storage Timeline with historical charts, scan comparison, and growth insights
- Background scanning with progress and cancellation
- SQLite scan history with reopen support
- Safe file actions: open file, open containing folder, move to Recycle Bin
- Action logging in SQLite
- Crash-safe diagnostic logging to `%LOCALAPPDATA%\StorageIQ\logs\storageiq.log`
- Professional Windows installer framework with manual update checks, diagnostics center, and diagnostic bundles

## UI Polish

StorageIQ uses a modern dark interface with custom branding, a dedicated application icon, icon-led sidebar navigation, consistent spacing, stronger visual hierarchy, and dashboard cards designed for quick scanning. Empty-state screens guide first-time use, while the scan loading panel and status bar keep progress visible during long scans.

Tables use larger rows, clearer selection color, hover states, and reduced grid clutter. The Largest Files page surfaces direct action buttons for opening files, revealing folders, and moving files to the Recycle Bin, while unusually large files are visually highlighted.

## Bulk File Management

The Largest Files page supports selecting several files and moving them to the
Windows Recycle Bin together (never permanent deletion). The bulk logic lives in
`storageiq/bulk/`, deliberately kept mostly Qt-free so it is unit-tested with a
mocked Recycle Bin adapter.

**Selection** uses standard Windows behavior: click, Ctrl-click, Shift-click,
Ctrl+A (all *eligible* visible rows), and Escape or "Clear Selection" to clear.
Selection is tied to a normalized, case-insensitive **path identity**, never a
row number, so sorting never redirects the selection. Selections persist across
filtering: files hidden by the active filter stay selected but are reported
separately in the selection bar ("N hidden by filter"), and the confirmation
dialog lists every path, so a hidden file is never acted on silently.

The **selection bar** shows the count, combined size, hidden-by-filter and
ineligible counts, and offers Clear Selection, Show in Folder (opens the shared
folder, or up to five distinct folders otherwise), Copy Paths (one absolute path
per line), and Move to Recycle Bin.

**Eligibility** is centralized in `storageiq/bulk/eligibility.py`. A file is
rejected (and left untouched) when it is a directory, an aggregate treemap item,
missing, not a regular file, a symlink/junction/reparse point, outside the scan
roots, in a protected Windows/application location, a StorageIQ database/log/
program file, a duplicate within the selection, changed since the scan (stale),
or Steam-managed (identified from local `appmanifest` metadata — remove those via
Steam). Comparisons are normalized and case-insensitive; safety never relies on
file extensions alone.

**Stale protection**: a scan is only a past observation, so every path is
revalidated immediately before acting. Size and last-modified time are compared
against the scanned record; if the file changed materially it is skipped and
reported, so a replacement file at the same path is never silently recycled.

The **bulk recycle** works from an immutable snapshot of the confirmed selection,
runs off the UI thread, shows progress, supports cancellation between files
(cancellation is never reported as success), and never rolls back earlier
successes when a later file fails. Only successfully recycled files are removed
from the current results; failed, skipped, and cancelled files stay selected for
retry. After success, the dashboard, file-type totals, largest-files/folders, and
treemap are reconciled locally without a full rescan (folder aggregates are
best-effort, so a rescan is still the source of exact folder totals). A completion
summary reports recycled/failed/skipped/cancelled counts with sanitized,
path-free failure reasons and a copy-details button. Pending destructive intent
is never persisted across an app restart.

This milestone is **files only** (no directories), **Recycle Bin only** (no
permanent deletion), with no wildcard/recursive removal, no shell commands built
from paths, no symlink following, and no elevation.

## File Category Breakdown

StorageIQ separates file *classification* from file-category *presentation*:

- **Classification** lives in `storageiq/scanner/engine.py` (`CATEGORY_EXTENSIONS` and `categorize_extension`). It decides which category an extension belongs to: Videos, Images, Documents, Archives, Executables, or the `Other` fallback.
- **Presentation** lives in `storageiq/categories.py`, the single source of truth for how each category looks (canonical id, display label, stable color, ordering). Every category-based view — treemap, File Types donut, legends, tables, proportional size bars, and the dashboard composition bar — resolves colors and labels through this module.

**Canonical color contract:** a category keeps the same color in every view and for every dataset. Colors are never assigned by ranking or current sort order (the File Types donut previously colored by rank, so a category's color drifted as data changed — that is fixed). Any unknown, empty, or missing category deterministically resolves to `Other`.

| Category | Color |
| --- | --- |
| Videos | `#8B5CF6` |
| Images | `#22C55E` |
| Documents | `#3B82F6` |
| Archives | `#F97316` |
| Executables | `#EF4444` |
| Other | `#6B7280` |

## Theme Behavior for Custom-Painted Widgets

Standard widgets are themed by the Qt stylesheet, but custom-painted widgets (treemap, File Types donut, timeline chart, dashboard composition bar, and the table size-bar delegate) draw with `QPainter` and cannot read a stylesheet. They take a semantic palette from `storageiq/theme.py` (`ChartTheme`, with dark and light variants) via a `set_theme()` method. `MainWindow.apply_chart_theme()` pushes the active palette to every mounted chart whenever the theme changes, so switching Dark/Light updates already-visible charts immediately. Category tile colors stay constant across themes; only surfaces, gridlines, borders, and label contrast adapt. Treemap tile labels pick dark or light text based on the tile's luminance so they stay readable on any category color. The selected theme persists in `QSettings` exactly as before.

## "Other small files" Aggregate

In the treemap, files whose tiles would be too thin to render (below a fixed on-axis pixel threshold) are folded into a single deterministic "Other small files" tile instead of disappearing. The aggregate:

- shows the combined size and item count, and is drawn with a dashed border so it reads as a summary, not a real file or folder;
- is always a contiguous tail of the smallest items (sizes are laid out largest-first), so it never swallows an individually visible large file;
- preserves the total represented size — its size equals exactly the sum of the items it folds in, with no double counting;
- is deterministic for the same input and viewport;
- forms only when at least two items would collapse (a lone small item is still shown individually);
- is computed after filtering/search, so it stays consistent with the current view. It is inert: it cannot be opened, drilled into, or recycled.

## Dashboard Space Accounting

The dashboard "Drive Utilization" panel is a segmented composition bar reconciled to the whole drive. Scanned category sizes describe only the scanned scope (a subset of used space), so the bar never implies that category totals equal physical drive usage. Segments always sum to the drive total:

- **categorized** — sum of scanned category sizes, capped at used space, colored with the canonical category palette;
- **unscanned / system** — used space not covered by the current scan;
- **reserved / other** — filesystem overhead (`total - used - free`);
- **free** — reported free space.

Utilization drives a documented warning state: at or above **80%** the bar shows an amber "low free space" state, and at or above **90%** a red "critical" state, with an accessible text summary and per-segment tooltips rather than color alone. Clicking the bar opens the full File Types breakdown.

## From Breakdown to Files (Drill-Down)

Visual breakdowns lead to the underlying files, reusing the existing Largest Files search/filter infrastructure (no parallel state, no destructive actions):

- Clicking a slice of the File Types donut, a legend row, or double-clicking a File Types table row filters the Largest Files list to that category and navigates there.
- The active category filter is shown as a chip on the Largest Files page with a one-click "Clear filter".
- In the treemap, clicking a tile selects it (enabling the existing Open / Show Folder / Recycle actions) and double-clicking a folder drills in, unchanged.

Deferred: the treemap's own tile selection does not yet cross-navigate to the Largest Files page (it uses the Storage Explorer's in-place detail/actions). This was left as-is to avoid reworking the explorer's navigation model; the donut/legend/table paths cover cross-page drill-down.

## Duplicate Finder

StorageIQ v1.1 adds a Duplicate Finder page. It scans the selected drive or folder by grouping files by size first, then hashing only same-size candidates. Duplicate groups show filename, full path, size, modified date, and SHA-256 hash.

Cleanup remains safety-first: no files are selected automatically, the "Select Older Copies" helper keeps the newest copy in each group, "Recycle Selected" is disabled unless at least one copy remains in every duplicate group, and all cleanup actions are logged to SQLite.

## Storage Explorer

StorageIQ v1.6 adds Storage Explorer, an interactive treemap that turns scan results into an instant visual map of disk usage. Rectangles are sized by storage usage and colored by category: videos, images, archives, documents, executables, and other files.

Hover shows name, size, path, and type. Click selects an item, double-click drills into folders, and right-click opens file, folder, and detail actions. Breadcrumbs, Back, Home, search highlighting, category filters, and minimum-size filtering help users move through large scans quickly.

The treemap renders a virtualized visible subset of the scan snapshot so the UI remains responsive with large folders. Current scans keep up to 100,000 files and folders available for explorer navigation while existing tables remain focused on top results.

## Storage Timeline

StorageIQ v1.2 adds a Storage Timeline page that uses scan history snapshots to chart used space, free space, file count, and folder count over time. The page supports Last 7 Days, Last 30 Days, Last 90 Days, and All Time ranges.

Timeline comparison tools let users compare two scans to identify top growing and shrinking folders. Automatic insights summarize recent scan growth, dominant file type usage, and duplicate cleanup recovery when cleanup size details are available.

## AI Cleanup Advisor

StorageIQ v1.3 adds an AI Cleanup Advisor page. It is not a chatbot and does not send data to an AI service. The advisor uses local rules over scan results, duplicate finder results, file age, file size, file type, and scan history to surface prioritized cleanup opportunities.

Recommendation cards cover large files, old Downloads items, duplicate files, large videos, temporary files, compressed archives, and storage growth alerts. Actions remain manual: users can open files, open folders, view recommendation details, or jump to Duplicate Finder or Storage Timeline for deeper review.

Advisor thresholds for large files, old Downloads age, archive age, and video size can be adjusted from Settings.

## Deployment, Updates, and Diagnostics

StorageIQ v1.6 provides a professional Windows deployment foundation. `storageiq/version.py` is the central source for app name, version, build number, and build date. The app displays this information in the window title, About dialog, Diagnostics page, Settings page, logs, and installer metadata.

The Settings page includes theme selection, Stable/Beta release channel preference, default scan location, advisor thresholds, duplicate detection settings, a manual Check for Updates button, and a Generate Diagnostic Bundle action. Update checks compare the installed version with release metadata and display the current version, latest version, release date, release notes, and status. StorageIQ does not auto-download updates in v1.6.

The Diagnostics Center displays app version, build number, database location, log location, last scan date, historical scan count, duplicate cleanup action count, and advisor recommendation count. Diagnostic bundles are ZIP files containing logs, version info, environment info, configuration, and aggregate scan statistics. They intentionally exclude user files, scan file inventories, and personal documents.

Crash reports are written to `%LOCALAPPDATA%\StorageIQ\logs\crash_reports`. SQLite initialization includes migration backup protection and corrupt database quarantine/recreation so the app can start safely.

## Requirements

- Python 3.11+
- Windows 10/11

Install dependencies:

```powershell
python -m pip install -r requirements.txt
```

## Run

```powershell
python -m storageiq
```

The app database is stored at:

```text
%LOCALAPPDATA%\StorageIQ\storageiq.sqlite3
```

## Tests

```powershell
python -m unittest
```

## Build

```powershell
.\build.ps1
```

The PyInstaller output will be created in `dist\StorageIQ`. If Inno Setup 6 is installed and `ISCC.exe` is available on PATH, the Windows installer is created under `dist\installer`.

Installer source files live in `installer\`. The installer targets Program Files, creates Start Menu shortcuts, optionally creates a Desktop shortcut, registers an Add/Remove Programs uninstall entry, supports clean uninstall, and preserves user data during upgrades and uninstall under:

```text
%LOCALAPPDATA%\StorageIQ
```

Release notes and QA guidance:

- `RELEASE_NOTES.md`
- `docs\QA_CHECKLIST.md`
- `docs\INSTALLER_BUILD.md`

## Safety

StorageIQ never permanently deletes files. The only delete-like action is "Move to Recycle Bin", implemented with `send2trash`, after a confirmation dialog that displays the full path.
