17#include <QQmlImageProviderBase>
46void syncRootObjectSize(QQuickView* quickView, QWidget* hostWidget) {
47 if (!quickView || !hostWidget || !quickView->rootObject())
50 QObject* root = quickView->rootObject();
54 hostWidget->height());
60 std::shared_ptr<core::ports::diagnostics::IErrorReporter> errorReporter,
62 : QMainWindow(parent), errorReporter_(std::move(errorReporter)) {
69 setCentralWidget(m_quickContainer);
76void MainWindow::setupQuickHost() {
77 if (m_quickView || m_quickContainer)
80 m_quickView =
new QQuickView();
81 m_quickView->setResizeMode(QQuickView::SizeRootObjectToView);
84 m_quickContainer = QWidget::createWindowContainer(m_quickView,
this);
85 m_quickContainer->setSizePolicy(QSizePolicy::Expanding,
86 QSizePolicy::Expanding);
87 m_quickContainer->setMinimumSize(0, 0);
88 m_quickContainer->setAcceptDrops(
true);
89 m_quickContainer->installEventFilter(
this);
92void MainWindow::setupUiContext() {
93 if (!m_quickView || !m_quickView->rootContext())
97 m_quickView->rootContext()->setContextProperty(
101 const auto services =
103 actions_ = services.actions;
104 workspaceStore_ = services.workspaceStore;
105 workspaceCommands_ = services.workspaceCommands;
106 workspaceSelection_ = services.workspaceSelection;
107 workspaceSelectors_ = services.workspaceSelectors;
108 settings_ = services.settings;
109 status_ = services.status;
111 setupAutosaveTimer();
114 appContext_->setActions(services.actions);
115 appContext_->setNavigation(services.navigation);
116 appContext_->setFileSystemBrowser(services.fileSystemBrowser);
117 appContext_->setLanguageService(services.languageService);
118 appContext_->setStatus(services.status);
120 appContext_->setIsDebugBuild(
true);
122 appContext_->setIsDebugBuild(
false);
127void MainWindow::setupActionRouting() {
129 {actions_,
nullptr, workspaceStore_,
130 workspaceCommands_, workspaceSelection_,
131 workspaceSelectors_,
nullptr,
nullptr,
139void MainWindow::setupQmlRuntime() {
140 auto* engine = m_quickView ? m_quickView->engine() :
nullptr;
145void MainWindow::prepareForQmlShutdown() {
146 if (qmlShutdownPrepared_ || (!m_quickView && !m_quickContainer))
149 qmlShutdownPrepared_ =
true;
150 auto* quickView = m_quickView;
151 auto* quickContainer = m_quickContainer;
152 m_quickView =
nullptr;
153 m_quickContainer =
nullptr;
156 quickContainer->removeEventFilter(
this);
157 if (quickView && !quickView->source().isEmpty())
158 quickView->setSource(QUrl());
159 if (quickContainer && centralWidget() == quickContainer)
161 if (quickContainer) {
162 quickContainer->hide();
163 quickContainer->setParent(
nullptr);
164 delete quickContainer;
165 }
else if (quickView) {
171 prepareForQmlShutdown();
175 QQmlImageProviderBase* provider) {
178 if (!m_quickView->engine())
180 m_quickView->engine()->addImageProvider(
id, provider);
186 if (!source.isEmpty() && m_quickView->source() == source)
189 if (source.isEmpty()) {
193 m_quickView, QUrl(QStringLiteral(
"module:FossRedder/Main")),
194 errorReporter_.get());
196 m_quickView->setSource(source);
198 errorReporter_.get());
200 syncRootObjectSize(m_quickView, m_quickContainer);
204 return m_quickView ? m_quickView->engine() :
nullptr;
208 if (obj == m_quickContainer && ev->type() == QEvent::Resize) {
209 syncRootObjectSize(m_quickView, m_quickContainer);
212 if (obj == m_quickContainer) {
213 const auto outcome = dropHandler_.handle(ev);
214 if (outcome.handled) {
215 if (ev->type() == QEvent::Drop && outcome.accepted && actions_) {
217 errorReporter_.get(),
221 emit actions_->importFilesDropped(outcome.files);
222 if (outcome.files.size() == 1)
223 emit actions_->importFileDropped(outcome.files.first());
228 return QMainWindow::eventFilter(obj, ev);
231void MainWindow::setupAutosaveTimer() {
232 if (!autosaveTimer_) {
233 autosaveTimer_ =
new QTimer(
this);
234 connect(autosaveTimer_, &QTimer::timeout,
this, [
this]() {
235 if (!workspaceStore_ || workspaceStore_->
currentPath().isEmpty()) {
239 errorReporter_.get(),
241 "Periodic autosave requested");
247 if (autosaveTimer_) {
248 autosaveTimer_->stop();
254 &MainWindow::applyAutosaveSchedule, Qt::UniqueConnection);
256 &MainWindow::applyAutosaveSchedule, Qt::UniqueConnection);
257 applyAutosaveSchedule();
260void MainWindow::applyAutosaveSchedule() {
261 if (!autosaveTimer_ || !settings_) {
265 const int minutes = settings_->autosaveIntervalMinutes();
267 autosaveTimer_->stop();
271 const int intervalMs = minutes * 60 * 1000;
272 if (autosaveTimer_->isActive() && autosaveTimer_->interval() == intervalMs) {
276 autosaveTimer_->start(intervalMs);
280 if (closeWorkflow_.allowImmediateClose(event)) {
281 prepareForQmlShutdown();
282 QMainWindow::closeEvent(event);
286 if (!settings_ || !settings_->autosaveOnClose()) {
288 errorReporter_.get(),
290 "Main window close requested; autosave on close disabled");
291 prepareForQmlShutdown();
293 QMainWindow::closeEvent(event);
298 errorReporter_.get(),
300 "Main window close requested; triggering save workflow");
301 closeWorkflow_.requestClose(event, [
this]() {
307 if (!closeWorkflow_.handleStorageOperationSucceeded(
309 QMetaObject::invokeMethod(
314 Qt::QueuedConnection);
320 errorReporter_.get(),
322 "Pending close save finished; closing main window");
326 const QString& error) {
327 if (!closeWorkflow_.handleStorageOperationFailed(
331 const QString message =
334 status_->setText(message);
337 errorReporter_.get(),
339 "Pending close save failed; keeping main window open",
341 {{kError, ui::strings::toStdString(message)}});
343 QMetaObject::invokeMethod(
348 Qt::QueuedConnection);
351void MainWindow::onAbout() {
352 QMessageBox dialog(
this);
359 dialog.setStandardButtons(QMessageBox::Ok);
Declares QAction wrappers exposed to the UI layer and QML.
Declares the QML application context object.
Defines UI-specific runtime constants that are not shared with core.
Declares the structured diagnostics reporting port.
Main window declaration for the UI application.
Declarations for the UI MainWindowContext component.
Declarations for the UI MainWindowTrace component.
Declarations for the UI Origins component.
QML registration and context property name constants used by the UI.
QML runtime diagnostics reporting helpers.
QML runtime setup helpers for registering types and configuring the engine.
Declares lightweight conversions between common Qt string types and standard strings.
Provides translated C++ UI strings for shell, workflow, adapter and view model code.
void closeEvent(QCloseEvent *event) override
void loadQml(const QUrl &source=QUrl())
void handleStorageOperationSucceeded(const QString &operation)
void handleStorageOperationFailed(const QString &operation, const QString &error)
QQmlEngine * qmlEngine() const noexcept
bool eventFilter(QObject *obj, QEvent *ev) override
void addImageProvider(const QString &id, QQmlImageProviderBase *provider)
MainWindow(std::shared_ptr< core::ports::diagnostics::IErrorReporter > errorReporter, QWidget *parent=nullptr)
void stateChanged()
Emitted when any settings value changes.
void autosaveIntervalMinutesChanged()
QString currentPath() const
Returns the current workspace path.
void configureRuntime(QQmlEngine *engine)
Configure QQmlEngine import paths and plugin library paths.
void reportQmlLoadErrors(QQuickView *quickView, const QUrl &source, core::ports::diagnostics::IErrorReporter *reporter)
Reports QQuickView load errors through the structured error reporter.
void registerTypes()
Register QML types and meta objects used by the application.
const auto kSaveFile
Operation key emitted for save-file actions.
const auto kApplicationDisplayName
Human-readable application name shown by the UI shell.
const auto kAppIconResource
Resource URL of the application icon embedded into the executable.
constexpr int kAboutDialogIconSize
Pixel size used for the About dialog application icon.
constexpr int kMainWindowDefaultWidth
Default width of the widget-hosted desktop main window.
constexpr int kMainWindowDefaultHeight
Default height of the widget-hosted desktop main window.
constexpr auto kActionRouting
constexpr auto kCloseSucceeded
constexpr auto kCloseFailed
constexpr auto kMainTypeName
constexpr auto kAppContextTypeName
QString aboutTitle()
About dialog window title.
QString aboutBody()
About dialog body copy.
QString aboutHeadline()
About dialog headline.
QString storageSaveFailed()
Error text for failed storage save operations.
void reportMainWindowFlow(core::ports::diagnostics::IErrorReporter *reporter, const char *origin, std::string message, core::errors::ErrorSeverity severity=core::errors::ErrorSeverity::Info, core::errors::ErrorContext context={})
Emits a structured main-window flow diagnostic.
MainWindowServices installMainWindowContext(QQmlEngine *qmlEngine, QObject *parent)
Creates shell services used by the main window and QML context.
core::errors::ErrorContext makeFileListContext(const QStringList &files)
Builds trace context for a list of selected or dropped files.
void wireMainWindowActions(MainWindow &window, const MainWindowServices &services, const std::shared_ptr< core::ports::diagnostics::IErrorReporter > &errorReporter, const std::function< void()> &showAbout)
Wires main window actions to dialogs, status text and window signals.