aboutsummaryrefslogtreecommitdiffstats
path: root/examples/demos/documentviewer/mainwindow.py
blob: e9abd0bec150321aa02c5b31de498abc74e5772b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

from PySide6.QtWidgets import (QDialog, QFileDialog, QMainWindow, QMessageBox)
from PySide6.QtCore import (QDir, QFile, QFileInfo, QSettings, Slot)

from ui_mainwindow import Ui_MainWindow
from viewerfactory import ViewerFactory
from recentfiles import RecentFiles
from recentfilemenu import RecentFileMenu


settingsDir = "WorkingDir"
settingsMainWindow = "MainWindow"
settingsViewers = "Viewers"
settingsFiles = "RecentFiles"


ABOUT_TEXT = """A Widgets application to display and print JSON,
text and PDF files. Demonstrates various features to use
in widget applications: Using QSettings, query and save
user preferences, manage file histories and control cursor
behavior when hovering over widgets.

"""


class MainWindow(QMainWindow):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_MainWindow()

        self._currentDir = QDir()
        self._viewer = None
        self._recentFiles = RecentFiles()

        self.ui.setupUi(self)
        self.ui.actionOpen.triggered.connect(self.onActionOpenTriggered)
        self.ui.actionAbout.triggered.connect(self.onActionAboutTriggered)
        self.ui.actionAboutQt.triggered.connect(self.onActionAboutQtTriggered)

        self._recentFiles = RecentFiles(self.ui.actionRecent)
        self._recentFiles.countChanged.connect(self._recentFilesCountChanged)

        self.readSettings()
        self._factory = ViewerFactory(self.ui.viewArea, self)
        viewers = ", ".join(self._factory.viewerNames())
        self.statusBar().showMessage(f'Available viewers: {viewers}')

        menu = RecentFileMenu(self, self._recentFiles)
        self.ui.actionRecent.setMenu(menu)
        menu.fileOpened.connect(self.openFile)
        button = self.ui.mainToolBar.widgetForAction(self.ui.actionRecent)
        if button:
            self.ui.actionRecent.triggered.connect(button.showMenu)

    @Slot(int)
    def _recentFilesCountChanged(self, count):
        self.ui.actionRecent.setText(f"{count} recent files")

    def closeEvent(self, event):
        self.saveSettings()

    @Slot(int)
    def onActionOpenTriggered(self):
        fileDialog = QFileDialog(self, "Open Document",
                                 self._currentDir.absolutePath())
        while (fileDialog.exec() == QDialog.Accepted
               and not self.openFile(fileDialog.selectedFiles()[0])):
            pass

    @Slot(str)
    def openFile(self, fileName):
        file = QFile(fileName)
        if not file.exists():
            nf = QDir.toNativeSeparators(fileName)
            self.statusBar().showMessage(f"File {nf} could not be opened")
            return False

        fileInfo = QFileInfo(file)
        self._currentDir = fileInfo.dir()
        self._recentFiles.addFile(fileInfo.absoluteFilePath())

        # If a viewer is already open, clean it up and save its settings
        self.resetViewer()
        self._viewer = self._factory.viewer(file)
        if not self._viewer:
            nf = QDir.toNativeSeparators(fileName)
            self.statusBar().showMessage(f"File {nf} can't be opened.")
            return False

        self.ui.actionPrint.setEnabled(self._viewer.hasContent())
        self._viewer.printingEnabledChanged.connect(self.ui.actionPrint.setEnabled)
        self.ui.actionPrint.triggered.connect(self._viewer.print_)
        self._viewer.showMessage.connect(self.statusBar().showMessage)

        self._viewer.initViewer(self.ui.actionBack, self.ui.actionForward,
                                self.ui.menuHelp.menuAction(),
                                self.ui.tabWidget)
        self.restoreViewerSettings()
        self.ui.scrollArea.setWidget(self._viewer.widget())
        return True

    @Slot()
    def onActionAboutTriggered(self):
        viewerNames = ", ".join(self._factory.viewerNames())
        mimeTypes = '\n'.join(self._factory.supportedMimeTypes())
        text = ABOUT_TEXT
        text += f"\nThis version has loaded the following plugins:\n{viewerNames}\n"
        text += f"\n\nIt supports the following mime types:\n{mimeTypes}"

        defaultViewer = self._factory.defaultViewer()
        if defaultViewer:
            n = defaultViewer.viewerName()
            text += f"\n\nOther mime types will be displayed with {n}."

        QMessageBox.about(self, "About Document Viewer Demo", text)

    @Slot()
    def onActionAboutQtTriggered(self):
        QMessageBox.aboutQt(self)

    def readSettings(self):
        settings = QSettings()

        # Restore working directory
        if settings.contains(settingsDir):
            self._currentDir = QDir(settings.value(settingsDir))
        else:
            self._currentDir = QDir.current()

        # Restore QMainWindow state
        if settings.contains(settingsMainWindow):
            mainWindowState = settings.value(settingsMainWindow)
            self.restoreState(mainWindowState)

        # Restore recent files
        self._recentFiles.restoreFromSettings(settings, settingsFiles)

    def saveSettings(self):
        settings = QSettings()

        # Save working directory
        settings.setValue(settingsDir, self._currentDir.absolutePath())

        # Save QMainWindow state
        settings.setValue(settingsMainWindow, self.saveState())

        # Save recent files
        self._recentFiles.saveSettings(settings, settingsFiles)

        settings.sync()

    def saveViewerSettings(self):
        if not self._viewer:
            return
        settings = QSettings()
        settings.beginGroup(settingsViewers)
        settings.setValue(self._viewer.viewerName(), self._viewer.saveState())
        settings.endGroup()
        settings.sync()

    def resetViewer(self):
        if not self._viewer:
            return
        self.saveViewerSettings()
        self._viewer.cleanup()

    def restoreViewerSettings(self):
        if not self._viewer:
            return
        settings = QSettings()
        settings.beginGroup(settingsViewers)
        viewerSettings = settings.value(self._viewer.viewerName())
        settings.endGroup()
        if viewerSettings:
            self._viewer.restoreState(viewerSettings)