pluginize device drivers: configuration and fix build errors.

This commit is contained in:
John Schember 2009-05-01 21:46:15 -04:00
parent d794904319
commit 27557bb1e4
8 changed files with 204 additions and 10 deletions

View File

@ -210,7 +210,31 @@ class DevicePlugin(Plugin):
Read the file at C{path} on the device and write it to outfile. Read the file at C{path} on the device and write it to outfile.
@param outfile: file object like C{sys.stdout} or the result of an C{open} call @param outfile: file object like C{sys.stdout} or the result of an C{open} call
''' '''
raise NotImplementedError() raise NotImplementedError()
@classmethod
def config_widget(cls):
'''
Should return a QWidget. The QWidget contains the settings for the device interface
'''
raise NotImplementedError()
@classmethod
def save_settings(cls, settings_widget):
'''
Should save settings to disk. Takes the widget created in config_widget
and saves all settings to disk.
'''
raise NotImplementedError()
@classmethod
def settings(cls):
'''
Should return an opts object. The opts object should have one attribute
`formats` whihc is an ordered list of formats for the device.
'''
raise NotImplementedError()

View File

@ -13,7 +13,7 @@ from calibre import __version__, iswindows, __appname__
from calibre.devices.errors import PathError from calibre.devices.errors import PathError
from calibre.utils.terminfo import TerminalController from calibre.utils.terminfo import TerminalController
from calibre.devices.errors import ArgumentError, DeviceError, DeviceLocked from calibre.devices.errors import ArgumentError, DeviceError, DeviceLocked
from calibre.devices import devices from calibre.customize.ui import device_plugins
from calibre.devices.scanner import DeviceScanner from calibre.devices.scanner import DeviceScanner
MINIMUM_COL_WIDTH = 12 #: Minimum width of columns in ls output MINIMUM_COL_WIDTH = 12 #: Minimum width of columns in ls output
@ -203,7 +203,7 @@ def main():
_wmi = wmi.WMI() _wmi = wmi.WMI()
scanner = DeviceScanner(_wmi) scanner = DeviceScanner(_wmi)
scanner.scan() scanner.scan()
for d in devices(): for d in device_plugins():
if scanner.is_device_connected(d): if scanner.is_device_connected(d):
dev = d(log_packets=options.log_packets) dev = d(log_packets=options.log_packets)
@ -334,4 +334,4 @@ def main():
return 0 return 0
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -10,9 +10,10 @@ import os, subprocess, time, re
from calibre.devices.interface import DevicePlugin as Device from calibre.devices.interface import DevicePlugin as Device
from calibre.devices.errors import DeviceError from calibre.devices.errors import DeviceError
from calibre.devices.usbms.deviceconfig import DeviceConfig
from calibre import iswindows, islinux, isosx, __appname__ from calibre import iswindows, islinux, isosx, __appname__
class Device(Device): class Device(DeviceConfig, Device):
''' '''
This class provides logic common to all drivers for devices that export themselves This class provides logic common to all drivers for devices that export themselves
as USB Mass Storage devices. If you are writing such a driver, inherit from this as USB Mass Storage devices. If you are writing such a driver, inherit from this
@ -94,7 +95,7 @@ class Device(Device):
for pid in cls.PRODUCT_ID: for pid in cls.PRODUCT_ID:
fdi_base_values = dict( fdi_base_values = dict(
app=__appname__, app=__appname__,
deviceclass=cls.__name__, deviceclass=cls.__class__.__name__,
vendor_id=hex(vid), vendor_id=hex(vid),
product_id=hex(pid), product_id=hex(pid),
main_memory=cls.MAIN_MEMORY_VOLUME_LABEL, main_memory=cls.MAIN_MEMORY_VOLUME_LABEL,

View File

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL 3'
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
from calibre.utils.config import Config, ConfigProxy
class DeviceConfig(object):
HELP_MESSAGE = _('Ordered list of formats the device will accept')
@classmethod
def _config(cls):
c = Config('device_drivers_%s' % cls.__class__.__name__, _('settings for device drivers'))
c.add_opt('format_map', default=cls.FORMATS, help=cls.HELP_MESSAGE)
return c
def _configProxy(cls):
return ConfigProxy(cls._config())
@classmethod
def config_widget(cls):
from calibre.gui2.device_drivers.configwidget import ConfigWidget
cw = ConfigWidget(cls.configProxy(cls._config()), cls.FORMATS)
return cw
@classmethod
def save_settings(cls, config_widget):
cls.configProxy(cls._config())['format_map'] = config_widget.format_map()
@classmethod
def settings(cls):
return cls._config().parse()
def customization_help(cls, gui=False):
return cls.HELP_MESSAGE

View File

@ -33,7 +33,7 @@ from calibre.ebooks.lrf.html.table import Table
from calibre import filename_to_utf8, setup_cli_handlers, __appname__, \ from calibre import filename_to_utf8, setup_cli_handlers, __appname__, \
fit_image, preferred_encoding fit_image, preferred_encoding
from calibre.ptempfile import PersistentTemporaryFile from calibre.ptempfile import PersistentTemporaryFile
from calibre.devices.interface import Device from calibre.devices.interface import DevicePlugin as Device
from calibre.ebooks.lrf.html.color_map import lrs_color from calibre.ebooks.lrf.html.color_map import lrs_color
from calibre.ebooks.chardet import xml_to_unicode from calibre.ebooks.chardet import xml_to_unicode

View File

@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
__license__ = 'GPL 3'
__copyright__ = '2009, John Schember <john@nachtimwald.com>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import QWidget, QListWidgetItem, Qt, QVariant, SIGNAL
from calibre.gui2.device_drivers.configwidget_ui import Ui_ConfigWidget
class ConfigWidget(QWidget, Ui_ConfigWidget):
def __init__(self, config, all_formats):
QWidget.__init__(self)
Ui_ConfigWidget.__init__(self)
self.setupUi(self)
self.config = config
format_map = config['format_map']
disabled_formats = list(set(all_formats).difference(format_map))
for format in format_map + disabled_formats:
item = QListWidgetItem(format, self.columns)
item.setData(Qt.UserRole, QVariant(format))
item.setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable|Qt.ItemIsSelectable)
item.setCheckState(Qt.Checked if format in format_map else Qt.Unchecked)
self.connect(self.column_up, SIGNAL('clicked()'), self.up_column)
self.connect(self.column_down, SIGNAL('clicked()'), self.down_column)
def up_column(self):
idx = self.columns.currentRow()
if idx > 0:
self.columns.insertItem(idx-1, self.columns.takeItem(idx))
self.columns.setCurrentRow(idx-1)
def down_column(self):
idx = self.columns.currentRow()
if idx < self.columns.count()-1:
self.columns.insertItem(idx+1, self.columns.takeItem(idx))
self.columns.setCurrentRow(idx+1)
def format_map(self):
formats = [unicode(self.columns.item(i).data(Qt.UserRole).toString()) for i in range(self.columns.count()) if self.columns.item(i).checkState()==Qt.Checked]
return formats

View File

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigWidget</class>
<widget class="QWidget" name="ConfigWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>442</width>
<height>332</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Select avaliable formats and their order for this device</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QListWidget" name="columns">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QToolButton" name="column_up">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../gui2/images.qrc">
<normaloff>:/images/arrow-up.svg</normaloff>:/images/arrow-up.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="column_down">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../gui2/images.qrc">
<normaloff>:/images/arrow-down.svg</normaloff>:/images/arrow-down.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../gui2/images.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -5,9 +5,9 @@ import sys, os, shutil
from subprocess import check_call, call from subprocess import check_call, call
from calibre import __version__, __appname__ from calibre import __version__, __appname__
from calibre.devices import devices from calibre.customize.ui import device_plugins
DEVICES = devices() DEVICES = device_plugins()
DESTDIR = '' DESTDIR = ''
if os.environ.has_key('DESTDIR'): if os.environ.has_key('DESTDIR'):
@ -293,7 +293,7 @@ def setup_udev_rules(group_file, reload, fatal_errors):
</match> </match>
</match> </match>
</device> </device>
'''%dict(cls=cls.__name__, vendor_id=cls.VENDOR_ID, product_id=cls.PRODUCT_ID, '''%dict(cls=cls.__class__.__name__, vendor_id=cls.VENDOR_ID, product_id=cls.PRODUCT_ID,
prog=__appname__, bcd=cls.BCD)) prog=__appname__, bcd=cls.BCD))
fdi.write('\n'+cls.get_fdi()) fdi.write('\n'+cls.get_fdi())
fdi.write('\n</deviceinfo>\n') fdi.write('\n</deviceinfo>\n')