Clipboard for ubuntu
update on 11.23
noilinux没有预装剪贴板是怎么回事呢?noilinux相信大家都很熟悉,但是noilinux没有预装剪贴板是怎么回事呢,下面就让小编带大家一起了解吧。
noilinux没有预装剪贴板,其实就是无法查看剪贴板历史,大家可能会很惊讶noilinux怎么会没有预装剪贴板呢?但事实就是这样,小编也感到非常惊讶。
这就是关于noilinux没有预装剪贴板的事情了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!
因为 noi linux 没装历史剪贴板所以写一个
大致思路:
明文存储剪贴板内容和sha256sum哈希较验码,更新时比较较验码
文件结构:
──clipboard/
├── sha/ //sha256sum
│ └── nw.txt
├── store/ //历史剪贴板内容
│ └── nw.txt
├── upd.py //记录内容
└── UI.py //GUI界面
使用说明:
upd.py
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk
import time
import os
cur_dir=''
cur_sto=''
cur_sha=''
nw_sto=''
nw_sha=''
maxn=10
cnt=0
def sto_file(id):
if(type(id)==type(0)):
fn=str(id)
return f'{cur_sto}{fn}.txt'
else:
return f'{cur_sto}{id}.txt'
def sha_file(id):
if(type(id)==type(0)):
fn=str(id)
return f'{cur_sha}{fn}.txt'
else:
return f'{cur_sha}{id}.txt'
def pre():
global cur_dir,cur_sto,cur_sha,nw_sto,nw_sha
cur_file_path = os.path.abspath(__file__)
cur_dir = os.path.dirname(cur_file_path)
cur_sto = cur_dir+'/store/'
cur_sha = cur_dir+'/sha/'
nw_sto = sto_file('nw')
nw_sha = sha_file('nw')
if os.path.exists('store')==False:
os.system('mkdir store')
if os.path.exists('sha')==False:
os.system('mkdir sha')
if os.path.exists('store/nw.txt')==False:
os.system('touch store/nw.txt')
if os.path.exists('sha/nw.txt')==False:
os.system('touch sha/nw.txt')
def count_files_in_directory(directory):
files = os.listdir(directory)
return len(files)
def chk(now):
global cnt
cnt=count_files_in_directory(cur_sto)-1
if cnt==0:
return 1
else:
flag=1
with open(nw_sto, 'w') as f:
f.write(now)
os.system(f'sha256sum {nw_sto} > {nw_sha}')
with open(nw_sha, 'r', encoding='utf-8') as f:
sha_nw,nwname= f.read().strip().split()
for i in range(1,cnt+1):
with open(sha_file(i), 'r', encoding='utf-8') as f:
sha_ps,psname= f.read().strip().split()
if sha_ps==sha_nw:
flag=0
break
return flag
def write_to_file(now):
for i in range(min(maxn-1,cnt),0,-1):
os.system(f'mv {sto_file(i)} {sto_file(i+1)}')
os.system(f'mv {sha_file(i)} {sha_file(i+1)}')
with open(sto_file(1), 'w') as f:
f.write(now)
os.system(f'sha256sum {sto_file(1)} > {sha_file(1)}')
def get_clipboard_text():
clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
text = clipboard.wait_for_text()
return text
def output():
now = get_clipboard_text()
if now==None:
now="There must be something wrong"
if chk(now):
write_to_file(now)
if __name__ == '__main__':
print('Recording clipboard content, please do not end the process or close the terminal')
pre()
# print(sto_file('nw'))
while 1:
output()
time.sleep(2)
UI.py
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk, Gdk, GLib
import cairo
import os
cur_dir = ''
def count_files_in_directory(directory):
files = os.listdir(directory)
return len(files)
def update_content(file_path):
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read().strip()
if len(content) > 50:
content = content[:50] + "..."
return content
return ""
class TextDisplayApp:
def __init__(self):
self.window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
self.window.set_title("pastebin")
self.window.set_default_size(350, 400)
self.window.set_resizable(True)
self.window.set_border_width(10)
self.window.set_keep_above(True)
self.window.set_skip_taskbar_hint(True)
self.window.set_skip_pager_hint(True)
self._position_window_bottom_right()
main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
self.window.add(main_box)
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
scrolled_window.set_shadow_type(Gtk.ShadowType.NONE)
main_box.pack_start(scrolled_window, True, True, 0)
self.text_container = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
scrolled_window.add(self.text_container)
self.text_labels = []
self.event_boxes = []
self.text_data = ["BY GON_TATA","https://www.cnblogs.com/gon-tata/p/19084568","gugugaga"]
GLib.timeout_add_seconds(2, self.flash_all_content)
self.window.connect("destroy", Gtk.main_quit)
self.create_text_areas()
self.window.show_all()
def _position_window_bottom_right(self):
display = Gdk.Display.get_default()
n_monitors = display.get_n_monitors()
mon_geoms = [
display.get_monitor(i).get_geometry()
for i in range(n_monitors)
]
x0 = min(r.x for r in mon_geoms)
y0 = min(r.y for r in mon_geoms)
x1 = max(r.x + r.width for r in mon_geoms)
y1 = max(r.y + r.height for r in mon_geoms)
screen_width = x1 - x0
screen_height = y1 - y0
self.window.realize()
width, height = self.window.get_size()
x = screen_width - width - 20
y = screen_height - height - 50
self.window.move(x, y)
def create_text_areas(self):
for child in self.text_container.get_children():
self.text_container.remove(child)
self.text_labels.clear()
self.event_boxes.clear()
self.flash_all_content(False)
for i, text in enumerate(self.text_data):
event_box = Gtk.EventBox()
event_box.connect("button-press-event", self.on_text_clicked, text)
frame = Gtk.Frame()
frame.get_style_context().add_class("text-frame")
event_box.add(frame)
text_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
frame.add(text_box)
label = Gtk.Label()
label.set_text(text)
label.set_line_wrap(True)
label.set_max_width_chars(35)
label.set_xalign(0)
label.set_yalign(0)
label.get_style_context().add_class("text-label")
text_box.pack_start(label, True, True, 0)
self.text_labels.append(label)
self.event_boxes.append(event_box)
self.text_container.pack_start(event_box, False, False, 0)
if i < len(self.text_data) - 1:
separator = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
self.text_container.pack_start(separator, False, False, 0)
self.text_container.show_all()
def flash_all_content(self, update_ui=True):
old_count = len(self.text_data)
self.text_data.clear()
cnt = count_files_in_directory(cur_dir + "/store")-1
for i in range(1, cnt + 1):
fileid = str(i)
content = update_content(cur_dir + "/store/" + fileid + '.txt')
self.text_data.append(content)
if old_count != cnt and update_ui:
self.create_text_areas()
elif update_ui:
for i, label in enumerate(self.text_labels):
if i < len(self.text_data):
label.set_text(self.text_data[i])
return True
def on_text_clicked(self, widget, event, text):
if event.button == 1:
index = self.event_boxes.index(widget)
file_id = index + 1
file_path = f"{cur_dir}/store/{file_id}.txt"
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
full_content = f.read().strip()
self.copy_to_clipboard(full_content)
self.show_notification("copied!")
return True
return False
def copy_to_clipboard(self, text):
clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
clipboard.set_text(text, -1)
clipboard.store()
def show_notification(self, message):
overlay = Gtk.Window(type=Gtk.WindowType.POPUP)
overlay.set_decorated(False)
overlay.set_resizable(False)
overlay.set_skip_taskbar_hint(True)
overlay.set_skip_pager_hint(True)
overlay.set_keep_above(True)
label = Gtk.Label(label=message)
label.set_name("notification-label")
label.get_style_context().add_class("notification")
css_provider = Gtk.CssProvider()
css = """
#notification-label {
background-color: rgba(0, 0, 0, 0.0);
color: white;
padding: 8px 12px;
border-radius: 4px;
font-weight: bold;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
}
"""
css_provider.load_from_data(css.encode())
Gtk.StyleContext.add_provider_for_screen(
Gdk.Screen.get_default(),
css_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
)
overlay.add(label)
overlay.show_all()
self._position_notification(overlay)
GLib.timeout_add(2000, overlay.destroy)
def _position_notification(self, notification_window):
screen = Gdk.Screen.get_default()
screen_width = screen.get_width()
notification_window.realize()
width, height = notification_window.get_size()
x = screen_width - width - 20
y = 20
notification_window.move(x, y)
def run(self):
Gtk.main()
if __name__ == "__main__":
cur_file_path = os.path.abspath(__file__)
cur_dir = os.path.dirname(cur_file_path)
app = TextDisplayApp()
app.run()
新建 upd.py 和 UI.py (不用管sha/和store/,upd.py会把它们建好)
终端 cd 到当前文件夹
python3 upd.py
另开一个终端
python3 UI.py
使用建议:
开一个终端跑 upd.py 挂后台,为 UI.py 设置快捷键
设置 > 键盘快捷键 拉到页面最底下点击 +
名称 随便填
命令 填 python3 $UI.py的绝对路径$
例:UI.py 的绝对路径为 /home/hzoi/下载/hwsp/clipboard/UI.py
命令 应填 python3 /home/hzoi/下载/hwsp/clipboard/UI.py
另:
默认保留最近10次记录,次数和更新频率可自行修改源代码,GUI界面单击预览部分可以快速复制对应文本

浙公网安备 33010602011771号