diff options
Diffstat (limited to 'kmag')
-rw-r--r-- | kmag/AUTHORS | 9 | ||||
-rw-r--r-- | kmag/COPYING | 280 | ||||
-rw-r--r-- | kmag/ChangeLog | 63 | ||||
-rw-r--r-- | kmag/INSTALL | 184 | ||||
-rw-r--r-- | kmag/Makefile.am | 40 | ||||
-rw-r--r-- | kmag/README | 8 | ||||
-rw-r--r-- | kmag/TODO | 57 | ||||
-rw-r--r-- | kmag/hi16-action-followmouse.png | bin | 0 -> 774 bytes | |||
-rw-r--r-- | kmag/hi16-action-hidemouse.png | bin | 0 -> 308 bytes | |||
-rw-r--r-- | kmag/hi16-action-window.png | bin | 0 -> 469 bytes | |||
-rw-r--r-- | kmag/hi16-app-kmag.png | bin | 0 -> 359 bytes | |||
-rw-r--r-- | kmag/hi32-app-kmag.png | bin | 0 -> 354 bytes | |||
-rw-r--r-- | kmag/kmag.cpp | 958 | ||||
-rw-r--r-- | kmag/kmag.desktop | 76 | ||||
-rw-r--r-- | kmag/kmag.h | 237 | ||||
-rw-r--r-- | kmag/kmag.kdevprj | 230 | ||||
-rw-r--r-- | kmag/kmag.lsm | 14 | ||||
-rw-r--r-- | kmag/kmag.mdk.spec | 108 | ||||
-rw-r--r-- | kmag/kmagselrect.cpp | 385 | ||||
-rw-r--r-- | kmag/kmagselrect.h | 146 | ||||
-rw-r--r-- | kmag/kmagui.rc | 109 | ||||
-rw-r--r-- | kmag/kmagzoomview.cpp | 927 | ||||
-rw-r--r-- | kmag/kmagzoomview.h | 249 | ||||
-rw-r--r-- | kmag/lo16-app-kmag.png | bin | 0 -> 359 bytes | |||
-rw-r--r-- | kmag/lo32-app-kmag.png | bin | 0 -> 354 bytes | |||
-rw-r--r-- | kmag/main.cpp | 81 | ||||
-rw-r--r-- | kmag/version.h | 8 |
27 files changed, 4169 insertions, 0 deletions
diff --git a/kmag/AUTHORS b/kmag/AUTHORS new file mode 100644 index 0000000..c3f200c --- /dev/null +++ b/kmag/AUTHORS @@ -0,0 +1,9 @@ +Rewrite and Current Maintainers : +Sarang Lakare <[email protected]> + +Contributors: +Olaf Schmidt <[email protected]> + +Original Author and Idea : +Michael Forster <[email protected]> + diff --git a/kmag/COPYING b/kmag/COPYING new file mode 100644 index 0000000..ffe677b --- /dev/null +++ b/kmag/COPYING @@ -0,0 +1,280 @@ + 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 Library 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 diff --git a/kmag/ChangeLog b/kmag/ChangeLog new file mode 100644 index 0000000..6171356 --- /dev/null +++ b/kmag/ChangeLog @@ -0,0 +1,63 @@ +//$Id$ + +ver 0.8 +-Mouse cursor is now visible +-Complete reference manual +-Fit-to-window for zoom view +-ported to KDE3 (still works under KDE2) +-Using bitBlt to reduce flicker even more +-Proper centering of zoomed image +-Some qt3 specific additions +-Mouse cursor in printing +-Smooth mouse movements inside zoom vew (very low CPU consumption) +-Zero CPU usage when magnifier window is hidden/minimized +-Using default key shortcuts for various actions +-Checkbox to show/hide mouse cursor +-Shortcut key binding configuration +-Moved to XML GUI +-New "Settings" menu in the toolbar +-Toolbar configuration + +ver 0.7 +-Printing and compiling for KDE 2.x +-Saving files to remote locations +-BUG_FIX:Saved image used to get saved to home directory +-BUG_FIX:Zoom selection window could go below the bottom edge of the screen + +ver 0.6 +-Printing support +-Saving zoomed image to disk +-Saving/Restoring settings to/from config file +-New grab-and-move mode for moving zoom region +-Magnification with mouse movement +-Option to always show selected region +-Ability to change refresh rate +-Copy zoomed image to clipboard +-More cleaner/bare minimal GUI +-Tons of code cleanup + +ver 0.5 +-No more garbage when the grab window is taken outside the screen +-Added a convenient drop down menu to select the zoom factor +-A new refresh button to start/stop window refresh when needed +-Added "tooltips" and "What's this" at lots of places +-New install and install-user scripts for easy installation +-Tons of code cleanup + +ver 0.4 +-No more flickering! + +ver 0.3 +-Fixed a slow-refresh bug.. making KMag 100% usable! +-Made resizing grab window much more easier (esp. for laptops!) +-GUI improvements.. got rid of sliders.. introduced zoom icons +-Centered display of magnified contents +-Now using Kdevelop 1.4b2.. +-Added documentation + +ver 0.2 +-First public release for the KDE2 port and rewrite +-Feature enhancements : Easy moving and resizing of grab-window + +ver 0.1 +-First public release for KDE1 diff --git a/kmag/INSTALL b/kmag/INSTALL new file mode 100644 index 0000000..cde242c --- /dev/null +++ b/kmag/INSTALL @@ -0,0 +1,184 @@ +//$Id$ + +Simple Install +============== + +Login as root and type ./install-root in the directory to install. +-or- +If you do not have root access on the machine, run ./install-user in +the directory. + +If you want to compile the program for KDE3, run ./configure with +options similar to these: + +--prefix=/opt/kde3 --enable-mt --with-qt-dir=/usr/lib/qt3 + +Then run make and make install (as root). + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/kmag/Makefile.am b/kmag/Makefile.am new file mode 100644 index 0000000..29dd1a7 --- /dev/null +++ b/kmag/Makefile.am @@ -0,0 +1,40 @@ +bin_PROGRAMS = kmag + +## INCLUDES were found outside kdevelop specific part + +kmag_SOURCES = kmagzoomview.cpp kmagselrect.cpp kmag.cpp main.cpp +kmag_LDADD = $(LIB_KDEPRINT) + + +EXTRA_DIST = main.cpp version.h kmag.cpp kmag.h kmagui.rc kmag.desktop lo32-app-kmag.png lo16-app-kmag.png kmagselrect.cpp kmagselrect.h hi16-app-kmag.png kmagzoomview.cpp kmagzoomview.h + +uninstall-local: + -rm -f $(DESTDIR)$(kde_appsdir)/Applications/kmag.desktop + +KDE_ICON = kmag + +kmagdir = $(kde_appsdir)/Applications +kmag_DATA = kmag.desktop + +kmagiconsdir = $(kde_datadir)/kmag/icons +kmagicons_ICON = followmouse hidemouse window + +# set the include path for X, qt and KDE +INCLUDES= $(all_includes) + +METASOURCES = AUTO + +KDE_OPTIONS = nofinal + +# the library search path. +kmag_LDFLAGS = $(all_libraries) $(KDE_RPATH) + +rcdir = $(kde_datadir)/kmag +rc_DATA = kmagui.rc + +messages: rc.cpp + LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \ + if test -n "$$LIST"; then \ + $(XGETTEXT) $$LIST -o $(podir)/kmag.pot; \ + fi + diff --git a/kmag/README b/kmag/README new file mode 100644 index 0000000..6ce1143 --- /dev/null +++ b/kmag/README @@ -0,0 +1,8 @@ +//$Id$ + +No README available. A good KDE program should not need a README indeed!! +Read the INSTALL file for installation tips and software requirements. + +In any case, check the web-site + +http://kmag.sourceforge.net diff --git a/kmag/TODO b/kmag/TODO new file mode 100644 index 0000000..f651880 --- /dev/null +++ b/kmag/TODO @@ -0,0 +1,57 @@ +$Id$ + +Planned features: + +Version 1.0: +- Mouse cursor type configuration +- Right mouse menu +- Configuration dialog +- Translations +- New Icon + +* show cursor +* Put the toolbar at the bottom by default +* Documentation +* KDE3 port +* Mouse cursor show/hide +* Toolbar configuration +* Shortcut configuration +* Maximizing use of the zoomed image display area +* zooming control on toolbar +* on/off rectangle update +* block "garbage" effect when rectangle is outside screen +* Add "Pause" button to pause to the current view +* More cleaner/bare minimal GUI +* Grab window moving with the mouse +* Code cleanup +* New grab-and-move mode for moving zoom area +* Add grabbing and saving of the currently selected area or zoomed area. +* Saving of settings across different instances +* Add printing support +* Always show selected region +* Allow setting of refresh rate +* Copying zoomed image to clipboard on "copy" +* Saving zoomed image to a remote file (via KIO slaves) +* Compilable under KDE 2.x + +Bug Fixing for 1.0: +@ When the zoom area is resized, the zoom display shows garbage outside + the zoomed region +- Sometimes the selection window remains on the screen + => Use overlay to draw the selection window. + +* Zoom selection going out of screen at the bottom edge +* Saved zoomed image always gets saved in home directory + + +Version 2.0: +- Show the exact cursor as on screen +- Advanced view to control everything using spin-boxes +- Block mirrror-to-mirror efect when zoom rectangle intersect KMag window +- Different profiles : for vision-impared & regular users. + +Key: + - : todo + * : done + @ : done, but not released yet (download via CVS) + % : in progress diff --git a/kmag/hi16-action-followmouse.png b/kmag/hi16-action-followmouse.png Binary files differnew file mode 100644 index 0000000..b454deb --- /dev/null +++ b/kmag/hi16-action-followmouse.png diff --git a/kmag/hi16-action-hidemouse.png b/kmag/hi16-action-hidemouse.png Binary files differnew file mode 100644 index 0000000..04415de --- /dev/null +++ b/kmag/hi16-action-hidemouse.png diff --git a/kmag/hi16-action-window.png b/kmag/hi16-action-window.png Binary files differnew file mode 100644 index 0000000..ea02070 --- /dev/null +++ b/kmag/hi16-action-window.png diff --git a/kmag/hi16-app-kmag.png b/kmag/hi16-app-kmag.png Binary files differnew file mode 100644 index 0000000..3f8e96e --- /dev/null +++ b/kmag/hi16-app-kmag.png diff --git a/kmag/hi32-app-kmag.png b/kmag/hi32-app-kmag.png Binary files differnew file mode 100644 index 0000000..bffa05d --- /dev/null +++ b/kmag/hi32-app-kmag.png diff --git a/kmag/kmag.cpp b/kmag/kmag.cpp new file mode 100644 index 0000000..f385c13 --- /dev/null +++ b/kmag/kmag.cpp @@ -0,0 +1,958 @@ +/*************************************************************************** + kmag.cpp - description + ------------------- + begin : Mon Feb 12 23:45:41 EST 2001 + copyright : (C) 2001-2003 by Sarang Lakare + email : sarang#users.sourceforge.net + copyright : (C) 2003-2004 by Olaf Schmidt + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +// include files for QT +#include <qdir.h> +#include <qprinter.h> +#include <qpainter.h> +#include <qlayout.h> +#include <qclipboard.h> +#include <qdragobject.h> +#include <qwhatsthis.h> +#include <qtooltip.h> +#include <qpopupmenu.h> + +#include <kdeversion.h> + +// include files for KDE +#if KDE_VERSION > 300 +#include <kapplication.h> +#else +#include <kapp.h> +#endif // KDE 3.x + +#include <kkeydialog.h> +#include <kinputdialog.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <kfiledialog.h> +#include <kmenubar.h> +#include <klocale.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kstdaction.h> +#include <khelpmenu.h> +#include <kimageio.h> +#include <kio/job.h> +#include <kio/netaccess.h> +#include <ktempfile.h> +#include <kpopupmenu.h> +#include <kedittoolbar.h> +#include <kwin.h> + +#if KDE_VERSION < 220 +#include <qprinter.h> +#else +#include <kprinter.h> +#endif + +// application specific includes +#include "kmag.moc" +#include "kmagzoomview.h" +#include "kmagselrect.h" + + +#ifdef KDE_IS_VERSION +#if KDE_IS_VERSION(3,2,90) + #define havesetCheckedState +#endif +#endif + +KmagApp::KmagApp(QWidget* , const char* name) + : KMainWindow(0, name, WStyle_MinMax | WType_TopLevel | WStyle_StaysOnTop | WDestructiveClose | WStyle_ContextHelp), + m_defaultMouseCursorType(2) +{ + config=kapp->config(); + + zoomArrayString << "5:1" << "2:1" << "1:1" << "1:1.5" << "1:2" << "1:3" << "1:4" << "1:5" + << "1:6" << "1:7" << "1:8" << "1:12" << "1:16" << "1:20"; + + // Is there a better way to initialize a vector array? + zoomArray.push_back(0.2); zoomArray.push_back(0.5); zoomArray.push_back(1.0); + zoomArray.push_back(1.5); zoomArray.push_back(2.0); zoomArray.push_back(3.0); + zoomArray.push_back(4.0); zoomArray.push_back(5.0); zoomArray.push_back(6.0); zoomArray.push_back(7.0); + zoomArray.push_back(8.0); zoomArray.push_back(12.0); zoomArray.push_back(16.0); zoomArray.push_back(20.0); + + fpsArrayString << i18n("&Very Low") << i18n("&Low") << i18n("&Medium") << i18n("&High") << i18n("V&ery High"); + + fpsArray.push_back(2); // very low + fpsArray.push_back(6); // low + fpsArray.push_back(10); // medium + fpsArray.push_back(15); // high + fpsArray.push_back(25); // very high + + rotationArrayString << i18n("&No Rotation (0 Degrees)") << i18n("&Left (90 Degrees)") << i18n("&Upside Down (180 Degrees)") << i18n("&Right (270 Degrees)"); + + rotationArray.push_back(0); // no rotation + rotationArray.push_back(90); // left + rotationArray.push_back(180); // upside down + rotationArray.push_back(270); // right + + // call inits to invoke all other construction parts + initView(); + initActions(); + initConnections(); + + // Register all KIO image formats - to be used when saving image. + KImageIO::registerFormats(); + + // read options from config file + readOptions(); +} + +/** + * Default destructor. + */ +KmagApp::~KmagApp() +{ + m_zoomView->showSelRect(false); +} + +void KmagApp::initActions() +{ + fileNewWindow = new KAction(i18n("New &Window"), "window_new", KStdAccel::openNew(), this, + SLOT(slotFileNewWindow()), actionCollection(),"new_window"); + fileNewWindow->setToolTip(i18n("Open a new KMagnifier window")); + + refreshSwitch = new KAction(i18n("&Stop"), "stop", KStdAccel::reload(), this, + SLOT(slotToggleRefresh()), actionCollection(), "start_stop_refresh"); + refreshSwitch->setToolTip(i18n("Click to stop window refresh")); + refreshSwitch->setWhatsThis(i18n("Clicking on this icon will <b>start</b> / <b>stop</b>\ + updating of the display. Stopping the update will zero the processing power\ + required (CPU usage)")); + + m_pSnapshot = new KAction(i18n("&Save Snapshot As..."), "ksnapshot", KStdAccel::save(), this, + SLOT(saveZoomPixmap()), actionCollection(),"snapshot"); + m_pSnapshot->setWhatsThis(i18n("Saves the zoomed view to an image file.")); + m_pSnapshot->setToolTip(i18n("Save image to a file")); + + m_pPrint = KStdAction::print(this, SLOT(slotFilePrint()), actionCollection(), "print"); + m_pPrint->setWhatsThis(i18n("Click on this button to print the current zoomed view.")); + + m_pQuit = KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection(), "quit"); + m_pQuit->setStatusText(i18n("Quits the application")); + m_pQuit->setWhatsThis (i18n("Quits the application")); + + m_pCopy = KStdAction::copy(this, SLOT(copyToClipBoard()), actionCollection(), "copy"); + m_pCopy->setWhatsThis(i18n("Click on this button to copy the current zoomed view to the clipboard which you can paste in other applications.")); + m_pCopy->setToolTip(i18n("Copy zoomed image to clipboard")); + + m_pShowMenu = new KToggleAction(i18n("Show &Menu"), "showmenu", CTRL+Key_M, this, + SLOT(slotShowMenu()), actionCollection(),"show_menu"); + #ifdef havesetCheckedState + m_pShowMenu->setCheckedState(i18n("Hide &Menu")); + #endif + m_pShowMainToolBar = new KToggleAction(i18n("Show Main &Toolbar"), 0, 0, this, + SLOT(slotShowMainToolBar()), actionCollection(),"show_mainToolBar"); + #ifdef havesetCheckedState + m_pShowMainToolBar->setCheckedState(i18n("Hide Main &Toolbar")); + #endif + m_pShowViewToolBar = new KToggleAction(i18n("Show &View Toolbar"), 0, 0, this, + SLOT(slotShowViewToolBar()), actionCollection(),"show_viewToolBar"); + #ifdef havesetCheckedState + m_pShowViewToolBar->setCheckedState(i18n("Hide &View Toolbar")); + #endif + m_pShowSettingsToolBar = new KToggleAction(i18n("Show &Settings Toolbar"), 0, 0, this, + SLOT(slotShowSettingsToolBar()), actionCollection(),"show_settingsToolBar"); + #ifdef havesetCheckedState + m_pShowSettingsToolBar->setCheckedState(i18n("Hide &Settings Toolbar")); + #endif + + m_modeFollowMouse = new KRadioAction(i18n("&Follow Mouse Mode"), "followmouse", Key_F1, this, + SLOT(slotModeFollowMouse()), actionCollection(), "mode_followmouse"); + m_modeFollowMouse->setToolTip(i18n("Magnify mouse area into window")); + m_modeFollowMouse->setWhatsThis(i18n("In this mode the area around the mouse cursor is shown in a normal window.")); + + m_modeSelWin = new KRadioAction(i18n("S&election Window Mode"), "window", Key_F2, this, + SLOT(slotModeSelWin()), actionCollection(), "mode_selectionwindow"); + m_modeSelWin->setToolTip(i18n("Magnify selected area into window")); + m_modeSelWin->setWhatsThis(i18n("In this mode a selection window is opened. The selected area is shown in a normal window.")); + + m_modeEdgeTop = new KRadioAction(i18n("&Top Screen Edge Mode"), 0, 0, this, + SLOT(slotModeEdgeTop()), actionCollection(),"mode_edgetop"); + m_modeEdgeTop->setToolTip(i18n("Magnify mouse area to top screen edge")); + m_modeEdgeTop->setWhatsThis(i18n("In this mode the area around the mouse is magnified to the top screen edge.")); + + m_modeEdgeLeft = new KRadioAction(i18n("&Left Screen Edge Mode"), 0, 0, this, + SLOT(slotModeEdgeLeft()), actionCollection(),"mode_edgeleft"); + m_modeEdgeLeft->setToolTip(i18n("Magnify mouse area to left screen edge")); + m_modeEdgeLeft->setWhatsThis(i18n("In this mode the area around the mouse is magnified to the left screen edge.")); + + m_modeEdgeRight = new KRadioAction(i18n("&Right Screen Edge Mode"), 0, 0, this, + SLOT(slotModeEdgeRight()), actionCollection(),"mode_edgeright"); + m_modeEdgeRight->setToolTip(i18n("Magnify mouse area to right screen edge")); + m_modeEdgeRight->setWhatsThis(i18n("In this mode the area around the mouse is magnified to the right screen edge.")); + + m_modeEdgeBottom = new KRadioAction(i18n("&Bottom Screen Edge Mode"), 0, 0, this, + SLOT(slotModeEdgeBottom()), actionCollection(),"mode_edgebottom"); + m_modeEdgeBottom->setToolTip(i18n("Magnify mouse area to bottom screen edge")); + m_modeEdgeBottom->setWhatsThis(i18n("In this mode the area around the mouse is magnified to the bottom screen edge.")); + + m_hideCursor = new KToggleAction(i18n("Hide Mouse &Cursor"), "hidemouse", Key_F4, this, + SLOT(slotToggleHideCursor()), actionCollection(), "hidecursor"); + #ifdef havesetCheckedState + m_hideCursor->setCheckedState(i18n("Show Mouse &Cursor")); + #endif + m_hideCursor->setToolTip(i18n("Hide the mouse cursor")); + + m_pZoomIn = KStdAction::zoomIn(this, SLOT(zoomIn()), actionCollection(), "zoom_in"); + m_pZoomIn->setWhatsThis(i18n("Click on this button to <b>zoom-in</b> on the selected region.")); + + m_pZoomBox = new KSelectAction(i18n("&Zoom"),0,actionCollection(),"zoom"); + m_pZoomBox->setItems(zoomArrayString); + m_pZoomBox->setWhatsThis(i18n("Select the zoom factor.")); + m_pZoomBox->setToolTip(i18n("Zoom factor")); + + m_pZoomOut = KStdAction::zoomOut(this, SLOT(zoomOut()), actionCollection(), "zoom_out"); + m_pZoomOut->setWhatsThis(i18n("Click on this button to <b>zoom-out</b> on the selected region.")); + + m_pInvert = new KToggleAction(i18n("&Invert Colors"), 0, Key_F6, this, + SLOT(slotToggleInvert()), actionCollection(), "invert"); + + m_pRotationBox = new KSelectAction(i18n("&Rotation"),0,actionCollection(),"rotation"); + m_pRotationBox->setItems(rotationArrayString); + m_pRotationBox->setWhatsThis(i18n("Select the rotation degree.")); + m_pRotationBox->setToolTip(i18n("Rotation degree")); + + // KHelpMenu *newHelpMenu = new KHelpMenu(this, KGlobal::instance()->aboutData()); + + m_keyConf = KStdAction::keyBindings( this, SLOT( slotConfKeys() ), actionCollection(), "key_conf"); + m_toolConf = KStdAction::configureToolbars( this, SLOT( slotEditToolbars() ), + actionCollection(), "toolbar_conf"); + + m_pFPSBox = new KSelectAction(i18n("Re&fresh"),0,actionCollection(),"fps_selector"); + m_pFPSBox->setItems(fpsArrayString); + m_pFPSBox->setWhatsThis(i18n("Select the refresh rate. The higher the rate, the more computing power (CPU) will be needed.")); + m_pFPSBox->setToolTip(i18n("Refresh rate")); + + createGUI(); +} + +void KmagApp::initView() +{ + m_zoomView = new KMagZoomView( this, "ZoomView" ); + m_zoomView->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)7, m_zoomView->sizePolicy().hasHeightForWidth() ) ); + m_zoomView->setFrameShape( QFrame::StyledPanel ); + m_zoomView->setFrameShadow( QFrame::Raised ); + + setCentralWidget(m_zoomView); +} + +/** + * Initialize all connections. + */ +void KmagApp::initConnections() +{ + // change in zoom value -> update the view + connect(this, SIGNAL(updateZoomValue(float)), m_zoomView, SLOT(setZoom(float))); + connect(this, SIGNAL(updateRotationValue(int)), m_zoomView, SLOT(setRotation(int))); + connect(this, SIGNAL(updateFPSValue(float)), m_zoomView, SLOT(setRefreshRate(float))); + + // change in zoom index -> update the selector + connect(this, SIGNAL(updateZoomIndex(int)), m_pZoomBox, SLOT(setCurrentItem(int))); + connect(this, SIGNAL(updateRotationIndex(int)), m_pRotationBox, SLOT(setCurrentItem(int))); + connect(this, SIGNAL(updateFPSIndex(int)), m_pFPSBox, SLOT(setCurrentItem(int))); + + // selector selects a zoom index -> set the zoom index + connect(m_pZoomBox, SIGNAL(activated(int)), this, SLOT(setZoomIndex(int))); + connect(m_pRotationBox, SIGNAL(activated(int)), this, SLOT(setRotationIndex(int))); + connect(m_pFPSBox, SIGNAL(activated(int)), this, SLOT(setFPSIndex(int))); + + connect(m_zoomView, SIGNAL(contextMenu(QPoint)), this, SLOT(contextMenu(QPoint))); +} + +/** + * Save options to config file. + */ +void KmagApp::saveOptions() +{ + config->setGroup("General Options"); + config->writeEntry("Geometry", size()); + config->writeEntry("ZoomIndex", m_zoomIndex); + config->writeEntry("Invertation", m_pInvert->isChecked()); + config->writeEntry("RotationIndex", m_rotationIndex); + config->writeEntry("FPSIndex", m_fpsIndex); + config->writeEntry("SelRect", m_zoomView->getSelRectPos()); + config->writeEntry("ShowMouse", m_zoomView->getShowMouseType()); + + if (m_modeFollowMouse->isChecked()) + config->writeEntry("Mode", "followmouse"); + else if (m_modeSelWin->isChecked()) + config->writeEntry("Mode", "selectionwindow"); + else if (m_modeEdgeTop->isChecked()) + config->writeEntry("Mode", "edgetop"); + else if (m_modeEdgeLeft->isChecked()) + config->writeEntry("Mode", "edgeleft"); + else if (m_modeEdgeRight->isChecked()) + config->writeEntry("Mode", "edgeright"); + else if (m_modeEdgeBottom->isChecked()) + config->writeEntry("Mode", "edgebottom"); + + config->writeEntry ("EdgeSize", edgesize); + + config->writeEntry("ShowMenu", m_pShowMenu->isChecked()); + config->writeEntry("ShowMainToolBar", m_pShowMainToolBar->isChecked()); + config->writeEntry("ShowViewToolBar", m_pShowViewToolBar->isChecked()); + config->writeEntry("ShowSettingsToolBar", m_pShowSettingsToolBar->isChecked()); + + toolBar("mainToolBar")->saveSettings(config,"Main ToolBar"); + toolBar("viewToolBar")->saveSettings(config,"View ToolBar"); + toolBar("settingsToolBar")->saveSettings(config,"Settings ToolBar"); +} + + +/** + * Read settings from config file. + */ +void KmagApp::readOptions() +{ + QColor blue (0,0,128); + QColor yellow (255,255,0); + QColor white (255,255,255); + + config->setGroup ("WM"); + setTitleColors ( + config->readColorEntry("inactiveBackground", &blue), + config->readColorEntry("inactiveForeground", &white), + config->readColorEntry("inactiveTitleBtnBg", &yellow)); + + config->setGroup("General Options"); + + QSize defSize(460,390); + QSize size=config->readSizeEntry("Geometry", &defSize); + if(!size.isEmpty()) + { + resize(size); + } + + // set zoom - defaults to 2x + unsigned int zoomIndex = config->readUnsignedNumEntry("ZoomIndex", 4); + setZoomIndex(zoomIndex); + emit updateZoomIndex(m_zoomIndex); + + m_pInvert->setChecked (config->readBoolEntry("Invertation", false)); + slotToggleInvert(); + + unsigned int rotationIndex = config->readUnsignedNumEntry("RotationIndex", 0); + setRotationIndex(rotationIndex); + emit updateRotationIndex(m_rotationIndex); + + unsigned int fpsIndex = config->readUnsignedNumEntry("FPSIndex", 2); + setFPSIndex(fpsIndex); + emit updateFPSIndex(m_fpsIndex); + + QRect defaultRect(0,0,211,164); + m_zoomView->setSelRectPos(config->readRectEntry("SelRect", &defaultRect)); + + m_mouseCursorType = config->readUnsignedNumEntry("ShowMouse", m_defaultMouseCursorType); + m_zoomView->showMouse(m_mouseCursorType); + if(m_mouseCursorType) + m_hideCursor->setChecked(false); + else + m_hideCursor->setChecked(true); + + if(config->hasGroup("Settings ToolBar")) + toolBar("settingsToolBar")->applySettings(config,"Settings ToolBar"); + + if(config->hasGroup("Main ToolBar")) + toolBar("mainToolBar")->applySettings(config,"Main ToolBar"); + + if(config->hasGroup("View ToolBar")) + toolBar("viewToolBar")->applySettings(config,"View ToolBar"); + + m_pShowMenu->setChecked(config->readBoolEntry("ShowMenu", true)); + slotShowMenu(); + + m_pShowMainToolBar->setChecked(config->readBoolEntry("ShowMainToolBar", false)); + slotShowMainToolBar(); + + m_pShowViewToolBar->setChecked(config->readBoolEntry("ShowViewToolBar", true)); + slotShowViewToolBar(); + + m_pShowSettingsToolBar->setChecked(config->readBoolEntry("ShowSettingsToolBar", true)); + slotShowSettingsToolBar(); + + config->setGroup("General Options"); + + edgesize = config->readNumEntry("EdgeSize", 0); + QString mode = config->readEntry("Mode", "followmouse"); + if (mode == "selectionwindow") + slotModeSelWin(); + else if (mode == "edgetop") + setEdgeMode (m_modeEdgeTop); + else if (mode == "edgeleft") + setEdgeMode (m_modeEdgeLeft); + else if (mode == "edgeright") + setEdgeMode (m_modeEdgeRight); + else if (mode == "edgebottom") + setEdgeMode (m_modeEdgeBottom); + else + slotModeFollowMouse(); +} + +bool KmagApp::queryClose() +{ + return (true); +} + +bool KmagApp::queryExit() +{ + saveOptions(); + return true; +} + + +///////////////////////////////////////////////////////////////////// +// SLOT IMPLEMENTATION +///////////////////////////////////////////////////////////////////// + +/** + * Shows/hides the mouse cursor + */ +void KmagApp::showMouseCursor(bool show) +{ + if(show) { + if(m_mouseCursorType == 0) + m_mouseCursorType = m_defaultMouseCursorType; + m_zoomView->showMouse(m_mouseCursorType); + } else { + m_zoomView->showMouse(0); + } +} + +/** + * Zoom in. + */ +void KmagApp::zoomIn() +{ + // set the new index .. checking will done inside setZoom + setZoomIndex(m_zoomIndex+1); + // signal change in zoom index + emit updateZoomIndex((int)m_zoomIndex); +} + +/** + * Zoom out. + */ +void KmagApp::zoomOut() +{ + // set the new index .. checking will done inside setZoom + setZoomIndex(m_zoomIndex-1); + // signal change in zoom index + emit updateZoomIndex((int)m_zoomIndex); +} +/** + * Sets the zoom index to index + */ +void KmagApp::setZoomIndex(int index) +{ + if(index < 0 || index >= (int)zoomArray.size()) { + // the index is invalid + kdWarning() << "Invalid index!" << endl; + return; + } else if((int)m_zoomIndex == index) { + // do nothing! + return; + } else { + m_zoomIndex = index; + } + + if(m_zoomIndex == 0) { + // meaning that no more zooming-out is possible + // -> disable zoom-out icon + m_pZoomOut->setEnabled(false); + } else { // enable the icon + m_pZoomOut->setEnabled(true); + } + + if(m_zoomIndex == zoomArray.size()-1) { + // meaning that no more zooming-in is possible + // -> disable zoom-in icon + m_pZoomIn->setEnabled(false); + } else { // enable the icon + m_pZoomIn->setEnabled(true); + } + + // signal change in zoom value + emit updateZoomValue(zoomArray[m_zoomIndex]); +} + +/** + * Shows/hides the mouse cursor + */ +void KmagApp::slotToggleInvert () +{ + m_zoomView->setInvertation (m_pInvert->isChecked()); +} + +/** + * Sets the rotation index to index + */ +void KmagApp::setRotationIndex(int index) +{ + if(index < 0 || index >= (int)rotationArray.size()) { + // the index is invalid + kdWarning() << "Invalid index!" << endl; + return; + } else if((int)m_rotationIndex == index) { + // do nothing! + return; + } else { + m_rotationIndex = index; + } + + // signal change in zoom value + emit updateRotationValue(rotationArray[m_rotationIndex]); +} + +/** + * Sets the fps index to index + */ +void KmagApp::setFPSIndex(int index) +{ + if(index < 0 || index >= (int)fpsArray.size()) { + // the index is invalid + kdWarning() << "Invalid index!" << endl; + return; + } else if((int)m_fpsIndex == index) { + // do nothing! + return; + } else { + m_fpsIndex = index; + } + + // signal change in fps value + emit updateFPSValue(fpsArray[m_fpsIndex]); +} + + +/** + * Save the zoomed image + */ +void KmagApp::saveZoomPixmap() +{ + bool toggled(false); + + // stop refresh temporarily + if (m_zoomView->getRefreshStatus()) { + slotToggleRefresh(); + toggled = true; + } + + KURL url = KFileDialog::getSaveURL(QString::null, + KImageIO::pattern(KImageIO::Writing), + 0,i18n("Save Snapshot As")); + + if(!url.filename().isEmpty()) { + if(!url.isLocalFile()) { + // create a temp file.. save image to it.. copy over the n/w and then delete the temp file. + KTempFile tempFile; + if(!m_zoomView->getPixmap().save(tempFile.name(), KImageIO::type(url.fileName()).latin1())) { + KMessageBox::error(0, i18n("Unable to save temporary file (before uploading to the network file you specified)."), + i18n("Error Writing File")); + } else { + if(!KIO::NetAccess::upload(tempFile.name(), url, this)) { + KMessageBox::error(0, i18n("Unable to upload file over the network."), + i18n("Error Writing File")); + } else { + KMessageBox::information(0, i18n("Current zoomed image saved to\n%1").arg(url.prettyURL()), + i18n("Information"), "save_confirm"); + } + } + // remove the temporary file + tempFile.unlink(); + + } else { + if(!m_zoomView->getPixmap().save(url.path(), KImageIO::type(url.fileName()).latin1())) { + KMessageBox::error(0, i18n("Unable to save file. Please check if you have permission to write to the directory."), + i18n("Error Writing File")); + } else { + KMessageBox::information(0, i18n("Current zoomed image saved to\n%1").arg(url.prettyURL()), + i18n("Information"), "save_confirm"); + } + } + } + if(toggled) { + slotToggleRefresh(); + } +} + + +void KmagApp::slotToggleRefresh() +{ + m_zoomView->toggleRefresh(); + if(m_zoomView->getRefreshStatus()) { + refreshSwitch->setIcon("stop.png"); + refreshSwitch->setText(i18n("Stop")); + refreshSwitch->setToolTip(i18n("Click to stop window update")); + } else { + refreshSwitch->setIcon("reload.png"); + refreshSwitch->setText(i18n("Start")); + refreshSwitch->setToolTip(i18n("Click to start window update")); + } +} + + +void KmagApp::slotModeSelWin() +{ + unsetEdgeMode(m_modeSelWin); + + m_zoomView->fitToWindow(); + m_zoomView->setFitToWindow (false); + m_zoomView->followMouse(false); + m_zoomView->showSelRect(true); +} + + +void KmagApp::slotModeFollowMouse() +{ + unsetEdgeMode(m_modeFollowMouse); + + m_zoomView->setFitToWindow (true); + m_zoomView->followMouse(true); + m_zoomView->showSelRect(false); +} + + +void KmagApp::slotModeEdgeTop() +{ + // ask for edgesize + int newedgesize; bool ok; + newedgesize = KInputDialog::getInteger (i18n ("Magnify to Screen Edge - Select Size"), + i18n ("Size:"), edgesize > 0 ? edgesize : 300, 200, + QApplication::desktop()->screenGeometry( this ).height()/2, + 25, 10, &ok, 0, "getedgesize"); + + if (ok) { + edgesize = newedgesize; + setEdgeMode(m_modeEdgeTop); + } +} + + +void KmagApp::slotModeEdgeLeft() +{ + // ask for edgesize + int newedgesize; bool ok; + newedgesize = KInputDialog::getInteger (i18n ("Magnify to Left Screen Edge - Select Size"), + i18n ("Size:"), edgesize > 0 ? edgesize : 300, 200, + QApplication::desktop()->screenGeometry( this ).width()/2, + 25, 10, &ok, 0, "getedgesize"); + + if (ok) { + edgesize = newedgesize; + setEdgeMode(m_modeEdgeLeft); + } +} + + +void KmagApp::slotModeEdgeRight() +{ + // ask for edgesize + int newedgesize; bool ok; + newedgesize = KInputDialog::getInteger (i18n ("Magnify to Right Screen Edge - Select Size"), + i18n ("Size:"), edgesize > 0 ? edgesize : 300, 200, + QApplication::desktop()->screenGeometry( this ).width()/2, + 25, 10, &ok, 0, "getedgesize"); + + if (ok) { + edgesize = newedgesize; + setEdgeMode(m_modeEdgeRight); + } +} + + +void KmagApp::slotModeEdgeBottom() +{ + // ask for edgesize + int newedgesize; bool ok; + newedgesize = KInputDialog::getInteger (i18n ("Magnify to Bottom Screen Edge - Select Size"), + i18n ("Size:"), edgesize > 0 ? edgesize : 300, 200, + QApplication::desktop()->screenGeometry( this ).height()/2, + 25, 10, &ok, 0, "getedgesize"); + + if (ok) { + edgesize = newedgesize; + setEdgeMode(m_modeEdgeBottom); + } +} + + +void KmagApp::setEdgeMode (KToggleAction *mode) +{ + if (m_modeEdgeLeft || mode == m_modeEdgeRight) { + if (edgesize < 200 || edgesize > QApplication::desktop()->screenGeometry( this ).width()/2) + edgesize = QApplication::desktop()->screenGeometry( this ).width()/4; + } else { + if (edgesize < 200 || edgesize > QApplication::desktop()->screenGeometry( this ).height()/2) + edgesize = QApplication::desktop()->screenGeometry( this ).height()/4; + } + + m_modeFollowMouse->setChecked(false); + m_modeSelWin->setChecked(false); + m_modeEdgeTop->setChecked(false); + m_modeEdgeLeft->setChecked(false); + m_modeEdgeRight->setChecked(false); + m_modeEdgeBottom->setChecked(false); + mode->setChecked (true); + + m_zoomView->setFitToWindow (true); + m_zoomView->followMouse(true); + m_zoomView->showSelRect(false); + + m_zoomView->reparent (0, QPoint(), false); + KWin::setType(m_zoomView->winId(), NET::Dock); + KWin::setState(m_zoomView->winId(), NET::Sticky | NET::KeepBelow | NET::SkipTaskbar | NET::SkipPager); + KWin::setOnAllDesktops(m_zoomView->winId(), true); + + m_pShowMenu->setEnabled (false); + m_pShowMainToolBar->setEnabled (false); + m_pShowViewToolBar->setEnabled (false); + m_pShowSettingsToolBar->setEnabled (false); + + hide(); + + if (mode == m_modeEdgeTop) { + QRect r = QApplication::desktop()->screenGeometry( this ); + r.setBottom( r.top() + edgesize ); + m_zoomView->setGeometry ( r ); + KWin::setExtendedStrut (m_zoomView->winId(), 0, 0, 0, 0, 0, 0, + edgesize, r.left(), r.right(), 0, 0, 0); + } else if (mode == m_modeEdgeLeft) { + QRect r = QApplication::desktop()->screenGeometry( this ); + r.setRight( r.left() + edgesize ); + m_zoomView->setGeometry ( r ); + KWin::setExtendedStrut (m_zoomView->winId(), + edgesize, r.top(), r.bottom(), + 0, 0, 0, 0, 0, 0, 0, 0, 0); + } else if (mode == m_modeEdgeRight) { + QRect r = QApplication::desktop()->screenGeometry( this ); + r.setLeft( r.right() - edgesize ); + m_zoomView->setGeometry ( r ); + KWin::setExtendedStrut (m_zoomView->winId(), 0, 0, 0, + edgesize, r.top(), r.bottom(), + 0, 0, 0, 0, 0, 0); + } else { + QRect r = QApplication::desktop()->screenGeometry( this ); + r.setTop( r.bottom() - edgesize ); + m_zoomView->setGeometry ( r ); + KWin::setExtendedStrut (m_zoomView->winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, + edgesize, r.left(), r.right()); + } + m_zoomView->show(); +} + + +void KmagApp::unsetEdgeMode (KToggleAction *mode) +{ + edgesize = 0; + + m_modeFollowMouse->setChecked(false); + m_modeSelWin->setChecked(false); + m_modeEdgeTop->setChecked(false); + m_modeEdgeLeft->setChecked(false); + m_modeEdgeRight->setChecked(false); + m_modeEdgeBottom->setChecked(false); + mode->setChecked (true); + + m_zoomView->reparent (this, QPoint(), true); + setCentralWidget(m_zoomView); + KWin::setExtendedStrut (winId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + m_pShowMenu->setEnabled (true); + m_pShowMainToolBar->setEnabled (true); + m_pShowViewToolBar->setEnabled (true); + m_pShowSettingsToolBar->setEnabled (true); + + show(); +} + + +void KmagApp::slotToggleHideCursor() +{ + showMouseCursor(!m_hideCursor->isChecked()); +} + + +void KmagApp::slotFileNewWindow() +{ + KmagApp *new_window= new KmagApp(); + new_window->show(); +} + + +void KmagApp::slotFilePrint() +{ +#ifndef QT_NO_PRINTER + + bool toggled(false); + +#if KDE_VERSION < 220 + QPrinter printer; +#else + KPrinter printer; +#endif + + // stop refresh temporarily + if (m_zoomView->getRefreshStatus()) { + slotToggleRefresh(); + toggled = true; + } + + const QPixmap pixmap(m_zoomView->getPixmap()); + +#if KDE_VERSION >= 220 + // use some AI to get the best orientation + if(pixmap.width() > pixmap.height()) { + printer.setOrientation(KPrinter::Landscape); + } else { + printer.setOrientation(KPrinter::Portrait); + } +#endif + + if (printer.setup(this)) { + QPainter paint; + + if(!paint.begin(&printer)) + return; + // draw the pixmap + paint.drawPixmap(0, 0, pixmap); + // end the painting + paint.end(); + } + + if(toggled) { + slotToggleRefresh(); + } +#endif // QT_NO_PRINTER +} + +void KmagApp::slotFileQuit() +{ + saveOptions(); + // close the first window, the list makes the next one the first again. + // This ensures that queryClose() is called on each window to ask for closing + KMainWindow* w; + if (memberList) + { + for(w=memberList->first(); w!=0; w=memberList->first()) + { + // only close the window if the closeEvent is accepted. If the user presses Cancel on the saveModified() dialog, + // the window and the application stay open. + if(!w->close()) + break; + memberList->removeRef(w); + } + } +} + +void KmagApp::copyToClipBoard() +{ + QClipboard *cb=KApplication::clipboard(); + cb->setPixmap(m_zoomView->getPixmap()); +} + +void KmagApp::slotShowMenu() +{ + /////////////////////////////////////////////////////////////////// + // turn Menu on or off + if(!m_pShowMenu->isChecked()) + { + menuBar()->hide(); + } + else + { + menuBar()->show(); + } + + +} + +void KmagApp::slotShowMainToolBar() +{ + /////////////////////////////////////////////////////////////////// + // turn mainToolbar on or off + if(!m_pShowMainToolBar->isChecked()) + { + toolBar("mainToolBar")->hide(); + } + else + { + toolBar("mainToolBar")->show(); + } +} + +void KmagApp::slotShowViewToolBar() +{ + /////////////////////////////////////////////////////////////////// + // turn viewToolbar on or off + if(!m_pShowViewToolBar->isChecked()) + { + toolBar("viewToolBar")->hide(); + } + else + { + toolBar("viewToolBar")->show(); + } +} + +void KmagApp::slotShowSettingsToolBar() +{ + /////////////////////////////////////////////////////////////////// + // turn viewToolbar on or off + if(!m_pShowSettingsToolBar->isChecked() || edgesize > 0) + { + toolBar("settingsToolBar")->hide(); + } + else + { + toolBar("settingsToolBar")->show(); + } +} + +void KmagApp::slotConfKeys() +{ + KKeyDialog::configure( actionCollection() ); +} + +void KmagApp::slotEditToolbars() +{ + saveMainWindowSettings( KGlobal::config(), "MainWindow" ); + KEditToolbar dlg( actionCollection() ); + connect( &dlg, SIGNAL( newToolbarConfig() ), this, SLOT( slotNewToolbarConfig() ) ); + if ( dlg.exec() ) + createGUI(); +} + + +void KmagApp::contextMenu (QPoint pos) +{ + // show popup + KXMLGUIFactory *factory = this->factory(); + QPopupMenu *popup = (QPopupMenu *)factory->container("mainPopUp",this); + if (popup != 0) + popup->popup(pos, 0); +} + + +void KmagApp::slotNewToolbarConfig() +{ + applyMainWindowSettings( KGlobal::config(), "MainWindow" ); + createGUI(); +} diff --git a/kmag/kmag.desktop b/kmag/kmag.desktop new file mode 100644 index 0000000..703101f --- /dev/null +++ b/kmag/kmag.desktop @@ -0,0 +1,76 @@ +# KDE Config File +[Desktop Entry] +Type=Application +Exec=kmag -caption "%c" %i %m +Icon=kmag +DocPath=kmag/index.html +Comment= +Comment[ro]=Un utilitar de mărit zone ale ecranului +Terminal=false +Name=KMag +Name[el]=K μεγεθυντικός φακός +Name[ne]=केडीई म्याग +Name[sk]=KLupa +Name[sv]=Kmag +Name[tg]=KMag +Name[th]=แว่นขยาย - K +Name[tr]=Kmag +Name[vi]=Kính lúp K +Name[zh_TW]=K-放大鏡 +GenericName=Screen Magnifier +GenericName[ar]=مكبَر الشاشة +GenericName[bg]=Лупа за екрана +GenericName[bs]=Povećalo za ekran +GenericName[ca]=Lupa de la pantalla +GenericName[cs]=Lupa obrazovky +GenericName[cy]=KChwyddwr +GenericName[da]=Skærmforstørrer +GenericName[de]=Bildschirmlupe +GenericName[el]=Μεγεθυντικός φακός οθόνης +GenericName[eo]=Ekrano-pligrandigilo +GenericName[es]=Aumenta la pantalla +GenericName[et]=Ekraani suurendaja +GenericName[eu]=Pantailaren lupa +GenericName[fa]=درشتنمای پرده +GenericName[fi]=Suurennuslasi +GenericName[fr]=Loupe d'écran +GenericName[ga]=Formhéadaitheoir Scáileáin +GenericName[gl]=Ampliación da pantalla +GenericName[he]=זכוכית מגדלת +GenericName[hi]=स्क्रीन का आकार बढ़ाने वाला +GenericName[hu]=Nagyító +GenericName[is]=Skjástækkunargler +GenericName[it]=Lente di ingrandimento per lo schermo +GenericName[ja]=画面拡大鏡 +GenericName[ka]=ეკრანის გამდიდებელი +GenericName[km]= កម្មវិធីពង្រីកអេក្រង់ +GenericName[lt]=Ekrano didintojas +GenericName[mk]=Зголемувач за екранот +GenericName[ms]=Pembesar Skrin +GenericName[nb]=Skjermforstørrer +GenericName[nds]=Schirmluup +GenericName[ne]=पर्दा अभिवर्धक +GenericName[nl]=Schermvergroter +GenericName[nn]=Skjermforstørrar +GenericName[pa]=ਪਰਦਾ ਵੱਡਦਰਸ਼ੀ +GenericName[pl]=Powiększanie fragmentów ekranu +GenericName[pt]=Lupa +GenericName[pt_BR]=Amplificador de Tela +GenericName[ro]=Lupă de ecran +GenericName[ru]=Экранная лупа +GenericName[sk]=Lupa obrazovky +GenericName[sl]=Povečevalnik zaslona +GenericName[sr]=Екрански увеличавач +GenericName[sr@Latn]=Ekranski uveličavač +GenericName[sv]=Förstoringsglas +GenericName[ta]=திரை பெரிதாக்கி +GenericName[tg]=Калон кардани экран +GenericName[th]=แว่นขยายหน้าจอ +GenericName[tr]=Ekran Büyüteci +GenericName[uk]=Збільшувач екрана +GenericName[uz]=Ekranni kattalashtiruvchi +GenericName[uz@cyrillic]=Экранни катталаштирувчи +GenericName[vi]=Kính lúp Màn hình +GenericName[zh_CN]=屏幕放大镜 +GenericName[zh_TW]=螢幕放大鏡 +Categories=Qt;KDE;Utility;Accessibility; diff --git a/kmag/kmag.h b/kmag/kmag.h new file mode 100644 index 0000000..bfd2e31 --- /dev/null +++ b/kmag/kmag.h @@ -0,0 +1,237 @@ +/*************************************************************************** + kmag.h - description + ------------------- + begin : Mon Feb 12 23:45:41 EST 2001 + copyright : (C) 2001 by Sarang Lakare + email : [email protected] + copyright : (C) 2003-2004 by Olaf Schmidt + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + + +#ifndef KMAG_H +#define KMAG_H + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "kmagzoomview.h" + +#include <vector> +// include files for Qt +#include <qstringlist.h> + +// include files for KDE +#include <kapplication.h> +#include <kmainwindow.h> +#include <kdockwidget.h> +#include <kaction.h> +#include <kaccel.h> +#include <knuminput.h> + +/** + * The base class for Kmag application windows. It sets up the main + * window and reads the config file as well as providing a menubar, toolbar + * and statusbar. An instance of KmagView creates your center view, which is connected + * to the window's Doc object. + * KmagApp reimplements the methods that KMainWindow provides for main window handling and supports + * full session management as well as using KActions. + * @see KMainWindow + * @see KApplication + * @see KConfig + * + * @author Source Framework Automatically Generated by KDevelop, (c) The KDevelop Team. + * @version KDevelop version 1.2 code generation + */ +class KmagApp : public KMainWindow +{ + Q_OBJECT + + public: + /** + * Construtor of KmagApp, calls all init functions to create the application. + */ + KmagApp(QWidget* parent=0, const char* name=0); + + /// Default destructor + ~KmagApp(); + + + + protected: + /** save general Options like all bar positions and status as well as the geometry and the recent file list to the configuration + * file + */ + void saveOptions(); + /** read general Options again and initialize all variables like the recent file list + */ + void readOptions(); + /** initializes the KActions of the application */ + void initActions(); + + /** creates the centerwidget of the KTMainWindow instance and sets it as the view + */ + void initView(); + + /// Initialize all connections + void initConnections(); + + virtual bool queryClose(); + + /** queryExit is called by KTMainWindow when the last window of the application is going to be closed during the closeEvent(). + * Against the default implementation that just returns true, this calls saveOptions() to save the settings of the last window's + * properties. + * @see KTMainWindow#queryExit + * @see KTMainWindow#closeEvent + */ + virtual bool queryExit(); + + public slots: + /** open a new application window by creating a new instance of KmagApp */ + void slotFileNewWindow(); + + /** print the actual file */ + void slotFilePrint(); + + void slotFileQuit(); + + /** put the marked text/object into the clipboard + */ + void copyToClipBoard(); + + /// Toggle the refreshing of the window + void slotToggleRefresh(); + + void slotModeFollowMouse(); + void slotModeSelWin(); + void slotModeEdgeTop(); + void slotModeEdgeLeft(); + void slotModeEdgeRight(); + void slotModeEdgeBottom(); + + /// Zooms in + void zoomIn(); + + /// Zooms out + void zoomOut(); + + /// Save the zoomed image + void saveZoomPixmap(); + + /// Sets the zoom index to index + void setZoomIndex(int index); + + /// Sets the invertation mode + void slotToggleInvert(); + + /// Sets the rotation index to index + void setRotationIndex(int index); + + /// Sets the fps index to index + void setFPSIndex(int index); + + /// Shows/hides the mouse cursor + void showMouseCursor(bool show); + + void slotShowMenu(); + void slotShowMainToolBar(); + void slotShowViewToolBar(); + void slotShowSettingsToolBar(); + + void slotToggleHideCursor(); + + /// Opens shortcut key configuration dialogue + void slotConfKeys(); + + /// Called when toolbar config is updated + void slotNewToolbarConfig(); + + /// Called when "configure toolbar" is clicked + void slotEditToolbars(); + + void contextMenu(QPoint pos); + + signals: + /// This signal is raised whenever the index into the zoom array is changed + void updateZoomIndex(int); + + /// This signal is raised whenever the zoom value changes + void updateZoomValue(float); + + /// This signal is raised whenever the index into the rotation array is changed + void updateRotationIndex(int); + + /// This signal is raised whenever the rotation value changes + void updateRotationValue(int); + + /// This signal is raised whenever the index into the fps array is changed + void updateFPSIndex(int); + + /// This signal is raised whenever the fps value changes + void updateFPSValue(float); + + private: + + void setEdgeMode (KToggleAction *mode); + void unsetEdgeMode (KToggleAction *mode); + + int edgesize; + + /// the configuration object of the application + KConfig *config; + + // KAction pointers to enable/disable actions + KAction *fileNewWindow, *m_pSnapshot, *m_pCopy, *m_keyConf, *m_toolConf; + KAction *m_pPrint; + KAction *m_pZoomIn; + KAction *m_pZoomOut; + KAction *m_pQuit; + KAction *refreshSwitch; + KToggleAction *m_pInvert, *m_pShowMenu, *m_pShowMainToolBar, *m_pShowViewToolBar, *m_pShowSettingsToolBar; + KSelectAction *m_pZoomBox, *m_pRotationBox, *m_pFPSBox; + + /// zoom slider + KIntNumInput *m_zoomSlider; + + /// Current index into the zoomArray + unsigned int m_zoomIndex; + + /// Current index into the rotationArray + unsigned int m_rotationIndex; + + /// Current index into the fpsArray + unsigned int m_fpsIndex; + + QStringList zoomArrayString; + std::vector<float> zoomArray; + + QStringList rotationArrayString; + std::vector<int> rotationArray; + + QStringList fpsArrayString; + std::vector<float> fpsArray; + + KMagZoomView* m_zoomView; + KToggleAction *m_hideCursor; + KRadioAction *m_modeFollowMouse, *m_modeSelWin; + KRadioAction *m_modeEdgeTop, *m_modeEdgeLeft, *m_modeEdgeRight, *m_modeEdgeBottom; + + /// Stores the non-zero cursor type to be used + unsigned int m_mouseCursorType; + + unsigned int m_defaultMouseCursorType; +}; + + +#endif // KMAG_H diff --git a/kmag/kmag.kdevprj b/kmag/kmag.kdevprj new file mode 100644 index 0000000..63d167f --- /dev/null +++ b/kmag/kmag.kdevprj @@ -0,0 +1,230 @@ +[AUTHORS] +dist=true +install=true +install_location=/usr/share/doc/kmag +type=DATA + +[COPYING] +dist=true +install=true +install_location=/usr/share/doc/kmag +type=DATA + +[ChangeLog] +dist=true +install=true +install_location=/usr/share/doc/kmag +type=DATA + +[Config for BinMakefileAm] +addcxxflags= +bin_program=kmag +cflags= +cppflags= +cxxflags=\s-O3 +ldadd=-lkdeprint $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_QT) +ldflags=\s \s + +[General] +AMChanged=false +author=Sarang Lakare +configure_args=--prefix=/usr\s +kdevprj_version=1.3 +lfv_open_groups=GNU,Headers,Others,Sources,User Interface +make_options=\s-j1 +makefiles=Makefile.am,kmag/Makefile.am,doc/Makefile.am,doc/en/Makefile.am,po/Makefile.am,doc/en/images/Makefile.am +modifyMakefiles=true +project_name=Kmag +project_type=normal_kde2 +sgml_file= +short_info= +sub_dir=kmag/ +version=0.8 +version_control=CVS +workspace=1 + +[INSTALL] +dist=true +install=false +install_location=/usr/share/doc/kmag +type=DATA + +[KPP] +kpp_appgrp=Multimedia +kpp_bldroot=/usr/ +kpp_icon=0 +kpp_license=5 +kpp_summary=Magnifies a part of the screen! +kpp_url=http://kmag.sourceforge.net +kpp_version=0.6 + +[LFV Groups] +GNU=AUTHORS,COPYING,ChangeLog,INSTALL,README,TODO,NEWS +Headers=*.h,*.hh,*.hxx,*.hpp,*.H +Others=* +Sources=*.cpp,*.c,*.cc,*.C,*.cxx,*.ec,*.ecpp,*.lxx,*.l++,*.ll,*.l +Translations=*.po +User Interface=*.kdevdlg,*.ui,*.rc +groups=Headers,Sources,User Interface,Translations,GNU,Others + +[Makefile.am] +files=kmag.kdevprj,AUTHORS,COPYING,ChangeLog,INSTALL,README,TODO,kmag.lsm,kmag.spec,install-user,install-root +sub_dirs=kmag,po,doc +type=normal + +[README] +dist=true +install=false +install_location=/usr/share/doc/kmag +type=DATA + +[TODO] +dist=true +install=false +install_location= +type=DATA + +[Workspace_1] +browser_file= +cpp_file= +header_file= +openfiles= +show_outputview=true +show_treeview=true + +[doc/Makefile.am] +sub_dirs=en +type=normal + +[doc/en/Makefile.am] +files=doc/en/index.docbook +sub_dirs=images +type=normal + +[doc/en/images/Makefile.am] +files=doc/en/images/screenshot.png +sub_dirs= +type=normal + +[doc/en/images/screenshot.png] +dist=true +install=true +install_location=$$(kde_htmldir)/en/kmag/images/screenshot.png +type=DATA + +[doc/en/index.docbook] +dist=true +install=true +install_location=$$(kde_htmldir)/en/kmag/index.docbook +type=DATA + +[install-root] +dist=true +install=false +install_location= +type=DATA + +[install-user] +dist=true +install=false +install_location= +type=DATA + +[kmag.kdevprj] +dist=true +install=false +install_location= +type=DATA + +[kmag.lsm] +dist=true +install=false +install_location= +type=DATA + +[kmag.spec] +dist=true +install=false +install_location= +type=DATA + +[kmag/Makefile.am] +files=kmag/main.cpp,kmag/kmag.cpp,kmag/kmag.h,kmag/kmagui.rc,kmag/kmag.desktop,kmag/lo32-app-kmag.png,kmag/lo16-app-kmag.png,kmag/kmagselrect.cpp,kmag/kmagselrect.h,kmag/hi16-app-kmag.png,kmag/kmagzoomview.cpp,kmag/kmagzoomview.h +type=prog_main + +[kmag/hi16-app-kmag.png] +dist=true +install=true +install_location=$$(kde_icondir)/hicolor/16x16/apps/kmag.png +type=DATA + +[kmag/kmag.cpp] +dist=true +install=false +install_location= +type=SOURCE + +[kmag/kmag.desktop] +dist=true +install=true +install_location=$$(kde_appsdir)/Applications/Accessibility/kmag.desktop +type=DATA + +[kmag/kmag.h] +dist=true +install=false +install_location= +type=HEADER + +[kmag/kmagselrect.cpp] +dist=true +install=false +install_location= +type=SOURCE + +[kmag/kmagselrect.h] +dist=true +install=false +install_location= +type=HEADER + +[kmag/kmagui.rc] +dist=true +install=false +install_location= +type=DATA + +[kmag/kmagzoomview.cpp] +dist=true +install=false +install_location= +type=SOURCE + +[kmag/kmagzoomview.h] +dist=true +install=false +install_location= +type=HEADER + +[kmag/lo16-app-kmag.png] +dist=true +install=true +install_location=$$(kde_icondir)/locolor/16x16/apps/kmag.png +type=DATA + +[kmag/lo32-app-kmag.png] +dist=true +install=true +install_location=$$(kde_icondir)/locolor/32x32/apps/kmag.png +type=DATA + +[kmag/main.cpp] +dist=true +install=false +install_location= +type=SOURCE + +[po/Makefile.am] +sub_dirs= +type=po diff --git a/kmag/kmag.lsm b/kmag/kmag.lsm new file mode 100644 index 0000000..6747d64 --- /dev/null +++ b/kmag/kmag.lsm @@ -0,0 +1,14 @@ +Begin3 +Title: Kmag +Version: 0.3 +Entered-date: +Description: +Keywords: +Author: Sarang Lakare <[email protected]> +Maintained-by: Sarang Lakare <[email protected]> +Primary-site: +Home-page: http://kmag.sourceforge.net +Original-site: +Platforms: Linux and other Unices +Copying-policy: GNU Public License +End diff --git a/kmag/kmag.mdk.spec b/kmag/kmag.mdk.spec new file mode 100644 index 0000000..983bf83 --- /dev/null +++ b/kmag/kmag.mdk.spec @@ -0,0 +1,108 @@ +%define name kmag +%define version 0.8 +%define release 1 + +Name: %{name} +Version: %{version} +Release: %{release} +Summary: KDE Screen Magnifier +Group: Graphical desktop/KDE +License: GPL +Source: %{name}-%{version}.tar.gz +URL: http://kmag.sourceforge.net +Packager: Sarang Lakare <[email protected]> +Buildroot: %_tmppath/%{name}-%{version}-buildroot +BuildRequires: gcc-cpp db3 readline pam popt libtermcap2 zlib1 XFree86-devel XFree86-libs Mesa-common +BuildRequires: automake arts autoconf diffutils kdelibs file +BuildRequires: m4 texinfo gettext libjpeg62-devel kdelibs-devel gcc-c++ libbinutils2 libbzip2_1 +BuildRequires: db1 freetype2 libjpeg62 libmng1 libpng libqt2 libqt2-devel rpm-build + + +%description +KMagnifier is a screen magnifier for KDE. It is useful for +people with bad sight or others needing to magnify a part of the screen. + +%prep +rm -rf $RPM_BUILD_ROOT + +%setup -n %{name}-%{version} + +%build +CFLAGS="%optflags" CXXFLAGS="%optflags" \ + ./configure --prefix=%_prefix \ + --disable-rpath \ + --disable-debug + +%make + +%install +make DESTDIR=%buildroot install + +install -d $RPM_BUILD_ROOT%_menudir + +kdedesktop2mdkmenu.pl kmag "Applications/Accessibility" %buildroot/%_datadir/applnk/Applications/Accessibility/kmag.desktop %buildroot/%_menudir/kmag + + +%clean +rm -rf $RPM_BUILD_ROOT + +%post +%update_menus + +%postun +%clean_menus + +%files +%defattr(-,root,root) +%_bindir/* +%_menudir/* +# +%_datadir/icons/locolor/16x16/apps/*.png +%_datadir/icons/locolor/32x32/apps/*.png +%_datadir/icons/hicolor/16x16/apps/*.png +# +%_datadir/applnk/Applications/Accessibility/*.desktop +# +%dir %_datadir/apps/kmag/ +%_datadir/apps/kmag/*.rc +# +#%doc README COPYING AUTHORS +#%doc %_docdir/HTML/en/*.docbook +%doc %_docdir/HTML/en/kmag/*.docbook +%doc %_docdir/HTML/en/kmag/images/*.png +#%doc %_docdir/HTML/en/kmag/common + +%changelog +* Sun Apr 21 2002 Sarang Lakare <[email protected]> 0.8-1mdk +- Rebuilding ver 0.8 for LM8.2/LM8.1 +- Added KDE documentation and removed GNU documentation + +* Tue Nov 20 2001 Sarang Lakare <[email protected]> 0.6-1mdk +- Rebuilding ver 0.6 for LM8.0 + +* Sat Oct 20 2001 Laurent MONTEL <[email protected]> 0.5-2mdk +- Rebuild against libpng3 + +* Wed Sep 19 2001 Laurent MONTEL <[email protected]> 0.5-1mdk +- update code (0.5) + +* Wed Aug 08 2001 Lenny Cartier <[email protected]> 0.3-6mdk +- rebuild + +* Tue Apr 10 2001 David BAUDENS <[email protected]> 0.3-5mdk +- Move KDE menu entriy in %%_datadir/applnk +- Fix and use optimizations +- Fix BuildRequires for non %%ix86 architectures +- Rebuild against latest GCC + +* Fri Mar 30 2001 Laurent MONTEL <[email protected]> 0.3-4mdk +- Fix typo in menu entry + +* Wed Mar 28 2001 Laurent MONTEL <[email protected]> 0.3-3mdk +- Add build requires + +* Tue Mar 13 2001 Laurent MONTEL <[email protected]> 0.3-2mdk +- REbuild with qt-2.3 + +* Sat Feb 24 2001 Daouda Lo <[email protected]> 0.3-1mdk +- first mdk package diff --git a/kmag/kmagselrect.cpp b/kmag/kmagselrect.cpp new file mode 100644 index 0000000..4347d96 --- /dev/null +++ b/kmag/kmagselrect.cpp @@ -0,0 +1,385 @@ +/*************************************************************************** + kmagselrect.cpp - description + ------------------- + begin : Mon Feb 12 23:45:41 EST 2001 + copyright : (C) 2001-2003 by Sarang Lakare + email : sarang#users.sf.net + copyright : (C) 2003-2004 by Olaf Schmidt + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "kmagselrect.h" +#include "kmagselrect.moc" + +#include <qapplication.h> +#include <qcursor.h> +#include <qdesktopwidget.h> +#include <qpixmap.h> +#include <qbitmap.h> + +#include <kapplication.h> +#include <klocale.h> + +static uchar line_bits[] = {0x2d, 0x96, 0x4b, 0xa5, 0xd2, 0x69, 0xb4, 0x5a}; + +static QColor titleColor = QColor (0,0,128); +static QColor titleBtnColor = QColor (255,255,0); +static QColor textColor = QColor (255,255,255); + +static int frameSize = 10; +static int titleSize = 24; + +void setTitleColors (QColor title, QColor text, QColor titleBtn) +{ + titleColor = title; + titleBtnColor = titleBtn; + textColor = text; +} + +void setFrameSize (int size) +{ + frameSize = size; +} + +void setTitleSize (int size) +{ + titleSize = size; +} + +QColor getTitleColor () +{ + return titleColor; +} + +QColor getTitleBtnColor () +{ + return titleBtnColor; +} + +QColor getTextColor () +{ + return textColor; +} + +int getFrameSize () +{ + return frameSize; +} + +int getTitleSize () +{ + if (titleSize > frameSize) + return titleSize; + else + return frameSize; +} + +//-------------------------------------------------------------------------- +// Construction +//-------------------------------------------------------------------------- + +KMagSelRect::KMagSelRect(QWidget *parent) : + QRect() +{ + init(parent); +} + +KMagSelRect::KMagSelRect(const QPoint &topLeft, const QPoint &bottomRight, + QWidget *parent) : +QRect(topLeft, bottomRight) +{ + init(parent); +} + +KMagSelRect::KMagSelRect(const QPoint &topLeft, const QSize &size, + QWidget *parent) : +QRect(topLeft, size) +{ + init(parent); +} + +KMagSelRect::KMagSelRect(int left, int top, int width, int height, + QWidget *parent) : +QRect(left, top, width, height) +{ + init(parent); +} + +void KMagSelRect::init(QWidget *parent) +{ + // Make sure parent is the window itself, not a widget within the window + if (parent != 0) + while (parent->parentWidget (true) != 0) + parent=parent->parentWidget (true); + + selectionwindow = 0; + selWindowParent = parent; + + m_alwaysVisible = false; +} + +KMagSelRect::~KMagSelRect() +{ +} + +//-------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------- + +WId KMagSelRect::winId() +{ + if (selectionwindow) + return selectionwindow->winId(); + else + return 0; +} + +bool KMagSelRect::visible() +{ + return (selectionwindow != 0); +} + +void KMagSelRect::alwaysVisible(bool visible) +{ + m_alwaysVisible = visible; +} + + +//-------------------------------------------------------------------------- +// Slots +//-------------------------------------------------------------------------- + +void KMagSelRect::show() +{ + if (selectionwindow == 0) { + selectionwindow = new KMagSelWin (selWindowParent, "selectionwindow"); + connect (selectionwindow, SIGNAL (resized ()), this, SLOT (selWinResized ())); + + update(); + selectionwindow->show(); + selWindowParent->setActiveWindow(); + } +} + +void KMagSelRect::hide() +{ + if(m_alwaysVisible) + return; + if (selectionwindow != 0) { + selectionwindow->hide(); + delete selectionwindow; + selectionwindow = 0; + } +} + +void KMagSelRect::update() +{ + // make sure the selection window does not go outside of the display + if (height() > QApplication::desktop()->geometry().height()) + setHeight (QApplication::desktop()->geometry().height()); + if (width() > QApplication::desktop()->geometry().width()) + setWidth (QApplication::desktop()->geometry().width()); + + if (top() < 0) + moveTop (0); + if (left() < 0) + moveLeft (0); + if (bottom() > QApplication::desktop()->geometry().bottom()) + moveBottom (QApplication::desktop()->geometry().bottom()); + if (right() > QApplication::desktop()->geometry().right()) + moveRight (QApplication::desktop()->geometry().right()); + + if (selectionwindow != 0) + selectionwindow->setSelRect (QRect (topLeft(), bottomRight())); +} + +void KMagSelRect::selWinResized() +{ + if (selectionwindow != 0) + { + QRect newRect = selectionwindow->getSelRect(); + setRect (newRect.x(), newRect.y(), newRect.width(), newRect.height()); + } +} + +//-------------------------------------------------------------------------- +// KMagSelWin +//-------------------------------------------------------------------------- + +KMagSelWin::KMagSelWin ( QWidget * parent, const char * name, WFlags ) : + QWidget (parent, name, WStyle_Customize | WStyle_NoBorder | WStyle_StaysOnTop | WType_TopLevel | WX11BypassWM) +{ + QBitmap line (8, 8, line_bits, true); + setPaletteBackgroundPixmap (line); + setBackgroundOrigin (QWidget::WindowOrigin); + + titleBar = new KMagSelWinCorner (this, "titlebar"); + titleBar->setPaletteBackgroundColor (getTitleColor ()); + titleBar->setPaletteForegroundColor (getTextColor ()); + titleBar->setText(i18n("Selection Window")+" - "+i18n("KMagnifier")); + connect (titleBar, SIGNAL (startResizing ()), this, SLOT (startResizing ())); + connect (titleBar, SIGNAL (resized (QPoint)), this, SLOT (titleMoved (QPoint))); + + topLeftCorner = new KMagSelWinCorner (this, "topleft"); + topLeftCorner->setCursor (Qt::SizeFDiagCursor); + topLeftCorner->setPaletteBackgroundColor (getTitleBtnColor ()); + connect (topLeftCorner, SIGNAL (startResizing ()), this, SLOT (startResizing ())); + connect (topLeftCorner, SIGNAL (resized (QPoint)), this, SLOT (topLeftResized (QPoint))); + + topRightCorner = new KMagSelWinCorner (this, "topright"); + topRightCorner->setCursor (Qt::SizeBDiagCursor); + topRightCorner->setPaletteBackgroundColor (getTitleBtnColor ()); + connect (topRightCorner, SIGNAL (startResizing ()), this, SLOT (startResizing ())); + connect (topRightCorner, SIGNAL (resized (QPoint)), this, SLOT (topRightResized (QPoint))); + + bottomLeftCorner = new KMagSelWinCorner (this, "bottomleft"); + bottomLeftCorner->setCursor (Qt::SizeBDiagCursor); + bottomLeftCorner->setPaletteBackgroundColor (getTitleBtnColor ()); + connect (bottomLeftCorner, SIGNAL (startResizing ()), this, SLOT (startResizing ())); + connect (bottomLeftCorner, SIGNAL (resized (QPoint)), this, SLOT (bottomLeftResized (QPoint))); + + bottomRightCorner = new KMagSelWinCorner (this, "bottomright"); + bottomRightCorner->setCursor (Qt::SizeFDiagCursor); + bottomRightCorner->setPaletteBackgroundColor (getTitleBtnColor ()); + connect (bottomRightCorner, SIGNAL (startResizing ()), this, SLOT (startResizing ())); + connect (bottomRightCorner, SIGNAL (resized (QPoint)), this, SLOT (bottomRightResized (QPoint))); +} + +KMagSelWin::~KMagSelWin() +{ + delete titleBar; + delete topLeftCorner; + delete topRightCorner; + delete bottomLeftCorner; + delete bottomRightCorner; +} + +void KMagSelWin::setSelRect (QRect selRect) +{ + selRect = selRect.normalize(); + + if (selRect.left() < 0) + selRect.setLeft (0); + if (selRect.top() < 0) + selRect.setTop (0); + if (selRect.right() > QApplication::desktop()->width()) + selRect.setRight (QApplication::desktop()->width()); + if (selRect.bottom() > QApplication::desktop()->height()) + selRect.setBottom (QApplication::desktop()->height()); + + setGeometry ( + selRect.left() - getFrameSize(), + selRect.top() - getTitleSize() - 2, + selRect.width() + getFrameSize() + getFrameSize(), + selRect.height() + getFrameSize() + getTitleSize()+2); + + int w = getFrameSize(); + if (selRect.width() < w+w) + w = static_cast<int>(selRect.width()/2); + + int h = getFrameSize(); + if (selRect.height() < h+h) + h = static_cast<int>(selRect.height()/2); + + setMask (QRegion (QRect (0, 0, width(), height ())) + - QRegion (QRect (getFrameSize(), getTitleSize()+2, selRect.width(), selRect.height())) + - QRegion (QRect (0, 0, getFrameSize()+w, getTitleSize()+2-getFrameSize())) + - QRegion (QRect (width()-getFrameSize()-w, 0, getFrameSize()+w, getTitleSize()+2-getFrameSize())) + - QRegion (QRect (0, getTitleSize()+2+h, getFrameSize()-2, selRect.height()-h-h)) + - QRegion (QRect (width()-getFrameSize()+2, getTitleSize()+2+h, getFrameSize()-2, selRect.height()-h-h)) + - QRegion (QRect (getFrameSize()+w, height()-getFrameSize()+2, selRect.width()-w-w, getFrameSize()-2))); + + titleBar->setGeometry (getFrameSize()+w, 0, selRect.width()-h-h, getTitleSize()); + topLeftCorner->setGeometry (0, getTitleSize()+2-getFrameSize(), getFrameSize()+w, getFrameSize()+h); + topRightCorner->setGeometry (width()-getFrameSize()-w, getTitleSize()+2-getFrameSize(), getFrameSize()+w, getFrameSize()+h); + bottomLeftCorner->setGeometry (0, height()-getFrameSize()-h, getFrameSize()+w, getFrameSize()+h); + bottomRightCorner->setGeometry (width()-getFrameSize()-w, height()-getFrameSize()-h, getFrameSize()+w, getFrameSize()+h); +} + +QRect KMagSelWin::getSelRect () +{ + return QRect ( + x() + getFrameSize(), + y() + getTitleSize()+2, + width() - getFrameSize() - getFrameSize(), + height() - getFrameSize() - getTitleSize()-2); +} + +void KMagSelWin::startResizing () +{ + oldSelRect = getSelRect(); +} + +void KMagSelWin::titleMoved ( QPoint offset ) +{ + QRect selRect = oldSelRect; + selRect.moveBy (offset.x(), offset.y()); + setSelRect (selRect); + emit resized (); +} + +void KMagSelWin::topLeftResized ( QPoint offset ) +{ + setSelRect (QRect(oldSelRect.topLeft() + offset, oldSelRect.bottomRight ())); + emit resized(); +} + +void KMagSelWin::topRightResized ( QPoint offset ) +{ + setSelRect (QRect(oldSelRect.topRight() + offset, oldSelRect.bottomLeft ())); + emit resized(); +} + +void KMagSelWin::bottomLeftResized ( QPoint offset ) +{ + setSelRect (QRect(oldSelRect.bottomLeft() + offset, oldSelRect.topRight ())); + emit resized(); +} + +void KMagSelWin::bottomRightResized ( QPoint offset ) +{ + setSelRect (QRect(oldSelRect.bottomRight() + offset, oldSelRect.topLeft())); + emit resized(); +} + + +//-------------------------------------------------------------------------- +// KMagSelWinCorner +//-------------------------------------------------------------------------- + +KMagSelWinCorner::KMagSelWinCorner ( QWidget * parent, const char * name, WFlags f ) : + QLabel (parent, name, f) +{ + setFrameStyle (QFrame::WinPanel | QFrame::Raised); + setLineWidth (1); +} + +KMagSelWinCorner::~KMagSelWinCorner() +{ +} + +void KMagSelWinCorner::mousePressEvent ( QMouseEvent * e ) +{ + oldPos = e->globalPos (); + emit startResizing (); +} + +void KMagSelWinCorner::mouseReleaseEvent ( QMouseEvent * e ) +{ + setFrameShadow (QFrame::Raised); + emit resized (e->globalPos () - oldPos); +} + +void KMagSelWinCorner::mouseMoveEvent ( QMouseEvent * e ) +{ + emit resized (e->globalPos () - oldPos); +} diff --git a/kmag/kmagselrect.h b/kmag/kmagselrect.h new file mode 100644 index 0000000..675954c --- /dev/null +++ b/kmag/kmagselrect.h @@ -0,0 +1,146 @@ +/*************************************************************************** + kmagselrect.h - description + ------------------- + begin : Mon Feb 12 23:45:41 EST 2001 + copyright : (C) 2001-2003 by Sarang Lakare + email : sarang#users.sf.net + copyright : (C) 2003-2004 by Olaf Schmidt + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef KMAGSELRECT_H +#define KMAGSELRECT_H + +#include <stdlib.h> + +// Qt includes +#include <qrect.h> +#include <qwidget.h> +#include <qlabel.h> + +class KMagSelWinCorner : public QLabel +{ + Q_OBJECT + +public: + + KMagSelWinCorner ( QWidget * parent = 0, const char * name = 0, WFlags f = 0 ); + + virtual ~KMagSelWinCorner(); + +signals: + + void startResizing (); + void resized ( QPoint offset ); + +protected: + + QPoint oldPos; + + virtual void mousePressEvent ( QMouseEvent * e ); + virtual void mouseReleaseEvent ( QMouseEvent * e ); + virtual void mouseMoveEvent ( QMouseEvent * e ); +}; + +class KMagSelWin : public QWidget +{ + Q_OBJECT + +public: + + KMagSelWin ( QWidget * parent = 0, const char * name = 0, WFlags f = 0 ); + + virtual ~KMagSelWin(); + + void setSelRect ( QRect selRect ); + QRect getSelRect (); + +public slots: + + void startResizing (); + void titleMoved ( QPoint offset ); + void topLeftResized ( QPoint offset ); + void topRightResized ( QPoint offset ); + void bottomLeftResized ( QPoint offset ); + void bottomRightResized ( QPoint offset ); + +signals: + + void resized(); + +protected: + + QRect oldSelRect; + + KMagSelWinCorner *titleBar; + KMagSelWinCorner *topLeftCorner; + KMagSelWinCorner *topRightCorner; + KMagSelWinCorner *bottomLeftCorner; + KMagSelWinCorner *bottomRightCorner; +}; + +/** + * This class stores the selected rectangular area for grabbing. It also displays the + * rectangular area on demand. + * + * @author Original : Michael Forster + * @author Current : Sarang Lakare + */ +class KMagSelRect : public QObject, public QRect +{ + Q_OBJECT + +public: + KMagSelRect(QWidget *parent=0); + KMagSelRect(const QPoint &topLeft, const QPoint &bottomRight, + QWidget *parent=0); + KMagSelRect(const QPoint &topLeft, const QSize &size, + QWidget *parent=0); + KMagSelRect(int left, int top, int width, int height, + QWidget *selWindowParent=0); + + virtual ~KMagSelRect(); + + WId winId(); + + bool visible(); + + /// Makes the rectangle always visible + void alwaysVisible(bool visible=true); + + /// Returns true if always visible is set + bool getAlwaysVisible() const { + return (m_alwaysVisible); + }; + +public slots: + + void show(); + void hide(); + void update(); + + void selWinResized(); + +protected: + + void init(QWidget *); + + QWidget *selWindowParent; + KMagSelWin *selectionwindow; + bool m_alwaysVisible; + +}; + +void setTitleColors (QColor title, QColor text, QColor titleBtn); +void setFrameSize (int size); + +#endif // KMAGSELRECT_H diff --git a/kmag/kmagui.rc b/kmag/kmagui.rc new file mode 100644 index 0000000..d30ce37 --- /dev/null +++ b/kmag/kmagui.rc @@ -0,0 +1,109 @@ +<!DOCTYPE kpartgui> +<kpartgui name="kmag" version="11"> + <ToolBar noMerge="1" name="mainToolBar"> + <Action name="new_window"/> + <Separator /> + <Action name="snapshot"/> + <Action name="print"/> + <Action name="copy"/> + </ToolBar> + + <ToolBar noMerge="1" name="viewToolBar"> + <Action name="start_stop_refresh"/> + <Separator /> + <Action name="zoom_in"/> + <Action name="zoom"/> + <Action name="zoom_out"/> + <Separator /> + <Action name="fps_selector"/> + </ToolBar> + + <ToolBar noMerge="1" name="settingsToolBar"> + <Action name="mode_followmouse"/> + <Action name="mode_selectionwindow"/> + <Separator /> + <Action name="hidecursor"/> + </ToolBar> + + <MenuBar> + <Menu name="file"><text>&File</text> + <Action name="new_window"/> + <Action name="snapshot"/> + <Action name="print"/> + <Separator /> + <Action name="quit"/> + </Menu> + <Menu name="edit"><text>&Edit</text> + <Action name="copy"/> + </Menu> + <Menu name="view"><text>&View</text> + <Action name="start_stop_refresh"/> + <Separator /> + <Action name="zoom"/> + <Action name="zoom_out"/> + <Action name="zoom_in"/> + <Separator /> + <Action name="invert"/> + <Action name="rotation"/> + <Action name="fps_selector"/> + </Menu> + <Menu name="settings"><text>&Settings</text> + <Action name="show_menu"/> + <Action name="show_mainToolBar"/> + <Action name="show_viewToolBar"/> + <Action name="show_settingsToolBar"/> + <Separator /> + <Action name="mode_followmouse"/> + <Action name="mode_selectionwindow"/> + <Action name="mode_edgetop"/> + <Action name="mode_edgeleft"/> + <Action name="mode_edgeright"/> + <Action name="mode_edgebottom"/> + <Separator /> + <Action name="hidecursor"/> + <Separator /> + <Action name="key_conf"/> + <Action name="toolbar_conf"/> + </Menu> + </MenuBar> + + <Menu name="mainPopUp"> + <Action name="new_window"/> + <Separator /> + <Action name="copy"/> + <Separator /> + <Menu name="view"><text>&View</text> + <Action name="start_stop_refresh"/> + <Separator /> + <Action name="zoom"/> + <Action name="zoom_out"/> + <Action name="zoom_in"/> + <Separator /> + <Action name="invert"/> + <Action name="rotation"/> + <Action name="fps_selector"/> + </Menu> + <Menu name="settings"><text>&Settings</text> + <Action name="show_menu"/> + <Action name="show_mainToolBar"/> + <Action name="show_viewToolBar"/> + <Action name="show_settingsToolBar"/> + <Separator /> + <Action name="mode_followmouse"/> + <Action name="mode_selectionwindow"/> + <Action name="mode_edgetop"/> + <Action name="mode_edgeleft"/> + <Action name="mode_edgeright"/> + <Action name="mode_edgebottom"/> + <Separator /> + <Action name="hidecursor"/> + <Separator /> + <Action name="key_conf"/> + <Action name="toolbar_conf"/> + </Menu> + <Separator /> + <Action name="snapshot"/> + <Action name="print"/> + <Action name="quit"/> + </Menu> +</kpartgui> diff --git a/kmag/kmagzoomview.cpp b/kmag/kmagzoomview.cpp new file mode 100644 index 0000000..a38c21c --- /dev/null +++ b/kmag/kmagzoomview.cpp @@ -0,0 +1,927 @@ +/*************************************************************************** + kmagview.cpp - description + ------------------- + begin : Mon Feb 12 23:45:41 EST 2001 + copyright : (C) 2001-2003 by Sarang Lakare + email : sarang#users.sourceforge.net + copyright : (C) 2003-2005 by Olaf Schmidt + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + + +// application specific includes +#include "kmagzoomview.h" +#include "kmagzoomview.moc" + +// include files for Qt +#include <qbitmap.h> +#include <qpixmap.h> +#include <qimage.h> +#include <qcursor.h> +#include <qglobal.h> +#include <qpainter.h> +#include <qwhatsthis.h> +#include <qwidget.h> + +// include files for KDE +#include <kapplication.h> +#include <kcursor.h> +#include <kdebug.h> +#include <klocale.h> + +#include <X11/Xlib.h> +#include <X11/Xatom.h> + +// include bitmaps for cursors +static uchar left_ptr_bits[] = { + 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, + 0xf8, 0x01, 0xf8, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0xd8, 0x00, 0x88, 0x01, + 0x80, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00}; + +static uchar left_ptrmsk_bits[] = { + 0x0c, 0x00, 0x1c, 0x00, 0x3c, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xfc, 0x01, + 0xfc, 0x03, 0xfc, 0x07, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x01, 0xdc, 0x03, + 0xcc, 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x03}; + +static uchar phand_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, + 0x7e, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, + 0x08, 0x08, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x08, 0x22, 0x00, 0x00, + 0x30, 0x41, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x40, 0x12, 0x00, 0x00, + 0x80, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static uchar phandm_bits[] = { + 0xfe, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, + 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, + 0xfc, 0x1f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, + 0xf8, 0xff, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, + 0xc0, 0x1f, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + + +static bool obscuredRegion (QRegion ®ion, Window winId, Window ignoreId, Window start = 0, int level = -1) { + Window root, parent, *children; uint nchildren; + if (0 == start) + start = qt_xrootwin(); + + bool winIdFound = false; + if (0 != XQueryTree (qt_xdisplay(), start, &root, &parent, &children, &nchildren)) { + for (uint i=0; i < nchildren; ++i) { + if (winIdFound) { + if (ignoreId != children [i]) { + XWindowAttributes atts; + XGetWindowAttributes (qt_xdisplay(), children [i], &atts); + if (atts.map_state == IsViewable) + region -= QRegion (atts.x, atts.y, atts.width, atts.height, QRegion::Rectangle); + } + } + else if (winId == children [i]) + winIdFound = true; + + // According to tests, my own window ID is either on toplevel or two levels below. + // To avoid unneccessary recursion, we limit the search to two recursion levels, + // then to five recursion levels, and make a full recursive search only if that + // was unsuccessful. + else if (level > 1) + winIdFound = obscuredRegion (region, winId, ignoreId, children [i], level-1); + else if (level == -1) + if (! (winIdFound = obscuredRegion (region, winId, ignoreId, children [i], 0))) + if (! (winIdFound = obscuredRegion (region, winId, ignoreId, children [i], 1))) + winIdFound = obscuredRegion (region, winId, ignoreId, children [i], -1); + } + + if (children != NULL) + XFree (children); + } + + return winIdFound; +} + + + + +KMagZoomView::KMagZoomView(QWidget *parent, const char *name) + : QScrollView(parent, name), + m_selRect(0, 0, 128, 128, this), + m_grabTimer(0), + m_mouseViewTimer(0), + m_latestCursorPos(0,0), + m_followMouse(false), + m_showMouse(1), + m_zoom(1.0), + m_rotation(0), + m_invert(false), + m_fitToWindow(true) +{ + KApplication::setGlobalMouseTracking(TRUE); + viewport()->setMouseTracking(TRUE); + viewport()->setBackgroundMode (NoBackground); + viewport()->setFocusPolicy(QWidget::StrongFocus); + + m_ctrlKeyPressed = false; + m_shiftKeyPressed = false; + m_refreshSwitch = true; + m_refreshSwitchStateOnHide = m_refreshSwitch; + + // set the refresh rate + setRefreshRate(10); + + // connect it to grabFrame() + connect(&m_grabTimer, SIGNAL(timeout()), SLOT(grabFrame())); + // start the grabTimer + m_grabTimer.start(static_cast<int>(1000.0/m_fps)); + + // connect it to updateMouseView() + connect(&m_mouseViewTimer, SIGNAL(timeout()), SLOT(updateMouseView())); + // start the grabTimer @ 25 frames per second! + m_mouseViewTimer.start(25); + + QWhatsThis::add(this, i18n("This is the main window which shows the contents of the\ + selected region. The contents will be magnified according to the zoom level that is set.")); + + // different ways to show the cursor. + m_showMouseTypes << "Hidden" << "Box" << "Arrow" << "Actual"; + + updateMatrix(); +} + +KMagZoomView::~KMagZoomView() +{ + KApplication::setGlobalMouseTracking(FALSE); +} + +/** + * This function will set/reset mouse following of grab window. + */ +void KMagZoomView::followMouse(bool follow) +{ + if(follow) { + m_followMouse = true; + m_mouseMode = Normal; + setVScrollBarMode (QScrollView::AlwaysOff); + setHScrollBarMode (QScrollView::AlwaysOff); + } else { + m_followMouse = false; + m_mouseMode = Normal; + setVScrollBarMode (QScrollView::AlwaysOn); + setHScrollBarMode (QScrollView::AlwaysOn); + } +} + +/** + * Called when the widget is hidden. Stop refresh when this happens. + */ +void KMagZoomView::hideEvent( QHideEvent* ) +{ + // Save the state of the refresh switch.. the state will be restored + // when showEvent is called + m_refreshSwitchStateOnHide = m_refreshSwitch; + + // Check if refresh is ON + if(m_refreshSwitch) { + toggleRefresh(); + } +} + + +/** + * Called when the widget is shown. Start refresh when this happens. + */ +void KMagZoomView::showEvent( QShowEvent* ) +{ + // Check if refresh switch was ON when hide was called and if currently it is OFF + if(m_refreshSwitchStateOnHide && !m_refreshSwitch) { + // start the refresh in that case + toggleRefresh(); + } +} + +/** + * Called when the widget is resized. Check if fitToWindow is active when this happens. + */ +void KMagZoomView::resizeEvent( QResizeEvent * e ) +{ + QScrollView::resizeEvent (e); + if(m_fitToWindow) + fitToWindow(); +} + +/** + * Called when the widget is to be repainted + * + * @param p + */ +void KMagZoomView::drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph ) +{ + if(m_grabbedPixmap.isNull()) + return; + + // A pixmap which will be eventually displayed + QRect areaToPaint = m_invertedMatrix.mapRect (QRect(clipx, clipy, clipw, cliph)); + QPixmap clippedPixmap (areaToPaint.size()); + clippedPixmap.fill (QColor (128, 128, 128)); + areaToPaint &= QRect (QPoint (0,0), m_selRect.size()); + bitBlt(&clippedPixmap, QPoint (0,0), &m_grabbedPixmap, areaToPaint); + + // show the pixel under mouse cursor + if(m_showMouse) { + // paint the mouse cursor + paintMouseCursor(&clippedPixmap, calcMousePos (m_refreshSwitch)-QPoint (areaToPaint.x(), areaToPaint.y())); + } + + QPixmap zoomedPixmap; + zoomedPixmap = clippedPixmap.xForm (m_zoomMatrix); + + if (m_invert) { + QImage zoomedImage; + zoomedImage = zoomedPixmap.convertToImage(); + zoomedImage.invertPixels (false); + p->drawImage (QPoint (clipx-contentsX(), clipy-contentsY()), zoomedImage, zoomedImage.rect(), + Qt::ThresholdDither | Qt::ThresholdAlphaDither | Qt::AvoidDither); + } else { + p->drawPixmap (QPoint (clipx, clipy), zoomedPixmap, zoomedPixmap.rect()); + } +} + +/** + * Draws the mouse cursor according to the current selection of the type of + * mouse cursor to draw. + */ +void KMagZoomView::paintMouseCursor(QPaintDevice *dev, QPoint mousePos) +{ + if(!dev) + return; + + QPainter pz(dev); + + if(m_latestCursorPos.x() >= 0 && m_latestCursorPos.x() < m_selRect.width() && + m_latestCursorPos.y() >= 0 && m_latestCursorPos.y() < m_selRect.height() ) { + // mouse position is indeed inside the selRect + + // How to show the mouse : + + switch(m_showMouse) { + case 1: + // 1. Square around the pixel + pz.setPen(Qt::white); + pz.setRasterOp(Qt::XorROP); + pz.drawRect(mousePos.x()-1, mousePos.y()-1, 3, 3); + break; + + case 2: + { + // 2. Arrow cursor + pz.setPen(Qt::black); + pz.setBackgroundColor(Qt::white); + + QBitmap sCursor( 16, 16, left_ptr_bits, TRUE ); + QBitmap mask( 16, 16, left_ptrmsk_bits, TRUE ); + sCursor.setMask(mask); + + // since hot spot is at 3,1 + pz.drawPixmap(mousePos.x()-3, mousePos.y()-1, sCursor); + } + break; + + case 3: + { + // 3. Actual cursor + // Get the current cursor type + QWidget *dummy = KApplication::widgetAt(QCursor::pos(), FALSE); + if(!dummy) + break; + kdDebug() << ">" << dummy->name() << ":" << dummy->cursor().shape() << "-" << endl; + switch(this->cursor().shape()) { + case ArrowCursor : + { + // 2. Arrow cursor + pz.setPen(Qt::black); + pz.setBackgroundColor(Qt::white); + + QBitmap sCursor( 16, 16, left_ptr_bits, TRUE ); + QBitmap mask( 16, 16, left_ptrmsk_bits, TRUE ); + sCursor.setMask(mask); + + // since hot spot is at 3,1 + pz.drawPixmap(mousePos.x()-3, mousePos.y()-1, sCursor); + } + break; + default: + QBitmap sCursor( 32, 32, phand_bits, TRUE ); + QBitmap mask( 32, 32, phandm_bits, TRUE ); + sCursor.setMask(mask); + + pz.drawPixmap(mousePos.x(), mousePos.y(), sCursor); + break; + } // switch(cursor) + + + } + break; + + default: + // do not show anything + break; + } // switch(m_showMouse) + } +} + + +QPoint KMagZoomView::calcMousePos(bool updateMousePos) +{ + // get position of mouse wrt selRect + if(updateMousePos) { // get a new position only if asked + m_latestCursorPos = QCursor::pos(); + m_latestCursorPos -= QPoint(m_selRect.x(), m_selRect.y()); + } + + // get coordinates of the pixel w.r.t. the pixmap + return QPoint (m_latestCursorPos.x(), m_latestCursorPos.y()); +} + + +// MOUSE ACTIONS + +/** + * Called when mouse is clicked inside the window + * + * @param e + */ +void KMagZoomView::mousePressEvent(QMouseEvent *e) +{ + switch(e->button()) { + case QMouseEvent::LeftButton : + if(m_ctrlKeyPressed) { + // check if currently in resize mode + // don't do anything if fitToWindow is enabled + if ((m_mouseMode != ResizeSelection) && !m_fitToWindow) { + // set the mode to ResizeSelection + m_mouseMode = ResizeSelection; + + // set mouse cursor to "resize all direction" + setCursor(sizeAllCursor); + + // backup the old position + m_oldMousePos.setX(e->globalX()); + m_oldMousePos.setY(e->globalY()); + + // set the cursor position to the bottom-right of the selected region + QCursor::setPos(m_selRect.bottomRight()); + + // show the selection rectangle + m_selRect.show(); + } + else { + #if QT_VERSION >= 300 + // ignore this button press.. so it goes to the parent + e->ignore(); + #endif + } + } else if(m_shiftKeyPressed) { + // check if currently in move mode + // don't do anything if follow mouse is enabled + if ((m_mouseMode != MoveSelection) && !m_followMouse) { + m_mouseMode = MoveSelection; + + // set mouse cursor to cross hair + setCursor(crossCursor); + + // backup the old position + m_oldMousePos.setX(e->globalX()); + m_oldMousePos.setY(e->globalY()); + + // set the cursor position to the center of the selected region + QCursor::setPos(m_selRect.center()); + + // show the selected rectangle + m_selRect.show(); + } + else { + #if QT_VERSION >= 300 + // ignore this button press.. so it goes to the parent + e->ignore(); + #endif + } + } else { + // check if currently in move mode + // don't do anything if follow mouse is enabled + if ((m_mouseMode != GrabSelection) && !m_followMouse) { + m_mouseMode = GrabSelection; + + // set mouse cursor to hand + setCursor(KCursor::handCursor()); + + // store the old position + m_oldMousePos.setX(e->globalX()); + m_oldMousePos.setY(e->globalY()); + + m_oldCenter = m_selRect.center(); + + // show the selected rectangle + m_selRect.show(); + } + else { + #if QT_VERSION >= 300 + // ignore this button press.. so it goes to the parent + e->ignore(); + #endif + } + } + break; + + case QMouseEvent::MidButton : + // check if currently in move mode + // don't do anything if follow mouse is enabled + if ((m_mouseMode != MoveSelection) && !m_followMouse) { + m_mouseMode = MoveSelection; + + // set mouse cursor to cross hair + setCursor(crossCursor); + + // backup the old position + m_oldMousePos.setX(e->globalX()); + m_oldMousePos.setY(e->globalY()); + + // set the cursor position to the center of the selected region + QCursor::setPos(m_selRect.center()); + + // show the selected rectangle + m_selRect.show(); + } + else { + #if QT_VERSION >= 300 + // ignore this button press.. so it goes to the parent + e->ignore(); + #endif + } + break; + // do nothing + default: +#if QT_VERSION >= 300 + // ignore this button press.. so it goes to the parent + e->ignore(); +#endif + break; + } +} + + +/** + * Called when a mouse button is released + * + * @param e + */ +void KMagZoomView::mouseReleaseEvent(QMouseEvent *e) +{ + switch(e->button()) { + case QMouseEvent::LeftButton : + case QMouseEvent::MidButton : + // check if currently in move mode + if(m_mouseMode == MoveSelection) { + // hide the selection window + m_selRect.hide(); + // set the mouse mode to normal + m_mouseMode = Normal; + + // restore the cursor shape + setCursor(arrowCursor); + + // restore the cursor position + QCursor::setPos(m_oldMousePos); + } else if(m_mouseMode == ResizeSelection) { + // hide the selection window + m_selRect.hide(); + // set the mouse mode to normal + m_mouseMode = Normal; + + // restore the cursor shape + setCursor(arrowCursor); + + // restore the cursor position + QCursor::setPos(m_oldMousePos); + } else if(m_mouseMode == GrabSelection) { + // hide the selection window + m_selRect.hide(); + + // set the mouse mode to normal + m_mouseMode = Normal; + + // restore the cursor shape + setCursor(arrowCursor); + } + break; + + case QMouseEvent::RightButton : + break; + case QMouseEvent::NoButton : + break; + + // do nothing + default: + ; + } +} + + +/** + * Called when mouse is moved inside the window + * + * @param e + */ +void KMagZoomView::mouseMoveEvent(QMouseEvent *e) +{ + if(m_mouseMode == ResizeSelection) { + // In resize selection mode + // set the current mouse position as the bottom, right corner + m_selRect.setRight(e->globalX()); + m_selRect.setBottom(e->globalY()); + m_selRect.update(); + + grabFrame(); + } else if(m_mouseMode == MoveSelection) { + QPoint newCenter; + + // set new center to be the current mouse position + m_selRect.moveCenter(e->globalPos()); + m_selRect.update(); + + grabFrame(); + } else if(m_mouseMode == GrabSelection) { + QPoint newPos; + + // get new position + newPos = e->globalPos(); + QPoint delta = (newPos - m_oldMousePos)/m_zoom; + m_selRect.moveCenter(m_oldCenter-delta); + m_selRect.update(); + + grabFrame(); + } +} + +void KMagZoomView::keyPressEvent(QKeyEvent *e) +{ + int offset = 16; + if (e->state() & QKeyEvent::ShiftButton) + offset = 1; + + if (e->key() == QKeyEvent::Key_Control) + m_ctrlKeyPressed = true; + else if (e->key() == QKeyEvent::Key_Shift) + m_shiftKeyPressed = true; + else if (e->key() == QKeyEvent::Key_Left) + { + if (e->state() & QKeyEvent::ControlButton) + { + if (offset >= m_selRect.width()) + m_selRect.setWidth (1); + else + m_selRect.setWidth (m_selRect.width()-offset); + } + else if (contentsX() > 0) + { + offset = (int)(offset*m_zoom); + if (contentsX() > offset) + setContentsPos (contentsX()-offset, contentsY()); + else + setContentsPos (0, contentsY()); + } + else if (m_followMouse == false) + { + if (offset > m_selRect.x()) + m_selRect.setX (0); + else + m_selRect.moveBy (-offset,0); + } + m_selRect.update(); + } + else if (e->key() == QKeyEvent::Key_Right) + { + if (e->state() & QKeyEvent::ControlButton) + m_selRect.setRight (m_selRect.right()+offset); + else if (contentsX() < contentsWidth()-visibleWidth()) + { + offset = (int)(offset*m_zoom); + if (contentsX()+offset < contentsWidth()-visibleWidth()) + setContentsPos (contentsX()+offset, contentsY()); + else + setContentsPos (contentsWidth()-visibleWidth(), contentsY()); + } + else if (m_followMouse == false) + m_selRect.moveBy (offset,0); + + m_selRect.update(); + } + else if (e->key() == QKeyEvent::Key_Up) + { + if (e->state() & QKeyEvent::ControlButton) + { + if (offset >= m_selRect.height()) + m_selRect.setHeight (1); + else + m_selRect.setHeight (m_selRect.height()-offset); + } + else if (contentsY() > 0) + { + offset = (int)(offset*m_zoom); + if (contentsY() > offset) + setContentsPos (contentsX(), contentsY()-offset); + else + setContentsPos (contentsX(), 0); + } + else if (m_followMouse == false) + { + if (offset > m_selRect.y()) + m_selRect.setY (0); + else + m_selRect.moveBy (0, -offset); + } + m_selRect.update(); + } + else if (e->key() == QKeyEvent::Key_Down) + { + if (e->state() & QKeyEvent::ControlButton) + m_selRect.setBottom (m_selRect.bottom()+offset); + else if (contentsY() < contentsHeight()-visibleHeight()) + { + offset = (int)(offset*m_zoom); + if (contentsY()+offset < contentsHeight()-visibleHeight()) + setContentsPos (contentsX(), contentsY()+offset); + else + setContentsPos (contentsX(), contentsHeight()-visibleHeight()); + } + else if (m_followMouse == false) + m_selRect.moveBy (0, offset); + m_selRect.update(); + } + else + e->ignore(); +} + +void KMagZoomView::keyReleaseEvent(QKeyEvent *e) +{ + if (e->key() == QKeyEvent::Key_Control) + m_ctrlKeyPressed = false; + else if (e->key() == QKeyEvent::Key_Shift) + m_shiftKeyPressed = false; + else + e->ignore(); +} + +void KMagZoomView::contextMenuEvent (QContextMenuEvent *e) +{ + emit contextMenu(e->globalPos()); + e->accept(); +} + +void KMagZoomView::focusOutEvent(QFocusEvent *e) +{ + if(e->lostFocus() == TRUE) { + m_ctrlKeyPressed = false; + m_shiftKeyPressed = false; + } +} + +// SLOTS + +/** + * This will fit the zoom view to the view window, thus using the maximum + * possible space in the window. + */ +void KMagZoomView::fitToWindow() +{ + QPoint currCenter = m_selRect.center(); + QRect newRect = m_invertedMatrix.mapRect (QRect(0, 0, visibleWidth(), visibleHeight())); + m_selRect.setSize (newRect.size()); + m_selRect.moveCenter(currCenter); + m_selRect.update(); + + viewport()->repaint(false); +} + +void KMagZoomView::setFitToWindow(bool fit) +{ + m_fitToWindow = fit; + if (fit) + fitToWindow(); +} + + +/** + * Grabs frame from X + */ +void KMagZoomView::grabFrame() +{ + // check refresh status + if (!m_refreshSwitch) + return; + + // check if follow-mouse is enabled + if(m_followMouse && (m_mouseMode != ResizeSelection)) { + // in this case grab w.r.t the current mouse position + QPoint newCenter; + + // set new center to be the current mouse position + m_selRect.moveCenter(QCursor::pos()); + m_selRect.update(); + } + + //QRect r = pixmapRect(); + + // define a normalized rectangle + QRect selRect = m_selRect.normalize(); + + // grab screenshot from the screen and put it in the pixmap + m_grabbedPixmap = QPixmap::grabWindow(QApplication::desktop()->winId(), selRect.x(), selRect.y(), + selRect.width(), selRect.height()); + + // If the KMag window itself is in the screenshot, then it need to be filled with gray to avoid recursion + QPoint globalPos = viewport()->mapToGlobal (viewport()->rect().topLeft()); + QRegion intersection (globalPos.x(), globalPos.y(), viewport()->width(), viewport()->height(), QRegion::Rectangle); + intersection &= QRegion (selRect, QRegion::Rectangle); + + // We don't want to overpaint other windows that happen to be on top + obscuredRegion (intersection, topLevelWidget()->winId(), m_selRect.winId()); + intersection.translate (-selRect.x(), -selRect.y()); + + QPainter painter (&m_grabbedPixmap, true); + QMemArray<QRect> rects (intersection.rects()); + for (uint i = 0; i < rects.size(); i++) + painter.fillRect (rects[i], QBrush (QColor (128, 128, 128))); + + // call repaint to display the newly grabbed image + QRect newSize = m_zoomMatrix.mapRect (m_grabbedPixmap.rect()); + resizeContents (newSize.width(), newSize.height()); + viewport()->repaint(false); +} + + +/** + * Updates the mouse cursor in the zoom view + */ +void KMagZoomView::updateMouseView() +{ + QPoint pos(QCursor::pos()); + if(m_selRect.left() <= pos.x() && pos.x() <= m_selRect.right() && + m_selRect.top() <= pos.y() && pos.y() <= m_selRect.bottom() && + m_refreshSwitch) + viewport()->repaint(false); +} + +/** + * Toggles the state of refreshing. + */ +void KMagZoomView::toggleRefresh() +{ + if(m_refreshSwitch) { + m_refreshSwitch = false; + m_grabTimer.stop(); + m_mouseViewTimer.stop(); + } else { + m_refreshSwitch = true; + m_grabTimer.start(1000/m_fps); + m_mouseViewTimer.start(40); + } +} + +/** + * This function sets the zoom value to be used. + */ +void KMagZoomView::setZoom(float zoom) +{ + m_zoom = zoom; + updateMatrix(); + viewport()->repaint(); +} + +/** + * This function sets the rotation value to be used. + */ +void KMagZoomView::setRotation(int rotation) +{ + m_rotation = rotation; + updateMatrix(); + viewport()->repaint(); +} + +/** + * This function sets whether the magnified image is shown inverted + */ +void KMagZoomView::setInvertation(bool invert) +{ + m_invert = invert; + viewport()->repaint(); +} + +/** + * Set a new refresh rate. + */ +void KMagZoomView::setRefreshRate(float fps) +{ + if(fps < 0.1) + return; + m_fps = static_cast<unsigned int>(fps); + + if(m_grabTimer.isActive()) + m_grabTimer.changeInterval(static_cast<int>(1000.0/m_fps)); +} + +void KMagZoomView::showSelRect(bool show) +{ + m_selRect.alwaysVisible(show); + if(show) { + m_selRect.show(); + } else if(m_mouseMode == Normal) { + m_selRect.hide(); + } +} + +/** + * Sets the selection rectangle to the given position. + */ +void KMagZoomView::setSelRectPos(const QRect & rect) +{ + m_selRect.setRect(rect.x(), rect.y(), rect.width(), rect.height()); + m_selRect.update(); + grabFrame(); +} + +bool KMagZoomView::showMouse(unsigned int type) +{ + if(type > m_showMouseTypes.count()-1) + return (false); + else + m_showMouse = type; + + return(true); +} + +unsigned int KMagZoomView::getShowMouseType() const +{ + return (m_showMouse); +} + +QStringList KMagZoomView::getShowMouseStringList() const +{ + return (m_showMouseTypes); +} + + +/** + * Returns the image which is being displayed. Its again drawn by adding + * the mouse cursor if needed. + */ +QPixmap KMagZoomView::getPixmap() +{ + // show the pixel under mouse cursor + if(m_showMouse && !m_grabbedPixmap.isNull()) { + // Pixmap which will have the pixmap + mouse + QPixmap mousePixmap(m_grabbedPixmap); + + // paint the mouse cursor w/o updating to a newer position + paintMouseCursor(&mousePixmap, calcMousePos(false)); + + return(mousePixmap); + } else { // no mouse cursor + return(m_grabbedPixmap); + } +} + +/** + * Update the magnification matrix + */ +void KMagZoomView::updateMatrix() +{ + // update selection window size if necessary + if (m_fitToWindow) + fitToWindow(); + + // recompute the zoom matrix + m_zoomMatrix.reset(); + m_zoomMatrix.scale(m_zoom, m_zoom); + m_zoomMatrix.rotate(m_rotation); + + bool inverted; + m_invertedMatrix = m_zoomMatrix.invert (&inverted); + +} diff --git a/kmag/kmagzoomview.h b/kmag/kmagzoomview.h new file mode 100644 index 0000000..a863ad6 --- /dev/null +++ b/kmag/kmagzoomview.h @@ -0,0 +1,249 @@ +/*************************************************************************** + kmagview.h - description + ------------------- + begin : Mon Feb 12 23:45:41 EST 2001 + copyright : (C) 2001-2003 by Sarang Lakare + email : sarang#users.sf.net + copyright : (C) 2003-2005 by Olaf Schmidt + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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; version 2 of the License * + * * + ***************************************************************************/ + + +#ifndef KMagZoomView_h_ +#define KMagZoomView_h_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +// include files for Qt +#include <qwidget.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qtimer.h> +#include <qscrollview.h> +#include <qstringlist.h> +#include <qrect.h> +#include <qcursor.h> + +//class KMagSelRect; +#include "kmagselrect.h" + +/** + * The KMagZoomView class provides the view widget for the KmagApp instance. + * + * @author Olaf Schmikt <[email protected]> + * @author Sarang Lakare <sarang#users.sourceforge.net> + */ +class KMagZoomView : public QScrollView +{ + Q_OBJECT + public: + /// Constructor for the main view + KMagZoomView(QWidget *parent = 0, const char *name=0); + + /// Destructor for the main view + ~KMagZoomView(); + + /// Toggles the refreshing of the window + void toggleRefresh(); + + /// Returns the currently displayed zoomed view + QPixmap getPixmap(); + + /// Returns the state of the refresh switch + bool getRefreshStatus() const { return m_refreshSwitch; }; + + /// Returns teh status of followMouse + bool getFollowMouse() const { return m_followMouse; }; + + /// Get the status of "show rect. always" + bool getShowSelRect() const { return (m_selRect.getAlwaysVisible()); }; + + /// Get the coordinates of the selection rectangle + QRect getSelRectPos() const { return static_cast<QRect>(m_selRect); }; + + /// Returns the current state of show mouse + unsigned int getShowMouseType() const; + + /// Returns the different ways of showing mouse cursor + QStringList getShowMouseStringList() const; + + /// Returns the status of "fit to window" option + bool getFitToWindow() const { return (m_fitToWindow); }; + + public slots: + + /// Sets zoom to the given value + void setZoom(float zoom = 0.0); + + /// Sets the rotation to the given value + void setRotation(int rotation = 0); + + /// Sets whether the magnified image is shown inverted + void setInvertation(bool invert); + + /// Grabs a frame from the given portion of the display + void grabFrame(); + + /// Update the mouse cursor in the zoom view + void updateMouseView(); + + /// Set grab-window-follows-mouse mode + void followMouse(bool follow = true); + + /// Shows/Hides the selection marker + void showSelRect(bool show=true); + + /// Set the position of the selection region to the given pos + void setSelRectPos(const QRect & rect); + + /// Set the refresh rate in fps (frames per second) + void setRefreshRate(float fps); + + /// Shows/Hides mouse cursor in the zoomed view + bool showMouse(unsigned int type); + + /// Set the status of "fit to window" option + void setFitToWindow (bool fit=true); + + /// Fits the zoom view to the zoom view window + void fitToWindow(); + + signals: + void contextMenu(QPoint pos); + + protected: + /// Called when the widget is hidden + void hideEvent( QHideEvent * e); + + /// Called when the widget is shown + void showEvent( QShowEvent * e); + + /// Called when the widget has been resized + void resizeEvent(QResizeEvent *e); + + /// Called when the widget is to be repainted + void drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph ); + + /// This function calculates the mouse position relative to the image + QPoint calcMousePos(bool updateMousePos=true); + + /// This function draws the mouse cursor + void paintMouseCursor(QPaintDevice *dev, QPoint mousePos); + + /// Called when mouse click is detected + void mousePressEvent (QMouseEvent *e); + + /// Called when mouse is moved + void mouseMoveEvent(QMouseEvent *e); + + /// Mouse button release event handler + void mouseReleaseEvent(QMouseEvent *e); + + /// Mouse button release event handler + void keyPressEvent(QKeyEvent *e); + + /// Mouse button release event handler + void keyReleaseEvent(QKeyEvent *e); + + /// Catch context menu events + void contextMenuEvent (QContextMenuEvent *e); + + /// Mouse button release event handler + void focusOutEvent(QFocusEvent *e); + + /// Returns the rectangle where the pixmap will be drawn + QRect pixmapRect(); + + private: + /// Stores the pixmap grabbed from the screen - to be zoomed + QPixmap m_grabbedPixmap; + + /// The selected rectangle which is to be grabbed + KMagSelRect m_selRect; + + /// Grabs a window when the timer goes off + QTimer m_grabTimer; + + /// Updates the mouse view + QTimer m_mouseViewTimer; + + /// Zoom matrix + QWMatrix m_zoomMatrix; + + /// Inverted zoom matrix + QWMatrix m_invertedMatrix; + + /// Saves the mouse position when a button is clicked and b4 the cursor is moved to new position + QPoint m_oldMousePos; + + /// Saves the center of the grab window + QPoint m_oldCenter; + + /// Possible modes for the mouse to be in + enum KMagMouseMode { + Normal, + StartSelect, + ResizeSelection, + MoveSelection, + GrabSelection + }; + + /// The current mode which the mouse is + KMagMouseMode m_mouseMode; + + /// stores the state of the Ctrl key + bool m_ctrlKeyPressed; + + /// stores the state of the Shift key + bool m_shiftKeyPressed; + + /// Store the more recent updated cursor position + QPoint m_latestCursorPos; + + /// Various ways of showing mouse cursor + QStringList m_showMouseTypes; + + // configuration options: + + /// To follow mouse motion or not when no key is pressed + bool m_followMouse; + + /// State of refreshing - on or off + bool m_refreshSwitch; + + /// Stores the state of the refresh switch on hide event + bool m_refreshSwitchStateOnHide; + + /// Show mouse cursor type - 0 : do not show, non zero: show + unsigned int m_showMouse; + + /// Frames per second for refresh + unsigned int m_fps; + + /// Stores the amount to zoom the pixmap + float m_zoom; + + /// Stores the degrees to rotate the pixmap + int m_rotation; + + /// Whether the magnified image is to be shown inverted + int m_invert; + + /// Fit the zoom view to the zoom window + bool m_fitToWindow; + + /// Update the magnification matrix + void updateMatrix(); +}; + +#endif // KMagZoomView_h_ diff --git a/kmag/lo16-app-kmag.png b/kmag/lo16-app-kmag.png Binary files differnew file mode 100644 index 0000000..91a27a6 --- /dev/null +++ b/kmag/lo16-app-kmag.png diff --git a/kmag/lo32-app-kmag.png b/kmag/lo32-app-kmag.png Binary files differnew file mode 100644 index 0000000..bffa05d --- /dev/null +++ b/kmag/lo32-app-kmag.png diff --git a/kmag/main.cpp b/kmag/main.cpp new file mode 100644 index 0000000..f0d0c31 --- /dev/null +++ b/kmag/main.cpp @@ -0,0 +1,81 @@ +/*************************************************************************** + main.cpp - description + ------------------- + begin : Mon Feb 12 23:45:41 EST 2001 + copyright : (C) 2001-2003 by Sarang Lakare + email : sarang#users.sf.net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + + +#include <kcmdlineargs.h> +#include <kaboutdata.h> +#include <klocale.h> + +#include "kmag.h" + +#include "version.h" + +KmagApp *kmagapp; + +// Not needed, not used. +//static const char description[] = +// I18N_NOOP("Kmag"); +// INSERT A DESCRIPTION FOR YOUR APPLICATION HERE + + +static KCmdLineOptions options[] = +{ + { "+[File]", I18N_NOOP("File to open"), 0 }, + KCmdLineLastOption + // INSERT YOUR COMMANDLINE OPTIONS HERE +}; + +int main(int argc, char *argv[]) +{ + // about the application + KAboutData *aboutData = new KAboutData("kmag", I18N_NOOP("KMagnifier"), KMAG_VERSION, + I18N_NOOP("Screen magnifier for the K Desktop Environment (KDE)"), + KAboutData::License_GPL, + "(C) 2001-2003, Sarang Lakare","", + "http://kmag.sourceforge.net"); + + // about the authors + aboutData->addAuthor("Sarang Lakare", + I18N_NOOP("Rewrite and current maintainer"),"[email protected]", + "http://www.cs.sunysb.edu/~lsarang/linux"); + aboutData->addAuthor("Michael Forster", + I18N_NOOP("Original idea and author (KDE1)"), "[email protected]"); + + aboutData->addCredit("Olaf Schmidt", I18N_NOOP("Rework of the user interface, improved selection window, speed optimisation, rotation, bug fixes"), "[email protected]"); + aboutData->addCredit("Claudiu Costin", I18N_NOOP("Some tips"), "[email protected]", + "http://www.ro.kde.org"); + + KCmdLineArgs::init( argc, argv, aboutData ); + KCmdLineArgs::addCmdLineOptions( options ); // Add our own options. + + KApplication app; + + if (app.isRestored()) + { + RESTORE(KmagApp); + } + else + { + kmagapp = new KmagApp(); + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + args->clear(); + } + + return app.exec(); +} diff --git a/kmag/version.h b/kmag/version.h new file mode 100644 index 0000000..cc1a9ce --- /dev/null +++ b/kmag/version.h @@ -0,0 +1,8 @@ +// KMag Version Information +// +#ifndef kmag_version_h +#define kmag_version_h + +#define KMAG_VERSION "1.0" + +#endif /*version_h*/ |