コード例 #1
0
    def initUI(self):
        QToolTip.setFont(QFont('SansSerif', 10))
        self.setToolTip('This is a <b>QWidget</b> widget.')
        #quitBtn = QPushButton('Quit', self)
        #quitBtn.clicked.connect(self.quitBtnEvent())
        #quitBtn.clicked.connect(QCoreApplication.instance().quit)
        #quitBtn.setToolTip('This is a <b>QPushButton</b> widget.')
        #quitBtn.resize(quitBtn.sizeHint())

        exitAction = QAction(QIcon('application-exit-4.png'), '&Exit', self)
        exitAction.setShortcut('Alt+F4')
        exitAction.setStatusTip('Exit Application')
        exitAction.triggered.connect(qApp.quit)

        menuBar = QMenuBar()
        fileMenu = menuBar.addMenu('&File')
        fileMenu.addAction(exitAction)
        fileMenu.resize(fileMenu.sizeHint())

        toolBar = QToolBar(self)
        toolBar.addAction(exitAction)
        #toolBar.resize(toolBar.sizeHint())
        toolBar.setFixedHeight(60)

        hozLine = QFrame()
        hozLine.setFrameStyle(QFrame.HLine)
        #hozLine.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Expanding)

        statusBar = QStatusBar(self)
        statusBar.showMessage('Ready')

        grid = QGridLayout()
        lbl_1 = QLabel('1,1')
        lbl_2 = QLabel('1,2')
        lbl_3 = QLabel('2,1')
        lbl_4 = QLabel('2,2')
        grid.addWidget(lbl_1, 1, 1)
        grid.addWidget(lbl_2, 1, 2)
        grid.addWidget(lbl_3, 2, 1)
        grid.addWidget(lbl_4, 2, 2)

        vbox = QVBoxLayout()
        vbox.addWidget(menuBar)
        vbox.addWidget(hozLine)
        vbox.addWidget(toolBar)
        # vbox.addWidget(hozLine)
        vbox.addLayout(grid)
        vbox.addStretch(1)
        vbox.addWidget(statusBar)

        self.setLayout(vbox)

        self.setGeometry(300, 300, 500, 500)
        self.setWindowTitle('Photos')
        self.setWindowIcon(QIcon('camera-photo-5.png'))
        self.center()
        self.show()
コード例 #2
0
    def __init__(self):
        super(MainWindow, self).__init__()

        self.ports = serial.listports()
        self.port = None

        # remove close & maximize window buttons
        #self.setWindowFlags(Qt.CustomizeWindowHint|Qt.WindowMinimizeButtonHint)
        self.setMinimumSize(850, 450)

        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.mdiArea.subWindowActivated.connect(self.updateMenus)
        self.mdiArea.setViewMode(QMdiArea.TabbedView)

        self.windowMapper = QSignalMapper(self)
        self.windowMapper.mapped[QWidget].connect(self.setActiveSubWindow)

        self.child = None

        self.createActions()
        self.createMenus()
        self.createStatusBar()
        self.updateMenus()
        self.readSettings()
        self.setWindowTitle("VISCAM")

        mytoolbar = QToolBar()
        ports_menu = QComboBox()
        ports_menu.addItem('Output Port')
        ports_menu.insertSeparator(1)
        for port in self.ports:
            ports_menu.addItem(port)
        self.ports_menu = ports_menu
        ports_menu.currentTextChanged.connect(self.setActivePort)
        mytoolbar.addWidget(ports_menu)
        mytoolbar.addSeparator()
        mytoolbar.setMovable(False)
        mytoolbar.setFixedHeight(60)
        self.addToolBar(Qt.TopToolBarArea, mytoolbar)
コード例 #3
0
ファイル: app.py プロジェクト: gitter-badger/happypanda
class AppWindow(QMainWindow):
	"The application's main window"
	def __init__(self):
		super().__init__()
		self.center = QWidget()
		self.display = QStackedLayout()
		self.center.setLayout(self.display)
		# init the manga view variables
		self.manga_display()
		# init the chapter view variables
		self.chapter_display()
		# init toolbar
		self.init_toolbar()
		# init status bar
		self.init_stat_bar()

		self.display.addWidget(self.manga_main)
		self.display.addWidget(self.chapter_main)

		self.setCentralWidget(self.center)
		self.setWindowTitle("Happypanda")
		self.resize(1029, 650)
		self.show()
	
	def init_stat_bar(self):
		self.status_bar = self.statusBar()
		self.status_bar.setMaximumHeight(20)
		self.status_bar.setSizeGripEnabled(False)
		self.stat_info = QLabel()
		self.stat_info.setIndent(5)
		self.sort_main = QAction("Asc", self)
		sort_menu = QMenu()
		self.sort_main.setMenu(sort_menu)
		s_by_title = QAction("Title", sort_menu)
		s_by_artist = QAction("Artist", sort_menu)
		sort_menu.addAction(s_by_title)
		sort_menu.addAction(s_by_artist)
		self.status_bar.addPermanentWidget(self.stat_info)
		#self.status_bar.addAction(self.sort_main)
		self.temp_msg = QLabel()
		self.temp_timer = QTimer()
		self.manga_list_view.series_model.ROWCOUNT_CHANGE.connect(self.stat_row_info)
		self.manga_list_view.series_model.STATUSBAR_MSG.connect(self.stat_temp_msg)

	def stat_temp_msg(self, msg):
		self.temp_timer.stop()
		self.temp_msg.setText(msg)
		self.status_bar.addWidget(self.temp_msg)
		self.temp_timer.timeout.connect(self.temp_msg.clear)
		self.temp_timer.setSingleShot(True)
		self.temp_timer.start(5000)

	def stat_row_info(self):
		r = self.manga_list_view.series_model.rowCount()
		t = len(self.manga_list_view.series_model._data)
		self.stat_info.setText("<b>Showing {} of {} </b>".format(r, t))

	def manga_display(self):
		"initiates the manga view"
		self.manga_main = QWidget()
		self.manga_main.setContentsMargins(-10, -12, -10, -10)
		self.manga_view = QHBoxLayout()
		self.manga_main.setLayout(self.manga_view)

		manga_delegate = series.CustomDelegate()
		manga_delegate.BUTTON_CLICKED.connect(self.setCurrentIndex)
		self.manga_list_view = series.MangaView()
		self.manga_list_view.setItemDelegate(manga_delegate)
		self.manga_view.addWidget(self.manga_list_view)

	def favourite_display(self):
		"initiates favourite display"
		pass

	def chapter_display(self):
		"Initiates chapter view"
		self.chapter_main = QWidget()
		self.chapter_main.setObjectName("chapter_main") # to allow styling this object
		self.chapter_layout = QHBoxLayout()
		self.chapter_main.setLayout(self.chapter_layout)

		#self.chapter_info.setContentsMargins(-8,-7,-7,-7)
		#self.chapter_info.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
		self.chapter_info_view = series.ChapterInfo()
		self.chapter_layout.addWidget(self.chapter_info_view)

		chapter_list_view = series.ChapterView()
		self.chapter_layout.addWidget(chapter_list_view)
		#self.chapter.setCollapsible(0, True)
		#self.chapter.setCollapsible(1, False)

	def init_toolbar(self):
		self.toolbar = QToolBar()
		self.toolbar.setFixedHeight(30)
		self.toolbar.setWindowTitle("Show") # text for the contextmenu
		#self.toolbar.setStyleSheet("QToolBar {border:0px}") # make it user defined?
		self.toolbar.setMovable(False)
		self.toolbar.setFloatable(False)
		#self.toolbar.setIconSize(QSize(20,20))
		self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)

		spacer_start = QWidget() # aligns the first actions properly
		spacer_start.setFixedSize(QSize(10, 1))
		self.toolbar.addWidget(spacer_start)

		favourite_view_icon = QIcon(gui_constants.STAR_BTN_PATH)
		favourite_view_action = QAction(favourite_view_icon, "Favourite", self)
		#favourite_view_action.setText("Manga View")
		favourite_view_action.triggered.connect(lambda: self.setCurrentIndex(1)) #need lambda to pass extra args
		self.toolbar.addAction(favourite_view_action)

		catalog_view_icon = QIcon(gui_constants.HOME_BTN_PATH)
		catalog_view_action = QAction(catalog_view_icon, "Library", self)
		#catalog_view_action.setText("Catalog")
		catalog_view_action.triggered.connect(lambda: self.setCurrentIndex(0)) #need lambda to pass extra args
		self.toolbar.addAction(catalog_view_action)
		self.toolbar.addSeparator()

		series_icon = QIcon(gui_constants.PLUS_PATH)
		series_action = QAction(series_icon, "Add series...", self)
		series_action.triggered.connect(self.manga_list_view.SERIES_DIALOG.emit)
		series_menu = QMenu()
		series_menu.addSeparator()
		populate_action = QAction("Populate from folder...", self)
		populate_action.triggered.connect(self.populate)
		series_menu.addAction(populate_action)
		series_action.setMenu(series_menu)
		self.toolbar.addAction(series_action)

		spacer_middle = QWidget() # aligns buttons to the right
		spacer_middle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
		self.toolbar.addWidget(spacer_middle)
		
		self.search_bar = QLineEdit()
		self.search_bar.setPlaceholderText("Search title, artist, genres")
		self.search_bar.setMaximumWidth(200)
		self.toolbar.addWidget(self.search_bar)
		self.toolbar.addSeparator()
		settings_icon = QIcon(gui_constants.SETTINGS_PATH)
		settings_action = QAction(settings_icon, "Set&tings", self)
		self.toolbar.addAction(settings_action)
		self.addToolBar(self.toolbar)
		
		spacer_end = QWidget() # aligns About action properly
		spacer_end.setFixedSize(QSize(10, 1))
		self.toolbar.addWidget(spacer_end)

	def setCurrentIndex(self, number, index=None):
		"""Changes the current display view.
		Params:
			number <- int (0 for manga view, 1 for chapter view
		Optional:
			index <- QModelIndex for chapter view
		Note: 0-based indexing
		"""
		if index is not None:
			self.chapter_info_view.display_manga(index)
			self.display.setCurrentIndex(number)
		else:
			self.display.setCurrentIndex(number)

	# TODO: Improve this so that it adds to the series dialog,
	# so user can edit data before inserting (make it a choice)
	def populate(self):
		"Populates the database with series from local drive'"
		msgbox = QMessageBox()
		msgbox.setText("<font color='red'><b>Use with care.</b></font> Choose a folder containing all your series'.")
		msgbox.setInformativeText("Oniichan, are you sure you want to do this?")
		msgbox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
		msgbox.setDefaultButton(QMessageBox.No)
		if msgbox.exec() == QMessageBox.Yes:
			path = QFileDialog.getExistingDirectory(None, "Choose a folder containing your series'")
			if len(path) is not 0:
				data_thread = QThread()
				loading_thread = QThread()
				loading = misc.Loading()

				if not loading.ON:
					misc.Loading.ON = True
					fetch_instance = fetch.Fetch()
					fetch_instance.series_path = path
					loading.show()

					def finished(status):
						if status:
							self.manga_list_view.series_model.populate_data()
							# TODO: make it spawn a dialog instead (from utils.py or misc.py)
							if loading.progress.maximum() == loading.progress.value():
								misc.Loading.ON = False
								loading.hide()
							data_thread.quit
						else:
							loading.setText("<font color=red>An error occured. Try restarting..</font>")
							loading.progress.setStyleSheet("background-color:red")
							data_thread.quit

					def fetch_deleteLater():
						try:
							fetch_instance.deleteLater
						except NameError:
							pass

					def thread_deleteLater(): #NOTE: Isn't this bad?
						data_thread.deleteLater

					def a_progress(prog):
						loading.progress.setValue(prog)
						loading.setText("Searching on local disk...\n(Will take a while on first time)")

					fetch_instance.moveToThread(data_thread)
					fetch_instance.DATA_COUNT.connect(loading.progress.setMaximum)
					fetch_instance.PROGRESS.connect(a_progress)
					data_thread.started.connect(fetch_instance.local)
					fetch_instance.FINISHED.connect(finished)
					fetch_instance.FINISHED.connect(fetch_deleteLater)
					fetch_instance.FINISHED.connect(thread_deleteLater)
					data_thread.start()
コード例 #4
0
class JobbiUI(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        # Init window
        self._setupWindow()

        # List containing custom job add widgets
        self.addElements = []

        # Init UI and create GUI components
        self._createToolBar()
        self._setupUI()
        self._createStatusBar()

    def insertJobs(self, adds):
        if adds is not None:
            adds = al.shuffle_adds(adds)
            adds.reverse()

            for add in adds:
                self.insertJobElement(add)

    # Insert job add objects
    def insertJobElement(self, jobAdd):
        element = _JobAddElement(jobAdd.add_heading, jobAdd.add_content,
                                 jobAdd.company, jobAdd.company_url,
                                 jobAdd.add_url, jobAdd.add_owner)

        # The first add element will have the index 0, with the current layout,
        # thus to insert new adds add the top of the list the insertWidget()
        # method is used insted of addWidget()
        self.generalLayout.insertWidget(0, element)

        self.addElements.append(element)

    def getIndices(self):
        for el in self.addElements:
            print(self.generalLayout.indexOf(el))

    def updateStatus(self, msg):
        self.status.showMessage(msg)
        self.update()

    def _setupUI(self):
        # Set central widget to be a scroll area
        self.mainScrollArea = QScrollArea(self)
        self.setCentralWidget(self.mainScrollArea)

        # Main job-add layout
        self.baseWidget = QWidget()
        self.generalLayout = QVBoxLayout()
        self.generalLayout.setContentsMargins(100, 20, 100, 20)
        self.baseWidget.setLayout(self.generalLayout)

        # Point baseWidget to the main scroll area
        self.mainScrollArea.setWidget(self.baseWidget)
        self.mainScrollArea.setWidgetResizable(True)

    def _createToolBar(self):
        # Define main toolbar
        self.toolbar = QToolBar("Main toolbar")
        self.addToolBar(self.toolbar)
        self.toolbar.setIconSize(QSize(22, 22))
        self.toolbar.setFixedHeight(36)

        # Define action to be included in the toolbar and add them to it
        self.settingsAction = QAction(QIcon(str(img_path / "build-24px.svg")),
                                      "Settings", self)
        self.updateAction = QAction(
            QIcon(str(img_path / "cloud_download-24px.svg")), "Load adds",
            self)

        self.toolbar.addAction(self.settingsAction)
        self.toolbar.addAction(self.updateAction)

    def _createStatusBar(self):
        self.status = QStatusBar()
        self.status.showMessage("Welcome")
        self.setStatusBar(self.status)

    def _setupWindow(self):
        self.setWindowTitle('Jobbi')
        self.setGeometry(0, 0, 990, 660)
        self.setMinimumWidth(800)
        self.setMinimumHeight(400)

        # Center main window
        qt_rectangle = self.frameGeometry()
        qt_rectangle.moveCenter(QDesktopWidget().availableGeometry().center())
        self.move(qt_rectangle.topLeft())

        # Set window background color
        self.setAutoFillBackground(True)
        p = self.palette()
        p.setColor(self.backgroundRole(), Qt.white)
        self.setPalette(p)
コード例 #5
0
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.browser = QWebEngineView()
        self.browser.setUrl(QUrl("https://www.stackoverflow.com"))

        self.browser.urlChanged.connect(self.update_urlbar)
        self.browser.loadFinished.connect(self.update_title)

        self.setCentralWidget(self.browser)
        self.status = QStatusBar()
        self.setStatusBar(self.status)

        #####################################################
        navtb2 = QToolBar()
        navtb2.setIconSize(QSize(16, 16))
        navtb2.setFixedHeight(50)
        navtb2.setIconSize(QSize(60, 60))

        self.query_bar = QLineEdit(self)
        self.query_bar.setFixedHeight(45)
        f = self.query_bar.font()
        f.setPointSize(20)  # sets the size to 27
        self.query_bar.setFont(f)
        self.query_bar.setPlaceholderText("Powered by IBM Cloud...")
        self.query_bar.returnPressed.connect(self.process_query)
        navtb2.addWidget(self.query_bar)

        self.back_btn = QAction(QIcon(os.path.join('images', 'arrow-180.png')), "Previous Answer", self)
        self.back_btn.setStatusTip("Back to previous page")
        self.back_btn.triggered.connect(self.prev_answer)
        self.back_btn.setDisabled(True)
        navtb2.addAction(self.back_btn)

        self.next_btn = QAction(QIcon(os.path.join('images', 'arrow-000.png')), "Next Answer", self)
        self.next_btn.setStatusTip("Forward to next page")
        self.next_btn.triggered.connect(self.next_answer)
        self.next_btn.setDisabled(True)
        navtb2.addAction(self.next_btn)

        self.addToolBar(navtb2)
        self.addToolBarBreak()
        #####################################################

        navtb = QToolBar("Navigation")
        navtb.setIconSize(QSize(16, 16))
        self.addToolBar(navtb)

        reload_btn = QAction(QIcon(os.path.join('images', 'arrow-circle-315.png')), "Reload", self)
        reload_btn.setStatusTip("Reload page")
        reload_btn.triggered.connect(self.browser.reload)
        navtb.addAction(reload_btn)

        home_btn = QAction(QIcon(os.path.join('images', 'home.png')), "Home", self)
        home_btn.setStatusTip("Go home")
        home_btn.triggered.connect(self.navigate_home)
        navtb.addAction(home_btn)

        navtb.addSeparator()

        self.httpsicon = QLabel()  # Yes, really!
        self.httpsicon.setPixmap(QPixmap(os.path.join('images', 'lock-nossl.png')))
        navtb.addWidget(self.httpsicon)

        self.urlbar = QLineEdit()
        self.urlbar.returnPressed.connect(self.navigate_to_url)
        navtb.addWidget(self.urlbar)

        stop_btn = QAction(QIcon(os.path.join('images', 'cross-circle.png')), "Stop", self)
        stop_btn.setStatusTip("Stop loading current page")
        stop_btn.triggered.connect(self.browser.stop)
        navtb.addAction(stop_btn)

        # Uncomment to disable native menubar on Mac
        # self.menuBar().setNativeMenuBar(False)

        file_menu = self.menuBar().addMenu("&File")

        open_file_action = QAction(QIcon(os.path.join('images', 'disk--arrow.png')), "Open file...", self)
        open_file_action.setStatusTip("Open from file")
        open_file_action.triggered.connect(self.open_file)
        file_menu.addAction(open_file_action)

        save_file_action = QAction(QIcon(os.path.join('images', 'disk--pencil.png')), "Save Page As...", self)
        save_file_action.setStatusTip("Save current page to file")
        save_file_action.triggered.connect(self.save_file)
        file_menu.addAction(save_file_action)

        print_action = QAction(QIcon(os.path.join('images', 'printer.png')), "Print...", self)
        print_action.setStatusTip("Print current page")
        print_action.triggered.connect(self.print_page)
        file_menu.addAction(print_action)

        help_menu = self.menuBar().addMenu("&Help")

        about_action = QAction(QIcon(os.path.join('images', 'question.png')), "About CRIO", self)
        about_action.setStatusTip("Find out more about CRIO")  # Hungry!
        about_action.triggered.connect(self.about)
        help_menu.addAction(about_action)

        navigate_mozarella_action = QAction(QIcon(os.path.join('images', 'lifebuoy.png')), "CRIO Homepage", self)
        navigate_mozarella_action.setStatusTip("Go to CRIO Homepage")
        navigate_mozarella_action.triggered.connect(self.navigate_mozarella)
        help_menu.addAction(navigate_mozarella_action)

        self.show()

        self.setWindowIcon(QIcon(os.path.join('images', 'ma-icon-64.png')))
コード例 #6
0
ファイル: panel_java_trace.py プロジェクト: yb1994917/Dwarf
class JavaTracePanel(QWidget):
    def __init__(self, app, *__args):
        super().__init__(app)
        self.app = app

        self.app.dwarf.onJavaTraceEvent.connect(self.on_event)
        self.app.dwarf.onEnumerateJavaClassesStart.connect(
            self.on_enumeration_start)
        self.app.dwarf.onEnumerateJavaClassesMatch.connect(
            self.on_enumeration_match)
        self.app.dwarf.onEnumerateJavaClassesComplete.connect(
            self.on_enumeration_complete)

        self.tracing = False
        self.trace_classes = []
        self.trace_depth = 0

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)

        self._record_icon = QIcon(
            utils.resource_path('assets/icons/record.png'))
        self._pause_icon = QIcon(utils.resource_path('assets/icons/pause.png'))
        self._stop_icon = QIcon(utils.resource_path('assets/icons/stop.png'))

        self._tool_bar = QToolBar()
        self._tool_bar.setFixedHeight(16)
        self._tool_bar.setContentsMargins(1, 1, 1, 1)
        self._tool_bar.addAction(self._record_icon, 'Record', self.start_trace)
        self._tool_bar.addAction(self._pause_icon, 'Pause', self.pause_trace)
        self._tool_bar.addAction(self._stop_icon, 'Stop', self.stop_trace)
        self._tool_bar.addSeparator()
        self._entries_lbl = QLabel('Entries: 0')
        self._entries_lbl.setAlignment(Qt.AlignRight)
        self._entries_lbl.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Preferred)
        self._tool_bar.addWidget(self._entries_lbl)

        layout.addWidget(self._tool_bar)

        self.setup_splitter = QSplitter()
        self.events_list = JavaTraceView(self)
        self.events_list.setVisible(False)

        self.trace_list = QListWidget()
        self.class_list = QListWidget()

        self.trace_list.itemDoubleClicked.connect(self.trace_list_double_click)

        self.class_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.class_list.customContextMenuRequested.connect(
            self.show_class_list_menu)
        self.class_list.itemDoubleClicked.connect(self.class_list_double_click)

        self.current_class_search = ''

        bar = QScrollBar()
        bar.setFixedWidth(0)
        bar.setFixedHeight(0)
        self.trace_list.setHorizontalScrollBar(bar)
        bar = QScrollBar()
        bar.setFixedWidth(0)
        bar.setFixedHeight(0)
        self.class_list.setHorizontalScrollBar(bar)

        self.setup_splitter.addWidget(self.trace_list)
        self.setup_splitter.addWidget(self.class_list)
        self.setup_splitter.setHandleWidth(1)

        layout.addWidget(self.setup_splitter)
        layout.addWidget(self.events_list)

        self.setLayout(layout)

    def class_list_double_click(self, item):
        try:
            if self.trace_classes.index(item.text()) >= 0:
                return
        except:
            pass
        self.trace_classes.append(item.text())
        q = NotEditableListWidgetItem(item.text())
        self.trace_list.addItem(q)
        self.trace_list.sortItems()

    def on_enumeration_start(self):
        self.class_list.clear()

    def on_enumeration_match(self, java_class):
        try:
            if PREFIXED_CLASS.index(java_class) >= 0:
                try:
                    if self.trace_classes.index(java_class) >= 0:
                        return
                except:
                    pass
                q = NotEditableListWidgetItem(java_class)
                self.trace_list.addItem(q)
                self.trace_classes.append(java_class)
        except:
            pass

        q = NotEditableListWidgetItem(java_class)
        self.class_list.addItem(q)

    def on_enumeration_complete(self):
        self.class_list.sortItems()
        self.trace_list.sortItems()

    def on_event(self, data):
        trace, event, clazz, data = data
        if trace == 'java_trace':
            self.events_list.add_event({
                'event': event,
                'class': clazz,
                'data': data.replace(',', ', ')
            })
            self._entries_lbl.setText('Events: %d' %
                                      len(self.events_list.data))

    def pause_trace(self):
        self.app.dwarf.dwarf_api('stopJavaTracer')
        self.tracing = False

    def search(self):
        accept, input = InputDialog.input(
            self.app,
            hint='Search',
            input_content=self.current_class_search,
            placeholder='Search something...')
        if accept:
            self.current_class_search = input.lower()
            for i in range(0, self.class_list.count()):
                try:
                    if self.class_list.item(i).text().lower().index(
                            self.current_class_search.lower()) >= 0:
                        self.class_list.setRowHidden(i, False)
                except:
                    self.class_list.setRowHidden(i, True)

    def show_class_list_menu(self, pos):
        menu = QMenu()
        search = menu.addAction('Search')
        action = menu.exec_(self.class_list.mapToGlobal(pos))
        if action:
            if action == search:
                self.search()

    def start_trace(self):
        self.app.dwarf.dwarf_api('startJavaTracer', [self.trace_classes])
        self.trace_depth = 0
        self.tracing = True
        self.setup_splitter.setVisible(False)
        self.events_list.setVisible(True)

    def stop_trace(self):
        self.app.dwarf.dwarf_api('stopJavaTracer')
        self.tracing = False
        self.setup_splitter.setVisible(True)
        self.events_list.setVisible(False)
        self.events_list.clear()

    def trace_list_double_click(self, item):
        try:
            index = self.trace_classes.index(item.text())
        except:
            return
        if index < 0:
            return
        self.trace_classes.pop(index)
        self.trace_list.takeItem(self.trace_list.row(item))

    def keyPressEvent(self, event):
        if event.modifiers() & Qt.ControlModifier:
            if event.key() == Qt.Key_F:
                self.search()
        super(JavaTracePanel, self).keyPressEvent(event)
コード例 #7
0
ファイル: app.py プロジェクト: utterbull/happypanda
class AppWindow(QMainWindow):
    "The application's main window"

    def __init__(self):
        super().__init__()
        self.initUI()
        self.start_up()
        QTimer.singleShot(3000, self._check_update)

    def init_watchers(self):
        def remove_gallery(g):
            index = self.manga_list_view.find_index(g.id)
            if index:
                self.manga_list_view.remove_gallery([index])

        def create_gallery(path):
            g_dia = gallerydialog.GalleryDialog(self, path)
            g_dia.SERIES.connect(self.manga_list_view.gallery_model.addRows)
            g_dia.show()

        def update_gallery(g):
            index = self.manga_list_view.find_index(g.id)
            if index:
                self.manga_list_view.replace_edit_gallery([g], index.row())
            else:
                log_e("Could not find gallery to update from Watcher")

        def created(path):
            c_popup = file_misc.CreatedPopup(path, self)
            c_popup.ADD_SIGNAL.connect(create_gallery)

        def modified(path, gallery):
            mod_popup = file_misc.ModifiedPopup(path, gallery, self)

        def deleted(path, gallery):
            d_popup = file_misc.DeletedPopup(path, gallery, self)
            d_popup.UPDATE_SIGNAL.connect(update_gallery)
            d_popup.REMOVE_SIGNAL.connect(remove_gallery)

        def moved(new_path, gallery):
            mov_popup = file_misc.MovedPopup(new_path, gallery, self)
            mov_popup.UPDATE_SIGNAL.connect(update_gallery)

        self.watchers = file_misc.Watchers()
        self.watchers.gallery_handler.CREATE_SIGNAL.connect(created)
        self.watchers.gallery_handler.MODIFIED_SIGNAL.connect(modified)
        self.watchers.gallery_handler.MOVED_SIGNAL.connect(moved)
        self.watchers.gallery_handler.DELETED_SIGNAL.connect(deleted)

        if gui_constants.LOOK_NEW_GALLERY_STARTUP:
            self.notification_bar.add_text("Looking for new galleries...")
            try:

                class ScanDir(QObject):
                    final_paths_and_galleries = pyqtSignal(list, list)

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

                    def scan_dirs(self):
                        db_data = self.model_data
                        paths = []
                        for g in range(len(db_data)):
                            paths.append(os.path.normcase(db_data[g].path))

                        contents = []
                        case_path = []  # needed for tile and artist parsing... e.g to avoid lowercase
                        for m_path in gui_constants.MONITOR_PATHS:
                            for p in os.listdir(m_path):
                                abs_p = os.path.join(m_path, p)
                                if os.path.isdir(abs_p) or p.endswith(utils.ARCHIVE_FILES):
                                    case_path.append(abs_p)
                                    contents.append(os.path.normcase(abs_p))

                        paths = sorted(paths)
                        new_galleries = []
                        for c, x in enumerate(contents):
                            y = utils.b_search(paths, x)
                            if not y:
                                # (path, number for case_path)
                                new_galleries.append((x, c))

                        galleries = []
                        final_paths = []
                        if new_galleries:
                            for g in new_galleries:
                                gallery = gallerydb.Gallery()
                                try:
                                    gallery.profile = utils.get_gallery_img(g[0])
                                except:
                                    gallery.profile = gui_constants.NO_IMAGE_PATH
                                parser_dict = utils.title_parser(os.path.split(case_path[g[1]])[1])
                                gallery.title = parser_dict["title"]
                                gallery.artist = parser_dict["artist"]
                                galleries.append(gallery)
                                final_paths.append(case_path[g[1]])
                        self.final_paths_and_galleries.emit(final_paths, galleries)
                        # if gui_constants.LOOK_NEW_GALLERY_AUTOADD:
                        # 	QTimer.singleShot(10000, self.gallery_populate(final_paths))
                        # 	return

                def show_new_galleries(final_paths, galleries):
                    if final_paths and galleries:
                        if gui_constants.LOOK_NEW_GALLERY_AUTOADD:
                            self.gallery_populate(final_paths)
                        else:
                            if len(galleries) == 1:
                                self.notification_bar.add_text(
                                    "{} new gallery was discovered in one of your monitored directories".format(
                                        len(galleries)
                                    )
                                )
                            else:
                                self.notification_bar.add_text(
                                    "{} new galleries were discovered in one of your monitored directories".format(
                                        len(galleries)
                                    )
                                )
                            text = (
                                "These new galleries were discovered! Do you want to add them?"
                                if len(galleries) > 1
                                else "This new gallery was discovered! Do you want to add it?"
                            )
                            g_popup = file_misc.GalleryPopup((text, galleries), self)
                            buttons = g_popup.add_buttons("Add", "Close")

                            def populate_n_close():
                                self.gallery_populate(final_paths)
                                g_popup.close()

                            buttons[0].clicked.connect(populate_n_close)
                            buttons[1].clicked.connect(g_popup.close)

                thread = QThread(self)
                self.scan_inst = ScanDir(self.manga_list_view.gallery_model._data)
                self.scan_inst.moveToThread(thread)
                self.scan_inst.final_paths_and_galleries.connect(show_new_galleries)
                self.scan_inst.final_paths_and_galleries.connect(lambda a: self.scan_inst.deleteLater())
                thread.started.connect(self.scan_inst.scan_dirs)
                thread.finished.connect(thread.deleteLater)
                thread.start()
            except:
                self.notification_bar.add_text(
                    "An error occured while attempting to scan for new galleries. Check happypanda.log."
                )
                log.exception("An error occured while attempting to scan for new galleries.")

    def start_up(self):
        def normalize_first_time():
            settings.set(2, "Application", "first time level")

        def done():
            self.manga_list_view.gallery_model.init_data()
            if gui_constants.ENABLE_MONITOR and gui_constants.MONITOR_PATHS and all(gui_constants.MONITOR_PATHS):
                self.init_watchers()
            if gui_constants.FIRST_TIME_LEVEL != 2:
                normalize_first_time()

        if gui_constants.FIRST_TIME_LEVEL < 2:

            class FirstTime(file_misc.BasePopup):
                def __init__(self, parent=None):
                    super().__init__(parent)
                    main_layout = QVBoxLayout()
                    info_lbl = QLabel(
                        "Hi there! Some big changes are about to occur!\n"
                        + "Please wait.. This will take at most a few minutes.\n"
                        + "If not then try restarting the application."
                    )
                    info_lbl.setAlignment(Qt.AlignCenter)
                    main_layout.addWidget(info_lbl)
                    prog = QProgressBar(self)
                    prog.setMinimum(0)
                    prog.setMaximum(0)
                    prog.setTextVisible(False)
                    main_layout.addWidget(prog)
                    main_layout.addWidget(QLabel("Note: This popup will close itself when everything is ready"))
                    self.main_widget.setLayout(main_layout)

            ft_widget = FirstTime(self)
            log_i("Invoking first time level 2")
            bridge = gallerydb.Bridge()
            thread = QThread(self)
            thread.setObjectName("Startup")
            bridge.moveToThread(thread)
            thread.started.connect(bridge.rebuild_galleries)
            bridge.DONE.connect(ft_widget.close)
            bridge.DONE.connect(self.setEnabled)
            bridge.DONE.connect(done)
            bridge.DONE.connect(bridge.deleteLater)
            thread.finished.connect(thread.deleteLater)
            thread.start()
            ft_widget.adjustSize()
            ft_widget.show()
            self.setEnabled(False)
        else:
            done()

    def initUI(self):
        self.center = QWidget()
        self.display = QStackedLayout()
        self.center.setLayout(self.display)
        # init the manga view variables
        self.manga_display()
        log_d("Create manga display: OK")
        # init the chapter view variables
        # self.chapter_display()
        self.m_l_view_index = self.display.addWidget(self.manga_list_main)
        self.m_t_view_index = self.display.addWidget(self.manga_table_view)
        # init toolbar
        self.init_toolbar()
        log_d("Create toolbar: OK")
        # init status bar
        self.init_stat_bar()
        log_d("Create statusbar: OK")

        self.system_tray = misc.SystemTray(QIcon(gui_constants.APP_ICO_PATH), self)
        gui_constants.SYSTEM_TRAY = self.system_tray
        tray_menu = QMenu(self)
        self.system_tray.setContextMenu(tray_menu)
        self.system_tray.setToolTip("Happypanda {}".format(gui_constants.vs))
        tray_quit = QAction("Quit", tray_menu)
        tray_menu.addAction(tray_quit)
        tray_quit.triggered.connect(self.close)
        self.system_tray.show()
        log_d("Create system tray: OK")

        # self.display.addWidget(self.chapter_main)

        self.setCentralWidget(self.center)
        self.setWindowTitle("Happypanda")
        self.setWindowIcon(QIcon(gui_constants.APP_ICO_PATH))

        props = settings.win_read(self, "AppWindow")
        if props.resize:
            x, y = props.resize
            self.resize(x, y)
        else:
            self.resize(gui_constants.MAIN_W, gui_constants.MAIN_H)
        posx, posy = props.pos
        self.move(posx, posy)
        self.show()
        log_d("Show window: OK")

        self.notification_bar = misc.NotificationOverlay(self)
        p = self.toolbar.pos()
        self.notification_bar.move(p.x(), p.y() + self.toolbar.height())
        self.notification_bar.resize(self.width())
        gui_constants.NOTIF_BAR = self.notification_bar
        log_d("Create notificationbar: OK")

        log_d("Window Create: OK")

    def _check_update(self):
        class upd_chk(QObject):
            UPDATE_CHECK = pyqtSignal(str)

            def __init__(self, **kwargs):
                super().__init__(**kwargs)

            def fetch_vs(self):
                import requests
                import time

                try:
                    log_d("Checking Update")
                    time.sleep(1.5)
                    r = requests.get(
                        "https://raw.githubusercontent.com/Pewpews/happypanda/master/VS.txt", verify="cacert.pem"
                    )
                    a = r.text
                    vs = a.strip()
                    self.UPDATE_CHECK.emit(vs)
                except:
                    log.exception("Checking Update: FAIL")
                    self.UPDATE_CHECK.emit("this is a very long text which is is sure to be over limit")

        def check_update(vs):
            log_i("Received version: {}\nCurrent version: {}".format(vs, gui_constants.vs))
            if vs != gui_constants.vs:
                if len(vs) < 10:
                    self.notification_bar.add_text(
                        "Version {} of Happypanda is".format(vs) + " available. Click here to update!", False
                    )
                    self.notification_bar.clicked.connect(
                        lambda: utils.open_web_link("https://github.com/Pewpews/happypanda/releases")
                    )
                    self.notification_bar.set_clickable(True)
                else:
                    self.notification_bar.add_text("An error occurred while checking for new version")

        self.update_instance = upd_chk()
        thread = QThread(self)
        self.update_instance.moveToThread(thread)
        thread.started.connect(self.update_instance.fetch_vs)
        self.update_instance.UPDATE_CHECK.connect(check_update)
        self.update_instance.UPDATE_CHECK.connect(self.update_instance.deleteLater)
        thread.finished.connect(thread.deleteLater)
        thread.start()

    def _web_metadata_picker(self, gallery, title_url_list, queue, parent=None):
        if not parent:
            parent = self
        text = "Which gallery do you want to extract metadata from?"
        s_gallery_popup = misc.SingleGalleryChoices(gallery, title_url_list, text, parent)
        s_gallery_popup.USER_CHOICE.connect(queue.put)

    def get_metadata(self, gal=None):
        thread = QThread(self)
        thread.setObjectName("App.get_metadata")
        fetch_instance = fetch.Fetch()
        if gal:
            galleries = [gal]
        else:
            if gui_constants.CONTINUE_AUTO_METADATA_FETCHER:
                galleries = [g for g in self.manga_list_view.gallery_model._data if not g.exed]
            else:
                galleries = self.manga_list_view.gallery_model._data
            if not galleries:
                self.notification_bar.add_text("Looks like we've already gone through all galleries!")
                return None
        fetch_instance.galleries = galleries

        self.notification_bar.begin_show()
        fetch_instance.moveToThread(thread)

        def done(status):
            self.notification_bar.end_show()
            fetch_instance.deleteLater()

        fetch_instance.GALLERY_PICKER.connect(self._web_metadata_picker)
        fetch_instance.GALLERY_EMITTER.connect(self.manga_list_view.replace_edit_gallery)
        fetch_instance.AUTO_METADATA_PROGRESS.connect(self.notification_bar.add_text)
        thread.started.connect(fetch_instance.auto_web_metadata)
        fetch_instance.FINISHED.connect(done)
        thread.finished.connect(thread.deleteLater)
        thread.start()

        # def style_tooltip(self):
        # 	palette = QToolTip.palette()
        # 	palette.setColor()

    def init_stat_bar(self):
        self.status_bar = self.statusBar()
        self.status_bar.setMaximumHeight(20)
        self.status_bar.setSizeGripEnabled(False)
        self.stat_info = QLabel()
        self.stat_info.setIndent(5)
        self.sort_main = QAction("Asc", self)
        sort_menu = QMenu()
        self.sort_main.setMenu(sort_menu)
        s_by_title = QAction("Title", sort_menu)
        s_by_artist = QAction("Artist", sort_menu)
        sort_menu.addAction(s_by_title)
        sort_menu.addAction(s_by_artist)
        self.status_bar.addPermanentWidget(self.stat_info)
        # self.status_bar.addAction(self.sort_main)
        self.temp_msg = QLabel()
        self.temp_timer = QTimer()

        self.manga_list_view.gallery_model.ROWCOUNT_CHANGE.connect(self.stat_row_info)
        self.manga_list_view.gallery_model.STATUSBAR_MSG.connect(self.stat_temp_msg)
        self.manga_list_view.STATUS_BAR_MSG.connect(self.stat_temp_msg)
        self.manga_table_view.STATUS_BAR_MSG.connect(self.stat_temp_msg)
        self.stat_row_info()

    def stat_temp_msg(self, msg):
        self.temp_timer.stop()
        self.temp_msg.setText(msg)
        self.status_bar.addWidget(self.temp_msg)
        self.temp_timer.timeout.connect(self.temp_msg.clear)
        self.temp_timer.setSingleShot(True)
        self.temp_timer.start(5000)

    def stat_row_info(self):
        r = self.manga_list_view.model().rowCount()
        t = self.manga_list_view.gallery_model._data_count
        self.stat_info.setText("Loaded {} of {} ".format(r, t))

    def manga_display(self):
        "initiates the manga view"
        # list view
        self.manga_list_main = QWidget()
        # self.manga_list_main.setContentsMargins(-10, -12, -10, -10)
        self.manga_list_main.setContentsMargins(10, -9, -10, -10)  # x, y, inverted_width, inverted_height
        self.manga_list_layout = QHBoxLayout()
        self.manga_list_main.setLayout(self.manga_list_layout)

        self.manga_list_view = gallery.MangaView(self)
        self.manga_list_view.clicked.connect(self.popup)
        self.manga_list_view.manga_delegate.POPUP.connect(self.popup)
        self.popup_window = self.manga_list_view.manga_delegate.popup_window
        self.manga_list_layout.addWidget(self.manga_list_view)

        # table view
        self.manga_table_main = QWidget()
        self.manga_table_layout = QVBoxLayout()
        self.manga_table_main.setLayout(self.manga_table_layout)

        self.manga_table_view = gallery.MangaTableView(self)
        self.manga_table_view.gallery_model = self.manga_list_view.gallery_model
        self.manga_table_view.sort_model = self.manga_list_view.sort_model
        self.manga_table_view.setModel(self.manga_table_view.sort_model)
        self.manga_table_view.sort_model.change_model(self.manga_table_view.gallery_model)
        self.manga_table_view.setColumnWidth(gui_constants.FAV, 20)
        self.manga_table_view.setColumnWidth(gui_constants.ARTIST, 200)
        self.manga_table_view.setColumnWidth(gui_constants.TITLE, 400)
        self.manga_table_view.setColumnWidth(gui_constants.TAGS, 300)
        self.manga_table_view.setColumnWidth(gui_constants.TYPE, 60)
        self.manga_table_view.setColumnWidth(gui_constants.CHAPTERS, 60)
        self.manga_table_view.setColumnWidth(gui_constants.LANGUAGE, 100)
        self.manga_table_view.setColumnWidth(gui_constants.LINK, 400)
        self.manga_table_layout.addWidget(self.manga_table_view)

    def search(self, srch_string):
        case_ins = srch_string.lower()
        if not gui_constants.ALLOW_SEARCH_REGEX:
            remove = "^$*+?{}\\|()[]"
            for x in remove:
                if x == "[" or x == "]":
                    continue
                else:
                    case_ins = case_ins.replace(x, ".")
        else:
            try:
                re.compile(case_ins)
            except re.error:
                return
        self.manga_list_view.sort_model.search(case_ins)

    def popup(self, index):
        if not self.popup_window.isVisible():
            m_x = QCursor.pos().x()
            m_y = QCursor.pos().y()
            d_w = QDesktopWidget().width()
            d_h = QDesktopWidget().height()
            p_w = gui_constants.POPUP_WIDTH
            p_h = gui_constants.POPUP_HEIGHT

            index_rect = self.manga_list_view.visualRect(index)
            index_point = self.manga_list_view.mapToGlobal(index_rect.topRight())
            # adjust so it doesn't go offscreen
            if d_w - m_x < p_w and d_h - m_y < p_h:  # bottom
                self.popup_window.move(m_x - p_w + 5, m_y - p_h)
            elif d_w - m_x > p_w and d_h - m_y < p_h:
                self.popup_window.move(m_x + 5, m_y - p_h)
            elif d_w - m_x < p_w:
                self.popup_window.move(m_x - p_w + 5, m_y + 5)
            else:
                self.popup_window.move(index_point)

            self.popup_window.set_gallery(index.data(Qt.UserRole + 1))
            self.popup_window.show()

    def favourite_display(self):
        "Switches to favourite display"
        if self.display.currentIndex() == self.m_l_view_index:
            self.manga_list_view.sort_model.fav_view()
        else:
            self.manga_table_view.sort_model.fav_view()

    def catalog_display(self):
        "Switches to catalog display"
        if self.display.currentIndex() == self.m_l_view_index:
            self.manga_list_view.sort_model.catalog_view()
        else:
            self.manga_table_view.sort_model.catalog_view()

    def settings(self):
        sett = settingsdialog.SettingsDialog(self)
        sett.scroll_speed_changed.connect(self.manga_list_view.updateGeometries)
        # sett.show()

    def init_toolbar(self):
        self.toolbar = QToolBar()
        self.toolbar.setFixedHeight(25)
        self.toolbar.setWindowTitle("Show")  # text for the contextmenu
        # self.toolbar.setStyleSheet("QToolBar {border:0px}") # make it user defined?
        self.toolbar.setMovable(False)
        self.toolbar.setFloatable(False)
        # self.toolbar.setIconSize(QSize(20,20))
        self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)

        spacer_start = QWidget()  # aligns the first actions properly
        spacer_start.setFixedSize(QSize(10, 1))
        self.toolbar.addWidget(spacer_start)

        favourite_view_icon = QIcon(gui_constants.STAR_BTN_PATH)
        favourite_view_action = QAction(favourite_view_icon, "Favorites", self)
        favourite_view_action.setToolTip("Show only favourite galleries")
        favourite_view_action.triggered.connect(self.favourite_display)  # need lambda to pass extra args
        self.toolbar.addAction(favourite_view_action)

        catalog_view_icon = QIcon(gui_constants.HOME_BTN_PATH)
        catalog_view_action = QAction(catalog_view_icon, "Library", self)
        catalog_view_action.setToolTip("Show all your galleries")
        # catalog_view_action.setText("Catalog")
        catalog_view_action.triggered.connect(self.catalog_display)  # need lambda to pass extra args
        self.toolbar.addAction(catalog_view_action)
        self.toolbar.addSeparator()

        gallery_menu = QMenu()
        gallery_action = QToolButton()
        gallery_action.setText("Gallery ")
        gallery_action.setPopupMode(QToolButton.InstantPopup)
        gallery_action.setToolTip("Contains various gallery related features")
        gallery_action.setMenu(gallery_menu)
        add_gallery_icon = QIcon(gui_constants.PLUS_PATH)
        gallery_action_add = QAction(add_gallery_icon, "Add gallery", self)
        gallery_action_add.triggered.connect(self.manga_list_view.SERIES_DIALOG.emit)
        gallery_action_add.setToolTip("Add a single gallery thoroughly")
        gallery_menu.addAction(gallery_action_add)
        add_more_action = QAction(add_gallery_icon, "Add galleries...", self)
        add_more_action.setStatusTip("Add galleries from different folders")
        add_more_action.triggered.connect(lambda: self.populate(True))
        gallery_menu.addAction(add_more_action)
        populate_action = QAction(add_gallery_icon, "Populate from folder...", self)
        populate_action.setStatusTip("Populates the DB with galleries from a single folder")
        populate_action.triggered.connect(self.populate)
        gallery_menu.addAction(populate_action)
        gallery_menu.addSeparator()
        metadata_action = QAction("Get metadata for all galleries", self)
        metadata_action.triggered.connect(self.get_metadata)
        gallery_menu.addAction(metadata_action)
        self.toolbar.addWidget(gallery_action)
        self.toolbar.addSeparator()

        misc_action = QToolButton()
        misc_action.setText("Misc ")
        misc_action_menu = QMenu()
        misc_action.setMenu(misc_action_menu)
        misc_action.setPopupMode(QToolButton.InstantPopup)
        misc_action.setToolTip("Contains misc. features")
        misc_action_random = QAction("Open random gallery", misc_action_menu)
        misc_action_random.triggered.connect(self.manga_list_view.open_random_gallery)
        misc_action_menu.addAction(misc_action_random)
        duplicate_check_simple = QAction("Simple duplicate finder", misc_action_menu)
        duplicate_check_simple.triggered.connect(lambda: self.manga_list_view.duplicate_check())
        misc_action_menu.addAction(duplicate_check_simple)
        self.toolbar.addWidget(misc_action)

        spacer_middle = QWidget()  # aligns buttons to the right
        spacer_middle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.toolbar.addWidget(spacer_middle)

        self.grid_toggle_g_icon = QIcon(gui_constants.GRID_PATH)
        self.grid_toggle_l_icon = QIcon(gui_constants.LIST_PATH)
        self.grid_toggle = QToolButton()
        if self.display.currentIndex() == self.m_l_view_index:
            self.grid_toggle.setIcon(self.grid_toggle_l_icon)
        else:
            self.grid_toggle.setIcon(self.grid_toggle_g_icon)
        self.grid_toggle.setObjectName("gridtoggle")
        self.grid_toggle.clicked.connect(self.toggle_view)
        self.toolbar.addWidget(self.grid_toggle)

        self.search_bar = misc.LineEdit()
        if gui_constants.SEARCH_AUTOCOMPLETE:
            completer = QCompleter(self)
            completer.setModel(self.manga_list_view.gallery_model)
            completer.setCaseSensitivity(Qt.CaseInsensitive)
            completer.setCompletionMode(QCompleter.PopupCompletion)
            completer.setCompletionRole(Qt.DisplayRole)
            completer.setCompletionColumn(gui_constants.TITLE)
            completer.setFilterMode(Qt.MatchContains)
            self.search_bar.setCompleter(completer)
        if gui_constants.SEARCH_ON_ENTER:
            self.search_bar.returnPressed.connect(lambda: self.search(self.search_bar.text()))
        else:
            self.search_bar.textChanged[str].connect(self.search)
        self.search_bar.setPlaceholderText("Search title, artist, namespace & tags")
        self.search_bar.setMinimumWidth(150)
        self.search_bar.setMaximumWidth(500)
        self.toolbar.addWidget(self.search_bar)
        self.toolbar.addSeparator()
        settings_icon = QIcon(gui_constants.SETTINGS_PATH)
        settings_action = QAction("Set&tings", self)
        settings_action.triggered.connect(self.settings)
        self.toolbar.addAction(settings_action)

        spacer_end = QWidget()  # aligns About action properly
        spacer_end.setFixedSize(QSize(10, 1))
        self.toolbar.addWidget(spacer_end)
        self.addToolBar(self.toolbar)

    def toggle_view(self):
        """
		Toggles the current display view
		"""
        if self.display.currentIndex() == self.m_l_view_index:
            self.display.setCurrentIndex(self.m_t_view_index)
            self.grid_toggle.setIcon(self.grid_toggle_g_icon)
        else:
            self.display.setCurrentIndex(self.m_l_view_index)
            self.grid_toggle.setIcon(self.grid_toggle_l_icon)

            # TODO: Improve this so that it adds to the gallery dialog,
            # so user can edit data before inserting (make it a choice)

    def populate(self, mixed=None):
        "Populates the database with gallery from local drive'"
        if mixed:
            gallery_view = misc.GalleryListView(self, True)
            gallery_view.SERIES.connect(self.gallery_populate)
            gallery_view.show()
        else:
            path = QFileDialog.getExistingDirectory(None, "Choose a folder containing your galleries")
            self.gallery_populate(path, True)

    def gallery_populate(self, path, validate=False):
        "Scans the given path for gallery to add into the DB"
        if len(path) is not 0:
            data_thread = QThread(self)
            data_thread.setObjectName("General gallery populate")
            loading = misc.Loading(self)
            if not loading.ON:
                misc.Loading.ON = True
                fetch_instance = fetch.Fetch()
                fetch_instance.series_path = path
                loading.show()

                def finished(status):
                    def hide_loading():
                        loading.hide()

                    if status:
                        if len(status) != 0:

                            def add_gallery(gallery_list):
                                def append_to_model(x):
                                    self.manga_list_view.gallery_model.insertRows(x, None, len(x))

                                class A(QObject):
                                    done = pyqtSignal()
                                    prog = pyqtSignal(int)

                                    def __init__(self, obj, parent=None):
                                        super().__init__(parent)
                                        self.obj = obj
                                        self.galleries = []

                                    def add_to_db(self):
                                        gui_constants.NOTIF_BAR.begin_show()
                                        gui_constants.NOTIF_BAR.add_text("Populating database...")
                                        for y, x in enumerate(self.obj):
                                            gui_constants.NOTIF_BAR.add_text(
                                                "Populating database {}/{}".format(y + 1, len(self.obj))
                                            )
                                            gallerydb.add_method_queue(gallerydb.GalleryDB.add_gallery_return, False, x)
                                            self.galleries.append(x)
                                            y += 1
                                            self.prog.emit(y)
                                        append_to_model(self.galleries)
                                        gui_constants.NOTIF_BAR.end_show()
                                        self.done.emit()

                                loading.progress.setMaximum(len(gallery_list))
                                a_instance = A(gallery_list)
                                thread = QThread(self)
                                thread.setObjectName("Database populate")

                                def loading_show():
                                    loading.setText("Populating database.\nPlease wait...")
                                    loading.show()

                                def loading_hide():
                                    loading.close()
                                    self.manga_list_view.gallery_model.ROWCOUNT_CHANGE.emit()

                                def del_later():
                                    try:
                                        a_instance.deleteLater()
                                    except NameError:
                                        pass

                                a_instance.moveToThread(thread)
                                a_instance.prog.connect(loading.progress.setValue)
                                thread.started.connect(loading_show)
                                thread.started.connect(a_instance.add_to_db)
                                a_instance.done.connect(loading_hide)
                                a_instance.done.connect(del_later)
                                thread.finished.connect(thread.deleteLater)
                                thread.start()

                            data_thread.quit
                            hide_loading()
                            log_i("Populating DB from gallery folder: OK")
                            if validate:
                                gallery_list = misc.GalleryListView(self)
                                gallery_list.SERIES.connect(add_gallery)
                                for ser in status:
                                    gallery_list.add_gallery(ser, os.path.split(ser.path)[1])
                                    # self.manga_list_view.gallery_model.populate_data()
                                gallery_list.show()
                            else:
                                add_gallery(status)
                            misc.Loading.ON = False
                        else:
                            log_d("No new gallery was found")
                            loading.setText("No new gallery found")
                            data_thread.quit
                            misc.Loading.ON = False

                    else:
                        log_e("Populating DB from gallery folder: Nothing was added!")
                        loading.setText("<font color=red>Nothing was added. Check happypanda_log for details..</font>")
                        loading.progress.setStyleSheet("background-color:red;")
                        data_thread.quit
                        QTimer.singleShot(10000, loading.close)

                def fetch_deleteLater():
                    try:
                        fetch_instance.deleteLater
                    except NameError:
                        pass

                def a_progress(prog):
                    loading.progress.setValue(prog)
                    loading.setText("Searching for galleries...")

                fetch_instance.moveToThread(data_thread)
                fetch_instance.DATA_COUNT.connect(loading.progress.setMaximum)
                fetch_instance.PROGRESS.connect(a_progress)
                data_thread.started.connect(fetch_instance.local)
                fetch_instance.FINISHED.connect(finished)
                fetch_instance.FINISHED.connect(fetch_deleteLater)
                data_thread.finished.connect(data_thread.deleteLater)
                data_thread.start()
                log_i("Populating DB from gallery folder")

    def resizeEvent(self, event):
        try:
            self.notification_bar.resize(event.size().width())
        except AttributeError:
            pass
        return super().resizeEvent(event)

    def closeEvent(self, event):
        # watchers
        try:
            self.watchers.stop_all()
        except AttributeError:
            pass

            # settings
        settings.set(self.manga_list_view.current_sort, "General", "current sort")
        settings.win_save(self, "AppWindow")

        # temp dir
        try:
            for root, dirs, files in os.walk("temp", topdown=False):
                for name in files:
                    os.remove(os.path.join(root, name))
                for name in dirs:
                    os.rmdir(os.path.join(root, name))
            log_d("Empty temp on exit: OK")
        except:
            log_d("Empty temp on exit: FAIL")

            # error
        err = sys.exc_info()
        if all(err):
            log_c("Last error before exit:\n{}\n{}\n{}".format(err[0], err[1], err[2]))
        else:
            log_d("Normal Exit App: OK")
        super().closeEvent(event)
        app = QApplication.instance()
        app.quit()
        sys.exit()
コード例 #8
0
ファイル: app.py プロジェクト: darmstard/happypanda
class AppWindow(QMainWindow):
	"The application's main window"
	move_listener = pyqtSignal()
	db_activity_checker = pyqtSignal()
	graphics_blur = QGraphicsBlurEffect()
	def __init__(self):
		super().__init__()
		app_constants.GENERAL_THREAD = QThread(self)
		app_constants.GENERAL_THREAD.finished.connect(app_constants.GENERAL_THREAD.deleteLater)
		app_constants.GENERAL_THREAD.start()
		self.setAcceptDrops(True)
		self.initUI()
		self.start_up()
		QTimer.singleShot(3000, self._check_update)
		self.setFocusPolicy(Qt.NoFocus)
		self.set_shortcuts()
		self.graphics_blur.setParent(self)
		#ex = settings.ExProperties()
		#d = pewnet.ExHenManager(ex.ipb_id, ex.ipb_pass)
		#item = d.from_gallery_url('http://exhentai.org/g/861957/02741dc584/')
		#def a(): print(item.file)
		#if not item.file:
		#	item.file_rdy.connect(a)
		#else:
		#	a()

	def set_shortcuts(self):
		quit = QShortcut(QKeySequence('Ctrl+Q'), self, self.close)

	def init_watchers(self):

		def remove_gallery(g):
			index = self.manga_list_view.find_index(g.id, True)
			if index:
				self.manga_list_view.remove_gallery([index])

		def create_gallery(path):
			g_dia = gallerydialog.GalleryDialog(self, path)
			g_dia.SERIES.connect(self.manga_list_view.gallery_model.addRows)
			g_dia.show()

		def update_gallery(g):
			index = self.manga_list_view.find_index(g.id)
			if index:
				self.manga_list_view.replace_edit_gallery([g], index.row())
			else:
				log_e('Could not find gallery to update from watcher')

		def created(path):
			c_popup = io_misc.CreatedPopup(path, self)
			c_popup.ADD_SIGNAL.connect(create_gallery)
		def modified(path, gallery):
			mod_popup = io_misc.ModifiedPopup(path, gallery, self)
		def deleted(path, gallery):
			d_popup = io_misc.DeletedPopup(path, gallery, self)
			d_popup.UPDATE_SIGNAL.connect(update_gallery)
			d_popup.REMOVE_SIGNAL.connect(remove_gallery)
		def moved(new_path, gallery):
			mov_popup = io_misc.MovedPopup(new_path, gallery, self)
			mov_popup.UPDATE_SIGNAL.connect(update_gallery)

		self.watchers = io_misc.Watchers()
		self.watchers.gallery_handler.CREATE_SIGNAL.connect(created)
		self.watchers.gallery_handler.MODIFIED_SIGNAL.connect(modified)
		self.watchers.gallery_handler.MOVED_SIGNAL.connect(moved)
		self.watchers.gallery_handler.DELETED_SIGNAL.connect(deleted)

	admin_db_method_invoker = pyqtSignal(str)
	def start_up(self):
		hello = ["Hello!", "Hi!", "Onii-chan!", "Senpai!", "Hisashiburi!", "Welcome!", "Okaerinasai!", "Welcome back!", "Hajimemashite!"]
		self.notification_bar.add_text("{} Please don't hesitate to report any bugs you find.".format(hello[random.randint(0, len(hello)-1)])+
								 " Go to Settings -> About -> Bug Reporting for more info!")
		level = 5
		def normalize_first_time():
			settings.set(level, 'Application', 'first time level')
			settings.save()

		def done(status=True):
			gallerydb.DatabaseEmitter.RUN = True
			if app_constants.FIRST_TIME_LEVEL != level:
				normalize_first_time()
			if app_constants.ENABLE_MONITOR and\
				app_constants.MONITOR_PATHS and all(app_constants.MONITOR_PATHS):
				self.init_watchers()
				if app_constants.LOOK_NEW_GALLERY_STARTUP:
					if self.manga_list_view.gallery_model.db_emitter.count == app_constants.GALLERY_DATA:
						self.scan_for_new_galleries()
					else:
						self.manga_list_view.gallery_model.db_emitter.DONE.connect(self.scan_for_new_galleries)
			self.download_manager = pewnet.Downloader()
			app_constants.DOWNLOAD_MANAGER = self.download_manager
			self.download_manager.start_manager(4)

		if app_constants.FIRST_TIME_LEVEL < 4:
			log_i('Invoking first time level {}'.format(4))
			settings.set([], 'Application', 'monitor paths')
			settings.set([], 'Application', 'ignore paths')
			app_constants.MONITOR_PATHS = []
			app_constants.IGNORE_PATHS = []
			settings.save()
			done()
		elif app_constants.FIRST_TIME_LEVEL < 5:
			log_i('Invoking first time level {}'.format(5))
			app_widget = misc.ApplicationPopup(self)
			app_widget.note_info.setText("<font color='red'>IMPORTANT:</font> Application restart is required when done")
			app_widget.restart_info.hide()
			self.admin_db = gallerydb.AdminDB()
			self.admin_db.moveToThread(app_constants.GENERAL_THREAD)
			self.admin_db.DONE.connect(done)
			self.admin_db.DONE.connect(lambda: app_constants.NOTIF_BAR.add_text("Application requires a restart"))
			self.admin_db.DONE.connect(self.admin_db.deleteLater)
			self.admin_db.DATA_COUNT.connect(app_widget.prog.setMaximum)
			self.admin_db.PROGRESS.connect(app_widget.prog.setValue)
			self.admin_db_method_invoker.connect(self.admin_db.rebuild_db)
			self.admin_db_method_invoker.connect(app_widget.show)
			app_widget.adjustSize()
			db_p = os.path.join(os.path.split(database.db_constants.DB_PATH)[0], 'sadpanda.db')
			self.admin_db_method_invoker.emit(db_p)
		else:
			done()

	def initUI(self):
		self.center = QWidget()
		self.display = QStackedLayout()
		self._main_layout = QVBoxLayout()
		self._main_layout.setSpacing(0)
		self._main_layout.setContentsMargins(0,0,0,0)
		self._main_layout.addLayout(self.display)
		self.center.setLayout(self._main_layout)
		# init the manga view variables
		self.manga_display()
		log_d('Create manga display: OK')
		# init the chapter view variables
		#self.chapter_display()
		self.m_l_view_index = self.display.addWidget(self.manga_list_view)
		self.m_t_view_index = self.display.addWidget(self.manga_table_view)
		self.download_window = io_misc.GalleryDownloader(self)
		self.download_window.hide()
		# init toolbar
		self.init_toolbar()
		log_d('Create toolbar: OK')
		# init status bar
		self.init_stat_bar()
		log_d('Create statusbar: OK')

		self.tags_treeview = None
		if app_constants.TAGS_TREEVIEW_ON_START:
			def tags_tree_none(): self.tags_treeview = None
			self.tags_treeview = misc_db.DBOverview(self, True)
			self.tags_treeview.about_to_close.connect(tags_tree_none)
			self.tags_treeview.show()

		self.system_tray = misc.SystemTray(QIcon(app_constants.APP_ICO_PATH), self)
		app_constants.SYSTEM_TRAY = self.system_tray
		tray_menu = QMenu(self)
		self.system_tray.setContextMenu(tray_menu)
		self.system_tray.setToolTip('Happypanda {}'.format(app_constants.vs))
		tray_quit = QAction('Quit', tray_menu)
		tray_update = tray_menu.addAction('Check for update')
		tray_update.triggered.connect(self._check_update)
		tray_menu.addAction(tray_quit)
		tray_quit.triggered.connect(self.close)
		self.system_tray.show()
		def tray_activate(r=None):
			if not r or r == QSystemTrayIcon.Trigger:
				self.showNormal()
				self.activateWindow()
		self.system_tray.messageClicked.connect(tray_activate)
		self.system_tray.activated.connect(tray_activate)
		log_d('Create system tray: OK')
		#self.display.addWidget(self.chapter_main)

		self.setCentralWidget(self.center)
		self.setWindowIcon(QIcon(app_constants.APP_ICO_PATH))


		props = settings.win_read(self, 'AppWindow')
		if props.resize:
			x, y = props.resize
			self.resize(x, y)
		else:
			self.resize(app_constants.MAIN_W, app_constants.MAIN_H)
		posx, posy = props.pos
		self.move(posx, posy)
		self.init_spinners()
		self.show()
		log_d('Show window: OK')

		self.notification_bar = misc.NotificationOverlay(self)
		p = self.toolbar.pos()
		self.notification_bar.move(p.x(), p.y()+self.toolbar.height())
		self.notification_bar.resize(self.width())
		app_constants.NOTIF_BAR = self.notification_bar
		log_d('Create notificationbar: OK')

		log_d('Window Create: OK')

	def _check_update(self):
		class upd_chk(QObject):
			UPDATE_CHECK = pyqtSignal(str)
			def __init__(self, **kwargs):
				super().__init__(**kwargs)
			def fetch_vs(self):
				import requests
				import time
				log_d('Checking Update')
				time.sleep(1.5)
				try:
					if os.path.exists('cacert.pem'):
						r = requests.get("https://raw.githubusercontent.com/Pewpews/happypanda/master/VS.txt",
							  verify='cacert.pem')
					else:
						r = requests.get("https://raw.githubusercontent.com/Pewpews/happypanda/master/VS.txt")
					a = r.text
					vs = a.strip()
					self.UPDATE_CHECK.emit(vs)
				except:
					log.exception('Checking Update: FAIL')
					self.UPDATE_CHECK.emit('this is a very long text which is sure to be over limit')

		def check_update(vs):
			log_i('Received version: {}\nCurrent version: {}'.format(vs, app_constants.vs))
			if vs != app_constants.vs:
				if len(vs) < 10:
					self.notification_bar.begin_show()
					self.notification_bar.add_text("Version {} of Happypanda is".format(vs)+
									   " available. Click here to update!", False)
					self.notification_bar.clicked.connect(lambda: utils.open_web_link(
						'https://github.com/Pewpews/happypanda/releases'))
					self.notification_bar.set_clickable(True)
				else:
					self.notification_bar.add_text("An error occurred while checking for new version")

		self.update_instance = upd_chk()
		thread = QThread(self)
		self.update_instance.moveToThread(thread)
		thread.started.connect(self.update_instance.fetch_vs)
		self.update_instance.UPDATE_CHECK.connect(check_update)
		self.update_instance.UPDATE_CHECK.connect(self.update_instance.deleteLater)
		thread.finished.connect(thread.deleteLater)
		thread.start()

	def _web_metadata_picker(self, gallery, title_url_list, queue, parent=None):
		if not parent:
			parent = self
		text = "Which gallery do you want to extract metadata from?"
		s_gallery_popup = misc.SingleGalleryChoices(gallery, title_url_list,
											  text, parent)
		s_gallery_popup.USER_CHOICE.connect(queue.put)

	def get_metadata(self, gal=None):
		metadata_spinner = misc.Spinner(self)
		def move_md_spinner():
			metadata_spinner.update_move(
			QPoint(
				self.pos().x()+self.width()-65,
				self.pos().y()+self.toolbar.height()+55))
		metadata_spinner.set_text("Metadata")
		metadata_spinner.set_size(55)
		metadata_spinner.move(QPoint(self.pos().x()+self.width()-65,
							   self.pos().y()+self.toolbar.height()+55))
		self.move_listener.connect(move_md_spinner)
		thread = QThread(self)
		thread.setObjectName('App.get_metadata')
		fetch_instance = fetch.Fetch()
		if gal:
			if not isinstance(gal, list):
				galleries = [gal]
			else:
				galleries = gal
		else:
			if app_constants.CONTINUE_AUTO_METADATA_FETCHER:
				galleries = [g for g in self.manga_list_view.gallery_model._data if not g.exed]
			else:
				galleries = self.manga_list_view.gallery_model._data
			if not galleries:
				self.notification_bar.add_text('Looks like we\'ve already gone through all galleries!')
				return None
		fetch_instance.galleries = galleries

		self.notification_bar.begin_show()
		fetch_instance.moveToThread(thread)

		def done(status):
			self.notification_bar.end_show()
			fetch_instance.deleteLater()
			if not isinstance(status, bool):
				galleries = []
				for tup in status:
					galleries.append(tup[0])

				class GalleryContextMenu(QMenu):
					app_instance = self
					def __init__(self, parent=None):
						super().__init__(parent)
						show_in_library_act = self.addAction('Show in library')
						show_in_library_act.triggered.connect(self.show_in_library)

					def show_in_library(self):
						viewer = self.app_instance.manga_list_view
						index = viewer.find_index(self.gallery_widget.gallery.id, True)
						if index:
							self.app_instance.manga_table_view.scroll_to_index(index)
							self.app_instance.manga_list_view.scroll_to_index(index)

				g_popup = io_misc.GalleryPopup(('Fecthing metadata for these galleries failed.'+
									  ' Check happypanda.log for details.', galleries), self, menu=GalleryContextMenu())
				#errors = {g[0].id: g[1] for g in status}
				#for g_item in g_popup.get_all_items():
				#	g_item.setToolTip(errors[g_item.gallery.id])
				g_popup.graphics_blur.setEnabled(False)
				close_button = g_popup.add_buttons('Close')[0]
				close_button.clicked.connect(g_popup.close)

		fetch_instance.GALLERY_PICKER.connect(self._web_metadata_picker)
		fetch_instance.GALLERY_EMITTER.connect(self.manga_list_view.replace_edit_gallery)
		fetch_instance.AUTO_METADATA_PROGRESS.connect(self.notification_bar.add_text)
		thread.started.connect(fetch_instance.auto_web_metadata)
		fetch_instance.FINISHED.connect(done)
		fetch_instance.FINISHED.connect(metadata_spinner.close)
		fetch_instance.FINISHED.connect(lambda: self.move_listener.disconnect(move_md_spinner))
		thread.finished.connect(thread.deleteLater)
		thread.start()
		metadata_spinner.show()

	def init_stat_bar(self):
		self.status_bar = self.statusBar()
		self.status_bar.setMaximumHeight(20)
		self.status_bar.setSizeGripEnabled(False)
		self.stat_info = QLabel()
		self.stat_info.setIndent(5)
		self.sort_main = QAction("Asc", self)
		sort_menu = QMenu()
		self.sort_main.setMenu(sort_menu)
		s_by_title = QAction("Title", sort_menu)
		s_by_artist = QAction("Artist", sort_menu)
		sort_menu.addAction(s_by_title)
		sort_menu.addAction(s_by_artist)
		self.status_bar.addPermanentWidget(self.stat_info)
		#self.status_bar.addAction(self.sort_main)
		self.temp_msg = QLabel()
		self.temp_timer = QTimer()

		self.manga_list_view.gallery_model.ROWCOUNT_CHANGE.connect(self.stat_row_info)
		self.manga_list_view.gallery_model.db_emitter.COUNT_CHANGE.connect(self.stat_row_info)
		self.manga_list_view.gallery_model.STATUSBAR_MSG.connect(self.stat_temp_msg)
		self.manga_list_view.STATUS_BAR_MSG.connect(self.stat_temp_msg)
		self.manga_table_view.STATUS_BAR_MSG.connect(self.stat_temp_msg)
		self.stat_row_info()
		app_constants.STAT_MSG_METHOD = self.stat_temp_msg

	def stat_temp_msg(self, msg):
		self.temp_timer.stop()
		self.temp_msg.setText(msg)
		self.status_bar.addWidget(self.temp_msg)
		self.temp_timer.timeout.connect(self.temp_msg.clear)
		self.temp_timer.setSingleShot(True)
		self.temp_timer.start(5000)

	def stat_row_info(self):
		r = self.manga_list_view.model().rowCount()
		t = self.manga_list_view.gallery_model.db_emitter.count
		self.stat_info.setText("Loaded {} of {} ".format(r, t))

	def manga_display(self):
		"initiates the manga view and related things"
		#list view
		self.manga_list_view = gallery.MangaView(self)

		#table view

		self.manga_table_view = gallery.MangaTableView(self)
		self.manga_table_view.gallery_model = self.manga_list_view.gallery_model
		self.manga_table_view.sort_model = self.manga_list_view.sort_model
		self.manga_table_view.setModel(self.manga_table_view.sort_model)
		self.manga_table_view.sort_model.change_model(self.manga_table_view.gallery_model)
		self.manga_table_view.setColumnWidth(app_constants.FAV, 20)
		self.manga_table_view.setColumnWidth(app_constants.ARTIST, 200)
		self.manga_table_view.setColumnWidth(app_constants.TITLE, 400)
		self.manga_table_view.setColumnWidth(app_constants.TAGS, 300)
		self.manga_table_view.setColumnWidth(app_constants.TYPE, 60)
		self.manga_table_view.setColumnWidth(app_constants.CHAPTERS, 60)
		self.manga_table_view.setColumnWidth(app_constants.LANGUAGE, 100)
		self.manga_table_view.setColumnWidth(app_constants.LINK, 400)


	def init_spinners(self):
		# fetching spinner
		self.data_fetch_spinner = misc.Spinner(self)
		self.data_fetch_spinner.set_size(60)
		self.move_listener.connect(
			lambda: self.data_fetch_spinner.update_move(
				QPoint(self.pos().x()+self.width()//2, self.pos().y()+self.height()//2)))
		
		self.manga_list_view.gallery_model.ADD_MORE.connect(self.data_fetch_spinner.show)
		self.manga_list_view.gallery_model.db_emitter.START.connect(self.data_fetch_spinner.show)
		self.manga_list_view.gallery_model.ADDED_ROWS.connect(self.data_fetch_spinner.before_hide)
		self.manga_list_view.gallery_model.db_emitter.CANNOT_FETCH_MORE.connect(self.data_fetch_spinner.before_hide)

		## deleting spinner
		#self.gallery_delete_spinner = misc.Spinner(self)
		#self.gallery_delete_spinner.set_size(40,40)
		##self.gallery_delete_spinner.set_text('Removing...')
		#self.manga_list_view.gallery_model.rowsAboutToBeRemoved.connect(self.gallery_delete_spinner.show)
		#self.manga_list_view.gallery_model.rowsRemoved.connect(self.gallery_delete_spinner.before_hide)


	def search(self, srch_string):
		self.search_bar.setText(srch_string)
		self.search_backward.setVisible(True)
		self.manga_list_view.sort_model.init_search(srch_string)
		old_cursor_pos = self._search_cursor_pos[0]
		self.search_bar.end(False)
		if self.search_bar.cursorPosition() != old_cursor_pos+1:
			self.search_bar.setCursorPosition(old_cursor_pos)


	def favourite_display(self):
		"Switches to favourite display"
		self.manga_table_view.sort_model.fav_view()
		self.favourite_btn.selected = True
		self.library_btn.selected = False

	def catalog_display(self):
		"Switches to catalog display"
		self.manga_table_view.sort_model.catalog_view()
		self.library_btn.selected = True
		self.favourite_btn.selected = False

	def settings(self):
		sett = settingsdialog.SettingsDialog(self)
		sett.scroll_speed_changed.connect(self.manga_list_view.updateGeometries)
		#sett.show()

	def init_toolbar(self):
		self.toolbar = QToolBar()
		self.toolbar.setFixedHeight(25)
		self.toolbar.setWindowTitle("Show") # text for the contextmenu
		#self.toolbar.setStyleSheet("QToolBar {border:0px}") # make it user defined?
		self.toolbar.setMovable(False)
		self.toolbar.setFloatable(False)
		#self.toolbar.setIconSize(QSize(20,20))
		self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
		self.toolbar.setIconSize(QSize(20,20))

		spacer_start = QWidget() # aligns the first actions properly
		spacer_start.setFixedSize(QSize(10, 1))
		self.toolbar.addWidget(spacer_start)

		self.favourite_btn = misc.ToolbarButton(self.toolbar, 'Favorites')
		self.toolbar.addWidget(self.favourite_btn)
		self.favourite_btn.clicked.connect(self.favourite_display) #need lambda to pass extra args

		self.library_btn = misc.ToolbarButton(self.toolbar, 'Library')
		self.toolbar.addWidget(self.library_btn)
		self.library_btn.clicked.connect(self.catalog_display) #need lambda to pass extra args
		self.library_btn.selected = True

		self.toolbar.addSeparator()

		gallery_menu = QMenu()
		gallery_action = QToolButton()
		gallery_action.setText('Gallery ')
		gallery_action.setPopupMode(QToolButton.InstantPopup)
		gallery_action.setToolTip('Contains various gallery related features')
		gallery_action.setMenu(gallery_menu)
		add_gallery_icon = QIcon(app_constants.PLUS_PATH)
		gallery_action_add = QAction(add_gallery_icon, "Add single gallery...", self)
		gallery_action_add.triggered.connect(self.manga_list_view.SERIES_DIALOG.emit)
		gallery_action_add.setToolTip('Add a single gallery thoroughly')
		gallery_menu.addAction(gallery_action_add)
		add_more_action = QAction(add_gallery_icon, "Add galleries...", self)
		add_more_action.setStatusTip('Add galleries from different folders')
		add_more_action.triggered.connect(lambda: self.populate(True))
		gallery_menu.addAction(add_more_action)
		populate_action = QAction(add_gallery_icon, "Populate from directory/archive...", self)
		populate_action.setStatusTip('Populates the DB with galleries from a single folder or archive')
		populate_action.triggered.connect(self.populate)
		gallery_menu.addAction(populate_action)
		gallery_menu.addSeparator()
		metadata_action = QAction('Get metadata for all galleries', self)
		metadata_action.triggered.connect(self.get_metadata)
		gallery_menu.addAction(metadata_action)
		scan_galleries_action = QAction('Scan for new galleries', self)
		scan_galleries_action.triggered.connect(self.scan_for_new_galleries)
		scan_galleries_action.setStatusTip('Scan monitored folders for new galleries')
		gallery_menu.addAction(scan_galleries_action)
		gallery_action_random = gallery_menu.addAction("Open random gallery")
		gallery_action_random.triggered.connect(self.manga_list_view.open_random_gallery)
		self.toolbar.addWidget(gallery_action)


		misc_action = QToolButton()
		misc_action.setText('Tools ')
		misc_action_menu = QMenu()
		misc_action.setMenu(misc_action_menu)
		misc_action.setPopupMode(QToolButton.InstantPopup)
		misc_action.setToolTip("Contains misc. features")
		gallery_downloader = QAction("Gallery Downloader", misc_action_menu)
		gallery_downloader.triggered.connect(self.download_window.show)
		misc_action_menu.addAction(gallery_downloader)
		duplicate_check_simple = QAction("Simple Duplicate Finder", misc_action_menu)
		duplicate_check_simple.triggered.connect(lambda: self.manga_list_view.duplicate_check())
		misc_action_menu.addAction(duplicate_check_simple)
		self.toolbar.addWidget(misc_action)

		spacer_middle = QWidget() # aligns buttons to the right
		spacer_middle.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
		self.toolbar.addWidget(spacer_middle)


		sort_action = QToolButton()
		sort_action.setIcon(QIcon(app_constants.SORT_PATH))
		sort_action.setMenu(misc.SortMenu(self.toolbar, self.manga_list_view))
		sort_action.setPopupMode(QToolButton.InstantPopup)
		self.toolbar.addWidget(sort_action)
		
		self.grid_toggle_g_icon = QIcon(app_constants.GRID_PATH)
		self.grid_toggle_l_icon = QIcon(app_constants.LIST_PATH)
		self.grid_toggle = QToolButton()
		if self.display.currentIndex() == self.m_l_view_index:
			self.grid_toggle.setIcon(self.grid_toggle_l_icon)
		else:
			self.grid_toggle.setIcon(self.grid_toggle_g_icon)
		self.grid_toggle.setObjectName('gridtoggle')
		self.grid_toggle.clicked.connect(self.toggle_view)
		self.toolbar.addWidget(self.grid_toggle)

		spacer_mid2 = QWidget()
		spacer_mid2.setFixedSize(QSize(5, 1))
		self.toolbar.addWidget(spacer_mid2)

		def set_search_case(b):
			app_constants.GALLERY_SEARCH_CASE = b
			settings.set(b, 'Application', 'gallery search case')
			settings.save()

		def set_search_strict(b):
			app_constants.GALLERY_SEARCH_STRICT = b
			settings.set(b, 'Application', 'gallery search strict')
			settings.save()

		self.search_bar = misc.LineEdit()
		search_options = self.search_bar.addAction(QIcon(app_constants.SEARCH_OPTIONS_PATH), QLineEdit.TrailingPosition)
		search_options_menu = QMenu(self)
		search_options.triggered.connect(lambda: search_options_menu.popup(QCursor.pos()))
		search_options.setMenu(search_options_menu)
		case_search_option = search_options_menu.addAction('Case Sensitive')
		case_search_option.setCheckable(True)
		case_search_option.setChecked(app_constants.GALLERY_SEARCH_CASE)
		case_search_option.toggled.connect(set_search_case)
		strict_search_option = search_options_menu.addAction('Match whole terms')
		strict_search_option.setCheckable(True)
		strict_search_option.setChecked(app_constants.GALLERY_SEARCH_STRICT)
		strict_search_option.toggled.connect(set_search_strict)
		self.search_bar.setObjectName('search_bar')
		self.search_timer = QTimer(self)
		self.search_timer.setSingleShot(True)
		self.search_timer.timeout.connect(lambda: self.search(self.search_bar.text()))
		self._search_cursor_pos = [0, 0]
		def set_cursor_pos(old, new):
			self._search_cursor_pos[0] = old
			self._search_cursor_pos[1] = new
		self.search_bar.cursorPositionChanged.connect(set_cursor_pos)

		if app_constants.SEARCH_AUTOCOMPLETE:
			completer = QCompleter(self)
			completer_view = misc.CompleterPopupView()
			completer.setPopup(completer_view)
			completer_view._setup()
			completer.setModel(self.manga_list_view.gallery_model)
			completer.setCaseSensitivity(Qt.CaseInsensitive)
			completer.setCompletionMode(QCompleter.PopupCompletion)
			completer.setCompletionRole(Qt.DisplayRole)
			completer.setCompletionColumn(app_constants.TITLE)
			completer.setFilterMode(Qt.MatchContains)
			self.search_bar.setCompleter(completer)
			self.search_bar.returnPressed.connect(lambda: self.search(self.search_bar.text()))
		if not app_constants.SEARCH_ON_ENTER:
			self.search_bar.textEdited.connect(lambda: self.search_timer.start(800))
		self.search_bar.setPlaceholderText("Search title, artist, namespace & tags")
		self.search_bar.setMinimumWidth(150)
		self.search_bar.setMaximumWidth(500)
		self.search_bar.setFixedHeight(19)
		self.manga_list_view.sort_model.HISTORY_SEARCH_TERM.connect(lambda a: self.search_bar.setText(a))
		self.toolbar.addWidget(self.search_bar)

		def search_history(_, back=True): # clicked signal passes a bool
			sort_model =  self.manga_list_view.sort_model
			nav = sort_model.PREV if back else sort_model.NEXT
			history_term = sort_model.navigate_history(nav)
			if back:
				self.search_forward.setVisible(True)

		back = QShortcut(QKeySequence(QKeySequence.Back), self, lambda: search_history(None))
		forward = QShortcut(QKeySequence(QKeySequence.Forward), self, lambda: search_history(None, False))

		search_backbutton = QToolButton(self.toolbar)
		search_backbutton.setText(u'\u25C0')
		search_backbutton.setFixedWidth(15)
		search_backbutton.clicked.connect(search_history)
		self.search_backward = self.toolbar.addWidget(search_backbutton)
		self.search_backward.setVisible(False)
		search_forwardbutton = QToolButton(self.toolbar)
		search_forwardbutton.setText(u'\u25B6')
		search_forwardbutton.setFixedWidth(15)
		search_forwardbutton.clicked.connect(lambda: search_history(None, False))
		self.search_forward = self.toolbar.addWidget(search_forwardbutton)
		self.search_forward.setVisible(False)

		spacer_end = QWidget() # aligns settings action properly
		spacer_end.setFixedSize(QSize(10, 1))
		self.toolbar.addWidget(spacer_end)

		settings_act = QToolButton(self.toolbar)
		settings_act.setIcon(QIcon(app_constants.SETTINGS_PATH))
		settings_act.clicked.connect(self.settings)
		self.toolbar.addWidget(settings_act)

		spacer_end2 = QWidget() # aligns About action properly
		spacer_end2.setFixedSize(QSize(5, 1))
		self.toolbar.addWidget(spacer_end2)
		self.addToolBar(self.toolbar)

	def toggle_view(self):
		"""
		Toggles the current display view
		"""
		if self.display.currentIndex() == self.m_l_view_index:
			self.display.setCurrentIndex(self.m_t_view_index)
			self.grid_toggle.setIcon(self.grid_toggle_g_icon)
		else:
			self.display.setCurrentIndex(self.m_l_view_index)
			self.grid_toggle.setIcon(self.grid_toggle_l_icon)

	# TODO: Improve this so that it adds to the gallery dialog,
	# so user can edit data before inserting (make it a choice)
	def populate(self, mixed=None):
		"Populates the database with gallery from local drive'"
		if mixed:
			gallery_view = misc.GalleryListView(self, True)
			gallery_view.SERIES.connect(self.gallery_populate)
			gallery_view.show()
		else:
			msg_box = misc.BasePopup(self)
			l = QVBoxLayout()
			msg_box.main_widget.setLayout(l)
			l.addWidget(QLabel('Directory or Archive?'))
			l.addLayout(msg_box.buttons_layout)

			def from_dir():
				path = QFileDialog.getExistingDirectory(self, "Choose a directory containing your galleries")
				if not path:
					return
				msg_box.close()
				app_constants.OVERRIDE_SUBFOLDER_AS_GALLERY = True
				self.gallery_populate(path, True)
			def from_arch():
				path = QFileDialog.getOpenFileName(self, 'Choose an archive containing your galleries',
									   filter=utils.FILE_FILTER)
				path = [path[0]]
				if not all(path) or not path:
					return
				msg_box.close()
				app_constants.OVERRIDE_SUBFOLDER_AS_GALLERY = True
				self.gallery_populate(path, True)

			buttons = msg_box.add_buttons('Directory', 'Archive', 'Close')
			buttons[2].clicked.connect(msg_box.close)
			buttons[0].clicked.connect(from_dir)
			buttons[1].clicked.connect(from_arch)
			msg_box.adjustSize()
			msg_box.show()

	def gallery_populate(self, path, validate=False):
		"Scans the given path for gallery to add into the DB"
		if len(path) is not 0:
			data_thread = QThread(self)
			data_thread.setObjectName('General gallery populate')
			loading = misc.Loading(self)
			self.g_populate_inst = fetch.Fetch()
			self.g_populate_inst.series_path = path
			loading.show()

			def finished(status):
				def hide_loading():
					loading.hide()
				if status:
					if len(status) != 0:
						def add_gallery(gallery_list):
							def append_to_model(x):
								self.manga_list_view.sort_model.insertRows(x, None, len(x))
								self.manga_list_view.sort_model.init_search(
									self.manga_list_view.sort_model.current_term)

							class A(QObject):
								done = pyqtSignal()
								prog = pyqtSignal(int)
								def __init__(self, obj, parent=None):
									super().__init__(parent)
									self.obj = obj
									self.galleries = []

								def add_to_db(self):
									for y, x in enumerate(self.obj):
										gallerydb.add_method_queue(
											gallerydb.GalleryDB.add_gallery_return, False, x)
										self.galleries.append(x)
										y += 1
										self.prog.emit(y)
									append_to_model(self.galleries)
									self.done.emit()
							loading.progress.setMaximum(len(gallery_list))
							self.a_instance = A(gallery_list)
							thread = QThread(self)
							thread.setObjectName('Database populate')
							def loading_show(numb):
								if loading.isHidden():
									loading.show()
								loading.setText('Populating database ({}/{})\nPlease wait...'.format(
									numb, loading.progress.maximum()))
								loading.progress.setValue(numb)
								loading.show()

							def loading_hide():
								loading.close()
								self.manga_list_view.gallery_model.ROWCOUNT_CHANGE.emit()

							self.a_instance.moveToThread(thread)
							self.a_instance.prog.connect(loading_show)
							thread.started.connect(self.a_instance.add_to_db)
							self.a_instance.done.connect(loading_hide)
							self.a_instance.done.connect(self.a_instance.deleteLater)
							#a_instance.add_to_db()
							thread.finished.connect(thread.deleteLater)
							thread.start()
						#data_thread.quit
						hide_loading()
						log_i('Populating DB from gallery folder: OK')
						if validate:
							gallery_list = misc.GalleryListView(self)
							gallery_list.SERIES.connect(add_gallery)
							for ser in status:
								if ser.is_archive and app_constants.SUBFOLDER_AS_GALLERY:
									p = os.path.split(ser.path)[1]
									if ser.chapters[0].path:
										pt_in_arch = os.path.split(ser.path_in_archive)
										pt_in_arch = pt_in_arch[1] or pt_in_arch[0]
										text = '{}: {}'.format(p, pt_in_arch)
									else:
										text = p
									gallery_list.add_gallery(ser, text)
								else:
									gallery_list.add_gallery(ser, os.path.split(ser.path)[1])
							#self.manga_list_view.gallery_model.populate_data()
							gallery_list.update_count()
							gallery_list.show()
						else:
							add_gallery(status)
					else:
						log_d('No new gallery was found')
						loading.setText("No new gallery found")
						#data_thread.quit

				else:
					log_e('Populating DB from gallery folder: Nothing was added!')
					loading.setText("<font color=red>Nothing was added. Check happypanda_log for details..</font>")
					loading.progress.setStyleSheet("background-color:red;")
					data_thread.quit
					QTimer.singleShot(8000, loading.close)

			def skipped_gs(s_list):
				"Skipped galleries"
				msg_box = QMessageBox(self)
				msg_box.setIcon(QMessageBox.Question)
				msg_box.setText('Do you want to view skipped paths?')
				msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
				msg_box.setDefaultButton(QMessageBox.No)
				if msg_box.exec() == QMessageBox.Yes:
					list_wid = QTableWidget(self)
					list_wid.setAttribute(Qt.WA_DeleteOnClose)
					list_wid.setRowCount(len(s_list))
					list_wid.setColumnCount(2)
					list_wid.setAlternatingRowColors(True)
					list_wid.setEditTriggers(list_wid.NoEditTriggers)
					list_wid.setHorizontalHeaderLabels(['Reason', 'Path'])
					list_wid.setSelectionBehavior(list_wid.SelectRows)
					list_wid.setSelectionMode(list_wid.SingleSelection)
					list_wid.setSortingEnabled(True)
					list_wid.verticalHeader().hide()
					list_wid.setAutoScroll(False)
					for x, g in enumerate(s_list):
						list_wid.setItem(x, 0, QTableWidgetItem(g[1]))
						list_wid.setItem(x, 1, QTableWidgetItem(g[0]))
					list_wid.resizeColumnsToContents()
					list_wid.setWindowTitle('{} skipped paths'.format(len(s_list)))
					list_wid.setWindowFlags(Qt.Window)
					list_wid.resize(900,400)

					list_wid.doubleClicked.connect(lambda i: utils.open_path(
						list_wid.item(i.row(), 1).text(), list_wid.item(i.row(), 1).text()))

					list_wid.show()

			def a_progress(prog):
				loading.progress.setValue(prog)
				loading.setText("Preparing galleries...")

			self.g_populate_inst.moveToThread(data_thread)
			self.g_populate_inst.DATA_COUNT.connect(loading.progress.setMaximum)
			self.g_populate_inst.PROGRESS.connect(a_progress)
			self.g_populate_inst.FINISHED.connect(finished)
			self.g_populate_inst.FINISHED.connect(self.g_populate_inst.deleteLater)
			self.g_populate_inst.SKIPPED.connect(skipped_gs)
			data_thread.finished.connect(data_thread.deleteLater)
			data_thread.started.connect(self.g_populate_inst.local)
			data_thread.start()
			#.g_populate_inst.local()
			log_i('Populating DB from directory/archive')

	def scan_for_new_galleries(self):
		available_folders =  app_constants.ENABLE_MONITOR and\
									app_constants.MONITOR_PATHS and all(app_constants.MONITOR_PATHS)
		if available_folders and not app_constants.SCANNING_FOR_GALLERIES:
			app_constants.SCANNING_FOR_GALLERIES = True
			self.notification_bar.add_text("Scanning for new galleries...")
			log_i('Scanning for new galleries...')
			try:
				class ScanDir(QObject):
					final_paths_and_galleries = pyqtSignal(list, list)
					finished = pyqtSignal()
					def __init__(self, parent=None):
						super().__init__(parent)
						self.scanned_data = []
					def scan_dirs(self):
						paths = []
						for p in app_constants.MONITOR_PATHS:
							if os.path.exists(p):
								dir_content = scandir.scandir(p)
								for d in dir_content:
									paths.append(d.path)
							else:
								log_e("Monitored path does not exists: {}".format(p.encode(errors='ignore')))

						fetch_inst = fetch.Fetch(self)
						fetch_inst.series_path = paths
						def set_scanned_d(d):
							self.scanned_data = d
						fetch_inst.FINISHED.connect(set_scanned_d)
						fetch_inst.local()
						#contents = []
						#for g in self.scanned_data:
						#	contents.append(g)

						#paths = sorted(paths)
						#new_galleries = []
						#for x in contents:
						#	y = utils.b_search(paths, os.path.normcase(x.path))
						#	if not y:
						#		new_galleries.append(x)

						galleries = []
						final_paths = []
						if self.scanned_data:
							for g in self.scanned_data:
								try:
									if g.is_archive:
										g.profile = utils.get_gallery_img(g.chapters[0].path, g.path)
									else:
										g.profile = utils.get_gallery_img(g.chapters[0].path)
									if not g.profile:
										raise Exception
								except:
									g.profile = app_constants.NO_IMAGE_PATH
							
								galleries.append(g)
								final_paths.append(g.path)
						self.final_paths_and_galleries.emit(final_paths, galleries)
						self.finished.emit()
						self.deleteLater()
					#if app_constants.LOOK_NEW_GALLERY_AUTOADD:
					#	QTimer.singleShot(10000, self.gallery_populate(final_paths))
					#	return

				def show_new_galleries(final_paths, galleries):
					if final_paths and galleries:
						app_constants.OVERRIDE_MOVE_IMPORTED_IN_FETCH = True
						if app_constants.LOOK_NEW_GALLERY_AUTOADD:
							self.gallery_populate(final_paths)
						else:

							class NewGalleryMenu(QMenu):

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

									ignore_act = self.addAction('Add to ignore list')
									ignore_act.triggered.connect(self.add_to_ignore)

								def add_to_ignore(self):
									gallery = self.gallery_widget.gallery
									app_constants.IGNORE_PATHS.append(gallery.path)
									settings.set(app_constants.IGNORE_PATHS, 'Application', 'ignore paths')
									if self.gallery_widget.parent_widget.gallery_layout.count() == 1:
										self.gallery_widget.parent_widget.close()
									else:
										self.gallery_widget.close()

							if len(galleries) == 1:
								self.notification_bar.add_text("{} new gallery was discovered in one of your monitored directories".format(len(galleries)))
							else:
								self.notification_bar.add_text("{} new galleries were discovered in one of your monitored directories".format(len(galleries)))
							text = "These new galleries were discovered! Do you want to add them?"\
								if len(galleries) > 1 else "This new gallery was discovered! Do you want to add it?"
							g_popup = io_misc.GalleryPopup((text, galleries), self, NewGalleryMenu())
							buttons = g_popup.add_buttons('Add', 'Close')

							def populate_n_close():
								g_popup.close()
								self.gallery_populate(final_paths)
							buttons[0].clicked.connect(populate_n_close)
							buttons[1].clicked.connect(g_popup.close)

				def finished(): app_constants.SCANNING_FOR_GALLERIES = False

				thread = QThread(self)
				self.scan_inst = ScanDir()
				self.scan_inst.moveToThread(thread)
				self.scan_inst.final_paths_and_galleries.connect(show_new_galleries)
				self.scan_inst.finished.connect(finished)
				thread.started.connect(self.scan_inst.scan_dirs)
				#self.scan_inst.scan_dirs()
				thread.finished.connect(thread.deleteLater)
				thread.start()
			except:
				self.notification_bar.add_text('An error occured while attempting to scan for new galleries. Check happypanda.log.')
				log.exception('An error occured while attempting to scan for new galleries.')
				app_constants.SCANNING_FOR_GALLERIES = False

	def dragEnterEvent(self, event):
		if event.mimeData().hasUrls():
			event.acceptProposedAction()
		else:
			self.notification_bar.add_text('File is not supported')

	def dropEvent(self, event):
		acceptable = []
		unaccept = []
		for u in event.mimeData().urls():
			path = u.toLocalFile()
			if os.path.isdir(path) or path.endswith(utils.ARCHIVE_FILES):
				acceptable.append(path)
			else:
				unaccept.append(path)
		log_i('Acceptable dropped items: {}'.format(len(acceptable)))
		log_i('Unacceptable dropped items: {}'.format(len(unaccept)))
		log_d('Dropped items: {}\n{}'.format(acceptable, unaccept).encode(errors='ignore'))
		if acceptable:
			self.notification_bar.add_text('Adding dropped items...')
			log_i('Adding dropped items')
			l = len(acceptable) == 1
			f_item = acceptable[0]
			if f_item.endswith(utils.ARCHIVE_FILES):
				f_item = utils.check_archive(f_item)
			else:
				f_item = utils.recursive_gallery_check(f_item)
			f_item_l = len(f_item) < 2
			subfolder_as_c = not app_constants.SUBFOLDER_AS_GALLERY
			if l and subfolder_as_c or l and f_item_l:
				g_d = gallerydialog.GalleryDialog(self, acceptable[0])
				g_d.SERIES.connect(self.manga_list_view.gallery_model.addRows)
				g_d.show()
			else:
				self.gallery_populate(acceptable, True)
		else:
			text = 'File not supported' if len(unaccept) < 2 else 'Files not supported'
			self.notification_bar.add_text(text)

		if unaccept:
			self.notification_bar.add_text('Some unsupported files did not get added')

	def resizeEvent(self, event):
		try:
			self.notification_bar.resize(event.size().width())
		except AttributeError:
			pass
		self.move_listener.emit()
		return super().resizeEvent(event)

	def moveEvent(self, event):
		self.move_listener.emit()
		return super().moveEvent(event)

	def showEvent(self, event):
		return super().showEvent(event)

	def cleanup_exit(self):
		self.system_tray.hide()
		# watchers
		try:
			self.watchers.stop_all()
		except AttributeError:
			pass

		# settings
		settings.set(self.manga_list_view.current_sort, 'General', 'current sort')
		settings.set(app_constants.IGNORE_PATHS, 'Application', 'ignore paths')
		settings.win_save(self, 'AppWindow')

		# temp dir
		try:
			for root, dirs, files in scandir.walk('temp', topdown=False):
				for name in files:
					os.remove(os.path.join(root, name))
				for name in dirs:
					os.rmdir(os.path.join(root, name))
			log_d('Flush temp on exit: OK')
		except:
			log.exception('Flush temp on exit: FAIL')

		if self.tags_treeview:
			self.tags_treeview.close()
		self.download_window.close()

		# check if there is db activity
		if not gallerydb.method_queue.empty():
			class DBActivityChecker(QObject):
				FINISHED = pyqtSignal()
				def __init__(self, **kwargs):
					super().__init__(**kwargs)

				def check(self):
					gallerydb.method_queue.join()
					self.FINISHED.emit()
					self.deleteLater()

			db_activity = DBActivityChecker()
			db_spinner = misc.Spinner(self)
			self.db_activity_checker.connect(db_activity.check)
			db_activity.moveToThread(app_constants.GENERAL_THREAD)
			db_activity.FINISHED.connect(db_spinner.close)
			db_spinner.set_size(50)
			db_spinner.set_text('Activity')
			db_spinner.move(QPoint(self.pos().x()+self.width()-70, self.pos().y()+self.height()-70))
			self.move_listener.connect(lambda: db_spinner.update_move(QPoint(self.pos().x()+self.width()-70,
																	self.pos().y()+self.height()-70)))
			db_spinner.show()
			self.db_activity_checker.emit()
			msg_box = QMessageBox(self)
			msg_box.setText('Database activity detected!')
			msg_box.setInformativeText("Closing now might result in data loss." +
								 " Do you still want to close?\n(Wait for the activity spinner to hide before closing)")
			msg_box.setIcon(QMessageBox.Critical)
			msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
			msg_box.setDefaultButton(QMessageBox.No)
			if msg_box.exec() == QMessageBox.Yes:
				return 1
			else:
				return 2
		else:
			return 0

	def closeEvent(self, event):
		r_code = self.cleanup_exit()
		if r_code == 1:
			log_d('Force Exit App: OK')
			super().closeEvent(event)
		elif r_code == 2:
			log_d('Ignore Exit App')
			event.ignore()
		else:
			log_d('Normal Exit App: OK')
			super().closeEvent(event)
コード例 #9
0
ファイル: main.py プロジェクト: kylevessPL/pyqt_totalcmd
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.resize(800, 600)
        MainWindow.setMinimumSize(600, 400)
        icon = QIcon()
        icon.addPixmap(QPixmap("icon.png"), QIcon.Normal, QIcon.Off)
        font = QFont()
        font.setFamily("MS Sans Serif")
        font.setBold(True)
        font.setWeight(75)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QWidget(MainWindow)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menuFiles = QMenu(self.menubar)
        self.menuMark = QMenu(self.menubar)
        self.menuCommands = QMenu(self.menubar)
        self.menuNet = QMenu(self.menubar)
        self.menuShow = QMenu(self.menubar)
        self.menuConfiguration = QMenu(self.menubar)
        self.menuStart = QMenu(self.menubar)
        MainWindow.setMenuBar(self.menubar)
        self.helpMenuBar = QMenuBar(self.menubar)
        self.menuHelp = QMenu(self.helpMenuBar)
        self.helpMenuBar.addMenu(self.menuHelp)
        self.menubar.setCornerWidget(self.helpMenuBar)
        self.toolBar = QToolBar(MainWindow)
        self.toolBar.setMovable(False)
        MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
        self.toolBar_2 = QToolBar(MainWindow)

        font2 = QFont()
        font2.setFamily("MS Sans Serif")
        font2.setWeight(700)
        font2.setPixelSize(8)
        font2.setBold(True)

        self.model1 = QFileSystemModel()
        self.model1.setRootPath('C:\\Windows')
        self.tree1 = QTreeView()
        self.tree1.setModel(self.model1)
        self.tree1.setRootIndex(self.model1.index("C:\\Windows\\"))
        self.tree1.setAnimated(False)
        self.tree1.setFont(font2)
        self.tree1.setIndentation(20)
        self.tree1.setSortingEnabled(True)
        self.tree1.setItemsExpandable(False)
        self.tree1.setRootIsDecorated(False)
        self.tree1.sortByColumn(0, QtCore.Qt.AscendingOrder)
        self.tree1.resize(350, 480)

        self.model2 = QFileSystemModel()
        self.model2.setRootPath('C:\\Windows\\System32')
        self.tree2 = QTreeView()
        self.tree2.setModel(self.model2)
        self.tree2.setRootIndex(self.model2.index("C:\\Windows\\System32\\"))
        self.tree2.setAnimated(False)
        self.tree2.setFont(font2)
        self.tree2.setIndentation(20)
        self.tree2.setItemsExpandable(False)
        self.tree2.setRootIsDecorated(False)
        self.tree2.setSortingEnabled(True)
        self.tree2.resize(350, 480)

        for i in range(1, self.tree1.model().columnCount()):
            self.tree1.header().hideSection(i)

        for i in range(1, self.tree2.model().columnCount()):
            self.tree2.header().hideSection(i)

        self.centralHBox = QHBoxLayout()
        self.centralHBox.addWidget(self.tree1)
        self.centralHBox.addWidget(self.tree2)
        self.centralHBox.setContentsMargins(3, 3, 3, 3)
        self.centralwidget.setLayout(self.centralHBox)

        self.toolBar_2.setMovable(False)

        self.toolBar_3 = QToolBar(MainWindow)
        self.toolBar_3.setFixedHeight(30)
        self.toolBar_3.setContentsMargins(1, 1, 1, 1)
        self.dirLabel = QLabel()
        self.dirLabel.setText('c:\\Windows>')
        self.dirBox = QComboBox()
        self.dirBox.setEditable(True)
        self.dirBox.addItem('')
        self.dirBox.setFixedWidth(470)
        self.spacer = QWidget()
        self.spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        self.toolBar_3.addWidget(self.spacer)
        self.toolBar_3.addWidget(self.dirLabel)
        self.toolBar_3.addWidget(self.dirBox)
        self.toolBar_3.setFont(font)
        self.toolBar_3.setMovable(False)
        self.toolBar_3.setStyleSheet("QToolBar{spacing: 5px;}")

        MainWindow.addToolBar(QtCore.Qt.BottomToolBarArea, self.toolBar_2)
        MainWindow.addToolBar(QtCore.Qt.BottomToolBarArea, self.toolBar_3)
        MainWindow.insertToolBarBreak(self.toolBar_3)
        self.actionIndex = QAction(MainWindow)
        icon1 = QIcon()
        icon1.addPixmap(QPixmap("help.png"), QIcon.Normal, QIcon.Off)
        self.actionIndex.setIcon(icon1)
        self.actionKeyboard = QAction(MainWindow)
        self.actionRegistration_Info = QAction(MainWindow)
        self.actionVisit_Total_CMD_s_website = QAction(MainWindow)
        self.actionAbout_Total_Commander = QAction(MainWindow)
        self.actionOption_1 = QAction(MainWindow)
        self.actionOption_2 = QAction(MainWindow)
        self.actionOption_3 = QAction(MainWindow)
        self.actionOption_4 = QAction(MainWindow)
        self.actionOption_5 = QAction(MainWindow)
        self.actionOption_6 = QAction(MainWindow)
        self.actionOption_7 = QAction(MainWindow)
        self.actionOption_8 = QAction(MainWindow)
        self.actionOption_9 = QAction(MainWindow)
        self.actionOption_10 = QAction(MainWindow)
        self.actionOption_11 = QAction(MainWindow)
        self.actionOption_12 = QAction(MainWindow)
        self.actionOption_13 = QAction(MainWindow)
        self.actionOption_14 = QAction(MainWindow)
        self.Refresh = QAction(MainWindow)
        icon2 = QIcon()
        icon2.addPixmap(QPixmap("refresh.png"), QIcon.Normal, QIcon.Off)
        self.Refresh.setIcon(icon2)
        self.action_view1 = QAction(MainWindow)
        icon3 = QIcon()
        icon3.addPixmap(QPixmap("folder_structure_1.png"), QIcon.Normal,
                        QIcon.Off)
        self.view_group = QActionGroup(MainWindow)
        self.action_view1.setIcon(icon3)
        self.action_view1.setCheckable(True)
        self.action_view2 = QAction(MainWindow)
        self.action_view2.setCheckable(True)
        self.action_view2.setChecked(True)
        icon4 = QIcon()
        icon4.addPixmap(QPixmap("folder_structure_2.png"), QIcon.Normal,
                        QIcon.Off)
        self.action_view2.setIcon(icon4)
        self.view_group.addAction(self.action_view1)
        self.view_group.addAction(self.action_view2)
        self.view_group.setExclusive(True)
        self.actionF3_View = QToolButton(MainWindow)
        self.actionF3_View.setStyleSheet("QToolButton{border: none;}")
        self.actionF3_View.setFont(font)
        self.actionF4_Edit = QToolButton(MainWindow)
        self.actionF4_Edit.setStyleSheet("QToolButton{border: none;}")
        self.actionF4_Edit.setFont(font)
        self.actionF5_Copy = QToolButton(MainWindow)
        self.actionF5_Copy.setStyleSheet("QToolButton{border: none;}")
        self.actionF5_Copy.setFont(font)
        self.actionF6_Move = QToolButton(MainWindow)
        self.actionF6_Move.setStyleSheet("QToolButton{border: none;}")
        self.actionF6_Move.setFont(font)
        self.actionF5_NewFolder = QToolButton(MainWindow)
        self.actionF5_NewFolder.setStyleSheet("QToolButton{border: none;}")
        self.actionF5_NewFolder.setFont(font)
        self.actionF8_Delete = QToolButton(MainWindow)
        self.actionF8_Delete.setStyleSheet("QToolButton{border: none;}")
        self.actionF8_Delete.setFont(font)
        self.actionAlt_F4_Exit = QToolButton(MainWindow)
        self.actionAlt_F4_Exit.setStyleSheet("QToolButton{border: none;}")
        self.actionAlt_F4_Exit.setFont(font)
        self.menuFiles.addAction(self.actionOption_1)
        self.menuFiles.addAction(self.actionOption_2)
        self.menuMark.addAction(self.actionOption_3)
        self.menuMark.addAction(self.actionOption_4)
        self.menuCommands.addAction(self.actionOption_5)
        self.menuCommands.addAction(self.actionOption_6)
        self.menuNet.addAction(self.actionOption_7)
        self.menuNet.addAction(self.actionOption_8)
        self.menuShow.addAction(self.actionOption_9)
        self.menuShow.addAction(self.actionOption_10)
        self.menuConfiguration.addAction(self.actionOption_11)
        self.menuConfiguration.addAction(self.actionOption_12)
        self.menuStart.addAction(self.actionOption_13)
        self.menuStart.addAction(self.actionOption_14)
        self.menuHelp.addAction(self.actionIndex)
        self.menuHelp.addAction(self.actionKeyboard)
        self.menuHelp.addAction(self.actionRegistration_Info)
        self.menuHelp.addAction(self.actionVisit_Total_CMD_s_website)
        self.menuHelp.addSeparator()
        self.menuHelp.addAction(self.actionAbout_Total_Commander)
        self.menubar.addAction(self.menuFiles.menuAction())
        self.menubar.addAction(self.menuMark.menuAction())
        self.menubar.addAction(self.menuCommands.menuAction())
        self.menubar.addAction(self.menuNet.menuAction())
        self.menubar.addAction(self.menuShow.menuAction())
        self.menubar.addAction(self.menuConfiguration.menuAction())
        self.menubar.addAction(self.menuStart.menuAction())
        self.helpMenuBar.addAction(self.menuHelp.menuAction())
        self.toolBar.addAction(self.Refresh)
        self.toolBar.addSeparator()
        self.toolBar.addAction(self.action_view1)
        self.toolBar.addSeparator()
        self.toolBar.addAction(self.action_view2)

        self.separator1 = QFrame()
        self.separator1.setFrameShape(QFrame.VLine)
        self.separator1.setFrameShadow(QFrame.Sunken)
        self.separator2 = QFrame()
        self.separator2.setFrameShape(QFrame.VLine)
        self.separator2.setFrameShadow(QFrame.Sunken)
        self.separator3 = QFrame()
        self.separator3.setFrameShape(QFrame.VLine)
        self.separator3.setFrameShadow(QFrame.Sunken)
        self.separator4 = QFrame()
        self.separator4.setFrameShape(QFrame.VLine)
        self.separator4.setFrameShadow(QFrame.Sunken)
        self.separator5 = QFrame()
        self.separator5.setFrameShape(QFrame.VLine)
        self.separator5.setFrameShadow(QFrame.Sunken)
        self.separator6 = QFrame()
        self.separator6.setFrameShape(QFrame.VLine)
        self.separator6.setFrameShadow(QFrame.Sunken)

        self.toolbarHBoxWidget = QWidget()
        self.toolbarHBoxWidget.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Preferred)
        self.toolbarHBox = QGridLayout()
        self.toolbarHBoxWidget.setLayout(self.toolbarHBox)
        self.toolbarHBox.addWidget(self.actionF3_View, 0, 0)
        self.toolbarHBox.addWidget(self.separator1, 0, 1)
        self.toolbarHBox.addWidget(self.actionF4_Edit, 0, 2)
        self.toolbarHBox.addWidget(self.separator2, 0, 3)
        self.toolbarHBox.addWidget(self.actionF5_Copy, 0, 4)
        self.toolbarHBox.addWidget(self.separator3, 0, 5)
        self.toolbarHBox.addWidget(self.actionF6_Move, 0, 6)
        self.toolbarHBox.addWidget(self.separator4, 0, 7)
        self.toolbarHBox.addWidget(self.actionF5_NewFolder, 0, 8)
        self.toolbarHBox.addWidget(self.separator5, 0, 9)
        self.toolbarHBox.addWidget(self.actionF8_Delete, 0, 10)
        self.toolbarHBox.addWidget(self.separator6, 0, 11)
        self.toolbarHBox.addWidget(self.actionAlt_F4_Exit, 0, 12)
        self.toolBar_2.addWidget(self.toolbarHBoxWidget)
        self.toolBar_2.setFixedHeight(40)

        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(
            "Total Commander 7.50a - Politechnika Lodzka - Wydzial EEIA")
        self.menuFiles.setTitle("Files")
        self.menuMark.setTitle("Mark")
        self.menuCommands.setTitle("Commands")
        self.menuNet.setTitle("Net")
        self.menuShow.setTitle("Show")
        self.menuConfiguration.setTitle("Configuration")
        self.menuStart.setTitle("Start")
        self.menuHelp.setTitle("Help")
        self.toolBar.setWindowTitle("toolBar")
        self.toolBar_2.setWindowTitle("toolBar_2")
        self.actionIndex.setText("Index")
        self.actionIndex.setIconText("Index")
        self.actionIndex.setShortcut("F1")
        self.actionKeyboard.setText("Keyboard")
        self.actionRegistration_Info.setText("Registration Info")
        self.actionVisit_Total_CMD_s_website.setText(
            "Visit Totalcmd\'s Web Site")
        self.actionAbout_Total_Commander.setText("About Total Commander...")
        self.actionOption_1.setText("Option 1")
        self.actionOption_2.setText("Option 2")
        self.actionOption_3.setText("Option 1")
        self.actionOption_4.setText("Option 2")
        self.actionOption_5.setText("Option 1")
        self.actionOption_6.setText("Option 2")
        self.actionOption_7.setText("Option 1")
        self.actionOption_8.setText("Option 2")
        self.actionOption_9.setText("Option 1")
        self.actionOption_10.setText("Option 2")
        self.actionOption_11.setText("Option 1")
        self.actionOption_12.setText("Option 2")
        self.actionOption_13.setText("Option 1")
        self.actionOption_14.setText("Option 2")
        self.Refresh.setText("Refresh")
        self.action_view1.setText("View 1")
        self.action_view2.setText("View 2")
        self.actionF3_View.setText("F3 View")
        self.actionF3_View.setShortcut("F3")
        self.actionF4_Edit.setText("F4 Edit")
        self.actionF4_Edit.setShortcut("F4")
        self.actionF5_Copy.setText("F5 Copy")
        self.actionF5_Copy.setShortcut("F5")
        self.actionF6_Move.setText("F6 Move")
        self.actionF6_Move.setShortcut("F6")
        self.actionF5_NewFolder.setText("F7 NewFolder")
        self.actionF5_NewFolder.setShortcut("F7")
        self.actionF8_Delete.setText("F8 Delete")
        self.actionF8_Delete.setShortcut("F8")
        self.actionAlt_F4_Exit.setText("Alt+F4 Exit")
        self.actionAlt_F4_Exit.setShortcut("Ctrl+Alt+F4")
コード例 #10
0
class DMSDecorateTypeWgt(QDialog):
    DEBUG = True
    tableWdg = None
    # 数据列位置
    TASK_ID = 0
    TASK_ORDER = 1
    TASK_NAME = 2
    TASK_DURATION = 3
    TASK_PRE = 4
    TASK_ROOM_BELONG = 5
    TASK_RESPONSIBLE = 6
    TASK_NODE_X = 7
    TASK_NODE_Y = 8
    TASK_NODE_COLOR = 9
    # 表头
    HEADER_NAME = [
        "id", '序号', '任务名称', '工期', '前置任务', '房间', '责任人', "x", "y", "颜色"
    ]

    TOOL_BAR_HEIGHT = 30
    TABLE_HEADER_HEIGHT = 30

    def __init__(self, parent=None):
        super(DMSDecorateTypeWgt, self).__init__(parent)
        self.tableWdg = QTableWidget(0, len(DMSDecorateTypeWgt.HEADER_NAME))
        self.toolBar = QToolBar('toolBar', self)
        self.actInsertTask = QAction(text="插入")
        self.actDelTask = QAction(text="删除")
        self.toolBar.addAction(self.actInsertTask)
        self.toolBar.addAction(self.actDelTask)
        self.commitBtn = QPushButton("确定")
        self.cancelBtn = QPushButton("取消")
        self.initUI()
        self.initSignal()
        pass

    def initSignal(self):
        self.actInsertTask.triggered.connect(self.addDecorateType)  # 插入任务
        self.actDelTask.triggered.connect(self.delDecorateType)  # 删除任务
        self.commitBtn.clicked.connect(self.submit)  # 提交
        self.cancelBtn.clicked.connect(self.cancel)  # 取消

    def initUI(self):
        '''布局'''
        self.setWindowTitle("编辑计划模板")
        self.setWindowModality(Qt.WindowModal)
        layout = QVBoxLayout(self)
        layout.addWidget(self.toolBar)
        layout.addWidget(self.tableWdg)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        self.resize(1200, 600)
        self.setFixedWidth(1200)
        '''底部按钮'''
        bottomBar = QHBoxLayout()
        bottomBar.setSpacing(4)
        bottomBar.setContentsMargins(10, 10, 24, 16)
        spacerItem = QSpacerItem(20, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        bottomBar.addItem(spacerItem)
        bottomBar.addWidget(self.commitBtn)
        bottomBar.addWidget(self.cancelBtn)
        self.commitBtn.setFixedSize(80, glb_dmsContext.BUTTON_NORMAL_HEIGHT)
        self.cancelBtn.setFixedSize(80, glb_dmsContext.BUTTON_NORMAL_HEIGHT)
        layout.addLayout(bottomBar)
        '''工具栏'''
        self.toolBar.setFixedHeight(DMSDecorateTypeWgt.TOOL_BAR_HEIGHT)
        '''中部表格'''
        # 隐藏不必要的列
        if not glb_dmsContext.IS_DEBUG:
            self.tableWdg.hideColumn(DMSDecorateTypeWgt.TASK_ID)
            self.tableWdg.hideColumn(DMSDecorateTypeWgt.TASK_NODE_X)
            self.tableWdg.hideColumn(DMSDecorateTypeWgt.TASK_NODE_Y)
            self.tableWdg.hideColumn(DMSDecorateTypeWgt.TASK_NODE_COLOR)
        # 尾列可伸缩
        self.tableWdg.horizontalHeader().setStretchLastSection(True)
        # 设置表头
        self.tableWdg.horizontalHeader().setFixedHeight(
            DMSDecorateTypeWgt.TABLE_HEADER_HEIGHT)
        # 列名
        self.tableWdg.setHorizontalHeaderLabels(DMSDecorateTypeWgt.HEADER_NAME)
        self.tableWdg.verticalHeader().setVisible(False)
        self.tableWdg.verticalHeader().setFixedWidth(30)
        '''设置表选择和编辑行为'''
        self.tableWdg.setEditTriggers(QAbstractItemView.DoubleClicked
                                      | QAbstractItemView.AnyKeyPressed)
        self.tableWdg.setSelectionMode(QAbstractItemView.ExtendedSelection)
        # Todo
        # self.tableWdg.setSelectionBehavior(QAbstractItemView.sel)

        # self.setWindowFlags(Qt.FramelessWindowHint)
        self.tableWdg.setShowGrid(False)
        # self.tableWdg.setStyleSheet("QTableWidget::Item{border:0px solid rgb(255,0,0);border-bottom:1px solid rgb(255,0,0);}")

    def updateDecorateType(self, currentBuildingAndCurrentUnitID):
        self.tableWdg.clear()
        task: DB_Decorate_Type
        decorateTaskList: List[DB_Decorate_Type] = dmsDatabase().getTableList(
            table=DB_Decorate_Type, filter_str=currentBuildingAndCurrentUnitID)
        rowNumber = 0
        for task in decorateTaskList:
            self.tableWdg.setItem(rowNumber, DMSDecorateTypeWgt.TASK_ID,
                                  QTableWidgetItem(task.id))
            self.tableWdg.setItem(rowNumber, DMSDecorateTypeWgt.TASK_ORDER,
                                  QTableWidgetItem(task.order))
            self.tableWdg.setItem(rowNumber, DMSDecorateTypeWgt.TASK_NAME,
                                  QTableWidgetItem(task.name))
            self.tableWdg.setItem(rowNumber, DMSDecorateTypeWgt.TASK_PRE,
                                  QTableWidgetItem(task.pre_task))
            self.tableWdg.setItem(rowNumber, DMSDecorateTypeWgt.TASK_DURATION,
                                  QTableWidgetItem(task.duration))
            self.tableWdg.setItem(rowNumber,
                                  DMSDecorateTypeWgt.TASK_NODE_COLOR,
                                  QTableWidgetItem(task.node_color))
            self.tableWdg.setItem(rowNumber, DMSDecorateTypeWgt.TASK_NODE_X,
                                  QTableWidgetItem(task.node_x))
            self.tableWdg.setItem(rowNumber, DMSDecorateTypeWgt.TASK_NODE_Y,
                                  QTableWidgetItem(task.node_y))
            rowNumber = rowNumber + 1

    def getCurrentItem(self):
        return self.tableWdg.currentItem()

    def addDecorateType(self):
        itemList = self.tableWdg.selectedItems()
        [itemRow, itemCol] = [
            self.tableWdg.rowCount(), self.TASK_ORDER
        ] if len(itemList) == 0 else [itemList[0].row(), itemList[0].column()]
        # print("before insert: current", self.tableWdg.currentItem().row(), self.tableWdg.currentItem().column())
        self.tableWdg.insertRow(itemRow)

        self.initNewRow(itemRow)

    def delDecorateType(self):
        itemList = self.tableWdg.selectedItems()
        if len(itemList) == 0:
            return
        else:
            item = itemList[0]
            taskID = self.tableWdg.item(
                item.row(), DMSDecorateTypeWgt.TASK_ID).data(Qt.UserRole)
            self.tableWdg.removeRow(item.row())

    def saveDecorateTypeDate2DB(self):
        pass

    def checkDateVisable(self):
        # 数据校验
        pass

    def initNewRow(self, rowNum):
        self.tableWdg.setItem(rowNum, self.TASK_ID,
                              QTableWidgetItem(str(uuid.uuid1())))
        self.tableWdg.setItem(rowNum, self.TASK_NODE_X, QTableWidgetItem("0"))
        self.tableWdg.setItem(rowNum, self.TASK_NODE_Y, QTableWidgetItem("0"))
        self.tableWdg.setItem(rowNum, self.TASK_NODE_COLOR,
                              QTableWidgetItem(GNode.brush.color().name()))
        # 设置色彩控件
        self.tableWdg.item(rowNum, self.TASK_NODE_COLOR).setBackground(
            QBrush(QColor(GNode.brush.color().name())))
        self.tableWdg.item(rowNum, self.TASK_NODE_COLOR).setFlags(
            Qt.ItemIsSelectable | Qt.ItemIsEnabled)  # 单元格不可被编辑

        # self.tableWdg.item(rowNum, self.TASK_NODE_COLOR).
        # col = QColorDialog.getColor()
        # col.name()

    def currAndSelect(self):
        print("after insert: current",
              self.tableWdg.currentItem().row(),
              self.tableWdg.currentItem().column())
        print("after insert: selected",
              self.tableWdg.selectedItems()[0].row(),
              self.tableWdg.selectedItems()[0].column())

    def submit(self):
        self.saveDecorateTypeDate2DB()
        self.close()

    def cancel(self):
        # todo 清空session
        self.close()
コード例 #11
0
class MainWindow(QMainWindow):
    def __init__(self, app):
        super().__init__()
        self.app = app
        self.setWindowTitle("Automatoes")
        self.setWindowIcon(QIcon('automato.png'))
        desktop = app.desktop()
        height = desktop.screenGeometry().height()
        width = desktop.screenGeometry().width()
        self.setGeometry(width / 4 - 100, height / 4 - 100, width / 2,
                         height / 2)
        self.setFixedSize(width / 2 + 200, height / 2 + 200)
        self.setup_components()

    def setup_components(self):
        self.statusbar_setup()
        self.central_widget_setup()
        self.toolbar_widget_setup()

    def statusbar_setup(self):
        stat = QStatusBar()
        self.setStatusBar(stat)
        label1 = QLabel()
        label1.setText("Label 1")
        label1.show()
        stat.addWidget(label1, 1)

    def central_widget_setup(self):
        home = SmartHomeView(self.app.home)
        self.setCentralWidget(home)

    def toolbar_widget_setup(self):
        new_user = QPushButton('Add new user', )
        new_user.clicked.connect(self.open_new_user_dialog)

        self.newAction = QAction(QIcon("Add_user.png"),
                                 "Add new user",
                                 self,
                                 statusTip="Add new user",
                                 triggered=self.open_new_user_dialog)
        self.logoutAction = QAction(QIcon("logout.png"),
                                    "Logout",
                                    self,
                                    statusTip="Add new user",
                                    triggered=self.close_action)

        self.mainToolBar = QToolBar()
        self.mainToolBar.addAction(self.newAction)
        self.mainToolBar.addSeparator()
        self.mainToolBar.addAction(self.logoutAction)
        self.addToolBar(self.mainToolBar)
        self.mainToolBar.setFixedHeight(36)
        self.mainToolBar.setFloatable(False)

    def open_new_user_dialog(self):
        dialog = NewUserDialog()
        dialog.show()
        dialog.exec_()

    def close_action(self):
        self.close()