diff --git a/resources/images/connect_share.svg b/resources/images/connect_share.svg new file mode 100644 index 0000000000..ab582ddc57 --- /dev/null +++ b/resources/images/connect_share.svg @@ -0,0 +1,5123 @@ + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/images/dictionary.png b/resources/images/dictionary.png deleted file mode 100644 index e9bd55d918..0000000000 Binary files a/resources/images/dictionary.png and /dev/null differ diff --git a/resources/images/dictionary.svg b/resources/images/dictionary.svg new file mode 100644 index 0000000000..37b17baf48 --- /dev/null +++ b/resources/images/dictionary.svg @@ -0,0 +1,1009 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/images/user_profile.svg b/resources/images/user_profile.svg index 0aecc0c1f7..3b2f36131a 100644 --- a/resources/images/user_profile.svg +++ b/resources/images/user_profile.svg @@ -2,7 +2,7 @@ + sodipodi:docbase="/home/pinheiro/artwork/Oxygen/theme/svg/actions" + sodipodi:docname="user_female.svg"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + inkscape:window-width="1106" + inkscape:window-height="958" + inkscape:window-x="128" + inkscape:window-y="215"> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="metadata1312"> image/svg+xml + + + + Oxygen team + + + + + + + + + + + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + + + style="opacity:0.38139535;fill:url(#radialGradient3297);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" + id="path3289" + sodipodi:cx="63.912209" + sodipodi:cy="115.70919" + sodipodi:rx="63.912209" + sodipodi:ry="12.641975" + d="M 127.82442 115.70919 A 63.912209 12.641975 0 1 1 0,115.70919 A 63.912209 12.641975 0 1 1 127.82442 115.70919 z" + transform="matrix(1,0,0,0.416667,0.266436,74.25798)" /> + style="fill:black;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 64.126842,1.3826379 C 58.426392,1.4554645 52.905637,4.1403867 48.381995,10.414566 C 35.911196,13.756106 32.695587,31.476866 31.599697,43.796082 C 30.207379,59.447533 38.215631,69.284604 49.114313,73.516007 C 48.955505,75.292398 48.560056,76.805464 48.015836,77.726838 C 45.968001,81.19384 41.318471,84.201393 33.277926,86.484146 C 24.307525,89.030883 17.192434,91.505674 12.040691,96.0348 C 7.4798115,100.04448 4.5344266,104.68101 4.5344266,110.62014 C 4.5344266,126.036 123.87182,126.85211 123.87182,110.62014 C 123.87183,104.68101 120.92644,100.04447 116.36556,96.0348 C 111.27103,91.555971 104.15639,88.925208 95.128324,86.362093 C 87.028227,84.062439 82.381647,81.149675 80.359901,77.726838 C 79.684606,76.58356 79.264762,74.560445 79.200397,72.203936 C 89.11651,67.571946 96.962124,58.62877 98.118624,45.443799 C 99.954507,24.513404 81.228191,1.1641579 64.126842,1.3826379 z " + id="path2375" /> - - - - - + id="path2878" + d="M 64.126842,1.3826379 C 58.426392,1.4554645 52.905637,4.1403867 48.381995,10.414566 C 35.911196,13.756106 32.695587,31.476866 31.599697,43.796082 C 30.207379,59.447533 38.215631,69.284604 49.114313,73.516007 C 48.955505,75.292398 48.560056,76.805464 48.015836,77.726838 C 45.968001,81.19384 41.318471,84.201393 33.277926,86.484146 C 24.307525,89.030883 17.192434,91.505674 12.040691,96.0348 C 7.4798115,100.04448 4.5344266,104.68101 4.5344266,110.62014 C 4.5344266,126.036 123.87182,126.85211 123.87182,110.62014 C 123.87183,104.68101 120.92644,100.04447 116.36556,96.0348 C 111.27103,91.555971 104.15639,88.925208 95.128324,86.362093 C 87.028227,84.062439 82.381647,81.149675 80.359901,77.726838 C 79.684606,76.58356 79.264762,74.560445 79.200397,72.203936 C 89.11651,67.571946 96.962124,58.62877 98.118624,45.443799 C 99.954507,24.513404 81.228191,1.1641579 64.126842,1.3826379 z " + style="fill:black;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:url(#linearGradient2898);fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.2073171" + d="M 63.805682,2.3189945 C 60.204653,2.3650007 56.68272,3.4814485 53.43117,5.8585338 C 56.378477,3.9906882 61.133543,3.7479685 64.326992,4.0398775 C 79.377077,5.4155836 98.565383,26.21259 96.7295,47.142988 C 95.820607,57.505059 90.782821,65.24448 83.8529,70.333073 C 91.331974,65.269474 96.842277,57.270013 97.797464,46.380156 C 99.633352,25.449758 80.907031,2.1005146 63.805682,2.3189945 z " + id="path2882" + sodipodi:nodetypes="ccsscsc" /> + style="fill:url(#linearGradient2911);fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 79.147382,75.901301 C 79.100289,75.923554 79.049359,75.937341 79.002158,75.959388 C 79.063429,78.202509 79.46307,80.128263 80.10587,81.216537 C 82.030334,84.47468 86.453333,87.247287 94.163669,89.436284 C 102.75732,91.876067 109.52963,94.380244 114.37901,98.643562 C 118.37935,102.16043 121.06728,106.18674 121.466,111.22007 C 121.49137,111.05961 121.5241,110.89043 121.5241,110.7263 C 121.5241,105.07295 118.72043,100.65951 114.37901,96.842768 C 109.52963,92.579463 102.75732,90.075276 94.163669,87.635494 C 86.453333,85.446506 82.030334,82.673889 80.10587,79.415746 C 79.636815,78.621639 79.320492,77.385183 79.147382,75.901301 z " + id="path2900" + sodipodi:nodetypes="ccssscssssc" /> + sodipodi:nodetypes="ccssscssssc" + id="path2913" + d="M 50.410374,75.901301 C 50.457467,75.923554 50.508398,75.937341 50.555598,75.959388 C 50.494327,78.202509 50.094687,80.128263 49.451887,81.216537 C 47.527422,84.47468 43.104424,87.247287 35.394087,89.436284 C 26.800432,91.876067 20.028126,94.380244 15.178743,98.643562 C 11.178409,102.16043 8.4904782,106.18674 8.0917552,111.22007 C 8.0663877,111.05961 8.033658,110.89043 8.033658,110.7263 C 8.033658,105.07295 10.837325,100.65951 15.178743,96.842768 C 20.028126,92.579463 26.800432,90.075276 35.394087,87.635494 C 43.104424,85.446506 47.527422,82.673889 49.451887,79.415746 C 49.920942,78.621639 50.237264,77.385183 50.410374,75.901301 z " + style="fill:url(#linearGradient2915);fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="opacity:0.19262294;fill:url(#linearGradient2934);fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 64.126842,1.3826379 C 58.426392,1.4554645 52.905637,4.1403867 48.381995,10.414566 C 35.911196,13.756106 32.695587,31.476866 31.599697,43.796082 C 30.207379,59.447533 38.215631,69.284604 49.114313,73.516007 C 48.955505,75.292398 48.560056,76.805464 48.015836,77.726838 C 45.968001,81.19384 41.318471,84.201393 33.277926,86.484146 C 24.307525,89.030883 17.192434,91.505674 12.040691,96.0348 C 10.934256,97.007517 9.9476914,98.029977 9.0503905,99.086127 C 43.790302,112.20602 86.237691,93.86764 120.45434,100.45922 C 119.31869,98.895255 117.94232,97.420999 116.36556,96.0348 C 111.27103,91.555971 104.15639,88.925208 95.128324,86.362093 C 87.028227,84.062439 82.381647,81.149675 80.359901,77.726838 C 79.684606,76.58356 79.264762,74.560445 79.200397,72.203936 C 89.11651,67.571946 96.962124,58.62877 98.118624,45.443799 C 99.954507,24.513404 81.228191,1.1641579 64.126842,1.3826379 z " + id="path2923" + sodipodi:nodetypes="ccscsssccssscsc" /> + style="opacity:0.147541;fill:url(#linearGradient2942);fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 64.126842,1.3826379 C 58.426392,1.4554645 52.905637,4.1403867 48.381995,10.414566 C 35.911196,13.756106 32.695587,31.476866 31.599697,43.796082 C 30.590647,55.139108 34.51846,63.410713 40.906244,68.725424 C 46.499431,43.086176 60.253253,23.183408 81.916078,8.8889022 C 76.436168,4.2058259 70.185402,1.3052361 64.126842,1.3826379 z M 91.588784,20.392405 C 69.413597,38.642858 59.93157,63.059075 62.204506,99.635366 C 82.545047,99.174142 102.74074,98.667446 120.45434,100.45922 C 119.31869,98.895255 117.94232,97.420999 116.36556,96.0348 C 111.27103,91.555971 104.15639,88.925208 95.128324,86.362093 C 87.028227,84.062439 82.381647,81.149675 80.359901,77.726838 C 79.684606,76.58356 79.264762,74.560445 79.200397,72.203936 C 89.11651,67.571946 96.962124,58.62877 98.118624,45.443799 C 98.867542,36.905593 96.177208,27.971578 91.588784,20.392405 z " + id="path2936" + sodipodi:nodetypes="ccsccccccssscsc" /> - - + style="fill:url(#radialGradient2824);fill-opacity:1.0;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;opacity:0.41803279" + d="M 64.126842,1.3826379 C 58.426392,1.4554645 52.905637,4.1403867 48.381995,10.414566 C 35.911196,13.756106 32.695587,31.476866 31.599697,43.796082 C 30.207379,59.447533 38.215631,69.284604 49.114313,73.516007 C 48.955505,75.292398 48.560056,76.805464 48.015836,77.726838 C 45.968001,81.19384 41.318471,84.201393 33.277926,86.484146 C 24.307525,89.030883 17.192434,91.505674 12.040691,96.0348 C 7.4798115,100.04448 4.5344266,104.68101 4.5344266,110.62014 C 4.5344266,126.036 123.87182,126.85211 123.87182,110.62014 C 123.87183,104.68101 120.92644,100.04447 116.36556,96.0348 C 111.27103,91.555971 104.15639,88.925208 95.128324,86.362093 C 87.028227,84.062439 82.381647,81.149675 80.359901,77.726838 C 79.684606,76.58356 79.264762,74.560445 79.200397,72.203936 C 89.11651,67.571946 96.962124,58.62877 98.118624,45.443799 C 99.954507,24.513404 81.228191,1.1641579 64.126842,1.3826379 z " + id="path1928" /> diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index c919547956..cdbe31de65 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -395,8 +395,6 @@ class DeviceAction(QAction): # {{{ class DeviceMenu(QMenu): # {{{ fetch_annotations = pyqtSignal() - connect_to_folder = pyqtSignal() - connect_to_itunes = pyqtSignal() disconnect_mounted_device = pyqtSignal() def __init__(self, parent=None): @@ -408,26 +406,6 @@ class DeviceMenu(QMenu): # {{{ self.set_default_menu = QMenu(_('Set default send to device action')) self.set_default_menu.setIcon(QIcon(I('config.svg'))) - opts = email_config().parse() - default_account = None - if opts.accounts: - self.email_to_menu = self.addMenu(_('Email to')+'...') - keys = sorted(opts.accounts.keys()) - for account in keys: - formats, auto, default = opts.accounts[account] - dest = 'mail:'+account+';'+formats - if default: - default_account = (dest, False, False, I('mail.svg'), - _('Email to')+' '+account) - action1 = DeviceAction(dest, False, False, I('mail.svg'), - _('Email to')+' '+account) - action2 = DeviceAction(dest, True, False, I('mail.svg'), - _('Email to')+' '+account+ _(' and delete from library')) - map(self.email_to_menu.addAction, (action1, action2)) - map(self._memory.append, (action1, action2)) - self.email_to_menu.addSeparator() - action1.a_s.connect(self.action_triggered) - action2.a_s.connect(self.action_triggered) basic_actions = [ ('main:', False, False, I('reader.svg'), @@ -457,13 +435,6 @@ class DeviceMenu(QMenu): # {{{ ] - if default_account is not None: - for x in (basic_actions, delete_actions): - ac = list(default_account) - if x is delete_actions: - ac[1] = True - x.insert(1, tuple(ac)) - for menu in (self, self.set_default_menu): for actions, desc in ( (basic_actions, ''), @@ -502,21 +473,7 @@ class DeviceMenu(QMenu): # {{{ config['default_send_to_device_action'] = repr(action) self.group.triggered.connect(self.change_default_action) - if opts.accounts: - self.addSeparator() - self.addMenu(self.email_to_menu) - self.addSeparator() - mitem = self.addAction(QIcon(I('document_open.svg')), _('Connect to folder')) - mitem.setEnabled(True) - mitem.triggered.connect(lambda x : self.connect_to_folder.emit()) - self.connect_to_folder_action = mitem - - mitem = self.addAction(QIcon(I('devices/itunes.png')), - _('Connect to iTunes')) - 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')), _('Eject device')) mitem.setEnabled(False) @@ -638,6 +595,8 @@ class DeviceMixin(object): # {{{ self.device_error_dialog = error_dialog(self, _('Error'), _('Error communicating with device'), ' ') self.device_error_dialog.setModal(Qt.NonModal) + self.share_conn_menu.connect_to_folder.connect(self.connect_to_folder) + self.share_conn_menu.connect_to_itunes.connect(self.connect_to_itunes) self.emailer = Emailer() self.emailer.start() self.device_manager = DeviceManager(Dispatcher(self.device_detected), @@ -675,21 +634,20 @@ class DeviceMixin(object): # {{{ def create_device_menu(self): self._sync_menu = DeviceMenu(self) + self.share_conn_menu.build_email_entries(self._sync_menu) self.action_sync.setMenu(self._sync_menu) self.connect(self._sync_menu, SIGNAL('sync(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'), self.dispatch_sync_event) 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_itunes.connect(self.connect_to_itunes) self._sync_menu.disconnect_mounted_device.connect(self.disconnect_mounted_device) if self.device_connected: - self._sync_menu.connect_to_folder_action.setEnabled(False) - self._sync_menu.connect_to_itunes_action.setEnabled(False) + self.share_conn_menu.connect_to_folder_action.setEnabled(False) + self.share_conn_menu.connect_to_itunes_action.setEnabled(False) self._sync_menu.disconnect_mounted_device_action.setEnabled(True) else: - self._sync_menu.connect_to_folder_action.setEnabled(True) - self._sync_menu.connect_to_itunes_action.setEnabled(True) + self.share_conn_menu.connect_to_folder_action.setEnabled(True) + self.share_conn_menu.connect_to_itunes_action.setEnabled(True) self._sync_menu.disconnect_mounted_device_action.setEnabled(False) def device_job_exception(self, job): @@ -726,16 +684,16 @@ class DeviceMixin(object): # {{{ def set_device_menu_items_state(self, connected): if connected: - self._sync_menu.connect_to_folder_action.setEnabled(False) - self._sync_menu.connect_to_itunes_action.setEnabled(False) + self.share_conn_menu.connect_to_folder_action.setEnabled(False) + self.share_conn_menu.connect_to_itunes_action.setEnabled(False) self._sync_menu.disconnect_mounted_device_action.setEnabled(True) self._sync_menu.enable_device_actions(True, self.device_manager.device.card_prefix(), self.device_manager.device) self.eject_action.setEnabled(True) else: - self._sync_menu.connect_to_folder_action.setEnabled(True) - self._sync_menu.connect_to_itunes_action.setEnabled(True) + self.share_conn_menu.connect_to_folder_action.setEnabled(True) + self.share_conn_menu.connect_to_itunes_action.setEnabled(True) self._sync_menu.disconnect_mounted_device_action.setEnabled(False) self._sync_menu.enable_device_actions(False) self.eject_action.setEnabled(False) @@ -983,6 +941,8 @@ class DeviceMixin(object): # {{{ else: self.status_bar.show_message(_('Sent by email:') + ', '.join(good), 5000) + if remove: + self.library_view.model().delete_books_by_id(remove) def cover_to_thumbnail(self, data): p = QPixmap() diff --git a/src/calibre/gui2/dialogs/config/__init__.py b/src/calibre/gui2/dialogs/config/__init__.py index 84d55c8fb6..1deb025c73 100644 --- a/src/calibre/gui2/dialogs/config/__init__.py +++ b/src/calibre/gui2/dialogs/config/__init__.py @@ -195,22 +195,32 @@ class PluginModel(QAbstractItemModel): class CategoryModel(QStringListModel): + CATEGORIES = [ + ('general', _('General'), 'dialog_information.svg'), + ('interface', _('Interface'), 'lookfeel.svg'), + ('conversion', _('Conversion'), 'convert.svg'), + ('email', _('Email\nDelivery'), 'mail.svg'), + ('add/save', _('Add/Save'), 'save.svg'), + ('advanced', _('Advanced'), 'view.svg'), + ('server', _('Content\nServer'), 'network-server.svg'), + ('plugins', _('Plugins'), 'plugins.svg'), + ] + def __init__(self, *args): QStringListModel.__init__(self, *args) - self.setStringList([_('General'), _('Interface'), _('Conversion'), - _('Email\nDelivery'), _('Add/Save'), - _('Advanced'), _('Content\nServer'), _('Plugins')]) - self.icons = list(map(QVariant, map(QIcon, - [I('dialog_information.svg'), I('lookfeel.svg'), - I('convert.svg'), - I('mail.svg'), I('save.svg'), I('view.svg'), - I('network-server.svg'), I('plugins.svg')]))) + self.setStringList([x[1] for x in self.CATEGORIES]) def data(self, index, role): if role == Qt.DecorationRole: - return self.icons[index.row()] + return QVariant(QIcon(I(self.CATEGORIES[index.row()][2]))) return QStringListModel.data(self, index, role) + def index_for_name(self, name): + for i, x in enumerate(self.CATEGORIES): + if x[0] == name: + return self.index(i) + return self.index(0) + class EmailAccounts(QAbstractTableModel): def __init__(self, accounts): @@ -332,7 +342,8 @@ class ConfigDialog(ResizableDialog, Ui_Dialog): def category_current_changed(self, n, p): self.stackedWidget.setCurrentIndex(n.row()) - def __init__(self, parent, library_view, server=None): + def __init__(self, parent, library_view, server=None, + initial_category='general'): ResizableDialog.__init__(self, parent) self._category_model = CategoryModel() @@ -461,7 +472,6 @@ class ConfigDialog(ResizableDialog, Ui_Dialog): self.button_osx_symlinks.setVisible(isosx) self.separate_cover_flow.setChecked(config['separate_cover_flow']) self.setup_email_page() - self.category_view.setCurrentIndex(self.category_view.model().index(0)) self.delete_news.setEnabled(bool(self.sync_news.isChecked())) self.connect(self.sync_news, SIGNAL('toggled(bool)'), self.delete_news.setEnabled) @@ -489,6 +499,8 @@ class ConfigDialog(ResizableDialog, Ui_Dialog): self.opt_disable_animations.setChecked(config['disable_animations']) self.opt_show_donate_button.setChecked(config['show_donate_button']) + self.category_view.setCurrentIndex(self.category_view.model().index_for_name(initial_category)) + def check_port_value(self, *args): port = self.port.value() if port < 1025: @@ -942,6 +954,5 @@ if __name__ == '__main__': from PyQt4.Qt import QApplication app = QApplication([]) d=ConfigDialog(None, LibraryDatabase2('/tmp')) - d.category_view.setCurrentIndex(d.category_view.model().index(0)) d.show() app.exec_() diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index 254d2c3d00..a3ae5b77aa 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -59,6 +59,7 @@ class LibraryViewMixin(object): # {{{ self.action_open_containing_folder, self.action_show_book_details, self.action_del, + self.action_conn_share, add_to_library = None, edit_device_collections=None, similar_menu=similar_menu) @@ -67,21 +68,24 @@ class LibraryViewMixin(object): # {{{ edit_device_collections = (_('Manage collections'), partial(self.edit_device_collections, oncard=None)) self.memory_view.set_context_menu(None, None, None, - self.action_view, self.action_save, None, None, self.action_del, + self.action_view, self.action_save, None, None, + self.action_del, None, add_to_library=add_to_library, edit_device_collections=edit_device_collections) edit_device_collections = (_('Manage collections'), partial(self.edit_device_collections, oncard='carda')) self.card_a_view.set_context_menu(None, None, None, - self.action_view, self.action_save, None, None, self.action_del, + self.action_view, self.action_save, None, None, + self.action_del, None, add_to_library=add_to_library, edit_device_collections=edit_device_collections) edit_device_collections = (_('Manage collections'), partial(self.edit_device_collections, oncard='cardb')) self.card_b_view.set_context_menu(None, None, None, - self.action_view, self.action_save, None, None, self.action_del, + self.action_view, self.action_save, None, None, + self.action_del, None, add_to_library=add_to_library, edit_device_collections=edit_device_collections) diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index 8604587649..b0ddf5eb0d 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -22,6 +22,7 @@ from calibre import human_readable from calibre.utils.config import prefs from calibre.ebooks import BOOK_EXTENSIONS from calibre.gui2.dialogs.scheduler import Scheduler +from calibre.utils.smtp import config as email_config ICON_SIZE = 48 @@ -262,7 +263,9 @@ class ToolBar(QToolBar): # {{{ ch.setCursor(Qt.PointingHandCursor) ch.setAutoRaise(True) if ac.menu() is not None: - ch.setPopupMode(ch.MenuButtonPopup) + name = getattr(ac, 'action_name', None) + ch.setPopupMode(ch.InstantPopup if name == 'conn_share' + else ch.MenuButtonPopup) for x in actions: self.addAction(x) @@ -306,6 +309,60 @@ class ToolBar(QToolBar): # {{{ class Action(QAction): pass +class ShareConnMenu(QMenu): + + connect_to_folder = pyqtSignal() + connect_to_itunes = pyqtSignal() + config_email = pyqtSignal() + + def __init__(self, parent=None): + QMenu.__init__(self, parent) + mitem = self.addAction(QIcon(I('devices/folder.svg')), _('Connect to folder')) + mitem.setEnabled(True) + mitem.triggered.connect(lambda x : self.connect_to_folder.emit()) + self.connect_to_folder_action = mitem + + mitem = self.addAction(QIcon(I('devices/itunes.png')), + _('Connect to iTunes')) + mitem.setEnabled(True) + mitem.triggered.connect(lambda x : self.connect_to_itunes.emit()) + self.connect_to_itunes_action = mitem + self.addSeparator() + self.email_actions = [] + + def build_email_entries(self, sync_menu): + from calibre.gui2.device import DeviceAction + for ac in self.email_actions: + self.removeAction(ac) + self.email_actions = [] + opts = email_config().parse() + if opts.accounts: + self.email_to_menu = QMenu(_('Email to')+'...', self) + keys = sorted(opts.accounts.keys()) + for account in keys: + formats, auto, default = opts.accounts[account] + dest = 'mail:'+account+';'+formats + action1 = DeviceAction(dest, False, False, I('mail.svg'), + _('Email to')+' '+account) + action2 = DeviceAction(dest, True, False, I('mail.svg'), + _('Email to')+' '+account+ _(' and delete from library')) + map(self.email_to_menu.addAction, (action1, action2)) + if default: + map(self.addAction, (action1, action2)) + map(self.email_actions.append, (action1, action2)) + self.email_to_menu.addSeparator() + action1.a_s.connect(sync_menu.action_triggered) + action2.a_s.connect(sync_menu.action_triggered) + ac = self.addMenu(self.email_to_menu) + self.email_actions.append(ac) + else: + ac = self.addAction(_('Setup email based sharing of books')) + self.email_actions.append(ac) + ac.triggered.connect(self.setup_email) + + def setup_email(self, *args): + self.config_email.emit() + class MainWindowMixin(object): def __init__(self, db): @@ -341,7 +398,6 @@ class MainWindowMixin(object): self.scheduler.start_recipe_fetch.connect( self.download_scheduled_recipe, type=Qt.QueuedConnection) - def read_toolbar_settings(self): pass @@ -372,18 +428,19 @@ class MainWindowMixin(object): setattr(self, 'action_'+name, action) all_actions.append(action) - ac(0, 7, 0, 'add', _('Add books'), 'add_book.svg', _('A')) + ac(0, 0, 0, 'add', _('Add books'), 'add_book.svg', _('A')) ac(1, 1, 0, 'edit', _('Edit metadata'), 'edit_input.svg', _('E')) ac(2, 2, 3, 'convert', _('Convert books'), 'convert.svg', _('C')) ac(3, 3, 0, 'view', _('View'), 'view.svg', _('V')) - ac(4, 4, 3, 'choose_library', _('%d books')%0, 'lt.png', + ac(-1, 4, 0, 'sync', _('Send to device'), 'sync.svg') + ac(5, 5, 3, 'choose_library', _('%d books')%0, 'lt.png', tooltip=_('Choose calibre library to work with')) - ac(5, 5, 3, 'news', _('Fetch news'), 'news.svg', _('F')) - ac(6, 6, 0, 'save', _('Save to disk'), 'save.svg', _('S')) - ac(7, 0, 0, 'sync', _('Send to device'), 'sync.svg') - ac(8, 8, 3, 'del', _('Remove books'), 'trash.svg', _('Del')) - ac(9, 9, 3, 'help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual")) - ac(10, 10, 0, 'preferences', _('Preferences'), 'config.svg', _('Ctrl+P')) + ac(6, 6, 3, 'news', _('Fetch news'), 'news.svg', _('F')) + ac(7, 7, 0, 'save', _('Save to disk'), 'save.svg', _('S')) + ac(8, 8, 0, 'conn_share', _('Connect/share'), 'connect_share.svg') + ac(9, 9, 3, 'del', _('Remove books'), 'trash.svg', _('Del')) + ac(10, 10, 3, 'help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual")) + ac(11, 11, 0, 'preferences', _('Preferences'), 'config.svg', _('Ctrl+P')) ac(-1, -1, 0, 'merge', _('Merge book records'), 'merge_books.svg', _('M')) ac(-1, -1, 0, 'open_containing_folder', _('Open containing folder'), @@ -402,6 +459,10 @@ class MainWindowMixin(object): self.action_news.setMenu(self.scheduler.news_menu) self.action_news.triggered.connect( self.scheduler.show_dialog) + self.share_conn_menu = ShareConnMenu(self) + self.share_conn_menu.config_email.connect(partial(self.do_config, + initial_category='email')) + self.action_conn_share.setMenu(self.share_conn_menu) self.action_help.triggered.connect(self.show_help) md = QMenu() @@ -528,6 +589,7 @@ class MainWindowMixin(object): for x in (self.preferences_action, self.action_preferences): x.triggered.connect(self.do_config) + return all_actions # }}} diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index 3efde4824d..870157c81a 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -214,14 +214,17 @@ class BooksView(QTableView): # {{{ state['column_sizes'][name] = h.sectionSize(i) return state + def write_state(self, state): + db = getattr(self.model(), 'db', None) + name = unicode(self.objectName()) + if name and db is not None: + db.prefs.set(name + ' books view state', state) + def save_state(self): # Only save if we have been initialized (set_database called) if len(self.column_map) > 0 and self.was_restored: state = self.get_state() - db = getattr(self.model(), 'db', None) - name = unicode(self.objectName()) - if name and db is not None: - db.prefs.set(name + ' books view state', state) + self.write_state(state) def cleanup_sort_history(self, sort_history): history = [] @@ -387,7 +390,7 @@ class BooksView(QTableView): # {{{ # Context Menu {{{ def set_context_menu(self, edit_metadata, send_to_device, convert, view, - save, open_folder, book_details, delete, + save, open_folder, book_details, delete, conn_share, similar_menu=None, add_to_library=None, edit_device_collections=None): self.setContextMenuPolicy(Qt.DefaultContextMenu) @@ -398,6 +401,8 @@ class BooksView(QTableView): # {{{ self.context_menu.addAction(send_to_device) if convert is not None: self.context_menu.addAction(convert) + if conn_share is not None: + self.context_menu.addAction(conn_share) self.context_menu.addAction(view) self.context_menu.addAction(save) if open_folder is not None: @@ -524,6 +529,19 @@ class DeviceBooksView(BooksView): # {{{ self.context_menu.popup(event.globalPos()) event.accept() + def get_old_state(self): + ans = None + name = unicode(self.objectName()) + if name: + name += ' books view state' + ans = gprefs.get(name, None) + return ans + + def write_state(self, state): + name = unicode(self.objectName()) + if name: + gprefs.set(name + ' books view state', state) + def set_database(self, db): self._model.set_database(db) self.restore_state() diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 6bcf564cc3..9913e320e9 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -351,7 +351,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ return self.memory_view.model().db, self.card_a_view.model().db, self.card_b_view.model().db - def do_config(self, *args): + def do_config(self, checked=False, initial_category='general'): if self.job_manager.has_jobs(): d = error_dialog(self, _('Cannot configure'), _('Cannot configure while there are running jobs.')) @@ -363,7 +363,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, # {{{ d.exec_() return d = ConfigDialog(self, self.library_view, - server=self.content_server) + server=self.content_server, initial_category=initial_category) d.exec_() self.content_server = d.server diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index bd4bd0a01a..4653529095 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -448,7 +448,7 @@ class DocumentView(QWebView): self.unimplemented_actions = list(map(self.pageAction, [d.DownloadImageToDisk, d.OpenLinkInNewWindow, d.DownloadLinkToDisk, d.OpenImageInNewWindow, d.OpenLink])) - self.dictionary_action = QAction(QIcon(I('dictionary.png')), + self.dictionary_action = QAction(QIcon(I('dictionary.svg')), _('&Lookup in dictionary'), self) self.dictionary_action.setShortcut(Qt.CTRL+Qt.Key_L) self.dictionary_action.triggered.connect(self.lookup)