view photocrop/src/photocrop.py @ 31:c1061f0721d7

bing4desktop-0.240208-1.2
author prymula <prymula76@outlook.com>
date Thu, 08 Feb 2024 16:14:36 +0100
parents dcd610585610
children
line wrap: on
line source

#!/usr/bin/env python3
# Photo Crop - photo crop to size app to print in the most popular photo paper sizes
# author: Przemysław R. Pietraszczyk
# license: GPL v.2
# date 21-01-2022
# editor: Geany

import sys
import cairo
import gi, os
import time
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GdkPixbuf, Gdk
from gi.repository.GdkPixbuf import Pixbuf

UI_INFO = """
<ui>
  <menubar name='MenuBar'>
  	<menu action='FileMenu'>
	  <menuitem action='FileLoad' />
	  <menuitem action='FileSave' />
	  <menuitem action='FilePrint' />
	  <separator />
	  <menuitem action='FileQuit' />
	</menu>
	<menu action='EditMenu'>
	  <menuitem action='Rotate'/>
	</menu>
	<menu action='InfoMenu'>
	  <menuitem action='Help'/>
	  <menuitem action='About'/>
	  <separator />
	  <menuitem action='License'/>
	</menu>
  </menubar>

</ui>
"""

"""
# szkielet z podmenu
<ui>
  <menubar name='MenuBar'>
	<menu action='FileMenu'>
	  <menu action='FileLoad'>
		<menuitem action='LoadImg' />
	  </menu>
	  <menuitem action='FilePrint' />
	  <separator />
	  <menuitem action='FileQuit' />
	</menu>
	<menu action='InfoMenu'>
	  <menuitem action='Help'/>
	  <menuitem action='About'/>
	</menu>
  </menubar>
</ui>
"""

grid = Gtk.Grid()
rotate = False
file_img_selected = ""

def get_resource_path(rel_path):
	dir_of_py_file = os.path.dirname(__file__)
	rel_path_to_resource = os.path.join(dir_of_py_file, rel_path)
	abs_path_to_resource = os.path.abspath(rel_path_to_resource)
	return abs_path_to_resource
	
class FileChooserIMGLoad(Gtk.Window):
	def __init__(self):
		Gtk.Window.__init__(self, title="Selection of graphic files")
		global file_img_selected

		dialog = Gtk.FileChooserDialog(title="Selection of graphic files", parent=self, action=Gtk.FileChooserAction.OPEN)
		dialog.add_buttons(
			Gtk.STOCK_CANCEL,
			Gtk.ResponseType.CANCEL,
			Gtk.STOCK_OPEN,
			Gtk.ResponseType.OK,
		)

		self.add_filters(dialog)

		response = dialog.run()
		if response == Gtk.ResponseType.OK:
			print("Open clicked")
			print("File selected: " + dialog.get_filename())
			file_img_selected=dialog.get_filename()
		elif response == Gtk.ResponseType.CANCEL:
			print("Cancel clicked")	
		
		dialog.destroy()

	def add_filters(self, dialog):
		
		filter_jpeg = Gtk.FileFilter()
		filter_jpeg.set_name("Files JPEG")
		filter_jpeg.add_mime_type("image/jpeg")
		dialog.add_filter(filter_jpeg)

		filter_png = Gtk.FileFilter()
		filter_png.set_name("Files PNG")
		filter_png.add_mime_type("image/png")
		dialog.add_filter(filter_png)
		"""
		filter_png = Gtk.FileFilter()
		filter_png.set_name("Files TIFF")
		filter_png.add_mime_type("image/tiff")
		dialog.add_filter(filter_png)
		"""

class FileChooserIMGSave(Gtk.Window):
	def __init__(self):
		Gtk.Window.__init__(self, title="Save the cropped photo")
		global file_img_selected

		dialog = Gtk.FileChooserDialog(title="Save the cropped photo", parent=self, action=Gtk.FileChooserAction.SAVE)
		dialog.add_buttons(
			Gtk.STOCK_CANCEL,
			Gtk.ResponseType.CANCEL,
			Gtk.STOCK_SAVE,
			Gtk.ResponseType.OK,
		)

		self.add_filters(dialog)

		response = dialog.run()
		if response == Gtk.ResponseType.OK:
			print("Open clicked")
			print("File selected: " + dialog.get_filename())
			file_img_selected=dialog.get_filename()
		elif response == Gtk.ResponseType.CANCEL:
			print("Cancel clicked")	
		
		dialog.destroy()

	def add_filters(self, dialog):
		
		filter_jpeg = Gtk.FileFilter()
		filter_jpeg.set_name("Files JPEG")
		filter_jpeg.add_mime_type("image/jpeg")
		dialog.add_filter(filter_jpeg)
		
		filter_png = Gtk.FileFilter()
		filter_png.set_name("Files PNG")
		filter_png.add_mime_type("image/png")
		dialog.add_filter(filter_png)
		"""
		filter_png = Gtk.FileFilter()
		filter_png.set_name("Files TIFF")
		filter_png.add_mime_type("image/tiff")
		dialog.add_filter(filter_png)
		"""


class DialogWarning(Gtk.Dialog):
	def __init__(self, parent):
		Gtk.Dialog.__init__(self, title="Attention!", transient_for=parent, flags=0)
		self.props.border_width = 20
		self.add_buttons(
			Gtk.STOCK_OK, Gtk.ResponseType.OK
		)
		self.set_default_size(150, 100)
		label1 = Gtk.Label(label="The frame is outside the canvas!\n")
		box = self.get_content_area()
		box.add(label1)
		self.show_all()	
		
class DialogCropWarning(Gtk.Dialog):
	def __init__(self, parent):
		Gtk.Dialog.__init__(self, title="Attention!", transient_for=parent, flags=0)
		self.props.border_width = 20
		self.add_buttons(
			Gtk.STOCK_OK, Gtk.ResponseType.OK
		)
		self.set_default_size(150, 100)
		label1 = Gtk.Label(label="Crop the photo first!\n")
		box = self.get_content_area()
		box.add(label1)
		self.show_all()	

class DialogHelp(Gtk.Dialog):
	def __init__(self, parent):
		Gtk.Dialog.__init__(self, title="Help", transient_for=parent, flags=0)
		self.props.border_width = 20
		self.add_buttons(
			Gtk.STOCK_OK, Gtk.ResponseType.OK
		)

		self.set_default_size(150, 100)
		label1 = Gtk.Label(label="An application for cropping photos to the most popular\nformats [13x18, 10x15, A4]\n\nScaling the size of the frame - mouse wheel with the CTRL key pressed\nMoving the frame - pressed LMB and moving the mouse\nin the desired direction.")
		#label2 = Gtk.Label(lanel="")
		box = self.get_content_area()
		box.add(label1)
		#box.add(label2)
		self.show_all()	
	
class DialogAbout(Gtk.Dialog):
	def __init__(self, parent):
		Gtk.Dialog.__init__(self, title="About", transient_for=parent, flags=0)
		self.props.border_width = 20
		self.add_buttons(
			Gtk.STOCK_OK, Gtk.ResponseType.OK
		)

		self.set_default_size(150, 100)

		label = Gtk.Label(label="\tThe application is based on:")
		box = self.get_content_area()
		box.add(label)
		
		button = Gtk.LinkButton("https://python-gtk-3-tutorial.readthedocs.io/", label="https://python-gtk-3-tutorial.readthedocs.io/")
		box.add(button)

		label2 = Gtk.Label(label="\n\tVersion: 0.230112-1~alpha\n\n\tPrzemysław R. Pietraszczyk\n\n\t\t  January 2022\n\n\n")
		box.add(label2)
		

		button = Gtk.LinkButton("https://prymula.ct8.pl", label="Site")
		box.add(button)

		self.show_all()
		
class DialogLicense(Gtk.Dialog):
	def __init__(self, parent):
		Gtk.Dialog.__init__(self, title="License", transient_for=parent, flags=0)
		self.props.border_width = 20
		self.add_buttons(
			Gtk.STOCK_OK, Gtk.ResponseType.OK
		)

		self.set_default_size(150, 100)

		label = Gtk.Label(label="This program is distributed without any warranty. More information:\n")

		box = self.get_content_area()
		box.add(label)

		button = Gtk.LinkButton("https://www.gnu.org/licenses/old-licenses/gpl-2.0.html", label="GNU General License version => 2")
		box.add(button)

		self.show_all()
		
class Brush(object):

	default_rgba_color = (0, 0, 0, 1)

	def __init__(self, width=None, rgba_color=None):

		if rgba_color is None:
			rgba_color = self.default_rgba_color

		if width is None:
			width = 3

		self.__width = width
		self.__rgba_color = rgba_color
		self.__stroke = []
		self.__current_line = []

	def _line_ended(self):
		self.__stroke.append(self.__current_line.copy())
		self.__current_line = []

	def _add_point(self, point):
		self.__current_line.append(point)

	def _draw(self, cairo_context):

		cairo_context.set_source_rgba(*self.__rgba_color)
		cairo_context.set_line_width(self.__width)
		cairo_context.set_line_cap(cairo.LINE_CAP_ROUND)

		cairo_context.new_path()
		for line in self.__stroke:
			for x, y in line:
				cairo_context.line_to(x, y)
			cairo_context.new_sub_path()

		for x, y in self.__current_line:
			cairo_context.line_to(x, y)

		cairo_context.stroke()


# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ #
# ~                          Getters & Setters                            ~ #
# ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ # 

	def _get_width(self):
		return self.__width

	def _set_width(self, width):
		self.__width = width

	def _get_rgba_color(self):
		return self.__rgba_color

	def _set_rgba_color(self, rgba_color):
		self.__rgba_color = rgba_color

	def _get_stroke(self):
		return self.__stroke
	
	def _get_current_line(self):
		return self.__current_line						
	
class MyWindow(Gtk.Window):

	def __init__(self):
		super().__init__()

		self.init_ui()
	
	def on_drawing_area_draw(self, drawable, cairo_context):
		global rotate
		 
		start = time.time()
		self.brush = Brush()

		# DrawingArea size depends on Pixbuf size
		#self.drawing_area.get_window().resize(self.displayed_pixbuf.get_width(), 
		#									  self.displayed_pixbuf .get_height())        
		#self.drawing_area.set_size_request(self.displayed_pixbuf.get_width(), 
		#								   self.displayed_pixbuf.get_height())
		
		
		# (x, y) offsets
		pixbuf_x = 0 #int(self.viewport.get_hadjustment().get_value())
		pixbuf_y = 0 # int(self.viewport.get_vadjustment().get_value())

		# Width and height of the image's clip
		width = cairo_context.get_target().get_width()
		height = cairo_context.get_target().get_height()
	
		if width > 0 and height > 0:

			# Draw created area of the Sample's Pixbuf
			Gdk.cairo_set_source_pixbuf(cairo_context, self.pixbuf_view, pixbuf_x, pixbuf_y)
			
			cairo_context.paint() 
			
			if self.border_visible == True:
				# Draw brush strokes
				self.brush._add_point((self.border_x, self.border_y))
				self.brush._add_point((self.border_width, self.border_y))
				self.brush._add_point((self.border_width, self.border_y+self.border_height))
				self.brush._add_point((self.border_x, self.border_y+self.border_height))
				self.brush._add_point((self.border_x, self.border_y)) # nie działa ?

				self.brush._draw(cairo_context)

		end = time.time()
		#print(f"Runtime of the program is {end - start}")


	def set_ratio_border_size(self):
		
		self.border_x = 0
		self.border_y = 0
		
		if self.format_size == "10x15":
			if self.horizontal == True and self.vertical == False:
				single = self.picture_view_height*0.5
				self.border_height = single
				self.border_width = single*1.4
				#self.look = "horizontal"
				#self.border_type = "horizontal"
			elif self.horizontal == False and self.vertical == True:
				single = self.picture_view_width*0.5
				self.border_width = single
				self.border_height = single*1.4
				#self.look = "vertical"
				#self.border_type = "vertical"
			elif self.horizontal == False and self.vertical == False:
				self.border_height = self.picture_view_height
				self.border_width = self.picture_view_width
			
		elif self.format_size == "13x18":
			if self.horizontal == True and self.vertical == False:
				single = self.picture_view_height*0.5
				self.border_height = single
				self.border_width = single*1.42
			elif self.horizontal == False and self.vertical == True:
				single = self.picture_view_width*0.5
				self.border_width = single
				self.border_height = single*1.42
			elif self.horizontal == False and self.vertical == False:
				self.border_height = self.picture_view_height
				self.border_width = self.picture_view_width
			
		elif self.format_size == "A4":
			if self.horizontal == True and self.vertical == False:
				single = self.picture_view_height*0.5
				self.border_height = single
				self.border_width = single*1.4
			elif self.horizontal == False and self.vertical == True:
				single = self.picture_view_width*0.5
				self.border_width = single
				self.border_height = single*1.4
			elif self.horizontal == False and self.vertical == False:
				self.border_height = self.picture_view_height
				self.border_width = self.picture_view_width
		
		
		
	# ustaw proporcje dla obrazu w kontrolce
	def set_ratio_picture_view(self):
		self.picture_orig_width = float(self.pixbuf_orig.get_width())
		self.picture_orig_height = float(self.pixbuf_orig.get_height())
		#if self.format_size == "10x15":
		#self.picture_orig_x = 0
		#self.picture_orig_y = 0
		
		if self.picture_orig_width > self.picture_orig_height:
			self.picture_view_width = 586.66 #600
			m = self.picture_orig_width / 586.66 #600
			self.picture_view_height = self.picture_orig_height/m
		if self.picture_orig_height > self.picture_orig_width:
			self.picture_view_height = 586.66 #600
			m = self.picture_orig_height / 586.66 #600
			self.picture_view_width = self.picture_orig_width/m

		# Zapamiętanie rozmiaru obrazka dla kontrolki
		self.orig_ratio_width = self.picture_view_width
		self.orig_ratio_height = self.picture_view_height
		
		
		
	# ustaw proporcje dla obrazu w kontrolce ppo rotacji
	def set_ratio_picture_view_after_rotation(self):
		
		self.picture_tmp_width = self.border_width - self.border_x
		self.picture_tmp_height = self.border_height - self.border_y
		
		if self.border_x != 0 :
			bx = self.picture_orig_width / self.border_x
			crop_x = self.picture_tmp_width / bx
		else:
			crop_x = 0
			
		if self.border_y != 0:
			by = self.picture_orig_height / self.border_y
			crop_y = self.picture_tmp_height / by
		else:
			crop_y = 0
		
		
		self.picture_orig_x = crop_x
		self.picture_orig_y = crop_y
		"""
		W zależności jaka była pierwotnie orientacja zdjęcia, po obrocie 
		jest ono odpowiedio przycinane
		"""
		print ("ORIG: "+self.look)
		if self.look == "vertical":
			if self.border_type == "horizontal":
				bw = self.picture_orig_width / (self.border_width - self.border_x)
				self.picture_tmp_width = self.picture_orig_width / bw - crop_x
				# w tym wypadku 'y' bez odejmowania gdyż skróciło by to fotografie w pione 
				bh = self.picture_orig_height / self.border_height
				self.picture_tmp_height = self.picture_orig_height / bh

			elif self.border_type == "vertical":
				bw = self.picture_orig_width / (self.border_width - self.border_x)
				self.picture_tmp_width = self.picture_orig_width / bw - crop_x
		
				bh = self.picture_orig_height / (self.border_height - self.border_y)
				self.picture_tmp_height = self.picture_orig_height / bh

		elif self.look == "horizontal":
			if self.border_type == "horizontal":
				bw = self.picture_orig_width / (self.border_width - self.border_x)
				self.picture_tmp_width = self.picture_orig_width / bw - crop_x
		
				bh = self.picture_orig_height / (self.border_height - self.border_y)
				self.picture_tmp_height = self.picture_orig_height / bh

			elif self.border_type == "vertical":
				bw = self.picture_orig_width / (self.border_width - self.border_x)
				self.picture_tmp_width = self.picture_orig_width / bw - crop_x
		
				bh = self.picture_orig_height / (self.border_height - self.border_y)
				self.picture_tmp_height = self.picture_orig_height / bh
		
			
		if self.picture_tmp_width > self.picture_tmp_height:
			self.picture_view_width = 586.66
			m = self.picture_tmp_width / 586.66
			self.picture_view_height = self.picture_tmp_height/m
		if self.picture_tmp_height > self.picture_tmp_width:
			self.picture_view_height = 586.66
			m = self.picture_tmp_height / 586.66
			self.picture_view_width = self.picture_tmp_width/m
		
		# Zapamiętanie rozmiaru obrazka dla kontrolki
		self.orig_ratio_width = self.picture_view_width
		self.orig_ratio_height = self.picture_view_height
		
	def on_menu_file_load_img_generic(self, widget):
		global grid, file_img_selected

		filename=FileChooserIMGLoad()
		
		if len(file_img_selected) != 0:
			
			self.pixbuf_orig = GdkPixbuf.Pixbuf.new_from_file(filename=file_img_selected)
			
			self.set_ratio_picture_view()
			self.pixbuf_view = self.pixbuf_orig.scale_simple(self.picture_view_width, self.picture_view_height, GdkPixbuf.InterpType.HYPER)
			
			if self.picture_view_width > self.picture_view_height:
				self.horizontal = True
				self.vertical = False
				self.resize(582.66,413.34)
				self.look = "horizontal"
				self.border_type = "horizontal"
			elif self.picture_view_height > self.picture_view_width:
				self.vertical = True
				self.horizontal = False
				self.resize(413.34,582.66)
				self.look = "vertical"
				self.border_type = "vertical"
			else:
				self.horizontal = False
				self.vertical = False
				
				
			self.set_ratio_border_size()
			
			
				
			self.border_visible = True
			
			# nie rysujemy na orginale ale na kopii z okna
			self.drawing_area.set_size_request(self.pixbuf_view.get_width(), self.pixbuf_view.get_height())
			self.drawing_area.set_events(Gdk.EventMask.ALL_EVENTS_MASK)

			self.show_all()
			
	def add_edit_menu_actions(self, action_group):
		action_info_menu = Gtk.Action(name="EditMenu", label="Edit")
		action_group.add_action(action_info_menu)

		action_new = Gtk.Action(
			name="Rotate",
			label="Frame rotation",
			tooltip="Rotate border",
		)
		action_new.connect("activate", self.on_menu_rotate)
		action_group.add_action_with_accel(action_new, None)

		
	def add_info_menu_actions(self, action_group):
		action_info_menu = Gtk.Action(name="InfoMenu", label="Info")
		action_group.add_action(action_info_menu)

		action_new = Gtk.Action(
			name="Help",
			label="Help",
			tooltip="Help",
		)
		action_new.connect("activate", self.on_menu_help)
		action_group.add_action_with_accel(action_new, None)

		action_new = Gtk.Action(
			name="About",
			label="About",
			tooltip="About",
		)
		action_new.connect("activate", self.on_menu_about)
		action_group.add_action_with_accel(action_new, None)
		
		action_new = Gtk.Action(
			name="License",
			label="License",
			tooltip="License",
		)
		action_new.connect("activate", self.on_menu_license)
		action_group.add_action_with_accel(action_new, None)


		
	def add_file_menu_actions(self, action_group):
		action_filemenu = Gtk.Action(name="FileMenu", label="File")
		action_group.add_action(action_filemenu)

		"""
		# sposób dodawania podmenu
		action_fileloadmenu = Gtk.Action(name="FileLoad", stock_id=Gtk.STOCK_OPEN)
		action_group.add_action(action_fileloadmenu)

		action_new = Gtk.Action(
			name="LoadImg",
			label="Wczytaj Obrazek",
			tooltip="Wczytuje obrazek",
		)
		action_new.connect("activate", self.on_menu_file_load_img_generic)
		action_group.add_action_with_accel(action_new, None)
		"""
		
		action_fileload = Gtk.Action(name="FileLoad", stock_id=Gtk.STOCK_OPEN)
		action_fileload.connect("activate", self.on_menu_file_load_img_generic)
		action_group.add_action(action_fileload)

		action_filesave = Gtk.Action(name="FileSave", stock_id=Gtk.STOCK_SAVE)
		action_filesave.connect("activate", self.on_menu_file_save_img)
		action_group.add_action(action_filesave)
		
		
		action_print = Gtk.Action(name="FilePrint", stock_id=Gtk.STOCK_PRINT)
		action_print.connect("activate", self.print_image)
		action_group.add_action(action_print)


		action_filequit = Gtk.Action(name="FileQuit", stock_id=Gtk.STOCK_QUIT)
		action_filequit.connect("activate", self.on_menu_file_quit)
		action_group.add_action(action_filequit)
	
		
		
	# tworzy menu bar
	def create_ui_manager(self):
		uimanager = Gtk.UIManager()

		# Throws exception if something went wrong
		uimanager.add_ui_from_string(UI_INFO)

		# Add the accelerator group to the toplevel window
		accelgroup = uimanager.get_accel_group()
		self.add_accel_group(accelgroup)
		return uimanager

	def on_menu_about(self, widget):
		dialog = DialogAbout(self)
		response = dialog.run()

		dialog.destroy()
		
	def on_menu_license(self, widget):
		dialog = DialogLicense(self)
		response = dialog.run()

		dialog.destroy()
		

	def on_menu_help(self, widget):
		dialog = DialogHelp(self)
		response = dialog.run()

		dialog.destroy()
		
	def on_menu_rotate(self, widget):
		global rotate
		
		
		if self.border_type == "horizontal":
			self.border_type = "vertical"
			self.horizontal = False
			self.vertical = True
			
			single = self.picture_view_width*0.3
			self.border_width = single
			self.border_height = single*1.4
			self.border_x = 0
			self.border_y = 0
			
			rotate = True
			
		elif self.border_type == "vertical":
			self.border_type = "horizontal"
			self.horizontal = True
			self.vertical = False
			
			single = self.picture_view_height*0.3
			self.border_height = single
			self.border_width = single*1.4
			self.border_x = 0
			self.border_y = 0
		
			rotate = True
		else:
			pass
		
		print ("ASPECT: "+self.border_type)
		print ("BORDER-WIDTH :"+str(self.border_width))
		print ("BORDER-HEIGHT:"+str(self.border_height))
			
		self.drawing_area.queue_draw()

	def on_menu_file_save_img(self, widget):
		global file_img_selected
		
		if self.pixbuf_tmp != None:
			filename=FileChooserIMGSave()
			if len(file_img_selected) != 0:
				self.pixbuf_view.savev(file_img_selected, "jpeg", ["quality"], ["100"])
		else:
			dialog = DialogCropWarning(self)
			response = dialog.run()
			
			dialog.destroy()

	def on_menu_file_quit(self, widget):
		Gtk.main_quit()

	def print_page(self, operation=None, context=None, page_nr=None):
		
		ctx = context.get_cairo_context()

		# make cairo ImageSurface from the png file
		surface = cairo.ImageSurface.create_from_png('/tmp/photocrop.png')
		#ctx.rectangle(50,50,100,100)
		ctx.set_source_surface(surface)
		ctx.paint ()
		os.remove("/tmp/photocrop.png");
		

	def print_image(self, widget):
		
		if self.pixbuf_tmp == None:
			self.pixbuf_tmp = self.pixbuf_orig
			
			
		#	źle obraca
		#if self.border_type == "horizontal":
		#	self.pixbuf_tmp.rotate_simple(GdkPixbuf.PixbufRotation.COUNTERCLOCKWISE)
		#	#pixbuf2.rotate_simple(GdkPixbuf.PixbufRotation.CLOCKWISE)
		#	self.border_type = "vertical"
			
		FACTOR_MM_TO_PIXEL = 2.834645669 
		
		
		if self.format_size == "10x15":
			#if self.horizontal == True and self.vertical == False:
			if self.border_type == "horizontal":
				page_width = 148
				page_height = 104.99
				
				img_height =104.99 * FACTOR_MM_TO_PIXEL
				img_width = 148 * FACTOR_MM_TO_PIXEL
			#elif self.horizontal == False and self.vertical == True:
			elif self.border_type == "vertical":

				page_width = 104.99
				page_height = 148
				
				img_width =104.99 * FACTOR_MM_TO_PIXEL
				img_height = 148 * FACTOR_MM_TO_PIXEL
				
			size = "10x15"
		elif self.format_size == "13x18":
			#if self.horizontal == True and self.vertical == False:
			if self.border_type == "horizontal":

				page_width = 178 
				page_height = 127 
				
				img_height = 127 * FACTOR_MM_TO_PIXEL 
				img_width = 178 * FACTOR_MM_TO_PIXEL 
			#elif self.horizontal == False and self.vertical == True:
			elif self.border_type == "vertical":

				page_width = 127 
				page_height = 178 
				
				img_width = 127 * FACTOR_MM_TO_PIXEL 
				img_height = 178 * FACTOR_MM_TO_PIXEL 
			size = "5x7"
		elif self.format_size == "A4":
			#if self.horizontal == True and self.vertical == False:
			if self.border_type == "horizontal":
				page_width = 297
				page_height = 207
				
				img_height = 207 * FACTOR_MM_TO_PIXEL
				img_width = 297 * FACTOR_MM_TO_PIXEL
			#elif self.horizontal == False and self.vertical == True:
			elif self.border_type == "vertical":

				page_width = 207
				page_height = 297
				
				img_width = 207 * FACTOR_MM_TO_PIXEL
				img_height = 297 * FACTOR_MM_TO_PIXEL
				
			size = "A4"
			
		dpi = 600

		# z orginalnymi wielkościami nie chce drukowac
		pixbuf2 = self.pixbuf_tmp.scale_simple(img_width, img_height, GdkPixbuf.InterpType.HYPER)

		pixbuf2.savev("/tmp/photocrop.png","png", ["quailty"], ["100"])
		
		#ps = Gtk.PaperSize.new_custom(size, size, self.pixbuf_tmp.get_width(), self.pixbuf_tmp.get_height(), Gtk.Unit.POINTS)
		ps = Gtk.PaperSize.new_custom(size, size, page_width, page_height, Gtk.Unit.MM)

		print_settings = Gtk.PrintSettings()
		print_settings.set_resolution(dpi)

		page_setup = Gtk.PageSetup()
		page_setup.set_paper_size(ps)
		page_setup.set_bottom_margin(0.0, Gtk.Unit.MM)
		page_setup.set_left_margin(0.0, Gtk.Unit.MM)
		page_setup.set_right_margin(0.0, Gtk.Unit.MM)
		page_setup.set_top_margin(0.0, Gtk.Unit.MM)
		
		#if self.border_type == "horizontal":
		#	page_setup.set_orientation(Gtk.PageOrientation.LANDSCAPE)
		#elif self.border_type == "vertical":
		# page_setup.set_orientation(Gtk.PageOrientation.PORTRAIT)


		print_operation = Gtk.PrintOperation()
		print_operation.set_unit(Gtk.Unit.POINTS)
		print_operation.set_n_pages(1)
		print_operation.set_default_page_setup(page_setup)
		print_operation.set_print_settings(print_settings)
		print_operation.connect("draw_page", self.print_page)
		#print_operation.set_export_filename("example.pdf")

		result = print_operation.run(Gtk.PrintOperationAction.PRINT_DIALOG, None) # window zamisat None

		#result = print_operation.run(Gtk.PrintOperationAction.PREVIEW, None)
		print(result)

	# przycinamy !
	def photo_crop(self, button):
		
		if self.border_x < 0:
			dialog = DialogWarning(self)
			response = dialog.run()
			dialog.destroy()
			return
		if self.border_y < 0:
			dialog = DialogWarning(self)
			response = dialog.run()
			dialog.destroy()
			return
		if self.border_width > self.picture_view_width:
			dialog = DialogWarning(self)
			response = dialog.run()
			dialog.destroy()
			return
		# FIXME - w sumie to jest zastanawiające !?
		if self.border_height + self.border_y > self.picture_view_height:
			dialog = DialogWarning(self)
			response = dialog.run()
			dialog.destroy()
			return
		
		
		if self.border_x != 0 :
			bx = self.picture_view_width / self.border_x
			crop_x = self.picture_orig_width / bx
		else:
			crop_x = 0
			
		if self.border_y != 0:
			by = self.picture_view_height / self.border_y
			crop_y = self.picture_orig_height / by
		else:
			crop_y = 0

		bw = self.picture_view_width / self.border_width
		crop_width = self.picture_orig_width / bw - crop_x
		
		bh = self.picture_view_height / self.border_height
		crop_height = self.picture_orig_height / bh
		
		
		# False - kanał Alpha
		self.pixbuf_tmp = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, False, 8, crop_width, crop_height)

		# zera na koncu to dest_x i dest_y
		self.pixbuf_orig.copy_area(crop_x, crop_y, crop_width, crop_height, self.pixbuf_tmp, 0, 0)

		if rotate == False:
			
			self.picture_tmp_width = float(self.pixbuf_tmp.get_width())
			self.picture_tmp_height = float(self.pixbuf_tmp.get_height())

			# tym razem przeliczamy z uwzględnieniem bufora tymczasowego
			if self.picture_tmp_width > self.picture_tmp_height:
				self.picture_view_width = 586.66
				m = self.picture_tmp_width / 586.66
				self.picture_view_height = self.picture_tmp_height/m
			if self.picture_tmp_height > self.picture_tmp_width:
				self.picture_view_height = 586.66
				m = self.picture_tmp_height / 586.66
				self.picture_view_width = self.picture_tmp_width/m
				
				

		else:
			self.set_ratio_picture_view_after_rotation()
	
		self.drawing_area.set_size_request(self.picture_view_width, self.picture_view_height)
		self.drawing_area.set_events(Gdk.EventMask.ALL_EVENTS_MASK)
	
		self.pixbuf_view = self.pixbuf_tmp.scale_simple(self.picture_view_width, self.picture_view_height, GdkPixbuf.InterpType.HYPER)

		self.picture_view_x = 0
		self.picture_view_y = 0

		self.border_visible = False

		self.drawing_area.queue_draw()

	# przywracamy
	def photo_restore(self, button):
		
		self.border_visible = True
		
		self.set_ratio_picture_view()		
		self.pixbuf_view = self.pixbuf_orig.scale_simple(self.orig_ratio_width, self.orig_ratio_height, GdkPixbuf.InterpType.BILINEAR)

		self.drawing_area.set_size_request(self.orig_ratio_width, self.orig_ratio_height)
		self.drawing_area.set_events(Gdk.EventMask.ALL_EVENTS_MASK)
		self.pixbuf_tmp = None # uniemożliwiamy zapis
		self.show_all()

		self.drawing_area.queue_draw()
		

	def on_format_combo_changed(self, combo):
		tree_iter = combo.get_active_iter()
		if tree_iter is not None:
			model = combo.get_model()
			self.format_size = model[tree_iter][0]
			print("Selected: format=%s" % self.format_size)
			
			self.set_ratio_border_size()
				
			self.drawing_area.queue_draw()

	def on_scroll(self, widget, event):
		""" handles on scroll event"""
		# Handles zoom in / zoom out on Ctrl+mouse wheel
		accel_mask = Gtk.accelerator_get_default_mod_mask()
		if event.state & accel_mask == Gdk.ModifierType.CONTROL_MASK:
			direction = event.get_scroll_deltas()[2]
			
			if direction > 0:
				scrolling = "zoom_out"
			else:
				scrolling = "zoom_in"
			
			self.border_height += self.border_properties[self.format_size][self.border_type][scrolling]["height"]
			self.border_width += self.border_properties[self.format_size][self.border_type][scrolling]["width"]
			"""
			# tu jest jakiś błąd
			if self.border_width > self.picture_view_width:  
				self.border_width -= 1
			if self.border_height+self.border_y > self.picture_view_height:
				self.border_height -= 1
			"""
			self.drawing_area.queue_draw()
			
	def unclick_in_drawing_area (self, box, event):
		self.button_press = False
		print ("Przycisk myszki puszczony")

	
	def onclick_in_drawing_area (self, box, event):
		if event.button == 1:
			self.button_press = True
			print ("Lewy przyciski myszki naciśnięty")
			
	def on_mouse_move_in_drawing_area(self, box, event):

		
		if self.button_press == True:
			
			if self.border_type == "vertical":
				
				#print ("VERTICAL  %%")
				
				if self.last_x < event.x:
					self.border_x += 1
					self.border_width += 1
				if event.x < self.last_x:
					self.border_x -= 1
					self.border_width -= 1
				if self.last_y < event.y:
					self.border_y += 1
					self.border_height += 0.0
				if event.y < self.last_y:
					self.border_y -= 1
					self.border_height -= 0.0
			
			elif self.border_type == "horizontal":
				#print ("Horizontal %%")
				if self.last_x < event.x:
					self.border_x += 1
					self.border_width += 1
				if event.x < self.last_x:
					self.border_x -= 1.
					self.border_width -= 1
				if self.last_y < event.y:
					self.border_y += 1
					self.border_height += 0.0
				if event.y < self.last_y:
					self.border_y -= 1
					self.border_height -= 0.0

			self.last_y = event.y
			self.last_x = event.x		
			"""
			# jeśli będzie się napierać na skraj krawędzi wówczas powiększa ramkę
			if self.border_x < 0:
				self.border_x += 1
				self.border_width += 1
			if self.border_y < 0:
				self.border_y += 1
				self.border_height +=1
			# tu jest jakiś błąd
			
			# powoduje błędne zachowanie ramki
			if self.border_type == "vertical":
				if self.border_width > self.picture_view_width:
					self.border_width -= 1
					self.border_x -= 1
				if self.border_height+self.border_y > self.picture_view_height:
					self.border_height -= 1
					self.border_y -= 1
			elif self.border_type == "horizontal":
				if self.border_height+self.border_y> self.picture_view_width:
					self.border_width -= 1
					self.border_x -= 1
				if self.border_width > self.picture_view_height:
					self.border_height -= 1
					self.border_y -= 1
			"""

			self.drawing_area.queue_draw()
			
	def init_ui(self):
		# JPG akceptuje jedynie z GIMPa
		self.border_properties = { "10x15" : { "horizontal" : { "zoom_out" : {"width" : -1.48, "height" : -0.92}, "zoom_in" : {"width" : 1.48, "height" : 0.92}},
			"vertical" : { "zoom_out": { "width" : -0.92, "height" : -1.48}, "zoom_in": { "width" : 0.92, "height" : 1.48}},
			"square" : { "zoom_out" : { "width" : -1, "height" : -1}, "zoom_out" : { "width" : 1, "height" : 1}}},
				
			"13x18" : { "horizontal" : { "zoom_out" : {"width" : -1.82, "height" : -1.30}, "zoom_in" : {"width" : 1.82, "height" : 1.30}},
			"vertical" : { "zoom_out": { "width" : -1.30, "height" : -1.78}, "zoom_in": { "width" : 1.30, "height" : 1.78}},
			"square" : { "zoom_out" : { "width" : -1, "height" : -1}, "zoom_out" : { "width" : 1, "height" : 1}}},
				
			"A4" : { "horizontal" : { "zoom_out" : {"width" : -2.97, "height" : -1.84}, "zoom_in" : {"width" : 2.97, "height" : 1.84}},
			"vertical" : { "zoom_out": { "width" : -1.84, "height" : -2.97}, "zoom_in": { "width" : 1.84, "height" : 2.97}},
			"square" : { "zoom_out" : { "width" : -1, "height" : -1}, "zoom_out" : { "width" : 1, "height" : 1}}}}
				
	
		#self.props.border_width = 20
		self.add(grid)
		self.pixbuf_tmp = None
		grid.set_row_spacing(10)
		grid.set_column_spacing(10)
		grid.set_column_homogeneous(True) # rozszerza kontrolki na resztę okna
		
		action_group = Gtk.ActionGroup(name="my_actions")

		self.add_file_menu_actions(action_group)
		self.add_edit_menu_actions(action_group)
		self.add_info_menu_actions(action_group)
		
		uimanager = self.create_ui_manager()
		uimanager.insert_action_group(action_group)

		menubar = uimanager.get_widget("/MenuBar")
		box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
		box.pack_start(menubar, False, False, 0)
		
		grid.attach(box, 0, 0, 3, 1)
		
		
		file_img_selected=get_resource_path("/usr/share/photocrop/IMG_6854.JPG") #img/blank.png
		self.pixbuf_orig = GdkPixbuf.Pixbuf.new_from_file(filename=file_img_selected)
		
		self.format_size = "10x15"
		self.set_ratio_picture_view()
		self.pixbuf_view = self.pixbuf_orig.scale_simple(self.picture_view_width, self.picture_view_height, GdkPixbuf.InterpType.HYPER)
		
		self.border_visible = True
		
		if self.picture_view_width > self.picture_view_height:
			self.horizontal = True
			self.vertical = False
			self.look = "horizontal"
			self.border_type = "horizontal"
		elif self.picture_view_height > self.picture_view_width:
			self.vertical = True
			self.horizontal = False
			self.look = "vertical"
			self.border_type = "vertical"
		else:
			self.horizontal = False
			self.vertical = False
			self.look = "square"
				
		self.drawing_area = Gtk.DrawingArea()

		self.drawing_area.set_size_request(self.pixbuf_view.get_width(), self.pixbuf_view.get_height())
		self.drawing_area.set_events(Gdk.EventMask.ALL_EVENTS_MASK)
		
		self.drawing_area.connect("draw", self.on_drawing_area_draw)

		frame = Gtk.Frame()
		event_box  = Gtk.EventBox ()
		self.last_x = 1
		self.last_y = 1
		self.border_x = 0
		self.border_y = 0
		self.button_press = False
		self.pixbuf_tmp = None
		event_box.connect ('button-press-event', self.onclick_in_drawing_area)
		event_box.connect ('button-release-event', self.unclick_in_drawing_area)
		event_box.connect("motion-notify-event", self.on_mouse_move_in_drawing_area)
		event_box.add_events(Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.BUTTON_PRESS_MASK)

		event_box.add(self.drawing_area)
		frame.add(event_box)
		grid.attach(frame,0,1,3,1) 

		button1 = Gtk.Button.new_with_label("Crop")
		button1.connect("clicked", self.photo_crop)
		grid.attach(button1,0,4,1,1)
		
		button2 = Gtk.Button.new_with_label("Restore")
		button2.connect("clicked", self.photo_restore)
		grid.attach(button2,1,4,1,1)
		
		format_store = Gtk.ListStore(str)
		format_photo = [
			"10x15",
			"13x18",
			"A4",
		]
		for fp in format_photo:
			format_store.append([fp])

		format_combo = Gtk.ComboBox.new_with_model(format_store)
		format_combo.connect("changed", self.on_format_combo_changed)
		renderer_text = Gtk.CellRendererText()
		format_combo.pack_start(renderer_text, True)
		format_combo.add_attribute(renderer_text, "text", 0)
		format_combo.set_active(0)
		grid.attach(format_combo,2,4,1,1)

		self.drawing_area.connect('scroll-event', self.on_scroll)

		self.set_border_width(10)
		self.set_title("Photo Crop (alpha)")
		#self.set_default_size(700, 600)
		#self.resize(700, 600)
		self.set_resizable(False)
		self.connect("destroy", Gtk.main_quit)
	
	
	
win = MyWindow()
win.show_all()
Gtk.main()