Commits

Erik Grinaker committed b57efdd

added clipboard chaining

Comments (0)

Files changed (11)

 
 ---------------[ xxxx-xx-xx : 0.4.0 ]---------------
 
+2004-12-17  Erik Grinaker <erikg@codepoet.no>
+
+	* added clipboard chaining
+
+	* added menu item for copying username and password chain
+	to clipboard
+
+	* removed option for copying username to PRIMARY on launch
+
+
 2004-12-16  Erik Grinaker <erikg@codepoet.no>
 
 	* used generic INSTALL instructions from automake
 - drag and drop of entries in tree
 - files can be dragged to Revelation to open them
 - the account clipboard is shared between Revelation instances
-- the account password is copied to the clipboard when launched
+- an account password chain is copied to the clipboard when launching entry
+- added menu item for copying username and password chain to clipboard
 - username and password can be copied to clipboard, even when hidden
 - added preference for launching entries on doubleclick
-- added preference for copying username to PRIMARY selection when launching
 - integrated with gnome session manager
 - new application icon
 - added icon and mime-type for the data files
 - add a dropdown widget for list fields (like email protocol etc)
 - restructure the configuration layout
 - recent docs
-- port to gtk+ 2.6
 - use gnome_authentication_manager_init() from gnome-python when
   available
+- port to gtk+ 2.6
+  - gtk.AboutDialog
 
 1.0.x:
 - attempt full HIG compliance

data/revelation.schemas

 		</schema>
 
 		<schema>
-			<key>/schemas/apps/revelation/launching/copy_primary</key>
-			<applyto>/apps/revelation/launching/copy_primary</applyto>
-			<owner>revelation</owner>
-			<type>bool</type>
-			<default>false</default>
-
-			<locale name="C">
-				<short>Copy username to PRIMARY selection on launch</short>
-				<long>
-					When enabled, the entry username will be copied to
-					the PRIMARY selection (instead of the password, which
-					is passed to the CLIPBOARD selection).
-				</long>
-			</locale>
-		</schema>
-
-		<schema>
 			<key>/schemas/apps/revelation/launching/doubleclick</key>
 			<applyto>/apps/revelation/launching/doubleclick</applyto>
 			<owner>revelation</owner>

data/ui/actions.xml

 		</action>
 
 		<action>
+			<name>clip-chain</name>
+			<label>Copy C_hain</label>
+			<stock>gtk-copy</stock>
+			<accel>&lt;Shift&gt;&lt;Control&gt;C</accel>
+			<description>Copy any usernames and passwords to the clipboard as a "chain"</description>
+		</action>
+
+		<action>
 			<name>clip-cut</name>
 			<label>Cu_t</label>
 			<stock>gtk-cut</stock>

data/ui/menubar.xml

 			<separator />
 			<menuitem action="clip-cut" />
 			<menuitem action="clip-copy" />
+			<menuitem action="clip-chain" />
 			<menuitem action="clip-paste" />
 			<separator />
 			<menuitem action="select-all" />

data/ui/popup-tree.xml

 		<separator />
 		<menuitem action="clip-cut" />
 		<menuitem action="clip-copy" />
+		<menuitem action="clip-chain" />
 		<menuitem action="clip-paste" />
 	</popup>
 </ui>

src/lib/config.py.in

 			self.get("view/window-width")
 			self.get("launcher/website")
 			self.get("view/searchbar")
-			self.get("launching/copy_primary")
 			self.get("launching/doubleclick")
 
 		except ConfigError:
 		self.clip_clipboard	= gtk.clipboard_get("CLIPBOARD")
 		self.clip_primary	= gtk.clipboard_get("PRIMARY")
 
+		self.content		= None
+		self.contentpointer	= 0
 
-	def __lookup_clipboard(self, selection):
-		"Looks up a clipboard based on a selection name"
 
-		if selection == "CLIPBOARD":
-			return self.clip_clipboard
+	def __cb_clear(self, clipboard, data = None):
+		"Clears the clipboard data"
 
-		elif selection == "PRIMARY":
-			return self.clip_primary
+		return
+		self.content		= None
+		self.contentpointer	= 0
 
 
-	def clear(self, selection = None):
+	def __cb_get(self, clipboard, selectiondata, info, data):
+		"Returns text for clipboard requests"
+
+		if self.content == None:
+			text = ""
+
+		elif type(self.content) == list:
+
+			if len(self.content) == 0:
+				text = ""
+
+			else:
+				text = self.content[self.contentpointer]
+
+			if self.contentpointer < len(self.content) - 1:
+				self.contentpointer += 1
+
+		else:
+			text = str(self.content)
+
+		selectiondata.set_text(text, len(text))
+
+
+	def clear(self):
 		"Clears the clipboard"
 
-		if selection == None:
-			self.clip_clipboard.clear()
-			self.clip_primary.clear()
+		self.clip_clipboard.clear()
+		self.clip_primary.clear()
 
-		else:
-			self.__lookup_clipboard(selection).clear()
 
-
-	def get(self, selection = "CLIPBOARD"):
+	def get(self):
 		"Fetches text from the clipboard"
 
-		text = self.__lookup_clipboard(selection).wait_for_text()
+		text = self.clip_clipboard.wait_for_text()
 
 		if text is None:
 			text = ""
 		return text
 
 
-	def has_contents(self, selection = "CLIPBOARD"):
+	def has_contents(self):
 		"Checks if the clipboard has any contents"
 
-		return self.__lookup_clipboard(selection).wait_for_text() != None
+		return self.clip_clipboard.wait_for_text() != None
 
 
-	def set(self, text, selection = None):
+	def set(self, content):
 		"Copies text to the clipboard"
 
-		if selection == None:
-			self.clip_clipboard.set_text(text)
-			self.clip_primary.set_text(text)
+		self.content		= content
+		self.contentpointer	= 0
 
-		else:
-			self.__lookup_clipboard(selection).set_text(text)
+		targets = (
+			( "text/plain",		0,	0 ),
+			( "STRING",		0,	0 ),
+			( "TEXT",		0,	0 )
+		)
+
+		self.clip_clipboard.set_with_data(targets, self.__cb_get, self.__cb_clear, None)
+		self.clip_primary.set_with_data(targets, self.__cb_get, self.__cb_clear, None)
 
 
 
 		self.clipboard = gtk.Clipboard(gtk.gdk.display_get_default(), "_REVELATION_ENTRY")
 		self.__has_contents = False
 
-		gobject.timeout_add(500, self.__cb_check_contents)
+		gobject.timeout_add(500, lambda: self.__check_contents())
 
 
-	def __cb_check_contents(self):
+	def __check_contents(self):
 		"Callback which check the clipboard"
 
 		state = self.has_contents()
 		"Clears the clipboard"
 
 		self.clipboard.clear()
-		self.__cb_check_contents()
+		self.__check_contents()
 
 
 	def get(self):
 		xml = datahandler.RevelationXML().export_data(copystore)
 		self.clipboard.set_text(xml)
 
-		self.__cb_check_contents()
+		self.__check_contents()
 
 
 gobject.signal_new("content-toggled", EntryClipboard, gobject.SIGNAL_ACTION, gobject.TYPE_BOOLEAN, ( gobject.TYPE_BOOLEAN, ))

src/lib/dialog.py

 		self.tooltips.set_tip(self.check_doubleclick, "When enabled, doubleclicking an entry will launch it instead of edit it")
 		self.section_launching.append_widget(None, self.check_doubleclick)
 
-		# copy username to PRIMARY selection
-		self.check_copy_primary = ui.CheckButton("Copy username to PRIMARY selection")
-		ui.config_bind(self.config, "launching/copy_primary", self.check_copy_primary)
-
-		self.tooltips.set_tip(self.check_copy_primary, "When enabled, the account username will be copied to the PRIMARY selection on launch")
-		self.section_launching.append_widget(None, self.check_copy_primary)
-
 
 	def __init_section_pwgen(self, page):
 		"Sets up the password generator section"

src/revelation.in

 
 		# set up callbacks for actions
 		callbacks = {
+			"clip-chain"		: lambda w: self.clip_chain(),
 			"clip-copy"		: lambda w: self.clip_copy(),
 			"clip-cut"		: lambda w: self.clip_cut(),
 			"clip-paste"		: lambda w: self.clip_paste(),
 
 			# scan for copy action, and remove dynamic items
 			children = menu.get_children()
-			index_copy = children.index(self.uimanager.get_widget("%s/clip-copy" % menupath))
+			index_chain = children.index(self.uimanager.get_widget("%s/clip-chain" % menupath))
 			index_paste = children.index(self.uimanager.get_widget("%s/clip-paste" % menupath))
 
-			for i in range(index_copy + 1, index_paste):
+			for i in range(index_chain + 1, index_paste):
 				children[i].destroy()
 
-			# create menuitem
+			# fetch entry data
 			if len(iters) != 1:
 				continue
 
 			e = self.entrystore.get_entry(iters[0])
+			secretfields = [ field for field in e.fields if (type(field) == entry.UsernameField or field.datatype == entry.DATATYPE_PASSWORD) and field.value != "" ]
 
-			i = index_copy + 1
-			for field in e.fields:
-				if (type(field) != entry.UsernameField and field.datatype != entry.DATATYPE_PASSWORD) or field.value == "":
-					continue
-
+			# create menuitems
+			i = index_chain + 1
+			for field in secretfields:
 				menuitem = ui.ImageMenuItem(gtk.STOCK_COPY, "Copy %s" % field.name)
 				menuitem.tooltip = "Copy the %s to the clipboard" % field.name.lower()
 				menuitem.connect("activate", self.__cb_clip_set, field.value)
 
 		files = [ file.strip() for file in seldata.data.split("\n") if file.strip() != "" ]
 
-		if len(files) == 0:
-			return
-
-		self.file_open(files[0])
+		if len(files) > 0:
+			self.file_open(files[0])
 
 
 	def __cb_exception(self, type, value, trace):
 
 	##### PUBLIC METHODS #####
 
+	def clip_chain(self):
+		"Copies any usernames and passwords from an entry as a chain"
+
+		iters = self.tree.get_selected()
+
+		if len(iters) != 1:
+			return
+
+		e = self.entrystore.get_entry(iters[0])
+
+		secrets = [ field.value for field in e.fields if field.datatype == entry.DATATYPE_PASSWORD and field.value != "" ]
+
+		if e.has_field(entry.UsernameField) == True and e[entry.UsernameField] != "":
+			secrets.insert(0, e[entry.UsernameField])
+
+		self.clipboard.set(secrets)
+
+
 	def clip_copy(self):
 		"Copies entries to the clipboard"
 
 				for field in e.fields:
 					subst[field.symbol] = field.value
 
-				# copy username / password to clipboard
-				for field in e.fields:
-					if field.datatype == entry.DATATYPE_PASSWORD and field.value != "":
-						secret = field.value
-						break
-				else:
-					secret = None
-
-				if e.has_field(entry.UsernameField) and self.config.get("launching/copy_primary") == True:
-					username = e[entry.UsernameField]
-
-				else:
-					username = None
-
-				if username != None:
-					self.clipboard.set(username, "PRIMARY")
-
-					if secret != None:
-						self.clipboard.set(secret, "CLIPBOARD")
-
-				elif secret != None:
-					self.clipboard.set(secret)
+				# copy passwords to clipboard
+				self.clip_chain()
 
 				# generate and run launch command
 				command = util.parse_subst(command, subst)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.