summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrzemyslaw <prymula76@outlook.com>2024-04-02 16:54:04 +0200
committerPrzemyslaw <prymula76@outlook.com>2024-04-02 16:54:04 +0200
commit6be61aef6ad0ffb370deb4df5ad48487b56e3678 (patch)
treee117d8199d4de50de11d7baa50753c5385abc071
-rw-r--r--DEBIAN/HOWTO2
-rw-r--r--DEBIAN/debian.changelog5
-rw-r--r--DEBIAN/debian.control13
-rw-r--r--DEBIAN/debian.rules29
-rw-r--r--DEBIAN/format.sh1
-rw-r--r--DEBIAN/photocrop.dsc41
-rw-r--r--INSTALL92
-rw-r--r--LICENSE339
-rw-r--r--Makefile21
-rw-r--r--Makefile.in.gzbin0 -> 247 bytes
-rw-r--r--RPM/photocrop.spec71
-rw-r--r--bugs.txt3
-rw-r--r--changelog70
-rw-r--r--configure.gzbin0 -> 495 bytes
-rw-r--r--data/IMG_6854.JPGbin0 -> 359172 bytes
-rw-r--r--data/clip.pngbin0 -> 55258 bytes
-rw-r--r--data/photocrop.desktop15
-rw-r--r--src/photocrop.py1164
-rw-r--r--xcf/clip.xcfbin0 -> 51253 bytes
19 files changed, 1866 insertions, 0 deletions
diff --git a/DEBIAN/HOWTO b/DEBIAN/HOWTO
new file mode 100644
index 0000000..a371e0b
--- /dev/null
+++ b/DEBIAN/HOWTO
@@ -0,0 +1,2 @@
+foramt zapisu nazwy pliku:
+ photocrop_0.221225-0~alpha.tar.gz
diff --git a/DEBIAN/debian.changelog b/DEBIAN/debian.changelog
new file mode 100644
index 0000000..0adf1f3
--- /dev/null
+++ b/DEBIAN/debian.changelog
@@ -0,0 +1,5 @@
+photocrop (0.221225-4) unstable; urgency=low
+
+ * Last release
+
+ -- Przemysław R. Pietraszczyk Sat, 25 Dec 2022 08:31:41 +0200
diff --git a/DEBIAN/debian.control b/DEBIAN/debian.control
new file mode 100644
index 0000000..bf96b7d
--- /dev/null
+++ b/DEBIAN/debian.control
@@ -0,0 +1,13 @@
+Source: photocrop
+Section: python
+Priority: extra
+Maintainer: Przemysław R. Pietraszczyk
+Build-Depends: debhelper-compat (= 13), python3-all, dh-python, python3-gi, python3-gi-cairo, gir1.2-gtk-3.0, fakeroot
+Standards-Version: 0.230112-0~alpha
+Homepage: http://prymula.ct8.pl
+
+
+Package: photocrop
+Architecture: all
+Depends: ${misc:Depends}, python3-all, python3-gi, python3-gi-cairo, gir1.2-gtk-3.0
+Description: An application for cropping photos to popular paper sizes.
diff --git a/DEBIAN/debian.rules b/DEBIAN/debian.rules
new file mode 100644
index 0000000..ce6541d
--- /dev/null
+++ b/DEBIAN/debian.rules
@@ -0,0 +1,29 @@
+#!/usr/bin/make -f
+
+export DH_VERBOSE = 1
+#export PYBUILD_NAME = photocrop
+#export PYBUILD_SYSTEM = custom
+
+clean:
+ @
+
+build:
+ @
+
+binary:
+ mkdir -pm 0755 debian/photocrop
+ mkdir -pm 0755 debian/photocrop/usr/bin
+ mkdir -pm 0755 debian/photocrop/usr/share
+ mkdir -pm 0755 debian/photocrop/usr/share/photocrop
+ mkdir -pm 0755 debian/photocrop/usr/share/applications
+ cp src/photocrop.py debian/photocrop/usr/bin
+ cp data/clip.png debian/photocrop/usr/share/photocrop
+ cp data/IMG_6854.JPG debian/photocrop/usr/share/photocrop
+ cp data/photocrop.desktop debian/photocrop/usr/share/applications
+ dh_gencontrol
+ dh_builddeb
+# dh $@ --with python3 --buildsystem=pybuild
+# dh $@ --with python3
+
+#override_dh_auto_configure:
+# dh_auto_configure --
diff --git a/DEBIAN/format.sh b/DEBIAN/format.sh
new file mode 100644
index 0000000..d0e6a06
--- /dev/null
+++ b/DEBIAN/format.sh
@@ -0,0 +1 @@
+exec /usr/lib/build/debtransform ./ ./photocrop.dsc ./exec
diff --git a/DEBIAN/photocrop.dsc b/DEBIAN/photocrop.dsc
new file mode 100644
index 0000000..a742dc5
--- /dev/null
+++ b/DEBIAN/photocrop.dsc
@@ -0,0 +1,41 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+Format: 1.0
+Source: photocrop
+Binary: photocrop
+Architecture: all
+Version: 0.230112-0~alpha
+Maintainer: Przemysław R. Pietraszczyk <przem@pietraszczyk.vxm.pl>
+Homepage: http://pietraszczyk.vxm.pl
+DEBTRANSFORM-TAR: debian.tar.gz
+DEBTRANSFORM-TAR: photocrop_0.2301012-0~alpha.tar.gz
+
+Standards-Version: 0.2301012-0~alpha
+Build-Depends: debhelper-compat (= 13), python3-all, dh-python, python3-gi, python3-gi-cairo, gir1.2-gtk-3.0, fakeroot
+Package-List:
+ photocrop deb x11 optional arch=all
+Files:
+ b31649bc23b2b7bca9ab70ea3410711a 128820 photocrop_0.230112-0~alpha.tar.gz
+ 29e7e7e60bc81891e3da3871b9eeb549 764 photocrop-0.230112-0~alpha.debian.tar.xz
+
+-----BEGIN PGP SIGNATURE-----
+
+mQENBGEf/c4BCAC2d4ymW0pRZV36qLtlt/WGb83kos5UX5UbwvkQrbUjAbOPOY8w
+DT3M1neYOAPZx38924aPTFKbZPcz+rK/7Wcv1kzgfux5zXQJTLeqpkhUYAgXUg2p
+oK9ZXsai82fOicTrClOyJLLYQ8C1vj8yUh7e3ERljEyp5Nxg/lY92rwcZ4WYR193
+nGDInlDl5JlWUcLlk/RFnC5bB+T6ZZr5FBX/eDnKAPEl+N3MWpDs2JLDy7EUPhcG
+U/60X0wuXHPTwMoNbB3ep/bWRxwEej0sFad5GXeCh7hKCroi/kLmLTDIxSD8lsRr
+Y4H/8H2lBBsQq7bRL88N6ZDGCocPo11V83kFABEBAAG0NmhvbWU6cHJ6ZW0gT0JT
+IFByb2plY3QgPGhvbWU6cHJ6ZW1AYnVpbGQub3BlbnN1c2Uub3JnPokBPgQTAQgA
+KAUCYR/9zgIbAwUJBB6wAAYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQcXEc
+NPcNefFEAAf+Kg4cs/C99kEIMv/PO85VW+p8rcTwCViOFUX5WrBhwsRyPAKrJPPG
+KD6PdnvoplcNQwhQ8nRsRiiaiUtPcj8Bvi6EdPgSgXXObKKJtCyaAa1rURdlb9iW
+CfvXA6oW+PGlii9BMnXOAtkeFIzZooO9oXd+wez66P+4VWFiFzxanLfLn/hwbWxQ
+68rlO3QNGbrMeODBgwh9s83XGmAg47mn2fldTAmTbJDf9tMi1LhX2MmLyN9wjqsd
+4IZ9JMri2JTnIhYfxWdKT9gsu7q0g8LqonaXMvlOEyHFRF1YQ0i7G6fFbvDcKCZN
+W1Eja55FdN7smv5Eck6UTIIYyWPuAv45uohGBBMRAgAGBQJhH/3PAAoJEDswEbdr
+nWUj4M0AniJ389dyvUjjgS91AcOb08E4moV9AJ9WDL3/7GYYUL/Azw43QucWPnXr
+uw==
+=+lfH
+-----END PGP SIGNATURE-----
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..0906aec
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,92 @@
+Windows
+
+Go to http://www.msys2.org/ and download the x86_64 installer
+
+Follow the instructions on the page for setting up the basic environment
+
+Run C:\msys64\mingw64.exe - a terminal window should pop up
+
+Execute pacman -Suy
+
+Execute pacman -S mingw-w64-x86_64-gtk3 mingw-w64-x86_64-python3 mingw-w64-x86_64-python3-gobject
+
+
+Ubuntu/Debian
+
+Installing the system provided PyGObject:
+Open a terminal
+
+Execute sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-3.0
+
+Installing from PyPI with pip:
+Open a terminal and enter your virtual environment
+
+Execute sudo apt install libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev gir1.2-gtk-3.0 to install the build dependencies and GTK
+
+Execute pip3 install pycairo to build and install Pycairo
+
+Execute pip3 install PyGObject to build and install PyGObject
+
+
+
+Fedora
+
+Installing the system provided PyGObject:
+Open a terminal
+
+Execute sudo dnf install python3-gobject gtk3
+
+Open a terminal and enter your virtual environment
+
+Execute sudo dnf install gcc gobject-introspection-devel cairo-gobject-devel pkg-config python3-devel gtk3 to install the build dependencies and GTK
+
+Execute pip3 install pycairo to build and install Pycairo
+
+Execute pip3 install PyGObject to build and install PyGObject
+
+
+Arch Linux
+
+Installing the system provided PyGObject:
+Open a terminal
+
+Execute sudo pacman -S python-gobject gtk3
+
+Installing from PyPI with pip:
+Open a terminal and enter your virtual environment
+
+Execute sudo pacman -S python cairo pkgconf gobject-introspection gtk3 to install the build dependencies and GTK
+
+Execute pip3 install pycairo to build and install Pycairo
+
+Execute pip3 install PyGObject to build and install PyGObject
+
+
+
+
+openSUSE
+
+Installing the system provided PyGObject:
+Open a terminal
+
+Execute sudo zypper install python3-gobject python3-gobject-Gdk typelib-1_0-Gtk-3_0 libgtk-3-0
+
+Installing from PyPI with pip:
+Open a terminal and enter your virtual environment
+
+Execute sudo zypper install cairo-devel pkg-config python3-devel gcc gobject-introspection-devel to install the build dependencies and GTK
+
+Execute pip3 install pycairo to build and install Pycairo
+
+Execute pip3 install PyGObject to build and install PyGObject
+
+
+
+
+macOS
+
+Go to https://brew.sh/ and install homebrew
+
+Open a terminal
+
+Execute brew install pygobject3 gtk+3
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3f36b99
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+
+prefix=/usr
+
+all:
+
+install:
+ mkdir -pm 0755 $(prefix)/share/photocrop
+ install -m 0755 src/photocrop.py $(prefix)/bin
+ install -m 0644 data/clip.png $(prefix)/share/photocrop
+ install -m 0644 data/IMG_6854.JPG $(prefix)/share/photocrop
+ install -m 0644 data/photocrop.desktop $(prefix)/share/applications
+
+
+uninstall:
+ rm $(prefix)/share/photocrop/clip.png
+ rm $(prefix)/share/photocrop/IMG_6854.JPG
+ rmdir $(prefix)/share/photocrop/
+ rm $(prefix)/bin/photocrop.py
+ rm $(prefix)/share/applications/photocrop.desktop
+
+.PHONY: all install uninstall
diff --git a/Makefile.in.gz b/Makefile.in.gz
new file mode 100644
index 0000000..457147f
--- /dev/null
+++ b/Makefile.in.gz
Binary files differ
diff --git a/RPM/photocrop.spec b/RPM/photocrop.spec
new file mode 100644
index 0000000..228be57
--- /dev/null
+++ b/RPM/photocrop.spec
@@ -0,0 +1,71 @@
+#
+# spec file for package photocrop
+#
+# Copyright (c) 2020 SUSE LLC
+#
+# All modifications and additions to the file contributed by third parties
+# remain the property of their copyright owners, unless otherwise agreed
+# upon. The license for this file, and modifications and additions to the
+# file, is the same license as for the pristine package itself (unless the
+# license for the pristine package is not an Open Source License, in which
+# case the license is the MIT License). An "Open Source License" is a
+# license that conforms to the Open Source Definition (Version 1.9)
+# published by the Open Source Initiative.
+
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
+#
+
+%define unmangled_version 0.230112-0~alpha
+Name: photocrop
+Version: 0.230112
+Release: 0~alpha
+Summary: An application for cropping photos to popular paper sizes.
+License: GPL
+URL: https://pietraszczyk.vxm.pl/przycinanie-zdjec/
+Source0: %{name}-%{unmangled_version}.tar.gz
+%if 0%{?suse_version}>=150000
+BuildRequires: python3, python3-gobject, python3-gobject-Gdk, typelib-1_0-Gtk-3_0, libgtk-3-0
+Requires: python3, python3-gobject, python3-gobject-Gdk, typelib-1_0-Gtk-3_0, libgtk-3-0
+%endif
+%if 0%{?fedora}>=35
+BuildRequires: python3, python3-gobject, gtk3
+Requires: python3, python3-gobject, gtk3
+%endif
+BuildArch: noarch
+
+%description
+
+
+%prep
+%setup -n %{name}-%{unmangled_version} -n %{name}-%{unmangled_version}
+
+%build
+
+%install
+
+mkdir -p %{buildroot}/usr
+mkdir -p %{buildroot}/usr/share
+mkdir -p %{buildroot}/usr/share/photocrop
+mkdir -p %{buildroot}/usr/share/applications
+mkdir -p %{buildroot}/usr/bin
+
+install -m 0755 src/photocrop.py %{buildroot}/usr/bin
+install -m 0644 data/clip.png %{buildroot}/usr/share/photocrop/clip.png
+#install -m 0644 data/blank.png %{buildroot}/usr/share/photocrop/blank.png
+install -m 0644 data/IMG_6854.JPG %{buildroot}/usr/share/photocrop/IMG_6854.JPG
+install -m 0644 data/photocrop.desktop %{buildroot}/usr/share/applications
+
+
+
+%files
+%defattr(0755,root,root)
+/usr/bin/photocrop.py
+/usr/share/photocrop/
+%defattr(0644,root,root)
+/usr/share/photocrop/clip.png
+#/usr/share/photocrop/blank.png
+/usr/share/photocrop/IMG_6854.JPG
+/usr/share/applications/photocrop.desktop
+
+%changelog
+
diff --git a/bugs.txt b/bugs.txt
new file mode 100644
index 0000000..0a6128d
--- /dev/null
+++ b/bugs.txt
@@ -0,0 +1,3 @@
+1. Losowe zniekształcenia na podglądzie po przycięciu, ale tylko na podglądzie, wydruk jest prawidłowy.
+2. Źle współpracuje z grafiką utworzoną w Krita.
+3. Przed wydrukiem należy spojrzeć w kreatorze wydruku na sugerowaną orientację zdjęcia.
diff --git a/changelog b/changelog
new file mode 100644
index 0000000..9d9b626
--- /dev/null
+++ b/changelog
@@ -0,0 +1,70 @@
+0.230112-0 - Poprawki odświeżania okna po przycięciu
+0.230107-0 - Poprawiłem skalowanie dla średniego formatu. Wyszła na jaw zła współpraca z grafiką utworzoną w Krita !
+0.221229-0 - Interfejs po angielsku, poprawiłem skalowanie ramki dla małego i dużego formatu.
+0.221225-0 - Korekta wielkości początkowej ramki
+0.221224-3 - Poprawki dla konfiguracji ramki dla pozostałych formatów
+0.221234-2 - Poprawiłem skalowanie dla zdjęć horyzontalnych
+0.221224-1 - W zależności jaka była pierwotnie orientacja zdjęcia, po obrocie jest ono odpowiednio przycinane
+0.221224-0 - Nie rozciąga już zdjęcia po przycięciu po obrocie na wertylkane
+0.221223-0 - Poprawiłem odzyskiwanie ramki po obrocie, dodałem zapis przyciętej fotografii
+0.221214-3 - Zrezygnowałem z ograniczeń ramki przy krawędziach zdjęcia gdyż źle oddziaływały na ramkę. Przywróciłem sposób z wyświetlaniem okna dialogowego po przekroczeniu krawędzi.
+0.221214-2 - Poprawki drobnych błędów
+0.221214-1 - Zwiększyłem rozmiar ramki po obrocie
+0.221214-0 - Poprawiłem błąd powodujący wyłączenie się skryptu po przycięciu obrazka w dolnych partiach
+0.221213-2 - Dodałem menu wraz z odnośnikiem z licencją (w końcu!). Poprawiłem informacje "O Programie"
+0.221213-1 - Poprawki błędów związanych z literówkami dotyczącymi aspektu ramki
+0.221213-0 - Poprawiłem odświeżanie kontrolki po obrocie - jednak dla obrazków wertykalnych zbyt niskie położenie ramki grozi krachem aplikacji
+0.221212-1 - Poprawiłem przekształcanie ramki po obrocie
+0.221212-0 - Okno zmienia już swoją wielkość po rotacji, lepsze dobór ramki po rotacji obrazu.
+0.221211-5 - Prawidłowo obraca obrazek do wydruku
+0.221211-4 - W celu okiełzania ramki należy operować wartościami w "self.border_properties"
+0.221211-3 - Przycina obrócony obraz, jednak partaczy wydruk
+0.221211-2 - Ramka już nie przyrasta vertykalnie
+0.221211-0 - Próba implementacji obrotu ramki - do poprawki
+0.221210-0 - Przepisanie rozmiaru ramki do słownika. Z sukcesem ! FIXME - zablokować możliwość powiększania ramki po dojściu z jednego z brzegów do konturu. W przeciwnym wypadku kłuci się to z sensownością aplikacji.
+0.220317-0 - Dodałem odczyt plików TIFF, jednak aplikacja źle przycina – szare tło
+0.220315-1 - Należało by aby aplikacja rozróżniała pochodzenie zdjęcia (lustrzanka, kompakt, smartphone)) w celu doboru współczynnika ramki
+0.220314-0 - Drukuje prawidłowo zdjęcia zarówno wertykalne jak i horyzontalne, jednak przy tych ostatnich papier należy również umieścić horyzontalnie w drukarce !
+0.220308-0 - Dalsza korekta ustawień ramki oraz skalowania ramki dla rozmiaru A6
+0.220306-1 - Likwidacja podmenu otwarcia pliku, rozmiar okna dostosowuje się do położenia/rozmiaru zdjęcia.
+0.220306-0 - Korekta ramki dla zdjęć horyzontalnych, korekta dotyczy również skalowania tych zdjęć. Jednak są sytuacje gdy dodawana jest ramka do zdjęć.
+0.220217-0 - Teraz drukuje !
+0.220216-3 - Korekta przy współżędnych tworzenia ramki, potrzebna korekta ramki przy skalowaniu
+0.220216-2 - Małe poprawki w 'Gtk.PaperSize.new.custom'
+0.220216-1 - Próba wydruku na orginalnych wymiarach zaraz po przycięciu, nie wiem czy drukarka ruszy...
+0.220216-0 - Podbicie nieco pikseli w wydruku, przejście z milimetrów na punkty przy wydruku
+0.220214-1 - Przywrócenie poprzednich rozmiarów ramki
+0.220214-0 - Rezygnacja ze stalej 0.075 na rzecz nie odejmowania 'crop_y'
+0.220213-0 - Przypisanie 'self.pixbuf_tmp' wartości None, oraz zapobiegnięcie wyjścia ramki poza obrazek przy scrolowaniu kółkiem myszki.
+0.220212-1 - Kalibracja wydruku
+0.220212-0 - Dodałem ograniczenia dla ramki na krawędziach zdjęcia
+0.220211-0 - Korekcja wspóczynników ramki dla rozmiaru 13x18
+0.220210-0 - Poprawiłem przywracanie zdjęcia w kontrolce dla 13x18
+0.220205-0 - Wstępne ustawienia dla papieru do wydruku – wszystkie formaty.
+0.220204-1 - Przyczółek do korekty wydruku w rozmiarze 10x15
+0.220204-0 - Poprawiłem odświeżenie podglądu po przywróceniu, jednak dla formatu ‘13x18’ odświeżenie bywa problematyczne. Dopisałem opcje drukowania bezpośrednio z ‘prevew’.
+0.220202-5 - Dopisałem ustawienia ramki dla pozostałych rozmiarów, uaktualniłem przypisanie rozmiaru obrazka w kontrolce po przywróceniu.
+0.220202-4 - Zakomentowanie odjęcia stałej 0,075 od 'bw' - powód: wyjście poza obszar przy przycięciu w okolicach prawego skraju zdjęcia.
+0.220202-3 - Optymalizacja kodu → set_ratio_picture_view()
+0.220202-2 - Optymalizacja kodu → self.set_ratio_border_size()
+0.220202-1 - Włącznie stałej 0,075 również do zmiennej ‘bw’ dla zachowania proporcji obrazu.
+0.220202-0 - Ustawienie stałej 0.075 jedynie dla zmiennej ‘bh’, poprawka dla aktualizacji podglądu po przycięciu.
+0.220201-2 - Zmniejszenie progresji ramki w funkcji ‘on_mouse_move_in_drawing_area()
+0.220201-1 - Dopisanie stalych 0.075 do odjęcia ze źródla wzgldem ramki
+0.220201-0 - Poprawiłem przycinanie dolnych partii zdjęcia po przycięciu. Jednak teraz pojawił się narzut po prawej stronie w wyniku.
+0.229128-1 - Cyrkulacja ramki
+0.220129-0 - Dodałem wyłączenie ramki po przycięciu, przywracanie fotografii do oryginału, po nieudanym przycięciu. Jednak skalowanie ramki nie jest idealne, przy pomniejszonym zaznaczeniu bywa że obcina dół.
+0.220128-0 - Napisałem wycinanie brzegów, jednak wycina więcej nie wskazuje ramka ! Potrafi przyciąć nogi.
+0.220125-2 - Nieudana propozycja kadrowania
+0.220125-1 - Napisałem przycinane zdjęcia, źle kadruje zdjęcia
+0.220125-0 - Prawidłowe wyliczenie proporcji ramki dla papieru A6
+0.220124-1 - Próba sformatowania ramki o proporcjach 3/2 dla wszystkich rozmiarów fotografii cyfrowych
+0.220124-0 - Poprawiłem odświeżanie ramki po ponownym wczytaniu zdjęcia, skalowana ramka dla wszystkich rozmiarów, jeszcze nie dokładna
+0.220123-2 - Dopisałem przesuwanie ramki za pomocą myszki
+0.220123-1 - Ustawiłem prawidłowe skalowanie ramki dla rozmiarów 10z15 0raz A4 (13x18 - nie dotyczy)
+0.220123-0 - Ramkę można teraz zmniejszać i zwiększać jednak bez ustawionych min. i max.
+0.220122-3 - Dodałem plik makefile oraz desktop, oraz ikone png
+0.220122-2 - Skrypt prawidłowo wyświetla zdjęcia, zarówno poziomo jak i pionowo. Ramka również jest prawidłowo rysowana - poza zdjęciami w formcie 4:3 !
+0.220122-1 - dodałem kompletną ramkę póki co nieruchomą, dodanie przycisków oraz combobox
+0.220122-0 - Zaangażowanie klasy DrawingArea do wyświetlania i rysowania linii, póki co skrypt rysuje pojedynczą linie
+0.220121-0 - Rozpoczęcie projektu, wyświetlenie okna z możliwością wczytania i wyświetlenia fotografii
diff --git a/configure.gz b/configure.gz
new file mode 100644
index 0000000..50437f0
--- /dev/null
+++ b/configure.gz
Binary files differ
diff --git a/data/IMG_6854.JPG b/data/IMG_6854.JPG
new file mode 100644
index 0000000..d630aed
--- /dev/null
+++ b/data/IMG_6854.JPG
Binary files differ
diff --git a/data/clip.png b/data/clip.png
new file mode 100644
index 0000000..43743fd
--- /dev/null
+++ b/data/clip.png
Binary files differ
diff --git a/data/photocrop.desktop b/data/photocrop.desktop
new file mode 100644
index 0000000..e1ad08e
--- /dev/null
+++ b/data/photocrop.desktop
@@ -0,0 +1,15 @@
+#!/usr/bin/env xdg-open
+
+[Desktop Entry]
+Encoding=UTF-8
+Type=Application
+Categories=Graphics;
+
+Name=Photo Crop
+
+Exec=python3 /usr/bin/photocrop.py
+#Exec=gnome-terminal -e "bash -c 'python3 /usr/bin/photocrop.py;$SHELL'"
+Terminal=false
+Icon=/usr/share/photocrop/clip.png
+
+Name[pl_PL]=Przycinanie Zdjęć
diff --git a/src/photocrop.py b/src/photocrop.py
new file mode 100644
index 0000000..c15e600
--- /dev/null
+++ b/src/photocrop.py
@@ -0,0 +1,1164 @@
+#!/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()
diff --git a/xcf/clip.xcf b/xcf/clip.xcf
new file mode 100644
index 0000000..a63b90e
--- /dev/null
+++ b/xcf/clip.xcf
Binary files differ