--- /dev/null
+*~
+*.o
+moc_*
+Makefile
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, 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.
+\f
+ 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.)
+\f
+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.
+\f
+ 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.
+\f
+ 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
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+evehomescreen (0.0.1-1) unstable; urgency=low
+
+ * Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
+
+ -- Jaakko Kyro <jkyro@korjaussarja.net> Wed, 5 May 2010 22:46:36 +0300
+
--- /dev/null
+Source: evehomescreen
+Section: user/Network
+Priority: extra
+Maintainer: Jaakko Kyro <jkyro@korjaussarja.net>
+Build-Depends: debhelper (>= 5)
+Standards-Version: 3.7.2
+
+Package: evehomescreen
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, qt4-maemo5-homescreen-loader
+Description: Homescreen widget to display Eve character training status
+ <insert long description, indented with spaces>
--- /dev/null
+usr/bin
+usr/sbin
--- /dev/null
+evehomescreen_0.0.1-1_i386.deb user/Network extra
--- /dev/null
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+
+
+
+CFLAGS = -Wall -g
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+ CFLAGS += -O0
+else
+ CFLAGS += -O2
+endif
+
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+ # Add here commands to configure the package.
+ cd src && /opt/qt4-maemo5/bin/qmake "PREFIX = /usr"
+ touch configure-stamp
+
+
+build: build-stamp
+
+build-stamp: configure-stamp
+ dh_testdir
+
+ # Add here commands to compile the package.
+ cd src && $(MAKE)
+ #docbook-to-man debian/evehomescreen.sgml > qt-eve-homescreen.1
+
+ touch $@
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp configure-stamp
+
+ # Add here commands to clean up after the build process.
+ -cd src && $(MAKE) clean
+
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ # Add here commands to install the package into debian/qt-eve-homescreen.
+ cd src && $(MAKE) INSTALL_ROOT=$(CURDIR)/debian/evehomescreen install
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installchangelogs
+ dh_installdocs
+ dh_installexamples
+# dh_install
+# dh_installmenu
+# dh_installdebconf
+# dh_installlogrotate
+# dh_installemacsen
+# dh_installpam
+# dh_installmime
+# dh_python
+# dh_installinit
+# dh_installcron
+# dh_installinfo
+ dh_installman
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+# dh_perl
+# dh_makeshlibs
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmaemo5homescreenadaptor.h"
+
+#include <QtCore/qsocketnotifier.h>
+
+#include <QtGui/qapplication.h>
+#include <QtGui/qx11info_x11.h>
+#include <QtGui/qwidget.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+static QCoreApplication::EventFilter oldEventFilter;
+static QList<QMaemo5HomescreenAdaptor *> allDesktopItems;
+
+static Atom atomByName(const char *name)
+{
+ Atom atom = XInternAtom(QX11Info::display(), name, False);
+ if (!atom)
+ qWarning("Unable to obtain %s atom. This class requires a running Hildon session.", name);
+
+ return atom;
+}
+
+enum HomescreenAtoms
+{
+ HildonAppletId = 0,
+ NetWmWindowType = 1,
+ Utf8String = 2,
+ HildonTypeHomeApplet = 3,
+ HildonAppletSettings = 4,
+ HildonAppletShowSettings = 5,
+ HildonAppletOnCurrentDesktop = 6,
+ EnumCount = 7
+};
+
+static Atom hsAtoms[EnumCount] = { 0, 0, 0, 0, 0, 0, 0 };
+
+static void initAtoms()
+{
+ hsAtoms[HildonAppletId] = atomByName("_HILDON_APPLET_ID");
+ hsAtoms[NetWmWindowType] = atomByName("_NET_WM_WINDOW_TYPE");
+ hsAtoms[Utf8String] = atomByName("UTF8_STRING");
+ hsAtoms[HildonTypeHomeApplet] = atomByName("_HILDON_WM_WINDOW_TYPE_HOME_APPLET");
+ hsAtoms[HildonAppletSettings] = atomByName("_HILDON_APPLET_SETTINGS");
+ hsAtoms[HildonAppletShowSettings] = atomByName("_HILDON_APPLET_SHOW_SETTINGS");
+ hsAtoms[HildonAppletOnCurrentDesktop] = atomByName("_HILDON_APPLET_ON_CURRENT_DESKTOP");
+}
+
+/*! \class QMaemo5HomescreenAdaptor
+
+ \brief The QMaemo5HomescreenAdaptor flags a top-level QWidget as homescreen widget
+
+ QMaemo5HomescreenAdaptor is used in conjunction with the Qt for Maemo homescreen
+ loader. It evaluates the two command line arguments "-plugin-id" and "-write-pipe"
+ to set up a Qt top-level widget as Maemo 5 homescreen widget.
+
+ Note: By default, the widget will have a black background. In order to make the
+ widget transparent, set the Qt::WA_TranslucentBackground widget attribute.
+
+ Example:
+
+ \code
+ QLabel *label = new QLabel("Hello Homescreen");
+ new QMaemo5HomescreenAdaptor(label);
+ label->show();
+ \endcode
+
+ Maemo 5 supports homescreen widgets with settings dialogs. To use it, set
+ the settingsAvailable() property and show a settings dialog when the
+ settingsRequested() signal is emitted.
+
+ Maemo 5 supports more than one homescreen. In order to determine whether
+ the homescreen widget is on the currently visible homescreen, connect to
+ the homescreenChanged() signal.
+*/
+
+/*! \property QMaemo5HomescreenAdaptor::settingsAvailable
+
+ Set this property to true if the widget can make use of a settings dialog,
+ otherwise to false. When this property is set to true, the Maemo 5 homescreen
+ renders a small settings icon on top of the homescreen widget when the
+ user enters the desktop menu. When the user clicks that settings icon, the
+ settingsRequested() signal is emitted.
+
+ The default is false.
+
+ \sa settingsRequested()
+ */
+
+/*! \fn void settingsRequested()
+
+ This signal is emitted every time the homescreen widget's settings icon is
+ invoked by the user. Note that this icon is only visible when the settingsAvailable()
+ property is set.
+
+ \sa settingsAvailable()
+ */
+
+/*! \fn void homescreenChanged(bool isOnCurrentHomescreen)
+
+ This is signal is emitted when current homescreen changes and the homescreen
+ widget becomes visible or invisible. The \a isOnCurrentHomescreen argument
+ indicates whether the homescreen widget is on the current homescreen or not.
+
+ This signal can be used to start/stop background processing in order to save
+ battery life.
+ */
+
+/*!
+ Constructs a new QMaemo5HomescreenAdaptor for the given \a widget.
+
+ Note: The widget must be a top-level widget, and must not be reparented
+ during the lifetime of this adaptor.
+
+ Note: \a widget is also the parent of this class, if the widget is destroyed,
+ so is this adaptor.
+ */
+QMaemo5HomescreenAdaptor::QMaemo5HomescreenAdaptor(QWidget *widget)
+ : QObject(widget),
+ hasSettings(false)
+{
+ Q_ASSERT(widget->isWindow());
+
+ if (!hsAtoms[0])
+ initAtoms();
+
+ Display *display = QX11Info::display();
+
+ const QStringList args = QApplication::arguments();
+
+ // parse the command line arguments.
+ int idx;
+ if ((idx = args.indexOf(QLatin1String("-plugin-id"))) != -1) {
+ appletId = args.value(idx + 1);
+ const QByteArray pluginId = appletId.toUtf8();
+ if (!pluginId.isEmpty()) {
+ XChangeProperty(display,
+ widget->winId(),
+ hsAtoms[HildonAppletId],
+ hsAtoms[Utf8String], 8, PropModeReplace,
+ reinterpret_cast<const unsigned char *>(pluginId.constData()),
+ pluginId.length());
+ }
+ }
+ if ((idx = args.indexOf(QLatin1String("-write-pipe"))) != -1) {
+ bool ok;
+ int sockId = args.value(idx + 1).toInt(&ok);
+ if (ok) {
+ socketNotifier = new QSocketNotifier(sockId, QSocketNotifier::Exception, this);
+ connect(socketNotifier, SIGNAL(activated(int)), this, SLOT(socketException()));
+ }
+ }
+
+ // set the X11 atoms to flag our widget as homescreen widget
+ if (!appletId.isEmpty()) {
+ XChangeProperty(display,
+ widget->winId(),
+ hsAtoms[NetWmWindowType],
+ XA_ATOM, 32, PropModeReplace,
+ reinterpret_cast<const unsigned char *>(&hsAtoms[HildonTypeHomeApplet]),
+ 1);
+
+ updateStatus();
+
+ // --- make this window a child of root
+ XSetTransientForHint(display, widget->winId(),
+ RootWindow(display, widget->x11Info().screen()));
+
+ // --- add an x11 event filter
+ if (!oldEventFilter)
+ oldEventFilter = QCoreApplication::instance()->setEventFilter(applicationEventFilter);
+
+ allDesktopItems.append(this);
+ }
+}
+
+QMaemo5HomescreenAdaptor::~QMaemo5HomescreenAdaptor()
+{
+ allDesktopItems.removeOne(this);
+}
+
+/*! \internal */
+void QMaemo5HomescreenAdaptor::updateStatus()
+{
+ if (appletId.isEmpty())
+ return;
+
+ Display *display = QX11Info::display();
+
+ // Set or remove settings property
+ if (hasSettings)
+ XChangeProperty(display,
+ appletWidget()->winId(),
+ hsAtoms[HildonAppletSettings],
+ XA_CARDINAL, 32, PropModeReplace,
+ (const unsigned char *) &(hasSettings), 1);
+ else
+ XDeleteProperty(display,
+ appletWidget()->winId(),
+ hsAtoms[HildonAppletSettings]);
+}
+
+/*! \internal */
+void QMaemo5HomescreenAdaptor::socketException()
+{
+ socketNotifier->setEnabled(false);
+ appletWidget()->close();
+}
+
+/*! \internal */
+bool QMaemo5HomescreenAdaptor::applicationEventFilter(void *message, long *result)
+{
+ bool retval = false;
+
+ if (oldEventFilter)
+ retval = oldEventFilter(message, result);
+
+ if (allDesktopItems.isEmpty())
+ return retval;
+
+ XEvent *ev = reinterpret_cast<XEvent *>(message);
+
+ if (ev->type == ClientMessage) {
+ XClientMessageEvent *cm = (XClientMessageEvent *)message;
+ if (cm->message_type == hsAtoms[HildonAppletShowSettings]) {
+ for (int i = 0; i < allDesktopItems.count(); ++i) {
+ if (allDesktopItems.at(i)->appletWidget()->winId() == ev->xproperty.window) {
+ emit allDesktopItems.at(i)->settingsRequested();
+ retval = true;
+ }
+ }
+ }
+ } else if (ev->type == PropertyNotify) {
+ if (ev->xproperty.atom == hsAtoms[HildonAppletOnCurrentDesktop]) {
+ for (int i = 0; i < allDesktopItems.count(); ++i) {
+ if (allDesktopItems.at(i)->appletWidget()->winId() == ev->xproperty.window) {
+ emit allDesktopItems.at(i)->homescreenChanged(ev->xproperty.window == 0);
+ retval = true;
+ }
+ }
+ }
+ }
+
+ return retval;
+}
+
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMAEMO5HOMESCREENADAPTOR_H
+#define QMAEMO5HOMESCREENADAPTOR_H
+
+#include <QtCore/qobject.h>
+#include <QtGui/qwidget.h>
+
+class QWidget;
+class QSocketNotifier;
+
+class QMaemo5HomescreenAdaptor : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool settingsAvailable READ settingsAvailable WRITE setSettingsAvailable)
+
+public:
+ QMaemo5HomescreenAdaptor(QWidget *widget);
+ ~QMaemo5HomescreenAdaptor();
+
+ inline void setSettingsAvailable(bool available)
+ {
+ hasSettings = available;
+ updateStatus();
+ }
+
+ inline bool settingsAvailable() const
+ {
+ return hasSettings;
+ }
+
+Q_SIGNALS:
+ void settingsRequested();
+ void homescreenChanged(bool isOnCurrentHomescreen);
+
+private Q_SLOTS:
+ void socketException();
+
+private:
+ inline QWidget *appletWidget() const { return static_cast<QWidget *>(parent()); }
+
+ void updateStatus();
+
+ static bool applicationEventFilter(void *message, long *result);
+
+ bool hasSettings;
+ QString appletId;
+ QSocketNotifier *socketNotifier;
+};
+
+#endif
--- /dev/null
+HEADERS += $$PWD/qmaemo5homescreenadaptor.h
+SOURCES += $$PWD/qmaemo5homescreenadaptor.cpp
+
+INCLUDEPATH += $$PWD
--- /dev/null
+#include "eveaccount.h"
+#include "QXmlStreamReader"
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QtDebug>
+EveCharacter::EveCharacter(QObject *parent) :
+ QObject(parent),
+ characterId(0),
+ corpId(0),
+ characterIcon(NULL)
+{
+}
+
+EveCharacter::EveCharacter(const EveCharacter &aOther):
+ QObject(aOther.parent()),
+ name(aOther.name),
+ corpName(aOther.corpName),
+ characterId(aOther.characterId),
+ corpId(aOther.corpId),
+ characterIcon(NULL)
+{
+ if (aOther.characterIcon) {
+ characterIcon = new QPixmap(*(aOther.characterIcon));
+ }
+}
+
+EveCharacter::~EveCharacter()
+{
+ if (characterIcon)
+ delete characterIcon;
+ characterIcon = NULL;
+}
+
+EveCharacter &EveCharacter::operator =(const EveCharacter &other)
+{
+ name = other.name;
+ characterId = other.characterId;
+ corpId = other.corpId;
+ corpName = other.corpName;
+ qDebug() << "Assignment, characterIcon " << characterIcon;
+ if (characterIcon != NULL) {
+ delete characterIcon;
+ characterIcon = NULL;
+ }
+ qDebug() << " after deletion";
+ qDebug() << " other icon" << other.characterIcon;
+ if (other.characterIcon != NULL)
+ characterIcon = new QPixmap(*(other.characterIcon));
+ qDebug() << "Assignment done";
+ return *this;
+}
+
+bool EveCharacter::fromXml(QXmlStreamReader &xml)
+{
+ if (xml.name() != "row")
+ return false;
+ name = xml.attributes().value("","name").toString();
+ characterId = xml.attributes().value("","characterID").toString().toInt();
+ corpName = xml.attributes().value("","corporationName").toString();
+ corpId = xml.attributes().value("","corporationID").toString().toInt();
+ return true;
+}
+
+bool EveCharacter::fetchImage()
+{
+ if (characterId == 0) {
+ qDebug() << "No character";
+ return false;
+ }
+ if (characterIcon != NULL) {
+ return true;
+
+ }
+ qDebug() << "Requesting image";
+ QNetworkRequest req(QUrl(QString("http://img.eve.is/serv.asp?c=%1&s=64").arg(characterId)));
+ m_reply = mgr.get(req);
+ connect(m_reply,SIGNAL(finished()),this,SLOT(imageReady()));
+ return true;
+}
+
+// Construct the pixmap from the reply data
+// and delete the reply
+void EveCharacter::imageReady()
+{
+ qDebug() << "Image ready";
+ characterIcon = new QPixmap;
+ if (!characterIcon->loadFromData(m_reply->readAll())) {
+ delete characterIcon;
+ characterIcon = NULL;
+ qDebug() << "Cannot load image";
+ return;
+ }
+ m_reply->deleteLater();
+ emit imageLoaded();
+}
--- /dev/null
+#ifndef EVEACCOUNT_H
+#define EVEACCOUNT_H
+
+#include <QObject>
+#include <QIODevice>
+#include <QXmlStreamReader>
+#include <QPixmap>
+#include <QNetworkReply>
+#include <QNetworkConfigurationManager>
+
+#include "eveskilltraining.h"
+class EveCharacter : public QObject
+{
+ Q_OBJECT
+public:
+ explicit EveCharacter(QObject *parent = 0);
+ EveCharacter(const EveCharacter &aOther);
+ EveCharacter &operator=(const EveCharacter&other);
+ ~EveCharacter();
+ bool fromXml(QXmlStreamReader &xml);
+ bool fetchImage();
+signals:
+ void imageLoaded();
+public slots:
+ void imageReady();
+public:
+ QString name;
+ QString corpName;
+ int characterId;
+ int corpId;
+ QPixmap *characterIcon;
+ EveSkillTraining currentSkill;
+private:
+ QNetworkReply *m_reply;
+ QNetworkAccessManager mgr;
+};
+
+#endif // EVEACCOUNT_H
--- /dev/null
+[Desktop Entry]
+Name=EVE Homescreen widget
+Comment=See character training
+Type=qt
+X-Path=evehomescreen
+X-Multiple-Instances=false
+X-home-applet-minwidth=128
+X-home-applet-minheight=128
+Name[en_US]=EVE Homescreen widget
+
--- /dev/null
+# -------------------------------------------------
+# Project created by QtCreator 2010-03-24T21:05:00
+# -------------------------------------------------
+QT += core \
+ gui \
+ network \
+ maemo5
+TARGET = evehomescreen
+TEMPLATE = app
+SOURCES += main.cpp \
+ widget.cpp \
+ evemodel.cpp \
+ eveaccount.cpp \
+ eveskilltraining.cpp \
+ evesettingsdialog.cpp \
+ mainwindow.cpp \
+ skilltree.cpp
+HEADERS += widget.h \
+ evemodel.h \
+ eveaccount.h \
+ eveskilltraining.h \
+ evesettingsdialog.h \
+ mainwindow.h \
+ skilltree.h
+FORMS += evesettingsdialog.ui \
+ mainwindow.ui
+
+CONFIG += mobility
+MOBILITY += bearer
+
+include(../qmaemo5homescreenadaptor/qmaemo5homescreenadaptor.pri)
+
+unix {
+ #VARIABLES
+ isEmpty(PREFIX) {
+ PREFIX = /usr/local
+ }
+BINDIR = $$PREFIX/bin
+DATADIR =$$PREFIX/share
+
+DEFINES += DATADIR=\\\"$$DATADIR\\\" PKGDATADIR=\\\"$$PKGDATADIR\\\"
+
+#MAKE INSTALL
+
+INSTALLS += target desktop iconxpm icon26 icon48 icon64
+
+ target.path =$$PREFIX/lib/hildon-desktop
+
+ desktop.path = $$DATADIR/applications/hildon-home
+ desktop.files += $${TARGET}.desktop
+
+ iconxpm.path = $$DATADIR/pixmap
+ iconxpm.files += ../data/maemo/$${TARGET}.xpm
+
+ icon26.path = $$DATADIR/icons/hicolor/26x26/apps
+ icon26.files += ../data/26x26/$${TARGET}.png
+
+ icon48.path = $$DATADIR/icons/hicolor/48x48/apps
+ icon48.files += ../data/48x48/$${TARGET}.png
+
+ icon64.path = $$DATADIR/icons/hicolor/64x64/apps
+ icon64.files += ../data/64x64/$${TARGET}.png
+}
+
--- /dev/null
+#include "evemodel.h"
+#include "eveaccount.h"
+#include <QNetworkAccessManager>
+#include <QXmlStreamReader>
+#include <QUrl>
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QtDebug>
+static QUrl imageUrl("http://img.eve.is/serv.asp");
+
+EveModel::EveModel(QObject *parent) :
+ QObject(parent),
+ m_userId(0)
+{
+}
+
+void EveModel::fetchAccounts()
+{
+ QNetworkRequest fetch(QUrl(QString("http://api.eveonline.com/account/Characters.xml.aspx?apiKey=%1&userID=%2")
+ .arg(apiKey())
+ .arg(userId())));
+ m_reply = mgr.get(fetch);
+ qDebug() << "Fetch accounts, reply " << m_reply;
+ connect(m_reply,SIGNAL(finished()),this,SLOT(replyReady()));
+ connect(m_reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(networkError(QNetworkReply::NetworkError)));
+}
+
+void EveModel::replyReady()
+{
+ if (m_reply->error()) {
+ qDebug() << "Failed! " << m_reply->errorString();
+ return;
+ }
+ QByteArray reply = m_reply->readAll();
+ qDebug() << "Reply ready";
+ qDebug() << reply;
+ QXmlStreamReader reader(reply);
+
+ reader.readNextStartElement();
+ if (reader.error()) {
+ qDebug() << "Parse error: " << reader.errorString();
+ }
+ qDebug() << "Relement: " << reader.name();
+ if (reader.name() != "eveapi")
+ return;
+ reader.readNextStartElement();
+ if (reader.error()) {
+ qDebug() << "Parse error: " << reader.errorString();
+ }
+ qDebug() << "1 element: " << reader.name();
+ if (reader.name() != "currentTime")
+ return;
+ reader.readNextStartElement();
+ reader.readNextStartElement();
+ if (reader.error()) {
+ qDebug() << "Parse error: " << reader.errorString();
+ }
+ qDebug() << "2 element: " << reader.name();
+ if (reader.name() != "result")
+ return;
+ reader.readNextStartElement();
+ qDebug() << "Relement: " << reader.name();
+ if (reader.name() != "rowset")
+ return;
+ reader.readNextStartElement();
+ qDebug() << "3 element: " << reader.name();
+ if (reader.name() == "row")
+ m_characters.clear();
+ while (reader.name() == "row") {
+ EveCharacter chara;
+ if (!chara.fromXml(reader)) {
+ qDebug() << "Error parsing character data";
+ break;
+ }
+ m_characters.append(chara);
+ reader.readNextStartElement(); // end current row
+ reader.readNextStartElement(); // start next row
+ }
+ m_reply->deleteLater();
+ emit accountsReady();
+}
+
+void EveModel::networkError(QNetworkReply::NetworkError error)
+{
+ qDebug() << "Network error " << error;
+}
+
--- /dev/null
+#ifndef EVEMODEL_H
+#define EVEMODEL_H
+
+#include "eveaccount.h"
+#include <QObject>
+#include <QString>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+class EveModel : public QObject
+{
+ Q_OBJECT
+public:
+ explicit EveModel(QObject *parent = 0);
+ void setApiKey(QString aKey) { m_apiKey = aKey; }
+ QString apiKey() const { return m_apiKey; }
+
+ void setUserId(int aId) { m_userId = aId; }
+ int userId() const { return m_userId; }
+ QList<EveCharacter> &characters() { return m_characters; }
+signals:
+ void accountsReady();
+
+public slots:
+ void fetchAccounts();
+private slots:
+ void replyReady();
+ void networkError(QNetworkReply::NetworkError);
+private:
+ QString m_apiKey;
+ int m_userId;
+ QNetworkAccessManager mgr;
+ QNetworkReply *m_reply;
+ QList<EveCharacter> m_characters;
+};
+
+#endif // EVEMODEL_H
--- /dev/null
+#include "evesettingsdialog.h"
+#include "ui_evesettingsdialog.h"
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QtDebug>
+#include <QtMaemo5>
+#include <QtGui>
+#include <QSettings>
+
+EveSettingsDialog::EveSettingsDialog(QWidget *parent) :
+ QDialog(parent),
+ m_reply(0),
+ m_selection(0),
+ userIdEdit(new QLineEdit(this)),
+ apiKeyEdit(new QLineEdit(this)),
+ characterPicker(new QMaemo5ValueButton(this)),
+ characterSelector(new QMaemo5ListPickSelector),
+ characterModel(new QStandardItemModel(0,1,this)),
+ m_layout(new QVBoxLayout(this))
+{
+ setWindowTitle("EVE account");
+ //QHBoxLayout *hbox = new QHBoxLayout(this);
+ //QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel,Qt::Vertical,this);
+ //hbox->addLayout(m_layout);
+ //hbox->addWidget(buttons);
+ setLayout(m_layout);
+ QLabel *label1 = new QLabel("User ID");
+ m_layout->addWidget(label1);
+ m_layout->addWidget(userIdEdit);
+ QLabel *label2 = new QLabel("API key");
+ m_layout->addWidget(label2);
+ m_layout->addWidget(apiKeyEdit);
+ m_layout->addWidget(characterPicker);
+ characterSelector->setModel(characterModel);
+ characterSelector->setModelColumn(0);
+ characterPicker->setValueLayout(QMaemo5ValueButton::ValueBesideText);
+ characterPicker->setText("Character");
+
+ QPushButton *button = new QPushButton("Done");
+ m_layout->addWidget(button);
+ characterPicker->setPickSelector(characterSelector);
+
+ connect(button,SIGNAL(pressed()),this,SLOT(accept()));
+ //connect(buttons,SIGNAL(rejected()),this,SLOT(reject()));
+ //connect(ui->getCharactersButton,SIGNAL(pressed()),this,SLOT(tryLoadCharacters()));
+ //connect(ui->characterCombo,SIGNAL(currentIndexChanged(int)),this,SLOT(characterSelected(int)));
+ //connect(apiKeyEdit,SIGNAL(editingFinished()),this,SLOT(tryLoadCharacters()));
+ //connect(userIdEdit,SIGNAL(editingFinished()),this,SLOT(tryLoadCharacters()));
+ //connect(characterSelector->view(),SIGNAL(activated(const QModelIndex &)),this,SLOT(characterSelected()));
+ connect(characterPicker,SIGNAL(pressed()),this,SLOT(tryLoadCharacters()));
+ connect(characterSelector,SIGNAL(selected(const QString &)),characterPicker,SLOT(setValuetext(const QString &)));
+}
+
+void EveSettingsDialog::changeEvent(QEvent *e)
+{
+ QDialog::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ //retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+void EveSettingsDialog::tryLoadCharacters()
+{
+ if (!apiKeyEdit->text().isEmpty() &&
+ !userIdEdit->text().isEmpty()) {
+ qDebug() << "Load characters, API key " << apiKeyEdit->text() << " user ID: " << userIdEdit->text();
+ characterModel->clear();
+ QStandardItem *item = new QStandardItem("Retrieving characters, please wait...");
+
+ characterModel->appendRow(item);
+ if (m_model.isNull()) {
+ m_model = QSharedPointer<EveModel>(new EveModel);
+ }
+ m_model->setApiKey(apiKeyEdit->text());
+ m_model->setUserId(userIdEdit->text().toInt());
+ connect(m_model.data(),SIGNAL(accountsReady()),this,SLOT(charactersLoaded()));
+ m_model->fetchAccounts();
+ setAttribute(Qt::WA_Maemo5ShowProgressIndicator, true);
+ }
+}
+
+// Setting the model also sets the
+// API key and user info since
+// Widget is responsible for loading and saving
+
+void EveSettingsDialog::setModel(QSharedPointer<EveModel> &model)
+{
+ m_model = model;
+ apiKeyEdit->setText(model->apiKey());
+ userIdEdit->setText(QString::number(model->userId()));
+ charactersLoaded();
+}
+
+void EveSettingsDialog::charactersLoaded()
+{
+ setAttribute(Qt::WA_Maemo5ShowProgressIndicator, false);
+ EveCharacter c;
+ qDebug() << "Characters loaded";
+ characterModel->clear();
+ foreach (c,m_model->characters()) {
+ qDebug() << "Found " << c.name;
+ QStandardItem *item = new QStandardItem(c.name);
+ item->setTextAlignment(Qt::AlignCenter);
+ item->setEditable(false);
+ characterModel->appendRow(item);
+ }
+}
+
+EveCharacter *EveSettingsDialog::selectedCharacter() {
+ int idx = characterSelector->currentIndex();
+ qDebug() << "Selected index is " << idx;
+ if ( idx >=0 && idx < m_model->characters().size() ) {
+ qDebug() << "Selecting " << m_model->characters().at(idx).name;
+ return &(m_model->characters()[idx]);
+ }
+ return NULL;
+}
+
+void EveSettingsDialog::characterSelected()
+{
+
+}
--- /dev/null
+#ifndef EVESETTINGSDIALOG_H
+#define EVESETTINGSDIALOG_H
+
+#include <QDialog>
+#include "evemodel.h"
+#include <QtMaemo5>
+#include <QtGui>
+#include <QSharedPointer>
+
+class QNetworkReply;
+class EveCharacter;
+namespace Ui {
+ class EveSettingsDialog;
+}
+
+class EveSettingsDialog : public QDialog {
+ Q_OBJECT
+public:
+ EveSettingsDialog(QWidget *parent = 0);
+
+ EveCharacter *selectedCharacter();
+ QSharedPointer<EveModel> model() { return m_model; }
+ void setModel(QSharedPointer<EveModel> &model);
+protected:
+ void changeEvent(QEvent *e);
+public slots:
+ void tryLoadCharacters();
+ void charactersLoaded();
+ void characterSelected();
+private:
+ QSharedPointer<EveModel> m_model;
+ QNetworkReply *m_reply;
+ EveCharacter *m_selection;
+ QLineEdit *userIdEdit;
+ QLineEdit *apiKeyEdit;
+ QMaemo5ValueButton *characterPicker;
+ QMaemo5ListPickSelector *characterSelector;
+ QStandardItemModel *characterModel;
+ QVBoxLayout *m_layout;
+
+};
+
+#endif // EVESETTINGSDIALOG_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>EveSettingsDialog</class>
+ <widget class="QDialog" name="EveSettingsDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>800</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>EVE settings</string>
+ </property>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="geometry">
+ <rect>
+ <x>710</x>
+ <y>20</y>
+ <width>81</width>
+ <height>241</height>
+ </rect>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_4">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>10</y>
+ <width>171</width>
+ <height>34</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'DejaVu Sans'; font-size:8pt; font-weight:400; font-style:normal;">
+<table style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;">
+<tr>
+<td style="border: none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">To see character info visit<br /><a href="http://www.eveonline.com/api/"><span style=" text-decoration: underline; color:#0057ae;">EVE Online account page</span></a></p></td></tr></table></body></html></string>
+ </property>
+ <property name="openExternalLinks">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QScrollArea" name="scrollArea">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>50</y>
+ <width>701</width>
+ <height>241</height>
+ </rect>
+ </property>
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>695</width>
+ <height>235</height>
+ </rect>
+ </property>
+ <widget class="QLineEdit" name="apiKeyEdit">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>671</width>
+ <height>61</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>24</pointsize>
+ </font>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>0</y>
+ <width>39</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>API key</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_2">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>70</y>
+ <width>34</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>UserID</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" name="userIdEdit">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>90</y>
+ <width>661</width>
+ <height>61</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="font">
+ <font>
+ <pointsize>24</pointsize>
+ </font>
+ </property>
+ </widget>
+ <widget class="QComboBox" name="characterCombo">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>170</y>
+ <width>70</width>
+ <height>24</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QLabel" name="label_3">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>153</y>
+ <width>87</width>
+ <height>16</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Choose character</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" name="getCharactersButton">
+ <property name="geometry">
+ <rect>
+ <x>540</x>
+ <y>180</y>
+ <width>121</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Fetch characters</string>
+ </property>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>EveSettingsDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>EveSettingsDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
--- /dev/null
+#include "eveskilltraining.h"
+#include "evemodel.h"
+#include "eveaccount.h"
+
+#include <QXmlStreamReader>
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QtDebug>
+EveSkillTraining::EveSkillTraining(QObject *parent) :
+ QObject(parent),
+ training(false),
+ typeId(0),
+ startSkillpoints(0),
+ destSkillpoints(0),
+ level(0),
+ m_character(NULL),
+ m_account(NULL),
+ m_reply(NULL)
+{
+}
+
+bool EveSkillTraining::fromXml(QXmlStreamReader &xml)
+{
+ if (xml.name() != "result") {
+ qDebug() << "Wrong element:" << xml.name();
+ return false;
+ }
+ qDebug() << "passed, element is result";
+ bool inResult = true;
+ while (inResult) {
+ inResult = xml.readNextStartElement();
+ qDebug() << "element:" << xml.name();
+ if (xml.name() == "trainingEndTime") {
+ qDebug() << "Parse end time";
+ endTime = QDateTime::fromString(xml.readElementText(),"yyyy-MM-dd hh:mm:ss");//2008-08-17 06:43:00
+ qDebug()<< endTime;
+
+ } else if (xml.name() == "trainingStartTime") {
+ qDebug() << "Parse start time";
+ startTime = QDateTime::fromString(xml.readElementText(),"yyyy-MM-dd hh:mm:ss");//2008-08-17 06:43:00
+ qDebug() << startTime;
+
+ } else if (xml.name() == "trainingTypeID") {
+ typeId = xml.readElementText().toInt();
+
+ } else if (xml.name() == "trainingStartSP"){
+ startSkillpoints = xml.readElementText().toInt();
+
+ } else if (xml.name() == "trainingDestinationSP"){
+ destSkillpoints = xml.readElementText().toInt();
+
+ } else if (xml.name() == "trainingToLevel"){
+ level = xml.readElementText().toInt();
+ } else
+ // Noop
+ xml.skipCurrentElement();
+
+ } // while
+ qDebug() << "Parsing finished";
+ return true;
+}
+
+void EveSkillTraining::fetchInfo()
+{
+ if (m_character == NULL || m_account == NULL)
+ return;
+ QNetworkRequest req(QUrl(QString("http://api.eveonline.com/char/SkillInTraining.xml.aspx?apiKey=%1&userID=%2&characterID=%3")
+ .arg(m_account->apiKey())
+ .arg(m_account->userId())
+ .arg(m_character->characterId)));
+ m_reply = m_mgr.get(req);
+ connect(m_reply,SIGNAL(finished()),this,SLOT(infoReady()));
+}
+
+void EveSkillTraining::infoReady()
+{
+ if (m_reply->error()) {
+ qDebug() << "Failed! " << m_reply->errorString();
+ return;
+ }
+ qDebug() << "Skill reply";
+ QByteArray reply = m_reply->readAll();
+ qDebug() << "Reply ready";
+ qDebug() << reply;
+ QXmlStreamReader reader(reply);
+
+ reader.readNextStartElement();
+ if (reader.name() != "eveapi")
+ return;
+ reader.readNextStartElement();
+ if (reader.name() != "currentTime")
+ return;
+ reader.readNextStartElement(); // end currentTime element
+ reader.readNextStartElement(); // start result element
+ fromXml(reader);
+ emit finished();
+}
--- /dev/null
+#ifndef EVESKILLTRAINING_H
+#define EVESKILLTRAINING_H
+
+#include <QObject>
+#include <QDateTime>
+#include <QString>
+#include <QXmlStreamReader>
+#include <QNetworkAccessManager>
+
+class EveCharacter;
+class EveModel;
+
+class EveSkillTraining : public QObject
+{
+ Q_OBJECT
+public:
+ explicit EveSkillTraining(QObject *parent = 0);
+ bool fromXml(QXmlStreamReader &xml);
+ void setCharacter(EveCharacter *character) { m_character = character; }
+ void setAccount(EveModel *aModel) { m_account = aModel; }
+signals:
+ void finished();
+
+public slots:
+ void fetchInfo();
+ void infoReady();
+
+public:
+ bool training;
+ QDateTime startTime;
+ QDateTime endTime;
+ int typeId;
+ int startSkillpoints;
+ int destSkillpoints;
+ int level;
+private:
+ EveCharacter *m_character;
+ EveModel *m_account;
+ QNetworkAccessManager m_mgr;
+ QNetworkReply *m_reply;
+};
+
+#endif // EVESKILLTRAINING_H
--- /dev/null
+#include <QtGui/QApplication>
+#include "widget.h"
+#include "qmaemo5homescreenadaptor.h"
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication::setGraphicsSystem("native");
+ QApplication a(argc, argv);
+ //MainWindow w;
+ Widget w;
+ QMaemo5HomescreenAdaptor *adaptor = new QMaemo5HomescreenAdaptor(&w);
+ adaptor->setSettingsAvailable(true);
+ QObject::connect(adaptor,SIGNAL(settingsRequested()),&w,SLOT(showSettingsDialog()));
+#if defined(Q_WS_S60)
+ w.showMaximized();
+#else
+ w.show();
+#endif
+ return a.exec();
+}
--- /dev/null
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include "evesettingsdialog.h"
+#include <QtDebug>
+MainWindow::MainWindow(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MainWindow),
+ m_settings(new EveSettingsDialog(this))
+{
+ ui->setupUi(this);
+ connect(ui->fetchButton,SIGNAL(pressed()),this,SLOT(settingsRequested()));
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+void MainWindow::changeEvent(QEvent *e)
+{
+ QMainWindow::changeEvent(e);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+}
+
+void MainWindow::settingsRequested()
+{
+ int result = m_settings->exec();
+ if (result == QDialog::Accepted) {
+ m_character = m_settings->selectedCharacter();
+
+ if (m_character != NULL ) {
+ qDebug() << "Selected character:" << m_character->name;
+ connect(m_character,SIGNAL(imageLoaded()),this,SLOT(setLabelImage()));
+ m_character->fetchImage();
+
+ skill.setCharacter(m_character);
+ skill.setAccount(m_settings->model().data());
+ connect(&skill, SIGNAL(finished()),this,SLOT(setSkillTraining()));
+ skill.fetchInfo();
+ }
+ }
+}
+
+void MainWindow::setLabelImage()
+{
+ ui->iconLabel->setPixmap(*(m_character->characterIcon));
+}
+
+void MainWindow::setSkillTraining()
+{
+ ui->trainingLabel->setText(QString("Skill ready at %1").arg(skill.endTime.toString(Qt::SystemLocaleShortDate)));
+}
+
--- /dev/null
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include "evesettingsdialog.h"
+#include "eveaccount.h"
+
+namespace Ui {
+ class MainWindow;
+}
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+public slots:
+ void settingsRequested();
+ void setLabelImage();
+ void setSkillTraining();
+protected:
+ void changeEvent(QEvent *e);
+
+private:
+ Ui::MainWindow *ui;
+ EveSettingsDialog *m_settings;
+ EveCharacter *m_character;
+ EveSkillTraining skill;
+};
+
+#endif // MAINWINDOW_H
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>394</width>
+ <height>236</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <widget class="QPushButton" name="fetchButton">
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>150</y>
+ <width>90</width>
+ <height>22</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Fetch!</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="iconLabel">
+ <property name="geometry">
+ <rect>
+ <x>80</x>
+ <y>60</y>
+ <width>70</width>
+ <height>70</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>TextLabel</string>
+ </property>
+ </widget>
+ <widget class="QLabel" name="trainingLabel">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>150</y>
+ <width>221</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>394</width>
+ <height>20</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+#include "skilltree.h"
+#include <QFile>
+#include <QDataStream>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QNetworkRequest>
+#include <QtDebug>
+#include <QXmlStreamReader>
+#include <assert.h>
+
+SkillTree::SkillTree(QObject *parent) :
+ QObject(parent),
+ mgr(0),
+ reply(0)
+{
+ QFile cacheFile("/var/tmp/skillCache");
+ if (cacheFile.exists()) {
+ QDataStream input(&cacheFile);
+ input >> skillNames;
+ } else {
+ // load from network
+
+ }
+
+}
+
+void SkillTree::loadSkills()
+{
+ QFile cacheFile("/var/tmp/skillCache");
+ if (cacheFile.exists()) {
+ cacheFile.open(QIODevice::ReadOnly);
+ qDebug() << "Load from file";
+ QDataStream input(&cacheFile);
+ input >> skillNames;
+ emit skillsLoaded();
+ } else {
+ // load from network
+ qDebug() << "load skills from network";
+ mgr = new QNetworkAccessManager(this);
+ QNetworkRequest req(QUrl("http://api.eveonline.com//eve/SkillTree.xml.aspx"));
+ reply = mgr->get(req);
+ connect(reply,SIGNAL(finished()),this,SLOT(replyReady()));
+ }
+}
+
+void SkillTree::replyReady()
+{
+ qDebug() << "Reply ready";
+ if (!reply->error()) {
+ QByteArray replyContent = reply->readAll();
+ qDebug() << replyContent;
+ fromXml(replyContent);
+ emit skillsLoaded();
+ } else {
+ qDebug() << "fetch error:" << reply->errorString();
+ }
+}
+
+void SkillTree::fromXml(QByteArray &content)
+{
+ QXmlStreamReader xml(content);
+ xml.readNextStartElement(); //eveapi
+ //assert(xml.name() == "eveapi");
+ xml.readNextStartElement(); //currentTime
+ xml.skipCurrentElement();
+ //assert(xml.name() == "currentTime");
+ xml.readNextStartElement(); //result
+ xml.readNextStartElement(); // rowset for skill groups
+ bool groupsLeft = xml.readNextStartElement(); // row for skill group
+ while (groupsLeft) {
+ xml.readNextStartElement(); // rowset for skills
+ bool skillsLeft = xml.readNextStartElement(); // row for skill
+ while (skillsLeft) {
+ assert(xml.name() == "row");
+ QString name = xml.attributes().value("","typeName").toString();
+ int typeId = xml.attributes().value("","typeID").toString().toInt();
+ qDebug() << "Found skill " << name << ":" << typeId;
+ skillNames[typeId] = name;
+
+ xml.skipCurrentElement(); // description
+ skillsLeft = xml.readNextStartElement(); // next skill row
+ }
+ xml.readNextStartElement(); // rowset ends
+ groupsLeft = xml.readNextStartElement(); // next skill group row
+ }
+ int len = 0;
+ QString name;
+ QString longestName;
+ foreach (name,skillNames) {
+ if (name.length() > len) {
+ longestName = name;
+ len = name.length();
+ }
+ }
+
+ qDebug() << skillNames;
+ qDebug() << longestName;
+}
+
+void SkillTree::save()
+{
+ QFile cache("/var/tmp/skillCache");
+ cache.open(QIODevice::WriteOnly);
+ QDataStream output(&cache);
+ output << skillNames;
+ cache.flush();
+ cache.close();
+}
+
--- /dev/null
+#ifndef SKILLTREE_H
+#define SKILLTREE_H
+
+#include <QObject>
+#include <QHash>
+
+class QNetworkAccessManager;
+class QNetworkReply;
+
+class SkillTree : public QObject
+{
+ Q_OBJECT
+public:
+ explicit SkillTree(QObject *parent = 0);
+ QString skillName(const int code) const { return skillNames.value(code); }
+signals:
+ void skillsLoaded();
+public slots:
+ void loadSkills();
+ void replyReady();
+ void save();
+private:
+ void fromXml(QByteArray &content);
+ QHash<int,QString> skillNames;
+ QNetworkAccessManager *mgr;
+ QNetworkReply *reply;
+};
+
+#endif // SKILLTREE_H
--- /dev/null
+/********************************************************************************
+** Form generated from reading UI file 'evesettingsdialog.ui'
+**
+** Created: Fri May 7 20:57:37 2010
+** by: Qt User Interface Compiler version 4.6.2
+**
+** WARNING! All changes made in this file will be lost when recompiling UI file!
+********************************************************************************/
+
+#ifndef UI_EVESETTINGSDIALOG_H
+#define UI_EVESETTINGSDIALOG_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QComboBox>
+#include <QtGui/QDialog>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QLineEdit>
+#include <QtGui/QPushButton>
+#include <QtGui/QScrollArea>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_EveSettingsDialog
+{
+public:
+ QDialogButtonBox *buttonBox;
+ QLabel *label_4;
+ QScrollArea *scrollArea;
+ QWidget *scrollAreaWidgetContents;
+ QLineEdit *apiKeyEdit;
+ QLabel *label;
+ QLabel *label_2;
+ QLineEdit *userIdEdit;
+ QComboBox *characterCombo;
+ QLabel *label_3;
+ QPushButton *getCharactersButton;
+
+ void setupUi(QDialog *EveSettingsDialog)
+ {
+ if (EveSettingsDialog->objectName().isEmpty())
+ EveSettingsDialog->setObjectName(QString::fromUtf8("EveSettingsDialog"));
+ EveSettingsDialog->resize(800, 300);
+ buttonBox = new QDialogButtonBox(EveSettingsDialog);
+ buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
+ buttonBox->setGeometry(QRect(710, 20, 81, 241));
+ buttonBox->setOrientation(Qt::Vertical);
+ buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
+ label_4 = new QLabel(EveSettingsDialog);
+ label_4->setObjectName(QString::fromUtf8("label_4"));
+ label_4->setGeometry(QRect(20, 10, 171, 34));
+ label_4->setOpenExternalLinks(true);
+ scrollArea = new QScrollArea(EveSettingsDialog);
+ scrollArea->setObjectName(QString::fromUtf8("scrollArea"));
+ scrollArea->setGeometry(QRect(10, 50, 701, 241));
+ scrollArea->setWidgetResizable(true);
+ scrollAreaWidgetContents = new QWidget();
+ scrollAreaWidgetContents->setObjectName(QString::fromUtf8("scrollAreaWidgetContents"));
+ scrollAreaWidgetContents->setGeometry(QRect(0, 0, 695, 235));
+ apiKeyEdit = new QLineEdit(scrollAreaWidgetContents);
+ apiKeyEdit->setObjectName(QString::fromUtf8("apiKeyEdit"));
+ apiKeyEdit->setGeometry(QRect(10, 10, 671, 61));
+ QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ sizePolicy.setHorizontalStretch(0);
+ sizePolicy.setVerticalStretch(0);
+ sizePolicy.setHeightForWidth(apiKeyEdit->sizePolicy().hasHeightForWidth());
+ apiKeyEdit->setSizePolicy(sizePolicy);
+ QFont font;
+ font.setPointSize(24);
+ apiKeyEdit->setFont(font);
+ apiKeyEdit->setFrame(true);
+ label = new QLabel(scrollAreaWidgetContents);
+ label->setObjectName(QString::fromUtf8("label"));
+ label->setGeometry(QRect(20, 0, 39, 16));
+ label_2 = new QLabel(scrollAreaWidgetContents);
+ label_2->setObjectName(QString::fromUtf8("label_2"));
+ label_2->setGeometry(QRect(20, 70, 34, 16));
+ userIdEdit = new QLineEdit(scrollAreaWidgetContents);
+ userIdEdit->setObjectName(QString::fromUtf8("userIdEdit"));
+ userIdEdit->setGeometry(QRect(10, 90, 661, 61));
+ sizePolicy.setHeightForWidth(userIdEdit->sizePolicy().hasHeightForWidth());
+ userIdEdit->setSizePolicy(sizePolicy);
+ userIdEdit->setFont(font);
+ characterCombo = new QComboBox(scrollAreaWidgetContents);
+ characterCombo->setObjectName(QString::fromUtf8("characterCombo"));
+ characterCombo->setGeometry(QRect(20, 170, 70, 24));
+ label_3 = new QLabel(scrollAreaWidgetContents);
+ label_3->setObjectName(QString::fromUtf8("label_3"));
+ label_3->setGeometry(QRect(20, 153, 87, 16));
+ getCharactersButton = new QPushButton(scrollAreaWidgetContents);
+ getCharactersButton->setObjectName(QString::fromUtf8("getCharactersButton"));
+ getCharactersButton->setGeometry(QRect(540, 180, 121, 22));
+ scrollArea->setWidget(scrollAreaWidgetContents);
+
+ retranslateUi(EveSettingsDialog);
+ QObject::connect(buttonBox, SIGNAL(accepted()), EveSettingsDialog, SLOT(accept()));
+ QObject::connect(buttonBox, SIGNAL(rejected()), EveSettingsDialog, SLOT(reject()));
+
+ QMetaObject::connectSlotsByName(EveSettingsDialog);
+ } // setupUi
+
+ void retranslateUi(QDialog *EveSettingsDialog)
+ {
+ EveSettingsDialog->setWindowTitle(QApplication::translate("EveSettingsDialog", "EVE settings", 0, QApplication::UnicodeUTF8));
+ label_4->setText(QApplication::translate("EveSettingsDialog", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
+"p, li { white-space: pre-wrap; }\n"
+"</style></head><body style=\" font-family:'DejaVu Sans'; font-size:8pt; font-weight:400; font-style:normal;\">\n"
+"<table style=\"-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;\">\n"
+"<tr>\n"
+"<td style=\"border: none;\">\n"
+"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">To see character info visit<br /><a href=\"http://www.eveonline.com/api/\"><span style=\" text-decoration: underline; color:#0057ae;\">EVE Online account page</span></a></p></td></tr></table></body></html>", 0, QApplication::UnicodeUTF8));
+ label->setText(QApplication::translate("EveSettingsDialog", "API key", 0, QApplication::UnicodeUTF8));
+ label_2->setText(QApplication::translate("EveSettingsDialog", "UserID", 0, QApplication::UnicodeUTF8));
+ label_3->setText(QApplication::translate("EveSettingsDialog", "Choose character", 0, QApplication::UnicodeUTF8));
+ getCharactersButton->setText(QApplication::translate("EveSettingsDialog", "Fetch characters", 0, QApplication::UnicodeUTF8));
+ } // retranslateUi
+
+};
+
+namespace Ui {
+ class EveSettingsDialog: public Ui_EveSettingsDialog {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_EVESETTINGSDIALOG_H
--- /dev/null
+/********************************************************************************
+** Form generated from reading UI file 'mainwindow.ui'
+**
+** Created: Fri May 7 20:57:37 2010
+** by: Qt User Interface Compiler version 4.6.2
+**
+** WARNING! All changes made in this file will be lost when recompiling UI file!
+********************************************************************************/
+
+#ifndef UI_MAINWINDOW_H
+#define UI_MAINWINDOW_H
+
+#include <QtCore/QVariant>
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QButtonGroup>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLabel>
+#include <QtGui/QMainWindow>
+#include <QtGui/QMenuBar>
+#include <QtGui/QPushButton>
+#include <QtGui/QStatusBar>
+#include <QtGui/QWidget>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_MainWindow
+{
+public:
+ QWidget *centralwidget;
+ QPushButton *fetchButton;
+ QLabel *iconLabel;
+ QLabel *trainingLabel;
+ QMenuBar *menubar;
+ QStatusBar *statusbar;
+
+ void setupUi(QMainWindow *MainWindow)
+ {
+ if (MainWindow->objectName().isEmpty())
+ MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
+ MainWindow->resize(394, 236);
+ centralwidget = new QWidget(MainWindow);
+ centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
+ fetchButton = new QPushButton(centralwidget);
+ fetchButton->setObjectName(QString::fromUtf8("fetchButton"));
+ fetchButton->setGeometry(QRect(280, 150, 90, 22));
+ iconLabel = new QLabel(centralwidget);
+ iconLabel->setObjectName(QString::fromUtf8("iconLabel"));
+ iconLabel->setGeometry(QRect(80, 60, 70, 70));
+ trainingLabel = new QLabel(centralwidget);
+ trainingLabel->setObjectName(QString::fromUtf8("trainingLabel"));
+ trainingLabel->setGeometry(QRect(10, 150, 221, 20));
+ trainingLabel->setAlignment(Qt::AlignCenter);
+ MainWindow->setCentralWidget(centralwidget);
+ menubar = new QMenuBar(MainWindow);
+ menubar->setObjectName(QString::fromUtf8("menubar"));
+ menubar->setGeometry(QRect(0, 0, 394, 20));
+ MainWindow->setMenuBar(menubar);
+ statusbar = new QStatusBar(MainWindow);
+ statusbar->setObjectName(QString::fromUtf8("statusbar"));
+ MainWindow->setStatusBar(statusbar);
+
+ retranslateUi(MainWindow);
+
+ QMetaObject::connectSlotsByName(MainWindow);
+ } // setupUi
+
+ void retranslateUi(QMainWindow *MainWindow)
+ {
+ MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0, QApplication::UnicodeUTF8));
+ fetchButton->setText(QApplication::translate("MainWindow", "Fetch!", 0, QApplication::UnicodeUTF8));
+ iconLabel->setText(QApplication::translate("MainWindow", "TextLabel", 0, QApplication::UnicodeUTF8));
+ trainingLabel->setText(QString());
+ } // retranslateUi
+
+};
+
+namespace Ui {
+ class MainWindow: public Ui_MainWindow {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_MAINWINDOW_H
--- /dev/null
+#include "widget.h"
+#include <QPainter>
+#include "eveaccount.h"
+#include "evesettingsdialog.h"
+#include "eveskilltraining.h"
+#include "skilltree.h"
+#include <QtDebug>
+#include <QNetworkConfigurationManager>
+
+QTM_USE_NAMESPACE
+
+Widget::Widget(QWidget *parent)
+ : QLabel(parent),
+ m_character(NULL),
+ m_settings(new EveSettingsDialog(this)),
+ m_training(NULL),
+ m_net(new QNetworkConfigurationManager(this)),
+ m_skills(new SkillTree(this)),
+ m_model(NULL)
+{
+ setAlignment(Qt::AlignCenter);
+ setAttribute(Qt::WA_TranslucentBackground);
+ setGeometry(0,0,150,180);
+ connect(m_net,SIGNAL(onlineStateChanged(bool)),this,SLOT(onlineStateChanged(bool)));
+ m_skills->loadSkills();
+}
+
+Widget::~Widget()
+{
+ delete m_character;
+}
+
+
+QSize Widget::sizeHint() const
+{
+ return 2 * QLabel::sizeHint();
+}
+
+void Widget::paintEvent(QPaintEvent *event)
+{
+ QPainter p(this);
+ p.setBrush(QColor(0, 0, 0, 128));
+ p.setPen(Qt::NoPen);
+ p.drawRoundedRect(rect(), 25, 25);
+ p.setPen(Qt::white);
+ QFont dFont(p.font());
+ dFont.setPixelSize(15);
+ p.setFont(dFont);
+ if (m_character != NULL) {
+ QPoint iconLoc((150-64)/2,(150-64)/2);
+ if (m_character->characterIcon) {
+ p.drawPixmap(iconLoc,*(m_character->characterIcon));
+ }
+ QRect nameLoc(0,10,150,20);
+ p.drawText(nameLoc,Qt::AlignCenter,m_character->name);
+ if (m_training) {
+ QRect skillTitle(0,110,150,50);
+ p.drawText(skillTitle,Qt::AlignCenter|Qt::TextWordWrap,
+ QString("%1 %2").arg(m_skills->skillName(m_training->typeId))
+ .arg(m_training->level));
+ QRect skillLoc(0,155,150,20);
+ p.drawText(skillLoc,Qt::AlignCenter,m_training->endTime.toString(Qt::SystemLocaleShortDate));
+ }
+
+ }
+ p.end();
+
+ QLabel::paintEvent(event);
+}
+
+void Widget::showSettingsDialog()
+{
+
+ int result = m_settings->exec();
+ if (result == QDialog::Accepted) {
+ m_character = m_settings->selectedCharacter();
+ m_model = m_settings->model();
+ qDebug() << "Got character " << m_character->name;
+ connect(m_character,SIGNAL(imageLoaded()),this,SLOT(skillReady()));
+ m_character->fetchImage();
+ qDebug() << "Fetch skills";
+ m_training = new EveSkillTraining(this);
+ m_training->setAccount(m_settings->model().data());
+ m_training->setCharacter(m_character);
+ connect(m_training,SIGNAL(finished()),this,SLOT(update()));
+
+ }
+}
+
+void Widget::skillReady()
+{
+ update();
+ m_training->fetchInfo();
+}
+
+void Widget::onlineStateChanged(bool online)
+{
+ qDebug() << "Online status changed, reloading info";
+ if (online) {
+ m_training->fetchInfo();
+ }
+}
+
+// TODO
+void Widget::loadSettings()
+{
+
+}
+
+// TODO
+void Widget::saveSettings()
+{
+
+}
--- /dev/null
+#ifndef WIDGET_H
+#define WIDGET_H
+
+#include <QtGui/QLabel>
+#include <QNetworkConfigurationManager>
+#include <QSharedPointer>
+
+QTM_USE_NAMESPACE
+
+class EveCharacter;
+class EveSettingsDialog;
+class EveSkillTraining;
+class SkillTree;
+class EveModel;
+
+class Widget : public QLabel
+{
+ Q_OBJECT
+
+public:
+ Widget(QWidget *parent = 0);
+ ~Widget();
+ QSize sizeHint() const;
+ void setCharacter(EveCharacter *aChar) { m_character = aChar; }
+ EveCharacter *character() { return m_character; }
+public slots:
+ void showSettingsDialog();
+ void paintEvent(QPaintEvent *event);
+ void skillReady();
+ void onlineStateChanged(bool online);
+ void loadSettings();
+ void saveSettings();
+
+private:
+ EveCharacter *m_character;
+ EveSettingsDialog *m_settings;
+ EveSkillTraining *m_training;
+ QNetworkConfigurationManager *m_net;
+ SkillTree *m_skills;
+ QSharedPointer<EveModel> m_model;
+};
+
+#endif // WIDGET_H
--- /dev/null
+#include <QtCore/QCoreApplication>
+#include <QtTest/QtTest>
+#include <eveaccount.h>
+#include <evemodel.h>
+#include <eveskilltraining.h>
+#include "skilltree.h"
+#include <QFile>
+class EveModelTest: public QObject
+{
+ Q_OBJECT
+private slots:
+ void testXml();
+ void testSkills();
+ void testSkillTree();
+};
+
+#define GONTH_ID 1525655037
+
+void EveModelTest::testXml()
+{
+ EveModel model;
+ model.setApiKey("2A671E53172C4F8A878BB770BBABFBD3CFF31815927F4E5591EA6D5576456E50");
+ model.setUserId(4079475);
+ model.fetchAccounts();
+ QSignalSpy spy(&model,SIGNAL(accountsReady()));
+ QTest::qWait(1000);
+ QCOMPARE(spy.length(),1);
+ QCOMPARE(model.characters().length(),2);
+ EveCharacter e;
+ foreach (e,model.characters()) {
+ qDebug() << e.name << ":" << e.characterId;
+ }
+ e = model.characters()[0];
+ qDebug() << "e assigned";
+ QSignalSpy imagespy(&e,SIGNAL(imageLoaded()));
+ qDebug() << "spy installed";
+ e.fetchImage();
+ qDebug() << "fetchImage called";
+ QTest::qWait(3000);
+ qDebug() << "waited";
+ qDebug() << e.characterIcon;
+ QVERIFY(imagespy.length() == 1);
+ qDebug() << "Test done";
+}
+
+void EveModelTest::testSkills()
+{
+ EveModel model;
+ model.setApiKey("2A671E53172C4F8A878BB770BBABFBD3CFF31815927F4E5591EA6D5576456E50");
+ model.setUserId(4079475);
+ model.fetchAccounts();
+ QTest::qWait(1000);
+ EveCharacter e = model.characters()[0];
+ EveSkillTraining skill;
+ skill.setCharacter(&e);
+ skill.setAccount(&model);
+ skill.fetchInfo();
+ QTest::qWait(1000);
+ qDebug() << skill.startTime
+ << skill.endTime
+ << skill.typeId
+ << skill.startSkillpoints
+ << skill.destSkillpoints
+ << skill.level;
+}
+
+void EveModelTest::testSkillTree()
+{
+ SkillTree stree;
+ QSignalSpy spy(&stree,SIGNAL(skillsLoaded()));
+ stree.loadSkills();
+ QTest::qWait(5000);
+ QCOMPARE(spy.count(),1);
+ QCOMPARE(stree.skillName(3442),QString("Drone Interfacing"));
+ stree.save();
+ QVERIFY(QFile::exists("/var/tmp/skillCache"));
+ QFile::remove("/var/tmp/skillCache");
+}
+
+QTEST_MAIN(EveModelTest)
+
+#include "main.moc"
--- /dev/null
+#-------------------------------------------------
+#
+# Project created by QtCreator 2010-05-02T08:36:06
+#
+#-------------------------------------------------
+
+QT += core network
+
+TARGET = tests
+CONFIG += console qtestlib
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+INCLUDEPATH += ../src
+
+SOURCES += main.cpp
+SOURCES += ../src/eveaccount.cpp \
+../src/evemodel.cpp \
+../src/eveskilltraining.cpp \
+../src/skilltree.cpp
+
+HEADERS += ../src/eveaccount.h \
+ ../src/evemodel.h \
+ ../src/eveskilltraining.h \
+../src/skilltree.h