#pragma once
#include "core/FilterSettings.h"
#include "core/MergeController.h"
#include "core/ScanController.h"
#include "ui/DiffTableModel.h"
#include "ui/FolderTreeModel.h"
#include "ui/PanelTableView.h"
#include "ui/StatusStrip.h"
#include <functional>
#include <QMainWindow>
#include <QPointer>
#include <QSet>
class QTreeView;
class QComboBox; class QAction; class QTimer;
class QPushButton; class QSplitter; class QShowEvent; class QResizeEvent;
namespace whittle {
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget* parent = nullptr);
protected:
void showEvent(QShowEvent*) override;
void resizeEvent(QResizeEvent*) override;
private slots:
void onScanButton();
void onScan();
void onUsbChanged();
void onReset();
void onMerge();
void onEject();
void onSettings();
void onSaveScheme();
void onSchemeActivated(int index);
void refreshUsbList();
void pollUsbDrives();
void onProgress(int folders, int files, qint64 bytes);
void onResults(whittle::DiffResult result,
whittle::FileMap sourceMap, whittle::FileMap usbMap);
void onUsbContextMenu(const QPoint& pos);
void onCanceled();
void cancelScan();
void onMergeProgress(QString rel, qint64 bytesDone, int filesDone);
void onMergeSkipped(QString rel, int reason);
void onMergeDeviceLost();
void onMergeDone(bool canceled);
void cancelMerge();
private:
using UdisksHandler = std::function<void(int exitCode, QString output)>;
QWidget* buildLeftPanel();
QWidget* buildMidPanel();
QWidget* buildUsbPanel();
void refreshSchemeCombo(const QString& select = QString());
void applyScheme(const QString& name);
QString schemeLabel(const QString& name) const;
void updateSchemeLabel();
void setSchemeDirty(bool dirty);
void clearLoadedScheme();
void startScan(const QStringList& roots, bool recursive, const QString& usb);
void applySplitProportions();
void runUdisks(const QStringList& args, UdisksHandler done);
void finishEject(const QString& message, bool unmounted);
void startMerge(QList<FileRecord> items);
void recompareFromCache();
void updateCounts();
void expandToPaths(const QStringList& paths);
void stepExpand();
bool revealPath(const QString& path);
void updateActionStates();
void setScanning(bool on);
QString currentUsbMount() const;
FolderTreeModel* m_treeModel = nullptr;
DiffTableModel* m_midModel = nullptr;
DiffTableModel* m_usbModel = nullptr;
QTreeView* m_tree = nullptr;
PanelTableView* m_midView = nullptr;
PanelTableView* m_usbView = nullptr;
QComboBox* m_schemeCombo = nullptr;
QWidget* m_schemeHeader = nullptr;
QPushButton* m_ejectBtn = nullptr;
QPushButton* m_saveSchemeBtn = nullptr;
QPushButton* m_resetBtn = nullptr;
QSplitter* m_split = nullptr;
QSplitter* m_panelSplit = nullptr;
StatusStrip* m_status = nullptr;
QWidget* m_midHeader = nullptr;
QPushButton* m_scanBtn = nullptr;
QPushButton* m_mergeBtn = nullptr;
QComboBox* m_usbCombo = nullptr;
QWidget* m_usbHeader = nullptr;
QPushButton* m_settingsBtn = nullptr;
QPushButton* m_quitBtn = nullptr;
QTimer* m_usbPoll = nullptr;
QStringList m_usbSignature;
bool m_usbFirstBuild = true;
bool m_userSplit = false;
bool m_ejecting = false;
QString m_loadedScheme;
bool m_schemeDirty = false;
bool m_applyingScheme = false;
QStringList m_expandPending;
QString m_expandScrollTo;
QPointer<ScanController> m_controller;
bool m_scanning = false;
QPointer<MergeController> m_merger;
bool m_merging = false;
bool m_deviceLost = false;
QSet<QString> m_mergeSkipped;
qint64 m_mergeTotalBytes = 0;
qint64 m_skippedBytes = 0;
qint64 m_mergedBytes = 0;
int m_mergedFiles = 0;
int m_mergeErrors = 0;
FileMap m_sourceMap;
FileMap m_usbMap;
QList<FileRecord> m_lastMerge;
QString m_lastUsbMount;
QStringList m_lastRoots;
bool m_lastRecursive = true;
QSet<QString> m_lastExcluded;
QStringList m_pendingRoots;
bool m_pendingRecursive = true;
QSet<QString> m_pendingExcluded;
QString m_pendingUsb;
bool m_postMergeMode = false;
QSet<QString> m_postMergeSkipped;
int m_countFolders = 0;
int m_countFiles = 0;
int m_countNew = 0;
int m_countDiff = 0;
qint64 m_countBytes = 0;
qint64 m_newBytes = 0;
qint64 m_diffBytes = 0;
FilterSettings m_settings;
};
}