From ddc2e5bbdd56a3167d8d9cea991972ca6978c1eb Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 4 Dec 2006 05:25:56 +0000 Subject: [PATCH] Fixed connection errors due to timeouts in the GUI (Basically, increased the timeout in PRS500Device.open to 10s to allow device to initialize USB handler. Refactored device display code to work with changed implementation of book list parsing in libprs500 --- libprs500/books.py | 3 +- libprs500/communicate.py | 42 ++- libprs500/gui/images.qrc | 1 + libprs500/gui/images/memory_stick_unmount.png | Bin 0 -> 4630 bytes libprs500/gui/images_rc.py | 317 +++++++++++++++++- libprs500/gui/main.py | 249 +++++++------- libprs500/gui/main.ui | 46 ++- libprs500/prstypes.py | 6 +- 8 files changed, 484 insertions(+), 180 deletions(-) create mode 100644 libprs500/gui/images/memory_stick_unmount.png diff --git a/libprs500/books.py b/libprs500/books.py index 7f88c901cb..c6fac5c608 100644 --- a/libprs500/books.py +++ b/libprs500/books.py @@ -16,6 +16,7 @@ from xml.dom.ext import PrettyPrint as PrettyPrint import xml.dom.minidom as dom from base64 import b64decode as decode +import time class book_metadata_field(object): def __init__(self, attr, formatter=None): @@ -27,7 +28,7 @@ class book_metadata_field(object): class Book(object): title = book_metadata_field("title") - author = book_metadata_field("author") + author = book_metadata_field("author", formatter=lambda x: x if x.strip() else "Unknown") mime = book_metadata_field("mime") rpath = book_metadata_field("path") id = book_metadata_field("id", formatter=int) diff --git a/libprs500/communicate.py b/libprs500/communicate.py index e8e73c13cd..32a2a41464 100755 --- a/libprs500/communicate.py +++ b/libprs500/communicate.py @@ -133,17 +133,22 @@ class PRS500Device(object): PRS500_BULK_OUT_EP = 0x02 #: Endpoint for Bulk writes MEDIA_XML = "/Data/database/cache/media.xml" #: Location of media.xml file on device CACHE_XML = "/Sony Reader/database/cache.xml" #: Location of cache.xml on storage card in device + + device_descriptor = DeviceDescriptor(SONY_VENDOR_ID, PRS500_PRODUCT_ID, PRS500_INTERFACE_ID) + def safe(func): """ Decorator that wraps a call to C{func} to ensure that exceptions are handled correctly. It also calls L{open} to claim the interface and initialize the Reader if needed. - As a convenience, C{safe} automatically sends the a L{USBConnect} after calling func, unless func has + As a convenience, C{safe} automatically sends the a L{EndSession} after calling func, unless func has a keyword argument named C{end_session} set to C{False}. - An L{ArgumentError} will cause the L{USBConnect} command to be sent to the device, unless end_session is set to C{False}. + An L{ArgumentError} will cause the L{EndSession} command to be sent to the device, unless end_session is set to C{False}. An L{usb.USBError} will cause the library to release control of the USB interface via a call to L{close}. + + @todo: Fix handling of timeout errors """ def run_session(*args, **kwargs): dev = args[0] @@ -153,17 +158,21 @@ class PRS500Device(object): res = func(*args, **kwargs) except ArgumentError, e: if not kwargs.has_key("end_session") or kwargs["end_session"]: - dev._send_validated_command(USBConnect()) + dev._send_validated_command(EndSession()) raise e except usb.USBError, e: if "No such device" in str(e): raise DeviceError() - elif "Connection timed out" in str(e): + elif "Connection timed out" in str(e): + dev.close() raise TimeoutError(func.__name__) + elif "Protocol error" in str(e): + dev.close() + raise ProtocolError("There was an unknown error in the protocol. Contact the developer.") dev.close() raise e if not kwargs.has_key("end_session") or kwargs["end_session"]: - dev._send_validated_command(USBConnect()) + dev._send_validated_command(EndSession()) return res return run_session @@ -174,16 +183,23 @@ class PRS500Device(object): @param: report_progress: Function that is called with a % progress (number between 0 and 100) for various tasks If it is called with -1 that means that the task does not have any progress information """ - self.device_descriptor = DeviceDescriptor(PRS500Device.SONY_VENDOR_ID, - PRS500Device.PRS500_PRODUCT_ID, - PRS500Device.PRS500_INTERFACE_ID) self.device = self.device_descriptor.getDevice() #: The actual device (PyUSB object) self.handle = None #: Handle that is used to communicate with device. Setup in L{open} self._log_packets = log_packets self.report_progress = report_progress - def is_connected(self): - return self.device_descriptor.getDevice() != None + def reconnect(self): + self.device = self.device_descriptor.getDevice() + self.handle = None + + @classmethod + def is_connected(cls): + """ + This method checks to see whether the device is physically connected. + It does not return any information about the validity of the software connection. You may need to call L{reconnect} if you keep + getting L{DeviceError}. + """ + return cls.device_descriptor.getDevice() != None @classmethod def _validate_response(cls, res, type=0x00, number=0x00): @@ -205,7 +221,7 @@ class PRS500Device(object): raise DeviceError() self.handle = self.device.open() self.handle.claimInterface(self.device_descriptor.interface_id) - res = self._send_validated_command(GetUSBProtocolVersion()) + res = self._send_validated_command(GetUSBProtocolVersion(), timeout=10000) # Large timeout as device mat still be initializing if res.code != 0: raise ProtocolError("Unable to get USB Protocol version.") version = self._bulk_read(24, data_type=USBProtocolVersion)[0].version if version not in KNOWN_USB_PROTOCOL_VERSIONS: @@ -216,12 +232,12 @@ class PRS500Device(object): if res.code != 0: raise ProtocolError("Unlocking of device not implemented. Remove locking and retry.") - def close(self): """ Release device interface """ + self.handle.reset() self.handle.releaseInterface() self.handle, self.device = None, None - + def _send_command(self, command, response_type=Response, timeout=1000): """ Send L{command} to device and return its L{response}. diff --git a/libprs500/gui/images.qrc b/libprs500/gui/images.qrc index e8c6bc113e..5c1aee6a10 100644 --- a/libprs500/gui/images.qrc +++ b/libprs500/gui/images.qrc @@ -3,6 +3,7 @@ images/cherubs.jpg images/mycomputer.png images/reader.png + images/memory_stick_unmount.png images/clear.png images/minus.png images/plus.png diff --git a/libprs500/gui/images/memory_stick_unmount.png b/libprs500/gui/images/memory_stick_unmount.png new file mode 100644 index 0000000000000000000000000000000000000000..f4d3a653a6ad58392c1f5b84f0c6e0e69e811332 GIT binary patch literal 4630 zcmV+x66x)UP)kuYccf|E||PLTk+*vl#Pjzin3WaGw-7jE9X zIrw^Xh(E+WV9S;*%al@gyRN&=^E?B$@QY7;=JQ{EExP`oJmC84uQ#52^2u*1rS>VM zE~zn6{!0tDny#n5aMMjUz5TW5^qp-Z-zeF-b?e(Mz4X%iq?D@+Lr0cd8(EQigt5Gz zaNs4gDzx-JfNKDR5Pq$-dnS6%`4HH;b*oP)^&KhY_oS3Y-0csXH*qUwahTykl;)U6 z(re^d|6j?`@zj#JH$}so~3jzSGTdP7<(n>(-EIn*Zc^-Z!O`X1sjRw>otP zx-deo6@vkRkWjx?A`C&M9AKgIqL^&>@CRyZYwt^^(`8_V5aNhFjf?$ABn&_54rM>z>qsYKDfk0q`<2Vvn2^@Q+dCv(C=<4eFpwH(!?7Hq}wVe+wns~}s zntYs*v`bk>2pq|i>aj6Heuno4*!y&dBb@;<2|=;833btT&~N)9buFui1kJ#wuKmQ- zQ>tr(5RI=i_q=*QPft%>u~@v-^St%0>xLrM5wRfKN#05`PztapF39Z~#~LmJFw*T% zwZH@_VeS8ub-3%k21XFHMr+N|rENyBWPcj??bI|Yf#l2CFmE2PXV0E%%jI&P=Xux2 zq7`mT?G*Ks-3(3G*n=sWm5Xoo1v_s#ypTe>pqe^gdw!{{0JG*S*v8y!VyM+#8xh*{+&zEB?~j)VPaDpwJ3Y7RR7uc7vu0HFv<`550*rWCw{rmx&iiYT7vVHgHNh~r?43Y?ZDD+os73$DEK%GFc176~E3 zbJ_H!5ODC|!M6ST_doA>-YtbfA*R#0P}RgFnTZUEyhBT40}&yxj}6X@QMOC!g+16= zNx@pk!mr&)%U|9=B9o(BF3*4!Ld=k$wMGbmX__o*X*RC9{E{zDsT078xomr*2{3wl zd;dmjy{}v@Us6aHqW+XbXUYsE(}cq@7SuO^2vXenJj@EmQ2T0XuDPBCe{nOurX`Gw zj9^(7a2zZgkN*=%S=_doXuM(7+O=z^dx2#_2>&StzEQ{r1_svj_V(^{9Os{Nxm?&w zd%=JeAd$+DDcZC)FCrYSMhidQ@KL;xej-6M=ieEQmS(=-?<@!|Ks@46|Id_dc5JI{IrP{TV9pueC-?Nx63u`TdVjCnCh_KX!3@dwb21BS$j8av?;o)>=*5dseH!=;-LX zY}kny({}2qdOzE4r4-)eA+o>!3FWb2JQpwoy~8&ypm_ch+!2h#wW*Vh(%$`ji_V0P97MDU|juGBC9T7 z!3F2zk3?tUI-k!oF)=X%^u%m0gqZoiQVQjk$h`1VCOfv{6$KzbRNiaDyNrb`AG*4s zq2bS{?rr?e9*|0@Ix?9I ztO$&kW@jXq~bxEhwr^Nd-V8bwGuDxQK ziLPIg?bwRSIRw{)(8@tM5(5Y>F^R@w1cM=59jB>QE{+ zIV)5Zs=_b~jvYHjBphMM;w31l(54@A(Rp}1#|cn7?x*F0*HX89=}B%~EEdV-ax)2T zI;l;6=lC^b4sBy%?gT-FMtPI5?P_1w{i@z~mX{fP6mxDbMq6&*gH#d_Etli`RjI zp`jt-)p4pKRY)mOQlX?mdX>-8m3Vue#Oru~w(s3VXwixpaE{|(Sr$sEnV3Ei@H9bM zx{U7n9h1*Jj2=9S0K5xUVkjF~E+L{mqR}uBzhu<6N)LN2<&GUYZ+ZBU-|UzJN*3tS zT4&%4l3=k|Y*9-6%(m^zQ>j!W91c@cUBl?eD5X+~h0O~qhPn!^G@k3Bl}5S}DJ9`p zn7YOlwG#=@T9X|aVCb1&!Jh5tf`t|avataj^daM6g0V2Mh!16k z=#dx5%;flsx8C{Sj}wVRaTXK>8~_fTxJ~woAy6)tzpSJCC>9aip3&Q%9*4#yR8NAY@7aKP|(OzUAh~3(be^Cpuu!$`K9Clk}Dlz)}ZFk&r z$JA!%iQ)nKwAM#nZjnzRKuY=Np6C56olcvDLc!nI*ofmejE;`d)YL>Q7OQ}signNP zDg=}YSTAlNeDOyraqoF(sfjnni8sV?9H%nwgm^!(t}CU;XY(B1xtGlN2+=){;ZGa_ z1R5wUT7$i)op^PGfax*h)ylMOOsX^UQ%cu#E%VTI<=NaFU!70#eG7ZQIha ztkB}ciy0goLE(k8R}ghL{Ei*LXjFz5sHPTnzQ5O zZF-(SgQA8*c0`Vi4FC4F+wb~C zKA)d`0^|UDwAO>1ft*4>AQ0GCDwWb&>*#c8s;#X(3A|DYRkSE{JWlw6%W=ks5vD=- zJs-u|@B<_aM7BQMN;kYQ{8N`b$Ww>`rdlvgwBBpMQR?Lyuu#m)6=o6Y%gdIUt=*f3;93+)yr;V@*v> z3=a>}+S+=O+h(7B5LwD&4;-SjcRR7GKZkGG`FQ0b&c5FxmR*QmaWS6b0kHhMZ!D>XiQf@obWVZVXpl^7}7a%gbiH~(|zT@RK@ zrP)VbWh(AIdZxgqWzH&4C=~7%Li`|?%hBB2jA0nKt~;}8<-^_h7Pc{Q%im(wHRD^b z3{|$s-uF+a+ynsO3$H>`aeLQsnM_R5*wTnnisVR=Bi*|Z+wLJc+=KRP$_vhCa`i`$ z!oc(k;&ts9hR4zDxK}6@6OV4(c*BkzJLYoheqisJ9)_L~0gDzbDh&+{-5d&qzBM*B z7Hw*3B9%%}Utf<>3TI*r|Ke3>*Tx&K*yIjY@{kCI@m+WoM(awX>!P$mX+>fGd7yd+4sa?)tUkIBJ%e z1uCWOWw*RvGXVgOF!8mWhlte>y!?~M$pqqU z>nf#CDfHCKbzSy!?SbSF(Wh<(yFj@AMJ6x44m-Axkm(~9jiIEXH__|mi}_<49^PVX>e_t~J%a<=t?A^QfexJ|xnX$34aARX5nM{UgG>TDOkJG;&grMrv z-^N_njypMyvL-Rw--*&1rB7&Yb%h8cJC1+ze_($YdQnM6v7*>*meTmG8Z z$G?H7X-0VtW=lKH!7fBFeA4PmRaqp3!r%F8%#wu?P+t0O?Du?zy7~o_%Vl==?{+QA z>U;245B}G_efws+wE_-OX=7)H!t0XLJ_~eqc5bmO>#Fwlc7HS)#j-5?em{k$9{|Hd z`}}BOU{uv1R=&H^7mfaf=X$v1627iYc<~m(=f97DKS1ALpBzpO%iX(o z-*NA~_dYX+36oS-{ggKLO(CG8qvHzKbvL`N8@cSV%NQ6KAQ%jyl|*Tft_Gn|y0ULK z1Na0YW(aUxBH;*Cu`2TUJY79qZYGo2f8YK0{iwIMceYzgU>|VWGyXS}0DxzoeRh{+ zSr=S%(M7`V_hVVsOfsC<)`ROx>MmQ2QpcYOT-Qaqvf>GzLLjKAsUhSKv8!j7H#|1% zcD~qo+d~gMw0({#6I3$%E4Hy`L(XVJL@D*JKA-Q7Lx&DkuUofnX6HsJg|n{%naiRs zU0DII6t3sa+($z^9w!!yk;!D(+OgHkq%$ww{foPQGRH=R3+z7AHuh}D84-|9rymIh zgEuDZlH*KveT3+F3uYd6q?8z@K|@0W;b54K9UboI*r>g2 z`?mjn?6JpQoMW0--Nv2`Iir)IYp=alDy4p4nr6DEr-!<_I!x0fy<O;WV2Zu$0T}Mv?a}e^@%_nU za%f~^WTd;hdoY{LI&+->uSL$<;iwRz7AR}2OJ_yl znError: "+str(e)+"

Traceback:
"+traceback.format_exc(e)) - def __init__(self, window): + def __init__(self, window, log_packets): QObject.__init__(self) Ui_MainWindow.__init__(self) - self.dev = device(report_progress=self.progress) + self.dev = device(report_progress=self.progress, log_packets=log_packets) self.is_connected = False self.setupUi(window) self.card = None @@ -618,52 +606,58 @@ class MainWindow(QObject, Ui_MainWindow): QObject.connect(self.library_model, SIGNAL("dataChanged(QModelIndex, QModelIndex)"), self.resize_columns) self.library_view.resizeColumnsToContents() - # Create Device list - self.tree = QStandardItemModel() - library = QStandardItem(QString("Library")) - library.setIcon(QIcon(":/library")) - font = library.font() - font.setBold(True) - self.tree.appendRow(library) - library.setFont(font) - library.appendRow(QStandardItem(QString("Books"))) - blank = QStandardItem(" ") - blank.setEnabled(False) - self.tree.appendRow(blank) - self.reader = QStandardItem(QString("SONY Reader")) - mm = QStandardItem(QString("Main Memory")) - mm.appendRow(QStandardItem(QString("Books"))) - self.reader.appendRow(mm) - mc = QStandardItem(QString("Storage Card")) - mc.appendRow(QStandardItem(QString("Books"))) - self.reader.appendRow(mc) - self.reader.setIcon(QIcon(":/reader")) - self.tree.appendRow(self.reader) - self.reader.setFont(font) - self.treeView.setModel(self.tree) - self.treeView.header().hide() - self.treeView.setExpanded(library.index(), True) - self.treeView.setExpanded(self.reader.index(), True) - self.treeView.setExpanded(mm.index(), True) - self.treeView.setExpanded(mc.index(), True) - self.treeView.setRowHidden(2, self.tree.invisibleRootItem().index(), True) - QObject.connect(self.treeView, SIGNAL("activated(QModelIndex)"), self.tree_clicked) - QObject.connect(self.treeView, SIGNAL("clicked(QModelIndex)"), self.tree_clicked) + # Create Device tree + QObject.connect(self.device_tree, SIGNAL("itemClicked ( QTreeWidgetItem *, int )"), self.tree_clicked) + QObject.connect(self.device_tree, SIGNAL("itemActivated ( QTreeWidgetItem *, int )"), self.tree_clicked) + self.device_tree.header().hide() + library = QTreeWidgetItem(self.device_tree, QTreeWidgetItem.Type) + library.setData(0, Qt.DisplayRole, QVariant("Library")) + library.setData(0, Qt.DecorationRole, QVariant(QIcon(":/library"))) + books =QTreeWidgetItem(library, QTreeWidgetItem.Type) + books.setData(0, Qt.DisplayRole, QVariant("Books")) + self.device_tree.expandItem(library) + buffer = QTreeWidgetItem(self.device_tree, QTreeWidgetItem.Type) + buffer.setFlags(Qt.ItemFlags()) + library = QTreeWidgetItem(self.device_tree, QTreeWidgetItem.Type) + library.setData(0, Qt.DisplayRole, QVariant("SONY Reader")) + library.setData(0, Qt.DecorationRole, QVariant(QIcon(":/reader"))) + books =QTreeWidgetItem(library, QTreeWidgetItem.Type) + books.setData(0, Qt.DisplayRole, QVariant("Books")) + self.device_tree.expandItem(library) + buffer = QTreeWidgetItem(self.device_tree, QTreeWidgetItem.Type) + buffer.setFlags(Qt.ItemFlags()) + library = QTreeWidgetItem(self.device_tree, QTreeWidgetItem.Type) + library.setData(0, Qt.DisplayRole, QVariant("Storage Card")) + library.setData(0, Qt.DecorationRole, QVariant(QIcon(":/card"))) + books =QTreeWidgetItem(library, QTreeWidgetItem.Type) + books.setData(0, Qt.DisplayRole, QVariant("Books")) + self.device_tree.expandItem(library) + self.device_tree.reader = self.device_tree.topLevelItem(2) + self.device_tree.card = self.device_tree.topLevelItem(4) + def hider(i): + def do(s, x): s.topLevelItem(i).setHidden(x), s.topLevelItem(i+1).setHidden(x) + return do + self.device_tree.hide_reader = hider(1) + self.device_tree.hide_card = hider(3) + self.device_tree.hide_reader(self.device_tree, True) + self.device_tree.hide_card(self.device_tree, True) + # Create Device Book list - self.device_model = DeviceBooksModel(window, []) - self.device_view.setModel(self.device_model) + self.reader_model = DeviceBooksModel(window) + self.card_model = DeviceBooksModel(window) + self.device_view.setModel(self.reader_model) self.device_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.device_view.setSortingEnabled(True) self.device_view.contextMenuEvent = self.list_context_event - QObject.connect(self.device_model, SIGNAL("layoutChanged()"), self.device_view.resizeRowsToContents) QObject.connect(self.device_view.selectionModel(), SIGNAL("currentChanged(QModelIndex, QModelIndex)"), self.show_book) - QObject.connect(self.search, SIGNAL("textChanged(QString)"), self.device_model.search) - QObject.connect(self.device_model, SIGNAL("sorted()"), self.model_modified) - QObject.connect(self.device_model, SIGNAL("searched()"), self.model_modified) - QObject.connect(self.device_model, SIGNAL("deleted()"), self.model_modified) - QObject.connect(self.device_model, SIGNAL("dataChanged(QModelIndex, QModelIndex)"), self.resize_columns) - self.device_view.hide() + for model in (self.reader_model, self. card_model): + QObject.connect(model, SIGNAL("layoutChanged()"), self.device_view.resizeRowsToContents) + QObject.connect(self.search, SIGNAL("textChanged(QString)"), model.search) + QObject.connect(model, SIGNAL("sorted()"), self.model_modified) + QObject.connect(model, SIGNAL("searched()"), self.model_modified) + QObject.connect(model, SIGNAL("deleted()"), self.model_modified) + QObject.connect(model, SIGNAL("dataChanged(QModelIndex, QModelIndex)"), self.resize_columns) # Setup book display self.BOOK_TEMPLATE = self.book_info.text() @@ -679,6 +673,7 @@ class MainWindow(QObject, Ui_MainWindow): self.device_detector = self.startTimer(1000) self.splitter.setStretchFactor(1,100) self.search.setFocus(Qt.OtherFocusReason) + self.show_device(False) window.show() def timerEvent(self, e): @@ -692,13 +687,13 @@ class MainWindow(QObject, Ui_MainWindow): def device_removed(self, timeout=False): """ @todo: only reset stuff if library is not shown """ self.is_connected = False - self.df.setText("Main memory:

Storage card:") - self.card = None - self.treeView.setRowHidden(2, self.tree.invisibleRootItem().index(), True) - self.device_model.set_data([]) + self.df.setText("SONY Reader:

Storage card:") + self.device_tree.hide_reader(self.device_tree, True) + self.device_tree.hide_card(self.device_tree, True) self.book_cover.hide() self.book_info.hide() self.device_view.hide() + self.library_view.show() def timeout_error(self): @@ -715,6 +710,7 @@ class MainWindow(QObject, Ui_MainWindow): self.progress_bar.setMaximum(100) self.progress_bar.reset() self.progress_bar.setFormat(msg + ": %p%") + self.progress(0) QCoreApplication.processEvents(QEventLoop.ExcludeUserInputEvents) def establish_connection(self): @@ -722,39 +718,38 @@ class MainWindow(QObject, Ui_MainWindow): self.status("Connecting to device") try: space = self.dev.available_space() - except TimeoutError: - c = 0 - self.status("Waiting for device to initialize") - while c < 100: # Delay for 10s while device is initializing - if c % 10 == c/10: - self.progress(c) - QThread.currentThread().msleep(100) - c += 1 - space = self.dev.available_space() + except DeviceError: + self.dev.reconnect() + return + except ProtocolError, e: + traceback.print_exc(e) + print >> sys.stderr, "Unable to connect device. Please try unplugiing and reconnecting it" + qFatal("Unable to connect device. Please try unplugiing and reconnecting it") + sc = space[1][1] if space[1][1] else space[2][1] - self.df.setText("Main memory: " + human_readable(space[0][1]) + "

Storage card: " + human_readable(sc)) + self.df.setText("SONY Reader: " + human_readable(space[0][1]) + "

Storage card: " + human_readable(sc)) self.is_connected = True - if space[1][2] > 0: self.card = "a:" - elif space[2][2] > 0: self.card = "b:" - else: self.card = None - if self.card: self.treeView.setRowHidden(1, self.reader.index(), False) - else: self.treeView.setRowHidden(1, self.reader.index(), True) - self.treeView.setRowHidden(2, self.tree.invisibleRootItem().index(), False) - self.status("Loading media list from device") - mb, cb, mx, cx = self.dev.books() - - for x in (mb, cb): - for book in x: - if "&" in book["author"]: - book["author"] = re.sub(r"&\s*", r"\n", book["author"]) - - self.main_books = mb - self.card_books = cb - self.main_xml = mx - self.cache_xml = cx + if space[1][2] > 0: card = "a:" + elif space[2][2] > 0: card = "b:" + else: card = None + if card: self.device_tree.hide_card(self.device_tree, False) + else: self.device_tree.hide_card(self.device_tree, True) + self.device_tree.hide_reader(self.device_tree, False) + self.status("Loading media list from SONY Reader") + self.reader_model.set_data(self.dev.books()) + if card: self.status("Loading media list from Storage Card") + self.card_model.set_data(self.dev.books(oncard=True)) + self.progress(100) self.window.setCursor(Qt.ArrowCursor) def main(): + from optparse import OptionParser + from libprs500 import __version__ as VERSION + parser = OptionParser(usage="usage: %prog [options]", version=VERSION) + parser.add_option("--log-packets", help="print out packet stream to stdout. "+\ + "The numbers in the left column are byte offsets that allow the packet size to be read off easily.", \ + dest="log_packets", action="store_true", default=False) + options, args = parser.parse_args() from PyQt4.Qt import QApplication, QMainWindow app = QApplication(sys.argv) global DEFAULT_BOOK_COVER @@ -771,7 +766,7 @@ def main(): handler = QErrorMessage.qtHandler() handler.resize(600, 400) handler.setModal(True) - gui = MainWindow(window) + gui = MainWindow(window, options.log_packets) ret = app.exec_() return ret diff --git a/libprs500/gui/main.ui b/libprs500/gui/main.ui index aa03ac7d31..cd4011a208 100644 --- a/libprs500/gui/main.ui +++ b/libprs500/gui/main.ui @@ -53,36 +53,30 @@ 6 - - - - 1 - 7 - 0 - 0 - - - - true - - - QFrame::Plain - - - Qt::ScrollBarAsNeeded - - - false + + + QAbstractItemView::DropOnly true - - 15 + + false - + true + + true + + + 1 + + + + 1 + + @@ -299,7 +293,7 @@ Add files to Library - a + A false @@ -313,7 +307,7 @@ Delete selected items - Delete + Del @@ -324,7 +318,7 @@ Edit meta-information for the currently selected items - e + E false diff --git a/libprs500/prstypes.py b/libprs500/prstypes.py index b297518a08..c64d7858fe 100755 --- a/libprs500/prstypes.py +++ b/libprs500/prstypes.py @@ -204,7 +204,7 @@ class Command(TransferBuffer): Command numbers are: 0 GetUsbProtocolVersion - 1 ReqUsbConnect + 1 ReqEndSession 10 FskFileOpen 11 FskFileClose @@ -343,11 +343,11 @@ class DirClose(ShortCommand): """ @param id: The identifier returned as a result of a L{DirOpen} command """ ShortCommand.__init__(self, number=DirClose.NUMBER, type=0x01, command=id) -class USBConnect(ShortCommand): +class EndSession(ShortCommand): """ Ask device to change status to 'USB connected' i.e., tell the device that the present sequence of commands is complete """ NUMBER=0x1 #: Command number def __init__(self): - ShortCommand.__init__(self, number=USBConnect.NUMBER, type=0x01, command=0x00) + ShortCommand.__init__(self, number=EndSession.NUMBER, type=0x01, command=0x00) class GetUSBProtocolVersion(ShortCommand): """ Get USB Protocol version used by device """