main_window.py 8.2 KB
Newer Older
之一Yo's avatar
之一Yo 已提交
1
# coding: utf-8
之一Yo's avatar
之一Yo 已提交
2
from typing import List
3 4
from PyQt5.QtCore import Qt, pyqtSignal, QEasingCurve, QUrl
from PyQt5.QtGui import QIcon, QDesktopServices
之一Yo's avatar
之一Yo 已提交
5
from PyQt5.QtWidgets import QApplication, QHBoxLayout, QFrame, QWidget
之一Yo's avatar
之一Yo 已提交
6

之一Yo's avatar
之一Yo 已提交
7
from qfluentwidgets import (NavigationInterface, NavigationItemPosition, MessageBox,
之一Yo's avatar
之一Yo 已提交
8
                            isDarkTheme, PopUpAniStackedWidget)
之一Yo's avatar
之一Yo 已提交
9 10 11 12
from qfluentwidgets import FluentIcon as FIF
from qframelesswindow import FramelessWindow

from .title_bar import CustomTitleBar
之一Yo's avatar
之一Yo 已提交
13 14
from .gallery_interface import GalleryInterface
from .home_interface import HomeInterface
之一Yo's avatar
之一Yo 已提交
15
from .basic_input_interface import BasicInputInterface
之一Yo's avatar
之一Yo 已提交
16
from .date_time_interface import DateTimeInterface
之一Yo's avatar
之一Yo 已提交
17
from .dialog_interface import DialogInterface
之一Yo's avatar
之一Yo 已提交
18
from .layout_interface import LayoutInterface
之一Yo's avatar
之一Yo 已提交
19
from .icon_interface import IconInterface
之一Yo's avatar
之一Yo 已提交
20 21 22 23 24
from .material_interface import MaterialInterface
from .menu_interface import MenuInterface
from .scroll_interface import ScrollInterface
from .status_info_interface import StatusInfoInterface
from .setting_interface import SettingInterface, cfg
之一Yo's avatar
之一Yo 已提交
25
from .text_interface import TextInterface
之一Yo's avatar
之一Yo 已提交
26
from .view_interface import ViewInterface
27
from ..common.config import SUPPORT_URL
之一Yo's avatar
之一Yo 已提交
28 29
from ..components.avatar_widget import AvatarWidget
from ..common.icon import Icon
之一Yo's avatar
之一Yo 已提交
30
from ..common.signal_bus import signalBus
31
from ..common.style_sheet import StyleSheet
之一Yo's avatar
之一Yo 已提交
32
from ..common import resource
之一Yo's avatar
之一Yo 已提交
33 34 35 36 37 38 39 40 41 42


class StackedWidget(QFrame):
    """ Stacked widget """

    currentWidgetChanged = pyqtSignal(QWidget)

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.hBoxLayout = QHBoxLayout(self)
之一Yo's avatar
之一Yo 已提交
43
        self.view = PopUpAniStackedWidget(self)
之一Yo's avatar
之一Yo 已提交
44 45 46 47 48 49 50 51 52 53 54

        self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
        self.hBoxLayout.addWidget(self.view)

        self.view.currentChanged.connect(
            lambda i: self.currentWidgetChanged.emit(self.view.widget(i)))

    def addWidget(self, widget):
        """ add widget to view """
        self.view.addWidget(widget)

之一Yo's avatar
之一Yo 已提交
55
    def setCurrentWidget(self, widget, popOut=False):
之一Yo's avatar
之一Yo 已提交
56
        widget.verticalScrollBar().setValue(0)
之一Yo's avatar
之一Yo 已提交
57 58 59
        if not popOut:
            self.view.setCurrentWidget(widget, duration=300)
        else:
之一Yo's avatar
之一Yo 已提交
60 61
            self.view.setCurrentWidget(
                widget, True, False, 200, QEasingCurve.InQuad)
之一Yo's avatar
之一Yo 已提交
62

之一Yo's avatar
之一Yo 已提交
63 64
    def setCurrentIndex(self, index, popOut=False):
        self.setCurrentWidget(self.view.widget(index), popOut)
之一Yo's avatar
之一Yo 已提交
65 66 67 68 69 70 71 72 73 74 75 76 77 78


class MainWindow(FramelessWindow):

    def __init__(self):
        super().__init__()
        self.setTitleBar(CustomTitleBar(self))
        self.hBoxLayout = QHBoxLayout(self)
        self.widgetLayout = QHBoxLayout()

        self.stackWidget = StackedWidget(self)
        self.navigationInterface = NavigationInterface(self, True, True)

        # create sub interface
之一Yo's avatar
之一Yo 已提交
79
        self.homeInterface = HomeInterface(self)
之一Yo's avatar
之一Yo 已提交
80
        self.iconInterface = IconInterface(self)
之一Yo's avatar
之一Yo 已提交
81
        self.basicInputInterface = BasicInputInterface(self)
之一Yo's avatar
之一Yo 已提交
82
        self.dateTimeInterface = DateTimeInterface(self)
之一Yo's avatar
之一Yo 已提交
83
        self.dialogInterface = DialogInterface(self)
之一Yo's avatar
之一Yo 已提交
84 85 86
        self.layoutInterface = LayoutInterface(self)
        self.menuInterface = MenuInterface(self)
        self.materialInterface = MaterialInterface(self)
之一Yo's avatar
之一Yo 已提交
87
        self.scrollInterface = ScrollInterface(self)
之一Yo's avatar
之一Yo 已提交
88
        self.statusInfoInterface = StatusInfoInterface(self)
之一Yo's avatar
之一Yo 已提交
89
        self.settingInterface = SettingInterface(self)
之一Yo's avatar
之一Yo 已提交
90
        self.textInterface = TextInterface(self)
之一Yo's avatar
之一Yo 已提交
91
        self.viewInterface = ViewInterface(self)
之一Yo's avatar
之一Yo 已提交
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

        # initialize layout
        self.initLayout()

        # add items to navigation interface
        self.initNavigation()

        self.initWindow()

    def initLayout(self):
        self.hBoxLayout.setSpacing(0)
        self.hBoxLayout.setContentsMargins(0, 0, 0, 0)
        self.hBoxLayout.addWidget(self.navigationInterface)
        self.hBoxLayout.addLayout(self.widgetLayout)
        self.hBoxLayout.setStretchFactor(self.widgetLayout, 1)

        self.widgetLayout.addWidget(self.stackWidget)
        self.widgetLayout.setContentsMargins(0, 48, 0, 0)

之一Yo's avatar
之一Yo 已提交
111
        signalBus.switchToSampleCard.connect(self.switchToSample)
之一Yo's avatar
之一Yo 已提交
112
        signalBus.supportSignal.connect(self.onSupport)
之一Yo's avatar
之一Yo 已提交
113

之一Yo's avatar
之一Yo 已提交
114 115 116 117 118
        self.navigationInterface.displayModeChanged.connect(
            self.titleBar.raise_)
        self.titleBar.raise_()

    def initNavigation(self):
之一Yo's avatar
之一Yo 已提交
119
        # add navigation items
之一Yo's avatar
之一Yo 已提交
120 121 122 123
        self.addSubInterface(
            self.homeInterface, 'homeInterface', FIF.HOME, self.tr('Home'), NavigationItemPosition.TOP)
        self.addSubInterface(
            self.iconInterface, 'iconInterface', Icon.EMOJI_TAB_SYMBOLS, self.tr('Icons'), NavigationItemPosition.TOP)
之一Yo's avatar
之一Yo 已提交
124 125
        self.navigationInterface.addSeparator()

之一Yo's avatar
之一Yo 已提交
126 127
        self.addSubInterface(
            self.basicInputInterface, 'basicInputInterface', FIF.CHECKBOX, self.tr('Basic input'))
之一Yo's avatar
之一Yo 已提交
128 129
        self.addSubInterface(
            self.dateTimeInterface, 'dateTimeInterface', FIF.DATE_TIME, self.tr('Date & time'))
之一Yo's avatar
之一Yo 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
        self.addSubInterface(
            self.dialogInterface, 'dialogInterface', FIF.MESSAGE, self.tr('Dialogs'))
        self.addSubInterface(
            self.layoutInterface, 'layoutInterface', FIF.LAYOUT, self.tr('Layout'))
        self.addSubInterface(
            self.materialInterface, 'materialInterface', FIF.PALETTE, self.tr('Material'))
        self.addSubInterface(
            self.menuInterface, 'menuInterface', Icon.MENU, self.tr('Menus'))
        self.addSubInterface(
            self.scrollInterface, 'scrollInterface', FIF.SCROLL, self.tr('Scrolling'))
        self.addSubInterface(
            self.statusInfoInterface, 'statusInfoInterface', FIF.CHAT, self.tr('Status & info'))
        self.addSubInterface(
            self.textInterface, 'textInterface', Icon.TEXT, self.tr('Text'))
        self.addSubInterface(
            self.viewInterface, 'viewInterface', Icon.GRID, self.tr('View'))
之一Yo's avatar
之一Yo 已提交
146 147 148 149

        # add custom widget to bottom
        self.navigationInterface.addWidget(
            routeKey='avatar',
之一Yo's avatar
之一Yo 已提交
150
            widget=AvatarWidget(':/gallery/images/shoko.png'),
之一Yo's avatar
之一Yo 已提交
151
            onClick=self.onSupport,
之一Yo's avatar
之一Yo 已提交
152
            position=NavigationItemPosition.BOTTOM
之一Yo's avatar
之一Yo 已提交
153
        )
之一Yo's avatar
之一Yo 已提交
154 155
        self.addSubInterface(
            self.settingInterface, 'settingInterface', FIF.SETTING, self.tr('Settings'), NavigationItemPosition.BOTTOM)
之一Yo's avatar
之一Yo 已提交
156 157 158

        #!IMPORTANT: don't forget to set the default route key if you enable the return button
        self.navigationInterface.setDefaultRouteKey(
之一Yo's avatar
之一Yo 已提交
159
            self.homeInterface.objectName())
之一Yo's avatar
之一Yo 已提交
160 161 162

        self.stackWidget.currentWidgetChanged.connect(
            lambda w: self.navigationInterface.setCurrentItem(w.objectName()))
之一Yo's avatar
之一Yo 已提交
163
        self.navigationInterface.setCurrentItem(
之一Yo's avatar
之一Yo 已提交
164
            self.homeInterface.objectName())
之一Yo's avatar
之一Yo 已提交
165 166
        self.stackWidget.setCurrentIndex(0)

之一Yo's avatar
之一Yo 已提交
167
    def addSubInterface(self, interface: QWidget, objectName: str, icon, text: str, position=NavigationItemPosition.SCROLL):
之一Yo's avatar
之一Yo 已提交
168 169
        """ add sub interface """
        interface.setObjectName(objectName)
之一Yo's avatar
之一Yo 已提交
170
        self.stackWidget.addWidget(interface)
之一Yo's avatar
之一Yo 已提交
171 172 173 174 175
        self.navigationInterface.addItem(
            routeKey=objectName,
            icon=icon,
            text=text,
            onClick=lambda t: self.switchTo(interface, t),
176 177
            position=position,
            tooltip=text
之一Yo's avatar
之一Yo 已提交
178 179
        )

之一Yo's avatar
之一Yo 已提交
180
    def initWindow(self):
之一Yo's avatar
之一Yo 已提交
181
        self.resize(960, 780)
之一Yo's avatar
之一Yo 已提交
182
        self.setMinimumWidth(760)
之一Yo's avatar
之一Yo 已提交
183
        self.setWindowIcon(QIcon(':/gallery/images/logo.png'))
之一Yo's avatar
之一Yo 已提交
184 185 186 187 188 189 190
        self.setWindowTitle('PyQt-Fluent-Widgets')
        self.titleBar.setAttribute(Qt.WA_StyledBackground)

        desktop = QApplication.desktop().availableGeometry()
        w, h = desktop.width(), desktop.height()
        self.move(w//2 - self.width()//2, h//2 - self.height()//2)

191
        StyleSheet.MAIN_WINDOW.apply(self)
之一Yo's avatar
之一Yo 已提交
192

之一Yo's avatar
之一Yo 已提交
193 194
    def switchTo(self, widget, triggerByUser=True):
        self.stackWidget.setCurrentWidget(widget, not triggerByUser)
之一Yo's avatar
之一Yo 已提交
195 196 197 198 199

    def resizeEvent(self, e):
        self.titleBar.move(46, 0)
        self.titleBar.resize(self.width()-46, self.titleBar.height())

之一Yo's avatar
之一Yo 已提交
200 201
    def onSupport(self):
        QDesktopServices.openUrl(QUrl(SUPPORT_URL))
之一Yo's avatar
之一Yo 已提交
202 203 204 205 206 207 208

    def switchToSample(self, routeKey, index):
        """ switch to sample """
        interfaces = self.findChildren(GalleryInterface)
        for w in interfaces:
            if w.objectName() == routeKey:
                self.stackWidget.setCurrentWidget(w)
之一Yo's avatar
之一Yo 已提交
209
                w.scrollToCard(index)