summaryrefslogtreecommitdiffstats
path: root/kandy
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 (patch)
tree67208f7c145782a7e90b123b982ca78d88cc2c87 /kandy
downloadtdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.tar.gz
tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kandy')
-rw-r--r--kandy/AUTHORS2
-rw-r--r--kandy/COPYING339
-rw-r--r--kandy/Makefile.am6
-rw-r--r--kandy/README15
-rw-r--r--kandy/RELEASENOTES76
-rw-r--r--kandy/TODO13
-rw-r--r--kandy/configure.in.in12
-rw-r--r--kandy/profiles/Makefile.am4
-rw-r--r--kandy/profiles/default.kandy27
-rw-r--r--kandy/src/Makefile.am38
-rw-r--r--kandy/src/atcommand.cpp313
-rw-r--r--kandy/src/atcommand.h111
-rw-r--r--kandy/src/cmdpropertiesdialog.cpp120
-rw-r--r--kandy/src/cmdpropertiesdialog.h50
-rw-r--r--kandy/src/cmdpropertiesdialog_base.ui172
-rw-r--r--kandy/src/commanditem.cpp102
-rw-r--r--kandy/src/commanditem.h57
-rw-r--r--kandy/src/commandscheduler.cpp140
-rw-r--r--kandy/src/commandscheduler.h76
-rw-r--r--kandy/src/commandset.cpp154
-rw-r--r--kandy/src/commandset.h61
-rw-r--r--kandy/src/kandy.cpp348
-rw-r--r--kandy/src/kandy.desktop121
-rw-r--r--kandy/src/kandy.h138
-rw-r--r--kandy/src/kandy.kcfg180
-rw-r--r--kandy/src/kandy_client.cpp48
-rw-r--r--kandy/src/kandyiface.h39
-rw-r--r--kandy/src/kandymobileui.rc8
-rw-r--r--kandy/src/kandyprefs.kcfgc11
-rw-r--r--kandy/src/kandyprefsdialog.cpp369
-rw-r--r--kandy/src/kandyprefsdialog.h102
-rw-r--r--kandy/src/kandyui.rc8
-rw-r--r--kandy/src/kandyview.cpp319
-rw-r--r--kandy/src/kandyview.h124
-rw-r--r--kandy/src/main.cpp158
-rw-r--r--kandy/src/mobilegui.cpp1671
-rw-r--r--kandy/src/mobilegui.h136
-rw-r--r--kandy/src/mobilegui_base.ui583
-rw-r--r--kandy/src/mobilemain.cpp191
-rw-r--r--kandy/src/mobilemain.h109
-rw-r--r--kandy/src/modem.cpp703
-rw-r--r--kandy/src/modem.h124
-rw-r--r--kandy/src/uninstall.desktop2
43 files changed, 7380 insertions, 0 deletions
diff --git a/kandy/AUTHORS b/kandy/AUTHORS
new file mode 100644
index 000000000..aa439fe7e
--- /dev/null
+++ b/kandy/AUTHORS
@@ -0,0 +1,2 @@
+Cornelius Schumacher <schumacher@kde.org>
+Heiko Falk <hf2@ls12.cs.uni-dortmund.de>
diff --git a/kandy/COPYING b/kandy/COPYING
new file mode 100644
index 000000000..0b84a43fd
--- /dev/null
+++ b/kandy/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU 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
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/kandy/Makefile.am b/kandy/Makefile.am
new file mode 100644
index 000000000..625eeeca1
--- /dev/null
+++ b/kandy/Makefile.am
@@ -0,0 +1,6 @@
+## kdebase/Makefile.am
+## (C) 1997 Stephan Kulow
+
+SUBDIRS = src profiles
+
+include $(top_srcdir)/admin/Doxyfile.am
diff --git a/kandy/README b/kandy/README
new file mode 100644
index 000000000..93c651c1f
--- /dev/null
+++ b/kandy/README
@@ -0,0 +1,15 @@
+Kandy 0.2
+---------
+
+Kandy provides access to your mobile phone and allows to sync the data on the
+phone with the data on your desktop computer.
+
+At the moment Kandy is more or less a terminal program with some special
+features to store commands and their parameters, but is also has a simple GUI to
+access the phone-book of a mobile phone and it is able to sync this phonebook
+with the KDE address book.
+
+Kandy is aimed at mobile phones with integrated (GSM) modems.
+
+
+Cornelius Schumacher <schumacher@kde.org>
diff --git a/kandy/RELEASENOTES b/kandy/RELEASENOTES
new file mode 100644
index 000000000..f40c0f818
--- /dev/null
+++ b/kandy/RELEASENOTES
@@ -0,0 +1,76 @@
+Kandy 0.5.1 (18.11.2004)
+------------------------
+
++ Support of user-defined baud rates via setting in serial device configuration
+ dialog.
+
++ Full support for SIM phone books starting with an entry != 1 and having an
+ arbitrary number of entries.
+
++ Removal of possible unsafe sprintf's, strdups and char* buffers.
+
+
+Kandy 0.5 (16.11.2004)
+----------------------
+
++ Kandy now supports different types of phone numbers associated with KAB
+ addressees. A config dialog was added where the user can specify whether
+ to exclude e.g. fax numbers or not. For every type of number, a suffix which
+ is appended to the name can be defined. This way, the e.g. office and cell
+ numbes of a person can be clearly distinguished in the mobile phone book.
+ Older version of Kandy prior to 0.5 simply grabbed the first phone number
+ attached to an addressee and dumped that one to the mobile phone...
+
++ Names from the KDE address book are formatted intelligently. Basically, the
+ ordering "Family Name, Given Name" is used. If "Family Name" only is a unique
+ string, it is used in order to save characters of the narrow mobile phone
+ display. If several people with the same family name (e.g. Meyer, Jens and
+ Meyer, Andy) exist, only the first letter of the given names are used if they
+ are unique (i.e. Meyer, J. and Meyer, A.). Depending on the allowed maximum
+ width of a name entry which is extracted from the mobile phone, names are
+ truncated in order to fit onto the mobile device.
+
++ A rudimentary conversion between "normal ASCII" characters and the strange
+ 7-bit GSM charset is implemented. Hence, names with e.g. german Umlauts are
+ now transfered correctly to the mobile phone and back. (Exception: the capital
+ "Ö" does not work and leads to modem errors. FIXME!)
+
++ If a suffix for a certain phone numbe type is quoted in the configuration
+ dialog (e.g. Cell suffix = "17"), then the unquoted suffix is interpreted as
+ the hexadecimal number of the desired character of the GSM charset. (The Cell
+ suffix "17" has the effect that every mobile phone entry of the KAB will be
+ followed by an antenna-like symbol in the display of the mobile phone). See
+ http://www.nobbi.com/atgsm.html for an illustration of the GSM charset.
+
++ The serial interface configuration dialog now contains the option to
+ specify in which directory the LOCK file should be generated (the old
+ hard-coded /var/lock directory doesn't exist on my Sun box).
+
++ The serial interface configuration dialog and the GUI offer the possibility
+ to set the mobile's clock according to the desktop's system time.
+
++ The maximum number of entries for the mobile phone book which was hard-coded
+ before (150) now is extracted dynamically from the mobile phone.
+
++ The sync mechanism of Kandy is completely rewritten.
+
++ The current states of the KAB and mobile phonebooks (unchanged or modified)
+ are properly reflected in the GUI.
+
++ Saving a modified phone book back to the mobile is done very efficiently by
+ just writing back only modified entries and not the whole phone book as was
+ the case before.
+
++ Deleting of mobile phone book items is supported now.
+
++ The GUI is heavily restructured and simplified.
+
++ All the improvements of Kandy 0.5 were tested with the following devices:
+ + Phones:
+ - Siemens ME45
+ - Siemens C65
+ + Host Machines:
+ - Sun UltraSparc 10, Solaris 9
+ + KDE versions:
+ - 3.2.3 (built with Sun's Workshop compiler)
+ - 3.3.1 (built with gcc 3.3.3)
diff --git a/kandy/TODO b/kandy/TODO
new file mode 100644
index 000000000..b0ad7764a
--- /dev/null
+++ b/kandy/TODO
@@ -0,0 +1,13 @@
++ Support of phone book memory of the phone itself instead of only the SIM
+ memory.
++ Adding a new tab to the MobileGUI supporting a mobile phone's records for
+ last dialled numbers, own numbers, missed calls, ...
++ Adding a new tab to the MobileGUI supporting short message services
+ (read, write, edit, send, sync with knotes, ...)
++ What about organizer features of a mobile phone (my Siemens supports a simple
+ calendar and a full address book. HotSync with korganizer and KAB?).
++ The old Terminal Window of Kandy basically serves only for debugging
+ purposes. The modem traffic is already mirrored in the "Terminal" tab of
+ the mobile GUI. Hence, the terminal window can be fully removed from Kandy
+ in the near future.
++ Somehow, a common kandy icon doesn't exist. Would be nice to have one...
diff --git a/kandy/configure.in.in b/kandy/configure.in.in
new file mode 100644
index 000000000..c21c2e307
--- /dev/null
+++ b/kandy/configure.in.in
@@ -0,0 +1,12 @@
+# check for lockdev, optionally used to lock serial device
+AH_TEMPLATE(HAVE_LOCKDEV)
+AC_CHECK_HEADERS(lockdev.h, HAVE_LOCKDEV_H=1, HAVE_LOCKDEV_H=)
+AC_SUBST(HAVE_LOCKDEV_H)
+# we check for dev_unlock since kmobile checks dev_lock, caches it
+# and the variables are fucked up then... *sigh*
+if test -n "$HAVE_LOCKDEV_H"; then
+ AC_CHECK_LIB(lockdev, dev_unlock,
+ [KANDY_LIBLOCKDEV="-llockdev $KANDY_LIBLOCKDEV"
+AC_DEFINE(HAVE_LOCKDEV)], , $KANDY_LIBLOCKDEV)
+fi
+AC_SUBST(KANDY_LIBLOCKDEV)
diff --git a/kandy/profiles/Makefile.am b/kandy/profiles/Makefile.am
new file mode 100644
index 000000000..cca6acd38
--- /dev/null
+++ b/kandy/profiles/Makefile.am
@@ -0,0 +1,4 @@
+
+profilesdir = $(kde_datadir)/kandy
+
+profiles_DATA = default.kandy
diff --git a/kandy/profiles/default.kandy b/kandy/profiles/default.kandy
new file mode 100644
index 000000000..106808202
--- /dev/null
+++ b/kandy/profiles/default.kandy
@@ -0,0 +1,27 @@
+ <commandset>
+ <command string="at+cbc" hexoutput="n" name="Battery charge" />
+ <command string="at+cclk?" hexoutput="n" name="Clock" />
+ <command string="at+cgmi" hexoutput="n" name="Issue manufacturer ID code" />
+ <command string="at+cgmm" hexoutput="n" name="Issue model ID code" />
+ <command string="at+csq" hexoutput="n" name="Output signal quality" />
+ <command string="at+cgmr" hexoutput="n" name="Output the GSM telephone version" />
+ <command string="at+cgsn" hexoutput="n" name="Output the serial number (IMEI)" />
+ <command string="at+cpbr=?" hexoutput="n" name="Output Phonebook Settings" />
+ <command string="at+cpbs=?" hexoutput="n" name="Output available Phonebooks" />
+ <command string="at+cpbs?" hexoutput="n" name="Output current Phonebook Properties" />
+ <command string="at+cpbs=" hexoutput="n" name="Set current Phonebook" >
+ <parameter userinput="y" value="ME" name="Phonebook" />
+ </command>
+ <command string="at+cpbr=1,2" hexoutput="n" name="Read Phonebook" >
+ <parameter userinput="n" value="2" name="Start" />
+ <parameter userinput="y" value="5" name="End" />
+ </command>
+ <command string="at+cpbr=70" hexoutput="n" name="Read Phonenumber" >
+ <parameter userinput="y" value="70" name="Index" />
+ </command>
+ <command string="at^sbnr=&quot;vcs&quot;,1" hexoutput="y" name="Read event 1" />
+ <command string="at^sbnr=&quot;vcs&quot;,2" hexoutput="y" name="Read event 2" />
+ <command string="at^sbnr=&quot;vcs&quot;,3" hexoutput="y" name="Read event 3" />
+ <command string="at+cpbr=1,150" hexoutput="n" name="Read telephone book" />
+ <command string="at+cpbr=1,3" hexoutput="n" name="Read telephone book 1-3" />
+ </commandset>
diff --git a/kandy/src/Makefile.am b/kandy/src/Makefile.am
new file mode 100644
index 000000000..d41626331
--- /dev/null
+++ b/kandy/src/Makefile.am
@@ -0,0 +1,38 @@
+bin_PROGRAMS = kandy kandy_client
+
+INCLUDES = -I$(top_srcdir) $(all_includes)
+
+kandy_LDFLAGS = $(KDE_RPATH) $(all_libraries)
+kandy_LDADD = $(KANDY_LIBLOCKDEV) $(LIB_KFILE) -lkabc $(top_builddir)/libkdepim/libkdepim.la
+kandy_SOURCES = main.cpp kandy.cpp \
+ cmdpropertiesdialog_base.ui cmdpropertiesdialog.cpp \
+ kandyview.cpp \
+ kandyiface.skel \
+ modem.cpp \
+ atcommand.cpp commanditem.cpp mobilegui_base.ui mobilegui.cpp \
+ commandscheduler.cpp commandset.cpp \
+ kandyprefs.kcfgc kandyprefsdialog.cpp \
+ mobilemain.cpp
+
+noinst_HEADERS = kandy.h kandyview.h modem.h atcommand.h \
+ commanditem.h mobilegui.h commandscheduler.h
+
+kandy_client_LDFLAGS = $(KDE_RPATH) $(all_libraries)
+kandy_client_LDADD = $(LIB_KDECORE)
+kandy_client_SOURCES = kandy_client.cpp
+
+METASOURCES = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kandy.pot
+
+xdg_apps_DATA = kandy.desktop
+
+kde_kcfg_DATA = kandy.kcfg
+
+install-data-local: uninstall.desktop
+ $(mkinstalldirs) $(DESTDIR)$(kde_appsdir)/Utilities
+ $(INSTALL_DATA) $(srcdir)/uninstall.desktop $(DESTDIR)$(kde_appsdir)/Utilities/kandy.desktop
+
+rcdir = $(kde_datadir)/kandy
+rc_DATA = kandyui.rc kandymobileui.rc
diff --git a/kandy/src/atcommand.cpp b/kandy/src/atcommand.cpp
new file mode 100644
index 000000000..006fedf15
--- /dev/null
+++ b/kandy/src/atcommand.cpp
@@ -0,0 +1,313 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include "atcommand.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+
+ATParameter::ATParameter()
+{
+ mUserInput = false;
+}
+
+ATParameter::ATParameter(const QString &value,const QString &name,
+ bool userInput)
+{
+ mName = name;
+ mValue = value;
+ mUserInput = userInput;
+}
+
+
+ATCommand::ATCommand()
+{
+ mHexOutput = false;
+
+ construct();
+}
+
+ATCommand::ATCommand(const QString &cmdString)
+{
+ setCmdName(i18n("New Command"));
+ setCmdString(cmdString);
+ mHexOutput = false;
+
+ extractParameters();
+
+ construct();
+}
+
+ATCommand::ATCommand(const QString &cmdName,const QString &cmdString,
+ bool hexOutput)
+{
+ setCmdName(cmdName);
+ setCmdString(cmdString);
+ mHexOutput = hexOutput;
+
+ construct();
+}
+
+void ATCommand::construct()
+{
+ mAutoDelete = false;
+ mResultFieldsList.setAutoDelete(true);
+ mParameters.setAutoDelete(true);
+}
+
+ATCommand::~ATCommand()
+{
+// kdDebug() << "~ATCommand: " << cmdString() << endl;
+}
+
+
+void ATCommand::setCmdName(const QString &cmdName)
+{
+ mCmdName = cmdName;
+}
+
+QString ATCommand::cmdName()
+{
+ return mCmdName;
+}
+
+
+void ATCommand::setCmdString(const QString &cmdString)
+{
+ mCmdString = cmdString;
+
+ mId = cmdString;
+ if (mId.startsWith("at")) mId = mId.mid(2);
+ else mCmdString.prepend("at");
+
+// kdDebug() << "ATCommand: Id: " << mId << endl;
+}
+
+QString ATCommand::cmdString()
+{
+ return mCmdString;
+}
+
+QString ATCommand::cmd()
+{
+ if (mParameters.count() > 0) {
+ QString cmd = cmdString().left(cmdString().find("=") + 1);
+// kdDebug() << "--1-cmd: " << cmd << endl;
+ for(uint i=0;i<mParameters.count();++i) {
+ cmd += mParameters.at(i)->value();
+ if (i < mParameters.count() - 1) cmd += ",";
+ }
+// kdDebug() << "--2-cmd: " << cmd << endl;
+ return cmd;
+ } else {
+ return cmdString();
+ }
+}
+
+QString ATCommand::id()
+{
+ return mId;
+}
+
+void ATCommand::setHexOutput(bool hexOutput)
+{
+ mHexOutput = hexOutput;
+}
+
+bool ATCommand::hexOutput()
+{
+ return mHexOutput;
+}
+
+void ATCommand::setResultString(const QString &resultString)
+{
+ mResultString = resultString;
+
+ mResultFieldsList.clear();
+
+ QStringList resultFields = QStringList::split("\n",mResultString);
+
+ for(QStringList::Iterator it = resultFields.begin();
+ it != resultFields.end(); ++it) {
+ setResultFields(*it);
+ }
+}
+
+
+void ATCommand::setResultFields( QString fieldsString )
+{
+ QString id = mId.upper().left( mId.find( '=' ) );
+
+
+ // Truncate the command name prepended to the output by the modem.
+ if ( fieldsString.startsWith( id ) )
+ fieldsString = fieldsString.mid( id.length() + 2 );
+
+ // If modem output is enclosed by brackets, remove them, too
+ if ( ( fieldsString[ 0 ] == '(' ) && ( fieldsString[ fieldsString.length() - 1 ] == ')' ) )
+ fieldsString = fieldsString.mid( 1, fieldsString.length() - 2 );
+
+ QStringList *fields = new QStringList;
+ QStringList TmpFields = QStringList::split( ',', fieldsString );
+ QString TmpString = "";
+
+
+ // Assume a phonebook entry of the mobile phone has the format
+ // <familyname>, <givenname>
+ // Then, the above split() call separtes this entry into 2 distinct fields
+ // leading to an error in MobileGui::fillPhonebook since the number of
+ // fields is != 4.
+ // Hence, the fieldsString needs to be parsed a little bit. Names stored on
+ // the mobile phone are quoted. Commas within a quoted are of the fieldsString
+ // must not be divided into differend fields.
+ for ( QStringList::Iterator it = TmpFields.begin(); it != TmpFields.end(); it++ )
+ {
+ // Start of a quoted area
+ if ( ( (*it)[ 0 ] == '\"' ) && ( (*it)[ (*it).length() - 1 ] != '\"' ) )
+ TmpString = (*it).copy();
+ else
+ // End of a quoted area
+ if ( ( (*it)[ 0 ] != '\"' ) && ( (*it)[ (*it).length() - 1 ] == '\"' ) )
+ {
+ TmpString += "," + (*it).copy();
+ (*fields).append( TmpString.copy() );
+ TmpString = "";
+ } else
+ // Not within a quoted area
+ if (TmpString.isEmpty())
+ (*fields).append( *it );
+ else
+ // Within a quoted area
+ TmpString += "," + (*it).copy();
+ }
+
+ mResultFieldsList.append( fields );
+}
+
+
+QString ATCommand::resultString()
+{
+ return mResultString;
+}
+
+QString ATCommand::resultField(int index)
+{
+ if (mResultFieldsList.count() == 0) return "";
+
+ QStringList *resultFields = mResultFieldsList.at(0);
+
+ QStringList::Iterator it = resultFields->at(index);
+ if (it == resultFields->end()) {
+ kdDebug() << "ATCommand::resultField: index " << index << " out of range."
+ << endl;
+ return "";
+ }
+
+ return *it;
+}
+
+
+QPtrList<QStringList> *ATCommand::resultFields()
+{
+ return &mResultFieldsList;
+}
+
+void ATCommand::addParameter(ATParameter *p)
+{
+ mParameters.append(p);
+}
+
+void ATCommand::clearParameters()
+{
+ mParameters.clear();
+}
+
+QPtrList<ATParameter> ATCommand::parameters()
+{
+ return mParameters;
+}
+
+void ATCommand::setParameter(int index,const QString &value)
+{
+ if (mParameters.count() <= (unsigned int)index) {
+ kdDebug() << "ATCommand " << cmdName() << " has no Parameter " << index
+ << endl;
+ return;
+ }
+
+ mParameters.at(index)->setValue(value);
+}
+
+void ATCommand::setParameter(int index,int value)
+{
+ setParameter(index,QString::number(value));
+}
+
+QString ATCommand::processOutput(const QString &output)
+{
+ if (hexOutput()) {
+ QString hexString = output.mid(output.find('\n')+1);
+ int i=0;
+ QString aChar = hexString.mid(i,2);
+ QString result;
+ while(!aChar.isEmpty()) {
+ int charValue = aChar.toInt(0,16);
+ QChar charEncoded(charValue);
+// result += aChar + ": " + charEncoded + "\n";
+ result += charEncoded;
+ i += 2;
+ aChar = hexString.mid(i,2);
+ }
+ result += "\n";
+ return result;
+ } else {
+ return output;
+ }
+}
+
+QString ATCommand::processOutput()
+{
+ return processOutput(mResultString);
+}
+
+void ATCommand::extractParameters()
+{
+// kdDebug() << "Arg String: " << cmdString() << endl;
+
+ int pos = cmdString().find("=");
+ if (pos < 0) return;
+
+ QString paraString = cmdString().mid(pos+1);
+// kdDebug() << "Para String: " << paraString << endl;
+ QStringList paraList = QStringList::split(",",paraString);
+
+ QStringList::ConstIterator it = paraList.begin();
+ QStringList::ConstIterator end = paraList.end();
+ int argNum = 1;
+ while(it != end) {
+ addParameter(new ATParameter(*it,i18n("Arg %1").arg(QString::number(argNum++)),
+ false));
+ ++it;
+ }
+}
diff --git a/kandy/src/atcommand.h b/kandy/src/atcommand.h
new file mode 100644
index 000000000..8296d1291
--- /dev/null
+++ b/kandy/src/atcommand.h
@@ -0,0 +1,111 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+#ifndef ATCOMMAND_H
+#define ATCOMMAND_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qptrlist.h>
+
+class ATParameter {
+ public:
+ ATParameter();
+ ATParameter(const QString &value,const QString &name="",
+ bool userInput=false);
+
+ void setName(const QString &name) { mName = name; }
+ QString name() const { return mName; }
+ void setValue(const QString &value) { mValue = value; }
+ QString value() const { return mValue; }
+ void setUserInput(bool userInput) { mUserInput = userInput; }
+ bool userInput() const { return mUserInput; }
+
+ private:
+ QString mName;
+ QString mValue;
+ bool mUserInput;
+};
+
+/**
+ This class provides an abstraction of an AT command.
+*/
+// TODO: emit a signal, when the command was executed.
+class ATCommand {
+ public:
+ ATCommand();
+ ATCommand(const QString &cmdString);
+ ATCommand(const QString &cmdName,const QString &cmdString,
+ bool hexOutput=false);
+ virtual ~ATCommand();
+
+ void setCmdName(const QString &);
+ QString cmdName();
+
+ void setCmdString(const QString &);
+ QString cmdString();
+
+ QString cmd();
+
+ QString id();
+
+ void setHexOutput(bool);
+ bool hexOutput();
+
+ QString processOutput(const QString &);
+ QString processOutput();
+
+ void setResultString(const QString &);
+ QString resultString();
+ QString resultField(int index);
+ QPtrList<QStringList> *resultFields();
+
+ void addParameter(ATParameter *);
+ void clearParameters();
+ QPtrList<ATParameter> parameters();
+
+ void setParameter(int index,const QString &value);
+ void setParameter(int index,int value);
+
+ void setAutoDelete(bool autoDelete) { mAutoDelete = autoDelete; }
+ bool autoDelete() { return mAutoDelete; }
+
+ private:
+ void construct();
+ void setResultFields(QString fieldsString);
+ void extractParameters();
+
+ QString mCmdName;
+ QString mCmdString;
+ QString mId;
+ bool mHexOutput;
+
+ QString mResultString;
+ QPtrList<QStringList> mResultFieldsList;
+
+ QPtrList<ATParameter> mParameters;
+
+ bool mAutoDelete;
+};
+
+#endif
diff --git a/kandy/src/cmdpropertiesdialog.cpp b/kandy/src/cmdpropertiesdialog.cpp
new file mode 100644
index 000000000..f871a02bb
--- /dev/null
+++ b/kandy/src/cmdpropertiesdialog.cpp
@@ -0,0 +1,120 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qlistview.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+
+#include <kinputdialog.h>
+#include <klocale.h>
+
+#include "atcommand.h"
+
+#include "cmdpropertiesdialog.h"
+#include "cmdpropertiesdialog.moc"
+
+class ParameterItem : public QCheckListItem {
+ public:
+ ParameterItem(ATParameter *p,QListView *parent) :
+ QCheckListItem(parent,p->name(),CheckBox),mParameter(p)
+ {
+ setText(1,p->value());
+ setOn(p->userInput());
+ }
+
+ void writeParameter()
+ {
+ mParameter->setName(text(0));
+ mParameter->setValue(text(1));
+ mParameter->setUserInput(isOn());
+ }
+
+ private:
+ ATParameter *mParameter;
+};
+
+
+/*
+ * Constructs a CmdPropertiesDialog which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ *
+ * The dialog will by default be modeless, unless you set 'modal' to
+ * TRUE to construct a modal dialog.
+ */
+CmdPropertiesDialog::CmdPropertiesDialog(ATCommand *cmd, QWidget* parent,
+ const char* name, bool modal,
+ WFlags fl )
+ : CmdPropertiesDialog_base( parent, name, modal, fl )
+{
+ mCmd = cmd;
+
+ readCommand();
+}
+
+CmdPropertiesDialog::~CmdPropertiesDialog()
+{
+}
+
+void CmdPropertiesDialog::readCommand()
+{
+ mNameEdit->setText(mCmd->cmdName());
+ mStringEdit->setText(mCmd->cmdString());
+ mHexCheck->setChecked(mCmd->hexOutput());
+
+ QPtrList<ATParameter> parameters = mCmd->parameters();
+ for(int i=(int)parameters.count()-1;i>=0;--i) {
+ ATParameter *p = parameters.at(i);
+ new ParameterItem(p,mParameterList);
+ }
+}
+
+void CmdPropertiesDialog::writeCommand()
+{
+ mCmd->setCmdName(mNameEdit->text());
+ mCmd->setCmdString(mStringEdit->text());
+ mCmd->setHexOutput(mHexCheck->isChecked());
+ ParameterItem *item = (ParameterItem *)mParameterList->firstChild();
+ while (item) {
+ item->writeParameter();
+ item = (ParameterItem *)item->nextSibling();
+ }
+}
+
+void CmdPropertiesDialog::editParameterName(QListViewItem *item)
+{
+ bool ok = false;
+
+ QString newName = KInputDialog::getText(QString::null,
+ i18n("Enter parameter name:"),item->text(0),&ok,this);
+
+ if (ok) {
+ item->setText(0,newName);
+ }
+}
+
+void CmdPropertiesDialog::slotAccept()
+{
+ writeCommand();
+ accept();
+}
diff --git a/kandy/src/cmdpropertiesdialog.h b/kandy/src/cmdpropertiesdialog.h
new file mode 100644
index 000000000..18849d3d6
--- /dev/null
+++ b/kandy/src/cmdpropertiesdialog.h
@@ -0,0 +1,50 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+#ifndef CMDPROPERTIESDIALOG_H
+#define CMDPROPERTIESDIALOG_H
+
+#include "cmdpropertiesdialog_base.h"
+
+class ATCommand;
+
+class CmdPropertiesDialog : public CmdPropertiesDialog_base
+{
+ Q_OBJECT
+ public:
+ CmdPropertiesDialog(ATCommand *cmd,QWidget* parent=0,const char* name=0,
+ bool modal=false,WFlags fl=0);
+ ~CmdPropertiesDialog();
+
+ protected slots:
+ void editParameterName(QListViewItem *);
+ void slotAccept();
+
+ private:
+ void readCommand();
+ void writeCommand();
+
+ ATCommand *mCmd;
+};
+
+#endif // CMDPROPERTIESDIALOG_H
diff --git a/kandy/src/cmdpropertiesdialog_base.ui b/kandy/src/cmdpropertiesdialog_base.ui
new file mode 100644
index 000000000..092074c6e
--- /dev/null
+++ b/kandy/src/cmdpropertiesdialog_base.ui
@@ -0,0 +1,172 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>CmdPropertiesDialog_base</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>CmdPropertiesDialog_base</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>323</width>
+ <height>281</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Command Properties</string>
+ </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="QLineEdit" row="0" column="1" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>mNameEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="1" column="1" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>mStringEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Name:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>String:</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>mHexCheck</cstring>
+ </property>
+ <property name="text">
+ <string>Hex result</string>
+ </property>
+ </widget>
+ <widget class="QListView" row="2" column="0" rowspan="1" colspan="4">
+ <column>
+ <property name="text">
+ <string>Position</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Parameter</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Value</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>mParameterList</cstring>
+ </property>
+ </widget>
+ <spacer row="4" column="0" rowspan="1" colspan="2">
+ <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>79</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="4" column="2">
+ <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" row="4" column="3">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>mParameterList</sender>
+ <signal>rightButtonClicked(QListViewItem*,const QPoint&amp;,int)</signal>
+ <receiver>CmdPropertiesDialog_base</receiver>
+ <slot>editParameterName(QListViewItem*)</slot>
+ </connection>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>CmdPropertiesDialog_base</receiver>
+ <slot>slotAccept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>CmdPropertiesDialog_base</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>editParameterName(QListViewItem *)</slot>
+ <slot access="protected">slotAccept()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kandy/src/commanditem.cpp b/kandy/src/commanditem.cpp
new file mode 100644
index 000000000..fde599c3f
--- /dev/null
+++ b/kandy/src/commanditem.cpp
@@ -0,0 +1,102 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qdom.h>
+
+#include <kdebug.h>
+
+#include "atcommand.h"
+
+#include "commanditem.h"
+
+CommandItem::CommandItem(QListView *listView,ATCommand *command)
+ : QListViewItem(listView)
+{
+ mCommand = command;
+
+ setItemText();
+}
+
+CommandItem::~CommandItem()
+{
+}
+
+ATCommand *CommandItem::command()
+{
+ return mCommand;
+}
+
+void CommandItem::load(QDomElement *c)
+{
+ mCommand->setCmdName(c->attribute("name","unknown"));
+ mCommand->setCmdString(c->attribute("string","at"));
+ mCommand->setHexOutput(c->attribute("hexoutput","n") == "y");
+
+ QDomNode n = c->firstChild();
+ while(!n.isNull()) {
+ QDomElement e = n.toElement();
+ if (!e.isNull()) {
+ ATParameter *p = new ATParameter;
+ p->setName(e.attribute("name","unnamed"));
+ p->setValue(e.attribute("value","0"));
+ p->setUserInput(e.attribute("userinput","n") == "y");
+
+ mCommand->addParameter(p);
+ }
+ n = n.nextSibling();
+ }
+
+ setItemText();
+}
+
+void CommandItem::save(QDomDocument *doc,QDomElement *parent)
+{
+ QDomElement c = doc->createElement("command");
+ c.setAttribute("name",mCommand->cmdName());
+ c.setAttribute("string",mCommand->cmdString());
+ c.setAttribute("hexoutput",mCommand->hexOutput() ? "y" : "n");
+ parent->appendChild(c);
+
+ QPtrList<ATParameter> paras = mCommand->parameters();
+ for(uint i=0;i<paras.count();++i) {
+ saveParameter(paras.at(i),doc,&c);
+ }
+}
+
+void CommandItem::saveParameter(ATParameter *p, QDomDocument *doc,
+ QDomElement *parent)
+{
+ QDomElement e = doc->createElement("parameter");
+ e.setAttribute("name",p->name());
+ e.setAttribute("value",p->value());
+ e.setAttribute("userinput",p->userInput() ? "y" : "n");
+ parent->appendChild(e);
+}
+
+void CommandItem::setItemText()
+{
+ setText(0,mCommand->cmdName());
+ setText(1,mCommand->cmdString());
+ setText(2,mCommand->hexOutput() ? "y" : "n");
+}
diff --git a/kandy/src/commanditem.h b/kandy/src/commanditem.h
new file mode 100644
index 000000000..853bba01b
--- /dev/null
+++ b/kandy/src/commanditem.h
@@ -0,0 +1,57 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef _COMMAND_ITEM_H_
+#define _COMMAND_ITEM_H_
+
+#include <qlistview.h>
+
+class ATCommand;
+class ATParameter;
+class QDomElement;
+class QDomDocument;
+
+/**
+ QListView item representing a modem command.
+*/
+class CommandItem : public QListViewItem {
+ public:
+ CommandItem(QListView *listView,ATCommand *command);
+ ~CommandItem();
+
+ ATCommand *command();
+
+ void load(QDomElement *c);
+ void save(QDomDocument *doc,QDomElement *parent);
+
+ void setItemText();
+
+ protected:
+ void saveParameter(ATParameter *p, QDomDocument *doc,QDomElement *parent);
+
+ private:
+ ATCommand *mCommand;
+};
+
+#endif
diff --git a/kandy/src/commandscheduler.cpp b/kandy/src/commandscheduler.cpp
new file mode 100644
index 000000000..23544e8a2
--- /dev/null
+++ b/kandy/src/commandscheduler.cpp
@@ -0,0 +1,140 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "modem.h"
+
+#include "commandscheduler.h"
+#include "commandscheduler.moc"
+
+CommandScheduler::CommandScheduler(Modem *modem,QObject *parent,
+ const char *name) :
+ QObject(parent,name),
+ mModem(modem)
+{
+ connect(mModem,SIGNAL(gotLine(const char *)),
+ SLOT(processOutput(const char *)));
+}
+
+void CommandScheduler::execute(ATCommand *command)
+{
+ if (!mModem->isOpen()) {
+ kdDebug(5960) << "Warning! Modem not open." << endl;
+ return;
+ }
+
+ mCommandQueue.append(command);
+
+// if (mCommandQueue.count() == 1) sendCommand(command->cmdString());
+ if (mCommandQueue.count() == 1) sendCommand(command->cmd());
+}
+
+void CommandScheduler::execute(const QString &command)
+{
+ ATCommand *cmd = new ATCommand("",command);
+ cmd->setAutoDelete(true);
+
+ execute(cmd);
+}
+
+void CommandScheduler::executeId(const QString &id)
+{
+ QPtrList<ATCommand> *cmds = mCommandSet.commandList();
+
+ for(uint i=0;i<cmds->count();++i) {
+ if (cmds->at(i)->id() == id) {
+ execute(cmds->at(i));
+ return;
+ }
+ }
+ kdDebug(5960) << "CommandScheduler::executeId(): Id '" << id << "' not found" << endl;
+}
+
+void CommandScheduler::sendCommand(const QString &command)
+{
+ if (command.isEmpty()) {
+ kdDebug(5960) << "CommandScheduler::sendCommand(): Warning! Empty command."
+ << endl;
+ return;
+ }
+
+ kdDebug(5960) << "CommandScheduler:sendCommand(): " << command << endl;
+
+ mModem->writeLine(command.latin1());
+}
+
+
+void CommandScheduler::processOutput(const char *line)
+{
+ QString l = line;
+ ATCommand *cmd = mCommandQueue.first();
+ if (l == "OK") {
+ mState = WAITING;
+ emit result(mResult);
+ cmd->setResultString(mResult);
+ emit commandProcessed(cmd);
+ nextCommand();
+ } else if (l == "ERROR") {
+ mState = WAITING;
+ emit result(i18n("Error"));
+ nextCommand();
+ } else {
+ if (mState == WAITING) {
+ mState = PROCESSING;
+ mResult = "";
+ } else if (mState == PROCESSING) {
+ if (!l.isEmpty()) {
+ mResult += l;
+ mResult += "\n";
+ }
+ }
+ }
+}
+
+void CommandScheduler::nextCommand()
+{
+ if (mCommandQueue.first()->autoDelete()) delete mCommandQueue.first();
+ mCommandQueue.removeFirst();
+ if (mCommandQueue.count() > 0) {
+ sendCommand(mCommandQueue.first()->cmd());
+ }
+}
+
+bool CommandScheduler::loadProfile(const QString& filename)
+{
+ mCommandSet.clear();
+
+ if (!mCommandSet.loadFile(filename)) return false;
+
+ return true;
+}
+
+bool CommandScheduler::saveProfile(const QString& filename)
+{
+ if (!mCommandSet.saveFile(filename)) return false;
+
+ return true;
+}
diff --git a/kandy/src/commandscheduler.h b/kandy/src/commandscheduler.h
new file mode 100644
index 000000000..20398aafa
--- /dev/null
+++ b/kandy/src/commandscheduler.h
@@ -0,0 +1,76 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+#ifndef COMMANDSCHEDULER_H
+#define COMMANDSCHEDULER_H
+
+#include <qobject.h>
+#include <qptrlist.h>
+
+#include "atcommand.h"
+#include "commandset.h"
+
+class Modem;
+
+class CommandScheduler : public QObject {
+ Q_OBJECT
+ public:
+ CommandScheduler (Modem *modem,QObject *parent = 0, const char *name = 0);
+
+ void execute(const QString &command);
+ void execute(ATCommand *command);
+ void executeId(const QString &id);
+
+ Modem *modem() { return mModem; }
+ CommandSet *commandSet() { return &mCommandSet; }
+
+ bool loadProfile(const QString& filename);
+ bool saveProfile(const QString& filename);
+
+ signals:
+ void result(const QString &);
+ void commandProcessed(ATCommand *);
+
+ private slots:
+ void processOutput(const char *line);
+
+ private:
+ void sendCommand(const QString &command);
+ void nextCommand();
+
+ private:
+ Modem *mModem;
+
+ CommandSet mCommandSet;
+
+ ATCommand *mLastCommand;
+
+ QPtrList<ATCommand> mCommandQueue;
+
+ enum State { WAITING, PROCESSING };
+ State mState;
+
+ QString mResult;
+};
+
+#endif
diff --git a/kandy/src/commandset.cpp b/kandy/src/commandset.cpp
new file mode 100644
index 000000000..f44899cac
--- /dev/null
+++ b/kandy/src/commandset.cpp
@@ -0,0 +1,154 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qdom.h>
+#include <qfile.h>
+#include <qtextstream.h>
+
+#include <kdebug.h>
+
+#include "atcommand.h"
+
+#include "commandset.h"
+
+CommandSet::CommandSet()
+{
+ mList.setAutoDelete(true);
+}
+
+CommandSet::~CommandSet()
+{
+}
+
+void CommandSet::addCommand(ATCommand *command)
+{
+ mList.append(command);
+}
+
+void CommandSet::deleteCommand(ATCommand *command)
+{
+ mList.removeRef(command);
+}
+
+bool CommandSet::loadFile(const QString& filename)
+{
+// kdDebug(5960) << "CommandSet::loadFile(): " << filename << endl;
+
+ QDomDocument doc("Kandy");
+ QFile f(filename);
+ if (!f.open(IO_ReadOnly))
+ return false;
+ if (!doc.setContent(&f)) {
+ f.close();
+ return false;
+ }
+ f.close();
+
+ QDomNodeList commands = doc.elementsByTagName("command");
+ for(uint i=0;i<commands.count();++i) {
+ QDomElement c = commands.item(i).toElement();
+ if (!c.isNull()) {
+ ATCommand *cmd = new ATCommand;
+ loadCommand(cmd,&c);
+ addCommand(cmd);
+ }
+ }
+
+ return true;
+}
+
+bool CommandSet::saveFile(const QString& filename)
+{
+ kdDebug(5960) << "CommandSet::saveFile(): " << filename << endl;
+
+ QDomDocument doc("Kandy");
+ QDomElement set = doc.createElement("commandset");
+ doc.appendChild(set);
+
+ for(uint i=0; i<mList.count();++i) {
+ saveCommand(mList.at(i),&doc,&set);
+ }
+
+ QFile xmlfile(filename);
+ if (!xmlfile.open(IO_WriteOnly)) {
+ kdDebug(5960) << "Error opening file for write." << endl;
+ return false;
+ }
+ QTextStream ts(&xmlfile);
+ doc.documentElement().save(ts,2);
+ xmlfile.close();
+
+ return true;
+}
+
+void CommandSet::clear()
+{
+ mList.clear();
+}
+
+void CommandSet::loadCommand(ATCommand *command,QDomElement *c)
+{
+ command->setCmdName(c->attribute("name","unknown"));
+ command->setCmdString(c->attribute("string","at"));
+ command->setHexOutput(c->attribute("hexoutput","n") == "y");
+
+ QDomNode n = c->firstChild();
+ while(!n.isNull()) {
+ QDomElement e = n.toElement();
+ if (!e.isNull()) {
+ ATParameter *p = new ATParameter;
+ p->setName(e.attribute("name","unnamed"));
+ p->setValue(e.attribute("value","0"));
+ p->setUserInput(e.attribute("userinput","n") == "y");
+
+ command->addParameter(p);
+ }
+ n = n.nextSibling();
+ }
+}
+
+void CommandSet::saveCommand(ATCommand *command,QDomDocument *doc,
+ QDomElement *parent)
+{
+ QDomElement c = doc->createElement("command");
+ c.setAttribute("name",command->cmdName());
+ c.setAttribute("string",command->cmdString());
+ c.setAttribute("hexoutput",command->hexOutput() ? "y" : "n");
+ parent->appendChild(c);
+
+ QPtrList<ATParameter> paras = command->parameters();
+ for(uint i=0;i<paras.count();++i) {
+ saveParameter(paras.at(i),doc,&c);
+ }
+}
+
+void CommandSet::saveParameter(ATParameter *p, QDomDocument *doc,
+ QDomElement *parent)
+{
+ QDomElement e = doc->createElement("parameter");
+ e.setAttribute("name",p->name());
+ e.setAttribute("value",p->value());
+ e.setAttribute("userinput",p->userInput() ? "y" : "n");
+ parent->appendChild(e);
+}
diff --git a/kandy/src/commandset.h b/kandy/src/commandset.h
new file mode 100644
index 000000000..41c9cd144
--- /dev/null
+++ b/kandy/src/commandset.h
@@ -0,0 +1,61 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+#ifndef COMMANDSET_H
+#define COMMANDSET_H
+
+#include <qlistview.h>
+
+class ATCommand;
+class ATParameter;
+class QDomElement;
+class QDomDocument;
+
+/**
+ QListView item representing a modem command.
+*/
+class CommandSet {
+ public:
+ CommandSet();
+ ~CommandSet();
+
+ void addCommand(ATCommand *);
+ void deleteCommand(ATCommand *);
+
+ bool loadFile(const QString &);
+ bool saveFile(const QString &);
+
+ void clear();
+
+ QPtrList<ATCommand> *commandList() { return &mList; }
+
+ protected:
+ void loadCommand(ATCommand *,QDomElement *c);
+ void saveCommand(ATCommand *,QDomDocument *doc,QDomElement *parent);
+ void saveParameter(ATParameter *p, QDomDocument *doc,QDomElement *parent);
+
+ private:
+ QPtrList<ATCommand> mList;
+};
+
+#endif
diff --git a/kandy/src/kandy.cpp b/kandy/src/kandy.cpp
new file mode 100644
index 000000000..860aff5bb
--- /dev/null
+++ b/kandy/src/kandy.cpp
@@ -0,0 +1,348 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2000,2001,2002 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qlineedit.h>
+#include <qprinter.h>
+#include <qprintdialog.h>
+#include <qpainter.h>
+#include <qpaintdevicemetrics.h>
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kmenubar.h>
+#include <kkeydialog.h>
+#include <kaccel.h>
+#include <kio/netaccess.h>
+#include <kfiledialog.h>
+#include <kconfig.h>
+#include <kurl.h>
+#include <kurlrequesterdlg.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kedittoolbar.h>
+#include <kstdaccel.h>
+#include <kaction.h>
+#include <kstdaction.h>
+#include <kurldrag.h>
+
+#include "kandyprefsdialog.h"
+#include "commandscheduler.h"
+#include "kandyprefs.h"
+#include "modem.h"
+
+#include "kandy.h"
+#include <kstatusbar.h>
+#include "kandy.moc"
+
+Kandy::Kandy(CommandScheduler *scheduler)
+ : KMainWindow( 0, "Kandy" ),
+ mPrinter(0)
+{
+ mScheduler = scheduler;
+
+ mPreferencesDialog = 0;
+
+ mView = new KandyView(mScheduler,this);
+
+ // accept dnd
+ setAcceptDrops(true);
+
+ // tell the KMainWindow that this is indeed the main widget
+ setCentralWidget(mView);
+
+ // then, setup our actions
+ setupActions();
+
+ statusBar()->insertItem(i18n(" Disconnected "),0,0,true);
+
+ setAutoSaveSettings();
+
+ // allow the view to change the statusbar and caption
+ connect(mView, SIGNAL(signalChangeStatusbar(const QString&)),
+ this, SLOT(changeStatusbar(const QString&)));
+ connect(mView, SIGNAL(signalChangeCaption(const QString&)),
+ this, SLOT(changeCaption(const QString&)));
+
+ connect(mView,SIGNAL(modifiedChanged(bool)),SLOT(setTitle()));
+
+ KConfig *config = KGlobal::config();
+ config->setGroup("General");
+ QString currentProfile = config->readEntry("CurrentProfile",
+ locate("appdata","default.kandy"));
+ if (!currentProfile.isEmpty()) load(currentProfile);
+}
+
+Kandy::~Kandy()
+{
+}
+
+void Kandy::load(const QString& filename)
+{
+ if (!mView->loadFile(filename)) {
+ KMessageBox::error(this,i18n("Could not load file %1").arg(filename));
+ }
+
+ mFilename = filename;
+ setTitle();
+}
+
+void Kandy::save(const QString & filename)
+{
+ if (!filename.isEmpty()) {
+ if (!mView->saveFile(filename)) {
+ KMessageBox::error(this,i18n("Could not save file %1.").arg(filename));
+ } else {
+ mFilename = filename;
+ setTitle();
+ }
+ }
+}
+
+void Kandy::setupActions()
+{
+ KStdAction::open(this, SLOT(fileOpen()), actionCollection());
+ KStdAction::save(this, SLOT(fileSave()), actionCollection());
+ KStdAction::saveAs(this, SLOT(fileSaveAs()), actionCollection());
+// KStdAction::print(this, SLOT(filePrint()), actionCollection());
+ KStdAction::quit(this, SLOT(close()), actionCollection());
+
+ createStandardStatusBarAction();
+ setStandardToolBarMenuEnabled(true);
+
+ KStdAction::keyBindings(this, SLOT(optionsConfigureKeys()), actionCollection());
+ KStdAction::configureToolbars(this, SLOT(optionsConfigureToolbars()), actionCollection());
+ KStdAction::preferences(this, SLOT(optionsPreferences()), actionCollection());
+
+ new KAction(i18n("Mobile GUI"),0,this,SLOT(showMobileGui()),
+ actionCollection(),"show_mobilegui");
+
+ mConnectAction = new KAction(i18n("Connect"),0,this,SLOT(modemConnect()),
+ actionCollection(),"modem_connect");
+ mDisconnectAction = new KAction(i18n("Disconnect"),0,this,
+ SLOT(modemDisconnect()),actionCollection(),
+ "modem_disconnect");
+
+ createGUI();
+}
+
+void Kandy::saveProperties(KConfig */*config*/)
+{
+ // the 'config' object points to the session managed
+ // config file. anything you write here will be available
+ // later when this app is restored
+}
+
+void Kandy::readProperties(KConfig */*config*/)
+{
+ // the 'config' object points to the session managed
+ // config file. this function is automatically called whenever
+ // the app is being restored. read in here whatever you wrote
+ // in 'saveProperties'
+}
+
+void Kandy::dragEnterEvent(QDragEnterEvent *event)
+{
+ // do nothing
+ KMainWindow::dragEnterEvent(event);
+
+ // accept uri drops only
+// event->accept(KURLDrag::canDecode(event));
+}
+
+void Kandy::dropEvent(QDropEvent *event)
+{
+ // this is a very simplistic implementation of a drop event. we
+ // will only accept a dropped URL. the Qt dnd code can do *much*
+ // much more, so please read the docs there
+
+ // do nothing
+ KMainWindow::dropEvent(event);
+/*
+ KURL::List list;
+
+ // see if we can decode a URI.. if not, just ignore it
+ if (KURLDrag::decode(event, list) && !list.isEmpty())
+ {
+ // okay, we have a URI.. process it
+ const KURL &url = uri.first();
+
+ if (url.isLocalFile())
+ {
+ // load in the file
+ load(url.path());
+ }
+ }
+*/
+}
+
+void Kandy::fileOpen()
+{
+ // this slot is called whenever the File->Open menu is selected,
+ // the Open shortcut is pressed (usually CTRL+O) or the Open toolbar
+ // button is clicked
+ QString filename = KFileDialog::getOpenFileName();
+ if (!filename.isEmpty()) load(filename);
+}
+
+void Kandy::fileSave()
+{
+ if (mFilename.isEmpty()) fileSaveAs();
+ else save(mFilename);
+}
+
+void Kandy::fileSaveAs()
+{
+ QString filename = KFileDialog::getSaveFileName();
+ save(filename);
+}
+
+void Kandy::filePrint()
+{
+ // this slot is called whenever the File->Print menu is selected,
+ // the Print shortcut is pressed (usually CTRL+P) or the Print toolbar
+ // button is clicked
+ if (!mPrinter) mPrinter = new QPrinter;
+ if (QPrintDialog::getPrinterSetup(mPrinter))
+ {
+ // setup the printer. with Qt, you always "print" to a
+ // QPainter.. whether the output medium is a pixmap, a screen,
+ // or paper
+ QPainter p;
+ p.begin(mPrinter);
+
+ // we let our view do the actual printing
+ QPaintDeviceMetrics metrics(mPrinter);
+ mView->print(&p, metrics.height(), metrics.width());
+
+ // and send the result to the printer
+ p.end();
+ }
+}
+
+void Kandy::optionsConfigureKeys()
+{
+ KKeyDialog::configure( actionCollection(), this );
+}
+
+void Kandy::optionsConfigureToolbars()
+{
+ // use the standard toolbar editor
+ saveMainWindowSettings( KGlobal::config(), autoSaveGroup() );
+ KEditToolbar dlg(actionCollection());
+ connect(&dlg, SIGNAL(newToolbarConfig()), this, SLOT(newToolbarConfig()));
+ dlg.exec();
+}
+
+void Kandy::newToolbarConfig()
+{
+ // this slot is called when user clicks "Ok" or "Apply" in the toolbar editor.
+ // recreate our GUI, and re-apply the settings (e.g. "text under icons", etc.)
+ createGUI();
+ applyMainWindowSettings( KGlobal::config(), autoSaveGroup() );
+}
+
+void Kandy::optionsPreferences()
+{
+ if (!mPreferencesDialog) {
+ mPreferencesDialog = new KandyPrefsDialog(this);
+ mPreferencesDialog->readConfig();
+ }
+
+ mPreferencesDialog->show();
+ mPreferencesDialog->raise();
+}
+
+void Kandy::changeStatusbar(const QString& text)
+{
+ // display the text on the statusbar
+ statusBar()->message(text);
+}
+
+void Kandy::changeCaption(const QString& text)
+{
+ // display the text on the caption
+ setCaption(text);
+}
+
+void Kandy::setTitle()
+{
+ if (mFilename.isEmpty()) {
+ setCaption(i18n("New Profile"),mView->isModified());
+ } else {
+ setCaption(mFilename,mView->isModified());
+ }
+}
+
+bool Kandy::queryClose()
+{
+ if (mView->isModified()) {
+ switch (KMessageBox::warningYesNoCancel(this,
+ i18n("Save changes to profile %1?").arg(mFilename), QString::null, KStdGuiItem::save(), KStdGuiItem::discard())) {
+ case KMessageBox::Yes :
+ fileSave();
+ return true;
+ case KMessageBox::No :
+ return true;
+ default: // cancel
+ return false;
+ }
+ } else {
+ return true;
+ }
+}
+
+void Kandy::modemConnect()
+{
+ if (!mScheduler->modem()->open()) {
+ KMessageBox::sorry(this,
+ i18n("Cannot open modem device %1.")
+ .arg(KandyPrefs::serialDevice()), i18n("Modem Error"));
+ return;
+ }
+
+ statusBar()->changeItem(i18n(" Connected "),0);
+
+ emit connectStateChanged(true);
+}
+
+void Kandy::modemDisconnect()
+{
+ mScheduler->modem()->close();
+
+ statusBar()->changeItem(i18n(" Disconnected "),0);
+
+ emit connectStateChanged(false);
+}
+
+void Kandy::showMobileGui()
+{
+ emit showMobileWin();
+}
+
+void Kandy::showErrorMessage( const QString &text )
+{
+ KMessageBox::error( 0, text );
+}
diff --git a/kandy/src/kandy.desktop b/kandy/src/kandy.desktop
new file mode 100644
index 000000000..b003dd045
--- /dev/null
+++ b/kandy/src/kandy.desktop
@@ -0,0 +1,121 @@
+[Desktop Entry]
+Name=Kandy
+Name[hi]=केंडी
+Name[ne]=केनà¥à¤¡à¥€
+Name[ta]=Kஅனà¯à®Ÿà®¿
+Comment=Tool for syncing address book data with mobile phones
+Comment[af]=Program om die adres boek data met die van 'n selfoon te sinkroniseer
+Comment[bg]=ИнÑтрумент за Ñинхронизиране на адреÑника Ñ Ð¼Ð¾Ð±Ð¸Ð»Ð½Ð¸ телефони
+Comment[bs]=Alat za sinhroniziranje podataka između adresara i mobilnih telefona
+Comment[ca]=Eina per sincronitzar dades de la llibreta d'adreces amb telèfons mòbils
+Comment[cs]=Nástroj pro synchronizaci kontaktů s mobilními telefony
+Comment[da]=Værktøj til at synkronisere adressebogens data med mobiltelefoner
+Comment[de]=Werkzeug zum Abgleich von Adressbuchdaten mit dem Mobiltelefon
+Comment[el]=ΕÏγαλείο συγχÏÎ¿Î½Î¹ÏƒÎ¼Î¿Ï Î²Î¹Î²Î»Î¯Ï‰Î½ διευθÏνσεων με κινητά τηλέφωνα
+Comment[es]=Herramienta para sincronizar datos de la libreta de direcciones con teléfonos móviles
+Comment[et]=Vahend aadressiraamatu andmete sünkroniseerimiseks mobiiltelefoniga
+Comment[eu]=Helbide-liburua zure mugikorrarekin sinkronizatzeko tresna
+Comment[fa]=ابزار برای همگام‌سازی دادۀ کتاب نشانی با تلÙنهای همراه
+Comment[fi]=Osoitekirjan tietojan ja kännykän liitostyökalu
+Comment[fr]=Outil pour synchroniser les données de carnets d'adresses avec les téléphones mobiles
+Comment[fy]=Helpmiddel om adresboekdata te syngronisearjen mei mobile tillefoans
+Comment[gl]=Ferramenta para sincronizar os datos do caderno de enderezos con teléfonos móbiles
+Comment[hu]=Segédprogram számítógép és mobiltelefon címjegyzékének szinkronizálásához
+Comment[is]=Tól sem samstillir vistfangagögn við farsíma
+Comment[it]=Strumento per sincronizzare i dati della rubrica indirizzi con i telefoni cellulari
+Comment[ja]=アドレス帳ã®ãƒ‡ãƒ¼ã‚¿ã‚’æºå¸¯é›»è©±ã¨åŒæœŸã™ã‚‹ãŸã‚ã®ãƒ„ール
+Comment[ka]=მáƒáƒ‘ილურ ტელეფáƒáƒœáƒ—áƒáƒœ წიგნáƒáƒ™áƒ˜áƒ¡ მáƒáƒœáƒáƒªáƒ”მების სინქრáƒáƒœáƒ˜áƒ–áƒáƒªáƒ˜áƒ˜áƒ¡ ხელსáƒáƒ¬áƒ§áƒ
+Comment[kk]=ÐдреÑтік кітапшаны қалта телефонмен қадамдаÑтыру құралы
+Comment[km]=ឧបករណáŸâ€‹ážŸáž˜áŸ’រាប់​ធ្វើ​សមកាលកម្ម​ទិន្ននáŸáž™â€‹ážŸáŸ€ážœáž—ៅ​អាសយដ្ឋាន​ជាមួយ​នឹង​ទូរសáŸáž–្ទ​ចលáŸáž
+Comment[lt]=Įrankis adresų knygelės sinchronizavimui su mobiliaisiais telefonais
+Comment[mk]=Ðлатка за Ñинхронизирање адреÑари Ñо мобилни телефони
+Comment[ms]=Alat untuk segerakkan data buku alamat dengan telefon bimbit
+Comment[nb]=Verktøy for synkronisering av adressebok med mobiltelefoner
+Comment[nds]=Synkroniseren vun Adressbookdaten mit Mobiltelefonen
+Comment[ne]=मोबाइल फोनमा ठेगाना पà¥à¤¸à¥à¤¤à¤¿à¤•à¤¾ समकà¥à¤°à¤®à¤£ गरà¥à¤¨à¤•à¤¾ लागि उपकरण
+Comment[nl]=Hulpmiddel om adresboekgegevens te synchroniseren met mobiele telefoons
+Comment[nn]=Verktøy for å synkronisera adresseboka med mobiltelefonar
+Comment[pl]=Narzędzie do synchronizacji książki adresowej z telefonami komórkowymi
+Comment[pt]=Ferramenta para sincronizar dados do livro de endereços com telemóveis
+Comment[pt_BR]=Ferramenta para a sincronização dos dados do livro de endereços com dispositivos móveis
+Comment[ru]=Программа Ñинхронизации адреÑной книги Ñ Ð¼Ð¾Ð±Ð¸Ð»ÑŒÐ½Ñ‹Ð¼ телефоном
+Comment[sk]=Nástroj pre synchronizáciu adresára s mobilmi
+Comment[sl]=Orodje za usklajevanje podatkov adresarja z mobilnim telefonom
+Comment[sr]=Ðлат за Ñинхронизацију адреÑара Ñа мобилним телефонима
+Comment[sr@Latn]=Alat za sinhronizaciju adresara sa mobilnim telefonima
+Comment[sv]=Verktyg för att synkronisera adressboksdata med mobiltelefoner
+Comment[ta]= செலà¯à®ªà¯‡à®šà®¿ கொணà¯à®Ÿ à®®à¯à®•à®µà®°à®¿ பà¯à®¤à¯à®¤à®• தரவின௠ஒனà¯à®±à®¿à®£à¯ˆà®•à¯à®•à®ªà¯à®ªà®Ÿà¯à®µà®¤à®±à¯à®•à®¾à®© கரà¯à®µà®¿
+Comment[tg]=Барномаи ÑинхронизатÑиÑи китоби адреÑÓ£ бо телефони мобилӣ
+Comment[tr]=Cep telefonları ile adres defteri paylaşımı için araç
+Comment[uk]=ІнÑтрумент Ð´Ð»Ñ Ñинхронізації даних адреÑної книги з мобільним телефоном
+Comment[zh_CN]=将地å€ç°¿æ•°æ®ä¸Žç§»åŠ¨ç”µè¯åŒæ­¥çš„工具
+Comment[zh_TW]=將通訊錄與手機åŒæ­¥çš„工具
+Exec=kandy %i %m -caption "%c"
+Icon=kandy
+Type=Application
+GenericName=Mobile Phone Tool
+GenericName[af]=Mobiele Foon Program
+GenericName[bg]=Мобилни телефони
+GenericName[bs]=Alat za mobilne telefone
+GenericName[ca]=Eina per a telèfons mòbils
+GenericName[cs]=Nástroj pro mobilní telefony
+GenericName[cy]=Erfyn Ffôn Symudol
+GenericName[da]=Mobiltelefonværktøj
+GenericName[de]=Programm für Mobiltelefone
+GenericName[el]=ΕÏγαλείο κινητών τηλεφώνων
+GenericName[eo]=Ilo por poÅtelefono
+GenericName[es]=Gestor de teléfonos móviles
+GenericName[et]=Mobiiltelefoni rakendus
+GenericName[eu]=Telefono mugikorrendako Tresna
+GenericName[fa]=ابزار تلÙÙ† همراه
+GenericName[fi]=Matkapuhelintyökalu
+GenericName[fr]=Outil de connexion à votre téléphone portable
+GenericName[fy]=Mobiele tillefoan-behear
+GenericName[gl]=Ferramenta para o Teléfono Móbil
+GenericName[he]=כלי טלפון נייד
+GenericName[hi]=मोबाइल फोन उपकरण
+GenericName[hr]=Alat za mobitele
+GenericName[hu]=Mobil-címjegyzék
+GenericName[is]=Farsímatól
+GenericName[it]=Strumento per i telefoni cellulari
+GenericName[ja]=æºå¸¯é›»è©±ãƒ„ール
+GenericName[ka]=მáƒáƒ‘ილურ ტელეფáƒáƒœáƒ—áƒáƒœ სáƒáƒ›áƒ£áƒ¨áƒáƒ ხელსáƒáƒ¬áƒ§áƒ
+GenericName[kk]=Қалта телефон құралы
+GenericName[km]=ឧបករណáŸâ€‹áž‘ូរសáŸáž–្ទ​ចលáŸáž
+GenericName[lt]=Mobilaus telefono įrankis
+GenericName[lv]=MobÄ«lÄ Telefona RÄ«ks
+GenericName[mk]=Ðлатка за мобилни телефони
+GenericName[ms]=Alatan Fon Mudah Alih
+GenericName[nb]=Mobiltelefonverktøy
+GenericName[nds]=Mobiltelefoon-Warktüüch
+GenericName[ne]=मोबाइल फोन उपकरण
+GenericName[nl]=Mobiele telefoon-beheer
+GenericName[nn]=Mobiltelefonverktøy
+GenericName[nso]=Sebereka sago Thatha sa Mogala
+GenericName[pl]=ÅÄ…cznik z telefonem komórkowym
+GenericName[pt]=Ferramenta para Telemóveis
+GenericName[pt_BR]=Ferramenta de Telefonia Móvel
+GenericName[ro]=Utilitar telefon mobil
+GenericName[ru]=Работа Ñ Ð¼Ð¾Ð±Ð¸Ð»ÑŒÐ½Ñ‹Ð¼ телефоном
+GenericName[se]=Mátketelefuvdnareaidu
+GenericName[sk]=Nástroj pre mobily
+GenericName[sl]=Orodje za mobilni telefon
+GenericName[sr]=Ðлат за мобилни телефон
+GenericName[sr@Latn]=Alat za mobilni telefon
+GenericName[sv]=Verktyg för mobiltelefon
+GenericName[ta]=செலà¯à®ªà¯‡à®šà®¿ கரà¯à®µà®¿
+GenericName[tg]=Кор бо телефони мобилӣ
+GenericName[th]=เครื่องมือสำหรับโทรศัพท์เคลื่อนที่
+GenericName[tr]=Cep Telefonu Aracı
+GenericName[uk]=ЗаÑіб Ð´Ð»Ñ Ð¼Ð¾Ð±Ñ–Ð»ÑŒÐ½Ð¸Ñ… телефонів
+GenericName[uz]=Uyali telefon uchun vosita
+GenericName[uz@cyrillic]=УÑли телефон учун воÑита
+GenericName[ven]=Tshishumiswa tsha lutingo thendeleki
+GenericName[vi]=Công cụ điện thoại di động
+GenericName[xh]=Isixhobo Semfono-mfono Ekuhanjwa nayo
+GenericName[zh_CN]=移动电è¯å·¥å…·
+GenericName[zh_TW]=行動電話工具
+GenericName[zu]=Ithuluzi Lamakhala ekhukhwini
+Terminal=false
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;Utility;X-KDE-Utilities-Peripherals;Network;Telephony;
diff --git a/kandy/src/kandy.h b/kandy/src/kandy.h
new file mode 100644
index 000000000..ba2e66155
--- /dev/null
+++ b/kandy/src/kandy.h
@@ -0,0 +1,138 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+#ifndef KANDY_H
+#define KANDY_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kapplication.h>
+#include <kmainwindow.h>
+
+#include "kandyview.h"
+
+class QPrinter;
+
+class KandyPrefsDialog;
+
+/**
+ * This class serves as the main window for Kandy. It handles the
+ * menus, toolbars, and status bars.
+ *
+ * @short Main window class
+ * @author Cornelius Schumacher <schumacher@kde.org>
+ * @version 0.1
+ */
+class Kandy : public KMainWindow
+{
+ Q_OBJECT
+ public:
+ /**
+ * Default Constructor
+ */
+ Kandy(CommandScheduler *);
+
+ /**
+ * Default Destructor
+ */
+ virtual ~Kandy();
+
+ /**
+ * Use this method to load whatever file/URL you have
+ */
+ void load(const QString& url);
+ void save(const QString& url);
+
+ public slots:
+ void setTitle();
+
+ void modemConnect();
+
+ void showErrorMessage( const QString & );
+
+ signals:
+ void showMobileWin();
+ void connectStateChanged(bool);
+
+ protected:
+ /**
+ * Overridden virtuals for Qt drag 'n drop (XDND)
+ */
+ virtual void dragEnterEvent(QDragEnterEvent *event);
+ virtual void dropEvent(QDropEvent *event);
+
+ bool queryClose();
+
+ protected:
+ /**
+ * This function is called when it is time for the app to save its
+ * properties for session management purposes.
+ */
+ void saveProperties(KConfig *);
+
+ /**
+ * This function is called when this app is restored. The KConfig
+ * object points to the session management config file that was saved
+ * with @ref saveProperties
+ */
+ void readProperties(KConfig *);
+
+
+ private slots:
+ void fileOpen();
+ void fileSave();
+ void fileSaveAs();
+ void filePrint();
+ void optionsConfigureKeys();
+ void optionsConfigureToolbars();
+ void optionsPreferences();
+ void modemDisconnect();
+ void showMobileGui();
+ void newToolbarConfig();
+
+ void changeStatusbar(const QString& text);
+ void changeCaption(const QString& text);
+
+
+ private:
+ void setupAccel();
+ void setupActions();
+
+ private:
+ CommandScheduler *mScheduler;
+
+ KandyView *mView;
+
+ QPrinter *mPrinter;
+
+ KAction *mConnectAction;
+ KAction *mDisconnectAction;
+
+ QString mFilename;
+
+ KandyPrefsDialog *mPreferencesDialog;
+};
+
+#endif // KANDY_H
diff --git a/kandy/src/kandy.kcfg b/kandy/src/kandy.kcfg
new file mode 100644
index 000000000..a93f674b8
--- /dev/null
+++ b/kandy/src/kandy.kcfg
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kandyrc"/>
+
+ <group name="Serial Port">
+ <entry type="String" key="Serial Device">
+ <label>Serial device</label>
+ <default>/dev/ttyS1</default>
+ </entry>
+ <entry type="String" key="Baud Rate">
+ <label>Baud rate</label>
+ <default>115200</default>
+ </entry>
+ <entry type="String" key="Lock Directory">
+ <label>Lock directory</label>
+ <default>/var/lock</default>
+ </entry>
+ <entry type="Bool" name="StartupModem">
+ <label>Open modem on startup</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="AutoSetClock">
+ <label>Auto-set clock of mobile on connection</label>
+ <default>true</default>
+ </entry>
+ </group>
+
+ <group name="Addressbook">
+ <entry type="Bool" name="ExcludeHome">
+ <label>Exclude home numbers</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="ExcludeWork">
+ <label>Exclude work numbers</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="ExcludeMessaging">
+ <label>Exclude messaging numbers</label>
+ <default>true</default>
+ </entry>
+ <entry type="Bool" name="ExcludeFax">
+ <label>Exclude fax numbers</label>
+ <default>true</default>
+ </entry>
+ <entry type="Bool" name="ExcludeCell">
+ <label>Exclude cell numbers</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="ExcludeVideo">
+ <label>Exclude video phone numbers</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="ExcludeMailbox">
+ <label>Exclude mailbox numbers</label>
+ <default>true</default>
+ </entry>
+ <entry type="Bool" name="ExcludeModem">
+ <label>Exclude modem numbers</label>
+ <default>true</default>
+ </entry>
+ <entry type="Bool" name="ExcludeCar">
+ <label>Exclude car phone numbers</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="ExcludeISDN">
+ <label>Exclude ISDN numbers</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="ExcludePager">
+ <label>Exclude pager numbers</label>
+ <default>true</default>
+ </entry>
+
+ <entry type="Bool" name="UseHomeSuff">
+ <label>Use home suffix</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="UseWorkSuff">
+ <label>Use work suffix</label>
+ <default>true</default>
+ </entry>
+ <entry type="Bool" name="UseMessagingSuff">
+ <label>Use messaging suffix</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="UseFaxSuff">
+ <label>Use fax suffix</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="UseCellSuff">
+ <label>Use mobile suffix</label>
+ <default>true</default>
+ </entry>
+ <entry type="Bool" name="UseVideoSuff">
+ <label>Use video suffix</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="UseMailboxSuff">
+ <label>Use mailbox suffix</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="UseModemSuff">
+ <label>Use modem suffix</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="UseCarSuff">
+ <label>Use car suffix</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="UseISDNSuff">
+ <label>Use ISDN suffix</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="UsePagerSuff">
+ <label>Use pager suffix</label>
+ <default>false</default>
+ </entry>
+
+ <entry type="String" name="HomeSuff">
+ <label>Home suffix</label>
+ <default></default>
+ </entry>
+ <entry type="String" name="WorkSuff">
+ <label>Work suffix</label>
+ <default>"\"0B\""</default>
+ </entry>
+ <entry type="String" name="MessagingSuff">
+ <label>Messaging suffix</label>
+ <default></default>
+ </entry>
+ <entry type="String" name="FaxSuff">
+ <label>Fax suffix</label>
+ <default></default>
+ </entry>
+ <entry type="String" name="CellSuff">
+ <label>Cell suffix</label>
+ <default>"\"17\""</default>
+ </entry>
+ <entry type="String" name="VideoSuff">
+ <label>Video suffix</label>
+ <default></default>
+ </entry>
+ <entry type="String" name="MailboxSuff">
+ <label>Mailbox suffix</label>
+ <default></default>
+ </entry>
+ <entry type="String" name="ModemSuff">
+ <label>Modem suffix</label>
+ <default></default>
+ </entry>
+ <entry type="String" name="CarSuff">
+ <label>Car suffix</label>
+ <default></default>
+ </entry>
+ <entry type="String" name="ISDNSuff">
+ <label>ISDN suffix</label>
+ <default></default>
+ </entry>
+ <entry type="String" name="PagerSuff">
+ <label>Pager suffix</label>
+ <default></default>
+ </entry>
+
+ </group>
+
+ <group name="Windows">
+ <entry type="Bool" name="StartupTerminalWin">
+ <label>Open terminal window on startup</label>
+ <default>false</default>
+ </entry>
+ <entry type="Bool" name="StartupMobileWin">
+ <label>Open mobile window on startup</label>
+ <default>true</default>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/kandy/src/kandy_client.cpp b/kandy/src/kandy_client.cpp
new file mode 100644
index 000000000..ece43f5da
--- /dev/null
+++ b/kandy/src/kandy_client.cpp
@@ -0,0 +1,48 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <kapplication.h>
+#include <dcopclient.h>
+#include <qdatastream.h>
+#include <qstring.h>
+
+int main(int argc, char **argv)
+{
+ KApplication app(argc, argv, "kandy_client", false);
+
+ // get our DCOP client and attach so that we may use it
+ DCOPClient *client = app.dcopClient();
+ client->attach();
+
+ // do a 'send' for now
+ QByteArray data;
+ QDataStream ds(data, IO_WriteOnly);
+ if (argc > 1)
+ ds << QString(argv[1]);
+ else
+ ds << QString("http://www.kde.org");
+ client->send("kandy", "KandyIface", "openURL(QString)", data);
+
+ return app.exec();
+}
diff --git a/kandy/src/kandyiface.h b/kandy/src/kandyiface.h
new file mode 100644
index 000000000..3b45bd013
--- /dev/null
+++ b/kandy/src/kandyiface.h
@@ -0,0 +1,39 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+#ifndef KANDYIFACE_H
+#define KANDYIFACE_H
+
+#include <dcopobject.h>
+
+class KandyIface : virtual public DCOPObject
+{
+ K_DCOP
+ public:
+
+ k_dcop:
+ virtual void syncPhonebooks() = 0;
+ virtual void exit() = 0;
+};
+
+#endif // KANDYIFACE_H
diff --git a/kandy/src/kandymobileui.rc b/kandy/src/kandymobileui.rc
new file mode 100644
index 000000000..aad843734
--- /dev/null
+++ b/kandy/src/kandymobileui.rc
@@ -0,0 +1,8 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="kandy" version="1">
+<MenuBar>
+ <Menu name="show"><text>&amp;Show</text>
+ <Action name="show_terminal" />
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/kandy/src/kandyprefs.kcfgc b/kandy/src/kandyprefs.kcfgc
new file mode 100644
index 000000000..1be429c46
--- /dev/null
+++ b/kandy/src/kandyprefs.kcfgc
@@ -0,0 +1,11 @@
+# Code generation options for kconfig_compiler
+File=kandy.kcfg
+ClassName=KandyPrefs
+Singleton=true
+Mutators=true
+#Inherits=KPimPrefs
+#IncludeFiles=libkdepim/kpimprefs.h
+MemberVariables=public
+#GlobalEnums=true
+ItemAccessors=true
+SetUserTexts=true
diff --git a/kandy/src/kandyprefsdialog.cpp b/kandy/src/kandyprefsdialog.cpp
new file mode 100644
index 000000000..d25688ff9
--- /dev/null
+++ b/kandy/src/kandyprefsdialog.cpp
@@ -0,0 +1,369 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+#include <qbuttongroup.h>
+#include <qlineedit.h>
+#include <qfont.h>
+#include <qslider.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qcombobox.h>
+#include <qvbox.h>
+#include <qhbox.h>
+#include <qspinbox.h>
+#include <qdatetime.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kfontdialog.h>
+#include <kstandarddirs.h>
+#include <kmessagebox.h>
+#include <kcolordialog.h>
+#include <kiconloader.h>
+#include <kiconeffect.h>
+
+#include "kandyprefs.h"
+
+#include "kandyprefsdialog.h"
+#include "kandyprefsdialog.moc"
+
+
+KandyPrefsDialog::KandyPrefsDialog(QWidget *parent, char *name, bool modal) :
+ KPrefsDialog(KandyPrefs::self(),parent,name,modal)
+{
+ setupSerialTab();
+ setupAddressbookTab();
+ setupWindowsTab();
+}
+
+
+KandyPrefsDialog::~KandyPrefsDialog()
+{
+ delete serialDevice;
+ delete lockDir;
+ delete openOnStartup;
+ delete startupTerminal;
+ delete startupMobile;
+}
+
+void KandyPrefsDialog::setupSerialTab()
+{
+ QFrame *topFrame = addPage(i18n("Serial Interface"),0,
+ DesktopIcon("connect_no",KIcon::SizeMedium));
+
+ QGridLayout *topLayout = new QGridLayout(topFrame,6,2);
+ topLayout->setSpacing(spacingHint());
+ topLayout->setMargin(marginHint());
+
+ // Define serial device
+ serialDevice = addWidString( KandyPrefs::self()->serialDeviceItem(),
+ topFrame );
+ topLayout->addWidget(serialDevice->label(),0,0);
+ topLayout->addWidget(serialDevice->lineEdit(),0,1);
+
+ // Define baud rate
+ baudRate = addWidString( KandyPrefs::self()->baudRateItem(), topFrame );
+ topLayout->addWidget( baudRate->label(), 1, 0 );
+ topLayout->addWidget( baudRate->lineEdit(), 1, 1 );
+
+ // Define location of LOCK file
+ lockDir = addWidString( KandyPrefs::self()->lockDirectoryItem(),
+ topFrame );
+ topLayout->addWidget(lockDir->label(),2,0);
+ topLayout->addWidget(lockDir->lineEdit(),2,1);
+
+ // Define startup modem behavior
+ openOnStartup = addWidBool( KandyPrefs::self()->startupModemItem(),
+ topFrame );
+ topLayout->addWidget(openOnStartup->checkBox(),3,0);
+
+ // Define clock setting hevahior
+ autoSetClock = addWidBool( KandyPrefs::self()->autoSetClockItem(),
+ topFrame );
+ topLayout->addWidget(autoSetClock->checkBox(),4,0);
+
+ topLayout->setRowStretch(5,1);
+}
+
+void KandyPrefsDialog::setupAddressbookTab()
+{
+ QFrame *topFrame = addPage(i18n("Address Book"), 0,
+ DesktopIcon("kaddressbook", KIcon::SizeMedium));
+
+ QGridLayout *topLayout = new QGridLayout(topFrame, 13, 4);
+ topLayout->setSpacing(spacingHint());
+ topLayout->setMargin(marginHint());
+
+ excHome = addWidBool ( KandyPrefs::self()->excludeHomeItem(), topFrame );
+ topLayout->addWidget(excHome->checkBox(), 0, 0);
+
+ excWork = addWidBool ( KandyPrefs::self()->excludeWorkItem(), topFrame );
+ topLayout->addWidget(excWork->checkBox(), 1, 0);
+
+ excMsg = addWidBool ( KandyPrefs::self()->excludeMessagingItem(), topFrame );
+ topLayout->addWidget(excMsg->checkBox(), 2, 0);
+
+ excFax = addWidBool ( KandyPrefs::self()->excludeFaxItem(), topFrame );
+ topLayout->addWidget(excFax->checkBox(), 3, 0);
+
+ excCell = addWidBool ( KandyPrefs::self()->excludeCellItem(), topFrame );
+ topLayout->addWidget(excCell->checkBox(), 4, 0);
+
+ excVideo = addWidBool ( KandyPrefs::self()->excludeVideoItem(), topFrame );
+ topLayout->addWidget(excVideo->checkBox(), 5, 0);
+
+ excBbs = addWidBool ( KandyPrefs::self()->excludeMailboxItem(), topFrame );
+ topLayout->addWidget(excBbs->checkBox(), 6, 0);
+
+ excModem = addWidBool ( KandyPrefs::self()->excludeModemItem(), topFrame );
+ topLayout->addWidget(excModem->checkBox(), 7, 0);
+
+ excCar = addWidBool ( KandyPrefs::self()->excludeCarItem(), topFrame );
+ topLayout->addWidget(excCar->checkBox(), 8, 0);
+
+ excISDN = addWidBool ( KandyPrefs::self()->excludeISDNItem(), topFrame );
+ topLayout->addWidget(excISDN->checkBox(), 9, 0);
+
+ excPager = addWidBool ( KandyPrefs::self()->excludePagerItem(), topFrame );
+ topLayout->addWidget(excPager->checkBox(), 10, 0);
+
+
+ useHomeSuff = addWidBool ( KandyPrefs::self()->useHomeSuffItem(), topFrame );
+ topLayout->addWidget(useHomeSuff->checkBox(), 0, 1);
+
+ useWorkSuff = addWidBool ( KandyPrefs::self()->useWorkSuffItem(), topFrame );
+ topLayout->addWidget(useWorkSuff->checkBox(), 1, 1);
+
+ useMessagingSuff = addWidBool ( KandyPrefs::self()->useMessagingSuffItem(), topFrame );
+ topLayout->addWidget(useMessagingSuff->checkBox(), 2, 1);
+
+ useFaxSuff = addWidBool ( KandyPrefs::self()->useFaxSuffItem(), topFrame );
+ topLayout->addWidget(useFaxSuff->checkBox(), 3, 1);
+
+ useCellSuff = addWidBool ( KandyPrefs::self()->useCellSuffItem(), topFrame );
+ topLayout->addWidget(useCellSuff->checkBox(), 4, 1);
+
+ useVideoSuff = addWidBool ( KandyPrefs::self()->useVideoSuffItem(), topFrame );
+ topLayout->addWidget(useVideoSuff->checkBox(), 5, 1);
+
+ useMailboxSuff = addWidBool ( KandyPrefs::self()->useMailboxSuffItem(), topFrame );
+ topLayout->addWidget(useMailboxSuff->checkBox(), 6, 1);
+
+ useModemSuff = addWidBool ( KandyPrefs::self()->useModemSuffItem(), topFrame );
+ topLayout->addWidget(useModemSuff->checkBox(), 7, 1);
+
+ useCarSuff = addWidBool ( KandyPrefs::self()->useCarSuffItem(), topFrame );
+ topLayout->addWidget(useCarSuff->checkBox(), 8, 1);
+
+ useISDNSuff = addWidBool ( KandyPrefs::self()->useISDNSuffItem(), topFrame );
+ topLayout->addWidget(useISDNSuff->checkBox(), 9, 1);
+
+ usePagerSuff = addWidBool ( KandyPrefs::self()->usePagerSuffItem(), topFrame );
+ topLayout->addWidget(usePagerSuff->checkBox(), 10, 1);
+
+
+ HomeSuff = addWidString( KandyPrefs::self()->homeSuffItem(), topFrame );
+ topLayout->addWidget(HomeSuff->label(), 0, 2);
+ topLayout->addWidget(HomeSuff->lineEdit(), 0, 3);
+
+ WorkSuff = addWidString( KandyPrefs::self()->workSuffItem(), topFrame );
+ topLayout->addWidget(WorkSuff->label(), 1, 2);
+ topLayout->addWidget(WorkSuff->lineEdit(), 1, 3);
+
+ MessagingSuff = addWidString( KandyPrefs::self()->messagingSuffItem(), topFrame );
+ topLayout->addWidget(MessagingSuff->label(), 2, 2);
+ topLayout->addWidget(MessagingSuff->lineEdit(), 2, 3);
+
+ FaxSuff = addWidString( KandyPrefs::self()->faxSuffItem(), topFrame );
+ topLayout->addWidget(FaxSuff->label(), 3, 2);
+ topLayout->addWidget(FaxSuff->lineEdit(), 3, 3);
+
+ CellSuff = addWidString( KandyPrefs::self()->cellSuffItem(), topFrame );
+ topLayout->addWidget(CellSuff->label(), 4, 2);
+ topLayout->addWidget(CellSuff->lineEdit(), 4, 3);
+
+ VideoSuff = addWidString( KandyPrefs::self()->videoSuffItem(), topFrame );
+ topLayout->addWidget(VideoSuff->label(), 5, 2);
+ topLayout->addWidget(VideoSuff->lineEdit(), 5, 3);
+
+ MailboxSuff = addWidString( KandyPrefs::self()->mailboxSuffItem(), topFrame );
+ topLayout->addWidget(MailboxSuff->label(), 6, 2);
+ topLayout->addWidget(MailboxSuff->lineEdit(), 6, 3);
+
+ ModemSuff = addWidString( KandyPrefs::self()->modemSuffItem(), topFrame );
+ topLayout->addWidget(ModemSuff->label(), 7, 2);
+ topLayout->addWidget(ModemSuff->lineEdit(), 7, 3);
+
+ CarSuff = addWidString( KandyPrefs::self()->carSuffItem(), topFrame );
+ topLayout->addWidget(CarSuff->label(), 8, 2);
+ topLayout->addWidget(CarSuff->lineEdit(), 8, 3);
+
+ ISDNSuff = addWidString( KandyPrefs::self()->iSDNSuffItem(), topFrame );
+ topLayout->addWidget(ISDNSuff->label(), 9, 2);
+ topLayout->addWidget(ISDNSuff->lineEdit(), 9, 3);
+
+ PagerSuff = addWidString( KandyPrefs::self()->pagerSuffItem(), topFrame );
+ topLayout->addWidget(PagerSuff->label(), 10, 2);
+ topLayout->addWidget(PagerSuff->lineEdit(), 10, 3);
+
+
+ topLayout->setRowStretch(11, 1);
+
+ if ( !KandyPrefs::self()->useHomeSuff() )
+ {
+ HomeSuff->lineEdit()->setEnabled( false );
+ HomeSuff->label()->setEnabled( false );
+ }
+ if ( !KandyPrefs::self()->useWorkSuff() )
+ {
+ WorkSuff->lineEdit()->setEnabled( false );
+ WorkSuff->label()->setEnabled( false );
+ }
+ if ( !KandyPrefs::self()->useMessagingSuff() )
+ {
+ MessagingSuff->lineEdit()->setEnabled( false );
+ MessagingSuff->label()->setEnabled( false );
+ }
+ if ( !KandyPrefs::self()->useFaxSuff() )
+ {
+ FaxSuff->lineEdit()->setEnabled( false );
+ FaxSuff->label()->setEnabled( false );
+ }
+ if ( !KandyPrefs::self()->useCellSuff() )
+ {
+ CellSuff->lineEdit()->setEnabled( false );
+ CellSuff->label()->setEnabled( false );
+ }
+ if ( !KandyPrefs::self()->useVideoSuff() )
+ {
+ VideoSuff->lineEdit()->setEnabled( false );
+ VideoSuff->label()->setEnabled( false );
+ }
+ if ( !KandyPrefs::self()->useMailboxSuff() )
+ {
+ MailboxSuff->lineEdit()->setEnabled( false );
+ MailboxSuff->label()->setEnabled( false );
+ }
+ if ( !KandyPrefs::self()->useModemSuff() )
+ {
+ ModemSuff->lineEdit()->setEnabled( false );
+ ModemSuff->label()->setEnabled( false );
+ }
+ if ( !KandyPrefs::self()->useCarSuff() )
+ {
+ CarSuff->lineEdit()->setEnabled( false );
+ CarSuff->label()->setEnabled( false );
+ }
+ if ( !KandyPrefs::self()->useISDNSuff() )
+ {
+ ISDNSuff->lineEdit()->setEnabled( false );
+ ISDNSuff->label()->setEnabled( false );
+ }
+ if ( !KandyPrefs::self()->usePagerSuff() )
+ {
+ PagerSuff->lineEdit()->setEnabled( false );
+ PagerSuff->label()->setEnabled( false );
+ }
+
+
+ connect( useHomeSuff->checkBox(), SIGNAL(toggled(bool)),
+ HomeSuff->lineEdit(), SLOT(setEnabled(bool)) );
+ connect( useHomeSuff->checkBox(), SIGNAL(toggled(bool)),
+ HomeSuff->label(), SLOT(setEnabled(bool)) );
+
+ connect( useWorkSuff->checkBox(), SIGNAL(toggled(bool)),
+ WorkSuff->lineEdit(), SLOT(setEnabled(bool)) );
+ connect( useWorkSuff->checkBox(), SIGNAL(toggled(bool)),
+ WorkSuff->label(), SLOT(setEnabled(bool)) );
+
+ connect( useMessagingSuff->checkBox(), SIGNAL(toggled(bool)),
+ MessagingSuff->lineEdit(), SLOT(setEnabled(bool)) );
+ connect( useMessagingSuff->checkBox(), SIGNAL(toggled(bool)),
+ MessagingSuff->label(), SLOT(setEnabled(bool)) );
+
+ connect( useFaxSuff->checkBox(), SIGNAL(toggled(bool)),
+ FaxSuff->lineEdit(), SLOT(setEnabled(bool)) );
+ connect( useFaxSuff->checkBox(), SIGNAL(toggled(bool)),
+ FaxSuff->label(), SLOT(setEnabled(bool)) );
+
+ connect( useCellSuff->checkBox(), SIGNAL(toggled(bool)),
+ CellSuff->lineEdit(), SLOT(setEnabled(bool)) );
+ connect( useCellSuff->checkBox(), SIGNAL(toggled(bool)),
+ CellSuff->label(), SLOT(setEnabled(bool)) );
+
+ connect( useVideoSuff->checkBox(), SIGNAL(toggled(bool)),
+ VideoSuff->lineEdit(), SLOT(setEnabled(bool)) );
+ connect( useVideoSuff->checkBox(), SIGNAL(toggled(bool)),
+ VideoSuff->label(), SLOT(setEnabled(bool)) );
+
+ connect( useMailboxSuff->checkBox(), SIGNAL(toggled(bool)),
+ MailboxSuff->lineEdit(), SLOT(setEnabled(bool)) );
+ connect( useMailboxSuff->checkBox(), SIGNAL(toggled(bool)),
+ MailboxSuff->label(), SLOT(setEnabled(bool)) );
+
+ connect( useModemSuff->checkBox(), SIGNAL(toggled(bool)),
+ ModemSuff->lineEdit(), SLOT(setEnabled(bool)) );
+ connect( useModemSuff->checkBox(), SIGNAL(toggled(bool)),
+ ModemSuff->label(), SLOT(setEnabled(bool)) );
+
+ connect( useCarSuff->checkBox(), SIGNAL(toggled(bool)),
+ CarSuff->lineEdit(), SLOT(setEnabled(bool)) );
+ connect( useCarSuff->checkBox(), SIGNAL(toggled(bool)),
+ CarSuff->label(), SLOT(setEnabled(bool)) );
+
+ connect( useISDNSuff->checkBox(), SIGNAL(toggled(bool)),
+ ISDNSuff->lineEdit(), SLOT(setEnabled(bool)) );
+ connect( useISDNSuff->checkBox(), SIGNAL(toggled(bool)),
+ ISDNSuff->label(), SLOT(setEnabled(bool)) );
+
+ connect( usePagerSuff->checkBox(), SIGNAL(toggled(bool)),
+ PagerSuff->lineEdit(), SLOT(setEnabled(bool)) );
+ connect( usePagerSuff->checkBox(), SIGNAL(toggled(bool)),
+ PagerSuff->label(), SLOT(setEnabled(bool)) );
+}
+
+void KandyPrefsDialog::setupWindowsTab()
+{
+ QFrame *topFrame = addPage(i18n("Windows"),0,
+ DesktopIcon("window_list",KIcon::SizeMedium));
+
+ QGridLayout *topLayout = new QGridLayout(topFrame,6,2);
+ topLayout->setSpacing(spacingHint());
+ topLayout->setMargin(marginHint());
+
+ startupTerminal = addWidBool( KandyPrefs::self()->startupTerminalWinItem(),
+ topFrame);
+ topLayout->addWidget(startupTerminal->checkBox(),0,0);
+
+ startupMobile = addWidBool( KandyPrefs::self()->startupMobileWinItem(),
+ topFrame );
+ topLayout->addWidget(startupMobile->checkBox(),1,0);
+
+ topLayout->setRowStretch(2, 1);
+}
diff --git a/kandy/src/kandyprefsdialog.h b/kandy/src/kandyprefsdialog.h
new file mode 100644
index 000000000..5d63331c5
--- /dev/null
+++ b/kandy/src/kandyprefsdialog.h
@@ -0,0 +1,102 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#ifndef _KANDYPREFSDIALOG_H
+#define _KANDYPREFSDIALOG_H
+
+#include <qframe.h>
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qpushbutton.h>
+
+#include <kdialogbase.h>
+
+#include <libkdepim/kprefsdialog.h>
+
+/**
+ Dialog to change the kandy configuration.
+*/
+class KandyPrefsDialog : public KPrefsDialog
+{
+ Q_OBJECT
+ public:
+ /** Initialize dialog and pages */
+ KandyPrefsDialog(QWidget *parent=0,char *name=0,bool modal=false);
+ ~KandyPrefsDialog();
+
+ protected:
+ void setupSerialTab();
+ void setupAddressbookTab();
+ void setupWindowsTab();
+ private:
+ KPrefsWidString *serialDevice;
+ KPrefsWidString *baudRate;
+ KPrefsWidString *lockDir;
+ KPrefsWidBool *openOnStartup;
+ KPrefsWidBool *autoSetClock;
+
+ KPrefsWidBool *excHome;
+ KPrefsWidBool *excWork;
+ KPrefsWidBool *excMsg;
+ KPrefsWidBool *excFax;
+ KPrefsWidBool *excCell;
+ KPrefsWidBool *excVideo;
+ KPrefsWidBool *excBbs;
+ KPrefsWidBool *excModem;
+ KPrefsWidBool *excCar;
+ KPrefsWidBool *excISDN;
+ KPrefsWidBool *excPager;
+
+ KPrefsWidBool *useHomeSuff;
+ KPrefsWidBool *useWorkSuff;
+ KPrefsWidBool *useMessagingSuff;
+ KPrefsWidBool *useFaxSuff;
+ KPrefsWidBool *useCellSuff;
+ KPrefsWidBool *useVideoSuff;
+ KPrefsWidBool *useMailboxSuff;
+ KPrefsWidBool *useModemSuff;
+ KPrefsWidBool *useCarSuff;
+ KPrefsWidBool *useISDNSuff;
+ KPrefsWidBool *usePagerSuff;
+
+ KPrefsWidString *HomeSuff;
+ KPrefsWidString *WorkSuff;
+ KPrefsWidString *MessagingSuff;
+ KPrefsWidString *FaxSuff;
+ KPrefsWidString *CellSuff;
+ KPrefsWidString *VideoSuff;
+ KPrefsWidString *MailboxSuff;
+ KPrefsWidString *ModemSuff;
+ KPrefsWidString *CarSuff;
+ KPrefsWidString *ISDNSuff;
+ KPrefsWidString *PagerSuff;
+
+ KPrefsWidBool *startupTerminal;
+ KPrefsWidBool *startupMobile;
+ KPrefsWidString *DisplayWidth;
+};
+
+#endif
diff --git a/kandy/src/kandyui.rc b/kandy/src/kandyui.rc
new file mode 100644
index 000000000..0555c499e
--- /dev/null
+++ b/kandy/src/kandyui.rc
@@ -0,0 +1,8 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui name="kandy" version="2">
+<MenuBar>
+ <Menu name="show"><text>&amp;Show</text>
+ <Action name="show_mobilegui" />
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/kandy/src/kandyview.cpp b/kandy/src/kandyview.cpp
new file mode 100644
index 000000000..5b9f06194
--- /dev/null
+++ b/kandy/src/kandyview.cpp
@@ -0,0 +1,319 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <unistd.h>
+
+#include <qpainter.h>
+#include <qlayout.h>
+#include <qhbox.h>
+#include <qvbox.h>
+#include <qtextedit.h>
+#include <qlistview.h>
+#include <qdom.h>
+#include <qtextstream.h>
+#include <qfile.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+
+#include <kurl.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kconfig.h>
+#include <kinputdialog.h>
+#include <kdialog.h>
+
+#include "modem.h"
+#include "cmdpropertiesdialog.h"
+#include "commanditem.h"
+#include "atcommand.h"
+#include "commandscheduler.h"
+#include "kandyprefs.h"
+
+#include "kandyview.h"
+#include "kandyview.moc"
+
+KandyView::KandyView(CommandScheduler *scheduler,QWidget *parent)
+ : QWidget(parent)
+{
+ mModified = false;
+ mScheduler = scheduler;
+
+ QBoxLayout *topLayout = new QVBoxLayout( this );
+
+ QSplitter *mainSplitter = new QSplitter( Horizontal, this );
+ topLayout->addWidget( mainSplitter );
+
+ QWidget *commandBox = new QWidget( mainSplitter );
+
+ QBoxLayout *commandLayout = new QVBoxLayout( commandBox );
+ commandLayout->setMargin( KDialog::marginHint() );
+ commandLayout->setSpacing( KDialog::spacingHint() );
+
+ mCommandList = new QListView( commandBox );
+ mCommandList->addColumn( i18n( "Name" ) );
+ mCommandList->addColumn( i18n( "Command" ) );
+ mCommandList->addColumn( i18n( "Hex" ) );
+ commandLayout->addWidget( mCommandList );
+
+ connect( mCommandList, SIGNAL( doubleClicked(QListViewItem*) ),
+ SLOT( executeCommand() ) );
+
+ QPushButton *buttonAdd = new QPushButton( i18n("Add..."), commandBox );
+ commandLayout->addWidget( buttonAdd );
+ connect( buttonAdd, SIGNAL( clicked() ), SLOT( addCommand() ) );
+
+ QPushButton *buttonEdit = new QPushButton( i18n("Edit..."), commandBox );
+ commandLayout->addWidget( buttonEdit );
+ connect( buttonEdit, SIGNAL( clicked() ), SLOT( editCommand() ) );
+
+ QPushButton *buttonDelete = new QPushButton( i18n("Delete"), commandBox );
+ commandLayout->addWidget( buttonDelete );
+ connect( buttonDelete, SIGNAL( clicked() ), SLOT( deleteCommand() ) );
+
+ QPushButton *buttonExecute = new QPushButton( i18n("Execute"), commandBox );
+ commandLayout->addWidget( buttonExecute );
+ connect( buttonExecute, SIGNAL( clicked() ), SLOT( executeCommand() ) );
+
+ QSplitter *ioSplitter = new QSplitter( Vertical, mainSplitter );
+
+ QWidget *inBox = new QWidget( ioSplitter );
+
+ QBoxLayout *inLayout = new QVBoxLayout( inBox );
+
+ QLabel *inLabel = new QLabel( i18n("Input:"), inBox );
+ inLabel->setMargin( 2 );
+ inLayout->addWidget( inLabel );
+
+ mInput = new QTextEdit( inBox );
+ inLayout->addWidget( mInput );
+
+ QWidget *outBox = new QWidget( ioSplitter );
+
+ QBoxLayout *outLayout = new QVBoxLayout( outBox );
+
+ QLabel *outLabel = new QLabel( i18n( "Output:"), outBox );
+ outLabel->setMargin( 2 );
+ outLayout->addWidget( outLabel );
+
+ mOutput = new QTextEdit( outBox );
+ mOutput->setReadOnly( true );
+ outLayout->addWidget( mOutput );
+
+ QVBox *resultBox = new QVBox( mainSplitter );
+
+ QLabel *resultLabel = new QLabel( i18n("Result:"), resultBox );
+ resultLabel->setMargin( 2 );
+
+ mResultView = new QTextEdit( resultBox );
+ mResultView->setReadOnly( true );
+
+ connect (mInput,SIGNAL(returnPressed()),SLOT(processLastLine()));
+
+ connect(mScheduler->modem(),SIGNAL(gotLine(const char *)),
+ SLOT(appendOutput(const char *)));
+
+ connect(mScheduler,SIGNAL(result(const QString &)),
+ mResultView,SLOT(setText(const QString &)));
+ connect(mScheduler,SIGNAL(commandProcessed(ATCommand *)),
+ SLOT(setResult(ATCommand *)));
+}
+
+KandyView::~KandyView()
+{
+}
+
+
+void KandyView::print(QPainter *, int, int)
+{
+ // do the actual printing, here
+ // p->drawText(etc..)
+}
+
+void KandyView::importPhonebook()
+{
+#if 0
+ createMobileGui();
+ connect (mMobileGui,SIGNAL(phonebookRead()),mMobileGui,SLOT(writeKab()));
+ mMobileGui->readPhonebook();
+#endif
+}
+
+void KandyView::slotSetTitle(const QString& title)
+{
+ emit signalChangeCaption(title);
+}
+
+void KandyView::processLastLine()
+{
+ int para = 0;
+ int row = 0;
+ mInput->getCursorPosition( &para, &row );
+
+ if ( para > 0 ) {
+ mLastInput = mInput->text( para - 1 );
+
+ kdDebug(5960) << "processLastLine(): " << mLastInput << endl;
+
+ mScheduler->execute(mLastInput);
+ }
+}
+
+void KandyView::appendOutput(const char *line)
+{
+// kdDebug(5960) << "OUT: " << line << endl;
+ mOutput->append(line);
+ mOutput->setCursorPosition(mOutput->paragraphs()-1,0);
+}
+
+void KandyView::setResult(ATCommand *command)
+{
+ if (command == 0) {
+ kdDebug(5960) << "KandyView::setResult(): Error! No command." << endl;
+ mResultView->setText(i18n("Error"));
+ return;
+ }
+
+// kdDebug(5960) << "KandyView::setResult(): " << endl << mResult << endl
+// << mLastCommand->processOutput(mResult) << endl;
+
+ mResultView->setText(command->cmdName() + ":\n" + command->processOutput());
+}
+
+void KandyView::addCommand()
+{
+ ATCommand *cmd = new ATCommand(mLastInput);
+
+ CmdPropertiesDialog *dlg = new CmdPropertiesDialog(cmd,this,"cmdprop",true);
+
+ int result = dlg->exec();
+
+ if (result == QDialog::Accepted) {
+ new CommandItem(mCommandList,cmd);
+ mScheduler->commandSet()->addCommand(cmd);
+ setModified();
+ } else {
+ delete cmd;
+ }
+}
+
+void KandyView::editCommand()
+{
+ QListViewItem *item = mCommandList->currentItem();
+ if (item) {
+ CommandItem *cmdItem = (CommandItem *)item;
+ ATCommand *cmd = cmdItem->command();
+
+ CmdPropertiesDialog *dlg = new CmdPropertiesDialog(cmd,this,"cmdprop",true);
+
+ int result = dlg->exec();
+
+ if (result == QDialog::Accepted) {
+ cmdItem->setItemText();
+ setModified();
+ }
+ }
+}
+
+void KandyView::executeCommand()
+{
+ CommandItem *item = (CommandItem *)(mCommandList->currentItem());
+ if (item) {
+ ATCommand *cmd = item->command();
+ QPtrList<ATParameter> paraList = cmd->parameters();
+ for(uint i=0;i<paraList.count();++i) {
+ ATParameter *p = paraList.at(i);
+ if (p->userInput()) {
+ bool ok = false;
+ QString value = KInputDialog::getText(QString::null,
+ i18n("Enter value for %1:").arg(p->name()),QString::null,&ok,this);
+ if (!ok)
+ return;
+ p->setValue(value);
+ }
+ }
+ kdDebug(5960) << "KandyView::executeCommand(): " << cmd->cmd() << endl;
+ mScheduler->execute(cmd);
+ }
+}
+
+void KandyView::deleteCommand()
+{
+ CommandItem *item = dynamic_cast<CommandItem *>(mCommandList->currentItem());
+ if (item) {
+ mScheduler->commandSet()->deleteCommand(item->command());
+ delete item;
+ setModified();
+ }
+}
+
+bool KandyView::loadFile(const QString& filename)
+{
+ mCommandList->clear();
+
+ if (!mScheduler->loadProfile(filename)) return false;
+
+ QPtrList<ATCommand> *cmds = mScheduler->commandSet()->commandList();
+
+ for(uint i=0;i<cmds->count();++i) {
+ new CommandItem(mCommandList,cmds->at(i));
+ }
+
+ KConfig *config = KGlobal::config();
+ config->setGroup("General");
+ config->writeEntry("CurrentProfile",filename);
+
+ setModified(false);
+
+ return true;
+}
+
+bool KandyView::saveFile(const QString& filename)
+{
+ if (!mScheduler->saveProfile(filename)) return false;
+
+ KConfig *config = KGlobal::config();
+ config->setGroup("General");
+ config->writeEntry("CurrentProfile",filename);
+
+ setModified(false);
+
+ return true;
+}
+
+void KandyView::setModified(bool modified)
+{
+ if (modified != mModified) {
+ mModified = modified;
+ emit modifiedChanged(mModified);
+ }
+}
+
+bool KandyView::isModified()
+{
+ return mModified;
+}
diff --git a/kandy/src/kandyview.h b/kandy/src/kandyview.h
new file mode 100644
index 000000000..259ee6c78
--- /dev/null
+++ b/kandy/src/kandyview.h
@@ -0,0 +1,124 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+#ifndef KANDYVIEW_H
+#define KANDYVIEW_H
+
+#include <qwidget.h>
+
+class QPainter;
+class QTextStream;
+class QDataStream;
+class QDomDocument;
+class QDomElement;
+class QTextEdit;
+class QListView;
+
+class KURL;
+
+class Modem;
+class ATCommand;
+class MobileGui;
+class CommandScheduler;
+class CmdPropertiesDialog;
+
+/**
+ This is the main view class for Kandy.
+
+ @short Main view
+ @author Cornelius Schumacher <schumacher@kde.org>
+*/
+class KandyView : public QWidget
+{
+ Q_OBJECT
+ public:
+ /**
+ * Default constructor
+ */
+ KandyView(CommandScheduler *,QWidget *parent);
+
+ /**
+ * Destructor
+ */
+ virtual ~KandyView();
+
+ /**
+ Import phonebook from mobile phone and save it to Kab. This function
+ returns before the job is actually done.
+ */
+ void importPhonebook();
+
+ /**
+ * Print this view to any medium -- paper or not
+ */
+ void print(QPainter *, int height, int width);
+
+ bool loadFile(const QString& filename);
+ bool saveFile(const QString& filename);
+
+ void setModified(bool modified=true);
+ bool isModified();
+
+ public slots:
+ void addCommand();
+ void executeCommand();
+ void deleteCommand();
+ void editCommand();
+
+ signals:
+ /**
+ * Use this signal to change the content of the statusbar
+ */
+ void signalChangeStatusbar(const QString& text);
+
+ /**
+ * Use this signal to change the content of the caption
+ */
+ void signalChangeCaption(const QString& text);
+
+ void modifiedChanged(bool);
+
+ protected slots:
+ void appendOutput(const char *line);
+
+ void setResult(ATCommand *);
+
+ private slots:
+ void slotSetTitle(const QString& title);
+ void processLastLine();
+
+ private:
+ QString mLastInput;
+
+ CommandScheduler *mScheduler;
+
+ bool mModified;
+
+ QListView *mCommandList;
+
+ QTextEdit *mInput;
+ QTextEdit *mOutput;
+ QTextEdit *mResultView;
+};
+
+#endif // KANDYVIEW_H
diff --git a/kandy/src/main.cpp b/kandy/src/main.cpp
new file mode 100644
index 000000000..9343c1ece
--- /dev/null
+++ b/kandy/src/main.cpp
@@ -0,0 +1,158 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <qfile.h>
+
+#include <kapplication.h>
+#include <dcopclient.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+
+#include "modem.h"
+#include "kandy.h"
+#include "mobilemain.h"
+#include "mobilegui.h"
+#include "commandscheduler.h"
+#include "kandyprefs.h"
+
+static const char description[] =
+ I18N_NOOP("Communicating with your mobile phone.");
+
+static const char version[] = "0.5.1";
+
+static KCmdLineOptions options[] =
+{
+ { "terminal", I18N_NOOP("Show terminal window"), 0 },
+ { "mobilegui", I18N_NOOP("Show mobile GUI"), 0 },
+ { "nogui", I18N_NOOP("Do not show GUI"), 0 },
+ { "+[profile]", I18N_NOOP("Filename of command profile file"), 0 },
+ KCmdLineLastOption // End of options.
+};
+
+void initModem(Modem *modem)
+{
+ kdDebug() << "Opening serial Device: "
+ << KandyPrefs::serialDevice()
+ << endl;
+
+ modem->setSpeed( KandyPrefs::baudRate().toUInt() );
+ modem->setData(8);
+ modem->setParity('N');
+ modem->setStop(1);
+
+#if 0
+ if (!modem->dsrOn()) {
+ KMessageBox::sorry(this, i18n("Modem is off."), i18n("Modem Error"));
+ modem->close();
+ return;
+ }
+ if (!modem->ctsOn()) {
+ KMessageBox::sorry(this, i18n("Modem is busy."), i18n("Modem Error"));
+ modem->close();
+ return;
+ }
+#endif
+
+#if 0
+ modem->writeLine("");
+ usleep(250000);
+ modem->flush();
+ modem->writeLine("ATZ");
+#endif
+}
+
+int main(int argc, char **argv)
+{
+ KAboutData about("kandy", I18N_NOOP("Kandy"), version, description,
+ KAboutData::License_GPL, "(C) 2001 Cornelius Schumacher",0,
+ "http://kandy.kde.org/");
+ about.addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );
+ about.addAuthor( "Heiko Falk", 0, "hf2@ls12.cs.uni-dortmund.de" );
+ KCmdLineArgs::init(argc,argv,&about);
+ KCmdLineArgs::addCmdLineOptions(options);
+
+ KApplication app;
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ // register ourselves as a dcop client
+ app.dcopClient()->registerAs(app.name(),false);
+
+ Modem *modem = new Modem(KandyPrefs::self());
+ CommandScheduler *scheduler = new CommandScheduler(modem);
+
+ // see if we are starting with session management
+ if (app.isRestored()) {
+ // TODO: do session management
+// RESTORE(Kandy)
+ } else
+ {
+ // no session.. just start up normally
+ Kandy *k = new Kandy(scheduler);
+
+ MobileMain *m = new MobileMain(scheduler, KandyPrefs::self());
+
+ if (!args->isSet("gui")) {
+ } else {
+ if (KandyPrefs::startupTerminalWin() ||
+ args->isSet("terminal")) {
+ k->show();
+ }
+ if (KandyPrefs::startupMobileWin() ||
+ args->isSet("mobilegui")) {
+ m->show();
+ }
+ }
+
+ if (args->count() == 1) {
+ k->load(QFile::decodeName(args->arg(0)));
+ } else if (args->count() > 1) {
+ args->usage();
+ }
+
+ args->clear();
+
+ QObject::connect(k,SIGNAL(showMobileWin()),m,SLOT(show()));
+ QObject::connect(m,SIGNAL(showTerminalWin()),k,SLOT(show()));
+ QObject::connect(m,SIGNAL(showPreferencesWin()),
+ k,SLOT(optionsPreferences()));
+
+ QObject::connect( m->view(), SIGNAL( connectModem() ), k,
+ SLOT( modemConnect() ) );
+ QObject::connect( m->view(), SIGNAL( disconnectModem() ), k,
+ SLOT( modemDisconnect() ) );
+
+ QObject::connect( modem, SIGNAL( errorMessage( const QString & ) ),
+ k, SLOT( showErrorMessage( const QString & ) ) );
+
+ initModem( modem );
+
+ if ( KandyPrefs::startupModem() )
+ m->view()->toggleConnection();
+ }
+
+ return app.exec();
+}
diff --git a/kandy/src/mobilegui.cpp b/kandy/src/mobilegui.cpp
new file mode 100644
index 000000000..374660902
--- /dev/null
+++ b/kandy/src/mobilegui.cpp
@@ -0,0 +1,1671 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <time.h>
+
+#include <qlabel.h>
+#include <qlistview.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qmessagebox.h>
+
+#include <qtextedit.h>
+#include <qgroupbox.h>
+#include <qpushbutton.h>
+
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kstatusbar.h>
+
+#include <kabc/stdaddressbook.h>
+
+#include "modem.h"
+#include "atcommand.h"
+#include "commandscheduler.h"
+
+#include "mobilegui.h"
+#include "mobilegui.moc"
+#include "mobilemain.h"
+
+
+class SyncEntry
+{
+ public:
+ SyncEntry()
+ {
+ mOn = true;
+ mToBeUpdated = false;
+ mToBeInserted = false;
+ }
+
+ bool mOn;
+ bool mToBeUpdated;
+ bool mToBeInserted;
+};
+
+
+class SyncEntryKab : public SyncEntry
+{
+ public:
+ SyncEntryKab( bool on, const QString &index, const QString &name,
+ const QString &phone )
+ {
+ mOn = on;
+
+ mIndex = index;
+ mName = name;
+ mPhone = phone;
+
+ mKABindex = -1;
+ mPhoneNumberIndex = -1;
+ }
+
+ QString mIndex;
+ QString mName;
+ QString mPhone;
+
+ KABC::Addressee mAddressee;
+ int mKABindex;
+ int mPhoneNumberIndex;
+};
+
+
+class SyncEntryMobile : public SyncEntry
+{
+ public:
+ SyncEntryMobile( bool on, const QString &index, const QString &phone,
+ const QString &name )
+ {
+ mOn = on;
+ mToBeDeleted = false;
+
+ mIndex = index;
+ mName = name;
+ mPhone = phone;
+ }
+
+ QString mIndex;
+ QString mName;
+ QString mPhone;
+
+ bool mToBeDeleted;
+};
+
+
+class SyncEntryCommon : public SyncEntry
+{
+ public:
+ SyncEntryCommon( bool on, SyncEntryKab *kabEntry,
+ SyncEntryMobile *mobileEntry )
+ {
+ mOn = on;
+ mKabEntry = kabEntry;
+ mMobileEntry = mobileEntry;
+ }
+
+ SyncEntryKab *mKabEntry;
+ SyncEntryMobile *mMobileEntry;
+};
+
+
+class AddressSyncer
+{
+ public:
+ AddressSyncer()
+ {
+ mKabEntries.setAutoDelete( true );
+ mMobileEntries.setAutoDelete( true );
+ mCommonEntries.setAutoDelete( true );
+ }
+
+ QPtrList<SyncEntryKab> mKabEntries;
+ QPtrList<SyncEntryMobile> mMobileEntries;
+ QPtrList<SyncEntryCommon> mCommonEntries;
+};
+
+
+class PhoneBookItem : public QCheckListItem
+{
+ public:
+ PhoneBookItem( QListView *v ) :
+ QCheckListItem( v, "", QCheckListItem::CheckBox )
+ {
+ mSyncEntry = 0;
+ }
+
+ PhoneBookItem( QListView *v, SyncEntry *syncEntry, const QString &name,
+ const QString &phone, const QString &index ) :
+ QCheckListItem( v, index, QCheckListItem::CheckBox )
+ {
+ mSyncEntry = syncEntry;
+
+ setText( 0, name );
+ setText( 1, phone );
+ setText( 2, index );
+ }
+
+ SyncEntry *syncEntry() { return mSyncEntry; }
+
+ private:
+ SyncEntry *mSyncEntry;
+};
+
+
+/*
+ * Constructs a MobileGui which is a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'
+ *
+ * The dialog will by default be modeless, unless you set 'modal' to
+ * TRUE to construct a modal dialog.
+ */
+MobileGui::MobileGui( CommandScheduler *scheduler, KandyPrefs *kprefs,
+ QWidget* parent, const char* name, WFlags fl ) :
+ DCOPObject( "KandyIface" ), MobileGui_base( parent, name, fl )
+{
+ // Setup links to related classes
+ mScheduler = scheduler;
+ mSyncer = new AddressSyncer;
+ mPrefs = kprefs;
+ mparent = parent;
+
+ // Setup mobile phone specific data
+ mMobManufacturer = "";
+ mMobModel = "";
+ mPBStartIndex = 0;
+ mPBLength = 0;
+ mPBNameLength = 0;
+ mPBIndexOccupied.resize( 0, false );
+ mMobHasFD = false;
+ mMobHasLD = false;
+ mMobHasME = false;
+ mMobHasMT = false;
+ mMobHasTA = false;
+ mMobHasOW = false;
+ mMobHasMC = false;
+ mMobHasRC = false;
+
+ // Setup status for asynchronous control flow
+ mLastWriteId = "";
+ mComingFromToggleConnection = false;
+ mComingFromReadPhonebook = false;
+ mComingFromSyncPhonebooks = false;
+ mComingFromExit = false;
+
+ // Setup initial state of phone books
+ setKabState( UNLOADED );
+ setMobState( UNLOADED );
+
+ // Setup signal handlers
+ connect( mScheduler, SIGNAL( commandProcessed( ATCommand * ) ),
+ SLOT( processResult( ATCommand * ) ) );
+ connect( mScheduler->modem(), SIGNAL( gotLine( const char * ) ),
+ SLOT( termAddOutput( const char * ) ) );
+}
+
+
+MobileGui::~MobileGui()
+{
+ delete mSyncer;
+}
+
+
+void MobileGui::exit()
+{
+ warnKabState( UNLOADED );
+
+ mComingFromExit = true;
+ if ( !warnMobState( UNLOADED ) ) {
+ mComingFromExit = false;
+ kapp->quit();
+ }
+}
+
+
+void MobileGui::readModelInformation()
+{
+ // Read generic manufacturer and model information
+ mScheduler->executeId( "+cgmi" );
+ mScheduler->executeId( "+cgmm" );
+ mScheduler->executeId( "+cgmr" );
+ mScheduler->executeId( "+cgsn" );
+
+ // Read information about additional phonebook memories
+ ATCommand *cmd = new ATCommand( "+cpbs=?" );
+ cmd->setAutoDelete( true );
+ mScheduler->execute( cmd );
+
+ // Select SIM phonebook by default
+ cmd = new ATCommand( "+cpbs=" );
+ cmd->setAutoDelete( true );
+ cmd->addParameter( new ATParameter( "SM" ) );
+ mScheduler->execute( cmd );
+
+ // Read phonebook properties
+ mScheduler->executeId( "+cpbr=?" );
+ mScheduler->executeId( "+cpbs?" );
+
+ // Set clock
+ if ( (*mPrefs).autoSetClock() )
+ setClock();
+}
+
+
+void MobileGui::readPhonebook()
+{
+ if ( mMobState == LOADED )
+ return;
+
+ mComingFromReadPhonebook = true;
+ if ( !warnMobState( LOADED ) ) {
+ mComingFromReadPhonebook = false;
+ QString tmp = "";
+
+ ATCommand *cmd = new ATCommand( "+cpbr=" );
+ cmd->setAutoDelete( true );
+ cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex ) ) );
+ cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex +
+ mPBLength - 1 ) ) );
+
+ mScheduler->execute( cmd );
+
+ emit statusMessage( i18n( "Reading mobile phonebook..." ) );
+ }
+}
+
+
+void MobileGui::writePhonebook()
+{
+ bool ModemCommandScheduled = false;
+
+
+ if ( mMobState != MODIFIED )
+ return;
+
+ PushButton12->setEnabled( false );
+
+
+ //
+ // Remove all entries from data structures which are marked as
+ // deleted but which are not found on the mobile phone
+ //
+
+ for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) {
+ SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i );
+
+
+ if ( entry->mToBeDeleted )
+ if ( entry->mIndex.isEmpty() ) {
+ // The current entry has to be deleted but doesn't come from
+ // the mobile phone. Hence, it was inserted during phonebook
+ // synchronisation or so.
+ // => It is sufficient to remove it from mMobileEntries, no
+ // ATCommand for deletion needs to be scheduled.
+ mSyncer->mMobileEntries.remove( i );
+ i--;
+ } else {
+ // The current entry has to be deleted and stems from the
+ // mobile phone. First thing to do is to free its associated
+ // index. This way, its index can be reused for entries which
+ // have be newly inserted to the mobile phone and we can save
+ // an explicit ATCommand for deletion and save time & battery
+ // energy.
+ uint theIndex = entry->mIndex.toUInt();
+ mPBIndexOccupied[ theIndex - mPBStartIndex ] = false;
+ }
+ }
+
+
+ //
+ // Write all elements which need an update to the mobile phone
+ //
+
+ for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) {
+ SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i );
+ QString id;
+
+
+ // Only process changed items of the mobile phonebook in
+ // order to save time.
+ if ( entry->mToBeUpdated || entry->mToBeInserted ) {
+ QString tmp = "";
+
+
+ if ( entry->mToBeUpdated ) {
+ id = "+cpbw=" + entry->mIndex;
+ } else {
+ int index = firstFreeIndex();
+
+
+ mPBIndexOccupied[ index ] = true;
+ id = "+cpbw=" + tmp.setNum( index + mPBStartIndex );
+ }
+ mLastWriteId = id;
+ entry->mToBeUpdated = false;
+ entry->mToBeInserted = false;
+
+ ATCommand *cmd = new ATCommand( id );
+ cmd->setAutoDelete( true );
+ cmd->addParameter( new ATParameter( quote( entry->mPhone ) ) );
+
+ if ( entry->mPhone.left( 1 ) == "+" )
+ cmd->addParameter( new ATParameter( "145" ) );
+ else
+ cmd->addParameter( new ATParameter( "129" ) );
+
+ cmd->addParameter( new ATParameter(
+ quote( string2GSM( entry->mName ) ) ) );
+
+ mScheduler->execute( cmd );
+ ModemCommandScheduled = true;
+ }
+ }
+
+
+ //
+ // As a final step, we need to check again all entries which should be
+ // deleted. If entries exist stemming from the mobile phone and whose
+ // index-position was not reused for updating or inserting other entries in
+ // the previous loop, we need to issue an explicit ATCommand for its deletion.
+ //
+
+ for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) {
+ SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i );
+
+
+ if ( entry->mToBeDeleted ) {
+ uint theIndex = entry->mIndex.toUInt();
+
+
+ if ( !mPBIndexOccupied[ theIndex - mPBStartIndex ] ) {
+ // Index of item to be deleted still is 0, so that index position
+ // wasn't reused. We must delete it explicitly.
+ QString id = "+cpbw=" + entry->mIndex;
+
+
+ mLastWriteId = id;
+ ATCommand *cmd = new ATCommand( id );
+ cmd->setAutoDelete( true );
+
+ mScheduler->execute( cmd );
+ ModemCommandScheduled = true;
+ }
+
+ // Remove entry from internal data structures
+ mSyncer->mMobileEntries.remove( i );
+ i--;
+ }
+ }
+
+ if ( ModemCommandScheduled )
+ emit statusMessage( i18n( "Writing mobile phonebook..." ) );
+ else
+ writePhonebookPostProcessing();
+}
+
+
+void MobileGui::writePhonebookPostProcessing()
+{
+ mLastWriteId = "";
+ emit transientStatusMessage( i18n( "Wrote mobile phonebook." ) );
+ PushButton12->setEnabled( true );
+ setMobState( LOADED );
+ updateMobileBook();
+
+ if ( mComingFromToggleConnection ) {
+ mComingFromToggleConnection = false;
+ disconnectGUI();
+ } else
+ if ( mComingFromReadPhonebook ) {
+ mComingFromReadPhonebook = false;
+ QString tmp = "";
+
+ ATCommand *cmd = new ATCommand( "+cpbr=" );
+ cmd->setAutoDelete( true );
+ cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex ) ) );
+ cmd->addParameter( new ATParameter( tmp.setNum( mPBStartIndex +
+ mPBLength - 1 ) ) );
+
+ mScheduler->execute( cmd );
+
+ emit statusMessage( i18n( "Reading mobile phonebook..." ) );
+ } else
+ if ( mComingFromExit ) {
+ mComingFromExit = false;
+ kapp->quit();
+ }
+}
+
+
+void MobileGui::setClock()
+{
+ char *timeStr = new char[50];
+ QString id = "+cclk=";
+ ATCommand *cmd = new ATCommand( id );
+
+
+ cmd->setAutoDelete( true );
+
+ time_t tloc;
+ time( &tloc );
+ struct tm *theTime = localtime( &tloc );
+ strftime( timeStr, 50, "%y/%m/%d,%T+00", theTime );
+
+ QString Time = timeStr;
+ cmd->addParameter( new ATParameter( quote( Time ) ) );
+
+ mScheduler->execute( cmd );
+
+ delete[] timeStr;
+}
+
+
+void MobileGui::readKabc()
+{
+ if ( mKabState == LOADED )
+ return;
+
+ warnKabState( LOADED );
+
+ emit statusMessage( i18n( "Reading KDE address book..." ) );
+
+ mSyncer->mKabEntries.clear();
+
+ KABC::AddressBook *addressBook = KABC::StdAddressBook::self( true );
+ KABC::AddressBook::Iterator it;
+ int kabIndex = 0;
+
+ for ( it = addressBook->begin(); it != addressBook->end();
+ it++, kabIndex++ ) {
+ QString index, name;
+ KABC::PhoneNumber phoneNumber;
+ KABC::PhoneNumber::List phoneNumbers = (*it).phoneNumbers();
+ KABC::PhoneNumber::List::Iterator it2;
+ int phoneNumberIndex = 0;
+
+
+ // Scan all numbers associated with a KAB entry
+ for ( it2 = phoneNumbers.begin(); it2 != phoneNumbers.end();
+ it2++, phoneNumberIndex++ ) {
+ bool excludeNumber = false;
+ phoneNumber = (*it2);
+ QString phone = phoneNumber.number();
+
+
+ if ( (*mPrefs).excludeHome() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Home ) )
+ excludeNumber = true;
+ if ( (*mPrefs).excludeWork() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Work ) )
+ excludeNumber = true;
+ if ( (*mPrefs).excludeMessaging() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Msg ) )
+ excludeNumber = true;
+ if ( (*mPrefs).excludeFax() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Fax ) )
+ excludeNumber = true;
+ if ( (*mPrefs).excludeCell() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Cell ) )
+ excludeNumber = true;
+ if ( (*mPrefs).excludeVideo() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Video ) )
+ excludeNumber = true;
+ if ( (*mPrefs).excludeMailbox() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Bbs ) )
+ excludeNumber = true;
+ if ( (*mPrefs).excludeModem() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Modem ) )
+ excludeNumber = true;
+ if ( (*mPrefs).excludeCar() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Car ) )
+ excludeNumber = true;
+ if ( (*mPrefs).excludeISDN() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Isdn ) )
+ excludeNumber = true;
+ if ( (*mPrefs).excludePager() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Pager ) )
+ excludeNumber = true;
+
+ if ( excludeNumber == false ) {
+ SyncEntryKab *kabEntry;
+
+
+ index = "";
+ name = (*it).familyName();
+
+ KABC::AddressBook::Iterator it3;
+ KABC::Addressee::List tmp;
+ bool firstCharIsUnique = true;
+ for ( it3 = addressBook->begin(); it3 != addressBook->end(); ++it3 )
+ if ( ( (*it3).familyName() == name ) && ( it3 != it ) ) {
+ tmp.append( (*it3) );
+ if ( (*it3).givenName()[0] == (*it).givenName()[0] )
+ firstCharIsUnique = false;
+ }
+
+ // There are several KAB entries with the same family name.
+ // So, we need to append the given name in order to
+ // distinguish them.
+ if ( ( tmp.size() > 0 ) && !(*it).givenName().isEmpty() ) {
+ name += ", ";
+
+ if ( firstCharIsUnique )
+ name += (*it).givenName()[0] + ".";
+ else
+ name += (*it).givenName();
+ }
+
+ // Truncate name field if it's too long for mobile phone
+ if ( name.length() > mPBNameLength )
+ name = name.remove( mPBNameLength, name.length() - mPBNameLength );
+
+ // Append Suffix to name if specified in preferences
+ if ( (*mPrefs).useHomeSuff() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Home ) )
+ formatPBName( &name, (*mPrefs).homeSuff() );
+ else
+ if ( (*mPrefs).useWorkSuff() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Work ) )
+ formatPBName( &name, (*mPrefs).workSuff() );
+ else
+ if ( (*mPrefs).useMessagingSuff() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Msg ) )
+ formatPBName( &name, (*mPrefs).messagingSuff() );
+ else
+ if ( (*mPrefs).useFaxSuff() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Fax ) )
+ formatPBName( &name, (*mPrefs).faxSuff() );
+ else
+ if ( (*mPrefs).useCellSuff() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Cell ) )
+ formatPBName( &name, (*mPrefs).cellSuff() );
+ else
+ if ( (*mPrefs).useVideoSuff() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Video ) )
+ formatPBName( &name, (*mPrefs).videoSuff() );
+ else
+ if ( (*mPrefs).useMailboxSuff() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Bbs ) )
+ formatPBName( &name, (*mPrefs).mailboxSuff() );
+ else
+ if ( (*mPrefs).useModemSuff() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Modem ) )
+ formatPBName( &name, (*mPrefs).modemSuff() );
+ else
+ if ( (*mPrefs).useCarSuff() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Car ) )
+ formatPBName( &name, (*mPrefs).carSuff() );
+ else
+ if ( (*mPrefs).useISDNSuff() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Isdn ) )
+ formatPBName( &name, (*mPrefs).iSDNSuff() );
+ else
+ if ( (*mPrefs).usePagerSuff() &&
+ ( phoneNumber.type() & KABC::PhoneNumber::Pager ) )
+ formatPBName( &name, (*mPrefs).pagerSuff() );
+
+ kabEntry = new SyncEntryKab( true, index, name, phone );
+ kabEntry->mKABindex = kabIndex;
+ kabEntry->mPhoneNumberIndex = phoneNumberIndex;
+
+ kabEntry->mAddressee = (*it);
+ mSyncer->mKabEntries.append( kabEntry );
+ }
+ }
+ }
+
+ // Display KAB entries
+ updateKabBook();
+
+ emit transientStatusMessage( i18n( "Read KDE address book." ) );
+
+ setKabState( LOADED );
+}
+
+
+QString MobileGui::decodeSuffix( const QString &suffix )
+{
+ QString theSuffix = suffix;
+
+
+ // Check whether suffix is quoted. If so, it should be interpreted
+ // as Hex-Number of a special GSM character.
+ if ( ( theSuffix.left( 1 ) == "\"" ) && ( theSuffix.right( 1 ) == "\"" ) ) {
+ QString tmp = "";
+ char suffixNumber = (char) dequote( suffix ).toUInt( 0, 16 );
+ tmp += suffixNumber;
+
+ theSuffix = GSM2String( tmp );
+ }
+
+ return theSuffix;
+}
+
+
+void MobileGui::formatPBName( QString *name, QString suffix )
+{
+ QString theSuffix = decodeSuffix( suffix );
+
+
+ if ( name->length() + theSuffix.length() > mPBNameLength ) {
+ // Truncate name field if it's too long for mobile phone
+ unsigned int toolong = name->length() + theSuffix.length() - mPBNameLength;
+ (*name) = name->remove( name->length() - toolong, toolong );
+ } else
+ if ( name->length() + theSuffix.length() < mPBNameLength )
+ // Add white spaces so that suffix is right justified
+ while ( name->length() + theSuffix.length() != mPBNameLength )
+ (*name) += ' ';
+
+ (*name) += theSuffix;
+}
+
+
+QString MobileGui::stripWhiteSpaces( const QString &theString )
+{
+ int pos = 0;
+ int len = theString.length();
+
+
+ for ( unsigned int i = 0; i < theString.length(); i++ )
+ if ( theString[ i ].latin1() == ' ' ) {
+ pos++;
+ len--;
+ } else
+ break;
+
+ if ( len == 0 )
+ return "";
+
+ for ( int i = theString.length() - 1; i >= 0; i-- )
+ if ( theString[ i ].latin1() == ' ' )
+ len--;
+ else
+ break;
+
+ return theString.mid( pos, len );
+}
+
+
+void MobileGui::writeKabc()
+{
+ if ( mKabState != MODIFIED )
+ return;
+
+ KABC::AddressBook *addressBook = KABC::StdAddressBook::self( true );
+ KABC::Ticket *ticket = addressBook->requestSaveTicket();
+
+ if ( !ticket ) {
+ kdDebug() << "Error! No ticket to save." << endl;
+ return;
+ }
+
+
+ for ( uint i = 0; i < mSyncer->mKabEntries.count(); i++ ) {
+ SyncEntryKab *kabEntry = mSyncer->mKabEntries.at( i );
+ QString phoneNumber = kabEntry->mPhone;
+
+
+ if ( kabEntry->mToBeUpdated ) {
+ // Find the entry in the KAB which has to be updated
+ KABC::AddressBook::Iterator it = addressBook->begin();
+ for ( int KABindex = 0; KABindex != kabEntry->mKABindex;
+ it++, KABindex++ ) ;
+
+ // Find the correct phonenumber of the phonebook entry
+ KABC::PhoneNumber::List phoneNumbers = (*it).phoneNumbers();
+ KABC::PhoneNumber::List::Iterator it2 = phoneNumbers.begin();
+ for ( int phoneNumberIndex = 0;
+ phoneNumberIndex != kabEntry->mPhoneNumberIndex;
+ it2++, phoneNumberIndex++ ) ;
+
+ (*it2).setNumber( phoneNumber );
+ (*it).insertPhoneNumber( (*it2) );
+ } else
+
+ if ( kabEntry->mToBeInserted ) {
+ int phoneType = 0;
+ bool goon = true;
+ KABC::AddressBook::Iterator it;
+ bool equivalentEntryFound = false;
+ QString name = kabEntry->mName;
+
+
+ //
+ // Identify Type of Phonenumber using possibly appended suffixes.
+ // If a suffix is found, remove it from the name.
+ //
+ if ( goon && (*mPrefs).useHomeSuff() ) {
+ QString theSuffix = decodeSuffix( (*mPrefs).homeSuff() );
+ if ( name.right( theSuffix.length() ) == theSuffix ) {
+ phoneType = KABC::PhoneNumber::Home;
+ name = stripWhiteSpaces(
+ name.left( name.length() - theSuffix.length() ) );
+ goon = false;
+ }
+ }
+ if ( goon && (*mPrefs).useWorkSuff() ) {
+ QString theSuffix = decodeSuffix( (*mPrefs).workSuff() );
+ if ( name.right( theSuffix.length() ) == theSuffix ) {
+ phoneType = KABC::PhoneNumber::Work;
+ name = stripWhiteSpaces(
+ name.left( name.length() - theSuffix.length() ) );
+ goon = false;
+ }
+ }
+ if ( goon && (*mPrefs).useMessagingSuff() ) {
+ QString theSuffix = decodeSuffix( (*mPrefs).messagingSuff() );
+ if ( name.right( theSuffix.length() ) == theSuffix ) {
+ phoneType = KABC::PhoneNumber::Msg;
+ name = stripWhiteSpaces(
+ name.left( name.length() - theSuffix.length() ) );
+ goon = false;
+ }
+ }
+ if ( goon && (*mPrefs).useFaxSuff() ) {
+ QString theSuffix = decodeSuffix( (*mPrefs).faxSuff() );
+ if ( name.right( theSuffix.length() ) == theSuffix ) {
+ phoneType = KABC::PhoneNumber::Fax;
+ name = stripWhiteSpaces(
+ name.left( name.length() - theSuffix.length() ) );
+ goon = false;
+ }
+ }
+ if ( goon && (*mPrefs).useCellSuff() ) {
+ QString theSuffix = decodeSuffix( (*mPrefs).cellSuff() );
+ if ( name.right( theSuffix.length() ) == theSuffix ) {
+ phoneType = KABC::PhoneNumber::Cell;
+ name = stripWhiteSpaces(
+ name.left( name.length() - theSuffix.length() ) );
+ goon = false;
+ }
+ }
+ if ( goon && (*mPrefs).useVideoSuff() ) {
+ QString theSuffix = decodeSuffix( (*mPrefs).videoSuff() );
+ if ( name.right( theSuffix.length() ) == theSuffix ) {
+ phoneType = KABC::PhoneNumber::Video;
+ name = stripWhiteSpaces(
+ name.left( name.length() - theSuffix.length() ) );
+ goon = false;
+ }
+ }
+ if ( goon && (*mPrefs).useMailboxSuff() ) {
+ QString theSuffix = decodeSuffix( (*mPrefs).mailboxSuff() );
+ if ( name.right( theSuffix.length() ) == theSuffix ) {
+ phoneType = KABC::PhoneNumber::Bbs;
+ name = stripWhiteSpaces(
+ name.left( name.length() - theSuffix.length() ) );
+ goon = false;
+ }
+ }
+ if ( goon && (*mPrefs).useModemSuff() ) {
+ QString theSuffix = decodeSuffix( (*mPrefs).modemSuff() );
+ if ( name.right( theSuffix.length() ) == theSuffix ) {
+ phoneType = KABC::PhoneNumber::Modem;
+ name = stripWhiteSpaces(
+ name.left( name.length() - theSuffix.length() ) );
+ goon = false;
+ }
+ }
+ if ( goon && (*mPrefs).useCarSuff() ) {
+ QString theSuffix = decodeSuffix( (*mPrefs).carSuff() );
+ if ( name.right( theSuffix.length() ) == theSuffix ) {
+ phoneType = KABC::PhoneNumber::Car;
+ name = stripWhiteSpaces(
+ name.left( name.length() - theSuffix.length() ) );
+ goon = false;
+ }
+ }
+ if ( goon && (*mPrefs).useISDNSuff() ) {
+ QString theSuffix = decodeSuffix( (*mPrefs).iSDNSuff() );
+ if ( name.right( theSuffix.length() ) == theSuffix ) {
+ phoneType = KABC::PhoneNumber::Isdn;
+ name = stripWhiteSpaces(
+ name.left( name.length() - theSuffix.length() ) );
+ goon = false;
+ }
+ }
+ if ( goon && (*mPrefs).usePagerSuff() ) {
+ QString theSuffix = decodeSuffix( (*mPrefs).pagerSuff() );
+ if ( name.right( theSuffix.length() ) == theSuffix ) {
+ phoneType = KABC::PhoneNumber::Pager;
+ name = stripWhiteSpaces(
+ name.left( name.length() - theSuffix.length() ) );
+ goon = false;
+ }
+ }
+
+
+ //
+ // Search for a KAB entry whose name, if formatted in exactly the
+ // same way as was done in readKabc, is equal to the actual name.
+ //
+
+ for ( it = addressBook->begin(); it != addressBook->end(); it++ ) {
+ QString kabName = (*it).familyName();
+ KABC::AddressBook::Iterator it3;
+ KABC::Addressee::List tmp;
+ bool firstCharIsUnique = true;
+ unsigned int minLength;
+
+
+ for ( it3 = addressBook->begin(); it3 != addressBook->end(); it3++ )
+ if ( ( (*it3).familyName() == kabName ) && ( it3 != it ) ) {
+ tmp.append( (*it3) );
+ if ( (*it3).givenName()[0] == (*it).givenName()[0] )
+ firstCharIsUnique = false;
+ }
+
+ // There are several KAB entries with the same family name.
+ // So, we need to append the given name in order to
+ // distinguish them.
+ if ( ( tmp.size() > 0 ) && !(*it).givenName().isEmpty() ) {
+ kabName += ", ";
+
+ if ( firstCharIsUnique )
+ kabName += (*it).givenName()[0] + ".";
+ else
+ kabName += (*it).givenName();
+ }
+
+ // Truncate name field if it's too long for mobile phone
+ if ( kabName.length() > mPBNameLength )
+ kabName = kabName.remove( mPBNameLength,
+ kabName.length() - mPBNameLength );
+
+ minLength = kabName.length();
+ if ( name.length() < minLength )
+ minLength = name.length();
+
+ if ( name.left( minLength ) == kabName.left( minLength ) ) {
+ (*it).insertPhoneNumber( KABC::PhoneNumber( phoneNumber,
+ phoneType ) );
+
+ equivalentEntryFound = true;
+ break;
+ }
+ }
+
+ //
+ // If no equivalent entry was found in KAB, we need to generate
+ // a complete new entry.
+ //
+
+ if ( !equivalentEntryFound ) {
+ KABC::Addressee entry;
+ QStringList *fields = new QStringList;
+
+
+ *fields = QStringList::split( ',', name );
+
+ if ( fields->count() > 1 ) {
+ // Name string contains comma separated entry so that we
+ // need to build family and given names out of them.
+ QString givenName = "";
+
+
+ entry.setFamilyName( stripWhiteSpaces( (*fields)[ 0 ] ) );
+
+ for ( unsigned int i = 1; i < fields->count(); i++ )
+ givenName += stripWhiteSpaces( (*fields)[ i ] ) + " ";
+ entry.setGivenName( stripWhiteSpaces( givenName ) );
+ } else
+ // Name string contains only one string without comma.
+ entry.setFamilyName( stripWhiteSpaces( name ) );
+
+ entry.insertPhoneNumber( KABC::PhoneNumber( phoneNumber, phoneType ) );
+
+ addressBook->insertAddressee( entry );
+ }
+ }
+
+ kabEntry->mToBeUpdated = false;
+ kabEntry->mToBeInserted = false;
+ }
+
+ addressBook->save( ticket );
+
+ emit transientStatusMessage( i18n( "Wrote KDE address book." ) );
+
+ setKabState( LOADED );
+}
+
+
+void MobileGui::refreshStatus()
+{
+ mScheduler->executeId( "+cbc" );
+ mScheduler->executeId( "+csq" );
+}
+
+
+void MobileGui::processResult( ATCommand *command )
+{
+ if ( command->id() == "+cbc" )
+ mBatteryChargeLabel->setText( command->resultField( 1 ) + " %" );
+ else
+ if ( command->id() == "+csq" )
+ mSignalQualityLabel->setText( command->resultField( 0 ) );
+ else
+ if ( command->id() == "+cgmi" ) {
+ mMobManufacturer = command->resultField( 0 );
+ mManufacturerLabel->setText( mMobManufacturer );
+ } else
+ if ( command->id() == "+cgmm" ) {
+ mMobModel = command->resultField( 0 );
+ mModelLabel->setText( mMobModel );
+ } else
+ if ( command->id() == "+cgmr" )
+ mGSMVersionLabel->setText( command->resultField( 0 ) );
+ else
+ if ( command->id() == "+cgsn" )
+ mSerialNumberLabel->setText( command->resultField( 0 ) );
+ else
+ if ( command->id() == "+cpbr=?" )
+ {
+ QStringList tmpList = QStringList::split( "-", command->resultField( 0 ) );
+ QString tmpString = tmpList.first().right( tmpList.first().length() - 1 );
+ mPBStartIndex = tmpString.toUInt();
+ mPBNameLength = command->resultField( 2 ).toUInt();
+ } else
+ if ( command->id() == "+cpbs?" ) {
+ mPBLength = command->resultField( 2 ).toUInt();
+
+ // Allocate and initialize memory for the buckets of indices
+ mPBIndexOccupied.resize( mPBLength, false );
+ for ( unsigned int i = 0; i < mPBLength; i++ )
+ mPBIndexOccupied[ i ] = false;
+ } else
+ if ( command->id() == "+cpbr=" ) {
+ fillPhonebook( command );
+
+ if ( mComingFromSyncPhonebooks ) {
+ mComingFromSyncPhonebooks = false;
+ mergePhonebooks();
+ }
+ } else
+ if ( command->id() == mLastWriteId )
+ writePhonebookPostProcessing();
+ else
+ if ( command->id() == "+cpbs=?" ) {
+ QPtrList<QStringList> *list = command->resultFields();
+ QStringList *fields = list->first();
+
+
+ while( fields ) {
+ for ( unsigned int i = 0; i < fields->count(); i++ ) {
+ QString memory = dequote( (*fields)[ i ] );
+
+
+ if ( memory == "FD" )
+ mMobHasFD = true;
+ else
+ if ( memory == "LD" )
+ mMobHasLD = true;
+ else
+ if ( memory == "ME" )
+ mMobHasME = true;
+ else
+ if ( memory == "MT" )
+ mMobHasMT = true;
+ else
+ if ( memory == "TA" )
+ mMobHasTA = true;
+ else
+ if ( ( memory == "OW" ) ||
+ ( ( memory == "ON" ) && ( mMobManufacturer == "SIEMENS" ) ) )
+ mMobHasOW = true;
+ else
+ if ( ( mMobManufacturer == "SIEMENS" ) && ( memory == "MC" ) )
+ mMobHasMC = true;
+ else
+ if ( ( mMobManufacturer == "SIEMENS" ) && ( memory == "RC" ) )
+ mMobHasRC = true;
+ }
+
+ fields = list->next();
+ }
+ }
+}
+
+
+QString MobileGui::noSpaces( const QString &theString )
+{
+ QString result = "";
+
+
+ for ( unsigned int i = 0; i < theString.length(); i++ )
+ if ( theString[ i ].latin1() != ' ' )
+ result += theString[ i ];
+
+ return result;
+}
+
+
+int MobileGui::firstFreeIndex()
+{
+ unsigned int i;
+
+
+ if ( mPBIndexOccupied.capacity() == 0 )
+ return 0;
+
+ for ( i = 1; i < mPBLength; i++ )
+ if ( !mPBIndexOccupied[ i ] )
+ break;
+
+ if ( i < mPBLength )
+ return i;
+
+ return 0;
+}
+
+
+QString MobileGui::string2GSM( const QString &theString )
+{
+ QString result = "";
+
+
+ for ( unsigned int i = 0; i < theString.length(); i++ )
+ switch ( theString[ i ].latin1() ) {
+ case 'Ä': result += '['; break;
+ case 'ä': result += '{'; break;
+ case 'Ö': result += 92; break;
+ case 'ö': result += '|'; break;
+ case 'Ü': result += '^'; break;
+ case 'ü': result += '~'; break;
+ case 'ß': result += 30; break;
+ case 'è': result += 4; break;
+ case 'é': result += 5; break;
+
+ default: result += theString[ i ];
+ }
+
+ return result;
+}
+
+
+QString MobileGui::GSM2String( const QString &theString )
+{
+ QString result = "";
+
+
+ for ( unsigned int i = 0; i < theString.length(); i++ )
+ switch ( theString[ i ].latin1() ) {
+ case '[': result += 'Ä'; break;
+ case '{': result += 'ä'; break;
+ case 92: result += 'Ö'; break;
+ case '|': result += 'ö'; break;
+ case '^': result += 'Ü'; break;
+ case '~': result += 'ü'; break;
+ case 30: result += 'ß'; break;
+ case 4: result += 'è'; break;
+ case 5: result += 'é'; break;
+
+ default: result += theString[ i ];
+ }
+
+ return result;
+}
+
+
+void MobileGui::fillPhonebook( ATCommand *cmd )
+{
+ mSyncer->mMobileEntries.clear();
+
+ QPtrList<QStringList> *list = cmd->resultFields();
+ QStringList *fields = list->first();
+
+ while( fields ) {
+ if ( fields->count() != 4 )
+ kdDebug() << "Error! Unexpected number of address fields." << endl;
+ else {
+ QString index = (*fields)[0];
+ QString phone = (*fields)[1];
+ QString type = (*fields)[2];
+ QString name = GSM2String( (*fields)[3] );
+
+ SyncEntryMobile *phoneEntry = new SyncEntryMobile( true, dequote( index ),
+ dequote( phone ),
+ dequote( name ) );
+ mPBIndexOccupied[ index.toUInt() - mPBStartIndex ] = true;
+ mSyncer->mMobileEntries.append( phoneEntry );
+ }
+ fields = list->next();
+ }
+
+ // Display mobile entries
+ updateMobileBook();
+
+ emit transientStatusMessage(i18n("Read mobile phonebook."));
+ emit phonebookRead();
+
+ setMobState( LOADED );
+}
+
+
+QString MobileGui::quote( const QString &str )
+{
+ if ( ( str.left(1) == "\"" ) && ( str.right(1) == "\"" ) )
+ return str;
+
+ return "\"" + str + "\"";
+}
+
+
+QString MobileGui::dequote( const QString &str )
+{
+ int pos = 0;
+ int len = str.length();
+
+
+ if ( str.left(1) == "\"" ) {
+ pos = 1;
+ len --;
+ }
+
+ if ( str.right(1) == "\"" )
+ len--;
+
+ return str.mid( pos, len );
+}
+
+
+void MobileGui::savePhonebook()
+{
+ if ( mMobState == UNLOADED )
+ return;
+
+ QString fileName = KFileDialog::getSaveFileName( "phonebook.csv" );
+ QFile outFile( fileName );
+
+ if ( outFile.open( IO_WriteOnly ) ) {
+ QTextStream t( &outFile ); // use a text stream
+
+ for( uint i = 0; i < mSyncer->mMobileEntries.count(); i++) {
+ SyncEntryMobile *e = mSyncer->mMobileEntries.at( i );
+
+
+ if ( !e->mToBeDeleted )
+ t << e->mIndex << "," << e->mPhone << "," << e->mName << endl;
+ }
+
+ outFile.close();
+ }
+}
+
+
+void MobileGui::deleteMobPhonebook()
+{
+
+ //
+ // Process all elements selected in the GUI
+ //
+
+ PhoneBookItem *item = (PhoneBookItem *) mMobileBook->firstChild();
+ while ( item ) {
+ if ( item->isOn() ) {
+ SyncEntryMobile *mobileItem = (SyncEntryMobile *) item->syncEntry();
+
+
+ // Deselect current item
+ item->setOn( false );
+ mobileItem->mOn = false;
+
+ // Mark current item as deleted
+ mobileItem->mToBeDeleted = true;
+ }
+
+ item = (PhoneBookItem *) item->nextSibling();
+ }
+
+ // Update GUI
+ updateMobileBook();
+ setMobState( MODIFIED );
+}
+
+
+void MobileGui::mergePhonebooks()
+{
+ uint i;
+
+
+ //
+ // Transfer current Selection State from GUI to mSyncer
+ //
+
+ PhoneBookItem *item = (PhoneBookItem *) mKabBook->firstChild();
+ while ( item ) {
+ item->syncEntry()->mOn = item->isOn();
+ item = (PhoneBookItem *) item->nextSibling();
+ }
+
+ item = (PhoneBookItem *) mMobileBook->firstChild();
+ while ( item ) {
+ item->syncEntry()->mOn = item->isOn();
+ item = (PhoneBookItem *) item->nextSibling();
+ }
+
+ mSyncer->mCommonEntries.clear();
+
+
+ //
+ // Put KDE Address Book list into Common List
+ //
+
+ for ( i = 0; i < mSyncer->mKabEntries.count(); i++ )
+ if ( mSyncer->mKabEntries.at( i )->mOn ) {
+ mSyncer->mCommonEntries.append(
+ new SyncEntryCommon( true, mSyncer->mKabEntries.at( i ), 0 ) );
+ mSyncer->mKabEntries.at( i )->mOn = false;
+ }
+
+
+ //
+ // Put Mobile Address Book list into Common List; Merge equivalent entries
+ //
+
+ for ( i = 0; i < mSyncer->mMobileEntries.count(); i++ ) {
+ SyncEntryMobile *mobileEntry = mSyncer->mMobileEntries.at( i );
+ bool equivalentEntryFound = false;
+ uint j;
+
+
+ if( !mobileEntry->mToBeDeleted )
+ for ( j = 0; j < mSyncer->mCommonEntries.count(); j++ ) {
+ SyncEntryCommon *theCommonEntry = mSyncer->mCommonEntries.at( j );
+
+
+ if ( theCommonEntry->mKabEntry &&
+ ( theCommonEntry->mKabEntry->mName == mobileEntry->mName ) ) {
+ theCommonEntry->mMobileEntry = mobileEntry;
+ equivalentEntryFound = true;
+
+ if ( noSpaces( theCommonEntry->mKabEntry->mPhone ) ==
+ mobileEntry->mPhone ) {
+ mobileEntry->mOn = false;
+ break;
+ } else {
+ // Conflict: 2 Entries have same name but different numbers.
+ // Prompt user.
+ QString text = "<qt><b>" + i18n( "Kab Entry:" ) + "</b><br>";
+ text += " " + theCommonEntry->mKabEntry->mName + " " +
+ theCommonEntry->mKabEntry->mPhone + "<br>";
+ text += "<b>" + i18n( "Mobile Entry:" ) + "</b><br>";
+ text += " " + mobileEntry->mName + " " + mobileEntry->mPhone;
+ text += "</qt>";
+
+ QMessageBox *msg =
+ new QMessageBox( i18n( "Conflicting Entries" ), text,
+ QMessageBox::Warning, 1, 2, 0, this );
+ msg->setButtonText( 1, i18n( "Use Kab Entry" ) );
+ msg->setButtonText( 2, i18n( "Use Mobile Entry" ) );
+
+ switch ( msg->exec() ) {
+ case 1:
+ // Use KDE Address Book Entry
+ mobileEntry->mPhone = theCommonEntry->mKabEntry->mPhone;
+ mobileEntry->mName = theCommonEntry->mKabEntry->mName;
+ mobileEntry->mOn = true;
+ mobileEntry->mToBeUpdated = true;
+
+ setMobState( MODIFIED );
+ break;
+
+ case 2:
+ // Use Mobile Address Book Entry
+ theCommonEntry->mKabEntry->mPhone = mobileEntry->mPhone;
+ theCommonEntry->mKabEntry->mName = mobileEntry->mName;
+ theCommonEntry->mKabEntry->mOn = true;
+ theCommonEntry->mKabEntry->mToBeUpdated = true;
+
+ mobileEntry->mOn = false;
+
+ setKabState( MODIFIED );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !equivalentEntryFound && mobileEntry->mOn ) {
+ // No equivalent entry exists; generate a new one.
+ mSyncer->mCommonEntries.append(
+ new SyncEntryCommon( true, 0, mobileEntry ) );
+ mobileEntry->mOn = false;
+ }
+ }
+
+
+ //
+ // Create new KAB and Mobile Entries
+ //
+
+ for ( i = 0; i < mSyncer->mCommonEntries.count(); i++ ) {
+ SyncEntryCommon *entry = mSyncer->mCommonEntries.at( i );
+ SyncEntryKab *kabEntry = entry->mKabEntry;
+ SyncEntryMobile *mobileEntry = entry->mMobileEntry;
+
+
+ if ( kabEntry && !mobileEntry ) {
+ // Create Mobile Entry
+ entry->mMobileEntry = new SyncEntryMobile( true, "", kabEntry->mPhone,
+ kabEntry->mName );
+ entry->mMobileEntry->mToBeInserted = true;
+ mSyncer->mMobileEntries.append( entry->mMobileEntry );
+
+ setMobState( MODIFIED );
+ } else
+ if ( mobileEntry && !kabEntry ) {
+ // Create KAB Entry
+ entry->mKabEntry = new SyncEntryKab( true, mobileEntry->mIndex,
+ mobileEntry->mName,
+ mobileEntry->mPhone );
+ entry->mKabEntry->mToBeInserted = true;
+ mSyncer->mKabEntries.append( entry->mKabEntry );
+
+ setKabState( MODIFIED );
+ }
+ }
+
+
+ //
+ // Update GUI
+ //
+
+ updateKabBook();
+ updateMobileBook();
+
+ emit transientStatusMessage( i18n( "Synced phonebooks." ) );
+ PushButton8_3->setEnabled( true );
+}
+
+
+void MobileGui::syncPhonebooks()
+{
+ PushButton8_3->setEnabled( false );
+
+ if ( mKabState == UNLOADED )
+ readKabc();
+ if ( mMobState == UNLOADED ) {
+ mComingFromSyncPhonebooks = true;
+ readPhonebook();
+ } else
+ mergePhonebooks();
+}
+
+
+void MobileGui::updateKabBook()
+{
+ mKabBook->clear();
+
+ for ( uint i = 0; i < mSyncer->mKabEntries.count(); i++ ) {
+ SyncEntryKab *kabEntry = mSyncer->mKabEntries.at( i );
+ PhoneBookItem *item = new PhoneBookItem( mKabBook, kabEntry,
+ kabEntry->mName, kabEntry->mPhone,
+ kabEntry->mIndex );
+ item->setOn( kabEntry->mOn );
+ }
+}
+
+
+void MobileGui::updateMobileBook()
+{
+ mMobileBook->clear();
+
+ for ( uint i = 0; i < mSyncer->mMobileEntries.count(); i++ ) {
+ SyncEntryMobile *entry = mSyncer->mMobileEntries.at( i );
+
+ if ( !entry->mToBeDeleted ) {
+ PhoneBookItem *item = new PhoneBookItem( mMobileBook, entry, entry->mName,
+ entry->mPhone, entry->mIndex );
+ item->setOn( entry->mOn );
+ }
+ }
+}
+
+
+void MobileGui::toggleConnection()
+{
+ if ( mConnectButton->text() == i18n( "Connect" ) ) {
+ emit connectModem();
+
+ readModelInformation();
+ refreshStatus();
+
+ mConnectButton->setText( tr2i18n( "Disconnect" ) );
+ PushButton1->setEnabled( true );
+ PushButton5_3->setEnabled( true );
+
+ mABTab->setEnabled( true );
+ setKabState( UNLOADED );
+ setMobState( UNLOADED );
+
+ ((MobileMain *) mparent)->statusBar()->changeItem( i18n(" Connected "), 1 );
+ } else {
+ warnKabState( UNLOADED );
+
+ mComingFromToggleConnection = true;
+ if ( !warnMobState( UNLOADED ) ) {
+ mComingFromToggleConnection = false;
+ disconnectGUI();
+ }
+ }
+}
+
+
+void MobileGui::disconnectGUI()
+{
+ emit disconnectModem();
+
+ mManufacturerLabel->setText( "x" );
+ mModelLabel->setText( "x" );
+ mGSMVersionLabel->setText( "x" );
+ mSerialNumberLabel->setText( "x" );
+
+ mBatteryChargeLabel->setText( "xx %" );
+ mSignalQualityLabel->setText( "x" );
+
+ mConnectButton->setText( tr2i18n( "Connect" ) );
+ PushButton1->setEnabled( false );
+ PushButton5_3->setEnabled( false );
+
+ mKabBook->clear();
+ mMobileBook->clear();
+ setKabState( UNLOADED );
+ setMobState( UNLOADED );
+
+ mABTab->setEnabled( false );
+
+ mMobHasFD = false;
+ mMobHasLD = false;
+ mMobHasME = false;
+ mMobHasMT = false;
+ mMobHasTA = false;
+ mMobHasOW = false;
+ mMobHasMC = false;
+ mMobHasRC = false;
+
+ mPBIndexOccupied.resize( 0, false );
+
+ ((MobileMain *) mparent)->statusBar()->changeItem( i18n(" Disconnected "),
+ 1 );
+}
+
+
+void MobileGui::termAddOutput( const char *line )
+{
+ mTermIO->append( line );
+ mTermIO->setCursorPosition( mTermIO->paragraphs() - 1, 0 );
+}
+
+
+void MobileGui::setKabState( ABState newState )
+{
+ switch ( mKabState ) {
+ case UNLOADED:
+ groupBox3->setTitle( tr2i18n( "KDE Address Book" ) );
+ mReadKabButton->setEnabled( true );
+ PushButton8->setEnabled( false );
+ break;
+
+ case LOADED:
+ if ( newState == MODIFIED ) {
+ groupBox3->setTitle( tr2i18n( "KDE Address Book (modified)" ) );
+ mReadKabButton->setEnabled( true );
+ PushButton8->setEnabled( true );
+ } else
+ if ( newState == UNLOADED ) {
+ groupBox3->setTitle( tr2i18n( "KDE Address Book" ) );
+ mReadKabButton->setEnabled( true );
+ PushButton8->setEnabled( false );
+ }
+ break;
+
+ case MODIFIED:
+ if ( newState != MODIFIED ) {
+ groupBox3->setTitle( tr2i18n( "KDE Address Book" ) );
+ mReadKabButton->setEnabled( true );
+ PushButton8->setEnabled( false );
+ }
+ break;
+ }
+
+ mKabState = newState;
+}
+
+
+void MobileGui::warnKabState( ABState newState )
+{
+ if ( ( mKabState == MODIFIED ) && ( newState != MODIFIED ) ) {
+ QString text = "<qt><b>" + i18n( "Warning" ) + "</b><br>";
+ text += i18n( "The KDE address book contains unsaved changes." ) +
+ "<br></qt>";
+
+ QMessageBox *msg = new QMessageBox( i18n( "Unsaved Changes" ), text,
+ QMessageBox::Critical, 1, 2, 0, this );
+ msg->setButtonText( 1, i18n( "Save" ) );
+ msg->setButtonText( 2, i18n( "Discard" ) );
+
+ switch ( msg->exec() ) {
+ case 1:
+ // Save Changes first
+ writeKabc();
+ break;
+
+ case 2:
+ break;
+ }
+ }
+}
+
+
+void MobileGui::setMobState( ABState newState )
+{
+ switch ( mMobState ) {
+ case UNLOADED:
+ if ( newState == UNLOADED ) {
+ groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) );
+ PushButton3->setEnabled( true );
+ PushButton12->setEnabled( false );
+ PushButton4_2->setEnabled( false );
+ MobDeleteButton->setEnabled( false );
+ } else
+ if ( newState == LOADED ) {
+ groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) );
+ PushButton3->setEnabled( true );
+ PushButton12->setEnabled( false );
+ PushButton4_2->setEnabled( true );
+ MobDeleteButton->setEnabled( true );
+ }
+ break;
+
+ case LOADED:
+ if ( newState == MODIFIED ) {
+ groupBox4->setTitle( tr2i18n( "Mobile Phone Book (modified)" ) );
+ PushButton3->setEnabled( true );
+ PushButton12->setEnabled( true );
+ PushButton4_2->setEnabled( true );
+ MobDeleteButton->setEnabled( true );
+ } else
+ if ( newState == UNLOADED ) {
+ groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) );
+ PushButton3->setEnabled( true );
+ PushButton12->setEnabled( false );
+ PushButton4_2->setEnabled( false );
+ MobDeleteButton->setEnabled( false );
+ }
+ break;
+
+ case MODIFIED:
+ if ( newState == UNLOADED ) {
+ groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) );
+ PushButton3->setEnabled( true );
+ PushButton12->setEnabled( false );
+ PushButton4_2->setEnabled( false );
+ MobDeleteButton->setEnabled( false );
+ } else
+ if ( newState == LOADED ) {
+ groupBox4->setTitle( tr2i18n( "Mobile Phone Book" ) );
+ PushButton3->setEnabled( true );
+ PushButton12->setEnabled( false );
+ PushButton4_2->setEnabled( true );
+ MobDeleteButton->setEnabled( true );
+ }
+ break;
+ }
+
+ mMobState = newState;
+}
+
+
+bool MobileGui::warnMobState( ABState newState )
+{
+ if ( ( mMobState == MODIFIED ) && ( newState != MODIFIED ) )
+ {
+ QString text = "<qt><b>" + i18n( "Warning" ) + "</b><br>";
+ text += i18n( "The mobile phone book contains unsaved changes." ) +
+ "<br></qt>";
+
+ QMessageBox *msg = new QMessageBox( i18n( "Unsaved Changes" ), text,
+ QMessageBox::Critical, 1, 2, 0, this );
+ msg->setButtonText( 1, i18n( "Save" ) );
+ msg->setButtonText( 2, i18n( "Discard" ) );
+
+ switch ( msg->exec() ) {
+ case 1:
+ // Save Changes first
+ writePhonebook();
+ return true;
+ break;
+
+ case 2:
+ return false;
+ break;
+ }
+ }
+
+ return false;
+}
diff --git a/kandy/src/mobilegui.h b/kandy/src/mobilegui.h
new file mode 100644
index 000000000..b3dbd33ff
--- /dev/null
+++ b/kandy/src/mobilegui.h
@@ -0,0 +1,136 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+#ifndef MOBILEGUI_H
+#define MOBILEGUI_H
+
+#include <kandyiface.h>
+
+#include "mobilegui_base.h"
+#include "kandyprefs.h"
+#include "qvaluevector.h"
+
+
+class CommandScheduler;
+class ATCommand;
+class AddressSyncer;
+
+
+class MobileGui : public MobileGui_base, virtual public KandyIface
+{
+ Q_OBJECT
+
+ public:
+ MobileGui( CommandScheduler *, KandyPrefs *kprefs, QWidget* parent=0,
+ const char* name=0, WFlags fl=0 );
+ ~MobileGui();
+
+ void exit();
+
+ signals:
+ void sendCommand( const QString & );
+ void phonebookRead();
+
+ void statusMessage( const QString & );
+ void transientStatusMessage( const QString & );
+ void connectModem();
+ void disconnectModem();
+
+ public slots:
+ void readModelInformation();
+ void readPhonebook();
+ void savePhonebook();
+ void refreshStatus();
+ void writePhonebook();
+ void readKabc();
+ void writeKabc();
+ void setClock();
+ void mergePhonebooks();
+ void syncPhonebooks();
+ void termAddOutput( const char *line );
+ void toggleConnection();
+ void deleteMobPhonebook();
+
+ protected slots:
+ void processResult( ATCommand * );
+
+ private:
+ /* Links to related classes */
+ CommandScheduler *mScheduler;
+ AddressSyncer *mSyncer;
+ KandyPrefs *mPrefs;
+ QWidget *mparent;
+
+ /* String Formatting Routines */
+ QString quote( const QString & );
+ QString dequote( const QString & );
+ void formatPBName( QString *, QString );
+ QString noSpaces( const QString & );
+ int firstFreeIndex();
+ QString string2GSM( const QString & );
+ QString GSM2String( const QString & );
+ QString decodeSuffix( const QString & );
+ QString stripWhiteSpaces( const QString & );
+
+ /* Routines for GUI updates */
+ void updateKabBook();
+ void updateMobileBook();
+ void disconnectGUI();
+
+ /* Phone specific items */
+ QString mMobManufacturer;
+ QString mMobModel;
+ unsigned int mPBStartIndex;
+ unsigned int mPBLength;
+ unsigned int mPBNameLength;
+ QValueVector<bool> mPBIndexOccupied;
+ bool mMobHasFD;
+ bool mMobHasLD;
+ bool mMobHasME;
+ bool mMobHasMT;
+ bool mMobHasTA;
+ bool mMobHasOW;
+ bool mMobHasMC;
+ bool mMobHasRC;
+
+ /* Routines and Flags for asynchronous control flow */
+ QString mLastWriteId;
+ bool mComingFromToggleConnection;
+ bool mComingFromReadPhonebook;
+ bool mComingFromSyncPhonebooks;
+ bool mComingFromExit;
+ void writePhonebookPostProcessing();
+
+ /* Routines and elements for current state of phone books */
+ enum ABState { UNLOADED, LOADED, MODIFIED };
+ ABState mKabState, mMobState;
+ void setKabState( ABState );
+ void warnKabState( ABState );
+ void setMobState( ABState );
+ bool warnMobState( ABState );
+
+ /* Misc */
+ void fillPhonebook( ATCommand * );
+};
+
+#endif // MOBILEGUI_H
diff --git a/kandy/src/mobilegui_base.ui b/kandy/src/mobilegui_base.ui
new file mode 100644
index 000000000..6361e5477
--- /dev/null
+++ b/kandy/src/mobilegui_base.ui
@@ -0,0 +1,583 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>MobileGui_base</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>MobileGui_base</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>865</width>
+ <height>473</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Mobile Device</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="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>GroupBox2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Model Information</string>
+ </property>
+ <grid>
+
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Model:</string>
+ </property>
+ </widget>
+
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>TextLabel3_2</cstring>
+ </property>
+ <property name="text">
+ <string>Serial number:</string>
+ </property>
+ </widget>
+
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>mManufacturerLabel</cstring>
+ </property>
+ <property name="text">
+ <string>x</string>
+ </property>
+ </widget>
+
+ <widget class="QLabel" row="2" column="1">
+ <property name="name">
+ <cstring>mGSMVersionLabel</cstring>
+ </property>
+ <property name="text">
+ <string>x</string>
+ </property>
+ </widget>
+
+ <widget class="QLabel" row="3" column="1">
+ <property name="name">
+ <cstring>mSerialNumberLabel</cstring>
+ </property>
+ <property name="text">
+ <string>x</string>
+ </property>
+ </widget>
+
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>mModelLabel</cstring>
+ </property>
+ <property name="text">
+ <string>x</string>
+ </property>
+ </widget>
+
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Manufacturer:</string>
+ </property>
+ </widget>
+
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>GSM version:</string>
+ </property>
+ </widget>
+
+ <spacer row="0" column="2">
+ <property name="name">
+ <cstring>spacer42</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>
+ </grid>
+ </widget>
+ <widget class="QTabWidget" row="1" column="0" colspan="2">
+ <property name="name">
+ <cstring>mTabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>mABTab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Address Books</string>
+ </attribute>
+ <property name="Enabled">
+ <bool>false</bool>
+ </property>
+ <grid>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>KDE Address Book</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QListView" row="0" column="0" rowspan="3" colspan="1">
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Phone</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>mKabBook</cstring>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>mReadKabButton</cstring>
+ </property>
+ <property name="text">
+ <string>Read</string>
+ </property>
+ </widget>
+ <spacer row="2" 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="1" column="1">
+ <property name="name">
+ <cstring>PushButton8</cstring>
+ </property>
+ <property name="text">
+ <string>Write</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox" row="0" column="1">
+ <property name="name">
+ <cstring>groupBox4</cstring>
+ </property>
+ <property name="title">
+ <string>Mobile Phone Book</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>PushButton3</cstring>
+ </property>
+ <property name="text">
+ <string>Read</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>PushButton12</cstring>
+ </property>
+ <property name="text">
+ <string>Write</string>
+ </property>
+ </widget>
+ <spacer row="3" 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>40</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="2" column="1">
+ <property name="name">
+ <cstring>PushButton4_2</cstring>
+ </property>
+ <property name="text">
+ <string>Save to File...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="4" column="1">
+ <property name="name">
+ <cstring>MobDeleteButton</cstring>
+ </property>
+ <property name="text">
+ <string>Delete</string>
+ </property>
+ </widget>
+ <widget class="QListView" row="0" column="0" rowspan="5" colspan="1">
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Phone</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>mMobileBook</cstring>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout21</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>PushButton8_3</cstring>
+ </property>
+ <property name="text">
+ <string>Sync</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>321</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>mTerminalTab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Terminal</string>
+ </attribute>
+ <grid>
+ <widget class="QTextEdit" row="0" column="0">
+ <property name="name">
+ <cstring>mTermIO</cstring>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ <widget class="QGroupBox" row="0" column="1">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Status</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="0" column="0">
+ <property name="name">
+ <cstring>mStatus</cstring>
+ </property>
+ <property name="text">
+ <string>Battery charge:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>TextLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>Signal quality:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>mSignalQualityLabel</cstring>
+ </property>
+ <property name="text">
+ <string>x</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>mBatteryChargeLabel</cstring>
+ </property>
+ <property name="text">
+ <string>xx %</string>
+ </property>
+ </widget>
+ <spacer row="2" column="0" colspan="5">
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="3" column="0">
+ <property name="name">
+ <cstring>mConnectButton</cstring>
+ </property>
+ <property name="text">
+ <string>Connect</string>
+ </property>
+ </widget>
+ <spacer row="3" column="2">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="3" column="3">
+ <property name="name">
+ <cstring>PushButton1</cstring>
+ </property>
+ <property name="text">
+ <string>Refresh</string>
+ </property>
+ <property name="Enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="3" column="4">
+ <property name="name">
+ <cstring>PushButton5_3</cstring>
+ </property>
+ <property name="text">
+ <string>Set Clock</string>
+ </property>
+ <property name="Enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>mReadKabButton</sender>
+ <signal>clicked()</signal>
+ <receiver>MobileGui_base</receiver>
+ <slot>readKabc()</slot>
+ </connection>
+ <connection>
+ <sender>PushButton8</sender>
+ <signal>clicked()</signal>
+ <receiver>MobileGui_base</receiver>
+ <slot>writeKabc()</slot>
+ </connection>
+ <connection>
+ <sender>PushButton3</sender>
+ <signal>clicked()</signal>
+ <receiver>MobileGui_base</receiver>
+ <slot>readPhonebook()</slot>
+ </connection>
+ <connection>
+ <sender>PushButton12</sender>
+ <signal>clicked()</signal>
+ <receiver>MobileGui_base</receiver>
+ <slot>writePhonebook()</slot>
+ </connection>
+ <connection>
+ <sender>PushButton4_2</sender>
+ <signal>clicked()</signal>
+ <receiver>MobileGui_base</receiver>
+ <slot>savePhonebook()</slot>
+ </connection>
+ <connection>
+ <sender>PushButton5_3</sender>
+ <signal>clicked()</signal>
+ <receiver>MobileGui_base</receiver>
+ <slot>setClock()</slot>
+ </connection>
+ <connection>
+ <sender>PushButton8_3</sender>
+ <signal>clicked()</signal>
+ <receiver>MobileGui_base</receiver>
+ <slot>syncPhonebooks()</slot>
+ </connection>
+ <connection>
+ <sender>PushButton1</sender>
+ <signal>clicked()</signal>
+ <receiver>MobileGui_base</receiver>
+ <slot>refreshStatus()</slot>
+ </connection>
+ <connection>
+ <sender>mConnectButton</sender>
+ <signal>clicked()</signal>
+ <receiver>MobileGui_base</receiver>
+ <slot>toggleConnection()</slot>
+ </connection>
+ <connection>
+ <sender>MobDeleteButton</sender>
+ <signal>clicked()</signal>
+ <receiver>MobileGui_base</receiver>
+ <slot>deleteMobPhonebook()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>mKabBook</tabstop>
+ <tabstop>mReadKabButton</tabstop>
+ <tabstop>PushButton8</tabstop>
+ <tabstop>mMobileBook</tabstop>
+ <tabstop>PushButton3</tabstop>
+ <tabstop>PushButton12</tabstop>
+ <tabstop>PushButton4_2</tabstop>
+ <tabstop>MobDeleteButton</tabstop>
+ <tabstop>PushButton5_3</tabstop>
+ <tabstop>PushButton1</tabstop>
+ <tabstop>PushButton8_3</tabstop>
+</tabstops>
+<slots>
+ <slot>readKabc()</slot>
+ <slot>readModelInformation()</slot>
+ <slot>readPhonebook()</slot>
+ <slot>refreshStatus()</slot>
+ <slot>savePhonebook()</slot>
+ <slot>setClock()</slot>
+ <slot>syncPhonebooks()</slot>
+ <slot>writeKabc()</slot>
+ <slot>writePhonebook()</slot>
+ <slot>termAddOutput( const char *line )</slot>
+ <slot>toggleConnection()</slot>
+ <slot>deleteMobPhonebook()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kandy/src/mobilemain.cpp b/kandy/src/mobilemain.cpp
new file mode 100644
index 000000000..118ee7f4e
--- /dev/null
+++ b/kandy/src/mobilemain.cpp
@@ -0,0 +1,191 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+
+#include <kglobal.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kmenubar.h>
+#include <kkeydialog.h>
+#include <kaccel.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kedittoolbar.h>
+#include <kurldrag.h>
+
+#include <kstdaccel.h>
+#include <kaction.h>
+#include <kstdaction.h>
+
+#include <qpushbutton.h>
+
+#include "mobilegui.h"
+
+#include "mobilemain.h"
+#include <kstatusbar.h>
+#include "mobilemain.moc"
+
+MobileMain::MobileMain(CommandScheduler *scheduler, KandyPrefs *prefs)
+ : KMainWindow( 0, "MobileMain" )
+{
+ mView = new MobileGui(scheduler, prefs, this);
+ setCentralWidget(mView);
+ setupActions();
+
+ statusBar()->insertItem(i18n(" Disconnected "),1,0,true);
+ connect(mView,SIGNAL(statusMessage(const QString &)),
+ SLOT(showStatusMessage(const QString &)));
+ connect(mView,SIGNAL(transientStatusMessage(const QString &)),
+ SLOT(showTransientStatusMessage(const QString &)));
+
+ statusBar()->show();
+
+ setAutoSaveSettings();
+}
+
+MobileMain::~MobileMain()
+{
+}
+
+void MobileMain::setupActions()
+{
+ KStdAction::quit(this, SLOT(close()), actionCollection());
+
+ new KAction(i18n("Terminal"),0,this,SLOT(showTerminal()),
+ actionCollection(),"show_terminal");
+
+ createStandardStatusBarAction();
+ setStandardToolBarMenuEnabled(true);
+
+ KStdAction::keyBindings(this, SLOT(optionsConfigureKeys()), actionCollection());
+ KStdAction::configureToolbars(this, SLOT(optionsConfigureToolbars()), actionCollection());
+ KStdAction::preferences(this, SLOT(optionsPreferences()), actionCollection());
+
+ createGUI("kandymobileui.rc");
+}
+
+void MobileMain::saveProperties(KConfig */*config*/)
+{
+ // the 'config' object points to the session managed
+ // config file. anything you write here will be available
+ // later when this app is restored
+}
+
+void MobileMain::readProperties(KConfig */*config*/)
+{
+ // the 'config' object points to the session managed
+ // config file. this function is automatically called whenever
+ // the app is being restored. read in here whatever you wrote
+ // in 'saveProperties'
+}
+
+void MobileMain::dragEnterEvent(QDragEnterEvent *event)
+{
+ // do nothing
+ KMainWindow::dragEnterEvent(event);
+
+ // accept uri drops only
+// event->accept(KURLDrag::canDecode(event));
+}
+
+void MobileMain::dropEvent(QDropEvent *event)
+{
+ // this is a very simplistic implementation of a drop event. we
+ // will only accept a dropped URL. the Qt dnd code can do *much*
+ // much more, so please read the docs there
+
+ // do nothing
+ KMainWindow::dropEvent(event);
+}
+
+void MobileMain::optionsConfigureKeys()
+{
+ KKeyDialog::configure( actionCollection(), this );
+}
+
+void MobileMain::optionsConfigureToolbars()
+{
+ // use the standard toolbar editor
+ saveMainWindowSettings( KGlobal::config(), autoSaveGroup() );
+ KEditToolbar dlg(actionCollection());
+ connect(&dlg, SIGNAL(newToolbarConfig()), this, SLOT(newToolbarConfig()));
+ dlg.exec();
+}
+
+void MobileMain::newToolbarConfig()
+{
+ // recreate our GUI
+ createGUI("kandymobileui.rc");
+ applyMainWindowSettings( KGlobal::config(), autoSaveGroup() );
+}
+
+void MobileMain::optionsPreferences()
+{
+ emit showPreferencesWin();
+}
+
+void MobileMain::showStatusMessage(const QString& text)
+{
+ // display the text on the statusbar
+ statusBar()->message(text);
+}
+
+void MobileMain::showTransientStatusMessage(const QString& text)
+{
+ // display the text on the statusbar for 2 s.
+ statusBar()->message(text,2000);
+}
+
+void MobileMain::changeCaption(const QString& text)
+{
+ // display the text on the caption
+ setCaption(text);
+}
+
+bool MobileMain::queryClose()
+{
+#if 0
+ if (m_view->isModified()) {
+ switch (KMessageBox::warningYesNoCancel(this,
+ i18n("Save changes to profile %1?").arg(mFilename))) {
+ case KMessageBox::Yes :
+ fileSave();
+ return true;
+ case KMessageBox::No :
+ return true;
+ default: // cancel
+ return false;
+ }
+ } else {
+ return true;
+ }
+#endif
+ return true;
+}
+
+void MobileMain::showTerminal()
+{
+ emit showTerminalWin();
+}
diff --git a/kandy/src/mobilemain.h b/kandy/src/mobilemain.h
new file mode 100644
index 000000000..091d0de0e
--- /dev/null
+++ b/kandy/src/mobilemain.h
@@ -0,0 +1,109 @@
+/*
+ This file is part of Kandy.
+
+ Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ As a special exception, permission is given to link this program
+ with any edition of Qt, and distribute the resulting executable,
+ without including the source code for Qt in the source distribution.
+*/
+#ifndef MOBILEMAIN_H
+#define MOBILEMAIN_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kapplication.h>
+#include <kmainwindow.h>
+
+#include "kandyprefs.h"
+
+class CommandScheduler;
+
+/**
+ * This class serves as the main window for MobileMain. It handles the
+ * menus, toolbars, and status bars.
+ *
+ * @short Main window class
+ * @author Cornelius Schumacher <schumacher@kde.org>
+ * @version 0.1
+ */
+class MobileMain : public KMainWindow
+{
+ Q_OBJECT
+ public:
+ /**
+ * Default Constructor
+ */
+ MobileMain(CommandScheduler *, KandyPrefs *prefs);
+
+ /**
+ * Default Destructor
+ */
+ virtual ~MobileMain();
+
+ MobileGui *view() { return mView; };
+
+ signals:
+ void showTerminalWin();
+ void showPreferencesWin();
+
+ protected:
+ /**
+ * Overridden virtuals for Qt drag 'n drop (XDND)
+ */
+ virtual void dragEnterEvent(QDragEnterEvent *event);
+ virtual void dropEvent(QDropEvent *event);
+
+ bool queryClose();
+
+ protected:
+ /**
+ * This function is called when it is time for the app to save its
+ * properties for session management purposes.
+ */
+ void saveProperties(KConfig *);
+
+ /**
+ * This function is called when this app is restored. The KConfig
+ * object points to the session management config file that was saved
+ * with @ref saveProperties
+ */
+ void readProperties(KConfig *);
+
+
+ private slots:
+ void showTerminal();
+ void optionsConfigureKeys();
+ void optionsConfigureToolbars();
+ void optionsPreferences();
+ void newToolbarConfig();
+
+ void showStatusMessage(const QString& text);
+ void showTransientStatusMessage(const QString& text);
+ void changeCaption(const QString& text);
+
+
+ private:
+ void setupActions();
+
+ private:
+ MobileGui *mView;
+};
+
+#endif // MOBILEMAIN_H
diff --git a/kandy/src/modem.cpp b/kandy/src/modem.cpp
new file mode 100644
index 000000000..3341ad589
--- /dev/null
+++ b/kandy/src/modem.cpp
@@ -0,0 +1,703 @@
+/*
+ KMLOCfg
+
+ A utility to configure the ELSA MicroLink(tm) Office modem.
+
+ Copyright (C) 2000 Oliver Gantz <Oliver.Gantz@epost.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ ------
+ ELSA and MicroLink are trademarks of ELSA AG, Aachen.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <pwd.h>
+#include <errno.h>
+
+#include <qglobal.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "modem.h"
+
+
+#ifndef CSOH
+#define CSOH 01
+#endif
+
+#ifndef CSTX
+#define CSTX 02
+#endif
+
+#ifndef CEOT
+#define CEOT 04
+#endif
+
+#ifndef CACK
+#define CACK 06
+#endif
+
+#ifndef CNAK
+#define CNAK 025
+#endif
+
+#ifndef CCAN
+#define CCAN 030
+#endif
+
+
+
+Modem::Modem( KandyPrefs *kprefs, QObject *parent, const char *name ) :
+ QObject(parent, name)
+{
+ mOpen = false;
+
+ prefs = kprefs;
+
+ timer = new QTimer( this, "modemtimer" );
+ Q_CHECK_PTR( timer );
+ connect( timer, SIGNAL( timeout() ), SLOT( timerDone() ) );
+
+ init();
+ xreset();
+}
+
+
+Modem::~Modem()
+{
+ close();
+}
+
+
+void Modem::setSpeed( int speed )
+{
+ switch ( speed ) {
+ case 300:
+ cspeed = B300;
+ break;
+ case 600:
+ cspeed = B600;
+ break;
+ case 1200:
+ cspeed = B1200;
+ break;
+ case 2400:
+ cspeed = B2400;
+ break;
+ case 4800:
+ cspeed = B4800;
+ break;
+ case 9600:
+ cspeed = B9600;
+ break;
+ case 19200:
+ cspeed = B19200;
+ break;
+ case 38400:
+ cspeed = B38400;
+ break;
+ case 57600:
+ cspeed = B57600;
+ break;
+ case 115200:
+ cspeed = B115200;
+ break;
+ case 230400:
+ cspeed = B230400;
+ break;
+ default:
+#ifdef MODEM_DEBUG
+ fprintf(stderr, "Modem: setSpeed(): fallback to default speed.\n");
+#endif
+ cspeed = B38400;
+ }
+}
+
+
+void Modem::setData( int data )
+{
+ cflag &= ~CSIZE;
+
+ switch ( data ) {
+ case 5:
+ cflag |= CS5;
+ break;
+ case 6:
+ cflag |= CS6;
+ break;
+ case 7:
+ cflag |= CS7;
+ break;
+ default:
+ cflag |= CS8;
+ }
+}
+
+
+void Modem::setParity( char parity )
+{
+ cflag &= ~( PARENB | PARODD );
+
+ if ( parity == 'E' )
+ cflag |= PARENB;
+ else if ( parity == 'O' )
+ cflag |= PARENB | PARODD;
+}
+
+
+void Modem::setStop( int stop )
+{
+ if (stop == 2)
+ cflag |= CSTOPB;
+ else
+ cflag &= ~CSTOPB;
+}
+
+
+bool Modem::open()
+{
+ struct termios tty;
+
+
+ close();
+
+ if ( !lockDevice() )
+ return false;
+
+ QCString dev = QFile::encodeName( (*prefs).serialDevice() );
+ const char *fdev = dev.data();
+ if ( ( fd = ::open( fdev, O_RDWR | O_NOCTTY | O_NONBLOCK ) ) == -1 ) {
+ emit errorMessage( i18n( "Unable to open device '%1'. "
+ "Please check that you have sufficient permissions." )
+ .arg( fdev ) );
+ return false;
+ }
+
+ tcflush( fd, TCIOFLUSH );
+ if ( tcgetattr( fd, &init_tty ) == -1 ) {
+ int errnumber = errno;
+ emit errorMessage( i18n( "Communication setup failed (tcgetattr code: %1)" )
+ .arg(strerror(errnumber)) );
+ ::close( fd );
+ fd = 0;
+ return false;
+ }
+
+ memset( &tty, 0, sizeof( tty ) );
+ tty.c_iflag = IGNBRK | IGNPAR;
+ tty.c_oflag = 0;
+ tty.c_cflag = cflag;
+ tty.c_lflag = 0;
+ cfsetospeed( &tty, cspeed );
+ cfsetispeed( &tty, cspeed );
+ tcdrain( fd );
+
+ if ( tcsetattr( fd, TCSANOW, &tty ) == -1 ) {
+ emit errorMessage( i18n( "tcsetattr() failed." ) );
+ ::close( fd );
+ fd = 0;
+ return false;
+ }
+
+ sn = new QSocketNotifier( fd, QSocketNotifier::Read, this,
+ "modemsocketnotifier" );
+ Q_CHECK_PTR( sn );
+ connect( sn, SIGNAL( activated( int ) ), SLOT( readChar( int ) ) );
+
+ mOpen = true;
+
+ return true;
+}
+
+
+void Modem::close()
+{
+ timer->stop();
+
+ delete sn;
+ sn = 0;
+
+ if ( fd ) {
+ tcflush( fd, TCIOFLUSH );
+ tcsetattr( fd, TCSANOW, &init_tty );
+ ::close( fd );
+ fd = 0;
+ }
+
+ xreset();
+
+ unlockDevice();
+
+ mOpen = false;
+}
+
+
+void Modem::flush()
+{
+ if ( fd ) {
+ tcflush( fd, TCIOFLUSH );
+ bufpos = 0;
+ }
+}
+
+#ifdef HAVE_LOCKDEV
+#include <lockdev.h>
+#endif
+
+bool Modem::lockDevice()
+{
+ if ( is_locked )
+ return true;
+
+#ifdef HAVE_LOCKDEV
+ is_locked = !dev_lock( (*prefs).serialDevice().local8Bit() );
+ if (!is_locked)
+ emit errorMessage( i18n( "Unable to lock device '%1'." ).arg(
+ (*prefs).serialDevice() ));
+ return is_locked;
+#else
+ ssize_t count;
+ pid_t pid;
+ int lfd;
+ struct passwd *pw;
+ QStringList pathList;
+ QString fileName, content;
+
+ pathList = QStringList::split( "/", (*prefs).serialDevice() );
+ fileName = (*prefs).lockDirectory() + "/LCK.." + pathList.last();
+
+ if ( !access( QFile::encodeName( fileName ).data(), F_OK ) ) {
+ char buf[256];
+
+
+ if ( ( lfd = ::open( QFile::encodeName( fileName ), O_RDONLY ) ) < 0 ) {
+ emit errorMessage( i18n( "Unable to open lock file '%1'.")
+ .arg( fileName ) );
+ return false;
+ }
+
+ count = read( lfd, buf, 79 );
+
+ if ( count < 0 ) {
+ emit errorMessage( i18n( "Unable to read lock file '%1'.")
+ .arg( fileName ) );
+ ::close( lfd );
+ return false;
+ }
+ buf[ count ] = 0;
+ ::close( lfd );
+
+ count = sscanf( buf, "%d", &pid );
+ if ( ( count != 1 ) || ( pid <= 0 ) ) {
+ emit errorMessage( i18n( "Unable to get PID from file '%1'.")
+ .arg( fileName ) );
+ return false;
+ }
+
+ if ( !kill( (pid_t) pid, 0 ) ) {
+ emit errorMessage( i18n( "Process with PID %1, which is locking the device, is still running.")
+ .arg( pid ) );
+ return false;
+ }
+
+ if ( errno != ESRCH ) {
+ emit errorMessage( i18n( "Unable to emit signal to PID of existing lock file.") );
+ return false;
+ }
+ }
+
+ if ( ( lfd = creat( QFile::encodeName( fileName ).data(), 0644 ) ) == -1 ) {
+ emit errorMessage( i18n( "Unable to create lock file '%1'. "
+ "Please check that you have sufficient permissions.")
+ .arg( fileName ) );
+ return false;
+ }
+
+ pid = (int) getpid();
+ pw = getpwuid( getuid() );
+ content.sprintf( "%08d %s %s", pid, "kandy", pw->pw_name );
+ write( lfd, QFile::encodeName( content ).data(), content.length() );
+ ::close( lfd );
+
+ is_locked = true;
+
+ return true;
+#endif
+}
+
+
+void Modem::unlockDevice()
+{
+#ifdef HAVE_LOCKDEV
+ dev_unlock( (*prefs).serialDevice().local8Bit(), getpid() );
+#else
+ if ( is_locked ) {
+ QStringList pathList = QStringList::split( "/", (*prefs).serialDevice() );
+
+ QFile::remove( (*prefs).lockDirectory() + "/LCK.." + pathList.last() );
+ is_locked = false;
+ }
+#endif
+}
+
+
+bool Modem::dsrOn()
+{
+ int flags;
+
+
+ if ( !fd ) {
+#ifdef MODEM_DEBUG
+ fprintf( stderr, "Modem: dsrOn(): File not open.\n" );
+#endif
+ return false;
+ }
+
+ if ( ioctl( fd, TIOCMGET, &flags ) == -1 ) {
+#ifdef MODEM_DEBUG
+ fprintf( stderr, "Modem: dsrOn(): ioctl() failed.\n" );
+#endif
+ return false;
+ }
+
+ return ( flags & TIOCM_DSR ) != 0;
+}
+
+
+bool Modem::ctsOn()
+{
+ int flags;
+
+
+ if ( !fd ) {
+#ifdef MODEM_DEBUG
+ fprintf( stderr, "Modem: ctsOn(): File not open.\n" );
+#endif
+ return false;
+ }
+
+ if ( ioctl( fd, TIOCMGET, &flags ) == -1) {
+#ifdef MODEM_DEBUG
+ fprintf( stderr, "Modem: ctsOn(): ioctl() failed.\n" );
+#endif
+ return false;
+ }
+
+ return ( flags & TIOCM_CTS ) != 0;
+}
+
+
+void Modem::writeChar( const char c )
+{
+ write( fd, (const void *) &c, 1 );
+}
+
+
+void Modem::writeLine( const char *line )
+{
+ kdDebug() << "Modem::writeLine(): " << line << endl;
+
+ write( fd, (const void *) line, strlen( line ) );
+ writeChar( '\r' );
+}
+
+
+void Modem::timerStart( int msec )
+{
+ timer->start( msec, true );
+}
+
+
+void Modem::receiveXModem( bool crc )
+{
+ disconnect( sn, 0, this, 0 );
+ connect( sn, SIGNAL( activated( int ) ), SLOT( readXChar( int ) ) );
+
+ xcrc = crc;
+
+ if ( xcrc ) {
+ writeChar( 'C' );
+ xstate = 1;
+ timerStart( 3000 );
+ } else {
+ writeChar( CNAK );
+ xstate = 5;
+ timerStart( 10000 );
+ }
+
+ xblock = 1;
+}
+
+
+void Modem::abortXModem()
+{
+ timer->stop();
+ writeChar( CCAN );
+ xreset();
+ emit xmodemDone( false );
+}
+
+
+void Modem::timerDone()
+{
+#ifdef MODEM_DEBUG
+ fprintf( stderr, "Modem: timeout, xstate = %d.\n", xstate );
+#endif
+
+ switch ( xstate ) {
+ case 0: /* non-XModem mode */
+ emit timeout();
+ break;
+
+ case 1: /* 1st 'C' sent */
+ case 2: /* 2nd 'C' sent */
+ case 3: /* 3rd 'C' sent */
+ writeChar( 'C' );
+ xstate++;
+ timerStart( 1000 ); /* Should be 3000 in original XModem */
+ break;
+
+ case 4: /* 4th 'C' sent */
+ xcrc = false;
+
+ case 5: /* 1st <NAK> sent */
+ case 6: /* 2nd <NAK> sent */
+ case 7: /* 3rd <NAK> sent */
+ case 8: /* 4th <NAK> sent */
+ case 9: /* 5th <NAK> sent */
+ writeChar( CNAK );
+ xstate++;
+ timerStart( 1000 ); /* Should be 10000 in original XModem */
+ break;
+
+ case 10: /* 6th <NAK> sent */
+ xreset();
+ emit xmodemDone( false );
+ break;
+
+ default: /* pending XModem block */
+ writeChar( CNAK );
+ xstate = 5;
+ timerStart( 1000 ); /* Should be 10000 in original XModem */
+ }
+}
+
+
+void Modem::readChar( int )
+{
+ uchar c;
+
+
+ while ( read( fd, (void *) &c, 1 ) == 1 ) {
+ if ( c == '\n' ) {
+ buffer[ bufpos ] = 0;
+ bufpos = 0;
+ emit gotLine( (const char *) buffer );
+ break;
+ } else
+ if ( ( bufpos < 1000 ) && ( c != '\r' ) )
+ buffer[ bufpos++ ] = c;
+ }
+}
+
+
+void Modem::readXChar( int )
+{
+ uchar c;
+ static uchar crc_hi, block, cblock;
+
+
+ while ( read( fd, (void *) &c, 1 ) == 1 ) {
+ switch ( xstate ) {
+ case 1: /* 1st 'C' sent */
+ case 2: /* 2nd 'C' sent */
+ case 3: /* 3rd 'C' sent */
+ case 4: /* 4th 'C' sent */
+ case 5: /* 1st <NAK> sent */
+ case 6: /* 2nd <NAK> sent */
+ case 7: /* 3rd <NAK> sent */
+ case 8: /* 4th <NAK> sent */
+ case 9: /* 5th <NAK> sent */
+ case 10: /* 6th <NAK> sent */
+ if ( c == CSOH ) {
+ timerStart( 1000 );
+ xsize = 128;
+ xstate = 11;
+ } else
+ if ( c == CSTX ) {
+ timerStart( 1000 );
+ xsize = 1024;
+ xstate = 11;
+ } else
+ if ( c == CEOT ) {
+ timer->stop();
+ writeChar( CACK );
+ xreset();
+ emit xmodemDone( true );
+ } else
+ timerStart( 1000 );
+ break;
+
+ case 11: /* <SOH> or <STX> received */
+ timerStart( 1000 );
+ block = c;
+ xstate++;
+ break;
+
+ case 12: /* block number received */
+ timerStart( 1000 );
+ cblock = c;
+ xstate++;
+ bufpos = 0;
+ break;
+
+ case 13: /* complement block number received */
+ timerStart( 1000 );
+ buffer[ bufpos++ ] = c;
+ if ( bufpos == xsize ) {
+ bufpos = 0;
+ xstate++;
+ if ( !xcrc )
+ xstate++;
+ }
+ break;
+
+ case 14: /* data block received */
+ timerStart( 1000 );
+ crc_hi = c;
+ xstate++;
+ break;
+
+ case 15: /* crc high-byte received */
+ timerStart( 10000 );
+ xstate = 4;
+ if ( (uchar) ( block ^ cblock ) != 0xff ) {
+ writeChar( CNAK );
+ break;
+ }
+ if ( block+1 == xblock ) {
+ writeChar( CACK );
+ break;
+ }
+ if ( block != xblock ) {
+ timer->stop();
+ writeChar( CCAN );
+ xreset();
+ emit xmodemDone( false );
+ break;
+ }
+ if ( xcrc ) {
+ if ( ( (ushort) crc_hi << 8 | (ushort) c ) != calcCRC() ) {
+ writeChar( CNAK );
+ break;
+ }
+ } else {
+ if ( c != calcChecksum() ) {
+ writeChar( CNAK );
+ break;
+ }
+ }
+ writeChar( CACK );
+ xblock++;
+ emit gotXBlock( buffer, xsize );
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+
+void Modem::init()
+{
+ is_locked = false;
+
+ fd = 0;
+ sn = 0;
+
+ cspeed = B38400;
+
+ // No flow control
+ cflag = CS8 | CREAD | CLOCAL;
+ // cflag = CS8 | CREAD | CLOCAL | CRTSCTS;
+
+ bufpos = 0;
+}
+
+
+void Modem::xreset()
+{
+ bufpos = 0;
+
+ xstate = 0;
+ xcrc = false;
+ xblock = 0;
+ xsize = 0;
+
+ if ( sn ) {
+ disconnect( sn, 0, this, 0 );
+ connect( sn, SIGNAL( activated( int ) ), SLOT( readChar( int ) ) );
+ }
+}
+
+
+uchar Modem::calcChecksum()
+{
+ int i;
+ uchar c = 0;
+
+
+ for ( i = 0; i < xsize; i++ )
+ c += buffer[ i ];
+
+ return c;
+}
+
+
+ushort Modem::calcCRC()
+{
+ int i, j;
+ ushort c = 0;
+
+
+ for ( i = 0; i < xsize; i++ ) {
+ c ^= (ushort) buffer[ i ] << 8;
+ for ( j = 0; j < 8; j++ )
+ if ( c & 0x8000 )
+ c = c << 1 ^ 0x1021;
+ else
+ c <<= 1;
+ }
+
+ return c;
+}
+
+#include "modem.moc"
diff --git a/kandy/src/modem.h b/kandy/src/modem.h
new file mode 100644
index 000000000..ecb0cfe91
--- /dev/null
+++ b/kandy/src/modem.h
@@ -0,0 +1,124 @@
+/*
+ KMLOCfg
+
+ A utility to configure the ELSA MicroLink(tm) Office modem.
+
+ Copyright (C) 2000 Oliver Gantz <Oliver.Gantz@epost.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ ------
+ ELSA and MicroLink are trademarks of ELSA AG, Aachen.
+*/
+
+#ifndef MODEM_H
+#define MODEM_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <termios.h>
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qtimer.h>
+#include <qsocketnotifier.h>
+#include <qfile.h>
+
+#include "kandyprefs.h"
+
+
+
+
+class Modem : public QObject
+{
+ Q_OBJECT
+public:
+ Modem(KandyPrefs *kprefs, QObject *parent = 0, const char *name = 0);
+ virtual ~Modem();
+
+ void setSpeed(int speed);
+ void setData(int data);
+ void setParity(char parity);
+ void setStop(int stop);
+
+ bool open();
+ void close();
+
+ bool isOpen() { return mOpen; }
+
+ void flush();
+
+ bool lockDevice();
+ void unlockDevice();
+
+ bool dsrOn();
+ bool ctsOn();
+
+ void writeChar(const char c);
+ void writeLine(const char *line);
+
+ void timerStart(int msec);
+
+ void receiveXModem(bool crc);
+ void abortXModem();
+
+private slots:
+ void timerDone();
+
+ void readChar(int);
+ void readXChar(int);
+
+private:
+ bool mOpen;
+
+ void init();
+ void xreset();
+
+ uchar calcChecksum();
+ ushort calcCRC();
+
+ bool is_locked;
+ struct termios init_tty;
+
+ speed_t cspeed;
+ tcflag_t cflag;
+
+ int fd;
+ QTimer *timer;
+ QSocketNotifier *sn;
+
+ uchar buffer[1024];
+ int bufpos;
+
+ int xstate;
+ bool xcrc;
+ uchar xblock;
+ int xsize;
+
+ KandyPrefs *prefs;
+
+signals:
+ void gotLine(const char *);
+ void gotXBlock(const uchar *, int);
+ void xmodemDone(bool);
+ void timeout();
+
+ void errorMessage( const QString & );
+};
+
+
+#endif // MODEM_H
diff --git a/kandy/src/uninstall.desktop b/kandy/src/uninstall.desktop
new file mode 100644
index 000000000..e1e3e1732
--- /dev/null
+++ b/kandy/src/uninstall.desktop
@@ -0,0 +1,2 @@
+[Desktop Entry]
+Hidden=true