#!/usr/bin/env python
# -*- coding: utf-8 -*-

#Product Photo 360 - version 1.0
#Author:  Adam Pereszlenyi
#       www.preparatorium.hu
#July, 2015.

#This script is used for 360 degree product photography. Connect the arduino and run the script with the - $ python productphoto.py - command.

#If Arduino is connected, but serial is not found check the serial port location in terminal and modify line 32.

import pygtk
pygtk.require('2.0')
import gtk
import os
import thread
import time
import gobject
import StringIO
import serial

no_of_photos = "0"
no_of_steps = "0"
rotate_direction = "clockwise"
text = ""
abort = "0"
dont_use_ser = False
filename = ""

#If you want to set the serial port manually, write the Ardiuno's serial location between the two apostrophe on the following line. Be careful adding the correct path, otherwise the program will not start. For example use: "/dev/ttyUSB0"
manual_serial = ""
if manual_serial:
  serial_path = manual_serial
else:
  #Detect which serial port is used.
  serial_no = 0
  serial_path = str("/sys/class/tty/ttyUSB" + str(serial_no))
  while not os.path.isdir(serial_path) and not dont_use_ser:
      serial_no = serial_no + 1
      serial_path = str("/sys/class/tty/ttyUSB" + str(serial_no))
      time.sleep(0.01)
      #If serial port is not found on ttyUSB1-ttyUSB19, the program doesn't load serial.
      if serial_no == 19:
	dont_use_ser = True
  if os.path.isdir(serial_path):
    serial_path = str ("/dev/ttyUSB" + str(serial_no))
    
#If serial is found or set manually, the program opens it.
if not dont_use_ser:
  ser = serial.Serial(serial_path , 9600)

class ProductPhoto360():
           
    def refreshLog(self):
      global text
      end_iter = self.textbuffer.get_end_iter()
      self.textview.scroll_to_iter(end_iter, 0, True, 1, 1)
      self.textbuffer.insert(end_iter, text + '\n')
      while gtk.events_pending():
	gtk.main_iteration()
 
    def rotate(self, widget, event, data=None):
	global text
	global abort
	global ser
	text = ""
	self.textview.set_justification(gtk.JUSTIFY_LEFT)
	self.textbuffer.set_text("")
	valid_integer = True
	try:
	  no_of_steps = int(self.entry1.get_text())
	except ValueError:
	  end_iter = self.textbuffer.get_end_iter()
	  self.textbuffer.insert(end_iter, '\n' + "Please add a valid integer for the No. of steps!")
	  valid_integer = False
	if valid_integer:
	  self.button1.set_sensitive(False)
	  self.button2.set_sensitive(False)
	  self.button3.set_sensitive(False)
	  self.button6.set_sensitive(False)
	  self.button7.set_sensitive(False)
	  self.entry1.set_sensitive(False)
	  self.entry2.set_sensitive(False)
	  self.entry3.set_sensitive(False)
	  self.button4.set_sensitive(True)

	  end_iter = self.textbuffer.get_end_iter()
	  self.textbuffer.insert(end_iter, "Positioning: " + '\n')
	  
	  self.textbuffer.insert(end_iter, str(no_of_steps))
	  self.textbuffer.insert(end_iter, " step(s) ")
	  if self.button_radio.get_active() == False:
	    rotate_direction = "clockwise..."
	    end_iter = self.textbuffer.get_end_iter()
	    self.textbuffer.insert(end_iter, rotate_direction + '\n')
	    fw_or_bw = "2"
	  else:
	    rotate_direction = "anticlockwise..."
	    end_iter = self.textbuffer.get_end_iter()
	    self.textbuffer.insert(end_iter, rotate_direction + '\n')
	    fw_or_bw = "1"
	  no_of_steps = no_of_steps + 1
	  count = 1
	  abort = "0"
          if no_of_steps < 0 and fw_or_bw == "2":
                fw_or_bw = "1"
                no_of_steps = no_of_steps * -1
          if no_of_steps < 0 and fw_or_bw == "1":
                fw_or_bw = "2"
                no_of_steps = no_of_steps * -1
	  self.button5.set_sensitive(False)
	  self.refreshLog()
	  time.sleep(1)
	  while (count < no_of_steps):
	      ser.write(fw_or_bw)
	      #Loop until the motor steps.
	      delay = True
	      while delay:
	        arduino_message = ser.read()
	        if arduino_message == '0':
		  delay = False
	      text = str(count)
	      self.refreshLog()
	      text = ""
	      #Check if user aborted.
	      if abort == "1":
	  	count = no_of_steps
	  	end_iter = self.textbuffer.get_end_iter()
	  	self.textbuffer.insert(end_iter, "Process aborted!")
	  	self.refreshLog()
	      count = count + 1
	  end_iter = self.textbuffer.get_end_iter()
	  if abort == "0":
	    self.textbuffer.insert(end_iter, "Done." + '\n')
	  else:
	    self.textbuffer.insert(end_iter, "" + '\n')
	  self.refreshLog()    
	  self.button1.set_sensitive(True)
	  self.button2.set_sensitive(True)
	  self.button3.set_sensitive(True)
	  self.button5.set_sensitive(True)
	  self.button6.set_sensitive(True)
	  self.button7.set_sensitive(True)
	  self.entry1.set_sensitive(True)
	  self.entry2.set_sensitive(True)
	  self.entry3.set_sensitive(True)
	  self.button4.set_sensitive(False)
	  self.entry1.select_region(0, 10)
	  self.entry1.grab_focus()
	
    def count(self, widget, event, data=None):
	self.textview.set_justification(gtk.JUSTIFY_LEFT)
	global text
	self.textbuffer.set_text("" + '\n')
	valid_integer = True
	try:
	  no_of_photos = int(self.entry2.get_text())
	except ValueError:
	  end_iter = self.textbuffer.get_end_iter()
	  self.textbuffer.insert(end_iter, '\n' + "Please add a valid integer for the No. of photos!")
	  valid_integer = False
	
	if valid_integer:
	  no_of_steps = (self.entry3.get_text())
	  blank = False
	  if not str(no_of_steps):
	    end_iter = self.textbuffer.get_end_iter()
	    blank = True
	    if no_of_photos > 512:
	      self.textbuffer.insert(end_iter, "The max. resolution is 512 images/one full turn." + '\n' + "Please add the No. of photos, at most 512 to calculate the suggested No. of steps." + '\n')
	      self.textbuffer.insert(end_iter, '\n' + "Note: It is possible to take more than one full turn with the device with more than 512 photos but calculating the No. of steps is not possible in this case.")
	    else:
	      full_rotate_step = 512 / no_of_photos
	      full_rotate_photo = (512 - (full_rotate_step * no_of_photos)) / full_rotate_step
	      full_step_no = (full_rotate_photo + no_of_photos) * full_rotate_step
	      self.textbuffer.insert(end_iter, "For the best result use " + str(full_rotate_photo + no_of_photos) + " photos and " + str(full_rotate_step) + " step(s)." + '\n')
	      self.textbuffer.insert(end_iter, "This way the device takes " + str(full_step_no) + " steps. (512 steps equals 360 degrees.)")
	      
	  try:
	     no_of_steps = int(self.entry3.get_text())
	  except ValueError:
	    if not blank:
	      end_iter = self.textbuffer.get_end_iter()
	      self.textbuffer.insert(end_iter, '\n' + "Please add a valid integer for the No. of steps or leave it blank!")
	    valid_integer = False
	
	  if valid_integer:
	    no_of_photos = int(self.entry2.get_text())
	    no_of_steps = int(self.entry3.get_text())
	    full_step_no = no_of_photos * no_of_steps
	    end_iter = self.textbuffer.get_end_iter()
	    self.textbuffer.insert(end_iter, str(no_of_photos))
	    self.textbuffer.insert(end_iter, " photos with ")
	    self.textbuffer.insert(end_iter, str(full_step_no))
	    self.textbuffer.insert(end_iter, " steps. (512 steps equals 360 degrees.)" + '\n')
	    self.textbuffer.insert(end_iter, "If you accept, click the Shoot button.")
	
    def shoot(self, widget, event, data=None):
	global text
	global abort
	global ser
	text = ""
	self.textview.set_justification(gtk.JUSTIFY_LEFT)
	self.textbuffer.set_text("" + '\n')
	valid_integer = True
	try:
	  no_of_photos = int(self.entry2.get_text())
	  no_of_steps = int(self.entry3.get_text())	
	except ValueError:
	  end_iter = self.textbuffer.get_end_iter()
	  self.textbuffer.insert(end_iter, "*** Error! ***" + '\n')
	  self.textbuffer.insert(end_iter, '\n' + "Please add a valid integer for both the No. of photos and No. of steps!")
	  valid_integer = False
	if valid_integer and no_of_photos < 0:
	  end_iter = self.textbuffer.get_end_iter()
	  self.textbuffer.insert(end_iter, "*** Error! ***" + '\n')
	  self.textbuffer.insert(end_iter, '\n' + "Negative numbers are not allowed!")
	  valid_integer = False
	if valid_integer:
	  self.button1.set_sensitive(False)
	  self.button2.set_sensitive(False)
	  self.button3.set_sensitive(False)
	  self.button6.set_sensitive(False)
	  self.button7.set_sensitive(False)
	  self.entry1.set_sensitive(False)
	  self.entry2.set_sensitive(False)
	  self.entry3.set_sensitive(False)
	  self.button4.set_sensitive(True)

	  full_step_no = no_of_photos * no_of_steps
	  end_iter = self.textbuffer.get_end_iter()
	  self.textbuffer.insert(end_iter, "Shooting ")
	  self.textbuffer.insert(end_iter, str(no_of_photos))
	  self.textbuffer.insert(end_iter, " photos with ")
	  self.textbuffer.insert(end_iter, str(full_step_no))
	  self.textbuffer.insert(end_iter, " steps...")
	  fw_or_bw = "2"
	  if no_of_steps < 0:
	    fw_or_bw = "1"
	    no_of_steps = no_of_steps * -1
	  no_of_steps = no_of_steps + 1
	  no_of_photos = no_of_photos + 1
	  os.system("gphoto2 --set-config /main/settings/capturetarget=1")
	  photo_count = 1
	  abort = "0"
	  self.button5.set_sensitive(False)
	  self.refreshLog()
	  time.sleep(1)
	  while (photo_count < no_of_photos):
	    abort = "0"
	    text = ""
	    end_iter = self.textbuffer.get_end_iter()
	    self.textbuffer.insert(end_iter, '\n' + "Photo No. " + str(photo_count) + "...")
	    self.refreshLog()
	    end_iter = self.textbuffer.get_end_iter()
	    self.textbuffer.insert(end_iter, "")
	    self.refreshLog()
	    time.sleep(2)
	    os.system("gphoto2 --capture-image > logfile.tmp")
	    logfile = open("logfile.tmp").read()
	    if "--debug" in logfile or not " " in logfile:
	        abort = "1"
	        end_iter = self.textbuffer.get_end_iter()
	        self.textbuffer.insert(end_iter, "*** Camera Error! ***" + '\n')
	        self.textbuffer.insert_at_cursor("Possible reasons:" + '\n')
	        self.textbuffer.insert_at_cursor("	  -Camera mounted," + '\n')
	        self.textbuffer.insert_at_cursor("	  -Camera not supported," + '\n')
	        self.textbuffer.insert_at_cursor("	  -Camera turned off (check the auto turn-off in camera settings)," + '\n')
	        self.textbuffer.insert_at_cursor("	  -Camera not plugged," + '\n')
	        self.textbuffer.insert_at_cursor("	  -Camera memory card is full," + '\n')
	        self.textbuffer.insert_at_cursor("	  -Focus not found (only on auto focus mode)." + '\n')
	        self.textbuffer.insert_at_cursor("Check the camera settings and try again. If error still occours run the following \ncommand in terminal:" + '\n')
	        self.textbuffer.insert_at_cursor( "      $ gphoto2 --capture-image" + '\n')
	        self.textbuffer.insert_at_cursor('\n')
	    else:
	      end_iter = self.textbuffer.get_end_iter()
	      self.textbuffer.insert(end_iter, logfile)
	      
	      end_iter = self.textbuffer.get_end_iter()
	      self.textbuffer.insert(end_iter, "Stepping..." + '\n')
	    steps_count = 1
	    while (steps_count < no_of_steps):
	        text = ""
	        #Check if user aborted.
	        if abort == "1":
	  	  steps_count = no_of_steps
	        else:
	  	  ser.write(fw_or_bw)
	  	  #Wait until the motor steps.
	  	  delay = True
	  	  while delay:
	  	    arduino_message = ser.read()
	  	    if arduino_message == '0':
	  	      delay = False
	  	  text = str(steps_count)
	  	  self.refreshLog()
	  	  steps_count = steps_count + 1
	    if abort == "1":
	      photo_count = no_of_photos
	      end_iter = self.textbuffer.get_end_iter()
	      self.textbuffer.insert(end_iter, "Process aborted!")
	      self.refreshLog()
	    photo_count = photo_count + 1
	  text = ""
	  end_iter = self.textbuffer.get_end_iter()
	  if abort == "0":
	    self.textbuffer.insert(end_iter, "Done." + '\n')
	  else:
	    self.textbuffer.insert(end_iter, "" + '\n')
	  self.refreshLog()
	  os.system("rm logfile.tmp")
	  self.button1.set_sensitive(True)
	  self.button2.set_sensitive(True)
	  self.button3.set_sensitive(True)
	  self.button5.set_sensitive(True)
	  self.button6.set_sensitive(True)
	  self.button7.set_sensitive(True)
	  self.entry1.set_sensitive(True)
	  self.entry2.set_sensitive(True)
	  self.entry3.set_sensitive(True)
	  self.button4.set_sensitive(False)
	
    def abort(self, widget, event, data=None):
	global abort
	abort = "1"
	
    def preview(self, widget, event, data=None):
	global filename
        self.textview.set_justification(gtk.JUSTIFY_LEFT)
        self.textbuffer.set_text("" + '\n')
        self.button1.set_sensitive(False)
	self.button2.set_sensitive(False)
	self.button3.set_sensitive(False)
	self.button6.set_sensitive(False)
	self.button7.set_sensitive(False)
	self.entry1.set_sensitive(False)
	self.entry2.set_sensitive(False)
	self.entry3.set_sensitive(False)
	self.textbuffer.set_text("")
	self.textbuffer.insert_at_cursor("Shooting, downloading and opening image..." + '\n')
	self.refreshLog()
	os.system("echo 'y' > yes.tmp")
	os.system("gphoto2 --capture-image-and-download <yes.tmp > logfile.tmp")
	os.system("rm yes.tmp")
	logfile = open("logfile.tmp").read()
	if "--debug" in logfile or not " " in logfile:
	    abort = "1"
	    end_iter = self.textbuffer.get_end_iter()
	    self.textbuffer.insert(end_iter, "*** Camera Error! ***" + '\n')
	    self.textbuffer.insert_at_cursor("Possible reasons:" + '\n')
	    self.textbuffer.insert_at_cursor("	  -Camera mounted," + '\n')
	    self.textbuffer.insert_at_cursor("	  -Camera not supported," + '\n')
	    self.textbuffer.insert_at_cursor("	  -Camera turned off (check the auto turn-off in camera settings)," + '\n')
	    self.textbuffer.insert_at_cursor("	  -Camera not plugged," + '\n')
	    self.textbuffer.insert_at_cursor("	  -Camera memory card is full," + '\n')
	    self.textbuffer.insert_at_cursor("	  -Focus not found (only on auto focus mode)." + '\n')
	    self.textbuffer.insert_at_cursor("Check the camera settings and try again. If error still occours run the following \ncommand in terminal:" + '\n')
	    self.textbuffer.insert_at_cursor("      $ gphoto2 --capture-image" + '\n')
	    self.textbuffer.insert_at_cursor('\n')
	else:
	  os.system("grep -o -E '\w*.JPG\w*|\w*.jpg\w*|\w*.Jpg\w*' logfile.tmp > logfile2.tmp")
	  logfile = open("logfile2.tmp").read()
	  count = 1
	  for grep_list in logfile.split('\n'):
	    if count == 2:
	      filename = grep_list
	    count = count + 1
	  end_iter = self.textbuffer.get_end_iter()
	  self.textbuffer.insert(end_iter, "The pictue's name is: " + filename + '\n')
	  self.previewwin = gtk.Window()
	  self.previewwin.set_position(gtk.WIN_POS_CENTER)
	  screen_width = gtk.gdk.screen_get_default().get_width()
	  screen_height = gtk.gdk.screen_get_default().get_height()
	  screen_height = screen_height - 25
	  screen_width = screen_width - 5
	  self.previewwin.set_title("Image Preview: " + filename)
	  #Find out image size...
	  os.system("identify " + filename +" > logfile.tmp")
	  logfile = open("logfile.tmp").read()
	  os.system("rm logfile2.tmp")
	  img_ident = logfile.split (' ', 3)
	  count = 1
	  for width_and_height in img_ident:
	    if count == 3:
	      wh = width_and_height
	    count = count + 1
	  count = 1
	  img_ident = wh.split ('x')
	  for width_and_height in img_ident:
	    if count == 1:
	      img_width = int(width_and_height)
	    if count == 2:
	      img_height = int(width_and_height)
	    count = count + 1
	  if screen_width < img_width or screen_height < img_height: #Image is bigger than screen
	      width_scale = img_width / float(screen_width)
	      height_scale = img_height / float(screen_height)
	      if width_scale > height_scale:
	  	  width = screen_width
	  	  height = img_height / width_scale
	      else:
	  	  height = screen_height
	  	  width = img_width / height_scale
	      self.previewwin.set_size_request(int(width), int(height))
	      pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
	      pixbuf = pixbuf.scale_simple(int(width), int(height), gtk.gdk.INTERP_BILINEAR)
	  else:
	    self.previewwin.set_size_request(img_width, img_height)
	    pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
	    pixbuf = pixbuf.scale_simple(img_width, img_height, gtk.gdk.INTERP_BILINEAR)
	    
	  self.image = gtk.image_new_from_pixbuf(pixbuf)        
	  self.previewwin.add_events(gtk.gdk.BUTTON_PRESS_MASK)
	  self.previewwin.connect('button-press-event', self.zoom, 0)
	  self.image.set_tooltip_text("Double click to open image in default viewer.")
	  self.image.show()
	  self.previewwin.add(self.image)
	  self.previewwin.show()
	os.system("rm logfile.tmp")
	self.button1.set_sensitive(True)
	self.button2.set_sensitive(True)
	self.button3.set_sensitive(True)
	self.button6.set_sensitive(True)
	self.button7.set_sensitive(True)
	self.entry1.set_sensitive(True)
	self.entry2.set_sensitive(True)
	self.entry3.set_sensitive(True)
    
    def zoom(self, widget, event, data=None):
	global filename
	if event.type == gtk.gdk._2BUTTON_PRESS:
	  os.system('xdg-open ' + filename)
	  self.previewwin.hide()
	
    def _help(self, widget, event, data=None):
	self.textview.set_justification(gtk.JUSTIFY_LEFT)
	self.textbuffer.set_text("")
	self.textbuffer.insert_at_cursor("Product Photo 360 - version 1.0" + '\n')
	self.textbuffer.insert_at_cursor('\n' + "- Description: " + '\n' + "This free and open source program can be used to take 360 degree product photography. The program consists of two parts (the Positioning and the Rotating photography frame)." + '\n')
	self.textbuffer.insert_at_cursor("" + '\n')
	self.textbuffer.insert_at_cursor("- The positioning frame:" + '\n' + "Use this frame to rotate and position the object. It is useful to check whether the object is always in the field of view over the full turn. Set the No. of steps and press the Rotate button. The direction of the rotation can be set by the radio buttons." + '\n' + '\n' + "Attention: the device will rotate only if the stepper_for_photo.ino file is installed to the arduino." + '\n' + "The file is available from the url below:" + '\n' + "http://preparatorium.hu/360_degree_product_photography/stepper_for_photo.ino" + '\n')
	self.textbuffer.insert_at_cursor("" + '\n')
	self.textbuffer.insert_at_cursor("- The rotating photography frame:" + '\n' + "1. The Count button: After setting the No. of photos and the No. of steps, the No. of all steps can be checked. If just the No. of photos are added, the count button suggests the No. of steps and also the No. of photos for the best result." + '\n' + "2. The Shoot button: After setting both the No. of photos and the No. of steps, use this button to start taking photos. Before clicking this button, make sure the camera is set properly." + '\n')
	self.textbuffer.insert_at_cursor("" + '\n')
	self.textbuffer.insert_at_cursor("- Abort button:" + '\n' + "Use this button for aborting the running process." + '\n')
	self.textbuffer.insert_at_cursor("" + '\n')
	self.textbuffer.insert_at_cursor("- Preview button:" + '\n' + "The camera takes a photo and the program opens it in a new window after donwloading. Double clicking on the image opens it in the default image viewer." + '\n')
	self.textbuffer.insert_at_cursor("" + '\n')
	self.textbuffer.insert_at_cursor("For further information visit:" + '\n' + "http://preparatorium.hu/360_degree_product_photography.html" '\n')
	self.textbuffer.insert_at_cursor("" + '\n')
	self.textbuffer.insert_at_cursor("Author: Adam Pereszlenyi - July 2015." + '\n' + "www.preparatorium.hu" '\n')

    def delete_event(self, widget, event, data=None):
        global ser
        global dont_use_ser
        if dont_use_ser == False:
	  ser.close()
        gtk.main_quit()
        return False
        
    def __init__(self):
	global dont_use_ser
	global serial_path
        # Create the window and widgets.
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_position(gtk.WIN_POS_CENTER)
        self.window.set_title("Product Photo 360")
        self.window.connect("delete_event", self.delete_event)
        self.window.set_size_request(600, 400)
        self.window.set_border_width(10)
        
        # Create vertical box (box1)
        self.box1 = gtk.VBox(False, 0)
        self.window.add(self.box1)
        
        self.table2 = gtk.Table(1, 3, False)
        self.box1.pack_start(self.table2, False, False, 0)
        self.table2.show()
        
        label = gtk.Label("Written by Adam Pereszlenyi - 2015.")
        self.table2.attach(label, 0, 1, 0, 1, gtk.EXPAND, gtk.EXPAND, 0, 0)
        label.show()
        linkbutton = gtk.LinkButton("http://preparatorium.hu/360_degree_product_photography.html#donate", "Click here to donate.")
        self.table2.attach(linkbutton, 1, 2, 0, 1, gtk.EXPAND, gtk.EXPAND, 0, 0)
        linkbutton.set_alignment(0, 1)
        linkbutton.show()
        
        self.box5 = gtk.HBox(True, 5)
        self.box1.pack_start(self.box5, False, False, 0)
        #Frame
        frame1 = gtk.Frame("Positioning")
        self.box5.pack_start(frame1, True, True, 0)
        frame1.show()
        # Create vertical box for positioning. (box2)
        self.box2 = gtk.VBox(False, 5)
        frame1.add(self.box2)
        #Label
        label = gtk.Label(" <i>Set No. of steps then click Rotate!</i>  ")        
        self.box2.pack_start(label, True, False, 5) 
        label.set_alignment(0, 0)
        label.show()
        label.set_use_markup(gtk.TRUE)
        #Create horizontal box in positioning. (box3)
        self.box3 = gtk.HBox(False, 5)
        self.box2.pack_start(self.box3, False, False, 0)
        self.entry1 = gtk.Entry(5)
        self.entry1.set_text("512")
        self.entry1.set_width_chars(8)
        self.entry1.connect("activate", self.rotate, 0)
        self.box3.pack_start(self.entry1, False, False, 0)
        self.entry1.show()
        #Create vertical box for radio buttons. (box4)
        self.box4 = gtk.VBox(False, 0)
        self.box3.add(self.box4)
        # Radiobuttons
        self.button_radio = gtk.RadioButton(None, "Clockwise")
        self.button_radio.set_active(True)
        self.box4.pack_start(self.button_radio, True, True, 0)
        self.button_radio.show()
        self.button_radio = gtk.RadioButton(self.button_radio, "Anticlockwise")
        self.button_radio.set_active(False)
        self.box4.pack_start(self.button_radio, True, True, 0)
        self.button_radio.show()

        self.button1 = gtk.Button("Rotate")
        self.button1.connect("clicked", self.rotate, 0)
        self.box3.pack_start(self.button1, False, False, 1)
        
        #Separator
        separator = gtk.HSeparator()
        self.box1.pack_start(separator, False, True, 0)
        separator.show()
        
        #FRAME
	frame2 = gtk.Frame("Rotating photography")
        self.box5.pack_start(frame2, True, True, 0)
        frame2.show()        
        
        #Table
        self.table = gtk.Table(2, 3, False)
        frame2.add(self.table)
        self.table.show()
        #Label - No. of photos
        label = gtk.Label("<i> Set No. of photos:</i>")
        self.table.attach(label, 0, 1, 0, 1, gtk.EXPAND, gtk.EXPAND, 5, 5)
        label.set_alignment(0, 0)
        label.show()
        label.set_use_markup(gtk.TRUE)
        
        #Entry - No. of photos
        self.entry2 = gtk.Entry(5)
        self.entry2.set_text("102")
        self.entry2.set_width_chars(10)
        self.table.attach(self.entry2, 1, 2, 0, 1, gtk.EXPAND, gtk.EXPAND, 5, 5)
        self.entry2.show()
        
        #Label - No. of steps between 2 photos
        label = gtk.Label("<i> Set No. of steps \n between 2 photos:</i>")
        self.table.attach(label, 0, 1, 1, 2, gtk.EXPAND, gtk.EXPAND, 5, 5)
        label.set_alignment(0, 0)
        label.show()
        label.set_use_markup(gtk.TRUE)
        
        #Entry - No. of steps between 2 photos
        self.entry3 = gtk.Entry(5)
        self.entry3.set_text("5")
        self.entry3.set_width_chars(10)
        self.table.attach(self.entry3, 1, 2, 1, 2, gtk.SHRINK, gtk.SHRINK, 5, 15)
        self.entry2.show()
        
        #Button - Count
        self.button2 = gtk.Button("Count")
        self.button2.connect("clicked", self.count, 0)
        self.table.attach(self.button2, 2, 3, 0, 1, gtk.SHRINK, gtk.SHRINK, 5, 5)
        
        #Button - Shoot!
        self.entry3.show()
        self.button3 = gtk.Button("Shoot")
        self.button3.connect("clicked", self.shoot, 0)
        self.table.attach(self.button3, 2, 3, 1, 2, gtk.SHRINK, gtk.SHRINK, 5, 5)
        
        #Separator
        separator = gtk.HSeparator()
        self.box1.pack_start(separator, False, True, 0)
        separator.show()
        
        #viewbox
        self.scrolledwindow = gtk.ScrolledWindow()
        self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.textview = gtk.TextView()
        self.textbuffer = self.textview.get_buffer()
        self.textview.set_justification(gtk.JUSTIFY_CENTER)
        self.textbuffer.insert_at_cursor("" + '\n')
        self.textbuffer.insert_at_cursor("" + '\n')
        self.textbuffer.insert_at_cursor("" + '\n')
        self.textbuffer.insert_at_cursor("Welcome!" + '\n')
	self.textbuffer.insert_at_cursor("" + '\n')
	self.textbuffer.insert_at_cursor("" + '\n')
	self.textbuffer.insert_at_cursor("Arduino found on port " + serial_path + "." + '\n')
	self.textbuffer.insert_at_cursor("Before continuing make sure the camera is connected and unmounted!")
	
	self.textview.set_editable(False)
	self.textview.set_wrap_mode(gtk.WRAP_WORD)
        self.scrolledwindow.add(self.textview)
        self.scrolledwindow.show()
        self.textview.show()
        self.box1.pack_start(self.scrolledwindow)
        
        self.table = gtk.Table(1, 4, False)
        self.box1.pack_start(self.table, False, False, 0)
        self.table.show()
        
        self.button7 = gtk.Button("Preview")
        self.button7.connect("clicked", self.preview, 0)
        self.table.attach(self.button7, 0, 1, 0, 1, gtk.EXPAND, gtk.EXPAND, 20, 5)
        
        # Button4 - Abort
        self.button4 = gtk.Button("Abort")
        self.button4.connect("clicked", self.abort, 0)
        self.table.attach(self.button4, 1, 2, 0, 1, gtk.EXPAND, gtk.EXPAND, 20, 5)
        self.button4.set_sensitive(False)
        
        #Button6 - Help
        self.button6 = gtk.Button(stock=gtk.STOCK_HELP)
        self.button6.connect("clicked", self._help, 0)
        self.table.attach(self.button6, 2, 3, 0, 1, gtk.EXPAND, gtk.EXPAND, 20, 5)
        
        #Button5 - Quit button
        self.button5 = gtk.Button(stock=gtk.STOCK_QUIT)
        self.button5.connect("clicked", self.delete_event, 0)
        self.table.attach(self.button5, 3, 4, 0, 1, gtk.EXPAND, gtk.EXPAND, 20, 5)
        
	self.refreshLog() 
	# Timer to autorefresh log 
	gobject.timeout_add(50, self.refreshLog) 
        
        #If serial port didn't found:
	if dont_use_ser:
	  self.textbuffer.set_text("")
	  self.button1.set_sensitive(False)
	  self.button2.set_sensitive(False)
	  self.button3.set_sensitive(False)
	  self.button4.set_sensitive(False)
	  self.button6.set_sensitive(False)
	  self.button7.set_sensitive(False)
	  self.entry1.set_sensitive(False)
	  self.entry2.set_sensitive(False)
	  self.entry3.set_sensitive(False)
	  self.textbuffer.insert_at_cursor("" + '\n')
	  self.textbuffer.insert_at_cursor("" + '\n')
	  self.textbuffer.insert_at_cursor("" + '\n')
	  self.textbuffer.insert_at_cursor("*** Error: Arduino not found. ***" + '\n')
	  self.textbuffer.insert_at_cursor("" + '\n')
	  self.textbuffer.insert_at_cursor("Plug in the arduino and restart the program." + '\n')
	  self.textbuffer.insert_at_cursor("If the arduino is plugged in check the place of the serial port and modify line 32 in the source file." + '\n')
        
        #Show buttons, boxes and window.
        self.button1.show()
        self.button2.show()        
        self.button3.show()
        self.button4.show()
        self.button5.show()
        self.button6.show()
        self.button7.show()
        self.box1.show()
        self.box2.show()
        self.box3.show()
        self.box4.show()
        self.box5.show()
        self.window.show()
        
def main():
    gtk.main()

if __name__ == "__main__":
    ProductPhoto360()
    main()
