1
- #!/usr/bin/env python
2
- # -*- coding: utf-8 -*-
3
- #
4
- # Copyright 2012
5
- #
6
- # Authors: Denis Kovalev <[email protected] >
7
- #
8
- # This program is free software: you can redistribute it and/or modify it
9
- # under the terms of either or both of the following licenses:
10
- #
11
- # 1) the GNU Lesser General Public License version 3, as published by the
12
- # Free Software Foundation; and/or
13
- # 2) the GNU Lesser General Public License version 2.1, as published by
14
- # the Free Software Foundation.
15
- #
16
- # This program is distributed in the hope that it will be useful, but
17
- # WITHOUT ANY WARRANTY; without even the implied warranties of
18
- # MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
19
- # PURPOSE. See the applicable version of the GNU Lesser General Public
20
- # License for more details.
21
- #
22
- # You should have received a copy of both the GNU Lesser General Public
23
- # License version 3 and version 2.1 along with this program. If not, see
24
- # <http://www.gnu.org/licenses>
25
- #
26
-
27
-
28
- __author__ = 'aikikode'
29
-
30
1
import cairo
31
2
import os
32
3
import re
33
4
import tempfile
34
5
import threading
35
- from gi .repository import GObject
36
- from gi .repository import Gdk
37
- from gi .repository import GdkPixbuf
38
- from gi .repository import Gtk
6
+ from gi .repository import GObject , Gdk , GdkPixbuf , Gtk
39
7
40
8
FILE_GRABBER_SIZE = 50
9
+ MAX_PREVIEW_WIDTH = 800
10
+ MAX_PREVIEW_HEIGHT = 600
41
11
42
12
43
13
class FileGrabber :
@@ -61,13 +31,18 @@ def __init__(self, app_icon, upload_callback):
61
31
# Add main widget for grabbing files
62
32
self .image = Gtk .Image ()
63
33
pixbuf = GdkPixbuf .Pixbuf .new_from_file (self .app_icon )
64
- scaled_buf = pixbuf .scale_simple (FILE_GRABBER_SIZE , FILE_GRABBER_SIZE , GdkPixbuf .InterpType .BILINEAR )
34
+ scaled_buf = pixbuf .scale_simple (
35
+ FILE_GRABBER_SIZE , FILE_GRABBER_SIZE ,
36
+ GdkPixbuf .InterpType .BILINEAR
37
+ )
65
38
self .image .set_from_pixbuf (scaled_buf )
66
39
self .image .show ()
67
40
self .window .add (self .image )
68
41
self .window .connect ('drag-motion' , self .window_drag_motion )
69
42
self .window .connect ('drag-drop' , self .window_drag_drop )
70
- self .window .connect ('drag-data-received' , self .window_drag_data_received )
43
+ self .window .connect (
44
+ 'drag-data-received' , self .window_drag_data_received
45
+ )
71
46
self .isShown = False
72
47
73
48
def set_upload_callback (self , upload_callback ):
@@ -79,23 +54,23 @@ def toggle_window(self):
79
54
self .isShown = False
80
55
else :
81
56
self .window .show ()
82
- self .window .set_keep_above (True ) # This may not work: it depends on the window manager
57
+ # This may not work: it depends on the window manager
58
+ self .window .set_keep_above (True )
83
59
self .isShown = True
84
60
85
61
def window_drag_motion (self , wid , context , x , y , time ):
86
62
Gdk .drag_status (context , Gdk .DragAction .COPY , time )
87
- return True # True means "I accept this data"
63
+ return True # True means "I accept this data"
88
64
89
65
def window_drag_drop (self , wid , context , x , y , time ):
90
66
wid .drag_get_data (context , context .list_targets ()[- 1 ], time )
91
67
return True
92
68
93
69
def window_drag_data_received (self , wid , context , x , y , data , info , time ):
94
- if data .get_text ():
95
- file_to_upload = data .get_text ().splitlines ()[0 ].replace ('file://' , '' )
96
- else :
97
- file_to_upload = data .get_data ().splitlines ()[0 ].replace ('file://' , '' )
98
- file_to_upload = re .sub (r'/([^/]+:/)' , r'\1/' , file_to_upload ) # handle Win path
70
+ text = data .get_text () or data .get_data ()
71
+ file_to_upload = text .splitlines ()[0 ].replace ('file://' , '' )
72
+ # Handle Win path
73
+ file_to_upload = re .sub (r'/([^/]+:/)' , r'\1/' , file_to_upload )
99
74
context .finish (True , False , time )
100
75
GObject .idle_add (self .upload_callback , file_to_upload , False )
101
76
@@ -108,8 +83,8 @@ def __init__(self, upload_callback, quit_callback, log):
108
83
self .log = log
109
84
self .log .debug ('ScreenGrabber: creating' )
110
85
self .selected = False
111
- self .screenWidth , self . screenHeight = Gdk . Screen . width (), Gdk .Screen .height ()
112
- width , height = self . screenWidth , self . screenHeight
86
+ self .screenWidth = width = Gdk .Screen .width ()
87
+ self . screenHeight = height = Gdk . Screen . height ()
113
88
self .drawingWindow = drawingWindow = Gtk .Window ()
114
89
drawingWindow .set_decorated (False )
115
90
drawingWindow .set_skip_taskbar_hint (True )
@@ -135,14 +110,24 @@ def __init__(self, upload_callback, quit_callback, log):
135
110
)
136
111
drawingWindow .show ()
137
112
drawingWindow .present ()
138
- drawingWindow .get_window ().set_fullscreen_mode (Gdk .FullscreenMode .ALL_MONITORS )
113
+ drawingWindow .get_window ().set_fullscreen_mode (
114
+ Gdk .FullscreenMode .ALL_MONITORS
115
+ )
139
116
cursor = Gdk .Cursor (Gdk .CursorType .CROSSHAIR )
140
117
drawingWindow .get_window ().set_cursor (cursor )
141
118
drawingWindow .connect ('draw' , self .initial_draw )
142
- drawingWindow .connect ('button-press-event' , self .select_area_event_handler , self )
143
- drawingWindow .connect ('button-release-event' , self .select_area_event_handler , self )
144
- drawingWindow .connect ('key-press-event' , self .select_area_event_handler , self )
145
- drawingWindow .connect ('motion-notify-event' , self .select_area_event_handler , self )
119
+ drawingWindow .connect (
120
+ 'button-press-event' , self .select_area_event_handler , self
121
+ )
122
+ drawingWindow .connect (
123
+ 'button-release-event' , self .select_area_event_handler , self
124
+ )
125
+ drawingWindow .connect (
126
+ 'key-press-event' , self .select_area_event_handler , self
127
+ )
128
+ drawingWindow .connect (
129
+ 'motion-notify-event' , self .select_area_event_handler , self
130
+ )
146
131
147
132
def initial_draw (self , widget , cr ):
148
133
cr .set_source_rgba (0 , 0 , 0 , 0.5 )
@@ -157,11 +142,18 @@ def select_area_event_handler(self, widget, event, selector):
157
142
selector .start_selection (event .x , event .y )
158
143
elif event .type == Gdk .EventType .BUTTON_RELEASE and event .button == 1 :
159
144
selector .stop_selection (event .x , event .y )
160
- selector .set_complete_handler (self .take_screen_of_area_complete_handler )
145
+ selector .set_complete_handler (
146
+ self .take_screen_of_area_complete_handler
147
+ )
161
148
selector .__del__ ()
162
149
del selector
163
- elif (event .type == Gdk .EventType .BUTTON_PRESS and event .button == 3 ) or (
164
- event .type == Gdk .EventType .KEY_PRESS and event .keyval == Gdk .keyval_from_name ('Escape' )):
150
+ elif (
151
+ (event .type == Gdk .EventType .BUTTON_PRESS and event .button == 3 )
152
+ or (
153
+ event .type == Gdk .EventType .KEY_PRESS
154
+ and event .keyval == Gdk .keyval_from_name ('Escape' )
155
+ )
156
+ ):
165
157
selector .__del__ ()
166
158
del selector
167
159
@@ -197,17 +189,23 @@ def response(dialog, resp_id):
197
189
preview_dialog .set_decorated (False )
198
190
preview_dialog .set_resizable (False )
199
191
# Scale image for preview
200
- preview_image_width = float (image .get_width ())
201
- preview_image_height = float (image .get_height ())
202
- MAX_PREVIEW_WIDTH = 800
203
- MAX_PREVIEW_HEIGHT = 600
204
- if preview_image_width / preview_image_height > MAX_PREVIEW_WIDTH / MAX_PREVIEW_HEIGHT :
205
- preview_image_height = int (round ((MAX_PREVIEW_WIDTH / preview_image_width ) * preview_image_height ))
206
- preview_image_width = MAX_PREVIEW_WIDTH
192
+ preview_width = float (image .get_width ())
193
+ preview_height = float (image .get_height ())
194
+ if preview_width / preview_height > (
195
+ MAX_PREVIEW_WIDTH / MAX_PREVIEW_HEIGHT
196
+ ):
197
+ preview_height = int (
198
+ round ((MAX_PREVIEW_WIDTH / preview_width ) * preview_height )
199
+ )
200
+ preview_width = MAX_PREVIEW_WIDTH
207
201
else :
208
- preview_image_width = int (round ((MAX_PREVIEW_HEIGHT / preview_image_height ) * preview_image_width ))
209
- preview_image_height = MAX_PREVIEW_HEIGHT
210
- preview_image = image .scale_simple (preview_image_width , preview_image_height , GdkPixbuf .InterpType .BILINEAR )
202
+ preview_width = int (
203
+ round ((MAX_PREVIEW_HEIGHT / preview_height ) * preview_width )
204
+ )
205
+ preview_height = MAX_PREVIEW_HEIGHT
206
+ preview_image = image .scale_simple (
207
+ preview_width , preview_height , GdkPixbuf .InterpType .BILINEAR
208
+ )
211
209
widget_image = Gtk .Image .new_from_pixbuf (preview_image )
212
210
widget_image .show ()
213
211
preview_dialog .vbox .add (widget_image )
@@ -220,16 +218,23 @@ def __del__(self):
220
218
return True
221
219
ctx = self .drawingWindow .get_window ().cairo_create ()
222
220
self .clear (ctx )
223
- # Give cairo some time to clear the screen before the destruction of the window
221
+ # Give cairo some time to clear the screen before the destruction of
222
+ # the window
224
223
GObject .timeout_add (50 , self .drawingWindow .destroy )
225
224
if self .selected and hasattr (self , 'complete_handler' ):
226
225
x = int (round (min (self .selection_x_start , self .selection_x_end )))
227
226
y = int (round (min (self .selection_y_start , self .selection_y_end )))
228
- width = int (round (abs (self .selection_x_end - self .selection_x_start )))
229
- height = int (round (abs (self .selection_y_end - self .selection_y_start )))
227
+ width = int (
228
+ round (abs (self .selection_x_end - self .selection_x_start ))
229
+ )
230
+ height = int (
231
+ round (abs (self .selection_y_end - self .selection_y_start ))
232
+ )
230
233
# Do not take screen shot if grabbed area is too small
231
234
if width > 10 and height > 10 :
232
- GObject .timeout_add (150 , self .complete_handler , x , y , width , height )
235
+ GObject .timeout_add (
236
+ 150 , self .complete_handler , x , y , width , height
237
+ )
233
238
else :
234
239
self .log .debug ('ScreenGrabber: selected area is too small' )
235
240
self .deleted = True
0 commit comments