def initialize(self, title, text): """ Initialize QDialog for UserNotesQDialog :param title: title of the QDialog :type title: str :param text: text to edit :type text: str """ self.old_text = text center_widget(self) # Main status_layout main_layout = QVBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, title)) text_title = QLabel(_("Edit your text:")) text_title.setObjectName('subtitle') main_layout.addWidget(text_title) main_layout.setAlignment(text_title, Qt.AlignCenter) main_layout.addWidget(self.get_text_widget())
def initialize(self, title, text): """ Initialize QDialog for UserNotesQDialog :param title: title of the QDialog :type title: str :param text: text to edit :type text: str """ self.old_text = text center_widget(self) # Main status_layout main_layout = QVBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, title)) text_title = QLabel(_("Edit your text:")) text_title.setObjectName('subtitle') main_layout.addWidget(text_title) main_layout.setAlignment(text_title, Qt.AlignCenter) main_layout.addWidget(self.get_text_widget())
def _setup_ui(self): self.setFixedWidth(300) layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.setAlignment(Qt.AlignTop) layout.addWidget(ImageInfo()) layout.addWidget(ProcessList()) self.setLayout(layout)
def initialize_synthesis(self): """ Initialize Synthesis QWidget """ synthesis_layout = QVBoxLayout() synthesis_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(synthesis_layout) # Search widget search_widget = self.get_search_widget() synthesis_layout.addWidget(search_widget) # Host widget self.host_widget.initialize() self.host_widget.setMaximumHeight(self.width() * 0.5) synthesis_layout.addWidget(self.host_widget) # Hint Widget hint_text = _( '<h4>Dahsboard</h4>' '<ul><li>At the top of App, ' 'you have a dashboard that summarizes the number of items per state.</li></ul>' '<h4>Tabs</h4>' '<ul><li><h4>Host Synthesis</h4></li>' 'Tap in the search bar to view a host and its services.' '<li><h4>Problems</h4></li>' 'The "Problems" tab will show you all problems detected in your backend.' '<li><h4>Spy Hosts</h4></li>' 'A "Spy Host" will keep you regularly informed of his condition. ' 'You will also see problems detected for this host, in the "Spy Hosts" panel.</ul>' '<h4>Alignak</h4>' '<ul><li>You can see your backend status and daemons if available, ' 'as well as your profile.</li></ul>' '<h4>Livestate</h4>' '<ul><li>In the livestate, you can see global state of your monitored items.</li></ul>' '<h4>Events</h4>' '<ul><li>Events will show you informative messages your actions inside App.</li></ul>' ) hint_layout = QVBoxLayout(self.hint_widget) hint_label = QLabel(hint_text) hint_label.setObjectName('subtitle') hint_layout.addWidget(hint_label) synthesis_layout.addWidget(self.hint_widget) # Services widget self.services_widget.initialize() synthesis_layout.addWidget(self.services_widget) # Align all widgets to Top synthesis_layout.setAlignment(Qt.AlignTop)
def initialize_synthesis(self): """ Initialize Synthesis QWidget """ synthesis_layout = QVBoxLayout() synthesis_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(synthesis_layout) # Search widget search_widget = self.get_search_widget() synthesis_layout.addWidget(search_widget) # Host widget self.host_widget.initialize() self.host_widget.setMaximumHeight(self.width() * 0.5) synthesis_layout.addWidget(self.host_widget) # Hint Widget hint_text = _( '<h4>Dahsboard</h4>' '<ul><li>At the top of App, ' 'you have a dashboard that summarizes the number of items per state.</li></ul>' '<h4>Tabs</h4>' '<ul><li><h4>Host Synthesis</h4></li>' 'Tap in the search bar to view a host and its services.' '<li><h4>Problems</h4></li>' 'The "Problems" tab will show you all problems detected in your backend.' '<li><h4>Spy Hosts</h4></li>' 'A "Spy Host" will keep you regularly informed of his condition. ' 'You will also see problems detected for this host, in the "Spy Hosts" panel.</ul>' '<h4>Alignak</h4>' '<ul><li>You can see your backend status and daemons if available, ' 'as well as your profile.</li></ul>' '<h4>Livestate</h4>' '<ul><li>In the livestate, you can see global state of your monitored items.</li></ul>' '<h4>Events</h4>' '<ul><li>Events will show you informative messages your actions inside App.</li></ul>' ) hint_layout = QVBoxLayout(self.hint_widget) hint_label = QLabel(hint_text) hint_label.setObjectName('subtitle') hint_layout.addWidget(hint_label) synthesis_layout.addWidget(self.hint_widget) # Services widget self.services_widget.initialize() synthesis_layout.addWidget(self.services_widget) # Align all widgets to Top synthesis_layout.setAlignment(Qt.AlignTop)
def initialize(self): """ Initialize QDialog for PasswordDialog """ center_widget(self) # Main status_layout main_layout = QVBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, _('Edit Password'))) pass_title = QLabel(_("Please type a new PASSWORD:"******"Your password must contain at least 5 characters.")) self.help_label.setWordWrap(True) pass_layout.addWidget(self.help_label) # Accept button accept_btn = QPushButton('Confirm', self) accept_btn.clicked.connect(self.handle_confirm) accept_btn.setObjectName('valid') accept_btn.setMinimumHeight(30) pass_layout.addWidget(accept_btn) main_layout.addWidget(pass_widget)
def initialize(self): """ Initialize the QWidget """ layout = QVBoxLayout(self) layout.setSpacing(0) title_lbl = QLabel('%s - %s' % (__application__, __version__)) title_lbl.setAlignment(Qt.AlignCenter) title_lbl.setObjectName('start') title_lbl.setFixedHeight(30) layout.addWidget(title_lbl) self.progress_bar.setFixedHeight(30) layout.addWidget(self.progress_bar) layout.setAlignment(Qt.AlignCenter)
def get_actions_widget(self): """ Return QWidget with actions buttons :return: widget with buttons :rtype: QWidget """ widget = QWidget() layout = QVBoxLayout() widget.setLayout(layout) action_title = QLabel(_('Actions:')) action_title.setObjectName('title') layout.addWidget(action_title) self.actions_widget.initialize(self.service_item) layout.addWidget(self.actions_widget) layout.setAlignment(Qt.AlignCenter) return widget
def get_message_widget(self, dialog, title, text): """ Return colored message QWidget :param dialog: type of dialog ('text' or 'error') :type dialog: str :param title: title of text to display :type title: str :param text: text to display :type text: str :return: message QWidget :rtype: QWidget """ # Token QWidget token_widget = QWidget() token_widget.setObjectName('dialog') token_layout = QVBoxLayout() token_widget.setLayout(token_layout) token_title = QLabel(title) token_title.setObjectName('itemtitle') token_layout.addWidget(token_title) token_layout.setAlignment(token_title, Qt.AlignCenter) token_label = QLabel(text) token_label.setObjectName(dialog) token_label.setTextInteractionFlags(Qt.TextSelectableByMouse) token_label.setWordWrap(True) token_layout.addWidget(token_label) # Login button accept_btn = QPushButton('OK', self) accept_btn.clicked.connect(self.accept) accept_btn.setObjectName('ok') accept_btn.setMinimumHeight(30) token_layout.addWidget(accept_btn) return token_widget
def get_actions_widget(self): """ Return QWidget with actions buttons :return: widget with buttons :rtype: QWidget """ widget = QWidget() layout = QVBoxLayout() widget.setLayout(layout) action_title = QLabel(_('Actions:')) action_title.setObjectName('title') layout.addWidget(action_title) self.actions_widget.initialize(self.service_item) layout.addWidget(self.actions_widget) layout.setAlignment(Qt.AlignCenter) return widget
def get_message_widget(self, dialog, title, text): """ Return colored message QWidget :param dialog: type of dialog ('text' or 'error') :type dialog: str :param title: title of text to display :type title: str :param text: text to display :type text: str :return: message QWidget :rtype: QWidget """ # Token QWidget token_widget = QWidget() token_widget.setObjectName('dialog') token_layout = QVBoxLayout() token_widget.setLayout(token_layout) token_title = QLabel(title) token_title.setObjectName('itemtitle') token_layout.addWidget(token_title) token_layout.setAlignment(token_title, Qt.AlignCenter) token_label = QLabel(text) token_label.setObjectName(dialog) token_label.setTextInteractionFlags(Qt.TextSelectableByMouse) token_label.setWordWrap(True) token_layout.addWidget(token_label) # Login button accept_btn = QPushButton('OK', self) accept_btn.clicked.connect(self.accept) accept_btn.setObjectName('ok') accept_btn.setMinimumHeight(30) token_layout.addWidget(accept_btn) return token_widget
def get_service_icon_widget(self): """ Return QWidget with its icon and name :return: widget with icon and name :rtype: QWidget """ widget = QWidget() layout = QVBoxLayout() widget.setLayout(layout) # Host Icon layout.addWidget(self.labels['service_icon']) layout.setAlignment(self.labels['service_icon'], Qt.AlignCenter) # Host Name self.labels['service_name'].setObjectName('itemname') self.labels['service_name'].setWordWrap(True) layout.addWidget(self.labels['service_name']) layout.setAlignment(self.labels['service_name'], Qt.AlignCenter) return widget
def get_service_icon_widget(self): """ Return QWidget with its icon and name :return: widget with icon and name :rtype: QWidget """ widget = QWidget() layout = QVBoxLayout() widget.setLayout(layout) # Host Icon layout.addWidget(self.labels['service_icon']) layout.setAlignment(self.labels['service_icon'], Qt.AlignCenter) # Host Name self.labels['service_name'].setObjectName('itemname') self.labels['service_name'].setWordWrap(True) layout.addWidget(self.labels['service_name']) layout.setAlignment(self.labels['service_name'], Qt.AlignCenter) return widget
def get_item_type_widget(self, item_type, problem_nb, total_nb): """ Create and return QWidget with backend data :param item_type: type of item: host, service, problem :type item_type: str :param problem_nb: number of problems for item type :type problem_nb: int :param total_nb: total number of item type :type total_nb: int :return: widget with its data :rtype: QWidget """ layout = QVBoxLayout() widget = QWidget() widget.setLayout(layout) problem_label = QLabel('%d' % problem_nb) problem_label.setObjectName('ok') problem_label.setToolTip( _('Number of unhandled %s problems') % ( item_type if 'problem' not in item_type else '' ) ) layout.addWidget(problem_label) layout.setAlignment(problem_label, Qt.AlignCenter) icon_label = QLabel() icon_label.setFixedSize(64, 64) icon_label.setScaledContents(True) layout.addWidget(icon_label) layout.setAlignment(icon_label, Qt.AlignCenter) total_label = QLabel('%d' % total_nb) total_label.setObjectName('total') total_label.setToolTip( _('Number of monitored %s') % ( item_type if 'problem' not in item_type else 'items' ) ) layout.addWidget(total_label) layout.setAlignment(total_label, Qt.AlignCenter) self.labels[item_type] = { 'problem': problem_label, 'icon': icon_label, 'total': total_label } return widget
def get_host_icon_widget(self): """ Return QWidget with overall icon state and host name :return: widget with host name and icon :rtype: QWidget """ widget = QWidget() layout = QVBoxLayout() widget.setLayout(layout) # Host Icon layout.addWidget(self.labels['host_icon']) layout.setAlignment(self.labels['host_icon'], Qt.AlignCenter) # Host Name self.labels['host_name'].setObjectName('itemname') self.labels['host_name'].setWordWrap(True) layout.addWidget(self.labels['host_name']) layout.setAlignment(self.labels['host_name'], Qt.AlignCenter) # Customs button customs_lbl = QLabel(_('Configuration:')) customs_lbl.setObjectName('subtitle') layout.addWidget(customs_lbl) layout.setAlignment(customs_lbl, Qt.AlignBottom) self.customs_btn.setIcon(QIcon(settings.get_image('settings'))) self.customs_btn.setFixedSize(80, 20) self.customs_btn.clicked.connect(self.show_customs) layout.addWidget(self.customs_btn) layout.setAlignment(self.customs_btn, Qt.AlignCenter) # Initialize Customs QWidget self.customs_widget.initialize() return widget
def get_host_icon_widget(self): """ Return QWidget with overall icon state and host name :return: widget with host name and icon :rtype: QWidget """ widget = QWidget() layout = QVBoxLayout() widget.setLayout(layout) # Host Icon layout.addWidget(self.labels['host_icon']) layout.setAlignment(self.labels['host_icon'], Qt.AlignCenter) # Host Name self.labels['host_name'].setObjectName('itemname') self.labels['host_name'].setWordWrap(True) layout.addWidget(self.labels['host_name']) layout.setAlignment(self.labels['host_name'], Qt.AlignCenter) # Customs button customs_lbl = QLabel(_('Configuration:')) customs_lbl.setObjectName('subtitle') layout.addWidget(customs_lbl) layout.setAlignment(customs_lbl, Qt.AlignBottom) self.customs_btn.setIcon(QIcon(settings.get_image('settings'))) self.customs_btn.setFixedSize(80, 20) self.customs_btn.clicked.connect(self.show_customs) layout.addWidget(self.customs_btn) layout.setAlignment(self.customs_btn, Qt.AlignCenter) # Initialize Customs QWidget self.customs_widget.initialize() return widget
def get_proxy_widget(self): """ Return the proxy QWidget :return: proxy QWidget :rtype: QWidget """ proxy_widget = QWidget() proxy_widget.setObjectName('dialog') proxy_layout = QVBoxLayout(proxy_widget) # Title title_lbl = QLabel(_('Proxy Settings')) title_lbl.setObjectName('itemtitle') proxy_layout.addWidget(title_lbl) proxy_layout.setAlignment(title_lbl, Qt.AlignTop) # Description desc_label = QLabel( _('Here you can define your proxy. Be sure to enter a valid address.') ) desc_label.setWordWrap(True) proxy_layout.addWidget(desc_label) # Proxy Settings proxy_lbl = QLabel(_('Proxy Address with Port')) proxy_layout.addWidget(proxy_lbl) proxy = settings.get_config('Alignak', 'proxy') self.proxy_address.setText(proxy) self.proxy_address.setPlaceholderText(_('proxy adress:port...')) self.proxy_address.setFixedHeight(25) proxy_layout.addWidget(self.proxy_address) # Proxy User proxy_user_lbl = QLabel(_('Proxy User (Optional)')) proxy_layout.addWidget(proxy_user_lbl) proxy_user = settings.get_config('Alignak', 'proxy_user') self.proxy_user.setText(proxy_user) self.proxy_user.setPlaceholderText(_('proxy user...')) self.proxy_user.setFixedHeight(25) proxy_layout.addWidget(self.proxy_user) # Proxy Password proxy_password_lbl = QLabel(_('Proxy Password (Optional)')) proxy_layout.addWidget(proxy_password_lbl) if settings.get_config('Alignak', 'proxy_password'): self.proxy_password.setText(settings.get_config('Alignak', 'proxy_password')) self.proxy_password.setPlaceholderText(_('proxy password...')) self.proxy_password.setFixedHeight(25) self.proxy_password.setEchoMode(QLineEdit.Password) proxy_layout.addWidget(self.proxy_password) # Valid Button valid_btn = QPushButton(_('Valid')) valid_btn.setObjectName('valid') valid_btn.setMinimumHeight(30) valid_btn.clicked.connect(self.accept_proxy) proxy_layout.addWidget(valid_btn) return proxy_widget
class Enlargement(QMdiSubWindow, form_Enlargement.Ui_frmEnlargement): # create "resized" as a signal that the window can emit # we respond to this signal with the form's resizeMe method below resized = pyqtSignal() class MyGraphicsView(QGraphicsView): def __init__(self): QGraphicsView.__init__(self) self.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setDragMode(QGraphicsView.ScrollHandDrag) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.mdiParent = "" def wheelEvent(self, event): adj = 1 + event.angleDelta().y() / 120 * 0.1 self.scale(adj, adj) # we need a keepress event handler here in case the user clicks on the photo. # when user clicks on the photo, the keypress handler is this GraphicsView, not the Englargement class. def keyPressEvent(self, e): # F key is pressed. Re-display the currentEnlargement to fit the screen if e.key() == Qt.Key_F: self.mdiParent.fitEnlargement() # Backspace key is pressed, so show previous image as enlargement if e.key() == Qt.Key_Backspace: self.mdiParent.showPreviousPhoto() # Space bar is pressed, so show next image as enlargement if e.key() == Qt.Key_Space: self.mdiParent.showNextPhoto() # F7 is pressed, so toggle display of cursor if e.key() == Qt.Key_F7: self.mdiParent.toggleHideCursor() # F9 is pressed, so toggle display of camera details if e.key() == Qt.Key_F9: self.mdiParent.toggleCameraDetails() # F11 is pressed, so toggle display of camera details if e.key() == Qt.Key_F11: self.mdiParent.toggleFullScreen() # Esc is pressed, so exit full screen mode, if we're in it if e.key( ) == Qt.Key_Escape and self.mdiParent.mdiParent.mdiParent.statusBar.isVisible( ) is False: self.mdiParent.toggleFullScreen() # 1-5 pressed, so rate the photo if e.key() in [ Qt.Key_0, Qt.Key_1, Qt.Key_2, Qt.Key_3, Qt.Key_4, Qt.Key_5 ]: self.mdiParent.ratePhoto(e.key()) # Right is pressed: show next photo if e.key() == Qt.Key_Right or e.key() == Qt.Key_PageDown: self.mdiParent.showNextPhoto() # Left is pressed: show previous photo if e.key() == Qt.Key_Left or e.key() == Qt.Key_PageUp: self.mdiParent.showPreviousPhoto() def contextMenuEvent(self, event): QApplication.restoreOverrideCursor() menu = QMenu(self) menu.setStyleSheet("color:silver; background-color: #343333;") actionFitToWindow = menu.addAction("Fit to window (F)") menu.addSeparator() actionShowNextPhoto = menu.addAction("Next photo (Right arrow)") actionShowPreviousPhoto = menu.addAction( "Previous photo (Left arrow)") menu.addSeparator() if self.mdiParent.isMaximized() is True: if self.mdiParent.cursorIsVisible: actionToggleHideCursor = menu.addAction("Hide cursor (F7)") else: actionToggleHideCursor = menu.addAction("Show cursor (F7)") if self.mdiParent.detailsPane.isVisible(): actionToggleCameraDetails = menu.addAction("Hide details (F9)") else: actionToggleCameraDetails = menu.addAction("Show details (F9)") if self.mdiParent.isMaximized( ) and self.mdiParent.mdiParent.mdiParent.isFullScreen(): actionToggleFullScreen = menu.addAction( "Exit full screen (F11)") else: actionToggleFullScreen = menu.addAction("Full screen (F11)") menu.addSeparator() actionDetachFile = menu.addAction("Detach photo from Yearbird") menu.addSeparator() actionDeleteFile = menu.addAction("Delete photo from file system") action = menu.exec_(self.mapToGlobal(event.pos())) if self.mdiParent.isMaximized() is True: if action == actionToggleHideCursor: self.parent().toggleHideCursor() if action == actionFitToWindow: self.parent().fitEnlargement() if action == actionShowNextPhoto: self.parent().showNextPhoto() if action == actionShowPreviousPhoto: self.parent().showPreviousPhoto() if action == actionToggleCameraDetails: self.parent().toggleCameraDetails() if action == actionToggleFullScreen: self.parent().toggleFullScreen() if action == actionDeleteFile: self.parent().deleteFile() if action == actionDetachFile: self.parent().detachFile() def __init__(self): super(self.__class__, self).__init__() self.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose, True) self.resized.connect(self.resizeMe) self.mdiParent = "" self.photoList = [] self.currentIndex = 0 self.pixmapEnlargement = QPixmap() self.layout().setDirection(1) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().setSpacing(0) self.setStyleSheet("color:silver; background-color: #343333") self.detailsPaneLayout = QVBoxLayout() self.detailsPaneLayout.setContentsMargins(0, 0, 0, 0) self.detailsPaneLayout.setSpacing(0) self.detailsPaneLayout.setAlignment(Qt.AlignCenter) self.detailsPane = QFrame() self.detailsPane.setLayout(self.detailsPaneLayout) self.detailsPane.setStyleSheet( "color:silver; background-color: #343333") self.layout().addWidget(self.detailsPane) # create label for species common name self.commonName = QLabel() self.commonName.setStyleSheet( "font:12pt; font-weight:bold; color:silver; background-color: #343333; padding: 3px" ) self.detailsPaneLayout.addWidget(self.commonName) # create label for species scientific name self.scientificName = QLabel() self.scientificName.setStyleSheet( "font:12pt; font-style:italic; color:silver; background-color: #343333; padding: 3px" ) self.detailsPaneLayout.addWidget(self.scientificName) # create label for camera details text self.cameraDetails = QLabel() self.cameraDetails.setStyleSheet( "color:silver; background-color: #343333; padding: 3px") self.detailsPane.setVisible(False) self.detailsPaneLayout.addWidget(self.cameraDetails) # create horizontal layout to show rating stars self.horizontalGroupBox = QGroupBox() self.horizontalGroupBox.setContentsMargins(0, 0, 0, 0) self.horizontalGroupBox.setStyleSheet( "background-color: #343333; padding: 3px") self.detailsPaneLayout.addWidget(self.horizontalGroupBox) ratingLayout = QHBoxLayout() ratingLayout.setContentsMargins(0, 0, 0, 0) ratingLayout.setSpacing(0) self.star1 = QPushButton() self.star2 = QPushButton() self.star3 = QPushButton() self.star4 = QPushButton() self.star5 = QPushButton() self.star1.setIconSize(QSize(40, 40)) self.star2.setIconSize(QSize(40, 40)) self.star3.setIconSize(QSize(40, 40)) self.star4.setIconSize(QSize(40, 40)) self.star5.setIconSize(QSize(40, 40)) self.star1.setStyleSheet( "QPushButton:pressed{ background-color: #343333; }") self.star1.setStyleSheet( "QPushButton:hover{ background-color: #343333; }") self.star1.setStyleSheet( "QPushButton:flat{ background-color: #343333; }") self.star1.setStyleSheet( "QPushButton{ background-color: #343333; border:none }") self.star2.setStyleSheet( "QPushButton:pressed{ background-color: #343333; }") self.star2.setStyleSheet( "QPushButton:hover{ background-color: #343333; }") self.star2.setStyleSheet( "QPushButton:flat{ background-color: #343333; }") self.star2.setStyleSheet( "QPushButton{ background-color: #343333; border:none }") self.star3.setStyleSheet( "QPushButton:pressed{ background-color: #343333; }") self.star3.setStyleSheet( "QPushButton:hover{ background-color: #343333; }") self.star3.setStyleSheet( "QPushButton:flat{ background-color: #343333; }") self.star3.setStyleSheet( "QPushButton{ background-color: #343333; border:none }") self.star4.setStyleSheet( "QPushButton:pressed{ background-color: #343333; }") self.star4.setStyleSheet( "QPushButton:hover{ background-color: #343333; }") self.star4.setStyleSheet( "QPushButton:flat{ background-color: #343333; }") self.star4.setStyleSheet( "QPushButton{ background-color: #343333; border:none }") self.star5.setStyleSheet( "QPushButton:pressed{ background-color: #343333; }") self.star5.setStyleSheet( "QPushButton:hover{ background-color: #343333; }") self.star5.setStyleSheet( "QPushButton:flat{ background-color: #343333; }") self.star5.setStyleSheet( "QPushButton{ background-color: #343333; border:none }") self.star1.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star2.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star3.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star4.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star5.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star1.clicked.connect(lambda: self.ratePhoto(Qt.Key_1, "Clicked")) self.star2.clicked.connect(lambda: self.ratePhoto(Qt.Key_2)) self.star3.clicked.connect(lambda: self.ratePhoto(Qt.Key_3)) self.star4.clicked.connect(lambda: self.ratePhoto(Qt.Key_4)) self.star5.clicked.connect(lambda: self.ratePhoto(Qt.Key_5)) ratingLayout.addWidget(self.star1) ratingLayout.addWidget(self.star2) ratingLayout.addWidget(self.star3) ratingLayout.addWidget(self.star4) ratingLayout.addWidget(self.star5) self.horizontalGroupBox.setLayout(ratingLayout) self.cursorIsVisible = True def resizeEvent(self, event): #routine to handle window resize event self.resized.emit() return super(self.__class__, self).resizeEvent(event) def resizeMe(self): QTimer.singleShot(5, self.fitEnlargement) def scaleMe(self): return def keyPressEvent(self, e): # F key is pressed. Re-display the currentEnlargement to fit the screen if e.key() == Qt.Key_F: self.fitEnlargement() # Backspace key is pressed, so show previous image as enlargement if e.key() == Qt.Key_Backspace: self.showPreviousPhoto() # Space bar is pressed, so show next image as enlargement if e.key() == Qt.Key_Space: self.showNextPhoto() # F7 is pressed, so toggle display of cursor if e.key() == Qt.Key_F7: self.toggleHideCursor() # F9 is pressed, so toggle display of camera details if e.key() == Qt.Key_F9: self.toggleCameraDetails() # F11 is pressed, so toggle display of camera details if e.key() == Qt.Key_F11: self.toggleFullScreen() # Esc is pressed, so exit full screen mode, if we're in it if e.key( ) == Qt.Key_Escape and self.mdiParent.mdiParent.statusBar.isVisible( ) is False: self.toggleFullScreen() # 1-5 pressed, so rate the photo if e.key() in [ Qt.Key_0, Qt.Key_1, Qt.Key_2, Qt.Key_3, Qt.Key_4, Qt.Key_5 ]: self.ratePhoto(e.key()) # Right is pressed: show next photo if e.key() == Qt.Key_Right or e.key() == Qt.Key_PageDown: self.showNextPhoto() # Left is pressed: show previous photo if e.key() == Qt.Key_Left or e.key() == Qt.Key_PageUp: self.showPreviousPhoto() def ratePhoto(self, ratingKey, actionType=""): if ratingKey == Qt.Key_0: self.photoList[self.currentIndex][0]["rating"] = "0" if ratingKey == Qt.Key_1: if self.photoList[self.currentIndex][0][ "rating"] == "1" and actionType == "Clicked": self.photoList[self.currentIndex][0]["rating"] = "0" else: self.photoList[self.currentIndex][0]["rating"] = "1" if ratingKey == Qt.Key_2: self.photoList[self.currentIndex][0]["rating"] = "2" if ratingKey == Qt.Key_3: self.photoList[self.currentIndex][0]["rating"] = "3" if ratingKey == Qt.Key_4: self.photoList[self.currentIndex][0]["rating"] = "4" if ratingKey == Qt.Key_5: self.photoList[self.currentIndex][0]["rating"] = "5" self.setCameraDetails() self.detailsPane.setVisible(True) self.mdiParent.mdiParent.db.photosNeedSaving = True self.viewEnlargement.setFocus() def showPreviousPhoto(self): if self.currentIndex > 0: self.currentIndex = self.currentIndex - 1 if self.currentIndex >= 0: self.changeEnlargement() def showNextPhoto(self): if self.currentIndex < len(self.photoList) - 1: self.currentIndex += 1 self.changeEnlargement() def fillEnlargement(self): # routine uses self.currentIndex to fill the right photo self.pixmapEnlargement = QPixmap( self.photoList[self.currentIndex][0]["fileName"]) self.sceneEnlargement = QGraphicsScene() # save the item ID of the pixmap so we can replace the pixmap photo easily later self.itemPixmap = self.sceneEnlargement.addPixmap( self.pixmapEnlargement) self.viewEnlargement = self.MyGraphicsView() self.viewEnlargement.mdiParent = self self.viewEnlargement.setScene(self.sceneEnlargement) self.viewEnlargement.setStyleSheet( "QWidget{ background-color: #343333;}") # add viewEnlargementto the default layout of the form self.layout().addWidget(self.viewEnlargement) self.setCameraDetails() self.setPhotoTitle() QTimer.singleShot(10, self.fitEnlargement) def changeEnlargement(self): self.pixmapEnlargement = QPixmap( self.photoList[self.currentIndex][0]["fileName"]) self.itemPixmap.setPixmap(self.pixmapEnlargement) self.setCameraDetails() self.setPhotoTitle() QTimer.singleShot(20, self.fitEnlargement) def fitEnlargement(self): # scale the view to fit the photo, edge to edge self.viewEnlargement.setSceneRect(0, 0, self.pixmapEnlargement.width(), self.pixmapEnlargement.height()) self.viewEnlargement.fitInView(self.viewEnlargement.sceneRect(), Qt.KeepAspectRatio) def setPhotoTitle(self): # display the file name in the window title bar basename = os.path.basename( self.photoList[self.currentIndex][0]["fileName"]) self.setWindowTitle(basename) def toggleCameraDetails(self): # toggle visibility of cameraDetails if self.detailsPane.isVisible(): self.detailsPane.setVisible(False) else: self.detailsPane.setVisible(True) QTimer.singleShot(10, self.fitEnlargement) def toggleHideCursor(self): # toggle visibility of the cursor # abort if we're not full screen (don't want to confuse user by hiding cursor) if not self.isMaximized(): return () # abort if we're not full screen (don't want to confuse user by hiding cursor) if not self.mdiParent.mdiParent.isFullScreen(): return () if self.cursorIsVisible is True: QApplication.setOverrideCursor(QCursor(Qt.BlankCursor)) self.cursorIsVisible = False else: QApplication.restoreOverrideCursor() self.cursorIsVisible = True def detachFile(self): # remove photo from database, but don't delete it from file system msgText = "Detach \n\n" + self.photoList[ self.currentIndex][0]["fileName"] + "\n\n from Yearbird?" msgText = msgText + "\n\n(File will NOT be deleted from file system)" msg = QMessageBox() msg.setText(msgText) msg.setWindowTitle("Detach photo?") msg.setStandardButtons(QMessageBox.No | QMessageBox.Yes) buttonClicked = msg.exec_() if buttonClicked == QMessageBox.Yes: # remove photo from database currentPhoto = self.photoList[self.currentIndex][0]["fileName"] photoCommonName = self.photoList[ self.currentIndex][1]["commonName"] photoLocation = self.photoList[self.currentIndex][1]["location"] self.mdiParent.mdiParent.db.removePhotoFromDatabase( photoLocation, "", "", photoCommonName, currentPhoto) # remove photo from current window's photo list self.photoList.remove(self.photoList[self.currentIndex]) # refresh display of parent photo list self.mdiParent.FillPhotos(self.mdiParent.filter) # advance display to next photo if len(self.photoList) == 0: self.close() if self.currentIndex < len(self.photoList): self.changeEnlargement() else: self.currentIndex -= 1 self.changeEnlargement() # set flag for requiring photo file save self.mdiParent.mdiParent.db.photosNeedSaving = True def deleteFile(self): # remove photo from database, but don't delete it from file system msgText = "Permanently delete \n\n" + self.photoList[ self.currentIndex][0][ "fileName"] + "\n\n from Yearbird and the file system?" msg = QMessageBox() msg.setText(msgText) msg.setWindowTitle("Permanently delete photo?") msg.setStandardButtons(QMessageBox.No | QMessageBox.Yes) buttonClicked = msg.exec_() if buttonClicked == QMessageBox.Yes: # remove photo from database currentPhoto = self.photoList[self.currentIndex][0]["fileName"] photoCommonName = self.photoList[ self.currentIndex][1]["commonName"] photoLocation = self.photoList[self.currentIndex][1]["location"] self.mdiParent.mdiParent.db.removePhotoFromDatabase( photoLocation, "", "", photoCommonName, currentPhoto) # remove photo from current window's photo list self.photoList.remove(self.photoList[self.currentIndex]) # advance display to next photo if len(self.photoList) == 0: self.close() if self.currentIndex < len(self.photoList): self.changeEnlargement() else: self.currentIndex -= 1 self.changeEnlargement() # set flag for requiring photo file save self.mdiParent.mdiParent.db.photosNeedSaving = True # delete file from file system if os.path.isfile(currentPhoto): try: os.remove(currentPhoto) except: pass # refresh display of parent photo list self.mdiParent.FillPhotos(self.mdiParent.filter) def toggleFullScreen(self): # toggle visibility of filter and menu bar if not self.mdiParent.mdiParent.isFullScreen() is True: self.mdiParent.mdiParent.dckFilter.setVisible(False) self.mdiParent.mdiParent.dckPhotoFilter.setVisible(False) self.mdiParent.mdiParent.menuBar.setVisible(False) self.mdiParent.mdiParent.toolBar.setVisible(False) self.mdiParent.mdiParent.statusBar.setVisible(False) self.setWindowFlags(Qt.FramelessWindowHint) self.mdiParent.mdiParent.showFullScreen() self.showMaximized() else: self.mdiParent.mdiParent.dckFilter.setVisible(True) self.mdiParent.mdiParent.dckPhotoFilter.setVisible(True) self.mdiParent.mdiParent.menuBar.setVisible(True) self.mdiParent.mdiParent.toolBar.setVisible(True) self.mdiParent.mdiParent.statusBar.setVisible(True) self.mdiParent.mdiParent.showNormal() self.mdiParent.mdiParent.showMaximized() self.setWindowFlags(Qt.SubWindow) self.showNormal() QApplication.restoreOverrideCursor() QTimer.singleShot(10, self.fitEnlargement) def setCameraDetails(self): currentPhoto = self.photoList[self.currentIndex][0]["fileName"] photoRating = self.photoList[self.currentIndex][0]["rating"] photoCommonName = self.photoList[self.currentIndex][1]["commonName"] photoScientificName = self.photoList[ self.currentIndex][1]["scientificName"] photoLocation = self.photoList[self.currentIndex][1]["location"] # get EXIF data try: exif_dict = piexif.load(currentPhoto) except: exif_dict = "" # get photo date from EXIF try: photoDateTime = exif_dict["Exif"][ piexif.ExifIFD.DateTimeOriginal].decode("utf-8") #parse EXIF data for date/time components photoExifDate = photoDateTime[0:4] + "-" + photoDateTime[ 5:7] + "-" + photoDateTime[8:10] photoExifTime = photoDateTime[11:13] + ":" + photoDateTime[14:16] photoWeekday = datetime.datetime(int(photoDateTime[0:4]), int(photoDateTime[5:7]), int(photoDateTime[8:10])) photoWeekday = photoWeekday.strftime("%A") + ", " except: photoExifDate = "Date unknown" photoExifTime = "Time unknown" photoWeekday = "" try: photoExifModel = exif_dict["0th"][piexif.ImageIFD.Model].decode( "utf-8") except: photoExifModel = "" try: photoExifLensModel = exif_dict["Exif"][ piexif.ExifIFD.LensModel].decode("utf-8") except: photoExifLensModel = "" try: photoExifExposureTime = exif_dict["Exif"][ piexif.ExifIFD.ExposureTime] photoExifExposureTime = "1/" + str( floor(photoExifExposureTime[1] / photoExifExposureTime[0])) + " sec" except: photoExifExposureTime = "" try: photoExifAperture = exif_dict["Exif"][piexif.ExifIFD.FNumber] photoExifAperture = round( photoExifAperture[0] / photoExifAperture[1], 1) except: photoExifAperture = "" try: photoExifISO = exif_dict["Exif"][piexif.ExifIFD.ISOSpeedRatings] except: photoExifISO = "" try: photoExifFocalLength = exif_dict["Exif"][ piexif.ExifIFD.FocalLength] photoExifFocalLength = floor(photoExifFocalLength[0] / photoExifFocalLength[1]) photoExifFocalLength = str(photoExifFocalLength) + " mm" except: photoExifFocalLength = "" self.commonName.setText(photoCommonName) self.scientificName.setText(photoScientificName) # detailsText = photoCommonName + "\n" # detailsText = photoScientificName + "\n" detailsText = "\n\n" + photoLocation + "\n" detailsText = detailsText + photoWeekday + photoExifDate + "\n" detailsText = detailsText + photoExifTime + "\n" detailsText = detailsText + "\n" detailsText = detailsText + photoExifModel + "\n" detailsText = detailsText + photoExifLensModel + "\n" detailsText = detailsText + "Focal Length: " + str( photoExifFocalLength) + "\n" detailsText = detailsText + str(photoExifExposureTime) + "\n" detailsText = detailsText + "Aperture: " + str( photoExifAperture) + "\n" detailsText = detailsText + "ISO: " + str(photoExifISO) detailsText = detailsText + "\n\n" + ntpath.basename(currentPhoto) detailsText = detailsText + "\n\n\n" #add space to separate rating stars from text if photoRating == "0": self.star1.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) self.star2.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) self.star3.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) self.star4.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) self.star5.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) if photoRating == "1": self.star1.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star2.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) self.star3.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) self.star4.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) self.star5.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) if photoRating == "2": self.star1.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star2.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star3.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) self.star4.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) self.star5.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) if photoRating == "3": self.star1.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star2.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star3.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star4.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) self.star5.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) if photoRating == "4": self.star1.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star2.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star3.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star4.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star5.setIcon(QIcon(QPixmap(":/icon_star_gray.png"))) if photoRating == "5": self.star1.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star2.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star3.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star4.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.star5.setIcon(QIcon(QPixmap(":/icon_star.png"))) self.cameraDetails.setText(detailsText)
def get_settings_widget(self): """ Return the alignak settings QWidget :return: settings QWidget :rtype: QWidget """ server_widget = QWidget() server_widget.setObjectName('dialog') server_layout = QVBoxLayout(server_widget) # Title title_lbl = QLabel(_('Alignak Backend')) title_lbl.setObjectName('itemtitle') server_layout.addWidget(title_lbl) server_layout.setAlignment(title_lbl, Qt.AlignTop) # Description desc_label = QLabel( _('Here you can define alignak settings. Be sure to enter a valid address.' )) desc_label.setWordWrap(True) server_layout.addWidget(desc_label) # Server URL server_lbl = QLabel(_('Server')) server_layout.addWidget(server_lbl) self.server_url.setText(settings.get_config('Alignak', 'url')) self.server_url.setPlaceholderText(_('alignak backend url...')) self.server_url.setFixedHeight(25) server_layout.addWidget(self.server_url) # Server Port port_lbl = QLabel(_('Port')) server_layout.addWidget(port_lbl) cur_port = settings.get_config('Alignak', 'backend').split(':')[2] self.server_port.setText(cur_port) self.server_port.setPlaceholderText(_('alignak backend port...')) self.server_port.setFixedHeight(25) server_layout.addWidget(self.server_port) # Server Processes (displayed only for Unix platforms) if 'win32' not in sys.platform: process_lbl = QLabel(_('Processes')) server_layout.addWidget(process_lbl) cur_proc = settings.get_config('Alignak', 'processes') self.server_proc.setText(cur_proc) self.server_proc.setPlaceholderText( _('alignak backend processes...')) self.server_proc.setFixedHeight(25) server_layout.addWidget(self.server_proc) # Web Service description server_layout.addStretch(1) webservice_lbl = QLabel(_('Web Service')) webservice_lbl.setObjectName('itemtitle') server_layout.addWidget(webservice_lbl) ws_desc_lbl = QLabel( _('Here you can define your alignak web service url, with port if needed' )) ws_desc_lbl.setWordWrap(True) server_layout.addWidget(ws_desc_lbl) # Web Service URL self.webservice_url.setText( settings.get_config('Alignak', 'webservice')) self.webservice_url.setPlaceholderText(_('alignak webservice url...')) self.webservice_url.setFixedHeight(25) server_layout.addWidget(self.webservice_url) # Valid Button valid_btn = QPushButton(_('Valid')) valid_btn.setObjectName('valid') valid_btn.setMinimumHeight(30) valid_btn.clicked.connect(self.accept) server_layout.addWidget(valid_btn) return server_widget
def FillPhotosByFilter(self, filter): # it's tempting to think that we could use the insertPhotoIntoTable routine, # but we can't here, because if we're filling photos by filter, we already know # each photo's meta data. The insertPhotoIntoTable routine tries to guess the # location, time, species, etc. from the photo file's embedded meta data. QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.scaleMe() self.resizeMe() self.fillingCombos = True # save the filter settings passed to this routine to the form itself for future use self.filter = filter photoSightings = self.mdiParent.db.GetSightingsWithPhotos(filter) if len(photoSightings) == 0: return False row = 0 # count photos for message display photoCount = 0 for s in photoSightings: photoCount = photoCount + len(s["photos"]) photoCount = str(photoCount) for s in photoSightings: for p in s["photos"]: self.mdiParent.lblStatusBarMessage.setVisible(True) self.mdiParent.lblStatusBarMessage.setText( "Processing photo " + str(row + 1) + " of " + photoCount) # p is a filename. Use it to add the image to the label as a pixmap buttonPhoto = QPushButton() buttonPhoto.setMinimumHeight(281) buttonPhoto.setMinimumWidth(500) # get thumbnail from file to display pixMap = self.GetPixmapForThumbnail(p["fileName"]) buttonPhoto.setIcon(QIcon(pixMap)) # size to 500x281 buttonPhoto.setIconSize(QSize(500, 281)) buttonPhoto.setStyleSheet( "QPushButton {background-color: #343333; border: 0px}") # display thumbnail to new row in grid self.gridPhotos.addWidget(buttonPhoto, row, 0) # set up layout in second column of row to house combo boxes # give each object a name according to the row so we can access them later container = QWidget() container.setObjectName("container" + str(row)) detailsLayout = QVBoxLayout(container) detailsLayout.setObjectName("layout" + str(row)) detailsLayout.setAlignment(Qt.AlignTop) self.gridPhotos.addWidget(container, row, 1) # create combo boxes for details # add connection for when user changes a combo box cboLocation = QComboBox() cboLocation.currentIndexChanged.connect( partial(self.cboLocationChanged, row)) cboDate = QComboBox() cboDate.currentIndexChanged.connect( partial(self.cboDateChanged, row)) cboTime = QComboBox() cboTime.currentIndexChanged.connect( partial(self.cboTimeChanged, row)) cboCommonName = QComboBox() cboCommonName.currentIndexChanged.connect( partial(self.cboCommonNameChanged, row)) cboRating = QComboBox() cboRating.addItems(["Not Rated", "1", "2", "3", "4", "5"]) cboRating.currentIndexChanged.connect( partial(self.cboRatingChanged, row)) # set stylesheet for cmbo boxes for c in [ cboLocation, cboDate, cboTime, cboCommonName, cboRating ]: self.removeHighlight(c) # fill location combo box with all locations in db locations = self.mdiParent.db.locationList cboLocation.addItems(locations) # set location combo box to the photo's location index = cboLocation.findText(s["location"]) if index >= 0: cboLocation.setCurrentIndex(index) # fill date combo box with all dates associated with selected location filterForThisPhoto = code_Filter.Filter() filterForThisPhoto.setLocationName(s["location"]) filterForThisPhoto.setLocationType("Location") dates = self.mdiParent.db.GetDates(filterForThisPhoto) cboDate.addItems(dates) # set date combo box to the photo's associated date index = cboDate.findText(s["date"]) if index >= 0: cboDate.setCurrentIndex(index) # fill time combo box with all times associated with selected location and date filterForThisPhoto.setStartDate(s["date"]) filterForThisPhoto.setEndDate(s["date"]) startTimes = self.mdiParent.db.GetStartTimes( filterForThisPhoto) cboTime.addItems(startTimes) # set time combo box to the photo's associated checklist time index = cboTime.findText(s["time"]) if index >= 0: cboTime.setCurrentIndex(index) # get common names from checklist associated with photo filterForThisPhoto.setChecklistID(s["checklistID"]) commonNames = self.mdiParent.db.GetSpecies(filterForThisPhoto) cboCommonName.addItem("**Detach Photo**") cboCommonName.addItems(commonNames) # set combo box to common name index = cboCommonName.findText(s["commonName"]) if index >= 0: cboCommonName.setCurrentIndex(index) # set combo box to rating value index = int(p["rating"]) cboRating.setCurrentIndex(index) # assign names to combo boxes for future access cboLocation.setObjectName("cboLocation" + str(row)) cboDate.setObjectName("cboDate" + str(row)) cboTime.setObjectName("cboTime" + str(row)) cboCommonName.setObjectName("cboCommonName" + str(row)) cboRating.setObjectName("cboRating" + str(row)) # add combo boxes to the layout in second column detailsLayout.addWidget(cboLocation) detailsLayout.addWidget(cboDate) detailsLayout.addWidget(cboTime) detailsLayout.addWidget(cboCommonName) detailsLayout.addWidget(cboRating) # create and add resent button btnReset = QPushButton() btnReset.setText("Reset") btnReset.clicked.connect(partial(self.btnResetClicked, row)) detailsLayout.addWidget(btnReset) # save meta data for future use when user clicks cbo boxes thisPhotoMetaData = {} thisPhotoMetaData["photoFileName"] = p["fileName"] thisPhotoMetaData["location"] = s["location"] thisPhotoMetaData["date"] = s["date"] thisPhotoMetaData["time"] = s["time"] thisPhotoMetaData["commonName"] = s["commonName"] thisPhotoMetaData["photoData"] = p thisPhotoMetaData["rating"] = p["rating"] self.metaDataByRow[row] = thisPhotoMetaData # initialize the "new" data so that there are values there, even if they're not really new # user can change the cbo boxes later, which will also change the "new" data self.saveNewMetaData(row) row = row + 1 qApp.processEvents() self.mdiParent.lblStatusBarMessage.setText("") self.mdiParent.lblStatusBarMessage.setVisible(False) QApplication.processEvents() icon = QIcon() icon.addPixmap(QPixmap(":/icon_camera.png"), QIcon.Normal, QIcon.Off) self.setWindowIcon(icon) self.setWindowTitle("Manage Photos") self.fillingCombos = False QApplication.restoreOverrideCursor() # tell MainWindow that we succeeded filling the list return (True)
def insertPhotoIntoTable(self, row, photoData, photoMatchData, pixMap): QApplication.processEvents() self.fillingCombos = True photoLocation = photoMatchData["photoLocation"] photoDate = photoMatchData["photoDate"] photoTime = photoMatchData["photoTime"] photoCommonName = photoMatchData["photoCommonName"] # p is a filename. Use it to add the image to the label as a pixmap buttonPhoto = QPushButton() buttonPhoto.setMinimumHeight(281) buttonPhoto.setMinimumWidth(500) buttonPhoto.setIcon(QIcon(pixMap)) # size to 500x281 buttonPhoto.setIconSize(QSize(500, 281)) buttonPhoto.setStyleSheet( "QPushButton {background-color: #343333; border: 0px}") # display thumbnail to new row in grid self.gridPhotos.addWidget(buttonPhoto, row, 0) # set up layout in second column of row to house combo boxes # give each object a name according to the row so we can access them later container = QWidget() container.setObjectName("container" + str(row)) detailsLayout = QVBoxLayout(container) detailsLayout.setObjectName("layout" + str(row)) detailsLayout.setAlignment(Qt.AlignTop) self.gridPhotos.addWidget(container, row, 1) # create combo boxes for details # add connection for when user changes a combo box cboLocation = QComboBox() cboLocation.currentIndexChanged.connect( partial(self.cboLocationChanged, row)) cboDate = QComboBox() cboDate.currentIndexChanged.connect(partial(self.cboDateChanged, row)) cboTime = QComboBox() cboTime.currentIndexChanged.connect(partial(self.cboTimeChanged, row)) cboCommonName = QComboBox() cboCommonName.currentIndexChanged.connect( partial(self.cboCommonNameChanged, row)) cboRating = QComboBox() cboRating.addItems(["Not Rated", "1", "2", "3", "4", "5"]) cboRating.currentIndexChanged.connect( partial(self.cboRatingChanged, row)) # set stylesheet for cbo boxes for c in [cboLocation, cboDate, cboTime, cboCommonName, cboRating]: self.removeHighlight(c) # fill location combo box with all locations in db locations = self.mdiParent.db.locationList cboLocation.addItems(locations) # set location combo box to the photo's location if photoLocation != "": index = cboLocation.findText(photoLocation) if index >= 0: cboLocation.setCurrentIndex(index) # fill date combo box with all dates associated with selected location filterForThisPhoto = code_Filter.Filter() filterForThisPhoto.setLocationName(photoLocation) filterForThisPhoto.setLocationType("Location") dates = self.mdiParent.db.GetDates(filterForThisPhoto) cboDate.addItems(dates) # set date combo box to the photo's associated date index = cboDate.findText(photoDate) if index >= 0: cboDate.setCurrentIndex(index) # fill time combo box with all times associated with selected location and date filterForThisPhoto.setStartDate(photoDate) filterForThisPhoto.setEndDate(photoDate) startTimes = self.mdiParent.db.GetStartTimes( filterForThisPhoto) cboTime.addItems(startTimes) # set time combo box to the photo's associated checklist time index = cboTime.findText(photoTime) if index >= 0: cboTime.setCurrentIndex(index) # get common names from checklist associated with photo filterForThisPhoto.setTime(photoTime) commonNames = self.mdiParent.db.GetSpecies(filterForThisPhoto) cboCommonName.addItem("**Detach Photo**") cboCommonName.addItems(commonNames) # set combo box to common name index = cboCommonName.findText(photoCommonName) if index >= 0: cboCommonName.setCurrentIndex(index) # assign names to combo boxes for future access cboLocation.setObjectName("cboLocation" + str(row)) cboDate.setObjectName("cboDate" + str(row)) cboTime.setObjectName("cboTime" + str(row)) cboCommonName.setObjectName("cboCommonName" + str(row)) cboRating.setObjectName("cboRating" + str(row)) lblFileName = QLabel() lblFileName.setText("File: " + os.path.basename(photoData["fileName"])) lblFileDate = QLabel() lblFileDate.setText("Date: " + photoData["date"]) lblFileTime = QLabel() lblFileTime.setText("Time: " + photoData["time"]) # add combo boxes to the layout in second column detailsLayout.addWidget(lblFileName) detailsLayout.addWidget(lblFileDate) detailsLayout.addWidget(lblFileTime) detailsLayout.addWidget(cboLocation) detailsLayout.addWidget(cboDate) detailsLayout.addWidget(cboTime) detailsLayout.addWidget(cboCommonName) detailsLayout.addWidget(cboRating) # create and add resent button btnReset = QPushButton() btnReset.setText("Reset") btnReset.clicked.connect(partial(self.btnResetClicked, row)) detailsLayout.addWidget(btnReset) # save meta data for future use when user clicks cbo boxes thisPhotoMetaData = {} thisPhotoMetaData["photoFileName"] = photoData["fileName"] thisPhotoMetaData["location"] = photoLocation thisPhotoMetaData["date"] = photoDate thisPhotoMetaData["time"] = cboTime.currentText() thisPhotoMetaData["commonName"] = photoCommonName thisPhotoMetaData["photoData"] = photoData thisPhotoMetaData["rating"] = thisPhotoMetaData["photoData"]["rating"] self.metaDataByRow[row] = thisPhotoMetaData # initialize the "new" data so that there are values there, even if they're not really new # user can change the cbo boxes later, which will also change the "new" data self.saveNewMetaData(row) self.fillingCombos = False
class LibraryCodesTab(QWidget): def __init__(self, mygui, myguidb, mymainprefs, myparam_dict, myuiexit, mysavedialoggeometry): super(LibraryCodesTab, self).__init__() #----------------------------------------------------- #----------------------------------------------------- self.gui = mygui #----------------------------------------------------- #----------------------------------------------------- self.guidb = myguidb #----------------------------------------------------- #----------------------------------------------------- self.lib_path = self.gui.library_view.model().db.library_path #----------------------------------------------------- #----------------------------------------------------- self.mytabprefs = mymainprefs #----------------------------------------------------- #----------------------------------------------------- self.param_dict = myparam_dict #----------------------------------------------------- #----------------------------------------------------- self.ui_exit = myuiexit #----------------------------------------------------- #----------------------------------------------------- self.save_dialog_geometry = mysavedialoggeometry #----------------------------------------------------- #----------------------------------------------------- font = QFont() font.setBold(False) font.setPointSize(10) #----------------------------------------------------- self.layout_top = QVBoxLayout() self.layout_top.setSpacing(0) self.layout_top.setAlignment(Qt.AlignLeft) self.setLayout(self.layout_top) #----------------------------------------------------- self.scroll_area_frame = QScrollArea() self.scroll_area_frame.setAlignment(Qt.AlignLeft) self.scroll_area_frame.setWidgetResizable(True) self.scroll_area_frame.ensureVisible(400, 400) self.layout_top.addWidget( self.scroll_area_frame ) # the scroll area is now the child of the parent of self.layout_top # NOTE: the self.scroll_area_frame.setWidget(self.scroll_widget) is at the end of the init() AFTER all children have been created and assigned to a layout... #----------------------------------------------------- self.scroll_widget = QWidget() self.layout_top.addWidget( self.scroll_widget ) # causes automatic reparenting of QWidget to the parent of self.layout_top, which is: self . #----------------------------------------------------- self.layout_frame = QVBoxLayout() self.layout_frame.setSpacing(0) self.layout_frame.setAlignment(Qt.AlignLeft) self.scroll_widget.setLayout( self.layout_frame ) # causes automatic reparenting of any widget later added to self.layout_frame to the parent of self.layout_frame, which is: QWidget . #----------------------------------------------------- self.lc_groupbox = QGroupBox('Settings:') self.lc_groupbox.setMaximumWidth(400) self.lc_groupbox.setToolTip( "<p style='white-space:wrap'>The settings that control 'Library Codes'. Using only ISBN or ISSN or Author/Title, Library Codes for selected books will be derived using the Current Settings." ) self.layout_frame.addWidget(self.lc_groupbox) self.lc_layout = QGridLayout() self.lc_groupbox.setLayout(self.lc_layout) #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- self.spacing0 = QLabel() self.layout_frame.addWidget(self.spacing0) self.spacing0.setMaximumHeight(20) #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- self.button_box = QDialogButtonBox() self.button_box.setOrientation(Qt.Horizontal) self.button_box.setCenterButtons(True) self.layout_frame.addWidget(self.button_box) #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- self.push_button_save_only = QPushButton("Save") self.push_button_save_only.clicked.connect(self.save_settings) self.push_button_save_only.setDefault(True) self.push_button_save_only.setFont(font) self.push_button_save_only.setToolTip( "<p style='white-space:wrap'>Save all user settings.") self.button_box.addButton(self.push_button_save_only, 0) self.push_button_exit_only = QPushButton("Exit") self.push_button_exit_only.clicked.connect(self.exit_only) self.push_button_exit_only.setDefault(False) self.push_button_exit_only.setFont(font) self.push_button_exit_only.setToolTip( "<p style='white-space:wrap'>Exit immediately without saving anything." ) self.button_box.addButton(self.push_button_exit_only, 0) #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- r = 4 self.ddc_labelname = QLineEdit(self) self.ddc_labelname.setText(self.mytabprefs['DDC']) self.ddc_labelname.setFont(font) self.ddc_labelname.setToolTip( "<p style='white-space:wrap'>Custom Column Search/Lookup #name for DDC.<br><br>See: https://www.oclc.org/dewey/features/summaries.en.html" ) self.ddc_labelname.setMaximumWidth(100) self.lc_layout.addWidget(self.ddc_labelname, r, 0) self.ddc_activate_checkbox = QCheckBox( "Activate 'Dewey Decimal Code' Classification?") self.ddc_activate_checkbox.setToolTip( "<p style='white-space:wrap'>Do you want to derive DDC?") r = r + 1 self.lc_layout.addWidget(self.ddc_activate_checkbox, r, 0) if prefs['DDC_IS_ACTIVE'] == unicode_type(S_TRUE): self.ddc_activate_checkbox.setChecked(True) else: self.ddc_activate_checkbox.setChecked(False) #----------------------------------------------------- self.spacing1 = QLabel() r = r + 1 self.lc_layout.addWidget(self.spacing1, r, 0) self.spacing1.setMaximumHeight(10) #----------------------------------------------------- self.lcc_labelname = QLineEdit(self) self.lcc_labelname.setText(self.mytabprefs['LCC']) self.lcc_labelname.setFont(font) self.lcc_labelname.setToolTip( "<p style='white-space:wrap'>Custom Column Search/Lookup #name for LCC.<br><br>See: http://www.loc.gov/catdir/cpso/lcco/ " ) self.lcc_labelname.setMaximumWidth(100) r = r + 4 self.lc_layout.addWidget(self.lcc_labelname, r, 0) self.lcc_activate_checkbox = QCheckBox( "Activate 'Library of Congress Code' Classification?") self.lcc_activate_checkbox.setToolTip( "<p style='white-space:wrap'>Do you want to derive LCC?") r = r + 1 self.lc_layout.addWidget(self.lcc_activate_checkbox, r, 0) if prefs['LCC_IS_ACTIVE'] == unicode_type(S_TRUE): self.lcc_activate_checkbox.setChecked(True) else: self.lcc_activate_checkbox.setChecked(False) #----------------------------------------------------- self.spacing2 = QLabel("") r = r + 1 self.lc_layout.addWidget(self.spacing2, r, 0) self.spacing2.setMaximumHeight(10) #----------------------------------------------------- self.fast_labelname = QLineEdit(self) self.fast_labelname.setText(self.mytabprefs['FAST']) self.fast_labelname.setFont(font) self.fast_labelname.setToolTip( "<p style='white-space:wrap'>Custom Column Search/Lookup #name for FAST Tag Values. " ) self.fast_labelname.setMinimumWidth(100) self.fast_labelname.setMaximumWidth(100) r = r + 4 self.lc_layout.addWidget(self.fast_labelname, r, 0) self.fast_activate_checkbox = QCheckBox("Activate 'FAST' Tags?") self.fast_activate_checkbox.setToolTip( "<p style='white-space:wrap'>Do you want to derive FAST Tags?\ <br><br>Text. Behaves like Tags. Not Names.<br><br>" ) r = r + 1 self.lc_layout.addWidget(self.fast_activate_checkbox, r, 0) if prefs['FAST_IS_ACTIVE'] == unicode_type(S_TRUE): self.fast_activate_checkbox.setChecked(True) else: self.fast_activate_checkbox.setChecked(False) #----------------------------------------------------- self.spacing6 = QLabel("") r = r + 1 self.lc_layout.addWidget(self.spacing6, r, 0) self.spacing6.setMaximumHeight(10) #----------------------------------------------------- self.oclc_labelname = QLineEdit(self) self.oclc_labelname.setText(self.mytabprefs['OCLC']) self.oclc_labelname.setFont(font) self.oclc_labelname.setToolTip( "<p style='white-space:wrap'>Custom Column Search/Lookup #name for OCLC-OWI.<br><br>See: #http://classify.oclc.org/classify2/ " ) self.oclc_labelname.setMaximumWidth(100) r = r + 4 self.lc_layout.addWidget(self.oclc_labelname, r, 0) self.oclc_activate_checkbox = QCheckBox( "Activate 'Online Computer Library Center' Work ID Code?") self.oclc_activate_checkbox.setToolTip( "<p style='white-space:wrap'>Do you want to derive OCLC-OWI?") r = r + 1 self.lc_layout.addWidget(self.oclc_activate_checkbox, r, 0) if self.mytabprefs['OCLC_IS_ACTIVE'] == unicode_type(S_TRUE): self.oclc_activate_checkbox.setChecked(True) else: self.oclc_activate_checkbox.setChecked(False) #----------------------------------------------------- self.spacing5 = QLabel("") r = r + 1 self.lc_layout.addWidget(self.spacing5, r, 0) self.spacing5.setMaximumHeight(10) #----------------------------------------------------- self.lc_author_details_labelname = QLineEdit(self) self.lc_author_details_labelname.setText( self.mytabprefs['EXTRA_AUTHOR_DETAILS']) self.lc_author_details_labelname.setFont(font) self.lc_author_details_labelname.setToolTip( "<p style='white-space:wrap'>Custom Column Search/Lookup #name for 'LC Extra Author Details'.\ <br><br>Text. Behaves like Tags. Not Names.<br><br>" ) self.lc_author_details_labelname.setMaximumWidth(100) r = r + 4 self.lc_layout.addWidget(self.lc_author_details_labelname, r, 0) self.lc_author_details_checkbox = QCheckBox( "Activate 'Library Codes Extra Author Details'?") self.lc_author_details_checkbox.setToolTip( "<p style='white-space:wrap'>Do you want to add (never delete or replace) any available Tag-like values to this Custom Column if they are associated with the OCLC-OWI Identifier?" ) r = r + 1 self.lc_layout.addWidget(self.lc_author_details_checkbox, r, 0) if self.mytabprefs['EXTRA_AUTHOR_DETAILS_IS_ACTIVE'] == unicode_type( S_TRUE): self.lc_author_details_checkbox.setChecked(True) else: self.lc_author_details_checkbox.setChecked(False) #----------------------------------------------------- #----------------------------------------------------- self.spacing4 = QLabel() r = r + 1 self.lc_layout.addWidget(self.spacing4, r, 0) self.spacing4.setMaximumHeight(10) #----------------------------------------------------- font.setBold(False) font.setPointSize(7) #----------------------------------------------------- self.push_button_autoadd_custom_columns = QPushButton( "Automatically Add Activated Custom Columns?") self.push_button_autoadd_custom_columns.clicked.connect( self.autoadd_custom_columns) self.push_button_autoadd_custom_columns.setDefault(False) self.push_button_autoadd_custom_columns.setFont(font) self.push_button_autoadd_custom_columns.setToolTip( "<p style='white-space:wrap'>Do you want to automatically add the Custom Columns selected above?<br><br>If you have any issues, please add them manually." ) r = r + 4 self.lc_layout.addWidget(self.push_button_autoadd_custom_columns, r, 0) self.push_button_autoadd_custom_columns.setMaximumWidth(250) #----------------------------------------------------- self.lc_custom_columns_generation_label = QLabel() r = r + 1 self.lc_layout.addWidget(self.lc_custom_columns_generation_label, r, 0) self.lc_custom_columns_generation_label.setText( " ") self.lc_custom_columns_generation_label.setMaximumHeight(10) self.lc_custom_columns_generation_label.setFont(font) self.oclc_identifier_only_checkbox = QCheckBox( "Always Create OCLC-OWI as an 'Identifier' (à la ISBN)?") self.oclc_identifier_only_checkbox.setToolTip( "<p style='white-space:wrap'>Do you want to update Calibre's Identifiers for an Identifier of 'OCLC-OWI',\ regardless of whether you want its own Custom Column updated?\ <br><br>REQUIRED to derive DDC/LCC using Author/Title." ) r = r + 2 self.lc_layout.addWidget(self.oclc_identifier_only_checkbox, r, 0) if prefs['OCLC_IDENTIFIER'] == unicode_type(S_TRUE): self.oclc_identifier_only_checkbox.setChecked(True) else: self.oclc_identifier_only_checkbox.setChecked(False) #----------------------------------------------------- self.spacing3 = QLabel("") r = r + 1 self.lc_layout.addWidget(self.spacing3, r, 0) self.spacing3.setMaximumHeight(10) #----------------------------------------------------- font.setBold(False) font.setPointSize(10) #----------------------------------------------------- self.lc_genre_labelname = QLineEdit(self) self.lc_genre_labelname.setText(self.mytabprefs['GENRE']) self.lc_genre_labelname.setFont(font) self.lc_genre_labelname.setToolTip( "<p style='white-space:wrap'>Custom Column Search/Lookup #name for 'Genre'.\ <br><br>Text. Behaves like Tags.<br><br>" ) self.lc_genre_labelname.setMaximumWidth(100) r = r + 1 self.lc_layout.addWidget(self.lc_genre_labelname, r, 0) self.lc_checkbox_buttongroup = QButtonGroup() self.lc_checkbox_buttongroup.setExclusive(True) self.lc_genre_ddc_checkbox = QCheckBox( "Update 'Genre' using DDC-to-Genre Mappings?") self.lc_genre_ddc_checkbox.setToolTip( "<p style='white-space:wrap'>Do you want LC to update 'Genre' using the DDC-to-Genre mapping in Table _lc_genre_mapping?" ) r = r + 1 self.lc_layout.addWidget(self.lc_genre_ddc_checkbox, r, 0) self.lc_genre_lcc_checkbox = QCheckBox( "Update 'Genre' using LCC-to-Genre Mappings?") self.lc_genre_lcc_checkbox.setToolTip( "<p style='white-space:wrap'>Do you want LC to update 'Genre' using the LCC-to-Genre mapping in Table _lc_genre_mapping?" ) r = r + 1 self.lc_layout.addWidget(self.lc_genre_lcc_checkbox, r, 0) self.lc_genre_inactive_checkbox = QCheckBox( "Do not update 'Genre' at all") self.lc_genre_inactive_checkbox.setToolTip( "<p style='white-space:wrap'>Do no 'Genre' processing at all?") r = r + 1 self.lc_layout.addWidget(self.lc_genre_inactive_checkbox, r, 0) self.lc_checkbox_buttongroup.addButton(self.lc_genre_ddc_checkbox) self.lc_checkbox_buttongroup.addButton(self.lc_genre_lcc_checkbox) self.lc_checkbox_buttongroup.addButton(self.lc_genre_inactive_checkbox) if self.mytabprefs['GENRE_DDC_IS_ACTIVE'] == unicode_type(S_TRUE): self.lc_genre_ddc_checkbox.setChecked(True) elif self.mytabprefs['GENRE_LCC_IS_ACTIVE'] == unicode_type(S_TRUE): self.lc_genre_lcc_checkbox.setChecked(True) elif self.mytabprefs['GENRE_IS_INACTIVE'] == unicode_type(S_TRUE): self.lc_genre_inactive_checkbox.setChecked(True) self.lc_exact_match_checkbox = QCheckBox( "DDC: Require an 'Exact Match', not a 'Best Match'?") self.lc_exact_match_checkbox.setToolTip( "<p style='white-space:wrap'>Check this checkbox if you want an exact DDC match to be required in Table _lc_genre_mapping. Otherwise, a 'best match' will be used via progressive shortening from right to left, but not past any decimal point. If there is no decimal point in a book's DDC, then no progressive shortening will be performed at all." ) r = r + 1 self.lc_layout.addWidget(self.lc_exact_match_checkbox, r, 0) if self.mytabprefs['GENRE_EXACT_MATCH'] == unicode_type(S_TRUE): self.lc_exact_match_checkbox.setChecked(True) self.spin_lcc = QSpinBox(self) self.spin_lcc.setMinimum(1) self.spin_lcc.setMaximum(50) self.spin_lcc.setProperty('value', prefs['GENRE_LCC_MATCH_LENGTH']) self.spin_lcc.setMaximumWidth(250) self.spin_lcc.setSuffix(" LCC: Maximum Length to Match") self.spin_lcc.setToolTip( "<p style='white-space:nowrap'>Maximum number of characters in the LCC that should be used to map to the 'Genre', starting from the left. A maximum of 1 guarantees a (broad) match.\ <br><br>LCCs are structured with either 1 or 2 beginning letters, so 2-character LCCs have special matching logic.\ <br><br>Example: Assume maximum = 2 for a LCC of 'Q1': Q1 would be attempted. If it failed, because the 2nd digit is a number, 'Q' would be attempted.\ <br><br>Example: Assume maximum = 2 for a LCC of 'PN1969.C65': PN would be attempted. If it failed, nothing else would be attempted.\ <br><br>Example: Assume maximum = 4 for a LCC of 'PN1969.C65': PN19 would be attempted. If it failed, nothing else would be attempted.\ <br><br>Example: Assume maximum = 4 for a LCC of 'Q1': Q1 would be attempted. If it failed, because the 2nd digit is a number, 'Q' would be attempted.\ <br><br>Example: Assume maximum = 4 for a LCC of 'Q389': Q389 would be attempted. If it failed, nothing else would be attempted." ) r = r + 2 self.lc_layout.addWidget(self.spin_lcc, r, 0) #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- self.scroll_widget.resize(self.sizeHint()) #----------------------------------------------------- #----------------------------------------------------- self.scroll_area_frame.setWidget( self.scroll_widget ) # now that all widgets have been created and assigned to a layout... #----------------------------------------------------- #----------------------------------------------------- self.scroll_area_frame.resize(self.sizeHint()) #----------------------------------------------------- #----------------------------------------------------- self.resize(self.sizeHint()) #----------------------------------------------------------------------------------------- def validate(self): return True #----------------------------------------------------------------------------------------- def autoadd_custom_columns(self): number_active = self.save_settings() if number_active == 0: return error_dialog( self.gui, _('Automatically Add Custom Columns'), _('No Activated Library Codes Custom Columns Found. Nothing to Add.' ), show=True) self.cli_param_list = self.create_cli_parameters() is_valid, restart_required = self.create_new_lc_custom_columns( self.cli_param_list) if is_valid: if restart_required: self.lc_custom_columns_generation_label.setText( "Addition of Custom Columns Complete. Restart Calibre Now." ) self.repaint() info_dialog( self.gui, 'Automatically Add Custom Columns', 'All Selected Custom Customs Were Added If They Did Not Already Exist. Please Restart Calibre now.' ).show() else: self.lc_custom_columns_generation_label.setText( "Selected Custom Columns Already Exist. Nothing Done.") self.repaint() else: self.lc_custom_columns_generation_label.setText( "Not Completed. Please Restart Calibre, then Add Manually.") self.repaint() msg = "Fatal error experienced in adding new Custom Columns." error_dialog(self.gui, _('Automatically Add Custom Columns'), _(msg), show=True) #----------------------------------------------------------------------------------------- def create_cli_parameters(self): try: del self.cli_param_list except: pass self.cli_param_list = [] temp_list = [] cc_taglike_list = [] cc_fast_name = "" if self.mytabprefs['DDC_IS_ACTIVE'] == unicode_type(S_TRUE): cc = self.mytabprefs['DDC'] if cc > '#': cc = cc.replace('#', "").strip() cc = unicode_type(cc) temp_list.append(cc) else: error_dialog(self.gui, _('Automatically Add Custom Columns'), _('Illogical DDC Settings. Please Correct.'), show=True) return self.cli_param_list if self.mytabprefs['LCC_IS_ACTIVE'] == unicode_type(S_TRUE): cc = self.mytabprefs['LCC'] if cc > '#': cc = cc.replace('#', "").strip() cc = unicode_type(cc) temp_list.append(cc) else: error_dialog(self.gui, _('Automatically Add Custom Columns'), _('Illogical LCC Settings. Please Correct.'), show=True) return self.cli_param_list if self.mytabprefs['FAST_IS_ACTIVE'] == unicode_type(S_TRUE): cc = self.mytabprefs['FAST'] if cc > '#': cc = cc.replace('#', "").strip() cc = unicode_type(cc) temp_list.append(cc) cc_taglike_list.append(cc) cc_fast_name = cc else: error_dialog(self.gui, _('Automatically Add Custom Columns'), _('Illogical FAST Settings. Please Correct.'), show=True) return self.cli_param_list if self.mytabprefs['OCLC_IS_ACTIVE'] == unicode_type(S_TRUE): cc = self.mytabprefs['OCLC'] if cc > '#': cc = cc.replace('#', "").strip() cc = unicode_type(cc) temp_list.append(cc) else: error_dialog(self.gui, _('Automatically Add Custom Columns'), _('Illogical OCLC Settings. Please Correct.'), show=True) return self.cli_param_list if self.mytabprefs['EXTRA_AUTHOR_DETAILS_IS_ACTIVE'] == unicode_type( S_TRUE): cc = self.mytabprefs['EXTRA_AUTHOR_DETAILS'] if cc > '#': cc = cc.replace('#', "").strip() cc = unicode_type(cc) temp_list.append(cc) cc_taglike_list.append(cc) else: error_dialog( self.gui, _('Automatically Add Custom Columns'), _('Illogical LC Extra Author Details Settings. Please Correct.' ), show=True) return self.cli_param_list else: pass if len(temp_list) == 0: del temp_list error_dialog(self.gui, _('Automatically Add Custom Columns'), _('Nothing to do. Please Review Settings.'), show=True) return self.cli_param_list cc_to_add_list = [] # for each cc currently set to active, create a parameter...but only if the cc does NOT already exist... my_db, my_cursor, is_valid = self.apsw_connect_to_library() if not is_valid: error_dialog(self.gui, _('Automatically Add Custom Columns'), _('Database Connection Error. Restart Calibre.'), show=True) return self.lc_custom_columns_generation_label.setText( "...Adding Custom Columns...") self.repaint() mysql = "SELECT label,name FROM custom_columns" my_cursor.execute(mysql) tmp_rows = my_cursor.fetchall() if not tmp_rows: for cc in temp_list: cc_to_add_list.append(cc) #END FOR else: if len(tmp_rows) == 0: for cc in temp_list: cc_to_add_list.append(cc) #END FOR else: for cc in temp_list: label_already_exists = False for row in tmp_rows: label, name = row if unicode_type(label) == unicode_type(cc): label_already_exists = True break else: continue #END FOR if not label_already_exists: cc_to_add_list.append(cc) #END FOR del tmp_rows del temp_list if len(cc_to_add_list) == 0: return self.cli_param_list cc_to_add_list.sort() for label in cc_to_add_list: label = unicodedata.normalize('NFKD', label).encode('ascii', 'ignore') label = unicode_type(label) label = label.lower() name = label.upper() datatype = 'text' if label in cc_taglike_list: is_multiple = "--is-multiple" if label == cc_fast_name: name = "FAST Tags" else: name = '"LC Extra Author Details"' param = is_multiple + '|||' + label + '|||' + name + '|||' + datatype else: param = label + '|||' + name + '|||' + datatype param = param.replace("[LIBRARY]", self.lib_path) self.cli_param_list.append(param) #END FOR del cc_to_add_list return self.cli_param_list #----------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------- def apsw_connect_to_library(self): my_db = self.gui.library_view.model().db self.lib_path = my_db.library_path self.lib_path = self.lib_path.replace(os.sep, '/') if isbytestring(self.lib_path): self.lib_path = self.lib_path.decode(filesystem_encoding) path = my_db.library_path if isbytestring(path): path = path.decode(filesystem_encoding) path = path.replace(os.sep, '/') path = os.path.join(path, 'metadata.db') path = path.replace(os.sep, '/') if isbytestring(path): path = path.decode(filesystem_encoding) if path.endswith("/"): path = path[0:-1] if path.count("metadata.db") == 0: path = path + "/metadata.db" try: my_db = apsw.Connection(path) is_valid = True except Exception as e: if DEBUG: print("path to metadata.db is: ", path) if DEBUG: print("error: ", as_unicode(e)) is_valid = False return None, None, is_valid my_cursor = my_db.cursor() mysql = "PRAGMA main.busy_timeout = 5000;" #PRAGMA busy_timeout = milliseconds; my_cursor.execute(mysql) return my_db, my_cursor, is_valid #----------------------------------------------------------------------------------------- def exit_only(self): self.save_dialog_geometry() # inherited from SizePersistedDialog self.ui_exit() #----------------------------------------------------------------------------------------- def save_settings(self): self.save_dialog_geometry() # inherited from SizePersistedDialog self.mytabprefs['DDC'] = self.ddc_labelname.text() self.mytabprefs['LCC'] = self.lcc_labelname.text() self.mytabprefs['FAST'] = self.fast_labelname.text() self.mytabprefs['OCLC'] = self.oclc_labelname.text() self.mytabprefs['DDC_IS_ACTIVE'] = unicode_type( self.ddc_activate_checkbox.isChecked()) self.mytabprefs['LCC_IS_ACTIVE'] = unicode_type( self.lcc_activate_checkbox.isChecked()) self.mytabprefs['FAST_IS_ACTIVE'] = unicode_type( self.fast_activate_checkbox.isChecked()) self.mytabprefs['OCLC_IS_ACTIVE'] = unicode_type( self.oclc_activate_checkbox.isChecked()) self.mytabprefs['OCLC_IDENTIFIER'] = unicode_type( self.oclc_identifier_only_checkbox.isChecked()) label = self.mytabprefs['DDC'] label = unicode_type(label) label = unicodedata.normalize('NFKD', label).encode('ascii', 'ignore') label = label.lower().strip() if not label.startswith("#"): label = "#" + label if label == "#": label = "" self.ddc_activate_checkbox.setChecked(False) self.mytabprefs['DDC'] = unicode_type(label) label = self.mytabprefs['LCC'] label = unicode_type(label) label = unicodedata.normalize('NFKD', label).encode('ascii', 'ignore') label = label.lower().strip() if not label.startswith("#"): label = "#" + label if label == "#": label = "" self.lcc_activate_checkbox.setChecked(False) self.mytabprefs['LCC'] = unicode_type(label) label = self.mytabprefs['FAST'] label = unicode_type(label) label = unicodedata.normalize('NFKD', label).encode('ascii', 'ignore') label = label.lower().strip() if not label.startswith("#"): label = "#" + label if label == "#": label = "" self.fast_activate_checkbox.setChecked(False) self.mytabprefs['FAST'] = unicode_type(label) label = self.mytabprefs['OCLC'] label = unicode_type(label) label = unicodedata.normalize('NFKD', label).encode('ascii', 'ignore') label = label.lower().strip() if not label.startswith("#"): label = "#" + label if label == "#": label = "" self.oclc_activate_checkbox.setChecked(False) self.mytabprefs['OCLC'] = unicode_type(label) if self.mytabprefs['DDC'] == unicode_type( "") and self.mytabprefs['LCC'] == unicode_type( "") and self.mytabprefs['FAST'] == unicode_type( "") and self.mytabprefs['OCLC'] == unicode_type(""): self.mytabprefs['DDC'] = unicode_type("#ddc") self.mytabprefs['LCC'] = unicode_type("#lcc") self.mytabprefs['FAST'] = unicode_type("#fast") self.mytabprefs['OCLC'] = unicode_type("#oclc_owi") else: if self.mytabprefs['DDC'] == unicode_type( "") and self.mytabprefs['LCC'] == unicode_type(""): self.oclc_identifier_only_checkbox.setChecked(False) #--------------------------------------- s = unicode_type(self.lc_genre_labelname.text()) s = s.strip() if s.startswith("#") and len(s) > 1: self.mytabprefs['GENRE'] = unicode_type(s) self.mytabprefs['GENRE_DDC_IS_ACTIVE'] = unicode_type( self.lc_genre_ddc_checkbox.isChecked()) self.mytabprefs['GENRE_LCC_IS_ACTIVE'] = unicode_type( self.lc_genre_lcc_checkbox.isChecked()) self.mytabprefs['GENRE_IS_INACTIVE'] = unicode_type( self.lc_genre_inactive_checkbox.isChecked()) self.mytabprefs['GENRE_EXACT_MATCH'] = unicode_type( self.lc_exact_match_checkbox.isChecked()) self.mytabprefs['GENRE_LCC_MATCH_LENGTH'] = self.spin_lcc.value() else: self.mytabprefs['GENRE'] = unicode_type("#genre") self.lc_genre_labelname.setText(unicode_type("#genre")) self.lc_genre_ddc_checkbox.setChecked(False) self.lc_genre_lcc_checkbox.setChecked(False) self.lc_genre_inactive_checkbox.setChecked(True) self.mytabprefs['GENRE_DDC_IS_ACTIVE'] = unicode_type(S_FALSE) self.mytabprefs['GENRE_LCC_IS_ACTIVE'] = unicode_type(S_FALSE) self.mytabprefs['GENRE_IS_INACTIVE'] = unicode_type(S_TRUE) self.mytabprefs['GENRE_EXACT_MATCH'] = unicode_type(S_TRUE) self.mytabprefs['GENRE_LCC_MATCH_LENGTH'] = 2 self.repaint() sleep(2) #--------------------------------------- #~ for k,v in self.mytabprefs.iteritems(): for k, v in iteritems(self.mytabprefs): v = unicode_type(v) v = v.strip() prefs[k] = v #END FOR prefs #--------------------------------------- self.ddc_labelname.setText(self.mytabprefs['DDC']) self.lcc_labelname.setText(self.mytabprefs['LCC']) self.fast_labelname.setText(self.mytabprefs['FAST']) self.oclc_labelname.setText(self.mytabprefs['OCLC']) self.repaint() sleep(0) #~ for k,v in self.mytabprefs.iteritems(): for k, v in iteritems(self.mytabprefs): self.param_dict[k] = v #END FOR number_active = 0 if self.mytabprefs['DDC_IS_ACTIVE'] == unicode_type(S_TRUE): number_active = number_active + 1 if self.mytabprefs['LCC_IS_ACTIVE'] == unicode_type(S_TRUE): number_active = number_active + 1 if self.mytabprefs['FAST_IS_ACTIVE'] == unicode_type(S_TRUE): number_active = number_active + 1 if self.mytabprefs['OCLC_IS_ACTIVE'] == unicode_type(S_TRUE): number_active = number_active + 1 self.ddc_name = self.mytabprefs['DDC'].replace("#", "").strip() self.lcc_name = self.mytabprefs['LCC'].replace("#", "").strip() self.fast_name = self.mytabprefs['FAST'].replace("#", "").strip() self.oclc_name = self.mytabprefs['OCLC'].replace("#", "").strip() if self.oclc_identifier_only_checkbox.isChecked(): self.oclc_identifier_is_desired = True else: self.oclc_identifier_is_desired = False return number_active #----------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------- def create_new_lc_custom_columns(self, execution_param_list): if len(self.cli_param_list) == 0: return True, False # successful since the labels already exist; no restart is required. dbpath = self.lib_path was_successful = True restart_required = True for param in execution_param_list: try: lc_cli_add_custom_column(self.guidb, param, dbpath) except Exception as e: if DEBUG: print("Exception: ", as_unicode(e)) was_successful = False break #END FOR return was_successful, restart_required #----------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------- #END of library_codes_dialog.py
class ConfigWidget(QWidget): def __init__(self): QWidget.__init__(self) self.main_layout = QVBoxLayout() self.l = QFormLayout() self.l2 = QHBoxLayout() self.l3 = QHBoxLayout() self.group_box = QGroupBox('Ustawienia ogólne') self.group_box2 = QGroupBox('Pobieraj metadane') self.group_box3 = QGroupBox( 'Pobieraj dodatkowe metadane i dołącz je do komentarza') # general settings self.max_results_label = QLabel('Maksymalna liczba wyników') self.max_results_label.setToolTip( 'Maksymalna liczba pobieranych metadanych. Dla książek o nieunikalnych tytułach \ pierwszy wynik może być niepoprawny') self.max_results = QLineEdit(self) self.max_results.setValidator(QIntValidator()) self.max_results.setText(str(PREFS['max_results'])) self.max_results_label.setBuddy(self.max_results) self.l.addRow(self.max_results_label, self.max_results) self.authors_search_label = QLabel('Używaj autorów do wyszukiwań') self.authors_search_label.setToolTip( 'Wyszukuj uwzględniając autorów. Może poprawić trafność wyników, ale błędni autorzy spowodują brak wyników' ) self.authors_search = QCheckBox() self.authors_search.setChecked(PREFS['authors_search']) self.authors_search_label.setBuddy(self.authors_search) self.l.addRow(self.authors_search_label, self.authors_search) self.only_first_author_label = QLabel( 'Używaj tylko pierwszego autora do wyszukiwania') self.only_first_author_label.setToolTip( 'Używaj tylko pierwszego autora do wyszukiwań, obowiązuje tylko gdy wyszukiwanie z autorami jest aktywowane' ) self.only_first_author = QCheckBox() self.only_first_author.setChecked(PREFS['only_first_author']) self.only_first_author_label.setBuddy(self.only_first_author) self.l.addRow(self.only_first_author_label, self.only_first_author) self.covers_label = QLabel('Pobieraj okładki') self.covers = QCheckBox() self.covers.setChecked(PREFS['covers']) self.covers_label.setBuddy(self.covers) self.l.addRow(self.covers_label, self.covers) self.max_covers_label = QLabel('Maksymalna liczba okładek') self.max_covers_label.setToolTip( 'Maksymalna liczba pobieranych okładek') self.max_covers = QLineEdit(self) self.max_covers.setValidator(QIntValidator()) self.max_covers.setText(str(PREFS['max_covers'])) self.max_covers_label.setBuddy(self.max_covers) self.l.addRow(self.max_covers_label, self.max_covers) self.threads_label = QLabel('Wielowątkowe przetwarzanie') self.threads_label.setToolTip( 'Przyśpiesza pracę używając wielu wątków') self.threads = QCheckBox() self.threads.setChecked(PREFS['threads']) self.threads_label.setBuddy(self.threads) self.l.addRow(self.threads_label, self.threads) self.max_threads_label = QLabel('Maksymalna liczba wątków') self.max_threads = QLineEdit(self) self.max_threads.setValidator(QIntValidator()) self.max_threads.setText(str(PREFS['max_threads'])) self.max_threads_label.setBuddy(self.max_threads) self.l.addRow(self.max_threads_label, self.max_threads) self.thread_delay_label = QLabel('Opóźnienie wątku') self.thread_delay_label.setToolTip( 'Czas oczekiwania na uruchomienie kolejnego wątku') self.thread_delay = QLineEdit(self) self.thread_delay.setValidator(QDoubleValidator()) self.thread_delay.setText(str(PREFS['thread_delay'])) self.thread_delay_label.setBuddy(self.thread_delay) self.l.addRow(self.thread_delay_label, self.thread_delay) # metadata settings if 'title' in PREFS.defaults: self.title = QCheckBox('Tytuł') self.title.setChecked(PREFS['title']) self.l2.addWidget(self.title) if 'authors' in PREFS.defaults: self.authors = QCheckBox('Autorzy') self.authors.setChecked(PREFS['authors']) self.l2.addWidget(self.authors) if 'pubdate' in PREFS.defaults: self.pubdate = QCheckBox('Data wydania') self.pubdate.setChecked(PREFS['pubdate']) self.l2.addWidget(self.pubdate) if 'publisher' in PREFS.defaults: self.publisher = QCheckBox('Wydawca') self.publisher.setChecked(PREFS['publisher']) self.l2.addWidget(self.publisher) if 'isbn' in PREFS.defaults: self.isbn = QCheckBox('ISBN') self.isbn.setChecked(PREFS['isbn']) self.l2.addWidget(self.isbn) if 'comments' in PREFS.defaults: self.comments = QCheckBox('Opis') self.comments.setChecked(PREFS['comments']) self.l2.addWidget(self.comments) if 'languages' in PREFS.defaults: self.languages = QCheckBox('Języki') self.languages.setChecked(PREFS['languages']) self.l2.addWidget(self.languages) if 'rating' in PREFS.defaults: self.rating = QCheckBox('Ocena') self.rating.setChecked(PREFS['rating']) self.l2.addWidget(self.rating) if 'tags' in PREFS.defaults: self.tags = QCheckBox('Etykiety (tagi)') self.tags.setChecked(PREFS['tags']) self.l2.addWidget(self.tags) if 'series' in PREFS.defaults: self.series = QCheckBox('Cykle') self.series.setChecked(PREFS['series']) self.l2.addWidget(self.series) if 'identifier' in PREFS.defaults: self.identifier = QCheckBox('Identyfikator') self.identifier.setChecked(PREFS['identifier']) self.l2.addWidget(self.identifier) # custom metadata if 'translators' in PREFS.defaults: self.translators = QCheckBox('Tłumaczenie') self.translators.setChecked(PREFS['translators']) self.l3.addWidget(self.translators) if 'original_title' in PREFS.defaults: self.original_title = QCheckBox('Tytuł oryginału') self.original_title.setChecked(PREFS['original_title']) self.l3.addWidget(self.original_title) if 'categories' in PREFS.defaults: self.categories = QCheckBox('Kategorie') self.categories.setChecked(PREFS['categories']) self.l3.addWidget(self.categories) if 'genres' in PREFS.defaults: self.genres = QCheckBox('Gatunki') self.genres.setChecked(PREFS['genres']) self.l3.addWidget(self.genres) self.group_box.setLayout(self.l) self.group_box2.setLayout(self.l2) self.group_box3.setLayout(self.l3) self.main_layout.addWidget(self.group_box) self.main_layout.addWidget(self.group_box2) self.main_layout.addWidget(self.group_box3) self.main_layout.setAlignment(Qt.AlignTop) self.setLayout(self.main_layout) def save_settings(self): PREFS['max_results'] = int(self.max_results.text()) PREFS['authors_search'] = self.authors_search.isChecked() PREFS['only_first_author'] = self.only_first_author.isChecked() PREFS['covers'] = self.covers.isChecked() PREFS['max_covers'] = int(self.max_covers.text()) PREFS['threads'] = self.threads.isChecked() PREFS['max_threads'] = int(self.max_threads.text()) PREFS['thread_delay'] = float(self.thread_delay.text().replace( ',', '.')) # metadata settings if 'title' in PREFS.defaults: PREFS['title'] = self.title.isChecked() if 'authors' in PREFS.defaults: PREFS['authors'] = self.authors.isChecked() if 'pubdate' in PREFS.defaults: PREFS['pubdate'] = self.pubdate.isChecked() if 'publisher' in PREFS.defaults: PREFS['publisher'] = self.publisher.isChecked() if 'isbn' in PREFS.defaults: PREFS['isbn'] = self.isbn.isChecked() if 'comments' in PREFS.defaults: PREFS['comments'] = self.comments.isChecked() if 'languages' in PREFS.defaults: PREFS['languages'] = self.languages.isChecked() if 'rating' in PREFS.defaults: PREFS['rating'] = self.rating.isChecked() if 'tags' in PREFS.defaults: PREFS['tags'] = self.tags.isChecked() if 'series' in PREFS.defaults: PREFS['series'] = self.series.isChecked() if 'identifier' in PREFS.defaults: PREFS['identifier'] = self.identifier.isChecked() # custom metadata settings if 'translators' in PREFS.defaults: PREFS['translators'] = self.translators.isChecked() if 'original_title' in PREFS.defaults: PREFS['original_title'] = self.original_title.isChecked() if 'categories' in PREFS.defaults: PREFS['categories'] = self.categories.isChecked() if 'genres' in PREFS.defaults: PREFS['genres'] = self.genres.isChecked() return PREFS
def initialize(self): """ Initialize QDialog """ main_layout = QVBoxLayout() main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) about_widget = QWidget() about_widget.setObjectName('about') about_layout = QVBoxLayout(about_widget) # QDialog Title about_title = QLabel(_('About')) about_title.setFixedHeight(40) about_title.setObjectName('aboutheader') main_layout.addWidget(about_title) # Main About about_text = "%s\nVersion %s\nCopyright: %s" % \ (__application__, __version__, __copyright__) main_about = QLabel(about_text) main_about.setObjectName('aboutmain') main_about.setToolTip(__application__) about_layout.addWidget(main_about) about_layout.setAlignment(main_about, Qt.AlignCenter) # Release notes release_data = QLabel(__releasenotes__) release_data.setObjectName('about') release_data.setToolTip(_('Release notes')) release_data.setWordWrap(True) about_layout.addWidget(release_data) # Homepage home_title = QLabel(_('Home page:')) home_title.setObjectName('abouttitle') home_title.setToolTip(_('Home page')) about_layout.addWidget(home_title) about_layout.addWidget(self.get_external_link_label(__project_url__)) # User Doc doc_title = QLabel(_('User documentation')) doc_title.setObjectName('abouttitle') doc_title.setToolTip(_('User documentation')) about_layout.addWidget(doc_title) about_layout.addWidget(self.get_external_link_label(__doc_url__)) # Alignak alignak_title = QLabel(_('About Alignak solution:')) alignak_title.setObjectName('abouttitle') alignak_title.setToolTip(_('About Alignak solution')) about_layout.addWidget(alignak_title) about_layout.addWidget(self.get_external_link_label(__alignak_url__)) # Powered powered_title = QLabel(_('Powered by:')) powered_title.setObjectName('abouttitle') powered_title.setToolTip(_('PyQt5')) about_layout.addWidget(powered_title) powered_data = self.get_external_link_label('https://www.riverbankcomputing.com/', 'PyQt5') about_layout.addWidget(powered_data) main_layout.addWidget(about_widget)
class LibraryCodesDialog(SizePersistedDialog): #----------------------------------------------------------------------------------------- def __init__(self, gui, icon, guidb, plugin_path, ui_exit, action_type): parent = gui unique_pref_name = 'library_codes:gui_parameters_dialog' SizePersistedDialog.__init__(self, parent, unique_pref_name) #----------------------------------------------------- self.gui = gui self.guidb = guidb #----------------------------------------------------- self.icon = icon #----------------------------------------------------- self.plugin_path = plugin_path #----------------------------------------------------- self.ui_exit = ui_exit #----------------------------------------------------- self.action_type = action_type #----------------------------------------------------- self.myparentprefs = collections.OrderedDict([]) prefsdefaults = deepcopy(prefs.defaults) tmp_list = [] #~ for k,v in prefs.iteritems(): for k, v in iteritems(prefs): tmp_list.append(k) #END FOR #~ for k,v in prefsdefaults.iteritems(): for k, v in iteritems(prefsdefaults): tmp_list.append(k) #END FOR tmp_set = set(tmp_list) tmp_list = list(tmp_set) #no duplicates del tmp_set tmp_list.sort() for k in tmp_list: self.myparentprefs[k] = " " # ordered by key #END FOR del tmp_list #~ for k,v in prefs.iteritems(): for k, v in iteritems(prefs): self.myparentprefs[k] = v #END FOR #~ for k,v in prefsdefaults.iteritems(): for k, v in iteritems(prefsdefaults): if not k in prefs: prefs[k] = v else: if not prefs[k] > " ": prefs[k] = v if not k in self.myparentprefs: self.myparentprefs[k] = v else: if not self.myparentprefs[k] > " ": self.myparentprefs[k] = v #END FOR #~ for k,v in self.myparentprefs.iteritems(): for k, v in iteritems(self.myparentprefs): prefs[k] = v #END FOR prefs #prefs now synched #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- self.param_dict = collections.OrderedDict([]) #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- self.init_tooltips_for_parent() self.setToolTip(self.parent_tooltip) #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- # Tab 0: LibraryCodesTab #----------------------------------------------------- #----------------------------------------------------- from calibre_plugins.library_codes.library_codes_dialog import LibraryCodesTab self.LibraryCodesTab = LibraryCodesTab(self.gui, self.guidb, self.myparentprefs, self.param_dict, self.ui_exit, self.save_dialog_geometry) #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- # Parent LibraryCodesDialog #----------------------------------------------------- font = QFont() font.setBold(False) font.setPointSize(10) tablabel_font = QFont() tablabel_font.setBold(False) tablabel_font.setPointSize(10) #----------------------------------------------------- self.setWindowTitle('Library Codes') self.setWindowIcon(icon) #----------------------------------------------------- self.layout_frame = QVBoxLayout() self.layout_frame.setAlignment(Qt.AlignLeft) self.setLayout(self.layout_frame) #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- n_width = 600 self.LCtabWidget = QTabWidget() self.LCtabWidget.setMaximumWidth(n_width) self.LCtabWidget.setFont(tablabel_font) self.LCtabWidget.addTab( self.LibraryCodesTab, "Derivation from ISBN or ISSN or Author/Title") self.LibraryCodesTab.setToolTip( "<p style='white-space:wrap'>Derive Library Codes DDC and/or LCC and/or OCLC-OWI from ISBN or ISSN or Author/Title. Visit: http://classify.oclc.org/classify2/ " ) self.LibraryCodesTab.setMaximumWidth(n_width) #----------------------------------------------------- self.layout_frame.addWidget(self.LCtabWidget) #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- #----------------------------------------------------- self.resize_dialog() # inherited from SizePersistedDialog #----------------------------------------------------- self.LCtabWidget.setCurrentIndex(0) #----------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------- # OTHER #----------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------- def init_tooltips_for_parent(self): self.setStyleSheet( "QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }" ) self.parent_tooltip = "<p style='white-space:wrap'>" + \ '''
def addVignette (self, warrior): label_name = "label_vignette_left" if self.current_page == 0 : widget_vignette = QWidget(self.vignettes_gauche) else: label_name = "label_vignette_right" widget_vignette = QWidget(self.vignettes_droite) # widget_vignette.setObjectName("toto") # widget_vignette.setStyleSheet("#toto { background-color: rgb(170, 255, 0,0);}") layout_one_vignette = QVBoxLayout(widget_vignette) layout_one_vignette.setSpacing(0) layout_one_vignette.setContentsMargins(0, 0, 0, 0) if type(warrior)== Temple: warrior_button = TempleButton(self.model, warrior, widget_vignette) else: warrior_button = HerosButton(self.model, warrior, widget_vignette) warrior_button.connect() layout_one_vignette.setAlignment(QtCore.Qt.AlignCenter) # warrior_button.setStyleSheet("QPushButton { background-color: rgb(170, 255, 0);border-style: outset; border-width: 2px; border-color: beige;}") # warrior_button.setAttribute(QtCore.Qt.WA_TranslucentBackground,True) layout_one_vignette.addWidget(warrior_button) # label if (type(warrior)==Temple): warrior_label = TempleLabel(warrior, widget_vignette) else: warrior_label = HerosLabel(warrior, widget_vignette) warrior_label.connect() warrior_label.setObjectName(label_name) layout_one_vignette.addWidget(warrior_label) # warrior_button.setFixedSize(QSize(100,120)) max_col = 3 # groupe_name = warrior.groupe().name # if warrior.masterGroupe() != None : # groupe_name = warrior.masterGroupe().name + "/" + groupe_name size_pic_height = warrior_button.size().height() size_pic_width = warrior_button.size().width() ratio_h = warrior.thumb.height() / size_pic_height ratio_v = warrior.thumb.width() / size_pic_width picture = warrior.thumb if ratio_h < ratio_v : if not warrior.thumb.isNull(): picture = warrior.thumb.scaledToHeight(size_pic_height) diff = picture.width() - size_pic_width picture = picture.copy(diff / 2.0, 0, size_pic_width, size_pic_height) else: if not warrior.thumb.isNull(): picture = warrior.thumb.scaledToWidth(size_pic_width) diff = picture.height() - size_pic_height picture = picture.copy(0, diff / 2.0, size_pic_width, size_pic_height) icon = QIcon(picture) warrior_button.setIcon(icon) warrior_button.setIconSize(QSize(picture.width() - 3, picture.height() - 3)) if self.nb_col == 0: self.nb_row = self.nb_row + 1 if self.current_page == 0 : self.gridLayout.addWidget(widget_vignette, self.nb_row, self.nb_col) else: self.gridLayout_2.addWidget(widget_vignette, self.nb_row, self.nb_col) self.nb_col = (self.nb_col + 1) % max_col
class _BuilderTab(QWidget): """Handles the creation of launchers.""" def __init__(self): super().__init__() self._layout = QVBoxLayout() host_label = QLabel("Server host (where EvilOSX will connect to):") self._host_field = QLineEdit() self._layout.addWidget(host_label) self._layout.addWidget(self._host_field) port_label = QLabel("Server port:") self._port_field = QLineEdit() self._layout.addWidget(port_label) self._layout.addWidget(self._port_field) live_label = QLabel( "Where should EvilOSX live? (Leave empty for ~/Library/Containers/.<RANDOM>): " ) self._live_field = QLineEdit() self._layout.addWidget(live_label) self._layout.addWidget(self._live_field) launcher_label = QLabel("Launcher name:") self._launcher_combobox = QComboBox() for launcher_name in launchers.get_names(): self._launcher_combobox.addItem(launcher_name) self._layout.addWidget(launcher_label) self._layout.addWidget(self._launcher_combobox) loader_label = QLabel("Loader name:") loader_combobox = QComboBox() self._loader_layout = QVBoxLayout() for loader_name in loaders.get_names(): loader_combobox.addItem(loader_name) self._layout.addWidget(loader_label) self._layout.addWidget(loader_combobox) loader_combobox.currentTextChanged.connect(self._set_on_loader_change) # Dynamically loaded loader layout self._layout.addLayout(self._loader_layout) self._set_on_loader_change(loader_combobox.currentText()) self._layout.setContentsMargins(10, 10, 10, 0) self._layout.setAlignment(Qt.AlignTop) self.setLayout(self._layout) def _set_on_loader_change(self, new_text: str): """Handles the loader combobox change event.""" while self._loader_layout.count(): child = self._loader_layout.takeAt(0) if child.widget(): child.widget().deleteLater() input_fields = [] for message in loaders.get_option_messages(new_text): input_field = QLineEdit() self._loader_layout.addWidget(QLabel(message)) self._loader_layout.addWidget(input_field) input_fields.append(input_field) create_button = QPushButton("Create launcher") create_button.setMaximumWidth(250) create_button.setMinimumHeight(30) create_button.pressed.connect(lambda: self._on_create_launcher( self._host_field.text(), self._port_field.text(), self._live_field.text(), new_text, self._launcher_combobox.currentText(), input_fields)) self._loader_layout.addWidget(QLabel("")) self._loader_layout.addWidget(create_button) @staticmethod def display_error(text: str): """Displays an error message to the user.""" message = QMessageBox() message.setIcon(QMessageBox.Critical) message.setWindowTitle("Error") message.setText(text) message.setStandardButtons(QMessageBox.Ok) message.exec_() @staticmethod def display_info(text: str): message = QMessageBox() message.setIcon(QMessageBox.Information) message.setWindowTitle("Information") message.setText(text) message.setStandardButtons(QMessageBox.Ok) message.exec_() def _on_create_launcher(self, server_host, server_port, program_directory, loader_name: str, launcher_name: str, input_fields: list): """Creates the launcher and outputs it to the builds directory.""" if not self._host_field.text(): self.display_error("Invalid host specified.") elif not str(self._port_field.text()).isdigit(): self.display_error("Invalid port specified.") else: set_options = [] for field in input_fields: set_options.append(field.text()) loader_options = loaders.get_options(loader_name, set_options) loader_options["program_directory"] = program_directory stager = launchers.create_stager(server_host, server_port, loader_options) launcher_extension, launcher = launchers.generate( launcher_name, stager) launcher_path = path.realpath( path.join( path.dirname(__file__), path.pardir, path.pardir, "data", "builds", "Launcher-{}.{}".format( str(uuid4())[:6], launcher_extension))) with open(launcher_path, "w") as output_file: output_file.write(launcher) self.display_info( "Launcher written to: \n{}".format(launcher_path))
def get_actions_widget(self): """ Return QWidget with actions buttons :return: widget with buttons :rtype: QWidget """ widget = QWidget() layout = QVBoxLayout() widget.setLayout(layout) # Actions action_title = QLabel(_('Host actions')) action_title.setObjectName('itemtitle') action_title.setFixedHeight(25) layout.addWidget(action_title) ack_down_lbl = QLabel(_('Acknowledge / Downtime:')) ack_down_lbl.setObjectName('subtitle') layout.addWidget(ack_down_lbl) self.actions_widget.initialize(self.host_item) layout.addWidget(self.actions_widget) # Active Checks activecheck_lbl = QLabel(_('Active checks:')) activecheck_lbl.setObjectName('subtitle') layout.addWidget(activecheck_lbl) self.activecheck_btn.initialize() self.activecheck_btn.toggle_btn.clicked.connect( lambda: self.patch_host_checks('active_checks_enabled', self.activecheck_btn.is_checked())) layout.addWidget(self.activecheck_btn) # Passive Checks passivecheck_lbl = QLabel(_('Passive checks:')) passivecheck_lbl.setObjectName('subtitle') layout.addWidget(passivecheck_lbl) self.passivecheck_btn.initialize() self.passivecheck_btn.toggle_btn.clicked.connect( lambda: self.patch_host_checks('passive_checks_enabled', self.passivecheck_btn.is_checked())) layout.addWidget(self.passivecheck_btn) # History hist_lbl = QLabel(_('Timeline:')) hist_lbl.setObjectName('subtitle') layout.addWidget(hist_lbl) self.history_btn.setIcon(QIcon(settings.get_image('time'))) self.history_btn.setFixedSize(80, 20) self.history_btn.clicked.connect(self.show_history) self.history_btn.setToolTip(_('See history of host')) layout.addWidget(self.history_btn) layout.setAlignment(self.history_btn, Qt.AlignCenter) self.history_widget.initialize() # Spy Button spy_lbl = QLabel(_('Spy Host:')) spy_lbl.setObjectName('subtitle') layout.addWidget(spy_lbl) self.spy_btn.setIcon(QIcon(settings.get_image('spy'))) self.spy_btn.setFixedSize(80, 20) self.spy_btn.setToolTip(_('Spy current host')) layout.addWidget(self.spy_btn) layout.setAlignment(self.spy_btn, Qt.AlignCenter) layout.setAlignment(Qt.AlignCenter | Qt.AlignTop) return widget
def get_actions_widget(self): """ Return QWidget with actions buttons :return: widget with buttons :rtype: QWidget """ widget = QWidget() layout = QVBoxLayout() widget.setLayout(layout) # Actions action_title = QLabel(_('Host actions')) action_title.setObjectName('itemtitle') action_title.setFixedHeight(25) layout.addWidget(action_title) ack_down_lbl = QLabel(_('Acknowledge / Downtime:')) ack_down_lbl.setObjectName('subtitle') layout.addWidget(ack_down_lbl) self.actions_widget.initialize(self.host_item) layout.addWidget(self.actions_widget) # Active Checks activecheck_lbl = QLabel(_('Active checks:')) activecheck_lbl.setObjectName('subtitle') layout.addWidget(activecheck_lbl) self.activecheck_btn.initialize() self.activecheck_btn.toggle_btn.clicked.connect(lambda: self.patch_host_checks( 'active_checks_enabled', self.activecheck_btn.is_checked() )) layout.addWidget(self.activecheck_btn) # Passive Checks passivecheck_lbl = QLabel(_('Passive checks:')) passivecheck_lbl.setObjectName('subtitle') layout.addWidget(passivecheck_lbl) self.passivecheck_btn.initialize() self.passivecheck_btn.toggle_btn.clicked.connect(lambda: self.patch_host_checks( 'passive_checks_enabled', self.passivecheck_btn.is_checked() )) layout.addWidget(self.passivecheck_btn) # History hist_lbl = QLabel(_('Timeline:')) hist_lbl.setObjectName('subtitle') layout.addWidget(hist_lbl) self.history_btn.setIcon(QIcon(settings.get_image('time'))) self.history_btn.setFixedSize(80, 20) self.history_btn.clicked.connect(self.show_history) self.history_btn.setToolTip(_('See history of host')) layout.addWidget(self.history_btn) layout.setAlignment(self.history_btn, Qt.AlignCenter) self.history_widget.initialize() # Spy Button spy_lbl = QLabel(_('Spy Host:')) spy_lbl.setObjectName('subtitle') layout.addWidget(spy_lbl) self.spy_btn.setIcon(QIcon(settings.get_image('spy'))) self.spy_btn.setFixedSize(80, 20) self.spy_btn.setToolTip(_('Spy current host')) layout.addWidget(self.spy_btn) layout.setAlignment(self.spy_btn, Qt.AlignCenter) layout.setAlignment(Qt.AlignCenter | Qt.AlignTop) return widget
def get_settings_widget(self): """ Return the alignak settings QWidget :return: settings QWidget :rtype: QWidget """ server_widget = QWidget() server_widget.setObjectName('dialog') server_layout = QVBoxLayout(server_widget) # Title title_lbl = QLabel(_('Alignak Backend')) title_lbl.setObjectName('itemtitle') server_layout.addWidget(title_lbl) server_layout.setAlignment(title_lbl, Qt.AlignTop) # Description desc_label = QLabel( _('Here you can define alignak settings. Be sure to enter a valid address.') ) desc_label.setWordWrap(True) server_layout.addWidget(desc_label) # Server URL server_lbl = QLabel(_('Server')) server_layout.addWidget(server_lbl) self.server_url.setText(settings.get_config('Alignak', 'url')) self.server_url.setPlaceholderText(_('alignak backend url...')) self.server_url.setFixedHeight(25) server_layout.addWidget(self.server_url) # Server Port port_lbl = QLabel(_('Port')) server_layout.addWidget(port_lbl) cur_port = settings.get_config('Alignak', 'backend').split(':')[2] self.server_port.setText(cur_port) self.server_port.setPlaceholderText(_('alignak backend port...')) self.server_port.setFixedHeight(25) server_layout.addWidget(self.server_port) # Server Processes (displayed only for Unix platforms) if 'win32' not in sys.platform: process_lbl = QLabel(_('Processes')) server_layout.addWidget(process_lbl) cur_proc = settings.get_config('Alignak', 'processes') self.server_proc.setText(cur_proc) self.server_proc.setPlaceholderText(_('alignak backend processes...')) self.server_proc.setFixedHeight(25) server_layout.addWidget(self.server_proc) # Web Service description server_layout.addStretch(1) webservice_lbl = QLabel(_('Web Service')) webservice_lbl.setObjectName('itemtitle') server_layout.addWidget(webservice_lbl) ws_desc_lbl = QLabel( _('Here you can define your alignak web service url, with port if needed') ) ws_desc_lbl.setWordWrap(True) server_layout.addWidget(ws_desc_lbl) # Web Service URL self.webservice_url.setText(settings.get_config('Alignak', 'webservice')) self.webservice_url.setPlaceholderText(_('alignak webservice url...')) self.webservice_url.setFixedHeight(25) server_layout.addWidget(self.webservice_url) # Valid Button valid_btn = QPushButton(_('Valid')) valid_btn.setObjectName('valid') valid_btn.setMinimumHeight(30) valid_btn.clicked.connect(self.accept) server_layout.addWidget(valid_btn) return server_widget
def setup_ui(self): layout = QVBoxLayout() self.setLayout(layout) columns_frame = QHBoxLayout() layout.addLayout(columns_frame) # How many columns of nine items each will it take to display # a text box for each tag in taglist? col_limit = 9 num_cols = len(TAGLIST)/col_limit num_cols = int(math.ceil(num_cols)) # If the column limit and the number of columns produces a single # orphan text entry widget, reduce the column limit accordingly. if num_cols > 1 and (len(TAGLIST) - ((num_cols - 1)*col_limit)) < 2: if num_cols >= 3: col_limit -= 1 # Create an integer-indexed dictionary of QVBoxLayouts representing the number of # columns necessary. Added left to right in the parent QHBoxLayout. column = {} for i in xrange(1, num_cols+1): column[i] = QVBoxLayout() column[i].setAlignment(Qt.AlignLeft) columns_frame.addLayout(column[i]) # Create a dictionary of QLineEdit widgets (indexed by tag name) and stack them # (top to bottom) and their labels in as many columns as it takes. curr_col = 1 curr_item = 1 tooltip = _('Comma separated list of html elements (no quotes, no angle "<" brackets).') for tag in TAGLIST: # Column item limit surpassed - switch to next column. if curr_item > col_limit: column[curr_col].addStretch() curr_col += 1 curr_item = 1 # Add lable and QLineEdit widget to current column. label = QLabel(_('<b>Choices to change "{}" elements to:</b>').format(tag), self) label.setAlignment(Qt.AlignCenter) self.qlinedit_widgets[tag] = QLineEdit(', '.join(plugin_prefs['{}_changes'.format(tag)]), self) self.qlinedit_widgets[tag].setToolTip('<p>{}'.format(tooltip)) column[curr_col].addWidget(label) column[curr_col].addWidget(self.qlinedit_widgets[tag]) if not len(CHANGE_TO_MAP[tag]): self.qlinedit_widgets[tag].setDisabled(True) curr_item += 1 column[curr_col].addStretch() layout.addSpacing(10) attrs_layout = QVBoxLayout() attrs_layout.setAlignment(Qt.AlignCenter) layout.addLayout(attrs_layout) label = QLabel(_('<b>HTML attributes available to search for:</b>'), self) label.setAlignment(Qt.AlignCenter) self.attrs_txtBox = QLineEdit(', '.join(plugin_prefs['attrs']), self) self.attrs_txtBox.setToolTip('<p>{}'.format(_('Comma separated list of html attribute names (no quotes).'))) attrs_layout.addWidget(label) attrs_layout.addWidget(self.attrs_txtBox) layout.addSpacing(10) right_layout = QHBoxLayout() right_layout.setAlignment(Qt.AlignRight) layout.addLayout(right_layout) reset_button = QPushButton(_('Reset all defaults'), self) reset_button.setToolTip('<p>{}'.format(_('Reset all settings to original defaults.'))) reset_button.clicked.connect(self.reset_defaults) right_layout.addWidget(reset_button) layout.addSpacing(10) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(self.save_settings) button_box.rejected.connect(self.reject) layout.addWidget(button_box)
def initialize(self): """ Initialize QDialog """ main_layout = QVBoxLayout() main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) about_widget = QWidget() about_widget.setObjectName('about') about_layout = QVBoxLayout(about_widget) # QDialog Title about_title = QLabel(_('About')) about_title.setFixedHeight(40) about_title.setObjectName('aboutheader') main_layout.addWidget(about_title) # Main About about_text = "%s\nVersion %s\nCopyright: %s" % \ (__application__, __version__, __copyright__) main_about = QLabel(about_text) main_about.setObjectName('aboutmain') main_about.setToolTip(__application__) about_layout.addWidget(main_about) about_layout.setAlignment(main_about, Qt.AlignCenter) # Release notes release_data = QLabel(__releasenotes__) release_data.setObjectName('about') release_data.setToolTip(_('Release notes')) release_data.setWordWrap(True) about_layout.addWidget(release_data) # Homepage home_title = QLabel(_('Home page:')) home_title.setObjectName('abouttitle') home_title.setToolTip(_('Home page')) about_layout.addWidget(home_title) about_layout.addWidget(self.get_external_link_label(__project_url__)) # User Doc doc_title = QLabel(_('User documentation')) doc_title.setObjectName('abouttitle') doc_title.setToolTip(_('User documentation')) about_layout.addWidget(doc_title) about_layout.addWidget(self.get_external_link_label(__doc_url__)) # Alignak alignak_title = QLabel(_('About Alignak solution:')) alignak_title.setObjectName('abouttitle') alignak_title.setToolTip(_('About Alignak solution')) about_layout.addWidget(alignak_title) about_layout.addWidget(self.get_external_link_label(__alignak_url__)) # Powered powered_title = QLabel(_('Powered by:')) powered_title.setObjectName('abouttitle') powered_title.setToolTip(_('PyQt5')) about_layout.addWidget(powered_title) powered_data = self.get_external_link_label( 'https://www.riverbankcomputing.com/', 'PyQt5') about_layout.addWidget(powered_data) main_layout.addWidget(about_widget)