def __init__(self, parent=None): #### Attributes self.searchResults = [] # Returned search results self.dispSearchResults = [] # Displayable search results self.myShows = [] # My Tracked Shows self.myColors = {} # My custom colors self.myColors['default'] = "" self.myColors['ranges'] = [] # self.modifFlag = False # Set to True if modifications were made # #self.lastColorUsed = QColor( 0xFF, 0xFF, 0xFF ) self.lastColorUsed = "#FFFFFF" # self.desktopSize = QDesktopWidget().screenGeometry() # Holds the desktop's Size (QRect) self.uiHelpDialogGeometry = QRect() # Holds the Format Help Window's Geometry (QRect) self.uiHelpDialogSize = QSize() # Holds the Format Help Window's Size (QSize) #### Init UI QDialog.__init__(self, parent) self.ui = Ui_NextShowsConfig() self.ui.setupUi(self) # Setup UI #### Drag n' Drop support self.ui.listSearchResults.setAcceptDrags(True) self.ui.listMyShows.setAcceptDrags(True) self.ui.listMyShows.setAcceptDrops(True) self.ui.listMyColors.setAcceptDrags(True) QObject.connect( self.ui.listMyShows, SIGNAL("dropReceived"), self.addToMyShows ) QObject.connect( self.ui.btnShowRemove, SIGNAL("dropReceived"), self.removeFromMyShows ) QObject.connect( self.ui.btnColorRemove, SIGNAL("dropReceived"), self.removeFromMyColors ) #### Initialize form (read config, set labels, etc...) self.initForm() #### Inititialize Format Help Dialog self.uiHelpDialog = FormatHelp() self.uiHelpDialog.setWindowFlags( Qt.Window ) self.uiHelpDialogSize = QSize( self.uiHelpDialog.width(), self.uiHelpDialog.height() ) self.uiHelpDialog.setMinimumSize( self.uiHelpDialogSize ) # Fix the size (ugly hack) self.uiHelpDialog.setMaximumSize( self.uiHelpDialogSize ) # Fix the size (ugly hack) #### Signals / Slots QObject.connect( self.ui.btnLookup, SIGNAL("clicked()"), self.lookupShow ) QObject.connect( self.uiHelpDialog, SIGNAL("hideWindow()"), self.resetBtnFormatInfos ) QObject.connect( self.ui.btnQuit, SIGNAL("clicked()"), self, SLOT("close()") ) #### Make sure the first tabs are shown when we 1st launch the GUI self.ui.tabWidgetWidget.setCurrentIndex(0) self.ui.tabWidget.setCurrentIndex(0)
def __init__(self, parent=None): #### Attributes self.searchResults = [] # Returned search results self.dispSearchResults = [] # Displayable search results self.myShows = [] # My Tracked Shows self.myColors = {} # My custom colors self.myColors['default'] = "" self.myColors['ranges'] = [] # self.modifFlag = False # Set to True if modifications were made # #self.lastColorUsed = QColor( 0xFF, 0xFF, 0xFF ) self.lastColorUsed = "#FFFFFF" # self.desktopSize = QDesktopWidget().screenGeometry( ) # Holds the desktop's Size (QRect) self.uiHelpDialogGeometry = QRect( ) # Holds the Format Help Window's Geometry (QRect) self.uiHelpDialogSize = QSize( ) # Holds the Format Help Window's Size (QSize) #### Init UI QDialog.__init__(self, parent) self.ui = Ui_NextShowsConfig() self.ui.setupUi(self) # Setup UI #### Drag n' Drop support self.ui.listSearchResults.setAcceptDrags(True) self.ui.listMyShows.setAcceptDrags(True) self.ui.listMyShows.setAcceptDrops(True) self.ui.listMyColors.setAcceptDrags(True) QObject.connect(self.ui.listMyShows, SIGNAL("dropReceived"), self.addToMyShows) QObject.connect(self.ui.btnShowRemove, SIGNAL("dropReceived"), self.removeFromMyShows) QObject.connect(self.ui.btnColorRemove, SIGNAL("dropReceived"), self.removeFromMyColors) #### Initialize form (read config, set labels, etc...) self.initForm() #### Inititialize Format Help Dialog self.uiHelpDialog = FormatHelp() self.uiHelpDialog.setWindowFlags(Qt.Window) self.uiHelpDialogSize = QSize(self.uiHelpDialog.width(), self.uiHelpDialog.height()) self.uiHelpDialog.setMinimumSize( self.uiHelpDialogSize) # Fix the size (ugly hack) self.uiHelpDialog.setMaximumSize( self.uiHelpDialogSize) # Fix the size (ugly hack) #### Signals / Slots QObject.connect(self.ui.btnLookup, SIGNAL("clicked()"), self.lookupShow) QObject.connect(self.uiHelpDialog, SIGNAL("hideWindow()"), self.resetBtnFormatInfos) QObject.connect(self.ui.btnQuit, SIGNAL("clicked()"), self, SLOT("close()")) #### Make sure the first tabs are shown when we 1st launch the GUI self.ui.tabWidgetWidget.setCurrentIndex(0) self.ui.tabWidget.setCurrentIndex(0)
class NextShowsConfig(QDialog): def __init__(self, parent=None): #### Attributes self.searchResults = [] # Returned search results self.dispSearchResults = [] # Displayable search results self.myShows = [] # My Tracked Shows self.myColors = {} # My custom colors self.myColors['default'] = "" self.myColors['ranges'] = [] # self.modifFlag = False # Set to True if modifications were made # #self.lastColorUsed = QColor( 0xFF, 0xFF, 0xFF ) self.lastColorUsed = "#FFFFFF" # self.desktopSize = QDesktopWidget().screenGeometry( ) # Holds the desktop's Size (QRect) self.uiHelpDialogGeometry = QRect( ) # Holds the Format Help Window's Geometry (QRect) self.uiHelpDialogSize = QSize( ) # Holds the Format Help Window's Size (QSize) #### Init UI QDialog.__init__(self, parent) self.ui = Ui_NextShowsConfig() self.ui.setupUi(self) # Setup UI #### Drag n' Drop support self.ui.listSearchResults.setAcceptDrags(True) self.ui.listMyShows.setAcceptDrags(True) self.ui.listMyShows.setAcceptDrops(True) self.ui.listMyColors.setAcceptDrags(True) QObject.connect(self.ui.listMyShows, SIGNAL("dropReceived"), self.addToMyShows) QObject.connect(self.ui.btnShowRemove, SIGNAL("dropReceived"), self.removeFromMyShows) QObject.connect(self.ui.btnColorRemove, SIGNAL("dropReceived"), self.removeFromMyColors) #### Initialize form (read config, set labels, etc...) self.initForm() #### Inititialize Format Help Dialog self.uiHelpDialog = FormatHelp() self.uiHelpDialog.setWindowFlags(Qt.Window) self.uiHelpDialogSize = QSize(self.uiHelpDialog.width(), self.uiHelpDialog.height()) self.uiHelpDialog.setMinimumSize( self.uiHelpDialogSize) # Fix the size (ugly hack) self.uiHelpDialog.setMaximumSize( self.uiHelpDialogSize) # Fix the size (ugly hack) #### Signals / Slots QObject.connect(self.ui.btnLookup, SIGNAL("clicked()"), self.lookupShow) QObject.connect(self.uiHelpDialog, SIGNAL("hideWindow()"), self.resetBtnFormatInfos) QObject.connect(self.ui.btnQuit, SIGNAL("clicked()"), self, SLOT("close()")) #### Make sure the first tabs are shown when we 1st launch the GUI self.ui.tabWidgetWidget.setCurrentIndex(0) self.ui.tabWidget.setCurrentIndex(0) ########################################################################### ## REACT TO USER INTERACTIONS ## ########################################################################### #### "Shows" Tab # Text Changed in Lookup QLineEdit @pyqtSignature("on_leditLookup_textChanged(const QString &)") def on_leditLookup_textChanged(self, qstring): text = str(qstring.toUtf8()) if text != "": self.ui.btnLookup.setEnabled(True) self.ui.btnLookup.setDefault(True) else: self.ui.btnLookup.setEnabled(False) self.ui.btnLookup.setDefault(False) # Click on "Clear Text" @pyqtSignature("on_btnLeditLookupClear_clicked()") def on_btnLeditLookupClear_clicked(self): self.ui.leditLookup.setText(u"") # Item on the search results selected @pyqtSignature("on_listSearchResults_currentRowChanged(int)") def on_listSearchResults_currentRowChanged(self, rowNum): if rowNum == -1: return self.ui.btnShowAdd.setEnabled(True) # Item double-clicked or add button clicked @pyqtSignature("on_listSearchResults_activated(const QModelIndex &)") def on_listSearchResults_activated(self, modelIndex): self.addToMyShows(modelIndex.row()) @pyqtSignature("on_btnShowAdd_clicked()") def on_btnShowAdd_clicked(self): self.addToMyShows(self.ui.listSearchResults.currentRow()) # Item on my shows selected @pyqtSignature("on_listMyShows_currentRowChanged(int)") def on_listMyShows_currentRowChanged(self, rowNum): if rowNum == -1: return self.ui.btnShowRemove.setEnabled(True) # "My Shows" item double-clicked or remove button clicked @pyqtSignature("on_listMyShows_activated(const QModelIndex &)") def on_listMyShows_activated(self, modelIndex): self.removeFromMyShows(modelIndex.row()) @pyqtSignature("on_btnShowRemove_clicked()") def on_btnShowRemove_clicked(self): self.removeFromMyShows(self.ui.listMyShows.currentRow()) # Filter state changed @pyqtSignature("on_chkbxFilter_stateChanged(int)") def on_chkbxFilter_stateChanged(self, state): self.displaySearchResults() #### "Widget" Tab #### "Widget"->"Display" Tab # Past days value changed @pyqtSignature("on_spinNumPastDays_valueChanged(int)") def on_spinNumPastDays_valueChanged(self, value): # Need to save self.saveRequired() # Click on Fixed Size radio @pyqtSignature("on_radioDispFixedLines_toggled(bool)") def on_radioDispFixedLines_toggled(self, checked): if checked: # Enable Fixed Size self.ui.lblFixedDispLines.setEnabled(True) self.ui.spinFixedDispLines.setEnabled(True) else: # Disable Fixed Size self.ui.lblFixedDispLines.setEnabled(False) self.ui.spinFixedDispLines.setEnabled(False) # Need to save self.saveRequired() # Fixed lines value changed @pyqtSignature("on_spinFixedDispLines_valueChanged(int)") def on_spinFixedDispLines_valueChanged(self, value): # Need to save self.saveRequired() # Click on Automatic Resize radio @pyqtSignature("on_radioDispAutoResize_toggled(bool)") def on_radioDispAutoResize_toggled(self, checked): if checked: # Enable Automatic Size self.ui.lblMinDispLines.setEnabled(True) self.ui.lblMaxDispLines.setEnabled(True) self.ui.spinMinDispLines.setEnabled(True) self.ui.spinMaxDispLines.setEnabled(True) else: # Disable Automatic Size self.ui.lblMinDispLines.setEnabled(False) self.ui.lblMaxDispLines.setEnabled(False) self.ui.spinMinDispLines.setEnabled(False) self.ui.spinMaxDispLines.setEnabled(False) # Need to save self.saveRequired() # MinDispLines Changed @pyqtSignature("on_spinMinDispLines_valueChanged(int)") def on_spinMinDispLines_valueChanged(self, newValue): currentMaxValue = self.ui.spinMaxDispLines.value() maxMaxValue = self.ui.spinMaxDispLines.maximum() if newValue >= currentMaxValue: if currentMaxValue < maxMaxValue: self.ui.spinMaxDispLines.setValue(newValue + 1) else: self.ui.spinMinDispLines.setValue(newValue - 1) # Need to save self.saveRequired() # MaxDispLines Changed @pyqtSignature("on_spinMaxDispLines_valueChanged(int)") def on_spinMaxDispLines_valueChanged(self, newValue): currentMinValue = self.ui.spinMinDispLines.value() minMinValue = self.ui.spinMinDispLines.minimum() if newValue <= currentMinValue: if currentMinValue > minMinValue: self.ui.spinMinDispLines.setValue(newValue - 1) else: self.ui.spinMaxDispLines.setValue(newValue + 1) # Need to save self.saveRequired() # Date Separator Changed @pyqtSignature("on_leditDateSeparator_editingFinished()") def on_leditDateSeparator_editingFinished(self): if not self.ui.leditDateSeparator.text( ) or self.ui.leditDateSeparator.text() == "%": self.ui.leditDateSeparator.setText("/") @pyqtSignature("on_leditDateSeparator_textChanged(const QString &)") def on_leditDateSeparator_textChanged(self, QString): if not self.ui.leditDateSeparator.text( ) or self.ui.leditDateSeparator.text() == "%": self.ui.comboDateFormat.clear() self.ui.comboDateFormat.addItem("INVALID SEPARATOR") self.ui.comboDateFormat.setEnabled(False) else: self.populateDateFormat(QString) # Need to save self.saveRequired() # Date Format Changed @pyqtSignature("on_comboDateFormat_currentIndexChanged(int)") def on_comboDateFormat_currentIndexChanged(self, idx): # Need to save self.saveRequired() # Click on checkable Format Info Button @pyqtSignature("on_btnFormatInfos_clicked()") def on_btnFormatInfos_clicked(self): # If this is the 1st time we ask for the Help Window # compute its geometry (relative to the main window) if not self.uiHelpDialogGeometry.isValid(): # Y pos yPos = self.pos().y() + ( (self.height() - self.uiHelpDialogSize.height()) / 2) # Choose the best pos (Left or Right) depending of the main window pos coordsRight = self.desktopSize.width() - (self.pos().x() + self.width()) if coordsRight > self.pos().x(): xPos = self.pos().x() + self.width() else: xPos = self.pos().x() - self.uiHelpDialogSize.width() self.uiHelpDialogGeometry = QRect(xPos, yPos, self.uiHelpDialogSize.width(), self.uiHelpDialogSize.height()) if self.ui.btnFormatInfos.isChecked(): self.uiHelpDialog.setGeometry(self.uiHelpDialogGeometry) self.uiHelpDialog.show() else: self.uiHelpDialogGeometry = self.uiHelpDialog.geometry() self.uiHelpDialog.hide() # Format text changed @pyqtSignature("on_leditFormat_textChanged(const QString &)") def on_leditFormat_textChanged(self, QString): text = str(QString) self.refreshFormatPreview(text) # Need to save self.saveRequired() # Resets the button state if help window is closed def resetBtnFormatInfos(self): self.ui.btnFormatInfos.setChecked(False) self.on_btnFormatInfos_clicked() #### "Widget"->"Colors" tab # Set Default Color clicked @pyqtSignature("on_btnSetDefaultColor_clicked()") def on_btnSetDefaultColor_clicked(self): selColor = QColorDialog.getColor(QColor(self.myColors['default']), self) if not selColor.isValid(): tools.msgDebug(u"Canceled by user!", __name__) return tools.msgDebug( u"Selected color: #%02X%02X%02X" % (selColor.red(), selColor.green(), selColor.blue()), __name__) self.ui.lblDefaultColor.setPixmap( self.drawPreviewColor(selColor, 36, 36)) self.myColors['default'] = str(selColor.name()) # Need to save self.saveRequired() # Select Color clicked @pyqtSignature("on_btnSelectColor_clicked()") def on_btnSelectColor_clicked(self): selColor = QColorDialog.getColor(QColor(self.lastColorUsed), self) if not selColor.isValid(): tools.msgDebug(u"Canceled by user!", __name__) return tools.msgDebug( u"Selected color: #%02X%02X%02X" % (selColor.red(), selColor.green(), selColor.blue()), __name__) self.ui.lblSelectColor.setPixmap( self.drawPreviewColor(selColor, 36, 36)) self.lastColorUsed = str(selColor.name()) # Click on Single Day radio @pyqtSignature("on_radioSingleDay_toggled(bool)") def on_radioSingleDay_toggled(self, checked): if checked: # Enable Single Day self.ui.lblColorsDay.setEnabled(True) self.ui.spinColorsSingleDay.setEnabled(True) else: # Disable Single Day self.ui.lblColorsDay.setEnabled(False) self.ui.spinColorsSingleDay.setEnabled(False) # Click on Automatic Resize radio @pyqtSignature("on_radioDayRange_toggled(bool)") def on_radioDayRange_toggled(self, checked): if checked: # Enable Range self.ui.lblColorsFrom.setEnabled(True) self.ui.lblColorsTo.setEnabled(True) self.ui.spinColorsFrom.setEnabled(True) self.ui.spinColorsTo.setEnabled(True) else: # Disable Range self.ui.lblColorsFrom.setEnabled(False) self.ui.lblColorsTo.setEnabled(False) self.ui.spinColorsFrom.setEnabled(False) self.ui.spinColorsTo.setEnabled(False) # Range From @pyqtSignature("on_spinColorsFrom_editingFinished()") def on_spinColorsFrom_editingFinished(self): fromValue = self.ui.spinColorsFrom.value() toValue = self.ui.spinColorsTo.value() maxToValue = self.ui.spinColorsTo.maximum() if fromValue >= toValue: if toValue < maxToValue: self.ui.spinColorsTo.setValue(fromValue + 1) else: self.ui.spinColorsFrom.setValue(fromValue - 1) # Range To @pyqtSignature("on_spinColorsTo_editingFinished()") def on_spinColorsTo_editingFinished(self): fromValue = self.ui.spinColorsFrom.value() toValue = self.ui.spinColorsTo.value() minFromValue = self.ui.spinColorsFrom.minimum() if toValue <= fromValue: if fromValue > minFromValue: self.ui.spinColorsFrom.setValue(toValue - 1) else: self.ui.spinColorsTo.setValue(toValue + 1) # Item on my colors selected @pyqtSignature("on_listMyColors_currentRowChanged(int)") def on_listMyColors_currentRowChanged(self, rowNum): if rowNum == -1: return self.ui.btnColorRemove.setEnabled(True) rangeStart, rangeStop, color = self.myColors['ranges'][rowNum] if rangeStart == rangeStop: self.ui.radioSingleDay.setChecked(True) self.ui.spinColorsSingleDay.setValue(rangeStart) else: self.ui.radioDayRange.setChecked(True) self.ui.spinColorsFrom.setValue(rangeStart) self.ui.spinColorsTo.setValue(rangeStop) self.lastColorUsed = color self.ui.lblSelectColor.setPixmap( self.drawPreviewColor(self.lastColorUsed, 36, 36)) # Color Add clicked @pyqtSignature("on_btnColorAdd_clicked()") def on_btnColorAdd_clicked(self): self.ui.spinColorsFrom.clearFocus() self.ui.spinColorsTo.clearFocus() self.addToMyColors() # "My colors" item double-clicked or remove button clicked @pyqtSignature("on_listMyColors_activated(const QModelIndex &)") def on_listMyColors_activated(self, modelIndex): self.removeFromMyColors(modelIndex.row()) @pyqtSignature("on_btnColorRemove_clicked()") def on_btnColorRemove_clicked(self): self.removeFromMyColors(self.ui.listMyColors.currentRow()) #### "Widget"->"Misc" tab # Cache expiration time changed @pyqtSignature("on_spinCacheExpiration_valueChanged(int)") def on_spinCacheExpiration_valueChanged(self, newValue): # Need to save self.saveRequired() # Text Changed in Browser @pyqtSignature("on_leditBrowser_textChanged(const QString &)") def on_leditBrowser_textChanged(self, qstring): # Need to save self.saveRequired() # Theme changed @pyqtSignature("on_comboTheme_currentIndexChanged(int)") def on_comboTheme_currentIndexChanged(self, idx): # Need to save self.saveRequired() #### General # Save button clicked @pyqtSignature("on_btnSave_clicked()") def on_btnSave_clicked(self): # import thread # thread.start_new_thread( self.saveConfig, ("",) ) self.saveConfig() # React to close event def closeEvent(self, event): if self.modifFlag: yesno = QMessageBox().question( self, "Attention", "Changes were made!\n" + "Are you sure you want to quit without saving?", QMessageBox.Yes, QMessageBox.No) if yesno == QMessageBox().No: event.ignore() return # User wants to quit # Make sure Config() isn't opened self.hide() self.uiHelpDialog.hide() while Config.LOCK: tools.msgDebug( u"Waiting for config to be written before exiting...", __name__) time.sleep(0.2) tools.msgDebug(u"Exiting...", __name__) ############################################################################### ############################################# ## Fills the form with the relevant values ## ############################################# def initForm(self): # 1st tab labels self.ui.lblResultsDisplayed.setText(u"Displayed results: 0/0") self.ui.lblTrackedShows.setText(u"Tracked shows: 0") # Format Sample fmtSample = u"<u><b>Sample:</b></u> <b>show:</b> %s, <b>title:</b> %s, <b>season</b>: %d, <b>episode</b>: %d" % ( Globals().sampleEpisode['show'], Globals().sampleEpisode['title'], Globals().sampleEpisode['season'], Globals().sampleEpisode['episode']) self.ui.lblFormatSample.setText(fmtSample) #### Versions version = Globals().versions # nextShows Footer Release labelContent = str(self.ui.lblFooterRelease.text()) self.ui.lblFooterRelease.setText(labelContent % version['nextShows']) # nextShows Release (About tab) labelContent = str(self.ui.lblNextShowsVersion.text()) self.ui.lblNextShowsVersion.setText(labelContent % version['nextShows']) # Libs releases (About tab) # Python version a, b, c, d, e = sys.version_info pythonVersion = "%d.%d.%d" % (a, b, c) # labelContent = str(self.ui.lblLibsVersion.text()) self.ui.lblLibsVersion.setText( labelContent % (pythonVersion, QT_VERSION_STR, PYQT_VERSION_STR, version["KDE"])) #### Default values self.ui.spinNumPastDays.setMinimum(0) self.ui.spinNumPastDays.setMaximum(99) #self.ui.spinNumPastDays.setValue(1) self.ui.spinFixedDispLines.setMinimum(1) self.ui.spinFixedDispLines.setMaximum(50) #self.ui.spinFixedDispLines.setValue(10) self.ui.spinMinDispLines.setMinimum(1) self.ui.spinMinDispLines.setMaximum(49) #self.ui.spinMinDispLines.setValue(1) self.ui.spinMaxDispLines.setMinimum(2) self.ui.spinMaxDispLines.setMaximum(50) #self.ui.spinMaxDispLines.setValue(10) # self.ui.spinColorsSingleDay.setMinimum(-99) self.ui.spinColorsSingleDay.setMaximum(99) self.ui.spinColorsSingleDay.setValue(0) self.ui.spinColorsFrom.setMinimum(-99) self.ui.spinColorsFrom.setMaximum(98) self.ui.spinColorsFrom.setValue(0) self.ui.spinColorsTo.setMinimum(-98) self.ui.spinColorsTo.setMaximum(99) self.ui.spinColorsTo.setValue(10) # default color for "Select color" self.ui.lblSelectColor.setPixmap( self.drawPreviewColor(self.lastColorUsed, 36, 36)) # Theme combo self.ui.comboTheme.addItems(Globals().availableThemes) #### #### Read config #### tools.msgDebug(u"Reading config...", __name__) config = Config() # Enable/Disable DEBUG if config.getboolean("main", "debug") == False: tools.msgDebug("Disabling debug messages !", __name__) Globals.DEBUG = False # Get Data self.myShows = config.getShows() self.displayMyShows() self.myColors = config.getColors() self.ui.lblDefaultColor.setPixmap( self.drawPreviewColor(self.myColors['default'], 36, 36)) self.displayMyColors() if config.get("display", "type") == "Fixed": self.ui.radioDispFixedLines.setChecked(True) else: self.ui.radioDispAutoResize.setChecked(True) self.ui.spinNumPastDays.setValue( int(config.get("display", "past_days"))) self.ui.spinFixedDispLines.setValue( int(config.get("display", "lines_fixed"))) self.ui.spinMinDispLines.setValue( int(config.get("display", "lines_min"))) self.ui.spinMaxDispLines.setValue( int(config.get("display", "lines_max"))) self.ui.leditFormat.setText(config.get("display", "format")) self.refreshFormatPreview(str(self.ui.leditFormat.text())) self.ui.spinCacheExpiration.setValue( int(config.get("misc", "cache_expiration"))) self.ui.leditBrowser.setText(config.get("misc", "browser")) # Fallback code since the "theme" key was located in the [display] section # in versions < 2.1.0 try: idx = int(Globals().availableThemes.index( config.get("misc", "theme"))) except: idx = 0 self.ui.comboTheme.setCurrentIndex(idx) # Date Separator # Fallback code since the "date_separator" key doesn't exist in version < 2.1.0 try: sep = config.get("display", "date_separator") except: sep = "/" self.ui.leditDateSeparator.setText(sep) # Date Format dateFormat = config.get("display", "date_format") data = ["%" + a for a in dateFormat.split(sep)] idx = self.ui.comboDateFormat.findData(QVariant(data)) if idx == -1: idx = 0 self.ui.comboDateFormat.setCurrentIndex(idx) config.close() # Reset "Save" button state self.saveRequired(False) tools.msgDebug(u"Done!", __name__) ####################################### ## Refreshes the Format Result label ## ####################################### def refreshFormatPreview(self, text): testFormat = tools.formatEpisode(Globals().sampleEpisode, text) self.ui.lblFormatPreview.setText(u"<u><b>Preview:</b></u> %s" % testFormat) ############################################################################### ####################################################### ## Draw a preview colour surrounded by a black frame ## ####################################################### def drawPreviewColor(self, color, width, height): pixmap = QPixmap(QSize(width, height)) pixmap.fill(QColor(color)) # Draw black frame painter = QPainter() painter.begin(pixmap) painter.setPen(QPen(QColor(0x00, 0x00, 0x00))) painter.drawRect(0, 0, width - 1, height - 1) painter.end() return pixmap ############################################ ## Draw a flag surrounded by a grey frame ## ############################################ def drawFlag(self, flag): flagFile = ":/images/flags/images/flags/%s.gif" % flag if not QFile().exists( flagFile ): # If we don't have the icon, substitute with "blank.gif" iconFile = ":/images/flags/images/flags/blank.gif" pixmapFlag = QPixmap(flagFile) pixmap = QPixmap(QSize(pixmapFlag.width() + 2, pixmapFlag.height() + 2)) painter = QPainter() painter.begin(pixmap) painter.drawPixmap(QPoint(1, 1), pixmapFlag) painter.setPen(QPen(QColor(0x77, 0x77, 0x77))) painter.drawRect(0, 0, pixmapFlag.width() + 1, pixmapFlag.height() + 1) painter.end() return QIcon(pixmap) # Return a QIcon() suitable for QListWidgetItem() ########################### ## Find a show on tvrage ## ########################### def lookupShow(self): # Change button... btnOldText = self.ui.btnLookup.text() self.ui.btnLookup.setEnabled(False) self.ui.btnLookup.setText(u"Fetching...") self.repaint() qApp.processEvents() # Make request keyword = self.ui.leditLookup.text().toUtf8() parser = TvRage() self.searchResults = parser.search(keyword) # Display the results self.displaySearchResults() # Restore button self.ui.btnLookup.setEnabled(True) self.ui.btnLookup.setText(btnOldText) self.ui.btnLookup.setChecked(False) ################################# ## Displays the search results ## ################################# def displaySearchResults(self): # Clear the list and enable various widgets self.ui.listSearchResults.clear() self.ui.lblResultsDisplayed.setEnabled(True) self.ui.chkbxFilter.setEnabled(True) # Find displayable shows self.dispSearchResults = [] if self.ui.chkbxFilter.checkState() == Qt.Unchecked: self.dispSearchResults = self.searchResults else: for show in self.searchResults: if show["year_end"] == "????": self.dispSearchResults.append(show) # If there are no results... if len(self.dispSearchResults) == 0: self.ui.listSearchResults.setEnabled(False) if len(self.searchResults) == 0: self.ui.listSearchResults.addItem(u"No results found!") self.ui.chkbxFilter.setEnabled(False) else: self.ui.listSearchResults.addItem( u"Results found but none to display!") self.ui.btnShowAdd.setEnabled(False) else: self.ui.listSearchResults.setEnabled(True) self.ui.lblResultsDisplayed.setText( u"Displayed results: %d/%d" % (len(self.dispSearchResults), len(self.searchResults))) # Proceed with display listIdx = 0 showLines = [] for show in self.dispSearchResults: showLines.append(listIdx) showLines[listIdx] = QListWidgetItem(self.ui.listSearchResults) showLines[listIdx].setIcon(self.drawFlag(show["flag"])) showLines[listIdx].setData( Qt.UserRole, QVariant(listIdx)) # Used for Drag n' Drop font = showLines[listIdx].font() if show["year_end"] == "????": font.setBold(True) showLines[listIdx].setText(u"%s" % show["name"]) showLines[listIdx].setForeground( QBrush(QColor(0x00, 0x00, 0x00))) showLines[listIdx].setToolTip( "<b>%s</b><br /><b><u>Status:</u></b> Running since %s" % (show["name"], show["year_begin"])) else: font.setItalic(True) showLines[listIdx].setText( u"%s [%s-%s]" % (show["name"], show["year_begin"], show["year_end"])) showLines[listIdx].setForeground( QBrush(QColor(0x55, 0x55, 0x55))) showLines[listIdx].setToolTip( "<b>%s</b><br /><b><u>Status:</u></b> Ended" % show["name"]) showLines[listIdx].setFont(font) listIdx += 1 ################################# ## Adds the show to "My Shows" ## ################################# def addToMyShows(self, index): # Restore the cursor in case we're dropping an item and a messagebox appears QApplication.changeOverrideCursor(Qt.ArrowCursor) selectedShow = self.dispSearchResults[index] # Make sure the requested show isn't already tracked # For that, check the id (which is unique) checkShow = [ item['id'] for item in self.myShows if item['id'] == selectedShow['id'] ] if selectedShow['id'] in checkShow: tools.msgDebug(u"""Show already in "My Shows". Can't add!""", __name__) QMessageBox().information( self, "Information", 'Cannot add "%s".\n' % selectedShow['name'] + 'This show is already tracked.', QMessageBox.Ok) return # Tell the user if the show is terminated if selectedShow['year_end'] != "????": yesno = QMessageBox().question( self, "Attention", '"%s" seem to be terminated.\n' % selectedShow['name'] + "Adding it to your list would be pointless.\n\n" + "Are you sure you still want to continue?", QMessageBox.Yes, QMessageBox.No) if yesno == QMessageBox().No: return # Add the show to our list self.myShows.append(selectedShow) # Sort the shows by names self.myShows = tools.sortShowsByName(self.myShows) # Need to save... self.saveRequired() ################################################# ## REMOVEME ################################################# #wct = TestConf( self.myShows ) #wct.start() ################################################# # Refresh list self.displayMyShows() ######################################## ## Remove a show from "My Shows" list ## ######################################## def removeFromMyShows(self, index): selectedShow = self.myShows[index] # Ask user before deletion yesno = QMessageBox().question( self, "Attention", 'Are you sure you want to remove "%s" ?' % selectedShow['name'], QMessageBox.Yes, QMessageBox.No) if yesno == QMessageBox().No: return # So be it... tmpMyShows = [] for show in self.myShows: if show['id'] != selectedShow['id']: tmpMyShows.append(show) self.myShows = tmpMyShows # Need to save... self.saveRequired() # Refresh List self.displayMyShows() ################################### ## Refreshes the "My Shows" list ## ################################### def displayMyShows(self): # Clear the list self.ui.listMyShows.clear() # If the list is empty... if len(self.myShows) == 0: self.ui.btnShowRemove.setEnabled(False) self.ui.listMyShows.setEnabled(False) else: self.ui.listMyShows.setEnabled(True) # Display our tracked shows listIdx = 0 showLines = [] for show in self.myShows: showLines.append(listIdx) showLines[listIdx] = QListWidgetItem(self.ui.listMyShows) #showLines[listIdx].setText( u"[%s-%s] %s" % ( show["year_begin"], show["year_end"], show["name"] ) ) showLines[listIdx].setText(u"%s" % show["name"]) showLines[listIdx].setIcon(self.drawFlag(show["flag"])) showLines[listIdx].setData( Qt.UserRole, QVariant(listIdx)) # Used for Drag n' Drop font = showLines[listIdx].font() if show["year_end"] == "????": font.setBold(True) showLines[listIdx].setForeground( QBrush(QColor(0x00, 0x00, 0x00))) showLines[listIdx].setToolTip(u"Show still running...") else: font.setItalic(True) showLines[listIdx].setForeground( QBrush(QColor(0x55, 0x55, 0x55))) showLines[listIdx].setToolTip( u"%s ended in %d!" % (show['name'], int(show["year_end"]))) showLines[listIdx].setFont(font) listIdx += 1 # Refresh Tracked shows count self.ui.lblTrackedShows.setText(u"Tracked shows: %d" % len(self.myShows)) ####################################### ## Add selected color to "My Colors" ## ####################################### def addToMyColors(self): if self.ui.radioSingleDay.isChecked(): rangeStart = self.ui.spinColorsSingleDay.value() rangeStop = rangeStart else: rangeStart = self.ui.spinColorsFrom.value() rangeStop = self.ui.spinColorsTo.value() # Just keep the ranges (excluding color names) chkRanges = [(range[0], range[1]) for range in self.myColors['ranges']] # Append our new range chkRanges.append((rangeStart, rangeStop)) # if True, ranges are overlapping (baaaad) if tools.checkRangeOverlap(chkRanges): if rangeStop == rangeStart: message = u"Overlapping detected.\nCannot add color for that day." else: message = u"Overlapping ranges detected (%d → %d).\nCannot add color for the specified range." % ( rangeStart, rangeStop) QMessageBox().information(self, "Information", message, QMessageBox.Ok) return # Looks like everything went fine... Adding new color... self.myColors['ranges'].append( (rangeStart, rangeStop, self.lastColorUsed)) # ...and sort everything self.myColors['ranges'] = tools.sortColorsByRange( self.myColors['ranges']) # Display colors self.displayMyColors() # Need to save self.saveRequired() ################## ## Remove color ## ################## def removeFromMyColors(self, index): selectedColor = self.myColors['ranges'][index] rangeStart, rangeStop, selColor = selectedColor # Ask user before deletion yesno = QMessageBox().question( self, "Attention", 'Are you sure you want to remove this color ?', QMessageBox.Yes, QMessageBox.No) if yesno == QMessageBox().No: return # So be it... tmpMyColors = [] for color in self.myColors['ranges']: if color[0] != rangeStart and color[1] != rangeStop: tmpMyColors.append(color) self.myColors['ranges'] = tmpMyColors # Need to save... self.saveRequired() # Refresh List self.displayMyColors() ######################### ## Display "My Colors" ## ######################### def displayMyColors(self): # Clear the list self.ui.listMyColors.clear() # If the list is empty... if len(self.myColors['ranges']) == 0: self.ui.btnColorRemove.setEnabled(False) self.ui.listMyColors.setEnabled(False) else: self.ui.listMyColors.setEnabled(True) # Display My colors listIdx = 0 colorLines = [] for color in self.myColors['ranges']: if color[0] == color[1]: text = u"Day: %d" % color[0] else: text = u"Days: %d → %d" % (color[0], color[1]) colorLines.append(listIdx) colorLines[listIdx] = QListWidgetItem(self.ui.listMyColors) colorLines[listIdx].setText(text) icon = QIcon(self.drawPreviewColor(color[2], 16, 16)) colorLines[listIdx].setIcon(icon) colorLines[listIdx].setData( Qt.UserRole, QVariant(listIdx)) # Used for Drag n' Drop listIdx += 1 ########################## ## Populate Date Format ## ########################## def populateDateFormat(self, sep="/"): # Store current index idx = self.ui.comboDateFormat.currentIndex() self.ui.comboDateFormat.clear() self.ui.comboDateFormat.setEnabled(True) self.ui.comboDateFormat.addItem("DD" + sep + "MM" + sep + "YY", QVariant(["%%d", "%%m", "%%y"])) self.ui.comboDateFormat.addItem("MM" + sep + "DD" + sep + "YY", QVariant(["%%m", "%%d", "%%y"])) self.ui.comboDateFormat.addItem("YY" + sep + "MM" + sep + "DD", QVariant(["%%y", "%%m", "%%d"])) self.ui.comboDateFormat.addItem("YY" + sep + "DD" + sep + "MM", QVariant(["%%y", "%%d", "%%m"])) self.ui.comboDateFormat.setCurrentIndex(idx) ##################################### ## Data were changed! Need to save ## ##################################### def saveRequired(self, state=True): if state == True: self.modifFlag = True self.ui.btnSave.setEnabled(True) #tools.msgDebug(u"Changes made, need to save...", __name__) else: self.modifFlag = False self.ui.btnSave.setEnabled(False) #tools.msgDebug(u"Save state reset!", __name__) ################# ## Save Config ## ################# #def saveConfig(self, dummy): # Changed because of crashes with Debian/Kubuntu def saveConfig(self): self.saveRequired(False) # Reset save button state # Disable quit button self.ui.btnQuit.setEnabled(False) # Save button icon & text s_btnIcon = self.ui.btnSave.icon() s_btnText = self.ui.btnSave.text() self.ui.btnSave.setText(u"Saving...") self.ui.btnSave.setIcon(QIcon()) self.repaint() qApp.processEvents() tools.msgDebug(u"Saving configuration...", __name__) config = Config() # Save Data config.setShows(self.myShows) config.setColors(self.myColors) if self.ui.radioDispFixedLines.isChecked(): value = "Fixed" else: value = "Automatic" config.set("display", "type", value) config.set("display", "past_days", str(self.ui.spinNumPastDays.value())) config.set("display", "lines_fixed", str(self.ui.spinFixedDispLines.value())) config.set("display", "lines_min", str(self.ui.spinMinDispLines.value())) config.set("display", "lines_max", str(self.ui.spinMaxDispLines.value())) config.set("display", "format", str(self.ui.leditFormat.text())) sep = self.ui.leditDateSeparator.text() list = self.ui.comboDateFormat.itemData( self.ui.comboDateFormat.currentIndex()).toStringList() dateFormat = list.join(sep) config.set("display", "date_separator", str(sep)) config.set("display", "date_format", str(dateFormat)) config.set("misc", "cache_expiration", str(self.ui.spinCacheExpiration.value())) config.set("misc", "browser", str(self.ui.leditBrowser.text())) config.set("misc", "theme", str(self.ui.comboTheme.currentText())) # Set this so that the widget knows something changed config.set("main", "config_changed", "True") tools.msgDebug(u"Saving done!", __name__) config.close() # Destroy Config() # Restore buttons self.ui.btnSave.setIcon(s_btnIcon) self.ui.btnSave.setText(s_btnText) self.ui.btnQuit.setEnabled(True)
class NextShowsConfig(QDialog): def __init__(self, parent=None): #### Attributes self.searchResults = [] # Returned search results self.dispSearchResults = [] # Displayable search results self.myShows = [] # My Tracked Shows self.myColors = {} # My custom colors self.myColors['default'] = "" self.myColors['ranges'] = [] # self.modifFlag = False # Set to True if modifications were made # #self.lastColorUsed = QColor( 0xFF, 0xFF, 0xFF ) self.lastColorUsed = "#FFFFFF" # self.desktopSize = QDesktopWidget().screenGeometry() # Holds the desktop's Size (QRect) self.uiHelpDialogGeometry = QRect() # Holds the Format Help Window's Geometry (QRect) self.uiHelpDialogSize = QSize() # Holds the Format Help Window's Size (QSize) #### Init UI QDialog.__init__(self, parent) self.ui = Ui_NextShowsConfig() self.ui.setupUi(self) # Setup UI #### Drag n' Drop support self.ui.listSearchResults.setAcceptDrags(True) self.ui.listMyShows.setAcceptDrags(True) self.ui.listMyShows.setAcceptDrops(True) self.ui.listMyColors.setAcceptDrags(True) QObject.connect( self.ui.listMyShows, SIGNAL("dropReceived"), self.addToMyShows ) QObject.connect( self.ui.btnShowRemove, SIGNAL("dropReceived"), self.removeFromMyShows ) QObject.connect( self.ui.btnColorRemove, SIGNAL("dropReceived"), self.removeFromMyColors ) #### Initialize form (read config, set labels, etc...) self.initForm() #### Inititialize Format Help Dialog self.uiHelpDialog = FormatHelp() self.uiHelpDialog.setWindowFlags( Qt.Window ) self.uiHelpDialogSize = QSize( self.uiHelpDialog.width(), self.uiHelpDialog.height() ) self.uiHelpDialog.setMinimumSize( self.uiHelpDialogSize ) # Fix the size (ugly hack) self.uiHelpDialog.setMaximumSize( self.uiHelpDialogSize ) # Fix the size (ugly hack) #### Signals / Slots QObject.connect( self.ui.btnLookup, SIGNAL("clicked()"), self.lookupShow ) QObject.connect( self.uiHelpDialog, SIGNAL("hideWindow()"), self.resetBtnFormatInfos ) QObject.connect( self.ui.btnQuit, SIGNAL("clicked()"), self, SLOT("close()") ) #### Make sure the first tabs are shown when we 1st launch the GUI self.ui.tabWidgetWidget.setCurrentIndex(0) self.ui.tabWidget.setCurrentIndex(0) ########################################################################### ## REACT TO USER INTERACTIONS ## ########################################################################### #### "Shows" Tab # Text Changed in Lookup QLineEdit @pyqtSignature("on_leditLookup_textChanged(const QString &)") def on_leditLookup_textChanged(self, qstring): text = str( qstring.toUtf8() ) if text != "": self.ui.btnLookup.setEnabled(True) self.ui.btnLookup.setDefault(True) else: self.ui.btnLookup.setEnabled(False) self.ui.btnLookup.setDefault(False) # Click on "Clear Text" @pyqtSignature("on_btnLeditLookupClear_clicked()") def on_btnLeditLookupClear_clicked(self): self.ui.leditLookup.setText(u"") # Item on the search results selected @pyqtSignature("on_listSearchResults_currentRowChanged(int)") def on_listSearchResults_currentRowChanged(self, rowNum): if rowNum == -1: return self.ui.btnShowAdd.setEnabled( True ) # Item double-clicked or add button clicked @pyqtSignature("on_listSearchResults_activated(const QModelIndex &)") def on_listSearchResults_activated(self, modelIndex): self.addToMyShows( modelIndex.row() ) @pyqtSignature("on_btnShowAdd_clicked()") def on_btnShowAdd_clicked(self): self.addToMyShows( self.ui.listSearchResults.currentRow() ) # Item on my shows selected @pyqtSignature("on_listMyShows_currentRowChanged(int)") def on_listMyShows_currentRowChanged(self, rowNum): if rowNum == -1: return self.ui.btnShowRemove.setEnabled( True ) # "My Shows" item double-clicked or remove button clicked @pyqtSignature("on_listMyShows_activated(const QModelIndex &)") def on_listMyShows_activated(self, modelIndex): self.removeFromMyShows( modelIndex.row() ) @pyqtSignature("on_btnShowRemove_clicked()") def on_btnShowRemove_clicked(self): self.removeFromMyShows( self.ui.listMyShows.currentRow() ) # Filter state changed @pyqtSignature("on_chkbxFilter_stateChanged(int)") def on_chkbxFilter_stateChanged(self, state): self.displaySearchResults() #### "Widget" Tab #### "Widget"->"Display" Tab # Past days value changed @pyqtSignature("on_spinNumPastDays_valueChanged(int)") def on_spinNumPastDays_valueChanged(self, value): # Need to save self.saveRequired() # Click on Fixed Size radio @pyqtSignature("on_radioDispFixedLines_toggled(bool)") def on_radioDispFixedLines_toggled(self, checked): if checked: # Enable Fixed Size self.ui.lblFixedDispLines.setEnabled(True) self.ui.spinFixedDispLines.setEnabled(True) else: # Disable Fixed Size self.ui.lblFixedDispLines.setEnabled(False) self.ui.spinFixedDispLines.setEnabled(False) # Need to save self.saveRequired() # Fixed lines value changed @pyqtSignature("on_spinFixedDispLines_valueChanged(int)") def on_spinFixedDispLines_valueChanged(self, value): # Need to save self.saveRequired() # Click on Automatic Resize radio @pyqtSignature("on_radioDispAutoResize_toggled(bool)") def on_radioDispAutoResize_toggled(self, checked): if checked: # Enable Automatic Size self.ui.lblMinDispLines.setEnabled(True) self.ui.lblMaxDispLines.setEnabled(True) self.ui.spinMinDispLines.setEnabled(True) self.ui.spinMaxDispLines.setEnabled(True) else: # Disable Automatic Size self.ui.lblMinDispLines.setEnabled(False) self.ui.lblMaxDispLines.setEnabled(False) self.ui.spinMinDispLines.setEnabled(False) self.ui.spinMaxDispLines.setEnabled(False) # Need to save self.saveRequired() # MinDispLines Changed @pyqtSignature("on_spinMinDispLines_valueChanged(int)") def on_spinMinDispLines_valueChanged(self, newValue): currentMaxValue = self.ui.spinMaxDispLines.value() maxMaxValue = self.ui.spinMaxDispLines.maximum() if newValue >= currentMaxValue: if currentMaxValue < maxMaxValue: self.ui.spinMaxDispLines.setValue( newValue+1 ) else: self.ui.spinMinDispLines.setValue( newValue-1 ) # Need to save self.saveRequired() # MaxDispLines Changed @pyqtSignature("on_spinMaxDispLines_valueChanged(int)") def on_spinMaxDispLines_valueChanged(self, newValue): currentMinValue = self.ui.spinMinDispLines.value() minMinValue = self.ui.spinMinDispLines.minimum() if newValue <= currentMinValue: if currentMinValue > minMinValue: self.ui.spinMinDispLines.setValue( newValue-1 ) else: self.ui.spinMaxDispLines.setValue( newValue+1 ) # Need to save self.saveRequired() # Date Separator Changed @pyqtSignature("on_leditDateSeparator_editingFinished()") def on_leditDateSeparator_editingFinished(self): if not self.ui.leditDateSeparator.text() or self.ui.leditDateSeparator.text() == "%": self.ui.leditDateSeparator.setText("/") @pyqtSignature("on_leditDateSeparator_textChanged(const QString &)") def on_leditDateSeparator_textChanged(self, QString): if not self.ui.leditDateSeparator.text() or self.ui.leditDateSeparator.text() == "%": self.ui.comboDateFormat.clear() self.ui.comboDateFormat.addItem("INVALID SEPARATOR") self.ui.comboDateFormat.setEnabled( False ) else: self.populateDateFormat( QString ) # Need to save self.saveRequired() # Date Format Changed @pyqtSignature("on_comboDateFormat_currentIndexChanged(int)") def on_comboDateFormat_currentIndexChanged(self, idx): # Need to save self.saveRequired() # Click on checkable Format Info Button @pyqtSignature("on_btnFormatInfos_clicked()") def on_btnFormatInfos_clicked(self): # If this is the 1st time we ask for the Help Window # compute its geometry (relative to the main window) if not self.uiHelpDialogGeometry.isValid(): # Y pos yPos = self.pos().y() + ( ( self.height() - self.uiHelpDialogSize.height() ) / 2 ) # Choose the best pos (Left or Right) depending of the main window pos coordsRight = self.desktopSize.width() - ( self.pos().x() + self.width() ) if coordsRight > self.pos().x(): xPos = self.pos().x() + self.width() else: xPos = self.pos().x() - self.uiHelpDialogSize.width() self.uiHelpDialogGeometry = QRect( xPos, yPos, self.uiHelpDialogSize.width(), self.uiHelpDialogSize.height() ) if self.ui.btnFormatInfos.isChecked(): self.uiHelpDialog.setGeometry( self.uiHelpDialogGeometry ) self.uiHelpDialog.show() else: self.uiHelpDialogGeometry = self.uiHelpDialog.geometry() self.uiHelpDialog.hide() # Format text changed @pyqtSignature("on_leditFormat_textChanged(const QString &)") def on_leditFormat_textChanged(self, QString): text = str( QString ) self.refreshFormatPreview(text) # Need to save self.saveRequired() # Resets the button state if help window is closed def resetBtnFormatInfos(self): self.ui.btnFormatInfos.setChecked(False) self.on_btnFormatInfos_clicked() #### "Widget"->"Colors" tab # Set Default Color clicked @pyqtSignature("on_btnSetDefaultColor_clicked()") def on_btnSetDefaultColor_clicked(self): selColor = QColorDialog.getColor(QColor(self.myColors['default']), self) if not selColor.isValid(): tools.msgDebug(u"Canceled by user!", __name__) return tools.msgDebug( u"Selected color: #%02X%02X%02X" % ( selColor.red(), selColor.green(), selColor.blue() ), __name__ ) self.ui.lblDefaultColor.setPixmap( self.drawPreviewColor( selColor, 36, 36 ) ) self.myColors['default'] = str( selColor.name() ) # Need to save self.saveRequired() # Select Color clicked @pyqtSignature("on_btnSelectColor_clicked()") def on_btnSelectColor_clicked(self): selColor = QColorDialog.getColor(QColor(self.lastColorUsed), self) if not selColor.isValid(): tools.msgDebug(u"Canceled by user!", __name__) return tools.msgDebug( u"Selected color: #%02X%02X%02X" % ( selColor.red(), selColor.green(), selColor.blue() ), __name__ ) self.ui.lblSelectColor.setPixmap( self.drawPreviewColor( selColor, 36, 36 ) ) self.lastColorUsed = str( selColor.name() ) # Click on Single Day radio @pyqtSignature("on_radioSingleDay_toggled(bool)") def on_radioSingleDay_toggled(self, checked): if checked: # Enable Single Day self.ui.lblColorsDay.setEnabled(True) self.ui.spinColorsSingleDay.setEnabled(True) else: # Disable Single Day self.ui.lblColorsDay.setEnabled(False) self.ui.spinColorsSingleDay.setEnabled(False) # Click on Automatic Resize radio @pyqtSignature("on_radioDayRange_toggled(bool)") def on_radioDayRange_toggled(self, checked): if checked: # Enable Range self.ui.lblColorsFrom.setEnabled(True) self.ui.lblColorsTo.setEnabled(True) self.ui.spinColorsFrom.setEnabled(True) self.ui.spinColorsTo.setEnabled(True) else: # Disable Range self.ui.lblColorsFrom.setEnabled(False) self.ui.lblColorsTo.setEnabled(False) self.ui.spinColorsFrom.setEnabled(False) self.ui.spinColorsTo.setEnabled(False) # Range From @pyqtSignature("on_spinColorsFrom_editingFinished()") def on_spinColorsFrom_editingFinished(self): fromValue = self.ui.spinColorsFrom.value() toValue = self.ui.spinColorsTo.value() maxToValue = self.ui.spinColorsTo.maximum() if fromValue >= toValue: if toValue < maxToValue: self.ui.spinColorsTo.setValue( fromValue+1 ) else: self.ui.spinColorsFrom.setValue( fromValue-1 ) # Range To @pyqtSignature("on_spinColorsTo_editingFinished()") def on_spinColorsTo_editingFinished(self): fromValue = self.ui.spinColorsFrom.value() toValue = self.ui.spinColorsTo.value() minFromValue = self.ui.spinColorsFrom.minimum() if toValue <= fromValue: if fromValue > minFromValue: self.ui.spinColorsFrom.setValue( toValue-1 ) else: self.ui.spinColorsTo.setValue( toValue+1 ) # Item on my colors selected @pyqtSignature("on_listMyColors_currentRowChanged(int)") def on_listMyColors_currentRowChanged(self, rowNum): if rowNum == -1: return self.ui.btnColorRemove.setEnabled( True ) rangeStart, rangeStop, color = self.myColors['ranges'][rowNum] if rangeStart == rangeStop: self.ui.radioSingleDay.setChecked( True ) self.ui.spinColorsSingleDay.setValue( rangeStart ) else: self.ui.radioDayRange.setChecked( True ) self.ui.spinColorsFrom.setValue( rangeStart ) self.ui.spinColorsTo.setValue( rangeStop ) self.lastColorUsed = color self.ui.lblSelectColor.setPixmap( self.drawPreviewColor( self.lastColorUsed, 36, 36 ) ) # Color Add clicked @pyqtSignature("on_btnColorAdd_clicked()") def on_btnColorAdd_clicked(self): self.ui.spinColorsFrom.clearFocus() self.ui.spinColorsTo.clearFocus() self.addToMyColors() # "My colors" item double-clicked or remove button clicked @pyqtSignature("on_listMyColors_activated(const QModelIndex &)") def on_listMyColors_activated(self, modelIndex): self.removeFromMyColors( modelIndex.row() ) @pyqtSignature("on_btnColorRemove_clicked()") def on_btnColorRemove_clicked(self): self.removeFromMyColors( self.ui.listMyColors.currentRow() ) #### "Widget"->"Misc" tab # Cache expiration time changed @pyqtSignature("on_spinCacheExpiration_valueChanged(int)") def on_spinCacheExpiration_valueChanged(self, newValue): # Need to save self.saveRequired() # Text Changed in Browser @pyqtSignature("on_leditBrowser_textChanged(const QString &)") def on_leditBrowser_textChanged(self, qstring): # Need to save self.saveRequired() # Theme changed @pyqtSignature("on_comboTheme_currentIndexChanged(int)") def on_comboTheme_currentIndexChanged(self, idx): # Need to save self.saveRequired() #### General # Save button clicked @pyqtSignature("on_btnSave_clicked()") def on_btnSave_clicked(self): # import thread # thread.start_new_thread( self.saveConfig, ("",) ) self.saveConfig() # React to close event def closeEvent(self, event): if self.modifFlag: yesno = QMessageBox().question(self, "Attention", "Changes were made!\n" + "Are you sure you want to quit without saving?", QMessageBox.Yes, QMessageBox.No) if yesno == QMessageBox().No: event.ignore() return # User wants to quit # Make sure Config() isn't opened self.hide() self.uiHelpDialog.hide() while Config.LOCK: tools.msgDebug(u"Waiting for config to be written before exiting...", __name__) time.sleep(0.2) tools.msgDebug(u"Exiting...", __name__) ############################################################################### ############################################# ## Fills the form with the relevant values ## ############################################# def initForm(self): # 1st tab labels self.ui.lblResultsDisplayed.setText( u"Displayed results: 0/0" ) self.ui.lblTrackedShows.setText( u"Tracked shows: 0" ) # Format Sample fmtSample = u"<u><b>Sample:</b></u> <b>show:</b> %s, <b>title:</b> %s, <b>season</b>: %d, <b>episode</b>: %d" % ( Globals().sampleEpisode['show'], Globals().sampleEpisode['title'], Globals().sampleEpisode['season'], Globals().sampleEpisode['episode'] ) self.ui.lblFormatSample.setText( fmtSample ) #### Versions version = Globals().versions # nextShows Footer Release labelContent=str(self.ui.lblFooterRelease.text()) self.ui.lblFooterRelease.setText(labelContent % version['nextShows']) # nextShows Release (About tab) labelContent=str(self.ui.lblNextShowsVersion.text()) self.ui.lblNextShowsVersion.setText(labelContent % version['nextShows']) # Libs releases (About tab) # Python version a,b,c,d,e = sys.version_info pythonVersion = "%d.%d.%d" % (a, b, c) # labelContent=str(self.ui.lblLibsVersion.text()) self.ui.lblLibsVersion.setText(labelContent % ( pythonVersion, QT_VERSION_STR, PYQT_VERSION_STR, version["KDE"]) ) #### Default values self.ui.spinNumPastDays.setMinimum(0) self.ui.spinNumPastDays.setMaximum(99) #self.ui.spinNumPastDays.setValue(1) self.ui.spinFixedDispLines.setMinimum(1) self.ui.spinFixedDispLines.setMaximum(50) #self.ui.spinFixedDispLines.setValue(10) self.ui.spinMinDispLines.setMinimum(1) self.ui.spinMinDispLines.setMaximum(49) #self.ui.spinMinDispLines.setValue(1) self.ui.spinMaxDispLines.setMinimum(2) self.ui.spinMaxDispLines.setMaximum(50) #self.ui.spinMaxDispLines.setValue(10) # self.ui.spinColorsSingleDay.setMinimum(-99) self.ui.spinColorsSingleDay.setMaximum(99) self.ui.spinColorsSingleDay.setValue(0) self.ui.spinColorsFrom.setMinimum(-99) self.ui.spinColorsFrom.setMaximum(98) self.ui.spinColorsFrom.setValue(0) self.ui.spinColorsTo.setMinimum(-98) self.ui.spinColorsTo.setMaximum(99) self.ui.spinColorsTo.setValue(10) # default color for "Select color" self.ui.lblSelectColor.setPixmap( self.drawPreviewColor( self.lastColorUsed, 36, 36 ) ) # Theme combo self.ui.comboTheme.addItems( Globals().availableThemes ) #### #### Read config #### tools.msgDebug(u"Reading config...", __name__) config = Config() # Enable/Disable DEBUG if config.getboolean("main", "debug") == False: tools.msgDebug("Disabling debug messages !", __name__) Globals.DEBUG = False # Get Data self.myShows = config.getShows() self.displayMyShows() self.myColors = config.getColors() self.ui.lblDefaultColor.setPixmap( self.drawPreviewColor( self.myColors['default'], 36, 36 ) ) self.displayMyColors() if config.get("display", "type") == "Fixed": self.ui.radioDispFixedLines.setChecked( True ) else: self.ui.radioDispAutoResize.setChecked( True ) self.ui.spinNumPastDays.setValue( int( config.get( "display", "past_days" ) ) ) self.ui.spinFixedDispLines.setValue( int( config.get( "display", "lines_fixed" ) ) ) self.ui.spinMinDispLines.setValue( int( config.get( "display", "lines_min" ) ) ) self.ui.spinMaxDispLines.setValue( int( config.get( "display", "lines_max" ) ) ) self.ui.leditFormat.setText( config.get( "display", "format" ) ) self.refreshFormatPreview( str(self.ui.leditFormat.text()) ) self.ui.spinCacheExpiration.setValue( int( config.get( "misc", "cache_expiration" ) ) ) self.ui.leditBrowser.setText( config.get( "misc", "browser" ) ) # Fallback code since the "theme" key was located in the [display] section # in versions < 2.1.0 try: idx = int( Globals().availableThemes.index( config.get( "misc", "theme" ) ) ) except: idx = 0 self.ui.comboTheme.setCurrentIndex( idx ) # Date Separator # Fallback code since the "date_separator" key doesn't exist in version < 2.1.0 try: sep = config.get( "display", "date_separator" ) except: sep = "/" self.ui.leditDateSeparator.setText( sep ) # Date Format dateFormat = config.get( "display", "date_format" ) data = [ "%"+a for a in dateFormat.split( sep ) ] idx = self.ui.comboDateFormat.findData( QVariant( data ) ) if idx==-1: idx = 0 self.ui.comboDateFormat.setCurrentIndex( idx ) config.close() # Reset "Save" button state self.saveRequired(False) tools.msgDebug(u"Done!", __name__) ####################################### ## Refreshes the Format Result label ## ####################################### def refreshFormatPreview(self, text): testFormat = tools.formatEpisode( Globals().sampleEpisode, text ) self.ui.lblFormatPreview.setText( u"<u><b>Preview:</b></u> %s" % testFormat ) ############################################################################### ####################################################### ## Draw a preview colour surrounded by a black frame ## ####################################################### def drawPreviewColor(self, color, width, height): pixmap = QPixmap( QSize( width, height ) ) pixmap.fill( QColor( color ) ) # Draw black frame painter = QPainter() painter.begin( pixmap ) painter.setPen( QPen( QColor( 0x00, 0x00, 0x00 ) ) ) painter.drawRect( 0, 0, width-1, height-1 ) painter.end() return pixmap ############################################ ## Draw a flag surrounded by a grey frame ## ############################################ def drawFlag(self, flag): flagFile = ":/images/flags/images/flags/%s.gif" % flag if not QFile().exists( flagFile ): # If we don't have the icon, substitute with "blank.gif" iconFile = ":/images/flags/images/flags/blank.gif" pixmapFlag = QPixmap( flagFile ) pixmap = QPixmap( QSize( pixmapFlag.width()+2, pixmapFlag.height()+2 ) ) painter = QPainter() painter.begin( pixmap ) painter.drawPixmap( QPoint( 1, 1 ), pixmapFlag ) painter.setPen( QPen( QColor( 0x77, 0x77, 0x77 ) ) ) painter.drawRect( 0, 0, pixmapFlag.width()+1, pixmapFlag.height()+1 ) painter.end() return QIcon( pixmap ) # Return a QIcon() suitable for QListWidgetItem() ########################### ## Find a show on tvrage ## ########################### def lookupShow(self): # Change button... btnOldText = self.ui.btnLookup.text() self.ui.btnLookup.setEnabled( False ) self.ui.btnLookup.setText( u"Fetching..." ) self.repaint() qApp.processEvents() # Make request keyword = self.ui.leditLookup.text().toUtf8() parser = TvRage() self.searchResults = parser.search( keyword ) # Display the results self.displaySearchResults() # Restore button self.ui.btnLookup.setEnabled( True ) self.ui.btnLookup.setText( btnOldText ) self.ui.btnLookup.setChecked( False ) ################################# ## Displays the search results ## ################################# def displaySearchResults(self): # Clear the list and enable various widgets self.ui.listSearchResults.clear() self.ui.lblResultsDisplayed.setEnabled( True ) self.ui.chkbxFilter.setEnabled( True ) # Find displayable shows self.dispSearchResults = [] if self.ui.chkbxFilter.checkState() == Qt.Unchecked: self.dispSearchResults = self.searchResults else: for show in self.searchResults: if show["year_end"] == "????": self.dispSearchResults.append(show) # If there are no results... if len(self.dispSearchResults) == 0: self.ui.listSearchResults.setEnabled( False ) if len(self.searchResults) == 0: self.ui.listSearchResults.addItem( u"No results found!" ) self.ui.chkbxFilter.setEnabled( False ) else: self.ui.listSearchResults.addItem( u"Results found but none to display!" ) self.ui.btnShowAdd.setEnabled( False ) else: self.ui.listSearchResults.setEnabled( True ) self.ui.lblResultsDisplayed.setText( u"Displayed results: %d/%d" % ( len( self.dispSearchResults ), len( self.searchResults ) ) ) # Proceed with display listIdx = 0 showLines = [] for show in self.dispSearchResults: showLines.append( listIdx ) showLines[listIdx] = QListWidgetItem( self.ui.listSearchResults ) showLines[listIdx].setIcon( self.drawFlag( show["flag"] ) ) showLines[listIdx].setData( Qt.UserRole, QVariant( listIdx ) ) # Used for Drag n' Drop font = showLines[listIdx].font() if show["year_end"] == "????": font.setBold( True ) showLines[listIdx].setText( u"%s" % show["name"] ) showLines[listIdx].setForeground( QBrush( QColor( 0x00, 0x00, 0x00 ) ) ) showLines[listIdx].setToolTip( "<b>%s</b><br /><b><u>Status:</u></b> Running since %s" % ( show["name"], show["year_begin"] ) ) else: font.setItalic( True ) showLines[listIdx].setText( u"%s [%s-%s]" % ( show["name"], show["year_begin"], show["year_end"] ) ) showLines[listIdx].setForeground( QBrush( QColor( 0x55, 0x55, 0x55 ) ) ) showLines[listIdx].setToolTip( "<b>%s</b><br /><b><u>Status:</u></b> Ended" % show["name"] ) showLines[listIdx].setFont( font ) listIdx += 1 ################################# ## Adds the show to "My Shows" ## ################################# def addToMyShows(self, index): # Restore the cursor in case we're dropping an item and a messagebox appears QApplication.changeOverrideCursor( Qt.ArrowCursor ) selectedShow = self.dispSearchResults[index] # Make sure the requested show isn't already tracked # For that, check the id (which is unique) checkShow = [ item['id'] for item in self.myShows if item['id'] == selectedShow['id']] if selectedShow['id'] in checkShow: tools.msgDebug(u"""Show already in "My Shows". Can't add!""", __name__) QMessageBox().information(self, "Information", 'Cannot add "%s".\n' % selectedShow['name'] + 'This show is already tracked.', QMessageBox.Ok) return # Tell the user if the show is terminated if selectedShow['year_end'] != "????": yesno = QMessageBox().question(self, "Attention", '"%s" seem to be terminated.\n' % selectedShow['name'] + "Adding it to your list would be pointless.\n\n" + "Are you sure you still want to continue?", QMessageBox.Yes, QMessageBox.No) if yesno == QMessageBox().No: return # Add the show to our list self.myShows.append( selectedShow ) # Sort the shows by names self.myShows = tools.sortShowsByName( self.myShows ) # Need to save... self.saveRequired() ################################################# ## REMOVEME ################################################# #wct = TestConf( self.myShows ) #wct.start() ################################################# # Refresh list self.displayMyShows() ######################################## ## Remove a show from "My Shows" list ## ######################################## def removeFromMyShows(self, index): selectedShow = self.myShows[index] # Ask user before deletion yesno = QMessageBox().question(self, "Attention", 'Are you sure you want to remove "%s" ?' % selectedShow['name'], QMessageBox.Yes, QMessageBox.No) if yesno == QMessageBox().No: return # So be it... tmpMyShows = [] for show in self.myShows: if show['id'] != selectedShow['id']: tmpMyShows.append( show ) self.myShows = tmpMyShows # Need to save... self.saveRequired() # Refresh List self.displayMyShows() ################################### ## Refreshes the "My Shows" list ## ################################### def displayMyShows(self): # Clear the list self.ui.listMyShows.clear() # If the list is empty... if len(self.myShows) == 0: self.ui.btnShowRemove.setEnabled( False ) self.ui.listMyShows.setEnabled( False ) else: self.ui.listMyShows.setEnabled( True ) # Display our tracked shows listIdx = 0 showLines = [] for show in self.myShows: showLines.append( listIdx ) showLines[listIdx] = QListWidgetItem( self.ui.listMyShows ) #showLines[listIdx].setText( u"[%s-%s] %s" % ( show["year_begin"], show["year_end"], show["name"] ) ) showLines[listIdx].setText( u"%s" % show["name"] ) showLines[listIdx].setIcon( self.drawFlag( show["flag"] ) ) showLines[listIdx].setData( Qt.UserRole, QVariant( listIdx ) ) # Used for Drag n' Drop font = showLines[listIdx].font() if show["year_end"] == "????": font.setBold( True ) showLines[listIdx].setForeground( QBrush( QColor( 0x00, 0x00, 0x00 ) ) ) showLines[listIdx].setToolTip(u"Show still running...") else: font.setItalic( True ) showLines[listIdx].setForeground( QBrush( QColor( 0x55, 0x55, 0x55 ) ) ) showLines[listIdx].setToolTip(u"%s ended in %d!" % (show['name'], int(show["year_end"]))) showLines[listIdx].setFont( font ) listIdx += 1 # Refresh Tracked shows count self.ui.lblTrackedShows.setText( u"Tracked shows: %d" % len(self.myShows) ) ####################################### ## Add selected color to "My Colors" ## ####################################### def addToMyColors(self): if self.ui.radioSingleDay.isChecked(): rangeStart = self.ui.spinColorsSingleDay.value() rangeStop = rangeStart else: rangeStart = self.ui.spinColorsFrom.value() rangeStop = self.ui.spinColorsTo.value() # Just keep the ranges (excluding color names) chkRanges = [ (range[0],range[1]) for range in self.myColors['ranges'] ] # Append our new range chkRanges.append( ( rangeStart, rangeStop ) ) # if True, ranges are overlapping (baaaad) if tools.checkRangeOverlap( chkRanges ): if rangeStop == rangeStart: message = u"Overlapping detected.\nCannot add color for that day." else: message = u"Overlapping ranges detected (%d → %d).\nCannot add color for the specified range." % (rangeStart ,rangeStop) QMessageBox().information(self, "Information", message, QMessageBox.Ok) return # Looks like everything went fine... Adding new color... self.myColors['ranges'].append( ( rangeStart, rangeStop, self.lastColorUsed ) ) # ...and sort everything self.myColors['ranges'] = tools.sortColorsByRange( self.myColors['ranges'] ) # Display colors self.displayMyColors() # Need to save self.saveRequired() ################## ## Remove color ## ################## def removeFromMyColors(self, index): selectedColor = self.myColors['ranges'][index] rangeStart, rangeStop, selColor = selectedColor # Ask user before deletion yesno = QMessageBox().question(self, "Attention", 'Are you sure you want to remove this color ?', QMessageBox.Yes, QMessageBox.No) if yesno == QMessageBox().No: return # So be it... tmpMyColors = [] for color in self.myColors['ranges']: if color[0] != rangeStart and color[1] != rangeStop: tmpMyColors.append( color ) self.myColors['ranges'] = tmpMyColors # Need to save... self.saveRequired() # Refresh List self.displayMyColors() ######################### ## Display "My Colors" ## ######################### def displayMyColors(self): # Clear the list self.ui.listMyColors.clear() # If the list is empty... if len(self.myColors['ranges']) == 0: self.ui.btnColorRemove.setEnabled( False ) self.ui.listMyColors.setEnabled( False ) else: self.ui.listMyColors.setEnabled( True ) # Display My colors listIdx = 0 colorLines = [] for color in self.myColors['ranges']: if color[0] == color[1]: text = u"Day: %d" % color[0] else: text = u"Days: %d → %d" % (color[0], color[1]) colorLines.append( listIdx ) colorLines[listIdx] = QListWidgetItem( self.ui.listMyColors ) colorLines[listIdx].setText( text ) icon = QIcon( self.drawPreviewColor( color[2], 16, 16 ) ) colorLines[listIdx].setIcon( icon ) colorLines[listIdx].setData( Qt.UserRole, QVariant( listIdx ) ) # Used for Drag n' Drop listIdx +=1 ########################## ## Populate Date Format ## ########################## def populateDateFormat(self, sep="/"): # Store current index idx = self.ui.comboDateFormat.currentIndex() self.ui.comboDateFormat.clear() self.ui.comboDateFormat.setEnabled( True ) self.ui.comboDateFormat.addItem( "DD"+sep+"MM"+sep+"YY", QVariant( [ "%%d", "%%m", "%%y" ] ) ) self.ui.comboDateFormat.addItem( "MM"+sep+"DD"+sep+"YY", QVariant( [ "%%m", "%%d", "%%y" ] ) ) self.ui.comboDateFormat.addItem( "YY"+sep+"MM"+sep+"DD", QVariant( [ "%%y", "%%m", "%%d" ] ) ) self.ui.comboDateFormat.addItem( "YY"+sep+"DD"+sep+"MM", QVariant( [ "%%y", "%%d", "%%m" ] ) ) self.ui.comboDateFormat.setCurrentIndex( idx ) ##################################### ## Data were changed! Need to save ## ##################################### def saveRequired(self, state=True): if state == True: self.modifFlag = True self.ui.btnSave.setEnabled( True ) #tools.msgDebug(u"Changes made, need to save...", __name__) else: self.modifFlag = False self.ui.btnSave.setEnabled( False ) #tools.msgDebug(u"Save state reset!", __name__) ################# ## Save Config ## ################# #def saveConfig(self, dummy): # Changed because of crashes with Debian/Kubuntu def saveConfig(self): self.saveRequired( False ) # Reset save button state # Disable quit button self.ui.btnQuit.setEnabled( False ) # Save button icon & text s_btnIcon = self.ui.btnSave.icon() s_btnText = self.ui.btnSave.text() self.ui.btnSave.setText(u"Saving...") self.ui.btnSave.setIcon(QIcon()) self.repaint() qApp.processEvents() tools.msgDebug(u"Saving configuration...", __name__) config = Config() # Save Data config.setShows( self.myShows ) config.setColors( self.myColors ) if self.ui.radioDispFixedLines.isChecked(): value = "Fixed" else: value = "Automatic" config.set( "display", "type", value ) config.set( "display", "past_days", str( self.ui.spinNumPastDays.value() ) ) config.set( "display", "lines_fixed", str( self.ui.spinFixedDispLines.value() ) ) config.set( "display", "lines_min", str( self.ui.spinMinDispLines.value() ) ) config.set( "display", "lines_max", str( self.ui.spinMaxDispLines.value() ) ) config.set( "display", "format", str( self.ui.leditFormat.text() ) ) sep = self.ui.leditDateSeparator.text() list = self.ui.comboDateFormat.itemData( self.ui.comboDateFormat.currentIndex() ).toStringList() dateFormat = list.join(sep) config.set( "display", "date_separator",str( sep ) ) config.set( "display", "date_format", str( dateFormat ) ) config.set( "misc", "cache_expiration", str( self.ui.spinCacheExpiration.value() ) ) config.set( "misc", "browser", str( self.ui.leditBrowser.text() ) ) config.set( "misc", "theme", str( self.ui.comboTheme.currentText() ) ) # Set this so that the widget knows something changed config.set( "main", "config_changed", "True" ) tools.msgDebug(u"Saving done!", __name__) config.close() # Destroy Config() # Restore buttons self.ui.btnSave.setIcon( s_btnIcon ) self.ui.btnSave.setText( s_btnText ) self.ui.btnQuit.setEnabled( True )