def _create_theme_menu(self): theme_menu = QMenu(self) theme_menu.setTitle('Buttons Theme') theme_menu.setTearOffEnabled(True) theme_menu.setWindowTitle(TAG) theme_actions = QActionGroup(self) theme_actions.setExclusive(True) # create ordered theme list custom_order_theme = sorted(THEMES.iterkeys()) custom_order_theme.remove('Maya Theme') custom_order_theme.insert(0, 'Maya Theme') default_item = True for theme in custom_order_theme: current_theme_action = QAction(theme, theme_actions) current_theme_action.setCheckable(True) current_theme_action.setChecked( MTTSettings.value('theme', 'Maya Theme') == theme) current_theme_action.triggered.connect(self.on_change_theme) theme_menu.addAction(current_theme_action) if default_item: theme_menu.addSeparator() default_item = False return theme_menu
def on_show_prompt_instance_delay_menu(self): prompt_instance_state = cmds.optionVar(query='MTT_prompt_instance_state') if prompt_instance_state == PROMPT_INSTANCE_WAIT: elapsed_time = time() - cmds.optionVar(query='MTT_prompt_instance_suspend') if elapsed_time > PROMPT_INSTANCE_WAIT_DURATION: prompt_instance_state = PROMPT_INSTANCE_ASK cmds.optionVar(iv=['MTT_prompt_instance_state', prompt_instance_state]) else: mtt_log('Remaining %.2fs' % (PROMPT_INSTANCE_WAIT_DURATION - elapsed_time)) elif prompt_instance_state == PROMPT_INSTANCE_SESSION: if 'mtt_prompt_session' not in __main__.__dict__: prompt_instance_state = PROMPT_INSTANCE_ASK cmds.optionVar(iv=['MTT_prompt_instance_state', prompt_instance_state]) self.instance_menu.clear() prompt_delay = QActionGroup(self) prompt_delay.setExclusive(True) for i in range(len(PROMPT_INSTANCE_STATE.keys())): current_delay_action = QAction(PROMPT_INSTANCE_STATE[i], prompt_delay) current_delay_action.setCheckable(True) current_delay_action.setChecked(prompt_instance_state == i) current_delay_action.triggered.connect( partial(self.view.on_choose_instance_delay, i, prompt=i != 0)) self.instance_menu.addAction(current_delay_action)
def on_show_debug_menu(self): self.debug_menu.clear() if self.is_master_cmd or self.power_user: power_user_mode = QAction('Power User Mode', self) power_user_mode.setCheckable(True) power_user_mode.setChecked(MTTSettings.value('powerUser')) power_user_mode.triggered.connect(self.__on_toggle_power_user) self.debug_menu.addAction(power_user_mode) self.is_master_cmd = False self.debug_menu.addSeparator() open_pref_folder_action = QAction('Open Preferences Folder', self) open_pref_folder_action.setStatusTip('Open MTT preference folder') open_pref_folder_action.triggered.connect( self.on_open_preference_folder) self.debug_menu.addAction(open_pref_folder_action) self.debug_menu.addSeparator() database_dump_csv = QAction('Dump Database as CSV', self) database_dump_csv.triggered.connect(self.view.model.database_dump_csv) self.debug_menu.addAction(database_dump_csv) database_dump_sql = QAction('Dump Database as SQL', self) database_dump_sql.triggered.connect(self.view.model.database_dump_sql) self.debug_menu.addAction(database_dump_sql) self.debug_menu.addSeparator() support_info = QMenu(self) support_info.setTitle('Supported Node Type') support_info.aboutToShow.connect(self.on_show_supported_type) self.debug_menu.addMenu(support_info)
def showContextMenu(self, point): 'Show the Columns context menu' if self.model() is None: return # If we are viewing a proxy model, skip to the source model mdl = self.model() while isinstance(mdl, QAbstractProxyModel): mdl = mdl.sourceModel() if mdl is None or not hasattr(mdl, 'columns'): return # Generate and show the Menu m = QMenu() for i in range(len(mdl.columns)): c = mdl.columns[i] if c.internal: continue a = QAction(mdl.headerData(i, Qt.Horizontal, Qt.DisplayRole), m) a.setCheckable(True) a.setChecked(not self.isColumnHidden(i)) a.triggered.connect(partial(self.showHideColumn, c=i, s=self.isColumnHidden(i))) m.addAction(a) m.exec_(self.header().mapToGlobal(point))
def on_show_prompt_instance_delay_menu(self): prompt_instance_state = cmds.optionVar( query='MTT_prompt_instance_state') if prompt_instance_state == PROMPT_INSTANCE_WAIT: elapsed_time = time() - cmds.optionVar( query='MTT_prompt_instance_suspend') if elapsed_time > PROMPT_INSTANCE_WAIT_DURATION: prompt_instance_state = PROMPT_INSTANCE_ASK cmds.optionVar( iv=['MTT_prompt_instance_state', prompt_instance_state]) else: mtt_log('Remaining %.2fs' % (PROMPT_INSTANCE_WAIT_DURATION - elapsed_time)) elif prompt_instance_state == PROMPT_INSTANCE_SESSION: if 'mtt_prompt_session' not in __main__.__dict__: prompt_instance_state = PROMPT_INSTANCE_ASK cmds.optionVar( iv=['MTT_prompt_instance_state', prompt_instance_state]) self.instance_menu.clear() prompt_delay = QActionGroup(self) prompt_delay.setExclusive(True) for i in range(len(PROMPT_INSTANCE_STATE.keys())): current_delay_action = QAction(PROMPT_INSTANCE_STATE[i], prompt_delay) current_delay_action.setCheckable(True) current_delay_action.setChecked(prompt_instance_state == i) current_delay_action.triggered.connect( partial(self.view.on_choose_instance_delay, i, prompt=i != 0)) self.instance_menu.addAction(current_delay_action)
def setup_ui(self): """ Setup the UI for the window. """ central_widget = QWidget() layout = QVBoxLayout() layout.addWidget(self.clock_view) layout.addWidget(self.message_view) central_widget.setLayout(layout) self.setCentralWidget(central_widget) menubar = self.menuBar() file_menu = QMenu('File') preferences_action = QAction('Preferences', file_menu) preferences_action.triggered.connect(self.on_preferences_triggered) quit_action = QAction('Quit', file_menu) quit_action.triggered.connect(self.on_quit_triggered) file_menu.addAction(preferences_action) file_menu.addAction(quit_action) menubar.addMenu(file_menu) view_menu = QMenu('View') fullscreen_action = QAction('Fullscreen', view_menu) fullscreen_action.setCheckable(True) fullscreen_action.setChecked(Config.get('FULLSCREEN', True)) fullscreen_action.setShortcut('Ctrl+Meta+F') fullscreen_action.toggled.connect(self.on_fullscreen_changed) view_menu.addAction(fullscreen_action) menubar.addMenu(view_menu)
def on_show_debug_menu(self): self.debug_menu.clear() if self.is_master_cmd or self.power_user: power_user_mode = QAction('Power User Mode', self) power_user_mode.setCheckable(True) power_user_mode.setChecked(MTTSettings.value('powerUser')) power_user_mode.triggered.connect(self.__on_toggle_power_user) self.debug_menu.addAction(power_user_mode) self.is_master_cmd = False self.debug_menu.addSeparator() open_pref_folder_action = QAction('Open Preferences Folder', self) open_pref_folder_action.setStatusTip('Open MTT preference folder') open_pref_folder_action.triggered.connect(self.on_open_preference_folder) self.debug_menu.addAction(open_pref_folder_action) self.debug_menu.addSeparator() database_dump_csv = QAction('Dump Database as CSV', self) database_dump_csv.triggered.connect(self.view.model.database_dump_csv) self.debug_menu.addAction(database_dump_csv) database_dump_sql = QAction('Dump Database as SQL', self) database_dump_sql.triggered.connect(self.view.model.database_dump_sql) self.debug_menu.addAction(database_dump_sql) self.debug_menu.addSeparator() support_info = QMenu(self) support_info.setTitle('Supported Node Type') support_info.aboutToShow.connect(self.on_show_supported_type) self.debug_menu.addMenu(support_info)
def add_action(lbl, tip, cmd, checkable=False, checked=False): a = QAction(lbl, self) a.setStatusTip(tip) a.triggered.connect(cmd) if checkable: a.setCheckable(True) a.setChecked(checked) return a
def on_show_supported_type(self): node_types = sorted( [n_type for (n_type, nice, attr) in MTTSettings.SUPPORTED_TYPE] + MTTSettings.UNSUPPORTED_TYPE) support_info = self.sender() support_info.clear() for node_type in node_types: current = QAction(node_type, self) current.setEnabled(False) current.setCheckable(True) current.setChecked(node_type not in MTTSettings.UNSUPPORTED_TYPE) support_info.addAction(current)
def create_size_menu(self): """ Create the toolbar's buttons size menu """ menu = QMenu(self) group = QActionGroup(self) sizes = (_("Tiny"), 16), (_("Small"), 32), (_("Medium"), 48), (_("Big"), 64) for name, size in sizes: action = QAction(name, menu) action.setCheckable(True) if size == self.base.toolbar_size: action.setChecked(True) action.triggered.connect(partial(self.set_btn_size, size)) group.addAction(action) menu.addAction(action) return menu
def __init__(self, parent=None): super(Status, self).__init__(parent) self.setupUi(self) self.base = parent self.wait_anim = QMovie(":/stuff/wait.gif") self.anim_lbl.setMovie(self.wait_anim) self.anim_lbl.hide() self.show_menu = QMenu(self) for i in [ self.act_page, self.act_date, self.act_text, self.act_comment ]: self.show_menu.addAction(i) # noinspection PyUnresolvedReferences i.triggered.connect(self.on_show_items) i.setChecked(True) sort_menu = QMenu(self) ico_sort = QIcon(":/stuff/sort.png") group = QActionGroup(self) action = QAction(_("Date"), sort_menu) action.setCheckable(True) action.setChecked(not self.base.high_by_page) action.triggered.connect(self.base.set_highlight_sort) action.setData(False) group.addAction(action) sort_menu.addAction(action) action = QAction(_("Page"), sort_menu) action.setCheckable(True) action.setChecked(self.base.high_by_page) action.triggered.connect(self.base.set_highlight_sort) action.setData(True) group.addAction(action) sort_menu.addAction(action) sort_menu.setIcon(ico_sort) sort_menu.setTitle(_("Sort by")) self.show_menu.addMenu(sort_menu) self.show_items_btn.setMenu(self.show_menu)
def __init__(self): QMainWindow.__init__(self) # setup ui (the pcef GenericEditor is created there using # the promoted widgets system) self.ui = simple_editor_ui.Ui_MainWindow() self.ui.setupUi(self) self.setWindowTitle("PCEF - Generic Example") editor = self.ui.genericEditor # open this file try: openFileInEditor(self.ui.genericEditor, __file__) except: pass # install Panel where user can add its own markers p = UserMarkersPanel() editor.installPanel(p, editor.PANEL_ZONE_LEFT) # add a fold indicator around our class and the main editor.foldPanel.addIndicator(136, 141) # add styles actions allStyles = styles.getAllStyles() allStyles.sort() self.styleActionGroup = QActionGroup(self) for style in allStyles: action = QAction(unicode(style), self.ui.menuStyle) action.setCheckable(True) action.setChecked(style == "Default") self.styleActionGroup.addAction(action) self.ui.menuStyle.addAction(action) self.styleActionGroup.triggered.connect( self.on_styleActionGroup_triggered) # add panels actions allPanels = self.ui.genericEditor.panels() allPanels.sort() self.panels_actions = [] for panel in allPanels: action = QAction(unicode(panel), self.ui.menuPanels) action.setCheckable(True) action.setChecked(panel.enabled) self.ui.menuPanels.addAction(action) self.panels_actions.append(action) action.triggered.connect(self.onPanelActionTriggered) # add panels actions allModes = self.ui.genericEditor.modes() allModes.sort() self.modes_actions = [] for mode in allModes: action = QAction(unicode(mode), self.ui.menuModes) action.setCheckable(True) action.setChecked(mode.enabled) self.ui.menuModes.addAction(action) self.modes_actions.append(action) action.triggered.connect(self.onModeActionTriggered)
def __init__(self): QMainWindow.__init__(self) # setup ui (the pcef PythonEditor is created in the Ui_MainWindow using # the promoted widgets system) self.ui = simple_python_editor_ui.Ui_MainWindow() self.ui.setupUi(self) self.setWindowTitle("PCEF - Python Editor Example") self.acceptDrops() # open this file try: openFileInEditor(self.ui.genericEditor, __file__) except: pass # add styles actions allStyles = styles.getAllStyles() allStyles.sort() self.styleActionGroup = QActionGroup(self) for style in allStyles: action = QAction(unicode(style), self.ui.menuStyle) action.setCheckable(True) action.setChecked(style == "Default") self.styleActionGroup.addAction(action) self.ui.menuStyle.addAction(action) self.styleActionGroup.triggered.connect( self.on_styleActionGroup_triggered) # add panels actions allPanels = self.ui.genericEditor.panels() allPanels.sort() self.panels_actions = [] for panel in allPanels: action = QAction(unicode(panel), self.ui.menuPanels) action.setCheckable(True) action.setChecked(panel.enabled) self.ui.menuPanels.addAction(action) self.panels_actions.append(action) action.triggered.connect(self.onPanelActionTriggered) # add panels actions allModes = self.ui.genericEditor.modes() allModes.sort() self.modes_actions = [] for mode in allModes: action = QAction(unicode(mode), self.ui.menuModes) action.setCheckable(True) action.setChecked(mode.enabled) self.ui.menuModes.addAction(action) self.modes_actions.append(action) action.triggered.connect(self.onModeActionTriggered)
class MainWindow(QWidget): def __init__(self, grid, U): assert isinstance(U, Communicable) super(MainWindow, self).__init__() U = U.data layout = QVBoxLayout() plotBox = QHBoxLayout() plot = GlumpyPatchWidget(self, grid, vmin=np.min(U), vmax=np.max(U), bounding_box=bounding_box, codim=codim) bar = ColorBarWidget(self, vmin=np.min(U), vmax=np.max(U)) plotBox.addWidget(plot) plotBox.addWidget(bar) layout.addLayout(plotBox) if len(U) == 1: plot.set(U.ravel()) else: plot.set(U[0]) hlayout = QHBoxLayout() self.slider = QSlider(Qt.Horizontal) self.slider.setMinimum(0) self.slider.setMaximum(len(U) - 1) self.slider.setTickPosition(QSlider.TicksBelow) hlayout.addWidget(self.slider) lcd = QLCDNumber(m.ceil(m.log10(len(U)))) lcd.setDecMode() lcd.setSegmentStyle(QLCDNumber.Flat) hlayout.addWidget(lcd) layout.addLayout(hlayout) hlayout = QHBoxLayout() toolbar = QToolBar() self.a_play = QAction(self.style().standardIcon(QStyle.SP_MediaPlay), 'Play', self) self.a_play.setCheckable(True) self.a_rewind = QAction(self.style().standardIcon(QStyle.SP_MediaSeekBackward), 'Rewind', self) self.a_toend = QAction(self.style().standardIcon(QStyle.SP_MediaSeekForward), 'End', self) self.a_step_backward = QAction(self.style().standardIcon(QStyle.SP_MediaSkipBackward), 'Step Back', self) self.a_step_forward = QAction(self.style().standardIcon(QStyle.SP_MediaSkipForward), 'Step', self) self.a_loop = QAction(self.style().standardIcon(QStyle.SP_BrowserReload), 'Loop', self) self.a_loop.setCheckable(True) toolbar.addAction(self.a_play) toolbar.addAction(self.a_rewind) toolbar.addAction(self.a_toend) toolbar.addAction(self.a_step_backward) toolbar.addAction(self.a_step_forward) toolbar.addAction(self.a_loop) hlayout.addWidget(toolbar) self.speed = QSlider(Qt.Horizontal) self.speed.setMinimum(0) self.speed.setMaximum(100) hlayout.addWidget(QLabel('Speed:')) hlayout.addWidget(self.speed) layout.addLayout(hlayout) self.timer = QTimer() self.timer.timeout.connect(self.update_solution) self.slider.valueChanged.connect(self.slider_changed) self.slider.valueChanged.connect(lcd.display) self.speed.valueChanged.connect(self.speed_changed) self.a_play.toggled.connect(self.toggle_play) self.a_rewind.triggered.connect(self.rewind) self.a_toend.triggered.connect(self.to_end) self.a_step_forward.triggered.connect(self.step_forward) self.a_step_backward.triggered.connect(self.step_backward) self.speed.setValue(50) self.setLayout(layout) self.plot = plot self.U = U def slider_changed(self, ind): self.plot.set(self.U[ind]) def speed_changed(self, val): self.timer.setInterval(val * 20) def update_solution(self): ind = self.slider.value() + 1 if ind >= len(self.U): if self.a_loop.isChecked(): ind = 0 else: self.a_play.setChecked(False) return self.slider.setValue(ind) def toggle_play(self, checked): if checked: if self.slider.value() + 1 == len(self.U): self.slider.setValue(0) self.timer.start() else: self.timer.stop() def rewind(self): self.slider.setValue(0) def to_end(self): self.a_play.setChecked(False) self.slider.setValue(len(self.U) - 1) def step_forward(self): self.a_play.setChecked(False) ind = self.slider.value() + 1 if ind == len(self.U) and self.a_loop.isChecked(): ind = 0 if ind < len(self.U): self.slider.setValue(ind) def step_backward(self): self.a_play.setChecked(False) ind = self.slider.value() - 1 if ind == -1 and self.a_loop.isChecked(): ind = len(self.U) - 1 if ind >= 0: self.slider.setValue(ind)
class PlotMainWindow(QWidget): """Base class for plot main windows.""" def __init__(self, U, plot, length=1, title=None): super(PlotMainWindow, self).__init__() layout = QVBoxLayout() if title: title = QLabel('<b>' + title + '</b>') title.setAlignment(Qt.AlignHCenter) layout.addWidget(title) layout.addWidget(plot) plot.set(U, 0) if length > 1: hlayout = QHBoxLayout() self.slider = QSlider(Qt.Horizontal) self.slider.setMinimum(0) self.slider.setMaximum(length - 1) self.slider.setTickPosition(QSlider.TicksBelow) hlayout.addWidget(self.slider) lcd = QLCDNumber(m.ceil(m.log10(length))) lcd.setDecMode() lcd.setSegmentStyle(QLCDNumber.Flat) hlayout.addWidget(lcd) layout.addLayout(hlayout) hlayout = QHBoxLayout() toolbar = QToolBar() self.a_play = QAction(self.style().standardIcon(QStyle.SP_MediaPlay), 'Play', self) self.a_play.setCheckable(True) self.a_rewind = QAction(self.style().standardIcon(QStyle.SP_MediaSeekBackward), 'Rewind', self) self.a_toend = QAction(self.style().standardIcon(QStyle.SP_MediaSeekForward), 'End', self) self.a_step_backward = QAction(self.style().standardIcon(QStyle.SP_MediaSkipBackward), 'Step Back', self) self.a_step_forward = QAction(self.style().standardIcon(QStyle.SP_MediaSkipForward), 'Step', self) self.a_loop = QAction(self.style().standardIcon(QStyle.SP_BrowserReload), 'Loop', self) self.a_loop.setCheckable(True) toolbar.addAction(self.a_play) toolbar.addAction(self.a_rewind) toolbar.addAction(self.a_toend) toolbar.addAction(self.a_step_backward) toolbar.addAction(self.a_step_forward) toolbar.addAction(self.a_loop) if hasattr(self, 'save'): self.a_save = QAction(self.style().standardIcon(QStyle.SP_DialogSaveButton), 'Save', self) toolbar.addAction(self.a_save) self.a_save.triggered.connect(self.save) hlayout.addWidget(toolbar) self.speed = QSlider(Qt.Horizontal) self.speed.setMinimum(0) self.speed.setMaximum(100) hlayout.addWidget(QLabel('Speed:')) hlayout.addWidget(self.speed) layout.addLayout(hlayout) self.timer = QTimer() self.timer.timeout.connect(self.update_solution) self.slider.valueChanged.connect(self.slider_changed) self.slider.valueChanged.connect(lcd.display) self.speed.valueChanged.connect(self.speed_changed) self.a_play.toggled.connect(self.toggle_play) self.a_rewind.triggered.connect(self.rewind) self.a_toend.triggered.connect(self.to_end) self.a_step_forward.triggered.connect(self.step_forward) self.a_step_backward.triggered.connect(self.step_backward) self.speed.setValue(50) elif hasattr(self, 'save'): hlayout = QHBoxLayout() toolbar = QToolBar() self.a_save = QAction(self.style().standardIcon(QStyle.SP_DialogSaveButton), 'Save', self) toolbar.addAction(self.a_save) hlayout.addWidget(toolbar) layout.addLayout(hlayout) self.a_save.triggered.connect(self.save) self.setLayout(layout) self.plot = plot self.U = U self.length = length def slider_changed(self, ind): self.plot.set(self.U, ind) def speed_changed(self, val): self.timer.setInterval(val * 20) def update_solution(self): ind = self.slider.value() + 1 if ind >= self.length: if self.a_loop.isChecked(): ind = 0 else: self.a_play.setChecked(False) return self.slider.setValue(ind) def toggle_play(self, checked): if checked: if self.slider.value() + 1 == self.length: self.slider.setValue(0) self.timer.start() else: self.timer.stop() def rewind(self): self.slider.setValue(0) def to_end(self): self.a_play.setChecked(False) self.slider.setValue(self.length - 1) def step_forward(self): self.a_play.setChecked(False) ind = self.slider.value() + 1 if ind == self.length and self.a_loop.isChecked(): ind = 0 if ind < self.length: self.slider.setValue(ind) def step_backward(self): self.a_play.setChecked(False) ind = self.slider.value() - 1 if ind == -1 and self.a_loop.isChecked(): ind = self.length - 1 if ind >= 0: self.slider.setValue(ind)
class SymbolWort(QWidget): def __init__(self): QWidget.__init__(self) self.setWindowTitle("Symbol-Worte") self.thread=MyWorker(self) self.thread.start() self.thread.calculator.calculationDone.connect(self.calculationDone) self.initUI() def about(self): QMessageBox.information(self,u"Über Symbol-Worte",u"Symbol-Worte ist ein kleines, zum Spaß entwickeltes, Programm. Es nutzt die Open-Source Entwicklungsumgebung Python (www.python.org) und PySide (Qt-Schnittstelle). Es ist unter GPL v.3 veröffentlicht. Entwickelt von Peter Waldert.") def update(self): text=self.lineEdit.text() if text.lower() != self.responseLabel.text().lower(): self.thread.startCalculation(text) def calculationDone(self,ok): if ok: self.responseLabel.setText(self.thread.calculator.result) else: self.responseLabel.setText(u"Keine Treffer") self.updateTable(self.thread.calculator.resultElements) def updateAuto(self,checked): if checked: self.lineEdit.textEdited.connect(self.update) else: self.lineEdit.textEdited.disconnect(self.update) def updateMaxLength(self,checked): if checked: self.lineEdit.setMaxLength(10) else: self.lineEdit.setMaxLength(100) def setupTable(self): self.tableWidget.setColumnCount(3) self.tableWidget.setHorizontalHeaderLabels(["OZ","Sym","Name"]) self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableWidget.setSelectionMode(QTableWidget.SingleSelection) self.tableWidget.setEditTriggers(QTableWidget.NoEditTriggers) self.tableWidget.setAlternatingRowColors(True) def updateTable(self,elements): self.tableWidget.clearContents() self.tableWidget.setRowCount(len(elements)) row=0 for element in elements: self.tableWidget.setItem(row,0,QTableWidgetItem(str(element.atomicNumber))) self.tableWidget.setItem(row,1,QTableWidgetItem(elements[row].symbol)) self.tableWidget.setItem(row,2,QTableWidgetItem(elements[row].name)) row+=1 self.tableWidget.resizeColumnsToContents() def initUI(self): wordLabel=QLabel("&Wort:") responseLabel=QLabel("Symbol-Wort:") progressLabel=QLabel("Rechen-Fortschritt:") self.lineEdit=QLineEdit() self.updateButton=QPushButton("&Berechnen") self.autoUpdate=QCheckBox("&Auto-Berechnung") self.responseLabel=QLabel() wordLabel.setBuddy(self.lineEdit) self.tableWidget=QTableWidget() self.progressView=ProgressView() self.disableMaxLengthAction=QAction("Zeichenmaximum (Achtung!)",self) self.disableMaxLengthAction.setCheckable(True) self.disableMaxLengthAction.toggled.connect(self.updateMaxLength) self.disableMaxLengthAction.setChecked(True) self.setupTable() self.progressView.setProgress(self.thread.calculator.progress) self.progressView.abortButton.setIcon(QIcon.fromTheme("process-stopp",QIcon("Abort.png"))) self.progressView.abortButton.setToolTip("Stoppe die Berechnung") self.lineEdit.setValidator(QRegExpValidator(QRegExp("[A-Za-z]+"))) self.lineEdit.setToolTip("Nur Zeichen von A-Z") self.lineEdit.setContextMenuPolicy(Qt.ActionsContextMenu) self.lineEdit.addAction(self.disableMaxLengthAction) self.responseLabel.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Fixed) self.responseLabel.setFrameStyle(QFrame.StyledPanel|QFrame.Sunken) self.aboutButton=QPushButton(u"Über") f=self.responseLabel.font() f.setPointSize(24) self.responseLabel.setFont(f) self.lineEdit.returnPressed.connect(self.update) self.updateButton.clicked.connect(self.update) self.autoUpdate.stateChanged.connect(self.updateAuto) self.aboutButton.clicked.connect(self.about) layout=QGridLayout() layout.addWidget(wordLabel,0,0) layout.addWidget(self.lineEdit,0,1) layout.addWidget(self.updateButton,0,2) layout.addWidget(self.autoUpdate,1,1,1,2) layout.addWidget(responseLabel,2,0) layout.addWidget(self.responseLabel,2,1,1,2) layout.addWidget(self.tableWidget,3,0,1,3) layout.addWidget(progressLabel,4,0) layout.addWidget(self.progressView,5,0,1,3) layout.addWidget(self.aboutButton,6,2) self.setLayout(layout) def closeEvent(self,event): self.thread.quit() self.thread.wait() event.accept() def keyPressEvent(self,event): if event.key() == Qt.Key_Escape: self.thread.calculator.progress.abort() event.accept() else: event.ignore()
class MainWindow(QMainWindow): start_acq = Signal(str) start_rec = Signal(str) collect_frame = Signal(object) collect_threshed = Signal(object) def __init__(self, parent=None): ''' sets up the whole main window ''' #standard init super(MainWindow, self).__init__(parent) #set the window title self.setWindowTitle('Open Ephys Control GUI') self.window_height = 700 self.window_width = 1100 self.screen2 = QDesktopWidget().screenGeometry(0) self.move( self.screen2.left() + (self.screen2.width() - self.window_width) / 2., self.screen2.top() + (self.screen2.height() - self.window_height) / 2.) self.get_info() self.noinfo = True while self.noinfo: loop = QEventLoop() QTimer.singleShot(500., loop.quit) loop.exec_() subprocess.Popen('start %s' % open_ephys_path, shell=True) self.collect_frame.connect(self.update_frame) self.collect_threshed.connect(self.update_threshed) self.acquiring = False self.recording = False self.video_height = self.window_height * .52 self.video_width = self.window_width * .48 self.resize(self.window_width, self.window_height) #create QTextEdit window 'terminal' for receiving stdout and stderr self.terminal = QTextEdit(self) #set the geometry self.terminal.setGeometry( QRect(self.window_width * .02, self.window_height * .15 + self.video_height, self.video_width * .96, 150)) #make widgets self.setup_video_frames() self.setup_thresh_buttons() self.overlay = True #create thread and worker for video processing self.videoThread = QThread(self) self.videoThread.start() self.videoproc_worker = VideoWorker(self) self.videoproc_worker.moveToThread(self.videoThread) self.vt_file = None """""" """""" """""" """""" """""" """""" """""" """ set up menus """ """""" """""" """""" """""" """""" """""" """""" #create a QMenuBar and set geometry self.menubar = QMenuBar(self) self.menubar.setGeometry( QRect(0, 0, self.window_width * .5, self.window_height * .03)) #set the QMenuBar as menu bar for main window self.setMenuBar(self.menubar) #create a QStatusBar statusbar = QStatusBar(self) #set it as status bar for main window self.setStatusBar(statusbar) #create icon toolbar with default image iconToolBar = self.addToolBar("iconBar.png") #create a QAction for the acquire button self.action_Acq = QAction(self) #make it checkable self.action_Acq.setCheckable(True) #grab an icon for the button acq_icon = self.style().standardIcon(QStyle.SP_MediaPlay) #set the icon for the action self.action_Acq.setIcon(acq_icon) #when the button is pressed, call the Acquire function self.action_Acq.triggered.connect(self.Acquire) #create a QAction for the record button self.action_Record = QAction(self) #make it checkable self.action_Record.setCheckable(True) #grab an icon for the button record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton) #set the icon for the action self.action_Record.setIcon(record_icon) #when the button is pressed, call advanced_settings function self.action_Record.triggered.connect(self.Record) #create QAction for stop button action_Stop = QAction(self) #grab close icon stop_icon = self.style().standardIcon(QStyle.SP_MediaStop) #set icon for action action_Stop.setIcon(stop_icon) #when button pressed, close window action_Stop.triggered.connect(self.Stop) #show tips for each action in the status bar self.action_Acq.setStatusTip("Start acquiring") self.action_Record.setStatusTip("Start recording") action_Stop.setStatusTip("Stop acquiring/recording") #add actions to icon toolbar iconToolBar.addAction(self.action_Acq) iconToolBar.addAction(self.action_Record) iconToolBar.addAction(action_Stop) # self.sort_button = QPushButton('Sort Now',self) # self.sort_button.setGeometry(QRect(self.window_width*.85,0,self.window_width*.15,self.window_height*.05)) # self.sort_button.clicked.connect(self.sort_now) #show the window if minimized by windows self.showMinimized() self.showNormal() """""" """""" """""" """""" """""" """""" """""" """""" """""" """""" "" """""" """""" """""" """""" """""" """""" """""" """""" """""" """""" "" #this function acts as a slot to accept 'message' signal @Slot(str) def print_message(self, message): ''' print stdout and stderr to terminal window ''' #move terminal cursor to end self.terminal.moveCursor(QTextCursor.End) #write message to terminal self.terminal.insertPlainText(message) def setup_thresh_buttons(self): ''' set up buttons for overlay/clearing thresh view ''' self.button_frame = QFrame(self) self.button_frame.setGeometry( QRect(self.window_width * .52, self.window_height * .13 + self.video_height, self.video_width * .98, 50)) button_layout = QHBoxLayout() self.button_frame.setLayout(button_layout) self.clear_button = QPushButton('Clear') self.overlay_button = QPushButton('Overlay') button_layout.addWidget(self.clear_button) button_layout.addWidget(self.overlay_button) self.clear_button.setEnabled(False) self.clear_button.clicked.connect(self.clear_threshed) self.overlay_button.setEnabled(False) self.overlay_button.clicked.connect(self.overlay_threshed) def setup_video_frames(self): ''' set up spots for playing video frames ''' filler_frame = np.zeros((360, 540, 3)) filler_frame = qimage2ndarray.array2qimage(filler_frame) self.raw_frame = QFrame(self) self.raw_label = QLabel() self.raw_label.setText('raw') self.raw_frame.setGeometry( QRect(self.window_width * .01, self.window_height * .15, self.video_width, self.video_height)) self.raw_frame raw_layout = QVBoxLayout() self.raw_frame.setLayout(raw_layout) raw_layout.addWidget(self.raw_label) self.threshed_frame = QFrame(self) self.threshed_label = QLabel() self.threshed_label.setText('Threshed') self.threshed_frame.setGeometry( QRect(self.window_width * .51, self.window_height * .15, self.video_width, self.video_height)) threshed_layout = QVBoxLayout() self.threshed_frame.setLayout(threshed_layout) threshed_layout.addWidget(self.threshed_label) self.label_frame = QFrame(self) self.label_frame.setGeometry( QRect(self.window_width * .01, self.window_height * .11, self.video_width * 2, 50)) self.label_rawlabel = QLabel() self.label_rawlabel.setText('Raw Video') self.label_threshedlabel = QLabel() self.label_threshedlabel.setText('Threshold View') label_layout = QHBoxLayout() self.label_frame.setLayout(label_layout) label_layout.addWidget(self.label_rawlabel) label_layout.addWidget(self.label_threshedlabel) self.raw_label.setPixmap(QPixmap.fromImage(filler_frame)) self.threshed_label.setPixmap(QPixmap.fromImage(filler_frame)) def Acquire(self): if self.action_Acq.isChecked(): self.vidbuffer = [] if self.recording: while 1: try: self.sock.send('StopRecord') self.sock.recv() except: continue break self.recording = False else: #create and start a thread to transport a worker to later self.workerThread = QThread(self) self.workerThread.start() #create a worker object based on Worker class and move it to our #worker thread self.worker = Worker(self) self.worker.moveToThread(self.workerThread) try: self.start_acq.disconnect() except: pass while 1: try: self.sock.send('StartAcquisition') self.sock.recv() except: continue break self.acquiring = True self.start_acq.connect(self.worker.acquire) self.start_acq.emit('start!') self.action_Acq.setEnabled(False) self.action_Record.setChecked(False) self.action_Record.setEnabled(True) record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton) #set the icon for the action self.action_Record.setIcon(record_icon) def Record(self): if self.action_Record.isChecked(): if not self.acquiring: self.workerThread = QThread(self) self.workerThread.start() self.worker = Worker(self) self.worker.moveToThread(self.workerThread) try: self.start_rec.disconnect() except: pass while 1: try: self.sock.send('StartAcquisition') self.sock.recv() except: continue break while 1: try: self.sock.send('StartRecord') self.sock.recv() except: continue break self.vidbuffer = [] self.start_rec.connect(self.worker.acquire) self.recording = True self.start_rec.emit('start!') else: while 1: try: self.sock.send('StartRecord') self.sock.recv() except: continue break self.vidbuffer = [] self.recording = True record_icon = self.style().standardIcon(QStyle.SP_DialogNoButton) #set the icon for the action self.action_Record.setIcon(record_icon) self.action_Record.setEnabled(False) self.action_Acq.setChecked(False) self.action_Acq.setEnabled(True) def Stop(self): self.acquiring = False self.recording = False while 1: try: self.sock.send('isRecording') rec = self.sock.recv() except: continue break if rec == '1': while 1: try: self.sock.send('StopRecord') self.sock.recv() except: continue break self.action_Record.setEnabled(True) self.action_Record.setChecked(False) while 1: try: self.sock.send('isAcquiring') acq = self.sock.recv_string() except: continue break if acq == '1': while 1: try: self.sock.send('StopAcquisition') self.sock.recv() except: continue break self.action_Acq.setEnabled(True) self.action_Acq.setChecked(False) try: #open a csv file for saving tracking data with open(self.vt_file, 'a') as csvfile: #create a writer vidwriter = csv.writer(csvfile, dialect='excel-tab') #check if it's an empty file for row in self.vidbuffer: vidwriter.writerow(row) except: pass record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton) #set the icon for the action self.action_Record.setIcon(record_icon) def update_frame(self, image): self.raw_label.setPixmap(QPixmap.fromImage(image)) def update_threshed(self, threshed_image): self.threshed_label.setPixmap(QPixmap.fromImage(threshed_image)) def clear_threshed(self): self.green_frame = np.zeros_like(self.green_frame) self.red_frame = np.zeros_like(self.red_frame) def overlay_threshed(self): if self.overlay: self.overlay = False elif not self.overlay: self.overlay = True # def sort_now(self): # # if self.recdir is not None: # os.chdir('./kilosort_control') # #create and show the main window # self.sort_frame = kilosort_control.sort_gui.MainWindow() # self.sort_frame.show() # # #set up stream for stdout and stderr based on outputStream class # self.outputStream = kilosort_control.sort_gui.outputStream() # #when outputStream sends messages, connect to appropriate function for # #writing to terminal window # self.outputStream.message.connect(self.sort_frame.print_message) # # #connect stdout and stderr to outputStream # sys.stdout = self.outputStream # sys.stderr = self.outputStream # # self.sort_frame.run_now(self.recdir) # # self.close() def get_info(self): self.info_window = QWidget() self.info_window.resize(400, 350) #set title self.info_window.setWindowTitle('Session Info') #give layout info_layout = QVBoxLayout(self.info_window) with open('info_fields.pickle', 'rb') as f: default_fields = pickle.load(f) f.close() #set label for pic_resolution setting experimenter_label = QLabel('Experimenter:') #make a QLineEdit box for displaying/editing settings experimenter = QComboBox(self.info_window) experimenter.setEditable(True) experimenter.addItems(default_fields['experimenter']) #add label and box to current window info_layout.addWidget(experimenter_label) info_layout.addWidget(experimenter) #set label for pic_resolution setting whose_animal_label = QLabel('Whose animal?') #make a QLineEdit box for displaying/editing settings whose_animal = QComboBox(self.info_window) whose_animal.setEditable(True) whose_animal.addItems(default_fields['whose_animal']) #add label and box to current window info_layout.addWidget(whose_animal_label) info_layout.addWidget(whose_animal) animal_number_label = QLabel('Animal number:') animal_number = QComboBox(self.info_window) animal_number.setEditable(True) animal_number.addItems(default_fields['animal_number']) info_layout.addWidget(animal_number_label) info_layout.addWidget(animal_number) session_number_label = QLabel('Session number:') session_number = QTextEdit(self.info_window) session_number.setText('1') info_layout.addWidget(session_number_label) info_layout.addWidget(session_number) session_type_label = QLabel('Session type:') session_type = QComboBox(self.info_window) session_type.setEditable(True) session_type.addItems(default_fields['session_type']) info_layout.addWidget(session_type_label) info_layout.addWidget(session_type) def save_info(self): info_fields = {} info_fields['experimenter'] = [ experimenter.itemText(i) for i in range(experimenter.count()) ] info_fields['whose_animal'] = [ whose_animal.itemText(i) for i in range(whose_animal.count()) ] info_fields['animal_number'] = [ animal_number.itemText(i) for i in range(animal_number.count()) ] info_fields['session_type'] = [ session_type.itemText(i) for i in range(session_type.count()) ] with open('info_fields.pickle', 'wb') as f: pickle.dump(info_fields, f, protocol=2) f.close() current_experimenter = str(experimenter.currentText()) current_whose_animal = str(whose_animal.currentText()) current_animal_number = str(animal_number.currentText()) current_session_number = str(session_number.toPlainText()) current_session_type = str(session_type.currentText()) recdir = data_save_dir + current_whose_animal + '/' + current_animal_number if not os.path.exists(recdir): os.makedirs(recdir) self.experiment_info = '###### Experiment Info ######\r\n' self.experiment_info += 'Experimenter: %s\r\n' % current_experimenter self.experiment_info += 'Whose animal? %s\r\n' % current_whose_animal self.experiment_info += 'Animal number: %s\r\n' % current_animal_number self.experiment_info += 'Session number: %s\r\n' % current_session_number self.experiment_info += 'Session type: %s\r\n' % current_session_type self.experiment_info = self.experiment_info.encode() config_file = config_path + '/' + current_animal_number + '.xml' if not os.path.exists(config_file): shutil.copy(default_config, config_file) tree = et.parse(config_file) root = tree.getroot() for child in root: if child.tag == 'CONTROLPANEL': child.attrib['recordPath'] = recdir.replace('/', '\\') tree.write(config_file) tree.write(default_config) self.info_window.close() self.noinfo = False ready_button = QPushButton('Ready!') ready_button.clicked.connect(lambda: save_info(self)) info_layout.addWidget(ready_button) self.info_window.show()
class Gui(): """main gui class""" def __init__(self): self.mainwindow = QMainWindow() settings.get_settings() self.access = tuple(settings.access.items()) self.progress = QProgressDialog("Setting up modules...", "cancel", 0, 7, self.mainwindow) self.progress.setWindowTitle( QApplication.translate("MainWindow", str(settings.company), None, QApplication.UnicodeUTF8)) def setup(self): """initializes the uio of the erp client""" self.progress.setFixedWidth(1000) self.progress.setCancelButton(None) # self.progress.setWindowModality(Qt.WindowModal) self.progress.setValue(1) self.mainwindow.setObjectName("MainWindow") self.mainwindow.resize(832, 668) self.mainwindow.setStyleSheet( "QToolBar{\n" "background: qlineargradient(x1:0, y1:0, x2:1, y2:1,\n" "stop:0 rgba(0,0,0),stop:1 rgb(162, 162, 162, 162));\n" "border: 0px;\n" "}\n" "QToolBar > QWidget{\n" "color:white;\n" "}\n" "QToolBar > QWidget:hover {\n" "background:transparent;\n" " }\n" "QToolBar > QWidget:checked {\n" "background:transparent;\n" " }\n" "#MainWindow{\n" "background: qlineargradient(x1:0, y1:0, x2:1, y2:1,\n" "stop:0 rgba(0,0,0),stop:1 rgb(162, 162, 162, 162));\n" "border: 0px;\n" "}\n" "") self.centralWidget = QWidget(self.mainwindow) self.centralWidget.setObjectName("centralWidget") self.gridLayout_2 = QGridLayout(self.centralWidget) self.gridLayout_2.setObjectName("gridLayout_2") self.stackedWidget = QStackedWidget(self.centralWidget) self.stackedWidget.setStyleSheet("") self.stackedWidget.setObjectName("stackedWidget") self.shortcut = NewShortcut() scroll = QScrollArea() scroll.setWidget(self.shortcut.shortcut_setting) self.stackedWidget.addWidget(self.shortcut.shortcut_setting) self.home_page = QWidget() self.home_page.setObjectName("home_page") self.gridLayout = QGridLayout(self.home_page) self.gridLayout.setObjectName("gridLayout") self.billing_frame_2 = QFrame(self.home_page) self.billing_frame_2.setStyleSheet( "background-image:url(:/images/billing_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#6CBED2;") self.billing_frame_2.setFrameShape(QFrame.StyledPanel) self.billing_frame_2.setFrameShadow(QFrame.Raised) self.billing_frame_2.setObjectName("billing_frame_2") self.verticalLayout_4 = QVBoxLayout(self.billing_frame_2) self.verticalLayout_4.setObjectName("verticalLayout_4") spacerItem = QSpacerItem(20, 217, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_4.addItem(spacerItem) self.label_10 = QLabel(self.billing_frame_2) self.label_10.setStyleSheet("background:transparent;") self.label_10.setObjectName("label_10") self.verticalLayout_4.addWidget(self.label_10) self.gridLayout.addWidget(self.billing_frame_2, 0, 1, 1, 1) self.employee_frame_3 = QFrame(self.home_page) self.employee_frame_3.setStyleSheet( "background-image:url(:/images/employee_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#0099CC;") self.employee_frame_3.setFrameShape(QFrame.StyledPanel) self.employee_frame_3.setFrameShadow(QFrame.Raised) self.employee_frame_3.setObjectName("employee_frame_3") self.verticalLayout_5 = QVBoxLayout(self.employee_frame_3) self.verticalLayout_5.setObjectName("verticalLayout_5") spacerItem1 = QSpacerItem(20, 217, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_5.addItem(spacerItem1) self.label_11 = QLabel(self.employee_frame_3) self.label_11.setStyleSheet("background:transparent;") self.label_11.setObjectName("label_11") self.verticalLayout_5.addWidget(self.label_11) self.gridLayout.addWidget(self.employee_frame_3, 0, 2, 1, 1) self.menu_frame_4 = QFrame(self.home_page) self.menu_frame_4.setStyleSheet( "background-image:url(:/images/menu_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#297ACC;") self.menu_frame_4.setFrameShape(QFrame.StyledPanel) self.menu_frame_4.setFrameShadow(QFrame.Raised) self.menu_frame_4.setObjectName("menu_frame_4") self.verticalLayout_3 = QVBoxLayout(self.menu_frame_4) self.verticalLayout_3.setObjectName("verticalLayout_3") spacerItem2 = QSpacerItem(20, 216, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_3.addItem(spacerItem2) self.label_12 = QLabel(self.menu_frame_4) self.label_12.setStyleSheet("background:transparent;") self.label_12.setObjectName("label_12") self.verticalLayout_3.addWidget(self.label_12) self.gridLayout.addWidget(self.menu_frame_4, 1, 0, 1, 1) self.report_frame_5 = QFrame(self.home_page) self.report_frame_5.setStyleSheet( "background-image:url(:/images/report_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#006BB2;") self.report_frame_5.setFrameShape(QFrame.StyledPanel) self.report_frame_5.setFrameShadow(QFrame.Raised) self.report_frame_5.setObjectName("report_frame_5") self.verticalLayout_6 = QVBoxLayout(self.report_frame_5) self.verticalLayout_6.setObjectName("verticalLayout_6") spacerItem3 = QSpacerItem(20, 216, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_6.addItem(spacerItem3) self.label_13 = QLabel(self.report_frame_5) self.label_13.setStyleSheet("background:transparent;") self.label_13.setObjectName("label_13") self.verticalLayout_6.addWidget(self.label_13) self.gridLayout.addWidget(self.report_frame_5, 1, 1, 1, 1) self.waste_frame_6 = QFrame(self.home_page) self.waste_frame_6.setStyleSheet( "background-image:url(:/images/waste_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#003D7A;") self.waste_frame_6.setFrameShape(QFrame.StyledPanel) self.waste_frame_6.setFrameShadow(QFrame.Raised) self.waste_frame_6.setObjectName("waste_frame_6") self.verticalLayout_7 = QVBoxLayout(self.waste_frame_6) self.verticalLayout_7.setObjectName("verticalLayout_7") spacerItem4 = QSpacerItem(20, 216, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_7.addItem(spacerItem4) self.label_14 = QLabel(self.waste_frame_6) self.label_14.setStyleSheet("background:transparent;") self.label_14.setObjectName("label_14") self.verticalLayout_7.addWidget(self.label_14) self.gridLayout.addWidget(self.waste_frame_6, 1, 2, 1, 1) self.inventory_frame_1 = QFrame(self.home_page) self.inventory_frame_1.setStyleSheet( "background-image:url(:/images/inventory_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#ADEBFF;") self.inventory_frame_1.setFrameShape(QFrame.StyledPanel) self.inventory_frame_1.setFrameShadow(QFrame.Raised) self.inventory_frame_1.setObjectName("inventory_frame_1") self.verticalLayout_2 = QVBoxLayout(self.inventory_frame_1) self.verticalLayout_2.setObjectName("verticalLayout_2") spacerItem5 = QSpacerItem(20, 217, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_2.addItem(spacerItem5) self.label_9 = QLabel(self.inventory_frame_1) self.label_9.setStyleSheet("background:transparent;") self.label_9.setObjectName("label_9") self.verticalLayout_2.addWidget(self.label_9) self.gridLayout.addWidget(self.inventory_frame_1, 0, 0, 1, 1) self.stackedWidget.addWidget(self.home_page) self.detail_page = QWidget() self.detail_page.setObjectName("detail_page") self.horizontalLayout_2 = QHBoxLayout(self.detail_page) self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.main_tabWidget = QTabWidget(self.detail_page) self.main_tabWidget.setAutoFillBackground(False) self.main_tabWidget.setStyleSheet("") self.main_tabWidget.setTabPosition(QTabWidget.West) self.main_tabWidget.setIconSize(QSize(60, 60)) self.main_tabWidget.setElideMode(Qt.ElideNone) self.main_tabWidget.setObjectName("main_tabWidget") ##initializes the tabs self.add_tabs() self.main_tabWidget.setFocusPolicy(Qt.StrongFocus) self.main_tabWidget.focusInEvent = self.change_focus self.main_tabWidget.currentChanged.connect(self.change_focus) self.stackedWidget.currentChanged.connect(self.change_focus) ###### self.horizontalLayout_2.addWidget(self.main_tabWidget) self.stackedWidget.addWidget(self.detail_page) if ('Admin', True) in self.access: self.stackedWidget.addWidget(Admin(self.mainwindow)) notification = NotificationTab() tab = notification.notificationTab_tab_4 tab.custom_class_object = notification # class_object is used to access the api through the self.stackedWidget.addWidget(tab) self.gridLayout_2.addWidget(self.stackedWidget, 0, 0, 1, 1) self.mainwindow.setCentralWidget(self.centralWidget) self.menuBar = QMenuBar(self.mainwindow) self.menuBar.setGeometry(QRect(0, 0, 832, 29)) self.menuBar.setObjectName("menuBar") self.mainwindow.setMenuBar(self.menuBar) self.mainToolBar = QToolBar(self.mainwindow) self.mainToolBar.setLayoutDirection(Qt.RightToLeft) self.mainToolBar.setStyleSheet("") self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainToolBar.setObjectName("mainToolBar") self.mainwindow.addToolBar(Qt.TopToolBarArea, self.mainToolBar) self.statusBar = QStatusBar(self.mainwindow) self.statusBar.setObjectName("statusBar") self.mainwindow.setStatusBar(self.statusBar) self.toolBar = QToolBar(self.mainwindow) self.toolBar.setLayoutDirection(Qt.RightToLeft) self.toolBar.setStyleSheet("") self.toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.toolBar.setObjectName("toolBar") self.mainwindow.addToolBar(Qt.TopToolBarArea, self.toolBar) self.actionNotification = QAction(self.mainwindow) self.actionNotification.setCheckable(True) self.actionNotification.setChecked(False) self.actionNotification.setEnabled(True) icon6 = QIcon() icon6.addPixmap(QPixmap(":/images/notification.png"), QIcon.Normal, QIcon.Off) self.actionNotification.setIcon(icon6) self.actionNotification.setAutoRepeat(True) self.actionNotification.setVisible(True) self.actionNotification.setIconVisibleInMenu(False) self.actionNotification.setObjectName("actionNotification") self.actionNotification self.actionAdmin = QAction(self.mainwindow) # self.actionAdmin.setCheckable(True) icon7 = QIcon() icon7.addPixmap(QPixmap(":/images/admin.png"), QIcon.Normal, QIcon.Off) self.actionAdmin.setIcon(icon7) self.actionAdmin.setObjectName("actionAdmin") self.actionRefresh = QAction(self.mainwindow) icon8 = QIcon() icon8.addPixmap(QPixmap(":/images/refresh.png"), QIcon.Normal, QIcon.Off) self.actionRefresh.setIcon(icon8) self.actionRefresh.setObjectName("actionRefresh") self.actionHome = QAction(self.mainwindow) # self.actionHome.setCheckable(True) icon9 = QIcon() icon9.addPixmap(QPixmap(":/images/home.png"), QIcon.Normal, QIcon.Off) self.actionHome.setIcon(icon9) self.actionHome.setObjectName("actionHome") self.actionSettings = QAction(self.mainwindow) icon10 = QIcon() icon10.addPixmap(QPixmap(":/images/settings.png"), QIcon.Normal, QIcon.Off) self.actionSettings.setIcon(icon10) self.actionSettings.setObjectName("actionRefresh") self.toolBar.addAction(self.actionNotification) self.toolBar.addSeparator() self.toolBar.addAction(self.actionAdmin) if ('Admin', True) in self.access: self.toolBar.addSeparator() else: self.actionAdmin.setVisible(False) self.toolBar.addAction(self.actionHome) self.toolBar.addSeparator() self.toolBar.addAction(self.actionRefresh) self.toolBar.addSeparator() self.toolBar.addAction(self.actionSettings) ##retranslates self.mainwindow.setWindowTitle( QApplication.translate("MainWindow", settings.company, None, QApplication.UnicodeUTF8)) self.label_10.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">BILLING</p></body></html>", None, QApplication.UnicodeUTF8)) self.label_11.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">EMPLOYEE</p></body></html>", None, QApplication.UnicodeUTF8)) self.label_12.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">MENU</p></body></html>", None, QApplication.UnicodeUTF8)) self.label_13.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">REPORT</p></body></html>", None, QApplication.UnicodeUTF8)) self.label_14.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">WASTE</p></body></html>", None, QApplication.UnicodeUTF8)) self.label_9.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">INVENTORY</p></body></html>", None, QApplication.UnicodeUTF8)) self.inventory_frame_1.setToolTip( QApplication.translate("MainWindow", "Go to the Inventory Tab", None, QApplication.UnicodeUTF8)) self.billing_frame_2.setToolTip( QApplication.translate("MainWindow", "Go to the Billing Tab", None, QApplication.UnicodeUTF8)) self.employee_frame_3.setToolTip( QApplication.translate("MainWindow", "Go to the Employee Tab", None, QApplication.UnicodeUTF8)) self.menu_frame_4.setToolTip( QApplication.translate("MainWindow", "Go to the Menu Tab", None, QApplication.UnicodeUTF8)) self.report_frame_5.setToolTip( QApplication.translate("MainWindow", "Go to the Report Tab", None, QApplication.UnicodeUTF8)) self.waste_frame_6.setToolTip( QApplication.translate("MainWindow", "Go to the Waste Tab", None, QApplication.UnicodeUTF8)) self.toolBar.setWindowTitle( QApplication.translate("MainWindow", "toolBar", None, QApplication.UnicodeUTF8)) self.actionNotification.setText("&&Notification") # QApplication.translate("MainWindow", "&Notification", None, QApplication.UnicodeUTF8)) self.actionNotification.setToolTip( QApplication.translate("MainWindow", "Click to see new notifications", None, QApplication.UnicodeUTF8)) # self.actionNotification.setShortcut( # QApplication.translate("MainWindow", "Ctrl+Shift+N", None, QApplication.UnicodeUTF8)) self.actionAdmin.setText('&&Admin') # QApplication.translate("MainWindow", "Admin", None, QApplication.UnicodeUTF8)) self.actionAdmin.setToolTip( QApplication.translate("MainWindow", "Click to go to admin interface", None, QApplication.UnicodeUTF8)) # self.actionAdmin.setShortcut( # QApplication.translate("MainWindow", "Ctrl+Shift+A", None, QApplication.UnicodeUTF8)) self.actionRefresh.setText("&&Refresh") # QApplication.translate("MainWindow", "Refresh", None, QApplication.UnicodeUTF8)) self.actionRefresh.setToolTip( QApplication.translate("MainWindow", "refreshes the data from the server", None, QApplication.UnicodeUTF8)) # self.actionRefresh.setShortcut( # QApplication.translate("MainWindow", "Ctrl+Shift+R", None, QApplication.UnicodeUTF8)) self.actionHome.setText('&&Home') # QApplication.translate("MainWindow", "Home", None, QApplication.UnicodeUTF8)) self.actionHome.setToolTip( QApplication.translate("MainWindow", "Go back to the home screen", None, QApplication.UnicodeUTF8)) self.actionSettings.setText('&&Settings') # QApplication.translate("MainWindow", "Settings", None, QApplication.UnicodeUTF8)) self.actionSettings.setToolTip( QApplication.translate("MainWindow", "Go to the settings panel", None, QApplication.UnicodeUTF8)) # self.actionHome.setShortcut( # QApplication.translate("MainWindow", "Ctrl+Shift+H", None, QApplication.UnicodeUTF8)) self.stackedWidget.setCurrentIndex(1) self.main_tabWidget.setCurrentIndex(0) self.ob = self.main_tabWidget.tabBar() # self.add_tool_tip(self.ob) todo avoided due to segmentation fault error, left for future fixes self.tb = EventHandlerForTabBar() self.ob.installEventFilter(self.tb) QMetaObject.connectSlotsByName(self.mainwindow) def add_tabs(self): """ adds new tabs """ global logger if ('Inventory', True) in self.access: logger.info('initiating Inventory') icon = QIcon() icon.addPixmap(QPixmap(":/images/inventory.png"), QIcon.Normal, QIcon.Off) from inventory.inventory import Inventory inventory = Inventory() # inventory.inventory_tab_1.setToolTip("Inventory Section") self.main_tabWidget.addTab(inventory.inventory_tab_1, icon, "") inventory.inventory_detail_tabWidget.setCurrentIndex(0) else: self.inventory_frame_1.setVisible(False) self.progress.setLabelText('Inventory Done....') self.progress.setValue(2) if ('Billing', True) in self.access: logger.info('initiating Billing') icon1 = QIcon() icon1.addPixmap(QPixmap(":/images/billing.png"), QIcon.Normal, QIcon.Off) from billing.billing import Billing bill = Billing() # bill.billing_tab_2.setToolTip("Billing Section") self.main_tabWidget.addTab(bill.billing_tab_2, icon1, "") bill.billing_detail_tabWidget.setCurrentIndex(0) else: self.billing_frame_2.setVisible(False) self.progress.setLabelText('Billing Done...') self.progress.setValue(3) if ('Employee', True) in self.access: logger.info('initiating Employee') icon2 = QIcon() icon2.addPixmap(QPixmap(":/images/employee.png"), QIcon.Normal, QIcon.Off) from employee.employee import Employee employee = Employee() # employee.employee_tab_3.setToolTip("Employee Section") self.main_tabWidget.addTab(employee.employee_tab_3, icon2, "") employee.employee_detail_tabWidget.setCurrentIndex(0) else: self.employee_frame_3.setVisible(False) self.progress.setLabelText('Employee Done...') self.progress.setValue(4) if ('Menu', True) in self.access: logger.info('initiating Menu') icon3 = QIcon() icon3.addPixmap(QPixmap(":/images/menu.png"), QIcon.Normal, QIcon.Off) from menu.menu import Menu menu = Menu() # menu.menu_tab_4.setToolTip("Menu Section") self.main_tabWidget.addTab(menu.menu_tab_4, icon3, "") menu.menu_detail_tabWidget.setCurrentIndex(0) else: self.menu_frame_4.setVisible(False) self.progress.setLabelText('Menu Done....') self.progress.setValue(5) if ('Report', True) in self.access: logger.info('initiating Report') icon4 = QIcon() icon4.addPixmap(QPixmap(":/images/report.png"), QIcon.Normal, QIcon.Off) from report.report import Report report = Report() # report.report_tab_5.setToolTip("Report Section") self.main_tabWidget.addTab(report.report_tab_5, icon4, "") report.report_detail_tabWidget.setCurrentIndex(0) else: self.report_frame_5.setVisible(False) self.progress.setLabelText('Report Done....') self.progress.setValue(6) if ('Waste', True) in self.access: logger.info('initiating Waste') icon5 = QIcon() icon5.addPixmap(QPixmap(":/images/waste.png"), QIcon.Normal, QIcon.Off) from waste.waste import Waste waste = Waste() # waste.waste_tab_6.setToolTip("Waste Section") self.main_tabWidget.addTab(waste.waste_tab_6, icon5, "") waste.waste_detail_tabWidget.setCurrentIndex(0) else: self.waste_frame_6.setVisible(False) self.progress.setLabelText('Waste Done....') self.progress.setValue(7) def change_focus(self, event=None): """ focus method to set focus to a tab to initialize the corresponding events of the tab """ wid = self.main_tabWidget.currentWidget() if wid: if wid.isVisible(): # print wid.objectName() # print '1y' wid.setFocus() def add_tool_tip( self, ob ): # todo not working causing segmentation fault, avoided calling this function """ method to add tool tip to the tabs :param ob: Tab bar """ obj = ob count = obj.count() hardcode = { 0: 'Inventory Section', 1: "Billing Section", 2: "Employee Section", 3: "Menu Section", 4: "Report Section", 5: "Waste Section" } for i in range(count): obj.setTabToolTip(i, hardcode[i])
class MainWindow(QtGui.QMainWindow): """The application's main window """ FILE_FILTER = "inselect files (*{0})".format(InselectDocument.EXTENSION) def __init__(self, app, filename=None): super(MainWindow, self).__init__() self.app = app # Boxes view self.view_graphics_item = GraphicsItemView() # self.boxes_view is a QGraphicsView, not a QAbstractItemView self.boxes_view = BoxesView(self.view_graphics_item.scene) # Metadata view self.view_specimen = SpecimenView() self.view_metadata = MetadataView() self.specimens = QtGui.QSplitter() self.specimens.addWidget(self.view_specimen) self.specimens.addWidget(self.view_metadata.widget) self.specimens.setSizes([600, 300]) # Views in tabs self.tabs = QtGui.QTabWidget(self) self.tabs.addTab(self.boxes_view, 'Boxes') self.tabs.addTab(self.specimens, 'Specimens') self.tabs.setCurrentIndex(0) # Summary view self.view_summary = SummaryView() # Main window layout layout = QtGui.QVBoxLayout() layout.addWidget(self.view_summary.widget) layout.addWidget(self.tabs) box = QtGui.QWidget() box.setLayout(layout) self.setCentralWidget(box) # Document self.document = None self.document_path = None # Model self.model = Model() self.view_graphics_item.setModel(self.model) self.view_specimen.setModel(self.model) self.view_metadata.setModel(self.model) self.view_summary.setModel(self.model) # A consistent selection across all views sm = self.view_specimen.selectionModel() self.view_graphics_item.setSelectionModel(sm) self.view_metadata.setSelectionModel(sm) self.view_summary.setSelectionModel(sm) # Plugins self.plugins = [SegmentPlugin, SubsegmentPlugin, BarcodePlugin] self.plugin_actions = len(self.plugins) * [None] # QActions self.plugin_image = None self.plugin_image_visible = False # Long-running operations are run in their own thread. self.running_operation = None self.create_actions() self.create_menus() # Conect signals self.tabs.currentChanged.connect(self.current_tab_changed) sm.selectionChanged.connect(self.selection_changed) # Filter events self.tabs.installEventFilter(self) self.boxes_view.installEventFilter(self) self.view_specimen.installEventFilter(self) self.view_metadata.installEventFilter(self) self.empty_document() self.setAcceptDrops(True) if filename: self.open_file(filename) def eventFilter(self, obj, event): if event.type() in (QEvent.DragEnter, QEvent.Drop): return True else: return super(MainWindow, self).eventFilter(obj, event) @report_to_user def open_file(self, path=None): """Opens path, which can be None, the path to an inselect document or the path to an image file. If None, the user is prompted to select a file. * If a .inselect file, the file is opened * If an image file for which a .inselect document already exists, the .inselect file is opened * If a _thumbnail.jpg file corresponding to an existing .inselect file, the .inselect file is opened * If an image file, a new .inselect file is created and opened """ debug_print(u'MainWindow.open_file [{0}]'.format(path)) if not path: folder = QSettings().value( 'working_directory', QDesktopServices.storageLocation( QDesktopServices.DocumentsLocation)) filter = u'Inselect documents (*{0});;Images ({1})' filter = filter.format(InselectDocument.EXTENSION, u' '.join(IMAGE_PATTERNS)) path, selectedFilter = QtGui.QFileDialog.getOpenFileName( self, "Open", folder, filter) if path: # Will be None if user cancelled getOpenFileName if not self.close_document(): # User does not want to close the existing document pass else: path = Path(path) if path.suffix in IMAGE_SUFFIXES: # Compute the path to the inselect document (which may or # may not already exist) of the image file doc_of_image = path.name.replace( InselectDocument.THUMBNAIL_SUFFIX, u'') doc_of_image = path.parent / doc_of_image doc_of_image = doc_of_image.with_suffix( InselectDocument.EXTENSION) else: doc_of_image = None if InselectDocument.EXTENSION == path.suffix: # Open the .inselect document debug_print('Opening inselect document [{0}]'.format(path)) self.open_document(path) elif doc_of_image and doc_of_image.is_file(): # An image file corresponding to an existing .inselect file msg = u'Opening inselect document [{0}] of thumbnail [{1}]' debug_print(msg.format(doc_of_image, path)) self.open_document(doc_of_image) elif path.suffix in IMAGE_SUFFIXES: msg = u'Creating new inselect document for image [{0}]' debug_print(msg.format(path)) self.new_document(path) else: raise InselectError('Unknown file type [{0}]'.format(path)) def new_document(self, path): """Creates and opens a new inselect document for the scanned image given in path """ debug_print('MainWindow.new_document [{0}]'.format(path)) path = Path(path) if not path.is_file(): raise InselectError( u'Image file [{0}] does not exist'.format(path)) else: # Callable for worker thread class NewDoc(object): def __init__(self, image): self.image = image def __call__(self, progress): progress('Creating thumbnail of scanned image') doc = ingest_image(self.image, self.image.parent) self.document_path = doc.document_path self.run_in_worker(NewDoc(path), 'New document', self.new_document_finished) def new_document_finished(self, operation): """Called when new_document worker has finished """ debug_print('MainWindow.new_document_finished') document_path = operation.document_path QSettings().setValue('working_directory', str(document_path.parent)) self.open_file(document_path) msg = u'New Inselect document [{0}] created in [{1}]' msg = msg.format(document_path.stem, document_path.parent) QMessageBox.information(self, "Document created", msg) def open_document(self, path): """Opens the inselect document given by path """ debug_print('MainWindow.open_document [{0}]'.format(path)) path = Path(path) document = InselectDocument.load(path) QSettings().setValue("working_directory", str(path.parent)) self.document = document self.document_path = path self.model.from_document(self.document) # TODO LH Prefer setWindowFilePath to setWindowTitle? self.setWindowTitle(u"Inselect [{0}]".format(self.document_path.stem)) self.sync_ui() @report_to_user def save_document(self): """Saves the document """ debug_print('MainWindow.save_document') items = [] self.model.to_document(self.document) self.document.save() self.model.clear_modified() @report_to_user def save_crops(self): """Saves cropped specimen images """ debug_print('MainWindow.save_crops') res = QMessageBox.Yes existing_crops = self.document.crops_dir.is_dir() if existing_crops: msg = 'Overwrite the existing cropped specimen images?' res = QMessageBox.question(self, 'Write cropped specimen images?', msg, QMessageBox.No, QMessageBox.Yes) if QMessageBox.Yes == res: def save_crops(progress): progress('Loading full-resolution scanned image') self.document.scanned.array progress('Saving crops') self.document.save_crops(progress) def completed(operation): QMessageBox.information(self, "Crops saved", msg) self.model.to_document(self.document) msg = "{0} crops saved in {1}" msg = msg.format(self.document.n_items, self.document.crops_dir) self.run_in_worker(save_crops, 'Save crops', completed) @report_to_user def export_csv(self): debug_print('MainWindow.export_csv') path = self.document.document_path.with_suffix('.csv') res = QMessageBox.Yes existing_csv = path.is_file() if existing_csv: msg = 'Overwrite the existing CSV file?' res = QMessageBox.question(self, 'Export CSV file?', msg, QMessageBox.No, QMessageBox.Yes) if QMessageBox.Yes == res: self.model.to_document(self.document) self.document.export_csv(path) msg = "Data for {0} boxes written to {1}" msg = msg.format(self.document.n_items, path) QMessageBox.information(self, "CSV saved", msg) @report_to_user def close_document(self): """Closes the document and returns True if not modified or if modified and user does not cancel. Does not close the document and returns False if modified and users cancels. """ debug_print('MainWindow.close_document') if self.model.modified: # Ask the user if they work like to save before closing res = QMessageBox.question( self, 'Save document?', 'Save the document before closing?', (QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel), QMessageBox.Yes) if QMessageBox.Yes == res: self.save_document() # Answering Yes or No means the document will be closed close = QMessageBox.Cancel != res else: # The document is not modified so it is OK to close it close = True if close: self.empty_document() return close @report_to_user def empty_document(self): """Creates an empty document """ debug_print('MainWindow.empty_document') self.document = None self.plugin_image = None self.plugin_image_visible = False self.model.clear() # TODO LH Prefer setWindowFilePath to setWindowTitle? self.setWindowTitle("Inselect") self.sync_ui() def closeEvent(self, event): """QWidget virtual """ debug_print('MainWindow.closeEvent') if self.close_document(): # User wants to close self.write_geometry_settings() event.accept() else: # User does not want to close event.ignore() @report_to_user def zoom_in(self): self.boxes_view.zoom_in() @report_to_user def zoom_out(self): self.boxes_view.zoom_out() @report_to_user def toggle_zoom(self): self.boxes_view.toggle_zoom() @report_to_user def zoom_home(self): self.boxes_view.zoom_home() @report_to_user def show_grid(self): self.view_specimen.show_grid() @report_to_user def show_expanded(self): self.view_specimen.show_expanded() @report_to_user def about(self): text = u"""<h1>Inselect {version}</h1> <h2>Contributors</h2> <p> <strong>Stefan van der Walt</strong>: Application development and segmentation algorithm </p> <p> <strong>Pieter Holtzhausen</strong>: Application development and segmentation algorithm </p> <p> <strong>Alice Heaton</strong>: Application development </p> <p> <strong>Lawrence Hudson</strong>: Application development </p> """.format(version=inselect.__version__) QMessageBox.about(self, 'Inselect', text) @report_to_user def help(self): """Open the help dialog""" d = HelpDialog(self) d.exec_() def run_in_worker(self, operation, name, complete_fn=None): """Runs the callable operation in a worker thread. The callable complete_fn is called when the operation has finished. """ debug_print("MainWindow.run_in_worker") if self.running_operation: debug_print('Operation already running') else: worker = WorkerThread(operation, name, self) worker.completed.connect(self.worker_finished) self.running_operation = (operation, name, complete_fn, worker) worker.start() @report_to_user def worker_finished(self, user_cancelled, error_message): debug_print("MainWindow.worker_finished", user_cancelled, error_message) operation, name, complete_fn, worker = self.running_operation self.running_operation = None if user_cancelled: QMessageBox.information(self, 'Cancelled', "'{0} cancelled'".format(name)) elif error_message: QMessageBox.information( self, "An error occurred running '{0}'".format(name), error_message + '\n\nExisting data has not been altered') else: if complete_fn: complete_fn(operation) self.sync_ui() @report_to_user def run_plugin(self, plugin_number): """Passes each cropped specimen image through plugin """ debug_print("MainWindow.run_plugin") if plugin_number < 0 or plugin_number > len(self.plugins): raise ValueError('Unexpected plugin [{0}]'.format(plugin_number)) else: plugin = self.plugins[plugin_number] self.model.to_document(self.document) # Create the plugin operation = plugin(self.document, self) if operation.proceed(): self.run_in_worker(operation, operation.name(), self.plugin_finished) else: pass def plugin_finished(self, operation): """Called when a plugin has finished running in a worker thread """ debug_print("MainWindow.plugin_finished") if hasattr(operation, 'items'): self.model.set_new_boxes(operation.items) if hasattr(operation, 'display'): # An image that can be displayed instead of the main image display = operation.display self.plugin_image = QtGui.QPixmap.fromImage(qimage_of_bgr(display)) self.update_boxes_display_pixmap() @report_to_user def select_all(self): """Selects all boxes in the model """ sm = self.view_specimen.selectionModel() m = self.model sm.select( QtGui.QItemSelection(m.index(0, 0), m.index(m.rowCount() - 1, 0)), QtGui.QItemSelectionModel.Select) @report_to_user def select_none(self): sm = self.view_specimen.selectionModel() sm.select(QtGui.QItemSelection(), QtGui.QItemSelectionModel.Clear) @report_to_user def delete_selected(self): """Deletes the selected boxes """ # Delete contiguous blocks of rows selected = self.view_specimen.selectionModel().selectedIndexes() selected = sorted([i.row() for i in selected]) # Remove blocks in reverse order so that row indices are not invalidated # TODO LH We shouldn't need to remove blocks in reverse order - stems # from crummy GraphicsItemView for row, count in reversed(list(contiguous(selected))): self.model.removeRows(row, count) @report_to_user def select_next_prev(self, next): """Selects the next box in the mode if next is True, the previous box in the model if next if False. """ sm = self.view_specimen.selectionModel() current = sm.currentIndex() current = current.row() if current else -1 select = current + (1 if next else -1) if select == self.model.rowCount(): select = 0 elif -1 == select: select = self.model.rowCount() - 1 debug_print('Will move selection [{0}] from [{1}]'.format( current, select)) select = self.model.index(select, 0) sm.select(QtGui.QItemSelection(select, select), QtGui.QItemSelectionModel.ClearAndSelect) sm.setCurrentIndex(select, QtGui.QItemSelectionModel.Current) @report_to_user def rotate90(self, clockwise): """Rotates the selected boxes 90 either clockwise or counter-clockwise. """ debug_print('MainWindow.rotate') value = 90 if clockwise else -90 selected = self.view_specimen.selectionModel().selectedIndexes() for index in selected: current = index.data(RotationRole) self.model.setData(index, current + value, RotationRole) def update_boxes_display_pixmap(self): """Sets the pixmap in the boxes view """ pixmap = self.plugin_image if self.plugin_image_visible else None self.view_graphics_item.show_alternative_pixmap(pixmap) @report_to_user def toggle_plugin_image(self): """Action method to switch between display of the last plugin's information image (if any) and the actual image. """ self.plugin_image_visible = not self.plugin_image_visible self.update_boxes_display_pixmap() def create_actions(self): # File menu self.open_action = QAction("&Open...", self, shortcut=QtGui.QKeySequence.Open, triggered=self.open_file, icon=self.style().standardIcon( QtGui.QStyle.SP_DialogOpenButton)) self.save_action = QAction("&Save", self, shortcut=QtGui.QKeySequence.Save, triggered=self.save_document, icon=self.style().standardIcon( QtGui.QStyle.SP_DialogSaveButton)) self.save_crops_action = QAction("&Save crops", self, triggered=self.save_crops) self.export_csv_action = QAction("&Export CSV", self, triggered=self.export_csv) self.close_action = QAction("&Close", self, shortcut=QtGui.QKeySequence.Close, triggered=self.close_document) self.exit_action = QAction("E&xit", self, shortcut=QtGui.QKeySequence.Quit, triggered=self.close) # Edit menu self.select_all_action = QAction("Select &All", self, shortcut=QtGui.QKeySequence.SelectAll, triggered=self.select_all) # QT does not provide a 'select none' key sequence self.select_none_action = QAction("Select &None", self, shortcut="ctrl+D", triggered=self.select_none) self.next_box_action = QAction("Next box", self, shortcut="N", triggered=partial(self.select_next_prev, next=True)) self.previous_box_action = QAction("Previous box", self, shortcut="P", triggered=partial( self.select_next_prev, next=False)) # TODO LH Does CMD + Backspace work on a mac? self.delete_action = QAction("&Delete selected", self, shortcut=QtGui.QKeySequence.Delete, triggered=self.delete_selected) self.rotate_clockwise_action = QAction("Rotate clockwise", self, shortcut="R", triggered=partial( self.rotate90, clockwise=True)) self.rotate_counter_clockwise_action = QAction( "Rotate counter-clockwise", self, shortcut="L", triggered=partial(self.rotate90, clockwise=False)) # Plugins # Plugin shortcuts start at F5 shortcut_offset = 5 for index, plugin in enumerate(self.plugins): action = QAction(plugin.name(), self, triggered=partial(self.run_plugin, index)) shortcut_fkey = index + shortcut_offset if shortcut_fkey < 13: # Keyboards typically have 12 function keys action.setShortcut('f{0}'.format(shortcut_fkey)) icon = plugin.icon() if icon: action.setIcon(icon) self.plugin_actions[index] = action # View menu # The obvious approach is to set the trigger to # partial(self.tabs.setCurrentIndex, 0) but this causes a segfault when # the application exits on linux. self.boxes_view_action = QAction("&Boxes", self, checkable=True, triggered=partial(self.show_tab, 0)) self.metadata_view_action = QAction("&Specimens", self, checkable=True, triggered=partial( self.show_tab, 1)) # FullScreen added in Qt 5.something # https://qt.gitorious.org/qt/qtbase-miniak/commit/1ef8a6d if not hasattr(QtGui.QKeySequence, 'FullScreen'): if 'darwin' == sys.platform: KeySequenceFullScreen = 'shift+ctrl+f' else: KeySequenceFullScreen = 'f11' else: KeySequenceFullScreen = QtGui.QKeySequence.FullScreen self.full_screen_action = QAction("&Full screen", self, shortcut=KeySequenceFullScreen, triggered=self.toggle_full_screen) self.zoom_in_action = QAction("Zoom &In", self, shortcut=QtGui.QKeySequence.ZoomIn, triggered=self.zoom_in, icon=self.style().standardIcon( QtGui.QStyle.SP_ArrowUp)) self.zoom_out_action = QAction("Zoom &Out", self, shortcut=QtGui.QKeySequence.ZoomOut, triggered=self.zoom_out, icon=self.style().standardIcon( QtGui.QStyle.SP_ArrowDown)) self.toogle_zoom_action = QAction("&Toogle Zoom", self, shortcut='Z', triggered=self.toggle_zoom) self.zoom_home_action = QAction( "Fit To Window", self, shortcut=QtGui.QKeySequence.MoveToStartOfDocument, triggered=self.zoom_home) # TODO LH Is F3 (normally meaning 'find next') really the right # shortcut for the 'toggle plugin image' action? self.toggle_plugin_image_action = QAction( "&Display plugin image", self, shortcut="f3", triggered=self.toggle_plugin_image, statusTip="Display plugin image", checkable=True) self.show_specimen_grid_action = QAction('Show grid', self, shortcut='g', triggered=self.show_grid) self.show_specimen_expanded_action = QAction( 'Show expanded', self, shortcut='e', triggered=self.show_expanded) # Help menu self.about_action = QAction("&About", self, triggered=self.about) self.help_action = QAction("&Help", self, shortcut=QtGui.QKeySequence.HelpContents, triggered=self.help) def create_menus(self): self.toolbar = self.addToolBar("Edit") self.toolbar.addAction(self.open_action) self.toolbar.addAction(self.save_action) for action in [a for a in self.plugin_actions if a.icon()]: self.toolbar.addAction(action) self.toolbar.addAction(self.zoom_in_action) self.toolbar.addAction(self.zoom_out_action) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.fileMenu = QMenu("&File", self) self.fileMenu.addAction(self.open_action) self.fileMenu.addAction(self.save_action) self.fileMenu.addAction(self.save_crops_action) self.fileMenu.addAction(self.export_csv_action) self.fileMenu.addAction(self.close_action) self.fileMenu.addSeparator() self.fileMenu.addAction(self.exit_action) self.editMenu = QMenu("&Edit", self) self.editMenu.addAction(self.select_all_action) self.editMenu.addAction(self.select_none_action) self.editMenu.addAction(self.delete_action) self.editMenu.addSeparator() self.editMenu.addAction(self.next_box_action) self.editMenu.addAction(self.previous_box_action) self.editMenu.addSeparator() self.editMenu.addAction(self.rotate_clockwise_action) self.editMenu.addAction(self.rotate_counter_clockwise_action) self.editMenu.addSeparator() for action in self.plugin_actions: self.editMenu.addAction(action) self.viewMenu = QMenu("&View", self) self.viewMenu.addAction(self.boxes_view_action) self.viewMenu.addAction(self.metadata_view_action) self.viewMenu.addSeparator() self.viewMenu.addAction(self.full_screen_action) self.viewMenu.addSeparator() self.viewMenu.addAction(self.zoom_in_action) self.viewMenu.addAction(self.zoom_out_action) self.viewMenu.addAction(self.toogle_zoom_action) self.viewMenu.addAction(self.zoom_home_action) self.viewMenu.addAction(self.toggle_plugin_image_action) self.viewMenu.addSeparator() self.viewMenu.addAction(self.show_specimen_grid_action) self.viewMenu.addAction(self.show_specimen_expanded_action) self.helpMenu = QMenu("&Help", self) self.helpMenu.addAction(self.help_action) self.helpMenu.addAction(self.about_action) self.menuBar().addMenu(self.fileMenu) self.menuBar().addMenu(self.editMenu) self.menuBar().addMenu(self.viewMenu) self.menuBar().addMenu(self.helpMenu) def show_tab(self, index): self.tabs.setCurrentIndex(index) def current_tab_changed(self, index): """Slot for self.tabs.currentChanged() signal """ self.sync_ui() def selection_changed(self, selected, deselected): """Slot for self.grid_view.selectionModel().selectionChanged() signal """ self.sync_ui() @report_to_user def toggle_full_screen(self): """Toggles between full screen and normal """ if self.isFullScreen(): self.showNormal() else: self.showFullScreen() def _accept_drag_drop(self, event): """If event refers to a single file that can opened, returns the path. Returns None otherwise. """ urls = event.mimeData().urls() if event.mimeData() else None path = Path(urls[0].toLocalFile()) if urls and 1 == len(urls) else None if (path and path.suffix in chain([InselectDocument.EXTENSION], IMAGE_SUFFIXES)): return urls[0].toLocalFile() else: return None def dragEnterEvent(self, event): """QWidget virtual """ debug_print('MainWindow.dragEnterEvent') if self._accept_drag_drop(event): event.acceptProposedAction() else: super(MainWindow, self).dragEnterEvent(event) def dropEvent(self, event): """QWidget virtual """ debug_print('MainWindow.dropEvent') res = self._accept_drag_drop(event) if res: event.acceptProposedAction() self.open_file(res) else: super(MainWindow, self).dropEvent(event) def write_geometry_settings(self): "Writes geometry to settings" debug_print('MainWindow.write_geometry_settings') # Taken from http://stackoverflow.com/a/8736705 # TODO LH Test on multiple display system s = QSettings() s.setValue("mainwindow/geometry", self.saveGeometry()) s.setValue("mainwindow/pos", self.pos()) s.setValue("mainwindow/size", self.size()) def show_from_geometry_settings(self): debug_print('MainWindow.show_from_geometry_settings') # TODO LH What if screen resolution, desktop config change or roaming # profile means that restored state is outside desktop? s = QSettings() self.restoreGeometry( s.value("mainwindow/geometry", self.saveGeometry())) if not (self.isMaximized() or self.isFullScreen()): self.move(s.value("mainwindow/pos", self.pos())) self.resize(s.value("mainwindow/size", self.size())) self.show() # if read_bool("mainwindow/maximized", self.isMaximized()): # debug_print('Will show maximized') # self.showMaximized() # elif read_bool("mainwindow/full_screen", self.isMaximized()): # debug_print('Will show full screen') # self.showFullScreen() # else: # debug_print('Will show normally') # self.show() def sync_ui(self): """Synchronise the user interface with the application state """ document = self.document is not None has_rows = self.model.rowCount() > 0 if self.model else False boxes_view_visible = self.boxes_view == self.tabs.currentWidget() specimens_view_visible = self.specimens == self.tabs.currentWidget() has_selection = len(self.view_specimen.selectedIndexes()) > 0 # File self.save_action.setEnabled(document) self.save_crops_action.setEnabled(has_rows) self.export_csv_action.setEnabled(has_rows) self.close_action.setEnabled(document) # Edit self.select_all_action.setEnabled(has_rows) self.select_none_action.setEnabled(document) self.delete_action.setEnabled(has_selection) self.next_box_action.setEnabled(has_rows) self.previous_box_action.setEnabled(has_rows) self.rotate_clockwise_action.setEnabled(has_selection) self.rotate_counter_clockwise_action.setEnabled(has_selection) for action in self.plugin_actions: action.setEnabled(document) # View self.boxes_view_action.setChecked(boxes_view_visible) self.metadata_view_action.setChecked(not boxes_view_visible) self.zoom_in_action.setEnabled(document and boxes_view_visible) self.zoom_out_action.setEnabled(document and boxes_view_visible) self.toogle_zoom_action.setEnabled(document and boxes_view_visible) self.zoom_home_action.setEnabled(document and boxes_view_visible) self.toggle_plugin_image_action.setEnabled(document and boxes_view_visible) self.show_specimen_grid_action.setEnabled(specimens_view_visible) self.show_specimen_expanded_action.setEnabled(specimens_view_visible)
class MainWindow(QMainWindow): """ Starting point of the GUI based application """ isMyProgressTimer = False def __init__(self): """ MainWindow Constructor Function""" super(MainWindow, self).__init__() wdgt = QWidget() wdgt.setWindowTitle = "ManageHD" self.setCentralWidget(wdgt) self.InitUI() self.GetParameterFileInfo() def InitUI(self): """ Initialize user created UI elements """ self.qlVidsDone = QLabel('0', self) self.qlVidsInProgress = QLabel('0', self) self.qlStartTime = QLabel(datetime.now().strftime("%a, %d %b %Y %H:%M:%S"), self) self.qlEndTime = QLabel('', self) self.qlTimeLeft = QLabel('', self) self.qlDestinationSpace = QLabel('', self) self.qlArcSpace = QLabel('', self) self.qlProcessingSpeed = QLabel('', self) self.qleSourceDir = QLineEditDirectoriesOnly() self.qleArchiveDir = QLineEditDirectoriesOnly() self.qleDestinationDir = QLineEditDirectoriesOnly() self.qleMaxVidsCap = QLineEditIntsOnly() self.qleVideoTypes = QLineEditNoPeriodsOrCommas() self.qleVideoTypes.installEventFilter(self) self.qpbSourceDir = self.__CreateButton('folder.png',"", 50, self.SelectSingleFileForSourceDirectory) self.qpbArchiveDir = self.__CreateButton('folder.png',"", 50, self.SelectSingleFileForArchiveDirectory) self.qpbTargetDir = self.__CreateButton('folder.png',"", 50, self.SelectSingleFileForTargetDirectory) self.qpbRun = self.__CreateButton(None,"Run", 75, self.Process) self.setWindowTitle("Manage HD Video") self.videoExtensionFileFilter = "Video (*.mkv *.mp4 *.avi)" self.qleVideoTypes.setText("mkv mp4 avi") self.statusLabel = QLabel('Showing Progress') self.progressBar = QProgressBar() self.progressBar.setMinimum(0) self.progressBar.setMaximum(100) self.__CreateActions() self.__CreateMenus() self.fileMenu.addAction(self.stdAction) self.fileMenu.addAction(self.altAction) if Progress.runPlatform == 'win': self.stdAction.setIcon(QIcon('checked.jpg')) self.stdAction.setChecked(True) self.fileMenu.addSeparator() self.fileMenu.addAction(self.exitAction) self.fileMenu.addSeparator() self.helpMenu.addAction(self.aboutAction) self.__SetIcon() self.__CenterWindow() self.__CreateGrid() def eventFilter(self, source, event): #Override """ Override the QMainWindow eventFilter method to add File Mask Validation. """ if (event.type() == QEvent.FocusOut and source is self.qleVideoTypes): self.ValidateFileMask() return QMainWindow.eventFilter(self, source, event) def DisableGuiElements(self): """ Change the setEnabled property of the main GUI elements to False. """ self.qleArchiveDir.setEnabled(False) self.qleDestinationDir.setEnabled(False) self.qleMaxVidsCap.setEnabled(False) self.qleSourceDir.setEnabled(False) self.qleVideoTypes.setEnabled(False) self.qpbArchiveDir.setEnabled(False) self.qpbSourceDir.setEnabled(False) self.qpbTargetDir.setEnabled(False) self.qpbRun.setEnabled(False) def EnableGuiElements(self): """ Change the setEnabled property of the main GUI elements to True. """ self.qleArchiveDir.setEnabled(True) self.qleDestinationDir.setEnabled(True) self.qleMaxVidsCap.setEnabled(True) self.qleSourceDir.setEnabled(True) self.qleVideoTypes.setEnabled(True) self.qpbArchiveDir.setEnabled(True) self.qpbSourceDir.setEnabled(True) self.qpbTargetDir.setEnabled(True) self.qpbRun.setEnabled(True) def __AddGridLabel(self, grid, lblText, custFont, row, column, justification): sd = QLabel(lblText, self) sd.setFont(custFont) grid.addWidget(sd, row, column, alignment = justification) def SelectSingleFileForSourceDirectory(self): self.qleSourceDir.setText( self.InvokeSingleSelectionDirectoryDialog() ) self.ValidateFileMask() def SelectSingleFileForArchiveDirectory(self): self.qleArchiveDir.setText( self.InvokeSingleSelectionDirectoryDialog() ) def SelectSingleFileForTargetDirectory(self): self.qleDestinationDir.setText( self.InvokeSingleSelectionDirectoryDialog() ) def InvokeSingleSelectionFileDialog(self): """ Prompts the user to select a single file from a file dialog window. """ dialog = QFileDialog() dialog.setFileMode(QFileDialog.ExistingFile) dialog.setFilter(self.videoExtensionFileFilter) ret = dialog.exec_() FileNames = dialog.selectedFiles() if len(FileNames) == 0: FileNames.append(None) return FileNames[0] def InvokeSingleSelectionDirectoryDialog(self): """ Prompts the user to select a single directory from a directory dialog window. """ dialog = QFileDialog() dialog.setFileMode(QFileDialog.DirectoryOnly) DirectoryName = dialog.getExistingDirectory() if len(DirectoryName) == 0: DirectoryName = None return DirectoryName def ValidateFileMask(self): """ Function to validate that the entered file mask is valid. """ extensionList = "" if len(self.qleVideoTypes.text().split(" ")) > 0: for videoExtension in self.qleVideoTypes.text().split(" "): extensionList += ("*." + videoExtension + " ") extensionList = extensionList[:-1] self.videoExtensionFileFilter = "Video ({})".format(extensionList) def __CreateGrid(self): g1 = QGridLayout() self.centralWidget().setLayout(g1) g1.setSpacing(5) bold = QFont() bold.setBold(True) self.__AddGridLabel(g1, 'Source Directory:', QFont(), 0, 0, -1) self.__AddGridLabel(g1, 'Archive Directory:', QFont(), 1, 0, -1) self.__AddGridLabel(g1, 'Target Directory:', QFont(), 2, 0, -1) self.__AddGridLabel(g1, 'Max Number of Videos:', QFont(), 3, 0, -1) self.__AddGridLabel(g1, 'Video File Types:', QFont(), 3, 2, -1) #self.__AddGridLabel(g1, 'Max Run Time in Hours:', QFont(), 4, 2, -1) g1.addWidget(self.qleSourceDir, 0, 1, 1, 3) g1.addWidget(self.qleArchiveDir, 1, 1, 1, 3) g1.addWidget(self.qleDestinationDir, 2, 1, 1, 3) g1.addWidget(self.qleMaxVidsCap, 3, 1) g1.addWidget(self.qleVideoTypes, 3, 3) #g1.addWidget(self.qleRunTimeMax, 4, 3) g1.addWidget(self.qpbRun, 10, 3, alignment = -1) g1.addWidget(QLabel('', self), 4, 0,) # Empty Column As Separator g1.addWidget(QLabel('', self), 5, 0,) # Empty Column As Separator self.__AddGridLabel(g1, 'Videos Completed:', bold, 5, 0, -1) self.__AddGridLabel(g1, 'Start Time:', bold, 5, 2, -1) self.__AddGridLabel(g1, 'Videos In Progress:', bold, 6, 0, -1) self.__AddGridLabel(g1, 'Time Remaining:', bold, 7, 2, -1) self.__AddGridLabel(g1, 'Target Space Left:', bold, 7, 0, -1) self.__AddGridLabel(g1, 'Archive Space Left:', bold, 8, 0, -1) self.__AddGridLabel(g1, 'End Time:', bold, 6, 2, -1) self.__AddGridLabel(g1, 'Processing Speed:', bold, 8, 2, -1) g1.addWidget(self.qlVidsDone, 5, 1,) g1.addWidget(self.qlVidsInProgress, 6, 1) g1.addWidget(self.qlStartTime, 5, 3,) g1.addWidget(self.qlEndTime, 6, 3,) g1.addWidget(self.qlTimeLeft, 7, 3,) g1.addWidget(self.qlDestinationSpace, 7, 1,) g1.addWidget(self.qlArcSpace, 8, 1,) g1.addWidget(self.qlProcessingSpeed, 8, 3,) g1.addWidget(self.qpbSourceDir, 0, 4,) g1.addWidget(self.qpbArchiveDir, 1, 4,) g1.addWidget(self.qpbTargetDir, 2, 4,) self.show def GetParameterFileInfo(self): Progress.DeterminePlatform() fm = FileManip() #params = Progress.cliParams.copy() params = fm.ReadSettingsFile() self.qlProcessingSpeed.setText(str(Progress.cliParams['ProcessingSpeedInGBperHour'])) self.qleSourceDir.setText(params['sourceDir']) self.qleArchiveDir.setText(params['archiveDir']) self.qleDestinationDir.setText(params['destinationDir']) def GetDriveSpace(self, path): """ Call the GetDriveSpace() method using an instance of the FileManip class. """ fm = FileManip() return fm.GetDriveSpace(path) def ResetStats(self): """ Change statistical data displays back to their original initialized values. """ Progress.ResetStatuses() self.qlVidsDone.setText( '0') self.qlVidsInProgress.setText('0') self.qlStartTime.setText(datetime.now().strftime("%a, %d %b %Y %H:%M:%S")) self.qlTimeLeft.setText("") if self.qleDestinationDir.text() != "": self.qlDestinationSpace.setText(str(self.GetDriveSpace(self.qleDestinationDir.text()))) if self.qleArchiveDir.text() != "": self.qlArcSpace.setText(str(self.GetDriveSpace(self.qleArchiveDir.text()))) self.qlEndTime.setText("") self.qlProcessingSpeed.setText("") def VerifyRequiredFieldsFilled(self): """ Cancels the RUN functionality and informs the user via Message Box if the required fields are not all completed. """ if self.qleSourceDir.text() == "" or \ self.qleVideoTypes.text() == "" or \ self.qleDestinationDir.text() == "": QMessageBox.critical(self, "Required Field Error", "You have not filled out the three required fields. " "'Source Directory', " "'Target Directory' and " "'Video File Types' " "are all required Fields.", QMessageBox.Ok) return 0 return True def Process(self): """ Batch processing of the source video files begins here. """ result = self.VerifyRequiredFieldsFilled() if result != True: return self.ResetStats() Progress.statuses['ProcessingComplete'] = False self.DisableGuiElements() Params = Progress.cliParams.copy() Params['sourceDir'] = self.qleSourceDir.text() Params['archiveDir'] = self.qleArchiveDir.text() Params['destinationDir'] = self.qleDestinationDir.text() maximumNumVids = "" for idx in range(0, len(self.qleMaxVidsCap.text())): if self.qleMaxVidsCap.text()[idx] != '.': maximumNumVids = maximumNumVids + self.qleMaxVidsCap.text()[idx] if maximumNumVids.isnumeric(): Params['maxNumberOfVideosToProcess'] = '%1.f' % float(self.qleMaxVidsCap.text()) if len(self.qleVideoTypes.text().split(" ")) > 0: extensionList = "" for videoExtension in self.qleVideoTypes.text().split(" "): extensionList += (videoExtension + ",") else: extensionList = None Params['videoTypes'] = extensionList #Create and instance of the processing class pm = ProcessMovies() #Disable applicable GUI elements self.DisableGuiElements #Spawn a thread to run this Thread(target=pm.StartWithGUI, args=(Params,)).start() sleep(1) self.qlTimeLeft.setText(Progress.CalculateTimeRemaining()) Progress.statuses['StatusesHaveChanged'] = True return def __CreateButton(self, folderIcon, txt, pxSize, actionFunction): """ Function to add a button """ if folderIcon != None: folderIcon = QIcon('folder.png') myButton = QPushButton(folderIcon, "") else: myButton = QPushButton(txt) myButton.setMaximumWidth(pxSize) myButton.clicked.connect(actionFunction) return myButton def aboutHelp(self): """ Displays the ABOUT box and sets its content. """ QMessageBox.about(self, "About ManageHD", "Program written in Python v3.4 \n\n" "ManageHD allows you to select an entire " "directory of HD video files and lower their " "resolution from 1080 HD to 720 HD, in batch. " "It calls the HandBrake Command Line Interface " "(CLI) in order to re-encode each video. \n\nYou must " "have the Handbrake CLI installed to use this " "software. " "The CLI (command line interface) can be downloaded at:\n\n " " http://handbrake.fr/downloads2.php \n\n" "The average video file at 720 HD " "is generally one fourth to one sixth the size " "of its 1080 HD source file. \n\n" "Coding was done by InfanteLabz. \n\n" "This sofware is released under GPL v3 " "licensing. \n\n Developed on Wing IDE") def exitFile(self): """ Exits the Main Window, ending the program. """ self.close() def __CreateActions(self): """ Function to create actions for menus """ self.stdAction = QAction(QIcon('convert.png'), 'Create MKV files', self, shortcut = "Ctrl+K", statusTip = "File format set to MKV container", triggered = self.stdConversion, checkable = True) self.altAction = QAction(QIcon('convert.png'), 'Create MP4 files', self, shortcut = "Ctrl+P", statusTip = "File format set to MP4 file", triggered = self.altConversion, checkable = True) self.exitAction = QAction(QIcon('exit.png'), '&Quit', self, shortcut="Ctrl+Q", statusTip = "Exit the Application", triggered=self.exitFile) #self.copyAction = QAction(QIcon('copy.png'), 'C&opy', #self, shortcut="Ctrl+C", #statusTip="Copy", #triggered=self.CopyFunction) self.aboutAction = QAction(QIcon('about.png'), 'A&bout', self, statusTip="Displays info about ManageHD", triggered=self.aboutHelp) def __CreateMenus(self): """ Function to create actual menu bar """ self.fileMenu = self.menuBar().addMenu("&File") self.helpMenu = self.menuBar().addMenu("&Help") def __CenterWindow(self): """ Function to center the window """ qRect = self.frameGeometry() centerPoint = QDesktopWidget().availableGeometry().center() qRect.moveCenter(centerPoint) self.move(qRect.topLeft()) def __SetAboutBox(self): """ Function to position and wire the ABOUT box """ self.aboutButton = QPushButton("About", self) self.aboutButton.move(200, 100) self.aboutButton.clicked.connect(self.ShowAbout) def __SetIcon(self): """ Function to set Icon """ appIcon = QIcon('ManageHD_Icon.png') self.setWindowIcon(appIcon) def DisplayAbnormalTerminationStatus(self, status): # Not Implemented pass def GetArchiveDirectory(self): # Not Implemented pass def stdConversion(self): """ Called by the STANDARD menu item under FILE. Sets ManageHD to perform the standard Handbrake conversion. """ Progress.statuses['HandbrakeOptionsString'] = str(" -i {0} -o {1} -f mkv --width 1280 --crop 0:0:0:0 --decomb -s 1 -N eng -m --large-file --encoder x264 -q 19 -E ffac3") Progress.statuses['OutputExtension'] = 'mkv' self.altAction.setChecked(False) if Progress.runPlatform == "win": self.altAction.setIcon(QIcon('convert.png')) self.stdAction.setIcon(QIcon('checked.jpg')) self.stdAction.setChecked(True) def altConversion(self): """ Called by the ALTERNATE menu item under FILE. Sets ManageHD to perform Handbrake conversions using an alternate series of settings. """ Progress.statuses['HandbrakeOptionsString'] = str(" -i {0} -o {1} -f mp4 --width 1280 --crop 0:0:0:0 --decomb -s 1 -N eng -m --large-file --encoder x264 -q 19 -E ffac3") Progress.statuses['OutputExtension'] = 'mp4' self.stdAction.setChecked(False) if Progress.runPlatform == "win": self.altAction.setIcon(QIcon('checked.jpg')) self.stdAction.setIcon(QIcon('convert.png')) self.altAction.setChecked(True) def CopyFunction(): # Not Implemented pass def ValidateAndRun(self): # Not Implemented pass
class PlotMainWindow(QWidget): """Base class for plot main windows.""" def __init__(self, U, plot, length=1, title=None): super().__init__() layout = QVBoxLayout() if title: title = QLabel('<b>' + title + '</b>') title.setAlignment(Qt.AlignHCenter) layout.addWidget(title) layout.addWidget(plot) plot.set(U, 0) if length > 1: hlayout = QHBoxLayout() self.slider = QSlider(Qt.Horizontal) self.slider.setMinimum(0) self.slider.setMaximum(length - 1) self.slider.setTickPosition(QSlider.TicksBelow) hlayout.addWidget(self.slider) lcd = QLCDNumber(m.ceil(m.log10(length))) lcd.setDecMode() lcd.setSegmentStyle(QLCDNumber.Flat) hlayout.addWidget(lcd) layout.addLayout(hlayout) hlayout = QHBoxLayout() toolbar = QToolBar() self.a_play = QAction( self.style().standardIcon(QStyle.SP_MediaPlay), 'Play', self) self.a_play.setCheckable(True) self.a_rewind = QAction( self.style().standardIcon(QStyle.SP_MediaSeekBackward), 'Rewind', self) self.a_toend = QAction( self.style().standardIcon(QStyle.SP_MediaSeekForward), 'End', self) self.a_step_backward = QAction( self.style().standardIcon(QStyle.SP_MediaSkipBackward), 'Step Back', self) self.a_step_forward = QAction( self.style().standardIcon(QStyle.SP_MediaSkipForward), 'Step', self) self.a_loop = QAction( self.style().standardIcon(QStyle.SP_BrowserReload), 'Loop', self) self.a_loop.setCheckable(True) toolbar.addAction(self.a_play) toolbar.addAction(self.a_rewind) toolbar.addAction(self.a_toend) toolbar.addAction(self.a_step_backward) toolbar.addAction(self.a_step_forward) toolbar.addAction(self.a_loop) if hasattr(self, 'save'): self.a_save = QAction( self.style().standardIcon(QStyle.SP_DialogSaveButton), 'Save', self) toolbar.addAction(self.a_save) self.a_save.triggered.connect(self.save) hlayout.addWidget(toolbar) self.speed = QSlider(Qt.Horizontal) self.speed.setMinimum(0) self.speed.setMaximum(100) hlayout.addWidget(QLabel('Speed:')) hlayout.addWidget(self.speed) layout.addLayout(hlayout) self.timer = QTimer() self.timer.timeout.connect(self.update_solution) self.slider.valueChanged.connect(self.slider_changed) self.slider.valueChanged.connect(lcd.display) self.speed.valueChanged.connect(self.speed_changed) self.a_play.toggled.connect(self.toggle_play) self.a_rewind.triggered.connect(self.rewind) self.a_toend.triggered.connect(self.to_end) self.a_step_forward.triggered.connect(self.step_forward) self.a_step_backward.triggered.connect(self.step_backward) self.speed.setValue(50) elif hasattr(self, 'save'): hlayout = QHBoxLayout() toolbar = QToolBar() self.a_save = QAction( self.style().standardIcon(QStyle.SP_DialogSaveButton), 'Save', self) toolbar.addAction(self.a_save) hlayout.addWidget(toolbar) layout.addLayout(hlayout) self.a_save.triggered.connect(self.save) self.setLayout(layout) self.plot = plot self.U = U self.length = length def slider_changed(self, ind): self.plot.set(self.U, ind) def speed_changed(self, val): self.timer.setInterval(val * 20) def update_solution(self): ind = self.slider.value() + 1 if ind >= self.length: if self.a_loop.isChecked(): ind = 0 else: self.a_play.setChecked(False) return self.slider.setValue(ind) def toggle_play(self, checked): if checked: if self.slider.value() + 1 == self.length: self.slider.setValue(0) self.timer.start() else: self.timer.stop() def rewind(self): self.slider.setValue(0) def to_end(self): self.a_play.setChecked(False) self.slider.setValue(self.length - 1) def step_forward(self): self.a_play.setChecked(False) ind = self.slider.value() + 1 if ind == self.length and self.a_loop.isChecked(): ind = 0 if ind < self.length: self.slider.setValue(ind) def step_backward(self): self.a_play.setChecked(False) ind = self.slider.value() - 1 if ind == -1 and self.a_loop.isChecked(): ind = self.length - 1 if ind >= 0: self.slider.setValue(ind)
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.debug = debug self.progset = QSettings("ADLMIDI-pyGUI", "ADLMIDI-pyGUI") self.about_window = None self.settings_window = None self.paused = False self.MaxRecentFiles = int(self.progset.value("file/MaxRecentFiles", 5)) self.recentList = self.progset.value("file/recent", []) if type(self.recentList) is unicode: self.recentList = [self.recentList] self.banks = [ " 0 = AIL (Star Control 3, Albion, Empire 2, Sensible Soccer, Settlers 2, many others)", "01 = Bisqwit (selection of 4op and 2op)", "02 = HMI (Descent, Asterix)", "03 = HMI (Descent:: Int)", "04 = HMI (Descent:: Ham)", "05 = HMI (Descent:: Rick)", "06 = HMI (Descent 2)", "07 = HMI (Normality)", "08 = HMI (Shattered Steel)", "09 = HMI (Theme Park)", "10 = HMI (3d Table Sports, Battle Arena Toshinden)", "11 = HMI (Aces of the Deep)", "12 = HMI (Earthsiege)", "13 = HMI (Anvil of Dawn)", "14 = DMX (Doom :: partially pseudo 4op)", "15 = DMX (Hexen, Heretic :: partially pseudo 4op)", "16 = DMX (MUS Play :: partially pseudo 4op)", "17 = AIL (Discworld, Grandest Fleet, Pocahontas, Slob Zone 3d, Ultima 4, Zorro)", "18 = AIL (Warcraft 2)", "19 = AIL (Syndicate)", "20 = AIL (Guilty, Orion Conspiracy, Terra Nova Strike Force Centauri :: 4op)", "21 = AIL (Magic Carpet 2)", "22 = AIL (Nemesis)", "23 = AIL (Jagged Alliance)", "24 = AIL (When Two Worlds War :: 4op, MISSING INSTRUMENTS)", "25 = AIL (Bards Tale Construction :: MISSING INSTRUMENTS)", "26 = AIL (Return to Zork)", "27 = AIL (Theme Hospital)", "28 = AIL (National Hockey League PA)", "29 = AIL (Inherit The Earth)", "30 = AIL (Inherit The Earth, file two)", "31 = AIL (Little Big Adventure :: 4op)", "32 = AIL (Wreckin Crew)", "33 = AIL (Death Gate)", "34 = AIL (FIFA International Soccer)", "35 = AIL (Starship Invasion)", "36 = AIL (Super Street Fighter 2 :: 4op)", "37 = AIL (Lords of the Realm :: MISSING INSTRUMENTS)", "38 = AIL (SimFarm, SimHealth :: 4op)", "39 = AIL (SimFarm, Settlers, Serf City)", "40 = AIL (Caesar 2 :: partially 4op, MISSING INSTRUMENTS)", "41 = AIL (Syndicate Wars)", "42 = AIL (Bubble Bobble Feat. Rainbow Islands, Z)", "43 = AIL (Warcraft)", "44 = AIL (Terra Nova Strike Force Centuri :: partially 4op)", "45 = AIL (System Shock :: partially 4op)", "46 = AIL (Advanced Civilization)", "47 = AIL (Battle Chess 4000 :: partially 4op, melodic only)", "48 = AIL (Ultimate Soccer Manager :: partially 4op)", "49 = AIL (Air Bucks, Blue And The Gray, America Invades, Terminator 2029)", "50 = AIL (Ultima Underworld 2)", "51 = AIL (Kasparov's Gambit)", "52 = AIL (High Seas Trader :: MISSING INSTRUMENTS)", "53 = AIL (Master of Magic, Master of Orion 2 :: 4op, std percussion)", "54 = AIL (Master of Magic, Master of Orion 2 :: 4op, orchestral percussion)", "55 = SB (Action Soccer)", "56 = SB (3d Cyberpuck :: melodic only)", "57 = SB (Simon the Sorcerer :: melodic only)", "58 = OP3 (The Fat Man 2op set)", "59 = OP3 (The Fat Man 4op set)", "60 = OP3 (JungleVision 2op set :: melodic only)", "61 = OP3 (Wallace 2op set, Nitemare 3D :: melodic only)", "62 = TMB (Duke Nukem 3D)", "63 = TMB (Shadow Warrior)", "64 = DMX (Raptor)" ] self.openicon = QIcon.fromTheme('document-open', QIcon('img/load.png')) self.saveicon = QIcon.fromTheme('document-save', QIcon('img/save.png')) self.playicon = QIcon.fromTheme('media-playback-start', QIcon('img/play.png')) self.pauseicon = QIcon.fromTheme('media-playback-pause', QIcon('img/pause.png')) self.stopicon = QIcon.fromTheme('media-playback-stop', QIcon('img/stop.png')) self.quiticon = QIcon.fromTheme('application-exit', QIcon('img/quit.png')) self.abouticon = QIcon.fromTheme('help-about', QIcon('img/about.png')) self.setticon = QIcon.fromTheme('preferences-desktop', QIcon('img/settings.png')) self.winsetup() def addWorker(self, worker): worker.message.connect(self.update) worker.finished.connect(self.workerFinished) self.threads.append(worker) def workerFinished(self): pass #barf('MSG', 'Thread completed the task!') def killWorkers(self): pass #for worker in self.threads: # worker.terminate() def winsetup(self): self.setWindowIcon(QIcon('img/note.png')) openFile = QAction(self.openicon, 'Open', self) openFile.setShortcut('Ctrl+O') openFile.triggered.connect(self.load) saveFile = QAction(self.saveicon, 'Save', self) saveFile.setShortcut('Ctrl+S') saveFile.triggered.connect(self.save) playFile = QAction(self.playicon, 'Play', self) playFile.setShortcut('Ctrl+P') playFile.triggered.connect(self.play) pausePlayb = QAction(self.pauseicon, 'Pause', self) pausePlayb.setShortcut('Ctrl+R') pausePlayb.triggered.connect(self.pause) stopPlay = QAction(self.stopicon, 'Stop', self) stopPlay.setShortcut('Ctrl+Z') stopPlay.triggered.connect(self.stop) exitAction = QAction(self.quiticon, 'Quit', self) exitAction.setShortcut('Ctrl+X') exitAction.triggered.connect(self.quit) aboutdlg = QAction(self.abouticon, 'About', self) aboutdlg.setShortcut('Ctrl+A') aboutdlg.triggered.connect(self.about) showSett = QAction(self.setticon, 'Settings', self) showSett.triggered.connect(self.settings) menubar = self.menuBar() fileMenu = menubar.addMenu('&File') configMenu = menubar.addMenu('&Options') configMenu.setStyleSheet("border: 1px solid black;") self.setLooped = QAction('Loop', configMenu, checkable=True) if self.progset.value("sound/Looped") == 'true': self.setLooped.setChecked(True) else: self.setLooped.setChecked(False) self.setLooped.setShortcut('Ctrl+L') self.setAutoplay = QAction('Autoplay', configMenu, checkable=True) if self.progset.value("sound/Autoplay") == 'true': self.setAutoplay.setChecked(True) else: self.setAutoplay.setChecked(False) self.setAutoplay.setShortcut('Ctrl+K') configMenu.addAction(self.setAutoplay) configMenu.addAction(self.setLooped) fileMenu.setStyleSheet("border: 1px solid black;") fileMenu.addAction(openFile) fileMenu.addAction(saveFile) fileMenu.addSeparator() self.recentMenu = fileMenu.addMenu('Recent') self.rfUpdate() fileMenu.addSeparator() fileMenu.addAction(showSett) fileMenu.addSeparator() fileMenu.addAction(exitAction) helpMenu = menubar.addMenu('&Help') helpMenu.setStyleSheet("border: 1px solid black;") helpMenu.addAction(aboutdlg) self.numCards = QSpinBox() numCards_text = QLabel(" OPL : ") self.numCards.setRange(1, 100) self.numCards.setValue(int(self.progset.value("sound/numCards", 3))) self.numCards.valueChanged.connect(self.updateMax4ops) self.fourOps = QSpinBox() fourOps_text = QLabel(" 4op Ch : ") self.fourOps.setRange(0, self.numCards.value()*6) self.fourOps.setValue(int(self.progset.value("sound/fourOps", self.numCards.value()*6))) self.twoOps = QSpinBox() twoOps_text = QLabel(" 2op Ch : ") self.twoOps.setValue((self.numCards.value()*12 - self.fourOps.value())) self.twoOps.setRange(self.twoOps.value(), self.twoOps.value()) toolbar = self.addToolBar('Media') toolbar.addAction(playFile) toolbar.addAction(pausePlayb) toolbar.addAction(stopPlay) toolbar.setMovable(False) toolbar.addSeparator() toolbar.addWidget(numCards_text) toolbar.addWidget(self.numCards) toolbar.addSeparator() toolbar.addWidget(fourOps_text) toolbar.addWidget(self.fourOps) #toolbar.addSeparator() #toolbar.addWidget(twoOps_text) #toolbar.addWidget(self.twoOps) self.statusBar() self.setFixedSize(380, 90) self.center() self.setWindowTitle('ADLMIDI pyGUI') self.show() if self.debug: barf("MSG", "Loaded Main Window", True, False) self.update("ready") self.threads = [] self.addWorker(AdlMidi(1)) self.addWorker(AdlMidiSave(2)) def rfUpdate(self): self.recentMenu.clear() def recentfile(f2l): return lambda: self.load2(f2l) self.recentFileActs = [] recentLength = len(self.recentList) for i in range(self.MaxRecentFiles): try: if i >= recentLength: break rev = (recentLength-1)-i filetoload = self.recentList[rev] filename = path.split(filetoload)[1] self.fileact = QAction(filename, self.recentMenu) self.fileact.triggered.connect(recentfile(filetoload)) self.recentFileActs.append(self.fileact) except Exception: pass for i in range(self.MaxRecentFiles): try: self.recentMenu.addAction(self.recentFileActs[i]) except Exception: pass def get_bank(self): try: selection = self.settings_window.combo.currentText() selection = str(selection[0])+str(selection[1]) return int(selection) except Exception: return 1 def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def about(self): if self.about_window is None: window = QMessageBox(self) self.about_window = window else: window = self.about_window window = self.about_window window.setWindowIcon(QIcon(self.abouticon)) window.setWindowTitle('About ADLMIDI pyGUI') credits = "<center><b>ADLMIDI pyGUI v%s (%s)</b><br>Developed by Tristy H. \"KittyTristy\"<br>[<a href=\"https://github.com/KittyTristy/ADLMIDI-pyGUI\">Website</a>] [<a href=\"mailto:[email protected]\">Email</a>] <br><br><br>" % (__version__, system()) title = "<b>ADLMIDI pyGUI</b> is a GUI wrapper<br>written in Python for use with..<br><br><b>ADLMIDI: MIDI Player<br>for Linux and Windows with OPL3 emulation</b><br>" cw = "(C) -- <a href=\"http://iki.fi/bisqwit/source/adlmidi.html\">http://iki.fi/bisqwit/source/adlmidi.html</a></center>" credits = credits + title + cw window.setText(credits) window.show() window.activateWindow() window.raise_() def settings(self): if self.settings_window is None: window = QDialog(self) self.settings_window = window else: window = self.settings_window window = self.settings_window window.setWindowTitle('Settings') window.notelabel = QLabel("Currently these settings are only guaranteed to work prior to loading the first MIDI!\nYou'll have to restart ADLMIDI pyGui to change them again if they stop working. \n\nSorry! This will be fixed soon!") window.notelabel.setWordWrap(True) window.notelabel.setStyleSheet("font-size: 8pt; border-style: dotted; border-width: 1px; padding: 12px;") window.banklabel = QLabel("<B>Choose Instrument Bank</B>") window.space = QLabel("") window.optlabel = QLabel("<B>Options</B>") window.combo = QComboBox() window.combo.addItems(self.banks) #window.combo.setMaximumWidth(350) window.combo.setMaxVisibleItems(12) window.combo.setStyleSheet("combobox-popup: 0;") window.combo.setCurrentIndex(int(self.progset.value("sound/bank", 1))) window.combo.currentIndexChanged.connect(self.saveSettings) window.perc = QCheckBox("Adlib Percussion Instrument Mode") #window.perc.stateChanged.connect(self.checkOpts) window.tremamp = QCheckBox("Tremolo Amplification Mode") #window.tremamp.stateChanged.connect(self.checkOpts) window.vibamp = QCheckBox("Vibrato Amplification Mode") #window.vibamp.stateChanged.connect(self.checkOpts) window.modscale = QCheckBox("Scaling of Modulator Volume") #window.modscale.stateChanged.connect(self.checkOpts) window.okButton = QPushButton('OK') window.okButton.clicked.connect(window.hide) vbox = QVBoxLayout() vbox.addWidget(window.space) vbox.addWidget(window.banklabel) vbox.addWidget(window.combo) vbox.addWidget(window.space) vbox.addWidget(window.optlabel) vbox.addWidget(window.perc) vbox.addWidget(window.tremamp) vbox.addWidget(window.vibamp) vbox.addWidget(window.modscale) vbox.addWidget(window.notelabel) hbox = QHBoxLayout() hbox.addStretch(1) hbox.addWidget(window.okButton) vbox.addLayout(hbox) window.setLayout(vbox) window.setFixedSize(530, 369) window.show() window.activateWindow() window.raise_() def updateMax4ops(self): self.fourOps.setMaximum(self.numCards.value()*6) self.fourOps.setValue(self.numCards.value()*6) barf("DBG", "Updating Maximum of 4ops Chs to %s" % (self.numCards.value()*6), True, False) #self.twoOps.setValue(self.numCards.value()*12 - self.fourOps.value()) #self.twoOps.setRange(self.twoOps.value(), self.twoOps.value()) def checkOpts(self): global arglist #barf("ACT", "Checking if Options have changed..", True, False) arglist = [] try: if QAbstractButton.isChecked(self.settings_window.perc) and not ('-p' in arglist): arglist.append('-p') elif not QAbstractButton.isChecked(self.settings_window.perc) and ('-p' in arglist): arglist.remove('-p') except Exception: pass try: if QAbstractButton.isChecked(self.settings_window.tremamp) and not ('-t' in arglist): arglist.append('-t') elif not QAbstractButton.isChecked(self.settings_window.tremamp) and ('-t' in arglist): arglist.remove('-t') except Exception: pass try: if QAbstractButton.isChecked(self.settings_window.vibamp) and not ('-v' in arglist): arglist.append('-v') elif not QAbstractButton.isChecked(self.settings_window.vibamp) and ('-v' in arglist): arglist.remove('-v') except Exception: pass try: if QAbstractButton.isChecked(self.settings_window.modscale) and not ('-s' in arglist): arglist.append('-s') elif not QAbstractButton.isChecked(self.settings_window.modscale) and ('-s' in arglist): arglist.remove('-s') except Exception: pass self.sel_bank = self.get_bank() def saveSettings(self): self.progset.setValue("sound/Autoplay", self.setAutoplay.isChecked()) self.progset.setValue("sound/Looped", self.setLooped.isChecked()) self.progset.setValue("sound/numCards", self.numCards.value()) self.progset.setValue("sound/fourOps", self.fourOps.value()) try: self.progset.setValue("sound/bank", self.settings_window.combo.currentIndex()) except Exception: pass if len(self.recentList) >= 1: self.progset.setValue("file/recent", self.recentList[-self.MaxRecentFiles:]) self.progset.setValue("file/MaxRecentFiles", self.MaxRecentFiles) #allkeys = self.progset.allKeys() #for key in allkeys: # barf('DBG', str(key) + " " + str(self.progset.value(key))) def closeEvent(self, event): self.stop() #self.pkill() self.saveSettings() barf("DBG", "Quitting", True, False) def quit(self): self.stop() #self.pkill() self.saveSettings() barf("DBG", "Quitting", True, False) exit(0) def pkill(self): try: p.kill() except Exception: pass ############################################################## ##### Statusbar Functions #################################### ############################################################## def clear(self): try: self.statusBar().removeWidget(self.playStatus) except Exception: pass @Slot(str) def update(self, status=''): self.clear() if status == "ready": text = " <B>Ready</b>" elif status == "play": text = " <B>Now Playing: </B>" + path.split(f.name)[1] elif status == "loop": text = " <B>Looping: </B>" + path.split(f.name)[1] elif status == "stop": text = " <B>Stopped: </B>" + path.split(f.name)[1] elif status == "pause": text = " <B>Paused: </B>" + path.split(f.name)[1] elif status == "loading": text = " <B>Loading.. </B>" elif status == "load": text = " <B>Loaded: </B>" + path.split(f.name)[1] elif status == "saving": text = " <B>Saving.. </B>" elif status == "saved": text = " <B>Saved as: </B>" + "saved/" + path.splitext(path.split(f.name)[1])[0] + ".wav" self.playStatus = QLabel(text) self.statusBar().addPermanentWidget(self.playStatus, 1) ############################################################## ####### Sound Functions ###################################### ############################################################## def play(self): global Paused, arglist if f != None and Paused == False: Paused = False self.stop() self.checkOpts() if not self.setLooped.isChecked(): arglist.append('-nl') arglist.append(str(self.progset.value("sound/bank", 1))) arglist.append(str(self.numCards.value())) arglist.append(str(self.fourOps.value())) for worker in self.threads: if worker.id == 1: worker.start() elif f != None and Paused == True: os.kill(p.pid, signal.SIGCONT) self.update("play") Paused = False def pause(self): global p, Paused if f != None: try: if Paused == False: os.kill(p.pid, signal.SIGSTOP) self.update("pause") Paused = True elif Paused == True: os.kill(p.pid, signal.SIGCONT) self.update("play") Paused = False except Exception: pass def stop(self): global Paused if f != None: Paused = False self.pkill() self.killWorkers() self.update("stop") ############################################################## ##### Load/Save Functions #################################### ############################################################## def load(self): global f lastdir = str(self.progset.value("file/lastdir", "")) fname, _ = QFileDialog.getOpenFileName(None, 'Open File', lastdir, "MIDI Audio File (*.mid *.MID)") if fname != "": f = file(fname, 'r') if not f.name in self.recentList: self.recentList.append(f.name) else: self.recentList.remove(f.name) self.recentList.append(f.name) self.progset.setValue("file/lastdir", path.split(f.name)[0]) self.rfUpdate() self.update("load") self.pkill() if self.debug: barf("SAV", "Loaded %s" % path.split(f.name)[1], True, False) if self.setAutoplay.isChecked(): self.play() else: self.update("load") def load2(self, r_file=None): global f f = file(r_file, 'r') self.recentList.remove(f.name) self.recentList.append(f.name) self.rfUpdate() self.update("load") self.pkill() if self.debug: barf("SAV", "Loaded %s" % path.split(f.name)[1], True, False) if self.setAutoplay.isChecked(): self.play() else: self.update("load") def save(self): if f != None: self.stop() for worker in self.threads: if worker.id == 2: worker.start()