class MainWindow(QMainWindow): tsize = (20, 20) BG_FREED = QtGui.QColor(255, 255, 153) BG_DOWN = QtGui.QColor(146, 208, 80) (COLUMN_ID, COLUMN_TITLE, COLUMN_AUTHOR, COLUMN_LINK, COLUMN_PROGRESS) = range(0, 5) COLUMNS_WIDTH = [50, 200, 200, 200, 200, 100] def __init__(self): self.duokan = Duokan() self.conf = Config() self.special = None self.downloader = None self.powerOff = False self.tag = MainWindow.__name__ super( MainWindow, self ).__init__() self.ui= Ui_MainWindow() self.ui.setupUi(self) self.setupPopup() self.bindSignal() def setupPopup(self): self.ui.tableWidget_books.addAction(self.ui.action_list_view_in_browser) self.ui.tableWidget_books.addAction(self.ui.action_list_download) self.ui.tableWidget_books.addAction(self.ui.action_list_remove) self.ui.tableWidget_books.addAction(self.ui.action_list_merge) self.ui.tableWidget_books.addAction(self.ui.action_list_crop) self.ui.tableWidget_books.addAction(self.ui.action_list_rename) self.ui.tableWidget_books.addAction(self.ui.action_list_mark_download) def bindSignal(self): QtCore.QObject.connect(self, QtCore.SIGNAL("when_information(QString, QString)"), self.do_message) QtCore.QObject.connect(self, QtCore.SIGNAL("when_item_progress(QString, QString)"), self.do_itemProgress) QtCore.QObject.connect(self, QtCore.SIGNAL("when_add_book(QString, QString, QString, QString, bool, bool)"), self.appendItem) def appendItem(self, id, title='', author='', link='', freed=False, done=False): row = self.ui.tableWidget_books.rowCount() self.when_add_book(row) item = QTableWidgetItem(id) self.ui.tableWidget_books.setItem(row, MainWindow.COLUMN_ID, item) item = QTableWidgetItem(title) self.ui.tableWidget_books.setItem(row, MainWindow.COLUMN_TITLE, item) item = QTableWidgetItem(author) self.ui.tableWidget_books.setItem(row, MainWindow.COLUMN_AUTHOR, item) item = QTableWidgetItem(link) self.ui.tableWidget_books.setItem(row, MainWindow.COLUMN_LINK, item) # item = QTableWidgetItem(progress) item = QProgressBar(self) item.setRange(0, 100) item.setValue(0) item.setTextVisible(True) item.setMaximumHeight(15) item.setTextDirection(QtGui.QProgressBar.TopToBottom) self.ui.tableWidget_books.setCellWidget(row, MainWindow.COLUMN_PROGRESS, item) if freed: self.ui.tableWidget_books.item(row, MainWindow.COLUMN_ID).setBackgroundColor(MainWindow.BG_FREED) self.ui.tableWidget_books.item(row, MainWindow.COLUMN_TITLE).setBackgroundColor(MainWindow.BG_FREED) self.ui.tableWidget_books.item(row, MainWindow.COLUMN_AUTHOR).setBackgroundColor(MainWindow.BG_FREED) self.ui.tableWidget_books.item(row, MainWindow.COLUMN_LINK).setBackgroundColor(MainWindow.BG_FREED) if done: self.ui.tableWidget_books.item(row, MainWindow.COLUMN_ID).setBackgroundColor(MainWindow.BG_DOWN) self.ui.tableWidget_books.item(row, MainWindow.COLUMN_TITLE).setBackgroundColor(MainWindow.BG_DOWN) self.ui.tableWidget_books.item(row, MainWindow.COLUMN_AUTHOR).setBackgroundColor(MainWindow.BG_DOWN) self.ui.tableWidget_books.item(row, MainWindow.COLUMN_LINK).setBackgroundColor(MainWindow.BG_DOWN) self.adjustListWidth() def adjustListWidth(self): self.ui.tableWidget_books.resizeColumnsToContents() # set download column progress def setProgress(self, row, prog): if row >= 0 and row < self.ui.tableWidget_books.rowCount(): item = self.ui.tableWidget_books.cellWidget(row, MainWindow.COLUMN_PROGRESS) item.setValue(prog) # for duoSpider def cbAddUrl(self, event, url): self.when_special_url(url) # for duoSpider def cbAddBook(self, event, id, title, author, link): notFreed = self.duokan.addBook(id, title, author, link) download = self.duokan.isDownload(id) self.when_add_book_info(id, title, author, link, (not notFreed), download) def startDownload(self): if self.downloadRow < self.ui.tableWidget_books.rowCount(): id = _fromQString(self.ui.tableWidget_books.item(self.downloadRow, MainWindow.COLUMN_ID).text()) proxy = self.conf.getProxy() self.downloader = Downloader(id, id, proxy[0], proxy[1], proxy[2]) self.downloader.bind(Downloader.EVT_START, self.cbStart) self.downloader.bind(Downloader.EVT_STOP, self.cbStop) self.downloader.bind(Downloader.EVT_LOG, self.cbLog) self.downloader.bind(Downloader.EVT_PROG, self.cbProgress) self.downloader.start() # for downloader def cbStart(self, event): self.when_itemProgress(self.downloadRow, 100) self.when_progress(0) # for downloader def cbStop(self, event): self.when_itemProgress(self.downloadRow, 100) self.when_progress(100) # self.list.SetItemBackgroundColour(self.downloadIdx, MainWindow.BG_DOWN) # start next self.downloadRow += 1 self.startDownload() if self.downloadRow >= self.ui.tableWidget_books.rowCount(): if self.powerOff: os.system('shutdown -t 60 -f -s') # for downloader def cbLog(self, event, str): self.when_logging(str) # for downloader def cbProgress(self, event, prog): self.when_progress(prog) ### signals and slots # signals def when_logging(self, logStr): self.emit(QtCore.SIGNAL("when_logging(QString)"), logStr) def when_special_url(self, url): self.emit(QtCore.SIGNAL("when_special_url(QString)"), url) def when_status(self, text): self.emit(QtCore.SIGNAL("when_status(QString)"), text) def when_add_book(self, row): self.emit(QtCore.SIGNAL("when_add_book(int)"), row) def when_del_book(self, row): self.emit(QtCore.SIGNAL("when_del_book(int)"), row) def when_progress(self, prog): self.emit(QtCore.SIGNAL("when_progress(int)"), prog) # self defined signal############################################################################################## def when_information(self, text, title='', info=True): self.emit(QtCore.SIGNAL("when_status(QString)"), '%s --> %s' % (title, text)) if info: self.emit(QtCore.SIGNAL("when_information(QString, QString)"), text, title) def when_itemProgress(self, row, prog): self.emit(QtCore.SIGNAL("when_item_progress(int, int)"), row, prog) def when_add_book_info(self, id, title, author, link, freed=False, done=False): self.emit(QtCore.SIGNAL("when_add_book(QString, QString, QString, QString, bool, bool)"), _fromUtf8(id), _fromUtf8(title), _fromUtf8(author), _fromUtf8(link), freed, done) # slots def do_update(self): self.when_progress(10) proxy = self.conf.getProxy() self.special = Special(proxy[0], proxy[1], proxy[2]) self.special.bind(Special.EVT_FIND_LINK, self.cbAddUrl) self.special.bind(Special.EVT_FIND_BOOK, self.cbAddBook) self.special.start() self.when_progress(100) def do_update_stop(self): if self.special: self.special.stop() self.special = None def do_download_all(self): self.dlgs = [] for row in range(self.ui.tableWidget_books.rowCount()): id = self.ui.tableWidget_books.item(row, MainWindow.COLUMN_ID).text() title = self.ui.tableWidget_books.item(row, MainWindow.COLUMN_TITLE).text() dlg = DownloaderDlg(self, self.conf, title) dlg.setId(id) dlg.setName(id) dlg.show() dlg.resize(640, 200) self.dlgs.append(dlg) if self.dlgs: for i, dlg in enumerate(self.dlgs): if i < 5: x = 0 y = 190 * i else: x = 640 y = 190 * (i - 5) dlg.resize(640, 190) dlg.move(x, y) def do_download_stop(self): pass def do_open_special_in_browser(self): self.duokan.openInNewTab(_fromQString(self.ui.lineEdit_specialUrl.text())) def do_open_books_folder(self): '''open books/new folder''' self.duokan.openNewFolder() def do_clean_tmp_folder(self): self.duokan.cleanTmp() self.when_information( 'Finished', 'Clear tmp folder') def do_merge_all(self): for row in range(self.ui.tableWidget_books.rowCount()): id = _fromQString(self.ui.tableWidget_books.item(row, MainWindow.COLUMN_ID).text()) self.duokan.merge(id) self.when_information('merge all finished') def do_crop_all(self): for row in range(self.ui.tableWidget_books.rowCount()): id = _fromQString(self.ui.tableWidget_books.item(row, MainWindow.COLUMN_ID).text()) self.duokan.crop(id) self.when_information('crop all finished') def do_rename_all(self): self.duokan.renameAll() self.when_information('Finished', 'Rename All') def do_done_all(self): for row in range(self.ui.tableWidget_books.rowCount()): id = _fromQString(self.ui.tableWidget_books.item(row, MainWindow.COLUMN_ID).text()) title = self.ui.tableWidget_books.item(row, MainWindow.COLUMN_TITLE).text() self.when_information('Start', 'Merge & Crop & Rename [%s]' % title, False) self.duokan.setDownload(id) self.duokan.merge(id) self.duokan.crop(id) self.duokan.rename(id) self.when_information('Finished!', 'Merge & Crop & Rename [%s]' % title, False) self.when_information('Finished!', 'All Merge & Crop & Rename') def do_crop_book(self): file_wildcard = "Pdf files (*.pdf)" filePath = QFileDialog.getOpenFileName(self, 'Open file to crop', _fromUtf8(os.path.join(os.getcwd(), 'books')), _fromUtf8(file_wildcard)) if filePath: self.duokan.cropSingle(_fromQString(filePath)) self.when_information( 'Finished!', 'Crop single') def do_merge_book(self): filePath = QFileDialog.getExistingDirectory(self, 'Open file to crop', _fromUtf8(os.path.join(os.getcwd(), 'tmp'))) if filePath: print _fromQString(filePath) self.duokan.mergeSingle(_fromQString(filePath)) self.when_information('Finished!', 'Merge single') def do_crop_4print(self): file_wildcard = "Pdf files (*.pdf)" filePath = QFileDialog.getOpenFileName(self, 'Open file to crop for printing', _fromUtf8(os.path.join(os.getcwd(), 'books')), _fromUtf8(file_wildcard)) if filePath: self.duokan.crop4Print(_fromQString(filePath)) self.when_information( 'Finished!', 'Crop for printing') def do_crop_4kindle(self): file_wildcard = "Pdf files (*.pdf)" filePath = QFileDialog.getOpenFileName(self, 'Open file to crop for printing', _fromUtf8(os.path.join(os.getcwd(), 'books')), _fromUtf8(file_wildcard)) if filePath: self.duokan.crop4Kindle(_fromQString(filePath)) self.when_information( 'Finished!', 'Crop for kindle') def do_crop_4nook(self): file_wildcard = "Pdf files (*.pdf)" filePath = QFileDialog.getOpenFileName(self, 'Open file to crop for printing', _fromUtf8(os.path.join(os.getcwd(), 'books')), _fromUtf8(file_wildcard)) if filePath: self.duokan.crop4Nook(_fromQString(filePath)) self.when_information('Finished!', 'Crop for nook') def on_power_off_setting(self, powerOff): self.powerOff = powerOff # print powerOff def do_destroyed(self): print 'destroyed' def do_list_view_in_browser(self): ''' open link in browser ''' row = self.ui.tableWidget_books.currentRow() if row != -1: url = _fromQString(self.ui.tableWidget_books.item(row, MainWindow.COLUMN_LINK).text()) self.duokan.openInNewTab(url) def do_list_download(self): '''download a book''' row = self.ui.tableWidget_books.currentRow() if row >=0 and row < self.ui.tableWidget_books.rowCount(): id = self.ui.tableWidget_books.item(row, MainWindow.COLUMN_ID).text() title = self.ui.tableWidget_books.item(row, MainWindow.COLUMN_TITLE).text() dlg = DownloaderDlg(self, self.conf, title) dlg.setId(id) dlg.setName(id) dlg.show() else: dlg = DownloaderDlg(self, self.conf) dlg.show() def do_list_remove(self): ''' delete an item ''' row = self.ui.tableWidget_books.currentRow() if row != -1: self.when_del_book(row) def do_list_merge(self): row = self.ui.tableWidget_books.currentRow() if row != -1: id = _fromQString(self.ui.tableWidget_books.item(row, MainWindow.COLUMN_ID).text()) self.duokan.merge(id) self.when_information('merge finished') def do_list_crop(self): row = self.ui.tableWidget_books.currentRow() if row != -1: id = _fromQString(self.ui.tableWidget_books.item(row, MainWindow.COLUMN_ID).text()) self.duokan.crop(id) self.when_information('crop finished') def do_list_rename(self): ''' rename a item from id to title ''' row = self.ui.tableWidget_books.currentRow() if row != -1: id = _fromQString(self.ui.tableWidget_books.item(row, MainWindow.COLUMN_ID).text()) title = _fromQString(self.ui.tableWidget_books.item(row, MainWindow.COLUMN_TITLE).text()) self.duokan.rename(id, title) self.when_information('rename finished') def do_list_mark_download(self, row, col): row = self.ui.tableWidget_books.currentRow() if row != -1: id = _fromQString(self.ui.tableWidget_books.item(row, MainWindow.COLUMN_ID).text()) self.duokan.setDownload(id) def do_list_dclick(self, row, col): url = _fromQString(self.ui.tableWidget_books.item(row, MainWindow.COLUMN_LINK).text()) self.duokan.openInNewTab(url) # self defined slots ############################################################################################### def do_message(self, text, title=''): QtGui.QMessageBox.information(self, title, text) def do_itemProgress(self, row, prog): self.setProgress(row, prog)
class MainWindow(wx.Frame): tsize = (20, 20) BG_FREED = wx.Colour(255, 255, 153) BG_DOWN = wx.Colour(146, 208, 80) ( ID_MENUITEM_FETCH, ID_MENUITEM_DOWNLOAD_ALL, ID_MENUITEM_OPEN_IN_BROWER, ID_MENUITEM_OPEN_NEW, ID_MENUITEM_SHUTDOWN, ID_MENUITEM_CLEAN_TMP, ID_MENUITEM_RENAME_ALL, ID_MENUITEM_MERGE_SINGLE, ID_MENUITEM_CROP_SINGLE, ID_MENUITEM_CROP_4_PRINT, ID_MENUITEM_CROP_4_KINDLE, ID_MENUITEM_DOWN, ID_MENUITEM_VIEW, ID_MENUITEM_REMOVE, ID_MENUITEM_MERGE, ID_MENUITEM_CROP, ID_MENUITEM_RENAME, ID_LIST, ID_TOOL_FETCH, ID_TOOL_OPEN, ID_TOOL_DOWN, ) = range(0, 21) COLUMNS = ["#", "ID", "TITLE", "AUTHOR", "LINK", "PROGRESS"] (COLUMN_NUM, COLUMN_ID, COLUMN_TITLE, COLUMN_AUTHOR, COLUMN_LINK, COLUMN_PROGRESS) = range(0, 6) COLUMNS_WIDTH = [50, 200, 200, 200, 200, 100] def __init__(self, tt): self.duokan = Duokan() self.conf = Config() self.MENUBAR = [ ( "&File", ( ("&Fetch", "", MainWindow.ID_MENUITEM_FETCH, self.onUpdate), ("&Download all", "", MainWindow.ID_MENUITEM_DOWNLOAD_ALL, self.onDownloadAll), ("", "", "", ""), ("&Open in brower", "", MainWindow.ID_MENUITEM_OPEN_IN_BROWER, self.onBrowser), ("&Open download folder", "", MainWindow.ID_MENUITEM_OPEN_NEW, self.onOpenNewFolder), ("", "", "", ""), ("Shutdown after finish", "", MainWindow.ID_MENUITEM_SHUTDOWN, self.menuShutdown, wx.ITEM_CHECK), ), ), ( "&Edit", ( ("&Clean tmp folder", "", MainWindow.ID_MENUITEM_CLEAN_TMP, self.onCleanTmp), ("&Rename all", "", MainWindow.ID_MENUITEM_RENAME_ALL, self.onRenameAll), ("", "", "", ""), ("&Merge", "", MainWindow.ID_MENUITEM_MERGE_SINGLE, self.onMergeSingle), ("&Crop", "", MainWindow.ID_MENUITEM_CROP_SINGLE, self.onCropSingle), ("Crop for &printing", "", MainWindow.ID_MENUITEM_CROP_4_PRINT, self.onCrop4Print), ("Crop for &kindle", "", MainWindow.ID_MENUITEM_CROP_4_KINDLE, self.onCrop4Kindle), ), ), ] self.POPMENU = [ (MainWindow.ID_MENUITEM_DOWN, "Download", self.onDownloadItem, MainWindow.ID_LIST), (MainWindow.ID_MENUITEM_VIEW, "View in browser", self.onBrowserItem, MainWindow.ID_LIST), (MainWindow.ID_MENUITEM_REMOVE, "Remove", self.onRemoveItem, MainWindow.ID_LIST), (MainWindow.ID_MENUITEM_MERGE, "Merge", self.onMergeItem, MainWindow.ID_LIST), (MainWindow.ID_MENUITEM_CROP, "Crop", self.onCropItem, MainWindow.ID_LIST), (MainWindow.ID_MENUITEM_RENAME, "Rename", self.onRenameItem, MainWindow.ID_LIST), ] self.TOOLBAR = [ ( MainWindow.ID_TOOL_FETCH, "Fetch", wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_BUTTON, MainWindow.tsize), self.onUpdate, ), ( MainWindow.ID_TOOL_OPEN, "View in browser", wx.ArtProvider.GetBitmap(wx.ART_FIND, wx.ART_BUTTON, MainWindow.tsize), self.onBrowser, ), ( MainWindow.ID_TOOL_DOWN, "Download all", wx.ArtProvider.GetBitmap(wx.ART_GO_DOWN, wx.ART_BUTTON, MainWindow.tsize), self.onDownloadAll, ), ] wx.Frame.__init__(self, None, title=tt, size=(1020, 800)) self.menubar = self.createMenubar() self.CreateStatusBar() self.createPopmenu() self.toolbar = self.createToolBar() # panel###################################### panel = wx.Panel(self) lblUrl = wx.StaticText(panel, -1, "Special URL: ", style=1) self.teUrl = wx.TextCtrl(panel, style=wx.TE_PROCESS_ENTER) hbox = wx.BoxSizer() hbox.Add(lblUrl, proportion=0, flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, border=5) hbox.Add(self.teUrl, proportion=1, flag=wx.EXPAND) self.gauge = wx.Gauge(panel, -1, 100, style=wx.GA_PROGRESSBAR) self.list = wx.ListCtrl( panel, MainWindow.ID_LIST, style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_HRULES | wx.LC_VRULES ) self.teInfo = wx.TextCtrl(panel, style=wx.TE_MULTILINE | wx.HSCROLL) for i in range(len(MainWindow.COLUMNS)): self.list.InsertColumn(i, MainWindow.COLUMNS[i], width=MainWindow.COLUMNS_WIDTH[i]) vbox = wx.BoxSizer(wx.VERTICAL) vbox.Add(hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) vbox.Add(self.gauge, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) vbox.Add(self.list, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) vbox.Add(self.teInfo, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.BOTTOM | wx.RIGHT, border=5) panel.SetSizer(vbox) self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.onDownloadItem, id=MainWindow.ID_LIST) self.Bind(wx.EVT_CONTEXT_MENU, self.onShowPopup, id=MainWindow.ID_LIST) self.downloadIdx = 0 # self.redir = RedirectText(self) # sys.stdout = self.redir self.Centre() def createMenubar(self): menuBar = wx.MenuBar() for eachMenu in self.MENUBAR: label = eachMenu[0] items = eachMenu[1] menuBar.Append(self.createMenuItems(items), label) self.SetMenuBar(menuBar) return menuBar def createMenuItems(self, menuData): menu = wx.Menu() for item in menuData: if len(item) == 2: label = item[0] subMenu = self.createMenuItems(item[1]) menu.AppendMenu(wx.ID_ANY, label, subMenu) else: label = item[0] help = item[1] id = item[2] handler = item[3] if len(item) > 4: kind = item[4] else: kind = wx.ITEM_NORMAL if label: menu.Append(id, label, help, kind=kind) self.Bind(wx.EVT_MENU, handler, id=id) else: menu.AppendSeparator() return menu def createPopmenu(self): self.popupmenu = wx.Menu() for item in self.POPMENU: self.popupmenu.Append(item[0], item[1]) self.Bind(wx.EVT_MENU, item[2], id=item[0], id2=item[3]) return self.popupmenu def createToolBar(self): toolbar = self.CreateToolBar() for item in self.TOOLBAR: toolbar.AddLabelTool(item[0], item[1], item[2]) self.Bind(wx.EVT_TOOL, item[3], id=item[0]) toolbar.Realize() return toolbar def appendItem(self, id, title="", author="", link="", freed=False, done=False, progress="=========="): newIdx = self.list.GetItemCount() self.list.InsertStringItem(newIdx, "%d" % (newIdx + 1)) self.list.SetStringItem(newIdx, MainWindow.COLUMN_ID, id) self.list.SetStringItem(newIdx, MainWindow.COLUMN_TITLE, title) self.list.SetStringItem(newIdx, MainWindow.COLUMN_AUTHOR, author) self.list.SetStringItem(newIdx, MainWindow.COLUMN_LINK, link) self.list.SetStringItem(newIdx, MainWindow.COLUMN_PROGRESS, progress) if freed: self.list.SetItemBackgroundColour(newIdx, MainWindow.BG_FREED) if done: self.list.SetItemBackgroundColour(newIdx, MainWindow.BG_DOWN) self.adjustListWidth() def adjustListWidth(self): self.list.SetColumnWidth(MainWindow.COLUMN_NUM, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(MainWindow.COLUMN_ID, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(MainWindow.COLUMN_TITLE, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(MainWindow.COLUMN_AUTHOR, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(MainWindow.COLUMN_LINK, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(MainWindow.COLUMN_PROGRESS, wx.LIST_AUTOSIZE) # set download column progress def setProgress(self, idx, prog): if idx < self.list.GetItemCount(): ppp = "" prog /= 10 for i in range(prog): ppp += ">" for i in range(10 - prog): ppp += "=" self.list.SetStringItem(idx, MainWindow.COLUMN_PROGRESS, ppp) def setUrl(self, url): self.teUrl.SetValue(url) def addLog(self, log): self.teInfo.AppendText(log) pass def onKeyDown(self, event): self.onUpdate(event) def onUpdate(self, event): self.gauge.SetValue(10) proxy = self.conf.getProxy() special = Special(proxy[0], proxy[1], proxy[2]) special.bind(Special.EVT_FIND_LINK, self.cbAddUrl) special.bind(Special.EVT_FIND_BOOK, self.cbAddBook) special.start() self.gauge.SetValue(100) def onBrowser(self, event): self.duokan.openInNewTab(self.teUrl.GetValue()) def onOpenNewFolder(self, event): self.duokan.openNewFolder() def menuShutdown(self, event): print self.menubar.IsChecked(MainWindow.ID_MENUITEM_SHUTDOWN) def onDownloadAll(self, event): self.downloadIdx = 0 self.startDownload() def onCleanTmp(self, event): self.duokan.cleanTmp() ux.showMsg(self, "Finished", "Clear tmp folder") def onRenameAll(self, event): self.duokan.renameAll() ux.showMsg(self, "Finished", "Rename All") def onMergeSingle(self, event): # file_wildcard = "Pdf files(*.pdf)|*.pdf" ret, filePath = ux.showDirDlg(self, "Open dir to merge", os.path.join(os.getcwd(), "tmp")) if ret and filePath: self.duokan.mergeSingle(filePath) ux.showMsg(self, "Finished!", "Merge single") def onCropSingle(self, event): file_wildcard = "Pdf files(*.pdf)|*.pdf" ret, filePath = ux.showFileDlg(self, "Open file to crop", os.path.join(os.getcwd(), "books"), file_wildcard) if ret and filePath: self.duokan.cropSingle(filePath) ux.showMsg(self, "Finished!", "Crop single") def onCrop4Print(self, event): file_wildcard = "Pdf files(*.pdf)|*.pdf" ret, filePath = ux.showFileDlg( self, "Open file to crop for printing", os.path.join(os.getcwd(), "books"), file_wildcard ) if ret and filePath: self.duokan.crop4Print(filePath) ux.showMsg(self, "Finished!", "Crop for printing") def onCrop4Kindle(self, event): file_wildcard = "Pdf files(*.pdf)|*.pdf" ret, filePath = ux.showFileDlg( self, "Open file to crop for printing", os.path.join(os.getcwd(), "books"), file_wildcard ) if ret and filePath: self.duokan.crop4Kindle(filePath) ux.showMsg(self, "Finished!", "Crop for kindle") # download a book def onDownloadItem(self, event): idx = self.list.GetFocusedItem() id = self.list.GetItemText(idx, MainWindow.COLUMN_ID) title = self.list.GetItemText(idx, MainWindow.COLUMN_TITLE) win = DownloaderWnd(self.conf, title) win.setId(id) win.setName(id) win.Show(True) # show popup menu def onShowPopup(self, event): if self.list.GetFirstSelected() != -1: pos = event.GetPosition() pos = self.list.ScreenToClient(pos) self.list.PopupMenu(self.popupmenu, pos) # open link in browser def onBrowserItem(self, event): idx = self.list.GetFirstSelected() if idx != -1: url = self.list.GetItemText(idx, MainWindow.COLUMN_LINK) self.duokan.openInNewTab(url) # rename a item from id to title def onRenameItem(self, event): idx = self.list.GetFirstSelected() if idx != -1: id = self.list.GetItemText(idx, MainWindow.COLUMN_ID) title = self.list.GetItemText(idx, MainWindow.COLUMN_TITLE) self.duokan.rename(id, title) # delete an item def onRemoveItem(self, event): idx = self.list.GetFirstSelected() if idx != -1: self.list.DeleteItem(idx) def onCropItem(self, event): idx = self.list.GetFirstSelected() if idx != -1: id = self.list.GetItemText(idx, MainWindow.COLUMN_ID) self.duokan.crop(id) def onMergeItem(self, event): idx = self.list.GetFirstSelected() if idx != -1: id = self.list.GetItemText(idx, MainWindow.COLUMN_ID) self.duokan.merge(id) def startDownload(self): if self.downloadIdx < self.list.GetItemCount(): id = self.list.GetItemText(self.downloadIdx, MainWindow.COLUMN_ID) proxy = self.conf.getProxy() self.down = Downloader(id, id, proxy[0], proxy[1], proxy[2]) self.down.bind(Downloader.EVT_START, self.cbStart) self.down.bind(Downloader.EVT_STOP, self.cbStop) self.down.bind(Downloader.EVT_LOG, self.cbLog) self.down.bind(Downloader.EVT_PROG, self.cbProgress) self.down.start() # for downloader def cbStart(self, event): wx.CallAfter(self.setProgress, self.downloadIdx, 0) # for downloader def cbStop(self, event): wx.CallAfter(self.setProgress, self.downloadIdx, 100) wx.CallAfter(self.gauge.SetValue, 100) self.list.SetItemBackgroundColour(self.downloadIdx, MainWindow.BG_DOWN) # rename id = self.list.GetItemText(self.downloadIdx, MainWindow.COLUMN_ID) title = self.list.GetItemText(self.downloadIdx, MainWindow.COLUMN_TITLE) self.duokan.rename(id, title) # start next self.downloadIdx += 1 self.startDownload() if self.downloadIdx >= self.list.GetItemCount(): if self.menubar.IsChecked(MainWindow.ID_MENUITEM_SHUTDOWN): os.system("shutdown -t 60 -f -s") # for downloader def cbLog(self, event, str): wx.CallAfter(self.addLog, str) print str # for downloader def cbProgress(self, event, prog): # itemCount = self.list.GetItemCount() # wx.CallAfter(self.setProgress, self.downloadIdx, prog) wx.CallAfter(self.gauge.SetValue, prog) # for duoSpider def cbAddUrl(self, event, url): wx.CallAfter(self.setUrl, url) # for duoSpider def cbAddBook(self, event, id, title, author, link): notFreed = self.duokan.addBook(id, title, author, link) download = self.duokan.isDownload(id) wx.CallAfter(self.appendItem, id, title, author, link, (not notFreed), download)
class MainWindow(wx.Frame): tsize = (20, 20) BG_FREED = wx.Colour(255, 255, 153) BG_DOWN = wx.Colour(146, 208, 80) (ID_MENUITEM_FETCH, ID_MENUITEM_DOWNLOAD_ALL, ID_MENUITEM_OPEN_IN_BROWER, ID_MENUITEM_OPEN_NEW, ID_MENUITEM_SHUTDOWN, ID_MENUITEM_CLEAN_TMP, ID_MENUITEM_RENAME_ALL, ID_MENUITEM_MERGE_SINGLE, ID_MENUITEM_CROP_SINGLE, ID_MENUITEM_CROP_4_PRINT, ID_MENUITEM_CROP_4_KINDLE, ID_MENUITEM_DOWN, ID_MENUITEM_VIEW, ID_MENUITEM_REMOVE, ID_MENUITEM_MERGE, ID_MENUITEM_CROP, ID_MENUITEM_RENAME, ID_LIST, ID_TOOL_FETCH, ID_TOOL_OPEN, ID_TOOL_DOWN) = range(0, 21) COLUMNS = ['#', 'ID', 'TITLE', 'AUTHOR', 'LINK', 'PROGRESS'] (COLUMN_NUM, COLUMN_ID, COLUMN_TITLE, COLUMN_AUTHOR, COLUMN_LINK, COLUMN_PROGRESS) = range(0, 6) COLUMNS_WIDTH = [50, 200, 200, 200, 200, 100] def __init__(self, tt): self.duokan = Duokan() self.conf = Config() self.MENUBAR = [ ('&File', ( ('&Fetch', '', MainWindow.ID_MENUITEM_FETCH, self.onUpdate), ('&Download all', '', MainWindow.ID_MENUITEM_DOWNLOAD_ALL, self.onDownloadAll), ("", '', '', ""), ('&Open in brower', '', MainWindow.ID_MENUITEM_OPEN_IN_BROWER, self.onBrowser), ('&Open download folder', '', MainWindow.ID_MENUITEM_OPEN_NEW, self.onOpenNewFolder), ("", '', '', ""), ('Shutdown after finish', '', MainWindow.ID_MENUITEM_SHUTDOWN, self.menuShutdown, wx.ITEM_CHECK), )), ('&Edit', (('&Clean tmp folder', '', MainWindow.ID_MENUITEM_CLEAN_TMP, self.onCleanTmp), ('&Rename all', '', MainWindow.ID_MENUITEM_RENAME_ALL, self.onRenameAll), ("", "", '', ""), ('&Merge', '', MainWindow.ID_MENUITEM_MERGE_SINGLE, self.onMergeSingle), ('&Crop', '', MainWindow.ID_MENUITEM_CROP_SINGLE, self.onCropSingle), ('Crop for &printing', '', MainWindow.ID_MENUITEM_CROP_4_PRINT, self.onCrop4Print), ('Crop for &kindle', '', MainWindow.ID_MENUITEM_CROP_4_KINDLE, self.onCrop4Kindle))) ] self.POPMENU = [(MainWindow.ID_MENUITEM_DOWN, 'Download', self.onDownloadItem, MainWindow.ID_LIST), (MainWindow.ID_MENUITEM_VIEW, 'View in browser', self.onBrowserItem, MainWindow.ID_LIST), (MainWindow.ID_MENUITEM_REMOVE, 'Remove', self.onRemoveItem, MainWindow.ID_LIST), (MainWindow.ID_MENUITEM_MERGE, 'Merge', self.onMergeItem, MainWindow.ID_LIST), (MainWindow.ID_MENUITEM_CROP, 'Crop', self.onCropItem, MainWindow.ID_LIST), (MainWindow.ID_MENUITEM_RENAME, 'Rename', self.onRenameItem, MainWindow.ID_LIST)] self.TOOLBAR = [ (MainWindow.ID_TOOL_FETCH, 'Fetch', wx.ArtProvider.GetBitmap(wx.ART_REDO, wx.ART_BUTTON, MainWindow.tsize), self.onUpdate), (MainWindow.ID_TOOL_OPEN, 'View in browser', wx.ArtProvider.GetBitmap(wx.ART_FIND, wx.ART_BUTTON, MainWindow.tsize), self.onBrowser), (MainWindow.ID_TOOL_DOWN, 'Download all', wx.ArtProvider.GetBitmap(wx.ART_GO_DOWN, wx.ART_BUTTON, MainWindow.tsize), self.onDownloadAll) ] wx.Frame.__init__(self, None, title=tt, size=(1020, 800)) self.menubar = self.createMenubar() self.CreateStatusBar() self.createPopmenu() self.toolbar = self.createToolBar() #panel###################################### panel = wx.Panel(self) lblUrl = wx.StaticText(panel, -1, "Special URL: ", style=1) self.teUrl = wx.TextCtrl(panel, style=wx.TE_PROCESS_ENTER) hbox = wx.BoxSizer() hbox.Add(lblUrl, proportion=0, flag=wx.LEFT | wx.ALIGN_CENTER_VERTICAL, border=5) hbox.Add(self.teUrl, proportion=1, flag=wx.EXPAND) self.gauge = wx.Gauge(panel, -1, 100, style=wx.GA_PROGRESSBAR) self.list = wx.ListCtrl(panel, MainWindow.ID_LIST, style=wx.LC_REPORT | wx.LC_SINGLE_SEL | wx.LC_HRULES | wx.LC_VRULES) self.teInfo = wx.TextCtrl(panel, style=wx.TE_MULTILINE | wx.HSCROLL) for i in range(len(MainWindow.COLUMNS)): self.list.InsertColumn(i, MainWindow.COLUMNS[i], width=MainWindow.COLUMNS_WIDTH[i]) vbox = wx.BoxSizer(wx.VERTICAL) vbox.Add(hbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) vbox.Add(self.gauge, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) vbox.Add(self.list, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) vbox.Add(self.teInfo, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.BOTTOM | wx.RIGHT, border=5) panel.SetSizer(vbox) self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.onDownloadItem, id=MainWindow.ID_LIST) self.Bind(wx.EVT_CONTEXT_MENU, self.onShowPopup, id=MainWindow.ID_LIST) self.downloadIdx = 0 # self.redir = RedirectText(self) # sys.stdout = self.redir self.Centre() def createMenubar(self): menuBar = wx.MenuBar() for eachMenu in self.MENUBAR: label = eachMenu[0] items = eachMenu[1] menuBar.Append(self.createMenuItems(items), label) self.SetMenuBar(menuBar) return menuBar def createMenuItems(self, menuData): menu = wx.Menu() for item in menuData: if len(item) == 2: label = item[0] subMenu = self.createMenuItems(item[1]) menu.AppendMenu(wx.ID_ANY, label, subMenu) else: label = item[0] help = item[1] id = item[2] handler = item[3] if len(item) > 4: kind = item[4] else: kind = wx.ITEM_NORMAL if label: menu.Append(id, label, help, kind=kind) self.Bind(wx.EVT_MENU, handler, id=id) else: menu.AppendSeparator() return menu def createPopmenu(self): self.popupmenu = wx.Menu() for item in self.POPMENU: self.popupmenu.Append(item[0], item[1]) self.Bind(wx.EVT_MENU, item[2], id=item[0], id2=item[3]) return self.popupmenu def createToolBar(self): toolbar = self.CreateToolBar() for item in self.TOOLBAR: toolbar.AddLabelTool(item[0], item[1], item[2]) self.Bind(wx.EVT_TOOL, item[3], id=item[0]) toolbar.Realize() return toolbar def appendItem(self, id, title='', author='', link='', freed=False, done=False, progress='=========='): newIdx = self.list.GetItemCount() self.list.InsertStringItem(newIdx, '%d' % (newIdx + 1)) self.list.SetStringItem(newIdx, MainWindow.COLUMN_ID, id) self.list.SetStringItem(newIdx, MainWindow.COLUMN_TITLE, title) self.list.SetStringItem(newIdx, MainWindow.COLUMN_AUTHOR, author) self.list.SetStringItem(newIdx, MainWindow.COLUMN_LINK, link) self.list.SetStringItem(newIdx, MainWindow.COLUMN_PROGRESS, progress) if freed: self.list.SetItemBackgroundColour(newIdx, MainWindow.BG_FREED) if done: self.list.SetItemBackgroundColour(newIdx, MainWindow.BG_DOWN) self.adjustListWidth() def adjustListWidth(self): self.list.SetColumnWidth(MainWindow.COLUMN_NUM, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(MainWindow.COLUMN_ID, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(MainWindow.COLUMN_TITLE, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(MainWindow.COLUMN_AUTHOR, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(MainWindow.COLUMN_LINK, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(MainWindow.COLUMN_PROGRESS, wx.LIST_AUTOSIZE) # set download column progress def setProgress(self, idx, prog): if idx < self.list.GetItemCount(): ppp = '' prog /= 10 for i in range(prog): ppp += '>' for i in range(10 - prog): ppp += '=' self.list.SetStringItem(idx, MainWindow.COLUMN_PROGRESS, ppp) def setUrl(self, url): self.teUrl.SetValue(url) def addLog(self, log): self.teInfo.AppendText(log) pass def onKeyDown(self, event): self.onUpdate(event) def onUpdate(self, event): self.gauge.SetValue(10) proxy = self.conf.getProxy() special = Special(proxy[0], proxy[1], proxy[2]) special.bind(Special.EVT_FIND_LINK, self.cbAddUrl) special.bind(Special.EVT_FIND_BOOK, self.cbAddBook) special.start() self.gauge.SetValue(100) def onBrowser(self, event): self.duokan.openInNewTab(self.teUrl.GetValue()) def onOpenNewFolder(self, event): self.duokan.openNewFolder() def menuShutdown(self, event): print self.menubar.IsChecked(MainWindow.ID_MENUITEM_SHUTDOWN) def onDownloadAll(self, event): self.downloadIdx = 0 self.startDownload() def onCleanTmp(self, event): self.duokan.cleanTmp() ux.showMsg(self, 'Finished', 'Clear tmp folder') def onRenameAll(self, event): self.duokan.renameAll() ux.showMsg(self, 'Finished', 'Rename All') def onMergeSingle(self, event): # file_wildcard = "Pdf files(*.pdf)|*.pdf" ret, filePath = ux.showDirDlg(self, 'Open dir to merge', os.path.join(os.getcwd(), 'tmp')) if ret and filePath: self.duokan.mergeSingle(filePath) ux.showMsg(self, 'Finished!', 'Merge single') def onCropSingle(self, event): file_wildcard = "Pdf files(*.pdf)|*.pdf" ret, filePath = ux.showFileDlg(self, 'Open file to crop', os.path.join(os.getcwd(), 'books'), file_wildcard) if ret and filePath: self.duokan.cropSingle(filePath) ux.showMsg(self, 'Finished!', 'Crop single') def onCrop4Print(self, event): file_wildcard = "Pdf files(*.pdf)|*.pdf" ret, filePath = ux.showFileDlg(self, 'Open file to crop for printing', os.path.join(os.getcwd(), 'books'), file_wildcard) if ret and filePath: self.duokan.crop4Print(filePath) ux.showMsg(self, 'Finished!', 'Crop for printing') def onCrop4Kindle(self, event): file_wildcard = "Pdf files(*.pdf)|*.pdf" ret, filePath = ux.showFileDlg(self, 'Open file to crop for printing', os.path.join(os.getcwd(), 'books'), file_wildcard) if ret and filePath: self.duokan.crop4Kindle(filePath) ux.showMsg(self, 'Finished!', 'Crop for kindle') # download a book def onDownloadItem(self, event): idx = self.list.GetFocusedItem() id = self.list.GetItemText(idx, MainWindow.COLUMN_ID) title = self.list.GetItemText(idx, MainWindow.COLUMN_TITLE) win = DownloaderWnd(self.conf, title) win.setId(id) win.setName(id) win.Show(True) # show popup menu def onShowPopup(self, event): if self.list.GetFirstSelected() != -1: pos = event.GetPosition() pos = self.list.ScreenToClient(pos) self.list.PopupMenu(self.popupmenu, pos) # open link in browser def onBrowserItem(self, event): idx = self.list.GetFirstSelected() if idx != -1: url = self.list.GetItemText(idx, MainWindow.COLUMN_LINK) self.duokan.openInNewTab(url) # rename a item from id to title def onRenameItem(self, event): idx = self.list.GetFirstSelected() if idx != -1: id = self.list.GetItemText(idx, MainWindow.COLUMN_ID) title = self.list.GetItemText(idx, MainWindow.COLUMN_TITLE) self.duokan.rename(id, title) # delete an item def onRemoveItem(self, event): idx = self.list.GetFirstSelected() if idx != -1: self.list.DeleteItem(idx) def onCropItem(self, event): idx = self.list.GetFirstSelected() if idx != -1: id = self.list.GetItemText(idx, MainWindow.COLUMN_ID) self.duokan.crop(id) def onMergeItem(self, event): idx = self.list.GetFirstSelected() if idx != -1: id = self.list.GetItemText(idx, MainWindow.COLUMN_ID) self.duokan.merge(id) def startDownload(self): if self.downloadIdx < self.list.GetItemCount(): id = self.list.GetItemText(self.downloadIdx, MainWindow.COLUMN_ID) proxy = self.conf.getProxy() self.down = Downloader(id, id, proxy[0], proxy[1], proxy[2]) self.down.bind(Downloader.EVT_START, self.cbStart) self.down.bind(Downloader.EVT_STOP, self.cbStop) self.down.bind(Downloader.EVT_LOG, self.cbLog) self.down.bind(Downloader.EVT_PROG, self.cbProgress) self.down.start() # for downloader def cbStart(self, event): wx.CallAfter(self.setProgress, self.downloadIdx, 0) # for downloader def cbStop(self, event): wx.CallAfter(self.setProgress, self.downloadIdx, 100) wx.CallAfter(self.gauge.SetValue, 100) self.list.SetItemBackgroundColour(self.downloadIdx, MainWindow.BG_DOWN) # rename id = self.list.GetItemText(self.downloadIdx, MainWindow.COLUMN_ID) title = self.list.GetItemText(self.downloadIdx, MainWindow.COLUMN_TITLE) self.duokan.rename(id, title) # start next self.downloadIdx += 1 self.startDownload() if self.downloadIdx >= self.list.GetItemCount(): if self.menubar.IsChecked(MainWindow.ID_MENUITEM_SHUTDOWN): os.system('shutdown -t 60 -f -s') # for downloader def cbLog(self, event, str): wx.CallAfter(self.addLog, str) print str # for downloader def cbProgress(self, event, prog): # itemCount = self.list.GetItemCount() # wx.CallAfter(self.setProgress, self.downloadIdx, prog) wx.CallAfter(self.gauge.SetValue, prog) # for duoSpider def cbAddUrl(self, event, url): wx.CallAfter(self.setUrl, url) # for duoSpider def cbAddBook(self, event, id, title, author, link): notFreed = self.duokan.addBook(id, title, author, link) download = self.duokan.isDownload(id) wx.CallAfter(self.appendItem, id, title, author, link, (not notFreed), download)