summaryrefslogtreecommitdiffstats
path: root/tools/qvfb
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
commitbd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch)
tree7a520322212d48ebcb9fbe1087e7fca28b76185c /tools/qvfb
downloadqt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz
qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip
Add Qt3 development HEAD version
Diffstat (limited to 'tools/qvfb')
-rw-r--r--tools/qvfb/LICENSE.GPL280
-rw-r--r--tools/qvfb/README55
-rw-r--r--tools/qvfb/config.ui1684
-rw-r--r--tools/qvfb/gammaview.h49
-rw-r--r--tools/qvfb/images/logo.pngbin0 -> 714 bytes
-rw-r--r--tools/qvfb/main.cpp97
-rw-r--r--tools/qvfb/pda.skin15
-rw-r--r--tools/qvfb/pda_down.pngbin0 -> 94345 bytes
-rw-r--r--tools/qvfb/pda_up.pngbin0 -> 92698 bytes
-rw-r--r--tools/qvfb/qanimationwriter.cpp414
-rw-r--r--tools/qvfb/qanimationwriter.h59
-rw-r--r--tools/qvfb/qvfb.cpp389
-rw-r--r--tools/qvfb/qvfb.h91
-rw-r--r--tools/qvfb/qvfb.pro11
-rw-r--r--tools/qvfb/qvfbratedlg.cpp80
-rw-r--r--tools/qvfb/qvfbratedlg.h59
-rw-r--r--tools/qvfb/qvfbview.cpp615
-rw-r--r--tools/qvfb/qvfbview.h126
-rw-r--r--tools/qvfb/skin.cpp174
-rw-r--r--tools/qvfb/skin.h78
20 files changed, 4276 insertions, 0 deletions
diff --git a/tools/qvfb/LICENSE.GPL b/tools/qvfb/LICENSE.GPL
new file mode 100644
index 0000000..3221c03
--- /dev/null
+++ b/tools/qvfb/LICENSE.GPL
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Steet, 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/tools/qvfb/README b/tools/qvfb/README
new file mode 100644
index 0000000..c627041
--- /dev/null
+++ b/tools/qvfb/README
@@ -0,0 +1,55 @@
+Qt/Embedded Virtual Framebuffer
+===============================
+
+Please note that the qvfb program needs to be compiled with the X11 version
+of Qt.
+
+The virtual frame buffer allows a Qt/Embedded program to be developed on your
+desktop machine, without switching between consoles and X11. The virtual
+framebuffer consists of a shared memory region (the virtual frame buffer)
+and a utility to display the framebuffer in a window. The display is updated
+periodically, so you will see discrete snapshots of the framebuffer rather
+than each individual drawing operation. For this reason drawing problems
+such as flickering may not be apparent until the program is run using a real
+framebuffer.
+
+To use the virtual framebuffer:
+
+1. Ensure QT_NO_QWS_VFB is not set in qconfig.h (when you configure Qt,
+ add the -qvfb option).
+2. Start qvfb (qvfb should be compiled as a normal Qt/X11 application,
+ NOT as a Qt/Embedded application!).
+3. Start a Qt/Embedded server (i.e. construct QApplication with
+ QApplication::GuiServer flag, or run a client with the -qws option).
+
+qvfb supports the following command line options:
+
+[-width width] the width of the virtual framebuffer (default: 240).
+[-height height] the height of the virtual framebuffer (default: 320).
+[-depth depth] the depth of the virtual framebuffer (1,4,8 or 32, default: 8).
+[-nocursor] do not display the X11 cursor in the framebuffer window.
+[-qwsdisplay] the Qt/Embedded display ID, e.g. -qwsdisplay :1 (default :0).
+[-skin skinfile] tells qvfb to load a skin file, e.g. -skin pda.skin
+
+Please refer to the file "pda.skin" for an example of what a skin file looks like.
+The format for skin files is:
+ Image filename of skin with buttons in their up positions
+ Image filename of skin with buttons in their down positions
+ X offset of top left corner of the virtual screen on the skin image
+ Y offset of top left corner of the virtual screen on the skin image
+ Width of the virtual screen on the skin image
+ Height of the virtual screen on the skin image
+ Transparancy level of the Virtual Frame Buffer
+ Number of defined button regions
+Then for each button region the format is:
+ Button identifier
+ Qt scan codes to generate for the button
+ Top left X coordinate of the button region
+ Top left Y coordinate of the button region
+ Bottom right X coordinate of the button region
+ Bottom right Y coordinate of the button region
+
+The virtual framebuffer is a development tool only. No security issues have
+been considered in the virtual framebuffer design. It should not be used
+in a production environment and QT_NO_QWS_VFB should always be in force
+in production libraries.
diff --git a/tools/qvfb/config.ui b/tools/qvfb/config.ui
new file mode 100644
index 0000000..dc8a8d3
--- /dev/null
+++ b/tools/qvfb/config.ui
@@ -0,0 +1,1684 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>Config</class>
+<comment>*********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+*********************************************************************</comment>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>Config</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>481</width>
+ <height>645</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Configure</string>
+ </property>
+ <property name="icon">
+ <pixmap>logo.png</pixmap>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QButtonGroup" row="0" column="1">
+ <property name="name">
+ <cstring>ButtonGroup2</cstring>
+ </property>
+ <property name="title">
+ <string>Depth</string>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>depth_1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>19</y>
+ <width>229</width>
+ <height>19</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>1 bit monochrome</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>depth_4gray</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>44</y>
+ <width>229</width>
+ <height>19</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>4 bit grayscale</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>depth_8</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>69</y>
+ <width>229</width>
+ <height>19</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>8 bit</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>depth_12</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>94</y>
+ <width>229</width>
+ <height>19</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>12 (16) bit</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>depth_16</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>119</y>
+ <width>229</width>
+ <height>19</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>16 bit</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>depth_32</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>144</y>
+ <width>229</width>
+ <height>19</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>32 bit</string>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QLayoutWidget" row="4" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>touchScreen</cstring>
+ </property>
+ <property name="text">
+ <string>Emulate touch screen (no mouse move).</string>
+ </property>
+ </widget>
+ <widget class="QGroupBox" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Gamma</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel" row="6" column="0">
+ <property name="name">
+ <cstring>TextLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Blue</string>
+ </property>
+ </widget>
+ <widget class="QSlider" row="6" column="1">
+ <property name="name">
+ <cstring>bslider</cstring>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>127</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>63</red>
+ <green>63</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </active>
+ <disabled>
+ <color>
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>127</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>38</red>
+ <green>38</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </disabled>
+ <inactive>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>127</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>38</red>
+ <green>38</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>170</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </inactive>
+ </palette>
+ </property>
+ <property name="maxValue">
+ <number>400</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLabel" row="6" column="2">
+ <property name="name">
+ <cstring>blabel</cstring>
+ </property>
+ <property name="text">
+ <string>1.0</string>
+ </property>
+ </widget>
+ <spacer row="5" column="1">
+ <property name="name">
+ <cstring>Spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Green</string>
+ </property>
+ </widget>
+ <widget class="QSlider" row="4" column="1">
+ <property name="name">
+ <cstring>gslider</cstring>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>255</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>63</red>
+ <green>255</green>
+ <blue>63</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>127</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </active>
+ <disabled>
+ <color>
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>255</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>38</red>
+ <green>255</green>
+ <blue>38</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>127</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </disabled>
+ <inactive>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>255</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>255</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>38</red>
+ <green>255</green>
+ <blue>38</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>127</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>170</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </inactive>
+ </palette>
+ </property>
+ <property name="maxValue">
+ <number>400</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="2">
+ <property name="name">
+ <cstring>glabel</cstring>
+ </property>
+ <property name="text">
+ <string>1.0</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel7</cstring>
+ </property>
+ <property name="text">
+ <string>All</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>TextLabel8</cstring>
+ </property>
+ <property name="text">
+ <string>1.0</string>
+ </property>
+ </widget>
+ <widget class="QSlider" row="0" column="1">
+ <property name="name">
+ <cstring>gammaslider</cstring>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </active>
+ <disabled>
+ <color>
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </disabled>
+ <inactive>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>170</red>
+ <green>170</green>
+ <blue>170</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </inactive>
+ </palette>
+ </property>
+ <property name="maxValue">
+ <number>400</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Red</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="2">
+ <property name="name">
+ <cstring>rlabel</cstring>
+ </property>
+ <property name="text">
+ <string>1.0</string>
+ </property>
+ </widget>
+ <widget class="QSlider" row="2" column="1">
+ <property name="name">
+ <cstring>rslider</cstring>
+ </property>
+ <property name="palette">
+ <palette>
+ <active>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>63</green>
+ <blue>63</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </active>
+ <disabled>
+ <color>
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>38</green>
+ <blue>38</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>128</red>
+ <green>128</green>
+ <blue>128</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </disabled>
+ <inactive>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>127</green>
+ <blue>127</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>38</green>
+ <blue>38</blue>
+ </color>
+ <color>
+ <red>127</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>170</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>220</red>
+ <green>220</green>
+ <blue>220</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>10</red>
+ <green>95</green>
+ <blue>137</blue>
+ </color>
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </inactive>
+ </palette>
+ </property>
+ <property name="maxValue">
+ <number>400</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="1">
+ <property name="name">
+ <cstring>Spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="8" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>PushButton3</cstring>
+ </property>
+ <property name="text">
+ <string>Set all to 1.0</string>
+ </property>
+ </widget>
+ <widget class="GammaView" row="0" column="3" rowspan="9" colspan="1">
+ <property name="name">
+ <cstring>MyCustomWidget1</cstring>
+ </property>
+ </widget>
+ <spacer row="7" column="1">
+ <property name="name">
+ <cstring>Spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>ButtonGroup1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Size</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>size_240_320</cstring>
+ </property>
+ <property name="text">
+ <string>240x320 "PDA"</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>size_320_240</cstring>
+ </property>
+ <property name="text">
+ <string>320x240 "TV"</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>size_640_480</cstring>
+ </property>
+ <property name="text">
+ <string>640x480 "VGA"</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>size_custom</cstring>
+ </property>
+ <property name="text">
+ <string>Custom</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>size_width</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1280</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="lineStep">
+ <number>16</number>
+ </property>
+ <property name="value">
+ <number>400</number>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>size_height</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1024</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="lineStep">
+ <number>16</number>
+ </property>
+ <property name="value">
+ <number>300</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>size_skin</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Skin</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <item>
+ <property name="text">
+ <string>pda.skin</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>ipaq.skin</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>qpe.skin</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>cassiopeia.skin</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>other.skin</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>skin</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLabel" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;p&gt;Note that any applications using the virtual framebuffer will be terminated if you change the Size or Depth &lt;i&gt;above&lt;/i&gt;. You may freely modify the Gamma &lt;i&gt;below&lt;/i&gt;.</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>GammaView</class>
+ <header location="local">gammaview.h</header>
+ <sizehint>
+ <width>64</width>
+ <height>64</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>3</hordata>
+ <verdata>3</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>Config</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>Config</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<pixmapinproject/>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/tools/qvfb/gammaview.h b/tools/qvfb/gammaview.h
new file mode 100644
index 0000000..b66b03f
--- /dev/null
+++ b/tools/qvfb/gammaview.h
@@ -0,0 +1,49 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef GAMMAVIEW_H
+#define GAMMAVIEW_H
+
+#include <qwidget.h>
+
+class GammaView: public QWidget
+{
+ Q_OBJECT
+public:
+ GammaView( QWidget *parent = 0,
+ const char *name = 0, WFlags f = 0 ) :
+ QWidget(parent,name,f)
+ { }
+};
+
+#endif
diff --git a/tools/qvfb/images/logo.png b/tools/qvfb/images/logo.png
new file mode 100644
index 0000000..0cb2b68
--- /dev/null
+++ b/tools/qvfb/images/logo.png
Binary files differ
diff --git a/tools/qvfb/main.cpp b/tools/qvfb/main.cpp
new file mode 100644
index 0000000..50e11ec
--- /dev/null
+++ b/tools/qvfb/main.cpp
@@ -0,0 +1,97 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qvfb.h"
+
+#include <qapplication.h>
+#include <qpainter.h>
+#include <qregexp.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+void usage( const char *app )
+{
+ printf( "Usage: %s [-width width] [-height height] [-depth depth] "
+ "[-nocursor] [-qwsdisplay :id]\n"
+ "Supported depths: 1, 4, 8, 32\n", app );
+}
+
+int main( int argc, char *argv[] )
+{
+ QApplication app( argc, argv );
+
+ int width = 240;
+ int height = 320;
+ int depth = 32;
+ bool cursor = TRUE;
+ QString displaySpec( ":0" );
+ QString skin;
+
+ for ( int i = 1; i < argc; i++ ){
+ QString arg = argv[i];
+ if ( arg == "-width" ) {
+ width = atoi( argv[++i] );
+ } else if ( arg == "-height" ) {
+ height = atoi( argv[++i] );
+ } else if ( arg == "-skin" ) {
+ skin = argv[++i];
+ } else if ( arg == "-depth" ) {
+ depth = atoi( argv[++i] );
+ } else if ( arg == "-nocursor" ) {
+ cursor = FALSE;
+ } else if ( arg == "-qwsdisplay" ) {
+ displaySpec = argv[++i];
+ } else {
+ printf( "Unknown parameter %s\n", arg.latin1() );
+ usage( argv[0] );
+ exit(1);
+ }
+ }
+
+ int displayId = 0;
+ QRegExp rx( ":[0-9]" );
+ int m = rx.search( displaySpec, 0 );
+ if ( m >= 0 ) {
+ displayId = displaySpec.mid( m+1, rx.matchedLength()-1 ).toInt();
+ }
+
+ qDebug( "Using display %d", displayId );
+
+ QVFb mw( displayId, width, height, depth, skin );
+ app.setMainWidget( &mw );
+ mw.enableCursor(cursor);
+ mw.show();
+
+ return app.exec();
+}
diff --git a/tools/qvfb/pda.skin b/tools/qvfb/pda.skin
new file mode 100644
index 0000000..135e6b6
--- /dev/null
+++ b/tools/qvfb/pda.skin
@@ -0,0 +1,15 @@
+pda_up.png pda_down.png
+57 81
+240 320
+0.5
+11
+"Power" 0x100a 277 36 302 57
+"F1" 0x1030 52 439 81 470
+"F2" 0x1031 101 422 130 451
+"F3" 0x1032 232 423 260 452
+"F4" 0x1033 279 445 309 473
+"Left" 0x1012 155 438 176 472
+"Down" 0x1015 169 471 203 486
+"Right" 0x1014 193 448 215 472
+"Up" 0x1013 166 427 199 451
+"Enter" 0x1005 177 448 193 468
diff --git a/tools/qvfb/pda_down.png b/tools/qvfb/pda_down.png
new file mode 100644
index 0000000..bc1f5ee
--- /dev/null
+++ b/tools/qvfb/pda_down.png
Binary files differ
diff --git a/tools/qvfb/pda_up.png b/tools/qvfb/pda_up.png
new file mode 100644
index 0000000..05e97df
--- /dev/null
+++ b/tools/qvfb/pda_up.png
Binary files differ
diff --git a/tools/qvfb/qanimationwriter.cpp b/tools/qvfb/qanimationwriter.cpp
new file mode 100644
index 0000000..35d6131
--- /dev/null
+++ b/tools/qvfb/qanimationwriter.cpp
@@ -0,0 +1,414 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qanimationwriter.h"
+
+#define QT_CLEAN_NAMESPACE
+#include <qfile.h>
+
+#include <png.h>
+#include <netinet/in.h> // for htonl
+
+class QAnimationWriterData {
+public:
+ QAnimationWriterData(QIODevice* d) : dev(d)
+ {
+ framerate = 1000;
+ }
+ void setFrameRate(int d) { framerate = d; }
+ virtual ~QAnimationWriterData() { }
+ virtual void setImage(const QImage& src)=0;
+ virtual bool canCompose() const { return FALSE; }
+ virtual void composeImage(const QImage&, const QPoint& ) { }
+
+protected:
+ int framerate;
+ QIODevice* dev;
+};
+
+
+class QAnimationWriterMNG : public QAnimationWriterData {
+ bool first;
+ png_structp png_ptr;
+ png_infop info_ptr;
+public:
+ QAnimationWriterMNG(QIODevice* d) : QAnimationWriterData(d)
+ {
+ first = TRUE;
+ begin_png();
+ }
+
+ ~QAnimationWriterMNG()
+ {
+ if ( first ) {
+ // Eh? Not images.
+ QImage dummy(1,1,32);
+ setImage(dummy);
+ }
+ writeMEND();
+ end_png();
+ }
+
+ void begin_png()
+ {
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
+ info_ptr = png_create_info_struct(png_ptr);
+ png_set_compression_level(png_ptr,9);
+ png_set_write_fn(png_ptr, (void*)this, write, 0);
+ }
+
+ void end_png()
+ {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ }
+
+
+ static void write( png_structp png_ptr, png_bytep data, png_size_t length)
+ {
+ QAnimationWriterMNG* that = (QAnimationWriterMNG*)png_get_io_ptr(png_ptr);
+ /*uint nw =*/ that->dev->writeBlock((const char*)data,length);
+ }
+
+ void writePNG(const QImage& image)
+ {
+ info_ptr->channels = 4;
+ png_set_sig_bytes(png_ptr, 8); // Pretend we already wrote the sig
+ png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
+ 8, image.hasAlphaBuffer()
+ ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
+ 0, 0, 0);
+ png_write_info(png_ptr, info_ptr);
+ if ( !image.hasAlphaBuffer() )
+ png_set_filler(png_ptr, 0,
+ QImage::systemByteOrder() == QImage::BigEndian ?
+ PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
+ //if ( QImage::systemByteOrder() == QImage::BigEndian ) {
+ //png_set_swap_alpha(png_ptr);
+ //}
+ if ( QImage::systemByteOrder() == QImage::LittleEndian ) {
+ png_set_bgr(png_ptr);
+ }
+
+ png_bytep* row_pointers;
+ uint height = image.height();
+ uchar** jt = image.jumpTable();
+ row_pointers=new png_bytep[height];
+ uint y;
+ for (y=0; y<height; y++) {
+ row_pointers[y]=jt[y];
+ }
+ png_write_image(png_ptr, row_pointers);
+ delete [] row_pointers;
+ png_write_end(png_ptr, info_ptr);
+ end_png();
+ begin_png();
+ }
+
+ void writeMHDR( const QSize& size, int framerate )
+ {
+ dev->writeBlock("\212MNG\r\n\032\n", 8);
+
+ struct {
+ int width;
+ int height;
+ int framerate;
+ int a,b,c;
+ int profile;
+ } chunk;
+ chunk.width = htonl(size.width());
+ chunk.height = htonl(size.height());
+ chunk.framerate = htonl(framerate);
+ chunk.a=0;
+ chunk.b=0;
+ chunk.c=0;
+ chunk.profile= htonl(0x00000003);
+
+ png_write_chunk(png_ptr, (png_byte*)"MHDR", (png_byte*)&chunk, sizeof(chunk));
+ }
+
+ void writeMEND()
+ {
+ png_write_chunk(png_ptr, (png_byte*)"MEND", 0, 0);
+ }
+
+ void writeDEFI( const QPoint& offset, const QSize& size )
+ {
+ struct {
+ ushort o;
+ uchar s;
+ uchar concrete;
+ int x,y;
+ int lc,rc,tc,bc;
+ } chunk;
+ chunk.o=0;
+ chunk.s=0;
+ chunk.concrete=1;
+ chunk.x=htonl(offset.x());
+ chunk.y=htonl(offset.y());
+ chunk.lc=0;
+ chunk.rc=0;
+ chunk.tc=htonl(INT_MAX);
+ chunk.bc=htonl(INT_MAX);
+
+ png_write_chunk(png_ptr, (png_byte*)"DEFI", (png_byte*)&chunk, sizeof(chunk));
+ }
+
+ void writeFRAM( const QSize& size )
+ {
+ struct {
+ uchar mode;
+ uchar n;
+ uchar nu;
+ uchar d;
+ uchar t;
+ uchar clip;
+ uchar s;
+ uchar deltatype;
+ uint left;
+ uint right;
+ uint top;
+ uint bottom;
+ } chunk;
+ chunk.mode=1;
+ chunk.n='a';
+ chunk.nu=0;
+ chunk.d=0;
+ chunk.clip=1;
+ chunk.t=0;
+ chunk.s=0;
+ chunk.deltatype=0;
+ chunk.left=0;
+ chunk.right=htonl(size.width());
+ chunk.top=0;
+ chunk.bottom=htonl(size.height());
+
+ png_write_chunk(png_ptr, (png_byte*)"FRAM", (png_byte*)&chunk, sizeof(chunk));
+ }
+
+ void writeMOVE( const QPoint& offset )
+ {
+ struct {
+ uchar filler[3];
+ uchar z[5];
+ int x,y;
+ } chunk;
+ memset(chunk.z,0,5);
+ chunk.x=htonl(offset.x());
+ chunk.y=htonl(offset.y());
+
+ png_write_chunk(png_ptr, (png_byte*)"MOVE", ((png_byte*)&chunk)+3, sizeof(chunk)-3);
+ }
+
+ void setImage(const QImage& src)
+ {
+ if ( first ) {
+ first = FALSE;
+ writeMHDR(src.size(),framerate);
+ }
+ composeImage(src,QPoint(0,0));
+ }
+
+ bool canCompose() const { return TRUE; }
+
+ void composeImage(const QImage& src, const QPoint& offset)
+ {
+ writeMOVE(offset);
+ //writeFRAM(src.size());
+ writePNG(src);
+ }
+};
+
+QAnimationWriter::QAnimationWriter( const QString& filename, const char* format )
+{
+ if ( QCString(format) != "MNG" ) {
+ qWarning("Format \"%s\" not supported, only MNG", format);
+ dev = 0;
+ d = 0;
+ } else {
+ QFile *f = new QFile(filename);
+ f->open(IO_WriteOnly);
+ dev = f;
+ d = new QAnimationWriterMNG(dev);
+ }
+}
+
+bool QAnimationWriter::okay() const
+{
+ return dev && dev->status() == IO_Ok;
+}
+
+QAnimationWriter::~QAnimationWriter()
+{
+ delete d;
+ delete dev;
+}
+
+void QAnimationWriter::setFrameRate(int r)
+{
+ if (d) d->setFrameRate(r);
+}
+
+void QAnimationWriter::appendFrame(const QImage& frm, const QPoint& offset)
+{
+ QImage frame = frm.convertDepth(32);
+ const int alignx = 1;
+ if ( dev ) {
+ if ( prev.isNull() || !d->canCompose() ) {
+ d->setImage(frame);
+ } else {
+ bool done;
+ int minx, maxx, miny, maxy;
+ int w = frame.width();
+ int h = frame.height();
+
+ QRgb** jt = (QRgb**)frame.jumpTable();
+ QRgb** pjt = (QRgb**)prev.jumpTable() + offset.y();
+
+ // Find left edge of change
+ done = FALSE;
+ for (minx = 0; minx < w && !done; minx++) {
+ for (int ty = 0; ty < h; ty++) {
+ if ( jt[ty][minx] != pjt[ty][minx+offset.x()] ) {
+ done = TRUE;
+ break;
+ }
+ }
+ }
+ minx--;
+
+ // Find right edge of change
+ done = FALSE;
+ for (maxx = w-1; maxx >= 0 && !done; maxx--) {
+ for (int ty = 0; ty < h; ty++) {
+ if ( jt[ty][maxx] != pjt[ty][maxx+offset.x()] ) {
+ done = TRUE;
+ break;
+ }
+ }
+ }
+ maxx++;
+
+ // Find top edge of change
+ done = FALSE;
+ for (miny = 0; miny < h && !done; miny++) {
+ for (int tx = 0; tx < w; tx++) {
+ if ( jt[miny][tx] != pjt[miny][tx+offset.x()] ) {
+ done = TRUE;
+ break;
+ }
+ }
+ }
+ miny--;
+
+ // Find right edge of change
+ done = FALSE;
+ for (maxy = h-1; maxy >= 0 && !done; maxy--) {
+ for (int tx = 0; tx < w; tx++) {
+ if ( jt[maxy][tx] != pjt[maxy][tx+offset.x()] ) {
+ done = TRUE;
+ break;
+ }
+ }
+ }
+ maxy++;
+
+ if ( minx > maxx ) minx=maxx=0;
+ if ( miny > maxy ) miny=maxy=0;
+
+ if ( alignx > 1 ) {
+ minx -= minx % alignx;
+ maxx = maxx - maxx % alignx + alignx - 1;
+ }
+
+ int dw = maxx-minx+1;
+ int dh = maxy-miny+1;
+
+ QImage diff(dw, dh, 32);
+
+ diff.setAlphaBuffer(TRUE);
+ int x, y;
+ for (y = 0; y < dh; y++) {
+ QRgb* li = (QRgb*)frame.scanLine(y+miny)+minx;
+ QRgb* lp = (QRgb*)prev.scanLine(y+miny+offset.y())+minx+offset.x();
+ QRgb* ld = (QRgb*)diff.scanLine(y);
+ if ( alignx ) {
+ for (x = 0; x < dw; x+=alignx) {
+ int i;
+ for (i=0; i<alignx; i++) {
+ if ( li[x+i] != lp[x+i] )
+ break;
+ }
+ if ( i == alignx ) {
+ // All the same
+ for (i=0; i<alignx; i++) {
+ ld[x+i] = qRgba(0,0,0,0);
+ }
+ } else {
+ // Some different
+ for (i=0; i<alignx; i++) {
+ ld[x+i] = 0xff000000 | li[x+i];
+ }
+ }
+ }
+ } else {
+ for (x = 0; x < dw; x++) {
+ if ( li[x] != lp[x] )
+ ld[x] = 0xff000000 | li[x];
+ else
+ ld[x] = qRgba(0,0,0,0);
+ }
+ }
+ }
+qDebug("%d,%d %d,%d",minx,miny,offset.x(),offset.y());
+ d->composeImage(diff,QPoint(minx,miny)+offset);
+ }
+ if ( prev.isNull() || prev.size() == frame.size() && offset == QPoint(0,0) ) {
+ prev = frame;
+ } else {
+ bitBlt(&prev,offset.x(),offset.y(),&frame,0,0,frame.width(),frame.height());
+ }
+ }
+}
+
+void QAnimationWriter::appendFrame(const QImage& frm)
+{
+ appendFrame(frm,QPoint(0,0));
+}
+
+void QAnimationWriter::appendBlankFrame()
+{
+ QImage i(1,1,32);
+ i.setAlphaBuffer(TRUE);
+ i.fill(0);
+ d->composeImage(i,QPoint(0,0));
+}
diff --git a/tools/qvfb/qanimationwriter.h b/tools/qvfb/qanimationwriter.h
new file mode 100644
index 0000000..2757fa8
--- /dev/null
+++ b/tools/qvfb/qanimationwriter.h
@@ -0,0 +1,59 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#ifndef QANIMATIONWRITER_H
+#define QANIMATIONWRITER_H
+
+#include <qimage.h>
+
+class QAnimationWriterData;
+
+class QAnimationWriter
+{
+public:
+ QAnimationWriter( const QString& filename, const char* format="MNG" );
+ ~QAnimationWriter();
+
+ bool okay() const;
+ void setFrameRate(int);
+ void appendBlankFrame();
+ void appendFrame(const QImage&);
+ void appendFrame(const QImage&, const QPoint& offset);
+
+private:
+ QImage prev;
+ QIODevice* dev;
+ QAnimationWriterData* d;
+};
+
+#endif
diff --git a/tools/qvfb/qvfb.cpp b/tools/qvfb/qvfb.cpp
new file mode 100644
index 0000000..1be15f8
--- /dev/null
+++ b/tools/qvfb/qvfb.cpp
@@ -0,0 +1,389 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qvfb.h"
+#include "qvfbview.h"
+#include "qvfbratedlg.h"
+#include "config.h"
+#include "skin.h"
+
+#include <qmenubar.h>
+#include <qpopupmenu.h>
+#include <qapplication.h>
+#include <qmessagebox.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qfiledialog.h>
+#include <qslider.h>
+#include <qspinbox.h>
+#include <qradiobutton.h>
+#include <qimage.h>
+#include <qpixmap.h>
+#include <qcursor.h>
+#include <qdragobject.h>
+#include <qcheckbox.h>
+
+QVFb::QVFb( int display_id, int w, int h, int d, const QString &skin, QWidget *parent,
+ const char *name, uint flags )
+ : QMainWindow( parent, name, flags )
+{
+ const QMimeSource *m = QMimeSourceFactory::defaultFactory()->data( "logo.png" );
+ if ( m ) {
+ QPixmap pix;
+ QImageDrag::decode( m, pix );
+ setIcon( pix );
+ }
+
+ imagesave = new QFileDialog( this, 0, TRUE );
+
+ rateDlg = 0;
+ view = 0;
+ init( display_id, w, h, d, skin );
+ createMenu( menuBar() );
+ adjustSize();
+}
+
+QVFb::~QVFb()
+{
+}
+
+void QVFb::popupMenu()
+{
+ QPopupMenu *pm = new QPopupMenu( this );
+ createMenu( pm );
+ pm->exec(QCursor::pos());
+}
+
+void QVFb::init( int display_id, int w, int h, int d, const QString &skin_name )
+{
+ setCaption( QString("Virtual framebuffer %1x%2 %3bpp Display :%4")
+ .arg(w).arg(h).arg(d).arg(display_id) );
+ delete view;
+
+ if ( !skin_name.isEmpty() && QFile::exists(skin_name) ) {
+ bool vis = isVisible();
+ if ( vis ) hide();
+ menuBar()->hide();
+ Skin *skin = new Skin( this, skin_name, w, h );
+ view = new QVFbView( display_id, w, h, d, skin );
+ skin->setView( view );
+ view->setMargin( 0 );
+ view->setFrameStyle( QFrame::NoFrame );
+ view->setFixedSize( w, h );
+ setCentralWidget( skin );
+ adjustSize();
+ view->show();
+ if ( vis ) show();
+ } else {
+ if ( !currentSkin.isEmpty() ) {
+ clearMask();
+ reparent( 0, 0, pos(), TRUE );
+ }
+ menuBar()->show();
+ view = new QVFbView( display_id, w, h, d, this );
+ view->setMargin( 0 );
+ view->setFrameStyle( QFrame::NoFrame );
+ setCentralWidget( view );
+ resize( sizeHint() );
+ view->show();
+ }
+
+ currentSkin = skin_name;
+}
+
+void QVFb::enableCursor( bool e )
+{
+ view->viewport()->setCursor( e ? ArrowCursor : BlankCursor );
+ viewMenu->setItemChecked( cursorId, e );
+}
+
+void QVFb::createMenu(QMenuData *menu)
+{
+ QPopupMenu *file = new QPopupMenu( this );
+ file->insertItem( "&Configure...", this, SLOT(configure()), ALT+CTRL+Key_C );
+ file->insertSeparator();
+ file->insertItem( "&Save image...", this, SLOT(saveImage()), ALT+CTRL+Key_S );
+ file->insertItem( "&Animation...", this, SLOT(toggleAnimation()), ALT+CTRL+Key_A );
+ file->insertSeparator();
+ file->insertItem( "&Quit", qApp, SLOT(quit()) );
+
+ menu->insertItem( "&File", file );
+
+ viewMenu = new QPopupMenu( this );
+ viewMenu->setCheckable( TRUE );
+ cursorId = viewMenu->insertItem( "Show &Cursor", this, SLOT(toggleCursor()) );
+ enableCursor(TRUE);
+ viewMenu->insertItem( "&Refresh Rate...", this, SLOT(changeRate()) );
+ viewMenu->insertSeparator();
+ viewMenu->insertItem( "Zoom scale &1", this, SLOT(setZoom1()) );
+ viewMenu->insertItem( "Zoom scale &2", this, SLOT(setZoom2()) );
+ viewMenu->insertItem( "Zoom scale &3", this, SLOT(setZoom3()) );
+ viewMenu->insertItem( "Zoom scale &4", this, SLOT(setZoom4()) );
+ viewMenu->insertItem( "Zoom scale &0.5", this, SLOT(setZoomHalf()) );
+
+ menu->insertItem( "&View", viewMenu );
+
+ QPopupMenu *help = new QPopupMenu( this );
+ help->insertItem("&About", this, SLOT(about()));
+ help->insertItem("About &Qt", this, SLOT(aboutQt()));
+ menu->insertSeparator();
+ menu->insertItem( "&Help", help );
+}
+
+void QVFb::setZoom(double z)
+{
+ view->setZoom(z);
+}
+
+void QVFb::setZoomHalf()
+{
+ setZoom(0.5);
+}
+
+void QVFb::setZoom1()
+{
+ setZoom(1);
+}
+
+void QVFb::setZoom2()
+{
+ setZoom(2);
+}
+
+void QVFb::setZoom3()
+{
+ setZoom(3);
+}
+
+void QVFb::setZoom4()
+{
+ setZoom(4);
+}
+
+void QVFb::saveImage()
+{
+ QImage img = view->image();
+ QString filename = imagesave->getSaveFileName("snapshot.png", "*.png", this, "", "Save Image");
+ if ( !!filename )
+ img.save(filename,"PNG");
+}
+
+void QVFb::toggleAnimation()
+{
+ if ( view->animating() ) {
+ view->stopAnimation();
+ } else {
+ QString filename = imagesave->getSaveFileName("animation.mng", "*.mng", this, "", "Save animation");
+ if ( !filename ) {
+ view->stopAnimation();
+ } else {
+ view->startAnimation(filename);
+ }
+ }
+}
+
+void QVFb::toggleCursor()
+{
+ enableCursor( !viewMenu->isItemChecked( cursorId ) );
+}
+
+void QVFb::changeRate()
+{
+ if ( !rateDlg ) {
+ rateDlg = new QVFbRateDialog( view->rate(), this );
+ connect( rateDlg, SIGNAL(updateRate(int)), view, SLOT(setRate(int)) );
+ }
+
+ rateDlg->show();
+}
+
+void QVFb::about()
+{
+#if defined( Q_WS_MAC )
+ QString platform("Mac OS X");
+ QString qt("Mac");
+#elif defined( Q_WS_WIN )
+ QString platform("Windows");
+ QString qt("Windows");
+#else
+ QString platform("X11");
+ QString qt("X11");
+#endif
+ QMessageBox::about(this, "About QVFB",
+ "<p><b><font size=+2>Qt/Embedded Virtual " + platform + " Framebuffer</font></b></p>"
+ "<p></p>"
+ "<p>Version 1.0</p>"
+ "<p>Copyright (C) 2001-2008 Trolltech ASA. All rights reserved.</p>"
+ "<p></p>"
+ "<p>This program is licensed to you under the terms of the GNU General "
+ "Public License Version 2 as published by the Free Software Foundation. This "
+ "gives you legal permission to copy, distribute and/or modify this software "
+ "under certain conditions. For details, see the file 'LICENSE.GPL' that came with "
+ "this software distribution. If you did not get the file, send email to "
+ "info@trolltech.com.</p>\n\n<p>The program is provided AS IS with NO WARRANTY "
+ "OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS "
+ "FOR A PARTICULAR PURPOSE.</p>"
+ );
+}
+
+void QVFb::aboutQt()
+{
+ QMessageBox::aboutQt( this, tr("QVFB") );
+}
+
+void QVFb::configure()
+{
+ config = new Config(this,0,TRUE);
+
+ int w = view->displayWidth();
+ int h = view->displayHeight();
+ QString skin;
+ config->size_width->setValue(w);
+ config->size_height->setValue(h);
+ config->size_custom->setChecked(TRUE); // unless changed by settings below
+ config->size_240_320->setChecked(w==240&&h==320);
+ config->size_320_240->setChecked(w==320&&h==240);
+ config->size_640_480->setChecked(w==640&&h==480);
+ config->skin->setEditable(TRUE);
+ if (!currentSkin.isNull()) {
+ config->size_skin->setChecked(TRUE);
+ config->skin->setEditText(currentSkin);
+ }
+ config->touchScreen->setChecked(view->touchScreenEmulation());
+ config->depth_1->setChecked(view->displayDepth()==1);
+ config->depth_4gray->setChecked(view->displayDepth()==4);
+ config->depth_8->setChecked(view->displayDepth()==8);
+ config->depth_12->setChecked(view->displayDepth()==12);
+ config->depth_16->setChecked(view->displayDepth()==16);
+ config->depth_32->setChecked(view->displayDepth()==32);
+ if ( view->gammaRed() == view->gammaGreen() && view->gammaGreen() == view->gammaBlue() ) {
+ config->gammaslider->setValue(int(view->gammaRed()*400));
+ config->rslider->setValue(100);
+ config->gslider->setValue(100);
+ config->bslider->setValue(100);
+ } else {
+ config->gammaslider->setValue(100);
+ config->rslider->setValue(int(view->gammaRed()*400));
+ config->gslider->setValue(int(view->gammaGreen()*400));
+ config->bslider->setValue(int(view->gammaBlue()*400));
+ }
+ connect(config->gammaslider, SIGNAL(valueChanged(int)), this, SLOT(setGamma400(int)));
+ connect(config->rslider, SIGNAL(valueChanged(int)), this, SLOT(setR400(int)));
+ connect(config->gslider, SIGNAL(valueChanged(int)), this, SLOT(setG400(int)));
+ connect(config->bslider, SIGNAL(valueChanged(int)), this, SLOT(setB400(int)));
+ updateGammaLabels();
+
+ double ogr=view->gammaRed(), ogg=view->gammaGreen(), ogb=view->gammaBlue();
+
+ if ( config->exec() ) {
+ int id = view->displayId(); // not settable yet
+ if ( config->size_240_320->isChecked() ) {
+ w=240; h=320;
+ } else if ( config->size_320_240->isChecked() ) {
+ w=320; h=240;
+ } else if ( config->size_640_480->isChecked() ) {
+ w=640; h=480;
+ } else if ( config->size_skin->isChecked() ) {
+ skin = config->skin->currentText();
+ } else {
+ w=config->size_width->value();
+ h=config->size_height->value();
+ }
+ int d;
+ if ( config->depth_1->isChecked() )
+ d=1;
+ else if ( config->depth_4gray->isChecked() )
+ d=4;
+ else if ( config->depth_8->isChecked() )
+ d=8;
+ else if ( config->depth_12->isChecked() )
+ d=12;
+ else if ( config->depth_16->isChecked() )
+ d=16;
+ else
+ d=32;
+
+ if ( w != view->displayWidth() || h != view->displayHeight()
+ || d != view->displayDepth() || skin != currentSkin )
+ init( id, w, h, d, skin );
+ view->setTouchscreenEmulation( config->touchScreen->isChecked() );
+ } else {
+ view->setGamma(ogr, ogg, ogb);
+ }
+
+ delete config;
+ config=0;
+}
+
+void QVFb::setGamma400(int n)
+{
+ double g = n/100.0;
+ view->setGamma(config->rslider->value()/100.0*g,
+ config->gslider->value()/100.0*g,
+ config->bslider->value()/100.0*g);
+ updateGammaLabels();
+}
+
+void QVFb::setR400(int n)
+{
+ double g = n/100.0;
+ view->setGamma(config->rslider->value()/100.0*g,
+ view->gammaGreen(),
+ view->gammaBlue());
+ updateGammaLabels();
+}
+
+void QVFb::setG400(int n)
+{
+ double g = n/100.0;
+ view->setGamma(view->gammaRed(),
+ config->gslider->value()/100.0*g,
+ view->gammaBlue());
+ updateGammaLabels();
+}
+
+void QVFb::setB400(int n)
+{
+ double g = n/100.0;
+ view->setGamma(view->gammaRed(),
+ view->gammaGreen(),
+ config->bslider->value()/100.0*g);
+ updateGammaLabels();
+}
+
+void QVFb::updateGammaLabels()
+{
+ config->rlabel->setText(QString::number(view->gammaRed(),'g',2));
+ config->glabel->setText(QString::number(view->gammaGreen(),'g',2));
+ config->blabel->setText(QString::number(view->gammaBlue(),'g',2));
+}
diff --git a/tools/qvfb/qvfb.h b/tools/qvfb/qvfb.h
new file mode 100644
index 0000000..aa959c8
--- /dev/null
+++ b/tools/qvfb/qvfb.h
@@ -0,0 +1,91 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include <qmainwindow.h>
+
+class QVFbView;
+class QVFbRateDialog;
+class QPopupMenu;
+class QMenuData;
+class QFileDialog;
+class Config;
+
+class QVFb: public QMainWindow
+{
+ Q_OBJECT
+public:
+ QVFb( int display_id, int w, int h, int d, const QString &skin, QWidget *parent = 0,
+ const char *name = 0, uint wflags = 0 );
+ ~QVFb();
+
+ void enableCursor( bool e );
+ void popupMenu();
+
+protected slots:
+ void saveImage();
+ void toggleAnimation();
+ void toggleCursor();
+ void changeRate();
+ void about();
+ void aboutQt();
+
+ void configure();
+
+ void setZoom(double);
+ void setZoom1();
+ void setZoom2();
+ void setZoom3();
+ void setZoom4();
+ void setZoomHalf();
+
+protected:
+ void createMenu(QMenuData *menu);
+
+private:
+ void init( int display_id, int w, int h, int d, const QString &skin );
+ QVFbView *view;
+ QVFbRateDialog *rateDlg;
+ QFileDialog* imagesave;
+ QPopupMenu *viewMenu;
+ int cursorId;
+ Config* config;
+ QString currentSkin;
+
+private slots:
+ void setGamma400(int n);
+ void setR400(int n);
+ void setG400(int n);
+ void setB400(int n);
+ void updateGammaLabels();
+};
+
diff --git a/tools/qvfb/qvfb.pro b/tools/qvfb/qvfb.pro
new file mode 100644
index 0000000..7896e7c
--- /dev/null
+++ b/tools/qvfb/qvfb.pro
@@ -0,0 +1,11 @@
+TEMPLATE = app
+CONFIG += qt warn_on release
+HEADERS = qvfb.h qvfbview.h qvfbratedlg.h qanimationwriter.h \
+ gammaview.h skin.h
+SOURCES = qvfb.cpp qvfbview.cpp qvfbratedlg.cpp \
+ main.cpp qanimationwriter.cpp skin.cpp
+INTERFACES = config.ui
+IMAGES = images/logo.png
+TARGET = qvfb
+INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/libpng $$QT_SOURCE_TREE/src/3rdparty/zlib
+DEPENDPATH = ../../include
diff --git a/tools/qvfb/qvfbratedlg.cpp b/tools/qvfb/qvfbratedlg.cpp
new file mode 100644
index 0000000..65c0fe2
--- /dev/null
+++ b/tools/qvfb/qvfbratedlg.cpp
@@ -0,0 +1,80 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qvfbratedlg.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qslider.h>
+#include <qpushbutton.h>
+
+QVFbRateDialog::QVFbRateDialog( int rate, QWidget *parent, const char *name,
+ bool modal )
+ : QDialog( parent, name, modal )
+{
+ oldRate = rate;
+
+ QVBoxLayout *tl = new QVBoxLayout( this, 5 );
+
+ QLabel *label = new QLabel( "Target frame rate:", this );
+ tl->addWidget( label );
+
+ QHBoxLayout *hl = new QHBoxLayout( tl );
+ rateSlider = new QSlider( 1, 100, 10, rate, QSlider::Horizontal, this );
+ hl->addWidget( rateSlider );
+ connect( rateSlider, SIGNAL(valueChanged(int)), this, SLOT(rateChanged(int)) );
+ rateLabel = new QLabel( QString( "%1fps" ).arg(rate), this );
+ hl->addWidget( rateLabel );
+
+ hl = new QHBoxLayout( tl );
+ QPushButton *pb = new QPushButton( "OK", this );
+ connect( pb, SIGNAL(clicked()), this, SLOT(accept()) );
+ hl->addWidget( pb );
+ pb = new QPushButton( "Cancel", this );
+ connect( pb, SIGNAL(clicked()), this, SLOT(cancel()) );
+ hl->addWidget( pb );
+}
+
+void QVFbRateDialog::rateChanged( int r )
+{
+ if ( rateSlider->value() != r )
+ rateSlider->setValue( r );
+ rateLabel->setText( QString( "%1fps" ).arg(r) );
+ emit updateRate(r);
+}
+
+void QVFbRateDialog::cancel()
+{
+ rateChanged( oldRate );
+ reject();
+}
diff --git a/tools/qvfb/qvfbratedlg.h b/tools/qvfb/qvfbratedlg.h
new file mode 100644
index 0000000..e5d02cb
--- /dev/null
+++ b/tools/qvfb/qvfbratedlg.h
@@ -0,0 +1,59 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include <qdialog.h>
+
+class QLabel;
+class QSlider;
+
+class QVFbRateDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ QVFbRateDialog( int value, QWidget *parent=0, const char *name=0,
+ bool modal=FALSE );
+
+signals:
+ void updateRate( int r );
+
+protected slots:
+ void rateChanged( int r );
+ void cancel();
+
+private:
+ QLabel *rateLabel;
+ QSlider *rateSlider;
+ int oldRate;
+};
+
+
diff --git a/tools/qvfb/qvfbview.cpp b/tools/qvfb/qvfbview.cpp
new file mode 100644
index 0000000..781cf78
--- /dev/null
+++ b/tools/qvfb/qvfbview.cpp
@@ -0,0 +1,615 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qglobal.h"
+#if !defined( Q_WS_QWS ) || defined( QT_NO_QWS_MULTIPROCESS )
+#define QLock QWSSemaphore
+#undef QT_NO_QWS_MULTIPROCESS
+#include "../../src/kernel/qlock.cpp"
+#else
+#include "qlock_p.h"
+#endif
+
+#include "qvfbview.h"
+#include "qvfbhdr.h"
+
+#define QTE_PIPE "QtEmbedded-%1"
+
+#include <qapplication.h>
+#include <qimage.h>
+#include <qbitmap.h>
+#include <qtimer.h>
+#include <qwmatrix.h>
+#include <qpainter.h>
+#include "qanimationwriter.h"
+
+#include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <math.h>
+
+//#define QT_QWS_EXPERIMENTAL_REVERSE_BIT_ENDIANNESS
+
+QVFbView::QVFbView( int display_id, int w, int h, int d, QWidget *parent,
+ const char *name, uint flags )
+ : QScrollView( parent, name, flags ), emulateTouchscreen(FALSE), qwslock(NULL)
+{
+ displayid = display_id;
+ viewport()->setMouseTracking( TRUE );
+ viewport()->setFocusPolicy( StrongFocus );
+ zm = 1;
+ animation = 0;
+ int actualdepth=d;
+
+ switch ( d ) {
+ case 12:
+ actualdepth=16;
+ break;
+ case 1:
+ case 4:
+ case 8:
+ case 16:
+ case 32:
+ break;
+
+ default:
+ qFatal( "Unsupported bit depth %d\n", d );
+ }
+
+ mousePipe = QString(QT_VFB_MOUSE_PIPE).arg(display_id);
+ keyboardPipe = QString(QT_VFB_KEYBOARD_PIPE).arg(display_id);
+
+ unlink( mousePipe.latin1() );
+ mkfifo( mousePipe.latin1(), 0666 );
+
+ mouseFd = open( mousePipe.latin1(), O_RDWR | O_NDELAY );
+ if ( mouseFd == -1 ) {
+ qFatal( "Cannot open mouse pipe" );
+ }
+
+ unlink( keyboardPipe );
+ mkfifo( keyboardPipe, 0666 );
+ keyboardFd = open( keyboardPipe, O_RDWR | O_NDELAY );
+ if ( keyboardFd == -1 ) {
+ qFatal( "Cannot open keyboard pipe" );
+ }
+
+ key_t key = ftok( mousePipe.latin1(), 'b' );
+
+ int bpl;
+ if ( d == 1 )
+ bpl = (w*d+7)/8;
+ else
+ bpl = ((w*actualdepth+31)/32)*4;
+
+ int dataSize = bpl * h + sizeof( QVFbHeader );
+ shmId = shmget( key, dataSize, IPC_CREAT|0666);
+ if ( shmId != -1 )
+ data = (unsigned char *)shmat( shmId, 0, 0 );
+ else {
+ struct shmid_ds shm;
+ shmctl( shmId, IPC_RMID, &shm );
+ shmId = shmget( key, dataSize, IPC_CREAT|0666);
+ data = (unsigned char *)shmat( shmId, 0, 0 );
+ }
+
+ if ( (long)data == -1 )
+ qFatal( "Cannot attach to shared memory" );
+
+ hdr = (QVFbHeader *)data;
+ hdr->width = w;
+ hdr->height = h;
+ viewdepth = d;
+ hdr->depth = actualdepth;
+ hdr->linestep = bpl;
+ hdr->numcols = 0;
+ hdr->dataoffset = sizeof( QVFbHeader );
+ hdr->update = QRect();
+
+ resizeContents( w, h );
+
+ timer = new QTimer( this );
+ connect( timer, SIGNAL(timeout()), this, SLOT(timeout()) );
+
+ gammatable=0;
+ setGamma(1.0,1.0,1.0);
+ setRate( 30 );
+}
+
+QVFbView::~QVFbView()
+{
+ stopAnimation();
+ sendKeyboardData( 0, 0, 0, TRUE, FALSE ); // magic die key
+ delete qwslock;
+ struct shmid_ds shm;
+ shmdt( (char*)data );
+ shmctl( shmId, IPC_RMID, &shm );
+ ::close( mouseFd );
+ ::close( keyboardFd );
+ unlink( mousePipe );
+ unlink( keyboardPipe );
+}
+
+QSize QVFbView::sizeHint() const
+{
+ int f = 2 * frameWidth();
+ return QSize( contentsWidth() + f, contentsHeight() + f );
+}
+
+void QVFbView::setGamma(double gr, double gg, double gb)
+{
+ if ( viewdepth < 12 )
+ return; // not implemented
+
+ gred=gr; ggreen=gg; gblue=gb;
+
+ switch ( viewdepth ) {
+ case 12:
+ rsh = 12;
+ gsh = 7;
+ bsh = 1;
+ rmax = 15;
+ gmax = 15;
+ bmax = 15;
+ break;
+ case 16:
+ rsh = 11;
+ gsh = 5;
+ bsh = 0;
+ rmax = 31;
+ gmax = 63;
+ bmax = 31;
+ break;
+ case 32:
+ rsh = 16;
+ gsh = 8;
+ bsh = 0;
+ rmax = 255;
+ gmax = 255;
+ bmax = 255;
+ }
+ int mm = QMAX(rmax,QMAX(gmax,bmax))+1;
+ if ( gammatable )
+ delete [] gammatable;
+ gammatable = new QRgb[mm];
+ for (int i=0; i<mm; i++) {
+ int r = int(pow(i,gr)*255/rmax);
+ int g = int(pow(i,gg)*255/gmax);
+ int b = int(pow(i,gb)*255/bmax);
+ if ( r > 255 ) r = 255;
+ if ( g > 255 ) g = 255;
+ if ( b > 255 ) b = 255;
+ gammatable[i] = qRgb(r,g,b);
+//qDebug("%d: %d,%d,%d",i,r,g,b);
+ }
+
+ setDirty(rect());
+}
+
+void QVFbView::getGamma(int i, QRgb& rgb)
+{
+ if ( i > 255 ) i = 255;
+ if ( i < 0 ) i = 0;
+ rgb = qRgb(qRed(gammatable[i*rmax/255]),
+ qGreen(gammatable[i*rmax/255]),
+ qBlue(gammatable[i*rmax/255]));
+}
+
+int QVFbView::displayId() const
+{
+ return displayid;
+}
+
+int QVFbView::displayWidth() const
+{
+ return hdr->width;
+}
+
+int QVFbView::displayHeight() const
+{
+ return hdr->height;
+}
+
+int QVFbView::displayDepth() const
+{
+ return viewdepth;
+}
+
+void QVFbView::setZoom( double z )
+{
+ if ( zm != z ) {
+ zm = z;
+ setDirty(QRect(0,0,hdr->width,hdr->height));
+ resizeContents( int(hdr->width*z), int(hdr->height*z) );
+ updateGeometry();
+ qApp->sendPostedEvents();
+ topLevelWidget()->adjustSize();
+ drawScreen();
+ }
+}
+
+void QVFbView::setRate( int r )
+{
+ refreshRate = r;
+ timer->start( 1000/r );
+}
+
+#ifndef Q_WS_QWS
+// Get the name of the directory where Qt/Embedded temporary data should
+// live.
+static QString qws_dataDir()
+{
+ QString username = "unknown";
+ const char *logname = getenv("LOGNAME");
+ if ( logname )
+ username = logname;
+
+ QString dataDir = "/tmp/qtembedded-" + username;
+ if ( mkdir( dataDir.latin1(), 0700 ) ) {
+ if ( errno != EEXIST ) {
+ qFatal( QString("Cannot create Qt/Embedded data directory: %1")
+ .arg( dataDir ) );
+ }
+ }
+
+ struct stat buf;
+ if ( lstat( dataDir.latin1(), &buf ) )
+ qFatal( QString( "stat failed for Qt/Embedded data directory: %1" )
+ .arg( dataDir ) );
+
+ if ( !S_ISDIR( buf.st_mode ) )
+ qFatal( QString( "%1 is not a directory" ).arg( dataDir ) );
+
+ if ( buf.st_uid != getuid() )
+ qFatal( QString( "Qt/Embedded data directory is not owned by user %1" )
+ .arg( getuid() ) );
+
+ if ( (buf.st_mode & 0677) != 0600 )
+ qFatal( QString( "Qt/Embedded data directory has incorrect permissions: %1" )
+ .arg( dataDir ) );
+
+ dataDir += "/";
+
+ return dataDir;
+}
+#endif
+
+void QVFbView::initLock()
+{
+ QString username = "unknown";
+ const char *logname = getenv("LOGNAME");
+ if ( logname )
+ username = logname;
+ qwslock = new QLock(qws_dataDir() + QString( QTE_PIPE ).arg( displayid ),
+ 'd', TRUE);
+}
+
+void QVFbView::lock()
+{
+ if ( !qwslock )
+ initLock();
+ qwslock->lock(QLock::Read);
+}
+
+void QVFbView::unlock()
+{
+ if ( qwslock )
+ qwslock->unlock();
+}
+
+void QVFbView::sendMouseData( const QPoint &pos, int buttons )
+{
+ write( mouseFd, &pos, sizeof( QPoint ) );
+ write( mouseFd, &buttons, sizeof( int ) );
+}
+
+void QVFbView::sendKeyboardData( int unicode, int keycode, int modifiers,
+ bool press, bool repeat )
+{
+ QVFbKeyData kd;
+ kd.unicode = unicode | (keycode << 16);
+ kd.modifiers = modifiers;
+ kd.press = press;
+ kd.repeat = repeat;
+ write( keyboardFd, &kd, sizeof( QVFbKeyData ) );
+}
+
+void QVFbView::timeout()
+{
+ lock();
+ if ( animation ) {
+ QRect r( hdr->update );
+ r = r.intersect( QRect(0, 0, hdr->width, hdr->height ) );
+ if ( r.isEmpty() ) {
+ animation->appendBlankFrame();
+ } else {
+ int l;
+ QImage img = getBuffer( r, l );
+ animation->appendFrame(img,QPoint(r.x(),r.y()));
+ }
+ }
+ if ( hdr->dirty ) {
+ drawScreen();
+ }
+ unlock();
+}
+
+QImage QVFbView::getBuffer( const QRect &r, int &leading ) const
+{
+ switch ( viewdepth ) {
+ case 12:
+ case 16: {
+ static unsigned char *imgData = 0;
+ if ( !imgData ) {
+ int bpl = ((hdr->width*32+31)/32)*4;
+ imgData = new unsigned char [ bpl * hdr->height ];
+ }
+ QImage img( imgData, r.width(), r.height(), 32, 0, 0, QImage::IgnoreEndian );
+ const int rsh = viewdepth == 12 ? 12 : 11;
+ const int gsh = viewdepth == 12 ? 7 : 5;
+ const int bsh = viewdepth == 12 ? 1 : 0;
+ const int rmax = viewdepth == 12 ? 15 : 31;
+ const int gmax = viewdepth == 12 ? 15 : 63;
+ const int bmax = viewdepth == 12 ? 15 : 31;
+ for ( int row = 0; row < r.height(); row++ ) {
+ QRgb *dptr = (QRgb*)img.scanLine( row );
+ ushort *sptr = (ushort*)(data + hdr->dataoffset + (r.y()+row)*hdr->linestep);
+ sptr += r.x();
+#ifdef QT_QWS_REVERSE_BYTE_ENDIANNESS
+ for ( int col=0; col < r.width()/2; col++ ) {
+#else
+ for ( int col=0; col < r.width(); col++ ) {
+#endif
+ ushort s = *sptr++;
+#ifdef QT_QWS_REVERSE_BYTE_ENDIANNESS
+ ushort s2 = *sptr++;
+ *dptr++ = qRgb(qRed(gammatable[(s2>>rsh)&rmax]),qGreen(gammatable[(s2>>gsh)&gmax]),qBlue(gammatable[(s2>>bsh)&bmax]));
+#endif
+ *dptr++ = qRgb(qRed(gammatable[(s>>rsh)&rmax]),qGreen(gammatable[(s>>gsh)&gmax]),qBlue(gammatable[(s>>bsh)&bmax]));
+ //*dptr++ = qRgb(((s>>rsh)&rmax)*255/rmax,((s>>gsh)&gmax)*255/gmax,((s>>bsh)&bmax)*255/bmax);
+ }
+ }
+ leading = 0;
+ return img;
+ }
+ case 4: {
+ static unsigned char *imgData = 0;
+ if ( !imgData ) {
+ int bpl = ((hdr->width*8+31)/32)*4;
+ imgData = new unsigned char [ bpl * hdr->height ];
+ }
+ QImage img( imgData, r.width(), r.height(), 8, hdr->clut, 16,
+ QImage::IgnoreEndian );
+ for ( int row = 0; row < r.height(); row++ ) {
+ unsigned char *dptr = img.scanLine( row );
+ unsigned char *sptr = data + hdr->dataoffset + (r.y()+row)*hdr->linestep;
+ sptr += r.x()/2;
+ int col = 0;
+#ifdef QT_QWS_EXPERIMENTAL_REVERSE_BIT_ENDIANNESS
+ if ( r.x() & 1 ) {
+ *dptr++ = *sptr++ & 0x0f;
+ col++;
+ }
+ for ( ; col < r.width()-1; col+=2 ) {
+ unsigned char s = *sptr++;
+ *dptr++ = s >> 4;
+ *dptr++ = s & 0x0f;
+ }
+ if ( !(r.right() & 1) )
+ *dptr = *sptr >> 4;
+#else
+ if ( r.x() & 1 ) {
+ *dptr++ = *sptr++ >> 4;
+ col++;
+ }
+ for ( ; col < r.width()-1; col+=2 ) {
+ unsigned char s = *sptr++;
+ *dptr++ = s & 0x0f;
+ *dptr++ = s >> 4;
+ }
+ if ( !(r.right() & 1) )
+ *dptr = *sptr & 0x0f;
+#endif
+ }
+ leading = 0;
+ return img;
+ }
+ case 32: {
+ leading = r.x();
+ return QImage( data + hdr->dataoffset + r.y() * hdr->linestep,
+ hdr->width, r.height(), hdr->depth, 0,
+ 0, QImage::LittleEndian );
+ }
+ case 8: {
+ leading = r.x();
+ return QImage( data + hdr->dataoffset + r.y() * hdr->linestep,
+ hdr->width, r.height(), hdr->depth, hdr->clut,
+ 256, QImage::LittleEndian );
+ }
+ case 1: {
+ leading = r.x();
+ return QImage( data + hdr->dataoffset + r.y() * hdr->linestep,
+ hdr->width, r.height(), hdr->depth, hdr->clut,
+#ifndef QT_QWS_EXPERIMENTAL_REVERSE_BIT_ENDIANNESS
+ 0, QImage::LittleEndian );
+#else
+ 0, QImage::BigEndian );
+#endif
+ }
+ }
+ return QImage();
+}
+
+void QVFbView::drawScreen()
+{
+ QPainter p( viewport() );
+
+ p.translate( -contentsX(), -contentsY() );
+
+ lock();
+ QRect r( hdr->update );
+ hdr->dirty = FALSE;
+ hdr->update = QRect();
+ // qDebug( "update %d, %d, %dx%d", r.y(), r.x(), r.width(), r.height() );
+ r = r.intersect( QRect(0, 0, hdr->width, hdr->height ) );
+ if ( !r.isEmpty() ) {
+ if ( int(zm) != zm ) {
+ r.rLeft() = int(int(r.left()*zm)/zm);
+ r.rTop() = int(int(r.top()*zm)/zm);
+ r.rRight() = int(int(r.right()*zm+zm+0.0000001)/zm+1.9999);
+ r.rBottom() = int(int(r.bottom()*zm+zm+0.0000001)/zm+1.9999);
+ r.rRight() = QMIN(r.right(),hdr->width-1);
+ r.rBottom() = QMIN(r.bottom(),hdr->height-1);
+ }
+ int leading;
+ QImage img( getBuffer( r, leading ) );
+ QPixmap pm;
+ if ( zm == 1 ) {
+ pm.convertFromImage( img );
+ } else if ( int(zm) == zm ) {
+ QWMatrix m;
+ m.scale(zm,zm);
+ pm.convertFromImage( img );
+ pm = pm.xForm(m);
+ } else {
+ pm.convertFromImage( img.smoothScale(int(img.width()*zm),int(img.height()*zm)) );
+ }
+ unlock();
+ p.setPen( black );
+ p.setBrush( white );
+ p.drawPixmap( int(r.x()*zm), int(r.y()*zm), pm,
+ int(leading*zm), 0, pm.width(), pm.height() );
+ } else {
+ unlock();
+ }
+}
+
+bool QVFbView::eventFilter( QObject *obj, QEvent *e )
+{
+ if ( obj == viewport() &&
+ (e->type() == QEvent::FocusIn || e->type() == QEvent::FocusOut) )
+ return TRUE;
+
+ return QScrollView::eventFilter( obj, e );
+}
+
+void QVFbView::viewportPaintEvent( QPaintEvent *pe )
+{
+ QRect r( pe->rect() );
+ r.moveBy( contentsX(), contentsY() );
+ r = QRect(int(r.x()/zm),int(r.y()/zm),
+ int(r.width()/zm)+1,int(r.height()/zm)+1);
+ setDirty(r);
+ drawScreen();
+}
+
+void QVFbView::setDirty( const QRect& r )
+{
+ lock();
+ hdr->update |= r;
+ hdr->dirty = TRUE;
+ unlock();
+}
+
+void QVFbView::contentsMousePressEvent( QMouseEvent *e )
+{
+ sendMouseData( e->pos()/zm, e->stateAfter() );
+}
+
+void QVFbView::contentsMouseDoubleClickEvent( QMouseEvent *e )
+{
+ sendMouseData( e->pos()/zm, e->stateAfter() );
+}
+
+void QVFbView::contentsMouseReleaseEvent( QMouseEvent *e )
+{
+ sendMouseData( e->pos()/zm, e->stateAfter() );
+}
+
+void QVFbView::contentsMouseMoveEvent( QMouseEvent *e )
+{
+ if ( !emulateTouchscreen || (e->state() & MouseButtonMask ) )
+ sendMouseData( e->pos()/zm, e->state() );
+}
+
+
+
+void QVFbView::keyPressEvent( QKeyEvent *e )
+{
+ sendKeyboardData(e->text()[0].unicode(), e->key(),
+ e->stateAfter()&(ShiftButton|ControlButton|AltButton),
+ TRUE, e->isAutoRepeat());
+}
+
+void QVFbView::keyReleaseEvent( QKeyEvent *e )
+{
+ sendKeyboardData(e->ascii(), e->key(),
+ e->stateAfter()&(ShiftButton|ControlButton|AltButton),
+ FALSE, e->isAutoRepeat());
+}
+
+
+QImage QVFbView::image() const
+{
+ ((QVFbView*)this)->lock();
+ int l;
+ QImage r = getBuffer( QRect(0, 0, hdr->width, hdr->height), l ).copy();
+ ((QVFbView*)this)->unlock();
+ return r;
+}
+
+void QVFbView::startAnimation( const QString& filename )
+{
+ delete animation;
+ animation = new QAnimationWriter(filename,"MNG");
+ animation->setFrameRate(refreshRate);
+ animation->appendFrame(QImage(data + hdr->dataoffset,
+ hdr->width, hdr->height, hdr->depth, hdr->clut,
+ 256, QImage::LittleEndian));
+}
+
+void QVFbView::stopAnimation()
+{
+ delete animation;
+ animation = 0;
+}
+
+void QVFbView::setTouchscreenEmulation( bool b )
+{
+ emulateTouchscreen = b;
+}
diff --git a/tools/qvfb/qvfbview.h b/tools/qvfb/qvfbview.h
new file mode 100644
index 0000000..69acddc
--- /dev/null
+++ b/tools/qvfb/qvfbview.h
@@ -0,0 +1,126 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include <qscrollview.h>
+
+class QImage;
+class QTimer;
+class QAnimationWriter;
+class QLock;
+struct QVFbHeader;
+
+class QVFbView : public QScrollView
+{
+ Q_OBJECT
+public:
+ QVFbView( int display_id, int w, int h, int d, QWidget *parent = 0,
+ const char *name = 0, uint wflags = 0 );
+ ~QVFbView();
+
+ int displayId() const;
+ int displayWidth() const;
+ int displayHeight() const;
+ int displayDepth() const;
+
+ bool touchScreenEmulation() const { return emulateTouchscreen; }
+ int rate() { return refreshRate; }
+ bool animating() const { return !!animation; }
+ QImage image() const;
+
+ void setGamma(double gr, double gg, double gb);
+ double gammaRed() const { return gred; }
+ double gammaGreen() const { return ggreen; }
+ double gammaBlue() const { return gblue; }
+ void getGamma(int i, QRgb& rgb);
+ void skinKeyPressEvent( QKeyEvent *e ) { keyPressEvent(e); }
+ void skinKeyReleaseEvent( QKeyEvent *e ) { keyReleaseEvent(e); }
+
+ double zoom() const { return zm; }
+
+ QSize sizeHint() const;
+public slots:
+ void setTouchscreenEmulation( bool );
+
+ void setRate( int );
+ void setZoom( double );
+ void startAnimation( const QString& );
+ void stopAnimation();
+
+protected slots:
+ void timeout();
+
+protected:
+ void initLock();
+ void lock();
+ void unlock();
+ QImage getBuffer( const QRect &r, int &leading ) const;
+ void drawScreen();
+ void sendMouseData( const QPoint &pos, int buttons );
+ void sendKeyboardData( int unicode, int keycode, int modifiers,
+ bool press, bool repeat );
+ virtual bool eventFilter( QObject *obj, QEvent *e );
+ virtual void viewportPaintEvent( QPaintEvent *pe );
+ virtual void contentsMousePressEvent( QMouseEvent *e );
+ virtual void contentsMouseDoubleClickEvent( QMouseEvent *e );
+ virtual void contentsMouseReleaseEvent( QMouseEvent *e );
+ virtual void contentsMouseMoveEvent( QMouseEvent *e );
+ virtual void keyPressEvent( QKeyEvent *e );
+ virtual void keyReleaseEvent( QKeyEvent *e );
+
+private:
+ bool emulateTouchscreen;
+ void setDirty( const QRect& );
+ int shmId;
+ unsigned char *data;
+ QVFbHeader *hdr;
+ int viewdepth; // "faked" depth
+ int rsh;
+ int gsh;
+ int bsh;
+ int rmax;
+ int gmax;
+ int bmax;
+ double gred, ggreen, gblue;
+ QRgb* gammatable;
+ QLock *qwslock;
+ QTimer *timer;
+ int mouseFd;
+ int keyboardFd;
+ int refreshRate;
+ QString mousePipe;
+ QString keyboardPipe;
+ QAnimationWriter *animation;
+ int displayid;
+ double zm;
+};
+
diff --git a/tools/qvfb/skin.cpp b/tools/qvfb/skin.cpp
new file mode 100644
index 0000000..6322750
--- /dev/null
+++ b/tools/qvfb/skin.cpp
@@ -0,0 +1,174 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "skin.h"
+#include "qvfb.h"
+#include "qvfbview.h"
+
+#include <qbitmap.h>
+#include <qpixmap.h>
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qpainter.h>
+#ifdef Q_WS_MAC
+# include <qt_mac.h>
+#endif
+
+Skin::Skin( QVFb *p, const QString &skinFile, int &viewW, int &viewH ) : QWidget(p)
+{
+ QFile f( skinFile );
+ f.open( IO_ReadOnly );
+ QTextStream ts( &f );
+ ts >> skinImageUpFileName;
+ ts >> skinImageDownFileName;
+ ts >> viewX1;
+ ts >> viewY1;
+ ts >> viewW;
+ ts >> viewH;
+ ts >> transparancy;
+ ts >> numberOfAreas;
+// Debug the skin file parsing
+// printf("read: -%s- -%i- -%i- -%i-\n", skinImage.latin1(), viewX1, viewY1, numberOfAreas );
+ areas = new ButtonAreas[numberOfAreas];
+
+ for (int i = 0; i < numberOfAreas; i++) {
+ ts >> areas[i].name;
+ ts >> areas[i].keyCode;
+ ts >> areas[i].x1;
+ ts >> areas[i].y1;
+ ts >> areas[i].x2;
+ ts >> areas[i].y2;
+// Debug the skin file parsing
+// printf("read: -%s- -%i- -%i- -%i- -%i- -%i-\n", areas[i].name.latin1(),
+// areas[i].keyCode, areas[i].x1, areas[i].y1, areas[i].x2, areas[i].y2 );
+ }
+
+ parent = p;
+ skinImageUp = new QPixmap( skinImageUpFileName );
+ skinImageDown = new QPixmap( skinImageDownFileName );
+// setPixmap( ipaq );
+ setFixedSize( skinImageUp->size() );
+ QBitmap mask = skinImageUp->createHeuristicMask();
+ int wf = WStyle_Customize | WType_TopLevel | WStyle_NoBorder;
+ parent->reparent( 0, wf, pos(), TRUE );
+ parent->setMask( mask );
+ parent->setFixedSize( skinImageUp->size() );
+ buttonPressed = FALSE;
+ buttonIndex = 0;
+}
+
+
+Skin::~Skin( )
+{
+}
+
+
+void Skin::setView( QVFbView *v )
+{
+ view = v;
+ view->move( viewX1, viewY1 );
+#ifdef Q_WS_MAC
+ QMacSavedPortInfo::setAlphaTransparancy(view, transparancy);
+#endif
+}
+
+
+void Skin::paintEvent( QPaintEvent * )
+{
+ QPainter p( this );
+// printf("read: -%s-\n", skinImageUp.latin1());
+ if (skinImageUp)
+ p.drawPixmap( 0, 0, *skinImageUp );
+ if (buttonPressed == TRUE) {
+ ButtonAreas *ba = &areas[buttonIndex];
+ if (skinImageDown)
+ p.drawPixmap( ba->x1, ba->y1, *skinImageDown, ba->x1, ba->y1, ba->x2 - ba->x1, ba->y2 - ba->y1 );
+ }
+}
+
+
+void Skin::mousePressEvent( QMouseEvent *e )
+{
+ if (e->button() == RightButton) {
+ parent->popupMenu();
+ } else {
+ buttonPressed = FALSE;
+
+ for (int i = 0; i < numberOfAreas; i++) {
+ QPoint p1( areas[i].x1, areas[i].y1 );
+ QPoint p2( areas[i].x2, areas[i].y2 );
+ QRect r( p1, p2 );
+ if ( r.contains( e->pos() ) ) {
+ buttonPressed = TRUE;
+ buttonIndex = i;
+ buttonCode = areas[buttonIndex].keyCode;
+ QKeyEvent keyEvent( QEvent::KeyPress, buttonCode, 0, 0 );
+ if (view)
+ view->skinKeyPressEvent( &keyEvent );
+// Debug message to be sure we are clicking the right areas
+// printf("%s clicked\n", areas[i].name);
+ ButtonAreas *ba = &areas[buttonIndex];
+ repaint( ba->x1, ba->y1, ba->x2 - ba->x1, ba->y2 - ba->y1, FALSE );
+ continue;
+ }
+ }
+
+// This is handy for finding the areas to define rectangles for new skins
+// printf("Clicked in %i,%i\n", e->pos().x(), e->pos().y());
+ clickPos = e->pos();
+ }
+}
+
+
+void Skin::mouseMoveEvent( QMouseEvent *e )
+{
+ if ( buttonPressed == FALSE ) {
+ QPoint newpos = e->globalPos() - clickPos;
+ parent->move( newpos );
+ }
+}
+
+
+void Skin::mouseReleaseEvent( QMouseEvent * )
+{
+ if ( buttonPressed ) {
+ QKeyEvent keyEvent( QEvent::KeyRelease, buttonCode, 0, 0 );
+ if (view)
+ view->skinKeyReleaseEvent( &keyEvent );
+ buttonPressed = FALSE;
+ ButtonAreas *ba = &areas[buttonIndex];
+ repaint( ba->x1, ba->y1, ba->x2 - ba->x1, ba->y2 - ba->y1, FALSE );
+ }
+}
+
+
diff --git a/tools/qvfb/skin.h b/tools/qvfb/skin.h
new file mode 100644
index 0000000..7a5b287
--- /dev/null
+++ b/tools/qvfb/skin.h
@@ -0,0 +1,78 @@
+/**********************************************************************
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of Qt/Embedded virtual framebuffer.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with
+** the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include <qwidget.h>
+
+
+class QVFb;
+class QVFbView;
+
+
+class Skin : public QWidget
+{
+public:
+ Skin( QVFb *p, const QString &skinFile, int &viewW, int &viewH );
+ ~Skin( );
+ void setView( QVFbView *v );
+protected:
+ virtual void paintEvent( QPaintEvent * );
+ virtual void mousePressEvent( QMouseEvent *e );
+ virtual void mouseMoveEvent( QMouseEvent *e );
+ virtual void mouseReleaseEvent( QMouseEvent * );
+private:
+ QVFb *parent;
+ QVFbView *view;
+ QPoint clickPos;
+ bool buttonPressed;
+ int buttonCode;
+ int buttonIndex;
+ float transparancy;
+
+ QString skinImageUpFileName;
+ QString skinImageDownFileName;
+ QPixmap *skinImageUp;
+ QPixmap *skinImageDown;
+ int viewX1, viewY1;
+ int numberOfAreas;
+
+ typedef struct {
+ QString name;
+ int keyCode;
+ int x1, y1;
+ int x2, y2;
+ } ButtonAreas;
+
+ ButtonAreas *areas;
+};
+
+