mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
GRiker's changes
This commit is contained in:
commit
b2e934a28a
Binary file not shown.
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
BIN
resources/images/devices/itunes.png
Normal file
BIN
resources/images/devices/itunes.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
@ -277,7 +277,6 @@ class ITUNES(DriverBase):
|
|||||||
|
|
||||||
# Fetch a list of books from iPod device connected to iTunes
|
# Fetch a list of books from iPod device connected to iTunes
|
||||||
|
|
||||||
|
|
||||||
if 'iPod' in self.sources:
|
if 'iPod' in self.sources:
|
||||||
booklist = BookList(self.log)
|
booklist = BookList(self.log)
|
||||||
cached_books = {}
|
cached_books = {}
|
||||||
@ -366,7 +365,7 @@ class ITUNES(DriverBase):
|
|||||||
self._dump_cached_books('returning from books()',indent=2)
|
self._dump_cached_books('returning from books()',indent=2)
|
||||||
return booklist
|
return booklist
|
||||||
else:
|
else:
|
||||||
return []
|
return BookList(self.log)
|
||||||
|
|
||||||
def can_handle(self, device_info, debug=False):
|
def can_handle(self, device_info, debug=False):
|
||||||
'''
|
'''
|
||||||
@ -377,7 +376,7 @@ class ITUNES(DriverBase):
|
|||||||
|
|
||||||
Confirm that:
|
Confirm that:
|
||||||
- iTunes is running
|
- iTunes is running
|
||||||
- there is an iPod-type device connected
|
- there is an iDevice connected
|
||||||
This gets called first when the device fingerprint is read, so it needs to
|
This gets called first when the device fingerprint is read, so it needs to
|
||||||
instantiate iTunes if necessary
|
instantiate iTunes if necessary
|
||||||
This gets called ~1x/second while device fingerprint is sensed
|
This gets called ~1x/second while device fingerprint is sensed
|
||||||
@ -2049,8 +2048,13 @@ class ITUNES(DriverBase):
|
|||||||
running_apps = appscript.app('System Events')
|
running_apps = appscript.app('System Events')
|
||||||
if not 'iTunes' in running_apps.processes.name():
|
if not 'iTunes' in running_apps.processes.name():
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info( "ITUNES:open(): Launching iTunes" )
|
self.log.info( "ITUNES:_launch_iTunes(): Launching iTunes" )
|
||||||
self.iTunes = iTunes= appscript.app('iTunes', hide=True)
|
try:
|
||||||
|
self.iTunes = iTunes= appscript.app('iTunes', hide=True)
|
||||||
|
except:
|
||||||
|
self.iTunes = None
|
||||||
|
raise UserFeedback(' ITUNES._launch_iTunes(): unable to find installed iTunes', details=None, level=UserFeedback.WARN)
|
||||||
|
|
||||||
iTunes.run()
|
iTunes.run()
|
||||||
self.initial_status = 'launched'
|
self.initial_status = 'launched'
|
||||||
else:
|
else:
|
||||||
@ -2091,7 +2095,12 @@ class ITUNES(DriverBase):
|
|||||||
os.path.normpath("//server/share") returns "\\\\server\\share"
|
os.path.normpath("//server/share") returns "\\\\server\\share"
|
||||||
'''
|
'''
|
||||||
# Instantiate iTunes
|
# Instantiate iTunes
|
||||||
self.iTunes = win32com.client.Dispatch("iTunes.Application")
|
try:
|
||||||
|
self.iTunes = win32com.client.Dispatch("iTunes.Application")
|
||||||
|
except:
|
||||||
|
self.iTunes = None
|
||||||
|
raise UserFeedback(' ITUNES._launch_iTunes(): unable to find installed iTunes', details=None, level=UserFeedback.WARN)
|
||||||
|
|
||||||
if not DEBUG:
|
if not DEBUG:
|
||||||
self.iTunes.Windows[0].Minimized = True
|
self.iTunes.Windows[0].Minimized = True
|
||||||
self.initial_status = 'launched'
|
self.initial_status = 'launched'
|
||||||
@ -2564,6 +2573,225 @@ class ITUNES(DriverBase):
|
|||||||
db_added.Genre = tag
|
db_added.Genre = tag
|
||||||
break
|
break
|
||||||
|
|
||||||
|
class ITUNES_ASYNC(ITUNES):
|
||||||
|
'''
|
||||||
|
This subclass allows the user to interact directly with iTunes via a menu option
|
||||||
|
'Connect to iTunes' in Send to device.
|
||||||
|
'''
|
||||||
|
name = 'iTunes interface'
|
||||||
|
gui_name = 'Apple iTunes'
|
||||||
|
icon = I('devices/itunes.png')
|
||||||
|
description = _('Communicate with iTunes.')
|
||||||
|
|
||||||
|
connected = False
|
||||||
|
|
||||||
|
def __init__(self,path):
|
||||||
|
if DEBUG:
|
||||||
|
self.log.info("ITUNES_ASYNC:__init__()")
|
||||||
|
|
||||||
|
if isosx and appscript is None:
|
||||||
|
self.connected = False
|
||||||
|
raise UserFeedback('OSX 10.5 or later required', details=None, level=UserFeedback.WARN)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.connected = True
|
||||||
|
|
||||||
|
if isosx:
|
||||||
|
self._launch_iTunes()
|
||||||
|
|
||||||
|
if iswindows:
|
||||||
|
try:
|
||||||
|
pythoncom.CoInitialize()
|
||||||
|
self._launch_iTunes()
|
||||||
|
except:
|
||||||
|
raise UserFeedback('unable to launch iTunes', details=None, level=UserFeedback.WARN)
|
||||||
|
finally:
|
||||||
|
pythoncom.CoUninitialize()
|
||||||
|
|
||||||
|
self.manual_sync_mode = False
|
||||||
|
|
||||||
|
def books(self, oncard=None, end_session=True):
|
||||||
|
"""
|
||||||
|
Return a list of ebooks on the device.
|
||||||
|
@param oncard: If 'carda' or 'cardb' return a list of ebooks on the
|
||||||
|
specific storage card, otherwise return list of ebooks
|
||||||
|
in main memory of device. If a card is specified and no
|
||||||
|
books are on the card return empty list.
|
||||||
|
@return: A BookList.
|
||||||
|
|
||||||
|
Implementation notes:
|
||||||
|
iTunes does not sync purchased books, they are only on the device. They are visible, but
|
||||||
|
they are not backed up to iTunes. Since calibre can't manage them, don't show them in the
|
||||||
|
list of device books.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not oncard:
|
||||||
|
if DEBUG:
|
||||||
|
self.log.info("ITUNES_ASYNC:books(oncard=%s)" % oncard)
|
||||||
|
|
||||||
|
# Fetch a list of books from iTunes
|
||||||
|
|
||||||
|
booklist = BookList(self.log)
|
||||||
|
cached_books = {}
|
||||||
|
|
||||||
|
if isosx:
|
||||||
|
library_books = self._get_library_books()
|
||||||
|
book_count = float(len(library_books))
|
||||||
|
for (i,book) in enumerate(library_books):
|
||||||
|
this_book = Book(library_books[book].name(), library_books[book].artist())
|
||||||
|
this_book.path = self.path_template % (library_books[book].name(),
|
||||||
|
library_books[book].artist())
|
||||||
|
try:
|
||||||
|
this_book.datetime = parse_date(str(library_books[book].date_added())).timetuple()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
this_book.db_id = None
|
||||||
|
this_book.device_collections = []
|
||||||
|
#this_book.library_id = library_books[this_book.path] if this_book.path in library_books else None
|
||||||
|
this_book.library_id = library_books[book]
|
||||||
|
this_book.size = library_books[book].size()
|
||||||
|
this_book.uuid = library_books[book].album()
|
||||||
|
# Hack to discover if we're running in GUI environment
|
||||||
|
if self.report_progress is not None:
|
||||||
|
this_book.thumbnail = self._generate_thumbnail(this_book.path, library_books[book])
|
||||||
|
else:
|
||||||
|
this_book.thumbnail = None
|
||||||
|
booklist.add_book(this_book, False)
|
||||||
|
|
||||||
|
cached_books[this_book.path] = {
|
||||||
|
'title':library_books[book].name(),
|
||||||
|
'author':[library_books[book].artist()],
|
||||||
|
'lib_book':library_books[book],
|
||||||
|
'dev_book':None,
|
||||||
|
'uuid': library_books[book].composer(),
|
||||||
|
#'format': 'pdf' if book.KindAsString.startswith('PDF') else 'epub'
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.report_progress is not None:
|
||||||
|
self.report_progress(i+1/book_count, _('%d of %d') % (i+1, book_count))
|
||||||
|
|
||||||
|
elif iswindows:
|
||||||
|
try:
|
||||||
|
pythoncom.CoInitialize()
|
||||||
|
self.iTunes = win32com.client.Dispatch("iTunes.Application")
|
||||||
|
library_books = self._get_library_books()
|
||||||
|
book_count = float(len(library_books))
|
||||||
|
for (i,book) in enumerate(library_books):
|
||||||
|
this_book = Book(library_books[book].Name, library_books[book].Artist)
|
||||||
|
this_book.path = self.path_template % (library_books[book].Name,
|
||||||
|
library_books[book].Artist)
|
||||||
|
try:
|
||||||
|
this_book.datetime = parse_date(str(library_books[book].DateAdded)).timetuple()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
this_book.db_id = None
|
||||||
|
this_book.device_collections = []
|
||||||
|
this_book.library_id = library_books[book]
|
||||||
|
this_book.size = library_books[book].Size
|
||||||
|
# Hack to discover if we're running in GUI environment
|
||||||
|
if self.report_progress is not None:
|
||||||
|
this_book.thumbnail = self._generate_thumbnail(this_book.path, library_books[book])
|
||||||
|
else:
|
||||||
|
this_book.thumbnail = None
|
||||||
|
booklist.add_book(this_book, False)
|
||||||
|
|
||||||
|
cached_books[this_book.path] = {
|
||||||
|
'title':library_books[book].Name,
|
||||||
|
'author':library_books[book].Artist,
|
||||||
|
'lib_book':library_books[book],
|
||||||
|
'uuid': library_books[book].Composer,
|
||||||
|
'format': 'pdf' if library_books[book].KindAsString.startswith('PDF') else 'epub'
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.report_progress is not None:
|
||||||
|
self.report_progress(i+1/book_count,
|
||||||
|
_('%d of %d') % (i+1, book_count))
|
||||||
|
|
||||||
|
finally:
|
||||||
|
pythoncom.CoUninitialize()
|
||||||
|
|
||||||
|
if self.report_progress is not None:
|
||||||
|
self.report_progress(1.0, _('finished'))
|
||||||
|
self.cached_books = cached_books
|
||||||
|
if DEBUG:
|
||||||
|
self._dump_booklist(booklist, 'returning from books()', indent=2)
|
||||||
|
self._dump_cached_books('returning from books()',indent=2)
|
||||||
|
return booklist
|
||||||
|
|
||||||
|
else:
|
||||||
|
return BookList(self.log)
|
||||||
|
|
||||||
|
def disconnect_from_folder(self):
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
if DEBUG:
|
||||||
|
self.log.info("ITUNES_ASYNC:disconnect_from_folder()")
|
||||||
|
self.connected = False
|
||||||
|
|
||||||
|
def eject(self):
|
||||||
|
'''
|
||||||
|
Un-mount / eject the device from the OS. This does not check if there
|
||||||
|
are pending GUI jobs that need to communicate with the device.
|
||||||
|
'''
|
||||||
|
if DEBUG:
|
||||||
|
self.log.info("ITUNES_ASYNC:eject()")
|
||||||
|
self.iTunes = None
|
||||||
|
self.connected = False
|
||||||
|
|
||||||
|
def free_space(self, end_session=True):
|
||||||
|
"""
|
||||||
|
Get free space available on the mountpoints:
|
||||||
|
1. Main memory
|
||||||
|
2. Card A
|
||||||
|
3. Card B
|
||||||
|
|
||||||
|
@return: A 3 element list with free space in bytes of (1, 2, 3). If a
|
||||||
|
particular device doesn't have any of these locations it should return -1.
|
||||||
|
"""
|
||||||
|
if DEBUG:
|
||||||
|
self.log.info("ITUNES_ASYNC:free_space()")
|
||||||
|
free_space = 0
|
||||||
|
if isosx:
|
||||||
|
s = os.statvfs(os.sep)
|
||||||
|
free_space = s.f_bavail * s.f_frsize
|
||||||
|
elif iswindows:
|
||||||
|
free_bytes = ctypes.c_ulonglong(0)
|
||||||
|
ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(os.sep), None, None, ctypes.pointer(free_bytes))
|
||||||
|
free_space = free_bytes.value
|
||||||
|
return (free_space,-1,-1)
|
||||||
|
|
||||||
|
def get_device_information(self, end_session=True):
|
||||||
|
"""
|
||||||
|
Ask device for device information. See L{DeviceInfoQuery}.
|
||||||
|
@return: (device name, device version, software version on device, mime type)
|
||||||
|
"""
|
||||||
|
if DEBUG:
|
||||||
|
self.log.info("ITUNES_ASYNC:get_device_information()")
|
||||||
|
|
||||||
|
return ('iTunes','hw v1.0','sw v1.0', 'mime type normally goes here')
|
||||||
|
|
||||||
|
def is_usb_connected(self, devices_on_system, debug=False,
|
||||||
|
only_presence=False):
|
||||||
|
return self.connected, self
|
||||||
|
|
||||||
|
def sync_booklists(self, booklists, end_session=True):
|
||||||
|
'''
|
||||||
|
Update metadata on device.
|
||||||
|
@param booklists: A tuple containing the result of calls to
|
||||||
|
(L{books}(oncard=None), L{books}(oncard='carda'),
|
||||||
|
L{books}(oncard='cardb')).
|
||||||
|
'''
|
||||||
|
|
||||||
|
if DEBUG:
|
||||||
|
self.log.info("ITUNES_ASYNC.sync_booklists()")
|
||||||
|
|
||||||
|
# Inform user of any problem books
|
||||||
|
if self.problem_titles:
|
||||||
|
raise UserFeedback(self.problem_msg,
|
||||||
|
details='\n'.join(self.problem_titles), level=UserFeedback.WARN)
|
||||||
|
self.problem_titles = []
|
||||||
|
self.problem_msg = None
|
||||||
|
self.update_list = []
|
||||||
|
|
||||||
class BookList(list):
|
class BookList(list):
|
||||||
'''
|
'''
|
||||||
|
@ -29,6 +29,7 @@ from calibre.utils.filenames import ascii_filename
|
|||||||
from calibre.devices.errors import FreeSpaceError
|
from calibre.devices.errors import FreeSpaceError
|
||||||
from calibre.utils.smtp import compose_mail, sendmail, extract_email_address, \
|
from calibre.utils.smtp import compose_mail, sendmail, extract_email_address, \
|
||||||
config as email_config
|
config as email_config
|
||||||
|
from calibre.devices.apple.driver import ITUNES_ASYNC
|
||||||
from calibre.devices.folder_device.driver import FOLDER_DEVICE
|
from calibre.devices.folder_device.driver import FOLDER_DEVICE
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
@ -105,10 +106,11 @@ class DeviceManager(Thread): # {{{
|
|||||||
self.scanner = DeviceScanner()
|
self.scanner = DeviceScanner()
|
||||||
self.connected_device = None
|
self.connected_device = None
|
||||||
self.ejected_devices = set([])
|
self.ejected_devices = set([])
|
||||||
self.connected_device_is_folder = False
|
self.mount_connection_requests = Queue.Queue(0)
|
||||||
self.folder_connection_requests = Queue.Queue(0)
|
|
||||||
self.open_feedback_slot = open_feedback_slot
|
self.open_feedback_slot = open_feedback_slot
|
||||||
|
|
||||||
|
ITUNES_STRING = '#itunes#'
|
||||||
|
|
||||||
def report_progress(self, *args):
|
def report_progress(self, *args):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -120,7 +122,7 @@ class DeviceManager(Thread): # {{{
|
|||||||
def device(self):
|
def device(self):
|
||||||
return self.connected_device
|
return self.connected_device
|
||||||
|
|
||||||
def do_connect(self, connected_devices, is_folder_device):
|
def do_connect(self, connected_devices, device_kind):
|
||||||
for dev, detected_device in connected_devices:
|
for dev, detected_device in connected_devices:
|
||||||
if dev.OPEN_FEEDBACK_MESSAGE is not None:
|
if dev.OPEN_FEEDBACK_MESSAGE is not None:
|
||||||
self.open_feedback_slot(dev.OPEN_FEEDBACK_MESSAGE)
|
self.open_feedback_slot(dev.OPEN_FEEDBACK_MESSAGE)
|
||||||
@ -133,8 +135,8 @@ class DeviceManager(Thread): # {{{
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
continue
|
continue
|
||||||
self.connected_device = dev
|
self.connected_device = dev
|
||||||
self.connected_device_is_folder = is_folder_device
|
self.connected_device_kind = device_kind
|
||||||
self.connected_slot(True, is_folder_device)
|
self.connected_slot(True, device_kind)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -152,7 +154,7 @@ class DeviceManager(Thread): # {{{
|
|||||||
if self.connected_device in self.ejected_devices:
|
if self.connected_device in self.ejected_devices:
|
||||||
self.ejected_devices.remove(self.connected_device)
|
self.ejected_devices.remove(self.connected_device)
|
||||||
else:
|
else:
|
||||||
self.connected_slot(False, self.connected_device_is_folder)
|
self.connected_slot(False, self.connected_device_kind)
|
||||||
self.connected_device = None
|
self.connected_device = None
|
||||||
|
|
||||||
def detect_device(self):
|
def detect_device(self):
|
||||||
@ -174,18 +176,18 @@ class DeviceManager(Thread): # {{{
|
|||||||
possibly_connected_devices.append((device, detected_device))
|
possibly_connected_devices.append((device, detected_device))
|
||||||
if possibly_connected_devices:
|
if possibly_connected_devices:
|
||||||
if not self.do_connect(possibly_connected_devices,
|
if not self.do_connect(possibly_connected_devices,
|
||||||
is_folder_device=False):
|
device_kind='device'):
|
||||||
prints('Connect to device failed, retrying in 5 seconds...')
|
prints('Connect to device failed, retrying in 5 seconds...')
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
if not self.do_connect(possibly_connected_devices,
|
if not self.do_connect(possibly_connected_devices,
|
||||||
is_folder_device=False):
|
device_kind='usb'):
|
||||||
prints('Device connect failed again, giving up')
|
prints('Device connect failed again, giving up')
|
||||||
|
|
||||||
def umount_device(self, *args):
|
def umount_device(self, *args):
|
||||||
if self.is_device_connected and not self.job_manager.has_device_jobs():
|
if self.is_device_connected and not self.job_manager.has_device_jobs():
|
||||||
self.connected_device.eject()
|
self.connected_device.eject()
|
||||||
self.ejected_devices.add(self.connected_device)
|
self.ejected_devices.add(self.connected_device)
|
||||||
self.connected_slot(False, self.connected_device_is_folder)
|
self.connected_slot(False, self.connected_device_kind)
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
if not self.jobs.empty():
|
if not self.jobs.empty():
|
||||||
@ -196,20 +198,19 @@ class DeviceManager(Thread): # {{{
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while self.keep_going:
|
while self.keep_going:
|
||||||
folder_path = None
|
kls = None
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
folder_path = self.folder_connection_requests.get_nowait()
|
(kls,device_kind, folder_path) = \
|
||||||
|
self.mount_connection_requests.get_nowait()
|
||||||
except Queue.Empty:
|
except Queue.Empty:
|
||||||
break
|
break
|
||||||
if not folder_path or not os.access(folder_path, os.R_OK):
|
if kls is not None:
|
||||||
folder_path = None
|
|
||||||
if not self.is_device_connected and folder_path is not None:
|
|
||||||
try:
|
try:
|
||||||
dev = FOLDER_DEVICE(folder_path)
|
dev = kls(folder_path)
|
||||||
self.do_connect([[dev, None],], is_folder_device=True)
|
self.do_connect([[dev, None],], device_kind=device_kind)
|
||||||
except:
|
except:
|
||||||
prints('Unable to open folder as device', folder_path)
|
prints('Unable to open %s as device (%s)'%(device_kind, folder_path))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
else:
|
else:
|
||||||
self.detect_device()
|
self.detect_device()
|
||||||
@ -251,13 +252,14 @@ class DeviceManager(Thread): # {{{
|
|||||||
|
|
||||||
# This will be called on the GUI thread. Because of this, we must store
|
# This will be called on the GUI thread. Because of this, we must store
|
||||||
# information that the scanner thread will use to do the real work.
|
# information that the scanner thread will use to do the real work.
|
||||||
def connect_to_folder(self, path):
|
# Note: this is used for iTunes
|
||||||
self.folder_connection_requests.put(path)
|
def mount_device(self, kls, kind, path):
|
||||||
|
self.mount_connection_requests.put((kls, kind, path))
|
||||||
|
|
||||||
# This is called on the GUI thread. No problem here, because it calls the
|
# This is called on the GUI thread. No problem here, because it calls the
|
||||||
# device driver, telling it to tell the scanner when it passes by that the
|
# device driver, telling it to tell the scanner when it passes by that the
|
||||||
# folder has disconnected.
|
# folder has disconnected. Note: this is also used for iTunes
|
||||||
def disconnect_folder(self):
|
def unmount_device(self):
|
||||||
if self.connected_device is not None:
|
if self.connected_device is not None:
|
||||||
if hasattr(self.connected_device, 'disconnect_from_folder'):
|
if hasattr(self.connected_device, 'disconnect_from_folder'):
|
||||||
# As we are on the wrong thread, this call must *not* do
|
# As we are on the wrong thread, this call must *not* do
|
||||||
@ -375,7 +377,8 @@ class DeviceMenu(QMenu): # {{{
|
|||||||
|
|
||||||
fetch_annotations = pyqtSignal()
|
fetch_annotations = pyqtSignal()
|
||||||
connect_to_folder = pyqtSignal()
|
connect_to_folder = pyqtSignal()
|
||||||
disconnect_from_folder = pyqtSignal()
|
connect_to_itunes = pyqtSignal()
|
||||||
|
disconnect_mounted_device = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QMenu.__init__(self, parent)
|
QMenu.__init__(self, parent)
|
||||||
@ -492,8 +495,18 @@ class DeviceMenu(QMenu): # {{{
|
|||||||
|
|
||||||
mitem = self.addAction(QIcon(I('eject.svg')), _('Disconnect from folder'))
|
mitem = self.addAction(QIcon(I('eject.svg')), _('Disconnect from folder'))
|
||||||
mitem.setEnabled(False)
|
mitem.setEnabled(False)
|
||||||
mitem.triggered.connect(lambda x : self.disconnect_from_folder.emit())
|
mitem.triggered.connect(lambda x : self.disconnect_mounted_device.emit())
|
||||||
self.disconnect_from_folder_action = mitem
|
self.disconnect_mounted_device_action = mitem
|
||||||
|
|
||||||
|
mitem = self.addAction(QIcon(I('document_open.svg')), _('Connect to iTunes (BETA TEST)'))
|
||||||
|
mitem.setEnabled(True)
|
||||||
|
mitem.triggered.connect(lambda x : self.connect_to_itunes.emit())
|
||||||
|
self.connect_to_itunes_action = mitem
|
||||||
|
|
||||||
|
mitem = self.addAction(QIcon(I('eject.svg')), _('Disconnect from iTunes (BETA TEST)'))
|
||||||
|
mitem.setEnabled(False)
|
||||||
|
mitem.triggered.connect(lambda x : self.disconnect_mounted_device.emit())
|
||||||
|
self.disconnect_from_itunes_action = mitem
|
||||||
|
|
||||||
self.addSeparator()
|
self.addSeparator()
|
||||||
self.addMenu(self.set_default_menu)
|
self.addMenu(self.set_default_menu)
|
||||||
@ -629,12 +642,17 @@ class DeviceMixin(object): # {{{
|
|||||||
|
|
||||||
def connect_to_folder(self):
|
def connect_to_folder(self):
|
||||||
dir = choose_dir(self, 'Select Device Folder',
|
dir = choose_dir(self, 'Select Device Folder',
|
||||||
_('Select folder to open as device'))
|
_('Select folder to open as device'))
|
||||||
if dir is not None:
|
kls = FOLDER_DEVICE
|
||||||
self.device_manager.connect_to_folder(dir)
|
self.device_manager.mount_device(kls=kls, kind='folder', path=dir)
|
||||||
|
|
||||||
def disconnect_from_folder(self):
|
def connect_to_itunes(self):
|
||||||
self.device_manager.disconnect_folder()
|
kls = ITUNES_ASYNC
|
||||||
|
self.device_manager.mount_device(kls=kls, kind='itunes', path=None)
|
||||||
|
|
||||||
|
# disconnect from both folder and itunes devices
|
||||||
|
def disconnect_mounted_device(self):
|
||||||
|
self.device_manager.unmount_device()
|
||||||
|
|
||||||
def _sync_action_triggered(self, *args):
|
def _sync_action_triggered(self, *args):
|
||||||
m = getattr(self, '_sync_menu', None)
|
m = getattr(self, '_sync_menu', None)
|
||||||
@ -649,16 +667,22 @@ class DeviceMixin(object): # {{{
|
|||||||
self.dispatch_sync_event)
|
self.dispatch_sync_event)
|
||||||
self._sync_menu.fetch_annotations.connect(self.fetch_annotations)
|
self._sync_menu.fetch_annotations.connect(self.fetch_annotations)
|
||||||
self._sync_menu.connect_to_folder.connect(self.connect_to_folder)
|
self._sync_menu.connect_to_folder.connect(self.connect_to_folder)
|
||||||
self._sync_menu.disconnect_from_folder.connect(self.disconnect_from_folder)
|
self._sync_menu.connect_to_itunes.connect(self.connect_to_itunes)
|
||||||
|
self._sync_menu.disconnect_mounted_device.connect(self.disconnect_mounted_device)
|
||||||
if self.device_connected:
|
if self.device_connected:
|
||||||
self._sync_menu.connect_to_folder_action.setEnabled(False)
|
self._sync_menu.connect_to_folder_action.setEnabled(False)
|
||||||
|
self._sync_menu.connect_to_itunes_action.setEnabled(False)
|
||||||
if self.device_connected == 'folder':
|
if self.device_connected == 'folder':
|
||||||
self._sync_menu.disconnect_from_folder_action.setEnabled(True)
|
self._sync_menu.disconnect_mounted_device_action.setEnabled(True)
|
||||||
|
if self.device_connected == 'itunes':
|
||||||
|
self._sync_menu.disconnect_from_itunes_action.setEnabled(True)
|
||||||
else:
|
else:
|
||||||
self._sync_menu.disconnect_from_folder_action.setEnabled(False)
|
self._sync_menu.disconnect_mounted_device_action.setEnabled(False)
|
||||||
else:
|
else:
|
||||||
self._sync_menu.connect_to_folder_action.setEnabled(True)
|
self._sync_menu.connect_to_folder_action.setEnabled(True)
|
||||||
self._sync_menu.disconnect_from_folder_action.setEnabled(False)
|
self._sync_menu.disconnect_mounted_device_action.setEnabled(False)
|
||||||
|
self._sync_menu.connect_to_itunes_action.setEnabled(True)
|
||||||
|
self._sync_menu.disconnect_from_itunes_action.setEnabled(False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -694,26 +718,31 @@ class DeviceMixin(object): # {{{
|
|||||||
|
|
||||||
# Device connected {{{
|
# Device connected {{{
|
||||||
|
|
||||||
def set_device_menu_items_state(self, connected, is_folder_device):
|
def set_device_menu_items_state(self, connected, device_kind):
|
||||||
if connected:
|
if connected:
|
||||||
self._sync_menu.connect_to_folder_action.setEnabled(False)
|
self._sync_menu.connect_to_folder_action.setEnabled(False)
|
||||||
if is_folder_device:
|
self._sync_menu.connect_to_itunes_action.setEnabled(False)
|
||||||
self._sync_menu.disconnect_from_folder_action.setEnabled(True)
|
if device_kind == 'folder':
|
||||||
|
self._sync_menu.disconnect_mounted_device_action.setEnabled(True)
|
||||||
|
elif device_kind == 'itunes':
|
||||||
|
self._sync_menu.disconnect_from_itunes_action.setEnabled(True)
|
||||||
self._sync_menu.enable_device_actions(True,
|
self._sync_menu.enable_device_actions(True,
|
||||||
self.device_manager.device.card_prefix(),
|
self.device_manager.device.card_prefix(),
|
||||||
self.device_manager.device)
|
self.device_manager.device)
|
||||||
self.eject_action.setEnabled(True)
|
self.eject_action.setEnabled(True)
|
||||||
else:
|
else:
|
||||||
self._sync_menu.connect_to_folder_action.setEnabled(True)
|
self._sync_menu.connect_to_folder_action.setEnabled(True)
|
||||||
self._sync_menu.disconnect_from_folder_action.setEnabled(False)
|
self._sync_menu.connect_to_itunes_action.setEnabled(True)
|
||||||
|
self._sync_menu.disconnect_mounted_device_action.setEnabled(False)
|
||||||
|
self._sync_menu.disconnect_from_itunes_action.setEnabled(False)
|
||||||
self._sync_menu.enable_device_actions(False)
|
self._sync_menu.enable_device_actions(False)
|
||||||
self.eject_action.setEnabled(False)
|
self.eject_action.setEnabled(False)
|
||||||
|
|
||||||
def device_detected(self, connected, is_folder_device):
|
def device_detected(self, connected, device_kind):
|
||||||
'''
|
'''
|
||||||
Called when a device is connected to the computer.
|
Called when a device is connected to the computer.
|
||||||
'''
|
'''
|
||||||
self.set_device_menu_items_state(connected, is_folder_device)
|
self.set_device_menu_items_state(connected, device_kind)
|
||||||
if connected:
|
if connected:
|
||||||
self.device_manager.get_device_information(\
|
self.device_manager.get_device_information(\
|
||||||
Dispatcher(self.info_read))
|
Dispatcher(self.info_read))
|
||||||
@ -722,7 +751,7 @@ class DeviceMixin(object): # {{{
|
|||||||
self.status_bar.show_message(_('Device: ')+\
|
self.status_bar.show_message(_('Device: ')+\
|
||||||
self.device_manager.device.__class__.get_gui_name()+\
|
self.device_manager.device.__class__.get_gui_name()+\
|
||||||
_(' detected.'), 3000)
|
_(' detected.'), 3000)
|
||||||
self.device_connected = 'device' if not is_folder_device else 'folder'
|
self.device_connected = device_kind
|
||||||
self.location_view.model().device_connected(self.device_manager.device)
|
self.location_view.model().device_connected(self.device_manager.device)
|
||||||
self.refresh_ondevice_info (device_connected = True, reset_only = True)
|
self.refresh_ondevice_info (device_connected = True, reset_only = True)
|
||||||
else:
|
else:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user