Exemplo n.º 1
0
class ImageToolTip(QtGui.QWidget):
    def __init__(self, parent):
        QtGui.QWidget.__init__(self, parent, QtCore.Qt.ToolTip or QtCore.Qt.BypassGraphicsProxyWidget)
    
        self.parent = parent
        
        self.waitWidget = WaitWidget(self)
        self.waitWidget.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed))
        self.waitWidget.hide()
        
        self.imageLabel = QtGui.QLabel(self)
        self.imageLabel.hide()
        
        self.dummyWidget = QtGui.QLabel("n/a", self)
        self.dummyWidget.hide()
        
        self.layout = QtGui.QVBoxLayout(self)    
        self.layout.setAlignment(QtCore.Qt.AlignHCenter or QtCore.Qt.AlignVCenter)
        self.setLayout(self.layout)
        
        self.hideTimer = QtCore.QTimer(self)
        self.hideTimer.timeout.connect(self.OnTimer)
        self.hideTimer.setSingleShot(True)
        
        QtCore.QCoreApplication.instance().installEventFilter(self)
        
        self.ShowWaitWidget()
                
    def eventFilter(self, obj, event):       
        if (event.type() == QtCore.QEvent.WindowActivate 
        or event.type() == QtCore.QEvent.WindowDeactivate
        or event.type() == QtCore.QEvent.FocusIn
        or event.type() == QtCore.QEvent.FocusOut
        or event.type() == QtCore.QEvent.MouseButtonPress
        or event.type() == QtCore.QEvent.MouseButtonRelease
        or event.type() == QtCore.QEvent.MouseButtonDblClick
        or event.type() == QtCore.QEvent.Wheel):
            self.hideTipImmediately()
        
        if event.type() == QtCore.QEvent.Leave:
            self.hideTip()
            
        return False
    
    def showTip(self, pos, pixmap = None):
        self.SetPixmap(pixmap)
        self.hideTimer.stop()
        self.move(pos + QtCore.QPoint(2, 21))
        self.show()
        
    def hideTip(self):
        if not self.hideTimer.isActive():
            self.hideTimer.start(300)
            
    def hideTipImmediately(self):
        self.hideTimer.stop()
        self.hide()
            
    def OnTimer(self):
        self.hideTipImmediately()
        
    def SetWidget(self, widget):
        if self.layout.count() > 1:
            print("suspicious layout items count")
            return
        
        if self.layout.count() != 0:
            if self.layout.itemAt(0).widget() == widget: return
            else:
                self.layout.itemAt(0).widget().hide()
                self.layout.removeWidget(self.layout.itemAt(0).widget())

        self.layout.addWidget(widget)
        widget.show()
        self.layout.layout()
        
    def ShowWaitWidget(self):
        self.SetWidget(self.waitWidget)
        self.waitWidget.Start()

    def ShowImageWidget(self, pixmap):
        self.imageLabel.setPixmap(pixmap)
        self.SetWidget(self.imageLabel)
        self.waitWidget.Stop()
        
    def ShowDummyWidget(self):
        self.SetWidget(self.dummyWidget)
        self.waitWidget.Stop()

    def SetPixmap(self, pixmap):
        if pixmap is None: self.ShowWaitWidget()
        elif pixmap.isNull(): self.ShowDummyWidget()
        else: self.ShowImageWidget(pixmap)
            
    def paintEvent(self, event):
        options = QtGui.QStyleOptionFrame()
        options.initFrom(self)
        
        painter = QtGui.QStylePainter()
        
        painter.begin(self)
        painter.drawPrimitive(QtGui.QStyle.PE_PanelTipLabel, options)
        painter.end()
Exemplo n.º 2
0
class MainForm(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)

        self.CreateToolBar()
        self.CreateStatusBar()
        self.CreateToolTip()

        self.removeAction.setEnabled(False)
        self.editAction.setEnabled(False)
        
        self.itemModel = ItemModel()
        self.itemSelectionModel = QtGui.QItemSelectionModel(self.itemModel)
        
        self.listView = QtGui.QTreeView(self)
        self.listView.setModel(self.itemModel)
        self.listView.setSelectionModel(self.itemSelectionModel)
        
        self.listView.setRootIsDecorated(False)
        self.listView.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.listView.setColumnWidth(self.itemModel.countryColumn(), 20)
        self.listView.setColumnWidth(self.itemModel.asinColumn(), 100)
        self.listView.setColumnWidth(self.itemModel.labelColumn(), 210)
        self.listView.setColumnWidth(self.itemModel.priceColumn(), 70)
        self.listView.setColumnWidth(self.itemModel.priceLastColumn(), 70)
        self.listView.setColumnWidth(self.itemModel.priceMinColumn(), 70)
        self.listView.setColumnWidth(self.itemModel.priceMaxColumn(), 70)
        self.listView.setColumnWidth(self.itemModel.chartColumn(), 30)            

        self.itemSelectionModel.selectionChanged.connect(self.OnItemSelectionChanged)
        
        self.listView.viewport().setMouseTracking(True)
        self.listView.viewport().installEventFilter(self);
        self.listView.installEventFilter(self)
        
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.OnTimer)
        self.timer.start()
        
        self.updateThread = WorkerThread()
        self.updateThread.setTask(lambda abort: self.OnUpdateItemsTask(abort))
        self.updateThread.resultReady.connect(self.OnUpdateItemsTaskFinished)
        
        self.fetchThread = WorkerThread()
        self.fetchThread.resultReady.connect(self.OnFetchImageTaskFinished)

        self.CreateTray()
        self.tray.show()
        
        self.setCentralWidget(self.listView)
        self.resize(640, 200);
        self.setWindowTitle(self.tr("Amazon Watch Dog"))
        self.setWindowIcon(QtGui.QIcon("images" + QtCore.QDir.separator() + "awd.svg"))
        
        self.timer.setInterval(60000 * 20)
        self.hideAfterStart = True
        self.showNotifications = True
        self.settings = QtCore.QSettings(helper.GetConfigDir() + QtCore.QDir.separator() + helper.GetConfigName(), QtCore.QSettings.IniFormat, self)
        
        self.imageCache = ImageCache(helper.GetConfigDir() + QtCore.QDir.separator() + "cache")

        self.listView.setItemDelegateForColumn(self.itemModel.chartColumn(), ChartItemDelegate(self.listView))
        
        self.LoadSettings()
        self.LoadGeometrySettings()
        self.UpdateListView()
        
        if self.hideAfterStart: self.hide()
        else: self.show()

        self.SetLastUpdateLabel(self.lastUpdate)
        
    def CreateToolBar(self):
        self.toolbar = QtGui.QToolBar(self.tr("Main Toolbar"), self)
        self.CreateActions()
        
        self.toolbar.addAction(self.addAction)
        self.toolbar.addAction(self.editAction)
        self.toolbar.addAction(self.removeAction)
        self.toolbar.addAction(self.updateAction)
        
        self.addToolBar(self.toolbar)

    def CreateStatusBar(self):
        statusbar = QtGui.QStatusBar(self)

        self.lastUpdateLabel = QtGui.QLabel(statusbar)
        self.waitWidget = WaitWidget(statusbar)
        self.waitWidget.hide()

        statusbar.addWidget(self.lastUpdateLabel)
        statusbar.addWidget(self.waitWidget)

        self.setStatusBar(statusbar)
        
    def CreateToolTip(self):
        self.tooltip = ImageToolTip(self)
        self.tooltipItem = None        

    def CreateTray(self):
        self.tray = QtGui.QSystemTrayIcon(self)
        self.trayMenu = QtGui.QMenu(self)
        
        self.trayMenu.addAction(self.updateAction)
        self.trayMenu.addAction(self.itemsAction)
        self.trayMenu.addAction(self.settingsAction)
        
        if helper.debug_mode:
            self.trayMenu.addSeparator()
            self.trayMenu.addAction(self.builderAction)
            self.trayMenu.addAction(self.updateMainTable)
        
        self.trayMenu.addSeparator()
        self.trayMenu.addAction(self.aboutAction)
        self.trayMenu.addAction(self.quitAction)
        
        self.tray.setContextMenu(self.trayMenu)
        self.tray.setIcon(QtGui.QIcon("images" + QtCore.QDir.separator() +  defaults.GetTrayIconName()))
        self.tray.activated.connect(self.OnTrayActivated)
        
    def CreateActions(self):
        self.addAction = QtGui.QAction(self.tr("Add item..."), self)
        self.addAction.setIcon(QtGui.QIcon("images" + QtCore.QDir.separator() + "add.png"))
        self.addAction.triggered.connect(self.OnAddItem)
        
        self.editAction = QtGui.QAction(self.tr("Edit item..."), self)
        self.editAction.setIcon(QtGui.QIcon("images" + QtCore.QDir.separator() + "edit.png"))
        self.editAction.triggered.connect(self.OnEditItem)
            
        self.removeAction = QtGui.QAction(self.tr("Remove item(s)"), self)
        self.removeAction.setIcon(QtGui.QIcon("images" + QtCore.QDir.separator() + "remove.png"))
        self.removeAction.triggered.connect(self.OnRemoveItem)
        
        self.updateAction = QtGui.QAction(self.tr("Update"), self)
        self.updateAction.setIcon(QtGui.QIcon("images" + QtCore.QDir.separator() + "update.png"))
        self.updateAction.triggered.connect(self.OnUpdateItems)
        
        self.settingsAction = QtGui.QAction(self.tr("Settings..."), self)
        self.settingsAction.setIcon(QtGui.QIcon("images" + QtCore.QDir.separator() + "settings.png"))
        self.settingsAction.triggered.connect(self.OnShowSettings)
        
        self.itemsAction = QtGui.QAction(self.tr("Items..."), self)
        self.itemsAction.setIcon(QtGui.QIcon("images" + QtCore.QDir.separator() + "list.png"))
        self.itemsAction.triggered.connect(self.show)    
        
        self.quitAction = QtGui.QAction(self.tr("Quit"), self)
        self.quitAction.triggered.connect(self.exit)

        self.aboutAction = QtGui.QAction(self.tr("About..."), self)
        self.aboutAction.triggered.connect(self.OnAbout)
        
        if helper.debug_mode:
            self.builderAction = QtGui.QAction(self.tr("Build request..."), self)
            self.builderAction.triggered.connect(self.OnBuildRequest)
            
            self.updateMainTable = QtGui.QAction(self.tr("Update main table"), self)
            self.updateMainTable.triggered.connect(self.OnUpdateMaintable)

    def OnTimer(self):
        self.OnUpdateItems()
        
    def OnTrayActivated(self, reason):
        if reason == QtGui.QSystemTrayIcon.DoubleClick:
            if self.isHidden(): self.show()
            else: self.hide()

    def OnAbout(self):
        form = AboutForm(self)
        form.exec_()

    def exit(self):
        if self.updateThread.isRunning(): self.updateThread.wait()
        if self.fetchThread.isRunning(): self.fetchThread.wait()

        self.SaveSettings()
        QtGui.qApp.quit()

    def closeEvent(self, event):
        self.hide()
        event.ignore()
        
    def eventFilter(self, obj, event):   
        if event.type() == QtCore.QEvent.ContextMenu:
            self.OnListViewContextMenuEvent(event)
            return True

        elif event.type() == QtCore.QEvent.MouseMove:
            self.OnListViewMouseMoveEvent(event)
            return True           
        
        elif event.type() == QtCore.QEvent.ToolTip:
            self.OnListViewToolTipEvent(event)
            return True
        
        return QtGui.QMainWindow.eventFilter(self, obj, event)
        
    def OnListViewContextMenuEvent(self, event):        
        asins = self.GetSelectedASINs()
        if not asins: return
    
        menu = QtGui.QMenu(self)
        
        if len(asins) == 1:
            urlAction = menu.addAction(self.tr("Open URL"))
            urlAction.triggered.connect(lambda: self.OnOpenURL(asins[0]))
            
            asinAction = menu.addAction(self.tr("Copy ASIN"))
            asinAction.triggered.connect(lambda: self.OnCopyASIN(asins[0]))
            
            if helper.debug_mode:
                attrsAction = menu.addAction(self.tr("Get attributes..."))
                attrsAction.triggered.connect(lambda: self.OnGetAttributes(asins[0]))     
                
                imagesAction = menu.addAction(self.tr("Get images..."))
                imagesAction.triggered.connect(lambda: self.OnGetImages(asins[0]))     
                
            menu.addSeparator()
            
        if len(asins) == 1:
            menu.addAction(self.editAction)
            
        menu.addAction(self.removeAction)

        if len(asins) > 0:
            menu.exec_(event.globalPos())
            
    def OnListViewMouseMoveEvent(self, event):
        index = self.listView.indexAt(event.pos())
        item = self.itemModel.item(index)

        if item is None:
            self.tooltipItem = None
            self.tooltip.hideTip()
        
        if self.tooltipItem is None or item is self.tooltipItem:
            return

        if not item is self.tooltipItem:
            self.tooltip.showTip(QtGui.QCursor.pos())
            self.tooltipItem = item
            self.FetchImage()
            
    def OnListViewToolTipEvent(self, event):
        if self.tooltip.isVisible(): return

        index = self.listView.indexAt(event.pos())
        self.tooltipItem = self.itemModel.item(index)
        
        if self.tooltipItem is None:
            self.tooltip.hideTip()
        else:
            self.tooltip.showTip(QtGui.QCursor.pos())
            self.FetchImage()

    def GetSelectedASINs(self):
        selected = self.itemSelectionModel.selectedRows()
        asins = map(lambda index: self.itemModel.asin(index), selected)
        
        return asins

    def UpdateListView(self):       
        self.itemModel.update()

    def OnItemSelectionChanged(self, selected, deselected):
        selectedRows = self.itemSelectionModel.selectedRows()
        
        enable_removing = len(selectedRows) > 0
        enable_editing = len(selectedRows) == 1
        
        self.removeAction.setEnabled(enable_removing)
        self.editAction.setEnabled(enable_editing)
    
    def OnAddItem(self):
        form = ItemForm(self, self.accessKey, self.secretKey, self.associateTag)
        if form.exec_() == QtGui.QDialog.Accepted: self.UpdateListView()
        
    def OnEditItem(self):
        asins = self.GetSelectedASINs()
        if len(asins) > 1: return
        
        form = ItemForm(self, self.accessKey, self.secretKey, self.associateTag, asins[0])
        if form.exec_() == QtGui.QDialog.Accepted: self.UpdateListView()
        
    def OnRemoveItem(self):
        if QtGui.QMessageBox.warning(self, self.tr("Warning"), self.tr("Delete this item(s) from database?"),
        QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No) == QtGui.QMessageBox.No: return
        
        for asin in self.GetSelectedASINs():
            db.DeleteItem(asin)
        
        self.UpdateListView()
        
    def OnUpdateItems(self):
        if self.updateThread.isRunning():
            print("Worker thread is already running")
            return
        
        if self.accessKey == "" or self.secretKey == "" or self.associateTag == "":
            QtGui.QMessageBox.warning(self, self.tr("Warning"),
            self.tr("Amazon access parameters are not set. Go to \"Settings\" dialog and fill corresponded fields"))
            return
        
        self.waitWidget.show()
        self.waitWidget.Start()
        
        self.toolbar.setEnabled(False)
        self.addAction.setEnabled(False)
        self.removeAction.setEnabled(False)
        self.editAction.setEnabled(False)
        
        self.updateThread.start()

    def OnUpdateItemsTask(self, abort):
        result = db.UpdateAllItems(self.accessKey, self.secretKey, self.associateTag)
        return TaskResult(result, 0, "")
        
    def OnUpdateItemsTaskFinished(self, result):
        self.waitWidget.hide()
        self.waitWidget.Stop()
        
        self.toolbar.setEnabled(True)
        self.addAction.setEnabled(True)
        self.removeAction.setEnabled(True)
        self.editAction.setEnabled(True)
        self.OnItemSelectionChanged(self.itemSelectionModel.selection(), QtGui.QItemSelection())
        
        if result.error != 0:
            QtGui.QMessageBox.information(self, self.tr("Fetching error"), result.message)
            return

        self.UpdateItems(result.result.total, result.result.changed, result.result.failed, result.result.error)
        
    def UpdateItems(self, total, changed, failed, error):        
        if error and total == failed:
            notify.Notify(self.tr("Updating [Failed]"), error, self, self.sysNotify)
            print(error)
            return

        self.lastUpdate = QtCore.QDateTime.currentDateTime()
        self.SetLastUpdateLabel(self.lastUpdate)
        
        self.settings.setValue("last_update", self.lastUpdate)
        
        if not self.showNotifications: return
        
        if failed > 0: text = self.tr("{0} items have been checked\n{1} changed, {2} failed").format(total, changed, failed)
        else: text = self.tr("{0} items have been checked\n{1} changed").format(total, changed)
        
        if error: text += "\n" + error
        
        notify.Notify(self.tr("Updating [Finished]"), text, self, self.sysNotify)
        self.UpdateListView()     
        
    def OnShowSettings(self):
        form = SettingsForm(self, self.settings, self.imageCache)
        if form.exec_() == QtGui.QDialog.Accepted: self.LoadSettings()
        
    def OnBuildRequest(self):
        form = RequestForm(self, self.accessKey, self.secretKey, self.associateTag)
        form.exec_()
        
    def OnUpdateMaintable(self):
        db.UpdateMainTable()
        self.UpdateListView() 
        
    def SaveSettings(self):
        self.settings.setValue("mainform_size", self.size())
        self.settings.sync()

    def LoadSettings(self):
        self.timer.setInterval(60000 * int(self.settings.value("interval", 20)))
        self.hideAfterStart = to_bool(self.settings.value("hide", "true"))
        self.showNotifications = to_bool(self.settings.value("notifications", "true"))
        self.accessKey = str(self.settings.value("access_key", ""))
        self.secretKey = str(self.settings.value("secret_key", ""))
        self.associateTag = str(self.settings.value("associate_tag", ""))
        self.sysNotify = to_bool(self.settings.value("sys_notify", "false"))
        self.lastUpdate = self.settings.value("last_update", QtCore.QDateTime())
        
        self.LoadAppearanceSettings()

    def LoadGeometrySettings(self):
        self.resize(self.settings.value("mainform_size", QtCore.QSize(640, 200)))

    def LoadAppearanceSettings(self):
        self.settings.beginGroup("Appearance")

        self.itemModel.SetNumSamples(int(self.settings.value("graph_n_samples", defaults.GetNumSamples())))
        self.itemModel.SetUpTextForegroundColor(ReadColorValue(self.settings, "text_up_foreground_color", defaults.GetTextUpForegroundColor()))
        self.itemModel.SetDownTextForegroundColor(ReadColorValue(self.settings, "text_down_foreground_color", defaults.GetTextDownForegroundColor()))
        self.itemModel.update()

        delegete = self.listView.itemDelegateForColumn(self.itemModel.chartColumn())

        if delegete:
            delegete.SetUpLineColor(ReadColorValue(self.settings, "graph_up_line_color", defaults.GetUpLineColor()))
            delegete.SetUpFillColor(ReadColorValue(self.settings, "graph_up_fill_color", defaults.GetUpFillColor()))
            delegete.SetDownLineColor(ReadColorValue(self.settings, "graph_down_line_color", defaults.GetDownLineColor()))
            delegete.SetDownFillColor(ReadColorValue(self.settings, "graph_down_fill_color", defaults.GetDownFillColor()))
            delegete.SetNeutralLineColor(ReadColorValue(self.settings, "graph_neutral_line_color", defaults.GetNeutralLineColor()))
            delegete.SetNeutralFillColor(ReadColorValue(self.settings, "graph_neutral_fill_color", defaults.GetDefaultNeutralFillColor()))

        if self.tray: self.tray.setIcon(QtGui.QIcon("images" + QtCore.QDir.separator() +  self.settings.value("tray_icon", defaults.GetTrayIconName())))

        self.settings.endGroup()
        
    def OnCopyASIN(self, asin):
        clipboard = QtGui.QApplication.clipboard()
        clipboard.setText(asin)
        
    def OnOpenURL(self, asin):
        country = db.GetItemCountry(asin)    
        domain = helper.GetDomain(country)
        
        if not domain or not asin: return
        
        url = "http://amzn." + domain + "/" + asin
        QtGui.QDesktopServices.openUrl(QtCore.QUrl(url))
        
    def OnGetAttributes(self, asin):
        try:
            country = db.GetItemCountry(asin)
            attrs = GetAttributes(asin, country, self.accessKey, self.secretKey, self.associateTag)
            print(attrs)
            
        except AWSError, e:
            print(e.GetFullDescription())