pax_global_header00006660000000000000000000000064121524106640014513gustar00rootroot0000000000000052 comment=f50c5b189a44c5c4faecea4b03a2277d4b611ba0 libqxt-0.6.2/000077500000000000000000000000001215241066400130235ustar00rootroot00000000000000libqxt-0.6.2/.hgignore000066400000000000000000000006501215241066400146270ustar00rootroot00000000000000syntax: glob *.pro.user *.app *.moc Makefile* debug/ release/ deploy/libs/ qtc-gdbmacros/ *.rej *.orig *.obj *.swp *.dll *.exp *.ilk *.pdb *.lib moc_*.cpp qrc_*.cpp qxt.prf modules.prf .obj\* *.o *.so.* *.so *.pdb ui_*.h tools/doqsy/doqsy doqsy.exe qrc_resources.cpp config.log config.pri* config.tests/* depends.pri* *~ lib/ tools/3rdparty/qdoc3/qdoc3 .qmake.cache qxtvars.prf glob:*.vcproj glob:*.exe glob:*.vcproj.*.user libqxt-0.6.2/AUTHORS000066400000000000000000000004231215241066400140720ustar00rootroot00000000000000Arvid Picciani Adam Higerd J-P Nurmi Benjamin Zeller Thomas Mueller thanks for all the minor contributions, bug reports, beta tests, and the free beer :-) libqxt-0.6.2/CHANGES000066400000000000000000000173401215241066400140230ustar00rootroot00000000000000LibQxt 0.6.2 contains improvements and bug fixes to the 0.6.x series. For more details, see the documentation included in this package or online at http://docs.libqxt.org. 0.6.2 ----- * QxtWindowSystem: - X11 implementation cleanup/overhaul - Fixed #85 QxtWindowSystem::windowGeometry issue * QxtSpanSlider: Improved span drawing on Mac * QxtGlobalShortcut: - Fixed #51 QxtGlobalShortcut doesn't send signal - Fixed #131 QxtGlobalShortcutKey unregistered other's shortcut key by mistake * QxtZeroconf: Fixed a bug in the custom AvahiPoll introduced by a timestamp wrap-around that accured just last week. * QxtCrumbView: - Don't render delegate for invalid indexes - Remove unnecessary padding * QxtDataStreamSignalSerializer: - Handle incomplete length - Added cast to eliminate a compiler warning * QxtMailMessage: - Fix some encoding issues, support explicit transfer encodings - Handle lines with only one word * QxtJSON: - Add support for long long ints - Handle control characters in QxtJSON::stringify - Fix \u decoding - Fixed a error in json parsing code. Nested arrays were incorrectly combined into one big array. * Build system - Various enhancements - Fixed #130 DEPENTPATH = DEPENDPATH? * QxtLogger: Fixed the incorrect association of log level string names to their enumerations * QxtAbstractHttpConnector: remove request disconnected on (QHash)"requests" * QxtWebContent: Fix comparison on size * QxtLanguageBox: - Fixed #124 QxtLanguageBox logic maybe bug - Fixed #125 QxtLanguageBox improvment in logic 0.6.1 ----- - Improvements * Revised configure.bat: - added -make-bin option - removed -msvc from help - added build_all config for -debug_and_release - cleaned up possible mkdir/move output * Added -I, -i and -L options to configure * Revised QxtConfig.cmake, based on a proposal from zeke (thanks!) * QxtGlobalShortcut/Mac: removed the extra route via QApplication::macEventFilter() - use qxt_mac_handle_hot_key() directly * tests/other/app: changed the shortcut to "ctrl+alt+s" (ie. "cmd+alt+s" on mac) * examples/jsonrpcclient: added CONFIG+=console to make windows users happy * Configure: added -nomake docs * Configure: added -no-openssl to -help * Added MediaKeys to qxtglobalshortcut_win * Added mod4 support in qxtglobalshortcut_x11 * Added QXT_RPCSERVICE_DEBUG environment variable for convenient network debugging * Improved QxtSlotMapper docs * Fixed qmake deprecation warnings - Bug fixes * #48 Won't build using Qt 4.4.3 b/c of QVariant::Hash * #6 QxtFileLockTest::rw_same() does not pass on Windows * Fixed QxtFileLock docs * Fixed examples/jsonrpcclient: exit properly with no arguments set * Fixed config.tests/db version check to respect MAJOR>4 * #69 Documentation errors * #46 Install on Mac * #62 QxtXMLFileLoggerEngine vs QxtXmlFileLoggerEngine * #60 including doens't work * #63 QxtCheckComboBox display not correct * Fixed qdoc3 tags in QxtZeroConf docs * QxtSerialDevice: fixed r/w in open, disable ionotifier on error * #77 QxtXmlRpcCall: default type not handled * #78 Case of an empty string as return parameter without type specified * #79 Missing element inside element in XML-RPC * #65 QxtCountryComboBox * #70 QxtConfigWidget display not correct * QxtAbstractHttpConnector: don't add null devices to buffer list * QxtZeroconf: Fixed the avahipoll so that the avahi mdns implementation work 0.6.0 ----- - General * Revised the build system * Revised docs (now based on qdoc3) * QxtConfig.cmake - Bug fixes * #4 QxtDaemon::daemonize() compilation warning * #24 QxtFlowView::currentIndex() * #29 qxtwecore * #33 Problem in QxtMailMessage * #34 Debug PDB files * #36 QxtCommandoptions on Windows wrong option parsing * #41 Compilation issue on Mac - QxtCore * Added QxtModelSerializer * Removed obsolete QxtSemaphore * Added QxtJSON - QxtGui * Added rich text support to QxtItemDelegate * Removed obsolete QxtTabWidget::TabMovementMode & QxtTabBar * Removed obsolete QxtDockWidget * Revised QxtConfigDialog & QxtConfigWidget * Enhanced QxtWindowSystem::idleTime() to resolve libXss at run-time * Added QxtCrumbView::crumbDelegate() * Added QxtFilterDialog and QxtLookupLineEdit - QxtNetwork * Added QxtXmlRpc * Added QxtMainAttachment::fromFile() * Revised QxtSmtp * Added QxtJSONRpcClient and QxtJSONRpcCall - Added QxtZeroConf module 0.5.2 ----- - Bug fixes * QxtSerialDevice: update QIODevice status when device is closed * QxtSerialDevice: destroy QSocketNotifier when device is closed * Modified QxtGlobalShortcut to use XSetErrorHandler() to catch X(Un)GrabKey() errors on X11 0.5.1 ----- - Bug fixes * #3 [Vista/Qt 4.5.0] - static build issue * #9 QxtCheckComboBox display is inconsistent * #10 qxtwindowsystem_win.cpp(105) : error C2065: 'LASTINPUTINFO': undeclared identifier * #16 Static lib linkage problem in Qt Creator * #17 QxtPushButton::minimumSizeHint returns wrong value * Fixed QxtGlobalShortcut to allow NumLock on X11 * Fixed compilation problems with the GCC-4.4.X series * Fixed QxtGlobalShortcut::shortcut() 0.5.0 ----- - General * Added LGPL license option * Run Krazy checks and fixed found issues * Improved configure.bat * Added missing export macros * Added missing convenience headers * Improved compatibility - QT_FORWARD_DECLARE_CLASS - Q_SLOTS, Q_SIGNALS & Q_FOREACH in headers - interface - QxtCore * Revised QxtFifo * Added QxtAlgorithms * Added QxtSerialDevice * Added QxtSlotMapper - QxtCrypto * Revised QxtBlowfish - QxtGui * Added QxtWindowSystem::idleTime() * Added QxtCrumbView * Improved QxtScheduleView * Added QxtSortFilterProxyModel * Improved QxtSpanSlider - Added QxtSpanSlider::HandleMovementMode * Improved QxtItemDelegate - Added ProgressMinimumRole & ProgressMaximumRole - Added support for busy indicator mode * Improved QxtLetterBoxWidget - Added QxtLetterBoxWidget::margin - Added QxtLetterBoxWidget::resizeWidget - QxtWeb * Added QxtWebCgiService 0.4.0 ----- - QxtCore * Added QxtDeplex * Added QxtLocale * Added QxtPointerList * Added QxtMultiSignalWaiter * Added QxtSignalGroup * Added QxtCommandOptions * Added QxtLogger * Added QxtAbstractConnectionManager * Added QxtDataStreamSignalSerializer * Added QxtAbstractSignalSerializer - QxtCrypto * Added QxtHmac - QxtGui * Added QxtItemEditorCreatorBase * Added QxtStandardItemEditorCreator * Added QxtItemEditorCreator * Added QxtBaseSpinBox * Added QxtCountryComboBox * Added QxtCountryModel * Added QxtLanguageComboBox * Added QxtScheduleView * Added QxtTabBar * Added QxtFlowView * Added QxtLetterBoxWidget * Improved QxtTabWidget - Added QxtTabWidget::alwaysShowTabBar - Added QxtTabWidget::tabAnimation - Added QxtTabWidget::tabMovementMode * Improved QxtConfirmationMessage - Added QxtConfirmationMessage::settingsFormat - Added QxtConfirmationMessage::rememberOnReject - Added QxtConfirmationMessage::overrideSettingsApplication - Added QxtConfirmationMessage::overrideSettingsKey - Added QxtConfirmationMessage::overrideSettingsOrganization - QxtBerkeley * Added QxtBdbTree - QxtWeb * Revised the whole module - QxtNetwork * Added QxtTcpConnectionManager libqxt-0.6.2/LICENSE000066400000000000000000000114201215241066400140260ustar00rootroot00000000000000Qt Extension Library Copyright (C) 2007 Qxt Foundation ------------------- Disclaimer ------------------------------------------------ Until the Qxt Foundation is legally established, copyright for the source code falls back to the original contributor. For information about the status of the Qxt Foundation, or about the copyright status of any part of Qxt, contact the Qxt project maintainers at Once the Qxt Foundation has been legally established, all contributors must transfer all copyright interest to the Qxt Foundation before their submissions will be added to the project. ------------------- License --------------------------------------------------- This library is free software; you can redistribute it and/or modify it under the terms of the Common Public License, version 1.0, as published by IBM or under the terms of the GNU Lesser General Public License, version 2.1, as published by the Free Software Foundation This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. You should have received a copy of the CPL along with this file. See the LICENSE file and the cpl1.0.txt file included with the source distribution for more information. If you did not receive a copy of the license, contact the Qxt Foundation. You should have received a copy of the LGPL along with this file. See the LICENSE file and the lgpl-2.1.txt file included with the source distribution for more information. If you did not receive a copy of the license, contact the Qxt Foundation. Parts of Qxt depend on Qt 4 and/or other libraries that have their own licenses. Qxt is independent of these licenses; however, use of these other libraries is subject to their respective license agreements. ------------------- Intent ---------------------------------------------------- The following section describes the opinions and intent of the Qxt Foundation with regards to the licensing and use of the Qxt source code and library. In the event that the CPL is found to be illegal or invalid, or if any application or clause of the license is subjected to question or abuse, this section is a general statement of the desired interpretation. This section has no legal standing and the statements made here are strictly subject to the text of the CPL; that is, if this section and the CPL are in disagreement, the text of the CPL takes precedence. In no way does this intent grant you any additional rights or impose any additional restrictions. If you have questions about licensing, contact the maintainers. Qxt is built and supported by open-source enthusiasts. - Please respect the open-source background of the contributors. The code is provided for everyone's use; you may not restrict the rights of anyone to use it. - No individual may claim ownership of any part of the code. It belongs to the community. - You may modify the source code to suit your needs, but these changes must be made free. If you distribute a modified form of Qxt, you must also distribute the entire source code of the modified form. - Digital Rights Management (DRM) puts unfair, unfree restrictions on users and developers. It is the opposite of Free Software. We can't stop you from using it, but please don't use the Qxt name for software restricted by DRM. - Please respect the time and effort put into the project by the developers. - If you find Qxt useful, it would be appreciated if you would include text in your application (for instance, in the About dialog) giving acknowledgement to Qxt. - If you make modifications to the source code, you must not call the modified version "Qxt." It's okay to include "Qxt" in the name, but anyone who receives the modified version needs to know that it's not the same as the version distributed by the Qxt Foundation. - We want everyone to be able to use Qxt without restrictions. - If you distribute Qxt in compiled binary form, please ensure that everyone who receives it can get the source code used to create it. - You are free to use Qxt in closed-source applications as long as you distribute Qxt in an open-source fashion. This does not require you to make your entire application open-source. - The Qxt Foundation is a non-profit, non-political organization. - Please don't use the Qxt name in any political or semi-political propaganda or publication. We don't like it. - Qxt is distributed "as-is," with no warranty. - If it makes your program crash, your computer blow up, or tiny demons fly out of your nose, please don't sue us. libqxt-0.6.2/README000066400000000000000000000026631215241066400137120ustar00rootroot000000000000001) configure make sure qmake is in your PATH and run ./configure or configure.bat on windows. see configure --help for more information (for msvc you could try ./configure.bat -msvc and open the solution file in msvc, we recomend compiling on commandline though) 2) build type make or nmake when using msvc then don't forget to make install Note: This will also install qxt.prf to your qtdir/mkspecs/features directory. 3) use Add the following lines to your qmake project file: CONFIG += qxt QXT += core gui The QXT variable should contain the modules you want. (In this example core and gui are used.) Note: Some modules depend on other modules. The required modules are added automatically. if you have an existing msvc project and can't swtich to qmake you can use zbenjamins solution: Howto use libqxt in a existing Visual Studio Project: 1. create and install libqxt. (See install instructions) 2. add {libqxtinstalldir}\include\qxt\QxtCore to your include path 3. add {libqxtinstalldir}\lib to your library search path 4. to add a specific libqxt module (f.e QxtSql) you have to: - add {libqxtinstalldir}\include\qxt\QxtSql to your include path - add the library QxtSql.lib to your project Most of the times you have also to include the QxtCore and QxtKit modules. It's done the same way like the example above. libqxt-0.6.2/config.tests/000077500000000000000000000000001215241066400154315ustar00rootroot00000000000000libqxt-0.6.2/config.tests/db/000077500000000000000000000000001215241066400160165ustar00rootroot00000000000000libqxt-0.6.2/config.tests/db/db.pro000066400000000000000000000001751215241066400171300ustar00rootroot00000000000000CONFIG -= app_bundle TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . SOURCES += main.cpp !win32:LIBS+=-ldb QT=core libqxt-0.6.2/config.tests/db/main.cpp000066400000000000000000000005141215241066400174460ustar00rootroot00000000000000#include #if DB_VERSION_MAJOR < 4 #error db>=4.4 required #endif #if DB_VERSION_MAJOR < 5 #if DB_VERSION_MINOR < 4 #error db>=4.4 required #endif #if DB_VERSION_MINOR < 6 #warning db < 4.6, some features will be disabled #endif #endif int main (int,char**) { DB * db; db_create(&db, NULL, 0); return 0; } libqxt-0.6.2/config.tests/qt4/000077500000000000000000000000001215241066400161415ustar00rootroot00000000000000libqxt-0.6.2/config.tests/qt4/main.cpp000066400000000000000000000002051215241066400175660ustar00rootroot00000000000000#include #if QT_VERSION < 0x040000 #error needs qt4 #endif int main (int,char**) { QObject(); return 0; } libqxt-0.6.2/config.tests/qt4/qt4.pro000066400000000000000000000001531215241066400173720ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . SOURCES += main.cpp QT=core CONFIG -= app_bundle libqxt-0.6.2/config.tests/xrandr/000077500000000000000000000000001215241066400167275ustar00rootroot00000000000000libqxt-0.6.2/config.tests/xrandr/main.cpp000066400000000000000000000003131215241066400203540ustar00rootroot00000000000000#include #include int main() { int major; int minor; Display* display = XOpenDisplay(0); XRRQueryVersion(display, &major, &minor); return 0; } libqxt-0.6.2/config.tests/xrandr/xrandr.pro000066400000000000000000000002051215241066400207440ustar00rootroot00000000000000win32:include(../../depends.pri) TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . SOURCES += main.cpp !win32:LIBS+=-lXrandr libqxt-0.6.2/config.tests/xss/000077500000000000000000000000001215241066400162465ustar00rootroot00000000000000libqxt-0.6.2/config.tests/xss/main.cpp000066400000000000000000000001411215241066400176720ustar00rootroot00000000000000#include int main() { XScreenSaverAllocInfo(); return 0; } libqxt-0.6.2/config.tests/xss/xss.pro000066400000000000000000000002271215241066400176060ustar00rootroot00000000000000win32:include(../../depends.pri) CONFIG -= app_bundle TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . SOURCES += main.cpp !win32:LIBS+=-lXss libqxt-0.6.2/config.tests/zeroconf/000077500000000000000000000000001215241066400172565ustar00rootroot00000000000000libqxt-0.6.2/config.tests/zeroconf/zeroconf.cpp000066400000000000000000000002441215241066400216070ustar00rootroot00000000000000#include int main(int, char**) { char buffer[kDNSServiceMaxDomainName]; return DNSServiceConstructFullName(buffer, 0, "_foo._tcp", "domain"); } libqxt-0.6.2/config.tests/zeroconf/zeroconf.pro000066400000000000000000000002401215241066400216210ustar00rootroot00000000000000unix:!macx:LIBS += -ldns_sd CONFIG -= app_bundle TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . SOURCES += zeroconf.cpp QT=core CONFIG -= app_bundle libqxt-0.6.2/configure000077500000000000000000000243461215241066400147430ustar00rootroot00000000000000#!/bin/bash # defaults QMAKE_BIN=qmake WHICH=which NO_DB=0 NO_ZEROCONF=0 NO_XRANDR=0 QXT_MODULES="docs berkeley core designer gui network sql web zeroconf" # detect platform if uname -a | grep -iq Darwin; then QXT_MAC=1 DEFAULT_LIBS="/Library/Frameworks" QMAKE_PARAMS="-spec macx-g++" NO_XRANDR=1 else QXT_MAC=0 DEFAULT_LIBS="PREFIX/lib" QMAKE_PARAMS="" fi # working directories QXT_SOURCE_TREE=`dirname $0` QXT_SOURCE_TREE=`(cd "$QXT_SOURCE_TREE"; /bin/pwd)` QXT_BUILD_TREE=`/bin/pwd` [ ! -d $QXT_BUILD_TREE/features ] && mkdir $QXT_BUILD_TREE/features [ ! -d $QXT_BUILD_TREE/examples ] && mkdir $QXT_BUILD_TREE/examples [ ! -d $QXT_BUILD_TREE/tests ] && mkdir $QXT_BUILD_TREE/tests # output files CONFIG_LOG=$QXT_BUILD_TREE/config.log QMAKE_CACHE=$QXT_BUILD_TREE/.qmake.cache QXT_VARS=$QXT_BUILD_TREE/features/qxtvars.prf [ -f $CONFIG_LOG ] && mv $CONFIG_LOG $CONFIG_LOG.bak [ -f $QMAKE_CACHE ] && mv $QMAKE_CACHE $QMAKE_CACHE.bak [ -f $QXT_VARS ] && mv $QXT_VARS $QXT_VARS.bak # colors C_RED='\e[1;31m' C_BLUE='\e[1;34m' C_GREEN='\e[1;32m' C_CYAN='\e[1;36m' C_NONE='\e[0m' # defaults echo "CONFIG += silent" > $QMAKE_CACHE echo "QXT_MODULES = $QXT_MODULES" >> $QMAKE_CACHE echo "QXT_MODULES = $QXT_MODULES" > $QXT_VARS # parse configure options while (( $# > 0 )); do if [ $1 == "-qmake-bin" ]; then QMAKE_BIN=$2; shift elif [ $1 == "-L" ]; then echo "LIBS += -L$2" >> $QMAKE_CACHE;shift elif [ $1 == "-l" ]; then echo "LIBS += -l$2" >> $QMAKE_CACHE;shift elif [ $1 == "-I" ]; then echo "INCLUDEPATH += $2" >> $QMAKE_CACHE;shift elif [ $1 == "-bootstrap" ]; then echo "CONFIG += bootstrap" >> $QMAKE_CACHE; shift elif [ $1 == "-nomake" ]; then echo "QXT_MODULES -= $2" >> $QMAKE_CACHE echo "QXT_MODULES -= $2" >> $QXT_VARS; shift elif [ $1 == "-prefix" ]; then QXT_INSTALL_PREFIX=$2; shift elif [ $1 == "-libdir" ]; then QXT_INSTALL_LIBS=$2; shift elif [ $1 == "-docdir" ]; then QXT_INSTALL_DOCS=$2; shift elif [ $1 == "-headerdir" ]; then QXT_INSTALL_HEADERS=$2; shift elif [ $1 == "-bindir" ]; then QXT_INSTALL_BINS=$2; shift elif [ $1 == "-featuredir" ]; then QXT_INSTALL_FEATURES=$2; shift elif [ $1 == "-static" ]; then echo "CONFIG += static staticlib" >> $QMAKE_CACHE echo "DEFINES += QXT_STATIC" >> $QXT_VARS elif [ $1 == "-debug" ]; then echo "CONFIG += debug" >> $QMAKE_CACHE echo "QXT_INSTALL_TYPE = debug" >> $QXT_VARS elif [ $1 == "-release" ]; then echo "CONFIG += release" >> $QMAKE_CACHE echo "QXT_INSTALL_TYPE = release" >> $QXT_VARS elif [ $1 == "-no-db" ]; then NO_DB=1 elif [ $1 == "-no-xrandr" ]; then NO_XRANDR=1 elif [ $1 == "-no-zeroconf" ]; then NO_ZEROCONF=1 elif [ $1 == "-no-avahi" ]; then echo "CONFIG += NO_AVAHI" >> $QMAKE_CACHE elif [ $1 == "-verbose" ]; then echo "CONFIG -= silent" >> $QMAKE_CACHE elif [ $1 == "-qws" ]; then echo "CONFIG += qws" >> $QMAKE_CACHE elif [ $1 == "-coverage" ]; then echo "CONFIG += coverage" >> $QMAKE_CACHE elif [ $1 == "-universal" ]; then echo "CONFIG += x86 ppc" >> $QMAKE_CACHE elif [ $1 == "-arch" ]; then echo "CONFIG += $2" >> $QMAKE_CACHE shift elif [ $1 == "-sdk" ]; then echo "QMAKE_MAC_SDK=$2" >> $QMAKE_CACHE; shift elif [ $1 == "-h" ] || [ $1 == "-help" ] || [ $1 == "--help" ]; then echo "Usage: configure [-prefix ] [-libdir ] [-docdir ]" echo " [-bindir ] [-headerdir ] [-featuredir ]" echo " [-qmake-bin ] [-static] [-debug] [-release]" echo " [-no-db] [-no-zeroconf] [-nomake ]" if [[ "$QXT_MAC" == "0" ]]; then echo -n " [-no-xrandr] [-qws]" else echo -n " [-universal] [-arch ] [-sdk ]" fi echo " [-verbose] [-coverage]" echo echo "Installation options:" echo echo "-prefix ....... This will install everything relative to " echo " default: /usr/local/Qxt" echo "-libdir ....... Libraries will be installed to " echo " default: $DEFAULT_LIBS" echo "-docdir ....... Documentation will be installed to " echo " default: PREFIX/doc" echo "-bindir ....... Executables will be installed to " echo " default: PREFIX/bin" echo "-headerdir .... Include files will be installed to " echo " default: PREFIX/include" echo "-featuredir ... Feature files will be installed to " echo " default: QMAKE_MKSPECS/features" echo "-qmake-bin ... Specifies the path to the qmake executable" echo " default: search the system path" echo "-L ........... Specifies the a additional library search path" echo "-I ........... Specifies the a additional include search path" echo "-l ........... Add a custom library" echo "-static ............. Build Qxt as a static library" echo "-debug .............. Build Qxt with debugging symbols" echo "-release ............ Build Qxt without debugging support" if [[ "$QXT_MAC" != "1" ]]; then echo "-qws ................ Build for Qt/Embedded" echo "-no-xrandr ......... Do not link to Xrandr" fi echo "-no-db .............. Do not link to Berkeley DB" echo "-no-zeroconf ........ Do not link to Zeroconf" echo "-no-openssl ......... Do not link to Openssl" echo "-no-avahi ........... Apple mdns-sd instead of avahi even on linux" echo "-nomake .... Do not compile the specified module" echo " options: $QXT_MODULES" echo "-verbose ............ Show full compiler output" echo "-coverage ........... Collect coverage information" if [[ "$QXT_MAC" == "1" ]]; then echo "-universal .......... Equivalent to -arch ppc -arch x86" echo "-arch ........ Include in universal binary" echo "-sdk ......... Use a different Mac SDK" fi [ -f $CONFIG_LOG.bak ] && mv $CONFIG_LOG.bak $CONFIG_LOG [ -f $QMAKE_CACHE.bak ] && mv $QMAKE_CACHE.bak $QMAKE_CACHE [ -f $QXT_VARS.bak ] && mv $QXT_VARS.bak $QXT_VARS exit else echo "Unrecognized configure option: $1" [ -f $CONFIG_LOG.bak ] && mv $CONFIG_LOG.bak $CONFIG_LOG [ -f $QMAKE_CACHE.bak ] && mv $QMAKE_CACHE.bak $QMAKE_CACHE [ -f $QXT_VARS.bak ] && mv $QXT_VARS.bak $QXT_VARS exit fi shift done # detect qmake if ! $WHICH $QMAKE_BIN >>$CONFIG_LOG 2>&1; then echo >&2 "You don't seem to have 'qmake' in your PATH." echo >&2 "Cannot proceed." exit 1 fi # default directories if [[ "$QXT_INSTALL_PREFIX" == "" ]]; then QXT_INSTALL_PREFIX="/usr/local/Qxt" fi if [[ "$QXT_INSTALL_LIBS" == "" ]]; then if [[ "$QXT_MAC" == "1" ]]; then QXT_INSTALL_LIBS="/Library/Frameworks" else QXT_INSTALL_LIBS="$QXT_INSTALL_PREFIX/lib" fi fi if [[ "$QXT_INSTALL_DOCS" == "" ]]; then QXT_INSTALL_DOCS="$QXT_INSTALL_PREFIX/doc" fi if [[ "$QXT_INSTALL_HEADERS" == "" ]]; then QXT_INSTALL_HEADERS="$QXT_INSTALL_PREFIX/include" fi if [[ "$QXT_INSTALL_BINS" == "" ]]; then QXT_INSTALL_BINS="$QXT_INSTALL_PREFIX/bin" fi if [[ "$QXT_INSTALL_FEATURES" == "" ]]; then QXT_INSTALL_FEATURES=`$QMAKE_BIN -query QMAKE_MKSPECS` QXT_INSTALL_FEATURES="$QXT_INSTALL_FEATURES/features" fi # output variables echo "QXT_INSTALL_PREFIX = $QXT_INSTALL_PREFIX" >> $QMAKE_CACHE echo "QXT_INSTALL_PREFIX = $QXT_INSTALL_PREFIX" >> $QXT_VARS echo "QXT_INSTALL_LIBS = $QXT_INSTALL_LIBS" >> $QMAKE_CACHE echo "QXT_INSTALL_LIBS = $QXT_INSTALL_LIBS" >> $QXT_VARS echo "QXT_INSTALL_BINS = $QXT_INSTALL_BINS" >> $QMAKE_CACHE echo "QXT_INSTALL_BINS = $QXT_INSTALL_BINS" >> $QXT_VARS echo "QXT_INSTALL_HEADERS = $QXT_INSTALL_HEADERS" >> $QMAKE_CACHE echo "QXT_INSTALL_HEADERS = $QXT_INSTALL_HEADERS" >> $QXT_VARS echo "QXT_INSTALL_FEATURES = $QXT_INSTALL_FEATURES" >> $QMAKE_CACHE echo "QXT_INSTALL_FEATURES = $QXT_INSTALL_FEATURES" >> $QXT_VARS echo "QXT_INSTALL_DOCS = $QXT_INSTALL_DOCS" >> $QMAKE_CACHE echo "QXT_INSTALL_DOCS = $QXT_INSTALL_DOCS" >> $QXT_VARS echo "QXT_SOURCE_TREE = $QXT_SOURCE_TREE" >> $QMAKE_CACHE echo "QXT_BUILD_TREE = $QXT_BUILD_TREE" >> $QMAKE_CACHE # detect make echo>$CONFIG_LOG if [ -z "$MAKE" ]; then MAKE= for mk in gmake make; do if "$WHICH" $mk 2>&1| grep -qv "no "; then MAKE=`$WHICH $mk` break fi done if [ -z "$MAKE" ]; then echo >&2 "You don't seem to have 'make' or 'gmake' in your PATH." echo >&2 "Cannot proceed." exit 1 fi fi # detect dependencies configtest() { echo -en "Checking for $1 " echo -e " \n\n $1\n" >>$CONFIG_LOG mkdir -p "$QXT_BUILD_TREE/config.tests/$1" cd "$QXT_BUILD_TREE/config.tests/$1" $QMAKE_BIN $QMAKE_PARAMS "$QXT_SOURCE_TREE/config.tests/$1/$1.pro" >>$CONFIG_LOG echo -n "." $MAKE clean >>$CONFIG_LOG 2>&1 [ -f ./$1 ] && rm ./$1 echo -n "." $MAKE >>$CONFIG_LOG 2>&1 >>$CONFIG_LOG 2>&1 if [ -x $1 ] ; then echo -e >&2 " [${C_GREEN}success${C_NONE}] " echo "DEFINES+=HAVE_$2">>$QMAKE_CACHE else echo -e >&2 " [${C_RED}failure${C_NONE}] " fi } echo >&2 "Testing for optional external libraries." echo >&2 "If tests fail, some features will not be available." configtest qt4 QT if [[ "$NO_DB" == "0" ]]; then configtest db DB fi if [[ "$QXT_MAC" == "0" ]]; then if [[ "$NO_XRANDR" == "0" ]]; then configtest xrandr XRANDR fi if [[ "$NO_ZEROCONF" == "0" ]]; then configtest zeroconf ZEROCONF fi else echo "DEFINES+=HAVE_ZEROCONF">>$QMAKE_CACHE fi # run qmake echo "Autodetection finished. Running qmake." cd $QXT_BUILD_TREE $QMAKE_BIN $QMAKE_PARAMS "$QXT_SOURCE_TREE/libqxt.pro" -recursive >>$CONFIG_LOG echo -e >&2 "${C_CYAN}Configure finished. Run $MAKE now.${C_NONE}\n" libqxt-0.6.2/configure.bat000066400000000000000000000260501215241066400154770ustar00rootroot00000000000000@ECHO off @rem -- defaults set QMAKE_BIN=qmake set MAKE_BIN= set STATIC=0 set DEBUG_OR_RELEASE=0 set MSVCMODE= set DB=1 set ZEROCONF=1 set QXT_MODULES=docs core gui network sql web designer berkeley zeroconf @rem -- initialize set QXT_INSTALL_PREFIX= set QXT_INSTALL_LIBS= set QXT_INSTALL_BINS= set QXT_INSTALL_HEADERS= set QXT_INSTALL_FEATURES= set QXT_INSTALL_DOCS= @rem -- working directories set QXT_BUILD_TREE=%CD% cd "%0\..\" SET QXT_SOURCE_TREE=%CD% cd %QXT_BUILD_TREE% if not exist %QXT_BUILD_TREE%\features mkdir %QXT_BUILD_TREE%\features >NUL 2>&1 if not exist %QXT_BUILD_TREE%\examples mkdir %QXT_BUILD_TREE%\examples >NUL 2>&1 if not exist %QXT_BUILD_TREE%\tests mkdir %QXT_BUILD_TREE%\tests >NUL 2>&1 @rem -- output files set CONFIG_LOG=%QXT_BUILD_TREE%\config.log set QMAKE_CACHE=%QXT_BUILD_TREE%\.qmake.cache set QXT_VARS=%QXT_BUILD_TREE%\features\qxtvars.prf if exist %CONFIG_LOG% move %CONFIG_LOG% %CONFIG_LOG%.bak >NUL 2>&1 if exist %QMAKE_CACHE% move %QMAKE_CACHE% %QMAKE_CACHE%.bak >NUL 2>&1 if exist %QXT_VARS% move %QXT_VARS% %QXT_VARS%.bak >NUL 2>&1 @rem -- defaults echo CONFIG += silent > %QMAKE_CACHE% echo QXT_MODULES = %QXT_MODULES% >> %QMAKE_CACHE% echo QXT_MODULES = %QXT_MODULES% > %QXT_VARS% shift :top if "%0" == "" goto finish if "%0" == "-qmake-bin" goto setqmake if "%0" == "-make-bin" goto setmake if "%0" == "-I" goto addinclude if "%0" == "-L" goto addlibpath if "%0" == "-l" goto addlib if "%0" == "-nomake" goto nomake if "%0" == "-prefix" goto prefix if "%0" == "-libdir" goto libdir if "%0" == "-docdir" goto docdir if "%0" == "-headerdir" goto headerdir if "%0" == "-bindir" goto bindir if "%0" == "-featuredir" goto featuredir if "%0" == "-static" goto static if "%0" == "-debug" goto debug if "%0" == "-release" goto release if "%0" == "-debug_and_release" goto debug_and_release if "%0" == "-no-db" goto nodb if "%0" == "-msvc" goto msvc if "%0" == "/help" goto help if "%0" == "-help" goto help if "%0" == "--help" goto help if "%0" == "/?" goto help echo Unrecognized configure option: %0 del %QMAKE_CACHE% del %QXT_VARS% goto end :setqmake set QMAKE_BIN=%1 goto bottom2 :setmake set MAKE_BIN=%1 goto bottom2 :addinclude set QXT_INCPATH=%1 set QXT_INCPATH=%QXT_INCPATH:\=/% echo INCLUDEPATH += %QXT_INCPATH% >> %QMAKE_CACHE% goto bottom2 :addlibpath set QXT_LIBPATH=%1 set QXT_LIBPATH=%QXT_LIBPATH:\=/% echo LIBS += -L%QXT_LIBPATH% >> %QMAKE_CACHE% goto bottom2 :addlib echo LIBS += -l%1 >> %QMAKE_CACHE% goto bottom2 :nomake if "%1"=="db" set DB=0 if "%1"=="zeroconf" set ZEROCONF=0 echo QXT_MODULES -= %1 >> %QMAKE_CACHE% echo QXT_MODULES -= %1 >> %QXT_VARS% goto bottom2 :prefix echo hmm set QXT_INSTALL_PREFIX=%1 goto bottom2 :libdir set QXT_INSTALL_LIBS=%1 goto bottom2 :docdir set QXT_INSTALL_DOCS=%1 goto bottom2 :headerdir set QXT_INSTALL_HEADERS=%1 goto bottom2 :bindir set QXT_INSTALL_BINS=%1 goto bottom2 :featuredir set QXT_INSTALL_FEATURES=%1 goto bottom2 :static set STATIC=1 echo CONFIG += static staticlib >> %QMAKE_CACHE% echo DEFINES += QXT_STATIC >> %QXT_VARS% goto bottom :debug set DEBUG_OR_RELEASE=1 echo CONFIG += debug >> %QMAKE_CACHE% goto bottom :release set DEBUG_OR_RELEASE=1 echo CONFIG += release >> %QMAKE_CACHE% goto bottom :debug_and_release set DEBUG_OR_RELEASE=1 echo CONFIG += debug_and_release build_all >> %QMAKE_CACHE% goto bottom :nodb set DB=0 echo DEFINES -= HAVE_DB >> %QMAKE_CACHE% goto bottom :nozeroconf set ZEROCONF=0 echo DEFINES -= HAVE_ZEROCONF >> %QMAKE_CACHE% goto bottom :msvc set MSVCMODE=-tp vc goto bottom :bottom2 shift :bottom shift goto top :help echo Usage: configure [-prefix (dir)] [-libdir (dir)] [-docdir (dir)] echo [-bindir (dir)] [-headerdir (dir)] [-qmake-bin (path)] echo [-make-bin (path)] [-nomake (module)] [-debug] [-release] echo [-static] echo. echo Installation options: echo. echo -prefix (dir) ....... This will install everything relative to (dir) echo default: C:\libqxt echo -libdir (dir) ....... Libraries will be installed to (dir) echo default: PREFIX/lib echo -docdir (dir) ....... Documentation will be installed to (dir) echo default: PREFIX/share/doc echo -bindir (dir) ....... Executables will be installed to (dir) echo default: PREFIX/bin echo -headerdir (dir) .... Include files will be installed to (dir) echo default: PREFIX/include echo -qmake-bin (path) ... Specifies the path to the qmake executable echo default: search the system path echo -make-bin (path) .... Specifies the path to the make executable echo default: search the system path echo -L (path)............ Specifies the a additional library search path echo -I (path)............ Specifies the a additional include search path echo -l (path)............ Add a custom library echo -static ............. Compile Qxt as a static library echo -debug .............. Build Qxt with debugging symbols echo -release ............ Build Qxt without debugging support echo -debug_and_release .. Build Qxt with and without debugging support echo -no-db .............. Do not link to Berkeley DB echo -nomake (module) .... Do not compile the specified module echo options: berkeley designer gui network sql web zeroconf del %QMAKE_CACHE% goto end :finish echo Testing for qmake... %QMAKE_BIN% -v >> %CONFIG_LOG% 2>&1 if errorlevel 1 goto qmakeERR goto qmakeOK :qmakeERR echo You don't seem to have 'qmake' in your PATH. echo Cannot proceed. goto end :qmakeOK if not "%MAKE_BIN%" == "" goto detectTools_end_test_make if "%QMAKESPEC%" == "win32-msvc" goto testnmake if "%QMAKESPEC%" == "win32-msvc.net" goto testnmake if "%QMAKESPEC%" == "win32-msvc2005" goto testnmake if "%QMAKESPEC%" == "win32-msvc2008" goto testnmake :testmingw echo Testing for mingw32-make... call mingw32-make -v >> %CONFIG_LOG% 2>&1 if errorlevel 1 goto testnmake echo Using mingw32-make. SET MAKE_BIN=mingw32-make GOTO detectTools_end_test_make :testnmake if "%QMAKESPEC%" == "win32-g++" goto testgmake echo Testing for nmake... nmake /? >> %CONFIG_LOG% 2>&1 if errorlevel 1 goto testgmake echo Using nmake. SET MAKE_BIN=nmake GOTO detectTools_end_test_make :testgmake echo Testing for GNU make... call make -v >> %CONFIG_LOG% 2>&1 if errorlevel 1 goto missingmake echo Using GNU make. SET MAKE_BIN=make GOTO detectTools_end_test_make :missingmake echo You don't seem to have 'mingw32-make', 'nmake' or 'make' in your PATH. echo Cannot proceed. goto end :detectTools_end_test_make if not "%QXT_INSTALL_PREFIX%" == "" goto skipdefaultprefix set QXT_INSTALL_PREFIX=C:\Qxt :skipdefaultprefix if not "%QXT_INSTALL_LIBS%" == "" goto skipdefaultlibs set QXT_INSTALL_LIBS=%QXT_INSTALL_PREFIX%\lib :skipdefaultlibs if not "%QXT_INSTALL_DOCS%" == "" goto skipdefaultdocs set QXT_INSTALL_DOCS=%QXT_INSTALL_PREFIX%\doc :skipdefaultdocs if not "%QXT_INSTALL_HEADERS%" == "" goto skipdefaultheaders set QXT_INSTALL_HEADERS=%QXT_INSTALL_PREFIX%\include :skipdefaultheaders if not "%QXT_INSTALL_BINS%" == "" goto skipdefaultbins set QXT_INSTALL_BINS=%QXT_INSTALL_PREFIX%\bin :skipdefaultbins if not "%QXT_INSTALL_FEATURES%" == "" goto skipdefaultfeatures %QMAKE_BIN% -query QMAKE_MKSPECS > %QXT_BUILD_TREE%\mkspecs.tmp set /p QXT_INSTALL_FEATURES=<%QXT_BUILD_TREE%\mkspecs.tmp set QXT_INSTALL_FEATURES=%QXT_INSTALL_FEATURES%\features del %QXT_BUILD_TREE%\mkspecs.tmp :skipdefaultfeatures echo QXT_INSTALL_PREFIX = %QXT_INSTALL_PREFIX:\=/% >> %QMAKE_CACHE% echo QXT_INSTALL_PREFIX = %QXT_INSTALL_PREFIX:\=/% >> %QXT_VARS% echo QXT_INSTALL_LIBS = %QXT_INSTALL_LIBS:\=/% >> %QMAKE_CACHE% echo QXT_INSTALL_LIBS = %QXT_INSTALL_LIBS:\=/% >> %QXT_VARS% echo QXT_INSTALL_BINS = %QXT_INSTALL_BINS:\=/% >> %QMAKE_CACHE% echo QXT_INSTALL_BINS = %QXT_INSTALL_BINS:\=/% >> %QXT_VARS% echo QXT_INSTALL_HEADERS = %QXT_INSTALL_HEADERS:\=/% >> %QMAKE_CACHE% echo QXT_INSTALL_HEADERS = %QXT_INSTALL_HEADERS:\=/% >> %QXT_VARS% echo QXT_INSTALL_FEATURES = %QXT_INSTALL_FEATURES:\=/% >> %QMAKE_CACHE% echo QXT_INSTALL_FEATURES = %QXT_INSTALL_FEATURES:\=/% >> %QXT_VARS% echo QXT_INSTALL_DOCS = %QXT_INSTALL_DOCS:\=/% >> %QMAKE_CACHE% echo QXT_INSTALL_DOCS = %QXT_INSTALL_DOCS:\=/% >> %QXT_VARS% echo QXT_SOURCE_TREE = %QXT_SOURCE_TREE:\=/% >> %QMAKE_CACHE% echo QXT_BUILD_TREE = %QXT_BUILD_TREE:\=/% >> %QMAKE_CACHE% echo Testing for optional external libraries. echo If tests fail, some features will not be available. :detectdb if "%DB%"=="0" goto detectzeroconf echo Testing for Berkeley DB... echo BDB... >> %CONFIG_LOG% if not exist %QXT_BUILD_TREE%\config.tests\db mkdir %QXT_BUILD_TREE%\config.tests\db cd %QXT_BUILD_TREE%\config.tests\db %QMAKE_BIN% %QXT_SOURCE_TREE%\config.tests\db\db.pro >> %CONFIG_LOG% 2>&1 if errorlevel 1 goto dbfailed call %MAKE_BIN% clean >> %CONFIG_LOG% 2>&1 call %MAKE_BIN% >> %CONFIG_LOG% 2>&1 if errorlevel 1 goto dbfailed set DB=1 echo DEFINES += HAVE_DB >> %QMAKE_CACHE% echo Berkeley DB enabled. goto detectzeroconf :dbfailed set DB=0 echo DEFINES -= HAVE_DB >> %QMAKE_CACHE% echo Berkeley DB disabled. :detectzeroconf if "%ZEROCONF%"=="0" goto alltestsok echo Testing for Zero Conf... echo ZEROCONF... >> %CONFIG_LOG% if not exist %QXT_BUILD_TREE%\config.tests\zeroconf mkdir %QXT_BUILD_TREE%\config.tests\zeroconf cd %QXT_BUILD_TREE%\config.tests\zeroconf %QMAKE_BIN% %QXT_SOURCE_TREE%\config.tests\zeroconf\zeroconf.pro >> %CONFIG_LOG% 2>&1 if errorlevel 1 goto zeroconffailed call %MAKE_BIN% clean >> %CONFIG_LOG% 2>&1 call %MAKE_BIN% >> %CONFIG_LOG% 2>&1 if errorlevel 1 goto zeroconffailed set ZEROCONF=1 echo DEFINES += HAVE_ZEROCONF >> %QMAKE_CACHE% echo Zero Conf enabled. goto alltestsok :zeroconffailed set ZEROCONF=0 echo DEFINES -= HAVE_ZEROCONF >> %QMAKE_CACHE% echo Zero Conf disabled. :alltestsok if "%DEBUG_OR_RELEASE%"=="1" goto skiprelease echo CONFIG += release >> %QMAKE_CACHE% :skiprelease echo Configuration successful. echo Generating makefiles... cd %QXT_BUILD_TREE% %QMAKE_BIN% %MSVCMODE% -recursive %QXT_SOURCE_TREE%\libqxt.pro if errorlevel 1 goto mainqmakeERR if not "%MSVCMODE%" == "" goto skipmakeannounce echo Makefiles generated. Run %MAKE% now. goto end :skipmakeannounce echo Visual Studio solution generated. Open libqxt.sln in Visual Studio. goto end :mainqmakeERR echo Error running qmake. Cannot proceed. goto end :end libqxt-0.6.2/cpl1.0.txt000066400000000000000000000263661215241066400145760ustar00rootroot00000000000000 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. libqxt-0.6.2/doc/000077500000000000000000000000001215241066400135705ustar00rootroot00000000000000libqxt-0.6.2/doc/doc.pri000066400000000000000000000026321215241066400150540ustar00rootroot00000000000000SUBDIRS += tools/3rdparty/qdoc3 win32 { QXT_WINCONFIG = release/ !CONFIG(release, debug|release) { QXT_WINCONFIG = debug/ } } win32:!win32-g++ { unixstyle = false } else :win32-g++:isEmpty(QMAKE_SH) { unixstyle = false } else { unixstyle = true } $$unixstyle { QDOC = QXT_SOURCE_TREE=$$QXT_SOURCE_TREE QXT_BUILD_TREE=$$QXT_BUILD_TREE $$QXT_BUILD_TREE/tools/3rdparty/qdoc3/$${QXT_WINCONFIG}qdoc3 } else { QDOC = set QXT_SOURCE_TREE=$$QXT_SOURCE_TREE&& set QXT_BUILD_TREE=$$QXT_BUILD_TREE&& $$QXT_BUILD_TREE/tools/3rdparty/qdoc3/$${QXT_WINCONFIG}qdoc3.exe QDOC = $$replace(QDOC, "/", "\\\\") } adp_docs.commands = ($$QDOC -DQXT_DOXYGEN_RUN $$QXT_SOURCE_TREE/doc/src/qxt.qdocconf) adp_docs.depends += sub-tools-3rdparty-qdoc3 docs.depends = adp_docs QMAKE_EXTRA_TARGETS += adp_docs docs htmldocs.files = $$QXT_BUILD_TREE/doc/html/* htmldocs.path = $$QXT_INSTALL_DOCS htmldocs.CONFIG += no_check_exist INSTALLS += htmldocs exists( $$[QT_INSTALL_BINS]/qhelpgenerator) { QHELPGENERATOR = $$[QT_INSTALL_BINS]/qhelpgenerator qch_docs.commands = $$QHELPGENERATOR $$QXT_BUILD_TREE/doc/html/qxt.qhp -o $$QXT_BUILD_TREE/doc/qch/qxt.qch qch_docs.depends = adp_docs docs.depends += qch_docs QMAKE_EXTRA_TARGETS += qch_docs qchdocs.files= $$QXT_BUILD_TREE/doc/qch/qxt.qch qchdocs.path = $$QXT_INSTALL_DOCS qchdocs.CONFIG += no_check_exist INSTALLS += qchdocs } libqxt-0.6.2/doc/src/000077500000000000000000000000001215241066400143575ustar00rootroot00000000000000libqxt-0.6.2/doc/src/images/000077500000000000000000000000001215241066400156245ustar00rootroot00000000000000libqxt-0.6.2/doc/src/images/qxt-logo.png000066400000000000000000002752131215241066400201160ustar00rootroot00000000000000PNG  IHDR,߇ pHYs  ~ vpAg,(QIDATxT6ɉ{ !B n'.C= m{fkw~WKZ&zSTң(=C-(=JRG)Kң(aQz(=JRG)Kң(aQz(=JRG)Kң(aQz(=JRG)Ĺ(=Jm? g{c[A ]~ң(Y^9(= ,D '%U ң$mv?yʉ֗?]%NjRYz`hS6;P&QPj KR@XG!&eDbĎĎ7KQzAh ^#Y;i+K^,'KAXzV+ct4`UKt]Oٍt) )9ayY!c)KR@Ș0F*!UO D̀C$vhqX ſGQ B )B%xZ*3b`VnvYP$YEam34G)d 8&FeJg3Z"f56#F F-$ad%B29giZO+u^՘ZMg3Q`(U .(k'Ů3Y5:_AQk0¯mlB*FC!dZRe6 _`*H2/]8Gga ! ln?̪ոTCJ@XGKtTHCPZ@2F$@X/{{)tHEbX[pYnwZ<0f"z.TAihSB%%:Ol*6cWDS;cEP;cϵ6oF?  `ʀQBN)=:ٿ}n?~wsG`FdrFh~]yHe3hm*nnk>|]N?RV6+0qb@i@; UcZVdRteh)%VhdD2ScKA+-)%\XDE.I Zzsz4PdH$i4f3,4S`%\E烯H'+tMA@l*aJ@Mhf5xn7qW"mVpG&)(f=(b%܊63(iׂ z\k+<[#"8DLA9ưcOI *UMg9{@d)PR)b&%P8h.lJ:CJ̵DdYBifTo @fX0!%et-PPqQ5jߵ*ׁ_V^"E9?>ǻv wa6!0Tp{*PNgI|"1Ed3馀tc 0E(L09k.2hVsᲒ؅dY7GXH/RlH1~M1zSfOⓁe!E1ej 1e`Wx(r\jH}+$[q߷JA?Q1Ϣ.Ah%"X 8'XmSڳTLc2-`8)T?31R:YΤ), #3b3+ǭj¦:ʪ/ݬK ]Z@H$Ś^+~1r +R0#xL)(lJ2}H6OsCœbL4نܔ(}E LA;9":S F~سCA 4Ά잂ɖ2G 0-h7z%AᚾetblҚUNJ̪1FK21sN[ ,*w9xSѦ5U*V$g ȈL?9.*<αIO&РSt$LmAPç+f8XIH ??$Ol|RO5Þ(A̴Ȉ|)LJp1M!X9%=c c o̠U߁VMl2*IXSe,:T ͚HB38PN1,cwQ 4mᨩe'tVPUAܖGGeど/ƏQ'Qg Cxx &gb&*$ĹV%o guPH[aoqXTo[ ̿P#W,E[-|_eIq$f|H :,<)MYfJDJ<&NO<$fX-6۬)x&%gE\Q$e_ H[^\Julb%6ΥjvXpvg.jg@U)Njfmf֊ 8GVRĹ+8ayA6Ū0d`j,%"5 T/m4|׽ҽֽuɆ/odQ1 Uj+Q{8k%8!S-|LqW D%VQ @GDI X!1J:\<400l3<p_ߥZdB:^Ħ+m{>A*Q7F1FPsbNU`a $`(G_[ZM/YcM-!4 J_w$3xt>^3Wg`& \.6g)32 |Vgjdm\*r,hcbh'N*7ؤ:kƚbӤpɨ\,8%*,<$T,L,B6PWwa6dn5ЅqN0w@O&+Me@|"5ɧ8}K41e>< H#D L$\M+e #%TZkL j]ay+aիPz6vu[Ò |Tg3ٴ(ތD䊭 TX/{8 > 8%Ps$H}'XO;f"xfiY!PU<+׃%e(j@snKE[3 W(tMaCZdc}Ta) ``଩ jN`X,QEb.)$] Z3II/ GIl졧PWԑE#ücÌ/ twwu7ABµ#b4M-Dȇ<U)!șG)V%gU 1i m\ o 㷩;װ*[̚(2d7`c-7e?U-ǧ@Ⰿ:DlS3t\M_8pT!IW($;Q!x5qgIsMD F#\*j`&ci R!Yy1gY؟b13*Z;̌8Zp.dz͔D&h zH_hL{'A7 2< 0xozz/}6]1]_1Ys[w \槽 N#w_!aLճ"+ AQoZ@+6&2W\}wat`\b=>.VCl+ jgr4JoSꁁ[e z$T~Ɋ <X й߉9_1/`߬-ay(U,8伳gPS1O D'(A #Aߴ}t?Пd꫟<>i@|О?i8E~ Dym dDl ohqzAkf4jܸ o r[qa)a ,QxQ3y_i<9!bdsE.[u@;Nv;T>*cxl!$LšhAh fZՁi/, Nxȡl 9Xghl5>M3i yLͥ@L*<$2o`s5tgXdA ThD<:I22&GPilYkj56 J}SOPm`|>|VTY$s^_|Ugؗ, / #"١RFOxr4sbiH1ֆ|yTqo) Uln/Xi8(J5VB hK0t>wo{^wTo{Zf^ySq[qrNe`GGɬ@tHM(cOE0Z fQX r8W Bcp@tLK$Lej:Wd,%&ebLȧBȐ\20 Bx6I?%`c-b7(QqAA^#Xw!?l 1Gbxb槑(U4:KxH2KJ"Ll AHǃ.:0> <<8I~GO<'?/|_ Tݎ=5J2cYDx O' 9 FXzQR`daO^_gZ gϰbqz>U'6 J!Si obk\6LzE~ 8|+Jj3_(Vl^~\Fau >jA%L+pZI2*RDD#- 2SPPx0`tNyDЂt2/iTC]Ue\v{G Ӎ`}49Y{[}gp:Qu PG\s 8Ҝ9=뭽Y{ޚˁ{A!g7qk//1G_d?P{V[Uj{#9IzGz_ylxfNd9dNʧRED&WMVR~&h..0C[3 '(.ҧ!,}OeE0 N!-.|%Brs6>Wlx.\tkw#d}ׂtث 31$S+yFJ2.5 %5b#($qK.ZX%*c Rɨ<2" L1z'?k?j_)!sW2ܾV]hЅKl&8^<|W?HN~L-g>n|*dkɡ_W ػd|' &UY*Wj Йj&]$D)'ۀŅPYbXhH= ]M?^C?y#x 6N~y)BlKmZB(@6?Umt WGZy䣿Qqy-9\x)6@|#Zt(7vp}g 1ث c.# Ȱ,*V $!GICࢀCԩ!p n [_ 3TܸG/z@ Dda'~dvrOZ@|}k?ny*ۉ̂W`e9 c#2&^H|6RȆ0o |%DYG]{gY/)p1`/ \䩌uOkAj,XłeCE+e=Rz(Y@AQzSw^XI2*Ixx˄ !Gŋd & P5LHKAY9Jd;h*IbF)Y ,Κ)ʢ*@բ\Lqx)pH5@E|KoչJP;6>%xWtmł;ʅwK*ߓ+Y!Y@b'10~<.CgQʦM">A~&w_eo9p>(|%ۋdcG KV#/]@+J s_Cx]⻢/+K7wA"]{U$+Iߕ,+Y![jp\vc` PR+JŠYq[tɊ{īI |^HjնW=G}M-OWI@#%K |&NB'K4"an-ګT *~h\O?Pb`(Bs=P+a4m$XhR(!$rTKù7O[aB-Yp]2l 7sK绋/-^?KU'jC QHRɠ$kc[!0仞ʶ?m{(|Oh;edKnݔϿ ll /CdᒍOd.=o~&یصl3/O۞(vpm忀l5)pUO񐯾X}G ܆G{ȁޟ>M{5X{3B/82AyDo"UAd)\ phd\޶ j^nKfJ3f= dΥFDVsV?PK\@'1%CpX<!)sM2t˒ɗ SJgݐͻ&u3oޝ7Iu#I ^oyϽz!HhmѪ[Dn/).}S⮘t< 4h;pIBdDW>~,[TGɏ5>hӢJ^8H)fҹ73oIߒN)|]<:Sݥ3ܥ%e ˗=| ]5a7 %oݔ-)Y~+%[_Jwy*N·<`#J)(L<-*NA9ZPggm!R_й?+FyOnң K&h7~Ue$u" Z!AtO)?J?v'gլ7D3'_(}^KEf(wKN*x1oyшsaCAK_s9oȤk7/']r%,E g'\L$qQ:"2&\랇p썼 7ESaͿ-^zWPLkŎw=h}՝ם ] ] 3PEGE_ř<|gc}}H6K2K|L?aqzTkxc|cz'goWgߐ,Of+ݞ'KtL7ZyJ&"܊^L$xQ6^M?Z9Wn{?on45$ tD4+-3PԮù^f4Ā#ZW3s5+\ K"IR | T (.ϛ!J.y* p9DD&3$3`AqtWr\{^0pgEC9?BrGs!ws f* Vjt@ &͟tV8@:w܉Ws\˞v3gm\xU`9ʶPz:YWÍ!`bq$\a2J}MR:$ `A2,?!`_31_2<'ooy%_DC<_(~y(_sGj̋)gN93\PC #<7`,|/y5)b8t?Fd= ݳ\˞_p% q\ Q<^;7|$Ӯg_.~ L∏Ia[t-"e Ad(J0d32 o D.f4lo;V kYs'{*wIDŽψA :7p``򕜙6՝ 1݈bgALWQDJvyV.v5gڥIr&\2|1@Go{ ZsSJΌNf:=H#A :15…w׼SVIcz>eY3,q(mY7Ϛ_v>_~S0+.L8=L3yOO >!xR8 y7D+6=Xuhj<2~cLNP3@PzRn$f >dQRf`lfoTׯP.? `GrzmO>Atړ@N9=<縠ߩg%.HF%tC>Ca{o7˕ GiM )ⓄATX&ER&S*CJfq#rTـIfql". A ҉/DMqÞgMwEsg_ʞr&ksp0/_H^#^Gr%ZXp 'LyƐ Kp2=O #,/{N~%X^޲9s/gL;>GzqIcGAsX0pccO \ι-\43!8Q.2b&Zɤjx̰0jVd<SG: R9]P.R~_]:YX Ry 2[N".*$L*<=ñ߱_Lg<ծ#&dހyڟqa݂f-v6ߕdgv=9mߟ@Nù`$GP<7 [Y a;Apy4!M!ipO6K 8!G%e~(tHEH4_1P%">OӉTkg$v?M}Klmki`Ne;p0!An{A GuoN#'rE&@v僚 w!&D s%q9DL6,:@~_FOBކ_ɷ?m_qY0`‰Dz@=&qX6Dw'Wu>aC¡'\Ȟ.sOb`B8v7xBxPLih_!E+%1Q|+y1Ьj@ q :ѿoaQb7~m6 ' V|9-2YD& ,<4AKi dPS&$3㘗#@wWO5_̝z&{ĉ3jp޼Vwݕ~_^ٽf;9L7EWfb؃c,b@7Q&KC APb G.z8!ͻ # r=xԱGuXiJ*(\LБYxp%x]yVNksO9Pf]fu@^ǃ@n3f;rmi9цp%f[ӛoMi#Ԏ;Mp8ܡT^yc' +m6(X\Hɉ$5$ p$/ceD+6|Ğw|-=p]0Lࣙ=du=i_f=-wg6ߝ|%owّzgZf83Ctw~<&Kd1aw_}ᾗ ݮ5WsOgO81d_JIwݞb[ZmwdՉLDn0{3:Jm-&SoJm1ŕMɍ6&5ts\_Zmo+GRzrU8tKcLWL,q[%@2EB34t:Ud V<LPJF)X%cAل_ cybgxz- g:}OJ]-v6ە|GZinpkFi·q DcH}RS ߌÞ(\*KNs''2Cͤu\)5)@7%ӥ xa: 0h8yE7O7K89$3Zؓ и#-9~n-v;:s4ciE$ߨ{.}EOs<:V)lb m<A90_lSo߰qD08i9@# 8_ @yE/ ʫe~Dٗ8`WBm ķؘ[oNj)椦$ܖzwjY `o,yNa^}Q8pڠI]~Ih _jCX-.[]Irݔ`cb.657둴.yYahxn& |2 ȼKI TPik6fh7R"bFÊy3h)3TyYtd:B~>F[ӟ{`ƥQ'N7 IM@mHsۘhczM)6%5ߜzkB]$>6J/>7c7Iw͆70*&S(jh3ۡƭWba*2eKAXiae=˵V`*~ZR&%rJ(f2\kt*H{FQ/_ӥw[ݳO/ymn)ychQ~k'~y.eO:6tO\-6D6[tuȪ5 ׄ6Ztm`M!@67bkh=ݏ>*0ϼ 5_|==gᩤbm9›h!Fbt]hCXMEtt昫3+6oy"_w3oq{zo m6&+C\tYxMPUMW5YlBY|cPmvFt?8|+^ivzKB)B"& xL)B2Q@%8E#:]f}G7݀P8y啍sQ"4W),5!|YUpQ_xh%]ŋTvIZ$)R\1( l,4K=㱗=OOen; 0AW,p|{|n mƫCֆ n&WnKX񄑗3gz0۽uǿO{鎼Rtݑ}6_by@_,늯6^x&+}x_~P<4jμGM ۱7x)MQaB:^@2[Bő_t{K=: CZZ"F+7+\t-DtܛOd[t'7bixXA 4)lU4PЙ(VYhTPu+z M I)9|"4aeʈt)&SDx"|t(:P7O$o->8b\ *|pBY:m5hfl 3י)+>Qn2 "'ԇ,|5) 2hUjUq RE '4 +dzVeJAl'KN$qYD@c+ɞ{$M{shA W^ܯ`c ~9qY)_Μ~'osOP[a;Wٷ*OM<7pʿ ?_/ş-c z;/v\k_w"iu't' wiw:EgQ߳Ƞ*8̠oɄw,.\<@=K9s$gSHߛ.oįߺH).iܻ͖4[*B:nu$mżٷe+υ74lS"&[fh*!ì{n\G3?L@BcQqœաF=%[s4l4Gf*IDd> ÒoHy ~xCɊgRF=<&xX+[WoE@uYu&w3Ldx`#-oK(|G95:k%i A)p^"?~w ? dw!h(OA@D]x?edH%z$;4۵E' Ʒ/u}uZ8\㌖o.+kѯ>YLwv8$|Fa=?w+/eg{.`.߹}pޛF޺{`λ:sמiW%_-nJ[:;R{` ±1mB~I!}SȯIԗxc,:x ,qܧŒ/M|q] uyr]-Az5_z{"J|Knd y+|mfcayx%MH\-TZEjpШ)7 E)n%U,<9̵!6@(`-(EdP;,Zj*#R2p( rQ]qvvףR#˺o͗~quz Az˾,dgP@q%}/@e22 pDBKT&x"?*Iy;~þrn=[.z:[^_ޢvuw η՞'=_^G}2t7{'`)XX/ůh@uiX7ku5g>un7u{Mo:Ap᳆ןR϶};y"eҗZ0PgoCW_ t__u.m[[-CqYł?oU`;gjxs_y-mSOLw7ԷL,HEE[#ij:U rjasTpowH2,@7h͵({"kH$fRQƇW>i4^>=Cik u:b] ՄXEd@:kT4v#^Q(E ZZPqO5Bfs\4ƂS3{7\1G ب *$l kˏLʷ?m4IAf??i9}2Wmx$vص//FwWi $cx ":K'3h.o{,9;z_Gxӟטƌ'u?j0AwN2˴ gv~ތf?h0Ai=?g q[`Ġ+3׾U-| X})y!uXuKǹ=y9/jzQ}Kn :u}7>ĵ(~<:AM|"QBW ,UQ+#Rg('$Pd"mhᇊrEنh_L VZ@$x!/S/?ţVm[Q#M{p{ԣaC~u``9N43=fsve3;{>V=sX5^;IMyOkyP{=wκ2n4^||5u+N_#x}ΤTB>o5gFV`hU]Iz;YцLl(tV. 6 %O?(w?8?y>˟^ќ.3or3nwθ`So7p{ns4[ӞWPml<] #Ēϓt7 q ytj>&fSEL2B ]#2)o>xg^}#oͩ[|-zl{Noמ|ޔ[ '^k0rIW&_v|d:Ovwrrʭo9֘w~p4穨>mۂGgܭ9㴻]n:FIݦtv[ufxԚ<۾^WgK Tdʔ%%JRZZ ca:2[:eKI2Hn aq=:3L G\2؀$3Jɝ$rV _qjȣʬ;5gެ=F7]glG"A簱ylNG&Ft.JB&:JLfl*Ma@̬hQG9V}96=ySO+@AOW0"q4 ԘM b"uPi("&'b/BM~0/x9kK_rسNCqް}v pö;VkZw8 Qgv t~ v ]on!kWg:uww;4FG /{tnG^ǘ?&?aYD *q,AE8eQP 'q??*En_mc!M&JnFL4@fNYPPqԇ챷++F ] 9^uؑ=tus{iԱ*V^gێBxV{jYĐROY_>rM|f fG*TڷOfD" 4MZd4\F$G?#73 qk ;Tij.;`o{]sCU=XyԱjKřW~̃&Yp{ <.FfducQ[v>W+4XEt܌4ZQj3(ITcR<-xK7ӝWD]ku4pGkq.a{qTs`0M<^g"!eT6 :֧@Hrx([Fgw{#=2׾՜ nRcdHb!]IFJ3f]&y@r#.L@uLE TZ>rH6ği>xvmQ#־m;Ӑ}nvnuusVUg}>*YW}9][: Um4pKš;*Sq˞6Ŕ%_h~0!N_fl|akL6sI*JP1kޖoJaMfmF *ZLΣxڱX`bP\n(ȗ9bpO~_ծrvU}WV뽪RT齲jAzο@ogu+ \uȶj8N]糱<Wmzm*k dFr[<;̸R܉\Qײڽ칤/^\Z Ȓ=T /W뿲uN=UK6~*f-o =c"q &4O%@@F2JkJDiD8od4].P&fm -@)u6*3(7 |Ğ?>]}$x|T۪ű溽ヲnuuz-?Znn;v暏cK!G>#'&RZ6QU~QAXhm+w4-<&l95Lłc,oNz-nmK5unuuix;2lKOڽ҉Gbd`hF<6 "4U⬎c6+.>hnZ$KUb!ONX L@+j TL9 [6B PQ'A+ i%rBhpJG2^k烰S!@n%vѦ[eVbx!BD|THٷ}O6ᆭFU=;wW׼:빨uo{Cj_~'0/S,2LK,rLmUlZ GT &̠6dEp}:#3 +T $"3hixdxx+އ5ӦMgjSݖW鴰Zׅ5V2zY l}Fnw]Z]gW< HUΫuSu:r2A׹ {.muKU=7Vܔ+57~h}2j`3:P[(E!jC*&ԇഒeMV ­@Co 7$B+0lPѦ2 R]KI X8DpWS2ɽ~߃Uڭ/imku[V:2x6걡j?]mBVyr9zN~ߥd4=o6S?-* l dnn4jVd2*SD ,'?N{xsܛ U*ﺤf/Q:;uYVʊV4xOՏ;T[s8=Mļ2,Z'4Ī ,1™!'u2 4@ 6)Qѩ"2M3^ H]Wu+nKOg؂FqvE5{.ks95;̬nO8tWd.S]Mq2~{ΩmcU;ͨqzӫ^Zf8NYq:Aϥu{Z2֘^߁Wf>mByy=ξ!iXtdlJ\TZI-DQn1;:6\C%vm%[L$"u6t(@!ŒSpD,X`)0㣽BFւۏ=WzXn9,c~n w[eU:To{˓1.2 !đOpDOR|ܼE:Q20\9 nR-Xy^6 vy {K ~љ8A":!#P2buV&1۴/Nbf En:]IP(&# 1Xp;e>Bdى)޸W9YY gU42ط3j<ױmfTh[Wi;ji:X'6jP̈́j&Uj=rI;Msj7F`$tS8[yØu{e%;W+ۛAx1B !) *=5Yśx% W@o/uLMʩD)+$2d2(?Lxعכ긨|ǹU̩ VqVvs[̭zqk[igo=?J$R0)tC94QlaDP^%ACʿ'i/P]}yRŊDtV.(OptW^f/shءfW8FhE 8&*Z0`Uz^Qt:p9 {J~"CЙ*:n&2xf`f`(Kj zSF1*R<":OCߣ_ >N?m6nؠyƞjnCye^8|YU:ͪϻlj]\ :.2mgVh;z۩Nm&9fsqNl5j[+vB㪴Wivn5ۡ2T賥6v.j`;1o@(i<)eaR,%tZX)܊fhjʯ[Ł%pCq@!Q\FnepdNYXD*= #|\x};cΏC&lsM#nB`ۉ[Onjv3ZϬj^KvX J}n&.T nF!QCdhQs,|Rdk=b"**JyNWiZ,%r$3"C=0] ?v;yciueٶvh367k=Z1M@pBvP~Cg>E"?eo bvU`HqDSpЬWx2KKEPËx'[w=#j1s5:-zn6s0,93PP0Tm9JU[ϭaY^[~͡f+Z嬊mf:ޠzo5ƹh֣U ͇m1" Uh;RLUݼr-g;[\v>%zv-n峼5{,W-L@wZ21d5c3LYX-*ce-\1xWFJo0kCHXZSB<c m/{k:o=Bi:LfBc*_ͤmͯ~NEЌ]V:;Z{ǡ37xjNYgؗl,4QjZc1YׁY sD)M[q5DXIFYxhnӋ0ԓGΙskU"WTfcAfg-'Vh;\eGq3AΆ7} IT+ED4JhmJoE Y#`KҨ GjJ$xؒ"AC-^OE.'m{-*mWm9b)AMRğ[M(jrJY[L鴟Zέ}m{qusz,fCә?5^T[ l=ұ𪭆Ul9HZzD*4Z Ui9r άrカm6>|1rƣ^AĻ7NPtICZhfPF˜>8k%9fgbG;MhH3n3iXmFPS8<|pY/y Ul;J[bd#k]͸m&VLٗ>afO`n.-@;@ chm¿/}YdYp6#)B9&2hXM8u~x٘y [YZOr-ǖi>V#+^MVi9jqOӜ }U]ؙo?NoRQy&$D43P#GD-EpWg,Vo)RB~◘HbqT,$7^~x+{˟x^_[\$On\emh=z+xj_dVs:,7doyۮ{`lAǎ7s)MbBcj^Ő-Wi5r.jXVC4\J͇Vm9z՚ zRvSk .rZnf}^#S>oJߏ^Ƒ_L2&ktOB,Xifu#'o?MUE48HdXɚbELF^7o|k^ @mܾ}jca[~2 vl)vSQ3ivx[9|hR*bg)<-00Z~F7}BJB5iDQ~1+CV;0{7:߱ń|tf4Z-h6j!Ut'9t_\iC~ng-MH і`wTB=~v8-rRvk[*mFTi7fюY[ul3ɱꭧWj=.ʍ:qcn ϿXr[XeO:?RrMf:4S Fڧj-WoѷF~՚-t@&+)߸ofj4PӵoCxX#+Xr;Y8wv.|ݬo},'YϣId2pO$$^m&+bžb6 @\6GI-VI3yLH&? 2>5}#q:t:c*]pVCjnSۡ[ -ajٶZq&_bGv'*"C4Pl5ʠRU 4;V  ì&\$ߒO۶}AN f5Pik1l4\q?50`'.~!|5SޤQtO"54R: m( sbHkrB0(#(Ea:" <6ɤsp~Kz0G/{zڝbCI:v$<|\ !đpts 2EEdl("aw:?X 1*w9S+ib.4(@21(GFML׼-9t.Szs>Nmhѿ|Zwh8s v}PK}&|?{}ɡ"Q7"W9Rcwgl rc0͌27DJ$ӈfo F͝}uM[L)͇TB[i*MTkڿHGk<ޡܟ&ms5T0w Od8+%KEHD4ۢ& a}gkwS6l|9M84S0<}ʍ{Tmܣz>4RrA1HwE"NLd˰<-؂{{ Jˌl#"@-S:" L$A;XIDAT|c̞!'_,{6Xp(pvldcʁ'jclݧF>`lHVc[xojH\ZS7ն O{Muppd\{hһ2\Wt^ٵ[Un5ܺiأ[j*wA:(F+;dgݎ?zI ,,&'Q%~a +2XAU&6p-*DGPIpm[ɔ7~TP*29j&]JfL<* gx'cƷ}t Zro4B՚ZY{VGc~n4ɡT;kn~7#cڱ'_H`*P"5k`A7 .QK4I2oL4g߉ ;T6K&94^VM֭kJ:WuZY=*6\&; ]{>kO[nӯ L,4OR5!6hh(+*`VLn2Zz4^ oT$/q(Uw-dK.$L|F7WjjּgVj3p*5WZ;yR@n5e`bjz)*p7rVn6ҡ2n'vҵbΕ\T)!}[cnTpTmH6|ZkO;ψ+_{k믄yxh.!bа[:]lr =\(9e(y ѝo_o-߃6eՓV TLϴD!w遷+#c^pm=levh4k/tWwѨsu8vګpFw谸τNG8C*=Χҹ eTƿ/cdQ&7hf:ZLM&H}&~_~áTo8mO+ڳ*܎]*u֩kM{;]wS593|7$_%J)xFI0*xe3ccZVή۔@!8 t\6F~MރYxќ{%u3mڑKvٕFWrVrWɥWY>eg[y?Ȧêp<~kL=dLJד<{k<`bi~c~g7ƛĘ?FXZ}џx {ِ٫a]G8SŭoUc]*\~Ҁ{X[Y^UqXe@n6m`?`'=X^~R ~/4Lǿf9dB# U(yb嫽|Gi;}.sfVTmhBm;zUX*Ⲉ" O;r5iGhO:*ӠwVͥcu5uuDoF+uh5lu5~yjCk`Lix/V-BB+IF\|Z̥"QSu(~p`/ӧmv : -һKj ViйrvڱzN5һrAe]9t[[unW2nnizyeyx x+#rʆld :Jm & 98Fb' ޺댳(dCٸms^ArVh2rWl8LaF840h=OO^Bpwf܉$k90QjN5~O1}Kļbב@u~Jφۨ\ q֨wF@X^rP/+PA* :VߩRΕR]íO}+]Se?5\0\a$7ϡCLIjXXBχk[|xvoVU_BPg"h+|8I4̀"2sâ͞AbR9.t׽l궯R}F5XYJMWh6l/TG!@y%fvpV=W`A : d2R<@xKޚbݫZ-9[~JuTFKC*5hWaN3uڷjnFt7d[Ӯ`T?Ӕ׹!b&!2ܦDؔQHJL4nL {K< Q%z#u.nyUpexOMװKŦ=k^hԣF~5( ,`HMg0Dݍ/zDYˍa8& I&Eó / GL5^֟-9t-vն#&we&}kAڮۥLN?8wN2is6eVצR6Uw۶zvҰg˹ ([Cq?u[Vc!:qW2fRQuƵ"` ۵\ec8B%AhÊ~\3 j}`cYZx>n)̌.cRrt<*g9B\̘:uU uz98w/ӠGUǶ봩ɹ^{hԧ[ :tY %bl̓﵌hV\3_4eiWiy4JE T_o=uML-tύ%UsyNWQm*뷯ZCFhÌ~0?J4xf`\J(l-$J V!PY(qQ&~'7.{]{gFaЄu;.uh:BU]kLʸ(hP5._Gz]߹L?iPOέiYƩUڭ*nUɹezjiQŹe*6h_nv,18]'8Pa‡ʞV┿Fi ! fpRZ\rjZBx4,_ڸ]GB6p yAysg.g' )-0orB`"LB,: L$#,/Qn2k^W;ġ=u^f-+;^Uzmk6"^7x ONUw) {HX2 JO[ϗoу0L @JLf t eM oSラjݣ]VwR4 l?:wj_Pݖ,נu9YTuO_R'g:&Sb:F& 5H)ͰjpM4x9z*MK%HTa I51Nf>FLh}mzeW\W-Tr[ݵS^U]zkݡa7..w,ťg%>?RvqIّkoyd踇֝n=N `xH%D}1cSPr*YN9D`gA)8c,tKsbGCkyycPoO{\O :uiWn2pPuV[ռ0gGվoQKP-$LEV[`o8?@3aYFnMhJtd3/k=Knk6XOT UuW߼K˲.m*Pٹs5Ukv豾O}o-<b~oJ3Zk2ˢ>VEx%k ˥ '`Ì ׾ V\3[YFVpQAך\ޥϮʺu/ҵ< u:ޡʊ3.n<]I{XnDO)O& ؝Q1٨0'\<jh xv#>vn6qP{Cҹ\6?mse\Y: tlQVN;5/[YYxӹEz*o]~ۊ*toWѵOE>(qJ.a_ؠկuk/~ !^dz>t2p(\ 0Z: f EҎvb(b,Θ (4qSbG_p* Zr>@H hHg2Uɍ|\0\%Z3E8#_[<g  =H-uq\^ UwnQֹeǖ?9,ԺRZWtVέgF*RqƗ"=obz* BPR6I\\v2\>f6Z*r7CiksjPgn:;4ΡA۟]WlСF5vܣcPVx^KH׽5 0X_ߧR߲H r1h  , MidSR W@m 6h qGM#glz6pܾ'XΰPPEe@`-ʎUUը|Fxqt+%Ff?9*ScYgTJbvQ]6>y)vsÓ/곡G@-R,^pttM~ZZ&Y fԂںp6cq6 c1&&)Z[MU3) *:YE*BrNHT,%9:FDsɋQ0*&^&h ?JCjhnd p拘dtKɯwG١kIkaQtܦJݖءfMUkRF `-SCN=tXt9GL1蕈V:JF} F7!u 4(u<:: *m%F[  PEK) (R ]![>!>73[_ʤk{ke 0^TYmGQ[cx @L mOą EF{Ս/Ou}}hԧ s AEh`J }i;SVskKb91H0\;q׽ʟ.lS$u"A?Ӯ7^ <|S_WG2>EVK]qμZpr]Ŧh8$T]P6|*ָRKH\ [!u|`Y+,u֊ Sq59e~xS-w*vO>? ATQ_"Yb';OB҄T]LE'YD~Hdݨv}> UgŎRmP(ծIk/w3Ux]ϱ2!{9e;AZk)Y t\9[oԘf&5@Z1ܘ Q,5@d֧^^iS_i_k^_@/6WbmJzcz ;l9ʒ 7iy9ms5B%hai%c#5ލS}p[{.`cZѝ   $h<7{p܋#\>CxbKLv1]nNdRY&bcmZmXUDQXmU%År׬>btN;.L/+t#sǝs(Ra!z}IwǩwjWD=ӝMOQr A\Urq4%X7dY$CnDiS?^n Dw %]N<ޏp&tΔuz"d充/5`.Sj{PRTCP3W挷l ~xΌ8j4fblNgln1U^潱T&Ƒ;Tt?>mw,$h"32XĖ:== UD:PE4#JE!="oȏ"DS@z}'[npqR5!yz/^`35\3DQT0( y*CRҧ7鳪 e7R}k]+]:0"bCJ1P`3>5"ra9Ƈ2eQ#s1g"}R!ԘUf}hA\rJ|60S/Aq)yзRp ).y']Nws]4c_;~>g? ]ڟُ>SW]Wh;pzm^n$N}9aِW/Wk9 M+mn."WyMƦb2QtShdc`&DDә$$Ӆ$%R5)TMTE69OZ|ezk},c)wL^IAjd 6<2xH:( @(J=hB7$p%<'68ԏc׃b{2}w+RH1^1=xm0eïSVenAρ}0 ԁ*U7763)<2qw|3fX${2ح\#qaK( t :^u{٢onW/9 O"SwQkSTiY6&SarPPӦOe=|޽s]>#IȜ$NPD~$|Ŗ dnvN\@r<&8 /t=:t{˞3MšȅiJ)5eBk-o)uj5D+*Z 0F^ޭ 8E0E/TԯR6o{.8ݘ]v>;CЅB=BhF!מ̱#qI!OS'CI:yOA}EW:|6j[*/%iT=Ei.1&@Vb6z6XDA&~OQIDݽD]s͕ڋOgb'Gbž?B'm__#`GN^܁tCt)6^1'vi  A5)tI68zdaF~:|vy"wĝ*t!AJ929l#G̱)j;ݾ[G }ͷk"_/jٔYg|{(fVh+eU;Zp1BR*Gf`s_/.mi8,}$;1&KL{bĎdHݨ/@[:u6gAgݨ.&h&S暃 23/gCov޾qK.v|<`! :xL/v8|$EA/rWK`K$CQY{=;wi7ʈj. >]bnqH[ I\m77V#g4|F8QX ]PZk冀 ~%THY|\z_Pú dXvs`)F1%Wd CU@ 'tDafTW-~~8u!IX4+Utu`;מM,Qč?#AZ\8Fʇ[geJ]q )Ot?wEB qZSLthOf/wo/I܇ 0!Z\ @7/cAdIϒ xx&0Lk3 i L[i+ U#UlP`KG],`~d},/I\!dBGL{_Bv}8}s37~9JK,ͣBͳRmB.JU˻^7Z0u-[fg;@H8O&(mvrcshL}t>8pݚu4KZO6&!ao$䝹"/A Ih%2܎%w&Kݐ nta|8+Vw4}F 1u<$ՕT4M D&0U{>dxk˰]>3{f< ehƠ+W_/[vtⅧfɘq=w%ja?^xЏ 6lG7?Q{O:Wڵ/tGҌM6.kԑ $ A`zSg{kJֆ4݉]~דx%A{Qd,3EH8 ),{GB{ 0R+MA1@d.t5 jvdICʨ<9e 8:P.HD>dqSԝ#A1hUw5OT]LPO\HԝO_H4O051H+T-Xǻ oUοf'LM?=C'ћ݇8h*YU>+D _%F0d-o6}sOgOgMQ q3$5|=k __B{|g%_bstM I.RoV# [d8+bGă)#є^^N\L{8ECMBUXqYmmW@H c &sE֔y |9p1?Y/u$vnl߁ɐQv8ؘ,1rx yta_r_yp:0DKrs͙8P+1K1Qa?ߩXy9c=7l9 $[CP⨐#se2oԏ!쌤rc}bmp(o/㚮di# 5I mQ6^4f)y:\=ئ،m6Z><6s["F!1 gy)e2`y=ڴf쓹E+h ٙ$Qn댸cAQ Qm8ʙ8:2CN7~,i'_ԗ% }a}s_U.Wnj:8>Ts(Z{(JszohӶݮ]ybW3gߕroOx~kp;ϢOy~A4l?,J BA1v!KG? @Q%hϼoxuhaPg*]/9! ]:|}eH嵈ƃ.3?HC3@D(p@|;2C͖ry26VT`gbW/$ig;ərz>0DIo1cT"G+Pn iIh~H}{CTWmRÉy;'90h{2 @.HO5\n,X 5qo΋#3 @neHzuawm.6Dk*ٵƢz#Ъ6l[ٖ>$f|;bݦjUV*ԛawƤ|CLa h{5Og,KB\$ܒ8#͎ htkO:wbԑk熋xe~Ȯ'ߓYpi׫^zTC/;}}WDŽmn#Y<>G#IN)^XB:cB$Dv·E=Ν+H"OS, =bē';%]+ {#9C87\GM{cT3L-Rsr6XCOފm:v=GПL؃`mSL !bElXB)M$GRGKgH+TmX8,mL6Rna-k3R`,&H|#2@bW4q}fkJ9ƚXn-<-Ĥ鞤ěCNߪzjsxZ?Z&F|(Awa怄T=!АBg:FEsDs<>E/ [CVNe$nI "L[</ܛmt>8`ḰXȡ!XJ|ϒ?nu?Ni9Lb"b llZwctG/޹ nLdrđl d YH_EN[Væ ծX4}`Q.;]J5Δ`V4[ߪj5ﵚ[ .r$me<{bNmVoU7M͹)ք7WcJY&cu*f|w0't1a3Ta%=IO2P=X^N c8=M%]z놘['H{ͽ!ᛅݿG!aHF^']ډ+f <8B\7|9s79RNT# @,ukU k· $I=V R&q_F~{fb QٺOܯ~(uw|Gx! #WAB [H'@H}؍/㱺`4I4]PGj5t[``6'Sm-8ӵ3T ņ){1NT'=L fp$tD ф! \(u\z,/~C9z ogL.d{'5\2G܁jG|"#Yɒvn9NBl7PחJޯDuT&` |q-NVxڶ 5ajjniyE)mujZ\mɯҧ2ORAq߃~^áܹC>a2bE#|!Ѥy v"xx>$twGgsG,}uީ%z-kY={.SnRD1h}^8"W.lÆoGlda̍)g&sR:O+Q;fJ{sNBi4|0R_L7uEHD9,1ẃ߮>?mʯ..!N@gߞ3"[XB"H a5'{'ެyX~g6VZl6ʖhOܿ ¿ŃG,xX!Q!7R^]n:1<,dTڗ.!S4!OK=ܨ\?$>sǟxV1ẗ́cHz߱;O:bʻ3A`:>R9I.Hd$u *螈 54H?;Vu@Ai/$nhc^K6X^7X**kΪ7M-OkNb"^ҵ)5DlT(2Jƨ4Ý8Ȧ#;V}`򒇃?kvC| 𐺳 ;9NA`"MrN<5[vSyMsN/{:d2Ys;Ru(fџnv EI4!4 AH;RO;3a '~?g'g4pebwC,ٻ$.T_rrX|9 oɐW}3>XZ8d_/>~KXc<OIfCΩ4S@"jb'Za;;-b:iiRXk-*s^[6~TíxH5?ZպGç6i7#Q_#^ 'qw{#!k,W!Ʈ!m'm lϐNݿyc ŭ.XvGw =('9N !iptǕ Iu$  QSQY|&f XbA q`Oq*cjQެ'%3lEXv|UD2$S/Nw.B{f멢kn =םʶg\9@1L!c3 aBkkU#T5– ,%OnV.9׏wg#m $UH >>@(ç]=+q+w$ꋸI||A~@"Kn,'Ƴ?<< PК"cէ7p+1t?z<)o.yPxT iRIJCXvqdG;ZBC> b $ r9BW`J$܍fכ0_NW 6xdzxKFS75C;n?ovi<,;6SW#O dLX3 ;S͒@#73 |:W0<6%t_k:@xMÆd;(wj9 zP$N>“RA )g$&\?4x}{ΩCWM`1#f''FB$vBB9ąؑuq=loǟ"D5g.MOeϸ^QauUw.D(ƃ~۽7Z>yBÿOVmk-Fx)

||| 89^$;2bˑ'Cb8 3fIcvOP0AOOG4W!ܞSfL4%TSL 2[%ͅHO07q4ac^׬6㙊 7lHņy4eH}6m[|ܽ)o>Z)G=FmI>gxN.Gwo ,2AWŝ\7 ߙ9O,l"1 $[4|!=t>W*^.HyB^ĵ yN4L)P8 82Nņ}6.kHUi2!q3+6.vUР N T;1b!㰹 drA8%c,W'A+ÕSUw T1E R}r{uv! +tBB Oe!]Hϒ+C|I<)r?Kf]']Gb#H\?Л%tc|](fH$ ,&n#.ވݕGvDiO%}{dm1 qɪ\aKZr,oalvJ~R_!afbCdnCC3g? =!ύqrB`K" O0%DIt>p0`}6={X4CԿ AĈ _<;>QHk1=_xQ%nITHl LR!l 0(`&5|#m߭{8QC+!S?PDJÕB;o{wa8x `:%pzarEH bPL\qcҞ$ag|cٮ4#mπÑ񉥈"a;BL>TG!+k =_iGtO8̥2<,G平^nO79θ^ i> >E˦9D ;Zɇ~Xd}xCq1#1t1)rD2Y\C -!_FMqUpyoymywk3w Q:^A1XB&MD! !ahL9K2$qzvuK7>pExΈ@X"P,D"qqb ? F}=/θYcվXڠ4|óW| Zmʪ7+M%ZsRMa9b\fsm|_;2aMl3AG[,mVsk;ZjKRYc|Un~\tUH HC4*v]B35_.^?Ey:/k.k,îKʹ[)#$88b6mhL!,4ʟT6(8=iB&.[ҹRGJ; 7_Y0%esn-#Tmxii όk=P[H֜Y'P.Xo, -2\!Mshֈ=":Uqܗ g֎@G;fUƤJS>dBMK lƕmR nV.ȱ]r;!Pb|C5M3d=bhtE2o_N}}{9HLX% cA$4/K2{!բ$4blyb2D5cg⍷ƨ|Sl[.th*-u*YeVdѶm-v[-m b BO}Gk^랤k')oƪGWﺭrqݥgʿۗ=~͓^_6vH{8<.GDkGZ8T9r;? ?~#|QIJGT)vy؍04hcC_}hXN^K[A »Lg"Lܬt$uᢳza{ '8z\ 3ytBC8ev?6}+Mr&&ߟ1Fϑs_Wm Ѷ7 :Z{j}~ Al `JIT  INݹ~]:D,9w:$ K1qٻHaY^ Ɇ3Svyo4\w;eV!$C-5'V6Ե4iejYmSWo7A^B8мTbXaO}ef$n,;/V>Q2ugW}GotGuD(\$8DBG, hH#.ِ@&qt.aQ,2 A+A` }_1L>!(O!#)v'Έtѝr2}X> Qh&eKuݠ~X_tA9YTxP /߬p"8#\1_d-JeQ,Zil*!ǝ|9" '8|({KTטҪL봭6P 2CZY.^Ò߳y .&#yNTŸw(WRn2$qqmfvH~,FANACĨF-H΄OrI9&=gh*~1BUa'S׳T}ha&,G|RyȐ;Nj,1d=I78 D@IoF@hq!ϔ2=>+oN;9Dv<\c)G֝m ѝ\ "$L!S  Hj'8q^ ? Dg?CS.[tn#% psͩtS`1hT,)W/٨ԛx$l^k~hyh~oh 7'2a{&A-ɪl-o3WsQ>!_Tu&a-Kol^c~v6k7W߅.q9p e+ w*l,LdEa>d¶-erGP8L؎=yа?lx]:NQهݶ=3e3o5 VU_} WAK3}m/7nhl)VThmV\m~@ c>?Z1cCm^4* w\y;ְG2]ل>Y#"Лq`L "@x"!¨|jA2(\?{TAp$ɿd?z;@\Q( qd`~"IH| ^t/ɮ7Dn?)7{1ks$]HqIdBZah*(SB+o1}.~s7$ȁB!L4Τ1XLFd& ^̛ؓ1{O]Zg ,T?6d^gh7ZS+׌=L񃶦vIކlD*cv&iVdvʕ[M|Wdޛ)b7 l-"+k|@&W𽐜ɔPhEFp :p`> X-{o˳'JTkUKl(=cH|gN4L7nO {a4׶rLu?ʖ?ǿp2_q6۾flSS@ږ7,4lk~i 5~дo$^zg<}'ڳh\o*߃ܝOH!0k`:#:Eg!"8"h2㯌?N%*saL2C3!ˑ BC{#bIq>'޴SN›o=x"Zw.V{=Qw/Mчj 4Tݗ[/gꎆkvݬlW{^r D3X>tqp,.ґ/B"9Y{#@ҤmݎϺS*ڴ'x.[DR+3UX*Uz:V:󘱁c|a3Q.1_jDO0djxZL*XM='!NW¾z2oKS_ ?ΝƗ =qt/d3yC$z~HACWp7mԱqgT?f⇊-@DS7ֽ(3$WJhJqqKs M%ڃb *0[ F)"*ÞN'|1I"O\s': ԡK'_{kog\[v~ƝњշR!:[B0G(My?E{+p9F{nϝ' 譎.  7 8B| r&9dDžd"$ ?rCy<3M OҕEda?m`nwKtu_\nz}Ǫ@&%ogCJ_Vj qcD[ ؜)>:ei?5m,Ó[Ĕ?GOVd YcSejz՝ou<*艨\;@Ȕ[Gb;RF qX ˎ%L%䏋At\smN_>1SR\L$rIdB7"\GS{Ǜceq㏽yja-_•OP_NR24a\}D6" 1YDzw狥Kw|1q :&>劸~tܠħvЖ{l!ydQD؁!$!+}rtyPX㑗kRCfuO;5@csQ!v@Q`xT[ _^4wcgt;+~ٯIwQJ6ԉ[B[p ЕvALW$dQ,֔~#GwxѲQ'ߍX7zò{[š=i<x)Yu+CyPbx d mG G66۸({}kv_k^ykbq˳ ]x (ő[ekZv521dq/LJr!\q [FeIl1) $`!qA{~F@じ4>i*}!V!es \<wכ-Jsĝ^ s_W.Vc`Ơma{bT4404yLMKMp3Ɉun[N6+D3kOI Aԑ! W]3+rd< +=ϦA_7i+ --;?΁'\_W 鯴/sUژgXuq 2}4`WO*#) fOFg`lP.xNNCWg]K򈭩vd ݝ=|o A>>R> @ !Ct@ "7ځC#ڛONT88N"xQsDPyx2k~>z#ovv΍Ƶw~y5iOdӡʋM3U٪BuD:*GNQ=FiN=Qi|tISwG>:!+eJ A#~ E@∰N5x!h.Cm~-p3Cؐ\ṋ56Zʵ-UHN7j¶ :-= rΜYK.ԾHWF'kF*?~GZÊso3f^3GR\.cGIl'dG&Y(ULdB)+s$j:3xӍ<}t>̜Viɭo)Wi:¬jP㒿ߍn_Bl'Ӫ#z|U!4mpf_dg:).8r")"7u M DGL>V% M@ P+Θ<\/-#' ,g݅Ew#}6+=W>bzyl)뿾s]f{@DcGgSR/g*ng+2|MPݍ5]y;u#IV^=l@:W3\A2a`eU= |?O# ,Q$pe;nҋ m==/gT ̯ruK̟Ӡa$%hm65YUi/drfh鮅+8R8sOXQK)Du`RĈ$E%@Itr|ih]0,s\uVF}}u6|T-k%3jҠ~y=J1V{;K^{ZbL$pWcyՈkZJ8liR2[|9mmxTP˂nxdT/bKw=~(#;Gj'tg.]$ T6BPE,Qt8v *cڻ:#$Xa/ȅ{>$+y3ٝ4OՌIۯ+o.zzOWL9_?J5n7lx%iwpLrzFӭLŝLtݗ;qѪs4mRK\){Xʤ,>>UNI;C)}xV\vtI>]-dͷv&f" 4/tZJ4ՠNV-@=v:@\MDASwj7,X9bΟn&!H8l1ǗM[^G.ρt`q=9,?lb7'W?>A0}"h< z OЀ9DP8vկSw^Ql|^jN~kI)mjPiZ&ܲd?1BbQVi}O+6ƥ[Fݫ\̟n D鋸^,+.](dL& J©I8n&pUC&F`0l4enMxD Ö2>^r0]L7ˋepnaEtS>+l3.; |vvڑy[f]CL:jWsխX9T#i_ϟyRs-Q{1Vs&Z}=3e a+q+]6_ȃs;!@~2gH8nbF-s)x~dOԝR'ݯYT,ͳ"MfրuZ*muʖ?6ѴFE<B$@@ڤ4+ YeRsb.*C]V mXta'4* {U] l&)apŸ-L}],Ypf}HDͭ,]X!"WU}mLhΫi.il.WTkZ-x'>"vjh!-(gh7YI7jw*[s'#0#aw'O@H \Ȋі>3pmH8 &ryb.W-ɀsD SB@Bsd䅰n?$A*noٗūnKj[k#.3:}su%E6?y0e+ު[Դ)\ ؆s՟לM2 WX=Dz]/?y:2$솯=xP<>6)&#շ׵}2}`)$vg>s^ȟZcd!@FSPhb}_҄> !jj&`qXjSN.94SR{7A}3HH[e L[8d.Sɢpg= SjC [nK)bU,gPɸ=Pih|6"{6xix ofu"a.v\DBؓ!@0蓅׮Vj:4Jq旯5֢v* ;$[ڣO-F<1XLwv#)4<ǰ&sx 8Lo.*q@ЌK0a܍xN'l*o 4l%l)⹿b'K!`r籇lph%wz}5s_~}wY3pޭ_U}%k6rq0w⵪Ew R+p$OuGj7S>fs.^ΔB.Jɓw\'C&l!AoO4>#qnXxKvGNY֗ ԋeRkյ)LgDσ[vnɬ1]-6>4oQ,ZΜ_mxcH|e|Vd2$kj.e(}Ӂ)˖z6fKhHݡ'u{?k\{q钙"M:(鵔$mnH|:"v(x>ɣAb?+: m dߙFMcg3n|;jyJT-ӗUZK-|v*{-zKЪԴ ;@`ʘ7=2=H\n< ayGO^t4rRmax,)%a3%4,% 9ԅ G ]EH/l~} Qe~zU*Ȅbnʑs$2Hƀ!r]cŽ=XeB?Ӝ^H^M` J&cC[bYKls>1?B!A> <@7{k :p\L72ӃIJ9I"~3cs*_){s*h]$u^s۹]1\&x(śAp" ϐꄧ9/緸/ZX~{-4)7)7ier1tAvb[g:67Y8<.d?hv,!߂kcLD]O(x.< I[o6+mh>J0i5 QMdMlVxKK֜_i(3&cpd핧ʓuVm;xmدv ó^\@N\; g cGSNl3뉋<'Asλny~k;silIHڟs\\/%<@BWRVƑM O蕲;|ʇu"UQTílsp1ƜΜAx:UKhEM,[a/x2l ژ4g?=y0 @"'ܙ*V$*v1I%!5"df jlEd,1>ir9 Q0qWptJA>yOZEW ߲G*?{smJ8ˣlK8Ǐ <fazIm?Bl-7{~P,AQE f>~ծu<^aL5fiozUmhM-6 ?@dQ,2|meΫ0Qy ͝DSOnx(m?94;y\,g0YJFeɩl;lw)WEQ{=W.fL9wm1kkF*$dJQUFs\f47`_@`}P9hjҙMok͸ܐ^O|ӄSW돆V_~s1t2A B9")/3_;`!{+CIvAN~ Sh֗cx:[CvH;-d>A®؀TfpEXO2dt':_o1JY iO;1T;]o? f_^*ZhS+;9-(%5Vs%&`o,6(Y[.C,[ f1Fk~Xbicq/d;b!-QH`r]aH9xγɗBm?%\G ω ́)%l @gۓsg\AL2%rLN PDJ9]8R=:ۙDݾL?Eǜxjik _c8q{"7.#m4.v=t܂&N('pD !lU@ CCg;wЦuRƈ2 %Mo~c4&|6'-4t{8--:U92UԙK,jðJxmsV>D^hquANLgy ,+JFfjl'-gxyߞ_xy]ή3ixLo0&œdHB#C}q\DP <_Yv !i?T/-VHLz~qi>e)ʐWco  3|F[M6͙ÿ=MiZ BƚUUsKJlthIv^?1HI:ʣJݙRȉw!\GA b9pc@)'xsI`.@sD%{aywܶ$ړ9dcLO[DgvEL?|F%."s ̳恼ƔLeHboLuBy]{NP(AX i,Mk]l>ژRcJ6dq=DKZԩ DM hq{@[>8xw·i$[1-zm)>-p>\Ͳ çL+l&ڌ>Hd;[ʗ:I%?ȑ8#v;Y쎟 F!3;k!ozǩ=s]g"'Hq*%xn{5krm劋5.~yIDATr޽`F Jg|x<blh㳸\6氙l= 2GNt>)m#}~sI>WbO6)&J(6št2C82T6B SL%Hp"1WҺ>nņhdLCh[K*(F+\gm07!uنI}hk%Wʖ65qj0XZZXTi*&iu!15yظf}I_:n# оn;?q RP I=)<[;r.u{uTi~)׬ W]"AÕGOp1y<+`q|0NA32x{"hJB*}r9!(ƪ/'{]xyk+7XmB^o)kchQs&{Aެ}o47ڌ(֦fx.ق _ԡ ڔwՖ7}FYj5.+rw \&Ib'a7$OޠD+IoB$nӲHdq7$9y@3LdݘS|{Dz#}9HΜcΖ.YnͰa=QVj<U&tTW=v/\=zZ I'C/#[l.bl|{lǶ' xʚ'r<[_nkNcH @ <ϥZV] n"<;(`Od'!! cDtW h4zl1K>ٛ>k+1xgά15Z*Ԗ:EanEڮ@؊=06UghV\Wo*_SnID=z)wV0O!\&@=tm)WBI̞%p<:OYJYf]I =X>jWo?0よ!|?<.3Dq2b!|E S`LW\J ƈWmx6w ~hL}(A{NQI+S|97`j*dyVhUFl4zb[X0u[?(]]3n/dhk K2^n:{oLY'z~~nӑD=y}F!O%q,rܧ ikk2q[]]֐N>r_-{54mQz-ZwxKo9U(z(TlcP1C+Zci[mf>as{ ?lː@u6[pY 3W xXg 1#7_.-r7=.e8AD0e;2> C8͸tәl7{|aerl䱪Ǭ{>r>o/>Fw£)8b7Ds1+ŝb|}qG*;9, "{ ^d?umg^+\T^n%iCO"C|11Th.iBۡ\57h(MVŪ6 @`[[dv~3k!h Mm;QTԷV7TsK/)>>plⵗ+rܺ{^ هfpÞrgqOϾe՞ oZ2÷Čٕ0@c3ϾR›e V9akhݏF=ӝ_^&$hu757WcUg+wݫ[{YeOR/*+k'`K9 y,.fnƲ` сC @2XTV8XdUAWߧ,5/D⻳A#\<v+'[9nd7RmN@&b<;h"/Ѭ&}Xst$Lӝ\ShYZՙߨZVc{Y?546MVGkQֺ:sY̜m J2_%T\-ac&r$C]ӝs1 )/g@Nhb)K5ߝ񺐹Ak^Kܘ㥓UM:]ɆQߌ]QtdSE/f7-/&^-sr#ծphXíd\p[}Z!ƘUgBeQiMuhVͨoҿ7ߛ%^/ZV*jUKyS뛺jK>'TE a9{ɚO~X^ڛK.9ձIG'/e};s&Ys)d%,>[Rʫu?\obmjզ'MD7z\}8DD՗)4ͣLMd6&GnN34MR߂8Ѵ/zWDO}sLo$b\{9[&b,!fh/*9,ÆC{O3!+p(|BQoc0߉Ӈ\G0ԂǠcЍ91$,A6KÅ;N,;MGoРY3m7`,Q EݥD]`>8]8K}V wJcJ)јdRSerFcXVEniZ{--kU!A/E*-o[J,UlХo /QEy xiH>=ۃT?WxG:PVku?]d뵛o5l l~W{u{!BGОJԜIRK]H1\I30fgBLsy]l| NA&I1E.L~T !$0E>מpG.H0Z}pIx'G7E9Pъ+p?N?2CЬnV(j-,%oETMc4{6.P>I_?dgXJ !W$[Q NR~8ܸVӹs5uspIȏ$p`;Ar$T\,5eQ4bj/|/% 8dz`4zK,5d-s2Q<˙G[1n+!!N:_Y*F"! b ^k^i# uDjsԏ2!ɪʋQ#A][~b<:WaH tsSa/>Bʡ$3 ۇF_S'vZzLJg-ѻ>@py<}@H!qOQxl; [Dzdv⿸UQئڛ Xn5lVj4+ lyoYBRksj!"<R|_"'OiM<BhBWȑ&"=IL: !<&Ew#u}&F-kog ݬ]ذ:isbOГc '7ݰj=S:7z7'4], #~>BL1:E~$!c|D{$y"2WF5t8h;ğáS&])X>/pNJ}Ojn 9s\9ؔVbxm,3eWj,iͩ-I ִF&kBe@Zen2W4Z*oAךJLE S;cF!H5f3麨4md&"E*=|_rM݊gk9T8ߜp62 7`ٓb*W<_8dq "ݦ/@αGF2GNc^!)h 1setDFlWQ,`|e$lEGT.rX"P',.Dv8l~6w֜~<olziIdxe3>/6_bUUc,WS+@`ygM\ΔA!>XTahet"*G T9(Gw'WKD:(O _\~X+<*R_ik" B\_vD6.Ns5s4Yiʻ/7#ҭ[~A3d#X#?)e9c5D$lGQՄP$\ f3[ewU6](voŃw<r1)l':KEؑrĶE,k(U 4t wG߬%Bu"^w1K1..>/ &Jk C _K> 2D :P^O,<2Z5H}c7 ߯\: ,OCn`E:qbr:ρBwnNz>2{ Dʉu*I":aLqqM{:x~9o~ k<ze /7VqZ kgj#&x !B|䖚g4Suo>9"C  O,qE,C’e Pihzݷ|z.ʍ7Q\xt5Y Є9 l|SߌVxr/,<{6 HfHHߎv35Oeq\h$I|gqr+ְ){Zc3_\};vŊ@?~x;Bw.Aw-YҴrQyBm$"BK,|-$J/e̷,9Ԕ X G)1Ę Ȉ JDJw~6(08#2 2>9SBlXAdd! qKqsc1aM7|KBݪ5KVS8uW;^5|}WyR;qta7Fc926G]3Cs`KbI*|HBN@CC~b:SРe]=zb,6!ZX 1VǐNeCz~K[x_*q 9"Ó2j|---nn l!Z]Zi7Ye.GT￐zх!nouE2_t/.s <"oЛe Pdpvgw?q:kek7G4%C@df"rԏk"ATu0fí҅u,n`aAvzD-.@6Ť2z!C*0>,0 w wtaf Cd0>8R iF@LS`6Nn~.( Iko<_Il4~ʵWW]zтE2bڲ#뛣Svuo>NN!H+:cclfnI<<+Pq$BNy!.ǽLV'4 Y[tO.>oF dz\CBs:sl%ǟН~Cu+e?oo,ŽP;Fğa.)3λ\fڻ CU{kEhGOGi.=^yao 7R{i|/<tlEH/ϵײA Mie\U\e-JH-3a[< Yߛ-:s^%9,Ww-xAɖ~[`$яЉ#|Ȣ$Ci; 'ewo4lQ-Bq<^}9Y{=MM:DU}kHz֘%Wd}^h5gc7U5vx񯱟ǡwdTͥ%$>_4!Od/&HPdR%\ *alXL{:ێeGscJ6u <"R4E1\jU!}7=娃Ny+ o*U UĊߣ=&h.JJU߶"jM=婃+DA6$S M@"UʇZ-ĝ[ɺ곗dUdD턦 Mg_OCPS԰v+5K,9Z>o_S>;|>_ z/`N DH0G3|IX:yk|K+M {ƳIXN-;Sc_8193|+?mps!l1vXJkB%ւ-$ŕrKV5ԚPʄM!:ׄ I[kD\E2D"DWh~9LuӦ1Mg6i8p8jWHUnʛg˛z0gچV=F`뷐p- w=VU R=Fc)}N3kOYvy,Pщ&H y2OAOp/ a1/F<ȝpcѼH><^~'.tmfzQ^΍iAyzS:}bW,9\{B1XV6Yj&hkn3Z%p{\g'aҜQb7jZɺGw&"H)ru_DU>lu!Nf?_vF)ǪO&j/h59ʒ[k.l6 o,% :k~%Ґ@aR03E }>C' \GPcw&ؠyISfC=e<+SA"}Ji5y%v^⾈ ;5Ƒ^P0\-\&n" - `b;vPG,C19Ѥ$Bod"9;bjeXgMAkſӥUꌥ *Us'A~WGmkk31'<\\Ɋc?_psfys.?쳣sUpzヺ?ל:Cw dI6H]EWsNk͸~.SY W :Cj!8OKԇlz/0Chyq@SEq?x1ԞEhCY,8 GfsSڛ_sNK> Y|B fdT ȁ,r\hbwؓ'rOA<+nŜ!kypv{ٮK]2lQrG /qΕ/v?]-pbͪ-7߮zfK`꺾dzM$XPPTĮ(v_셦( Ut%!@hBzOmS}L$Xg=Q]g}k4sO-u[gntwˌ-sΦ6~~|_*__ڒ]}qUK<(Lwgu]yQ~0=WxJK"RrBMHIDa"YP"D$d 4 ԟo'<ʻ%C_yPIAwA $DD52@{W\aO$҄<ݏJ$s?G7C_ _z!ʗt'1 3n(~`Ü3iƽe UdV=U dktf#B,uv#iӚlMZk ۳msCL[MnWҫ˒}T~iNqID˚K4jgy y%dtoѩL6@{IRۛLt&`כ:-l`RC@JemiY+->┕ÇV u_1Epgx>wjsYz7;_wվRThx2_Y "VbhcAn)P$'!b ~Y>13"y7=ÐWVs=z~oόޅ-I,s'V=&UWZIk pυ}ڂg?&oI+)O-M$en<1##?>8w6U9yEQAc`S~;Hk3 .JW!8yt40ϩV5R%*񹂰7t"n7}KǼx_ ZXϗ 'S4uMŵ>]|ް6kP%LvZgkĎFed6ϐІI_[s4WT4.;ֺh5-o1mqY6]$#y"*埕t2xⲹխRଇeSN=(fl_VԱlNs4r%zm~ѡvXz73lnyTu/?u/挵ZS~*p %쾈| E^"( b+"7c vt!|Y8J|eY4!gxd`%cyXIM fԨ\:+óEOWLZҐ~ yEԟ{ϛc?Mm/a[N]s˔7K<]">QP|;NRjޏ "C ih:z~0`-눬,×GQm_" &-ze DÊ_}: Mm*eq0ڰ$LHꘂ6š\j?o?mݛFoOvNa'*S=)d|OcfЇW"&N3T%mrH,Īf`ЮCNk :<{ˤwkt5Sʴ8żcxCy꾄`_XJl@ |d~a[`Ѕ]Ɏ4<=)bHEhh _50B>,BIJh_I \>.m:򛁟Aa9b5*cP@}OO覉&*HcG?(+_:8 :* 8) } ɔ𤑾R|QDda` ``sWw'$IQ^(ႁ+Յxx?Az(&6SjD!Zo^i/_~4i}b^̻;~uj'~|dȌCfƏ[ܦnӦ.7fP{ tRff ]KLvwvʩ*xa9Eg'IŶKWi*&.:!`oۓnH/9sĊ*MokpۂY̡Bt)u1ՠnEmmX|OG3Di69fW+ uZ,#/K^b1uz8RkJ"*vͩӲj3]Ct,tpJ>\es9NDf'cz֠eZZL/1,aYwX'm׺/6Ց.psj (…G"&5)xr!_ʿno5O.Tpгl0Ļ n\5"A`P7H}S'ASOF^Np"(E7PF(1B >4~P橻a~WʃPY˓p> RHe -V*d'½G-nK̙bs .{2Z(TJebT#nbgxsN׈bkhBoTej)"0Jwe 1Z~0-s`(\ Q #M:sbꆉ,:]Js]Å3Tj=j".:I[p__ PHBCDVJ:QbY2ٕdV5u0BгTٮTW*ut0ٓfz\sTpvwIw 2X '[T2!T2=?`Dž^с<j yHm,P>VbR% $~Xׇ SH C};P&/ 6 kjዠPYT΃w9O;(.nj+4VU+A$d\KejQAzAC6 }'yO:aVˋoyaxX|E£QHnK1E]1uښڪ93ajy`r`he\f0t(u֚6)oaKQ2UhRlfTȦ9F>WO|=WHE:L6zSxXGe Ý7Ծ8w}NSh(E *xIaPB ?'$:{bP,W3㇎'t?C,xcGv'*pYwt2vkh`"yF|;|;,#`)~ GX ġ_ aWO~2lȘ{dp=?_RB"V-T+5(r /~ܼ57ޯy"lJjly lY [u,<(6%a;&rd &k+"3ZUk-UsUlqQvkVh,@ÇwEyABv-?MK-f PKW6(WL&2+%Z}QHDJ>AQ =',"q|p#p18T]6U;OB SRU'Hhw{ew}zA>o/%<ZRe*% B_ iF}Ꮮ9ym-׷=nl|KCTqJ ,:PJJ)o%& '64M ӏ Ug Q$"*l:?v4tЊyhulXD[Izh\mKǸfGZ_Y \M"ȢTֆ~b`P*&ԚoMf_f[7!kIZ=dоc}†T}|zK{IQyR;TyAΚ@C~Ƨq QNͫ{vZ&CGy5FL]>o~KvBt(; !+Bv 6x'*P TGI"%(UI |A! /L^_Y[bE2#9O.%SjقFkEi)m7!Qx:nڸ vQ ժ9I<\x3AMkuqƲe؜h'C g3immÊ:k~ZF_Υ.Iɖ ƥ-ldc?%Qc }L2D}W$t!*ҡ8<4TǛn`?< O$/vIxNs)}8lWݛoA$uJ q/߽|pF Q)zd!in}<>3%_ZrO#(W: xt#xC<rT ұ_vG,I~nK{qms'7Q{ -+z Ra!D`(;ۭ9i:k-sNznD݀!;[ `E׌V L(4[5-F6Ψ l%Ӗ Ԛ|vʜW>;&l0_h >l*ħɐq~bɟBWq᠏{{_$}""hEU!( q!|T`ԋqW Y]ކ/O]l H+:S{3ٮGoBB%=8 (=uһsQ[9?"GGHFB.ibYErIւ'k)9McJ9MJ^@ۯtk{?¤Ydxaε76 ôFsIJ?9>a6) y!v"CJS0\>#Py˒D"Bxᾱoн"x)|"&-Է>;~<6>ܹ+N\#d| 4)xOXtPDEO@08Z[*xwܿO|qf?֧|޾^eF$VQ $Tp* !Ѿ4O<:_9C >)]c2*ɅQtit5Y\:i/3vG܏m8 dJ5a^ pn((yx5츻Se_+jR$$bLJ@<@-U˗Cz.&HiH_b!>[^>83j1?徼]-onk|ysEc]_zDtЪceH:B Bxԗ6:ՕCe- O1[/Zd[J5z*k& aQ-בC/uG 3U앫Lf1s9>a9xBnH|ָ,^`O۪[G_Y1T' -xd!&L4~b5dY?4'{m0^QV$_ >6T~]Zܛ7D!ܾp iAO'PϹ'ȂŊpD-@"n$]ŔUCg7T}Cƙͳi?6geahh*?^|UT!) "VG?J)[q,!GI z}m_=IJ?Y{-9n)Nc~Ѿ9۪g+8i~v>AS P5(@-x7(^`?xZ CQ+2_]7qzZ2̇ΕaR@:dži Spn8MjoV5گV+،bbϜȢ{Ҝ q-]撩˒}|+c2AhB<+S51ҀH2D |yl~ҰlݥRSV @1h:6'Ij3GC"wniuPuڛ`΅J[z{:CL_b&QLu ~adMw>^zL&Lz(8G $j J.-}l \(Z:9;m_HK lui*8O+1i?<"=23\Ri\a(0!䃈0|҇熽eSWflކ/4>M-;aXzʸyKg,0(byGn.}`g,ϛ g UTJDr()E>`WP mOȰ]wiI݂ _:mM hK;Y:Z0L%  ~X<mLMӸOn_XQik(ov$x]wA @E9DCOo -oWH e7A`t/1yb0~E \}wOGu L+?_']0JfqC`HdޓluڴnQw{^g?=x߆~'8"XG)T("}x 0%(M \4ZNkȔ:)CI)*,6=I؉B۰84M5MJ8eM̚UdKϥΧO0ݺQ%?;e؏n㥾Q@Brh4E | LQ%BY .˚< ɹzwxZS9Rѻ]RD"%žJ'b 0fNq! HO'K&d!rO1O><3x꺛`Yړ늟ZGN$Q.ہ{L2>r*$'SE,lbcyej%ێr/~_]uaca^9''+UDKc;AOo:;qO~H0nL+"O/V[Q!W)k5 +;qpo؀?emPH9(qG^fna*ּJkv9YJY.癓r cM5w(YsK}kԬ.M}nc[;f/m 3DnJvdPrc`/G ȌZ2i4M,f2ޒ^mNj\D^ȡR $놓҃9[kf{Yo4ṷDDG5EC%}w)ysԞ\s<} 8-A lR{vA"h픣vc8ZhWem֒f5tN%vi悭Lr738iyѡi{tꏗ'7?[M?2a^݄hh 9&y$OTՑbE((;B &PȕjJRK%E 75!Vrāeݽ:TotïVנ¡􇀂?̂4MX#GQFTxh_e/ {h k"&nyIvGߜxhyMo`W O藟2M4oJl8nO:g+ uLr#DgyZHGJUm *dY YP:,)e?jG[ǴsdXIdj{VנX37i HUrCW;jg " 64=AUeUlW1ټ:6@T,!/6x*Cb؝d^vw470n恆v^`s;/ɽVbzPBFD:1pԔ?=i7/aʌW~)zN?٧tK֜5l9o{r4BBSF%*2t_5Skֳ&T3l$fuTE]fXʙBb}>JH2:mr²q7V> a}r7dCArRխcX@f+LEdI]0:kZdXl夵6XmšV0Xk6kaJ-]AgX 2)w޼%Ѽn־Ə‹3~؉>; -b(!;_iĖQUy]rREd7lXa&i$6Fv %S-zP.DVB)~$*&+J"r>Kȴĥ_2n8o\uVdc3fֲC3_{ݣ_\=o{Q)☉٠AobBd(\"@/P-;%X)@B)Q*(i:~4mqg@-^ JUU/uA eů!Ob5DXh+͍xuՠiFΌpŧM\O4~}uI݂Ɵ.N%7gѻsCy4dr^A]!K&jclZk!QFP?(rť79P2_ZނKUsr&%ϒaٟBn`Y{ּp}՟]6ַd( 7AoĄ|wg˧l:U.UtjJيB_od3 ]7re;YINvҔDi2:mf[5xۊPHgWY+ٌR[K,/΢$ˢZCkiMayni|q5~vIˊ\>6/|䇲;M>BDOGy3O,]P7u5# .=2_*8זv>oyX;~9K̆dz[*+r |$x"ϘPd>LuIe&k>JUq7Z̬+Iq&|,:K{dDwgɡ5Y[Lh!PvZ\*'OXNw^0@W#*9DzCPwC6N"}Q|u:G:,^j^a("f,Ewq"^:C'>4Wn*yo{Ŵ5mna÷ NS?amIMfqT|!}IA\9YEeױWkX(7;j,&Ҧglf v3nmdҮhE5FΌhlof3j 2rbhy[eIq;>YQڬS?6O*Dj¤׷5x]6}i:uu;=$3 455׎?A!&Հdk0j SfHRtn%qN2<*!e_4KsէNpo6Un(|su+Ҟ.鉙'8nknzvṂc|z?OO$BSKhB>AHn#DC,RuQA yH(41W} {P"`! 4cD#DM/Ng|LE!/~&S󫳦lkk{*?;X;X-'V*a{ز+ܛIgҊB\NZX71e-ly+[y0PZl(D`@Glc{@<؎9i.逛cum5:ka#TSW-i(fSR=I-kf_ʹuo=ć{Ƽj+L;vy}m_%WW-)5tN=[b b+qIwi?῎XCڰpAa83c3 z[Vfma*ib=_K_AkU*Jh>_`N7$N^N@y0Ͳ'ٸq9ú3ƕ'tK~{nq SV=le}%vt;{x}۰ |f73fGMW' =% ~|BHm:mYm 3US+r^EY-Kdb%,j m@"7zN8*bɜvh3: &im5UQ:k~ [dV2r yU*1:KƣETj,kY~:C.=KH->i0~Ϸ7~n7^15ySV漼<ŗ&O0;~|gć|{764eCDO)CXxx^CW3covWeS6셵eϯ*SKL!{eL>iK ɏr&e 1anfOԂ+O,.~g?U/{uC5h`qMnwu Dug7]0md~ɸ5Ų/ڃFT'RGhm&S)Π ޚ`-h6KZmJD?j29@YХC9H"n!-NBT"!٠i'q'*,rT48s>HXS-?G7,4RA{fn3k; 749;["jfWMv^ݼ}M O0N&&睵,Ld^fD dzS9Tb.}:r,eN9SH+e.1)WLf%[2E֒Z/j4bqЛ nqEBW{Ǿ7^԰;ԡ7ZlZTʼ*:|ǘӅl|d8NJȓ r51,lh-6ڙ}r|T4a>},ѣZZ 9Li]TWrY+^Τ2K yI9٦lLcRLdH fd/ k/W5L4di)(~"0S׭8_sJi螨__q?mXbFΚ7_lDo¬Je֦2_2m̮,jw`>y|&Ϝ`<"r RjM-eL6R:Tz(u@F+ԁ=➫[Vr&9φ9k3H{ FءXLl3*Mln1 Q ΖWSȌsv)WoV ˂zgwHnwW9Br4 1LU+@6SLW51@Hń* : 6* JbKz%\@^@z)!x2p<|<dZ(>TjfXw z}7r:6.kb8Yyڰp;̀@ڴ(BZLimhc[ΑDhvd42muV@ PŢ. Lu\C]&]uL8q @PI'Vxp ]`kior6SF|omSQKvsϝC{W57~:7J'`gğb1oI m1㼶$ڙ"ac;q``Сo1`=vDQ'!Ը{QFBi$K&yݯBph]nYjס͡:^w|؍#6q:9_MM>OTLB7t:NJyYgT$ѱou=t;!p3`u۰"y@'r ->L5'Sln;m#p"N~({xYw]_~{Z卒ΑΫag\vXp\~UK yNkkvw_nG4D3 (p=ψ.}ۜRw/"Q ORWxdz\bntyFoQYد@J@ @GZq:K~Ig|V4 T&F X[܁7!`#X ] pTZ@+8:yp\]0/w[,_ @QFt6x#H4G#H9R"H?r sEC1Q(K+*APUTj5&:h :DэvUz 00,dc01mK!$f`uVXol6 Ğ^cqD pr\37-x 7ߊ/7wS%E" VU8 HT!}qĝ iuJ&9H}K7d2YlK%WOhbzbnb\bbbb(x:ŎE)ܡ̉5#ķW_IJxK$II4KܐbT'*G=FB!4UCMk]M1tݍO/LKR%%%HVK^0Í(fa2>J)HIEIjZ.n(ÔqI/)D%-+){D]R#W wF<,-'-L~@~AAQE!YRœ"CV1^LGqVdTtQSiLdV0ʮuʃK*,\6'Ujjj꼚ZZ#u:[=VzK#HcF Kb5ɚ6)0ZlZwamXj;:NaUUxWtt3t[t'zzzzC101H4h0xlH5t756HۈcTmt5yV612>bfeǤ䳩)ߴtL,ܬlMg;ϛ0H8c񗥮ee֚5 k&T"Lpezg\Fi;-xSv .9".NT**1-.&..\Ѯ]8nMnf)>b|}|}۴y;{b Ǡ A~[!!q!]ЅN 3 ڰeÍ7^Dl8:<(9SwD}B[dM<ǁsk-FYEFMG[EFX-s{_p"a91(- tG%6+n޲y(Y'9?Ybr0eoLR7vхt'233gf"e`ֽ[g9ٽ99r&mm޻CuGގ.;O"Ju; 4y y;&p%_,?rO폨~ܻzo/܂兟8E72}M`Jx%m,(*sר/?9qyC`CqF'x''N55557--NVֺ6F[ip:_=q,lִ :󝱝sz-y$/zz/f]\|irM_7xk׮_nu nov21`2~v`;]wv|޵no }06&x}00GG<RTiZ L&'{x3?>M='?/Vn19?<{S/_.)g+We|k忋ȼ9mwI ˼?cOO>w2,r \@"D. r \@"]ax h(a&M>PLTEi6\Dsvvvxxxf888四Kxƚon999;;;EEEKKKHv眵***111ژIwY\\\uuuiЃذ)))ه???aaaLyU'''///ҕ藱wwwGGGjsrn\ÁAIDATHŖS@W`lHb {+رncB!qMfM^ db6\ã0 מDӃ0A\d̙@0D2ZkQ0%0x%$&V+3/?ր $qdd ! bJjX?=##`dwsw8!'G¢ CvɣRO SZPCEeUuM-]ǐ׎y~QaZZioC^{ooJv}Ro\C#cwJUoc,)/yb^&f!;8gfѵD.0CXy~5M['=nl6)˼a?1$lh1-6*ltaacKĘ 0 ?IENDB`libqxt-0.6.2/doc/src/images/qxtcheckcombobox.png000066400000000000000000000117021215241066400216760ustar00rootroot00000000000000PNG  IHDRcLCsRGB7MS riCCPiccxgPTYϽs@sɢdhI AD$)8:EEFeETT[U{}껧Tݧ 3NN H]BBÔ%8 t#i)^@\/y7 ޿C$s9@8'pNp'#O9+=EP nP!BIB; wp98RW&rW2; L`ڷ_#%|xnz4 ^bi#\/u1+6 Ha(^:@W)ROo5p@ @h=` ́ 66ɀ@. @(A53 5p 1i,w` ,D4C1Ăl g B(BP.*ʠjj~A0栿0`,k0 =x p>Sp'||%0eDa! 2|@aPtJerCبTvT1uՉGCMP_dZmvGcYt ݁EOa0&FcqÄb09baL;f3YbX]5M`#i{3ƹp\\ׂōfpxq:K4~@%h .B%p0AxC$UD?bEJSN!A\WaNhXxQ񅒄RRR҂rr򲊦JJJU*K5F\OuAMQ[-WU:^~H}@}ICS#XcFƬffYV+UA6F}XcSsG5Ӎ=; bwUêq=^^ޤ>SK?OKA~/IhFFyF=Fk&vYcu&&&GLMM~637㙵͙Gך,_V1byfg,ҳJj]&zM)kHzkMQmm3;U;]݌})W<%GKm'WB!gssSXVWSKnh7Onlfsm$u՞ϼtx^=ްkk|'a|j۴eݻǁZ}A栥``~Aȶ[2aذ7 /۠aˆe6&m)rtDpDKħHȆ(ڨ#%ǎSΙ.)=;gW7_:-.a)'DJRpR{2.9"MoVؼepnJA ?2`ϓהmHNg~̃Z?dLfdd :epֽ[g]r9}ʹr'om޷CuG靮;O"Ju;0,=;~p@W0jOݏڻzo/›EEE72}1JJbJcm,eM>YT^Xঃ7*L*eWzUvWUV}qi[tsxݑ:G>wlh89yycPq&'''O777ȵ­sO6vf{ip:_"~;y,lۯv; ;έ ]q]szz:~y5$.z{W.f_\rir婾M}\?tk.׮ \n} nnv29h:qvǐP;w- |޵o {0>y00G@O>RTiڿ&&{x=?>M?'?Qi5=?2w/S^.I֫_kp!da5oߜxkowwKߟ01r'ڟ{x~XI^YD. r \@"D. r \@.uFD8 TU% /PLTEuy``` dddeeeOOO HHH醆xxx YYYuuuKKKrrrJJJEEEsss+++[[[ooo ,,,DDDkkk===vvvMMMtttWWW###!!!000aaawwwXXXմ333TTT'''111E^aFIpy}䲴%%%뀄瀄ĊĊŃw{___^^^󍍍zzzFFF555{{{nnnLLL\\\mmmqqqZZZ<zTXtauthorx P+- 98Iɑ1;D ]MX#WUZ2sC 3_rxBɣ^cH-l}AHuYZwo1<ٓ#(--nO1;Z3;r41$l`=L6-ڙ=9R ٓ8oj̧mLWΖJ8[Z.b;t[fɶ6s5S ,Y]n.zլxj 5y^7~سs׮7z3>|^,18w}>?ȳaqO4sƇ{9K$"$PZfг"f Yj߬zV^s[ 5>g_ϙzV7Zı ?6wczVXСH ,=|8j.'ySye M̧A戦fJd9;󏀬ȱ1;Q͹sf9ƫ|Ե{EBɒXetZse#?TZḍHHk/CKXr+9gS؊ £HHk/IKicq-2G^i 4|q|1sSQ$@$pQf#~MoHHk/ƒXEơ1^7jDaz˼EDZ{1.]5~蓣OA3GUW?rtDs9 9B7`B3Te!swtrn:f(H@)83rn:f(HA@ 3rn:f@ pm[Y+HT3k=ِ#dp&1#G䬺}|el2Gi#r}L]fYcX9krٟ3:䘕9S?CTLHU\O9RH<,TqcFrD wӆQҙ 9P3rDaJg6BuH(,ZG?s3Gߙw_eT`IENDB`libqxt-0.6.2/doc/src/images/qxtconfigdialog.png000066400000000000000000001305071215241066400215220ustar00rootroot00000000000000PNG  IHDRp٦.sRGBgAMA a cHRMz&u0`:pQ<tEXtSoftwarePaint.NET v3.07́pIDATx^GےFfwwήF̎ ^!, dBA/ {/1 wƟ{:QIVuUS]U}yΓ.223**N\K.3W:G/4W9Wr=g\vY ΞOIR6>WءSNO(KNWGt]cW> N3 C;c@3^SY)O^%o$NЕ-=Ǯ=`Kt{oǪseei%sYS'4MٿD(dlW^u$LŠ`Ks`o6SJ6(ņץu .}(]9цد>%dhn_X^Z&Z&Z$b@/&/< {c"+3qJcb`)Z)tI\c)]V][JstYK2&Xdi~E >ΪNӥS~jZP.y"V'YG9 ,f aPJTR=/?eRʫ~dbhe6~ <ZG^aJKy9|cK 0{:[.J)vRC;:uJRnZ$XM`惘 2:k̔RmHcBR]Hڲ[GM@@@RJd `XT0{U_[j!>a݈( `btXf?T8W\1yX!.KhYhYh:Pu3a\J?Q}sg}j.5Iy˓]9 ?>@8À3)7|g'37(0`29lB{IH[NzN]^.IƲۺ,Uq\ fSj9jIߣjPL5޶Et"cwpo0vcO/͍=8 v^R){+T2[Ԧ&5(t{k4v>WǞ>KTs3b^M)ֿvaƾD0i>V`U3j}`gU@B4~V27'Sw)pIjo 8Io|YB {Ы zKO{H"M]_Xg-By=RȈTՇ۳ |ewkHٝ_/գ6/Pfg)Z#t]tMic7RzRǕ ` `ѿwK{*vJJ?벇n=mhVĪ.dP +Emث q@CjSSqIjɊY?@$5+=Kg qVj+[:F{ f=[:2z zwdE֒r>lF IJ;BYRV(SqVhQ GGcNp!f P`f,CGn OSNtŪ&L6[ β{G4@+sMl<ײҲ:u uPxbOQORA'I%s}QxN"-Oo߿rdj07|jWО߯~ւroB]^(PF'Yu=Zdutٛi㿧q'3`0][?foE%xc/glI37is+dB*`@8^Gց;|w:uըI|):^|@cs!,u`vyjU `՚r_XW/w2YM@y}:x[bddp5{U C^p9~bx:X羰-5HoEy4& Q$ѫsG^mJ;MN;s,z"p;?,f{=$o>45fD?Ow0e Azۧ^qw)CEhbZٿ|Yc"۟y_K6r+?bxmuՖ9ԟhS-5BB })4A f(5.3{UjD4wo˧՛r鲻]>]xH` |AOV#Iޒ9д 0ZbQ&=ءumT?K>vVÿuPb {o(b ص7lbzM_qrWVz:}tnu:UtdvܽN/wiBt b@8JoХeu1V@rGhaK[es_F7O݆ Db{ff~~& bm[,*橍B_ɡi%{%Ts1=Ծi}] `v5{0nhTD1=c}`XVhC,[Do=+uٟ5~M:X:PiKnR!`Zb8QYT؅Pk `c+XG}Ety r٦AuXݙgG庌⹵8ǽO#T`ulLs?q.6!rr<f C=guߺ:eeu:vBDeG%T]x{8`vX蘯_όߍX W3-p 6|,4m뚾մ5v~tMj=qm{x&* Mك<˨/g@ 5zlQ` s fC֗N蛬q8fanj O;.+9~(Ǯ9yP z I_\霟YD!F%y]/[1.-sFr{m?ژ(PT~@u +'Xϱ)FCUjV\ oi1I1qG|{ 3ĴY-,Dxy= hn?O?GJ7^(ul5EM5&-&Mh \!|PA`G)g6|A`Sg>4@';W?u.۴ ǀk\A4^5oߏVؕvzHѫ u߅JDDumMIX"zv=>#k3rt)^=~Ӫ~բm^L6c9}%~B2`8M1|׳vmgY+CO2j^K5e%v-mZן9y;xvvg:)_bDwW`-{ؙ.S+)l8^ھ~qܽOՓ%1>yEq_˸O|I'o{ ܣW>&^iTP=Mj ShUPfp= {{}rvSM;X/LrN)Y ;KK`&m:ƸIw`i+l6>Z9ӓw~$\k&GF/?^ɽP=eE,,T zCUW-=16``N3~J%tuf?߿дy`lx:T: fU, h3߸dF!f9e=~ ~jyg'o %010$ ^$\q!K]o^huC9Ѵw)ڝclX_p69׳s܆D849q ]KR6Z]&8#9c#pޑ P=YC--ڧ7!z+/^>Av/u):ڝIf%SVpB&]qOA>a\G9D2 @GPf{(;`z 8Q?w M*t%3S=9?kM?3lXm [%oKI͜ )n# )#1etucwqls̆J84{F>뇬֝fb+4ܟ}?UJh^GA"岚;%<̹{B>g$(?IZW)y)Oq3l 1A<|#sp(^|~`INkT2һt)u/8-J{fZ(@ht?}lP)[)M]¯Y(vrK0v+ SJY=W7;rv\Rti,5~&/oQ]g~yRf0L'O+oWAWe]~\qRT}^$mYH'iN=Oc%ZiyhMupU2M+9ٰtM>^=LˣbC(gљ6XuޚU`UYIO۳b/۲/oOХOg%}Qg?q#=Sg۸;lzBuo̗HY@>ʺ_pi_/D`?y]}weo˚+++Zpvestek^L_֒x_13jX8|1rT}M{r{X8iy'_yZtK׎_8Bmz'=Jxj͎џLoX/7;AWs\W?Nx}1;nFS{-J{>;_hҁnפTzQڳ9O%?sJjJt+ҦИSJ&.D خx1+p f֛41<|(9QW82uO$=FR6%_çir|gwO~AN5/w~vNKfпNē]V^5^l_֜@ʓ!=;Z{մ 6NOn0zvl0QbW49 2@,xUv칃uw veߗ}Dx*/hP{ѷŴqQݳKw͠>쁹M?6]<X@?}`ZDܵ=w ^i|ju` Q4ш?o4hMF3w4mB524LtM4wѴ^B~B^9[7P>X`x7 `dc>21VfPg0TNQttm[_~G.ox@b?P[ q0+%N$7]^ܿ4 Hk2}`p!*00f/S;5`Dz*DihkU oȴWuVD6uhƵ!9Va3`Xzd))st!`I>a,M3ZJo]r?GM0f]R#ۛ=L,۲Q&|ԥ3񥚖ARԁ1TJ8C}lxE 3=ݹtRc9aW?:Be惘 2f+ }_Z(^U2ߵL%BtM^ީeu@qWR`փ`q%u@ց LU)h:u@7!+UEu@L:u@@BV܄[}k:S)h:u@7!+Z(` 0Z$dPiMȊ߷ 0L Y<OJ٤eNߩ^ 01/N%u1+^D${Yցt˧\;ǜeIk:xm#X~'}9^:fG^@>q:P@L6o<~T?Mj*?j$ۑ.XXYc6Iu,>ɛ[5._޽{ ƫ*4^Zc #FNЎuiɴ-uc{LTim߶mNϠ;f3iΙt`,J5vΦliP9tp\:g.3ΣCὰyo>e_ȶ2,4m1ed;K(R^_Jه~4sx/ӗQ6[NrXa,/s%/VR~*^~+YCܵ>[K][bq+?5&\+&h 0Wց*Wb RZ#kٔ _$-abaǖ@^Jyl?R>[a2*dXNlY+!r4{%aYEGWt׏筦~"o DZuT+\o*>VaMtf:yة[.m3lv^n%;ΞIbN"wӻvgx},}ֹvi6~;hZ^9y[Ei1:2a22j, Prjl9 C)J)U,,VPguTP+twcr9c8r 7 #3Jln%ǷI&E)b@gn3Opz>w1ۜ%o_p\*{m wzr1z l5f1xe/ b7{nxe99,|KhcXUٵ f3X΁00 \-^| @hBP>H)IgXayF9%9sb& ԅ\@1Xt2T`0aVcJXCMj,XeA`X̪ +UcrhyX˱-fj(R5v0rQ2j8+;nFGm"Vc"j˧HYvdv\K?|iR{{o>*UCN-F%DžڸC bv-^N'rVЉTVQ C855tZ:YNuc9NHgNlfH6"vo~td/ar`;vz/Nt.v,t0D/}bg>kG) X}[φsT7y{QYsU`! .CqK݂G%|}!ۨ雯>S!V_Q]ƍ0~ Tc 7(uġ#UZ`Uv5M {#dFrNx ՁyNF,mwRjR'u_~;=۳x^sl^n48f3lڕJ ̙KhD?mNJ-NbDU QgqףbPƅKyp[Du"i=Us5I=J%5K瞫MϜ޼IqSi qxK(.VV}Vc~'aBD\Xe)04(=)O)?=GS@^*>ciQ9'NSNӧ/Xb;+ϝ,w~^g:Ν;G/{tˤ' V\~wa)0+dRD^f/ nD(0VI ,v<6幧S}vo4@rV-hѢ%9Of$aoY @P$r-F};ڵxVYo 0'K `q?!GZnCLg VQ_|P# 8(* x)ﻭR]nx1R)z0`C];u½^y-{NE]Xu  / ܻ/4~xaBگuF]vmR0{6s:niFg&ܻ<|'8_}hEthzgR/Q[7uh^.9 @qv> (.ԉWJm`GZ(hQsn рW 롖I""ڴiab 0(0 C8 q4pǝ={⮧?OӋ/H/2԰aCjҤ 5k֌ZhAZvQǎK.h·~H~)uޝ>sիӇG A8~74x`o}w&iqտ۷/}w}7͘1{ (g,>eѤ)_Qj1G3]dx=0^ֱށ0}b2_47T]!BsGs%&|w07 TڨزG'8S5u/M Ү| NO>$}FyJ}}gH`.O#F1ciҤI4m49s&͞=* ŋiҥl2Z|9\VZEW6fcc+V0iGZd -2y͙3{W`xlOAϧ$d? rԡ2i')޴+}(b(޼,_ Ф:c }8$?F?cӦE /wq%6*`ʻ?N$ 7mYRVqe"ց-[[Tf`pS;K/Qƍm۶ԡCtDYd={ СCi4cĉiʔ)4}t2`L`%84HpBs(BuIuԡLVTTd: u&fp+>tX&M Yr`` ٜ-[  Q`ޟfpq[ԣ: "Bt/ "eVm^nB/w[m 'P~`iT_8ibXbJ1xXM9.DV`>mشiSN: >c.qX?=(/0kܸq~x2 lf/(4/6|D(½o>`< Tرc'[60μ3k9.D(~OԢ>_vqf30tnJ 9!X#}`0XhB4Z.Ģ]ؕvFe&f& }` yꧦsv5CQ.P`D}>-,kժE Tn]kݺQCf͚e!$.u֙~71D׮]k\J2"Fó`G.[s"e" ֯擔QQ`ļh03Ƃ!Vޚ5PZ~Z~@,?B)WohL*6>0V`;v޳g&!'' O>1Ƹ[Md`?z!z7 T&L`܆(/ 0)Dnڴx6v׉a sȤ? @ĵ ,PG`<̥$,Wۚ'>0(. tO&c|UAZƢi㦍ց]bѮ`F3q k};3v4F0BX0뮻}Ip@lȐ!,PGp.C 0]vݻyb=};w4 <nEQbP_#1 F0j` ̣lqtNExdPf 1M0mT:v%s`B+#ϟ>}=W.kٲP2ByV\_(ouZpbPHp=nPGPbX!xAQJ>,۰/55 >@LG,/.Z2|c^\ 'OsDL{BtFzaX,BEEƫj7^v%s(0m"N䀇# Qf/̸0g믿ތ $pr@ewA}a </. JKKҡC 8`8x` Eoi@ <r"y م~Ae/tXcQѴL@ծhWb 0 7Kƴe+a:YbP.ջwoz'nAT n>(7 >/q< j JOO 3 ewa8uK(:$&/pv-S>!Ftq!80 0l!+A"fw~]Ff k̚6U؄6oƪ Ġ\ڴi~]ee *@[}&/q@ / яyyy~52TW"TT oQhPx\ܱ+2fFa*)_W@s`h]0[Lxe,*6 ߀wAeցX+W`5Bt2`6oe{bP.0/B0xA}0~&ZBlAUAy^ $bp/zp;TPapI"\ psx(O1W减_[ F_ `Fos3e%9 7D}`hkkíu@,ڕ ћשp=}`i0@ AXͤOH`ɓz4uT Iu% % N? / _c0ufwuxby%[a4]P` _?$ǁ9}` 0# 8+0~@fm*!@ԁ tlL7maGHY桾i1<`vM7u̺!b`H2:#ܠ`vv2{Ve@ J =nD ׅ 9xM؅>0@fDv!bs!b*PD6qGE{6XTTx=GJSbѮV}.DV`6nf{ @ fGƾk{L#CX=YQBp-%ל`('}-eF" 2g~p_Ѓ*Np͛U(#ߌ,m_?2bC4q |s!. ѼN0ˆF}0dfO/*!Mi)5(B(* }f8*jPxi@c<2cM<0g0m( ΦL4(z֛ 0e*)o`G!f0=6zhE> C<#^ ꫼ g: #и! M F#EB]s&:yvUY(0u!VPցՁ("Ɓac9( \p! .C@0r`(y ^` |ҎCܐp5BEAdT\M NϠNƧl%x|M8Ȅc*)q`؅x!*bP}vur<G}Դ(_u 1coBkm.T! LEa&z(0`/y'Y1^{5D`P4 nD(2f4e (D܇W"\HxPOmrT#4"@!/\o;H'T&g%``|"XƱ}v=\ A6S[ G:P:p8 sؚ"|3`0`BC1/lڴifzD$&mGP`fǜ \ʐq`*80\B07d`CC4|JIc\lE "V`8AB8?`G|yY(0U^.?s( hì:x80v!@G^  y3q Û1Blذa&x%g /zWp!x  f %垉^3qBss +0v4ʉ! v!2|y#4*Ċ;N{>0XY P >e2<pS`0z"̅~0R1iС4|pJalf׫ _6ヰx|0Q0A@̞ QDЏ&s!ʬ^s!m C+>Op"s!}1NnCK Dg`Vp)`^L#&nI@fr\]XZ rPJ lp#X0Dȓځv?\P`dL@ SO=e/D&gpln0y/F91 I  FxJ1̛ w8~-ېgX 7&Z׍ιn jJ:p{# 0SI[r 噈C{΄wͨ0FX0#QTI^w} A=C 2W"fڀod72c|y#3Fp Pam1l6. 5(; ™8|A 0(c/8vʏB6׹sg+`^ ԝ@2ԗ<ԗAK^/j;&tUI>LadF+L bjF_^( Ŕ C?fx0ȁ`^nD C_+j{13g! !X.̲aQ]pP&fy] ìP*l4Ҍ]yxz`|X/}~!/`vV`Tz;T>0FX8*Kj(܀PT)T!f3R~1Rohl+`F1XE9o]܂;w]g7"шUB꡶Jdf@ K@ >u}`aD.CAp>`׹ F P Kݻڱ+:駲uv-{h+0J8L|[W1`xA|Ο  ^s+K벴AU9r\SEVLXq`P` v<ޱcGč(шPa" Dg@ $|pBhaw~ e .J  \}Ծ  `Ge@cF}Cj@w4o /cu 0V`wU Q)fB= sP,H+#q䵞 >[dwW)0Dž8 q!A˖lD$2G!tԩ hDCT$".Am!5Ƞ3D | s ={]72 TSNL0L !% APkp9Fܽ'td"/9 cB XZ&RΕl{`1b<")ZPvH@>x2V` sFNOA`hӦ jo*LB_ەx)b'%0@DD" P~,x] p.f$w`s ]8 `:K/xۇy 36BKѳռs!gs-FJiéu 9@LQA+0/(`fJW&،qa1/HtC `$?!LG1}_:B7 щF}(o$wֺ)`u7|L;n̗d2_B4 {wa#9ky ?ױ5tcVIFW^]`B1:1,]愜 * 7̒-[h+2?c_/O #_<2/@u('\CI %Xp_u5* B!h^z чxwMm`8b55(c~q;̜/v fq|Εl(hWrONY`̸9xɏ`pU>%q(* maĤO YJ j D 6 }c2 0"e.F@ ъp9FܱcA2-4 pJHj3v!SIA}zq+pGY-b\966k@B̄gHyBlD/5>)`P.\r(w@ naAez` :.EG@E+iI"B%P>d^Hx& ۾}'m݄]2a!('؅(AFYX. >Zx!E ׇD4@&OaNHL\'2>F;K-ƃKb+J軒0fJ"NDQc6 PfP%KpybvDGjPn0*l۶Ԧ~*<vvBשBoDv q'ϙ; ʛ7i:uveq`5S`O0 N0RY:YȊuC`:0 ;N L]ڸ%~a 0g (ԉ a0{1U JL YnDN/"ԘA18C iDXP`{Q9 "_X`PxlFmZ6f@#1ʉ0{ywnF_<}j3~>N7j NX6@8 m8`3R~c͛43&01*؁wbR5f "+*L6d6{L9ABc$nF̕c@4T[Y5a! BaC a 1RLE>$%M~8B: Pbcס<˦M[+003WtR]רoc6Zjn3߰]DS+y9VZۨ.D@NG#^s؅رm .(5k90 сq^D-C 0t@'Р5,5@2 >` "/KH o1-c8yl_5#0k?1{ɼ!th+: 3XU 1yCN%^~hzڨk~HH=Y.:"XgZ`xzôN P@Pb NO;0E2HF h(.ʓ`p9Fܸq3fĮ?SWjx@s/r_:| M75sB$<|9`uN@wWro>=1{Af+2(+`H'*CPfK2os79޽LUL(d+b@:V,Y:y 3m @G׳ o:XY+Wb x!>-@u /| , #+ٳՂt:ìµ^k0 cD!*nx!2Q\Dh ǠĽ(j PdC7fkg`"PGkYA-23;R&uhomF uN6p~ BܓGY & ^EE'Fp QpSt^o^7n>.!_l =B7ׄϞ3ϸ ^àbu7Lߍz&J;0իWm?A]<,PFPspK029b8 3x xm׺>ӗBՖ255Ԝg/p8.U@f,\x+tRMFS=~]a*Z3qոvXд3}!rz0euP0Y°.fﳏ~>G. ^t^0nߢ3=#a<~\p)_9Jae!.#} ByʅH۪bvdJ>wWyޏ|q޼QiR)C(|.#Zvi׀ q`x7nh1(2YmI+,X.u;}&{%l箝K:sL5嬟D+?cQXc +ɧNv':+q*))X^gΜ. B ׵}n`Adou˺ﲮ%5g|8'F>0v!÷y07 T?`ai>ٶX?Xtc%ВF] ctYa 4 Yc؆$._:Z61N e ;مX}`^ц^:wlKR#TIy`kyLݑߘWE&F1|N[}`i7 M(/7Uz7pن aCҬ[%I:Wa70u[}yfEr3<iW8 )rTCl;}p+:|E ݅ Bt+ `*P Jy>:,EUbW)* ci2Iz>m[q NVw>Y /yĜc"wz'L^״(=49G^ƹs. 㫯Z5 [s_=Y*m; 9ǝcwx)wW0z{W(xa `(HzlZU 0c؞`hԪY]-j .Ծ]ﰅZ|-:^V9'TzV<Ͳu^vqI;&iZO>~Z4oBvkK߬K[Ll,d`Kfhs%>[:w08[[g\`c  d}BǶ<\l"9tJTnV[8 aW[8 l=1+}`PT+1ţ+=VT#Q 0LL>0(&сS6"K=CTS (V\˅\`Xdy[ZLlhY8Bvayn͒CvGxf X8u%rtҹV._ͬ*υXU /ՁgD3J\0?|h\ڠ܂ dp0Z\>0l{fˀm \Vd0s!(1ΧdX!1[(Jt!8WU 0??v*l"G#N2j }b'^}7݊L} 7~~v9u,J ͧv@ۡ]:*/aZ:.=1GRZm/Rcf6,bщYٰ4N:Gڳ9$/?c. .Q( ?F}nց@l]Ӥ7u<; {D'‡9Nۙ~叼\F'؊Qqr^. *udJ*1_M%Xy, Vi, װuGҙ#xɓey_A7~9~)(5Woy|1oo .&K^Iz/us19n̽{!C=Jqd?b-/-Zb FKߨczԬ~{덟ai֟3BsԲԂ,|Ye7}x}gێ~ -޺9`mxnJ-kQڰa ضc)k_|pMvkNm_O͘ʊB?F}nց@}}j׾:+P:su 1vIk{t|N[9KYoۮC`~~w K:Ry-}r]:1:}tX9gyF(FHK˫u ЪF\d8/bGFS@ׁX+)<},\bT?- D 0UX% Lxo^U|k"Xk{PM2qi9NMS`ژ{cWh~ ?꜊^{HE:bשhV5Ϋw^e-D+pAW׋w9o.:p`<Ԭ: IkT [ILy{LA`{EHW ,\x}aXEZ__d+oL46W`yD3}(xXQrϩ e}#s?Rp<¹Ny҄{otW{sƱ_8L X(W.JJC*0F4҆eF\0hC/x;wB楚Bq&|lؔsxϭ#oY#m4}_Xy'*ϹxNE,++򲩰0-`:|,J"Ҽ 0F?{*/|`U8"-Q6.h /Ny#m#MLmEˍ…uCG,Z S&*`(/)Ɓy˂" hpk;TN8kr$rz+ pkG8}j4gBZeVeP+mh#,kBEk;M4V'TywVyXk;y}vr}}$S>&ihE:by'X5hzNփSGGQ1lOecn3Ĭ| |Y/g}=c_uuys9ʻ>+v* `ڠ$nߝ~wY* `WUI4)j-oՃM4r=o?F٩6۳RX~a9|l4rN*0c7罃gud{6>^}s9-s J%Uq'n72G[ȆKDR^z3n66n3|%}v m`}Iz[FEx3ԆLFC!Su>^"P'p!'/'o9Ji*xmouW)`Z$4n@=V =׺Ko~BE^m^k+]-z;u;g,4N\Oa$s<МcN>!zf7h+ߊZցp@7p?4NZ Ő_xL fCTK@&.^  5B @Y3/}:K7SGsoϊ== M>~L`}Sg~{Ԩ}&@c7kd) JBwk#s_QfU`:Rk:p q åg n̥m`¾[8:vAG B=Ϣ/_@F-V1s7'MX&.Cci:~݋}i+0I!2AXN ut&0 qp8&.8ϟ k` Q'?x}Į FllzN;p;>j:}1d.Vp:?,G3W2jkL`Cg}2 ǸNAhC;4>nG%.22y`SOWhAaKi6}i¢C V`B8T=w+1T2 kq4!BtB|빏;tK瞜ܟsu^y ,| d0v![p *Z vhLM6nc6Π2xx9!`aQ}5k ?/w8䙆rZj\ӧhg`fȁs=\W r!u@Hs}6>;uzN8'm qQӓϠ`Ju`ӦQoWR>J)c4 =aԩHz 쫱ˍ1sdq|B$( p2($\ x]k -{Qcyԡt˨ˠ9֧^+zN>MZ{P,3$`0m)N8;Oy#;jئMh%QlUǪϪp:PZlYFhW]&1X]x#GCM>}1?we5qq ;.\̭_DuIg-2OM@ցՁE:?-+ N  *g[P3`hr  {C(=@kpA"n笖|WCSWVM'qʏ&0cܽ>WP:N@T6& r fy=nĎ_ϧF.GwzҝO6sxq~X",ͺo9r3/KIc91G1 V~XIDjF=_mj`QƁA!шp%~3~%טzk5  pxcDb_(,Frc}fal[K "$D%z{v/*7 #Gҧ#l(H^R 0}{ i#^5ud%Ԏ1澴j8YKv@'/ +C`QȜWQXZb 04Yu|q!ާߢ~Wa àf@Lffav ^%jخ7x ʛ׳xͼy2׹Gs9FU{!55:3 C8C#{xl3s[aݻJYqn$YA:P@LVyOv._L28y](Ͼa"R"C(3]GMkL=h:ưOLGᆟ֟.x1kqx,AFwHf0~9exUcBSgw=Awy|V6\U:(D(IP` 0D"ZM6q~ƕo:Cda/0 j LAjGdA)?`4(i \(V.|j 0ƤeY|S#X\K=|T{5iXz?2ЌnК{3(JK{Y]ju ؒ&2VG^Ҡmo3@ 5@aEtF,b7b[4}R^}^@AXA Ġ:*[_cФ1ˁj4uԅFUhu cf cll^J˞bPbͺ2D4(xfb̞o̓P94n@euCOT$(.0.÷2upVfҭ9d2&ьPI܋e^0u!jU/}f1XOV" *l/ˆĚq)dp+"Je:`wrPcF1TV Ӹد}qɶ_5xhԼL\VbyrPƨ0@ y_} A#/۩5#6?k =E\c:T? 70D֨@Ŧw{sD(­Ahb~M3й2,`tb̼}lΆ%cYG@-Lt匕9\ƟQKmX>m!?[O]sMd{}s?|f6~%E!qw[  cxh5h{ =݉|R=(%j;2`э%eDr/ u щ0^Bka1ӯq?W>aV G8Y/9Bm@[e^cPV8GQw~VQ~ Cݠy~fSzKL\;盼L0^8Ccͺ}[n@) 1GeW*a=R{r\51Ӵ׾Cإʳs>G4 蓫Laj p\q# vhܫ;m+Ok`P`pMIu\aIgj!SwyVxw㽇-Y9r]c^e> ȋmÜX~=}Kg[wjF?JKO>Ioz![5v~s!|~'bˊ.vŬ,lwyA+m$'` (^6Y7ΖufUX}V`9}x'hܱ?cE/hчFPr p@U~, e/#p(P$Sc0Q`PH>ppqm>;n21i]p D Lܵ$ %Hkdžuvb L0{' mLIY&A*H'Z)@ 0[9Du~2Džea8?[,p̍l,ý/:߭){MK:[ƴ~/L7^p1'_NҼ<%wi" ۙ-\``xa!=V C j`^Fӯw3ro=jdqR='l|@ZaZ0d|ow7c2{u { Xޠ]Y)V oY.ʸ'%},` x` \pBvUi<3Hw/n<喇_33@` `Z+xox{v.ÖS{V]X7~GWPA^߆9!1|cHe!  `kVXt]hѮneDU"u=Ec}WLSCiO1a!8è%9jago2(>!.; D1f@d| 3`rL1׿ r'9:~9eb&Cds-@ O1l` u0TY͠k{4bQђϠp:P:v%vEe&a^:`:`1ДRx2]<\sܗ7K}=c0KeD6y~?xjv~NSB; ;Ź]Tݐ%K˃~62Qh}|0q`u!G ց 0vqK^&-8lxqzx*V@;v鹒%ҹ01܇ A܃<¼o>/fƅufQ`]J0>⠋>Ѓu;R~ - )@ nE(ǭ6D!6 ,Ƣi#Q1sցX+U`-Y!rϤ3gA?^=]C}aŀΆc;9=EhH ?^Q`L$MfLJ0m#=y0}ȳq@}_ ()q[J#41(1q/~3~xX6< =WX`&ZJ@v!A3A5dn#63v^GbZ޿M@7r%bf9fgmғ}&/=d( K7>,p;|?RG݃/wG5_2>)z܉=Ǭ9DŽ!L2@`d0liLV\>0m,:u V`.S_~A]b x߰ DS/V)|`nufo_lI 07FC )[Wpa 3C CgƺZE_UL=!J֡{M/`M:/qD=<77U"ց+C ( z@qZZ bTv5rq2CeC_la%m>M}ҽ LK!C1W!ƎA0}# uzLpvʨӷQ/'sxZP\m&""1v ۀ]NYJRL_:u @UV`Jn : ݄҇PaFy eUöl< &ۓ~] p7Sf\ %`!.Ds-G!…8fc.=n'#VPE:a= j|3%hw>0 [ly"#{Z6  156W6}a=[ml嬳*(߮ĵ<_Qc^u I+~XL](0B 0qBD?`|n,2Ϯ4hۋrşC0Уuԛm(As 6p*+S߷ªjN8ڪpڠ?l~#(0vJZSf&&5!їښP>A̘JkP}#nCu~WGB7i# NDD{O.}&ӝ4QKƁA`p1"2|` վ mZ$  mƊt1sul( 3`/*q H#'.m&̴fp8t[&1{vd?ǭ>XG}33Eiʚl3 .lGh܋q~` t&wH8A5B3]v_BHDGy9 80tdM>ـ~ܹٞf>g"` 5\-քԻ7" ďyYfc 7:/@ӷ2[iaF!* 3wYGb ň{C?s[2 MjZZ!b)4se: pFl( [lƁٯ=@0 1ni촇f 󄅻Lȋm ` 6B0j)=3YWɛG "p/LqoX}fasv(qSI|13[A"07::U  ~v HJs( , Ҍ šyPԁkhmf+S~Iov'k׷Ӑ;i4O%қkC\X,X%֨j7ZQI ^ЏN4m>,Vg5Ѡf2Y0Ih_`<:d`8b{as`'y9~ A M"&FcI#T'0{'biG b23(;+@ qdXa`ps: l m?+'CX|4 zZYI 4K@eQ)dt f3ZGms89Vj:y 9/ӄEiи 4vR+`3Bp}،x#sC1Lb݈תJar~4cjH񘯯gla~asvs`D^H'!HW@ 09oPuI8||G0@ KSAeWHc9`LX{ n\%)3m`<sb @3rre)`ϱ9 .EGxa E%6h~<Pn C odjGT&+Qf_rA؟njof5YT,1BD#΁Wbv_9+0PYam%T\K@K`Y ,%%wa΀g~}\cc'sTِ)7יQ`C c1D C@%* CW+-{ЭX.^2"|081YO 觃+% HHZަ`rGUm>+D`V6ǰJ'1_Cw!7 c%T5H|ךͮ< P[F}a8[a|!s? w"fzvVTTB, }T]'f~;qOՕFIb8.h h $-^cv!<凛Jg΂΂ӸFæ4t*skB 1 a$* JQ~D̓h 1/ ?Qc6Ƞʠ(@ B_K~(`ps6ثqBOY8AZ%7ݬκ,Ʊ 5Xwe,l30scNz؞ÑXzg Kvű9ks1s2ݎGOIx$%T+ 10W@ 6ZXa>܋ 0& `10zXj $o $-^FnCf b;B9!p 43Jl9y _ x^u8,DUhaP_&Dw 17N"@&& ^D?lc ɸ21SiD?2yI?Q OFKLK@J if #8κTT@QRCd蹀Oqa?@̯Yf2Ϝ4](0 A03 K=_a ;D*{1!`8#TSv+0,\^Sic%%Cc/JJ@Ⱥ@q ++am\{ F>>>0L߄ ق< b|b/jL@"T`C@%miC?0g"\C04`0i h +m+l XXj(*2yf velv>>HiX0*x`:0>Vbʠ4a?LB1yO{L--/vŐk@R6c&q3Y ZXxceN49Hζ\u}F]aAsۣ z Ws'b1T"amK_@>3O#ܜ?l*3gWV?b-ZI / g\>1lqĻpMX@l,6 /|{<\ :q__`C6u [y݀f^JLbdx3AI_m9tT/d6K]UHb9 j 0) 3yV +!64!i܌PV KJfq؂ `C5c 㖇_ ߥ^jY0aRpAĵ(02_6qQo[~:_ ,Ԝ11cQɭ^^K Hb}i+P9 Ta7}eTRqND蹈*|yzm9`  Q_^LO[1;!Ab7& kY0C_Y(pyO'~&xr!^@`c"=ir-- ,Xv}|+ǀIuɱs^Y )m(Ér,!͂ (~5J0$0"0Ff)J 1kA1[ ע 3 eg:8. y?˯\4Wa&xL%]G/%HZ5(DǍ0ٶ!} 6Y1N B=8;ӤA}-5b{|V`=[c0Ɵ|@It* 0;юN!f1E O&0L#pP`xX p^vn(.@K i%"nA3!JaؚVYٖ0nj'靼^˹s-*c[)…H?)`: D Da $`&J j &2,7SA`XB )>wLu)bhZQ,Xn1n <ŷa%Chsi>?KY^`l) %L0z2 `f4iN0ŶmAbxsY3 AL 鮜`Ƅ@ء}aQl]4+-@̯DAh~\lwT*m>xs>5* F%:CDp.a6)u>וP`Uq&.BJMzѥ:@J iT p| xݤAP %oއ` 煸>.Ͼi%0~d¼i9rn|%*ǰ{]8k0d1hZZ\ 0V`N?V.CAdԒ.sԔ|yK^ǵB\߁D$Ȣ+.cVYcs}_pâu/ kh^3v!F/%HZ~-e7|Bl,hcr:.y]p*rJl2O#5x*4n}obzgaxYgfv>'X>r\KľpqXŝ/b +@@R̙B6JCavy;$^> vnxǘś =Ygsc<w%%Hj3x# RK@K K iS2HW`hf;AYUQ`OtZz{ZqSI 0Qeey[wmܸs;-j6E Pcp/wk $[ ބۮk<|RLR= tU]tMް2ˆYVhL~ByVlͦ>O@Ix xU]f~TRiN[y] 6z⥩Q)RV[ʚ7X~eJ gyU_<66zOZ.pX _n+p+TE,jr+}*i~V7 2HTV­P0lY G) B ^$[ϣ%Q)RVX$ Rcb>|mo`0weRc~ITbV()wp{0+.6#Y}-h@".`.B_Vxp1[bh@4?---pXKy, %nRow%(%n{@SZe)V(X4zZ[7 w%%PEq|W0w^(7_HP­PcZ N_$\* jV(XUkjy_7 Pj 09}@"TQ&nRMޟ@@MB(/p+,>@K &W_/KzztwvvY縏{4^(W/[`ikZ_7 >Zje\*,,[AAAu9fsǽGt~}'>(_, }B-x,X=yt)JKKt>|8\9^#W: IX{PGy\Q(gX<`o69s:D~ muqi%VVV}?Yb 1Ϗ{D|`Hj k $5ZhAgϞ5p mu/x+_ImTڵkرm淭[lvI{Xxi}i $ $5*R }UҷuX1(X2 ,}B-D(fZlBיBCv-0r;s1J^rP !.C݇c 1}y~Wg%%>ϛ` 4bh}v\7o+B)0E;ZD6B7Gy\,9}*-D)> ?Cnb]<6vl(х^v5ĕxA3h>?%O]SK J iBE*0чac!8.m@`vw'* `>PA-.k`fp+)D% pAQC.K(҂딥 /F L(?uO-+\[2=u@B bu}!Cje mHmj,0(?(:7pϏ.k`WVE4)j`ڏ?hXC)0?k>0sytV4>4wy"@@ }3pq! `d s50#"Q` X;vJJJf搓'ORqqpƍ:x҆ brEjX`v@=X:Ch f6|oe|'N0͟?[ꫯhѴj*{ FkWHDE }~P<,y}2-D)\\Q`e.8}O7o60lЇ1 .;K藿%4a3^.h(_g%%"[My)0jso˫SooKe+#GШQnZ^z)]ve 4lfR>B)HV`BLΆAJK J ֺuk&PCbh̽eؗu ;z'TMQQY't^ ~,~3:QB%b?XU%\QK 9K iIX KY>xv:4Nɓ' ZnlK/0e+_BIZE)0 >@"@X[ Gq菃bP]ytm/LuԡjժՖ.I+ۿs.bB_zth*0Ȝ?qG--C ךdݽtet~sD"3|D`p1Xn& 1ĉMu(35gYą ,y}2-x/=L*gCR1>6k G.?D(~^1q-~&*nD a^^zP}h&uX`P$t~ƌJow 4W߮];3mզM3# զ*!i T|_ {p ͹۴ic\sw14m iswt>[n@}kP]Lf;wlfcЎ=wz[4_.Īl3k G $-`lWsԂ}Leq.\hs8 ^7nfo1y`)̿(DmfA4>>~zZU`Px)0[ PlUc+` sKԒ^j2ϋRMHUY>{[(Dm:u :[uS nQEЏyD.]Ԅ#d^4ib:#&Y[1;o+q,ȹlmm4֕pM F) :`miCcs:^yy@d/~e{w<׏/{y1.pV v!F; 14w߫~Y*`B( 0{v'vcc}k8B1h2 FLMM5s%GQ(WAPi#R^[_eՁv!ڊFԅ n;V@p]1!/诹aÆ(P!8mv1ϏTRUj:I)ą4vmR9nuf+[S6nu 7"1y1cXncuV佻v~+B}cL)y)#uh>(0 F)%}ցv!B1wLK'yq[) q/~? >}@̾w+{rJ_]i]I:SAI\7܍B P1^-[4 xȱzj:{Q^Q뻡Iz`F S5L+0]`?̌H`cG}~@ӆ)&}ԁ Lʫ@E?~/+V}ģý|`cǮi$[)BR+n$iSdPWPCi…f>Go+0 І)&}ԁv!ew)e]Va]K6W "J9sƯ6{-Uk'Xb 0 Y-Jl%&D0f8DDƍ2==|w_]/O`(a0%cäϤ::sA!H(z0bX)0QapRqȌ:C ĢP`(WΏ]h=I:Sׅ- ČxLkKffs&X B cBF@*5-u uR2f 9oiOЮD1޳%|{C#m˶{?αӸ62w{7F p8*0u?&CeHH{RZM@ց55ROPbl* }c*,Sp^*-Ub mi}&ih:P:vS1T`1`lZ(uK}(oav 4엾0VR^0p_ư|= 򚷵XM@ցhOsvG$Qk 1F"W46 wz󽮑j[}yqoj޷o>~{Ϗ'.D6<ٳgԴ h!hO 'l"Ce(0\xp&BܿiUb*̍'h֦RM@ցHIn?h"Ӟ)8X+Ky) jfG<HD ^ ̾`d8j2珥M[w?Q RM@ց@IIMmHs&ZqWch]sm+ w{~[x\/gQx.o`#Xqq5-Z"EEN1y\kVowGц@`/ ,A4~oԴ S"-e5Xa lCya FeH_X,8D^VH1gG /f}{^8*+ﲎs MS'XB ..|0 8@m(ii%}r Z\ny%]v x|/|c/Χ#jq^h`N{^YxYyu4w[bD6I}.L `O,` <Ϗg0zXX+ 0QfrRpJNun갬{ +w _ )# h6 *ݑ@Y]8.D 1V `j_6$¾Pߝs9ϝ}+e=ǎlyW`H8a**Rxy`\E/uX7HWB]_b5|͡r,PK2pyvwVC^Γ<ǂ]r@^x uoZWzX> Hnb ~@*^?A s8 J^׍"'2[` 믿{1z衇VRAOH7QMˠ:FWzTXMhCzNLW)/h;r$GM@ց@aAi?vQ}^}Ţ,&WSFOrs)XeYix, }u;o-]SI%ԥcT2:Y@{r(UT`WVI4)jbh8cGE}^.`iC5>]S Դ h(W@;Ҥ0*:OXTJnhTR0c bT. Ͻo俚(7{MPIq,07/>/xMYgRqQ>WB:Y|Niցӧyk5-:9FN()`X00 p/_SS@u )]U`)6,Աp 4ILL@X0+6ZZu )f+$/_(WWGY.j?Ǯߋ~/V` 0Z(&dM<D^` 0Z(&d[22F@ꪸK2. }kL9" 0XD&ʥi+22G:o7fw'C(fca, IҴ՘QU0Zao"LSm)NFiH̵̵xާSjepg)T`WTkCu@ց:v;wٳ3jV9sO3T?rݙJ)Z:L!mh:l.(T:RcH.eeu:yXU%%Eth3`ցXq r츚UEE\:^~xZZZ.LuVV5ý^QQX,M?ijj^(1@Klõk^L'N#ٔy@?,,\|I#;VPyl#|/‚,PE?΋qjjj]* ` eՙ F*t& qZ`Ґ6c4#`i}ǎPA~&eWTEu@@<ՁR{*9[bqǎ32`L#{FY@bցDIP@&Ȣ<uCJgP%E9޴WI;Vx-ǽG6qhSW` u 9 }=Gcjn}r]x}r}9GyqHqڑqr4=F=Q^Pjepg=c7`yBTye@ Zi ܜC~pʤǵ:u"́V 09:|p`iyvT_I: ͠\끡UP^ޭ`G F)`UDoPY[KJ WӁ}[)m6^ ?u3ٱf̟oQ{m,Š`56ZmG['L`iۆ4y z^Ԥ0~%uD&+"(H Vju@@vV w4nx}&S ,(7{3PIqLm8h: k,.GdITc\&G)=hu@ց :TD׊ۊu@@Yu@}` nZ$dPiMȊ[?3=޵$P)`ZhH:ӊW]'k;.(` 0Z$dPiMȊ[?3=޵$P)`ZhH:ӊW]'k;.(` 0Z$d =N4)j+ LjZZh::P=RRSIO.=;ö;R؆Wתsmx3t}7:@!vy7[$yǪ ½׈Ӆ=[1店(>cDu&}C:< ;YQ2:u@ց?fIENDB`libqxt-0.6.2/doc/src/images/qxtconfirmationmessage.png000066400000000000000000000207041215241066400231270ustar00rootroot00000000000000PNG  IHDR IDATxwxTU?Lz %P4-}H ]tQYĆkhR[H +ɤd&3I=gs9y9̝ʲsǤjXL?MVUЩ l+ZXX}LL dOWecRͮleV kӟ{XLI(*.GuRr(Q IFiC&o@?dԩG="_T2wB[/.Iʑ[~4Wm֑Nc3wuyxsr;ԁre9o]_@Nޅw+ ܶғ~Gvdeez \pq)W|?;EH}Lp/zw 7ghgkm=M˖-(֎Wgp '()5,.{w=#xAfqݱOڲb\ BqtV#c YNqI9)?JAa̟69Wzń扫R%owzkC!8OU_cROmҴwF{& jQ((_4BQfJˌ]=B굋8% Ґٹr3oO JJee}nJm~wnED_t٠` MOpsdvض/ rWLp} ./{E֚OO5hU1wzwkiSmQ|9z:oo/$II`H' Ӳru5'f0/o>GX'/1|`+ ض/-;b7[U}5!huKd>N^Q$StvEpo kcZXoFm0俸K:|2oǟnZ!u"ϕ=~--,oΓSLt?B&I{ʱЉtlޣI]Ngʀ)+Wi;bpk<vUoN!sT)?{0?ߒ'MڪL˕I8'2{XP*oe4ڒfU˨/fPt?eaNet@fB^n4Ǵ{iIGAz{i|,S`hr;IKөKNTti/,a|zӵ?;.l}Yo/jm~=/PT+wǯ():S;*?dVDFxeO#W-@2|vwr"atϮsP$ QrR.Զe*?uj]._`XkU_gNX/X8~j \%U{~sݗ2ԖNjff5SU$IE~mPʈpN  +p~&+O`wgdfP]І@o28tBEfx{("`vn޼$IdgpV_BBζ@ۆp۷t8m[3fDprtкűڱ2v4ߪVgչh3)w}#Q/8:CJJvX:>^.2[b3^}z*w? ՐfFSj;n&&͐Sױ;7''wL z=7'Rl'fdV{+XEEI;6çTe`pϋWҧG$d\b-Hޑ=B-(Tŀ~8|N]hmWЯW[b: ëyExI^~^ܼjoJkgcs>/OW~KRp$d2ukUr{G*j5o\A 99k|GN}8z_O$KTdcFvgҸ~t Gq B}iĘ=4g/QiOX᧏VOF&;7_o7=/(j4o^n#+3@&3;{j1K s y AQ<(//GU*e ros ƍI!8:9&#{ I^ǓO$3Wl'=qz EŔ$(Qں"yŌՓqvry?3' Җ9vZ1lpg\\\'ّ7e4T[?ek|bj^RV.=$0G4lp4.<:(Z{CVR*`,X-%v=p͕[GeNB0R򹞘R%i7m(ap=1SO̘tzs:vdO<=qwsv r_z^"㝵i?/zf! 3WT\ ڤA,AH^/4 d2;{v /w{He\ܱ֕WXu{6&=32 J?\z.(E %_|gg/'_yt`{^[s~@aQ9?ˈ!~9QRZNlmv\N.-ԯyl{=ې94۟o9]xn#ծ.2j嚠KDKc(/Wp+GkvcFtEx3 19v3;?:poOWkǟv0^Qɾ삩5o"؏5|γ &SY&2X[w$%JPѬV8? OL|]),*'K02y~@=3;d@89y{H%,ZݽNPh[|]2Lۖҽbd(+.BST*yiۦ!<5}*EEEͥMdK*ѶM+233))Q%"< PRi[C{ЌF법~vC|:ɝ;whŽ{_{7u$D1&##C79!.]ӶQ;1W}JJJ7w6!DEEkk-ӪڡoϦϿSh۷Qb-))'2nxb%%AkϜ>ŁT[qa'/XnoooFƍi[rKM鳜:GrrVs_fϚKH8W(!Cjsvщ]?n!}1slo$r=>vXlN]dϻtaÇ`).]FVvIwO``PUqӧE`Q~;Ǝk^'LS$&&R^^իWxjTt邫/vj0z/[Bff&,^ch;vﯥ}va>m*׮]J [C>{4p0v P舳3,\dōx1wk*c;K^)_Ƙ EźyL˓ Wegӷ/HBC9)FUc[/ 55>}jӖ/_@ݺv{BBCYl6k?`D!)1 $aAK_i~2\Wu3dPm^\N`x|}5V~ p'2ϒ%K#Sɯo̱>Ȟ_[8srH7lԔT{dze2|~=?Ś^> 9d~bLcGgS`4X$T*ӧOgT*i5y/b)\P'bZ'^LST̘1+C_3g}&GRFll,?FckG,KG֪ƍСPhAA̘1%Koijw3'>(U폺on T}LDU(3{XT5׿ޫׯgʔ)*>LTQ8~v.1F4U9At<ֺon T}LD}Uc_=Zk_AS>Ȝ9t8::ZGmڴ٩>LwuZ)//'$8 uԮDuZn xF+׌y#6`qq1fgQt̙;#F`ݻ͛fÆ7ڷիl;N“Oh@ض}'-[ 11bS>1?AP5|F,0͚5KGag͚e!2n%hM?"fxumFxxvgsק1 S/ji&mZ6m7mڤlmw۵ixi@rrvgsXzU7_WʬmMSϜ5co@TL?Ͳ"33h}cVE{iݺuL4I&n:d2Y4sXU|~bY_۸0U96kZ͉˖ӓNӷO/zꅃ ,Kzj`L|2_gĝ`iSFhc'jU^`y #sG6}O0ׇM-W^]ŪURZZjP E1 O0ZDpb ֺ jF7-Yּ$I޻,Y\yͻc߾\#\9Ι3Es+6[wp&LZ}'٫UJZTN<kVY@w66!VIIR62JڵyxsVz"I* Vz \YEbcBJj iiif{nk?Y]/ב.I*~Ῥzu5k&?}j #MkFo6S-zݻqim{RS0a5:zL&oذw׼Úwř_֨vjaO,3Փ$&Leet õdff6B Tq@T+\Kl7׾kb@@ ۷ 8$D6u~>K .GkT;+a5kSis 4)!T4$%%ic޺u  jbi0/]Ih|cҤ<3$&$RZZƕ+W5k6\zʕJJeۨ#kSRՇNN,x| '3/L3Xl)O<ڱ}$/72 ƍͽ4F eG6$%"22aӌGVѣǰ?t˖9-4I6!V k(;wSuڒ`޼̛PMQF1j(y_6L|}N5鎎~VξMmYIa!oIi6C?_7|VAЬxpQOwohaO7M{]f̗XoŎ ڙ1pKb5haf 'CIDAT؄X5Bܹ6ԦBkYm [MKݺtt%Kb5hay9EPЪmΪT:sn]: I*ޥ\X55eHW%%3'noWXڞjL8oLKbHļysټ[>ȔO>Iضu++ƍ_I!#)QX4L0zҦX-/<7:267U}:2fԈՋU,^x–X/ȯy}4I6x"1k!5ӯCV2 j&@`3 6@`# 6@`# 6@`# 6@`#n8nJK!Lk!#-i@ 0=N( IDATx{\W$.! xUV[qk]ԮZ-/뫭RV,+RVe7mՂUnն VED \BNǙd.|?~9<y9ssVnH:\%̓SNv)0a|b5kV'Y=̙3g<|0B{[ZZl'EӉYf>| lo!B1L]ð @'c\wذaEEE%:c:t(BHT>3qqqnnn̂kuw~GG]~r 󴸸ݻ [n}D* *..(.Э.gSct] <<<6lpI\x٧~:44$((y §ƍe._>.AdK ޻w/}>vؘ1c|M@53Q7RhZ⁛m۶MTX+AYfa7Ν;7**ёneĉWZRXZZZRR+ @'  p9~l ׭ի>.//_p!Ia(U5ͧ~RJJJ^|E'''f+&M"U=%%O>>'%|?Ϭ#a̫W3^ʭe潮4Kn۶mʔ)oƍ'NJ7VXXXUUMoӧB瞛>}zTTӧO~V5r_~6w\S 駟y`[[ ü-jRpuR9yz kNJJZ~ҥKB׮]C-^xܹͣ-zg[[[]6dرcغu lBQb5>3g /֔̚5kV\ B#Eٳgƌ9ϥ`57o{912/\p!2u},2X o5dt 7[fEt w] .@n@@Çg̘aS0^oii#Eϵ"0òrЕZV2 gĻ… U*Ug=_5//ϬdHHHhh… ÿ\[Db7_~kV2)) !JwCtkHT>`ǎZzg7Pѥ/-|p?ǥ|nۛ'iNmB3{GK>pvvNOO7OIIimmeJfff;wNRÇ*a[eYYYYYYbnyYPP J񁗗 3 l$ |\D(tRy飏>2sEtS)jyP 7o&&&~jJc0g>+ӟ0^ M$xYVԫ@ л's%EQ?Ò%KKc z=.$cP>lΝ9992޽{L$Io\ſRk Bak)ruuU(H$t m<.XG899566R%Y`/Y*oo׷ln~Z?ⶸ:7oޜ31J7%)))66k˃uiJj*S$|=MQK9wijAj/$7kZu~ZArw1++!$T8[vv6BhĈiii:)z :t^1XJp,/''';;W{AAAff&br%m% X5}tZܼm6:+111_}թVOs=\ϔ $Idd$ceٲe (}zjjMһwzJ%kujQJDޥuOQfռ`u:jkkW\o_IC`WƎ+oۈ͒%KLJKK[h̙3,AT3gZ465,, аN 7?R%&3Z2۠DC&ikC 5k d4=KG!u )>B#HDArDMԝ:NKVTŴ't]Si ׬&{.Y*)LNC:$p]B׭f?@'#D.Ẑd=گ:3s[Ku-"`0h4+V.9m:ۻmafh>s77 fX t)s]*͏[K&12͛8ڻw/]HQԥKNj*\fYrezzJ3gΜ9spaDDI&ʼn`{xrݨ,<_o9{yt9W'Of^bnWo'}K+ uqv~rLUxPEdnn9sH dbIPԍ9W}S!7rؿ_>GqwZ)2s*+gJ;; e>t1}-}lu[)Ӯoͻ{AOL)w!&݃6m#-Z퉺BKQTN~aCKg-Y kh-rйQҰѻCm Y9Ľ*//lj>Ҵ置N>5oK_}r뉚Sf!ޫa___DW_F娜g9B"i>{4;L4[0GFF2?+/|0o޼1, e # 4{9! q>ԯNR|)CSziOe/rԸT47PޯW-7{WxW_7eT\+9R]|*}c9scW==J`s Amw8 s%]w3t!I0Q+J<(ydAɓ_Eg3Fӽ*>0% LuX?WQQq咒faJ#3c_o'5˾}>JVrV&78wI Эc>vW$늡w?A,V\n:VQ-*E}h4˕G~Ww -۷oyy9e ĥ8<<$IcTǪـ,+R %PNJ*K(?S: shȑ555fȑV+{F]&#D D 4!G,̡Yf:t7?ժ ح+ChBMA!G,fq… ^ƙٳ좃Ξ=ȑ#G孢h(^^^[qSV*M+g0'ӞرcVe&ГAKAA'H7$xJJy9JEx񢏏ViVVVVV>eOOO_~=>uvvNOO7̫ÇWڡCrZ$ôQN'SVku?)A>G~+/--e"HLY.)Ja5k|'fڵEIRNЀO7nܸQFݹs_T*Jx`.VTӛelz86//FIP8s~Æ tjɓ'Ϝ9C+gfMNMM}WF#B(**nnn*QPPСCz=30'''77VGdg´ɴ+.gu)))"S˖-˗/^1oUj* ,,ԩSX`WWwyG.XB@ԭ6=ОCo}X`;NoxiϞCo6fSuS'9zKvAx4 nI{P}'b\,֭gd+2s,vL! X`e !wJ@7k!Ȓ:sHP$&&Z}6G뢮NCQ/E?=^EFJrBz͛6b!y!bc^fq3{L5E͊xӒ.$II}񁎃{)]]p9iҤUV!H0'tŻ`\\\xu7-6۷B9xb'|2m4P|||jj*ނGNM$B.jpwwǴ,Y… xef,pPU1Q(J]wAI s`Uջvz嗱YKQԥKNu9 !pŋ/_IDpԭ3ua?1n!VSx))) XѸnݺ+W=Y^XXtR NfT% 2s#nݺ/ 9$H{#FN(|cccccPԕiM 111Æ do6.yB!،lpϲe[ZZ( ;5P(^{M617h4-Zf w2: Knnn.BHhϡR\X<IIIb322^}Uz!zZurD-!׍ݑ-^%z,!!!⅙B;[!&S)L" Ȥ? e˓`LeZA )9XOq75?o۩"vXǘʴOƊ׭`:~{LPs/r/6o)]D+^QĒMu'g)_z!c_VE544) }`!]f~wJ*҆ry}Ο<2z>=~1~SLSk۩ י~xBIƪ;sO ;:P=k ޾.TjoAܨpۄڦ?^*M>Hiqdz$]ZBU]Z;oyW'<>uMelT*9p]C˰AV)nՉsMjA,ݽvfN՚{ =~>/W<$z9ܵ /N8}] ׷,$s]߫UwnAe2gF"B-X32?-1ߣ;؏v0 ]U"ͭ@w~[SScV`0X^ɳC-[C;sSfsA{ )nuMVQP`yRRtS Vҟ.|'| )fan҉cԩSztY0at]{;0\.vBIENDB`libqxt-0.6.2/doc/src/images/qxtcountrymodel.png000066400000000000000000000045011215241066400216130ustar00rootroot00000000000000PNG  IHDR Od֑PLTEU~IDATxokt!Fvn` y=y( u 1M2V2<7a  >̓2kyF:`Izyiڒ-R ظWWJP(őG\gC+F%vSA!z0R9K[Zr-@8`(\ A|e> g^T+@8`(BlG 09,e(o3wf\Fe{L]ɾzO7*4aoNȯU#zf,P0sRq 437嘤'l;*O/]V}`l!µ=080sWiXq15V?2瀁뛅E80g=[I0Dp܊f^?,pyC۫~cœ0XI8gN -ر֜~X {$-u5ax% BP( Yk.ߜU/OT X C` 2%e9s$E_ʯAߧRǶB- soһ^eꏣIfz)%7ȝɑ^$ؒ"\{MߺM[][OiDT +5 =I_?⦽͉D3-VI)0h  BP(ԋ{6?"ycFG ZѢr U (BF,}uBTVƁ% `]~d}n틏ڬ%BYɟlT]iiEt֮9~.*@4yUȷC m1 3<0+3@WHE|"(y(ƐE/W?] .@OKfG嵤"`(#flpnM `D'b'ԬX{MinһdYx EX;( BPXWcz\:]!up@-]?&sEek:@pΆ%u$!>a N @CO @Cb' ^Y렜sgl]s ;dp"6{0,Ix@'[G" BP(T9Ԭtփ#f>:1x%Lh̐,?CY+yy7DCA$W;l&2L\d=KUj{LM x9S!B!X{C!Brc{ϣ>$B!x/ԺHBTUEUU֍EAQ]B!B|z6@rOqJ)4(.'5~!B!M IP컁jZ/mtw4Z1^9N!}ʲ;Sԕ~kGyWU=[+++~^n[!w笐8_#/9_S+#L)3'p8!IӔO~W.;)VVVx+_777_EyJ!ݿm1^d++o>ȭw'/C'!RO4c<s~x;x{áCx;{^7rawr}qײ;N>Rɟѣh7l?qտW<o۹9u{xQJe}{y׻[^3LxGЇ>_Bo'0yN W;瀿~kEsnB7wwez׻H{ixG?pÇ?a^mu]guu*N9g[V>믧*n6~~U躎m5'@UUqxza!wo}ex[?oymɱc`<#BB "W2_9s ?0.\̙3s=-oᓟ$g%M\9si|myy0 ԧ>Żn9g>ny'9t'N੧ѣ;wmMo{W%o7?|F]oydr8~E!˞|In6$o__C~;/yK$Z'cnĉyy>9>w{ʱ_=o'N<綏?wwB,̟ɟv.{1P|SDi[Bqu|3{ess??_5>я|`kkloo}~WO׿s=$IG>N8R]رclmm/cϟ?>FɄ|#\>9^WlmmCMB!_& p]w1J)b|dk<{[xk__{gBuB4FG0*Vi]6@ *1`l Q\C|GyЩ:p0i9yCk DBh"(B1wXY`2y駯:|Hjޢ0yB"]w Ν庣o\GyOqB$TcyO4I#@ A]TӖ* (1F(eyd}c鼡m[4ﯯ4!5"IdalF -mWӵ,O'$iFt5 xg ]DRW>p5#\;m4[&p6 JCyBThx!2fC "ւw i&lo7Kǚ0V9J"y#_;:`)m1 +<1 ekk,.ik:K3$&isDuv,u u]r@L&o3ޥRKIfϞ RrY57c>W&eՍ=L3U HCJU9WWIlJVtؑ("/X][b Rk(t2c6$x2fz*y)-gܥKH=cPZѶ !CHؑ&pGd:g:k]rk zMt 0Ɛgk ռ!E}Z_ JJE$ 6=AI1(i<-!!4ՌyUQ 4 'FѨj泚z^TbG<́N|Vah*(S抪v7yk^!Ϝ>þlG8} 7F%MSgwgJJ^DcZ$$K(R1Zu<"iLDkE&1b&0MD|.Yjq={ ҬhR2pit"ISAd6aԌ9aI]t]$`8f)^{)ʒ"D'sTUMt;ϠgrM7\$KϟAӯ VYZY\Gf0;1x4Ekw|`sL;wMGz&M ǩr< Dt>ģ_rQ!wpH B\׿ZΟ?4R9AN%t[jljk(Uд-Z+V7J̢%xt0Uԕ;ET i4KQ֣l j]=4upq;2،L$L+?+$&%YR}Bi@c͝)*L@G\q^5&o!3xhTrd2k5IZisC'-"xRqAWڈk6V1ewwWpdu{ zn O=/}8cMX\tq 4-ΓyYT`yu$KAgc Bj-JJk YV@Tyyt8א82X[Zg^)}l]ɓ,OP1%K3v7Jcti,%IR:61h$֢ Y][K+IF䘴jkط tXڣGX߷ ݡnZ(Meտ.2Vxhꖦڎ9$!FH`:7;O\Σ{QѺZicZCr\y"Dq\:N>ݿJ3Pt䙡<=G'sGS)WHYe{gj8vl^cIÕ5Egi-m`3ж/ Kɒ%Y^]fuck8u)?|+gϞgZM8 !.Gcps%Ecf2t3!bLdyuW(!o}QsA6.P]1(&3Gڶ%OSw(MgxqQ%5\|՚j~ _;SOc6S1X G+EӴD\ (_cJaSh cmuHQb8ȩ&;Y h&VxiNdV1jbcS]Հ,.F}yC556׸x**b{?CoQ .Q ywDsa;v⪟3/ HW͍ĩO (!>,NjT$; &1pTS[cI2o;tb=Z\$񴍣m($MP}e>DLff,M 81iICƵN$Vi+HSN$+46t#t_?dž4Md&ٴfei=kay .v"a0zPƐrAns(RL4S;/8|7=:^uo C̛qJY1jYۡ[QC"M `ނJ-mȲ=z̷n ~GKLFl`5m&)6Olj~ڃ3Ce0y(%5B2o2܄zRZ5s,e#Fvm!O3z¼%rtU*pq|l4'D#diT0:`e۰='p9$e:(eԕRDitox\JVR VS)ifhubdYNdxf4MG_}77'hĠ1I'KSl}`cu:4\殿-!x@"j^қ޹6;,C `!~ !TcՇO!27hm*uD)CԠBkISCU!eLUnhrUCz8IEdFs|'p%~#ٝNp_ #+BhPPϧ$iJ}_s5QC@V}QAXeE$iJdtmS5mRf e491Z t~'Os☴HRCQloW>44mKRy \> O2ϸxn5u]B% &M0Ei" l`ޒvRk"go}@zRVL9꺡"`ڄ$&MSF!yއdrXW%ҔX4c4*i-]q'K-QNjeƗ"OB`HW 7\g1V%Z4u.D.oݪ@I4NQIu,JSA+FW$O9"'EYǖ\`mV{K)| fXY6ԎDogo>DFC h]PO6Z6Oq)x7p3yqYEU5dPfJGlQ9"7$rUk:2ͨvg ӢoVW(VY?@5u0J%׼@l6WLBw)Cu(:GY.sѧCB!Dqr?h@8&9"wd*!xs#FYv7gi2BIBDyFj,&D]EhՏCueT QTCGiҶ)\i1=Zk*ib IDATs 9WT՜fZEv>T$2 ̑}ĵ ;sxNg\1ޭP:s-{PSLIy\=?J*qE54ME;Huo ?E?%<AkMYOMSMh\:;Ϝ&K57p x;ۗvY3gɆK&cyjw"`U|:ccc/w<?}*pkvf,#yC6pG¥D6 ƻȓWrKn3#'*UP9֊D{G I`9?{ߡuoh%z61.ukybp!R m0Fg -ey)#KsײCՍy%z;^]|}f|fEtuW$JcU4M==i^ z &%<η|B I Bi& ]0c{<[ *7%j3&hi1(E1(Xy, ]hت;R呁J%6Cd:RCyt Gh~B4#Zx^6غCZ^=beψ_9سq ?a=fO1k+$=}#Es͵*Ē'  S8ݘt}lM ӺeX8hچDt\࡯5$(aBbFzqpg>O\`4M?dr߈z:c ۡC{y+_x5:=l! !)B<^9YeQ!D W6b>@Z&zVmڗu֑ؗ؄Yࣺ 2n?鋈Ն 4dh6c﹅$?-<}Afr9Ӛ\O{Ax8_`K$1$IId8L1*C5@$]Vs Yf+$Ei`Xn -3!pa.Cd.HYM/, 7 fm.yAiayBHɖQ5-&HT̳.{R⽧EW j,fеQ0_Ъ.(0} X4^i 3`e6h掺4FM>;,m/X_]{GpPhP*2 Jo`ɸmZ[",K(VDguTCG68|>\[c]:=vt2iBtVѸ$Yc󂣞9PMaU5E)CD~þ%K,l:f8Zn,S' kc2QZtxH% +0Ilw$MS BD)˒ s"c:r.mm`@9(QQOҸH( Pm47%7r&k+<}*MUʂ]:Ҵ l9//ZFK9= ? ;~k~=?<<9.h};@NBbl2.')L'C%b')v8!U l@h f4}w9Ys{yw'e~ǽغ'Ȼ~^t $H-g#rt0cv+GYZҭY"*G.0NFl5#2)gdBD,]9:S7#F1>$*1XE3rH-y,AkMgw)$iP0_,.D2`:)Ӻs~uIPB$)!&&oK|~__{ێAWF+q݉LU!R %2gr!"Iȁb)6GbJs* 䱤K,Bڶ#aQR}+R.!JT/Byv ~.xRg( ܾp [0aCZHֵ )%{%Ix0$)Z-1 Q RTlM,W3V+.X.g,Kg))M M]s>dl4 <{wp|ϟ?wr|t_yGxe_;}/>},׎D#D mR Y2ed$:GJ+$=h -*{pm4 UeXRKpンWo$;Ǖs}puAwTf!{[0op{'5>$U~Ϟ8==W BDX8BkM׵loWت!鄉c\ЇGr:TT{b(Z.BkeJLHzTŠkc;B+r#Hb,Hq>2숇 ?}K\<{o'uR_'ĿS@}J;wɟz[_cK&8{?KCSօk@Kׯ)!Wˢxo +X_W̗"ӟ)J TQ[r'uRoWiێQ]3˜cZ7dw(.NZ1b#8W6eRdԍDIjւ gk%@Iɣ$!b") 03R)V> ¡t{Az% #kRHo׉PJJa1 Xm!WqE)/y I6VH8}+үtЭ5͔%]Ȍ<)e@X3oY~Af[߃L}?r}+UG6ŲEKEe ZskgtiFR VrBȒƱ4j̲4; 31Izw%Q\tG??-X Tڪ9<9\_sd(ZKٿ,˿7ͯь$AO?9]@UvQ5ש#pzr؞mfEɢHIY/(S9\? 78i]֪:˞_3/9{_gwVqR'!}'|r{WQ-W"AD$Ϝ}KVҲfܰEaySM$BVĘxx1q8܏m/ !z/򻪷 )JN0%:D$V+܉IRG) Hi`"9 !D_?+rH!p}d.ޑE"fWdHFR.:C 3RLcb,f3+5㢿05lՄ!()UDҰiQ-1V0Đ i[)AS"RbDŬ+t rx{ JVb#Bi6TUs LG .͑B"Q|1G+@ω-- ~a^x1?:b1[_kǜ?Y|w$,WmϾp6 xMCVP)|D!SkRu=BeqE۷dg:b!XM&1MS5\x *'{fTmF/qp`s4z:r.`vs~gyw3?:~'&g.w+]Ϊu{!^|Yդ`[c6;^ࣀJx6 IfSRM3Adbhc8>ZBPR!Kܪege-l~ R!$C?ʕye^~D[{65Nꤾzwem1n8N_?Á k/q.Ae6"rFdBoX#܍\#:3(6#򐲮Ĝc)Gg˙D,9C=e)Hymi)B"f$s ۻ (B$ZItbCdY:e#e%HA?;yߪeG3R,J6t٦ PRMn*ֽP&$HL 0*BBJU)KΉ"xgΡ%ޖTs|S YD|I1Җs&EI{K$ ! _M[JE1^<%JIw -.d|PRPY4vAVXba5JeRhJ(RS&0VP.:emBIfڰwz a)Dydcёf5jU/!IlV$i{F\dJbHZbސTą"*ӐG5'\9 ;abՒb>k )3swz:]b#-H,--)u+x/<)$\zLpKCvŲ;^{^e=%PKlP2Rq}ڎ$( $v>oKs/R3g>Ռm1;e5_oYZBy(]|:}x_3_"ϟ(9T$FMh2LMS׿Ҩ믽$!I 1AOH'ǯ}^r*3Tn:@4>䰎 Z@ 9B(OCJԏ}gJ ryy}_9I GUBX7A*1A,2о_[ް ,dw7clH[BbDPF/BG%')@s)oOS!,7\# ~NUqPny H)%ZF ;4' XW),RѤ$J'%RtC#c+>8{iS,iS^r|R[ !zN%߄Mhk䍞f]d<*SX-4㽣s~KjTĻbF32lmYJ2p.tM6Y!0fH)ۧ(hP%{ˎ@ MV 5mRL3q䡍M]&}Q[[>$y+$28> *y#!\.˵P[kK/YC;+O}sdҥƧ>/<ՊSg&vĐPb֔]D)!O?I.^3{0y'8{-"êxi_-9tgtUq<[FyWz7IDHx՗U{eKL c {Bh =ٜmQ*sB]_scb2LGqս9I? z2]W4iRr*5HL=1gRT֢\e<8a/2 .Y ;ڞ~AGpQ~7G!_9gK%njCbS:f6IHC$_0V IDATM(ș`nlDH!$Z73W_zeWjz葛4d\gf? yJIG %,TN,(Qr@fO1*'qe/( %HNR@ȅFc4ŘsBgoŷ]=w%xHX-h%{5eG"=Դ+;gx{㓟|3Nݒ~_~ᙧu$}~.]Sg2e1[颧d2u]E F tS~``/]d;0v/Ԡs( =@ބ3%YMk?ߣB(A~OG;WX>H@I)A(#}DK3JKR( e *ţAxJ΀Di߾u":Q![B)A (#8)#PJ`<[s.PU!Je&b1Xt3DV` m{֒uغB!Ja!1!]i>@2c1cZlF8@iX097Rہ!.ܲ@n:s,"BfhE E;vvi%mbkŏ1dbrf,)+R$!&V  gBU R WA! tHu׏ӌj˖t]2Uy~hrh) H"4Df1uS{1BYF))yGHR5*fR+11Rln1/ؚLlQ#jgsB9\Zi !禲쌧%Y*sQdG0W>1{[[WQR24FR\+/2j3ؙNkryj =Cr JTH||1c9[ Bj2 hC /\9O`dkpB+؞LXS{{]|ӟo=NKՇ?}\hzi|IXV`?4\d2)RH]R,M,PJnuSo ӑCfԗM S+S1L_ z#pyW}ݻ$2&r&9@B+˖ȍxM$AiQߥ\~xa'?*dF E4Pd(4>EhE)tuDr Bsy|cʇ~g2nFSWe!QHU` *C]~mP D">Uʰ,-jo%AV"Oo )1WZo)_@A܊3R˂.Hyp.C2(c)$@.R5Umi1AUZH="!s6'n^'*Ē3꒑!U,%Ya*h_aݴh/3 Ci !jH]u}O.51E$޷HF DJc>r?żs|pTz9qIAG۵Luњh2b9tbowDt/905P8ϼ\s8;&r WOꤾ!턒'ェ{8hR Յ&jakkgXW$x穨 1`% 4D+T 5 sqc[& r%0ȸidIIL7ny0B#@D?d!g20"Ip#$Id I(ksٴʍ)dX% BN$,[e98q$(-hjמ;PNfb2'3,@L)/"Hv%݇V\Af.!Z]9gJ b0uyipc)VU+m Ɔ4"\~qB:~tS$Fb$з) *"Q53>TĻζ&NR͈U6z,"hI*aS X=#[hFֈ91Α бub{@"DEKΉzlޛ:A9,@Gv#B}! V%u2@$'5EVe2H *%1xb:ӯ)Tsveg[Ү(I:V89k-Hll5%QG QbdDWBVFƱcypm{#H 1$֔_S37"A'#%E$6Jz T$9w,s]|[>g>y>󙧹߂i1Rfk2W/tt2Aw.劐iEXe ){Y&spxH;#""k+Ll9ַlL9::$"Kf˞QSU,{rΪ+ tTs<+s'uRBp/wА"vp .x zÛ'7cM{As5߯Q1pwk&oI2IHy\}1Qe/嘇de $2j2gqCIeܜumɃ>{7Zng{g;^z  p9v&oPP"d -pFYvF#Fㆌ {g(e]RD*e& Z-|䷪~7 %SSJ׭O$@MqS`ǦT GFSM2l&J €ƅX-q!pc%dA ?PJP,jͶH$Rd97[D΃4uE׹۬sD*Avޑ>dmњ=@"%uU3-rL ؄(.6%ćH}Ok+r*%ʂ|֚~* d褕EsFks H޳X.Npރjh4ZrTUEʙdD;*J L˔m8ӷКHݔꆾ[UyƣV|?"NerJ:& T "DD) (&͔ղ#DhpmOǢ!:rFK[)x!Ed}*FbVH!&I:bx&.ј3Y4$6#b/mSm2@"*Qk3RG4eo@!{ ԣ9}9u4v $P&kmQN`:VK(R ^9F .JI| b,^ޡ&&bqD3=1峫jKdǴ2}PYD)9DҶd-2j%,i&R Bh+|P0JPkJm5QudVs.fDFbzh,ɒA$vSgUƑ?'&{meAa >`XM) ]^RHf%ΕDhjqp0c*2xS7 1 UؖfO QDھ#!]+%F5"H]쨍DxR?aJPhQ=,ϟ/Tۜ]{,!1|`h̦$bQ{{>Bah7iPsu-"%47M>})Ժ.Y7 o7:n*)ok4H[*(5dH= A!БԗWBbJaL0ږĘptX" SW<]Wlcȁu2 R(Bdr,6eZJcDkQF)lmWѨ1$!0@JbxcVt$QZM= A UZQ55Mck\pHi0FX.HcEoո$bY\bDYNƆse ,"6%1tk,[B$ÀHbPJbmb\ %ˌS[wL,sәyOXM#]uCHy.=EJ ׶('ٚք]h:EKM<:&xFt+SmMhՂ"樟*%@C><*m,cdwkrIc,gv4-QmۖuM鍌˶eXvj8uٌ]sYϕk9BINѨ!O{Ah|v$!HBLǤDE5. ƓIY}yV:/_yeSO޲Ɇvc,9m( !`dJL#RnR <ܸ0C+Y-4 FLJl%} H"UΨ,9F.lv֬#drCgR?"9!P9!*"d^ ȩDp SzBi^ ߋͼA&_$bM>䱢# 18\(" )ymM;HS?P~܌w;C@/r}GAIEJYڒ,3ks,kLc%Vb - FKb.~ "dAD$rdwJRI)ԬpȂxStʇoKrH\Қ3PƐ9%]",RC1p}PcjM4V];#(cDV{.^D䕧.}'~_TJZy!稸C 9z'T9p'zVX\jcڢKȒhH>u=1$%&]}dG(U(t$ lUbks=n;sٜŲ%VvCW> $a!3f[-r(c{RwYRMqUMU'5#_an$ \\*A/PF@KiU' vFn ށPT6o:BdRn1wh+(FѺJ 0R#e0߷JK5GVe<"@.I0ٮILW-&#jh,0Q `ь̖2TdY2Z5~W^ۧ%YYV2;*%VBO΢d:P6cMEm%nrCqdH2* Z4/<1L0;$>1e1 җ)6VrFg]eP.8$'/0Z<<0lU4 ֚uN{2B9toLSrpJ\!9g\ߣ$s ǀԪ|ӭ `/Yw)bL(n 9gZåBo`750, s5|##ˌůkM2C.26x?ǡX .~4-@Tvp Y2LoΥW9.^ȧ?8<(}I //|~ ? `{r/'" b. ])dV,\+%"I^]DjA$BeRޚDF QKɕQ^ׯڗҕu%j Bބ#r#Q\,CңMYq 4\)*7d^d cl!D, [t]GtŭKZʰy}~=tE5.%"5r ;#lI$t.:u.QRbe$@F7XPL֥ٔ;'5QV+d2d1")C%p#m*Sb%]*C$ұrPW!21εC% h"5.]NUd\M]WX>Rm[͈"2ͥAg$5FՅV7OCM|>kּ=63{ IfhZMb4LC2IEČD2j&10E/X3*kBIZ??88KKVjE1R&Ĉ %Pdycaa{#JUEO6hM2=݆A=zSZ#u1+@DpF"`_ژ (Lw3* A1@asF EL7L `!M,aȠ -zVIT6SAXOMX޺nx#z M.)*2ZWb7d{CKw͏h8c~!_3StICG惲)Z 瀕O< *4B*G _Njc}@z<%v*@R,xCJ#]kM:SS^ e.A%U<ѐmm^=X АO`brGѢJ$J?z?>wa'^m(#63%ލ# 7ݎK=U_w^[yOkݽme6/tDkZkY* ޹@!2u]ޛ[]5 wʬ'%ђ$+L`pxc0Z2~8l//<#x8 2HHBjun\Yw<{<|{ԍ ejEf7tgdeXS\Kb jC̎'qyyδ݈4\Bְ\1ưnY.[ڶdkkzBlҔhSF9=>eZ$[l )GAQeý'N):tIfHF+CL*-na |&(Q8f&|%b"uq-W.ghۆoJo_Hс8HW)hϸƊ05)(~! !Su!}rq}ALpߵ/ GRܝ7$ߓO9WkqU >ǏRrCw%4yKVL1C$D *mm:ɹellj$R*ՀB !W)2z[58Kka`$YhQ()%&/)Ĵu/I j1XWCUV ]Jg7_BVJ;U_hLgA~ ðlxŠeg{i .z`OWR;T>M$(+HTV2\Tژ >$xM&*dNru),Uc44JfO*W&ϗ~F"II Mt!iG{4qkߐ8l\^]q_gW*??7 y.7vF"Wγh](%oސ ٩d#Vk\%Zßvӈ8R;9Z1UdH.gY .Sĉ@gTxmJ*(-ФBxE oa3)2{5;O7Y۲"g\q%?5M]I4,gͫ:]: F!Fs"2ͼ )XX.笮׬6WQB+#]mFi6X2@܉J @I(9s8Z. 9NOq$@QR4מ?21|7~c)3l]7 񵉐ag} f׊)0,sCgjø0X ֿ: mZV-qbҋ ~j.⬂>g=yN(AO)#'l#>$rbXא1B GKJIWkq̖ A/(I2VRhCg7O)iK25lYqL)?cwW0nxbA1 Ged̀Q2! 9 5}$/e)%^y^}5rNa vžQV"4L!)daB8%IHLZ|>O+gZ'wl̾yYO}GB@e5XKsk,E]YGa I(UE;Bկ) -U ^T'o>4$ݵds(]PթHRMjVA9}]AiD*TI^EL ŠmE -t@`Q RQd!(QRBoP7&Tw3H?sz[.?g?OOX߃.H1]!D#"b t`L5,VUю>$i:uc4•~p r XƔ=TZ%j I,ȅaN[+Gr;b% SQ@9=0њ~3-2Eg#]׊(2$TҍVDJEr4XN35(ϯ KRv'Ã)G01E Ht)D4ߦ[ȧ|j̀^.pւJ㈳}w\P0124MT̊#Hk >yE2-)%Cx34~]Ǹ,gg(eqh.9<_#YʌD )E$-3 ۑ= k5J }t(vBj&^Ã%OM׾~j{EcBdqxjM'c:R*szJvNc hHi8>[뗾{k~W^yEsm8L zruB"i^.tPݞ9<<'Cm:PbmmҊs jK&kMNZr!Tx{+Ce^uJUHk.y~(ljT?'\EE}Qj H䪚f|"pWI㧊Qk5Dc[;=jRPjbgY\TMVA ]vFib:cƸҘQ6Ul4fo'򗹸8g_?S??:;n]mvY+#9GR-g7ik :)X-CSvSZ8h*j,潼1? .@>{,KWT#WPU^md3^ӍK5hGr؞ɛڤ*Օ$1H{w-LYc8"ar.[0rYEHbk6ļqlW51)˙%LJ)$0D U" a\~l__˼2lGZsO1n'=z6ɏt]W҅")ECqZqKfLZo#1&(SCSm4I)0u.xhJ==5cۂ9f=8y.nYHLBYS8?qqq2%m8>aa55Mkh;7tCZۑi)5u!|fi%sy0G5`eżC%ENxtlW;3f-m12)д-:p ĄRLaD %ٜ0c&t 4/ZBq=lZy)6-)\PZcC(Y)`o-G M +AKFjӜ"]ifLebnPZq|tѼg8f=4w=4qd9隖`| ~lƉ|2*,g$N7\\93f#' Vk m)h8qp<S@"NuEɋrV(I똊P02/Q#x7x7٦i I7ֺֈ8#Biig=1c;( }? FfG# MV2vֿJP9v.FrݔڣEqߴhe()`Q蚭s^휻q-~uMmdELTE-P%5DiI/Kn+A+4(!YTߙ"ʐO9$ҺRvmK/(UB`d,#U t5는Cե2b5jT.$ɠA\7Դ$g6{ο'.W| AP7 &p˪HgK1:RHwA0 GZQY 4EgLlɍԤKS"<xZU/%e Qҍ#,MDŽE R{*āYӦOq|wMۆ C"j4|pɱ`Cf\'ZU躆a98nQ=Mg|L)i4}O+lW$ʠYo41P"_D\o!SjJvYug^zo[AQ$Iߵ m5O>R$=91$ r ø5=qMM$C@GrAZ&DH0Z]heso9,K5X%M)p= [ѳ'RLѪU.8ZfJZ1)OOPV٬aMf_s@vB~CQj#>J ) !5(Tjתɤ9nyK/RVH*Ffsxℜ[?ϲbCA;bĐV()PڠۦvCv}fhKE\Ql]zK,YۃJy&ĸhpmلnNv/mZ^Puk<_Q\}:LQdrq~A%})ŝCfd> BϚ5Ri2pU" ){SokїlFu'HG<~|zSpαxL"w3q$@7خ!$7e66qiNa4-dr+ 9l X_Яb ֛Xky뭷*}$o(JU?WКR[R0ZK5VRgWRuZPKa+I-wڐf} )ZZ뜓n~ V| bQ$ZPmq5`)}B{``j2^Xis[uٕ*R Î9#KCх (Td@Kx?&Zl#UP*׻ף)&sHVvpUn53]? (V=Z,Ch9{I>wqh#TmhX_/k`D޿p[u9.t)Nl3aU"GQ  nUQv/eLQm$̆h?LIRˍBN6%Gfc"'ŏ̋}Kc棏4<¶pyeyE5YCc2JarɌn>c@IEؤ0)B 0ES] $ i0Aن w+VMGadJï2ztu "!_WEƋZ{hOW+OY2Sd^]1-DB1ޒCˍ1QR"Qh]G-i(cxkQB(K'%QTܘ qX.g3fdlG7A(MaGTFizKdB}ZWљ3M3'*k0k(%񜒊X|E e3jQ x?h53>wㅗ~7C.S*ߒMan{]rX븺^ta#%+<&x4]&kZvLCD)0xӖXc)bPIHRE)CMMk΁X3hsy!||F.\װGCA-BMS#yu2i8nDu8Jk%E\q}}u|FfMG6'bɏ4H\ ,g=։C"Dz-* )aiG'٠UsM&Kqֵ]^Ơq"DCşd淾+lt#l&{R$8F7#<>;ԼsqB0AiJB ,pu%Mb R(jyDRHiHF)6Var>F bZ8q r_i.(nU+v=KcI}[Y Ja |(*UwhK"VTGzR2{D+ H2K/ &}ۛHFcѵv+*IUFa&zv1M1䆬8kh犴 c5j y;57\*Z" %ACNnW4qwdC45wOO8<<;h4k eo G6qzzD4\]L\nN4QbmaX‰4()_qg+|Oy.w,)i6|ցTf+-'a`(_tVVRsSdP V5[̠u%s#lF?obzE9#H:l= kF>zХ[޻bYğg,7轷8>T>1*w"9ۑ%&ƀ#(正Kph5]q3x)idf92>&g~d>?9(@v2qޱ =V=/~4$VkFK N[ ML:`]O?[_k^}Ux @)&f:ؔx?jZW]ZF? žtyAYKJT5X#{eʉx?U !u uQ6x$o21 IDATFchנĒ˾Zrtmv{f4 V ]sRAFzg(Vp6 mF B zcֿX5k!Q&$SZݏnKeRе\d>1kS"V*r 9Jw]'kϓD6Ay 2OE 7$)}7V`[|bKFk˝rJ\(qrJ.-,6hsV4BY*2:Ns-ys,hls"vZZHc(-cl{kGǧ4| |t~ 6\]_61N i-)"JPi@+Ǹ3{g~Xwoʰ9 J딻Ũ3/pl,#C!l#%zj@%FG㜡ϗ,\_Dё){QP 4ٖ}F,%%dzaf]1-r֢P]8D&i\C0MqM7_0[!f3/<_ <6 bFtg?"-9>jP%[G<C1D0"o_Wjs&Ng٨fF3&grԫtQ>]}2%:(Eu MTe@4ZAu&M:VsL2w:) "TnŒTJG:T;aWTe.V h[oOl@8yPF"ƒ Ţv̫e–U(>sd>fz(ӥJ~fNs9;tJ#oFhKJiIOm,sfDί ./5fDwKy'Oa:C_◿w=F1kbXqqi%i{%|E =1pbo'0ư٬8'p|ip$C>hs}m ՖwXi[Lج5Vi.jYA4Cq xJXm1dL׿믿2})ЉR|3 N7{q9 !RuV]{k5UDi@)5,XW2I*>{K#gGպR߶L׸'(Y"BH%hwI PVQh U7 wN\+8Rc&6- eVcx>yV;xDU}Ugz7ڱaT׾F)K[zn>[AIpVـŤ3n"q ֊_7fX] 2n,1rݙv!3!e\\p,%ʯiXt]Sgw29(fEP tDMД*$HFmhB L_X,X|cr߾F"og?G)_ǔ(VnYjFOEw.-CҦ^8xEGz3=]|  r8dCNl *g-B9Ž;M.S( &QXed Xk!su&iB"UO,gDZ ʇNŢk1(*W\M{3?Ua*w?8B?)'m881 [`ͣL9 p$7dBjLΌ 85]sRHPj- نUΫT8 e떧|{o]aQud6S/<˝ji9sBcI)ѵ/Ef䭷^z'P(v l'QY>V;8S&ˮ|,A"(&0֢TLL3k8nOI)ݮ{|;C(=a6<PJ%kŔ ~GCJƠDot*V(%:V a?O4}M^߄24X pNZib}awtN')(.V9Mq.SqxzjSgWQ)}Vplǡ:Vf&qka\5B>6N=IʕiN^hsEg?" |M^}5-z)ƈ37\"! jWC s53pcxOΙq>p}qx.4ml>ǹf@hLjZ'INڠ4B 0SH``ad5RGdU)UMI ~ZYp}k6(ZA~kc^PjoI.ER 6btC^TzP{>"xާ2EQ!.@R `*->^D-|Ԏ2d=;m薨6!*VlQ2SjJ׭fnߐ(=r)֫o7[Z~k?"P9eH. i8gh1_ѕMMP*2 쨜L\=DxDn@nM6 Wv*j1hkqNY(5^6xPNj+eQh֡}oOg3D|{:-BJm:a5-{^Sh.YL]HTc cDU{If̼zP[hViheӚ1yUFg}#WL*0b^JQ ܡ(_T( qrmヘ=Ev;ھ'l7(hy 0M#]ļsH-h8ӑBDk3MXcO3e@+A͜ddSfk]uZIVU\K@ "ZMHAUwWݤ1|"O=w=E$>h:G PHYZ%J 5M4]#?WwW^W( A"\ðBdivRIU =XB 5"{R 8йonGggnn5@8/2M f}9×/kf}ئŹdiuK2i?O=ܳ89xɧwprI sx,lrx-p]' ٚ*|QwjN9 =q8yh\lWlt|x5,6ð8լ? ;h5yy8'+WEcM;u4 ֓ <Ӳz !<#sU"4-\M4L0m*B5)1Vxh/f6>~EчѴv ;|&YGlqb 5Svʆ"Sd_**+7+eudخvff ē`+뤒8M4޻/TIB?~s֛oXM1$O25hs3kD(l,EiL 7c)Y?vXI#o[zEa8M\7Ĕ΢T  %V碒284Q$;c0VӶžv~^Ho:_s~oE`.1JCL޳pR($i}ob&AiX]_NՊRK{ڦE7(p̤:ԋQ"HɎiM#F:s\I2T !N+ff7l%#ۏ%n^~qsZK? 5&$jekԫhK)C۴!+Նh,!z1HI[P"d\1f$Vԍ^EԘwz]0E!)H.Xѩ֚Ȉ*׾;{4MCUVT!jf;] +CYkܤt86UmOĕ&2 o)DWT{ձXE,vX6=*V' #6ei;OU8(9J>)$s(WY4%q7mQ( ijc8ygD DyQF6/Ee+k?98x/SgkIwb29_=`JMPn~hp$$ s A>O֑Z-.KuGsb1: #Zif)f)hNWT6Ȑ~Fk+ ^Ƚ,,x6c!Ov8^h=*ՆFAR|Fe')`+ڡGg͓K {\%l =u8 [qޖ5 91jx yJ1gRO2[D{ԗu]L e4O^JI7`f6[g<`t^$Aꬁ"tiR7k5fʃ IIN[Tq+[+Xqjc)d}H{e{*E\(a[x1d@khht _4ƦWۧɗ$5?P`̍hRt⚤b 7&1v5S SUA΍BEOP QLJl`C؏s+%}yʗx? Ƣjw?& puV9c8::GK  R0DXc/ eRH8eYs9iEeZCHN@JP5jVJa-j*S@{AB E?Rˋۊ{ԉ:Lg33L1QӺmwAbܐ;)9Ύ5ǯtNF~3qdhϩb6'5'=mҵ+_tC1b w%OpztY7^Ug|#N[Jdc _BD۔t3 r>0V,+#ԪFNNq&h:IلmDv-atJ (Ʉa"  q`dcȟ4?O;^*M5CJp1l9 |?n{uKPn+%yPiE4 Z_^6$))]q~X Jm-nZk()2T z $<2Zm !day3m4Ҭ{R Փʲ4ωUQeCJCb+F\zbTIInr 5FŒT66ٙp ek`"l+j E!JSgqVTYQFmQPbd6D&Bʆ7S?H{rg-y vj6'G8x9Jc> wq*{۟a$?A{ /Ѷ-7oNEl q(nfpɤv( pr uc٧j^s6al金uؙN'w=pu=Fi`4NM#İh󫚾;ͦא D-k!fQG)HGAF8fm"yzr|Xsդm|K%* cġkRc0QѵҤ4!(ʪfO/xt3 /8GA*iBH,k4+@3JO65X$ϡEl2a:bh@ir6)mܛXϦsI=!yMU.4J7Dl3)u'E(k5Eaj RTJVܽ} 麆hێ|,WvBFhW ]J'f Iю1:5UAD3T>ڞ3BT]1Q&{;51Ej[ʀGY@?}Hfd"xv/~,3S8{t gXnOwH d 5]ҵrƤ^pq'Ng#RRWK"'G 9>EV͚[FJʗNL0ơCpZ)fB* y28[c6ezJaYcƀ2Z3-MӣE!KZTc+QDFP`Du+pEmw_+ :)>wW/Zmڛ$3S6SP͚Non `IzffNb0bcۆħ@#u!9F\^77BxF ZR+@^6Z@n NҢDq>p@c"1)HX:O)PEIr<.jЯ>횒>W_'(fS줢ޙX72-gI9Jؒ{_[_*O~z4ŞnwvJykZO]2Un%-٢`yޱwv=:\h)Ӕα&8nY0 V5 \ydu2"YցX14qn]xta*R:B]8&Jk 0dfJ7FWm<җY.Jh Z+$6'LCIㆯiQAiTLf%c'q=cu.5}(MU"a+g9(!$tZRll`:h4@H9\,W/OMb>^- ۝cpra$a,fSfu%YIm-mGQs)ӎK^@M}5Qcl ?DK,|Wa2[P.Ozٲ<_d20'OI & :.ךD@LWFl-U!hf!`rfRTZ @J>\!(Ғg'fk ]S3֚kP X'sڮmf,J_)1mMA#I1hF@71ŊcULʊe;P%il A|MJ2u?t)E|y/1$ѐ :,֡"D޵_w_67^?O^9]eYuA$%$dxS&?_wMR< 8@9,ˊ^x0HNO=~K\{z̚8&svMaIH.wyp9fuɫwӬbUb 4x7VIsڜX|wx 6&749p!b'T$|F搔atQHYwt]DYIdv.FEi>I (4)M6AJHPB!*itvĩ7ywP֑\#˜r^V c (/*/FY)I8X~`qxNZ&&QLf#ݹ;TX]ı&Eɂ :]FSTV)c֫vMR/|SO=PU 3:*WR.9Fvv0zC$y3:̓݀dcLrpR DW8ӈ%!(b9?}l21TUIQ8\`An4mJ"1 uI/SUYp`5^{O%Vkfm1xFhI'2ۦMH$q?~w1FS?)Sܾ}!4#c R{Gx [>Va۔8N S%mbmIAJ< B[&= (Aƨ$T(kds u-l2AH 6L3$+m.VhmG(t1ʽYIeKr_AU8F34SHP`I۔t2[R(8K gy#1FΈ|؊SJ)0m( َ *7 .mǏPh&EZLnXsW-5VA;O\|hQplej HԹ>K:[$O2\SHIc!a~#QJe %C\GEPR҂(y}PW<%l /? Ə¿CVOܣy 5mHV:Byz.)oC7ܯ(7Ὠ]% ؜NJ[˝/?ki4(-b^I*K *BG-6*>f#9JЯ>BUII4IE-ãGkL9ʗQhSX#!:&fO 2) fP^8IMsZ&D,Ɩr uU8;Y\XMSɌ{;\ r&)ŧmP0;W^Mc/qDoGLmN'Ds|WF-РKت $ܻsm{{a^HzF?H(*,FX̹X9ػ!|766+b2kնq0FZXW4O\ӳcJhIQ 0b2ܽwjIz'ݿՁ"cQGP~`on,>$ Lv¶c–0dRKA#$Ϥ,1\4KN WyYzOU:ɖE<I){Cv)͉"R 31E1|k_#75/_ F;иuh@C`3a(m)7zqDE˽{kW~;aRpBB'Tu:JkU}À+ a kʊ%ĒKw ~1%'Ƹ: k2ѹ ӏ|E)h~]jb`XI)6~DBa@_F_R6vE!n B^)I=MV֛L"A%AqpzjuTp0c^PcIQQ(RuPMvhWYW(eTJVm@T~AGT)n#r>ʢȹYYJbE qyК\q%t/,+B bUTJvoI5MDU7^x!AzCJRD+8<4IO[ :2S`w#z Q[Ͼ}X eY .čx`2q* 1q5&dh#e(sKx4*kF sPZ&lX_˜4&O2LFG/e1%tPJf|b}ߤ.]lF;hςRU1zє)S0K{|xD"x#44 ;'[7x<{uAϋ%zʴ4.WZj[ӝr]pb;wR΋^!&0=chYwkk|Y6=uef5xe.7(^o>Qg.th\!Ş$a\؀($C;~~a5<{9xB)Uc¯V8=e;;8>IB>~M[4HJC@ՠ(ΔhP6rx:7o]/~rVU]Wyx.A [oܾ&q!Dk| hDVZQPIZ䞛dPRx$K4,QY]n<:=a1c>c/M0ƑeWK| 9sEF$c R:1)bɜ鄹 } M,&RDŽQҔ]֖b3+ %3h?}Cw @Iկ~/˗,ͧƿRůM\cGJ Dd0& 4Fp9 zXj-rRZ 4 xUQ!Rx;cR%Mס]iʍEaHqGB\bs~p־,ey%";v A  (atd8A1㛁G]OP9Er9Q^B6+]s`iqbq}cLQY;w4GcSyZv$Cױ RIŵ]ۆ&8IѶ+XԛB=]2} $-d*jL IJM#\eGT3]F\ =Iiʧ~W`, ^~breqm&SO c>1zm %m{AԤ Ϸ /}H (/IU.p&e`g!^L ~Gi4~/[T勿Y>w~X[}'PښjRrXeXKjnԪڢTiՋ+ 28;?xr5W4wP 9]kߦ^slUҭ=E%3xw޸½GQэwh֚6UaI4C/_M IDAT .B+ƣGc7;b6 L*r5\ :*H (HӚMFF$Z$pZф8Jc4 3E?DtaPX8JR^#q+eHyRnhMH!;zcI41X_=!z.-)CjХBwZ)= oܼM׬Z޲ޢ( ,nqzrFΗGE3 n2FLwC1Ȕh>✠Z*Zk!R=KrXGS|.xt>W>S1ݽͽGUͳCvuHhtF9=;+ LO!pqȺ[Q%XIÇopvt|>c\^t# |qgL K WhZQiхe[ ViN`RUܻ}K,EY$4fuNգ^F=#a^FԠ,קgGܾY)%CG7Oi!^)& }׳gJ4hiQɢMFfg&&ѻHAbAiHᬸq3[Nm.BCe{Ϸ-RR+"AE%уY@)OL]&3EUs&Nf[m͛ R8 č'BѬ-z0N3B(n1HQA1SDkneOY)MuAb괱wL!RmsrmG?D]VQD7UTEaTU8 [6Zڮ|-eʨl}m& (cjycʵ6aZ{M\ {{e71bբtdR}ɧbenX{3Q ;;9O_ [90QkA='p/E\E&fPkRa'Ap:kjmAƵT!)+?k2W_4jC"W$>bX;P'C44FԊBXe֠lp-zFЀ*)g4n]];BP9<ŀHh&$m=cx6|m)B&Gd4"FsFPyCE6<ެFwyQ9ch؝KW^A)sϾćϑgwwBn2čn裛^$5cW=ϨsgVZ "Vdj{|5˞ý}Àkvr10QEJ:OMy1n,vjg:-VXxݐй@{QIruTAQѠ]1%:yُKG M䷤D]AWZº'Ꜷ/BRF,7ksUJl4y'%HBAњ i*1dIcڢC n0d1J|=D΂zV {:򜜜3k]{GX/`: IE18K-UpV.RJ9#|4>!fMɄ.F&q*C#Q;Ogj=0{^ٻrqS5]5~x].CV}'{ (?`Rl&LzGA!Eơc6A%Lv$QLF,|L QZ@$ B4 EOG)71F{t~")7E~V%OOpAedPg'dw*qկ3?Yu|guGB E=VzbP(S0&(-圚Sf%|9ڈl`Ήs9ÇF$]0KwgJ=aP솑o}ӊEH jW܋K=W[*X'ԓRv;%Z<\vtڰ͒U$$/'QZAQ8LRNRS$ )>>a8}կn-M٫7Նҕ1 {PzJez'X&?ӷS`#rR|׮ububZqj(U@DJp$#븲GCOD D..Vz ,*/uF#))z$at6xI粬sSL6:)_.RfC*J)EQۼWXڶ%HY 7Τ}SUe)y bv-ڱJhʐ(7k}3!bm@qppR2+ p}mGɦ$ &i [Q;mkxǞc q'N1P^RL˚ SsM~7>Y!)&3#>aQ[z1a1 l]"W)%Z'U=aْg_泟G_E7_:'HXm)$ M|60:5G ~t&2ZV%H=1;!Hs2yB#>:Br85~hc6q4떮<H5R6)8яZ;+=z@4 cyzvϿ~Tu;'iJ`!C%c\pnZ wX'GK I/=ڜ(I!6m4F99ۧ֊iBpj(~)HGȴ.5ѽx (A)jtG:f9x✤jopE<pc{X+s}-hS[(E;M D#ïq??g?ų/^}?c?Ƨ?[oWU A>/|'@oo1 =l#Uc놭VjC}JD~6T֛ ;R }KRfkP4Kc"@E(*Ķ7EI.Io"JbmlKG#VԆ!7{Ql=c֒Ǐ4ccihMU]b>cR4p\#g4l;|Js$gpbŵ4}Ʊ֝{ԓ)أ.c "CЍM))uCXRm)D$Rv{lì@E1AdE7 s|R|Su\=@y)gh=c՛MI* |QY~ !_,RT>DʴeMbmjvwۼޫbXlE"EIBF8 = $$ A& $ YEREѢHdU^{۞v7[F jO{}^߿ʑla,!.( im#%Q:acNKT IYH6sh ӏg-ݬp%>?|?M"aLIHL>?)ˊĖ{pwq\i}L7Ns_1˶łtDPz.ОtL4@ ?;4>"dɣ!FAo1#d ELJPRՒJ§H$[j5a`˝\i|EZ[uQ Вml>x2k,>)T8T)V@QlpFIѓmIlq`F5*0'n:|w[JmЃǖT5G3_hS~]| Hڰnl,6 0 ݬUGmqIjL)6TUxTSYPZ v$礨4&FZaԂ?`q~vaQS<8_0vu-^!ˋ%gkZ>%d˘d2b^-1'EU08CpX@=R&!D|09KLu&}2/ c4Y޺u[>_24Bm){O/_q9W~frȯ_o//\lG6e+ C49J4Z(E2Ma'l e z_xuf# NXUJ)18<O#C ?Wϔ'h[kqc2<'BLgMq#̥N~߷oV󛐦1pq)GL >D^s(1'MIqq02JW~kGs.OsvIzŻ@3vwv3R)*;(JӃLɀT9JXwmD#H^0h1)o6=d:.h2_m;'[QOd:?zXսlυ6txݓ")sݕ'O&SRp I(kTFlKcU gsH|@Yk\Y{׎YjVEDM  %ċZ[3BrTI|s bm!)aJ.XE3)qi4cp?' Z(DA~P 1QljGJ'2ۨa\kw.cO) ;`ܬHO@GI;V*{`(BS(?DGT |6@HJ%f:x&3vs )0p5}`~oȆTXS9(FeX, k QU`1}ǃ n#VKit<뙌G͈ LAi tq1NrW$\ۣ]`m?(TeqcЩ;rFŐQac?}0xɌ0{J24e#|ĻẁFި!Ph*Bkbr0"F|M,@bX_Rĺ ,7'8@4V_?$E)"k (1}(j!QP!' W!%( "D]"yAB5< )}Gp1Fl(k gk" K$%/q6C7̧#R*@UNTE]O M"'ߕTkK*;0){K!8D뒲Q)> oi7-c~w>DRKe=`4U) j(y{o5$ςϊ݁z3fJ\uoi`{1|?ͯg_g7ܹ=#e'?&eeXk;{o00NƠ14peO?d<#FqڽHkƻRX{LRj46 b!Ev@@]DeT5IR ]=0 F# o{cyUoҘF30nu(|6=$Kw+hga3FvavA~a,KY|=_+WS%(pyTiyucs͟Ö|vŻo(')hKf ɵVA4K9Fj8ڳâ·2<`CU>eH#i \Ox(mh./-}~)u0g:Kn1qK^) &O-qCd"yijl!(gTJ1GQipY4GeBF]bMh$ %NZVP>2p5&7ްA)Ij4JTV\BVz)ЙHTVCAeM(k?dna:!jCԁMǴN49iQo{v 2Bi EvE>v6Fktwb2A 1R<b $t ^yD"Jg~py}j%'<&h 11EUc rrDQBJ2mrLÿ*ZK=OB: IDAT Ungjl\+!jʞ0( pчi’4on_kN?Zg#9q!S"* !b+Rj$6ŧ$Y?G#юD]BB ʲmPm1x?ޘi'>dj0 rD+ ɘ(DObH8KXkeS߼f!)ExO;6ڲi6gxDqjrp1Ntf 'FBzq-%'|?F -x`皥PzoУUf={:G݀ I^Z7!N`V);rH 0B@w*?c [(ePkC2U M ŠjƬgپ,1(Х- UsJ9%1I}ѳ r="v ʢƍ[(AFI(mQ(.&nW$ex9 w3g\*@Q.[qi]djJ[|~fC=)9#4Qs?3Aq4M*^xΠʂN o\ W*L\#? g/r~e~#?܍'hs)^{UHBw8DB<{ܗsZEJ-,QgRt[i.kPAflFZƊ]aTP"xh>]#FA];%uje$#N [1ѵ$`vuヒ5SGSASNI Ń! }/!P>Bo<|2DUM3qxm,ZOzWecLE%hFc cH.0BUW|jbO\wG\X`6T( VJ k )3T) F ?8 _?rv~ƭk)k_:ABy%EzZtqtvbRP mۢ*jmz xk@x]KZQ{3b iW:LYWm"UvCvaHC"YFk*X[qXآPz֫%nb2SaҶ)45eՠMEDInK ;a`YeKYD[> &a",e= ŻA5cF18A֠b4(PIB!Ĕ)-2;F$T&u7?=`~mo~]I+I\.ʖB+Ux?0xOꫯ]qud@Y/aJ 5D U1Kh15!9;D02MFSއɌ ZS'(+dZj.g2 {&ɾRrQLAL ·ܜ)r%H70+ >V11nFq٪:7/5M#!VxFo=(}% dZɔ10`eV v TOYc\IegS-:kc17% sI< cl K>18!Nr=2$ar\ ƐDmPåC_iHG+{~pX,=1qL|ǐi F*bk|Wee%>(ɓ b⑎Lx''Ep:|5qzm8 NO/lD!f[AbN?=a<]/QE~:3?IU[tiXtqD!lyƈ}QGÇl;f$5)'LF3b5%Ry0maݲ]o} ;MjI׵L2.W+Bd^ Cw4–{޳ .S@~`̓'yoRo୷*h-e]'%o:M5E~NdMVZlC:XT2'f̸V3l3.U:TeՖ+O ^(Ma]OUk kr6ALj6D 1ҷ89'BV4M̏J(m!umɴ`*@4E7'x8(f>RpX-|_?opoڣ$7P\\\Phz ~7GAbP&/ֲkrPPL ,'2S2ٍ*U&z4x,MTqOQF>TҲx]OFEr70W(m5u7L{F1]P%(S6Y m6D贵XA $vr807|d:..OY-/À *[Q-}2L+R̭`4cbrr2# ]Wf1{Y_.Y.CO]Dn`pHUk+RUI׵FQ7%,KIf.( ݺҚ* |2jܻ6x1HGCbHcBJE Mg,KJn TJ,O&ǍM͆R (lcR$$M~LBes^rc2@9;Ϧgy,Tʔ_,C` jJ=ڗ͚,cGG"!).-)Ea1nP "hD34m -y%͈f>rHw {je";7 ګTu-}?b۵Cըf m74)%&">NkR,]R{Jtvt4cЈMnY,VK~IZң&7]<)*##)$!He3p)e*0JܶЦ+9y[T{|wXaLO;X<:X,Ę$_ bY_j47)u]c<FB ){RK|%lIV+) G!ٮBtM12?sTiS1mh\yKD[UlkZ9Cd]j,`5 01b,rU%N܊dHL1k 2׻>zGOBe⼑%Q(!%ـ<#Fw:mīߍ_Ȃsd =KTESAGJ5E & 1)|EOLOD?(MyxF|!%ķǘox/nP$>O3>< 'd{6SM,>}X-o[cJh]rҞsO޻+KPz\0 5E]^{VCf!x2!Z+uS(H# Rb2hitZ"Ts o9?y6ĻGT/~8Gy}/bd~t) U)o4o~kv?N+*cX N-f K{7Dn¥ IT eL 4HR& 3 sSI 2 ǽ߯0GC(kg\GQӈ-xLG鉱N)q?BFe34x7v6^,1U>Ǩ{[V ʥ5)iLBj#B DvC[cgM9{.kupx6.pjav5 "ۺ%$ "lڮ{(!8m+$*2?sis@X,ml!;(N&B k H Kf|EyAwk )i.L+|T3vCHf2$Q7nbq˕"8/if*%0`<"%ږlV-T8yxJ"V+*]tŒ#Ck]cq~R#1| w(+EEQJq6t,4b,.WsJU! {l Yb[>; kVSؒ RZ'KUݚTTb2 x?R?8V[O+G?)eQPע}@ ֿQM((\Q%mGmq CX4eh4z pCY%>xJڮniCv#a8<<&q;6 42=$G+빞 zd2eQo. 9jR1dŽǔR_}`?I !02-M$HۛsRfkXo)˒7H)QjR2t gL'c/<95Ea9:cl'M+ 4Me92b-J lLRH l3qBdm+DPjPwW}b4h£F"&%MOH  ̕wtc)wFW^R)b~Մ%Q UPIaENnp1@9u^K`U]Rx6|=YӍ݅Èڿ1?sDa ?>+_]B?PVSDߋ+E뼠^dqrv%i%Tn!8Y Qj4߲Ѻrlڠ*G3%5o"GG&@$JE)* LT a@ X-X-/QۮN e]~(e5y?>)y$)8>ϐ_|B{vq>W:[s=ZPI<$so6S*%X:pa āl7c9OdAՊQSC X-6}K]>W9' [cޡo:E"zTgPx-e@yI(e988DMcjrZn9Ӕ% >[QL@J鳣s%M$hc6vE=Ql(8aޅ< )F%z) y!kw:k-}кƚ#[xqWG߸K/kX]Fkv#;jcl/}nJV}~0VӶQ6ۖ ń-+iB)}۶,F &FRlV+ m79O=^\Z]@̫9C2DЕeHT@UUbQhw^DEQXαޮRܹg(%u9BU#Na4P4N[7c֗|ObCSDCeQQW+cA$윤v/6C?@4llB1sT${S52"ZNevo{B{~QY^,/g̽7P{P3FO9fgzw<߳As85UxZ" =qmڧc~^2NQi| Γ) Eb?D1.Oct'L%->8bKրV1n{ZWQCm1ZDJ)a>~4Kɢ*r$X].n7rzCǏS7  m;ھ({2u-dߘj)V`lPRWc:ɺ@IZha ZM+ RiL1D"S)[ҞHv䠀!@:9&1* M >\{}gF.fQRT2[=S`?;%!w)r% 2;)lEa-$*#EC0(:BG\AqOtg'~&b70?@6*x/C^E++(eҌo}T/?l20Ea"ģ!VArنk^?)L4Gd3Tͺu2Z'[ NI8K?axӍs0 eԼGMK<|`8o[#KӞI3zеͨxOitjc`$FŃ7^JN}Ihpuyd:4"{ G%A_ >2*A$/_%$}#)R=~,y8T@$E1DbN|oDGqKeI\ $J᐀-V>FE# ޢQX[Pے+] 1R*uui){-#@睈>*geA٤a<QG!nMӊhFОd:fˊ4b3^^NE[&2i 3򂏶 IDATJQS#6nͫo>$ FRTB\ b]mG(/ʫJP#MS38fĒu,3|Y֜]\"ekSU}VSUdncwWu )_Jga$#~$6^Gy?N Пc6sp|x!*"Ŧ(:`0*f=ݿ!\:HkkxѨamc S qa2ZPG Q *gn!)?9훜>* RTa> $<.x]TƁuRm {( qO? ?;oE9` )*z7Kg4<]pQWlvK]UĴ +Tb;%i+ϔEa9%m[b:95I<Adzw|LM#԰ I銭ca^])I(j\,e1DbP@8:Z01$ 1-|h& Os]ͨ*(L9[\P4RQJgGӎLfghQAԄ%&E%-"iEJz$2Ye[%$|eFPD(YÊR]I7! Ϟ I˄'e*QU ^liGvyaOHOWEx2jQStq\L&F9y$娤2e,m\Qdy9(ryb@%M2BASt!1EjwSVԾ]7nyo~-DžG? GG7O o{cFX']([Myx )[) 1[~†9sz$l֊jpvwGl-kf>Qí]PrSلLJv z=sz_o~r1ݗ!KhmY.DPp@5Q۵X0 ]XIZ7d/}^\C}Ѓ4/VC:@%X[؟- | 7oP#8UJL2b,,Զdv9@{teVIqfh eݠmD> $#߹,Jq]Ǽ,*L Ay(Jwho>|MLRe{RTM) Dž^AB~WUS3u׵9@q;^RήTUE;eGՐ,}BHYR -Z n 0Ք_0 =|ěͷMdBRF9?0[MMPu+2<`:#+)-(׸~&/C|K_Bd:"=P JcnZ21Eyrzf(ʒY5bK;xMFcFSR<:lj91fӯǶaOg986iIT" b$13)@b6ezScgo|wbl%s@HdC5vYyWUFBTYן[10\S5aQ/=="O q>͗TeA 1zyƀodDIGzI+B̹㢳z@\?q!E=.DEQqo Dx!W_J$ƨ*8<ŢsFs6+p9oYhgg%JJq{ > Rp~6#Z hVG| r-x󤥘6WK2ym r؛qz3)蛏qSS$fE7٥3ӺDw3 \JtfZDf^{oC0#ްwtjT8?w9;;OxM uHi ?5G8kh7gcBɣ;otdP##"m@ h^D ?]zN*#wW3.s6톶ۣ q!n\좔rrE*ANE[>M#]EhA]S ĕ5&Z"$*&~Co;d2#945ZdףNc6΀QoY >1H㓭w!R>ck,Hń7޿{Lv戮bRy9y!t7-;BPG[XQDzx|FeV{Iv dÕ535֥Io7/OɵcG,g|_$wӣ4/=ƺHqW%gc2aӐr2f s&;O6U!AEGo1}O@ R@9bqAi V:*ژ 5ON@JMC%­p]q c*AfϿ ":G(@骪BI|>*Y-,lfûoF&eRMRW^歷)NDtA?*hxL*5#ml5-m\&ͯؐyu\vcL=s.Q{ڻ8=/]|h{H `gwNJzȦK@F'=僐1O_+|⓷ޔί`?/%YGc,:`LΖl֔)&;#F{\bR/.Ӝnp3CA"?"D~{`mOA+|xi(88*ֱy 6;"/i{Z 6D 5c#bSPD?3UEJMVeitøP>D3aN8{|eNҚΜrikzP Go}92P]а~7ђƲb?=EYpvvBk3i’kXK88匛5 AA۶9m58/PyFQ$]۲qboxs|@tO*pHt?}: ''_mtT(AZ}k"K7\3V)yǤcʒqS(.6H"e:R 2Ex:_e)3LK,}8UsR`łӝ1q.=;rU9N޽c ##TFo,IomӰ^-i{æXW9Z8l̬Y9m d^ e!E ,+j`d{O=hNVM4gtOb!@Ȁ1.5kb֓r3 o=h?->x: xp'U"3&ír3<~lQU0R6m@C@!eZ.2e8A%b2B h"ǢiV 5e^lUQu eY`ml1hY7v)˘UDUL!<2QZc1fۆoxC1Q:21Qb폓ScvI#P=}a\񾷞>|[)}g-y?Y}<z>g3M2oJppH*L+S%HKy!r[/ =GźQCt DPx$"!D]ۙM㲨yfRcJtcrnݽϋ_fx*޲ypBqٲ{fC:r"0ϋICq/2Z&RPQK[R!=yaO(dϤ`6-Hp(FcG?]'Y{W6낗xwcgH}/oMY%t'g>~r1B( ]<ǃ>f7E} ]L|@ɔ r\'pF;T~R]`ѧ=ԗK&Epѡ̆MDigMe9RLZ*O LQ`N/(T<63.nї vsdzD1{#?{0.0JĨh6+&);=>胘t0:k &Kb*YAYuNRw;a!' O?oSMwcǩDl8ua#;L֑J'%!&[KLo7 媮9]^љlr5maSS;J {OW՘yŞд=uvtrlX(wP9=a,ȎQ? z/i`2ј܆LԈ‱SW8SܽT{ < S={{V ˶O.y+pw|o~?}y>-&3ڮg\2qW "8os NтT8:'5BIνg vʊ;w(IAk𲧨 qԫJجΣ95]tLW şmAc<9xBF@@ES-B߇h*G*Yi E)2!XC2O֐ PAΝch5|E-]0X-]bmj&;zd(p.yYimڬCxzxq.z<\$G]%Yv0L7)&iq Xce}yAjCܾș^x%) eHצ )g{B1fqNY:w 1iXEx ܾ{<><>*Yd2z(SpcBxŝgcۆy%EYm\MfLg;uOߛT ܤ^1TiM6lъPYFgH@OY "{6rSӛɸd>S{|CW X 8afO53F)gX㽅NA蒈ZYCl׵:J M")yzT X_]"< HQRBr곶' vj8u^|u`5gg'ʜQuR|+%J2]2N8AJu L-\L?ڋxm"2cr^*P8Q>)Y >1v3:HNev`haZ1޳, $xXu&75;^/$FuJ*(N[:D Z4C, {͚ou]=*q:QLk̄㙣ES3Rxph>F IDATxk)) yXpvy EYe|Ro;>`z58D4A $ȈD1Oĺ;1PHxp"D(Ez"E28GP($Jg3לwtgӧע=% u7)DeuxtZU"B*Q}U ֹ.LJvfZ6Y@eggy(cw<Ϟ^n6$L;^QSp'g0,Y^ 蚖7~V%x/G?C*|ir!?.G@s8f>ArGC##`&4m.)9W̦͚jCo._Fm=>=xDg~ַx7_o;r-—.{X9ěGf,./iV+dy^w:\098M5Xp4O?y}%d TF9!C+ѯ7[=@Z(tKʬ$`{|G/|:CCgO;`]K\ɔ\43!A!uկdS7]r:T *dBo=< B!#4m\3tZH Xq0ѓS{scPA!z򬈉Tb2fnƶ-+9TrPUƇ6C.'OĢz3kM1eZKZbcitA]7'TSWWONc}2( eU"lߣ=՚>] u1?_GW8AYx|ޮhEguTDnBa㣏>Fi\tfCYTd*Cvf  K/ᄈ+! 2hT2 XLɳn1&۞uj5iqT\`1lLK ORIXִ͆ ΥɦWlՊM0u"/!(CzcbYzĻRm:BBژieܾ岦m=D#a7+t5|=!{טs v.!A|=8 zwdRAY\M*pާ黦(mGwGk?sL#,mq֐EgQ]*V.ryu9uW??ئ'1L Dt ElUJQ,MhQ{Ŷk*Qa)WWKnS P ʲJgyIHۭ87ھc<ge4 kLH2 2ZVcifDx;RqU1NQ\Mt?C }ƻ\^P)[&ʋ/%ư.h-^fˤZ=GtxRDׇ8D4!lO24]j$x/_k<[yH!,^EE)L{^w٨'/Kؿ[?dی=Nc8yכdzP3%i>}ͥw3|PX0)\*(BhYˋӥ2\'|}ON{6lbqh%1C&$V?oS8L$~Y>ߘ+_ukuyN?x۷!3`g3L:);/>WւxF~hQYEY#r:7H8|9;G" q#vɣY .c&u,) vD]tklg1AHAYM躖[w8?7d:|<_xxYVܹ9{-=,6DR\>gW|gqce dY0O(lOC@uREӢ$x=||7U#tGCLo1+YVRbvt,SkƢ"~yEӭxjGg-VZ5M޻}9;0A> T ";gH.%[LSRI}lZ&v-)WW= ˚<5}zA|cQBLj<ڧ(?DHNx t^F1ftYe|wzt }$B,cy~uq*)bY1OU9"v"}ʡh`'26Ql:FKk,4F"7!i: 6Zkjg6h.VW zs;{^h~9Z_N@BJBKX&:Hl ј$z.K2ig,GȌf&bww<̶uKN 'TxE[$Z'TAed2zMh2A:7",+\zIYdw7jNwg)6NIAi L"D AR] JdHZ#Fş",eu!yC &ZҠ$Lg)^ FA**cefliۦۢ(}';h+WI/xEaXB752իÐfH5Re(H qUQɃb>QXac0t|ٔKZ ]jq%!H1H%1sJ0-r4E2> G3e|#e'X8H@"iԈ{gkޏ!=(6PZ$2(ls0fz4/uj>O%]P۰hhBT"wBg/#*[dEjᡦYz:ho{>yQd /VTHgd؟}z<55Ϳmgg JbکTc~p !* QwvC^z+duQo NT&i%{&May%E|tG!3%Yc|+̦#&;#<:αm㫇MYY̽{x53/r|xʝB9o|Ãc&1ٛ4RH65ffy~o.r4vv;<ҴU,nB^^ЛX ɧQnSv 4Aݖl7%9;ڗx\d:Z!0UL12.=`sSH;dZ0M?1 R*o >i6_8˛i!q,MͯљeWJ 4 E, &}!R^\e';xXmp6\Kӓ+E֌"jcT^D3CziSZb:M̓g|՟9 =b YN(3C9OMOWHMt|os~)}>J)FSԪupi5JjzYȄ1%ü&8h-7gdY=AԎӬ#ЊV`F|RXe5il,eJsw7֥!=}hAQE c4\"kGhdXXfZ3QJoڄE Lreش.Kw\g%ܺfbuγG'%EF[ae2-q5痴uV57pSU+G59C*{Hz)1oWC~W bې8w(pzC0ޢ[IW>L,&O7q^p\]A7M8 Y)t&ljjD4"p 2)"F7_wACP"n$.*ߔyMpPyoA^8uMk%ϞN~|XrS5?yiyI;jOZ'deRmU (QBȬg M&X1Ȫr4f!8Ǩ*9y3VkfE26un[ Pl0F%rK&qEuL2.V .5_⃷⅗~g^|kɋx5 [@4fOYoTY0Heܗpxrtw'}D:YY%i#5($5rD, lB⺆eAJM,oi13 L#_[h67iƂQU>nG~U<](S{i9Iyc} /ŏw( OT,#W{_Xn& ˒Z;Ee֑nt>8I2CIo}?y#m&" Q@Z/$uPû!"Dlo5#Dnq ]n3>˲ "m͋%_NJلr\`Dcdcvv8rW֐%jq vvZ1l2 kZ+<,35ۂv1Y,]HIWV1 ϣqy~\HB4Lhϱn/XdH5^4Ǹg-eC4][#gٛ$8x_G P,/at{Ԍiak7]<~ځy aŀ`:-IH*,#ךW9FַLH꺞L"뮧uQjdPtShcz,!.R,6R EKu5K8qmMDz2n:h\zmg t(߮MJ*L*XRQ)j87ݺ\E мɒ86UUmdHv)"V)dP8D.]OBP!PJ'4ny\Lby4OgMCx}lXV% hUzK2Η+m+bxB%" taI#FE%'V[Ė B Oiq80a[h2Mwt9'A.9x(>/_'>;綢ad $n@!XXc3ͪi,3!RB{WTJ)ǦtF!36 =HiP(ے(J^{žʘe.2vJam2 hMTB~W +^ͿtW {@YEN2RPtH ˝CNb|*8S7:'Ro*/ȪZؘF4m .d]\/Y^Llkjvps?{[{uUtg'5C)0d ?z ?0dȀð^4Q& g8[饶-?{#gDhdvfTFč{swcPxr8bnEB7P o|6_s rlMHWQ\.?$+Krx(ƅ.PNwS$y//H4&%5rvS'?ejp! IP{_e:PlnAmUY.RkE0™v Vlkl 7 ''U%H7}J; z7z@b4y'Oy~qN31, ,cmQF1.DtvP@bQm{b2TGH:lb\tlv-HFpzup䃧HN)()*~OϛFrsxUj j !Ãz;Df7}  m">4ܺ{M,!nͦl VA '8WӸۡ IDAT¦L RB*$Q- tlFPѝ>%y3iNP|q /~}ձOiQ7-jYq޲nvM %9)GSNZ??+N퓵&g+:苿-b^ljbF_}Qyt^Wzz>-= e( 96A)B7 yt 3)2Ӏn7wXh$$tk`Ԃ:+ESWtv(Lbo2$M^Tg9.0O}#]oʋk;Y-z- 7HıJ-E@u3~ķС;O?\FuͲ$!*Z7n]hۖ{؅Ë꒸js8RtAYTb<`Zr\Rfͦʔ65ur"֎AYKwYGWџ.Q=jPAbF@ nbnBдzdE+yΞ07ŵ5 As!I^~gO)(L[}^\<uW $Q&ƣq \EJnEmteS5-Y)bVNNL#uhQ3ݡf 2u\FYbOR梿@_o_Օ?_0jï~xщ ;CUKJ])pmtF-GhMŚd:'|NS9hc`~"mT-l{o|k0',k|ٝ)xkxIR xD>Rmvb4(9#up-WHhMo^Qڲ:Gah6 ں}Z>P& >:!pb}yN֫% G'84[hCK$Fwm b#xJF?]b 1J_?6 ,ҵ_pt#R;H')5L{\-_/yrBe%b՜r8H&Ubs՚Ew>ѳ.nz hfi1FE[ =FLf[3M5E1X- f+Zc1Dg&(GNnQfmK]<>{.N]DwncnkX\Lu?(skIR1fLB[5x%BZKW:|j o,'M`s :pG[SL Ͷ'F6jpX_9FV&{^I:f5>|"% .Vȃc&C$UBT =,JҬMP#??bQt(MT7Lb8 Sl;kPݘԤݽ(m۹pp0fYkՏ TuUI%u pCE}B@>"1jTYQ(s"to;C&$5bӜ%)[6yȊ̚}TO)vwhȰҩGY[0ܾujEu/FUUM@=keYiR$벡 mݐ |+j bX-PZ+.fIJȰqDQ&D-=[ AP捯}"nX2x_B' G!{&o~D䓟WYBi>>Wm)Za O>s2Q "O>ٻƱ]!GXPcۚ6#;ݮ^^sz|v&-5G >|glyvv)ϸ{o~m]aM"Fyw^n J& Ӻw?{ ._^kSNFÂ4ߴ rҲ oCTjdcb8<`4Lۖ%X9Vym,RCl@"E9f~f3h68YWV dj+_cG^D鋧+7|cqs0 /WM\YH Td L\^-yfɢZ9O}t̨,Hm+<-W_=rB !64!g t4N1Z\ *+|Debke2Pb? jֆxR _l6TUWWl[Z)6-lFUXc9Q,K=~DUKVL A3AwskD<Ji1EV2,F+WqMjId/9>>a~9' #2:pMdvpO~DTC\<%:wmw *jKsхI1Kح:=ӷ$o4WWOXj|Ipp'gs5ZO>:j2}A`Tg/#Z,p{njv8yIYlnG\Fjڶ,kfɿ l{A>Ԕp6H1&,h:P{GYF 2i>]wG7|l), ʙ4]0B(T,HVu=X iq ki̔$*npn7B4ݡ2kk8ܓ45RvVɲGwGj\+*Tu@ǽhi-D#|@K^H}e}c")M4htdך)RlC@/.|䈣cN'$6A+)Z vYs'yՏ^/1ժ/6TՆZQU5v)0̊!Y2*,|7~k\un ?`ݬ8#Fl6fP$idT?A)eSo=d$5E9 diCٓOyјfM|MAe Y#tL}>``,CҼ/ [9~.GON8 lF99&$bL":xafو|yc&ФIa҄A^-II*:F./ |$):1yp@gEZp3P >wztQ &n(+Ğ j?#?|&vae`Xg<}~5u˥PtWZ.>a(lp.{#ϺiV1p8bZue]FD)udIbC= ٮ\_\)IVvdn;Oky-E15-ͦd:"slHHt`^Siv#cъ])r!ãٌUU`Ϟ>mM "ۤJ13BTܻ{;No].110<9np1)gTͶW+MX^_szEbSF'6͚%.dgQIdbSCN;(eF\__R$$CٮmW\s!ٔ[iCh4dnK!:,}!iq]W傫mmtS "(&Ce Q\崒MUiΨkʃLwGS$#̈mM^1 KldBJQ9p|g_c7cw  O&0R/ ݻg(ag+?=~׾N(BgEưH}4j'Yn]jw?q>`cr40 4i- 嚈7pFt^e8:ZP7T5y3,R./\_ԎJvIXp!!lm5USaS,KU2qquG6.%` KLg3OpG)'3nݾç~J=׾㷤p@r?Q~> ېƊc Vgs`POX&SRRׯ/縎OCS[ˆلhsS"j<  \,~ Fn9Bd5VN ?ݿ_=|OQF/ޤqt,s6nE9B;~sUYCڡ}tt[\ҟk#?}p4M@+CX|}?U!%@nIl֖ҴR04\.#]jབྷEf$!OAtf6qr|8wS]֜mSKVv\!X7UUvTi(r[th ZBA7 ;FEh\wt^|nz.#fTA^B|譸oT[R+2XFE1,6EkEVBoR]u5^iV5QER(iD-SE{dBE &Zz>" ~qE Jڒ>D?72@}P=n$jq IbQAuA# Gr}ctjC#FcFԩ(̴ uvאgz% x_mETu|[KtwZ((ݳ:DX#+ŝ[?8hQﺼmM 2FWU7P98|izy1<Wz|| O|_;of),Nn962لprrB^Y ^P-wC?~W%߾\?;c MYmM|~F(&hެw*FyGqk2f[%4-ru jf=NY\a_ZI5_Lk ͚m8apC$yATmQmE;Ƣ?i=}@ua! B6~u#X`/ni xWOrkZXEkQsԚDۄGpiT.a}F{  `b3Mj~!Ghg⊥0gpL[zAiY@(KIJn$`L&4~eY2K^<{\2m4uM*%y&4I!FA)2"0Fy\=#Ĉ]2Ӌ'4I.38@t 1 @cN/1li'}UmQQQ9QqF樎!se轵op>&:T.J& C2D曆M) CEcNSyMH}b~svh]37 (!ٔzs_ƣ/1TUE5k]7 I"8(E?u]Z:JQk"-ZA;Ikp!}wn]jԵuB0(K$ټˆpH& b696M0[+ByScu~l.[(jrú}p~-?R$_H:lފBUDq .A??{<#t:ESj3 C,JOoߤ[z$xlh:=ڶN'ܹuIJcxŐ"-E's~CFSG<^`MIф,CU͸d04"ω!j0P<}4;_z?!I K5166V1M28><" lc4!6IJSUخʣld0i]m6\<{B) ``:F4ayo]9шmtl7KB%qy}]N_Cgm Y^j'1eSMIQ #Yb\]Vi[vtq/Eا(* ?~z1!)x IDATo|o2&x^$43{tWKSlGGFĨHCp\H DAV2%L h"*9w&$Sf4ˊl;X7["kƇzlb`<`f^)WWW$z%KՒxzNR\EƐ8\kT}3(S14P" 41^M7'KSy?^=j^gOPR5n$I!ti˶m-[Om'EηNA⺏CDčjg[2DJN4bntZeV?狯U_۾0yw)DeUUhh! $-_c})K;kTjY{$]bov =-oRa+rp4 bHLRNӧÍXGViZhS9`0 se4IAǶCfQb$( mӰ6J+k.}U]S5o6͆HvvOT CD2CbV$}$QggHtGUd`k1k,FG5ԍwx|>g2% TNIXa^ː5?IKz C>8 h hdt],A#kJc9T>2ʷQey>iҢ5U $K>s6"g+>M3V@=0#k ZͶ>H13U.ҴjQD%'F4f 1.[?Ehu~"xֆAY0 9>>FiKQܽF$TĊ M2A{306۰ɣGI?nx9=y_"M բ۷1Y?xo03,Y Ȭ%)iR JNO_% fllN(&6M>aq~N:5'M|th#nU5C(E װiho|rrtz,76#r J|NqNe^$%S̎*bÒmMxO:ϯGl#JY Tpbˌ"YSa9b]mA͒7["4-v8q E6 Î9A|S9UUtUc^#?~'|{|99QZƁ] ޏֆ`>&8FnXkif<yZn(6&SA6FF*ؖ]W$YF[GDiEU`y7e V :GeZuUk6k`3lk8<: 5YoI (&sXF ε;A &BoPkIPoqj<חhTI5!*Bc2MJ28WneG~ xyww~U?~E\'5LE_wUϹ^F~^ޓzfpnPZ(?ftC} }Ͻ_KzAϑJDwM] QGŶjyzvIv'>߉\ PO(.m|aPf6i3F'%oZ"+if ci>L$Ci HUoll+n;Q֥7 $>$y+TE Q2T1 -"oA&0*FAkm%[$/:Nf(E3bTUGy\eYbV2LW':Կ31!;Ĉ*Zwή7Ĭ D \ nJ"A-ݟo2M!Ѻk`%`CEE%K^ݝqNΈF@q_aY5ճO5w vDmw% DVb݉K`x&c:>FWBt+Diњ~bi(2$r~.HB:%1,l6#K 2-i!22QCaM_T "/TMM4ʌw>e: 5_ΗW\nqkj0oWǷFZ жkb>6 kkb@ᜈy N9^t2~mԠ׵kz l?5]҇&I)l>@d/ GNgJ){TsVLdшy6(=[p&_JD־xN@ T?AuډhG}F_(Q:`Vxߙ^= uB8zT4Edp2$MdB~4`B({ IXkwss&ֶp ͈3,r+uGE'iDItXC4!5L+64n* ǗH I2B|}c/nL^X P䩈~9_꛼n?@O?zH|ɇkNo*"Et7wo~GOfj;M-y3!)Xst4Wn62l* > wDmP6瘎yοQGlVKkxQ OnLy)'%TsUM`8͉h*Kj=ÃCvTm56I|h$ c4$1IʳgOY- F9?K1V7 $_&ږ QLXnVh ˳''9GChd$YI (1`1P/$:D=Ue4LB&fwZ~/SK^7_4#Rз$awx=FiLZ : ^ӄfw#=LU~(E%#8jo֖i^@ʲd^TGC R[)?=}qI!&VB ]qm]<&<¿3T>8}ӹk\nSK,c,M"ʹ8Ʌ LG8r~u`4EiKٰb>0j*qOhZM>bm MIHqMCS74-1(2PW$?W5~[YHQYTeA:u*`o o_{$eۿ^٫W]~SI5MO@c$PrY3?PJ41JRiDo`ѷIQPv} zɭ &$iNeTd4&MQhν[,K1F26Bg"s” c=:Yg!ĩ󒦪1bBAb{4vp .zB+kgY* MX#-MA4~WFw„Nu;IM^n{iK椩>TX+Vy!b7RB;mjݡ@4 H.J;yYR=GMPZԯSz:Чd^k* _-qROG D ,Jo;hRDbElp`20 `ɒ]-90hj Ip#ݨ{a1=KV}CK(Wщ!ˤ y|MC >ZbP \ TX/'*hfTR$ $>TA/51g)|dBnF!ji=y^{^#ۏQɚ/Ʒ.xވG=Z6âzÌT'KΨۆjFقXt 7VQQg; wfj)ʑV-\t~!ѐeX͹};ali-XUE1SztTpܺk>C^{~(hV"4-ii)(E]mˤ !R"AAiGar%a<{%WXI)C9n4 +mKSn$g$ SLS ;} x4%Kb5 G@TՖn% |,qR?k]q~=JӔD J::*MĆWDs_k99r 5&V:kQ'C&JI÷r8 " #mMs">*l2fd0iۊ3PlX Ds ͮiDجmy9\f0IBl\t*F4(O3h沺 C){~5.as?Pl5^롔P)4bTCKjeOզMgr Z?{|p\h-|N*:T:Gy-7P计z}[MB7@F#aqju A4}vJL 'bж,67$)6 >[R-Ij_z9Yh%_ٰ%77s>_T."-Ե@Sg7c%n*MbA'&Im*N\(AE(q1flmnկ}c|;CL_ ̑gVOװ=3ׯc.C)b-!Ϲ5Bd{c ɈhɜٱZ@D\lMC*Il!6P MMj;8$9m lnlPk>><][̭K)$|CȆ9D m6[5|Hʵp._Ah< `32Ӑ"%Gh n]d4bg4 @ܼO3dWonûdu O<,XĖZTL%\^0;9`8fĠ@iMI "vɇk8W iF޳8|pJbIG6f'}qe2lu]R!il}VA4P}&O?o|2ךPdMMJ{0Gu`{kAT2 V1,X&`ãCbRq`3#EJ✕-D|h m©b)zl|#u`czŢ$9:iɆPrxg"u]2-1kyF"u*ԝ,SJyN]T-õ1*SH2 18fHCR1VsϡsQ{EbKBvC$_eل']C쮝UFJ9| B bBb;(q~Q4u#-FkT ci[Bs[viCt$LBtYX1wtNXP8Y즗Zksy靇7‘t(Å4FQ;5=? *Qt+>P2tA_犥T$-"(>AfQ+yQP1 x43zɆJ2Q8i&LJ 'G{4ߒ">!;9g6CIc37&<>jʫ/ Wr8>F&$R;(Nd 4,:q2dkѭb@9%'o0bAY5fA].oFm F9FG4ZTDepN-F G ٹt%׶LyMbe>w[׹}v3ܢ. 261?|;J1eyt2 x#\,pIF+ioݤmrP{̍TfZCđ r */_4O'8e^2S:O鏋 }q{^uڇ:~05Y=޹{6&=3η5y1<-/WIh[R U&2CnXw_o>Y;V gZ5T@'fr2. ģGy8o0 ${bQ (+C7MVUh99c ڄMo @c: $pC\GD(,1DZ4*mKt,4A0dz;[V5eSS|"\Т Ţ|Kj݆qB,jC$z)uj4ץi%%|HBVF(1n-9hTRh~ R7%c L]bjF7F+Z3bϮmѿ&mZ l@傊u4<$AVt8Lp>$yXO1(+s}Ε2ݿsԢ0LgAV|H\^&ĚÍ"NH^ɶ`$鄊 c.DdS$%1A ]|%]̫1>(RHk(r!{Ty2*{ݚw ݷQHש0\}hƕ)w6?뗩GesЅhX/&i&:ˬ6ZIT"(*h+yÇCY7m؈IEHǿicqobh@Uֈ]mY7G}^6 ?"o"[h(G,Phf',2of\LpB0o+.,)t`uy>D|+*I6 f$ﻋ!t%3*KpW4'Bu~QB ?y6$u>7l@Sy5[g3F5IDWN f4+c60= Lh|`qK(d[8 ۓ 5C\QPW#.!wC%l]&Ʉiq9T]|]#{(먘H 'B~JO/Σ"gh1JAOI25ݤxMzd|kF\s)pw[? I{|SQ E;b|/:[kcB20ZC"JFShS4o,99u:qjGXB%ÕWJĨmCjB 6[ 9":Db 8EbOCNOfPj m! gY 9xMwN5]?umKl#|VFc 2]z1mO2'uj%IIl@dk$?o~Kvz:㳮A*,S^":H3:ѺJnÞ4 bu :U^g|\2[kf6^w*&, Ç VLˆ*Kv+S֜tOa*Xxzۻ`# ԝEoܒky# /^*l2HC* smdJiƤPI!(y oY;v $ƣw\9])O&q1J6NmpKUv3hXn5u ><"!}˃}bNj^6(e:C :Qa '4GGE=ԡt|>椬LpH_t bhTrZO4)Re#+^}GQi(Cfq3ľ|3m { "4 )6Zf'c5Z[j煒նLh6{}ɕ,KbjI>v6( U~Bݟff}9>jƲ9V ^3.S+ CHG> GT݀"&ZY+>HѕgwVRBKT"f }zdu g\ڶJTWȖmoZ3)ys>=)@J^ƃu5uŭ$B+_˔t[)Esnˊ"ˉ> bt c2K ʩv%,őfZ G,iJBی- !%꺑|1Mk$PII Xc1JqxtD;Hݾ@;Z)wAmt.&1Cb^e1 b /~K|wQ* )iBpKa j>?-s״?i:2M},,n&$40ojwl-R2LJK'АՋNZ]thKS=12͙Է-fh.|h7e2nLW7(_%E7[|p#y)6q&Gtl] }$iKIM35>&lB1L seh͗-\Lq0/)rfβ>ba{Kh\&{ٸ*/^D8 [ФGY۱G%MxoqXGPO1}kC*F,5XNTuF=&D@ &Cyxp_&1o`0@+ןh(Y!sC޻ˍK*EU2LCzl4qJɤ9u6?%QVcl].*%ɤ kS6[_d-1-tJ'/]3NثJX}F\Ahf{Dc]~pGL6`qԊ(\rt'X-d"3. ,dYL&/  OU#!k3bX+C>VJ"YCPŸh-ӿG?Q][^,u:sҟ: ~jp j1lR":v(ISZ+ FᵘDEII Pt :d}?-v kr7ƔA4ܹ~ov8͹{|O]V6W&hLxr@Um q%aߘ_+2M6u3t ME98 :dusf75*x78||HyݷK z*e._Fc(~ FŘwx[|}O|9BLUHFᣆb^{!W4~NK{P+->w)2vYtI1Q3Hh6CLY 1&x!4Wsc2*/WD6Oqα)-suHu\s;4ٺѽnjc%үٹvyy xRH [?=0DkgR\٧^^g6)ɬ%u/m17m5rM2g)ޓ(( #g0bo-,ыhcsS05uwfhx1(%FXmIM`0r? dk*TCcQKoL2Y3O |kqqY5~:0 :h bcmcI"'CR 9AHk mZɪPJaN !E Llx KH^noIG p?O[r'c*T缥p2Q̅BJIKePlίՂ~JMYvf])Ҥxפz3%(茶;tٯ ״j zY}}=eՐzԅxLSlxrd&h?鄱 1TI4 a̡4{zOXs}cg#$wEd>'(4Ӡz֜N8K#U#!-IR&NbNusc %V&U>j(qxS/|E2f[{.UY3Y](1zib̏d) ai.]~d~7PjJ+k*x%?, ޓ[GgKVvժEq ^>BHu)ddA},ZF]nTCԠ) Y`gs7+`ٸ {_1X-ΡРNъiC _oGqGtTn1$:IF1xRb$%K mٍU7>v,0a뿏 'B'o)m]Bup^V2 SiؽqKx|YxZ)'U&?&x|/$wyjqs<'FOԆuLvxncK- 1)1yNf'R̸w!W\~Kb$R5gQ.}ˬ\4oHJ{Id,M qsKrz))+v)bT5˨oB'F>F 6><]m9N˝Up#("q)ܓ*+B 5-yQP֒ 4li{D8]YثGA|fy RbPdDZ.mo} w9ɈׯQvy qiI_.il֧S?6L4%G" GO}~2NQMd:@dž7z#_bfc,޽-~Z.2ޣ,Km"7>iܼ7ָi&p8ҵYb`<`kclp(2aɒbm)qf8BxcdK;W0d5Ge `P8+ MAH>NjMGԨ&X00ڑ|hmvxh@(F,'sBLif`Q%l\⢯_t\Td>j ~, fi8_o6 |8?! gLK4k|_~pqr=яBn57 YQ-ӵ5杽gŒ6pNlP> IΉ+(TJs_{-796 ٦RFc LY.01*f4vԍDD&E e u2wO,Mf͹^;͒ |M^UDbTK*Y{{H`DKVUd*:Ɋp}9AJxϕ<%4VِiF,zZ[w[w^/8 F\~n,Ǚ&I-UXNEwkEd /\t$/p`5'MYF5?_|>'5$'jf5M?ṏk|Ga QNd}ʵOSQ#tOy\e0)t_wI)qwY݇?A'0w<}܍oci"Ŝ/r˸͹u7??q2q Ҙ< OL#B%B<'޻k/>/ Iiˢid"FGGc}rw bm_30馢fb @U.ȋ喲s,YqCmrb%8g?kl=&#BeŃ}Nʆ_ynߺ/"sĀojb ڈi]Ҵ wd4dV>j,:娼~*T#!Nõ4O걊FF`XݐAIU@|PzA9)/Ki8ESS au5/>>vCBgtZ${ 7Xp7} IR[{+:X+Fb&*H%-v̥DRZޫžqFeL5UGA8W)$TՉ I^W>#z0N(͚j9zK 791fY\:٨M&WG>Q"g>ͷ_kc1FkTSJ6&tl9oō|g99{4>AHVh)q_mV)gUZb>s}Os1V9kVҽ!n@ LCDHFi7\҄/ Pi vO#ƒ9'6Zj2(kKiM<}UKX{ 9'G_{S\`mBh$Y)2N4yz(}ナӆl /؜LY썧<A4ݯh+eN%^9eh渧Ed2IBoF -tUZܠ:@w>s͜_/1ZB43) BZw"\oNK}3K7IN?J KCS$#_-$:-pH69ˈm{/+JzC^C"F;#\}I$m`(_ڒϻYVeC"`-ܷ;g猵+ قCŰliL`sFe⥻?e6oI䗾o󓊔JCGn KS" YM|Z^Okg^8?I:_\E[=4?'9.ٽwP|_W^qZ!K|F:r1QZcz! %!o;9h޿߰isǰ(lHel_$N:MR=1Jk圄 &luf1 |ynW~ ~r@ c!3?ۗ(/>$oV D4x,/MQp-& '_}EDdJ oI'X-.B8rճiU "߄|xzT$-[S0j~_۟~hp8fm$XV½4F#+;#&rSa~r̢jx{!1R,ٌ"M <ۗBMRgV.̱juJn`Zan"G8*MASmYВt$ !p:w讐f˩g5vG7%nbDg9"mtYi*ϳV x7͊)eT&TJ:ri-w-t|A,T ,F8~EOɏ*{GRb޽"R[Zi/lWҹ@yy,א!Tu, EUR#!@J-˵1sNM),FSV%ᘤMrX*R]z ArBQN baPbdԱe~t̵gъ5!! (e Cڶe>?e]xф.]e8C̒ s|Pb{LLOQMWtyzIO!RЙ9wf)(b^繬nؤ s]!-o\FϚ.{)t(uvb E9!D$R$"Z/%[כnN;; "Ԧ>Žr\Y*b&βށ!v.SŴ_=\'U?ʠTJ{4@yᙌ:$.Q;|igrmasb{8cڧYYg1&uqJڶ;7v_|J EElj?R|o~K33Oa^[9e9W\&s_f4}yᲜhQrrq6e8LjQZp XT nQ'[3*e~2O eePU_)"):O/#OeRJܜ3&k71&w\liCF1tk ܸ*UW_igL6/3 c8c0%\\Mdv)l8dcl/3^rsln_bv|mi~}'#^{-w>`| <褸>%n]SP{a̝+}XWn1HԉLJGX3d׉[(([dū.:ꜺzLXY[ARE|_tx5#^EB.zngH]).-- xᩧƳϱ11sgmGePhmPS tՒ7>yhcNC謐$^m%|cJH#)ѽ [QS mQZav Z&:>G:z(miO 4kLn"ZHUE@W<|.#}*6>rcvO׫ :Į{ѭN=/BNR,9(4k)1- 1rrrLp"as$76y\1 M>Wwֹq穧lNcW`,%@hcOOsŪm'Śm:,Ыbs XXUiۖsIΐی%=2e J2!I"b$V4gNt.*\jۖȗEmiMqC| ^yuz ?z{43$NwuFСOtTds7osYr0C_~d : S&JjI,ru:|Pʜѽ %ru?+ZB BQBK1`uhM )j3V,+h| 1$`uɸ0DNv_)k;a JD!92[29Z/נ"(GҲ~҉Ey }#e"(M;Ա{7d 'ST34=C muwY6$y *ݹXҹ ZiztTLRIzٿe n_my㯸!Fܢf}c ^̎[R(ټqtPq3ٰ!'BH۔匶hc|]}hbCP/@}nLQ㋢0$A)( ~ӆ^Vnu#[|;Rxb-;t;Uݪ"YU)E(YrKpq܈ H#yC @^Ct$4NJn$Y)Rj` ;qkso-\Y{}^{og7=ky3/^d81*K04Da*f課D$MI'ԦM5f&!=lmţ8Jֈj<~rg6ؽG!6uJ޿n5u i-MUp'xG9=d<+ؿsoX̏8ܻO߹:|" ^yːO Arnk$3|pv~)*4wvY[$Oz}kFkI5Z_ p,"CIEmFbE6n^uo:Wm%,{9~k_aӄ"\i^"CgiN yI88R n(s\bx \]{oÍ;UTiQ{RTʇ̧ܵ`z/~NDoXu%%K%1*z;i,XPdRJ;mG/vIb?[ˊPDc_KE&QxT'i dkCtݐbש:v|$њ$M9E*&J~J&y`'3gymzzź~o?%L B!B`>f) c'HΧ+߽'&I4YC(>q.ȵPi`8 ׯ3W 60“c‚[[aVBIqßO)V$%` Ghq|LrR OI3޹N@J@9t'Wy CC[x(B,;]*|x%p; 浜*:b`-h ï~xbs~?CI VMDhJQ%?hmf:8PW%ymݸqD- WLMpУGRWTMMe,*IJ2 DwjM"`XDNSKuAJ&)UUSUZH,xGbiX'F]PxYKlh#Q Zt)(&k(1֣>6 NAby";ƨϥ[uedu*0=*Xe_x9zJ1d9;9HSTt? |@@]Ι&NsmzιA* _y?'?:"H3Ĭ& rK4ĩitpc【oE1+DC UDۡK["D4a1_'*vK8cRFUq5~ܛN$DbJ(뼲y.?vg|w _>IWŅ!jG!NXdzZ&g{<=KRKа;3+D!ztKVQ0 E?'$Vk1FIVLq֣4M[Dr)|\e՜B\ЮIP7M MqbCSjyIգ Ss.nn9tD6D":dsXӆ.|JAKxj[>a*&`@]M,NkM$[f8D[{ޱ0K~LJ!N&'"eB$): UpQ/E힪HT[9ڍ[ww /(EXϝ~qkRw柿"I >J RזݺJi{ٔɂF6e955l~ĵyHU;s6+׮`ebꚺ1ŵ1XSckq&Vӭǚw]-Xfx6\D4Hi{Ţ)<[c>]\rz_z%xIdp4VHn5aqϼ*Vd`?!CYD&qǻ?~~q%4i ?;,˜p}>c.@,~8uh*V5鵧O] º[|tﻊ] OY< źWmSD[>dC"[CQ]GiLLSrk6scwջXb)@Yc%4'P/UN &CLDPS%h YoH\Q58TT iPj!,5agZ$He%lhk.]A$hI^ݫ;|p>D®RUttE^{ ʫ0۽ϥ3kobb>L|]zdE jOg=Q;?/믢!b!u־%$?|]޻ziUb[[cyr.Cv$43ԉ{ՑT-$h6h |_()N({|WsPLyΤb8Eͳ/~9ijWp2_V Z䬈BIҨXWW;W0< !1Xqړ ï~/mei  Ba RX[x1uEٔ\~?yG$bL D fy7F5L ڣrLʶGʆ5aI4 kCJI(]}iTMY6 4)8IǞ*Kn_ ,`@Fbk4S;Vdi <9w.Fh" $.dXTV ۿ{7ﳖmK;s`L X|Y2=7P H35lҗFĉJ!BJ ^yl{'G~΃=CJ4/,G%Ś#dt֧etyc~5#QYKŎ x  1ϗHP/Z\pВk1s("I[;b>()RvpZt Y%$6U,V#$*ޫ-@8V*u4Mt_70P%h=u:ue'^J5GXU麩ljE7L"%9]țz$. D5u4;pʠ" -H!J8?b@ H &AIҲ~iO)9%EINܻ+ I6_$96:s#"fW?UInuἤq7tX3VKm;L]MNP {i<9};}^:v?T۪JR SOIlUz?:Iݓ+ّmG LUmSJ޶)·Qˍ-ѨmA-C!HŦatΡs+] v4~ [",xېJM6!M5Ɍgw7} qxyABStAo$5>.qЁF ^ԑ (BH (ᱬ ZPc,Ju$.G#i0xJ5!7z"iyϝapbGG+H}m0REE%jZr80ݣ11?w $*Z+XX[Ř-6!r,K%k*AjMGy Z I҄i0Mp81d^.X4g>GD"EI3]̰,1"Д5A%lm" A R'Ӷ2hCI@(< (L5ۛ7[6੅J,hRB\ޓhRlcy9 BX]`0$vVZ8"IuT-jOVF4I ֌υNɓh!$䩀XIGuftfD=;`EUUXۜ ;JV.ZKB"ͨP 7Hp"v98<;yZorܑޓ*:K.<'Q c'$8HE^1$Љ^gYny^Ή1 dtII<0]!YQKy#r@tлΟoU2k[MvcL-$˰XfJ,?N?а5u6-<߮:&B$\/\!R6d ,%:VAbK}5 ~܋ pҕ/ς֚fΐ wn/14"˥T[^)dhZV ,(LpAٵtAGbe3Im&!&9>b$ 7ZK' 'yN9|AUՈ>?N&Np$,d:H$ꬤwVRձ='"O06`XKe,^JUc*:Ž(rg.![]+V#4!erQ2#(aXa.} 9|="dAto2x68<< Q AI|޴Z!v$G|^23n  I"hkֆCBKtFn QQ[ɩ0,[q6v$TTJ%B^#BZ$inO' aR'N&.ݫnYU :~ÄǷZZMlVkH9oY~~T!e{t|nѣ@h8bMMY7Nf}[Ǐ?yHz@EXٻuK"oe`  T8U=D1]LJE%Dk9:/> nֽ'LeմX !,=a;8 x|>!5iݚ DvuLQ*-;{sEfZ%m>Q`t-H$umG!J,Ei$!蔲,JڵZj; t? .|+qBxOZ,KC,KʪZ&Y ܽK]Ͽ~|B\DtGs"B9G?KIyZoe6q9ll2?䰜s{bChʲuK]J jC4-J!%tj \xO*ՉBT]'1+xl]"` !=FK3ZM8FDU8\O x2vOUjt3:8al7"IqƍǞexvk\XUNG?ǏH >kG#o]3<65p^hU\JWt=BJQ,Ιep65 ]e_Po&4O {А摔Eq$ gR<$."T-<:0Mh2gk{BIyl):TjED5P0~[G %%ˠyƹs`)kiwH9MF!A(ވ(E;-L+ҼA?YgjjA@՞3ih7?շyBVlD-:B&%ܠz(QY $ Dl{wPB&9Bj+IRsyyN0V7.I*\]$K.VVq9c# !W.=?sa{D -*& QW)ooMr{rv=  {,LIPY BZ걅vFTUc;غ/؆~o*,!!D`d6Y=!MZ [/"YHjծҁRI!k{ io {lSbUPn:E$]hyITe8psoPRY[_! bT |Od㏟!>hF5[ yA Q4\v7i 6Ucڗ_3O?I"5)db(@5*D Ҷɧ2HsΌzEv'ܾ{h2j<Ǣ1 \J_J#Dž($N4b`p'P):xsY5ZJ*!ω2]'B]D4$m`&zpMBt(g^ycHr&ԵkJR!`lCTdI;wP>4C^AY."RtkmjRUuk[}2N Vл*"&wITxDߎ+-KH)ZBAGYw.K]ŀV!MpRh!PI XЍ(noiLC/!|h~XB[I@ˎJ7uO:TsebtuƊ{`1eel" ڤMLbqrDbsxd\NĤZ_VJ/2s.5 /|G&%wcjB01Zk!)Zys )<=lO"(/B q4:^,xTHBDxWF R)5AGQhR8~lt%RRyTHҌ,-HSM4#IҴRQT %#,=NH҄VV䩢5wv&ػ97Pd`Lq~rfpx<#KmNQH%YV&U.] {a?rGS&P^RM'%R 4嗿uNa8Z祗^dsk)n≧5zI)E M2Th-"vp^{ȖAhd(v= D_ZǼݟg{o(MT=ˠԢ%[#X*>ϞX g?h=e9ca.leu,Zݡ15/+TP/T6SU65U<—Sf<.Nn^bĿWV'Zt(b1>E[@W"so2\ڢȓ@#c4~5`T<ؽ?pbTH%3Ԣm^"D{fQ~帗b:Fui*T4Ŏ 0e,K8Z[#IZ^Q^ 4.0L / GilJ#G!Q& %-$ݢxE`2;b}k:X*RṚGȸIxyrls >Xpf$H4"`b$| Lm 676(t7gEZ`rOhR3 vw~+0:Y>< M2E(k ,ȑҠ5hѧ(yȝܼ(5 yΎN/O[RDCxxE,!$J+T#G)[myln$hךU#[3S!2a}׋FeYR8R5u4~6o_g1H-[YwY0~Ģ/nj_.uv,gu-e:s@5rX^8. C!&<{ . #lYF)2XWA' (%6Dx3~| 3B}aքtjD+1Y D tD.gY4bYI?N&']:1va,Ƭv>3~XDt -G6'` acMhdI[gվUqiTot ^?.xO};j"X&$k8 JNB]TV97ؿ5 z%Ș끌س$j)a m q($ꚔK FĖ Gp(Z!CZ|h~Q4D(%=-,͕$s׿??vwwIXUZ6X_w߻Mq7+w~`xo2NvMzMܾOSVip3I8w)~7/O^&4Ղd<˹ʫ_~C@ ԫپp5gΐ{DG|KӺxpɑ6Xgm0Θ-"v1/M_n eo`pc01# f3fg8rw=o}Hx3L,)yL!fY3e ܺA*ToBkuQjR(It;ձ)uqsK /;c}%(-5QW~}QA6aNA"I46yԍ'ؒ?zq:!M%1ޑrI9# к@Ȉ{<_K{"7Z۠ y5_HTBc><:T"cA9*E֖TChQO2÷pإu+i.TwQY|si -K򼇮꨷^Z@f}M0kM3gc}h8Z4|ܾvݻ7I$^c}ݛkȬ@Lc@$,jw=|F{Iw|+X;NUyr~NB`*d$sȄW` *g?w V):@?ͨ1 iF#C:롔a߸O0pc^̳l=q)Dt6"Y􏐙b\4,.^̳EbrHmbFUU hLp1 .b2뿎_o&;HT`F+{ᅪ5=zaMk%y0ަl* G}TZ)bm@. 2qӚZcszbUEzgS x[(EI`+ccE:!$ˇq:w q.UQ8:\´ҫݚ,ywhz,"ڗV6r /"b{bI֒hl69|dYh4b>/b$ U]15i!I 0n 76"DlcViY}L ъ7ݯs18؎]B<ϴv8Nq1 ^B;DDi!CHb0w6QG'!W8q:v ;A*2;C,2Ia&%k#hJmJY%9S/??"k˓,*r} DL&Pƣ@ ZDc(yF(*Jh [|RpI{?x}s] 4gsꦌF:x l21 ih[Tu{Gܷ{\rý)?4bUѷp06xCl}JSCLrB3^[ӲbL!!z tEkLdT702> d*Z 8*fK RYR%1pZ MrGS0HÞsBE5F0LR A)8 S=D0:f~i:/6ӆҴ(chtEz훸wSorz:?nnR]ֺH/7t9ysp)ߤf>&wzzʰưX.$ck{i:9]6șeR(*[bsT\c 4( ˥Y؁fjy'C\Ux~oju-syL9iBoRRA3Ri|}Q лBrJ])^sPu \*g|eJ"$uVu3FAj &7ZލmwݐD킘5fg Ȭ)3Lkb% `TjGg<0™)\vUD61źiulĤ`&%71 U%׾Aϣa2F ʹqzבG5ZZ@Bg^.:jrg)gZ;3bw,Mspt ڰwqk-jX3p j)q9ʉ邓c~ƻ\{Tjo4ِ8ۢs鐳"錳Z0\>iZQ e(Iѐr@Pơa41|aFhZRDKe,^B wۧ\8B)C +eL^u+L1bL2L +G`: *z%61x12 uUE1y2zbmWhBQRğҒ98>b21ٚ1m$X]V:B[I3F j%ޘ:AS$Hp2(;K/R;/b*k|Im*0n2}\D@^Xk.G!rE;e\`vzz{5^|7mLC.d">+Wxыa iDjع]?KJy΍V\ַ҆ܜg Ir ǀGhMP~,m$;2 ͇R^Fn+v*VB_CXuCT-UDP٠T&* "霛/`\Ё731Kbx6b[EGtƿ.+AJtes<;|{>\U#)жu=@) F[89; &[41U]cuF{W- C#ń V,NI[",[X:]lIuUktgJZ6[6S9 9q2qx.Z$!ӸewJ6bxMb0`V5)͠:SyG&?g~6Gvyd4270ܽdzygq/zUrTAFO/T%j-޼EVl?!ŶsgNۖo0;UCJbME_'%ԋk8ń@kNh *BQQY66xBWCzP! Jf]ĉqI{Put]K{LUPHR&w,/Z  T!uw{J z Tt\mٽ{/?l(^/[fep8dv^03kڴFi9~w~?NpmBS2-t+HԺ&D4IkRbִ۬QLilJJ»R,8H7z}A<챾+ͪ&p}F );s񑕰w=ؿuLv2hEm) gʢ(nRg7F[1҅;w0[ԑ`EADTFsfᗴ휛1+"hʨQ$,2ME]YNNV10b$FpJr!mquQlL0&iB$7YEFD̊ 1Y&eXMHwݛw?3>Osr`{k{ng>w.)>zJk B|#ʆ'ScZgа;tJs.KaiddؘYWi ?6XSUU?0tZk)6QM*d}N_JhMF|g/GG k+.Pu(}f??rA%?y]~WђL,DMSPU┮miWsb (۠نrY 'USU1Elm);))VHft!Q5IM⨥"ZERX1L9h}b8QU (-b%`t+B{/2+)V+[;Tm+k*:j>CW Oрjtit`P[iҊFu Cǚ;$Ws::b82έw&Ajy 5-Խ:uѪ "j"׿&Ǣo tΡVhYugQQjjR9m pQ΃Ʈk'n%u`uYپUЙtv<jT'^ kHr-!̩P8P Jwl@XIj͜н6s9A7[Ò)zohQ>n`I[OcWs5fca!1^5c4mƠ]oE<[VR@ƢtSThlatR)>2eLV`!E7L«LP  6{C4*&"r[/0DJEC9~X~yT`] d6ԕ×LC)4 =NNDdDȤMH%q$1s'/]|ugwi/p57O\rd@x!>xʄ(Yːڎ2f4bBkiLbZ2~QU%Pip%QC*g+nwU9ӒgE2 g3,Zj{Ah'6:yt1ЦHJ"mDq6L4\8AekQ,~SE۠JalFq`tk7\a2eZq|r*9\2.&lVϘ$VT[wܓ=ragdG-^\x]❷hhؠ {vx(Q4ÇzBj[ƃtD9~{~}{GD18:b.'xW]}ɤֆ-?}W?yvƲ:c:P /xAڋm/EQ2uHA Thc7Fj%C ܓ_'o\ݰ0ZHɠT'5js0})(5%xOKo,tB"GP0pFZU듟92t?F"]XRNl\?oTՙrKoR&f?7M }*zŭ1B,yGd+Lv=}'C!&xpj!((.KQ%@r#bH]'Mkaݔ+Qo :R(\TZSJ4JpAD~s]חiJBaH!~)#ES -_iG$;*cNS. N0S|2.g|l?m2 P-k wm'?"t+ObswuzUq2tFY΄"4QA8h hDGF F;$u2-BJ-&z6 __(UGI|qwݢUp\CK AFSQ]>—+(,1Pe*oEw!$IT  o^_|aZ}]d1_,P9w{ ;y.%f'\a{gʽ;9?[q Npմ)b3db @aCe,Z %@2npGΰbK&_²8(%!+1FvG.^teL4ڐRfuޢE;ow~lVP|V݊|"Ԯ=mے2TCǨstzY Y Y-?676=xl _78Xduݹaz4ag_1445FufXXkWm֊KQǰ*S^{O||gmG2R &T\Y>!t>0Ղ2DueHg',`&L R*R>" ݄qm{w)HjL6(TUx9xk_S>c{#^i3bj XU#"] wmG+fv/OQV0 )tx EVam S|)-W,&3.(njiی\%_)(Oq(MXLUax&DT 㟾"Ÿ@NE*3j*#L̼Xj%C T10*Qժ]w$1䔦Q}X \YA; UURbP5dPHFQҒP86XPezB mkJ f/S1njDepO& JHR& ~??.p̥+O.f߹;^#)I͗tS)BHviڈ6H3Tq0oK:%s1V ؔuSS5(9MԻZsn|Fj9.U7yw";M8:'2 ƉCg*Rm@qBiEu\3lJ6ag4Tu#AzELւַ[qLdq` !y4Y,Zd,ZS9BL%$Ƣs!m([)srrB][BDr <9|$D.t[o Ihuݰ*M5Zk\]Ӫ\M$ߢM8|`e4DZbJ?>Ap?=ea@X%ߤL G`+N8wE^w~2QU[wPK3R#r{;GxwQ9EH~*"˜)S8C5p tZ'Ŏzb u29xHm_}O\%Ƞ@R(X t(bօ^џ 5j)z$2dG ?F}xwp۷0Z1h2 G2לLp@U9&)J)f9\'''lo216 s:;ò]3bgwWY& d4$̭JCxP55''cBLGvc{I)9U٘kXJj^ KLsxxlA JoXM31 ي ͵PVhV] 2<@{Yd6xF]wBA +m-*sN[WlM C( VBŊ!HMff& Eh!^wS^D.38X둒ʥ*,CI Jm3ZX̊!$+AO4^<ę?( ;6 UhaɽӖ_W^e:dEt4p+P[6HNB=@.[d*S%ɍLj^%+l:eV%Q>qE]-ŘQLSm tKPC"X<[?3CRTY[P ].P`(yM-}1$TZ)cSp1V9]۲X? b~Zk|>g8r||ёL1|6Xh<ʥZls.{{J~!3_;woq=4V$7ߦF\c xauz?!_4;_w(׬^fMN~?ehhRbZs1!wd]GaJQ91ХF퍸i-ƘJkkQ}ڠ7EHm(c0RU Z2v *AUKΜrj{$dXE נ!0\Hg,6h5Bsa>C=R[^D"R^(4,yrMV@R]O%{D j, D3W41&Tt~0wV5;ؽpi6h=nb%nC\0gX{*[\ ud6aDzH)h#Y$*&Ӓ%k'3*c(yHC#jyU^_,W5sJ'ptѣ @>eRpc5 " 9.hf2:+L 7c >T/?5ylgNh=dյTYP1e5kl帲wnܻ&&1E:+-Uf(uE](-Dѕ1c13ԕ[1n]"p]h( 2lϐтNF ;"cQ 2hC h%?zSN}W&?n>Kۼy{CމG g4*XB·TprdXMHA Ĥ1V-JbKlMo,~IR!ڶ]o}Ƀ,>)l>Ԁ.{2#Fb&aHY!fX( cK_y<;u6U0ZQ7 )֞=Zw>p2ƍ|忤Ád:]fqI2,J[ug"ٽēO=K3ޢjrThY9|X,s6*Ϲw.o*vEX %?ٖaOm(H/ R8rȨL2#,\ C@6n wʑXKSU5̻$ O0t v߿ONYaHEwmoo|G?O>uf~Сkơxd: -Z.vbٵĒ+1 p~x*l^d98YG>M=#.hYY9M+ӚBIfNk 'FD~X~-Y.8Ff:ǮX~n1_,^v EIr7EZa8f2m˸ѐ2قO8d1_?u?v]jW?O~?wߠRg"^m'_`gXgƯ9py2屭=|?7yܪR lJjkdZoadE7STS+ORR 4ܳwWשYrεҚ`3ZP2L6&~}aeϡ@B;1IUINx1IZ(VrnOɝ:C B jT*n^䄛0 |ҘZsĪV[M4Ҷ3hd[@2I'lJ,fj+Z钰+}1E$b0x{,K oIˬ[@#'`0YP(u!ƿW_ef'2RV&YL(NSX3)_3e1ɉDEqIeR˿!!Y),bwlXחӡ/6asD;5-AͰQFSbv )2N>'Ks6[#꺦(i9EkI,>*hS;k>G Q3h.]bAķYJp# IDAT(mJY)LS;(x%Z5@[vւtt2&vGx79-Gj*(uY֚!T7hLфah51E%֠&%޾v38=9Ʒ+HDh4:fPe+\3bNICL$ۓm%Zenܺӆ6#$[`9>U1e+\}g&cdA7~:6bT혵<8t jrx4iYOgF4.QϿ|%x).b^r$o %gF_EbԤo|g(cIy94M\ Td8K]9֔ru1MSsppPt&͗[H0̙/TU%M4uc2&+ȉd)J&z˓mvvwPZN)af,MQ?ܧfQ0l:X-*k*_,?~o:6Z[ٚȖP؜ mVK効_RX$8ւyd(=Sz4_scOGGZ2wg@]ZA ^Ë1n*ڮ-5ZÙIH ipKupd&7|ٯ9cspkyHGJ{f2lPT0)3s ~^_va:&6uC2! 2z[4)`HHɍTATRȱhQ vo. ѕBAr*eR,*yZ㓦lE)f-bsx1xQ~#U5*51tgn˟Q+*t4ZlKؤV(siHQTZQ䕛Ev<)נl, BnN6yxEwMM r̥;L\?~g_-IŨjyI`%*V=b g*p$&D@C@qFۍdЀkr`FZ\6#1IrLf7ǧA]#S;#âe-ɋV&kPX >:r)F}$Zf{v*!; Z{U -C!BSx\v7mAy{8=vsz=cZ9qz|&5$ʲ`r8f`L:cGP3ZY#F hx8ܽ%xd^Oh VF=ێT;ՙO f3XILԎW :k,Vh}ģڲA۴,=z&:㛆d@$:,5d F)%ynywg>CqשƩ|#f{~S41PE]Y]Yf83-6,O.}v4Tzٶի\yU sL h3)?bŅN;l^+)abnش;,N F!w:&9&z-Ux 4Zi2+_5hA@tG6u5)|H['[_-Me`NDN) mNCqu{m'FDtXTT.̷Ǐ<1=jHVV) ̘<o;e牘E*E M2c}ݽW4Vw^֢4VTRر$Q蒕*rj(EL"Qiړse$J)ljQ]Ɔ IJH!hP1D֎ $S@GN";;h|-%oZ+`"J=eY2oZʪu"FG_ xU}i_D)J {|6%2p)AUbtƈ˗J*lu(ahcQ!`!֎餦7D8R%9JpZ0h2%z>= 3$~cRB%' 6Och |upks&!sHyF bϴepkB7 ! nuDlAcYHFG/]Q*E ?{~77[-sHjF |^~xg7XL{='eپ%ȕa>P8/󦅘8<˕GGYN;b=+ V {=¼e2q5QR{@% +7i5x/]sަ؝Hgޱ!٘^s'qIɁb.yG׶4A5-IzmP$- vvqSzE͎EMX&bh0kV΅B$U!=kFUHEE :@k5]Ή5vo9 |W/ζsL|˵8w||擟*M][v-}5do GCAEM,8wk+K9!=kISFTK܃N"'m`S].ֿJR~U62m蕴|9^xx^U0Lٟ%S #.DJmqU(|ŀɝv"*M hcҖ6deMQRx%=&*l#|ǟxpw=s~_?£e%RjG8ޕ>ӎ?_nf$.ld4N't4$&U3hi]p !b5OItQl>ZOI#x<)%DxlŖlQ#ګZ^_Oﻗa X) %1YB/ʮUlD|$yӰ?7V2_yr~eudJW4.^a8u*H*P錶q8(T3(JIMiT&X9svF2aG/9<ޠ(,uMY $Mv<kYPS1qyǣ4-j*]|؏Av*"h\3")K+!%emSHidIZ4ln8-OgX]IPZf?+B NJu)&0E !0JBGq`ao"XAP]54iO(6!8\zGBBL=\ơ #x7K֧?{5J3o( & 3E#E#mD<6J< h\ 2b+ v0E@go>dI_wy(Ò:yJkxo?RhS-ZW˴mS &O eUQ0PV*& HZAa#֢UbsHrM),=9mu`AnV dC<sOpr$/^ op]w?o{}/QeОQ(I< NtVM\͍O~G?SO< [`$ؤK #) ʬ[䂻sRf8޼šq|Z)ym$#ZCt*, xJvꒉ{@Z^%RFXHW wY|pvګ1? Q[|+s<̚Zpce)Vk>/p2x§36VI BH(ʂs-Sw88c (԰ӛt뱠]麸X^h-e4ƈV'jWEhsGVC4nul?>FG;>81戊;"1S]_w:%{agH]{nn(yIH!1 畐PtO_Y[[[Ǟ8pTg:;6ևl !U%?xd+A:3+]aKr/Oj&^/Đ, "D*# `t=&tQ *F4$8/$J `P- Hpk 49`ʠc+JdĈǠ+AAVei{.$+(-1)AQX&hp1s}6Bs9mpH _TCC?#ހYzU~W LŢZ)9uVխ|ܾA[ I)JĤ*$jI!0kFl ErcE3IIIcZia ت8J<};4EHSm!OxӬ./{3αҫ%DJ z2mDlDN^WS$z:f{{'7"р".' ;}^ezJDk[\v)Q& W], e"țWS>@h9++kllsIn\-+ +@eE35vvP2/Q>4mӶNh[O8 =ĉm Eϰ{pR9]X+~IcP< #ΉK6P'XX:1d6>Dof5^|/)yyGwo\]cgCRXq eǞ>n5+*LJDB=q|Qd+&$ڦA^ U|hG}c.*k~) nIZA{MPR73g+wn4 8?'>K<ցN Oh[F#&͜dtIԚy|+z:/OwUQQ+EUXRk u (\=uڈ7ĭ1onoC?7{i5ɄQ.@ LAYKUx/T<1HhY\`?$6Thi˼mԩSz彧, (  ,2! M:6m?*9*hSb{w ZtFatV)e<̳,9ԗmQIJx̻{^(DUEk]-cO|ьG@X/M{wG\tδc)xPF"oT1H S+*kc*=_ ""^&H29+,Vn@BWZERҐE!6IݡT)7z]#ﷶwQ*\ ZiS%p;={^5$0ypGjAww>OS$KHPd}ԋ˜᭘<ڐΥLvR22J5ȴ]FNbU]D,Kb4:3|Ӌ~k/vИʞ^k8Ֆ5LfC`6J XCJV&ӂd qQ$c%A)_\";ߘp00EE Ph/ŵpY F46 RpXi1:< 6л;Փ'!EtfзD` r1_Bbzw=(g678hl آ!^쑽*bR"ʍ.O3.%[o̰?dPyUQ֢^ݡ8x-뛏 !ikno7>%zy4Pz<--SHiLNxeN#ߡ(*Ndg!o3g$bmŬѶ=!W]`Q- 5 _y3Jho nܾpdĀ܅6{yҍ6} &WfidY'pz$7/9|_~/8O>4>׾4L9#̻?No/vJ4;ڀ*Wg!FBd4IGjuLD9-wc.pi!%}3x T8-VƤDa,&Y@RkoIf<.Μ>҈AC} ׷/O?SW'Ɔ"_mXY_#XEup[ҒtMNolpӜ`_T@2e&EO_;G;bٞL˼-26Gf -0;lɹ9 l6ayy5ٌiTU|>_ۦ0εMCV̦w>g.mm ylߗPz^{2"(w@,BfR;46LCΥ_`p:GThAo^| - Ƃ[$ TZD" 2<keDݡéX# J[RVAdIb$uh*r%Nt:js3dqtE $#i!S8sɝ ls}W[$ђlJ O%Ѧ˵J)S>ES)woEm#o[G39') oNX{xԐUW~s(`| !]RҬ$I&cBP&|Ds]^JaA)y2 ͎ESCPBQ`lο"([D6ΉF3 sLjօ4j gXcőIw-h ($-⯤ $''9&O$>Q3ZQ;Gi !olf.lLIJ3UO19{kV$ i3e VV&]i#5f.sF&{;|:?Mk) 1qT2:A@s0 :q??!M6ۛ@Ŋ(4nW\'W{tOE۶T\'zkWyJ@Sdmi{N|>g?[ë.^﹟:WHyC@`i5ZBS`khseI(4yDr~N|g|3 Y}~~=>f[CnV ZWKyUyw#YBr f7X≇gg׬>k0F"HXk XkRbfnqV%!FlKUA:]N ,-uΎX0+E6ܺuKtI(`>Fvt$5m+ Ҩt5C1]ƍ+d:/Ծ%oM翌D{lơk1|\8Ly ޳*{{Y{#/R^(EȂZH7Ytg՜|G6GHIhVZyXޏ:qIщk ~7Gt!Iy@'8zS.pcuLI^PF'A F8jd!*SbF`X jg »k[֣ 3i=52džG Iϥ˗y&gΜa:bLxK.L&޶ VW8 KuN0t",5$>hˆk% Lג'1x SP#HI 1CvDrȝǷ'5ߪvIjtAz$#X mF̦ 6kX@[)m>I=[eQ>%f'wFc3P]aUihCH5޵VP "Z[BH(y2Xh.bRDZ=@Z$+%]cui۷,O?/E)S@'ði>xr'J"VgPâh|vz5 '!V4>!vS׸&R攽 BbA*$xIpXkV.`WqncQOUTm޸Xʦ*u"SZ|ZMl'Ϡ5e)6#dGq'Ƅ#};^cR7 C^tW/_᮳wQ5oq=14;s*S1ox Y>olr j+Mkhm3KŬcCa*u1ZsM[ܾq&P ]x룒ADSH !P*ͨBj5s f =E\bK$MkJ#(k·{D&xf)){Z&4WޠYYg>#ps ?]3}<ʅ׾+/N1./~+o&?fFp ,fW_0fm4`ɳ0hlɎO ]Hmī #;]yϼ]FK<8$U=m%Oub%t/)eE=ulq|ʔtRTdةn\{$kk{( E2);N'<xІҾNS21/d: < M֚pB[јZ XtRU%BآR/2/JB#[^<[w7nRX<U[n1{srH[ A s( >/]O= zL['Ԟ hLa5BTU6[O Rg5d֚lsh i0ù3ht@J%*1-J;(_}2c+ Hdh޺u Fc-|)&qO;ݶs,J,Y! FI9Hj0A_HRb4Lt?Bsänɟغ>k;,uK9y+> 6w=(%g"v? o{>qRFkIjO@ 1#*DwRXCd.?[SsTXZ(l4F|tP9pǑ|i#BNy $h{icG,p*%gh硫ZX*"+DtIr;iQN^g-t5$4,%ȈAIҪw貏VbI5y,U)!@.|"&B_+kB"E 5ZIIaz= ʢVG\N2X Y~/%n5-{*-kv@wQ_x"Z|e*]J^ %.+W D{c^)NI!"ia$נJv'xq丣q80B Jqmnlﲶ4b/iЉ"Yk&c9B2r/7OںMgDNWDc1>tw(i[|ʛZa s_~2.8nysz-,>-ZWQ-alBg@(FBt|K_foogyX1zR\'/e51xfЙt)ѮD@)B\|&#V׉a e z5ٌ`++L'9FRSBbn׾Y#{xGPNrnu$J&y^Z]Y8TUoe ^AA[4W ]@qLJ)Rx>0xVrC2~g{sw͋/~#HI8"ǩ$NBQJ &@)c8-1 ,1i|/i0DEm&d[ɟ6.xBDa mD@-F\IkG@]d 2\(7|=N2h{\0QDQl—>ǡ곾ABDXNdo4mQC6<ŀ$KKLktg.Yjv9kHO_C2hͼmpgW藆HV. +02d8O5 15u=eme) 1h0GH)ᝧs O9pcʊ;Agf /}Ջ\Shz & ;{Ci8ۯIIh5R}<'eycϞ f}4 =%RJաqSh`:3ιv&/{y;G0(Qh{MM٭K+W #: *d:J+&̈́ۇ<3yu4cji~ с S`{n_jK>͋/V?h/*s){?$Dn޾I1a+U [ )wPU%ZP1Igco@W-!z8AͻtoՓ[v({e`i7.] MI.+ 6buĸ-.*CJr@n޸&S9/޸;{zd6))Fskw@ T#kEɻt>I;tNwSNݡJ)L<2(Z+Aꨐ_7ͦ]!|49&B\Ȩy'Bpa&I+6V׸6RY02n 랱&8x/1Ը9D@!d6f ƘZ+EQeK`#Bk` ws 쒸P SáTcX r 5 ~I&U k܉`|Cw]iw|c[P2D,%%i(ɯ/QRf{)PQ.W},a0 S, )Ʒ'+ )˓8v((,8wGCrib;w,Y]]굫lm7Y>ӧOq<|*֘SP@iE-СkHJG v`#tLc IQtTd0Iʔ:r ~Οj_1캖LjaEj:ocr)à{4 2g#J̩QT,D6)A)HMFcW%ڵ!g 0 |)MZ tԑ*$'MD#O )0CAJl%FkCli9c2i&*՚=œgK?` O6sW^3TEbT׶jع otn `Ω{{kzOW^b%Lƍms`:k@+Wd,C[ rm{̰WPbo_#֑Ă~*QjҬ?2kH'&BJ'6ɢa6xKZ;8ƴ &'Ņk{L đ#_Vfӆ݊gS#LT\hh=[/,/~{;{8p,E* $MTA(&h|)RB#KM^fF]{ M 4V{9sW>NvO?q1n\갏2JgzP*b&حpUk F[b)QI/Dŧ~U3KRbl%T^T,{S-El:=eYtn+ad2)ENn SL&h-T2R*E!6,%1HhRȴzPjNAFF-q$#9sjc7 nGJYksC'HhqD3u|O3sܞ,IHAS8K^gemEUivMC+冩ZKY5mϕuV[ͬE$Jut"gR<~Xlc~ iw-ǂvjJs|mDR"&'dzȇ$D+k̴Mrj8meUK=|Y~W}R.)W6vuOysW[Α#I)Ѓ?{s ]w%+q>Sy IDATIBb=k 6 lsVe)Y PRĪX'%IeVFbC,D2=kbPXESbEy ^}O3 f {,v@ӚeFV'&Lf$AxK%LP0F[ZR tg V)c^)|$C^= 9::'Ą-,.$4N:rCOڅX&Ob4IP$cdN #:5$+Ri %{ᅢz%7sz_{$c.لrw~Uccx_c0SVȩRLylBdZ,b'S'/ّE!GĞ(q1Z6AT4o%(%Xl΃^^AIGs`XGїF^{&s8h>C7mE>D}qndoׯ\婗^xBe0K}ۧL=lo8#y?(z z^YRXAДT(p}7nr b=a55,QV3\^xo {bLlldssfii)U5Mċ0BM (:4D$w2&WW>z*N0M `YV >7e{W*28sEvP)ĜęSrmiUS ٌ'ϩM~ӿˉ'{8~4ufFf#,QLș5>Pb2 PW4hʴ$Jz~?K/>U5x9tU^d`v 4d'J-^-3X;|FUX1,Q1X({tMFS&uP٘%{Pf1# 1d+_S 3Ubm$7xOmӄf]׵X/H_aUWz搉붝l7!Rt2]R;Xvz|6M4MEӧOY`#&qkX]H [!#J ]Z d i5MCatu|>]TUHR._>f9uk!C9aËa^#ߘ)pKutzQfaFc dvεSR3JVP]5 ~-Hf%N-tiT3Я]_(J<<?~5\y`.j5%׮]\ nndM9m !ZeI9l e6m;HH't+H8>YX82*\vhJd_bOQ{dt}R:˴iNk(7Q&T F9pɷFD2IM!U7b8e-CAb$4 %Ie8_DP!`hJUCehWbK\G V6)BkEU6ĨH!u?L*b6z,_=Ǿ|gi\_IC^dQtJ '#S ,lg*br: 4JA )0D*#:aTowg̱C,ZPNbFx1KQ\r]]#gIϼ༵@j's[}?w!$%1c4>OBL&2=J1Q=gFxN ソdʹBLٲnҏt֦'3.޸o繸;33z$ϭVTl,W#)EUW,-3L*4O4y룜:JimzeJaA 1@s$+y/ԵpέYE#HqƍK_+ѓgxm{:#MM=a%py-3h2A]ygLF5648;ʐޑ"ө/='~ظzzCFm}X+tȴl%J%,VM%T:Z)\6bϴebk,T71f;P9'S,;LҼ0:eQfZ/锘 CR*75FYEԸeA@* **K1L+HrJ ~AcݾjH)1s PriAyT456%3k0ZmȚ":6sd[P5L $9k :[7MIb. F/P Q7%1)jrPjLվNRr8SŬD4(s9Bh0ahх :ڤ$v?5(̑Ff*s$_ELȴŖ:F,?VNWٯ BAjE)g[FN?pws䈤 |R~~oL5UͰ,Bt3R붕J'8fae4*V5Y66ᔑ 9~}CY^GX@PRKɴ!b Ok"՚H=4MV )+BJXSc1/g?GPVG]ZG(a_Q<|i~͔f$@S_{MJEJ AmL"5f^ր $.D ${#_(*&J+V:ɴ.;C3Ls `9 2ȭZ3s׮qAJ~0c"%FJ}QZfEE0̓H]WTn%D:=J@,S9Rj6c"yT- JYʟw0#J'zE)ԥn)Q4 {B,}92c$5E(9"FAfZ٩Jo|6=iQP:y71o%eK(N9+NeZ 4MF${x]~ { |K"4Q`l6nLweey@u3ě3&l~. I&R̓(TĥE' Ryv xBth)@ )A]sf_f;/dB,2Y0qF0%!ZMҪ2ת NdI=k8L >Qh ҁ4yMR#OJD]1BR/Ym[7w`:%)~~666F3I~L=IROE(^ߪpKN$Lc)P!>{ +7͚0f1Lꆗ^?eeA Z?oJJBN0P=nCsi. F|xijoXCacdՓlj E8 u-GnoF 7-e|g0N*N9d$_fWz|F:$ifnծc ܸI(Cky+@̔bzX!7YtW7 +KloimN@;b2fJ#Pxp@i\?$_{>h(9(!g`RYvo_+%ГM+4L5)H51ߝ:ɄNc.*"JB%  ¢u,"WӛW<1}۷aL ji SX-0{O=&J2[(T!C6z7W u-@ ]Gַ>SO>c8{"9Ӈј!fP,]gN伊~Cl]?{%\t#2}B\(J6o6Sr^6^+R4:d xf2 SnDcśD7$4Y+%d{]ʒg_R ׷l-FX}(v"&hi9)O( U=מ<{"up ?ǚ0 "BNJbzʋO}w^ֆxxSL&G㬧!Jyg͔'6fgI(Ě= V޸eXl6ZxofxHHAdѡ$h<N[)fokO^bj\kKrbPW[aWТkITBkQ#p1,--'i rddP7<79.Δ,s` K|EʢѣXc~:Y`w7,-Mdi}Cw>k1q=ro~_w#F) K͌ISԓ dIpЛbp1X-)y.PB'Ie?$'c;>}R c,ERL)COܼɎi]Z{ԹEIp^@b ˅b@'MfΆ9Dl,kYH Z#Am;P*k$bz.m^-*r6ʈG9}g`jP)[&q -J],7R^PYN[iZq؋pH\ 7sY@{:=KJbמRNTW Uh=?e'~rg]\9&d b@;tJ1`:.C<|G{xٳu6 !J?K3a[.sNY (ip)]!M:ܳRj5 WA޵Iswg7:M|u{{wkm* ԳMBlIR`"A++ͬ4GHb#0|Ph'J&mxI6ME>KSo>u*h* jL)hSQ!{,J X'WAYO2݁AAǢk{Hr[Rh+1J3Bcg UUc+k}Wt$ b$61 CH%7_ē' 'ϙGx:` x};8Tj^1'+?7y|?oA$&uP1dZ_j<}%j4D.lJ㥹F#JpC<{aPҎg'_c|~GԼxh֏qEWk )E2 ^H$ElR eb%`:üJc*qVU DŠVA#oc]_]*6vk\TDΊ0QUr=1{sh21gئw'jmZi_53O^y!^0yǷڛɤ`bi GIf{mj.vK` o 69z7vX:~єP8s!q\u|^Bـi1$Wl߸΍˗(kꜦA*Eg[MF8BCi4^H`zipIag#}b!a]!ʾZ/BDE[x`KEZ(#-m*zeme{PX;$? FZDia̦_%O>Gʕ+u`22ֈ_FQx;Khfb"EJQ=ș{嵫ثv`) Ka-E60FH:jVN :7"NDͨd Kʃ*b›h ʴy FjY\2\`-{św*79$ưUg+HP*)-CFRnZhLcWɍؾ_pF(SL e=3_e 뵔{Wnls:5M#.Q~m4AW4Nee V2~^0o1ZMZ0$X[r_130PzҺ-RRM(SXc}2ߩ7gf 1%y;z^2&*|!\g8]NEt&KTEZ `<=%qʙ0p!j0KYb#!-N IDAT$ߨ1Ez6z'G5/qjχ|f)?ڿ3۔JtLSB!j&((hňD %SY6~"yN}+\= 7FrF*>f!r%1ws&_?]<奭+5 *e'Aqu 4MdVh&?76KjXY=/S}:sO~qi}PZ5rXj<4D%܌gH(lʥOZX"X4"AG7W?p8̍LQ) , r/,r}Gi:b&Al)p0jiRĕ{#\!g ƂR&#,ab4!\7okm>ʢs4[3bb>[[ e4gmļVY,zRV[ v saQTSJ „Z>FlqF1CG"}:µc i#塃ɟvhJ;xQ:18gf5YPV؃ 1ὠ%japJF(PZt-Y1O\vg^<˓^^jRGumϵ|}5M]`|~%"t+Di*;.DlQ4˃(M\.}x[)G l6/=*O]>8_|ף3yWGEx 쥯V;@GVt@hPJ!Eu R4)2PP^8;#[XAƽɄ/Wy}GN'ɿ7NϿ}!^| oy^Nqן:)@q<){6Q\kM] &*}EY$]ˤJǀ+ )A4RYھ۝C%SPl&|WYX1l5%ꌖ䬚L]Fۈɜ{-0I6]E޵oU :%Mbs+yw0JXF;[! CK#|{W?]hD#!IAMu}")#$1uy)f;LjD ȋR'IP䄓lMΟ}*eB ŬLıDaތ0ޟ7$)._z=v9X=c8I'~ Ɉ7ɍ4oD LaTlf7P[h [Z}l!7D-XM3NbUGL2rЌ/[uoylSrC"6",g{OS֥ ,1]wj$#EWu-*aI͐?^xE~7Kkr0%rvۚ7)E X8D(%}r L܅+>eYe/9~N6^U.ok ;oobO+%xǷRo9x ;ۉ:Y%'  R`4|5rFDd6*]k^eJRĮXQb:A+fBQP~=X\d'q" H%R&@"RS/D< ۍG)AEG:n`>#P39BSמXW6 Wa#s~:S_2x>p{yb%N;̴%Fcͬn ܸn5_]1MmV/uEjLQ;/-s?Ɲ47) I"'۷G;EL)B Wrw/^Wh)lR+ kٲBϊMjҚr0b z) G"@eپ2{]ʍs^҈CTdJ,PiB+@$d/~rCHT^uD}J$ZGH8+YUfMLc 7doo(`2Zw?c裡A2uhЪ]:>څqd Ek3Eaq`inuj*:0Iuz,oZIʌ4/r1jGMhMc2/H܏1JJ*HhHщbΔhϣA[!#Q+&GH4Y5ͅ,J&SL'Sz} f~{4ܝ]k>r񎢗<}yϙ{ٰ(QBzh~tHdFC##ZQeqT+RnU(emcԚl|`*RcAf eiiábI~GJ)|v[' x8e+Dz|;Ք+;v]kl/MĂSHjKC[V@YhDΟYI ax/hs:([{_ #XTo5D ߾JHu2뤨ؠ0֣Uv W-KאڵTU˗? Gcp,- k<s4$7oZ{748(ʈRF\{1nhK Ψgpi_f`,):$T %cBA"|?BG}kVgNs$}kIZcQ2m !XܰdYټE` {r1;*EgM R& s~lrz]UN41*0Y7$DD4\m?c|[9pɘߋhL _?ͅꊃ|c|=%ɞH>x\aPJ()%|`$Y|P&z(Lnl :|Ϸiϰ=fY]_cwow>ɕ(G==iDܼ7kwx?+=~dqW)D;O*=_a.]Z 452(Ro:+&> m?)ȧCµ,=za`XǠDPӉ(m1 #\E^QY-sB2 P%hi|BLx]'QCxYtMJCMS7CO_ϯ_t?9q^7 vLQ*OJ{ypBsnZ~?MB}nD+iEY8صZ)K|ZౢOG lq>[cϟ}4/<쌵T<4>N/*ǙM+it<;ƹ/'ЋP=D҆=Ecbsgޱs|/ gz=˼}?wKOk8;q|Ͱ Sbcuwqz䷾_ѓ$F'MHu@)2]gG1ĭ${JJD0"ԀaJ7lAqFM|iIfK Ctѣ(hg`98*DL-WGBIeAddPFeQ~0EI=md~oa}}wٸpv t;0]t~z]6XS Ty ?[5sd6\(Әa(EO8@ǽ.3-uۓ b='O|38zN8unmI{X۲[_޼i,a%[Ն؎p Hb CQK!DIGFT,"kHaM}ޫ73"F{1Zs0Cޘݽ! q:U$qa7&*h'=*I* SP邅;& gRDuNiLrD1 4+XZkhqRE<fp|+ݱ1dW[mQ*P2tȯζ15Z0PU2 [ܸt(@t4̮ Z/ZЉsaQ,l^YGю@QYs`.QXh_"I*.+X][[ )d4J.jdB "x >#"жжM4LX'>P׍n{MkA 1PJl1 E)麮kRϬ9l6:Be}mguu-?uK32H$,B/K2*"g#,XZe'$F+\3\sNJ|Ѡ?EuԮ9vu.^xDZe$.Za48RIg cѐ,8M$SO7zzeO|y{ 7E^Yͷ&/>wAgXc |ʲcHƙ׊:6&&R{nVeGK)ELL4Jc $' * _Q;I SJRZMzy#SC>kE#}+︗O~G8:7^1iEY[E1 hrSGEhCGs|+O1lJΕ<[$'Jb+.#0%ělF5^Du"b7&gP& X.>l#z-=^9Z3rtjwk!E{|yJ ,ːVjYEyl"\OI23Ҵ>R7e 3N63/e~4֎x>?߻нwpri_}9haqW_m*+nnsyKI7\y7+oɨS R6:OA-6Π@)_g6NٱfjF H\dSE&]?T1IAe48c0J y#6)B!vC4=Wl?]7ʑt*|g*TϱuܺsqF1Yz+4fLl*T\M)b i6Jg)*)c;qg:F\bb$E-ԝ]c7aU80*eTRxCZѕ9!=ń-- sh;cK(*WQmRTה;|¡E1V³Ã[ihj=1No$m fQG0B}'9鞻XKLJs8@J\$0QQ%5DeYͲsŊmjZB Y+bⶪ1#{Qiۛu= mhvq-(hDq A֩ ,HB ƇH۴4ɳP473{3xu.\-mg0lMȂhN8o&$ؤ^=r;lD:%unc; IDAT6:}4:yrD?GD>)=܂D$<*Rv)if!GmS$!7]:Kx[ҲP9We{3DZj6$ꌆɓá6i"R4QQbA@xF4e=9yQ(Y~Eڒ<ȎX "u# 5c#{( _4X}< _HE՝(R]kSv QZ6IS oJT'XoU[eLJ-m MM$2 vh#Ak @t-FuKcQBg>oIP+nCB`:ô%n{=_7_=Ha u>6.M,q[OR=sͩ2$ԫ?vsPU,C:Iaamj+~Y=J4MjV{$cbyu}֣|_,[6̗;/kTQ-+iF1њtU/ 3f y`;Y?Do6x:ER^o2sP*b>Mzђ'b y y[q%ng4*{;9{۝ F)~^g}&xzN9] <)12hF\a`RJuhW`C&C@˴Mt(k o(`"aeI* 2ۇ M ggũ䝤LSTӊ+z'S| JCb+fAkG(6+VmK3+ N'Or{4{SwfouKJ~@Lc8ZcԟzʝrPFX(Le>}mإ7Ѵe䜼RG"<늼GkKY7~(Qv߉htt"~rF`_ٌIvN4/~oXO<ӯ FTE1e;\EgsPm7?i^o}ݳNi)w_=wK7iąDU1Ey)!*DBr_r"hZ]!)Дx5Zx?^Uwܐky[™U.ۻXN[*+EBu"nC-y`69g }\Yx?鏖xbݤg@9N+r$mh84%5(+)Pڢ M`ű/BG1D DM"mGRnS¿6*dJ.ơ&kmi9kZQgMҋ%>FzbV aĶ3B 0o F$ ;/%2;w,~IsЎ0,E`~eQq iDH^NFG<-ABTL51ׯ_\|.3ߕb9T-$EN:|I:oQ%{AV5G !Hb!=|whYS1~=4d$`</D{qiS9<ޤ4*-VԳc*OXzNhmen޼y RcL&ƤݽӶ-NZ4$ IsCb>6yyںsk!7l׌t?ӹ`)%HINFkdmd)dxg< c}hBCH? ++ù[ ĶL)p=hؘQ!I JXZevAqzᘂDYAYIO mi h3L=ƈQʉ '4 BބsݏiJ/.beXЧ<Ն;oiuX8 iL`'!6s7ӶTeEoe?o^YeվUG^d;hIDc@Kt}س?N?< Uΰ wuQ]p*PDAQO9$y愭%{G^S2-Q_z' p_gy4v UǞ҅ 'Zt$lRsh1YB3"qb䞧{"2ZDY lkRXKBcژotk5ĸnH&'ؿzCW~__'<[O{+c7ʟ! |BN$i2=K qP4rd$2OfiZ`4$e<E~|tȔ68͢R7sYVGCz>%n^ή[F j5:%\ KHeݴ'51Ny?ƣ}h@1ZZW̧-Qr|LCM"66\bҬs1 h[^;`9b_ ?3?Wysge2.GǓqƻ~}X`uPWQ2sceeEybf]l ZR DYZE JeH]8Ȗ،W o$Hurr.ѭępt|49FU@))Yih E'C,'ĖK;k4x 泖o &j19q4o{wl?OmAs?qji P$jHfr-vNp7Je|nViTaPqF˫?y^E/<^`vŷ5ZK۴dF(XD`lC+K-ajZ2ɜI\WFiYXzs•9NCB;[ۣ9 $YS mGty!vZqQJ:xTNSрt pc2 QJe./Ӷaau{ԥQLuӡy]9\ꖲ,2HmRUUv-$hdd@p96kZЧG)M("Lb~ Mvy1"awìaJ5MC==|:RgxɔI16wxa̛Q_sxqLCdh؝v+Y7QBmԜb~ND҆L(sbO ^.tmIcu«^#ysym[ɀ (ty/ypp|Gk|#MAVb ТDԑB)Ο:mY*U(DN8mQYgtҌsʔ6^o b4#ߏ*)+,adžPPs!O?E3R\6PLt =F!uD+C0bS?giewypiϝ欇: W7-_ǹg<{+їQIJӷ% aLV(Z|@D:U%-G豦pM1ZIS8C6ҏsssA^4)?yk?;~zIܛ_{Μҁxft.CRty L./S`L_I!d`2hsVa6`f:iEZxڽrJ׭W N7>p?7+e-)Eق&67(.R1kR&k-~Nf̂s1 apβ?cpY.]A0W =N(ISTk[ZO!88e{>Ӽ?>뗯cS׽!Ξ:wƬ9~m>~PU}DO&g='nCJe:CvHj,0ؾ)hKLҔki49IzxQnyu^+>kx;IӶ*q%s9EIiUQBxB:(zb2ʆ}dCL$M <ș;'~'y[M*q)qGqzƜf+`.1fa8'3Kl^,+ ڃiy (!:+ƙhHx6fL5WdueP^8y4oy{Ng\|Z1)Zz^$8磲euP-ECsz=ح 隣(iF)@~"A5L>]3C$eX+cDS&yΔf[y <վ>}^ao:e6 ؛OhcX zu Iw Zslz;+ɺm*JZ%s?Y# j,-.RuLdܤ#Iq$+\B2v#VG2WlŘQ3O0R2hCoŋänL䄜0zL&|/̅'K,-/q ozv4I`7aU@QHHbDXzqv(VȞdpݭjGQւ*vmsygJy4XzE ml+zU4tl(ں$ӫ ~/YE @}f1מ;du٣(w63_ |Jhڌv^s1H~Boi0XkB{bpT=CvvwظypI Yg5t ;\z/L1ڤs=ViՠdcA?Y RBpVZ\$&\-;zHCY4ezhq{MӐ&lul~\d%C_nj W,\ɺE!l"F8baEsVݽ)Ei,ָ[έu[RbCݖ6S[5bVֹ`?{ޜ.u>k>ċSNrƜol5k0W8՚^ɚ 8h9k6s+9=.b?ReԳ7*578^hHh*dXԓc~7>#6,0V7/=|VS[|͡eks=&l[,>1asz=w֡5Hu.8DNq \boB EJTS.8#ԕ#)Ƿ#S/BnR?kedADu$T oNnҟR=۹'iLuzLmt`:.rS m$xgLri+lm5x?oԇrc82p5\%qknpsu|_FkK5\cyݜ?s "V+Uhq|/}s}͛vB8met[kEКSwޯ!?$Hb!ߊςʔ'qXf1 5F=tG#Ku4)04}E JWBѐcP0LE8 1~$h2k IDAT\|Ң_)6 Jsv{ϟCP^ Eݴmsb}1) :"twk]^W++KLfSߴ"no$;DkS8"m0(i2GK aD/K꺦"&+ hL򚨀 1;{2ԐbHmxμK<}W >ӣ蚺#xuݽ5Q!:W|=|u IS"v^wCT8A鮈nu$J%;#X-cGINgG+# )[q oSЇvz}c(~` I,s6WTIKC#r:qLQrKH ^EPBQc(vsBxh^q7쁿ʱѯs<2qR E $ XS[W?'C <1>a:WlGJx%͜Z:{:mqbuM9'|瞹gy_|sv"1z|1 ypdY.ɻ9ӃUJ7/dJe9NIć%Ŗǥ˻@\Sb2oe!U- i$ O!Jr{"*E+Y_]g?:r _o֎5zw_<!zY\S՟{:2>c0 EҖ$4q$ LM?le4~~eG9-Jd*C•xrqo\swrR2?Z;FwY-(U EU0'v]ll쐒kty(2@UcyyeF>Ug]6Ʉ&MRi .63)(p|gʷ-[6M*uku)PCv$qMPۖx=LU@%TK#bQY-B~/LONW:8J.S 4k Qف֊A g`2hBGQbԳ)QGL2$P7-!AL- :YFWI)b67z.bq;7wKq}:`Rʠ@ǚdoc/1.fìC)w1g@' 1_|QY,ވ*FuOOQ>[6eDW9|lrt $ %5 E:+%D]P5\x%uY$e*yi_M4G" e(˒=md:YuwM2(% S;qNƷyEsr|9*yp.U]1N)Wsnp ! ix 0x׌T$ٜضf3}g02+!׾/cSCof{gdi顶-ic`?,xC *)O[5-@9D|qLn;d$%-cIH6VC`X ({x5 YiZܼhi6v$D#1jp!1Jǟbyy7orIN< > ~C? BrϽb@O) A6QNne5#I*MTDRh+KʡCFbDIZldF@$~F{#NfR"Q%AL|֑VѿOʣq{/(0b: BBldlDcKv-`o43|6_Gh6y[ vCJb&6FC9U5|?g8T?v|"MT"X:`>':9:ӊǾ+ˌR]itRꆪ|Ƿ"FY" &DdIrOJy4+o?s#ox~){r/]~&_dܵ\[C-C#{LQr̩v@6k[CWbZX*+ إ+(riY$,9Eydx|FbZ,s=T SJ&ⲋA3S}GRbNkl<8ƨrc]yH$(eW¢gx{>)W.'`R9bkY8Љu?O=$+K>۔vFX(0=({{|a>˽$"9KK- b3s\T[␰RI"ZN}}NYuDg4 eJ!0kuZ뼯(=+%)'zq:"{c{ *NSǵ:ۛ,:[Y/"s)~<,8v6f&aXC 5gêֳt|a:ݥiU}j&xəSK'Du .:7x)'e;8~cǏ2-׿`*3(cͳn7 ê/L!J41~5燰&vpmxICWr|mE1]`goZ'V\4\aITJ&Ev" Bʠeٵu- 7ɿ_"({y˥^ay&[֋ԵS`VqEhC FálŇH_f$UfNz`LMT)oZcG>>PΦ#xfs'Z*M%N et%~>f}ec-UU3L@•m[Ss| Yk](!ѐrcs"󹄰@:8Jav7MD唏Wi>&PTWe,0Z/`{>CcKlmd$_|(4b4J-SGlҔ^U7IwX?uwY'/p[E/35A,,q_]z'qQH[h4x.`-Q{4ư<`09$@>@ oJl6t߉*W%1ʚ85ٵJPCԪoQSi/  |eѭ 93ͨkqwN| Z ha/X[_0x|3m+ٔ?sWivYLG|-},2b/ W62E \rw= Xtcc5m( 7_ !olwxӂ&$dPjG^KѠ[MkMc%;߻ڷolHjm'eL<@ld oaL2$38qbJd'cǑZQ"ERbI6rse><9Uݤd []9<+XuхQHRT.S|+Z6`OP>[/~f4G0kJ9$Zl}K“&57<(5d!G`3DdNp4(L 8Y0^}Ggx\pgXrc)~C_*27BkԒOf:;(00K[wȬes0}gd9Rk>ZKpSX0Ѥ"yP)H^7\uf`6ة6SWS6Z_}O\ʜ,1sЙc2 #{;h5o|+ȃyK+9s'9̡L_칚Ͽ ߹Dc f )B87%=g\xwq348TcGg992XZ+J *Bi*}_d5{@"/PHP67јqDQlluPd :LI_Ӥ5WB$/ Bֺ59Ն<KC"V\O@K:-ma&Y6]d2AM#$Qz0".mupLAt\ḣ9Fjr&n*}Ck cA؃4;+K !+GGIZ :NOۢ=vkBwAPGX8Ĵz6$ -P;$(\c( i5ƻ@t:|Tc, 3g,ŷ.WbnE=O#o%x0 EYI6݇k@;GM!B ץ:$ZjG10"&``\1 F$rM1\pgϱ,]z|Yw/~{^pzu4XK]Pi]r\h'tCT&r(鈋h]ATB@_6NoW v 17 Ȫ1HG:F.},EJ7X&}M러ɴJh"T;4&:tjwKr8X#yfѰ=*J}~||9í>?_Kn<蒵5WQ#TDN3,rq0e-c ]Q5j Z^׈ڲ0M]&%nE?oW?? d|L,s x酗%lo>p %FLS(Iw%B/xsޣ-/Bb#Eiebg5Zԓ)q GQ8.cK ߽w{QJєڲ*S|t"_z*-f # ʑKi ;n>Oq)Tb9SBD،dL1ܨWZpwjr x!|~ ZҵҐ(o'֖1f"bk4ynȳ, '4e (2l2a`x)rʲVڵ8KNʆN{뺢n:޸=7*Qz齘4T̒g<6rGר*$GJB`8 'i&n$z4 140Ei/kJؓ1Zk^XAk'_≿o=ͱQN=Nb9l{L&{ݹMnYqx(v$Oa\9CQ%KkՃ1AtqFU=߼΍+ʣ]+ s=#Kk>Ξ{=}'OthG? q·+3%DK Vk&u\ZľuwZIeT)8 }}K9H,--72L!L+Q@*)ˇiUu@̊kҦe޸|ItIo! PŌB`ia`=քԌH)tZqd7$hPN^C XdbıL4JFksw媪"Tst4E%735Y k ֐V dd&Wb$Mr^HZ*_WB6FuY% N fڿQ]U|3/ſ=EfzPfO,Z4]h$~OJ B!+ Zv蚕Df/>+CHg" YTؠ3 5>d2ݏ?p4i6,<Ϲz*JETGhlTͧ?(DVtt&꘦ ZD49"ZQc* (A=.M<7G j4J|@h F)^B5`LNCiRGR/ŷ#xQC upi:ܼF))t.l]rQڌ<>ţx\?Xq4[>q2#z/x^}^|uyrќ8'=m֖P%;%AHnmoS5#Z:DyӖSQZ1UiESd9Ystʑ\SVzn t[jnnHTK&J>W&()BFf6B,wŗ^?dCCYxOZxIH# 2C]jp;_ sT3:YVJibG'O.L!F2qIfJjACr#1Ofm>T;tk9efpC`h =4(FOQh,}B&v/ IDATD|#.Uʱw:^|~7i~n-:cwox6D=V}x(i47vY (W<`3xh)`|i j;'O,s%Na8ͫݢ/ fgWo^k|S'N#q& Uzš?gz4uB_>PB\`00@ %A!d m:::Q~| |d8#sr0 UPsyq~ E7h}\ruV/ Aa3[+-fC2 dX2g;ŷ_@A= l~xAcB5 WJ\’_3REFn4Tʶ12N)Kd(Ӛ:Ӂ(ijY@)CYcxz\Ys6dLC hb@X,?yMݰ*rC/հ[OQ,ajݗ{"S\#ۼz;Ptd" E\PDepA.>xGk7o>eo<E3 !놲,Ņ-Sm7^4YS=tfX^Zh i\{nnJnR#Mi)"O2G+It/cG _>>H fe0`7*ؤId-JP~uO|k+Z(Hs\@_+n y%^yBe噵JVM}iMFn51b"?#8 ͍c,-DzFn-E TghRewfRiduj/4S4JsX&wWq~hEb؊X;?[t5JjXhe痟IkWcMUD10.zXFU_9i\;/"Dʭ%7xOeԾIwYlbHz-CѣLofY@C?h4:'FOȩJ yJ&?G5uPs_'ǻC\Jyg,+T)<*rX`ppsUunv/<-~ţyӥ3R ܺ{JMN8K|'O1~PK,.0SF3ivm{ \|<>Hb!Μ>ˣ>`m?gy؄1F8,ރ1J(WVwC7)V& f^u5k3PEڌyʏ5m"qiqݽ:!f3l}dG+7xi\)EfpQ("eY2%8OQf2Ŵh∱E9)(QDAӤLc6<%kcY&T?fyNrAM 4pߍ okg㽕ֽ__ g9dvl;fRG%7-͋y 2KbGayȳ9vh6v B(]Z̀6&(U vJ+uTtUM;}'^yIUq9y}ѻNR'`8'bU sC0Å"M CyP.ްGͰ56pk$~f᭐% hbL\j\cU!#gPkĘt4Z%E]%7:BY fӠ81F}xϱWS(Tg5_y&W}` w 6>~_1X(O|kc;L?܎x 5M}@셆ɭq]BĞqd1TZclWʸ8WseoCϠmk5cV 0}tJZV͜3k=LiT o_GmMS8NvNmBE/ ρISU ]b4'779qWoDM A*֞هH ^/HHq|/6K}QkC?4=p\46Q i$%Y-&7 *1W\x}W/?G\ei0+,.ѵ /"+W;γ]6ؤU+\y_z qm;8m4Mm=c tEwN466A29AϞmP4(IQdY22EK,->MjyegĺiDLfV,J{Jɪ\3-NJ7ݝYaD 0uEPq.` <4pWg{1FvFmگX'8#hB$K/blfy .0͕|o|<09xNqu?$~I_J惔 9O0>o}:"dhAXXZPnP&p031u|/bt˚:XX[]`\фѲZ H*B!ޓg yVSH1oiWkT0DJ&[ceXh=MQX>8V sgG݊QZC* u}֩ɐH&cn#8l͘ooazԩ &W #\۵~aaaIbHQ).b  U` ty^O]%1`1h5zZkVV@ƚڈH^6C򴚒}.k;AS?c|w?ŰlOv(}CMa%J7(ˏ}I7r4!LP=̊߶N\4&C]r"e(T6W{,,/a?.JRjR 4W6Ӓk!C_PhhZc@E w &2vjNr/f5PǴAGё#)A ɩHiF ^c1d:b!׉j,`AQvv%6Ih!jz ǎnÔı,DruBl5!X2ɵI!;ܥ^Dn2XҲ=+9Ebm3!ɪ䜢kݤ4J軤$4GeN*Kf4^c8M,9AE@Hsb޼C% f4FV#o9{b*psQ0(x³<ďs w*Tb&3f9Q k^/xHsOܸA;O>b}&wh}Kugý_y58}4=(عzX`ʸঊS6VFB}o ocS&=79CX=]; y੿o< =w1I%M] m_".z uKrv=ZR׎<ϻsOla9MtCI;hr tΉ>7 r zFCAWwgQy.8ҺA$@jn:h#XM/(| MNմ bdP}~38thg=0vwwC-* ԩX%Q D=cqVݓYNRFEO$Gp:Ii!J@ԠИRG{]BCq盖"k}X%rgT ZJ!F^HB!bM.dMDw :M!y+Qý'rX1j ,5ƿso_c9q0z_߹{?Fvqz+,z؜_G88V) (#q6F\ BgzQ'b ႃ:%0YF Q|Cs`ؚ:~K<5M.Q= K$36 .[$:(pRl 5ĕYAgKLQsm<_k+˃$pK% d[iZS5j&i15TlE҆U=ɑckܰ#&6#oijqɭX#d&Mf$ vF'(,1hZd7wp2:B l9s)Q RbTM8 1&ZH>?)JHR 2嶟֡KjMOy%"zՕLHz-Cu^A)V[PXF4\RiqUS3 N־̢FQnonk\F\;$1*iQv ^d wvo>&QLoP*v΅H,%/?Sg|x '^d5zަfX\nD"4ys/Az0r݈hMolV`ӏO3yeE=(b2.ʥO5{2޸_~TzYʅuV-z0!i?E؞M46훨.hX^d ز6E/ec5W.e)4rĻQit jA%(F&'*閍2.r#E=6rrk=y,+gyaWbsp;^O\#g6XiƜ؇Fw_~nε)u4v*Zn9pkLDNn'W+zFu]J&gi\,112v`>9bS1uqKW8&wvA4F) 9M;" -_7Q#Nc& fl M* h^c){6iAX- L͛?-_~f:v[)f}ż]U)*&JȒrmIǡM\V2:^E˴}qU%l޳hM0qs; / +>~??ɉ#G8u|C+K\} @,u \c"i!OXJ@7ق0ؔJYRmb@Ϥm5P)TQ*"(gu#VC\#؇zDNg?8~F? Œj{4BdB5>S+SV!E+NmA{%d#Haoc (#oG>\f4-J)4VcSGߝ|9fse.>41:Tk-ϰ>g?O-L+qCKĺ&ǑGǘUo_ئS?E.~w9<#mO޾?Ok){{:FC E)ן!3A"4BJ3OX[?h4?/MoroX~woEc5y/.cKQ{nm Q,Ơ(,eY"ϲB&!, &] j'Z lBLY& 1Z]Y7AF%ZQbBW+3Pcd,/Cw|ѧ 3 kTjXLZ#(ʢ!O)C$%EjR@֡VJȭ"ika?&pioL7,:lDÌ<Һ#*uj)Z2jD.S17L/htr̕ TWiCc Z: \m s ɂ |3ecchgϞe<q8.LL$;MU /nIΑiEASZh *M y@MpZ&H=s(<C47K۶ǿgqJ)eH>`D"i=_/[j'6Y%xz~%]ц}\3'v=k\5᠚X(vԏǏ+ֲR8 ^zC>sk/=LOp",-.Wo.rg2ewZM;x6#Fa AHe,.-rg{[Y YY9۷1y.7^^eq`ZTi?qivPs0rk{[; |Ddž{l [6uEL@kB7Q^@$~ᔝd±ut/=41Zyӵ]t@` +!֠Ue2I8n7  Aj!MꌉcPCb(,M1F:jd}l65Gv yf<=`ҸdUwwGHPnP%ǩ:A}̚._OkֆBېTcҚXVW%YkM*e^GuEnb-`64+Ίj;9>FlQ9dT y/sY8Azܦ]1t=z&5ď|'G>ƙw0?+?O/|gӄ;%7]Eeaem ̷+b@]6JarC .~J1VLSr _P]WǸ;CP/RM͐(;XQ>g>M.k/K{>J4(m9b}Z?h4_WS/wgxPx9Bu"eK6)EY2=DR,H1b>\Ťq1VX \&uMHbHzj! 㪊,enc PcyZ+Lclba뽧g]͔!1( hL9|dݝDQb"2z!h*Nn]f^C #f(AuHRZC|r2F>?RFPo=̡H1;wMK3]>Z4{iѐ79s"= =Wk:b7A͜ZẋfŐ-"sR.DŽf(TjJzeR 0%kMC]#k֐\r^'>hc~Id.ɣA |&ts˲1kqAE阁RFETD8ZQ+ r l{ok߭nB vjI 6SxY򁦮)a"Kl i%;6-u#2N8I@yɕU˂ͥlMoֱSe~㷿Ļ>s<Ȁ7 ~Ͼs + xha嵲Ϧsv^L4&E@!B B^L*GQZ*נgwWk|EX:=p[X6Z&g?s|TN+b 6Ӡ%.Li IhkWMdt "x5Zx 5TOlhZT[nѥ/\3.߸2L/v|kKf:dQ߳3=b|_$r-Q4%dT`u'H^)O(Y.KUj\l1\!bd"fBUSMbB, ͡f'QKA !Cאd`ly<[;GVLGB2j%b|Tñes !`UK#zJ5&J5 <Ѷ>wvw 8k [`<t 1xػo3w60YWlB+64 OyGaKS[swy[v(FkfugYCC+5E"<ˣ}eCCsmBֳrSC2SzfX$/W6ߩ(%976㠎!&L a?O~?F#ڇƹ +_Z8(r[xQ^KFJt!3X&Eɴ4!p0CT4I( C+PLQO:f`0I9eݱVrOI|ZBD%BYBt%\jkZCm )BͩJ 7tz֢x!FC4 14ԪsdsH4%1ʞ`! $d>gY0p3 Wn_sՙdZ\c{}&wRC9T^bSF$u}[tOݻؒ}u˾t̙ gpDRLQR$l1 @ނ?{%A'A`Ų-3IQ8HJΙ9O}֗o>}e E}ZUwovI_aqaB Nhp9> Zmn: ZX 熖s7ktH:hg>3|r_{5ז!/]n\͛lztCYB&8$E Ȑ* Z`O$r2%Oc34DsqQwel, 'ݻ8z?yQ,CEԁ3n+kB~hg?x'ZqcY<^q=zȷ<[B/x7ynuÕ><\Ywczzc iՔvz{w9tʈ}]UھPW-j$J衇z"wq:ǝ;1I,BIG=FmuMY *[*5Ri!vFWMAI^S"}T+QyOSW(yFBlaJcLQ"@c;o4-634ŪQdĹ ZѺ׶rv6ԉRaZ5lRGF+FT;R cl,(фbh*v)`!ik@ |mV&L:NPFϋr2CP>.++6eFaFuC\uݧۣSDΈcX$3*QX !ϣPbD)u#d؈uӧERU.|5Az}-^ƿm7n9`cI{oy {[??y⩏_/aۼ]ٿs3=v{BXzO{Ɍg+o5#rGOkN_9`ewº+=>GW90춴^! Txj` Q"Xgc0LRw1gA٨@U~\;$'7e+ʫvϲϱzZO WYg; G ahۖmiG“sv.dB7ŀ5okjlb$AY4ka3.ow;{Q;UTV0uiHH.M*2^YFH>ot$BȄirBe=k;@ 1S2'G8!9cu5f\{.~i}2sVvF\rZLRGkP4Ieْ%)g(a[,tbD *d#-AL*3s,[o+NS,W`<~4|Oc3t#$nsK OP[W 2b%Fo#ˀKhNbqa Cf'r9oYLǃ>^)yk uӲl*=a$]O4g1I H2lMTyR$Ia%ȍ||c4׮c\i.P4my]ML{}|a>|{o-xنGb2ܼ'ܺWa+jWnâiJ s8 :Cf!ڦZf=N&G/w~oNJa[)v4``SRkL;3=^}M^yr2ݱ;*sxazGpWS-X.V,|ˮ߽Cl;ܢ) (о Ű;OQ:)rmF>λ31Zׇ)0%s_nPg,/-|`.7t^h cKa>7t]1Yrb\0bQ'>zIBenK70rޔui8;Ӽ 5o{S{;m^QU[EQ}$g2˰ms~$ H))F^9JR>pSKF 3KcI3.vB|kU/EdԅE6IJcEV"N06HhLM\#!LS\l7Kabtv dILv EqX'D#X:ʂ0'$O<8O0bpb18|'ݟ!;?yPZ˾޲oYK[-i,kg>1'2\ZM%(*,7)Qe1Ufz/}ݺ_%6S Wa8_]:^&7rzr__7_~wy|6|䑏7CVsζjlNOThTrX'\=8cFteڰh k g'UM JA@>"%e˺j8wF & }1NFDHgssa()NQGfB5st -0[Rj_JĹmGFcGS5YTVmXil"DDah=0+u^VىAVM~#Ϝ3@&RFhl4y}ץ8Vhh1R%C~ЂxHME)6Rh񍭨E}Q@4z8fC ^P59Ø7Ch`4H A"HT:bfawT^=Gۄ$mãCnhӘݯO~W^a7\u ftjQzR5S5:՗WkDZ+<<|{'u"1 0@Ht)s4S ' %<~wx?嗾˫C i+re#(~ ffHi&#2^QQ !,V!`!|ԏՙKș<~s'Ⱦی{({?Q듳S~OclZ?؋quėAfAWn0Q)nC.\E}2(Ԥ8$@"$c3niypNbTuEu]u;vW\U/7h!IJ=\#"xC[2!306,٢%CKd^#mqVO;9Y4[?2kIYHũHfџxǜ fX< 5i ±Z/cRM6>?,hO0/C2QkDXڧLg5z!zr@2`rMcMZB-ڲ*U$"ݱFHLK6,Vk:Vׯqc\p.Gh@MH7yut")-.T%6 Р=O9Cz8 #%h*]#2cP$OZ6LNG:焔Q@cȐpb!"d* WW4źYԫfbWUu&6܀%w ъ-^4l69hfJvB8sb,*-R.ŏfWPWi\ ힻnr+f3",2;+bIj6)sdJLY()17nSI1C, !jȬ`$bnj*ToJ9#+\WQ<5H "dP`/\T}E q(d6!XL1<ި!AY* uΕuU!ZOk#Dea@LsY75Mn+%= nڷ;7զr!X,=vq0@ 2$!nqXQ!XN6wr!`2ߜ92)b.&hMV7NX_?LU-rĢ}ISyg%$m%ܼ/gefp>J~![J~&lm115 !#Fe7J\.Ǝj?~W{%͛7݀ώJBΔkZ# ?s2^[i49fHbT:ߔy0Ki"T m.XV56)b6DRkѾlۖ!t2 ~ljrْ&+VrϜ_?Ivvgк`uLΎr yݶW~3c&вkHisZ)%1)g3'RJ6QytFfiz!$zcC0:`,:e)I)ŷ\zM7W9T_'?W4 !mEVs1(\jo@ c,6*̦D!V[K . (rFޫrن׮o -d FnK}p'>y^7wY})~hm dmCJ}X1FbF=]oI8[`bu[DCD}ښG9m=~GV jg!o0&dMlݳ;XICԇ7؋W2D!jѰ2gu|Ѝ;όD6fWzzI xA%%K !(Å x%٣F5"s;BS]$΋}7 9 C`@SjaqBh|¢ƖFH8=-Ub`Z.ZV%]6ZϩXw,(t$"Q׭Z)fuEqh*'ǭ̠N^qb0eAd5Tɔ}0d2z" +أŋf*z31dBġE̠gG=H#Xe,%쌐a$/=!%l9#==:!Fa26e18"6,f^u r˃]mw00t=閮=H1hQqPDeޱJ%h9T$%YZgAL1'x8{׌$Dڋ 0>~:_g3eY=)ϱ> ׁ$G]q)Y\qMj0KrFU y9j#XtJNubg}ieWR{`y7atHM;=ʛosO}gxו K*~l8!tU`36p'5 sg;z">3hmz@E"MSW{opI)$i:3M"]tqq̈́{eWocA/ . 𕡭yGc'yKToӤו=Ό3*XW2O h7-y!%a -/Ś6g^p:ݖbIם0=~QN߼5`oȐ4J[Ð% 6r~ Ys/[;oslI/ WkJ1*s)}*ĨcIߗ:H1; (a7Eͧ}PC@$IfgJaSRpu(:K3AJdQHЪe\:XѮ, leU"E!ؐ ŤVh27R4ɚkGšd#v\"Yv|L/=e!ה"c(;QC@.X 3ѨfIs0#Kcqj' $ t}ԓDv^ʩjM{ M% J11 $Zsh-ɧr5 %]lw=tat6y]4I8^df⃪]R5갡n=ݎ3v fKu }O? AI溦ܝژLd` 8HcN Se62Or`I? iƸ5tLojMv˜wLR';<粢"m53E٧"1DK٘VCvHCK ŴXkV]ev4ZbTHů|g-mKPSF?=딸q!Vkׄˑ{hfE2 |UkLVMroƾLeڪ& \fjV*C9{^Y']߳h Nk߆7ӣ5g%PS)蓓ؙ\I "1RvBxB@H$2˓dWAF)}]F@N!FWE=݃yk׮Ѷ >޻n0|#%|ptM'WNnk\/v?LO#0FPElk">*5fF2vV{ڌ?&??¿擟4O\CLFpI%} ^L53Fu/ +de<૗eg P&Md9:̳ͨNvܗN}3 }?ώΉ_xƇ"3ϜUU?|;fN8e@Ԯ&e~N{+O D!i/#~WYM?w\X#޾o_|e\S.D񚚏P孛ӟ G~Սs`uP$h4:?2P {_xs:h TnA8!Mt'y>oǿgo}@ˢ0r>EAVC*kQ.-GrwΨW_?mHr;u qS;٩%ķAݝFd҈,H)yr!5M &{~/EΏ81f|Ģg ̖/b9Zj1EBp) Mb&!F5ng=GFVNϘ;yiZ睑A=\Sοs1/W•J臱oPQvHvNY(%);g[D8ZOnX,<\qptph[ xfV `s 6yF3Sy_F"j-V]Q1&U>4&3s,w#khAgggzϫCeHpC"v9нզ%2ulI$*zA7 lzR%#?74iX661줣jc>s  bĄQ0>ٻbɲZ1lBe{vG1bq:c^VyzIS7˅ofDt99㹯} u]QUnik|U1WsN'{ՙ># _̻m03~T)g/ V)햞Gw# `øOCԦÅ/d}_˗t696/Rb5/Q_x*?ν/}c+ /]O3yeܹZW X[a|@Oncr]8c}ٶ>);e>x׮0>Ղ!7;Ci1Xl UD2*U4/r% +#8coQV0x1}Qc,yؤTI[,/3Q_ uه]}N 0'.U/. pkc5#o EnD1D bI:>N! #!Ȥ _(rȴ9ZW"Y N(y#Pc)B+;h[C[Yju#ZJG"!0 ̒ PG1&ثs˺b 쇠LuL_`eYNe["iseG(YRPhvbgɴiDCckR3@ vOU|"&X_Q5ъGWYX9zbL"L;= z)J) kTUفK2>8uR$f\!)N&K #Z$a.w8[eU E%)'DX!:zaC}|»cviO}fEӓ0K AZ!A,͢UYn{r#ǚes&P4"d8Mp Yi&HDR%ba".+2"e aA5v轊iEѲs Jν̞ɋ^ЩC>`xk5dWW[ ]KvrG;}77n_OjOmHud<WRNU&XӓJ? 8 VVx`$q* lBS :6Kpo}9 %!X4l~בw_D|WI~772W8IHT pxJwbv;:V~Q .ı_)3䎯 R81Ll ɐϰe*ԍ{ޫr]&3s f:HjghfIG_ŁqC T=S2*st5Z JU}oYK(<alvysA'Y-uxAYsJG]S^Z2c ^pF0&ߎ{ؼŐٜ3n^*PCQ 4S` )O`%ddmb{v~OYc}VGkVK%u[sp^ִf&L@2aPQł(4JS{͙>F1Z0E4[n"]v[Ċ%dyf5_8hop}}'=zMb:v~3B:޾{.l1]!Jd?h LB K5@UڇNa0ĐFBȍc5] 6 9r6,Gt=I&uR AH!Y'u,k`zwR0O|H2=ʇzRYSL٦ASo;̄()wXk3s4/+~>(Y_/s憺_|]azNN9s]VmpD QZa)E}-2^{fs\] h7D,U^!*Gg:WleN) IDAT8{$$橯+|V3EӰZ.k\UkG]9>أG= oo!'9F~Ǟ 83M9SO?wgQ!y4L#7gC0.(/z>9eD(-] D1BSPC6 p=9vQ]?v!o_f< S'sOB&#@CxЬ G;qehtnđ9tEqye$&؅`Iƍb @exL@Tb[nH"1P$f?ufu baeeV2!oQ#y<@\^R󏇜]1d=%` Omp\HS+>cZP9o:E>y9R=N03~QQ0clj\b3pq?k?nݞK/$5USSfrt 8eM6Tu<׽or=܂nhV $0SkqK}ьܬQXh 6R&Eýc*jRfh5C{i[B,Kb:WXS҄1cD! 1D!*׬QRr7y48FCP` \hW:Gvv6 m2>&$jGb@MP.TP抻˶b̥lGO$V?JuwZ5 c:ތI\Qv+Ŝ(*00` Ν;E1]? u}?L苀EJ n;GKBWLc$9ݷ>؟ /267d|#lqosA(;=QZ`^M4`x--\1tm$*ךdip,jmMsj{ Cbjl:޺}a6! !O-o۷C#Wz>gUaC^y4Bi1ӎ,߻eZMpzcpZ^$QQ+X9!h E#p.}&ˍG=<~_~Qݿ]N[A sXnagd D0DuJ) * emF$1H 'a8A?h 5j31 ٚ O)S &UBX#zPţ"!ҥ=c-3V`sܴ0Dv ~7q,@b0 癞b.+!"#7h^}l#Y$̌7OnE0(ɔM+YwGGєk,ǻ8Ku<a?v?sRb؂ݝ-g錷y++7$ Ivc:E|G83>Orp)Ns=n~ZǹKԌ('sy./?̜{Nv>'y]H䋈FdپId#e6rqq!.דg03UǧctH=ŝ۳ &:8|`R7yǨ( `qY )o{?LK BX =C?̞luP l6]*FRW*Gj_W^|gOiENTY SO=ŗ%nߺE8hCdQ҇#`o7l-S S>}+Hh nYc\\hAbopxZZ ,8_q;CD+,Ը/1@%ESX4PP@m "l`=+ 7-]j7ꪔ2 vhKR dgՂv,UUqjPH 9jmL"$%A3$C$ENʐh:AcOC.y9?Q|,g\x3{ 8ދe4Z͹ONhو~xC\0'yn}O2SQ:hmH?R ia׾K30/gɗ=RJ|>GOiRH`%_6.:-ynܸ1e:9Rr+"k}X}gJo m Y9Z@dl3$p|wOm6&wx7ׯ (Ή-#NF۴'cyȍQ~߿7[nxe\Ƹ?~Rt7xMg9  h$¾&70yg -rC~2 ˆFq/RwUc;aTk LXhg֙  6LZ퉌; H./:7SpsS2g$ Cdq'at0EP|k m[c1lw cׅ{9/jK\}߿O^"o7c/$/f.Uy.P:Ώ]2$x4KϝhY\mێHiӨ~3;L6csasouG,+Nv=5w^y8D{Qkn$"܊|)~鏳ٞW7^{n:%\ڝzgN3Hư\,Y;+)IXd(ey\,8`*Oh0mt+g#lA E 6rB*1E\BҬ5E-E{H De).i."Beh(2饤1$evdJD8BJ2z$ c;BD >rV #5$qau}c텟Qoϲ{-Ir}֭Gw11s>DIB;iVZq?čF" CQH z {xdU] κpp7Ϟi=zMUw"4ܻeVk ;ׅ&fZjט09Жo0F,+=R3-^E}Y&3_kk?(gάvY; hBqmmk{{xgw^LA'0֐pN 09*`&U2K$nPN<9@㧮 Nw^;eYAp6 !j{sb- p) JdU.I>:9i'fj1GAI I Am8s8xM&h6 ;#13&U4#ሏ9 fA]԰!!b 0SbF|1dtm`hmpbkeE-RP‰FƖ*Pϵv|д$Δ96)b%`MIsbܿz O?3|pw LDo&?iͺVfX4?;[]{d'8No>/>‡/>< y+?c|{SG?XO'Ɋ~\}1'Z"none`ybbW{%O>^Bp[; aY,8"N$^D;(JN%/B3S(fւ|y(e$ByRK:b:R$l 'Du81椾%\8DM0$3wZ$9ӊQ ƾ⥥[ͫ{tMc@0'x o=sp>1܍oE5f.g{aML0$V=-ȟ bi|\ .Œ>yʘY"b2St"77*MXa1k-/\SiFHZ j~yl0ZRJ5j>yހңh_FڔU{HQvDl&0!"eIBPrˇ/"FhM'_~ )~_[Ϟ>/0_yN<?WOg_t:b'NKJIG~XӪNxdv|g I4_~^+gIx2 8Ow7x)߉'{vo|#7'Oo1 qNge'KΠH-n['1/pW6OEH%+'aƲD2>>{F̈hxBZ5ꊘ Yղ,$VG"YCʒ ;\@NZ/@r b L(.0A Y.u'G?Fjd7>a£QZZYm.`SdW7 k'{4W?V1}zhDnDX$"T0M/ ZV1$^Z=7Z) &AAKnwN~4]sikv(t#@-3޾nYr ׬%ydHZw@!8^A@)Reh~HzJs1ft,ŪB3fZıм, m2PS)wXa7՜d_ `V4Yf)g̓8(s9 8 D y pI%޳u&[ 3}vS_s{Gݟt/^//u/K`B4HKB +nn$0ᴮ%۲MH{lSDJ#=%dvZ/> a.y5EVIkZ^x{|NsQ0~ÌgoH ?7$m~/ⓔNnC_TY&l ,=Ϋ[~\mhO~/_}j@b>Lɶ$S(O-cÏ]sx6GGH`@uP_'5Pb$g^g!Z0HqZ!e@ƣQж%kbZ `#@H$5)kxU$#M*N A* Frȹš=akTq#A Z+oJWƀeB$vf }9@TL?N!R;fM֏M~ 0u+7@ 4}iF|2VꆸC裏pww!"s -B{JԽtFݚNHX2 -c|{o~W/[?OH!$z7u9!ЌeY )ɓ')' O/?ÿW?/?|{5gQ 4|mh/rJAYLa| Dsu\%'ccy 8H BC_7HAk<{7 @9jhi VUɠp{sGS 8<}Ó[<O!9CD<pwx~_V‰OR I+X2maYđu9(Yլrv\O8!g’D](y1G5"T7?x[HB#( M#__L s3#0Ff QSA2 @)bfa1_d[M])'йJhLz 0)W.Pf$6/Kp7Z\>%wlp۪B%-,j@aS8j-Nk$9Su[4-3JZO@JG@! DN ^e̝-8a䯁YPўe3HCl ̌WD 9(Ɔ0vJ̄ͳ@dbvSEQUJl=j@.* C~{&ݛUfTiNԿ}񚗜$kJ }>Cbi!Mƒ NGtzvIMG%5L1_w3~N/GOZ! ŋ3xċ0Eg~OhOէ9A4' vG˿+'wg?3z SQda3N8Gp&%(4LnZ4jo㣏?/2 ĄT9qTskZL "9"8!Ϟ>̌wO:W%xL5焔3N#"."9c#V/.٘(]n*d4,p{;nb1D<9z1&iB>1u"iUb{F P &Hj:L!JjVN9HFcPSAɈ%^zAަi{%t#7g^C&[` fW#=wwߎ㊅W  2p%ݳ,!&! < Qf0F=G UJ1r嶱?4a_%Ps{f$ Po%i \&PHJ38 F FZ3юA2IP.YИFV^Ub%в.ns]&5I$"HtA܄ sC,I h\- þsÃf s$ 6D8Y.69 ;e$I@Igxxrs 0IHpSӄfPpH$ 91 IDATAkQP]41oV)O'{#N7Xӊ [ ϟ!/?WEY˲s/1I^?&>z %?W>_ŏD5<XWI(~DΗU,ےX`f7?ğɿ«W'"TfQhQ+f%t|(( ηC?x;|4իWXSƒ&|٧O~0ds[y85`$+p;SŸ'/Y(|;}p;Ï>ӧOa0f`d,|<88fL77|Xp&`(fk~)>Y[Z P`5\%~M8qOAr6TəU<.W /E6X{Q PF]*8рKn\;~i.,~o\Z&A$=H< J%77@!Ѹ41U!&ʈ*U gB"?KiX`0y "̌JQhD\^rNFsVQߣ9QI{%iY}mFy_e#aa@jRinp'PBN_It{P7[C#G 9s%;|.ǯ^-9`9ex( ֕?.;`#no}C<“Äwwͯ f=| . η죏0ϳ0q«O?/S{<{!iF!DO?ݿO>$`J$hcme 1FpX{?'?+M1 f4A(~ohߗe0i8Vͅ. n7kRDwxy^&|CH0~į|[ Q-'on$,Ä'O0&xS,Qo\5ߕ- P &(/Z7eK b^{y %,Lmd!`N5c;dl7ϊ;jcK/^̃U#.n(9@:)W Ixnc6vl{kZې?cR; <53VTel&c DY9cS5 &1;0?ϓX1iL[RRf[f`#c`s`Kk$2zfW,lg5bfM8YǬ9 $A,`gd^֒7WS|c}Tlӌ=Bi8WcKvUKG439>;op|gkQ$៨ӟO͜g$pt>iaI5g=) I+9tQD .҂5e#N'?$'(dJ?ů0Nф-(KM*풶F,()K9fƚV5QB_?d5A\M{H5cGts)\{;[y' ٖcx߾^ruJm-{N9wŗxЦ\S~mM^1{?Lx.6Ҙl.~R2 15!{B_ F^g7IFsMB۷ 6j ( C{_'t{$dM5wTP3!ĺī)'CPC:Vf Y5aga_d4a",9E戜UbIjvACϓ%ʬ~9+1·&4o',"WT`s,@f}@.+Ne-A3<$$k(61l(bA\ 5Z#et9tn5Hְ^$߶$Q5Tu$a~?e28W'D^L;#@5HihCu(6W~|GڹiD\ih# 󘬡4;k*#ξ,tv2z'_:xKd~5oMQ~kZ* q&[:Gbsn% ?se"8z`2~{~zΤ:鉱?*+V[P&Z~Lk&pTf@^sLtSm:X25  Vj5aIٙLguġ܇z~v!Hyr A'ò5YH+w$2 -޽}$˲t vy N0,9dz00KuYe܌ H&3 $5F!!Dʼ TuĴ*_ 9 YhVɽQEصCKq3zip&aRHD?ƈevA78U&J@&Aϩ9\*-dr]鄿X[hRNz[w0.e|Mb" vzz^QO]T.!)9gנoWdrs>G?ۃs~o;/eo(IZr -ʒ÷ƵH%mset#R" Ιi:`HOd'ไ58E׍n!}( \eQ?cθԬ L jt-cЙV$-qZ挔Y}Y&!蔪vu1X7DI$9rx $K~ !%9jEN]}dw~ wHӚT$3#t.( Y%?ĚV1e*AYNUoIi|*R@ < Hf5' ;;| ~ 5wWZcQ k꺦e8I4(U+ e@`RWk2g۝ط}$wxT8`nݨZO_<}#wlM{`vh› sU1&l3CS?zf̎-jxi&yvNva[~24ѐTu2r9CT i=e}s#-Kķ0IhN NڟK&Z9cav;#򃈙٪`lp=`V 9mv(OyPBdFuBS5y$9J)B($`Ɍ`YP \ڷ6ܚvo>jWgS Tu:@/ͭ"uT@Pl5@)f=oeidqmI.q˜ b xpAU5++?1 (oCtfj\=p+h ݼgz`WwCOmޱ! >]A\X{ԼY{Fj3C=Hi:6ltA ?-/Nӷx 6V CwKqIWyI xQe3H0A@Z9Y7?٢kyM Ⱑ:9{_Yx5<҃;>!~$+(ЈVa!*HM.'jsYmL N故Ce (,%p'^3ce,HW7fkUbAFpX”9DB593^A1⸬X~Us4fhZn`\wFseAHʷ H/?6_gzPŒfPdHPͬ02PQ0nW@" Gf9^@t`K:F2q *M%$7lcUSQ|fԙ2nfo~?18 SۓkxHڊۥaP$Mvs RVǘqsQStnX~JJ$cI$FMf%✣[^1Da TGpbBV eHce&xazѶ]:viwa1eZh2MNϻi<\ZSA"I!:JP^{T@7C64`j{c>;_zZK7wt7ۼky?sN2k;0* 5+*6dkFS-zޝ5aKԝdnʛp%$rdkb0g݆yn=pe$"Ş:a/,nvbiib+N' }JQ`gT$aM˂@"^%T1O7e'W1؍둅7_%,71Q0I<+Nӣۚ.Ir Ps*Zaʶݾ&[˘6mom$ b~$576H\3j3^ qwVSKˬnZ6z^/ ZcH6߭dDV/afNWeL7 iU梾/p6|wJaf?k@IB;yn/iھJLw3b,>>CW;>in^Lk^y*0S'߃ՂWٓ2sll`e:K~$̼Zג`,ТR2͈@dak'Ȱd.n DϠWKv}n*-}gL;vi BIIxu\nqHahHHMcѵc|K}uܾB2@.iWJsM*)PYI.Ѡƈ_xL5)j60*`L$(ZP5*$WowWƀ<ܞFwS 1\|FC ؅/iu@BżSKKRN{: ]c.V©7zb`k,BO>3|Φ,=h乿P rk 4o3٪^~gt.8Ǘ= b`a9׌(~ٸV 2(E(N89'm\P9 $CuqF4g@s00gPwKgccsӞ(Eď6JfwTK(;{҆A?7k>_t9- kOko@BJuXe7{T6}fVO%A!P#90w:8ZWKj~SdT;2M1PiE r-RMI!JC.Y.8 5{G$eNFDrI^sgX& +άc@;8ȩn^ҹr{/PݼY8.W^0Η2ucmNЂ)* !*pPK$_vE&W'5o#;̎*1)sRFb*{@R9 H|k@RA2nsZ$-Q@{!)c4=([o3gg<*S9+bPLYq@] j̲t(2/Ɉ׶ 6A70s&1OgclZc\(hR,`{QUF!B&3A,Ĭ XO?˞9XA3*rOb>3d3[u@$Ѣn\ ]ƅc$ij~J+Żӏסĭ;JcF/Zf_ε /Y~ AD0ת!104%ak9_s > )?Iㆸ~3ݘ{DP;Plc@Hx2mpɮPx];Ffڏ"4# 4#Ĩ DͯLCb`#o(u^JRsZDKܦ@?C \$vT!L=73p\ !ғw D \򐁸ZhVq޳ڐA?lGXTh9 @/HOEr6-c8$:q QѼ&b(W oyМfSefƚ$+C5 )$\>Trߒ2N)>  te*-Qy S'w{[sͷ&Lӄi>`O&IZ@`/,^CQ wf.ɕ/]6i׵W^. 0gq}g4l(#K/?O=%?T'9븾- _ywh|H*Ǻz/oϟCv|nYwkI~ %/Л!s'2+^C)ݦZ(%¥v?\=̰!1˹6YnN@N!o=:{%GǎɁגM>ɖ)&NBAm V~>ʵUѻŸPP4 P\KNi$T|Pq4o4hAĦ6 @ҎPu8Ooy|ﯴP- ɜ2J?#!Ȁ=zA@]@Ϩ~2w?C4͘nnp8T- 9"v_b{>q[Y RǾv÷umh:6eޢC핃` IDATfzCd/׍O>f5g"Ukpʠj[ _BN)4C]lt½@] mN3#0iFF.-  R 8!G 'Bu dEb`p^ƒVFcWHdIvtuGNȧuvd[um;]FBa2اxǹ k$Ρ%BfLq|,D5@ HI0:֧ q?h{;tn6M=')$@BޟЁ $OG}_SC {^*9o.DY32M3C H_-0'{V)oWžm=ͦXuǝ/@/L(g_\Q/'* 3~2qrۿ%ɣ {]omoFLCd[W=Õyۜ٭"DaB=Dl  hInҦƋ@Tr+dʀ "XrG(F;hUf@9c9ӛ +ݔ')gs&;df05ZEs3fƒkct|xdQ,W" 8r6hs sS9S5؂ Mom4򰽉ʃvdHN%(Z jFȁ JmoskP߳ac݃ OJ! y1S$ȉ7 <%1/@䲿4CS5'Pӭm&]9VᏛ0>o uፗy<:-jQ53^]){e76_`UriWyY ]3Cظ !#0ͰF۶<O~w pLmwi$}uw~Wuv>ϙlum6dg`DƃynMfvwl!)߃]*nʿ/ʠ{S. x " >_dy>FIUC_3#==wlf 7m&LQ}H %B&gxae)`)hRw\ܞU\%AOӛ*u3M$9}? UO3 [@zs7ߨ[w 8b ș9˳H9Y7#eRp;GdQkSǹ0 >|&N&D΢zw=6*q/Lu}c3'A, Ũ!cxmu?Xe"svȋ.,"r*!k4,r֢!#-a;-JtU}fLGa$NRB9>:ّUQApq@bFj}4߿8RN+J;Dj7:D,UQq$UR߯©>\2~1}hp HLoc;CwۃD:fihk+ 8tNXD 8[CRC0*B Ao^lYH 4 =.+ s(a [)JϖYPMM[ה UfL;WfF`FgOny 20ňit5I-*1ƐIS1#In< 7e/-rsZf `d@z? Ac޷o6\~ogO~ (N$[:TuQzD4ʈ$t3z}M hriH}d31!y c8-2/S =-XA-dlFݾSƒO_ph~ D1cv0zT$Dgs PxޚJw JӇeL^0ʻr#-8 [{bdd1c`(l) P%k1VA;oOgi3d m+o^iVd1EzuA|_bs{|ɥ:l{K \vs压CyUE'߹ ёPFX@ )Q3#)F#V< ˺Էw?O qFq-e_RI Uv׀hR9WH,IjyV(p`g@^rIhCJHF&Yͭcc;!8`}0$"RUds`U88/jMXHviHLJH;@{'a%j3c+$2Z$H4fCr{ݛ*Q}煔HS@b@ rK»H! (go_f!l9ٙ~{yLζ4G/2kRD$~>Q1 qwjg ]P\nx*yͨsXbZ{d&`K%qf$c޴ot;Y'C|b6i5_*_ͨC鞷5℔[0&LH5WS]L.ǀ}=ў%IY 9OA$$3#X )$(VݹkJa)"@` L^7VŽ))m\0'DQ3zTf U@Xf x-A1HZj>F 0~*Εm xJ/1պW純1Y'G7~ Ȧe4$TI h4$4LyGKz@BV+\i@Vw~ h T .ӁJ!8H$xP9 PLo צpļ.{w|w6ߚȴ2w=,%k"jg'059xRmuZ@Y0P}Sҏc[ `cE̓Jv1$SXusavM#e/Ǵ'L6d;KLMrx3ݦB~Lk'h$UbVTTSd WFq; _ ; !GLnM` Y!f"2WqU  ^ ` HںĀc$]kFrFEca+eLSGL 0)}ɠѪ#a*I2I(E\]Y3aO=B'zZnG"W4B@Dy,{Оo n5R7;[T5)[[f$,.ZM/i=\vw{# 4:iA"5.?cY&$`2C/%~,dj=imrF!5a5ob&}M{?gŀ6;ʁIB`>>VEx6dz9)eڊ6&ix8f_ӬQ$rV'yItۯE,H9msbH:,kRGwy;yŃ1 G+n&-liRaS7y@%v)l:箋-tWgf& CAuߊڦeS#6np`dA,B+.XLBjE# +A\$kPF hQJs H@ںg1(3&伂RBH+h (ZKu-P8(5ę3C|Wh-'׎@ {y Y.w_wdTp"T8LRVTe~ᚒZ778£Bk8 G<$&C H P\uo8IiFe9W@ԾI|WYTYAl # tcJ}hG̠2TW&iUTGn>K k. bd&,:je-f Pia\ӫ+呸* $vHp,+h>d?t{HfdLq& A.`66^W+佥}G0UP ) 1 ªBl CT1bb% D4!`|H "3q#j!Bv08kLre(sGiQ"THB%$狅vwS]_L2Ē [AA^PÁPK~%.=kQ mJIFSȺ|XZ:U DfYTSvbmu%ƈG@s΅~6=?.0%Z2i2f~iǢl]S:?t~qNJ$8yca6?sUU8 W NgS)!\%Q5*n&B}MQAH V@b fIbEVW/l6;@[މBh Hqfo3[J3=w.H&Lm)S/1ӲRZ,T㛔MU8&M9#ƈ9-+3Ukn嶐}}RΗk@Ofdeˊ)e|ijsi]q;8fl_#!%.əs6e<A)"N3wl~51(C&\S-z&%: evnnxTRhKǝ"Z #x]Pĩ ~?7© c(/_yU&IߏbuL10u`r*p3a}劒br ǹI?b$̖( $8rH;Ӕn&mdݘ3kDL`3tݿWSmN͇q5r cބC0K/||zo5ḟyI̲,+$HE@Gǒz =#}4@`6'-:zMNC3;7InBڨm U0bgg]6Wjzx/L32x!vH >V~Uo\5aߚuEi.% (GN,|>\6N{HClXRS pw@H 8#Iä3`J@@*P@X?K%2uSW Y@eGpԐm+⺻ gIcTkyMBsPg5B Q^iaYR F0N 1DRYI1v*\I3[\ +bR;OYH²* 1K3&~,ůp`7 q '1`UXMgUǍKq"Ԑ, ͬK#RnWNH<BY0YڞERXT Rwz֋]@@1&ۙvH+ pmmγWgMުMq \# )0JyX$!4ʖ$k-{D@kR8I Q 2a$!8ڠN1L¤[;@B iWqڝⷢab(au͍/V7ޏu\tW_c/Ǩޏ?Zr] Uӂ\hHW58Đanc/ gdUf_  A A4pP$N/1 hrF500ί7t=/WMί֢j%Ogʗ!H8@iSfmQ5"jģڇbhD$)geeEfqa'0VA"FK2Ɩ/o._!A ( -e/P/V ^3&@/e*9L l`i7 cw9C]eZM9zƹ0,_Ĥ,)i=\8!%$OMt~xfc=hٴ^! 0 gK@i'Sd+.Z^bnmLJRWf _Dž36$60U@ɤ$mּWKq  Gf}ç*UOf`YPs])iHP~ Y^}4a"h.* meOjw\SIPR$r%0E ?Ya:RgYm/B*.&Iq93;QzpA{2/;{u2ʠfej@N۔ Wի'(HJEvI$LF,mr^h{_΂ x аhC[3gPחE*F_Pm{YwjVYzfe-- ol7rW ^]WU/C/lq IDATDiy\97so|42)߅k&;ڶmQ6}Yãlf .쯏=0 LW g5+'J6HHY)5tYRr$d&-nq@lXjżOdA1Ss 3emGš A~VYKCdz>_Qx{ŏS$*@beZZnx *堨'a'~Q~G i@"2YpPH"P@St망:6%Beח{]=`bk1DQIb9XϗKֺEPiШffpJ1*>ZaT$]l 3x)|+5r3','M$W/JaIMơ]Y1vw&[=S9PenV,2R;Faξ6kl<@}5gmy;-UgN;z-cAg{6ꥺwW7ˑB<muX}KJ. cA|ʼn7gn"V/VJ0)tF}+%Yf/;ޜ* W93sє6d@~4l^jqPRuX{stV nR igvhPPI\ p$X&b\a1bLؙ&(Afʃ`QmS) Ft llцDK9ʇme6k\hMj>0攊jۜi*xRv")9i|⬴g$b예ޗkA goMʥgD{4yǾ|A'49*ԁh&9[Q Ԃ^WcӶZ>oamIXwQ~L(\ % p#pMc̉IYћ-cY5Ilk;Ȓ>{7mlJADԘ~ ~הKUnV2}Ȧ2 彥9Fд'Cm /ȋ$ & gRkso8H)!k&yM+}bgP_$_aWEP B3`Y)IkMRbƒ?2aofd!7ӄ%%H6J)>7 j({v^oKˏn~i1!<Ej>#FԈ!"~9@R#ȨTbJrqmwqXmն߫< ǰ9_>8y8YtGeJ.\ٌmJT A3Gi* Pxl K{~. dT)K4k*ɞl[385/FOY4 *! %ʕHc j@, 0!jbI33Rytg֤ZW vCieCA"j+5f嬌A. A2orbWff^Ba'jk:.zAum oZaW1Ƭ"2!vZaٙ1g &:rz@#tWz@H~ˊu]*R,8 m!_RvyGk=h~uX,9!DoY4%LX>:avQh,fYhքe]oBy6̗y-3*-YU@gcQ/ .1oW9Snb&^^Dͭ$OT-H9}ѻǫѳ%puwGC{mnLߗ<[lqIɱIHb8Y3.Lm.4|^ݻX^Asn4k-eche&C1dQFųmQQU)9E }LJSSB]BLі@7i!;@քu]U[ͦh0:wråQ6DV&m]w51!;Ziv+ Š ~y3|}my %gW=b|'X1Ii02z@PeG t˞[7m5# tGd V@  3RZeUjFjiކ- e$\S/n.7,Wc k;2NJ݌ 럄)gSl~skΚs,VUsFkQж-ckG[#p}Qeׇ$ЈpU'f:OB@C}Yv#-p?Zu Z6ȒtbRZ]0@l$z1d 2Xz1,N a14ǓW},ur03v߰V?(f0!yy%X-}Qt^;+=Ji;#Lſn XyidoBAg60gݖdBݝ{qdH c]atZak;5kvͅdx#q3S&L|ELW.b2^Jj<6D6E? DOV? l~[m/PЈ[ d5[i)}-AmY$yDv%$!Vm :Κic ['6'NDh+B#>z9|;{G(~&9V'rQ @8˧U[yQ(^|J-u![U\gDK`@W$@[k|JEFK@&B, i;%UJ0kDM9hXF -?cY'Iɸ)rjih~~¿NQ[iFBm#`4> f.卐L6 I<0JF$;Zwd8O_ A1_$cgeC\>6@v5pO4E2\|C v!h~ejOKxnaeۚT+ce]| 12M몋VIɷz.wBʾç s02R6V mv[SYqd!f[d-L(i Od̤wJpNd1!1 s9Õcd{OH^E?[kP?6~v~H4b H;{o؀H*Y5P<$T1}c=Խ aL@CBi(IO"ذmVgn6jz:7ψOsV]<'epwAya5ucDH -w~8rqy E[z)&wHlVk`{w߳Ю+7HNϜYصJVZևƴ7IHdlLP—HZ7w*Dnlhv0ƫj5mQ}RꪥDUO_dnu^+þK=,a+J:2e5*e[Q,Xb.0U7˲4%-k/?d^L3.L"j^LU'{]h%NM@Nc{w\MhZҶqPH7JJ&p,P. ?V!!o]aX5Ka5 ~Γܧ#]{))Ȕ=8tGcNc,@O^BXxֵۍu GwmEkKB#B *}G9{1NrMΫG5cY~;}S2#wmƐTR+`JY*Y/YS҈,W+!C߬svˡ hߍ()Ww(Vm˜xG˃ڷ=r0%!Ua)l}X$zr(Hv0)@DHWDn'&5M j}!Mj^ϫxxБ/$|Sτ &~Qt n ¾!/98XKS0E"V~ުRvabàⴰQG;, 4Z>ey<p.s]}+w<%f~ egf 6w FOP`od-0daw|uzF63 O G8Wb^&nLsBҬ| *lp<+t9Bky]AVC#ijr7e^KemO@V56+{w&*7'ukch.vЫO|cT$NQ<&"kh!'+#@ugvmq9IP'G~h:?)L mA_^N;F)8>:\+*y!i'Xt9:$aPFF V^4ZXƐ♢k A\*'(|e'l^Ytrr{IE5TB~ד[yui9P147s/ʂ"~-:+W|y ~"GpW׍;;{GG?ۈNۯ?qvPk,(y,z:[sC&Iң\& h%Ai:!!>mDk7MO ١Nxw@3<6P^6!mh< DrYwVm@HO@cєSU2geBԎ +w vUIw$QBB8cy|>D<4),=SVĪ- JþCZAij!e$Hc4 $L+enj78)cدq!weca]B9\=T~Hs_e85o@[a֊"B5&/!ZuMSuEWϵ Ák7.L_GggjGFa:WDP*-yhԝYU3| ĶԼ+QkWaE?1f`G<: 2bcv6\F Beʬ υhill%(a@C9_A%{bFsB}{Tb۾+;&犌öB$$B Qvk ˹hlu#Oh)3`{ |=ncޛ.vÐmz/qGEB" WS2w.c6Zx-=g `]cyk0뽓WTkDG=> >!qKJ@R&IQ$؋ Gk #8w;o0O\JZQ^&!I2jH쉈}0>{+є " -Vb)JZ^Du'JιRg6>>ض#liZWߎQ.gH\ q$Ɲa?|B/ $2#$檄KonZ4Ƥ~ #׃`EiC$ a^(P4㝯{8wqF6mYߏY÷U8@:˳1nJzncW=#7|ƌe 䧕l,afeodJqȫ!8 S6J&~!]Z%$hJQ tĖeAHٯÔl|ll.Я2S ٍaFD ;]߈i- qeвk o/T_($ C"HWBV/!!9SQPw>Xi 8̵{"=knnFFϠu#;})˾JŸ-dWQḦ "rvcab潱8ץ__XrQ1UeQWi;'V(rzUW 8n:6XOᄃϯȌ?emӊ5HҺ%O֪Xؐ7Y;2h ZX'] hK&%bZt [`sF~\["(>GGj HCBLt9®ˬ{B { llOk >kUkO2fc+u0o~9KkOz:o!v/ڪz}ZlR,~뉇Ng¯z±yH;! O0= D~C$aHt-g2bK^ݽ*b ײ 7/}y'\V(4^Hnۖ@DPӢʫWOW;Au=2V+m[7;<ϐXe6o=6!!v$[_&f`i p"X5 t'6W۳{ h;1(d%MGPo2ȓ qMy{^DO .Gv7+z݄~_Y`X +?)\!^)a6[]kG& Ai+hU.*$snR>f֦B/H qBNM/`eѶ,#ZS0/@^ϬKFK[m#o&gTaW,怰J2A̾GVjߪ=vo+$“g@.zAwWus̓Nu6|}/BB_$5+LnU о ![}:>%[AXECސcğ>\gWؠ&U7X(v}$\[1c:s} @YaA,Ł& rt&ef$t݆qwYalBH ĿBNBo9oRJQ+K wA|w؟{ݏe{8mH {ֿ&:wR&`]%X9qc@}xIDҙO< aIqe! %܎ݗc;=+oߛ>Sd,߻EIhgUwP=xJGyTz-h9>֏vwnµ~t+D&'X$JS/XѲ92r-wk0ox?kձ"E'm▒n{FPoz 2`aJfZ_@BV]b&jTBx&M:û=)Z_ ؉Wtmx7ɉ7N(G#xM2D~xr5kNS;u<#N'24|g`hŁ$~Y:!#XμA![pdMHHy&EӍ!9K(Nr\òpXPZ TDD5!;x1Ӈky2" H` O UU}Za7j2$Aۙ }BJ2D\L5k2|? JV1H)*(7([[$I&iQ]q[>iRةHntE4rlܲUI y6{M8T[@\˙HPlOiӍH(_ o]Dڹ'J F=fBVVg,, 2ԓ4{Oz67{z#3 ̰J+BEܵ87!L]i! C-͝ЧJ%WS&neA`*K)4?=:Cyo#+w?`{<^>Sa+;/l!\#`o^YWx@ۮ3Ԃ/Ϲg5 1 3Nlۇq5kdBJ\⌫ bVJɤ@D":4aTҧ љN (+;|u91(~&7mC#2RS4?늪K1/aNם)u q籠QOBWq6GRxzLI߂}!: 9Dحu"g@8/W%2Ne'F{JTDS\Ֆ޹[؃bʪ\ZGF -_&Ja =sFFˣS'!!A;ivVVfqܝnV-ZG< 4;xp s7O-2מB ؝-&Ɣ@=qDK|}3=+}7A hp=5ܤ:atq< cHĸ>=?W]}K5;`qk !!@F$V7h͗ u >ld'_Y}I\RE ^2—]TCKCO1{LY>_+S P!&%ܾʻ х ]ݎ["<Dx ɇeG}B؀G98B#ȮasVC-U[EI׭0y˔ #!9W"c~ 2TdRI-D^^ҼBŖh52V&A}'' X>\^zO"OD BjW7@ @qQ@aR/`]QJɥu+T$j$' _+iv>. ȺnmXr7˔J&ALj ūSEY4\b>K23yݝVO~ٚ+yYw^tgt%eߧĤ"%@CCb#!4,k*UޖR ]*M[ vpR UGFLz̠@ Ʈf,?B!lF\}kVJ@Bj51ku UۛYLO&);n|$ǟ DKx(Q(N@&Mb. x'xS=_$,@$6&{|~ UHIdqN}Pd qDIH QC]"2x_}1X>D|25uCRN%IK )3zջ7xH 6A۳a![,d𨵆 SɬMty!w ¹z2qY.C"t؋" y?ЈMqj~2k6B<&- 2 ;"ݖc[P'%XȄ` $@u#$`=?a /8 :,5/^JaSv%%#&.&DӒ}FvBHCo5pdd$$mE*jLxf N'g8e?@Fy^0wE#yq*HHTUǫҪޑ!')Jlɔ!T04ASON^=GPz2yxh+vǖ^/`1a#Ru0dg+$1 pW7d&" vњ,2X{=BB8|_QvoutL(9WH\QL`Z`+nn3; CA,4a{E&ߟc>~M0**b]TIU跋ܗ㣹g Q PhX?F3R>! jgx `S2UˆCBR'(41NaR?2H$$J~vޑj$xqj28##f46?!і&%8);»+l.CT+ R_Lk;qLŝ'@?@u}cJ_.KYX"L{Hj=x<:o^ qeNg^3̮[y>J^+}jRJ"tO%Y,y5^*JXB=%dEBR!.aSc_>+A+'%m‚h6rVLy69!,ZK"2Ib%j#ģB{z. ȕA7MW$J+Dq,"c}[_['$$ap\"vlr0;W Խ.=o=pKe vD LgA{2#'N/R "iRAh {{rT1XU+J&.u{mQ'{D [hd{ u8kcMY]6/`sd+6+&dR>=HxMzJW)]{xour:%jNEؘ( HXO{?$MnĕZ`NsJLU05ŻFRI"#x0|ڄs6@. }FH\}"!A@s2 ̈́tU'O,DlEHzx"#P-~,#_ʼnc/NZB3R^8@<-a;bXǣ  % (I겯JQ `"tDZ!Q_)n 'v݃1K=ލDy}|SIz3iPb!p<$~~K A&z~u:'tʼ'sqp*gp/]TyEZh >:2q^mkZ !0-D#!Gv^,kL M?GK 1/8"' Ny{׈}qa*A9VYW\JswQ*ݶ}痸t>QbU7є녗Ȁe[> ξH#|@|̎Z#q@4ìR!l% 0#! @^4'Bevۇ¬1dIL>%$v6BÔ(KbƟ 3 sBvVqVJ5&)p10?94#$! )O%ؐ?hAlhHkDd?#$U'ʫGnAH}놚q^]02b=evb)9q?p''Q~D_.{3 +иd)m'#~/U41+[OH*Ty7xO­ aD_0΢iSF! ˎnb"Yh ӐiG /S D"29q4 ϧ_jpFX]## S~U't! :)5 Hprcy쁋/g4*;"J(lJ+OBrL? h0H^1I;h~Lו@Ʌ PH UF^)=$TyDd9oC\1>LL+~ZNJBx t \O 'C7ouRoy{2 sAؤ'1v hB@ ג‚T9З;Xr}SY'bl7ɱ`5PKJo v&$7p# _-1D+xG:I6a e[Y F0m.q7S>&v唝zq3DbBC杄^HOPf;qDBAz I{[% =ܾ*G)lFrڵDP~aP~G獘]$1~W +}v J/ LG&L[ryWׄr@T .lI5^x%#Ǐƙ7e7aP2>!$,\%8~  .TpդpZDa=9 "9(Cm\ zL=I$} maN=]evE.>vO@$J9_HBB;ϑHQ/" ɱ*q_f$GY?ݧXXcnPݱ]<%mgx"B_O2$'>'%dEψϭФ(RB"#=!ч>݀R`6od #pkۍ;՝uLHdz eS/; i 'WC5zn/|.HP79w?趵=JU=#S,6|,Ϝν|mu#ޑOBl\~ $?YsZXxO"^6ɩ/ Lɱmd>qYRzR;·y+=%.!/O!$pa^\AYb!y=)\lUc$s]8mD=kBGFTݍY$vCr/8#'UϾ-,b۷م% ҫ7"iziC˳\e \W3IקE@ܽgCQٳNOH@Q$e'ke.`Z0녔 k@Gzw3J|=?)Pg,8$}=WĕWl3rH͈WOHdD^Pʖ$>LɉqcHNˉ6 zA˸HA9̴-)õDMj"[Hwb,{w|5l맓7^ߗ^}+T:vȢ^ *PySd.DK4.Sc˜TkJJ`4IW?ŚqRØ.^ONv0~LOHv.#H.X4nb5rL_6E:q=[:>=J|ۓڣ0+f& -GSǟW?]aWº'Э? IDATH )AʊHm# CZ IlϦ !~Ǡ9, ^ARsY}zOY53״"$e6_Vf̶|=$H]3`+aJN܏N{s,- I90/m{O9=,Lj/ $ I$_'%3]#jx}:x=B≙$YYpxb(&L{1ݱe,mDN~AIPg$ H" ƛ#zBX`4 4ԇ܅XgʤDYNDׯlAIDÞXyD< GjY8öUhPȮQ!W B"}'+Ww3aH3r EDIo{> 0eu\&#Cڿ tEsA׃緀2}؝).Ҋȡ>,en Yecjm(k7= !L!Y BR/`^1[FW4<Sb& !ҕ @/HZɉ`qH#ghXe)n+SPH9 ^D pwiVʛ'*0/ Rij i_dF9I=8yBY+SBrRN Xe/“IRċy ʎ( !Hl" 9%!z9wx te? z-xN=n,N5$$x3~$*yo0u-eB~++TmNrN3~Ȉ*!y$/ϼ#5NfثI]er@[@B,mZWg:9 x.ޓ+f w߅O~zOc"'k!Owp 陙\.KD"zHXm emm!֤6`%$M%j+TLTNd߁f;P[OF`BN~ ѰF;O~bz?ҵ#,r?dˬw!ȸZz&F+%7w꠲M~S=&OC DDJ/|%{^BJt ~JlnTd*.g{poBO$MuZɃ0N&̲Lq5eSKL;,ؙH>yI~3*@e ƒ$?YA& 2ϣY.~ox%eGῤ 1[ahM9X$$p|1_zFZ~yI¬n⁑1mFDhyO43wo$'a/$5ʨ :=(EaIC7'#֗ʀ/&S* ZAEd8>͒:w(ErW=KA=x1WlVD"8o# xJ(ͺ RҲnZ{Q~aK_ Z qq|1, 3/9#$ͯW {<{̷DHBH$AV)!LHXTHJgAz2N}+W 4T6Ƕ)aۿ6 ] NC.#j'[߁mM$FD"xFõF"aEyA %W~\qOR5im!yBfO֚HUW"D@W iLgOI$߂$$D",AbE) 6I k,q~mNL3Ҹ䡒4ho"HBH$/e^%xB!ڄh`rr9Uf=r2D"HBH$SPcHo.f> -D]papXD";$H$^~87Co ʵ},.8D=? D"H̑$H$^M#]vXP倡WI3u㟠g2zd#'AD"rA 71^6pԪDI tٓCe"H$^$$DC.`^7"0d=-dW @2, vPJAP @#hm ep w(x ` X  !:$ )B.d P(P 톊2_se4 =&9o#$̂aO8©p6+ _o0~ /"!"LDCX#⃄!1َ"H҆ =#PCYP(6*UFDuQP4-E[!Xt]nBwGw Ęc0LsӎLaX4VkFbӱ*)EvG)q.0zq#2^9|#?_&P kB!PIh#\%LDяOI$&^'N?h$#)AG:ADzHzC&5v0r:y|^./.!V#)6"S))ٔ Yʼ8^\CQ~ɱs梭ˢgbcbfccU;WǿNpKKXJI<ԞKH>ǥq6oLzQ;'OğT<{|3Ig=bO#O+fgggϹ}˔R}׿\Y~{w7'ޚ[]|.R{'?> | 8 /_&VWVD. r \@"D. r \@" |w#(D TU%'#t=dpPLTE̙(((%%%aaa$$$+++iiiggg``` uuuKKKHHHAAAEEEٿLLL___bbb333TTTvvv///111 ^^^dddeeerrrJJJsssMMMttt틋ʭ GGG???WWW555@@@zzz򄄄999kkk---222{{{ ׷...񂂂===&&&,,,\\\湹VVVmmmllloooppp:::QQQhhhUUU;;;𕕕XXX666 IIIBBBFFF444  ***ϽԲOOOPPPNNNѥ)))CCCxxxYYYDDD000P zTXtauthorx P+- IDATx흋_U;-ZXvU5gbC|PB "+]PVe/ǿܹ3e3|&p]ν읝g *ɢ))83X64:xSr,FdSR줡Ro7aH8(J+}{#{cL8.YNw*\ܶإ1=cgaȓ]a>FIDSFY9+mVNEFbyE^W(K6G)ys5֮ׄXZGMMf 2xn`9m񚏑y@ vf$iQlF3=_33#2BF!#dP!#d2BF(d Ũ&*a KlaѰrt-Ko+q\#+{[kYN{'b~(=lv0b8y @VsKu!~3~f0eRF}IF]** gρd 3QU5 r-:0zj=Mɣp8C^pͷ`mv"1&Z'U>&q%:#;B{ð;Q^O=lUxOEňT}~PND}?ͣzUfed}/Nأ'ǟOىTߏA4K$HA=ŭYz9 C\;1qQ]=L(:EE/J;1(ΗZCPkD}^grO|p}bDb#ᤃ [Xby?2BF!#dBF!#dfGBFB6=)kA*XNNL._ Ib;Fͣ٪t\v\hs}3 0o^`:ͣbUyM}UGGIt)O\orc·9cԮƪл_ߪ`3._ڥNG>BOLy"k~~yd<\CF2BFQFy)"CQ|; BP(jfP3;#U)|>9d0iE>]9U LY:o MDO,]7Z;[Nr>tcjQF&5|2ep2ΙDKܦ>t7-&MG^MjUbd,1v<"4m)Kg;=wyjE0 iKS04!#k(VK/ZtIENDB`libqxt-0.6.2/doc/src/images/qxtheaderview.png000066400000000000000000000051301215241066400212110ustar00rootroot00000000000000PNG  IHDRUbof IDATxOhY7HTjAJ+Xt[=iv+Z!vO{Sr^8nzBǰe aȤhN&3oF3FA OOo~of4bأG§OQvk  /?@x rIS@Ȟ2X_O~ysy`=sg2{N $I½ܥVM 78Kg-ש|E*;+z^r;{\)FCɡhT :]qXflzo-B?|zhof+U#z&iDbL-=,ERAy@7/9`ͱ\Ҳ('/ʌ(ӈ46~\*9DEjfX#AMYesSOVE˳s5Y2X8|z>ܶ7Xk&"%GbqcʝfS "e9T}^x8YժсW\V~F>/{,c,1} bq+߈Dcpl0RB~>Ao0ۓՃRǍ1QE?o|S<7^2p濠W4m/BALƘri(ѷS+L5+H:Jώړ'X fVUw1EQ ep۬PM0"QL(NJHպno ξ_DuK Ui\JH xܒF><豄2P\hVi$HJDjeWD<$b3r 2k?ސTMoPf7jv]ɜz[11]=ܶ%}L8L#No΍>}]|*B#_}$1@i~}V?'"eWn"tv/ȯID$ DFw r5i;SV r'fAMq^nuEH ܙ鑏eQ?q( Me3d?_.JF7rZ6^͌f<?@4$FHp*QfF*c AσQw r[[RUv=];@i(+>.HOأkG CN[h~ уxb*TdKT2VsTy@uV .x:sV 3h#:Dߞnfm8n$1~L%=*N:t0@g}~?ǭ~Gu43V4'԰DLtV=+USDeFxH}e6ʌjݫtMf䞴-O.3zܧ\eL}l[X77޿;7@wkP/|\j;P{puJ^^{U>0#zBku?94f؀ Ѝ'G⍤Ցus?¿-r$`Kyg"o_]i77kzדpgqo18@thK8 []*0h(NNK ]8ӕ[kTۍK.Wߚnׄ w]?4 P  P  P/_6?JRw'_W+ӫW>M`%Ծc?2_4{"\/$ߩ{uH&kX$?@v;}5:6ƻg-i40or}`ٌK-hi:KY/[o{v)EYc@hO7뿞W#K]~+ i={TequgK$ÖNn^꿱 0}sdOKws@Mı ՝‡~9{dl#!? cAXn2sx W?\d)2|8ϼlfwZҋ{4cs/p0it8n7zR_+˒+~G[= 7~{g/J$;| :4naF,IJ̿+saqa~Zk"z_X Ǐ%T8(V?yS.{(.y1iԨz*D?FyXÉ͋rE%sҀ>v~?g{ i>Pvсys;-1-k8a6wdUT<9_?#"IENDB`libqxt-0.6.2/doc/src/images/qxtlabel.png000066400000000000000000000121711215241066400201500ustar00rootroot00000000000000PNG  IHDR3TpisRGB7MS tiCCPiccxgPTY{sirM(9I,*M DD"(CQTD1 idPQDEe[[klmWuW睪©z_@v"M:()cJp+NKւwc1d.'Nt[$s !gr< 8DQ8IȱxךG#~eQ!G}e)!xv տZ‡PGIK,M£2}XQ=Y X@J@ @g\qJ~e~ˡ Ё Pj@ c`.K; <`#`8 x ]RpT:A8yp\]0 >/x!Bd@J C,r (b!.B" ft CIh#0 &l`{7p* J>w—[(̇_‹@QA aH C#HҀ!=r#EC)PV(7T JEmGQ'Q~=$jMFˣuіhwt:.@WQ4a`s&cc10Ø)"b>Hl:[=Nc8%1p\/n7[Ƌ5x<_o `M $v* m "J ;ICr$2HH'HHIod&َFN'#7ߋ8b;j:F^Q =e#%RA9KCNjk;Go?'>.(A0H(h!1KR5T5zz:EChj4GHJcL;=^D>D_JHIn g M;#Q8c|R+&5"$-'m'-](.=*QFYY&QfLYl٫rt9+9\G򰼎|1AEEW*+ E;r^9%RREʒIʕ **n***C*˪L@yx'j>>|2}S}=7XG[i]˺w%3(AAAKNem!BeCCðaAaMa\?n^>aˆe7&m)rtDpDKħHȆ(ڨ#%ǎSΙ.)=;gW7_:-.a)'DJRpR{2.9"MoVܼepnJA ?2`ϓהmHN ~̃Z?dLfdd :Eb wV{ddAsrUrwNnVoڎ;]wEؕva^Y{wOCkX`|՞Q?8wު_ 97 *>odSO+b )ŔrK?Y&Q]6u@gryaۃި0;D8q_U]^UZ:zơVvoa#vG>?޵AXAYǛd>?l"R fΝ ?ugE/~e百mjZA(:v.tuCyMU\PK]}qRʥ˱6=r~_Uϫׯ\2`?p7,oɺuV`mCfCwtߵ3fwv={߿5vtx,px8äe>Z~s=QDIS k7_t|)?4bFiyx_LLy<_ğ^_ ! ӯyW.~#[}O%[^*|/ևg>a?U~JʊD. r \@"D. r \@"?v{7@˱qr @U51PV5zTXtauthorx P+-  IDATx\ TGg@AEF `RAw=MpKf߂"d !KEjD"&x5F8 0lMNKFwMMU}t BbB2B2md^#y5P%>-xD< 摓 };j&f_f\ɔfO2o Ei8$,GW6:kHp|Q-|)@>`6? @hUX ةa tt^0>  oSڐ[ aӢ^| ,.]@4ˇPI9FX.r6{#dF#Y &8t)gV6 s V6 u5:^,%PGryJy\qh<XP礮 )PVo+ٴl6jKXvc6M 2z.Ze3 oaPcA&&ݳD lt,p`Vr6! |0|{o2>Q1Xqx}p'e)h gxhfL++V]4-x`K5ِC.ɻM HźޡWaasfV#T&l$0Tx!˗!!H/Sa>I'>^:M!OHTD,v`]ǺAZƼz9Z^8߼1UXV&ZF2fmR,~c!! ]{KJ~7ܺ-|XoJU==tP' L<ˎ EbB8tkzL=OFe ]VࣜzN_} OVmm.ҺG%?+lSLMMMy2D2zZEGg ++lVŷ-L-~~}B qfqmLwNu!wDO<9د!=sfߛ~8r*r-"9bEZC&_|Q#y׮ZwBpԠ)~d@agfFzGG]9w>/ԤI';~qid'kW^/-Kc~S빴RRR/\eoH]0 QyIos41,WۡU|)i ]eM>cY.ܸSNN6]+1Kiw}FF6<555Z"AA9dd);;;agIuM=U푛7n}7_a' \]U/?|X5l 6`oGFF7:UwcNf5>(}fΚ=mt)" D"[]EEŐ!*1Ōd ԗJ`P޳u1Q1\FmT3I&  eCI#sL[6;QFeРAj^Q\(|왕3"ѕxzzQwe2MgggJ)+}VZ۷691Ǡ-d.󏶶rQ3ܜ={f֬11ՏU MN4kSZ%],niii "/o/_82qyr[ZZjkkQ_[aCzьtZP̽擓,9eڄ#Gzxxn41qJbHOCkؘ>߁JE66>CǏCV 5F20NdTtHȴйpvr3gvȴGr7Rdԩ={v v__%--[usnݚnB>0iyhi~)HFiYo_idw:Uh7oM}%Ic~ѻhtIJʆz.Of..<=!Ao׈I0 0uZN~$09'qAŃd& &nPpYIENDB`libqxt-0.6.2/doc/src/images/qxtlanguagecombobox.png000066400000000000000000000154041215241066400224070ustar00rootroot00000000000000PNG  IHDRsKzIDATx{XTw 8Nս]GMRL,v9}O?=l04r9V5ׯ_mm-~mJtҧzsEQ!!!T`^aÆYf1u֭[7wܘ\~ĉϟs-_ܦ//rHHyY>tDd~s]UUg4iN siӦO?TV;wg4ɓ'SU__o)x 288شBeexCB}x ePPкu&N(J|wYYٕ+W~LVSSӧOB̙3bbb 4YP4ԃoVT*rrrxB !/ܹsَ<㭭ϟt=g#sO>ݾ.{hiiS/KqN2 ;l?NV]-V?^TT$XSՆťab&1a%!!Afrr2!$,,]"yOeeeFk\FdX!,Z(33~G iB +.f0lA>W?'hO|5A}oɉaJ(ZbEQ b-*jϞ=l梤$44T&a SEނ+>A#So`Â7:uj„ 'NׯZtlҥK ;`f[LIRR?{yևc"K!_fBΝ;٥ [b.yoT-.&Px g,`,x ."wU~W{n\ ݇Y"˞Kױkϝ;eٜY FcyfnLϫk)LzeS9ˠ{5v{gѕ[r]ļ> &&)1_{(4M0_Uk-}6aʫxjhiG}Kʼ8[Y! l۞:߮QfruVN9EHпsyoa:z//M61?>rʣGуht:ԩS䉅Sxh7n{Dk+>ubӜe-Ȼy׮]JtmOdYr֗<wɷ822%Tmm-"===..i:$وMRWpH@x=6!!~ؘ/3qS~ 3!ͭ?_;dK[3>Wp;"|mM'gYr[!6b܉p0Ǐ'06[);?jhil; ;9>2啧Fǔ0 {e.ռl>^{n%#zL29Kdd$ar.wNk &LcLmɹ-,I9hL ߟKܓ O]'/|iռC]ahZvҵe-:/xo=[G9/@åzbLYǚZyhV!'_ iu,>]9\䨥OtNg퉋2C&e~B*:s!$b5opAo,7od޲tm|m߭ gY!Y<{ЯΡXwqk0=<^rL& ?IQx]vy{{/Zg%QgIRR?xp E%%2C)WCxYis8<1;911qϞ= ,҈N۲e`8 -~ Q 4FcK[{_^rJ83_x1""z_zmRRRC ,ri# RO8p`^^[bbbϟ?iҤ7gCQc$XnRRRtte2a KT;?<ϼ` ۷RN;8IoD oKE?t/V)"Y*;MHHS"ƌ#>0;WBdV솋{psLcpG,#ށ {_BۛWC>'O`Zgp%[s`v\\hPb \N f`.)) dX 4Yj[ZZ!˖-]f [9...664*g'q8Cp~HRBHyy)Sƻg`.++RŝY8ef߾}gzxIuŔ^_z5g #-----MP یXZL ///7}ld~ZZZj4W?YP5oxz*7'+7'ƍ @qpk\E,>t~=^}[$ɉż-477+J^[|MOp%G7-FHYv_:9EBBBccceeL&{7E(..\D}8x--,]ӊTz(ԬGӇe˗3kz9s!%*,qp,~𝲇|_{^6ufs8YV̙BHff3gt:%`rQβYג}{칛Rz(<ۂ+WOӴ@ϼk7nhe EY,~ggx/Zްbٳ~r++y@ر7 vsѳ !UkЀ^][o㓚j^A׿ 3f K!SLtҪUmօn.gѧ&ȤRKw)4_ly S^ E,IN4جSgp#.Y^\v3L9p#.Y/(X xZgf\4EIzֆ͓RBzeCbcϼ-PeVضrqY =f,LX1=(B}vޚuO}rq&-TTTlmn:8,gHLLի׈#]fSѣG[vrqUZ9rرcVFUxS_βx`&4ƆgddX/8,lƱ}fejjjKKΝ;,8%88믿.**j,;~xQQQBB`M桭"Yo9C ¼ȰBYhQfff# [Ȼv9///??РAVpƆO}),,61`E=qKW &,4MK$w>wݻ11zիe2t2鈈 `[!gd8y@oy@Uqs_~̵eBHFFFCCCtt:̩Ϝh.((ݻ7oņҞ=2+2n8N'>s7,֞L#nZmffʖ5DfC3ʘ wܢWw9}܋,e,9 ݩ6cZhv?NLL.RSSUTT6g4nܸ!􊊊$1bf8l`/;v͎K7?{3cO_~oF3>䓓'O= /VX!ˉ8|C&͔(jፍ57|s{c}r@GίzAArʕiiiŴiӘBVlZŬTVs̙3g.MӧN\|9S2uԗ^ziɦ!tK^pdH$aaaaaa_]@U^Ē%K|g}_ٓrf :111R-e Ȟ[f_ ]P?vOʃt[-ǯ]v…999R4(((//h4K !2ٝh4N7uT&Bt:]aaa{{رc<܄ٖŦYFw1jC&J{x#RSS?.&=3ӦM[j!$%%%66^`7s2eR<+V$2cW^-)a)?^Pܸqˡog./^\̘1\lnjjjjj*!dΝXy 8oH*N6~~~A}{O!h4޺ݷo &?[`Ӑ /Q,}7o^^Dj bZ#صj|}i@ZYgh*33. X7cNEVt\IDATx{PTU{EXPQGe ! S9JfW䘦f5Y?9N: **$-`{?a,]#,|?ݹpݙ{J`pB  @  @  @  @ F^G209^%^p-,5Zn6ɲ'<_RWIPoıQӦs:P*T77gƮG,.X_"ld*_:|Ķ6*8׏n<ۉ,󂛏CVL `mݲK1Ѓ>ʭyׯ]7:EQ=Eq<A+W jl4,xjh^\RB'M2i%JK/X ;(zJnabB-e=Se6?ض]RJi̤ n=_ul6_6kwxȨظJS?޺~(Ee}٬Ն$&%9_e(.Q̈OK*뽄ę``pڌlpS dn=]=~&,`&,``)bY[QښjY=qadVe,;(zA,(˿2#t-$`Ex^T̀Nfu9Ne*XG!`&,`&,`cۼ?^=MW C'=h:dwǺzth۵gxtc(5[Zk>XwSq{BI!̮9{kcQ9Vcn>[!0`0`0`0`0`0`0`0`E0ȸ?'bJKt;[\7l,(׵GX+>mk򯡌njmJ? oX00`0`0`0`0x8IENDB`libqxt-0.6.2/doc/src/images/qxtlistwidget.png000066400000000000000000000167631215241066400212630ustar00rootroot00000000000000PNG  IHDRsRGB7MS tiCCPiccxgPi CD HIdQ20$L "AD\]"QP ."**7}xWO?UOU x"')6 sg2c p/"Q ORWxdz\bnt~FoQYد@J@ @GZq:K~Ig|V4 T&F X[܁7!`#X ] pTZ@+8:yp\]0/w[,_ @QFt6x#H4G#H9R"H?r sEC1Q(K+*APUTj5&:h :DэvUz 00,dc01mK!$f`uVXol6 Ğ^cqD pr\37-x 7ߊ/7wS%E" VU8 HT!}qĝ iuJ&9H}K7d2YlK%WOhbzbnb\bbbb(x:ŎE)ܡ̉5#ķW_IJxK$II4KܐbT'*G=FB!4UCMk]M1tݍO/LKR%%%HVK^0Í(fa2>J)HIEIjZ.n(ÔqI/)D%-+){D]R#W wF<,-'-L~@~AAQE!YRœ"CV1^LGqVdTtQSiLdV0ʮuʃK*,\6'Ujjj꼚ZZ#u:[=VzK#HcF Kb5ɚ6)0ZlZwamXj;:NaUUxWtt3t[t'zzzzC101H4h0xlH5t756HۈcTmt5yV612>bfeǤ䳩)ߴtL,ܬlMg;ϛ0H8c񗥮ee֚5 k&T"Lpezg\Fi;-xSv .9".NT**1-.&..\Ѯ]8nMnf)>b|}|}۴y;{b Ǡ A~[!!q!]ЅN 3 ڰeÍ7^Dl8:<(9SwD}B[dM<ǁsk-FYEFMG[EFX-s{_p"a91(- tG%6+n޲y(Y'9?Ybr0eoLR7vхt'233gf"e`ֽ[g9ٽ99r&mm޻CuGގ.;O"Ju; 4y y;&p%_,?rO폨~ܻzo/܂兟8E72}M`Jx%m,(*sר/?9qyC`CqF'x''N55557--NVֺ6F[ip:_=q,lִ :󝱝sz-y$/zz/f]\|irM_7xk׮_nu nov21`2~v`;]wv|޵no }06&x}00GG<RTiZ L&'{x3?>M='?/Vn19?<{S/_.)g+We|k忋ȼ9mwI ˼?cOO>w2,r \@"D. r \@"]ax h(aE:ozTXtauthorx P+- IDATx TW7!!,D\& `$rи m9Qx̀G `Ѹ.A'/QT A$@T]U]Mw4;eEu}n_z٣Kܓd05]M_v ?d1J<A^XPPXXD';q ?80 /ƪmb LP?v._QGGlڹ^(( ڳ(ҥKٵkM``mۼ+AzU5j2POwAyy9hHXX~H/nӣׯ__\\LkRSS=<<&MDAOΝkkkkaa1cƌg@c8%==6Tdee3(b=d1< ,--TU@ M6?dgg644GEE9sDGG?_^z5ظq\.)(vV jjjccc5hXE X[uȭx, h: `L 5k|͛`ii pc&pAwssT޽ӮPNLL0a56nN0Z9t|1cz"D H9??ʔ)1ڀ΀ `1I$ &&&b-b)TzȼyVZuFڳɓ'kkkVXA*]\\***@y>(ɓ'OHֳvNu=@ ${ٲe~%%% tZwK.s[xPlٲ`4,n3سg'|C7|և (..:PRpp0 ,X =p w,'ukebt/aް?$ޯ}{]\˞xA'Qx?G@;H$~p_ޘ( |#@ ˡ>*bh`+Qkם[`V q߷{{۞LtOţ~ } a(@~z@A DGTꪟkY+gaC-@f/A)A |2QFAHAҰY3_5Ӡ^*41m߁p9JjQP  ^|9~b&55U MǙҲO`L}ft ik|faeeJÇ[>|u]͠1o+}5 {>J~@A1|  auAK5P 4wS!m7L; j:_h}as6٣U;|wkk3Bf)V[㜜} x&hDXhю;VZEAiod9^6F?TL/&J7'-CxgR>wvX^!8hyOtp|P|M(wٳgz}:00Vx -@Y%ŋ_nڵkKjYbbb@+H~Hژ7(/]Ν;n݂Q,[Yȏaz>z(/Us:4zhhߓJ/^ɉ9 h'Nd^@@ 0:Tq|jQbT/{[~UUU WH'[A`$X!8A-p7JD #Fz?P%K$~??! P @R_|J1(0F,-bPhsa)_FH٠] $2===;;ȑ#J- X[55?i'.]`V!TK=cPX`V*(Ŋ+)))˗/755JNNNVVVaaaUd$Qޒ###[ZZTxSP&$$ >\,gffBYYY(C(6t 2M \СC 䰱+LQ5R)VX hV\\\^^^UUa?)~m , ?e,0zѣ:o޼T':::r)j X$PPZIE`O@(۷Qۃ:Սիwٳ;vL\a&{dFhI`eL:fH>צ/|WUOU x"')6 sg2c ȀTB'5ke/z7 =?ύJ9Mȱ$J>™i v2/@!p7N\o?!#|eS+̉' %ܯ\ f/-ϋH^b+<2=.1M7?ge^s1*g {vn:zg,@)'-C,h@$E4j]`̀%Nx6I2AA!(A 35p #1)̃w` ,Dh C:Ć!'Bp(AP*J*j~Af0`:k0=`xYpSp|%0eDa#7D#|d;R#H+ҍ#2|@aP4DPT j;U:@&P/h2Z@1Lt>݈nG_E0 ˜a\1!xL6sӆLbX VkF`ӰJ)E0v G)pθP+5zpøi^{b|?_"HX+?!PAh%\%D9їGI &^'N?$m)NG:ADzHzC&5ȶPry|^&'&!V-!6,S()YrYʜ8^\CAM[Mgjt}mno S43YZ&X6[άaZӰfJ*ªJ`ʹ>j-Qyfj˵mӲ;eon`#X8Du przć/Ƿ__:ںM׽/H l \ r * o " m ]X0 [6(1qMMΆÃ›?ExGG,DEDs88/2lUTitUtiLÚXع8 'ےpIIxT^o-u))ST(uCjW]aHL!}"::}f`-[x[joݻu:9x6*ݛ+gbݶ;Tw.®]s rKsݝ3oZc{,1VR-YhPX^St'ß*~ZoشH W2fRҬ^:ʘeeon:xܸP!AgEWZeI姪تj5iU-x4:zccǞ76gojm,l|wBpd_YSS|sq ܒ2{*ݟjmkcO%3gzϲ϶kM;1) :~۲7NW>_}ABq'gbŅKɗ.\J}}W=^|J]V߰q&f-[&Mnv1unКa]vڑрcac3~hqx'O{Tpaqbٺg'9/HTsiγw_12\ּ|_ O^̛o.,<}ni?}^TYs/I"D. r \@"D. r \?TV %#D2PxGPLTE埡uy{|ى䰱}ׁ{‡vzŃvzwzؓ{|vy~|wzvzuy슌~|Π%%&###mno"""(()556bbdz{|`ab 堠==>@AAGGHFFGppr;;<QRS445{|}778yz{99:||y{ʒަ|Â܅YYZ[\],,-lmnVVWjklopq**+7bzTXtauthorx P+- 3IDATXc`` ```dbx02@-02`EF*zb,4u3! N.n^66>~A!avQ1q Iv)1i <Pʋ٥~9Y,7/?l+())ɪkhjikP3^pYAH /*Fb%ed{FWVMEV,d k.Ǯ%gdLEτGDF!y&4)A#@L%ٞ15a35[ZKhiJXYQ31q1LpфD&*$5Yd{FVNV(t=(J88: 9SgIJfbJIEx&A{!y^ud{ZU $b'4R̤g01ef!z0LbC#EEsl3XH^ėtk4g3gMED癅xM߰MܴCf4졎gf1fτ΁\0 Il%aKlKo[\OՠZ;Ę?|X+fMmzf3N=a4(;3il8h]{P9IENDB`libqxt-0.6.2/doc/src/images/qxtpushbutton.png000066400000000000000000000247141215241066400213120ustar00rootroot00000000000000PNG  IHDR-sRGB7MS siCCPiccxgPi CN% 9' Ef00!+HR\pu (DA,ʺ܌~>ݗۿStxWN$`C<WfHh;@V{__/a/z7 ޿?IrpND.8N2GO9+=EN(!G}$!~_{\ G̎% -W6kk oMq#iXGe'sG7zcu@f;`)YqJ~e~P @(U10V8@( $`(Eՠ4f΀.p\-pǀKށeA2B !/ "X e@n*z:]n@Ch>L, p, g>nOe< ""@=8">HH!R4 mH2C<APL DQbT5$ՏD-hy.AǢ t}=F`0 & $`r0ŘØv%0f beXk6-VaOa/bG8"N gsḸ<\׋xu%oŗ=;i2AI&6U HT!ZĝJiu$J!9I}K7d2YlG#WOhbbbb5bb#b(x:ŞMܡ̋5#ŷ׈_IIH$KKHܐbTg*O=FB!4U#MMk]M1tM;=^D>D_JHIn g ;#Q8c|R+&5"$-'m'-](.=*Q),(_K,JVGO6KUy9[P#yX^G_>GBByEbbbMF)^\ $ӞĬd3ݔ3땇U4UUTUTY1} jJjjjj,8CK{44f5555[5'ZZZ Z1,Dwu`S8;naUUV2Z&^y]  |145L2l4|lD5031Xǘm\c|5yW6569bfmǴϬl\<¼|EgY-;,[|4Lyx'֪>>|j{o?nӺuJjfQƒ˂!!BnʆƇvaš;?~:4 |l-nlݘ&ʦMg#-"}""ܣj؎C;N9g.:,z&:,f6:@\m\E|c|uD+IIɸs\*7ۿYq)))Tԃ +(--[u:}<Uݕ;~[vh{;wLtyraWyyeyowWߙ?b=V{~D{~),2,(T.O?7TbVrS-odDYv7QaRQwp(ҫJSu\hCM{|ڥÜ#G쎴)}<Ak}gFC1̱c7765}>=?ټEnh;~N?wշ3ڋN_3}gYg~UQ un\wv8co'+ yЛ߻r1⥔Kc/Om{|%~W_sve~uoX8wu٭Aۦ;̆:kqgxp{NwktX؃q΃هI_?|xzO~oƿ049lݳS쩗i:9yŌL9/ֿ~ryO?k_i/B_^]F͉&o}K~T^?,g}~痉 \@"D. r \@"D._ .6Uh@ #D;zTXtauthorx P+- IDATx]\gd " 2u (V , Z˨{/@+"8U+̰eɅ31Aߛw;.>>޾}˻ǏOo4j|w$ߓ@cL)pl}>;vnqD=Ti.YYBhia sCMChj.u 4ע qA 2J*7cز2OK M UڬoB+.±}z,*DyIFqM5yJl<r2:!=@n.pc -[8pl{봷x=72_{[E@jҥxg'N@Ȣx-/m؎w[=g޵,z/ڵ7gefIJJΞ3g}wzJXzjo8t TT¶z&*ŋfN[Oor/22YΰE„ Zj^^K;d5NrONrR%DX"uf?ݺ v,X_Ptos|V#Yzh׮iӦL:-88_B=}~`_`Юښsf=~?8UQ||V"_037:*+iə!e TTTbklJIN22H4;;{aaq!$&$"D"xY9IEE_Sf"Qld'򐬳gNCtjQo59}m-=3v 7}˗ӆܸ1yZ())TVV:Pm 6{ XcKRR)&hZZi.Zj UHɓA}?Ν[}akP% n5UZZ Qyy9d/++c[[MMGDl`=fސ=C*+)ʩ)tClyoU">((c G)Y[[bv3SE/OOD;HHJ644 fg^&!ẵLRiiIy9 zݣL_i-tu^9~Y)ȭ jx̌} [0yS)UUw"e,-Gr [>>NJJյ~kЧXKKADT r岜l&}_b;o.G777=".d[ =tt3_I/4t/T瓝fmE 333^`3 :DUeQOsqMnYЮ P\mGۡء_BysgڎFsAxy.{woa}-}VXTT d6'~h8ukFXD+33lramcâX'g,?z\; Y|9C:뵺@UUUK/zѭӓKQ06~.Bg܈z5ƍdeQRƳ̝?UHH[w 車 e lA$%%uV րb׺+d4=-eeet"A t[ѻULMű5(E"a7;)//ñ5(Gb"ڊckP`H0rr8PU>tMo9r$A-7999&iϞ!;A-Vڇql l9L0|$a±'YaÆү1m7$b -.cz2Lրʭ$\n (ׄ-pcwr ߩ#}#u _K쬬JJJD"VX'$tBrlOzXIIMOW#ffn [Z'Lڜ yݣ.qq_]S3yHd_S.a7ܹH4;;/-[_$ݽ{ɬfCCի89;bK-.VLLǎOEE%;MDD˷4ޒWH{138zķ%-USSÂ-t$Dԧ~GYYjk/_?h2wnO>EwpE \mi'|1....흒8kzp̞5ѣd4-ICGZ*~Nmkĉun bΎppiZjF{y.F pgBFFHj}9Ezիӧ~ڲ511})C醴4F41nakohH߈0cLs [Ci;ak#Z/+@d!tQ.g.G!%,4#TE]4HaWgk;QJo>Iw=ڮ'a8[-87mmdL45 F8RR(1 Z>}yYL$,D537G0`Q#ɢo d#7oP`ja{Lʳ2jT\vTO<2:: h:fq7c.-x hB(BuB] )A&ݼ9M[ѧ |ʊ]nknn3gNnÆuu YUU GPNHܸ1%&q#QTΝJ*@Bs?V,W6 ޽;wվpk5{KYYy۶` Ndddmkc:qGScT@SNH.&U+ #Ot̵f s38Z?O;ٱc"V--;Y`ͭ}4qSBߏ8t`:$%%N+/E$Y㗔Xuf6 Xi!֒8 ʕۋFGE}Hs;Sr|90ւ2~[LC^ Y_/JyYjľ\qjhlj6|oj~׿v5 .:q]y-d%_Xgk,]E.&6u8p±c x@uBuloIKK&\'N±˭/ {m|ʑSN±˭[ښԭcw\nr '\n±[lUn=w&|]^\Z*>$R yc@u_ı5}"!`!{v*)6{-mBI8r$4;30qT9v֠Hz:xgcbBfH>2s}p2-ڮ\˖-;-?~\Lա4PTtOu]t TU)=6؂ZdYv3ҜWcwɓ%NQD}TO|p־w}/r2V:[C' qvW^n$WKzlgɨb9^ЩS'y0ٔ!K\{]/_FpDrv2{KZm]Þڔ: 121 rs[;xW^^'u~~=vb/q<XE$6zz5y-e2ẃ̲[>x{TS !|Qѥ˖GD Z ~Gffv?WII^NVjmʁTu5nÇzح02?u$ױ94ri kkk!ReVDGA%k! HJJH$''!II&sZ퓛[W```)`#*WH夜wZ|v[7o @ 0!i,ܲu[iY{>Ʊb*jjʪCǏYWda*RS ݟucc# StZ̙N8DO>5}rr(<xi$,mܸqDĶ5ȷif1qM(yzXII1Tp'qH"^_["ߒfa<1;鯒<(zZ[ڏ= QZE͛zꚪϝ;SSS'ORRT"(_UUVFXXO=RRbX{;C>#P$QWAq&zl\p0axC}=2AAA!45FZ277֡TRRRtE'Ovԓ=цU*O /VWW#,-D)V[B;Q:/!h(yPA} r v8<,l_<<;{?҆f!aaD }}Wc?dZ_4sqvvvkk+Tv}^qNEEJd6j^IzV&7r_! i%)%%$$dmm[?ށLkhh;nym[TM2f=ZJ򿅅ߺJǢ..S.pUcǎ[[M4hRTP*%#Q >'ggtJ_YʣЊT_6%}6+=z[]T ]224/Χ2B˜|'NYY2ި7FZ SP`M +gVm -' A̡) Fu.[VG)S$<-l5ulo^[nҠm8cHn "hc_s5)++>okT]-D'ׂ⩫!/'Ȑχ۳r3$nݺ9u4Oׅ-zcGE%751-S{Ǽ~sss@|ug=[[\ %(0gN1\EYi,$Zzô### ]$~9(OV_]կ-Faڕ+ɵO?h7FmΞ=k丸;uvvYI߷o7o>LL}^TT8hbKꗃܔ[;f#giӦ-G~UTTD45,&:jOHtp b~/ Q<߻)D绺vxzDL#mooGr ^^ '('ѦHM߶SU_H X|kǏG>b!ԵL۽}bKKKҌ55UtL>-(*)Q?Soa%E۽;CC@|;JIIA<0n%]7M122ojj.-)1a?o-[6k۶n`/l}NQqKntBAN%W3!&zKxG$]5g\)))g0W\_G)mmm}I742}X'l~E;waNXF %.^SM zB-nV{CDIL߻-q5򉈰׏ Bl)]\СڼУPQbDx 책 w[lj,}x*1:!?,A'ĉWr?AZ(#ÇOӀb(քO_'rX-";45&96哗DZE5r #̍ 03{KVZ r+ /R,+nܱSJӦ5)BNKI"q;&V>a:DWMG>_(F#?Eϟ_WiWIENDB`libqxt-0.6.2/doc/src/images/qxtscheduleview.png000066400000000000000000000335611215241066400215660ustar00rootroot00000000000000PNG  IHDRlS sRGBbKGD pHYs  tIME $d`) IDATxy|TlL$$$,n Ы-VVޖVڪmEz{[ .lzE٬/B $I 3IfHXF̼|s|ˎ]M@lDDDZ{DTMi}A/b)"" f[+EDDA܌+∂XDDZǵ? **| YTgqK[ӉAuVEuVqj?SΪwYmu^x .]vN<֛Q__ǟv^ٿa`X=6zn6%j~kOy$%9Z-|iM^{Ǽ\}ׯJrsrym&;sUs1M=o=8@ee%Pv睇3)K܊o`ڴ2dPVZwuњl&OҨ>ݞӞ׷Yo=G|6mbXj5V@ lc$9bڶm{sxجF4M,xѣof5:a0l0~G+.)))O>Ggmo~ ._͘ 0qbs}o+ ]_~I~^>GT7ҹwcƾ5ռ)k?EMrsU׮'~OMM 78<`4 y>>UW1h`VZEvv67ogϞ[ f?XVi6}na4ٿP}KU0". #b٦ϸ:w.??w~\}Օ 4u;mv` xW\ɿ|; F&G`بf <믻/}qʾ < =_|QݺRv>={d͚Yx)#|h]?wn^RjeD&IS|ͼ;ѯvmTWWGV~=wÿ|;:v؉1Z\;|>f7LLiږSϰxRb[em#n+VDܹoÊÈ,!ӵKט5p4|wïkV97A1&׫woWȌ_rar-"nfiaƍwZX^|oJ}(ke</YJ\X٬|[>~|޽MKkaD T#b}‘z&|E OkJ߾}ͥw>MVsii)WHMM ߱P8G}ĠC$bTTT0ed&N"رo 56so˱ggOsvӱc'r;vf3hѢVYۦs|;tn1 Vx#.>3g_?g&l.nM~sƌ?<7n`׏5X>bbЦM2)mےa\r֮Yss2 ;\x'Yz5eee{Tl׎H$LJJ*. 0رկ8a)))k׎O=رoM5oc5כv| 6qo&7rKmS)/WY\.b?yqcҵkW l.e˖lRf?_|{qLu>`03O?EB^}5l6GfElZUwyjL~ٸ91 ?oW^y%潌Ñ:+[=OT篍1#F z\rrJIuN:+[oVő+%Yu9!^^U__jVnqw"" ֊XDD$1ɧU5ED-$Z"""XiFx]T8W[ĎZU_!Cؽ@9ٽ+XDDDA,""" b(EDD[})3#Y/=wq`BU~sI:7IM;n34q9BKEsG,""" b쥗^d-_ȋ4u1nX?D(͜$|1*?Xm""" Ə{cŊ)-)fP_W ϿOt6gt.g˖18[HB;fc),Y/ Ҽ<裌i86z1b$cMDD$ჸ:DEUb#trz̓?1YYY̚=}jI n۶-%~,q8p\;[~>b$|_z饔dƍ̟Wn5*vP)۶m`ʕs93u*gLm""":JJJb/0e8].z]v'NtS`D"ddd@,[CVVտHke)r1J>/Tcg%Vv`ġWeȐ,v*|NK}XDDDA,""" b(EDD""" QXDDDA,""" b(EDD""" QXDDDA,""" b(EDD""" bQ(EDDDA,""vA{vRU >_#~u .EqҷMzz#=GHz|NN:ִXDDDA,""" b(EDD""" 94]"NL@X ڒYSjkHԀ"NyL(EZp8d5q:kT (EZ*Ӵ_P3>LHKp ỰZ*հaHr`Xů)4q~8]@G (EZǪx8_b[1ͤE\}U)ǍI8v ^wq˹O!Kuh_[*j_Paq ;<Q.mp8nǭnJm MYJCCԂyCkW%$y;- bV/G TkhZ3}©$9uBDA,qx1]Vcib-XDDD""" bQ(EDDDA,"" XDDD""" bQ(EDDDA,"" XDDDNb)l'z>>UTDDZ{SaKPйBBd`xuS.vEYA,ҢXE(6[*Njk-2̬#55SK8%)i8&I VRC,YڙEiV$/7-հh>'|VK+VM8ktdCaLS#=3gN}.?/`wh>'|nWM1nX?D(jپ%Y#s­aXXi.k?!Z|NAVxҒR{n63f+Q;v bDׯ6SdO~df2bHrs;?V$P].iWK;wgOglkwߙM#-li0M afyq,YL-L]}k>'|nҫ...C8e7ңg5{61olߒ=[Ll6?E/ϟΠ<Y+9̘1<5:3sdG֘sHKWb&%\<jΝ bbӘ:%x`ÇOi-ڗ^ęMm۶4uv<4?[~@,>\0ƀVpw1}N.!Mnw[wכsXm=#eCR{f:yJbPvey^ijk]@5f>7i_z饔dƍ̟Wn56֭#əDAAg***gTJKKcߘ%18TU~!RR2ӳ954Avv7Rf2zOSbؾcmg&o;n'=Νp)q~~<޽[9s, JjVV|NܤAĜ_`2d0GeI y䗿'?y0A-[JUUUӷ$=JyYr%S]]} i0َ[zWؾcmW+P-ߟpv1n ]6MLyҋ7@A@? 'Le;OZ-Θ;poۓͽ>E?r˨ٶm }gܿ1}m0dy~dl6;:zi.aDZmy0|>IRc.X߿c+}P[ĎZٵŝ[W|3Z.%ҫp.f9WeȐ,v*||N|V[ af&+{1wLou^V^Ģm7ܜ UP|>GY5-DBZp9soىIUEa>[5"M#)}E! i-""" bĤkHekП l(//]"33T<p$YA,"2B,]qw}yy&\n7G i9¡z֬YÆ f|ǜ9> 8XA,""B8b5/k5 b0`^5-"-԰pCB]wBjA}hE,"ҼBz.[vJ%K/N:1bHl6[5M6^XVfzB([n8xW_y0޽;Ç߄z&yj3 e˗sQ8FP4jbfQ蔶gȑtXZ »úu_H$C?LMM ϙä;poN^1 dƏd`>9NOO';;)}w;-ߚ̙O͐Cjՠip׿))..>y6*++xZ4OuEuuuq0ljǭY+;cWY6L2ټ⋄9y<{ ~QindP]]c걡={6f_>v;V^}!Gt2x`l6Ji>i`Z:dh:\@)1ִ*61w ҿ_ۼ|9}\]]Ͷm8h)m<0 Hٺm+}l3ڴiäIwr3gcA _'~;N+f&--MJQQƍe!'ϽNJSZRs͎uԉ-4M+K/`t.g˖g#VHB;fc),Y$裏1<.B:ѿ^/#F$7c>ֿHBqqq1:t>ˋ/4M~|r&o|s ++YgXm""" m۶4 \w\tEs=oG6I,25q*=-fBYAM]z饔dƍ̟Wn5 oNEy9vW!ZQQ=SRZZXmXBdfiFIDAT ԱZ4G})))9ϿwtueL8 /174ygA-[{!++}_o⦥4q `D4 oj|ɺӶM8 'Kz`=#V$p80$X&Ng- 4 ω}oimLB$F~A#3 泂Xs8q]XzV EsCYA,;`ĉ+t5 b[p8@Zb6I+R5 7Ҋ%cwW۹B | jҹK9wݵrcwx40 7*nmp8nǭnJm MYJCCԂyCkW%$y;-<'p$0q{x*ήK%1S'JSg t9D|VH#oA *,{[588v##)EDZ cK-ZGJlUWrdf֑%4YA,"1SwG[uo_Vum+JFܴ;cVe?4cƧcOrpoo:sa @J i~wvI@qJ\B* tkZDYT @qv޻o +?l6ѷ'w 9\g> O bZ!dtNKSo5x1m3[F=D Xl66W~Jiqrz]v#VYcX j F`:̤IϞO%N3bĽle;swzִ9gbQPpJmm h[ZZ4,!'Ì9X@sǰXF4N}SN99n?" aS <ɓ_7V@Ѿ4rFH3  %5њJLb_p)5G}#eCR{f:-ݻ͢4x.W2W(_}j뎲z_z+sl/aשV/ .J ִH3P[om(Ngc;H$|lleCxy_p1}/)m3=߭N?QSg-̜9n }wipܓxg IU).?RR2ۧgSSs,TCgl;QeB Z4ϊ8hvGuu_'n?j.ڿP O }X3~|eվ Ӧɔ)/!|^z~ݷH$L.cF\TW}5#vr V4PïmGmm UU8p`;p;th5W!VL۶V?G0x8l6;ʃ=|e!<(^x~ }K/89P]]/P=`Ew菲%LC "VEV+={^矯jz^y?!Cs&cINN.g۶5 ]R[y0HW@Hv8sݵ {4'>MI 3,\$rs/Q&gQ^ዛ+}tƹ=w W;YrU^^`[s#]ԗUSG;\KW\v=,z ~|_!Cؽ V""qEo=۞o!9~Mh|2;8+}jiXKDDDA,"" s,#޳{Tz Cp@ sP(Dmm|A0| Z#UWvWw=㉹1p{RQۺ5-"" QXDDDA,""" b(EDD""" QXDDDA,""" b(EDD""" QXDDDA,""" bXDDD""" bQ(EDDDA,"" XDDD""" bQ(EDDDA,"" MIfFz^Dy/{vRU^/ >_E] bn 1TM'as+%fE?Z4!|:KWvWw=㉹1p{RQAg{_l(//V?ZEff&x<0IIF ,YEUV$/?7݄HҀ Yf  7`ZW6cΜsy ]a,"qI_5]TTĸqc:t?P(ڶzjx\c>zpG!z *[10Xz~!PDDg3ax>VxҒR{n6L|7s<m[7۷osA>[lڎ6nPuDBjA (cٱc#B~lL2%e/( 䞩ޢ0bHrs;#VۉBz.[vW•J gDm_9s3<{+;#VۉLd kc+e˗ӌӡC㼼{ߺv͛ټ3qa5{61] [,l6|y| Sfk ԰pn3)SRZRºOp!fx%cqs.bܯm+Wn׌mۖҒcOVV;v䷿ロFʖ͛q]ߨXmAp0a)ʀb6X-g" K/ 7n`r˨Qc>font=|ԩlñ7WUUADSSS@v8pѣ9r)}'fNt~tu>PYYd$%%12n ѣG8qi}Wq؍<ȲeKGcw8At\TWWGhxyS7ӟp8QNmה65GmEDmMuglS[d̘;GvӨ>ֿb! /ssf~:vdCa!=z݇>qFʀc|9pC>Y~}F(Qo6?1`@^͸zfcwpv;nڸzm۶1p Rڦo?@]]a:|3 _|icNV\N- +طowCVo2dw>$J_E_ݱØ17rE}Yjo ]߾۶ut̄ "" >.~ tD!""LDDDA,"" HЋDDEQH PF / bi1BzK.efP=k֬aCLLVHp85k(\_p׮WMH6nH׊XDDU(Te˚vt%SUUEN1b$6 /w}ɊޣwkMuY/V+f=b! ѭ[7FiQH-l6E<^?#G1#ck2x5.X?!)|}s!3Iwމel߾޽zcɌ?H$r1 ,Эii>v@ Ьp0a)ʀb6}"fp8jsDSSS@v8p ';GrRڦ0zm|N'555ݻ3$;;!C>q f C59\.`4^Yk8c_ǟ;jŴi?O}K/4ScWEDX,Y99TWWl(,GϞ>p0~ڵkGFFƱUo__HC<7t2x`l6Ji$4Ƙ;`vrss߯iݴq#@uu5۶mcA=0 ֯׹y"""ӵKWxglB 0.;:0}/l#3<>\vK0l3VİuV>]Ν0ab護z\ q[H tK_iَIlԶzH3R(EDDS=G\ Uq(Pg. Hzq;p 18q>' bMzz~!CKEEh@\" 'V+>9B׋B?ukZDDDA,"" XDDD""" bQ(EDDDA,"" XDDD""" bQ(EDDDA,"" XDDD""" b(EDD""" Q&ivT8AD-V("33SUS([AqjA," ,xTxFZq:QdiD/WeL~A>pX!" HñZxZ 6$^'" ▿*\n7\ՍW^ /"qp$1p, ?]at+d{E_*$ ([Յ9꫹O.[FѾ"r+aZ/ga8].([HQ)++W[4vzq\B!='," co{q{!;;,*~b6INDDčެQ^ݻT:?Km0WwvCۅB!jks U_ݙ: >1[A. !|: iZI:%7*}n3p`D+>9B׋89 bfa;lU.<;s-eYGjjpKRpL 48 i+Ph)!,4 Ia_Ɉrp jX$㧤&z5k,̙G!Xط79svmpF" &]4?H"ƍСCxN]ۇ$px9tp},Sesk@DA*++;{=|0~<{+VOiI)=7۷ӹ -[6lmhk]jJPA' P,i0DAڴiw?X,vAĈЯ_?l6La%(1܎1&'z˺`ilظ 8v_ܹӘ={"o=H5*vc8ֶfg<8,yE-L]}u5пڴi@qq1:|rˋg,++YgsXm`ah_?'V3w4^_˱ <ɓ_{1c8Kvlmg:ɏO~{WRRN:z說iӦ_oqNG:skfeׯ_p!33- 9s6lҥsխZ5,,,..ѣyyy~GDD%ׯwYYYǫj+S%''~^pz۶m0aBVV֪UݻPYY޽{#455%&&޹s'88ϟ?T>>>\P+"STyyyk׮/` /!fG3駟?jK(+Vػwoee1c(:`03O>innnhh(((0;QOJJboBLŧ BܥF8JXXɓ?C.gff:uGV/_I.;vԩSݺu $$ٳr|ɒ%2,&&f?jTWW+J-^X&)QFY RY]]-p^& 9rʕ+~mFp†Ջ{x}KT*- Q wwwNgv:!W,JNN|իW w ?DXaaa`Tfiiixxr:*VʹRT*=<< ј1ct:Ν; ! !jM766 !dĉyyy«/xܸqZ6\ fSfܹ +((())k׮GݵkBxw8УGBR!V8|5k<<<8@?? >lF%L{scfلXsE`(444L>}ʔ)K.e_h4=?)ɒw.///))V^mv>>>f={r#pE%Ii礪Wt:ݫgq1B&effruc2sb͛oee%kuAtjgyDdg+---[nmll4ך5k,X銊bcc r梢v*^^=zǏ;BȡC\[{8%cٖי2ӧ ݭ[sSލOOϐcǎڵLJa7nmrN޺uo߾ї_~JILLtһw-^ɓ'sa+ߞ>k֬[}4i)1cX&yƝO`t 2OuuzhDֆnyYeڵ?0@0`Ν;ǎkg.>'l8Wѹ[:Y"{5:+| rЬT*ٳrʊ 777;u N~<3ZRrvCMQJfBmW˖-sg̘Q__޵kWB}Y<_n ZN+8R+Nƨ vaǼτoultЕ 5fra75H Tp+@s :\t/lby*WcvBti2s >V+&\G9:mf 1_p` `W@dW^mZ 80G@tv;w ڵk``իsM' R"## ,o߾555ۦ&Z !Wk)))֭۱cVJLLXG^yEUWW-YĶz;f;Gm6/ 0aڴiiiiX73j EFF7L.^vMV_vRzEFSVV`{zzuPPP0bBE)5*RڧO?p„ 3fXv-0wyG#Ft;au֍;_~|7_KKK'MݫWܸqaâmh7' $'֐&Fk\9~СCt0̄ nܸaOiYOOϖ#G~-[<ܵkFZmmZNJJ~1W+MMM۷o7 G4*RڧOǏ555=z8<+|^_v!C؁ $&&RJ"""^ׯW\-..4Zpљģ"}FB`b]6TUUjvÇuss1bDPPPRRΝkiiIHHh4񵵵ܧgϞK,d111Ç駟VC&ťĸq*JWWUVձ/^LqwwOJJ:x 7sխZ5,,,..ѣF I},@mb.ZHPT3fۗr֭ɓ'+{rTѣGXxܹPZ]RBJJ #4h4=wMyZ&dĒTBhhݻKJJ~իWsݿW^[*g֬YogϞm۶A+44`0SdEq뾕Lx]lbJ!d2LP5yyy'̙3'$$bN{C//5k,X ''G 2tٳgNV}SSS˛cƌt;w$dddӧO7*/--ȑ#/s]]R "zӦM;v숍4|̘1TNg0 JKKkD`J-6pڵA%'']v _0 SQQ5kW_}pR:eʔ4%8B۷[ޗ_~JILLt޽{kZJh~WJ]|||̼{n\\ŋ}8q_/  7a„?XPܹsR0_|ѻwoaVZMhv[^z%oooaƍWRRBaH|ڀewZ Hنj\_~„ fG0͕r# 6,--M` -VSS*jkuK|mHIXۥ&Y|)5"MZub>#?ҥK\ڵk/^ܡ8(fu]0 s…cҤI/G}$333O:V/_dww[cǎݺuq!*[lYTTT{asMiAEF)Ìm#vx$K"&쩃"z9ס]* ŗ ~֚mV @>7LHH偁ׯ^ 2;..KWl'vx$K:̣BSYAAA ӧO},qFl[NFx#_wG[??BZZZJ'kbչt]tZB6\.1:={\.;vW_}ջwo5{Uv6l'vx$Kjfi?n9f[|ȑ ^t}ʴeHm3!Wl'vx$cֆ=eʔiӦ%'' [r`ʘm{^^ߪ ̐~"zUU?~9񠭭$\Xi!mCV^K. JOOg{BjUe̓_H +Z~=-;}  Bmcֿ B}{2{ePVAHZk'z T+R^jG#T)s?.J T6dg Tfes TgfC TN'תhA+O` T@BsիRHQ˗/oZ;_JiDDDYY5p>ό Ehlذ_o޼y7n޻ws2_7oe2ҥKׯ_/z=hAJBBJ}AAA)))&MoM֥Kk?yD8тPqJe4J߿EE]:{lHHFIHH2eNRRSSGb v۳gOB1rByM:ˋ?~`Xpauuッsrr! jllM͟4//d߾}QF]zvڴiX˗/h_unrss"##q/_,p^Y BDd&W V-..!!!Pyyy ̞=Οp2LP5ݳ*JWWUV SuuR4,L)j!3贌kǚ1+#G\roh.\}={rojN#l۶mРAz 5 o{(JKcT]] b3>99W^-,,ܽ{77׷{{m+E_tiݺuG(--రRa7˖R)0 `&W (J`0p=}!СCW\Rt]]R "onn6G766 !dĉyyy@VsoǍ'pr\;w.0z JJJ>rww?xڵk5MFFƄ ri 1cDFF?22޽{ tUVyxx>|x͚5 ̟?~x$ǫT,BHFFFTTw ژۆ3ܹsرWkٯ/ Ǐe˖C^%S6[ېx$ `VJ^^J={V\YQQѵkWѫjZ5֭[}>fI|$I NbY?cƌtG !ۆtd6 vO޵Ȯ`\{b`'<'dt] ȕ(tz+a)٧U @{9/ۤ=_OHHpss8s ; !dΝ]v \z5'N6lJd;bbR:N.vn X;_yI۳ƞ={]lu1[>>+?ZqvrY_ihh>})S.]_h4=?P7ݻwoW6>>>fUu>]C>@Zy殦_tjhhg} _1bL&>*///((愄̜9mtRh(Z;S2?* ӧO_Yrի~mOOmÄ4k֬#G VSS9_dOn>vpv- 4H6W/0`@TTsd.>]$~,I陊᝖o`\e˖9bvK}@g`%Zuh2;+q4 ӲE}eo9h47|2ER%bA8'thʏ?~Ǐo߾Ds-Q" &|gte'Nq֭ɓ'+{o޼['$$$p32eʮ],MRRRR"""OMV?pZ644X Fك?#QHz&ddrXۧOVUUnٲRCCCׯ_\[\\ܷoߵk655~Jjjj>|ӳTBQb3vC˞PdIl eFGG:uhBrExiNCߧOJ:sfJӧ ;ynn??q-F>jСGK/de*a.^h?߿m\^v:vB*cin;w2wn;o`۶m_ɓ'ݻG|a޽:TWWwΝ`*6;Q'߿?>>T: 1D4TJhMՓ,IUAAAw0v0֭[{9Jpܸqc^^^棏>$T8X]&&&曔P1sss{e4t4T*wBki*K'MMMlgnoaX9wߨOIIaf塡QF]zvڴi&.***))ٿC!z~ԩG6m!$%%h. ܊+[YY9fJijjN3 cƌqssO ̎fTfppp!Sq,Q"Ө$ndIݬ|sMDZ^TccV2 ߲eK\\Z sZ@ 4&&wߥ޺u륗^ffܸq%%%k׮EFF* uYB)ݲe !熘ʍ76';of;ī'Y\ucs~=-m۶}555ǝ;wT*Uaa!{СC۷owa_r&m [cvk@:*lwۧOn۷ormO=zXk-/_0Ϟ"zf%vV߼ysCCÝ;wvK1oT?}A+-V0a€g̘BrcN:խ[cǎƒA _MՓ,I٨0[7G%T~]Hjw ru3h DB{-vV!W$UwE  Q&JhAmgG& 9T;| yҙCdY B.͌_pl8kA+άUтPQ WhAX+тP!W:+тPq!W: тP!W:hA# W:ӳ CtFF}MI!TA+ & bB+ &bU!W@L. + &3b 8rXXBtu Y8_qrK q%D:ɨpeH_o@qhc(HS+AAXFd2@\-u[J)r~Y\;p[@&bJ) 7 E_#3btToy}kb?.ZH8 +8e9- 6WfU#`h-=\!8qY ڑ\!8Ş+^@<Ą\1!W@LrĄ\hWY˿H)(++s\͛77oyCWTTTPP@)U*h̘1:nΝ_uZ]^^΍ 2qļ/3###**\&M2tgϞ믿˭p[l:t#je3vCD9qhz??VME)uV>}T+!Wcp\q2F+ & 83!?q!WQJe2ҥ-!WS+]DE\6TOn]+}>!!! -""̙3pW!;w ڵk``ի'N6lJJ6[ 8?x͕ƞ={J>h`HNNV ÄR??+WPJ FP(²( ,pqq  >&**jpVP(2221ryaa===Mh. lܸqذa1 yQF{gΜׯZ?~tttZZ;|ᙙ_om+9v?G999aaaՔk׮/wSSS@@ ѣG+++)ƍr//ZJi YxzzG9r^[[V?~?a[o ={^pRw^Jr9+sٴi=k{`毌Jmmy6l>ߞJUUZvqyjWܽ{z{{;w%!!A֚-?99٨io.yyy ̞=.ݺ W@l;v~ay ӧO2eҥ~+ѣG'%BY244t%%%իp\=`oonݺ͝;nGDDxzz;vd׮]>>> dff޸qhN޺uo߾ї_~JILLtһw-^ɓ'sa+ߞ>k֬[}4i)1c˽Y{+k׮ݿ?a]BȀv9vX;ussR/0`@TTf7p@RgϞ+WVTT٭Qũ)$dR{K"5+? @2, vPJAP @#hm ep w(x ` X  !:$ )B.d P(P 톊2_se4 =&9o#$̂aO8©p6+ _o0~ /"!"LDCX#⃄!1َ"H҆ =#PCYP(6*UFDuQP4-E[!Xt]nBwGw Ęc0LsӎLaX4VkFbӱ*)EvG)q.0zq#2^9|#?_&P kB!PIh#\%LDяOI$&^'N?h$#)AG:ADzHzC&5v0r:y|^./.!V#)6"S))ٔ Yʼ8^\CQ~ɱs梭ˢgbcbfccU;WǿNpKKXJI<ԞKH>ǥq6oLzQ;'OğT<{|3Ig=bO#O+fgggϹ}˔R}׿\Y~{w7'ޚ[]|.R{'?> | 8 /_&VWVD. r \@"D. r \@" |ݻ"\mЈ_p$NPLTE NP|lpnrpuZ] zTXtauthorx P+- IDATx܋N0 ^7eƥSMXMQ &$kSfnGˇڿuHsL3 ]tE]tE]tE]tEw]T])<ؖ]TRU9ᐭn;U>^Wܧ nG\ u=uxW{r=3E]tE]tE]tcM't袻oX[\ktU^D"tj*Jwb>f)uoz'yKPHw1rKPm4Zg\rDIe!\T]dx=wɐpe#U$\c9eZr0˙.֊;2iLR;2O{[+w,kN4 tE]tE]tE]tE]Ws#ݠN W[el~.uu!h+^cݝޮjtE]tE]tE~u]..Z|6藉4IENDB`libqxt-0.6.2/doc/src/images/qxtstars.png000066400000000000000000000067001215241066400202260ustar00rootroot00000000000000PNG  IHDRzOssRGB7MS tiCCPiccxgPi CD HIdQ20$L "AD\]"QP ."**7}xWO?UOU x"')6 sg2c !l YwZ9c$'xnT*GiB&qW+,B(Ɖ+w~sr8RW&]ȯL=œX~]~osF\s&q(>/"Q ORWxdz\bnt~FoQYد@J@ @GZq:K~Ig|V4 T&F X[܁7!`#X ] pTZ@+8:yp\]0/w[,_ @QFt6x#H4G#H9R"H?r sEC1Q(K+*APUTj5&:h :DэvUz 00,dc01mK!$f`uVXol6 Ğ^cqD pr\37-x 7ߊ/7wS%E" VU8 HT!}qĝ iuJ&9H}K7d2YlK%WOhbzbnb\bbbb(x:ŎE)ܡ̉5#ķW_IJxK$II4KܐbT'*G=FB!4UCMk]M1tݍO/LKR%%%HVK^0Í(fa2>J)HIEIjZ.n(ÔqI/)D%-+){D]R#W wF<,-'-L~@~AAQE!YRœ"CV1^LGqVdTtQSiLdV0ʮuʃK*,\6'Ujjj꼚ZZ#u:[=VzK#HcF Kb5ɚ6)0ZlZwamXj;:NaUUxWtt3t[t'zzzzC101H4h0xlH5t756HۈcTmt5yV612>bfeǤ䳩)ߴtL,ܬlMg;ϛ0H8c񗥮ee֚5 k&T"Lpezg\Fi;-xSv .9".NT**1-.&..\Ѯ]8nMnf)>b|}|}۴y;{b Ǡ A~[!!q!]ЅN 3 ڰeÍ7^Dl8:<(9SwD}B[dM<ǁsk-FYEFMG[EFX-s{_p"a91(- tG%6+n޲y(Y'9?Ybr0eoLR7vхt'233gf"e`ֽ[g9ٽ99r&mm޻CuGގ.;O"Ju; 4y y;&p%_,?rO폨~ܻzo/܂兟8E72}M`Jx%m,(*sר/?9qyC`CqF'x''N55557--NVֺ6F[ip:_=q,lִ :󝱝sz-y$/zz/f]\|irM_7xk׮_nu nov21`2~v`;]wv|޵no }06&x}00GG<RTiZ L&'{x3?>M='?/Vn19?<{S/_.)g+We|k忋ȼ9mwI ˼?cOO>w2,r \@"D. r \@"]ax h(a(1~wPLTE237RSVACf mqqrt67Ruydg()9Ѱ$$(TWqqtOOS005%%289Utx)+BJMvY\gjsw_c^aZ^WZ+,>vvx:yz{nnn$$$MNNWWXHHH(()YCzTXtauthorx P+- IDATHO1"SĽ=P{7(nŅm5Hy{ O壣>q\`PP,'&''|00>5r@P!q!gfnvFGE 1d"6F9rj΢qĤT2KK K+k¼\L! zegfdx-mymnm <wGN~¢ E}ϾҾ}O%_JſxҡxRsAo*ehd9Tf, FG*DVS' WYE'*~ꠧ5l?;WZ_)PWO^KCCuL$FKn 6547A(0݉usqm*@WgG;T1ݻ?{z?>z{Yxz'#?Xnyyb P5#6IENDB`libqxt-0.6.2/doc/src/images/qxtstringspinbox.png000066400000000000000000000061271215241066400220060ustar00rootroot00000000000000PNG  IHDRq11sRGB7MS tiCCPiccxgPi CD HIdQ20$L "AD\]"QP ."**7}xWO?UOU x"')6 sg2c@e'5 %FrI<.NܨTӄMW83-YXL /P+W8 2pL8‘_zj9$dj~M0xiQ|^Dof<48蜕X}{m_|t VC,h@@2@M  oBF A&@>(% 4Vpt2n`<0^y,A uH2ؐ5yB~P@<(ʁvCP)TAM/92tB,7F`L` Xfvoc8 ΃p=| /÷X"lFBhlG riE~"@( btQ(WTJAmGP'Q>=jMFˣuh7t0:Ga`X3+&ac00CI`l6[=Na8%rqf\n7[‹xo<_owK `E'v*q"B4'; Mr IH'HHIodٖJN##7ߋĸb;Ī:Ć^Que#%RN9KCNjk;Go?'>& A0H(h!1CR5NT.5zz:ICh4@Jc,=^H>HJKJn )` #Q8e|R+*5,(-'m+%] &="Q)$ _S,JV[W6SU99G@#yX^[O>[BB9EbbbMZ)NL $ӎȬ`1]ӕTX***m*OT lh2^y5%5/Gxuz!~E FN4ˍjak5m4S45kaZ Zj&ڱwt`S8:CЫWVկ%fN13_G[i]w4z)aMAAA`mBdCBB \?f6aˆe7&n)bptxPxsHȚy%ז[Ɲ*.93k[;W:56~1;DrbPb[.)<KmVܼePNr~ "`<߃ߘ nHJ ??OdXgTg ?lQ?8wʽ_ 7 ?qndSO )JF?Y*QU:y@GMo"J?$T,T[5Rm_V#_f0# }PRQQ_~ s,MONNk2kjjo.n[[fO]umt2zLY_it@[;;c;]!]Cv[vۉ/H^(!,_̺p)˓z_ rϷoל]x7dezcdA;fwZ33l3|kY;240`,lL`a׏2-=9/x"ߵ~o .L8N <[$g|{N~^>44c4s~y/^&\SϚW~ys--yCǠK*>k}e|9iyY"D. r \@"D. r 7 +˱1 @ePfxEPLTEA]wbꔱ~e᤼qjشhrgcvoʍŹݟmfkѥ¾獊5zTXtauthorx P+- LIDATHǽR0I]Qp߭ E[Idp;0>}lد$#E[d E,hYHQJ+AH$-888HV aqxd͐[\Z^YFf3""nmg;3 0$'"?UoU x"')6 sg2c Ȁ(IMZRFr"rx\ Q! 9]W83-YB(Ɖ+w~sr8RW&]ȯL=œX~]~o~-q͕`ҢD-߮K,uG%GYo@f;`)Yq:K~Ig|P+ SH2@M  oBF A&@>(% 4Vpt2n`<0^y,A uH2ؐ5yB~P@<(ʁvCP)TAM/92tB,7F`L` Xfvoc8 ΃p=| /÷X"lFBhlG riE~"@( btQ(WTJAmGP'Q>=jMFˣuh7t0:Ga`X3+&ac00CI`l6[=Na8%rqf\n7[‹xo<_owK `E'v*q"B4'; Mr IH'HHIodٖJN##7ߋĸb;Ī:Ć^Que#%RN9KCNjk;Go?'>& A0H(h!1CR5NT.5zz:ICh4@Jc,=^H>HJKJn )` #Q8e|R+*5,(-'m+%] &="Q)$ _S,JV[W6SU99G@#yX^[O>[BB9EbbbMZ)NL $ӎȬ`1]ӕTX***m*OT lh2^y5%5/Gxuz!~E FN4ˍjak5m4S45kaZ Zj&ڱwt`S8:CЫWVկ%fN13_G[i]w4z)aMAAA`mBdCBB \?f6aˆe7&n)bptxPxsHȚy%ז[Ɲ*.93k[;W:56~1;DrbPb[.)<KmVܼePNr~ "`<߃ߘ nHJ ??OdXgTg ?lQ?8wʽ_ 7 ?qndSO )JF?Y*QU:y@GMo"J?$T,T[5Rm_V#_f0# }PRQQ_~ s,MONNk2kjjo.n[[fO]umt2zLY_it@[;;c;]!]Cv[vۉ/H^(!,_̺p)˓z_ rϷoל]x7dezcdA;fwZ33l3|kY;240`,lL`a׏2-=9/x"ߵ~o .L8N <[$g|{N~^>44c4s~y/^&\SϚW~ys--yCǠK*>k}e|9iyY"D. r \@"D. r 7BVccgy*4a [<zTXtauthorx P+- EIDATx] X8.@B )ijEb/-heb\AI<>P]khvբr&,)刊BO~9̙9 }97矙fwzegѣ' W"`ezRZM`p@r%  .˕R%_#ȕBD!Q" 1m";rsrO}5*Μ9Ĥ_~&M'~駡2lN W\iccchhgylUͪ P8+"6NkkkxxyBBlx[[[###'GGmHpڵ#FP%999Ǐy&p ނN6ޫeHߚ5k=z $I~~~AAA]]]߾}WXͪ(B@|nnn)(bC\ 24}DGGw=9]q@9EPYZZu WoF4 L$n pq!11^x'vmm-\댫K`m/o X,f%P΅+? E3p"EbCt9\uG$J[ZZֶ6byxx.gff(ٿ?)vwwQ#wmV#1֭[BDiƠT~n,`zr|ħs z*RTcƌ9pT*wD +**@9["ݻw@mV#@p?T!Pt‘ EttD%KPsνtk% ;R] ii)hŋ,Srp7ns8Q؊Y'+;vPPB>Ngaaa \!mpҥ$oϟ!B\`/S3f̘={6 O~]H!0ry{{ Xnsbff6nܸ &7%g§j7StV^=l0(L5|p !LDGda|K";Y p]cl@@ 0dWu+FAGLIIaYeM:(AJBD!W}@tGD P"1"="e!@hUW_ER;6(m@G>}b?Tdd%vi:*r]]jP܅`L)Eee:;)U#jB4)D#"P# g)-acklge}A`>Tgk /PyK#1#cƌe(--M L.P,rFPZ40ݹPѝ;޴1(xͷ.0FxNQAq߾}zli `ڵϔi&2Bp=uuu,!ϝ;*=Y, RN8APQ+Gwаe%/hos?y*6( Q1t- Jqw#&N z{%lLK7(vw)^}sI: ?^} f{?ajwa*wìYO sXfLZpyK6k+Cj=F$_e`_ 15eK̽̚Y#F fMeUcf֥ɓcx-Z8 wfjРee7̋S'z'ٲT+޸ȈZ~G+ }sܝ<" D,|9LʜQ 'Y{3cϟ=o Trw:HSt7}}}74ƒkfx/F60@W+zC[f]lgOuXF#g͘ LBw#s L7Znx=BD@cD{Ri3 d l`A0GddDs%w+'ЊG$V&f|7f="BD9BTᪧs7V36p8tЊ+ 7mڴnd W999wf|7ҊA0dɯX[8: \(VF$nݺ :u@{zW~~~ǎ*Wa޾IJJ *.Knnok\p֭{W v||l+^ޚ{b+meP1k,jv`ZcWW'+ӧπOAgرbXnJ4_[4 o1v(X~o =#"(D вR)7C@!v8ݟIENDB`libqxt-0.6.2/doc/src/images/qxttabwidget.png000066400000000000000000000144751215241066400210540ustar00rootroot00000000000000PNG  IHDRC:sRGBgAMA a cHRMz&u0`:pQ<tEXtSoftwarePaint.NET v3.05\IDATx^KGr}%ٷ>ڧEb+:,šя"` ˕%KgI*zį="GOWeDUe?"22[zmt﷿uѵݾq8zUo6~q|֯_+?쏝O[R\O3ΞG_l͟]w|Vl{ 1>bt^RPbtxǵ`X\=zxϞ=1 1?7D\iOSض MпQk'=9NU/տ>SqN 9H%u-'eRX̟׆i]#&D]јѱ 6lӔq{c+SD6@K %V9z2%Fs4 1zrhBxdB %r"{ztM 4ɓYm,QO)9"]h&#oz9F[WB'Gw+Qxp 4:rMQzh<(r|Dƣюv Hrܻugwˇv͙sNГǟO?Ow g?g:k+ۼFٽi߿w] ѣiUh]ǿ\ w#yjp׍9)$%F*OMw]IЅvq:~_{י ua^['rQ%4:Smcr]·iŋ݇~޽+{A/ueʉ[ҏNc>?t$29bB nU(J9."KH .W?tou{{X5#a=}qxxHTAU=5IS\ W)eν._nڒmD;n$z' Y<(P|CuYӴV9H/ѭW:dl<48?%M/d *^בo )u6ŜdB%;1u&+$˪6nM%QzrtK1 $['iLƏ% t'Cwg^95Z>Uz7V=VEǪ{iJ%9/;YV\bdL@Kz$&z~\!BO6&HMI r@rT - X$%䃪*ՏE؈CC<*)( ?.h{9ԊIr<#@/JaȑJwrjH!"O.%NVY!ic- #s)uÒ>A*G%C/2/;qW/_fuW`9r)N|<6x ,"s|&mypXm⵫o6%I*}6"``䠌Yzv;Ru]O0Y+F%-u:.&A]U͓7w#Mcf:RBsI)Dm,lgg=|ݻwOȶRƖs{qMθu떼{K#灼" bmɸ7!T2n:̛LEzs0H}GCuGCVOˏƲ]ՂtZKrhcY,=!vdT]x$:Eszh`*|~^ZCˡ-HʅJ`L縖HZ=+:DC#I#I% =CуKUtN;dL΁$VKӑc,Aa. z=믁s&ht =AѦSF^!698n|P'bk ұ.:3f.IrPB?H~قՖEE˫.ژ5]ݴo&r~o@BS=OugiLDUƬ^ح98.0D܍TS=wS9|!NM:^gm?SS]˱MZXu.'c%oz#Dkj99z{c< ]W 'ϚV5Eάԓ*ULSXu.'3.9HM^~y%"}ZWOKr(ϗ+ĘgKM(r}q})CY\/xMWc=;=!?ͧ8UƐ3*Siőʱzbm}(~{\egbecFWK~?w<>~.dP \fqkd,-o~9a~Oԛ.4g|?!ReȮP? YaHQ񽽸`+m\qQ(^w|,޷^1ʬK%Rx8/v\ Hcx P?m{qӉ*Q|iIӔUsl4?(ڔmUUG㩶z,b짗Y&nnYIt:독c|L\ݓ:Ei2D+@ehض'=tNxNԱ~?1&nɗ"h4SeV9**n9|.tNyDJVabN"NmVoBP&;!׋zxΓΈ|p>Sc]q ǼLx:!^ǽN7WΎvatsxBr'e/a]κU)oљ\tiZ͈S*mQ%u'B߭êԇ$J]()6QURG撰Qfo5<ؓa"Bd*I:1P V7\LHqh\9#A*Fpvss!kX:[byұ.RB&J䘈7%@z=EpEF E{ҰrEMG62eV]tYUl:rD+M;PUTׁ  zp;ɄMr,Tx,ȀJBDPi(6@V<3`W+n4yqc+AF^z8CZ=L(4(t؝pu 7'VuY.eݴMgUO[FX4yi2 `L z"PJ ,@ D"S]ܪ/97˓fŜ9HCV]M9*C6+Ƣy3?$ͬsaO7AtuZIGlW'r_<֍X'DP.:k" cim,c^lZ!. 5L`/jHX/"cdK&707ؗA<uО7> vK@fy3)#A 9A-:IL{yY6 Iٜ~.X9־Dq89;3X 49ƲvE $[!au~B"di(.΅v ~thOO#EY.^NCٶD¸/9sThZ=s,Oߟu|33tD=)m,~^+Zxo/6C@ M^ZXby:g>l,O hrGh5rНG{zk4y-h;rku.Ɲ=)Mu?Vў6fZm|>:[jm|VӞ?Zh}huzsm[=K,O/m,>lGs͵-O.6Z=>tgV#=#>JVzs4ӃAmVOKߟNirX:=m4y鴏~^V+w&/m,Yu"y꜃~Xzp[:XN[7vHC{w/]rwow~cף6ĸtn/[{}ۀ؀F %ƣ_ml|/aIENDB`libqxt-0.6.2/doc/src/images/qxttooltip.png000066400000000000000000002366761215241066400206050ustar00rootroot00000000000000PNG  IHDR4p pHYs+ IDATx~HE   $ $      3:    # %1$  θ   >P'!, 8%<   "  5- 1S    ! Dl       " >  ! ;V           "              Ƶ    .+*?2B!  $   !5                 #<1` $ $          5$Q      (      .$   !   )3           ## zH$  "  *2@(Q    0 ,)< $"8  *      0. !  , %" O               3/   %,%#'2    #     *                      $     '  -   &# %   "             3    $    <     Tp        (          #    #     "/ $H& B         !     !/,     !            %%"  %   ) 3                      $@ !+   A 4    !   %       "Pq    (< "0       "G%?˺     >6 =H $   %"          % ,      %    1$( (  .C    -        !+ ,  (     )          !      +"3#     4  ?   2  % (4      ,#+      6 )       " !      %44+           #     & !      0%     -!   )$  =G IDAT  $    "   5     &'           &     " 0:     A$         $               %              0 " E (, :-K     #A       "  _y           & ^               ! 3        "              $5  #     8     ) '                     !     +               "#                            ('             )!#        $    ,        $'#T 9)                 ( 9                                 4.T'                 [n-      &!/  *$       ʺ      * #       !        !          &       ?   ()        k    ) =jҢDg ," !* )%       . TTIְ.   "     +      #     %(J      W{ IDAT         0            <VԲ  085 #E! # $ &D&!   ("    sBL2 ",)   4  $MDX             ߻   #   *9#'%' (t×5"J"4  4-3'! + #  窪     % $  e{$ O<[ (      ʶ(# ( ˯(  $      -Boo ||KK@nn990    ì!1           "    #( OD.% $Q9G6ι  !     6  5 +  9    ==5CC:>>5 ''!00*991oo//(GG=!!           ' 6;    + !      -  ..(ZZM991$$ YYLBB8     [u   N<[  #     /+%    >700 $#( !!!.   -    &A **$88011*881OOD//)::211*##""<<3//)((#**$""00)11+ Ȳ%         @[       F8S   *C   -= %  '  -( 6Ǽ" -G   "   % '$:$$ **%..(%% !!## ))#!!::2 Ű           1$  )12'  ߺ       $0  ͵'&#.   )M % 'N =  &300)    *#          #-  !"       iWG(*+  :     1 b % %- $      0@    #         4(@ #0B-;&     !    "     ˭䰰ii}㖖   4"%                   һ-7.$ (&5(2Q  !  "   NNDપѸvvVVJppa""--&ccx(($>>4NNC  ()            7+:  ! # O Ϳ<     -&   '    eeV!!44-bbU(("OOD--'ppaXXK<<3 ;;3YYK              .& $   DX1E(<       "# !!<<5 pp`..( KK@####ppaCC:;;266.$$ //)??6GG>] IDAT   !    %9 !       3 ) .  " %  «J^9л & 0       ,    5  & ! "'|EE<JJ@//(@@8&& xq--'ii[VVJ__QII?XXL         $"       #   !     2"  ƶ"(+1"' !#  !G?^   hhZhhZ XXL        .0   (     #    0   8          "'           -#            %)"3C  $  &% &$/ ,* !!(("LLA""""     Ul&$     O>Y          &      ' %    ,(%-  ,*2gg|<<4UUm!!00*991 && ""ʯ 3  '         "    ,     !9>"       ʷE     @.X'(6 $$;;3pphh} NND$$ ##$$ ##>>5              [)F&t 9"  ! #      Һ0       0  <<4yyh  ܣ55. (    $             1    Ӿ J68         owwf w 44.77.BB8>>5. 991<<4''"LLB 33+EE< s#  ** Yt    +Q@[         "          %  .0 (7!!$$??6   ## ..' 44- 5/        ?c     N>W         #  $$#*  ,    $   ! A <5C     "       8      +   02SԹ   !     $  "*   10-V  *  )#'6@$%   !       (3 +   '"$. '  א݊󔔣嚚˹A ./; # &  !& !&0" !&H :!      &  *     *    6         ddy~~ee{oo隚bbw//)  ((#II? # 3/  5"   5      2 2   !  $QFX'!  彧W  V IDAT"  rBB8lljj[ hhZ%%  3Q @    ~Yw0  ! N@L    #    +)     2         & D--'GG> (("00* KKA770??6$$66/8808805+' 9    ,"+ ' "       5    !  /0#  !#  !  YYLmm^66/00*(("//)//)II?bbTffXddV#L ,?&%    Jb=* 4  ? VFX       $&  "1--        2     1G   3'   Bd     "%QCQ   K    7 B  #  %      $    ')  *A         >Q   @#Z( "      & #     "(Z '  +   =O *        + !   $     &1&  !        ۹ #,      !'T #$ % /,!2       &     !   $1; A.8     @)T 8 )    5@     E , $-. :\"          %     1 e ֵ        ! #     #+         & A%D     $*     % %06  & "")        3.4    (# 9( +     +   % "       "      6     5  / &  &B  !0              * ):   %/"U     G IDAT  /     1   %=  "  %%              %     R-  % !J)# @    *4 0?# '>  ,(      3 ٰƛ    .D @ %4   # )# !1     .:;(4    "+$#   2''  8)    #  % 6  93    " 45      /,3(,(& .0 +-  %,   $" %   "'-C   츺    2  *%   (             31  * %& !!   ')Ϣ9   " " 3  #$;       ,&"   A      %#( B   " 0') :M     0.'  #*# *2        ===   0G ' F.!J~5<# 84""&  '   Om'   TEV   %$$   87= *$   $A-%4 " 7#;32J     %          0 #$!(# // # **6 (# >  & 2G      8$D  %    0//      -    *1%"+i'8! ,/7,? "36         *"I &() ,),)3.  \ctΞ   %+&$/6")'      * ) :4  Q"'    ''٫%   EOb!2     -/9!=>&/ ,. !       !!  ;   '" #   & +:8 " w IDAT##    0' (9!J   ,      "/57  !      .-   ο+%(Ը %:  &     ",    $ 9 (2% , 9      *   M    -% &      (-3 ;  > #3$ !.  "           +E     +(   !-4"!28 9f6 ! /#C               #!$(+  6EA  1O   .)9    %     &* !      (('+%?>00!       61% !&   6   ۬-C #2!    ,K$)   232K+       $          !<  6 3U) ,&   9 ۹        ')1/+  )    " #"!$# He% )/*UB\ /%8"0ȥ &        +9!#   # C$"91 +ƵB "      !$   !& ,*F <%23B : "7 $:(    %   # &   # EEV   34  02  On "   ) YGaƮ%>-+1 "-O $7 &4-  !%&%,     "#     ))0 *$<*.¨       Rm '     RES/2++/" &"     $(  0:& 39<  &7)"  (  %!1&+ )3α+-(%-  !     (!        !!ڧϦU)a EY8;@. @1    b IDAT   -'B   ٷ'-'*$ $#   '2(+ $,'   '  1T        OCK +$ݦ3/ / '1  -'   " 3"       $%   $3!F8    No      $ 6  ULJ1 #97>E+(@3. 27#  ! %7  +3#  %6 )@ )  %&B2H  &3     'Gf"  :  , ** >ON>*#='.  -1L $ /M   ) ! %  #'%    (  ?K  "$ 10'G     Qh4  "$ ,,; ,$LL:՗à .!%)(.Z ##    )!2" '     '(  ,L*%00%/#"! +(     Om)  # '-  QP@  73(     +35  "( "3    *,5 (   !% 2# +#,L %      $#  )?!2 (    (    ;U/ $ B*"&>>    - V      ; /  T)@A -[     & $    "    !        8 2   %     ' 3E         51/ $!%     '#% $&0 ǿSQO %2 %)$5  ,          !                  eehRW%,  %!1 '%  +!     Wc5%             ./0 /&$&3     !      >Y)      !#     97;&        )#          |}% IDAT  ,           # $0!$           :NUd4 ( (               &&*1   $',     ##$Qg##  "         G=J(1 ! . &!  !)      "                   !    612(.  E 2 !                       %&$      !,!&       "!                   $$&        #1     +  ,$   @  &                  -= !# *`l~dC*.-0      !   4+?- &              -%2\K2޺˼  $*K2    #  3R!)'  '2)           ,˩     !$.       "             />@DGٿ   /  !   '+.             =#   !08zݙ˼        "#    ! +    ߻   4 '"= & #*            Ū !  & +$'  0            #/ xIDAT  "  *,      $  +       -2E$/>ʟ&!    -> #* ߧ"    &#'    5(Ef 1G       %Űÿ       0&R    CL6IǞ $Խ             ('TLJQ, ->3 '  .   *       ("           㧭 (M?D  %     *                  '2' ",   #2         $9  +":  &.پ          !&2    * ) 6+*&!   &     CMVA3   ' &,( 4a   +CG         +,% ݫ)2!*+' (9" +') %) "'      = L]   '5  M22&' !+c %4.5    %KU[  ! $=/󪳽 A8   1 -     TSR     6CR:0! :  1M '@$& +  2gIENDB`libqxt-0.6.2/doc/src/images/qxttreewidget.png000066400000000000000000000235351215241066400212420ustar00rootroot00000000000000PNG  IHDR@ssRGB7MS siCCPiccxgPTYϽs@shD HIdQn2$L "AD"QPN#2"**j~oչO}T}7Td9II4RpHv hNj'fe.C&@8!sR9BNr,7R_̴da v2/A!p7N\o?!#|eʴS+̉' %׈k9`U4& ΀Np\-p@K0ށ%CҐ"@F O ¡C9n*: :]n@CCh>L<l p gy>Oe< "D]8 H(HR#H7ҏCAQJ(]%RPQE*ITu5G}Arh AgFt;*z=~` c1EØ6%fb:X+76VbOa/bS8"Ngsƅx\\9׃Mxuo;)J`x.Bp0NxC$UD_bq'xx8A@I0R:i! L ےCi}&S{1WlXXذ+ NldQ)g)w(sxq qt!՛D-6SoPghX͉ƥюѮ&]@wWS pc3 ?34 c@-$Ltc&2g̏vQ{%[%%dl ڤF>J+I;I'H~"іɔ9"sUfN!k)ˑ-=#HӖ˖;&7 ",_)E~N`PУ0HWVS,SBIBN)QBOi^YNU9]NyPyIҦDVV-SUWSTRQkQ{WgǪRW_`iiԘaIXYָ&YF3E^FuX6m]}G1Չ93 |oU1]nnSS/WS~~~/&  i݆iq&v^cu:QGML|653囶Κ՘lv9|yig,ԵLlYZaͤUUZ:F&¦晭-׶vN.+{{}6Kc)驳ss󼋉K%W~17y7[ۼ6>:*gڞ|n/ZOo_j~~9~6k^޿qf@z@o %0,)p114H-VLH\HW(6401taLF76lpcč6Q6El: oQY9qr˸QVQQVѥ31V1bfcmbc^ǻ/&x'HXN JlK%'x lJIOXL{S ]i y ]3 gP l޺wtslT6'7G9gW6muۡ{w1e]] n;O>og.?Xc܏{W[pРSO?U/z`iL dtҬ^:ʔ tFqy!¡C ϊJʒOUU#m5r5{ks=Z+_[Xhu.u02=ol?>(Xɾ&f%eTة?;ժZl+< N~K/g|('Oʟ=]6„uOr&_ǧӊM3F3ggXbe˥?ּ|_ O^o.,<}ni?}^TYs/I"D. r \@"D. r \ 6UhD@ SozTXtauthorx P+- sIDATx \MNj -)iqCL*S2˯o)5Z"%P 3BvI3cMPQ8=h}9|YNʪg)߅ : LU~~!?/H ij:z _S&ޫ$d߹ LwЫW`հcedAЦLwEjjjnn.Kp8暚ZI90+=*HD⽋-b)۶mw5A3_XGb xyjj_cU_>F{֝.Mv}VoY{= oӣ"tH{FF#4l3 cryFdE^=HG&&&1k`G,mzT\9q` ]xڵk׾}Ё[ ˗޶469rԨ<ê'Ǜ7o\`4t`& 3QTTtrrɡje9@/{YYٲG1Hq⪪JbOO`kc a[k6n1۫TBoPYQ|J~ ,oێ:?~r۷(?nٍR?fYYhQi/gL SN1a;~$ƺАZT- R >6U~֭?hk/^_/_6"(8؝:Ξ37\:|]\z-s_@rbLHz;+C^<Bm--LФy@*M?>|;OM=zDAa?_ +%9ws򴵵Ƿ#)׈166ܓ^sЦ MŶ'0~j3TwPAWrrr0N,44O>Xp7{cԎn&\yEEeG '(@k4!4c(ECh"iIrcԨQ?lJL̚X!&/A>724 vr]V^Qv]1g/{SQQtP ɣVMMŊڳښҞ't8^__ONFffLjn6AW5 i$Ξ=l䩍z1MIHIIUW髪*);bE&V0{Ǵ۩ڗݺ˂([~~ -ncw /))5//Íiꫣ}{BmmmEE[@n*wKb::ڬMJFV˝;:.ɹ:9s== _~unOiTޛ6m~q~r/Ŷ狧kH ;nQ::&"6nNa)eݟD_pGoMXaq&>LVV.W ij߰:;C|kks1cxyǭ[ rHb;zc׭LH ЕU ;ttu c?ӆlM?y"esgO)?bIdkC} H[9g"Kp8~d)VKg:ǁG=j#r`nnN.+6 b~A15 C‡ԱRNL:L^T`)VSN<֐:KЁr:}箘})]L0<99Me ͓`ºgM74S<  -=7#V5[`cc*%$Og表駔jj*}f@_䪨ѣM߿ͶN컹^t{m [=MMIKKkDDF sݻwYL`?L@?nf63cQP`ׯ;dwzURcH֭^ƙV[6CFmBb׮&N7LH⼔;@_aoۖ`##h (I9.ǂC/VuТ udo?|هnܰ^Νբñq-:/3ƛH[7o8Dx?**ܝ!8y#x TL,Ե3*Cی5%7 ))@mO}*"=0,=0H[__OmFGG  iU9ٯJIIIÆ >*,,:ujEEF#..N]]]JJn^OOOZZz(dρQe큝W^PWWW#kkkجhDWWã._QWWG7Ι3'$$iiiW\A!ۿFEh qAHhiiQeee\XX͖۷o_cˡ晌!,끙 ~EzI=zxQG111̙3\.=t Z=02*~޶@p`C70q O>0&i7ώ|7cǎ)++E޳c5dy[Pe /Yf arrnݺcnPTT@ bbb@]29::6[;w^z^(ҞB";vX|9 &M4~x3#{̘1|ǃ |}}كBrTD]?.vcC ID|>0At`AЁXNda#%$ΓuRHD> kai^dddI\fj*VK9y2:0u`1ཟ~UR,:yсq-5{z-,s`BZuk='?\OVV6:0?e]S Ѿ#* 7nX"puCC3|h`h(`wyfʥ%LFRSW3bX婸Q.dDN(Rl>zW7GzÆsRT"=ׁ\f;vlo7o֚k5Zj K,o|xwwO3fǶw sRT…4k/N8a(} LM}{ӽx6Aukc?kbd! ҳρ5?477̼1Mku7ls']tIᡡfBYY:0Bdd\3@~\ BJ|w3o[Iʪs'%xfߺ%++ࡤ?$#-&&Unp:\gϞQP6>}*rIG$~'} lV_YEgϞ^O8fd 4[ H_DD"䤀 _~AJ4Jĉ"s3sښ3TnN^{AMHC $~͛7nal@`EßI=zF2k4݋0xp]BBV? [!%HҊH^z4/DIzobis=9'7Nh7- y|19ծ]|'OꡯoeKCTַLQ*23obqKOXDv rϘ%LM=5 me5GR&OHϣ ?wԠ.]uk8,^f + =<`džm"#ª`"\Fef*~fPII \yyynbpChGG'v^(ŋkb,q|/˃H,?寧fcHJiΜ[RRM}^=w7W3 ErV04""|}`-Sxa3;;;2$vm1Cc>޴G9@LL-qt7wVyyg {ЍAz/O~d!+ ߴy(Ѫh_ ?OI9F6IXZNvrr,n~]zbtwxX~Ò牝4''.]fϚ s8.ul\w"rh=TTDįNK`TԚC4 /bŋ"rLd)%խe; KbHe))cG&YL&9SJf|/urmmxmW_}әg/訫_lzseUW׸y gD}$ W3Pͺсedd={106%[I=wCC!EuqH2V@9Eu&D/(u`Kˉ⻏K|t;wg`,6*ɱ3}oT|MS;[xu_#"|3564Ox<"a… ?ӿ>EC=!-U>822`ҕ+W-nnnuuu6[n[nQiDRϟ_[[+=~ ~!'Nt|`u*Yt޽{B<՛ FWfddЛϟ]rjݼy~FDD̚հPҞFŶ~ɏffyժU$ hzz\\\qqӕwI 0ǏCyzk׮FŹHLUyؼyׯa@i&cYYԚrEEɜx. :tfРw MǷ_0h =y*M, X ^%ѣG/FFF AyTTTUUU#GLJJDJJʂ lmm. HTbjjj`EW>_ TYlfG//صkBX/^~-߹sիWP8"N|Kvsshu̙>⪫5ݫ فQet`^myu6vXb533޽Y=z {졮 cccBC,hCBB1!!f{3f  6Uf)"rqGvc,APeqB# :0 2Dd)*4cvUByy)S@с[m&- \.[80 lt9#*IENDB`libqxt-0.6.2/doc/src/modules.qdoc000066400000000000000000000120201215241066400166720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the documentation of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \module QxtCore \title QxtCore Module \keyword QxtCore \ingroup modules \brief The QxtCore module extends QtCore and contains core non-GUI functionality. All other Qt modules rely on this module. To include the definitions of the module's classes, use the following directive: \code #include \endcode */ /*! \module QxtGui \title QxtGui Module \keyword QxtGui \ingroup modules \brief The QxtGui module extends QxtCore and QtGui. To include the definitions of both Qxt modules' classes, use the following directive: \code QXT = core gui \endcode */ /*! \module QxtBerkeley \title QxtBerkeley Module \keyword QxtBerkeley \ingroup modules \brief The QxtBerkeley module provides a Qt interface to the Berkeley DB. berkeley db is in wide use where relational databases, especially SQL, are not desired due to heavy overhead or its programming complexity. QxtBerkeley provides you an extremly easy to use interface to the fast and stable file based berkeley database. The API is designed after Qts tulip container classes.

Platform specific notes

Windows

On Windows the buildsystem is unfortunately unable to detect the berkeley db library on your system automatically, because of the wide differences in naming scheme.
You will have to add the library yourself:
MSVC: \code configure.bat -I C:\BDB-MSVC\include -L C:\BDB-MSVC\lib -l libdb46 (or libdb45) \endcode MinGW (http://mathieu.carbou.free.fr/wiki/index.php?title=Berkeley_DB_for_MinGW) \code configure.bat -I C:\BDB-MINGW\include -L C:\BDB-MINGW\lib -l db \endcode

Linux

If you have issues compiling QxtBerkeley with your distributions bdb package, it is suggested that you try the upstream version from http://www.oracle.com/technology/software/products/berkeley-db/index.html */ /*! \module QxtNetwork \title QxtNetwork Module \keyword QxtNetwork \ingroup modules \brief The QxtNetwork module extends QtNetwork */ /*! \module QxtSql \title QxtSql Module \keyword QxtSql \ingroup modules \brief The QxtSql module extends QtSql with serializable queries. */ /*! \module QxtWeb \title QxtWeb Module \keyword QxtWeb \ingroup modules \brief The QxtWeb module provides tools for creating web services using Qt. QxtWeb provides tools for creating event-driven web services using Qt. The general usage pattern is as follows: \list \o Create a QxtAbstractWebSessionManager object, such as QxtHttpSessionManager, for each protocol that can interface to the service. \o If using QxtHttpSessionManager, select a connector plugin, such as QxtHttpServerConnector. \o Register a QxtAbstractWebService factory. The factory is invoked each time a new session is created and returns a service object for that session. QxtWebServiceDirectory allows you to register multiple services and selects between them based on the path. \o Invoke QxtAbstractWebSessionManager::start() to begin accepting connections. \endlist When a new visitor connects who does not belong to a session, a new service instance is created. When a request is received, a QxtAbstractWebService::pageRequestedEvent() is dispatched to the service. When the service is ready to respond to the request, it posts a QxtWebPageEvent to the session manager. This is done asynchronously; there is no requirement that the pageRequestedEvent handler must respond to the request before the function ends, but such a response must eventually be posted or the web browser will eventually time out. */ /*! \module QxtZeroconf \title QxtZeroconf Module \keyword QxtZeroconf \ingroup modules \brief The QxtZeroconf module implements configure free service discovery */ libqxt-0.6.2/doc/src/pages.qdoc000066400000000000000000000243631215241066400163360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the documentation of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \page index.html \keyword Qxt Reference Documentation \title Qxt Reference Documentation Qxt, an extension library for Qt, provides a suite of cross-platform utility classes to add functionality not readily available in the Qt toolkit by Nokia. \raw HTML
Getting Started Api Reference
Technologies About
\endraw */ /*! \group modules \title Qxt's Modules Qxt consists of several modules, each of which lives in a separate library: \table 80% \row \o \l{QxtBerkeley} \o The QxtBerkeley module provides a Qt interface to the Berkeley DB. \row \o \l{QxtCore} \o The QxtCore module extends QtCore and contains core non-GUI functionality. \row \o \l{QxtGui} \o The QxtGui module extends QxtCore and QtGui. \row \o \l{QxtNetwork} \o The QxtNetwork module extends QtNetwork with RPC functionality. \row \o \l{QxtSql} \o The QxtSql module extends QtSql with serializable queries. \row \o \l{QxtWeb} \o The QxtWeb module provides tools for creating web services using Qt. \row \o \l{QxtZeroconf} \o Qxt QxtZeroconf module implements configure free service discovery \endtable To use one of these modules, add them to the QXT variable in your qmake project (.pro) file. For example: \code CONFIG += qxt QXT += network \endcode The QxtCore and QxtGui modules are included by default. To link only against QxtCore, do this: \code QXT = core \endcode \sa {Qxt's Classes}, {Qxt's Namespaces}, {Qxt's Functions} */ /*! \page classes.html \title Qxt's Classes \ingroup classlists This is a list of all Qxt classes. \generatelist classes \sa {Qxt's Modules}, {Qxt's Namespaces}, {Qxt's Functions} */ /*! \page namespaces.html \title Qxt's Namespaces \ingroup classlists This is a list of the main namespaces in Qxt. \generatelist{namespaces} \sa {Qxt's Modules}, {Qxt's Classes}, {Qxt's Functions} */ /*! \page functions.html \title Qxt's Functions \ingroup classlists This is a list of all Qxt functions. \generatelist functionindex \sa {Qxt's Modules}, {Qxt's Classes}, {Qxt's Namespaces} */ /*! \page tech-ipc.html \title Inter-Process Communication Qxt provides you with a range of IPC Implementations for different use cases. \raw HTML

Qt Signals and Slots over the air

QxtRpcService provides a facility to use Qt signals and slots over any QIODevice. It let's you connect two QObjects on the fly and marshals arguments for you. If all you want is a quick and easy solution to connect two Qt programs, QxtRpcService is for you.
On top of that, QxtRpcPeer provides a higher level implementation over TCP connections.

Qt in the cloud. Xml and Json rpcs

If you want to connect your qt program to an existing web service in the cloud, qxt provides ready implementations of common http based protocols.

\endraw \sa {QxtNetwork} */ /*! \page tech-web.html \title Web Service Framework \raw HTML

Webkit brings the Web to Qt, and QxtWeb brings Qt to the web. It lets you create web services within the Qt Toolkit. Typicall you'd implement a "Website", but its flexible enough to to let you mix websites with other content, other connection protocols, and other clients.

Sessions

At first, there is a QxtAbstractWebSessionManager. Typically you would use a QxtHttpSessionManager which utilizes http cookies, but it is entirely possible to use different session techniques. The session manager starts a session either by just asigning it a number you can later use to identify sessions, or by instantiation a session stack (if you set serviceFactory). The former is more like the traditional webapp flow, where a request does not leave any traces other then some persisted session data, after it is handled. The later technique leaves qobjects in the main memory for the time of the session. They can handle background tasks for the specific session, and even later notify the session user asyncronously. However, it does come at a cost.

Connectors. Protocol implementations.

Qxt can connect your services with a range of protocols. Currently those are Http and Scgi. It is not recommended to run the http connector directly as a frontend service on the internet. Instead use it for development, or on embedded devices within a trusted network. Scgi allows easy integration into frontend servers, such as apaches httpd.

The Services.

Finally, you will want to implement one or many QxtAbstractWebService which handle the actual requests from clients. Your service then receives a pageRequestedEvent, with the request from a client. It responds to it by posting a response via postEvent. Note that the default event distribution is single threaded. Blocking a service will block the entire server. However, you will rarely find sitations where you have to block, thanks to Qts excellent asyncronous api. A few convenience implementations are provided, such as qxtwebservicedirectory.html, qxtwebcgiservice.html,qxtwebslotservice.html

\endraw \sa {QxtWeb} */ /*! \page tech-log.html \title Pluggable Logging Framework \raw HTML

QxtLogger provides your application with an excelene framework for logging errors and debug messages in different levels. It can write to different backend plugins, such as QxtBasicFileLoggerengine , QxtBasicStdLoggerEngine

\endraw */ /*! \page tech-zeroconf.html \title Configure free service discovery \raw HTML

QxtZeroconf implements classes for announcing and discovering services on the local network, without the need for any user configuration. Commonly this is known as "Zeroconf". A computer in the Local Area Network could announce a "printing service", and other computers could find this service without knowing the topology of the network. QxtZeroconf implements multiple possible system backends, namely apples mdnsd, and avahi.

\endraw */ libqxt-0.6.2/doc/src/qt.index000066400000000000000000477150711215241066400160620ustar00rootroot00000000000000 libqxt-0.6.2/doc/src/qxt.qdocconf000066400000000000000000000122321215241066400167110ustar00rootroot00000000000000project = Qxt description = Qxt Reference Documentation url = http://doc.libqxt.org/0.6.2 language = Cpp modules = QxtBerkeley QxtCore QxtGui QxtNetwork QxtSql QxtWeb QxtZeroconf qhp.projects = Qxt qhp.Qxt.file = qxt.qhp qhp.Qxt.namespace = org.libqxt.062 qhp.Qxt.virtualFolder = qdoc qhp.Qxt.indexTitle = Qxt Reference Documentation qhp.Qxt.indexRoot = qhp.Qxt.extraFiles = stylesheet.css qhp.Qxt.filterAttributes = qxt 0.6.2 qxtrefdoc qhp.Qxt.customFilters.Qxt.name = Qxt 0.6.2 qhp.Qxt.customFilters.Qxt.filterAttributes = qxt 0.6.2 qhp.Qxt.subprojects = classes overviews examples qhp.Qxt.subprojects.classes.title = Classes qhp.Qxt.subprojects.classes.indexTitle = Qxt's Classes qhp.Qxt.subprojects.classes.selectors = class fake:headerfile qhp.Qxt.subprojects.classes.sortPages = true qhp.Qxt.subprojects.overviews.title = Overviews qhp.Qxt.subprojects.overviews.indexTitle = All Overviews and HOWTOs qhp.Qxt.subprojects.overviews.selectors = fake:page,group,module qhp.Qxt.subprojects.examples.title = Tutorials and Examples qhp.Qxt.subprojects.examples.indexTitle = Qxt Examples qhp.Qxt.subprojects.examples.selectors = fake:example indexes = $QXT_SOURCE_TREE/doc/src/qt.index headerdirs = $QXT_SOURCE_TREE/src sourcedirs = $QXT_SOURCE_TREE/src $QXT_SOURCE_TREE/doc/src excludedirs = $QXT_SOURCE_TREE/src/designer sources.fileextensions = "*.cpp *.qdoc" examples.fileextensions = "*.cpp *.h *.ui *.qhp *.qhcp" exampledirs = $QXT_SOURCE_TREE/examples imagedirs = $QXT_SOURCE_TREE/doc/src/images outputdir = $QXT_BUILD_TREE/doc/html tagfile = $QXT_BUILD_TREE/doc/qxt.tags base = file:$QXT_BUILD_TREE/doc extraimages.HTML = implicitshared.png \ logo.png \ note.png \ qxtbasespinbox.png \ qxtcheckcombobox.png \ qxtconfigdialog.png \ qxtconfirmationmessage.png \ qxtcountrycombobox.png \ qxtcountrymodel.png \ qxtflowview.png \ qxtgroupbox.png \ qxtheaderview.png \ qxtlabel.png \ qxtlanguagecombobox.png \ qxtlineedit.png \ qxtlistwidget.png \ qxt-logo.png \ qxtprogresslabel.png \ qxtpushbutton.png \ qxtscheduleview.png \ qxtslotmapper.png \ qxtspanslider.png \ qxtstars.png \ qxtstringspinbox.png \ qxttablewidget.png \ qxttabwidget.png \ qxttooltip.png \ qxttreewidget.png \ see.png \ warning.png HTML.stylesheets = stylesheet.css HTML.postheader = "\n" \ "\n" \ "\n" \ "" \ "\n" \ "
" \ "" \ "" \ "  " \ "" \ "Home ·" \ " " \ "Modules ·" \ " " \ "Classes ·" \ " " \ "Namespaces ·" \ " " \ "Functions" \ "
" HTML.footer = "


\n" \ "\n" \ "\n" \ "\n" \ "
Copyright © 2007-2011\n" \ "Qxt Foundation
\n" \ "Qxt 0.6.2
" libqxt-0.6.2/doc/src/qxtnamespace.qdoc000066400000000000000000000106231215241066400177220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the documentation of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \namespace Qxt \inmodule QxtCore \brief The Qxt namespace contains miscellaneous identifiers used throughout the Qxt library. */ /*! \enum Qxt::Rotation This enum describes the rotation. \value NoRotation No rotation. \value UpsideDown Upside down (180 degrees). \value Clockwise Clockwise (90 degrees). \value CounterClockwise CounterClockwise (-90 degrees). */ /*! \enum Qxt::DecorationStyle This enum describes the decoration style. \value NoDecoration No decoration. \value Buttonlike A style like in Qt Designer's Widget Box. \value Menulike A menu alike style. */ /*! \enum Qxt::ErrorCode The error Code dropped by QxtError \value NoError Everything fine. \value UnknownError An unknown error. \value LogicalError Something happened that makes no sense (e.g. you tryed to compare apples and bananas). \value Bug That should not happen. please report any ocurence of it. \value UnexpectedEndOfFunction Suddenly the function returned where it should not. please report this behaiviour. \value NotImplemented The feature you requested has not been implemented for this situation. this could also mean you are trying to compare apples and bananas. \value CodecError Something went wrong with some codec. Please check if your codec is supported. \value NotInitialised Somone tryed to call a function of an object that needs to be start() ed or something like it. \value EndOfFile The end of the Input has been reached. There is no more data. \value FileIOError File Input/Output Error. \value FormatError The Format of the input is corupted or not supported. \value DeviceError The Device of the Computer reported failure or we are not able to comunicate with it. \value SDLError SDL reported an error. \value InsufficientMemory Not enough memory to perform the action. \value SeeErrorString The Error has no definition here, but the Error String should tell you more. This is mostly used for third party errors. \value UnexpectedNullParameter NULL was passed where it shouldn't. \value ClientTimeout The Client didn't answer within the expected time rang. \value SocketIOError Socket Input/Output Error. \value ParserError Unable to parse the requested string or file. \value HeaderTooLong The Header that was passed for parsing was too long. \value Auth Authentication failed. \value Overflow Overflow protection triggered. */ /*! \enum Qxt::QxtItemDataRole Data roles for qxt models/views \value ItemStartTimeRole The starttime of a item in timebased views. \value ItemDurationRole The duration of a item in timebased views. \value UserRole The first role that can be used for application-specific purposes. */ /*! \enum Qxt::Timeunit Time units \value Second A second \value Minute A minute \value Hour An hour \value Day A day \value Week A week \value Month A month \value Year A year */ libqxt-0.6.2/doc/src/qxtnativeeventfilter.qdoc000066400000000000000000000077421215241066400215340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the documentation of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtNativeEventFilter \inmodule QxtGui \brief The QxtNativeEventFilter class provides a native event filter to access platform specific events. QxtNativeEventFilter provides access to platform specific native events without the need of subclassing QApplication. \bold {Note:} QxtNativeEventFilter requires QxtApplication. Example usage: \code qxtApp->installNativeEventFilter(myObject); class MyObject : public QxtNativeEventFilter { public: ... bool x11EventFilter(XEvent* event) { if (event->type == ...) { ... } return false; } bool winEventFilter(MSG* msg, long* result) { if (msg->message == ...) { ... } return false; } bool macEventFilter(EventHandlerCallRef caller, EventRef event) { if (GetEventClass(event) == ...) { ... } return false; } }; \endcode \sa QxtApplication::installNativeEventFilter() */ /*! \fn QxtNativeEventFilter::~QxtNativeEventFilter() Destructs the native event filter. The native event filter is automatically removed from the application. \sa QxtApplication::removeNativeEventFilter() */ /*! \fn QxtNativeEventFilter::x11EventFilter(XEvent* event) Filters X11 events if this object has been installed as a native event filter. The events are passed in the \a event parameter. In your reimplementation of this function, if you want to filter the event out, i.e. stop it being handled further, return \c true; otherwise return \c false. \sa QxtApplication::installNativeEventFilter() */ /*! \fn QxtNativeEventFilter::winEventFilter(MSG* msg, long* result) Filters Windows events if this object has been installed as a native event filter. The window messages are passed in the \a msg parameter and the return value of the window procedure can be set to the \a result parameter. In your reimplementation of this function, if you want to filter the event out, i.e. stop it being handled further, return \c true; otherwise return \c false. \sa QxtApplication::installNativeEventFilter() */ /*! \fn QxtNativeEventFilter::macEventFilter(EventHandlerCallRef caller, EventRef event) Filters Mac events if this object has been installed as a native event filter. The events are passed in the \a event parameter with the \a caller parameter. In your reimplementation of this function, if you want to filter the event out, i.e. stop it being handled further, return \c true; otherwise return \c false. \sa QxtApplication::installNativeEventFilter() */ libqxt-0.6.2/doc/src/qxtslotmapper.dia000066400000000000000000000042241215241066400177630ustar00rootroot00000000000000]KFPʙ'3nrHT8B֒ PgJB0x*4Lӣi?<.}fa_Qϒy/bŇyW+L]o|DO');Q_A㛋hs\q4(xY]<QŸY%ޏork=sE0MzIdU],TCΐycQ/nyU\Wu.xWZ.H`bNtq~EKfU"I~l]\N6#ebBgyrQvǝ꽋4wޭ5"lB2;zr?|qfwop{y TYU6"0{dY݈Q7tZ>U " "!$B w5Dr2KxtaǮ^ρ$7_>Ay/D nI]ÙOg//N!mMDmC\vA^ˠ eGJR3ַBKqP Wi[$qJcu%܀>)ϒ8a4jgPuc#sckfTqpE:0 4c Ja+:T#Vwɼ݀eαF,{XVҶъ(V}X.=+E8PN3.4o9OeA21enYLa@b,`,0BȻ:p sVk`9C+z@=B)Ykj8l$!g4IāGmx@W(ɟV琴gF:KKm-)C[ l%jCvVSPTbNDrjՇ;[e剩qnŧkQtݤtCTʀ1ɀMBW(˵p(}#T"q^30u9%W]yLu*3c0؁ajr&P,Wֲ*GuUrQ Qxx( pvDYl#uPB 'selfyCɥ6J//ҺCo0 +ˢ( MtBP0n@áM_4ʢ[/2L)&hXyRW0zu5vw0Trwl<`s#_Z7Υv( ^IRRJzQKvbQZڪE/]]W||t6*[v &*CsڃVZ}CǾ9\|%}{꒨VopXA+Jsi~{Dy|(D43ZU+j s,ݓ'*η.;6v?D 2\kISWtl,Ubuzo`pg%>~U`P $tx]mS'FBCƯc!⺵al?bCh _To\}hlibqxt-0.6.2/doc/src/stylesheet.css000066400000000000000000000026541215241066400172710ustar00rootroot00000000000000h3.fn,span.fn { margin-left: 1cm; text-indent: -1cm; } a:link { color: #004faf; text-decoration: none } a:visited { color: #672967; text-decoration: none } a.obsolete { color: #661100; text-decoration: none } a.compat { color: #661100; text-decoration: none } a.obsolete:visited { color: #995500; text-decoration: none } a.compat:visited { color: #995500; text-decoration: none } td.postheader { font-family: sans-serif } tr.address { font-family: sans-serif } body { background: #ffffff; color: black } table tr.odd { background: #f0f0f0; color: black; } table tr.even { background: #e4e4e4; color: black; } table.annotated th { padding: 3px; text-align: left } table.annotated td { padding: 3px; } table tr pre { padding-top: none; padding-bottom: none; padding-left: none; padding-right: none; border: none; background: none } tr.qt-style { background: #96E066; color: black } body pre { padding: 0.2em; border: #e7e7e7 1px solid; background: #f1f1f1; color: black } table tr.qt-code pre { padding: 0.2em; border: #e7e7e7 1px solid; background: #f1f1f1; color: black } span.preprocessor, span.preprocessor a { color: darkblue; } span.comment { color: darkred; font-style: italic } span.string,span.char { color: darkgreen; } .title { text-align: center } .subtitle { font-size: 0.8em } .small-subtitle { font-size: 0.65em } libqxt-0.6.2/examples/000077500000000000000000000000001215241066400146415ustar00rootroot00000000000000libqxt-0.6.2/examples/berkeley/000077500000000000000000000000001215241066400164435ustar00rootroot00000000000000libqxt-0.6.2/examples/berkeley/addressbook/000077500000000000000000000000001215241066400207435ustar00rootroot00000000000000libqxt-0.6.2/examples/berkeley/addressbook/addressbook.pro000066400000000000000000000003001215241066400237560ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . CONFIG+=qxt QXT+=berkeley HEADERS += contact.h mainwindow.h FORMS += mainwindow.ui SOURCES += contact.cpp main.cpp mainwindow.cpp libqxt-0.6.2/examples/berkeley/addressbook/contact.cpp000066400000000000000000000004351215241066400231040ustar00rootroot00000000000000#include "contact.h" QDataStream &operator<<(QDataStream &out,const Contact &c) { out<>(QDataStream &in, Contact &c ) { in>>c.name; in>>c.phone; in>>c.address; return in; } libqxt-0.6.2/examples/berkeley/addressbook/contact.h000066400000000000000000000005421215241066400225500ustar00rootroot00000000000000#ifndef CONTACT_H #define CONTACT_H #include #include #include #include struct Contact { QString name; QString phone; QString address; }; Q_DECLARE_METATYPE(Contact); QDataStream &operator<<(QDataStream &out,const Contact &c); QDataStream &operator>>(QDataStream &in, Contact &c ); #endif libqxt-0.6.2/examples/berkeley/addressbook/main.cpp000066400000000000000000000004521215241066400223740ustar00rootroot00000000000000#include #include "mainwindow.h" #include "contact.h" int main(int argc, char ** argv) { QApplication app(argc,argv); qRegisterMetaType ("Contact"); qRegisterMetaTypeStreamOperators ("Contact"); MainWindow m; m.show(); app.exec(); } libqxt-0.6.2/examples/berkeley/addressbook/mainwindow.cpp000066400000000000000000000013611215241066400236240ustar00rootroot00000000000000#include "mainwindow.h" #include #include MainWindow::MainWindow() { ui.setupUi(this); hash.open("contacts.db"); initTree(); } void MainWindow::initTree() { ui.treeWidget->clear(); QxtBdbHashIterator it=hash.begin(); do { Contact c=it.value(); QTreeWidgetItem *item=new QTreeWidgetItem(ui.treeWidget); item->setText(0,c.name); item->setText(1,c.phone); item->setText(2,c.address); } while((++it).isValid()); } void MainWindow::on_addButton_clicked() { Contact c; c.name=ui.inputName->text(); c.phone=ui.inputPhone->text(); c.address=ui.inputAddress->text(); qDebug()< class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); private: Ui::MainWindow ui; QxtBdbHash hash; void initTree(); private slots: void on_addButton_clicked(); }; #endif // MAINWINDOW_H_INCLUDED libqxt-0.6.2/examples/berkeley/addressbook/mainwindow.ui000066400000000000000000000067131215241066400234650ustar00rootroot00000000000000 MainWindow 0 0 715 756 QxtBerkeley Address Book example 0 27 715 706 Name Phone Nr. Address 0 0 Add Entry Name Phone Address Qt::Horizontal 455 20 add 0 0 715 27 0 733 715 23 libqxt-0.6.2/examples/berkeley/berkeley.pro000066400000000000000000000004101215241066400207620ustar00rootroot00000000000000###################################################################### # Automatically generated by qmake (2.01a) Fri Jan 16 22:48:34 2009 ###################################################################### TEMPLATE = subdirs SUBDIRS += addressbook xmlstorage libqxt-0.6.2/examples/berkeley/xmlstorage/000077500000000000000000000000001215241066400206305ustar00rootroot00000000000000libqxt-0.6.2/examples/berkeley/xmlstorage/main.cpp000066400000000000000000000004471215241066400222650ustar00rootroot00000000000000#include #include "mainwindow.h" #include "node.h" int main(int argc, char ** argv) { QApplication app(argc,argv); qRegisterMetaType ("XmlNode"); qRegisterMetaTypeStreamOperators ("XmlNode"); MainWindow m; m.show(); app.exec(); } libqxt-0.6.2/examples/berkeley/xmlstorage/mainwindow.cpp000066400000000000000000000007571215241066400235210ustar00rootroot00000000000000#include "mainwindow.h" #include #include #include #include MainWindow::MainWindow() { ui.setupUi(this); model.open("xml.db"); ui.treeView->setModel(&model); ui.treeView->header()->resizeSection ( 0,300); } void MainWindow::on_actionLoad_triggered() { model.loadXml(QFileDialog::getOpenFileNames (this, "Load Xml file",QString(), "Xml File (*.xml)")); } void MainWindow::on_actionQuit_triggered() { close(); } libqxt-0.6.2/examples/berkeley/xmlstorage/mainwindow.h000066400000000000000000000005501215241066400231550ustar00rootroot00000000000000#ifndef MAINWINDOW_H_INCLUDED #define MAINWINDOW_H_INCLUDED #include "ui_mainwindow.h" #include "model.h" class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); private: Ui::MainWindow ui; XmlDbModel model; private slots: void on_actionQuit_triggered(); void on_actionLoad_triggered(); }; #endif // MAINWINDOW_H_INCLUDED libqxt-0.6.2/examples/berkeley/xmlstorage/mainwindow.ui000066400000000000000000000110761215241066400233500ustar00rootroot00000000000000 MainWindow 0 0 574 603 QxtBerkeley XML Storage example 0 25 574 557 <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Candara'; font-size:11pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Welcome to the QxtBerkeley XML Storage example.</span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You can load some xml files by clicking on the menu File-&gt;Load and scroll through the parsed files. </p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note that parsing xml files takes a while, even with the QXmlStreamReader it is using.</p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Then open and close the application, and see how very fast it is starting up, thanks to the already parsed nodes stored in a QxtBdbTree.</p></body></html> true <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Candara'; font-size:11pt; font-weight:400; font-style:normal;"> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">QPatternist</span></p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If you are using Qt 4.4, you can type in an XQUery expression here, and press execute, or hit enter. The Query will evaluate on the database and imidiatly show you the results.</p> <p align="justify" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If you are using a lower QT version, this does nothing.</p></body></html> true execute 0 0 574 25 File 0 582 574 21 Load Quit libqxt-0.6.2/examples/berkeley/xmlstorage/model.cpp000066400000000000000000000121541215241066400224370ustar00rootroot00000000000000#include "model.h" #include "xml2bdb.h" #include #include #include #include XmlDbModel::XmlDbModel(QString db):QAbstractItemModel(),QxtBdbTree() { open(db); } XmlDbModel::XmlDbModel():QAbstractItemModel(),QxtBdbTree() { cache.root()->children=-1; cache.root()->node=root(); } bool XmlDbModel::open (QString file) { bool p= QxtBdbTree::open(file); cache.root()->children=-1; cache.root()->node=root(); if(canFetchMore(QModelIndex())) fetchMore(QModelIndex()); reset(); return p; } void XmlDbModel::loadXml(QStringList files) { reset(); QProgressDialog d; d.setLabelText("Loading xml files into database."); d.show(); d.setMaximum(files.count()); for (int i=0;ichildren=-1; cache.root()->node=root(); if(canFetchMore(QModelIndex())) fetchMore(QModelIndex()); reset(); } int XmlDbModel::columnCount ( const QModelIndex & ) const { return 3; } QVariant XmlDbModel::data ( const QModelIndex & index, int role ) const { Q_ASSERT_X(index.isValid(),Q_FUNC_INFO,"invalid index"); if(role!=Qt::DisplayRole) return QVariant(); if(index.column()==0) return cache.fromVoid(index.internalPointer())->node.value().name; if(index.column()==1) { switch(cache.fromVoid(index.internalPointer())->node.value().type) { case 0: return "NoToken"; case 2: return "StartDocument"; case 3: return "EndDocument"; case 4: return "StartElement"; case 5: return "EndElement"; case 6: return "Characters"; case 7: return "Comment"; case 8: return "DTD"; case 9: return "EntityReference"; case 10: return "ProcessingInstruction"; case 1: default: return "Invalid"; } } if(index.column()==2) return cache.fromVoid(index.internalPointer())->node.value().value; return QVariant(); } QVariant XmlDbModel::headerData ( int section, Qt::Orientation orientation, int role) const { if(orientation!=Qt::Horizontal) return QVariant(); if(role!=Qt::DisplayRole) return QVariant(); if (section==0) return "name"; if (section==1) return "type"; if (section==2) return "value"; return QVariant(); } QModelIndex XmlDbModel::parent ( const QModelIndex & index ) const { Q_ASSERT_X(index.isValid(),Q_FUNC_INFO,"invalid index"); QxtLinkedTreeIterator it; it=cache.fromVoid(index.internalPointer()).parent(); Q_ASSERT_X(it.isValid(),Q_FUNC_INFO,"invalid iterator inside valid index (wtf?)"); if(!it.isValid()) return QModelIndex(); if(it==cache.root()) return QModelIndex(); int row=0; QxtLinkedTreeIterator et=it; --et; while(et.isValid()) { --et; row++; } return createIndex(row,0,cache.toVoid (it)); } QModelIndex XmlDbModel::index ( int row, int column, const QModelIndex & parent ) const { if(canFetchMore(parent)) const_cast(this)->fetchMore(parent); QxtLinkedTreeIterator it; if (parent.isValid()) it=cache.fromVoid(parent.internalPointer()).child(); else it=cache.root().child(); it+=row; if(!it.isValid()) return QModelIndex(); return createIndex(row,column,cache.toVoid (it)); } int XmlDbModel::rowCount ( const QModelIndex & parent ) const { if(canFetchMore(parent)) const_cast(this)->fetchMore(parent); QxtLinkedTreeIterator it; if(parent.isValid()) it=cache.fromVoid(parent.internalPointer()); else it=cache.root(); if (it->children<0) return 0; return it->children; } void XmlDbModel::fetchMore ( const QModelIndex & parent ) { QxtLinkedTreeIterator itl; if(parent.isValid()) itl=cache.fromVoid(parent.internalPointer()); else itl=cache.root(); QxtBdbTreeIterator it=itl->node.child(); int cc=0; while(it.isValid()) { XmlDbModelCacheItem ci; ci.node=it; ci.children=-1; itl.append(ci); ++it; ++cc; } itl->children=cc; } bool XmlDbModel::canFetchMore ( const QModelIndex & parent ) const { QxtLinkedTreeIterator itl; if(parent.isValid()) itl=cache.fromVoid(parent.internalPointer()); else itl=cache.root(); return(itl.child().isValid()!=itl->node.child().isValid()); } libqxt-0.6.2/examples/berkeley/xmlstorage/model.h000066400000000000000000000023031215241066400220770ustar00rootroot00000000000000#ifndef MODEL_H_INCLUDED #define MODEL_H_INCLUDED #include #include #include #include "node.h" #include struct XmlDbModelCacheItem { QxtBdbTreeIterator node; int children; }; class XmlDbModel : public QAbstractItemModel, public QxtBdbTree { public: XmlDbModel(QString db); XmlDbModel(); bool open (QString file); void loadXml (QStringList files); virtual int columnCount ( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual QModelIndex parent ( const QModelIndex & index ) const; virtual QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount ( const QModelIndex & parent = QModelIndex() ) const; virtual bool canFetchMore ( const QModelIndex & parent ) const; virtual void fetchMore ( const QModelIndex & parent ); private: mutable QxtLinkedTree cache ; }; #endif // MODEL_H_INCLUDED libqxt-0.6.2/examples/berkeley/xmlstorage/node.cpp000066400000000000000000000006371215241066400222670ustar00rootroot00000000000000#include "node.h" QDataStream &operator<<(QDataStream &out,const XmlNode &c) { out<>(QDataStream &in, XmlNode &c ) { in>>c.name; in>>c.value; in>>c.type; return in; } QDebug operator<<(QDebug dbg, const XmlNode &c) { dbg.nospace() << "(" << c.name << ", " << c.value << ")"; return dbg.space(); } libqxt-0.6.2/examples/berkeley/xmlstorage/node.h000066400000000000000000000006751215241066400217360ustar00rootroot00000000000000#ifndef NODE_H_INCLUDED #define NODE_H_INCLUDED #include #include #include #include #include struct XmlNode { QString name; QString value; int type; }; Q_DECLARE_METATYPE(XmlNode); QDataStream &operator<<(QDataStream &out,const XmlNode &c); QDataStream &operator>>(QDataStream &in, XmlNode &c ); QDebug operator<<(QDebug dbg, const XmlNode &c); #endif // NODE_H_INCLUDED libqxt-0.6.2/examples/berkeley/xmlstorage/xml2bdb.cpp000066400000000000000000000017031215241066400226670ustar00rootroot00000000000000#include "xml2bdb.h" #include Xml2Bdb::Xml2Bdb() : QXmlStreamReader() { } void Xml2Bdb::read(QxtBdbTreeIterator root) { while (!atEnd()) { readNext(); if (isStartElement()) { readElement(root); } } } void Xml2Bdb::readElement(QxtBdbTreeIterator i) { XmlNode x; x.name=name().toString(); x.value=text().toString(); x.type=tokenType(); i=i.append(x); while (!atEnd()) { QApplication::processEvents (); readNext(); if (isEndElement()) break; else if (isStartElement()) { readElement(i); } else { if(text().toString().simplified().isEmpty()) continue; XmlNode x; x.name=name().toString(); x.value=text().toString(); x.type=tokenType(); i.append(x); } } } libqxt-0.6.2/examples/berkeley/xmlstorage/xml2bdb.h000066400000000000000000000005151215241066400223340ustar00rootroot00000000000000#ifndef XML2BDB_H_INCLUDED #define XML2BDB_H_INCLUDED #include #include #include "node.h" class Xml2Bdb : public QXmlStreamReader { public: Xml2Bdb(); void read(QxtBdbTreeIterator root); private: void readElement(QxtBdbTreeIterator i); }; #endif // XML2BDB_H_INCLUDED libqxt-0.6.2/examples/berkeley/xmlstorage/xmlstorage.pro000066400000000000000000000003421215241066400235360ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . CONFIG+=qxt QXT+=berkeley HEADERS += node.h mainwindow.h xml2bdb.h model.h FORMS += mainwindow.ui SOURCES += node.cpp main.cpp mainwindow.cpp xml2bdb.cpp model.cpp libqxt-0.6.2/examples/country/000077500000000000000000000000001215241066400163445ustar00rootroot00000000000000libqxt-0.6.2/examples/country/country.pro000066400000000000000000000010531215241066400205700ustar00rootroot00000000000000###################################################################### # Automatically generated by qmake (2.01a) Mi Nov 7 07:22:25 2007 ###################################################################### TEMPLATE = app CONFIG += debug_and_release CONFIG += qxt TARGET = test DEPENDPATH += . INCLUDEPATH += . QXT += core gui CONFIG(debug, debug|release) { unix: TARGET = $$join(TARGET,,,_debug) else: TARGET = $$join(TARGET,,d) } # Input FORMS += country.ui SOURCES += main.cpp HEADERS += testdialog.h RESOURCES += country.qrc libqxt-0.6.2/examples/country/country.qrc000066400000000000000000000005121215241066400205540ustar00rootroot00000000000000 ../../translations/qxt_de.qm ../../translations/qxt_en.qm ../../translations/qxt_es.qm ../../translations/qxt_fr.qm libqxt-0.6.2/examples/country/country.ui000066400000000000000000001476751215241066400204320ustar00rootroot00000000000000 Dialog 0 0 590 466 Dialog 9 6 0 6 12 75 true TextLabel 0 6 Afghanistan Albania Algeria AmericanSamoa Andorra Angola Anguilla Antarctica AntiguaAndBarbuda Argentina Armenia Aruba Australia Austria Azerbaijan Bahamas Bahrain Bangladesh Barbados Belarus Belgium Belize Benin Bermuda Bhutan Bolivia BosniaAndHerzegowina Botswana BouvetIsland Brazil BritishIndianOceanTerritory BritishVirginIslands BruneiDarussalam Bulgaria BurkinaFaso Burundi Cambodia Cameroon Canada CapeVerde CaymanIslands CentralAfricanRepublic Chad Chile China ChristmasIsland CocosIslands Colombia Comoros CookIslands CostaRica Croatia Cuba Cyprus CzechRepublic DemocraticRepublicOfCongo DemocraticRepublicOfKorea Denmark Djibouti Dominica DominicanRepublic EastTimor Ecuador Egypt ElSalvador EquatorialGuinea Eritrea Estonia Ethiopia FalklandIslands FaroeIslands Fiji Finland France FrenchGuiana FrenchPolynesia FrenchSouthernTerritories Gabon Gambia Georgia Germany Ghana Gibraltar Greece Greenland Grenada Guadeloupe Guam Guatemala Guinea GuineaBissau Guyana Haiti HeardAndMcDonaldIslands Honduras HongKong Hungary Iceland India Indonesia Iran Iraq Ireland Israel Italy IvoryCoast Jamaica Japan Jordan Kazakhstan Kenya Kiribati Kuwait Kyrgyzstan Lao Latvia Lebanon Lesotho Liberia LibyanArabJamahiriya Liechtenstein Lithuania Luxembourg Macau Macedonia Madagascar Malawi Malaysia Maldives Mali Malta MarshallIslands Martinique Mauritania Mauritius Mayotte MetropolitanFrance Mexico Micronesia Moldova Monaco Mongolia Montserrat Morocco Mozambique Myanmar Namibia Nauru Nepal Netherlands NetherlandsAntilles NewCaledonia NewZealand Nicaragua Niger Nigeria Niue NorfolkIsland NorthernMarianaIslands Norway Oman Pakistan Palau PalestinianTerritory Panama PapuaNewGuinea Paraguay PeoplesRepublicOfCongo Peru Philippines Pitcairn Poland Portugal PuertoRico Qatar RepublicOfKorea Reunion Romania RussianFederation Rwanda SaintKittsAndNevis Samoa SanMarino SaoTomeAndPrincipe SaudiArabia Senegal Seychelles SierraLeone Singapore Slovakia Slovenia SolomonIslands Somalia SouthAfrica SouthGeorgiaAndTheSouthSandwichIslands Spain SriLanka StHelena StLucia StPierreAndMiquelon StVincentAndTheGrenadines Sudan Suriname SvalbardAndJanMayenIslands Swaziland Sweden Switzerland SyrianArabRepublic Taiwan Tajikistan Tanzania Thailand Togo Tokelau Tonga TrinidadAndTobago Tunisia Turkey Turkmenistan TurksAndCaicosIslands Tuvalu Uganda Ukraine UnitedArabEmirates UnitedKingdom UnitedStates UnitedStatesMinorOutlyingIslands Uruguay USVirginIslands Uzbekistan Vanuatu VaticanCityState Venezuela VietNam WallisAndFutunaIslands WesternSahara Yemen Yugoslavia Zambia Zimbabwe NOTHING All Languages of QLocale: Abkhazian Afan Afar Afrikaans Albanian Amharic Arabic Armenian Assamese Aymara Azerbaijani Bashkir Basque Bengali Bhutani Bihari Bislama Bosnian Breton Bulgarian Burmese Byelorussian Cambodian Catalan Chinese Corsican Croatian Czech Danish Default Divehi Dutch English Esperanto Estonian Faroese Fiji Finnish French Frisian Gaelic Galician Georgian German Greek Greenlandic Guarani Gujarati Hausa Hebrew Hindi Hungarian Icelandic Indonesian Interlingua Interlingue Inuktitut Inupiak Irish Italian Japanese Javanese Kannada Kashmiri Kazakh Kinyarwanda Kirghiz Korean Kurdish Kurundi Laothian Latin Latvian Lingala Lithuanian Macedonian Malagasy Malay Malayalam Maltese Manx Maori Marathi Moldavian Mongolian Nauru Nepali Norwegian Occitan Oriya Pashto Persian Polish Portuguese Punjabi Quechua RhaetoRomance Romanian Russian Samoan Sangho Sanskrit Serbian SerboCroatian Sesotho Setswana Shona Sindhi Singhalese Siswati Slovak Slovenian Somali Spanish Sundanese Swahili Swedish Tagalog Tajik Tamil Tatar Telugu Thai Tibetan Tigrinya Tonga Tsonga Turkish Turkmen Twi Uigur Ukrainian Urdu Uzbek Vietnamese Volapuk Welsh Wolof Xhosa Yiddish Yoruba Zhuang Zulu Translations in Qt Resources: QxtLanguageComboBox::AvailableTranslations :/ Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok QxtCountryComboBox QComboBox
QxtCountryComboBox
QxtLanguageComboBox QComboBox
QxtLanguageComboBox
buttonBox accepted() Dialog accept() 248 254 157 274 buttonBox rejected() Dialog reject() 316 260 286 274 qxtLanguageComboBox currentLanguageChanged(QLocale::Language) qxtLanguageComboBox_2 setCurrentLanguage(QLocale::Language) 294 90 294 136 countryComboBox currentCountryNameChanged(QString) label_4 setText(QString) 294 43 294 67
libqxt-0.6.2/examples/country/main.cpp000066400000000000000000000010251215241066400177720ustar00rootroot00000000000000#include #include #include #include #include "testdialog.h" int main(int argc, char* argv[]) { // Q_INIT_RESOURCE(flags); QApplication app(argc, argv); QTranslator trans; bool ok = trans.load(":/qxt_"+QLocale::system().name()); if (!ok) qDebug() << "Loading translation failed."; qDebug() << trans.translate("Country", "Germany"); app.installTranslator(&trans); TestDialog* w = new TestDialog(); w->show(); app.exec(); } libqxt-0.6.2/examples/country/testdialog.h000066400000000000000000000007721215241066400206620ustar00rootroot00000000000000#ifndef TESTDIALOG_H_INCLUDED #define TESTDIALOG_H_INCLUDED #include #include "ui_country.h" #include class TestDialog : public QDialog { Q_OBJECT public: TestDialog(QWidget *parent = 0) : QDialog(parent) { ui.setupUi(this); ui.label->setText(QString("Current Locale: %1").arg(QLocale::system().name())); ui.tableView->setModel(new QxtCountryModel(this)); } private: Ui::Dialog ui; }; #endif // TESTDIALOG_H_INCLUDED libqxt-0.6.2/examples/displaysettings/000077500000000000000000000000001215241066400200675ustar00rootroot00000000000000libqxt-0.6.2/examples/displaysettings/displaysettings.pro000066400000000000000000000006461215241066400240450ustar00rootroot00000000000000###################################################################### # Automatically generated by qmake (2.01a) Sun Mar 1 19:09:35 2009 ###################################################################### TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . CONFIG += qxt QXT += core gui # Input FORMS += displaysettingsdialog.ui HEADERS += displaysettingsdialog.h SOURCES += displaysettingsdialog.cpp main.cpp libqxt-0.6.2/examples/displaysettings/displaysettingsdialog.cpp000066400000000000000000000144731215241066400252120ustar00rootroot00000000000000#include "displaysettingsdialog.h" #include #include #include #include #include static int greatestCommonDivisor(int a, int b) { if (b == 0) return a; return greatestCommonDivisor(b, a % b); } DisplaySettingsDialog::DisplaySettingsDialog(QWidget* parent) : QDialog(parent) { ui.setupUi(this); ui.letterBoxWidget->setMargin(20); ui.letterBoxWidget->setWidget(ui.labelBox); ui.letterBoxWidget->setBackgroundColor(QColor("wheat")); connect(ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), SLOT(apply())); connect(ui.refreshButton, SIGNAL(clicked()), SLOT(refresh())); fillScreens(); selectScreen(qApp->desktop()->primaryScreen()); fillRefreshRates(); fillColorDepths(); connect(ui.comboBoxScreen, SIGNAL(currentIndexChanged(int)), SLOT(selectScreen(int))); connect(ui.comboBoxReso, SIGNAL(currentIndexChanged(int)), SLOT(fillRefreshRates())); connect(ui.comboBoxReso, SIGNAL(currentIndexChanged(int)), SLOT(fillColorDepths())); updateUi(true); connect(ui.comboBoxScreen, SIGNAL(currentIndexChanged(int)), SLOT(updateUi())); connect(ui.comboBoxReso, SIGNAL(currentIndexChanged(int)), SLOT(updateUi())); connect(ui.comboBoxRate, SIGNAL(currentIndexChanged(int)), SLOT(updateUi())); connect(ui.comboBoxDepth, SIGNAL(currentIndexChanged(int)), SLOT(updateUi())); } void DisplaySettingsDialog::apply() { int resoIndex = ui.comboBoxReso->currentIndex(); if (resoIndex != -1) { const QSize reso = ui.comboBoxReso->itemData(resoIndex).toSize(); screen.setResolution(reso); } int rateIndex = ui.comboBoxRate->currentIndex(); if (rateIndex != -1) { const int rate = ui.comboBoxRate->itemData(rateIndex).toInt(); screen.setRefreshRate(rate); } int depthIndex = ui.comboBoxDepth->currentIndex(); if (depthIndex != -1) { const int depth = ui.comboBoxDepth->itemData(depthIndex).toInt(); screen.setColorDepth(depth); } screen.apply(); QMessageBox messageBox(this); messageBox.setWindowTitle(windowTitle()); messageBox.setIcon(QMessageBox::Information); messageBox.setText(tr("Your desktop has been reconfigured. Do you want to keep these settings?")); messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); messageBox.setDefaultButton(QMessageBox::No); messageBox.setWindowModality(Qt::WindowModal); messageBox.show(); QEventLoop eventLoop; connect(messageBox.button(QMessageBox::Yes), SIGNAL(clicked()), &eventLoop, SLOT(quit())); connect(messageBox.button(QMessageBox::No), SIGNAL(clicked()), &eventLoop, SLOT(quit())); for (int i = 15; i > 0; --i) { messageBox.setInformativeText(tr("Reverting in %1 seconds").arg(i)); QTimer::singleShot(1000, &eventLoop, SLOT(quit())); eventLoop.exec(); if (messageBox.clickedButton()) break; } if (messageBox.clickedButton() == messageBox.button(QMessageBox::Yes)) ui.buttonBox->button(QDialogButtonBox::Apply)->setDisabled(true); else screen.cancel(); } void DisplaySettingsDialog::refresh() { screen.refresh(); fillScreens(); updateUi(true); } void DisplaySettingsDialog::fillScreens() { ui.comboBoxScreen->clear(); int numScreens = qApp->desktop()->numScreens(); for (int i = 0; i < numScreens; ++i) ui.comboBoxScreen->addItem(tr("Screen %1").arg(i)); } void DisplaySettingsDialog::selectScreen(int screenNumber) { screen.setScreenNumber(screenNumber); fillResolutions(); } void DisplaySettingsDialog::fillResolutions() { ui.comboBoxReso->clear(); const QList resos = screen.availableResolutions(); foreach (const QSize& reso, resos) { QSize ratio = reso / greatestCommonDivisor(reso.width(), reso.height()); QString text = tr("%1 x %2 (%3:%4)") .arg(reso.width()).arg(reso.height()) .arg(ratio.width()).arg(ratio.height()); ui.comboBoxReso->addItem(text, reso); } const QSize reso = screen.resolution(); ui.comboBoxReso->setCurrentIndex(resos.indexOf(reso)); } void DisplaySettingsDialog::fillRefreshRates() { const int resoIndex = ui.comboBoxReso->currentIndex(); if (resoIndex != -1) { const QSize reso = ui.comboBoxReso->itemData(resoIndex).toSize(); ui.comboBoxRate->clear(); const QList rates = screen.availableRefreshRates(reso); foreach (int rate, rates) { QString text = tr("%1 Hz").arg(rate); ui.comboBoxRate->addItem(text, rate); } } } void DisplaySettingsDialog::fillColorDepths() { const int resoIndex = ui.comboBoxReso->currentIndex(); if (resoIndex != -1) { const QSize reso = ui.comboBoxReso->itemData(resoIndex).toSize(); ui.comboBoxDepth->clear(); const QList depths = screen.availableColorDepths(reso); foreach (int depth, depths) { QString text = tr("%1 bit").arg(depth); ui.comboBoxDepth->addItem(text, depth); } } } void DisplaySettingsDialog::updateUi(bool init) { if (init) { const QSize reso = screen.resolution(); const QList resos = screen.availableResolutions(); ui.comboBoxReso->setCurrentIndex(resos.indexOf(reso)); const int rate = screen.refreshRate(); const QList rates = screen.availableRefreshRates(reso); ui.comboBoxRate->setCurrentIndex(rates.indexOf(rate)); #ifdef Q_WS_WIN const int depth = screen.colorDepth(); const QList depths = screen.availableColorDepths(reso); ui.comboBoxDepth->setCurrentIndex(depths.indexOf(depth)); #else ui.labelDepth->setDisabled(true); ui.comboBoxDepth->setDisabled(true); #endif } const int resoIndex = ui.comboBoxReso->currentIndex(); const QSize reso = ui.comboBoxReso->itemData(resoIndex).toSize(); QSize ratio = reso / greatestCommonDivisor(reso.width(), reso.height()); QString text = tr("%1 x %2 (%3:%4)") .arg(reso.width()).arg(reso.height()) .arg(ratio.width()).arg(ratio.height()); ui.labelBox->setText(text); ui.labelBox->setSizeIncrement(reso); ui.letterBoxWidget->resizeWidget(); ui.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(!init); } libqxt-0.6.2/examples/displaysettings/displaysettingsdialog.h000066400000000000000000000011161215241066400246450ustar00rootroot00000000000000#ifndef DISPLAYSETTINGSDIALOG_H #define DISPLAYSETTINGSDIALOG_H #include #include "ui_displaysettingsdialog.h" class DisplaySettingsDialog : public QDialog { Q_OBJECT public: DisplaySettingsDialog(QWidget* parent = 0); private slots: void apply(); void refresh(); void fillScreens(); void selectScreen(int screenNumber); void fillResolutions(); void fillRefreshRates(); void fillColorDepths(); void updateUi(bool init = false); private: Ui::DisplaySettingsDialog ui; QxtScreen screen; }; #endif // DISPLAYSETTINGSDIALOG_H libqxt-0.6.2/examples/displaysettings/displaysettingsdialog.ui000066400000000000000000000121061215241066400250340ustar00rootroot00000000000000 DisplaySettingsDialog 0 0 338 392 Display Settings 0 0 320 200 QFrame::StyledPanel QFrame::Raised 80 40 161 111 background: salmon; border: 2px solid blue Qt::PlainText Qt::AlignCenter QFormLayout::AllNonFixedFieldsGrow &Resolution comboBoxReso Re&fresh Rate comboBoxRate &Screen comboBoxScreen Refresh &Depth comboBoxDepth Qt::Horizontal QDialogButtonBox::Apply|QDialogButtonBox::Close buttonBox letterBoxWidget QxtLetterBoxWidget QFrame
QxtLetterBoxWidget
1
comboBoxScreen comboBoxReso comboBoxRate comboBoxDepth refreshButton buttonBox buttonBox accepted() DisplaySettingsDialog accept() 248 254 157 274 buttonBox rejected() DisplaySettingsDialog reject() 316 260 286 274
libqxt-0.6.2/examples/displaysettings/main.cpp000066400000000000000000000002701215241066400215160ustar00rootroot00000000000000#include #include "displaysettingsdialog.h" int main(int argc, char* argv[]) { QApplication app(argc, argv); DisplaySettingsDialog dialog; return dialog.exec(); } libqxt-0.6.2/examples/examples.pro000066400000000000000000000011221215241066400171750ustar00rootroot00000000000000###################################################################### # Automatically generated by qmake (2.01a) Fri Jan 16 22:47:44 2009 ###################################################################### TEMPLATE = subdirs contains(DEFINES,HAVE_DB):contains(QXT_MODULES, berkeley):SUBDIRS += berkeley contains(QXT_MODULES, gui) { !macx:SUBDIRS += displaysettings SUBDIRS += qxtflowview } contains(QXT_MODULES, network):SUBDIRS += ircpeer jsonrpcclient contains(QXT_MODULES, web):SUBDIRS += web contains(DEFINES,HAVE_ZEROCONF):contains(QXT_MODULES, zeroconf):SUBDIRS += zeroconf libqxt-0.6.2/examples/ircpeer/000077500000000000000000000000001215241066400162725ustar00rootroot00000000000000libqxt-0.6.2/examples/ircpeer/dialog.cpp000066400000000000000000000016651215241066400202450ustar00rootroot00000000000000#include "dialog.h" #include ConnectDialog::ConnectDialog() { ui.setupUi(this); connect(this, SIGNAL(accepted()), this, SLOT(save())); QSettings settings("libqxt.org", "ircpeer"); if(settings.contains("username")) ui.nick->setText(settings.value("username").toString()); if(settings.contains("port")) ui.port->setText(settings.value("port").toString()); if(settings.contains("server")) ui.server->setText(settings.value("server").toString()); } void ConnectDialog::save() { QSettings settings("libqxt.org", "ircpeer"); settings.setValue("username", nickname()); settings.setValue("port", QString::number(port())); settings.setValue("server", hostname()); } QByteArray ConnectDialog::hostname() { return ui.server->text().toAscii(); } int ConnectDialog::port() { return ui.port->text().toInt(); } QString ConnectDialog::nickname() { return ui.nick->text(); } libqxt-0.6.2/examples/ircpeer/dialog.h000066400000000000000000000005161215241066400177040ustar00rootroot00000000000000#ifndef DIALOG_H_INCLUDED #define DIALOG_H_INCLUDED #include #include "ui_dialog.h" class ConnectDialog : public QDialog { Q_OBJECT public: ConnectDialog(); QByteArray hostname(); int port(); QString nickname(); private slots: void save(); private: Ui::Dialog ui; }; #endif // DIALOG_H_INCLUDED libqxt-0.6.2/examples/ircpeer/dialog.ui000066400000000000000000000055461215241066400201020ustar00rootroot00000000000000 Dialog 0 0 379 163 connect Server: chat.freenode.net Port: 6667 Nickname: qxtirc Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok Qt::Vertical 20 40 nick server port buttonBox buttonBox accepted() Dialog accept() 248 254 157 274 buttonBox rejected() Dialog reject() 316 260 286 274 libqxt-0.6.2/examples/ircpeer/ircpeer.cpp000066400000000000000000000124601215241066400204320ustar00rootroot00000000000000#include "ircpeer.h" #include IRCSerializer::IRCSerializer() : QxtAbstractSignalSerializer() { qRegisterMetaType(); } bool IRCSerializer::canDeserialize(const QByteArray& buffer) const { return buffer.indexOf('\n') != -1 || buffer.indexOf('\r') != -1; } static bool serializeParam(QTextStream& str, QVariant p) { if(!p.isValid() || !p.canConvert(QVariant::ByteArray)) { str << "\r\n" << flush; return true; } QByteArray ba = p.toByteArray(); if(ba.contains(' ') || ba[0] == ':') { str << " :" << ba << "\r\n" << flush; return true; } str << " " << ba << flush; return false; } QByteArray IRCSerializer::serialize(const QString& fn, const QVariant& p1, const QVariant& p2, const QVariant& p3, const QVariant& p4, const QVariant& p5, const QVariant& p6, const QVariant& p7, const QVariant& p8) const { if(fn == "raw") return p1.toString().toUtf8() + "\r\n"; QByteArray rv; QTextStream str(&rv); if(p1.isValid()) { if(p1.canConvert()) { QByteArray name = p1.value().assemble(); if(!name.isEmpty()) str << ":" << p1.value().assemble() << " "; } else if(!p1.toByteArray().isEmpty()) { str << ":" << p1.toByteArray() << " "; } } str << fn << flush; if(serializeParam(str, p2)) return rv; if(serializeParam(str, p3)) return rv; if(serializeParam(str, p4)) return rv; if(serializeParam(str, p5)) return rv; if(serializeParam(str, p6)) return rv; if(serializeParam(str, p7)) return rv; if(serializeParam(str, p8)) return rv; return rv + "\r\n"; } QPair > IRCSerializer::deserialize(QByteArray& data) { int lfPos = data.indexOf('\n'), crPos = data.indexOf('\r'), wordPos = 0, endPos = (crPos == -1 || lfPos < crPos) ? lfPos : crPos; QByteArray message = data.left(endPos).trimmed(), prefix; data = data.mid(endPos+1); if(message.isEmpty()) return qMakePair(QString(), QList()); QList words = message.split(' '); if(words[0][0] == ':') { prefix = words[0].mid(1); while(wordPos < words.count() && words[wordPos++].isEmpty()) return qMakePair(QString(), QList() << QVariant()); } QString command(words[wordPos]); QList params; int cmdNum = command.toInt(); if(cmdNum != 0) { params << QVariant::fromValue(IRCName((prefix + ':' + command).toUtf8(), "", prefix)); command = "numeric"; } else { if(prefix.isEmpty()) params << QVariant::fromValue(IRCName("","","")); else if(prefix.contains('@')) params << QVariant::fromValue(IRCName::fromName(prefix)); else params << QVariant::fromValue(IRCName(prefix, prefix, prefix)); } while(wordPos++ < words.count()-1) { if(words[wordPos].isEmpty()) continue; if(words[wordPos][0] == ':') { QByteArray trailing = words[wordPos++].mid(1); while(wordPos < words.count()) trailing = trailing + ' ' + words[wordPos++]; params << trailing; break; } params << words[wordPos]; } if(command == "numeric") { params.removeAt(1); // always your own nick while(params[1].toByteArray() == "=" || params[1].toByteArray() == "@") params.removeAt(1); // nothing important if(params.size() == 2) { params.push_front(QByteArray()); // make it show up in the system window params.swap(0, 1); } else if(cmdNum < 300 || params.size() > 3) { // some numeric responses aren't a single string QList newparams; newparams << params[0]; int i; if(cmdNum < 300) { newparams << QByteArray(); i = 1; } else { newparams << params[1]; i = 2; } QByteArray ba; for(; i < params.count(); i++) ba += params[i].toByteArray() + ' '; newparams << ba; params = newparams; } } else if(command == "PRIVMSG") { QByteArray p2 = params[2].toByteArray(); if(p2.size() > 0 && p2[0] == '\001') { message = p2.replace("\001", ""); int spacePos = message.indexOf(' '); if(spacePos == -1) spacePos = message.size(); command = "CTCP-"+message.left(spacePos); params[2] = message.mid(spacePos); } } else if(command == "NOTICE" && params[0].isNull()) { params[0] = QVariant::fromValue(IRCName(params[1].toByteArray(), "", params[1].toByteArray())); } return qMakePair(command, params); } IRCName IRCName::fromName(const QByteArray& name) { QRegExp re("([^@!]*)(?:!([^@]*)?)(?:@(.*))?"); re.exactMatch(QString::fromUtf8(name.data())); return IRCName(re.cap(1).toUtf8(), re.cap(2).toUtf8(), re.cap(3).toUtf8()); } IRCName::IRCName(QByteArray nick, QByteArray ident, QByteArray host) : nick(nick), ident(ident), host(host) {} QByteArray IRCName::assemble() const { return nick + (ident.isEmpty() ? QByteArray() : '!' + ident) + (host.isEmpty() ? QByteArray() : '@' + host); } libqxt-0.6.2/examples/ircpeer/ircpeer.h000066400000000000000000000020051215241066400200710ustar00rootroot00000000000000#ifndef QXTIRCPEER_H #define QXTIRCPEER_H #include #include struct IRCName { IRCName(QByteArray nick = QByteArray(), QByteArray ident = QByteArray(), QByteArray host = QByteArray()); QByteArray nick; QByteArray ident; QByteArray host; QByteArray assemble() const; static IRCName fromName(const QByteArray& name); }; Q_DECLARE_METATYPE(IRCName) class IRCSerializer : public QxtAbstractSignalSerializer { public: IRCSerializer(); virtual QByteArray serialize(const QString& fn, const QVariant& p1 = QVariant(), const QVariant& p2 = QVariant(), const QVariant& p3 = QVariant(), const QVariant& p4 = QVariant(), const QVariant& p5 = QVariant(), const QVariant& p6 = QVariant(), const QVariant& p7 = QVariant(), const QVariant& p8 = QVariant()) const; virtual DeserializedData deserialize(QByteArray& data); virtual bool canDeserialize(const QByteArray& buffer) const; }; #endif libqxt-0.6.2/examples/ircpeer/ircpeer.pro000066400000000000000000000002561215241066400204500ustar00rootroot00000000000000TEMPLATE = app TARGET = CONFIG += qxt QXT += network HEADERS += mainwindow.h ircpeer.h dialog.h SOURCES += mainwindow.cpp ircpeer.cpp dialog.cpp FORMS += dialog.ui libqxt-0.6.2/examples/ircpeer/mainwindow.cpp000066400000000000000000000210751215241066400211570ustar00rootroot00000000000000#include "mainwindow.h" MainWindow::MainWindow() : QMainWindow(0) { centralwidget = new QWidget(this); gridLayout = new QGridLayout(centralwidget); tabWidget = new QTabWidget(centralwidget); tabWidget->setTabPosition(QTabWidget::South); gridLayout->addWidget(tabWidget, 0, 0, 1, 2); pushButton = new QPushButton("&Send", centralwidget); gridLayout->addWidget(pushButton, 1, 1, 1, 1); lineEdit = new QLineEdit(centralwidget); gridLayout->addWidget(lineEdit, 1, 0, 1, 1); setCentralWidget(centralwidget); QObject::connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(send())); QObject::connect(pushButton, SIGNAL(clicked()), this, SLOT(send())); QObject::connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(tabActivated(int))); lineEdit->installEventFilter(this); irc.setSerializer(new IRCSerializer); irc.attachSlot("PRIVMSG",this, SLOT(receiveMessage(IRCName, QByteArray, QByteArray))); irc.attachSlot("NOTICE",this, SLOT(receiveNotice(IRCName, QByteArray, QByteArray))); irc.attachSlot("JOIN",this, SLOT(userJoin(IRCName, QByteArray))); irc.attachSlot("PART",this, SLOT(userPart(IRCName, QByteArray))); irc.attachSlot("QUIT",this, SLOT(userQuit(IRCName, QByteArray))); irc.attachSlot("PING",this, SLOT(pong(IRCName, QByteArray))); irc.attachSlot("CTCP-ACTION",this, SLOT(receiveAction(IRCName, QByteArray, QByteArray))); irc.attachSlot("system",this, SLOT(receiveMessage(IRCName, QByteArray, QByteArray))); irc.attachSlot("numeric",this, SLOT(receiveMessage(IRCName, QByteArray, QByteArray))); irc.attachSignal(this, SIGNAL(sendMessage(IRCName, QByteArray, QByteArray)), "PRIVMSG"); QObject::connect(&irc, SIGNAL(connectedToServer()), this, SLOT(peerConnected())); QObject::connect(&irc, SIGNAL(serverError(QAbstractSocket::SocketError)), this, SLOT(peerError(QAbstractSocket::SocketError))); connect(this, SIGNAL(sendMessage(IRCName, QByteArray, QByteArray)), this, SLOT(receiveMessage(IRCName, QByteArray, QByteArray))); setWindowTitle("Qxt RPC IRC example"); resize(800,600); QTimer::singleShot(0,this,SLOT(lateInit())); } void MainWindow::lateInit() { if(condiag.exec()) { irc.connect(condiag.hostname(), condiag.port()); receiveMessage(IRCName(condiag.hostname()),condiag.hostname(), "connecting to "+condiag.hostname()+':'+QByteArray::number(condiag.port())); } else { qApp->quit(); } } void MainWindow::pong(IRCName, QByteArray key) { irc.call("PONG", QVariant(), key); } void MainWindow::peerConnected() { irc.call("USER", QVariant(), condiag.nickname(), condiag.hostname(), condiag.hostname(), QByteArray("QxtRPCPeer")); irc.call("NICK", QVariant(), condiag.nickname()); receiveMessage(IRCName(condiag.hostname()),condiag.hostname(),"connected. type /join #channel, to join a channel"); lineEdit->setFocus(Qt::OtherFocusReason); } void MainWindow::peerError(QAbstractSocket::SocketError e) { receiveMessage(IRCName(condiag.hostname()),condiag.hostname(),"QAbstractSocket::SocketError "+QByteArray::number(e)); } void MainWindow::receiveMessage(IRCName nick, QByteArray channel, QByteArray message) { if(message.startsWith(QByteArray("\001ACTION "))) receiveAction(nick, channel, message.mid(8, message.size()-9)); else logMessage(nick, channel, message, "<%1> %2"); } void MainWindow::receiveNotice(IRCName nick, QByteArray channel, QByteArray message) { logMessage(nick, channel, message, "[%1] %2"); } void MainWindow::receiveAction(IRCName nick, QByteArray channel, QByteArray message) { logMessage(nick, channel, message, "* %1 %2"); } void MainWindow::userJoin(IRCName nick, QByteArray channel) { if(channels.contains(nick.nick)) logMessage(nick, nick.nick, channel, "! %1 joined %2"); logMessage(nick, channel, "joined the channel", "! %1 %2"); } void MainWindow::userPart(IRCName nick, QByteArray channel) { if(nick.nick == condiag.nickname()) return; logMessage(nick, channel, "left the channel", "! %1 %2"); } void MainWindow::userQuit(IRCName nick, QByteArray message) { if(channels.contains(nick.nick)) logMessage(nick, nick.nick, message, "! %1 Quit: %2"); logMessage(nick, "", message, "! %1 Quit: %2"); } void MainWindow::logMessage(IRCName nick, QByteArray channel, QByteArray message, QString format) { if(channel == condiag.nickname()) { if(channel == nick.nick) channel = condiag.hostname(); else channel = nick.nick; } if(channel.isEmpty() || channel == "AUTH") { channel = condiag.hostname(); } else if(!channels.contains(channel)) { channels[channel] = new QTextBrowser(); channels[channel]->setFrameShape(QFrame::NoFrame); tabWidget->addTab(channels[channel], channel); } channels[channel]->append(format.arg(QString(nick.nick)).arg(QString(message))); channels[channel]->moveCursor(QTextCursor::End); channels[channel]->ensureCursorVisible(); int index = tabWidget->indexOf(channels[channel]); if(index != tabWidget->currentIndex()) tabWidget->setTabIcon(index, qApp->style()->standardIcon(QStyle::SP_ArrowRight)); qApp->alert(this, 250); } void MainWindow::send() { QByteArray msg=lineEdit->text().toUtf8(); if(msg.trimmed().isEmpty()) return; if(msg.startsWith('/')) { if(msg.startsWith(QByteArray("/join "))) { if(msg.mid(6,1) == "#" || msg.mid(6,1) == "&") irc.call("JOIN", QVariant(),msg.mid(6)); receiveMessage(IRCName(condiag.hostname()),msg.mid(6),"you have joined "+msg.mid(6)); tabWidget->setCurrentWidget(channels[msg.mid(6)]); } else if(msg.startsWith(QByteArray("/me "))) { emit sendMessage(IRCName(condiag.nickname().toUtf8()), tabWidget->tabText(tabWidget->currentIndex()).toUtf8(), QByteArray("\001ACTION " + msg.mid(4) + "\001")); } else if(msg.startsWith(QByteArray("/names"))) { if(msg == "/names") irc.call("NAMES", QVariant(), tabWidget->tabText(tabWidget->currentIndex()).toUtf8()); else irc.call("NAMES", QVariant(), msg.mid(7)); } else if(msg == "/part") { partCurrentChannel(); } else if(msg.startsWith(QByteArray("/raw "))) { irc.call("raw", msg.mid(5)); } else if(msg == "/quit") { qApp->quit(); } else { receiveMessage(IRCName(condiag.hostname()),condiag.hostname(),"unknown command "+msg); } } else { emit sendMessage(IRCName(condiag.nickname().toUtf8()), tabWidget->tabText(tabWidget->currentIndex()).toUtf8(), msg); } lineEdit->clear(); } void MainWindow::partCurrentChannel() { if(tabWidget->currentIndex() == 0) return; if(tabWidget->tabText(tabWidget->currentIndex())[0] == '#' || tabWidget->tabText(tabWidget->currentIndex())[0] == '&') irc.call("PART", QVariant(), tabWidget->tabText(tabWidget->currentIndex()).toUtf8()); channels.remove(tabWidget->tabText(tabWidget->currentIndex()).toUtf8()); tabWidget->currentWidget()->deleteLater(); tabWidget->removeTab(tabWidget->currentIndex()); } bool MainWindow::eventFilter(QObject* obj, QEvent* event) { if(obj != lineEdit) return false; if(event->type() != QEvent::KeyPress) return false; QKeyEvent* ke = static_cast(event); if(ke->key() == Qt::Key_PageUp || ke->key() == Qt::Key_PageDown) { QScrollBar* scroll = qobject_cast(tabWidget->currentWidget())->verticalScrollBar(); if(ke->key() == Qt::Key_PageUp) scroll->triggerAction(QScrollBar::SliderPageStepSub); else scroll->triggerAction(QScrollBar::SliderPageStepAdd); return true; } if(ke->modifiers().testFlag(Qt::ControlModifier) && (ke->key() == Qt::Key_F4 || ke->key() == Qt::Key_W)) { partCurrentChannel(); return true; } if(ke->key() != Qt::Key_Tab && ke->key() != Qt::Key_Backtab) return false; if(!ke->modifiers().testFlag(Qt::ControlModifier)) return false; int nextTab = tabWidget->currentIndex(); if(ke->key() == Qt::Key_Backtab) nextTab--; else nextTab++; if(nextTab == -1) nextTab = tabWidget->count() - 1; if(nextTab == tabWidget->count()) nextTab = 0; tabWidget->setCurrentIndex(nextTab); return true; } void MainWindow::tabActivated(int index) { tabWidget->setTabIcon(index, QIcon()); } int main(int argc, char** argv) { QApplication app(argc, argv); MainWindow main; main.show(); return app.exec(); } libqxt-0.6.2/examples/ircpeer/mainwindow.h000066400000000000000000000023051215241066400206170ustar00rootroot00000000000000#ifndef MAINWINDOW_H_INCLUDED #define MAINWINDOW_H_INCLUDED #include #include #include "ircpeer.h" #include "dialog.h" class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); protected: bool eventFilter(QObject* obj, QEvent* event); private slots: void lateInit(); void peerConnected(); void peerError(QAbstractSocket::SocketError); void receiveMessage(IRCName, QByteArray, QByteArray); void receiveNotice(IRCName, QByteArray, QByteArray); void receiveAction(IRCName, QByteArray, QByteArray); void userJoin(IRCName, QByteArray); void userPart(IRCName, QByteArray); void userQuit(IRCName, QByteArray); void logMessage(IRCName, QByteArray, QByteArray, QString); void send(); void tabActivated(int index); void partCurrentChannel(); void pong(IRCName, QByteArray); signals: void sendMessage(IRCName, QByteArray, QByteArray); private: QWidget *centralwidget; QGridLayout *gridLayout; QTabWidget *tabWidget; QLineEdit *lineEdit; QPushButton *pushButton; QMenuBar *menubar; QHash channels; QxtRPCPeer irc; ConnectDialog condiag; }; #endif // MAINWINDOW_H_INCLUDED libqxt-0.6.2/examples/jsonrpcclient/000077500000000000000000000000001215241066400175165ustar00rootroot00000000000000libqxt-0.6.2/examples/jsonrpcclient/jsonrpcclient.pro000066400000000000000000000001631215241066400231150ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . SOURCES += main.cpp CONFIG+=qxt console QXT=core network libqxt-0.6.2/examples/jsonrpcclient/main.cpp000066400000000000000000000013571215241066400211540ustar00rootroot00000000000000#include #include #include #include #include #include int main(int argc, char ** argv){ QCoreApplication app(argc,argv); if(app.arguments().count()<2){ qDebug()<<"usage: ./qxtjsonrpcclient method [arguments] \n see http://www.raboof.com/projects/JayRock/Demo.ashx?help for methods to use"; exit(1); } QxtJSONRpcClient client; client.setServiceUrl(QString("http://www.raboof.com/projects/JayRock/Demo.ashx")); QxtJSONRpcCall * call = client.call(app.arguments()[1],QVariant(app.arguments().mid(2)).toList()); QxtSignalWaiter w(call,SIGNAL(finished())); w.wait(); qDebug()<result(); } libqxt-0.6.2/examples/qxtflowview/000077500000000000000000000000001215241066400172405ustar00rootroot00000000000000libqxt-0.6.2/examples/qxtflowview/fsimagemodel.cpp000066400000000000000000000067531215241066400224130ustar00rootroot00000000000000#include "fsimagemodel.h" #include #include #include #include struct FsImageModelImage { QFileInfo info; QImage image; }; FsImageModel::FsImageModel(QString path,QObject * parent ):QAbstractItemModel(parent) { dir = QDir::current(); if(!path.isEmpty()) dir = QDir(path); connect(&watcher,SIGNAL(directoryChanged ( const QString & )),this,SLOT(directoryChanged ( const QString & ))); connect(&watcher,SIGNAL(fileChanged ( const QString & )),this,SLOT(fileChanged ( const QString & ))); watcher.addPath(dir.absolutePath()); dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); QFileInfoList list = dir.entryInfoList(); for (int i = 0; i < list.size(); ++i) { FsImageModelImage * img= new FsImageModelImage; img->info=list.at(i); img->image.load(dir.absoluteFilePath(img->info.fileName())); files.append(img); watcher.addPath(dir.absoluteFilePath(img->info.fileName())); } } FsImageModel::~FsImageModel() { qDeleteAll(files); } QModelIndex FsImageModel::index(int row, int column, const QModelIndex &parent) const { return createIndex ( row, column, files.at(row) ); } QModelIndex FsImageModel::parent(const QModelIndex &index) const { return QModelIndex(); } int FsImageModel::rowCount(const QModelIndex & parent ) const { if(parent.isValid()) return 0; return files.count(); } int FsImageModel::columnCount(const QModelIndex & parent ) const { return 1; } QVariant FsImageModel::data(const QModelIndex & index, int role ) const { FsImageModelImage* img=static_cast(index.internalPointer()); if(role==Qt::DisplayRole) return img->info.fileName(); if(role==Qt::DecorationRole) return img->image; return QVariant(); } class Thread : public QThread { friend class FsImageModel; }; void FsImageModel::directoryChanged ( const QString & path ) { Q_ASSERT(path==dir.absolutePath()); QStringList org=watcher.files (); QFileInfoList list = dir.entryInfoList(); for (int i = 0; i < list.size(); ++i) { QString path= dir.absoluteFilePath(list.at(i).fileName()); if(org.contains(path)) { org.removeAll(path); } else { beginInsertRows (QModelIndex(),files.count(),files.count()); FsImageModelImage * img= new FsImageModelImage; img->info=list.at(i); int retry=100; while(!img->image.load(path)) { Thread::usleep(1000); if(--retry<0) { break; } }; ///hax files.append(img); watcher.addPath(path); endInsertRows (); } } foreach(const QString &a, org) fileChanged(a); } void FsImageModel::fileChanged ( const QString & path ) { int i=0; foreach(FsImageModelImage* img,files) { if(dir.absoluteFilePath(img->info.fileName())==path) { if(img->info.exists()) { emit dataChanged ( index(i,0), index(i,0)); } else { beginRemoveRows (QModelIndex(),i,i); watcher.removePath(path); delete files.at(i); files.removeAt(i); endRemoveRows (); break; } break; } ++i; } } libqxt-0.6.2/examples/qxtflowview/fsimagemodel.h000066400000000000000000000021251215241066400220450ustar00rootroot00000000000000#ifndef FSIMAGEMODEL_H_INCLUDED #define FSIMAGEMODEL_H_INCLUDED /** warning: this model is a quick and dirty hack. it has major flaws and should not be used for anything but testing */ #include #include #include struct FsImageModelImage; class FsImageModel : public QAbstractItemModel { Q_OBJECT public: explicit FsImageModel(QString path,QObject * parent = 0); virtual ~FsImageModel(); virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; virtual QModelIndex parent(const QModelIndex &index) const; virtual int rowCount(const QModelIndex & parent = QModelIndex()) const; virtual int columnCount(const QModelIndex & parent = QModelIndex()) const; virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; private: QList files; QDir dir; QFileSystemWatcher watcher; private slots: void directoryChanged ( const QString & path ); void fileChanged ( const QString & path ); }; #endif // FSIMAGEMODEL_H_INCLUDED libqxt-0.6.2/examples/qxtflowview/main.cpp000066400000000000000000000010141215241066400206640ustar00rootroot00000000000000#include #include "fsimagemodel.h" #include #include int main( int argc, char ** argv ) { QApplication app ( argc, argv ); if(app.arguments().count()<2) qFatal("./qxtflowview /path/to/images"); FsImageModel model(app.arguments().at(1)); // QTreeView view; // view.setModel(&model); // view.show(); QxtFlowView w; w.setSlideSize(QSize( 4*60,3*60)); w.resize(800, 600); w.setModel(&model); w.show(); return app.exec(); } libqxt-0.6.2/examples/qxtflowview/qxtflowview.pro000066400000000000000000000001501215241066400223550ustar00rootroot00000000000000TEMPLATE = app CONFIG+=qxt QXT=core gui HEADERS = fsimagemodel.h SOURCES = fsimagemodel.cpp main.cpp libqxt-0.6.2/examples/web/000077500000000000000000000000001215241066400154165ustar00rootroot00000000000000libqxt-0.6.2/examples/web/main.cpp000066400000000000000000000015711215241066400170520ustar00rootroot00000000000000#include #include #include #include #include class MyService : public QxtWebSlotService{ Q_OBJECT; public: MyService(QxtAbstractWebSessionManager * sm, QObject * parent = 0 ): QxtWebSlotService(sm,parent){ } public slots: void index(QxtWebRequestEvent* event) { postEvent(new QxtWebPageEvent(event->sessionID, event->requestID, "

It Works!

")); } }; int main(int argc, char ** argv){ QCoreApplication app(argc,argv); QxtHttpServerConnector connector; QxtHttpSessionManager session; session.setPort(8080); session.setConnector(&connector); MyService s1(&session); session.setStaticContentService ( &s1); session.start(); return app.exec(); } #include "main.moc" libqxt-0.6.2/examples/web/web.pro000066400000000000000000000001471215241066400167170ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . SOURCES += main.cpp CONFIG+=qxt QXT=core web libqxt-0.6.2/examples/zeroconf/000077500000000000000000000000001215241066400164665ustar00rootroot00000000000000libqxt-0.6.2/examples/zeroconf/foo.h000066400000000000000000000025631215241066400174300ustar00rootroot00000000000000#ifndef FOO_H #define FOO_H #include #include #include #include #include #include #include #include class Foo : public QObject { Q_OBJECT public: QxtServiceBrowser* browser; public slots: void err(int err) { qDebug() << "error=" << err; } void ok() { qDebug() << "registered yay"; } void add(const QString& name, const QString& domain) { qDebug() << "added" << name; QString st = "_"+browser->serviceType()+"._"; if(browser->socketType() == QAbstractSocket::TcpSocket) { st += "tcp"; } else { st += "udp"; } QxtDiscoverableService* svc = new QxtDiscoverableService(st, name, browser); svc->setDomain(domain); QObject::connect(svc, SIGNAL(resolved(QByteArray)), this, SLOT(resolved(QByteArray))); QObject::connect(svc, SIGNAL(resolveError(int)), this, SLOT(err(int))); svc->resolve(); } void remove(const QString& name) { qDebug() << "removed" << name; } void resolved(const QByteArray& domainName) { QxtDiscoverableService* svc = static_cast(sender()); qDebug() << "resolved " << domainName << " on port " << svc->port(); } }; #endif libqxt-0.6.2/examples/zeroconf/test.cpp000066400000000000000000000017041215241066400201530ustar00rootroot00000000000000#include "foo.h" #include #include #include #include #include int main(int argc, char** argv) { QCoreApplication app(argc, argv); QxtDiscoverableService svc("daap"); svc.setPort(9123); Foo foo; QObject::connect(&svc, SIGNAL(registered()), &foo, SLOT(ok())); QObject::connect(&svc, SIGNAL(registrationError(int)), &foo, SLOT(err(int))); qDebug() << "registering..."; svc.registerService(true); qDebug() << "registerService invoked"; QxtServiceBrowser browser("daap"); foo.browser = &browser; QObject::connect(&browser, SIGNAL(browsingFailed(int)), &foo, SLOT(err(int))); QObject::connect(&browser, SIGNAL(serviceAdded(QString,QString)), &foo, SLOT(add(QString,QString))); QObject::connect(&browser, SIGNAL(serviceRemoved(QString,QString)), &foo, SLOT(remove(QString))); browser.browse(); app.exec(); } libqxt-0.6.2/examples/zeroconf/zeroconf.pro000066400000000000000000000002251215241066400210340ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . .. CONFIG += qxt QXT = core network zeroconf # Input HEADERS += foo.h SOURCES += test.cpp libqxt-0.6.2/extras/000077500000000000000000000000001215241066400143315ustar00rootroot00000000000000libqxt-0.6.2/extras/GPL_Exception1.0.txt000066400000000000000000000065161215241066400177610ustar00rootroot00000000000000Trolltech GPL Exception version 1.0 Additional rights granted beyond the GPL (the "Exception"). As a special exception to the terms and conditions of version 2.0 of the GPL, Trolltech hereby grants you the rights described below, provided you agree to the terms and conditions in this Exception, including its obligations and restrictions on use. Nothing in this Exception gives you or anyone else the right to change the licensing terms of the Qt Open Source Edition. Below, "Licensed Software" shall refer to the software licensed under the GPL and this exception. 1) The right to use Open Source Licenses not compatible with the GNU General Public License: You may link software (hereafter referred to as "Your Software") against the Licensed Software and/or distribute binaries of Your Software linked against the Licensed Software, provided that: A) Your Software is licensed under one of the following licenses: License name Version(s)/Copyright Date Academic Free License 2.0 or 2.1 Apache Software License 1.0 or 1.1 Apache License 2.0 Apple Public Source License 2.0 Artistic license From Perl 5.8.0 BSD license "July 22 1999" Common Public License 1.0 GNU Library or "Lesser" 2.0 or 2.1 General Public License (LGPL) Jabber Open Source License 1.0 MIT License (as attached) Mozilla Public License (MPL) 1.0 or 1.1 Open Software License 2.0 OpenSSL license (with original "2003" ("1998") SSLeay license) PHP License 3.0 Python license (CNRI Python License) (as attached) Python Software Foundation License 2.1.1 Q Public License v1.0 Sleepycat License "1999" W3C License "2001" X11 License X11R6.6 Zlib/libpng License (as attached) Zope Public License 2.0 (Licenses without a specific version number or date are reproduced in the file GPL_Exception1.0_Addendum.txt in your source package). and B) You must, on request, make a complete package including the complete source code of Your Software (as defined in the GNU General Public License version 2, section 3, but excluding anything excluded by the special exception in the same section) available to Trolltech under the same license as that granted to other recipients of the source code of Your Software. and C) Your or any other contributor's rights to: i) distribute the source code of Your Software to anyone for any purpose; and ii) publicly discuss the development project for Your Software and its goals in any form and in any forum are not prohibited by any legal instrument, including but not limited to contracts, non-disclosure agreements, and employee contracts. 2) The right to link non-Open Source applications with pre-installed versions of the Licensed Software: You may link applications with binary pre-installed versions of the Licensed Software, provided that such applications have been developed and are deployed in accordance in accordance with the terms and conditions of the Qt Commercial License Agreement. libqxt-0.6.2/extras/artwork/000077500000000000000000000000001215241066400160225ustar00rootroot00000000000000libqxt-0.6.2/extras/artwork/logo.png000066400000000000000000002752131215241066400175020ustar00rootroot00000000000000PNG  IHDR,߇ pHYs  ~ vpAg,(QIDATxT6ɉ{ !B n'.C= m{fkw~WKZ&zSTң(=C-(=JRG)Kң(aQz(=JRG)Kң(aQz(=JRG)Kң(aQz(=JRG)Ĺ(=Jm? g{c[A ]~ң(Y^9(= ,D '%U ң$mv?yʉ֗?]%NjRYz`hS6;P&QPj KR@XG!&eDbĎĎ7KQzAh ^#Y;i+K^,'KAXzV+ct4`UKt]Oٍt) )9ayY!c)KR@Ș0F*!UO D̀C$vhqX ſGQ B )B%xZ*3b`VnvYP$YEam34G)d 8&FeJg3Z"f56#F F-$ad%B29giZO+u^՘ZMg3Q`(U .(k'Ů3Y5:_AQk0¯mlB*FC!dZRe6 _`*H2/]8Gga ! ln?̪ոTCJ@XGKtTHCPZ@2F$@X/{{)tHEbX[pYnwZ<0f"z.TAihSB%%:Ol*6cWDS;cEP;cϵ6oF?  `ʀQBN)=:ٿ}n?~wsG`FdrFh~]yHe3hm*nnk>|]N?RV6+0qb@i@; UcZVdRteh)%VhdD2ScKA+-)%\XDE.I Zzsz4PdH$i4f3,4S`%\E烯H'+tMA@l*aJ@Mhf5xn7qW"mVpG&)(f=(b%܊63(iׂ z\k+<[#"8DLA9ưcOI *UMg9{@d)PR)b&%P8h.lJ:CJ̵DdYBifTo @fX0!%et-PPqQ5jߵ*ׁ_V^"E9?>ǻv wa6!0Tp{*PNgI|"1Ed3馀tc 0E(L09k.2hVsᲒ؅dY7GXH/RlH1~M1zSfOⓁe!E1ej 1e`Wx(r\jH}+$[q߷JA?Q1Ϣ.Ah%"X 8'XmSڳTLc2-`8)T?31R:YΤ), #3b3+ǭj¦:ʪ/ݬK ]Z@H$Ś^+~1r +R0#xL)(lJ2}H6OsCœbL4نܔ(}E LA;9":S F~سCA 4Ά잂ɖ2G 0-h7z%AᚾetblҚUNJ̪1FK21sN[ ,*w9xSѦ5U*V$g ȈL?9.*<αIO&РSt$LmAPç+f8XIH ??$Ol|RO5Þ(A̴Ȉ|)LJp1M!X9%=c c o̠U߁VMl2*IXSe,:T ͚HB38PN1,cwQ 4mᨩe'tVPUAܖGGeど/ƏQ'Qg Cxx &gb&*$ĹV%o guPH[aoqXTo[ ̿P#W,E[-|_eIq$f|H :,<)MYfJDJ<&NO<$fX-6۬)x&%gE\Q$e_ H[^\Julb%6ΥjvXpvg.jg@U)Njfmf֊ 8GVRĹ+8ayA6Ū0d`j,%"5 T/m4|׽ҽֽuɆ/odQ1 Uj+Q{8k%8!S-|LqW D%VQ @GDI X!1J:\<400l3<p_ߥZdB:^Ħ+m{>A*Q7F1FPsbNU`a $`(G_[ZM/YcM-!4 J_w$3xt>^3Wg`& \.6g)32 |Vgjdm\*r,hcbh'N*7ؤ:kƚbӤpɨ\,8%*,<$T,L,B6PWwa6dn5ЅqN0w@O&+Me@|"5ɧ8}K41e>< H#D L$\M+e #%TZkL j]ay+aիPz6vu[Ò |Tg3ٴ(ތD䊭 TX/{8 > 8%Ps$H}'XO;f"xfiY!PU<+׃%e(j@snKE[3 W(tMaCZdc}Ta) ``଩ jN`X,QEb.)$] Z3II/ GIl졧PWԑE#ücÌ/ twwu7ABµ#b4M-Dȇ<U)!șG)V%gU 1i m\ o 㷩;װ*[̚(2d7`c-7e?U-ǧ@Ⰿ:DlS3t\M_8pT!IW($;Q!x5qgIsMD F#\*j`&ci R!Yy1gY؟b13*Z;̌8Zp.dz͔D&h zH_hL{'A7 2< 0xozz/}6]1]_1Ys[w \槽 N#w_!aLճ"+ AQoZ@+6&2W\}wat`\b=>.VCl+ jgr4JoSꁁ[e z$T~Ɋ <X й߉9_1/`߬-ay(U,8伳gPS1O D'(A #Aߴ}t?Пd꫟<>i@|О?i8E~ Dym dDl ohqzAkf4jܸ o r[qa)a ,QxQ3y_i<9!bdsE.[u@;Nv;T>*cxl!$LšhAh fZՁi/, Nxȡl 9Xghl5>M3i yLͥ@L*<$2o`s5tgXdA ThD<:I22&GPilYkj56 J}SOPm`|>|VTY$s^_|Ugؗ, / #"١RFOxr4sbiH1ֆ|yTqo) Uln/Xi8(J5VB hK0t>wo{^wTo{Zf^ySq[qrNe`GGɬ@tHM(cOE0Z fQX r8W Bcp@tLK$Lej:Wd,%&ebLȧBȐ\20 Bx6I?%`c-b7(QqAA^#Xw!?l 1Gbxb槑(U4:KxH2KJ"Ll AHǃ.:0> <<8I~GO<'?/|_ Tݎ=5J2cYDx O' 9 FXzQR`daO^_gZ gϰbqz>U'6 J!Si obk\6LzE~ 8|+Jj3_(Vl^~\Fau >jA%L+pZI2*RDD#- 2SPPx0`tNyDЂt2/iTC]Ue\v{G Ӎ`}49Y{[}gp:Qu PG\s 8Ҝ9=뭽Y{ޚˁ{A!g7qk//1G_d?P{V[Uj{#9IzGz_ylxfNd9dNʧRED&WMVR~&h..0C[3 '(.ҧ!,}OeE0 N!-.|%Brs6>Wlx.\tkw#d}ׂtث 31$S+yFJ2.5 %5b#($qK.ZX%*c Rɨ<2" L1z'?k?j_)!sW2ܾV]hЅKl&8^<|W?HN~L-g>n|*dkɡ_W ػd|' &UY*Wj Йj&]$D)'ۀŅPYbXhH= ]M?^C?y#x 6N~y)BlKmZB(@6?Umt WGZy䣿Qqy-9\x)6@|#Zt(7vp}g 1ث c.# Ȱ,*V $!GICࢀCԩ!p n [_ 3TܸG/z@ Dda'~dvrOZ@|}k?ny*ۉ̂W`e9 c#2&^H|6RȆ0o |%DYG]{gY/)p1`/ \䩌uOkAj,XłeCE+e=Rz(Y@AQzSw^XI2*Ixx˄ !Gŋd & P5LHKAY9Jd;h*IbF)Y ,Κ)ʢ*@բ\Lqx)pH5@E|KoչJP;6>%xWtmł;ʅwK*ߓ+Y!Y@b'10~<.CgQʦM">A~&w_eo9p>(|%ۋdcG KV#/]@+J s_Cx]⻢/+K7wA"]{U$+Iߕ,+Y![jp\vc` PR+JŠYq[tɊ{īI |^HjնW=G}M-OWI@#%K |&NB'K4"an-ګT *~h\O?Pb`(Bs=P+a4m$XhR(!$rTKù7O[aB-Yp]2l 7sK绋/-^?KU'jC QHRɠ$kc[!0仞ʶ?m{(|Oh;edKnݔϿ ll /CdᒍOd.=o~&یصl3/O۞(vpm忀l5)pUO񐯾X}G ܆G{ȁޟ>M{5X{3B/82AyDo"UAd)\ phd\޶ j^nKfJ3f= dΥFDVsV?PK\@'1%CpX<!)sM2t˒ɗ SJgݐͻ&u3oޝ7Iu#I ^oyϽz!HhmѪ[Dn/).}S⮘t< 4h;pIBdDW>~,[TGɏ5>hӢJ^8H)fҹ73oIߒN)|]<:Sݥ3ܥ%e ˗=| ]5a7 %oݔ-)Y~+%[_Jwy*N·<`#J)(L<-*NA9ZPggm!R_й?+FyOnң K&h7~Ue$u" Z!AtO)?J?v'gլ7D3'_(}^KEf(wKN*x1oyшsaCAK_s9oȤk7/']r%,E g'\L$qQ:"2&\랇p썼 7ESaͿ-^zWPLkŎw=h}՝ם ] ] 3PEGE_ř<|gc}}H6K2K|L?aqzTkxc|cz'goWgߐ,Of+ݞ'KtL7ZyJ&"܊^L$xQ6^M?Z9Wn{?on45$ tD4+-3PԮù^f4Ā#ZW3s5+\ K"IR | T (.ϛ!J.y* p9DD&3$3`AqtWr\{^0pgEC9?BrGs!ws f* Vjt@ &͟tV8@:w܉Ws\˞v3gm\xU`9ʶPz:YWÍ!`bq$\a2J}MR:$ `A2,?!`_31_2<'ooy%_DC<_(~y(_sGj̋)gN93\PC #<7`,|/y5)b8t?Fd= ݳ\˞_p% q\ Q<^;7|$Ӯg_.~ L∏Ia[t-"e Ad(J0d32 o D.f4lo;V kYs'{*wIDŽψA :7p``򕜙6՝ 1݈bgALWQDJvyV.v5gڥIr&\2|1@Go{ ZsSJΌNf:=H#A :15…w׼SVIcz>eY3,q(mY7Ϛ_v>_~S0+.L8=L3yOO >!xR8 y7D+6=Xuhj<2~cLNP3@PzRn$f >dQRf`lfoTׯP.? `GrzmO>Atړ@N9=<縠ߩg%.HF%tC>Ca{o7˕ GiM )ⓄATX&ER&S*CJfq#rTـIfql". A ҉/DMqÞgMwEsg_ʞr&ksp0/_H^#^Gr%ZXp 'LyƐ Kp2=O #,/{N~%X^޲9s/gL;>GzqIcGAsX0pccO \ι-\43!8Q.2b&Zɤjx̰0jVd<SG: R9]P.R~_]:YX Ry 2[N".*$L*<=ñ߱_Lg<ծ#&dހyڟqa݂f-v6ߕdgv=9mߟ@Nù`$GP<7 [Y a;Apy4!M!ipO6K 8!G%e~(tHEH4_1P%">OӉTkg$v?M}Klmki`Ne;p0!An{A GuoN#'rE&@v僚 w!&D s%q9DL6,:@~_FOBކ_ɷ?m_qY0`‰Dz@=&qX6Dw'Wu>aC¡'\Ȟ.sOb`B8v7xBxPLih_!E+%1Q|+y1Ьj@ q :ѿoaQb7~m6 ' V|9-2YD& ,<4AKi dPS&$3㘗#@wWO5_̝z&{ĉ3jp޼Vwݕ~_^ٽf;9L7EWfb؃c,b@7Q&KC APb G.z8!ͻ # r=xԱGuXiJ*(\LБYxp%x]yVNksO9Pf]fu@^ǃ@n3f;rmi9цp%f[ӛoMi#Ԏ;Mp8ܡT^yc' +m6(X\Hɉ$5$ p$/ceD+6|Ğw|-=p]0Lࣙ=du=i_f=-wg6ߝ|%owّzgZf83Ctw~<&Kd1aw_}ᾗ ݮ5WsOgO81d_JIwݞb[ZmwdՉLDn0{3:Jm-&SoJm1ŕMɍ6&5ts\_Zmo+GRzrU8tKcLWL,q[%@2EB34t:Ud V<LPJF)X%cAل_ cybgxz- g:}OJ]-v6ە|GZinpkFi·q DcH}RS ߌÞ(\*KNs''2Cͤu\)5)@7%ӥ xa: 0h8yE7O7K89$3Zؓ и#-9~n-v;:s4ciE$ߨ{.}EOs<:V)lb m<A90_lSo߰qD08i9@# 8_ @yE/ ʫe~Dٗ8`WBm ķؘ[oNj)椦$ܖzwjY `o,yNa^}Q8pڠI]~Ih _jCX-.[]Irݔ`cb.657둴.yYahxn& |2 ȼKI TPik6fh7R"bFÊy3h)3TyYtd:B~>F[ӟ{`ƥQ'N7 IM@mHsۘhczM)6%5ߜzkB]$>6J/>7c7Iw͆70*&S(jh3ۡƭWba*2eKAXiae=˵V`*~ZR&%rJ(f2\kt*H{FQ/_ӥw[ݳO/ymn)ychQ~k'~y.eO:6tO\-6D6[tuȪ5 ׄ6Ztm`M!@67bkh=ݏ>*0ϼ 5_|==gᩤbm9›h!Fbt]hCXMEtt昫3+6oy"_w3oq{zo m6&+C\tYxMPUMW5YlBY|cPmvFt?8|+^ivzKB)B"& xL)B2Q@%8E#:]f}G7݀P8y啍sQ"4W),5!|YUpQ_xh%]ŋTvIZ$)R\1( l,4K=㱗=OOen; 0AW,p|{|n mƫCֆ n&WnKX񄑗3gz0۽uǿO{鎼Rtݑ}6_by@_,늯6^x&+}x_~P<4jμGM ۱7x)MQaB:^@2[Bő_t{K=: CZZ"F+7+\t-DtܛOd[t'7bixXA 4)lU4PЙ(VYhTPu+z M I)9|"4aeʈt)&SDx"|t(:P7O$o->8b\ *|pBY:m5hfl 3י)+>Qn2 "'ԇ,|5) 2hUjUq RE '4 +dzVeJAl'KN$qYD@c+ɞ{$M{shA W^ܯ`c ~9qY)_Μ~'osOP[a;Wٷ*OM<7pʿ ?_/ş-c z;/v\k_w"iu't' wiw:EgQ߳Ƞ*8̠oɄw,.\<@=K9s$gSHߛ.oįߺH).iܻ͖4[*B:nu$mżٷe+υ74lS"&[fh*!ì{n\G3?L@BcQqœաF=%[s4l4Gf*IDd> ÒoHy ~xCɊgRF=<&xX+[WoE@uYu&w3Ldx`#-oK(|G95:k%i A)p^"?~w ? dw!h(OA@D]x?edH%z$;4۵E' Ʒ/u}uZ8\㌖o.+kѯ>YLwv8$|Fa=?w+/eg{.`.߹}pޛF޺{`λ:sמiW%_-nJ[:;R{` ±1mB~I!}SȯIԗxc,:x ,qܧŒ/M|q] uyr]-Az5_z{"J|Knd y+|mfcayx%MH\-TZEjpШ)7 E)n%U,<9̵!6@(`-(EdP;,Zj*#R2p( rQ]qvvףR#˺o͗~quz Az˾,dgP@q%}/@e22 pDBKT&x"?*Iy;~þrn=[.z:[^_ޢvuw η՞'=_^G}2t7{'`)XX/ůh@uiX7ku5g>un7u{Mo:Ap᳆ןR϶};y"eҗZ0PgoCW_ t__u.m[[-CqYł?oU`;gjxs_y-mSOLw7ԷL,HEE[#ij:U rjasTpowH2,@7h͵({"kH$fRQƇW>i4^>=Cik u:b] ՄXEd@:kT4v#^Q(E ZZPqO5Bfs\4ƂS3{7\1G ب *$l kˏLʷ?m4IAf??i9}2Wmx$vص//FwWi $cx ":K'3h.o{,9;z_Gxӟטƌ'u?j0AwN2˴ gv~ތf?h0Ai=?g q[`Ġ+3׾U-| X})y!uXuKǹ=y9/jzQ}Kn :u}7>ĵ(~<:AM|"QBW ,UQ+#Rg('$Pd"mhᇊrEنh_L VZ@$x!/S/?ţVm[Q#M{p{ԣaC~u``9N43=fsve3;{>V=sX5^;IMyOkyP{=wκ2n4^||5u+N_#x}ΤTB>o5gFV`hU]Iz;YцLl(tV. 6 %O?(w?8?y>˟^ќ.3or3nwθ`So7p{ns4[ӞWPml<] #Ēϓt7 q ytj>&fSEL2B ]#2)o>xg^}#oͩ[|-zl{Noמ|ޔ[ '^k0rIW&_v|d:Ovwrrʭo9֘w~p4穨>mۂGgܭ9㴻]n:FIݦtv[ufxԚ<۾^WgK Tdʔ%%JRZZ ca:2[:eKI2Hn aq=:3L G\2؀$3Jɝ$rV _qjȣʬ;5gެ=F7]glG"A簱ylNG&Ft.JB&:JLfl*Ma@̬hQG9V}96=ySO+@AOW0"q4 ԘM b"uPi("&'b/BM~0/x9kK_rسNCqް}v pö;VkZw8 Qgv t~ v ]on!kWg:uww;4FG /{tnG^ǘ?&?aYD *q,AE8eQP 'q??*En_mc!M&JnFL4@fNYPPqԇ챷++F ] 9^uؑ=tus{iԱ*V^gێBxV{jYĐROY_>rM|f fG*TڷOfD" 4MZd4\F$G?#73 qk ;Tij.;`o{]sCU=XyԱjKřW~̃&Yp{ <.FfducQ[v>W+4XEt܌4ZQj3(ITcR<-xK7ӝWD]ku4pGkq.a{qTs`0M<^g"!eT6 :֧@Hrx([Fgw{#=2׾՜ nRcdHb!]IFJ3f]&y@r#.L@uLE TZ>rH6ği>xvmQ#־m;Ӑ}nvnuusVUg}>*YW}9][: Um4pKš;*Sq˞6Ŕ%_h~0!N_fl|akL6sI*JP1kޖoJaMfmF *ZLΣxڱX`bP\n(ȗ9bpO~_ծrvU}WV뽪RT齲jAzο@ogu+ \uȶj8N]糱<Wmzm*k dFr[<;̸R܉\Qײڽ칤/^\Z Ȓ=T /W뿲uN=UK6~*f-o =c"q &4O%@@F2JkJDiD8od4].P&fm -@)u6*3(7 |Ğ?>]}$x|T۪ű溽ヲnuuz-?Znn;v暏cK!G>#'&RZ6QU~QAXhm+w4-<&l95Lłc,oNz-nmK5unuuix;2lKOڽ҉Gbd`hF<6 "4U⬎c6+.>hnZ$KUb!ONX L@+j TL9 [6B PQ'A+ i%rBhpJG2^k烰S!@n%vѦ[eVbx!BD|THٷ}O6ᆭFU=;wW׼:빨uo{Cj_~'0/S,2LK,rLmUlZ GT &̠6dEp}:#3 +T $"3hixdxx+އ5ӦMgjSݖW鴰Zׅ5V2zY l}Fnw]Z]gW< HUΫuSu:r2A׹ {.muKU=7Vܔ+57~h}2j`3:P[(E!jC*&ԇഒeMV ­@Co 7$B+0lPѦ2 R]KI X8DpWS2ɽ~߃Uڭ/imku[V:2x6걡j?]mBVyr9zN~ߥd4=o6S?-* l dnn4jVd2*SD ,'?N{xsܛ U*ﺤf/Q:;uYVʊV4xOՏ;T[s8=Mļ2,Z'4Ī ,1™!'u2 4@ 6)Qѩ"2M3^ H]Wu+nKOg؂FqvE5{.ks95;̬nO8tWd.S]Mq2~{ΩmcU;ͨqzӫ^Zf8NYq:Aϥu{Z2֘^߁Wf>mByy=ξ!iXtdlJ\TZI-DQn1;:6\C%vm%[L$"u6t(@!ŒSpD,X`)0㣽BFւۏ=WzXn9,c~n w[eU:To{˓1.2 !đOpDOR|ܼE:Q20\9 nR-Xy^6 vy {K ~љ8A":!#P2buV&1۴/Nbf En:]IP(&# 1Xp;e>Bdى)޸W9YY gU42ط3j<ױmfTh[Wi;ji:X'6jP̈́j&Uj=rI;Msj7F`$tS8[yØu{e%;W+ۛAx1B !) *=5Yśx% W@o/uLMʩD)+$2d2(?Lxعכ긨|ǹU̩ VqVvs[̭zqk[igo=?J$R0)tC94QlaDP^%ACʿ'i/P]}yRŊDtV.(OptW^f/shءfW8FhE 8&*Z0`Uz^Qt:p9 {J~"CЙ*:n&2xf`f`(Kj zSF1*R<":OCߣ_ >N?m6nؠyƞjnCye^8|YU:ͪϻlj]\ :.2mgVh;z۩Nm&9fsqNl5j[+vB㪴Wivn5ۡ2T賥6v.j`;1o@(i<)eaR,%tZX)܊fhjʯ[Ł%pCq@!Q\FnepdNYXD*= #|\x};cΏC&lsM#nB`ۉ[Onjv3ZϬj^KvX J}n&.T nF!QCdhQs,|Rdk=b"**JyNWiZ,%r$3"C=0] ?v;yciueٶvh367k=Z1M@pBvP~Cg>E"?eo bvU`HqDSpЬWx2KKEPËx'[w=#j1s5:-zn6s0,93PP0Tm9JU[ϭaY^[~͡f+Z嬊mf:ޠzo5ƹh֣U ͇m1" Uh;RLUݼr-g;[\v>%zv-n峼5{,W-L@wZ21d5c3LYX-*ce-\1xWFJo0kCHXZSB<c m/{k:o=Bi:LfBc*_ͤmͯ~NEЌ]V:;Z{ǡ37xjNYgؗl,4QjZc1YׁY sD)M[q5DXIFYxhnӋ0ԓGΙskU"WTfcAfg-'Vh;\eGq3AΆ7} IT+ED4JhmJoE Y#`KҨ GjJ$xؒ"AC-^OE.'m{-*mWm9b)AMRğ[M(jrJY[L鴟Zέ}m{qusz,fCә?5^T[ l=ұ𪭆Ul9HZzD*4Z Ui9r άrカm6>|1rƣ^AĻ7NPtICZhfPF˜>8k%9fgbG;MhH3n3iXmFPS8<|pY/y Ul;J[bd#k]͸m&VLٗ>afO`n.-@;@ chm¿/}YdYp6#)B9&2hXM8u~x٘y [YZOr-ǖi>V#+^MVi9jqOӜ }U]ؙo?NoRQy&$D43P#GD-EpWg,Vo)RB~◘HbqT,$7^~x+{˟x^_[\$On\emh=z+xj_dVs:,7doyۮ{`lAǎ7s)MbBcj^Ő-Wi5r.jXVC4\J͇Vm9z՚ zRvSk .rZnf}^#S>oJߏ^Ƒ_L2&ktOB,Xifu#'o?MUE48HdXɚbELF^7o|k^ @mܾ}jca[~2 vl)vSQ3ivx[9|hR*bg)<-00Z~F7}BJB5iDQ~1+CV;0{7:߱ń|tf4Z-h6j!Ut'9t_\iC~ng-MH і`wTB=~v8-rRvk[*mFTi7fюY[ul3ɱꭧWj=.ʍ:qcn ϿXr[XeO:?RrMf:4S Fڧj-WoѷF~՚-t@&+)߸ofj4PӵoCxX#+Xr;Y8wv.|ݬo},'YϣId2pO$$^m&+bžb6 @\6GI-VI3yLH&? 2>5}#q:t:c*]pVCjnSۡ[ -ajٶZq&_bGv'*"C4Pl5ʠRU 4;V  ì&\$ߒO۶}AN f5Pik1l4\q?50`'.~!|5SޤQtO"54R: m( sbHkrB0(#(Ea:" <6ɤsp~Kz0G/{zڝbCI:v$<|\ !đpts 2EEdl("aw:?X 1*w9S+ib.4(@21(GFML׼-9t.Szs>Nmhѿ|Zwh8s v}PK}&|?{}ɡ"Q7"W9Rcwgl rc0͌27DJ$ӈfo F͝}uM[L)͇TB[i*MTkڿHGk<ޡܟ&ms5T0w Od8+%KEHD4ۢ& a}gkwS6l|9M84S0<}ʍ{Tmܣz>4RrA1HwE"NLd˰<-؂{{ Jˌl#"@-S:" L$A;XIDAT|c̞!'_,{6Xp(pvldcʁ'jclݧF>`lHVc[xojH\ZS7ն O{Muppd\{hһ2\Wt^ٵ[Un5ܺiأ[j*wA:(F+;dgݎ?zI ,,&'Q%~a +2XAU&6p-*DGPIpm[ɔ7~TP*29j&]JfL<* gx'cƷ}t Zro4B՚ZY{VGc~n4ɡT;kn~7#cڱ'_H`*P"5k`A7 .QK4I2oL4g߉ ;T6K&94^VM֭kJ:WuZY=*6\&; ]{>kO[nӯ L,4OR5!6hh(+*`VLn2Zz4^ oT$/q(Uw-dK.$L|F7WjjּgVj3p*5WZ;yR@n5e`bjz)*p7rVn6ҡ2n'vҵbΕ\T)!}[cnTpTmH6|ZkO;ψ+_{k믄yxh.!bа[:]lr =\(9e(y ѝo_o-߃6eՓV TLϴD!w遷+#c^pm=levh4k/tWwѨsu8vګpFw谸τNG8C*=Χҹ eTƿ/cdQ&7hf:ZLM&H}&~_~áTo8mO+ڳ*܎]*u֩kM{;]wS593|7$_%J)xFI0*xe3ccZVή۔@!8 t\6F~MރYxќ{%u3mڑKvٕFWrVrWɥWY>eg[y?Ȧêp<~kL=dLJד<{k<`bi~c~g7ƛĘ?FXZ}џx {ِ٫a]G8SŭoUc]*\~Ҁ{X[Y^UqXe@n6m`?`'=X^~R ~/4Lǿf9dB# U(yb嫽|Gi;}.sfVTmhBm;zUX*Ⲉ" O;r5iGhO:*ӠwVͥcu5uuDoF+uh5lu5~yjCk`Lix/V-BB+IF\|Z̥"QSu(~p`/ӧmv : -һKj ViйrvڱzN5һrAe]9t[[unW2nnizyeyx x+#rʆld :Jm & 98Fb' ޺댳(dCٸms^ArVh2rWl8LaF840h=OO^Bpwf܉$k90QjN5~O1}Kļbב@u~Jφۨ\ q֨wF@X^rP/+PA* :VߩRΕR]íO}+]Se?5\0\a$7ϡCLIjXXBχk[|xvoVU_BPg"h+|8I4̀"2sâ͞AbR9.t׽l궯R}F5XYJMWh6l/TG!@y%fvpV=W`A : d2R<@xKޚbݫZ-9[~JuTFKC*5hWaN3uڷjnFt7d[Ӯ`T?Ӕ׹!b&!2ܦDؔQHJL4nL {K< Q%z#u.nyUpexOMװKŦ=k^hԣF~5( ,`HMg0Dݍ/zDYˍa8& I&Eó / GL5^֟-9t-vն#&we&}kAڮۥLN?8wN2is6eVצR6Uw۶zvҰg˹ ([Cq?u[Vc!:qW2fRQuƵ"` ۵\ec8B%AhÊ~\3 j}`cYZx>n)̌.cRrt<*g9B\̘:uU uz98w/ӠGUǶ봩ɹ^{hԧ[ :tY %bl̓﵌hV\3_4eiWiy4JE T_o=uML-tύ%UsyNWQm*뷯ZCFhÌ~0?J4xf`\J(l-$J V!PY(qQ&~'7.{]{gFaЄu;.uh:BU]kLʸ(hP5._Gz]߹L?iPOέiYƩUڭ*nUɹezjiQŹe*6h_nv,18]'8Pa‡ʞV┿Fi ! fpRZ\rjZBx4,_ڸ]GB6p yAysg.g' )-0orB`"LB,: L$#,/Qn2k^W;ġ=u^f-+;^Uzmk6"^7x ONUw) {HX2 JO[ϗoу0L @JLf t eM oSラjݣ]VwR4 l?:wj_Pݖ,נu9YTuO_R'g:&Sb:F& 5H)ͰjpM4x9z*MK%HTa I51Nf>FLh}mzeW\W-Tr[ݵS^U]zkݡa7..w,ťg%>?RvqIّkoyd踇֝n=N `xH%D}1cSPr*YN9D`gA)8c,tKsbGCkyycPoO{\O :uiWn2pPuV[ռ0gGվoQKP-$LEV[`o8?@3aYFnMhJtd3/k=Knk6XOT UuW߼K˲.m*Pٹs5Ukv豾O}o-<b~oJ3Zk2ˢ>VEx%k ˥ '`Ì ׾ V\3[YFVpQAך\ޥϮʺu/ҵ< u:ޡʊ3.n<]I{XnDO)O& ؝Q1٨0'\<jh xv#>vn6qP{Cҹ\6?mse\Y: tlQVN;5/[YYxӹEz*o]~ۊ*toWѵOE>(qJ.a_ؠկuk/~ !^dz>t2p(\ 0Z: f EҎvb(b,Θ (4qSbG_p* Zr>@H hHg2Uɍ|\0\%Z3E8#_[<g  =H-uq\^ UwnQֹeǖ?9,ԺRZWtVέgF*RqƗ"=obz* BPR6I\\v2\>f6Z*r7CiksjPgn:;4ΡA۟]WlСF5vܣcPVx^KH׽5 0X_ߧR߲H r1h  , MidSR W@m 6h qGM#glz6pܾ'XΰPPEe@`-ʎUUը|Fxqt+%Ff?9*ScYgTJbvQ]6>y)vsÓ/곡G@-R,^pttM~ZZ&Y fԂںp6cq6 c1&&)Z[MU3) *:YE*BrNHT,%9:FDsɋQ0*&^&h ?JCjhnd p拘dtKɯwG١kIkaQtܦJݖءfMUkRF `-SCN=tXt9GL1蕈V:JF} F7!u 4(u<:: *m%F[  PEK) (R ]![>!>73[_ʤk{ke 0^TYmGQ[cx @L mOą EF{Ս/Ou}}hԧ s AEh`J }i;SVskKb91H0\;q׽ʟ.lS$u"A?Ӯ7^ <|S_WG2>EVK]qμZpr]Ŧh8$T]P6|*ָRKH\ [!u|`Y+,u֊ Sq59e~xS-w*vO>? ATQ_"Yb';OB҄T]LE'YD~Hdݨv}> UgŎRmP(ծIk/w3Ux]ϱ2!{9e;AZk)Y t\9[oԘf&5@Z1ܘ Q,5@d֧^^iS_i_k^_@/6WbmJzcz ;l9ʒ 7iy9ms5B%hai%c#5ލS}p[{.`cZѝ   $h<7{p܋#\>CxbKLv1]nNdRY&bcmZmXUDQXmU%År׬>btN;.L/+t#sǝs(Ra!z}IwǩwjWD=ӝMOQr A\Urq4%X7dY$CnDiS?^n Dw %]N<ޏp&tΔuz"d充/5`.Sj{PRTCP3W挷l ~xΌ8j4fblNgln1U^潱T&Ƒ;Tt?>mw,$h"32XĖ:== UD:PE4#JE!="oȏ"DS@z}'[npqR5!yz/^`35\3DQT0( y*CRҧ7鳪 e7R}k]+]:0"bCJ1P`3>5"ra9Ƈ2eQ#s1g"}R!ԘUf}hA\rJ|60S/Aq)yзRp ).y']Nws]4c_;~>g? ]ڟُ>SW]Wh;pzm^n$N}9aِW/Wk9 M+mn."WyMƦb2QtShdc`&DDә$$Ӆ$%R5)TMTE69OZ|ezk},c)wL^IAjd 6<2xH:( @(J=hB7$p%<'68ԏc׃b{2}w+RH1^1=xm0eïSVenAρ}0 ԁ*U7763)<2qw|3fX${2ح\#qaK( t :^u{٢onW/9 O"SwQkSTiY6&SarPPӦOe=|޽s]>#IȜ$NPD~$|Ŗ dnvN\@r<&8 /t=:t{˞3MšȅiJ)5eBk-o)uj5D+*Z 0F^ޭ 8E0E/TԯR6o{.8ݘ]v>;CЅB=BhF!מ̱#qI!OS'CI:yOA}EW:|6j[*/%iT=Ei.1&@Vb6z6XDA&~OQIDݽD]s͕ڋOgb'Gbž?B'm__#`GN^܁tCt)6^1'vi  A5)tI68zdaF~:|vy"wĝ*t!AJ929l#G̱)j;ݾ[G }ͷk"_/jٔYg|{(fVh+eU;Zp1BR*Gf`s_/.mi8,}$;1&KL{bĎdHݨ/@[:u6gAgݨ.&h&S暃 23/gCov޾qK.v|<`! :xL/v8|$EA/rWK`K$CQY{=;wi7ʈj. >]bnqH[ I\m77V#g4|F8QX ]PZk冀 ~%THY|\z_Pú dXvs`)F1%Wd CU@ 'tDafTW-~~8u!IX4+Utu`;מM,Qč?#AZ\8Fʇ[geJ]q )Ot?wEB qZSLthOf/wo/I܇ 0!Z\ @7/cAdIϒ xx&0Lk3 i L[i+ U#UlP`KG],`~d},/I\!dBGL{_Bv}8}s37~9JK,ͣBͳRmB.JU˻^7Z0u-[fg;@H8O&(mvrcshL}t>8pݚu4KZO6&!ao$䝹"/A Ih%2܎%w&Kݐ nta|8+Vw4}F 1u<$ՕT4M D&0U{>dxk˰]>3{f< ehƠ+W_/[vtⅧfɘq=w%ja?^xЏ 6lG7?Q{O:Wڵ/tGҌM6.kԑ $ A`zSg{kJֆ4݉]~דx%A{Qd,3EH8 ),{GB{ 0R+MA1@d.t5 jvdICʨ<9e 8:P.HD>dqSԝ#A1hUw5OT]LPO\HԝO_H4O051H+T-Xǻ oUοf'LM?=C'ћ݇8h*YU>+D _%F0d-o6}sOgOgMQ q3$5|=k __B{|g%_bstM I.RoV# [d8+bGă)#є^^N\L{8ECMBUXqYmmW@H c &sE֔y |9p1?Y/u$vnl߁ɐQv8ؘ,1rx yta_r_yp:0DKrs͙8P+1K1Qa?ߩXy9c=7l9 $[CP⨐#se2oԏ!쌤rc}bmp(o/㚮di# 5I mQ6^4f)y:\=ئ،m6Z><6s["F!1 gy)e2`y=ڴf쓹E+h ٙ$Qn댸cAQ Qm8ʙ8:2CN7~,i'_ԗ% }a}s_U.Wnj:8>Ts(Z{(JszohӶݮ]ybW3gߕroOx~kp;ϢOy~A4l?,J BA1v!KG? @Q%hϼoxuhaPg*]/9! ]:|}eH嵈ƃ.3?HC3@D(p@|;2C͖ry26VT`gbW/$ig;ərz>0DIo1cT"G+Pn iIh~H}{CTWmRÉy;'90h{2 @.HO5\n,X 5qo΋#3 @neHzuawm.6Dk*ٵƢz#Ъ6l[ٖ>$f|;bݦjUV*ԛawƤ|CLa h{5Og,KB\$ܒ8#͎ htkO:wbԑk熋xe~Ȯ'ߓYpi׫^zTC/;}}WDŽmn#Y<>G#IN)^XB:cB$Dv·E=Ν+H"OS, =bē';%]+ {#9C87\GM{cT3L-Rsr6XCOފm:v=GПL؃`mSL !bElXB)M$GRGKgH+TmX8,mL6Rna-k3R`,&H|#2@bW4q}fkJ9ƚXn-<-Ĥ鞤ěCNߪzjsxZ?Z&F|(Awa怄T=!АBg:FEsDs<>E/ [CVNe$nI "L[</ܛmt>8`ḰXȡ!XJ|ϒ?nu?Ni9Lb"b llZwctG/޹ nLdrđl d YH_EN[Væ ծX4}`Q.;]J5Δ`V4[ߪj5ﵚ[ .r$me<{bNmVoU7M͹)ք7WcJY&cu*f|w0't1a3Ta%=IO2P=X^N c8=M%]z놘['H{ͽ!ᛅݿG!aHF^']ډ+f <8B\7|9s79RNT# @,ukU k· $I=V R&q_F~{fb QٺOܯ~(uw|Gx! #WAB [H'@H}؍/㱺`4I4]PGj5t[``6'Sm-8ӵ3T ņ){1NT'=L fp$tD ф! \(u\z,/~C9z ogL.d{'5\2G܁jG|"#Yɒvn9NBl7PחJޯDuT&` |q-NVxڶ 5ajjniyE)mujZ\mɯҧ2ORAq߃~^áܹC>a2bE#|!Ѥy v"xx>$twGgsG,}uީ%z-kY={.SnRD1h}^8"W.lÆoGlda̍)g&sR:O+Q;fJ{sNBi4|0R_L7uEHD9,1ẃ߮>?mʯ..!N@gߞ3"[XB"H a5'{'ެyX~g6VZl6ʖhOܿ ¿ŃG,xX!Q!7R^]n:1<,dTڗ.!S4!OK=ܨ\?$>sǟxV1ẗ́cHz߱;O:bʻ3A`:>R9I.Hd$u *螈 54H?;Vu@Ai/$nhc^K6X^7X**kΪ7M-OkNb"^ҵ)5DlT(2Jƨ4Ý8Ȧ#;V}`򒇃?kvC| 𐺳 ;9NA`"MrN<5[vSyMsN/{:d2Ys;Ru(fџnv EI4!4 AH;RO;3a '~?g'g4pebwC,ٻ$.T_rrX|9 oɐW}3>XZ8d_/>~KXc<OIfCΩ4S@"jb'Za;;-b:iiRXk-*s^[6~TíxH5?ZպGç6i7#Q_#^ 'qw{#!k,W!Ʈ!m'm lϐNݿyc ŭ.XvGw =('9N !iptǕ Iu$  QSQY|&f XbA q`Oq*cjQެ'%3lEXv|UD2$S/Nw.B{f멢kn =םʶg\9@1L!c3 aBkkU#T5– ,%OnV.9׏wg#m $UH >>@(ç]=+q+w$ꋸI||A~@"Kn,'Ƴ?<< PК"cէ7p+1t?z<)o.yPxT iRIJCXvqdG;ZBC> b $ r9BW`J$܍fכ0_NW 6xdzxKFS75C;n?ovi<,;6SW#O dLX3 ;S͒@#73 |:W0<6%t_k:@xMÆd;(wj9 zP$N>“RA )g$&\?4x}{ΩCWM`1#f''FB$vBB9ąؑuq=loǟ"D5g.MOeϸ^QauUw.D(ƃ~۽7Z>yBÿOVmk-Fx)

||| 89^$;2bˑ'Cb8 3fIcvOP0AOOG4W!ܞSfL4%TSL 2[%ͅHO07q4ac^׬6㙊 7lHņy4eH}6m[|ܽ)o>Z)G=FmI>gxN.Gwo ,2AWŝ\7 ߙ9O,l"1 $[4|!=t>W*^.HyB^ĵ yN4L)P8 82Nņ}6.kHUi2!q3+6.vUР N T;1b!㰹 drA8%c,W'A+ÕSUw T1E R}r{uv! +tBB Oe!]Hϒ+C|I<)r?Kf]']Gb#H\?Л%tc|](fH$ ,&n#.ވݕGvDiO%}{dm1 qɪ\aKZr,oalvJ~R_!afbCdnCC3g? =!ύqrB`K" O0%DIt>p0`}6={X4CԿ AĈ _<;>QHk1=_xQ%nITHl LR!l 0(`&5|#m߭{8QC+!S?PDJÕB;o{wa8x `:%pzarEH bPL\qcҞ$ag|cٮ4#mπÑ񉥈"a;BL>TG!+k =_iGtO8̥2<,G平^nO79θ^ i> >E˦9D ;Zɇ~Xd}xCq1#1t1)rD2Y\C -!_FMqUpyoymywk3w Q:^A1XB&MD! !ahL9K2$qzvuK7>pExΈ@X"P,D"qqb ? F}=/θYcվXڠ4|óW| Zmʪ7+M%ZsRMa9b\fsm|_;2aMl3AG[,mVsk;ZjKRYc|Un~\tUH HC4*v]B35_.^?Ey:/k.k,îKʹ[)#$88b6mhL!,4ʟT6(8=iB&.[ҹRGJ; 7_Y0%esn-#Tmxii όk=P[H֜Y'P.Xo, -2\!Mshֈ=":Uqܗ g֎@G;fUƤJS>dBMK lƕmR nV.ȱ]r;!Pb|C5M3d=bhtE2o_N}}{9HLX% cA$4/K2{!բ$4blyb2D5cg⍷ƨ|Sl[.th*-u*YeVdѶm-v[-m b BO}Gk^랤k')oƪGWﺭrqݥgʿۗ=~͓^_6vH{8<.GDkGZ8T9r;? ?~#|QIJGT)vy؍04hcC_}hXN^K[A »Lg"Lܬt$uᢳza{ '8z\ 3ytBC8ev?6}+Mr&&ߟ1Fϑs_Wm Ѷ7 :Z{j}~ Al `JIT  INݹ~]:D,9w:$ K1qٻHaY^ Ɇ3Svyo4\w;eV!$C-5'V6Ե4iejYmSWo7A^B8мTbXaO}ef$n,;/V>Q2ugW}GotGuD(\$8DBG, hH#.ِ@&qt.aQ,2 A+A` }_1L>!(O!#)v'Έtѝr2}X> Qh&eKuݠ~X_tA9YTxP /߬p"8#\1_d-JeQ,Zil*!ǝ|9" '8|({KTטҪL봭6P 2CZY.^Ò߳y .&#yNTŸw(WRn2$qqmfvH~,FANACĨF-H΄OrI9&=gh*~1BUa'S׳T}ha&,G|RyȐ;Nj,1d=I78 D@IoF@hq!ϔ2=>+oN;9Dv<\c)G֝m ѝ\ "$L!S  Hj'8q^ ? Dg?CS.[tn#% psͩtS`1hT,)W/٨ԛx$l^k~hyh~oh 7'2a{&A-ɪl-o3WsQ>!_Tu&a-Kol^c~v6k7W߅.q9p e+ w*l,LdEa>d¶-erGP8L؎=yа?lx]:NQهݶ=3e3o5 VU_} WAK3}m/7nhl)VThmV\m~@ c>?Z1cCm^4* w\y;ְG2]ل>Y#"Лq`L "@x"!¨|jA2(\?{TAp$ɿd?z;@\Q( qd`~"IH| ^t/ɮ7Dn?)7{1ks$]HqIdBZah*(SB+o1}.~s7$ȁB!L4Τ1XLFd& ^̛ؓ1{O]Zg ,T?6d^gh7ZS+׌=L񃶦vIކlD*cv&iVdvʕ[M|Wdޛ)b7 l-"+k|@&W𽐜ɔPhEFp :p`> X-{o˳'JTkUKl(=cH|gN4L7nO {a4׶rLu?ʖ?ǿp2_q6۾flSS@ږ7,4lk~i 5~дo$^zg<}'ڳh\o*߃ܝOH!0k`:#:Eg!"8"h2㯌?N%*saL2C3!ˑ BC{#bIq>'޴SN›o=x"Zw.V{=Qw/Mчj 4Tݗ[/gꎆkvݬlW{^r D3X>tqp,.ґ/B"9Y{#@ҤmݎϺS*ڴ'x.[DR+3UX*Uz:V:󘱁c|a3Q.1_jDO0djxZL*XM='!NW¾z2oKS_ ?ΝƗ =qt/d3yC$z~HACWp7mԱqgT?f⇊-@DS7ֽ(3$WJhJqqKs M%ڃb *0[ F)"*ÞN'|1I"O\s': ԡK'_{kog\[v~ƝњշR!:[B0G(My?E{+p9F{nϝ' 譎.  7 8B| r&9dDžd"$ ?rCy<3M OҕEda?m`nwKtu_\nz}Ǫ@&%ogCJ_Vj qcD[ ؜)>:ei?5m,Ó[Ĕ?GOVd YcSejz՝ou<*艨\;@Ȕ[Gb;RF qX ˎ%L%䏋At\smN_>1SR\L$rIdB7"\GS{Ǜceq㏽yja-_•OP_NR24a\}D6" 1YDzw狥Kw|1q :&>劸~tܠħvЖ{l!ydQD؁!$!+}rtyPX㑗kRCfuO;5@csQ!v@Q`xT[ _^4wcgt;+~ٯIwQJ6ԉ[B[p ЕvALW$dQ,֔~#GwxѲQ'ߍX7zò{[š=i<x)Yu+CyPbx d mG G66۸({}kv_k^ykbq˳ ]x (ő[ekZv521dq/LJr!\q [FeIl1) $`!qA{~F@じ4>i*}!V!es \<wכ-Jsĝ^ s_W.Vc`Ơma{bT4404yLMKMp3Ɉun[N6+D3kOI Aԑ! W]3+rd< +=ϦA_7i+ --;?΁'\_W 鯴/sUژgXuq 2}4`WO*#) fOFg`lP.xNNCWg]K򈭩vd ݝ=|o A>>R> @ !Ct@ "7ځC#ڛONT88N"xQsDPyx2k~>z#ovv΍Ƶw~y5iOdӡʋM3U٪BuD:*GNQ=FiN=Qi|tISwG>:!+eJ A#~ E@∰N5x!h.Cm~-p3Cؐ\ṋ56Zʵ-UHN7j¶ :-= rΜYK.ԾHWF'kF*?~GZÊso3f^3GR\.cGIl'dG&Y(ULdB)+s$j:3xӍ<}t>̜Viɭo)Wi:¬jP㒿ߍn_Bl'Ӫ#z|U!4mpf_dg:).8r")"7u M DGL>V% M@ P+Θ<\/-#' ,g݅Ew#}6+=W>bzyl)뿾s]f{@DcGgSR/g*ng+2|MPݍ5]y;u#IV^=l@:W3\A2a`eU= |?O# ,Q$pe;nҋ m==/gT ̯ruK̟Ӡa$%hm65YUi/drfh鮅+8R8sOXQK)Du`RĈ$E%@Itr|ih]0,s\uVF}}u6|T-k%3jҠ~y=J1V{;K^{ZbL$pWcyՈkZJ8liR2[|9mmxTP˂nxdT/bKw=~(#;Gj'tg.]$ T6BPE,Qt8v *cڻ:#$Xa/ȅ{>$+y3ٝ4OՌIۯ+o.zzOWL9_?J5n7lx%iwpLrzFӭLŝLtݗ;qѪs4mRK\){Xʤ,>>UNI;C)}xV\vtI>]-dͷv&f" 4/tZJ4ՠNV-@=v:@\MDASwj7,X9bΟn&!H8l1ǗM[^G.ρt`q=9,?lb7'W?>A0}"h< z OЀ9DP8vկSw^Ql|^jN~kI)mjPiZ&ܲd?1BbQVi}O+6ƥ[Fݫ\̟n D鋸^,+.](dL& J©I8n&pUC&F`0l4enMxD Ö2>^r0]L7ˋepnaEtS>+l3.; |vvڑy[f]CL:jWsխX9T#i_ϟyRs-Q{1Vs&Z}=3e a+q+]6_ȃs;!@~2gH8nbF-s)x~dOԝR'ݯYT,ͳ"MfրuZ*muʖ?6ѴFE<B$@@ڤ4+ YeRsb.*C]V mXta'4* {U] l&)apŸ-L}],Ypf}HDͭ,]X!"WU}mLhΫi.il.WTkZ-x'>"vjh!-(gh7YI7jw*[s'#0#aw'O@H \Ȋі>3pmH8 &ryb.W-ɀsD SB@Bsd䅰n?$A*noٗūnKj[k#.3:}su%E6?y0e+ު[Դ)\ ؆s՟לM2 WX=Dz]/?y:2$솯=xP<>6)&#շ׵}2}`)$vg>s^ȟZcd!@FSPhb}_҄> !jj&`qXjSN.94SR{7A}3HH[e L[8d.Sɢpg= SjC [nK)bU,gPɸ=Pih|6"{6xix ofu"a.v\DBؓ!@0蓅׮Vj:4Jq旯5֢v* ;$[ڣO-F<1XLwv#)4<ǰ&sx 8Lo.*q@ЌK0a܍xN'l*o 4l%l)⹿b'K!`r籇lph%wz}5s_~}wY3pޭ_U}%k6rq0w⵪Ew R+p$OuGj7S>fs.^ΔB.Jɓw\'C&l!AoO4>#qnXxKvGNY֗ ԋeRkյ)LgDσ[vnɬ1]-6>4oQ,ZΜ_mxcH|e|Vd2$kj.e(}Ӂ)˖z6fKhHݡ'u{?k\{q钙"M:(鵔$mnH|:"v(x>ɣAb?+: m dߙFMcg3n|;jyJT-ӗUZK-|v*{-zKЪԴ ;@`ʘ7=2=H\n< ayGO^t4rRmax,)%a3%4,% 9ԅ G ]EH/l~} Qe~zU*Ȅbnʑs$2Hƀ!r]cŽ=XeB?Ӝ^H^M` J&cC[bYKls>1?B!A> <@7{k :p\L72ӃIJ9I"~3cs*_){s*h]$u^s۹]1\&x(śAp" ϐꄧ9/緸/ZX~{-4)7)7ier1tAvb[g:67Y8<.d?hv,!߂kcLD]O(x.< I[o6+mh>J0i5 QMdMlVxKK֜_i(3&cpd핧ʓuVm;xmدv ó^\@N\; g cGSNl3뉋<'Asλny~k;silIHڟs\\/%<@BWRVƑM O蕲;|ʇu"UQTílsp1ƜΜAx:UKhEM,[a/x2l ژ4g?=y0 @"'ܙ*V$*v1I%!5"df jlEd,1>ir9 Q0qWptJA>yOZEW ߲G*?{smJ8ˣlK8Ǐ <fazIm?Bl-7{~P,AQE f>~ծu<^aL5fiozUmhM-6 ?@dQ,2|meΫ0Qy ͝DSOnx(m?94;y\,g0YJFeɩl;lw)WEQ{=W.fL9wm1kkF*$dJQUFs\f47`_@`}P9hjҙMok͸ܐ^O|ӄSW돆V_~s1t2A B9")/3_;`!{+CIvAN~ Sh֗cx:[CvH;-d>A®؀TfpEXO2dt':_o1JY iO;1T;]o? f_^*ZhS+;9-(%5Vs%&`o,6(Y[.C,[ f1Fk~Xbicq/d;b!-QH`r]aH9xγɗBm?%\G ω ́)%l @gۓsg\AL2%rLN PDJ9]8R=:ۙDݾL?Eǜxjik _c8q{"7.#m4.v=t܂&N('pD !lU@ CCg;wЦuRƈ2 %Mo~c4&|6'-4t{8--:U92UԙK,jðJxmsV>D^hquANLgy ,+JFfjl'-gxyߞ_xy]ή3ixLo0&œdHB#C}q\DP <_Yv !i?T/-VHLz~qi>e)ʐWco  3|F[M6͙ÿ=MiZ BƚUUsKJlthIv^?1HI:ʣJݙRȉw!\GA b9pc@)'xsI`.@sD%{aywܶ$ړ9dcLO[DgvEL?|F%."s ̳恼ƔLeHboLuBy]{NP(AX i,Mk]l>ژRcJ6dq=DKZԩ DM hq{@[>8xw·i$[1-zm)>-p>\Ͳ çL+l&ڌ>Hd;[ʗ:I%?ȑ8#v;Y쎟 F!3;k!ozǩ=s]g"'Hq*%xn{5krm劋5.~yIDATr޽`F Jg|x<blh㳸\6氙l= 2GNt>)m#}~sI>WbO6)&J(6št2C82T6B SL%Hp"1WҺ>nņhdLCh[K*(F+\gm07!uنI}hk%Wʖ65qj0XZZXTi*&iu!15yظf}I_:n# оn;?q RP I=)<[;r.u{uTi~)׬ W]"AÕGOp1y<+`q|0NA32x{"hJB*}r9!(ƪ/'{]xyk+7XmB^o)kchQs&{Aެ}o47ڌ(֦fx.ق _ԡ ڔwՖ7}FYj5.+rw \&Ib'a7$OޠD+IoB$nӲHdq7$9y@3LdݘS|{Dz#}9HΜcΖ.YnͰa=QVj<U&tTW=v/\=zZ I'C/#[l.bl|{lǶ' xʚ'r<[_nkNcH @ <ϥZV] n"<;(`Od'!! cDtW h4zl1K>ٛ>k+1xgά15Z*Ԗ:EanEڮ@؊=06UghV\Wo*_SnID=z)wV0O!\&@=tm)WBI̞%p<:OYJYf]I =X>jWo?0よ!|?<.3Dq2b!|E S`LW\J ƈWmx6w ~hL}(A{NQI+S|97`j*dyVhUFl4zb[X0u[?(]]3n/dhk K2^n:{oLY'z~~nӑD=y}F!O%q,rܧ ikk2q[]]֐N>r_-{54mQz-ZwxKo9U(z(TlcP1C+Zci[mf>as{ ?lː@u6[pY 3W xXg 1#7_.-r7=.e8AD0e;2> C8͸tәl7{|aerl䱪Ǭ{>r>o/>Fw£)8b7Ds1+ŝb|}qG*;9, "{ ^d?umg^+\T^n%iCO"C|11Th.iBۡ\57h(MVŪ6 @`[[dv~3k!h Mm;QTԷV7TsK/)>>plⵗ+rܺ{^ هfpÞrgqOϾe՞ oZ2÷Čٕ0@c3ϾR›e V9akhݏF=ӝ_^&$hu757WcUg+wݫ[{YeOR/*+k'`K9 y,.fnƲ` сC @2XTV8XdUAWߧ,5/D⻳A#\<v+'[9nd7RmN@&b<;h"/Ѭ&}Xst$Lӝ\ShYZՙߨZVc{Y?546MVGkQֺ:sY̜m J2_%T\-ac&r$C]ӝs1 )/g@Nhb)K5ߝ񺐹Ak^Kܘ㥓UM:]ɆQߌ]QtdSE/f7-/&^-sr#ծphXíd\p[}Z!ƘUgBeQiMuhVͨoҿ7ߛ%^/ZV*jUKyS뛺jK>'TE a9{ɚO~X^ڛK.9ձIG'/e};s&Ys)d%,>[Rʫu?\obmjզ'MD7z\}8DD՗)4ͣLMd6&GnN34MR߂8Ѵ/zWDO}sLo$b\{9[&b,!fh/*9,ÆC{O3!+p(|BQoc0߉Ӈ\G0ԂǠcЍ91$,A6KÅ;N,;MGoРY3m7`,Q EݥD]`>8]8K}V wJcJ)јdRSerFcXVEniZ{--kU!A/E*-o[J,UlХo /QEy xiH>=ۃT?WxG:PVku?]d뵛o5l l~W{u{!BGОJԜIRK]H1\I30fgBLsy]l| NA&I1E.L~T !$0E>מpG.H0Z}pIx'G7E9Pъ+p?N?2CЬnV(j-,%oETMc4{6.P>I_?dgXJ !W$[Q NR~8ܸVӹs5uspIȏ$p`;Ar$T\,5eQ4bj/|/% 8dz`4zK,5d-s2Q<˙G[1n+!!N:_Y*F"! b ^k^i# uDjsԏ2!ɪʋQ#A][~b<:WaH tsSa/>Bʡ$3 ۇF_S'vZzLJg-ѻ>@py<}@H!qOQxl; [Dzdv⿸UQئڛ Xn5lVj4+ lyoYBRksj!"<R|_"'OiM<BhBWȑ&"=IL: !<&Ew#u}&F-kog ݬ]ذ:isbOГc '7ݰj=S:7z7'4], #~>BL1:E~$!c|D{$y"2WF5t8h;ğáS&])X>/pNJ}Ojn 9s\9ؔVbxm,3eWj,iͩ-I ִF&kBe@Zen2W4Z*oAךJLE S;cF!H5f3麨4md&"E*=|_rM݊gk9T8ߜp62 7`ٓb*W<_8dq "ݦ/@αGF2GNc^!)h 1setDFlWQ,`|e$lEGT.rX"P',.Dv8l~6w֜~<olziIdxe3>/6_bUUc,WS+@`ygM\ΔA!>XTahet"*G T9(Gw'WKD:(O _\~X+<*R_ik" B\_vD6.Ns5s4Yiʻ/7#ҭ[~A3d#X#?)e9c5D$lGQՄP$\ f3[ewU6](voŃw<r1)l':KEؑrĶE,k(U 4t wG߬%Bu"^w1K1..>/ &Jk C _K> 2D :P^O,<2Z5H}c7 ߯\: ,OCn`E:qbr:ρBwnNz>2{ Dʉu*I":aLqqM{:x~9o~ k<ze /7VqZ kgj#&x !B|䖚g4Suo>9"C  O,qE,C’e Pihzݷ|z.ʍ7Q\xt5Y Є9 l|SߌVxr/,<{6 HfHHߎv35Oeq\h$I|gqr+ְ){Zc3_\};vŊ@?~x;Bw.Aw-YҴrQyBm$"BK,|-$J/e̷,9Ԕ X G)1Ę Ȉ JDJw~6(08#2 2>9SBlXAdd! qKqsc1aM7|KBݪ5KVS8uW;^5|}WyR;qta7Fc926G]3Cs`KbI*|HBN@CC~b:SРe]=zb,6!ZX 1VǐNeCz~K[x_*q 9"Ó2j|---nn l!Z]Zi7Ye.GT￐zх!nouE2_t/.s <"oЛe Pdpvgw?q:kek7G4%C@df"rԏk"ATu0fí҅u,n`aAvzD-.@6Ť2z!C*0>,0 w wtaf Cd0>8R iF@LS`6Nn~.( Iko<_Il4~ʵWW]zтE2bڲ#뛣Svuo>NN!H+:cclfnI<<+Pq$BNy!.ǽLV'4 Y[tO.>oF dz\CBs:sl%ǟН~Cu+e?oo,ŽP;Fğa.)3λ\fڻ CU{kEhGOGi.=^yao 7R{i|/<tlEH/ϵײA Mie\U\e-JH-3a[< Yߛ-:s^%9,Ww-xAɖ~[`$яЉ#|Ȣ$Ci; 'ewo4lQ-Bq<^}9Y{=MM:DU}kHz֘%Wd}^h5gc7U5vx񯱟ǡwdTͥ%$>_4!Od/&HPdR%\ *alXL{:ێeGscJ6u <"R4E1\jU!}7=娃Ny+ o*U UĊߣ=&h.JJU߶"jM=婃+DA6$S M@"UʇZ-ĝ[ɺ곗dUdD턦 Mg_OCPS԰v+5K,9Z>o_S>;|>_ z/`N DH0G3|IX:yk|K+M {ƳIXN-;Sc_8193|+?mps!l1vXJkB%ւ-$ŕrKV5ԚPʄM!:ׄ I[kD\E2D"DWh~9LuӦ1Mg6i8p8jWHUnʛg˛z0gچV=F`뷐p- w=VU R=Fc)}N3kOYvy,Pщ&H y2OAOp/ a1/F<ȝpcѼH><^~'.tmfzQ^΍iAyzS:}bW,9\{B1XV6Yj&hkn3Z%p{\g'aҜQb7jZɺGw&"H)ru_DU>lu!Nf?_vF)ǪO&j/h59ʒ[k.l6 o,% :k~%Ґ@aR03E }>C' \GPcw&ؠyISfC=e<+SA"}Ji5y%v^⾈ ;5Ƒ^P0\-\&n" - `b;vPG,C19Ѥ$Bod"9;bjeXgMAkſӥUꌥ *Us'A~WGmkk31'<\\Ɋc?_psfys.?쳣sUpzヺ?ל:Cw dI6H]EWsNk͸~.SY W :Cj!8OKԇlz/0Chyq@SEq?x1ԞEhCY,8 GfsSڛ_sNK> Y|B fdT ȁ,r\hbwؓ'rOA<+nŜ!kypv{ٮK]2lQrG /qΕ/v?]-pbͪ-7߮zfK`꺾dzM$XPPTĮ(v_셦( Ut%!@hBzOmS}L$Xg=Q]g}k4sO-u[gntwˌ-sΦ6~~|_*__ڒ]}qUK<(Lwgu]yQ~0=WxJK"RrBMHIDa"YP"D$d 4 ԟo'<ʻ%C_yPIAwA $DD52@{W\aO$҄<ݏJ$s?G7C_ _z!ʗt'1 3n(~`Ü3iƽe UdV=U dktf#B,uv#iӚlMZk ۳msCL[MnWҫ˒}T~iNqID˚K4jgy y%dtoѩL6@{IRۛLt&`כ:-l`RC@JemiY+->┕ÇV u_1Epgx>wjsYz7;_wվRThx2_Y "VbhcAn)P$'!b ~Y>13"y7=ÐWVs=z~oόޅ-I,s'V=&UWZIk pυ}ڂg?&oI+)O-M$en<1##?>8w6U9yEQAc`S~;Hk3 .JW!8yt40ϩV5R%*񹂰7t"n7}KǼx_ ZXϗ 'S4uMŵ>]|ް6kP%LvZgkĎFed6ϐІI_[s4WT4.;ֺh5-o1mqY6]$#y"*埕t2xⲹխRଇeSN=(fl_VԱlNs4r%zm~ѡvXz73lnyTu/?u/挵ZS~*p %쾈| E^"( b+"7c vt!|Y8J|eY4!gxd`%cyXIM fԨ\:+óEOWLZҐ~ yEԟ{ϛc?Mm/a[N]s˔7K<]">QP|;NRjޏ "C ih:z~0`-눬,×GQm_" &-ze DÊ_}: Mm*eq0ڰ$LHꘂ6š\j?o?mݛFoOvNa'*S=)d|OcfЇW"&N3T%mrH,Īf`ЮCNk :<{ˤwkt5Sʴ8żcxCy꾄`_XJl@ |d~a[`Ѕ]Ɏ4<=)bHEhh _50B>,BIJh_I \>.m:򛁟Aa9b5*cP@}OO覉&*HcG?(+_:8 :* 8) } ɔ𤑾R|QDda` ``sWw'$IQ^(ႁ+Յxx?Az(&6SjD!Zo^i/_~4i}b^̻;~uj'~|dȌCfƏ[ܦnӦ.7fP{ tRff ]KLvwvʩ*xa9Eg'IŶKWi*&.:!`oۓnH/9sĊ*MokpۂY̡Bt)u1ՠnEmmX|OG3Di69fW+ uZ,#/K^b1uz8RkJ"*vͩӲj3]Ct,tpJ>\es9NDf'cz֠eZZL/1,aYwX'm׺/6Ց.psj (…G"&5)xr!_ʿno5O.Tpгl0Ļ n\5"A`P7H}S'ASOF^Np"(E7PF(1B >4~P橻a~WʃPY˓p> RHe -V*d'½G-nK̙bs .{2Z(TJebT#nbgxsN׈bkhBoTej)"0Jwe 1Z~0-s`(\ Q #M:sbꆉ,:]Js]Å3Tj=j".:I[p__ PHBCDVJ:QbY2ٕdV5u0BгTٮTW*ut0ٓfz\sTpvwIw 2X '[T2!T2=?`Dž^с<j yHm,P>VbR% $~Xׇ SH C};P&/ 6 kjዠPYT΃w9O;(.nj+4VU+A$d\KejQAzAC6 }'yO:aVˋoyaxX|E£QHnK1E]1uښڪ93ajy`r`he\f0t(u֚6)oaKQ2UhRlfTȦ9F>WO|=WHE:L6zSxXGe Ý7Ծ8w}NSh(E *xIaPB ?'$:{bP,W3㇎'t?C,xcGv'*pYwt2vkh`"yF|;|;,#`)~ GX ġ_ aWO~2lȘ{dp=?_RB"V-T+5(r /~ܼ57ޯy"lJjly lY [u,<(6%a;&rd &k+"3ZUk-UsUlqQvkVh,@ÇwEyABv-?MK-f PKW6(WL&2+%Z}QHDJ>AQ =',"q|p#p18T]6U;OB SRU'Hhw{ew}zA>o/%<ZRe*% B_ iF}Ꮮ9ym-׷=nl|KCTqJ ,:PJJ)o%& '64M ӏ Ug Q$"*l:?v4tЊyhulXD[Izh\mKǸfGZ_Y \M"ȢTֆ~b`P*&ԚoMf_f[7!kIZ=dоc}†T}|zK{IQyR;TyAΚ@C~Ƨq QNͫ{vZ&CGy5FL]>o~KvBt(; !+Bv 6x'*P TGI"%(UI |A! /L^_Y[bE2#9O.%SjقFkEi)m7!Qx:nڸ vQ ժ9I<\x3AMkuqƲe؜h'C g3immÊ:k~ZF_Υ.Iɖ ƥ-ldc?%Qc }L2D}W$t!*ҡ8<4TǛn`?< O$/vIxNs)}8lWݛoA$uJ q/߽|pF Q)zd!in}<>3%_ZrO#(W: xt#xC<rT ұ_vG,I~nK{qms'7Q{ -+z Ra!D`(;ۭ9i:k-sNznD݀!;[ `E׌V L(4[5-F6Ψ l%Ӗ Ԛ|vʜW>;&l0_h >l*ħɐq~bɟBWq᠏{{_$}""hEU!( q!|T`ԋqW Y]ކ/O]l H+:S{3ٮGoBB%=8 (=uһsQ[9?"GGHFB.ibYErIւ'k)9McJ9MJ^@ۯtk{?¤Ydxaε76 ôFsIJ?9>a6) y!v"CJS0\>#Py˒D"Bxᾱoн"x)|"&-Է>;~<6>ܹ+N\#d| 4)xOXtPDEO@08Z[*xwܿO|qf?֧|޾^eF$VQ $Tp* !Ѿ4O<:_9C >)]c2*ɅQtit5Y\:i/3vG܏m8 dJ5a^ pn((yx5츻Se_+jR$$bLJ@<@-U˗Cz.&HiH_b!>[^>83j1?徼]-onk|ysEc]_zDtЪceH:B Bxԗ6:ՕCe- O1[/Zd[J5z*k& aQ-בC/uG 3U앫Lf1s9>a9xBnH|ָ,^`O۪[G_Y1T' -xd!&L4~b5dY?4'{m0^QV$_ >6T~]Zܛ7D!ܾp iAO'PϹ'ȂŊpD-@"n$]ŔUCg7T}Cƙͳi?6geahh*?^|UT!) "VG?J)[q,!GI z}m_=IJ?Y{-9n)Nc~Ѿ9۪g+8i~v>AS P5(@-x7(^`?xZ CQ+2_]7qzZ2̇ΕaR@:dži Spn8MjoV5گV+،bbϜȢ{Ҝ q-]撩˒}|+c2AhB<+S51ҀH2D |yl~ҰlݥRSV @1h:6'Ij3GC"wniuPuڛ`΅J[z{:CL_b&QLu ~adMw>^zL&Lz(8G $j J.-}l \(Z:9;m_HK lui*8O+1i?<"=23\Ri\a(0!䃈0|҇熽eSWflކ/4>M-;aXzʸyKg,0(byGn.}`g,ϛ g UTJDr()E>`WP mOȰ]wiI݂ _:mM hK;Y:Z0L%  ~X<mLMӸOn_XQik(ov$x]wA @E9DCOo -oWH e7A`t/1yb0~E \}wOGu L+?_']0JfqC`HdޓluڴnQw{^g?=x߆~'8"XG)T("}x 0%(M \4ZNkȔ:)CI)*,6=I؉B۰84M5MJ8eM̚UdKϥΧO0ݺQ%?;e؏n㥾Q@Brh4E | LQ%BY .˚< ɹzwxZS9Rѻ]RD"%žJ'b 0fNq! HO'K&d!rO1O><3x꺛`Yړ늟ZGN$Q.ہ{L2>r*$'SE,lbcyej%ێr/~_]uaca^9''+UDKc;AOo:;qO~H0nL+"O/V[Q!W)k5 +;qpo؀?emPH9(qG^fna*ּJkv9YJY.癓r cM5w(YsK}kԬ.M}nc[;f/m 3DnJvdPrc`/G ȌZ2i4M,f2ޒ^mNj\D^ȡR $놓҃9[kf{Yo4ṷDDG5EC%}w)ysԞ\s<} 8-A lR{vA"h픣vc8ZhWem֒f5tN%vi悭Lr738iyѡi{tꏗ'7?[M?2a^݄hh 9&y$OTՑbE((;B &PȕjJRK%E 75!Vrāeݽ:TotïVנ¡􇀂?̂4MX#GQFTxh_e/ {h k"&nyIvGߜxhyMo`W O藟2M4oJl8nO:g+ uLr#DgyZHGJUm *dY YP:,)e?jG[ǴsdXIdj{VנX37i HUrCW;jg " 64=AUeUlW1ټ:6@T,!/6x*Cb؝d^vw470n恆v^`s;/ɽVbzPBFD:1pԔ?=i7/aʌW~)zN?٧tK֜5l9o{r4BBSF%*2t_5Skֳ&T3l$fuTE]fXʙBb}>JH2:mr²q7V> a}r7dCArRխcX@f+LEdI]0:kZdXl夵6XmšV0Xk6kaJ-]AgX 2)w޼%Ѽn־Ə‹3~؉>; -b(!;_iĖQUy]rREd7lXa&i$6Fv %S-zP.DVB)~$*&+J"r>Kȴĥ_2n8o\uVdc3fֲC3_{ݣ_\=o{Q)☉٠AobBd(\"@/P-;%X)@B)Q*(i:~4mqg@-^ JUU/uA eů!Ob5DXh+͍xuՠiFΌpŧM\O4~}uI݂Ɵ.N%7gѻsCy4dr^A]!K&jclZk!QFP?(rť79P2_ZނKUsr&%ϒaٟBn`Y{ּp}՟]6ַd( 7AoĄ|wg˧l:U.UtjJيB_od3 ]7re;YINvҔDi2:mf[5xۊPHgWY+ٌR[K,/΢$ˢZCkiMayni|q5~vIˊ\>6/|䇲;M>BDOGy3O,]P7u5# .=2_*8זv>oyX;~9K̆dz[*+r |$x"ϘPd>LuIe&k>JUq7Z̬+Iq&|,:K{dDwgɡ5Y[Lh!PvZ\*'OXNw^0@W#*9DzCPwC6N"}Q|u:G:,^j^a("f,Ewq"^:C'>4Wn*yo{Ŵ5mna÷ NS?amIMfqT|!}IA\9YEeױWkX(7;j,&Ҧglf v3nmdҮhE5FΌhlof3j 2rbhy[eIq;>YQڬS?6O*Dj¤׷5x]6}i:uu;=$3 455׎?A!&Հdk0j SfHRtn%qN2<*!e_4KsէNpo6Un(|su+Ҟ.鉙'8nknzvṂc|z?OO$BSKhB>AHn#DC,RuQA yH(41W} {P"`! 4cD#DM/Ng|LE!/~&S󫳦lkk{*?;X;X-'V*a{ز+ܛIgҊB\NZX71e-ly+[y0PZl(D`@Glc{@<؎9i.逛cum5:ka#TSW-i(fSR=I-kf_ʹuo=ć{Ƽj+L;vy}m_%WW-)5tN=[b b+qIwi?῎XCڰpAa83c3 z[Vfma*ib=_K_AkU*Jh>_`N7$N^N@y0Ͳ'ٸq9ú3ƕ'tK~{nq SV=le}%vt;{x}۰ |f73fGMW' =% ~|BHm:mYm 3US+r^EY-Kdb%,j m@"7zN8*bɜvh3: &im5UQ:k~ [dV2r yU*1:KƣETj,kY~:C.=KH->i0~Ϸ7~n7^15ySV漼<ŗ&O0;~|gć|{764eCDO)CXxx^CW3covWeS6셵eϯ*SKL!{eL>iK ɏr&e 1anfOԂ+O,.~g?U/{uC5h`qMnwu Dug7]0md~ɸ5Ų/ڃFT'RGhm&S)Π ޚ`-h6KZmJD?j29@YХC9H"n!-NBT"!٠i'q'*,rT48s>HXS-?G7,4RA{fn3k; 749;["jfWMv^ݼ}M O0N&&睵,Ld^fD dzS9Tb.}:r,eN9SH+e.1)WLf%[2E֒Z/j4bqЛ nqEBW{Ǿ7^԰;ԡ7ZlZTʼ*:|ǘӅl|d8NJȓ r51,lh-6ڙ}r|T4a>},ѣZZ 9Li]TWrY+^Τ2K yI9٦lLcRLdH fd/ k/W5L4di)(~"0S׭8_sJi螨__q?mXbFΚ7_lDo¬Je֦2_2m̮,jw`>y|&Ϝ`<"r RjM-eL6R:Tz(u@F+ԁ=➫[Vr&9φ9k3H{ FءXLl3*Mln1 Q ΖWSȌsv)WoV ˂zgwHnwW9Br4 1LU+@6SLW51@Hń* : 6* JbKz%\@^@z)!x2p<|<dZ(>TjfXw z}7r:6.kb8Yyڰp;̀@ڴ(BZLimhc[ΑDhvd42muV@ PŢ. Lu\C]&]uL8q @PI'Vxp ]`kior6SF|omSQKvsϝC{W57~:7J'`gğb1oI m1㼶$ڙ"ac;q``Сo1`=vDQ'!Ը{QFBi$K&yݯBph]nYjס͡:^w|؍#6q:9_MM>OTLB7t:NJyYgT$ѱou=t;!p3`u۰"y@'r ->L5'Sln;m#p"N~({xYw]_~{Z卒ΑΫag\vXp\~UK yNkkvw_nG4D3 (p=ψ.}ۜRw image/svg+xml Q + Qt extension library Q + libqxt-0.6.2/extras/artwork/logo.xcf000066400000000000000000027644151215241066400175070ustar00rootroot00000000000000gimp xcf file){BB.$gimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) i){fade     .D){hiiii){L$=DZdo%9Yy-Nnk;͛U.5B|bZt[ AFUu* 5bU\j/ku2C8BV2"                            ! ! !! !!  !  ! !  !  !  ! !  ! ! ! ! ! !! !! !! ! ! ! ! ! !! !"!!"!!"!""!!"!!"!!"!"!!"!!"!"!!"!!"!""!" "!"!!""!""!!"!""!""!#"#"#"##""#"##"##"#"##""#"#""#""#"#""#"#""#""#"##"#"#"##""#""#"##"#"##$$#$#$#$$##$##$$#$#$#$# #$##$# #"$#$#$$#$$#$$#$$#$#$%$%%$%$$%$$%$$%$%$$%%$%$%%$%$$%$ $%$$%$%%$%%$%%$%$%%$%$%$%$$%%$%$%%$%&&%%&%%&%&%%&&%%&%%&%%&%%&%%&&%&%%&& %&'&&%& &%&&%&&%&&%&&%&&%&%&%%&%''&&''&'&&'&'&'&&'&''& &'&'&&'&'&''&'&''&''&'&''&''&' '&''&''(''('(''(''(''(' '(''('(''(' ')(()(('('('(('('(('(''('('()(()())(()(())()(()(()(())(()()(()()())())()())())()())()*))*)*)*)*))*)*))*))*)*)*))*))* ) *)*)* *)**))**)**+*+*++*+*++**+**++*+**+**+*+**+**+*+**+*+*++*+*++*+*++*++*+**+**++*+*+,,+,,+,,++,+,,++,++,+,++,++,++,,+ +,+,+,,+ ,+,,+,+,+,,+,+,,-,,-,-,-,,-,-,-,,-,--,-,,-,-,,-, ,.--,-,- -,--,--,--,-,--,-,-,,-..-.-.--.--.--..--.-..-.--.--.--.--./..-. .-..-..-..-..-.--./..//.//.//.//.././/./././.././././../..0//.//./..//./././../.././/0/0/0//0/00/0//0/0//0//0/0// 0/00/0 0/00/0/00/00/00/00/0/0/0/0/110110100101011001011001010 010010110110110110100110110012112122122121221121122121121121211211212212 21221212 23232232232322323223322322322323323323232323 3233232233434434344344343343433433434343343433 434434434 4344344344343445455445545545455445455445454544544 54554545545454455445565655655655655655665655656655655655655655655 656 656656656566566565657767667767767667766766776677676676 67677677676776767767766776778778787887787887787878878788778787787877878878878788787887889889899898898989899898989889898898 8989989989898998989989                                               ! !! !! !  ! ! !!  ! !! !  ! ! !! ! !! ! !! !!  ! ! !!"!""!"!"!!"!"!!""!!"!"!""!!"!!"!!"!!""! !"!" "!""!"!" "!""!!"!""##""##"#"##"#""##""#"#"##"#""#"#""#""#"##"##"#"##"#"##"##"#"#$#$#$$#$#$#$$#$$#$##$$#$##$##$# #$#$$#$$#$##$#$%$%$%$%$$%%$%%$$%$$%$$%$%$$%$$%$ $&%%$% %$% %$%$$%%$%%$%&%&%&&%&%&&%&%%&%&&%&%&&%%&%&%%&%&%%&%%&&'&&%&%&%%&&%&&%&&%&%&&%&&%&&%&%&%%&&'&&'&''&'&&'&&'&''&&'&&''&&'&'&&'&''&''&''&&'&'&''&'&&'&'('('(('('('((''('('((''(''(' '('(' '('(('(('(('('(('(('(''(''))(()())()(())()(()()(()()()()( ()())())())())())(())(())(())()((*)**)**)**)*)*)*))*)*))**)**))*)**)*))**+**)**)**)**)*)*)*)**+*+*+*+*++*+*+*+*+**+*++*+**+**+**+*+**+**+*+*++*++*++*++*+**+*++*++*++*+*++,+,,+,+,,+,+,++,+,+,++,+,++,+,+ ,+,+,,+,,+,+,++,+,,+,--,,-,--,,--,,-,-,,-, ,-,,-,,-, ,-,,-,--,--,-,--,-,--,-,--,--,-..-.--.-..-..-.-..-.--.-.--.-..--.--.-..-..-.-..-..-..-..--.--../././././/././..//./. ./../..//.././../0/ /.//.//./ /.//.//././/../..0/00/0/00/0/00/00//0/0/0//0/0//0//0100/0/00/00/00/0//0/00/00/00//1010011010010101001001010110 010100 1011011011011011010110101011011021221212212212112112112112121121212211211232212 212212122121212122122322332232232323232232332332332332332323233233434344343434344344343434334433443343343433433433 434434434344343443443344344545454454454544545445445454544545454454544544565 545 54 545545544544545565565566556556656565565655656656 5656566566565665656656565665665655767667676767667676 6 7677676676776767667676776787877877878788787878778787787787787787 7898 87887887887887887877887887798989889989989898988989889898898 898998989 98998899898                                  ! !  ! ! ! ! ! ! !  ! !  ! !! !! !! !! !! ! ! !  ! ""!"!!""!""!""!"!!"!"!!"!"!"!!"!!#"#""!"!""!""!"!!"!"!!""!!"!"!"!!"!"##"#"##"#"#""##""#"#""#"#""#""#""#"##" #"##"##"##"##"##"#$#$#$#$#$##$##$$#$#$$##$##$##$#$##$##$##%$%$$#$$##$$#$$#$$#$#$$#$$%$%%$$%$$%$$%$%$%$%%$%$%$%$$%$%$%$$%$$%&% %$%%$%%$%$% %$%%$%%$%%$%%$%$$&%&%&%%&%&%%&%%&%&&%&&%%&%%&%%&%%&%&&%&&%&&%& &%&%%&%&&'&'&&'&''&&'&&'&&'&'&&'&&'&'&&'&&'&&'&''&'&''&'&''&'&''&'(''(('(('(''('('('(''('(''(' '('(('(('('( ('('('('(('('())()()(()()(())())())(()()()(()()()(()())())()()())())())())()())()()*))**))**)*))*)*)*)**)*))* )*))*)* *)**)*)**)*)*))**)**+*+**++*+**+**+**+**+**+*+**+**+*++*++*+*++*++*++**+*+,,+,,++,+,,++,+,,+,+,+,++,++,++,+,+ +,--, ,+,+,,+,,+,+,,+,,+,+,+,,-,-,-,--,-,,-,-,,-,,-,,-,,-,,-,,-,,-,-,-,--,--,--,-,--,-..-..-.--.--.--.-..-..-.-.--.--.--.-.-.-/..-..-.-..-..-.--..-..-/./././/./.././/./../. ./../.././.0//.//..//.//.//.//.//.//.//.//0/0//0//00/0/0/00/0/0//0//00//0//0//0//0/0//010 0/0 0/00/00/0//00/00/0/0/010010010110110100101010101010010010100101101101011011011011011011001121221221212211212212121121121211211211 21221212122122122123232323323223323232232232232232323223223233232332332332322344343433443443343 343343343344343 34344344344344343344344345445455445445445454544544545544545445445445455455455454455455445454545545455466566565565665 565665565565565 5656656 65665665665667667676766776676766766766767667667677667767767677667677676677877877887787878787877878778787787877877 87887887887787887887887899898898898988988988988989989899899899898                                ! !  ! ! ! ! !! !! ! !! ! !!  !  !  !  ! !! !! !! ! !! !! !! !! ! !! ! !! !"!"!""!"!""!"!!""!"!!"!!"!"!"!!"!!"!""!!"!!"!""!"!!""!""!!""!"!""!#""##""##"##"#"#""#"#"#"#""#""#""#"##"#"##"##"#""##"##"#"#""$$#$#$##$#$#$##$#$##$$##$##$$##$##$##$##$##$#$#$$#$#$ $#$#$$#$#$%$%$%$%$$%$%$$%$$%$%$$%$$%$%$%%$%%$% %$%$%$%%$%$&&%&&%%&&%&%&%%&%%&%%&%%&%%&%%&%&%&% %&%%&%&&%&&%&%&&%&&%&&%%&%%&'&&'&''&'&'&'&''&&'&'&'&'&&'&&'(' '&'&''&''&' '&''&'&''&''&&'&&'('(''(('('(''(''(''(''('('(''('')(('(('(('(('(('(('('(('(''('((''())()())()(())(()()(()(()()(()(()()()())()(())())()())()())()*))*))*)*))*)*)*)*))*)*))*)*))*))*))*+**+**)*)**)**)* *)**)**)*)**+*++*++*++**+*+*+*+**+*+*++**++** +*++*+**++*+*+*++**+*+,,+,+,++,++,,+,++,+,++,+,+,++,++ ,+,,+,,+,,+,,+ ,+,++,+,-,,-,,-,-,,-,--,-,,-,,-,,--,,-,-,-,,-,-,,-,-,--,-,--,--,--,--,--,-,-,,--,--,--.--.--.-.-.-..--.- -.--.- -.-..-. .-..-..-.-..-..-..--./../../.././/..//./././/.././/.././.././ /.//.//.//.././/./0/00/0//0/0//0/0//00//0//0/0//00//0/ 0/00/00/00/00/00/00/00/00/010101101010010010010100100101010010110101101101010110100221221221122112112121121121211212 21221221212212232332323322323233232 23232 232234332332332323233232232322322332334434343343433434343343343344343443443434433434334344344545 54544554544544544544545445454454545545545455455445445545455455655656556655656566565566556565 565 5 65665665655665656767667676767676676767676676676676676776776776776776677667676778787887878787787887787787878877877898 878878878787787878878998988989889898898899898899898988988                                     ! !!  ! !  ! ! ! ! !! ! ! ! !! !! ! !! ! !! !! !!""!""!"!"!!"!"!"!!"!""!!"!"!!#" "!" "!""!""!!"!""!"!"!!""##"#""#""#"#""##"#"#""#"#"#"#"#""#""#"##"##""##"##"##"#""##""#$#$$#$##$##$$#$$#$#$##$#$$##$#$##$#$#$$#$##$#$##$##$$#$$#$%%$$%$$%$%$%$$%$$%$%$$%$%%$%%$ $%$%$$% %$%%$%%$%%$%%$%%$%%$%&%&&%&&%&&%&&%%&&%&%%&%%&%%&%%&%&%%&%&&% %'&&%&&%&&%&%&%&%%&'&''&''&''&&'&&''&'&&'&'&'&'&&'&''&''&''&''&'&(('('('('((''(''(''('('(''(''('('' ('('(('(('(('('(('('('((')()())(()()()(()())())(()(()(()(()())())()())())())())()()(())())()(()*)**)**))*))*))*))**)*)*)*))*))*)*))*)*)**)**))**)**)*)*)*)*)**++*+*++*+**+*+*++**+*+**+**+**+*++*++*+*++*+*+*+**+*++*++,,+,+,++,+,,+,++,++,++,++,+,+, ,+,+,+,+,,+,,+,+,,+,--,-,--,,-,-,,-,,--,-,-,,-,-,,-,,-,,-,,#-,--,-,--,-,-,,-,--..--.--.-..-.--.--..-.-.--.-.--.-.-..--.--.--).-..-.-.-..--..--./../../../.././.././/././.././/./../../../././/.//.//././/././0/0/0/0//00//00/0//0/0/00/00/0//0/00//0//10 0/00/0/00/00/00/0/0/00/00/10100101001010110110101011001001010010010101101100101101010011011221122112112121212121221221 12112112112122121221221212212122122121223223223322332332322323323232322322322 323 323 323 3232332334334433434433434433434343343443343 34344344344343443434343433454545545454454545445454454454 454554554545545455454544565656566556556556565 5655655656656656656556556566567677677676766766767667667676 676676676676776776776767677677687887887877878787878778778788787787 7898878 878878788788787878878898989989898 8988988988988                         !              ! !! !! !  !  ! ! ! ! !  ! ! !! !  ! !  !"!! !! ! !! !! !! ! !! ! ! !"!!"!!"!!"!!"!!"!!"!!""!!"!"! !"!!"!!"!""!""!""!"!!""!"!"!!"!!"!#"##""#""#"#""#"#"#""#""#""#"#""#"#"#!#"#"##"##""#""#"##"#""#$#$$#$##$$##$$#$#$##$##$##$#$##$##$##$%$$#$#$$#$$#$##$#$$#$$%$%$%$%$%%$$%$%%$$%%$%$$%$$%$%$$%$%$$%$$%$$%%$%%$% %$%%$%$%$$%$%&%&&%&&%&%&%%&%&%%&%%& %&%%&%&&%&%&&%&&%%&%&&%&''&'&''&'&&'&&''&'&'&'&&'&'&&'&''&'&' '&''&''&''&'&('(('(''(''('(''(''(''('(''(''(''('(('(('('(''('(('((''(('(''()(())())()()()()(()()( ()(()( ()(()())())())())())()(())()())())((*)*))**)**)**)**)*))*)*))*)*))*) *)**)**)**))**)**)*)**)**)*)*)**)*)*++*+**++*+*++**+*+*+**+*+**+*+**+**+*+*++*++*++*+*++*+**+*,+,+,,+,,+,++,+,+,,++,++,+,++,+,++,-,,+,+,,+,,+,+,+,++,,+,++,-,-,--,,-,,-,--,-,-,,-,,--,,-,,-,,-, ,-,--,--,- -,--,-,--.--.-..-..-..-.-.--.--.-.-.-.--.--.-..-.-..-..-..-..--.-.././/./..//.//.//.//./../ ./././/. ./..//0//./ /.//./././00/0/0/0//0/0//0/0/0//0//0/00/0/00/00/0//0/0//0/00100101101010 0101011010010 01211011010110110110011011001100212211212121122112122121 12112122121221221121221232322323232332323322322323322322323323323233232323233233233443344344343434334334343343343343 3434434434 434343433443344343354545455445454554455455445544544545454454565565)5455454454656566556565565656566566565565565565565655%656565656656556 676776776767667766767677676767667676 67677677676776767767667878 878778878787887787787787 78778988788787878878787877887878998989898898989889898988988988                               ! !! !  ! ! !  !  ! ! !  ! ! !  ! ! !! ! ! !! !! ! ! !!"!""!"!""!"!!""!!"!""!"!!"! !"!!"!" "!""!""!"!""!"#"##"##"#""#""#"##"#""#""#""##"#""#""#"#"##"##"##"##"##"#"##"#"#""#"$$#$#$#$##$$#$##$$#$#$#$##$##$##$#$##$##$#$##$$%$ $#$ $#$$#$##$$#$$#$$#$$#$%$%%$$%%$%$%$%$%%$%%$%$$%$%$$%$$%$$%$$%$$%$$%$$ %$% %$%$%$%%$%$%$%$$%%&%&&%&%&%&&%%&%%&%&%%&%&%%&%&&%&&%&&%&&%%&%&&%&%&&%&'&''&'&'&'&&'&'&&'&'&&'&''& &'&''&'&' '&'&''&'('(''('('('((''('('(''((' '(''('(('(''('('((''(('('(('(()(()(()()(())())()())(()(()(()(()())()())()(())())())())()*))**)*)*)**)*))*))*))*))*)*))*))*)**)**)**)*)**)**)++*++*+**+**+**+*+*++*+*+**+*++**+*+ +*++*++*++*++*+**+ +*+*++,+,++,+,,+,,+,+,++,++,++,++,+,++ ,+,,+,,+, ,+,,+,,+,,+,,+,,+,+,,+,-,--,--,-,,-, ,-,-,,-,-,,-,--,-,--,,--,--,-,-.-..-.-..-.-..--.-.--..-.--..--.--.--.--.--./..-..-.-.-.-..-.-.-..-.././/.//../.././../. ./././../0/ /.//./././/.//.//.//././/0/0/0/0//0/0//0//0/0//0//0/0//0//0/ 0/0//0/00//0//0/010101101001011010101100101100100101001001010 0 101101101101101101101101010101010100101221221211211221121212112112112121212122122122121221211212323322332232323232233 2322322322 3232323233233243343434334334334344334343344343 343343443 434434344343454554544545445454554455445455454454 4545 545 545545545454665655656556565655656565565565565566566566566566566566565665656556655667667766766766766766766767667667766766 7676776767767667676766768778787788787787878878787 787887 7 878878 8787787887878787                         ! !               !  ! ! !  ! ! ! ! ! ! !  !  !"! ! !! !! !  ! !! !"!!"!"!!"!!"!"!!"!""!""!"!!"!!"!!"!!"!!"!"!"!"!!""!"!"!""!""!""!""#""#"#"##"#""#""#"#"#"#""#""#"#""#""#"##"##"##"#"##"##"#""##"##"#"##$##$$#$$#$$#$#$##$#$##$##$##$##$#$##$#$$#$$#$$#$$#$$#$#$$#$##$$#$$%%$%$%%$$%%$%%$%$$%$%$$%$%$$%$$%$%%%$%%$%%$%$%$$%$%%$%%&%&%%&%&%%&%%&&%%& %&%&%%&'&&%&&%&%&&%&%%&%%&&%&'&'&'&'&''&'&&'&&'&&'&&'&&'&&'&'&&('&''&''&''&''&''&&'&''&''('('(''('(''(''((''('('('('(('(''(''(''('( ('(('(('(('('('(('('()(()(()()(()(()()(()( ()( ()())())())())()(()(()(*)**))*))*))*)*))*))*) )*)*) )*))*+* *)**)**)**)**)**))**)*)*)*)*+*++**+*+**++**+**+*+*++**+**+**+**+**+*++*++*++*++*++*+*+*+*++*+*++*++*++,+,+,,+,++,++,++,++,+,+ +,++,+,-,,+,+,,+,,+,,+,,++,,+,-,-,-,,--,--,,-,-,,-,,-,-,,-,-,,-,,-,,-.- -,--,-,-,--,-,--,--,--,--,-,--.-.--.-.--.-..--.-.-.--.--..-..-.--.-.--.-.-..-..-..-..-.--.-..-/././../..//./../..//../.././././/.//././/..//.././/./0/0/0//00/00/00//0//0/00 /0//0/0/0/0110 0/00/0/00/00/00//00/00//00/0/0//00101010010101011001010 010010010011001011010110110110110100100112212122121212121121121121121 1212 2122121121221221221221212212121121223232332332323232232322323322322323233232323323233232323322434434334334343343343343343433433434434434344344343433435445455445445545454545455455454454545545545454554554554545656565565665655655655655656 5655656656565656556566566556566767767676766767667676 6766 7677676767767887787 7878778787787787787787 789887878877878788787887887                                    ! !! !! ! ! !! ! ! !! !  !"! !! ! ! ! !! ! !! !  "!"!!"!"!!"!!"!!"!"!"! !"!"!!"!""!""!""!""!""!""!"!!#"#"#""#""#"##""#"#""##" "#""#"#"##"#"#"#"#"##$#$$#$##$#$##$##$##$#$##$#$##$#$#$#$ $#$#$#$#$#$$#$$%$%$%%$%%$%$$%$%%$%$$%%$%$ $%$$%$$%%$%$%$%%$%%$%%$%%$%$%%$%$%&%%&&%&&%&%%&%%&%%&%&%%&%&%%&%%&%%&%% &%&&%&&%&&%&&%&%&&%&%&%&%%''&'&'&&'&'&&'&&'&''&&'&&'&&'&'&&'&'&''&''&''&''&''&'&''&''(' '('('('(''(''(''('(''(' '('(('(('(('(''((''('(('('))(())())(()()()()()(()(()(()(*))()() )())()())(())(**)*)*))**)*))*)*))*))*))*))*)*))*) )*)*)**)**)* *)**)*)**+*+**++**+*++*+**+**+*++*++**+**+**+*+**+*+*++*+*+*+*+*++*+*+*++*+**,,+,,+,+,+,,++,+,++,+,++,++,+,++,++,++,++, ,+,,+,,+,,+,,+,+,,+,,-,--,-,-,,--,,-,-,,-,--,-,-,,-,,-,--,,-,,-,,-,--,-,- -,-,--,,-,--.-..-.-.-.--.--.-.--.-.-.--.-.--.--. .-..-. .-.--..-.-..-..-..--.././/././/.//.//./../../. ././../0//.//.//.//././/.//.//0/0/0/0//0/0/0/00//0//0/0/ /0/00/00/00//00/0//0/00/00101101100100110101001001010110010 01011011011010101010110221212112112121221212112112112211211212212212212212122121232332322332323323223223223233223232232232332332332332332322323323344334334343343443443343343443343343443433443433443454454554544554545545545545445445445445445445445545545 545454545545454454556556656565656556655655655655655656656566565665656656566576767767667767667676776676767667667767766767767767767767676766767766787877887878778778788778778778877877877878877878878788788788                     !                 ! !! ! ! !! !  ! ! ! !  !  ! "!! ! ! !! ! !! ! !! !! ! ! ! !!"!!"!"!"!"!"!""!!"!!"!!"!!"!!"! !"#""!""!""!""!"!""!""!""!!"#"#""#"#"#""#"#""#""#""#"#""#""#$# #"#"##"##"##"##""#"##"##"#""#"##"##"#$#$##$##$$#$#$$##$$#$#$##$##$##$%$ $#$$#$#$$#$$#$$#$$#$##$$#$$#$#$$#%%$%$%%$%%$%$%$$%$%$$%$$%$$%$ $%$%$%%$%%$%%$%$%%$&%&%%&%&%&&%%&%&%&%%&%&%% &%&%&%&&%&%&&%&%&&%&'&&'&''&'&''&'&'&'&'& &'&&'&&'&&'(''&''&'&''&''&'&''&'&''&'(('('((''(''('(''(''(''('('('(''('(''(''(''('(('( ('(('(''('('(('('(('(('())())()())()())()(())(()(()(()(()())() )()())(()())()(())*)**)**)**)*))*))*))*))*))*)**)**)*)**)**)**)*))*)*)*))*))+**+*+**++*+*+**+**+**+*+**+*+* *+**+*++*++*+**++*+**++*+*+*+*+**++,++,++,+,,++,+,+,+,++,++,-,,+,+,,+,,+ ,+,+,--,,-,,--,,--,,--,-,--,-,,--,,-,,-,--,-,, -,--,-,- -,--,-,--,--,--,,.--..-.-..-.-..-..-.--.-.-.--.--.--.-. .-..-..-..-.-.-..--.-/../..//.././/../..//../..// ./../.. /./ /././/././././.././../.././/.00/0/00/0/00/00/00/0//0/0//0 /0/0 0/0/0 0/0/0/00101101001001011 010010110100110110101101101001001102212212122112112122121 121211212112112322122121221221122121223223232233232322323223 23232 23233232332323323233223343343443434344344343343433443434334343343343343434434434434343443433445545545445455454544545445445445454 4655454545545455455455445454554566565665655656556565565565565565 56566566566566566566566567767767767667767767667677676766767676766766767767767767767767767676678787877878877878877878778778787 7877                                          !  ! ! !! !! ! !  !  !  ! !  ! ! "!! !! !! !! !! ! !! !!"!!""!!"!"!!""!!"!""!!"!"!!"!!"! !"!!"!""!""!""!!""!""!"!""!"#"#""#""##"#"##""#""#""#""#"#""#"##"##"# #"#"##""##"##"##$$#$##$$#$#$$#$#$##$$#$##$##$#$##$## $#$ $#$$#$$#$$##$##$#$#$$##%$$%$$%$%$%%$%$%$%$$%$$%%$%$ $%$$%&%%$%%$%%$%%$%$%$$%&%&%&%%&%%&%%&%%&%%&%&%&%%&%%&%%&%&&%&&%&&%&&%&&%&%&%&%&&%&&%&%&''&&''&&'&''&'&'&&''&'&&'&&'&'&'&'&''&''&&''&'&'&'&''&'&''&'&&'('(''('(''(''(('(''('('(('(''(''(''()(('(('(('(''(('(('('()(()( ()())())())()(()( ()()(())())())())()()(())(()(()())())**))*))*)*))*)**))**))*))**))*)*)*)*))*)*))*) ) *)**)**)**)*)**)**)**))*)*))*))*))+*++*+*++*++**+*+*+**+**+**+*++**+*++*++*+*++*+*++*++,,+,+,,++,++,++,,++,++,++,++,+,+,++,++,++,++,++%,+,,+,,+,+,,+,++,++-,,-,-,,-,,-,,-,-,-,,-,--,,-,,-,-,, -,--,--,-,--,-,-,--,-.-..--.-.-.-.--.--.-.-.--.--.--.--.--.-.--..-..-..-..-.-..--..-..-..-.--/.//./.././../.././../. ././/.//.//./ /.//.//./././/.00/0//00/0/0//0/0/0//00//0//00/0/0//00//0//0//00/00/0/0/00/01010010100110010010110100101001010101011010010100110110110101121212211221211212212112112112112 1212 21221212 212212132323323232332332323232232323233232232232232323323323323 323322332324344334344334344344334334343343433434344344343344344343443454455454454454545445445455454454454544544544 54554554554554554455454544655655655655656656556566 56556565565655676656556566565655656566565566776766776766766766766766767677677676676766776787887887787878877877878778778778877877877"                                   ! !!  ! ! !! !! !!  ! !!  ! !  ! !! !! !! ! !!  ! !! ! ! ! !!""!"!"!!"!!"!!"!!"!!"!!"!"!!""!!"!!"!!""!""!""!""!"!""!""!"!#"#"#""##"#"#""#"##"##""#""#"#""#""#"#""#""#""#"##"##"# #"##"#"##"#"##"#""##""$#$$#$#$$#$#$##$##$##$#$##$#$##$#$##$#$#$#$$#$$#$#$#$#$##$$#$#$$%$%%$%$%%$$%$%$%$$%$$%$$%$$%$%$%%$%$$%$$%$$%%$% %$%%$%$$%%$%%$%$%$$%$$%&%%&%%&%%&%%&%%&%%&%&%&%%&%&%&% %&%&&%&&%&&%&%&&%&%&%%&&%&&%&&'&'&''&'&&'&'&&'&'&'&&'&'&&'&'&&'&&'&''&''&'&''&'&'&''&''('((''('('('(''(''(''('(''(''(''(''('(('(('('(('(('(('())(()()(()(())()()()(()(() ()()((")())()(())())())())())()**)*))*))*)*)*)*)*))*))*) )*)*)*)*)*))**)*))*+*+*+**+*+*+**+*+**+**+*++*+**+*+* *+*+ +* +*++*+*+**++*++*++,+,+,+,+,++,,+,++,+,+,+,++,++,++,++,++ ,+,,+,,+,+,+,,+,,+,,+,-,--,-,,-,-,-,-,-,-,,-,,-,--,--,- -,--,-,-,-,,.-..-..--.--.--.-.--..-.--..--.-.--.--.--.-&.-..-.-. .-.-.-..-//./..//./././../. ././/.//.//.//.//.//./..//.//00/00/0//0/0//0//0/00//0/0//0//0/00/0 0/00/0/0/00/00/00/0/00/001011010010010010 01010010010010010010110110101011001101101 101010101121221121122121212112112112112121 1 2121221221221212212122112233233232232332322322323323223223232332332332332332334343343434344334334343344343 3433434 434343443443443434344545445545445455445445454544544544544545454455454554554554565655665665655655655656566565565 5 65665656656565656656566565667676676676766766767676776676676676676 6787767677677677677677676788787787877878788778778787 787 7              !          ! !  !  ! ! ! ! !!  ! !! !  !  ! ! !! ! ! ! !! ! !! ! ! !! ! !!""!"!!"!"!""!"!"!!"!!"!!"!!"#""!""!"!"!""!"!""!""!##"#"##"#""#""#"#"##"#""#""#""#""# "#"##"##"##"##"#"#""#"#"##$##$##$$#$#$$#$#$##$#$$##$##%$$%$$#$$#$$#$ $#$$#$#$$#$$#$$#$%$$%%$%$%%$$%$$%$%$$%$$%$$%$%$ $%$$%$%$%%$%%$%$%$%$%$$%$%%$%%$$%%$%%$%$%%$%$%%&%%&%&%%&&%&&%&&%&%%&%&%%&% &%&&%&%%&%&&%&%%&&%&&%&%&&''&''&'&'&'&'&'&''&'&''&&'&&'& &'&&'&&'&'&''&''&' '&''&'&''&&'('('(('(('(''('((''('(''(''((''(''( '('(('(('(('('('(('(()()()(()()(()()(())())(()(()(()((")()() )()())*)**))**))**)*))*)*)*))*))*))*) )+**)*)*)**)**)**)*)**)*)++*+*+*+**+*+**+*+*++**+*+* *+*++*+ +*++*++*++**++**++*++*++,++,+,++,+,+,,++,++,+,+,++,++,+,++,++,+ +,+,,+,,+,+,,+,++,+,-,-,--,--,-,,-,-,,--,,-,-,,-,,-, ,-,- -,--,-,,--,--,-,-,,-,--,,--.-.-..-.-.--.--.--.--.--..-.--.--.--.--./..-..-.--.--.--.-.-.-//../.././../../../../../../../!/.//.//././././/..00/0/0/0/0//0//0 /0//0//0//0/0//0/00/0/00/00//00/0/0//00101010011001010010101010010010 01211010110101101001101101011221122121122112212122121121212112 1212112 212212212121221232232332322322323323323223232 2322323232322332323323233223223434434334334434334343434433433433 4344343443434344344334545454554454554545455445445454545 5455455455454554545544565655656565565565565565 565655655656656656656566577677676776766766766766766766766766766767 76776776767677&                              ! ! !! ! !! ! !  ! !  ! ! ! ! !  ! !! !! !! ! ! !! ! ! !!"!!"!"!!"!"!!"!"!!"!!"!!"!"!!"! !"!"!" "!"!""!"!"!""!""#""##"#""#""#"#"#""#""#""#""#"#"#""$##"#"##"##"#"##"##"#"##"#"#"##$#$$#$#$$##$##$##$##$#$#$# #$#$$#$#$##$$#$#$$#$$#$$#$$%$$%$%$$%$%%$$%$$%%$%%$%$$%$$%$$%$$%$$%$%$ $%$%%$%%$%$%%$%$%%$%%$%&%&&%%&%&&%&%&&%&% %&%%&%&&%&&%&&%&&%&%&&%%&&%&&%%&%&%&%%&&%&&'&''&'&&'&&'&'&&'&&'&''&&'&&'&&'&''&&'&' '&' '&''&''&''&'&&'('(('(('(('((''(''(''(''('(''(''()(('(('(('(('('(('('(''(''()())()()(()()(()(()(()(()(()()((!)())(())())())())()())*)*)*)*))*)*))*) )*))*)*))*) )*+* *)**)*)**)*)**)*)*)*))*++**+**+*+**+*+*++*++**+* *+*+**+** +*+ +*++*+**++*+*+**+*++*+*++*+*++*+*+*+,+,,+,+,+,++,+,,+,,+,,+,+,+,+,,+,++,+ +,++,-,,+, ,+, ,+,+,+,++,+,,+--,-,,-,,-,,-,,-,--,,-,,-,,-,,-,,-,,-,--,--,--,-,--,-,,--,,-,--,--.-.-.-.--..--.-.--.-.-.--.-.--.--.--.--.-..-..-.-.-.-..--.--..-//./..//././..//./..//./.././../../../..//./ /.//.//.//././/.//././/0/0//0/00//00/00//0/0//0//0//0//0/0/ /0/0 0/0/00/00/0/0/00/001001011001010100101100100101001211011011010110110110101101121221221221212122112112112121121121211212 21221221212112122133223223323233232232232322323223233223232 2 32332332332323323233232323233434433434343343343443434343433433434 43443443344344343443443445445544545445445445454 45454 4544545455454454455455454554544 54545566565655655656556556 565656656656656566566566566566776776776766766767767676676676 676767767667677677676776767                                  !!  ! ! !! ! !! !  !  ! ! !! !! ! !! !! !! !! !! ! !!"!""!"!""!"!!"!""!"!"!!"!!"!"!!"!" "!"!""!""!"!""!""!#"##"#""##""#"##"#""##""#"#""#"#"##""#""#""##$##"##"##"#"##""# #"#"##"#$$#$#$#$#$##$##$##$##%$$%$$#$$#$$#$$#$$#$$#$$##$#$#$#$#%$%%$%$$%$$%%$$%$$%$$%$%$%$$%$$%$ $%$%%$%%$%$%$% %$%%$%$%$%$%%&&%&&%&%&&%&%%&%%&%%&%&%%&%%&%&&%&&%&&%&%&%&%&%&&%&%%&%&'&'&'&''&'&'&&'&'&&'&'&&'&&'&&'&& '&''&' '&'&''&'&''&'&&'&'&&''&(''((''('('(('(''(''('('((''(''(''((''('()(('(('(('((''('((''(('(()())(())(()(()(()(()(()(()(()(() )())()())())(()()(**)**)*)*)*))*))*)*)*))*))*+**)*)**)*)*)*)**))**)**+**+*+**+*+*+*++*++*+**+**+**+**+* *+**+,++*++*++*+**+**++*+,+,,+,++,++,+,,+,++,,+,++,++,++,+, ,+,++,,+,+,++,,+--,--,-,,-,,-,-,,-,,-,,-,-,,-,-,,-,,-.--,-,-,-,,- -,-,--,-,-.-.-.-..-.--..-.--.--.--.-..-.-.--.--.-..-..-.-.-..-.-.-..--..-..-.-.//./././././/./../././../..//./.././/.//.//.//./././/././/..0/0//0//0/0//00//0/0//00//0//0/0//0/00//0//00100/00/0/00/0/00/00/0/0/0/00/100100101001010010110010010110100100100121101001101100110101001101100122121221212112112112 121212212 21 2121211232332323233223223232322322332323232332322332232323323233232332334434334344334343343343343433433433433433454 434 4344343434434345545454554 45454456554554554544554554545465565665656556556565565565565655655 6565665665665665665656776766766767676 6767667667667677676776776776776767       !                               ! !! !! ! ! !! ! !! !  ! !  !  ! !  ! ! ! !  ! ! ! ! !! ! !! ! !!"!!"!!"!!"!"!"!!"!!"!!"!!"!"!!"!!!"!""!""!!"!""!"!""!"#"#""#""#"##""#""#"##""#""#" "#""#""#""#"##"##"#"##"##"##""##""#""#$#$$##$#$$#$$#$##$#$ #$##$#$ $#$$#$#$#$%$%$%%$%$%$%$%$$%$$%$%$ $%&%%$%%$%%$%%$%%$%%$%%$%%$$%$%%$$%$%$%%&%%&%&%%&&%&%%&%%&%%&%%&%&&%&%&&%&%&&%%&%&&%&&%&&'&'&'&&''&'&&'&&'&&'&''&&'&&''& &'& &'&' '&''&'&'&''&''&''&''&''&''('(''('(''((''(''((''(''(''(' '('(('(('((''(('(('('('(('('(('('(()()()())()(()(()()(()(()(()(()(()()())())())()()(()(())())()*))*)*)**)**))**)*)**)*)*))*)*))*)*)**)**)**)*)*))*))*)*++*+**+*+*++*+*++*++*+* *+**+*+**+**+*++*++*+ +*+*++*+*+,++,,+,++,+,++,++,++,++,++,+,+ +,+,,+, ,+,,+,+,++,++,+--,--,--,,-,-,-,,-,--,-,-,,-, ,.- -,--,--,-,--,--,--,--,,-,-..-..--.-.-.-..--.-..-.--.- -.-.-..-..-..-..-.--.--..-..-/.//./././../././../../../. ././ /.//.//.//./..//./././/.//.//0/00/00/0/0/00/0/0//0//0//0//0//0//0 0/00/0/0//0//00/0/001011010110110100110010010101001010010010010110101101101101010010110102112121121221211212212121121121211211212 212212 2122122121332323223223223233223223223223223232332323323323233232323323323323232334334334334344343433433434334344334334344344343443 434434434454554454544554455445445445445445445 4+54544554454545455665565665565566566556 5656766566566566565665665665656656655665566767677677676776767676676776766766     '                           !! !! ! ! ! ! !! ! ! ! ! !!  !  !  !  ! !! ! !! ! ! ! !! ! !"!!"!""!"!""!!"!!"!!"!"!""!"!!"!"!!"!"!!"!!"!!"!""#""!""!"!"!""!""!""!""!"!##""#"#"#""#"#""#""##""##"#""#""#"#$##"##" #"#"#"#"$$#$##$$#$$#$$##$#$#$##$#$##$#$#$$#$#$#$#$##$$##$$#$$#%$$%$%$%$$%%$%%$%$%%$%$$%$$%$$%$$%$%$$%$% %$%%$$%%$%%$%%$ %$ %&%%&%&%&&%%&%&%%&%&%%&% %&%%&%&&'&&%&%&&%&&%&&%&&%&&%&%&%&&'&''&&'&'&&'&&'&''&'&&'&'&'&''&&'& &'&''(' '&' '&'&''&''&''&'&'&'&&''&&'&''(''('('('('('((''(''((''('(''(''('' ('( ('('(''(('(('(''))())())())())()()())(()( ()(()(()*))())()())()())())(())()())*))*))*)*)*))*)**)*))*))*))*))*))*))*)**)*)**)*)*))+*+*++**+*+**+**+**+*+**+**+*+**+**+**+*+*++*+*++*++*++*++*++*+**++,+,+,,+,++,++,,++,+,++,+,,+,++,++,++,+, ,+,,+ ,+,+,,+,,+,+,++-,,-,-,,-,,-,,-,,--,-,,-,,-,,-,-,,-,--,,-,--,--,--,--,--,-,--,-,-,,-.--.-.-..--..-..-.--.--.-.--.-.--..-..-..-..-..-.-.--.-..-..//./..//.//.//././/./.././../..//. ./../0//.//.././/./././..//0/0//0//0//00/0//00//0/0//0/0//0/0/0//0// 0/00/0/0 0/00/00/0/00/0/0010110110010101101001001001001010101011011001101100110110121121221212212112121212112121 212212211211212121221323223323232232232332322322323223233233233233233232323443433433434343343343343343343344343343343443443443434434434343344334334554544545544544545454454454454 54545 545546565565656565565565565565 565656565655656 6566557677676767767667667667667676676676676676766                           ! ! !  ! !! ! !! !  ! !!  !  ! !  !  "!! !! ! !! !! ! ! !!  !"!!"!"!!"!""!"!""!"!"! !"!!"#""!""!"!""!"!"##"#"#""#"##""#"#""#"#"#""#" "#" #"##"#"#"##"#"#"##"$$#$#$$##$#$$#$#$$#$##$#$##$##%$%$$#$#$ $#$#$##$$#$#$$%%$%$%$%$$%$$%$%$%$$%$%$%$$%&% %$%%$%%$%$%%$%%$%$$%%$$%$%$%$%%$%%&%&&%%&%&&%&&%&%&%&%&&%&%%&%%&%&%&%%&%&&%&&%&&%&&%&&%&%%&%&%&&%%&&%&%&&'&'&&'&&''&&'&'&&'&'&''&''&&''&&'&&'&&'&& '&''&''&''&'&''&'&''&'&'&'&'&'&&((''(''(''(('(('(('(('(('('((''(''('(' '('(('(('(('(('('(('(('(('(('('))()(())(()()())(()(()())()(()(())(()(()(())()())())())()())())()(*)**)*)*)**)*))*)*))*))*))*))*)**)**)**)**)**)*)*)**))**)*)**+**++*+*+**+*+ *+*+**+**+**+**+*++*++*++**+*++*+*++*++**+*,++,+,,+,+,+,+,,++,+,++,+,++, +,+, ,+,,+,,+,,+,,+,+,++,+,,++,+--,-,-,--,--,,-,-,-,,-,,-,-, ,-, -,-,--,--,,--,,--,--,--,--.-.--..-.--.--.-.--.-..--.-.--.--.--.--.-.-- .-..-..-.--.--.-..-.-.-.-..-..-.-.--./..//.//././../../../.././.././ /./ /.//./././/0/0//0/00/0//0/00//0/0/0/0//0/0//0/ /0/00/00/0/00/0/0/010101001100110010101010101100100 101 1011010011010110100121122122121121121212112112212112122112212122112122123232322332232322323323232232322323323323323323322332323233434343343344334334343 343343433454 434434 434344343443345454545545455445445445445455455455454554554544544554454465565665655655655655665566556565665655 656 6566565656565565665655665565567677677676677667667667 676                             !           !!  ! ! !  ! !  !  ! !!  !  ! !! !! !! !! !! ! ! !!"!!"!!"!!"!"!!"!""!"!"! !"!!"!!"!""!""!"!"!"!"!""!""!""#""##"##"#""#""##"##"#""#""#""#""#"#"#""$# #"# #"#"##"##"#"#"##"##"#$$#$#$#$$#$#$$##$#$##$#$$##$##$#$#$## $#$ $#$$#$$#$##$#$##$#$##$##%$%%$%$%%$%$%$%$$%$%$%$%%$%$$%$$%& %$%%$%%$%%$%%$%%$%%$$%%$%$%%&%&%&%%&%&%%&%&&%&%&&%%&%%& %&%%&%%'& &%&&%&&%&&%& &%&%&%&%&&%&'&'&''& &'&'&''&&'&&'&&'&'&&'& & '&''&' '&'&''&'&'&''&'&&''&&'('(''('('('(('(''(''(''(''('('(''('(' '('(('('(('(''(''(('(''('('())())(())()()(()()())(()(()(()(()()(()()((")()(())())())())())()()*)**))*))*)*))*))*)**)*))*))*)*))*)) *)**)*)**)**)**)*)**+*++*+**+**+*+**+*+**+*+**+**+,++*+ +* +*+*+**+,,+,+,+,,+,+,+,+,+,++,+,++,++,++,++,+,+,,+,,+,+,+,+,+,,++,++--,-,-,,-,,-,,-,,-,-,,-, ,-,,-,,-,,-,--,--,--,-,-,-,--,-.--.--.-.--.-.-.--.--.-.--.--.--.--.-.-..-..-..-.--.--..-.-//.//./../././.././.././../../../././././../.././/.//.//.//././..//.//./0/00/00/0/00/00//0//0//0/00//0/00/0//0/00/0/0/00/0//110101101001001101001001001001011001001011010110101101121212112121211211211211212212212121221212112212232232323232 2322322332 2323323233233232323323223232323443434343 3433433434 434343434434545544545454454544544544544544544545 545545544554554544565665665565565665566565565565565576 656 65656 65656656566566                      !         !! !  ! ! !  !  !  !  !  ! !! !! ! ! ! !!  ! ! ! !! !!"!"!""!"!!"!!"!"!!"!!""!"!!"!!"#""!" "!""!"!!""!!""!"!"!"##""#"#""#"##"#""# "#" " #"#"##"##"##"##"##"#"#""#"#""#$#$$#$##$#$$#$#$$#$##$#$##$#$##$## $#$$#$$#$$#$$#$#$$#$$#$##$#$##$%$$%$%%$$%$%$%$$%$$%$%$ $%$ $%$%%$%%$%$%%$%$$%%$%%$$%%$%%$$%&%&%&&%%&%&%%&%&%&%&%&%%&%%&%%&%%&%&&%&%&&%&&%&%&%&%&&%''&&'&&'&'&&'&'&'&&'&&'&&'&&'&&'&&'&&'&& '&' '&''&'&''&&''&''&''('('('(''(''('('(''(''(''(''(''(''('('(''('(('(''('('(''('((''(''('(('()()())(()())(()(()()(()()()(()( ()())())())())())())()(()(()*)**)*)*))*)*))**)*))*)*))*))*) )*))*))**)**)*))**)**))*)**)**)*)*+*++*+**+*++*+*+**+**+**+,++*++*+*++*++*++*+*++*+,++,+,++,+,+,+,++,++,+,+,++,++,++,+,,++,,+,,+,,+,++,,+,+,,+,+,+,-,--,--,--,--,-,--,-,-,,-,-,,-, ,-,--,--,--,-,,-,--,--,-.-.--..-..-.--..-.-.--.-..-..--.-.--.--.--.-..-..-.-.-.-..-..--.-../././././././../../.././././../.././/.//././/.//././/.//././.00/00//00/00/0//0//0/0/ /010 0/00/00/0/0 0/00/0/00/0101001010110010010100100100101001211011011010110110010011001011212212112121121121121221212212121221221221221211223323323223233232323323223223232232232 23233233233232232332322332323433443343433434344343343343 3 43434 43443443434334434434434545454545454 454544545 545545545454545455455445565656556556556565565565565565565565665665665655656656656656656                                   ! ! !! ! ! ! !! !  ! ! ! !  !  ! ! ! !! !! !! !! ! ! !! ! ! ! !!""!""!!"!"!!"!!"!!"!!"!"!"!!"!!""!!"!!"!! "!""!""!""!""!""!"!"!!""!""#"#""##"##"#"#""#"#""##"#""#"#""##"#""#""#"##"##"#"##"#""# #$#$#$$#$#$#$##$#$##$##$##$ #$##$#$#$$#$#$#$$#$$#$$#$#$$#$#$$#$%$$%%$%$%$$%%$%$$%$$%$$%$$%$$%$%%$%$%%$%%$%%$%%$%%$%&%&&%&%&&%&&%&%%&&%&%%&%&%%&%&&%%&&%%&%%&&%&&%&&%&&%&%%&&%&%&%&&%&%&%&''&&'&''&'&'&&'&&'&&'&&'&'&'&&'& &'&' '&'&''&''&'&'&''(''('(''('('(('(('((' '('(' '('(('(('(('(('(''('('('(''(())()()()(()(()(()()(()(( )())())()())())())()())()(()(*)*))*)*)*)*))*))*))*))*)*))*))*))*)**)**)**)*)**)**)*)*)**)**)**+*+*++*+*+*+**+*+**+*+**+**+**+*++*++*+*++*+*+,+,++,+,++,+,+,,+,++,++,++,++,++,++,++,+,,-,,+,+,,+,+,,+, ,+,,++,--,-,-,-,-,-,-,-,,-,-,-,,-,- ,-.- -,- -,-,--,--,-,--,--.-.-.-.-.--.--.--.--.--.--.--.--.--.--.--. .-..-..-.-..-.-.-..-.-.-.--.././/./././../.././../. ./../0/ /.//./ /.//.././/././/.//./././0/0//0/0//0/00//00/00/00//0//0/ /0100/00/0/0/00/0/00/00/00/0/00101100101011010010010010010011001 0100100 1011010110110101001011010011012211221121121212121121212112112112121211212212212212121221212122122323223223232322323232232232232 234332332332332323233233233223323434334343343344334343343343 3434334343443443443434433434435545445455455445445445455454454 45455455455454545545566565655656656566556556556565565565665565665665665656656566565655                           !  ! ! ! ! !! ! ! !  ! !!  ! !  !  !  ! !! !! ! !! ! !! ""!"!""!""!"!"!!"!!"!!"!!"!!"!"!"!""!"!""!""!""!""!"!""!"!"!""#"#"##"#""#"#""#"#""##"#"#""#"#""#"#""#""#"# #"##"#"##"##"##"#"##"##$#$#$$#$$#$##$#$##$$#$$##$#$##$##$# #$#$#$#$$#$$#$#$##$#$$%$%%$$%$$%$%%$%$$%$$%$%$$%$%$$%&%%$%$%%$%%$%%$%%$%%$%%$%$%$%%$$&%%&&%&%%&%&%&%&%%&&%&%%&%&% %!&%&%%&%&%&&%&&%&&%&%&%%'&&'&&'&&'&&'&'&''&&'&'&&'& &'&''& &'(''&''&''&''&'&'&'&&''&''&''&'&&''('(('(''('((''('(('((''(''('(''(''('( ('(('(('(('('(('(('(''(()) ()()()(()()(()()(()(()())())()()())())())())()()**)*))*))**)*)*)*))*)*)**)*)*))*)) *)**)**)*)*)**)*))*))**))**)+*++*++*+*+*++*+*+**+**+**+**+**+*++*++*+*++*++*++*+*+**+,+,,+,++,+,+,,++,+,,+ +,+,+,,++,++,+ +,+, ,+,++,,++,+,,+,,+,++,++,++,,-,--,-,-,,-,-,-,,-,,-,-, ,-,--,,-,-,,--,--,-,--,-.-.-.--.--..--.--.--.--.--..--..--.-.- -.-..--..-.-..-..-.-..-.--.-./..//.//././/././..//./.././../.././././. ./././/.//././/../../././/.//0/0//00/0/00/0/0//0/0//0/0/0//0/00/00/00/00/0/00/00/0/01101010011001100100100110101100100110100100 101 10110110101001100110110122112112122112121221121121221221221221212112121123323323233232322323223223232232232 23232332323 32322332332332323323343343344343433433443344334334334343343 34343434434344344344354455445455445445455454454554554454454 45445655455455454454554556565656565565565565655656556565!$                                ! !!  ! !  ! ! !! ! ! !! !!  !  ! ! !! !! ! !! !! ! ! ! ! !! ""!"!!"!!"!!"!"!!"!"!!"!!"!!"!"!!"!"!""!""!"!""!""!""!"!""!"#"##"#"#""#""#""#""#""#""#" "#"" #"##"#"#""##"##"#""#"##""##"##"##$##$$##$#$$#$#$##$#$##$#$#$##$#$$#$$#$#$$#$#$#$$#$#$$%$%%$%$$%$%$$%$%$%$%%$%$$%$%$%%$$%$%%$%%$%$% %$%$%$%%&%%&&%&&%%&%&%%&%%&%%&%%&%%&%&%%&%%&% %&'& &%&&%&&%&&%&%&%&% &'&'&'&&'&&'&'&''&''&'&&'&&'&' '&'&&''&''&''&'&''&''('(''(('('('(('('((''('(''(('(''(''(''('(('('((''(''( ('('(''(''(())(()(())(()(()(())()(()( ()(()(())())())() )())())()()(()(**)*)*)**)*)*))*) )*) )*) )*)**)**)**)**)*)**)**))**)*))**)**++**++*+*+*+**+*+**+*+**+**++*+* *+**+*+*+ +*++** +*++*+*+**+* +,+,++,++,++,++,,+,++,++,+,++,++,+,,+,,++,,+,,+,,+,,+,++,++,,+,,+,-,-,-,,--,,-,,-,-,-,,-,,-,,-,--,--,--,-,,--,--,-,-,-.--..-.-.--.--.--..-.-..-.--.--.--.-. .-.-.--.-.--../.././/././..//../././.././../../.././/.//.//././..//.//.././.00/0//00/00/00//0//0/0/0//0/0/ 0/00/00/00/0/00//0/0/00/00/010100110010110110110110010110010010100101 101001010110112121211211212121121211211212113221 2122121212122323223232323322323223323223232332323223343323323323323323323232332323323233234434434433434334343434334343434433434354434434 434344344343454545544545545454 454454454 4565 545545545 5454554554544544565656566556565656565565 5                                   ! !! ! ! ! ! ! ! !  ! ! !  ! !! !! !! ! !! !! !! !! !!"!!"!!""!""!"!"!!"!""!"!"!!"!!"! !"!! "!"!""!""!""!"!""!"!""!"#"#"#""#""#"#"#"#"## "#" "#$##"##"#"##"##"##""##"#$#$#$#$$#$$#$$##$#$##$##$##$#$# # $#$$#$$#$$#$#$ $#$#$$##$#$$#$$#$%$%$%$$%%$%$%%$$%$%%$%$$%$%%$%$$%$%$$%$$%$%%$%$$%%$%$%%$%%$%$&&%&%&%&%&&%&&%%&&%&%&&%%&&%&&%%&%%&%&%&&%&%&%&&%%&%% &%&&%&&%&&%&&%&%&&%&&%%&&%&%&%&%&%&&''&''&''&&'&''&'&&'&'&&'&'&&'&&'&'&'&'&'&'&'&&''&''&'&'(('(('('('(''(''((''(''('(''(''('('('(('(('(('((''('(('(''()(()())()()()())(()(()())(()(()(()(()(()(() )())())()())()())()())())()(()())()()**)*))*))*))*)**)*))*)*))*))*))*))*))*)**)*)**)*)**)*)*)*)*)**++*+*+*++**+*++*+**++*+* *+*+*+*+**+*+*++*++*+*++*+**+*+**+*+,,+,+,++,+,,++,+,++,, +,++,+,++,+,++!,+,,++,,+,,+,++,,+,,++-,,-,--,,-,-,-,-,,-,-,,--,-,,-, ,-,,-,,-,--,-,-,--,--,-,--,--,-.-.--.-.--.--..-.--.-.- -.--.-..-..-..-. .-.-.-.-.--..-..-.--././/././/../././/./../..//../../../.././. ./..//.//.//.//./././..//./..//0/0//00//0/0//00/0//0//0//0//0//100/00/0//0/00/0/0/00/0101010010010010011001011001001011010010010110110110101001011010112121121121211212112122112112112121211212112212122122122123233232232232322323223232232232332332323232323233232323223443434433433433434334343343433 434434434434434344334434343443435545545545545454544544544545455455454554545455454554566566566565565656556565565565  "            !        ! !! ! !! ! ! ! ! !!  ! !!"!! ! !! !!"!""!"!!""!"!!"!!"!""!#""!""!""#"#"##""#"##"#"#"#""#""#&#"#$#$##$#$$##$#$##$##$##$#$#$$#$$#$$#$$#$#$$%$%%$%%$%$$%$%%$%$$%$$%$%$%%$%$%&%&%&&%&%&%&%&&%&%&&%&&%&&'&''&'&&''&''&'&&'&'&&'&'&&''&'&' '&''('('(('(''(''(''(('(''(''($('()(()()()(()(())()(()(()(()(()(()()())())())*)**)*)**)*)*)**)*)*))**)**+*++*+*+*++*+**+**+**+**+**+*++** +*++*++*++*,,+,,+,+,+,,++,,+,+,+,,+,,+,,+,+,,-,-,--,-,,--,,-,,-,,-,,-.--,--.--.-.-.. -.-..-.-..-.-..-.-..-..-.././././/.//.//..//././/../0//.//././/0/0/0//0//0/0//0/0/0//100/00//00/00/0/00/11011010100101001010010110101101 121211212112112112112121212212122122322332322322332332323323322343 323 3233232334344334344343433443434335443443443443434454554544545545454544544544545455454554554554455455        '                    ! ! ! ! !! ! ! !  !  ! !"!! !! !! !"!"!"!!"!!"!""!""!"!!"!!"!"!""!""!"!!"!!""!""#""#""#"#""#"#""#""##""#"# #"# #"##"##$#$#$##$#$##$##$#$#$$#$$#$$##$$#$$%%$%$%%$%$$%$$%$%%$%%$$%$%$$%$%$%%&%&&%&%&&%%&%&%&&%&%&&%&%%&%% &%&&%&&%&&%&&'&&''&''&&'&&'&'&&'&&'&&'&& '&''&''& '&'(''((''(''((''('('(''(''('(''(''(('(('(('(())()(()())()(()()())()(()(()(()*))()())())**)**)*)*) )*))*))*)**+**)**)**)*)**)*++*+*++*+*+**+**+**+*+**+*++*+*++*+**++,+,,+,+,+,++,+,+, ,+,+,,+,,+,--,-,--,,-,,-,,-,-,,-,-,-,--,--,--,-.-.--..-..--.-.-.--..-.--.- -.--.-..-.-. ./..//././../../././/../..0/ /./ /././/.0//0/00//0//00/0/0/00//0/0//0/00/00/0/00/01001010110010010100101010010110)1212212112212121121121121121221221223233232323322322322322 323323434433434334343 343433434 4343434454554554544554544544545445545545455454554              ) ! !! ! !! ! !  ! !! ! !  ! ! !! ! !"!"!!"!"!!""!"!"!!"!!"!""!!"!!"#""!"!""#"#"##"#""#""#""#"#""#""#""#$#"##$##$#$$#$#$#$$#$##$##$#$#$#$$#$$#$$#$$#$%$%%$%$%$$%$$%$$%%$%$$%$$%$%%$%%$%%&%&%%&%&&%&%&&%&%%&%%&%%&%&&%& &'&&''&&''&&'&&''&''&&''&'&&'&&'&''&''('(('(''('('('(('(('(''(''('(''('('(()())())()(()()())(()(()(()()())())())())(())*)*)**)*)**)*)*))*)**)**))**+*+**+*++**+**+*+* *+**+*+,++*+ +*++,+,++,+,,+,,++,,+,+,+,++,++,,+,,+,,+,,+,,+,++--,-,-,,-,--,,-,-,--,--.-.--..-.-.-.--.-.--./..- .-../././../././.././../.././/././/0/00/0/0/00/0//0//0//0/0 0/0100101001010110100100101011010101101101121221212212122112112112112132 212213322323223223232232332322322332323223323323343443443434434343343433454434434344345445445454545545445454455455455 @:9::99:99::9:99:99:99:99:9:99:9:99:9 9:;::9:99::9:9:9::99:9::;::;;:;:;;:;;:;;:;;::;::;:;;::;:;: :;:;::;:;:; ;:;;:;;:;;:;;:;;:;:<;<<;<<;<;;<<;;<<;<;;<;<;;<;<;;<;<;;<;;<;;<;<;<<;<<;<;<<;<<;<<;<=<==<=<==<<=<=<<=<<=<=<<=<<=<<=<<=<<=<= =<=<==<==<=<=>>=>>==>==>==>=>==>==>==>=>==>=>?>>=>=>>=>=>>=>>=>>=>>=>>=>=>?>>?>?>?>?>>?>??>??>?>?>?>>??>>?>?>>?>>?>>?>>?>??>??>??>??>??>?@@?@?@??@?@@?@@??@??@?@??@?@??@?@?@??@A@A@@?@@?@@?@?@??@?@?@@?@??@??@@?@@A@@A@A@AA@@A@@AA@A@A@@A@@A@@A@@A@@A@@A@AA@A@A@AA@AA@AA@A@A@BBAA BABAABABBABAABAABABAABABAABAABBCBBAB BABABABABBABABABAACBBCCBBCBCCBCBCBBCBCCBCBCBCBBCBBCBBCBCCBCCBCCBCBCCBCBCCBDCCDCCDCCDCDCDDCDCCDCDCDDCDCCDCCDCCDEDDCDDCDDCDCDDCDEDDEDEDEDDEDEDEDEDDEDDEDDEDEEDEDEDEDDEDEEDEEDDEDDEEDFEFEEFEFEEFEFFEEFEEFEEFEEFEEFFEFFEFEFFEFFEFEFFEFFEFGFGGFFGFGFGFGGFFGFFGFFGFFGFF GFG GFG GFGGFGFGFGGHGHHGHGHGHGHGHGGHGHGGHGHG G HGHHGHHGHHGHHGHHGHHGHGHGHHGGHGHHIHIHIHIIHIHHIHHIHHIH HIHHIHHIHHIH IHIIHIIHIHIIHHIHJJIJIJIJIJIIJJIJJIJJIJJIJIJIIJIIJIIJIJIIJKJJIJJIJIJJIJJIJJIJJIIJJIJIJJIIJKKJKJKJJKJJKJKJJKJJKJKJJKJJKJKKJJKJKJJKJJKJKKJJKKJKKJKKJKKJKJKKJJKJKKJLLKLKKLLKLLKLKLLKLLKLLKLKKLKLK KLKKLKKLKLLKLKLLKKLLKLKLLKLLKLKKLMLLMLLMLMLLMLMLMMLLMMLLMLLMMLMLLMLMML L MLMMLMMLMMLLMLMLMMLMLMLMLLMNMNMMNMMNMMNMNMNMMNMMNMMNMMNMNMNMMNMNMMNON NMNNMNNMNMNNMNMNONNONNONOONONONNONONNONNONNOONONNONNONNONNONOONONOONOONOONONOONOONONNONOOPPOPPOPOPOPOOPOPPOPOOPOPOOPOOP OPOOPOOPOOPQP POPPOPPOPPOPPOPPOPPOPOPOOPPQPPQPQPPQPQPPQPQPPQQPQPPQPPQPPQPQP PQPQQPQQPQQPPQQPQPQQPQPQRRQRRQRRQRQRQQRQQRRQQRQRQQRQRRQ QSRRQRRQRRQRQQRRQRQRRQRQSRSRRSRSSRSSRRSRRSRRSRSRSR RSRSSRSSRS SRSRRSRSRSSRSTSTTSTSSTSSTSTSTTSTTSSTSTSST STS STSTTSTSTTSTTSTSTSTTSSTSTSSTSTTUTTUTTUTTUTUTTUTUTUUTTUTTUTUTTUVUUTU UTUTUUTUTUUTUTUUTUTUTUTTUUTVVUUVUUVUVUUVUVUUVUUVUVUVUUVUUVUUVUVVUVUVUVVUVUUVUVVWVWVWVVWVVWVWWVWVVWVWVVWVVWVV WVWWVW WVWWVWWVWVWVWVWWVWVWVWVWXWXWXWWXWWXWXXWXWXWXXWXXWWXWXXWW$XWXWXWXXWXXWXXWXXWXWXXYXXYYXYXXYXXYXYYXYXXYXXYXYXXYXXYX XYXXYXYYXYYXYYXYXYXYXYYXYYXXYYXXYX:9:99::9:9:9:9:99::9:9::99:99:99:99:99:9::9::9:9::9::9::9:9:9:9::;:;::;::;:;:;::;::;::;:;::;:;;:;;:;;:;;:;::;;:;;::;;:;:;;::<;<;<;;<;<<;;<;;<;;<;;<;;<;<;;<;;<;<<;<;<<;;<;<;<<;;<<==<=<==<==<==<=<<=<=<<=<<=<<=<<=< <=<==<==<==<=<==<<==<=<<=>==>==>>==>=>==>=>>=>>=>>==>==>>=>==>==>= >=>=>=>>=>=>>=>==>=>=>>?>??>??>?>>?>??>>?>?>?>>?>>?>>?>>?@? ?>??>?>?>??>??>?>??>??>?@?@??@@?@??@?@@?@@?@??@?@@?@@?@??@??@??@??@?@?@@?@@?@@?@@?@@?@@??@?AA@@A@@A@A@@A@@A@A@@AA@@A@@AA@ @A@@A@A@AA@AA@AA@A@AA@A@A@@AA@A@AABABBAABABABBAABABAABAABAABABAABABAAB BABBAB BABABABBABBABAABCBCCBBCCBCBBCBCBBCBBCBBCBCCBCBCBCBBCB BCBCBCCBCCBCCBCBCCBCCBCCBCCDCDDCDCCDDCDCCDCDCCDCCDCDCCDCCDDCDC DCD DCDCDCDDCDDCDDCDDCDDCDDCDCCEEDEDEDEDEDEDDEDDEDEEDDEDEDDEDEDDEDE EDEDEDEEDEEDEEDEDEEDFEFEEFEEFEFEFFEEFFEFEEFEEFEEFEEFEEFEEFEEFEFEEFEEFEFEFFEFFEFEFFEFFEFEFFEFFEFEFGFGFFGFGGFGGFGFGFGFGFFGFFGFGGFGFGGFFGFGGFGFGFGGFGFGFHHGHGHGHGGHGGHHGGHGGHGGHGHHGH GHGHGGHGGIIHHGHHGHGHHGHHGHHGHHGHGHGGHIHIIHIHIIHIIHIHHIIHIIHIHHIH HIHHIIHIIHI IHIIHIIHIHIIHIJJIIJJIJIJIIJIIJIIJJIIJJI IJIIJI IJIJJIJJIJIJIJJIJJIJJIJKJKJKKJKJKJJKJJKJKJJKJJKJKJJKJKJJKKJJKJKKJKKJKJKKJKJKJKKLKLKKLKLKKLKKLKKLKLKLKKLKKLKLK KLMLLKLLKL LKLKKLLKLLKLKKLKLLKLLKLLMLMLMLMLLMLMLLMLLMLLMLLMNMMNMMLMLMMLMMLMMLMMLMLMMLMMLMMLMMNNMMNMNNMNMNNMNMNMNNMNMMNMMNMMNMMNONNMNNM NMNMN NMNNMMNONOONONONONNOONONOONNONONNONNONNONNONNONOONOONOONONONNOONOONONNONOPOPOOPPOPPOPOPOPPOPOPPOOPOPOOPOOPOPOPOOPOOPOOPOQPPOPOPPOPOPOOPOOPPOPOQQPQQPQPPQPQQPQPQQPPQPQPQQPQQPPQPPQPQPQPPQPPQPPQPQQPQQPQQPQPQPQQPQPPQQRQQRQRQRQQRQQRQRQRQQRQRQQR Q RQRRQRRQRRQRRQQRQQRQRRQRRQRRQRQQRQRSSRSRRSRSRSSRSRRSRRSRSSRRSRSRRSR RSRRSSTSSRS SRSSRRSSRSSRSRSRSSRRSRSRRSRTSTTSTTSTSTTSTTSTSTTSSTSSTSSTS STSTTSTTSTTSTTSTSTSTSTTSTSTTUTTUUTTUTTUTTUUTUTTUTTUT TUTTUTTUVU UTUUTUTUUTUUTUUTUTTUUTUUTTUTTUVUVVUVUUVUUVUVUVUVUUVU UVUUVWVVUVVUVVUVVUVUVUVVUVVUVUUVUUVVUVUVVUWVWWVVWVWWVWVWVWVVWVWVVWVVWVVWVVWVVWVVWVVWVVWVW WVWWVWWVWWVWVWVWWVWWVWWXWXXWXWWXXWXWWXWXWXWWXWWXWWXWWXWWXWWXWWXWWXXWXXWXXWXWXWWXWWXWXXWXWWXWXWWYXYXXYXYYXYXXYXYXXYXXYXXYXX$YXYYXYYXXYXYYXYYXYXXYXYX9:9:99:99:99:9:99:9:9:99:99:9:99::99:99:99:99::99 :9::9:9:9:9:9:99:9:99;:;:;;::;::;;:;::;:;:;: :;::;:: ;:;:;;:;;::;;:;;:;;:;:;;<;<<;;<<;;<;<;;<<;<< ; <;<;<<;<<;<;<<;<<;<<;<;<<;<<;<;;<=<=<<==<=<=<==<<=<=<=<=<=<<=<<=<<=<< =<==<==<==<==<=<=<==<==<=<<==<==<<=<=>>=>>=>=>==>>==>>==>>=>==>==>==>=>==>==>==>=>=>>=>=>=>=>??>??>>?>>?>?>?>>?>?>??>?>>?>?>>?>?>? ?>??>?>??>?>>?>?>?>@@?@??@?@??@?@@?@?@?@@?@?@??@?@??@??@??@?@? ?@?@@?@@?@?@@?@?@?@@?@@A@AA@A@A@@AA@@A@A@@A@A@@A@A@@A@@A@@A@AA@AA@A@AA@AA@A@A@AA@A@@ABABBABABABABAABAABABBAABABA ABABBABBABBABABBABBABBABAABABABABCBCBCBCBCBCBCCBBCCBCCBBCBBCBBCBBCBBCBBCBBCBCBBCBBCCBCCBCCB CBCBCBCBCCBBCBBCBBCCBDCDCDCCDCDDCDDCCDCCDCDCDCCDCCDCDDCDCDCCDCCDCDDCDCDDCDCDDCDDCDCDDCDCCDEEDEEDDEDEDEDDEDDEDDEEDEDDEDEEDDEDEDEEDEEDEDEEDEEDEEDDEEDEDEEDEEFFEFEFFEFEFEEFFEFEEFEEFEFE EFEFE EGFFEFFEFEFEFFEFEEFEFEFEFEFFGGFGFGFFGFGFGFFGFGFFGFFGGFGF F GFGGFGGFGFGFGGFGGFFGGFGGFGFGGFGGFGFGFGGFHGHGHGGHGHGHHGHGHHGGHGHGHGGH GHGHG GHGHHGHGHHGHHGHHGHHGHHGHGGHGGHGGHGGHGHHIIHIHHIHIIHHIHIHHIHIIHHIHIHHIHHIHHIIHHIHIHIHHJIIHIIHI IHIIHHIHIIHIHIIHJIJIJIIJJIJJIJIJJIJJIJIJIIJIIJI IJIJIJJIJ JIJJIJIJIKJKJKJJKJKKJKKJKJJKJJKJJKKJJKJJKJJKJJKJJKJJKJKKJKKJKJKJKKLKLKLLKLKKLLKKLKLKKLKLKLLKKLKLKLKKLKKLKKLKLLKLLKLLKLLKLLKLLKKLLKLKLLKLLKKMLLMLMLMLLMLLMMLMMLLMLLMLMMLMMLMMLMLLMLMLMLMMLLMLL MLMLMMLMMLMMLMMLMMLMLLMLMMLMMLNNMMNMMNMMNMMNMNMMNMNMMNMMNMNNMMNMNMMNMMNMNMNNMNMNNMNMMNMMNMNNMMNONOONONONNONNONNONONNONONONONNONOONONOONOONONOONONOONONNOPOOPPOOPOPOOPOOPOPPOPOPOOPOPOOPOOPOOPO"POPPOPOPOP POPPOOPQQPQPPQPQPQQPQPPQPPQPPQPPQPQPPQPPQPQQPQPQQPQPQQPQRRQRRQRQQRQRRQRQRQQRQQRQQRQ QRQQRQQRQR RQRQQRQRQRRQRRQRSSRSRSSRSRSRSRRSSRRSSRRSRSRRSR RSRRSRRSTS SRSSR SRSSRSSRSSRSSRTTSTTSSTSSTTSSTSTTSTSSTSSTSTSTSTSSTSSTUTTSTTSTSTTSTTSTTSSTTSTTSTSSTUTTUTUTTUTTUTUUTTUTTUTTUTUTTUTUUT TUTTUTUUTUUTUUT UTUTUUTUTUVUVUVUUVUUVUUVUVUUVUUVUUVUUVUUVUVUVVUVVUVVUVVUVUVVUVUVVUVWWVWWVVWVWVVWVWVWWVWWVVWVVWVVWVWVWWVWVWVVWWVWWVWWVWWXWXXWWXWXWXXWWXWXXWWXWWXWWXWXWWXWXWWXWWXW XWXXWXWXXWXXWXWXXYXYXYXYXYYXYXXYXYXYXYXYXXYXYX XYXYYXYYXYXYXYYXYYXYXYYXYXYYX#9899899899898989988988:9:99:9:99::99:99:99:9:99::99:99:99:9::9::9:9::9::9::9:9:9::;:;:;::;;::;:;:;::;::;::; :;<;;:;;:;;: ;:;;:;:;;:;:;<<;<;<;<<;<;<;<;;<<;<;;<;<; ;<;<;<;;<=<<;<<;<<;<<;<<;<<;;<;<<==<<==<==<==<<=<=<==<<=<=< <=< < =<= =<==<=<==<=>=>>=>==>=>=>>==>==>=>==>=>==>==>==>?>>?>>=> >=>=>>=>>==>=>>=>>=>?>??>>?>>?>?>>?>?>?>?>??>?>>?>>??>?>>?>>?>??>??>??>??>?>??>??>>?>>??@@?@@?@@?@?@??@?@@?@??@??@??@??@??@A@@?@?@@?@@?@@??@@?@@?@@?@A@A@A@A@@A@A@@A@A@A@A@ @A@@A@A@AA@AA@AA@A@A@AA@A@A@AA@A@@BABABBABABBAABABABBAABBABBABAABAABABAABA ABABAB BABAABBABABABABABBCCBBCBCCBCBBCCBCBCBBCBBCBCCBBCBBCBCBCCBCBCCBCCBCBBCBCBCCBDCCDDCDDCDCDDCDCDCCDCDCCDCCDCCDCDCCDCDCDDCDCDDCDCDDCDCDDCDDEDEDEEDDEDEDDEDDEDDEDEDDED DEDDEDDEDDEDEEDEEDEEDDEEDEEDEEDEDEEDDEDEFFEFFEFEFFEFEFFEFEFEFEFEEFEFEEFFEFEEFEEFEEFEEFEEFEFFEFFEFFEFEFFEFFEFFEGFGGFFGGFFGGFFGFFGFGFGFGFFGFFGFGF FGFFGHGGFGGFGGFG GFGFGFFGHGHGHHGHGGHGGHGHGGHGHGGHGHGHGGHHGGHGHGGHGHHGGHGGHHGHGHGHIHHIHIIHIHIHHIIHIIHIHIHHIHIHIHHIHHIHHIHIHIIHIIHIIHIHIHIIHIHHIHHIJJIJIIJJIJIJIIJIIJIJIJJIIJIJIIJJIIJIIJIIJIJJIJJIJIIJJIJJIJIJJIJJIJJIJJKJJKJJKJJKKJKJKJJKJJKJKJKKJJKJJKJJKJJKJKJKKJKKJKJKKJKKJKKJKLKKLKLKLLKLKKLLKKLLKLKKLK KLKLLKKLKKLKKLKKLKL LKLLKLKLLKLKLKKLKLLKKLLMLMLLMLLMLLMMLMLLMLLMLMLLMLMLLMLLMLMLLMNMMLMMLMLMMLMMLMMLMLLMMNMNMNMMNMMNMNNMNMNMMNMNMMNMNMNNMN NMNMNNMNNMMNNMMNMMONONONONNONNOONONNONONNONONNONNON NONO ONOONONONOONOOPOPPOPOPPOOPPOPOPOOPOOPOPOOPOOPOPPOO POPOPPOP POPPOPPOPPOPPOPPOPQQPQPPQPQPQPQPPQPQPPQP PQPPQPPQPQ QPQPQQPQQPQPQPQPPQRRQQRQQRRQQRRQRRQRQRQQRRQQRQRQQRRQRQQRQRQQRQQRQQRSRRQRRQRRQRRQRQRRQRQQRSSRSRSRSSRSRSRRSRSRSRSSRSRRSR RSRR SRSSRSSRSSRSRSSRSRSSRSSRSSRSSTTSSTSTSTSTSSTSSTSTTSSTSSTSSTSTSSTSSTTSTTSTTSTTSTTSTSTSTUTUTTUTTUUTTUTUTTUTUUTTUTTUTT UTUUTUUTU UTUTUUTUUTUUTUTUUTUTTVUVUUVUVVUVUVVUVUVUVUVUVUVUUVUUVUUVUVVUUVUVVUVVUVUV VUVUUVUUVVUVUUVVWVWVWWVWVVWVWWV VWVVWV VWVVWVWVWWVVWVWWVWVWVWWVWVVWVWVXWXWWXWWXWXXWXWXWWXWWXWXWXWXWWXWWXWWXWWXWXXWXXWXWWXWXWXWXXWXXWXXWXWXWWYYXYXYXYXXYYXXYXXYXYXXYXYXXYXX9898998989899898988:9::9::9:9:9:99:9 9:99:9:99:99:9:9::9::9::99:99::9::9:9::9;:;;:;::;:;:;;::;:;;::;::;:;;:;:;::<;<;;:;:;;:;;:;:;;:;;:;;:;;:;:;;<;<;;<;<<;<<;<;<;<;;<;;<<;<;< ;<;< <;<<;<<;<<;;<<;<;;<;=<=<<=<=<<=<==<=<<=<<==<=<=<<=<<=<<=< <=<==<==<==<<==<=<<==<==>=>=>=>>=>=>>=>==>=>>=>=>= =>=>>=>=>>=>=>=>==>==>=>>?>?>?>>?>?>??>?>?>?>>?>>?>>?>>?>>?>?>>?>??>?>??>?>??>?>?>??>??>?@?@?@@?@?@@??@??@?@??@?@?@??@ ?@?@??@?@?@@?@?@@?@@?@@A@A@@A@@AA@A@@A@A@A@A@@A@A@@A@@A@@A@@A@AA@AA@AA@AA@A@AA@AA@A@@AA@AABABBAABABBABABBABABBAABABBA ABA ABAABBCBBABBABBABABBABBABBABBABABBABBCBCCBCBBCBCBCCBCBBCCBCCBCBBCBBCB BCBCCBCCBCCBC CBCCBCCBCCBCCBDCDCDCDCDCDCDCCDDCCDCDCCDCCDCDC C DCD DCDCDCDDCDDCDDCDDCDDCDDCDDEDEDDEDEDEEDEDEDEDDEDDEDEDED DEDE EDEDDEEDEDEEDEEDEDDEDEEDFEFEFFEFFEFEFEFEEFEEFEEFEEFEEFEEGF FEFFEFFEFEFFEFEEFEEFEFFEGGFGFFGFGFGGFGFGFGFGFFGFFGFFGFF GFGFGF FGFGFGGHHGHHGHGHGHGHHGGHGHHGGHHGHGHGGHGGHGGHGGHGGHGGHGHHGHHGHHGHGHHGHHGGHHGHIIHIHIIHIIHHIIHIIHHIHHIHIHIHHIHIHHIHHIHI IHIIHIIHIIHIHIHIIHIIJIJIJIIJIIJIIJIJIJIJIIJIIJIIJIIJIIJIJIJ JIJ JIJIJIJJIJJIJIJIJIJIJJIJKKJKJKJKJJKJKJKJJKJJKJK JKJJKJKKJKKJKJKKJKJJKJKKJKKJKKJLKKLLKLKLKLKKLLKKLKKLLKKLKKLKKLMLLKLKLLKLLKLLKLLKLKLKLKMMLMLMLMLLMMLLMLMLLMLMLLMLML LMLMLMMLMMLMLLMMLLMLMMLMLLMLLMMLLMMNMNMMNMNMMNMNMNMMNMMNNMMNMNMM NMN NMNNMNMNMNNMNNMNNMNNMNMNNONONNONOONOONNONONNONNONNONNONONOONONOONOONOONOONNPOPOPOPOOPOPOOPPOOPOOPOOPPOOPOPO OPQPPOPPOPPOPOPPOPPOPPOPPOPPOPPOPPQPQPQPPQPQPPQPPQQPPQPQPQPPQPPQPQ QPQQPQQPQQPQPQQPRRQQRRQRQQRQRRQRRQQRQQR QRQR QRSRRQRQRRQR RQRRQRQRRQRQRRQRSRSRSSRRSRSRSRSRRSSRRSRRSRSSRSSRSSRSSRSRRSRSSRSRSRRSRSSRSTTSTSTSTSSTSSTTSTSTTSTTSTSSTTSTSSTSTSSTSTSTTSTTSTSTSTTSTSTTSSTTUTUTUTUTUUTUTUTTUTTUTTUT TUTUUTUUTUUTUUTUUTUVUVUVVUVUUVUUVVUVUUVUVUUVUUVUVUU VUVVUVVUVUVVUVVUVUUVUVVUVUUVUUVUVUVVUUVVWVWVWWVVWVWVWVWVVWVWVVWVWVWVVWVVWVVXWXWWVWWVWVWWVWVWWXWXWXWWXWWXWXWXXWWXWWXWXWXW W XWXXWXXWXXWXXWXXWXWXWXXWXWXXWXXYXXYXXYYXXYYXXYXYYXXYXXYXXYXYXXYXYXXYX X 989899899898:9::9::99:9::9:99:9:99:9:99:99:;: :9:9::9::9:9:9::99::9:9::9:9::;:;:;;:;;:;::;:;;:;:;::;::;::;::;: ;:;;:;;:;:;:;;:;;<<;;<;<<;<;<;<;<;;<;;<;<;;<;;<;;<;<;=<<;<<;;<<;<<;; <;<;<;;< <=<<=<<=<<==<=<=<=<<=<=<==<==<=<<=<=<<=>= =<==<==<==<==<==<=<==<==<=<==>=>=>>=>=>=>=>=>=>=>==>==>= =>==>=> >=>>=>==>=>=>==>=>=>=>>??>?>?>?>>?>?>>??>?>?>?>?>>?>>?>>?>>?>>?>??>? ?>?>?>?>?>??>>?>@@?@??@??@@?@??@?@??@?@?@??@?@??@??@A@ @?@@?@@?@@?@@?@?@@?@@?@@?@@A@A@A@AA@A@AA@@A@@AA@A@@A@@A@@A@@A@A@@A@AA@AA@A@@AA@AA@AA@AA@A@BBABABBABABAABABAABABAABAABAABAABABBABBABABABAABBABAABBABABBAABAABBABCBBCBCCBBCBCBCCBCCBCBCBBCBCBBCBCBBCBCBCCBCBCCBCBBCBBDCDCCDCDDCDCCDCDCCDCCDCDCCDCCDCDCCEDDCDDCDCCDDCDDCDDCDCDDCEDEDDEDEDDEDEEDDEDEDDEDEDDEDDEDDEDEDDEEDEEDEDEEDEDEDEEDEDEEDDEEDEFEEFEFEFEFEFEEFEEFEEFFEEFEEFEEFEEFE E!FEFFEFFEFEFFEFGFGGFGFFGFFGFGGFGGFGFFGFGGFGFGFFGFFGFFGFFGFGFFGGFGFGFGGFFG GFGFFGFGFFGGHGHGGHGGHHGGHHGHGHGHGGHGGHGGHGHGGHGGHGH HGHHGHHGHHGHHGHGHGHHGGHGHHGHHGHGHIHHIHIIHHIHHIIHIHIHHIHHIHIHHIHIH HIHHIJIIHIHHIIHIHHIHHIHIHIHHI JIJIJIJIJIIJIIJIJJIIJIJI IJIJJIJJIJIJJIIJJIJIJIIJIIKJKKJKJKJJKJKJKJJKJKKJKJJKJKJJKJJKJJKJJKJKJKKJKKJKKJKKJKKJKJKJKKJKKJKKJJKLKKLKLKLLKLLKLLKLKKLKKLLK KLKKLKKLKK LKL LKLKLLKLLKLKKLKLKKLKLKLKKMMLLMLMMLMLLMLMLLMLMLLMLLMLLMLLMLMMLMMLMMLMMLMLMMLMLMLMMLMLMMNMNMMNMNNMNMNNMMNNMMNMMNMNMMNMMNMNNMNNMNMNNMNMNMNNMNMNMNMNNMNNONONONNONNONONONNONOONNONONNONNONNONOONONOONOONONNOONONNOONOONNONONPOPOOPOPOPOPOPOPPOOPPOPOOPOOPOOPOOPO O POPPOPPOPPOPPOPPOPPOPOPOPPOPPOPOPOPPQPQPQQPPQPQPQQPPQPPQPQQPQPPQPQQPQQPQPQPPQPQPQQPQPQPPQPQQPQQRQQRQQRQRQQRRQRQQRQQRQRQQRQQRQQRQQRQRQQ&RQRRQRRQQRRQRRQRSRSRSSRSRSSRSRSRRSRRSRRSRRSRS SRSSRSSRSSRSSRSSRSSRSTSSTSSTTSTSTSTSTTSTTSTSTSSTSSTSSTSSTSTTSTTST TSTSSTSTTSTSTTSSTSTUUTUTTUTUUTTUTTUTTUTTUUTTUTTUTUTT UTUUTUUTUTUTUUTTUTUUTUTUVUVVUVVUVUUVUUVUVUUVUUVUVUVVUVVUVUUVU UVUVVUUVVUVVUVVUVVUVUVVWVWVWVWWVVWVWWVWVWV VWVWVVWVVWVW WVWWVWWVWWVWVVWXWXWXWWXWXWXWWXW WXWWXWXWWXXWXWWYX XWXXWXXWXXWXWXWXXWXXWXWXWXXYXYXYYXYYXYYXYYXXYYXYXYXXYXXYXXYXXYXXYX89898899899898988988989889889:998989989989898899899898898998898989898:99:99::9:9:99:99: 9:9 9:9:9::9::9:9::9:99::;:;::;:;::;::;:;:;;:;;:;::;:;;:;;:;;:;;:;;:;;:;:;;:;;:;::;;<;;<;;<;;<<;<;<;;<<;<;<;;<;;<;;<;;<;< <;< <;<;<<;<;;<<;<;;<<;<;<<;<<;<==<=<=<=<=<=<=<<=<<=<=<<=<<=<<=<<=<==<==<=<=<==<=<==<=<==<==>>=>>=>==>=>>=>==>==>=>>=>=>=>=>==>==>==>=>=>==>=>>=>>=>=>==>>=>=??>?>>?>?>>??>?>>?>>?>>?>>?>>?>??@??>?>??>??>??>?>>??>?>??@@?@?@@?@?@??@?@?@?@??@?@?@??@?@??@? ?"@? @?@?@?@?@@A@AA@@A@@A@@A@AA@AA@A@@A@A@@A@@A@@A@A@ @ A@AA@AA@AA@AA@AA@A@@AA@ABABBABABBABBABBAABABBAABABAABAABA ABABBABBAABBABABBABBABBABABABCBBCBBCBCCBCBCCBCBCBCBBCBBCCBBCCBBCBBCBCB BCBCCBCCBBCBCBCCBCCBCCBCBCCBBCBCCDCCDDCDCCDCDDCDCDCCDCCDCDCCD CDCD DCDDCDCCDCDDCDDCDCDDCDCDDEDDEDDEEDDEDDEDDEDDEDDEDEDEDDEDDFE EDEEDEEDEEDEEDEEDEEDEEDDEDEEDEEFEFEEFFEFEEFFEEFEFEEFEFFEFEEFEEFEEFEFEEFEFEFEF FEFEEFEFEFFEFFEGFGFGFFGFGGFGFFGFFGFGFGFFGFFGFFGF F GFGGFGGFGFG GFGGFFGFGFGGFGHGHHGHGHHGHGGHGGHGHHGGHGHGGHGHGGHG GHGHHGHHGHHGHHGHHGHHGGHIHIIHIIHHIHHIHIIHHIIHHIHHIHHIHIHIHHIHIIHIIHIIHIHIIHIHIHIHHJIJIIJIIJJIIJIIJJIJIIJIJIJIIJIJIJIIJIIJIJIJJIJJIJJI JIJJIJJIJJKJJKJJKJJKJKKJKJJKJKJKJJKJKJJKJJKJKJKJKKJKKJKKJKJJKJKJKJKJKJKKLKLLKLKKLKLKKLKLKKLKKLKLLKKLLKKLKKLKLK KLKLLKL LK LKLKLLKLLMMLMMLMLLMLMMLMLMMLLMLMLLMLLMLMLLMNMMLM MLMMLMMLMLMMLMMLMMLMNMNMMNMNNMNMNMMNNMMNMMNNMNMMNMMNMMNMMNMNMNMMNM MNMNNMNMNNMNNMNNMNMOONONONOONONNONNONONONNONONNONNONONN ONO ONOONOONOONONNOONNOONOONOPPOOPOOPOOPOPOOPOOPOOPOOPOOPOOPOOPOOPOOPOOPOPPOP POPPOPPOPOOPOOPPOPPOPPOOPQPQPPQPQQPPQQPPQPQPPQPPQPPQQPQPP$QPQQPQQPQQPQQPQPQQPRQRRQRRQRQQRQQRQQRQRQRQQRQRQR QRQRRQR RQRRQRRQRQRQRRQQRSRSSRSRSRSRRSRRSRRSSRSSRSRSRSRRSSTSSRSSRS SRSSRSRSSRSSRSSTSSTSTSTSTSSTSTSTSSTSSTSST STSTSSUTTUT TSTTSTTSTTSTTSTTSSTSSTTSTTSTTUTUUTUTTUUTUTTUTTU TUTUTUTTUTTUTUUTUUTUUTUUTUUTUUTUUTUUTUUTUTUUTUUTUUVUVUVUVVUUVVUUVUUVUVUUVVU UVUUVUVUVVUVUVVUVVUVUUVUUVWWVWVWVWWVVWVWVVWVWVVWVVWVVWV WVWVWVWVVWXWXXWXWXXWWXWXWWXWXWWXWWXWXWWXWWXWXXWXXWXXWXXWXXWXXWXXWXWWXW9899898898998898988989889898 89889889898998998989899899::9:99::99::9:99::99:99:99:9:99:99:9:9::9:9: :9:9::9::9:9::;::;:;::;;::;:;::;:;:;:;::;::;;:;::;::;:;:;;:;;:;:;:;;::;;:;<;<<;<<;<;<;<;;<;;<;;<;<;<<;;<;;<; ;=<=<<;< <;<<;<;<<;<;<;<=<=<==<==<=<<=<<==<==<=<<=<=<=<<=<=<<=<<>=<= =<=<=<<==<==<==<==<=>==>==>>=>>==>>=>=>>==>>=>>==>= =>==>==>=>?> >=>>=> >=>>=>=>>=>>=>>=??>?>>?>??>??>??>?>?>>?>>?>>?>>?>>?>>??>>?>??>?>??>??>>??>??>?>?@??@?@@?@??@??@??@?@?@??@??@??@??@??@?@?@?@?@@?@?@@??@??@@??@A@A@AA@AA@A@@A@AA@AA@A@@A@AA@A@A@AA@AA@AA@@AA@A@AA@A@BBABAABABBABABBABAABAABABABABAAB ACBBABBABBABBABBABBAABABBAABABBACBCBBCCBCCBCBBCBBCBCBCBBCB BCB BCDCDCCBCBCCBCCBCCBCBBCBBCBCDDCDDCDCDCDCCDC CDCCDCCDDCCDC CDCDDCDDCDDCDCDCEDDEDEEDDEDDEDDEDEEDDEDEEDEDDEDEDDEFEEDEEDEEDEEDEEDEEDEEDDEDDEDEEDEDEEDEFFEFEFEEFEFEEFEFEEFEFFEEFEEF EFEEFEEGFFEFFEFFEFFEFFEFFEFEFFGGFGFGFGGFGFGGFGGF FGFFGFGFFGFGFGGFGGFGFFGGFGFFGGFGGFGFGFGGFFGFHGHHGHHGHGHGGHGGHGHGGHGHHGGHGHHGGHG GHGHHGHHGH HGHGHGGHHGHGHIIHIIHHIIHIHHIHIHHIHHI HIHIH HIHHIIHI IHIIHIHIIHIHIIHIIHIHHIHJJIJIIJIIJIJJIJIJJIJIIJIIJIIJIIJIIJIJIJIIJIJIIJIIJJKJ JIJJIJJIJIJJIJIJIIJIJJIJIKKJJKJJKJJKKJKJKJKK JKJJKJ JKJKKJKKJKKJJKKJKJKKJKJKKLKLLKKLKLLKKLKKLKLKLKKLKLKKLKKLKLKKLKKLKLLKLLKLLKLKLKLLKLLKLLKLKKLKLMLMLLMMLMMLMLLMLLMLLMLMLMLLMLMMLMMLMMLMLMLMLMLMMLMNMNNMNNMNMNMNNMMNMN MNMNNMM NMNNMNNMN NMNNMNNMNNMNMMNNMNNMMNMMNMNOONOONONOONNONONNONNONONNONNONONOONOONOONONNONOONOONNOOPOPOPPOOPOPPOPOOPOPPOPOOP O POPPOPPOPPOPPOPOPPOPPOPOPPOPOOQPQQPQQPQPPQPQPQPQQPQPQPPQPQPPQPQPQPPQPPQPPQPQPQQPQQPQPQQPQPQQPQQPQQPQPPQRQQRQRRQQRQRQQRQQRQRQQRQQRQ QRQRQRRQ RQRRQRSSRSSRRSRRSRSSRRSRRSRSRRSRRSRSRRSSR RSRRSRSRSSRRSSRSR SRSRSRRTSTSSTSTSSTSTSSTSSTSTTSTSTSTSSTSSTSSTSSTSS TSTSTTSTTSTTSTTSTSTTSTSSTSTTSTUTTUTUUTTUTTUTTUTTUTTUTTUTTUTTUTTUTTUTUTUUTUUTUUTUTUTUUVUVUVUUVUUVUVUUVUVUUVUUVUUVUUVUUVVUVVUVVUVVUVVUVVUUVUVVUVVUUWVWWVWVWVVWVWVVWVVWVWWVWVVWVVWVVWVWVVWVVWVWWVWWVWWVW WVWVVWVWVWWXWXXWXWXWWXXWWXWWXWWXWXX WXWXYXXWXWX XWXXWXW9899889889989989989989889899898 8988%989898988989989::9:9:9::9:9:9:99:9:9 9:9:99:9:9 9:9:99::9:9::9:9::9::9::9::9::;:;::;:;;::;::;::;:;:;:;::;::;::;::;::!;:;:;;:;;:;;:;:;:;;:;;<<;<<;<<;;<;;<;<;<;<;;<<;<;<<;<<;<<;<; ;<;;<;< <;<;<;<;<<;<<;<;<==<=<<=<=<<=<<=<<=<=<=<=<<=<<=<<=<=< <=<==<==< =<==<==<=<==>=>=>=>>==>==>=>=>=>>=>>==>=>==>=>==>== >=>>=>>=>==>>=>=>>==>>==>=>>=>=>=??>?>??>?>?>>?>>?>?>>?>>?@??>??>??>?>?>>??>??>>??>>?>?>?>>?@?@??@?@?@?@@??@@?@??@?@??@?@@?@?@@??@?@@?@??@??@AA@A@A@@A@A@@A@@A@@A@@A@@A@ @A@AA@AA@AA@A@A@A@AA@@AA@@A@AABABBABAABABAABABBABAABAAB ABAABAA BABBABBABBABBAABABBABBABBAABCBBCBCBBCBCCBBCCBCBBCB BC BCBBCBCCBCBCCBCCB CBCBBCCBCDCCDDCDCDCCDCCDCDCDCCDCDCCDCCDCCDDCCDCDCCDCC"DCDDCDCD DCDDCDDEDDEDEDDEEDEDEDDEDEDDEEDDEDDEDDEDDEDE EDEEDEEDEDEDEEDEEDEDEDEDEDEEDEDEDFEFEEFFEFFEEFEFEFEFEEFEEFEFEEFEEFEF FEFFEFFEFEFFEFEFEEFFGFGGFGFGFFGFFGFFGFFGFGFGFFGFFGFGFGGFGFG GFGFFGGFFGGHHGGHGHGGHGHHGGHGGHGHGHHGHG GHGHHGH HGHHGHGHHGHGHHGGHHGHGGHHIIHHIHHIHIHHIHIHHIHHIHIHHIHHIHIIHIIHIIHIHIHHIIHIHHIHIHIIJIJIJJIJIIJJIIJIJJIJIIJIIJIJIJIIJI IJIJJIJIIJJIJJIJIJIIJIIJJKJKJJKJJKJJKJJKJKJKKJJKJKJKJJKJKJJ KJKKJKKJKJKJKJKKJKJLKKLLKKLKKLKKLKLLKKLKLKLKKLKKLKLML LKLKLLKLLKLLKLLKL LKLKKLKLMLLMLMLMLMMLLMLLMLMMLLMLMLLMMLLMLMLMLLMLLML MLMLM MLMMLMMLMMLMLMLLNMMNMNMNMNMNNMMNMNMMNMNMMNMNMMNMNNMN M NMNMNMNNMNMNNMNMNNMNMNNMMNNMMNNONNONOONNONOONOONONOONNONNONNONNONNONNONOONOONOONONOONONNONNOONNONNONOONPPOPOPOPPOPOOPOOPOPOOPOOPOOPOOPOOPOPPOPOPPOPPOPOPPOPOOPOPOPPOQPQPQPPQPQPQP PQPQPQPPQPPQPPQP PQPQPPQPQQPQQPQQPQPQPQQPQPQPRRQRQRQRQRRQRRQRRQQRQRQQRQRQQRQQRQRQRQ QRQRQRRQQR RQRQRRQRRQRRQRRQRSRRSRSSRSSRRSRSSRSRSRSRRSSRSR RSRSRSSRSSRSSRSSRSSRSSRSRSRTTSTTSSTSTTSTSTSSTTSTSSTSSTSTSTS S TSTSTTSTSTTSTSTTSUUTUUTTUTUTTUTTUTTUTTUUTUTTUT TUTUUTUTTUUTUUTUTUTUTTUUTVVUVUUVUUVUVVUUVUVUUVUUVU UVUUVUVUUWVVUVVUVVUVVUVVUVVUVVUVUVVUVVUVUVUVVWVWWVWWVWWVVWWVWVVWVWVWVVWV VWVWVWVWWVWVWWVWVVWVVXWXWXXWXWXWXWWXWXWWXWWXWXWWXWWXWXXWXXWXXWXXWXWXXWXXWXXWXXWXWXWXWWX 878878878788788787887878788787787989889898998898899899898898989898898998898989989989989898989989989989:9::9:99::99:9::9:99:9:9::99:99%:9:99:9:99:9:;:;:;;:;::;;:;::;:;:;:;::; :;::;:;;:;::;:;::;:;:;;:;:;;::;:;;:;::;;<;;<;;<;<<;<;<<;;<;;<;<;;<;<;;<;;<=<<;<<;<;<<;<<;<<;<;<<;<;<<;<<;;<<;<<;;=<<==<==<=<<=<<=<<==<==<<=<<=<<=<<=<==<==<==<==<==<=>>==>=>>=>==>=>==>==>==>=>==>==>=>>=>>=>=>>==>>?>?>?>>??>??>>?>??>>?>?>?>>??>?>>? >?>?>>??>??>?>>?>?>>@?@??@?@@?@?@@?@??@?@?@??@?@??@?@@?@?@?@??@??@ @?@@?@@?@@?@??@?@@?@@?@@??@@?A@AA@AA@A@@A@@AA@AA@@AA@A@@A@@A@A@@A@@A@AA@AA@AA@AA@A@A@AA@A@A@ABABBABABAABAABAABABA ABAABCB BABBABBABABBABABBABABBABABBABACCBBCBCBBCCBBCBCCBBCBCCBCBBCBCBCBBCBBCBB CBCCBCBBCCBBCCBCBCCBCCBCDCCDDCDCDDCCDCDCDCDCCDDCDCDCCDCCDCDCCDCCDCCDDCDCDDCDDCDDCDDCDCDDCDCDDEDEDEDDEDEDDEDEEDEDDEDDEDDEDEDEDEEDEDEEDEDEDEEDEEDEEDEFFEFFEEFEFEEFEFEFEEFEFEFEEFEEFEEFEFFEFFEFFEFFEFEFFEEFFEFEFEFFEFFEFFGFGGFFGFGFFGFFGFGFGFFGFGGFGFGFFGFGF GFGGFGGFGFGGFGFGGFGFFGHGHGGHGGHHGHGGHGGHGHHGGHGGHGHGHHGHHGHHGHGHHGGHGHGHHGHGGIHIIHIIHHIHHIHHIHIIHIHIIHIHHIIHHIHIHHIHHIJIIHIIHIIHIHIIHHIHIHIJIIJIJIJIJJIJIJJIJIIJIJIJIIJIIJIIJIJI IJKJIJJI JIJJIIJIJIIJJIJJIIJIJJIJIJKJJKKJKJKKJJKJKKJKJJKJJKJKKJJKJKJJKJKJJKJJ(KJKJKKJKKJKJKKJJKKJKKLKKLKLLKLKLLKKLKLKLLKKLKKLK KLKLKKLKL LKLKLKKLKKLLKLLMMLMMLLMMLMLLMMLMLMLMLLMLLMLLML MLMMLMMLMMLMMLMMLMMLMMLLMLLMMNMMNNMNNMNMMNMMNMNMMNMMNM MNMMNMM NMNNMNNMNMNNMNMNNMNNMNMNMNNONONNONONONNONNONONOONONON NONO ONOONOONO ONOONOONOONONNOONOONOONPOOPOPOPOPPOPOOPOPOPOPOOPOOPOPPOPOPOOPOPPOPOPOPOOPPOPPQQPQPQQPPQPPQPQPPQQPPQPQPPQPPQPPQPPQ PQPQPQPQPQPQQPQQPQPQPQPPQRQQRQRRQRQQRQQRQQRQRQQRQRQQRQRRQRRQRQQRRQRRQRRQRQQRQRRQRRSRSSRSSRRSRRSRRSSRRSRSRRSRRSRSRSRSR RSRSSRSRSRSSRSSRSSRTSTSSTSTSSTTSTTSSTSTTSSTSSTS STSTSSTSTSTTSTSTTSTTS TSTSTSTTUTTUTUUTUTTUTUTTUTUTTUTTUTTUTUTUUTUUTUUTUTUUTUTUTUUTTUUTUVVUUVUVVUVUVVUUVUVUVUUVUUVUVUUVUUVUVVUV VUVUVVUVUUVUVVUVUWVWVVWWVWVWWVWWVWWVWVVWVVWVVWVVWVWV!WVWWVWWVWVWVVWWVWVWWVXXWXWWXWXWWXWWXWXWXWWXWWXWXXWWXWXW WXWWXWW87887787887878787878788787878788787998898989889898998898998898898988988988$9898989899899:9:9::9:99:9:9:9:99:99:9:99:9::99:99:9 9:9::9:9 :9::9:9:9::9;:;:;;:;::;::;:;::;::;::;:;;: ;:;:;:;;:;;::;;:<;<<;<;<<;;<<;<;<<;<<;;<;<;;<;<=<<;<<;<;<;<<;<<;;<;;<;<==<<=<==<=<=<=<<==<=<=<<=<==<=<<=<=<=<==<==<=<=<==<==<==<==>=>=>==>=>==>=>==>==>==>==>=>>=>=>>=>=>>=>=>?>>?>>?>?>?>>??>?>??>>?>>?>?>>?>?>?>>?>>?>??>??>>??>??>??>??>?>??>?>>?>>@?@?@@??@?@?@?@??@@?@?@@??@??@??@?@??@?@@?@@?@@?@@?@@?@?@@?@@?@@?@??@A@AA@A@AA@A@AA@A@A@A@@A@A@@A@A@@A@A A@A A@AA@AA@@AA@A@@AA@@AA@AA@A@AA@@ABBABAABAABBAABAABABAABABAABAABAA BABBABBABABBABBABABBABABBCBCBCBBCCBBCBBCBCBBCBBCBBCBBCBBCBBCB BCBCCBCCBCCBCCBCBCBCBBCDCCDCDCDDCDCDDCCDCDCDCDCCDCDCDDCDCDDCDDCDCDDCDDCCDCDCDCCDEDEEDEDDEDEDDEEDDEDED DEDDED D EDEDEEDEEDEDEEDEEDEEDEEDEEDEDEDEFEEFEFFEFEEFEEFEFEFEEFE EFEEFEFFEE FEFFEFFEFFEEFFEFFEFEFEFFEFEFEEFEEFGFFGFGFGGFFGFGFGFGGFGGFGFFGFGFFGFFGFFGFFGFGGFGGFGFGGFGGFGGFGGFGFFGHGHGGHGGHGHGHHGHGGHHGGHGGHGGHGGHGGHGG HGHHGHGHHGHHGHGHHGHGHHGHGHHGHHIHIHHIIHIHIIHHIHHIHIHHIHHIHIHIHIHIHHIHIIHJJIJJIJIJIJIIJIJIIJIJIJIIJIIJIJII JI JIJIJJIIJIJJIJJIJIJJIIJIJIJIIJKJKKJKKJKKJJKJKJJKJKJJKJ JKJKJJKJJKJKJJKJKJKKJKKJKKJKKJKLKLKKLLKLKLKKLLKLKKLKKLKKLKLKKLK KLKLKLLKLLKLLKLKLKLLKLLKMMLMMLLMLLMMLMLLMLMLLMLMLLMLLMLLMLL+MLMLMMLLMMLMMLMMNMNMNMNNMNMMNMNMNMMNMMNMNMNMMNMNM MNMNMNMNNMMNNMNMNMNNMNNMNNMNNONONONNOONONNONNONOONNONNONNONNONOONOONOONOONOONOONPPOPOOPOPOOPOPOOPOPOPPOOPOOPOPOPPOPO O POP POPOPOPPOPOPPOPPOOPOPQPQPQPQPPQPPQQPPQPQQPPQPPQPPQPPQPPQPQQPQPQPPQQPQPPQPPQPQQRQQRQRQQRRQQRRQRQRRQ QRQQRQ QRQRQQRQRRQRQRRQRRQRQQRRQQRRQRRQRRQRSRRSSRRSRRSSRSRSRSSRSRRSRRSRSRRSR RSRR SRS SRSRSRSRSSRSSRSSRSSRSSRSRSSRSTTSTSTTSSTSTSSTSTSSTSTSTSSTSTSSTSTSSTSSTS TSTTSTTSTSSTSTTSTSTSSTUTUTUUTUUTTUUTUTTUUTTUTUTTUTTUTTUT TUTUTUTUUTUUTUTUUTTUUTUUTVUVUVUUVVUVUUVUUVUVVUVUUVUUWVVUVVUVVUVVUVUVUUVUVVWVWVWWVWVWVVWVWWVWWVWVVWVWVWVVWVWVVWVVWVVWVWWVWWVW WVWVWVVWVVWVVWXWXXWXWXWXW WXWWXWW9887878 878879 89898998898988989889889898898 8 98998989989899898989:99:99:9:9:9::9::9::99:9:99:99:9::9::9:9::9::99:9:9::;:;:;;:;:;:;::;:;::;:;: :;:;:;;:;;:;;:;;:;;:;:;;:;;::;<;<;;<<;;<<;;<;<<;;<;<;<;;<;;<;;<=< <;<;<<;<;<<;<<;<<;;<;;<<=<=<=<==<==<=<==<=<<=< <=< <=<<=<= =<= =<==<=<=<=<==<=<=>=>==>=>=>==>=>==>==>=>>==>==>=>==>==>==>==?>>=>>=>=>=>>=>>=>=>>=>>?>?>>?>?>??>??>>?>?>>?>>?>?>>?>>?>? ?>?>??>??>??>??>>?>?>??@??@?@@?@@? ?@?@?@@?@??@? ?@??@??@A@@?@ @?@@?@@??@@?@@?@@?@@?@@?@@?@@?@@A@@A@AA@@AA@@A@A@@A@@A@@A@@AA@A@@A@@A@A@AA@A@AA@AA@AA@AABABABABABAABBAABAABAABABAABA ABAABABBAB BABBAB BABBABBABABBCBCCBCCBCBCBCBCCBBCBCCBBCBBCBBCBCBCCBCCBCBCCBBCBCCBCCBCBBCDCDCDCDCCDCDCDCDCCDCCDCCDCCDCCEDDCD DCDDCDCDCDCCDCCDCCDEEDDEDEEDEDEDDEDEEDDEDDEDEDDEDDEDEEDDEDDEDDEEDD EDEEDEEDEEDEEDEDEEDEDEEDEDEEDEEDEEDEEFEFEFEFEEFEFEEFEFEEFEEFEEFEEFEFE EGFFEFFEFFEFFEFEEFEFFEFFEFEGGFGFFGFFGFGGFGFGFFGFGFFGFFGFFGFGFFGFGGFG GFGFGFFGFFGFGGFGFGFGGHGHGGHGGHGHGGHGHGGHGHGHGGHGGHGGHG G HGHHGHHGHHGHHGHGHGGHHGGHGGHHIHIHIHIIHHIHHIHHIIHHIHHIHHIJIJIIHIIHIIH IHIHHIIHIIHIIJJIJIIJJIJIIJIJIJIIJIJI IJIIJIIJIJIJJIIJJIJJIJJIJIJIJJIJIJJIJIIJJIKKJKJJKJJKJKJJKJJKJKJJKJKKJKJ JKJJKJJ KJK KJKJKKJKJKKJKKJKKJJKLKLLKLLKLLKLKLKLKKLKKLKLLKLKLKLLKLKLLKLKLKKLKLKMLMLMLMML LMLMLLMLLMLLMLLMLLMLLMLMLMLMMLMMLMMLMMLMMLMMLMMLNMNNMNNMMNMMNMMNMNMNMMNMMNMMNMMNMMNMMNMMNNMNNMNMMNNMNNMNMNNMNMNMMNNMNOONONNONOONNONONNONOONONOONONOONOONOONOONOONOONONOONNOONNONNOONPPOPOOPPOPOPOPOPP OPOOPOOPOPPOPOPOOPOPOPPOOPOPPQQPQPPQPPQQPQPQQ PQPQPQQPQPPQPPQPPQPPQPQPQQPQQPQQPQPPQQPQQPQQPQQPQQPPRRQRQRQRQQRQQRQQRQQRQQR QRQRQQRQRRQRRQRRQRRQRQRQRRQRRQRSSRSRSRSRRSRSRSSRRSRSRSRRSRRSRSSRSSRSSRSSRSSRSSRSRSRSRSRSSRRSRRSRSRRSTSTSTSTSTSTTS STSSTSTSTSSTS STSSTSTTSTSTSTTSTTSTTSTSSTSTTSSUUTUTTUUTUTUTTUTTUUTUTTUTTUTTUTTUTTUVUTUUTUTUUTUUTUUTUUTUTUTTUVUVUVUUVUUVUUVUUVUVUVUUVUVUUVUUVUUVUUVUVVUVVUVVUV VUVUUVVUWWVVWWVWVVWVVWVWVWVVWVVWVWVVWVVWVVWVWWVWVWWVWWVWWVWVWWVWVVWWVWXWXWWXWWXWWXXWXWWXWWXWXWWXWXW WXWXWW8778878878787787878788787 787787 78778988788787887878778788989899898 898898898 8 98998998998998989899898899898998:99:9:9::9:9:99:99:99:9:9:99:99:99:9:99::99:9::9::9::9:99:9::9::9::9:9::9:;:;;:;:;;:;::;:;::;:;;::;:;;:;::;::;: :;:;:;;:;:;;:;;::;::;;:;;::;::;:;;:<<;<<;;<;<<;;<;;<;<;<<;;<;;<;;< ;<;; <;<<;< <;<<;<;<;<<;<<;;<<;<==<=<<==<==<=<=<<=<=<=<<=<<=<=<<=<<=<=<<=<==<==<= =<==<==<==<=<=<>>=>==>>=>=>==>= =>==>==>==>==>=>==>>=>=> >=>>=>>=>>==>=>>=>>=>??>??>>?>?>>?>?>?>?>>?>>?>>?>>?>??>??>??>??>>?>??>??>??>?>??@?@?@@?@?@@?@@?@@??@?@?@??@?@@?@?@??@?@?@ @?@?@??@@?@?@?@@A@@AA@@A@@A@A@A@A@@A@@A@A@@AA @A@@AABA A@A A@AA@AA@AA@A@@A@AA@AA@A@@BBABAABBABABABAABAABAABAABBAABABAABABBABBABBABABAABBABBABBCBCBCCBBCBCBCCBCBCBCBCBCBCB BCB BCBCCBCBCCBCCBCCBCBCBCCBCBBCCBCCBCBBDDCDCCDDCDCDCDCCDCCDDCCDCCDCCDDCDDCDDCDCDCDCDDCDCDDEDEDEDDEDEEDDEEDEEDEDDEEDEDEDEDDEDDEDDEDEEDEDDEEDEEDEDEEDEFFEEFEFEEFEFEEFEFFEFEEFEEFEFEEFEFEEFEEFEEFEFEFFEFFEFEFEEFFEFFEFFEFEFEFFGFGFFGFFGGFFGGFGFFGFGGFGGFG FGFFHG#GFGGFGFFGGFGGFGFGHHGHHGHGGHGGHGHHGGHGGHG GHGHHGGHGHHGHHGHHGHHGHHGHGGHHGHGHGHHGGHHGHHGGHGHIHHIHIHIIHIHIHIHIHHIHHIHIHIHHIHHIHHIHIIHIIHIIHIHIIHIIHIHIHIIHIHIHIIHIIHIIJIJIIJIJIJIIJIIJIJIJIIJIJIIJIIJIJ IJIJIJJIIJJIJJIJIIJIJIIJKJJKJKKJKJJKJJKKJJKKJJKKJKJJKJKJJKJKJJKJJKJJKJJKJKKJKKJKJKKJKKJKKJKKJKKLKKLKLKLLKLLKKLKLKKLLKLLKKLKLKKLKKLKLKLLKL LKLKLLKLKLLKLLKLKKLMLMLMMLMLLMLMLLMLMLLMLMLLML LML(MLMLMLMMLMMLMLMNMMNNMNNMNMNMMNMNMNM MNM M NMN NM NMNNMNNMNNMMNMNMNMNNMMOONONONONOONONOONONNONNONNONNONONONNO ONO ONOONOONONOONOONONOONONOPOOPOPOPOOPPOPOOPOPOOPOOPOOPOPOOPOOPOPPOPPOPOPOPOPPOPPOPOPOPPQPQQPQPPQQPQPPQPQQPQQPPQP PQPPQPQQPQQPQQPPQQPPQQPQPQQPQQRQRQRQRQQRQRRQRRQRRQR RQRRQQRRQRRSSRRSRSSRRSRRSRSRSRRSRRSRRSSRRSRSRRSRRS SRSSRSSRSSRRSRSRSRRSSRSSRRSRRSRSSTSTSTSTTSTSSTTSTSTTSSTSTSTSSTSTSSTSSTSSTS TSTSTTSTTSTTSTTSTSSTSSTSSTTUTTUUTUTUUTUUTUUTUTUTTUTUTUUTTUT TUTTUTUTUUTUUTUUTUTTUTUUTUTUUTUTTUUTVUVUVUUVVUUVVUVUVVUUVUUVU UV UVUVVUVVUVUVUVUVVUUVUVWVVWWVVWVWVWVWWVVWVWVVWVWVVWVWVWVVWV VWV VWVWWVWVWWVWVWWVWVVWWV78787887877877887887877877877!87887878 87898989989889899898898998988989898 8989 989989989989988 989:99::99:: 9:99:99::9:99:99:99 :9::9:9:9::9:9::9:9::9::;:;:;:;::;:;:;::;:;::;:;::;::;::;: : ;:; ;:;:;;:;;::;::;::;;:;::;;:;:;;<;<<;<;;<<;<;<;<;;<;<; ;<;;<;<<;<;<;;<;<<;<;<<;<;;<;<<;<=<=<<=<<=<=<=<<=<<==<<=<<=<==< <=< =<=<==<==<=<=>=>=>= =>=>>==>=>==>>=>==>==>== >=> >=>>=>>=>=>>=>>=>>=>>=>>?>?>??>?>?>>?>?>>?>?>?>?>>?>>?>?? >?>?>??>?>??>??>??>>?>?>>?>>?@?@?@?@?@?@@??@?@@?@??@?@??@??@@??@? @?@@?@@?@@?@@?@??@?@@?@?@@??@AA@A@@A@A@@A@@A@@A@@A@@A@ @A@ @ABA A@AA@AA@AA@A@AA@@A@A@AA@A@AA@ABABAABABBAABABA AB ABAABAA BAB BABBABBABBABBAB BCBCBBCCBCBBCCBCBCBBCBBCBBCBBCBBCBCCBCCBCCBCBCCBCCBCBCBCCBCCBCBCBCDDCCDDCDDCDDCCDCCDCDDCDCCDCCDCCDCCDCDCDCDDCDDCDDCDDCCDCEDEEDEDEDDEDEEDEDDED DEDDEDE EDEEDEDEEDEDFFEFFEFEFE EFEEFEEFEEFE EFEE FEF FEFEFFE FEFEFEFEEFEFEEGFFGFGFFGGFFGFGGFGGFGFFGFFGFFGHGGFGFGGFGFGGFGGFGFGGFGFFGGHHGHHGGHGHHGHGHGGHGHGGHGHGHGGHGGHG GHGHHGHHGH HGHGHHGHHGHHIHHIHIHIHIHIIHIHIIHHIHHIHHIH HIHIIHIIHIIHIHIHIIHIIHIIHIHIHIJJIJIJJIIJJIJIJIJIIJIJIIJIIJIIJIJJIJJIJIJJIJJIJIIJ JKJKKJJKJJKJKJJKJKJKKJJKJJKJJKJKKJJKJKJJKJKKJKKJ KJKJKKJKJKKJKJKJLLKLKLLKKLKLKKLKLKLKLKKLLKKLKKLKKLKLLKLKLLKLLKLLKLLKLKLLKLKLKLMMLMLLMLMLLMLMLLMLLMLMLMLLMMLLMLM MLMLMMLMMLMLMLMMLMLMMLMLLMMLLNMNNMMNMNMMNMNMNNMMNMNMMNMMNMNMMNMNNMNMNNMNMNNMNNMNNMNNMMNNMNMNONNONONNOONONONNONNONONNONNONNON N ONO ONOONONOONOONONONOONNONNONPPOPOOPOOPOOPOOPOPOOPPOOPOOPOOPOPOO POPPOPOPPOPOPOOPPOPOPPQPQPQQPPQQPQPQPPQQPQPPQPQPPQPQPPQPQQPQPPQQPQQPQPQPQQPQQRQQRQRRQRQQRQRQQRQRQ QRQRQQRQQRQRQQRQQRRQRRQRQQRRQRRQRQRRQRQQRRSRSRSRSRSSRSRRSRSSRSR RSRRSTS SRSSRSSRSSRSSRS SRSRSRSSRRSSRSSRTTSST STSTSTSSTSSTSSTSSTS STSTTSTTST TSTTSTTSTTSTTSSTSTTSTTSTSTTUTUTUUTTUTUTTUTTUUTUTTUTUTUTUTTUTTUUTTUVU UTUUTUUTUUTUTUUTUUTUUTUTTUTVVUVUVVUVUUVUVUVUUVUVUVUUVUUVUUVUUVUUVUVVUVUVUUVUVUUVVUVUVUVVUVUVWWVWVWWVWWVVWVWVWWVWVWVVWVVWVVWVVWVVWVWWVWWVWWVW WVWWVWWVWWVWVVWVWVWVWV7878787788778778878787787787787787887878878787787998899899889898989988988988989889:998989989989989989898998998989 9:9:9:9:9:99:9:99:9::99:9:9::9:9::9::9::99:99;:;:;:;:;::;:;;:;;::;::;::; :;:;:;;:;;:;:;;:; ;:;:;;:;;:;<<;<;;<;<;;<;;<<;;<;;<;<;;<;;<; ;<=<<;<;<<;<;<;<;<<;<<;<;;<<=<=<=<=<<=<<=<<=<=<=<< =<= =<=<=<=<==<==<<==<==<=<==<<==<==<==<==>>==>>=>=>=>==>>=>==>==>=>==>==>==>==>=> >=>=>>=>=>>=>??>?>?>?>>?>?>>?>>?>?>?>>?>>?>>?>?>?>> ?>??>??>??>?>??>>?@@?@?@@?@??@??@@?@??@?@??@??@?@? ?@?@??@?@@?@@?@@?@@?@?@@?@@??@?@??@A@@AA@@AA@A@AA@A@@AA@A@A@A@A@A@A@@A@@ABAA@AA@A@AA@A@AA@A@AA@AABABAABAABABAABABBABABAABBABAABABAABAABCBBABBABABBABBABBABABABBABABBABCCBCBCCBCCBCBBCBCBCBBCCBCBBCBCBCBB CBC CBCCBCBBCCBCBCCBBCCBCCBCBCBCCDCDCDDCDCDDCCDCCDCDCDCCDCCD CDC CED DCDDCDDCDCCDDCDCDCDCDDCCDEEDEEDEDEDEEDEEDEDDEDEEDDEDDEDEDDFEDEEDEDEDEDDEEDEDEEFEFEFFEFFEFEEFEEF EFEE FEF FEFEFFEFFEFFEFEFFEEFEFEGGFFGGFFGFGGFGGFGGFGFFGFGFGFFGFGFGFG GFGGFGFGGFGGFGFGHGHHGHGHGHHGGHGHGGHHGGHGHHG GHGGHGHHGHHGHGH HGHGGHGHGHGHGGIIHIHIHIIHIHHIHIIHIHHIHHIHHIHHIIHHIHHIHIHIHH IHI IHIHIIHIHIIHIIHHIIHIHIIJIJIJJIJIIJJIJIJIIJIIJIIJIJ JIJIJJIJIJIIJIJJKJKJJKJKKJKKJKKJKKJJKJJKJKJJKJJKJ JLKKJKKJKKJK KJKKJKKJKKJKJKKJKKLKLKLLKLKLKLKKLKKLKKLKKLKKLKKLKKLKLLKLLKLLKLLKLLKLKLMMLLMMLMLLMMLMMLMLMLLMLMLMLMLMMLMLL MLMMLMMLMLMMLMLLMLMLLMLLMLMMNNMNMNMMNMNMNMMNMMNNMMNMMNMMNMMNMM NMNNM NMNMNMMNMNNMNNMNMNMNONNOONONNONONNONNONOONNONNONNONONNONNONNONOONOONONOONNONNOONOPPOPPOOPOPPOOPOOPPOPOOPOPOOPOOPOO POPOPOPPOPPOPPOPPOPOPPQQPQPPQPPQPPQPQQPPQPQPPQPPQPPQPQQPQQPQQPQPQQPPQQPQPQQPPQQPQPQRQRRQRRQQRQRQRQRQRQQRQRQQRQQRQRQQRQ QRSR RQR RQRRQRRQRQRQQRQRRQRSRSRSSR RSRRSRRSRRSRRSRRSRR SRSSRSSRSSRSRSSRSSRSRSRSRSRSSTSTSTTSTTSSTSTTSSTTSTSTSSTTSTTSSTSSTSSTSS TSTTSTSTTSTTSTSSTTSTSTUTUUTTUTTUTTUTUTUTTUTUUTUTTUTUTTUTUTTUTTUTTUTTUUTUUTUUTUUTUTUUTUTUTTUVUVUVVUVUVUUVUVUVUUVUVU UVUUVUVUVUVVUVVUUVVUUVVUVUUWWVWWVVWWVVWVVWWVWVWVVWVVWVVWVV WVWWVWWVWWVVWWVWVWWVWVVWVWWVWWVWWVWVV76767676776776768878787887787787787787887787887787877878877887887877887887887877878898898989889988989889889898898898 8988988:9 9899899899899899898998988989899:9::99::9:9:9:99:99:99:99::9::9:9::9:9:9::9::9:9;;:;:;:;::;;::;::;::;::;: ;:;;:;;:;:;:;:;:;;:;;<;<<;<;;<<;;<<;<;<; ;<;;<;<;<;<<;<<;<<;<<;<<;<;<;<<;=<==<=<<=<<=<=<=<==<<=<<==<=<<=<<=<<=<==<==<=<=<==<=<<==<==<=<>>=>>=>>=>=>>=>==>=>>==>==>=>>==>=>==>==>=>==>==>=>=>>=>=>>=>>==>=>=??>?>>??>>?>>?>>?>>?>>?>?>>??>>?>>?>?> > ?>?>>??>?>?>??>??@??@@?@?@?@?@?@?@??@??@?@??@?@??@??@??@?@@?@@?@@?@??@??@@?@?@?@@?A@AA@A@@A@A@@A@@A@@A@A@@A@@A@A@@A@A@@A@@A@@A@@AA@A@AA@AA@AA@AA@A@A@A@@ABABBABAABABAABABA ABABAABABABABBABABBAABBAABABBABBABAABCBCCBCBCCBBCBCCBCBBCBCBCBBCBBCBCBBCBBCBCCBCBCCBCCBCBBCBCBBCDDCDCDCCDCCDCDDCDCCDCCDCCDCDC CDCDDCDDCDDCDDCDCDDCCDCDEEDEDEDEDEDDEDEDEDED DEDEDEEDEEDEDEDEEDEEDEEDDEDEEFEFFEFEEFFEFEFEEFEEFEEFEEFEEFEEFEFEFFEFFEFEFFEFEFEGFFGGFGFGGFFGFFGFGFGFFGFGFFG FGFGFFGFFGFG GFGFG GFGGFGGFGFGHGGHGHHGHGGHGGHGGHGHGHGHHGHGGHGGHGIHGHGHGHHGHHGHHGHGHGHHGHHGHHGHHGHHGHHIHIHIIHHIHHIHHIHIHIHIIHIHHIHIHIJIIHIIHIIHIIHIHIHIIHIJIJJIJIIJJIIJJI IJIIJIJJIJIJJIJIIJJIIJIJJIIJKJKKJJKKJKJJKJJKJKJJKJJKKJJKJ JLKKJKKJK KJKJKKJKKJJKLKLLKLKLKLKLLKLKKLKLKKLKLKKLKLKKLKKLKK LKLLKLKLLKLLKLKLKLKKMLMMLMMLMLMMLLMLMLLMLLMLMLLMLLMLLMLLMLL MLMMLMMLMLMLLMLMMLMMLMLLMLMNMNMMNNMNMMNMNMMNMNMMNMNMMNMMNMNMMNMMNM MNMNNMNNMNMNNMNMNMNNONONNOONONNONOONONNOONNONNON NONN ONOONOONOONNOONOONONOONNONONONONPOOPOOPPOPOOPOOPOOPOOPOPOOPOPOOPOOPOOPOOPOOPOPPOPPOPOPPOPPOPPOPPOPPOPPOPOPOOPOOPPQPQPQQPQPQQPQPQQPPQPQPQPPQPPQPPQP PQPQQPQPQQPQQPQPQPQQPQQPQQPQPQQRQRQQRQQRQQRQRQQRQRQQRQRQQRQQRRQRQQRQQRQRQRRQ RQRRQRRQRQQRRQRRQRSRRSSRSRSSRSRSSRSSRRSSRSSRRSRSRSRSRSRRS RSRSSRSRSSRSSRSSRSRSSRRSSRSSTSTSSTSTSSTSSTSTTSTSSTSTSSTSSTSTSS TSTTST TSTTSTTSTTSTTSTSTTSTUUTUTUTUTUTTUTTUTUTTUTTUTTUTTUTUUTUTUUTTUUTUTUUTUTUUVUVUUVVUVUUVVUVUUVUUVUUVU UVUUVUUVUU!VUVUVUVVUVUUVVUVVUVUUVUVWWVVWVWWVVWVWWVVWVWVVWWVWVVWVVWVVWVV76767767667677677678877877878778787877877877878787787 878878 87887887887878788787989889889988989899889889898988988989889898 8989989898989 989899::9:9:9:9::9::9:99:99:99:99:99:9:9 9:;::9:9::9::9::9::9::9::;:;;:;::;::;:;:;;::;::;::;:;::;::;::;:;;:;:;:;;:;:;;:;;:;:;:;:;::;<<;<;<<;<;<;<<;;<<;;<;<;<<;<;<<;<;;<;<;=<<==<<==<=<<=<=<=<==<<= <=<=<<=<<=<==<==<==<=<==<=<=<=<=<<=>==>=>=>=>==> =>==>=>= =>=>>=>==> >=>>=>>=>=>>=>>=>=>>=>>?>>?>?>?>??>>?>?>>?>>?>?>>?>?>>?>>?>>?>??>?>?>>?>??>??>?>>?>??@?@@??@@?@??@@?@?@@??@?@?@??@??@??@?@@?@?@@?@@?@@?@?@?@@?@?A@AA@@A@A@AA@@A@A@@A@AA@A@A@A A@A@AA@A@AA@@A@AA@AABBABAABAABBABBABABAABAABABBAABABAABABBABBABBABBA BABAABCBCBBCCBCBBCBBCBBCBBCBCCBBCBBCBB CBCCBCBCBCCBCCBBCBCCDCDDCDCCDCDCDCCDCDC C DCD DCDCDCDDCCDDCCDCDCDDCDDCDEEDDEEDEDEDDEDDEDDEDDEDEDEEDEDED DEFEEDEEDEDEDEDEFEEFFEFFEFEEFFEFEFEFEFFEFEEFEEFEE FEFEFFEFEFEFFEFGGFGFGGFGFGGFGFFGFGFFGFGGFFGFFGFGFFGFFGFGGFGGFGGFGFGFFGFGGFGGFG GFGGFGHHGGHGHGGHGHHGGHGGHGHHGHGHGHGGHGGHGGHGHHGHHGHGHHGHHGHHGHHGHGHGHGHIIHIHHIIHHIIHHIHIIHIHHIHHIHHIHIHHIHHIHIHIHIHIIHIIHIHIHIIHIHIHHIIHJJIJJIJIJIIJIIJIJJIIJIJIIJIIJKJJIJJIJJIJJIJIJJIIJIJJIIJJIJIJIJJKJKKJKJKJJKJJKJJKJKJKJJKJJKJKJJKJKJJKJKJJKJKJJKKJKKJKKJKKJKJKJKJKKJKKJKJKJKLKLKLKKLLKLLK KLKLKKLKLK KLKKLKLLKLKLLKLLKLKLKLLKLMLMLLMLMLLMLLMLLMMLLMLLMLMLLMLMLMLLMLLMLLNMMLMMLMLLM MLMMNMNNMNMMNNMNMMNNMNMNMMNMMNMNMNNMMN MNMMNMNNMNMNMMNNMNNMMNMNNMNMNNMNNMNNMMNONONNOONONNONOONNONNONONONNON NONO ONOONONNONONNOON OPOOPOOPOOPOPPOPOOPOOPOOPOPOOPOPOOPOPOPPOPPOPOOPOPPOPPOOPOPOPPOPOOPPOOPQPQQPQPPQPQPPQPQPQPPQPPQPPQP P QPQ QPQPQQPQQPQQPQQPQPQPQPQRRQRQRQRRQRRQRQRRQRQQRQRQQRQRQRRQR RQRRQRQRRQRQRQRQQRSRSRRSRSSRRSRRSRSRRSRSRSSRSRSRRSRRSRSRR SRSSRSRSSRSSRSRSRSSRSRRSRSRTTSTSTTSSTSSTSSTSTTSSTSTSSTSTSSTUT TSTSSTTSTTSSTTSTTSTSTSTSTUTUTUTUTUTTUTTUTUTTUTTU TUTTUTTUUTUTUUTUUTU UTUTUVUVVUVUUVUVUVVUUVUVUUVUVUUVUVUVVUUVUUVUUVUVVWVVUVVUVVUVVUV VUVUVUUVVUWVWVWWVWVWVVWVVWVWVVWVVWVWVVWVVWVVWVV767767 767767767676677678878878778878878787787787787787787787887887887878 87887887878998899889988989989889898898898898898 8988998998998998989899889899898989989989899:9::9:99:99:9::99:9::9:9:9:99:9::9:9::99:9:9:9 9:9:9:9:9::9::9::9::9:9:9::9;:;;::;::;;::;;::;::;:;::;::;::;::;::;;:;:;:;;:;;:;::;;:;;<;<<;<;;<;<;;<;<;;<;<;;<;;<;< ;<;<<;<<;<<;<;<;;<;<;;<<;<<;;<==<<=<=<=<<=<<=<<=<=<<=<>==<= =<==<==<=<=<=<=<=<==<<=<==<==<=<<==<==>=>=>==>>=>=>>==>=>=>==>>=>==>=>==>=>>=>>=>=>==>=>=>>==>>=>=>>?>??>>?>>?>??>?>>??>??>>?>?>?>>?>>?>>?>??>??>??>?>?>?>?>??>??>??>?>??@??@@??@??@?@@?@?@?@?@?@??@??@??@? ?@?@A@ @?@?@@?@@?@@?@ @?@?@@AA@A@A@@A@A@A@A@@A@@A@@A@@A@@A@@A@@ A@AA@A A@AA@A@A@@AA@A@@A@ABBABABBABBAABABABABAABABAABAABAABA ABABBA BABABAABBABBABAABCBCBCBCBCBBCBCBCBBCBBCBBCBBCBBCBBCBCCBBCCBCCBCCBCBCCDCDCDCCDDCDCCDCDCCDCCDCDCCDCCDC DCDDCDDCDCDDCDCDDEDEDEDEDDEDEEDDEDDEDED DEDDEDDEDDEDEEDEEDE EDEDEEDEEDEEDEDDEEDEDEEDEDEEDFEEFEFEEFFEFFEFFEFEEFEFEFEEFEEFE EFEFFEFFEFFEFFEFEEFFEFFEEFEFEFFEFFEFFGFGGFGGFGGFGFGGFGFGGFFGFGFF'GFGGFGFGGFFGFGGFFGFGGHGHGGHGGHGGHGHHGHGGHGHGGHGGHGGHGGHGGHGHHG HGHHGHHGHGHHGHHGHHGHGHGHGHIIHIHIHIHIHHIHHIH HIHIHIHIIHIIHIIHIHIIHIHHIIHIJIJIIJIIJIJIIJIJ IJI IJIJJIJJIJJIJIJIJIIJIIJIJJIJJIJJKJKJKJKJJKJJKJJKJKJJKJJKJ JKJKKJKJK KJKKJKKJKJKKJKJJLLKKLKKLKKLKKLKLKLKKLKKLKLKKLKKLKK'LKLLKLLKLLKLLKLLKKLKLLMMLLMMLMLMMLLMLMLLMLLML LMLLMLLMMLL MLMMLMLMLMLMMLMMLLMLNMNNMNMNMMNMMNMMNMMNNMMNMNMMNMMNMMNMMNMNNMNMNMNMMNNMNMNNMNNMNNMNOONONONNONONNONONNONNOONONNONNONNONOONOONONOONONNOONONOONONNOPPOPOOPOPOOPOPPOPOOPOPOOPOPOOPOOPOPPOPOPPOPOOPOPPOPOPOPPQPQQPQPQPQQPQPQPQPPQPPQPPQPQPPQPPQPPQPQPQQPQPQQPQPPQQPPQRQRRQRRQRQRRQQRQRQQRQQRQQRQQRQRRQRRQQRQQRQRQRQRRQRQRRQQRQRRQRQSRRSRRSRSRSRRSSRSRRSRRSRRSRRSRRSRS SRSSRSRSSRSRSSRSRTTSTTSSTTSTSSTSSTTSTSSTSSTS STS S TSTTSTTSTTSTTSTTSTSTTUTTUUTUUTUUTUTUUTTUTTUTTUTTUTUTUUTTUUTTUT TVUUVUUTUTUTUUTUTUUTUUTUTTUUVUVUUVVUVUVUUVUVUUVVUVUVUVUVUUVUUVUVUUVUV VUVVUVVUVVUVUVVUVUVVWWVWWVWVVWVVWVVWVVWVWVVWVVWVWVV676677667667667667676676676676676676766767676776776776776766767766767787887878878778787877887887787877 87887878878788787887899889898989898988998898988988998898898998 8 989989 989989899899899898:99:9:9:99:99:99::9:99:9 9:;: :9::9::9::9::9:9::99:99:;:;:;;:;:;:;::;:;:;:;;:;:;::;::;::;: :;<;;:;;:;;:;;:;::;;<;;<;<<;;<;<;;<;<;;<;;<;<<;;<;;<=<<;<<;<<;<<;<<;<<;< <;<;<<;<<=<==<=<==<=<=<=<<=<=<<=<=<>=>>=>>==>=>==>==>=> =>==>==>==>?>>=>>=>>=>==>==>=>==>=>==>>=>>?>??>>?>?>>?>??>?>?>>?>?>>?>>?>>??>?>>?>>?>??>?>>?>??>??>?>>??>??>??>??@@?@@?@?@??@?@??@??@??A@@?@ @?@@?@@?@?@ @?@?@@A@A@@A@AA@A@@A@AA@A@@AA@A@@A@ @A@AA@A@@A@AA@A@AA@A@@A@@BABBABABAABABABBABABAABBAABAABAABAABA ABAAB BABBABAABBABBABBABAB BABABACBBCBCCBCCBCBBCBCCBCCBBCBBCBBCBBCBCBBCBCBBCBC CBCCBCCBCBBCCBCBCBCCBCDDCCDCCDCDCDDC CDCCDCCDC CDED DCDDCDDCDCDCDCDCDCDDEDEDEEDEDEDDEDEEDEDEDDEDDEDDEDDEDEEDEDEEDEEDFEEFEEFEEFEEFEFEFFEEFEFEFEEF EFEFEEFEFFEFEFFEFFEFEFFEFFEFEGGFGGFFGFFGFGFFGFGGFGFFGFFGFGFFGFFGFFGFFGFGGFGFGGFGGFGFGGFGGFGFFGGFHGHGGHGGHGHGGHGHG GHGGHGGHGGHGGHGGHGH HGHHGHGHHGHHGHHGHGHGHHIIHIIHHIIHHIHHIHIHIHHIHHIHI IHIHIIHIIHIHIIHIJJIJIJIJJIJIIJJIIJJIIJIIJIIJIJJIIJIJIIJIJIJJIJJIJJIJIIJIJJIJIJIJIJJIJKJKJKKJKKJJKKJKKJJKJJKJKKJJKJJKJJK JKJ J KJKKJKJKJKJKJKKJKKJKJKKJLLKLKLLKLKKLKLKLKKLLKKLKLKKLKKLKLKKLK KLKLLKLKLLKLLKLKLLKLLKLLKLKLLKLMMLLMLMLMLLMLLMLLMLLMLMLLMLMMLMLMMLMMLMMLMMLMLLMLMLMMLLMLNMNNMMNMMNMNMNNMNMNMMNMMNMMNMMNMMNMMNMMNMMNMNNMNNMNNMNNMNNMNMNMMNMNMNMNNMNNONONONONNONNOONONONNOONONNONOONONNONNONOONOONOONONO ONONONOONONPPOPOPPOOPOPOPPOOPOPOOPOPO O POPPOPOP POPPOPOPOPPOPPOPPQQPQPQPPQPQPQPQPPQPPQPPQPPQPPQPPRQQPQQPQQPQQPQQPQPQPRRQRRQRRQQRQRQRRQRQRQRRQQRRQRRQRQRQQRQQRQRQQRQR RQRRQRQRQRRQRRQRRQRRSRSRRSRSSRRSRSRSSRSRSRSRRSRSSRRSRSRRSRRSRSSRSSRSSRSRSRRSRSRRSRSSTTSTTSTSTSTTSSTSSTSTTSTSSTSTSSTSSTSTTST TSTTSTTSTTSTTSTSSTTSUUTUTUTTUTTUTTUTUTTUTUTTUTTUTTUTTUTUTUUTUUTUTUUTUTUTUUTTUTVUUVVUVUVUVUUVUVVUUVUUVUUVUVUVUUVUUVUUVUUWVVUVVUVUVVUUVUVUVVUVUVUUVVUUV67677676766776676776767667667667676676687 767767676677677677676776788788787788787887 7878787787787 7878 8788788788787887787789989889889989889889889898989889889889889:9 9898998 9899898899899899889::9:99:99:99:9:99::99:99:99:99:99:9:9:9::9:9:99::9::9::9::9:;;:;:;::;:;;::;::;:;:;::;:;;:;;:;;:;;:;:;;:;;:;:;:;<<;<;<;<<;<<;<<;<<;<;<;;<;;<;<<;;<;<;<;;<;<<=<<=<<;<<;<;<<;<;;<;;<;;<<;<=<==<<=<<=<=<=<=<<=<=< <=<<=<<=<=<==<=<=<=<==<=<=<>==>>=>>=>=>==>=>==>=>>=>==>==>=>==>>==>==>=>>=>=>>=>=>==>>=>>=>=>==>=??>?>?>?>?>>?>>?>?>?>??>?>>?>?>? ?>?>??>?>??>?>??>??>?>>@??@?@?@??@?@?@??@??@?@@?@ @?@@?@@??@??@@?@@?@?@@AA@A@AA@A@A@@AA@@A@A@@A@AA@A@@A@A@@A@A@@AA@AA@AA@A@AA@AA@A@AA@@A@A@@BAABBAABAABABBABBAABAABAABAABABAABAABAABAABABBABBABBABABBABAABBABABBABCCBCBCBCCBBCBBCBBCBBCBCBCB BCBBCBC CBC CBCCBCBCBBCBDCDDCCDDCDCDDCDDCCDCDCDCDCDDCCDCCDCCDCDDCDDCDDCDDCDCDDCDCDDCCDCDCCDCCEDDEDEDDEEDEDDEDDEDDEDDEDEDEEDEDEEDEEDEEDDEDEDDEDEDEEDEEFEFEEFEFEFFEEFEEFE EFEFFEEFEEFEFEFEFFEFFEFEEFFEFEFEFEEGFFGFGGFGFGFGGFGGFFGFFGFGFFGFGFFGFF GFGGFGGFGFFGFFGGFGFFGFGGFGFGGFGFHGGHGGHHGHG GHGGHGGHGGHGGHGGHGHHGHHGHGGHHGHGGHHGHHGHIHIHHIHIHIHHIHHIHHIHHIHHIHI IHIHIIHIHIIHIHIIHIHHIHJJIJJIJIJIJIJIJIIJIJIJIIJIIJIIJI IJIIKJ JIJJIJJIJJIJIJJIJJIJJIKJJKJKKJJKJJKJKJJKJKJKJJKJJKJJKJJKJ JKJKKJKKJKKJKKJKJKKJKJLKLKLKLLKLKKLKLKKLLKLKLLKKLKLKKLK KLKLLKLKLLKLKLKLLKKLKLMLLMMLMLMMLMLMMLMLLMLMLLMLLMLMLLMLLMLMMLMLMMLMLMMLMLLMMLMLMMNMNMNMNNMMNMNMMNMMNMMNMMNMMNMMNMNMNMNNMNNMNNMNNMNNMMNNMNONONNONOONOONONOONONNOONONNONNONNONNONO ONONNONNONNOONONNOPOOPPOPPOOPOPOOPOPOOPOOPOPOOPOPOOPP O POPPOPPOPOPPOPPOOPPOPOPPOPOPQQPQQPQQPPQPQPQP PQPPQPQPPQPPQPQQPQQPQPQPPQQPQQPQQPPQPPQPQQPQQRRQQRQQRRQQRQQRQRQQRQRRQ QRQRQQRQ QRSRRQRQRQRRQRRQRQQRQQRSRRSSRSRRSRSRRSRSRSRRSRSRRSRRSR RSR RSRSSRSSRSSRSSRSSRRSSRSSRSRRTSSTTSTSSTTSTSSTSTSSTSTSTTSSTSTSTSSTS STSTSTTSTTSTSTTSTSTTSTSTTUTUTUTUTUUTTUTTUTTUTTUT TUTUTUUTUUTUUTUTUUTUUTUTTUUTTUUVUVUUVUVUVUUVUVUVUUVUUVUUVUUVUVVUVVUVVUVVUV VUVVUVVUVVUVV677667676767667667676676676 6767 7676776766767676676776877877877878877877877878778788778778788788787887878788998988989988989898 89898988989989989889899899899:99:9:9:99:9:99:99:99:99:99::9:9:99:99:9:99:9::9: :9::9:9:99::9:9:;:;;:;:;::;::;;::;::;:;:;::;::;::;::;::;: ;:;;:;;:;;:;:;;:;;:;:;;:;;:;<<;;<;<<;;<;<<;< ;<;;<;;<;;< <;<;<<;<;<<;;<;<<;<<;<;<;;<<;<;;==<==<=<<=<=<<=<<=<==<<=<<=<<=<=<==<<=<=<<=!=<==<<==<==<=<<=>=>==>==>>=>==>==>=>==>=>==>=>?>>=>>==>>=>>=>>=>=>=>>=>?>??>?>?>?>>??>>? >? >?> > ?>??>?>?>?>?@??@??@??@@??@?@?@@??@?@??@?@??@??@?A@"@?@@? @?@?@@?@@A@A@AA@A@@A@@A@@A@@A@ @A@AA@ A@AA@AA@A@AA@AABBAABAABAABBAABABBABAABABAABAABAABAABA ACB BABBABABABBABAB BABAABBABBABABACBCBBCBCBBCCBBCBBCBBCBBCBBCBBCBCBCCBCBCCBCCBCCBCBCCBCBDCCDCCDDCDCCDDCDCCDCDCCDCCDCDCCDCCEDDCDDCDDCDCDCDDCCDDCDEDDEEDEEDDEDEDEDEDDEDEEDEDDEDDEDDEDDEDEEDEEDEDEEDEDEDEDEDDEEFFEEFFEEFEFEFEFEFFEEFEEFEFFE EFEEFEFFEFEFFEFFEFFEFFEFFEFFEFFEEFGGFFGFGGFGGFGFFGFFGFGGFGFGFFGF FGFF GFGGFGGFGFGGFGGFGGFGGFGHGHGGHGHGGHGHGHHGHGGHHGGHGGHGGHGGHGHHGHHGHGHGHHGGHGHHGHGHGHHGHHGHHIHHIHIHIHHIHHIIHIHHIHIHHIHHIHI HJIIHIHIHIIHIIHIHHIIHIIHIIHIHHIHIJJIJIJJIIJIIJIIJIIJIIJIIJI IJIJIJJIJJIJJIJJIJJIJJIKKJKKJKJJKJJKJJKJJKJJKJJKJKJ JKJKJJK KJKJJKJKKJKKJKJKJJKJKJKLKKLLKLKKLKKLLKLKLLKKLKKLKKLLKLKKLKKLKKL LKLLKKLLKLLKLLKLLKLLKLLKLKLKLLMLMMLMLMLMMLMMLLMLML LMLMLMMLML LMLMMLMLMMLMLMMLMMLMLMLMLLNMMNNMNNMNMNM MNMNNMNMMNMMNMM!NMNMNNMNNMNNMNMNNMMNMMNNMNNONOONONONNONOONNONNONNONONNOONNONNONOONOONOONOONONOOPOPOOPOOPOPOPPOOPOPOOPOOPOOPOOPPO OPOOPOPPOPPOPOPOPOOPPOPOPPOPPQQPQQPQPQQPPQPQPQP PQPPQPPQPQPPQPQQPQQPQPQQPQQPQQPQPPQPQQPQPPQPQQRQRRQRQRQRRQRQQRQRQQRQRQ Q RQRRQRRQRRQRRQRRQRRQQRQRQRRQRQQRQRQSRSRRSRSSRSRRSSRRSRRSRRSRRSRSRRSR RSRSSRSSRSRRSRSRSRRSRSSRSRSSRSTSTTSTSSTSTSSTSSTSTTSSTTSTTSTSSTSTTSTTSTSTTSTSTTSTTSTSSTSTTUTTUUTTUUTUTUTUUTUTUTUTTUUTUTTUTTUTTUTTUTTUTUTUTUUTUUTUTUUTUTTUUVVUVVUVUUVUUVVUVUUVUVUUVVUVUUV UVUVWVVUVVUVVUVUVUVVUVVUVVUVVUVUUVUVV 656656656566566566566566566566766767667676676767667677676676766766787767767767 767767676676766787878787787788788778778778787877878787787788778788788788788787887887878878779989898989889889889889898 8988988989989989899899899898998:9::9::9:9::9:: 9:99:99: 9:9::9::9:9: :9:9::9:99:99::;:;;:;;::;:;::;::;::;::;::;::;::;;:;;:;:;;:;;:;::;;:;;::;;:;;:;:;<<;;<<;<;<;;<;<;;<;;<;<<;<;;<;<;<<;<<;<<;<<;<<;<<;<;<<;<;<;==<<==<<==<==<=<<=<=<<=<<=<<=<=< <=<<=<==<=<==<==<==<==<=<==<=<==>=>>=>=>>= =>=>=>=>==>=>==>= =>=>==>=>>=>=>>=>>=>>=>=>=>>=>>=>=>=>=>??>?>?>>?>>?>>?>??>?>?>?>>?>>?>?>>?>>??>??>?>?>>??>>??>@@?@@??@??@@?@@?@?@??@??@? @?@@?@?@@?@@?@@?@@?@@?@?@??@@?@A@@A@A@@A@AA@A@A@A@@A@@A@@A@@ A@AA@AA@AA@AA@A@A A@A@A@@A@AA@BABBABABBAABABABA ABABABABAABCB BABBABBABBABABBACBBCBBCBBCBCBBCBBCBCBBCBCBCCBBCBBCBBCBC CBCCB CBCBCCBCBCDCCDDCCDCCDDCCDCDDCDDCCDCCDCCDCCDDCCDCCDCCEDDCD DCDCDDCDDCDCCDDCDCCDCDDCCDDEEDEDEEDEEDDEDEEDEDEDDEDDEDDEDDEDED DEDEEDEEDEDEEDEEDEDEEDEEDEEDFFEEFFEFEFEEFEFFEEFEFFEEFEFEEFEEFEEFE EFEFEFFEFEFEEFEFEFEEFFEGFGGFGFGFGFGGFGFFGFFGFGFGGFFGFGFGFFGGFFGFGFGGFGF GFGGFFGFFGFGHGGHGHHGHGHGHHGHGGHGHGGHGGHGGHGGHG GHGHHGHGHHGH HGHGHGHHGGHGGHGHHIIHIHIIHIHIHHIIHHIIHIIHHIHHIHHIHIHHIHHJIIHIIHIHIIHIHIIHIHIIHIJIJIJIIJIJIIJIIJIJIIJIIJIIJI IJIJIJJIJIJIJIJJIJJIJIIJIJIIJJKJKJJKJKKJJKJJKJJKJJKJKJKJJKJKJKKJKKJKKJKKJKJKKJKLKKLKLKKLKLLKLKLLKLKKLKLKKLKKLKKLKKLKKLML LKLLKLLKLLKLKLLKKLKLKLLKLLKKLKLKLKLMLLMLMLMLMLLMLMLMLMMLLMLLMLLMLMMLMLMMLMLMMLMMLMMLMMLMNMMNMNMNNMMNMNMMNMNNMNMMNMMNMNNMNNMNMN NMNNMMNMNMNNONNONOONNONOONNOONONNONNONNONNONOONONOONONOONOONOONOONONOOPOPOPOOPOOPPOOPOPOPOPOOPOOPOPOOPOPPOPPOPPOP POPOPPOPOPPOOPPOPQPPQQPQPPQPQPQQPQPPQQPPQPPQPPQPQQPQPQQPQQPQQPQQPQQPPQPQRQRRQQRRQRQQRQQRRQRQQRQQRQRQQRRQQRSR RQRRQRRQRQRQQRQSSRSSRSRSSRSRSRSRRSRRSRSRRSRR SRSSRSRSSRSRSSRSSRRSRSRTSTTSTSSTSSTSTTSSTSTTSSTSTSSTSSTST TSTTSTSTTSTTSTTSSTTSTTSTTSTSTSTTSTSUUTUUTUUTUUTUTTUTUTUTTUTTUTTUTTUT TUTU UTUUTUUTUUTUTUUTUTTUTUUTTUUTTVVUUVU UVUVVUUVVUVUVUVUV676656566565565655665665665667676766766767676766767 676678776767767767676676767767787887887788787787787787787787878878878 878878788778778878878988989989898998899889889889889898898898998998989898998989:9:9:99:99:99:99::9:99:99:99:9:99:9 9:9::9::9::9::99::9:99::9:;::;::;::;;::;:;:;;:;::;::;:;::;;:;::;:;:: ;:; ;:;;:;::;;::;;:;;:;:;;:;::;;<;<;<<;<<;<;;<;<;<<;;<;;<;;<; <;<<;<<;<<;<;<<;<<;<<;;<;<;<;;<=<=<=<=<=<<=<=<< =<= =<==<==<==<<==<<=<=<==<==<==<>=>>==>=>=>==>==>==>==>==>=>==>==>=>==>==>==>=>>=>>=>>=>>=>=>>=>>=>>=>=>==>>=>=>??>?>?>>??>?>>?>??>??>>?>?>>? >?>??>>?>?>??>??>??>>??>>??>??>??@??@??@@??@@?@@?@?@@??@??@??@??@??@?@?@@?@?@?@?@?@?@?@@A@@A@@A@AA@A@A@@A@@A@@BA A@AA@A@AA@AA@AA@@A@AA@A@ABABABAABBABAABABBAABABBABAABBAABBAABABBABBABABABABBABAABBCBBCBCCBCBCBCBCBCBBCB BCBBCBCBCBCCBCBBCCBCCBCBCCBCBCCBBCBCCDCCDCCDCDCDCDCDCCDCCDCCDC C"DCDDCDDCDDCDDCDCDCEDDEEDEDDEDDEDEDEDDEEDEDEDDEDDED D EDEEDEEDE EDEDEEDEDEEDDEEDEDDEFEFEEFEEFFEEFEEFEFEFEFFEFFEEFEFEEFEEFEEFEFFEFFEFFEFFEEFEFFEEFEFFGFGFGFGFGFFGFFGFGFFGFFGFFGFGGFGGFGFGGFGGFGHGHGGHGHGGHGHGHGHGGHGHGGHGGHGGHHGGHGHGGHGGHGGHGIH HGHHGHGHGHHGHHGHGHHGHHGHGHGHGHHGIIHIIHIHIHIHHIHIIHIIHIHHIHHIHIIHIIHIHIIHIHHIIHIHIIHHIHHIIHIJIJIIJJIJIIJJIJIJIIJIJIIJIJJIJI IJIJJIJJIJJIJIIJIIJKJKJKJJKJJKJ JKJJKJKJJKJKJJKJ JKJKKJKKJKJKJJKKJKJKJKLKLLKLKKLKKLKLLKKLLKLKKLKKLKKLKKLKKLKKLKLLKLKLLKLKLKLKLKKLKKLMLLMLLMLLMLMLMMLLMLMLMLLMLLMLLMLML LMLMLMMLMMLMMLMNNMNMMNMNNMNMNNMNMMNMNMMNMNMMNMMNMMNMMNMNNMNMNNMNNMNNMNMNMMNNMNMMNMMOONONNONOONONNONNONNONONNONNONNONOONONNOONOONONOONONNONNPOPOPOOPOPOOPOPOOPOOPOOPOPOOPOPOPPOPPOPOPOPPOPPOOPPOPOPOPPQPPQPQPPQPQPQQPQPPQPPQPPQPPQP P QPQQPQPQQPQPPQPPQQPQQPQPPQRRQRQQRQRQRQQRQRQRQ QRQQRQ RQRRQRQRQRRQRRQRRQRRQRRQRRQRRSRSSRSRRSRSRSRRSRSRSSRSRRSRTSSTSSRSSRSSRSSRSSRRSSRSRSRRTSSTTSTSTTSTSTTSTSTSTSSTSSTSSTSSTSSTSTTSTTSTTSTSTTSTTSTTSTTSTTSTTSTSTSTTSSUUTUTTUUTTUTTUTTUT TUTUTUTTUTTUVU UTUUTUTUUTUTUTUUTUUTUTUTUUVUVUVUVUUVVUVUVVUVUVUVUVUVUUVVUUVUUVUUVUUVUU656656656556565665656556677676776676766766776676676767767667676 6 767 767 7677677676677667676767887878877878778778778778787787787 789887887787887887887879889899898998998988988988989889898898898898989898899:9 98 9899898998989988998988989::9::99:9:99:9:9:99:9:99:99:9 9:9:9::99:9::9:9::9::99::9:9:99::99:;::;::;:;: :;:;:;::;::;:;;:;;::;:;;:;;::;;:;::;;::;:;::<;<<;<;<;;<;<; ;<;<;;<;;<;;<;;<; ;<;<<;<;< <;<;;<<;;<;;<<;<;<<=<==<<==<=<==<=<==<=<<=<<=<<=<=<<=<<=<<=< <=<==<=<=<=<<==>=>>==>==>>=>>=>==>>==>=>>==>==>==>==>==>==>=>>=>>=>>=>==>>=>=>>=>=>??>?>??>>?>??>>??>?>?>>??>??>>?>>?>>?>??>?>>??>?>??>??>??>??>??>?@?@@?@?@??@@??@?@@??@??@?@??@??@?@??@??@??@?@ @?@@?@@?@??@@A@A@A@AA@A@@A@A@AA@A@@A@A@A@@A@@A@A@@BAA@A@AA@AA@AA@A@AA@A@A@AA@AA@AA@A@BABBABABABABAABBAABAABABBAABABAABA ABAB BABABBABBABAABBABABBABABACCBCCBCBCBCBBCBCBBCBBCCBBCBCCBCBCBCBCCBCCBBCCBCCDCDDCDCDCDCCDCDCDDCDCDCCDC CDCCDDCD DCDCDDCDDCDCDDCDDCDCDDEDEDDEEDEDEDDEDDEDEDDEDEDED DEDEDEEDEEDEEDEEDEEDEDEEDEEDDEDEDEEFEFFEEFEEFEFEEFEFEFEFFEFEEFEEFE"FEFEFEF FEFFEFGFGFGGFFGFFGFFGFFGFFGFGFFGFFGFGFFGFFGFFGFGGFGGFGFGFFGFFGFGFGGFGGHGHGHGHHGHGHHGHGGHGGHGHGGHGG HGHHGHGHHGHHGHHGGHGHGGHHIIHIHIHIIHHIIHIHIHIHHIHHIIHHIHHIHIHHIHHIHIIHIIHIIHHIIHIHIIHHIHIHIIHIIHIIHIHIIHJIJIIJIIJJIJIIJJIJJIIJIIJJIIJIIJIIJIIJIIJI I JIJIJIJIJJIJIJJIJIJJIJJIJIKKJJKJKKJKJKJJKKJJKJKJKJJKJ JKJ JKJKJKKJK KJKKJKKJJKKJKJJKJJKKJKKJKJLLKLLKLKLLKLKKLKLKLKKLKKLKKLKKLKLLKLLKLLKLLKLKLLKKLMLMLMLLMLMLLMLMLMMLMMLLMLLMLLMLL MLMMLMLMLMMLMMLLMLMNMMNMNNMNNMNMMNMNNMNMNMNMMNMNMNMMNMMNMNMMNMMNMMNMNNMNNMNNMNMNMNNMNNMNNMNMMNNONNONNONOONOONNONONNOONNONNONNONO ONONOONONNOONOONOONPOPPOPPOPPOPOPPOPPOPPOOPP OPOPOPOOPO OQPPOPOP POPPOPOPPOOPQPQPQPQQPQPQPPQPQPPQPPQPPQPQPQPPQP PQPQPQPPQ QPQPQQPQPQPPQRRQRQQRQRRQRQRRQQRQRQQRQQRQ QRQ RQRRQRRQRQQRQRRQQRQRRQRQRSRRSRSRSSRSRSRSSRSR RSRSRSRRSRSSRSSRSRSRSRSSRSSRRSTSSTTSTTSSTSSTTSTTSTTSSTS STSSTSSTSSTSSTSS TSTTSTTSTTSTTST TSTSTSTSSTSTSSTUTUUTUTUUTTUTUTUUTTUTUTUUTTUTUTUTUTTUTTUTTUTUUTUUTUTUTTUTUUTUTUTVUVUVVUUVUVUVUUVVUUVUVU UVUVVU UVU5665655655655655656656 6565667677676767767676677676676767 767767787878778778788788787877877898 87887887887878879889989898988989988989988988989898998899899:99::9:9::9:99:99::9:99:9:9::9::9::9:9::;:;:;:;::;:;::;::;:;;:;;:;:;;<;<;<;<;;<;;<;<;;<;<<;;<;;<;;<;;< <;<<;<;;<<;<==<=<==<=<==<==<=<<=<=<<=<==<=<=<=>>==>=>>=>==>==>==>==>==>=>=> >=>=>=>=??>?>?>?>>?>?>>?>> ?>??>>??@?@??@?@?@@??@??@??@?? @? @?@@?@@?@@?AA@A@AA@A@@A@A@@A@AA@@A@A@A@AA@A@AA@AA@A@AABABBABABAABABAABAABAAB ABCBBAB BACBCBBCBBCBCBCBBCBCCBCBBCBCCBCBCCBCCBCDDCDCCDCDDCDDCDCDCDCDCCDCC#DCDDEDEDDEDEDEDDEDDEDEDDEDDEDDEEDEDEDEEDEDEDEDDEEDEEDEEDEFEFEFEFFEFEEFEEFEFEEFEFFEFGF FEFFEF FEGFGFFGFFGGFGFGFFGGFFGFFGFFGFGFFGFGGFGFGGFGGFGGHGHHGHGHGGHGGHGHHGHGGHGHGH HGHGH HGHHGHGHHGHHIHIIHHIHHIHHIIHIIHIHIHHIHI IHIIHJIIJIIJIJIIJJIIJIIJIJJKJJIJJIJIJJIJJIJKJKJKKJJKJKKJKJKJJKJJKKJKJKKJKKJKJKJJKKLKLKLKLKLLKLKKLKLKKLKLLKLKKL LKLLKLLKLLMLMLLMLLMLMLLMLLMLLMLMNMMLMMLMNMMNMNMMNMMNMMNMNMNMMNMMNMN NMNMNMNNONONNONOONONONNONONOONOONOONONOPPOPOPPOPOOPOPOOPOOPOPOOPPO PQPQPQPPQPQQPPQPPQPQPQPPQP QPQQPQQPQQPQQPQPQQRQRQQRQRQRQQRQRQRQQRQRRQQRRQRRQRQRRSSRSRSRSRRSRRSRSRRSRSRSSRSSRTSTTSSTTSTSTTSTSSTSSTSTSTSTTUTTSTSTTSTTUTUTUTUTUTUUTTUTUUTTUTTUTUUTU UTUT656556556566556556656556556556656656656676776676676677676766768776776776887887877887887878787877877877878878788788787878998998998989989989989988988988989989989989899:9::9:9:99:99:99:9::9:99:9::9::9::9::;;::;:;::;:;::;::;;:;::;:;:: ;:;:;;:;:;;<;<<;<<;<;<<;<<;;<;<<;;<;;<;<;<;<;<<=<=<=<=<=<<=<<=<=<=<=<<= =<=<==<<=>==>>=>=>==> =>==>>=> >=>>=>>=>=>>?>?>>?>>?>?>?>>?>>??>>?>?>??>??>?>>?>??@?@?@@??@??@?@?@??@?@??@@?@@?@@?@@?@@?@@?AA@A@A@A@@A@AA@AA@AA@A@@A@AA@@A@@AA@A@@AA@A@@A@AA@AA@@ABBABBABBABAABABBABAABAABABBABBABCCBCBCCBCBCBCCBCBCBBCBBCBC CBCCBCBCBBCBCCBCCDCCDCDCDDCCDDC CDCDCCDCDCCEDDCDDCDCDDEDEDDEDEDEDEDEDEDDEDEDDEEDEDEDDEDEEDEEDEDEEDEDEEDEEFFEFEFFEEFEFEEFEEFEFEEFEFEFEEFFEFFEFFGFGFGFFGFGFFGFFGFFGFFGFFGFGGFGGFGFGGFGHGGHGGHHGGHGGHGGHGHGGHGGHGHHGHHGHHIHHIIHIHIHHIHIHIHHIIHHIHIIHIIHIIHIIJIJIJIJIJIIJIIJIIJIJJIIJIJIKJJIJJIJJIJJIJJIJJIJIJKKJKKJKKJKJJKKJJKJKJJKJJ"KJKJKKJLLKLLKKLLKLKKLKLLKLK KLKLLKLLKLMLLMLLMLMLMLMLMLMLLMMLLMLLMLLMNMMLMLMMNMMNMNNMNMNNMMNMMNMM%NMNNMNOONONOONNONOONONNONNONONO ONOONOONOONOONOONOOPOOPOPPOPPOPOOPOOPPOOPOPPOPPOPPOPPQPPQPQPPQPQPPQPPQPQPPQPPQPQQPQQPQPQPQRQQRQQRQRQRQRRQRQRQRQQRRQQRQRRQRQR RSRSRSRRSRRSSRRSRSRSSRSRRSRSRSSRS STSSTSTSTTSTTSTSTTSSTSTSTTSTUUTUTUTTUTTUTUUTTUTTUTUVUUTUTUUTUTUTTUUTT6565656556565655656656656656656656776676676677667667676776676676676676776 76767787878877878788788778877887787878787889898998988989989889889889899:9:9:99:99:99:9:99:99:99::99:99::;::9::9:9::9:;:;;:;;:;:;;:;::;:;:;::;::;:;&;:;;<;<<;<;<;;<;;<<; ;<;< <;<=<=<==<=<=<=<<==<<=<==<=>==<=<=>=>>=>=>==>==>==>=>==>==>>=>>=> >=>=?>>?>?>>??>?>>?>>?>?>??>?>??>??>??>?@?@?@?@@??@?@??@?@?@??@??@?@?@@?@@?@@A@AA@AA@@AA@@AA@@AA@A@@A@A@@AA@A A@A@@ABAABABBABABABAABABAABABBABABBABABCBCCBBCBCCBCBBCBBCBBCBBCBBCBBCBBCCBCCBC CBCCBCCDDCDCCDCCDCCDCDCCDCDCDCDCC DCDDCDCDDCDDCCEDEDDEDDEEDEDEDEEDDEDDEEDEEDEEDDEEFEFEFEEFFEFEFEEFEE FEFEF FEFEFFGFGGFFGFGGFGFGGFFGFGFGFGGFGGFGGHGHGHGGHGGHGHGGHG GHGHGHHGHGHHGIIHIHIIHHIHHIHIHHIHIHHIHHIHIIHIHIIHIHIJIIJIIJJIJJIIJIJIJIJII%JIJJKJKJKKJJKJKJJKJJKJK KJKJKKLKLKKLLKKLLKLLKKLKKLLKLLKKLKLKLLKLLKL LKLLKLKLMLLMMLLMLMLMLLMLLMLLMMLMLLMLLMNM MLMLMMLMMLLMMLMMNMNNMMNMNNMNMNMMNMNMMNMNMMNMMNMMN NMNNMN NMOONOONOONONOONONNOONNONOONNONOONNONOONOONOOPOOPOPPOPOOPOOPOPOOPOP POPOPPOPOOPPOPPOPQPQPPQPPQPQPQPQPQPPQPPQPPQPPQQPQRQ QPQ QPQPQQPQPQRRQRQRRQRQQRRQQRQRQ QRQQRQRRQRRQRSRSRSRRSRRSRRSSRRSRRSRSSRSSRSRRSSTSTTSSTSTTSTSSTSTSSTSSTSSTUUTTSTTSTTSTTSTSTTUTTUTUUTTUTUTUTTUTUTUUTUUTUUT @YZYZZYYZYYZZYZYZYZZYZYYZYZYZYYZYZYYZYYZYZYYZ ZYZZYZZYZZYYZZYZYZYZYZZYZZYY[[Z[[Z[[ZZ[[Z[[ZZ[Z[ZZ[[ZZ[ZZ[Z[Z[[Z[ZZ[Z[\[[Z[[Z[ZZ[Z[Z[[ZZ[[ZZ[ZZ[[\\[\[[\\[[\\[\[\[\[[\[[\[[\[[!\[\\[\\[\\[\[\[\\[\[\\]\]]\]]\\]\\]\]\]]\]]\]\\]\\]\\]\]\\ ]\]]\]]\]]\]]\]\\]]\]\\]\]\]]\]]^]^^]^^]^]^^]]^]^]]^]^]]^]^]]^ ]^]^^]^]^^]^]^^]^^]^^]^]^^_^_^__^^__^_^_^_^^_^^_^_^_^^_^_^^_^ ^ _^__^_^ _^_^^__^_^_^__^^_`_`_``__`_``__`__``__`_`_`_``__`__!`_ `_``_``_`__a`a`aa`a``aa`a``a``a``a`a``a``a`aa` `a`aa`a``aa`aa`aababbababbaababaabaababbaabaaba abcb bab bababbaabababbabbabbcbbccbccbccbbcbbcbccbbcbcbbcbcbbcbcc b cbcbccbccbcbccbcbcbccdcdcdcdccdcdcdccddccdccdcdccdcdccdccddccdccdcced dcdcddcdcddcdcd dcdcddcdeeddeededdeddededdeddededdedededdeddedeede ededdedeededeedededededeefefeffeffefeefeeffeefefeefeefeefeefefe efgf fef feffeffefeffefefeffggfgffgffgfgfgffgfgffgffgffgffgfggfggfggffggfgfggfggfgfgffgghghgghhghgghhghghhgghgghgghg ghih hgh hghhghghhghgghhghghghghhgihihhihhihhihhiihiihhihhihhihhihhihihihhihhihh ihi ihihihihihhiihihhihihhihiijijijjijijiijiijiijiijijiijiiji i jijjijjijjijijjijijijijjijijjijiikkjkkjkjjkjkjkjkjkjkjjkjjkjjkjjkjkjjkjkjkkjkkjkjkkjkjkjkkjjkklkklkklkkllklkklklklklkklkklkklk klkllklkllkllkllkklkllkllkllmlmlmlmmlmmlmlmmllmllmllmllmllmlm mlmmlmllmmlmlmlmmlmlmlmnmnmnmnmmnnmnmnmmnmmnmmnmmnmnnmm nmn nmnnmnnmnnmnnmmnmnnmnmnmnnoonnonoononononnonnonnonnonnononoonoon onoononnoonnopoppopoopopoopopoopopoopoopooppoppoppopopoopopopoopoppoppqpqpqqppqqppqppqpqqpqppqpp#qpqqpqqpqqpqqpqppqpqqrqrrqrrqrqqrqrqrrqqrqqrqqrqqrqrqqrqrqqrrqrrqqrrqrqrqrrqrrqrqrqrrqrqrsrsrrsrrsrsrrsrsrrsrsrrsrsrrsrrsrrsr rsrssrsrssrsrssrsrsrrsttssttststs ststtsstsstsstsstsststtstts tstststtststssttsutuututtututtuuttutuuttututuututut tutuutuutuutuuttutuutuutuvvuvuuvuuvuuvuvuuvuuvuvuvuuvuuvu uvwvvuvuvvuvvuvuvvuvwwvwvwvwvwvvwvvwvvwvvwvvwvwvvwvvwvvwvwwvwwvvwvwwvwvvwvwxwxwwxwxwwxwxxwwxwwxwxwxwwxwwxw wxwxxwxwxxwxwxwwxwxwwxwxxyxxyyxxyxyxxyxxyyxyxyxxyxxyx xyxyyxyyxyxyxyyxyyxyxyyxyyZYZZYZYZYZZYZYZZYZYYZYZZYZZYYZYZYY ZYZ ZYZYZZY ZYZZYYZZYZ[[ZZ[Z[Z[[Z[[Z[[ZZ[ZZ[Z[ZZ[ZZ[ZZ[[ZZ[Z[ZZ[ZZ[Z[[Z [Z[Z[Z[[\[\\[\[[\[[\[[\[\[\[[\]\\[\\[\\[\\[\\[\\[\\[[\\[\\[[\\]\]]\]\]\]\\]\\]\]\\]\]]\]]\]]\]]\]\]]\]\]]\^]^]^^]^]^]^^]^]]^^]]^]]^]]^^]]^]]^]]^]] ^]^^]^]^^]^^]^ ^]^^]^^]]^]^]]^_^__^_^_^_^ ^_^^_^ ^_^^_^__^__^_^^_^__^__^_^__^_^_`_`__`_`_`__``__`__`__`__`_``__`__`_`_`__`__`_`_``_`__``_``_`_`_``_`_`_``a`a`a``aa`a`a`aa`a``a``a``a``a``a``a``a`` a` a`aa`aa`aa`aa`aa``aa`a`aa`abaabbababaabbabbabaabababaababaabaababbababbabbabbabbabbabaabaabcbccbcbbcbcbbcbbccbcbcbccbcbbcbbcbccbcbccbcbccbccbccbccbcdcdccdccdcdccdccdccdcddccdcdccdcddcddcddccdccddccdcddcdcceededdedeededededeeddeddeddededdeddedd"edeedeededeededeedeedefefeefefeefeffeefeeffeeffefeefefe e fefefef fefefeffefeffeffefefgfgfggfggfgfgffggfgfggfgfgffgfgffgffgfg gfggffgfggfgfgfgghgghghgghghghghgghgghgghgghgghgghgghggh hghghghhghhghghghhghhghhghihiihihihihihiihhihiihih hihhihhihiihihiihiihihihhihiihihhijijijijijjijijjijiji iji jijjij jijijijjijjijiijijiijijjijjijjkjkjjkjkjkjkjjkjkjjkjkjjkjkjjkjjkjkkjkkjkjkkjkkjkkjkkjkkjjlkklkklkkllklkllkllkkllklkklk klk klkklkllkllklkllkllklkllkklkmllmmlmlmlm lmlmllmllmllmlmmlmmlmmlmmlmmllmlmnmnnmmnmnmmnmmnmnmmnnmnnmnmnmmnm m nmnnmnnmnmnmmnnmnnmnmnmmnnmnnmononoonnonononoonnonnonnononnonoonoonoononoononnoonoopoppopoopoopoopopopoopoopopopoopoopoopoopoopoppopopopooppoppoppopoopqpqqpqppqpqppqqppqppqppqqpqpqppqpqppqpqqpqpqqpqqpqpqpqppqqpqpqqppqrrqrrqqrqrqqrrqqrqrqqrqrqrq qrqrqrrqrrqrrqrrqqrqrrqrsrsrrssrsrssrsrsrrssrrsrrsrsrrsrrsrrsrrsrsrssrssrssrssrssrsrssrssrs ststtststsststsstsststssttsstsstssts stst tststtststtststsuututtutuuttuutututtuututtututut ututuututututututtuuvuuvuuvuuvvuvvuuvuuvuuvuuvuuvuuvuuvuuvuuvuvvuvuuvuvvuv vuvvuuvwwvwvvwwvvwvwvvwvwvvwvvwvvwwvw wvwwvwvwwvwvwwvwvwvwwvwwxwwxwxwxxwwxwxxwwxwxxwwxwxxwxwxwwxwwxxwwyx xwxxwxwxxwxxwxwx xwxwxwxxwxxyxyyxyxxyxyxxyxyyxyxxyxxyxyxxyx xyxyxyyx yxyxyyxyxxyxyyxYZZYZYYZYYZYZYYZZYZZYZYYZYZYYZYYZYZY Y!ZYZYZZYZZYZYZYYZYZ[[Z[[Z[ZZ[Z[Z[Z[Z[ZZ[Z[Z[ZZ[ZZ[ZZ[Z[[Z[ [Z[[Z[Z[[Z[[Z[[Z[Z\[\[[\[\\[\[[\[\[[\[\[[\[\[[\[[\[[\[[\[[\[\[\\[\\[\[\\[\\[\[\[\\[[\\[]]\]]\]\\]]\]\]\\]\]]\\]\\]\\ ]\]]\]]\\]]\]\]]\\]]\]\]\]\]]\]]\]]^]^]]^^]^]]^]^]]^]]^]^]]^]]^] ]^]^^]^]^ ^]^^]^]^]^]]_^^_^_^_^_^_^__^_^^_^_^^_^^_^^_^_^_^^_`_ _^_^__^_^__^_^^_^__`__`__``_``_``__`__`_``_`__`__``_`__`_`_`__`__`a``_``_` `_`_`_``_`__`__`a``a``a`a`aa`a``a``a`a a`aa`aa`aa``a`a`a`aa`aababbabaabababaabababaaba abacbbabbaba babbabbabaababababaabcbccbccbcbbccbccbbcbcbbcbbcbbcbbcbbcbbcbccbcbbccbccbccbccbccbccbcbccdcddcdccdccdcdccdcdc cdccdc cdccdeddcddcddcdcddcddcdccdcdcddcededeedeedeeddededeedeeddeddededdedeededdeddeddede edeedededdeddefeffefefeeffeefeffeefeefefefeefeefgffefeffe fefefeffeffgfggfgfggfgfgffgfgffgffgfgffggffg f gfggfggfgfggfgfggfgffgfgfgghghhghhgghhghghgghghhghgghgghghghgghgghgghghgghghghhghhghghghghhgghgihihihhihhihhihihih hihhihiihiihiihiihiihihiihiihiihihjjijjijiijijiijijjiijiijijiijiijiijij jijiijijijijjijijjkjkjkjkkjkjkjkkjkkjjkkjjkjjkjjkjjkjjkjkjkjkkjkkjkjkjkjkjjkjkkllkllkllklklkklkklkklkklkllkklkklkklkllklkl lklkllklklmlmlmlmmllmllmlmllmlmllml lmlmlmmlmmlmmlmmlmmlmmlmlmmlmmnmnmnmmnmnmmnmnmmnmmnmnmnmmnmmnmmnmmnmmn nmnnmnnmn nmnmnnmnnmnmnnmmnmnonoononnonnononnoononnonnonononnonnonnonnonnonoonoononnonononoononnoononononnoopopopoopoopoopopoopoopoppoo poppopopoppopopoppopooppqppqpqqppqpqppqqpqpqqpqpqpqqpqpqqpqpqppqppqpqppqpqppqqpqqpqpqpqppqpqqrqrqrqqrrqqrqrqrqrrqrqqrq qrsr rqrrqrrqr rqrrqrqrrqrrqqrqrqrqqrsrssrsrsrrssrrsrssrsrsrrsrssrrsrsrsrrsrsrrsrsrssrssrsrsrrssrssrssrsrssrrsrsrsstssttsttsttsts ststs ststtstststssttstssttststtututuututututtuututtuuttutuututtuttututtutuututuutuututtutuututututtuvvuvuvuvuuvuvuvvuuvuuvuuvvuuvuuvuuvuuvuuvuvvuvvuvvuvvuvuvvuvvuuvvuvvuuvwvwwvwwvwvvwwvwwvwvwvvwvvwvwvwvvwvwwvwwvvwwvwwvwwvwwvvwvwwvwxxwxwxwwxwwxwwxwxwxwwxwwxwwxww$xwxxwxwxwxxwxwxyyxyyxxyxyxyxxyxyxxyxxyxxyxxyxyyxyxxyxyyxyyxyxyyxyyxxyxyxx YXY YXYYXYXYYXYYXYYXYXXYXYZYZZYYZYYZYZYYZZYZYYZYYZYYZYZZYZYZYYZYYZYZYZZYZYZZYZZYZZYZYYZYZYYZYZY[Z[ZZ[Z[[Z[[Z[[Z[ZZ[Z[ZZ[ZZ[ZZ[ZZ[ZZ[Z Z[Z[Z[[Z[ZZ[[Z[Z[[Z[Z[[Z[Z[[Z[\\[\[\[\\[[\[[\[[\[\[[\[[\[[\[[ \[\ \[\ \[\[\[\\[\[\\[\\]\]\]]\]\\]\\]\]\]]\\]\]\]]\^]]\]\]]\]]\]]\\]]\]]\]]\]\]]\]\]]^]^^]^]^^]]^]^]]^]]^]^]^^]^]^^]^]]^^]^]^^_^__^_^_^^_^^_^__^^_^^_^ ^_^^_^__^ _^_^_^_^^__^__^__^__`_`_`_`__`__``_ _`_`__`__`_ _ `_` `_`_`_``_`_``_``_`_`__`_``__``a`aa``aa`a`aa``a`a``a` `a` `a``a`aa`a`aa`a`a`aa`a`aa`aababababaabaabaabbaabaabababaabaabab babbabbabbababbabbabcbccbcbbcbcbbcbcbbcbcbbcbccbbcb bcbcbbc cbccbccbcbccbcbcbccddcdcdccddcdcdcddcdcddcddcdccdcdccdccdccdccddeddcddcddcd dcdcdcddcddcdcdceddedeededdededdedededdededd edeedeedeedede edeedededdedeeffefeefeefeffeffeefefefeefeefeefeefefeeffeffeffefeffeeffefeefeffggffgfgfggfgffgffgffgffgfgffgffgff gfggfggfggfggfgfgfggfgfghghgghghghghhghhgghghgghhgghg ghgghgh hghhghghhghhghhghhghihhihhihhihhihiihihihhihhihihhihhihhihiihiihhiihiihiihihiihihiihihhijijjijiijijiijijiijiijii(jijijjijijjijijjkjkjkjkjjkkjkj jkjjkjkjkjkjkjjkj jkjjkjjklkklk kjk kjkkjkkjkkjjkjkjkkjjkkjkklkllkllkklkllklkkllklkklkkl klkl lkllkllkllklkklkklklkkllklklkllkllklkmmllmmllmml mlmllmlmllmlmlml lmllmmnm mlmmlmmlmmlmmlmmlmllnnmnnmmnmnmnmnmmnmnmnmmnnmmnmnnmnmmnmmnnmmnmnonnmnnmnnmnnmnmnmnnmnnmnmnonoonnoonononnoononnonoonnono non nono onoonoonononoonoonoononoonppopoopopoopoopoopoopoopopoopoopoopop poppoppopooppoppopqpqppqpqqpqppqppqpqppqpqppqqp$qpqpqqpqpqqpqpqqrqrqrrq qrqqrqrqqrqqrqqrqqrsrrqrrqrrqrqrqrqrrqrqqrqrrsrrssrsrssrsrsrrssrrsr rsrsrrsrrssrssrssrssrsrssrssrssrssrsrssrsrrsttsttststsststsststtsttstststsstsstsststtstststtsttststststtututtuttutuut tututtututtututu utuutu ututtututuuttvuvvuvuuvuuvuvuuvvuvuuvuuvuuvuvuuvuuvuvuuvvuvvuvvuvuvuv vwvwwvwvvwvwwvvwvwvwvvwwvvwvwvvwvwwvwwvwwv wvwwvxxwxwwxwxxwwxwwxxwxwxwwxwwxw wxwwxyxxwxxwxxwxxwxwxwxxwxxwxwwxwxyxyxxyyxyyxyyxyxyxxyxyxxyxxyxxyx xZY YXY YXYYXYYXYXYYXYYXYXYYXYYXYZZYZYZZYZYYZZYZYZYYZZYYZY YZYZYZYZZYZZYZ ZYZYZYZYZZYZZ[Z[ZZ[ZZ[Z[Z[ZZ[ZZ[ZZ[ZZ[ZZ[ZZ[ZZ[ZZ[\[[Z[[Z[Z[[Z[[Z[Z[[Z[ZZ[ZZ\\[[\[[\[\[[\\[[\[\[[\[\[[\[[\[\\[\[[\[\[\\[\\[\\[\\[\\[[\[[\\[\[\[\\]\]]\]\\]]\]\\]\\]\\]]\]]\\]\]\\]\\]\\]\\ ]\]]\]\]]\]]\]]\\]]\\]\]]\]]\\]\]]\]]^^]^^]]^^]^]^]^^]^]]^]^]]^]^^]]^]]^]]^]^^]^ ^]^]^]^^]__^__^__^^_^_^_^^_^^_^^_^ _^_^^__^__^__^__^__^^_^_^_^_``_``_`_`__`_`__``__`__`__`__`__`__`__`_``_``_``_``__``_``_``_`_``_`_`_`aa`aa`a``a`a`a`a`a`a`a``a`a``aaba a`aa`aa`a`a a`a`aababbaababababbababaabaabaababaabaabaabaababbabbabbabbababbabbabbabaabbabccbcbbccbccbcbccbbccbbcbbcbcbbcbbcbbccbbcb cbcbcbcbccbcbbcbbcddcdcddcdcdccdcddcdcddcdccdcdccdc dcd dcddcddcdcddccdccddcdcddcddcddeededeedededdedeededdededded dededeedeedeedeededeedeedeffeffeffefefeffeffeefefefeefeffefeffefeffefegffgffgffgfgffgfg fgfgffgffgffgfgff gfg gfggfggfggfggfgffggfggfggfghghhghhgghhghgghghghgghghhghghgghghhghghhghhghhghhgihhiihihihihhihihhi hih hihihhijiihiihihiihhihihiihiihhihiihihhijjijiijijijijijjijjiiji ijijiijjiijijiijij jijijjijjijjijjijijkjjkjkjkkjjkkjkjkjkjjkjkkjjkjjkjjkjjkjjkjkkjkkjkkjkjkkjkkjjkjkjkjlkllklkklkklkklklkklkklklkklkklkkllklk klklkllklkllklkllkllklmlmlmmllmmlmlmlmmlmllmllmllmlmllmllmllmlm mlmlmmlmmlmmlmmllmlmmnmmnmmnmnmmnnmmnmmnmnmnmnmnmmnmmnmnm mnmmnmmn nmnmnmnnmnnmnnmnmnmmnnmnmnmnmnmnmnonnononoonoononnononnononnononn ononoonoonononoononoonnonnoppoopoopopooppoopoopopoopoopopopoopo opoo pop poppopopoppopopoppoppopooppqqppqqpqqpqpqpqppqpqqpqppqppqpqpqppqpp qpq qpqqpqpqqpqppqppqqpqpqqpqpqprrqrqqrqrqqrqrqqrqr qrq q rqrrqrqrrqrqrrqrqqrssrssrsrrsrsrrsr rsrrsrrssrssrssrssrssrsrssrsrssrsrssrssrstststsstsstsstssts stsstsstsstsstststtststtssttsststtstsstsutututuutuutuututtuttututut tututtutututututuututuvuuvvuvuvuuvvuuvuuvuvuuvuuvuuvvuvuuvuvuuvuuvuv vuvvuvuvvuuvvuuvwwvwwvwvvwvvwvvwvwvwvvwv vwvvwvvwvwwvwvwwvwvwvvwvwwvwvwxxwwxwxwxwxwwxwwxwxwwxwwxwxwwxwxww"xwxxwxwxxwxwxwxxwyxyyxyxyxxyxxyxyxyxxyxxyxxyyxxyyxxyx xYXYXYXYXYXYXYYXYXYYXYXYXYYZYZZYZYZZYZYYZYZYYZYYZYZYYZYYZYYZYZZYZYZZYYZYYZYZZYYZZYYZYZZYZ[Z[ZZ[Z[ZZ[[Z[ZZ[Z[ZZ[Z[[Z Z[\[\[ [Z[Z[ [Z[[Z[ZZ[Z[[Z[[Z[Z[[\[[\\[[\\[\\[\[\[[\[[\[\[[\[\[ [\[[\[[\[\[\\[\\[\\[\\[\\[\[\\]\]]\]\\]\]\\]]\]\\]\\]\\]\]\\]\]\ \]\] ]\]]\]]\]\]\\]^]^]^^]^]^^]]^^]]^]]^]^]^]^]^] ]^]] ^] ^]^]^]^^_^_^^_^_^_^__^_^^__^^_^^`_&_^_^__^__^__^__^_`_`__`_``_`_`__`__`_``_`__`__`_`_ _`a` `_``_``_`__`_`_`_``_``_`__``_``_a``aa`a``a`aa``a``a``a``a``a`a``a`a``a`a``a``a`aa`a`aa`aa`a`a`aa`a``a`aa`abbabababbabaabababa ababaabbababcbbababbababbababbaabaabcbcbccbbcbccbbcbcbbcbcbbcbbcbbcbcbbcbc cbccbccbbcbccbccbbccbcbccdcdccdccdcdccdcdcdccdccdccdccdc cdcdccdcdcddcddcddcdcdcdccddcdedeededeeddededdededdededdeddedfeedeededeedeededeedeededeedeedefeefeffeefefeffefeefefefeeffeefeefeffeffefeffefeffeffefggfgffggfggfggfgffgffggffgfgfgffgffgffgffgffgfgfggfgfgfgfgfggfgffghghhghhghhghghhgghghhgghgghghg ghgghghhg hghhghhgghghghhgghihiihiihihhihihhihhihhihhiihhihhihiihihiihiihiihiihiihiihihjjijiijijjijiijijiijiijijiijijjijjijjijjijjijijijijijijjikkjkjjkjkjjkjjkjjkjkjjkjjkjjkjjkjkkjkjkkjjkjkkjjkjkjkkjkklklklkllklkklkllkllkklkklklkklk klkllklklklklkllkllkklklkkmllmlmllmlmllmlmlmllmlmllmllmllmlmllmlml l mlmmlmmlmmlmlmmlmmlmlmlmlmllmmlmmnmnmnmnmnmnmnnmnnmnmnmmnmmnmnm mnm mnmnnmnnmnmmnmnmmnmmnmnnoonoonoononononoononnonnonnon n onoonoonoonononoonoonoonoonononoopopoopoopoppopoppopopoopoopoopoppopoppopooppopqqpqqppqpqppqpqqpqpqqppqpqpqppqp pqrqqpqqpqpqpqpqqppqpqpqqrqrqqrqrrqrrqrrqrrqqrqrqqrqrqqrqqrqqrqqrqqrrqrqrrqrqrrqrrqrqrqrrqrrqrqssrsrrsrssrsrsrrsrsrrsrrsrsr rsr srssrsrsrssrsrssrsstststtssttsttstststsstststsstsststsstst tststtststtstssttstsststtsttutututtutututuututtuttut tutuutuutututuutuutuututuutututuutuuvvuvvuvuuvuvvuuvvuvuuvuuvuvuuvu uvuvuuvuvuvvuvvuvuvvuvvuvvwvwvwvvwvvwvvwvvwvwvwvvwv v!wvwvwwvvwwvwwvwvvwvwwxwxxwxwwxwwxwwxwwxwwxwwxwwxwxw wxwwxyxxwxwxxwxxwwxwxwxxwxxwxyyxyxyxyyxyyxyxxyxyxxyxxyyxy xyxxXYXXYYXYXYXYXXYXYXY XYXX YXYYXYYXXYYXYYXYXYXYYZYZYZZYZYYZYZYZZYYZYYZYYZYYZYYZYYZYYZYZZYZZYZZYZZYZZYYZYZYZZYZZYZZ[ZZ[Z[ZZ[Z[ZZ[Z[Z[ZZ[Z[#[Z[[Z[Z[[Z[\[\[\[[\[[\[[\[\[\[\[[\[\[\[[\[\[\\[\\[\\[\\[\\[\\[\\]\\]\\]\\]\\]]\\]\]\]\\]\\]\]\]]\]]\]]\]\]\\]]\]]\]^^]]^]^^]]^]]^]]^]]^]]^^]]^]]^ ]^]]^]^^]^^]^]^]]^]^^]^^]]^^]^^]^_^__^_^_^^_^_^__^_^^__^_^_^^_^^__^ ^_^__^__^_^__^__^`_`_``_`_`_`__``__``__`_`_`__`_`_``__`__ `_` `_` `_ `_`_``_``a`aa``aa`aa`a`a``aa`a``a`aa`aa`aa`aa`aa`aa`abababaabababaabaabaabaab abaabcbbabbabbabbabbabbabbaabbabbababbabbccbcbbcbbcbccbcbccbccbbcbcbcbbcbbcbbccb bcbccbccbcbcbbccbccbbcbbccddcdcdccdccdcdcdccdccdcdcd dcddcddcddcddcddcddcddcdeddeddeddeddeddedeededdededdeddeddeddedd ededeedeedeededeedeedededeedfeffefefeefeeffeefeefeefee feffeffeffefeffeffeeffeffeffefeefeefefefggfgfggfgffgfgfggfgffgfgffgfgffgffgffgffggfggfgfggfggfgffgffhhghhghhghgghgghgghhgghghgghggh ghghgghghhghhghhghhghghghhghhgghgiihihihhihihihhihiihihihhihhihhihh,ihiihihihhihiihiijjijjijjiijijiijiijijjiji ijiijijijjij jijjijijiijijjkkjkjjkjkjjkjkjkjkjjkjjkjkjjkjjkjjkjjkjkjk kjkkjjkkjkjkkjkjkkjkjjklklkklklklklklkklklkklklkklk klkllklklkllkllkllkmlmmlmlmllmlmmllmllmlmllmlmllmllmll!mlmlmmlmmlmmllmllmllmnmnmmnmmnnmmnmmnmmnmnmmnmmnmnmmnmnnmnnmnnmmnmnnmnnmnmmnnmnmnmmnmnnononnonoononononnonnonnon nonoonnopo onoonoononoononoonoonopooppopooppopoopoppoopoopoopoopooppopoppoppopopoppopooppqpqpqqpqppqpqpqppqppqpqppqppqppqpqp p&qpqqpqpqpqqppqqrqrqrqrqrqqrqqrqqrqrq qrqrrqrrqrrqrrqrqrrqrrqrqrqrrqrqrqrqsrssrsrrsrrsrsrsrrsrsrrsrr srssrssrsrssrsrrssrsrsrrsrtstsststsststssttsstsstsstsststs stss tst tsttstststtsttststtssttstsuututtuttututtuttu tuttu tuttutuutuutuututu utututuututvuvvuvvuvuuvuvuvuuvuuvuuvuvuuvuuvuvvuvuvvuvuuvuvvuvvuvvwvwvwvwvwvwvvwvwv vwvvwvwvvwvvwvwwvwwvwwvwvwvwwvwwvwwvvwvwwxwxxwxwwxwxwxwwxwxxwwxwxw wxwwxwwxwxxwxxwxwx xwxwxxwxwxxwwxxwxxwxxwYXYXYYXYXXYYXYYXXYXYYXXYXYXXYXX YXYYXYYXYYXYXYXYYXYXYXYYXYXY YZYZYZYZZYZYZZYZYZY YZYYZYYZYZZYYZZYZYZYZYZZYZYZZYYZZYYZZ[Z[Z[Z[[ZZ[[Z[Z[ZZ[Z[Z[[ZZ[Z[[Z Z[Z Z[\[[Z[ZZ[[Z[[Z[[Z[ZZ[[Z[[Z\[\\[\[[\[[\\[\\[[\[\\[\[\\[\[[\\[\[[\[[\[[ \[\\[\[\\[\\[\[\\[ \[\\[]\]\]\]\\]\\]\]]\\]\]\\]\]\\]\\]\\]\\]\\] \]\]]\] ]\]]\\]]\]\]]\]]\]^]^]^^]]^]]^]^]]^]^]]^]]^] ]^]]^]^^]^^]^]^]^]]^]^_^__^_^^__^_^_^_^_^_^^_^^_^_^_^^_^_^_^^ _^__^_ _^__^__^__^__^_^^_^_^__`_``_``_`__`_`_`__`_`__`__`__`_` `_`_`__``_`_``_``_`_`_aa`aa`a`a``a``a `a``a `a`aa`aa`aa`aa`a`aa`a`a`aa`a`baabbababb ababaabaacb bab babbabbabab babbcbcbcbbcbbcbbcbccbbcbbcbbcbbcbbcbbcbcbbcdccbccbcbccbccbcbccbccbccbccbbcdcddccdcddcdccdccdccdcdcdccdccdccdccdccdcdccdcd dcddcddcddcddcddcdcdccddcddcdcdcddccdcdcddeeddedededdededdedededde dede edeedededeedeedeedeefeffefefeefeffeffeefeefefeefeefeefee%fefefeffefeffefefeffgffggffgffgffgffgffgffgffgffgffgf fgfggfggfggfggfggfggfggfgfghhghgghgghghgghgghghghghhgghgghghg ghgghghghhghhghhghghhghhghhghihhiihhihihiihihihhihhiihhihhih hih ihiihihihhiihiihiihiihjjijijjiijijiijijijijjiiji ijkjjijijiijijjijijjijjiijjijjijjkjkjjkjkjkkjjkjjkjkjjkj jkjkkjkkjkjkkjkjjkjkjjkjjkjkkjjklklkklkklkllklklkllkklkklklk klkklkkllkllkllklklklkllmlmlmmlmllmmllmmlmmlmlmlmllmmlmlmllmmlmlmmlmmlmllmllmmlmmlmlmmlmmnmnmmnnmnmmnmnmmnmnnmnnmnm mnmmnmmnmnmmnmnnmnmmnmnnmnmnnmnnoonononoonoonnoonononnononn onono onoononoononoonnonoononppopoppoppoopoopooppoopopoopoopopo poppopoopooppopqpqpqpqppqpqqpqqpqppqqpqqpqp pqpqppqp pqpqqpq qpqppqpqqppqpqqrqrrqqrrqqrrqrqrrqqrrqrqqrqqrq qrqqrqqrqrrqrrqrrqrrqrrqrqrqrqrrqrsrsrssrsrrsrrsrsrrsrrsrrsrrsrrsrrsrs srsrssrsrssrsstststtsttssttsststtstsststsstsstsststsststtsttsttststtsttssutututtutututututtuttuttuttuttuttuttuttututuutuutututtuututuuvuvvuvuuvuvvuvuuvuvuvvuuvuvu uvuvuuwvvuvvuvvuvvuvuvuvvuwvvwvwvwwvwvwvvwvvwvwvwvvwvvwv v wvw wvwwvwvwwvwwvwwvwvwwvwxwxxwxwwxwxwwxxwxxwxwwxwxw wxwxwwxwxxwxwxxwxxwxxwxwxxwxxwwxwxxwxwXYXXYXYXXYXXYXYXYXXYXYXXYXYYXYXXYXXYXYYXYYXYYXYYXYYXYYXXYXXYXYYXYXZYZZYZYZYYZYZZ YZYYZYZYYZYZ ZYZYZZYZYYZYZ[Z[ZZ[Z[[ZZ[Z[Z[ZZ[Z[Z[ZZ[Z Z[ZZ[Z[Z[[Z[[Z[[Z[ZZ[\[\\[\\[\\[[\\[[\[\\[[\[\[[\[[\[[\[[\[\ \[\\[\[\\[\[\\]]\]\]\\]]\]\]\]\\]\\]\]]\]\\]\\]\\]\\]\\ ]\]]\]]\]]\]]\]]\]]\]]\\]\]\]\]\]]^]]^^]^]]^]^^]^]]^^]^]]^]]^]^]^]^]^^]^]^]^^]^^]^]^^]]__^_^^_^_^_^_^^_^_^ ^_^^_^^_^_^^_^^_^__^__^_^_^__^_^_^__^_``_`_`__`__`_`_`__`_`__`_``_`_``_`__`__ `_``_``_``_`_``_``_``_`__``_`__``_``a`a`a`aa`aa`a``a``a`a``a` `a`a a`a`aa`aa`aa`aa`a`abbababaababbabaabaababaabbaaba ababbaabbabbabbabbabaabbaccbbcbbcbccbbcbcbbcbccbccbbcbcbcbbcbbcbbcbbcdc cbcbccbcbccbccbccbccbcbbccdcdccdccdccdccdccdccdcdcdc cdcdcddcdcddcdccdcddeddeedeeddeeddeded deddedededded defeede edeedeedeedeedeedffefeefefefeefefeefefeffeefeefeefee feffefefeffeffeffeefggffgfggfggfggfggffgffgffgffgfggf fgfg gfgfgfggfggfggfgfggffghgghghghgghgghghhgghghgghgghghghgghgghgghgh hghghhghhghhghghgiihhiihhihhihhihhihihiihhihhih hihhihhiihi ihiihiihihiihihiihihhihhijijiijijjijijiijjiijiijiiji ijiijjijjijjijjijiijijjijjijijijjiijjkkjkkjkjjkjjkjkjjkjkjjkjkjjkjjkj jkjkjkkjkkjkkjklklkklkklklklkkllklkklk klk klkllklkllklkllkl lkllkllkllkklkmllmlmlmllmllmllmllmllmllmllmllmlmllmllmlmmlmmlmlmlmlmnmnmnmmnmmnmnmmnmnmnmnmmnmmnmnmmnmm nmnnmnnmnnmnnmn nmnmnnmnmnmnnoononnonnoonnoonnononnonoononnon npo onoonoonoonoonoonoonoonoonoonoonnooppoopopopoppopopooppopo"opoppopoopoppooppopoppoppoppoppqpqqpqqpqqpqppqppqppqpqpqqpqpp qpqqpq qpqqpqqpqppqqprqrqrqrqqrqrqrqqrqrqrqqrqqrqqrqrrqqrqrqqrrqrqrrqr rqrrqrrqrrqrrqrsrsrrsrrsrssrrsrrsrssrrsrsr rsrrsrssrssrsrssrssrsrsstsststtsststtsttstssttststs stsststtut!tstststssttsutututtututtututtututtuututtuuttututtutuututuutuutuututuutuututuvuvvuvvuvuvuvvuuvuuvuuvvuuvu uvuuvuuvvuvvuvuvvuvuvvuvuvvuvvwvvwvwvwvwwvwvvwvwvvwvvwvvwvwvvwvwvwvwwvwwvwwvwvwwvwwvwwvvwvwvxxwxwxwwxwwxxwxxwxwxxwwxwwxwxwxxwxwwxwwxwwxwxwxww xwx xwxxwxxwxwxwwxwxxwXYXXWXXWXWXWXWXWXWWXXWXXWXXYXYYXXYYXXYXXYYXYXYXXYXXYXXYXYXYYXYXYXYYXYYXYXXYXYXXYXYYXYYZYZYZYYZYZZYYZYZYZYYZYYZYYZYZZYZZYZZYZ ZYZZYZYYZYZY[ZZ[Z[ZZ[[ZZ[Z[ZZ[ZZ[ZZ[Z[ZZ[Z[[Z[[Z[[Z[Z[[\[\\[\\[\\[\\[[\[\[\[[\[[\[[\ [\[ [\[\\[\\[\[\\[\\[\[\\[\[\\[[\[\\[\]]\\]\\]\]\\]\]\\]\\]\\]\\]\\]\\]\]\\]\]\]]\]\\]\]]\]\]]\\]^]^^]^^]^]]^^]]^]^^]^^]^]]^]]^]]^]^]]^ ] ^]^^]^]^^]^]]^]^]^^]^]^]^^_^_^^_^^_^^_^_^^_^^_^^_^^ _^__^_ _^_^^_^_^^__^_^__^__^^__`_``_`__`_`_`__`__``_``_`__`_`__`_`_`_`__`__`_`__`_`_``_ `_``_``_``a`aa`aa`a`a` `a``a`a``a``a``a`aa`aa`aa`a`a`a`a`a`abbaababbababababbabbababaababaabaabaabaababbabbababbabbabababaababbabacbccbccbbccbcbbcbcbbcbccbcbbcbbcbbcbbcb bcbcbcbccbccbccbccbcbbcbcdcddcddcdcddccdccdccdccdcddcdccdccdccddcdccdccdcddcddcdcddcddcdcdcddededdededdededeeddeeddeddededdededdeedeedeedeedeededeffefeefeffeffefefe efefefeefeffeffeeffefeffeffgfggfgffgffgffgfggffggffgfgfgfgfgffgffgff gfgfggfggfg gfggfgfgffggfggfgghgghghghhghgghgghghghgghgghgghgghgghgghhg ghghghghhghghhghghhghghhghghghhihhihihihiihhihhihhihihhihhihih hihhihihihihiihiihihihiijijijjiijiijjiijiijiijiijiijijiijiij jijjijjijjijjijjijjijijjijiijijijjijjijjkjkjkjkkjkjjkjkjjkkjkkjjkjkkjkjjkjkj jkjkkjkkjkkjkkjkjkkjkkjkkjklklkllkkllkklklkllklklkklkklkklk klkk lkllkllkllk lklklklkllmmlmlmllmllmlmllmlmmlmllmllmllmlmllml lmllmmlmmlmlmmlmlmmlmmlmmlmmlmlmmnmmnmnmnmmnmmnmmnmnmmnmnm m nmnnmnnmnnmnmnnmnmnnmnnmnnmnononnoononononnonnoononnonnononnonnonoonoonoono onoononoonoopopopopopoopopoopoopopoppoppoppoppoppoppoopoppopooppoppqpqpqppqqppqqpqppqpqqpqppqpqppqpqppqpqqpqqpqqppqppqqpqqrqrqrqrrqrrqrqrqqrqrqqrqqrqqrqqrq qrqrqrrqrrqrrqrrqrrqrrqrrqrrsrrssrrsrrsrrssrsrrsrrssrrsrrsrr srssrssrssrsrssrs srs srssttsttststssts stststsststtststtsttsttststtstuuttuutuuttuttuutututtuttututuuttututtuutt utuutuuttuutuutuututtutututuutuuvuvuuvuuvuvuuvvuvuuvuuvwv vuvuvvuv vuvuuvuuvvuvuvuvuvvwvwvvwvwwvwvvwvvwvvwvvwvwvwwvwwvwvwwvvwvwvwvwvwxxwxwxxwxwwxwxxwxwwxwxwxxwwxwwxwwxw w XWXXWXWXXWXXWXXWXWXWXXWXYXYYXXYXYXYXYXYXXY XYX X YXYXYYXYYXXYYXYXYYXYYXYYXXYXXYYZZYZZYYZYZYZZYZZYYZYZYZYYZYYZZY YZYYZYYZYZZYZZYZYZYYZYZZY[Z[Z[Z[ZZ[Z[ZZ[ZZ[[ZZ[Z Z [Z[[Z[Z[[Z[Z[[Z[[Z[Z\[\\[\[[\[[\[\[[\[\\[[\[[\[[\[ [\[[\[\[[\[[\]\\[\ \[\[[\[\[[\[\[[\]]\]\]\\]\]]\]\ \]\]\\]\\]\\]\\]\]]\\]\]]\]]\]]\]\]]\]]\]\]]^]^]^]]^]^^] ]^]^]]^]^] ]^]]^^]]^_^^]^^]^]^^]^]^]^^]]^]^]]^]]^]^^]^_^^_^^_^_^_^^_^_^^_^^__^^_^^_^_^^ _^_ _^__^_^^__^__^ _^__`_`__``_``_`_`` _`__`_`_``__``_``_``_``_``_``_`_`a`a``a`aa`a`a`a``a`a``a`a``a``a``a`a``a``a`aa`a a`a``a`a`aabababababababaababababaabaabba abaabaabaababbabbababbababbabbabbabbabccbccbbccb bcb bcbbcbbcbbcb bcbccbccbccbccbcbcbcbccddcdcddccdcdcdcddc cdccdccdccdccddcd dcddcddcddcddcddcddccddcddceededdeddedededeeddedededdededdededdeeddededeededdeedeedeededeededdefefeefefeeffeefeffeeffeefe efeefeefeefeefeffeffeffefeffefeffefeffefeefgfgffgfgffgf fgffgfggffgfgfgffgffgffggfgfgfgfgghgghhghghhghghh ghg hghhghgh hghhghhghghhghghhghhihihihhiihihiihhihhiihihihiihihih hihhihihiihiihiihihhihihhijjijiijijiijiijiijijiiji ijiijijjijjijjijjijjijijjikjkkjjkjkkjkjjkjkjjkjjkjjkjjkjjlklkkj kjkkjkjkkjkjkjkjkjkllklkklkklklk klklkklkk$lkllk lkllklklmllmmlmlmmlmlmlmllmlmllmllmllml lmlmmlmlmllmlmmlmmllmmlmmnmmnnmnmnnmnmmnmnmmnmnmmnmmnmmnmn nmnnmnmnnmnnmnnmnmonononoonnonoononoonnononnonnononnononnonoonoonoono onoononoonnoonooppopopopoopopoopoopopoopoppooppopoopoopoopoppoppopoppoppoppoppoppoppqqppqpqppqpqpqppqpqppqppqppqppqppqppqp qpqqpqpqqpqqppqqpqppqqpqppqrrqrqqrqqrqrqqrqrqqrqqrq qrqqrqq rqrrqrqrrqrrqrrqrqqrqqrqqrrqsrrsrsrsrrsrrsrsrsrsrrsrsrrsrsrsrrsrsr rsrssrsrrssrrssrsrssrsrssrsrrsrsrsrrstsstssttssttststststtststststsstsstssts ststtsttststtsttsttsttstutuututtuuttutuutututtuttut tutu utututuutuutuutuutuutututuuvuuvuvuuvuvuuvuvuuvuvuvuuvuuvuvvuvvuvuv vuvvuvuuvuuvuuwvwvwwvwvvwwvvwvwvwvvwvvwvv wvwwvwwvwvvwwvvwwvwvwwvwvwwvwwvwvwwvwxxwxwwxwwxwxwwxxwxwxwxwwxwxwwxwwxwwxww XWXXWXXWWXXWXXWXWWXWWXWXWXXYXYXXYYXYYXXYXXYXXYXYXYXXYXYYXXYXXYXYYXYYXYYXYXYYXYYXYXYXYXYYXYYXYZYZYZZYZZYZYZZYZYZYZYYZZYYZYYZYYZYZZYZZYZYZYZ[Z[Z[Z[[ Z[ZZ[ZZ[ZZ[Z[[Z[[Z[ZZ[Z[Z[[Z[Z[[ZZ[ZZ\[\[\\[\\[[\\[\[\[\[[\[[\[[\[[\[\[\[[\[\[[\]\\[\\[\[\\[\\[\[\\[\\[\[\\]]\]\\]]\]\]\\]\\]\]]\]\\]\] \]\\]\]]\]]\]]\\]]\]\]\\]\]]\]\]]\]\\]\\^]^]^^]^^]^^]^^]]^^]]^]]^]]^^ ]^]]^]^]^^]^]]^]^]^^]^^]^]^^]^]]^^_^_^_^^_^_^__^_^^_^_^^_^^_^^_^_^ ^_^^_^__^^_^__^ _^_^_^__^__^__``__`_`_`__`_`_`__`_`_`__`_`__``_ _`_``_`_`_``_`_``__`__`_``_`__``aa``a``a`a`a``a``a``a``a``a`a`aa`a`aa`a`a`a``ababbabaabababbabaababaabaabcbbabbababbababababccbccbcbbcbbcbbcbbcbbcbbcbcbbcbcbccbccbccbcbccbbcbbcbccbccbccdcdccddccddcdcdcdcdcdcdccd cdcdcdcdcddcddcddcdcdcdccdeddededeedededdeeddeddededdedd edeedeedededdedeedeededeeddedeedeefefefeeffeefeefeffeefefeefefeefeeffef fefeffeffef feffeffggfggfgfgfggfggffgfgffg fgf fgfggfggfgffgfggfggfghghgghgghghgghgghgghgghgghgghghghghghhghhghghhghhghgghhihiihiihhiihihiihihihhiihhiihihhihiihiih ihihihhiihjjiijiijjijjijiijijiijiiji ijiijiijijijjijjijijijijjijjijkjkkjkkjkjjkjjkjkjjkjjkjjkjjkjkjkkjkjkkj kjkjkkjkkjkkjkkjkjkkjkkjkkjjkjjkkllklklkklklkklklkklk klklkklkllklklklklkklkllkkmlmlmmlmlmlmmlmlmmllmllmllmllmlmllmlmmlmlmmlmlmllmlmmllmmllmllmlmllmlmmlmnmmnmnmnmmnmnmnmmnmmnmnmnmnmnmmnm mnmmnnmnnmnmnnmnnmnmmnnmnmmonnoonoononnonononnononnononnonnonnonno onoonoonoonononnononoonoonnonoonoopoppopopoopoopoopoopoopoopoppoppoppoppopopoppopoppoppoppopqpqqpqppqpqp pqppqpqppqppqp pqpqqpqpqqpqqpqppqqpqqpqpqppqrqrqqrqrrqqrqrqqrqqrrqrqqrqqrqrqrrqq rqrrqrqrqrrqrqrqqrqrsrsrsrrsrsrsrrsrsrssrsrsrsrrsrssrssrssrs srssrrsrrssrsrrsrsrrtststsstststsststsstsstsstsststtsttssttststtsttsttsstststtstuutututuututtututtuuttuttututututuuttuttuvuutuutuututuutuutuututtuutuuvvuvuuvuuvuuvuuvuvuuvuuvuvuuvuuv uvuvuvvuvuvuvvuvuvvuvvuvuvvuuvvuvuvvwvwvvwvvwvwvwvwwvvwvvwvwwvwwvvwv wvwvvw wvwwvwwvvwvwwvwwvwvwwxwxwxwxwwxwwxwxwxwwxwwxwwxwwxwwxxwwxwwXWXWXWXXWXWXXWXWXWXWWXWXWWXWWXWXXWXWXXWXWX XWXWXXWXWXXYXYXYXYYXXYXYYXYXYXXYXYYXXYXXYXYZYYXYXYYXYXYYXYYXYXXYYXYXYXXYXZYYZYZYYZYYZYYZYYZYYZYYZZYZYZYYZYYZYZYZZYYZYY ZYZ ZYZZYZYZZYZYZYZZYZYZYZZY[ZZ[ZZ[Z[Z[[Z[[ZZ[[Z[ZZ[Z[[ZZ[[Z[Z[[Z[ZZ[ZZ[Z[ZZ[Z[Z[ [Z[[Z[[Z[Z[[Z[Z[Z[Z[\\[[\[\[[\[\[\[[\[[\[[\[[\[[\\[\ \[\\[\[\\[\\[\\[\[[\[\[\]\\]]\\]\]\\]\]\]\\]\\]\]\\]\\]\]\\]]\]]\]\]\\] ]\]\\]]\]\^^]^]]^]]^]]^]]^^]]^]]^]]^]]^]]^]]^]]^]^^]^]^]^]^^]^^]^_^_^__^^__^_^^__^_^^_^_^^_^^_^_^^_^^ _^_^__^__^__^_^^__^_^__^_`_` _`__`_``__`__`__`_`__`a``_`_`__`_`_``_`_`_`_`__`aa`aa`aa``a`a`a``aa``a`a`a``a``a` ` a`a a`a a`a`aa`aa`aa`aa`ababaabababababbaabaabcbbabbabbabbabababaabababaabbabbaabbccbcbccbbcbccbccbcbbccbbcbbcbbcbbcbbcbbcbbcbcbcbbcbbcdccbcbccbccbcbcbcbccbbcddcdccdcdccdcddcdccdcdcdcdccdccdcdccdccdccdcddcd dcddcddcddcddcddcdcddededeedeeddeddededdeddeddeddeddeddedeedeedeedeedededdedefeefeffeeffeffeffeeffeffefefefeefe efeffef feffeffeffefefeefeffeefeggfggffgffgfgfggf fgfgfgfggfggfgffgffgffghg gfggfggfggffggfg gfggffgffggfgfghghgghhghghgghgghgghgghghgghghhghgghgghghhghghhghhghhghghhghhgghhghgghhihhiihiihiihihhihhihihhihihih hihhihiihiihiihiihihhiihhihhihihhiijjijjiijjijjiijiijijijiijiijiijiijiji ijijjijjijijjiijijjiijiijjikjkjjkjjkjkkjkkjkjkkjkjkjkjjkjkjkjjkjkjjkjjkj jkjkkjkkjkjkkjkkjkjjlklklkklklkkllkklkklkklklkklklkklkllkllklklkklklkklklmmllmlmlmmllmlmmlmllmllmllmllmlmlmllmllmlm mlmmlmlmllmlmmlmlmmlmlmlmlmmlmnnmnmnnmnmnmmnmnmmnmmnmmnmnmmn mon nmnnmnmnnmnnmnnmnnmmnnmnmnnmnmnnmnonnoonnononoonoononnononnonnonoononoononoononoonoononoopoopopoopopoopoopopopooppooppoppoopoo"popoopoppoopoppopopopooppoqqpqqpqpqqpqpqpqppqppqppqpqppqppqp p qpq qpqpqqpqpqqppqqpqqpqqpqqrqqrqqrqqrqqrqrqrqqrqqrqqrqrrqrrqrrqrrqr rqrqrrqrrqrrqrsrsrssrrsrrsrsrssrsrrssrrsrrsrrsr rsrssrssrsrssrsrrsrsrststsstststsstsstststsstststtststtststtsstststtssttututtuutututtututtuttuttuttut t utuutuutuutuutuuttuttuuttututtuututuuvuvuvuuvuuvuuvuuvuuvuvvuvuuvuvuuvuvuv vuvvuvuuvuvuvvuvvuuvvuuvvuvvwvvwvwwvwvvwwvwvvwvwwvwvvwvwvvwwvv wvw wvwwvwwvwwvwvwwvwwvwvWXXWWXWXWWXWXXWWXWXWWXWWXWXWWXWWXWWXWXWWX XWXWXWWXWXWXXWXWWXWXXYYXYXYYXYXXYXXYXXYXYXXYXYXYXXYXYXXYXXY YXYYXY YXY YXYXXYXXYXYYXYYZZYZYZYZZYYZYZYZYYZYZYZYYZYYZYZZYYZYZYYZYZYZYZZYZZYZZYZYZZYZ[Z[[Z[Z[ZZ[ZZ[[Z[[Z[ZZ[Z[Z[[Z Z[ZZ[ZZ [Z[Z[[Z[Z[[Z[Z\[[\[\\[\[[\[\[\[[\[\[[\[\\[ [\[\[\[\\[\\[\\[\[\[[\[\[\[\\[\\]\]]\\]\]\]\]\]\\]\\]\]\] ]\]]\]]\]]\]]\]\]\]^]^^]]^]^]]^]]^]]^]]^]^]^]]^]]^]]^]]^]^^]^]^]^^]]^^]^]^^_^_^_^^_^^_^_^^__^^_^_^^_^^_^^ _^__^__^__^__^__^__^_^^_^_``_`__`_`_``_`__`_`_`_`_``__`__`__`__`_`_``_` `_``_`_`_`__``_`aa`aa`aa`a`aa`a`a``a``a`a``a``a`a`a`a`` a`aa`aa`a`aa`aa`aa`a`a``aa`a``aababbabbabbababaabaabaabaabaabaa babbabbaabbababbabbabbabccbccbcbcbcbbcbccbbccbccbccbbcbcbbc bcbbcbbcbccbccbccbcbccbccbccddcdccdcdcdccdcddcdcddcdcdccdcdc cdcc!dcdcd dcddcdccdeddedeedededdededdeddeddededdeddeddedeedeedededeedededeededefefefeefefeffeefefeefeefeefeef e*fefeffeffefefgffgfggffgffggfgffgffgffggfggffgffgff gfggfggfgfggfgfggfggfhgghhghghgghgghgghgghg ghgghghhghhghgghghhghhghgiihihhihhihiihhihihhih hihhihhihhihiihiihiihiihiihihhihiihiihijjijiijiijijjiijjijijjijiijiijiijiiji ijiijijjijjijjij jijjijjijijjijijjijijjk kjkjjkjkjjkjjkjkjj kjkjkkjkkjkkjkjkkjjkjkkjkkjkklkklkllkllklkllkklklklkllklkklkklkllkllkllkklkklkkllkklkllmlmmlmlmmlmllmllmllmlmllmllmlmllmlmllmlmmlm mlmlmllmlmmlmlmmnmnnmmnmnmnmnmmnmnnmnmnmnnmmnmmnm mon nmn nmnnmnnmnnmnnmnnmnnmnnmnmnnmnmoonoononononnonnonnononnonnonnonoon ononoonnonoonoonoopoppoopoppopoopoopopoopopopoopoo poppopooppopoppoppoppoppoppoppoppqppqppqpqqpqppqqppqppqppqpqppqpqqpqqpqpqqpqpqpqqpqpqpqppqrqqrqrrqqrqqrqrqrqrqqrqqrqrqrrqrrqrrqrrqrqrrqrrqrqqrrqqrqqsrrssrrsrrssrrsrrsrsrsrsrrsrrsrssrsrsrssrssrrsrsrsstssttststsststsstsstts stsstssts s tstst tststtsttststtststtssttuutututtuutututtuttuttuttuttuttuutut utuutuututtuutuvuuvuuvvuvuuvuvuuvuvuuvuuvuuvuu vuv vuvuvvuvvuvvuuvuvvuvvwvvwvwwvwwvvwvvwvvwvvwvwwvvwvwvv wvwwvwwvwwvvwwvwwvwvvwvwvwwvwvWXWXXWXWWXWXWWXWXXWXWWXWWXWWXWWXWWXXWWXW WXWXWX XWXXWXWWXWXWWXXWXXYXYYXYXYXXYXXYXYXXYYXXYXYYXXYXXYXXY XYXYYXYYXY YXYXYYXYYXYXYYXYYXYYXZZYZYYZYZYYZYZZYZYZYYZZYYZYYZYYZYYZYYZYY ZYZ ZYZZYZZYZYZZYZYZYZYZZ[ZZ[ZZ[Z[Z[[Z[ZZ[Z Z[ZZ[ZZ[Z[ [Z[Z[[Z[Z[[Z[\[\[\\[[\[\[[\[\[[\[\[[\[[\[[\[\\[\[\\[\\[\[\\[\[\[\[\\[\\]\]\\]\]\\]]\]\]]\\]\]]\\]]\ \]\\]^]]\]]\] ]\]\]]\]]\]\]]\]]\]]\]\^^]^^]^]]^]^]^]]^]^^]^]]^]]^]]^]]^]^ ^]^]^^]^^]^]^^]^]^^_^_^^__^_^_^__^^__^_^^_^^_^_^^_^^_^^_^__^__^_^__^__^__^__^^__^_^__^__`__`_`_`__`_``_`_`_`__`_`__` _`__`_`__`_``_`_``_``__``_`_`_``_a`a`aa`a``aa`a`aa`a`a``a`a`a``a``a``aba`a a`a``a`a``a``aa`a``aa`ababbabbaabbabaabaabaababbabaabaababa abababbabababbabbabbaabbacbccbcbbccbcbcbbccbbcbbcbbcbbcbcbbcbbcbc cbccbccbcbc cbcddcddcddccdccdcdcdccdccdccddcddccdcddcdcddcdcd dcddcdcdcdcdcddcdcddccedeededeededeedededdeddeddededeeddeedeedeedeedeedededdeededeededdeffefeeffeefefefefefeefeefeefeefeffeffeffeffeffeffeffefeffeffeffgfgfgfgffgffgfgfgfggffgffgfgf fgfggfggfggfgfggfggfgfggfgghhghghgghghgghg ghgghg ghghhghghhghhghghghhgghgghghhiihiihiihihhihihhihhihhihhihhihhihhihihi ihi ihiihiihiihjiijiijjijjijjijijijjijiijiijiijiijiijijijjijjij jijijijiijiijkkjkjjkjjkkjjkjjkj jkjjkjjkjjkjjkjkkjkjkkjkjkkjjkjjkjjkjjkllkllklklkklkklkkllkllklkklkklkklkklkk lkl lkllkklklkklklkllkllklkllkkllmllmllmlm lmllmllmllmlmlmmlmlmlmmlmlmmlmmlmllmnmnmnmnmnnmnnmnmmnm mnm mnmnnmnmn nmnmnmnmnnmnmmnmnonnonnonnonoononnononnononnonnonnonnonon n onoonoonnonoonoonononnpoppoppoopoppopoopoppopooppoopopo opoo pop poppoppoopooppoppopopoopopqpqpqpqqpqpqppqpqp pqpqppqppqppqpqqp qpqpqqpqpqpqqppqpqpqqrrqrrqrrqrqqrqrrqrqqrqqrqqrqqrqrrqrrqrqrrqrqrrqrrqrqrqrrqrssrssrsrrssrssrsrsrrsrrsrsrrssrsrsrrsrsr r srs srsr srsrs srsrttstssttststststsstsstsststsststsstssttsttst tsttsttsststtsttsttsttuuttuttututtuututtuutututtuttuttutuutuutuutututtutuutuvvuvvuvuvvuuvvuvvuvvuuvuuvuuvuuvvuuvuuvuvvuvuvvuvuvvuvvuvuuvvuwvwvvwvvwwvvwvwvvwwvwvwvvwvvwvvwvwwvwvwwvwwvwwvwwvwwvwwvvwvwwvwwvvWVWWVWWVWWV WVWWVWXWXXWXWWXWXXWXWWXWXWWXWXWWXWWXWWXWXWWXWWXWXXWXXWXXWXXWXWXXWXXWXXWXXWXXWXXWXYYXYXXYXYXXYXXYXYYXXYXXYXYXYYXYYXYYXYXYYZYZYZZYZZYZYZYYZYYZYYZYZYYZYYZYYZYZ ZYZYZYZZYZYYZYZZ [Z[Z[Z[ZZ[ZZ[Z Z[ZZ[ZZ[Z[ZZ[[Z[Z[Z[ZZ[ZZ\[\[\\[\\[[\[\[[\[\[\[[ \[\ \[\\[\ \[\\[\[\\[\\[[\[\\]\\]\]\]\\]\\]\]]\]\]\]\]\\]\ \]\\]\]\]]\]]\]]\] ]\]]\]\]]\]]\]]\]]^^]^^]^]]^]^]^]]^]^]^]]^]]^]]^]] ^]^^]^^]^^]^^]^^]^^]^^]]^^]^]^]^]]^^_^^_^_^_^^_^^_^__^_^__^^_^^_^^ _^__^__^__^__^__^__^_^_^__^__^__`_`_`_``_`__`__``_``__`__`_`__`_`__`__`` _`a``_``_``_``_``_``_``_``__`_``_`_`a``a``a``a``a``aa``a`aa`a``a`a`a``a`aa`a`aa`a`a`a``a`bbababbababbaabaab ababaabaaba ababbabbabbaababbababaababbabcbccbcbcbcbcbbcbbcbccbccbcb bcbccbcbcbccbccbcbcbcbccbdcdcdcdcdcddccdccdcdc cdc dcddcddcdccddcdcdccdccddcddcedededdededdeeddededeeddededeeddeddedeededd edeedeededeedeedeededdeeddeedeededeefeffeffefeefeefeefeefeefefefeeffeefe efeffeffefeffeffefeffeffefeffeffefefegffgffgfggfgffgfgfgfggffgffgff gfggfggfgfggfgfggfgfggfggfghgghghgghghhghghgghhgghgghgghgghgghgghhgghg ghgghhghhgh hghhghghgghghghhghghghhihhihihhihhihihhihhihihih hihhihiihihhi ihihiihiihihiijijijiijiijjiijijiijiijijjijiijjijijjijjijijiijiijkkjkjkjkkjkjkjjkjkkjkkjkjkkjjk jkjjkjkjjklkkjk kjkkjkjkjkjjkkjlklkllklkkllkklklkklklkklkklklkklklkkllkllklkllklkkllkllmlmlmmllmllmllmlmllmllmllmlmllmllnm mlmmlmmlmmlmmlmmlmmlmlmlmlmmnmnnmnnmmnmnnmmnmnmmnmnnmnmmnmmnmnmmn mnmnnmnnmnnmnnmnnmnmnnmnmononnononnonnonnononnononnonnonnonoonoononononoononnonoononoonnopoopooppoppooppopopoop opopoopopoppopoppoppopooppopoopqppqqppqpqqpqpqpqpqppqpqqpqqpqpqqppqpp qpqqpqqpqqppqqpqpqqpqqpqpqpqrqqrqrrqqrrqrqqrqqrqrrqqrrq qrqrqqrqrrqrqrrqrqrqrqrqqrssrsrsrssrsrsrrsrrsrrsr rsrrsrrsrsrrssrsrssrssrssrssrssrssrsrrssrstsstsststststtsststssts stsststtststststtstststssttststtutuuttuttutuutututtututtutututuutuutuututuututtuuttuutuutuuvuvvuuvuuvuvuuvuvu uvuvu uvuvuu vuvvuvvuvvuvuvvuvvuvuuvuvuvuvwvwvwvvwwvvwvvwvvwvvwvvwvvwvwvWVWVWVWWVWWVWWVWVWWVWVVWWVWWVWWXWXWWXXWWXWWXWWXWXWWXWXWXWWXWXWWXYX XWXXWXXWXXWXXWXXWXWXXWXXWXXYXXYXXYXYYXXYY XYXYXXYXYXXYXXYXXYXXYYXYXYXYYXY YXYXXYXXYXZYZZYZZYYZYYZZYZYYZYZYZZYZYY ZYZZYZYZYYZYZYZYY[ZZ[Z[[Z[Z[Z[Z[Z[ZZ[Z[ZZ[ZZ[Z[Z[ZZ[ZZ[ZZ![Z[ [Z[ZZ[Z[ZZ[ZZ[Z[[\[\\[\\[\[[\[\[\[\[[\[[\[\[ \[\ \[\\[\[[\\[\[\[[\\[[\]\\]\]\\]\\]\\]\ \]\\]^]]\] ]\]]\]\]]\]]^]^^]^]]^]]^]^]]^]^]]^]]^]]^]^^]^]^^]^^]^^]^]]^]^]^^]^__^_^_^_^_^_^^_^^_^^__^^_^^_^^_^__^__^__^^__^__^_^__^__^__^``_`__``__``_`_`_`__`__`__`__`_`_ _ `_``_``_``_``_``_`__``_`_`_``_``a`aa`aa``a`aa`a`a``a`aa`a`a` `a``a``a``abaa`aa`aa`a`a``aa`aa`a`aababaabbabbabbabbabbabaabababaababaaba abababbabbabababbaababbabababaabbccbbcbbcbbccbbcbcbcbbcbcbbcbbcb bcbcbcbbcbcbc cbccbccbcbccbccbccbcbbccdcdccddccddccdcdccdcdc cd cdcddcddcddcddcdccdcdcddcdcededdeddededdedeedded deddededdfeedeedeedeededeededdedeedeedffeefeefeefeefeefeefefefeefeefeeffeffeffeffefeffeffefeffefggfggffgffgfgfgfgffgffgfgfggffgffgffgffgffgffgfg gfggfggfggfggf gfgffhghgghhgghgghhghghhgghgghghghghgghghhghhghhghgghhghhghghhghhghgiihhihhihihhihihihhihhihhihihihhihhihhihiihhi ihi ihiihiihihhihiihihiihiihihihijjijijjiijiiji iji ijijiijii jij jijjijijjijjijjijiijijijjijjijjkkjjkkjkjkjjkjkjjkjkkjkjjkjjkj jkjk"kjkkjkkjjkjkkjkkjkjkklklklklkklkklklk klklklkk lkl lklkllklklkkllkkllkklkllkmlmllmllmllmllmlmlmmlmlmml lmllmllmmllmlm ml mlmlmlmlmmlmnnmmnmnnmnmnmmnmmn mnmmnmmnmnmmnon nmn nmnmn nmnmnnmmnmonoononononoonnononnonnonononnon nonoonoonoono onoononoononpoppoppoopopoopoppopopoopopo opoppoppop poppooppopoppopoppqqpqpqpqqppqqpqpqqppqpqppqppqppqpqpp qpqqpqqpqqpqqpqqpqqpqqpqpqpqqpqrrqrqrrqrqrqqrrqrqqrqqrqrqrqqrqqrqrqrrqrqr rqrrqrqrrqrrssrrssrssrrsrsrrsrrsrrsrrsrrsrsrrsrrsrrstssrssrssrssrssrrssrssrsrttsststststssttstststsstsstsstsstsstsstss tsttsttsttsttstsstssttsttststtuutututtuututtutuututtututtututtuttutt utuutuutuututuutututtutututtuutuvuuvuvuvuvuuvuuvuuvuuvuvuvuu vuvvuvvuvvuvuvuvvuvuuvvuvuvvuvvuvvuvvwwvvwwvwvwvvwvwvwwvvwvwvv WVWWVWWVWWVWVWWVWVWVWVW WVWVWWXWXXWXWXXWWXWWXWWXWXXWXWWXWWXYXXWX XWXXWWXWXXWXXWXXWXXWYXYXYXXYXYYXYYXYXXYXYXXYX XYXYXXYXXYXXYXYYXYYXYYXYYXYYXYYXYXYXYYXXYXXYXZZYYZYYZYZYYZYZYZYYZYZYYZYZYYZYYZYYZYZZYZYZ ZYZYZZYZZYZZYZZYZY[[Z[Z[Z[Z[Z[[Z[[Z[Z[ZZ[ZZ[ZZ[ZZ[Z[ZZ[Z[[Z[ [Z[[Z[Z[[Z[[Z[[Z[Z[[Z\[\\[\\[\[\[\\[\[\[[\[\[\\[ [\[[\[\\[\\[[\[\\[\\[[\[\[[\\]\\]\]\]\\]\]\]\]]\\]\]\\]\]]\]]\]]\]]\] ]\]\^]]^]^]]^]^]]^^]^]^]]^]]^]^]]^] ]^]]^]]^]^^]^^]^^]^]^^]^]]^]^_^_^__^_^^_^_^^_^_^_^^_^^_^^_^__^__^__^__^__^__^__^_^^__^_^__`_`__``_`__`__`__``_`_`__`__` _`_``_ `_`__``_``_``_`_`aa`aa`a`a``a`a``a`a``a``a`` a`aa``aa`a`a`aa`aa``a`a``bbababbaabbabbababbaababaabaababaabaabaabaa babbababbababbababababaabbabaabccbcbbcbcbbcbbcbbcdccbccbcbbccbbccbcbcbccbbcbcbccdcdcdcdcddcdcdcdccdccdccdccdccdcdcddccdcddcddcddcddcddcdcddcdcdcdeddeddedeededeededed dedede edeededeedeedeededededdedeedfefeeffeffeefeefefefeffefefeefeefeefeefeffeffeffefeffefeefeefefeegfgffgfggfggffgfggfgffgffgfggfgfgfggfgffggfgfggfgfhgghhghgghghhgghgghgghgghgghghghghhghhghghhghhghghhghgghiihihhihhiihiihihhiihihihiihih hihhiji ihiihiihiihiihiihiihhiihihhiihiijijijjijjiijiijiijijiijijijiijiijiijiijijjijjijjijjijjijjijijjijijijijjkkjjkjkkjkjkkjjkjjkjkjkjjkjjkj jkjkjkkjkjkjkjkkjjkkjlklkklkllklklkklkklkklklkklkklkklkklkklkklmllkl lklklkllklklklklklmmlmlmllmllmmllmmlm lmlml lmllmlmmllmmlmmlmlmmlmlmlmmlmlmmlmlnnmnnmnmmnmnnmnmmnmmnm mnm mnmmn nmnnmnmnmnnmnnmnnmnmnmnmnmmnnmnmmnnmmnnon nonnoononnon nononnonnon nonoononoonnoonnonnonoonoppoopoopopoopoppopopoopoopoopoopoopopooqppqppoppoppoppoppoppoppopopoopoopoppoppooqpqpqqpqpqqpqpqpqqpqpqppqp pqpqpqp pqpqqpqpqqpqqppqqpqppqppqqprqrqrrqqrqrqqrqqrq qrqrqqrq q rqrrqrrqrqrrqrrqrqrrqrqrrqqrrqrrqssrsrrsrsrsrrssrsrrsrrsrrsrrsrrsr rsrssts srssrsrssrssrsrssrsrrtststsststsstsstsstsstsstuttst tsttsttststsststtsttsttututtututtututtuttuttuttu utu ututuutuutuututuutuutuututtuutvvuvuuvuuvuvuvuuvuvuvuuvuuvuuvuuvu uvuuvuvvuvvuvvuvuvvuvvuvuvuvuvwvwvvwvvwvwwvvwvvwvvwvwvvwvwvvwvvwvvwvvWVWVVWVWVVWVVWVWVWVWVVWWVWVVWVVWVWVVWVV WVWWVWVW WVWWVWWVWVWWVWWXXWXX WXWXWWXWWXWXWWXWXXWXXWX XWXXWXXWXWXXWXXWXWWYXYXXYXXYXYXXYXXYXYXXYX XYXYXXYXYYXXYXXYXYXYXYYXYYXXYYXYZZYZYZZYZZYZZYZYZYYZZYZYYZY YZYZYZYZZYZZYZZYZZYZYZZYY[Z[[Z[Z[ZZ[Z[[Z[Z[Z[ZZ[ZZ[ZZ[ZZ[ZZ[ZZ[ZZ[ZZ[Z[[Z[[ZZ[[Z[[Z[Z[ZZ[Z\\[\[\\[\[\[\\[[\[[\[\[[\[\[[\[[\ [ \[\\[\[\\[\\[\[\[\]\]]\\]\\]\\]\]\]\]\\]\]]\\]\]\]\\]\ \]\\]\]]\]\]]\]\]]\\]\]]^]^^]^]^^]^]]^]]^]^]]^]^^]^]]^^]^^]^^]^]]^]^]]^]]^]^_^_^__^_^__^_^_^^_^^_^^_^^_^^_^^_`__^_^_^^__^__^__^__^__^_^__^__^__`_``__``__`_`_`_`__`__`_`__`__`_``_``_``_``_``_``_``_`aa`a`a``a``a``aa`a``a``a`a``a``a` `!a`aa`a``aa`a``a`a``aa``a`aabbababaabaabaabababbabbaabaababaabaabababbabbabbababbabababbcbccbccbcbccbbcbcbccbcbcbbccbbcbbcbbcbbdccbccbccbccbcddccdcddcdcdcddccdcdccdcdcdccdccdccdcdcdccdcc dcddcdcd dcdccdcddcddcddcdeeddededeededdeddedeeddededded ede ededeedeedeedeededeffefeffefeefeff efeefeefe efeffefeffeeffeffeffefefeffgfggfgfggfgfggffgffgffgf fgffgffgfgffghg gfggfggfggfgfggfggfgfgffgffgfggffhghghgghgghghhghgghghhgghghghgghgghgghg gihhghhghhghhghhghhghhgihhihihihhihhihihhihihhihhihhih hihiihiihihihiihiihihijijijiijijiijijiijiijijiijiijiijiijijjijjijjiijjijijjijjijijjijjkjjkjkjjkjjkkjkjjkjkjjkjjkjkjkjkkjkjkkjkjkkjkjkkjkllklkkllkkllklkkllkklklklklkllk klklmllkl lklklklklkllklkllkklkkmllmlmlmmllmlmmllmllmlmllmllmlml lmllmlm mlmmlmlmmlmmlmmlmlmmlmmlmlmmlmmnmmnmnmmnmmnmnnmmnmmnn mnmmnmnmnnmnnmnmnmnnmnnmnmnonnoonononnonnonnonnonononnonoonnononnon nonnonononoonononoonoononononoopopoppopooppoppopoopopoopopoopoopop poppoppoppopopqpqpqpqpqppqppqp pqpqp pqpqqpqpqqpqpqppqpqqpqqpqppqqrqqrqqrqqrrqrqrrqqrqrqqrqqrqqrrqq rqrrqr rqrrqrrqrrqrqrrqrrqrqqrssrsrrssrssrrsrsrsrsrsrsrrsrrstssrs srssrsrssrs srssrsrsstst tststststtststtst stsststtstststsststsststtuuttutuututtutuutuuttut tuttuttut t utuutuututuututuutuututtutuututuuttuvuuvuvvuvvuuvuuvuvuuvuuvuvvuvvuvvuuvvuvuuvuvvuuvvuvuvVWWVWVWVVWVWWVWVWVWVWVVWVVWVWVVWVVWVVWVW WVWWVWVWWVWVWWVWVWWVWVWVVWVXWXWXXWXWWXWXWXWXWWXWWXWWXXWXWWXWWXWWXW W XWXXWXXWXWXWWXXWXWXXWXWXWXXWYXXYXXYXYXXYYXXYYXYXXYXXYXYYX XYXXYZY YXYYXYXYXYYXYYXYYXYXYYXYXYYXZYZZYZYYZYZYZZYZZYZZYYZYZYYZYZYZYZY YZYZZYZZYZZYZYZYZYY[Z[[ZZ[ZZ[[Z[[Z[ZZ[ZZ[ZZ[ZZ[ZZ[ZZ[ZZ\[[Z[Z[Z[[Z[ZZ[[Z[Z[[Z[\[\\[\\[\[[\[[\[[\\[\[[\[[\[[\[[\[\\[\\[[\\[\[[\\[\[\[[\\]\]]\]\\]\]\]\]\\]\\]\]\\]\\] \]\]\\]^]]\]]\]\]]\]]\]\]]\]\]]\]\\]]\\]\\]]\]]^^]^^]^^]]^^]^]]^]]^]^]^]^]]^]^]]^]]_^^]^^]^^]^^]^^]^^]^]^^]^]]^^]^]^]^]^^_^_^^__^_^_^__^^_^_^^_^^_^^_^_^^_^__^ ^_^__`_ _^__^__^__^_^_^^__^__^_^__^__^__^^``_`_`__`_`__`__`_`__`__`__``__`__`__``_``_``_` `_``_`_``_``a``a``a``a`a`a``a``a`a``a``a``a`aa`aa`a`a`a``aa`aa`a`a`a``baabaababaab ababababaabaababbabbabbabbababbabbabbababbabbabaababaccbcbccbbccbcbbcbcbbcb bcbccbcbcbbcbbcbccbcbcbccbccbcbcbccbcddcdcdccddcdcdccdcddccdccdccdccdccdccdcc dcddcdcddcdcddcddcddcdededdeededeedeedededdededdeddeded d$edeededdeededdeedeefeffefeefeefefeefeffefeffeefeefeefeefeefefefeefeffefefefefeffgfgfgfgfgfggfggfgfggfgfgffgfggfggfgfggfggfgfggfggffggfgfgghgghghhghghgghgghgghgghgghgghghggih hghhghhghghghghghghihihhihihhihiihiihhihhihhihiih hihhihhihhiihihiihihihihiihihhiihihhiihjjiijiijjijijijijjiijjiijijijjijiijiijiijiikjjijjijijjijijjijjijjijijijjkjjkjkjkjkjjkjkjkjkkjkkjkjjkjjkjjkjkkjkkjkjkkjkjkjkkjkkjllklkklklkklklklkklkklkklk k lkl lklkllklklklkllklkkllmlmmlmmlmllmllmllmllmllmmllmllmllml l mlmmlmml mlmmlmllmlmmllmlmmnmnmnnmmnmnmmnmnmnmmnmmnmmnmmnmmn nmn nmnnmnmnnmnnmnnmnmonnononoonnonnoonononnonnononnonnonoononnpoononoonoononoonoonnononoonnpoppopopoopoopoppoopopoopoopopoopoopoopoppoppopoppopopoppopoppopopoppqpqppqpqpqppqpqppqpqppqppqppqp pqp pqpqqpqqpqpqqpqpqqpqqpqpqqpqpqpqpqprqrrqrqrqqrqrqqrqqrqqrqqrq qsrrq rqrqqrrqrqqrqrqrrqrqqrsrssrsrssrrsrsrrsrssrrsrrsrrsrsrrsrr srssrssrsrssrsrssrsrsrssrsrsrrstststststtststsststtsststsstsstsstss tsttsttstststtstsststtsttsttststtstuttuutututtuututtututtutuutuutuututuutuututuutuututuutuutvuvvuvuuvuuvuvvuvvuuvuuvuvvuuvuuvuuvuu vuvvuvuv vuvuvuvvuvuvuWVWVVWWVVWVWWVVWVWWVWVVWVWWVVWWVWVWVVWVVWVVWVV WVWWVWWVWWVWVWWVVWVWWVWWVWWVWVVWVWWVWVWWXWWXWXWWX WXWXXWWXWWXWWXWXWWXWWXWXXWXXWXXWXWWXXWXWXWXWXXWXXYXYYXYXYXXYXXYXXYXXYXXYXXYXXYXXYX XYZY YXYYXYYXYYXYYXYYXYYXYXXYXYZYYZYZZYYZYZYZYZZ YZYZYZYZYY ZYZZYZZYZZYZZYZZYYZZ[Z[[Z[[ZZ[[Z[[ZZ[Z[ZZ[Z[ZZ[ZZ[ZZ[ [Z[[Z[[Z[Z[[Z[[Z[\[[\[[\[\\[\[[\[[\[[\[\[[\[\[\[[\[[\[\\[\\[\\[\\[\\[\[\[\\[\\]\]]\]\\]\]\\]\]\\]\]]\]]\]]\]\]\]\]\\]\\]\]]\]]\]]\\]]\]\]\]]\]\^]]^]]^]^]^^]^^ ]^]]^]]^]]^] ]^]]^^]^^]^^]^]^^]^^]^^]^]_^_^_^_^_^^__^_^__^_^^_^^_ ^_^__^__^__^__^__^^_^_^__^__^__^_``_``_``__`_` _`__`__`__``_ _`_``_``_``_`_``_``_`_`_``_`_``aa`aa`a`aa`a`a`a`a`aa``a `a``a``baba a`aa``a`aa` a`aa`a``aababbababaababaabababaabaabbabaaba ababababbabbabbababbaabbaababbabaabbccbbccbcbcbbcbbcbcbbcbbcbcbbcbbcbccbccbcbccbccbcbccbcbccbbccdcddccddcddccdccdcdcdccdccdcd cdccdcddcdcddcdcdcdccdcddedeeddeddedededeeddeddeddedeededdedeededeedeeddeedefeefeffeffefeeffefefeefefe efe efefeeffefefefeefeefeffefefefgffggfgfgfggffgfgffgffgffgffgffgffggffgffgfgfgfggfgffggfggfgfgffghghgghghghhghghgghgghgghggh ghghhghhghhghghhghhgghhghghiihihhihiihhihhi hihhih hihhihhihiihiihiihiihiihihhiihhiijijijiijijjijjiijiijiijijjijjijijijjijjijiijkjjkkjjkjkjkjjkkjjkjjkjjkjkjjkjkjjkjjklkkjkkjkkjkkjkkjkkjkjjkjjkjkkjklkllklkllklklkklklklkllkklklkklkklkllkllkklkllklklkllkllklkkllklklkklkllmmlmlmllmlmlmlmlmllmlmlmml lmll mlmlmmlmmlmmlmmlmmlmlmmlmllmmlmmnmnnmnmmnmnnmmnmnmnnmnnmmnmmnmnnmnnmnnmnmmnnmnnmnmnnmnnmnnmoononnoononnonnonoononnonnononnonnonnonoonoonoononoonnonnonnonnoopoppoppoppopopopoopoopopo opo opoppopopoopooppoppoppopoppoppoppqppqppqpqqpqqpqppqpqppqppqppqp pqpqqpqpqqpqpqpqqpqqpqqpqppqpqqppqrqrqrqqrrqrqqrqrqrrqqrqqrqqrqqr qrqqrrqrrqrrqrrqrqqrqqrrqrqrqrrqrrqrqrrqrsrssrssrsrrsrsrssrsrsrssrsrsrsrrsr r srssrssrssrssrsrssrsrsrsrssrstssttststststssttstsstsstsststssttsstsstst tsttsttsttstststtuutuuttututtututtuttuuttuttut t$ututtuututuutuutuututtvvuvuuvuuvvuvvuvuuvuvuuvuuvuuvvuvuuvuuvuvvuvvuvvuvvuvvuvvuvvuvvuvvuvvuv#VUVVUVUUVVUVUVUVVUVWVWWVWWVWWVWVVWVVWVWVWVVWV VWVXXWWVWWVWWVWVWWVWVWWVWXWXWWXXWXXWXWWX&WXWXWXWXWXWXXWXXWXWXXWXWXXYYXYXYXYXYXYXYXXYXYXXYXYXXYXXYXXYXXYXX YXYYXYYXYYXYYXYXYXYYXYYXYYZYZYZZYYZYZYYZYYZYYZYYZYYZYZYYZYYZYYZYYZYZZYZZYZYZZYZYZZ[[ZZ[Z[[Z[[Z[ZZ[Z[Z[[ZZ[ZZ\[ [Z[[Z[Z[[Z[[Z[ZZ[Z[[Z[Z[[\[[\[\\[\[\\[\[[\[\[\[\\ [\[\[[\[\[[\[[\ \[\[\\[\ \[\[\\[\\[\[\\[[\]\\]]\]\]\\]\\]\]\\]\\]\\]\\]\]]\\]\]\]]\]\]]\]]\]]\]\]\\]]\]^]^^]^^]^^]^]^]^]]^]^]^]]^] ] ^]^ ^]^^]^]^^]^]^^]^^]^]^^]]^]]^__^_^_^__^_^^_ ^_^_^^_^^_^__^_^_^__^__^_^_^__^_^__^_^^_^`_``_`_`__``_`_`__`_ _`__`__`__`_`_``_``_``_``_``_``_``_`_``_`_``a`aa`a`a``a`a`a``a `a``a``a``a`a`a`aa`aa`a``a`a`aa`aa`aa`aa`bbabbabaababbabbabbababbaab abaababbabbabbabababbabbabaababbabbcb bcbbcbbccbccbcbbcb bcbbcb bcbccbcbcbccbccbccbbcbbccbbcddcddcdcdccdccdccdcdcdcdccddccdccdccdcc dcd dcddcddcddcddcdccddcdccddcdeddeddeededeedededeededdeddefedeedeedeedededeedeeddeedededeedeefefefeefefeefefeefefeef efefe e feffeffeefefeffefeffefeffggfggfgffgfgffgffgffgffgffgf fgfgfgfggfggfggfgfggfgffgfgfgghhghgghghghgghhghghhgghgghgghggh g hghhghhghhghhghhghghghghhiihihhiihhiihihhihhihhihihhih hihihiihhiihihihihijijjijijijiijiijiijiijiji ijiijijkjjijijijjijijijiijiijjijijjkkjkkjkjjkjkjjkjjkjjk jkjkkjkjkjkkjkjkkjkkjkkjkklkklklklkklkklkkllkklkklkkllkklkllkllklkllklklkllklkklkllkllklmlmllmlmlmllmlmllmlmlmllmlm mlmmlmmlmlmmlmmlmmlmlmlmmllmmlmlmlmnnmnmmnnmmnnmnmmnnmnmmnm mnmnmnnmnmmnmmnonnmnmnmnmmnmnnmnmnnmnnmnnonoonoonnoononnonnonnononnononnonnon nopo onoonono onoononoononononnonnoopopooppopoopopoppoppoopopoopopooppopoop oqppopoppoppoppopopoppoppopoopoopooqpqppqpqpqppqppqpqpqppqp pqppqpp qpq qpqpqqpqqpqpqqpqqpqpqppqpqppqrrqqrqrqqrrqqrrqrqrrqqrqrqqrqrqqrqrqqrq qrqrqr rqrrqrqrrqqrqqrssrsrrsrsrrsrsrrssrsrsrrsrrsrsrr srsrssrssrssrsrsrrsrrsrstsstststtsttstsstsststs tsttstssttststtsttsttsttsttsttutuuttuttutuututtuttututuuttuttuttutuutuutuutuutuututuututuututuutvvuuvuuvvuvuuvuvuuv uVUVVUVVUVUVUVVUVUVVUVUUVWVWWVWVWWVVWVWWVWVVWVVWVV WVWWVVWWVWWVWVWWVVWVWVVWVVWWVWVVWXXWXWXWWXWWXWWXWXWWXWWXWXW WXWXXW WXWXXWXXWXXWXXWXXWXXWXXWXWXWXWXWXWWXYYXYXXYXXYXYXXYXXYXYXXYXYXXYXXYXXYXXYXYXYYXYYXYYXYYXYXXYXXYYXYXYXYXYYXYYZYZYZYYZYZYZYYZYYZYYZYZYYZYZYYZYZZYZZYZZYZZYZYZZYZYZY[Z[Z[Z[ZZ[ZZ[ZZ[Z[ZZ[Z[ZZ[[ZZ[Z[ Z[Z[[Z[ [Z[[Z[[Z[[Z[[Z[[Z[[Z[ZZ[[\[\[\[\[[\[[\[[\[[\[\[[\[[\[\[\\[\[\\[\[\\]\]]\]]\]\\]\]\\]\\]]\\]]\\]\\]\ \]\\]\]]\]]\]\] ]\]]\]\]]\]]\^]]^]^]]^^]^]^]]^]]^]^]^]^]^]]^]^]^]]^]]^]^^]^^]^^]^]^^]^]^^]^]^^_^^_^^_^_^_^^_!^_^__^__^__^__^_^__^^_^_^``_`__``_``__`_`_`__`__`__`__``_`_``_`_`_``_`_``_``_``_`a`a`aa`aa`a``aa`a`a`a``a``a`a``$a`a`a`aa``a`a`aababbabaababbababbabaabaabaabaabaabababbabbabbaababbabbaabbabbababbabbcbbcbbcbbcbcbcbbc bcbbcbcbcbcbccbccbcbbccbcbbcbc cdcdccdcdccddcddccdccdcddcdccdccddccdcddcdccdccdcdcddcdccdccddcdccdcdcdcddcddcddcededdededdeedededdededdeddeddedd edeedeedeedeedeedeededefeefefeefefefefeefeefefeefeefefeffeefefefeffefeffefeffeggfgffgfgffgffggfgfgffgfgffgffgfggfggfggfgfgfggfggfggffgfghghghhghgghghgghghgghgghghghgghghg g!hghhghghhghhghhghhghgghhiihhiihihihiihihihhihihhiihi hihhi ihi ihiihiihiihihhiihhiihiihiihhiijijijijijijjiijijiijijiijiijiijiijiijijjijjijijjijjijjijjijiijijjkjkkjkjjkkjkkjjkkjkjjkjjkkjk jkjkkjkkjkjjkkjkkjjkkjkjjkjkjkkjkllkklkklkllklklkklklkllkklk klklkllklkkllklkllklklkklkllmlmmlmmlmllmllmllmllmllmlmllmllml lmlmmlmmlmlmmlmmlmmlmmllmlmmnmmnmnmnmmnmmnmnmnmnmmnmnmmnmmnmnm mnmnnmnnmnnmnmmnnmnmmnmnnmnmmnnononnoonoonnonnonoonnononoonnoononnonnonoonoonoonoonononoononoonoonoono popopoopopoopoopoopo opoopoppoppopooppopopooppoppopoppooppoppopqppqpqppqpqpqpqppqppqppqpqppqpq qpqqpqpqqpqqpqppqqpqpqqpqqprrqrqrqqrqqrqrqqrqqrqqrr qrqqrqqrqrrqr rqrqqrqqrqrqqrrqrrsrsrsrrsrsrssrsrrsrrs rsrrsrrsrsrssrsrsrssrssrssrsrststtstsststts stsstsstststststssttstssttsstststtsttsttstuutututtuuttututututtututtuttutuutu utuututuutuututututuvuvvuvvuvuuvuvuvuuvuuvuuVUVVUV VUVVUVUVVUVVUVUVUUVWWVWWVWWVVWVWVVWWVWVVWVVWVWVVWV VWVWWVWVWWVWWVWWVWVWVWVVWWVWWVWVWVVXXWXWWXWXWWXWXXWWXXWXWWXWWXWXWXWWXW WXWWXWWXWX XWXXWXWWXXWXXWXXWXWWXWWYXXYXYXYYXYYXYXYXYYXYXXYXXYXYYXXYXYXXYXXYXYYXXY YXYXYYXYXYXXYXXYZYYZYZYZZYZYYZZYZYYZYYZYZYZZYZZY ZYZYZZYZYZYZYZZ[ZZ[[ZZ[ZZ[Z[Z[[Z[ZZ[ZZ[ZZ[Z[Z[Z[[Z[[Z[[Z[[Z[[Z[[ZZ[ZZ[[Z[Z[Z[Z[[\\[[\[\[\[\\[[\[[\[\[[\[[\[[\[ [\[\\[\[\\[\\[\[\\[\[\\]]\]\\]\]]\]\\]\]]\]\]\\]\]]\\]\\]\\]\\^]]\]]\]\]]\]\]]\]]\]\]\] ]^]^]^^]]^]^^]^]^]^]]^]^]]^]]^] ]^]]^^]^^]^]^^]^^]^^]^]]^]^__^_^^_^_^^_^_^^_^^_^^_^^_^^_^^_^^_^^_^__^_^_ _^_^__^^_^^_^__^__^_``_`_`_``_`_`__`_`__`__`_` `_`_``_` `_` `_``__``_`_`a``a`aa`a``a`a`a`a``a`a`aa``a``a`a`aa``a` `a`aa`aa`a`a`aa`a`a``aabaababaabababaabaabaababaabcbbabbabbabababababaabababbaaccbcbbcbcbbcbbccbbcbbcbcbbcbbcbbcbbcbbcbbcbccbccbbcbcbccbccbccbcbbcbcddccddccdcddccdcdcdccdcdccdc cdcdccdccdcddcddcddcddcdcddcdcddccdceddeddeeddededdeddeddededdeddefeede edeedeededeedeedededdedeedededfeefefeefeefeefeefefefeefeffefeefeffef fefeffefefeffefefefeegffgfggfggfgfgffgffgffgffgffgfgffgfggfggfggfgfggfghghghhghghgghghgghgghgghghgh hghhghhghhghhgghghihhihhihhiihhihihihihhihhihhihhihiihiihihhihiihihhihjijijijijjijijijjijijiijjiijijjiijiijiijkjjijjijjijjijjij jijjijijjijkjjkjkjkkjkkjkkjjkjkjkjjkkjkjkjjkj jkjkjk kjkkjkkjkjkjjkjlklkllkllklklkklkklkklkklklkklkklkllkllkllklklkllklkllmlmmlmlmmlmlmllmllmllmlmlmllnmmlmmlmmlmmlmlmmlmlmmlnnmnnmmnmmnnmnmmnmmnmmnmmnmmnm mnmnnmnnmnmmnnmnnmnnmnnmnnmnmnnmnnoonnonnononnononnoon nonnonoonoononoonoonoononnonnononnonnoppoopoppopooppopoopoopoopoopoopopoopo opoppoppopopopopooppoppopoppopqpqpqppqppqppqppqqpqpqpqppqppqpqqppqpq qpqpqpqqpqppqqpqqpqqrqrrqrqrqqrrqqrqrqqrqqrrqrqqrqqrq qrqrqrqrrqrrqr rqrrqrqqrqrrqrrqssrsrrsrssrrsrsrsrrsrsrrsrrsrrsrrsrssrs srsrrssrssrsrrssrsrsrrsrsrsttsststtssttsstsststsstsstsstss tsttsttsttstststtsttstststssututuuttuuttutututuututtut t utuutuutuutututtuutuutuutuutuvuuvuuvvuuvuvvuvvuvuuvuuvuuvuuvuuvuuvuuVUVVUVUVUVVUVUUVUUVUVUVUVVUVVUVUUVVWVVWVVWWVWVVWVVWVVWVVWVWVWVVWVVWVWWVWWVWVWXWXWXXWXXWXWXWXWXWXWXWWXWWXWXXWXWXXWXWXWWXXWXYYXYXYXXYXYXXYXXYYXXYXYXYYXYXYYXZYYZYZYYZYYZYYZYZZYZYYZYYZYZYYZYZYZZ[ZZ[[Z[Z[[Z[ZZ[ZZ[ZZ[ZZ[Z [Z[[Z[[Z[Z[[Z[[Z[[\[[\[\[\[\[\\[\\[\[\[\\[\\[\[\[]\\]\]\\]\\]\\]\\]\\]\]]\]\]]\]^]^^]^^]^]]^]^ ]^]^^]^^]^]^]^^]^__^_^__^_^^_ ^_^^_^_^^_^^_^_``_``__`_``__``_`__`__`__``__`a``_` `_``_`_``a`a`a``a``a`a`a``a`a`aa`ababaabaabbabababbabababbabbabbab bcbcbcbbcbbcbcbbcbbcbcb cbccbccbccbcbcbccddcdccddccdccdcddcddccdcd dcdcddededeeddeeddedededdeeddedd edeedededeedeedeeffeffeffefeeffefefefeefeefeffeffefgfgffggffgfggffggffgfgfgffgffggfgff gfggfggfgfgghghgghhghgghghghhgghghghghhgg hghghhgh hghhihihihihihihhihhihhihhihhiihi ijijijjijiijiijijiijiijiijijijjij jijjijjijijjkjkkjjkjjkjjkjjkkjkjkklkkjkkjkjk kjkkjkjjkklkllklkllklkklklkklkklkklkllkllkmlmllmmlmlmlmmllmllmlmlmlmmllmlmmlmlmmlmlmnnmnmmnnmnmmnmmnnmmnmnmmnnmn nmnnonoonnoononononoonoonoonnononnonnonn onoonono onoonoonooppoopoppopoopoopoppoopoppooppoopoppopoppoppqpqppqppqpqpqppqpp qpq qpqqpqqpqrqrqrqrrqrqqrrqqrqrqrqrrqqr rqr rqrqrrqrsrrsrrsrrsrsrrsrssrsrrsrsrssrs srs srsststtstsststsststsstststststsuttuututuutuuttutututuutuutuutuutuVUVVUUVUVUUVUVUUVUUVVUVVUVVUUVUVUUV VUVUVVUVVUUVVUVVUVWVVWVWVWVWVVWVVWVWVV WVW WVWWVWWXWXWWXWXWXXWXWXXWXW WXWWYXXWXXWXWXWYXYXXYXXYXYYXYXYXXYXYXYXXYYXZYYXYYZYZYYZYZZYYZYZYZYYZYZYZYZZYZZYZZYZYYZ[Z[Z[[Z[Z[Z[Z[[Z[ZZ[ZZ[Z[[Z[Z[[Z[[\[\[\[[\\[\[[\[[\[\[\ \[\\[\\[\\[\[\\]\]]\]\\]\]]\]\\]\\]\]]\]]\]]\]]^^]]^]]^]]^]^]]^]]^]]^ ^]^^]^^]^]^]^^]^^_^_^_^_^_^__^^_^_^^_^^_^_^^_^__^__^^_^`__`_``__`__`__`__`_``__`_`__``_``_`_`_` `a`aa`a`a``a``a`a` `a`aa`a`a`aa``a``abaababaababaabababaabbababaababbabbabbacbcbcbcbccbcbbcbcbcbbcbbcbbccbcbcbccbccbcbccbcdccdcdcdcdccdccdcddcddcdcddcdcddedeedededdeddeddedd edeededdedeefefeefeefeffeffefeefeefefeeffeffeffefegffgfgfgfgfggffg f gfgfggfgghghhghghhgghgghgghghgghghhghhghhgh hghhghhghhihiihhihihiihhih hihiihiihhihiijijjijiijijjiijijijijij jij jijjijjkjkjkkjkjkkjkj jkjjkjkkjkkjkkjkjkkjkjkjllklkllkllkkllklklkkllklkklkllkllkllmlmlmmlmmllmlmlmllmllmlmmlmlmlmlmmlmlnnmmnmnnmnmmnmnmnmnmnnmnnmmnmnnmnnmnnmnmnnonnonnonoonnonononnonnonnonnoononoonoonnoopoopoppopopoppopoopoopopoopoopooppop poppqpqpqpqpqppqppqppqpqpqqpqppqqpqqpqrrqrrqrrqrqqrqrrqqrqqrqrrqrrqrrsrsrrsrsrrsrsrrsrrsrsrsrsrrsrrsrssrssrs srttstsststsstsststtssttss tsttsttststtsttstssttututtuutuuttutuuttuttututuutuutututuUVUUVVUVUVUUVUUVVUVUUVUUVWVVUVUUVVUVUUVVUVVUVVWVWWVWVWVVWVWVWVVWWVVWVVWWVVWVW WVWWVWVWWVWWVWXXWXWXXWWXWXXWXWWXWXXWWXWWXWXXWW XWXXWXXWXXWWXXWXWXXWYXXYXXYXYYXY XYXYYXYXXYXYYXYYXYXXYZYZZYZZYYZYZYZYYZ YZYY ZYZ ZYZZYZZ[Z[ZZ[ZZ[Z[Z[ZZ[[ZZ[Z[Z[Z[[Z[[Z[ [Z[\[\[[\\[\[[\[\[[\[\\[[\[\\[\\[\[\\[\\[[\\]\]\]\\]]\\]\\]\]]\]\]\\]\]]\]]\]]\]]\]]^]^]]^]^]]^]]^]]^]]^]]^]]^ ^]^]^^]^^]^]^^_^_^__^^_^_^_^__^_^^__^__^_^_ _`_`__`_``__`_`_``__`_`_`_``_``_``a`a`a``a`a``a`a`a`aa`aa`a`a`a a`aa`aabaabaababaababaabababaabaabbaacbbabbabbcbbcbcbccbcbcbcbcbccbccbcbbcbccbccbccbccbcbccbcddcdcdccddcddcdccdccdcdcdccdcc dcddcddcdcddcdeeddeddededeedeeddeddededeededeededdfefeefeefeefeffeefeefefeefef feffeffeffeffefefgfggfggfgfggfggfgffgffgffgfgfg gfgfghhghhgghgghhghhghghhghgghghghhggh hghhghhghhghhghghhgihiihihhihihihhihhihhihihhihiihiihiihiihiihihiijijjijijiijijijjijijjiijijjijjijijijjkjkjkkjkjkjkjjkjjkjjkjkklklkllklklklkklklkk lkllkllkllkllkllkllmmlmmlmlmlmllmlmmllmlmmlmmllmllmlmnnmnmmnmmnnmnmnnmnnmmnmnnmmnmmnnmn nmnnmnnmnmmnnmnnmnoonnoononnonnonoononoononnonnoono ononoononoonoonopoppopooppoppoopopoopoopoppoppop poqpqpqpqqpqppqppqppqppqqppqppqqpqqpqqrqrqrqrrqqrqqrqqrqqrqrqqrsrrqrrqrqrsrsr rsrrsrssrsrrsrrsrssrs srsttstssttsstsstssttssttsststsstststutututuututuututtuttuu tutu utuututuu @zyzyzyyzyyzyyzyzyzzyyzyzyzzy yzyyzyyzyzzyzyyzyzzyzyyzzyz{zz{z{z{z{z{zz{zz{zz{zz{zz{zz{zz{z{{z{z{z{z{{z{{z{{z{{z{z{{z{|{||{||{|{|{{|{{|{|{|{{|{{|{{|{{|{||{||{|{{||{|{|{{|{|{{||{|{{||{}}|}}| |}|}||}}||}|}}||}|}|}||}|}||}|}|}|}}|}}|}}|}|}|}}|}|}}|}}~}}~~}~}~}}~}~}~}}~}}~}~}~~}~~}~~}~~}~~}}~}~~}~}}~~}~~~~~~~~~~~~~ ~~ ~"~~~~~        򄃄      񍌍      󒑒   󕔕   򘙘zyyzzyzyyzyzyyzzyyzyzyyzyyzyzyyzyzyzyyzyyzzyzzyzzyzyzzyzzyyzyzzyzzyzzyyzyzyy{z{z{{zz{z{zz{z{zz{zz{zz{zz {z{{z{{z{z{z{z{{zz{{z{z{{z{{|{|{{||{{|{{|{|{{||{||{{|{ {|{|{{|{|{|{|{||{{||{|{{|{||}|}}||}||}}||}|}||}||}||}~}|}}|}|}|}}|}|}||}|~~}~~}~}}~}~~}~}}~}}~}}~}~~}~~}~~}~}}~~}~~}~ ~~~~~~~~~~~~~~~~ ~ ~~~~~~~~~~     򅄄  膇󇈇 􈉈 󊉉􊉊 􋌋 ꏎ "􎏎    񐑑       zyyzyzyzyzyzyyzyyzyzyyzyzyyzyz zyzyzzyzzyyzyzzyzzyzz{z{z{z{{zz{z{{zz{z{z{{z{z{z{zz{zz{z z{z{{z{z{{z{{z{z{z{z{z{{z{||{|{|{|{|{{|{{||{|{|{|{{|{ {|{{|{{|{||{|{|{{||{||{||{||{||{{|{|{||}|}||}||}||}|}}|}||}|}}|}|}}||}||}||}||}|}}|} }|}||}||}}|}|~~}~}~~}~}~}~}}~}}~}}~}~~}~}}~} ~}~~}~~}~ ~}~~}~}~}~~}~}~}~}~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ 񀁀   񄃄脅  􇆇   󌋋!  됏  󑒑 򓔓  󕖖    yzyyxyyxyyxyyxy yxyxyxyxyyxxyyxyxxyyzyyzzyzzyyzyyzyzyzyyzyyzyzyzyy zyz zyzzyzzyzzyzzyzyyzyzzyzyzzyyzz{zz{z{{z{{z{z{zz{z{{z{z{zz{zz{{zz{z z{z{zz{z{{z{{z{{z{z{{z{z{{|{|{{|{||{||{{|{|{{|{|{{||{{|{||{||{|{||{|{|{|{||{|{|{|{||}|}||}|}||}||}||}||}||}||}||}| }|}}|}|}}|}}|}|}}|}}|}||}|}~}}~}~}}~}~}}~}~~}~}}~}}~} }~}~~} ~}~}~}~~}~}~~}~}}~}~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~-  '        􊉉 񉊊  􌋋   􌍌   쎏  𑒒󒑒蓒 𓔓          򙘘 yxyyxyyxyyxyxyxyyxyyxyxxyxyxyxxyyxyyzyzyyzyzzyzyyzyyzzyyzyyzzyzyyzyyzzyyzy yzyy{z{zzyzzyzzyzzyzzyzz{{zz{z{z{{zz{z{{z{zz{zz{z{z z {z{{z{z{{z{{z{z{{z{z{{z{z{{zz{||{|{{|{{||{||{|{{|{|{|{|{|{|{{||{{|{{|{{|{{|{||{||{||{||{|{||{||{|{|{|{}}|}|}}||}}|}||}||}||}|}||}||}||}||}|} }|}|}||}||}|}||}~}~}~~}}~}}~~}}~}~}~}~}}~}~~}~~}~}~~}~}~}~}~~~~~~~~~~~~~~~~~~ ~~~ ~~~~~~~~~ 񁀁 򀁁   񅆆񆇇 򇈈󈉉򌋋􌋋썌 폎          yxyxy yxyyxyxyyxyxyyxyzyyzyzzyyzyzzyzyzyzyyzyyzyyzyzzyzzyzzyzyz zyzz{z{{z{{z{{z{zz{zz{{z{z{zz{z{zz{z{z z{z{{z{{z{{z{zz{{z{{z{{z{z||{||{|{||{{|{|{{|{{|{{|{|{|}||{||{|{| |{||{|{|{||}|}}|}|}|}}|}}|}||}||} |}|}}|}||}||}|}|}}|}|}}|}~}~~}~}~}}~}~~}~~}~~}}~}~} }~}~ ~}~~}~}~~}~}~~}~}~~}~~}~~}~~}}~}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  􂁂                𐑐     % xyxyxyyxxyxxyxyxxyxyxyxxyyxyx xyxyxxyxyxyyxyxxyyxyyxyxxyxyxyyxyyzyzzyzzyzyzyyzyzyzyzyyzyzzyzyyzyyzyzyy zyzzyzzyzzyzzyzzyzyzyyzyzyzzyzy{{zz{{z{{z{z{{zz{zz{zz{z{zz{zz{zz{zz{z{{z{{z{{z{{z{z{z{z{{z||{|{{|{||{||{|{|{{|{{|{{|{||{||{|{||{||{{||{{|{||{{||{|{|{||}|}}|}|}|}}||}|}}|}||}}|}|}| |}||}||}||}|| }|}}|}}|}}|}}|}}|}|}}||}||}~}~}~~}}~}~}~} }~}}~}~} }~}}~}~~}~~}~}~~}~~}}~}~~}~~}~}~}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  悃   󄃃  !   󉈈 $񌍍  ܏ 󐏐󑐑󐑐   𖕖  xyyxxyxxyxxyxxyxxyxyxxyxxyxyxxyxxyyxyxxyxxyyxyxyyxyyxyxyyxyxyyxyyxyzzyzyzyyzyyzyzyyzyyzyzyyzyyzyyzyyzyzzyzzyzzyzzyzyzzyzyyzzyzzyzz{{z{zz{z{z{{zz{z{zz{{z{zz{zz{ z{zz{z{{z{{z{{z{{z{ {z{z{zz{|{||{{||{|{|{||{{|{|{|{||{{|{{|{| |{|{||{|{||{|{||{|{{|{}||}}|}|}|}}|}||}|}||}|}| |}||}|}}|}}|}}|}|}}|}}||}|}|}|}|}||}}~~}~}~}}~}~}~}~} }~}~}}~}~}}~}} ~}~~}~~}~~}~~}~}~~}~~}~~}}~}~}}~~~~~~~~~~~~~~~ ~~~~~~~~~󂁂%􂃂  %    򉊉􉊉 񌍌  &  󓔔   xyyxyxxyxxyxyxxyxyyxxyxyxyxxyxxyxxyxxyxyxxyxyyxyxyxyyxyxxyxxyxxyxyxxyxyxxzyzyyzyzzyyzzyzyzzyzzyyzzyzzyyzyyzyyzyyzyyzyzzyzzyzzyzyzyzzyzzyzyzyy{z{{z{z{z{zz{z{{z{zz{z{zz{zz{zz{zz{zz{z z{|{{z{z{z{z{{zz{{z{z{{zz{{|{|{|{|{ {|{{|{|{{|{{|{ {}||{||{| |{|{||{|{|{|{{||}|}}|}|}|}|}}||}|}||}||}||}~}}|}}|}}|}}|}}|}}|}|}}||}}|}|}||}||}~}~}~}~}}~}~}~}~}~}}~} }~}}~}~}~}~}~}~ ~}~~}~}~~}~~}~~~~~~~~~~~~~~ ~~~~~~~~~~~􁀁   񅆆 ) 󈇈􉈉 򊉉(   񐏏   򓔔    䕔    xwxxwxxwxwxxwxwxwwxxwxxwxwxxyyxyxyxxyxyxyy xyxxyxyxxyxyyxyyxyxyxyxyxyxxyxyxyyzyzyzyzyyzzyzyyzyzyzyyzyyzzyyzyzzyzyzzyzzyzyzzyzzyzyzzyyzyyz{{z{{z{zz{z{{z{z{z{z{z{z{{zz{zz{z{|{{z{{z{z{{z{ {z{zz{z{{|{|{{|{||{{|{{|{|{{|{{|{|{|{{ |{||{|{{|{||{||{|{|{{|{{|}}|}|}}||}||}|}}|}||}|}||}}||}||}|}||}|}|}}|}}|}||}|}||}}||}|~}~}~}~~}~~}}~}~}}~}}~}~~}~}~~}}~} }~}~~}}~~}~~}~}}~~}~~}~}~~}~}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    󀁀        󈇈   슉  󊋋 鋌   󍎍􎏎  ꎏ   󒑒   򖕖   xwxxwxxwxwxwxwxxyxyxxyxyyxyyxyyxxyxyyxxyxxyxyxyyxyyxyxyyxyxyyxyyzzyyzyzzyzzyzzyyzyzyyzyyzyyzyyzyzzyzyzyzzyyzzyyzzyzyzyy{{z{z{{zz{zz{zz{zz{z{z{zz{{zz{zz{z{{zz{{z{z{{z{{z{{z{z{z{zz{z{zz{z{{|{{|{{|{{|{||{|{|{{|{|{|{{|{|{|{||{||{|{|{|{||{|}|}||}||}}|}|}||}|}||}}|}|}||}||}||}| |}|}|} }| }|}|}}|}||}|}~~}~}~}~}}~}~}}~~}~}~}}~} }~}} ~}~}~~}~~}~~}~}~}~~}~~}~}~~}~~}}~}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #  򃂂  񈇈  ꊉ      󍎍            xwxxwxwxwxxwxxwxwwxwwxwxwwxwwxyyxyyxxyxyyxyxxyxxyxyxyxyxyxxyxyyxxyxyxxyyxyxyyxyyxyyxyxyxyyxy yzyzzyyzyyzyyzyyzy yzyzyzyzzyzyzzyzyyzzyzzyzyzyzyzz{zz{z{z{zz{zz{z{zz{z{zz{z{z{z{zz{z{z{{z{{z{zz{{z{z{{z{{z{{z{{z|{||{{||{|{{|{{|{{|{{|{|{{|{|{{|{{|{{|{{ |{||{|{||{||{|{||{|{|{{|{{|{|{{}|}||}|}}||}|}||}||}| |}|}||}| |}|}}|}|}|}}|}|}|}}|}}|}|}~~}~}~}}~}}~}~}~}~} }~}}~}~~}}~}}~}~~}~}~~}~}~~}}~~}~}~~}~~}~~~~~~~~~~~~~ ~~~ ~ ~~~~~~~~~~~ 뀁 񂃂򄃄 년󄅄 񈇇  񉊉󉊋늋     􏐏     )铔     떗xwwxxwwxxwxwwxxwwxwwxwwxwwxwxww xwxxwxxwxwxwwxwxxwxwwxwxxwwxwxwwxyxxyxyxxyxxyxyxxyxxyxxyxxyxxyxxyxxyxxyxxyxyyxyxyyxyyxyyxyxyyxyyxxyyzyyzyzyyzyzyzyyzyzyzyyzyzyzyzzyzzyzzyzzyzzyzyyzyyzz{z{{z{zz{{z{z{zz{z{z{zz{z z{zz{{z{z{{z{{zz{z{{z{{z{{z{{z{|{|{|{{||{||{{|{{|{|{{|{{|{|{|{{|{{|{| |{|{|{{||{||{|{|{{||{|{||{{||}||}||}||}|}|}|}}||}|}||}||}||}| |~}&}|}}|}|}|}|}}||}}~}~~}}~}}~~}}~}~}~}}~} }~}}~} }~}~}~~}~}~~}~~}~}~}~}~~}~~~~~~~~~~~~~~&~~~~~~"퀁       􅆆 򆇇􈇇     􋊊  󌍌  󍎎  󎏎 񐑑 둒       $  wxxwxxwwxxwxxwxxwxw wxwwxwxwwxwwxwwxwxxwxxwxxwxxwwxxwxxwxxwyyxyyxyxyyxyxxyxyyxxyxxyxyyxyxxyxxyxxyx xyxyyxyyxyyxyyxyxyxyxxyyxxyxyxyyzyzzyyzyzzyzyzzyzyzyyzyyzyyzyyzyyzyzzyz zyzzyzzyzzyzyzyyzy{z{z{{z{{z{{z{zz{zz{zz{{zz{z{{z{zz{zz{z{z{{z{{z{z{{|{||{|{||{{|{{|{ {|{{|{{|{{|{{|{||{||{|{||{|{{|{{|{{|{|{|}}|}}|}||}}|}}||}}||}| |}||}}||}|}|}||}}| |}~}}|}|} }|}|}| }~}~~}}~}}~}}~}}~} }~}}~}~}~~}~}~~}}~}~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~  넃󄅄   񈉉      񎍍    󑐑 򒓓  󔓔  񕖕 xwwxwwxwxxwxwxwxwxwwxwwxw wxwxww xwxxwxxwxxwxxwxyyxyxyyxxyxyxyyxyxyxxyxyxx yxyyxyyxyxyyxyyxxyyxyyzyyzyzzyyzzyzzyzzyyzyzyzyyzyyzyzyz zyzzyzzyzyzyyzzyyzzyzz{z{{z{z{zz{z{{z{z{zz{z{z z {z{{z{{z{{z{{zz{{z{{z{{z{z{z{{zz{z{|{||{|{|{|| {|{|{|{{| {|{{|{{ |{||{||{||{|{{|{|{||{|{{|{|{|{|{||}}|}}|}||}|}|}||}||}||}||}|}||}|}}|}}|}}|}|}|}}|}~~}~}}~}}~}~}~~}}~}}~}}~}~~}}~}}~ }~}~ ~}~~}~~}~~}~~}~~}~}~}~~~~~~~~~~~~~~~~~~~~~  򁂂򄃄       񈉉 􉋊       򒑒  󒓒  wvwwvwwvwwvwvwvwwvwvwwvwwxwwxwxwwxxwxxwxwxxwwxwwxwwxwxwxwwxyxxwxxwxxwxwxwwxwxxwxyxyxyxyxxyxxyyxyxyyxyyxyxxyyxyxyyxyxyxyyxyxyxyyxyxyyxyxxyyzyzyyzyyzyzyyzyyzyyzyyzyzyyzyy{zzyzyzzyzzyzzyzzyzzyzzyzzyzyy{z{{z{zz{zz{{zz{{zz{zz{zz{zz{ z{zz{zz{zz {z{{z{{z{{z{{z{z{z{{z{{z{z{{|{|{|{{|{|{|{||{||{|{{|{{|{{|{||{||{{||{{ |{||{| |{||{{|{||{||{|{||{|{{||{{}||}}||}}||}||}}||}|}}|}|}||}||}|}||}||}|}}|}}|}|}}|}}|}}|}||}|}||~~}}~}~~}~}~}}~}~~}}~}}~} }~}~~}~~}~~}}~}~~}~~}~~}~}~}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    ꃂ󄃄   񅇆 򈉈    󊋊   퍌     󔓔     wvw wvwwvwvwvwwvwvwwvwvwwvwvwvwwxwxwxxwxwxwxxwwxwwxwxwwxwwxwxwxwwxwxxwxxwxwxxwxwxwwxxwxwxxwxyxyxyyxyxyxyxyyxyyxxyxyxyyxyxxyxxyxyxy yxyyxyyxyxyxyxyxyxyyzyzzyzzyyzzyyzzyzyyzyyzyzyzzyyzyzy yzyyzyzzyz zyzzyyzzyzyzzyz z{z{z{z{z{zz{z{{z{z z{z{z{zz{z z {z{z{{z{{z{{z{z{zz{z{{z{z{zz{{||{{||{||{{|{{|{{|{{|{|{{|{{|{|{|{{|{|{||{||{ |{|{||{|{|}}|}|}}|}}|}||}||}|}|}}||}||}||}|}|| }|}}|}}|}}|}}|}||}|}|}}||}~~}~}~}}~}}~}}~}}~}~~}}~}}~}}~}}~}}~}} ~}~}~~}~~}~~}~~}~~}~}~}~~}~}~}~~~~~~~~~~~~~~ ~~~~ ~~~~~      %  񅄅  􇈇   툉򉊉 犉􌋌 󎍎 󏎏󎏏 򏐏   󒑒򒓓  󔓓   wvw wvwvwwvwvwwvwwvwwvwvwwvwvwxxwwxwxwxwwxwwxwwxwwxwwxwwxwwxxwwxwwxwwxwx xwxxwxwxxwwxwwxxwxyyxyyxxyyxyxyyxyyxxyxyxxyxxyxxy xyxyyxyyxyxyxyxyxyyxyxyxyxyyxyyxyxyyzyzyzyzyzzyzzyzyyzyzyzzyyzyyzyy zyzzyzzyyzyzzyzzyzzyzyzyzyzyzzyzyzyz{z{{z{zz{{z{zz{z{z{z{z{{zz{zz{zz{z{{z{{z{{z{{z{{z{z{z{z{z|{|{{||{|{{|{|{{|{{|{{|{{|{|{{|{{|{{|{||{|{{||{|{||{{|{||{||{|{||{|}}|}}|}|}||}|}|}||}||}||}|}|}||}||}||}|}}|} }|}|}}|}|}}|}}|}}|}|~}~~}} ~}~}~~}~}}~}}~}~ ~}~~}~}~ ~}~}~}~~}~}}~~}}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~        胄􆅆 􇆇     튋  򋌋􍌌 񍎍   뎏   𒓒   𗖗wvwvwvvwvwvvwvwvvwvvwvwv vwv vwvv#wvwwvwvvwvwvwwvwwvwwxwxxwxxwxw wxwwxwxwxwxxwxxwxwxxwxxwxxwxxwxwwxwxwwxxwxxwyyxyxyxyxyyxxyxxyxyxxyxxyxx yxyxyyxxyyxyyxyyxyxxyzyyzzyyzyyzzyzyzyzyyzyyzyzyzyyzyzyyzyy zyzzyzzyzzyzyyzzyyzzyzyzyyzyzyzzyzyzy{{z{z{zz{z{zz{{z{z{z{{zz{zz{zz{zz{z{{z{{z{z{{z{z{z{{z{z{{z|{{|{{|{{||{{|{{||{|{|{{|{{|{{|{{ |{||{||{|{{| |{||{{||{|{|{{|{|{||}||}}|}}|}|}|}|}}|}||}||}|}}|}||}||}}||}|}||}}||}|}}|}|}}|~}~}}~}~}~}~}~~}~}~}}~}~}}~}}~}~}}~}} ~}~~}~}~~}}~}~~}~~}~}~}}~}~~}~~}~~}~~~~~~~~~~~~~~~~~ ~~~~~~~~~~ ~       $ 򃄃  󅆆 󆇇% 󋊊 󌍌󌍍  쒑      򕖕wvwvvwvwwvwvwvvwvvwwv vwvwvvwwvw wvwwvwvwvwwvwwvwwxwxwxxwwxwxwwxwwxwwxwwxwwxwxxwwxwxxwx xwxxwxxwxxwxxwxwxxwxxyxyyxyyxxyyxyxxyxxyxyxyxyyxyxxyxyxyyxxyxx yxyyxy yxyxxyyxyxyyxyyxxyxyzyzyzzyyzyzyzyzyyzyzyyzyyzyyzyzzyzyzzyyzyzzyzzyzzyzyyzy{{z{zz{{z{{zz{z{z{{z{zz{zz{zz{zz{zz{z{z{{z{{z{z{{z{z{{z{{z{z{{z{{z{{|{|{{|{{|{||{|{{|{|{{ |{||{|{||{{|{||{||{|{|{|{|{||{||}|}||}|}}|}||}|}||}||}||}||}|}||} |}||~} }|}}|}}|}}|}}|}||}|}}|}||}}~}~}}~}}~}~}}~}}~}~} }~}}~} } ~}~~}~ ~}~}}~}}~}~~}~}}~}}~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~         󆇇 󇈈    򊋊   ی   񒑒   !씕򖕕wvwwvwvwvwvwwvvwwvwvvwwvwvvwvwvwwvwv vwvw wvwwvwwvwwvvwvwwvxwwxwwxxwxwwxwwxwwxwwxwwxwxwwxwwxw w xwx xw xwxxwwxwxxwxxwwxwxyyxxyxyyxyxxy xyxxyxxyxxyxxyxx yxyyxyxyyxyyxyxyxyyxyyxxyzzyyzyyzyzyyzyzyzyyzyzyyzyzyyz zyzyzzyz zyzyzzyzzyyzzyzyzyyzyz{{z{zz{zz{z{z{z{z{{zz{z{z{zz{z{{z{{z{{z{z{{z{z{{z{z{{z{{|{{|{||{||{{|{|{{|{|{||{|{{|{{|{{|{{|{||{||{|{|{|{|{||{|{||{|{{||{|}|}|}}|}||}||}|}||}|}}||}|}||}}|}||}||}||}|}}||}||}}|}|}||}}||}|}|~~}~~}~~}}~~}}~~}~~}}~}}~}}~}}~}}~}}~}~~}~}~~}}~}~~}~~}}~}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    򅄅  񄆅     抉     򋌋% 쎏     𔓓     𕖖vuvuvvuvvuvuuvuuvvwwvvwwvwvvwvvwvwvvwwvwvvwvvwvvwvwwvvwvwvvwwvwwvwwvwvwvwxwxwxwxwxwxwxxwwxxwwxxwwxwwxwxxwx xwxxwxxwxxwxxwxxwxwwxwyxyyxyyxyxyxyxyxyxxyxyxxyxyxxyxxyx xyxxyxx yxyyxy yxyyxyyxyxxyxxyxyyzyzyyzyzzyyzyzyyzyzyyzyyzyyzyyzyy{z zyzyzzyzzyzyzzyzyzyzzyyzzyz{zz{z{zz{ z{z{z{zz{{zz{zz{zz{ z{z{{z{z{{z{{z{{z{{z{{z{z{z{{zz{{|{|{{|{|{||{{|{|{{|{|{{|{{|{{|{{|{{|{||{||{||{| |{|{{||{||{|{{|}||}||}|}|}||}||}||}|}||}|}||}||}|}}|}}|}}|}}|}}|}||}}|}~~}~~}~}~~}~}~}}~}}~}}~} }~}}~}~~}~~}~}~}~}~~}~}~~}~}~}~~}~}}~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~  킁􂁂    $    ! 󉊉  􊋊򊋋     󐏐򑐑 񑐑  󔕕vuvvuvvuvvuvuvvuvvuvvuvvuvvuvuwvvwvvwvwvwvwvvwvvwvvwvwvvwv vwvw wvwvwvwwvwvwwvvwwvvwwxwxxwxwwxxwwxwxxwxwxwxwwxwwxwxwwxxwxx w xwxwxwxxwxxwxxwxxwxwwxxwwxwwxxyxxyxyxxyxxyxxyxxyxyxxyxxyxyyxxyxxyxyyxyyxyxyxyyxyyxyxyyxyxyxyxyxyyxzzyzyyzyyzyyzyzyyzyzyzzyzzyzzyzyyzzyzzyzzyzyzzyzz{z{z{zz{{z{{zz{z{{zz{zz{zz{z{{zz{z z{z{z{{z{ {z{{z{z{{z{z{|{||{|{|{{||{|{|{{|{{| {|{{|{{|{|{|{||{||{|{||}||}||}|}}||}| |}|}|}||}||~} }|} }|}}|}|}|}|}}||}||}|}}|}}|}}|}~}}~}~}}~}}~~}~}}~}}~} }~}}~~~}~~}~~}~~}~}~~}~}}~~}~~}~}~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~􂁂       񊋋    􍎍  ꏎ       𕔕 vuvvuvvuvvuvuvuvvuvvuvuvuvuuvuvuwwvwwvwvwwvvwvwvwvwvvwvxwvwwvwvwwvwvwvwwvwvwwvwvvwvwwvwwxwwxwwxwwxxwwxxwxwwxxwwxwwxwxxwxwwxwwxwwxwxxwxwwxxwxwxwxwxxwxwyxxyxyxxyxyyxxyxxyxxyxxyxxyxyxyxyxxyxxzyyx yxyxyyxxyyxyxyxyyxyxyyxyyzyyzyzyzyyzyyzyyzyzyyzyzyyzyzy yzyyzyz zyzyzzyzzyzyzyz zyzyzz{{z{zz{{z{zz{zz{z{zz{zz{zz{z{z{z{{z{z z{z{z{{z{{z{z{zz{{z{z{z{{|{||{|{{||{|{{|{|{|{{|{{|{ {|{{|{||{||{|{||{{|{||{{|{||{||}|}|}|}|}||}||}|}||}| |}|}}|}|}|}}|}}|}}|}}|}}~}~}}~}}~}}~~}~}~}~~}~}}~} } ~}~~}~~}~}~ ~}~}~}~~}~}~}}~}}~}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~􀁀󁂂 킃  ꅆ 󇈈     !   񎏎򏎏 񐑐  󒑒   𔕔uvuuvuuvvuvuuvuvuvuvuuvuvuuvuuvuvvuvvuvuvvuvvwwvvwvwvwvvwvwwvvwvvwvvwvwvvwvwvwwvwwxwwxwxwwxwxwxwxwwxwxwxwwxwwxwx xwxxwxxwxxwwxwwxxyxyxxyxyxyxxyxyxyxxyyx yxyyxyyxyxyyxyyxyxyyzyzyzzyzyyzyyzyzyyzyzyyzyzyyzyyzzyz zyz zyzz{z{{z{zz{zz{z{{z{z{{z{z{z{ {z{z{ {z{{z{{z{z{||{|{|{|{{||{{|{||{|{{|{{||{||{||{||{||{}}|}}|}}|}||}|}}||}| |}|}}|}|}}|}|}}|}}~}~~}~}}~}~}}~}~}~~}~}}~}}~}~~}~ ~}~~~~~~~ ~~~~~~~~~~~~~~ 􂃂    '$򊉊  򊋋   쐑$     vuvuvvuvvuvuvvuuvuvuuv vuvvuvuvuuvvuvvuvwvwvvwvwvwvvwvwvwwvvwwvwwvwvvwvwwvwwvwwvwwvwvvwwvwwxxwxwxxwwxwwxwwxwwxwwxxw wxwxxwxxwxxyxyxxyxyxxyxxyxxyxxyxxyxxyxyyxyyxyyxyyxyxxzyyzyzyzyzyyzzyzyzzyyzyzyzzyzzyzzyzyyzzyzyzz{z{z{{z{z{zz{z{z{zz{z{zz{{z{z{z{{z{{z{z||{|{{||{|{{|{{|{|{|{{|{{|{|{|{{| |{| |{||{|}||}|}}|}}||}}||}||}||}|}||}|}}|} }|}||}~}}~~}}~}~}~~}~~}~}}~~}}~}}~}}~~}~~}~~}~~}~~~~~ ~~~~~~~~     񇆆  " 񊋊   񎏏󑐑    uvuvuvuvvuvuvvuvuuvuvuuvuuvuvvuvvuvvuvvuvvuvvuvvwvvwvwvwwvwwvvwwvwvvwvwvwwvwwvwvwwvwwxwxwxwxwwxwxwxwxxwxxwxwwxwxxwxxwxwxwwxyyxyxyxxyxyxyyxyxxyxxyxx yxy yxyyxyxyyzyyzzyzz yzyyzyyzyzyzzyzzyzz{z{z{zz{{z z{z{z{zz{zz{zz{z{{z{{z{{z{{z{{z{{|{|{{|{|{|{|{{|{{|{{|{{|{||{|{||}||}|}|}}||}}|}}|}|}|| }|}}|}}||}||}~~}~~}~}~}}~}~~}}~}}~}~}~}}~}}~~}~ ~}~~~~~~~~~~~~~~~~~~ ~~~~~            @       頡   󢣣  򥤤 즧      𪫪'𫬬򬭬      򲳲򲳳촳 " 򵶵 򸹹      󠟟  𠡠 󠡠  殮 񥦥  𧨧      񮭮     񱰰 񰱱    򷸸!  𜝜󝞝  򠡡    ᡢ     𥦦獵  𩨨 󫪪 𪫪   ۮ     󴵴  ﷸ    󛚛        蠡      󥦦 獵   򩪪 𪫫     ﲱ󲳲  򴵴  ﵶ!   󛜛򝜝 읜  󟠟       򧦧 񩨩  쨩   𪫫󫬫       󰱰      #   븹 󚙙 󚛛    힟     𦥥 󥦦          󮯮    񱲲    󳴴 ﴵ񵶶    Ꙛ뛚   盜򝞞      񠡠 򡢢򢣣        񮭭   򯰯 ﰱ  񱲱  󲳲 򵴵   󷸷"       흞  򟠠 򠡠           򬫬 𬭭 𯰰     󵴵  򵶶    󛚚 望         򥤤  󥦦  򩪩       󮯮              𝜝    ퟞ    򢣣 񤥤򥤤 񥦧񨧧    쩪 񫬬     ﰯ󱰱        򙘙      󜝝    ꠢ  뢣     復򥦦  񧩨   򭬬          򸷸󸷷   𙘙򙚙򛚛  񛝜  񞟟     𢡡! 򢣢  񥦦𧦧  裡  󫪫      򯮮   汰  𵶵 񶷶   񚙚  򜝝 󞝞 󟞟򠟟   䡢           󫬬         򲳳   ﶷ 󗘗     𜝞  랟񟞟 󟠟        𡢢   𥦦 𦧦󧦦 󩨩  󨩩  񪫫      诮    𱰱            󝜝             𩪪   򯮮    糴     환    󝞞󟞞   񠟠)      󧨧    򭯮𯮮  *       񖗗  񘗙  󚜛 휝 읞   򟠠     襦 󥦥󦧧󩪩      !       񴵴 虘 "𙚚          򠡡 񣢣  󥤥  󨧧񩨨 󩪪     𯮯      񳲳     󗖗$񖘘    𜛜     죤  򨧨    欭              𘙘 񙚙󛚚  󝞝   ! 󡠡   碣𣤤    󧨧       髬 魮񲱲  䗖   󚙙  웜    񞟟  𡠠  񣢣򢣢 󤥤       𫬬뭬   󰯰   񲱲 𳴳  󗖖  痘     뛜 뜝   򞟟 󟠟   򤣣     򩨩 󪩩     磌쫬 嬭񭮭   󰱰󲳳 󳴴𵴵     𙘙   󝞞 󝞞򝞝 🞞  󢡡񡢡   󤣣 󥤥 𧦦    磌      𱲱 񴵴   𘗘  򛜛 󝜝  󝞞 񟞞   󢡢  󣢣     󨧧   򫬫﫬񬭬򬭬        񗘘    򝜝 󢣢     򭮮      򴵵󖕖  񖗗 횙  훜 󟠠   󦧧    쬭 򮭭 󮯯 󲳳  򗖖 ꗘ    !    %򨧧  睊  򴳴  @    󾽾 򾿿  "                           "  #   !#  (   !          򼽼                        򹺺  !    ﾿ ྿                    '         &    빺󺻻                             󸹹 񹺹    𽾽𾿿                              񺻺     㽾     $              #    𺼻      "                񹺹򻺻 󺻺󼽼                               潾                       ﹸﺹ    򼽼񼽽                            ϸ       #                               󹸸    𽼽 𽾽                    򻼼(               #            𾿿                       󶷶   𸹹                  !    %                                       񽾾                          񷶶   !𸷸 򺹹蹺  シ                         񶷶  񹺺                             鷸򺹹 򺻺򼻼        (                   򹺺󻺻                         󹺹                             򶵵  踹                          󸹹   򿾿     $            󹸸              󵶶 񹸹 󹺺            !      s^E/"){ outline copy     %j){jeq}){kkm7mGmWmgmwmmmmqDw{~29,(j]'7܊H%5EU .($ɡ"ƝtM<.**9`ڻqI 9e߻gH8 6jȅ2!M{Ȉ4&En߿^+F 8U U8-8q q8'8UUq ƍq8#8q ƍU!UqU8UƪU8q8Uƍq8UƍqU88ƪU @ @ @ @ زtE +ZƚZ. 0[ܮH0XϚk29gN !DoӤj4!D{俊S"(Qاo:.ZďT&2Wܨt8 Č`+5ڲxJ 5̟`2 4㳅F!5Μv=5ɍ]% 5ܱq?5œW& 5ڭ{C5ϗ`) 4}D5Қe+4߸}Q$ 5Ӧg84黌L$5ՠt94Œd/5ܸyJ6˞89<> U!q8U!ƍq8U!ƍq88q"ƍUU"qU8q"ƪU#8q!8q8qU8qU 8q"U#8q%U&8q(U)8q+U,U -8Uq 0U18q3U48q6U78q9U98q;8q==<:850`4Do4;g6?v4%T5/W{3 (O5 2a5 9e5?j5?o5 (T|5 (Jr5!M6.b4:e59k5!Q)Jv`0 &TJ!9bӝl32dˆQ U 8q'U 8q)U U+U8q!qU!q8U!ƍU U8q ƍq8 U8q q8 UU!U U8q ƪU ƍq qU8 ƍU/q8 -ƍU ,q8 *ƍU(ƍq8&ƍq8%q8$U"ƍU!q8ƍUq8ƍUƍq8ƍq8q8!ƍU#U$U$U#8#q"U!U UUUq8ƍU U!U"q8#ƍU%q8&ƍU(U)q8*ƍq8 ,ƍU .q8 /ƍq81ƍq83ƍU5qU86ƪU9qU89ƪq<x68:< ~=:85]{3 &Mt/ƍq85ƍq87q89U;8 }8<qU89ƪq87ƍqU84ƪq82ƍqUU8. ةj0 6꿅J!5ҝ^%5v<4ōN6ܤe/ )ܷ|C$CW|ҘX&  &Nxڮo7 "CW{ČL"Jxՠb) 84U4U4U4U4U4U4U4U4U4U4U4U4U4U4U4U4U4U4U4U4U4U4U4U484q4U5U5U5U585q5U6U686q687q7U888U8q98:q:U;8;U;q<U=8=> @ @ @ @ڳv= )XߣQo-Dܒ<ߊ6+bɀ2 څ/ Hy7څ/ -g}څ/ %Q@9j g$M$T8r&ڤQ0d(ݣ^.&M{.ܮ{03 5 r8q88UƍUUUƍq8UUq8UUUUUƪUUUqU8U8U#Uq ƍU%U8 q8'UƍU-Uq8/UƍU2Uq848UU8 q =8 <:;Ƀ<:Ɋ@9̊@8ΒC7ґQ6Ӧe66{9 6ƃ;6ɑQ"6اg/ 6q/6}?5ƓW(4߭x:6ɏb.5ܵyB6ΖV&5تo?5ēS&5ݧvH(5ĝvB5ɖ^24ܲj?4ڿ]$ 4ܱxM$4̣vL& 4ˠ{T*3ϩT*2Ө^43Ӳ[.2ڰaM*3ַT) 1թ|[D& 2ұ{O-0Ϥ^Q.1ֳe:"1غv57:=@=U8UUqƪU8q 8UUq 8q8UUq8q8UUq3Uq5ƪ9ƍqU6ƪq83ƪqU80ƪqU8.ƍqUU8)ƪq8 'ƍqUU8 "ƪq8 ƍqUU8ƪq8ƍqUU8ƪq8!ƪqUU8# ƪqUU8(ƪqUU8,ƪqU82qUU85>.47"o6^7!W6!`5$]5&e5(e5*k5.l//q/=eeVHHV02v182o 93 M|6NĊM!Iՠa)Jh*Ev9DQ!VTܤ^!$e9qv=+j!JȌN)h 2`ܤQ(b L{ܠ`& &t0dݵvB3QˍEJJӚJS 6V֞`) ` &Qlߵt;0q !=[{Ʌ= .q [tˌ@-ΌCC ϓT% Q Өj4 `8+q9 9ȅ< BɒS"Vاg/ "jq0.{x3 Cx:XĎO&&xդe( [l* )x k. Ct!v900@^$O"%Ot&ڤj:.9Mv(ḏ+. 52U1U0U 0q /8 .U -U ,U +U*U)U(U'U&U"ƪU"qU8"U#U$U%U&U'U(U)U*8+q+U,U -U .8  q ƪU UUU ƪUUUƍqU88qUƪq8UUƍqU8U8q8 UqU8UUUU8qUU8UqUU8qUU8UUUUUU U8!8qU#UƍU%U ƍq8'Uƪq8*UqUU8-UU48UU8 @ @ @ @ s s s s^E/"){outline     !9){]){AQ(8!|2mB[gYgigygsƪԌ  %<-FV\Nuq+u-| V}}TT}}*}T}}}}}}#}T}}}}}}𔝨}}}}}}}}}쎓}}}}}}}ꅃ}}}}xxyxvxyy{{}T} }}yvtoolkjklqqtvx{}} }ͮyvqnjgebaabbeejkorvx}}}}yrlhe^][WVVXZ[]`dgjnrv}}}}}Ǩ{rle`[VSOMMLLMMOSVX]`ehlqv{}T}|tne^XSMIFCCBBCEFJMQV[^eglrv{xog`WQJE@=:97679:<@CFJOT[^ehntx{}˨vne]TMD@:72/../0249;@DJOT[`ejot|}ĵ{tkaZOH@:4/+(&&(+.27;?DJOT[`ekqx|}ĵ{tj`WME?82+(%!!"&(-269@DJOV]agotx}˨}tj`WME=7/*&!!%(-26;@ELQV^djot| , %         !#$%&&%$"!  #&),/12344320-+'$   "&+/48;>ACDEEDB@=951,'"   "(.49?DIMPSVWXYXWUROJF@;5/)#   %-4;CIPV[`dhjlmnmlifb^XRKE=60)#  '09BKS[ciouy}~{wrle^VNF>70)#  '1;FPZdmv}yqi`WNF>6/("  %/:FR^juન}sjaWNE=5.("   +6CQ^ly༺}tj`WME=5.("  $0=KZiwĿ}si_VMD<5.'"  '4BQaqü|rh_UMD<4-'!  )6DTeuĽ{rh^ULD;4-&  )6EUfwļ{qg^TKC;3,% (5DSduļ{qg]TJB:2+%@}=}};}9}7}5}}3}}1=;:8 6 4 2 0 @ @ @ @vkdZQI@80*&!!$(-27;@FMTX^ejov{㾵xoe^TMC;4.&!$(.27 &2@O`pûzpf\SIA91 ".;IXhxûyod[QH? (4AO^m|»wmcYO "-8ESao}ºvla %/:FS`n{t &0:FQ^jw &/9CNZeq}ǿ %-6?JT_kvŽ "*2;DNYdozĽ &.6?HR]hs~ ")19BLV`kw  %,4HR]iu !(09BMWco{ $,4=GR]iu !(09BLWco{ $,4=GR]iu !(09BMXco{ $,4>HR]iu !(09BMWcnz $,4=GQ\gs~ !(08BLValw $+3HR]it# ")09BLWbnz% %,4=GQ\hs& !(08BLVamy( $+46/(" *XNF=5.(" )j`WNE=5.(" '}si_VMD<4-'! %䐆|rh^ULD;4-&  #⣙{qh^ULC;3,% !ᴫ{qg]SJA92+$  ļzpf\RI@80*# ûxndZQG?7/(" ºwmcYOF>6.'! ºukaWND<4-&  ~ti_ULC:2+% |rg]SJA81*# ƾzpe[QH?6/(" ŽxmcYOF=5-'! ļvk`VMD;3,%  º~sh^TKB:2+%  {qg\SIA81*$  ǿyoe[QH?70)#  ŽxmcYOF>6.(! ûvkaWNE<5-'! ¹tj`VMD;3,&  }rh^TKB:2+% ǿ{qf\SJA91*$ Žyoe[QH@80*$ ļxncZPG?70)# ûvlbYOF>6/(" ¹ukaXNF=5.'! ~tj`VMD<4-&  ǿ}si_ULC;3,% wƾ|rh^TKB:2+$ep|Ž{pf\RI@80)#T_juļyodZQH?6/(CMXcnyļwmbXOE=45>GQ\gr~ºuk`VLC)09BKU`kw~sh^T$+3HR]iuú !(09BMXco{ $,4=HR^jvƾ !(09BMXdp} $,5>HS_kw !(09CNZfr~ %-6?JUamy ")2;EP\ht &.7ALWco{  #+3=GR^jw  (09DOZgt  &.7AMYes  %-6AMYgu  &.8DP]l{  "*3>JXfu   !)2=IVds  #+5?KXfu  !(1;EQ^l{   ")1:DO[hv  $+3@ACDE   "$%')+-/1469;>@BDEGHIJKLMNOQSTVWY!   "%'*,/1468:=?BEGJMPRTWXZ[\]^`abdegikln-&  "%'*-0369BFJNRVZ]aeilorux{~[QH@93/+)()*,.25:>CGLQUY^bfjnrvz~mcYQIC>:8778;>BFKPUZ_dinrw{̀vlc[TOKIHHJLPTY^dioty~ٓvngb^\[[]`dhmsx~ᥜ{vrpoprux}϶Ž¿¿}zxwvuttƿ}zvspmjgeca`__^Ļ|xurnkhea^[XUSQONMLKKżysniea^ZWTQNKHEC@>=;;:99ɿyqjc]XTPLHEB?<97420/-,++Ǽyof^WPKFA=9630-+(&$#!  ƻti`WOGA;62.+'$" Ǽsh]TKC<50+&" wk`ULC;4-(#    ƻsg\RH?7/)#   ø~rf[QG>6.'!   øth]SI@7/(!  ĺxmbWLC:1*#"}#}T}}}}}}}}}}T}}} ᆌ݅}}{}{}}}yxvttvtvxvxvxxvyxy}oollkonoklklnnkolooqqx{{}􍌎eedbbaeedababdadbedeghjloqvx{||}[ZXX ZWXXWXZXZZ[]^`begjlqrrtvxy{{QQOO NMNMNOMNQQTVVZ[`adgghjjkloqrvxxEDF DCDCCDEEFHHJMNQTVXZ[]^^``baeggjlnn<;:9::;=<:988754310.,*(&$#"!!"$&Z[\\]^]\[ZYWVTSQONMKJIHGEDB@>;96420/../14opqrrstsrqponlkigedba_^][ZXWURPMJHECA?>>?AD ن~}{ywvusrqomkigda^[XUSRQPPRTW ٛ|yvspmjhfedefhk ٯ}|{zz{~      䴵⡢ߋttuvwxy{}^^_`abcdfhjlpsw{KKLMNOPQSVX[_cglrx~99::;<=>@ADFJMQV[agmt|++,-./0257:>BGLRX_fnv~ !"$&(*-15:?EKRZbjr{Ľ!$'+05;AHPX`ir{û $(-39@HPXakt~»#(-4:BJR\eoy»}v$)06>FNWajt~û{rjb &,3;CKT]gq{û{qh_WO#*08@IR[eoyļ{qh^UME>(.6>FOYcmwĽ{qh^ULD<5/:}}7}}}}5}}}2}}/}T-}}*}}}}'}%}}"}}}}}}{xt}ߨ}}|{yvtqol}}}|xxrrqnkjge}ڨ}}{yxtqqnjheea`^^}}}}{xxtqnkhgda`^][WVV}}}}xttqnjheb`^[XVTTQO}}}{xtqljge`^[ZVTSQONMMLLM }T}{xtqnjgd`]ZWVTQMMLJJIJ }}}{yrolgd`]ZVTQOMJIIFEEDEDFHIJ}T}{{vqojed^[XTQOMJHEDCBBCDFIJL}}{yvolhe`[ZVQNLJFDB@@?@BCEHJMO}T}yvrojeb^ZVTOMJEDC@?=<;;<==@BCEIJNQT}}}{vrolgd`]XTQMJFDB@=<;:99::;=@BCFJMOTW[}}|xtqljea]ZVQOMIDC@=;:989989:DJQX_fnu}  #(,17DKQX_fmt| "&+0682-(# ɿ|skc[TMF@:4/*%! |tme^WPJC=72-(# ûxqjc\UNHA;50*%! ¼~wohaZSLF?93-(#Ŀ|unf_WPIB<60+%!þzskc\TMF?93-(ýwog_XPIB<5¼{skc[TLEwog_W埡Ŀ{sjኍ¼~}yussuw{~ſoida_^^`bfinrw|»[UQMKJKLORUY^bglrw}ľIC?<:99;=?BFJNSX]bhnsy83/,+**+-/259=AEJOTY_ejpv|*&"  "$'*-159=BGLQV\bhntzB}}T}}.}T}}}+})󵮾ľ˾}'砛}}&暤˾%欄ξ$𡩨}#ꗓ˨}"鉊˸"ꀃºĨ}"}{yxvvx{!tqqoonoqtx{Ӿ˨!kjhggjnqv{˨}!b``aeglqxĺӨ}![ZZXZ[^`ehot{}!VTTVWZ]`glt{ĺӨ}!OQQSTVX]`elt{˨}!MNQSVX^agnv{º¾˨!LMOQTW[`ejqx!MOQTV[`dhot{Ĩ}"NQTX]aejot{"TW[`dglqt{¾˨}"X]`ehnrv{®Ĩ}#`ehnqx{Ӿ$glrvyӾ}%otx}}&x|ӗ'适˾}(񛞚}}*}},񘝤}}.񛠟}0}}}3}}5T}8}}:}}=}}:}}}8}}}6}}3򝜚}}1򛠟}}/𚛞}}-󝤤}}+ꂅ}})x}}}(orx|}&ehotx|}$X^bjnrx}}T}#NTW^dhntx}!CIMSX^ejotx}9=CIMTX^djot{}}039=CHMTZ^djqv{}2-*  (  '  % !!  $ #&)+,-.-,*'# #%)-047:<==;840+%  #27<@DHKMOONKHC>70)" "BHMRW[^abba^YTME=4+# !TZ`fkosuvvtqle]TJ?5+" !hntz}ulbVJ>3( !|znbTG:.# !ᐖxj\M?2&  ᣨqaRC5)  ᳸scTE6*  ĿrcSD6)  ý}n^O@3'  ýtfWI;/$ !vi\NA5*  !th\PD8-$ !ĿyodYNC9/& !㽷zqg]TJ@7.& "䯨ypg^UMD;3+$ #䞗~vne]ULE=5.'! #匄{skcZSKC<5/(# $yph`XPIA;4.(# %e]UMF?92,'" &RKC=60*%  (A:4.)$ )2,'" +%  - / 1 468;~=;97 4 2 0# ./*$ ,>71+&! *OH@93,'! (bZQJB;4-'" &umd[SKC<5.(" %䉁xof]TLD=5.(" #㝔ypg^VME=5.(" "ᯧ{qh_VMD<5-'!  |ri_VMD;3,% |rh^TKB91*# »{qf\RH?7/(!  @ @ @ @};}:}}9}}8}}7}}6}}6}}4}}3}}2}}1}}1}}0}󨝨}v/}{vl.}|vle-|tnd],T}tne[T,}益|vke[SJ+}}tle]TJB*}vog]TLC9)Txog^TLC92)}yoh`VMC;2*(}xqj`VMD;3+%'T{tj`ZNE<3+%'}ꨗ{rleZQI?6.&&}vle[SJ@7.&%Txog^TLC9/(!%}託{tj`VMC:2(! $}}vjaXOE<3*$ #}yog]SI?6-% #}衤{tj`VMB9/( "}voeXOE;2)! "}痜|qh^TI@6-$ !}vlbXNC9/( !}{qg]QI=2*! !嗝vkbWMC9/& "}|qg]QH<2(! "}tlbVMB8.% "}|qg[QF;2(! "}xlbWLB8.% "˨}rh^QF;2( #}揠vodXMC8.% "}vj^TI=2(! #}{qeZNC9/% #}vl`VJ@3)! }rg^QE:/& }yoeWMB7+" }vj^TH<2( |qg[QD9/% }vnaVL@4+! }菠th^TH;2& }|qe[OC9/% xlaVJ@6*! }tj^TH<0( }訠{qg[OD9.% }菓xlbVM@6*! }{rj`TI=2( T{qg[OE9/% ?<;987 6 5 4 3 '3 '12 '1=1 '2=J0 '2=JX/ '1=JXf. '1=JXfv- '1N_q  *7GXj|  $1?Pat  +8HYl  %1@Pcv *8HYl $0?Pbv )7GXk #/>Nat '5DVi}  ,;L^q %2ASfz )7HZm !.=Nau %3CTh| )8H[o !-=Nau $1ASg| (6FYm +:K^s !.>Pcx $1ATh} &4EXl )7I\q+:L`t}}}xrkg`XTMHB<72.(%!"%((*))(&"}{tnga[VOIC<72/)&!!$(*/23442/+($}}|vqje^WQLD=93/*&!"%).069<@@=:72-("ytlg`[TME@94/*&"!%(.28;@CHJLMJJEB;70*}}vqje^WQIC;60+&"!%(.28;BFJQTVXXWVQMH@:3|tlg`ZSLE@92.($$(+06:BFLQV[`deea]WSLE=xqje[VNIB;4/)%!!&*/4:@FLQV[`ejlqoolgb^VNI|xog`[SLE?82-&"$(-29?DJQV[bglqvxy|xvrlgaZSytle^VNIB:4.)$%*/6;CIOV[`glqv|xqke^{rje[TME?82-&!!&+29?EMTX`elrv}{tngxqjaZQLC;4.(""(.3:BIOV]ejqv{}xqvng^WOI@92-&!$)/7DKT^iu&0:FR_m{sh]RI@82.+)*,/5GR10$  !'.ó{hUD5)  %,3<ʻq^L<."   #)19BLó{gUD5(    '.6?HR]˼r^L<."   $+3;EOYdoƶ}iVD5(   !'/8AKU`kvοt`N=/"   $+4=FQ[gr}ɹlXF7)   !(08BLWbmyijxdQ@1$  $,4=GR]htξq]J:+  !(09BLWcnzɹ~jVD4'  %,5>GR]itŴxcP?/"  !(09CMXco{r^K:+  %,5>HR]iuͽmXF5'  !)1:CMXdo{ɹ}hTA1$  %,5>HS^juƵxcO=.!  !(09CMXdp|òt_L:+  $,4>HR^jvp[H7(  !(09BMXco|ξmXE4& \ $,4=GR]iu̼jUC2$  !(09BLWco{ʺ}hSA1#  $,4=GR]itɸ{eQ?/"  !(09BMXco{ȷydP>/" $,4=GR]iuǶxcO>."!(09BLWco{ǶxcO>/$%-5>GR]iuǶxdP?1&#*1:CMXcnzǶyeRB4*##(/7?IS^iu   "(-39?DJQX^djqv|  $(.29@DLSZ`ejqv{  %(/4:@FMT[`elqv|&  %*065-'!!&-¹xmbWLC:2,&# !#'-3:ƾsh]SIA93/,*+,05;BJúzodZQIB=:88;>DJR[ vlcZSNJIIKPU\en ƽumf`][[^bhox ¹ytpoorv| ȿ Ž ľǁ n{]ivMXdp}>HT_kx1:DOZfr~%-6?JU`lx"*2;EP[gs &.7@JUamy #*2;EP[gt   '.7AKWco|  $+4=HS_ly !(1:EP]jx '/9DP]ky '0:FS`o~ !*4?LYhx '1JVds  %,5?IUbo~  !(08ALWcp} %,4=FP[gs#*19BLValx!'/7?IR]hs~%,460+(''(,18@IS^jvº|rg\RI@70)$  %+2:CNYdq}żti_UKB91*$ &-5>IT_lxwlbWMD;3,% ")1:DOZfsĻzoeZPG>5.'   %-6@JUamzȿ~sh]SI@70)"  "*2Hui]RH>5-&   !(1:úzncWMC90)"   %-Ž~sg\QG=4,%  "wlaVLB90(!  ¹{odZOE<3+$  ż~sh]SI?7.'   ⌊yvqlga]VQLE@:40+&"!&*/49?DJOT[`ekqv|{vqkga]VQJD@:60*&"!&*/39?DJMTX`ejoty{xvokg`[VQJD@:60*&"!&*/29=CINTX^ehnqx{roje`[VQLE@960*&"!&).29=CHMQX]bglrv{he^ZVQJE@:60+&"!%(.286/(" zpe[QH?70)# ¹}rg]SJA91*$ ûuj_ULC:2+% ļwmbXNE<4,&  ŽzoeZPG>6.'! ǿ|qg]SI@80)" }si^UKB:2*$ ûtj`VMD<4,&  ȿvlbXNE=5.'!  ŻyncYPG>6/("  Ĺ~rg\RH@70)# ŹzmbVLC:2+$ ȼxk^SH>5-&  ´zl^RF<3*# ʽrcUI>3+# Ⱥ|l^PC8.& Ⱥ{k\OB6,$ ɼ~n`RE9/& ufXK?4+# ƹpbUI=3*" }obUI>4+# ʿ~qdWKA7-% ɿtg[OD:1(! xk_TH>5,% ù}pdXMB90(! Ƽvj^RH=4,$  {ocXLB80(!  Ļui]RG=4,$  ȿ{ocWLB80(!  ùti]RG=4,$  Ǿ{ocWLB80(!  ùth]RG=4,$  Ǿ{ocWLB80(!  ùth]RG=4,$  Ǿ{ocWLB80(! ùth]RG=4,$ Ǿ{ocWLB80(! ùth]RG=4+$  Ǿ{ocWLB8/'   ùth\QF<3+#  ǾznbVKA7.&  ùtg[PE;2)" ǾymaUI?5,$ ¹~rfYNC90'  ǽwj^RG=3* ¸|ocWK@6 Ƽth[OD yl_S ĺ}qdv Ⱦudq~ T`ly ŻDO[hu Ⱦ6@KWdp} ·*3=GS_lx  '09DO[gs %-6@JVbn{ "*3DJPV]dkry #'+/49>DJPW^emu} "&*/49?EKRYaiqy "&+05;AGNU]emv~  #',17=DKRZbjs|  $).4:AHOW`hqz "&,18>FMU^gpy  $*/6=DLT]fox #).5- ")0/ $1 3 5 79:<=<:98 6 .  "  -%  :0(     H=3+#   WLA7-%  h\PD:1(!   "#$%&'(()ym`TH>4+#   "$&)+-/1245667788~qdXLA7.&   "$&(*-/247:4,$ #&),/258BFJMQUX\_bfimqtx{~ȿuh\PF=61-++-/259=AEIMQUY]aeimptw{¸yl`ULD?;99:4*" 8AJT_juugYMA6,# +3;DNXcnzøwi\OB7-$  &.5>HR]htƻzl^QD8.% ")09BLWco{Ⱦ|n`RE:/% $,4=GR^jw~paTF:/&  !(09CNYfs¶qcUG;/%  $,5?JVcp~ørcUG:/%  !)2JXfuƹ{jZK=0%  (2=JXfuķxgWH:.# '1=JWfvõudTE8,! '1=JXgwqaQB5) '1=JYhx˾n]N?2' (2>LZj{Ȼ{jZJL]nǹvd (4BRcuõp !,9GXi|̿| $0>M_qȺ )5DUfyĵ "-;K\o̾ '3BSfyƷ !,:J\o &3CTgzȹ  !-;L^r (5EWj~ #/>Obv     *8I[o  &3CUi}  "/>Ocw))('&$#!  +9J]r88765420.+($   '5EXlJJIHGECA>:61,'" $2ASg|]]\[ZXVSOKFA;4-'! ".=Ocxssrqpomjgc^XRKC;3+#  +:K_sՆ|xrle\SJ@6-$)7H[pԜwndYNB7-$(5EXm԰vj]PC6+"&3CVjyk\N@3(&2BTh~@=}=}<};:}9}}9}87}6}65}4}4􆏗3􂊓}}3}2x}1q{1jr}}}1dnx}0^gq{}}0Vbkv/Q[gq{}}/LVakv.EQ[eq{}.@LV`lv}.;EQ]gq|-7BMWbnv}}-2;FQ]hq|}-.8BMXbnx,(2." +ȸ}iUC3% +ͽo[H7) +±u`M<-  +Ƕ{fR@0# *˻kWD4& *p\H7) *òu`L;, * @ @ @ @ ~};}}:}}:}9}8}77}6}6˨6} ?;::98 7 7 6 6  5 &5  ,xoeXMB7-$ }xl`VJ@4)! }}tj^TH<2(  }鏠{qg^SF;0&  }yqg[QE9/&  }{og[ND9.$  TxoeZOC9-$  {ogZMC8-"  {qe[NB8-"  }{qgZNC7+!  }|qg[MB7+!  }}rgZNB6+! &}騠{qe[NB6+! &}騠{qe[N@6+! &}騠{qeXN@6+! &}騠{qeXNB6+! &}|oeZMB6*! &}{qeXMB7+! &}{qeXM@7*! %{qeZMB7-! %{qeXMC7-" %{qe[NC8-$ %}{qe[NC9.$ &}{qg]OD9/& &}鏓{rg[QE;0& &}鏠{tj^TI=2( &}vl`VJ@3)! &}xoeXMB7-! %}{rg[QE9/% %}tj^TH;2& %˨xnbVJ?2( %}|qeXM@6* $}}rh]OC7+" $}}vh^QD9-" "}}th^QC8-$ !}|tg[OC8-" }xoeXMB6+! }}䝠|tj`VJ?3( }}vkdZND:/& }}ytne]TI?6*! }}vqke]TJ@9/& }ytlg`ZSJB92)! }}vqjd^WOI@92+$ }ytng`ZTME@92*% }T}}vojd^VOJC<60*$ }{toga[TMF@92.($  }}yrje^WQJC=72+&"  }}xqjb[TMH@93/)% }|tog`[QLC?82-&" }T}yrke^VQJC;6/)&!!! }{vqjb]TMH@93.($!%()*))($ }}{rng`ZQJD?72-&""&).026430-(" }|xohb]VOHB;6/*%!!%(.27;?@@?;70*" {tng`ZSLE?92.(%!"&-07;@EILJJE@92*$ vrje^VQJC<70+($"&)/4:@ELQTVVQJC;2)" {vqh`[TMF@94/*&!!$(-28=CJQV[`ba^[TLC:2(! yrng^WQJC<82.(%!$&+/69@FMT[`gjnnje^TLC9/& xojb[TOHB:6/*&$"%).38?CJQW^ejqtxvtoe^TJ@7.$ voh`ZSLD?92.(%!!%(-27;BHMT[ahov{|xne[QH=3*" }vng`WQJC<70+($!!$(*/4:@ELQX^djqx}xlbXND:2(! }vne^VNF@:4/*&"!&).28?DJOV[bgnt{vk`VLB9/&xoe^VMF@92.(%!!%(+06;BHMT[`ejrx}|rg^TI@6.%{rh`VNE?82+(%!!$&*/39?EJQV^ejot{xod[QF=3+$vkaXOF@82+($!!!%(+07Pdy ,ITam{  !(09CMYer~  $+4=GR^jv  '/8BLXco| #+3;:;?FP\ix2?N^n}ƽ{ocXND<50--.29BN[jz9HXizth]RH>6.)$"!#'-6AN\l| "+7CM[erxrke[VOHB:3/($  %(/39@ "-8CMZgv}xog`ZQLD?82+&!   !&-28?DJ !-7CO[jvytog^WQJC;4/($  !&+06;BHOT !+8CO^jvxqjb[TMF@92+&! "(/39@FLSX` !+7DQ^jxvqh`ZSLC<6/)% !&+28=CJOV]bg !+7CQ]jv{tne^VOH@92-&!  %(/6;@FNVZagkt *6BN]htyrjd[TME?80*&  !(+28?EJQZ^ejqvy )4@MZeq{}xog`XQJC:6.("  %*/6;BIOV]dhoty &2?JWbktxyxtne^VMF@92+&!  !(-29@EMS[`elry| &/:FS]elqqngb[SLC<7/($  !&*/7;CINV]bjqv| "-7CMV^deeb^WOH@92-&!  $(.29@ELSX`glty (2;EMTX[ZVQJD<7/)$  !&+27=CJQV^djov} $+4=DJMOMJF@92.&! %)/4:@FMTZ`gnrx} &.4:@BCC?:6/*%$(.29@EJQW^bhov{ &-248863/*&!!&*/6;BHMV[agnqx $(+--+)&"%(.29@FMTZ^ekox{} !!"&-28=CJQV^bjqv|} !&+06;BIMT[`ekrx{}} %)/4:@FLSW^djqv{}  $(.28?DJOV]agnty}  !&+28=CINV[aglrx{}}  $)/4:@FMT[`ekqv{} !&-29@DLTX^ejqx{} !(/4;CJQW^dhotx} !(/8@FMV[bhot{} (/8@IQX`glrx}T} %.7?IS[dkqx} (261/04:BKU`kwù˻p_QF>;:=BIR\gr}ƽ;wgZPIGGKQYcny~pd[VTV[bjtĻ{Ʒ{phddflt}ȿth˽}wtux~¹xmbWķƽ}qf[PF˿vk_UJA7ȿĻzodYND;2*½Ǿsh]RH?6.& ¹wlaVLB91)"ż|peZPF=4,%uj^TI@7/'! úyncXMC:2*# Ǿ~rg\QG>5-& ¹wk`UKA80(" ƽ{peZOE<3+$ ¸ti^SI?6.'  ƽynbWMC:1*# ¸sg\QG=4,% ƽymbVKA80(! ¸sg\QF<3+$  ɿznbVKA8/'  Ƚth\QF<3+#  ɾ}pcWLB8/'   {m`TH>4,$  ƹ}n`RF;2)! ³rcTG;1(  ̾|k[L?4*! ˼xgWH:/% ˽xfVG9-# Ϳ{iXI;/% ôo^N@4)  ɺxgWH;0& ³rbSE9.% ʼ~o_QD8.% ƹ}n_RE9/&  ķ}oaSG<1(   öqcVJ>4+#  ÷sfYLA7.%  øvi\PD:1(!  źzm`TI>4,$  ǽ~qeXMB8/'  ɿvi]QF<3+$  ¸{nbVKA8/'!  Żsg\QF<4,%  ȿymbVLB91)#  ùsh]RH?6.'!  ǽzncYOE<4-&   vk`VLC:3,%  ƽ}rh]SJA91+$ ¹zpe[RI@81*% ȿxndZQH@81+% żwmcYQH@92 ºvlcZQIB vmd[S ǿwnf ƾy ƿ ƿ  FNT]djqx|}}T}QX`elt{}}"}}[bjqx|}#}elrx}}}(}ov|})y}}+˾},}.󘖠}0}}2}3}5}T}7}8}:}<=}<;}};}:}::}99:}8}8888}}7}}}5T}3˨}}0}}}.}}}},}쨱})}˨}&}󗨠}}}$}炅}}}"⾵y|}}} }otx}}}}}}}dhoqv{}T}}}X^dglot{|}}}TT}}NQW]bgjqrx{}}}T}}CIMQV[`ehnrvy}}}}}T}}8=CELQTZ^bgjotx{}}}T}} 㶬vkaVLC:1*# zodYOF<4,% ~rg]RI?7/(! !vk`VLB91*# %odYOE<4,% ']RH?6.'! *LB91*# ,=4,% -/(! /# 1 2 4 679:<;;::9 9 9 8 8 8 88 8 7 4 2 1  /  ,  )   ' ,'" % ;4.)$ " KD=60+&!  ]UNG@93.)$  qh`XQJC=71,'# |tld\UNG@:50+&" xph`YRKE?94/*&! ի|tme^WPJD>83.)%! yrkc\VOIC=83.)%!  ƿwpib\UOHB=72-)$!  ܠ}xqkb]VOI@92-&!   &/7{rng`XQJC;4.(!   !(/9vqje[VNE?82)%  &-3;}xtle^WQIB:3+&  !&+29B}}|vqjb[SJC;3.(!  %(.39@F}ᝤxqje[TME?7/)$  $(-27;@FM}}{tle^VOH@92*%   !&).26:?CIMQ}}vog`XQJB93.(!$&*/27:?CFJMQV}xogbZTLD<70*&!"&)-038;?CEILNQTV}}}yrjb[VMH@:3/*&"!!"&(+/279<@CFILMOQQST}{tng^WQLD?962.+)(()*-/269;?BDFJLMNOON}{vojb[VQJE@<974344679;?BCFIJLMMLJIF }}}vqke`[VQMIEC@@BCDFIJLMMLJIHEC@= }|xqlgb^WTQNLJJIJJLLMMLJIFDC@<973 }}|xtnhe`]ZWTTQQONMLJHEC@<973/-) }T}}|xrojeb`[ZWVTSQNMLJFC@=:730-)&"}{vqlhea^[WTQNMJFC@<942.)&"}}xtojga^XVQMJFC?:73/+(%! }}{xqlgb^[TQMHC?:62.)&" }yvqlgb^XTMIC?960-(%!  }֖}yvqlhd^ZTNJD@94/+($  }}{vrojeb]XTNJC@93/*&! }{xtolgb^[VQLHC?93/*%!  }T}}xroje^[VSMHD@:72-(%  }{voje^ZTOJE@<83/*&"  }}}vqne`[TNJD?:62-(&!  }}֝|vogb[VNJC?94/+&" }}ytkg`XQLE@93/*&! ׾|vqjb]VNIB<60*&! ؾ{vngaZQLD?82-&" }}{rle^VQIB:4/)$ }ۛxqhb]TMF?92-&! ٨xqgaZSJC<6/($ ۾}vog`VQI@93.(! ߡ}tog^VME=80*% ޝvoe]TMD=6/(! ࠝxog]TLD;3-&! ⮤|rh`VMD:3+& !㝤}vj`WND<3+% "埞xoe[QF<4-% $栛|rj`TJ@7.& %硞yoe[QE:2(! !螔vk`VL@6-$ }th^TH=2) {rg]QE:0&  }qg[OD:/&  {qg]OD9/(  |tg]QF;2(!    !"vj`TJ@7-&   !"$&()-xoeZNC;2+%!$%&()+/0248{tg^TJB:2-&"! !"$&()*-/22369:=@Cxoe[QIB:4/-(&%""!!"$&(*-/023689;?@BCFILM|tjbXQJC?:732/.--+**+-/023479;=@@CDHIJMNQTVXyqjbZTMHD@=;:9877676789;IT`my  !(1:DP[hu  %.7ALWdp}  #+3=HS_lx   (0:DO[gs  %-6@JVbnz  "*2IT`ly  ")1;EP]jw  '/8CO[iw  &/8CP]kz  '1;GTbq  $,6BO]l{  #+5AM[jz  &.8DP^l|  $,5?JVdr  %,5>ITan|  !(/8AKVbn{  %,4Pdx "/>Pcw !-CGKORUWYZ[\\[ZYWUSQOLJHEC@><:8642/-*(%#  "&*.26:=@BDFGHHIIHGFEDBA?=:86420.-+)'&$"  "%(+-02345677654321/-+*(&$#!   !"$%&'(('&%$#"    @JT^jt}ytrnkge`^[WTQOMLIHCB@=;:986322//-+)((&%%$$@JT^jt}{tojgd`]ZTQOMJFDC@?;98620/.-*((&&%"!!DMV`jt{|tohe^[VTQMJHDB?;97422.-*((&%"!IQ[bjry|vohd]WTNLHDB@<9742/.*(&&"! NV]ejqvy||{vohb]VQMID@=9832/+)&&"!    SX^ejnqttqnhb]VOJE@=942/-)&&"     V[`bgjkjjhe`[VNIC?942.*(%"!  X[]`aa`^[WTMIB<82/*&%!  VXZZXWVQNJE@;60+($!  TSQQOMLIEB<93/*&! MLJHDC@;93/+($ DB@<972/+(%! :842/*(%! "0.)&$! %&" ) , - .11 2 2 1 / ", !&+* !&*06' !&)/49@% "&*/49@DJ# !%)-27:@EJQV  "(+/39<@FLOT[` !&*.38;@DJNSX]agk $(-27;@DJNSW]`ehlqv !&*/39?CIMSW[`ehlqv{ $(-27;BFLQV[`ejorvy} !&*/39DLVbn|MIEA>:630-+)((),06>GR^ky;841.+(%#  %*1:EP]jx,)&$!!'/9DP]ky '0:EQ_m{   !)3=IVdr   &/9DQ^lz    '/8CO\ix  $+34.,-2;HWh{ɽq`QD:2..18BP`rɾueVI>60/06?KYj| ɽwhZMB9301474248?ITbrŻsfZOE=74248?HS`o|ocWMD<73348?GR_m|úxl`UKB;63348?GR^l{ƽ~sg\RIA:63359@HR_lzxmbWNE>84235:@IS_m{|qf\RIB;63225:AJUan{tj_VMD=731025;BKVbo}wlbXOF?940..15;CLWcq~zoe[QHA:40-,-/4;CMXersh]SJB:4/+))*.3:CNYftaWMD<5/*'&&(,29CNZguQG>60*&#"#%*08BMZgvD;3,&"  #(.7AMYgv90)$ !&-5@LYgv2*#$+4>JXfu.& ")2=IWeu.&!"(0;GUds1)$!!$(0:ESbq7/*((+19DQ`oA93115;DP^m}ME?<=@GQ]k{[SMJJNU_ky kb\YY]cmy ˼|smiils| ô~{z} ʼ ó ʻ  ǹ ̿y ĵn ɻvc Ϳ|jY õp_N ǹvdSC ʽ{jYI: o^M>1 ötbRC5) ƹxgVF8,!  Ȼ|kZJ.! *ɹ|gS@0# )̼jVC2$ )ξlXD4% )ϿnYF5' )p[G6' )°q\H7( )±r]I7( )ñr]I8) )òs]I8) )òs]J8) )IJs]J8) )IJs]J8) )IJs]J8) )IJs]J8) )IJs]J8) )òs]J8) )ñr]I8) )ñr]I7( )±q\I7( )°p[H6( )oZG5' )ϿnYF5& )ξlWD3% )̼jUC2$ )ʺ}gS@0# )ȷzeQ>.! *ŴvaM<,  *ñs^K9* *ϿoZG6( *̼kWD4& *ȸ|gS@0# *ijvbN<-  +οq]J9* +ʺkWE4' +ĴyeQ@0# +;r^K:,  +ȸkWE5( ,wcP?0# ,ɺo[I9+ ,ózgTB3& -q^L;-! -{hUD5' -龎r_M=." .|iVE5( .r_M=/# /|iWE6) /r`N=/# 0{hVE6) 0q^M=/# 1gUD5( 1\K;." 2RB3' 2H9,! 3?1% 35) 4-" 4& 5 6 6 7 8 89 @ @ @ @6}555˨5˨5˨556}6}6˾6}7}7}8}8}}9}:;}<}= 6 $15 '55 *85 +:5  ,;5 +:5 *85 '55 $15  ,6 &6 !6 7 7 8 9 9:;< {oe[TJ@92-&%!!!!$(*/49@FLQZ^ejqx|{qj^VMC:2(vlaVMD;4/)&"!!$&(.285-%  '1=JXfu9HYjzymbWLB90(!  '1=JWf2@O^n|}rg\QF=4,$   '1=IW+8ES`ny}tj`UKA8/(!   '1BEFEC@<60*$   !&+/356541-)$    #&'('&$!          "%)- ! " !&)(! # !/(! $ 8/(! % ?6/(! % F?8/(! 'OH?8/(! (WOH@82)$ )`WOH@92*% *h`ZQJC:2+& )rjd[SMC<4.(! ({tje[VMD?6/(! &|tke^VMF?80*% %䉂{tng^WQJ@93+& #㍊}voh`ZQJC;3.(! "ᖎ}yqjb[VME=80($  ytle]VOF@92*% ޜ{tng`WQIB:4.(! ߨ|vqhbZTLD=7/)$ ݠ}xqje[TMF@92-&! ُ{tlg^VQJC;6/)$ ח|voh`[TMD?92-(! }ר}xqjd]VNIB;6/*%! }}ם}yqne^XQMD?93.($ }}ތ{tojd]VOIC=72-(" }}yqng`XTMHB<60+&! }T}{tojd^WQMF@;60+&! }}ytogb[VQLE@:4/+&! }{vtkga[VOJD@:4/*&! }}|vqjg`[VQJD?:4/*&! }ytoke`[VOJC?94/)&! }}}{vqjg`[TQJD?94/*&!  }{vqkga[VQJD?:4/+&"  }}ؖyvojg`[TQJE?:42-($!  }{vqkg`[TOJE@:72-(%! }yvqlg`[VQLE@<82/)&" }}yvqje`]WQMIC?94/+(%!}{vqlga^VSMJC@:72.)&"}ؗyvqngd^XTOJDB<830+(&!}}ࠤ|vtnje`[VQMHC@:73/+(}}˵⠤xtqke`^VTNJEC=962}䠛yvqlgd^ZVQMJE@<}硟yvqlje`]XTOMH}ਗ}xvolge`]WT}⨾}yvrojgd^!}䨾}{xqoj#}}|yt%}}}'}*}},}}/}}1}}4}7}9}}=       u et VdsHUcr;GTbp~0:FR`n|%.9DP]ky $-7BN[hv#+5@KXer!*3=IUbo|   (1;FR^kx  &.8CNZfs  $,5?JUamz  !)2;EP\ht  &/8ALWcn{  $+4=GR]ht   (08BLWcnz  $,4=GR]ht  !(08BLWbmy $+4=FQ[fr} !'/8AKU`kv $+3;ENYcny   '.6?HR\fq|  #)19AKT^is~  %+3;DMWaku   &-5=FOXblv "(/7?GPYclv #)08@HQZclu $*18@HPYbkt} %+18@GPXajs| %+18?GOW_hqy $*07>EMU]fnv~ $)/6=DKS[cjrz #(.4;AIPW_fnv} "',28?ELSZbiqx  %*/5;AHOV]dksz #',27=CJQW^elsz"  %).49?ELRY_f$ "&+05;@FLR& #',16;@(  $(,0*  #- 0 2 58</27:@DINTV[`egkorvx|}}}}}}TT}}%(-049=BFJOTX^aehloqtvx{{}}}}e}}ܨTT}"&)/27:@CIMQTZ[`dehjnoqrtvxy{M}}!%(-249<@EIMOTV[]^bdghjloqrvv{{} "&).269=@DHLNQTVX[^`aeghjoqqvxx{ !%(+.249;@BEHJMOSTW[]^`dehjlorvvx{{} !%(+/238:<@CDHJMOSTW[]^adehjnoqttvy{{}{}} !%&)+/2479<¿{wsplifca^[YVTQN|yvspnkheb¾~{x         $%+-1,*$! ߩ ܕ ր lryX^djpv|FKQV\bgmsy5:?DINSY_djpv|'+/38CGLPUY]bfjosw{ !$'+/36:>BFJNRVZ^bfjnrvz~ "%(+/259<@CGKNRVZ^aeimqtx{ !$'*-0369<@CGJMQTX\_cfiloqsvxz|~  "%'*-0258;?BEHLORTWZ\^`begijlnopqrrs  "%'*,/147:=?BDFHJLNPRTVWYZ[\\] "$&(+-/13579:<>?ACDEFGHIIJJ   "$%'(*+-.0123556778   !"#$%&''(()  }T} 쨚}}}T}}} } }}}}}}}} }음}} 卅 􉅅}{}y}}}}}{}{yxvvtqtqttvvy{}}}{xyvvtrvtrqqoonkjhgllnnonnoqttxx{}xtqqollnlkjjhggeeba`][`aadbegjloorrvvxvroljgeeddbbaa^^][ZWVTQQVVZXZ[]``deeggjjkkjgedb`^[ZWXVVTQOMMJIHDJMMNQQTTVX[]]^``b`^][XVTTQONMLLJJIHFDC@@=;9@@BCCEIIJMNOQTTVTQONMJHEECB@@?=<;::86332/4677899;;=@@CCEFIIJIFEECC@@=;997763322//.+*(&&*++-../2234899;<<=<;986422/..++))((&%%"!!!"$%&&()*+.//020/.+)(&&%$"!!!"$%%&&(&%$"!!                    X702/ /   -    ' !!"%+!"%&((*-/+!"$&&)*-//23479$*$%&&()*-./22479:;?@CC.-#-./0023689;=@CCEFIJLN887 89;=@CDEIJMMQTTVXX@@'BCDEHILMNQTTVX[^^aadJJ*MQSVWX]^`bdegjknoTT%VWXZZ^^`beghjkoqqrtvx`)`abeeghknqqvtxy{{}hhghjknoqrqtxyy}}oonrrtooqtvx{}{}tt{x{tx{}}yy }񂉎} v}􆏏                     !#&(! !#%'),.137+)'%$"!  !"$&(*,.1368;>ADH:7531/.-,++**+,-.02479<>ADGJMPTW[LIFDB@><;::99:;=>@BEHKNQTWZ]`dhlp_\YWTRPOMLLKK JKLMNOQSUX[^aehkoruy}uqnligeca`__^^_`acegjmpsvz}~|zxwvuttuvwxz}ߠ¿ᵶ""$%.1A362 )5/1& *'''& ¿&¿#찯 ꜛ~zvso!톅~|ywtrolieb^Zsstsrqponljhfdb_]ZWTQNJG]]^]\[ZYWVTRPNKIGDA?<96JJKJIHGFEDCA?><:8631/,*'88987654321/.,+)'%#" ))* )('&%$#" #   ב{xvqkg`XQJ@90)" ㌗|{{yxxvtqlga[TLD;3-& 受}yxxtrqqoqrttqqnjd^VNH@7/(! {{vtqokjgeebbaadeghknoonje`XQJB92*$ }{xvrqlheb`]ZWVTTVZ^`egjnnljg`[TMD=6.&! }{{xtrlkgd`]ZVTQMLIHFEFFIMOTX^bgjklljgb^WOH@90)" }{xxtqonjgd`]ZVQMJHCB?;99799:?CFMSX^bejjkjge`ZQJC;3+% vxttqoljgea^[XVQMJFC?;942/.++-.26:@EMSX^dgjkjhe`[TME=6/(! ooljgeb`^]XVSOMIFC?:740.+(%$!!"&).39@FMT[`egjjhga]VOI@92)" eda`][ZVTQMLHD@=;830.)&$!"(.4;CJQW^behjgeb^WQJC;3-&ZWVTQOMJIEB@;972/-)&$!"(/7?EMT[`dggeb^ZTME=7/(!NMJIFCB@<9842/-)&$!  &+29BIOW]`deged`[VNH@92)$CB?=:9732/-*(%"  !(/7=DLSX^adeeb`[VQJC:3+86420/-)(%$!  %+29BINT[^addb`]WSLD=6.+)(&$"!  !(/7=DLQV[^aba`]XTMF?"!  %+29@HMTX]``]ZTNH   !(/4;CJOTZ]^`^]ZTO  %*29?ELQV[]^^]ZT  !&.4:BHMSW[[X $)07=DJOTWZ[Z !&-39@FLQTVW$ ")/7AEJNSX]chntzLPTY]bglrw}_dhmrw|ty}܉ ವ  "$    þĿĿ Ŀ~w½xqjbxqjc]VOÿxrkd^WPJD>~wqjd]WQKE?94/2þ|uoic]VPKE?:50+&"ÿysmga[UOJD?940+'#|vpjd^YSMHC>94/+'#~ysmgb\VQKFA<73.*&" ÿzuojd^YSNID?:51-)%! {vpkf`[VPKFA<83/+'$  |vqlfa\WRMHC?:61-)&" {vqlgb\WRNID@;73/+'$! ~yupkfa]XSNIE@<840,)%" ɩzvqmhd`[WRNIEA<840-)&#  ̕~zvrnjea]YTPLHD@<841-*&#   Ѐ|yuqmifa]YUQMIEB>:730-)&#   kgc`\YUQNJFB?;851.+(%#  VSOLIEB?<852/,)&$! D@=:752/,*'$" 30.+)&$"  %#!  # ' +0" !&/7@IS[eov !&/7@HQZblt} (/7?HQXajt{ !(/8@IOXajq{ $)/9@JQZakq{} &*29BJS[bkr{}} "(/6;CMT[dkt{}} !&+29?FMV^glv{}  !&+27=CJQX`gov|  "(/61' ƺ|l\M?3( ǻ~n^OA4)  ȼp`QC6+! ɽrbSD7," ɽsdTF9-# ʾteVG:/$ ˿vfWI;0% wgXJ=1& ķyiZK>2' Ȼ}l]N@3) ³raRC6+! ʼziYI;/$ ǹtcRC5* ŷq`O@2' Ʒq`O@2& ȺtcRB4( ˾ziXH:-" õq`PA3(  ʽ{jZJ?AFMU`kxǺ{jYJ0  #+5@KXer˾ygUD5  !)3=HUbo}ôm[I9   '0;FR_lzƸr_M<  &.8CO\jxŸs`N> $-6AMZhv¶r`N>  "+4?KXesƻo]L<  !)2=IUcp~ļyhXH9 '1;GS`n{ľ~o`PA4 &/9DQ]kxrdUG:. %-7BNZgtzocWJ=2' #,5@KVbnyzqh^TI>3)  !)3=GR]gpxztmf_VNE;2)!  '09BLU]ekorsrpmie_ZSMF>7/'  %,4=861036533)- *''%%##!(&$*43<;>8558;:937153310+ $$" '%$## &&$/43;:><:33298760+*10.. ##""%$"! 0.8<;98A>8510364431-/.- !#)'%%#!('&$*47<:=8538;977-,3200+0)+ '%##! &&*.47:?A::3658754++-0/.,,. $#" $#"! $/.8;:9<>8750-64321(+.,++) ##""!)3<;>8758;:932/3210..)(*(' "'&%##!'&$/.1;:E<:4369765/*)0.-,+*)(' $$" %$#" )/47;:8A>8610254310(*,,+)+*% ##"""! $38<98738;973,+20/.-/(*)('%'  !*''%%#!!&&*.41;:B<:3668754+*,..,++-($%$" $$" '$$#" ).4;::A?9750025310++,+*)()($%  $#" %#"! $/38;9989=;4320/20/.,(')''&$%! ##" $#!('%*)37??85536:875/*)0..,*)('&%#!!  " '&$##! &%/44;:?A?3314664310+),+)(')$#! %$#"%$#" $/3<;98<>8:5313310/-0()('&%#$  %#""""!$/1<;>8537;:775/.-/.,+*,'&%$"   !*''%%##!&&$/.7;:C<:3219654310.-,+)()%$$  $$# '%$## /.87;98?>850/2330/.).')('%$%!  $#""%$"! $88A=8537;976,+.0/.,+*,'#$#!!    #" %%#!(&&*.41;:B::36586532-(.-+))'('#$    '%$#" &&).46:9850/2430/.)(')(&%$$  $$" %#"! $/38<9958<;976++.0/.,+)+'%$"   '##""'%$)47?:85:3698653.)+.,+)(')'"!" !"*''%##! &%/.4;::A?8750-6431/.)()('&$#$" $" '&$##! $/.7;9879<;932+2.0/.,*)''%$"  $#" %""!$3<;>85576:865/*)..,+)(')$"!! ##"%$#!(&$*.4;:?8:531/300/-+*('&%#"   %$#"%$#"!$)87>8748;:775/*)/.,+)(*&$" !%##""(&$*417:C<:3319654310')()('%$%! !! #)'%%##!&&$/47;:8A>851/-330/.,+',$&%#"" !!!  '&$## %*/8<;9838;977,+.,/.,+)'*&$" ! %$""%$""!/1<:=8537697543-0+-()('%$%!   $#""$#('&*/.7;:=A?86102430/.).#('&%#""    !*''%$## &)/47;98>>;973,+20/.,+)''&$"  $# %$#" $38;=853768755+)-.-,)('%$%!  "$#"""!&$*41;:B<:321025310.)+')(&%$""    #"'%%##!&&$/46;:8?>8543-+20/.,+*,'#$"  !"'&$## %/.8<99738;9754+*(.-,+)')'%!! " $$" %$"! /7<:=7:3659653210&,')('%$%"    " $#"""('&*/47;:=A>851/2330/.,+*/'#$"!  *)'%%## &&)/47;9899;977,+.0..,+)'*'%!! "  '%$#" $38;=8537687533-0'-')('%$%    $$""%$"!!$*417:B<:32102430/.)+','&$#!  ##""%$#!&&$/46;:8A>8583,+20/.,+)'*%#$!  " *''&$## //8<:9738;9755/)-.-,)('%$%    # %$#" $1<:=7:471965311/).')'&%#!!  #"""(&$*47;:=A>851/-/20/.,+*,'&$" !!  " #" %%##!&&$/47;98:9;9774/*)..,+)'&$%!   !"'&$## $/87>853769754310')()('%$""  "%$""!$/17:C<:331024300/,+*,'#$"!!  !!"((&$/.3;:8A>8:930+2-/.,+)(*($!   ! '&%##! $/4<;9848;:765/.0.)()('%$#    !!'&$#"! $.<;>85432966430/-,$&'&%#"!!  ! %"!$*.47:?A?875/1/320.-+*)')$"   !" $#!!&%/44;:8<><;875/*)..,+)'&$#$    !! %##! $/37;875869865310*)(&('%$" !!!  "!# $#"! $3<;:=?:350-6420/.,+)'#%#!!  !!"""'%*.4;::A?><536++.0.-+)('%$$  !! " #!!&&).8;:988;;8753.-'&,+)(&$#! !  "!" #! %/38?=8536536531/.,+*/'"$" !  "!" 0/.-/+)('(# "  "%" ""%"" %%"%"%%''*'%%'*'$'&)((&&%(0.-,+-('%#"" " ""% %""%"%'%%'%'*%%''),&&(*&%%*,,+)(&*& """"$"$"$"$'$$'$')$''&)((&((*'%,+*)''%$#""$""$$"$'$$')'$$'')$'')'&&(&(&%**',*,('%$!"""$"""$$""&$$"&&$$&$&$$&&)&&)(&&%*(%%')*)''(#!"""$""$"$$"&$$&$&$$&&)$&&)&(&&%(*''%(&('%#$""$""$"$$" $&(&$&&(($&&(&(**'%'))'$+'%$!!!$!$!$&$$&(&$$&&$&&(&%**%%&((&%&"!!!!!$!$$!&$&(&$$&&(&#&&((&&(*(%%'))'((%$"!!!!!$!!#!&##!&&##&#(##&&(&#&&*&&%%*''%')(&&($"!!#!#!##!&#&#&##&&(##&&(*%%(**'%'))'$((&&(""!!#!!!#!#!!##!##(%%##%%(#%%(*%%(**%%)&('%#!!!!#!!#!#%##%#%#%%(%%'*'%%'))'&((&&'!#!!#!!#!##%(%##%%''#%%''%'*'%%))'&$(''%)+!#!!#! ##%##%'%##%%#%%'%'%%')'$$((&(%''24!!!  ## #%## #%#%##%%'%%'%')'%%')'&&('%%)26<   #  #%##"'%%""%%'%"%%''%')''$&((&&')068>  #  "" "%"" %%""%'""%%''$'))'$'))'&&(('%')26:@H   " " "" "%""%"$'$'$'))'$$&((&&')46>BHJ    ""  " $$""$"$'$$&(&$$&((&&('))46ELGPY  " "$"$&$$"$$&$&(&$&(('-68DJKRW^_"  ""$"""$""$&""$$&$$&($$#(&&('-68FLMVW^adcikl!!!!!#!#!!##%%##%#%''%%'%)+4<@FHNWW_abfnmjm!!!!#!!%##!!##%##%'%##'")%''/46@DNMVW^acfiopmm!!!!#!!#%# ##%#%%##'%%""%'')'&/3<@FHNXY_^djnmmopp!!!!!# #%# ##%'%""%'%%$&&+36>FLMVW^adhiopoop!!!#  #%# ##% ""%'%%"$&&$$&&-59@FJNV[_^djjooqrqsp   ## #%""%""$&&$$&$(37>DLMVW]affknrqsqrtq   #"" "%"%%""$&&$""&$"&&*059FHNV\]^fhjopsrsurss   "  " "$&$""$&$$"&&$&37;DJKRW_affkprsttvsvt   "  "$" ""$&&$"$$&$$&(05;AGKTX[^dfjorstuwttuw " "" ""$"$&"$"$&&(048AEKQY[addkprsvvwuxuwv   "  "$""$&&""$&&$$#%%.48@GKSWY_dcimrstwyvwvyxyw  $ ""$" ""$&&$""%#%(%-48>GIOW[_bflnnotxxywzwxxzx  $" ""$"$""$%##!#%%#)48FJPR\^cgkmsry{~~~!!!!#!! "%"$"(24>DJPTW[ciilntxw~}|}!!! ""%  "$$""$(.2BFFEIKHLJPOORURSUUXWYVZ\Y[X\Z[[X\YWYZVWWXXWW'))'$((&&(''+48:@FFIKKNRSPRTVWVVXZ[[Z]\[\^[]\]YY\ZY\YZZWYWX$$&((&&('%')/669BHJGKMMNNROOPUTVSVVXXYZX\\]^\[^`^\_[[^[Y\YYZZYX)'&((&&%'')26:BHHLRRNPRSQUUTTUVVXXYZX\\]^`]^ba_`a]`^]_^^]\[[\ZY&&('%%)26:@FHNMRQUUTTWUWTXUUXWYVZ\Y]\^]^^ac`ac_aa``]_^\_[\\^ZY&&%''+46<@HHMRSPURVUUXWXZY[Z]\]]_]^`a^`a``caabaa`__`]__[[\Z''%)+4:DLGPUUWWZWWYZYYZZ\YZZ]Z^]`^^ac`abbcbdgbacab^_`^`_^]^[\[%)26:@HHNTVUWYZX[[ZY[\\Z[]\\[_\]^`a_`ca`ccdcddecb`c``ba^_`\^_[Z+26>BFJMRWWYX\][[Z^]]\[]\]\]^\]_`a\`a_`ccadeccddccbdbaba``]\]]\48BLGPYY[[\[_]]`]\`^_`^__a`_]^aa^ac_ccdcbdedfeddcddcbca``]_^_\\@FJLTXW[]][_a^__``b_a__a`_ab`^aa_`ccadedcddcgdffedebbaa_`_]^Z\FLKTW^]\^a_a^a`^bac`caabc``ac^`cb_cdcedcdgedgdeffddcc`a``_^]\]\\JNXX^]`__abbacbbdbaabdbabdc`ba_bcbacdcdfcfeeffdefecbc`aa`_^_]][[PUY]_`bccaccbbfcddebdadbacdd`dbcdfdcddedcffeffdeebcbe_a`^_]\ZZVW``b_aeddcddebdeddfeccddebcbdgdcdggdgfgeffeffcdf`ab`_^\\[WY_abcfebefdfcgfefdeghecfecbedacdccdcdgcffeffdfefccaa_^^]][YYV`bccgheefegdggffgfeghdfgefdfeccddeddffdeffddfcdedbbcaa``][\[VTU`dhhfeghgieihhgjifggdfgfcddefgddhdeffdeegcfeefedc`b_]^\XVVUUffehhgigiihiihgjhghjgfhghggfedfcdeefeeffgddedcbd__ZWVWVVYjihikhikijilgiijkjghjfhgihidffgdefefehedgfeebdcddba`[[YWWYWWijjijikljmjlikjilljhjjhgifgfgffefdegeebdcca`_^ZYZYWYYWYYhkljkkmkjnkljkljklkjjkjjghggeeffefefcgeefeddbaa`[YZZ[knkmnnmlmlmkknljillijkiijhhiffeffddfededdceddbb`^[[Z[[Z[\[\[[nnmmnmlponnkmnlmjmkjjkhkjhfggeffgcfedeedccbe`_`\[\[[\[\\^\^^omnnoonnponmonkmnnlkmkklihiigghffcfggcfecdcdaa`^Z[\\^\\^^__^^_^^qnpoprqpnpqmnonomnmlmlkmljhhigfgfefeedcceaca^Z[\\^^_^_``^_`^ppsqqprqpoppmnopoommlmjkjkjghghffefeecbcbb^]\\^\__`_``_``_a`qqrsurprsporpqpoopmmknlkjkhghgehcdedcc`^[[\_`a`aa`cacctssrssrprsoqprqoonnlklkjjifgfdbfbdbaa`][\\^_^_`aac`daadaddctuwsrsurqsrsqpopqqnnlmkkijghifebbaba^Z\\^\__aaccecceceddutwuvrsursttrqpqpqpnomnlkkiihffddcca`b^Z\[^^__acdeceedfededxutuwtruutsrqqsropopmmkjifggddbab_[Z\\^_^`acacceddfeefeefe_Wxwwtuwstuuturrsqppmlklkjjihfedcb`^[\\^`aceddffgffgc\VYvwywtwvuursrrqrrqnqpmljkjiggfca`^Z\[^^__`caaddfggie_YZWUyvyyuvwvuuttssqrpqpololkkjhggfdca[[\\^^__`accefgfiikgeZYWWVQzyvyxuvwtutsstspqqomllijiggca`\\^_`ac`ccddeffgiif^Y[YWTVRzzyvywvvwvuwstrsrqnpomkkijhfdca[^\^`__`cacdedeffgigjjcZ\[ZUWTTRx{zwxywwvvstwtqrppnmlkiggfd_^^_^__`accddefggijf\[[VYUUTT{x{yxxwtsrqqpomkljjgee__^__`acaccedffgfiikia\\[W[VVUTT{{|{yxxuxutrrqppnmljjhgd^__`cacdedeffgiie_ZZ[[VZWUWVTRQ|{zzyxxvuuvsspqpommkkged``acdefggigijjcZ\[ZWZWVVURTQ}~{zzywwxxutssrqqpnllkihe_a`aacadaccedefgfiijf^\Z[WZWWUVTTQQT|}}|zzxxwwxusrrpnmljhc`aacaccdcdeedeffikid\^[W[WWYWWUTQTTQL{||}|xyywvtwttqqoliieccdefggijg`Z[[VYYWUVVQOQ~||{{zzyxuttpqommkibccddedeefeefgfijjf[[Z\WZWWYYVVUTTVQQOO~}~{|zzywxuurqrqpljiddedeefgffggfiic[\[W[WWVUVVTYTVQOQQ}|yzxwxusqppnmicddeedeffgigigiijga^[ZZWYYWVWUUVTVOTLLOQOT~}|}zyzwwutsrqnmjdeefifgfiggiijijjf^[ZZYZYWWVQTQQT~~}|{{zyzuusqsonkeeffefggiijijjf\\WYYVYVWVYVYVVQOLOTOOQQ}~}|zzxvwvtrqokeffgijkjkjkke^[ZZYWWVUVVQQVQQJQQTOQQ|}}{zzwwuttqolggifiijkjjkkjlklc[[ZYYWVWVUVTTQTQQLOQ~}|{zyxvurqqmfggijklkllkd\[[WZVWWVTVQTLLOOLOLOOLOQO~~}||zxvvrpmiijkkjkknllnka\[YZWYWWVVUTTQTTQOOLLOQ|}{{xwvtsrogjijjklnllonoj__\[WYYWWUTVTVQOQOQLJLLOQLLOLO}||zxvvsqqjjknkllnnoonnok``^Z[YYWVTOTOLLQLLJLLJLLOO~|{zyvutqikjkklnonnoopj`_^^[YYVWTTQOJLJJLLJLL}{zxyvsqjkklnopqi`a_\\[ZWYWUVTTOLOTOLLJGJJLJLLJ~||zxuvrkkllknnopooqpqpqqkcc_\^ZZYYVTTQOJOOJLJJL}|{yyusnllnopqppsqtka`a`\[[ZYYVVTOQQLJLJJLLGGJGJJGLLVWUUTRSSRRSPQRNNOMMNKNLKKNLMMLLMMLLNLPMOONPOONNOMPPNPMPMJLKJKGWUVVUUSVSSQRPPSQOPPNMMKMLMLLMMQLOKOMJNNONNMPOMPMOMMOKLMJJHGWVWVWVUVSTUUQRRPQOOPNLNMNLMNLNMONLOPPOMNMPNOONOONOKOOLMKIIFFJFFXZWWUVTVUSVTRSRQPOPPNNOMNLNLMPONOMONQNOOMOMNPKNNLMMIKIJKIIGIIGYWXVWXWUVUSURRSQOPOONQLOMOPNOMNMPQNPNNOLNOLMMJKKLKLKLLKJKIIGJGXWYWVWWUVTTURSSQQRPONOMLONONLOMPNOMKOPMNLJKKLMLKJIZZXYUWXVUVTRSRRQROPOONPNPNLONKONKKJKLKLLMOMLMLMKKLMK[ZXYYWWVWVUVURTRSQOPLONPQMONNPKNNIJLKJLLMMOMOOPOQPOOMOMMKZ[WXZWUVVUUTUSSQOMQOPMKOOLLKLLKMMOMMOOPOQPQQTRQPPOQMPOOLOZZ[ZZXYXVUUTTQTPOPPONONLONJKKLLMMOPPQRURTRRQRQRQRPRMOPOP[YYXWZUWVTTQRRPOPKOMJJLKKLMOOPOOPQURURTUTVUURUQTQRQQRQPPMP[Y[YWXWWSWSRSRSQQPMNMIKLKLMMOPOPQTQTTUTVVTYTVUUVUUQUQTRTTRT][]WZYWVTUURPRPNLJKLLMMOPQRTTURTWVVYWYWYVTWUWUUVUVURTTQ]YZXXUVUVTRSNPMJKLMLOMMOLPQQRURTTUVVYWYWWYVYYZYWYWVWWUVTTUUTT[YZWXWVVSUTQOMLLMPOPPRTUTVTYVWWYZ[[\[[ZYZZWWYWWVUVUVUV[YYWYWUVSQQLMMPOPQURTTVUVVWWYY[Y[Z\[[\[ZZ[[ZYZYZY[WWYWWVU[ZZXXWSTPOOPMPPRUTTUVWUWWYWZZ\[[^^\[\[^[[ZZ[ZZWZWVVYZZXWUSOPPOQPQPOQRRTTURVWWYZ[W[Z\\^\_^_^`^^\^[[ZZ\[[Z[Z[YZUXUPPQQPRTRUUTUYVWYWZZ\[[^^_`_`_d`_`_[Z[\^Z[[ZYWVZWYWXWQRRQRUQRRUTVUVVYWYYW[Z\[[^^\__``c`ac`^[\[\Y[YZYWZWYWYYZZUYVTUTTURUTQTTUUTVTVVYWYZZ[\^^_`_a`a_^^ZZ\Y[[WYYWYZZUYVWWVVWWVUUTUUTTUUTUUWY\[[^\\^^_`c_``\WZ[[ZYVZYWYZVWWUVWVWVWVWUVVUVUUWVVYWYZY[[^\__``c_\ZVWZZYZYYWZYZYUYVYVWUWVWTUUVVTVWVVWYWYWWVYWY[[\\_^__`\YUVYWVYVVZYYWWVUWVVUWUVVUUVTWTVVYZWYYWZ[\[\\^^__a``^YRVVUWVVWYYUWVWVWVWUVUUTVTV[TVV[YZZYZZYZY\[[\^^`_c__ZRRUTUVRVRVVUWVUVVUUVVUVVYTTYVTVVTVVZ[Z\Z[[Z\[[^^`_d_\VQTTRTQQTTVTVUWWUVUUTVVTTYTTVTYVTV[QQVY\[^[[^[\\^_`_a^YRTTURRQQRQTQUTTUWUVVUTYVVTYVQYVTTVTTVYTT[TT[^\^_\^^\^^_`a^^WRTRTQRPRRQRQTQRUUTVWVVTYTTVVTVVTVYVTTYYTVVTV__`^^_`a_^VQURTPTOTQQPRTTPTTUTVVYTYVTTYVTVYTTVYVV[TTQYYVQVa__``_`_c^ZUQUUTPTOTQPQRRTQRQRTQVVTYVTVTTVVTTVYTTV[TVTTVYVVT`aa`a`d^YTRUUPPTPRPQQRQVQQTVTVTVYQTTYYTTVYQTQVVYQVVTQTTQTTcacad_YTRQTQQRRPRQQRQRRTQVTQTVV[QQTYTTVYYVTQVYVTVVTQTTQTTQTVOccaZRTQTPTRRQRQQPRRTTVTTVYVTVVTVT[TVTQVYVVTVTQTQQTTQQTOOTQOdc\TTQUPRQRRQTPQRRTRQQVTVTTVYVYVYVTTVYQVVTQTTQQTQQTTOOQOQ_UUTUPTQRRQTQPRQTTVTVVTTYYVVYVOVVTQTTQQVQQTTOOQOQQOOQLOOLVVUPTQRRQTTPRQROTQTVTVQVYYVYY[TYTVVTQTTQQVTQTTOOLQOOJLOLLVRUORQQRRPRQRTVVQTVTYVTTYYTVV[YYTVVQTTQTQOOQOOLJLJJVPTQPRRPRQROVQTVTVQVYVVY[[YV[YVTVVTTOOQOLJLLJLJGJLGGLUQPQRPRQRTVTQVV[YVV[VYVVYYVYYTVQTQTQQOOLOJOLLJJLGGLJGGJJQRQRROQTTVVQTYYTVV[[YY[VVTQOLLOJLLJLGGLJGJJGJLGGBEQRQRRTVTQVV[YVV[[YYVYYVYTTQOQQLLJLGGLJGJJGJGGEGERROQTTVVQTYYVVY[YVYYVYVYVVTOLJLGGLJGJJGGEEGGEGEBEERQTVTVV[YVVY[YY[YY[YYVTQQLOQLJOJGJJGGEEGGEGEBBEEBBEBQOQTVVQTYYVVYVYYVYVVYVVTTVOQQOLJJLJLGEGGEGEBBEE@BEB@BB@QTTYVY[[YY[YYVYYTTQOQLLQLOLJJGEEGEBBEE@BEB@B@@B@@QTOQV[TVVYYVYYVYYVVYYVVQTTOOTQQOLLJGGJGBBEE@BB@B@@B=@BB==@TTYVYVYY[YVYYTYYTVVTVOOQOOJJLGEEGG@B@BB@B=@B@@=@@=TTYVVYVYVQTQTOLOOJEBGEB@@B@@B@@=@@=@;=TVOVQYVTY[YVYYVTYVVYTTVYVTQQLEGGJGEBBEB@@=@@=@@==@=TTVYVYTTVTTQOOJLLJEEGEBB@==@=@=@==@@==;@QTTQVYTVTTVVYVVTYTQVQOLOOLGJJGJGEEB@@E==@;@==@==;@@8@@TTVTTVVTVVYVTVVTQQOQQJLLJLGGEBEG@@B@B@=@==@;=B@=@@TVTTQQTVQTVQTVTTYVYTTVTLOQQLLJJLGGEGGBEBEB@@=B@;=@@=BB=B@=B@BOQQTQTTYTVVYTTLOLJJGEEGEBE@EBB@B@B@=BB=B=@BBEQQTOTTOQTQQTTYTTVQTQQLLJGGJJGJGEGEEBBEBBEBBE@B@BEBEEBGEOQQOQQVTQTTVYVTTVVTOQOOQLLJLOGJGJJEGEEGGEGEBGGBEBEEBEEBGEBEEBOQOOQOQTQQTVQTQQTOOLJLJJEJJGJJGJJGEEJEEGGEBEGGJGJOLOOQOQQVQQTVVTQQOLLOOJLLJLJJGLJGLLGJGJJGLEJJEJLGLLJLLQLLQOTLOOQTQOQQTVQQTLQLOOLLJLLJOLGLJLJJLLJJGLOJJOLLOLJOOLQLLOOQTOQOOTTQTOQOQOOJLOLOLLQLOOLOJOQLQQOQLQTTOLVVTJJOQLLQLOQTQOOTTQOQTLQOOQOQOOLOQOQLQTOQTQTQTTVTVTYVVYYJLLOQLLOOQQOQOQTTQOQTTQQOQQOTTQTOQTOQQTTQTVVTVVTTYYVYV[Y^[Y[^`[OLJJLOLJLLOQOOQTQQOQTQTQQTQTTVTTYVYVYY[Y^^``^^ec``ccIFGEFECCAB?A@=>==<:;<:;8:9897:86677635134/32/0010141013024463FEBDBDDAAB@A@?@==;:8:7866755233123131311-0/.101013103325FFEDDEDDABAA@A@=@=?=<=;=;::886765520/-/../-0/.1/12234FGFEEDEBBAAB@@??A?=<=?<;;:<88:7766553122100-/-,,-.-/.01/23GFFEDBDBBABA@@?@?=<<=<;;::877665335232200/--,-+,,-/.01GJIGGIEEDBDDBAABA@?=?=?<;;876566323110//-,-,,/,-/JLKJIGIIFGEEFDEBBE@B@@A?@==?<=;;8;:8767663310//-,,-,--/LJJLIKJJGIIGGEIFFDDFBDAAB@A@=@?==<:<::;7:66765653110--,-/0MLLKMJKJJKIJGGFGEEDDEBAAB@@??@<==<=::;8:87363552210//,/-/0MOLLIKIJKGJFGIFGDFEDE@BAAB=@?@=;<<:;78768665312100-/0//-00OOPMOMOLMMLLKJKIJIGIFGFFEDDBABAA?@?;==:;8:877673361320/1-//01QQPOPOOMKLKKIJGIIFGEEGEEBBDBBAA?@=?==<;;:;:57765351220110-1/RPRRPOOMKMKKIJIJGGFGEEDBDAD@?@@=?<=<<;;86562321211TRRQRQQPOQOQMMLKPLLJJLJJGGFEJEFDBDBDA@A??<=<;;8::87665532303221TTRTTRQRQQPPOMLKJFIGGFEFDEDDBB@@D?@=<=;:;8:867665535125VUVTRRUTTQQRQROQOPOMOLMKLKJKGGEBA@?@==<@;<:8876763655355WYWWVWUUTUURRQQPOOMLMLKKIKKIIGGFGDEEAA@?A?=?<;<:;:;767663656YWWYVWVVWUVVUUTTRQPOMMLKJGJGFFEEDDBDDABA==<;<;::886687766YYZYVZVWVWWUURUUTQRQPQQPMOMKMLMLIKIJIIGGFFDEAA@@?@@<==:878868WYVVWUVWVYUVVWUTUTTRQQPPOMLMKMJJIGFDFEDDBA@@==<<;<;::887VUVVWUWTUUVVUVVUUTRQQPOMLMKKJIIGIFEFDDB@BAA@@?<:<;<;;8UVVUUVVUVUVVUWUUTURTRQPPQOMLLKKJIGFFDDABA@@=??<<;;:>==B@547756:99<;>;=>A@@DBCDCEIFGHHJIIHJJIGHJGGIFEEB=8:;5798::<==346578:9;:8==BACBDBFFGGKJHKIHHFIGJHHGDFFCC@>??65:9:88<9;;34557789;8<<;;?=?@@BDFEDIEGJIIJGIIHIGGJHGGFBC@B?=:75599::<>=1425669877<9==<<@??BCBCDEDFGIIHHJGJJHIIFHGIDJHGFFCC@BA;6:55:02053467::9;::<>@?A>@BDCFEEIGHGLFGJIIJHGGHFFGHDEEBBC@>=??8379978/1/034637789::<;97=657;900/2015246797<;;?>=?AACDAAEFFIHHLKJGKHHLIGJHHFEFDDCA>??<==9::55/101223226687::<@@>>BBCDEDFHGIIJJIJGJIJIIKIGGDHGDBDC@A==<;>?8601011323535356:;9<=?@@?AEDEFDDHIIJIKKJGKJGIJGHFFCBD?A@@==<;;=1102122356675677:;=?>;;=:<;11232232556677;7:=;@@BDCBDHGIJIFIJIIHIIJGFHEDECCBA@@??@<==<2251533556787:8:=<@@DGEJIHGIJIIJGIHEEDEEB>C@==?>=;=12332535567867677:8<;:<:>@<<:90335356637787788:8:;<;;=;;@@BCDGGFEIJKJGFHFGGFFDDCB@CA@>?<;;<<53256365676788:8:8<<;<=;==?ACFCIHFEIIFJIEEGEDEEDACB?A@=><>9:35363663767868:;7::;;<?=@=?CCFFHHGHFGEGHCFCBDED?B@??>=>;97635668776887:78<;:;;<==<<=?@?@DCGFFHGFCGGDCEDCBBA@B>@=><=<<76657687:88:8;::<<=?=<<9;87:7767887::;:<;;<<;??=??@@DBADABECDDFBDDED@@B>?B@?<>=<<7:88778788:;:;;<<;<<=?=??@?@A@@ABBA@BDADCCDADACBB?A>?@>?;:==;:;788;:;::<=;??@?@@B?BB@B@BDAAB?@?A@@CA?BC?>@>>=>=;<;<;;=<88::<;<;<=?<;>=;:??;<;;<::<;;<==<@=@?A?@A@ABB@DDBDDBD@A@@?<<@??@A@@?@?><<>:;;?==?==<<:=;<=;<==@?=?@?B@BAABDBDDB@A@?@??;;?=>??=>;?>=;=<>>=<=>=;<<;B@@AA??===;=;8:9;<9=<=8<;BBEBD@AA?=@=?@@?AADAABBDDEDGEFEDDEFD?BA?==;<;::77;9:;9:;;GEEBEBBA@@A@@A@AD@@BDEBDDEEFEFEFEFEBEBCDB@A@?<=::;8:78;8::9EEGGEGBEBBAA@AAB@ADEABDEFDEEFEFEEFBDBBAA@=@=:;:8:787797:9GGLEGEBEEBAB@BBDABEFEDDFGFFEFEEFEFEEBDB?@?@=<;;:87765778JOJGEGGJGEBEEBBABADBEFBDFFGEEGGIGFFEFEDGEFDDBAA??;=<:;8877375GLJJLGGEGGEGBEBDBEDDFDFGGFFGIGFFEFEDFEEDBA?@??:<<886677535LLOJGLGGJJLEEBEGEEDEEFGFIIGFGGIGFFEDEEB@A@>=?=8<:976673LLOJLLOJJLJGGJLGGEEFIGIIFGGFGGFFIFEDDABA?=<<:<::8775LJJLOLGJJGLJGEGGEGEJGJFIGIJGIGIJFFGFGDDBD@@A==<;7:87757JLOLLJJLOLGGJJGGJLEGEGEGGJIJGGIJFFGFFGFEGBBAA??@<<;7;:77JLOJJLJLLJGLGGEGGJJGLJLGGJIJGGIJGEGFEEDDEAA@?==;:;<;88JLJJLOJLJJLOGGLJJGJJGJGGJJGJIJIGGIJGEIEDDBA@??<:<::87JJLJJLJJLOOLJJLJGOJGGJJOLJLJJIGJIJIFIGJGGDBE@A?A==?;<<:7;JLJGJJLLJJLJJLOGLLGJJLJJLJJGJIIGJGGFFEBBAD@@??=<<;GJLJJLJGJJLLJLOJLJJLJGLLJJLJOLJLJJGJIIGIJEEDEBBABA@@==<;:AAEBFFHIELNLOORVWZZ_adhkms|񉆆==?B@B?CCFFHIIJLPQSTVY[^^efjmpy<=?@@A?CCFGIJNNQTVWY^\ccdjmrw::;;?@B@?AEDFFHKJNLNOSXY[^bcelott|:<>==@BAACFJFJMOPRUXZW[`behhmpy|5:<=?@@AACBFHIKNPRQUXZa[bbeiqrvy79978::;;>@BBCAGHHLMOPRUWYZZ`dgghorv|8499:<>==?@@BCCGJLMMRUUWW\^_ddgiqsxx8::55:=?B@AEEIHHNOQRUY[[\^cfillrr~;?=8779978<9;;?@BDGGKLLPRVUWWZ`acffiosv{=<;;=6497::<>>??ADDEGKHLNQQRVWY^\^afllsv}8=8<98:85577::<=??DDHGGKNPNRSYY[[`cciilpuw}:==@<=?;88:9::@>ACCFFHIIPNPQSTW]^^`chknoqxx><9;==:9;;3579:<>@>AFFHGKMOPPUUY[[``efhknpuw}Ȗ;6:7;;<:<;<679;9<@>ACEDHHMKMPRSUVZ[^``ehlppqxxȔ988:9;7;<<;=<6:;==@BDCEGJHKMQRRUWYZ]`cgjjmmpt|}87886:<:==<;;=<799==@@CEEKJNMMQRWWVZ]_dbehlprsz}9:5;6;799?=:@?=<:<>??BFDFGIIMOQTRUYY\^bdgijoort~~<9:87657879==<=?A:;;??ADFHEKKPOQQVYWYZ]cbdginrtww;:;87764588=:<=>?A:<@@?DFFHHKMMOQUTW[[_^dfgklnqtv~:987967448757;=C>@DA:@ACCEFFGMMRRQSWX[Y^^cdfgkpsvzw<786796552337:=??@>>?@>>AEGHJJMQOPSWTX]]_bchimpnss{|9;9985764346569;??=DD=BDDEGGJHMOPTSUWX]]^baejikquy{|898:6875647464::<>AACBB>@ADGHLLMOQRUYXX[_abehhornuz}{9899:7437787566<=>BAEDBCBEFGGINLLQQVSUW\__bcillmsu{}~:788665766778676;<<@BEEDFH@BBDGGLLOQSTUWYZ]aadgjjomru|{~889856877668788:78:DBIFIKEDDFIILPPSSUVY[\_cchijlooyz~~88:6:8:99:9;<<9;:>CDFHGGHCEHIKMQOPUUXZZ[_aacdhmpspwz}}88995:9879;:98<>;::;;?A@DHEKMHEFHLLMPRUSWX[_^aefjilnqsw{98878:977;:;;:;;:<<=:>;AACHHIGGHIIHLMSSRVWZ\\]_ccffjopvty||7569:7:<;::;=<;<=>><==CEFHFMMLGHLLNORTUYYZ]abbghlkkpsv{~4687788;<9<<;:<@==:?@>>@>DCCGJLJIJIKINOSURXY\^\_behhlrsxw{}}656568:89=<;:=>==<@>?@@?>>?AHHIHOOHKPNPQQVV[[\^cdfijlomrsx}7374776:<=;<==>;?@?>>BC@?@BDCEIKLLKNMKKPQUWVX[\`^adgjnlouvz~v|~6675569::9:>?=<<>=@>B@@AAB?AACGIKLPQOJMQPRSUXX\]^`cfhklorruux~|6755668;=<;@??=>?@B?A@DBCAC@FHKMOPMQNMMQRVYXZ]^b`chiknorry{}}87567675;;8=@?@=>A@@ACB@CCACCABDHKKMRSQNNSQTUWZZ^_``ehlljomvxwy}:77879<<><C>BC@BEDACDFECCDFJLMOSTUPPUSTVY\^``ehkloqqwzz;:88:978:8:9<>?=@BAA@AEBCBFEFEEFEDGLIPSSPURPQVVXYZZabbcdhknpsswu<;7<;::<:88=@@BA@EECDEGGFEGJGDFGKKQPSWZVSSUWZ[]]`bfdgkkoqqu?=<==;?=<<;<=?>DEFECCGFGGFIHGIIHIIQLTVWTWVTXZZ[^`cdhklnpsuA??@??@?<<==<==;==ABBCGFFEFHGHGHJKJIJIMOQRUY\ZSSWZ__cfgfinnprA@@A@==?=?==?=BCCEEHGGFIKKLIJMMLKMJPSSTUY\XPUU[\a_aegihiosABBADAABAA?@@=@@?>@BDGFHKJIJHJKLJLMNLKLMQSVWWVZ]]\_abigfhllDBEDDBBAB@?A?A@?@??@BCEGGIIHJMLLKKOPMMOLPSTVU[^YTVY^bb_biinjFDDADBDABB@B@AA@BDFGGILLKLJLMLMLNNJNQSXYWVUY]]_^acfiikkEBEDDEDEEDDBDAA@DGIHKJJINNLMLKQRMNOMRUVWV]^YVX[^ddbeiikDGEEFEEDFEFBEBDABEBCBBDFIHIJNMNLKMONOLNNLMRSUZZ[^S[]_]aeehkmGGEIGFFEDFEEFEEDBBDB@BBAFEJJLKONNOLKOPMMONRYW\Z[_Y\^_bdeffjFGFGGFFGFGGFEEFEEDBDDBFGJJMNONMOQONOLPPLPVW]]\^^W^]_ddgilGGFJFIGJGGIFGEFGFDDEEBDEDBGGKMNLLMNQNNOMMQONOORT\Y]_]`[`cadfikIIGIJIJKIJIIGFGEFFEEDBIHKJKPNOLLMSRPQNQQROSVY\]`a^Z\^bhffGIIKKIGJIJIJJIGGEGFFEFFEDFIKNPNLKMOOPORRQPQRWWZ]``_\]beddfJJIKJJLIJKJJKJJIJJHIGIFEFEEFFIKLJLPNNONPUTQQSSQTUWZ]_`ec\``bfgIJJKIJLKLKJLJJKJKKJJIGFFJGHIGGFFIJLONNOPOQQOPTUTSTSYY^c``b_cdgeGJLJKKJLMKLLKLKKJKKJIJJGFGIKLKMRPOPPRSUSSVUTVYZ[`]dgb]`deGLLKOLLMLKOKLLKJJIJJIFJLNOQMPQTSTSQPUUVSUU[\^b`a^cdd~{yvtqoolgege`^[[VTOOLHFA<31,"# ""#$$%!"#)*,'(*+,~~~{~yy{yvvqoolgee`^[[YTQQJKIA@81$"" !""# %&())%&')*+}}z}}xxusupnnkifdb__XUSPNLKFA<2-!  "##$%''#%%&..)}}zzxzxsspnniidd__XXSPPNID=751( ""##%%!##*,,()~{ywtoomjjfcb__]ZUSNLHDA:3*!"# ""%&'()+,'(~{ywtrrojhjcca^YWWUKKD=<1-  #$%&'#$%%'{~{{ytrrojjhca\YWUPPOFA;42-$" !##$%!"#)*,}zzxxsqnnlgeeb][TTOLLID?73#!!" ""# %&()),}}z}zusqllie``]YVTOJLFA;7,# ##$%''#%~{yxussqlige``[[TQOLHD<;4,'! !"##%%"##~{ywtrmkkfdd__XSQNLFD?>4,  !" ""#%&(@ˁ~~~~{wrpmmkfd_\\XUNLLIA?;-, #$%&}}}zvsqnnhffaa\ZXSQNIE?<61,# !##$Dٓxvsnjjgec^^WURPKHDB<31# ! ""#+~}zvsqnnljcc^\WWRMKKE?73+# K~{ywrpmkidc^^\YURPKGC:43+&!뒏~{{wtrmkifib_[[VQOMHGC=90% !" 9z}}zywrppmkidd]]XVQMJJEA87*( $l}zvssqolhcaa_]XVQQJJC;;40( 4󓐎}zxxsqlhfhaa\ZUQQNJEA?;31"yy~~yywpoolhfc\\ZUQLLJH?<9,+3~~|upnkigbb`YXUQNNGB@;40+#񙗗z||ywrrnikge`[[URPNIGBA;11"0}}xzxvtmnkgib`[YUURKIHC?5/*%Ւ}}zzvvtqokhfa__]XWRPNIFA:43_ނ~~|ywzxvqqmkkfd_[[XTOMKGF@=4򕓏~||ywuplljhda_[XVTOKIJC>~||ywwspnlgeea^\ZVQPNIIf}}vxxwuupljjgc^\ZXSOMKI󍋉{{xvtookijcaaZZUTMKꗕ~~|}}xxtomkidd``]ZVTm~||uywuutokiifd`[ZXS }~~yywqnqljhb``ZZ 둜}{{wsqnlhcc_`p 𚘖}}xtsljhfhcb 핒~|~}xxvpmpkiga ~|zzvrmkh 柝~~||wsqmkv ΀}}|wzwwuuolw }}{yytwuuv~|}{}{{vvr|~힛~~zyv|w}鞗~~||zxxw}y󞚙򅃃}{z|zzux{}}yv|埠}}{{qw{z|束|zyrww{}𢞟~|rtvx}{qsvvxx|􏌈zqssuyz🝟^prruwy{z~ퟛԣmprttyw{}oqvvx~}󖒔imoqswvzz|~kmppquuw{|󚛙pllnptvy{{}|klnlqtrxx}{󝙚kmonppsvxv~hjkkmqquuw|~|~flnqqsvuwwy~iklpnnttvv{}gikmnnrrvxv|}}hijjmoqtpuwxzz~.0*4..**+$'!" '.013-.1)#$%(,!$+,-0**+.'/*-$''" *,,.)*--./**#%'!" *++5.03-./1*#$%"& .(+,@wϴJ*%%(*!! (*wߜ9$''! '5O(!" %C(,!$s 9''" `+'!" 8%" C$$(*!" P#$'! S+$%!" P#$%*!!$ P1*$$''" D1*+#''" |6/)*$%,$ I,.''"#$%*,!"--4./**$%'! W03-./**#$'"  4.0*+/))#$%!!&  I,..*+-''3*$$'(!  *+.(0+4..**+%'!"  L(*,-01+..1*#$%!"  '(*+,-0**-/'1#/%(!!$  %&'**+..0*4%/3*#$''!  w%%&/)+&.014-.1*+$'"  3$%,.()+,-0**./)#$%,!&  z((),&'**,-.**-.'1*-$'*!!$9&'#%%')*+,5004-.1*+$'' h+%"#$%+-.#+,013-./)+#%! 5%&(#),,()*,,.**+.')$%',!& P#$%'()%&')*+,.)*--//**$''$ރ*"##%%'#$%&')+,-003-./**#''" ݸ8 ""#!!##*+,()+,,01+./)*$$!@ #%&'()+,')*+,.**+.'/"#%'*,!$w!" !#$%&'#$%'(*++500--./**$%'"۹%  ""#$%!##%+-.#+-.03-./**#$'"6 "%&'#)+,()*,,.1*+.))$$!ڍ "#$%&()%&''*+,.)*--//*#$$(,?!! "##$%"#$%&')++-.0--./**#%'k0) !"!!(#*+,()+,,.3+./1*#$'<5( #%&'()+,'(*+,.**+.''$$'V<9-"!" !##%&'#$%'(*++.))--//**$%{B=81-# ""#$%!##%+-.$3-.03-./**#%IHA<<3(# %&'#)+,()*,,01*./)*#$aKIF?:7-" "#$%&()%,')*+,.)*-.''#$PNKGA<82+! "##%%"#$%&()++500--./*"TQMIGA=43, !"!!##%+-()+,003-./**x[KIIGA;21" #%&((),,')*,,.**-/)*_LKGD<7-( !" "#$%&'#%&')*+,.)*--'/aKGF=;4-& ""#!!"#$%%-(%&.004-.1UGIC?<0(  "%&(#),,()+,-13-./NIF?84- " !"#$%(()%&'**,-.**-.ںaIIA972.  "##%%'#%%')*+..0*-%قIGGB=40( "" !&#$%,..*,-014-KKIC>8/*"#$%&((),'(*+,-0*+ONIF?74-% !" !##$%'')%&'**,-.**QMKGE?<2+& "##%!"#%%&)*+'(0*VOKIGB<40"  !&#)*,..*,-01UONNID>8/* !"#$$'()),'(*,,-0~XTOMIGD=40% !##$%'#$%''*++.("! *41;?BA9850/1+20/.,+)'*'"!    ! "!('&*/46;98>>;9770+*).-,)('%$%"   !   !&&)/8<:953769754310).')'&%#!!!  "   $-<:=7:33102430/.,+*(*&$% !! "!!!$*41;:=A>85131+2-/.,+)'&$#!   #   !!&$/47;9858;:875/.0')()('%$" !  !!""$/37:85536976430/.,$)''"#!   !#$3<;:=?9350.4/20..,*)'($' " !" !#*.47::A>><476/+),.,+)(&%#! !  " "  ).4;:9886;875320+)+*('&$" !   "!!/.8A=8536102430/.,+)'*%%!   !   !!!/17:BA?8513,+20/.,+)'%$%  !  "  .1;:8A>;9775/)0+)()('%$"!!  ! "!!4<;97486976431/-,'('#""! !!  !"8;?8:4310-4320..+*)'($$  "!""  "7:?A?8;536+*)+.,+)(&$#!   "! "!!!;:9=9<;875320+)(*('#$"    !  !!! " <98536536430/.,+)'*%%!   ! " " "":B<:361/-+20/.,+)'%$%# !  "!!! :8A>89775/*-.)()('%$"! !!!  !"  9848;:76531/-,$('#""! " !""  ""!85532926420/.,*)'($$   " "!!>;9753.-,&+'('&$"    ! "   "!7376865310.,+*,*%#!!  " "!!#! !:32102330/.,+)'&$##   !!  !! " ?85131+*).),)('%$" !  "    ""!!><:875310*)$'('%#! "  "!!! !!36986430/.,+)'('% ! !! !"360/1+20..,*('%$"" !! !    ""!!85770+*0+)()(&%#! " !  "!!!! ;:76531/-,*)'&$"#" ! "" !2926420/.+*(&%$$!   !    "!!502/+.,.,+)(&$#!   ! " "!# !! 4753/-,%+'($#$"   ! ! " ! 875310.,+*(*(&!! !  !    " "!!!02430/.,+)'&$#  !  ! " "! !! $32+.)+*,*('&$"  "  !#!"" ! %75320+)(*+'%#$!!!!   " !!! +6530/.,+)')$%  !  !!"   !!  %,2320/.,+)'&$" "   "!!" ! ),5/*).&()('%#!!!   "" !!! +05310.,+*'*'%!  !!!"  ! ',1430/.,+)'%$%" !    "!!!"" ! "+,6+2,..,)('%$" "   "!!! $,0:/*0')(#('"#!  !  ! ',1:31/.,+)')'% ! ! "!!! ""  "+,6;20/.,+('%$""  " "  "!!! %,1:;.).-()('%#!!!  ! '.3;>10&)$)'#(" !   !!" "!!!!!"  ",,8=A0/.,+)'%$$" !    !!! ""!!! ',1:;E0/.,+('%$""!   !! ").3;>I).)()('%#!  !!" " !!!   ,.8=BH0.,$)')''  !  !!! ""!!! ',1:=EH/.,+)'%$""    "  !! ").3;>IK..,)('%#!!!  !  ,.8;BHM.)(#('"#! !  !  "!!! "" !!! ',1:=EJO.,+)')$% !!"     !! '.3;AIKP.,+)'%$" !   ",,6;BHNP-,)('%#"  !!" "!!!#!"" !!! $*1:=EJOR)('($%#!     ! '.3;?IJPS,+)')$%#  "!! "+,6;@GLPS,+('%$"!!"" "!!!!"" !!!"*08=BJORU()('%#!    !  !! ',3;?IJOSZ!!#!#!!#(069ACLPVZ]ahimssyy~!!##!$"$,28?FFPSW]bfikotx{|~!#!!#"*03;AEOQY]^bgkprxw|~~#! "&.57CBLOUZ^dfijpqw|{~|!!! "" */7>BHOUX\bcijkssy}돌~|!##  ""*-3:@FMOUZ[cejmqtyx~} "" " "$$-17>DIOTV[chjkprxyz~|{#!  "" &/3>BENRX]^bfknpxw~~|x ""   ""&/48@AKNV[]`cgknsyz}~~|w " ""#'16BMNVY[^dglnqvx|~zvvxv!(.3<>EKRU[`cehmmtww~}}uvxxyy"!#,17>BMNSW\_ehiots{z}얘xxyz"!!(.3>@ELSUZ^cdhmpuw}{𑏎zxyyzz{!!&-38@AJLQX^`dfilptxz~~yy{z{{!&/5FLRSV\abgkosty{|}}~~! ")05>AIJQX]`bdglotwx|󗖓}~~ ',4:AELQSX[`chjmrtx}|}~~" +,7<@HLSVY^^cjipss|{~ ',0:=EJPPW\acdkpovv{~Ⴤ""+05BB>>BFB>BBF>FIUXX`gnvrv}}}XQQIMQIFIMFFIIBBFF>>F>>FB>>BB>BQUX``cgkrnrvrry}UQMUQMMQQIIMMFFIIBBFF>>BBF>>BF>>FF>>FFB>>BB>BIQXc`gkknnrvvUQQUMMQQIMQMIIFIFFBFBBFBFBBF>BF>>FF>>BMXXcckknrrXQUXUQQMQQMMFIIFBFBFBFBFBFBBF>>BF>>BFIQ\`kgnrvv}XUXUXXQUUQMMQMIIMMIFIIFBFFBFFBBFFBFBFBBF>>BFB>>BBMU``knnry\\XUUXXUU\QQUQMMIMIFFMFFIFFBFBFFBF>>BFBB>FM\ggnrX\\cXX\UUXQQMI FMFFBFFBFFBF>>BBFUgn`\\`XXUXXUQUXQMQUIIMMIIFIFFIFFBFFBFB>>BF>BBII``\``X\`XU\\UQXXQQUQIQQMFMMIFFMIFIFIFFBIFFBFBFF>>IIFIccg\cc`X``X\\XXUXQUQUMMIMIFMMIFMMFFIIFIFFIIFBFIBFgg`cc`c``\X\UXUXQUQUMMQMIIMIMMFFMMFFIIFIBFFBBgkcgcg`c`c``\UXXUQUUQQMIMIMIMIMIFMMIFFIIQMMIFMFFIgkkggkgg`cck``c`\``\X\`UUXUQQMIMMIMIFMMIMMIMIQMIIkgkkgkkgcggc`cc``\X\\UUXXQUUQMQUMMIMMIQQMMQMQQMQMIUnrnknngkgkngcggcc\``X\\UX\UUQMQMMQQMMQMMQMQMUUMUUQMMQUQQrrnknggkkcggc`\UQXUQQMQMQMQMQMQQUQXUQMQQUQUUvnrrnnrrnrnnknnkggcggc``\`\X\XXQUUMMQQMQQUUQUXUXUXUQUUQUyrvvrvvrrnrnkknnkgngcgcc`\\XUXUQUUMQXUQUXXUXUUX\UQ\XXyvyvvyvvyvrvvnnrkknkggkccgc``g`\X\UUQUXQU\XUXX\`XX`\\XU`XUy}yyy}vzzuupuppkfb`XX\\UU\XXUX\\X\`\\X\`\\X\X}zzzzzzuzzuppuupkkpkkfkbb]X\X\X``XX``\``\\X\`\X݄zzzuzzpuzzpkpukffkkbbfb]]b]]`\c``\`c\\`cc`]`\\zzupfbkf]bbf]]bfbbcg``gcg`cgc`c\\gc\zzzuzppkbfkbbfbbfbckgccggcgkcc\zupuppkupkkbfkffkgkkggckk``򎉎񎉄zzuupupkpukkpffkkfkkgknkccgc쎉zzzuuzpuppkukkppukkpkknkgkk`zuuzpuppkuppkuppkppkrngkgzuukkuupuuzppuuppgkgupzuzzupupkrn혓uzuzzuzuukp霘zzuzzzuupuzpsuꘓzzuuzzuz로zz 򘓎zzVTTVTQQLTQQOQQOLJLJJGEGGJGJGJGJGJJLJIGHGJJGJJYVQTVTVVQTTQQOLOJGGJGJGGEJGJGJJLJJLLGJLJJL[YV[YVTYTTVTYVVTTOOLJLJJEGGEGGJGJGLJGJLJGJJGJGJLJJO``[^^Y[[YYVTQTQQOQOOJGJJGJGEGGEGJGGJJGGJLJJIGGHJLLgcece^``[[^[YY[[VYVTOOQLJLLJJGEGGEJJGJLJLJGJGJOLLOjggjeedc`Y`^Y[^YYVTTVTQOQQOOJGJJGGJGGJGGJGEJJGJGGJGEEGJGLJJOqljljjedc`^c`^^[YVVTQQOLJLLJJGEGEJJGJGJJGGJKJJMLvyqqoojggecge``[YVYVQOTQOLOJGGJGJGJGJGGJJEGJJELLJEGJGJLGLQO~~yvvqqoojjljg^c`^[^[VYVVQQOLLJEGGEGGEEGGJEGLGJJLLO~{yvvqqooljede``^YVYVTQQOLOJGGJJGJGJJGJLJJLLNL~~{tvqtlljjece^[^^VYVVQQOOLLJLJJEGGEGGEGJJGGJLJLQJ~{{vtqqljgg`c`^^[VYVVQQOLOJJGJGGEGGEJJGGJOLLꠞ~~yttooljee`[^^VYVVQQOOLLJGJGGJGJJGEJGGJLLOLLQ𣗍~vvtqlligcc^[VYVQOQOLOJJEGGEGGEEGGJLy{tqoojgee`^^VYVVQQOOJGJJGJGGJJGJJGGJLQ꥔~~vqtllijc`c^^[[VVTQOOJLJJEGGEGGJGEJJGLOOQ凜~{vtoojgee`^^VYVVTQOOJGGJJGGEGGJL枒~yqtllijc`c^^[YVVTQQLLJGJEGGJJKJJLߨ~{vtqojgee`[^^YYVVTQQOOJEGGJGGJGLLJO륙~yttlljjcc`^^YYTTOLGJJGJJGJLLOᥨ{vqqojgee`[^[VYYVTOQOJLJJGJJLGKLLO降~yttlljg`c`^YYVTQQOOGJLJJGLJJLLOᣏ{vqqljege[[^[VYVQOOLLJLJJLLJLJOOQ򪗍~vtqllgc``[VYVVTTOOLOLLJJLMOO񞏊~{{voojgee`^^YVVTQLJLJJLOLLJJOLL~yttlliec^`^[VVTOQQLLOOLLJLOOL홊~{vtoljg`c`[[YTQQOLJOLOLQꥏ~vqqljge`[^^[VYTQOOQOQLOy}y勒~{toljjc``^YVVTQQOQOLLOrrv}~yvqojee`^^YVTTOQQOOQOcgvvy}y왍{ttljjg`^^[YYTTQQOLOOQIXcrvyv}~votjgcc`^^[VTQQOIM\gkvv}}yץyvtllgec[[^[VYTTOOLLOOMMIIMXcrvvy𣔅~vqolje`c^YVVTQTTOOMFIIM`kkvvy~vtqlgee`^[YTTQQOIFFIMIMIM`krrݨ~yvtojjg`^^[VYVTQOQLMMIMMFIIXgnry}~votjg`c`^YYTVTTOUMMIIFFMMIMM\krv}yꥨyytllge`[[^YTVQQMQQMMFIIMMcrnv}Д~vqojjc^`^[YVVTOXUQUQMQIIFIMMIM`kvv}}॒{tvljeec^[VTVVQXUQUQMUMMIMMIIMQ`rvv~yvqllee`[[VTTUU\UQQUQMIIFFMIIQ`kry}㥏~voqje`c[YTYV\XUXUQUQMQMIIMFIMXkrvy{tqlgee^[VV`\UXUUXUQQUQMMIFFIIMQcryv쒅~{toljg^YY[V\\X\\XXUQUQMQIMIMMIIM`gvy먥~vttjg^`[YT]\\XUQXXQUQMIMMFIIM\kvyy}𙍀{ytllde[[Y\\``\XUQUQMQIIFFMII\nnv}~volge[[gc\]`XX\XUUQXXQQMIMMIIXkvvyqtlgc^[`c\\`\X\XUXUQUQMIIMFIIM`ry}y॔{tljb`^``cgc\]`XX`XUXUQUQMQIIFMMIQgrvy~vqlee[ckc`c\\XUXUQQUMIMMIFIMkrv}ytqje`kk``c\]`XX`XUXUQUQQMIIFFIIcrv}y虈{qlg_gkgckc`c`\`\\XXUUXUQQMIIFMMIQgrvy泌~tqjcgnggk``c\]`\\XUXUQQUMIMMIFIMkrvឍyqogprkgkgckc`c`]``\`\UXUQUQQIFIMcry}}~yqjpkpgrgkk``c\``\X\UUX\UQQIIMIXkrvꨥ{qluppurkgkcggcc\]`XX`XUXUQUQMIMMFFIXkry淚vozpuupkkngkk``\`\``XXUQUQQIFIMXkv}vzpsukkprkgkckgcgc\]`X\\XUXUQQMIIMII`vvyzuzupzuknngkc``\`\\`\XUXUQUQMIMMFMM`nv⢛wuzupsukpncggcgccg\\U\UQUQUMQIFFIIMgyyuU3,Oezzpzupkpgnkckc`c`]`\X\XXUXUQUMMIMMIUgvw[/zzuzukpuurngk``c\``\\UXUQQUQIMMQ^gjhgC  zzzpsukkggkcggcgg\`\\XXUUQMUF<, JLOLLMMLMLMLLMLKLJKLKIIGFFEILNMOPRRQRRUSUVUVUVX[_^c`bgcaeJOOLJLLOLPOLLOLOMMLMLLKJLJIGIGFJJINQQOQPSVUVVURWWXTX^[accef^aLLOLOOMPOPOMPMMOMMKLLKLJJHGJIGKKLMOTSTURUVWVWXXWVZ[cbdfedcLLQSOOPMOQOOPOPOPLOMMOLKKJKGEJLKOSTSRRSVWWVWXXWVZ]acehjfONOOTQLOORPPQPORPPOPOOPOLLIJKHGJIGLNNORVTVWUWTYY[X[X[_ddgdgLLQOOQQLQQPQQPQQPRPPMOOMLLKJJKJJKKOPRSUSUTYWYWXVZZ]affgjOOQOTSPQQTRPQRPRQPPQOMKLMIKLKIKJILPRQRUXXVUWXWYZ\YX[Z``difOOQQOVTQQTQRTTRTRQRPQQOMOOMOOKJLLJKLMMRUWUUVYX[WZX\[[`bffdLMQOOQTQQTOTTQRTRTRQRRPOQOOMMKMMLJLLKORSQRXXWXYYXYZ][][\baghLOOQQTVRQVRTUTQTRPPQPPMQOPPLLMMLKMQRSWYWWYX\]Y\]]\[_`ggOQQTSTTOTQTQTUTUURQRQQRTPRQPMOOLPOLLMLKRTUTU[]XYZ[YZ^]_][^bgOOQOOQTQTVTTVQTTQUVQRVRQRRQPROPRQMMOOMLOQPUXWYWXZZ[]][^]`]bhOOQTQTQTTVTXUTVRTTQTTPTQQPOQMRPNLOOMQSWUVZZ[ZY\]\Z_`a]^dOTOQTTVUVVTTVUTUTRRVTTQROPOMKQQRWZ[ZYZ\]a_^_`]`^aOOQTQQTVTTYTYYVTTUTVRUTUTRRTROQRONLPOPQWXXY[]\\_`\_`_``_OOTQQTVVTVVTURUWUVUUVUTTQRUTPPQQPOQSSXX[[Z]\`]aada_aLOOQVQTVVYZYYTTVXTTYTVWYVUVUUTVTTSRPURQORQPUWZYYZZ_``_b^bb`LOTQQTVTVYXYVT[YVTVVUWWVUVUWVVUVVTUTUUQQRTROQTTY\^\]__^`_accdQQTQQTTSTTRVYYVVYVVUVTYZVVYVWVWVUUVSQTTQQRVZ[[\]`_bb`cbcOOTQTYTV[YVVTXVVYWYWWYWWYWWVUUWVRRTTQVW\[\``_`ac_`cbOOQQVTTVYXYVQTTVYWYWZZYWZWWVYVVRUUSRVTPWZ]\\^]_bccedfOOTTVTTVVUTTRVVYVYTVXWYZZYWZYYWZYVWVWWTTUVUQVVW[[a``abddcOOQVTVVTV[YVVYVVY[\YZ^YZZYWRWVUTUTUWZ]`b_``cfOQTVTTYVVYXYYTTVXYW^Z[\[[Z[\ZZYWZYUUVVTZ[]\^bdbbeeLQTQQYVTTVXTTYV[VV[YY[Y[Z^\Z[^[[ZZ[WYYXWUVWUUWU[\aa`a`ccfdQQTQQTQTVTVVTVWVYVVYVYYZ[[\^\Z\\[\[WYZZWWVTY]^]^bbeghPQQTQQTTQTQQTYYVYVY\\^\[[_^[[\ZZYXZVWYYUVWV[]_adcdffgQOOQTQQVVTVTVYXXVVTYY`[\^\^^\\^\^\\ZWXYYUZ^a`a`cdfeOQQTQQTQTTYVTUTTVY^[^Y^[^^`\_a^\^^\[[WYWYWVVZZ\`efddfdQLQOQOQTQQTVYYVTVVYY^[_\a\_``__`^^[Z[ZXZYYVZ\abbeefQLOOQOQTOTVVTVYXY[VY[`_^\_`^_a__^\^\\[[\ZYZZWWY]]acchigLOOQQOQTQQTTQTTVVUUTTVYYVYV[Y^^_a^`aa`^``^^[]\\[[XWZZX^aegffQOQQOPQQOQQVTTVTVYVYYVYY^[^``_a``_ca__^`^^[\^ZZ[[ZYW^_aacjfOOQLLQOOQVQQVTQVTTYVY[^`a_``cda`aa`__^_\Z_\[Z^ZW_bfeggOOLLOOQOTQTQQVVTVXVTQYYZ[[cba_cac`dd`a`a__\__\[[\\Y^accdgOOQQOQLQPQQTQTQQVVTVTTVY[[^c^^a`a_ccac`caa`_`^[`^\[\\acdmOOQLQOOQOQQTQTTQTTVYYVY[[`c^`aadceadfccaca`__``\[^^Z^chQQOOLOOQOOQOQQVVTVY^^[^[`ccacadeedcddca`aa`^`__^[[`eOQLOOQOQQPQTQQTVUTTY[]^^[^`eacddecdfdccdaa`aa^^_^^aTQOOLQQTLOQOOTQQTVTVWV[[^``ccedecffeddeecadd`_^__^^QOLOQOQTOTQQVVTTQTYY[^^`c`ceddefedgdd`edaadc`_hTQOQLOOQQOQQRRQQTVYV^^``cefdfggfdffdcba__VTTOQOTOLQQTQQTVTUTWY^^`^``ceegffeifegefeccdcTQTOOQOQTQQVTTYQTQV[Y^^c`eecffgigegffedcsVTQOQLOOLQOQQTQQTQQVVTTQTVYY[[^``ceceeffigffgigieigyYVVTOJTQOQLQOQQTQTTVZVYV``bec`eeggigfifgm[VTQTQTOOQLQQTVY^^``c`cggfjiiggjijYTVVQOOLLOLOOQQOTQTQOTVTVTTVY`^``egjejgiijiggi [YYTVVTTOOLTTOQOQPQQTVY[[^^`ccecggiijjlir [VQOLQQLQOOQTQQTTYZY[Yccdgecgjkijjkr ^[[TVVTQOOLOQOOQTQTTY\``cceejlkkl| `[[YYTVTQTOOQOQOQRQTQQVVTVV[``ccejjlgkjyc[[VQOLQOLQPQOQTTQTTY[[^^``ceegjtc`^[[TVVTQOQOOLQOOQOQTQQY[][^\eegjgejze_`[[YYTVTQQOOQLQOQQTQQOVVTYT[Y[^^cceeggoj`c[[YTTQQOQOQLQPQQTVTYVY[^cceehyle``^[YTYVTQQOQLOOQTVV[^^_`cceg}ogc_`[[YYTVQQOLOOQOOQOQQVY[[_^`agojgc`[[YTTOLTTOQOVRQTQQYYV[V[Y`citjje`^^[YVYTTQQTOOLQOLQOQQTQVVY[[^cmtjec_`[[VVQOQOQOLLQQOOQOQQTTYY`dwMlkeec^[YY[TTVTTOLOTQOQQTOTQTVVYd 7dgec`[^[[VYTQQOQOPQQY\e >fgcd``[[VVTOOQOQOOLQOQQTV{fhhlnnmqqsuw{z~~cejjnpquuwy{ figgjkoprrssxx} dcdikijoottvxwz|!fgfjhmmnquqrtxz|z"gbfghjkmpposwvy{{"gcgglnlnrrwzy{}#ikeghiilnoptptw|z}$jiidegkomlnqrtxx~%jiiffhlhmmoswsvvy|z|%hjljehijlloprquux{{&imlhigkkmnnprttyy|{}%gkilmiggkmmpqtvtvz~&egjmkmfgilronpstvxz'efhjkmmhlnjmoquyux&aidmljmkjjlnpqrtt'wdgiiknlmimmlpprt{'xtadhgmomqhgimooru(wvdadfjjokngmkmsw({xvdb`ffllmpojnpn)xzxedgdijmolmkllƂxywfedeilkolnmlyywyffddeliprosyЄyzvybggedgjlnow|{zxweigigfijp{ӑ~}yxyegehigfkj~}{wxdhgghhekω}~}zzihhjjho蜂~|yxghgfji~|yyhkjin։~{ygjji~{ghi-Œ|{gm-ך}}i뫊}~~-đ}՚}ޢ᧒㬓쭔*󡔕)('遲&%|}$zz#ˆ~"Ԏzyy|~!ܕwxyzz yxxz}~wwxyzyx|~swyvwvyzzvtvwvxvz|~ttsswxwzyz|~rtturuyvyvy|z}qttutvvwwxxz||~ٓrvsqssuvwv{wz|בuursruursuwvwxy|z}ҋturtrutrvvwz}|~‡}vtvptspssusuywvywx|{|zzqqsrsrutuvwwzy||}w~z}wutqrttvxvvxwz|||dUTTOGDDA<5(#!"$!!##%%'.++-.L][XTPKIG?<9- #%&'()+,()+,,b]ZXSOMKGB;8/+ !" "#$%&()%,')*,,_]\ZUTQMIDA=40( "##%%"#$%'(*+,jac]]ZXQNKID>82(  "!&##%+-.$,hfd`[ZXQONIGB:7*" " !##$&((),,()+ތggc`]ZZSQMKDB<92.# " !"#$%'')%&'**viecab]ZXVOKIGB<41( !"##!!"#%%&)*ojjhfb]YXUONNIC>8/% $ &&#)*,..qqlig``q^ZXTOKJF@84-# !" !#$$'()),'(rqlkgcc_`\UTQOGDB<93+  ""#$%'#$%''wtnlhijfc]][UTPKIF?:11" "!!##%%'rtrolligb`]ZXSOMIJA<7-%"!#%&(#)+,uuqqomgec_]ZZSTQMIDA;2.#!" !"#$%'()%&ustrpjigfcd][XVOKIHA<40(  "##%!'#%%rurppojihcd[YZUNPNID>5/+ " !&#$%ttsqsqlkgea`^ZXTOMIGA84-# !""#$%'()*wxusrpjiicca`[XTQOIDB?<3+  !##$%')*vwsstpllhhcb]\XTPKIF?:11!"#$%"#$zttssrqlkigd``ZXSOMIJA<7-" %&(#vwtustromiec_]ZXVTQIGDA<2.#!" !"#$%((xvwsstnnoghhcb]]XVOKIHB<40( !"##%''xztrttqljigad]YZSNPNIE>8/" ""#!!"ywwtuuqrqlkgcc`\ZXTQMIF=84- "#%&&yxvvxssrpligfac`[XTQKGFA<43, !#$%&yxxvtrrtroljhfd][XZTPKID>82(  ""#%%zwxttouqsqlkgec`]ZXSOMII?:7* "!yywvvxustplkicca]ZXTTMKGE:40+ !" !##%xwxxvwpstnlohjhc`][VTOKIF@;4+& !##$zzwxxttssrsojigb`]ZXSOPKKD<9-"!"##zxywvwtustromiec_]ZZSTOKGB94,+ yxwwxxwssrnnoighcd]YXVOKGG@;4+&!" !"#yzxyxzwttstqljigcd]YXUQNKLC<90(  !"#zzxyywwtuuqrqlkgfa`\ZXQOKGB>6/( ""{ywyyxvvxstrpligca_`ZUTQOIGC;1-"}{zxxwtrrtrojihfb][ZVQKIHC<73(  !|zzx{wwttuqsqlkebd`]ZXQPNID>8/%  "|yxyywvvxssrpjkgcc_\ZXTQMJG?82* }{yzwxxvwprtplhijfc`]XTQOGEB<40% !"}~}zzwxwttssrqlkihd`[ZZTPKIGA;2(# ~|yxyywvwuuqrplmgec`]ZXSONIF?84- ~{{yxwxxvwsstnokifca]\XTTMIFA:40"~}zzyxzttstroljhhcb][VTOKIFA<3+  !"~|{xxywvwtuqqokggd`]ZXSPNIF?:1+~|yyxwwvvxsstplmibc_]ZZSOMIJA<7*~{yzxzxxwpstplohhcb]ZVVOIGE:60+ ~~|zxwwywtssrqljigc`]ZZVOKIF@<4+#"|yywyvvwustrlmgec``ZXSOPKG?:70"{yzvzxxwrsrnnlihca]ZXTTOKGB94-"~||zzwwxttstrqljghcb]YVTOKGFA<2. |}wxywvwtusqqomigc`]ZZSPNIGB<4(&|{yxwwxxwsstnpmiec_]ZZSOMIID<9-"~}{zzyxztprttoojhhcb]ZVTOKGB970(~}zxywvwtuurqojigc`]YXTOKIF@<2+ |{yxwwvvwustromgec``ZXSOPKI?:11~{{zxzxxwrstnloihca]ZXSQMKGA<7-~~{zxwwyttssrqljghcb]YVVQKGD<90+|yyvtustqokigd`]ZZSPKIG@<4+#{yzvxxwsstnpmiec_]ZXSOMIG?:41~||zzwvzttsttoohhc`]XTTMKGA94*|{xyywvwtusrqljihd`][UTOKGB?93+}{yxwwvvxsstrlmgec``ZXSPKIF@;5(#}~}zzyxvwprtnljgfca]ZXTOMIIB:70~|yxyywwtssroljhhc]]XTTMKFD:4-$*+*%#!!!"   ! "),6;AGJNSW+)(&$# !!!"  !#"" !! )06=BHOPUW+)'&$"  !  "!  " !! %,18?EJOSXY'('#$$    ""#,3GMPSW\)(&$# ! " "!!! ""! $+06=BHORU[])(&$" !!      !"",1<=EHMRX[_('#$%" "  #!"  ),5<>GJPUV\])'($$!  #" "!!!! ""! )05;@HMPU[]_('%#!  !  "",,8;BGOPUY\`(&%#! !    !$+1:=ELOUV[]`'&'% "!  " ! !!!"! %,3;?IJPSZ]_a'%$%" !!  "!  !!" ),6;@GJNSW\_c'%$"!       ).5?BIORSY\`d'"#$!   !   !!#"" !! $,06?BJMSXZ_^b*%&!  ! "" "!   "!! #,1<=EHNRW[_ae&$#      %,5<>GJPUV[]af&$" !   #!" " !!! ).3;@HMPU[]`cd#$"   " "! "!!!! "!! "+.8;BGOPSW\_ce($$" !   ! +08=DLOSVYZ`dh%$!!     " !!! %,1:AGJPSZ\acdf%#!  " !!   !!" " !!! #.5;=GHNRW\_adf%#!! !!!  "  ),5=>GMPSW\_afg$%     !!! )15;@HOPU[]`edk$"     !! ""! "+.8=BHORSY\]ffk$"  !#" "!!! ! +/:=ELOSV[]bfji$$ !   %,1:AGJPSZ\acdfk$"!   !" !! ',3;=GHNSW\_afhl#!  !!  "!!!  " "',5<>GKPUW\__fii## !! !!!    ! )01;@HOPU[]`eckm%!  #!" ""!! +06=BGOPSW\]efio#      "!!! " "+0:=DJOSUY]_dikl" "!!"  !"*08AEJMSZ\_cdfkm"#!   " !! %,3:=CHNRW[_`ffjo$"    !#! " "!!"#,/<;GJPUW[_`fikm"  !!" "!!).3:>IKPUZ]`edjln"  !   !!! '.3;?GJNSW\]cdhon!! !!!!"" !!" ',6:>HMRSW\_afkln$    !  "!!! )05?DHORU[]`eekmn!! " "!!   !!! "+06;BHORUY\]ffioo! !! ##""!"",.8;DHOSU[_`dikkp!    !!!  ! )06AEJMSZ\_cehkmm !  ! " "! $,18=CHMRW[]`fekoq!  !!   ! "" !! ",1:;EJPUV[_adglkr ! !!#!  ! $,18?GKPUZ\acdjjno    "!!!! %,3:=EJNSW\]cdhjqo !   "!! "   "" !!!  #,3<>GJPSW\_`filmr   !!" " "!! %,5?>IMPUZ]`ccjlnr  "!! ! ),3:AJJNSW\]efglqo"  !!""  !!!  ',6;>HKPSW\_afklnr   !   !"" !!! "),5?@IOPU[]`eekmmt!  !!   ).5;AHNNSW\]dfgmqp!   !  " !!!  +.6;BHOPSW]_bgkknr!   "!!!!   !""! "),5?@HORUZ]`ehkmms !!!   )15;@GMPUY\_ffimop!  "!! !! "+.8;BHOUSY]_dfkkns    !!"  " ""!!""+.8?@HOSXZ]aehkmms  " !! ##   )16;BGORUY[`ffimor!   !!!  ! "+08;BHOUVY]`dfkkns  ! " " "!!""+.8=@JOSZZ_aehjomu  "!!!   ## "" ! )16?BHORXY]`fhimor  ! !! "+06;BHOUV[_`dfkkns!!   "" !! ",.:=BJOSZZ_aehjoou    !"  !""!! '06?BHORVY]`fhikor\acdflkqrvz|}~~{yv\]cehmnousx|}򚗎~~yyvt]_diilorvx|}{~{vyv_cdfkknrwwz~܈~yyvt]cfhlmossyz|朒{y{vy_afklqovxzz}߃~{~{vvtaefklnrrvz|硟Ã{~~y{vtaffjomutzwz~{yyvqafikpotvyz~{yytvcekmnrsvxzz󟞐~{yvtqffiootvxz{}~{yvtdhkkorvyz|띞~~yytcjjnouuw{{󟢓{{~ytvfgmpttx||}~Ⴠ{{yvtqfkkprtwz|䚛{~{yythkmmssxz{|楡р~~{{ytthhoqtyw{~~£~~vvtglmrrvy|}~{vvqkmnrtvwz{~쟞~~{{vttgmqrww{}}׊~~yvvqkkprvwz|𝞟~~{yvqjmousyzz}{yytohqovwy|~~~{yvvqlnrsvzz{yytommstxz{~܍{~{yttlopwy{}ǟ~{{yvtoknruvz{쥡҈~{yytomrtuy{}~颙~{{vqqovvy|~~{vvqnpuxwz{č~{yvqtmtvx{|ɏ~{{vtqprvwz}~~yvtqmusxzz}{y{vvotyy{~~{ytyqqrvyz}~~yytqousx{{{yyttvxz|~~{{yyvrrvz||몬y{ytrtxw{}{{yttrwy{|~{{vvqrwvz{~{y{tusyx{~ꧨŏ{y~vyvwy}~ʀ~~yvvrvv{{~{yytsuz{}~{yvvz|~y{vsvwz{~؊~~yyttv{|~ᯱ{{vvwz|賯~~y{sxwz|{~yvx{}}{{vwwz|~~yysxwz}Ï~{{vw{}yvwz|~~ysxwz}~{yvw{}ۍ~{vwz{ɠ{szx}~ꭩ~{wy{}~{wwz{~~szx}~ᗘ攒wy|}Ƀ~wvz{}~voqlljee`^^YVTQOOJGEEB@==;@;8;=@@ELQT^elɗ}vngqolljge`ec^^YYVQQOJJBE@=@=;88;=@BGJTV`jv܍vrcUtqoljgec`^[YVYTQLOJGEBB=;;8;;B@BEQV[`qߐ}vrngUFtooljee``[YYVQQOJGJBB@@=;=;=@BGLQY[evېyrgcFItollgjec`[Y[TVTOJLGEEB@==;;@ELTYcoʒ}vngMFMqlljgeg`c`^[YTTQOJJGEB@=@;;==@@EGOQ^ey䒍}rnk\FFMqqllgec``^[YVQQLBEEBE;@==@EJLOY`gފ}}rnk`MFIIqoojeec`^[YVTQOLJGGBB@;=;=BGGLT^etˊyncQFFIFtoogjeg``^^VVQOOLGJEBEB@;;=@@BEJQVYovnkXFFIIojgcec[[YVTTOLJGGBE@@EJLTV`q񍊍}ynn\FFMqlljecc`^[VVTOOLGGEE@=@@=@EGJOT^j~䍈}yrncXBBFBFMqolgee``^YVVQOJGGEEBB@@BELOY`qyrgcIFFIqoljjec`c^[YVQQOLJEEBE@@BGLLQYcvvnkXBFBFIMMqjljjgce^^YVVTQJJEB@=@EGJOT[g~}}yvnn`FFBIMMqolgee`^[YYTQOQLJJGGE@@BB@BGEOOVct󅃈}}yyvrcUFBBFBIMqljggc`^[[VVTQLLJGGEBBEEB@GLLQYe~yrg`FFIMoollegcc`^[YVQQLJGGEGEE@GJLQQ[g~}vnkUBBFFIIMlolgjec``YVYQTLOJJGBE@@EGGOLVcvރ}}yvvnn`IBFBBFIIFMojjggc`^[YVTQOOLJJGEBEBBELLQYe{~~yyvvrcUFBFBFBIMIMlljjec`^[YYVVOQLLGGBEJLQQYg{{}}vncFFIqoogjecc^^[VTQOOLJEJJEEBGJOLY`y~~}}}vnkXBBFFIIojleec`[YYTQOOLLJJGEEJOQVe{{~{~~~y}vvnkgFBFBBFMIMIlljjec^^[YYVQQOLOLJEEGJGGJLQQVg{y~~yvrrgXIFFBFFIMollgee``[^YVTTOLLJGLJJGEGJLQV^v{{~{~~{}yvyvngQBFFIIMIoqjlgee`^^YVQTQOOJJGJGGEJOTTcv{y{y{{~{}}yvrn\FBFFIMIQqlogge`^^YVTQOOLJGJJGGLQVeyv{{~{yyvrnrkg`BBFBBIMIMMollgec``[[VTVQOOLLJLLELLQV[ovyy{y{{~~yvvrnkkncQFFIMQQoojgjcc`^YYTTOQJOOJJGJJGOLT`vyvyvyy{yvrvvnk`FFIMQtlojggc^`YVQVQQOOLJJGLLQV^vvyvyy{yvyyvrkkXBBFFIMoqjjgcc^[YYVVQQJLQLLOLQTYetvvyvyy{{vyvvrnkggIBBFMIMMQoojgecc^^[VYTTQOOQOOLJLLOLV^tvtvttvvyyvrrnkgcg`FFBFIIMQqljlegec`[YVVOTLQLOLLJOQV^ttvtvvyvtrrkrrkcXBFBFIIMIQMMUqqolje`c^^VVTTQQOLOQOJOOLQV^qttvytvvrnggMFFBFIIMQtlljee`^[[YVTTQOQQLQOLOVYettqttvrncgcIBBFBFIIMMQqllgeec``[[YTTQTQQOOQLQLQ[qqtvnkgcc`IFFIMQUologjgec^[YYVVYOOQQOLOOQV[oqqttvqnkgkkg`XBFBIIMIMQMQUqqolgecc^[YYVVTTQTQTQQTOQV`oqqtvtvrrnnkccMBFFBIFFIMMQtolgge``^[YVYTVQTQOOQOOLTYeooqtrvnnkcc`IBBFBFIIMQUoolggec``^[[VVTQOQOQVeolqqtorngcc``\BFFIQMMUUqojjgc^[^YY[TTQTTQTV[gooloqtqqokggc\UBFBIIMQvqoojeg`[[YVVTVQVTTOV^lolooqonkkckg``MBFFBFFMQUqqjjgeec^`[[VVTVTOVQV`llooqonnkgc`UFBFBFBFIIMIMQQUUXqoljggecc^^Y[TYTVTTQVTQV[jlloloqookgc\\XBFFIQMQUUqtloljec[`[[YVVYYVYVTTYcljljjlloggc``cUUFFIFIMMQUvtqljgce`^^[[YYVYTTVTVTT[ejjlojgc`gg`\QBBFFBFIMMQUXtqlljggc``[[YTVTVVQYegjjlljoololjknkgc\\I>FBBFFIIMQMQUUtqlojgge`^``^YYVYYVYV^ejjljjgngcc`XUFFBFFIIMQMQQUvvtoolgc^^`^[^VVY[T[Y[OT`gjggjjlgc`\U\UMFFBIIFQMMQUXvttojgecc`^`[[^[YYQ[QV^gegjjljjljcc`\``XQFBFFBIIMIMMQQUXUvooljjece`^^Y^Y[YYV[YVV^cggjggjgjk`c`c\XMFFBFFIIMUXtqoojggcc[^cY[[^[[Y[`geegjeggc`UXQBBFFIIMIMMQQUXUyytqoljgc``^[[Y[YV`eeggjgecc`XXUUIIFFIIFIMMQUXUyvqolgjee`c`^[`[[Y[[TV^ceegegeg``\XXQIBBFFIMQMUUXvqqolljege``[`[[Y^^TYcececeegc`\X`\UUIBFBBFFIIMQU\vtqoqojgegc``^^`^`[^^VYYccegeccgc`\UQFBBFIIMQUXUyvvtqolgeecc`^^[^^Y^[VV``cceg``XXQMFFIMQXU{ytqljlggcecc``^[^`YYcc`cec``\XUUXMFBFFBIFFIMMQUUX\yttqooljggee``^`c`^c`^V^c``cec`\XUXXQQBFFBBFIIQMMQQUyvtqtqlgjeecc^`cc^^YVY^`^cc``cc`\\XQFFBBFIIMQUXUX~vyvtoljggeec`^c^``[Y^^``c`^``\XUMFBFFIMQUQUUXX~{ttolljjeec`c`cY[``^^``c`^cXUQIQIFBFFIMIIMMUQUU\{vvtqooljjggec`egce`cY[[`^^``^`c``c^XUQQUMIBBFBBFIIMQMQQUXXU{yttvtojlggce`cc^e^YY[^^`^^XUQXUMFBBFIIMIMMQQUXUXy{yvqoljgjeec`cce`Y^^[^^`^[\\XQMFBFFIMQUX\QMMQX\`cgkgnkrvyy}IQQU`\cc\ggnnrrvvyy}MQUUXX\`ccgkrnrvv}y}}IQMUXX\cgknrvry}}}MIQMQU\X``cgkknnvy}IQUUX\``cgcgnrrvy}}MUX`c`cgknnrvy}MIMUUX\X``cggkkvrvyzQUX\\`c`gkrnnrvyQU\`\ccgkknnvy}MQQUXU\\ccgkrrvvzzMUMUXX\`\cgnknnvvzMQQX`cggkkrrzzMQQX`cgnnrrzMUQ\XX``kgkkrruzMQUUX\X`ccggnkpzzMUXX\\``ckknnuzz{QQXUXX`ccggnruu󓎘{QQUU\``cgkgkpz񄉎{QUUX\\cgkkpuz{MQUX\X``cknppuu{݊QUQ\\``ccgkkupzzMQUX\X`ccgkkuzzQUUX\``kkpzQMUXX`\cckkppzz{QUXU``ccfpkzu{𪡪QQUXX\`gffpuuzQU\X\`\gfkkuu{QUUXX\`ffkkuuz{QUX``ffupuzQUX\`XbkppuzUUX\bfkppzz{UQUX\\bffkppz{QUXX\bbfkpuzz{UXUXX]bfkkpuz UUXXbkuz{UUX`]]bbkkpzX]fkkpzz UX]ffkpuzuyUX\XXbffkppzz{uyXXUX]]ffpuz{wuuyUX]]fbkkpu{wuyX\XXbfkpuzz{wkuuyU\SXbbfkkuuwnkunnyxXX]fbkpzz{wwnkknyxXX]]bfpz{wnknmyyxx\`]]Xbbfkpuz{wnbkknmkxxUXXbbfpz{twnnfbkccnmkxX]b]bffkpuzz{twnnfbcmkqo\X]]bkpu{{tnfbcammkkqoX]]Xbbfkppz{tnfbcakqowX]Xbbfkupz{tmnff]Xa]kqqofXX]bbfkfppuuzy{{ttmnf]XXa]c_fm\X]]fbbfkfpuy{tmnf]Xa]c_fmX]]fbbffkkuzzytmf]XU]c_f[X]]Xbbfkkpuuzytmf]UNXNXXMMUP]ccO_U[[XXbbfpuysttmf]UNMUPcUOOU[[\X]]fbfpkfpuzystmmf]UNMUPUOU[[XX]]fbfkkuzysmf^]]UUNMHUHPPUOU`|X]X]bbfkkppuysmf^]]UULLNNMBMMHHPUON\Xbbfpkppuzzysmf^]UULDBHCUFG}XXbbfkkfkuuzzysmf^]UULLDDBHCF`X]]bfbfkkupuzzyysmf^W]UULLDBHB<:;?:78955r=d+ ] B󪣪<_f /   ꊑ & {Z ჊û S)&ûCûք)xE$խsI' 쾖eQLGICBCFCCFC?= Ľ Ķ ĽjYD'b+  u0 쾓Y0 {8 [-Cd{ͬ!"#$%%%%&&&'(w(wu)wuu*mus+mus.muss2mbujss3[bujs5bj6Nf8_:<>351150,,.,*.*)(,*))'%##$$ !$" <#9!S5&Nv1 >f0(Vp1;05}0;y1Ck1#Sg. ;e# *Rn||nR* 6 X$mҩm$ : 88 [ =86zR $(9 X '5a񠣟0s:ǔ9ҟ7כ6yy}5yvvy}}4}yrr}2֒{yvvyy}1Ǎ}}vvry}y}/嶐}}vrvyzy.ԡ}yyrv}},漙}yyvvryy+̝}vvr}yy)ᷚ}yyvrvry&}yrrz}#׸yyvvrvv!˹쓐}vyvryvví}yvvrrʡ}yrrnoy<윛y}vvrvvᰡ}vyyrrƩ}yrvrvnr֮񓗐}}yvrnorJhecc[[Y[YTVQTQOOLOOQOOQV-^ge``^^[[VVQQOTOQQPQqQjgcbc[[VVTQOQLQP  Ejgec`[YYTVTQQLOOLLQq"=lee`^^[[YTTOQ#=qlgcc`^[YTYVTQQTz%Fvljecc`Y[VVQO`&Zyojgg``[^[[TT^(+v~qojgc``^[[V)Ktojgcb`[[n+*x~qleg`c[-gqojgc|-dtqlj,͕rv,͗yy,ݮzzy,㷎zz{zz,꽕~}}zz{+鱑}}{}{{*붇|}~{~~{~,繆yy~~~}}{+گv{vy{~~~}~*⬋yvyy{~~}}'ٞ|ooryy{y{{~~$ӝzpoqytvv{{~y~~#ngjqqvy{y{~Δqcgjjllqssvvy{{~ܲndceeljolooqqr{{~{~ݞwd^^`ceegjlolqtyvy{}~{؍iV[Y^_`cegjgjlttvyy{{~bVTTV[^^ccejllootstyy{~~~ߙ_QTQV[YY^^`ceggolqlttv~~~Ւ_VQOQTT[^``cejgjooqotvyw~~q^VTQTTQTYY^[`acegjjotvv{{~~ٴ[[VYVQQTTVVYY^``eegoloqtvuy{{~~~ ɤi^[YYVVTOVV[^[^``ccgjlqotovvy{~ ǝqjec`^^[YTVQQVVY[^``cecgljlqqtqvyy|ɧyqljec`c[YVVTVTTYY[[^adgjjllqtvy{{⦈yqljgcc[YYVVTYVYVY^^ceggjjqqtyyz{~~~ݫ{qolgc`^[[TVVQYY`^cceggjlqtqvvyxy~~涗ㅃvqlgcd`^[[VTYVTYY[``ceejjloqqtvtyy|ﻗvolegc`[[VVYVVYY[Yc`edgjoloottyy{~tooge``[YYTTVVY[[^``cejjlqqtvy{{냅xtojgc`[^[[VYVV[[c`ceegjloovvyv{z}샀{qojec_`[Y[YYV[[^ceeggjlooqtvvyy{{~~{qljgec[Y[V[YV[Y[^^cgiloqqtvyy{~~~}tqjgc`^[[V[[Y^[Y`eceeglloovqv~~냅~vqljcd`^[[Y[[Y^^`ecgjjllotvyty{{~{~{volegc`[[Y^[[^`ceggjooqtt{yy~~򀃅~{{vooge`^[Y[[^`ejklotqtty{{压~~{{|{ytljec`^^[^`^ceejoqtvv{~~{{voleec_`[[`[`[[``ejlqty{y{y}~|~~{{yyooje`c[[^Y`^^``^cegjgoqlqqty{{y}}~~{yxtojgc`[[`^[`^^c`c`egjkoqttvyy{~{~掐}~{{yy{yyqojec_``c[`^^cc`jjglloqqtvyy{}~~{{|y{{yvvqlggcc`^``^`cgjlloqtty{{~y}y~{{y{vyvvqolge`[^^c`^c``egjjlooqtvyy{{񊍍}yy~~׀~{{yvvyvyvqjgc`[``c^cc`ececgjjopttvy{{~慍}yy{{~{yzyyvvtlecbcc`e`c``eeljooqvtvy{y~}}~~{yyvtqojgec``c^c``eelqoqttv{~~󍏔ry}{~{{yvttrqvtqjgc`^``ce`ecejgjloqqtvv{{~y}vy~{y{yvwvvtvtqqolecbcc`e`eecgegegllqsvtyy~慈yyvv~{{yvvwvvtqqolggcegccecejgooloqtvvy{{vv}}y{yyvyvttqrqqlge``cecggcggotqtvvy~先ryy}{yv{yttqtqqjgcc`cceeggjloottvyy~wvxz|~z|trvstqptssuywyywy~xsttzz|xxsrosrsrutsvwwxwzy| 꺈uswvutvw{z{ztsrrtrttvtuwzwz|}|~ ǖ|xvwxuxtx|{ywrqtpsqqtsrwuwwyy{} ƒ~vvxvuvwvxuzy{ywrsosrprttsvtvuvzzxۚ|yxzxxyzywxvzz{zyqrruvrststutzwx{}{~wwvywywxxwvx{yuwostsststssxvxv{yz{}ɏqtxwv{xwyyvvxwxwv{zzxursqrrutsvvwvx|z۞|nltxz{yyxy{xyxywxy}zyzwqrqtusttstwwz|x{z{}vnopstyvyxxyxzvwvyvwz{zyvwopsrurttuswyxvywz|~ﴀqqopvx{{|{{x}xxyxxvwx{x{wssqtrttsvvwyxy||}ttutqppnqwyyzx{w{yxzyzv|xyzwzssvsussttrquwwzw}|~|vutpsqssouwxx{xyyzywvzxxzxyvwsqrsrsrwrstswywywx|xvtuvutsqqotyzzy{{|{{z{xxwzxxwssttqpvvsxuvwwzz|}zxvvxssutsqqvxxyz{z{zxxywx{w~twoqrrupsrqrssxwx|}|~{xxvxtxutstqxy||}zy{{xz{y{xwxxyumppsqpttsrwwvyy{}}zyyxvxutrsqtxxzz{y|z|}{{|{{xwxzzuqrqurrtxsvvwxz|z}{yxxvuusuv{{z|z{z|yxy{xxy{zvwqpursppsswx|x{||{zyyxyyvtussz|}}|~}{}{{yvxx{uzvroqsqruustuywwywz|}}{yzxtutvuttxx{z||{{~{|wyx}zyzsstqttvxvwwyxy||}}}{zxyvzxvvsyzz|~|{}|yz{{zyvwx{ytsqrsspqtqrsuxwz|}|~}{}zzvxvttvyz{|~||~|}~zywxvyxxrspsrprtsrxuwwy{|~{{zyxyxxuvx|{||{ysz|wzxwqrquuptxsvsvwwzz~~{}zz{yvvuuy}~~~|{y}|zuvx{xwwppurspqtstsux{x{|~{zvxxyxvvyz{|~|~{~~}~}yyvu{zzxsrqsqruussuywwxwz|~~~z}{{zzyyu{z|}}||~|}{}ywvwx{wysstruttvxvwwyxy|z}~~}|{yyxvxyz{~}~~|~~~~{yvyv{wwsqrrqsqtqssuwwz{~~~~}}zzxy{~}}~~|~zwvw{yxxwsprrtsxwwyw{|~~{yyxxz~~|{}|wvxyyzvyouttvssvsvsvwwzz⃆~}yzz{zyz{z~~~~À~|yuxx{uzvopsrurstutsux{x{|}~}}{{y{|~|~~~~{vyx}zxyssqrrtstuywwywz|}~}~{{y}|~}}|zzvwx{vvrqtsvpssvxvwwyxyz|}}z{{|~}~~yxxywwrpprqsttqrsuxwz|}}|{zz{{}|{wwvx{yxzuqrrutsxvwvyyw{}}}~}{}|~~}}{zvyywxvqrstsqsvsvwvwvxzz턁~}}{||~~|{xxv{zwusosrsrttssuwx|z|~~~}z}~~||yvxzuzuyqrrtqttsvuw{wywy~~}~{~~{xuux{xywostpspttsvsvwwzyz~{}~~|{vyw{zzwsrqssrttussvxwx|}}~냁~}}zywux|wzsstqtuttvuywvzyx|}ȁ}}|~|yuvxxywupsrruqssvxvwwyxyz|~~~{ywtxzzxxssprrpttsrsuxwz|߀}~}|}|yvxy{ywsqrqtrtutsvvy{|~~}yxuuyvxsorsrssvsvwvyvyzz~z|wtz|wzxwspsrqrwssruww||ဂ~}{yuxyxzvyosqusrwtsxuwyyw{~̂{{xvu|uxvppurspstsvwvwvxzz􅆅~~|{ywwzz{zyrsqrqrutssuwx|z}}򊋊{xuuxyytyotquupvtsvuw{vyw{|~|{vvuzxyvppsrsrqtstuvwvzwz~}|zyvwx{vzssqtqrutusstxxz}||yvvxxywwpqtsuttsvuyxv{yy툅ȁ~~|~{vxx{xzurprssqqsstsvwwzwx|ρ~}zyvux{wzusqsqrttwssuxwz|}}掍~~yyxywvsqtruttusvuywv|yx{񅃁~}|~wwxzzxwpprsqqtuwwzwx|内}{zvxz{wzuqqsqrttssuxyz{}}~~{ywxx{wtsqtsuttvtywv|y|{|}zwtxx{xxrsprqqtvvwzwx|~{yvxxywysqrsqrttssuxwz{}~}釅~|{wvwx{wurqvsuttvtwwzy|{|}zwwz{xzsspsqsqtvvwzwz|}~ڎ~~ywvzx{wwsqrrqrttssuxwz{||}񈅈}|{ywwzxyupsrsuqttsvtwwzy|{{yywvvxuqrqlkggb`[ZZTPKIDA93+}~{zzxxvwsstpjkicc_]ZXSOPID>83(#~|zxzwxwttstrojijac`\UTQMJJB82-~{{wyywvtuuqsqlkgfd]]ZVOKGHD=1-}{zvyxvvxssrplkgeb`]ZXTPKIF<43)~{zzxttrrppligcc_\ZXTONID>80({yxyywwtusrsojihfd][UTQMIF=8/+چ~}yxwyxvwussrqligad[YXVOKGGB;4.􅆅~|{zxxwrstppkigc_`\XSONKLA<4.~}zxwwxttuttoojhhc_\ZUQMKGC?9-|yywyvwtuuqqolihcb][XVOIIB94,~{yzvxxvwsstrlmgec`]ZZVOKIF@<2~|zzwvztprtnljiec_]ZXSOPKF?=4~|yxyywwtssroljjhc`[UTQMHKD:7}{yxwxvvxuqrqlkifd`]ZVQMIGD:4|{zzxvtstrpkkgec`]ZXSPKIE<4}yxyyxttstrohifc_\ZXTONID>8~}ywwyxvtuuqsqjihfb][XTQMID@8~}{zxyxxwustromke`b[YXVOKGD@;~{zxwzztpurnnjigc_`ZXSONKHB<~|yywvwtssrqljjhcbZXSOMKIC<~{yzwwvvxustqokihcb]YXVOKGB9~zzxvwsstplkgec`]ZZTOKGB<}yxyywttstrlhicc_\ZXSONIDA}}{wwyxvtuuqsqjihfc`\UTQMGF@}~|{zxyxxvussrqlkead][ZVOKIG@~}zxwyxtpurnpkigc_`\ZUQNIHBzyywvwtssroojhha]ZZSOOKJC}~{yzwxvvxusrqojihc`]ZVTOKGA~zzxvwsstplmged`[ZUTQIGE~{yxyywttpligcc_]ZXQPKID}}yxwyxvtuuqsojihcc`ZXTONID~|{zxyxxwussrqligcd]]XTQMID|}zxwxztpsrnpmiec``YZVOKGG}yywvwtstrooihc_]ZXSONIG}|}zzwxvvxuqrqljghc`[XTOMIG~zzxyzxwtssrplkged][ZVQOIH|{wxywxttpnligcc`]ZUQNII~{yxwyvvtuurqojjha_\ZXQPNI~zz xzxvwustqojihcb]ZVTOKG|yx{wxywpttnikged`[ZUTQIG~}ywyywwttstrlhgcc_]ZXSPKI}~}{zvyxvwuuqsqjihcc`ZXTONI~|{zzwxxwsstromigab]]XTQMG{{wyywyttstnnmiec``ZXVOKG}{zvyxvwtusrolifc_]ZXSPKI~~{zxxvxssrqlkhfc`\XTOMI~|}zxwyxtrsrrpmkg`d][ZVQMI{yywvwtsttloigc_`\ZUQKG|{zzyxvvxuqrsljjha]ZZSONI~}zxyzxvwssrqlkihc]]XTQMIzyyxywxttrppkiged]YZVQOI}~{yzwwvwtusrooigcc`\ZUQNG~zzxvxuqrqljghcbZZSOPK~{yxywxttstrplkgedb]XTTMI{yxwwvwttpligca`]XUQMK~}zzvxvvwuurqljhfa]\ZSNNK|zxzyxvwsstqojihcb]ZSOON|{yxyyxttrrpjkggd`][TVMK}~{yzwyvwtustpoigcc`]ZXQOG~zzxzxvxusqqljjha_\ZUNPK|{yxywxwtsstplkihcb]ZUTMN~{yxwyvwttpnliged`[[VTOK~|zzvwvvtuurqohgcc`^ZXQPI  " !!!!! ! "+06=BHOSVY]`dfkkns    !! !! "+,8=BKMQXZ]aefjoor! !"" """!! )06ABHOSUY[`fhikpr!  !!  !!   ! )06=BHMRUY]_dfkmns!   !! !!!  +,6=BKORUZ]`efkoor!   "" ""!! ).6?@HMRUW\_fhilpr  !!   !!""  )06;@GMPUY]_bekmnr   !!!! !  ),6GKPU[]`cehopq     !! !"',5;>HKPSY\]cfglnr    " "" "!!',3:=GJNSV\_adilnr ! ! "  #! ! ',3<=GJPSZ\accflpo   "" !!!"",18?IJOSW\]afikkr !  "! ""!!$,18=CHNSV[_adhkno ! ! "  !!  %,1<;EKOSZ\_adfjoo!  "!!! !! ! "+08?EJOUX[]bdjkkn! "" "! "!! )16;BHORV[_`dfkmm$    ! "  ! "+.8;DJOSUZ]`chioq!! ! !  !!!  ),5?BHMSUW\_bikkn" " !!! " !!! )03;AGNPUW\_cckmn$     """  '.5;>IMPU[]`cchlq$" !""  #  !! #,5<>IKPSW\]afilm"  ! !! !! %*3:?CHNSVZ_adjjm" !    "!! "" "! %,3:;EJOSZ\_adfip" !    !! ! ",/8=EJOUX[]bfikk#   ! !! !! )08;BHORVY]_dfkm#!   "  !" ""! )06;BHORUZ]`ceil## !    " "!  !! ),5=@HORSW\_afkl#! !  !  !!!"',3;AHJNUW\_cdjm$"! ! !! ""!!! ',3;=GJPSZ\_affi$"   "#" " ! ",/:=GJOSW[]`fhl$""   "  !! !" +08?AHNSV[_`dhk'%#   ! ! "!!! ,06;BHOSUZ]`ffg$#!! " ""!!"" ! +,6=@HORUW\`afk%#!    "  ## !! "),3;AJJNSW\_ecj%#! !!  !  ! ',3;?GJPSZ\_afh&$$!! ! !!""  %,1:=EJOSW[]`df%$"!  !! ! " +08?BHNRVY]aeh&$"  ! "  !  !!! *06;BHORU[\_eg&""  !!!!"" ! ),6=>IMRSW\__d*'# ! "! "!" !!  %,5:?HJNSV\_ed&%#! " "  ! ! $,3:=EJOSZ\_`f'%#$!  !   !! ""! %,/:=DHMUUY[`d'#$$"   "!!#  !! "+.8;@HOPSW]`e')$" !   #!! !! ).3;@HKPUZZ_c(&$" !  !  !! ""! '.3<>GJOSW\]b(&%#! ! !! !" " !! ",18ACHNSV[ac('%&$ ! ! " !#! !! )06=BHORUY\],'%$"  "  ! "!! ),6=>IMPSW\_)'&$"!!"" ! #,5:?HJNSW\a)(&$" !  "!! %,3:=EJOSZZ])(''# !     ! !! $+.8=@HMSSWZ'('%#!  !  !!"" !  ),5;AHNPSW]*)'%$$!   ! "!# !! ),3;?GJPSZZ+)'#$'"  "! "  !!   !!! %,1:=DJOSWY')'*$# ! " !"  !! "" ! "+08?@HOPSY(*(&%#!  !! !#  ! '.3;@IMPUZ+*('%#$!   !  "#!!  !! ',3<>GJORV,+('#$$"  "  ! "" "! ",06?BHOSS,'&')$#   !  !#" ! '16;@HMPU)$*(&$#! !  " #!! !! '.3<>GJNR,+*('%#!     !! " "! ",18?AHOSsyz~𲳴ɤwyy}vvzz}tw{~wy{}䈊tvzz}Ǜtx{}wyz|rxw{}tx{|vxz|z½svw|~쵸ޒtxz|}¾vwz{~ssx{}ʥtyy|~Ĵsww{{~ķ݊sszx~~Ǻuwyz}Ϩpvwzz}ƾrtxz|}·tvwz|}úrrvxz}Ǹpuuzz~ȹƯrtwy|}˽̲qrvwzz~ɥnssw{~üȯmrwyz|}ƺ𵲴prrxw{~Ƚ¨nntx||̼ènrvvyz{~¾nrruxz}ƾkmuwyz}ɽȲoorvwz{}lprrxw|}οեlnrrxz|ͻ¿lnovvyz{~ɿikrrsy{~̿ѥkmmuwyz}¿koqpvvzz~glnruu{z}᪥glnrtyy|{~կhloorvwz{~¿hkknstw{|ξfkmmtwyz|zѻþehmqrqvw}}filkouuyz}dfkmqrwyz{}efimprrxw|}żdfklnntxz||¾󹷷adjjmrvv{z~cdfimorsz{}ƾҷ`diklnrvwz|zƺþ_ccjmmovvu{}þ`cdfimrusy{~_afhkmmswyz|}Ƽ[_bfkooqtvw}ع]`ceghmpuuy{}ӻZ]afgknmtwyz}[_`dhjoqrrxw}ǀþ[]`ceglmptx{}þY\]afhjmqtvx{|W[_adhkoprry}~VZ]`egklnosy|~~~yvqoolljgjgccecege`[[^[[^^`^`[`XUQIIFBFFIMIIMMIQUQUU~yyvtqqojljggeegcc`[VYY[[^[[XUQMMFBBFBBFIIMQUXUX~{yvytqjojjgeegccgceg[Y[[Y[[^[YUQMUQIIBBFIIMQUX{~{ytqoljljggeg`[[YY[^[[XUUQIFBFBFIIMIMMQUQU\{yttoqljjgegjjggcVYV[YY[YY[YVXXQMFBBFBIIBIIMQUXU{{yvvttooljjgegcee`YVVYYVVYY[YV\UQIFMBBFBBFIIMQXUU~{~{ytloolljgege^VYYVVYQMIFB>FBFIIMQUX~{{tqqlojjlgjjgjjggYYVVYVYVVYTQMIQMFFBBFIIMQUQUX{yvvqtoloqgjjlgglcYTTVVYTXUUQMBBFIFIIMQMMQQUXU~{{yyvqololjjlljljjeVVTVVUXQIF>>BBFBFIIMIMMQQUUX~~~ytqqoqlljgjjogj[VTTVVTVTTVVTQQIFFIBBFBFIIMQUXUU~~vvtqqoolololoeYTQTTVTQMIFMIBBFBFFIIMIMMQUQUX~{yyvvttqoljoollgol^QTTVTVVTMMQMFBBFBIIFMIIMQMQQUXU{yvvqqoljloYQTTQTTQTTQOQQMFB>BBFBFIIMQUX{yvttolqljcQQOQQTOUMFBBFBBIIMQUQUy{vvtqtqolqoqlloocQOOQQOQQTQMIFFIBB>BFFIIMIMMQMQQX\~~{vvoqqoloeQQOQOQQOIFFBFIMQU\X~{yvttqtolootllVQOOQOOQOQMMIF>>BFBFFBBFIIMIMMQQXXU郀~yvvttqtoqqtqtqvgTLLOOLOOQIF>;BBFBFIIMQXUU\{{yytvvqqoqtqqlqlVOOLOQOLLJMFBBFBB>BFFIIMIMMQQUX\~{{vyvttqqtqooqo[OOLLOOLLOLLOJFB>FBBFIMIIMQUU\\~yyvtvtqqvtoeJJLLOLOIBIFB>BBFFBFIIMMQUU\돍~{yvyvqvqtvvqqt`OJLLJJLLOLLJJMIIB>;FBBFBFIIFMMQQUXX쒍~{~{vy{vttvttqjQLLJLLJLJGMB>;>BB>BFFIIMIMUUXX\{yvyvtvvqeTJGJJGJJLLJBB>BBFIOQUXX\~y{{yvvtjYGGJGJJLJJGGB>BB>BFFBIMQUXX\X숃~{yy{vvtyvtvtqq[JJGJJGJGIFF>>;BBFBFIIMQQUUX~~yyvtvttoeOJGGJGIB;;>BB>BFFIIFMIMOQUXX~y{yyvyv{vt`QEEGGEGGJGGBFB;>BBFBFIFIIMUQQXU~~{~y{yy~tvtojVEGGEEGGEEGE>>;>BB>BBFBFIIMQQUXU{~{yyvytol^GGEEG BFBBIIMQQUXX~{yy{yyvo[JEBEEGEE@BB>;>BBFIFIMOQQU~~{~{~{~{{to`OBEEBBEEBBEB>>;;>BBFBIBBFIMQQXX~~{~yqlgTBEBBEBBE>;;B>BBFFBFGIMMQUU~y{{yoj^JBB@BBEBB@;;>BB>BBFBBFFIMMSQ~~{~{{tlVJ@@B@@B@@B=B>>;>BB>BBFFMUQ㔏~{~~yvojgTBB@@B@@B;B;;>BB>BGIQQ𠛞~{ytlg^E@@=@@B@@8;;>BB>BB>BFIFMQQ~~{{qlYJ==@==@==@;;>BB>B>FIIMO~{ogcQ@@=@=@==@;>BB;;>>BFFIMM~{yqje[B@=;==;==@==;>>;;>;>;>FGMM{yvogTG;;=;;=;=;;=;=;;>;>;>;;BFIIM~~yoecO==;==;=;>;>;;BFFI􀃀{yqge[@=;;8;;=;;>7;BFI~ytle[J88;8;;8;8;>;77;>;BGI~{vogcO=;;8;86877;7;BFIvoecY@;;8688688;88677;7;BFBꅃ~yqje[O866886886686877;;3377;77>B񛗗{tqgcL@6886866866;7337;>;Btqg`^J686366366833663733773733;7;B򙗒yqjc^Q=636636336373077;B򣠞􅃀ytqj`TE66366 370337;>{ytg^^L;6633133131137003;7ފ~vqle^TB311331331313313130033003;7썈{tojcYG6133131131/110030,00337䙗{ytlc^TB131/11/11/1/1030,,0037鏍~~tle[YO81//1//1//1/,/03,,0303~~tojc^QB11/11/,//,0,,0,003𭪨񈃀{vqoe^[J611//,/,0,(,00{vlg`YTE/,,/,,//,,/,,0,(,,0򲭯锒{vojg^YG6,//,/,,/**,*,,(,(0壠~yqoj^VVB//,,*,,**,*(,蔒~{ttjc[TJ8,**,**,**,*'**((,,$$,壠~{tqje`YT@/*,,**'**'*($(\]]Xbbffppuzussmgff^WULLD:B77FGFMIOQQXX\XX`\`\\`fbbfbkkpkpkkfbggaa[UNHNNBHB<6;;BFIFIMQQUUX`\\`\``]bb]ffkkpkfbaa[aUU[QNBNH=3;;>BFFIMQQUUX\\X``\`\`bbfkffppkpkkfbgaU[[NHNNH07;;>>BGIMMLQUX\XX\\`fkppkfbaU[UU[UN377;>>BFIIMMUQXUUXX\\X`\``cbffbkkppkpuppkfbfgga[aU[[U33;7;BFBFIMQQUX\`\``ccbfkkpkkuuppkppkkfkffba[[0377;BB>FGFMMOQQXX\`c`cgkfkkpupuppkpkkfbaga[[00337;;BFIIMQQUX\\c`cggfkkpuppuuppkppkkfkf]f[[003377;;>BFIFIMQQUQUXU\\``cggfkkppuupuuppukppkfkcbb],,00377;;B>BGIMMOQUXX\``gkpkppupuupuppkppkkfkkffbbc771à3n@.2J6 :7J9_5㮭38/DDLUW^f^Wa[[UUdsyyG;;DLPW^f^^[Uksszy~Q533;;DHPW^f^[[Ucmsy ǜdA2433;DAAHHPW^W[[UYgsyyϦjH-++3:AHPW^[U[`gsmszyۻW4$$+3:AHPW^[[UYajsyyغ`B&$+3:AHPW[asst̝`<$+3:AHPWUU[[UUXrmyK $+3:AHPNUU[ksszy $+3:AHPNNUYajmsyyy$+3:AHNXfgssyy$+3:ABBHNSagssyyz'$$*06<BHSLcgmsty<6**'$*06<BMB][agssyyH<<6600.-$"$$*06}~{yxyywwqstqoliha_^ZXTOKIB?~zzwvwttrpplkihcb]ZXQPKGB:|}zxxvxusrooiged`]XTOMKJC=}{yywzttssrqlhhc_`YXVQMII?<~|{zwywwttstrqlkhfa]ZXSQKIG@8|zzxyxvtustnnkggab]ZXSOKIFA8~{yxyyxvwusqqohgbc`][XTQNIDA<|{yxywxwtsstqojjhc_]ZZTOKGB?9~{zxwxvwtutnplkihcbZZSNNIEA99{{xzyxxvxusrljig`d]]XTOPKHA=4'}~}ywyyxzwssqsqlifc``YZTQMIFB;4~zyzwyvwtrstrojiha_\ZXVOKID@83|}zzxxvvtuspnjmigcb]ZXQPKGD97/}yyxwzxvxuqrqoigfd`]YVTMNIC<4-~|yzyywytrssrqljhc_`[XVQMHJA<4-|zzvwxvttqtnnmigfc]ZXSQKIG?81(~{yxzyxvwuutrlkgeab]ZXTOKIF@5/%|{yywxwwssqslhgcc`[[XTQNIDA90%~{zxwwvttrrqojhha]^ZXTOKGC?93&|{yzzyxvttstnpmkgfc`ZZSONGHA:71&}~{yxywvvwusqrohiecd]]UTOPIGC;2* ~{zzwwtwsstqojicc`]YXTQKIDA<2+~|}zzyxvwtutpplkihc_\ZXTQIGB>83+}}yxxwxxvxusrljiged]]XSONIFD990(~}yxyywyyssqsolibc`[[ZTONKHB;4*~zzwvwttrtrolihc_]ZXVQMGF@<2.}{{xxyxxvtstpnkkghcb\ZUSOKGB>80+~}ywyyxzwusqrooiged]]XSOPKGC:7-".,*($&$$"! ! !!"  !! )16;BHMP.,'(')$" !!! "! !! ).6<>IJN.)+)(&%#!   ! !! ""!! ",1:?CHO.-+*('"#!  !" !!"" !! *06;BHM/.,*(')$"!  !!"! !! ).6<>IL/.-()'&$" !  !! ""!! #,1:?CH)')+)('%#! !  "  !"" !! *06;DI-/.,+('%$$! ! !! !! ),6<>H1/.,'($($"  " !! ""!! ",1:?C00.)$)(&$#   !  !!"" !! *06;D.)')+*('%#! !  !  !! !! ),6<>*1/.,+($&$%!  !! " !!  ""!! ",08=30/.,'(')$" ! !  !!"" !! )06;320.)+*(&%##  "!  !# !! ',3;90-+/1/.,',$($" ! "! " !!"" !!871075300.)$*(&%#!     !!  !!53597542)')+*('#$$"   !!"   !#   ":8<982/+-/.,+)')$#!   !  ""!"" !A><64.,/10.-('(&%$!  ! !" !!<982135420/&.*)'&$" !!   " !!  "854747643*0.,+)('%#!! "!"!! "" 85:8;921+.0/.,),*%$"! !!  !!" !=;:4-+/1/.-()'&%#!     !!  <>BA>72035310.&.*)'&$%    "!""8:?853657642-(-,+)(&'#!! !!  !" 7;:9598:823+*0..,)/*%$"!    !!  4;;8;9/2/30/.,#)(&$"! !  !! "!!! "48;2035320.&+*)'&$'  "!!  !!#$.48:?<33257643-(*,+)('%#! !  !!$/.<;:95489865+*0..,),'%$"   ! "!!&$)1;:85?=;9/-/30/.,')(&%#!  "! !&)47<=A?861075310.)+*('#$$ !  !  ! *.8;:8=33597642)0.,+)'*$#!   "!!%$/3<:9753=:82/+1/.-(','%$"" !!  ! !"&&$/1;:8:><69/5330/*++)'&%"! ! "!   !( )47A>A>8617753.)',+)('&$"   " "! $*.8;:97435876+*-/.,*(')$#! !  "!  #!!&$/37:98:8;:4-,/1/.-(*)'%$$  !  !#"(&$43;>8A>62035320.&,+)(&%%!  ""$( .47:?=43257643*0.,+)('($"  "!   %" $/.8;:9558:862+.1/.,')'&$#!  !  #"!&$/1;;97?>;9064300.)+*('#$$  ! "UW\]_dhjmquxw|SV[_cefimpruy}SXZ]^dgklnsuz{}ˈPVY\_`djjoqsyz{NSVZ_cefilpsvzOSXZ]]diklotxxz~νMPVW[_adjkpptv}}͑LNSV\aceejlprw{~HOSV[\]bfhmpvyzy~IMPSW\_adimpqtw}ѾHJNSV\aafgjmptx|BHOSUY\]afilotw{|}@IMPSW\_beimosux}>IHNUU]]`eimnqvxz~;BHOPUY\]aejmrtvx}Ԃ;>IKPSW[_dfilnrty}GNRWV\adiklqtw|! "$-08=@KORWYccdkmosv{|!! (-2;BDKRUY^acfkprux{~!!!!"+18=BJOTWZ`cfjlruxx}!!*-4@MNSWYaegioqu{~""!!'.1DMOT[_bdfhnuvz{~ "  ""!+.7?DFMUV]_dgmmpsy{}""  "" ""#-2:?CLOUX\afhkprwz  "  " ).6=AJNQVZacdhnorvy|  "  "$""%-/8?AKPU[Z`eklquxz{"  "" ""%-3:?GNRU]^cegkouyz}! " " ""-16@EGNVX]`fiipquz{}#!! "  ""  "$/3:@EMRVZ]`hjkpty|!#!! "" "$)/7>BGOQV[ccfjmptvz~#!!!# "" $./9>DIOVX[aelkqsvy}Ô!!##!!"" ""$/3;@FOQVZ\eejlquxy{獔!#!!#!!"$ ,17?EHOS[\bdgjptwz~!!#!!##!##"(.09ACLSWY]`ikintxz葔!!#!!#!##&.4;AEPPW]_dgimstx}|!!#!##!!#!##*26?GIPVZ_bdjmosx{ !!!!#!!!##!!#$026ACMQVZ]ehhnpsxz}"  $!!####!#%(06BIQVZ\bekmptu{||þ񹴯뙗~{vojg[VO=*,**'*''*'%'%$($$(þݴ{vtoe^VQG6''*'**''*%%'%'$$(þ蛞{yqogc^VL=,**''%''%'"%$$($־{{ytjee[TJ;'*''%'%%"$(!䞛~ytqgc[QOE3%%''%'%%'%"%%"$!ު~yvqle^[TL;*''%"%%"%" !ᣛytvogccVQL6''"%%"%%"" " ~{vqoe`YQL@3""%%" ""  "  ڹ~vtojc`[QL8,%%"" "  þ蛞~yqtoec`QLJ;*"  "  "  ؼ{ytolc^VQL=8% "   蛙~{tqjg``YQL=, "    þ٭~~vtqle`^QJJ='  壞~yvqlje^VTLE6% {yqoge^[YQJB1 થ~{vqlje`[QJG=1 磞~ytqlge^YQJG3,ͼ~{tqoje`[YOEE;*砞{{tolgc`YTLEB1'藒yqqlgg^VTLGB1"٪~yvqljg`[VTGB@6 {vqlljc`YTOJE;,"򾼹ߗ~vqqlec^VTQJB@1 þࠛ~{vtlggc[YVLE@;/ ּ~vtojje`^VQOG@@, ݪ~~vqqoge`YVQLE@=1"þ۲~yttogec^[VQJGB@,"ȟ~ytqlje`^YTQOG@@6~vtolee`YVTLG@=Я{vqqjggc[[VQOGB{yvollec`[VQOGܯ{ytqoogee^[YTO{ytoljgec^^VQ{vtqljgec`^Vڲyvtoqjgge``~yvvtolleceþ޹~yyttoojgeyvtqoljl{~yvtqll⹷~{yvtoq~{{vvt왗~~yytչ~~{vƾ{{ᾼ~鷴𞛛شüþþü繴Ⱦþ,(,007>;BFIIMQUX\\`gcggnkkpkuupupuppkpkkfbff($,00337;7;>FIIFMMQQXUX\c``gcckgkknkppuupuppkpkkfb$$,,0337;>>BGFMMQXU\\`cgkgknnupuupuupupkppkkb$((,(003077;>>BFIIMQQUU\\`ccggnknnrppuupuupuppkpf!$(,$,00377;7;BFIIKQQWXX``cgnknrrvzuupuupupuppkpp!$($(,,0337;BBIKIQQUXX\``ccggkkrnrrvuupuupupukppk!$!$$,,303077>BBFIIMQUXX\cgkrnrvvupuupuupupp!$$(,$,00377>;>FIMMNQUUX`\ccgknrvrvvupuupupu!!$$(,00337;;>>BFMQQX\c`ggknvrvyvvupuupuupu!!$$,(3373;;BFBIMMQUXX^`ggknrvyvvzuupuupu!$!$$(,(03377;B>BIIMRQXX\``gcgknnrvyvvyvvupuu!(03377;>>BBFIMQUUX\``bckknryvyyvyyvvzuupuu!$((,0,377>FIQQVX\\`gcckgknrrvyvvyvvuzuu !$($(,0,377;;>>FFMUXX\``cfgnnrrnvvyyvyyvyvvuzuu!!$(,,3;>>BBFIIQUUXX\``cggnknrrvyvvyvvyyvvyvvu"!$(,(,0303;;>>BFIIQUQX\\`ccgiknrrvyvvyvyyvvyvv "$$((,03307;>>BBIFIMMQUXX\``ccgkkrnvvyvvyvvyyvvyv %$$(,0,0377>B>FFMMUXU\]c`cgkkqnvvyvvyvvyvvyvvyyv  "%((,0073;>>BBFIMMQUX\\``cggkknnvrvvyvvyvvyvvyyvvyv" %'(,,00373;>>BBFIIMQQUX\\`ccgkknqrrvvrvvyvvyv""%(,,0337;7>BBFFIIQMQXUX``cecknnrqrvvrvvrvvrvvyv "%%*(,,3037;;BFIMQUU\`\cggknnrtrvv  %"'**00377;>?>FFIIMMUUX`ccghhknrrnrtrrvrvvyvv""'%,,0377>;>FFIIMQQUXX`c`gkgklnnrnrtrrvrrvv "''*,0337;>;BBIMQXUXX\`cgglnkknrnrrnrttrrv  %'**/,0337;7;;B>BIIMQUU\cklnknrnnrrnrt %"%*',//03377;>>B>FIIMMQU\X\`c`ggknkklknnrnnr" ""'%'*,//37;7;>>BFBFMMQUX`\``gcggkgknnkknknn1' !"%%',*,//337;>>BFFBIMMQQUX`\`ccgknkklB6'  "%%*'*/,11377;;>>BBFIFIQQUUXU\\cc`ccgk@=6/ "#%*'*/,1/3637;;>B>BFIIFMQQUU\X\\`c`ccgccggJEB;,  "%''*,,/113687;;>>BBFFIMIMUUX\`c`ccgccQJB@=/% ""%&'**//1366;>>BFBFIMMIQQUXX\\`\``c`cc`cTOJGB@3*  ""%'**,,/3166;8;>>BBFFIIMQMMUXX\\`\\`\``c`YTQOG@@3/ ""%%('*,,1/16388=>>BIFIIMMQUQUX\\`\\`\\^YVTLJB@=,  " %%''*+,1/133688;=@>BBFFIMIMQUUQXX\`\c^^YVOLE@=3* ""%"''*,,//31386;;==BFIMQXUXX\g``[VTQLGB@8,   ""%'%**,-/113368;8=;B@@BFIIMQUXUUXXUXXUeec`[[VQOLB@=1/" %%''*,,//013388;==@@EEFIIQMQQUUXUUXjgge``[VTQJEB@6/" " "%%'*'*,//16366;@BGEIIMMQUQUUollece`[[TQOJB@@33"  %#''*,,//1236688;@==BBEJGIMMQQUQtoojgge``YVTQJEE@=6*%"%""''*,,/1335688;;=B@@EEGLJLMQQUttollece`[[TOOLEBB63* ""'%**,//13688;@=@EBBGGJJOMQyqtoojggc``YVTQJJGGB=6'"%'%%*(,,/13368;;=B@BGEEJGLLOLQ~yvtqtollece`[[VOQOGEE@63'""'*'*,*/1/1336688;==@EBEJGGLJLLJLL~y{vyqqoojggc``[VVTOOLGJB=6'%'',*,//13368;=B@@BBEEGJJLJLL~{yvtoojlece`[[YTVQOGJJ@;3,'*,**/-113668;=@EBBEEGGJGJLJ{{vvqqoojgge``^Y^YVTQLJJ@;6,'',/,,1/133688;=@BGDEGGJ~yyvtoqolleec^`^YYOLOGB=1,,1//323668;;8=@@BEFGJGG셈~yvvtqoojggecc^[YYVTLOOGE86/,/./31166488;;=;@@BBEGFGG~{yvtqoolleeceec^^YVTTOOJE@83//113866;==@=@BEEG{yyvtqoqjglgejecc``^^VVTTJE@83/136366;89==@B@BEEBE~{yvtqqljgeec`^^[QQVVTLGB86116866;8;=;@@BE{yyvvqoqllqljjgecc^[^[VTVTQOLE=63388=;;@=>BB@B~{{tvtqtqooloojllggecc^[^YVVTQOJ@=;68;;=@B@B~~{{vyttqqotllolljjgjegge^^YTOG@@;8=@;@B@@Ꮝ~~yvtyvvttqotqoollojjegeg`^``[[YVTOJBB@@=@y~yyvytqtqtqlqooljegg^ee^^`VQLOJG~~y{{vyyvvyvqvvtqttooljlee`ceccYY^~~{y{y~{yyvt{ttvvtqqtolooljogjjege~~{{~yyv{yvvyvvtqtqoqqllooll웙~~{{{y{yvyyvyvytvttvqtqtt~~~~~~{~{{~~{~~y~{y{{v{~~~~~~~bffcbb]]faagagmmggssmmysyȳbfkfbfcbffhfkffppkkuppuzuuzzkkbbfbfhfkpmkpmppuwuzz|zkkbkfbbffkkfkpkpuupuzzuzzۉgfpfkkpfkffkpkkpuppuzuuzzՄkkpgfkpfkkpkppupuppuzuuz􎄉kplfkpkkpupuuzuzzzppkpkkpkkpuqppzvuuzzupkuppkpkkpuz鉎uppupkppkpuupuzzuzzz鄎uppuppuppupuupuzzuzz󎉉ukpuppupuuzupkuuppuppuzuuzzzuuskuupkuupuzzuuzz󉅈}}upuunpuusuzzuuz}}~~}vyzuupupuz}󈁁}}~}}}vvpuupuuzuuzz}~}yyvyvvrvrrvvy}y}}}~}y}y}yvxvyyvyvvrvvrrvvy}}~}}y}yyvyrvyvvyyvvyvvyvrvvy}yy}}񁅅}}}}yyvrrvyvyvvyrryyrryvv}}yy}}}}y}yvxvvrvrnrvvyvvyvyyrrvrrvyvy}yy}}}}}}}~}y}}yyxyvyrrvrpnkvvyvrryrrvyvy}}y}}}}}}}~}y}}y}yyvyyvrrvvnnknknvvrvvyvvsrrvrrvvy}yy}}}y}}~}}y}}y}yyvtrvrvrnnlnggccrvvrvvyvvrsrvywvyzyy~}y}}y}yy}yyvxvrrvnlnkknkc``vrrvrvvrvvrnrvvrryyvv}}yy}}yyvyy}yxvyvxvrvrrvnknnggcc`\\rnrtrrtrrvrnrrvy}yy}}yyvxyyvrrvrrvnkpnggc`\rnnrrnnrnrrtrrqrrqrvrtyyvxyyvxvyvrrvrrvrnnknlkkngg``\nknnrnrrnrrnrvrrvrrvrvrnnknlkknkkgc``\\Xnkklnkknkknnknrnnrvrrvrnrvrnnlnknlkkgcc`\Xkgkklnkklnkkhkgkhknnlnknlnknlnknknggkkgcc`\XUgkgkknkgkgkgkknknkkngknnggcg``cc``\XUXQcgcggkggkgcckggckggcg`cc`\X\XQU`cc`ccgccggccgc``c``c``\`\X\XUQ`c``cc`cc`cc`cc``\`\`\\X\XUXQQ\`\\``c``c``\`\\X\\`\\X\\X\XUXQUQM\`\\``\``\``\X\\X\X\XXUXUQQUUQUQQMQMMIIX\ \`\\`\X XUXUXQUQMLUXXUXX\XX\\X\\XUXXUXUXQQUQUQQMLJUXUXXUUXXUXXUXX\UUXQUUQUUQU QMIMLJJUXUUXUUXUXXUXXUQQUQQUQQUQQMQMMIMMLJJGJQUUQU UXUUXQQUQQMQQMIMMLJGJJGJEEGQQUQUQUUQUUQUUMQQMQQMQMIMMLJLJJGJEEGGEEMQ QUQQUQUMMQMMIMILLJJGJJGJEEGGEEFOOLOQQMQQMQQMIMIMMLLJLJGJJGJJGJGEGGEEBFBBELLOLLOOLOOLOOLJLJJLJGJJGJJGGJJGGEGGEEBDBBEBBJLJLLJLLJL LJGJJGJJGJJGGJJGGJEGGEGEEBFBEEBB@GJJLJLLJLLJLLJLLJLJGJGGJJGJJGGJEGGEEGGEEGEDEBDBEEBB@B@@GGJGJJGJJGJJGJLGJLJJLJJLJGJJGGJEGGEEGEEGEEDEEDBBEBB@B@>@@FGJGGJGGJGGJGGJGGJJGJJGJJEGGEEGEEGEEGEEDEEBBEBB@B@@=@EEGFEGGFGJGGJGGJGGJGGJGGJEEDEEDEEDDEEBBEBBEBB@B@@>==@== EFEGFEGFEGFFGGFGGDEEDBEEBBEBB@B@@B@@>=@@==;=EBEBEEBEBBEBB@BB@@B@@=@=@EOQBBEBBEBBEBBEBBEBEEBE@@BB@@B@ @>=@@==@==BEQQY`eB@B BEBBEBBEBBEBBE@@B>@@>=@@==@==;=BJQTY`ccggB@@B@@BB@B@@B@@BB@BB@B@@BB>@@>@@=@@==@==@==@EQO[Vcceegoo@@B@@B@@B@@BB@@B@@B@@BB==@==@==;==@ELTQY^eejqlsvvB@B@@=@@B@@B@@B@@B@@B@@=@;==;==@=EJLLVQ[^ccgegjoostvy{{YVQOLJGGE@@=@B@=@@==@==@@==@;=@@B@EJGLQTTYV^ccecggollqvvyy{~~gegc[Y^[TTYYQOQLLJGLJJOQOOTQQYTVYV[`^ccecjjloosvvy~ljejgeeggeccec`^c^^`^Y[`^``ccecceccgecggejljlqqtxvvyy{y~~vqqollojjejgejgegjgejgeelgcjjgjljloostqsvty{{y~텃vyvytvtvqtqqoqloqoloqloqqloqooqoostqsvvy{y~~~څ~{{~y~vyv{yvyyvtyvvyvvtyvvyyvtyy{{yy{{~~~}yy}yyrrnngg``\\XUQUMMILLJJGGBEBB@>==@Q}~}}yytrrvnnk``\\XXUQMILJGGEB@=;G^}~vyvrrnkgc``\\XXUUQQMLJJGEEDBB@@=BTe}}yvrllgg``\XUQUQMMJGE@>==@L[e􅁁~}yvxrrngc`\\XUQMIILJGJEEDBB@=;GYcg}}y}}yrvnnkgc``\\XXUQMLJJGEB@=EVccj~}}yyxvrvvnlng``\XQMLJGJGEEB@B>==L[ejl}}}yvrrnkkngc`\\XUQMILJJGEEDBB@@=;G[cglo~}}yyvyyvvnnkgc``X\XXUQMIMJJGGEB@>==EVecloq}}v}vxrrvnnknc``\\XQMLJJGEEDBB@=;=O^glost}~}}yy}yyrvnnkgcc\\XUMJGEB@=O^cjotvv}}yvxrrvvnlgg``\XUQMIMLJGJEEB@>==LVecltvtv}~}}yyrnknng``\\XQMJGEDBB@@=;G[cjlqvyvvyyyxxrvvrlnkgc``\XXUQUMMJGEB@@==BTccjtvy{{yvrrnknnk``\XUUQILJJGEEDBB@=BV^egovvyy{~}vxvrvvrlnkgcc`\\XQMJGGEB@@=BO^ejoty{{y{{yyvrrng``\XUQMMLJJEDBB@>==OVceotty{{~~rrvrnnkc`\\XUXUQQMIILGGEBB@@=@JYeelsyy{~~~rrnknkng``\XUQUQQMLJEB@@>==JTegqqv~~rlnkkgg``\\XUUQMLGEFBB@=@EVcejqyy~~~knngc``\XQMILJEB@@;GYcglov{~kgcc``\\XUQMLGGEDBB@=EVecjtvy~g``\XUQQMLJEB@@=;EY^ejov{{``\\XUQQMIMLJGGEDBB@>==GTeellty`\\XUQMJEB@=;;GY`egqvt{\\XQILJJGGEDBB@>==;JVcglos{~XUQMJEB@@=@GVecjoty~XQMLJGJGGEDBB@>@@=L[cejov{{~UUQMILJJGEEB@=@QQcclltyXXQQMLJGEDBB@=;@LYcejqvv~UUQMILJGGJEEB@@=BT^cglovy~QMLJJEGEDBB@=GY`ecltv{~QQMILJGEDEEB@>==@LQcejlsv{􍏔QMMLJGGJJGEEB@>@@=;=LVecjoty~~󔙗MMIIMLJJGEDBEEB@@>==EO^cglov{y~MMJGEB@>=@@=;=EVcceoqty~JLLJGGJEDBB@=BO[ceglqyy~JGJJEGGEDEEB@@B@>==@@;@EY`ccjotxy~JJGEBEBB@=BOYcggjsvv~GGEDBB@=@=@EY^ccjoqxy~EEGEDBEEBB@=ETYcggjqvv{GEEB@=@JY^ecjoqvy{EBE@@B>=@@==ET[cggjqvv{~BBEBB@B@@=;EOY`ecjqqvy{B@=@==BLV^cgjlsvt{~B@@B>=@@==EOQ^eegltqx{~󔙛@@>@@==;@LYYccjlovv{@=@=@EOT^cgejotvy{~ꞣ==@==EOY[cecjoqv{y~==BGOV^cejjoqvvy~~䯭==BGVQecegjottx{{~ܭEVQ^`ecgolsxy{~[^ecgljqtvy{~޲cgjjltqx{{y𷹼gloqvyv{~~紷oxyvy~~زy{{~~񠥪𹾾y~쒔󹷷贷폒ƅƍﯴ־þȏȔ^ellqttvy{~󯱱eglotvy{y򃈈쥨̼ejloqvy~{˾llnqtyy{~˼loqvy{y~޲loqvy{{~񯱲սnqtyy{~򯭯зqvy{y~پqvy{{~ɸtyy{~򽾺y{y~y{{~ֵy{~y~¿{ƾ¿¿߷þ~崳¿諃㍏뛚徺ⷹܵӴ¿陛޷¿쪯¿뺹¿𹸸󷹼Ϳ¼񪭭½󴲴񳱤ٿݷٻ¿󴷹᷹¿򴯲¾¿¿땐¿޼뽼¾񓒓¿⾽º¿踯⽿¿􍈎¿燄޿¿ǖ¼Ǜÿ|}z}}}{ttuourrutsxuyxxzyx|}|{{x}vsrtvutussvwvwyy}z|~}}zzrtussptvsrwuxyvyy|}}}|}uttuvrrussvwywyzyz|}͓}z}{rusutptusrswvyy|}}{wtvstrqstsvxuxyxyw|ې{~yuuwsswssvvww{zz|}}~}|svtutputsrswvww{{|}}vswrvttpvsvwvwyxww{萏~}zxwutxuttsvtww{z|z|}獊}}tutvwttvrsswwy|}~~wuytxttsusvuvxyxwx{}~vxuwyvwussvvwwyz|z|}~xvxuvvswxvtsuwwy{}}|yuwxxuwxvuwuyxzzwzy~~uwvvwuvxuswvvwyz}x~ux{vwutxzuvwtuwxyz}~~xtxuxxwuvwwxxzwzyܒ|}xxwxwytwxwvz|zxwzxvuuwyvxwwywxy|}}}xwyxzwywtxxwywzzy|꒑~xx{yxxwwxxuwwxxz|z}v||zwyxzw{wxzv{wz}y{xzyywxwwzy{yz{~}yxzywxxyvxxwy{|}|~|{|x{{xx{ww|xy{{x|x|~~~}z|{{zw{{xxy{{||{{||~|y{x}yyv|xwywzz{~|ԏ|{y|zz~{|zxy{y||yz{~{y|z{{v|zyyz|z{||{~|{|x~{|z|{|y||{{݆|}zƉ|}|{||x{|zz|{|yz}{||~}{x}{||z{yy|zy|{}z}|~}yx{~||}|{}|z~{{}}x|{~|{zx~{||y}}{{z}z~~|}}}{yxz}}~||x~{z{z||}{~|{yy}~~|}|~|y{}{~~{}|zzvy|~||}y|}}{|~|}~|}}yzxx}~|||~}||}}{~~~~}ywywx|}~|{~|~}}~~~~zzwyw|}{~~{{}|~}{yzzywv}~~~|}}~~{}ɑ~|{yx{yxv~}{~{{}~~~|{zxywxv~~}~}~~|򐎋}}{zzvwxwt~~}}~~~~}{yxyxvvt~}~{Ћ~zyzyyxzvx~~ۊ~{{zxwyvtws|}~~{yxzyxvwtr~~~{zyywvvwusz{zzvywytwss΄}~}ywxxvwtrst~{yxyyxxvtutt~{{zxwwtwuust~~{yxzzxvwrssrs񊉅~|{xyyxvttsrrq쇂}|}zzwywzwxuutpl~}yxzxxvwtpsso솈񏍊~{yywxxwtsrrqojۊ}z{zzvywxwwuutnplkă~}ywxzxxwtpssrqlkkƒ~{yxywxxvttrtrqligӔ~{{zxwwxvwuutppllif~{yxzyxvttssqrlmkihٚ~z{xyyzxvttrtrqlhiea~zzwywttpstrqjhfc_`YZTQMKHB=1*|}zxxvtplkihc_\ZZTMOJF@;4.ʀ~{wywzxvxusrnligecb]ZXQPKGB;80( ~|yzwywytrssqligc`]]XTOOKGB:4-"|}zzxwvwttrtrqlijc_`ZXVQMIIB=4-}}ywxwxxvwusrnjmihcc\ZXSOKID@85+~|yxyywzwusqrooigedb]ZXQPKDE97-( |zzvyxwtpstrqlhfc_`YZTQMKKA<4*" }}yzxzxvvtutrplmiha_]ZZXMMJG?<4.!~}{wyyzvxusrnliggcb]ZXSPKGD>83+~zzwywttrssqligcd]]XSOPKGB:7-(z}zxxjvwttrtrqlijc_`YXVQMIIB=1*!!~}{wywxxvxusrnkmihca\ZXVOKIF@;4."~zyzwyw{wssqsooiged`]ZXQPKGB<80(|}zzxwvwttstrqjhfc``[ZTOOKIA<4-"~}yxxwxxvtutpplkiha_]ZZVQMIFB;4*!"~}yxyywzwuuqrlligecb[ZUSOKGB>83+"|}zzwwvttpstqqjibc`]]XSONKFD990(~}{xzyxvwtutrpljihc_`YXTQMKGB;4*  ~}yxyyvxwuustnkkghcb\ZXTQMGD><2+!" ~|zzwxtwssqsohiecd][XSNNIGA<90, ~{yxzyxvwttrrqojjcc`[[XTOPIGB851& |{yxywxxvuutnpmkghc]^ZUVQKIDA<2+  !~{zxywxtwssqsoiieab`ZXSQKKIC?<0( !!"{yzxyxvwtstrqljgcc`][UTOKID@:1+& "{yxyyxvtustnnlkhha`]\VTONIFA9/%# !{zyywxwwuurplkggfc]ZXUOOIJA<40" !!"#zzvwxwtpssrqligebb]ZXQPKGF@:4+" ""#yxyxxvttrtrqlhhc_`[YTQOKIB97/(  "#xyywzvxustnjmihc_]ZZXQMIHA=1*"   "zwyvttrsqsooigbdb]ZXSOKIF@;4.!""##%xyxvwttrtpojifc`[]XSONKDB<90+" "##$yyvxvuutpplkiha_`ZXTQMKHB=4-" #%wwtssqrlkigcc`ZZXTOMGDA<2+ !"$ %zxvwtutrqljgbcd][XSPKGFA?93(!"!"#$%!yxvwustnnlkjfc`][XTONIGC81.&"#$&&wxtwusrplkkgfc]ZZVQMKIBA9,"# !#%&(xwtpssrqoigedb]ZXSOKII?<40 !!"#!"'xvtuttrqlhfc_]]XUQPKGD=83+" ""#$!"#zwuustnkkiha_]ZXTQMKIA:4-( "#$&(#twssoligecb\ZXTOMGFB;4* "$%'()ttsrrqojicc`]]XSONIDB>83.!" "## !'))wuutnplkgha`]YXTOPIGD871& "#$%&"#%rssrqoiggfc]ZZUQQKIDA<,'# "#$%'#$%trtrqlhgfdb]\XSOKIID<40"  !!%((%%usppljijc_`[WTQPKGD=83+" ""#%!"')*,sqrljkghc_]ZXVQMKIA:4-(  "#$&'#%,,ttqqjie`d`ZZUTQKGFB;4* "#%'(#%&'tnpljjcc`]]USONIDA?83+!" !"# %'()%''rrlmigfa`]ZVTOPIGC871&" "#$%!")),')rqoiggcb`ZXUOMKJCA9,%# "#$%&#$%,((rqjhfcb]]ZXQPKIJ?<4-  !$%&(#%%'()pmkiha_`Y[TOPKDB;83+"""# !"')%%'**ohigccb\ZZVQMKGB=4-( "##$!"#*,,.*+ljgccd]\ZSQKKGDA<2+ #%'##%&'.++mihc_`[YUTOKGGA<40%! !#!%'()%'')*-iggc_[ZXVTMNID;8/(#"!"#$%!')*+'**,-iecd`]ZUTMMJIB=1*"  "#$&&#$,,.*+,,jfc`]]USONIGB>;2.  "#%&(#%&'(*+,-gfa]]ZVTOPIGD:90," "## %'()%'')+&..edb`ZXUOMKIGA8/.& "#$%!"#),')*,,()c`]]ZXQPKIJ?<40"  "#$%'#$%,.)+,,00a_`Y[TONKDB>85+!! !%&(#%%'(#+,.13d]ZZXVQKIGB:70(" "##%!"()%%'**-5.*+$#"(&%$44<>AA87207542)'-,+)$''#!   "!" &$$! *.48:?85374764+*0.-,),'%$"# !!  !  '#"! $).<;:9598;9--/30/.,$)'&%#$!   ##"'&$$3;;8=;9/5330/+0+)('%$%    !# %##"&&%/47;=A?8613753.)+-,+(')$#! !   !""%$#"!*.8;:88335976/*-/.,('(&%$" !  #"''%#! */3<:97:9=:9-,/10/*++)'&"%$!  !$##'##!&&0)1;:8<>86135531(',+)($)$"!    !## %$#"&/47<69/5330/',+)('&$"    "$## %##!&&$/46;=A>8617753.-..,*(')$#!!  % %$#" )48;:88335972++1/.-(*)'&$"   "" &%! */8<:97:8;:9.,320/*/+)('%$" !    ##''##!&%/.1;98A>8613553.)+,,+(')$#!!   %## %##"&%/47<6435530(',+)(')$#!  $##'##!&&$/46;=A>8657753.-/.,'#'&%$"    ## %$#" )48;:8853;982/+1/.-(*)'&%&$"  !"" &$$!! */3<:98:9=;9/5430,',+)($)$#! ! #"''##!&%/)1;;8<>8613753.)0.,+)+&%$"   $$# %##"&&%/477217643*0/.,')('%$% $#"$#"!&$447613653.-/.,'*)'&$(# "  #"''%##!&&*436;=A?335872++1/.-++)('&$"!   $##%##"&)48;?9853<:9.0330,')++('*%$"   $# %$$!! */3<;:8:><61/7542)0.,(','&%#$ !#" '%%#"! $/)1;;=865775+*1/.-,+*)('%$ !""''%#"!&&$/47<>A<336982,/30/.),+*(+'%$#'##"'&).8;::8598;9/6532)0.-,(*)'& %$#" %$$! */.<;:8BA3379861+310/'-,+*& !$#"'##"!&.48:?85:8;:03543/10/.)(' $## %#"( *.87:98?>861775,+200.))( $ %$! %$/.1;;=AA335982-/320,'*) ""''##!&&%/.87:98538;9/7643*-,+*$#'##"!*..<;:85?9;10875-+/-,( $#" %$$! $)/17;=BA8375983-,/.-$ ""'&%##!!&$44<:?85:8<;10321,+* " !#!!##!!##%/68BBKSWZ^fdimttu{}" "" $$ !##!!##%!+14DGKQUY`bbhlkppuwwxx}!!!!#!!""  % "$""$"$$,26@BFNQUW]_ffhinqsvxxwz~!!#!! " "%% "$$"$$.28@BHPRXY]aegiknqtwxx{~!!!!#!!#!"%" "%""$$&".48@FFNRVZ^_eihimpqtwxwy~!!!!!#!!%#!!%#!!%%""%%"$"(037>@HNRVZ\bdfkkmosuxyz}~#!!#!!#!!#!#%#!#"%% ""&.3;AEFNUW[^^eghikpqquxx{~"!!!!!#!%!%#" " )/3;?EKMRU[a`cdgikoqtwx|""!!#!!##!!%#!!%%!##! "+/5=ACMMUUY^^edfihpqouy|| "$"$$"!#!!#!#%#!##!#+/3;?CLMQSY_aabfijmortx| " """$""!#!!#%#!!##!!!%--3;=CLNTWY\^adfihnnmuy{~  " " """"$""##!!#!!!!+/7>BDLNRUY[__bdghkortx|    $" ""$" "$""$"$#!!!%+03:GHNPUTV]_^`cfgortx  " "" " "$"" "   &*.68=DHLMSRX\\^bcfknqu    "  " %"" ""   &(.78BGJMPU"! $(.28>@HIMN""""" (026>BEGO  "$"" $(024>BFI  (,26BHMQU[^aehmqv{|*.26FLPS[]cfionvv{ $*366@GHRVY[bfilpuy|{ &,48>DJPTW[cdhmntu{~ &.56?GHNVX]aegmpruz| $*58GPRX\_cejnsux{"$(17AAGOPW^`fhmntu{z&*.3=ADKRYV]aegnrux|}ﲯ􀅀𒏔ナ戊󣞞獊렞󒾼򨥣撔𠛙锗þ뛙þ北򛞛þڨﴹ魨߷ۭ湼ƾþþüþӾþ ~{~{~~{~{{~{~{~{~~{{~~~钔Ւ񏍍򗔒홒𞛠ؙ栣룠ү鶴ٯй޵ôȹ˹þþþ  젣˛ÿ̨͞𯲴þ̭鴹βʹͷͼμþƼýſ¾ûºžƾҀûþɞ졣¾þæ¼졢Ž䷳Սÿ栞¾޼½͆}ÿ~}~~¾}{y~ɱ½}~{z}{ž~~}~~y{|}½~~~}x|{yzz}þ}͹ÿ|~~|~}½~||}||{}|Ŀ~}|z{}ľ}||}|z|~zx{z~~}|~y|}~~ͳ||wzw~~{~|ɀǿ}|~|{|}|~~}~|~yxw}xy||Ǿ|~zzy|{|{z|ľ|~xxw}x{|z~}~ǿ|~zxzy|x|{z|~}Ƽ}}~zxw|x{~x~}}~Ž|~}zwzyzz}{z|}}ͨŻ|~zxy|y{|z}}}{þ}~zwzyzz}yz~}}~}~zxy|y{||{}}}Ƚ~zzy|z}yz||}ƽzxy}y{||{~}}|}yzxy|z{{z~|}ƽzzy{y{||{|}~}זǻ|}zzxyz{{z~~|~wzw{y{|{|~~~}}zzyy|{y{|~|ûB|}xzz{|y|}z~|{wzyyx}y{|}~||~~|xxz{{y|{}x~z|yzy|x{zy~}}~~}yvyzx{{|}~}{|zz|{|x}yy~}~}|zwzw}x{||{~}}}ɠz{y|}z{z{z~~~}~}wzxy~y{z{{}~~}|xzyy{z~z{|~||~|yzyyzyzy~}~ˡzxwzy|{|}{|}{z~~Ġzz{zy|z}|z~}}zzw}x{|~{z|}|}~xzy{{|}{}z|}~}}yzyy|{y|}}x}~}ʙzzwzyzz|yy~}}}~}|~zy|z{|z}~}}}~}{z}z{zz{z|~~}{}}|}{|}y||~~~{{|{{|}}x{{|~||y|z|yy~}}}|{y|z{||~}}~𤢟}y|{z|~|{~~}~|{y{~}z{y|z{~|}||~~~{|}{|}~~}א{z{z}~|񢞟x{||}{~}}󦢡|}|{}||~}あ姣}{}zzwywzwxuspnoljhcaڎ~~{yxzyxvtwssqrlmkiha_ጉz{wyyxvttrrqohigfcb~{}zzwywzwxustnqljgccd]ɓ{yxzxxvttrsqrnlmihc_`[񛙛}{yywxvwttqooigeca\Z~~zzvywxvxustnpojiccd]\Z~|zxxvwtrsqrplmihhc`][UŒ~|{yywxvwttstqooiggfa]\XT}{{wywxvwustnpojibcd`]ZXV횔}{yyxwtrsqrrnmkhfc`]]XSN}|zzxxwttstsooiggfa][\XTO||xzxxvwustppojiebdb]ZXVQM|zzywtrssrrnmkhfc`]]XSSOK}{{yywttstrqoiggfa]][XTONG}}y{yyxxuutppojigedb`ZZVTONI朚}{{|zxxussrnmkjfc`]]XUSOOJI~z||zzxuustrqoiggfa`][XTONIGB~~|zyvtnpojigedb`ZZVVONIGD᠛~|}}{yyvttrrnmkjfc`]]ZUSOOIJC<{}}y{yvvsusqoiggfa`][XTONIGB>;ퟝ}}{|wzwwuoqojigbdb[ZZVTMNIGA:9񈅃~~||zzwsussomkjfc`]]ZUTMMILC:8/|~||zwwtvrppiggfa`]YUTONGGD>;1*~~|{}x{xxvprpkie`dd\ZZVTMKIDA<93+֋}}{{xtvttpnnljfc`][ZUTOMILB:6/(#ʘ}}}{{xwuwsqqjhhc_`][UTOKIGDA;1*" ~|yywqsnljfadd\ZXVTOKID?<<3+~||yuwuuqookidd`]\ZSTOMIHB:62+~~|}{xvvtrmkiid``YYUTPKKGDA;4-%ʂ}{}x{xvrromifcec\ZXTQOKGFB:40(򒍉}{{xvvpnnljeca^\XSQOKKHA993+ ɖ~~|yywuplljjeaaZXUQPKIICA;2-(򌊈~||yyupljgdda[[VTOPKDB@<40" Ȃ~||yyxvqqomkfa__]XVQQKIGA990+ ȉ}}}zxxvqmkkhd__[VTPPKIIC<9/1&!"ŋ}xzzxvvqqmiigeb[[WUPNIGB>;4- "́}}y|yurpnkkgb``[YWPNKIF@870.  ͏~~~~|uwupnkiie`^^WUQNJGFB=4/(&!" ~y|yywrrqohhc_\\XUQLGGA?<2*""!"lj}zzxvqqolhcca_\UUQNJLB;81-%  ""}}xvxsqojhhca\\XVQMJHEA;4-( ! "#醄}}zzttrpkiifd][[TQMHG@=40+ "!!ʈ~~{ywpmpmfdbb][VTOMJIB:92.  "## {~~wytrpmkiibc^\WRRMKKEB901&! "#$%}zvvsnljgcc^\YYRRKHD?<5.#" !"#%&Ɔ}zxvqnnlee``\WWRPKKF<984, "## %'ˆ}}}zvvsnlgkha__XXSNIIFD?50(# "#$%!'~~~yttrpkhfd__\ZUQNLFA?=3+#" !#%&'#{{wprmmkffa\\XUSNLJC;:4,# ""#!%(##~yxusnliig``[YTTOLLFD>42)  "##%!"')%}}zssqqlgee`][VTQLKEA>6/#$" !#$%&##)+ŋzzxusqnliee`[YTTQLLID;:20  "## %&(#$%,yytmhca^\YUPKKHD@61)$ ! "#$%!'()%&'~~yttorjhhfa^YYWRPMJD=<5-" !#$&&#)*+''{ywtrojmffbbZXUPPLIF==5-! ! ""#!%'(#%,,.*}}xussniffb_]ZUSPLHDA9/3(" "##%!"'(%%'(.*}}zxusppkidf_ZZUSPNMH@<70!% # !"#$%&"#)*%'()1{{vtoolec`^[VTOLKFA<61( !" ""#$%&(#$%,-)*+-`]ZXSQKKGCA<2*"#$&'#),,'**,-(**..'"TOKIDA:73( #%'(#%,-.*+,00*+./3"OMIIB:8/(&! "#$!%'()%''(%+-01--.1**PIGFB=1*"  "#$%!')*+'**+-.03-.')+#NIHA?83+ "#$&&#%,,.**,-0**../*#$NIF;81.&!" !"%&(#%&'(++,-0*+//**$%JGB=40"#!"##!!'()%'')*,.014-/)**%GB>;2+ "#$&&#)*,')*+-.**-.')+#$'FC870&!" "#%'(#%,,.*+,-0**../)$$'(C<7/%#"!"## %'()%''(%+,-0--/1**$%''>;4*  "#$%!'))+''*+'.034-')*#$:93+! "#$&&#*,,.**,-(**-.')##$'!4/(&!" !"$%&(#%&'(*+,-0*+..3*$$'*"4*"  "#$%!'()%'')*+.01--.1**%%'!3+ "#$&&#)*,'**+-.1+-.')*#$!"(&! !"#%'(#%,,.*+,-0**../"##%*!"&" "!"#$!%'()%''(%+,.0*-//*"$''**" "#$%!')*+'(*+'.034-/)**%!" ! #%&(#%,,.**,-(**-.')+$$'!& "!"#!%(($%&'.*+,00*+../$$%'*!  ""#$!!')*%'()1+-01--/1*#%''*,"  ##$&"#),,(**,..13-&'**$!" " !#!%'#$%,..*+,.0**..'##$$!"&  "## !"()%%'(.++-00++/13$$''"  "#$$!"#)*%'**,..034-1**#%''!!" !#$%'#$%,-)*+,.)*+-/'*+$!"  "## %'(#%%'((+,,00*../1##%'!$&  "#$%!"))%&'()+-.13-./**$%''!" !#$%&#$+,')*+-..14-')**$!  "## %&(#%&&()+,,0)*-./'+#$%! "#$%!'()%''($+,-0*+./33$$'(" "#$&&#)*,')*+'..34-.1**%%'',! #$ %'(#%,,.**,-(**-.')*#$!! #$!!'()%''.++,.0*+../"#$$*!!& #$&"#)*+'(),,.01--/1*#$''*" %'##%,,/**,..1+-%'**$! !'((%%'((+,,00*+./'+#$%!" !"#)%&'()+,-00+./13$$%'!$& '#$%,')*+-..134.1**#%''*!" (#%&'()+,,.)*-./)*+$!! )%''($+,-0*+../1##$'!$  *,,'**+'.014-.1**$%'(!  %,-.**,.(*+-&')*#%! %'(.++,00**..'##$$!" &')*3..01--/**$$%'!$& .)*+-..134.)**#%''*!"()+,,0)*-./)*+$! )*+--0*+../3$$%(!$ *,-.034-.1**$%''! +,.0*+-.')*$%! ,-00*+.//##$$!" .034./**$$''!$& ^E/"libqxt-0.6.2/extras/bitrock/000077500000000000000000000000001215241066400157665ustar00rootroot00000000000000libqxt-0.6.2/extras/bitrock/instructions.txt000066400000000000000000000026631215241066400213020ustar00rootroot00000000000000from BitRock Sales to J-P Nurmi date Thu, Jan 31, 2008 at 12:45 PM subject RE: BitRock InstallBuilder for Qt Hi J-P, Thank you for your interest in BitRock InstallBuilder. We are happy to provide you with a free license. I am attaching the license, "license.xml" to this email. First, you need to download the latest version of InstallBuilder for Qt (Professional edition) from: http://www.bitrock.com/download_installbuilderqt_download.html Then, to register the product, you can either copy the file to the BitRock InstallBuilder installation directory or, from the main application menu, select 'License', then 'Register license' and follow the on-screen instructions. We hope you and your users enjoy BitRock InstallBuilder, and we wish you the best of luck with your projects. We are attaching an "Installers by BitRock" icon. Posting it and/or a link to bitrock.com in your download or project page would be greatly appreciated, although it is not required. We will keep you informed of InstallBuilder's new features and functionality by sending you a monthly newsletter. If for any reason you prefer to not receive this, simply send us an email requesting to be taken off our list. Please do not hesitate to contact us with feature suggestions or any issues you may find. We love to hear from our users and your feedback helps us improve our software. Best Regards, Ericalibqxt-0.6.2/extras/bitrock/license.xml000066400000000000000000000006611215241066400201350ustar00rootroot00000000000000 2008-01-31 1.2 opensource 5 4 Qxt 1 BitRock InstallBuilder for Qt 3b2cf4ed2151e92fe9053be6db3f054d libqxt-0.6.2/extras/coding_style.txt000066400000000000000000000357661215241066400175760ustar00rootroot00000000000000LibQxt Coding Style Guidelines 1. Files 1.1. Every header and source file begins with a header comment 1.2. Comments must be written in C++-format (// ...). Multiline comments may be written in syntax of C (/* ... */). 1.3. Header files 1.3.1. The file name extension of a header file is .h 1.3.2. A single public header file contains one public interface (class or namespace). 1.3.3. Header files contain only declarations. Implementation belongs to source files. - Exception: inline and template functions must be placed within header files because of compiler limitations. 1.3.4. Header files include only necessary header files. - Unnecessary include directives produce unnecessary dependencies between compile units. 1.3.5. Use forward declarations whenever possible. - A forward declaration is enough when a type is referred only as reference or pointer. 1.3.6. Header files do not contain using-clauses. - Using explicit namespace prefixes in header files lowers the risk of name conflicts. 1.3.7. Header files must be protected against multiple inclusion - Multiple inclusion of header files causes a compile error. #ifndef CLASSNAME_H #define CLASSNAME_H ... #endif // CLASSNAME_H 1.3.8. Include directives do not contain references to certain directories. - Using directory hierachies in include directives binds files strictly to certain environment and complicates portability. #include "../../module/header.h" // WRONG 1.4. Source files 1.4.1. The file name extension of a source file is .cpp 1.4.2. Source files include only necessary header files. - Unnecessary include directives produce unnecessary dependencies between compile units. 1.4.3. Source files include first local headers, and then external library headers. - This order assures that header files do not depend on external library headers and leads to easier portability. 1.4.4. Implementation of an interface is in the same order than in the header file. - This makes it easier to find the corresponding implementation. 2. Names 2.1. Comments and symbolic names are in English. 2.2. Symbolic names must not start with an underscore or contain two consecutive underscores. - ISO C++-standard reserves such names for compilers. 2.3. Names of classes, structs, namespaces and typedefs start with "Qxt". class QxtClass; 2.4. Names of variables, functions and member functions start with a lowercase letter. - Exception: constructors and destructors must be named after corresponding class QxtClass variable; void doSomething(); 2.5. Constants are written in uppercase. static const unsigned int BUFFER_LIMIT = 1024; 3. Variables and constants 3.1. Variables should be declared within innermost possible scope. - Variables declared close to where they are used improves code clarity. 3.2. Declare variables by separate clauses. char* p1, p2; // WRONG (p1 is a pointer, p2 is a char) 3.3. Variables must be always initialized. 3.4. Member variables are initialized in initialization list in order of declaration. - The initialization list is the only efficient way to initialize member variables. 3.5. #define directive must not be used for defining constants or functional macros. - In C++, named constants are implemented as const variables and functional macros are replaced with inline functions. 3.6. Constants are defined concentratedly in header files or at the beginning of source files. 3.7. Truth values are expressed as boolean values; true or false. - C uses zero and non-zero as truth values. These work in C++ as well, but are not recommended by ISO C++-standard. 4. Layout and style 4.1. Every programmer has his/her own programming style. The exact style does not matter as long as it is consistent per file. - This is important while applying changes to files which were originally written by somebody else. - Code looks awful and is unreadable if the programming style varies within a file. 4.2. It is troublesome to handle files of more than thousand (1000) lines. 4.3. It is not recommended to write functions of more than hundred (100) lines. 4.4. Pointer and reference characters are recommended to place to type name. - Pointers and references are considered as types. In addition, this leads to better readability: Result* result = 0; void printResult(const Result& result); 4.5. Indentation is done with spaces. - Tabulator characters are not recommended because different editors and viewers show them differently, often even unreadable. 4.6. An indented code block follows every if,else,while,for and do primitive. 4.7. Initial ({) and terminal (}) characters of code blocks must be clearly placed separately from code. The preferred way is to place them on separate lines. 4.8. Every switch clause contains a default branch. 5. Mixing C and C++ 5.1. Do not use exit() or abort(). - These functions stop execution without desctructing objects properly. 5.2. The return value of main() is int. - Defined in ISO C++-standard. 5.3. Do not use goto. - There are better control structures. Using goto leads to unreadable spaghetti code. 5.4. Use output streams instead of C IO functions. - printf() has to type checks. 5.5. Do not use malloc(), realloc() or free(). Use new and delete operators instead. - Old memory allocation routines know nothing about constructors and destructors. 5.6. Use extern "C" while including headers of C libraries. extern "C" { #include } 6. Type conversions 6.1. Do not use C-style cast. Use static_cast, dynamic_cast, reinterpret_cast and qobject_cast. - New type cast operators make sanity checks. 6.2. Avoid const_cast whenever possible. - Constant is an attribute bound at design time. There should be no need to remove constness. 7. Functions and member functions 7.1. Function parameters must be named. Function parameter names must match in both, function declaration and function definition. - Self-documentary parameter names are as important as verbose docs. 7.2. Object parameters must always be (const) references where possible. - Avoid unnecessary copying. - Implicit sharing is no excuse. Avoid unnecessary detaching. 7.3. Do not use a variable number of function parameters (ellipsis notation). - Complier does no checks to passed parameters. 7.4. Possible default values of parameters must be placed in function declaration only. - Possible default values must be clearly seen from header files. 7.5. Do not return a reference or a pointer to local data. - Local data of a function is no more existent after the function returns. 7.6. A member function must be a const function whenever possible. 8. Classes and objects 8.1. Objects are implemented as classes and records are implemented as structs. - A clear separation between structural data and objects. 8.2. A struct may have a constructor and (virtual) destructor but no member functions. - Records collect related data together. The only acceptable functionality is initialization and uninitialization. 8.3. Access levels are declared in order public, protected and private. - End-users are interested of public interface, which makes it natural to declare as first. 8.4. The visibility of class member variables is always private. - Exception: It is acceptable to use public variables in private implementation classes. 8.5. Class declaration does not contain implementation. Inline and template functions are implemented separately in the header file after the declaration. - End-users consider it easier to read clear declarations not cluttered with implementation details. 8.6. Avoid friend functions and classes. - Friendship breaks encapsulation. - Exception: A tight group of classes belonging together. 8.7. Retain semantics of overloaded operators. - For example, operator + does always an operation correspondent to addition. 9. Scope 9.1. Memory management 9.1.1. Ownership of dynamically allocated memory belongs to its allocator. Otherwise it must be clearly documented. 9.1.2. It is acceptable to use operator delete only to deallocate memory that was allocated by operator new. - Same thing with delete[] and new[] - Defined in ISO C++-standard. 9.1.3. It is acceptable to use operator delete[] only to deallocate memory that was allocated by operator new[]. 9.1.4. Nullify pointers after deletion. - Dereferencing floating pointers to already deleted memory tend to produce confusing error messages. 9.2. Constructing and destructing objects 9.2.1. It is preferred to provide at least one constructor for every class. - Default constructors provided by compilers are rarely usable. 9.2.2. You must not call virtual functions in class constructors or destructors. - Dynamic binding does not work in expected way when the object is in a half-baked state. 9.2.3. Do not use static (or global) variables in class constructors or destructors. - Initialization order of static variables is undefined. The object could itself be static (or global) whereas the static variable it depends on might not be initialized yet. Correspondingly, in destructor the referenced static variable might already have been destructed. 9.2.4. Constructor with one parameter must be marked as explicit. - Exception: Do not mark copy constructors as explicit. - This prevents compiler from using the constructor for implicit type conversion: QWidget widget = new QWidget(); // produces an error only because QWidget constructor is explicit 9.2.5. Classes with virtual functions must have public virtual destructors. 9.2.6. The destructor is responsible for freeing all resources allocated by the class. 9.3. Copying objects 9.3.1. It is preferred to provide a copy constructor for every class. - Default copy constructors provided by compilers might be non-suitable. 9.3.2. Inappropriate copying is prevented by declaring a private copy constructor. private: Q_DISABLE_COPY(ClassName) 9.3.3. An inherited class must always call base class copy constructor in the initializer list. - Ensures that the base class gets copied properly (what the default constructor might not always do). 9.4. Assigning objects 9.4.1. It is preferred to provide an assigment operator for every class. - Default assignment operator provided by compilers might be non-suitable. 9.4.2. Inappropriate assignment is prevented by declaring a private assignment operator. 9.4.3. An inherited class must always call base class assignment operator. - Note: Compilers do not do this automatically. 9.4.4. Assignment operators should skip assignment to self. - An unnecessary operation. Object& object::operator=(const Object& other) { if (this != &other) { ... } return *this; } 9.4.5. The return value of an assignment operator is *this. - Makes for example chained assignment possible. a=b=c; 10. Inheritance 10.1. Use only public inheritance. - Exception: Inheritance from Ui class in the multiple inheritance approach. 10.2. Inheritance is a static "is-a" relationship. Implement "has-a" relationship with member variables and type independent code with templates. 10.3. TODO: Do not misuse multiple inheritance. :) 10.4. Member functions of an interface class are pure virtual. - The purpose of an interface is to declare operations. Pure virtuality enforces declared operations to be implemented in subclasses. 10.5. An inherited class must always call base class constructor in the initializer list. - Ensures that the base class gets constructed properly (what the default constructor might not always do). 10.6. Inherited non-virtual member function is not recommended to be re-declared eg. shadowed in subclasses. 10.7. Default parameter values of inherited virtual member functions must not be redefined. 11. Templates and containers 11.1. Parameter type requirements of template functions must be clearly documented. - Error messages of template functions tend to be confusing. 11.2. Use type definitions to give sensible names to (at least complex) template containers. typedef QMap PhoneBook; 11.3. Make sure objets stored in template containers have suitable copy and assign operators. - Template containers handle stored objects by copying and assigning them. Resulting objects of copy and assign must be identical to original objects. 11.4. Use QtAlgorithms and/or STL algorithms instead of hand-made algorithms where possible. 11.5. The preferred way to iterate through a container is to use iterators. 11.6. Incrementing and decrementing an iterator is done with prefix operator (preincrement and predecrement). - Postincrement is less efficient, because it will have to return a copy of the old value. 11.7. Make sure not to use invalid iterators. - Non-mutable iterators get invalidated when a container is altered. 12. Exceptions 12.1. Never use exceptions in Qt code. - Qt isn't required to be compiled with exception support, and just by enabling exception support you invoke a performance hit -- even if you never use it -- so you can't rely on it being there. References: - http://www.cs.tut.fi/~oliot/kirja/tyyliopas/ - http://doc.trolltech.com/qq/qq13-apis.html Suggestions: [19:54:43] 13:54:43> i would prefer "Layout and style" beeing more strict [19:54:43] 13:55:04> "The exact style does not matter as long as it is consistent per file." thats a bad idea [19:54:43] 13:55:19> it should be consistent all over the entire prohect [19:54:43] 13:55:34> i think the GNU style or whatever it is called, we are currently using is all right [19:54:43] 13:55:37> with 4 spaces [19:54:43] 13:56:20> actually just removing that sentence is all right [19:54:43] 17:59:25> Suggestion for coding style: [19:54:43] 17:59:42> Use an enum in a namespace for related integer constants instead of const int or #define [19:54:43] 17:59:46> This is the Qt style. [19:54:43] 17:59:55> Er, in a namespace or class. libqxt-0.6.2/extras/nsis/000077500000000000000000000000001215241066400153055ustar00rootroot00000000000000libqxt-0.6.2/extras/nsis/libqxt.ini000066400000000000000000000012111215241066400173040ustar00rootroot00000000000000[Settings] NumFields=8 [Field 1] Type=GroupBox Left=0 Right=-1 Top=0 Bottom=-5 Text=Installation options [Field 2] Type=checkbox Text=Install release version Left=10 Right=-10 Top=17 Bottom=25 State=1 Flags=GROUP|NOTIFY [Field 3] Type=checkbox Text=Install debug version Left=10 Right=-10 Top=30 Bottom=38 State=0 Flags=NOTIFY [Field 4] Type=Label Left=10 Right=-10 Top=56 Bottom=68 Text=Path to qmake: [Field 5] Type=FileRequest State=C:\Qt\4.3.3\bin\qmake.exe Left=10 Right=-10 Top=73 Bottom=85 Filter=Executables|*.exe|All files|*.* Flags=GROUP|FILE_MUST_EXIST|FILE_EXPLORER|FILE_HIDEREADONLY libqxt-0.6.2/extras/nsis/libqxt.nsi000066400000000000000000000201231215241066400173210ustar00rootroot00000000000000;-------------------------------- ;LibQxt Installation ;-------------------------------- ;Includes !include "MUI.nsh" !include "Sections.nsh" !include "InstallOptions.nsh" ;-------------------------------- ;General !define PRODUCT_NAME "LibQxt" !define PRODUCT_VERSION "0.3.0" !define PROJECT_NAME "libqxt" ;Name and file Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" OutFile "${PROJECT_NAME}-${PRODUCT_VERSION}.exe" ;Default installation folder InstallDir "C:\${PROJECT_NAME}-${PRODUCT_VERSION}" ;Get installation folder from registry if available InstallDirRegKey HKCU "Software\$(^Name)" "" ;Vista redirects $SMPROGRAMS to all users without this RequestExecutionLevel admin ;Show installation details ShowInstDetails show ;-------------------------------- ;Interface Settings !define MUI_ABORTWARNING ;-------------------------------- ;Variables Var MUI_TEMP Var STARTMENU_FOLDER Var RELEASE_MODE Var DEBUG_MODE Var QMAKE_PATH Var MKSPEC_FOLDER ;-------------------------------- ;Functions Function EnableDisableNextButton ;Get release and debug check states ReserveFile "libqxt.ini" !insertmacro MUI_INSTALLOPTIONS_READ $0 "libqxt.ini" "Field 2" "HWND" !insertmacro MUI_INSTALLOPTIONS_READ $1 "libqxt.ini" "Field 3" "HWND" SendMessage $0 ${BM_GETCHECK} 0 0 $RELEASE_MODE SendMessage $1 ${BM_GETCHECK} 0 0 $DEBUG_MODE IntOp $0 $RELEASE_MODE + $DEBUG_MODE ;At least either one must be checked GetDlgItem $R0 $HWNDPARENT 1 ${If} $0 == "0" EnableWindow $R0 0 ; disable next button ${Else} EnableWindow $R0 1 ; enable next button ${EndIf} FunctionEnd Function CreateOptionsPage ReserveFile "libqxt.ini" !insertmacro MUI_INSTALLOPTIONS_EXTRACT "libqxt.ini" !insertmacro MUI_INSTALLOPTIONS_DISPLAY "libqxt.ini" FunctionEnd Function LeaveOptionsPage !insertmacro MUI_INSTALLOPTIONS_READ $R0 "libqxt.ini" "Settings" "State" ${if} $R0 == 0 !insertmacro MUI_INSTALLOPTIONS_WRITE "libqxt.ini" "Field 2" "State" $RELEASE_MODE !insertmacro MUI_INSTALLOPTIONS_WRITE "libqxt.ini" "Field 3" "State" $DEBUG_MODE ${else} Call EnableDisableNextButton Abort ${endif} FunctionEnd ;-------------------------------- ;Pages !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "..\..\cpl1.0.txt" !insertmacro MUI_PAGE_COMPONENTS Page custom CreateOptionsPage LeaveOptionsPage !insertmacro MUI_PAGE_DIRECTORY ;Start Menu Folder Page Configuration !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU" !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\$(^Name)" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES ;-------------------------------- ;Languages !insertmacro MUI_LANGUAGE "English" ;-------------------------------- ;Installer Sections Section Docs SecDocs SetOutPath "$INSTDIR\doc\libqxt" File /r /x .svn "..\..\doc\html\*" SectionEnd Section QxtBerkeley SecQxtBerkeley SetOutPath "$INSTDIR\lib" File "..\..\lib\QxtBerkeley.dll" File "..\..\lib\QxtBerkeley.lib" SetOutPath "$INSTDIR\include\Qxt\QxtBerkeley" File /r /x .svn "..\..\include\QxtBerkeley\*" File /r /x .svn "..\..\src\berkeley\*.h" SectionEnd Section QxtCore SecQxtCore SectionIn RO ; Mandatory section (appears disabled) SetOutPath "$INSTDIR\lib" File "..\..\lib\QxtCore.dll" File "..\..\lib\QxtCore.lib" SetOutPath "$INSTDIR\include\Qxt\QxtCore" File /r /x .svn "..\..\include\QxtCore\*" File /r /x .svn "..\..\src\core\*.h" ;Store installation folder WriteRegStr HKCU "Software\$(^Name)" "" $INSTDIR ;Create uninstaller WriteUninstaller "$INSTDIR\uninstall.exe" ;Create shortcuts !insertmacro MUI_STARTMENU_WRITE_BEGIN Application CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\uninstall.lnk" "$INSTDIR\uninstall.exe" !insertmacro MUI_STARTMENU_WRITE_END SectionEnd Section QxtCrypto SecQxtCrypto SetOutPath "$INSTDIR\lib" File "..\..\lib\QxtCrypto.dll" File "..\..\lib\QxtCrypto.lib" SetOutPath "$INSTDIR\include\Qxt\QxtCrypto" File /r /x .svn "..\..\include\QxtCrypto\*" File /r /x .svn /x thirdparty "..\..\src\crypto\*.h" SectionEnd Section QxtGui SecQxtGui SetOutPath "$INSTDIR\lib" File "..\..\lib\QxtGui.dll" File "..\..\lib\QxtGui.lib" SetOutPath "$INSTDIR\include\Qxt\QxtGui" File /r /x .svn "..\..\include\QxtGui\*" File /r /x .svn "..\..\src\gui\*.h" SectionEnd Section QxtDesignerPlugins SecDesignerPlugins SectionEnd Section QxtNetwork SecQxtNetwork SetOutPath "$INSTDIR\lib" File "..\..\lib\QxtNetwork.dll" File "..\..\lib\QxtNetwork.lib" SetOutPath "$INSTDIR\include\Qxt\QxtNetwork" File /r /x .svn "..\..\include\QxtNetwork\*" File /r /x .svn "..\..\src\network\*.h" SectionEnd Section QxtSql SecQxtSql SetOutPath "$INSTDIR\lib" File "..\..\lib\QxtSql.dll" File "..\..\lib\QxtSql.lib" SetOutPath "$INSTDIR\include\Qxt\QxtSql" File /r /x .svn "..\..\include\QxtSql\*" File /r /x .svn "..\..\src\sql\*.h" SectionEnd Section QxtWeb SecQxtWeb SetOutPath "$INSTDIR\lib" File "..\..\lib\QxtWeb.dll" File "..\..\lib\QxtWeb.lib" SetOutPath "$INSTDIR\include\Qxt\QxtWeb" File /r /x .svn "..\..\include\QxtWeb\*" File /r /x .svn "..\..\src\web\*.h" SectionEnd ;-------------------------------- ;Descriptions ;Language strings LangString DESC_SecDocs ${LANG_ENGLISH} "The Qxt Reference Documentation." LangString DESC_SecQxtBerkeley ${LANG_ENGLISH} "The QxtBerkeley module provides a persistent storage." LangString DESC_SecQxtCore ${LANG_ENGLISH} "The QxtCore module extends QtCore and contains core non-GUI functionality." LangString DESC_SecQxtCrypto ${LANG_ENGLISH} "The QxtCrypto module provides tools for encryption and hashing." LangString DESC_SecQxtGui ${LANG_ENGLISH} "The QxtGui module extends QtGui." LangString DESC_SecQxtDesignerPlugins ${LANG_ENGLISH} "The QxtDesignerPlugins module provides designer plugins for QxtGui widgets." LangString DESC_SecQxtNetwork ${LANG_ENGLISH} "The QxtNetwork module extends QtNetwork with RPC functionality." LangString DESC_SecQxtSql ${LANG_ENGLISH} "The QxtSql module extends QtSql with serializable queries." LangString DESC_SecQxtWeb ${LANG_ENGLISH} "The QxtWeb module provides Qt like Web Developement tools." ;Assign language strings to sections !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${SecDocs} $(DESC_SecDocs) !insertmacro MUI_DESCRIPTION_TEXT ${SecQxtBerkeley} $(DESC_SecQxtBerkeley) !insertmacro MUI_DESCRIPTION_TEXT ${SecQxtCore} $(DESC_SecQxtCore) !insertmacro MUI_DESCRIPTION_TEXT ${SecQxtCrypto} $(DESC_SecQxtCrypto) !insertmacro MUI_DESCRIPTION_TEXT ${SecQxtGui} $(DESC_SecQxtGui) !insertmacro MUI_DESCRIPTION_TEXT ${SecDesignerPlugins} $(DESC_SecQxtDesignerPlugins) !insertmacro MUI_DESCRIPTION_TEXT ${SecQxtNetwork} $(DESC_SecQxtNetwork) !insertmacro MUI_DESCRIPTION_TEXT ${SecQxtSql} $(DESC_SecQxtSql) !insertmacro MUI_DESCRIPTION_TEXT ${SecQxtWeb} $(DESC_SecQxtWeb) !insertmacro MUI_FUNCTION_DESCRIPTION_END ;-------------------------------- ;Uninstaller Section Section "Uninstall" ;ADD YOUR OWN FILES HERE... Delete "$INSTDIR\uninstall.exe" RMDir /r "$INSTDIR" !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP Delete "$SMPROGRAMS\$MUI_TEMP\uninstall.lnk" ;Delete empty start menu parent diretories StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" startMenuDeleteLoop: ClearErrors RMDir $MUI_TEMP GetFullPathName $MUI_TEMP "$MUI_TEMP\.." IfErrors startMenuDeleteLoopDone StrCmp $MUI_TEMP $SMPROGRAMS startMenuDeleteLoopDone startMenuDeleteLoop startMenuDeleteLoopDone: DeleteRegKey /ifempty HKCU "Software\$(^Name)" SectionEnd libqxt-0.6.2/extras/syntax_highlighting/000077500000000000000000000000001215241066400204045ustar00rootroot00000000000000libqxt-0.6.2/extras/syntax_highlighting/kate/000077500000000000000000000000001215241066400213305ustar00rootroot00000000000000libqxt-0.6.2/extras/syntax_highlighting/kate/cpp.xml000066400000000000000000000303231215241066400226350ustar00rootroot00000000000000 asm break case catch class const_cast continue default delete do dynamic_cast else enum explicit export extern false friend for goto if inline namespace new operator private protected public qobject_cast reinterpret_cast return sizeof static_cast struct switch template this throw true try typedef typeid type_info typename union using virtual while and and_eq bad_cast bad_typeid bitand bitor compl not not_eq or or_eq xor xor_eq except finally xalloc K_DCOP SLOT SIGNAL Q_CLASSINFO Q_ENUMS Q_EXPORT Q_OBJECT Q_OVERRIDE Q_PROPERTY Q_SETS Q_SIGNALS Q_SLOTS Q_FOREACH Q_DECLARE_FLAGS Q_INIT_RESOURCE Q_CLEANUP_RESOURCE Q_GLOBAL_STATIC Q_GLOBAL_STATIC_WITH_ARGS Q_DECLARE_INTERFACE Q_DECLARE_TYPEINFO Q_DECLARE_SHARED Q_DECLARE_FLAGS Q_DECLARE_OPERATORS_FOR_FLAGS Q_FOREVER Q_DECLARE_PRIVATE Q_DECLARE_PUBLIC Q_D Q_Q Q_DISABLE_COPY Q_INTERFACES Q_FLAGS Q_SCRIPTABLE Q_INVOKABLE Q_GADGET Q_ARG Q_RETURN_ARG Q_ASSERT Q_ASSERT_X TRUE FALSE connect disconnect emit signals slots foreach forever SKIP QXT_INIT_PRIVATE QXT_DECLARE_PUBLIC QXT_DECLARE_PRIVATE BALL QXT_DROP QXT_DROP_OK QXT_DROP_F QXT_DROP_SCOPE QXT_DROP_S Qxt auto bool char const double float int long mutable register short signed static unsigned void volatile uchar uint int8_t int16_t int32_t int64_t uint8_t uint16_t uint32_t uint64_t wchar_t libqxt-0.6.2/features/000077500000000000000000000000001215241066400146415ustar00rootroot00000000000000libqxt-0.6.2/features/FindQxt.cmake000066400000000000000000000123051215241066400172210ustar00rootroot00000000000000############# ## basic FindQxt.cmake ## This is an *EXTREMELY BASIC* cmake find/config file for ## those times you have a cmake project and wish to use ## libQxt. ## ## It should be noted that at the time of writing, that ## I (mschnee) have an extremely limited understanding of the ## way Find*.cmake files work, but I have attempted to ## emulate what FindQt4.cmake and a few others do. ## ## To enable a specific component, set your QXT_USE_${modname}: ## SET(QXT_USE_QXTCORE TRUE) ## SET(QXT_USE_QXTGUI FALSE) ## Currently available components: ## QxtCore, QxtGui, QxtNetwork, QxtWeb, QxtSql ## Auto-including directories are enabled with INCLUDE_DIRECTORIES(), but ## can be accessed if necessary via ${QXT_INCLUDE_DIRS} ## ## To add the libraries to your build, TARGET_LINK_LIBRARIES(), such as... ## TARGET_LINK_LIBRARIES(YourTargetNameHere ${QXT_LIBRARIES}) ## ...or.. ## TARGET_LINK_LIBRARIES(YourTargetNameHere ${QT_LIBRARIES} ${QXT_LIBRARIES}) ################### TODO: ## The purpose of this cmake file is to find what components ## exist, regardless of how libQxt was build or configured, thus ## it should search/find all possible options. As I am not aware ## that any module requires anything special to be used, adding all ## modules to ${QXT_MODULES} below should be sufficient. ## Eventually, there should be version numbers, but ## I am still too unfamiliar with cmake to determine how to do ## version checks and comparisons. ## At the moment, this cmake returns a failure if you ## try to use a component that doesn't exist. I don't know how to ## set up warnings. ## It would be nice having a FindQxt.cmake and a UseQxt.cmake ## file like done for Qt - one to check for everything in advance ############## ###### setup SET(QXT_MODULES QxtGui QxtWeb QxtZeroConf QxtNetwork QxtSql QxtBerkeley QxtCore) SET(QXT_FOUND_MODULES) FOREACH(mod ${QXT_MODULES}) STRING(TOUPPER ${mod} U_MOD) SET(QXT_${U_MOD}_INCLUDE_DIR NOTFOUND) SET(QXT_${U_MOD}_LIB_DEBUG NOTFOUND) SET(QXT_${U_MOD}_LIB_RELEASE NOTFOUND) SET(QXT_FOUND_${U_MOD} FALSE) ENDFOREACH(mod) SET(QXT_QXTGUI_DEPENDSON QxtCore) SET(QXT_QXTWEB_DEPENDSON QxtCore QxtNetwork) SET(QXT_QXTZEROCONF_DEPENDSON QxtCore QxtNetwork) SET(QXT_QXTNETWORK_DEPENDSON QxtCore) SET(QXT_QXTQSQL_DEPENDSON QxtCore) SET(QXT_QXTBERKELEY_DEPENDSON QxtCore) FOREACH(mod ${QXT_MODULES}) STRING(TOUPPER ${mod} U_MOD) FIND_PATH(QXT_${U_MOD}_INCLUDE_DIR ${mod} PATH_SUFFIXES ${mod} include/${mod} Qxt/include/${mod} include/Qxt/${mod} PATHS ~/Library/Frameworks/ /Library/Frameworks/ /sw/ /usr/local/ /usr /opt/local/ /opt/csw /opt "C:\\" "C:\\Program Files\\" "C:\\Program Files(x86)\\" NO_DEFAULT_PATH ) FIND_LIBRARY(QXT_${U_MOD}_LIB_RELEASE NAME ${mod} PATH_SUFFIXES Qxt/lib64 Qxt/lib lib64 lib PATHS /sw /usr/local /usr /opt/local /opt/csw /opt "C:\\" "C:\\Program Files" "C:\\Program Files(x86)" NO_DEFAULT_PATH ) FIND_LIBRARY(QXT_${U_MOD}_LIB_DEBUG NAME ${mod}d PATH_SUFFIXES Qxt/lib64 Qxt/lib lib64 lib PATHS /sw /usr/local /usr /opt/local /opt/csw /opt "C:\\" "C:\\Program Files" "C:\\Program Files(x86)" NO_DEFAULT_PATH ) IF (QXT_${U_MOD}_LIB_RELEASE) SET(QXT_FOUND_MODULES "${QXT_FOUND_MODULES} ${mod}") ENDIF (QXT_${U_MOD}_LIB_RELEASE) IF (QXT_${U_MOD}_LIB_DEBUG) SET(QXT_FOUND_MODULES "${QXT_FOUND_MODULES} ${mod}") ENDIF (QXT_${U_MOD}_LIB_DEBUG) ENDFOREACH(mod) FOREACH(mod ${QXT_MODULES}) STRING(TOUPPER ${mod} U_MOD) IF(QXT_${U_MOD}_INCLUDE_DIR AND QXT_${U_MOD}_LIB_RELEASE) SET(QXT_FOUND_${U_MOD} TRUE) ENDIF(QXT_${U_MOD}_INCLUDE_DIR AND QXT_${U_MOD}_LIB_RELEASE) ENDFOREACH(mod) ##### find and include # To use a Qxt Library.... # SET(QXT_FIND_COMPONENTS QxtCore, QxtGui) # ...and this will do the rest IF( QXT_FIND_COMPONENTS ) FOREACH( component ${QXT_FIND_COMPONENTS} ) STRING( TOUPPER ${component} _COMPONENT ) SET(QXT_USE_${_COMPONENT}_COMPONENT TRUE) ENDFOREACH( component ) ENDIF( QXT_FIND_COMPONENTS ) SET(QXT_LIBRARIES "") SET(QXT_INCLUDE_DIRS "") # like FindQt4.cmake, in order of dependence FOREACH( module ${QXT_MODULES} ) STRING(TOUPPER ${module} U_MOD) IF(QXT_USE_${U_MOD} OR QXT_DEPENDS_${U_MOD}) IF(QXT_FOUND_${U_MOD}) STRING(REPLACE "QXT" "" qxt_module_def "${U_MOD}") ADD_DEFINITIONS(-DQXT_${qxt_module_def}_LIB) SET(QXT_INCLUDE_DIRS ${QXT_INCLUDE_DIRS} ${QXT_${U_MOD}_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${QXT_${U_MOD}_INCLUDE_DIR}) SET(QXT_LIBRARIES ${QXT_LIBRARIES} ${QXT_${U_MOD}_LIB_RELEASE}) ELSE(QXT_FOUND_${U_MOD}) MESSAGE("Could not find Qxt Module ${module}") RETURN() ENDIF(QXT_FOUND_${U_MOD}) FOREACH(dep QXT_${U_MOD}_DEPENDSON) SET(QXT_DEPENDS_${dep} TRUE) ENDFOREACH(dep) ENDIF(QXT_USE_${U_MOD} OR QXT_DEPENDS_${U_MOD}) ENDFOREACH(module) MESSAGE(STATUS "Found Qxt Libraries:${QXT_FOUND_MODULES}") libqxt-0.6.2/features/qxt.prf000066400000000000000000000055031215241066400161710ustar00rootroot00000000000000include(qxtvars.prf) DEPENDPATH += $${QXT_INSTALL_HEADERS} INCLUDEPATH += $${QXT_INSTALL_HEADERS} QMAKE_RPATHDIR += $${QXT_INSTALL_LIBS} macx:LIBS += -F$${QXT_INSTALL_LIBS} LIBS += -L$${QXT_INSTALL_LIBS} contains(QXT, berkeley) { contains(QXT_MODULES, berkeley):DEFINES += QXT_BERKELEY_LIB else:warning(Qxt was built without QxtBerkeley) DEPENDPATH += $${QXT_INSTALL_HEADERS}/QxtBerkeley INCLUDEPATH += $${QXT_INSTALL_HEADERS}/QxtBerkeley macx:INCLUDEPATH += $${QXT_INSTALL_LIBS}/QxtBerkeley.framework/HEADERS/ qtAddLibrary(QxtBerkeley) QXT += core } contains(QXT, web) { contains(QXT_MODULES, web):DEFINES += QXT_WEB_LIB else:warning(Qxt was built without QxtWeb) DEPENDPATH += $${QXT_INSTALL_HEADERS}/QxtWeb INCLUDEPATH += $${QXT_INSTALL_HEADERS}/QxtWeb macx:INCLUDEPATH += $${QXT_INSTALL_LIBS}/QxtWeb.framework/HEADERS/ qtAddLibrary(QxtWeb) QXT += core network QT += network } contains(QXT, gui) { contains(QXT_MODULES, gui):DEFINES += QXT_GUI_LIB else:warning(Qxt was built without QxtGui) DEPENDPATH += $${QXT_INSTALL_HEADERS}/QxtGui INCLUDEPATH += $${QXT_INSTALL_HEADERS}/QxtGui macx:INCLUDEPATH += $${QXT_INSTALL_LIBS}/QxtGui.framework/HEADERS/ qtAddLibrary(QxtGui) QXT += core QT += gui } contains(QXT, zeroconf) { contains(QXT_MODULES, zeroconf):DEFINES += QXT_ZEROCONF_LIB else:warning(Qxt was built without QxtZeroConf) DEPENDPATH += $${QXT_INSTALL_HEADERS}/QxtZeroconf INCLUDEPATH += $${QXT_INSTALL_HEADERS}/QxtZeroconf macx:INCLUDEPATH += $${QXT_INSTALL_LIBS}/QxtZeroconf.framework/HEADERS/ qtAddLibrary(QxtZeroconf) QXT += core network QT += network } contains(QXT, network) { contains(QXT_MODULES, network):DEFINES += QXT_NETWORK_LIB else:warning(Qxt was built without QxtNetwork) DEPENDPATH += $${QXT_INSTALL_HEADERS}/QxtNetwork INCLUDEPATH += $${QXT_INSTALL_HEADERS}/QxtNetwork macx:INCLUDEPATH += $${QXT_INSTALL_LIBS}/QxtNetwork.framework/HEADERS/ qtAddLibrary(QxtNetwork) QXT += core QT += network } contains(QXT, sql) { contains(QXT_MODULES, sql):DEFINES += QXT_SQL_LIB else:warning(Qxt was built without QxtSql) DEPENDPATH += $${QXT_INSTALL_HEADERS}/QxtSql INCLUDEPATH += $${QXT_INSTALL_HEADERS}/QxtSql macx:INCLUDEPATH += $${QXT_INSTALL_LIBS}/QxtSql.framework/HEADERS/ qtAddLibrary(QxtSql) QXT += core QT += sql } contains(QXT, core) { contains(QXT_MODULES, core):DEFINES += QXT_CORE_LIB else:warning(Qxt was built without QxtCore) DEPENDPATH += $${QXT_INSTALL_HEADERS}/QxtCore INCLUDEPATH += $${QXT_INSTALL_HEADERS}/QxtCore macx:INCLUDEPATH += $${QXT_INSTALL_LIBS}/QxtCore.framework/HEADERS/ qtAddLibrary(QxtCore) } libqxt-0.6.2/include/000077500000000000000000000000001215241066400144465ustar00rootroot00000000000000libqxt-0.6.2/include/QxtBerkeley/000077500000000000000000000000001215241066400167055ustar00rootroot00000000000000libqxt-0.6.2/include/QxtBerkeley/QxtBdb000066400000000000000000000000241215241066400200100ustar00rootroot00000000000000#include "qxtbdb.h" libqxt-0.6.2/include/QxtBerkeley/QxtBdbHash000066400000000000000000000000311215241066400206120ustar00rootroot00000000000000#include "qxtbdbhash.h" libqxt-0.6.2/include/QxtBerkeley/QxtBdbHashIterator000066400000000000000000000000311215241066400223240ustar00rootroot00000000000000#include "qxtbdbhash.h" libqxt-0.6.2/include/QxtBerkeley/QxtBdbTree000066400000000000000000000000311215241066400206260ustar00rootroot00000000000000#include "qxtbdbtree.h" libqxt-0.6.2/include/QxtBerkeley/QxtBdbTreeIterator000066400000000000000000000000311215241066400223400ustar00rootroot00000000000000#include "qxtbdbtree.h" libqxt-0.6.2/include/QxtBerkeley/QxtBerkeley000066400000000000000000000000321215241066400210620ustar00rootroot00000000000000#include "qxtberkeley.h" libqxt-0.6.2/include/QxtCore/000077500000000000000000000000001215241066400160335ustar00rootroot00000000000000libqxt-0.6.2/include/QxtCore/Qxt000066400000000000000000000000321215241066400165250ustar00rootroot00000000000000#include "qxtnamespace.h" libqxt-0.6.2/include/QxtCore/QxtAbstractConnectionManager000066400000000000000000000000521215241066400235260ustar00rootroot00000000000000#include "qxtabstractconnectionmanager.h" libqxt-0.6.2/include/QxtCore/QxtAbstractFileLoggerEngine000066400000000000000000000000511215241066400233000ustar00rootroot00000000000000#include "qxtabstractfileloggerengine.h" libqxt-0.6.2/include/QxtCore/QxtAbstractIOLoggerEngine000066400000000000000000000000461215241066400227340ustar00rootroot00000000000000#include "qxtabstractiologgerengine.h"libqxt-0.6.2/include/QxtCore/QxtAbstractSignalSerializer000066400000000000000000000000511215241066400234020ustar00rootroot00000000000000#include "qxtabstractsignalserializer.h" libqxt-0.6.2/include/QxtCore/QxtAlgorithms000066400000000000000000000000331215241066400205600ustar00rootroot00000000000000#include "qxtalgorithms.h" libqxt-0.6.2/include/QxtCore/QxtBasicFileLoggerEngine000066400000000000000000000000461215241066400225620ustar00rootroot00000000000000#include "qxtbasicfileloggerengine.h" libqxt-0.6.2/include/QxtCore/QxtBasicSTDLoggerEngine000066400000000000000000000000441215241066400223330ustar00rootroot00000000000000#include "qxtbasicstdloggerengine.h"libqxt-0.6.2/include/QxtCore/QxtBoundCFunction000066400000000000000000000000371215241066400213330ustar00rootroot00000000000000#include "qxtboundcfunction.h" libqxt-0.6.2/include/QxtCore/QxtBoundFunction000066400000000000000000000000361215241066400212270ustar00rootroot00000000000000#include "qxtboundfunction.h" libqxt-0.6.2/include/QxtCore/QxtBoundFunctionBase000066400000000000000000000000421215241066400220170ustar00rootroot00000000000000#include "qxtboundfunctionbase.h" libqxt-0.6.2/include/QxtCore/QxtCommandOptions000066400000000000000000000000371215241066400214050ustar00rootroot00000000000000#include "qxtcommandoptions.h" libqxt-0.6.2/include/QxtCore/QxtCore000066400000000000000000000000251215241066400173400ustar00rootroot00000000000000#include "qxtcore.h" libqxt-0.6.2/include/QxtCore/QxtCsvModel000066400000000000000000000000321215241066400201620ustar00rootroot00000000000000#include "qxtcsvmodel.h" libqxt-0.6.2/include/QxtCore/QxtDaemon000066400000000000000000000000301215241066400176470ustar00rootroot00000000000000#include "qxtdaemon.h" libqxt-0.6.2/include/QxtCore/QxtDataStreamSignalSerializer000066400000000000000000000000531215241066400236660ustar00rootroot00000000000000#include "qxtdatastreamsignalserializer.h" libqxt-0.6.2/include/QxtCore/QxtDeplex000066400000000000000000000000301215241066400176650ustar00rootroot00000000000000#include "qxtdeplex.h" libqxt-0.6.2/include/QxtCore/QxtError000066400000000000000000000000271215241066400175430ustar00rootroot00000000000000#include "qxterror.h" libqxt-0.6.2/include/QxtCore/QxtFifo000066400000000000000000000000261215241066400173340ustar00rootroot00000000000000#include "qxtfifo.h" libqxt-0.6.2/include/QxtCore/QxtFileLock000066400000000000000000000000321215241066400201360ustar00rootroot00000000000000#include "qxtfilelock.h" libqxt-0.6.2/include/QxtCore/QxtFuture000066400000000000000000000000311215241066400177170ustar00rootroot00000000000000#include "qxtslotjob.h" libqxt-0.6.2/include/QxtCore/QxtGenericFunctionPointer000066400000000000000000000000331215241066400230720ustar00rootroot00000000000000#include "qxtmetaobject.h" libqxt-0.6.2/include/QxtCore/QxtHyperMacros000066400000000000000000000000351215241066400207050ustar00rootroot00000000000000#include "qxthypermacros.h" libqxt-0.6.2/include/QxtCore/QxtJSON000066400000000000000000000000261215241066400172220ustar00rootroot00000000000000#include "qxtjson.h" libqxt-0.6.2/include/QxtCore/QxtJob000066400000000000000000000000251215241066400171620ustar00rootroot00000000000000#include "qxtjob.h" libqxt-0.6.2/include/QxtCore/QxtLineSocket000066400000000000000000000000341215241066400205100ustar00rootroot00000000000000#include "qxtlinesocket.h" libqxt-0.6.2/include/QxtCore/QxtLinkedTree000066400000000000000000000000341215241066400204760ustar00rootroot00000000000000#include "qxtlinkedtree.h" libqxt-0.6.2/include/QxtCore/QxtLinkedTreeItem000066400000000000000000000000331215241066400213140ustar00rootroot00000000000000#include "qxtlinkedtree.h" libqxt-0.6.2/include/QxtCore/QxtLinkedTreeIterator000066400000000000000000000000331215241066400222070ustar00rootroot00000000000000#include "qxtlinkedtree.h" libqxt-0.6.2/include/QxtCore/QxtLocale000066400000000000000000000000301215241066400176430ustar00rootroot00000000000000#include "qxtlocale.h" libqxt-0.6.2/include/QxtCore/QxtLogStream000066400000000000000000000000311215241066400203420ustar00rootroot00000000000000#include "qxtlogstream.h"libqxt-0.6.2/include/QxtCore/QxtLogger000066400000000000000000000000271215241066400176710ustar00rootroot00000000000000#include "qxtlogger.h" libqxt-0.6.2/include/QxtCore/QxtLoggerEngine000066400000000000000000000000341215241066400210150ustar00rootroot00000000000000#include "qxtloggerengine.h"libqxt-0.6.2/include/QxtCore/QxtMetaObject000066400000000000000000000000341215241066400204650ustar00rootroot00000000000000#include "qxtmetaobject.h" libqxt-0.6.2/include/QxtCore/QxtMetaType000066400000000000000000000000321215241066400201760ustar00rootroot00000000000000#include "qxtmetatype.h" libqxt-0.6.2/include/QxtCore/QxtModelSerializer000066400000000000000000000000401215241066400215370ustar00rootroot00000000000000#include "qxtmodelserializer.h" libqxt-0.6.2/include/QxtCore/QxtMultiSignalWaiter000066400000000000000000000000421215241066400220530ustar00rootroot00000000000000#include "qxtmultisignalwaiter.h" libqxt-0.6.2/include/QxtCore/QxtNull000066400000000000000000000000261215241066400173630ustar00rootroot00000000000000#include "qxtnull.h" libqxt-0.6.2/include/QxtCore/QxtNullable000066400000000000000000000000321215241066400202040ustar00rootroot00000000000000#include "qxtnullable.h" libqxt-0.6.2/include/QxtCore/QxtPairList000066400000000000000000000000311215241066400201740ustar00rootroot00000000000000#include "qxtpairlist.h" libqxt-0.6.2/include/QxtCore/QxtPimpl000066400000000000000000000000271215241066400175330ustar00rootroot00000000000000#include "qxtpimpl.h" libqxt-0.6.2/include/QxtCore/QxtPipe000066400000000000000000000000261215241066400173460ustar00rootroot00000000000000#include "qxtpipe.h" libqxt-0.6.2/include/QxtCore/QxtPointerList000066400000000000000000000000351215241066400207250ustar00rootroot00000000000000#include "qxtpointerlist.h" libqxt-0.6.2/include/QxtCore/QxtRPCService000066400000000000000000000000331215241066400204140ustar00rootroot00000000000000#include "qxtrpcservice.h" libqxt-0.6.2/include/QxtCore/QxtSerialDevice000066400000000000000000000000351215241066400210100ustar00rootroot00000000000000#include "qxtserialdevice.h" libqxt-0.6.2/include/QxtCore/QxtSharedPrivate000066400000000000000000000000401215241066400212060ustar00rootroot00000000000000#include "qxtsharedprivate.h" libqxt-0.6.2/include/QxtCore/QxtSignalGroup000066400000000000000000000000341215241066400207020ustar00rootroot00000000000000#include "qxtsignalgroup.h" libqxt-0.6.2/include/QxtCore/QxtSignalWaiter000066400000000000000000000000361215241066400210430ustar00rootroot00000000000000#include "qxtsignalwaiter.h" libqxt-0.6.2/include/QxtCore/QxtSlotJob000066400000000000000000000000311215241066400200210ustar00rootroot00000000000000#include "qxtslotjob.h" libqxt-0.6.2/include/QxtCore/QxtSlotMapper000066400000000000000000000000331215241066400205350ustar00rootroot00000000000000#include "qxtslotmapper.h" libqxt-0.6.2/include/QxtCore/QxtStdStreambufDevice000066400000000000000000000000441215241066400221740ustar00rootroot00000000000000#include "qxtstdstreambufdevice.h" libqxt-0.6.2/include/QxtCore/QxtStdio000066400000000000000000000000271215241066400175340ustar00rootroot00000000000000#include "qxtstdio.h" libqxt-0.6.2/include/QxtCore/QxtTimer000066400000000000000000000000261215241066400175310ustar00rootroot00000000000000#include "qxttimer.h" libqxt-0.6.2/include/QxtCore/QxtTypeList000066400000000000000000000000311215241066400202220ustar00rootroot00000000000000#include "qxttypelist.h" libqxt-0.6.2/include/QxtCore/QxtXmlFileLoggerEngine000066400000000000000000000000431215241066400222760ustar00rootroot00000000000000#include "qxtxmlfileloggerengine.h"libqxt-0.6.2/include/QxtGui/000077500000000000000000000000001215241066400156675ustar00rootroot00000000000000libqxt-0.6.2/include/QxtGui/QxtApplication000066400000000000000000000000351215241066400205500ustar00rootroot00000000000000#include "qxtapplication.h" libqxt-0.6.2/include/QxtGui/QxtBaseSpinBox000066400000000000000000000000351215241066400204620ustar00rootroot00000000000000#include "qxtbasespinbox.h" libqxt-0.6.2/include/QxtGui/QxtCheckComboBox000066400000000000000000000000371215241066400207550ustar00rootroot00000000000000#include "qxtcheckcombobox.h" libqxt-0.6.2/include/QxtGui/QxtConfigDialog000066400000000000000000000000361215241066400206330ustar00rootroot00000000000000#include "qxtconfigdialog.h" libqxt-0.6.2/include/QxtGui/QxtConfigWidget000066400000000000000000000000361215241066400206570ustar00rootroot00000000000000#include "qxtconfigwidget.h" libqxt-0.6.2/include/QxtGui/QxtConfirmationMessage000066400000000000000000000000451215241066400222430ustar00rootroot00000000000000#include "qxtconfirmationmessage.h" libqxt-0.6.2/include/QxtGui/QxtCountryComboBox000066400000000000000000000000411215241066400213760ustar00rootroot00000000000000#include "qxtcountrycombobox.h" libqxt-0.6.2/include/QxtGui/QxtCountryModel000066400000000000000000000000361215241066400207320ustar00rootroot00000000000000#include "qxtcountrymodel.h" libqxt-0.6.2/include/QxtGui/QxtCrumbView000066400000000000000000000000321215241066400202050ustar00rootroot00000000000000#include "qxtcrumbview.h" libqxt-0.6.2/include/QxtGui/QxtFlowView000066400000000000000000000000321215241066400200440ustar00rootroot00000000000000#include "qxtflowview.h" libqxt-0.6.2/include/QxtGui/QxtGlobalShortcut000066400000000000000000000000401215241066400212350ustar00rootroot00000000000000#include "qxtglobalshortcut.h" libqxt-0.6.2/include/QxtGui/QxtGroupBox000066400000000000000000000000311215241066400200460ustar00rootroot00000000000000#include "qxtgroupbox.h" libqxt-0.6.2/include/QxtGui/QxtGui000066400000000000000000000000261215241066400170310ustar00rootroot00000000000000#include "qxtgui.h" libqxt-0.6.2/include/QxtGui/QxtHeaderView000066400000000000000000000000341215241066400203270ustar00rootroot00000000000000#include "qxtheaderview.h" libqxt-0.6.2/include/QxtGui/QxtItemDelegate000066400000000000000000000000361215241066400206370ustar00rootroot00000000000000#include "qxtitemdelegate.h" libqxt-0.6.2/include/QxtGui/QxtItemEditorCreator000066400000000000000000000000431215241066400216710ustar00rootroot00000000000000#include "qxtitemeditorcreator.h" libqxt-0.6.2/include/QxtGui/QxtItemEditorCreatorBase000066400000000000000000000000471215241066400224700ustar00rootroot00000000000000#include "qxtitemeditorcreatorbase.h" libqxt-0.6.2/include/QxtGui/QxtLabel000066400000000000000000000000271215241066400173250ustar00rootroot00000000000000#include "qxtlabel.h" libqxt-0.6.2/include/QxtGui/QxtLanguageComboBox000066400000000000000000000000421215241066400214570ustar00rootroot00000000000000#include "qxtlanguagecombobox.h" libqxt-0.6.2/include/QxtGui/QxtLetterBoxWidget000066400000000000000000000000401215241066400213550ustar00rootroot00000000000000#include "qxtletterboxwidget.h" libqxt-0.6.2/include/QxtGui/QxtLineEdit000066400000000000000000000000321215241066400177770ustar00rootroot00000000000000#include "qxtlineedit.h" libqxt-0.6.2/include/QxtGui/QxtListWidget000066400000000000000000000000341215241066400203630ustar00rootroot00000000000000#include "qxtlistwidget.h" libqxt-0.6.2/include/QxtGui/QxtListWidgetItem000066400000000000000000000000401215241066400211770ustar00rootroot00000000000000#include "qxtlistwidgetitem.h" libqxt-0.6.2/include/QxtGui/QxtNativeEventFilter000066400000000000000000000000431215241066400217020ustar00rootroot00000000000000#include "qxtnativeeventfilter.h" libqxt-0.6.2/include/QxtGui/QxtProgressLabel000066400000000000000000000000361215241066400210520ustar00rootroot00000000000000#include "qxtprogresslabel.h" libqxt-0.6.2/include/QxtGui/QxtProxyStyle000066400000000000000000000000341215241066400204460ustar00rootroot00000000000000#include "qxtproxystyle.h" libqxt-0.6.2/include/QxtGui/QxtPushButton000066400000000000000000000000341215241066400204170ustar00rootroot00000000000000#include "qxtpushbutton.h" libqxt-0.6.2/include/QxtGui/QxtScheduleHeaderWidget000066400000000000000000000000451215241066400223170ustar00rootroot00000000000000#include "qxtscheduleheaderwidget.h" libqxt-0.6.2/include/QxtGui/QxtScheduleItemDelegate000066400000000000000000000000451215241066400223140ustar00rootroot00000000000000#include "qxtscheduleitemdelegate.h" libqxt-0.6.2/include/QxtGui/QxtScheduleView000066400000000000000000000000351215241066400206740ustar00rootroot00000000000000#include "qxtscheduleview.h" libqxt-0.6.2/include/QxtGui/QxtScreen000066400000000000000000000000271215241066400175250ustar00rootroot00000000000000#include "qxtscreen.h" libqxt-0.6.2/include/QxtGui/QxtSortFilterProxyModel000066400000000000000000000000461215241066400224270ustar00rootroot00000000000000#include "qxtsortfilterproxymodel.h" libqxt-0.6.2/include/QxtGui/QxtSpanSlider000066400000000000000000000000341215241066400203500ustar00rootroot00000000000000#include "qxtspanslider.h" libqxt-0.6.2/include/QxtGui/QxtStandardItemEditorCreator000066400000000000000000000000531215241066400233530ustar00rootroot00000000000000#include "qxtstandarditemeditorcreator.h" libqxt-0.6.2/include/QxtGui/QxtStars000066400000000000000000000000261215241066400174010ustar00rootroot00000000000000#include "qxtstars.h" libqxt-0.6.2/include/QxtGui/QxtStringSpinBox000066400000000000000000000000371215241066400210600ustar00rootroot00000000000000#include "qxtstringspinbox.h" libqxt-0.6.2/include/QxtGui/QxtStringValidator000066400000000000000000000000411215241066400214160ustar00rootroot00000000000000#include "qxtstringvalidator.h" libqxt-0.6.2/include/QxtGui/QxtStyleOptionScheduleViewItem000066400000000000000000000000541215241066400237260ustar00rootroot00000000000000#include "qxtstyleoptionscheduleviewitem.h" libqxt-0.6.2/include/QxtGui/QxtTabWidget000066400000000000000000000000331215241066400201550ustar00rootroot00000000000000#include "qxttabwidget.h" libqxt-0.6.2/include/QxtGui/QxtTableWidget000066400000000000000000000000351215241066400205000ustar00rootroot00000000000000#include "qxttablewidget.h" libqxt-0.6.2/include/QxtGui/QxtTableWidgetItem000066400000000000000000000000411215241066400213140ustar00rootroot00000000000000#include "qxttablewidgetitem.h" libqxt-0.6.2/include/QxtGui/QxtToolTip000066400000000000000000000000301215241066400176720ustar00rootroot00000000000000#include "qxttooltip.h" libqxt-0.6.2/include/QxtGui/QxtTreeWidget000066400000000000000000000000341215241066400203470ustar00rootroot00000000000000#include "qxttreewidget.h" libqxt-0.6.2/include/QxtGui/QxtTreeWidgetItem000066400000000000000000000000401215241066400211630ustar00rootroot00000000000000#include "qxttreewidgetitem.h" libqxt-0.6.2/include/QxtGui/QxtWindowSystem000066400000000000000000000000361215241066400207620ustar00rootroot00000000000000#include "qxtwindowsystem.h" libqxt-0.6.2/include/QxtNetwork/000077500000000000000000000000001215241066400165745ustar00rootroot00000000000000libqxt-0.6.2/include/QxtNetwork/QxtJSONRpcCall000066400000000000000000000000341215241066400212230ustar00rootroot00000000000000#include "qxtjsonrpccall.h" libqxt-0.6.2/include/QxtNetwork/QxtJSONRpcClient000066400000000000000000000000361215241066400215700ustar00rootroot00000000000000#include "qxtjsonrpcclient.h" libqxt-0.6.2/include/QxtNetwork/QxtNetwork000066400000000000000000000000311215241066400206370ustar00rootroot00000000000000#include "qxtnetwork.h" libqxt-0.6.2/include/QxtNetwork/QxtRPCPeer000066400000000000000000000000311215241066400204460ustar00rootroot00000000000000#include "qxtrpcpeer.h" libqxt-0.6.2/include/QxtNetwork/QxtTcpConnectionManager000066400000000000000000000000451215241066400232540ustar00rootroot00000000000000#include "qxttcpconnectionmanager.h" libqxt-0.6.2/include/QxtNetwork/QxtXmlRpcCall000066400000000000000000000000341215241066400212120ustar00rootroot00000000000000#include "qxtxmlrpccall.h" libqxt-0.6.2/include/QxtNetwork/QxtXmlRpcClient000066400000000000000000000000361215241066400215570ustar00rootroot00000000000000#include "qxtxmlrpcclient.h" libqxt-0.6.2/include/QxtSql/000077500000000000000000000000001215241066400157025ustar00rootroot00000000000000libqxt-0.6.2/include/QxtSql/QxtSql000066400000000000000000000000241215241066400170550ustar00rootroot00000000000000#include "qxtsql.h" libqxt-0.6.2/include/QxtSql/QxtSqlPackage000066400000000000000000000000341215241066400203320ustar00rootroot00000000000000#include "qxtsqlpackage.h" libqxt-0.6.2/include/QxtSql/QxtSqlPackageModel000066400000000000000000000000411215241066400213110ustar00rootroot00000000000000#include "qxtsqlpackagemodel.h" libqxt-0.6.2/include/QxtWeb/000077500000000000000000000000001215241066400156605ustar00rootroot00000000000000libqxt-0.6.2/include/QxtWeb/QxtAbstractHttpConnector000066400000000000000000000000471215241066400225570ustar00rootroot00000000000000#include "qxtabstracthttpconnector.h" libqxt-0.6.2/include/QxtWeb/QxtAbstractWebService000066400000000000000000000000441215241066400220200ustar00rootroot00000000000000#include "qxtabstractwebservice.h" libqxt-0.6.2/include/QxtWeb/QxtAbstractWebSessionManager000066400000000000000000000000531215241066400233360ustar00rootroot00000000000000#include "qxtabstractwebsessionmanager.h" libqxt-0.6.2/include/QxtWeb/QxtHtmlTemplate000066400000000000000000000000361215241066400206770ustar00rootroot00000000000000#include "qxthtmltemplate.h" libqxt-0.6.2/include/QxtWeb/QxtHttpServerConnector000066400000000000000000000000461215241066400222610ustar00rootroot00000000000000#include "qxtabstracthttpconnector.h" libqxt-0.6.2/include/QxtWeb/QxtHttpSessionManager000066400000000000000000000000441215241066400220540ustar00rootroot00000000000000#include "qxthttpsessionmanager.h" libqxt-0.6.2/include/QxtWeb/QxtMail000066400000000000000000000000261215241066400171600ustar00rootroot00000000000000#include "qxtmail.h" libqxt-0.6.2/include/QxtWeb/QxtScgiServerConnector000066400000000000000000000000461215241066400222270ustar00rootroot00000000000000#include "qxtabstracthttpconnector.h" libqxt-0.6.2/include/QxtWeb/QxtSendmail000066400000000000000000000000321215241066400200270ustar00rootroot00000000000000#include "qxtsendmail.h" libqxt-0.6.2/include/QxtWeb/QxtWeb000066400000000000000000000000241215241066400170110ustar00rootroot00000000000000#include "qxtweb.h" libqxt-0.6.2/include/QxtWeb/QxtWebCgiService000066400000000000000000000000361215241066400207600ustar00rootroot00000000000000#include "qxtwebcgiservice.h" libqxt-0.6.2/include/QxtWeb/QxtWebContent000066400000000000000000000000341215241066400203450ustar00rootroot00000000000000#include "qxtwebcontent.h" libqxt-0.6.2/include/QxtWeb/QxtWebErrorEvent000066400000000000000000000000321215241066400210240ustar00rootroot00000000000000#include "qxtwebevent.h" libqxt-0.6.2/include/QxtWeb/QxtWebEvent000066400000000000000000000000321215241066400200120ustar00rootroot00000000000000#include "qxtwebevent.h" libqxt-0.6.2/include/QxtWeb/QxtWebFileUploadEvent000066400000000000000000000000311215241066400217560ustar00rootroot00000000000000#include "qxtwebevent.h" libqxt-0.6.2/include/QxtWeb/QxtWebPageEvent000066400000000000000000000000321215241066400206070ustar00rootroot00000000000000#include "qxtwebevent.h" libqxt-0.6.2/include/QxtWeb/QxtWebRedirectEvent000066400000000000000000000000321215241066400214740ustar00rootroot00000000000000#include "qxtwebevent.h" libqxt-0.6.2/include/QxtWeb/QxtWebRemoveCookieEvent000066400000000000000000000000311215241066400223210ustar00rootroot00000000000000#include "qxtwebevent.h" libqxt-0.6.2/include/QxtWeb/QxtWebRequestEvent000066400000000000000000000000321215241066400213630ustar00rootroot00000000000000#include "qxtwebevent.h" libqxt-0.6.2/include/QxtWeb/QxtWebServiceDirectory000066400000000000000000000000451215241066400222220ustar00rootroot00000000000000#include "qxtwebservicedirectory.h" libqxt-0.6.2/include/QxtWeb/QxtWebSlotService000066400000000000000000000000401215241066400211720ustar00rootroot00000000000000#include "qxtwebslotservice.h" libqxt-0.6.2/include/QxtWeb/QxtWebStoreCookieEvent000066400000000000000000000000311215241066400221600ustar00rootroot00000000000000#include "qxtwebevent.h" libqxt-0.6.2/include/QxtZeroconf/000077500000000000000000000000001215241066400167305ustar00rootroot00000000000000libqxt-0.6.2/include/QxtZeroconf/QxtDiscoverableService000066400000000000000000000000441215241066400232710ustar00rootroot00000000000000#include "qxtdiscoverableservice.h" libqxt-0.6.2/include/QxtZeroconf/QxtDiscoverableServiceName000066400000000000000000000000501215241066400240670ustar00rootroot00000000000000#include "qxtdiscoverableservicename.h" libqxt-0.6.2/include/QxtZeroconf/QxtServiceBrowser000066400000000000000000000000371215241066400223140ustar00rootroot00000000000000#include "qxtservicebrowser.h" libqxt-0.6.2/include/QxtZeroconf/QxtZeroConf000066400000000000000000000000311215241066400210670ustar00rootroot00000000000000#include "qxtzeroconf.h" libqxt-0.6.2/lgpl-2.1.txt000066400000000000000000000635041215241066400150300ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 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. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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 with this License. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. 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. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; 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. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libqxt-0.6.2/libqxt.pro000066400000000000000000000063021215241066400150510ustar00rootroot00000000000000# # Qxt main project file # # Do not edit this file. # Use the configure script to specify compile options. # TEMPLATE = subdirs DESTDIR = lib #check Qt version lessThan(QT_MAJOR_VERSION, 4) | lessThan(QT_MINOR_VERSION, 3) { error(LibQxt requires Qt 4.3 or newer but Qt $$[QT_VERSION] was detected.) } contains( QXT_MODULES, docs ){ message( building docs ) include(doc/doc.pri) } contains( QXT_MODULES, core ){ message( building core module ) sub_core.subdir = src/core SUBDIRS += sub_core } contains( QXT_MODULES, gui ){ message( building gui module ) sub_gui.subdir = src/gui sub_gui.depends = sub_core SUBDIRS += sub_gui contains( QXT_MODULES, designer ){ sub_designer.subdir = src/designer sub_designer.depends = sub_core sub_gui SUBDIRS += sub_designer } } contains( QXT_MODULES, network ){ message( building network module ) sub_network.subdir = src/network sub_network.depends = sub_core SUBDIRS += sub_network } contains( QXT_MODULES, sql ){ message( building sql module ) sub_sql.subdir = src/sql sub_sql.depends = sub_core SUBDIRS += sub_sql } contains(DEFINES,HAVE_DB){ contains( QXT_MODULES, berkeley ){ message( building berkeley module ) sub_berkeley.subdir = src/berkeley sub_berkeley.depends = sub_core SUBDIRS += sub_berkeley } } contains(DEFINES,HAVE_ZEROCONF){ contains( QXT_MODULES, zeroconf ){ message( building zeroconf module ) sub_zeroconf.subdir = src/zeroconf sub_zeroconf.depends = sub_network SUBDIRS += sub_zeroconf } } contains( QXT_MODULES, web ){ message( building web module ) sub_web.subdir = src/web sub_web.depends = sub_core sub_network SUBDIRS += sub_web } features.path = $$QXT_INSTALL_FEATURES features.files = $$QXT_SOURCE_TREE/features/qxt.prf $$QXT_BUILD_TREE/features/qxtvars.prf INSTALLS += features style.CONFIG = recursive style.recurse = $$SUBDIRS style.recurse_target = astyle QMAKE_EXTRA_TARGETS += style sub-examples.commands += cd examples && $(QMAKE) $$QXT_SOURCE_TREE/examples/examples.pro && $(MAKE) QMAKE_EXTRA_TARGETS += sub-examples sub-tests.commands += cd tests && $(QMAKE) $$QXT_SOURCE_TREE/tests/tests.pro && $(MAKE) QMAKE_EXTRA_TARGETS += sub-tests runtests.depends += sub-tests runtests.commands += cd tests && $(MAKE) test QMAKE_EXTRA_TARGETS += runtests unix { cov_zerocounters.CONFIG += recursive cov_zerocounters.recurse = $$SUBDIRS cov_zerocounters.recurse -= sub_designer cov_zerocounters.recurse_target = zerocounters QMAKE_EXTRA_TARGETS += cov_zerocounters cov_capture.CONFIG += recursive cov_capture.recurse = $$SUBDIRS cov_capture.recurse -= sub_designer cov_capture.recurse -= sub_sql # TODO: write unit tests for these! cov_capture.recurse_target = capture QMAKE_EXTRA_TARGETS += cov_capture cov_genhtml.CONFIG += recursive cov_genhtml.recurse = $$SUBDIRS cov_genhtml.recurse -= sub_designer cov_genhtml.recurse -= sub_sql # TODO: write unit tests for these! cov_genhtml.recurse_target = genhtml QMAKE_EXTRA_TARGETS += cov_genhtml coverage.depends += first cov_zerocounters runtests cov_capture cov_genhtml QMAKE_EXTRA_TARGETS += coverage } libqxt-0.6.2/src/000077500000000000000000000000001215241066400136125ustar00rootroot00000000000000libqxt-0.6.2/src/berkeley/000077500000000000000000000000001215241066400154145ustar00rootroot00000000000000libqxt-0.6.2/src/berkeley/berkeley.pri000066400000000000000000000003221215241066400177270ustar00rootroot00000000000000INCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += qxtberkeley.h HEADERS += qxtbdb.h HEADERS += qxtbdbhash.h HEADERS += qxtbdbtree.h SOURCES += qxtbdb.cpp SOURCES += qxtbdbhash.cpp SOURCES += qxtbdbtree.cpp libqxt-0.6.2/src/berkeley/berkeley.pro000066400000000000000000000003371215241066400177430ustar00rootroot00000000000000CLEAN_TARGET = QxtBerkeley DEFINES += BUILD_QXT_BERKELEY QT = core QXT = core CONVENIENCE += $$CLEAN_TARGET include(berkeley.pri) include(../qxtbase.pri) !win32:LIBS += -ldb libqxt-0.6.2/src/berkeley/qxtbdb.cpp000066400000000000000000000226621215241066400174140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtBerkeley module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtbdb.h" #include #include #include #include static void qxtBDBDatabaseErrorHandler(const BerkeleyDB::DB_ENV*, const char* a, const char* b) { qDebug("QxtBDBDatabase: %s, %s", a, b); } QxtBdb::QxtBdb() { isOpen = false; if (db_create(&db, NULL, 0) != 0) qFatal("db_create failed"); db->set_errcall(db, qxtBDBDatabaseErrorHandler); } QxtBdb::~QxtBdb() { db->close(db, 0); } bool QxtBdb::open(QString path, OpenFlags f) { Q_ASSERT(!isOpen); if (QFileInfo(path).exists()) { BerkeleyDB::DB * tdb; if (db_create(&tdb, NULL, 0) != 0) qFatal("db_create failed"); if (tdb->verify(tdb, qPrintable(path), NULL, NULL, 0) == DB_VERIFY_BAD) qCritical("QxtBdb::open Database '%s' is corrupted.", qPrintable(path)); } int flags = 0; if (f&CreateDatabase) flags |= DB_CREATE; if (f&ReadOnly) flags |= DB_RDONLY; if (f&LockFree) flags |= DB_THREAD; isOpen = (db->open(db, /* DB structure pointer */ NULL, /* Transaction pointer */ qPrintable(path), /* On-disk file that holds the database. */ NULL, /* Optional logical database name */ BerkeleyDB::DB_BTREE, /* Database access method */ flags, /* Open flags */ 0) == 0); return isOpen; } QxtBdb::OpenFlags QxtBdb::openFlags() { if (!isOpen) return 0; OpenFlags f; BerkeleyDB::u_int32_t open_flags; db->get_open_flags(db, &open_flags); if (open_flags&DB_CREATE) f |= CreateDatabase; if (open_flags&DB_RDONLY) f |= ReadOnly; if (open_flags&DB_THREAD) f |= LockFree; return f; } bool QxtBdb::flush() { if (!isOpen) return false; return (db->sync(db, 0) == 0); } /*! low level get function. serialised key and value with the given meta ids. always reads and writes both key and value, if given. use this when doing operations that require the key to be read out of the db. */ bool QxtBdb::get(void* key, int keytype, void* value, int valuetype, BerkeleyDB::u_int32_t flags, BerkeleyDB::DBC * cursor) const { BerkeleyDB::DBT dbkey, dbvalue; ::memset(&dbkey, 0, sizeof(BerkeleyDB::DBT)); ::memset(&dbvalue, 0, sizeof(BerkeleyDB::DBT)); if (key) { QByteArray d_key; QBuffer buffer(&d_key); buffer.open(QIODevice::WriteOnly); QDataStream s(&buffer); if (!QMetaType::save(s, keytype, key)) qCritical("QMetaType::save failed. is your key registered with the QMetaType?"); buffer.close(); dbkey.size = d_key.size(); dbkey.data = ::malloc(d_key.size()); ::memcpy(dbkey.data, d_key.data(), d_key.size()); } if (value) { QByteArray d_value; QBuffer buffer(&d_value); buffer.open(QIODevice::WriteOnly); QDataStream s(&buffer); if (!QMetaType::save(s, valuetype, value)) qCritical("QMetaType::save failed. is your value registered with the QMetaType?"); buffer.close(); dbvalue.size = d_value.size(); dbvalue.data = ::malloc(d_value.size()); ::memcpy(dbvalue.data, d_value.data(), d_value.size()); } dbvalue.ulen = 0; dbvalue.flags = DB_DBT_USERMEM; dbkey.ulen = 0; dbkey.flags = DB_DBT_USERMEM; int ret; if (cursor) ret = cursor->c_get(cursor, &dbkey, &dbvalue, flags); else ret = db->get(db, NULL, &dbkey, &dbvalue, flags); if (ret != DB_BUFFER_SMALL) { ::free(dbvalue.data); ::free(dbkey.data); return (ret == 0); } dbvalue.ulen = dbvalue.size; dbvalue.data =::malloc(dbvalue.size); dbkey.ulen = dbkey.size; dbkey.data =::malloc(dbkey.size); if (cursor) ret = cursor->c_get(cursor, &dbkey, &dbvalue, flags); else ret = db->get(db, NULL, &dbkey, &dbvalue, flags); QByteArray d_value = QByteArray::fromRawData((const char*) dbvalue.data, dbvalue.size); QByteArray d_key = QByteArray::fromRawData((const char*) dbkey.data, dbkey.size); if (ret != 0) { ::free(dbvalue.data); ::free(dbkey.data); return false; } if (key) { QBuffer buffer(&d_key); buffer.open(QIODevice::ReadOnly); QDataStream s(&buffer); if (!QMetaType::load(s, keytype, key)) qCritical("QMetaType::load failed. is your key registered with the QMetaType?"); buffer.close(); } if (value) { QBuffer buffer(&d_value); buffer.open(QIODevice::ReadOnly); QDataStream s(&buffer); if (!QMetaType::load(s, valuetype, value)) qCritical("QMetaType::load failed. is your value registered with the QMetaType?"); buffer.close(); } ::free(dbvalue.data); ::free(dbkey.data); return true; } /*! low level get function. serialised key and value with the given meta ids. doesn't write to the key. use this when doing operations that require the key to be passed. */ bool QxtBdb::get(const void* key, int keytype, void* value, int valuetype, BerkeleyDB::u_int32_t flags, BerkeleyDB::DBC * cursor) const { BerkeleyDB::DBT dbkey, dbvalue; memset(&dbkey, 0, sizeof(BerkeleyDB::DBT)); memset(&dbvalue, 0, sizeof(BerkeleyDB::DBT)); if (key) { QByteArray d_key; QBuffer buffer(&d_key); buffer.open(QIODevice::WriteOnly); QDataStream s(&buffer); if (!QMetaType::save(s, keytype, key)) qCritical("QMetaType::save failed. is your key registered with the QMetaType?"); buffer.close(); dbkey.size = d_key.size(); dbkey.data = ::malloc(d_key.size()); ::memcpy(dbkey.data, d_key.data(), d_key.size()); } if (value) { QByteArray d_value; QBuffer buffer(&d_value); buffer.open(QIODevice::WriteOnly); QDataStream s(&buffer); if (!QMetaType::save(s, valuetype, value)) qCritical("QMetaType::save failed. is your value registered with the QMetaType?"); buffer.close(); dbvalue.size = d_value.size(); dbvalue.data = ::malloc(d_value.size()); ::memcpy(dbvalue.data, d_value.data(), d_value.size()); } dbvalue.ulen = 0; dbvalue.flags = DB_DBT_USERMEM; dbkey.ulen = 0; dbkey.flags = 0; dbkey.flags = DB_DBT_USERMEM; //it's my memory, ffs. stop deleting it! >_< int ret; if (cursor) ret = cursor->c_get(cursor, &dbkey, &dbvalue, flags); else ret = db->get(db, NULL, &dbkey, &dbvalue, flags); if (ret != DB_BUFFER_SMALL) { ::free(dbvalue.data); ::free(dbkey.data); return (ret == 0); } dbvalue.ulen = dbvalue.size; dbvalue.data =::malloc(dbvalue.size); if (cursor) ret = cursor->c_get(cursor, &dbkey, &dbvalue, flags); else ret = db->get(db, NULL, &dbkey, &dbvalue, flags); QByteArray d_value((const char*) dbvalue.data, dbvalue.size); QByteArray d_key((const char*) dbkey.data, dbkey.size); ::free(dbvalue.data); ::free(dbkey.data); Q_ASSERT_X(ret != DB_BUFFER_SMALL, Q_FUNC_INFO, "QxtBdb::get bdb inists on retriving the key for this operation. You need to specify a non const key. (or just specify a non const void* with the value of 0, i'll delete the key for you after bdb fetched it, so you don't need to bother)"); if (ret != 0) { return false; } if (value) { QBuffer buffer(&d_value); buffer.open(QIODevice::ReadOnly); QDataStream s(&buffer); if (!QMetaType::load(s, valuetype, value)) qCritical("QMetaType::load failed. is your value registered with the QMetaType?"); buffer.close(); } return true; } QString QxtBdb::dbErrorCodeToString(int e) { switch (e) { case DB_LOCK_DEADLOCK: return QString("Dead locked (%1)").arg(e); case DB_SECONDARY_BAD: return QString("Bad Secondary index (%1)").arg(e); case DB_RUNRECOVERY: return QString("Database corrupted. Run Recovery. (%1)").arg(e); default: return QString("Unknown error %1").arg(e); }; } libqxt-0.6.2/src/berkeley/qxtbdb.h000066400000000000000000000107021215241066400170510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtBerkeley module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /************************************************************************** This is private API. it might change at any time without warning. ****************************************************************************/ #ifndef QxtBdb_H_kpasd #define QxtBdb_H_kpasd #include #include #include #include #include #include #include #include ///its impossible to forward anyway, namespace BerkeleyDB { extern "C" { #include } /// aparantly MSVC and GCC have different understanding of what goes into a namespace and what not. #ifndef Q_CC_MSVC typedef quint32 u_int32_t; #endif } class QXT_BERKELEY_EXPORT QxtBdb { public: enum OpenFlag { CreateDatabase = 0x1, ReadOnly = 0x2, LockFree = 0x4 }; Q_DECLARE_FLAGS(OpenFlags, OpenFlag); QxtBdb(); ~QxtBdb(); bool get(void* key, int keytype, void* value, int valuetype, BerkeleyDB::u_int32_t flags = NULL, BerkeleyDB::DBC * cursor = 0) const ; bool get(const void* key, int keytype, void* value, int valuetype, BerkeleyDB::u_int32_t flags = NULL, BerkeleyDB::DBC * cursor = 0) const ; bool open(QString path, OpenFlags f = 0); OpenFlags openFlags(); bool flush(); BerkeleyDB::DB * db; bool isOpen; static QString dbErrorCodeToString(int e); template static T qxtMetaLoad(const void * data, size_t size) { T t; QByteArray b = QByteArray::fromRawData((const char*)data, size); QBuffer buffer(&b); buffer.open(QIODevice::ReadOnly); QDataStream s(&buffer); if (!QMetaType::load(s, qMetaTypeId(), &t)) qCritical("QMetaType::load failed. is your type registered with the QMetaType?"); buffer.close(); return t; } static void * qxtMetaLoad(const void * data, size_t size, int type) { void *p = QMetaType::construct(type); QByteArray b = QByteArray::fromRawData(static_cast(data), size); QBuffer buffer(&b); buffer.open(QIODevice::ReadOnly); QDataStream s(&buffer); if (!QMetaType::load(s, type, p)) qCritical("QMetaType::load failed. is your type registered with the QMetaType?"); buffer.close(); return p; } template static QByteArray qxtMetaSave(const T & t) { QByteArray d; QBuffer buffer(&d); buffer.open(QIODevice::WriteOnly); QDataStream s(&buffer); if (!QMetaType::save(s, qMetaTypeId(), &t)) qCritical("QMetaType::save failed. is your type registered with the QMetaType?"); buffer.close(); return d; } static void * qxtMetaSave(size_t * size, void * t, int type) { QByteArray d; QBuffer buffer(&d); buffer.open(QIODevice::WriteOnly); QDataStream s(&buffer); if (!QMetaType::save(s, type, t)) qCritical("QMetaType::save failed. is your type registered with the QMetaType?"); buffer.close(); *size = d.size(); void *p = ::malloc(d.size()); ::memcpy(p, d.data(), d.size()); return p; } }; Q_DECLARE_OPERATORS_FOR_FLAGS(QxtBdb::OpenFlags); #endif libqxt-0.6.2/src/berkeley/qxtbdbhash.cpp000066400000000000000000000155011215241066400202520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtBerkeley module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtbdbhash.h" /*! \class QxtBdbHash \inmodule QxtBerkeley \brief The QxtBdbHash class is a template class that provides key/value access to a berkeley db file. Both value and key must be registered with the qt meta system. You may not touch the file while a QxtBdbHash instance is running on it. examples usage: \code QxtBdbHash db("test.db"); db.insert(344.4,QStringList<<"HI"<<":)"); qDebug()< QxtBdbHash::begin() Returns an iterator to the first key,value pair. \sa QxtBdbHashIterator */ /*! \fn QxtBdbHashIterator QxtBdbHash::end() Return an iterator to the last key,value pair \sa QxtBdbHashIterator */ /*! \fn QxtBdbHashIterator QxtBdbHash::find ( const KEY & key ) Returns an iterator to the position of the pair identified by \a key \sa QxtBdbHashIterator */ /*! \fn bool QxtBdbHash::contains ( const KEY & key ) const Returns \c true if there is a record for the specified \a key. */ /*! \fn bool QxtBdbHash::remove ( const KEY & key ) Removes all records with the specified \a key. Returns \c true on success and \c false on failure. */ /*! \fn bool QxtBdbHash::insert( KEY key, VAL value ) Inserts a record with the specified \a key / \a value combination. Replaces any record with the same key. \bold {Note:} When working with iterators, keep in mind that inserting pairs, works reverse to the iteration. */ /*! \fn const VAL QxtBdbHash::value( const KEY & key ) const Returns the value associated with the specified \a key, or a default contructed value, if no such key exists. */ /*! \fn const VAL QxtBdbHash::operator[] ( const KEY & key ) const Same as value() */ /*! \fn bool QxtBdbHash::flush() Flushes the underlying DB file. All changes are synced to disk. */ /*! \class QxtBdbHashIterator \inmodule QxtBerkeley \brief The QxtBdbHashIterator class provides a fast iterator over a QxtBdbHash \sa QxtBdbHash TODO: {implicitshared} */ /*! \fn void QxtBdbHashIterator::QxtBdbHashIterator() Constructs an invalid QxtBdbHashIterator */ /*! \fn QxtBdbHashIterator::QxtBdbHashIterator(const QxtBdbHashIterator & other) Copy constructor */ /*! \fn QxtBdbHashIterator & QxtBdbHashIterator::operator= ( const QxtBdbHashIterator & other ) Assignment operator */ /*! \fn bool QxtBdbHashIterator::isValid() const Returns \c true if the iterator is valid. Invalid iterators are unusable and accessing any function will fail. */ /*! \fn QxtBdbHashIterator::operator KEY() const Convertion operator to the current value. \sa key() */ /*! \fn KEY QxtBdbHashIterator::key() const Returns the current key. \sa value() */ /*! \fn VAL QxtBdbHashIterator::value() const Returns the current value. \sa key() */ /*! \fn QxtBdbHashIterator QxtBdbHashIterator::operator + ( int j ) const Returns an iterator to the item at \a j positions forward from this iterator. */ /*! \fn QxtBdbHashIterator & QxtBdbHashIterator::operator ++ () The prefix ++ operator (++i) advances the iterator to the next item in the hash and returns an iterator to the new current item. */ /*! \fn QxtBdbHashIterator QxtBdbHashIterator::operator ++ (int) The postfix ++ operator (i++) advances the iterator to the next item in the hash and returns an iterator to the previously current item. */ /*! \fn QxtBdbHashIterator & QxtBdbHashIterator::operator += ( int j ) Advances the iterator by \a j items. */ /*! \fn QxtBdbHashIterator QxtBdbHashIterator::operator - ( int j ) const Returns an iterator to the item at \a j positions backward from this iterator. */ /*! \fn QxtBdbHashIterator & QxtBdbHashIterator::operator -- () The prefix -- operator (--i) makes the preceding item current and returns an iterator pointing to the new current item. */ /*! \fn QxtBdbHashIterator QxtBdbHashIterator::operator -- (int) The postfix -- operator (i--) makes the preceding item current and returns an iterator pointing to the previously current item. */ /*! \fn QxtBdbHashIterator & QxtBdbHashIterator::operator -= ( int j ) Makes the iterator go back by \a j items. */ /*! \fn QxtBdbHashIterator QxtBdbHashIterator::erase () Removes the (key, value) pair associated with the iterator from the hash, and returns an iterator to the next item in the hash. This instance is invalid then, and cannot be used further. */ libqxt-0.6.2/src/berkeley/qxtbdbhash.h000066400000000000000000000320071215241066400177170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtBerkeley module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QxtBdbHash_H_kpasd #define QxtBdbHash_H_kpasd #include "qxtbdb.h" #include #include #include #include #include template class QxtBdbHashIterator; template class /*QXT_BERKELEY_EXPORT*/ QxtBdbHash { public: QxtBdbHash(); QxtBdbHash(QString file); bool open(QString file); QxtBdbHashIterator begin(); QxtBdbHashIterator end(); QxtBdbHashIterator find(const KEY & key); void clear(); bool contains(const KEY & key) const; bool remove(const KEY & key); bool insert(KEY k, VAL v); const VAL value(const KEY & key) const; const VAL operator[](const KEY & key) const; bool flush(); private: int meta_id_key; int meta_id_val; QxtSharedPrivate qxt_d; }; class QxtBdbHashIteratorPrivate { public: QxtBdb * db; BerkeleyDB::DBC *dbc; void invalidate() { if (dbc) dbc->c_close(dbc); dbc = 0; } ~QxtBdbHashIteratorPrivate() { invalidate(); } }; template class QxtBdbHashIterator { public: QxtBdbHashIterator(); QxtBdbHashIterator(const QxtBdbHashIterator & other); QxtBdbHashIterator & operator= (const QxtBdbHashIterator & other); bool isValid() const; operator KEY() const; KEY key() const; VAL value() const; QxtBdbHashIterator operator + (int j) const; QxtBdbHashIterator & operator ++ (); QxtBdbHashIterator operator ++ (int); QxtBdbHashIterator & operator += (int j); QxtBdbHashIterator operator - (int j) const; QxtBdbHashIterator & operator -- (); QxtBdbHashIterator operator -- (int); QxtBdbHashIterator & operator -= (int j); QxtBdbHashIterator erase(); private: friend class QxtBdbHash; QxtBdbHashIterator(BerkeleyDB::DBC*, QxtBdb * p); QxtSharedPrivate qxt_d; int meta_id_key; int meta_id_val; /*won't work. no support in bdb*/ bool operator== (const QxtBdbHashIterator & other) const { return false; } bool operator!= (const QxtBdbHashIterator & other) const { return false; } }; template QxtBdbHash::QxtBdbHash() { qxt_d = new QxtBdb(); ///this will fail to compile if KEY or VALUE are not declared metatypes. Good. meta_id_key = qMetaTypeId(); meta_id_val = qMetaTypeId(); } template QxtBdbHash::QxtBdbHash(QString file) { qxt_d = new QxtBdb(); open(file); ///this will fail to compile if KEY or VALUE are not declared metatypes. Good. meta_id_key = qMetaTypeId(); meta_id_val = qMetaTypeId(); } template bool QxtBdbHash::open(QString file) { return qxt_d().open(file, QxtBdb::CreateDatabase | QxtBdb::LockFree); } template QxtBdbHashIterator QxtBdbHash::begin() { BerkeleyDB::DBC *cursor; qxt_d().db->cursor(qxt_d().db, NULL, &cursor, 0); if (qxt_d().get((void*)0, 0, 0, 0, DB_FIRST, cursor)) return QxtBdbHashIterator(cursor, &qxt_d()); else return QxtBdbHashIterator(); } template QxtBdbHashIterator QxtBdbHash::end() { BerkeleyDB::DBC *cursor; qxt_d().db->cursor(qxt_d().db, NULL, &cursor, 0); if (qxt_d().get((void*)0, 0, 0, 0, DB_LAST, cursor)) return QxtBdbHashIterator(cursor, &qxt_d()); else return QxtBdbHashIterator(); } template QxtBdbHashIterator QxtBdbHash::find(const KEY & k) { BerkeleyDB::DBC *cursor; qxt_d().db->cursor(qxt_d().db, NULL, &cursor, 0); if (qxt_d().get(&k, meta_id_key, 0, 0, DB_SET, cursor)) return QxtBdbHashIterator(cursor, &qxt_d()); else return QxtBdbHashIterator(); } template void QxtBdbHash::clear() { if (!qxt_d().isOpen) return; BerkeleyDB::u_int32_t x; qxt_d().db->truncate(qxt_d().db, NULL, &x, 0); } template bool QxtBdbHash::contains(const KEY & k) const { if (!qxt_d().isOpen) return false; BerkeleyDB::DBT key; /* Zero out the DBTs before using them. */ memset(&key, 0, sizeof(BerkeleyDB::DBT)); QByteArray d_key; { QBuffer buffer(&d_key); buffer.open(QIODevice::WriteOnly); QDataStream s(&buffer); if (!QMetaType::save(s, meta_id_key, &k)) qCritical("QMetaType::save failed. is your type registered with the QMetaType?"); buffer.close(); } key.data = d_key.data(); key.size = d_key.size(); return (qxt_d().db->exists(qxt_d().db, NULL, &key, 0) == 0); } template bool QxtBdbHash::remove(const KEY & k) { if (!qxt_d().isOpen) return false; BerkeleyDB::DBT key; /* Zero out the DBTs before using them. */ memset(&key, 0, sizeof(BerkeleyDB::DBT)); QByteArray d_key; { QBuffer buffer(&d_key); buffer.open(QIODevice::WriteOnly); QDataStream s(&buffer); if (!QMetaType::save(s, meta_id_key, &k)) qCritical("QMetaType::save failed. is your type registered with the QMetaType?"); buffer.close(); } key.data = d_key.data(); key.size = d_key.size(); return (qxt_d().db->del(qxt_d().db, NULL, &key, 0) == 0); } template bool QxtBdbHash::insert(KEY k, VAL v) { if (!qxt_d().isOpen) return false; QByteArray d_key, d_value; { QBuffer buffer(&d_key); buffer.open(QIODevice::WriteOnly); QDataStream s(&buffer); if (!QMetaType::save(s, meta_id_key, &k)) qCritical("QMetaType::save failed. is your type registered with the QMetaType?"); buffer.close(); } { QBuffer buffer(&d_value); buffer.open(QIODevice::WriteOnly); QDataStream s(&buffer); if (!QMetaType::save(s, meta_id_val, &v)) qCritical("QMetaType::save failed. is your value registered with the QMetaType?"); buffer.close(); } BerkeleyDB::DBT key, value; /* Zero out the DBTs before using them. */ memset(&key, 0, sizeof(BerkeleyDB::DBT)); memset(&value, 0, sizeof(BerkeleyDB::DBT)); key.data = d_key.data(); key.size = d_key.size(); value.data = d_value.data(); value.size = d_value.size(); int ret = qxt_d().db->put(qxt_d().db, NULL, &key, &value, 0); return (ret == 0); } template const VAL QxtBdbHash::value(const KEY & k) const { if (!qxt_d().isOpen) return VAL() ; VAL v; if (!qxt_d().get(&k, meta_id_key, &v, meta_id_val)) return VAL(); return v; } template const VAL QxtBdbHash::operator[](const KEY & key) const { return value(key); } template bool QxtBdbHash::flush() { return qxt_d().flush(); } template QxtBdbHashIterator::QxtBdbHashIterator() { qxt_d = new QxtBdbHashIteratorPrivate; qxt_d().dbc = 0; qxt_d().db = 0; meta_id_key = qMetaTypeId(); meta_id_val = qMetaTypeId(); } template QxtBdbHashIterator::QxtBdbHashIterator(const QxtBdbHashIterator & other) { ///FIXME: possible leaking, since the other isnt properly destructed? qxt_d = other.qxt_d; meta_id_key = qMetaTypeId(); meta_id_val = qMetaTypeId(); } template QxtBdbHashIterator & QxtBdbHashIterator::operator= (const QxtBdbHashIterator & other) { ///FIXME: possible leaking, since the other isnt properly destructed? qxt_d = other.qxt_d; return *this; } template bool QxtBdbHashIterator::isValid() const { return (qxt_d().dbc != 0); } template QxtBdbHashIterator::operator KEY() const { return key(); } template KEY QxtBdbHashIterator::key() const { if (!isValid()) return KEY(); KEY k; if (qxt_d().db->get(&k, meta_id_key, 0, 0, DB_CURRENT, qxt_d().dbc)) return k; else return KEY(); } template VAL QxtBdbHashIterator::value() const { if (!isValid()) return VAL(); VAL v; if (qxt_d().db->get((void*)0, 0, &v, meta_id_val, DB_CURRENT, qxt_d().dbc)) return v; else return VAL(); } template QxtBdbHashIterator QxtBdbHashIterator::operator + (int j) const { // if j is negative, it should subtract as apposed to do nothing... if(j < 0) return this->operator-(j*(-1)); QxtBdbHashIterator d = *this; for (int i = 0;i < j;i++) ++d; return d; } template QxtBdbHashIterator & QxtBdbHashIterator::operator ++ () /*prefix*/ { if (!isValid()) return *this; if (!qxt_d().db->get((void*)0, 0, 0, 0, DB_NEXT, qxt_d().dbc)) { qxt_d().invalidate(); } return *this; } template QxtBdbHashIterator QxtBdbHashIterator::operator ++ (int) /*postfix*/ { if (!isValid()) return *this; QxtBdbHashIterator d = *this; this->operator++(); return d; } template QxtBdbHashIterator & QxtBdbHashIterator::operator += (int j) { // if j is negative it should subtract as apposed to do nothing if(j < 0) return this->operator-=(j*(-1)); for (int i = 0;i < j;i++) this->operator++(); return *this; } template QxtBdbHashIterator QxtBdbHashIterator::operator - (int j) const { // if j is negative, then we should add as opposed to do noting... I really need to learn to spell "opposed" correctly more regularly... hmm.. if(j < 0) return this->operator+(j*(-1)); QxtBdbHashIterator d = *this; for (int i = 0;i < j;i++) --d; return d; } template QxtBdbHashIterator & QxtBdbHashIterator::operator -- () /*prefix*/ { if (!isValid()) return *this; if (!qxt_d().db->get((void*)0, 0, 0, 0, DB_PREV, qxt_d().dbc)) qxt_d().invalidate(); return *this; } template QxtBdbHashIterator QxtBdbHashIterator::operator -- (int) /*postfix*/ { if (!isValid()) return *this; QxtBdbHashIterator d = *this; this->operator--(); return d; } template QxtBdbHashIterator & QxtBdbHashIterator::operator -= (int j) { // if j is negative, we should add if(j < 0) return this->operator+=(j*(-1)); for (int i = 0;i < j;i++) this->operator--(); return *this; } template QxtBdbHashIterator QxtBdbHashIterator::erase() { BerkeleyDB::DBC * newdbc; qxt_d().dbc->c_dup(qxt_d().dbc, &newdbc, DB_POSITION); QxtBdbHashIterator d(newdbc, qxt_d().db); qxt_d().dbc->del(qxt_d().dbc, NULL); ++d; qxt_d().invalidate(); return d; } template QxtBdbHashIterator::QxtBdbHashIterator(BerkeleyDB::DBC* dbc, QxtBdb * p) { qxt_d = new QxtBdbHashIteratorPrivate; qxt_d().dbc = dbc; qxt_d().db = p; meta_id_key = qMetaTypeId(); meta_id_val = qMetaTypeId(); } #endif libqxt-0.6.2/src/berkeley/qxtbdbtree.cpp000066400000000000000000000173041215241066400202710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtBerkeley module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtbdbtree.h" /*! \class QxtBdbTree \inmodule QxtBerkeley \brief The QxtBdbTree class is a template berkeley container for tree structured data The template argument must be registered with the Qt meta system. You may not touch the file while a QxtBdbTree instance is running on it. Example usage: \code QxtBdbTree db("test.db"); db.root().append("fooooo").append("bla"); db.dumpTree(); //try this if you are unsure, how the data will look like \endcode There is an extensive example in /examples/berkeley/xmlstorage All functions of this class are thread safe. Calling open() multiple times is undefined. An iterator may only be used from one thread at once, but you can have multiple iterators. TODO: {implicitshared} \sa QxtBdbTreeIterator */ /*! \fn QxtBdbTree::QxtBdbTree() Constructs an invalid QxtBdbTree */ /*! \fn QxtBdbTree::QxtBdbTree (QString file) Constructs a QxtBdbTree, and opens the \a file specified as its database. */ /*! \fn bool QxtBdbTree::open (QString file) Opens the specified \a file. Returns \c true on success and \c false on failure. \bold {Note:} a sanity check is performed before opening the file. */ /*! \fn void QxtBdbTree::clear() Erase all records. This does not delete the underlying file. */ /*! \fn bool QxtBdbTree::flush() Flushes the underlying DB file. All changes are synced to disk. */ /*! \fn QxtBdbTreeIterator QxtBdbTree::root() const Returns the rootnode, which is, similar to QAbstractItemModel, invalid and has no data itself. */ /*! \fn void QxtBdbTree::dumpTree() const Outputs the contents of the database as flat file, and as iterateable tree onto qDebug(). This function assumes, the class used for template initialisation implements the QDebug<< operator */ /*! \class QxtBdbTreeIterator \inmodule QxtBerkeley \brief The QxtBdbTreeIterator class provides a tree iterator on QxtBdbtree TODO: {implicitshared} \sa QxtBdbTree */ /*! \fn QxtBdbTreeIterator::QxtBdbTreeIterator() Constructs an invalid QxtBdbTreeIterator It's an error to use this to iterate, access data, etc.. */ /*! \fn QxtBdbTreeIterator::~QxtBdbTreeIterator() Destructs the iterator. The underlying cursors will be closed. */ /*! \fn QxtBdbTreeIterator::QxtBdbTreeIterator(const QxtBdbTreeIterator & other) Copies the \a other iterator. The underlying cursor is duped, meaning the position will be copied, but the copy can be used independently. */ /*! \fn QxtBdbTreeIterator & QxtBdbTreeIterator::operator= ( const QxtBdbTreeIterator & other ) Copies the \a other iterator. The underlying cursor is duped, meaning the position will be copied, but the copy can be used independently */ /*! \fn bool QxtBdbTreeIterator::isValid() const Returns \c true if the iterator seems to point to a valid location. Calls to value() might fail anyway (but not crash), in case of concurrent access. If you want to be 100% sure value() will return valid data, while using multiple threads, then you have to track changes yourself. */ /*! \fn QxtBdbTreeIterator::operator T() const \sa value() */ /*! \fn T QxtBdbTreeIterator::value() const Returns the value, the iterator is currently pointing to. It is an error to call value() when isValid() returns \c false. In case an database error ocures, like the item been deleted, value() will return a default constructed T. */ /*! \fn QxtBdbTreeIterator QxtBdbTreeIterator::parent () const Returns the parent of this item, or an invalid QxtBdbTreeIterator if this is the root item. */ /*! \fn QxtBdbTreeIterator QxtBdbTreeIterator::next () const Returns the next sibling of this item, or an invalid QxtBdbTreeIterator if this is the last one. */ /*! \fn QxtBdbTreeIterator QxtBdbTreeIterator::previous () const Returns the previous sibling of this item, or an invalid QxtBdbTreeIterator if this is the last one. */ /*! \fn QxtBdbTreeIterator QxtBdbTreeIterator::child () const Returns the first child of this item, or an invalid QxtBdbTreeIterator if there are none. */ /*! \fn QxtBdbTreeIterator QxtBdbTreeIterator::operator + ( int j ) const Returns an iterator, \a j items next to this one. If there is no such item, the returned iterator is invalid. \sa next() */ /*! \fn QxtBdbTreeIterator & QxtBdbTreeIterator::operator ++ () This prefix operator increments the item by one. If there are no more items, the iterator becomes invalid. */ /*! \fn QxtBdbTreeIterator QxtBdbTreeIterator::operator ++ (int) This postfix operator makes a copy of the item, then increments itself and returns the copy. If there are no more items, the iterator becomes invalid. */ /*! \fn QxtBdbTreeIterator & QxtBdbTreeIterator::operator += ( int j ) Increments the item by \a j. If there are no more items, the iterator becomes invalid. */ /*! \fn QxtBdbTreeIterator QxtBdbTreeIterator::operator - ( int j ) const Returns an iterator, \a j previous next to this one. If there is no such item, the returnediterator is invalid. \sa previous() */ /*! \fn QxtBdbTreeIterator & QxtBdbTreeIterator::operator -- () This prefix operator decrements the item by one. If there are no more items, the iterator becomes invalid. */ /*! \fn QxtBdbTreeIterator QxtBdbTreeIterator::operator -- (int) This postfix operator makes a copy of the item, then decrements itself and returns the copy. If there are no more items, the iterator becomes invalid. */ /*! \fn QxtBdbTreeIterator & QxtBdbTreeIterator::operator -= ( int j ) Decrements the item by \a j. If there are no more items, the iterator becomes invalid. */ /*! \fn QxtBdbTreeIterator QxtBdbTreeIterator::append (const T & item ) Appends an \a item to the children of this one, and returns an iterator to it. If insertion fails, an invalid iterator is returned. */ /*! \fn QxtBdbTreeIterator QxtBdbTreeIterator::erase() TODO returns */ /*! \fn void QxtBdbTreeIterator::invalidate() TODO */ /*! \fn quint64 QxtBdbTreeIterator::level() const TODO returns */ /*! \fn QxtBdbTreeIterator QxtBdbTreeIterator::prepend(const T& t) TODO \a t */ /*! \fn bool QxtBdbTreeIterator::setValue(T value) TODO \a value */ libqxt-0.6.2/src/berkeley/qxtbdbtree.h000066400000000000000000000414061215241066400177360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtBerkeley module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QxtBdbTree_H_Guard_pyxvby #define QxtBdbTree_H_Guard_pyxvby #include #include #include #include #include "qxtbdb.h" template class QxtBdbTreeIterator; template class QxtBdbTree { public: QxtBdbTree(); QxtBdbTree(QString file); bool open(QString file); void clear(); bool flush(); QxtBdbTreeIterator root() const; void dumpTree() const; private: int meta_id; QxtSharedPrivate qxt_d; void debugprintchildren(QxtBdbTreeIterator it) const; }; template QxtBdbTree::QxtBdbTree() { meta_id = qMetaTypeId(); qxt_d = new QxtBdb; } template QxtBdbTree::QxtBdbTree(QString file) { meta_id = qMetaTypeId(); qxt_d = new QxtBdb; open(file); } template bool QxtBdbTree::open(QString file) { BerkeleyDB::u_int32_t f; qxt_d().db->get_flags(qxt_d().db, &f); f |= DB_DUP; qxt_d().db->set_flags(qxt_d().db, f); bool r = qxt_d().open(file, QxtBdb::CreateDatabase | QxtBdb::LockFree); return r; } template void QxtBdbTree::clear() { if (!qxt_d().isOpen) return; BerkeleyDB::u_int32_t x; qxt_d().db->truncate(qxt_d().db, NULL, &x, 0); } template bool QxtBdbTree::flush() { return qxt_d().flush(); } template QxtBdbTreeIterator QxtBdbTree::root() const { QxtBdbTreeIterator r(0, const_cast(&qxt_d())); r.root = true; return r; } template void QxtBdbTree::debugprintchildren(QxtBdbTreeIterator it) const { it = it.child(); while (it.isValid()) { QByteArray p; for (quint64 x = 0; x < it.level();x++) { p += " |"; } qDebug() << p.data() << "-" << it.value(); debugprintchildren(it); ++it; } } /* |-n1 |-n2 | |-n3 |-n1 | |-n1 | | |-n3 | | | -n2 */ template void QxtBdbTree::dumpTree() const { BerkeleyDB::DBC *cursor; qxt_d().db->cursor(qxt_d().db, NULL, &cursor, 0); if (!qxt_d().get((void*)0, 0, 0, 0, DB_FIRST, cursor)) { return; } QxtBdbTreeIterator k(cursor, const_cast(&qxt_d())); qDebug() << "\r\nQxtBdbTree<" << QMetaType::typeName(qMetaTypeId()) << ">::dumpTree()\r\n"; qDebug() << "Level\t \t Value"; Q_FOREVER { qDebug() << k.level() << " \t->\t" << k.value(); if (!qxt_d().get((void*)0, 0, 0, 0, DB_NEXT, cursor)) break; } qDebug() << "\r\n"; qDebug() << "Iterate"; debugprintchildren(root()); qDebug() << "\r\n"; } template class QxtBdbTreeIterator { public: QxtBdbTreeIterator(); ~QxtBdbTreeIterator(); QxtBdbTreeIterator(const QxtBdbTreeIterator & other); QxtBdbTreeIterator & operator= (const QxtBdbTreeIterator & other); bool isValid() const; operator T() const; T value() const; bool setValue(T); QxtBdbTreeIterator parent() const; QxtBdbTreeIterator next() const; QxtBdbTreeIterator previous() const; QxtBdbTreeIterator child() const; QxtBdbTreeIterator operator + (int j) const; QxtBdbTreeIterator & operator ++ (); QxtBdbTreeIterator operator ++ (int); QxtBdbTreeIterator & operator += (int j); QxtBdbTreeIterator operator - (int j) const; QxtBdbTreeIterator & operator -- (); QxtBdbTreeIterator operator -- (int); QxtBdbTreeIterator & operator -= (int j); QxtBdbTreeIterator append(const T & t); QxtBdbTreeIterator prepend(const T & t); QxtBdbTreeIterator erase(); protected: quint64 level() const; void invalidate() { if (dbc) dbc->c_close(dbc); dbc = 0; } private: friend class QxtBdbTree; QxtBdbTreeIterator(BerkeleyDB::DBC*, QxtBdb * p); QxtBdbTreeIterator croot() const; int meta_id; QxtBdb * db; BerkeleyDB::DBC *dbc; bool root; /*won't work. no support in bdb*/ bool operator== (const QxtBdbTreeIterator & other) const { return false; } bool operator!= (const QxtBdbTreeIterator & other) const { return false; } }; template QxtBdbTreeIterator::QxtBdbTreeIterator() { dbc = 0; db = 0; root = false; meta_id = qMetaTypeId(); } template QxtBdbTreeIterator::~QxtBdbTreeIterator() { invalidate(); } template QxtBdbTreeIterator::QxtBdbTreeIterator(const QxtBdbTreeIterator & other) { dbc = 0; db = 0; root = false; meta_id = qMetaTypeId(); db = other.db; root = other.root; if (other.dbc) { other.dbc->c_dup(other.dbc, &dbc, DB_POSITION); } } template QxtBdbTreeIterator::QxtBdbTreeIterator(BerkeleyDB::DBC* dbc, QxtBdb * p) { this->dbc = dbc; db = p; root = false; meta_id = qMetaTypeId(); } template QxtBdbTreeIterator QxtBdbTreeIterator::croot() const { QxtBdbTreeIterator k = *this; k.invalidate(); k.root = true; return k; } template QxtBdbTreeIterator & QxtBdbTreeIterator::operator= (const QxtBdbTreeIterator & other) { invalidate(); db = other.db; root = other.root; if (other.dbc) { other.dbc->c_dup(other.dbc, &dbc, DB_POSITION); } return *this; } template bool QxtBdbTreeIterator::isValid() const { if (root) return true; return (dbc != 0 && db != 0); } template QxtBdbTreeIterator::operator T() const { return value(); } template T QxtBdbTreeIterator::value() const { if (!dbc) { qWarning("QxtBdbTreeIterator::value() on invalid iterator "); return T(); } BerkeleyDB::DBT dbkey, dbvalue; memset(&dbkey, 0, sizeof(BerkeleyDB::DBT)); memset(&dbvalue, 0, sizeof(BerkeleyDB::DBT)); dbvalue.ulen = 0; dbvalue.flags = DB_DBT_USERMEM; dbkey.ulen = 0; dbkey.flags = DB_DBT_USERMEM; int ret = dbc->c_get(dbc, &dbkey, &dbvalue, DB_CURRENT); if (ret != DB_BUFFER_SMALL) return T(); dbvalue.ulen = dbvalue.size; dbvalue.data =::malloc(dbvalue.size); dbkey.ulen = dbkey.size; dbkey.data =::malloc(dbkey.size); ret = dbc->c_get(dbc, &dbkey, &dbvalue, DB_CURRENT); T t = QxtBdb::qxtMetaLoad((quint64*)dbvalue.data + 1, dbvalue.size - sizeof(quint64)); ::free(dbkey.data); ::free(dbvalue.data); if (ret != 0) return T(); return t; } template bool QxtBdbTreeIterator::setValue(T t) { if (!dbc) { qWarning("QxtBdbTreeIterator::setValue() on invalid iterator "); return false; } BerkeleyDB::DBT dbkey, dbvalue; ::memset(&dbkey, 0, sizeof(BerkeleyDB::DBT)); ::memset(&dbvalue, 0, sizeof(BerkeleyDB::DBT)); char uselesszero = 0; dbkey.data = &uselesszero; dbkey.size = sizeof(char); dbkey.ulen = 0; dbkey.flags = DB_DBT_USERMEM; quint64 mylevel = level(); QByteArray d = QxtBdb::qxtMetaSave(t); dbvalue.size = sizeof(quint64) + d.size(); dbvalue.ulen = dbvalue.size; dbvalue.data =::malloc(dbvalue.size); ::memcpy(dbvalue.data, &mylevel, sizeof(quint64)); ::memcpy((quint64*)dbvalue.data + 1, d.data(), d.size()); dbvalue.flags = DB_DBT_USERMEM; int ret = 234525; ret = dbc->c_put(dbc, &dbkey, &dbvalue, DB_CURRENT); ::free(dbvalue.data); if (ret != 0) return false; return true; } template QxtBdbTreeIterator QxtBdbTreeIterator::parent() const { if (root) return croot(); if (!dbc) return QxtBdbTreeIterator(); QxtBdbTreeIterator d(*this); quint64 lvl = level(); Q_FOREVER { #if DB_VERSION_MINOR > 5 if (!d.db->get((void*)0, 0, 0, 0, DB_PREV_DUP, d.dbc)) #else if (!d.db->get((void*)0, 0, 0, 0, DB_PREV, d.dbc)) #endif return croot(); if (d.level() == lvl - 1) break; } return d; } template QxtBdbTreeIterator QxtBdbTreeIterator::next() const { if (root) return QxtBdbTreeIterator(); return QxtBdbTreeIterator(*this) + 1; } template QxtBdbTreeIterator QxtBdbTreeIterator::previous() const { if (root) return QxtBdbTreeIterator(); return QxtBdbTreeIterator(*this) - 1; } template QxtBdbTreeIterator QxtBdbTreeIterator::child() const { QxtBdbTreeIterator d(*this); if (root) { BerkeleyDB::DBC *cursor; db->db->cursor(db->db, NULL, &cursor, 0); d = QxtBdbTreeIterator(cursor, db); if (!d.db->get((void*)0, 0, 0, 0, DB_FIRST, d.dbc)) { return QxtBdbTreeIterator(); } } else { if (!dbc) return QxtBdbTreeIterator(); quint64 lvl = level(); if (!d.db->get((void*)0, 0, 0, 0, DB_NEXT_DUP, d.dbc)) { return QxtBdbTreeIterator(); } if (d.level() != lvl + 1) return QxtBdbTreeIterator(); } return d; } template QxtBdbTreeIterator QxtBdbTreeIterator::operator + (int j) const { if(j < 0) return this->operator-(j*(-1)); QxtBdbTreeIterator d(*this); for (int i = 0;i < j;i++) ++d; return d; } template QxtBdbTreeIterator & QxtBdbTreeIterator::operator ++ () { if (root) { invalidate(); return *this; } if (!dbc) return *this; quint64 before = level(); Q_FOREVER { if (!db->get((void*)0, 0, 0, 0, DB_NEXT_DUP, dbc)) { invalidate(); break; } if (before == level()) break; if (before > level()) { invalidate(); break; } } return *this; } template QxtBdbTreeIterator QxtBdbTreeIterator::operator ++ (int) { QxtBdbTreeIterator d(*this); operator++(); return d; } template QxtBdbTreeIterator & QxtBdbTreeIterator::operator += (int j) { if(j < 0) return this->operator-=(j*(-1)); for (int i = 0;i < j;i++) operator++(); return *this; } template QxtBdbTreeIterator QxtBdbTreeIterator::operator - (int j) const { if(j < 0) return this->operator+(j*(-1)); QxtBdbTreeIterator d(*this); for (int i = 0;i < j;i++) --d; return d; } template QxtBdbTreeIterator & QxtBdbTreeIterator::operator -- () { if (root) return *this; if (!dbc) return *this; int lvl = level(); #if DB_VERSION_MINOR > 5 do { if (!db->get((void*)0, 0, 0, 0, DB_PREV_DUP, dbc)) { invalidate(); break; } } while (lvl != level()); #else do { if (!db->get((void*)0, 0, 0, 0, DB_PREV, dbc)) { invalidate(); break; } } while (lvl != level()); #endif return *this; } template QxtBdbTreeIterator QxtBdbTreeIterator::operator -- (int) { QxtBdbTreeIterator d(*this); operator--(); return d; } template QxtBdbTreeIterator & QxtBdbTreeIterator::operator -= (int j) { if(j < 0) return this->operator+=(j*(-1)); for (int i = 0;i < j;i++) operator--(); return *this; } template QxtBdbTreeIterator QxtBdbTreeIterator::append(const T & t) { Q_ASSERT(isValid()); BerkeleyDB::DBT dbkey, dbvalue; ::memset(&dbkey, 0, sizeof(BerkeleyDB::DBT)); ::memset(&dbvalue, 0, sizeof(BerkeleyDB::DBT)); char uselesszero = 0; dbkey.data = &uselesszero; dbkey.size = sizeof(char); dbkey.ulen = 0; dbkey.flags = DB_DBT_USERMEM; quint64 newlevel = level() + 1; QByteArray d = QxtBdb::qxtMetaSave(t); dbvalue.size = sizeof(quint64) + d.size(); dbvalue.ulen = dbvalue.size; dbvalue.data =::malloc(dbvalue.size); ::memcpy(dbvalue.data, &newlevel, sizeof(quint64)); ::memcpy((quint64*)dbvalue.data + 1, d.data(), d.size()); dbvalue.flags = DB_DBT_USERMEM; int ret = 234525; QxtBdbTreeIterator e = *this; if (dbc) { while (e.db->get((void*)0, 0, 0, 0, DB_NEXT_DUP, e.dbc)) { if (e.level() <= level()) { #if DB_VERSION_MINOR > 5 e.db->get((void*)0, 0, 0, 0, DB_PREV_DUP, e.dbc); #else e.db->get((void*)0, 0, 0, 0, DB_PREV, e.dbc); #endif break; } } ret = dbc->c_put(e.dbc, &dbkey, &dbvalue, DB_AFTER); } else if (root) { ret = db->db->put(db->db, NULL, &dbkey, &dbvalue, NULL); BerkeleyDB::DBC *cursor; db->db->cursor(db->db, NULL, &cursor, 0); if (db->get((void*)0, 0, 0, 0, DB_LAST, cursor)) e = QxtBdbTreeIterator(cursor, db); } ::free(dbvalue.data); if (ret != 0) { qWarning("QxtBdbTreeIterator::append failed %i", ret); return QxtBdbTreeIterator(); } return e; } template QxtBdbTreeIterator QxtBdbTreeIterator::prepend(const T & t) { if (!dbc) return QxtBdbTreeIterator(); QxtBdbTreeIterator e(*this); BerkeleyDB::DBT dbkey, dbvalue; ::memset(&dbkey, 0, sizeof(BerkeleyDB::DBT)); ::memset(&dbvalue, 0, sizeof(BerkeleyDB::DBT)); char uselesszero = 0; dbkey.data = &uselesszero; dbkey.size = sizeof(char); dbkey.ulen = 0; dbkey.flags = DB_DBT_USERMEM; quint64 newlevel = level(); QByteArray d = QxtBdb::qxtMetaSave(t); dbvalue.size = sizeof(quint64) + d.size(); dbvalue.ulen = dbvalue.size; dbvalue.data =::malloc(dbvalue.size); ::memcpy(dbvalue.data, &newlevel, sizeof(quint64)); ::memcpy((quint64*)dbvalue.data + 1, d.data(), d.size()); dbvalue.flags = DB_DBT_USERMEM; int ret = 234525; ret = e.dbc->c_put(e.dbc, &dbkey, &dbvalue, DB_BEFORE); ::free(dbvalue.data); if (ret != 0) return QxtBdbTreeIterator(); return e; } template quint64 QxtBdbTreeIterator::level() const { if (!dbc) return 0; BerkeleyDB::DBT dbkey, dbvalue; memset(&dbkey, 0, sizeof(BerkeleyDB::DBT)); memset(&dbvalue, 0, sizeof(BerkeleyDB::DBT)); dbvalue.size = 0; dbvalue.size = 0; dbvalue.ulen = 0; dbvalue.flags = DB_DBT_USERMEM; dbkey.ulen = 0; dbkey.flags = DB_DBT_USERMEM; int ret = dbc->c_get(dbc, &dbkey, &dbvalue, DB_CURRENT); if (ret != DB_BUFFER_SMALL) qFatal("QxtBdbTreeIterator::level() %s", qPrintable(QxtBdb::dbErrorCodeToString(ret))); dbvalue.ulen = dbvalue.size; dbvalue.data =::malloc(dbvalue.size); dbkey.ulen = dbkey.size; dbkey.data =::malloc(dbkey.size); ret = dbc->c_get(dbc, &dbkey, &dbvalue, DB_CURRENT); quint64 lvl; ::memcpy(&lvl, dbvalue.data, sizeof(quint64)); ::free(dbkey.data); ::free(dbvalue.data); if (ret != 0) return 0; return lvl; } template QxtBdbTreeIterator QxtBdbTreeIterator::erase() { Q_ASSERT(isValid()); quint64 before = level(); Q_FOREVER { int ret = dbc->c_del(dbc, 0); if (ret != 0) { qWarning("QxtBdbTreeIterator::erase() failed %s", qPrintable(QxtBdb::dbErrorCodeToString(ret))); return QxtBdbTreeIterator(); } if (!db->get((void*)0, 0, 0, 0, DB_NEXT_DUP, dbc)) return *this; if (level() <= before) return *this; } Q_ASSERT(false); return *this; } #endif libqxt-0.6.2/src/berkeley/qxtberkeley.h000066400000000000000000000025231215241066400201260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtBerkeley module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTBERKELEY_H_INCLUDED #define QXTBERKELEY_H_INCLUDED #include "qxtbdb.h" #include "qxtbdbhash.h" #include "qxtbdbtree.h" #endif // QXTBERKELEY_H_INCLUDED libqxt-0.6.2/src/core/000077500000000000000000000000001215241066400145425ustar00rootroot00000000000000libqxt-0.6.2/src/core/core.pri000066400000000000000000000065111215241066400162110ustar00rootroot00000000000000INCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += qxtabstractconnectionmanager.h HEADERS += qxtabstractfileloggerengine.h HEADERS += qxtabstractiologgerengine.h HEADERS += qxtabstractsignalserializer.h HEADERS += qxtalgorithms.h HEADERS += qxtbasicfileloggerengine.h HEADERS += qxtbasicstdloggerengine.h HEADERS += qxtboundcfunction.h HEADERS += qxtboundfunction.h HEADERS += qxtboundfunctionbase.h HEADERS += qxtcore.h HEADERS += qxtcommandoptions.h HEADERS += qxtcsvmodel.h HEADERS += qxtdaemon.h HEADERS += qxtdatastreamsignalserializer.h HEADERS += qxtdeplex.h HEADERS += qxtdeplex_p.h HEADERS += qxterror.h HEADERS += qxtfifo.h HEADERS += qxtglobal.h HEADERS += qxthmac.h HEADERS += qxtjson.h HEADERS += qxtjob.h HEADERS += qxtjob_p.h HEADERS += qxtlinesocket.h HEADERS += qxtlinesocket_p.h HEADERS += qxtlinkedtree.h HEADERS += qxtlocale.h HEADERS += qxtlocale_data_p.h HEADERS += qxtlogger.h HEADERS += qxtlogger_p.h HEADERS += qxtloggerengine.h HEADERS += qxtlogstream.h HEADERS += qxtlogstream_p.h HEADERS += qxtmetaobject.h HEADERS += qxtmetatype.h HEADERS += qxtmodelserializer.h HEADERS += qxtmultisignalwaiter.h HEADERS += qxtnamespace.h HEADERS += qxtnull.h HEADERS += qxtnullable.h HEADERS += qxtpairlist.h HEADERS += qxtpimpl.h HEADERS += qxtpipe.h HEADERS += qxtpipe_p.h HEADERS += qxtpointerlist.h HEADERS += qxtsharedprivate.h HEADERS += qxtsignalgroup.h HEADERS += qxtsignalwaiter.h HEADERS += qxtslotjob.h HEADERS += qxtslotjob_p.h HEADERS += qxtslotmapper.h HEADERS += qxtstdio.h HEADERS += qxtstdio_p.h HEADERS += qxtstdstreambufdevice.h HEADERS += qxttimer.h HEADERS += qxttypelist.h HEADERS += qxtrpcservice.h HEADERS += qxtrpcservice_p.h HEADERS += qxtxmlfileloggerengine.h SOURCES += qxtabstractconnectionmanager.cpp SOURCES += qxtabstractfileloggerengine.cpp SOURCES += qxtabstractiologgerengine.cpp SOURCES += qxtbasicfileloggerengine.cpp SOURCES += qxtbasicstdloggerengine.cpp SOURCES += qxtcommandoptions.cpp SOURCES += qxtcsvmodel.cpp SOURCES += qxtdaemon.cpp SOURCES += qxtdatastreamsignalserializer.cpp SOURCES += qxtdeplex.cpp SOURCES += qxterror.cpp SOURCES += qxtfifo.cpp SOURCES += qxtglobal.cpp SOURCES += qxthmac.cpp SOURCES += qxtlocale.cpp SOURCES += qxtjson.cpp SOURCES += qxtjob.cpp SOURCES += qxtlinesocket.cpp SOURCES += qxtlinkedtree.cpp SOURCES += qxtlogger.cpp SOURCES += qxtloggerengine.cpp SOURCES += qxtlogstream.cpp SOURCES += qxtmetaobject.cpp SOURCES += qxtmodelserializer.cpp SOURCES += qxtmultisignalwaiter.cpp SOURCES += qxtnull.cpp SOURCES += qxtpipe.cpp SOURCES += qxtpointerlist.cpp SOURCES += qxtsignalgroup.cpp SOURCES += qxtsignalwaiter.cpp SOURCES += qxtslotjob.cpp SOURCES += qxtslotmapper.cpp SOURCES += qxtstdio.cpp SOURCES += qxtstdstreambufdevice.cpp SOURCES += qxttimer.cpp SOURCES += qxtrpcservice.cpp SOURCES += qxtxmlfileloggerengine.cpp !symbian { # QxtSerialDevice and QxtFileLock # are disabled for Symbian pending implementation HEADERS += qxtfilelock.h HEADERS += qxtfilelock_p.h SOURCES += qxtfilelock.cpp unix { HEADERS += qxtserialdevice.h HEADERS += qxtserialdevice_p.h SOURCES += qxtfilelock_unix.cpp SOURCES += qxtserialdevice.cpp SOURCES += qxtserialdevice_unix.cpp } win32 { SOURCES += qxtfilelock_win.cpp } } libqxt-0.6.2/src/core/core.pro000066400000000000000000000002651215241066400162170ustar00rootroot00000000000000CLEAN_TARGET = QxtCore DEFINES += BUILD_QXT_CORE QT = core QXT = CONVENIENCE += $$CLEAN_TARGET include(core.pri) include(../qxtbase.pri) libqxt-0.6.2/src/core/qxtabstractconnectionmanager.cpp000066400000000000000000000112171215241066400232230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtabstractconnectionmanager.h" #include #include /*! * \class QxtAbstractConnectionManager * \inmodule QxtCore * \brief The QxtAbstractConnectionManager class is an interface for classes that maintain connection pools * * QxtAbstractConnectionManager is a standardized interface for accepting and tracking * incoming connections. * * Each incoming connection is assigned an arbitrary, opaque client ID number. This * number can be used to retrieve the QIODevice associated with it. A list of IDs * for all current connections can be retrieved with the clients() function. * * As an abstract class, QxtAbstractConnectionManager cannot be used on its own. * Subclasses must implement isAcceptingConnections() to indicate the current listening * status of the connection manager and removeConnection() to perform necessary clean-up * of an established connection before disconnecting. Finally, a subclass must invoke * addConnection() after a new incoming connection has been established and prepared. * * \sa QxtTcpConnectionManager */ class QxtAbstractConnectionManagerPrivate : public QxtPrivate { public: QHash clients; QXT_DECLARE_PUBLIC(QxtAbstractConnectionManager) }; /*! * Constructs a QxtAbstractConnectionManager object with the specified \a parent. */ QxtAbstractConnectionManager::QxtAbstractConnectionManager(QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtAbstractConnectionManager); } /*! * Destructs the connection manager. */ QxtAbstractConnectionManager::~QxtAbstractConnectionManager() { // virtual for subclasses, no need for implementation } /*! * Returns the number of connected clients. */ int QxtAbstractConnectionManager::clientCount() const { return qxt_d().clients.count(); } /*! * Returns a list of client IDs for all connected clients. */ QList QxtAbstractConnectionManager::clients() const { return qxt_d().clients.keys(); } /*! * Returns the QIODevice for the requested \a clientID. */ QIODevice* QxtAbstractConnectionManager::client(quint64 clientID) const { return qxt_d().clients.value(clientID, NULL); } /*! * Disconnects the connection with the specified \a clientID. * * Implementations should invoke this function when the connection should no longer be * used; for instance, when the QIODevice object is destroyed or the connection has been * closed. Code that uses the connection manager service should invoke this function to * close a connection on demand. */ void QxtAbstractConnectionManager::disconnect(quint64 clientID) { QIODevice* device = qxt_d().clients.value(clientID, 0); if (!device) { qWarning() << "QxtAbstractConnectionManager::disconnect: client ID not in use"; return; } qxt_d().clients.remove(clientID); emit disconnected(device, clientID); removeConnection(device, clientID); } /*! * Begins managing a connection. Each \a device must have a unique, non-zero \a clientID, but * beyond this constraint implementations may use any convenient value. Implementations * should invoke this function after establishing a usable connection and performing any * desired initial negotiation. * * This function will emit the newConnection signal after the internal data structures have * been suitably updated. */ void QxtAbstractConnectionManager::addConnection(QIODevice* device, quint64 clientID) { qxt_d().clients[clientID] = device; emit newConnection(device, clientID); } libqxt-0.6.2/src/core/qxtabstractconnectionmanager.h000066400000000000000000000053351215241066400226740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTABSTRACTCONNECTIONMANAGER_H #define QXTABSTRACTCONNECTIONMANAGER_H #include #include QT_FORWARD_DECLARE_CLASS(QIODevice) class QxtAbstractConnectionManagerPrivate; class QXT_CORE_EXPORT QxtAbstractConnectionManager : public QObject { Q_OBJECT public: QxtAbstractConnectionManager(QObject* parent); virtual ~QxtAbstractConnectionManager(); int clientCount() const; QList clients() const; QIODevice* client(quint64 clientID) const; /*! * Returns true if the connection manager is currently accepting connections. * Returns false otherwise. */ virtual bool isAcceptingConnections() const = 0; Q_SIGNALS: /*! * Indicates that the specified device, with the specified client ID, is ready for use. */ void newConnection(QIODevice* device, quint64 clientID); /*! * Indicates that the device with the specified client ID has been disconnected. */ void disconnected(QIODevice* device, quint64 clientID); public Q_SLOTS: void disconnect(quint64 clientID); protected: void addConnection(QIODevice* device, quint64 clientID); /*! * Stops managing a connection. This function is invoked by disconnect(). * Implementations should perform whatever steps are necessary to close the connection * and clean up any internal data structures, including deleting the QIODevice object. */ virtual void removeConnection(QIODevice* device, quint64 clientID) = 0; private: QXT_DECLARE_PRIVATE(QxtAbstractConnectionManager) }; #endif libqxt-0.6.2/src/core/qxtabstractfileloggerengine.cpp000066400000000000000000000107441215241066400230420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtabstractfileloggerengine.h" /*! \class QxtAbstractFileLoggerEngine \brief The QxtAbstractFileLoggerEngine class is the base class of file logger engines. \inmodule QxtCore \sa QxtLogger */ class QxtAbstractFileLoggerEnginePrivate : public QxtPrivate { QXT_DECLARE_PUBLIC(QxtAbstractFileLoggerEngine) public: QString logFile; QIODevice::OpenMode mode; }; /*! Constructs a QxtAbstractFileLoggerEngine with \a fileName and open \a mode. */ QxtAbstractFileLoggerEngine::QxtAbstractFileLoggerEngine(const QString &fileName, QIODevice::OpenMode mode) : QxtAbstractIOLoggerEngine(0) { QXT_INIT_PRIVATE(QxtAbstractFileLoggerEngine); qxt_d().mode = mode; setLogFileName(fileName); } /*! Destructs the file logger engine. */ QxtAbstractFileLoggerEngine::~QxtAbstractFileLoggerEngine() { killLoggerEngine(); } /*! \reimp */ void QxtAbstractFileLoggerEngine::initLoggerEngine() { // Are we already logging to a file? If so, close it and disable logging. killLoggerEngine(); // If the file exists, check if we can write to it. If we can, we append! // If the file doesn't exits, try to create it. // If we can't write to a file, disable this plugin. if (qxt_d().logFile.isEmpty()) return; // if there's no filename, disable the engine until one is given setDevice(new QFile(qxt_d().logFile)); if (!device()->open(qxt_d().mode) || !device()->isWritable()) { killLoggerEngine(); return; } enableLogging(); } /*! \reimp */ void QxtAbstractFileLoggerEngine::killLoggerEngine() { if (device() != 0) { if (device()->isOpen()) device()->close(); delete device(); setDevice(0); } } /*! \reimp */ bool QxtAbstractFileLoggerEngine::isInitialized() const { return (device() != 0); } /*! \reimp */ void QxtAbstractFileLoggerEngine::writeFormatted(QxtLogger::LogLevel level, const QList &messages) { switch (level) { case QxtLogger::ErrorLevel: writeToFile("Error", messages); break; case QxtLogger::WarningLevel: writeToFile("Warning", messages); break; case QxtLogger::CriticalLevel: writeToFile("Critical", messages); break; case QxtLogger::FatalLevel: writeToFile("Fatal", messages); break; case QxtLogger::TraceLevel: writeToFile("Trace", messages); break; case QxtLogger::DebugLevel: writeToFile("Debug", messages); break; case QxtLogger::InfoLevel: writeToFile("Info", messages); break; default: writeToFile(QString(), messages); break; } } /*! Sets the log \a fileName. */ void QxtAbstractFileLoggerEngine::setLogFileName(const QString &fileName) { qxt_d().logFile = fileName; initLoggerEngine(); } /*! Returns the log file name. */ QString QxtAbstractFileLoggerEngine::logFileName() const { return qxt_d().logFile; } /*! \fn virtual void QxtAbstractFileLoggerEngine::writeToFile( const QString &level, const QVariantList &messages ) = 0 Writes \a messages to file with given \a level. This function is called by QxtAbstractFileLoggerEngine. Reimplement this function when creating a subclass of QxtAbstractFileLoggerEngine. */ libqxt-0.6.2/src/core/qxtabstractfileloggerengine.h000066400000000000000000000040611215241066400225020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTABSTRACTFILELOGGERENGINE_H #define QXTABSTRACTFILELOGGERENGINE_H #include "qxtabstractiologgerengine.h" #include "qxtglobal.h" class QxtAbstractFileLoggerEnginePrivate; class QXT_CORE_EXPORT QxtAbstractFileLoggerEngine : public QxtAbstractIOLoggerEngine { QXT_DECLARE_PRIVATE(QxtAbstractFileLoggerEngine) public: QxtAbstractFileLoggerEngine(const QString &fileName, QIODevice::OpenMode mode); ~QxtAbstractFileLoggerEngine(); virtual void initLoggerEngine(); virtual void killLoggerEngine(); virtual bool isInitialized() const; virtual void writeFormatted(QxtLogger::LogLevel level, const QList &messages); void setLogFileName(const QString &fileName); QString logFileName() const; protected: virtual void writeToFile(const QString &level, const QVariantList &messages) = 0; }; #endif // QXTABSTRACTFILELOGGERENGINE_H libqxt-0.6.2/src/core/qxtabstractiologgerengine.cpp000066400000000000000000000042251215241066400225270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtabstractiologgerengine.h" /*! \class QxtAbstractIOLoggerEngine \brief The QxtAbstractIOLoggerEngine class is the base class of IO logger engines. \inmodule QxtCore \sa QxtLogger */ class QxtAbstractIOLoggerEnginePrivate : public QxtPrivate { QXT_DECLARE_PUBLIC(QxtAbstractIOLoggerEngine) public: QxtAbstractIOLoggerEnginePrivate(); QIODevice *io_device; }; QxtAbstractIOLoggerEnginePrivate::QxtAbstractIOLoggerEnginePrivate() : io_device(0) { } /*! Constructs a QxtAbstractIOLoggerEngine with \a device. */ QxtAbstractIOLoggerEngine::QxtAbstractIOLoggerEngine(QIODevice *device) { QXT_INIT_PRIVATE(QxtAbstractFileLoggerEngine); setDevice(device); } /*! Sets the IO \a device. */ void QxtAbstractIOLoggerEngine::setDevice(QIODevice *device) { qxt_d().io_device = device; } /*! Returns the IO device. */ QIODevice *QxtAbstractIOLoggerEngine::device() const { return qxt_d().io_device; } libqxt-0.6.2/src/core/qxtabstractiologgerengine.h000066400000000000000000000032001215241066400221640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTABSTRACTIOLOGGERENGINE_H #define QXTABSTRACTIOLOGGERENGINE_H #include "qxtloggerengine.h" #include "qxtglobal.h" class QxtAbstractIOLoggerEnginePrivate; class QXT_CORE_EXPORT QxtAbstractIOLoggerEngine : public QxtLoggerEngine { QXT_DECLARE_PRIVATE(QxtAbstractIOLoggerEngine) public: QxtAbstractIOLoggerEngine(QIODevice *device = 0); void setDevice(QIODevice *device); QIODevice* device() const; }; #endif // QXTABSTRACTIOLOGGERENGINE_H libqxt-0.6.2/src/core/qxtabstractsignalserializer.h000066400000000000000000000112261215241066400225450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTABSTRACTSIGNALSERIALIZER_H #define QXTABSTRACTSIGNALSERIALIZER_H #include #include #include #include #include #include /*! * \class QxtAbstractSignalSerializer * \inmodule QxtCore * \brief The QxtAbstractSignalSerializer class provides an interface for classes that convert signals to a binary form. * * QxtAbstractSignalSerializer is an abstract interface used by, for example, QxtRPCService to convert signals into a * serialized binary format suitable for storing or transmitting over an I/O device. * * Qxt provides a default implementation in the form of QxtDataStreamSignalSerializer, which is generally sufficient for * most applications. Implement other subclasses of QxtAbstractSignalSerializer to allow QxtRPCService and similar tools * to integrate with existing protocols. */ class QXT_CORE_EXPORT QxtAbstractSignalSerializer { public: /*! * The first half of QxtAbstractSignalSerializer::DeserializedData is the name of the deserialized signal. The * second half is an array of QVariants containing the parameters of the signal. */ typedef QPair > DeserializedData; /*! * Destroys the QxtAbstractSignalSerializer. */ virtual ~QxtAbstractSignalSerializer() {} /*! * Serializes a signal into a form suitable for sending to an I/O device. */ virtual QByteArray serialize(const QString& fn, const QVariant& p1 = QVariant(), const QVariant& p2 = QVariant(), const QVariant& p3 = QVariant(), const QVariant& p4 = QVariant(), const QVariant& p5 = QVariant(), const QVariant& p6 = QVariant(), const QVariant& p7 = QVariant(), const QVariant& p8 = QVariant()) const = 0; /*! * Deserializes binary data into a signal name and a list of parameters. When implementing this function, be sure * to remove the processed portion of the data from the reference parameter. * Return QxtAbstractSignalSerializer::NoOp() if the deserialized data does not invoke a signal. * Return QxtAbstractSignalSerializer::ProtocolError() if the protocol has been violated and the connection should * be severed. */ virtual DeserializedData deserialize(QByteArray& data) = 0; /*! * Indicates whether the data currently in the buffer can be deserialized. */ virtual bool canDeserialize(const QByteArray& buffer) const = 0; /*! * Returns an object that indicates that the deserialized data does not invoke a signal. */ static inline DeserializedData NoOp() { static DeserializedData rv = qMakePair(QString(), QList()); return rv; } /*! * Returns an object that indicates that the deserialized data indicates a fatal protocol error. */ static inline DeserializedData ProtocolError() { static DeserializedData rv = qMakePair(QString(), QList() << QVariant()); return rv; } /*! * Checks to see if the provided object does not invoke a signal. */ static inline bool isNoOp(const DeserializedData& value) { return value.first.isEmpty() && value.second.isEmpty(); } /*! * Checks to see if the provided object indicates a fatal protocol error. */ static inline bool isProtocolError(const DeserializedData& value) { return value.first.isEmpty() && !value.second.isEmpty(); } }; #endif libqxt-0.6.2/src/core/qxtalgorithms.h000066400000000000000000000047701215241066400176310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTALGORITHMS_H #define QXTALGORITHMS_H template InputIterator qxtMinimum(InputIterator begin, InputIterator end, LessThan lessThan) { InputIterator iter = begin, rv = begin; while ((++iter) != end) { if (lessThan(*iter, *rv)) rv = iter; } return rv; } template InputIterator qxtMinimum(InputIterator begin, InputIterator end) { InputIterator iter = begin, rv = begin; while ((++iter) != end) { if ((*iter) < (*rv)) rv = iter; } return rv; } template typename Container::const_iterator qxtMinimum(const Container& container) { return qxtMinimum(container.begin(), container.end()); } template InputIterator qxtMaximum(InputIterator begin, InputIterator end, GreaterThan greaterThan) { return qxtMinimum(begin, end, greaterThan); } template InputIterator qxtMaximum(InputIterator begin, InputIterator end) { InputIterator iter = begin, rv = begin; while ((++iter) != end) { if ((*iter) > (*rv)) rv = iter; } return rv; } template typename Container::const_iterator qxtMaximum(const Container& container) { return qxtMinimum(container.begin(), container.end()); } #endif libqxt-0.6.2/src/core/qxtbasicfileloggerengine.cpp000066400000000000000000000062331215241066400223160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtbasicfileloggerengine.h" #include /*! \class QxtBasicFileLoggerEngine \brief The QxtBasicFileLoggerEngine class provides a basic file logger engine. \inmodule QxtCore Example basic file log output: \code [22:38:33.159] [Error] Unknown error [22:51:43.488] [Debug] What's going on? Hi there! \endcode \sa QxtLogger */ class QxtBasicFileLoggerEnginePrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtBasicFileLoggerEngine) QString dateFormat; }; /*! Constructs a basic file logger engine with \a fileName. */ QxtBasicFileLoggerEngine::QxtBasicFileLoggerEngine(const QString &fileName) : QxtAbstractFileLoggerEngine(fileName, QIODevice::ReadWrite | QIODevice::Append | QIODevice::Unbuffered) { QXT_INIT_PRIVATE(QxtBasicFileLoggerEngine); qxt_d().dateFormat = "hh:mm:ss.zzz"; } /*! Returns the date format in use by this logger engine. \sa QDateTime::toString() */ QString QxtBasicFileLoggerEngine::dateFormat() const { return qxt_d().dateFormat; } /*! Sets the date \a format used by this logger engine. \sa QDateTime::toString() */ void QxtBasicFileLoggerEngine::setDateFormat(const QString& format) { qxt_d().dateFormat = format; } /*! \reimp */ void QxtBasicFileLoggerEngine::writeToFile(const QString &level, const QVariantList &messages) { if (messages.isEmpty()) return; QString header = '[' + QDateTime::currentDateTime().toString(qxt_d().dateFormat) + "] [" + level + "] "; QString padding; QIODevice* file = device(); Q_ASSERT(file); file->write(header.toUtf8()); for (int i = 0; i < header.size(); i++) padding.append(" "); int count = 0; Q_FOREACH(const QVariant& out, messages) { if (!out.isNull()) { if (count != 0) file->write(padding.toUtf8()); file->write(out.toString().toUtf8()); file->write("\n"); } count++; } } libqxt-0.6.2/src/core/qxtbasicfileloggerengine.h000066400000000000000000000040661215241066400217650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTBASICFILELOGGERENGINE_H #define QXTBASICFILELOGGERENGINE_H #include "qxtloggerengine.h" #include "qxtabstractfileloggerengine.h" #include #include /******************************************************************************* QBasicSTDLoggerEngine The basic logger engine included with QxtLogger. *******************************************************************************/ class QxtBasicFileLoggerEnginePrivate; class QXT_CORE_EXPORT QxtBasicFileLoggerEngine : public QxtAbstractFileLoggerEngine { public: QxtBasicFileLoggerEngine(const QString &fileName = QString()); public: QString dateFormat() const; void setDateFormat(const QString& format); protected: virtual void writeToFile(const QString &level, const QVariantList &messages); private: QXT_DECLARE_PRIVATE(QxtBasicFileLoggerEngine) }; #endif // QXTBASICFILELOGGERENGINE_H libqxt-0.6.2/src/core/qxtbasicstdloggerengine.cpp000066400000000000000000000145271215241066400221760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtbasicstdloggerengine.h" #include #include #define QXT_REQUIRED_LEVELS (QxtLogger::WarningLevel | QxtLogger::ErrorLevel | QxtLogger::CriticalLevel | QxtLogger::FatalLevel) /*! \class QxtBasicSTDLoggerEngine \brief The QxtBasicSTDLoggerEngine class provides a basic STD logger engine. \inmodule QxtCore Example basic STD log output: \code [22:38:33.159] [Error] Unknown error [22:51:43.488] [Debug] What's going on? Hi there! \endcode \sa QxtLogger */ class QxtBasicSTDLoggerEnginePrivate : public QxtPrivate { QXT_DECLARE_PUBLIC(QxtBasicSTDLoggerEngine) public: QxtBasicSTDLoggerEnginePrivate(); QTextStream *errstream, *outstream; }; QxtBasicSTDLoggerEnginePrivate::QxtBasicSTDLoggerEnginePrivate() { errstream = new QTextStream(stderr); outstream = new QTextStream(stdout); } /*! Constructor. */ QxtBasicSTDLoggerEngine::QxtBasicSTDLoggerEngine() { QXT_INIT_PRIVATE(QxtBasicSTDLoggerEngine); #ifndef QT_NO_DEBUG setLogLevelsEnabled(QXT_REQUIRED_LEVELS); #else setLogLevelsEnabled(QXT_REQUIRED_LEVELS | QxtLogger::DebugLevel); #endif enableLogging(); } /*! Destructor. */ QxtBasicSTDLoggerEngine::~QxtBasicSTDLoggerEngine() { if (qxt_d().errstream) { qxt_d().errstream->flush(); delete qxt_d().errstream; qxt_d().errstream = 0; } if (qxt_d().outstream) { qxt_d().outstream->flush(); delete qxt_d().outstream; qxt_d().errstream = 0; } } /*! \reimp */ void QxtBasicSTDLoggerEngine::initLoggerEngine() { return; // Should work out of the box! } /*! \reimp */ void QxtBasicSTDLoggerEngine::killLoggerEngine() { return; // I do nothing. } /*! \reimp */ bool QxtBasicSTDLoggerEngine::isInitialized() const { return qxt_d().errstream && qxt_d().outstream; } /*! Returns the stderr stream. */ QTextStream* QxtBasicSTDLoggerEngine::stdErrStream() const { return qxt_d().errstream; } /*! Returns the stdout stream. */ QTextStream* QxtBasicSTDLoggerEngine::stdOutStream() const { return qxt_d().outstream; } /*! Enables \a level if \a enable is \c true, disables otherwise. */ void QxtBasicSTDLoggerEngine::setLogLevelEnabled(QxtLogger::LogLevels level, bool enable) { QxtLoggerEngine::setLogLevelsEnabled(level | QXT_REQUIRED_LEVELS, enable); if (!enable) QxtLoggerEngine::setLogLevelsEnabled(QXT_REQUIRED_LEVELS); } /*! \reimp */ void QxtBasicSTDLoggerEngine::writeFormatted(QxtLogger::LogLevel level, const QList &msgs) { switch (level) { case QxtLogger::ErrorLevel: writeToStdErr("Error", msgs); break; case QxtLogger::WarningLevel: writeToStdOut("Warning", msgs); break; case QxtLogger::CriticalLevel: writeToStdErr("Critical", msgs); break; case QxtLogger::FatalLevel: writeToStdErr("!!FATAL!!", msgs); break; case QxtLogger::TraceLevel: writeToStdOut("Trace", msgs); break; case QxtLogger::DebugLevel: writeToStdErr("DEBUG", msgs); break; case QxtLogger::InfoLevel: writeToStdOut("INFO", msgs); break; default: writeToStdOut("", msgs); break; } } /*! A helper function that actually writes \a msgs to stderr with given \a level. This function is called by QxtBasicSTDLoggerEngine. Reimplement this function when creating a subclass of QxtBasicSTDLoggerEngine. */ void QxtBasicSTDLoggerEngine::writeToStdErr(const QString &level, const QList &msgs) { if (msgs.isEmpty()) return; QString header = '[' + QTime::currentTime().toString("hh:mm:ss.zzz") + "] [" + level + "] "; QString padding; QTextStream* errstream = stdErrStream(); Q_ASSERT(errstream); *errstream << header; for (int i = 0; i < header.size(); i++) padding.append(" "); int count = 0; Q_FOREACH(const QVariant& out, msgs) { if (!out.isNull()) { if (count != 0) *errstream << padding; *errstream << out.toString() << '\n'; } count++; } *errstream << endl; } /*! A helper function that actually writes \a msgs to stdout with given \a level. This function is called by QxtBasicSTDLoggerEngine. Reimplement this function when creating a subclass of QxtBasicSTDLoggerEngine. */ void QxtBasicSTDLoggerEngine::writeToStdOut(const QString& level, const QList &msgs) { /* Message format... [time] [error level] First message..... second message third message */ if (msgs.isEmpty()) return; QString header = '[' + QTime::currentTime().toString("hh:mm:ss.zzz") + "] [" + level + "] "; QString padding; QTextStream* outstream = stdOutStream(); Q_ASSERT(outstream); *outstream << header; for (int i = 0; i < header.size(); i++) padding.append(' '); int count = 0; Q_FOREACH(const QVariant& out, msgs) { if (!out.isNull()) { if (count != 0) *outstream << padding; *outstream << out.toString() << '\n'; } count++; } *outstream << endl; } libqxt-0.6.2/src/core/qxtbasicstdloggerengine.h000066400000000000000000000045241215241066400216370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTBASICSTDLOGGERENGINE_H #define QXTBASICSTDLOGGERENGINE_H #include "qxtloggerengine.h" #include "qxtglobal.h" QT_FORWARD_DECLARE_CLASS(QTextStream) class QxtBasicSTDLoggerEnginePrivate; /******************************************************************************* QBasicSTDLoggerEngine The basic logger engine included with QxtLogger. *******************************************************************************/ class QXT_CORE_EXPORT QxtBasicSTDLoggerEngine : public QxtLoggerEngine { QXT_DECLARE_PRIVATE(QxtBasicSTDLoggerEngine) public: QxtBasicSTDLoggerEngine(); ~QxtBasicSTDLoggerEngine(); void initLoggerEngine(); void killLoggerEngine(); void writeFormatted(QxtLogger::LogLevel level, const QList &messages); void setLogLevelEnabled(QxtLogger::LogLevels level, bool enable = true); bool isInitialized() const; QTextStream* stdErrStream() const; QTextStream* stdOutStream() const; protected: virtual void writeToStdErr(const QString& str_level, const QList &msgs); virtual void writeToStdOut(const QString& str_level, const QList &msgs); }; #endif // QXTBASICSTDLOGGERENGINE_H libqxt-0.6.2/src/core/qxtboundcfunction.h000066400000000000000000000745351215241066400205060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTBOUNDCFUNCTION_H #define QXTBOUNDCFUNCTION_H #include #include #include #include #ifndef QXT_DOXYGEN_RUN #define QXT_RETURN(fp) *reinterpret_cast(returnValue.data()) = (*reinterpret_cast(fp)) #define QXT_INVOKE(fp) (*reinterpret_cast(fp)) #define QXT_PARAM(i) *reinterpret_cast(p ## i .data()) template < typename RETURN, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, typename T9 = void, typename T10 = void > class /*QXT_CORE_EXPORT*/ qxt_cfunction_return : public QxtGenericFunctionPointer { public: typedef RETURN(*FUNCTION)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_RETURN(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5), QXT_PARAM(6), QXT_PARAM(7), QXT_PARAM(8), QXT_PARAM(9), QXT_PARAM(10)); return true; } private: qxt_cfunction_return(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction_return : public QxtGenericFunctionPointer { public: typedef RETURN(*FUNCTION)(); bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_RETURN(funcPtr)(); return true; } private: qxt_cfunction_return(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction_return : public QxtGenericFunctionPointer { public: typedef RETURN(*FUNCTION)(T1); bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_RETURN(funcPtr)(QXT_PARAM(1)); return true; } private: qxt_cfunction_return(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction_return : public QxtGenericFunctionPointer { public: typedef RETURN(*FUNCTION)(T1, T2); bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_RETURN(funcPtr)(QXT_PARAM(1), QXT_PARAM(2)); return true; } private: qxt_cfunction_return(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction_return : public QxtGenericFunctionPointer { public: typedef RETURN(*FUNCTION)(T1, T2, T3); bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_RETURN(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3)); return true; } private: qxt_cfunction_return(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction_return : public QxtGenericFunctionPointer { public: typedef RETURN(*FUNCTION)(T1, T2, T3, T4); bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_RETURN(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4)); return true; } private: qxt_cfunction_return(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction_return : public QxtGenericFunctionPointer { public: typedef RETURN(*FUNCTION)(T1, T2, T3, T4, T5); bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_RETURN(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5)); return true; } private: qxt_cfunction_return(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction_return : public QxtGenericFunctionPointer { public: typedef RETURN(*FUNCTION)(T1, T2, T3, T4, T5, T6); bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_RETURN(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5), QXT_PARAM(6)); return true; } private: qxt_cfunction_return(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction_return : public QxtGenericFunctionPointer { public: typedef RETURN(*FUNCTION)(T1, T2, T3, T4, T5, T6, T7); bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_RETURN(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5), QXT_PARAM(6), QXT_PARAM(7)); return true; } }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction_return : public QxtGenericFunctionPointer { public: typedef RETURN(*FUNCTION)(T1, T2, T3, T4, T5, T6, T7, T8); bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_RETURN(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5), QXT_PARAM(6), QXT_PARAM(7), QXT_PARAM(8)); return true; } private: qxt_cfunction_return(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction_return : public QxtGenericFunctionPointer { public: typedef RETURN(*FUNCTION)(T1, T2, T3, T4, T5, T6, T7, T8, T9); bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_RETURN(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5), QXT_PARAM(6), QXT_PARAM(7), QXT_PARAM(8), QXT_PARAM(9)); return true; } private: qxt_cfunction_return(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template < typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, typename T9 = void, typename T10 = void > class /*QXT_CORE_EXPORT*/ qxt_cfunction : public QxtGenericFunctionPointer { public: typedef void(*FUNCTION)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_INVOKE(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5), QXT_PARAM(6), QXT_PARAM(7), QXT_PARAM(8), QXT_PARAM(9), QXT_PARAM(10)); return true; } private: qxt_cfunction(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template <> class /*QXT_CORE_EXPORT*/ qxt_cfunction : public QxtGenericFunctionPointer { public: typedef void(*FUNCTION)(); bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_INVOKE(funcPtr)(); return true; } private: qxt_cfunction(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction : public QxtGenericFunctionPointer { public: typedef void(*FUNCTION)(T1); bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_INVOKE(funcPtr)(QXT_PARAM(1)); return true; } private: qxt_cfunction(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction : public QxtGenericFunctionPointer { public: typedef void(*FUNCTION)(T1, T2); bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_INVOKE(funcPtr)(QXT_PARAM(1), QXT_PARAM(2)); return true; } private: qxt_cfunction(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction : public QxtGenericFunctionPointer { public: typedef void(*FUNCTION)(T1, T2, T3); bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_INVOKE(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3)); return true; } private: qxt_cfunction(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction : public QxtGenericFunctionPointer { public: typedef void(*FUNCTION)(T1, T2, T3, T4); bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_INVOKE(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4)); return true; } private: qxt_cfunction(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction : public QxtGenericFunctionPointer { public: typedef void(*FUNCTION)(T1, T2, T3, T4, T5); bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_INVOKE(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5)); return true; } private: qxt_cfunction(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction : public QxtGenericFunctionPointer { public: typedef void(*FUNCTION)(T1, T2, T3, T4, T5, T6); bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_INVOKE(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5), QXT_PARAM(6)); return true; } private: qxt_cfunction(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction : public QxtGenericFunctionPointer { public: typedef void(*FUNCTION)(T1, T2, T3, T4, T5, T6, T7); bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_INVOKE(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5), QXT_PARAM(6), QXT_PARAM(7)); return true; } private: qxt_cfunction(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction : public QxtGenericFunctionPointer { public: typedef void(*FUNCTION)(T1, T2, T3, T4, T5, T6, T7, T8); bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_INVOKE(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5), QXT_PARAM(6), QXT_PARAM(7), QXT_PARAM(8)); return true; } private: qxt_cfunction(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template class /*QXT_CORE_EXPORT*/ qxt_cfunction : public QxtGenericFunctionPointer { public: typedef void(*FUNCTION)(T1, T2, T3, T4, T5, T6, T7, T8, T9); bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { QXT_10_UNUSED; QXT_INVOKE(funcPtr)(QXT_PARAM(1), QXT_PARAM(2), QXT_PARAM(3), QXT_PARAM(4), QXT_PARAM(5), QXT_PARAM(6), QXT_PARAM(7), QXT_PARAM(8), QXT_PARAM(9)); return true; } private: qxt_cfunction(voidFunc* ptr, const QByteArray& typeIdName) : QxtGenericFunctionPointer(ptr, typeIdName) {} }; template < typename RETURN = void, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, typename T9 = void, typename T10 = void > class /*QXT_CORE_EXPORT*/ QxtBoundCFunction : public QxtBoundFunctionBase { public: QxtGenericFunctionPointer funcPtr; QxtBoundCFunction(QObject* parent, QxtGenericFunctionPointer funcPointer, QGenericArgument* params[10], QByteArray types[10]) : QxtBoundFunctionBase(parent, params, types), funcPtr(funcPointer) { // initializers only, thanks to template magic } virtual bool invokeImpl(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QGenericArgument)) { if (type != Qt::AutoConnection && type != Qt::DirectConnection) { qWarning() << "QxtBoundCFunction::invoke: Cannot invoke non-Qt functions using a queued connection"; return false; } return reinterpret_cast*>(&funcPtr)->invoke(returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } }; template class /*QXT_CORE_EXPORT*/ QxtBoundCFunction : public QxtBoundFunctionBase { public: QxtGenericFunctionPointer funcPtr; QxtBoundCFunction(QObject* parent, QxtGenericFunctionPointer funcPointer, QGenericArgument* params[10], QByteArray types[10]) : QxtBoundFunctionBase(parent, params, types), funcPtr(funcPointer) { // initializers only, thanks to template magic } virtual bool invokeImpl(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QGenericArgument)) { Q_UNUSED(returnValue); if (type != Qt::AutoConnection && type != Qt::DirectConnection) { qWarning() << "QxtBoundCFunction::invoke: Cannot invoke non-Qt functions using a queued connection"; return false; } return reinterpret_cast*>(&funcPtr)->invoke(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } }; #undef QXT_RETURN #undef QXT_INVOKE #undef QXT_PARAM #endif namespace QxtMetaObject { /*! * \relates QxtMetaObject * \sa QxtMetaObject::connect * \sa qxtFuncPtr * \sa QxtBoundFunction * \sa QXT_BIND * * Creates a binding to the provided C/C++ function using the provided parameter list. * Use the qxtFuncPtr function to wrap a bare function pointer for use in this function. * Use the Q_ARG macro to specify constant parameters, or use the QXT_BIND macro to * relay a parameter from a connected signal or passed via the QxtBoundFunction::invoke() * method. * * The first template parameter must match the return type of the function, or * void if the function does not return a value. The remaining template parameters must * match the types of the function's parameters. If any type does not match, this * function returns NULL. * * The returned QxtBoundFunction will not have a parent. Assigning a parent using * QObject::setParent() is strongly recommended to avoid memory leaks. */ template QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QXT_IMPL_10ARGS(QGenericArgument)) { // Make sure the template parameters make a function pointer equivalent to the one passed in if (funcPointer.typeName != typeid(typename qxt_cfunction_return::FUNCTION).name()) { qWarning() << "QxtMetaObject::bind: parameter list mismatch, check template arguments"; return 0; } QGenericArgument* args[10] = { &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10 }; for (int i = 0; i < 10; i++) { if (args[i]->name() == 0) break; // done if (QByteArray(args[i]->name()) == "QxtBoundArgument") { Q_ASSERT_X((quintptr)(args[i]->data()) > 0 && (quintptr)(args[i]->data()) <= 10, "QXT_BIND", "invalid argument number"); } } QByteArray types[10]; types[0] = QxtMetaType::name(); types[1] = QxtMetaType::name(); types[2] = QxtMetaType::name(); types[3] = QxtMetaType::name(); types[4] = QxtMetaType::name(); types[5] = QxtMetaType::name(); types[6] = QxtMetaType::name(); types[7] = QxtMetaType::name(); types[8] = QxtMetaType::name(); types[9] = QxtMetaType::name(); return new QxtBoundCFunction(0, funcPointer, args, types); } /*! * \relates QxtMetaObject * \sa QxtMetaObject::connect * \sa qxtFuncPtr * \sa QxtBoundFunction * * Creates a binding to the provided C/C++ function using the provided parameter list. * Use the qxtFuncPtr function to wrap a bare function pointer for use in this function. * The type of each argument is deduced from the type of the QVariant. This function * cannot bind positional arguments; see the overload using QGenericArgument. * * The first template parameter must match the return type of the function, or * void if the function does not return a value. The remaining template parameters must * match the types of the function's parameters. If any type does not match, this * function returns NULL. * * The returned QxtBoundFunction will not have a parent. Assigning a parent using * QObject::setParent() is strongly recommended to avoid memory leaks. */ template QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QXT_IMPL_10ARGS(QVariant)) { QVariant* args[10] = { &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10 }; return QxtMetaObject::bind(funcPointer, QXT_VAR_ARG(1), QXT_VAR_ARG(2), QXT_VAR_ARG(3), QXT_VAR_ARG(4), QXT_VAR_ARG(5), QXT_VAR_ARG(6), QXT_VAR_ARG(7), QXT_VAR_ARG(8), QXT_VAR_ARG(9), QXT_VAR_ARG(10)); } // The following overloads exist because C++ doesn't support default parameters in function templates #ifndef QXT_DOXYGEN_RUN template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer) { return bind(funcPointer, QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QGenericArgument p1) { return bind(funcPointer, p1, QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QGenericArgument p1, QGenericArgument p2) { return bind(funcPointer, p1, p2, QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QGenericArgument p1, QGenericArgument p2, QGenericArgument p3) { return bind(funcPointer, p1, p2, p3, QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QGenericArgument p1, QGenericArgument p2, QGenericArgument p3, QGenericArgument p4) { return bind(funcPointer, p1, p2, p3, p4, QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QGenericArgument p1, QGenericArgument p2, QGenericArgument p3, QGenericArgument p4, QGenericArgument p5) { return bind(funcPointer, p1, p2, p3, p4, p5, QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QGenericArgument p1, QGenericArgument p2, QGenericArgument p3, QGenericArgument p4, QGenericArgument p5, QGenericArgument p6) { return bind(funcPointer, p1, p2, p3, p4, p5, p6, QGenericArgument(), QGenericArgument(), QGenericArgument(), QGenericArgument()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QGenericArgument p1, QGenericArgument p2, QGenericArgument p3, QGenericArgument p4, QGenericArgument p5, QGenericArgument p6, QGenericArgument p7) { return bind(funcPointer, p1, p2, p3, p4, p5, p6, p7, QGenericArgument(), QGenericArgument(), QGenericArgument()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QGenericArgument p1, QGenericArgument p2, QGenericArgument p3, QGenericArgument p4, QGenericArgument p5, QGenericArgument p6, QGenericArgument p7, QGenericArgument p8) { return bind(funcPointer, p1, p2, p3, p4, p5, p6, p7, p8, QGenericArgument(), QGenericArgument()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QGenericArgument p1, QGenericArgument p2, QGenericArgument p3, QGenericArgument p4, QGenericArgument p5, QGenericArgument p6, QGenericArgument p7, QGenericArgument p8, QGenericArgument p9) { return bind(funcPointer, p1, p2, p3, p4, p5, p6, p7, p8, p9, QGenericArgument()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QVariant p1) { return bind(funcPointer, p1, QVariant(), QVariant(), QVariant(), QVariant(), QVariant(), QVariant(), QVariant(), QVariant(), QVariant()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QVariant p1, QVariant p2) { return bind(funcPointer, p1, p2, QVariant(), QVariant(), QVariant(), QVariant(), QVariant(), QVariant(), QVariant(), QVariant()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QVariant p1, QVariant p2, QVariant p3) { return bind(funcPointer, p1, p2, p3, QVariant(), QVariant(), QVariant(), QVariant(), QVariant(), QVariant(), QVariant()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QVariant p1, QVariant p2, QVariant p3, QVariant p4) { return bind(funcPointer, p1, p2, p3, p4, QVariant(), QVariant(), QVariant(), QVariant(), QVariant(), QVariant()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5) { return bind(funcPointer, p1, p2, p3, p4, p5, QVariant(), QVariant(), QVariant(), QVariant(), QVariant()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6) { return bind(funcPointer, p1, p2, p3, p4, p5, p6, QVariant(), QVariant(), QVariant(), QVariant()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7) { return bind(funcPointer, p1, p2, p3, p4, p5, p6, p7, QVariant(), QVariant(), QVariant()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8) { return bind(funcPointer, p1, p2, p3, p4, p5, p6, p7, p8, QVariant(), QVariant()); } template inline QxtBoundFunction* bind(QxtGenericFunctionPointer funcPointer, QVariant p1, QVariant p2, QVariant p3, QVariant p4, QVariant p5, QVariant p6, QVariant p7, QVariant p8, QVariant p9) { return bind(funcPointer, p1, p2, p3, p4, p5, p6, p7, p8, p9, QVariant()); } #endif } #endif libqxt-0.6.2/src/core/qxtboundfunction.h000066400000000000000000000261121215241066400203270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTBOUNDFUNCTION_H #define QXTBOUNDFUNCTION_H #include #include #include #include #include #include #include /*! \class QxtBoundFunction \inmodule QxtCore \brief Binds parameters to a function call * A bound function is very similar to what the C++ FAQ Lite refers to as "functionoids." * (http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.10) * It is similar in use to a function pointer, but allows any or all parameters to be * pre-filled with constant values. The remaining parameters are specified when the * function is invoked, for instance, by a Qt signal connection. * * By far, the most common expected use is to provide a parameter to a slot when the * signal doesn't have offer one. Many developers new to Qt try to write code like this: * \code * connect(button, SIGNAL(clicked()), lineEdit, SLOT(setText("Hello, world"))); * \endcode * Experienced Qt developers will immediately spot the flaw here. The typical solution * is to create a short, one-line wrapper slot that invokes the desired function. Some * clever developers may even use QSignalMapper to handle slots that only need one * int or QString parameter. * * QxtBoundFunction enables the previous connect statement to be written like this: * \code * connect(button, SIGNAL(clicked()), QxtMetaObject::bind(lineEdit, SLOT(setText(QString)), Q_ARG(QString, "Hello, world!"))); * \code * This accomplishes the same result without having to create a new slot, or worse, * an entire object, just to pass a constant value. * * Additionally, through the use of the QXT_BIND macro, parameters from the signal * can be rearranged, skipped, or passed alongside constant arguments provided * with the Q_ARG macro. This can be used to provide stateful callbacks to a * generic function, for example. * * Many kinds of functions can be bound. The most common binding applies to * Qt signals and slots, but standard C/C++ functions can be bound as well. * Future development may add the ability to bind to C++ member functions, * and developers can make custom QxtBoundFunction subclasses for even more * flexibility if necessary. * * */ class QXT_CORE_EXPORT QxtBoundFunction : public QObject { Q_OBJECT public: /*! * Invokes the bound function and returns a value. * * The template parameter should be the return type of the invoked function. This overload accepts * QVariant parameters and will guess the data type of each parameter based on the type of the QVariant. */ template inline QxtNullable invoke(QXT_PROTO_10ARGS(QVariant)) { if (!parent() || QThread::currentThread() == parent()->thread()) return invoke(Qt::DirectConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); #if QT_VERSION >= 0x040300 return invoke(Qt::BlockingQueuedConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); #else qWarning() << "QxtBoundFunction::invoke: Cannot return a value using a queued connection"; return QxtNull(); #endif } /*! * Invokes the bound function and returns a value. * * The template parameter should be the return type of the invoked function. This overload accepts * QGenericArgument parameters, expressed using the Q_ARG() macro. */ template QxtNullable invoke(Qt::ConnectionType type, QVariant p1, QXT_PROTO_9ARGS(QVariant)) { if (type == Qt::QueuedConnection) { qWarning() << "QxtBoundFunction::invoke: Cannot return a value using a queued connection"; return QxtNull(); } T retval; // I know this is a totally ugly function call if (invoke(type, QGenericReturnArgument(qVariantFromValue(*reinterpret_cast(0)).typeName(), reinterpret_cast(&retval)), p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)) { return retval; } else { return QxtNull(); } } /*! * Invokes the bound function, discarding the return value. * * This overload accepts QVariant parameters and will guess the data type of each * parameter based on the type of the QVariant. * * This function returns true if the invocation was successful, otherwise it * returns false. */ inline bool invoke(QVariant p1, QXT_PROTO_9ARGS(QVariant)) { return invoke(Qt::AutoConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } /*! * Invokes the bound function, discarding the return value. * * This overload accepts QVariant parameters and will guess the data type of each * parameter based on the type of the QVariant. It also allows you to specify the * connection type, allowing the bound function to be invoked across threads using * the Qt event loop. * * This function returns true if the invocation was successful, otherwise it * returns false. */ bool invoke(Qt::ConnectionType, QVariant p1, QXT_PROTO_9ARGS(QVariant)); /*! * Invokes the bound function, discarding the return value. * * This overload accepts QGenericArgument parameters, expressed using the Q_ARG() * macro. * * This function returns true if the invocation was successful, otherwise it * returns false. */ inline bool invoke(QXT_PROTO_10ARGS(QGenericArgument)) { return invoke(Qt::AutoConnection, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } /*! * Invokes the bound function, discarding the return value. * * This overload accepts QGenericArgument parameters, expressed using the Q_ARG() * macro. It also allows you to specify the connection type, allowing the bound * function to be invoked across threads using the Qt event loop. * * This function returns true if the invocation was successful, otherwise it * returns false. */ inline bool invoke(Qt::ConnectionType type, QXT_PROTO_10ARGS(QGenericArgument)) { return invoke(type, QGenericReturnArgument(), p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } /*! * Invokes the bound function and assigns the return value to a parameter passed by reference. * * Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's * return type. When the function completes, its return value will be stored in that object. * * This overload accepts QVariant parameters and will guess the data type of each * parameter based on the type of the QVariant. * * This function returns true if the invocation was successful, otherwise it * returns false. */ inline bool invoke(QGenericReturnArgument returnValue, QVariant p1, QXT_PROTO_9ARGS(QVariant)) { return invoke(Qt::AutoConnection, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } /*! * Invokes the bound function and assigns the return value to a parameter passed by reference. * * Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's * return type. When the function completes, its return value will be stored in that object. * * This overload accepts QVariant parameters and will guess the data type of each * parameter based on the type of the QVariant. It also allows you to specify the * connection type, allowing the bound function to be invoked across threads using * the Qt event loop. * * This function returns true if the invocation was successful, otherwise it * returns false. */ bool invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QVariant p1, QXT_PROTO_9ARGS(QVariant)); /*! * Invokes the bound function and assigns the return value to a parameter passed by reference. * * Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's * return type. When the function completes, its return value will be stored in that object. * * This overload accepts QGenericArgument parameters, expressed using the Q_ARG() * macro. * * This function returns true if the invocation was successful, otherwise it * returns false. */ inline bool invoke(QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) { return invoke(Qt::AutoConnection, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } /*! * Invokes the bound function and assigns the return value to a parameter passed by reference. * * Use the Q_RETURN_ARG() macro to pass a reference to an assignable object of the function's * return type. When the function completes, its return value will be stored in that object. * * This overload accepts QGenericArgument parameters, expressed using the Q_ARG() * macro. It also allows you to specify the connection type, allowing the bound * function to be invoked across threads using the Qt event loop. * * This function returns true if the invocation was successful, otherwise it * returns false. */ bool invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)); protected: #ifndef QXT_DOXYGEN_RUN QxtBoundFunction(QObject* parent = 0); #endif /*! * Performs the work of invoking the bound function. * * This function is pure virtual. The various QxtMetaObject::bind() functions return opaque subclasses * of QxtBoundFunction. If you wish to create a new kind of bound function, reimplement this function to * perform the invocation and assign the function's return value, if any, to the returnValue parameter. * * This function should return true if the invocation is successful and false if an error occurs. */ virtual bool invokeImpl(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)) = 0; }; #endif libqxt-0.6.2/src/core/qxtboundfunctionbase.h000066400000000000000000000046061215241066400211660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ // This file exists for the convenience of QxtBoundCFunction. // It is not part of the public API and is subject to change. // // We mean it. #ifndef QXTBOUNDFUNCTIONBASE_H #define QXTBOUNDFUNCTIONBASE_H #include #include #include #include #include #ifndef QXT_DOXYGEN_RUN #define QXT_10_UNUSED Q_UNUSED(p1) Q_UNUSED(p2) Q_UNUSED(p3) Q_UNUSED(p4) Q_UNUSED(p5) Q_UNUSED(p6) Q_UNUSED(p7) Q_UNUSED(p8) Q_UNUSED(p9) Q_UNUSED(p10) class QXT_CORE_EXPORT QxtBoundFunctionBase : public QxtBoundFunction { public: QByteArray bindTypes[10]; QGenericArgument arg[10], p[10]; void* data[10]; QxtBoundFunctionBase(QObject* parent, QGenericArgument* params[10], QByteArray types[10]); virtual ~QxtBoundFunctionBase(); int qt_metacall(QMetaObject::Call _c, int _id, void **_a); bool invokeBase(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_PROTO_10ARGS(QGenericArgument)); }; #define QXT_ARG(i) ((argCount>i)?QGenericArgument(p ## i .typeName(), p ## i .constData()):QGenericArgument()) #define QXT_VAR_ARG(i) (p ## i .isValid())?QGenericArgument(p ## i .typeName(), p ## i .constData()):QGenericArgument() #endif #endif libqxt-0.6.2/src/core/qxtcommandoptions.cpp000066400000000000000000000764461215241066400210560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtcommandoptions.h" #include #include #include #include /*! \class QxtCommandOptions \inmodule QxtCore \brief The QxtCommandOptions class is a Parser for command-line options This class is used by applications that need to accept command-line arguments. It can also automatically generate help text, which keeps it from accidentally falling out of sync with the supported options, and it can produce warnings for common errors. It accepts Windows-style ("/option"), UNIX-style ("-option"), and GNU-style ("--option") options. By default, QxtCommandOptions uses Windows-style options (QxtCommandOptions::Slash) on Windows and GNU-style options (QxtCommandOptions::DoubleDash) on UNIX and Mac. When using GNU-style options, single-character option names only require a single leading dash and can be grouped together, for example, "-abc". Any parameter that does not start with the option prefix is considered a positional parameter. Most applications treat positional parameters as filenames. When using GNU- or UNIX-style options, use a double dash ("--") alone to force the remaining parameters to be interpreted as positional parameters. To use QxtCommandOptions, first add the supported options using the add() and alias() methods, then process the command line using the parse() method, and finally retrieve the processed options using the positional(), count(), value() and/or parameters() methods. Mutually-exclusive options can be specified by using the \a group parameter to add(). Only one option in a group will be accepted on the command line; if multiple options are provided, only the last one takes effect. Some options may accept an optional or required parameter. Depending on the value of the paramStyle() property, the parameter may be separated from the option by an equals sign ("/option=value") or by a space ("-option value"). By default, Windows uses an equals sign and UNIX and Mac accept both an equals sign and a space. Optional parameters always require an equals sign. Note that, when using GNU-style options, single-character options cannot have optional parameters. A simple archiving application might use code similar to this: \code QxtCommandOptions options; options.add("compress", "create a new archive"); options.alias("compress", "c"); options.add("extract", "extract files from an archive"); options.alias("extract", "x"); options.add("level", "set the compression level (0-9)", QxtCommandOptions::Required); options.alias("level", "l"); options.add("verbose", "show more information about the process; specify twice for more detail", QxtCommandOptions::AllowMultiple); options.alias("verbose", "v"); options.add("help", "show this help text"); options.alias("help", "h"); options.parse(QCoreApplication::arguments()); if(options.count("help") || options.showUnrecognizedWarning()) { options.showUsage(); return -1; } bool verbose = options.count("verbose"); int level = 5; if(options.count("level")) { level = options.value("level").toInt(); } \endcode \sa QCoreApplication::arguments() */ static const char* qxt_qt_options[] = { "=style", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application GUI style"), "=stylesheet", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application stylesheet"), "=session", QT_TRANSLATE_NOOP("QxtCommandOptions", "restores the application from an earlier session"), "widgetcount", QT_TRANSLATE_NOOP("QxtCommandOptions", "displays debugging information about widgets"), "reverse", QT_TRANSLATE_NOOP("QxtCommandOptions", "use right-to-left layout"), #ifdef QT_DEBUG "nograb", QT_TRANSLATE_NOOP("QxtCommandOptions", "never grab the mouse or keyboard"), #endif #if defined(QT_DEBUG) && defined(Q_WS_X11) "dograb", QT_TRANSLATE_NOOP("QxtCommandOptions", "grab the mouse/keyboard even in a debugger"), "sync", QT_TRANSLATE_NOOP("QxtCommandOptions", "run in synchronous mode for debugging"), #endif #ifdef Q_WS_WIN "direct3d", QT_TRANSLATE_NOOP("QxtCommandOptions", "use Direct3D by default"), #endif #ifdef Q_WS_X11 "=display", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the X11 display"), "=geometry", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the geometry of the first window"), "=font", "", "=fn", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default font"), "=background", "", "=bg", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default background color"), "=foreground", "", "=fg", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default foreground color"), "=button", "", "=btn", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the default button color"), "=name", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application name"), "=title", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the application title"), "=visual", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the X11 visual type"), "=ncols", QT_TRANSLATE_NOOP("QxtCommandOptions", "limit the number of colors on an 8-bit display"), "cmap", QT_TRANSLATE_NOOP("QxtCommandOptions", "use a private color map"), "=im", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the input method server"), "noxim", QT_TRANSLATE_NOOP("QxtCommandOptions", "disable the X Input Method"), "=inputstyle", QT_TRANSLATE_NOOP("QxtCommandOptions", "sets the style used by the input method"), #endif 0, 0 }; /* * This function is used to check to see if a parameter * is used by Qt. */ static int isQtOption(const QString& param) { // Qt options all start with a single dash regardless of platform if (param.length() < 2) return 0; if (param[0] != '-') return 0; if (param[1] == '-') return 0; #ifdef Q_OS_MAC if (param.left(5) == "-psn_") return 1; #endif QString name = param.mid(1), value; bool hasEquals; // Separate the option and the value, if present if (name.indexOf('=') != -1) { value = param.section('=', 1); name = param.section('=', 0, 0); hasEquals = true; } else { value = ""; hasEquals = false; } const char* option; bool optionHasValue; for (int i = 0; qxt_qt_options[i]; i += 2) { option = qxt_qt_options[i]; // In the table above, options that require parameters start with = if (option[0] == '=') { optionHasValue = true; option = option + 1; // pointer math to skip = } else { optionHasValue = false; } // The return value indicates how many parameters to skip if (name == option) { if (optionHasValue) return 2; return 1; } } return 0; } // Storage structure for option data struct QxtCommandOption { QStringList names; // aliases accepted at the command line QString canonicalName; // name used for alias()/count()/value() QString desc; // documentation string QStringList values; // values passed on command line QxtCommandOptions::ParamTypes paramType; // flags quint16 group; // mutual exclusion group }; class QxtCommandOptionsPrivate : public QxtPrivate { Q_DECLARE_TR_FUNCTIONS(QxtCommandOptions) public: QXT_DECLARE_PUBLIC(QxtCommandOptions) QList options; QHash lookup; // cache structure to simplify processing QHash > groups; // cache structure to simplify processing QxtCommandOptions::FlagStyle flagStyle; QxtCommandOptions::ParamStyle paramStyle; QStringList positional; // prefixless parameters QStringList unrecognized; // prefixed parameters not in recognized options QStringList missingParams; // parameters with required values missing int screenWidth; bool parsed; QxtCommandOption* findOption(const QString& name); const QxtCommandOption* findOption(const QString& name) const; void setOption(QxtCommandOption* option, const QString& value = QString()); void parse(const QStringList& params); }; /* Looks up an option in qxt_d().options by canonical name */ QxtCommandOption* QxtCommandOptionsPrivate::findOption(const QString& name) { // The backwards loop will find what we're looking for more quickly in the // typical use case, where you add aliases immediately after adding the option. for (int i = options.count() - 1; i >= 0; --i) { if (options[i].canonicalName == name) return &options[i]; } qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("option \"%1\" not found").arg(name)); return 0; } /* Looks up an option in qxt_d().options by canonical name * This is a const overload for const functions */ const QxtCommandOption* QxtCommandOptionsPrivate::findOption(const QString& name) const { // The backwards loop will find what we're looking for more quickly in the // typical use case, where you add aliases immediately after adding the option. for (int i = options.count() - 1; i >= 0; --i) { if (options[i].canonicalName == name) return &(options.at(i)); } qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("option \"%1\" not found").arg(name)); return 0; } /*! * Constructs a QxtCommandOptions object. */ QxtCommandOptions::QxtCommandOptions() { QXT_INIT_PRIVATE(QxtCommandOptions); qxt_d().screenWidth = 80; qxt_d().parsed = false; #ifdef Q_OS_WIN setFlagStyle(Slash); setParamStyle(Equals); #else setFlagStyle(DoubleDash); setParamStyle(SpaceAndEquals); #endif } /*! * Sets which prefix is used to identify options. The default value is Slash on Windows * and DoubleDash on all other platforms. * * Note that Qt's built-in options (see QApplication) always use a single dash, * regardless of this setting. */ void QxtCommandOptions::setFlagStyle(FlagStyle style) { qxt_d().flagStyle = style; } /*! * Gets which prefix is used to identify options. */ QxtCommandOptions::FlagStyle QxtCommandOptions::flagStyle() const { return qxt_d().flagStyle; } /*! * Sets which value separator is used for options that accept parameters. * The default value is Equals on Windows and SpaceAndEquals on all other * platforms. * * Single-letter options with optional parameters in DoubleDash mode * always use an equals sign, regardless of this setting. * * Qt's built-in options always behave as SpaceAndEquals, regardless of * this setting. */ void QxtCommandOptions::setParamStyle(ParamStyle style) { qxt_d().paramStyle = style; } /*! * Sets which value separator is used for options that accept parameters. */ QxtCommandOptions::ParamStyle QxtCommandOptions::paramStyle() const { return qxt_d().paramStyle; } /*! * Sets the width of the screen, in characters. This is used for word-wrapping * the automatically-generated help text to the size of the screen. The default * value is 80 characters. Pass 0 to disable word-wrapping. */ void QxtCommandOptions::setScreenWidth(quint16 width) { qxt_d().screenWidth = width; } /*! * Gets the width of the screen, in characters. */ quint16 QxtCommandOptions::screenWidth() const { return qxt_d().screenWidth; } /*! * Adds a section separator. Section separators are only used in generating * help text, and can be used to visually separate related groups of * options. */ void QxtCommandOptions::addSection(const QString& name) { QxtCommandOption option; option.canonicalName.clear(); option.desc = name; qxt_d().options.append(option); } /*! * Adds an option to the parser. * * The name parameter defines the name that will be used by the alias(), * count(), value(), and parameters() methods. Additional names for the * same option can be defined using the alias() method. * * The group parameter, if used, defines a set of mutually-exclusive options. * If more than one option in the same group is passed on the command line, * only the last one takes effect. */ void QxtCommandOptions::add(const QString& name, const QString& desc, ParamTypes paramType, int group) { QxtCommandOption option; option.canonicalName = name; option.desc = desc; option.paramType = paramType; option.group = group; qxt_d().options.append(option); if (group != -1) qxt_d().groups[group].append(&(qxt_d().options.last())); // Connect the canonical name to a usable name alias(name, name); } /*! * Provides an alias for an option. An alias is another name for the option that can be * given on the command line. Aliases cannot be used as parameters to alias(), count() * or value() nor can single-letter aliases be created for options with an optional value. * * The from parameter must be a name has previously been added with the add() method. */ void QxtCommandOptions::alias(const QString& from, const QString& to) { QxtCommandOption* option = qxt_d().findOption(from); if (!option) return; // findOption outputs the warning option->names.append(to); qxt_d().lookup[to] = option; if (option->paramType & ValueOptional && qxt_d().flagStyle == DoubleDash && to.length() == 1) qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("Short options cannot have optional parameters")); } /*! * Returns the positional parameters from the command line, that is, the arguments that * do not begin with the option prefix. * * \sa flagStyle() */ QStringList QxtCommandOptions::positional() const { if (!qxt_d().parsed) qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("positional() called before parse()")); return qxt_d().positional; } /*! * Returns the options that could not be parsed. * * An argument is unrecognized if it begins with the option prefix but was never * defined using the add() or alias() methods, or if it requires a value but the * user did not provide one. */ QStringList QxtCommandOptions::unrecognized() const { if (!qxt_d().parsed) qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("unrecognized() called before parse()")); return qxt_d().unrecognized + qxt_d().missingParams; } /*! * Returns the number of times an option was passed on the command line. * * This function will only return 0 or 1 for options that were not created with the * QxtCommandOptions::AllowMultiple flag set. */ int QxtCommandOptions::count(const QString& name) const { if (!qxt_d().parsed) qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("count() called before parse()")); const QxtCommandOption* option = qxt_d().findOption(name); if (!option) return 0; // findOption outputs the warning return option->values.count(); } /*! * Returns the value or values for an option passed on the command line. * * If the option was not passed on the command line, this function returns a null QVariant. * If the option was created with the QxtCommandOptions::AllowMultiple flag, and the option * was passed more than once, this function returns a QStringList containing the values. * Otherwise, this function returns the last (or only) value given to the option on the * command line. When an option allowing an optional value is provided on the command * line and for which no value is provided, an empty but non-null QString will be returned * in the QVariant. */ QVariant QxtCommandOptions::value(const QString& name) const { if (!qxt_d().parsed) qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("value() called before parse()")); const QxtCommandOption* option = qxt_d().findOption(name); if (!option) return QVariant(); // findOption outputs the warning int ct = option->values.count(); if (ct == 0) return QVariant(); if (ct == 1) return option->values.first(); return option->values; } /*! * Returns all of the recognized options passed on the command line. */ QMultiHash QxtCommandOptions::parameters() const { if (!qxt_d().parsed) qWarning() << qPrintable(QString("QxtCommandOptions: ") + tr("parameters() called before parse()")); QMultiHash params; int ct; foreach(const QxtCommandOption& option, qxt_d().options) { ct = option.values.count(); if (!ct) { continue; } else if (!(option.paramType & (ValueOptional | ValueRequired))) { // Valueless options are really a true/false flag params.insert(option.canonicalName, true); } else { foreach(const QVariant& value, option.values) params.insert(option.canonicalName, value); } } return params; } /*! * This is an overloaded member function, provided for convenience. * * Process a set of command-line options. This overload accepts a number of * arguments and a pointer to the list of arguments. * * Note that parse() may be invoked multiple times to handle arguments from * more than one source. */ void QxtCommandOptions::parse(int argc, char** argv) { QStringList args; for (int i = 0; i < argc; i++) args << argv[i]; parse(args); } /*! * Process a set of command-line options. This overload accepts a QStringList * containing the command-line options, such as the one returned by * QCoreApplication::arguments(). * * Note that parse() may be invoked multiple times to handle arguments from * more than one source. * * \sa QCoreApplication::arguments() */ void QxtCommandOptions::parse(QStringList params) { qxt_d().parse(params); qxt_d().parsed = true; } /* Update the internal data structures with an option from the command line. */ void QxtCommandOptionsPrivate::setOption(QxtCommandOption* option, const QString& value) { if (groups.contains(option->group)) { // Clear mutually-exclusive options QList& others = groups[option->group]; foreach(QxtCommandOption* other, others) { if (other != option) other->values.clear(); } } // Clear all previous values if multiples are not accepted if (!(option->paramType & QxtCommandOptions::AllowMultiple)) option->values.clear(); option->values.append(value); } /* Do the work of parsing the command line */ void QxtCommandOptionsPrivate::parse(const QStringList& params) { int pos = 1; // 0 is the application name int ct = params.count(); int skip = 0; bool endFlags = false; bool notUnrecognized, hasEquals; QString name, param, value; while (pos < ct) { // Ignore Qt built-in options while ((skip = isQtOption(params[pos]))) { pos += skip; if (pos >= ct) return; } param = params[pos]; pos++; if (!endFlags && ((flagStyle == QxtCommandOptions::Slash && param[0] == '/') || (flagStyle != QxtCommandOptions::Slash && param[0] == '-'))) { // tagged argument if (param.length() == 1) { // "-" or "/" alone can't possibly match a flag, so use positional. positional.append(param); continue; } notUnrecognized = false; if (flagStyle != QxtCommandOptions::Slash && param == "--") { // End of parameters flag endFlags = true; } else if (flagStyle == QxtCommandOptions::DoubleDash && param[1] != '-') { // Handle short-form options int len = param.length(); QxtCommandOption* option; for (int i = 1; i < len; i++) { QString ch(param[i]); if (ch == "-") { endFlags = true; } else { option = lookup.value(ch, 0); if (!option) { // single-letter flag has no known equivalent unrecognized.append(QString("-") + param[i]); } else { if (option->paramType & QxtCommandOptions::ValueRequired) { // Check for required parameters // Short options can't have optional parameters if (pos >= params.count()) { missingParams.append(param); break; } value = params[pos]; } else { value = ""; } setOption(option, value); } } } } else { // Break apart a value if (param.indexOf('=') != -1) { value = param.section('=', 1); param = param.section('=', 0, 0); hasEquals = true; } else { value = ""; hasEquals = false; } if (flagStyle == QxtCommandOptions::DoubleDash) name = param.mid(2); else name = param.mid(1); QxtCommandOption* option = lookup.value(name, 0); if (!option) { unrecognized.append(param); } else { if (option->paramType & QxtCommandOptions::ValueRequired && !hasEquals) { // Check for parameters if (pos >= params.count()) { missingParams.append(param); break; } value = params[pos]; pos++; } else if ((paramStyle & QxtCommandOptions::Space) && (option->paramType & QxtCommandOptions::ValueOptional) && !hasEquals) { if (pos < params.count()) { if (!((flagStyle == QxtCommandOptions::Slash && params.at(pos)[0] == '/') || (flagStyle != QxtCommandOptions::Slash && params.at(pos)[0] == '-'))) { value = params[pos]; pos++; } } } setOption(option, value); } } } else { // positional argument positional.append(param); } } } /*! * This is an overloaded member function, provided for convenience. * * Outputs a warning about any unrecognized options to the provided device, or * standard error by default. The device must already be opened for writing. * * This function returns true if any warnings were output, or false otherwise. * * If a QCoreApplication or a subclass of QCoreApplication has been instantiated, * this function uses QCoreApplication::applicationFilePath() to get the name * of the executable to include in the message. * * \sa QCoreApplication::applicationFilePath() */ bool QxtCommandOptions::showUnrecognizedWarning(QIODevice* device) const { if (!device) { QTextStream stream(stderr); return showUnrecognizedWarning(*&stream); } else { QTextStream stream(device); return showUnrecognizedWarning(*&stream); } } /*! * Returns the automatically-generated warning text about any unrecognized options. * * If a QCoreApplication or a subclass of QCoreApplication has been instantiated, * this function uses QCoreApplication::applicationFilePath() to get the name * of the executable to include in the message. * * \sa QCoreApplication::applicationFilePath() */ QString QxtCommandOptions::getUnrecognizedWarning() const { QString usage; QTextStream stream(&usage); showUnrecognizedWarning(*&stream); return usage; } /*! * This is an overloaded member function, provided for convenience. * * Outputs a warning about any unrecognized options to the provided stream. * * This function returns true if any warnings were output, or false otherwise. * * If a QCoreApplication or a subclass of QCoreApplication has been instantiated, * this function uses QCoreApplication::applicationFilePath() to get the name * of the executable to include in the message. * * \sa QCoreApplication::applicationFilePath() */ bool QxtCommandOptions::showUnrecognizedWarning(QTextStream& stream) const { if (!qxt_d().unrecognized.count() && !qxt_d().missingParams.count()) return false; QString name; if (QCoreApplication::instance()) name = QDir(QCoreApplication::applicationFilePath()).dirName(); if (name.isEmpty()) name = "QxtCommandOptions"; if (qxt_d().unrecognized.count()) stream << name << ": " << tr("unrecognized parameters: ") << qxt_d().unrecognized.join(" ") << endl; foreach(const QString& param, qxt_d().missingParams) stream << name << ": " << tr("%1 requires a parameter").arg(param) << endl; return true; } /*! * This is an overloaded member function, provided for convenience. * * Outputs automatically-generated usage text for the accepted options to the provided * device, or standard error by default. The device must already be opened for writing. * * Pass true to showQtOptions to output usage text for the options recognized by * QApplication. * * \sa QApplication */ void QxtCommandOptions::showUsage(bool showQtOptions, QIODevice* device) const { if (!device) { QTextStream stream(stdout); showUsage(showQtOptions, *&stream); } else { QTextStream stream(device); showUsage(showQtOptions, *&stream); } } /*! * Returns the automatically-generated usage text for the accepted options. */ QString QxtCommandOptions::getUsage(bool showQtOptions) const { QString usage; QTextStream stream(&usage); showUsage(showQtOptions, *&stream); return usage; } /*! * This is an overloaded member function, provided for convenience. * * Outputs automatically-generated usage text for the accepted options to the provided * stream. * * Pass true to showQtOptions to output usage text for the options recognized by * QApplication. * * \sa QApplication */ void QxtCommandOptions::showUsage(bool showQtOptions, QTextStream& stream) const { QStringList names; QStringList descs; int maxNameLength = 0; QString name; foreach(const QxtCommandOption& option, qxt_d().options) { // Don't generate usage for undocumented parameters if (option.paramType & Undocumented) continue; foreach(const QString& n, option.names) { if (name.length()) name += ", "; if (qxt_d().flagStyle == Slash) name += '/'; else if (qxt_d().flagStyle == DoubleDash && n.length() > 1) name += "--"; else name += '-'; name += n; if (option.paramType & (ValueOptional | ValueRequired)) { if (option.paramType & ValueOptional) name += "[=x]"; else if (qxt_d().paramStyle == SpaceAndEquals) name += "[=]x"; else if (qxt_d().paramStyle == Equals) name += "=x"; else name += " x"; } } // The maximum name length is used for formatting the output columns if (name.length() > maxNameLength) maxNameLength = name.length(); names.append(name); descs.append(option.desc); name = ""; } if (showQtOptions) { // Add a section header names.append(QString()); descs.append("Common Qt Options"); // Parse through qxt_qt_options const char* option; bool optionHasValue; for (int i = 0; qxt_qt_options[i]; i += 2) { option = qxt_qt_options[i]; if (option[0] == '=') { // The option takes a parameter optionHasValue = true; option = option + 1; // pointer math to skip the = } else { optionHasValue = false; } // Concatenate on the option alias if (!name.isEmpty()) name += ", "; name += '-'; name += option; if (optionHasValue) name += "[=]x"; if (qxt_qt_options[i+1][0] != 0) { // The last alias for the option has the description if (name.length() > maxNameLength) maxNameLength = name.length(); names.append(name); descs.append(qxt_qt_options[i+1]); name = ""; } } } int ct = names.count(); QString line, wrap(maxNameLength + 3, ' '); for (int i = 0; i < ct; i++) { if (names[i].isEmpty()) { // Section headers have no name entry stream << endl << descs[i] << ":" << endl; continue; } line = ' ' + names[i] + QString(maxNameLength - names[i].length() + 2, ' '); foreach(const QString& word, descs[i].split(' ', QString::SkipEmptyParts)) { if (qxt_d().screenWidth > 0 && line.length() + word.length() >= qxt_d().screenWidth) { stream << line << endl; line = wrap; } line += word + ' '; } stream << line << endl; } } libqxt-0.6.2/src/core/qxtcommandoptions.h000066400000000000000000000113261215241066400205050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCOMMANDOPTIONS_H #define QXTCOMMANDOPTIONS_H #include #include #include #include // for Q_DECLARE_TR_FUNCTIONS #include #include class QxtCommandOptionsPrivate; QT_FORWARD_DECLARE_CLASS(QTextStream) QT_FORWARD_DECLARE_CLASS(QIODevice) class QXT_CORE_EXPORT QxtCommandOptions { Q_DECLARE_TR_FUNCTIONS(QxtCommandOptions) public: /*! * \enum QxtCommandOptions::FlagStyle * This enum type defines which type of option prefix is used. * Slash is the default on Windows. * DoubleDash is the default on all other platforms. */ enum FlagStyle { DoubleDash, /*!< Two dashes (GNU-style) */ SingleDash, /*!< One dash (UNIX-style) */ Slash /*!< Forward slash (Windows-style) */ }; /*! * \enum QxtCommandOptions::ParamStyle * This enum type defines what syntax is used for options that * require parameters. Equals is the default on Windows. * SpaceAndEquals is the default on all other platforms. */ enum ParamStyle { Space = 1, /*!< Space ("-option value") */ Equals = 2, /*!< Equals sign ("/option=value") */ SpaceAndEquals = 3 /*!< Accept either */ }; /*! * \enum QxtCommandOptions::ParamType * \flags QxtCommandOptions::ParamTypes * This enum type is used to specify flags that control the * interpretation of an option. * * The ParamTypes type is a typedef for QFlags. It stores * an OR combination of ParamType values. */ enum ParamType { NoValue = 0, /*!< The option does not accept a value. */ ValueOptional = 1, /*!< The option may accept a value. */ ValueRequired = 2, /*!< The option requires a value. */ Optional = ValueOptional, /*!< The option may accept a value. Deprecated in favor of ValueOptional. */ Required = ValueRequired, /*!< The option requires a value. Deprecated in favor of ValueRequired. */ AllowMultiple = 4, /*!< The option may be passed multiple times. */ Undocumented = 8 /*!< The option is not output in the help text. */ }; Q_DECLARE_FLAGS(ParamTypes, ParamType) QxtCommandOptions(); void setFlagStyle(FlagStyle style); FlagStyle flagStyle() const; void setParamStyle(ParamStyle style); ParamStyle paramStyle() const; void setScreenWidth(quint16 width); quint16 screenWidth() const; void addSection(const QString& name); void add(const QString& name, const QString& desc = QString(), ParamTypes paramType = NoValue, int group = -1); void alias(const QString& from, const QString& to); QStringList positional() const; QStringList unrecognized() const; int count(const QString& name) const; QVariant value(const QString& name) const; QMultiHash parameters() const; void parse(int argc, char** argv); void parse(QStringList params); void showUsage(bool showQtOptions = false, QIODevice* device = 0) const; void showUsage(bool showQtOptions, QTextStream& stream) const; QString getUsage(bool showQtOptions = false) const; bool showUnrecognizedWarning(QIODevice* device = 0) const; bool showUnrecognizedWarning(QTextStream& stream) const; QString getUnrecognizedWarning() const; private: QXT_DECLARE_PRIVATE(QxtCommandOptions) }; Q_DECLARE_OPERATORS_FOR_FLAGS(QxtCommandOptions::ParamTypes) #endif // QXTCOMMANDOPTIONS_H libqxt-0.6.2/src/core/qxtcore.h000066400000000000000000000051731215241066400164060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCORE_H_INCLUDED #define QXTCORE_H_INCLUDED #include "qxtabstractfileloggerengine.h" #include "qxtabstractconnectionmanager.h" #include "qxtabstractiologgerengine.h" #include "qxtabstractsignalserializer.h" #include "qxtalgorithms.h" #include "qxtbasicfileloggerengine.h" #include "qxtbasicstdloggerengine.h" #include "qxtboundcfunction.h" #include "qxtboundfunction.h" #include "qxtboundfunctionbase.h" #include "qxtcommandoptions.h" #include "qxtcsvmodel.h" #include "qxtdaemon.h" #include "qxtdatastreamsignalserializer.h" #include "qxtdeplex.h" #include "qxterror.h" #include "qxtfifo.h" #include "qxtfilelock.h" #include "qxtglobal.h" #include "qxthmac.h" #include "qxtjson.h" #include "qxtjob.h" #include "qxtlinesocket.h" #include "qxtlinkedtree.h" #include "qxtlogger.h" #include "qxtloggerengine.h" #include "qxtlogstream.h" #include "qxtlocale.h" #include "qxtmetaobject.h" #include "qxtmetatype.h" #include "qxtmodelserializer.h" #include "qxtmultisignalwaiter.h" #include "qxtnamespace.h" #include "qxtnull.h" #include "qxtnullable.h" #include "qxtpairlist.h" #include "qxtpimpl.h" #include "qxtpipe.h" #include "qxtpointerlist.h" #include "qxtrpcservice.h" #include "qxtsharedprivate.h" #include "qxtsignalgroup.h" #include "qxtsignalwaiter.h" #include "qxtslotjob.h" #include "qxtslotmapper.h" #include "qxtstdio.h" #include "qxtstdstreambufdevice.h" #include "qxttimer.h" #include "qxttypelist.h" #include "qxtxmlfileloggerengine.h" #endif // QXTCORE_H_INCLUDED libqxt-0.6.2/src/core/qxtcsvmodel.cpp000066400000000000000000000300101215241066400176110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtCsvModel \inmodule QxtCore \brief The QxtCsvModel class provides a QAbstractTableModel for CSV Files */ /*! \fn QxtCsvModel::QxtCsvModel(QObject *parent = 0); Constructs a new QxtCsvModel with \a parent */ /*! \fn QxtCsvModel::~QxtCsvModel(); Destructor */ /*! \fn QxtCsvModel::QxtCsvModel(QIODevice *file, QObject *parent=0, bool withHeader = false, QChar separator= ',') constructs a QxtCsvModel from a QIODevice \a file as source \a withHeader specifies if the data on the device contains a header or not. \a separator is the separator to use for the columns. most widely used separators are ',' '\\t' ';' */ /*! \fn QxtCsvModel::QxtCsvModel(const QString filename, QObject *parent = 0, bool withHeader = false, QChar separator = ',') constructs a QxtCsvModel from \a filename as source \a withHeader specifies if the data in the file contains a header or not. \a separator is the separator to use for the columns. most widely used separators are ',' '\\t' ';' */ /*! \fn void QxtCsvModel::setSource(QIODevice *file, bool withHeader = false, QChar separator = ','); reads the cvs data from \a file \a withHeader specifies if the data on the device contains a header or not. \a separator is the separator to use for the columns. most widely used separators are ',' '\\t' ';' */ /*! \fn void QxtCsvModel::setSource(const QString filename, bool withHeader = false, QChar separator = ','); reads the cvs data from \a filename \a withHeader specifies if the data in the file contains a header or not. \a separator is the separator to use for the columns. most widely used separators are ',' '\\t' ';' */ /*! \fn void QxtCsvModel::toCSV(QIODevice *file, bool withHeader = false, QChar separator = ','); writes the cvs data to \a file \a withHeader specifies if to write the header or not \a separator is the separator to use for the columns. most widely used separators are ',' '\\t' ';' */ /*! \fn void QxtCsvModel::toCSV(const QString filename, bool withHeader = false, QChar separator = ','); writes the cvs data to \a filename \a withHeader specifies if to write the header or not \a separator is the separator to use for the columns. most widely used separators are ',' '\\t' ';' */ #include "qxtcsvmodel.h" #include #include class QxtCsvModelPrivate : public QxtPrivate { public: QxtCsvModelPrivate() : csvData(), header(), maxColumn(0) {} QXT_DECLARE_PUBLIC(QxtCsvModel) QStringList csvData; QStringList header; int maxColumn; }; QxtCsvModel::QxtCsvModel(QObject *parent) : QAbstractTableModel(parent) { QXT_INIT_PRIVATE(QxtCsvModel); } QxtCsvModel::QxtCsvModel(QIODevice *file, QObject *parent, bool withHeader, QChar separator) : QAbstractTableModel(parent) { QXT_INIT_PRIVATE(QxtCsvModel); setSource(file, withHeader, separator); } QxtCsvModel::QxtCsvModel(const QString filename, QObject *parent, bool withHeader, QChar separator) : QAbstractTableModel(parent) { QXT_INIT_PRIVATE(QxtCsvModel); QFile src(filename); setSource(&src, withHeader, separator); } QxtCsvModel::~QxtCsvModel() {} /*! \reimp */ int QxtCsvModel::rowCount(const QModelIndex& parent) const { if (parent.row() != -1 && parent.column() != -1) return 0; return qxt_d().csvData.count(); } /*! \reimp */ int QxtCsvModel::columnCount(const QModelIndex& parent) const { if (parent.row() != -1 && parent.column() != -1) return 0; return qxt_d().maxColumn; } /*! \reimp */ QVariant QxtCsvModel::data(const QModelIndex& index, int role) const { if (index.parent() != QModelIndex()) return QVariant(); if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) return qxt_d().csvData[index.row()].section(QChar(1), index.column(), index.column()); else { //QVariant v; return QVariant(); } } /*! \reimp */ QVariant QxtCsvModel::headerData(int section, Qt::Orientation orientation, int role) const { if (section < qxt_d().header.count() && orientation == Qt::Horizontal && (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole)) { return qxt_d().header[section]; } else return QAbstractTableModel::headerData(section, orientation, role); } void QxtCsvModel::setSource(const QString filename, bool withHeader, QChar separator) { QFile src(filename); setSource(&src, withHeader, separator); } void QxtCsvModel::setSource(QIODevice *file, bool withHeader, QChar separator) { QxtCsvModelPrivate* d_ptr = &qxt_d(); QString l; int size; bool isQuoted, headerSet = false; if (!file->isOpen()) file->open(QIODevice::ReadOnly); if (withHeader) d_ptr->maxColumn = 0; else d_ptr->maxColumn = d_ptr->header.size(); d_ptr->csvData.clear(); while (!file->atEnd()) { l = file->readLine(); l.remove('\n'); l.remove('\r'); size = l.length(); isQuoted = false; for (int i = 0;i < size;i++) { if (i > 0) { if (l[i] == '"' && l[i-1] != '\\') isQuoted = !isQuoted; else if (!isQuoted && l[i] == separator) l[i] = QChar(1); } else { if (l[i] == '"') isQuoted = !isQuoted; else if (!isQuoted && l[i] == separator) l[i] = QChar(1); } } if (l.count(QChar(1)) + 1 > d_ptr->maxColumn) d_ptr->maxColumn = l.count(QChar(1)) + 1; if (withHeader && !headerSet) { d_ptr->header = l.split(QChar(1)); headerSet = true; } else d_ptr->csvData.append(l); } file->close(); } /*! \reimp */ void QxtCsvModel::setHeaderData(const QStringList data) { qxt_d().header = data; emit headerDataChanged(Qt::Horizontal, 0, data.count()); } /*! \reimp */ bool QxtCsvModel::setData(const QModelIndex& index, const QVariant& data, int role) { if (index.parent() != QModelIndex()) return false; QString before, after; if (role == Qt::DisplayRole || role == Qt::EditRole || role == Qt::UserRole) { if (index.row() >= rowCount() || index.column() >= columnCount() || index.row() < 0 || index.column() < 0) return false; if (index.column() != 0) before = qxt_d().csvData[index.row()].section(QChar(1), 0, index.column() - 1) + QChar(1); else before = ""; after = qxt_d().csvData[index.row()].section(QChar(1), index.column() + 1); qxt_d().csvData[index.row()] = before + data.toString() + QChar(1) + after; emit dataChanged(index, index); return true; } else { return false; } } /*! \reimp */ bool QxtCsvModel::insertRow(int row, const QModelIndex& parent) { return insertRows(row, 1, parent); } /*! \reimp */ bool QxtCsvModel::insertRows(int row, int count, const QModelIndex& parent) { if (parent != QModelIndex() || row < 0) return false; emit beginInsertRows(parent, row, row + count); QxtCsvModelPrivate& d_ptr = qxt_d(); if (row >= rowCount()) { for (int i = 0;i < count;i++) d_ptr.csvData << ""; } else { for (int i = 0;i < count;i++) d_ptr.csvData.insert(row, ""); } emit endInsertRows(); return true; } /*! \reimp */ bool QxtCsvModel::removeRow(int row, const QModelIndex& parent) { return removeRows(row, 1, parent); } /*! \reimp */ bool QxtCsvModel::removeRows(int row, int count, const QModelIndex& parent) { if (parent != QModelIndex() || row < 0) return false; if (row >= rowCount()) return false; if (row + count >= rowCount()) count = rowCount() - row; emit beginRemoveRows(parent, row, row + count); QxtCsvModelPrivate& d_ptr = qxt_d(); for (int i = 0;i < count;i++) d_ptr.csvData.removeAt(row); emit endRemoveRows(); return true; } /*! \reimp */ bool QxtCsvModel::insertColumn(int col, const QModelIndex& parent) { return insertColumns(col, 1, parent); } /*! \reimp */ bool QxtCsvModel::insertColumns(int col, int count, const QModelIndex& parent) { if (parent != QModelIndex() || col < 0) return false; beginInsertColumns(parent, col, col + count - 1); QxtCsvModelPrivate& d_ptr = qxt_d(); if (col < columnCount()) { QString before, after; for (int i = 0;i < rowCount();i++) { if (col > 0) before = d_ptr.csvData[i].section(QChar(1), 0, col - 1) + QChar(1); else before = ""; after = d_ptr.csvData[i].section(QChar(1), col); d_ptr.csvData[i] = before + QString(count, QChar(1)) + after; } } for (int i = 0;i < count;i++) d_ptr.header.insert(col, ""); d_ptr.maxColumn += count; endInsertColumns(); return true; } /*! \reimp */ bool QxtCsvModel::removeColumn(int col, const QModelIndex& parent) { return removeColumns(col, 1, parent); } /*! \reimp */ bool QxtCsvModel::removeColumns(int col, int count, const QModelIndex& parent) { if (parent != QModelIndex() || col < 0) return false; if (col >= columnCount()) return false; if (col + count >= columnCount()) count = columnCount() - col; emit beginRemoveColumns(parent, col, col + count); QxtCsvModelPrivate& d_ptr = qxt_d(); QString before, after; for (int i = 0;i < rowCount();i++) { if (col > 0) before = d_ptr.csvData[i].section(QChar(1), 0, col - 1) + QChar(1); else before = ""; after = d_ptr.csvData[i].section(QChar(1), col + count); d_ptr.csvData[i] = before + after; } for (int i = 0;i < count;i++) d_ptr.header.removeAt(col); emit endRemoveColumns(); return true; } void QxtCsvModel::toCSV(QIODevice* dest, bool withHeader, QChar separator) { QxtCsvModelPrivate& d_ptr = qxt_d(); int row, col, rows, cols; rows = rowCount(); cols = columnCount(); QString data; if (!dest->isOpen()) dest->open(QIODevice::WriteOnly | QIODevice::Truncate); if (withHeader) { data = ""; for (col = 0; col < cols; ++col) { data += '"' + d_ptr.header.at(col) + '"'; if (col < cols - 1) data += separator; } data += QChar(10); dest->write(data.toLatin1()); } for (row = 0; row < rows; ++row) { data = ""; for (col = 0; col < cols; ++col) { data += '"' + d_ptr.csvData[row].section(QChar(1), col, col) + '"'; if (col < cols - 1) data += separator; } data += QChar(10); dest->write(data.toLatin1()); } dest->close(); } void QxtCsvModel::toCSV(const QString filename, bool withHeader, QChar separator) { QFile dest(filename); toCSV(&dest, withHeader, separator); } /*! \reimp */ Qt::ItemFlags QxtCsvModel::flags(const QModelIndex& index) const { return Qt::ItemIsEditable | QAbstractTableModel::flags(index); } libqxt-0.6.2/src/core/qxtcsvmodel.h000066400000000000000000000064601215241066400172720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCSVMODEL_H #define QXTCSVMODEL_H #include #include #include #include #include #include #include #include class QxtCsvModelPrivate; class QXT_CORE_EXPORT QxtCsvModel : public QAbstractTableModel { Q_OBJECT public: QxtCsvModel(QObject *parent = 0); explicit QxtCsvModel(QIODevice *file, QObject *parent = 0, bool withHeader = false, QChar separator = ','); explicit QxtCsvModel(const QString filename, QObject *parent = 0, bool withHeader = false, QChar separator = ','); ~QxtCsvModel(); int rowCount(const QModelIndex& parent = QModelIndex()) const; int columnCount(const QModelIndex& parent = QModelIndex()) const; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; bool setData(const QModelIndex& index, const QVariant& data, int role = Qt::EditRole); QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; void setHeaderData(const QStringList data); bool insertRow(int row, const QModelIndex& parent = QModelIndex()); bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()); bool removeRow(int row, const QModelIndex& parent = QModelIndex()); bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()); bool insertColumn(int col, const QModelIndex& parent = QModelIndex()); bool insertColumns(int col, int count, const QModelIndex& parent = QModelIndex()); bool removeColumn(int col, const QModelIndex& parent = QModelIndex()); bool removeColumns(int col, int count, const QModelIndex& parent = QModelIndex()); void setSource(QIODevice *file, bool withHeader = false, QChar separator = ','); void setSource(const QString filename, bool withHeader = false, QChar separator = ','); void toCSV(QIODevice *file, bool withHeader = false, QChar separator = ','); void toCSV(const QString filename, bool withHeader = false, QChar separator = ','); Qt::ItemFlags flags(const QModelIndex& index) const; private: QXT_DECLARE_PRIVATE(QxtCsvModel) }; #endif libqxt-0.6.2/src/core/qxtdaemon.cpp000066400000000000000000000163121215241066400172510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtDaemon \inmodule QxtCore \brief The QxtDaemon class is a Qt-based Implementation of a Unix daemon QxtDaemon will provide you with a standard UNIX daemon implementation. after sucessful forking it will install a messageHandler which logs all qDebug/qWarning/etc... output to /var/log/mydaemon.log example usage: \code int main(int argc, char ** argv) { QxtDaemon d("exampled"); qDebug("about to fork"); d.daemonize(); qDebug("forked"); d.changeUser("nobody"); QCoreApplication app(argc,argv); return app.exec(); } \endcode */ #include "qxtdaemon.h" #include #include #include #include #include #ifdef Q_OS_UNIX #include #include #include #include #include #include #endif static QxtDaemon * qxt_daemon_singleton = 0; #ifdef Q_OS_UNIX void QxtDaemon::signalHandler(int sig) { emit(qxt_daemon_singleton->signal(sig)); if (sig == SIGHUP) { qDebug("hangup signal caught"); emit(qxt_daemon_singleton->hangup()); } else if (sig == SIGTERM) { qDebug("terminate signal caught"); emit(qxt_daemon_singleton->terminate()); QCoreApplication::exit(0); } } #endif void QxtDaemon::messageHandler(QtMsgType type, const char *msg) { QFile * f = qxt_daemon_singleton->logfile; f->write("["); f->write(QDateTime::currentDateTime().toString(Qt::ISODate).toLocal8Bit()); f->write("] "); if (type == QtDebugMsg) f->write("[qDebug] "); else if (type == QtWarningMsg) f->write("[qWarning] "); else if (type == QtCriticalMsg) f->write("[qCritical] "); else if (type == QtFatalMsg) { f->write("[qFatal] "); f->write(msg); f->write("\n"); f->write("aborting \n"); f->flush(); abort(); } f->write(msg); f->write("\n"); f->flush(); } /*! constructs a new QxtDaemon the applicationName is used as a base for log and pid files */ QxtDaemon::QxtDaemon(QString name) { #ifdef Q_OS_UNIX if (name.isEmpty()) { qFatal("you need to set an applicationName (e.g. using QCoreApplication::setApplicationName() )"); } if (qxt_daemon_singleton) { qFatal("unable to construct more then one QxtDaemon instance"); } else { qxt_daemon_singleton = this; m_name = name; logfile = new QFile("/var/log/" + m_name + ".log"); } #else qFatal("currently QxtDaemon is only implemented on unix"); #endif } /*based on work of Levent Karakas May 2001*/ /*! forks the current Process you can specify weather it will write a pidfile to /var/run/mydaemon.pid or not if you specify true (the default) QxtDaemon will also try to lock the pidfile. If it can't get a lock it will assume another daemon of the same name is already running and exit be aware that after calling this function all file descriptors are invalid. QFile will not detect the change, you have to explicitly close all files before forking. return true on success */ bool QxtDaemon::daemonize(bool pidfile) { #if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) if (!logfile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) qFatal("cannot open logfile %s", qPrintable(logfile->fileName())); logfile->close(); if (pidfile) { QFile f("/var/run/" + m_name + ".pid"); if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) qFatal("cannot open pidfile \"/var/run/%s.pid\"", qPrintable(m_name)); if (lockf(f.handle(), F_TEST, 0) < 0) qFatal("can't get a lock on \"/var/run/%s.pid\". another instance is propably already running.", qPrintable(m_name)); f.close(); } if (!logfile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) qFatal("cannot open logfile %s", qPrintable(logfile->fileName())); logfile->close(); int i; if (getppid() == 1) return true; /* already a daemon */ i = fork(); /* double fork.*/ if (i < 0) return false; /*fork error */ if (i > 0) exit(0); /*parent exits */ if (i < 0) return false; /*fork error */ if (i > 0) exit(0); /*parent exits */ /* child (daemon) continues */ setsid(); /* obtain a new process group */ for (i = getdtablesize();i >= 0;--i) close(i); /* close all descriptors */ #ifdef Q_OS_LINUX ::umask(027); /* some programmers don't understand security, so we set a sane default here */ #endif ::signal(SIGCHLD, SIG_IGN); /* ignore child */ ::signal(SIGTSTP, SIG_IGN); /* ignore tty signals */ ::signal(SIGTTOU, SIG_IGN); ::signal(SIGTTIN, SIG_IGN); ::signal(SIGHUP, QxtDaemon::signalHandler); /* catch hangup signal */ ::signal(SIGTERM, QxtDaemon::signalHandler); /* catch kill signal */ if (pidfile) { int lfp =::open(qPrintable("/var/run/" + m_name + ".pid"), O_RDWR | O_CREAT, 0640); if (lfp < 0) qFatal("cannot open pidfile \"/var/run/%s.pid\"", qPrintable(m_name)); if (lockf(lfp, F_TLOCK, 0) < 0) qFatal("can't get a lock on \"/var/run/%s.pid\". another instance is propably already running.", qPrintable(m_name)); QByteArray d = QByteArray::number(pid()); Q_UNUSED(::write(lfp, d.constData(), d.size())); } assert(logfile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)); qInstallMsgHandler(QxtDaemon::messageHandler); return true; #else return false; #endif } /*! returns the current processId */ int QxtDaemon::pid() { #ifdef Q_OS_UNIX return getpid(); #else return -1; #endif } /*! changes the current user of this process. do this after forking to drop root rights. returns true on success */ bool QxtDaemon::changeUser(QString name) { #ifdef Q_OS_UNIX ///according to the posix spec, i'm not suposed to delete it. *shrug* weird passwd *p =::getpwnam(qPrintable(name)); if (!p) return false; return setuid(p->pw_uid) == 0; #else return false; #endif } libqxt-0.6.2/src/core/qxtdaemon.h000066400000000000000000000036041215241066400167160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTDAEMON_H #define QXTDAEMON_H #include "qxtglobal.h" #include #include #include QT_FORWARD_DECLARE_CLASS(QFile) class QXT_CORE_EXPORT QxtDaemon : public QObject { Q_OBJECT public: QxtDaemon(QString applicationName = QCoreApplication::applicationName()); bool daemonize(bool pidfile = true); static int pid(); bool changeUser(QString name); #ifndef QXT_DOXYGEN_RUN static void messageHandler(QtMsgType type, const char *msg); #ifdef Q_OS_UNIX static void signalHandler(int signal); #endif #endif private: QString m_name; QFile *logfile; Q_SIGNALS: void signal(int); void hangup(); void terminate(); }; #endif // QXT_DAEMON_H libqxt-0.6.2/src/core/qxtdatastreamsignalserializer.cpp000066400000000000000000000064431215241066400234270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include #include #include #include #include #include QByteArray QxtDataStreamSignalSerializer::serialize(const QString& fn, const QVariant& p1, const QVariant& p2, const QVariant& p3, const QVariant& p4, const QVariant& p5, const QVariant& p6, const QVariant& p7, const QVariant& p8) const { QByteArray rv; QDataStream str(&rv, QIODevice::WriteOnly); str << fn; unsigned char ct = 8; if (!p1.isValid()) ct = 0; else if (!p2.isValid()) ct = 1; else if (!p3.isValid()) ct = 2; else if (!p4.isValid()) ct = 3; else if (!p5.isValid()) ct = 4; else if (!p6.isValid()) ct = 5; else if (!p7.isValid()) ct = 6; else if (!p8.isValid()) ct = 7; str << ct; if (ct-- > 0) str << p1; if (ct-- > 0) str << p2; if (ct-- > 0) str << p3; if (ct-- > 0) str << p4; if (ct-- > 0) str << p5; if (ct-- > 0) str << p6; if (ct-- > 0) str << p7; if (ct-- > 0) str << p8; char sizeData[4]; qToLittleEndian(quint32(rv.size()), (uchar*)sizeData); return QByteArray(sizeData, 4) + rv; } QxtAbstractSignalSerializer::DeserializedData QxtDataStreamSignalSerializer::deserialize(QByteArray& data) { QByteArray cmd; quint32 len = qFromLittleEndian(reinterpret_cast(data.constData())); cmd = data.mid(4, len); data = data.mid(len + 4); if (cmd.length() == 0) return NoOp(); QDataStream str(cmd); QString signal; unsigned char argCount; QList v; QVariant t; str >> signal >> argCount; if (str.status() == QDataStream::ReadCorruptData) return ProtocolError(); for (int i = 0; i < argCount; i++) { str >> t; v << t; } return qMakePair(signal, v); } bool QxtDataStreamSignalSerializer::canDeserialize(const QByteArray& buffer) const { if(buffer.length() < int(sizeof(quint32))) return false; quint32 headerLen = qFromLittleEndian(reinterpret_cast(buffer.constData())); quint32 bodyLen = quint32(buffer.length() - 4); return headerLen <= bodyLen; } libqxt-0.6.2/src/core/qxtdatastreamsignalserializer.h000066400000000000000000000043111215241066400230640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTDATASTREAMSIGNALSERIALIZER_H #define QXTDATASTREAMSIGNALSERIALIZER_H #include #include class QXT_CORE_EXPORT QxtDataStreamSignalSerializer : public QxtAbstractSignalSerializer { public: /*! * Serializes a signal into a form suitable for sending to an I/O device. */ virtual QByteArray serialize(const QString& fn, const QVariant& p1 = QVariant(), const QVariant& p2 = QVariant(), const QVariant& p3 = QVariant(), const QVariant& p4 = QVariant(), const QVariant& p5 = QVariant(), const QVariant& p6 = QVariant(), const QVariant& p7 = QVariant(), const QVariant& p8 = QVariant()) const; /*! * Deserializes binary data into a signal name and a list of parameters. */ virtual DeserializedData deserialize(QByteArray& data); /*! * Indicates whether the data currently in the buffer can be deserialized. */ virtual bool canDeserialize(const QByteArray& buffer) const; }; #endif libqxt-0.6.2/src/core/qxtdeplex.cpp000066400000000000000000000066011215241066400172670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtdeplex_p.h" /*! \class QxtDeplex \inmodule QxtCore \brief The QxtDeplex class puts a standard QIODevice into a QxtPipe chain implements a normal QxtPipe with the exception that r/w operations are delegated to the device set by setDevice() \sa QIODevice \sa QxtPipe */ /*! \fn QxtDeplex::QxtDeplex(QObject * parent) \brief creates a new QxtDeplex \fn QxtDeplex::QxtDeplex(QIODevice * device,QObject * parent) \brief creates a new QxtDeplex and delegates r/w operations to the device \fn void QxtDeplex::setDevice(QIODevice * device); \brief delegate r/w operations to the device \fn QIODevice *QxtDeplex::device() const; \brief returns the device currently delegated \fn virtual void QxtDeplex::receiveData (QByteArray data, const QxtPipe * sender ) */ QxtDeplex::QxtDeplex(QObject * parent): QxtPipe(parent) { QXT_INIT_PRIVATE(QxtDeplex); qxt_d().delegate = 0; setDevice(0); } QxtDeplex::QxtDeplex(QIODevice * device, QObject * parent): QxtPipe(parent) { QXT_INIT_PRIVATE(QxtDeplex); qxt_d().delegate = 0; setDevice(device); } void QxtDeplex::setDevice(QIODevice * device) { if (qxt_d().delegate) { QObject::disconnect(qxt_d().delegate, SIGNAL(readyRead()), &qxt_d(), SLOT(readyRead())); QObject::disconnect(qxt_d().delegate, SIGNAL(destroyed(QObject *)), &qxt_d(), SLOT(extDestroyed(QObject *))); } qxt_d().delegate = device; if (qxt_d().delegate) { QObject::connect(qxt_d().delegate, SIGNAL(readyRead()), &qxt_d(), SLOT(readyRead())); QObject::connect(qxt_d().delegate, SIGNAL(destroyed(QObject *)), &qxt_d(), SLOT(extDestroyed(QObject *))); } } QIODevice *QxtDeplex::device() const { return qxt_d().delegate; } void QxtDeplexPrivate::readyRead() { QByteArray d = static_cast(sender())->readAll(); qxt_p().enqueData(d); qxt_p().sendData(d); } void QxtDeplexPrivate::extDestroyed(QObject *) { delegate = 0; } qint64 QxtDeplex::writeData(const char * a, qint64 s) { if (!qxt_d().delegate) return 0; return qxt_d().delegate->write(a, s); } void QxtDeplex::receiveData(QByteArray data, const QxtPipe *) { if (!qxt_d().delegate) return; qxt_d().delegate->write(data); } libqxt-0.6.2/src/core/qxtdeplex.h000066400000000000000000000033521215241066400167340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTDEPLEX_H #define QXTDEPLEX_H #include "qxtglobal.h" #include "qxtpipe.h" class QxtDeplexPrivate; class QXT_CORE_EXPORT QxtDeplex : public QxtPipe { Q_OBJECT public: QxtDeplex(QObject * parent = 0); explicit QxtDeplex(QIODevice * device, QObject * parent = 0); void setDevice(QIODevice * device); QIODevice *device() const; protected: virtual qint64 writeData(const char * data, qint64 maxSize); virtual void receiveData(QByteArray data, const QxtPipe * sender); private: QXT_DECLARE_PRIVATE(QxtDeplex) }; #endif // QXTDEPLEX_H libqxt-0.6.2/src/core/qxtdeplex_p.h000066400000000000000000000033561215241066400172570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /**************************************************************************** * this is private API. it might change at any time without notice. yarly. *****************************************************************************/ #ifndef QXTDEPLEX_P_H_INCLUDED #define QXTDEPLEX_P_H_INCLUDED #include "qxtdeplex.h" class QxtDeplexPrivate: public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtDeplex) QIODevice * delegate; public Q_SLOTS: void readyRead(); void extDestroyed(QObject*); }; #endif // QXTDEPLEX_P_H_INCLUDED libqxt-0.6.2/src/core/qxterror.cpp000066400000000000000000000036131215241066400171370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxterror.h" QxtError::QxtError(const char * file, long line, Qxt::ErrorCode errorcode, const char * errorString) { file_m = file; line_m = line; errorcode_m = errorcode; errorString_m = errorString; } Qxt::ErrorCode QxtError::errorCode() const { return errorcode_m; } long QxtError::line() const { return line_m; } const char * QxtError::file() const { return file_m; } QxtError::operator Qxt::ErrorCode() { return errorcode_m; } /*! The Error String or NULL depending how the error was constructed. Be carefull with stack and temporary objects, QxtError just saves the pointer you passed, not the actual data. */ const char * QxtError::errorString() const { return errorString_m; } libqxt-0.6.2/src/core/qxterror.h000066400000000000000000000061151215241066400166040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTERROR_H #define QXTERROR_H #include #include /*! \class QxtError QxtError \inmodule QxtCore \brief Information about Errors ocuring inside Qxt */ /*! \relates QxtError droping an error inside a function that returns QxtError short for return QxtError(__FILE__,__LINE__,x); */ #define QXT_DROP(x) return QxtError(__FILE__,__LINE__,x); /*! \relates QxtError droping an error inside a function that returns QxtError aditionaly specifies an errorstring \n short for return QxtError(__FILE__,__LINE__,x,s); */ #define QXT_DROP_S(x,s) return QxtError(__FILE__,__LINE__,x,s); /*! \relates QxtError droping no error inside a function that returns QxtError short for return QxtError(__FILE__,__LINE__,Qxt::NoError); */ #define QXT_DROP_OK return QxtError(__FILE__,__LINE__,Qxt::NoError); /*! \relates QxtError forward a drop drops from this function if the call inside dropped too. the inner function must return or be a QxtError. example \code QXT_DROP_F(critical_function()); \endcode */ #define QXT_DROP_F(call) {QxtError error_sds = call; if (error_sds != Qxt::NoError ) return error_sds; else (void)0; } /*! \relates QxtError check for errors example \code QXT_DROP_SCOPE(error,critical_function()) { qDebug()< ** ****************************************************************************/ /*! \class QxtFifo \inmodule QxtCore \brief The QxtFifo class provides a simple loopback QIODevice. read and write to the same object emits a readyRead Signal. useful for loopback tests where QBuffer does not work. \code QxtFifo fifo; QTextStream (&fifo)<>a; qDebug()< #include #include #include #include #if QT_VERSION >= 0x040400 # include # define QXT_EXCHANGE fetchAndStoreOrdered # define QXT_ADD fetchAndAddOrdered #else typedef QBasicAtomic QBasicAtomicInt; # define QXT_EXCHANGE exchange # define QXT_ADD fetchAndAdd #endif struct QxtFifoNode { QxtFifoNode(const char* data, int size) : content(data, size) { next = NULL; } QByteArray content; QBasicAtomicPointer next; }; class QxtFifoPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtFifo) QxtFifoPrivate() { head = tail = new QxtFifoNode(NULL, 0); available = 0; } QBasicAtomicPointer head, tail; QBasicAtomicInt available; }; /*! Constructs a new QxtFifo with \a parent. */ QxtFifo::QxtFifo(QObject *parent) : QIODevice(parent) { QXT_INIT_PRIVATE(QxtFifo); setOpenMode(QIODevice::ReadWrite); } /*! \reimp */ qint64 QxtFifo::readData ( char * data, qint64 maxSize ) { int bytes = qxt_d().available, step; if(!bytes) return 0; if(bytes > maxSize) bytes = maxSize; int written = bytes; char* writePos = data; QxtFifoNode* node; while(bytes > 0) { node = qxt_d().head; step = node->content.size(); if(step >= bytes) { int rem = step - bytes; memcpy(writePos, node->content.constData(), bytes); step = bytes; node->content = node->content.right(rem); } else { memcpy(writePos, node->content.constData(), step); qxt_d().head.QXT_EXCHANGE(node->next); delete node; node = qxt_d().head; } writePos += step; bytes -= step; } qxt_d().available.QXT_ADD(-written); return written; } /*! \reimp */ qint64 QxtFifo::writeData ( const char * data, qint64 maxSize ) { if(maxSize > 0) { if(maxSize > INT_MAX) maxSize = INT_MAX; // qint64 could easily exceed QAtomicInt, so let's play it safe QxtFifoNode* newData = new QxtFifoNode(data, maxSize); qxt_d().tail->next.QXT_EXCHANGE(newData); qxt_d().tail.QXT_EXCHANGE(newData); qxt_d().available.QXT_ADD(maxSize); QMetaObject::invokeMethod(this, "bytesWritten", Qt::QueuedConnection, Q_ARG(qint64, maxSize)); QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); } return maxSize; } /*! \reimp */ bool QxtFifo::isSequential () const { return true; } /*! \reimp */ qint64 QxtFifo::bytesAvailable () const { return qxt_d().available; } /*! */ void QxtFifo::clear() { qxt_d().available.QXT_EXCHANGE(0); qxt_d().tail.QXT_EXCHANGE(qxt_d().head); QxtFifoNode* node = qxt_d().head->next.QXT_EXCHANGE(NULL); while (node && node->next) { QxtFifoNode* next = node->next.QXT_EXCHANGE(NULL); delete node; node = next; } qxt_d().head->content = QByteArray(); } libqxt-0.6.2/src/core/qxtfifo.h000066400000000000000000000032541215241066400163770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTFIFO_H #define QXTFIFO_H #include "qxtglobal.h" #include class QxtFifoPrivate; class QXT_CORE_EXPORT QxtFifo : public QIODevice { Q_OBJECT public: QxtFifo(QObject * parent = 0); virtual bool isSequential() const; virtual qint64 bytesAvailable() const; void clear(); protected: virtual qint64 readData(char * data, qint64 maxSize); virtual qint64 writeData(const char * data, qint64 maxSize); private: QXT_DECLARE_PRIVATE(QxtFifo) }; #endif // QXTFIFO_H libqxt-0.6.2/src/core/qxtfilelock.cpp000066400000000000000000000111011215241066400175650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtfilelock.h" #include "qxtfilelock_p.h" /*! \class QxtFileLock \inmodule QxtCore \brief The QxtFileLock class provides a crossplattform way to lock a QFile. QxtFileLock supports range locking of a file. The File will take parentship of the lock. The lock gets cleaned up with the QFile, and it is released when the QFile is closed. Example usage: \code off_t lockstart = 0x10; off_t locklength = 30 QFile file("test.lock"); //the lock gets deleted when file is cleaned up QxtFileLock * writeLock = new QxtFileLock(&file,lockstart,locklength,QxtFileLock::WriteLock); if(file.open(QIODevice::ReadWrite)) { if(writeLock->lock()) { // some write operations writeLock->unlock(); } else //lock failed } \endcode \bold {Note:} QxtFileLock behaves different than normal unix locks on *nix. A thread can writelock the region of a file only ONCE if it uses two different handles. A different thread can not writelock a region that is owned by a other thread even if it is the SAME process. \bold {Note:} On *nix this class uses fctnl to lock the file. This may not be compatible to other locking functions like flock and lockf \bold {Note:} Please do not mix QxtFileLock and native file lock calls on the same QFile. The behaviour is undefined \bold {Note:} QxtFileLock lives in the same thread as the passed QFile \warning due to a refactoring issues of QFile this class will not work with Qt from version 4.3.0 to 4.3.2 */ /*! \fn bool QxtFileLock::lock() \brief Locks the file Returns \c true if succeeds, \c false otherwise. */ /*! \fn bool QxtFileLock::unlock() \brief Unlocks the file. Returns \c true if succeeds, \c false otherwise. */ /*! \enum QxtFileLock::Mode \brief The mode of the lock \value ReadLock A non blocking read lock \value WriteLock A non blocking write lock \value ReadLockWait A blocking read lock. The lock() function will block until the lock is created. \value WriteLockWait A blocking write lock. The lock() function will block until the lock is created. */ QxtFileLockPrivate::QxtFileLockPrivate() : offset(0), length(0), mode(QxtFileLock::WriteLockWait), isLocked(false) { } /*! Contructs a new QxtFileLock. The lock is not activated. \a file the file that should be locked \a offset the offset where the lock starts \a length the length of the lock \a mode the lockmode */ QxtFileLock::QxtFileLock(QFile *file, const off_t offset, const off_t length, const QxtFileLock::Mode mode) : QObject(file) { QXT_INIT_PRIVATE(QxtFileLock); connect(file, SIGNAL(aboutToClose()), this, SLOT(unlock())); qxt_d().offset = offset; qxt_d().length = length; qxt_d().mode = mode; } /*! Destructs the file lock. */ QxtFileLock::~QxtFileLock() { unlock(); } /*! Returns the offset of the lock */ off_t QxtFileLock::offset() const { return qxt_d().offset; } /*! Returns \c true if the lock is active otherwise it returns \c false */ bool QxtFileLock::isActive() const { return qxt_d().isLocked; } /*! Returns the length of the lock */ off_t QxtFileLock::length() const { return qxt_d().length; } /*! Returns the file the lock is created on. */ QFile * QxtFileLock::file() const { return qobject_cast(parent()); } /*! Returns the mode of the lock */ QxtFileLock::Mode QxtFileLock::mode() const { return qxt_d().mode; } libqxt-0.6.2/src/core/qxtfilelock.h000066400000000000000000000040061215241066400172400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTFILELOCK_H #define QXTFILELOCK_H #include #include #include "qxtglobal.h" #ifdef Q_OS_WIN #include typedef long off_t; #else #include #endif class QxtFileLockPrivate; class QXT_CORE_EXPORT QxtFileLock : public QObject { Q_OBJECT public: enum Mode { ReadLockWait, ReadLock, WriteLockWait, WriteLock }; QxtFileLock(QFile *file, const off_t offset, const off_t length, const QxtFileLock::Mode mode = WriteLockWait); ~QxtFileLock(); off_t offset() const; off_t length() const; bool isActive() const; QFile *file() const; QxtFileLock::Mode mode() const; public Q_SLOTS: bool lock(); bool unlock(); private: QxtFileLock(const QxtFileLock &other); QXT_DECLARE_PRIVATE(QxtFileLock) }; #endif // QXTFILELOCK_H libqxt-0.6.2/src/core/qxtfilelock_p.h000066400000000000000000000030721215241066400175610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTFILELOCK_P_H #define QXTFILELOCK_P_H #include #include #include #include class QxtFileLock; class QxtFileLockPrivate : public QxtPrivate { public: QxtFileLockPrivate(); QXT_DECLARE_PUBLIC(QxtFileLock) off_t offset; off_t length; QxtFileLock::Mode mode; bool isLocked; }; #endif // QXTFILELOCK_P_H libqxt-0.6.2/src/core/qxtfilelock_unix.cpp000066400000000000000000000207211215241066400206400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtfilelock.h" #include "qxtfilelock_p.h" #include #include #include #include /*include pthread to make errno threadsafe*/ #include #include #include #include #include /*! * \internal this class is used on *nix to register all locks created by a process and to let locks on *nix act like locks on windows */ class QxtFileLockRegistry { public: bool registerLock(QxtFileLock *lock); bool removeLock(QxtFileLock *lock); static QxtFileLockRegistry& instance(); private: QLinkedList < QPointer > procLocks; QMutex registryMutex; QxtFileLockRegistry(); }; QxtFileLockRegistry::QxtFileLockRegistry() {} QxtFileLockRegistry& QxtFileLockRegistry::instance() { static QxtFileLockRegistry instance; return instance; } /*! * \internal this function locks the lockregistry and checks if there is a collision between the process locks * \internal if there is no collision it inserts the lock into the registry and returns * \internal return true for success */ bool QxtFileLockRegistry::registerLock(QxtFileLock * lock) { QMutexLocker locker(&this->registryMutex); QFile *fileToLock = lock ->file(); if (fileToLock) { struct stat fileInfo; if (fstat(fileToLock->handle(), &fileInfo) < 0) return false; int newLockStart = lock ->offset(); int newLockEnd = lock ->offset() + lock ->length(); QMutableLinkedListIterator< QPointer >iterator(this->procLocks); while (iterator.hasNext()) { QPointer currLock = iterator.next(); if (currLock && currLock->file() && currLock->file()->isOpen()) { struct stat currFileInfo; /*first check if the current lock is on the same file*/ if (fstat(currLock->file()->handle(), &currFileInfo) < 0) { /*that should never happen because a closing file should remove all locks*/ Q_ASSERT(false); continue; } if (currFileInfo.st_dev == fileInfo.st_dev && currFileInfo.st_ino == fileInfo.st_ino) { /*same file, check if our locks are in conflict*/ int currLockStart = currLock->offset(); int currLockEnd = currLock->offset() + currLock->length(); /*do we have to check for threads here?*/ if (newLockEnd >= currLockStart && newLockStart <= currLockEnd) { //qDebug() << "we may have a collision"; //qDebug() << newLockEnd << " >= " << currLockStart << " && " << newLockStart << " <= " << currLockEnd; /*same lock region if one of both locks are exclusive we have a collision*/ if (lock ->mode() == QxtFileLock::WriteLockWait || lock ->mode() == QxtFileLock::WriteLock || currLock->mode() == QxtFileLock::WriteLockWait || currLock->mode() == QxtFileLock::WriteLock) { /*FIXED BUG #6 test rw_same() passes on Unix keeping the old code for a while */ return false; #if 0 //qDebug() << "Okay if this is not the same thread using the same handle there is a collision"; /*the same thread can lock the same region with the same handle*/ //qDebug() << "! (" << lock ->thread() << " == " << currLock->thread() << " && " << lock ->file()->handle() << " == " << currLock->file()->handle() << ")"; if (!(lock ->thread() == currLock->thread() && lock ->file()->handle() == currLock->file()->handle())) { qDebug() << "Collision"; return false; } #endif } } } } else //remove dead locks iterator.remove(); } //qDebug() << "The lock is okay"; /*here we can insert the lock into the list and return*/ procLocks.append(QPointer(lock)); return true; } return false; } bool QxtFileLockRegistry::removeLock(QxtFileLock * lock) { QMutexLocker locker(&this->registryMutex); procLocks.removeAll(lock); return true; } bool QxtFileLock::unlock() { if (file() && file()->isOpen() && isActive()) { /*first remove real lock*/ int lockmode, locktype; int result = -1; struct flock lockDesc; lockmode = F_SETLK; locktype = F_UNLCK; errno = 0; do { lockDesc.l_type = locktype; lockDesc.l_whence = SEEK_SET; lockDesc.l_start = qxt_d().offset; lockDesc.l_len = qxt_d().length; lockDesc.l_pid = 0; result = fcntl(this->file()->handle(), lockmode, &lockDesc); } while (result && errno == EINTR); QxtFileLockRegistry::instance().removeLock(this); qxt_d().isLocked = false; return true; } return false; } bool QxtFileLock::lock() { if (file() && file()->isOpen() && !isActive()) { /*this has to block if we can get no lock*/ bool locked = false; while (1) { locked = QxtFileLockRegistry::instance().registerLock(this); if (locked) break; else { if (qxt_d().mode == ReadLockWait || qxt_d().mode == WriteLockWait) usleep(1000 * 5); else return false; } } /*now get real lock*/ int lockmode, locktype; int result = -1; struct flock lockDesc; switch (qxt_d().mode) { case ReadLock: lockmode = F_SETLK; locktype = F_RDLCK; break; case ReadLockWait: lockmode = F_SETLKW; locktype = F_RDLCK; break; case WriteLock: lockmode = F_SETLK; locktype = F_WRLCK; break; case WriteLockWait: lockmode = F_SETLKW; locktype = F_WRLCK; break; default: QxtFileLockRegistry::instance().removeLock(this); return (false); break; } errno = 0; do { lockDesc.l_type = locktype; lockDesc.l_whence = SEEK_SET; lockDesc.l_start = qxt_d().offset; lockDesc.l_len = qxt_d().length; lockDesc.l_pid = 0; result = fcntl(this->file()->handle(), lockmode, &lockDesc); } while (result && errno == EINTR); /*we dot get the lock unregister from lockregistry and return*/ if (result == -1) { QxtFileLockRegistry::instance().removeLock(this); return false; } qxt_d().isLocked = true; return true; } return false; } libqxt-0.6.2/src/core/qxtfilelock_win.cpp000066400000000000000000000054761215241066400204640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtfilelock.h" #include "qxtfilelock_p.h" #include #include bool QxtFileLock::unlock() { if (file() && file()->isOpen() && isActive()) { HANDLE w32FileHandle; OVERLAPPED ov1; w32FileHandle = (HANDLE)_get_osfhandle(file()->handle()); if (w32FileHandle == INVALID_HANDLE_VALUE) return false; memset(&ov1, 0, sizeof(ov1)); ov1.Offset = qxt_d().offset; if (UnlockFileEx(w32FileHandle, 0, qxt_d().length, 0, &ov1)) { qxt_d().isLocked = false; return true; } } return false; } bool QxtFileLock::lock() { if (file() && file()->isOpen() && !isActive()) { HANDLE w32FileHandle; OVERLAPPED ov1; DWORD dwflags; w32FileHandle = (HANDLE)_get_osfhandle(file()->handle()); if (w32FileHandle == INVALID_HANDLE_VALUE) return false; switch (qxt_d().mode) { case ReadLock: dwflags = LOCKFILE_FAIL_IMMEDIATELY; break; case ReadLockWait: dwflags = 0; break; case WriteLock: dwflags = LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY; break; case WriteLockWait: dwflags = LOCKFILE_EXCLUSIVE_LOCK; break; default: return (false); } memset(&ov1, 0, sizeof(ov1)); ov1.Offset = qxt_d().offset; if (LockFileEx(w32FileHandle, dwflags, 0, qxt_d().length, 0, &ov1)) { qxt_d().isLocked = true; return true; } } return false; } libqxt-0.6.2/src/core/qxtglobal.cpp000066400000000000000000000172651215241066400172560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtglobal.h" /*! \headerfile \title Global Qxt Declarations \inmodule QxtCore \brief The header provides basic declarations and is included by all other Qxt headers. */ /*! \macro QXT_VERSION \relates This macro expands a numeric value of the form 0xMMNNPP (MM = major, NN = minor, PP = patch) that specifies Qxt's version number. For example, if you compile your application against Qxt 0.4.0, the QXT_VERSION macro will expand to 0x000400. You can use QXT_VERSION to use the latest Qt features where available. For example: \code #if QXT_VERSION >= 0x000400 qxtTabWidget->setTabMovementMode(QxtTabWidget::InPlaceMovement); #endif \endcode \sa QXT_VERSION_STR, qxtVersion() */ /*! \macro QXT_VERSION_STR \relates This macro expands to a string that specifies Qxt's version number (for example, "0.4.0"). This is the version against which the application is compiled. \sa qxtVersion(), QXT_VERSION */ /*! \relates Returns the version number of Qxt at run-time as a string (for example, "0.4.0"). This may be a different version than the version the application was compiled against. \sa QXT_VERSION_STR */ const char* qxtVersion() { return QXT_VERSION_STR; } /*! \headerfile \title The Qxt private implementation \inmodule QxtCore \brief The header provides tools for hiding details of a class. Application code generally doesn't have to be concerned about hiding its implementation details, but when writing library code it is important to maintain a constant interface, both source and binary. Maintaining a constant source interface is easy enough, but keeping the binary interface constant means moving implementation details into a private class. The PIMPL, or d-pointer, idiom is a common method of implementing this separation. QxtPimpl offers a convenient way to connect the public and private sides of your class. \section1 Getting Started Before you declare the public class, you need to make a forward declaration of the private class. The private class must have the same name as the public class, followed by the word Private. For example, a class named MyTest would declare the private class with: \code class MyTestPrivate; \endcode \section1 The Public Class Generally, you shouldn't keep any data members in the public class without a good reason. Functions that are part of the public interface should be declared in the public class, and functions that need to be available to subclasses (for calling or overriding) should be in the protected section of the public class. To connect the private class to the public class, include the QXT_DECLARE_PRIVATE macro in the private section of the public class. In the example above, the private class is connected as follows: \code private: QXT_DECLARE_PRIVATE(MyTest) \endcode Additionally, you must include the QXT_INIT_PRIVATE macro in the public class's constructor. Continuing with the MyTest example, your constructor might look like this: \code MyTest::MyTest() { // initialization QXT_INIT_PRIVATE(MyTest); } \endcode \section1 The Private Class As mentioned above, data members should usually be kept in the private class. This allows the memory layout of the private class to change without breaking binary compatibility for the public class. Functions that exist only as implementation details, or functions that need access to private data members, should be implemented here. To define the private class, inherit from the template QxtPrivate class, and include the QXT_DECLARE_PUBLIC macro in its public section. The template parameter should be the name of the public class. For example: \code class MyTestPrivate : public QxtPrivate { public: MyTestPrivate(); QXT_DECLARE_PUBLIC(MyTest) }; \endcode \section1 Accessing Private Members Use the qxt_d() function (actually a function-like object) from functions in the public class to access the private class. Similarly, functions in the private class can invoke functions in the public class by using the qxt_p() function (this one's actually a function). For example, assume that MyTest has methods named getFoobar and doBaz(), and MyTestPrivate has a member named foobar and a method named doQuux(). The code might resemble this example: \code int MyTest::getFoobar() { return qxt_d().foobar; } void MyTestPrivate::doQuux() { qxt_p().doBaz(foobar); } \endcode */ /*! * \macro QXT_DECLARE_PRIVATE(PUB) * \relates * Declares that a public class has a related private class. * * This shuold be put in the private section of the public class. The parameter is the name of the public class. */ /*! * \macro QXT_DECLARE_PUBLIC(PUB) * \relates * Declares that a private class has a related public class. * * This may be put anywhere in the declaration of the private class. The parameter is the name of the public class. */ /*! * \macro QXT_INIT_PRIVATE(PUB) * \relates * Initializes resources owned by the private class. * * This should be called from the public class's constructor, * before qxt_d() is used for the first time. The parameter is the name of the public class. */ /*! * \macro QXT_D(PUB) * \relates * Returns a reference in the current scope named "d" to the private class. * * This function is only available in a class using \a QXT_DECLARE_PRIVATE. */ /*! * \macro QXT_P(PUB) * \relates * Creates a reference in the current scope named "q" to the public class. * * This macro only works in a class using \a QXT_DECLARE_PUBLIC. */ /*! * \fn QxtPrivate& PUB::qxt_d() * \relates * Returns a reference to the private class. * * This function is only available in a class using \a QXT_DECLARE_PRIVATE. */ /*! * \fn const QxtPrivate& PUB::qxt_d() const * \relates * Returns a const reference to the private class. * * This function is only available in a class using \a QXT_DECLARE_PRIVATE. * This overload will be automatically used in const functions. */ /*! * \fn PUB& QxtPrivate::qxt_p() * \relates * Returns a reference to the public class. * * This function is only available in a class using \a QXT_DECLARE_PUBLIC. */ /*! * \fn const PUB& QxtPrivate::qxt_p() const * \relates * Returns a const reference to the public class. * * This function is only available in a class using \a QXT_DECLARE_PUBLIC. * This overload will be automatically used in const functions. */ libqxt-0.6.2/src/core/qxtglobal.h000066400000000000000000000132571215241066400167200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTGLOBAL_H #define QXTGLOBAL_H #include #define QXT_VERSION 0x000602 #define QXT_VERSION_STR "0.6.2" //--------------------------global macros------------------------------ #ifndef QXT_NO_MACROS #endif // QXT_NO_MACROS //--------------------------export macros------------------------------ #define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE #if !defined(QXT_STATIC) # if defined(BUILD_QXT_CORE) # define QXT_CORE_EXPORT Q_DECL_EXPORT # else # define QXT_CORE_EXPORT Q_DECL_IMPORT # endif #else # define QXT_CORE_EXPORT #endif // BUILD_QXT_CORE #if !defined(QXT_STATIC) # if defined(BUILD_QXT_GUI) # define QXT_GUI_EXPORT Q_DECL_EXPORT # else # define QXT_GUI_EXPORT Q_DECL_IMPORT # endif #else # define QXT_GUI_EXPORT #endif // BUILD_QXT_GUI #if !defined(QXT_STATIC) # if defined(BUILD_QXT_NETWORK) # define QXT_NETWORK_EXPORT Q_DECL_EXPORT # else # define QXT_NETWORK_EXPORT Q_DECL_IMPORT # endif #else # define QXT_NETWORK_EXPORT #endif // BUILD_QXT_NETWORK #if !defined(QXT_STATIC) # if defined(BUILD_QXT_SQL) # define QXT_SQL_EXPORT Q_DECL_EXPORT # else # define QXT_SQL_EXPORT Q_DECL_IMPORT # endif #else # define QXT_SQL_EXPORT #endif // BUILD_QXT_SQL #if !defined(QXT_STATIC) # if defined(BUILD_QXT_WEB) # define QXT_WEB_EXPORT Q_DECL_EXPORT # else # define QXT_WEB_EXPORT Q_DECL_IMPORT # endif #else # define QXT_WEB_EXPORT #endif // BUILD_QXT_WEB #if !defined(QXT_STATIC) # if defined(BUILD_QXT_BERKELEY) # define QXT_BERKELEY_EXPORT Q_DECL_EXPORT # else # define QXT_BERKELEY_EXPORT Q_DECL_IMPORT # endif #else # define QXT_BERKELEY_EXPORT #endif // BUILD_QXT_BERKELEY #if !defined(QXT_STATIC) # if defined(BUILD_QXT_ZEROCONF) # define QXT_ZEROCONF_EXPORT Q_DECL_EXPORT # else # define QXT_ZEROCONF_EXPORT Q_DECL_IMPORT # endif #else # define QXT_ZEROCONF_EXPORT #endif // QXT_ZEROCONF_EXPORT #if defined BUILD_QXT_CORE || defined BUILD_QXT_GUI || defined BUILD_QXT_SQL || defined BUILD_QXT_NETWORK || defined BUILD_QXT_WEB || defined BUILD_QXT_BERKELEY || defined BUILD_QXT_ZEROCONF # define BUILD_QXT #endif QXT_CORE_EXPORT const char* qxtVersion(); #ifndef QT_BEGIN_NAMESPACE #define QT_BEGIN_NAMESPACE #endif #ifndef QT_END_NAMESPACE #define QT_END_NAMESPACE #endif #ifndef QT_FORWARD_DECLARE_CLASS #define QT_FORWARD_DECLARE_CLASS(Class) class Class; #endif /**************************************************************************** ** This file is derived from code bearing the following notice: ** The sole author of this file, Adam Higerd, has explicitly disclaimed all ** copyright interest and protection for the content within. This file has ** been placed in the public domain according to United States copyright ** statute and case law. In jurisdictions where this public domain dedication ** is not legally recognized, anyone who receives a copy of this file is ** permitted to use, modify, duplicate, and redistribute this file, in whole ** or in part, with no restrictions or conditions. In these jurisdictions, ** this file shall be copyright (C) 2006-2008 by Adam Higerd. ****************************************************************************/ #define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface qxt_d; #define QXT_DECLARE_PUBLIC(PUB) friend class PUB; #define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this); #define QXT_D(PUB) PUB##Private& d = qxt_d() #define QXT_P(PUB) PUB& p = qxt_p() template class QxtPrivate { public: virtual ~QxtPrivate() {} inline void QXT_setPublic(PUB* pub) { qxt_p_ptr = pub; } protected: inline PUB& qxt_p() { return *qxt_p_ptr; } inline const PUB& qxt_p() const { return *qxt_p_ptr; } private: PUB* qxt_p_ptr; }; template class QxtPrivateInterface { friend class QxtPrivate; public: QxtPrivateInterface() { pvt = new PVT; } ~QxtPrivateInterface() { delete pvt; } inline void setPublic(PUB* pub) { pvt->QXT_setPublic(pub); } inline PVT& operator()() { return *static_cast(pvt); } inline const PVT& operator()() const { return *static_cast(pvt); } private: QxtPrivateInterface(const QxtPrivateInterface&) { } QxtPrivateInterface& operator=(const QxtPrivateInterface&) { } QxtPrivate* pvt; }; #endif // QXT_GLOBAL libqxt-0.6.2/src/core/qxthmac.cpp000066400000000000000000000147531215241066400167250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxthmac.h" #include #if QT_VERSION >= 0x040300 /* \class QxtHmac \inmodule QxtCore \brief The QxtHmac class calculates keyed-Hash Message Authentication Codes HMAC is a well-known algorithm for generating a message authentication code (MAC) that can be used to verify the integrity and authenticity of a message. This class requires Qt 4.3.0 or greater. To verify a message, the sender creates a MAC using a key, which is a secret known only to the sender and recipient, and the content of the message. This MAC is then sent along with the message. The recipient then creates another MAC using the shared key and the content of the message. If the two codes match, the message is verified. HMAC has been used as a password encryption scheme. The final output of the HMAC algorithm depends on the shared key and an inner hash. This inner hash is generated from the message content and the key. To use HMAC as a password scheme, the key should be the username; the message should be the user's password. The authenticating party (for instance, a login server) only needs to store this inner hash generated by the innerHash() function. When requesting authentication, the user calculates a HMAC using this key and message and sends his username and this HMAC to the authenticator. The authenticator can then use verify() using the provided HMAC and the stored inner hash. When using this scheme, the password is never stored or transmitted in plain text. */ #ifndef QXT_DOXYGEN_RUN class QxtHmacPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtHmac) QxtHmacPrivate() : ohash(0), ihash(0) {} ~QxtHmacPrivate() { // deleting NULL is safe, so no tests are needed here delete ohash; delete ihash; } QCryptographicHash* ohash; QCryptographicHash* ihash; QByteArray opad, ipad, result; QCryptographicHash::Algorithm algorithm; }; #endif /*! * Constructs a QxtHmac object using the specified algorithm. */ QxtHmac::QxtHmac(QCryptographicHash::Algorithm algorithm) { QXT_INIT_PRIVATE(QxtHmac); qxt_d().ohash = new QCryptographicHash(algorithm); qxt_d().ihash = new QCryptographicHash(algorithm); qxt_d().algorithm = algorithm; } /*! * Sets the shared secret key for the message authentication code. * * Any data that had been processed using addData() will be discarded. */ void QxtHmac::setKey(QByteArray key) { // We make the assumption that all hashes use a 512-bit block size; as of Qt 4.4.0 this is true of all supported hash functions QxtHmacPrivate* d = &qxt_d(); d->opad = QByteArray(64, 0x5c); d->ipad = QByteArray(64, 0x36); if (key.size() > 64) { key = QCryptographicHash::hash(key, d->algorithm); } for (int i = key.size() - 1; i >= 0; --i) { d->opad[i] = d->opad[i] ^ key[i]; d->ipad[i] = d->ipad[i] ^ key[i]; } reset(); } /*! * Resets the object. * * Any data that had been processed using addData() will be discarded. * The key, if set, will be preserved. */ void QxtHmac::reset() { QxtHmacPrivate* d = &qxt_d(); d->ihash->reset(); d->ihash->addData(d->ipad); } /*! * Returns the inner hash of the HMAC function. * * This hash can be stored in lieu of the shared secret on the authenticating side * and used for verifying an HMAC code. When used in this manner, HMAC can be used * to provide a form of secure password authentication. See the documentation above * for details. */ QByteArray QxtHmac::innerHash() const { return qxt_d().ihash->result(); } /*! * Returns the authentication code for the message. */ QByteArray QxtHmac::result() { QxtHmacPrivate* d = &qxt_d(); Q_ASSERT(d->opad.size()); if (d->result.size()) return d->result; d->ohash->reset(); d->ohash->addData(d->opad); d->ohash->addData(innerHash()); d->result = d->ohash->result(); return d->result; } /*! * Verifies the authentication code against a known inner hash. * * \sa innerHash() */ bool QxtHmac::verify(const QByteArray& otherInner) { result(); // populates d->result QxtHmacPrivate* d = &qxt_d(); d->ohash->reset(); d->ohash->addData(d->opad); d->ohash->addData(otherInner); return d->result == d->ohash->result(); } /*! * Adds the provided data to the message to be authenticated. */ void QxtHmac::addData(const char* data, int length) { Q_ASSERT(qxt_d().opad.size()); qxt_d().ihash->addData(data, length); qxt_d().result.clear(); } /*! * Adds the provided data to the message to be authenticated. */ void QxtHmac::addData(const QByteArray& data) { addData(data.constData(), data.size()); } /*! * Returns the HMAC of the provided data using the specified key and hashing algorithm. */ QByteArray QxtHmac::hash(const QByteArray& key, const QByteArray& data, Algorithm algorithm) { QxtHmac hmac(algorithm); hmac.setKey(key); hmac.addData(data); return hmac.result(); } /*! * Verifies a HMAC against a known key and inner hash using the specified hashing algorithm. */ bool QxtHmac::verify(const QByteArray& key, const QByteArray& hmac, const QByteArray& inner, Algorithm algorithm) { QxtHmac calc(algorithm); calc.setKey(key); QxtHmacPrivate* d = &calc.qxt_d(); d->ohash->reset(); d->ohash->addData(d->opad); d->ohash->addData(inner); return hmac == d->ohash->result(); } #endif libqxt-0.6.2/src/core/qxthmac.h000066400000000000000000000040441215241066400163620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTHMAC_H #define QXTHMAC_H #include #if QT_VERSION < 0x040300 # warning QxtHmac requires Qt 4.3.0 or greater #else #include #include "qxtglobal.h" class QxtHmacPrivate; class QXT_CORE_EXPORT QxtHmac { public: typedef QCryptographicHash::Algorithm Algorithm; QxtHmac(QCryptographicHash::Algorithm algorithm); void setKey(QByteArray key); void reset(); void addData(const char* data, int length); void addData(const QByteArray& data); QByteArray innerHash() const; QByteArray result(); bool verify(const QByteArray& otherInner); static QByteArray hash(const QByteArray& key, const QByteArray& data, Algorithm algorithm); static bool verify(const QByteArray& key, const QByteArray& hmac, const QByteArray& inner, Algorithm algorithm); private: QXT_DECLARE_PRIVATE(QxtHmac) }; #endif #endif libqxt-0.6.2/src/core/qxtjob.cpp000066400000000000000000000064631215241066400165660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /* \class QxtJob \inmodule QxtCore \brief The QxtJob class executes a job on a QThread. Once or multiple times. QxtJob allows easily starting jobs on different threads. exec() will ask for the QThread to run the job on. The Qthread needs an event loop. since version 4.4, QThread has a non pure run function with a default event loop, allowing easy deployment of jobs. \code QThread thread; thread.start(); LockJob().exec(&thread); \endcode */ /* \fn void QxtJob::run() This function is called by QxtJob. reimplemented this function to do useful work. Returning from this method will end the execution of the job. */ /* \fn void QxtJob::done() This signal is emitted, when the run() function returns. */ #include "qxtjob_p.h" #include #include class Thread : public QThread { public: static void usleep(unsigned long usecs) { QThread::usleep(usecs); } }; /*! default constructor */ QxtJob::QxtJob() { QXT_INIT_PRIVATE(QxtJob); qxt_d().running.set(false); connect(&qxt_d(), SIGNAL(done()), this, SIGNAL(done())); } /*! execute the Job on \a onthread */ void QxtJob::exec(QThread * onthread) { qxt_d().moveToThread(onthread); connect(this, SIGNAL(subseed()), &qxt_d(), SLOT(inwrap_d()), Qt::QueuedConnection); qxt_d().running.set(true); emit(subseed()); } /*! \warning The destructor joins. Means it blocks until the job is finished */ QxtJob::~QxtJob() { join(); } /*! block until the Job finished Note that the current thread will be blocked. If you use this, you better be damn sure you actually want a thread. Maybe you actualy want to use QxtSignalWaiter. */ void QxtJob::join() { while (qxt_d().running.get() == true) { /*! oh yeah that sucks ass, but since any kind of waitcondition will just fail due to undeterminnism, we have no chance then polling. And no, a mutex won't work either. using join for anything else then testcases sounds kindof retarded anyway. */ Thread::usleep(1000); } } void QxtJobPrivate::inwrap_d() { synca.wakeAll(); qxt_p().run(); running.set(false); emit(done()); } libqxt-0.6.2/src/core/qxtjob.h000066400000000000000000000031731215241066400162260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTJOB_H #define QXTJOB_H #include #include class QxtJobPrivate; QT_FORWARD_DECLARE_CLASS(QThread) class QXT_CORE_EXPORT QxtJob : public QObject { Q_OBJECT public: QxtJob(); ~QxtJob(); void exec(QThread * onthread); void join(); protected: virtual void run() = 0; Q_SIGNALS: void done(); private: QXT_DECLARE_PRIVATE(QxtJob) Q_SIGNALS: ///\internal void subseed(); }; #endif // QXTJOB_H libqxt-0.6.2/src/core/qxtjob_p.h000066400000000000000000000035651215241066400165520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTJOB_P_H #define QXTJOB_P_H #include #include #include class QxtJobPrivate : public QObject, public QxtPrivate { Q_OBJECT public: class RunningState { public: void set(bool a) { mutex.lock(); r = a; mutex.unlock(); } bool get() { mutex.lock(); bool a = r; mutex.unlock(); return a; } QMutex mutex; bool r; } running; QXT_DECLARE_PUBLIC(QxtJob) QMutex mutexa; QWaitCondition synca; public Q_SLOTS: void inwrap_d(); Q_SIGNALS: void done(); }; #endif // QXTJOB_P_H libqxt-0.6.2/src/core/qxtjson.cpp000066400000000000000000000227271215241066400167660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtJSON \inmodule QxtCore \brief The QxtJSON class implements serializing/deserializing from/to JSON implements JSON (JavaScript Object Notation) is a lightweight data-interchange format. see http://www.json.org/ \section2 Type Conversion \table 80% \header \o JSON Type \o Qt Type \row \o object \o QVariantMap/QVariantHash \row \o array \o QVariantList/QStringList \row \o string \o QString \row \o number \o int,double \row \o true \o bool \row \o false \o bool \row \o null \o QVariant() \endtable */ #include "qxtjson.h" #include #include #include #include QString QxtJSON::stringify(QVariant v){ if (v.isNull()){ return "null"; } int t = v.type(); if (t == QVariant::String){ QString in = v.toString(); QString out; for(QString::ConstIterator i = in.constBegin(); i != in.constEnd(); i++){ if( (*i) == QChar('\b')) out.append("\\b"); else if( (*i) == QChar('\f')) out.append("\\f"); else if( (*i) == QChar('\n')) out.append("\\n"); else if( (*i) == QChar('\r')) out.append("\\r"); else if( (*i) == QChar('\t')) out.append("\\t"); else if( (*i) == QChar('\f')) out.append("\\f"); else if( (*i) == QChar('\\')) out.append("\\\\"); else if( (*i) == QChar('/')) out.append("\\/"); else out.append(*i); } return "\""+out+"\""; } else if (t == QVariant::Bool){ return v.toBool()?"true":"false"; }else if (t == QVariant::Int){ return QString::number(v.toInt()); }else if (t == QVariant::Double){ return QString::number(v.toDouble()); }else if (t == QVariant::Map){ QString r="{"; QMap map = v.toMap(); QMapIterator i(map); while (i.hasNext()){ i.next(); r+="\""+i.key()+"\":"+stringify(i.value())+","; } if(r.length()>1) r.chop(1); r+="}"; return r; #if QT_VERSION >= 0x040500 }else if (t == QVariant::Hash){ QString r="{"; QHash map = v.toHash(); QHashIterator i(map); while (i.hasNext()){ i.next(); r+="\""+i.key()+"\":"+stringify(i.value())+","; } if(r.length()>1) r.chop(1); r+="}"; return r; #endif }else if (t == QVariant::StringList){ QString r="["; QStringList l = v.toStringList(); foreach(QString i, l){ r+="\""+i+"\","; } if(r.length()>1) r.chop(1); r+="]"; return r; }else if (t == QVariant::List){ QString r="["; QVariantList l = v.toList(); foreach(QVariant i, l){ r+=stringify(i)+","; } if(r.length()>1) r.chop(1); r+="]"; return r; } return QString(); } static QVariant parseValue(QTextStream &s,bool & error); static QVariantMap parseObject (QTextStream & s,bool & error); static QVariantList parseArray (QTextStream & s,bool & error); static QString parseString (QTextStream & s,bool & error); static QVariant parseLiteral (QTextStream & s,bool & error); QVariant QxtJSON::parse(QString string){ QTextStream s(&string); bool error=false; QVariant v=parseValue(s,error); if(error) return QVariant(); return v; } static QVariant parseValue(QTextStream &s,bool & error){ s.skipWhiteSpace(); QChar c; while(!s.atEnd() && !error){ s>>c; if (c=='{'){ return parseObject(s,error); } else if (c=='"'){ return parseString(s,error); } else if (c=='['){ return parseArray(s,error); } else { return parseLiteral(s,error); } s.skipWhiteSpace(); } return QVariant(); } static QVariantMap parseObject (QTextStream & s,bool & error){ s.skipWhiteSpace(); QVariantMap o; QString key; bool atVal=false; QChar c; while(!s.atEnd() && !error){ s>>c; if (c=='}'){ return o; } else if (c==',' || c==':'){ /* They're syntactic sugar, since key:value come in bundles anyway Could check for error handling. too lazy. */ } else if (c=='"'){ if(atVal){ o[key]=parseString(s,error); atVal=false; }else{ key=parseString(s,error); atVal=true; } } else if (c=='['){ if(atVal){ o[key]=parseArray(s,error); atVal=false; }else{ error=true; return QVariantMap(); } } else if (c=='{'){ if(atVal){ o[key]=parseObject(s,error); atVal=false; }else{ error=true; return QVariantMap(); } } else { if(atVal){ o[key]=parseLiteral(s,error); atVal=false; }else{ error=true; return QVariantMap(); } } s.skipWhiteSpace(); } error=true; return QVariantMap(); } static QVariantList parseArray (QTextStream & s,bool & error){ s.skipWhiteSpace(); QVariantList l; QChar c; while(!s.atEnd() && !error){ s>>c; if (c==']'){ return l; } else if (c==','){ } else if (c=='"'){ l.append(QVariant(parseString(s,error))); } else if (c=='['){ l.append(QVariant(parseArray(s,error))); } else if (c=='{'){ l.append(QVariant(parseObject(s,error))); } else { l.append(QVariant(parseLiteral(s,error))); } s.skipWhiteSpace(); } error=true; return QVariantList(); } static QString parseString (QTextStream & s,bool & error){ QString str; QChar c; while(!s.atEnd() && !error){ s>>c; if(c=='"'){ return str; }else if(c=='\\'){ s>>c; if(c=='b'){ str.append('\b'); }else if(c=='f'){ str.append('\f'); }else if(c=='n'){ str.append('\n'); }else if(c=='r'){ str.append('\r'); }else if(c=='t'){ str.append('\t'); }else if(c=='f'){ str.append('\f'); }else if(c=='u'){ QString k; for (int i = 0; i < 4; i++ ) { s >> c; k.append(c); } bool ok; int i = k.toInt(&ok, 16); if (ok) str.append(QChar(i)); }else{ str.append(c); } }else{ str.append(c); } } error=true; return QString(); } static QVariant parseLiteral (QTextStream & s,bool & error){ s.seek(s.pos()-1); QChar c; while(!s.atEnd() && !error){ s>>c; if (c=='t'){ s>>c;//r s>>c;//u s>>c;//e return true; } else if (c=='f'){ s>>c;//a s>>c;//l s>>c;//s s>>c;//e return false; }else if (c=='n'){ s>>c;//u s>>c;//l s>>c;//l return QVariant(); }else if (c=='-' || c.isDigit()){ QString n; while(( c.isDigit() || (c=='.') || (c=='E') || (c=='e') || (c=='-') || (c=='+') )){ n.append(c); if(s.atEnd() || error) break; s>>c; } s.seek(s.pos()-1); if(n.contains('.')) { return n.toDouble(); } else { bool ok = false; int result = n.toInt(&ok); if(ok) return result; return n.toLongLong(); } } } error=true; return QVariant(); } libqxt-0.6.2/src/core/qxtjson.h000066400000000000000000000026341215241066400164260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTJSON_H #define QXTJSON_H #include "qxtglobal.h" #include #include class QXT_CORE_EXPORT QxtJSON { public: static QVariant parse (QString string); static QString stringify (QVariant v); }; #endif libqxt-0.6.2/src/core/qxtlinesocket.cpp000066400000000000000000000061541215241066400201510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlinesocket_p.h" #include /*! \class QxtLineSocket \inmodule QxtCore \brief The QxtLineSocket class acts on a QIODevice as baseclass for line-based protocols */ /*! \fn QxtLineSocket::newLineReceived(const QByteArray& line) This signal is emitted whenever a new \a line is received. */ /*! Constructs a new QxtLineSocket with \a parent. */ QxtLineSocket::QxtLineSocket(QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtLineSocket); } /*! Constructs a new QxtLineSocket with \a socket and \a parent. */ QxtLineSocket::QxtLineSocket(QIODevice* socket, QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtLineSocket); setSocket(socket); } /*! Sets the \a socket. */ void QxtLineSocket::setSocket(QIODevice* socket) { if (qxt_d().socket) disconnect(qxt_d().socket, SIGNAL(readyRead()), &qxt_d(), SLOT(readyRead())); qxt_d().socket = socket; if (qxt_d().socket) connect(qxt_d().socket, SIGNAL(readyRead()), &qxt_d(), SLOT(readyRead())); } /*! Returns the socket. */ QIODevice* QxtLineSocket::socket() const { return qxt_d().socket; } /*! Sends a \a line. */ void QxtLineSocket::sendLine(const QByteArray& line) { QByteArray copy(line); copy.replace(QByteArray("\n"), ""); //krazy:exclude=doublequote_chars qxt_d().socket->write(copy + '\n'); } /*! This virtual function is called by QxtLineSocket whenever a \a line was received. Reimplement this function when creating a subclass of QxtLineSocket. \note The default implementation does nothing. */ void QxtLineSocket::newLine(const QByteArray& line) { Q_UNUSED(line); } void QxtLineSocketPrivate::readyRead() { buffer += socket->readAll(); int i = 0; while ((i = buffer.indexOf('\n')) > -1) { QByteArray line = buffer.left(i); emit qxt_p().newLineReceived(line); qxt_p().newLine(line); buffer = buffer.mid(i + 1); } } libqxt-0.6.2/src/core/qxtlinesocket.h000066400000000000000000000035261215241066400176160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLINESOCKET_H #define QXTLINESOCKET_H #include #include QT_FORWARD_DECLARE_CLASS(QIODevice) class QxtLineSocketPrivate; class QXT_CORE_EXPORT QxtLineSocket : public QObject { Q_OBJECT public: explicit QxtLineSocket(QObject* parent = 0); explicit QxtLineSocket(QIODevice* socket, QObject* parent = 0); void setSocket(QIODevice* socket); QIODevice* socket() const; public Q_SLOTS: void sendLine(const QByteArray& line); Q_SIGNALS: void newLineReceived(const QByteArray& line); protected: virtual void newLine(const QByteArray& line); private: QXT_DECLARE_PRIVATE(QxtLineSocket) }; #endif // QXTLINESOCKET_H libqxt-0.6.2/src/core/qxtlinesocket_p.h000066400000000000000000000030621215241066400201300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLINESOCKET_P_H #define QXTLINESOCKET_P_H #include "qxtlinesocket.h" class QxtLineSocketPrivate : public QObject, public QxtPrivate { Q_OBJECT QXT_DECLARE_PUBLIC(QxtLineSocket) public: QxtLineSocketPrivate() : socket(0) { } QIODevice* socket; QByteArray buffer; private Q_SLOTS: void readyRead(); }; #endif // QXTLINESOCKET_P_H libqxt-0.6.2/src/core/qxtlinkedtree.cpp000066400000000000000000000142611215241066400201350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlinkedtree.h" /*! \class QxtLinkedTree \inmodule QxtCore \brief The QxtLinkedTree class is a fast container for tree structured data this template class can be used to store data easily in a tree structure. Internally it uses the doublelinked list scheme, but adds client/parent links. There are no random access functions, you have to use QxtLinkedTree::iterator to access the data. This is very fast and efficient. \code QxtLinkedTree tree(1); QxtLinkedTreeIterator it= tree.root(); it.append(34); qDebug()< it= tree.fromVoid(root); \endcode TODO: {implicitshared} */ /*! \fn QxtLinkedTree::QxtLinkedTree(); constructs a QxtLinkedTree with a default constructed root node. */ /*! \fn QxtLinkedTree::QxtLinkedTree(T t); constructs a QxtLinkedTree. sets the rootnode to \a t */ /*! \fn QxtLinkedTree::~QxtLinkedTree() the destructor deletes all items, when they are no longer referenced by any other instance. */ /*! \fn void QxtLinkedTree::clear(); deletes all nodes recursively. this might take forever depending on the size of your tree. */ /*! \fn QxtLinkedTreeIterator QxtLinkedTree::root(); returns an iterator on the root node */ /*! \fn void * QxtLinkedTree::toVoid (QxtLinkedTreeIterator); get an unique void pointer to be able to stuff an iterator into other structures. You must not do anything else but pass this to fromVoid(). the pointer is invalid when the actual data has been removed and passing it to fromVoid will crash. You have been warned. */ /*! \fn QxtLinkedTreeIterator QxtLinkedTree::fromVoid (void *); returns an iterator pre positioned on the item specified with toVoid. passing anything that has not being created by toVoid() will crash. also note that passing invalidated nodes will crash too. Be extremly carefull. It is easy to currupt your data with this! */ /*! \class QxtLinkedTreeIterator \inmodule QxtCore \brief The QxtLinkedTreeIterator class provides fast access to an QxtLinkedTree */ /*! \fn QxtLinkedTreeIterator QxtLinkedTreeIterator::child () const; returns an iterator to the first child item of this or an invalid iterator when there are no children */ /*! \fn QxtLinkedTreeIterator QxtLinkedTreeIterator::parent () const; returns an iterator to the parent item of this. or an invalid iterator when this is the root node */ /*! \fn QxtLinkedTreeIterator QxtLinkedTreeIterator::previous () const; returns an iterator to the previous item of this or an invalid iterator when this is the first one in the next/previous chain */ /*! \fn QxtLinkedTreeIterator QxtLinkedTreeIterator::next () const; returns an iterator to the next item of this in the previous/next chain or an invalid iterator when this is the last one */ /*! \fn bool QxtLinkedTreeIterator::isValid () const; verfies if this iterator points to a valid location inside the tree an invalid node is decoupled from the iteration. it can not be used for anything anymore. \code QxtLinkedTree tree(1); QxtLinkedTreeIterator it= tree.begin(); it++; //invalid. there are no siblings. it--; //still invalid! \endcode */ /*! \fn int QxtLinkedTreeIterator::children() const returns the amount of childnodes. */ /*! \fn T & QxtLinkedTreeIterator::operator* () const; Returns a modifiable reference to the current item. You can change the value of an item by using operator*() on the left side of an assignment, for example: \code if (*it == "Hello") *it = "Bonjour"; \endcode */ /*! \fn T QxtLinkedTreeIterator::operator T () const; returns a copy of the current item. */ /*! \fn QxtLinkedTreeIterator QxtLinkedTreeIterator:: operator + ( int j ) const; */ /*! \fn QxtLinkedTreeIterator & QxtLinkedTreeIterator::operator ++ (); */ /*! \fn QxtLinkedTreeIterator & QxtLinkedTreeIterator::operator ++ (int); */ /*! \fn QxtLinkedTreeIterator & QxtLinkedTreeIterator::operator += ( int j ); */ /*! \fn QxtLinkedTreeIterator QxtLinkedTreeIterator::operator - ( int j ) const; */ /*! \fn QxtLinkedTreeIterator & QxtLinkedTreeIterator::operator -- (); */ /*! \fn QxtLinkedTreeIterator & QxtLinkedTreeIterator::operator -- (int); */ /*! \fn QxtLinkedTreeIterator & QxtLinkedTreeIterator::operator -= ( int j ); */ /*! \fn bool QxtLinkedTreeIterator::operator== ( const iterator & other ) const; compares */ /*! \fn bool QxtLinkedTreeIterator::operator!= ( const iterator & other ) const; compares */ /*! \fn QxtLinkedTreeIterator QxtLinkedTreeIterator::erase () const; deletes the current item. returns an iterator to the next sibling. this instance is then invalid. deleting is recursive. all subitems will be deleted too. */ /*! \fn QxtLinkedTreeIterator QxtLinkedTreeIterator::append (const T & value ) const; appens an item to the children of this item. returns an iterator to the new item. */ libqxt-0.6.2/src/core/qxtlinkedtree.h000066400000000000000000000266531215241066400176120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLINKEDTREE_H #define QXTLINKEDTREE_H #include #include template class QxtLinkedTree; template class QxtLinkedTreeIterator; template class QXT_CORE_EXPORT QxtLinkedTreeItem { public: ~QxtLinkedTreeItem() { clear(); } private: QxtLinkedTreeItem(T tt) { t = tt; next = 0; previous = 0; parent = 0; child = 0; childcount = 0; } void clear() { if (child) { QxtLinkedTreeItem * c = child; while (c) { QxtLinkedTreeItem * e = c; c = c->next; delete e; } child = 0; } } friend class QxtLinkedTree; friend class QxtLinkedTreeIterator; QxtLinkedTreeItem * next; QxtLinkedTreeItem * previous; QxtLinkedTreeItem * parent; QxtLinkedTreeItem * child; int childcount; T t; ///TODO: somehow notify all iterators when one deletes this. so they can be made invalid instead of undefined. }; ///FIXME: nested would be cooler but c++ has no typdefs with templates and doxygen doesn't undertsand nested templates template class QXT_CORE_EXPORT QxtLinkedTreeIterator { public: QxtLinkedTreeIterator(); QxtLinkedTreeIterator(const QxtLinkedTreeIterator & other); QxtLinkedTreeIterator & operator= (const QxtLinkedTreeIterator & other); QxtLinkedTreeIterator parent() const; QxtLinkedTreeIterator next() const; QxtLinkedTreeIterator previous() const; QxtLinkedTreeIterator child() const; bool isValid() const; int children() const; T & operator*() const; T * operator-> () const; operator T() const; QxtLinkedTreeIterator operator + (int j) const; QxtLinkedTreeIterator & operator ++ (); QxtLinkedTreeIterator operator ++ (int); QxtLinkedTreeIterator & operator += (int j); QxtLinkedTreeIterator operator - (int j) const; QxtLinkedTreeIterator & operator -- (); QxtLinkedTreeIterator operator -- (int); QxtLinkedTreeIterator & operator -= (int j); bool operator== (const QxtLinkedTreeIterator & other) const; bool operator!= (const QxtLinkedTreeIterator & other) const; QxtLinkedTreeIterator erase() ; QxtLinkedTreeIterator append(const T & value); QxtLinkedTreeIterator insert(int i, const T & value); private: friend class QxtLinkedTree; QxtLinkedTreeIterator(QxtLinkedTreeItem * t); QxtLinkedTreeItem *item; }; template class QXT_CORE_EXPORT QxtLinkedTree { public: QxtLinkedTree(); QxtLinkedTree(T t); ~QxtLinkedTree(); void clear(); QxtLinkedTreeIterator root(); static QxtLinkedTreeIterator fromVoid(void *) ; static void * toVoid(QxtLinkedTreeIterator) ; #if 0 QxtLinkedTreeIterator insert(iterator before, const T & value); #endif private: QxtSharedPrivate< QxtLinkedTreeItem > qxt_d; }; template QxtLinkedTreeIterator::QxtLinkedTreeIterator() { item = 0; } template QxtLinkedTreeIterator::QxtLinkedTreeIterator(const QxtLinkedTreeIterator & other) { item = other.item; } template QxtLinkedTreeIterator & QxtLinkedTreeIterator::operator= (const QxtLinkedTreeIterator & other) { item = other.item; return *this; } template QxtLinkedTreeIterator QxtLinkedTreeIterator::parent() const { Q_ASSERT_X(item, Q_FUNC_INFO, "iterator out of range"); return QxtLinkedTreeIterator(item->parent); } template QxtLinkedTreeIterator QxtLinkedTreeIterator::next() const { Q_ASSERT_X(item, Q_FUNC_INFO, "iterator out of range"); return QxtLinkedTreeIterator(item->next); } template QxtLinkedTreeIterator QxtLinkedTreeIterator::previous() const { Q_ASSERT_X(item, Q_FUNC_INFO, "iterator out of range"); return QxtLinkedTreeIterator(item->previous); } template QxtLinkedTreeIterator QxtLinkedTreeIterator::child() const { Q_ASSERT_X(item, Q_FUNC_INFO, "iterator out of range"); return QxtLinkedTreeIterator(item->child); } template bool QxtLinkedTreeIterator::isValid() const { return (item != 0); } template int QxtLinkedTreeIterator::children() const { Q_ASSERT_X(item, Q_FUNC_INFO, "iterator out of range"); return item->childcount; } template T & QxtLinkedTreeIterator::operator*() const { Q_ASSERT_X(item, Q_FUNC_INFO, "iterator out of range"); return item->t; } template T * QxtLinkedTreeIterator::operator-> () const { Q_ASSERT_X(item, Q_FUNC_INFO, "iterator out of range"); return &item->t; } template QxtLinkedTreeIterator::operator T() const { Q_ASSERT_X(item,Q_FUNC_INFO, "iterator out of range"); return item->t; } template QxtLinkedTreeIterator::QxtLinkedTreeIterator(QxtLinkedTreeItem * t) { item = t; } template QxtLinkedTreeIterator QxtLinkedTreeIterator::operator + (int j) const { QxtLinkedTreeItem * m = item; for (int i = 0;i < j;i++) { m = m->next; if (m == 0) return QxtLinkedTreeIterator(); } return QxtLinkedTreeIterator(m); } template QxtLinkedTreeIterator & QxtLinkedTreeIterator::operator ++ () /*prefix*/ { *this = QxtLinkedTreeIterator(item->next); return *this; } template QxtLinkedTreeIterator QxtLinkedTreeIterator::operator ++ (int) /*postfix*/ { QxtLinkedTreeIterator d(*this); *this = QxtLinkedTreeIterator(item->next); return d; } template QxtLinkedTreeIterator & QxtLinkedTreeIterator::operator += (int j) { *this = *this + j; return *this; } template QxtLinkedTreeIterator QxtLinkedTreeIterator::operator - (int j) const { QxtLinkedTreeItem * m = item; for (int i = 0;i < j;i++) { m = m->previous; if (m == 0) return QxtLinkedTreeIterator(); } return QxtLinkedTreeIterator(m); } template QxtLinkedTreeIterator & QxtLinkedTreeIterator::operator -- () /*prefix*/ { *this = QxtLinkedTreeIterator(item->previous); return *this; } template QxtLinkedTreeIterator QxtLinkedTreeIterator::operator -- (int) /*postfix*/ { QxtLinkedTreeIterator d(*this); *this = QxtLinkedTreeIterator(item->previous); return d; } template QxtLinkedTreeIterator & QxtLinkedTreeIterator::operator -= (int j) { *this = *this - j; return *this; } template bool QxtLinkedTreeIterator::operator== (const QxtLinkedTreeIterator & other) const { return (other.item == item); } template bool QxtLinkedTreeIterator::operator!= (const QxtLinkedTreeIterator & other) const { return (other.item != item); } template QxtLinkedTreeIterator QxtLinkedTreeIterator::erase() { QxtLinkedTreeItem *node = item; Q_ASSERT_X(item, Q_FUNC_INFO, "can't erase invalid node."); QxtLinkedTreeItem *parent = item->parent; Q_ASSERT_X(parent, Q_FUNC_INFO, "erasing root node not supported."); QxtLinkedTreeItem *next = node->next; ///delete children QxtLinkedTreeIterator ci = child(); while (ci.isValid()) { ci = ci.erase(); } ///realign chains if (parent->child == node) { parent->child = node->next; } else { QxtLinkedTreeItem * n = parent->child; while (n->next != node) { Q_ASSERT_X(n->next != 0, Q_FUNC_INFO, "reached end of chain and didn't find the node requested for removal."); n = n->next; } n->next = node->next; } parent->childcount--; delete node; item = 0; return QxtLinkedTreeIterator(next); } template QxtLinkedTreeIterator QxtLinkedTreeIterator::append(const T & value) { QxtLinkedTreeItem * parent = item; Q_ASSERT_X(parent, Q_FUNC_INFO, "invalid iterator"); QxtLinkedTreeItem *node = new QxtLinkedTreeItem(value); if (parent->child == 0) { parent->child = node; node->parent = parent; node->previous = 0; parent->childcount = 1; return QxtLinkedTreeIterator(node); } QxtLinkedTreeItem * n = parent->child; while (n->next != 0) n = n->next; n->next = node; node->parent = parent; node->previous = n; parent->childcount++; return QxtLinkedTreeIterator(node); } template QxtLinkedTreeIterator QxtLinkedTreeIterator::insert(int i, const T & value) { QxtLinkedTreeItem * parent = item; Q_ASSERT_X(parent, Q_FUNC_INFO, "invalid iterator"); Q_ASSERT_X(i <= children(), Q_FUNC_INFO, "cannot insert out of range"); if (parent->child == 0 || i == children()) { return append(value); } QxtLinkedTreeItem *node = new QxtLinkedTreeItem(value); QxtLinkedTreeItem * n = parent->child; while (i-- > 0) { n = n->next; Q_ASSERT_X(n, Q_FUNC_INFO, "out of range"); } if (n->previous) { n->previous->next = node; node->previous = n->previous; } else { Q_ASSERT_X(parent->child == n, Q_FUNC_INFO, "corupted linked tree"); parent->child = node; node->previous = 0; } node->next = n; n->previous = node; node->parent = parent; parent->childcount++; return QxtLinkedTreeIterator(node); } template QxtLinkedTree::QxtLinkedTree(T t) { qxt_d = new QxtLinkedTreeItem(t); } template QxtLinkedTree::QxtLinkedTree() { qxt_d = new QxtLinkedTreeItem(T()); } template QxtLinkedTree::~QxtLinkedTree() { } template void QxtLinkedTree::clear() { qxt_d().clear(); } template QxtLinkedTreeIterator QxtLinkedTree::fromVoid(void * d) { return QxtLinkedTreeIterator(reinterpret_cast *>(d)); } template void * QxtLinkedTree::toVoid(QxtLinkedTreeIterator n) { return reinterpret_cast(n.item); } template QxtLinkedTreeIterator QxtLinkedTree::root() { return QxtLinkedTreeIterator(&qxt_d()); } #endif // QXTLINKEDTREE_H libqxt-0.6.2/src/core/qxtlocale.cpp000066400000000000000000000106731215241066400172510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlocale.h" #include "qxtlocale_data_p.h" #include #include /*! \class QxtLocale \inmodule QxtCore \brief The QxtLocale class has some additional data and functionality, missing in QLocale. QxtLocale defines currencies and continents. Methods are available to gather various mappings and information. */ /*! \enum QxtLocale::Continent This enumerated type is used to specify a language. */ /*! \enum QxtLocale::Currency This enumerated type is used to specify a currency. */ /*! \fn QxtLocale::currencyToCode(Currency currency) This static method returns the 3-letter code for the given \a currency. */ QString QxtLocale::currencyToCode(Currency currency) { QString code; code.resize(3); const unsigned char *c = currency_code_list + 3 * (uint(currency)); code[0] = ushort(c[0]); code[1] = ushort(c[1]); code[2] = ushort(c[2]); return code; } /*! \fn QxtLocale::countryToISO2Letter(QLocale::Country country) This static method returns the 2-letter ISO 3166 code for the given \a country. */ QString QxtLocale::countryToISO2Letter(QLocale::Country country) { if (country == QLocale::AnyCountry) return QString(); QString code; code.resize(2); const unsigned char *c = two_letter_country_code_list + 2 * (uint(country)); code[0] = ushort(c[0]); code[1] = ushort(c[1]); return code; } /*! \fn QxtLocale::countryToISO3Letter(QLocale::Country country) This static method returns the 3-letter ISO 3166 code for the given \a country. */ QString QxtLocale::countryToISO3Letter(QLocale::Country country) { if (country == QLocale::AnyCountry) return QString(); QString code; code.resize(3); const unsigned char *c = three_letter_country_code_list + 3 * (uint(country)); code[0] = ushort(c[0]); code[1] = ushort(c[1]); code[2] = ushort(c[2]); return code; } /*! \fn QxtLocale::currencyToName(Currency currency) This static method returns the translated name for given \a currency. */ QString QxtLocale::currencyToName(Currency currency) { return QCoreApplication::instance()->translate("QxtLocale", currency_names[currency]); } /*! \fn QxtLocale::currencyForCountry(QLocale::Country country) This static method returns the currency for the given \a country. */ QxtLocale::Currency QxtLocale::currencyForCountry(QLocale::Country country) { return currency_for_country_list[country]; } /*! \fn QxtLocale::currencyToSymbol(Currency currency) This static method returns the symbol for the given \a currency. */ QString QxtLocale::currencyToSymbol(Currency currency) { QChar* data = symbol_for_country_list[currency]; int size = data[0].cell(); return QString(data + 1, size); } /*! \fn QxtLocale::continentToName(Continent continent) This static method returns the translated name for the given \a continent. */ QString QxtLocale::continentToName(Continent continent) { return QCoreApplication::instance()->translate("QxtLocale", continent_names[continent]); } /*! This static method returns the continent for the given \a country. */ QxtLocale::Continent QxtLocale::continentForCountry(QLocale::Country country) { return continent_for_country_list[country]; } libqxt-0.6.2/src/core/qxtlocale.h000066400000000000000000000147511215241066400167170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLOCALE_H #define QXTLOCALE_H #include #include #include class QXT_CORE_EXPORT QxtLocale { Q_GADGET Q_ENUMS(Currency Continent) public: enum Currency { NoCurrency = 0, Afghani = 1, AlgerianDinar = 2, ArgentinePeso = 3, ArmenianDram = 4, ArubanGuilder = 5, AustralianDollar = 6, AzerbaijanianManat = 7, BahamianDollar = 8, BahrainiDinar = 9, Baht = 10, Balboa = 11, BarbadosDollar = 12, BelarussianRuble = 13, BelizeDollar = 14, BermudianDollar = 15, BolivarFuerte = 16, Boliviano = 17, BrazilianReal = 18, BruneiDollar = 19, BulgarianLev = 20, BurundiFranc = 21, CFAFrancBCEAO = 22, CFAFrancBEAC = 23, CFPFranc = 24, CanadianDollar = 25, CapeVerdeEscudo = 26, CaymanIslandsDollar = 27, ChileanPeso = 28, ColombianPeso = 29, ComoroFranc = 30, ConvertibleMarks = 31, CordobaOro = 32, CostaRicanColon = 33, CroatianKuna = 34, CubanPeso = 35, CyprusPound = 36, CzechKoruna = 37, Dalasi = 38, DanishKrone = 39, Denar = 40, DjiboutiFranc = 41, Dobra = 42, DominicanPeso = 43, Dong = 44, EastCaribbeanDollar = 45, EgyptianPound = 46, ElSalvadorColon = 47, EthiopianBirr = 48, Euro = 49, FalklandIslandsPound = 50, FijiDollar = 51, Forint = 52, FrancCongolais = 53, GhanaCedi = 54, GibraltarPound = 55, Gourde = 56, Guarani = 57, GuineaBissauPeso = 58, GuineaFranc = 59, GuyanaDollar = 60, HongKongDollar = 61, Hryvnia = 62, IcelandKrona = 63, IndianRupee = 64, IranianRial = 65, IraqiDinar = 66, JamaicanDollar = 67, JordanianDinar = 68, KenyanShilling = 69, Kina = 70, Kip = 71, Kroon = 72, KuwaitiDinar = 73, Kwanza = 74, Kyat = 75, Lari = 76, LatvianLats = 77, LebanesePound = 78, Lek = 79, Lempira = 80, Leone = 81, LiberianDollar = 82, LibyanDinar = 83, Lilangeni = 84, LithuanianLitas = 85, Loti = 86, MalagasyAriary = 87, MalawiKwacha = 88, MalaysianRinggit = 89, MalteseLira = 90, Manat = 91, MauritiusRupee = 92, Metical = 93, MexicanPeso = 94, MexicanUnidadDeInversion = 95, MoldovanLeu = 96, MoroccanDirham = 97, Mvdol = 98, Naira = 99, Nakfa = 100, NamibiaDollar = 101, NepaleseRupee = 102, NetherlandsAntillianGuilder = 103, NewIsraeliSheqel = 104, NewLeu = 105, NewTaiwanDollar = 106, NewTurkishLira = 107, NewZealandDollar = 108, Ngultrum = 109, NorthKoreanWon = 110, NorwegianKrone = 111, NuevoSol = 112, Ouguiya = 113, Paanga = 114, PakistanRupee = 115, Pataca = 116, PesoUruguayo = 117, PhilippinePeso = 118, PoundSterling = 119, Pula = 120, QatariRial = 121, Quetzal = 122, Rand = 123, RialOmani = 124, Riel = 125, Rufiyaa = 126, Rupiah = 127, RussianRuble = 128, RwandaFranc = 129, SaintHelenaPound = 130, SaudiRiyal = 131, SerbianDinar = 132, SeychellesRupee = 133, SingaporeDollar = 134, SlovakKoruna = 135, SolomonIslandsDollar = 136, Som = 137, SomaliShilling = 138, Somoni = 139, SriLankaRupee = 140, SudanesePound = 141, SurinamDollar = 142, SwedishKrona = 143, SwissFranc = 144, SyrianPound = 145, Taka = 146, Tala = 147, TanzanianShilling = 148, Tenge = 149, TrinidadAndTobagoDollar = 150, Tugrik = 151, TunisianDinar = 152, UAEDirham = 153, USDollar = 154, UgandaShilling = 155, UnidadDeValorReal = 156, UnidadesDeFomento = 157, UruguayPesoEnUnidadesIndexadas = 158, UzbekistanSum = 159, Vatu = 160, Won = 161, YemeniRial = 162, Yen = 163, YuanRenminbi = 164, ZambiaKwacha = 165, ZimbabweDollar = 166, Zloty = 167, LastCurrency = Zloty }; enum Continent { None = 0, NorthAmerica = 1, SouthAmerica = 2, Europe = 3, Africa = 4, Asia = 5, Australia = 6, Antarctica = 7, LastContinent = Antarctica }; static QString countryToISO2Letter(QLocale::Country country); static QString countryToISO3Letter(QLocale::Country country); static Currency currencyForCountry(QLocale::Country country); static QString currencyToCode(Currency currency); static QString currencyToName(Currency currency); static QString currencyToSymbol(Currency currency); static QString continentToName(Continent continent); static Continent continentForCountry(QLocale::Country country); }; #endif // QXTLOCALE_H libqxt-0.6.2/src/core/qxtlocale_data_p.h000066400000000000000000001355571215241066400202370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ // // Generated on Fri Aug 14 00:10:57 2009 // for Qt 4.5.2 // #ifndef QXTLOCALE_DATA_P_H #define QXTLOCALE_DATA_P_H #include #include static const unsigned char two_letter_country_code_list[] = " " // Default "AF" // Afghanistan "AL" // Albania "DZ" // Algeria "AS" // AmericanSamoa "AD" // Andorra "AO" // Angola "AI" // Anguilla "AQ" // Antarctica "AG" // AntiguaAndBarbuda "AR" // Argentina "AM" // Armenia "AW" // Aruba "AU" // Australia "AT" // Austria "AZ" // Azerbaijan "BS" // Bahamas "BH" // Bahrain "BD" // Bangladesh "BB" // Barbados "BY" // Belarus "BE" // Belgium "BZ" // Belize "BJ" // Benin "BM" // Bermuda "BT" // Bhutan "BO" // Bolivia "BA" // BosniaAndHerzegowina "BW" // Botswana "BV" // BouvetIsland "BR" // Brazil "IO" // BritishIndianOceanTerritory "BN" // BruneiDarussalam "BG" // Bulgaria "BF" // BurkinaFaso "BI" // Burundi "KH" // Cambodia "CM" // Cameroon "CA" // Canada "CV" // CapeVerde "KY" // CaymanIslands "CF" // CentralAfricanRepublic "TD" // Chad "CL" // Chile "CN" // China "CX" // ChristmasIsland "CC" // CocosIslands "CO" // Colombia "KM" // Comoros "CD" // DemocraticRepublicOfCongo "CG" // PeoplesRepublicOfCongo "CK" // CookIslands "CR" // CostaRica "CI" // IvoryCoast "HR" // Croatia "CU" // Cuba "CY" // Cyprus "CZ" // CzechRepublic "DK" // Denmark "DJ" // Djibouti "DM" // Dominica "DO" // DominicanRepublic "TL" // EastTimor "EC" // Ecuador "EG" // Egypt "SV" // ElSalvador "GQ" // EquatorialGuinea "ER" // Eritrea "EE" // Estonia "ET" // Ethiopia "FK" // FalklandIslands "FO" // FaroeIslands "FJ" // Fiji "FI" // Finland "FR" // France "FX" // MetropolitanFrance "GF" // FrenchGuiana "PF" // FrenchPolynesia "TF" // FrenchSouthernTerritories "GA" // Gabon "GM" // Gambia "GE" // Georgia "DE" // Germany "GH" // Ghana "GI" // Gibraltar "GR" // Greece "GL" // Greenland "GD" // Grenada "GP" // Guadeloupe "GU" // Guam "GT" // Guatemala "GN" // Guinea "GW" // GuineaBissau "GY" // Guyana "HT" // Haiti "HM" // HeardAndMcDonaldIslands "HN" // Honduras "HK" // HongKong "HU" // Hungary "IS" // Iceland "IN" // India "ID" // Indonesia "IR" // Iran "IQ" // Iraq "IE" // Ireland "IL" // Israel "IT" // Italy "JM" // Jamaica "JP" // Japan "JO" // Jordan "KZ" // Kazakhstan "KE" // Kenya "KI" // Kiribati "KP" // DemocraticRepublicOfKorea "KR" // RepublicOfKorea "KW" // Kuwait "KG" // Kyrgyzstan "LA" // Lao "LV" // Latvia "LB" // Lebanon "LS" // Lesotho "LR" // Liberia "LY" // LibyanArabJamahiriya "LI" // Liechtenstein "LT" // Lithuania "LU" // Luxembourg "MO" // Macau "MK" // Macedonia "MG" // Madagascar "MW" // Malawi "MY" // Malaysia "MV" // Maldives "ML" // Mali "MT" // Malta "MH" // MarshallIslands "MQ" // Martinique "MR" // Mauritania "MU" // Mauritius "YT" // Mayotte "MX" // Mexico "FM" // Micronesia "MD" // Moldova "MC" // Monaco "MN" // Mongolia "MS" // Montserrat "MA" // Morocco "MZ" // Mozambique "MM" // Myanmar "NA" // Namibia "NR" // Nauru "NP" // Nepal "NL" // Netherlands "AN" // NetherlandsAntilles "NC" // NewCaledonia "NZ" // NewZealand "NI" // Nicaragua "NE" // Niger "NG" // Nigeria "NU" // Niue "NF" // NorfolkIsland "MP" // NorthernMarianaIslands "NO" // Norway "OM" // Oman "PK" // Pakistan "PW" // Palau "PS" // PalestinianTerritory "PA" // Panama "PG" // PapuaNewGuinea "PY" // Paraguay "PE" // Peru "PH" // Philippines "PN" // Pitcairn "PL" // Poland "PT" // Portugal "PR" // PuertoRico "QA" // Qatar "RE" // Reunion "RO" // Romania "RU" // RussianFederation "RW" // Rwanda "KN" // SaintKittsAndNevis "LC" // StLucia "VC" // StVincentAndTheGrenadines "WS" // Samoa "SM" // SanMarino "ST" // SaoTomeAndPrincipe "SA" // SaudiArabia "SN" // Senegal "SC" // Seychelles "SL" // SierraLeone "SG" // Singapore "SK" // Slovakia "SI" // Slovenia "SB" // SolomonIslands "SO" // Somalia "ZA" // SouthAfrica "GS" // SouthGeorgiaAndTheSouthSandwichIslands "ES" // Spain "LK" // SriLanka "SH" // StHelena "PM" // StPierreAndMiquelon "SD" // Sudan "SR" // Suriname "SJ" // SvalbardAndJanMayenIslands "SZ" // Swaziland "SE" // Sweden "CH" // Switzerland "SY" // SyrianArabRepublic "TW" // Taiwan "TJ" // Tajikistan "TZ" // Tanzania "TH" // Thailand "TG" // Togo "TK" // Tokelau "TO" // Tonga "TT" // TrinidadAndTobago "TN" // Tunisia "TR" // Turkey "TM" // Turkmenistan "TC" // TurksAndCaicosIslands "TV" // Tuvalu "UG" // Uganda "UA" // Ukraine "AE" // UnitedArabEmirates "GB" // UnitedKingdom "US" // UnitedStates "UM" // UnitedStatesMinorOutlyingIslands "UY" // Uruguay "UZ" // Uzbekistan "VU" // Vanuatu "VA" // VaticanCityState "VE" // Venezuela "VN" // VietNam "VG" // BritishVirginIslands "VI" // USVirginIslands "WF" // WallisAndFutunaIslands "EH" // WesternSahara "YE" // Yemen "YU" // Yugoslavia "ZM" // Zambia "ZW" // Zimbabwe "CS" // SerbiaAndMontenegro ; static const unsigned char three_letter_country_code_list[] = " " // Default "AFG" // Afghanistan "ALB" // Albania "DZA" // Algeria "ASM" // AmericanSamoa "AND" // Andorra "AGO" // Angola "AIA" // Anguilla "ATA" // Antarctica "ATG" // AntiguaAndBarbuda "ARG" // Argentina "ARM" // Armenia "ABW" // Aruba "AUS" // Australia "AUT" // Austria "AZE" // Azerbaijan "BHS" // Bahamas "BHR" // Bahrain "BGD" // Bangladesh "BRB" // Barbados "BLR" // Belarus "BEL" // Belgium "BLZ" // Belize "BEN" // Benin "BMU" // Bermuda "BTN" // Bhutan "BOL" // Bolivia "BIH" // BosniaAndHerzegowina "BWA" // Botswana "BVT" // BouvetIsland "BRA" // Brazil "IOT" // BritishIndianOceanTerritory "BRN" // BruneiDarussalam "BGR" // Bulgaria "BFA" // BurkinaFaso "BDI" // Burundi "KHM" // Cambodia "CMR" // Cameroon "CAN" // Canada "CPV" // CapeVerde "CYM" // CaymanIslands "CAF" // CentralAfricanRepublic "TCD" // Chad "CHL" // Chile "CHN" // China "CXR" // ChristmasIsland "CCK" // CocosIslands "COL" // Colombia "COM" // Comoros "COD" // DemocraticRepublicOfCongo "COG" // PeoplesRepublicOfCongo "COK" // CookIslands "CRI" // CostaRica "CIV" // IvoryCoast "HRV" // Croatia "CUB" // Cuba "CYP" // Cyprus "CZE" // CzechRepublic "DNK" // Denmark "DJI" // Djibouti "DMA" // Dominica "DOM" // DominicanRepublic "TLS" // EastTimor "ECU" // Ecuador "EGY" // Egypt "SLV" // ElSalvador "GNQ" // EquatorialGuinea "ERI" // Eritrea "EST" // Estonia "ETH" // Ethiopia "FLK" // FalklandIslands "FRO" // FaroeIslands "FJI" // Fiji "FIN" // Finland "FRA" // France "FX." // MetropolitanFrance "GUF" // FrenchGuiana "PYF" // FrenchPolynesia "ATF" // FrenchSouthernTerritories "GAB" // Gabon "GMB" // Gambia "GEO" // Georgia "DEU" // Germany "GHA" // Ghana "GIB" // Gibraltar "GRC" // Greece "GRL" // Greenland "GRD" // Grenada "GLP" // Guadeloupe "GUM" // Guam "GTM" // Guatemala "GIN" // Guinea "GNB" // GuineaBissau "GUY" // Guyana "HTI" // Haiti "HMD" // HeardAndMcDonaldIslands "HND" // Honduras "HKG" // HongKong "HUN" // Hungary "ISL" // Iceland "IND" // India "IDN" // Indonesia "IRN" // Iran "IRQ" // Iraq "IRL" // Ireland "ISR" // Israel "ITA" // Italy "JAM" // Jamaica "JPN" // Japan "JOR" // Jordan "KAZ" // Kazakhstan "KEN" // Kenya "KIR" // Kiribati "PRK" // DemocraticRepublicOfKorea "KOR" // RepublicOfKorea "KWT" // Kuwait "KGZ" // Kyrgyzstan "LAO" // Lao "LVA" // Latvia "LBN" // Lebanon "LSO" // Lesotho "LBR" // Liberia "LBY" // LibyanArabJamahiriya "LIE" // Liechtenstein "LTU" // Lithuania "LUX" // Luxembourg "MAC" // Macau "MKD" // Macedonia "MDG" // Madagascar "MWI" // Malawi "MYS" // Malaysia "MDV" // Maldives "MLI" // Mali "MLT" // Malta "MHL" // MarshallIslands "MTQ" // Martinique "MRT" // Mauritania "MUS" // Mauritius "MYT" // Mayotte "MEX" // Mexico "FSM" // Micronesia "MDA" // Moldova "MCO" // Monaco "MNG" // Mongolia "MSR" // Montserrat "MAR" // Morocco "MOZ" // Mozambique "MMR" // Myanmar "NAM" // Namibia "NRU" // Nauru "NPL" // Nepal "NLD" // Netherlands "ANT" // NetherlandsAntilles "NCL" // NewCaledonia "NZL" // NewZealand "NIC" // Nicaragua "NER" // Niger "NGA" // Nigeria "NIU" // Niue "NFK" // NorfolkIsland "MNP" // NorthernMarianaIslands "NOR" // Norway "OMN" // Oman "PAK" // Pakistan "PLW" // Palau "PSE" // PalestinianTerritory "PAN" // Panama "PNG" // PapuaNewGuinea "PRY" // Paraguay "PER" // Peru "PHL" // Philippines "PCN" // Pitcairn "POL" // Poland "PRT" // Portugal "PRI" // PuertoRico "QAT" // Qatar "REU" // Reunion "ROU" // Romania "RUS" // RussianFederation "RWA" // Rwanda "KNA" // SaintKittsAndNevis "LCA" // StLucia "VCT" // StVincentAndTheGrenadines "WSM" // Samoa "SMR" // SanMarino "STP" // SaoTomeAndPrincipe "SAU" // SaudiArabia "SEN" // Senegal "SYC" // Seychelles "SLE" // SierraLeone "SGP" // Singapore "SVK" // Slovakia "SVN" // Slovenia "SLB" // SolomonIslands "SOM" // Somalia "ZAF" // SouthAfrica "SGS" // SouthGeorgiaAndTheSouthSandwichIslands "ESP" // Spain "LKA" // SriLanka "SHN" // StHelena "SPM" // StPierreAndMiquelon "SDN" // Sudan "SUR" // Suriname "SJM" // SvalbardAndJanMayenIslands "SWZ" // Swaziland "SWE" // Sweden "CHE" // Switzerland "SYR" // SyrianArabRepublic "TWN" // Taiwan "TJK" // Tajikistan "TZA" // Tanzania "THA" // Thailand "TGO" // Togo "TKL" // Tokelau "TON" // Tonga "TTO" // TrinidadAndTobago "TUN" // Tunisia "TUR" // Turkey "TKM" // Turkmenistan "TCA" // TurksAndCaicosIslands "TUV" // Tuvalu "UGA" // Uganda "UKR" // Ukraine "ARE" // UnitedArabEmirates "GBR" // UnitedKingdom "USA" // UnitedStates "UMI" // UnitedStatesMinorOutlyingIslands "URY" // Uruguay "UZB" // Uzbekistan "VUT" // Vanuatu "VAT" // VaticanCityState "VEN" // Venezuela "VNM" // VietNam "VGB" // BritishVirginIslands "VIR" // USVirginIslands "WLF" // WallisAndFutunaIslands "ESH" // WesternSahara "YEM" // Yemen "YUG" // Yugoslavia "ZMB" // Zambia "ZWE" // Zimbabwe "SRB" // SerbiaAndMontenegro ; static QxtLocale::Currency currency_for_country_list[] = { QxtLocale::NoCurrency, // Default QxtLocale::Afghani, // Afghanistan QxtLocale::Lek, // Albania QxtLocale::AlgerianDinar, // Algeria QxtLocale::USDollar, // AmericanSamoa QxtLocale::Euro, // Andorra QxtLocale::Kwanza, // Angola QxtLocale::EastCaribbeanDollar, // Anguilla QxtLocale::NoCurrency, // Antarctica QxtLocale::EastCaribbeanDollar, // AntiguaAndBarbuda QxtLocale::ArgentinePeso, // Argentina QxtLocale::ArmenianDram, // Armenia QxtLocale::ArubanGuilder, // Aruba QxtLocale::AustralianDollar, // Australia QxtLocale::Euro, // Austria QxtLocale::AzerbaijanianManat, // Azerbaijan QxtLocale::BahamianDollar, // Bahamas QxtLocale::BahrainiDinar, // Bahrain QxtLocale::Taka, // Bangladesh QxtLocale::BarbadosDollar, // Barbados QxtLocale::BelarussianRuble, // Belarus QxtLocale::Euro, // Belgium QxtLocale::BelizeDollar, // Belize QxtLocale::CFAFrancBCEAO, // Benin QxtLocale::BermudianDollar, // Bermuda QxtLocale::IndianRupee, // Bhutan QxtLocale::Boliviano, // Bolivia QxtLocale::ConvertibleMarks, // BosniaAndHerzegowina QxtLocale::Pula, // Botswana QxtLocale::NorwegianKrone, // BouvetIsland QxtLocale::BrazilianReal, // Brazil QxtLocale::USDollar, // BritishIndianOceanTerritory QxtLocale::BruneiDollar, // BruneiDarussalam QxtLocale::BulgarianLev, // Bulgaria QxtLocale::CFAFrancBCEAO, // BurkinaFaso QxtLocale::BurundiFranc, // Burundi QxtLocale::Riel, // Cambodia QxtLocale::CFAFrancBEAC, // Cameroon QxtLocale::CanadianDollar, // Canada QxtLocale::CapeVerdeEscudo, // CapeVerde QxtLocale::CaymanIslandsDollar, // CaymanIslands QxtLocale::CFAFrancBEAC, // CentralAfricanRepublic QxtLocale::CFAFrancBEAC, // Chad QxtLocale::ChileanPeso, // Chile QxtLocale::YuanRenminbi, // China QxtLocale::AustralianDollar, // ChristmasIsland QxtLocale::AustralianDollar, // CocosIslands QxtLocale::ColombianPeso, // Colombia QxtLocale::ComoroFranc, // Comoros QxtLocale::CFAFrancBEAC, // DemocraticRepublicOfCongo QxtLocale::CFAFrancBEAC, // PeoplesRepublicOfCongo QxtLocale::NewZealandDollar, // CookIslands QxtLocale::CostaRicanColon, // CostaRica QxtLocale::CFAFrancBCEAO, // IvoryCoast QxtLocale::CroatianKuna, // Croatia QxtLocale::CubanPeso, // Cuba QxtLocale::CyprusPound, // Cyprus QxtLocale::CzechKoruna, // CzechRepublic QxtLocale::DanishKrone, // Denmark QxtLocale::DjiboutiFranc, // Djibouti QxtLocale::EastCaribbeanDollar, // Dominica QxtLocale::EastCaribbeanDollar, // DominicanRepublic QxtLocale::USDollar, // EastTimor QxtLocale::USDollar, // Ecuador QxtLocale::EgyptianPound, // Egypt QxtLocale::ElSalvadorColon, // ElSalvador QxtLocale::CFAFrancBEAC, // EquatorialGuinea QxtLocale::Nakfa, // Eritrea QxtLocale::Kroon, // Estonia QxtLocale::EthiopianBirr, // Ethiopia QxtLocale::FalklandIslandsPound, // FalklandIslands QxtLocale::DanishKrone, // FaroeIslands QxtLocale::FijiDollar, // Fiji QxtLocale::Euro, // Finland QxtLocale::Euro, // France QxtLocale::Euro, // MetropolitanFrance QxtLocale::Euro, // FrenchGuiana QxtLocale::CFPFranc, // FrenchPolynesia QxtLocale::Euro, // FrenchSouthernTerritories QxtLocale::CFAFrancBEAC, // Gabon QxtLocale::Dalasi, // Gambia QxtLocale::Lari, // Georgia QxtLocale::Euro, // Germany QxtLocale::GhanaCedi, // Ghana QxtLocale::GibraltarPound, // Gibraltar QxtLocale::Euro, // Greece QxtLocale::DanishKrone, // Greenland QxtLocale::EastCaribbeanDollar, // Grenada QxtLocale::Euro, // Guadeloupe QxtLocale::USDollar, // Guam QxtLocale::Quetzal, // Guatemala QxtLocale::CFAFrancBEAC, // Guinea QxtLocale::GuineaFranc, // GuineaBissau QxtLocale::GuyanaDollar, // Guyana QxtLocale::Gourde, // Haiti QxtLocale::AustralianDollar, // HeardAndMcDonaldIslands QxtLocale::Lempira, // Honduras QxtLocale::HongKongDollar, // HongKong QxtLocale::Forint, // Hungary QxtLocale::IcelandKrona, // Iceland QxtLocale::IndianRupee, // India QxtLocale::Rupiah, // Indonesia QxtLocale::IranianRial, // Iran QxtLocale::IraqiDinar, // Iraq QxtLocale::Euro, // Ireland QxtLocale::NewIsraeliSheqel, // Israel QxtLocale::Euro, // Italy QxtLocale::JamaicanDollar, // Jamaica QxtLocale::Yen, // Japan QxtLocale::JordanianDinar, // Jordan QxtLocale::Tenge, // Kazakhstan QxtLocale::KenyanShilling, // Kenya QxtLocale::AustralianDollar, // Kiribati QxtLocale::Won, // DemocraticRepublicOfKorea QxtLocale::NorthKoreanWon, // RepublicOfKorea QxtLocale::KuwaitiDinar, // Kuwait QxtLocale::Som, // Kyrgyzstan QxtLocale::Kip, // Lao QxtLocale::LatvianLats, // Latvia QxtLocale::LebanesePound, // Lebanon QxtLocale::Rand, // Lesotho QxtLocale::LiberianDollar, // Liberia QxtLocale::LibyanDinar, // LibyanArabJamahiriya QxtLocale::SwissFranc, // Liechtenstein QxtLocale::LithuanianLitas, // Lithuania QxtLocale::Euro, // Luxembourg QxtLocale::Pataca, // Macau QxtLocale::Denar, // Macedonia QxtLocale::MalagasyAriary, // Madagascar QxtLocale::MalawiKwacha, // Malawi QxtLocale::MalaysianRinggit, // Malaysia QxtLocale::Rufiyaa, // Maldives QxtLocale::CFAFrancBCEAO, // Mali QxtLocale::MalteseLira, // Malta QxtLocale::USDollar, // MarshallIslands QxtLocale::Euro, // Martinique QxtLocale::Ouguiya, // Mauritania QxtLocale::MauritiusRupee, // Mauritius QxtLocale::Euro, // Mayotte QxtLocale::MexicanPeso, // Mexico QxtLocale::USDollar, // Micronesia QxtLocale::MoldovanLeu, // Moldova QxtLocale::Euro, // Monaco QxtLocale::Tugrik, // Mongolia QxtLocale::EastCaribbeanDollar, // Montserrat QxtLocale::MoroccanDirham, // Morocco QxtLocale::Metical, // Mozambique QxtLocale::Kyat, // Myanmar QxtLocale::Rand, // Namibia QxtLocale::AustralianDollar, // Nauru QxtLocale::NepaleseRupee, // Nepal QxtLocale::Euro, // Netherlands QxtLocale::Euro, // NetherlandsAntilles QxtLocale::CFPFranc, // NewCaledonia QxtLocale::NewZealandDollar, // NewZealand QxtLocale::CordobaOro, // Nicaragua QxtLocale::CFAFrancBCEAO, // Niger QxtLocale::CFAFrancBCEAO, // Nigeria QxtLocale::NewZealandDollar, // Niue QxtLocale::AustralianDollar, // NorfolkIsland QxtLocale::USDollar, // NorthernMarianaIslands QxtLocale::NorwegianKrone, // Norway QxtLocale::RialOmani, // Oman QxtLocale::PakistanRupee, // Pakistan QxtLocale::USDollar, // Palau QxtLocale::NewIsraeliSheqel, // PalestinianTerritory QxtLocale::Balboa, // Panama QxtLocale::GuineaFranc, // PapuaNewGuinea QxtLocale::Guarani, // Paraguay QxtLocale::NuevoSol, // Peru QxtLocale::PhilippinePeso, // Philippines QxtLocale::NewZealandDollar, // Pitcairn QxtLocale::Zloty, // Poland QxtLocale::Euro, // Portugal QxtLocale::USDollar, // PuertoRico QxtLocale::QatariRial, // Qatar QxtLocale::Euro, // Reunion QxtLocale::NewLeu, // Romania QxtLocale::RussianRuble, // RussianFederation QxtLocale::RwandaFranc, // Rwanda QxtLocale::EastCaribbeanDollar, // SaintKittsAndNevis QxtLocale::EastCaribbeanDollar, // StLucia QxtLocale::EastCaribbeanDollar, // StVincentAndTheGrenadines QxtLocale::USDollar, // Samoa QxtLocale::Euro, // SanMarino QxtLocale::Dobra, // SaoTomeAndPrincipe QxtLocale::SaudiRiyal, // SaudiArabia QxtLocale::CFAFrancBCEAO, // Senegal QxtLocale::SeychellesRupee, // Seychelles QxtLocale::Leone, // SierraLeone QxtLocale::SingaporeDollar, // Singapore QxtLocale::SlovakKoruna, // Slovakia QxtLocale::Euro, // Slovenia QxtLocale::SolomonIslandsDollar, // SolomonIslands QxtLocale::SomaliShilling, // Somalia QxtLocale::Rand, // SouthAfrica QxtLocale::PoundSterling, // SouthGeorgiaAndTheSouthSandwichIslands QxtLocale::Euro, // Spain QxtLocale::SriLankaRupee, // SriLanka QxtLocale::SaintHelenaPound, // StHelena QxtLocale::Euro, // StPierreAndMiquelon QxtLocale::SudanesePound, // Sudan QxtLocale::SurinamDollar, // Suriname QxtLocale::NorwegianKrone, // SvalbardAndJanMayenIslands QxtLocale::Lilangeni, // Swaziland QxtLocale::SwedishKrona, // Sweden QxtLocale::SwissFranc, // Switzerland QxtLocale::SyrianPound, // SyrianArabRepublic QxtLocale::NewTaiwanDollar, // Taiwan QxtLocale::Somoni, // Tajikistan QxtLocale::TanzanianShilling, // Tanzania QxtLocale::Baht, // Thailand QxtLocale::CFAFrancBCEAO, // Togo QxtLocale::NewZealandDollar, // Tokelau QxtLocale::Paanga, // Tonga QxtLocale::TrinidadAndTobagoDollar, // TrinidadAndTobago QxtLocale::TunisianDinar, // Tunisia QxtLocale::NewTurkishLira, // Turkey QxtLocale::Manat, // Turkmenistan QxtLocale::USDollar, // TurksAndCaicosIslands QxtLocale::AustralianDollar, // Tuvalu QxtLocale::UgandaShilling, // Uganda QxtLocale::Hryvnia, // Ukraine QxtLocale::UAEDirham, // UnitedArabEmirates QxtLocale::PoundSterling, // UnitedKingdom QxtLocale::USDollar, // UnitedStates QxtLocale::USDollar, // UnitedStatesMinorOutlyingIslands QxtLocale::PesoUruguayo, // Uruguay QxtLocale::UzbekistanSum, // Uzbekistan QxtLocale::Vatu, // Vanuatu QxtLocale::Euro, // VaticanCityState QxtLocale::BolivarFuerte, // Venezuela QxtLocale::Dong, // VietNam QxtLocale::USDollar, // BritishVirginIslands QxtLocale::USDollar, // USVirginIslands QxtLocale::CFPFranc, // WallisAndFutunaIslands QxtLocale::MoroccanDirham, // WesternSahara QxtLocale::YemeniRial, // Yemen QxtLocale::NoCurrency, // Yugoslavia QxtLocale::ZambiaKwacha, // Zambia QxtLocale::ZimbabweDollar, // Zimbabwe }; static const char* currency_names[] = { QT_TRANSLATE_NOOP("QxtLocale", "*No Currency*"), // NoCurrency QT_TRANSLATE_NOOP("QxtLocale", "Afghani"), // Afghani QT_TRANSLATE_NOOP("QxtLocale", "Algerian Dinar"), // AlgerianDinar QT_TRANSLATE_NOOP("QxtLocale", "Argentine Peso"), // ArgentinePeso QT_TRANSLATE_NOOP("QxtLocale", "Armenian Dram"), // ArmenianDram QT_TRANSLATE_NOOP("QxtLocale", "Aruban Guilder"), // ArubanGuilder QT_TRANSLATE_NOOP("QxtLocale", "Australian Dollar"), // AustralianDollar QT_TRANSLATE_NOOP("QxtLocale", "Azerbaijanian Manat"), // AzerbaijanianManat QT_TRANSLATE_NOOP("QxtLocale", "Bahamian Dollar"), // BahamianDollar QT_TRANSLATE_NOOP("QxtLocale", "Bahraini Dinar"), // BahrainiDinar QT_TRANSLATE_NOOP("QxtLocale", "Baht"), // Baht QT_TRANSLATE_NOOP("QxtLocale", "Balboa"), // Balboa QT_TRANSLATE_NOOP("QxtLocale", "Barbados Dollar"), // BarbadosDollar QT_TRANSLATE_NOOP("QxtLocale", "Belarussian Ruble"), // BelarussianRuble QT_TRANSLATE_NOOP("QxtLocale", "Belize Dollar"), // BelizeDollar QT_TRANSLATE_NOOP("QxtLocale", "Bermudian Dollar"), // BermudianDollar QT_TRANSLATE_NOOP("QxtLocale", "Bolivar Fuerte"), // BolivarFuerte QT_TRANSLATE_NOOP("QxtLocale", "Boliviano"), // Boliviano QT_TRANSLATE_NOOP("QxtLocale", "Brazilian Real"), // BrazilianReal QT_TRANSLATE_NOOP("QxtLocale", "Brunei Dollar"), // BruneiDollar QT_TRANSLATE_NOOP("QxtLocale", "Bulgarian Lev"), // BulgarianLev QT_TRANSLATE_NOOP("QxtLocale", "Burundi Franc"), // BurundiFranc QT_TRANSLATE_NOOP("QxtLocale", "CFA Franc BCEAO"), // CFAFrancBCEAO QT_TRANSLATE_NOOP("QxtLocale", "CFA Franc BEAC"), // CFAFrancBEAC QT_TRANSLATE_NOOP("QxtLocale", "CFP Franc"), // CFPFranc QT_TRANSLATE_NOOP("QxtLocale", "Canadian Dollar"), // CanadianDollar QT_TRANSLATE_NOOP("QxtLocale", "Cape Verde Escudo"), // CapeVerdeEscudo QT_TRANSLATE_NOOP("QxtLocale", "Cayman Islands Dollar"), // CaymanIslandsDollar QT_TRANSLATE_NOOP("QxtLocale", "Chilean Peso"), // ChileanPeso QT_TRANSLATE_NOOP("QxtLocale", "Colombian Peso"), // ColombianPeso QT_TRANSLATE_NOOP("QxtLocale", "Comoro Franc"), // ComoroFranc QT_TRANSLATE_NOOP("QxtLocale", "Convertible Marks"), // ConvertibleMarks QT_TRANSLATE_NOOP("QxtLocale", "Cordoba Oro"), // CordobaOro QT_TRANSLATE_NOOP("QxtLocale", "Costa Rican Colon"), // CostaRicanColon QT_TRANSLATE_NOOP("QxtLocale", "Croatian Kuna"), // CroatianKuna QT_TRANSLATE_NOOP("QxtLocale", "Cuban Peso"), // CubanPeso QT_TRANSLATE_NOOP("QxtLocale", "Cyprus Pound"), // CyprusPound QT_TRANSLATE_NOOP("QxtLocale", "Czech Koruna"), // CzechKoruna QT_TRANSLATE_NOOP("QxtLocale", "Dalasi"), // Dalasi QT_TRANSLATE_NOOP("QxtLocale", "Danish Krone"), // DanishKrone QT_TRANSLATE_NOOP("QxtLocale", "Denar"), // Denar QT_TRANSLATE_NOOP("QxtLocale", "Djibouti Franc"), // DjiboutiFranc QT_TRANSLATE_NOOP("QxtLocale", "Dobra"), // Dobra QT_TRANSLATE_NOOP("QxtLocale", "Dominican Peso"), // DominicanPeso QT_TRANSLATE_NOOP("QxtLocale", "Dong"), // Dong QT_TRANSLATE_NOOP("QxtLocale", "East Caribbean Dollar"), // EastCaribbeanDollar QT_TRANSLATE_NOOP("QxtLocale", "Egyptian Pound"), // EgyptianPound QT_TRANSLATE_NOOP("QxtLocale", "El Salvador Colon"), // ElSalvadorColon QT_TRANSLATE_NOOP("QxtLocale", "Ethiopian Birr"), // EthiopianBirr QT_TRANSLATE_NOOP("QxtLocale", "Euro"), // Euro QT_TRANSLATE_NOOP("QxtLocale", "Falkland Islands Pound"), // FalklandIslandsPound QT_TRANSLATE_NOOP("QxtLocale", "Fiji Dollar"), // FijiDollar QT_TRANSLATE_NOOP("QxtLocale", "Forint"), // Forint QT_TRANSLATE_NOOP("QxtLocale", "Franc Congolais"), // FrancCongolais QT_TRANSLATE_NOOP("QxtLocale", "Ghana Cedi"), // GhanaCedi QT_TRANSLATE_NOOP("QxtLocale", "Gibraltar Pound"), // GibraltarPound QT_TRANSLATE_NOOP("QxtLocale", "Gourde"), // Gourde QT_TRANSLATE_NOOP("QxtLocale", "Guarani"), // Guarani QT_TRANSLATE_NOOP("QxtLocale", "Guinea-Bissau Peso"), // GuineaBissauPeso QT_TRANSLATE_NOOP("QxtLocale", "Guinea Franc"), // GuineaFranc QT_TRANSLATE_NOOP("QxtLocale", "Guyana Dollar"), // GuyanaDollar QT_TRANSLATE_NOOP("QxtLocale", "Hong Kong Dollar"), // HongKongDollar QT_TRANSLATE_NOOP("QxtLocale", "Hryvnia"), // Hryvnia QT_TRANSLATE_NOOP("QxtLocale", "Iceland Krona"), // IcelandKrona QT_TRANSLATE_NOOP("QxtLocale", "Indian Rupee"), // IndianRupee QT_TRANSLATE_NOOP("QxtLocale", "Iranian Rial"), // IranianRial QT_TRANSLATE_NOOP("QxtLocale", "Iraqi Dinar"), // IraqiDinar QT_TRANSLATE_NOOP("QxtLocale", "Jamaican Dollar"), // JamaicanDollar QT_TRANSLATE_NOOP("QxtLocale", "Jordanian Dinar"), // JordanianDinar QT_TRANSLATE_NOOP("QxtLocale", "Kenyan Shilling"), // KenyanShilling QT_TRANSLATE_NOOP("QxtLocale", "Kina"), // Kina QT_TRANSLATE_NOOP("QxtLocale", "Kip"), // Kip QT_TRANSLATE_NOOP("QxtLocale", "Kroon"), // Kroon QT_TRANSLATE_NOOP("QxtLocale", "Kuwaiti Dinar"), // KuwaitiDinar QT_TRANSLATE_NOOP("QxtLocale", "Kwanza"), // Kwanza QT_TRANSLATE_NOOP("QxtLocale", "Kyat"), // Kyat QT_TRANSLATE_NOOP("QxtLocale", "Lari"), // Lari QT_TRANSLATE_NOOP("QxtLocale", "Latvian Lats"), // LatvianLats QT_TRANSLATE_NOOP("QxtLocale", "Lebanese Pound"), // LebanesePound QT_TRANSLATE_NOOP("QxtLocale", "Lek"), // Lek QT_TRANSLATE_NOOP("QxtLocale", "Lempira"), // Lempira QT_TRANSLATE_NOOP("QxtLocale", "Leone"), // Leone QT_TRANSLATE_NOOP("QxtLocale", "Liberian Dollar"), // LiberianDollar QT_TRANSLATE_NOOP("QxtLocale", "Libyan Dinar"), // LibyanDinar QT_TRANSLATE_NOOP("QxtLocale", "Lilangeni"), // Lilangeni QT_TRANSLATE_NOOP("QxtLocale", "Lithuanian Litas"), // LithuanianLitas QT_TRANSLATE_NOOP("QxtLocale", "Loti"), // Loti QT_TRANSLATE_NOOP("QxtLocale", "Malagasy Ariary"), // MalagasyAriary QT_TRANSLATE_NOOP("QxtLocale", "MalawiKwacha"), // MalawiKwacha QT_TRANSLATE_NOOP("QxtLocale", "Malaysian Ringgit"), // MalaysianRinggit QT_TRANSLATE_NOOP("QxtLocale", "Maltese Lira"), // MalteseLira QT_TRANSLATE_NOOP("QxtLocale", "Manat"), // Manat QT_TRANSLATE_NOOP("QxtLocale", "Mauritius Rupee"), // MauritiusRupee QT_TRANSLATE_NOOP("QxtLocale", "Metical"), // Metical QT_TRANSLATE_NOOP("QxtLocale", "Mexican Peso"), // MexicanPeso QT_TRANSLATE_NOOP("QxtLocale", "Mexican Unidad de Inversion"), // MexicanUnidadDeInversion QT_TRANSLATE_NOOP("QxtLocale", "Moldovan Leu"), // MoldovanLeu QT_TRANSLATE_NOOP("QxtLocale", "Moroccan Dirham"), // MoroccanDirham QT_TRANSLATE_NOOP("QxtLocale", "Mvdol"), // Mvdol QT_TRANSLATE_NOOP("QxtLocale", "Naira"), // Naira QT_TRANSLATE_NOOP("QxtLocale", "Nakfa"), // Nakfa QT_TRANSLATE_NOOP("QxtLocale", "Namibia Dollar"), // NamibiaDollar QT_TRANSLATE_NOOP("QxtLocale", "Nepalese Rupee"), // NepaleseRupee QT_TRANSLATE_NOOP("QxtLocale", "Netherlands Antillian Guilder"), // NetherlandsAntillianGuilder QT_TRANSLATE_NOOP("QxtLocale", "New Israeli Sheqel"), // NewIsraeliSheqel QT_TRANSLATE_NOOP("QxtLocale", "New Leu"), // NewLeu QT_TRANSLATE_NOOP("QxtLocale", "New Taiwan Dollar"), // NewTaiwanDollar QT_TRANSLATE_NOOP("QxtLocale", "New Turkish Lira"), // NewTurkishLira QT_TRANSLATE_NOOP("QxtLocale", "New Zealand Dollar"), // NewZealandDollar QT_TRANSLATE_NOOP("QxtLocale", "Ngultrum"), // Ngultrum QT_TRANSLATE_NOOP("QxtLocale", "North Korean Won"), // NorthKoreanWon QT_TRANSLATE_NOOP("QxtLocale", "Norwegian Krone"), // NorwegianKrone QT_TRANSLATE_NOOP("QxtLocale", "Nuevo Sol"), // NuevoSol QT_TRANSLATE_NOOP("QxtLocale", "Ouguiya"), // Ouguiya QT_TRANSLATE_NOOP("QxtLocale", "Pa'anga"), // Paanga QT_TRANSLATE_NOOP("QxtLocale", "Pakistan Rupee"), // PakistanRupee QT_TRANSLATE_NOOP("QxtLocale", "Pataca"), // Pataca QT_TRANSLATE_NOOP("QxtLocale", "Peso Uruguayo"), // PesoUruguayo QT_TRANSLATE_NOOP("QxtLocale", "Philippine Peso"), // PhilippinePeso QT_TRANSLATE_NOOP("QxtLocale", "Pound Sterling"), // PoundSterling QT_TRANSLATE_NOOP("QxtLocale", "Pula"), // Pula QT_TRANSLATE_NOOP("QxtLocale", "Qatari Rial"), // QatariRial QT_TRANSLATE_NOOP("QxtLocale", "Quetzal"), // Quetzal QT_TRANSLATE_NOOP("QxtLocale", "Rand"), // Rand QT_TRANSLATE_NOOP("QxtLocale", "Rial Omani"), // RialOmani QT_TRANSLATE_NOOP("QxtLocale", "Riel"), // Riel QT_TRANSLATE_NOOP("QxtLocale", "Rufiyaa"), // Rufiyaa QT_TRANSLATE_NOOP("QxtLocale", "Rupiah"), // Rupiah QT_TRANSLATE_NOOP("QxtLocale", "Russian Ruble"), // RussianRuble QT_TRANSLATE_NOOP("QxtLocale", "Rwanda Franc"), // RwandaFranc QT_TRANSLATE_NOOP("QxtLocale", "Saint Helena Pound"), // SaintHelenaPound QT_TRANSLATE_NOOP("QxtLocale", "Saudi Riyal"), // SaudiRiyal QT_TRANSLATE_NOOP("QxtLocale", "Serbian Dinar"), // SerbianDinar QT_TRANSLATE_NOOP("QxtLocale", "Seychelles Rupee"), // SeychellesRupee QT_TRANSLATE_NOOP("QxtLocale", "Singapore Dollar"), // SingaporeDollar QT_TRANSLATE_NOOP("QxtLocale", "Slovak Koruna"), // SlovakKoruna QT_TRANSLATE_NOOP("QxtLocale", "Solomon Islands Dollar"), // SolomonIslandsDollar QT_TRANSLATE_NOOP("QxtLocale", "Som"), // Som QT_TRANSLATE_NOOP("QxtLocale", "Somali Shilling"), // SomaliShilling QT_TRANSLATE_NOOP("QxtLocale", "Somoni"), // Somoni QT_TRANSLATE_NOOP("QxtLocale", "Sri Lanka Rupee"), // SriLankaRupee QT_TRANSLATE_NOOP("QxtLocale", "Sudanese Pound"), // SudanesePound QT_TRANSLATE_NOOP("QxtLocale", "Surinam Dollar"), // SurinamDollar QT_TRANSLATE_NOOP("QxtLocale", "Swedish Krona"), // SwedishKrona QT_TRANSLATE_NOOP("QxtLocale", "Swiss Franc"), // SwissFranc QT_TRANSLATE_NOOP("QxtLocale", "Syrian Pound"), // SyrianPound QT_TRANSLATE_NOOP("QxtLocale", "Taka"), // Taka QT_TRANSLATE_NOOP("QxtLocale", "Tala"), // Tala QT_TRANSLATE_NOOP("QxtLocale", "Tanzanian Shilling"), // TanzanianShilling QT_TRANSLATE_NOOP("QxtLocale", "Tenge"), // Tenge QT_TRANSLATE_NOOP("QxtLocale", "Trinidad and Tobago Dollar"), // TrinidadAndTobagoDollar QT_TRANSLATE_NOOP("QxtLocale", "Tugrik"), // Tugrik QT_TRANSLATE_NOOP("QxtLocale", "Tunisian Dinar"), // TunisianDinar QT_TRANSLATE_NOOP("QxtLocale", "UAE Dirham"), // UAEDirham QT_TRANSLATE_NOOP("QxtLocale", "US Dollar"), // USDollar QT_TRANSLATE_NOOP("QxtLocale", "Uganda Shilling"), // UgandaShilling QT_TRANSLATE_NOOP("QxtLocale", "Unidad de Valor Real"), // UnidadDeValorReal QT_TRANSLATE_NOOP("QxtLocale", "Unidades de fomento"), // UnidadesDeFomento QT_TRANSLATE_NOOP("QxtLocale", "Uruguay Peso en Unidades Indexadas"), // UruguayPesoEnUnidadesIndexadas QT_TRANSLATE_NOOP("QxtLocale", "Uzbekistan Sum"), // UzbekistanSum QT_TRANSLATE_NOOP("QxtLocale", "Vatu"), // Vatu QT_TRANSLATE_NOOP("QxtLocale", "Won"), // Won QT_TRANSLATE_NOOP("QxtLocale", "Yemeni Rial"), // YemeniRial QT_TRANSLATE_NOOP("QxtLocale", "Yen"), // Yen QT_TRANSLATE_NOOP("QxtLocale", "Yuan Renminbi"), // YuanRenminbi QT_TRANSLATE_NOOP("QxtLocale", "ZambiaKwacha"), // ZambiaKwacha QT_TRANSLATE_NOOP("QxtLocale", "Zimbabwe Dollar"), // ZimbabweDollar QT_TRANSLATE_NOOP("QxtLocale", "Zloty"), // Zloty }; static QChar symbol_for_country_list[][5] = { { }, // NoCurrency { 1,0x60b }, // Afghani { }, // AlgerianDinar { 1,0x24 }, // ArgentinePeso { }, // ArmenianDram { 1,0x192 }, // ArubanGuilder { 1,0x24 }, // AustralianDollar { 3,0x43c,0x430,0x43d }, // AzerbaijanianManat { 1,0x24 }, // BahamianDollar { }, // BahrainiDinar { 1,0xe3f }, // Baht { 3,0x42,0x2f,0x2e }, // Balboa { 1,0x24 }, // BarbadosDollar { 2,0x70,0x2e }, // BelarussianRuble { 3,0x42,0x5a,0x24 }, // BelizeDollar { 1,0x24 }, // BermudianDollar { 2,0x42,0x73 }, // BolivarFuerte { 2,0x24,0x62 }, // Boliviano { 2,0x52,0x24 }, // BrazilianReal { 1,0x24 }, // BruneiDollar { 2,0x43b,0x432 }, // BulgarianLev { }, // BurundiFranc { }, // CFAFrancBCEAO { }, // CFAFrancBEAC { }, // CFPFranc { 1,0x24 }, // CanadianDollar { }, // CapeVerdeEscudo { 1,0x24 }, // CaymanIslandsDollar { 1,0x24 }, // ChileanPeso { 1,0x24 }, // ColombianPeso { }, // ComoroFranc { 2,0x4b,0x4d }, // ConvertibleMarks { 2,0x43,0x24 }, // CordobaOro { 1,0x20a1 }, // CostaRicanColon { 2,0x6b,0x6e }, // CroatianKuna { 1,0x20b1 }, // CubanPeso { }, // CyprusPound { 2,0x4b,0x10d }, // CzechKoruna { }, // Dalasi { 2,0x6b,0x72 }, // DanishKrone { 3,0x434,0x435,0x43d }, // Denar { }, // DjiboutiFranc { }, // Dobra { 3,0x52,0x44,0x24 }, // DominicanPeso { 1,0x20ab }, // Dong { 1,0x24 }, // EastCaribbeanDollar { 1,0xa3 }, // EgyptianPound { 1,0x24 }, // ElSalvadorColon { }, // EthiopianBirr { 1,0x20ac }, // Euro { 1,0xa3 }, // FalklandIslandsPound { 1,0x24 }, // FijiDollar { 2,0x46,0x74 }, // Forint { }, // FrancCongolais { }, // GhanaCedi { 1,0xa3 }, // GibraltarPound { }, // Gourde { 2,0x47,0x73 }, // Guarani { }, // GuineaBissauPeso { }, // GuineaFranc { 1,0x24 }, // GuyanaDollar { 1,0x5143 }, // HongKongDollar { 1,0x20b4 }, // Hryvnia { 2,0x6b,0x72 }, // IcelandKrona { 1,0x20a8 }, // IndianRupee { 1,0xfdfc }, // IranianRial { }, // IraqiDinar { 2,0x4a,0x24 }, // JamaicanDollar { }, // JordanianDinar { }, // KenyanShilling { }, // Kina { 1,0x20ad }, // Kip { 2,0x6b,0x72 }, // Kroon { }, // KuwaitiDinar { }, // Kwanza { }, // Kyat { }, // Lari { 2,0x4c,0x73 }, // LatvianLats { 1,0xa3 }, // LebanesePound { 3,0x4c,0x65,0x6b }, // Lek { 1,0x4c }, // Lempira { }, // Leone { 1,0x24 }, // LiberianDollar { }, // LibyanDinar { }, // Lilangeni { 2,0x4c,0x74 }, // LithuanianLitas { }, // Loti { }, // MalagasyAriary { }, // MalawiKwacha { 2,0x52,0x4d }, // MalaysianRinggit { }, // MalteseLira { }, // Manat { 1,0x20a8 }, // MauritiusRupee { 2,0x4d,0x54 }, // Metical { 1,0x24 }, // MexicanPeso { }, // MexicanUnidadDeInversion { }, // MoldovanLeu { }, // MoroccanDirham { }, // Mvdol { 1,0x20a6 }, // Naira { }, // Nakfa { 1,0x24 }, // NamibiaDollar { 1,0x20a8 }, // NepaleseRupee { 1,0x192 }, // NetherlandsAntillianGuilder { 1,0x20aa }, // NewIsraeliSheqel { 3,0x6c,0x65,0x69 }, // NewLeu { 3,0x4e,0x54,0x24 }, // NewTaiwanDollar { 3,0x59,0x54,0x4c }, // NewTurkishLira { 1,0x24 }, // NewZealandDollar { }, // Ngultrum { 1,0x20a9 }, // NorthKoreanWon { 2,0x6b,0x72 }, // NorwegianKrone { 3,0x53,0x2f,0x2e }, // NuevoSol { }, // Ouguiya { }, // Paanga { 1,0x20a8 }, // PakistanRupee { }, // Pataca { 2,0x24,0x55 }, // PesoUruguayo { 3,0x50,0x68,0x70 }, // PhilippinePeso { 1,0xa3 }, // PoundSterling { 1,0x50 }, // Pula { 1,0xfdfc }, // QatariRial { 1,0x51 }, // Quetzal { 1,0x52 }, // Rand { 1,0xfdfc }, // RialOmani { 1,0x17db }, // Riel { }, // Rufiyaa { 2,0x52,0x7 }, // Rupiah { 3,0x440,0x443,0x431 }, // RussianRuble { }, // RwandaFranc { 1,0xa3 }, // SaintHelenaPound { 1,0xfdfc }, // SaudiRiyal { 4,0x414,0x438,0x43d,0x2e }, // SerbianDinar { 1,0x20a8 }, // SeychellesRupee { 1,0x24 }, // SingaporeDollar { }, // SlovakKoruna { 1,0x24 }, // SolomonIslandsDollar { 2,0x43b,0x432 }, // Som { 1,0x53 }, // SomaliShilling { }, // Somoni { 1,0x20a8 }, // SriLankaRupee { }, // SudanesePound { 1,0x24 }, // SurinamDollar { 2,0x6b,0x72 }, // SwedishKrona { 3,0x43,0x48,0x46 }, // SwissFranc { 1,0xa3 }, // SyrianPound { }, // Taka { }, // Tala { }, // TanzanianShilling { 2,0x43b,0x432 }, // Tenge { 3,0x54,0x54,0x24 }, // TrinidadAndTobagoDollar { 1,0x20ae }, // Tugrik { }, // TunisianDinar { 1,0x62c }, // UAEDirham { 1,0x24 }, // USDollar { }, // UgandaShilling { }, // UnidadDeValorReal { }, // UnidadesDeFomento { }, // UruguayPesoEnUnidadesIndexadas { 2,0x43b,0x432 }, // UzbekistanSum { }, // Vatu { 1,0x20a9 }, // Won { 1,0xfdfc }, // YemeniRial { 1,0xa5 }, // Yen { 1,0x5143 }, // YuanRenminbi { }, // ZambiaKwacha { 2,0x5a,0x24 }, // ZimbabweDollar { 2,0x7a,0x142 }, // Zloty } ; static const unsigned char currency_code_list[] = " " // NoCurrency "AFN" // Afghani "DZD" // AlgerianDinar "ARS" // ArgentinePeso "AMD" // ArmenianDram "AWG" // ArubanGuilder "AUD" // AustralianDollar "AZN" // AzerbaijanianManat "BSD" // BahamianDollar "BHD" // BahrainiDinar "THB" // Baht "PAB" // Balboa "BBD" // BarbadosDollar "BYR" // BelarussianRuble "BZD" // BelizeDollar "BMD" // BermudianDollar "VEF" // BolivarFuerte "BOB" // Boliviano "BRL" // BrazilianReal "BND" // BruneiDollar "BGN" // BulgarianLev "BIF" // BurundiFranc "XOF" // CFAFrancBCEAO "XAF" // CFAFrancBEAC "XPF" // CFPFranc "CAD" // CanadianDollar "CVE" // CapeVerdeEscudo "KYD" // CaymanIslandsDollar "CLP" // ChileanPeso "COP" // ColombianPeso "KMF" // ComoroFranc "BAM" // ConvertibleMarks "NIO" // CordobaOro "CRC" // CostaRicanColon "HRK" // CroatianKuna "CUP" // CubanPeso "CYP" // CyprusPound "CZK" // CzechKoruna "GMD" // Dalasi "DKK" // DanishKrone "MKD" // Denar "DJF" // DjiboutiFranc "STD" // Dobra "DOP" // DominicanPeso "VND" // Dong "XCD" // EastCaribbeanDollar "EGP" // EgyptianPound "SVC" // ElSalvadorColon "ETB" // EthiopianBirr "EUR" // Euro "FKP" // FalklandIslandsPound "FJD" // FijiDollar "HUF" // Forint "CDF" // FrancCongolais "GHS" // GhanaCedi "GIP" // GibraltarPound "HTG" // Gourde "PYG" // Guarani "GWP" // GuineaBissauPeso "GNF" // GuineaFranc "GYD" // GuyanaDollar "HKD" // HongKongDollar "UAH" // Hryvnia "ISK" // IcelandKrona "INR" // IndianRupee "IRR" // IranianRial "IQD" // IraqiDinar "JMD" // JamaicanDollar "JOD" // JordanianDinar "KES" // KenyanShilling "PGK" // Kina "LAK" // Kip "EEK" // Kroon "KWD" // KuwaitiDinar "AOA" // Kwanza "MMK" // Kyat "GEL" // Lari "LVL" // LatvianLats "LBP" // LebanesePound "ALL" // Lek "HNL" // Lempira "SLL" // Leone "LRD" // LiberianDollar "LYD" // LibyanDinar "SZL" // Lilangeni "LTL" // LithuanianLitas "LSL" // Loti "MGA" // MalagasyAriary "MWK" // MalawiKwacha "MYR" // MalaysianRinggit "MTL" // MalteseLira "TMM" // Manat "MUR" // MauritiusRupee "MZN" // Metical "MXN" // MexicanPeso "MXV" // MexicanUnidadDeInversion "MDL" // MoldovanLeu "MAD" // MoroccanDirham "BOV" // Mvdol "NGN" // Naira "ERN" // Nakfa "NAD" // NamibiaDollar "NPR" // NepaleseRupee "ANG" // NetherlandsAntillianGuilder "ILS" // NewIsraeliSheqel "RON" // NewLeu "TWD" // NewTaiwanDollar "TRY" // NewTurkishLira "NZD" // NewZealandDollar "BTN" // Ngultrum "KPW" // NorthKoreanWon "NOK" // NorwegianKrone "PEN" // NuevoSol "MRO" // Ouguiya "TOP" // Paanga "PKR" // PakistanRupee "MOP" // Pataca "UYU" // PesoUruguayo "PHP" // PhilippinePeso "GBP" // PoundSterling "BWP" // Pula "QAR" // QatariRial "GTQ" // Quetzal "ZAR" // Rand "OMR" // RialOmani "KHR" // Riel "MVR" // Rufiyaa "IDR" // Rupiah "RUB" // RussianRuble "RWF" // RwandaFranc "SHP" // SaintHelenaPound "SAR" // SaudiRiyal "RSD" // SerbianDinar "SCR" // SeychellesRupee "SGD" // SingaporeDollar "SKK" // SlovakKoruna "SBD" // SolomonIslandsDollar "KGS" // Som "SOS" // SomaliShilling "TJS" // Somoni "LKR" // SriLankaRupee "SDG" // SudanesePound "SRD" // SurinamDollar "SEK" // SwedishKrona "CHF" // SwissFranc "SYP" // SyrianPound "BDT" // Taka "WST" // Tala "TZS" // TanzanianShilling "KZT" // Tenge "TTD" // TrinidadAndTobagoDollar "MNT" // Tugrik "TND" // TunisianDinar "AED" // UAEDirham "USD" // USDollar "UGX" // UgandaShilling "COU" // UnidadDeValorReal "CLF" // UnidadesDeFomento "UYI" // UruguayPesoEnUnidadesIndexadas "UZS" // UzbekistanSum "VUV" // Vatu "KRW" // Won "YER" // YemeniRial "JPY" // Yen "CNY" // YuanRenminbi "ZMK" // ZambiaKwacha "ZWD" // ZimbabweDollar "PLN" // Zloty ; static const char* continent_names[] = { QT_TRANSLATE_NOOP("QxtLocale", "None"), // None QT_TRANSLATE_NOOP("QxtLocale", "NorthAmerica"), // NorthAmerica QT_TRANSLATE_NOOP("QxtLocale", "SouthAmerica"), // SouthAmerica QT_TRANSLATE_NOOP("QxtLocale", "Europe"), // Europe QT_TRANSLATE_NOOP("QxtLocale", "Africa"), // Africa QT_TRANSLATE_NOOP("QxtLocale", "Asia"), // Asia QT_TRANSLATE_NOOP("QxtLocale", "Australia"), // Australia QT_TRANSLATE_NOOP("QxtLocale", "Antarctica"), // Antarctica }; static const QxtLocale::Continent continent_for_country_list[] = { QxtLocale::None, // Default QxtLocale::Asia, // Afghanistan QxtLocale::Europe, // Albania QxtLocale::Africa, // Algeria QxtLocale::Australia, // AmericanSamoa QxtLocale::Europe, // Andorra QxtLocale::Africa, // Angola QxtLocale::NorthAmerica, // Anguilla QxtLocale::Antarctica, // Antarctica QxtLocale::NorthAmerica, // AntiguaAndBarbuda QxtLocale::SouthAmerica, // Argentina QxtLocale::Europe, // Armenia QxtLocale::NorthAmerica, // Aruba QxtLocale::Australia, // Australia QxtLocale::Europe, // Austria QxtLocale::Europe, // Azerbaijan QxtLocale::NorthAmerica, // Bahamas QxtLocale::Asia, // Bahrain QxtLocale::Asia, // Bangladesh QxtLocale::NorthAmerica, // Barbados QxtLocale::Europe, // Belarus QxtLocale::Europe, // Belgium QxtLocale::SouthAmerica, // Belize QxtLocale::Africa, // Benin QxtLocale::NorthAmerica, // Bermuda QxtLocale::Asia, // Bhutan QxtLocale::SouthAmerica, // Bolivia QxtLocale::Europe, // BosniaAndHerzegowina QxtLocale::Africa, // Botswana QxtLocale::None, // BouvetIsland QxtLocale::SouthAmerica, // Brazil QxtLocale::Asia, // BritishIndianOceanTerritory QxtLocale::Asia, // BruneiDarussalam QxtLocale::Europe, // Bulgaria QxtLocale::Africa, // BurkinaFaso QxtLocale::Africa, // Burundi QxtLocale::Asia, // Cambodia QxtLocale::Africa, // Cameroon QxtLocale::NorthAmerica, // Canada QxtLocale::Africa, // CapeVerde QxtLocale::NorthAmerica, // CaymanIslands QxtLocale::Africa, // CentralAfricanRepublic QxtLocale::Africa, // Chad QxtLocale::SouthAmerica, // Chile QxtLocale::Asia, // China QxtLocale::Australia, // ChristmasIsland QxtLocale::Australia, // CocosIslands QxtLocale::SouthAmerica, // Colombia QxtLocale::Africa, // Comoros QxtLocale::Africa, // DemocraticRepublicOfCongo QxtLocale::Africa, // PeoplesRepublicOfCongo QxtLocale::Australia, // CookIslands QxtLocale::NorthAmerica, // CostaRica QxtLocale::Africa, // IvoryCoast QxtLocale::Europe, // Croatia QxtLocale::NorthAmerica, // Cuba QxtLocale::Europe, // Cyprus QxtLocale::Europe, // CzechRepublic QxtLocale::Europe, // Denmark QxtLocale::Africa, // Djibouti QxtLocale::NorthAmerica, // Dominica QxtLocale::NorthAmerica, // DominicanRepublic QxtLocale::Asia, // EastTimor QxtLocale::SouthAmerica, // Ecuador QxtLocale::Africa, // Egypt QxtLocale::NorthAmerica, // ElSalvador QxtLocale::Africa, // EquatorialGuinea QxtLocale::Africa, // Eritrea QxtLocale::Europe, // Estonia QxtLocale::Africa, // Ethiopia QxtLocale::SouthAmerica, // FalklandIslands QxtLocale::Europe, // FaroeIslands QxtLocale::Australia, // Fiji QxtLocale::Europe, // Finland QxtLocale::Europe, // France QxtLocale::Europe, // MetropolitanFrance QxtLocale::SouthAmerica, // FrenchGuiana QxtLocale::Australia, // FrenchPolynesia QxtLocale::None, // FrenchSouthernTerritories QxtLocale::Africa, // Gabon QxtLocale::Africa, // Gambia QxtLocale::Europe, // Georgia QxtLocale::Europe, // Germany QxtLocale::Africa, // Ghana QxtLocale::Europe, // Gibraltar QxtLocale::Europe, // Greece QxtLocale::NorthAmerica, // Greenland QxtLocale::NorthAmerica, // Grenada QxtLocale::NorthAmerica, // Guadeloupe QxtLocale::Australia, // Guam QxtLocale::NorthAmerica, // Guatemala QxtLocale::Africa, // Guinea QxtLocale::Africa, // GuineaBissau QxtLocale::SouthAmerica, // Guyana QxtLocale::NorthAmerica, // Haiti QxtLocale::None, // HeardAndMcDonaldIslands QxtLocale::SouthAmerica, // Honduras QxtLocale::Asia, // HongKong QxtLocale::Europe, // Hungary QxtLocale::Europe, // Iceland QxtLocale::Asia, // India QxtLocale::Australia, // Indonesia QxtLocale::Asia, // Iran QxtLocale::Asia, // Iraq QxtLocale::Europe, // Ireland QxtLocale::Asia, // Israel QxtLocale::Europe, // Italy QxtLocale::NorthAmerica, // Jamaica QxtLocale::Asia, // Japan QxtLocale::Asia, // Jordan QxtLocale::Europe, // Kazakhstan QxtLocale::Africa, // Kenya QxtLocale::Australia, // Kiribati QxtLocale::Asia, // DemocraticRepublicOfKorea QxtLocale::Asia, // RepublicOfKorea QxtLocale::Asia, // Kuwait QxtLocale::Asia, // Kyrgyzstan QxtLocale::Asia, // Lao QxtLocale::Europe, // Latvia QxtLocale::Asia, // Lebanon QxtLocale::Africa, // Lesotho QxtLocale::Africa, // Liberia QxtLocale::Africa, // LibyanArabJamahiriya QxtLocale::Europe, // Liechtenstein QxtLocale::Europe, // Lithuania QxtLocale::Europe, // Luxembourg QxtLocale::Asia, // Macau QxtLocale::Europe, // Macedonia QxtLocale::Africa, // Madagascar QxtLocale::Africa, // Malawi QxtLocale::Asia, // Malaysia QxtLocale::Asia, // Maldives QxtLocale::Africa, // Mali QxtLocale::Europe, // Malta QxtLocale::Australia, // MarshallIslands QxtLocale::NorthAmerica, // Martinique QxtLocale::Africa, // Mauritania QxtLocale::Africa, // Mauritius QxtLocale::Africa, // Mayotte QxtLocale::NorthAmerica, // Mexico QxtLocale::Australia, // Micronesia QxtLocale::Asia, // Moldova QxtLocale::Europe, // Monaco QxtLocale::Asia, // Mongolia QxtLocale::NorthAmerica, // Montserrat QxtLocale::Africa, // Morocco QxtLocale::Africa, // Mozambique QxtLocale::Asia, // Myanmar QxtLocale::Africa, // Namibia QxtLocale::Australia, // Nauru QxtLocale::Asia, // Nepal QxtLocale::Europe, // Netherlands QxtLocale::NorthAmerica, // NetherlandsAntilles QxtLocale::Australia, // NewCaledonia QxtLocale::Australia, // NewZealand QxtLocale::NorthAmerica, // Nicaragua QxtLocale::Africa, // Niger QxtLocale::Africa, // Nigeria QxtLocale::Australia, // Niue QxtLocale::Australia, // NorfolkIsland QxtLocale::Australia, // NorthernMarianaIslands QxtLocale::Europe, // Norway QxtLocale::Asia, // Oman QxtLocale::Asia, // Pakistan QxtLocale::Australia, // Palau QxtLocale::Asia, // PalestinianTerritory QxtLocale::NorthAmerica, // Panama QxtLocale::Australia, // PapuaNewGuinea QxtLocale::SouthAmerica, // Paraguay QxtLocale::SouthAmerica, // Peru QxtLocale::Asia, // Philippines QxtLocale::Australia, // Pitcairn QxtLocale::Europe, // Poland QxtLocale::Europe, // Portugal QxtLocale::NorthAmerica, // PuertoRico QxtLocale::Asia, // Qatar QxtLocale::Africa, // Reunion QxtLocale::Europe, // Romania QxtLocale::Europe, // RussianFederation QxtLocale::Africa, // Rwanda QxtLocale::NorthAmerica, // SaintKittsAndNevis QxtLocale::NorthAmerica, // StLucia QxtLocale::NorthAmerica, // StVincentAndTheGrenadines QxtLocale::Australia, // Samoa QxtLocale::Europe, // SanMarino QxtLocale::Africa, // SaoTomeAndPrincipe QxtLocale::Asia, // SaudiArabia QxtLocale::Africa, // Senegal QxtLocale::Africa, // Seychelles QxtLocale::Africa, // SierraLeone QxtLocale::Asia, // Singapore QxtLocale::Europe, // Slovakia QxtLocale::Europe, // Slovenia QxtLocale::Australia, // SolomonIslands QxtLocale::Africa, // Somalia QxtLocale::Africa, // SouthAfrica QxtLocale::SouthAmerica, // SouthGeorgiaAndTheSouthSandwichIslands QxtLocale::Europe, // Spain QxtLocale::Asia, // SriLanka QxtLocale::Africa, // StHelena QxtLocale::NorthAmerica, // StPierreAndMiquelon QxtLocale::Africa, // Sudan QxtLocale::SouthAmerica, // Suriname QxtLocale::Europe, // SvalbardAndJanMayenIslands QxtLocale::Africa, // Swaziland QxtLocale::Europe, // Sweden QxtLocale::Europe, // Switzerland QxtLocale::Asia, // SyrianArabRepublic QxtLocale::Asia, // Taiwan QxtLocale::Asia, // Tajikistan QxtLocale::Africa, // Tanzania QxtLocale::Asia, // Thailand QxtLocale::Africa, // Togo QxtLocale::Australia, // Tokelau QxtLocale::Australia, // Tonga QxtLocale::NorthAmerica, // TrinidadAndTobago QxtLocale::Africa, // Tunisia QxtLocale::Europe, // Turkey QxtLocale::Asia, // Turkmenistan QxtLocale::NorthAmerica, // TurksAndCaicosIslands QxtLocale::Australia, // Tuvalu QxtLocale::Africa, // Uganda QxtLocale::Europe, // Ukraine QxtLocale::Asia, // UnitedArabEmirates QxtLocale::Europe, // UnitedKingdom QxtLocale::NorthAmerica, // UnitedStates QxtLocale::Australia, // UnitedStatesMinorOutlyingIslands QxtLocale::SouthAmerica, // Uruguay QxtLocale::Asia, // Uzbekistan QxtLocale::Australia, // Vanuatu QxtLocale::Europe, // VaticanCityState QxtLocale::SouthAmerica, // Venezuela QxtLocale::Asia, // VietNam QxtLocale::NorthAmerica, // BritishVirginIslands QxtLocale::NorthAmerica, // USVirginIslands QxtLocale::Australia, // WallisAndFutunaIslands QxtLocale::Africa, // WesternSahara QxtLocale::Asia, // Yemen QxtLocale::Europe, // Yugoslavia QxtLocale::Africa, // Zambia QxtLocale::Africa, // Zimbabwe QxtLocale::Europe, // SerbiaAndMontenegro }; #endif libqxt-0.6.2/src/core/qxtlogger.cpp000066400000000000000000001151541215241066400172710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtLogger \brief The QxtLogger class is an easy to use, easy to extend logging tool. \inmodule QxtCore \section1 Overview QxtLogger is an easy to use, easy to extend, thread-safe logging tool. It was designed to be used "out of the box". \code #include ... QxtLogger::getInstance()->debug("Hi!"); // without using the macro qxtLog->debug("Hi!"); // using the macro \endcode \sa getInstance() \section1 Usage QxtLogger is designed to work "out of the box". The Logger itself is a singleton object that manages all of the logging that is requested. It provides 8 methods to actually log content; they are listed from the most logically verbose to the most logically important: \list \o trace() \o debug() \o info() \o warning() \o error() \o critical() \o fatal() \o write() \endlist These named members only have meaning to the person who uses them. For example, you could call qxtLog->trace() from many parts of a complicated, massively recursive function to trace it's output; use qxtLog->info() to log that an event such as "Logging has started" has happened; use qxtLog->fatal() when an unhandled exception is thrown. Or, you could use qxtLog->write() for everything. Each of these members comes in two forms: the first takes up to ten QVariants (for moc compatibility), the second form takes a QList. Thus, you can invoke the info() member in the following ways: \code // Using the 10-param members. qxtLog->info(15); qxtLog->info("I am a test"); qxtLog->info(QTime::currentTime(), "something happened", 3.14); // Now with QList qxtLog->info(QList() << "test" << 15 << QTime::currentTime()); \endcode The real power behind QxtLogger comes from telling it which log levels you actually want to see. Calling qxtLog->enableAllLogLevels() can give you a lot of data if you need it. But if you only want to see warnings and errors, qxtLog->setMinimumLogLevel(WarningLevel) might be more useful. \section1 Extending The functionality of QxtLogger can be extended by creating plugins derived from QxtLoggerEngine. Logger Engines are the little workers that actually take the raw data, format it, and spit it out into meaningful forms. */ /*! \macro qxtLog \relates QxtLogger A global pointer referring to the unique logger object. It is equivalent to the pointer returned by the QxtLogger::instance() function. \sa QxtLogger::getInstance() */ /*! \fn void QxtLogger::loggerEngineAdded(const QString& engineName) This signal is emitted when an engine with \a engineName has been added. \sa loggerEngineRemoved() */ /*! \fn void QxtLogger::loggerEngineRemoved(const QString& engineName) This signal is emitted when an engine with \a engineName has been removed. \sa loggerEngineAdded() */ /*! \fn void QxtLogger::loggerEngineEnabled(const QString& engineName) This signal is emitted when an engine with \a engineName has been enabled. \sa loggerEngineDisabled() */ /*! \fn void QxtLogger::loggerEngineDisabled(const QString& engineName) This signal is emitted when an engine with \a engineName has been disabled. \sa loggerEngineEnabled() */ #include "qxtlogger.h" #include "qxtlogger_p.h" #include "qxtlogstream.h" #include "qxtbasicstdloggerengine.h" #include #include #include /******************************************************************************* Constructor for QxtLogger's private data *******************************************************************************/ QxtLoggerPrivate::QxtLoggerPrivate() { mut_lock = new QMutex(QMutex::Recursive); } /******************************************************************************* Destructor for QxtLogger's private data *******************************************************************************/ QxtLoggerPrivate::~QxtLoggerPrivate() { Q_FOREACH(QxtLoggerEngine *eng, map_logEngineMap) { if (eng) { eng->killLoggerEngine(); delete eng; } } delete mut_lock; mut_lock = NULL; } void QxtLoggerPrivate::log(QxtLogger::LogLevel level, const QList& msgList) { Q_FOREACH(QxtLoggerEngine *eng, map_logEngineMap) { if (eng && eng->isInitialized() && eng->isLoggingEnabled() && eng->isLogLevelEnabled(level)) { eng->writeFormatted(level, msgList); } } } void QxtLoggerPrivate::setQxtLoggerEngineMinimumLevel(QxtLoggerEngine *eng, QxtLogger::LogLevel level) { QMutexLocker lock(mut_lock); if (!eng) return; (QxtLogger::TraceLevel < level) ? eng->disableLogLevels(QxtLogger::TraceLevel) : eng->enableLogLevels(QxtLogger::TraceLevel); (QxtLogger::DebugLevel < level) ? eng->disableLogLevels(QxtLogger::DebugLevel) : eng->enableLogLevels(QxtLogger::DebugLevel); (QxtLogger::InfoLevel < level) ? eng->disableLogLevels(QxtLogger::InfoLevel) : eng->enableLogLevels(QxtLogger::InfoLevel); (QxtLogger::WarningLevel < level) ? eng->disableLogLevels(QxtLogger::WarningLevel) : eng->enableLogLevels(QxtLogger::WarningLevel); (QxtLogger::ErrorLevel < level) ? eng->disableLogLevels(QxtLogger::ErrorLevel) : eng->enableLogLevels(QxtLogger::ErrorLevel); (QxtLogger::CriticalLevel < level) ? eng->disableLogLevels(QxtLogger::CriticalLevel) : eng->enableLogLevels(QxtLogger::CriticalLevel); (QxtLogger::FatalLevel < level) ? eng->disableLogLevels(QxtLogger::FatalLevel) : eng->enableLogLevels(QxtLogger::FatalLevel); (QxtLogger::WriteLevel < level) ? eng->disableLogLevels(QxtLogger::WriteLevel) : eng->enableLogLevels(QxtLogger::WriteLevel); } /*! \brief Returns the named Engine. */ QxtLoggerEngine *QxtLogger::engine(const QString &engineName) { if (! isLoggerEngine(engineName)) return 0; else return qxt_d().map_logEngineMap.value(engineName); } /*! \brief Opens a stream to write a message to all Engines with the InfoLevel set. The parameterless logging functions return a QxtLogStream for use similar to qDebug(). \code qxtLog->info() << "informational message"; \endcode */ QxtLogStream QxtLogger::info() { return stream(QxtLogger::InfoLevel); } /*! \brief Opens a stream to write a message to all Engines with the TraceLevel set. The parameterless logging functions return a QxtLogStream for use similar to qDebug(). \code qxtLog->trace() << "detailed trace message"; \endcode */ QxtLogStream QxtLogger::trace() { return stream(QxtLogger::TraceLevel); } /*! \brief Opens a stream to write a message to all Engines with the ErrorLevel set. The parameterless logging functions return a QxtLogStream for use similar to qDebug(). \code qxtLog->error() << "error message"; \endcode */ QxtLogStream QxtLogger::error() { return stream(QxtLogger::ErrorLevel); } /*! \brief Opens a stream to write a message to all Engines with the WarningLevel set. The parameterless logging functions return a QxtLogStream for use similar to qDebug(). \code qxtLog->warning() << "warning message"; \endcode */ QxtLogStream QxtLogger::warning() { return stream(QxtLogger::WarningLevel); } /*! \brief Opens a stream to write a message to all Engines with the DebugLevel set. The parameterless logging functions return a QxtLogStream for use similar to qDebug(). \code qxtLog->debug() << "debugging log message"; \endcode */ QxtLogStream QxtLogger::debug() { return stream(QxtLogger::DebugLevel); } /*! \brief Opens a stream to write a message to all Engines with the CriticalLevel set. The parameterless logging functions return a QxtLogStream for use similar to qDebug(). \code qxtLog->critical() << "critical error message"; \endcode */ QxtLogStream QxtLogger::critical() { return stream(QxtLogger::CriticalLevel); } /*! \brief Opens a stream to write a message to all Engines with the FatalLevel set. The parameterless logging functions return a QxtLogStream for use similar to qDebug(). \code qxtLog->fatal() << "fatal error message"; \endcode */ QxtLogStream QxtLogger::fatal() { return stream(QxtLogger::FatalLevel); } /*! \brief Opens a stream to write a message to all Engines with the WriteLevel set. The parameterless logging functions return a QxtLogStream for use similar to qDebug(). \code qxtLog->write() << "log message"; \endcode */ QxtLogStream QxtLogger::write() { return stream(QxtLogger::WriteLevel); } /*! \brief Writes a message to all Engines with the InfoLevel set. The 10-parameter logging functions are designed to be used with Qt's Signals and Slots, since moc currently only accepts functions with up to 10 parameters. They can take any value that QVariant can take as an argument. */ void QxtLogger::info(const QVariant &message, const QVariant &msg1, const QVariant &msg2, const QVariant &msg3, const QVariant &msg4, const QVariant &msg5, const QVariant &msg6, const QVariant &msg7, const QVariant &msg8 , const QVariant &msg9) { QMutexLocker lock(qxt_d().mut_lock); QList args; args.push_back(message); if (!msg1.isNull()) args.push_back(msg1); if (!msg2.isNull()) args.push_back(msg2); if (!msg3.isNull()) args.push_back(msg3); if (!msg4.isNull()) args.push_back(msg4); if (!msg5.isNull()) args.push_back(msg5); if (!msg6.isNull()) args.push_back(msg6); if (!msg7.isNull()) args.push_back(msg7); if (!msg8.isNull()) args.push_back(msg8); if (!msg9.isNull()) args.push_back(msg9); info(args); } /*! \brief Writes a message to all Engines with the TraceLevel set. The 10-parameter logging functions are designed to be used with Qt's Signals and Slots, since moc currently only accepts functions with up to 10 parameters. They can take any value that QVariant can take as an argument. */ void QxtLogger::trace(const QVariant &message, const QVariant &msg1 , const QVariant &msg2 , const QVariant &msg3 , const QVariant &msg4 , const QVariant &msg5 , const QVariant &msg6 , const QVariant &msg7 , const QVariant &msg8 , const QVariant &msg9) { QMutexLocker lock(qxt_d().mut_lock); QList args; args.push_back(message); if (!msg1.isNull()) args.push_back(msg1); if (!msg2.isNull()) args.push_back(msg2); if (!msg3.isNull()) args.push_back(msg3); if (!msg4.isNull()) args.push_back(msg4); if (!msg5.isNull()) args.push_back(msg5); if (!msg6.isNull()) args.push_back(msg6); if (!msg7.isNull()) args.push_back(msg7); if (!msg8.isNull()) args.push_back(msg8); if (!msg9.isNull()) args.push_back(msg9); trace(args); } /*! \brief Writes a message to all Engines with the WarningLevel set. The 10-parameter logging functions are designed to be used with Qt's Signals and Slots, since moc currently only accepts functions with up to 10 parameters. They can take any value that QVariant can take as an argument. */ void QxtLogger::warning(const QVariant &message, const QVariant &msg1 , const QVariant &msg2 , const QVariant &msg3 , const QVariant &msg4 , const QVariant &msg5 , const QVariant &msg6 , const QVariant &msg7 , const QVariant &msg8 , const QVariant &msg9) { QMutexLocker lock(qxt_d().mut_lock); QList args; args.push_back(message); if (!msg1.isNull()) args.push_back(msg1); if (!msg2.isNull()) args.push_back(msg2); if (!msg3.isNull()) args.push_back(msg3); if (!msg4.isNull()) args.push_back(msg4); if (!msg5.isNull()) args.push_back(msg5); if (!msg6.isNull()) args.push_back(msg6); if (!msg7.isNull()) args.push_back(msg7); if (!msg8.isNull()) args.push_back(msg8); if (!msg9.isNull()) args.push_back(msg9); warning(args); } /*! \brief Writes a message to all Engines with the ErrorLevel set. The 10-parameter logging functions are designed to be used with Qt's Signals and Slots, since moc currently only accepts functions with up to 10 parameters. They can take any value that QVariant can take as an argument. */ void QxtLogger::error(const QVariant &message, const QVariant &msg1 , const QVariant &msg2 , const QVariant &msg3 , const QVariant &msg4 , const QVariant &msg5 , const QVariant &msg6 , const QVariant &msg7 , const QVariant &msg8 , const QVariant &msg9) { QMutexLocker lock(qxt_d().mut_lock); QList args; args.push_back(message); if (!msg1.isNull()) args.push_back(msg1); if (!msg2.isNull()) args.push_back(msg2); if (!msg3.isNull()) args.push_back(msg3); if (!msg4.isNull()) args.push_back(msg4); if (!msg5.isNull()) args.push_back(msg5); if (!msg6.isNull()) args.push_back(msg6); if (!msg7.isNull()) args.push_back(msg7); if (!msg8.isNull()) args.push_back(msg8); if (!msg9.isNull()) args.push_back(msg9); error(args); } /*! \brief Writes a message to all Engines with the DebugLevel set. The 10-parameter logging functions are designed to be used with Qt's Signals and Slots, since moc currently only accepts functions with up to 10 parameters. They can take any value that QVariant can take as an argument. */ void QxtLogger::debug(const QVariant &message, const QVariant &msg1 , const QVariant &msg2 , const QVariant &msg3 , const QVariant &msg4 , const QVariant &msg5 , const QVariant &msg6 , const QVariant &msg7 , const QVariant &msg8 , const QVariant &msg9) { QMutexLocker lock(qxt_d().mut_lock); QList args; args.push_back(message); if (!msg1.isNull()) args.push_back(msg1); if (!msg2.isNull()) args.push_back(msg2); if (!msg3.isNull()) args.push_back(msg3); if (!msg4.isNull()) args.push_back(msg4); if (!msg5.isNull()) args.push_back(msg5); if (!msg6.isNull()) args.push_back(msg6); if (!msg7.isNull()) args.push_back(msg7); if (!msg8.isNull()) args.push_back(msg8); if (!msg9.isNull()) args.push_back(msg9); debug(args); } /*! \brief Writes a message to all Engines with the WriteLevel set. The 10-parameter logging functions are designed to be used with Qt's Signals and Slots, since moc currently only accepts functions with up to 10 parameters. They can take any value that QVariant can take as an argument. */ void QxtLogger::write(const QVariant &message, const QVariant &msg1 , const QVariant &msg2, const QVariant &msg3 , const QVariant &msg4 , const QVariant &msg5 , const QVariant &msg6 , const QVariant &msg7 , const QVariant &msg8 , const QVariant &msg9) { QMutexLocker lock(qxt_d().mut_lock); QList args; args.push_back(message); if (!msg1.isNull()) args.push_back(msg1); if (!msg2.isNull()) args.push_back(msg2); if (!msg3.isNull()) args.push_back(msg3); if (!msg4.isNull()) args.push_back(msg4); if (!msg5.isNull()) args.push_back(msg5); if (!msg6.isNull()) args.push_back(msg6); if (!msg7.isNull()) args.push_back(msg7); if (!msg8.isNull()) args.push_back(msg8); if (!msg9.isNull()) args.push_back(msg9); write(args); } /*! \brief Writes a message to all Engines with the CriticalLevel set. The 10-parameter logging functions are designed to be used with Qt's Signals and Slots, since moc currently only accepts functions with up to 10 parameters. They can take any value that QVariant can take as an argument. */ void QxtLogger::critical(const QVariant &message, const QVariant &msg1 , const QVariant &msg2 , const QVariant &msg3 , const QVariant &msg4 , const QVariant &msg5 , const QVariant &msg6 , const QVariant &msg7 , const QVariant &msg8 , const QVariant &msg9) { QMutexLocker lock(qxt_d().mut_lock); QList args; args.push_back(message); if (!msg1.isNull()) args.push_back(msg1); if (!msg2.isNull()) args.push_back(msg2); if (!msg3.isNull()) args.push_back(msg3); if (!msg4.isNull()) args.push_back(msg4); if (!msg5.isNull()) args.push_back(msg5); if (!msg6.isNull()) args.push_back(msg6); if (!msg7.isNull()) args.push_back(msg7); if (!msg8.isNull()) args.push_back(msg8); if (!msg9.isNull()) args.push_back(msg9); critical(args); } /*! \brief Writes a message to all Engines with the FatalLevel set. The 10-parameter logging functions are designed to be used with Qt's Signals and Slots, since moc currently only accepts functions with up to 10 parameters. They can take any value that QVariant can take as an argument. */ void QxtLogger::fatal(const QVariant &message, const QVariant &msg1 , const QVariant &msg2 , const QVariant &msg3 , const QVariant &msg4 , const QVariant &msg5 , const QVariant &msg6 , const QVariant &msg7 , const QVariant &msg8 , const QVariant &msg9) { QMutexLocker lock(qxt_d().mut_lock); QList args; args.push_back(message); if (!msg1.isNull()) args.push_back(msg1); if (!msg2.isNull()) args.push_back(msg2); if (!msg3.isNull()) args.push_back(msg3); if (!msg4.isNull()) args.push_back(msg4); if (!msg5.isNull()) args.push_back(msg5); if (!msg6.isNull()) args.push_back(msg6); if (!msg7.isNull()) args.push_back(msg7); if (!msg8.isNull()) args.push_back(msg8); if (!msg9.isNull()) args.push_back(msg9); fatal(args); } /*! \brief Writes a message to all Engines with the InfoLevel set. The 1-parameter logging messages can take any number of arguments in the form of a QList, or QList. */ void QxtLogger::info(const QList &args) { log(QxtLogger::InfoLevel, args); } /*! \brief Writes a message to all Engines with the TraceLevel set. The 1-parameter logging messages can take any number of arguments in the form of a QList, or QList. */ void QxtLogger::trace(const QList &args) { log(QxtLogger::TraceLevel, args); } /*! \brief Writes a message to all Engines with the WarningLevel set. The 1-parameter logging messages can take any number of arguments in the form of a QList, or QList. */ void QxtLogger::warning(const QList &args) { log(QxtLogger::WarningLevel, args); } /*! \brief Writes a message to all Engines with the ErrorLevel set. The 1-parameter logging messages can take any number of arguments in the form of a QList, or QList. */ void QxtLogger::error(const QList &args) { log(QxtLogger::ErrorLevel, args); } /*! \brief Writes a message to all Engines with the DebugLevel set. The 1-parameter logging messages can take any number of arguments in the form of a QList, or QList. */ void QxtLogger::debug(const QList &args) { log(QxtLogger::DebugLevel, args); } /*! \brief Writes a message to all Engines with the CriticalLevel set. The 1-parameter logging messages can take any number of arguments in the form of a QList, or QList. */ void QxtLogger::critical(const QList &args) { log(QxtLogger::CriticalLevel, args); } /*! \brief Writes a message to all Engines with the FatalLevel set. The 1-parameter logging messages can take any number of arguments in the form of a QList, or QList. */ void QxtLogger::fatal(const QList &args) { log(QxtLogger::FatalLevel, args); } /*! \brief Writes a message to all Engines with the WriteLevel set. The 1-parameter logging messages can take any number of arguments in the form of a QList, or QList. */ void QxtLogger::write(const QList &args) { log(QxtLogger::WriteLevel, args); } /*! A Generic Logging Function that takes a LogLevel and a QList of messages This function is provided for convenience. */ void QxtLogger::log(LogLevel level, const QList& args) { /* QMutexLocker lock(qxt_d().mut_lock); qxt_d().log(level, msgList); */ QMetaObject::invokeMethod(&qxt_d(), "log", Qt::AutoConnection, Q_ARG(QxtLogger::LogLevel, level), Q_ARG(QList, args)); } /******************************************************************************* Message Handler for qdebug, qerror, qwarning, etc... When QxtLogger is enabled as a message handler for Qt, this function redirects message calls like qdebug, qwarning, qfatal. \sa QxtLogger::installAsMessageHandler \sa QxtLogger::removeAsMessageHandler *******************************************************************************/ void QxtLoggerMessageHandler(QtMsgType type, const char *msg) { switch (type) { case QtDebugMsg: QxtLogger::getInstance()->debug(msg, "qdebug"); break; case QtWarningMsg: QxtLogger::getInstance()->warning(msg, "qwarning"); break; case QtCriticalMsg: QxtLogger::getInstance()->critical(msg, "qcritical"); break; case QtFatalMsg: QxtLogger::getInstance()->fatal(msg, "qfatal"); abort(); } } /*! \brief Installs QxtLogger as Qt's message handler. This will make Qt macros use QxtLogger instead of the default mechanism: \list \o qDebug() \o qWarning() \o qCritical() \o qFatal() will call abort() and terminate your application. \endlist */ void QxtLogger::installAsMessageHandler() { QMutexLocker lock(qxt_d().mut_lock); qInstallMsgHandler(QxtLoggerMessageHandler); } /*! \brief Tells Qt to use it's own message handling again. */ void QxtLogger::removeAsMessageHandler() { QMutexLocker lock(qxt_d().mut_lock); qInstallMsgHandler(0); } /***************************************************************************** Constructor Private, since QxtLogger is a singleton. *****************************************************************************/ QxtLogger::QxtLogger() { QXT_INIT_PRIVATE(QxtLogger); qRegisterMetaType(); qRegisterMetaType(); addLoggerEngine("DEFAULT", new QxtBasicSTDLoggerEngine); setMinimumLevel("DEFAULT", QxtLogger::InfoLevel); } /***************************************************************************//*! Destructor. The Destructor for QxtLogger iterates through all the currently installed QxtLoggerEngines, calls their killLoggerEngine functions through QxtLoggerEngine::killLoggerEngine(), and then deletes them from the map. *******************************************************************************/ QxtLogger::~QxtLogger() { // implicit destruction only } /*! \brief Returns a pointer to the instance of the Logger. QxtLogger is implemented as a singleton, a single object, that manages all of the logging done in an application. The easiest way to use it is by calling the qxtLog macro: \code #include ... qxtLog->info("I can log things!"); \endcode qxtLog expands to QxtLogger::getInstance, which returns a pointer to the logger. QxtLogger manages it's own memory, so please remember the second rule of pointers: don't delete it unless you instantiated it yourself. \code delete qxtLog; // Will horribly crash your app, and possibly your system \endcode */ QxtLogger *QxtLogger::getInstance() { static QxtLogger objectInstance; return &objectInstance; } /*! \brief Returns a QString of the given LogLevel. This function is provided for convenience. */ QString QxtLogger::logLevelToString(LogLevel level) { switch (level) { case TraceLevel: return "TraceLevel"; case DebugLevel: return "DebugLevel"; case InfoLevel: return "InfoLevel"; case WarningLevel: return "WarningLevel"; case ErrorLevel: return "ErrorLevel"; case CriticalLevel: return "CriticalLevel"; case FatalLevel: return "FatalLevel"; case WriteLevel: return "WriteLevel"; case AllLevels: return "AllLevels"; default: return "NoLevels"; } } /*! \brief Returns a LogLevel for the given string, or QxtLogger::NoLevels if invalid. This function is provided for convenience. */ QxtLogger::LogLevel QxtLogger::stringToLogLevel(const QString& level) { if (level.toLower() == "alllevels") return QxtLogger::AllLevels; else if (level.toLower() == "writelevel") return QxtLogger::WriteLevel; else if (level.toLower() == "fatallevel") return QxtLogger::FatalLevel; else if (level.toLower() == "criticallevel") return QxtLogger::CriticalLevel; else if (level.toLower() == "errorlevel") return QxtLogger::ErrorLevel; else if (level.toLower() == "warnlevel") return QxtLogger::WarningLevel; else if (level.toLower() == "infolevel") return QxtLogger::InfoLevel; else if (level.toLower() == "debuglevel") return QxtLogger::DebugLevel; else if (level.toLower() == "tracelevel") return QxtLogger::TraceLevel; else return QxtLogger::NoLevels; } /*! \brief Enables the given LogLevels across all Engines. \code qxtLog->enableLogLevels(QxtLogger::NoLevels); qxtLog->write("I don't do anything!"); qxtLog->enableLogLevels(QxtLogger::AllLevels); qxtLog->write("Hi there!"); \endcode \a levels A bitmask of LogLevels */ void QxtLogger::enableLogLevels(LogLevels levels) { QMutexLocker lock(qxt_d().mut_lock); if (qxt_d().map_logEngineMap.empty()) return; Q_FOREACH(QxtLoggerEngine *eng, qxt_d().map_logEngineMap) { if (eng) { eng->enableLogLevels(levels); } } } /*! \brief Returns a reference to a refcounted stream. This is still in its early phases and is in dire need of testing and debugging. \code QxtLogger::stream(QxtLogger::WriteLevel) << "This should write stuff" << 1.5 << QString(); \endcode */ QxtLogStream QxtLogger::stream(LogLevel level) { return QxtLogStream(this, level, QList()); } /*! \brief Enables the given LogLevels on a named Engine. This will use the given engine name to tell a loaded QxtLoggerEngine what LogLevels it should enable. \code qxtLog->addLoggerEngine("test", "libTestLogger"); qxtLog->enableLogLevels("test", QxtLoger::AllLevels); qxtLog->write("You can see me through your 'test' logger now!"); \endcode \a engineName The name of a QxtLoggerEngine. \a levels A LogLevel or LogLevels to enable. \sa addLoggerEngine() *******************************************************************************/ void QxtLogger::enableLogLevels(const QString &engineName, LogLevels levels) { QMutexLocker lock(qxt_d().mut_lock); if (qxt_d().map_logEngineMap.contains(engineName)) { if (qxt_d().map_logEngineMap.value(engineName)) { qxt_d().map_logEngineMap.value(engineName)->enableLogLevels(levels); } } } /*! \brief Turns on all log levels for a named engine. This is a function provided for convenience, and is equivalent to calling: \code qxtLog->enableLogLevels("test", QxtLogger::AllLevels); \endcode */ void QxtLogger::enableAllLogLevels(const QString &engineName) { enableLogLevels(engineName, QxtLogger::AllLevels); } /*! \brief Turns on all log levels for all engines. This is a function provided for convenience, and is equivalent to calling: \code qxtLog->enableLogLevels(QxtLogger::AllLevels); \endcode */ void QxtLogger::enableAllLogLevels() { enableLogLevels(QxtLogger::AllLevels); } /*! \brief Enables a named engine if it is currently disabled. \a engineName the name of a QxtLoggerEngine. */ void QxtLogger::enableLoggerEngine(const QString &engineName) { QMutexLocker lock(qxt_d().mut_lock); if (qxt_d().map_logEngineMap.contains(engineName)) { if (qxt_d().map_logEngineMap.value(engineName)) { qxt_d().map_logEngineMap.value(engineName)->enableLogging(); emit loggerEngineEnabled(engineName); } } } /*! \brief Unflags the given LogLevels across all Engines. Disables the given LogLevel across all QxtLoggersEngines. Note that some \a levels A LogLevel or LogLevels to disable. */ void QxtLogger::disableLogLevels(LogLevels levels) { QMutexLocker lock(qxt_d().mut_lock); if (qxt_d().map_logEngineMap.empty()) return; Q_FOREACH(QxtLoggerEngine *eng, qxt_d().map_logEngineMap) { if (eng) { eng->disableLogLevels(levels); } } } /*! \brief Disables the named Engine. Disables the the named QxtLoggerEngine if it exists. \a engineName The name of a log Engine to disable. */ void QxtLogger::disableLoggerEngine(const QString &engineName) { QMutexLocker lock(qxt_d().mut_lock); if (qxt_d().map_logEngineMap.contains(engineName)) { if (qxt_d().map_logEngineMap.value(engineName)) { qxt_d().map_logEngineMap.value(engineName)->disableLogging(); emit loggerEngineDisabled(engineName); } } } /*! \brief Sets the minimumlog level for all Engines, as well as the levels above it. \a level The single LogLevel to set as minimum. */ void QxtLogger::setMinimumLevel(LogLevel level) { QMutexLocker lock(qxt_d().mut_lock); Q_FOREACH(QxtLoggerEngine *eng, qxt_d().map_logEngineMap) { if (eng) { qxt_d().setQxtLoggerEngineMinimumLevel(eng, level); } } } /*! \brief Sets the minimumlog level for the named Engine, as well as the levels above it. \a engineName The name of a QxtLoggerEngine. \a level The single LogLevel to set as minimum. */ void QxtLogger::setMinimumLevel(const QString &engineName, LogLevel level) { QMutexLocker lock(qxt_d().mut_lock); if (qxt_d().map_logEngineMap.contains(engineName)) { if (qxt_d().map_logEngineMap.value(engineName)) { qxt_d().setQxtLoggerEngineMinimumLevel(qxt_d().map_logEngineMap.value(engineName), level); } } } /*! \brief Calls QxtLoggerEngine::initLoggerEngine() for the named Engine. Some QxtLoggerEngine plugins might require additional initialization. Check the documentation for your plugin. Most basic plugins will not require special tasks. \a engineName The name of a QxtLoggerEngine. */ void QxtLogger::initLoggerEngine(const QString &engineName) { QMutexLocker lock(qxt_d().mut_lock); if (qxt_d().map_logEngineMap.contains(engineName)) { if (qxt_d().map_logEngineMap.value(engineName)) { qxt_d().map_logEngineMap.value(engineName)->initLoggerEngine(); } } } /*! \brief Calls QxtLoggerEngine::killLoggerEngine() for the named Engine. Some QxtLoggerEngine plugins might require special cleanup before destruction. Check the documentation for your plugin. Most basic plugins will not require this. \a engineName The name of a QxtLoggerEngine. */ void QxtLogger::killLoggerEngine(const QString &engineName) { QMutexLocker lock(qxt_d().mut_lock); if (qxt_d().map_logEngineMap.contains(engineName)) { if (qxt_d().map_logEngineMap.value(engineName)) { qxt_d().map_logEngineMap.value(engineName)->killLoggerEngine(); } } } /*! \brief Checks if the named Engine has the given LogLevel enabled. \a engineName The name of a QxtLoggerEngine to query \a level A LogLevel or LogLevels to disable. Returns true or false. */ bool QxtLogger::isLogLevelEnabled(const QString &engineName, LogLevel level) const { QMutexLocker lock(qxt_d().mut_lock); if (qxt_d().map_logEngineMap.contains(engineName)) { return qxt_d().map_logEngineMap.value(engineName)->isLogLevelEnabled(level); } else return false; } /*! \brief Disables the given LogLevel across the named QxtLoggersEngines. \a engineName The name of a QxtLoggerEngine. \a level A LogLevel or LogLevels to disable. */ void QxtLogger::disableLogLevels(const QString &engineName, LogLevels levels) { QMutexLocker lock(qxt_d().mut_lock); if (qxt_d().map_logEngineMap.contains(engineName)) { if (qxt_d().map_logEngineMap.value(engineName)) { qxt_d().map_logEngineMap.value(engineName)->disableLogLevels(levels); } } } /*! \brief Disables all log levels for the named Engine. \a engineName The name of an Engine. */ void QxtLogger::disableAllLogLevels(const QString &engineName) { disableLogLevels(engineName, QxtLogger::AllLevels); } /*! \brief Disables all log levels for all named Engines. */ void QxtLogger::disableAllLogLevels() { disableLogLevels(QxtLogger::AllLevels); } /*! \brief Gives QxtLogger an already-instantiated QxtLoggerEngine to use. addLoggerEngine inserts a subclass of QxtLoggerEngine for QxtLogger to manage. QxtLogger takes ownership of the engine and will manage memory on its own. \code #include ... class MyLoggerEngine : public QxtLoggerEngine; ... qxtLog->addLoggerEngine("my engine", new MyLoggerEngine); \endcode \sa QxtLoggerEngine */ void QxtLogger::addLoggerEngine(const QString &engineName, QxtLoggerEngine *engine) { QMutexLocker lock(qxt_d().mut_lock); if (!qxt_d().map_logEngineMap.contains(engineName) && engine) { qxt_d().map_logEngineMap.insert(engineName, engine); emit loggerEngineAdded(engineName); } } /* \brief Gives QxtLogger an already-instantiated QLibrary. This is an overloaded functionand not the preferred method of adding Engines. It is useful to load plugins that are not in the applications Path. \code QLibrary *lib = new QLibrary("/path/to/plugin"); qxtLog->addLogger("my engine", lib); \endcode void QxtLogger::addLoggerEngine(const QString &engineName, QLibrary *engineLib) { QMutexLocker lock(qxt_d().mut_lock); typedef QxtLoggerEngine* (*LibInstance)(); LibInstance instance = (LibInstance)engineLib->resolve("getInstance"); qWarning() << engineLib->errorString(); if (!instance) return; else if (!qxt_d().map_logEngineMap.contains(engineName) && engineLib) { qxt_d().map_logEngineMap.insert(engineName, instance()); emit loggerEngineAdded(engineName); } } \brief Loads an Engine from a plugin in the current path. \code qxtLog->addLogger("my lib", "libQxtSomeKindOfLoggerEngine"); \endcode \a engineName The name to give this QxtLoggerEngine. \a libName The name of the library to load. void QxtLogger::addLoggerEngine(const QString &engineName, const QString &libName) { QLibrary engineLib(libName); addLoggerEngine(engineName, &engineLib); } */ /*! \brief Remove the named Engine from use. */ void QxtLogger::removeLoggerEngine(const QString &engineName) { QMutexLocker lock(qxt_d().mut_lock); QxtLoggerEngine* eng = takeLoggerEngine(engineName); if (!eng) return; eng->killLoggerEngine(); delete eng; } /*! \brief Remove the Engine from use. */ void QxtLogger::removeLoggerEngine(QxtLoggerEngine *engine) { QMutexLocker lock(qxt_d().mut_lock); Q_FOREACH(const QString& i, this->qxt_d().map_logEngineMap.keys(engine)) { takeLoggerEngine(i); // return value ignored } } /*! \brief Take the named Engine. */ QxtLoggerEngine *QxtLogger::takeLoggerEngine(const QString &engineName) { QMutexLocker lock(qxt_d().mut_lock); QxtLoggerEngine *eng = qxt_d().map_logEngineMap.take(engineName); if (!eng) return NULL; emit loggerEngineRemoved(engineName); return eng; } /*! \brief Retuns a QStringList containing the names of all loaded Engines being managed by QxtLogger. Returns QStringList engine names. */ QStringList QxtLogger::allLoggerEngines() const { QMutexLocker lock(qxt_d().mut_lock); return qxt_d().map_logEngineMap.keys(); } /*! \brief Retuns a QStringList containing the names of all loaded Engines that are currently enabled. Returns QStringList engine names. */ QStringList QxtLogger::allEnabledLoggerEngines() const { QMutexLocker lock(qxt_d().mut_lock); QStringList engineNames = qxt_d().map_logEngineMap.keys(); QStringList result; Q_FOREACH(const QString& name, engineNames) { if (qxt_d().map_logEngineMap.value(name)->isLoggingEnabled()) result.append(name); } return result; } /*! \brief Retuns a QStringList containing the names of all loaded Engines that have currently certain log level enabled. Returns QStringList engine names. */ QStringList QxtLogger::allEnabledLoggerEngines(LogLevel level) const { QMutexLocker lock(qxt_d().mut_lock); QStringList engineNames = qxt_d().map_logEngineMap.keys(); QStringList result; Q_FOREACH(const QString& name, engineNames) { QxtLoggerEngine* engine = qxt_d().map_logEngineMap.value(name); if (engine->isLoggingEnabled() && engine->isLogLevelEnabled(level)) { result.append(name); } } return result; } /*! \brief Retuns a QStringList containing the names of all loaded Engines that are currently disabled. Returns QStringList engine names. */ QStringList QxtLogger::allDisabledLoggerEngines() const { QMutexLocker lock(qxt_d().mut_lock); QStringList sl_engineNames = qxt_d().map_logEngineMap.keys(); QStringList result; Q_FOREACH(const QString& name, sl_engineNames) { if (!qxt_d().map_logEngineMap.value(name)->isLoggingEnabled()) result.append(name); } return result; } /*! \brief Checks if the given string names a currently loaded Engine. Returns True or false. */ bool QxtLogger::isLoggerEngine(const QString &engineName) const { QMutexLocker lock(qxt_d().mut_lock); return qxt_d().map_logEngineMap.contains(engineName); } /*! \brief Checks if the named engine is currently enabled. Returns True or false */ bool QxtLogger::isLoggerEngineEnabled(const QString &engineName) const { QMutexLocker lock(qxt_d().mut_lock); return (qxt_d().map_logEngineMap.contains(engineName) && qxt_d().map_logEngineMap.value(engineName)->isLoggingEnabled()); } libqxt-0.6.2/src/core/qxtlogger.h000066400000000000000000000245171215241066400167400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLOGGER_H #define QXTLOGGER_H #include "qxtglobal.h" #include #include #include #include #include class QxtLoggerPrivate; class QxtLogStream; class QxtLoggerEngine; void QxtLoggerMessageHandler(QtMsgType type, const char *msg); class QXT_CORE_EXPORT QxtLogger : public QObject { Q_OBJECT QXT_DECLARE_PRIVATE(QxtLogger) // Constructor & Destructor. Made private as QxtLogger is implemented as a singleton. QxtLogger(); ~QxtLogger(); public: /******************************************************************************* Defines for a bitmask to enable/disable logging levels. Arranged in levels from (assumed) most verbose to most important. *******************************************************************************/ enum LogLevel { NoLevels = 0, /**< No Levels enabled */ TraceLevel = 1 << 0, /**< The most verbose, flags trace() messages to be logged */ DebugLevel = 1 << 1, /**< Flags debug() messages to be logged */ InfoLevel = 1 << 2, /**< Flags info() messages to be logged */ WarningLevel = 1 << 3, /**< Flags warning() messages to be logged */ ErrorLevel = 1 << 4, /**< Flags error() messages to be logged */ CriticalLevel = 1 << 5, /**< Flags critical() messages to be logged */ FatalLevel = 1 << 6, /**< Flags fatal() messages to be logged */ WriteLevel = 1 << 7, /**< The most important, flags write() messages to be logged */ AllLevels = TraceLevel | DebugLevel | InfoLevel | WarningLevel | ErrorLevel | CriticalLevel | FatalLevel | WriteLevel /**< Enables all log levels */ }; Q_DECLARE_FLAGS(LogLevels, LogLevel) /* Sone useful things */ static QString logLevelToString(LogLevel level); static QxtLogger::LogLevel stringToLogLevel(const QString& level); static QxtLogger* getInstance(); void initLoggerEngine(const QString& engineName); void killLoggerEngine(const QString& engineName); // Functions to install or remove QxtLogger as a handler for qDebug, qFatal, etc... void installAsMessageHandler(); void removeAsMessageHandler(); //Functions for adding and removing loggers. void addLoggerEngine(const QString& engineName, QxtLoggerEngine *engine); void removeLoggerEngine(const QString& engineName); void removeLoggerEngine(QxtLoggerEngine *engine); QxtLoggerEngine* takeLoggerEngine(const QString& engineName); QxtLoggerEngine* engine(const QString& engineName); // Functions for checking loggers. QStringList allLoggerEngines() const; QStringList allEnabledLoggerEngines() const; QStringList allEnabledLoggerEngines(LogLevel level) const; QStringList allDisabledLoggerEngines() const; bool isLogLevelEnabled(const QString& engineName, LogLevel level) const; bool isLoggerEngine(const QString& engineName) const; bool isLoggerEngineEnabled(const QString& engineName) const; /******************************************************************************* Streaming! *******************************************************************************/ QxtLogStream stream(LogLevel level); QxtLogStream trace(); QxtLogStream debug(); QxtLogStream info(); QxtLogStream warning(); QxtLogStream error(); QxtLogStream critical(); QxtLogStream fatal(); QxtLogStream write(); /******************************************************************************* Log Level enable and disable: The 1-param functions enable/disable that level on ALL log engines. The 2-param functions enable/disable that on a named logger. *******************************************************************************/ void enableLogLevels(LogLevels levels); void enableLogLevels(const QString& engineName, LogLevels levels); void enableAllLogLevels(); void enableAllLogLevels(const QString& engineName); void enableLoggerEngine(const QString& engineName); void disableLogLevels(LogLevels levels); void disableLogLevels(const QString& engineName, LogLevels levels); void disableAllLogLevels(); void disableAllLogLevels(const QString& engineName); void disableLoggerEngine(const QString& engineName); void setMinimumLevel(LogLevel level); void setMinimumLevel(const QString& engineName, LogLevel level); public Q_SLOTS: /******************************************************************************* Logging Functions: what the QxtLogger is all about. *******************************************************************************/ void info(const QVariant& message, const QVariant& msg1 = QVariant(), const QVariant& msg2 = QVariant(), const QVariant& msg3 = QVariant(), const QVariant& msg4 = QVariant(), const QVariant& msg5 = QVariant(), const QVariant& msg6 = QVariant(), const QVariant& msg7 = QVariant(), const QVariant& msg8 = QVariant(), const QVariant& msg9 = QVariant()); void trace(const QVariant& message, const QVariant& msg1 = QVariant(), const QVariant& msg2 = QVariant(), const QVariant& msg3 = QVariant(), const QVariant& msg4 = QVariant(), const QVariant& msg5 = QVariant(), const QVariant& msg6 = QVariant(), const QVariant& msg7 = QVariant(), const QVariant& msg8 = QVariant(), const QVariant& msg9 = QVariant()); void warning(const QVariant& message, const QVariant& msg1 = QVariant(), const QVariant& msg2 = QVariant(), const QVariant& msg3 = QVariant(), const QVariant& msg4 = QVariant(), const QVariant& msg5 = QVariant(), const QVariant& msg6 = QVariant(), const QVariant& msg7 = QVariant(), const QVariant& msg8 = QVariant(), const QVariant& msg9 = QVariant()); void error(const QVariant& message, const QVariant& msg1 = QVariant(), const QVariant& msg2 = QVariant(), const QVariant& msg3 = QVariant(), const QVariant& msg4 = QVariant(), const QVariant& msg5 = QVariant(), const QVariant& msg6 = QVariant(), const QVariant& msg7 = QVariant(), const QVariant& msg8 = QVariant(), const QVariant& msg9 = QVariant()); void debug(const QVariant& message, const QVariant& msg1 = QVariant(), const QVariant& msg2 = QVariant(), const QVariant& msg3 = QVariant(), const QVariant& msg4 = QVariant(), const QVariant& msg5 = QVariant(), const QVariant& msg6 = QVariant(), const QVariant& msg7 = QVariant(), const QVariant& msg8 = QVariant(), const QVariant& msg9 = QVariant()); void critical(const QVariant& message, const QVariant& msg1 = QVariant(), const QVariant& msg2 = QVariant(), const QVariant& msg3 = QVariant(), const QVariant& msg4 = QVariant(), const QVariant& msg5 = QVariant(), const QVariant& msg6 = QVariant(), const QVariant& msg7 = QVariant(), const QVariant& msg8 = QVariant(), const QVariant& msg9 = QVariant()); void fatal(const QVariant& message, const QVariant& msg1 = QVariant(), const QVariant& msg2 = QVariant(), const QVariant& msg3 = QVariant(), const QVariant& msg4 = QVariant(), const QVariant& msg5 = QVariant(), const QVariant& msg6 = QVariant(), const QVariant& msg7 = QVariant(), const QVariant& msg8 = QVariant(), const QVariant& msg9 = QVariant()); void write(const QVariant& message, const QVariant& msg1 = QVariant(), const QVariant& msg2 = QVariant(), const QVariant& msg3 = QVariant(), const QVariant& msg4 = QVariant(), const QVariant& msg5 = QVariant(), const QVariant& msg6 = QVariant(), const QVariant& msg7 = QVariant(), const QVariant& msg8 = QVariant(), const QVariant& msg9 = QVariant()); /******************************************************************************* Logging Functions in QList form. *******************************************************************************/ void info(const QList& args); void trace(const QList& args); void warning(const QList& args); void error(const QList& args); void debug(const QList& args); void critical(const QList& args); void fatal(const QList& args); void write(const QList& args); /******************************************************************************* And now a generic Logging function *******************************************************************************/ void log(LogLevel level, const QList& args); Q_SIGNALS: void loggerEngineAdded(const QString& engineName); void loggerEngineRemoved(const QString& engineName); void loggerEngineEnabled(const QString& engineName); void loggerEngineDisabled(const QString& engineName); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QxtLogger::LogLevels) Q_DECLARE_METATYPE(QxtLogger::LogLevel) Q_DECLARE_METATYPE(QxtLogger::LogLevels) #define qxtLog QxtLogger::getInstance() #include "qxtlogstream.h" #endif // QXTLOGGER_H libqxt-0.6.2/src/core/qxtlogger_p.h000066400000000000000000000040061215241066400172460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLOGGERPRIVATE_H #define QXTLOGGERPRIVATE_H #include "qxtlogger.h" #include /******************************************************************************* QxtLoggerPrivate This is the d_ptr private class containing the actual data this library works with. *******************************************************************************/ QT_FORWARD_DECLARE_CLASS(QMutex) class QxtLoggerPrivate : public QObject, public QxtPrivate { Q_OBJECT QXT_DECLARE_PUBLIC(QxtLogger) public: QxtLoggerPrivate(); ~QxtLoggerPrivate(); void setQxtLoggerEngineMinimumLevel(QxtLoggerEngine *engine, QxtLogger::LogLevel level); QHash map_logEngineMap; QMutex* mut_lock; public Q_SLOTS: void log(QxtLogger::LogLevel, const QList&); }; #endif // QXTLOGGERPRIVATE_H libqxt-0.6.2/src/core/qxtloggerengine.cpp000066400000000000000000000105761215241066400204610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtloggerengine.h" /*! \class QxtLoggerEngine \brief The QxtLoggerEngine class is the parent class of all extended Engine Plugins. \inmodule QxtCore \section1 Overview QxtLoggerEngine is what gives the QxtLogger it's power. While the Logger itself manages memory, logic, and log levels, it is the various Engine Plugins that do the actual work of logging the data. */ class QxtLoggerEnginePrivate : public QxtPrivate { QXT_DECLARE_PUBLIC(QxtLoggerEngine) public: QxtLoggerEnginePrivate(); QxtLogger::LogLevels bm_logLevel; bool b_isLogging; }; QxtLoggerEnginePrivate::QxtLoggerEnginePrivate() : bm_logLevel(QxtLogger::AllLevels), b_isLogging(true) { } /*! Constructor */ QxtLoggerEngine::QxtLoggerEngine() { QXT_INIT_PRIVATE(QxtLoggerEngine); } /*! Destructor */ QxtLoggerEngine::~QxtLoggerEngine() { QxtLogger::getInstance()->removeLoggerEngine(this); } /*! \fn virtual void QxtLoggerEngine::initLoggerEngine() = 0 Initializes the logger engine. This function is called by QxtLogger. Reimplement this function when creating a subclass of QxtLoggerEngine. */ /*! \fn virtual void QxtLoggerEngine::killLoggerEngine() = 0 Kills the logger engine. This function is called by QxtLogger. Reimplement this function when creating a subclass of QxtLoggerEngine. */ /*! \fn virtual bool QxtLoggerEngine::isInitialized() const = 0 Returns \c true if the logger engine is initialized. This function is called by QxtLogger. Reimplement this function when creating a subclass of QxtLoggerEngine. */ /*! \fn virtual void QxtLoggerEngine::writeFormatted(QxtLogger::LogLevel level, const QList& messages) = 0 Writes formatted \a messages with given \a level. This function is called by QxtLogger. Reimplement this function when creating a subclass of QxtLoggerEngine. */ /*! Returns \c true if logging is enabled and \c false otherwise. */ bool QxtLoggerEngine::isLoggingEnabled() const { return qxt_d().b_isLogging; } /*! Enables logging. */ void QxtLoggerEngine::enableLogging() { setLoggingEnabled(); } /*! Disables logging. */ void QxtLoggerEngine::disableLogging() { setLoggingEnabled(false); } /*! Sets logging enabled if \a enable is \c true, or disabled otherwise. */ void QxtLoggerEngine::setLoggingEnabled(bool enable) { qxt_d().b_isLogging = enable; } /*! Sets log \a levels enabled if \a enable is \c true, or disabled otherwise. */ void QxtLoggerEngine::setLogLevelsEnabled(QxtLogger::LogLevels levels, bool enable) { if (enable) { qxt_d().bm_logLevel |= levels; } else { qxt_d().bm_logLevel &= ~levels; } } /*! Enables log \a levels. */ void QxtLoggerEngine::enableLogLevels(QxtLogger::LogLevels levels) { setLogLevelsEnabled(levels, true); } /*! Disables log \a levels. */ void QxtLoggerEngine::disableLogLevels(QxtLogger::LogLevels levels) { setLogLevelsEnabled(levels, false); } /*! Returns \c true if log \a level is enabled and \c false otherwise. */ bool QxtLoggerEngine::isLogLevelEnabled(QxtLogger::LogLevel level) const { return (qxt_d().bm_logLevel & level); } libqxt-0.6.2/src/core/qxtloggerengine.h000066400000000000000000000043371215241066400201240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLOGGERENGINE_H #define QXTLOGGERENGINE_H #include #include #include #include #include "qxtlogger.h" class QxtLoggerEnginePrivate; class QXT_CORE_EXPORT QxtLoggerEngine { QXT_DECLARE_PRIVATE(QxtLoggerEngine) public: QxtLoggerEngine(); virtual ~QxtLoggerEngine(); virtual void initLoggerEngine() = 0; virtual void killLoggerEngine() = 0; virtual bool isInitialized() const = 0; virtual void writeFormatted(QxtLogger::LogLevel level, const QList& messages) = 0; virtual void setLoggingEnabled(bool enable = true); bool isLoggingEnabled() const; void enableLogging(); void disableLogging(); virtual void setLogLevelsEnabled(QxtLogger::LogLevels levels, bool enable = true); bool isLogLevelEnabled(QxtLogger::LogLevel level) const; void enableLogLevels(QxtLogger::LogLevels levels); void disableLogLevels(QxtLogger::LogLevels levels); }; #endif // QXTLOGGERENGINE_H libqxt-0.6.2/src/core/qxtlogstream.cpp000066400000000000000000000044651215241066400200110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlogstream.h" #include "qxtlogstream_p.h" #include "qxtlogger.h" /*! \class QxtLogStream \brief The QxtLogStream class provides a logging stream. \inmodule QxtCore \sa QxtLogger */ QxtLogStreamPrivate::QxtLogStreamPrivate(QxtLogger *owner, QxtLogger::LogLevel level, const QList &data) : owner(owner), level(level), refcount(1), data(data) { // Nothing to see here. } QxtLogStreamPrivate::~QxtLogStreamPrivate() { owner->log(level, data); } /*! Constructs a new QxtLogStream with log \a level and \a data, owned by \a owner. */ QxtLogStream::QxtLogStream(QxtLogger *owner, QxtLogger::LogLevel level, const QList &data) : d(new QxtLogStreamPrivate(owner, level, data)) { // Nothing here either. } /*! Constructs a copy of \a other. */ QxtLogStream::QxtLogStream(const QxtLogStream &other) { d = other.d; d->refcount++; } /*! Destructor. */ QxtLogStream::~QxtLogStream() { d->refcount--; if (d->refcount == 0) delete d; } /*! Appends \a value. */ QxtLogStream& QxtLogStream::operator<< (const QVariant &value) { d->data.append(value); return *this; } libqxt-0.6.2/src/core/qxtlogstream.h000066400000000000000000000032451215241066400174510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLOGSTREAM_H #define QXTLOGSTREAM_H #include #include #include "qxtlogger.h" class QxtLogger; class QxtLogStreamPrivate; class QXT_CORE_EXPORT QxtLogStream { friend class QxtLogger; public: QxtLogStream(const QxtLogStream &other); ~QxtLogStream(); QxtLogStream& operator<< (const QVariant &value); private: QxtLogStream(QxtLogger *owner, QxtLogger::LogLevel level, const QList &data); QxtLogStreamPrivate *d; }; #endif // QXTLOGSTREAM_H libqxt-0.6.2/src/core/qxtlogstream_p.h000066400000000000000000000032751215241066400177730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLOGSTREAM_P_H #define QXTLOGSTREAM_P_H #include "qxtlogger.h" class QxtLogStream; class QxtLogStreamPrivate { friend class QxtLogStream; public: QxtLogStreamPrivate(QxtLogger* owner, QxtLogger::LogLevel level, const QList& data); ~QxtLogStreamPrivate(); QxtLogger *owner; QxtLogger::LogLevel level; int refcount; // Unfortunately, QExplicitlySharedDataPointer was introduced in Qt 4.4, and we have to work with Qt 4.2 ;_; QList data; }; #endif // QXTLOGSTREAM_P_H libqxt-0.6.2/src/core/qxtmetaobject.cpp000066400000000000000000000333651215241066400201320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \namespace QxtMetaObject \inmodule QxtCore \brief The QxtMetaObject namespace provides extensions to QMetaObject including QxtMetaObject::bind */ #include "qxtmetaobject.h" #include "qxtboundfunction.h" #include "qxtboundcfunction.h" #include "qxtmetatype.h" #include #include #include #include #ifndef QXT_DOXYGEN_RUN class QxtBoundArgument { // This class intentionally left blank }; Q_DECLARE_METATYPE(QxtBoundArgument) class QxtBoundFunctionBase; QxtBoundFunction::QxtBoundFunction(QObject* parent) : QObject(parent) { // initializer only } #endif bool QxtBoundFunction::invoke(Qt::ConnectionType type, QXT_IMPL_10ARGS(QVariant)) { return invoke(type, QXT_VAR_ARG(1), QXT_VAR_ARG(2), QXT_VAR_ARG(3), QXT_VAR_ARG(4), QXT_VAR_ARG(5), QXT_VAR_ARG(6), QXT_VAR_ARG(7), QXT_VAR_ARG(8), QXT_VAR_ARG(9), QXT_VAR_ARG(10)); } bool QxtBoundFunction::invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QVariant)) { return invoke(type, returnValue, QXT_VAR_ARG(1), QXT_VAR_ARG(2), QXT_VAR_ARG(3), QXT_VAR_ARG(4), QXT_VAR_ARG(5), QXT_VAR_ARG(6), QXT_VAR_ARG(7), QXT_VAR_ARG(8), QXT_VAR_ARG(9), QXT_VAR_ARG(10)); } QxtBoundFunctionBase::QxtBoundFunctionBase(QObject* parent, QGenericArgument* params[10], QByteArray types[10]) : QxtBoundFunction(parent) { for (int i = 0; i < 10; i++) { if (!params[i]) break; if (QByteArray(params[i]->name()) == "QxtBoundArgument") { arg[i] = QGenericArgument("QxtBoundArgument", params[i]->data()); } else { data[i] = qxtConstructFromGenericArgument(*params[i]); arg[i] = p[i] = QGenericArgument(params[i]->name(), data[i]); } bindTypes[i] = types[i]; } } QxtBoundFunctionBase::~QxtBoundFunctionBase() { for (int i = 0; i < 10; i++) { if (arg[i].name() == 0) return; if (QByteArray(arg[i].name()) != "QxtBoundArgument") qxtDestroyFromGenericArgument(arg[i]); } } int QxtBoundFunctionBase::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QObject::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { if (_id == 0) { for (int i = 0; i < 10; i++) { if (QByteArray(arg[i].name()) == "QxtBoundArgument") { p[i] = QGenericArgument(bindTypes[i].constData(), _a[(quintptr)(arg[i].data())]); } } invokeImpl(Qt::DirectConnection, QGenericReturnArgument(), p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]); } _id = -1; } return _id; } bool QxtBoundFunctionBase::invokeBase(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QGenericArgument)) { QGenericArgument* args[10] = { &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10 }; for (int i = 0; i < 10; i++) { if (QByteArray(arg[i].name()) == "QxtBoundArgument") { p[i] = *args[(quintptr)(arg[i].data()) - 1]; } } return invokeImpl(type, returnValue, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]); } bool QxtBoundFunction::invoke(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QGenericArgument)) { return reinterpret_cast(this)->invokeBase(type, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } #ifndef QXT_DOXYGEN_RUN class QxtBoundSlot : public QxtBoundFunctionBase { public: QByteArray sig; QxtBoundSlot(QObject* receiver, const char* invokable, QGenericArgument* params[10], QByteArray types[10]) : QxtBoundFunctionBase(receiver, params, types), sig(invokable) { // initializers only } virtual bool invokeImpl(Qt::ConnectionType type, QGenericReturnArgument returnValue, QXT_IMPL_10ARGS(QGenericArgument)) { if (!QMetaObject::invokeMethod(parent(), QxtMetaObject::methodName(sig.constData()), type, returnValue, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)) { qWarning() << "QxtBoundFunction: call to" << sig << "failed"; return false; } return true; } }; #endif namespace QxtMetaObject { /*! Returns the name of the given method. Example usage: \code QByteArray method = QxtMetaObject::methodName(" int foo ( int bar, double baz )"); // method is now "foo" \endcode */ QByteArray methodName(const char* method) { QByteArray name = methodSignature(method); const int idx = name.indexOf("("); if (idx != -1) name.truncate(idx); return name; } /*! Returns the signature of the given method. */ QByteArray methodSignature(const char* method) { QByteArray name = QMetaObject::normalizedSignature(method); if(name[0] >= '0' && name[0] <= '9') return name.mid(1); return name; } /*! Checks if \a method contains parentheses and begins with 1 or 2. */ bool isSignalOrSlot(const char* method) { QByteArray m(method); return (m.count() && (m[0] >= '0' && m[0] <= '9') && m.contains('(') && m.contains(')')); } /*! * Creates a binding to the provided signal, slot, or Q_INVOKABLE method using the * provided parameter list. The type of each argument is deduced from the type of * the QVariant. This function cannot bind positional arguments; see the * overload using QGenericArgument. * * If the provided QObject does not implement the requested method, or if the * argument list is incompatible with the method's function signature, this * function returns NULL. * * The returned QxtBoundFunction is created as a child of the receiver. * Changing the parent will result in undefined behavior. * * \sa QxtMetaObject::connect, QxtBoundFunction */ QxtBoundFunction* bind(QObject* recv, const char* invokable, QXT_IMPL_10ARGS(QVariant)) { if (!recv) { qWarning() << "QxtMetaObject::bind: cannot connect to null QObject"; return 0; } QVariant* args[10] = { &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10 }; QByteArray connSlot("2"), recvSlot(QMetaObject::normalizedSignature(invokable)); const QMetaObject* meta = recv->metaObject(); int methodID = meta->indexOfMethod(QxtMetaObject::methodSignature(recvSlot.constData())); if (methodID == -1) { qWarning() << "QxtMetaObject::bind: no such method " << recvSlot; return 0; } QMetaMethod method = meta->method(methodID); int argCount = method.parameterTypes().count(); const QList paramTypes = method.parameterTypes(); for (int i = 0; i < argCount; i++) { if (paramTypes[i] == "QxtBoundArgument") continue; int type = QMetaType::type(paramTypes[i].constData()); if (!args[i]->canConvert((QVariant::Type)type)) { qWarning() << "QxtMetaObject::bind: incompatible parameter list for " << recvSlot; return 0; } } return QxtMetaObject::bind(recv, invokable, QXT_ARG(1), QXT_ARG(2), QXT_ARG(3), QXT_ARG(4), QXT_ARG(5), QXT_ARG(6), QXT_ARG(7), QXT_ARG(8), QXT_ARG(9), QXT_ARG(10)); } /*! * Creates a binding to the provided signal, slot, or Q_INVOKABLE method using the * provided parameter list. Use the Q_ARG macro to specify constant parameters, or * use the QXT_BIND macro to relay a parameter from a connected signal or passed * via the QxtBoundFunction::invoke() method. * * If the provided QObject does not implement the requested method, or if the * argument list is incompatible with the method's function signature, this * function returns NULL. * * The returned QxtBoundFunction is created as a child of the receiver. * Changing the parent will result in undefined behavior. * * \sa QxtMetaObject::connect, QxtBoundFunction, QXT_BIND */ QxtBoundFunction* bind(QObject* recv, const char* invokable, QXT_IMPL_10ARGS(QGenericArgument)) { if (!recv) { qWarning() << "QxtMetaObject::bind: cannot connect to null QObject"; return 0; } QGenericArgument* args[10] = { &p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8, &p9, &p10 }; QByteArray connSlot("2"), recvSlot(QMetaObject::normalizedSignature(invokable)), bindTypes[10]; const QMetaObject* meta = recv->metaObject(); int methodID = meta->indexOfMethod(QxtMetaObject::methodSignature(recvSlot.constData()).constData()); if (methodID == -1) { qWarning() << "QxtMetaObject::bind: no such method " << recvSlot; return 0; } QMetaMethod method = meta->method(methodID); int argCount = method.parameterTypes().count(); connSlot += QxtMetaObject::methodName(invokable) + '('; for (int i = 0; i < 10; i++) { if (args[i]->name() == 0) break; // done if (i >= argCount) { qWarning() << "QxtMetaObject::bind: too many arguments passed to " << invokable; return 0; } if (i > 0) connSlot += ','; // argument separator if (QByteArray(args[i]->name()) == "QxtBoundArgument") { Q_ASSERT_X((quintptr)(args[i]->data()) > 0 && (quintptr)(args[i]->data()) <= 10, "QXT_BIND", "invalid argument number"); connSlot += method.parameterTypes()[i]; bindTypes[i] = method.parameterTypes()[i]; } else { connSlot += args[i]->name(); // type name } } connSlot = QMetaObject::normalizedSignature(connSlot += ')'); if (!QMetaObject::checkConnectArgs(recvSlot.constData(), connSlot.constData())) { qWarning() << "QxtMetaObject::bind: provided parameters " << connSlot.mid(connSlot.indexOf('(')) << " is incompatible with " << invokable; return 0; } return new QxtBoundSlot(recv, invokable, args, bindTypes); } /*! Connects a signal to a QxtBoundFunction. */ bool connect(QObject* sender, const char* signal, QxtBoundFunction* slot, Qt::ConnectionType type) { const QMetaObject* meta = sender->metaObject(); int methodID = meta->indexOfMethod(meta->normalizedSignature(signal).mid(1).constData()); if (methodID < 0) { qWarning() << "QxtMetaObject::connect: no such signal: " << QByteArray(signal).mid(1); return false; } return QMetaObject::connect(sender, methodID, slot, QObject::staticMetaObject.methodCount(), (int)(type)); } /*! \relates QxtMetaObject This overload always invokes the member using the connection type Qt::AutoConnection. \sa QMetaObject::invokeMethod() */ bool invokeMethod(QObject* object, const char* member, const QVariant& arg0, const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, const QVariant& arg4, const QVariant& arg5, const QVariant& arg6, const QVariant& arg7, const QVariant& arg8, const QVariant& arg9) { return invokeMethod(object, member, Qt::AutoConnection, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } /*! \relates QxtMetaObject Invokes the \a member (a signal or a slot name) on the \a object. Returns \c true if the member could be invoked. Returns \c false if there is no such member or the parameters did not match. \sa QMetaObject::invokeMethod() */ bool invokeMethod(QObject* object, const char* member, Qt::ConnectionType type, const QVariant& arg0, const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, const QVariant& arg4, const QVariant& arg5, const QVariant& arg6, const QVariant& arg7, const QVariant& arg8, const QVariant& arg9) { #define QXT_MO_ARG(i) QGenericArgument(arg ## i.typeName(), arg ## i.constData()) return QMetaObject::invokeMethod(object, methodName(member), type, QXT_MO_ARG(0), QXT_MO_ARG(1), QXT_MO_ARG(2), QXT_MO_ARG(3), QXT_MO_ARG(4), QXT_MO_ARG(5), QXT_MO_ARG(6), QXT_MO_ARG(7), QXT_MO_ARG(8), QXT_MO_ARG(9)); } } libqxt-0.6.2/src/core/qxtmetaobject.h000066400000000000000000000110751215241066400175710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTMETAOBJECT_H #define QXTMETAOBJECT_H #include #include #include #include #include "qxtnullable.h" #include "qxtglobal.h" QT_FORWARD_DECLARE_CLASS(QByteArray) class QxtBoundArgument; class QxtBoundFunction; #define QXT_PROTO_10ARGS(T) T p1 = T(), T p2 = T(), T p3 = T(), T p4 = T(), T p5 = T(), T p6 = T(), T p7 = T(), T p8 = T(), T p9 = T(), T p10 = T() #define QXT_PROTO_9ARGS(T) T p2 = T(), T p3 = T(), T p4 = T(), T p5 = T(), T p6 = T(), T p7 = T(), T p8 = T(), T p9 = T(), T p10 = T() #define QXT_IMPL_10ARGS(T) T p1, T p2, T p3, T p4, T p5, T p6, T p7, T p8, T p9, T p10 class QXT_CORE_EXPORT QxtGenericFunctionPointer { template friend QxtGenericFunctionPointer qxtFuncPtr(FUNCTION funcPtr); public: QxtGenericFunctionPointer(const QxtGenericFunctionPointer& other) { funcPtr = other.funcPtr; typeName = other.typeName; } typedef void(voidFunc)(); voidFunc* funcPtr; QByteArray typeName; protected: QxtGenericFunctionPointer(voidFunc* ptr, const QByteArray& typeIdName) { funcPtr = ptr; typeName = typeIdName; } }; template QxtGenericFunctionPointer qxtFuncPtr(FUNCTION funcPtr) { return QxtGenericFunctionPointer(reinterpret_cast(funcPtr), typeid(funcPtr).name()); } namespace QxtMetaObject { QXT_CORE_EXPORT QByteArray methodName(const char* method); QXT_CORE_EXPORT QByteArray methodSignature(const char* method); QXT_CORE_EXPORT bool isSignalOrSlot(const char* method); QXT_CORE_EXPORT QxtBoundFunction* bind(QObject* recv, const char* invokable, QXT_PROTO_10ARGS(QGenericArgument)); QXT_CORE_EXPORT QxtBoundFunction* bind(QObject* recv, const char* invokable, QVariant p1, QXT_PROTO_9ARGS(QVariant)); QXT_CORE_EXPORT bool connect(QObject* sender, const char* signal, QxtBoundFunction* slot, Qt::ConnectionType type = Qt::AutoConnection); QXT_CORE_EXPORT bool invokeMethod(QObject* object, const char* member, const QVariant& arg0 = QVariant(), const QVariant& arg1 = QVariant(), const QVariant& arg2 = QVariant(), const QVariant& arg3 = QVariant(), const QVariant& arg4 = QVariant(), const QVariant& arg5 = QVariant(), const QVariant& arg6 = QVariant(), const QVariant& arg7 = QVariant(), const QVariant& arg8 = QVariant(), const QVariant& arg9 = QVariant()); QXT_CORE_EXPORT bool invokeMethod(QObject* object, const char* member, Qt::ConnectionType type, const QVariant& arg0 = QVariant(), const QVariant& arg1 = QVariant(), const QVariant& arg2 = QVariant(), const QVariant& arg3 = QVariant(), const QVariant& arg4 = QVariant(), const QVariant& arg5 = QVariant(), const QVariant& arg6 = QVariant(), const QVariant& arg7 = QVariant(), const QVariant& arg8 = QVariant(), const QVariant& arg9 = QVariant()); } /*! * \relates QxtMetaObject * Refers to the n'th parameter of QxtBoundFunction::invoke() or of a signal connected to * a QxtBoundFunction. * \sa QxtMetaObject::bind */ #define QXT_BIND(n) QGenericArgument("QxtBoundArgument", reinterpret_cast(n)) #endif // QXTMETAOBJECT_H libqxt-0.6.2/src/core/qxtmetatype.h000066400000000000000000000066611215241066400173110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTMETATYPE_H #define QXTMETATYPE_H #include #include #include #include #include template class /*QXT_CORE_EXPORT*/ QxtMetaType { public: static inline T* construct(const T* copy = 0) { return QMetaType::construct(qMetaTypeId(), reinterpret_cast(copy)); } static inline void destroy(T* data) { QMetaType::destroy(qMetaTypeId(), data); } // no need to reimplement isRegistered since this class will fail at compile time if it isn't static inline bool load(QDataStream& stream, T* data) { return QMetaType::load(stream, qMetaTypeId(), reinterpret_cast(data)); } static inline bool save(QDataStream& stream, const T* data) { return QMetaType::save(stream, qMetaTypeId(), reinterpret_cast(data)); } static inline int type() { return qMetaTypeId(); } static inline const char* name() { return QMetaType::typeName(qMetaTypeId()); } }; template <> class /*QXT_CORE_EXPORT*/ QxtMetaType { public: static inline void* construct(const void* copy = 0) { Q_UNUSED(copy); return 0; } static inline void destroy(void* data) { Q_UNUSED(data); } static inline bool load(QDataStream& stream, void* data) { Q_UNUSED(stream); Q_UNUSED(data); return false; } static inline bool save(QDataStream& stream, const void* data) { Q_UNUSED(stream); Q_UNUSED(data); return false; } static inline int type() { return 0; } static inline const char* name() { return 0; } }; inline void* qxtConstructByName(const char* typeName, const void* copy = 0) { return QMetaType::construct(QMetaType::type(typeName), copy); } inline void qxtDestroyByName(const char* typeName, void* data) { QMetaType::destroy(QMetaType::type(typeName), data); } inline void* qxtConstructFromGenericArgument(QGenericArgument arg) { return qxtConstructByName(arg.name(), arg.data()); } inline void qxtDestroyFromGenericArgument(QGenericArgument arg) { qxtDestroyByName(arg.name(), arg.data()); } #endif libqxt-0.6.2/src/core/qxtmodelserializer.cpp000066400000000000000000000105071215241066400212000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtmodelserializer.h" #include #include /* \class QxtModelSerializer \inmodule QxtCore \brief The QxtModelSerializer class provides serialization of QAbstractItemModel */ struct QxtModelItem { QMap itemData; int rowCount; int columnCount; }; inline QDataStream& operator<<(QDataStream& out, const QxtModelItem& item) { out << item.itemData; out << item.rowCount; out << item.columnCount; return out; } inline QDataStream& operator>>(QDataStream& in, QxtModelItem& item) { in >> item.itemData; in >> item.rowCount; in >> item.columnCount; return in; } class QxtModelSerializerPrivate : public QxtPrivate { public: QxtModelSerializerPrivate() : model(0) { } void save(QDataStream& stream, const QModelIndex& index) const; bool restore(QDataStream& stream, const QModelIndex& index); void print(const QByteArray& data) const; QAbstractItemModel* model; }; void QxtModelSerializerPrivate::save(QDataStream& stream, const QModelIndex& index) const { QxtModelItem item; item.itemData = model->itemData(index); item.rowCount = model->rowCount(index); item.columnCount = model->columnCount(index); stream << item; for (int r = 0; r < item.rowCount; ++r) for (int c = 0; c < item.columnCount; ++c) save(stream, model->index(r, c, index)); } bool QxtModelSerializerPrivate::restore(QDataStream& stream, const QModelIndex& index) { QxtModelItem item; stream >> item; if (index.isValid()) model->setItemData(index, item.itemData); if (item.rowCount > 0) model->insertRows(0, item.rowCount, index); if (item.columnCount > 0) model->insertColumns(0, item.columnCount, index); for (int r = 0; r < item.rowCount; ++r) { for (int c = 0; c < item.columnCount; ++c) restore(stream, model->index(r, c, index)); } return stream.status() == QDataStream::Ok; } void QxtModelSerializerPrivate::print(const QByteArray& data) const { QDataStream stream(data); while (!stream.atEnd()) { QxtModelItem item; stream >> item; } } QxtModelSerializer::QxtModelSerializer(QAbstractItemModel* model) { qxt_d().model = model; } QxtModelSerializer::~QxtModelSerializer() { } QAbstractItemModel* QxtModelSerializer::model() const { return qxt_d().model; } void QxtModelSerializer::setModel(QAbstractItemModel* model) { qxt_d().model = model; } QByteArray QxtModelSerializer::saveModel(const QModelIndex& index) const { if (!qxt_d().model) { qWarning("QxtModelSerializer::saveModel(): model == null"); return QByteArray(); } QByteArray data; QDataStream stream(&data, QIODevice::WriteOnly); qxt_d().save(stream, index); qxt_d().print(data); return data; } bool QxtModelSerializer::restoreModel(const QByteArray& data, const QModelIndex& index) { if (!qxt_d().model) { qWarning("QxtModelSerializer::restoreModel(): model == null"); return false; } QDataStream stream(data); qxt_d().print(data); return qxt_d().restore(stream, index); } libqxt-0.6.2/src/core/qxtmodelserializer.h000066400000000000000000000035401215241066400206440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTMODELSERIALIZER_H #define QXTMODELSERIALIZER_H #include #include class QxtModelSerializerPrivate; QT_FORWARD_DECLARE_CLASS(QByteArray) QT_FORWARD_DECLARE_CLASS(QAbstractItemModel) class QXT_CORE_EXPORT QxtModelSerializer { public: QxtModelSerializer(QAbstractItemModel* model = 0); ~QxtModelSerializer(); QAbstractItemModel* model() const; void setModel(QAbstractItemModel* model); QByteArray saveModel(const QModelIndex& index = QModelIndex()) const; bool restoreModel(const QByteArray& data, const QModelIndex& index = QModelIndex()); private: QXT_DECLARE_PRIVATE(QxtModelSerializer) }; #endif // QXTMODELSERIALIZER_H libqxt-0.6.2/src/core/qxtmultisignalwaiter.cpp000066400000000000000000000100321215241066400215430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtMultiSignalWaiter \inmodule QxtCore \brief The QxtMultiSignalWaiter class blocks and processes events until a group of signals is emitted Code written in a synchronous style will sometimes need to block until any of several conditions are met, or until all of a set of conditions are met. This class allows a group of signals to be defined and waited upon in a simple AND or OR fashion. More complex Boolean relationships can be written by connecting together multiple QxtSignalGroup objects and waiting for all or any of these groups to emit one of their signals. \bold {Note:} QxtMultiSignalWaiter is subject to the same reentrancy problems as QxtSignalWaiter. \sa QxtSignalWaiter */ #include "qxtmultisignalwaiter.h" #include "qxtsignalwaiter.h" /*! * Constructs a QxtMultiSignalWaiter with the specified \a parent. */ QxtMultiSignalWaiter::QxtMultiSignalWaiter(QObject* parent) : QxtSignalGroup(parent) { /* initializers only */ } /*! * Destructs the multi signal waiter. */ QxtMultiSignalWaiter::~QxtMultiSignalWaiter() { /* no-op */ } /*! * Blocks the current function by processing events from the event queue according to * \a flags until any of the signals in the group are emitted. * If \a msec is not \c -1, waitForAny() will return before a signal is emitted if the * specified number of milliseconds have elapsed. Returns \c true if a signal was * caught, or \c false if the timeout elapsed. * Note that waitForAny() may continue to block after a signal is emitted or the * timeout elapses; the function only guarantees that it will not return BEFORE * one of these conditions has occurred. This function is not reentrant. * * \sa QxtSignalGroup::addSignal(), QxtSignalGroup::firstSignalReceived() */ bool QxtMultiSignalWaiter::waitForAny(int msec, QEventLoop::ProcessEventsFlags flags) { if (hasReceivedFirstSignal()) return true; return QxtSignalWaiter::wait(this, SIGNAL(firstSignalReceived()), msec, flags); } /*! * Blocks the current function by processing events from the event queue according to * \a flags until all of the signals in the group have been emitted. If \a msec is not * \c -1, waitForAll() will return before all of the signals are emitted if the specified * number of milliseconds have elapsed. Returns \c true if each signal was caught at * least once, or \c false if the timeout elapsed. Note that waitForAll() may continue * to block after the last signal is emitted or the timeout elapses; the function only * guarantees that it will not return BEFORE one of these conditions has occurred. * This function is not reentrant. * * \sa QxtSignalGroup::addSignal(), QxtSignalGroup::allSignalsReceived() */ bool QxtMultiSignalWaiter::waitForAll(int msec, QEventLoop::ProcessEventsFlags flags) { if (hasReceivedAllSignals()) return true; return QxtSignalWaiter::wait(this, SIGNAL(allSignalsReceived()), msec, flags); } libqxt-0.6.2/src/core/qxtmultisignalwaiter.h000066400000000000000000000032621215241066400212170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTMULTISIGNALWAITER_H #define QXTMULTISIGNALWAITER_H #include #include #include class QXT_CORE_EXPORT QxtMultiSignalWaiter : public QxtSignalGroup { Q_OBJECT public: QxtMultiSignalWaiter(QObject* parent = 0); virtual ~QxtMultiSignalWaiter(); bool waitForAny(int msec = -1, QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); bool waitForAll(int msec = -1, QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); }; #endif libqxt-0.6.2/src/core/qxtnamespace.h000066400000000000000000000051101215241066400174010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTNAMESPACE_H #define QXTNAMESPACE_H #include #if (defined BUILD_QXT | defined Q_MOC_RUN) && !defined(QXT_DOXYGEN_RUN) #include class QXT_CORE_EXPORT Qxt : public QObject { Q_OBJECT Q_ENUMS(Rotation) Q_ENUMS(DecorationStyle) Q_ENUMS(ErrorCode) public: #else namespace Qxt { #endif enum Rotation { NoRotation = 0, UpsideDown = 180, Clockwise = 90, CounterClockwise = 270 }; enum DecorationStyle { NoDecoration, Buttonlike, Menulike }; enum ErrorCode { NoError, UnknownError, LogicalError, Bug, UnexpectedEndOfFunction, NotImplemented, CodecError, NotInitialised, EndOfFile, FileIOError, FormatError, DeviceError, SDLError, InsufficientMemory, SeeErrorString, UnexpectedNullParameter, ClientTimeout, SocketIOError, ParserError, HeaderTooLong, Auth, Overflow }; enum QxtItemDataRole { ItemStartTimeRole = Qt::UserRole + 1, ItemDurationRole = ItemStartTimeRole + 1, UserRole = ItemDurationRole + 23 }; enum Timeunit { Second, Minute, Hour, Day, Week, Month, Year }; }; #endif // QXTNAMESPACE_H libqxt-0.6.2/src/core/qxtnull.cpp000066400000000000000000000023531215241066400167600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtnull.h" // nothing here libqxt-0.6.2/src/core/qxtnull.h000066400000000000000000000034151215241066400164250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTNULL_H #define QXTNULL_H #include /*! \class QxtNull QxtNull \inmodule QxtCore \brief An object representing the "null" value for QxtNullable. \sa QxtNullable */ struct QXT_CORE_EXPORT QxtNull { /*! integer cast operator * In expressions, QxtNull behaves as an integer zero for compatibility with generic functions. */ operator int() const { return 0; } enum { isNull = true }; }; #ifndef QXT_NO_MACROS /*! \relates QxtNull * A convenience alias for QxtNull(). */ #define QXT_NULL QxtNull() #endif // QXT_NO_MACROS #endif // QXTNULL_H libqxt-0.6.2/src/core/qxtnullable.h000066400000000000000000000061011215241066400172440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtNullable QxtNullable \inmodule QxtCore \brief distinct null value compatible with any data type. in general it's a templated abstraction to allow any data type to be expressed with a null value distinct from any real value. An example of such a use is for optional arguments. \n prepare a function for argument skipping: \code void somefunction( qxtNull(int,a) , qxtNull(int,b) ) { if (!a.isNull()) { int i = a.value(); //do something with i } if (!b.isNull()) { int x = b.value(); //do something with x } } \endcode usage: \code somefunction(SKIP,1,2); somefunction(3,4); somefunction(3,SKIP,6); somefunction(1); \endcode */ #ifndef QXTNULLABLE_H #define QXTNULLABLE_H #include /*! \relates QxtNullable * defines a skipable argument with type \a t and variable name \a n */ #define qxtNull(t,n) QxtNullable n = QxtNullable() #include template class /*QXT_CORE_EXPORT*/ QxtNullable { public: QxtNullable(QxtNull); QxtNullable(const T& p); QxtNullable(); ///determinates if the Value is set to something meaningfull bool isNull() const; ///delete Value void nullify(); T& value() const; operator T() const; void operator=(const T& p); private: T* val; }; template QxtNullable::QxtNullable(QxtNull) { val = 0; } template QxtNullable::QxtNullable(const T& p) { val = const_cast(&p); } template QxtNullable::QxtNullable() { val = 0; } template QxtNullable::operator T() const { return *val; } template T& QxtNullable::value() const { return *val; } template bool QxtNullable::isNull() const { return (val == 0); } template void QxtNullable::nullify() { val = 0; } template void QxtNullable::operator=(const T & p) { val = const_cast(&p); } #endif libqxt-0.6.2/src/core/qxtpairlist.h000066400000000000000000000073671215241066400173140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTPAIRLIST_H #define QXTPAIRLIST_H /*! \class QxtPairList QxtPairList \ingroup kit \brief Searchable List of Pairs Pair list provides a list with two values, a bit like QHash, but with the possibility to operate on both values. in contrast to QHash, every entry has a unique id, you can work with. like a QList. \code QxtPairList list; list.append(1,2); list.append(1,5); list.append(5,6); qDebug()<< list.find(1); // "0,1" qDebug()<< list.find(SKIP,5); // "2" qDebug()<< list.find(5); // "2" \endcode you may allso play around with the list itself \code list.list.append(qMakePair(1,2)); \endcode */ #include #include #include #include template class QXT_CORE_EXPORT QxtPairList { public: QxtPairList() {} QxtPairList(const QxtPairList & other) { list = other.list; } QxtPairList operator= (const QxtPairList & other) { list = other.list; } void append(T v1, K v2) { list.append(qMakePair(v1, v2)); } /*! \brief search entries by match both arguments are optional, due to the use of QxtNullable \code find(SKIP,v2); find(v1,SKIP); find(v1); \endcode are all valid */ QList find(qxtNull(T, v1) , qxtNull(K, v2)) { QList found; if ((!v1.isNull()) and(!v2.isNull())) { for (int i = 0;i < list.count();i++) if ((list[i].first() == v1)and(list[i].second() == v2)) found.append(i); return found; } if ((!v1.isNull()) and(v2.isNull())) { for (int i = 0;i < list.count();i++) if (list[i].first() == v1) found.append(i); return found; } if ((v1.isNull()) and(!v2.isNull())) { for (int i = 0;i < list.count();i++) if (list[i].second() == v2) found.append(i); return found; } } ///remove an entries position by position void remove(int nr) { list.removeAt(nr); } ///remove a list of entries by position void remove(QList nrs) { int i; Q_FOREACH(i, nrs) list.removeAt(i); } /*! \brief operate on the list directly you may use the internal list directly, but be carefull don't expect to work the QxPairList to work normal if you mess around with it. */ QList > list; }; #endif // QXTPAIRLIST_H libqxt-0.6.2/src/core/qxtpimpl.h000066400000000000000000000023021215241066400165660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include libqxt-0.6.2/src/core/qxtpipe.cpp000066400000000000000000000150161215241066400167430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtpipe_p.h" #include #include #include /*! * \class QxtPipe * \inmodule QxtCore * \brief The QxtPipe class provides a pipeable QIODevice * * pipes can be connected to other pipes, to exchange data * The default implementation uses a buffer. * Reimplement to make your custom class able to be connected into a pipe chain. * * Example usage: * \code * QxtPipe p1; * QxtPipe p2; * QxtPipe p3; * p1|p2|p3; * p1.write("hi. how are you?"); * qDebug()<Subclassing When implementing your own pipe element, like a de/encoder or something, you have to reimplement receiveData() and call sendData() whenever you have something to send to the pipe network. If you want to the user to be able to read from the device directly via the QIODevice facility you have to call enqueuData() too If you don't want to the user to be able to write to the device directly via the QIODevice facility (that would be fatal for a decoder, for example), then reimplement the functions readData() and writeData() and return 0. \sa QxtDeplex */ /*! * Contructs a new QxtPipe with \a parent. */ QxtPipe::QxtPipe(QObject * parent): QIODevice(parent) { QXT_INIT_PRIVATE(QxtPipe); setOpenMode(QIODevice::ReadWrite); } /*!\reimp*/ bool QxtPipe::isSequential() const { return true; } /*!\reimp*/ qint64 QxtPipe::bytesAvailable() const { return qxt_d().q.count(); } /*! Pipes the output of this instance to the \a other QxtPipe using the given \a mode and \a connectionType. Returns \c true if succeeds. Connection pipes with this function can be considered thread safe. Example usage: \code QxtPipe p1; QxtPipe p2; p1.connect(&p2,QIODevice::ReadOnly); //this data will go nowhere. p2 is connected to p1, but not p2 to p1. p1.write("hello"); //while this data will end up in p1 p2.write("world"); qDebug()<connect(this, QIODevice::WriteOnly, connectionType); } Connection c; c.pipe = other; c.mode = mode; c.connectionType = connectionType; qxt_d().connections.append(c); return true; } /*! * Cuts the connection to the \a other QxtPipe and returns \c true if succeeds. */ bool QxtPipe::disconnect(QxtPipe * other) { bool e = false; QMutableListIterator i(qxt_d().connections); while (i.hasNext()) { i.next(); if (i.value().pipe == other) { i.remove(); e = true; other->disconnect(this); } } return e; } /*! * Convenience function for QxtPipe::connect(). * Pipes the output of this instance to the \a target QxtPipe in readwrite mode with auto connection. */ QxtPipe & QxtPipe::operator | (QxtPipe & target) { connect(&target); return *this; } /*!\reimp*/ qint64 QxtPipe::readData(char * data, qint64 maxSize) { QQueue * q = &qxt_d().q; qint64 i = 0; for (;i < maxSize;i++) { if (q->isEmpty()) break; (*data++) = q->dequeue(); } return i; } /*!\reimp*/ qint64 QxtPipe::writeData(const char * data, qint64 maxSize) { sendData(QByteArray(data, maxSize)); return maxSize; } /*! Call this from your subclass to write \a data to the pipe network. All write connected pipes will be invoked with receiveData In this case this is called from receiveData, the sender will be excluded from the receiver list. */ void QxtPipe::sendData(QByteArray data) const { foreach(const Connection& c, qxt_d().connections) { //don't write back to sender if (c.pipe == qxt_d().lastsender) continue; if (!(c.mode & QIODevice::WriteOnly)) continue; bool r = QMetaObject::invokeMethod(&c.pipe->qxt_d(), "push", c.connectionType, Q_ARG(QByteArray, data), Q_ARG(const QxtPipe *, this)); #ifdef QT_NO_DEBUG Q_UNUSED(r); #else if (!r) { QObject::connect(this, SIGNAL(readyRead()), &c.pipe->qxt_d(), SLOT(push(QByteArray, const QxtPipe *)), c.connectionType); qFatal("metacall failed. see debug output of QObject::connect above"); } #endif } qxt_d().lastsender = 0; } /*! Call this from your subclass to make \a datab available to the QIODevice::read facility */ void QxtPipe::enqueData(QByteArray datab) { QQueue * q = &qxt_d().q; const char * data = datab.constData(); qint64 maxSize = datab.size(); qint64 i = 0; for (;i < maxSize;i++) q->enqueue(*data++); if (i > 0) emit(readyRead()); } /*! This function is called from any connected pipe to input \a datab from \a sender into this instance. Reimplement this function to handle data from the pipe network. The default implementation calls enqueData() and sendData(). */ void QxtPipe::receiveData(QByteArray datab , const QxtPipe * sender) { enqueData(datab); qxt_d().lastsender = sender; sendData(datab); } void QxtPipePrivate::push(QByteArray data, const QxtPipe * sender) { (&qxt_p())->receiveData(data, sender); } libqxt-0.6.2/src/core/qxtpipe.h000066400000000000000000000041151215241066400164060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTPIPE_H #define QXTPIPE_H #include "qxtglobal.h" #include #include class QxtPipePrivate; class QXT_CORE_EXPORT QxtPipe : public QIODevice { Q_OBJECT public: QxtPipe(QObject * parent = 0); virtual bool isSequential() const; virtual qint64 bytesAvailable() const; bool connect(QxtPipe * other , QIODevice::OpenMode mode = QIODevice::ReadWrite, Qt::ConnectionType connectionTyp = Qt::AutoConnection); bool disconnect(QxtPipe * other); QxtPipe & operator | (QxtPipe & target); protected: virtual qint64 readData(char * data, qint64 maxSize); virtual qint64 writeData(const char * data, qint64 maxSize); virtual void receiveData(QByteArray data, const QxtPipe * sender); void sendData(QByteArray data) const; void enqueData(QByteArray data); private: QXT_DECLARE_PRIVATE(QxtPipe) }; #endif // QXTPIPE_H libqxt-0.6.2/src/core/qxtpipe_p.h000066400000000000000000000033151215241066400167260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTPIPE_P_H #define QXTPIPE_P_H #include "qxtpipe.h" struct Connection { QxtPipe * pipe; QIODevice::OpenMode mode; Qt::ConnectionType connectionType; }; class QxtPipePrivate: public QObject, public QxtPrivate { Q_OBJECT QXT_DECLARE_PUBLIC(QxtPipe) public: QxtPipePrivate() { lastsender = 0; } QQueue q; QList connections; mutable const QxtPipe * lastsender; public Q_SLOTS: void push(QByteArray data, const QxtPipe * sender); }; #endif // QXTPIPE_P_H libqxt-0.6.2/src/core/qxtpointerlist.cpp000066400000000000000000000030421215241066400203560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtpointerlist.h" /*! \class QxtPointerList \inmodule QxtCore \brief The QxtPointerList class manages a list of pointers to QObjects, that cleans itself when you add a QObject* to this list, it will be removed from the list when the QObject is deleted. \sa QPointer */ void QxtPointerListDeleter::removeSender() { removeThisObject(QObject::sender()); } libqxt-0.6.2/src/core/qxtpointerlist.h000066400000000000000000000074231215241066400200320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTPOINTERLIST_H #define QXTPOINTERLIST_H #include #include #include "qxtglobal.h" class QXT_CORE_EXPORT QxtPointerListDeleter : public QObject { Q_OBJECT protected: virtual void removeThisObject(QObject * obj) = 0; private Q_SLOTS: void removeSender(); }; template class QxtPointerList : public QxtPointerListDeleter, public QList { public: ///constructs a new QxtPointerList QxtPointerList(): QList() { } ///destructs the QxtPointerList ~QxtPointerList() { QList::clear(); } ///\reimp QxtPointerList(const QxtPointerList & other): QxtPointerListDeleter(), QList(other) { for (int i = 0;i < other.size();i++) { addThisObject(other.at(i)); } } ///\reimp void append(T* value) { addThisObject(value); QList::append(value); } ///\reimp void insert(int i, T * value) { addThisObject(value); QList::insert(i, value); } ///\reimp typename QList::iterator insert(typename QList::iterator before, T* value) { addThisObject(value); return QList::insert(before, value); } ///\reimp QxtPointerList operator+ (const QxtPointerList & other) const { QxtPointerList m = *this; m += other; return m; } ///\reimp QxtPointerList & operator+= (const QxtPointerList & other) { Q_FOREACH(T*t, other) { *this << t; } return *this; } ///\reimp QxtPointerList & operator+= (T* value) { addThisObject(value); QList::operator+=(value); return *this; } ///\reimp QxtPointerList & operator<< (const QxtPointerList & other) { *this += other; return *this; } ///\reimp QxtPointerList & operator<< (T* value) { *this += value; return *this; } ///\reimp QxtPointerList & operator= (const QxtPointerList & other) { QList::clear(); Q_FOREACH(T*t, other) { *this << t; } return *this; } protected: ///reimplement to access objects before they are removed virtual void removeThisObject(QObject * obj) { removeAll(reinterpret_cast(obj)); } ///reimplement to access objects before they are added virtual void addThisObject(QObject * obj) { QObject::connect(obj, SIGNAL(destroyed(QObject *)), this, SLOT(removeSender())); } }; #endif // QXTPOINTERLIST_H libqxt-0.6.2/src/core/qxtrpcservice.cpp000066400000000000000000001025651215241066400201610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtrpcservice.h" #include "qxtrpcservice_p.h" #include "qxtabstractconnectionmanager.h" #include "qxtdatastreamsignalserializer.h" #include "qxtmetaobject.h" #include "qxtboundfunction.h" #include #include #include #include #include #include #include #include #include #include static bool qxt_rpcservice_debug = false; /*! * \class QxtRPCService * \inmodule QxtCore * \brief The QxtRPCService class transmits Qt signals over a QIODevice * * QxtRPCService is a tool that encapsulates Qt signals and transmits them over a QIODevice. The signal is subsequently * re-emitted on the receiving end of the connection. * * QxtRPCService can act as a client or a server. When acting as a server, it uses a QxtAbstractConnectionManager to * accept connections. When acting as a client, the application should provide an already-connected QIODevice to the * setDevice() function. * * All data types used in attached signals and slots must be declared and registered with QMetaType using * Q_DECLARE_METATYPE and qRegisterMetaType. Additional requirements may be imposed by the QxtAbstractSignalSerializer * subclass in use; the default (QxtDataStreamSignalSerializer) requires that they have stream operators registered * with qRegisterMetaTypeStreamOperators. * * Due to a restriction of Qt's signals and slots mechanism, the number of parameters that can be passed to call() and * its related functions, as well as the number of parameters to any signal or slot attached to QxtRPCService, is * limited to 8. */ /* * QxtRPCServiceIntrospector is a customized QObject subclass that implements dynamic slots instead of using a static * metaobject. Trolltech/Nokia has published a document on the concept in Qt Quarterly, available at * , although work on QxtRPCService (originally QxRPCPeer) had * begun before this document was released to non-subscribers. * * This class is responsible for dealing with incoming Qt signals. */ class QxtRPCServiceIntrospector : public QObject { public: // Maintain a pointer back to the service object that owns the introspector. QxtRPCService* rpc; // Keep track of the ID of the next virtual slot to be defined. quint32 nextSlotID; // Maps an incoming signal's metamethod to an entry in signalParameters. QHash signalIDs; // Maps an incoming signal's metamethod to its index in its metaobject. QHash methodIDs; // Each signal and slot has a list of parameters associated with it. // QMetaType provides a type ID for every recognized data type. QList > signalParameters; // A signal connection can be identified by the object emitting it and the signature of the signal. typedef QPair SignalDef; // Maps a signal connection to one or more dynamic slot IDs. QMultiHash signalToId; // Maps a dynamic slot ID to an entry in signalParameters. QHash idToParams; // Keep track of which RPC messages should be emitted for each dynamically created slot. QMultiHash idToRpc; QxtRPCServiceIntrospector(QxtRPCService* parent); bool addSignal(QObject* obj, const char* signature, const QString& rpcFunction); void disconnectObject(QObject* obj); int qt_metacall(QMetaObject::Call _c, int _id, void **_a); }; QxtRPCServiceIntrospector::QxtRPCServiceIntrospector(QxtRPCService* parent) : QObject(parent), rpc(parent) { // We start numbering our dynamic slots one after the last static one in the superclass. nextSlotID = QObject::staticMetaObject.methodCount(); } bool QxtRPCServiceIntrospector::addSignal(QObject* obj, const char* signature, const QString& rpcFunction) { const QMetaObject* meta = obj->metaObject(); QByteArray norm = QxtMetaObject::methodSignature(signature); QxtRPCServicePrivate::MetaMethodDef signal = qMakePair(meta, norm); int sigID, methodID; if(!signalIDs.count(signal)) { // This signal hasn't been encountered before, so read the metaobject and cache the results. methodID = meta->indexOfMethod(norm.constData()); if(methodID < 0) { // indexOfMethod() returns -1 if the signal was not found, so report a warning and return an error. qWarning() << "QxtRPCService::attachSignal: " << obj << "::" << signature << " does not exist"; return false; } // Look up the signal's parameter list, ensure each parameter is queueable, and cache the type IDs. QList types = meta->method(methodID).parameterTypes(); QList typeIDs; int ct = types.count(); for(int i = 0; i < ct; i++) { int typeID = QMetaType::type(types.value(i).constData()); if(typeID <= 0) { qWarning() << "QxtRPCService::attachSignal: cannot queue arguments of type " << types.value(i); return false; } typeIDs.append(typeID); } // Cache the looked-up parameter list, associate the list with the signal definition, and cache the signal's // QMetaObject method index. int nextSignalID = signalParameters.count(); signalParameters.append(typeIDs); signalIDs[signal] = nextSignalID; methodIDs[signal] = methodID; // And finally, set the signal ID for the connect call below. sigID = nextSignalID; } else { // Use the cached values from before. sigID = signalIDs.value(signal); methodID = methodIDs.value(signal); } // Use an undocumented function from QMetaObject to connect the incoming signal to the next dynamic slot. bool success = QMetaObject::connect(obj, methodID, this, nextSlotID); if(!success) { // Presumedly connect() will output its own warning. // The remaining setup is unnecessary if the connection failed. return false; } // Associate the signal and source object with the dynamic slot. signalToId.insert(qMakePair(obj, norm), nextSlotID); // Associate the new dynamic slot with an RPC message, or use the signal signature as the default message. idToRpc.insert(nextSlotID, rpcFunction.isEmpty() ? norm : rpcFunction); // Associate the new dynamic slot with the parameter list definition. idToParams[nextSlotID] = sigID; do { // This variable is perfectly allowed to wrap around; it's terribly unlikely to have four billion // concurrent connections but a particularly long-lived object with a lot of disconnects and // reconnects might survive to see a wraparound. nextSlotID++; // But of course we need to make sure the next ID isn't in use. } while(nextSlotID < quint32(QObject::staticMetaObject.methodCount()) || idToParams.contains(nextSlotID)); return true; } void QxtRPCServiceIntrospector::disconnectObject(QObject* obj) { const QMetaObject* meta = obj->metaObject(); foreach(const SignalDef& sig, signalToId.keys()) { // Iterate through all tracked connections and skip any that don't match the incoming object. if(sig.first != obj) continue; int methodID = methodIDs[qMakePair(meta, sig.second)]; foreach(int id, signalToId.values(sig)) { // Iterate through all of the different connections for the object and explicitly disconnect them. QMetaObject::disconnect(obj, methodID, this, id); // Remove the connection from our mappings. idToRpc.remove(id); idToParams.remove(id); } // Remove the object/signal from the mapping. signalToId.remove(sig); } } int QxtRPCServiceIntrospector::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { // Qt's signal dispatch mechanism invokes qt_metacall for each slot connected to the object. // The metacall protocol expects slots to be checked from the bottom up, starting with QObject and proceeding to // the more derived classes. qt_metacall returns a negative number to indicate that the request was processed or a // positive number to indicate the greatest method ID that was checked. moc-generated qt_metacall implementations // subtract the return value from _id so that slots on a given class can be counted starting at 0, allowing the // subclasses to add new signals or slots without breaking compatibility. QxtRPCService doesn't need this because // it just asks its base class how many methods it has before adding slots. if(QObject::qt_metacall(_c, _id, _a) < 0) return _id; // qt_metacall is also used for other behaviors besides just invoking methods; we don't implement any of these, so // we just return here. if(_c != QMetaObject::InvokeMetaMethod) return _id; // Construct an array of QVariants based on the parameters passed through _a. QVariant v[8]; const QList& types = signalParameters.at(idToParams.value(_id)); int ct = types.count(); for(int i = 0; i < ct; i++) { // The qt_metacall implementation is expected to already know the data types in _a, so that's why we tracked it. v[i] = QVariant(types.at(i), _a[i+1]); } foreach(const QString& rpcName, idToRpc.values(_id)) { // Invoke each RPC message connected to the requested dynamic slot ID. rpc->call(rpcName, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); } // Inform the calling function that we handled the call. return -1; } QxtRPCServicePrivate::QxtRPCServicePrivate() : QObject(NULL), manager(NULL), serializer(new QxtDataStreamSignalSerializer), device(NULL) { // initializers only // As you can see, the default serializer is a QxtDataStreamSerializer. } void QxtRPCServicePrivate::clientConnected(QIODevice* dev, quint64 id) { // QxtMetaObject::bind() is a nice piece of magic that allows parameters to a slot to be defined in the connection. QxtMetaObject::connect(dev, SIGNAL(readyRead()), QxtMetaObject::bind(this, SLOT(clientData(quint64)), Q_ARG(quint64, id))); // Inform other objects that a new client has connected. emit qxt_p().clientConnected(id); // Initialize a new buffer for this connection. buffers[id] = QByteArray(); // If there's any unread data in the device, go ahead and process it up front. if(dev->bytesAvailable() > 0) clientData(id); } void QxtRPCServicePrivate::clientDisconnected(QIODevice* dev, quint64 id) { // When a device is disconnected, disconnect all signals connected to the object... QObject::disconnect(dev, 0, this, 0); QObject::disconnect(dev, 0, &qxt_p(), 0); // ... remove its buffer object... buffers.remove(id); // ... and inform other objects that the disconnection has happened. emit qxt_p().clientDisconnected(id); } void QxtRPCServicePrivate::clientData(quint64 id) { // Get the device from the connection manager. QIODevice* dev = manager->client(id); // Cache a reference to the buffer. QByteArray& buf = buffers[id]; // Read all available data on the device. buf.append(dev->readAll()); while(serializer->canDeserialize(buf)) { // Extract one deserialized signal from the buffer. QxtAbstractSignalSerializer::DeserializedData data = serializer->deserialize(buf); // Check to see if it's a blank command. if(serializer->isNoOp(data)) continue; // Check for protocol errors. if(serializer->isProtocolError(data)) { qWarning() << "QxtRPCService: Invalid data received; disconnecting"; qxt_p().disconnectClient(id); return; } // Pad the arguments to 8, because that's what dispatchFromClient() expects. while(data.second.count() < 8) data.second << QVariant(); // And finally, invoke the dispatcher. dispatchFromClient(id, data.first, data.second[0], data.second[1], data.second[2], data.second[3], data.second[4], data.second[5], data.second[6], data.second[7]); } } void QxtRPCServicePrivate::serverData() { // This function does the same thing as clientData() except there's only one server connection instead of // multiple client connections. // Read all available data on the device. serverBuffer.append(device->readAll()); while(serializer->canDeserialize(serverBuffer)) { // Extract one deserialized signal from the buffer. QxtAbstractSignalSerializer::DeserializedData data = serializer->deserialize(serverBuffer); // Check to see if it's a blank command. if(serializer->isNoOp(data)) continue; // Check for protocol errors. if(serializer->isProtocolError(data)) { qWarning() << "QxtRPCService: Invalid data received; disconnecting"; qxt_p().disconnectServer(); return; } // Pad the arguments to 8, because that's what dispatchFromServer() expects. while(data.second.count() < 8) data.second << QVariant(); // And finally, invoke the dispatcher. dispatchFromServer(data.first, data.second[0], data.second[1], data.second[2], data.second[3], data.second[4], data.second[5], data.second[6], data.second[7]); } } // Constructing a QGenericArgument object is generally done with a Q_ARG macro; this macro is a convenience that // does basically the same thing but dramatically shortens the call to invokeMethod(). #define QXT_ARG(i) ((numParams>i)?QGenericArgument(p ## i .typeName(), p ## i.constData()):QGenericArgument()) void QxtRPCServicePrivate::dispatchFromServer(const QString& fn, const QVariant& p0, const QVariant& p1, const QVariant& p2, const QVariant& p3, const QVariant& p4, const QVariant& p5, const QVariant& p6, const QVariant& p7) const { // If the received message is not connected to any slots, ignore it. if(!connectedSlots.contains(fn)) return; foreach(const SlotDef& slot, connectedSlots.value(fn)) { // Look up the parameters for each slot based on its metamethod definition. MetaMethodDef method = qMakePair(slot.recv->metaObject(), slot.slot); const QList& params = slotParameters.value(method); int numParams = params.count(); // Invoke the specified slot on the receiver object using the arguments passed to the function. The // QGenericArgument stuff is done here for safety, as it's not inconceivable (but it IS dangerous) for // different slots to have different parameter lists. if(qxt_rpcservice_debug) qDebug() << "QxtRPCService: received" << fn << "- invoking" << slot.recv << slot.slot.constData() << slot.type << p0 << p1 << p2 << p3 << p4 << p5 << p6 << p7; if(!QMetaObject::invokeMethod(slot.recv, slot.slot.constData(), slot.type, QXT_ARG(0), QXT_ARG(1), QXT_ARG(2), QXT_ARG(3), QXT_ARG(4), QXT_ARG(5), QXT_ARG(6), QXT_ARG(7))) { qWarning() << "QxtRPCService: invokeMethod for " << slot.recv << "::" << slot.slot << " failed"; } } } void QxtRPCServicePrivate::dispatchFromClient(quint64 id, const QString& fn, const QVariant& p0, const QVariant& p1, const QVariant& p2, const QVariant& p3, const QVariant& p4, const QVariant& p5, const QVariant& p6, const QVariant& p7) const { // If the received message is not connected to any slots, ignore it. if(!connectedSlots.contains(fn)) return; foreach(const SlotDef& slot, connectedSlots.value(fn)) { // Look up the parameters for each slot based on its metamethod definition. MetaMethodDef method = qMakePair(slot.recv->metaObject(), slot.slot); const QList& params = slotParameters.value(method); int numParams = params.count(); // Invoke the specified slot on the receiver object using the arguments passed to the function. // See dispatchFromServer() for a discussion of the safety of QXT_ARG here. if(qxt_rpcservice_debug) qDebug() << "QxtRPCService: received" << fn << "- invoking" << slot.recv << slot.slot.constData() << slot.type << id << p0 << p1 << p2 << p3 << p4 << p5 << p6 << p7; if(!QMetaObject::invokeMethod(slot.recv, slot.slot.constData(), slot.type, Q_ARG(quint64, id), QXT_ARG(0), QXT_ARG(1), QXT_ARG(2), QXT_ARG(3), QXT_ARG(4), QXT_ARG(5), QXT_ARG(6), QXT_ARG(7))) { qWarning() << "QxtRPCService: invokeMethod for " << slot.recv << "::" << slot.slot << " failed"; } } } /*! * Creates a QxtRPCService object with the given \a parent. */ QxtRPCService::QxtRPCService(QObject* parent) : QObject(parent) { // Every QxtRPCService object has two private worker objects. // QxtRPCServicePrivate is responsible for most of the heavy lifting. QXT_INIT_PRIVATE(QxtRPCService); // QxtRPCServiceIntrospector is responsible for capturing and processing incoming signals. qxt_d().introspector = new QxtRPCServiceIntrospector(this); // turn on debugging if the QXT_RPCSERVICE_DEBUG environment variable is set qxt_rpcservice_debug = qgetenv("QXT_RPCSERVICE_DEBUG").toInt(); } /*! * Creates a QxtRPCService object with the given \a parent and connects it to the specified I/O \a device. * * The I/O device must already be opened for reading and writing. */ QxtRPCService::QxtRPCService(QIODevice* device, QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtRPCService); qxt_d().introspector = new QxtRPCServiceIntrospector(this); setDevice(device); } /*! * Destroys the QxtRPCService object. */ QxtRPCService::~QxtRPCService() { // QxtAbstractSignalSerializer isn't a QObject, so we have to explicitly clean it up. delete qxt_d().serializer; } /*! * Returns \c true if the connection manager is accepting connections or if any clients are currently connected. It is * possible for both isServer() and isClient() to return \c false if the connection manager is not accepting * connections, no clients are connected, and no QIODevice is set for a server. * \sa isClient() */ bool QxtRPCService::isServer() const { return qxt_d().manager && (qxt_d().manager->isAcceptingConnections() || qxt_d().manager->clientCount() > 0); } /*! * Returns \c true if the QxtRPCService is currently communicating with a server. It is possible for both isServer() * and isClient() to return \c false if the connection manager is not accepting connections, no clients are connected, * and no QIODevice is set for a server. * \sa isServer() */ bool QxtRPCService::isClient() const { return qxt_d().device != NULL; } /*! * Disconnects a client with \a id using the attached connection manager. * * If connected to a server, this function is ignored with a warning. */ void QxtRPCService::disconnectClient(quint64 id) { if(!isServer()) { qWarning() << "QxtRPCService::disconnectClient: not operating as a server"; return; } if(!qxt_d().manager->client(id)) { qWarning() << "QxtRPCService::disconnectClient: no client with specified ID"; return; } // Ask the manager to disconnect the client. QxtAbstractConnectionManager will emit disconnected(), which is chained // to QxtRPCService::clientDisconnected(), so that signal is not explicitly emitted here. qxt_d().manager->disconnect(id); } /*! * Disconnects from the server. The QIODevice is deleted. Use takeDevice() to disconnect from the server without * deleting the device. * * If not connected to a server, for instance if acting as a server, this function is ignored with a warning. * \sa device() * \sa takeDevice() */ void QxtRPCService::disconnectServer() { if(!isClient()) { qWarning() << "QxtRPCService::disconnectServer: not connected to a server"; return; } takeDevice()->deleteLater(); } /*! * Disconnects all clients, or disconnects from the server. */ void QxtRPCService::disconnectAll() { if(isClient()) disconnectServer(); if(isServer()) { QList clientIDs = clients(); foreach(quint64 id, clientIDs) { // Disconnect from each client in turn. disconnectClient(id); } } } /*! * Returns a list of client IDs for all connected clients. */ QList QxtRPCService::clients() const { if(!isServer()) { qWarning() << "QxtRPCService::clients: not a server"; return QList(); } // This function is mostly a convenience wrapper. return qxt_d().manager->clients(); } /*! * When operating as a client, returns the QIODevice connected to the server. * When operating as a server, or if not connected to a server, returns NULL. * \sa setDevice() * \sa takeDevice() */ QIODevice* QxtRPCService::device() const { return qxt_d().device; } /*! * Begins communicating with a server through the provided QIODevice \a dev. If called while acting as a server, this * function is ignored with a warning. If called while another device is set, the original QIODevice is deleted. The * provided device will be reparented to the QxtRPCService. * * Note that because QIODevice is a generic interface, QxtRPCService cannot provide signals when this device is * disconnected or has low-level errors. Connect to the QIODevice subclass's signals directly if you need this * information. * \sa device() */ void QxtRPCService::setDevice(QIODevice* dev) { // First, delete the old device if one is set. if(qxt_d().device) delete qxt_d().device; // Then set the device and claim ownership of it. qxt_d().device = dev; dev->setParent(this); // Listen for data arriving on the device. QObject::connect(dev, SIGNAL(readyRead()), &qxt_d(), SLOT(serverData())); // If there's already data available on the device, process it. if(dev->bytesAvailable() > 0) qxt_d().serverData(); } /*! * When operating as a client, returns the QIODevice used to communicate with the server. After this function is called, * the QxtRPCService will no longer be connected and device() will return NULL. When operating as a server, or if not * connected to a server, this function returns NULL without any other effect. * \sa device() */ QIODevice* QxtRPCService::takeDevice() { QIODevice* oldDevice = qxt_d().device; if(oldDevice) { // Make sure all signals from the device are disconnected before releasing it so that we don't get spurious // signals firing off where we don't want them. QObject::disconnect(oldDevice, 0, this, 0); QObject::disconnect(oldDevice, 0, &qxt_d(), 0); qxt_d().device = NULL; } return oldDevice; } /*! * Returns the signal serializer used to encode signals before transmission. * \sa setSerializer() */ QxtAbstractSignalSerializer* QxtRPCService::serializer() const { return qxt_d().serializer; } /*! * Sets the signal \a serializer used to encode signals before transmission. The existing serializer will be deleted. * \sa serializer() */ void QxtRPCService::setSerializer(QxtAbstractSignalSerializer* serializer) { delete qxt_d().serializer; qxt_d().serializer = serializer; } /*! * Returns the connection manager used to accept incoming connections. * \sa setConnectionManager() */ QxtAbstractConnectionManager* QxtRPCService::connectionManager() const { return qxt_d().manager; } /*! * Sets the connection \a manager used to accept incoming connections. The existing manager will be deleted and the * provided manager will be reparented to the QxtRPCService. * \sa connectionManager() */ void QxtRPCService::setConnectionManager(QxtAbstractConnectionManager* manager) { // Delete the old manager, if one is set. if(qxt_d().manager) delete qxt_d().manager; // Set the manager and claim ownership of it. qxt_d().manager = manager; manager->setParent(this); // Listen for connections and disconnections. QObject::connect(manager, SIGNAL(newConnection(QIODevice*, quint64)), &qxt_d(), SLOT(clientConnected(QIODevice*, quint64))); QObject::connect(manager, SIGNAL(disconnected(QIODevice*, quint64)), &qxt_d(), SLOT(clientDisconnected(QIODevice*, quint64))); } /*! * Attaches the given signal. * * When the attached \a signal is emitted by \a sender, it will be transmitted to all connected servers, clients, or * peers. If an optional \a rpcFunction is provided, it will be used in place of the name of the transmitted signal. * Use the SIGNAL() macro to specify the signal, just as you would for QObject::connect(). * * Like QObject::connect(), attachSignal() returns \c false if the connection cannot be established. */ bool QxtRPCService::attachSignal(QObject* sender, const char* signal, const QString& rpcFunction) { return qxt_d().introspector->addSignal(sender, signal, rpcFunction); } /*! * Attaches an RPC function to the given slot. * * When a signal with the name given by \a rpcFunction is received from the network, the attached \a slot is executed. * Use the SLOT() macro to specify the slot, just as you would for QObject::connect(). * * Like QObject::connect(), attachSlot() returns \c false if the connection cannot be established. * Also like QObject::connect(), a signal may be used as a slot; invocation will cause the signal to be emitted. * * \bold {Note:} When acting like a server, the first parameter of the slot must be quint64 id. The parameters * of the incoming signal follow. For example, SIGNAL(mySignal(QString)) from the client connects to * SLOT(mySlot(quint64, QString)) on the server. */ bool QxtRPCService::attachSlot(const QString& rpcFunction, QObject* recv, const char* slot, Qt::ConnectionType type) { const QMetaObject* meta = recv->metaObject(); QByteArray name = QxtMetaObject::methodName(slot); QxtRPCServicePrivate::MetaMethodDef info = qMakePair(meta, name); if(!qxt_d().slotParameters.count(info)) { // This method hasn't been encountered before, so read the metaobject and cache the results. QByteArray norm = QxtMetaObject::methodSignature(slot); int methodID = meta->indexOfMethod(norm.constData()); if(methodID < 0) { // indexOfMethod() returns -1 if the method was not found, so report a warning and return an error. qWarning() << "QxtRPCService::attachSlot: " << recv << "::" << norm << " does not exist"; return false; } // Look up the method's parameter list, ensure each parameter is queueable, and cache the type IDs. QList types = meta->method(methodID).parameterTypes(); int ct = types.count(); for(int i = 0; i < ct; i++) { int typeID = QMetaType::type(types.value(i).constData()); if(typeID <= 0) { qWarning() << "QxtRPCService::attachSlot: cannot queue arguments of type " << types.value(i); return false; } } // Cache the looked-up parameter list. qxt_d().slotParameters[info] = types; } // If the RPC function name appears to be a signal or slot, normalize the signature. QString rpcFunc = rpcFunction; if(QxtMetaObject::isSignalOrSlot(rpcFunction.toAscii().constData())) rpcFunc = QxtMetaObject::methodSignature(rpcFunction.toAscii().constData()); // Construct a slot definition and associate it with the RPC function name. QxtRPCServicePrivate::SlotDef slotDef; slotDef.recv = recv; slotDef.slot = name; slotDef.type = type; qxt_d().connectedSlots[rpcFunc].append(slotDef); return true; } /*! * Detaches all signals and slots for the given object \a obj. */ void QxtRPCService::detachObject(QObject* obj) { detachSignals(obj); detachSlots(obj); } /*! * Detaches all signals for the given object \a obj. */ void QxtRPCService::detachSignals(QObject* obj) { qxt_d().introspector->disconnectObject(obj); } /*! * Detaches all slots for the given object \a obj. */ void QxtRPCService::detachSlots(QObject* obj) { foreach(const QString& name, qxt_d().connectedSlots.keys()) { // Iterate over all connected slots. foreach(const QxtRPCServicePrivate::SlotDef& slot, qxt_d().connectedSlots.value(name)) { // Skip slots on other objects. if(slot.recv != obj) continue; qxt_d().connectedSlots[name].removeAll(slot); } } } /*! * Sends the signal \a fn with the given parameter list to the server, or to all connected clients. * * The receiver is not obligated to act upon the signal. If no clients are connected, and if not communicating with a * server, this function does nothing. */ void QxtRPCService::call(QString fn, const QVariant& p1, const QVariant& p2, const QVariant& p3, const QVariant& p4, const QVariant& p5, const QVariant& p6, const QVariant& p7, const QVariant& p8) { if(isClient()) { if(qxt_rpcservice_debug) qDebug() << "QxtRPCService: calling" << fn << "on peer with parameters" << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8; // Normalize the function name if it has the form of a signal or slot. if(QxtMetaObject::isSignalOrSlot(fn.toAscii().constData())) fn = QxtMetaObject::methodSignature(fn.toAscii().constData()); // Serialize the parameters and write the result to the device. QByteArray data = qxt_d().serializer->serialize(fn, p1, p2, p3, p4, p5, p6, p7, p8); qxt_d().device->write(data); } if(isServer()) { // Delegate the call to the other overload of call(). call(clients(), fn, p1, p2, p3, p4, p5, p6, p7, p8); } } /*! * Sends the signal \a fn with the given parameter list to the provided list of clients. * * The receivers are not obligated to act upon the signal. If no client is connected with a provided ID, the ID is * ignored with a warning. If acting as a client, this function does nothing. */ void QxtRPCService::call(QList ids, QString fn, const QVariant& p1, const QVariant& p2, const QVariant& p3, const QVariant& p4, const QVariant& p5, const QVariant& p6, const QVariant& p7, const QVariant& p8) { if(qxt_rpcservice_debug) qDebug() << "QxtRPCService: calling" << fn << "on" << ids << "with parameters" << p1 << p2 << p3 << p4 << p5 << p6 << p7 << p8; // Serialize the parameters first. QByteArray data = qxt_d().serializer->serialize(fn, p1, p2, p3, p4, p5, p6, p7, p8); foreach(quint64 id, ids) { // Find the specified client. QIODevice* dev = qxt_d().manager->client(id); if(!dev) { qWarning() << "QxtRPCService::call: client ID not connected"; continue; } // Transmit the data to the client. dev->write(data); } } /*! * Sends the signal \a fn with the given parameter list to the specified client. * * The receiver is not obligated to act upon the signal. If no client with the given ID is connected, the call will be * ignored with a warning. If acting as a client, this function does nothing. */ void QxtRPCService::call(quint64 id, QString fn, const QVariant& p1, const QVariant& p2, const QVariant& p3, const QVariant& p4, const QVariant& p5, const QVariant& p6, const QVariant& p7, const QVariant& p8) { // Wrap the ID in a list and delegate it to the appropriate overload. call(QList() << id, fn, p1, p2, p3, p4, p5, p6, p7, p8); } /*! * Sends the signal \a fn with the given parameter list to all connected clients except for the client specified. * * The receiver is not obligated to act upon the signal. This function is useful for rebroadcasting a signal from one * client to all other connected clients. If acting as a client, this function does nothing. */ void QxtRPCService::callExcept(quint64 id, QString fn, const QVariant& p1, const QVariant& p2, const QVariant& p3, const QVariant& p4, const QVariant& p5, const QVariant& p6, const QVariant& p7, const QVariant& p8) { // Get the list of clients and remove the exception, then delegate the call to the appropriate overload of call(). QList ids = clients(); ids.removeAll(id); call(ids, fn, p1, p2, p3, p4, p5, p6, p7, p8); } /*! * Detaches all signals and slots for the object that emitted the signal connected to detachSender(). */ void QxtRPCService::detachSender() { detachObject(sender()); } libqxt-0.6.2/src/core/qxtrpcservice.h000066400000000000000000000104731215241066400176220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTRPCSERVICE_H #define QXTRPCSERVICE_H #include #include #include #include #include #include QT_FORWARD_DECLARE_CLASS(QIODevice) class QxtAbstractConnectionManager; class QxtAbstractSignalSerializer; class QxtRPCServicePrivate; class QXT_CORE_EXPORT QxtRPCService : public QObject { Q_OBJECT public: QxtRPCService(QObject* parent = 0); explicit QxtRPCService(QIODevice* device, QObject* parent = 0); virtual ~QxtRPCService(); bool isServer() const; bool isClient() const; QList clients() const; QIODevice* device() const; void setDevice(QIODevice* dev); QIODevice* takeDevice(); QxtAbstractSignalSerializer* serializer() const; void setSerializer(QxtAbstractSignalSerializer* serializer); QxtAbstractConnectionManager* connectionManager() const; void setConnectionManager(QxtAbstractConnectionManager* manager); bool attachSignal(QObject* sender, const char* signal, const QString& rpcFunction = QString()); bool attachSlot(const QString& rpcFunction, QObject* recv, const char* slot, Qt::ConnectionType type = Qt::AutoConnection); void detachSignals(QObject* obj); void detachSlots(QObject* obj); void detachObject(QObject* obj); public Q_SLOTS: void disconnectClient(quint64 id); void disconnectServer(); void disconnectAll(); void call(QString fn, const QVariant& p1 = QVariant(), const QVariant& p2 = QVariant(), const QVariant& p3 = QVariant(), const QVariant& p4 = QVariant(), const QVariant& p5 = QVariant(), const QVariant& p6 = QVariant(), const QVariant& p7 = QVariant(), const QVariant& p8 = QVariant()); void call(QList ids, QString fn, const QVariant& p1 = QVariant(), const QVariant& p2 = QVariant(), const QVariant& p3 = QVariant(), const QVariant& p4 = QVariant(), const QVariant& p5 = QVariant(), const QVariant& p6 = QVariant(), const QVariant& p7 = QVariant(), const QVariant& p8 = QVariant()); void call(quint64 id, QString fn, const QVariant& p1 = QVariant(), const QVariant& p2 = QVariant(), const QVariant& p3 = QVariant(), const QVariant& p4 = QVariant(), const QVariant& p5 = QVariant(), const QVariant& p6 = QVariant(), const QVariant& p7 = QVariant(), const QVariant& p8 = QVariant()); void callExcept(quint64 id, QString fn, const QVariant& p1 = QVariant(), const QVariant& p2 = QVariant(), const QVariant& p3 = QVariant(), const QVariant& p4 = QVariant(), const QVariant& p5 = QVariant(), const QVariant& p6 = QVariant(), const QVariant& p7 = QVariant(), const QVariant& p8 = QVariant()); void detachSender(); Q_SIGNALS: /*! * This signal is emitted after a successful connection from a client. * * The given ID is used for disconnectClient(), call(), and related functions. */ void clientConnected(quint64 id); /*! * This signal is emitted when a client disconnects. The given ID is no longer valid. */ void clientDisconnected(quint64 id); private: QXT_DECLARE_PRIVATE(QxtRPCService) }; #endif libqxt-0.6.2/src/core/qxtrpcservice_p.h000066400000000000000000000107271215241066400201430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTRPCSERVICE_P_H #define QXTRPCSERVICE_P_H #include "qxtrpcservice.h" #include #include #include #include #include class QxtRPCServiceIntrospector; class QxtRPCServicePrivate : public QObject, public QxtPrivate { Q_OBJECT public: QxtRPCServicePrivate(); QXT_DECLARE_PUBLIC(QxtRPCService) QxtRPCServiceIntrospector* introspector; QxtAbstractConnectionManager* manager; QxtAbstractSignalSerializer* serializer; QPointer device; // One buffer is needed for the "server" connection, and one buffer is needed for each connected client. QByteArray serverBuffer; QHash buffers; // A Qt invokable, such as a signal or slot, can be identified by the metaobject containing its description plus // its signature or name. It is worth noting that QxtRPCService uses the same structure for both signals and slots, // but in slightly different ways: For identifying incoming signals, this structure contains the signature. For // identifying outgoing slots, this structure only contains the name, and the parameters coming from the signal are // used to determine which overload to use. // TODO: Is this actually safe? typedef QPair MetaMethodDef; // A slot connection can be identified by the object receiving it and the name of the function. Additionally, a // connection can be Direct, Queued, or BlockingQueued. struct SlotDef { QObject* recv; QByteArray slot; Qt::ConnectionType type; inline bool operator==(const SlotDef& other) const { // Two slots are equivalent only if they refer to the same slot on the same object with the same // connection type. return (recv == other.recv) && (slot == other.slot) && (type == other.type); } }; // Maps an RPC function name to a list of slot connections. QHash > connectedSlots; // Maps a slot's metamethod to an array of parameter type names. QHash > slotParameters; // As described in the main class's documentation, QMetaObject::invokeMethod is limited to 10 parameters, so // QxtRPCService is limited to 8. void dispatchFromServer(const QString& fn, const QVariant& p0 = QVariant(), const QVariant& p1 = QVariant(), const QVariant& p2 = QVariant(), const QVariant& p3 = QVariant(), const QVariant& p4 = QVariant(), const QVariant& p5 = QVariant(), const QVariant& p6 = QVariant(), const QVariant& p7 = QVariant()) const; void dispatchFromClient(quint64 id, const QString& fn, const QVariant& p0 = QVariant(), const QVariant& p1 = QVariant(), const QVariant& p2 = QVariant(), const QVariant& p3 = QVariant(), const QVariant& p4 = QVariant(), const QVariant& p5 = QVariant(), const QVariant& p6 = QVariant(), const QVariant& p7 = QVariant()) const; public Q_SLOTS: void clientConnected(QIODevice* dev, quint64 id); void clientDisconnected(QIODevice* dev, quint64 id); void clientData(quint64 id); void serverData(); }; #endif libqxt-0.6.2/src/core/qxtserialdevice.cpp000066400000000000000000000072451215241066400204520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtserialdevice.h" #include "qxtserialdevice_p.h" QxtSerialDevicePrivate::QxtSerialDevicePrivate() { fd = -1; notifier = 0; } /** * Creates a new QxtSerialDevice with the specified parent and sets the device name to \a device. */ QxtSerialDevice::QxtSerialDevice(const QString& device, QObject* parent) : QIODevice(parent) { QXT_INIT_PRIVATE(QxtSerialDevice); setDeviceName(device); setBaud(Baud9600); } /** * Creates a new QxtSerialDevice with the specified parent. */ QxtSerialDevice::QxtSerialDevice(QObject* parent) : QIODevice(parent) { QXT_INIT_PRIVATE(QxtSerialDevice); setBaud(Baud9600); } /** * \reimp */ bool QxtSerialDevice::atEnd() const { return (bytesAvailable() == 0); } /** * \reimp */ bool QxtSerialDevice::canReadLine() const { if(QIODevice::canReadLine()) return true; if(openMode() & QIODevice::Unbuffered) return false; if(qxt_d().constFillBuffer()) return false; return qxt_d().buffer.contains('\n'); } /** * \reimp */ bool QxtSerialDevice::isSequential() const { return true; } /** * Sets the device name to \a device. This is a device node like "/dev/ttyS0" on UNIX or a device name like "COM1" on Windows. * \sa deviceName */ void QxtSerialDevice::setDeviceName(const QString& device) { qxt_d().device = device; } /** * Returns the current device name. * \sa device */ QString QxtSerialDevice::deviceName() const { return qxt_d().device; } /** * Returns the file descriptor for the open device. If the device is not open, this function returns -1. */ int QxtSerialDevice::handle() const { if(!isOpen()) return -1; return qxt_d().fd; } bool QxtSerialDevice::open(const QString& device, OpenMode mode) { setDeviceName(device); return(open(mode)); } bool QxtSerialDevice::setPortSettings(PortSettings setup) { qxt_d().portSettings = setup; return qxt_d().setPortSettings(setup); } QxtSerialDevice::PortSettings QxtSerialDevice::portSettings() const { return qxt_d().portSettings; } QxtSerialDevice::PortSetting QxtSerialDevice::dataBits() const { return PortSetting(int(qxt_d().portSettings & BitMask)); } QxtSerialDevice::PortSetting QxtSerialDevice::flowControl() const { return PortSetting(int(qxt_d().portSettings & FlowMask)); } QxtSerialDevice::PortSetting QxtSerialDevice::parity() const { return PortSetting(int(qxt_d().portSettings & ParityMask)); } QxtSerialDevice::PortSetting QxtSerialDevice::stopBits() const { return PortSetting(int(qxt_d().portSettings & StopMask)); } libqxt-0.6.2/src/core/qxtserialdevice.h000066400000000000000000000060431215241066400201120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSERIALDEVICE_H #define QXTSERIALDEVICE_H #include "qxtglobal.h" #include class QxtSerialDevicePrivate; class QXT_CORE_EXPORT QxtSerialDevice : public QIODevice { Q_OBJECT Q_ENUMS(BaudRate) Q_FLAGS(PortSetting PortSettings) public: enum BaudRate { Baud110, Baud300, Baud600, Baud1200, Baud2400, Baud4800, Baud9600, Baud19200, Baud38400, Baud57600, Baud115200 }; enum PortSetting { Bit8 = 0, Bit7 = 1, Bit6 = 2, Bit5 = 3, BitMask = 3, FlowOff = 0, FlowRtsCts = 4, FlowXonXoff = 8, FlowMask = 12, ParityNone = 0, ParityOdd = 16, ParityEven = 32, ParityMark = 48, ParitySpace = 64, ParityMask = 112, Stop1 = 0, Stop2 = 128, StopMask = 128 }; Q_DECLARE_FLAGS(PortSettings, PortSetting); explicit QxtSerialDevice(const QString& device, QObject* parent = 0); QxtSerialDevice(QObject* parent = 0); virtual bool atEnd() const; virtual qint64 bytesAvailable() const; virtual bool canReadLine() const; virtual void close(); virtual bool isSequential() const; bool open(const QString& device, OpenMode mode); virtual bool open(OpenMode mode); int handle() const; void setDeviceName(const QString& device); QString deviceName() const; bool setBaud(BaudRate rate); BaudRate baud() const; bool setPortSettings(PortSettings setup); PortSettings portSettings() const; PortSetting dataBits() const; PortSetting flowControl() const; PortSetting parity() const; PortSetting stopBits() const; protected: virtual qint64 readData(char* data, qint64 maxSize); virtual qint64 writeData(const char* data, qint64 maxSize); private: QXT_DECLARE_PRIVATE(QxtSerialDevice) }; Q_DECLARE_OPERATORS_FOR_FLAGS(QxtSerialDevice::PortSettings); #endif libqxt-0.6.2/src/core/qxtserialdevice_p.h000066400000000000000000000037651215241066400204410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSERIALDEVICE_P_H #define QXTSERIALDEVICE_P_H #include "qxtserialdevice.h" #include #ifdef Q_OS_UNIX #include #endif QT_FORWARD_DECLARE_CLASS(QSocketNotifier) class QxtSerialDevicePrivate : public QObject, public QxtPrivate { Q_OBJECT public: QxtSerialDevicePrivate(); int fd; bool errorState; QSocketNotifier* notifier; mutable QByteArray buffer; QString device; int baud, flow, format; QxtSerialDevice::PortSettings portSettings; // duplicated for convenience #ifdef Q_OS_UNIX termios reset, settings; #endif qint64 deviceBuffer() const; bool setPortSettings(QxtSerialDevice::PortSettings settings); bool updateSettings(); public slots: int fillBuffer(); int constFillBuffer() const; }; #endif // QXTSERIALDEVICE_P_H libqxt-0.6.2/src/core/qxtserialdevice_unix.cpp000066400000000000000000000175321215241066400215150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtserialdevice.h" #include "qxtserialdevice_p.h" #include #include #include #include #include #include #include #if defined(Q_OS_BSD4) || defined(Q_OS_DARWIN) || defined(Q_OS_BSDI) || defined(Q_OS_NETBSD) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) // definition of FIONREAD #include #endif qint64 QxtSerialDevicePrivate::deviceBuffer() const { int bytes; ioctl(fd, FIONREAD, &bytes); return bytes; } qint64 QxtSerialDevice::bytesAvailable() const { return QIODevice::bytesAvailable() + qxt_d().buffer.length() + qxt_d().deviceBuffer(); } void QxtSerialDevice::close() { if(isOpen()) { emit aboutToClose(); tcsetattr(qxt_d().fd, TCSANOW, &qxt_d().reset); ::close(qxt_d().fd); qxt_d().notifier->setEnabled(false); qxt_d().notifier->deleteLater(); qxt_d().notifier = 0; setOpenMode(QIODevice::NotOpen); } } bool QxtSerialDevice::open(OpenMode mode) { if(qxt_d().notifier) { delete qxt_d().notifier; qxt_d().notifier = 0; } int m; if(mode & QIODevice::ReadOnly && mode & QIODevice::WriteOnly) { // r/w m = O_RDWR; } else if(mode & QIODevice::ReadOnly) { m = O_RDONLY; } else { m = O_WRONLY; } qxt_d().fd = ::open(qxt_d().device.toLocal8Bit().constData(), m | O_NOCTTY); if(qxt_d().fd < 0) { // TODO: set error message return false; } fcntl(qxt_d().fd, F_SETFL, O_NONBLOCK); tcgetattr(qxt_d().fd, &qxt_d().reset); cfmakeraw(&qxt_d().settings); qxt_d().notifier = new QSocketNotifier(qxt_d().fd, QSocketNotifier::Read, this); if(mode & QIODevice::Unbuffered) { QObject::connect(qxt_d().notifier, SIGNAL(activated(int)), this, SIGNAL(readyRead())); } else { QObject::connect(qxt_d().notifier, SIGNAL(activated(int)), &qxt_d(), SLOT(fillBuffer())); } setOpenMode(mode); return qxt_d().updateSettings(); } int QxtSerialDevicePrivate::constFillBuffer() const { notifier->setEnabled(false); int sz = deviceBuffer(); QVarLengthArray buf(sz); int rv = read(fd, buf.data(), sz); if(rv < 0) { notifier->setEnabled(true); if(errno == EAGAIN) return 0; // harmless return errno; } buffer += QByteArray(buf.constData(), rv); notifier->setEnabled(true); return 0; } int QxtSerialDevicePrivate::fillBuffer() { int sz = buffer.length(); int rv = constFillBuffer(); if(rv) { notifier->setEnabled(false); qxt_p().setErrorString(strerror(rv)); } if(buffer.length() != sz) QMetaObject::invokeMethod(&qxt_p(), "readyRead", Qt::QueuedConnection); return rv; } bool QxtSerialDevice::setBaud(BaudRate rate) { switch(rate) { case Baud110: qxt_d().baud = B110; break; case Baud300: qxt_d().baud = B300; break; case Baud600: qxt_d().baud = B600; break; case Baud1200: qxt_d().baud = B1200; break; case Baud2400: qxt_d().baud = B2400; break; case Baud4800: qxt_d().baud = B4800; break; case Baud9600: qxt_d().baud = B9600; break; case Baud19200: qxt_d().baud = B19200; break; case Baud38400: qxt_d().baud = B38400; break; case Baud57600: qxt_d().baud = B57600; break; case Baud115200: qxt_d().baud = B115200; break; }; return qxt_d().updateSettings(); } QxtSerialDevice::BaudRate QxtSerialDevice::baud() const { switch(qxt_d().baud) { case B110: return Baud110; case B300: return Baud300; case B600: return Baud600; case B1200: return Baud1200; case B2400: return Baud2400; case B4800: return Baud4800; case B19200: return Baud19200; case B38400: return Baud38400; case B57600: return Baud57600; case B115200: return Baud115200; default: return Baud9600; }; } qint64 QxtSerialDevice::readData(char* data, qint64 maxSize) { qxt_d().notifier->setEnabled(true); int b = bytesAvailable(); if(maxSize > b) maxSize = b; if(!(openMode() & QIODevice::Unbuffered)) { if(qxt_d().fillBuffer()) return 0; } int bufsize = qxt_d().buffer.length(); int rv = 0; if(maxSize <= bufsize) { memcpy(data, qxt_d().buffer.constData(), maxSize); qxt_d().buffer = qxt_d().buffer.mid(maxSize); return maxSize; } else { memcpy(data, qxt_d().buffer.constData(), bufsize); qxt_d().buffer.clear(); rv = bufsize; data += bufsize; maxSize -= bufsize; } int readVal = ::read(qxt_d().fd, data, maxSize); if(readVal < 0) { qxt_d().notifier->setEnabled(false); setErrorString(strerror(errno)); return -1; } else { rv += readVal; } return rv; } qint64 QxtSerialDevice::writeData(const char* data, qint64 maxSize) { int rv = ::write(qxt_d().fd, data, maxSize); if(rv < 0) { qxt_d().notifier->setEnabled(false); setErrorString(strerror(errno)); } return rv; } bool QxtSerialDevicePrivate::setPortSettings(QxtSerialDevice::PortSettings setup) { int bits = setup & QxtSerialDevice::BitMask; switch(bits) { case QxtSerialDevice::Bit8: format = CS8; break; case QxtSerialDevice::Bit7: format = CS7; break; case QxtSerialDevice::Bit6: format = CS6; break; case QxtSerialDevice::Bit5: format = CS5; break; }; if(setup & QxtSerialDevice::Stop2) format |= CSTOPB; int parity = setup & QxtSerialDevice::ParityMask; if(parity != QxtSerialDevice::ParityNone) { format |= PARENB; if(parity == QxtSerialDevice::ParityOdd) { format |= PARODD; } else if(parity == QxtSerialDevice::ParityMark || parity == QxtSerialDevice::ParitySpace) { #ifdef CMSPAR format |= CMSPAR; if(parity == QxtSerialDevice::ParityMark) format |= PARODD; #else qxt_p().setErrorString("Space/Mark parity not supported"); return false; #endif } } int flowbits = setup & QxtSerialDevice::FlowMask; if(flowbits == QxtSerialDevice::FlowRtsCts) { #ifdef CRTSCTS flow = CRTSCTS; #else qxt_p().setErrorString("Hardware flow control not supported"); return false; #endif } else if(flowbits == QxtSerialDevice::FlowXonXoff) { flow = IXON | IXOFF; } return updateSettings(); } bool QxtSerialDevicePrivate::updateSettings() { if(qxt_p().isOpen()) { settings.c_cflag = baud | flow | format | CLOCAL | CREAD; tcflush(fd, TCIFLUSH); if(tcsetattr(fd, TCSANOW, &settings)) { notifier->setEnabled(false); qxt_p().setErrorString(strerror(errno)); return false; } } return true; } libqxt-0.6.2/src/core/qxtsharedprivate.h000066400000000000000000000112201215241066400203050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtSharedPrivate QxtSharedPrivate \inmodule QxtCore \brief base class for shared data objects using the pimpl idom combines both, the functionality of QxtPimpl and QSharedData \n It is assumed you are familiar with QxtPimpl and QSharedData / QSharedDataPointer. If not, please read their documentation before this one. \n

Major differences to QxtPimpl are:

- there is no qxt_p() since there are multiple public classes sharing the same private - you have to explicitly initialise the private data in the ctor of your public class using new - instead of using QXT_DECLARE_PRIVATE(MyClass) you use QxtSharedPrivate d; - The private data does not have to be a QxtPrivate subclass

Major differences to QSharedData / QSharedDataPointer are:

- the actual Data can be a private implementation - access via d().member() instead of d->member(); (QxtPimpl style) - The private data does not have to be a QSharedData subclass

example

expanding the example from the QSharedDataPointer we get this: \code #ifndef EMPLOYEE_H #define EMPLOYEE_H #include #include class EmployeePrivate; class Employee { public: Employee(); Employee(int id, const QString &name); void setId(int id) { d->id = id; } void setName(const QString &name); int id() const { return d->id; } QString name() const; private: QxtSharedPrivate qxt_d; }; class EmployeePrivate { public: int id; QString name; }; #endif \endcode note that contrary to QxtPimpl you need to initialise your private data once \code Employee::Employee() { qxt_d = new EmployeePrivate; } \endcode if you ever really want to define a copy constructor for your public class, remember you must not reinitialise qxt_d as this would defeat the whole point of shared data. instead just copy it. The underlying QSharedDataPointer will take care of the rest. \code Employee::Employee(const Employee & other) { qxt_d = other.qxt_d; } \endcode Also remember you must not delete the private data yourself at any time. */ #ifndef QXTSHAREDPRIVATE_H #define QXTSHAREDPRIVATE_H #include #include #include #ifndef QXT_DOXYGEN_RUN template class QxtSharedPrivateData : public QSharedData { public: QxtSharedPrivateData() { } ~QxtSharedPrivateData() { delete data; } QxtSharedPrivateData(const QxtSharedPrivateData & other): QSharedData(other) { data = new PVT(*other.data); } PVT * data; }; #endif // QXT_DOXYGEN_RUN class QxtSharedPrivateDestructor { public: virtual ~QxtSharedPrivateDestructor() {} }; template class /*QXT_CORE_EXPORT*/ QxtSharedPrivate { public: QxtSharedPrivate() { pvt = 0; } QxtSharedPrivate(const QxtSharedPrivate &other) { pvt = other.pvt; } inline PVT& operator=(PVT * n) { Q_ASSERT(pvt == 0); QxtSharedPrivateData *t = new QxtSharedPrivateData; t->data = n; pvt = t; return *static_cast(pvt->data); } inline PVT& operator()() { return *static_cast(pvt->data); } inline const PVT& operator()() const { return *static_cast(pvt->data); } private: QSharedDataPointer > pvt; }; #endif // QXTSHAREDPRIVATE_H libqxt-0.6.2/src/core/qxtsignalgroup.cpp000066400000000000000000000142001215241066400203320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtSignalGroup \inmodule QxtCore \brief The QxtSignalGroup class groups signals together in a Boolean fashion When carrying out multiple tasks in parallel, it can be useful to know when any or all of the tasks have emitted a signal. This class allows a group of signals to be defined and re-signalled in a simple AND or OR fashion. More complex Boolean relationships can be written by connecting together multiple QxtSignalGroup objects. For a simple example, suppose you have four QHttp requests pending and you want to know when the last request has completed. A QxtSignalGroup defined like this will emit its allSignalsReceived() signal after each request has emitted its done() signal. \code QxtSignalGroup* group = new QxtSignalGroup; for(int i = 0; i < 4; i++) { group->addSignal(http[i], SIGNAL(done())); } \endcode For a more complex example, suppose you have two such batches of requests, and you want a signal to be emitted when the first batch is completed. Create two QxtSignalGroup objects (perhaps group1 and group2) and add their signals to a third group. This third group will emit its firstSignalReceived() signal when the first batch is completed and its allSignalsReceived() signal when all batches are finished. \code QxtSignalGroup* batches = new QxtSignalGroup; batches->addSignal(group1, SIGNAL(allSignalsReceived())); batches->addSignal(group2, SIGNAL(allSignalsReceived())); \endcode */ #include "qxtsignalgroup.h" #include #include #include class QxtSignalGroupPrivate : public QObject, public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtSignalGroup) QxtSignalGroupPrivate() : QObject(0) { // since we don't have a metaobject of our own due to not // using the Q_OBJECT macro, we need to find methodOffset // on our own. baseSignal = QObject::staticMetaObject.methodCount(); emitCount = disconnectCount = 0; } QVector emittedSignals; int baseSignal, emitCount, disconnectCount; protected: int qt_metacall(QMetaObject::Call _c, int _id, void **_a) { Q_UNUSED(_c); Q_UNUSED(_a); // We don't care about QObject's methods, so skip them _id -= baseSignal; int ct = emittedSignals.count(); // cached for slight performance gain if (_id < 0 || _id > ct) return _id; bool& state = emittedSignals[_id]; // more performance caching if (!state) { if (emitCount == 0) qxt_p().firstSignalReceived(); emitCount++; state = true; if (emitCount + disconnectCount == ct) qxt_p().allSignalsReceived(); } return _id; } }; /*! * Constructs a QxtSignalWaiter with the specified \a parent. */ QxtSignalGroup::QxtSignalGroup(QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtSignalGroup); } /*! * Returns \c true if at least one attached signal has been emitted since the last reset(). */ bool QxtSignalGroup::hasReceivedFirstSignal() const { return qxt_d().emitCount > 0; } /*! * Returns \c true if every attached signal has been emitted at least once since the last reset(). */ bool QxtSignalGroup::hasReceivedAllSignals() const { return (qxt_d().emitCount + qxt_d().disconnectCount) >= qxt_d().emittedSignals.count(); } /*! * Add a signal from \a sender with signature \a sig to the group. */ void QxtSignalGroup::addSignal(QObject* sender, const char* sig) { int signalID = sender->metaObject()->indexOfSignal(QMetaObject::normalizedSignature(sig + 1)); if (signalID < 0) { qWarning() << "QxtSignalGroup::addSignal: no such signal" << sig; } else { QMetaObject::connect(sender, signalID, &(qxt_d()), qxt_d().emittedSignals.count() + qxt_d().baseSignal); qxt_d().emittedSignals.append(false); } } /*! * Remove a signal from \a sender with signature \a sig from the group. */ void QxtSignalGroup::removeSignal(QObject* sender, const char* sig) { if (QObject::disconnect(sender, sig, &(qxt_d()), 0)) qxt_d().disconnectCount++; } /*! * Reset the signal tracking, that is, after calling reset() no signals are considered to have been caught. */ void QxtSignalGroup::reset() { qxt_d().emittedSignals.fill(false); qxt_d().emitCount = 0; } /*! * Removes all signals from the group and resets the signal tracking. */ void QxtSignalGroup::clear() { qxt_d().emittedSignals.clear(); qxt_d().emitCount = 0; qxt_d().disconnectCount = 0; } /*! * \fn void QxtSignalGroup::firstSignalReceived(); * This signal is emitted the first time a signal in the group is emitted. * After this signal is emitted once, you must call reset() before it can be emitted again. */ /*! * \fn void QxtSignalGroup::allSignalsReceived(); * This signal is emitted after every signal in the group has been emitted at least once. * After this signal is emitted once, you must call reset() before it can be emitted again. */ libqxt-0.6.2/src/core/qxtsignalgroup.h000066400000000000000000000034261215241066400200070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSIGNALGROUP_H #define QXTSIGNALGROUP_H #include #include class QxtSignalGroupPrivate; class QXT_CORE_EXPORT QxtSignalGroup : public QObject { Q_OBJECT QXT_DECLARE_PRIVATE(QxtSignalGroup) public: QxtSignalGroup(QObject* parent = 0); void addSignal(QObject* sender, const char* sig); void removeSignal(QObject* sender, const char* sig = 0); void clear(); bool hasReceivedFirstSignal() const; bool hasReceivedAllSignals() const; public Q_SLOTS: void reset(); Q_SIGNALS: void firstSignalReceived(); void allSignalsReceived(); }; #endif libqxt-0.6.2/src/core/qxtsignalwaiter.cpp000066400000000000000000000142031215241066400204740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtSignalWaiter \inmodule QxtCore \brief The QxtSignalWaiter class blocks and processes events until a signal is emitted In many cases, writing code that assumes certain actions are synchronous is considerably simpler than breaking your function into multiple blocks and using signals and slots to connect them all. Using this class, QSignalWaiter::wait will block until a certain signal is emitted and then return. The return value is true if the signal was caught, or false if a user-specified timeout elapses before catching the signal. \code void MyObject::myFunction() { QxtSignalWaiter waiter(myOtherObject, SIGNAL(longProcessFinished())); myOtherObject->longProcess(); if(waiter.wait(5000)) { doSomething(myOtherObject->information()); } else { QMessageBox::information(0, "MyObject", "Timed out while waiting on longProcessFinished()", QMessageBox::Ok); } } \endcode \bold {Note:} QxtSignalWaiter is not reentrant. In particular, only one QxtSignalWaiter object per thread can be safely waiting at a time. If a second QxtSignalWaiter is used while the first is waiting, the first will not return until the second has timed out or successfully caught its signal. */ #include #include #include class QxtSignalWaiterPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtSignalWaiter) QxtSignalWaiterPrivate() { ready = false; emitted = false; timeout = false; waiting = false; } bool ready, timeout, emitted, waiting; int timerID; void stopTimer() { if (timerID) qxt_p().killTimer(timerID); timerID = 0; waiting = false; } }; /*! * Constructs a QxtSignalWaiter that will wait for \a signal from \a sender ie. sender::signal() * to be emitted. QxtSignalWaiter objects are intended to be created on the stack, therefore no * parent parameter is accepted. */ QxtSignalWaiter::QxtSignalWaiter(const QObject* sender, const char* signal) : QObject(0) { Q_ASSERT(sender && signal); QXT_INIT_PRIVATE(QxtSignalWaiter); connect(sender, signal, this, SLOT(signalCaught())); } /*! * This is an overloaded function provided for convenience. This version can be invoked without first instantiating * a QxtSignalWaiter object. Waits for \a signal from \a sender to be emitted within \a msec while processing events * according to \a flags. Returns \c true if the signal was caught, or \c false if the timeout elapsed. */ bool QxtSignalWaiter::wait(const QObject* sender, const char* signal, int msec, QEventLoop::ProcessEventsFlags flags) { QxtSignalWaiter w(sender, signal); return w.wait(msec, flags); } /*! * Blocks the current function until sender::signal() is emitted. If msec is not -1, wait() will return before the * signal is emitted if the specified number of milliseconds have elapsed. * Returns \c true if the signal was caught, or \c false if the timeout elapsed. * Note that wait() may continue to block after the signal is emitted or the timeout elapses; the function only * guarantees that it will not return BEFORE one of these conditions has occurred. This function is not reentrant. */ bool QxtSignalWaiter::wait(int msec, QEventLoop::ProcessEventsFlags flags) { QxtSignalWaiterPrivate& d = qxt_d(); // Clear the emission status d.ready = false; d.emitted = false; // Check input parameters if (msec < -1 || msec == 0) return false; // activate the timeout if (msec != -1) d.timerID = startTimer(msec); else d.timerID = 0; // Make sure to wait for events flags |= QEventLoop::WaitForMoreEvents; // Begin waiting d.waiting = true; while (!d.ready && !d.timeout) QCoreApplication::processEvents(flags); // Clean up and return status qxt_d().stopTimer(); d.emitted = d.ready; d.waiting = false; return d.ready; } /*! * Returns \c true if the desired signal was emitted during the last wait() call. */ bool QxtSignalWaiter::hasCapturedSignal() const { return qxt_d().emitted; } /*! * Signals a waiting object to stop blocking because the desired signal was emitted. * QxtSignalWaiter::hasCapturedSignal() will return true after this slot is invoked. * Use this slot to allow QxtSignalWaiter to wait for the first of multiple signals. */ void QxtSignalWaiter::signalCaught() { if (!qxt_d().waiting) return; qxt_d().ready = true; qxt_d().stopTimer(); } /*! * \reimp */ void QxtSignalWaiter::timerEvent(QTimerEvent* event) { Q_UNUSED(event); cancelWait(); } /*! * Signals a waiting object to stop blocking because the timeout has elapsed. * QxtSignalWaiter::hasCapturedSignal() will return false after this slot is invoked. * Use this slot to allow QxtSignalWaiter to be interrupted for reasons other than * a timeout. */ void QxtSignalWaiter::cancelWait() { if (!qxt_d().waiting) return; qxt_d().timeout = true; qxt_d().stopTimer(); } libqxt-0.6.2/src/core/qxtsignalwaiter.h000066400000000000000000000036061215241066400201460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSIGNALWAITER_H #define QXTSIGNALWAITER_H #include #include #include class QxtSignalWaiterPrivate; class QXT_CORE_EXPORT QxtSignalWaiter : public QObject { Q_OBJECT QXT_DECLARE_PRIVATE(QxtSignalWaiter) public: QxtSignalWaiter(const QObject* sender, const char* signal); static bool wait(const QObject* sender, const char* signal, int msec = -1, QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); bool wait(int msec = -1, QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents); bool hasCapturedSignal() const; public Q_SLOTS: void signalCaught(); void cancelWait(); private: void timerEvent(QTimerEvent* event); }; #endif libqxt-0.6.2/src/core/qxtslotjob.cpp000066400000000000000000000124601215241066400174620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtslotjob_p.h" /*! \class QxtSlotJob \inmodule QxtCore \brief The QxtSlotJob class executes an arbitrary slot on a QThread. \warning It is essential to understand that the QObject you pass is not safe to use untill done(); is emitted or result() or join() is called. */ /*! execute \a slot from \a precv on \a thread detached returns a QFuture which offers the functions required to get the result. \code QxtFuture f= QxtSlotJob::detach(&thread,&q,SLOT(exec(QString)),Q_ARG(QString, "select NOW();")); \endcode \warning keep your hands of \a recv until you called QFuture::result(); */ QxtFuture QxtSlotJob::detach(QThread * thread, QObject* recv, const char* slot, QGenericArgument p1, QGenericArgument p2, QGenericArgument p3, QGenericArgument p4, QGenericArgument p5, QGenericArgument p6, QGenericArgument p7, QGenericArgument p8, QGenericArgument p9, QGenericArgument p10) { QxtSlotJob * p = new QxtSlotJob(recv, slot, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); connect(p, SIGNAL(done()), p, SLOT(deleteLater())); return p->exec(thread); } /*! Construct a new Job Object that will run \a slot from \a precv with the specified arguments */ QxtSlotJob::QxtSlotJob(QObject* recv, const char* slot, QGenericArgument p1, QGenericArgument p2, QGenericArgument p3, QGenericArgument p4, QGenericArgument p5, QGenericArgument p6, QGenericArgument p7, QGenericArgument p8, QGenericArgument p9, QGenericArgument p10) { qxt_d().f = QxtMetaObject::bind(recv, slot, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); qxt_d().receiver = recv; qxt_d().orginalthread = QThread::currentThread(); connect(this, SIGNAL(done()), this, SLOT(pdone())); } /*! asks for the result of the execution. This calls QxtJob::join() means it will _block_ the current thread untill the Slot has finished execution */ QVariant QxtSlotJob::result() { join(); return qxt_d().r; } /*! execute this job on \a thread \warning keep your hands of the Object you passed until you called result() or join() */ QxtFuture QxtSlotJob::exec(QThread *thread) { qxt_d().receiver->moveToThread(thread); QxtJob::exec(thread); return QxtFuture(this); } void QxtSlotJob::run() { qxt_d().r = qVariantFromValue(qxt_d().f->invoke()); qxt_d().receiver->moveToThread(qxt_d().orginalthread); } void QxtSlotJob::pdone() { emit(done(qxt_d().r)); } /*! \class QxtFuture \inmodule QxtCore \brief The QxtFuture class provides a reference to a future result of a QxtSlotJob */ QxtFuture::QxtFuture(const QxtFuture& other): QObject() { job = other.job; connect(job, SIGNAL(done()), this, SIGNAL(done())); connect(job, SIGNAL(done(QVariant)), this, SIGNAL(done(QVariant))); waiter = new QxtSignalWaiter(job, SIGNAL(done())); } QxtFuture::QxtFuture(QxtSlotJob* j): QObject() { job = j; connect(job, SIGNAL(done()), this, SIGNAL(done())); connect(job, SIGNAL(done(QVariant)), this, SIGNAL(done(QVariant))); waiter = new QxtSignalWaiter(job, SIGNAL(done())); } QxtFuture::~QxtFuture() { delete waiter; } /*! asks for the result of the execution. This calls QxtJob::join() means it will _block_ the current thread untill the Slot has finished execution */ QVariant QxtFuture::joinedResult() { return job->result(); } /*! asks for the result of the execution. waits until the done() signal occurred or return a QVariant() if the timout ocures earlier This uses QxtSignalWaiter so it will _not_ block your current thread. \warning this function is not reentrant. You have been warned */ QVariant QxtFuture::delayedResult(int msec) { if (!waiter->wait(msec, false)) return QVariant(); return job->result(); } libqxt-0.6.2/src/core/qxtslotjob.h000066400000000000000000000070051215241066400171260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSLOTJOB_H #define QXTSLOTJOB_H #include #include #include class QxtSignalWaiter; class QxtSlotJob; class QXT_CORE_EXPORT QxtFuture: public QObject { Q_OBJECT public: QVariant delayedResult(int msec = -1); QVariant joinedResult(); QxtFuture(const QxtFuture& other); ~QxtFuture(); private: friend class QxtSlotJob; QxtFuture(QxtSlotJob* j); QxtSlotJob * job; QxtSignalWaiter * waiter; Q_SIGNALS: void done(); void done(QVariant); }; class QxtSlotJobPrivate; QT_FORWARD_DECLARE_CLASS(QThread) class QXT_CORE_EXPORT QxtSlotJob : public QxtJob { Q_OBJECT public: static QxtFuture detach(QThread * o, QObject* recv, const char* slot, QGenericArgument p1 = QGenericArgument(), QGenericArgument p2 = QGenericArgument(), QGenericArgument p3 = QGenericArgument(), QGenericArgument p4 = QGenericArgument(), QGenericArgument p5 = QGenericArgument(), QGenericArgument p6 = QGenericArgument(), QGenericArgument p7 = QGenericArgument(), QGenericArgument p8 = QGenericArgument(), QGenericArgument p9 = QGenericArgument(), QGenericArgument p10 = QGenericArgument()); QxtSlotJob(QObject* recv, const char* slot, QGenericArgument p1 = QGenericArgument(), QGenericArgument p2 = QGenericArgument(), QGenericArgument p3 = QGenericArgument(), QGenericArgument p4 = QGenericArgument(), QGenericArgument p5 = QGenericArgument(), QGenericArgument p6 = QGenericArgument(), QGenericArgument p7 = QGenericArgument(), QGenericArgument p8 = QGenericArgument(), QGenericArgument p9 = QGenericArgument(), QGenericArgument p10 = QGenericArgument()); QVariant result(); QxtFuture exec(QThread *o); protected: virtual void run(); Q_SIGNALS: void done(QVariant); private: QXT_DECLARE_PRIVATE(QxtSlotJob) ///must not be in pimpl. that's heavy doom when they are both Qobject and one moves to another thread private Q_SLOTS: void pdone(); }; #endif // QXTSLOTJOB_H libqxt-0.6.2/src/core/qxtslotjob_p.h000066400000000000000000000030471215241066400174470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSLOTJOB_P_H #define QXTSLOTJOB_P_H #include "qxtslotjob.h" #include #include class QxtSlotJobPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QxtBoundFunction * f; QVariant r; QThread * orginalthread; QObject * receiver; QXT_DECLARE_PUBLIC(QxtSlotJob) }; #endif // QXTSLOTJOB_P_H libqxt-0.6.2/src/core/qxtslotmapper.cpp000066400000000000000000000155771215241066400202100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtslotmapper.h" #include "qxtmetaobject.h" #include #include #include /*! \class QxtSlotMapper \inmodule QxtCore \brief The QxtSlotMapper class maps signals with a specific parameter value to certain slots. QxtSlotMapper is the counterpart of QSignalMapper. Where QSignalMapper maps a parameterless signal into one that has a parameter based on the sender, QxtSlotMapper maps a signal with a parameter to a specified slot and receiver based on that parameter's value. Different slots on potentially different receivers can be invoked by the same signal, according to that parameter. The parameter comparison is based on QVariant::operator==(). Thus, any built-in Qt type supported by QVariant and QMetaType is supported. \sa QVariant, QMetaType::Type \image qxtslotmapper.png Example usage: \code QxtSlotMapper mapper; mapper.connect(sender, SIGNAL(signal1(int))); mapper.connect(sender, SIGNAL(signal2(QString))); mapper.addMapping(3, receiver1, SLOT(slot1(int))); mapper.addMapping(QString("abc"), receiver2, SLOT(slot2(QString))); \endcode \sa QSignalMapper */ struct QxtSlotMapInfo { QVariant parameter; QPointer receiver; const char* member; }; class QxtSlotMapperPrivate : public QxtPrivate { public: static int checkSignal(const QObject* sender, const char* signal); QList mappings; }; int QxtSlotMapperPrivate::checkSignal(const QObject* sender, const char* signal) { if (!sender || !signal) { qWarning("QxtSlotMapper: Cannot connect %s::%s", sender ? sender->metaObject()->className() : "(null)", (signal && *signal) ? signal+1 : "(null)"); return false; } const QByteArray signalName = QMetaObject::normalizedSignature(signal+1); int signalId = sender->metaObject()->indexOfSignal(signalName); if (signalId < 0) { qWarning("QxtSlotMapper: No such signal %s::%s", sender->metaObject()->className(), signal+1); return false; } return signalId; } /*! Constructs a new QxtSlotMapper with \a parent. */ QxtSlotMapper::QxtSlotMapper(QObject* parent) : QObject(parent) { } /*! Destructs the slot mapper. */ QxtSlotMapper::~QxtSlotMapper() { } /*! Adds mapping from connected signals with \a parameter to \a receiver's \a member. */ void QxtSlotMapper::addMapping(const QVariant& parameter, QObject* receiver, const char* member) { QxtSlotMapInfo mapping = { parameter, receiver, member }; qxt_d().mappings.append(mapping); } /*! Removes mapping from connected signals with \a parameter to \a receiver's \a member. If \a member is \c 0, any mapping with \a parameter to \a receiver is removed. If \a receiver is \c 0, any mapping with \a parameter is removed. */ void QxtSlotMapper::removeMapping(const QVariant& parameter, QObject* receiver, const char* member) { QMutableListIterator it(qxt_d().mappings); while (it.hasNext()) { const QxtSlotMapInfo& info = it.next(); if (info.parameter == parameter) { if ((!receiver || receiver == info.receiver) && (!member || QxtMetaObject::methodName(member) == QxtMetaObject::methodName(info.member))) { it.remove(); } } } } /*! Connects to \a sender's \a signal. Returns \c true if the connection succeeds and \c false otherwise. */ bool QxtSlotMapper::connect(const QObject* sender, const char* signal) { QByteArray signalName = QMetaObject::normalizedSignature(signal); int signalId = QxtSlotMapperPrivate::checkSignal(sender, signal); if (signalId < 0) return false; int index = signalName.indexOf('('); if (index != -1) { QByteArray typeName = signalName.mid(index + 1); int index = typeName.indexOf(')'); if (index != -1) typeName.truncate(index); typeName = QMetaObject::normalizedType(typeName); int type = QMetaType::type(typeName); int methods = metaObject()->methodCount(); return QMetaObject::connect(sender, signalId, this, methods + type); } return false; } /*! \internal */ int QxtSlotMapper::qt_metacall(QMetaObject::Call call, int id, void** arguments) { id = QObject::qt_metacall(call, id, arguments); if (id < 0 || call != QMetaObject::InvokeMetaMethod) return id; QVariant param(id, arguments[1]); foreach (const QxtSlotMapInfo& info, qxt_d().mappings) { if (info.receiver && info.parameter == param) { const QMetaObject* metaObject = info.receiver->metaObject(); int index = metaObject->indexOfMethod(QxtMetaObject::methodSignature(info.member)); if (index != -1) { QMetaMethod method = metaObject->method(index); switch (method.parameterTypes().count()) { case 0: QMetaObject::invokeMethod(info.receiver, QxtMetaObject::methodName(info.member)); break; case 1: QMetaObject::invokeMethod(info.receiver, QxtMetaObject::methodName(info.member), QGenericArgument(QMetaType::typeName(param.type()), arguments[1])); break; default: qWarning("QxtSlotMapper does not support slots with more than one parameter"); break; } } } } return -1; } libqxt-0.6.2/src/core/qxtslotmapper.h000066400000000000000000000034571215241066400176470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSLOTMAPPER_H #define QXTSLOTMAPPER_H #include #include class QxtSlotMapperPrivate; class QXT_CORE_EXPORT QxtSlotMapper : public QObject { QXT_DECLARE_PRIVATE(QxtSlotMapper) public: explicit QxtSlotMapper(QObject* parent = 0); ~QxtSlotMapper(); void addMapping(const QVariant& parameter, QObject* receiver, const char* member); void removeMapping(const QVariant& parameter, QObject* receiver = 0, const char* member = 0); bool connect(const QObject* sender, const char* signal); int qt_metacall(QMetaObject::Call call, int id, void** arguments); }; #endif // QXTSLOTMAPPER_H libqxt-0.6.2/src/core/qxtstdio.cpp000066400000000000000000000071051215241066400171300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtstdio_p.h" #include /*! \class QxtStdio \inmodule QxtCore \brief The QxtStdio class provides QIODevice and QxtPipe support for stdin and stdout including readyRead() signal. perfect as a counter part for QProcess or debug output into a QxtPipe chain \sa QIODevice \sa QxtPipe \bold {Note:} when using this class, the buffers for stdin/stdout will be disabled, and NOT reenabled on destruction */ /*! Constructs a new QxtStdio with \a parent. */ QxtStdio::QxtStdio(QObject * parent): QxtPipe(parent) { QXT_INIT_PRIVATE(QxtStdio); setvbuf(stdin , NULL , _IONBF , 0); setvbuf(stdout , NULL , _IONBF , 0); setOpenMode(QIODevice::ReadWrite); qxt_d().notify = new QSocketNotifier( #ifdef Q_CC_MSVC _fileno(stdin) #else fileno(stdin) #endif , QSocketNotifier::Read, this); QObject::connect(qxt_d().notify, SIGNAL(activated(int)), &qxt_d(), SLOT(activated(int))); } /*! \reimp */ qint64 QxtStdio::writeData(const char * data, qint64 maxSize) { qint64 i = 0; for (;i < maxSize;i++) { char c = *data++; putchar(c); } // emit(bytesWritten (i)); ///FIXME: according to the docs this may not be recoursive. how do i prevent that? return i; } void QxtStdioPrivate::activated(int) { char c = getchar(); if (c == EOF) { #if QT_VERSION >= 0x040400 emit qxt_p().readChannelFinished(); #endif hadeof = true; return; } QByteArray b(1, c); qxt_p().enqueData(b); qxt_p().sendData(b); } /*! Receive \a data. */ void QxtStdio::receiveData(QByteArray data, const QxtPipe *) { writeData(data.data(), data.size()); } /*! \reimp */ bool QxtStdio::waitForReadyRead(int) { if (qxt_d().hadeof) return false; char c = getchar(); if (c == EOF) { #if QT_VERSION >= 0x040400 emit readChannelFinished(); #endif qxt_d().hadeof = true; return false; } QByteArray b(1, c); enqueData(b); sendData(b); return true; } /*!Blocks until EOF is received.*/ void QxtStdio::waitForEOF() { if (qxt_d().hadeof) return; forever { char c = getchar(); if (c == EOF) { #if QT_VERSION >= 0x040400 emit readChannelFinished(); #endif qxt_d().hadeof = true; return; } QByteArray b(1, c); enqueData(b); sendData(b); } } libqxt-0.6.2/src/core/qxtstdio.h000066400000000000000000000032321215241066400165720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSTDIO_H #define QXTSTDIO_H #include #include class QxtStdioPrivate; class QXT_CORE_EXPORT QxtStdio : public QxtPipe { Q_OBJECT QXT_DECLARE_PRIVATE(QxtStdio) public: QxtStdio(QObject * parent = 0); virtual bool waitForReadyRead(int msecs); void waitForEOF(); protected: virtual qint64 writeData(const char * data, qint64 maxSize); virtual void receiveData(QByteArray data, const QxtPipe * sender); }; #endif // QXTSTDIO_H libqxt-0.6.2/src/core/qxtstdio_p.h000066400000000000000000000031171215241066400171130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSTDIO_P_H #define QXTSTDIO_P_H #include "qxtstdio.h" #include class QxtStdioPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtStdio) QxtStdioPrivate() { notify = 0; hadeof = false; } bool hadeof; private: QSocketNotifier * notify; private Q_SLOTS: void activated(int); }; #endif // QXTSTDIO_P_H libqxt-0.6.2/src/core/qxtstdstreambufdevice.cpp000066400000000000000000000047211215241066400216720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtstdstreambufdevice.h" /*! \class QxtStdStreambufDevice \inmodule QxtCore \brief The QxtStdStreambufDevice class provides QIODevice support for std::streambuf \warning does NOT emit the readyRead() signal \sa QIODevice */ /*! \brief creates a QxtStdStreambufDevice using a single stream buffer as in and output */ QxtStdStreambufDevice::QxtStdStreambufDevice(std::streambuf * b, QObject * parent): QIODevice(parent), buff(b) { setOpenMode(QIODevice::ReadWrite); //we don't know the real state buff_w = 0; } /*! \brief creates a QxtStdStreambufDevice using \a r to read and \a w to write */ QxtStdStreambufDevice::QxtStdStreambufDevice(std::streambuf * r, std::streambuf * w, QObject * parent): QIODevice(parent), buff(r), buff_w(w) { setOpenMode(QIODevice::ReadWrite); } /*! \reimp */ bool QxtStdStreambufDevice::isSequential() const { return true;//for now } /*! \reimp */ qint64 QxtStdStreambufDevice::bytesAvailable() const { return buff->in_avail(); } /*! \reimp */ qint64 QxtStdStreambufDevice::readData(char * data, qint64 maxSize) { return buff->sgetn(data, maxSize); } /*! \reimp */ qint64 QxtStdStreambufDevice::writeData(const char * data, qint64 maxSize) { if (buff_w) return buff_w->sputn(data, maxSize); return buff->sputn(data, maxSize); } libqxt-0.6.2/src/core/qxtstdstreambufdevice.h000066400000000000000000000035751215241066400213450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSTDSTREAMBUFDEVICE_H #define QXTSTDSTREAMBUFDEVICE_H #include #include #include #include "qxtglobal.h" class QXT_CORE_EXPORT QxtStdStreambufDevice : public QIODevice { Q_OBJECT public: explicit QxtStdStreambufDevice(std::streambuf *, QObject * parent = 0); QxtStdStreambufDevice(std::streambuf * r, std::streambuf * w, QObject * parent = 0); virtual bool isSequential() const; virtual qint64 bytesAvailable() const; protected: virtual qint64 readData(char * data, qint64 maxSize); virtual qint64 writeData(const char * data, qint64 maxSize); private: std::streambuf * buff; std::streambuf * buff_w; }; #endif // QXTSTDSTREAMBUFDEVICE_H libqxt-0.6.2/src/core/qxttimer.cpp000066400000000000000000000073501215241066400171300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxttimer.h" #include "qxtmetaobject.h" #include #include /*! \class QxtTimer \inmodule QxtCore \brief The QxtTimer class extends QTimer. QxtTimer extends QTimer with capability to call a slot after with given parameters after a given time interval. Example usage: \code QxtTimer::singleShot(500, widget, SLOT(setWindowTitle(QString)), QString("Window Title")); \endcode */ class QxtSingleShotTimer : public QObject { public: QxtSingleShotTimer(int msec, QObject* receiver, const char* member, const QVariantList& args); protected: void timerEvent(QTimerEvent* event); private: QPointer receiver; const char* member; QVariantList args; int timerId; }; QxtSingleShotTimer::QxtSingleShotTimer(int msec, QObject* receiver, const char* member, const QVariantList& args) : receiver(receiver), member(member), args(args), timerId(-1) { timerId = startTimer(msec); } void QxtSingleShotTimer::timerEvent(QTimerEvent* event) { if (event->timerId() == timerId) { QxtMetaObject::invokeMethod(receiver, member, args.at(0), args.at(1), args.at(2), args.at(3), args.at(4), args.at(5), args.at(6), args.at(7), args.at(8), args.at(9)); deleteLater(); } } /*! Constructs a new QxtTimer with \a parent. */ QxtTimer::QxtTimer(QObject* parent) : QTimer(parent) { } /*! Destructs the timer. */ QxtTimer::~QxtTimer() { } /*! This static function calls a slot with given parameters after a given time interval. It is very convenient to use this function because you do not need to bother with a timerEvent or create a local QTimer object. You can pass up to ten arguments (\a arg0, \a arg1, \a arg2, \a arg3, \a arg4, \a arg5, \a arg6, \a arg7, \a arg8 and \a arg9). The \a receiver is the receiving object and the \a member is the slot. The time interval is \a msec milliseconds. */ void QxtTimer::singleShot(int msec, QObject* receiver, const char* member, const QVariant& arg0, const QVariant& arg1, const QVariant& arg2, const QVariant& arg3, const QVariant& arg4, const QVariant& arg5, const QVariant& arg6, const QVariant& arg7, const QVariant& arg8, const QVariant& arg9) { if (receiver && member) { QVariantList args; args << arg0 << arg1 << arg2 << arg3 << arg4 << arg5 << arg6 << arg7 << arg8 << arg9; (void) new QxtSingleShotTimer(msec, receiver, member, args); } } libqxt-0.6.2/src/core/qxttimer.h000066400000000000000000000037561215241066400166030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTIMER_H #define QXTTIMER_H #include #include #include class QXT_CORE_EXPORT QxtTimer : public QTimer { public: explicit QxtTimer(QObject* parent = 0); virtual ~QxtTimer(); using QTimer::singleShot; static void singleShot(int msec, QObject* receiver, const char* member, const QVariant& arg0, const QVariant& arg1 = QVariant(), const QVariant& arg2 = QVariant(), const QVariant& arg3 = QVariant(), const QVariant& arg4 = QVariant(), const QVariant& arg5 = QVariant(), const QVariant& arg6 = QVariant(), const QVariant& arg7 = QVariant(), const QVariant& arg8 = QVariant(), const QVariant& arg9 = QVariant()); }; #endif // QXTTIMER_H libqxt-0.6.2/src/core/qxttypelist.h000066400000000000000000000107051215241066400173300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTYPELIST_H #define QXTTYPELIST_H #include namespace QxtType { struct NoExtend { typedef QxtNull head; enum { length = 0, extends = false }; }; template < typename T1 = QxtNull, typename T2 = QxtNull, typename T3 = QxtNull, typename T4 = QxtNull, typename T5 = QxtNull, typename T6 = QxtNull, typename T7 = QxtNull, typename T8 = QxtNull, typename T9 = QxtNull, typename EXTEND = QxtType::NoExtend > struct QxtTypeList; template struct QxtTypeList { typedef T1 head; typedef QxtTypeList tail; typedef EXTEND extend; enum { length = tail::length + 1, extends = EXTEND::extends }; }; template struct QxtTypeList { typedef typename EXTEND::head head; typedef typename EXTEND::tail tail; typedef EXTEND extend; enum { length = EXTEND::length, extends = EXTEND::extends }; }; template<> struct QxtTypeList { typedef QxtNull extend; enum { length = 0, extends = false }; }; } #ifndef QXT_NO_USING using QxtType::QxtTypeList; #endif #ifndef QXT_NO_MACROS /*! \relates QxtTypeList * Declares a one-column tuple. */ #define Qxt1TypeList(a) QxtTypeList /*! \relates QxtTypeList * Declares a two-column tuple, similar to QPair. */ #define Qxt2TypeList(a, b) QxtTypeList /*! \relates QxtTypeList * Declares a three-column tuple, similar to QxtTriple. */ #define Qxt3TypeList(a, b, c) QxtTypeList /*! \relates QxtTypeList * Declares a four-column tuple. */ #define Qxt4TypeList(a, b, c, d) QxtTypeList /*! \relates QxtTypeList * Declares a five-column tuple. */ #define Qxt5TypeList(a, b, c, d, e) QxtTypeList /*! \relates QxtTypeList * Declares a six-column tuple. */ #define Qxt6TypeList(a, b, c, d, e, f) QxtTypeList /*! \relates QxtTypeList * Declares a seven-column tuple. */ #define Qxt7TypeList(a, b, c, d, e, f, g) QxtTypeList /*! \relates QxtTypeList * Declares an eight-column tuple. */ #define Qxt8TypeList(a, b, c, d, e, f, g, h) QxtTypeList /*! \relates QxtTypeList * Declares a nine-column tuple. */ #define Qxt9TypeList(a, b, c, d, e, f, g, h, i) QxtTypeList /*! \relates QxtTypeList * Declares an extended tuple with ten or more columns. Pay special attention to the syntax of the tenth parameter, which * must be a QxtTypeList, not a storage type. \code QxtLongTypeList(int, int, int, int, int, int, int, int, int, Qxt1TypeList(int)) tuple; // correct way to implement a 10-tuple QxtLongTypeList(int, int, int, int, int, int, int, int, int, int) tuple; // this will produce a (very long) compile-time error \endcode */ #define QxtLongTypeList(a, b, c, d, e, f, g, h, i, extend) QxtTypeList #endif #endif // QXTTYPELIST_H libqxt-0.6.2/src/core/qxtxmlfileloggerengine.cpp000066400000000000000000000116301215241066400220320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtxmlfileloggerengine.h" #include /*! \class QxtXmlFileLoggerEngine \brief The QxtXmlFileLoggerEngine class provides an XML file logger engine. \inmodule QxtCore Example XML log output: \code Unknown error What's going on? Hi there \endcode \sa QxtLogger */ class QxtXmlFileLoggerEnginePrivate : public QxtPrivate { QXT_DECLARE_PUBLIC(QxtXmlFileLoggerEngine) public: QxtXmlFileLoggerEnginePrivate(); QString tab; }; QxtXmlFileLoggerEnginePrivate::QxtXmlFileLoggerEnginePrivate() : tab(" ") { } /*! Constructs an XML file logger engine with \a fileName. */ QxtXmlFileLoggerEngine::QxtXmlFileLoggerEngine(const QString& fileName) : QxtAbstractFileLoggerEngine(fileName, QIODevice::ReadWrite | QIODevice::Unbuffered) { QXT_INIT_PRIVATE(QxtXmlFileLoggerEngine); } /*! \reimp */ void QxtXmlFileLoggerEngine::initLoggerEngine() { QxtAbstractFileLoggerEngine::initLoggerEngine(); // Mkay, we have an open file. We need to check that it's all valid. // at the end of this block of code, we either can't log, or the carat is ready for writing. /* What's going on? */ QIODevice* file = device(); Q_ASSERT(file); if (file->size() == 0) { file->write("\n"); file->write("\n"); file->write(""); } else { QByteArray data = file->read(64); if (!data.startsWith(QByteArray("\n"))) { QFile* ptr_fileTarget = static_cast(file); qxtLog->warning(QString(" is not a valid XML log file.").prepend(ptr_fileTarget->fileName())); killLoggerEngine(); return; } } } /*! \reimp */ void QxtXmlFileLoggerEngine::writeToFile(const QString &level, const QVariantList &messages) { QIODevice* ptr_fileTarget = device(); Q_ASSERT(ptr_fileTarget); ptr_fileTarget->seek(ptr_fileTarget->size() - 6); ptr_fileTarget->write(qxt_d().tab.toUtf8()); ptr_fileTarget->write("write(level.toUtf8()); ptr_fileTarget->write("\" time=\""); ptr_fileTarget->write(QTime::currentTime().toString("hh:mm:ss.zzzz").toUtf8()); ptr_fileTarget->write("\">"); ptr_fileTarget->write("\n"); Q_FOREACH(const QVariant& m, messages) { ptr_fileTarget->write(qxt_d().tab.toUtf8()); ptr_fileTarget->write(qxt_d().tab.toUtf8()); ptr_fileTarget->write(""); ptr_fileTarget->write(toXmlSafeString(m.toString()).toUtf8()); ptr_fileTarget->write("\n"); } ptr_fileTarget->write(qxt_d().tab.toUtf8()); ptr_fileTarget->write(""); ptr_fileTarget->write("\n"); ptr_fileTarget->write(""); } /*! Replaces reserved characters from \a raw with corresponding entities. */ QString QxtXmlFileLoggerEngine::toXmlSafeString(const QString &raw) { /* Reserved characters: < < & & > < ' ' " " Convert ampersands first, then the rest. */ return QByteArray(raw.toUtf8()).replace('&', "&").replace('<', "<").replace('>', ">").replace('\'', "'").replace('"', """); } libqxt-0.6.2/src/core/qxtxmlfileloggerengine.h000066400000000000000000000035621215241066400215040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtCore module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTXMLFILELOGGERENGINE_H #define QXTXMLFILELOGGERENGINE_H #include "qxtloggerengine.h" #include "qxtabstractfileloggerengine.h" #include #include class QxtXmlFileLoggerEnginePrivate; class QXT_CORE_EXPORT QxtXmlFileLoggerEngine : public QxtAbstractFileLoggerEngine { QXT_DECLARE_PRIVATE(QxtXmlFileLoggerEngine) public: QxtXmlFileLoggerEngine(const QString& fileName = QString()); virtual void initLoggerEngine(); protected: virtual void writeToFile(const QString &level, const QVariantList &messages); static QString toXmlSafeString(const QString& unformatted); // because we're using 4.2, this was added in 4.4 }; #endif // QXTXMLFILELOGGERENGINE_H libqxt-0.6.2/src/designer/000077500000000000000000000000001215241066400154125ustar00rootroot00000000000000libqxt-0.6.2/src/designer/designer.pri000066400000000000000000000026571215241066400177400ustar00rootroot00000000000000INCLUDEPATH += $$PWD DEPENDPATH += $$PWD RESOURCES += resources.qrc HEADERS += qxtbasespinboxplugin.h HEADERS += qxtcheckcomboboxplugin.h HEADERS += qxtcountrycomboboxplugin.h HEADERS += qxtdesignerplugin.h HEADERS += qxtdesignerplugins.h HEADERS += qxtflowviewplugin.h HEADERS += qxtgroupboxplugin.h HEADERS += qxtlabelplugin.h HEADERS += qxtlanguagecomboboxplugin.h HEADERS += qxtletterboxwidgetplugin.h HEADERS += qxtlineeditplugin.h HEADERS += qxtlistwidgetplugin.h HEADERS += qxtprogresslabelplugin.h HEADERS += qxtpushbuttonplugin.h HEADERS += qxtspansliderplugin.h HEADERS += qxtstarsplugin.h HEADERS += qxtstringspinboxplugin.h HEADERS += qxttablewidgetplugin.h HEADERS += qxttreewidgetplugin.h SOURCES += qxtbasespinboxplugin.cpp SOURCES += qxtcheckcomboboxplugin.cpp SOURCES += qxtcountrycomboboxplugin.cpp SOURCES += qxtdesignerplugin.cpp SOURCES += qxtdesignerplugins.cpp SOURCES += qxtflowviewplugin.cpp SOURCES += qxtgroupboxplugin.cpp SOURCES += qxtlabelplugin.cpp SOURCES += qxtlanguagecomboboxplugin.cpp SOURCES += qxtletterboxwidgetplugin.cpp SOURCES += qxtlineeditplugin.cpp SOURCES += qxtlistwidgetplugin.cpp SOURCES += qxtprogresslabelplugin.cpp SOURCES += qxtpushbuttonplugin.cpp SOURCES += qxtspansliderplugin.cpp SOURCES += qxtstarsplugin.cpp SOURCES += qxtstringspinboxplugin.cpp SOURCES += qxttablewidgetplugin.cpp SOURCES += qxttreewidgetplugin.cpp libqxt-0.6.2/src/designer/designer.pro000066400000000000000000000004671215241066400177430ustar00rootroot00000000000000CLEAN_TARGET = QxtDesignerPlugins DEFINES += BUILD_QXT_DESIGNER QT = core gui QXT = core gui CONVENIENCE += include(designer.pri) include(../qxtbase.pri) CONFIG += designer plugin target.path = $$[QT_INSTALL_PLUGINS]/designer INSTALLS = target libqxt-0.6.2/src/designer/qxtbasespinboxplugin.cpp000066400000000000000000000031451215241066400224120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtbasespinboxplugin.h" #include "qxtbasespinbox.h" #include QxtBaseSpinBoxPlugin::QxtBaseSpinBoxPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtBaseSpinBox") { } QWidget* QxtBaseSpinBoxPlugin::createWidget(QWidget* parent) { return new QxtBaseSpinBox(parent); } QString QxtBaseSpinBoxPlugin::domXml() const { return ""; } libqxt-0.6.2/src/designer/qxtbasespinboxplugin.h000066400000000000000000000030331215241066400220530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTBASESPINBOXPLUGIN_H #define QXTBASESPINBOXPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtBaseSpinBoxPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtBaseSpinBoxPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTBASESPINBOXPLUGIN_H libqxt-0.6.2/src/designer/qxtcheckcomboboxplugin.cpp000066400000000000000000000036131215241066400227030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtcheckcomboboxplugin.h" #include "qxtcheckcombobox.h" #include QxtCheckComboBoxPlugin::QxtCheckComboBoxPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtCheckComboBox") {} QWidget* QxtCheckComboBoxPlugin::createWidget(QWidget* parent) { return new QxtCheckComboBox(parent); } QString QxtCheckComboBoxPlugin::domXml() const { return "\n" " \n" " \n" " 0\n" " 0\n" " 57\n" " 17\n" " \n" " \n" "\n"; } libqxt-0.6.2/src/designer/qxtcheckcomboboxplugin.h000066400000000000000000000030451215241066400223470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCHECKCOMBOBOXPLUGIN_H #define QXTCHECKCOMBOBOXPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtCheckComboBoxPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtCheckComboBoxPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTCHECKCOMBOBOXPLUGIN_H libqxt-0.6.2/src/designer/qxtcountrycomboboxplugin.cpp000066400000000000000000000036401215241066400233310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtcountrycomboboxplugin.h" #include "qxtcountrycombobox.h" #include QxtCountryComboBoxPlugin::QxtCountryComboBoxPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtCountryComboBox") {} QWidget* QxtCountryComboBoxPlugin::createWidget(QWidget* parent) { return new QxtCountryComboBox(parent); } QString QxtCountryComboBoxPlugin::domXml() const { return "\n" " \n" " \n" " 0\n" " 0\n" " 57\n" " 17\n" " \n" " \n" "\n"; } libqxt-0.6.2/src/designer/qxtcountrycomboboxplugin.h000066400000000000000000000030571215241066400230000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCOUNTRYCOMBOBOXPLUGIN_H #define QXTCOUNTRYCOMBOBOXPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtCountryComboBoxPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtCountryComboBoxPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTCOUNTRYCOMBOBOXPLUGIN_H libqxt-0.6.2/src/designer/qxtdesignerplugin.cpp000066400000000000000000000037051215241066400216770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtdesignerplugin.h" QxtDesignerPlugin::QxtDesignerPlugin(const QString& plugin) : init(false), plugin(plugin) {} QString QxtDesignerPlugin::group() const { return "QxtGui Widgets"; } QIcon QxtDesignerPlugin::icon() const { return QIcon(":/logo.png"); } QString QxtDesignerPlugin::includeFile() const { return plugin; } void QxtDesignerPlugin::initialize(QDesignerFormEditorInterface*) { if (init) return; init = true; } bool QxtDesignerPlugin::isContainer() const { return false; } bool QxtDesignerPlugin::isInitialized() const { return init; } QString QxtDesignerPlugin::name() const { return plugin; } QString QxtDesignerPlugin::toolTip() const { return plugin; } QString QxtDesignerPlugin::whatsThis() const { return plugin; } libqxt-0.6.2/src/designer/qxtdesignerplugin.h000066400000000000000000000034501215241066400213410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTDESIGNERPLUGIN_H #define QXTDESIGNERPLUGIN_H #include class QxtDesignerPlugin : public QDesignerCustomWidgetInterface { Q_INTERFACES(QDesignerCustomWidgetInterface) public: QxtDesignerPlugin(const QString& plugin); QString group() const; QIcon icon() const; QString includeFile() const; void initialize(QDesignerFormEditorInterface*); bool isContainer() const; bool isInitialized() const; QString name() const; QString toolTip() const; QString whatsThis() const; private: bool init; QString plugin; }; #endif // QXTDESIGNERPLUGIN_H libqxt-0.6.2/src/designer/qxtdesignerplugins.cpp000066400000000000000000000050511215241066400220560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtdesignerplugins.h" #include "qxtbasespinboxplugin.h" #include "qxtcheckcomboboxplugin.h" #include "qxtcountrycomboboxplugin.h" #include "qxtgroupboxplugin.h" #include "qxtlabelplugin.h" #include "qxtlanguagecomboboxplugin.h" #include "qxtlistwidgetplugin.h" #include "qxtprogresslabelplugin.h" #include "qxtpushbuttonplugin.h" #include "qxtspansliderplugin.h" #include "qxtstarsplugin.h" #include "qxtstringspinboxplugin.h" #include "qxttablewidgetplugin.h" #include "qxttreewidgetplugin.h" #include "qxtflowviewplugin.h" #include "qxtletterboxwidgetplugin.h" #include "qxtlineeditplugin.h" #include QList QxtDesignerPlugins::customWidgets() const { QList plugins; plugins << new QxtLabelPlugin() << new QxtPushButtonPlugin() << new QxtLineEditPlugin() << new QxtCheckComboBoxPlugin() << new QxtSpanSliderPlugin() << new QxtBaseSpinBoxPlugin() << new QxtStringSpinBoxPlugin() << new QxtGroupBoxPlugin() << new QxtListWidgetPlugin() << new QxtTreeWidgetPlugin() << new QxtTableWidgetPlugin() << new QxtStarsPlugin() << new QxtProgressLabelPlugin() << new QxtCountryComboBoxPlugin() << new QxtLanguageComboBoxPlugin() << new QxtFlowViewPlugin() << new QxtLetterBoxWidgetPlugin(); return plugins; } Q_EXPORT_PLUGIN(QxtDesignerPlugins) libqxt-0.6.2/src/designer/qxtdesignerplugins.h000066400000000000000000000031041215241066400215200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTDESIGNERPLUGINS_H #define QXTDESIGNERPLUGINS_H #include #include class QxtDesignerPlugins : public QObject, public QDesignerCustomWidgetCollectionInterface { Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) public: QList customWidgets() const; }; #endif // QXTDESIGNERPLUGINS_H libqxt-0.6.2/src/designer/qxtflowviewplugin.cpp000066400000000000000000000031061215241066400217340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtflowviewplugin.h" #include "qxtflowview.h" #include QxtFlowViewPlugin::QxtFlowViewPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtFlowView") {} QWidget* QxtFlowViewPlugin::createWidget(QWidget* parent) { return new QxtFlowView(parent); } QString QxtFlowViewPlugin::domXml() const { return ""; } libqxt-0.6.2/src/designer/qxtflowviewplugin.h000066400000000000000000000030031215241066400213750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTFLOWVIEWPLUGIN_H_jasubd #define QXTFLOWVIEWPLUGIN_H_jasubd #include #include "qxtdesignerplugin.h" class QxtFlowViewPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtFlowViewPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif libqxt-0.6.2/src/designer/qxtgroupboxplugin.cpp000066400000000000000000000035321215241066400217420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtgroupboxplugin.h" #include "qxtgroupbox.h" #include QxtGroupBoxPlugin::QxtGroupBoxPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtGroupBox") {} QWidget* QxtGroupBoxPlugin::createWidget(QWidget* parent) { return new QxtGroupBox(parent); } QString QxtGroupBoxPlugin::domXml() const { return "\n" " \n" " \n" " 0\n" " 0\n" " 120\n" " 80\n" " \n" " \n" "\n"; } libqxt-0.6.2/src/designer/qxtgroupboxplugin.h000066400000000000000000000031121215241066400214010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTGROUPBOXPLUGIN_H #define QXTGROUPBOXPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtGroupBoxPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtGroupBoxPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; bool isContainer() const { return true; } }; #endif // QXTGROUPBOXPLUGIN_H libqxt-0.6.2/src/designer/qxtlabelplugin.cpp000066400000000000000000000036541215241066400211610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlabelplugin.h" #include "qxtlabel.h" #include QxtLabelPlugin::QxtLabelPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtLabel") {} QWidget* QxtLabelPlugin::createWidget(QWidget* parent) { return new QxtLabel(parent); } QString QxtLabelPlugin::domXml() const { return "\n" " \n" " \n" " 0\n" " 0\n" " 57\n" " 17\n" " \n" " \n" " \n" " QxtLabel\n" " \n" "\n"; } libqxt-0.6.2/src/designer/qxtlabelplugin.h000066400000000000000000000027751215241066400206310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLABELPLUGIN_H #define QXTLABELPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtLabelPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtLabelPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTLABELPLUGIN_H libqxt-0.6.2/src/designer/qxtlanguagecomboboxplugin.cpp000066400000000000000000000036511215241066400234130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlanguagecomboboxplugin.h" #include "qxtlanguagecombobox.h" #include QxtLanguageComboBoxPlugin::QxtLanguageComboBoxPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtLanguageComboBox") {} QWidget* QxtLanguageComboBoxPlugin::createWidget(QWidget* parent) { return new QxtLanguageComboBox(parent); } QString QxtLanguageComboBoxPlugin::domXml() const { return "\n" " \n" " \n" " 0\n" " 0\n" " 57\n" " 17\n" " \n" " \n" "\n"; } libqxt-0.6.2/src/designer/qxtlanguagecomboboxplugin.h000066400000000000000000000030641215241066400230560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLANGUAGECOMBOBOXPLUGIN_H #define QXTLANGUAGECOMBOBOXPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtLanguageComboBoxPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtLanguageComboBoxPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTLANGUAGECOMBOBOXPLUGIN_H libqxt-0.6.2/src/designer/qxtletterboxwidgetplugin.cpp000066400000000000000000000036411215241066400233120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtletterboxwidgetplugin.h" #include "qxtletterboxwidget.h" #include QxtLetterBoxWidgetPlugin::QxtLetterBoxWidgetPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtLetterBoxWidget") { } QWidget* QxtLetterBoxWidgetPlugin::createWidget(QWidget* parent) { return new QxtLetterBoxWidget(parent); } QString QxtLetterBoxWidgetPlugin::domXml() const { return "\n" " \n" " \n" " 0\n" " 0\n" " 120\n" " 80\n" " \n" " \n" "\n"; } libqxt-0.6.2/src/designer/qxtletterboxwidgetplugin.h000066400000000000000000000030571215241066400227600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLETTERBOXWIDGETPLUGIN_H #define QXTLETTERBOXWIDGETPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtLetterBoxWidgetPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtLetterBoxWidgetPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTLETTERBOXWIDGETPLUGIN_H libqxt-0.6.2/src/designer/qxtlineeditplugin.cpp000066400000000000000000000032301215241066400216650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlineeditplugin.h" #include "qxtlineedit.h" #include QxtLineEditPlugin::QxtLineEditPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtLineEdit") { } QWidget* QxtLineEditPlugin::createWidget(QWidget* parent) { QxtLineEdit* lineEdit = new QxtLineEdit(parent); lineEdit->setSampleText("QxtLineEdit"); return lineEdit; } QString QxtLineEditPlugin::domXml() const { return ""; } libqxt-0.6.2/src/designer/qxtlineeditplugin.h000066400000000000000000000030141215241066400213320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLINEEDITPLUGIN_H #define QXTLINEEDITPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtLineEditPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtLineEditPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTLINEEDITPLUGIN_H libqxt-0.6.2/src/designer/qxtlistwidgetplugin.cpp000066400000000000000000000031321215241066400222500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlistwidgetplugin.h" #include "qxtlistwidget.h" #include QxtListWidgetPlugin::QxtListWidgetPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtListWidget") {} QWidget* QxtListWidgetPlugin::createWidget(QWidget* parent) { return new QxtListWidget(parent); } QString QxtListWidgetPlugin::domXml() const { return ""; } libqxt-0.6.2/src/designer/qxtlistwidgetplugin.h000066400000000000000000000030261215241066400217170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLISTWIDGETPLUGIN_H #define QXTLISTWIDGETPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtListWidgetPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtListWidgetPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTLISTWIDGETPLUGIN_H libqxt-0.6.2/src/designer/qxtprogresslabelplugin.cpp000066400000000000000000000036131215241066400227410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtprogresslabelplugin.h" #include "qxtprogresslabel.h" #include QxtProgressLabelPlugin::QxtProgressLabelPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtProgressLabel") {} QWidget* QxtProgressLabelPlugin::createWidget(QWidget* parent) { return new QxtProgressLabel(parent); } QString QxtProgressLabelPlugin::domXml() const { return "\n" " \n" " \n" " 0\n" " 0\n" " 57\n" " 17\n" " \n" " \n" "\n"; } libqxt-0.6.2/src/designer/qxtprogresslabelplugin.h000066400000000000000000000030451215241066400224050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTPROGRESSLABELPLUGIN_H #define QXTPROGRESSLABELPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtProgressLabelPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtProgressLabelPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTPROGRESSLABELPLUGIN_H libqxt-0.6.2/src/designer/qxtpushbuttonplugin.cpp000066400000000000000000000037431215241066400223140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtpushbuttonplugin.h" #include "qxtpushbutton.h" #include QxtPushButtonPlugin::QxtPushButtonPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtPushButton") {} QWidget* QxtPushButtonPlugin::createWidget(QWidget* parent) { return new QxtPushButton(parent); } QString QxtPushButtonPlugin::domXml() const { return "\n" " \n" " \n" " 0\n" " 0\n" " 105\n" " 27\n" " \n" " \n" " \n" " QxtPushButton\n" " \n" "\n"; } libqxt-0.6.2/src/designer/qxtpushbuttonplugin.h000066400000000000000000000030261215241066400217530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTPUSHBUTTONPLUGIN_H #define QXTPUSHBUTTONPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtPushButtonPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtPushButtonPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTPUSHBUTTONPLUGIN_H libqxt-0.6.2/src/designer/qxtspansliderplugin.cpp000066400000000000000000000031321215241066400222350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtspansliderplugin.h" #include "qxtspanslider.h" #include QxtSpanSliderPlugin::QxtSpanSliderPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtSpanSlider") {} QWidget* QxtSpanSliderPlugin::createWidget(QWidget* parent) { return new QxtSpanSlider(parent); } QString QxtSpanSliderPlugin::domXml() const { return ""; } libqxt-0.6.2/src/designer/qxtspansliderplugin.h000066400000000000000000000030261215241066400217040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSPANSLIDERPLUGIN_H #define QXTSPANSLIDERPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtSpanSliderPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtSpanSliderPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTSPANSLIDERPLUGIN_H libqxt-0.6.2/src/designer/qxtstarsplugin.cpp000066400000000000000000000034731215241066400212350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtstarsplugin.h" #include "qxtstars.h" #include QxtStarsPlugin::QxtStarsPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtStars") {} QWidget* QxtStarsPlugin::createWidget(QWidget* parent) { return new QxtStars(parent); } QString QxtStarsPlugin::domXml() const { return "\n" " \n" " \n" " 0\n" " 0\n" " 57\n" " 17\n" " \n" " \n" "\n"; } libqxt-0.6.2/src/designer/qxtstarsplugin.h000066400000000000000000000027751215241066400207060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSTARSPLUGIN_H #define QXTSTARSPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtStarsPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtStarsPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTSTARSPLUGIN_H libqxt-0.6.2/src/designer/qxtstringspinboxplugin.cpp000066400000000000000000000031701215241066400230040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtstringspinboxplugin.h" #include "qxtstringspinbox.h" #include QxtStringSpinBoxPlugin::QxtStringSpinBoxPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtStringSpinBox") {} QWidget* QxtStringSpinBoxPlugin::createWidget(QWidget* parent) { return new QxtStringSpinBox(parent); } QString QxtStringSpinBoxPlugin::domXml() const { return ""; } libqxt-0.6.2/src/designer/qxtstringspinboxplugin.h000066400000000000000000000030451215241066400224520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSTRINGSPINBOXPLUGIN_H #define QXTSTRINGSPINBOXPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtStringSpinBoxPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtStringSpinBoxPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTSTRINGSPINBOXPLUGIN_H libqxt-0.6.2/src/designer/qxttablewidgetplugin.cpp000066400000000000000000000031441215241066400223670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxttablewidgetplugin.h" #include "qxttablewidget.h" #include QxtTableWidgetPlugin::QxtTableWidgetPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtTableWidget") {} QWidget* QxtTableWidgetPlugin::createWidget(QWidget* parent) { return new QxtTableWidget(parent); } QString QxtTableWidgetPlugin::domXml() const { return ""; } libqxt-0.6.2/src/designer/qxttablewidgetplugin.h000066400000000000000000000030331215241066400220310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTABLEWIDGETPLUGIN_H #define QXTTABLEWIDGETPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtTableWidgetPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtTableWidgetPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTTABLEWIDGETPLUGIN_H libqxt-0.6.2/src/designer/qxttreewidgetplugin.cpp000066400000000000000000000031321215241066400222340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxttreewidgetplugin.h" #include "qxttreewidget.h" #include QxtTreeWidgetPlugin::QxtTreeWidgetPlugin(QObject* parent) : QObject(parent), QxtDesignerPlugin("QxtTreeWidget") {} QWidget* QxtTreeWidgetPlugin::createWidget(QWidget* parent) { return new QxtTreeWidget(parent); } QString QxtTreeWidgetPlugin::domXml() const { return ""; } libqxt-0.6.2/src/designer/qxttreewidgetplugin.h000066400000000000000000000030261215241066400217030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtDesigner module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTREEWIDGETPLUGIN_H #define QXTTREEWIDGETPLUGIN_H #include #include "qxtdesignerplugin.h" class QxtTreeWidgetPlugin : public QObject, public QxtDesignerPlugin { Q_OBJECT public: QxtTreeWidgetPlugin(QObject* parent = 0); QWidget* createWidget(QWidget* parent); QString domXml() const; }; #endif // QXTTREEWIDGETPLUGIN_H libqxt-0.6.2/src/designer/resources.qrc000066400000000000000000000002071215241066400201320ustar00rootroot00000000000000 ../../extras/artwork/logo.png libqxt-0.6.2/src/gui/000077500000000000000000000000001215241066400143765ustar00rootroot00000000000000libqxt-0.6.2/src/gui/gui.pri000066400000000000000000000106671215241066400157100ustar00rootroot00000000000000INCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += qxtbasespinbox.h HEADERS += qxtcheckcombobox.h HEADERS += qxtcheckcombobox_p.h HEADERS += qxtconfigdialog.h HEADERS += qxtconfigdialog_p.h HEADERS += qxtconfigwidget.h HEADERS += qxtconfigwidget_p.h HEADERS += qxtconfirmationmessage.h HEADERS += qxtcountrycombobox.h HEADERS += qxtcountrycombobox_p.h HEADERS += qxtcountrymodel.h HEADERS += qxtcountrymodel_p.h HEADERS += qxtcrumbview.h HEADERS += qxtcrumbview_p.h HEADERS += qxtflowview.h HEADERS += qxtflowview_p.h HEADERS += qxtgui.h HEADERS += qxtgroupbox.h HEADERS += qxtheaderview.h HEADERS += qxtitemdelegate.h HEADERS += qxtitemdelegate_p.h HEADERS += qxtitemeditorcreator.h HEADERS += qxtitemeditorcreatorbase.h HEADERS += qxtlabel.h HEADERS += qxtletterboxwidget.h HEADERS += qxtletterboxwidget_p.h HEADERS += qxtlineedit.h HEADERS += qxtlistwidget.h HEADERS += qxtlistwidget_p.h HEADERS += qxtlistwidgetitem.h HEADERS += qxtlanguagecombobox.h HEADERS += qxtlanguagecombobox_p.h HEADERS += qxtnativeeventfilter.h HEADERS += qxtprogresslabel.h HEADERS += qxtproxystyle.h HEADERS += qxtpushbutton.h HEADERS += qxtspanslider.h HEADERS += qxtspanslider_p.h HEADERS += qxtstandarditemeditorcreator.h HEADERS += qxtstars.h HEADERS += qxtstringspinbox.h HEADERS += qxtstringvalidator.h HEADERS += qxtstringvalidator_p.h HEADERS += qxttablewidget.h HEADERS += qxttablewidget_p.h HEADERS += qxttablewidgetitem.h HEADERS += qxttabwidget.h HEADERS += qxttabwidget_p.h HEADERS += qxttooltip.h HEADERS += qxttooltip_p.h HEADERS += qxttreewidget.h HEADERS += qxttreewidget_p.h HEADERS += qxttreewidgetitem.h HEADERS += qxtscheduleheaderwidget.h HEADERS += qxtscheduleitemdelegate.h HEADERS += qxtscheduleview.h HEADERS += qxtscheduleviewheadermodel_p.h HEADERS += qxtscheduleview_p.h HEADERS += qxtstyleoptionscheduleviewitem.h HEADERS += qxtsortfilterproxymodel.h HEADERS += qxtfilterdialog.h HEADERS += qxtfilterdialog_p.h HEADERS += qxtlookuplineedit.h HEADERS += qxtlookuplineedit_p.h SOURCES += qxtbasespinbox.cpp SOURCES += qxtcheckcombobox.cpp SOURCES += qxtconfigdialog.cpp SOURCES += qxtconfigwidget.cpp SOURCES += qxtconfirmationmessage.cpp SOURCES += qxtcountrymodel.cpp SOURCES += qxtcountrycombobox.cpp SOURCES += qxtcrumbview.cpp SOURCES += qxtflowview.cpp SOURCES += qxtflowview_p.cpp SOURCES += qxtgroupbox.cpp SOURCES += qxtheaderview.cpp SOURCES += qxtitemdelegate.cpp SOURCES += qxtlabel.cpp SOURCES += qxtletterboxwidget.cpp SOURCES += qxtlineedit.cpp SOURCES += qxtlistwidget.cpp SOURCES += qxtlistwidgetitem.cpp SOURCES += qxtlanguagecombobox.cpp SOURCES += qxtprogresslabel.cpp SOURCES += qxtproxystyle.cpp SOURCES += qxtpushbutton.cpp SOURCES += qxtspanslider.cpp SOURCES += qxtstars.cpp SOURCES += qxtstringspinbox.cpp SOURCES += qxtstringvalidator.cpp SOURCES += qxttablewidget.cpp SOURCES += qxttablewidgetitem.cpp SOURCES += qxttabwidget.cpp SOURCES += qxttooltip.cpp SOURCES += qxttreewidget.cpp SOURCES += qxttreewidgetitem.cpp SOURCES += qxtscheduleitemdelegate.cpp SOURCES += qxtscheduleview.cpp SOURCES += qxtscheduleview_p.cpp SOURCES += qxtscheduleviewheadermodel_p.cpp SOURCES += qxtstyleoptionscheduleviewitem.cpp SOURCES += qxtscheduleheaderwidget.cpp SOURCES += qxtsortfilterproxymodel.cpp SOURCES += qxtfilterdialog.cpp SOURCES += qxtlookuplineedit.cpp !qws:!symbian { # QxtApplication, QxtGlobalShortcut, QxtScreen and # QxtWindowSystem are disabled for QWS/Symbian pending implementation HEADERS += qxtapplication.h HEADERS += qxtapplication_p.h HEADERS += qxtglobalshortcut.h HEADERS += qxtglobalshortcut_p.h HEADERS += qxtscreen.h HEADERS += qxtscreen_p.h HEADERS += qxtwindowsystem.h SOURCES += qxtapplication.cpp SOURCES += qxtglobalshortcut.cpp SOURCES += qxtscreen.cpp SOURCES += qxtwindowsystem.cpp unix:!macx { SOURCES += qxtapplication_x11.cpp SOURCES += qxtglobalshortcut_x11.cpp SOURCES += qxtscreen_x11.cpp SOURCES += qxtwindowsystem_x11.cpp } macx { SOURCES += qxtapplication_mac.cpp SOURCES += qxtglobalshortcut_mac.cpp SOURCES -= qxtscreen.cpp qxtwindowsystem.cpp HEADERS -= qxtscreen.h qxtwindowsystem.h } win32 { SOURCES += qxtapplication_win.cpp SOURCES += qxtglobalshortcut_win.cpp SOURCES += qxtscreen_win.cpp SOURCES += qxtwindowsystem_win.cpp } } RESOURCES += resources.qrc libqxt-0.6.2/src/gui/gui.pro000066400000000000000000000011641215241066400157060ustar00rootroot00000000000000CLEAN_TARGET = QxtGui DEFINES += BUILD_QXT_GUI QT = core gui QXT = core CONVENIENCE += $$CLEAN_TARGET include(gui.pri) include(../qxtbase.pri) contains(DEFINES,HAVE_XRANDR){ !win32:LIBS += -lXrandr } win32:LIBS += -luser32 macx:LIBS += -framework Carbon # Debian and derivatives pass --no-undefined to the linker, which # means that each library must explicitly link to all dependencies # than assuming that the application or another library will bring # in the necessary symbols at run time. contains(QMAKE_LFLAGS, "-Wl,--no-undefined"):LIBS += $${QMAKE_LIBS_X11} libqxt-0.6.2/src/gui/qxtapplication.cpp000066400000000000000000000077271215241066400201570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtapplication.h" #include "qxtapplication_p.h" /*! \class QxtApplication \inmodule QxtGui \brief The QxtApplication class is an extended QApplication with support for native event filters. QxtApplication lets you install native event filters. This gives an easy and straightforward access to platform specific native events. \sa QxtNativeEventFilter */ /*! \fn QxtApplication::instance() Returns a pointer to the instance of the application object. A convenience macro \l qxtApp is also available. */ /*! \macro qxtApp \relates QxtApplication \inmodule QxtGui A global pointer referring to the unique application object. It is equivalent to the pointer returned by QxtApplication::instance(). \sa QxtApplication::instance() */ /*! Constructs a new QxtApplication with \a argc and \a argv. \sa QApplication::QApplication() */ QxtApplication::QxtApplication(int& argc, char** argv) : QApplication(argc, argv) { } /*! Constructs a new QxtApplication with \a argc, \a argv and \a GUIenabled. \sa QApplication::QApplication() */ QxtApplication::QxtApplication(int& argc, char** argv, bool GUIenabled) : QApplication(argc, argv, GUIenabled) { } /*! Constructs a new QxtApplication with \a argc, \a argv and \a type. \sa QApplication::QApplication() */ QxtApplication::QxtApplication(int& argc, char** argv, Type type) : QApplication(argc, argv, type) { } /*! Destructs the QxtApplication. \sa QApplication::~QApplication() */ QxtApplication::~QxtApplication() { } /*! Installs a native event \a filter. A native event filter is an object that receives all native events before they reach the application object. The filter can either stop the native event or forward it to the application object. The filter receives native events via its platform specific native event filter function. The native event filter function must return \c true if the event should be filtered, (i.e. stopped); otherwise it must return \c false. If multiple native event filters are installed, the filter that was installed last is activated first. \sa removeNativeEventFilter() */ void QxtApplication::installNativeEventFilter(QxtNativeEventFilter* filter) { if (!filter) return; qxt_d().nativeFilters.removeAll(filter); qxt_d().nativeFilters.prepend(filter); } /*! Removes a native event \a filter. The request is ignored if such a native event filter has not been installed. \sa installNativeEventFilter() */ void QxtApplication::removeNativeEventFilter(QxtNativeEventFilter* filter) { qxt_d().nativeFilters.removeAll(filter); } libqxt-0.6.2/src/gui/qxtapplication.h000066400000000000000000000050271215241066400176130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTAPPLICATION_H #define QXTAPPLICATION_H #include #include "qxtglobal.h" class QxtApplicationPrivate; class QxtNativeEventFilter; #define qxtApp (QxtApplication::instance()) class QXT_GUI_EXPORT QxtApplication : public QApplication { Q_OBJECT QXT_DECLARE_PRIVATE(QxtApplication) public: QxtApplication(int& argc, char** argv); QxtApplication(int& argc, char** argv, bool GUIenabled); QxtApplication(int& argc, char** argv, Type type); #if defined(Q_WS_X11) explicit QxtApplication(Display* display, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); QxtApplication(Display* display, int& argc, char** argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); #endif // Q_WS_X11 virtual ~QxtApplication(); void installNativeEventFilter(QxtNativeEventFilter* filter); void removeNativeEventFilter(QxtNativeEventFilter* filter); #if defined(Q_WS_X11) virtual bool x11EventFilter(XEvent* event); #elif defined(Q_WS_WIN) virtual bool winEventFilter(MSG* msg, long* result); #elif defined(Q_WS_MAC) virtual bool macEventFilter(EventHandlerCallRef caller, EventRef event); #endif // Q_WS_* inline static QxtApplication* instance() { return qobject_cast(QApplication::instance()); } }; #endif // QXTAPPLICATION_H libqxt-0.6.2/src/gui/qxtapplication_mac.cpp000066400000000000000000000031401215241066400207600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtapplication.h" #include "qxtapplication_p.h" #include "qxtnativeeventfilter.h" /*! \reimp */ bool QxtApplication::macEventFilter(EventHandlerCallRef caller, EventRef event) { foreach (QxtNativeEventFilter* filter, qxt_d().nativeFilters) { if (filter && filter->macEventFilter(caller, event)) return true; } return QApplication::macEventFilter(caller, event); } libqxt-0.6.2/src/gui/qxtapplication_p.h000066400000000000000000000030251215241066400201260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTAPPLICATION_P_H #define QXTAPPLICATION_P_H #include #include "qxtapplication.h" class QxtNativeEventFilter; class QxtApplicationPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtApplication) QList nativeFilters; }; #endif // QXTAPPLICATION_P_H libqxt-0.6.2/src/gui/qxtapplication_win.cpp000066400000000000000000000031311215241066400210150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtapplication.h" #include "qxtapplication_p.h" #include "qxtnativeeventfilter.h" /*! \reimp */ bool QxtApplication::winEventFilter(MSG* msg, long* result) { foreach (QxtNativeEventFilter* filter, qxt_d().nativeFilters) { if (filter && filter->winEventFilter(msg, result)) return true; } return QApplication::winEventFilter(msg, result); } libqxt-0.6.2/src/gui/qxtapplication_x11.cpp000066400000000000000000000035661215241066400206450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtapplication.h" #include "qxtapplication_p.h" #include "qxtnativeeventfilter.h" QxtApplication::QxtApplication(Display* display, Qt::HANDLE visual, Qt::HANDLE colormap) : QApplication(display, visual, colormap) { } QxtApplication::QxtApplication(Display* display, int& argc, char** argv, Qt::HANDLE visual, Qt::HANDLE colormap) : QApplication(display, argc, argv, visual, colormap) { } /*! \reimp */ bool QxtApplication::x11EventFilter(XEvent* event) { foreach(QxtNativeEventFilter* filter, qxt_d().nativeFilters) { if (filter && filter->x11EventFilter(event)) return true; } return QApplication::x11EventFilter(event); } libqxt-0.6.2/src/gui/qxtbasespinbox.cpp000066400000000000000000000135041215241066400201570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtbasespinbox.h" class QxtBaseSpinBoxPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtBaseSpinBox) QxtBaseSpinBoxPrivate(); int base; bool upper; }; QxtBaseSpinBoxPrivate::QxtBaseSpinBoxPrivate() : base(10), upper(false) { } /*! \class QxtBaseSpinBox \inmodule QxtGui \brief The QxtBaseSpinBox widget is a spin box with support for numbers in base between \c 2 and \c 36. Example spinbox for hexadecimal input: \code QxtBaseSpinBox* spinBox = new QxtBaseSpinBox(16, this); spinBox->setPrefix("0x"); spinBox->setValue(0xbabe); spinBox->setUpperCase(true); \endcode \image qxtbasespinbox.png "QxtBaseSpinBox in action." \bold {Note:} Notice that QxtBaseSpinBox is not locale-aware. */ /*! \fn QxtBaseSpinBox::baseChanged(int base) This signal is emitted whenever the number \a base has changed. */ /*! Constructs a new QxtBaseSpinBox with \a parent. Base defaults to \c 10. */ QxtBaseSpinBox::QxtBaseSpinBox(QWidget* parent) : QSpinBox(parent) { QXT_INIT_PRIVATE(QxtBaseSpinBox); } /*! Constructs a new QxtBaseSpinBox with \a base and \a parent. */ QxtBaseSpinBox::QxtBaseSpinBox(int base, QWidget* parent) : QSpinBox(parent) { QXT_INIT_PRIVATE(QxtBaseSpinBox); qxt_d().base = base; } /*! Destructs the spin box. */ QxtBaseSpinBox::~QxtBaseSpinBox() { } /*! \reimp */ void QxtBaseSpinBox::fixup(QString& input) const { QString inputWithoutPrefix = input.mid(prefix().length()); inputWithoutPrefix = qxt_d().upper ? inputWithoutPrefix.toUpper() : inputWithoutPrefix.toLower(); input = prefix() + inputWithoutPrefix; } /*! \reimp */ QValidator::State QxtBaseSpinBox::validate(QString& input, int& pos) const { // quick rejects const QString prefix = QSpinBox::prefix(); const QString inputWithoutPrefix = input.mid(prefix.length()); if (pos < prefix.length()) { // do not let modify prefix return QValidator::Invalid; } else if (inputWithoutPrefix.isEmpty()) { // allow empty input => intermediate return QValidator::Intermediate; } // Invalid: input is invalid according to the string list // Intermediate: it is likely that a little more editing will make the input acceptable // Acceptable: the input is valid. Q_UNUSED(pos); bool ok = false; const int min = minimum(); const int max = maximum(); const int number = inputWithoutPrefix.toInt(&ok, qxt_d().base); QValidator::State state = QValidator::Invalid; if (!ok) { // cannot convert => invalid state = QValidator::Invalid; } else if (number >= min && number <= max) { // converts ok, between boundaries => acceptable if case matches if (qxt_d().upper) return (input == prefix + inputWithoutPrefix.toUpper() ? QValidator::Acceptable : QValidator::Intermediate); else return (input == prefix + inputWithoutPrefix.toLower() ? QValidator::Acceptable : QValidator::Intermediate); } else { // converts ok, outside boundaries => intermediate state = QValidator::Intermediate; } return state; } /*! \property QxtBaseSpinBox::base \brief the number base. The base must be between \c 2 and \c 36. The default value is \c 10. */ int QxtBaseSpinBox::base() const { return qxt_d().base; } void QxtBaseSpinBox::setBase(int base) { if (base < 2 || base > 36) qWarning("QxtBaseSpinBox: base must be between 2 and 36"); base = qBound(2, base, 36); if (qxt_d().base != base) { qxt_d().base = base; emit baseChanged(base); setValue(value()); } } /*! \property QxtBaseSpinBox::upperCase \brief whether letters are shown in upper case. Naturally, this applies to only bases which can contain letters. The default value is \c false. */ bool QxtBaseSpinBox::isUpperCase() const { return qxt_d().upper; } void QxtBaseSpinBox::setUpperCase(bool upperCase) { if (qxt_d().upper != upperCase) { qxt_d().upper = upperCase; setValue(value()); } } /*! \reimp */ QString QxtBaseSpinBox::textFromValue(int value) const { QString text = QString::number(value, qxt_d().base); if (qxt_d().upper) return text.toUpper(); return text; } /*! \reimp */ int QxtBaseSpinBox::valueFromText(const QString& text) const { return text.toInt(0, qxt_d().base); } libqxt-0.6.2/src/gui/qxtbasespinbox.h000066400000000000000000000041431215241066400176230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTBASESPINBOX_H #define QXTBASESPINBOX_H #include #include "qxtglobal.h" class QxtBaseSpinBoxPrivate; class QXT_GUI_EXPORT QxtBaseSpinBox : public QSpinBox { Q_OBJECT QXT_DECLARE_PRIVATE(QxtBaseSpinBox) Q_PROPERTY(int base READ base WRITE setBase) Q_PROPERTY(bool upperCase READ isUpperCase WRITE setUpperCase) public: explicit QxtBaseSpinBox(QWidget* parent = 0); explicit QxtBaseSpinBox(int base, QWidget* parent = 0); virtual ~QxtBaseSpinBox(); virtual void fixup(QString& input) const; virtual QValidator::State validate(QString& input, int& pos) const; bool isUpperCase() const; void setUpperCase(bool upperCase); int base() const; public Q_SLOTS: void setBase(int base); Q_SIGNALS: void baseChanged(int base); protected: virtual QString textFromValue(int value) const; virtual int valueFromText(const QString& text) const; }; #endif // QXTBASESPINBOX_H libqxt-0.6.2/src/gui/qxtcheckcombobox.cpp000066400000000000000000000200131215241066400204410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtcheckcombobox.h" #include "qxtcheckcombobox_p.h" #include #include QxtCheckComboBoxPrivate::QxtCheckComboBoxPrivate() : containerMousePress(false) { separator = QLatin1String(","); } bool QxtCheckComboBoxPrivate::eventFilter(QObject* receiver, QEvent* event) { switch (event->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: { QKeyEvent* keyEvent = static_cast(event); if (receiver == &qxt_p() && (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down)) { qxt_p().showPopup(); return true; } else if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Escape) { // it is important to call QComboBox implementation qxt_p().QComboBox::hidePopup(); if (keyEvent->key() != Qt::Key_Escape) return true; } } case QEvent::MouseButtonPress: containerMousePress = (receiver == qxt_p().view()->window()); break; case QEvent::MouseButtonRelease: containerMousePress = false;; break; default: break; } return false; } void QxtCheckComboBoxPrivate::updateCheckedItems() { QStringList items = qxt_p().checkedItems(); if (items.isEmpty()) qxt_p().setEditText(defaultText); else qxt_p().setEditText(items.join(separator)); // TODO: find a way to recalculate a meaningful size hint emit qxt_p().checkedItemsChanged(items); } void QxtCheckComboBoxPrivate::toggleCheckState(int index) { QVariant value = qxt_p().itemData(index, Qt::CheckStateRole); if (value.isValid()) { Qt::CheckState state = static_cast(value.toInt()); qxt_p().setItemData(index, (state == Qt::Unchecked ? Qt::Checked : Qt::Unchecked), Qt::CheckStateRole); } } QxtCheckComboModel::QxtCheckComboModel(QObject* parent) : QStandardItemModel(0, 1, parent) // rows,cols { } Qt::ItemFlags QxtCheckComboModel::flags(const QModelIndex& index) const { return QStandardItemModel::flags(index) | Qt::ItemIsUserCheckable; } QVariant QxtCheckComboModel::data(const QModelIndex& index, int role) const { QVariant value = QStandardItemModel::data(index, role); if (index.isValid() && role == Qt::CheckStateRole && !value.isValid()) value = Qt::Unchecked; return value; } bool QxtCheckComboModel::setData(const QModelIndex& index, const QVariant& value, int role) { bool ok = QStandardItemModel::setData(index, value, role); if (ok && role == Qt::CheckStateRole) { emit dataChanged(index, index); emit checkStateChanged(); } return ok; } /*! \class QxtCheckComboBox \inmodule QxtGui \brief The QxtCheckComboBox widget is an extended QComboBox with checkable items. QxtComboBox is a specialized combo box with checkable items. Checked items are collected together in the line edit. \code QxtCheckComboBox* comboBox = new QxtCheckComboBox(this); comboBox->addItems(...); comboBox->setItemCheckState(2, Qt::Checked); comboBox->setItemCheckState(4, Qt::Checked); // OR comboBox->setCheckedItems(QStringList() << "dolor" << "amet"); \endcode \image qxtcheckcombobox.png "QxtCheckComboBox in Plastique style." */ /*! \fn QxtCheckComboBox::checkedItemsChanged(const QStringList& items) This signal is emitted whenever the checked \a items have been changed. */ /*! Constructs a new QxtCheckComboBox with \a parent. */ QxtCheckComboBox::QxtCheckComboBox(QWidget* parent) : QComboBox(parent) { QXT_INIT_PRIVATE(QxtCheckComboBox); setModel(new QxtCheckComboModel(this)); connect(this, SIGNAL(activated(int)), &qxt_d(), SLOT(toggleCheckState(int))); connect(model(), SIGNAL(checkStateChanged()), &qxt_d(), SLOT(updateCheckedItems())); connect(model(), SIGNAL(rowsInserted(const QModelIndex &, int, int)), &qxt_d(), SLOT(updateCheckedItems())); connect(model(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)), &qxt_d(), SLOT(updateCheckedItems())); // read-only contents QLineEdit* lineEdit = new QLineEdit(this); lineEdit->setReadOnly(true); setLineEdit(lineEdit); lineEdit->disconnect(this); setInsertPolicy(QComboBox::NoInsert); view()->installEventFilter(&qxt_d()); view()->window()->installEventFilter(&qxt_d()); view()->viewport()->installEventFilter(&qxt_d()); this->installEventFilter(&qxt_d()); } /*! Destructs the combo box. */ QxtCheckComboBox::~QxtCheckComboBox() { } /*! \reimp */ void QxtCheckComboBox::hidePopup() { if (qxt_d().containerMousePress) QComboBox::hidePopup(); } /*! Returns the check state of the item at \a index. */ Qt::CheckState QxtCheckComboBox::itemCheckState(int index) const { return static_cast(itemData(index, Qt::CheckStateRole).toInt()); } /*! Sets the check \a state of the item at \a index. */ void QxtCheckComboBox::setItemCheckState(int index, Qt::CheckState state) { setItemData(index, state, Qt::CheckStateRole); } /*! \property QxtCheckComboBox::checkedItems \brief the checked items. */ QStringList QxtCheckComboBox::checkedItems() const { QStringList items; if (model()) { QModelIndex index = model()->index(0, modelColumn(), rootModelIndex()); QModelIndexList indexes = model()->match(index, Qt::CheckStateRole, Qt::Checked, -1, Qt::MatchExactly); foreach(const QModelIndex& index, indexes) items += index.data().toString(); } return items; } void QxtCheckComboBox::setCheckedItems(const QStringList& items) { // not the most efficient solution but most likely nobody // will put too many items into a combo box anyway so... foreach(const QString& text, items) { const int index = findText(text); setItemCheckState(index, index != -1 ? Qt::Checked : Qt::Unchecked); } } /*! \property QxtCheckComboBox::defaultText \brief the default text. The default text is shown when there are no checked items. The default value is an empty string. */ QString QxtCheckComboBox::defaultText() const { return qxt_d().defaultText; } void QxtCheckComboBox::setDefaultText(const QString& text) { if (qxt_d().defaultText != text) { qxt_d().defaultText = text; qxt_d().updateCheckedItems(); } } /*! \property QxtCheckComboBox::separator \brief the default separator. The checked items are joined together with the separator string. The default value is a comma (","). */ QString QxtCheckComboBox::separator() const { return qxt_d().separator; } void QxtCheckComboBox::setSeparator(const QString& separator) { if (qxt_d().separator != separator) { qxt_d().separator = separator; qxt_d().updateCheckedItems(); } } libqxt-0.6.2/src/gui/qxtcheckcombobox.h000066400000000000000000000043711215241066400201170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCHECKCOMBOBOX_H #define QXTCHECKCOMBOBOX_H #include #include "qxtnamespace.h" #include "qxtglobal.h" class QxtCheckComboBoxPrivate; class QXT_GUI_EXPORT QxtCheckComboBox : public QComboBox { Q_OBJECT QXT_DECLARE_PRIVATE(QxtCheckComboBox) Q_PROPERTY(QString separator READ separator WRITE setSeparator) Q_PROPERTY(QString defaultText READ defaultText WRITE setDefaultText) Q_PROPERTY(QStringList checkedItems READ checkedItems WRITE setCheckedItems) public: explicit QxtCheckComboBox(QWidget* parent = 0); virtual ~QxtCheckComboBox(); virtual void hidePopup(); QString defaultText() const; void setDefaultText(const QString& text); Qt::CheckState itemCheckState(int index) const; void setItemCheckState(int index, Qt::CheckState state); QString separator() const; void setSeparator(const QString& separator); QStringList checkedItems() const; public Q_SLOTS: void setCheckedItems(const QStringList& items); Q_SIGNALS: void checkedItemsChanged(const QStringList& items); }; #endif // QXTCHECKCOMBOBOX_H libqxt-0.6.2/src/gui/qxtcheckcombobox_p.h000066400000000000000000000042271215241066400204360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCHECKCOMBOBOX_P_H #define QXTCHECKCOMBOBOX_P_H #include #include #include "qxtcheckcombobox.h" class QxtCheckComboModel : public QStandardItemModel { Q_OBJECT public: explicit QxtCheckComboModel(QObject* parent = 0); virtual Qt::ItemFlags flags(const QModelIndex& index) const; virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); Q_SIGNALS: void checkStateChanged(); }; class QxtCheckComboBoxPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtCheckComboBox) QxtCheckComboBoxPrivate(); bool eventFilter(QObject* receiver, QEvent* event); QString separator; QString defaultText; bool containerMousePress; public Q_SLOTS: void updateCheckedItems(); void toggleCheckState(int index); }; #endif // QXTCHECKCOMBOBOX_P_H libqxt-0.6.2/src/gui/qxtconfigdialog.cpp000066400000000000000000000124531215241066400202710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtconfigdialog_p.h" #include "qxtconfigdialog.h" #include "qxtconfigwidget.h" #include #include #include void QxtConfigDialogPrivate::init( QxtConfigWidget::IconPosition pos ) { QxtConfigDialog* p = &qxt_p(); configWidget = new QxtConfigWidget(pos); buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, p); QObject::connect(buttons, SIGNAL(accepted()), p, SLOT(accept())); QObject::connect(buttons, SIGNAL(rejected()), p, SLOT(reject())); layout = new QVBoxLayout(p); layout->addWidget(configWidget); layout->addWidget(buttons); } /*! \class QxtConfigDialog \inmodule QxtGui \brief The QxtConfigDialog class provides a configuration dialog. QxtConfigDialog provides a convenient interface for building common configuration dialogs. QxtConfigDialog consists of a list of icons and a stack of pages. Example usage: \code QxtConfigDialog dialog; dialog.configWidget()->addPage(new ConfigurationPage(&dialog), QIcon(":/images/config.png"), tr("Configuration")); dialog.configWidget()->addPage(new UpdatePage(&dialog), QIcon(":/images/update.png"), tr("Update")); dialog.configWidget()->addPage(new QueryPage(&dialog), QIcon(":/images/query.png"), tr("Query")); dialog.exec(); \endcode \image qxtconfigdialog.png "QxtConfigDialog with page icons on the left (QxtConfigDialog::West)." \sa QxtConfigWidget */ /*! \fn QxtConfigDialog::currentIndexChanged(int index) This signal is emitted whenever the current page \a index changes. \sa currentIndex() */ /*! Constructs a new QxtConfigDialog with \a parent and \a flags. */ QxtConfigDialog::QxtConfigDialog(QWidget* parent, Qt::WindowFlags flags) : QDialog(parent, flags) { QXT_INIT_PRIVATE(QxtConfigDialog); qxt_d().init(QxtConfigWidget::West); } /*! Constructs a new QxtConfigDialog with icon \a position, \a parent and \a flags. */ QxtConfigDialog::QxtConfigDialog(QxtConfigWidget::IconPosition position, QWidget* parent, Qt::WindowFlags flags) : QDialog(parent, flags) { QXT_INIT_PRIVATE(QxtConfigDialog); qxt_d().init(position); } /*! Destructs the config dialog. */ QxtConfigDialog::~QxtConfigDialog() { } /*! Returns the dialog button box. The default buttons are QDialogButtonBox::Ok and QDialogButtonBox::Cancel. \sa setDialogButtonBox() */ QDialogButtonBox* QxtConfigDialog::dialogButtonBox() const { return qxt_d().buttons; } /*! Sets the dialog \a buttonBox. The previous button box is deleted if the parent equals \c this. \sa dialogButtonBox() */ void QxtConfigDialog::setDialogButtonBox(QDialogButtonBox* buttonBox) { if (qxt_d().buttons != buttonBox) { if (qxt_d().buttons && qxt_d().buttons->parent() == this) delete qxt_d().buttons; qxt_d().buttons = buttonBox; if (qxt_d().buttons) qxt_d().layout->addWidget(qxt_d().buttons); } } /*! Returns the config widget. \sa setConfigWidget() */ QxtConfigWidget* QxtConfigDialog::configWidget() const { return qxt_d().configWidget; } /*! Sets the \a configWidget. The previous config widget is deleted if the parent equals \c this. \sa configWidget() */ void QxtConfigDialog::setConfigWidget(QxtConfigWidget* configWidget) { if (qxt_d().configWidget != configWidget) { if (qxt_d().configWidget && qxt_d().configWidget->parent() == this) qxt_d().configWidget->deleteLater(); qxt_d().configWidget = configWidget; if (qxt_d().configWidget) qxt_d().layout->insertWidget(0, qxt_d().configWidget); } } /*! \bold {Note:} The default implementation calls SLOT(accept()) of each page page provided that such slot exists. \sa reject() */ void QxtConfigDialog::accept() { qxt_d().configWidget->accept(); QDialog::accept(); } /*! \bold {Note:} The default implementation calls SLOT(reject()) of each page provided that such slot exists. \sa accept() */ void QxtConfigDialog::reject() { qxt_d().configWidget->reject(); QDialog::reject(); } libqxt-0.6.2/src/gui/qxtconfigdialog.h000066400000000000000000000040011215241066400177240ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCONFIGDIALOG_H #define QXTCONFIGDIALOG_H #include #include #include QT_FORWARD_DECLARE_CLASS(QDialogButtonBox) class QxtConfigDialogPrivate; class QXT_GUI_EXPORT QxtConfigDialog : public QDialog { Q_OBJECT QXT_DECLARE_PRIVATE(QxtConfigDialog) public: explicit QxtConfigDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0); explicit QxtConfigDialog(QxtConfigWidget::IconPosition position, QWidget* parent = 0, Qt::WindowFlags flags = 0); virtual ~QxtConfigDialog(); QDialogButtonBox* dialogButtonBox() const; void setDialogButtonBox(QDialogButtonBox* buttonBox); QxtConfigWidget* configWidget() const; void setConfigWidget(QxtConfigWidget* configWidget); public Q_SLOTS: virtual void accept(); virtual void reject(); }; #endif // QXTCONFIGDIALOG_H libqxt-0.6.2/src/gui/qxtconfigdialog_p.h000066400000000000000000000033761215241066400202610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCONFIGDIALOG_P_H #define QXTCONFIGDIALOG_P_H #include "qxtconfigwidget.h" #include "qxtconfigdialog.h" QT_FORWARD_DECLARE_CLASS(QDialogButtonBox) QT_FORWARD_DECLARE_CLASS(QWidget) QT_FORWARD_DECLARE_CLASS(QxtConfigWidget) QT_FORWARD_DECLARE_CLASS(QVBoxLayout) class QxtConfigDialogPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtConfigDialog) void init( QxtConfigWidget::IconPosition pos ); QDialogButtonBox* buttons; QxtConfigWidget* configWidget; QVBoxLayout* layout; }; #endif // QXTCONFIGDIALOG_P_H libqxt-0.6.2/src/gui/qxtconfigwidget.cpp000066400000000000000000000463761215241066400203300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtconfigwidget.h" #include "qxtconfigwidget_p.h" #include #include #include #include #include #include #include QxtConfigTableWidget::QxtConfigTableWidget(QWidget* parent) : QTableWidget(parent) { int pm = style()->pixelMetric(QStyle::PM_LargeIconSize); setIconSize(QSize(pm, pm)); setItemDelegate(new QxtConfigDelegate(this)); viewport()->setAttribute(Qt::WA_Hover, true); } QStyleOptionViewItem QxtConfigTableWidget::viewOptions() const { QStyleOptionViewItem option = QTableWidget::viewOptions(); option.displayAlignment = Qt::AlignHCenter | Qt::AlignTop; option.decorationAlignment = Qt::AlignHCenter | Qt::AlignTop; option.decorationPosition = QStyleOptionViewItem::Top; option.showDecorationSelected = false; return option; } QSize QxtConfigTableWidget::sizeHint() const { return QSize(sizeHintForColumn(0), sizeHintForRow(0)); } bool QxtConfigTableWidget::hasHoverEffect() const { return static_cast(itemDelegate())->hover; } void QxtConfigTableWidget::setHoverEffect(bool enabled) { static_cast(itemDelegate())->hover = enabled; } QxtConfigDelegate::QxtConfigDelegate(QObject* parent) : QItemDelegate(parent), hover(true) { } void QxtConfigDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QStyleOptionViewItem opt = option; if (hover) { QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled; if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)) cg = QPalette::Inactive; if (option.state & QStyle::State_Selected) painter->fillRect(opt.rect, option.palette.brush(cg, QPalette::Highlight)); else if ((option.state & QStyle::State_MouseOver) && (option.state & QStyle::State_Enabled)) { QColor color = option.palette.color(cg, QPalette::Highlight).light(); if (color == option.palette.color(cg, QPalette::Base)) color = option.palette.color(cg, QPalette::AlternateBase); painter->fillRect(opt.rect, color); } else painter->fillRect(opt.rect, option.palette.brush(cg, QPalette::Base)); opt.showDecorationSelected = false; opt.state &= ~QStyle::State_HasFocus; opt.state &= ~QStyle::State_Selected; } QItemDelegate::paint(painter, opt, index); } QSize QxtConfigDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { int margin = qApp->style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1; int textWidth = option.fontMetrics.width(index.data().toString()); int width = qMax(textWidth, option.decorationSize.width()) + 2 * margin; int height = option.fontMetrics.height() + option.decorationSize.height() + margin; return QSize(width, height); } void QxtConfigWidgetPrivate::init(QxtConfigWidget::IconPosition position) { QxtConfigWidget* p = &qxt_p(); splitter = new QSplitter(p); stack = new QStackedWidget(p); table = new QxtConfigTableWidget(p); pos = position; QObject::connect(table, SIGNAL(currentCellChanged(int, int, int, int)), this, SLOT(setCurrentIndex(int, int))); QObject::connect(stack, SIGNAL(currentChanged(int)), p, SIGNAL(currentIndexChanged(int))); QVBoxLayout* layout = new QVBoxLayout(p); layout->addWidget(splitter); initTable(); relayout(); } void QxtConfigWidgetPrivate::initTable() { table->horizontalHeader()->hide(); table->verticalHeader()->hide(); table->setEditTriggers(QAbstractItemView::NoEditTriggers); table->setTabKeyNavigation(true); table->setAcceptDrops(false); table->setDragEnabled(false); table->setShowGrid(false); table->setSelectionMode(QAbstractItemView::SingleSelection); } void QxtConfigWidgetPrivate::relayout() { if (pos == QxtConfigWidget::North) { splitter->setOrientation(Qt::Vertical); table->setRowCount(1); table->setColumnCount(0); table->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); table->verticalHeader()->setResizeMode(QHeaderView::Stretch); table->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } else { splitter->setOrientation(Qt::Horizontal); table->setRowCount(0); table->setColumnCount(1); table->horizontalHeader()->setResizeMode(QHeaderView::Stretch); table->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents); table->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); table->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); } // clear for (int i = splitter->count() - 1; i >= 0; --i) { splitter->widget(i)->setParent(0); } // relayout switch (pos) { case QxtConfigWidget::North: // +-----------+ // | Icons | // +-----------| // | Stack | // +-----------| splitter->addWidget(table); splitter->addWidget(stack); break; case QxtConfigWidget::West: // +---+-------+ // | I | | // | c | | // | o | Stack | // | n | | // | s | | // +---+-------+ splitter->addWidget(table); splitter->addWidget(stack); break; case QxtConfigWidget::East: // +-------+---+ // | | I | // | | c | // | Stack | o | // | | n | // | | s | // +-------+---+ splitter->addWidget(stack); splitter->addWidget(table); break; default: qWarning("QxtConfigWidgetPrivate::relayout(): unknown position"); break; } } QTableWidgetItem* QxtConfigWidgetPrivate::item(int index) const { return pos == QxtConfigWidget::North ? table->item(0, index) : table->item(index, 0); } void QxtConfigWidgetPrivate::setCurrentIndex(int row, int column) { if (pos == QxtConfigWidget::North) setCurrentIndex(column); else setCurrentIndex(row); } void QxtConfigWidgetPrivate::setCurrentIndex(int index) { int previousIndex = stack->currentIndex(); if (previousIndex != -1 && previousIndex != index) qxt_p().cleanupPage(previousIndex); stack->setCurrentIndex(index); table->setCurrentItem(item(index)); if (index != -1) qxt_p().initializePage(index); } /*! \class QxtConfigWidget \inmodule QxtGui \brief The QxtConfigWidget class provides a configuration widget. QxtConfigWidget provides a convenient interface for building common configuration views. QxtConfigWidget consists of a list of icons and a stack of pages. \sa QxtConfigDialog */ /*! \enum QxtConfigWidget::IconPosition This enum describes the page icon position. \value North The icons are located above the pages. \value West The icons are located to the left of the pages. \value East The icons are located to the right of the pages. */ /*! \fn QxtConfigWidget::currentIndexChanged(int index) This signal is emitted whenever the current page \a index changes. \sa currentIndex() */ /*! Constructs a new QxtConfigWidget with \a parent and \a flags. */ QxtConfigWidget::QxtConfigWidget(QWidget* parent, Qt::WindowFlags flags) : QWidget(parent, flags) { QXT_INIT_PRIVATE(QxtConfigWidget); qxt_d().init(); } /*! Constructs a new QxtConfigWidget with icon \a position, \a parent and \a flags. */ QxtConfigWidget::QxtConfigWidget(QxtConfigWidget::IconPosition position, QWidget* parent, Qt::WindowFlags flags) : QWidget(parent, flags) { QXT_INIT_PRIVATE(QxtConfigWidget); qxt_d().init(position); } /*! Destructs the config widget. */ QxtConfigWidget::~QxtConfigWidget() { } /*! \property QxtConfigWidget::hoverEffect \brief whether a hover effect is shown for page icons The default value is \c true. \bold {Note:} Hovered (but not selected) icons are highlighted with lightened QPalette::Highlight (whereas selected icons are highlighted with QPalette::Highlight). In case lightened QPalette::Highlight ends up same as QPalette::Base, QPalette::AlternateBase is used as a fallback color for the hover effect. This usually happens when QPalette::Highlight already is a light color (eg. light gray). */ bool QxtConfigWidget::hasHoverEffect() const { return qxt_d().table->hasHoverEffect(); } void QxtConfigWidget::setHoverEffect(bool enabled) { qxt_d().table->setHoverEffect(enabled); } /*! \property QxtConfigWidget::iconPosition \brief the position of page icons */ QxtConfigWidget::IconPosition QxtConfigWidget::iconPosition() const { return qxt_d().pos; } void QxtConfigWidget::setIconPosition(QxtConfigWidget::IconPosition position) { if (qxt_d().pos != position) { qxt_d().pos = position; qxt_d().relayout(); } } /*! \property QxtConfigWidget::iconSize \brief the size of page icons */ QSize QxtConfigWidget::iconSize() const { return qxt_d().table->iconSize(); } void QxtConfigWidget::setIconSize(const QSize& size) { qxt_d().table->setIconSize(size); } /*! Adds a \a page with \a icon and \a title. In case \a title is an empty string, QWidget::windowTitle of \a page is used. Returns the index of added page. \warning Adding and removing pages dynamically at run time might cause flicker. \sa insertPage() */ int QxtConfigWidget::addPage(QWidget* page, const QIcon& icon, const QString& title) { return insertPage(-1, page, icon, title); } /*! Inserts a \a page with \a icon and \a title at \a index. In case \a title is an empty string, QWidget::windowTitle of \a page is used. Returns the index of inserted page. \warning Inserting and removing pages dynamically at run time might cause flicker. \sa addPage() */ int QxtConfigWidget::insertPage(int index, QWidget* page, const QIcon& icon, const QString& title) { if (!page) { qWarning("QxtConfigWidget::insertPage(): Attempt to insert null page"); return -1; } index = qxt_d().stack->insertWidget(index, page); const QString label = !title.isEmpty() ? title : page->windowTitle(); if (label.isEmpty()) qWarning("QxtConfigWidget::insertPage(): Inserting a page with an empty title"); QTableWidgetItem* item = new QTableWidgetItem(icon, label); item->setToolTip(label); if (qxt_d().pos == QxtConfigWidget::North) { qxt_d().table->model()->insertColumn(index); qxt_d().table->setItem(0, index, item); qxt_d().table->resizeRowToContents(0); } else { qxt_d().table->model()->insertRow(index); qxt_d().table->setItem(index, 0, item); qxt_d().table->resizeColumnToContents(0); } qxt_d().table->updateGeometry(); return index; } /*! Removes the page at \a index and returns it. \bold {Note:} Does not delete the page widget. */ QWidget* QxtConfigWidget::takePage(int index) { if (QWidget* page = qxt_d().stack->widget(index)) { qxt_d().stack->removeWidget(page); delete qxt_d().item(index); return page; } else { qWarning("QxtConfigWidget::removePage(): Unknown index"); return 0; } } /*! \property QxtConfigWidget::count \brief the number of pages */ int QxtConfigWidget::count() const { return qxt_d().stack->count(); } /*! \property QxtConfigWidget::currentIndex \brief the index of current page */ int QxtConfigWidget::currentIndex() const { return qxt_d().stack->currentIndex(); } void QxtConfigWidget::setCurrentIndex(int index) { qxt_d().setCurrentIndex(index); } /*! Returns the current page. \sa currentIndex(), setCurrentPage() */ QWidget* QxtConfigWidget::currentPage() const { return qxt_d().stack->currentWidget(); } /*! Sets the current \a page. \sa currentPage(), currentIndex() */ void QxtConfigWidget::setCurrentPage(QWidget* page) { qxt_d().setCurrentIndex(qxt_d().stack->indexOf(page)); } /*! Returns the index of \a page or \c -1 if the page is unknown. */ int QxtConfigWidget::indexOf(QWidget* page) const { return qxt_d().stack->indexOf(page); } /*! Returns the page at \a index or \c 0 if the \a index is out of range. */ QWidget* QxtConfigWidget::page(int index) const { return qxt_d().stack->widget(index); } /*! Returns \c true if the page at \a index is enabled; otherwise \c false. \sa setPageEnabled() */ bool QxtConfigWidget::isPageEnabled(int index) const { const QWidget* widget = page(index); return widget && widget->isEnabled(); } /*! Sets the page at \a index \a enabled. The corresponding page icon is also \a enabled. \sa isPageEnabled() */ void QxtConfigWidget::setPageEnabled(int index, bool enabled) { QWidget* page = qxt_d().stack->widget(index); QTableWidgetItem* item = qxt_d().item(index); if (page && item) { page->setEnabled(enabled); if (enabled) item->setFlags(item->flags() | Qt::ItemIsEnabled); else item->setFlags(item->flags() & ~Qt::ItemIsEnabled); } else { qWarning("QxtConfigWidget::setPageEnabled(): Unknown index"); } } /*! Returns \c true if the page at \a index is hidden; otherwise \c false. \sa setPageHidden() */ bool QxtConfigWidget::isPageHidden(int index) const { if (qxt_d().pos == QxtConfigWidget::North) return qxt_d().table->isColumnHidden(index); return qxt_d().table->isRowHidden(index); } /*! Sets the page at \a index \a hidden. The corresponding page icon is also \a hidden. \sa isPageHidden() */ void QxtConfigWidget::setPageHidden(int index, bool hidden) { if (qxt_d().pos == QxtConfigWidget::North) qxt_d().table->setColumnHidden(index, hidden); else qxt_d().table->setRowHidden(index, hidden); } /*! Returns the icon of page at \a index. \sa setPageIcon() */ QIcon QxtConfigWidget::pageIcon(int index) const { const QTableWidgetItem* item = qxt_d().item(index); return (item ? item->icon() : QIcon()); } /*! Sets the \a icon of page at \a index. \sa pageIcon() */ void QxtConfigWidget::setPageIcon(int index, const QIcon& icon) { QTableWidgetItem* item = qxt_d().item(index); if (item) { item->setIcon(icon); } else { qWarning("QxtConfigWidget::setPageIcon(): Unknown index"); } } /*! Returns the title of page at \a index. \sa setPageTitle() */ QString QxtConfigWidget::pageTitle(int index) const { const QTableWidgetItem* item = qxt_d().item(index); return (item ? item->text() : QString()); } /*! Sets the \a title of page at \a index. \sa pageTitle() */ void QxtConfigWidget::setPageTitle(int index, const QString& title) { QTableWidgetItem* item = qxt_d().item(index); if (item) { item->setText(title); } else { qWarning("QxtConfigWidget::setPageTitle(): Unknown index"); } } /*! Returns the tooltip of page at \a index. \sa setPageToolTip() */ QString QxtConfigWidget::pageToolTip(int index) const { const QTableWidgetItem* item = qxt_d().item(index); return (item ? item->toolTip() : QString()); } /*! Sets the \a tooltip of page at \a index. \sa pageToolTip() */ void QxtConfigWidget::setPageToolTip(int index, const QString& tooltip) { QTableWidgetItem* item = qxt_d().item(index); if (item) { item->setToolTip(tooltip); } else { qWarning("QxtConfigWidget::setPageToolTip(): Unknown index"); } } /*! Returns the what's this of page at \a index. \sa setPageWhatsThis() */ QString QxtConfigWidget::pageWhatsThis(int index) const { const QTableWidgetItem* item = qxt_d().item(index); return (item ? item->whatsThis() : QString()); } /*! Sets the \a whatsthis of page at \a index. \sa pageWhatsThis() */ void QxtConfigWidget::setPageWhatsThis(int index, const QString& whatsthis) { QTableWidgetItem* item = qxt_d().item(index); if (item) { item->setWhatsThis(whatsthis); } else { qWarning("QxtConfigWidget::setPageWhatsThis(): Unknown index"); } } /*! \bold {Note:} The default implementation calls SLOT(accept()) of each page page provided that such slot exists. \sa reject() */ void QxtConfigWidget::accept() { Q_ASSERT(qxt_d().stack); for (int i = 0; i < qxt_d().stack->count(); ++i) { QMetaObject::invokeMethod(qxt_d().stack->widget(i), "accept"); } } /*! \bold {Note:} The default implementation calls SLOT(reject()) of each page provided that such slot exists. \sa accept() */ void QxtConfigWidget::reject() { Q_ASSERT(qxt_d().stack); for (int i = 0; i < qxt_d().stack->count(); ++i) { QMetaObject::invokeMethod(qxt_d().stack->widget(i), "reject"); } } /*! Returns the internal table widget used for showing page icons. \sa stackedWidget() */ QTableWidget* QxtConfigWidget::tableWidget() const { return qxt_d().table; } /*! Returns the internal stacked widget used for stacking pages. \sa tableWidget() */ QStackedWidget* QxtConfigWidget::stackedWidget() const { return qxt_d().stack; } /*! This virtual function is called to clean up previous page at \a index before switching to a new page. \bold {Note:} The default implementation calls SLOT(cleanup()) of the corresponding page provided that such slot exists. \sa initializePage() */ void QxtConfigWidget::cleanupPage(int index) { Q_ASSERT(qxt_d().stack); QMetaObject::invokeMethod(qxt_d().stack->widget(index), "cleanup"); } /*! This virtual function is called to initialize page at \a index before switching to it. \bold {Note:} The default implementation calls SLOT(initialize()) of the corresponding page provided that such slot exists. \sa cleanupPage() */ void QxtConfigWidget::initializePage(int index) { Q_ASSERT(qxt_d().stack); QMetaObject::invokeMethod(qxt_d().stack->widget(index), "initialize"); } libqxt-0.6.2/src/gui/qxtconfigwidget.h000066400000000000000000000074121215241066400177610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCONFIGWIDGET_H #define QXTCONFIGWIDGET_H #include #include "qxtglobal.h" QT_FORWARD_DECLARE_CLASS(QTableWidget) QT_FORWARD_DECLARE_CLASS(QStackedWidget) QT_FORWARD_DECLARE_CLASS(QDialogButtonBox) class QxtConfigWidgetPrivate; class QXT_GUI_EXPORT QxtConfigWidget : public QWidget { Q_OBJECT QXT_DECLARE_PRIVATE(QxtConfigWidget) Q_PROPERTY(int count READ count) Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex) Q_PROPERTY(bool hoverEffect READ hasHoverEffect WRITE setHoverEffect) Q_PROPERTY(QxtConfigWidget::IconPosition iconPosition READ iconPosition WRITE setIconPosition) Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) Q_ENUMS(IconPosition) public: enum IconPosition { North, West, East }; explicit QxtConfigWidget(QWidget* parent = 0, Qt::WindowFlags flags = 0); explicit QxtConfigWidget(QxtConfigWidget::IconPosition position, QWidget* parent = 0, Qt::WindowFlags flags = 0); virtual ~QxtConfigWidget(); bool hasHoverEffect() const; void setHoverEffect(bool enabled); QxtConfigWidget::IconPosition iconPosition() const; void setIconPosition(QxtConfigWidget::IconPosition position); QSize iconSize() const; void setIconSize(const QSize& size); int addPage(QWidget* page, const QIcon& icon, const QString& title = QString()); int insertPage(int index, QWidget* page, const QIcon& icon, const QString& title = QString()); QWidget* takePage(int index); int count() const; int currentIndex() const; QWidget* currentPage() const; int indexOf(QWidget* page) const; QWidget* page(int index) const; bool isPageEnabled(int index) const; void setPageEnabled(int index, bool enabled); bool isPageHidden(int index) const; void setPageHidden(int index, bool hidden); QIcon pageIcon(int index) const; void setPageIcon(int index, const QIcon& icon); QString pageTitle(int index) const; void setPageTitle(int index, const QString& title); QString pageToolTip(int index) const; void setPageToolTip(int index, const QString& tooltip); QString pageWhatsThis(int index) const; void setPageWhatsThis(int index, const QString& whatsthis); public Q_SLOTS: void setCurrentIndex(int index); void setCurrentPage(QWidget* page); virtual void accept(); virtual void reject(); Q_SIGNALS: void currentIndexChanged(int index); protected: QTableWidget* tableWidget() const; QStackedWidget* stackedWidget() const; virtual void cleanupPage(int index); virtual void initializePage(int index); }; #endif // QXTCONFIGWIDGET_H libqxt-0.6.2/src/gui/qxtconfigwidget_p.h000066400000000000000000000050411215241066400202740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCONFIGWIDGET_P_H #define QXTCONFIGWIDGET_P_H #include "qxtconfigwidget.h" #include #include QT_FORWARD_DECLARE_CLASS(QSplitter) QT_FORWARD_DECLARE_CLASS(QStackedWidget) QT_FORWARD_DECLARE_CLASS(QDialogButtonBox) class QxtConfigTableWidget : public QTableWidget { public: QxtConfigTableWidget(QWidget* parent = 0); QStyleOptionViewItem viewOptions() const; QSize sizeHint() const; bool hasHoverEffect() const; void setHoverEffect(bool enabled); }; class QxtConfigDelegate : public QItemDelegate { public: QxtConfigDelegate(QObject* parent = 0); void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; bool hover; }; class QxtConfigWidgetPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtConfigWidget) void init(QxtConfigWidget::IconPosition position = QxtConfigWidget::West); void initTable(); void relayout(); QTableWidgetItem* item(int index) const; QSplitter* splitter; QStackedWidget* stack; QxtConfigTableWidget* table; QxtConfigWidget::IconPosition pos; public Q_SLOTS: void setCurrentIndex(int row, int column); void setCurrentIndex(int index); }; #endif // QXTCONFIGWIDGET_P_H libqxt-0.6.2/src/gui/qxtconfirmationmessage.cpp000066400000000000000000000325621215241066400217040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtconfirmationmessage.h" #include #include #include #include #include static const QLatin1String DEFAULT_ORGANIZATION("QxtGui"); static const QLatin1String DEFAULT_APPLICATION("QxtConfirmationMessage"); class QxtConfirmationMessagePrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtConfirmationMessage) void init(const QString& message = QString()); QString key() const; QString applicationName() const; QString organizationName() const; int showAgain(); void doNotShowAgain(int result); void reset(); bool remember; QCheckBox* confirm; QString overrideApp; QString overrideKey; QString overrideOrg; static QString path; static QSettings::Scope scope; static QSettings::Format format; }; QString QxtConfirmationMessagePrivate::path; QSettings::Scope QxtConfirmationMessagePrivate::scope = QSettings::UserScope; QSettings::Format QxtConfirmationMessagePrivate::format = QSettings::NativeFormat; void QxtConfirmationMessagePrivate::init(const QString& message) { remember = false; confirm = new QCheckBox(&qxt_p()); if (!message.isNull()) confirm->setText(message); else confirm->setText(QxtConfirmationMessage::tr("Do not show again.")); QGridLayout* grid = qobject_cast(qxt_p().layout()); QDialogButtonBox* buttons = qFindChild(&qxt_p()); if (grid && buttons) { const int idx = grid->indexOf(buttons); int row, column, rowSpan, columnSpan = 0; grid->getItemPosition(idx, &row, &column, &rowSpan, &columnSpan); QLayoutItem* buttonsItem = grid->takeAt(idx); grid->addWidget(confirm, row, column, rowSpan, columnSpan, Qt::AlignLeft | Qt::AlignTop); grid->addItem(buttonsItem, ++row, column, rowSpan, columnSpan); } } QString QxtConfirmationMessagePrivate::key() const { QString value = overrideKey; if (value.isEmpty()) { const QString all = qxt_p().windowTitle() + qxt_p().text() + qxt_p().informativeText(); const QByteArray data = all.toLocal8Bit(); value = QString::number(qChecksum(data.constData(), data.length())); } return value; } QString QxtConfirmationMessagePrivate::applicationName() const { QString name = overrideApp; if (name.isEmpty()) name = QCoreApplication::applicationName(); if (name.isEmpty()) name = DEFAULT_APPLICATION; return name; } QString QxtConfirmationMessagePrivate::organizationName() const { QString name = overrideOrg; if (name.isEmpty()) name = QCoreApplication::organizationName(); if (name.isEmpty()) name = DEFAULT_ORGANIZATION; return name; } int QxtConfirmationMessagePrivate::showAgain() { QSettings settings(format, scope, organizationName(), applicationName()); if (!path.isEmpty()) settings.beginGroup(path); return settings.value(key(), -1).toInt(); } void QxtConfirmationMessagePrivate::doNotShowAgain(int result) { QSettings settings(format, scope, organizationName(), applicationName()); if (!path.isEmpty()) settings.beginGroup(path); settings.setValue(key(), result); } void QxtConfirmationMessagePrivate::reset() { QSettings settings(format, scope, organizationName(), applicationName()); if (!path.isEmpty()) settings.beginGroup(path); settings.remove(key()); } /*! \class QxtConfirmationMessage \inmodule QxtGui \brief The QxtConfirmationMessage class provides a confirmation message. QxtConfirmationMessage is a confirmation message with checkable \bold {"Do not show again."} option. A checked and accepted confirmation message is no more shown until reseted. Example usage: \code void MainWindow::closeEvent(QCloseEvent* event) { static const QString text(tr("Are you sure you want to quit?")); if (QxtConfirmationMessage::confirm(this, tr("Confirm"), text) == QMessageBox::No) event->ignore(); } \endcode \image qxtconfirmationmessage.png "QxtConfirmationMessage in action." \bold {Note:} QCoreApplication::organizationName and QCoreApplication::applicationName are used for storing settings. In case these properties are empty, \bold "QxtGui" and \bold "QxtConfirmationMessage" are used, respectively. */ /*! Constructs a new QxtConfirmationMessage with \a parent. */ QxtConfirmationMessage::QxtConfirmationMessage(QWidget* parent) : QMessageBox(parent) { QXT_INIT_PRIVATE(QxtConfirmationMessage); qxt_d().init(); } /*! Constructs a new QxtConfirmationMessage with \a icon, \a title, \a text, \a confirmation, \a buttons, \a parent and \a flags. */ QxtConfirmationMessage::QxtConfirmationMessage(QMessageBox::Icon icon, const QString& title, const QString& text, const QString& confirmation, QMessageBox::StandardButtons buttons, QWidget* parent, Qt::WindowFlags flags) : QMessageBox(icon, title, text, buttons, parent, flags) { QXT_INIT_PRIVATE(QxtConfirmationMessage); qxt_d().init(confirmation); } /*! Destructs the confirmation message. */ QxtConfirmationMessage::~QxtConfirmationMessage() { } /*! Opens an confirmation message box with the specified \a title, \a text and \a confirmation. The standard \a buttons are added to the message box. \a defaultButton specifies the button used when Enter is pressed. \a defaultButton must refer to a button that was given in \a buttons. If \a defaultButton is QMessageBox::NoButton, QMessageBox chooses a suitable default automatically. Returns the identity of the standard button that was clicked. If Esc was pressed instead, the escape button is returned. If \a parent is \c 0, the message box is an application modal dialog box. If \a parent is a widget, the message box is window modal relative to \a parent. */ QMessageBox::StandardButton QxtConfirmationMessage::confirm(QWidget* parent, const QString& title, const QString& text, const QString& confirmation, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { QxtConfirmationMessage msgBox(QMessageBox::NoIcon, title, text, confirmation, QMessageBox::NoButton, parent); QDialogButtonBox* buttonBox = qFindChild(&msgBox); Q_ASSERT(buttonBox != 0); uint mask = QMessageBox::FirstButton; while (mask <= QMessageBox::LastButton) { uint sb = buttons & mask; mask <<= 1; if (!sb) continue; QPushButton* button = msgBox.addButton((QMessageBox::StandardButton)sb); // Choose the first accept role as the default if (msgBox.defaultButton()) continue; if ((defaultButton == QMessageBox::NoButton && buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) || (defaultButton != QMessageBox::NoButton && sb == uint(defaultButton))) msgBox.setDefaultButton(button); } if (msgBox.exec() == -1) return QMessageBox::Cancel; return msgBox.standardButton(msgBox.clickedButton()); } /*! \property QxtConfirmationMessage::confirmationText \brief the confirmation text The default value is \bold {"Do not show again."} */ QString QxtConfirmationMessage::confirmationText() const { return qxt_d().confirm->text(); } void QxtConfirmationMessage::setConfirmationText(const QString& confirmation) { qxt_d().confirm->setText(confirmation); } /*! \property QxtConfirmationMessage::overrideSettingsApplication \brief the override application name used for settings QCoreApplication::applicationName is used when no \bold overrideSettingsApplication has been set. The application name falls back to \bold "QxtConfirmationMessage" when no QCoreApplication::applicationName has been set. The default value is an empty string. */ QString QxtConfirmationMessage::overrideSettingsApplication() const { return qxt_d().overrideApp; } void QxtConfirmationMessage::setOverrideSettingsApplication(const QString& application) { qxt_d().overrideApp = application; } /*! \property QxtConfirmationMessage::overrideSettingsKey \brief the override key used for settings When no \bold overrideSettingsKey has been set, the key is calculated with qChecksum() based on title, text and confirmation message. The default value is an empty string. */ QString QxtConfirmationMessage::overrideSettingsKey() const { return qxt_d().overrideKey; } void QxtConfirmationMessage::setOverrideSettingsKey(const QString& key) { qxt_d().overrideKey = key; } /*! \property QxtConfirmationMessage::overrideSettingsOrganization \brief the override organization name used for settings QCoreApplication::organizationName is used when no \bold overrideSettingsOrganization has been set. The organization name falls back to \bold "QxtGui" when no QCoreApplication::organizationName has been set. The default value is an empty string. */ QString QxtConfirmationMessage::overrideSettingsOrganization() const { return qxt_d().overrideOrg; } void QxtConfirmationMessage::setOverrideSettingsOrganization(const QString& organization) { qxt_d().overrideOrg = organization; } /*! \property QxtConfirmationMessage::rememberOnReject \brief whether \bold {"Do not show again."} option is stored even if the message box is rejected (eg. user presses Cancel). The default value is \c false. */ bool QxtConfirmationMessage::rememberOnReject() const { return qxt_d().remember; } void QxtConfirmationMessage::setRememberOnReject(bool remember) { qxt_d().remember = remember; } /*! Returns The format used for storing settings. The default value is QSettings::NativeFormat. */ QSettings::Format QxtConfirmationMessage::settingsFormat() { return QxtConfirmationMessagePrivate::format; } /*! Sets the \a format used for storing settings. */ void QxtConfirmationMessage::setSettingsFormat(QSettings::Format format) { QxtConfirmationMessagePrivate::format = format; } /*! Returns The scope used for storing settings. The default value is QSettings::UserScope. */ QSettings::Scope QxtConfirmationMessage::settingsScope() { return QxtConfirmationMessagePrivate::scope; } /*! Sets the \a scope used for storing settings. */ void QxtConfirmationMessage::setSettingsScope(QSettings::Scope scope) { QxtConfirmationMessagePrivate::scope = scope; } /*! Returns the path used for storing settings. The default value is an empty string. */ QString QxtConfirmationMessage::settingsPath() { return QxtConfirmationMessagePrivate::path; } /*! Sets the \a path used for storing settings. */ void QxtConfirmationMessage::setSettingsPath(const QString& path) { QxtConfirmationMessagePrivate::path = path; } /*! Shows the confirmation message if necessary. The confirmation message is not shown in case \bold {"Do not show again."} has been checked while the same confirmation message was earlierly accepted. A confirmation message is identified by the combination of title, QMessageBox::text and optional QMessageBox::informativeText. A clicked button with role QDialogButtonBox::AcceptRole or QDialogButtonBox::YesRole is considered as "accepted". \warning This function does not reimplement but shadows QMessageBox::exec(). \sa QWidget::windowTitle, QMessageBox::text, QMessageBox::informativeText */ int QxtConfirmationMessage::exec() { int res = qxt_d().showAgain(); if (res == -1) res = QMessageBox::exec(); return res; } /*! \reimp */ void QxtConfirmationMessage::done(int result) { QDialogButtonBox* buttons = qFindChild(this); Q_ASSERT(buttons != 0); int role = buttons->buttonRole(clickedButton()); if (qxt_d().confirm->isChecked() && (qxt_d().remember || role != QDialogButtonBox::RejectRole)) { qxt_d().doNotShowAgain(result); } QMessageBox::done(result); } /*! Resets this instance of QxtConfirmationMessage. A reseted confirmation message is shown again until user checks \bold {"Do not show again."} and accepts the confirmation message. */ void QxtConfirmationMessage::reset() { qxt_d().reset(); } libqxt-0.6.2/src/gui/qxtconfirmationmessage.h000066400000000000000000000072631215241066400213510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCONFIRMATIONMESSAGE_H #define QXTCONFIRMATIONMESSAGE_H #include #include #include "qxtglobal.h" class QxtConfirmationMessagePrivate; class QXT_GUI_EXPORT QxtConfirmationMessage : public QMessageBox { Q_OBJECT QXT_DECLARE_PRIVATE(QxtConfirmationMessage) Q_PROPERTY(QString confirmationText READ confirmationText WRITE setConfirmationText) Q_PROPERTY(QString overrideSettingsApplication READ overrideSettingsApplication WRITE setOverrideSettingsApplication) Q_PROPERTY(QString overrideSettingsKey READ overrideSettingsKey WRITE setOverrideSettingsKey) Q_PROPERTY(QString overrideSettingsOrganization READ overrideSettingsOrganization WRITE setOverrideSettingsOrganization) Q_PROPERTY(bool rememberOnReject READ rememberOnReject WRITE setRememberOnReject) public: explicit QxtConfirmationMessage(QWidget* parent = 0); virtual ~QxtConfirmationMessage(); QxtConfirmationMessage(QMessageBox::Icon icon, const QString& title, const QString& text, const QString& confirmation = QString(), QMessageBox::StandardButtons buttons = QMessageBox::NoButton, QWidget* parent = 0, Qt::WindowFlags flags = Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint); static QMessageBox::StandardButton confirm(QWidget* parent, const QString& title, const QString& text, const QString& confirmation = QString(), QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::No, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); QString confirmationText() const; void setConfirmationText(const QString& confirmation); QString overrideSettingsApplication() const; void setOverrideSettingsApplication(const QString& application); QString overrideSettingsKey() const; void setOverrideSettingsKey(const QString& key); QString overrideSettingsOrganization() const; void setOverrideSettingsOrganization(const QString& organization); bool rememberOnReject() const; void setRememberOnReject(bool remember); static QSettings::Format settingsFormat(); static void setSettingsFormat(QSettings::Format format); static QSettings::Scope settingsScope(); static void setSettingsScope(QSettings::Scope scope); static QString settingsPath(); static void setSettingsPath(const QString& path); public Q_SLOTS: int exec(); void reset(); virtual void done(int result); }; #endif // QXTCONFIRMATIONMESSAGE_H libqxt-0.6.2/src/gui/qxtcountrycombobox.cpp000066400000000000000000000102421215241066400210720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtcountrycombobox.h" #include "qxtcountrycombobox_p.h" #include "qxtcountrymodel.h" #include QxtCountryComboBoxPrivate::QxtCountryComboBoxPrivate() { } void QxtCountryComboBoxPrivate::comboBoxCurrentIndexChanged(int) { emit qxt_p().currentCountryChanged(currentCountry()); emit qxt_p().currentCountryNameChanged(currentCountryName()); } QLocale::Country QxtCountryComboBoxPrivate::currentCountry() const { QModelIndex idx = qxt_p().model()->index(qxt_p().currentIndex(), 2); return static_cast(idx.data().toInt()); } QString QxtCountryComboBoxPrivate::currentCountryName() const { return qxt_p().currentText(); } void QxtCountryComboBoxPrivate::setCurrentCountry(QLocale::Country country) { // column 3 is QLocale::Country QModelIndex start = qxt_p().model()->index(0, 2); QModelIndexList result = qxt_p().model()->match(start, Qt::DisplayRole, country, 1, Qt::MatchExactly); if (!result.isEmpty()) qxt_p().setCurrentIndex(result.first().row()); } /*! \class QxtCountryComboBox \inmodule QxtGui \brief The QxtCountryComboBox widget is an extended QComboBox to display countries. QxtCountryComboBox is a specialized combo box to display countries. The languages are taken from QLocale::Country. \image qxtcountrycombobox.png "QxtCountryComboBox in Plastique style." */ /*! \fn QxtCountryComboBox::currentCountryChanged(QLocale::Country country) This signal is emitted whenever the current \a country has been changed. */ /*! \fn QxtCountryComboBox::currentCountryNameChanged(const QString& name) This signal is emitted whenever the current country \a name has been changed. */ /*! Constructs a new QxtCountryComboBox with \a parent. */ QxtCountryComboBox::QxtCountryComboBox(QWidget* parent) : QComboBox(parent) { QXT_INIT_PRIVATE(QxtCountryComboBox); #ifdef QXT_DESIGNER_MODE setEditable(false); #else setModel(new QxtCountryModel(this)); setModelColumn(0); setCurrentCountry(QLocale::system().country()); #endif connect(this, SIGNAL(currentIndexChanged(int)), &qxt_d(), SLOT(comboBoxCurrentIndexChanged(int))); } #ifdef QXT_DESIGNER_MODE void QxtCountryComboBox::paintEvent(QPaintEvent *e) { QComboBox::paintEvent(e); QStylePainter painter(this); painter.drawItemText(e->rect(), Qt::AlignCenter, palette(), true, tr("DESIGNER MODE - DESIGNER MODE")); } #endif /*! Destructs the country combo box. */ QxtCountryComboBox::~QxtCountryComboBox() { } /*! \property QxtCountryComboBox::currentCountry \brief the current country. */ QLocale::Country QxtCountryComboBox::currentCountry() const { return qxt_d().currentCountry(); } /*! \property QxtCountryComboBox::currentCountryName \brief the name of the current country. */ QString QxtCountryComboBox::currentCountryName() const { return qxt_d().currentCountryName(); } void QxtCountryComboBox::setCurrentCountry(QLocale::Country country) { return qxt_d().setCurrentCountry(country); } libqxt-0.6.2/src/gui/qxtcountrycombobox.h000066400000000000000000000041621215241066400205430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCOUNTRYCOMBOBOX_H #define QXTCOUNTRYCOMBOBOX_H #include #include #include "qxtglobal.h" class QxtCountryComboBoxPrivate; class QXT_GUI_EXPORT QxtCountryComboBox : public QComboBox { Q_OBJECT QXT_DECLARE_PRIVATE(QxtCountryComboBox) Q_PROPERTY(QString currentCountryName READ currentCountryName) #if QT_VERSION >= 0x040300 Q_PROPERTY(QLocale::Country currentCountry READ currentCountry WRITE setCurrentCountry) #endif public: explicit QxtCountryComboBox(QWidget* parent = 0); virtual ~QxtCountryComboBox(); QLocale::Country currentCountry() const; QString currentCountryName() const; public Q_SLOTS: void setCurrentCountry(QLocale::Country country); Q_SIGNALS: void currentCountryChanged(QLocale::Country country); void currentCountryNameChanged(const QString& name); #ifdef QXT_DESIGNER_MODE protected: void paintEvent(QPaintEvent *e); #endif }; #endif //QXTCOUNTRYCOMBOBOX_H libqxt-0.6.2/src/gui/qxtcountrycombobox_p.h000066400000000000000000000033411215241066400210600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCOUNTRYCOMBOBOX_P_H #define QXTCOUNTRYCOMBOBOX_P_H #include "qxtcountrycombobox.h" #include class QxtCountryComboBoxPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtCountryComboBox) public: explicit QxtCountryComboBoxPrivate(); QLocale::Country currentCountry() const; QString currentCountryName() const; public Q_SLOTS: void setCurrentCountry(QLocale::Country country); void comboBoxCurrentIndexChanged(int index); }; #endif // QXTCOUNTRYCOMBOBOX_P_H libqxt-0.6.2/src/gui/qxtcountrymodel.cpp000066400000000000000000000136141215241066400203700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtcountrymodel.h" #include "qxtcountrymodel_p.h" #include "qxtlocale.h" #include #include #include class QxtCountry; typedef QList QxtCountryList; class QxtCountry { public: explicit QxtCountry(QLocale::Country country) : _mCountry(country) { _mName = qApp->translate("QLocale", qPrintable(QLocale::countryToString(_mCountry))); _mCurrency = QxtLocale::currencyForCountry(_mCountry); } const QString& name() const { return _mName; } QLocale::Country country() const { return _mCountry; } QxtLocale::Currency currency() const { return _mCurrency; } bool operator<(const QxtCountry& country) const { return _mName.localeAwareCompare(country._mName) < 0; } static const QxtCountryList& loadCountries() { if (!_smCountryNames.empty()) return _smCountryNames; for (int idx = 0; idx < QLocale::LastCountry; ++idx) { QLocale::Country c = static_cast(idx); if (c == QLocale::LastCountry) continue; if (c == QLocale::AnyCountry) continue; _smCountryNames.push_back(QxtCountry(c)); } qSort(_smCountryNames); return _smCountryNames; } private: QString _mName; QLocale::Country _mCountry; QxtLocale::Currency _mCurrency; private: static QxtCountryList _smCountryNames; }; QxtCountryList QxtCountry::_smCountryNames; QxtCountryModelPrivate::QxtCountryModelPrivate() { } QVariant QxtCountryModelPrivate::data(const QModelIndex& index, int role) const { if (!index.isValid()) return QVariant(); const QxtCountry& c = QxtCountry::loadCountries().operator[](index.row()); if (role == Qt::DecorationRole && index.column() == 0) return QIcon(":/flags/" + QxtLocale::countryToISO2Letter(c.country()) + ".png"); if (role == Qt::DisplayRole) { switch (index.column()) { case 0: return c.name(); case 1: return QxtLocale::countryToISO2Letter(c.country()); case 2: return c.country(); case 3: return QxtLocale::countryToISO3Letter(c.country()); case 4: return QxtLocale::currencyToName(c.currency()); case 5: return QxtLocale::currencyToCode(c.currency()); case 6: return QxtLocale::currencyToSymbol(c.currency()); case 7: return QxtLocale::continentToName(QxtLocale::continentForCountry(c.country())); default: return QVariant(); } } return QVariant(); } /*! \class QxtCountryModel \inmodule QxtGui \brief The QxtCountryModel class is a subclass of QAbstractTableModel to display country data. QxtCountryModel is a specialized QAbstractTableModel to display countries. The countries are taken from QLocale::Country. \image qxtcountrymodel.png "QxtCountryModel in a QTableView in Plastique style." */ /*! Constructs a new QxtCountryModel with \a parent. */ QxtCountryModel::QxtCountryModel(QObject* parent) : QAbstractTableModel(parent) { QXT_INIT_PRIVATE(QxtCountryModel); } /*! Destructs the country model. */ QxtCountryModel::~QxtCountryModel() { } /*! Returns the number of countries for \a parent in the model. */ int QxtCountryModel::rowCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : QxtCountry::loadCountries().size(); } /*! Returns the number of columns \a parent in the model. */ int QxtCountryModel::columnCount(const QModelIndex& parent) const { return parent.isValid() ? 0 : 8; } /*! Returns the data for the given \a index for a specific \a role. */ QVariant QxtCountryModel::data(const QModelIndex& index, int role) const { return qxt_d().data(index, role); } /*! Returns the column or row name for the given \a section in \a orientation for a sepcific \a role. */ QVariant QxtCountryModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { switch (section) { case 0: return tr("Name"); case 1: return tr("ISO 3166 Alpha 2"); case 2: return tr("QLocale"); case 3: return tr("ISO 3166 Alpha 3"); case 4: return tr("Currency"); case 5: return tr("Currency Code"); case 6: return tr("Currency Symbol"); case 7: return tr("Continent"); } } return QAbstractTableModel::headerData(section, orientation, role); } libqxt-0.6.2/src/gui/qxtcountrymodel.h000066400000000000000000000034741215241066400200400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCOUNTRYMODEL_H #define QXTCOUNTRYMODEL_H #include #include "qxtglobal.h" class QxtCountryModelPrivate; class QXT_GUI_EXPORT QxtCountryModel : public QAbstractTableModel { Q_OBJECT public: explicit QxtCountryModel(QObject* parent = 0); ~QxtCountryModel(); int rowCount(const QModelIndex&) const; int columnCount(const QModelIndex&) const; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; private: QXT_DECLARE_PRIVATE(QxtCountryModel) }; #endif //QXTCOUNTRYMODEL_H libqxt-0.6.2/src/gui/qxtcountrymodel_p.h000066400000000000000000000030611215241066400203470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCOUNTRYMODEL_P_H #define QXTCOUNTRYMODEL_P_H #include "qxtcountrymodel.h" class QxtCountryModelPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtCountryModel) public: explicit QxtCountryModelPrivate(); QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; }; #endif //QXTCOUNTRYMODEL_H libqxt-0.6.2/src/gui/qxtcrumbview.cpp000066400000000000000000000301051215241066400176410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtcrumbview.h" #include "qxtcrumbview_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include // This class exists only to grant access to QListView's protected members class QxtCrumbViewList : public QListView { friend class QxtCrumbView; public: QxtCrumbViewList(QWidget* parent) : QListView(parent) { } }; QxtCrumbViewDelegate::QxtCrumbViewDelegate(QAbstractItemDelegate* other, QObject* parent) : QAbstractItemDelegate(parent), delegate(other) { QObject::connect(other, SIGNAL(closeEditor(QWidget*, QAbstractItemDelegate::EndEditHint)), this, SIGNAL(closeEditor(QWidget*, QAbstractItemDelegate::EndEditHint))); QObject::connect(other, SIGNAL(commitData(QWidget*)), this, SIGNAL(commitData(QWidget*))); QObject::connect(other, SIGNAL(sizeHintChanged(QModelIndex)), this, SIGNAL(sizeHintChanged(QModelIndex))); } void QxtCrumbViewDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { delegate->paint(painter, option, index); if(!index.model()->hasChildren(index)) return; int arrow = 8; int pad = (option.rect.height() - arrow) / 2; QStyleOption arrowOption; arrowOption = option; arrowOption.rect = QRect(option.rect.right() - arrow, option.rect.top() + pad, arrow, arrow); QApplication::style()->drawPrimitive(QStyle::PE_IndicatorArrowRight, &arrowOption, painter); } QSize QxtCrumbViewDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { return delegate->sizeHint(option, index) + QSize(8, 0); } QWidget* QxtCrumbViewDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) { return delegate->createEditor(parent, option, index); } void QxtCrumbViewDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const { delegate->setEditorData(editor, index); } void QxtCrumbViewDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { delegate->setModelData(editor, model, index); } void QxtCrumbViewDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const { delegate->updateEditorGeometry(editor, option, index); } bool QxtCrumbViewDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) { return delegate->editorEvent(event, model, option, index); } class QxtCrumbViewButton : public QAbstractButton { public: QxtCrumbViewButton(const QModelIndex& idx, QxtCrumbView* parent) : QAbstractButton(parent), index(idx) { // initializers only } QModelIndex index; QSize sizeHint() const { QStyleOptionViewItem itemOption; itemOption.initFrom(this); int border = style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2; int arrow = 8; if(index.isValid()) return static_cast(parent())->itemDelegate()->sizeHint(itemOption, index) + QSize(border + arrow, border); else return QSize(border + arrow, border + arrow); } protected: void enterEvent(QEvent* event) { Q_UNUSED(event); update(); } void leaveEvent(QEvent* event) { Q_UNUSED(event); update(); } void paintEvent(QPaintEvent* event) { Q_UNUSED(event); QStylePainter painter(this); QStyleOptionButton option; option.initFrom(this); if(rect().contains(mapFromGlobal(QCursor::pos()))) { painter.drawPrimitive(QStyle::PE_PanelButtonTool, option); } int border = painter.style()->pixelMetric(QStyle::PM_DefaultFrameWidth); option.rect = option.rect.adjusted(border, border, -border, -border); if(index.isValid()) { QAbstractItemDelegate* delegate = static_cast(parent())->crumbDelegate(); QStyleOptionViewItem itemOption; itemOption.initFrom(this); itemOption.rect = option.rect; delegate->paint(&painter, itemOption, index); } int arrow = 8; int pad = (height() - (2 * border) - arrow) / 2; QStyleOption arrowOption; arrowOption.initFrom(this); arrowOption.rect = QRect(width() - border - arrow, pad, arrow, arrow); painter.drawPrimitive(QStyle::PE_IndicatorArrowRight, arrowOption); } }; QxtCrumbViewPrivate::QxtCrumbViewPrivate() : crumbDelegate(0) { // initializers only } void QxtCrumbViewPrivate::addCrumb(const QModelIndex& index) { crumbs.append(index); QxtCrumbViewButton* button = new QxtCrumbViewButton(index, &qxt_p()); button->setFocusPolicy(Qt::NoFocus); button->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); buttons.append(button); buttonLayout->insertWidget(buttons.count() - 1, button, 0); QObject::connect(button, SIGNAL(clicked()), this, SLOT(buttonPressed())); } void QxtCrumbViewPrivate::buttonPressed() { qxt_p().enterTree(static_cast(sender())->index); } QxtCrumbView::QxtCrumbView(QWidget* parent) : QAbstractItemView(parent) { QXT_INIT_PRIVATE(QxtCrumbView); setAutoFillBackground(false); setBackgroundRole(QPalette::Window); viewport()->setAutoFillBackground(false); viewport()->setBackgroundRole(QPalette::Window); setFrameStyle(QFrame::NoFrame); QVBoxLayout* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); qxt_d().buttonLayout = new QHBoxLayout; qxt_d().buttonLayout->setContentsMargins(0, 0, 0, 0); qxt_d().buttonLayout->setSpacing(0); qxt_d().buttonLayout->addStretch(1); QToolButton* backButton = new QToolButton(this); backButton->setIcon(style()->standardPixmap(QStyle::SP_FileDialogBack)); backButton->setAutoRaise(true); backButton->setFocusPolicy(Qt::NoFocus); qxt_d().buttonLayout->addWidget(backButton); layout->addLayout(qxt_d().buttonLayout, 0); qxt_d().view = new QxtCrumbViewList(this); layout->addWidget(qxt_d().view, 1); qxt_d().addCrumb(QModelIndex()); QObject::connect(qxt_d().view, SIGNAL(activated(QModelIndex)), this, SLOT(enterTree(QModelIndex))); QObject::connect(backButton, SIGNAL(clicked()), this, SLOT(back())); } void QxtCrumbView::setModel(QAbstractItemModel* model) { qxt_d().view->setModel(model); QAbstractItemView::setModel(model); delete qxt_d().view->itemDelegate(); qxt_d().view->setItemDelegate(new QxtCrumbViewDelegate(itemDelegate(), this)); } void QxtCrumbView::reset() { QAbstractItemView::reset(); qDeleteAll(qxt_d().buttons); qxt_d().crumbs.clear(); qxt_d().buttons.clear(); qxt_d().addCrumb(QModelIndex()); qxt_d().view->reset(); } int QxtCrumbView::horizontalOffset() const { return qxt_d().view->horizontalOffset(); } int QxtCrumbView::verticalOffset() const { return qxt_d().view->verticalOffset(); } QModelIndex QxtCrumbView::indexAt(const QPoint& point) const { return qxt_d().view->indexAt(qxt_d().view->mapFromParent(point)); } bool QxtCrumbView::isIndexHidden(const QModelIndex& index) const { return qxt_d().view->isIndexHidden(index); } QModelIndex QxtCrumbView::moveCursor(CursorAction action, Qt::KeyboardModifiers mods) { return qxt_d().view->moveCursor(action, mods); } void QxtCrumbView::scrollTo(const QModelIndex& index, ScrollHint hint) { if(index.parent() != qxt_d().view->rootIndex()) { // TODO: set the breadcrumbs and the view's root index correctly } qxt_d().view->scrollTo(index, hint); } void QxtCrumbView::setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags) { QPoint tl = qxt_d().view->mapFromParent(rect.topLeft()); qxt_d().view->setSelection(QRect(tl, rect.size()), flags); } QRect QxtCrumbView::visualRect(const QModelIndex& index) const { QRect rect = qxt_d().view->visualRect(index); return QRect(qxt_d().view->mapToParent(rect.topLeft()), rect.size()); } QRegion QxtCrumbView::visualRegionForSelection(const QItemSelection& selection) const { QRegion region = qxt_d().view->visualRegionForSelection(selection); return region.translated(qxt_d().view->pos()); } void QxtCrumbView::enterTree(const QModelIndex& index) { if(!model()) return; if(!model()->hasChildren(index)) { emit activated(index); return; } if(index == qxt_d().view->rootIndex()) { // do nothing but reload the view } else if(index.parent() != qxt_d().view->rootIndex()) { foreach(QxtCrumbViewButton* b, qxt_d().buttons) b->deleteLater(); qxt_d().crumbs.clear(); qxt_d().buttons.clear(); qxt_d().addCrumb(QModelIndex()); QList chain; QModelIndex pos = index; while(pos.isValid()) { chain.append(pos); pos = pos.parent(); } while(!chain.isEmpty()) { qxt_d().addCrumb(chain.last()); chain.removeLast(); } } else { qxt_d().addCrumb(index); } qxt_d().view->setRootIndex(index); } void QxtCrumbView::back() { if(qxt_d().crumbs.count() <= 1) return; qxt_d().buttons.last()->deleteLater(); qxt_d().buttons.removeLast(); qxt_d().crumbs.removeLast(); qxt_d().view->setRootIndex(qxt_d().crumbs.last()); } void QxtCrumbView::setItemDelegate(QAbstractItemDelegate* delegate) { QAbstractItemView::setItemDelegate(delegate); //delete qxt_d().view->itemDelegate(); //qxt_d().view->setItemDelegate(new QxtCrumbViewDelegate(itemDelegate(), this)); } QAbstractItemView* QxtCrumbView::itemView() const { return qxt_d().view; } void QxtCrumbView::showEvent(QShowEvent* event) { QxtCrumbViewDelegate* viewDelegate = qobject_cast(qxt_d().view->itemDelegate()); if(viewDelegate->delegate != itemDelegate()) { qxt_d().view->setItemDelegate(new QxtCrumbViewDelegate(itemDelegate(), this)); delete viewDelegate; qxt_d().view->reset(); } QAbstractItemView::showEvent(event); } void QxtCrumbView::paintEvent(QPaintEvent* event) { QxtCrumbViewDelegate* viewDelegate = qobject_cast(qxt_d().view->itemDelegate()); if(viewDelegate->delegate != itemDelegate()) { qxt_d().view->setItemDelegate(new QxtCrumbViewDelegate(itemDelegate(), this)); delete viewDelegate; qxt_d().view->reset(); } QAbstractItemView::paintEvent(event); } QAbstractItemDelegate* QxtCrumbView::crumbDelegate() const { QAbstractItemDelegate* rv = qxt_d().crumbDelegate; if(!rv) return itemDelegate(); return rv; } void QxtCrumbView::setCrumbDelegate(QAbstractItemDelegate* delegate) { qxt_d().crumbDelegate = delegate; update(); foreach(QxtCrumbViewButton* button, qxt_d().buttons) { button->update(); } } libqxt-0.6.2/src/gui/qxtcrumbview.h000066400000000000000000000051231215241066400173100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCRUMBVIEW_H #define QXTCRUMBVIEW_H #include "qxtglobal.h" #include QT_FORWARD_DECLARE_CLASS(QListView) class QxtCrumbViewPrivate; class QXT_GUI_EXPORT QxtCrumbView : public QAbstractItemView { Q_OBJECT public: QxtCrumbView(QWidget* parent = 0); virtual void setModel(QAbstractItemModel* model); virtual QModelIndex indexAt(const QPoint& point) const; virtual void scrollTo(const QModelIndex& index, ScrollHint hint = EnsureVisible); virtual QRect visualRect(const QModelIndex& index) const; void setItemDelegate(QAbstractItemDelegate* delegate); QAbstractItemDelegate* crumbDelegate() const; virtual void setCrumbDelegate(QAbstractItemDelegate* delegate); QAbstractItemView* itemView() const; public slots: virtual void reset(); void back(); void enterTree(const QModelIndex& index); protected: virtual int horizontalOffset() const; virtual int verticalOffset() const; virtual bool isIndexHidden(const QModelIndex& index) const; virtual QModelIndex moveCursor(CursorAction action, Qt::KeyboardModifiers mods); virtual void setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags); virtual QRegion visualRegionForSelection(const QItemSelection& selection) const; virtual void showEvent(QShowEvent* event); virtual void paintEvent(QPaintEvent* event); private: QXT_DECLARE_PRIVATE(QxtCrumbView) }; #endif libqxt-0.6.2/src/gui/qxtcrumbview_p.h000066400000000000000000000052621215241066400176330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTCRUMBVIEW_P_INCLUDED #define QXTCRUMBVIEW_P_INCLUDED #include "qxtcrumbview.h" QT_FORWARD_DECLARE_CLASS(QHBoxLayout) class QxtCrumbViewList; class QxtCrumbViewButton; class QxtCrumbViewPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QxtCrumbViewPrivate(); QList crumbs; QList buttons; QHBoxLayout* buttonLayout; QxtCrumbViewList* view; QAbstractItemDelegate* crumbDelegate; void addCrumb(const QModelIndex& index); QXT_DECLARE_PUBLIC(QxtCrumbView) public slots: void buttonPressed(); }; class QxtCrumbViewDelegate : public QAbstractItemDelegate { Q_OBJECT public: QxtCrumbViewDelegate(QAbstractItemDelegate* other, QObject* parent); QAbstractItemDelegate* delegate; void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index); void setEditorData(QWidget* editor, const QModelIndex& index) const; void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const; bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index); }; #endif // QXTCRUMBVIEW_P_INCLUDED libqxt-0.6.2/src/gui/qxtfilterdialog.cpp000066400000000000000000000225201215241066400203050ustar00rootroot00000000000000#include "qxtfilterdialog.h" #include "qxtfilterdialog_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "qxtgroupbox.h" QxtFilterDialogPrivate::QxtFilterDialogPrivate() : QObject(0), matchCaseOption(0), filterModeOption(0), filterMode(0), listingTreeView(0), lineEditFilter(0), proxyModel(0), lookupColumn(0), lookupRole(Qt::DisplayRole), syntax(QRegExp::FixedString), caseSensitivity(Qt::CaseInsensitive) { } void QxtFilterDialogPrivate::createRegExpPattern(const QString &rawText) { QRegExp regExp(rawText,caseSensitivity,syntax); if(regExp.isValid()) proxyModel->setFilterRegExp(regExp); else proxyModel->setFilterRegExp(QString()); } void QxtFilterDialogPrivate::updateFilterPattern() { createRegExpPattern(lineEditFilter->text()); } void QxtFilterDialogPrivate::filterModeOptionStateChanged(const int state) { if(state == Qt::Checked) this->filterMode->setEnabled(true); else this->filterMode->setEnabled(false); } void QxtFilterDialogPrivate::filterModeChoosen(int index) { if(index < 0) return; if( filterMode->itemData(index).isValid()) { QRegExp::PatternSyntax mode = static_cast(filterMode->itemData(index).toInt()); qxt_p().setPatternSyntax(mode); } } void QxtFilterDialogPrivate::matchCaseOptionStateChanged(const int state) { if(state == Qt::Checked) this->caseSensitivity = Qt::CaseSensitive; else this->caseSensitivity = Qt::CaseInsensitive; updateFilterPattern(); } /*! \class QxtFilterDialog QxtFilterDialog \brief The QxtFilterDialog class provides a dialog to select data from a QAbstractItemModel Provides a dialog to select data from a QAbstractItemModel, the user can filter the items depending on a role and column to make the selection easier. */ QxtFilterDialog::QxtFilterDialog(QWidget *parent) : QDialog(parent) { QXT_INIT_PRIVATE(QxtFilterDialog); qxt_d().proxyModel = new QSortFilterProxyModel(this); QVBoxLayout * dlgLayout = new QVBoxLayout(this); /*the line edit to type in the filter*/ qxt_d().lineEditFilter = new QLineEdit(); dlgLayout->addWidget(qxt_d().lineEditFilter); connect(qxt_d().lineEditFilter,SIGNAL(textChanged(const QString &)),&qxt_d(),SLOT(createRegExpPattern(const QString &))); /*the treeview that shows the filtered choices */ qxt_d().listingTreeView = new QTreeView(this); qxt_d().listingTreeView->setSortingEnabled(true); //not editable , even if the model supports it qxt_d().listingTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers); dlgLayout->addWidget(qxt_d().listingTreeView); connect(qxt_d().listingTreeView,SIGNAL(activated ( const QModelIndex & )),this,SLOT(accept())); #if 1 /*Group Box for changing search behaviour*/ QxtGroupBox *group = new QxtGroupBox(this); // group->setCollapsive(true); group->setTitle(tr("Filter options")); qxt_d().matchCaseOption = new QCheckBox(tr("Match case")); connect(qxt_d().matchCaseOption,SIGNAL(stateChanged ( int )),&qxt_d(),SLOT(matchCaseOptionStateChanged(int))); qxt_d().filterModeOption = new QCheckBox(tr("Filter mode:")); connect(qxt_d().filterModeOption,SIGNAL(stateChanged ( int )),&qxt_d(),SLOT(filterModeOptionStateChanged(int))); qxt_d().filterMode = new QComboBox(); qxt_d().filterMode->addItem(tr("Fixed String (Default)"),QRegExp::FixedString); qxt_d().filterMode->addItem(tr("Wildcard"),QRegExp::Wildcard); qxt_d().filterMode->addItem(tr("Regular Expression"),QRegExp::RegExp); qxt_d().filterMode->setEnabled(false); connect(qxt_d().filterMode,SIGNAL(activated (int)),&qxt_d(),SLOT(filterModeChoosen(int))); QVBoxLayout * groupBoxLayout = new QVBoxLayout(group); groupBoxLayout->addWidget(qxt_d().matchCaseOption); groupBoxLayout->addWidget(qxt_d().filterModeOption); groupBoxLayout->addWidget(qxt_d().filterMode); group->setLayout(groupBoxLayout); dlgLayout->addWidget(group); //group->setCollapsed(); group->setChecked(false); /*end group box*/ #endif /*a button to cancel the selection*/ QPushButton *cancelButton = new QPushButton(tr("Cancel")); dlgLayout->addWidget(cancelButton); connect(cancelButton,SIGNAL(released()),this,SLOT(reject())); QWidget::setTabOrder(qxt_d().lineEditFilter,qxt_d().listingTreeView); //QWidget::setTabOrder(qxt_d().listingTreeView,group); //QWidget::setTabOrder(group,qxt_d().matchCaseOption); QWidget::setTabOrder(qxt_d().listingTreeView,qxt_d().matchCaseOption); QWidget::setTabOrder(qxt_d().matchCaseOption,qxt_d().filterModeOption); QWidget::setTabOrder(qxt_d().filterModeOption,qxt_d().filterMode); QWidget::setTabOrder(qxt_d().filterMode,cancelButton); /*set the layout and title*/ setLayout(dlgLayout); setWindowTitle(tr("Filter")); } QRegExp::PatternSyntax QxtFilterDialog::patternSyntax () { return qxt_d().syntax; } void QxtFilterDialog::setPatternSyntax (QRegExp::PatternSyntax syntax) { qxt_d().syntax = syntax; qxt_d().updateFilterPattern(); } void QxtFilterDialog::setSourceModel(QAbstractItemModel *model) { qxt_d().listingTreeView->setModel(0); qxt_d().proxyModel->setSourceModel(model); qxt_d().model = model; qxt_d().listingTreeView->setModel(qxt_d().proxyModel); if(model) qxt_d().listingTreeView->setCurrentIndex(model->index(0,0)); } void QxtFilterDialog::setLookupColumn (int column) { qxt_d().proxyModel->setHeaderData(qxt_d().lookupColumn,Qt::Horizontal,QVariant(),Qt::ForegroundRole); qxt_d().lookupColumn = column; qxt_d().proxyModel->setFilterKeyColumn(qxt_d().lookupColumn); qxt_d().proxyModel->setHeaderData(qxt_d().lookupColumn,Qt::Horizontal,QColor(Qt::red),Qt::ForegroundRole); } void QxtFilterDialog::setLookupRole (int role) { qxt_d().lookupRole = role; qxt_d().proxyModel->setFilterRole(qxt_d().lookupRole); } QAbstractItemModel * QxtFilterDialog::sourceModel( ) const { return qxt_d().model; } int QxtFilterDialog::lookupColumn ( ) const { return qxt_d().lookupColumn; } int QxtFilterDialog::lookupRole ( ) const { return qxt_d().lookupRole; } QString QxtFilterDialog::filterText ( ) const { return qxt_d().lineEditFilter->text(); } void QxtFilterDialog::setFilterText (QString text) { qxt_d().lineEditFilter->setText(text); } QModelIndex QxtFilterDialog::selectedIndex() const { return qxt_d().selectedIndex; } void QxtFilterDialog::setCaseSensitivity (Qt::CaseSensitivity caseSensitivity) { qxt_d().caseSensitivity = caseSensitivity; qxt_d().updateFilterPattern(); } QModelIndex QxtFilterDialog::getIndex(QWidget* parent, QAbstractItemModel *model, int column, int role, QString filterText) { QxtFilterDialog dialog(parent); dialog.setSourceModel(model); dialog.setLookupColumn(column); dialog.setLookupRole(role); dialog.setFilterText(filterText); if(dialog.qxt_d().proxyModel->rowCount() == 1){ QModelIndex source; QModelIndex filtered = dialog.qxt_d().proxyModel->index(0,column); if(filtered.isValid()){ source = dialog.qxt_d().proxyModel->mapToSource(filtered); } return source; } int ret = dialog.exec(); if(ret == QDialog::Accepted) return dialog.selectedIndex(); return QModelIndex(); } void QxtFilterDialog::done ( int r ) { if(r==QDialog::Accepted){ qxt_d().selectedIndex = QModelIndex(); QModelIndex proxyIndex = qxt_d().listingTreeView->currentIndex(); proxyIndex = qxt_d().proxyModel->index(proxyIndex.row(),lookupColumn()); if(proxyIndex.isValid()) { qxt_d().selectedIndex = qxt_d().proxyModel->mapToSource(proxyIndex); } } else qxt_d().selectedIndex = QModelIndex(); return QDialog::done(r); } void QxtFilterDialog::accept () { return QDialog::accept(); } void QxtFilterDialog::reject () { return QDialog::reject(); } void QxtFilterDialog::keyPressEvent(QKeyEvent *e) { //reimplemented to disable the default button ! if (!e->modifiers() || (e->modifiers() & Qt::KeypadModifier && e->key() == Qt::Key_Enter)) { switch (e->key()) { case Qt::Key_Enter: case Qt::Key_Return: accept(); return; } } QDialog::keyPressEvent(e); } libqxt-0.6.2/src/gui/qxtfilterdialog.h000066400000000000000000000041771215241066400177620ustar00rootroot00000000000000#ifndef QXTFILTERDIALOG_H_INCLUDED #define QXTFILTERDIALOG_H_INCLUDED #include #include #include "qxtglobal.h" #include "qxtpimpl.h" class QAbstractItemModel; class QxtFilterDialogPrivate; class QKeyEvent; class QXT_GUI_EXPORT QxtFilterDialog : public QDialog { Q_OBJECT Q_PROPERTY(int lookupColumn READ lookupColumn WRITE setLookupColumn ) Q_PROPERTY(int lookupRole READ lookupRole WRITE setLookupRole ) Q_PROPERTY(QString filterText READ filterText WRITE setFilterText ) public: QxtFilterDialog(QWidget *parent = 0); void setSourceModel (QAbstractItemModel *model); QRegExp::PatternSyntax patternSyntax (); QAbstractItemModel * sourceModel ( ) const; int lookupColumn ( ) const; int lookupRole ( ) const; QString filterText ( ) const; QModelIndex selectedIndex ( ) const; static QModelIndex getIndex (QWidget* parent = 0, QAbstractItemModel *model = 0 , int column = 0, int role = Qt::DisplayRole , QString filterText = QString()); protected: virtual void keyPressEvent (QKeyEvent *e); public slots: virtual void done ( int r ); virtual void accept (); virtual void reject (); void setPatternSyntax (QRegExp::PatternSyntax syntax); void setCaseSensitivity (Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive); void setFilterText (QString text); void setLookupColumn (int column); void setLookupRole (int role); private: QXT_DECLARE_PRIVATE(QxtFilterDialog); }; #endif libqxt-0.6.2/src/gui/qxtfilterdialog_p.h000066400000000000000000000025341215241066400202740ustar00rootroot00000000000000#ifndef QXTFILTERDIALOG_P_H_INCLUDED #define QXTFILTERDIALOG_P_H_INCLUDED #include #include #include #include #include "qxtpimpl.h" class QxtFilterDialog; class QAbstractItemModel; class QTreeView; class QSortFilterProxyModel; class QLineEdit; class QCheckBox; class QComboBox; class QxtFilterDialogPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QxtFilterDialogPrivate(); QXT_DECLARE_PUBLIC(QxtFilterDialog); /*widgets*/ QCheckBox * matchCaseOption; QCheckBox * filterModeOption; QComboBox * filterMode; QTreeView * listingTreeView; QLineEdit * lineEditFilter; /*models*/ QPointer model; QSortFilterProxyModel* proxyModel; /*properties*/ int lookupColumn; int lookupRole; QRegExp::PatternSyntax syntax; Qt::CaseSensitivity caseSensitivity; /*result*/ QModelIndex selectedIndex; /*member functions*/ void updateFilterPattern(); public slots: void createRegExpPattern(const QString &rawText); void filterModeOptionStateChanged(const int state); void matchCaseOptionStateChanged(const int state); void filterModeChoosen(int index); }; #endif libqxt-0.6.2/src/gui/qxtflowview.cpp000066400000000000000000000512161215241066400175060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ** ** This is a derived work of PictureFlow (http://pictureflow.googlecode.com) ** The original code was distributed under the following terms: ** ** Copyright (C) 2008 Ariya Hidayat (ariya@kde.org) ** Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and associated documentation files (the "Software"), to deal ** in the Software without restriction, including without limitation the rights ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ** copies of the Software, and to permit persons to whom the Software is ** furnished to do so, subject to the following conditions: ** ** The above copyright notice and this permission notice shall be included in ** all copies or substantial portions of the Software. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ** THE SOFTWARE. ****************************************************************************/ #include "qxtflowview_p.h" #include /*! \class QxtFlowView \inmodule QxtGui \brief The QxtFlowView widget is an item view for images with impressive flow effects A widget for showin images with animation effects, like Apple's Cover Flow (in iTunes and iPod). Images are arranged in form of slides, one main slide is shown at the center with few slides on the left and right sides of the center slide. When the next or previous slide is brought to the front, the whole slides flow to the left or to the right with smooth animation effect; until the new slide is finally placed at the center. \image qxtflowview.png "QxtFlowView in action." This is a derived work of \l{http://pictureflow.googlecode.com}{PictureFlow} */ /*! \enum QxtFlowView::ReflectionEffect \brief This enum describes available reflection effects. \value NoReflection No reflection \value PlainReflection Plain reflection \value BlurredReflection Blurred reflection */ /*! \fn QxtFlowView::currentIndexChanged(QModelIndex index) This signal is emitted whenever the current \a index has changed. */ /*! Constructs a new QxtFlowView with \a parent. */ QxtFlowView::QxtFlowView(QWidget* parent): QWidget(parent) { d = new QxtFlowViewPrivate; d->model = 0; d->picrole = Qt::DecorationRole; d->textrole = Qt::DisplayRole; d->piccolumn = 0; d->textcolumn = 0; d->state = new QxtFlowViewState; d->state->reset(); d->state->reposition(); d->renderer = new QxtFlowViewSoftwareRenderer; d->renderer->state = d->state; d->renderer->widget = this; d->renderer->init(); d->animator = new QxtFlowViewAnimator; d->animator->state = d->state; QObject::connect(&d->animator->animateTimer, SIGNAL(timeout()), this, SLOT(updateAnimation())); QObject::connect(&d->triggerTimer, SIGNAL(timeout()), this, SLOT(render())); setAttribute(Qt::WA_StaticContents, true); setAttribute(Qt::WA_OpaquePaintEvent, true); setAttribute(Qt::WA_NoSystemBackground, true); } /*! Destructs the flow view. */ QxtFlowView::~QxtFlowView() { delete d->renderer; delete d->animator; delete d->state; delete d; } /*! Sets the \a model. \bold {Note:} The view does not take ownership of the model unless it is the model's parent object because it may be shared between many different views. */ void QxtFlowView::setModel(QAbstractItemModel * model) { d->setModel(model); } /*! Returns the model. */ QAbstractItemModel * QxtFlowView::model() { return d->model; } /*! \property QxtFlowView::backgroundColor \brief the background color The default value is black. */ QColor QxtFlowView::backgroundColor() const { return QColor(d->state->backgroundColor); } void QxtFlowView::setBackgroundColor(const QColor& c) { d->state->backgroundColor = c.rgb(); triggerRender(); } /*! \property QxtFlowView::slideSize \brief the slide size The slide dimensions are in pixels. The default value is 150x200. */ QSize QxtFlowView::slideSize() const { return QSize(d->state->slideWidth, d->state->slideHeight); } void QxtFlowView::setSlideSize(QSize size) { d->state->slideWidth = size.width(); d->state->slideHeight = size.height(); d->state->reposition(); triggerRender(); } /*! \property QxtFlowView::reflectionEffect \brief the reflection effect The default value is PlainReflection. */ QxtFlowView::ReflectionEffect QxtFlowView::reflectionEffect() const { return d->state->reflectionEffect; } void QxtFlowView::setReflectionEffect(ReflectionEffect effect) { d->state->reflectionEffect = effect; d->reset(); } /*! \property QxtFlowView::pictureRole \brief the picture role The default value is Qt::DecorationRole. */ int QxtFlowView::pictureRole() { return d->picrole; } void QxtFlowView::setPictureRole(int a) { d->picrole = a; d->reset(); } /*! \property QxtFlowView::pictureColumn \brief the picture column The default value is \c 0. */ int QxtFlowView::pictureColumn() { return d->piccolumn; } void QxtFlowView::setPictureColumn(int a) { d->piccolumn = a; d->reset(); } #if 0 int QxtFlowView::textRole() { return d->textrole; } void QxtFlowView::setTextRole(int a) { d->textrole = a; d->reset(); } int QxtFlowView::textColumn() { return d->textcolumn; } void QxtFlowView::setTextColumn(int a) { d->textcolumn = a; d->reset(); } #endif /*! \property QxtFlowView::rootIndex \brief the root index The root index is the parent index to the view's toplevel items. The root can be invalid. */ QModelIndex QxtFlowView::rootIndex() const { return d->rootindex; } void QxtFlowView::setRootIndex(QModelIndex index) { d->rootindex = index; } /*! \property QxtFlowView::currentIndex \brief the current index The slide of the current index is shown in the middle of the viewport. \bold {Note:} No animation effect will be produced. \sa showSlide() */ QModelIndex QxtFlowView::currentIndex() const { if (!d->model) return QModelIndex(); return d->currentcenter; } void QxtFlowView::setCurrentIndex(QModelIndex index) { d->setCurrentIndex(index); } /*! Rerender the widget. Normally this function will be automatically invoked whenever necessary, e.g. during the transition animation. */ void QxtFlowView::render() { d->renderer->dirty = true; update(); } /*! Schedules a rendering update. Unlike render(), this function does not cause immediate rendering.*/ void QxtFlowView::triggerRender() { d->triggerRender(); } /*! Shows previous slide using animation effect. */ void QxtFlowView::showPrevious() { int step = d->animator->step; int center = d->state->centerIndex; if (step > 0) d->animator->start(center); if (step == 0) if (center > 0) d->animator->start(center - 1); if (step < 0) d->animator->target = qMax(0, center - 2); } /*! Shows next slide using animation effect. */ void QxtFlowView::showNext() { int step = d->animator->step; int center = d->state->centerIndex; if (step < 0) d->animator->start(center); if (step == 0) if (center < d->state->slideImages.count() - 1) d->animator->start(center + 1); if (step > 0) d->animator->target = qMin(center + 2, d->state->slideImages.count() - 1); } /*! Go to specified slide at \a index using animation effect. */ void QxtFlowView::showSlide(QModelIndex index) { int r = d->modelmap.indexOf(index); if (r < 0) return; d->showSlide(r); } /*! \reimp */ void QxtFlowView::keyPressEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Left) { if (event->modifiers() == Qt::ControlModifier) d->showSlide(currentIndex().row() - 10); else showPrevious(); event->accept(); return; } if (event->key() == Qt::Key_Right) { if (event->modifiers() == Qt::ControlModifier) d->showSlide(currentIndex().row() + 10); else showNext(); event->accept(); return; } event->ignore(); } /*! \reimp */ void QxtFlowView::mousePressEvent(QMouseEvent* event) { d->lastgrabpos = event->pos(); } /*! \reimp */ void QxtFlowView::mouseMoveEvent(QMouseEvent * event) { int i = (event->pos() - d->lastgrabpos).x() / (d->state->slideWidth / 4); if (i > 0) { showPrevious(); d->lastgrabpos = event->pos(); } if (i < 0) { showNext(); d->lastgrabpos = event->pos(); } } /*! \reimp */ void QxtFlowView::mouseReleaseEvent(QMouseEvent* event) { Q_UNUSED(event); } /*! \reimp */ void QxtFlowView::paintEvent(QPaintEvent* event) { Q_UNUSED(event); d->renderer->paint(); } /*! \reimp */ void QxtFlowView::resizeEvent(QResizeEvent* event) { triggerRender(); QWidget::resizeEvent(event); } /*! \reimp */ void QxtFlowView::wheelEvent(QWheelEvent * event) { if (event->orientation() == Qt::Horizontal) { event->ignore(); } else { int numSteps = -((event->delta() / 8) / 15); if (numSteps > 0) { for (int i = 0;i < numSteps;i++) { showNext(); } } else { for (int i = numSteps;i < 0;i++) { showPrevious(); } } event->accept(); } } /*! \internal */ void QxtFlowView::updateAnimation() { int old_center = d->state->centerIndex; d->animator->update(); triggerRender(); if (d->state->centerIndex != old_center) { d->currentcenter = d->modelmap.at(d->state->centerIndex); emit currentIndexChanged(d->currentcenter); } } void QxtFlowViewPrivate::columnsAboutToBeInserted(const QModelIndex & parent, int start, int end) { Q_UNUSED(parent); Q_UNUSED(start); Q_UNUSED(end); } void QxtFlowViewPrivate::columnsAboutToBeRemoved(const QModelIndex & parent, int start, int end) { Q_UNUSED(parent); Q_UNUSED(start); Q_UNUSED(end); } void QxtFlowViewPrivate::columnsInserted(const QModelIndex & parent, int start, int end) { Q_UNUSED(parent); Q_UNUSED(start); Q_UNUSED(end); } void QxtFlowViewPrivate::columnsRemoved(const QModelIndex & parent, int start, int end) { Q_UNUSED(parent); Q_UNUSED(start); Q_UNUSED(end); } void QxtFlowViewPrivate::dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight) { Q_UNUSED(topLeft); Q_UNUSED(bottomRight); if (topLeft.parent() != rootindex) return; if (bottomRight.parent() != rootindex) return; int start = topLeft.row(); int end = bottomRight.row(); for (int i = start;i <= end;i++) replaceSlide(i, qvariant_cast(model->data(model->index(i, piccolumn, rootindex), picrole))); } void QxtFlowViewPrivate::headerDataChanged(Qt::Orientation orientation, int first, int last) { Q_UNUSED(orientation); Q_UNUSED(first); Q_UNUSED(last); } void QxtFlowViewPrivate::layoutAboutToBeChanged() { } void QxtFlowViewPrivate::layoutChanged() { reset(); setCurrentIndex(currentcenter); } void QxtFlowViewPrivate::modelAboutToBeReset() { } void QxtFlowViewPrivate::modelReset() { reset(); } void QxtFlowViewPrivate::rowsAboutToBeInserted(const QModelIndex & parent, int start, int end) { Q_UNUSED(parent); Q_UNUSED(start); Q_UNUSED(end); } void QxtFlowViewPrivate::rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end) { Q_UNUSED(parent); Q_UNUSED(start); Q_UNUSED(end); } void QxtFlowViewPrivate::rowsInserted(const QModelIndex & parent, int start, int end) { if (rootindex != parent) return; for (int i = start;i <= end;i++) { QModelIndex idx = model->index(i, piccolumn, rootindex); insertSlide(i, qvariant_cast(model->data(idx, picrole))); modelmap.insert(i, idx); } } void QxtFlowViewPrivate::rowsRemoved(const QModelIndex & parent, int start, int end) { if (rootindex != parent) return; for (int i = start;i <= end;i++) { removeSlide(i); modelmap.removeAt(i); } } void QxtFlowViewPrivate::setModel(QAbstractItemModel * m) { if (model) { disconnect(this->model, SIGNAL(columnsAboutToBeInserted(const QModelIndex & , int , int)), this, SLOT(columnsAboutToBeInserted(const QModelIndex & , int , int))); disconnect(this->model, SIGNAL(columnsAboutToBeRemoved(const QModelIndex & , int , int)), this, SLOT(columnsAboutToBeRemoved(const QModelIndex & , int , int))); disconnect(this->model, SIGNAL(columnsInserted(const QModelIndex & , int , int)), this, SLOT(columnsInserted(const QModelIndex & , int , int))); disconnect(this->model, SIGNAL(columnsRemoved(const QModelIndex & , int , int)), this, SLOT(columnsRemoved(const QModelIndex & , int , int))); disconnect(this->model, SIGNAL(dataChanged(const QModelIndex & , const QModelIndex &)), this, SLOT(dataChanged(const QModelIndex & , const QModelIndex &))); disconnect(this->model, SIGNAL(headerDataChanged(Qt::Orientation , int , int)), this, SLOT(headerDataChanged(Qt::Orientation , int , int))); disconnect(this->model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(layoutAboutToBeChanged())); disconnect(this->model, SIGNAL(layoutChanged()), this, SLOT(layoutChanged())); disconnect(this->model, SIGNAL(modelAboutToBeReset()), this, SLOT(modelAboutToBeReset())); disconnect(this->model, SIGNAL(modelReset()), this, SLOT(modelReset())); disconnect(this->model, SIGNAL(rowsAboutToBeInserted(const QModelIndex & , int , int)), this, SLOT(rowsAboutToBeInserted(const QModelIndex & , int , int))); disconnect(this->model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex & , int , int)), this, SLOT(rowsAboutToBeRemoved(const QModelIndex & , int , int))); disconnect(this->model, SIGNAL(rowsInserted(const QModelIndex & , int , int)), this, SLOT(rowsInserted(const QModelIndex & , int , int))); disconnect(this->model, SIGNAL(rowsRemoved(const QModelIndex & , int , int)), this, SLOT(rowsRemoved(const QModelIndex & , int , int))); } model = m; if (model) { rootindex = model->parent(QModelIndex()); connect(this->model, SIGNAL(columnsAboutToBeInserted(const QModelIndex & , int , int)), this, SLOT(columnsAboutToBeInserted(const QModelIndex & , int , int))); connect(this->model, SIGNAL(columnsAboutToBeRemoved(const QModelIndex & , int , int)), this, SLOT(columnsAboutToBeRemoved(const QModelIndex & , int , int))); connect(this->model, SIGNAL(columnsInserted(const QModelIndex & , int , int)), this, SLOT(columnsInserted(const QModelIndex & , int , int))); connect(this->model, SIGNAL(columnsRemoved(const QModelIndex & , int , int)), this, SLOT(columnsRemoved(const QModelIndex & , int , int))); connect(this->model, SIGNAL(dataChanged(const QModelIndex & , const QModelIndex &)), this, SLOT(dataChanged(const QModelIndex & , const QModelIndex &))); connect(this->model, SIGNAL(headerDataChanged(Qt::Orientation , int , int)), this, SLOT(headerDataChanged(Qt::Orientation , int , int))); connect(this->model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(layoutAboutToBeChanged())); connect(this->model, SIGNAL(layoutChanged()), this, SLOT(layoutChanged())); connect(this->model, SIGNAL(modelAboutToBeReset()), this, SLOT(modelAboutToBeReset())); connect(this->model, SIGNAL(modelReset()), this, SLOT(modelReset())); connect(this->model, SIGNAL(rowsAboutToBeInserted(const QModelIndex & , int , int)), this, SLOT(rowsAboutToBeInserted(const QModelIndex & , int , int))); connect(this->model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex & , int , int)), this, SLOT(rowsAboutToBeRemoved(const QModelIndex & , int , int))); connect(this->model, SIGNAL(rowsInserted(const QModelIndex & , int , int)), this, SLOT(rowsInserted(const QModelIndex & , int , int))); connect(this->model, SIGNAL(rowsRemoved(const QModelIndex & , int , int)), this, SLOT(rowsRemoved(const QModelIndex & , int , int))); } reset(); } void QxtFlowViewPrivate::clear() { int c = state->slideImages.count(); for (int i = 0; i < c; i++) delete state->slideImages[i]; state->slideImages.resize(0); state->reset(); modelmap.clear(); triggerRender(); } void QxtFlowViewPrivate::triggerRender() { triggerTimer.setSingleShot(true); triggerTimer.start(0); } void QxtFlowViewPrivate::insertSlide(int index, const QImage& image) { state->slideImages.insert(index, new QImage(image)); triggerRender(); } void QxtFlowViewPrivate::replaceSlide(int index, const QImage& image) { Q_ASSERT((index >= 0) && (index < state->slideImages.count())); QImage* i = image.isNull() ? 0 : new QImage(image); delete state->slideImages[index]; state->slideImages[index] = i; triggerRender(); } void QxtFlowViewPrivate::removeSlide(int index) { delete state->slideImages[index]; state->slideImages.remove(index); triggerRender(); } void QxtFlowViewPrivate::showSlide(int index) { if (index == state->centerSlide.slideIndex) return; animator->start(index); } void QxtFlowViewPrivate::reset() { clear(); if (model) { for (int i = 0;i < model->rowCount(rootindex);i++) { QModelIndex idx = model->index(i, piccolumn, rootindex); insertSlide(i, qvariant_cast(model->data(idx, picrole))); modelmap.insert(i, idx); } if(modelmap.count()) currentcenter=modelmap.at(0); else currentcenter=QModelIndex(); } triggerRender(); } void QxtFlowViewPrivate::setCurrentIndex(QModelIndex index) { if (model->parent(index) != rootindex) return; int r = modelmap.indexOf(index); if (r < 0) return; state->centerIndex = r; state->reset(); animator->stop(r); triggerRender(); } libqxt-0.6.2/src/gui/qxtflowview.h000066400000000000000000000121521215241066400171470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ** ** This is a derived work of PictureFlow (http://pictureflow.googlecode.com) ** The original code was distributed under the following terms: ** ** Copyright (C) 2008 Ariya Hidayat (ariya@kde.org) ** Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and associated documentation files (the "Software"), to deal ** in the Software without restriction, including without limitation the rights ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ** copies of the Software, and to permit persons to whom the Software is ** furnished to do so, subject to the following conditions: ** ** The above copyright notice and this permission notice shall be included in ** all copies or substantial portions of the Software. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ** THE SOFTWARE. ****************************************************************************/ #ifndef QXT_FLOWVIEW_H #define QXT_FLOWVIEW_H #include #include #include "qxtglobal.h" class QxtFlowViewPrivate; class QXT_GUI_EXPORT QxtFlowView : public QWidget { Q_OBJECT Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor) Q_PROPERTY(QSize slideSize READ slideSize WRITE setSlideSize) Q_PROPERTY(QModelIndex currentIndex READ currentIndex WRITE setCurrentIndex) Q_PROPERTY(int pictureRole READ pictureRole WRITE setPictureRole) Q_PROPERTY(int pictureColumn READ pictureColumn WRITE setPictureColumn) Q_PROPERTY(QModelIndex rootIndex READ rootIndex WRITE setRootIndex) Q_PROPERTY(ReflectionEffect reflectionEffect READ reflectionEffect WRITE setReflectionEffect) Q_ENUMS(ReflectionEffect) #if 0 Q_PROPERTY(int textRole READ textRole WRITE setTextRole) Q_PROPERTY(int textColumn READ textColumn WRITE setTextColumn) #endif public: enum ReflectionEffect { NoReflection, PlainReflection, BlurredReflection }; QxtFlowView(QWidget* parent = 0); ~QxtFlowView(); void setModel(QAbstractItemModel * model); QAbstractItemModel * model(); QColor backgroundColor() const; void setBackgroundColor(const QColor& c); QSize slideSize() const; void setSlideSize(QSize size); QModelIndex currentIndex() const; QModelIndex rootIndex() const; void setRootIndex(QModelIndex index); ReflectionEffect reflectionEffect() const; void setReflectionEffect(ReflectionEffect effect); int pictureRole(); void setPictureRole(int); int pictureColumn(); void setPictureColumn(int); #if 0 int textRole(); void setTextRole(int); int textColumn(); void setTextColumn(int); #endif public Q_SLOTS: void setCurrentIndex(QModelIndex index); void showPrevious(); void showNext(); void showSlide(QModelIndex index); void render(); void triggerRender(); Q_SIGNALS: void currentIndexChanged(QModelIndex index); protected: virtual void paintEvent(QPaintEvent *event); virtual void keyPressEvent(QKeyEvent* event); virtual void mousePressEvent(QMouseEvent* event); virtual void mouseMoveEvent(QMouseEvent * event); virtual void mouseReleaseEvent(QMouseEvent* event); virtual void resizeEvent(QResizeEvent* event); virtual void wheelEvent(QWheelEvent * event); private Q_SLOTS: void updateAnimation(); private: QxtFlowViewPrivate* d; }; #endif // PICTUREFLOW_H libqxt-0.6.2/src/gui/qxtflowview_p.cpp000066400000000000000000000535671215241066400200400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ** ** This is a derived work of QxtFlowView (http://pictureflow.googlecode.com) ** The original code was distributed under the following terms: ** ** Copyright (C) 2008 Ariya Hidayat (ariya@kde.org) ** Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and associated documentation files (the "Software"), to deal ** in the Software without restriction, including without limitation the rights ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ** copies of the Software, and to permit persons to whom the Software is ** furnished to do so, subject to the following conditions: ** ** The above copyright notice and this permission notice shall be included in ** all copies or substantial portions of the Software. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ** THE SOFTWARE. ****************************************************************************/ #include "qxtflowview_p.h" // ------------- QxtFlowViewState --------------------------------------- QxtFlowViewState::QxtFlowViewState(): backgroundColor(0), slideWidth(150), slideHeight(200), reflectionEffect(QxtFlowView::BlurredReflection), centerIndex(0) { } QxtFlowViewState::~QxtFlowViewState() { for (int i = 0; i < (int)slideImages.count(); i++) delete slideImages[i]; } // readjust the settings, call this when slide dimension is changed void QxtFlowViewState::reposition() { angle = 70 * IANGLE_MAX / 360; // approx. 70 degrees tilted offsetX = slideWidth / 2 * (PFREAL_ONE - fcos(angle)); offsetY = slideWidth / 2 * fsin(angle); offsetX += slideWidth * PFREAL_ONE; offsetY += slideWidth * PFREAL_ONE / 4; spacing = 40; } // adjust slides so that they are in "steady state" position void QxtFlowViewState::reset() { centerSlide.angle = 0; centerSlide.cx = 0; centerSlide.cy = 0; centerSlide.slideIndex = centerIndex; centerSlide.blend = 256; leftSlides.resize(6); for (int i = 0; i < (int)leftSlides.count(); i++) { SlideInfo& si = leftSlides[i]; si.angle = angle; si.cx = -(offsetX + spacing * i * PFREAL_ONE); si.cy = offsetY; si.slideIndex = centerIndex - 1 - i; si.blend = 256; if (i == (int)leftSlides.count() - 2) si.blend = 128; if (i == (int)leftSlides.count() - 1) si.blend = 0; } rightSlides.resize(6); for (int i = 0; i < (int)rightSlides.count(); i++) { SlideInfo& si = rightSlides[i]; si.angle = -angle; si.cx = offsetX + spacing * i * PFREAL_ONE; si.cy = offsetY; si.slideIndex = centerIndex + 1 + i; si.blend = 256; if (i == (int)rightSlides.count() - 2) si.blend = 128; if (i == (int)rightSlides.count() - 1) si.blend = 0; } } // ------------- QxtFlowViewAnimator --------------------------------------- QxtFlowViewAnimator::QxtFlowViewAnimator(): state(0), target(0), step(0), frame(0) { } void QxtFlowViewAnimator::start(int slide) { target = slide; if (!animateTimer.isActive() && state) { step = (target < state->centerSlide.slideIndex) ? -1 : 1; animateTimer.start(30); } } void QxtFlowViewAnimator::stop(int slide) { step = 0; target = slide; frame = slide << 16; animateTimer.stop(); } void QxtFlowViewAnimator::update() { if (!animateTimer.isActive()) return; if (step == 0) return; if (!state) return; int speed = 16384 / 4; #if 1 // deaccelerate when approaching the target const int max = 2 * 65536; int fi = frame; fi -= (target << 16); if (fi < 0) fi = -fi; fi = qMin(fi, max); int ia = IANGLE_MAX * (fi - max / 2) / (max * 2); speed = 512 + 16384 * (PFREAL_ONE + fsin(ia)) / PFREAL_ONE; #endif frame += speed * step; int index = frame >> 16; int pos = frame & 0xffff; int neg = 65536 - pos; int tick = (step < 0) ? neg : pos; PFreal ftick = (tick * PFREAL_ONE) >> 16; if (step < 0) index++; if (state->centerIndex != index) { state->centerIndex = index; frame = index << 16; state->centerSlide.slideIndex = state->centerIndex; for (int i = 0; i < (int)state->leftSlides.count(); i++) state->leftSlides[i].slideIndex = state->centerIndex - 1 - i; for (int i = 0; i < (int)state->rightSlides.count(); i++) state->rightSlides[i].slideIndex = state->centerIndex + 1 + i; } state->centerSlide.angle = (step * tick * state->angle) >> 16; state->centerSlide.cx = -step * fmul(state->offsetX, ftick); state->centerSlide.cy = fmul(state->offsetY, ftick); if (state->centerIndex == target) { stop(target); state->reset(); return; } for (int i = 0; i < (int)state->leftSlides.count(); i++) { SlideInfo& si = state->leftSlides[i]; si.angle = state->angle; si.cx = -(state->offsetX + state->spacing * i * PFREAL_ONE + step * state->spacing * ftick); si.cy = state->offsetY; } for (int i = 0; i < (int)state->rightSlides.count(); i++) { SlideInfo& si = state->rightSlides[i]; si.angle = -state->angle; si.cx = state->offsetX + state->spacing * i * PFREAL_ONE - step * state->spacing * ftick; si.cy = state->offsetY; } if (step > 0) { PFreal ftick = (neg * PFREAL_ONE) >> 16; state->rightSlides[0].angle = -(neg * state->angle) >> 16; state->rightSlides[0].cx = fmul(state->offsetX, ftick); state->rightSlides[0].cy = fmul(state->offsetY, ftick); } else { PFreal ftick = (pos * PFREAL_ONE) >> 16; state->leftSlides[0].angle = (pos * state->angle) >> 16; state->leftSlides[0].cx = -fmul(state->offsetX, ftick); state->leftSlides[0].cy = fmul(state->offsetY, ftick); } // must change direction ? if (target < index) if (step > 0) step = -1; if (target > index) if (step < 0) step = 1; // the first and last slide must fade in/fade out int nleft = state->leftSlides.count(); int nright = state->rightSlides.count(); int fade = pos / 256; for (int index = 0; index < nleft; index++) { int blend = 256; if (index == nleft - 1) blend = (step > 0) ? 0 : 128 - fade / 2; if (index == nleft - 2) blend = (step > 0) ? 128 - fade / 2 : 256 - fade / 2; if (index == nleft - 3) blend = (step > 0) ? 256 - fade / 2 : 256; state->leftSlides[index].blend = blend; } for (int index = 0; index < nright; index++) { int blend = (index < nright - 2) ? 256 : 128; if (index == nright - 1) blend = (step > 0) ? fade / 2 : 0; if (index == nright - 2) blend = (step > 0) ? 128 + fade / 2 : fade / 2; if (index == nright - 3) blend = (step > 0) ? 256 : 128 + fade / 2; state->rightSlides[index].blend = blend; } } // ------------- QxtFlowViewSoftwareRenderer --------------------------------------- QxtFlowViewSoftwareRenderer::QxtFlowViewSoftwareRenderer(): QxtFlowViewAbstractRenderer(), size(0, 0), bgcolor(0), effect(-1), blankSurface(0) { } QxtFlowViewSoftwareRenderer::~QxtFlowViewSoftwareRenderer() { surfaceCache.clear(); buffer = QImage(); delete blankSurface; } void QxtFlowViewSoftwareRenderer::paint() { if (!widget) return; if (widget->size() != size) init(); if (state->backgroundColor != bgcolor) { bgcolor = state->backgroundColor; surfaceCache.clear(); } if ((int)(state->reflectionEffect) != effect) { effect = (int)state->reflectionEffect; surfaceCache.clear(); } if (dirty) render(); QPainter painter(widget); painter.drawImage(QPoint(0, 0), buffer); } void QxtFlowViewSoftwareRenderer::init() { if (!widget) return; surfaceCache.clear(); blankSurface = 0; size = widget->size(); int ww = size.width(); int wh = size.height(); int w = (ww + 1) / 2; int h = (wh + 1) / 2; #ifdef PICTUREFLOW_QT4 buffer = QImage(ww, wh, QImage::Format_RGB32); #endif #if defined(PICTUREFLOW_QT3) || defined(PICTUREFLOW_QT2) buffer.create(ww, wh, 32); #endif buffer.fill(bgcolor); rays.resize(w*2); for (int i = 0; i < w; i++) { PFreal gg = ((PFREAL_ONE >> 1) + i * PFREAL_ONE) / (2 * h); rays[w-i-1] = -gg; rays[w+i] = gg; } dirty = true; } // TODO: optimize this with lookup tables static QRgb blendColor(QRgb c1, QRgb c2, int blend) { int r = qRed(c1) * blend / 256 + qRed(c2) * (256 - blend) / 256; int g = qGreen(c1) * blend / 256 + qGreen(c2) * (256 - blend) / 256; int b = qBlue(c1) * blend / 256 + qBlue(c2) * (256 - blend) / 256; return qRgb(r, g, b); } static QImage* prepareSurface(const QImage* slideImage, int w, int h, QRgb bgcolor, QxtFlowView::ReflectionEffect reflectionEffect) { #ifdef PICTUREFLOW_QT4 Qt::TransformationMode mode = Qt::SmoothTransformation; QImage img = slideImage->scaled(w, h, Qt::IgnoreAspectRatio, mode); #endif #if defined(PICTUREFLOW_QT3) || defined(PICTUREFLOW_QT2) QImage img = slideImage->smoothScale(w, h); #endif // slightly larger, to accommodate for the reflection int hs = h * 2; int hofs = h / 3; // offscreen buffer: black is sweet #ifdef PICTUREFLOW_QT4 QImage* result = new QImage(hs, w, QImage::Format_RGB32); #endif #if defined(PICTUREFLOW_QT3) || defined(PICTUREFLOW_QT2) QImage* result = new QImage; result->create(hs, w, 32); #endif result->fill(bgcolor); // transpose the image, this is to speed-up the rendering // because we process one column at a time // (and much better and faster to work row-wise, i.e in one scanline) for (int x = 0; x < w; x++) for (int y = 0; y < h; y++) result->setPixel(hofs + y, x, img.pixel(x, y)); if (reflectionEffect != QxtFlowView::NoReflection) { // create the reflection int ht = hs - h - hofs; int hte = ht; for (int x = 0; x < w; x++) for (int y = 0; y < ht; y++) { QRgb color = img.pixel(x, img.height() - y - 1); result->setPixel(h + hofs + y, x, blendColor(color, bgcolor, 128*(hte - y) / hte)); } if (reflectionEffect == QxtFlowView::BlurredReflection) { // blur the reflection everything first // Based on exponential blur algorithm by Jani Huhtanen QRect rect(hs / 2, 0, hs / 2, w); rect &= result->rect(); int r1 = rect.top(); int r2 = rect.bottom(); int c1 = rect.left(); int c2 = rect.right(); int bpl = result->bytesPerLine(); int rgba[4]; unsigned char* p; // how many times blur is applied? // for low-end system, limit this to only 1 loop for (int loop = 0; loop < 2; loop++) { for (int col = c1; col <= c2; col++) { p = result->scanLine(r1) + col * 4; for (int i = 0; i < 3; i++) rgba[i] = p[i] << 4; p += bpl; for (int j = r1; j < r2; j++, p += bpl) for (int i = 0; i < 3; i++) p[i] = (rgba[i] += (((p[i] << 4) - rgba[i])) >> 1) >> 4; } for (int row = r1; row <= r2; row++) { p = result->scanLine(row) + c1 * 4; for (int i = 0; i < 3; i++) rgba[i] = p[i] << 4; p += 4; for (int j = c1; j < c2; j++, p += 4) for (int i = 0; i < 3; i++) p[i] = (rgba[i] += (((p[i] << 4) - rgba[i])) >> 1) >> 4; } for (int col = c1; col <= c2; col++) { p = result->scanLine(r2) + col * 4; for (int i = 0; i < 3; i++) rgba[i] = p[i] << 4; p -= bpl; for (int j = r1; j < r2; j++, p -= bpl) for (int i = 0; i < 3; i++) p[i] = (rgba[i] += (((p[i] << 4) - rgba[i])) >> 1) >> 4; } for (int row = r1; row <= r2; row++) { p = result->scanLine(row) + c2 * 4; for (int i = 0; i < 3; i++) rgba[i] = p[i] << 4; p -= 4; for (int j = c1; j < c2; j++, p -= 4) for (int i = 0; i < 3; i++) p[i] = (rgba[i] += (((p[i] << 4) - rgba[i])) >> 1) >> 4; } } // overdraw to leave only the reflection blurred (but not the actual image) for (int x = 0; x < w; x++) for (int y = 0; y < h; y++) result->setPixel(hofs + y, x, img.pixel(x, y)); } } return result; } QImage* QxtFlowViewSoftwareRenderer::surface(int slideIndex) { if (!state) return 0; if (slideIndex < 0) return 0; if (slideIndex >= (int)state->slideImages.count()) return 0; #ifdef PICTUREFLOW_QT4 int key = slideIndex; #endif #if defined(PICTUREFLOW_QT3) || defined(PICTUREFLOW_QT2) QString key = QString::number(slideIndex); #endif QImage* img = state->slideImages.at(slideIndex); bool empty = img ? img->isNull() : true; if (empty) { surfaceCache.remove(key); imageHash.remove(slideIndex); if (!blankSurface) { int sw = state->slideWidth; int sh = state->slideHeight; #ifdef PICTUREFLOW_QT4 QImage img = QImage(sw, sh, QImage::Format_RGB32); QPainter painter(&img); QPoint p1(sw*4 / 10, 0); QPoint p2(sw*6 / 10, sh); QLinearGradient linearGrad(p1, p2); linearGrad.setColorAt(0, Qt::black); linearGrad.setColorAt(1, Qt::white); painter.setBrush(linearGrad); painter.fillRect(0, 0, sw, sh, QBrush(linearGrad)); painter.setPen(QPen(QColor(64, 64, 64), 4)); painter.setBrush(QBrush()); painter.drawRect(2, 2, sw - 3, sh - 3); painter.end(); #endif #if defined(PICTUREFLOW_QT3) || defined(PICTUREFLOW_QT2) QPixmap pixmap(sw, sh, 32); QPainter painter(&pixmap); painter.fillRect(pixmap.rect(), QColor(192, 192, 192)); painter.fillRect(5, 5, sw - 10, sh - 10, QColor(64, 64, 64)); painter.end(); QImage img = pixmap.convertToImage(); #endif blankSurface = prepareSurface(&img, sw, sh, bgcolor, state->reflectionEffect); } return blankSurface; } #ifdef PICTUREFLOW_QT4 bool exist = imageHash.contains(slideIndex); if (exist) if (img == imageHash.find(slideIndex).value()) #endif #ifdef PICTUREFLOW_QT3 bool exist = imageHash.find(slideIndex) != imageHash.end(); if (exist) if (img == imageHash.find(slideIndex).data()) #endif #ifdef PICTUREFLOW_QT2 if (img == imageHash[slideIndex]) #endif if (surfaceCache.contains(key)) return surfaceCache[key]; QImage* sr = prepareSurface(img, state->slideWidth, state->slideHeight, bgcolor, state->reflectionEffect); surfaceCache.insert(key, sr); imageHash.insert(slideIndex, img); return sr; } // Renders a slide to offscreen buffer. Returns a rect of the rendered area. // col1 and col2 limit the column for rendering. QRect QxtFlowViewSoftwareRenderer::renderSlide(const SlideInfo &slide, int col1, int col2) { int blend = slide.blend; if (!blend) return QRect(); QImage* src = surface(slide.slideIndex); if (!src) return QRect(); QRect rect(0, 0, 0, 0); int sw = src->height(); int sh = src->width(); int h = buffer.height(); int w = buffer.width(); if (col1 > col2) { int c = col2; col2 = col1; col1 = c; } col1 = (col1 >= 0) ? col1 : 0; col2 = (col2 >= 0) ? col2 : w - 1; col1 = qMin(col1, w - 1); col2 = qMin(col2, w - 1); int zoom = 100; int distance = h * 100 / zoom; PFreal sdx = fcos(slide.angle); PFreal sdy = fsin(slide.angle); PFreal xs = slide.cx - state->slideWidth * sdx / 2; PFreal ys = slide.cy - state->slideWidth * sdy / 2; PFreal dist = distance * PFREAL_ONE; int xi = qMax((PFreal)0, ((w * PFREAL_ONE / 2) + fdiv(xs * h, dist + ys)) >> PFREAL_SHIFT); if (xi >= w) return rect; bool flag = false; rect.setLeft(xi); for (int x = qMax(xi, col1); x <= col2; x++) { PFreal hity = 0; PFreal fk = rays[x]; if (sdy) { fk = fk - fdiv(sdx, sdy); hity = -fdiv((rays[x] * distance - slide.cx + slide.cy * sdx / sdy), fk); } dist = distance * PFREAL_ONE + hity; if (dist < 0) continue; PFreal hitx = fmul(dist, rays[x]); PFreal hitdist = fdiv(hitx - slide.cx, sdx); int column = sw / 2 + (hitdist >> PFREAL_SHIFT); if (column >= sw) break; if (column < 0) continue; rect.setRight(x); if (!flag) rect.setLeft(x); flag = true; int y1 = h / 2; int y2 = y1 + 1; QRgb* pixel1 = (QRgb*)(buffer.scanLine(y1)) + x; QRgb* pixel2 = (QRgb*)(buffer.scanLine(y2)) + x; QRgb pixelstep = pixel2 - pixel1; int center = (sh / 2); int dy = dist / h; int p1 = center * PFREAL_ONE - dy / 2; int p2 = center * PFREAL_ONE + dy / 2; const QRgb *ptr = (const QRgb*)(src->scanLine(column)); if (blend == 256) while ((y1 >= 0) && (y2 < h) && (p1 >= 0)) { *pixel1 = ptr[p1 >> PFREAL_SHIFT]; *pixel2 = ptr[p2 >> PFREAL_SHIFT]; p1 -= dy; p2 += dy; y1--; y2++; pixel1 -= pixelstep; pixel2 += pixelstep; } else while ((y1 >= 0) && (y2 < h) && (p1 >= 0)) { QRgb c1 = ptr[p1 >> PFREAL_SHIFT]; QRgb c2 = ptr[p2 >> PFREAL_SHIFT]; *pixel1 = blendColor(c1, bgcolor, blend); *pixel2 = blendColor(c2, bgcolor, blend); p1 -= dy; p2 += dy; y1--; y2++; pixel1 -= pixelstep; pixel2 += pixelstep; } } rect.setTop(0); rect.setBottom(h - 1); return rect; } void QxtFlowViewSoftwareRenderer::renderSlides() { int nleft = state->leftSlides.count(); int nright = state->rightSlides.count(); QRect r = renderSlide(state->centerSlide); int c1 = r.left(); int c2 = r.right(); for (int index = 0; index < nleft; index++) { QRect rs = renderSlide(state->leftSlides[index], 0, c1 - 1); if (!rs.isEmpty()) c1 = rs.left(); } for (int index = 0; index < nright; index++) { QRect rs = renderSlide(state->rightSlides[index], c2 + 1, buffer.width()); if (!rs.isEmpty()) c2 = rs.right(); } } // Render the slides. Updates only the offscreen buffer. void QxtFlowViewSoftwareRenderer::render() { buffer.fill(state->backgroundColor); renderSlides(); dirty = false; } libqxt-0.6.2/src/gui/qxtflowview_p.h000066400000000000000000000216621215241066400174740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ** ** This is a derived work of PictureFlow (http://pictureflow.googlecode.com) ** The original code was distributed under the following terms: ** ** Copyright (C) 2008 Ariya Hidayat (ariya@kde.org) ** Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and associated documentation files (the "Software"), to deal ** in the Software without restriction, including without limitation the rights ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ** copies of the Software, and to permit persons to whom the Software is ** furnished to do so, subject to the following conditions: ** ** The above copyright notice and this permission notice shall be included in ** all copies or substantial portions of the Software. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ** THE SOFTWARE. ****************************************************************************/ #ifndef QXTFLOWVIEW_P_H_INCLUDED #define QXTFLOWVIEW_P_H_INCLUDED #include "qxtflowview.h" #define PICTUREFLOW_QT4 #include #include #include #include #include #include #include #include #include #include #include #include #include // for fixed-point arithmetic, we need minimum 32-bit long // long long (64-bit) might be useful for multiplication and division typedef long PFreal; #define PFREAL_SHIFT 10 #define PFREAL_ONE (1 << PFREAL_SHIFT) #define IANGLE_MAX 1024 #define IANGLE_MASK 1023 inline PFreal fmul(PFreal a, PFreal b) { return ((long long)(a))*((long long)(b)) >> PFREAL_SHIFT; } inline PFreal fdiv(PFreal num, PFreal den) { long long p = (long long)(num) << (PFREAL_SHIFT * 2); long long q = p / (long long)den; long long r = q >> PFREAL_SHIFT; return r; } inline PFreal fsin(int iangle) { // warning: regenerate the table if IANGLE_MAX and PFREAL_SHIFT are changed! static const PFreal tab[] = { 3, 103, 202, 300, 394, 485, 571, 652, 726, 793, 853, 904, 947, 980, 1004, 1019, 1023, 1018, 1003, 978, 944, 901, 849, 789, 721, 647, 566, 479, 388, 294, 196, 97, -4, -104, -203, -301, -395, -486, -572, -653, -727, -794, -854, -905, -948, -981, -1005, -1020, -1024, -1019, -1004, -979, -945, -902, -850, -790, -722, -648, -567, -480, -389, -295, -197, -98, 3 }; while (iangle < 0) iangle += IANGLE_MAX; iangle &= IANGLE_MASK; int i = (iangle >> 4); PFreal p = tab[i]; PFreal q = tab[(i+1)]; PFreal g = (q - p); return p + g * (iangle - i*16) / 16; } inline PFreal fcos(int iangle) { return fsin(iangle + (IANGLE_MAX >> 2)); } /* ---------------------------------------------------------- QxtFlowViewState stores the state of all slides, i.e. all the necessary information to be able to render them. QxtFlowViewAnimator is responsible to move the slides during the transition between slides, to achieve the effect similar to Cover Flow, by changing the state. QxtFlowViewSoftwareRenderer (or QxtFlowViewOpenGLRenderer) is the actual 3-d renderer. It should render all slides given the state (an instance of QxtFlowViewState). Instances of all the above three classes are stored in QxtFlowViewPrivate. ------------------------------------------------------- */ struct SlideInfo { int slideIndex; int angle; PFreal cx; PFreal cy; int blend; }; class QxtFlowViewState { public: QxtFlowViewState(); ~QxtFlowViewState(); void reposition(); void reset(); QRgb backgroundColor; int slideWidth; int slideHeight; QxtFlowView::ReflectionEffect reflectionEffect; QVector slideImages; int angle; int spacing; PFreal offsetX; PFreal offsetY; SlideInfo centerSlide; QVector leftSlides; QVector rightSlides; int centerIndex; }; class QxtFlowViewAnimator { public: QxtFlowViewAnimator(); QxtFlowViewState* state; void start(int slide); void stop(int slide); void update(); int target; int step; int frame; QTimer animateTimer; }; class QxtFlowViewAbstractRenderer { public: QxtFlowViewAbstractRenderer(): state(0), dirty(false), widget(0) {} virtual ~QxtFlowViewAbstractRenderer() {} QxtFlowViewState* state; bool dirty; QWidget* widget; virtual void init() = 0; virtual void paint() = 0; }; class QxtFlowViewSoftwareRenderer: public QxtFlowViewAbstractRenderer { public: QxtFlowViewSoftwareRenderer(); ~QxtFlowViewSoftwareRenderer(); virtual void init(); virtual void paint(); private: QSize size; QRgb bgcolor; int effect; QImage buffer; QVector rays; QImage* blankSurface; #ifdef PICTUREFLOW_QT4 QCache surfaceCache; QHash imageHash; #endif #ifdef PICTUREFLOW_QT3 QCache surfaceCache; QMap imageHash; #endif #ifdef PICTUREFLOW_QT2 QCache surfaceCache; QIntDict imageHash; #endif void render(); void renderSlides(); QRect renderSlide(const SlideInfo &slide, int col1 = -1, int col2 = -1); QImage* surface(int slideIndex); }; // ----------------------------------------- class QxtFlowViewPrivate : public QObject { Q_OBJECT public: QxtFlowViewState* state; QxtFlowViewAnimator* animator; QxtFlowViewAbstractRenderer* renderer; QTimer triggerTimer; QAbstractItemModel * model; void setModel(QAbstractItemModel * model); void clear(); void triggerRender(); void insertSlide(int index, const QImage& image); void replaceSlide(int index, const QImage& image); void removeSlide(int index); void setCurrentIndex(QModelIndex index); void showSlide(int index); int picrole; int textrole; int piccolumn; int textcolumn; void reset(); QList modelmap; QPersistentModelIndex currentcenter; QPoint lastgrabpos; QModelIndex rootindex; public Q_SLOTS: void columnsAboutToBeInserted(const QModelIndex & parent, int start, int end); void columnsAboutToBeRemoved(const QModelIndex & parent, int start, int end); void columnsInserted(const QModelIndex & parent, int start, int end); void columnsRemoved(const QModelIndex & parent, int start, int end); void dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight); void headerDataChanged(Qt::Orientation orientation, int first, int last); void layoutAboutToBeChanged(); void layoutChanged(); void modelAboutToBeReset(); void modelReset(); void rowsAboutToBeInserted(const QModelIndex & parent, int start, int end); void rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end); void rowsInserted(const QModelIndex & parent, int start, int end); void rowsRemoved(const QModelIndex & parent, int start, int end); }; #endif // QXTFLOWVIEW_P_H_INCLUDED libqxt-0.6.2/src/gui/qxtglobalshortcut.cpp000066400000000000000000000147171215241066400207050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtglobalshortcut.h" #include "qxtglobalshortcut_p.h" #include #include bool QxtGlobalShortcutPrivate::error = false; #ifndef Q_WS_MAC int QxtGlobalShortcutPrivate::ref = 0; QAbstractEventDispatcher::EventFilter QxtGlobalShortcutPrivate::prevEventFilter = 0; #endif // Q_WS_MAC QHash, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts; QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier) { #ifndef Q_WS_MAC if (!ref++) prevEventFilter = QAbstractEventDispatcher::instance()->setEventFilter(eventFilter); #endif // Q_WS_MAC } QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate() { #ifndef Q_WS_MAC if (!--ref) QAbstractEventDispatcher::instance()->setEventFilter(prevEventFilter); #endif // Q_WS_MAC } bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut) { Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier; key = shortcut.isEmpty() ? Qt::Key(0) : Qt::Key((shortcut[0] ^ allMods) & shortcut[0]); mods = shortcut.isEmpty() ? Qt::KeyboardModifiers(0) : Qt::KeyboardModifiers(shortcut[0] & allMods); const quint32 nativeKey = nativeKeycode(key); const quint32 nativeMods = nativeModifiers(mods); const bool res = registerShortcut(nativeKey, nativeMods); if (res) shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p()); else qWarning() << "QxtGlobalShortcut failed to register:" << QKeySequence(key + mods).toString(); return res; } bool QxtGlobalShortcutPrivate::unsetShortcut() { bool res = false; const quint32 nativeKey = nativeKeycode(key); const quint32 nativeMods = nativeModifiers(mods); if (shortcuts.value(qMakePair(nativeKey, nativeMods)) == &qxt_p()) res = unregisterShortcut(nativeKey, nativeMods); if (res) shortcuts.remove(qMakePair(nativeKey, nativeMods)); else qWarning() << "QxtGlobalShortcut failed to unregister:" << QKeySequence(key + mods).toString(); key = Qt::Key(0); mods = Qt::KeyboardModifiers(0); return res; } void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods) { QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods)); if (shortcut && shortcut->isEnabled()) emit shortcut->activated(); } /*! \class QxtGlobalShortcut \inmodule QxtGui \brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey". A global shortcut triggers even if the application is not active. This makes it easy to implement applications that react to certain shortcuts still if some other application is active or if the application is for example minimized to the system tray. Example usage: \code QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(window); connect(shortcut, SIGNAL(activated()), window, SLOT(toggleVisibility())); shortcut->setShortcut(QKeySequence("Ctrl+Shift+F12")); \endcode \bold {Note:} Since Qxt 0.6 QxtGlobalShortcut no more requires QxtApplication. */ /*! \fn QxtGlobalShortcut::activated() This signal is emitted when the user types the shortcut's key sequence. \sa shortcut */ /*! Constructs a new QxtGlobalShortcut with \a parent. */ QxtGlobalShortcut::QxtGlobalShortcut(QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtGlobalShortcut); } /*! Constructs a new QxtGlobalShortcut with \a shortcut and \a parent. */ QxtGlobalShortcut::QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtGlobalShortcut); setShortcut(shortcut); } /*! Destructs the QxtGlobalShortcut. */ QxtGlobalShortcut::~QxtGlobalShortcut() { if (qxt_d().key != 0) qxt_d().unsetShortcut(); } /*! \property QxtGlobalShortcut::shortcut \brief the shortcut key sequence \bold {Note:} Notice that corresponding key press and release events are not delivered for registered global shortcuts even if they are disabled. Also, comma separated key sequences are not supported. Only the first part is used: \code qxtShortcut->setShortcut(QKeySequence("Ctrl+Alt+A,Ctrl+Alt+B")); Q_ASSERT(qxtShortcut->shortcut() == QKeySequence("Ctrl+Alt+A")); \endcode */ QKeySequence QxtGlobalShortcut::shortcut() const { return QKeySequence(qxt_d().key | qxt_d().mods); } bool QxtGlobalShortcut::setShortcut(const QKeySequence& shortcut) { if (qxt_d().key != 0) qxt_d().unsetShortcut(); return qxt_d().setShortcut(shortcut); } /*! \property QxtGlobalShortcut::enabled \brief whether the shortcut is enabled A disabled shortcut does not get activated. The default value is \c true. \sa setDisabled() */ bool QxtGlobalShortcut::isEnabled() const { return qxt_d().enabled; } void QxtGlobalShortcut::setEnabled(bool enabled) { qxt_d().enabled = enabled; } /*! Sets the shortcut \a disabled. \sa enabled */ void QxtGlobalShortcut::setDisabled(bool disabled) { qxt_d().enabled = !disabled; } libqxt-0.6.2/src/gui/qxtglobalshortcut.h000066400000000000000000000041071215241066400203420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTGLOBALSHORTCUT_H #define QXTGLOBALSHORTCUT_H #include "qxtglobal.h" #include #include class QxtGlobalShortcutPrivate; class QXT_GUI_EXPORT QxtGlobalShortcut : public QObject { Q_OBJECT QXT_DECLARE_PRIVATE(QxtGlobalShortcut) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) public: explicit QxtGlobalShortcut(QObject* parent = 0); explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = 0); virtual ~QxtGlobalShortcut(); QKeySequence shortcut() const; bool setShortcut(const QKeySequence& shortcut); bool isEnabled() const; public Q_SLOTS: void setEnabled(bool enabled = true); void setDisabled(bool disabled = true); Q_SIGNALS: void activated(); }; #endif // QXTGLOBALSHORTCUT_H libqxt-0.6.2/src/gui/qxtglobalshortcut_mac.cpp000066400000000000000000000172521215241066400215220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include #include "qxtglobalshortcut_p.h" #include #include #include #include typedef QPair Identifier; static QMap keyRefs; static QHash keyIDs; static quint32 hotKeySerial = 0; static bool qxt_mac_handler_installed = false; OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) { Q_UNUSED(nextHandler); Q_UNUSED(data); if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed) { EventHotKeyID keyID; GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID); Identifier id = keyIDs.key(keyID.id); QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first); } return noErr; } quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) { quint32 native = 0; if (modifiers & Qt::ShiftModifier) native |= shiftKey; if (modifiers & Qt::ControlModifier) native |= cmdKey; if (modifiers & Qt::AltModifier) native |= optionKey; if (modifiers & Qt::MetaModifier) native |= controlKey; if (modifiers & Qt::KeypadModifier) native |= kEventKeyModifierNumLockMask; return native; } quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) { UTF16Char ch; // Constants found in NSEvent.h from AppKit.framework if (key == Qt::Key_Up) ch = 0xF700; else if (key == Qt::Key_Down) ch = 0xF701; else if (key == Qt::Key_Left) ch = 0xF702; else if (key == Qt::Key_Right) ch = 0xF703; else if (key >= Qt::Key_F1 && key <= Qt::Key_F35) ch = key - Qt::Key_F1 + 0xF704; else if (key == Qt::Key_Insert) ch = 0xF727; else if (key == Qt::Key_Delete) ch = 0xF728; else if (key == Qt::Key_Home) ch = 0xF729; else if (key == Qt::Key_End) ch = 0xF72B; else if (key == Qt::Key_PageUp) ch = 0xF72C; else if (key == Qt::Key_PageDown) ch = 0xF72D; else if (key == Qt::Key_Print) ch = 0xF72E; else if (key == Qt::Key_ScrollLock) ch = 0xF72F; else if (key == Qt::Key_Pause) ch = 0xF730; else if (key == Qt::Key_SysReq) ch = 0xF731; else if (key == Qt::Key_Stop) ch = 0xF734; else if (key == Qt::Key_Menu) ch = 0xF735; else if (key == Qt::Key_Select) ch = 0xF741; else if (key == Qt::Key_Execute) ch = 0xF742; else if (key == Qt::Key_Help) ch = 0xF746; else if (key == Qt::Key_Mode_switch) ch = 0xF747; else if (key == Qt::Key_Escape) ch = 27; else if (key == Qt::Key_Return) ch = 13; else if (key == Qt::Key_Enter) ch = 3; else if (key == Qt::Key_Tab) ch = 9; else ch = key; KeyboardLayoutRef layout; KeyboardLayoutKind layoutKind; KLGetCurrentKeyboardLayout(&layout); KLGetKeyboardLayoutProperty(layout, kKLKind, const_cast(reinterpret_cast(&layoutKind))); if (layoutKind == kKLKCHRKind) { // no Unicode available if (ch > 255) return 0; char* data; KLGetKeyboardLayoutProperty(layout, kKLKCHRData, const_cast(reinterpret_cast(&data))); int ct = *reinterpret_cast(data + 258); for (int i = 0; i < ct; i++) { char* keyTable = data + 260 + 128 * i; for (int j = 0; j < 128; j++) { if (keyTable[j] == ch) return j; } } return 0; } char* data; KLGetKeyboardLayoutProperty(layout, kKLuchrData, const_cast(reinterpret_cast(&data))); UCKeyboardLayout* header = reinterpret_cast(data); UCKeyboardTypeHeader* table = header->keyboardTypeList; for (quint32 i=0; i < header->keyboardTypeCount; i++) { UCKeyStateRecordsIndex* stateRec = 0; if (table[i].keyStateRecordsIndexOffset != 0) { stateRec = reinterpret_cast(data + table[i].keyStateRecordsIndexOffset); if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0; } UCKeyToCharTableIndex* charTable = reinterpret_cast(data + table[i].keyToCharTableIndexOffset); if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue; for (quint32 j=0; j < charTable->keyToCharTableCount; j++) { UCKeyOutput* keyToChar = reinterpret_cast(data + charTable->keyToCharTableOffsets[j]); for (quint32 k=0; k < charTable->keyToCharTableSize; k++) { if (keyToChar[k] & kUCKeyOutputTestForIndexMask) { long idx = keyToChar[k] & kUCKeyOutputGetIndexMask; if (stateRec && idx < stateRec->keyStateRecordCount) { UCKeyStateRecord* rec = reinterpret_cast(data + stateRec->keyStateRecordOffsets[idx]); if (rec->stateZeroCharData == ch) return k; } } else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) { if (keyToChar[k] == ch) return k; } } // for k } // for j } // for i return 0; } bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) { if (!qxt_mac_handler_installed) { EventTypeSpec t; t.eventClass = kEventClassKeyboard; t.eventKind = kEventHotKeyPressed; InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, NULL, NULL); } EventHotKeyID keyID; keyID.signature = 'cute'; keyID.id = ++hotKeySerial; EventHotKeyRef ref = 0; bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref); if (rv) { keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id); keyRefs.insert(keyID.id, ref); } return rv; } bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) { Identifier id(nativeMods, nativeKey); if (!keyIDs.contains(id)) return false; EventHotKeyRef ref = keyRefs.take(keyIDs[id]); keyIDs.remove(id); return !UnregisterEventHotKey(ref); } libqxt-0.6.2/src/gui/qxtglobalshortcut_p.h000066400000000000000000000045601215241066400206640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTGLOBALSHORTCUT_P_H #define QXTGLOBALSHORTCUT_P_H #include "qxtglobalshortcut.h" #include #include #include class QxtGlobalShortcutPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtGlobalShortcut) QxtGlobalShortcutPrivate(); ~QxtGlobalShortcutPrivate(); bool enabled; Qt::Key key; Qt::KeyboardModifiers mods; bool setShortcut(const QKeySequence& shortcut); bool unsetShortcut(); static bool error; #ifndef Q_WS_MAC static int ref; static QAbstractEventDispatcher::EventFilter prevEventFilter; static bool eventFilter(void* message); #endif // Q_WS_MAC static void activateShortcut(quint32 nativeKey, quint32 nativeMods); private: static quint32 nativeKeycode(Qt::Key keycode); static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers); static bool registerShortcut(quint32 nativeKey, quint32 nativeMods); static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods); static QHash, QxtGlobalShortcut*> shortcuts; }; #endif // QXTGLOBALSHORTCUT_P_H libqxt-0.6.2/src/gui/qxtglobalshortcut_win.cpp000066400000000000000000000144151215241066400215550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtglobalshortcut_p.h" #include bool QxtGlobalShortcutPrivate::eventFilter(void* message) { MSG* msg = static_cast(message); if (msg->message == WM_HOTKEY) { const quint32 keycode = HIWORD(msg->lParam); const quint32 modifiers = LOWORD(msg->lParam); activateShortcut(keycode, modifiers); } return false; } quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) { // MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN quint32 native = 0; if (modifiers & Qt::ShiftModifier) native |= MOD_SHIFT; if (modifiers & Qt::ControlModifier) native |= MOD_CONTROL; if (modifiers & Qt::AltModifier) native |= MOD_ALT; if (modifiers & Qt::MetaModifier) native |= MOD_WIN; // TODO: resolve these? //if (modifiers & Qt::KeypadModifier) //if (modifiers & Qt::GroupSwitchModifier) return native; } quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) { switch (key) { case Qt::Key_Escape: return VK_ESCAPE; case Qt::Key_Tab: case Qt::Key_Backtab: return VK_TAB; case Qt::Key_Backspace: return VK_BACK; case Qt::Key_Return: case Qt::Key_Enter: return VK_RETURN; case Qt::Key_Insert: return VK_INSERT; case Qt::Key_Delete: return VK_DELETE; case Qt::Key_Pause: return VK_PAUSE; case Qt::Key_Print: return VK_PRINT; case Qt::Key_Clear: return VK_CLEAR; case Qt::Key_Home: return VK_HOME; case Qt::Key_End: return VK_END; case Qt::Key_Left: return VK_LEFT; case Qt::Key_Up: return VK_UP; case Qt::Key_Right: return VK_RIGHT; case Qt::Key_Down: return VK_DOWN; case Qt::Key_PageUp: return VK_PRIOR; case Qt::Key_PageDown: return VK_NEXT; case Qt::Key_F1: return VK_F1; case Qt::Key_F2: return VK_F2; case Qt::Key_F3: return VK_F3; case Qt::Key_F4: return VK_F4; case Qt::Key_F5: return VK_F5; case Qt::Key_F6: return VK_F6; case Qt::Key_F7: return VK_F7; case Qt::Key_F8: return VK_F8; case Qt::Key_F9: return VK_F9; case Qt::Key_F10: return VK_F10; case Qt::Key_F11: return VK_F11; case Qt::Key_F12: return VK_F12; case Qt::Key_F13: return VK_F13; case Qt::Key_F14: return VK_F14; case Qt::Key_F15: return VK_F15; case Qt::Key_F16: return VK_F16; case Qt::Key_F17: return VK_F17; case Qt::Key_F18: return VK_F18; case Qt::Key_F19: return VK_F19; case Qt::Key_F20: return VK_F20; case Qt::Key_F21: return VK_F21; case Qt::Key_F22: return VK_F22; case Qt::Key_F23: return VK_F23; case Qt::Key_F24: return VK_F24; case Qt::Key_Space: return VK_SPACE; case Qt::Key_Asterisk: return VK_MULTIPLY; case Qt::Key_Plus: return VK_ADD; case Qt::Key_Comma: return VK_SEPARATOR; case Qt::Key_Minus: return VK_SUBTRACT; case Qt::Key_Slash: return VK_DIVIDE; case Qt::Key_MediaNext: return VK_MEDIA_NEXT_TRACK; case Qt::Key_MediaPrevious: return VK_MEDIA_PREV_TRACK; case Qt::Key_MediaPlay: return VK_MEDIA_PLAY_PAUSE; case Qt::Key_MediaStop: return VK_MEDIA_STOP; // couldn't find those in VK_* //case Qt::Key_MediaLast: //case Qt::Key_MediaRecord: case Qt::Key_VolumeDown: return VK_VOLUME_DOWN; case Qt::Key_VolumeUp: return VK_VOLUME_UP; case Qt::Key_VolumeMute: return VK_VOLUME_MUTE; // numbers case Qt::Key_0: case Qt::Key_1: case Qt::Key_2: case Qt::Key_3: case Qt::Key_4: case Qt::Key_5: case Qt::Key_6: case Qt::Key_7: case Qt::Key_8: case Qt::Key_9: return key; // letters case Qt::Key_A: case Qt::Key_B: case Qt::Key_C: case Qt::Key_D: case Qt::Key_E: case Qt::Key_F: case Qt::Key_G: case Qt::Key_H: case Qt::Key_I: case Qt::Key_J: case Qt::Key_K: case Qt::Key_L: case Qt::Key_M: case Qt::Key_N: case Qt::Key_O: case Qt::Key_P: case Qt::Key_Q: case Qt::Key_R: case Qt::Key_S: case Qt::Key_T: case Qt::Key_U: case Qt::Key_V: case Qt::Key_W: case Qt::Key_X: case Qt::Key_Y: case Qt::Key_Z: return key; default: return 0; } } bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) { return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey); } bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) { return UnregisterHotKey(0, nativeMods ^ nativeKey); } libqxt-0.6.2/src/gui/qxtglobalshortcut_x11.cpp000066400000000000000000000105161215241066400213670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtglobalshortcut_p.h" #include #include static int (*original_x_errhandler)(Display* display, XErrorEvent* event); static int qxt_x_errhandler(Display* display, XErrorEvent *event) { Q_UNUSED(display); switch (event->error_code) { case BadAccess: case BadValue: case BadWindow: if (event->request_code == 33 /* X_GrabKey */ || event->request_code == 34 /* X_UngrabKey */) { QxtGlobalShortcutPrivate::error = true; //TODO: //char errstr[256]; //XGetErrorText(dpy, err->error_code, errstr, 256); } default: return 0; } } bool QxtGlobalShortcutPrivate::eventFilter(void* message) { XEvent* event = static_cast(message); if (event->type == KeyPress) { XKeyEvent* key = (XKeyEvent*) event; activateShortcut(key->keycode, // Mod1Mask == Alt, Mod4Mask == Meta key->state & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask)); } return false; } quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) { // ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask quint32 native = 0; if (modifiers & Qt::ShiftModifier) native |= ShiftMask; if (modifiers & Qt::ControlModifier) native |= ControlMask; if (modifiers & Qt::AltModifier) native |= Mod1Mask; if (modifiers & Qt::MetaModifier) native |= Mod4Mask; // TODO: resolve these? //if (modifiers & Qt::MetaModifier) //if (modifiers & Qt::KeypadModifier) //if (modifiers & Qt::GroupSwitchModifier) return native; } quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) { Display* display = QX11Info::display(); return XKeysymToKeycode(display, XStringToKeysym(QKeySequence(key).toString().toLatin1().data())); } bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) { Display* display = QX11Info::display(); Window window = QX11Info::appRootWindow(); Bool owner = True; int pointer = GrabModeAsync; int keyboard = GrabModeAsync; error = false; original_x_errhandler = XSetErrorHandler(qxt_x_errhandler); XGrabKey(display, nativeKey, nativeMods, window, owner, pointer, keyboard); XGrabKey(display, nativeKey, nativeMods | Mod2Mask, window, owner, pointer, keyboard); // allow numlock XSync(display, False); XSetErrorHandler(original_x_errhandler); return !error; } bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) { Display* display = QX11Info::display(); Window window = QX11Info::appRootWindow(); error = false; original_x_errhandler = XSetErrorHandler(qxt_x_errhandler); XUngrabKey(display, nativeKey, nativeMods, window); XUngrabKey(display, nativeKey, nativeMods | Mod2Mask, window); // allow numlock XSync(display, False); XSetErrorHandler(original_x_errhandler); return !error; } libqxt-0.6.2/src/gui/qxtgroupbox.cpp000066400000000000000000000101751215241066400175100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtgroupbox.h" #include class QxtGroupBoxPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtGroupBox) QxtGroupBoxPrivate(); bool collapsive; bool flat; // so we can restore it when expanding }; QxtGroupBoxPrivate::QxtGroupBoxPrivate() : collapsive(true), flat(false) {} /*! \class QxtGroupBox \inmodule QxtGui \brief The QxtGroupBox widget is a collapsive and checkable QGroupBox. QxtGroupBox is a checkable group box automatically expanding/collapsing its content according to the check state. QxtGroupBox shows its children when checked and hides its children when unchecked. \image qxtgroupbox.png "Two QxtGroupBoxes - an expanded and a collapsed - on top of each other." */ /*! Constructs a new QxtGroupBox with \a parent. */ QxtGroupBox::QxtGroupBox(QWidget* parent) : QGroupBox(parent) { QXT_INIT_PRIVATE(QxtGroupBox); setCheckable(true); setChecked(true); connect(this, SIGNAL(toggled(bool)), this, SLOT(setExpanded(bool))); } /*! Constructs a new QxtGroupBox with \a title and \a parent. */ QxtGroupBox::QxtGroupBox(const QString& title, QWidget* parent) : QGroupBox(title, parent) { QXT_INIT_PRIVATE(QxtGroupBox); setCheckable(true); setChecked(true); connect(this, SIGNAL(toggled(bool)), this, SLOT(setExpanded(bool))); } /*! Destructs the group box. */ QxtGroupBox::~QxtGroupBox() {} /*! \property QxtGroupBox::collapsive \brief whether the group box is collapsive The default value is \c true. */ bool QxtGroupBox::isCollapsive() const { return qxt_d().collapsive; } void QxtGroupBox::setCollapsive(bool enable) { if (qxt_d().collapsive != enable) { qxt_d().collapsive = enable; if (!enable) setExpanded(true); else if (!isChecked()) setExpanded(false); } } /*! Sets the group box \a collapsed. A collapsed group box hides its children. \sa setExpanded(), QGroupBox::toggled() */ void QxtGroupBox::setCollapsed(bool collapsed) { setExpanded(!collapsed); } /*! Sets the group box \a expanded. An expanded group box shows its children. \sa setCollapsed(), QGroupBox::toggled() */ void QxtGroupBox::setExpanded(bool expanded) { if (qxt_d().collapsive || expanded) { // show/hide direct children foreach(QObject* child, children()) { if (child->isWidgetType()) static_cast(child)->setVisible(expanded); } if (expanded) { setFlat(qxt_d().flat); } else { qxt_d().flat = isFlat(); setFlat(true); } } } /*! \reimp */ void QxtGroupBox::childEvent(QChildEvent* event) { QObject* child = event->child(); if (event->added() && child->isWidgetType()) { QWidget* widget = static_cast(child); if (qxt_d().collapsive && !isChecked()) widget->hide(); } } libqxt-0.6.2/src/gui/qxtgroupbox.h000066400000000000000000000035571215241066400171630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTGROUPBOX_H #define QXTGROUPBOX_H #include #include "qxtglobal.h" class QxtGroupBoxPrivate; class QXT_GUI_EXPORT QxtGroupBox : public QGroupBox { Q_OBJECT QXT_DECLARE_PRIVATE(QxtGroupBox) Q_PROPERTY(bool collapsive READ isCollapsive WRITE setCollapsive) public: explicit QxtGroupBox(QWidget* parent = 0); explicit QxtGroupBox(const QString& title, QWidget* parent = 0); virtual ~QxtGroupBox(); bool isCollapsive() const; void setCollapsive(bool enabled); public Q_SLOTS: void setCollapsed(bool collapsed = true); void setExpanded(bool expanded = true); protected: virtual void childEvent(QChildEvent* event); }; #endif // QXTGROUPBOX_H libqxt-0.6.2/src/gui/qxtgui.h000066400000000000000000000050501215241066400160700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTGUI_H_INCLUDED #define QXTGUI_H_INCLUDED #if !defined(Q_WS_QWS) #include "qxtapplication.h" #endif #include "qxtbasespinbox.h" #include "qxtcheckcombobox.h" #include "qxtconfigdialog.h" #include "qxtconfirmationmessage.h" #include "qxtcountrycombobox.h" #include "qxtcountrymodel.h" #include "qxtflowview.h" #include "qxtglobalshortcut.h" #include "qxtgroupbox.h" #include "qxtheaderview.h" #include "qxtitemdelegate.h" #include "qxtitemeditorcreator.h" #include "qxtitemeditorcreatorbase.h" #include "qxtlabel.h" #include "qxtlanguagecombobox.h" #include "qxtletterboxwidget.h" #include "qxtlineedit.h" #include "qxtlistwidget.h" #include "qxtlistwidgetitem.h" #include "qxtnativeeventfilter.h" #include "qxtprogresslabel.h" #include "qxtproxystyle.h" #include "qxtpushbutton.h" #include "qxtscheduleheaderwidget.h" #include "qxtscheduleitemdelegate.h" #include "qxtscheduleview.h" #include "qxtspanslider.h" #include "qxtstandarditemeditorcreator.h" #include "qxtstars.h" #include "qxtstringspinbox.h" #include "qxtstringvalidator.h" #include "qxtstyleoptionscheduleviewitem.h" #include "qxttablewidget.h" #include "qxttablewidgetitem.h" #include "qxttabwidget.h" #include "qxttooltip.h" #include "qxttreewidget.h" #include "qxttreewidgetitem.h" #if !defined(Q_WS_QWS) && !defined(Q_WS_MAC) #include "qxtwindowsystem.h" #endif #include "qxtsortfilterproxymodel.h" #endif // QXTGUI_H_INCLUDED libqxt-0.6.2/src/gui/qxtheaderview.cpp000066400000000000000000000073061215241066400177700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtheaderview.h" class QxtHeaderViewPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtHeaderView) QxtHeaderViewPrivate(); bool proportional; QMap factors; }; QxtHeaderViewPrivate::QxtHeaderViewPrivate() : proportional(false) { } /*! \class QxtHeaderView \inmodule QxtGui \brief The QxtHeaderView class is an extended QHeaderView with optionally proportional section sizes. */ /*! Constructs a new QxtHeaderView with \a orientation and \a parent. */ QxtHeaderView::QxtHeaderView(Qt::Orientation orientation, QWidget* parent) : QHeaderView(orientation, parent) { QXT_INIT_PRIVATE(QxtHeaderView); } /*! \property QxtHeaderView::proportionalSectionSizes \brief whether section sizes are proportional. The default value is \c true. \bold {Note:} Enabling proportional sections sizes sets resize mode QHeaderView::Fixed, which means that the user cannot resize sections. */ bool QxtHeaderView::hasProportionalSectionSizes() const { return qxt_d().proportional; } void QxtHeaderView::setProportionalSectionSizes(bool enabled) { if (qxt_d().proportional != enabled) { qxt_d().proportional = enabled; if (enabled) setResizeMode(QHeaderView::Fixed); } } /*! Returns the stretch factor of the section at \a logicalIndex. \sa setSectionStretchFactor() */ int QxtHeaderView::sectionStretchFactor(int logicalIndex) const { return qxt_d().factors.value(logicalIndex); } /*! Sets the stretch \a factor of the section at \a logicalIndex. \sa sectionStretchFactor() */ void QxtHeaderView::setSectionStretchFactor(int logicalIndex, int factor) { qxt_d().factors.insert(logicalIndex, factor); } /*! \reimp */ void QxtHeaderView::resizeEvent(QResizeEvent* event) { QHeaderView::resizeEvent(event); if (qxt_d().proportional) { int total = 0; for (int i = 0; i < count(); ++i) total += qxt_d().factors.value(i, 1); int totalSize = 0; for (int i = 0; i < count() - 1; ++i) { qreal factor = qxt_d().factors.value(i, 1) / static_cast(total); int sectionSize = factor * (orientation() == Qt::Horizontal ? width() : height()); sectionSize = qMax(minimumSectionSize(), sectionSize); resizeSection(i, sectionSize); totalSize += sectionSize; } // avoid rounding errors, give rest to the last section resizeSection(count() - 1, width() - totalSize); } } libqxt-0.6.2/src/gui/qxtheaderview.h000066400000000000000000000036131215241066400174320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTHEADERVIEW_H #define QXTHEADERVIEW_H #include #include "qxtglobal.h" class QxtHeaderViewPrivate; class QXT_GUI_EXPORT QxtHeaderView : public QHeaderView { Q_OBJECT QXT_DECLARE_PRIVATE(QxtHeaderView) Q_PROPERTY(bool proportionalSectionSizes READ hasProportionalSectionSizes WRITE setProportionalSectionSizes) public: explicit QxtHeaderView(Qt::Orientation orientation, QWidget* parent = 0); bool hasProportionalSectionSizes() const; void setProportionalSectionSizes(bool enabled); int sectionStretchFactor(int logicalIndex) const; void setSectionStretchFactor(int logicalIndex, int factor); protected: void resizeEvent(QResizeEvent* event); }; #endif // QXTHEADERVIEW_H libqxt-0.6.2/src/gui/qxtitemdelegate.cpp000066400000000000000000000365371215241066400203060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtitemdelegate.h" #include "qxtitemdelegate_p.h" #include #include #include #include #include #include static const int TOP_LEVEL_EXTENT = 2; QxtItemDelegatePrivate::QxtItemDelegatePrivate() : textVisible(true), progressFormat("%1%"), elide(Qt::ElideMiddle), style(Qxt::NoDecoration), document(0) { } void QxtItemDelegatePrivate::paintButton(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QTreeView* view) const { // draw the button QStyleOptionButton buttonOption; buttonOption.state = option.state; #ifdef Q_WS_MAC buttonOption.state |= QStyle::State_Raised; #endif buttonOption.state &= ~QStyle::State_HasFocus; if (view->isExpanded(index)) buttonOption.state |= QStyle::State_Sunken; buttonOption.rect = option.rect; buttonOption.palette = option.palette; buttonOption.features = QStyleOptionButton::None; view->style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, view); // draw the branch indicator static const int i = 9; const QRect& r = option.rect; if (index.model()->hasChildren(index)) { QStyleOption branchOption; branchOption.initFrom(view); if (branchOption.direction == Qt::LeftToRight) branchOption.rect = QRect(r.left() + i / 2, r.top() + (r.height() - i) / 2, i, i); else branchOption.rect = QRect(r.right() - i / 2 - i, r.top() + (r.height() - i) / 2, i, i); branchOption.palette = option.palette; branchOption.state = QStyle::State_Children; if (view->isExpanded(index)) branchOption.state |= QStyle::State_Open; view->style()->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, painter, view); } // draw the text QRect textrect = QRect(r.left() + i * 2, r.top(), r.width() - ((5 * i) / 2), r.height()); QString text = option.fontMetrics.elidedText(index.data().toString(), elide, textrect.width()); view->style()->drawItemText(painter, textrect, Qt::AlignCenter, option.palette, view->isEnabled(), text); } void QxtItemDelegatePrivate::paintMenu(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QTreeView* view) const { // draw the menu bar item QStyleOptionMenuItem menuOption; menuOption.palette = view->palette(); menuOption.fontMetrics = view->fontMetrics(); menuOption.state = QStyle::State_None; // QModelIndex::flags() was introduced in 4.2 // => therefore "index.model()->flags(index)" if (view->isEnabled() && index.model()->flags(index) & Qt::ItemIsEnabled) menuOption.state |= QStyle::State_Enabled; else menuOption.palette.setCurrentColorGroup(QPalette::Disabled); menuOption.state |= QStyle::State_Selected; menuOption.state |= QStyle::State_Sunken; menuOption.state |= QStyle::State_HasFocus; menuOption.rect = option.rect; menuOption.text = index.data().toString(); menuOption.icon = QIcon(index.data(Qt::DecorationRole).value()); view->style()->drawControl(QStyle::CE_MenuBarItem, &menuOption, painter, view); // draw the an arrow as a branch indicator if (index.model()->hasChildren(index)) { QStyle::PrimitiveElement arrow; if (view->isExpanded(index)) arrow = QStyle::PE_IndicatorArrowUp; else arrow = QStyle::PE_IndicatorArrowDown; static const int i = 9; const QRect& r = option.rect; menuOption.rect = QRect(r.left() + i / 2, r.top() + (r.height() - i) / 2, i, i); view->style()->drawPrimitive(arrow, &menuOption, painter, view); } } void QxtItemDelegatePrivate::paintProgress(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { QVariant min = index.data(QxtItemDelegate::ProgressMinimumRole); QVariant max = index.data(QxtItemDelegate::ProgressMaximumRole); QStyleOptionProgressBar opt; opt.minimum = (min.isValid() && min.canConvert(QVariant::Int)) ? min.toInt() : 0; opt.maximum = (max.isValid() && max.canConvert(QVariant::Int)) ? max.toInt() : 100; opt.progress = index.data(QxtItemDelegate::ProgressValueRole).toInt(); opt.rect = option.rect; opt.textVisible = textVisible; opt.text = progressFormat.arg(opt.progress); QApplication::style()->drawControl(QStyle::CE_ProgressBar, &opt, painter, 0); QWidget* viewport = dynamic_cast(painter->device()); if (viewport) { if (opt.minimum == 0 && opt.maximum == 0) { if (!updatedItems.contains(viewport)) connect(viewport, SIGNAL(destroyed()), this, SLOT(viewDestroyed())); updatedItems.replace(viewport, index); } else { updatedItems.remove(viewport, index); if (!updatedItems.contains(viewport)) disconnect(viewport, SIGNAL(destroyed()), this, SLOT(viewDestroyed())); } } if (updatedItems.isEmpty()) { if (updateTimer.isActive()) updateTimer.stop(); } else { if (!updateTimer.isActive()) updateTimer.start(1000 / 25, const_cast(this)); } } void QxtItemDelegatePrivate::setCurrentEditor(QWidget* editor, const QModelIndex& index) const { currentEditor = editor; currentEdited = index; } void QxtItemDelegatePrivate::timerEvent(QTimerEvent* event) { if (event->timerId() == updateTimer.timerId()) { QMutableHashIterator it(updatedItems); while (it.hasNext()) { it.next(); if (!it.key()) { it.remove(); continue; } // try to update the specific view item instead of the whole view if possible if (QAbstractItemView* view = qobject_cast(it.key()->parentWidget())) view->update(it.value()); else it.key()->update(); } } } void QxtItemDelegatePrivate::viewDestroyed() { QWidget* viewport = qobject_cast(sender()); if (viewport) { updatedItems.remove(viewport); } } void QxtItemDelegatePrivate::closeEditor(QWidget* editor) { if (currentEdited.isValid() && editor == currentEditor) { setCurrentEditor(0, QModelIndex()); emit qxt_p().editingFinished(currentEdited); } } /*! \class QxtItemDelegate \inmodule QxtGui \brief The QxtItemDelegate class is an extended QItemDelegate QxtItemDelegate provides signals for starting and finishing of editing and an optional decoration of top level items in a QTreeView. QxtItemDelegate can also draw a progress bar for items providing appropriate progress data. Just like QProgressBar, QxtItemDelegate can show a busy indicator. If minimum and maximum both are set to \c 0, a busy indicator is shown instead of a percentage of steps. */ /*! \fn QxtItemDelegate::editingStarted(const QModelIndex& index) This signal is emitted after the editing of \a index has been started. \sa editingFinished() */ /*! \fn QxtItemDelegate::editingFinished(const QModelIndex& index) This signal is emitted after the editing of \a index has been finished. \sa editingStarted() */ /*! \enum QxtItemDelegate::Role This enum defines custom roles used by QxtItemDelegate. \value ProgressValueRole The progress value. \value ProgressMinimumRole The minimum progress value. The default value \c 0 is used if no value is provided for ProgressMinimumRole. \value ProgressMaximumRole The maximum progress value. The default value \c 100 is used if no value is provided for ProgressMaximumRole. */ /*! Constructs a new QxtItemDelegate with \a parent. */ QxtItemDelegate::QxtItemDelegate(QObject* parent) : QItemDelegate(parent) { QXT_INIT_PRIVATE(QxtItemDelegate); connect(this, SIGNAL(closeEditor(QWidget*)), &qxt_d(), SLOT(closeEditor(QWidget*))); } /*! Destructs the item delegate. */ QxtItemDelegate::~QxtItemDelegate() {} /*! \property QxtItemDelegate::decorationStyle \brief the top level index decoration style Top level indices are decorated according to this property. The default value is Qxt::NoDecoration. \bold {Note:} The property has effect only in case the delegate is installed on a QTreeView. The view must be the parent of the delegate. \bold {Note:} Set QTreeView::rootIsDecorated to \c false to avoid multiple branch indicators. \sa Qxt::DecorationStyle, QTreeView::rootIsDecorated */ Qxt::DecorationStyle QxtItemDelegate::decorationStyle() const { return qxt_d().style; } void QxtItemDelegate::setDecorationStyle(Qxt::DecorationStyle style) { qxt_d().style = style; } /*! \property QxtItemDelegate::elideMode \brief the text elide mode The text of a decorated top level index is elided according to this property. The default value is Qt::ElideMiddle. \bold {Note:} The property has effect only for decorated top level indices. \sa decorationStyle, Qt::TextElideMode */ Qt::TextElideMode QxtItemDelegate::elideMode() const { return qxt_d().elide; } void QxtItemDelegate::setElideMode(Qt::TextElideMode mode) { qxt_d().elide = mode; } /*! \property QxtItemDelegate::progressTextFormat \brief the format of optional progress text The progress text is formatted according to this property. The default value is \bold "%1%". \bold {Note:} Progress bar is rendered for indices providing valid numerical data for ProgressValueRole. \bold {Note:} \bold \%1 is replaced by the progress percent. \sa progressTextVisible, Role */ QString QxtItemDelegate::progressTextFormat() const { return qxt_d().progressFormat; } void QxtItemDelegate::setProgressTextFormat(const QString& format) { qxt_d().progressFormat = format; } /*! \property QxtItemDelegate::progressTextVisible \brief whether progress text is visible The default value is \c true. \bold {Note:} Progress bar is rendered for indices providing valid numerical data for ProgressValueRole. \sa progressTextFormat, QxtItemDelegate::Role */ bool QxtItemDelegate::isProgressTextVisible() const { return qxt_d().textVisible; } void QxtItemDelegate::setProgressTextVisible(bool visible) { qxt_d().textVisible = visible; } /*! \reimp */ QWidget* QxtItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const { QWidget* editor = QItemDelegate::createEditor(parent, option, index); qxt_d().setCurrentEditor(editor, index); emit const_cast(this)->editingStarted(index); return editor; } /*! \reimp */ void QxtItemDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { QItemDelegate::setModelData(editor, model, index); qxt_d().setCurrentEditor(0, QModelIndex()); emit const_cast(this)->editingFinished(index); } /*! \reimp */ void QxtItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { const QAbstractItemModel* model = index.model(); const QTreeView* tree = qobject_cast(parent()); const bool topLevel = !index.parent().isValid(); if (tree && model && topLevel && qxt_d().style != Qxt::NoDecoration) { QStyleOptionViewItem opt; opt.QStyleOption::operator=(option); opt.showDecorationSelected = false; QModelIndex valid = model->index(index.row(), 0); QModelIndex sibling = valid; while (sibling.isValid()) { opt.rect |= tree->visualRect(sibling); sibling = sibling.sibling(sibling.row(), sibling.column() + 1); } switch (qxt_d().style) { case Qxt::Buttonlike: qxt_d().paintButton(painter, opt, valid, tree); break; case Qxt::Menulike: qxt_d().paintMenu(painter, opt, valid, tree); break; default: qWarning("QxtItemDelegate::paint() unknown decoration style"); QItemDelegate::paint(painter, opt, valid); break; } } else { QItemDelegate::paint(painter, option, index); const QVariant data = index.data(ProgressValueRole); if (data.isValid() && data.canConvert(QVariant::Int)) qxt_d().paintProgress(painter, option, index); } } /*! \reimp */ void QxtItemDelegate::drawDisplay(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QString& text) const { if (!Qt::mightBeRichText(text)) { QItemDelegate::drawDisplay(painter, option, rect, text); return; } QString key = QString(QLatin1String("QxtItemDelegate:%1")).arg(text); QPixmap pixmap; if (!QPixmapCache::find(key, pixmap)) { if (!qxt_d().document) qxt_d().document = new QTextDocument(const_cast(this)); qxt_d().document->setHtml(text); qxt_d().document->adjustSize(); pixmap = QPixmap(qxt_d().document->size().toSize()); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); qxt_d().document->drawContents(&painter); painter.end(); QPixmapCache::insert(key, pixmap); } painter->drawPixmap(option.rect.topLeft(), pixmap); } /*! \reimp */ QSize QxtItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const { // something slightly bigger for top level indices if decorated QSize size = QItemDelegate::sizeHint(option, index); if (!index.parent().isValid() && qxt_d().style != Qxt::NoDecoration) size += QSize(TOP_LEVEL_EXTENT, TOP_LEVEL_EXTENT); const QString text = index.data(Qt::DisplayRole).toString(); if (Qt::mightBeRichText(text)) { if (!qxt_d().document) qxt_d().document = new QTextDocument(const_cast(this)); qxt_d().document->setHtml(text); qxt_d().document->adjustSize(); size = size.expandedTo(qxt_d().document->size().toSize()); // TODO: checkbox, icon, etc. } return size; } libqxt-0.6.2/src/gui/qxtitemdelegate.h000066400000000000000000000061251215241066400177410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTITEMDELEGATE_H #define QXTITEMDELEGATE_H #include #include "qxtglobal.h" #include "qxtnamespace.h" class QxtItemDelegatePrivate; class QXT_GUI_EXPORT QxtItemDelegate : public QItemDelegate { Q_OBJECT QXT_DECLARE_PRIVATE(QxtItemDelegate) Q_PROPERTY(Qxt::DecorationStyle decorationStyle READ decorationStyle WRITE setDecorationStyle) Q_PROPERTY(Qt::TextElideMode elideMode READ elideMode WRITE setElideMode) Q_PROPERTY(QString progressTextFormat READ progressTextFormat WRITE setProgressTextFormat) Q_PROPERTY(bool progressTextVisible READ isProgressTextVisible WRITE setProgressTextVisible) public: explicit QxtItemDelegate(QObject* parent = 0); virtual ~QxtItemDelegate(); enum Role { ProgressValueRole = Qt::UserRole + 328, ProgressMinimumRole, ProgressMaximumRole }; Qxt::DecorationStyle decorationStyle() const; void setDecorationStyle(Qxt::DecorationStyle style); Qt::TextElideMode elideMode() const; void setElideMode(Qt::TextElideMode mode); QString progressTextFormat() const; void setProgressTextFormat(const QString& format); bool isProgressTextVisible() const; void setProgressTextVisible(bool visible); virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const; virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const; virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; virtual void drawDisplay(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QString& text) const; virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; Q_SIGNALS: void editingStarted(const QModelIndex& index); void editingFinished(const QModelIndex& index); }; #endif // QXTITEMDELEGATE_H libqxt-0.6.2/src/gui/qxtitemdelegate_p.h000066400000000000000000000051671215241066400202650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTITEMDELEGATE_P_H #define QXTITEMDELEGATE_P_H #include "qxtitemdelegate.h" #include #include #include #include QT_FORWARD_DECLARE_CLASS(QPainter) QT_FORWARD_DECLARE_CLASS(QTreeView) QT_FORWARD_DECLARE_CLASS(QTextDocument) class QxtItemDelegatePrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtItemDelegate) QxtItemDelegatePrivate(); void paintButton(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QTreeView* view) const; void paintMenu(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QTreeView* view) const; void paintProgress(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; void setCurrentEditor(QWidget* editor, const QModelIndex& index) const; bool textVisible; QString progressFormat; Qt::TextElideMode elide; Qxt::DecorationStyle style; typedef QPointer QWidgetPointer; mutable QWidgetPointer currentEditor; mutable QPersistentModelIndex currentEdited; mutable QMultiHash updatedItems; mutable QBasicTimer updateTimer; mutable QTextDocument* document; protected: void timerEvent(QTimerEvent* event); private Q_SLOTS: void viewDestroyed(); void closeEditor(QWidget* editor); }; #endif // QXTITEMDELEGATE_P_H libqxt-0.6.2/src/gui/qxtitemeditorcreator.h000066400000000000000000000061241215241066400210340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTITEMEDITORCREATOR_H #define QXTITEMEDITORCREATOR_H #include #include "qxtitemeditorcreatorbase.h" #include "qxtglobal.h" /*! \class QxtItemEditorCreator QxtItemEditorCreator \inmodule QxtGui \brief An extended QItemEditorCreator with default values for user-chosen properties. The QxtItemEditorCreator class provides the possibility to set default values for user-chosen properties. Usage: \code QItemEditorFactory *factory = new QItemEditorFactory; QxtItemEditorCreator* spinBoxCreator = new QxtItemEditorCreator("value"); QxtItemEditorCreator* lineEditCreator = new QxtItemEditorCreator("text"); // spin boxes for degrees between -180 and 180 spinBoxCreator->setDefaultPropertyValue("minimum", -180); spinBoxCreator->setDefaultPropertyValue("maximum", 180); // line edits for passwords lineEditCreator->setDefaultPropertyValue("echoMode", QLineEdit::Password); factory->registerEditor(QVariant::Int, spinBoxCreator); factory->registerEditor(QVariant::String, lineEditCreator); QItemEditorFactory::setDefaultFactory(factory); \endcode Setting default properties above makes sure that spin boxes have ranges from -180 to 180 and line editors' echo mode is set to QLineEdit::Password. \sa QItemEditorCreator */ template class QXT_GUI_EXPORT QxtItemEditorCreator : public QxtItemEditorCreatorBase, public QItemEditorCreator { public: /*! Constructs a new QxtItemEditorCreator with \a valuePropertyName. */ inline QxtItemEditorCreator(const QByteArray& valuePropertyName) : QItemEditorCreator(valuePropertyName) { } /*! \reimp */ inline QWidget* createWidget(QWidget* parent) const { return initializeEditor(QItemEditorCreator::createWidget(parent)); } }; #endif // QXTITEMEDITORCREATOR_H libqxt-0.6.2/src/gui/qxtitemeditorcreatorbase.h000066400000000000000000000052321215241066400216660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTITEMEDITORCREATORBASE_H #define QXTITEMEDITORCREATORBASE_H #include #include #include #include #include /*! \class QxtItemEditorCreatorBase QxtItemEditorCreatorBase \inmodule QxtGui \brief Provides means for introducing default property values to initialize an editor with. The QxtItemEditorCreator class provides the possibility to set default property values which are applied when initializing given editor. */ template class QXT_GUI_EXPORT QxtItemEditorCreatorBase { public: /*! Returns the default value of \a property. */ QVariant defaultPropertyValue(const QByteArray& property) const { return properties.value(property); } /*! Sets the default \a value for \a property. */ void setDefaultPropertyValue(const QByteArray& property, const QVariant& value) { properties.insert(property, value); } /*! Initializes \a editor with introduced default property values. */ inline QWidget* initializeEditor(QWidget* editor) const; private: QHash properties; }; template Q_INLINE_TEMPLATE QWidget* QxtItemEditorCreatorBase::initializeEditor(QWidget* editor) const { QHashIterator i(properties); while (i.hasNext()) { i.next(); editor->setProperty(i.key(), i.value()); } return editor; } #endif // QXTITEMEDITORCREATORBASE_H libqxt-0.6.2/src/gui/qxtlabel.cpp000066400000000000000000000170111215241066400167160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlabel.h" #include #include #include #include #include static const int Vertical_Mask = 0x02; class QxtLabelPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtLabel) void init(const QString& txt = QString()); void updateLabel(); QTime time; QString text; Qt::Alignment align; Qt::TextElideMode mode; Qxt::Rotation rot; }; void QxtLabelPrivate::init(const QString& txt) { text = txt; align = Qt::AlignCenter; mode = Qt::ElideMiddle; rot = Qxt::NoRotation; } void QxtLabelPrivate::updateLabel() { qxt_p().updateGeometry(); qxt_p().update(); } /*! \class QxtLabel \inmodule QxtGui \brief The QxtLabel widget is a label which is able to show elided and rotated plain text. QxtLabel is a label which is able to show elided and rotated plain text. In addition, QxtLabel provides a signal for clicking. \image qxtlabel.png "QxtLabel in action." Usage: \code QxtLabel* label = new QxtLabel(tr("Hello, World!"), this); label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); label->setElideMode(Qt::ElideRight); label->setRotation(Qxt::CounterClockwise); connect(label, SIGNAL(clicked()), this, SLOT(labelClicked())); \endcode \sa QLabel */ /*! \fn QxtLabel::clicked() This signal is emitted whenever the label has been clicked. \bold {Note:} A combination of mouse button press and release in shorter time than QApplication::doubleClickInterval is considered as a click. \sa QApplication::doubleClickInterval */ /*! \fn QxtLabel::textChanged(const QString& text) This signal is emitted whenever the \a text has changed. */ /*! Constructs a new QxtLabel with \a parent and \a flags. */ QxtLabel::QxtLabel(QWidget* parent, Qt::WindowFlags flags) : QFrame(parent, flags) { QXT_INIT_PRIVATE(QxtLabel); qxt_d().init(); } /*! Constructs a new QxtLabel with \a text, \a parent and \a flags. */ QxtLabel::QxtLabel(const QString& text, QWidget* parent, Qt::WindowFlags flags) : QFrame(parent, flags) { QXT_INIT_PRIVATE(QxtLabel); qxt_d().init(text); } /*! Destructs the label. */ QxtLabel::~QxtLabel() {} /*! \property QxtLabel::text \brief the text of the label */ QString QxtLabel::text() const { return qxt_d().text; } void QxtLabel::setText(const QString& text) { if (qxt_d().text != text) { qxt_d().text = text; qxt_d().updateLabel(); emit textChanged(text); } } /*! \property QxtLabel::alignment \brief the alignment of the text The text is aligned according to this property. The default value is Qt::AlignCenter. \sa text, Qt::Alignment */ Qt::Alignment QxtLabel::alignment() const { return qxt_d().align; } void QxtLabel::setAlignment(Qt::Alignment alignment) { if (qxt_d().align != alignment) { qxt_d().align = alignment; update(); // no geometry change, repaint is sufficient } } /*! \property QxtLabel::elideMode \brief the elide mode of the text The text is elided according to this property. The default value is Qt::ElideMiddle. \sa text, Qt::TextElideMode */ Qt::TextElideMode QxtLabel::elideMode() const { return qxt_d().mode; } void QxtLabel::setElideMode(Qt::TextElideMode mode) { if (qxt_d().mode != mode) { qxt_d().mode = mode; qxt_d().updateLabel(); } } /*! \property QxtLabel::rotation \brief the rotation of the label The label is rotated according to this property. The default value is Qxt::NoRotation. \sa Qxt::Rotation */ Qxt::Rotation QxtLabel::rotation() const { return qxt_d().rot; } void QxtLabel::setRotation(Qxt::Rotation rotation) { if (qxt_d().rot != rotation) { Qxt::Rotation prev = qxt_d().rot; qxt_d().rot = rotation; switch (rotation) { case Qxt::NoRotation: case Qxt::UpsideDown: if (prev & Vertical_Mask) { updateGeometry(); } break; case Qxt::Clockwise: case Qxt::CounterClockwise: if ((prev & Vertical_Mask) == 0) { updateGeometry(); } break; default: // nothing to do break; } } update(); } /*! \reimp */ QSize QxtLabel::sizeHint() const { const QFontMetrics& fm = fontMetrics(); QSize size(fm.width(qxt_d().text), fm.height()); if (qxt_d().rot & Vertical_Mask) size.transpose(); return size; } /*! \reimp */ QSize QxtLabel::minimumSizeHint() const { switch (qxt_d().mode) { case Qt::ElideNone: return sizeHint(); default: { const QFontMetrics& fm = fontMetrics(); QSize size(fm.width("..."), fm.height()); if (qxt_d().rot & Vertical_Mask) size.transpose(); return size; } } } /*! \reimp */ void QxtLabel::paintEvent(QPaintEvent* event) { QFrame::paintEvent(event); QPainter p(this); p.rotate(qxt_d().rot); QRect r = contentsRect(); switch (qxt_d().rot) { case Qxt::UpsideDown: p.translate(-r.width(), -r.height()); break; case Qxt::Clockwise: p.translate(0, -r.width()); break; case Qxt::CounterClockwise: p.translate(-r.height(), 0); break; default: // nothing to do break; } if (qxt_d().rot & Vertical_Mask) { QSize s = r.size(); s.transpose(); r = QRect(r.topLeft(), s); } const QString elidedText = fontMetrics().elidedText(qxt_d().text, qxt_d().mode, r.width()); p.drawText(r, qxt_d().align, elidedText); } /*! \reimp */ void QxtLabel::changeEvent(QEvent* event) { QFrame::changeEvent(event); switch (event->type()) { case QEvent::FontChange: case QEvent::ApplicationFontChange: qxt_d().updateLabel(); break; default: // nothing to do break; } } /*! \reimp */ void QxtLabel::mousePressEvent(QMouseEvent* event) { QFrame::mousePressEvent(event); qxt_d().time.start(); } /*! \reimp */ void QxtLabel::mouseReleaseEvent(QMouseEvent* event) { QFrame::mouseReleaseEvent(event); if (qxt_d().time.elapsed() < qApp->doubleClickInterval()) emit clicked(); } libqxt-0.6.2/src/gui/qxtlabel.h000066400000000000000000000051421215241066400163650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLABEL_H #define QXTLABEL_H #include #include "qxtnamespace.h" #include "qxtglobal.h" class QxtLabelPrivate; class QXT_GUI_EXPORT QxtLabel : public QFrame { Q_OBJECT Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment) Q_PROPERTY(Qt::TextElideMode elideMode READ elideMode WRITE setElideMode) Q_PROPERTY(Qxt::Rotation rotation READ rotation WRITE setRotation) public: explicit QxtLabel(QWidget* parent = 0, Qt::WindowFlags flags = 0); explicit QxtLabel(const QString& text, QWidget* parent = 0, Qt::WindowFlags flags = 0); virtual ~QxtLabel(); QString text() const; Qt::Alignment alignment() const; void setAlignment(Qt::Alignment alignment); Qt::TextElideMode elideMode() const; void setElideMode(Qt::TextElideMode mode); Qxt::Rotation rotation() const; void setRotation(Qxt::Rotation rotation); virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; public Q_SLOTS: void setText(const QString& text); Q_SIGNALS: void clicked(); void textChanged(const QString& text); protected: virtual void changeEvent(QEvent* event); virtual void mousePressEvent(QMouseEvent* event); virtual void mouseReleaseEvent(QMouseEvent* event); virtual void paintEvent(QPaintEvent* event); private: QXT_DECLARE_PRIVATE(QxtLabel) }; #endif // QXTLABEL_H libqxt-0.6.2/src/gui/qxtlanguagecombobox.cpp000066400000000000000000000237631215241066400211660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlanguagecombobox.h" #include "qxtlanguagecombobox_p.h" #include #include #include class Language; typedef QList LanguageList; static QStringList findQmFiles(const QString& pathToTranslations) { QDir dir(pathToTranslations); QStringList fileNames = dir.entryList(QStringList("*.qm"), QDir::Files, QDir::Name); QSet found; QMutableStringListIterator i(fileNames); while (i.hasNext()) { i.next(); int start = i.value().indexOf('_'); int end = i.value().lastIndexOf('.'); QString s = i.value().mid(start + 1, end - start - 1).toLower(); if (found.contains(s)) { i.setValue(s); found.insert(s); } } return fileNames; } class Language { public: Language(const QLocale::Language& language) : _mLanguage(language) , _mCountryCode("C") { QLocale loc(language); if (loc.language() == language) _mCountryCode = loc.name().right(2); else _mCountryCode = ""; _mDisplayName = qApp->translate("QLocale", qPrintable(QLocale::languageToString(_mLanguage))); }; bool operator<(const Language& lang) const { return _mDisplayName.localeAwareCompare(lang._mDisplayName) < 0; } static const LanguageList& getAllLanguages() { if (_smAllLanguages.empty()) { for (int idx = 0; idx < QLocale::LastLanguage; ++idx) { QLocale::Language l = static_cast(idx); if (l == QLocale::LastLanguage) continue; // obsolete - NorwegianNynorsk is used instead if (l == QLocale::Nynorsk) continue; if (l == QLocale::C) continue; _smAllLanguages.push_back(Language(l)); } qSort(_smAllLanguages); } return _smAllLanguages; }; static LanguageList getTrLanguages(const QString& translationPath) { LanguageList trLanguages; QStringList qms = findQmFiles(translationPath); for (int i = 0; i < qms.size(); ++i) { QLocale locale(qms[i]); if (locale.language() == QLocale::C) continue; trLanguages.push_back(Language(locale.language())); } qSort(trLanguages); return trLanguages; }; const QString& name() const { return _mDisplayName; } const QLocale::Language& language() const { return _mLanguage; } const QString& countryName() const { return _mCountryCode; } private: QLocale::Language _mLanguage; QString _mDisplayName; QString _mCountryCode; static LanguageList _smAllLanguages; }; LanguageList Language::_smAllLanguages; class LanguageModel : public QAbstractTableModel { public: LanguageModel(const LanguageList& languages, QObject* parent = 0) : QAbstractTableModel(parent), _mLanguages(languages) { } int rowCount(const QModelIndex&) const { return _mLanguages.size(); } int columnCount(const QModelIndex&) const { return 2; } QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const { if (!index.isValid()) return QVariant(); if (_mLanguages.empty()) return QVariant(); int idx = qMin(index.row(), _mLanguages.size()); const Language& l = _mLanguages[idx]; if (role == Qt::DecorationRole) { return QIcon(":/flags/" + l.countryName() + ".png"); } if (role == Qt::DisplayRole) { switch (index.column()) { case 0: return l.name(); case 1: return l.language(); default: return QVariant(); } } return QVariant(); } private: LanguageList _mLanguages; }; QxtLanguageComboBoxPrivate::QxtLanguageComboBoxPrivate() : _mDisplayMode(QxtLanguageComboBox::AllLanguages), _mTranslationPath("."), _mModel(0) { } void QxtLanguageComboBoxPrivate::init() { connect(&qxt_p(), SIGNAL(currentIndexChanged(int)), this, SLOT(comboBoxCurrentIndexChanged(int))); } void QxtLanguageComboBoxPrivate::setTranslationPath(const QString& path) { if (_mTranslationPath == path) return; _mTranslationPath = path; reset(); } void QxtLanguageComboBoxPrivate::setDisplayMode(QxtLanguageComboBox::DisplayMode mode) { if (_mDisplayMode == mode && _mModel != 0) return; _mDisplayMode = mode; reset(); } void QxtLanguageComboBoxPrivate::reset() { if (_mModel != 0) { delete _mModel; _mModel = 0; } QLocale::Language currentLang = currentLanguage(); if (_mDisplayMode == QxtLanguageComboBox::AllLanguages) _mModel = new LanguageModel(Language::getAllLanguages(), &qxt_p()); else _mModel = new LanguageModel(Language::getTrLanguages(_mTranslationPath), &qxt_p()); qxt_p().setModel(_mModel); qxt_p().setModelColumn(0); setCurrentLanguage(currentLang); } void QxtLanguageComboBoxPrivate::comboBoxCurrentIndexChanged(int) { handleLanguageChange(); } void QxtLanguageComboBoxPrivate::handleLanguageChange() { emit qxt_p().currentLanguageChanged(currentLanguage()); emit qxt_p().currentLanguageNameChanged(currentLanguageName()); } QLocale::Language QxtLanguageComboBoxPrivate::currentLanguage() const { if (_mModel == NULL) return QLocale::C; QModelIndex idx = _mModel->index(qxt_p().currentIndex(), 1); QLocale::Language currentLang = static_cast(idx.data().toInt()); return currentLang; } QString QxtLanguageComboBoxPrivate::currentLanguageName() const { return qxt_p().currentText(); } void QxtLanguageComboBoxPrivate::setCurrentLanguage(QLocale::Language language) { // column 1 is QLocale::Language QModelIndex start = _mModel->index(0, 1); QModelIndexList result = _mModel->match(start, Qt::DisplayRole, language, 1, Qt::MatchExactly); if (!result.isEmpty()) { qxt_p().setCurrentIndex(result.first().row()); handleLanguageChange(); } // else // qDebug() << "Cannot setCurrentLanguage: " << language << _mModel; } /*! \class QxtLanguageComboBox \inmodule QxtGui \brief The QxtLanguageComboBox widget is an extended QComboBox to display languages. QxtLanguageComboBox is a specialized combo box to display spoken languages. The languages are taken from QLocale::Language. \image qxtlanguagecombobox.png "QxtLanguageComboBox in Plastique style." */ /*! \enum QxtLanguageComboBox::DisplayMode This enum describes the displayed languages. \value AllLanguages Show all languages. \value AvailableTranslations Show translated languages. \sa QxtLanguageComboBox::displayMode */ /*! \fn QxtLanguageComboBox::currentLanguageChanged(QLocale::Language language) This signal is emitted whenever the current selected \a language has been changed. */ /*! \fn QxtLanguageComboBox::currentLanguageNameChanged(const QString& name) This signal is emitted whenever the of the current selected language with \a name has been changed. */ /*! Constructs a new QxtCountryComboBox with \a parent. */ QxtLanguageComboBox::QxtLanguageComboBox(QWidget* parent) : QComboBox(parent) { QXT_INIT_PRIVATE(QxtLanguageComboBox); setDisplayMode(AllLanguages); setCurrentLanguage(QLocale::system().language()); qxt_d().init(); } /*! Destructs the combo box. */ QxtLanguageComboBox::~QxtLanguageComboBox() { } /*! \property QxtLanguageComboBox::currentLanguage \brief the current selected language. */ QLocale::Language QxtLanguageComboBox::currentLanguage() const { return qxt_d().currentLanguage(); } /*! \property QxtLanguageComboBox::currentLanguageName \brief the name of the current selected language. */ QString QxtLanguageComboBox::currentLanguageName() const { return qxt_d().currentLanguageName(); } void QxtLanguageComboBox::setCurrentLanguage(QLocale::Language language) { qxt_d().setCurrentLanguage(language); } /*! \property QxtLanguageComboBox::displayMode \brief the display mode of the widget. */ void QxtLanguageComboBox::setDisplayMode(DisplayMode mode) { qxt_d().setDisplayMode(mode); } QxtLanguageComboBox::DisplayMode QxtLanguageComboBox::displayMode() const { return qxt_d().displayMode(); } /*! \property QxtLanguageComboBox::translationPath \brief the path to the translation files. */ void QxtLanguageComboBox::setTranslationPath(const QString& path) { qxt_d().setTranslationPath(path); } QString QxtLanguageComboBox::translationPath() const { return qxt_d().translationPath(); } libqxt-0.6.2/src/gui/qxtlanguagecombobox.h000066400000000000000000000051251215241066400206230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLANGUAGECOMBOBOX_H #define QXTLANGUAGECOMBOBOX_H #include #include #include "qxtglobal.h" class QxtLanguageComboBoxPrivate; class QXT_GUI_EXPORT QxtLanguageComboBox : public QComboBox { Q_OBJECT QXT_DECLARE_PRIVATE(QxtLanguageComboBox) Q_PROPERTY(QString currentLanguageName READ currentLanguageName) #if QT_VERSION >= 0x040300 Q_PROPERTY(QLocale::Language currentLanguage READ currentLanguage WRITE setCurrentLanguage) #endif Q_PROPERTY(DisplayMode displayMode READ displayMode WRITE setDisplayMode) Q_PROPERTY(QString translationPath READ translationPath WRITE setTranslationPath) Q_ENUMS(DisplayMode) public: explicit QxtLanguageComboBox(QWidget* parent = 0); virtual ~QxtLanguageComboBox(); enum DisplayMode {AllLanguages, AvailableTranslations}; DisplayMode displayMode() const; QString translationPath() const; QLocale::Language currentLanguage() const; QString currentLanguageName() const; public Q_SLOTS: void setCurrentLanguage(QLocale::Language lang); void setDisplayMode(DisplayMode mode); void setTranslationPath(const QString& path); Q_SIGNALS: void currentLanguageChanged(QLocale::Language country); void currentLanguageNameChanged(const QString& name); /*public: QSize sizeHint() const; QSize minimumSize() const; QSize maximumSize() const;*/ }; #endif // QXTLANGUAGECOMBOBOX_H libqxt-0.6.2/src/gui/qxtlanguagecombobox_p.h000066400000000000000000000043441215241066400211440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLANGUAGECOMBOBOX_P_H #define QXTLANGUAGECOMBOBOX_P_H #include "qxtlanguagecombobox.h" #include class QxtLanguageComboBoxPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtLanguageComboBox) public: explicit QxtLanguageComboBoxPrivate(); void init(); QLocale::Language currentLanguage() const; QString currentLanguageName() const; void setDisplayMode(QxtLanguageComboBox::DisplayMode mode); void setTranslationPath(const QString& path); QxtLanguageComboBox::DisplayMode displayMode() const { return _mDisplayMode; } QString translationPath() const { return _mTranslationPath; } public Q_SLOTS: void setCurrentLanguage(QLocale::Language language); void comboBoxCurrentIndexChanged(int index); private: void handleLanguageChange(); void reset(); private: QxtLanguageComboBox::DisplayMode _mDisplayMode; QString _mTranslationPath; QAbstractTableModel* _mModel; }; #endif // QXTLANGUAGECOMBOBOX_P_H libqxt-0.6.2/src/gui/qxtletterboxwidget.cpp000066400000000000000000000116501215241066400210560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtletterboxwidget.h" #include "qxtletterboxwidget_p.h" #include #include QxtLetterBoxWidgetPrivate::QxtLetterBoxWidgetPrivate() : center(0), timer(), margin(0) { timer.setSingleShot(true); } /*! \class QxtLetterBoxWidget \inmodule QxtGui \brief The QxtLetterBoxWidget widget is a letter box widget. QxtLetterBoxWidget preserves the aspect ratio of its content widget. Use QWidget::sizeIncrement to define the aspect ratio: \code QxtLetterBoxWidget letterBox; widget->setSizeIncrement(16, 9); letterBox.setWidget(widget); letterBox.show(); \endcode */ /*! Constructs a new QxtLetterBoxWidget with \a parent. */ QxtLetterBoxWidget::QxtLetterBoxWidget(QWidget* parent) : QFrame(parent) { QXT_INIT_PRIVATE(QxtLetterBoxWidget); connect(&qxt_d().timer, SIGNAL(timeout()), this, SLOT(resizeWidget())); } /*! Destructs the group box. */ QxtLetterBoxWidget::~QxtLetterBoxWidget() { } /*! \property QxtLetterBoxWidget::backgroundColor \brief the background color This property is provided for convenience. This property corresponds to QPalette::Window. \bold {Note:} Setting or clearing the property also sets the property QWidget::autoFillBackground as \c true or \c false, respectively. */ QColor QxtLetterBoxWidget::backgroundColor() const { return palette().color(QPalette::Window); } void QxtLetterBoxWidget::setBackgroundColor(const QColor& color) { QPalette pal = palette(); pal.setColor(QPalette::Window, color); setPalette(pal); setAutoFillBackground(true); } void QxtLetterBoxWidget::clearBackgroundColor() { setBackgroundColor(QColor()); setAutoFillBackground(false); } /*! \property QxtLetterBoxWidget::margin \brief the margin The default value is \c 0. */ int QxtLetterBoxWidget::margin() const { return qxt_d().margin; } void QxtLetterBoxWidget::setMargin(int margin) { if (qxt_d().margin != margin) { qxt_d().margin = margin; resizeWidget(); } } /*! Returns the widget for the letter box. This function returns zero if the widget has not been set. \sa setWidget() */ QWidget* QxtLetterBoxWidget::widget() const { return qxt_d().center; } /*! Sets the given \a widget to be the letter box's widget. \bold {Note:} QxtLetterBox takes ownership of the widget pointer and deletes it at the appropriate time. \sa widget() */ void QxtLetterBoxWidget::setWidget(QWidget* widget) { if (qxt_d().center && qxt_d().center != widget) qxt_d().center->deleteLater(); qxt_d().center = widget; if (widget) { widget->setParent(this); resizeWidget(); } } /*! \property QxtLetterBoxWidget::resizeDelay \brief the delay of resize The default value is \c 0 which means immediate resize. Using a short resize delay might be useful if the widget is complex and resizing it is expensive. */ uint QxtLetterBoxWidget::resizeDelay() const { return qxt_d().timer.interval(); } void QxtLetterBoxWidget::setResizeDelay(uint delay) { qxt_d().timer.setInterval(delay); } /*! Resizes the content widget. */ void QxtLetterBoxWidget::resizeWidget() { if (qxt_d().center) { QSize s = qxt_d().center->sizeIncrement(); s.scale(size(), Qt::KeepAspectRatio); s -= QSize(2 * qxt_d().margin, 2 * qxt_d().margin); s = QLayout::closestAcceptableSize(qxt_d().center, s); QRect r = QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, s, rect()); qxt_d().center->setGeometry(r); } } /*! \reimp */ void QxtLetterBoxWidget::resizeEvent(QResizeEvent* event) { QFrame::resizeEvent(event); if (resizeDelay() > 0) qxt_d().timer.start(); else resizeWidget(); } libqxt-0.6.2/src/gui/qxtletterboxwidget.h000066400000000000000000000042361215241066400205250ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLETTERBOXWIDGET_H #define QXTLETTERBOXWIDGET_H #include #include "qxtglobal.h" class QxtLetterBoxWidgetPrivate; class QXT_GUI_EXPORT QxtLetterBoxWidget : public QFrame { Q_OBJECT QXT_DECLARE_PRIVATE(QxtLetterBoxWidget) Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor RESET clearBackgroundColor) Q_PROPERTY(int margin READ margin WRITE setMargin) Q_PROPERTY(uint resizeDelay READ resizeDelay WRITE setResizeDelay) public: QxtLetterBoxWidget(QWidget* parent = 0); ~QxtLetterBoxWidget(); QColor backgroundColor() const; void setBackgroundColor(const QColor& color); void clearBackgroundColor(); int margin() const; void setMargin(int margin); QWidget* widget() const; void setWidget(QWidget* widget); uint resizeDelay() const; void setResizeDelay(uint delay); public Q_SLOTS: void resizeWidget(); protected: void resizeEvent(QResizeEvent* event); }; #endif // QXTLETTERBOXWIDGET_H libqxt-0.6.2/src/gui/qxtletterboxwidget_p.h000066400000000000000000000030751215241066400210440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLETTERBOXWIDGET_P_H #define QXTLETTERBOXWIDGET_P_H #include "qxtletterboxwidget.h" #include class QxtLetterBoxWidgetPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtLetterBoxWidget) QxtLetterBoxWidgetPrivate(); public: QWidget* center; QTimer timer; int margin; }; #endif // QXTLETTERBOXWIDGET_P_H libqxt-0.6.2/src/gui/qxtlineedit.cpp000066400000000000000000000066241215241066400174440ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlineedit.h" #include #include #include // copied from qlineedit.cpp: #define vMargin 1 #define hMargin 2 class QxtLineEditPrivate : public QxtPrivate { public: QString sampleText; }; /*! \class QxtLineEdit \inmodule QxtGui \brief The QxtLineEdit widget is a line edit that is able to show a sample text. QxtLineEdit is a line edit that is able to show a sample text. The sample text is shown when the line edit is empty and has no focus. \image qxtlineedit.png "Two empty QxtLineEdits: non-focused and focused." */ /*! Constructs a new QxtLineEdit with \a parent. */ QxtLineEdit::QxtLineEdit(QWidget* parent) : QLineEdit(parent) { } /*! Constructs a new QxtLineEdit with \a text and \a parent. */ QxtLineEdit::QxtLineEdit(const QString& text, QWidget* parent) : QLineEdit(text, parent) { } /*! Destructs the line edit. */ QxtLineEdit::~QxtLineEdit() { } /*! \property QxtLineEdit::sampleText \brief the sample text of the line edit The sample text is shown when the line edit is empty and has no focus. */ QString QxtLineEdit::sampleText() const { return qxt_d().sampleText; } void QxtLineEdit::setSampleText(const QString& text) { if (qxt_d().sampleText != text) { qxt_d().sampleText = text; if (displayText().isEmpty() && !hasFocus()) update(); } } /*! \reimp */ void QxtLineEdit::paintEvent(QPaintEvent* event) { QLineEdit::paintEvent(event); if (displayText().isEmpty() && !hasFocus()) { QStyleOptionFrameV2 option; initStyleOption(&option); QRect r = style()->subElementRect(QStyle::SE_LineEditContents, &option, this); #if QT_VERSION >= 0x040500 // TODO: sort out prior Qt 4.5 int left, top, right, bottom; getTextMargins(&left, &top, &right, &bottom); r.adjust(left, top, -right, -bottom); #endif // QT_VERSION >= 0x040500 r.adjust(hMargin, vMargin, -hMargin, -vMargin); QPainter painter(this); QPalette pal = palette(); pal.setCurrentColorGroup(QPalette::Disabled); style()->drawItemText(&painter, r, alignment(), pal, false, qxt_d().sampleText, QPalette::Text); } } libqxt-0.6.2/src/gui/qxtlineedit.h000066400000000000000000000034361215241066400171070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLINEEDIT_H #define QXTLINEEDIT_H #include #include class QxtLineEditPrivate; class QXT_GUI_EXPORT QxtLineEdit : public QLineEdit { Q_OBJECT Q_PROPERTY(QString sampleText READ sampleText WRITE setSampleText) public: explicit QxtLineEdit(QWidget* parent = 0); QxtLineEdit(const QString& text, QWidget* parent = 0); virtual ~QxtLineEdit(); QString sampleText() const; public Q_SLOTS: void setSampleText(const QString& text); protected: virtual void paintEvent(QPaintEvent* event); private: QXT_DECLARE_PRIVATE(QxtLineEdit) }; #endif // QXTLINEEDIT_H libqxt-0.6.2/src/gui/qxtlistwidget.cpp000066400000000000000000000063201215241066400200170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlistwidget.h" #include "qxtlistwidget_p.h" #include "qxtitemdelegate.h" QxtListWidgetPrivate::QxtListWidgetPrivate() {} void QxtListWidgetPrivate::informStartEditing(const QModelIndex& index) { QListWidgetItem* item = qxt_p().itemFromIndex(index); Q_ASSERT(item); emit qxt_p().itemEditingStarted(item); } void QxtListWidgetPrivate::informFinishEditing(const QModelIndex& index) { QListWidgetItem* item = qxt_p().itemFromIndex(index); Q_ASSERT(item); emit qxt_p().itemEditingFinished(item); } /*! \class QxtListWidget \inmodule QxtGui \brief The QxtListWidget class is an extended QListWidget with additional signals. QxtListWidget offers a few most commonly requested signals. \image qxtlistwidget.png "QxtListWidget in Plastique style." \sa QxtListWidgetItem */ /*! \fn QxtListWidget::itemEditingStarted(QListWidgetItem* item) This signal is emitted after the editing of \a item has been started. \sa itemEditingFinished() */ /*! \fn QxtListWidget::itemEditingFinished(QListWidgetItem* item) This signal is emitted after the editing of \a item has been finished. \sa itemEditingStarted() */ /*! \fn QxtListWidget::itemCheckStateChanged(QxtListWidgetItem* item) This signal is emitted whenever the check state of \a item has changed. \bold {Note:} Use QxtListWidgetItem in order to enable this feature. \sa QxtListWidgetItem, QListWidgetItem::checkState() */ /*! Constructs a new QxtListWidget with \a parent. */ QxtListWidget::QxtListWidget(QWidget* parent) : QListWidget(parent) { QXT_INIT_PRIVATE(QxtListWidget); QxtItemDelegate* delegate = new QxtItemDelegate(this); connect(delegate, SIGNAL(editingStarted(const QModelIndex&)), &qxt_d(), SLOT(informStartEditing(const QModelIndex&))); connect(delegate, SIGNAL(editingFinished(const QModelIndex&)), &qxt_d(), SLOT(informFinishEditing(const QModelIndex&))); setItemDelegate(delegate); } /*! Destructs the list widget. */ QxtListWidget::~QxtListWidget() {} libqxt-0.6.2/src/gui/qxtlistwidget.h000066400000000000000000000033731215241066400174710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLISTWIDGET_H #define QXTLISTWIDGET_H #include #include "qxtglobal.h" #include "qxtlistwidgetitem.h" class QxtListWidgetPrivate; class QXT_GUI_EXPORT QxtListWidget : public QListWidget { Q_OBJECT QXT_DECLARE_PRIVATE(QxtListWidget) friend class QxtListWidgetItem; public: explicit QxtListWidget(QWidget* parent = 0); virtual ~QxtListWidget(); Q_SIGNALS: void itemEditingStarted(QListWidgetItem* item); void itemEditingFinished(QListWidgetItem* item); void itemCheckStateChanged(QxtListWidgetItem* item); }; #endif // QXTLISTWIDGET_H libqxt-0.6.2/src/gui/qxtlistwidget_p.h000066400000000000000000000031321215241066400200010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLISTWIDGET_P_H #define QXTLISTWIDGET_P_H #include "qxtlistwidget.h" class QxtItemDelegate; class QxtListWidgetPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtListWidget) QxtListWidgetPrivate(); private Q_SLOTS: void informStartEditing(const QModelIndex& index); void informFinishEditing(const QModelIndex& index); }; #endif // QXTLISTWIDGET_P_H libqxt-0.6.2/src/gui/qxtlistwidgetitem.cpp000066400000000000000000000071131215241066400206770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtlistwidgetitem.h" #include "qxtlistwidget.h" /*! \class QxtListWidgetItem \inmodule QxtGui \brief The QxtListWidgetItem class is an extended QListWidgetItem. QxtListWidgetItem provides means for offering check state change signals and convenience methods for testing and setting flags. \sa QxtListWidget */ /*! Constructs a new QxtListWidgetItem with \a parent and \a type. */ QxtListWidgetItem::QxtListWidgetItem(QListWidget* parent, int type) : QListWidgetItem(parent, type) { } /*! Constructs a new QxtListWidgetItem with \a text, \a parent and \a type. */ QxtListWidgetItem::QxtListWidgetItem(const QString& text, QListWidget* parent, int type) : QListWidgetItem(text, parent, type) { } /*! Constructs a new QxtListWidgetItem with \a icon, \a text, \a parent and \a type. */ QxtListWidgetItem::QxtListWidgetItem(const QIcon& icon, const QString& text, QListWidget* parent, int type) : QListWidgetItem(icon, text, parent, type) { } /*! Constructs a copy of \a other. */ QxtListWidgetItem::QxtListWidgetItem(const QxtListWidgetItem& other) : QListWidgetItem(other) { } /*! Destructs the list widget item. */ QxtListWidgetItem::~QxtListWidgetItem() { } /*! Returns \c true if the \a flag is set, otherwise \c false. \sa setFlag(), QListWidgetItem::flags(), Qt::ItemFlag */ bool QxtListWidgetItem::testFlag(Qt::ItemFlag flag) const { return (flags() & flag); } /*! If \a enabled is \c true, the item \a flag is enabled; otherwise, it is disabled. \sa testFlag(), QListWidgetItem::setFlags(), Qt::ItemFlag */ void QxtListWidgetItem::setFlag(Qt::ItemFlag flag, bool enabled) { if (enabled) setFlags(flags() | flag); else setFlags(flags() & ~flag); } /*! \reimp */ void QxtListWidgetItem::setData(int role, const QVariant& value) { if (role == Qt::CheckStateRole) { const Qt::CheckState newState = static_cast(value.toInt()); const Qt::CheckState oldState = static_cast(data(role).toInt()); QListWidgetItem::setData(role, value); if (newState != oldState) { QxtListWidget* list = qobject_cast(listWidget()); if (list) { emit list->itemCheckStateChanged(this); } } } else { QListWidgetItem::setData(role, value); } } libqxt-0.6.2/src/gui/qxtlistwidgetitem.h000066400000000000000000000036731215241066400203530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTLISTWIDGETITEM_H #define QXTLISTWIDGETITEM_H #include #include "qxtnamespace.h" #include "qxtglobal.h" class QXT_GUI_EXPORT QxtListWidgetItem : public QListWidgetItem { public: explicit QxtListWidgetItem(QListWidget* parent = 0, int type = Type); explicit QxtListWidgetItem(const QString& text, QListWidget* parent = 0, int type = Type); explicit QxtListWidgetItem(const QIcon& icon, const QString& text, QListWidget* parent = 0, int type = Type); explicit QxtListWidgetItem(const QxtListWidgetItem& other); virtual ~QxtListWidgetItem(); bool testFlag(Qt::ItemFlag flag) const; void setFlag(Qt::ItemFlag flag, bool enabled = true); virtual void setData(int role, const QVariant& value); }; #endif // QXTLISTWIDGETITEM_H libqxt-0.6.2/src/gui/qxtlookuplineedit.cpp000066400000000000000000000123401215241066400206660ustar00rootroot00000000000000#include "qxtlookuplineedit.h" #include "qxtlookuplineedit_p.h" #include #include #include #include #include #include #include #include #include /*! \class QxtLookupLineEdit QxtLookupLineEdit \brief The QxtLookupLineEdit class is a QLineEdit to select from data provided by a QAbstractItemModel. QxtLookupLineEdit uses QxtFilterDialog to make it easy for the user, to select data from a large dataset. \code QSqlQueryModel *model = new QSqlQueryModel(parent); model->setQuery("Select employeeNr,name,forename,hometown,phone from employees;",dbConnection); QxtLookupLineEdit* edit = new QxtLookupLineEdit(parent); edit->setSourceModel(model); //we want to search by name not by nr so use the name column edit->setLookupColumn(1); //we need the employeeNr in the lineEdit , so choose col 0 as dataColumn edit->setDataColumn(0); //we want to seek the Display Role edit->setLookupRole(Qt::DisplayRole); //if the user presses * in the lineEdit open the popup edit->setPopupTrigger(QKeySequence("*")); \endcode */ QxtLookupLineEditPrivate::QxtLookupLineEditPrivate() { } QxtLookupLineEdit::QxtLookupLineEdit(QWidget *parent) : QLineEdit(parent) { QXT_INIT_PRIVATE(QxtLookupLineEdit); qxt_d().m_dataColumn = qxt_d().m_lookupColumn = 0; qxt_d().m_lookupRole = Qt::DisplayRole; qxt_d().m_sourceModel = 0; } QxtLookupLineEdit::~QxtLookupLineEdit() { } /*! \brief returns the sourceModel \sa setSourceModel(QAbstractItemModel *model) */ QAbstractItemModel *QxtLookupLineEdit::sourceModel() const { return qxt_d().m_sourceModel; } /*! \brief returns the column the lineEdit is looking \sa setLookupColumn(const int column) */ int QxtLookupLineEdit::lookupColumn () const { return qxt_d().m_lookupColumn; } /*! \brief returns the role the lineEdit is looking \sa setLookupRole(const int role) */ int QxtLookupLineEdit::lookupRole () const { return qxt_d().m_lookupRole; } /*! \brief returns the trigger that opens the popup \sa setPopupTrigger (const QKeySequence &trigger) */ QKeySequence QxtLookupLineEdit::popupTrigger () const { return qxt_d().m_trigger; } /*! \brief sets the sourceModel used in the popup dialog */ void QxtLookupLineEdit::setSourceModel(QAbstractItemModel *model) { qxt_d().m_sourceModel = model; } /*! \brief sets the column wherethe popup dialog searches */ void QxtLookupLineEdit::setLookupColumn (const int column) { qxt_d().m_lookupColumn = (column); } /*! \brief sets the model role the popup should use */ void QxtLookupLineEdit::setLookupRole (const int role) { qxt_d().m_lookupRole = (role); } /*! \brief Sets the popup trigger that makes QxtLookupLineEdit open the popup dialog */ void QxtLookupLineEdit::setPopupTrigger (const QKeySequence &trigger) { qxt_d().m_trigger = trigger; } void QxtLookupLineEdit::showPopup () { /*open wildcard dialog*/ if(!sourceModel()) return; QString tempText = text(); if(hasSelectedText()){ QString selected = selectedText(); tempText.replace(selected,""); } QModelIndex currIndex = QxtFilterDialog::getIndex(this,qxt_d().m_sourceModel,qxt_d().m_lookupColumn,qxt_d().m_lookupRole,tempText); if(currIndex.isValid()){ QModelIndex dataIndex = sourceModel()->index(currIndex.row(),dataColumn()); if(dataIndex.isValid()) { setText(dataIndex.data(lookupRole()).toString()); emit selected(); this->nextInFocusChain()->setFocus(); } } #if 0 QPoint pos = this->geometry().topLeft(); if(qobject_cast(this->parent())) pos = qobject_cast(this->parent())->mapToGlobal(pos); qxt_d().filterView->setGeometry(QRect(pos,QSize(400,300))); qxt_d().filterView->setFilterText(text()); int ret = qxt_d().filterView->exec(); if(ret == QDialog::Accepted) { QModelIndex currIndex = qxt_d().filterView->selectedIndex(); QModelIndex dataIndex = sourceModel()->index(currIndex.row(),dataColumn()); if(dataIndex.isValid()) { setText(dataIndex.data(lookupRole()).toString()); this->nextInFocusChain()->setFocus(); } } #endif } void QxtLookupLineEdit::keyPressEvent ( QKeyEvent * event ) { QKeySequence currSeq = QKeySequence(event->key() | event->modifiers()); if(currSeq.matches(qxt_d().m_trigger)) showPopup (); else QLineEdit::keyPressEvent(event); } /*! \brief set the model column index QxtLookupLineEdit will use to get data from the model after the user has chosen the dataset in the popup */ void QxtLookupLineEdit::setDataColumn (const int column) { qxt_d().m_dataColumn = column; } /*! \brief returns the model column index QxtLookupLineEdit will use to get data from the model after the user has chosen the dataset in the popup */ int QxtLookupLineEdit::dataColumn ( ) const { return qxt_d().m_dataColumn; } libqxt-0.6.2/src/gui/qxtlookuplineedit.h000066400000000000000000000021361215241066400203350ustar00rootroot00000000000000#ifndef QXTLOOKUPLINEEDIT_H_INCLUDED #define QXTLOOKUPLINEEDIT_H_INCLUDED #include #include #include #include "qxtglobal.h" class QxtLookupLineEditPrivate; class QAbstractItemModel; class QKeyEvent; class QXT_GUI_EXPORT QxtLookupLineEdit : public QLineEdit { Q_OBJECT public: QxtLookupLineEdit(QWidget *parent = 0); ~QxtLookupLineEdit(); void setSourceModel (QAbstractItemModel *model); void setLookupColumn (const int column); void setDataColumn (const int column); void setLookupRole (const int role); void setPopupTrigger (const QKeySequence &trigger); QAbstractItemModel *sourceModel() const; int lookupColumn ( ) const; int dataColumn ( ) const; int lookupRole ( ) const; QKeySequence popupTrigger () const; protected: virtual void keyPressEvent ( QKeyEvent * event ); protected slots: virtual void showPopup(); signals: void selected (); private: QXT_DECLARE_PRIVATE(QxtLookupLineEdit); }; #endif // QXTLOOKUPLINEEDIT_H_INCLUDED libqxt-0.6.2/src/gui/qxtlookuplineedit_p.h000066400000000000000000000013141215241066400206510ustar00rootroot00000000000000#ifndef QXTLOOKUPLINEEDIT_P_H_INCLUDED #define QXTLOOKUPLINEEDIT_P_H_INCLUDED #include "qxtpimpl.h" #include "qxtfilterdialog.h" #include #include #include #include class QxtLookupLineEdit; class QAbstractItemModel; class QxtLookupLineEditPrivate : public QxtPrivate { public: QxtLookupLineEditPrivate(); QXT_DECLARE_PUBLIC(QxtLookupLineEdit); int m_dataColumn; int m_lookupColumn; int m_lookupRole; QAbstractItemModel* m_sourceModel; QKeySequence m_trigger; }; #endif //QXTLOOKUPLINEEDIT_P_H_INCLUDED libqxt-0.6.2/src/gui/qxtnativeeventfilter.h000066400000000000000000000036631215241066400210520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTNATIVEEVENTFILTER_H #define QXTNATIVEEVENTFILTER_H #include "qxtapplication.h" class QxtNativeEventFilter { public: virtual ~QxtNativeEventFilter() { qxtApp->removeNativeEventFilter(this); } #if defined(Q_WS_X11) || defined(QXT_DOXYGEN_RUN) virtual bool x11EventFilter(XEvent*) { return false; } #endif // Q_WS_X11 #if defined(Q_WS_WIN) || defined(QXT_DOXYGEN_RUN) virtual bool winEventFilter(MSG*, long*) { return false; } #endif // Q_WS_WIN #if defined(Q_WS_MAC) || defined(QXT_DOXYGEN_RUN) virtual bool macEventFilter(EventHandlerCallRef, EventRef) { return false; } #endif // Q_WS_MAC }; #endif // QXTNATIVEEVENTFILTER_H libqxt-0.6.2/src/gui/qxtprogresslabel.cpp000066400000000000000000000150671215241066400205140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtprogresslabel.h" #include #include #include class QxtProgressLabelPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtProgressLabel) QxtProgressLabelPrivate(); QTime start; int interval; int cachedMin; int cachedMax; int cachedVal; QString cformat; QString tformat; QBasicTimer timer; }; QxtProgressLabelPrivate::QxtProgressLabelPrivate() : interval(-1), cachedMin(0), cachedMax(0), cachedVal(0) {} /*! \class QxtProgressLabel \inmodule QxtGui \brief The QxtProgressLabel widget is a label showing progress related time values. QxtProgressLabel is a label widget able to show elapsed and remaining time of a progress. Usage is as simple as connecting signal QProgressBar::valueChanged() to slot QxtProgressLabel::setValue(). Example usage: \code QProgressBar* bar = new QProgressBar(this); QxtProgressLabel* label = new QxtProgressLabel(this); connect(bar, SIGNAL(valueChanged(int)), label, SLOT(setValue(int))); \endcode \image qxtprogresslabel.png "QxtProgressLabel in action." */ /*! Constructs a new QxtProgressLabel with \a parent and \a flags. */ QxtProgressLabel::QxtProgressLabel(QWidget* parent, Qt::WindowFlags flags) : QLabel(parent, flags) { QXT_INIT_PRIVATE(QxtProgressLabel); refresh(); } /*! Constructs a new QxtProgressLabel with \a text, \a parent and \a flags. */ QxtProgressLabel::QxtProgressLabel(const QString& text, QWidget* parent, Qt::WindowFlags flags) : QLabel(text, parent, flags) { QXT_INIT_PRIVATE(QxtProgressLabel); refresh(); } /*! Destructs the progress label. */ QxtProgressLabel::~QxtProgressLabel() {} /*! \property QxtProgressLabel::contentFormat \brief the content format of the progress label The content of the label is formatted according to this property. The default value is an empty string which defaults to \bold "ETA: %r". The following variables may be used in the format string: \table \header \o Variable \o Output \row \o \%e \o elapsed time \row \o \%r \o remaining time \endtable \sa timeFormat */ QString QxtProgressLabel::contentFormat() const { return qxt_d().cformat; } void QxtProgressLabel::setContentFormat(const QString& format) { if (qxt_d().cformat != format) { qxt_d().cformat = format; refresh(); } } /*! \property QxtProgressLabel::timeFormat \brief the time format of the progress label Time values are formatted according to this property. The default value is an empty string which defaults to \bold "mm:ss". \sa contentFormat, QTime::toString() */ QString QxtProgressLabel::timeFormat() const { return qxt_d().tformat; } void QxtProgressLabel::setTimeFormat(const QString& format) { if (qxt_d().tformat != format) { qxt_d().tformat = format; refresh(); } } /*! \property QxtProgressLabel::updateInterval \brief the update interval of the progress label The content of the progress label is updated according to this interval. A negative interval makes the content to update only during value changes. The default value is \c -1. */ int QxtProgressLabel::updateInterval() const { return qxt_d().interval; } void QxtProgressLabel::setUpdateInterval(int msecs) { qxt_d().interval = msecs; if (msecs < 0) { if (qxt_d().timer.isActive()) qxt_d().timer.stop(); } else { if (!qxt_d().timer.isActive()) qxt_d().timer.start(msecs, this); } } /*! Sets the current value to \a value. \bold {Note:} Calling this slot by hand has no effect. Connect this slot to QProgressBar::valueChange(). */ void QxtProgressLabel::setValue(int value) { QProgressBar* bar = qobject_cast(sender()); if (bar) { if (!qxt_d().start.isValid()) restart(); qxt_d().cachedMin = bar->minimum(); qxt_d().cachedMax = bar->maximum(); qxt_d().cachedVal = value; refresh(); } } /*! Restarts the calculation of elapsed and remaining times. */ void QxtProgressLabel::restart() { qxt_d().cachedMin = 0; qxt_d().cachedMax = 0; qxt_d().cachedVal = 0; qxt_d().start.restart(); refresh(); } /*! Refreshes the content. */ void QxtProgressLabel::refresh() { // elapsed qreal elapsed = 0; if (qxt_d().start.isValid()) elapsed = qxt_d().start.elapsed() / 1000.0; QTime etime(0, 0); etime = etime.addSecs(static_cast(elapsed)); // percentage qreal percent = 0; if (qxt_d().cachedMax != 0) percent = (qxt_d().cachedVal - qxt_d().cachedMin) / static_cast(qxt_d().cachedMax); qreal total = 0; if (percent != 0) total = elapsed / percent; // remaining QTime rtime(0, 0); rtime = rtime.addSecs(static_cast(total - elapsed)); // format QString tformat = qxt_d().tformat; if (tformat.isEmpty()) tformat = tr("mm:ss"); QString cformat = qxt_d().cformat; if (cformat.isEmpty()) cformat = tr("ETA: %r"); QString result = QString(cformat).replace("%e", etime.toString(tformat)); result = result.replace("%r", rtime.toString(tformat)); setText(result); } /*! \reimp */ void QxtProgressLabel::timerEvent(QTimerEvent* event) { Q_UNUSED(event); refresh(); } libqxt-0.6.2/src/gui/qxtprogresslabel.h000066400000000000000000000043641215241066400201570ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTPROGRESSLABEL_H #define QXTPROGRESSLABEL_H #include #include "qxtglobal.h" class QxtProgressLabelPrivate; class QXT_GUI_EXPORT QxtProgressLabel : public QLabel { Q_OBJECT QXT_DECLARE_PRIVATE(QxtProgressLabel) Q_PROPERTY(QString contentFormat READ contentFormat WRITE setContentFormat) Q_PROPERTY(QString timeFormat READ timeFormat WRITE setTimeFormat) Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval) public: explicit QxtProgressLabel(QWidget* parent = 0, Qt::WindowFlags flags = 0); explicit QxtProgressLabel(const QString& text, QWidget* parent = 0, Qt::WindowFlags flags = 0); virtual ~QxtProgressLabel(); QString contentFormat() const; void setContentFormat(const QString& format); QString timeFormat() const; void setTimeFormat(const QString& format); int updateInterval() const; void setUpdateInterval(int msecs); public Q_SLOTS: void setValue(int value); void refresh(); void restart(); virtual void timerEvent(QTimerEvent* event); }; #endif // QXTPROGRESSLABEL_H libqxt-0.6.2/src/gui/qxtproxystyle.cpp000066400000000000000000000175541215241066400201150ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtproxystyle.h" #include /*! \class QxtProxyStyle \inmodule QxtGui \brief The QxtProxyStyle class provides a proxy style. A technique called "proxy style" is a common way for creating cross-platform custom styles. Developers often want to do slight adjustments in some specific values returned by QStyle. A proxy style is the solution to avoid subclassing any platform specific style (eg. QPlastiqueStyle, QWindowsXPStyle, or QMacStyle) and to retain the native look on all supported platforms. The subject has been discussed in \l {http://doc.trolltech.com/qq/qq09-q-and-a.html#style} {Qt Quarterly 9} (just notice that there are a few noteworthy spelling mistakes in the article). Proxy styles are becoming obsolete thanks to style sheets introduced in Qt 4.2. However, style sheets still is a new concept and only a portion of features are supported yet. Both - style sheets and proxy styles - have their pros and cons. \section1 Usage Implement the custom behaviour in a subclass of QxtProxyStyle: \code class MyCustomStyle : public QxtProxyStyle { public: MyCustomStyle(const QString& baseStyle) : QxtProxyStyle(baseStyle) { } int pixelMetric(PixelMetric metric, const QStyleOption* option = 0, const QWidget* widget = 0) const { if (metric == QStyle::PM_ButtonMargin) return 6; return QxtProxyStyle::pixelMetric(metric, option, widget); } }; \endcode Using the custom style for the whole application: \code QString defaultStyle = QApplication::style()->objectName(); QApplication::setStyle(new MyCustomStyle(defaultStyle)); \endcode Using the custom style for a single widget: \code QString defaultStyle = widget->style()->objectName(); widget->setStyle(new MyCustomStyle(defaultStyle)); \endcode */ /*! Constructs a new QxtProxyStyle for \a baseStyle. See QStyleFactory::keys() for supported styles. \sa QStyleFactory::keys() */ QxtProxyStyle::QxtProxyStyle(const QString& baseStyle) : QStyle(), style(QStyleFactory::create(baseStyle)) { setObjectName(QLatin1String("proxy")); } /*! Destructs the proxy style. */ QxtProxyStyle::~QxtProxyStyle() { delete style; } /*! \reimp */ void QxtProxyStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const { style->drawComplexControl(control, option, painter, widget); } /*! \reimp */ void QxtProxyStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const { style->drawControl(element, option, painter, widget); } /*! \reimp */ void QxtProxyStyle::drawItemPixmap(QPainter* painter, const QRect& rect, int alignment, const QPixmap& pixmap) const { style->drawItemPixmap(painter, rect, alignment, pixmap); } /*! \reimp */ void QxtProxyStyle::drawItemText(QPainter* painter, const QRect& rect, int alignment, const QPalette& pal, bool enabled, const QString& text, QPalette::ColorRole textRole) const { style->drawItemText(painter, rect, alignment, pal, enabled, text, textRole); } /*! \reimp */ void QxtProxyStyle::drawPrimitive(PrimitiveElement elem, const QStyleOption* option, QPainter* painter, const QWidget* widget) const { style->drawPrimitive(elem, option, painter, widget); } /*! \reimp */ QPixmap QxtProxyStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap& pixmap, const QStyleOption* option) const { return style->generatedIconPixmap(iconMode, pixmap, option); } /*! \reimp */ QStyle::SubControl QxtProxyStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex* option, const QPoint& pos, const QWidget* widget) const { return style->hitTestComplexControl(control, option, pos, widget); } /*! \reimp */ QRect QxtProxyStyle::itemPixmapRect(const QRect& rect, int alignment, const QPixmap& pixmap) const { return style->itemPixmapRect(rect, alignment, pixmap); } /*! \reimp */ QRect QxtProxyStyle::itemTextRect(const QFontMetrics& metrics, const QRect& rect, int alignment, bool enabled, const QString& text) const { return style->itemTextRect(metrics, rect, alignment, enabled, text); } /*! \reimp */ int QxtProxyStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const { return style->pixelMetric(metric, option, widget); } /*! \reimp */ void QxtProxyStyle::polish(QWidget* widget) { style->polish(widget); } /*! \reimp */ void QxtProxyStyle::polish(QApplication* app) { style->polish(app); } /*! \reimp */ void QxtProxyStyle::polish(QPalette& pal) { style->polish(pal); } /*! \reimp */ QSize QxtProxyStyle::sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& contentsSize, const QWidget* widget) const { return style->sizeFromContents(type, option, contentsSize, widget); } /*! \reimp */ QPalette QxtProxyStyle::standardPalette() const { return style->standardPalette(); } /*! \reimp */ QPixmap QxtProxyStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption* option, const QWidget* widget) const { return style->standardPixmap(standardPixmap, option, widget); } /*! \reimp */ int QxtProxyStyle::styleHint(StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const { return style->styleHint(hint, option, widget, returnData); } /*! \reimp */ QRect QxtProxyStyle::subControlRect(ComplexControl control, const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget) const { return style->subControlRect(control, option, subControl, widget); } /*! \reimp */ QRect QxtProxyStyle::subElementRect(SubElement element, const QStyleOption* option, const QWidget* widget) const { return style->subElementRect(element, option, widget); } /*! \reimp */ void QxtProxyStyle::unpolish(QWidget* widget) { style->unpolish(widget); } /*! \reimp */ void QxtProxyStyle::unpolish(QApplication* app) { style->unpolish(app); } /*! \reimp */ QIcon QxtProxyStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption* option, const QWidget* widget) const { QIcon result; QMetaObject::invokeMethod(style, "standardIconImplementation", Qt::DirectConnection, Q_RETURN_ARG(QIcon, result), Q_ARG(StandardPixmap, standardIcon), Q_ARG(const QStyleOption*, option), Q_ARG(const QWidget*, widget)); return result; } libqxt-0.6.2/src/gui/qxtproxystyle.h000066400000000000000000000075551215241066400175620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTPROXYSTYLE_H #define QXTPROXYSTYLE_H #include #include "qxtglobal.h" class QXT_GUI_EXPORT QxtProxyStyle : public QStyle { Q_OBJECT public: explicit QxtProxyStyle(const QString& baseStyle); virtual ~QxtProxyStyle(); virtual void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget = 0) const; virtual void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = 0) const; virtual void drawItemPixmap(QPainter* painter, const QRect& rect, int alignment, const QPixmap& pixmap) const; virtual void drawItemText(QPainter* painter, const QRect& rect, int alignment, const QPalette& pal, bool enabled, const QString& text, QPalette::ColorRole textRole = QPalette::NoRole) const; virtual void drawPrimitive(PrimitiveElement elem, const QStyleOption* option, QPainter* painter, const QWidget* widget = 0) const; virtual QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap& pixmap, const QStyleOption* option) const; virtual SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex* option, const QPoint& pos, const QWidget* widget = 0) const; virtual QRect itemPixmapRect(const QRect& rect, int alignment, const QPixmap& pixmap) const; virtual QRect itemTextRect(const QFontMetrics& metrics, const QRect& rect, int alignment, bool enabled, const QString& text) const; virtual int pixelMetric(PixelMetric metric, const QStyleOption* option = 0, const QWidget* widget = 0) const; virtual void polish(QWidget* widget); virtual void polish(QApplication* app); virtual void polish(QPalette& pal); virtual QSize sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& contentsSize, const QWidget* widget = 0) const; virtual QPalette standardPalette() const; virtual QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption* option = 0, const QWidget* widget = 0) const; virtual int styleHint(StyleHint hint, const QStyleOption* option = 0, const QWidget* widget = 0, QStyleHintReturn* returnData = 0) const; virtual QRect subControlRect(ComplexControl control, const QStyleOptionComplex* option, SubControl subControl, const QWidget* widget = 0) const; virtual QRect subElementRect(SubElement element, const QStyleOption* option, const QWidget* widget = 0) const; virtual void unpolish(QWidget* widget); virtual void unpolish(QApplication* app); protected Q_SLOTS: QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption* option = 0, const QWidget* widget = 0) const; private: QStyle* style; }; #endif // QXTPROXYSTYLE_H libqxt-0.6.2/src/gui/qxtpushbutton.cpp000066400000000000000000000205221215241066400200530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtpushbutton.h" #include #include #include #include #include #include static const int Vertical_Mask = 0x02; class QxtPushButtonPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtPushButton) QxtPushButtonPrivate(); bool isRichText() const; QStyleOptionButton getStyleOption() const; QString text; Qxt::Rotation rot; Qt::TextFormat format; mutable QTextDocument* doc; }; QxtPushButtonPrivate::QxtPushButtonPrivate() : rot(Qxt::NoRotation), format(Qt::PlainText), doc(0) { } bool QxtPushButtonPrivate::isRichText() const { bool rich = (format == Qt::RichText) || (format == Qt::AutoText && Qt::mightBeRichText(qxt_p().text())); if (rich && !doc) { doc = new QTextDocument(const_cast(&qxt_p())); doc->setUndoRedoEnabled(false); } return rich; } QStyleOptionButton QxtPushButtonPrivate::getStyleOption() const { QStyleOptionButton option; option.initFrom(&qxt_p()); if (rot & Vertical_Mask) { QSize size = option.rect.size(); size.transpose(); option.rect.setSize(size); } option.features = QStyleOptionButton::None; if (qxt_p().isFlat()) option.features |= QStyleOptionButton::Flat; if (qxt_p().menu()) option.features |= QStyleOptionButton::HasMenu; if (qxt_p().autoDefault() || qxt_p().isDefault()) option.features |= QStyleOptionButton::AutoDefaultButton; if (qxt_p().isDefault()) option.features |= QStyleOptionButton::DefaultButton; if (qxt_p().isDown() || (qxt_p().menu() && qxt_p().menu()->isVisible())) option.state |= QStyle::State_Sunken; if (qxt_p().isChecked()) option.state |= QStyle::State_On; if (!qxt_p().isFlat() && !qxt_p().isDown()) option.state |= QStyle::State_Raised; if (!isRichText()) { option.text = qxt_p().text(); option.icon = qxt_p().icon(); option.iconSize = qxt_p().iconSize(); } return option; } /*! \class QxtPushButton \inmodule QxtGui \brief The QxtPushButton widget is an extended QPushButton with rotation and rich text support. QxtPushButton is a QPushButton which can be rotated. In addition, QxtPushButton provides rich text support. \image qxtpushbutton.png "QxtPushButton in action." */ /*! Constructs a new QxtPushButton with \a parent. */ QxtPushButton::QxtPushButton(QWidget* parent) : QPushButton(parent) { QXT_INIT_PRIVATE(QxtPushButton); } /*! Constructs a new QxtPushButton with \a text and \a parent. */ QxtPushButton::QxtPushButton(const QString& text, QWidget* parent) : QPushButton(text, parent) { QXT_INIT_PRIVATE(QxtPushButton); } /*! Constructs a new QxtPushButton with \a icon, \a text and \a parent. \bold {Note:} An icon is not rendered when using rich text. */ QxtPushButton::QxtPushButton(const QIcon& icon, const QString& text, QWidget* parent) : QPushButton(icon, text, parent) { QXT_INIT_PRIVATE(QxtPushButton); } /*! Constructs a new QxtPushButton with \a rotation, \a text and \a parent. */ QxtPushButton::QxtPushButton(Qxt::Rotation rotation, const QString& text, QWidget* parent) : QPushButton(text, parent) { QXT_INIT_PRIVATE(QxtPushButton); setRotation(rotation); } /*! Destructs the button. */ QxtPushButton::~QxtPushButton() {} /*! \property QxtPushButton::rotation \brief the rotation of the button The button is rotated according to this property. The default value is Qxt::NoRotation. \sa Qxt::Rotation */ Qxt::Rotation QxtPushButton::rotation() const { return qxt_d().rot; } void QxtPushButton::setRotation(Qxt::Rotation rotation) { if (qxt_d().rot != rotation) { qxt_d().rot = rotation; switch (rotation) { case Qxt::NoRotation: case Qxt::UpsideDown: setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); break; case Qxt::Clockwise: case Qxt::CounterClockwise: setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); break; default: // nothing to do break; } updateGeometry(); update(); } } /*! \property QxtPushButton::textFormat \brief the text format of the button Supported formats are Qt::PlainText, Qt::RichText and Qt::AutoText. The default format is Qt::PlainText. \sa Qt::TextFormat */ Qt::TextFormat QxtPushButton::textFormat() const { return qxt_d().format; } void QxtPushButton::setTextFormat(Qt::TextFormat format) { if (qxt_d().format != format) { qxt_d().format = format; if (!qxt_d().isRichText()) { delete qxt_d().doc; qxt_d().doc = 0; } qxt_d().text.clear(); update(); updateGeometry(); } } /*! \reimp */ QSize QxtPushButton::sizeHint() const { QSize size; if (qxt_d().isRichText()) size = qxt_d().doc->documentLayout()->documentSize().toSize(); else size = QPushButton::sizeHint(); if (qxt_d().rot & Vertical_Mask) size.transpose(); return size; } /*! \reimp */ QSize QxtPushButton::minimumSizeHint() const { return sizeHint(); } /*! \reimp */ void QxtPushButton::paintEvent(QPaintEvent* event) { Q_UNUSED(event); // the only reliable way to detect text changes if (text() != qxt_d().text) { qxt_d().text = text(); if (qxt_d().isRichText()) qxt_d().doc->setHtml(qxt_d().text); updateGeometry(); } QStylePainter painter(this); painter.rotate(qxt_d().rot); switch (qxt_d().rot) { case Qxt::UpsideDown: painter.translate(-width(), -height()); break; case Qxt::Clockwise: painter.translate(0, -width()); break; case Qxt::CounterClockwise: painter.translate(-height(), 0); break; default: // nothing to do break; } const QStyleOptionButton option = qxt_d().getStyleOption(); painter.drawControl(QStyle::CE_PushButton, option); if (qxt_d().isRichText()) { int dx = 0; int dy = 0; if (option.state & (QStyle::State_On | QStyle::State_Sunken)) { dx += style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &option, this); dy += style()->pixelMetric(QStyle::PM_ButtonShiftVertical, &option, this); } QRect area = rect(); const QSizeF docSize = qxt_d().doc->documentLayout()->documentSize(); if (qxt_d().rot & Vertical_Mask) { dx += static_cast((height() - docSize.width()) / 2); dy += static_cast((width() - docSize.height()) / 2); painter.translate(dx, dy); QSize size = area.size(); size.transpose(); area.setSize(size); } else { dx += static_cast((width() - docSize.width()) / 2); dy += static_cast((height() - docSize.height()) / 2); painter.translate(dx, dy); } qxt_d().doc->drawContents(&painter, area); } } libqxt-0.6.2/src/gui/qxtpushbutton.h000066400000000000000000000043551215241066400175260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTPUSHBUTTON_H #define QXTPUSHBUTTON_H #include #include "qxtnamespace.h" #include "qxtglobal.h" class QxtPushButtonPrivate; class QXT_GUI_EXPORT QxtPushButton : public QPushButton { Q_OBJECT QXT_DECLARE_PRIVATE(QxtPushButton) Q_PROPERTY(Qxt::Rotation rotation READ rotation WRITE setRotation) Q_PROPERTY(Qt::TextFormat textFormat READ textFormat WRITE setTextFormat) public: explicit QxtPushButton(QWidget* parent = 0); explicit QxtPushButton(const QString& text, QWidget* parent = 0); explicit QxtPushButton(const QIcon& icon, const QString& text, QWidget* parent = 0); explicit QxtPushButton(Qxt::Rotation rotation, const QString& text, QWidget* parent = 0); virtual ~QxtPushButton(); Qxt::Rotation rotation() const; void setRotation(Qxt::Rotation rotation); Qt::TextFormat textFormat() const; void setTextFormat(Qt::TextFormat format); virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; protected: virtual void paintEvent(QPaintEvent* event); }; #endif // QXTPUSHBUTTON_H libqxt-0.6.2/src/gui/qxtscheduleheaderwidget.cpp000066400000000000000000000060031215241066400220070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtscheduleheaderwidget.h" #include "qxtscheduleview.h" #include "qxtscheduleviewheadermodel_p.h" #include #include #include #include /*! * @internal the QxtAgendaHeaderWidget operates on a internal model , that uses the QxtScheduleView as DataSource * */ QxtScheduleHeaderWidget::QxtScheduleHeaderWidget(Qt::Orientation orientation , QxtScheduleView *parent) : QHeaderView(orientation, parent) { QxtScheduleViewHeaderModel *model = new QxtScheduleViewHeaderModel(this); setModel(model); if (parent) { model->setDataSource(parent); } } void QxtScheduleHeaderWidget::paintSection(QPainter * painter, const QRect & rect, int logicalIndex) const { if (model()) { switch (orientation()) { case Qt::Horizontal: { QHeaderView::paintSection(painter, rect, logicalIndex); } break; case Qt::Vertical: { QTime time = model()->headerData(logicalIndex, Qt::Vertical, Qt::DisplayRole).toTime(); if (time.isValid()) { QRect temp = rect; temp.adjust(1, 1, -1, -1); painter->fillRect(rect, this->palette().background()); if (time.minute() == 0) { painter->drawLine(temp.topLeft() + QPoint(temp.width() / 3, 0), temp.topRight()); painter->drawText(temp, Qt::AlignTop | Qt::AlignRight, time.toString("hh:mm")); } } } break; default: Q_ASSERT(false); //this will never happen... normally } } } void QxtScheduleHeaderWidget::setModel(QxtScheduleViewHeaderModel *model) { QHeaderView::setModel(model); } libqxt-0.6.2/src/gui/qxtscheduleheaderwidget.h000066400000000000000000000035171215241066400214630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSCHEDULEHEADERWIDGET_H_INCLUDED #define QXTSCHEDULEHEADERWIDGET_H_INCLUDED #include #include "qxtglobal.h" class QxtScheduleView; class QxtScheduleViewHeaderModel; class QXT_GUI_EXPORT QxtScheduleHeaderWidget : public QHeaderView { Q_OBJECT public: explicit QxtScheduleHeaderWidget(Qt::Orientation orientation, QxtScheduleView *parent = 0); protected: virtual void paintSection(QPainter * painter, const QRect & rect, int logicalIndex) const; private: virtual void setModel(QxtScheduleViewHeaderModel *model); }; #endif // QXTSCHEDULEHEADERWIDGET_H_INCLUDED libqxt-0.6.2/src/gui/qxtscheduleitemdelegate.cpp000066400000000000000000000246631215241066400220200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtscheduleitemdelegate.h" #include #include #include #include #include #include #include #include #include #include "qxtnamespace.h" QxtScheduleItemDelegate::QxtScheduleItemDelegate(QObject *parent) : QAbstractItemDelegate(parent) { } QxtScheduleItemDelegate::~QxtScheduleItemDelegate() { } /*! * reimplemented for item painting * You should not reimplement this to change the item painting, use paintItemBody, paintItemHeader and paintSubItem instead * because this function uses caches to speed up painting. If you want to change the item shape only you could also reimplement * the createPainterPath function. * \note the parameter option hast to be of type QxtStyleOptionScheduleViewItem or the delegate will not paint something * \sa paintItemBody(), paintItemHeader(), paintSubItem() */ void QxtScheduleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { const QxtStyleOptionScheduleViewItem *agendaOption = qstyleoption_cast(&option); if (!agendaOption) return; QStringList rowsData = index.data(Qt::EditRole).toStringList(); QRect currRect; painter->save(); if (agendaOption->itemPaintCache->size() != agendaOption->itemGeometries.size()) (*agendaOption->itemPaintCache) = QVector(agendaOption->itemGeometries.size(), QPixmap()); int lastPart = agendaOption->itemGeometries.size() - 1; int paintedSubItems = 0; for (int iLoop = 0; iLoop < agendaOption->itemGeometries.size();iLoop++) { if ((*agendaOption->itemPaintCache)[iLoop].width() != agendaOption->itemGeometries[iLoop].width() || (*agendaOption->itemPaintCache)[iLoop].height() != agendaOption->itemGeometries[iLoop].height()) { //If we enter this codepath we have to rebuild the pixmap cache //so first we create a empty pixmap (*agendaOption->itemPaintCache)[iLoop] = QPixmap(agendaOption->itemGeometries[iLoop].size()); (*agendaOption->itemPaintCache)[iLoop].fill(Qt::transparent); QPainter cachePainter(&(*agendaOption->itemPaintCache)[iLoop]); QRect rect = QRect(QPoint(0, 0), agendaOption->itemGeometries[iLoop].size()); //what kind of itempart do we need to paint? ItemPart part = iLoop == 0 ? Top : (iLoop == lastPart ? Bottom : Middle); //if the item has only one part if (lastPart == 0) part = Single; //paint the item body cachePainter.save(); paintItemBody(&cachePainter, rect, *agendaOption, part, index); cachePainter.restore(); int remainingHeight = rect.height(); //paint item header if (iLoop == 0 && agendaOption->itemHeaderHeight > 0 && agendaOption->itemHeaderHeight < remainingHeight) { QRect headerRect(0, 0, rect.width(), agendaOption->itemHeaderHeight); paintItemHeader(&cachePainter, headerRect, *agendaOption, index); remainingHeight -= agendaOption->itemHeaderHeight; } //paint subitems if there are any int subItems = index.model()->rowCount(index); for (int items = paintedSubItems; items < subItems; items++) { QModelIndex currSubItem = index.model()->index(items, 0, index); QSize size = sizeHint(option, currSubItem); if (currSubItem.isValid()){ paintSubItem(&cachePainter, QRect(), *agendaOption, currSubItem); } paintedSubItems++; } cachePainter.end(); } currRect = agendaOption->itemGeometries[iLoop]; currRect.translate(agendaOption->translate); painter->drawPixmap(currRect, (*agendaOption->itemPaintCache)[iLoop]); } painter->restore(); } /*! * \brief paints the items body reimplement this to paint a custom body * \a QPainter *painter the initialized painter * \a const QRect rect the ItemPart rect * \a const QxtStyleOptionScheduleViewItem & option * \a const ItemPart part this indicates what part of the item gets painted, remember items can be splitted in parts * \a const QModelIndex &index the items model index */ void QxtScheduleItemDelegate::paintItemBody(QPainter *painter, const QRect rect , const QxtStyleOptionScheduleViewItem & option , const ItemPart part, const QModelIndex & index) const { int iCurrRoundTop, iCurrRoundBottom; iCurrRoundTop = iCurrRoundBottom = 0; QColor fillColor = index.data(Qt::BackgroundRole).value(); fillColor.setAlpha(120); QColor outLineColor = index.data(Qt::ForegroundRole).value(); painter->setFont(option.font); painter->setRenderHint(QPainter::Antialiasing); if (part == Top || part == Single) iCurrRoundTop = option.roundCornersRadius; if (part == Bottom || part == Single) iCurrRoundBottom = option.roundCornersRadius; QPainterPath cachePath; QRect cacheRect = QRect(QPoint(1, 1), rect.size() - QSize(1, 1)); painter->setBrush(fillColor); painter->setPen(outLineColor); createPainterPath(cachePath, cacheRect, iCurrRoundTop, iCurrRoundBottom); painter->drawPath(cachePath); } /*! * \brief paints the items header reimplement this to paint a custom header * \a QPainter *painter the initialized painter * \a const QRect rect the header rect * \a const QxtStyleOptionScheduleViewItem & option * \a const QModelIndex &index the items model index */ void QxtScheduleItemDelegate::paintItemHeader(QPainter *painter, const QRect rect , const QxtStyleOptionScheduleViewItem & option, const QModelIndex &index) const { bool converted = false; int startUnixTime = index.data(Qxt::ItemStartTimeRole).toInt(&converted); if (!converted) return; int duration = index.data(Qxt::ItemDurationRole).toInt(&converted); if (!converted) return; QDateTime startTime = QDateTime::fromTime_t(startUnixTime); QDateTime endTime = QDateTime::fromTime_t(startUnixTime + duration); if (!startTime.isValid() || !endTime.isValid()) return; QFont font; QVariant vfont = index.data(Qt::FontRole); if (vfont.isValid()) font = vfont.value(); else font = option.font; QString text = startTime.toString("hh:mm") + ' ' + endTime.toString("hh:mm"); QFontMetrics metr(font); text = metr.elidedText(text, Qt::ElideRight, rect.width()); painter->drawText(rect, Qt::AlignCenter, text); } /*! * \brief paints a subitem, if you want custom subitem painting reimplement this member function * \a QPainter *painter the initialized painter * \a const QRect rect the subitem rect * \a const QxtStyleOptionScheduleViewItem & option * \a const QModelIndex &index the items model index */ void QxtScheduleItemDelegate::paintSubItem(QPainter * /*painter*/, const QRect /*rect*/, const QxtStyleOptionScheduleViewItem & /*option*/, const QModelIndex & /*index*/) const { } /*! * \brief returns the sizeHint for subitems. */ QSize QxtScheduleItemDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const { //we return the size only for subitems and only the height if (index.parent().isValid()) { QSize size = index.data(Qt::SizeHintRole).toSize(); if (!size.isValid()) { QFont font; QVariant vfont = index.data(Qt::FontRole); if (vfont.isValid()) font = vfont.value(); else font = option.font; int height = 0; QFontMetrics metr(font); height = metr.height() + 2; return QSize(0, height); } } return QSize(); } void QxtScheduleItemDelegate::createPainterPath(QPainterPath & emptyPath, const QRect & fullItemRect, const int iRoundTop, const int iRoundBottom) const { emptyPath = QPainterPath(); bool bRoundTop = iRoundTop > 0; bool bRountBottom = iRoundBottom > 0; if (bRoundTop) { emptyPath.moveTo(fullItemRect.topLeft() + QPoint(0, iRoundTop)); emptyPath.quadTo(fullItemRect.topLeft(), fullItemRect.topLeft() + QPoint(iRoundTop, 0)); } else emptyPath.moveTo(fullItemRect.topLeft()); emptyPath.lineTo(fullItemRect.topRight() - QPoint(iRoundTop, 0)); if (bRoundTop) emptyPath.quadTo(fullItemRect.topRight(), fullItemRect.topRight() + QPoint(0, iRoundTop)); emptyPath.lineTo(fullItemRect.bottomRight() - QPoint(0, iRoundBottom)); if (bRountBottom) emptyPath.quadTo(fullItemRect.bottomRight(), fullItemRect.bottomRight() - QPoint(iRoundBottom, 0)); emptyPath.lineTo(fullItemRect.bottomLeft() + QPoint(iRoundBottom, 0)); if (bRountBottom) emptyPath.quadTo(fullItemRect.bottomLeft(), fullItemRect.bottomLeft() - QPoint(0, iRoundBottom)); emptyPath.closeSubpath(); } libqxt-0.6.2/src/gui/qxtscheduleitemdelegate.h000066400000000000000000000053201215241066400214520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSCHEDULEITEMDELEGATE_H_INCLUDED #define QXTSCHEDULEITEMDELEGATE_H_INCLUDED #include #include #include "qxtstyleoptionscheduleviewitem.h" #include "qxtglobal.h" QT_FORWARD_DECLARE_CLASS(QPainter) /*! @author Benjamin Zeller */ class QXT_GUI_EXPORT QxtScheduleItemDelegate : public QAbstractItemDelegate { Q_OBJECT public: enum ItemPart { Top, Middle, Bottom, Single }; QxtScheduleItemDelegate(QObject *parent = 0); ~QxtScheduleItemDelegate(); virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; virtual void paintItemBody(QPainter *painter, const QRect rect , const QxtStyleOptionScheduleViewItem & option , const ItemPart part, const QModelIndex & index) const; virtual void paintItemHeader(QPainter *painter, const QRect rect , const QxtStyleOptionScheduleViewItem & option , const QModelIndex & index) const; virtual void paintSubItem(QPainter *painter, const QRect rect , const QxtStyleOptionScheduleViewItem & option , const QModelIndex & index) const; virtual QSize sizeHint(const QStyleOptionViewItem & option , const QModelIndex & index) const; virtual void createPainterPath(QPainterPath &emptyPath, const QRect &fullItemRect , const int iRoundTop, const int iRoundBottom) const; }; #endif // QXTSCHEDULEITEMDELEGATE_H_INCLUDED libqxt-0.6.2/src/gui/qxtscheduleview.cpp000066400000000000000000000765561215241066400203510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtscheduleview.h" #include "qxtscheduleview_p.h" #include "qxtscheduleheaderwidget.h" #include "qxtscheduleviewheadermodel_p.h" #include #include #include #include #include #include #include #include #include #include #include #include /*! \class QxtScheduleView QxtScheduleView \inmodule QxtGui \brief The QxtScheduleView class provides an iCal like view to plan events QxtScheduleView is a item based View,inspired by iCal, that makes it possible to visualize event planning. \raw HTML It's time based and can show the events in different modes:
  • DayMode : Every column in the view shows one day
  • HourMode : Every column in the view shows one hour
  • MinuteMode : Every column in the view shows one minute
In addition you can adjust how much time every cell represents in the view. The default value is 900 seconds or 15 minutes and DayMode. \endraw \image qxtscheduleview.png QxtScheduleView */ QxtScheduleView::QxtScheduleView(QWidget *parent) : QAbstractScrollArea(parent) { QXT_INIT_PRIVATE(QxtScheduleView); /*standart values are 15 minutes per cell and 69 rows == 1 Day*/ qxt_d().m_currentZoomDepth = 15 * 60; qxt_d().m_currentViewMode = DayView; qxt_d().m_startUnixTime = QDateTime(QDate::currentDate(),QTime(0, 0, 0)).toTime_t(); qxt_d().m_endUnixTime = QDateTime(QDate::currentDate().addDays(6),QTime(23, 59, 59)).toTime_t(); qxt_d().delegate = qxt_d().defaultDelegate = new QxtScheduleItemDelegate(this); #if 0 qxt_d().m_vHeader = new QxtScheduleHeaderWidget(Qt::Vertical, this); connect(qxt_d().m_vHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries())); qxt_d().m_vHeader->hide(); qxt_d().m_hHeader = new QxtScheduleHeaderWidget(Qt::Horizontal, this); connect(qxt_d().m_hHeader, SIGNAL(geometriesChanged()), this, SLOT(updateGeometries())); qxt_d().m_hHeader->hide(); #else //init will take care of initializing headers qxt_d().m_vHeader = 0; qxt_d().m_hHeader = 0; #endif } /*! * returns the vertial header *\note can be NULL if the view has not called init() already (FIXME) */ QHeaderView* QxtScheduleView::verticalHeader ( ) const { return qxt_d().m_vHeader; } /** * returns the horizontal header *\note can be NULL if the view has not called init() already (FIXME) */ QHeaderView* QxtScheduleView::horizontalHeader ( ) const { return qxt_d().m_hHeader; } /** * sets the model for QxtScheduleView * * \a model */ void QxtScheduleView::setModel(QAbstractItemModel *model) { if (qxt_d().m_Model) { /*delete all cached items*/ qDeleteAll(qxt_d().m_Items.begin(), qxt_d().m_Items.end()); qxt_d().m_Items.clear(); /*disconnect all signals*/ disconnect(qxt_d().m_Model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(dataChanged(const QModelIndex &, const QModelIndex &))); disconnect(qxt_d().m_Model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)), this, SLOT(rowsAboutToBeInserted(const QModelIndex &, int , int))); disconnect(qxt_d().m_Model, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(rowsInserted(const QModelIndex &, int , int))); disconnect(qxt_d().m_Model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), this, SLOT(rowsAboutToBeRemoved(const QModelIndex &, int , int))); disconnect(qxt_d().m_Model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SLOT(rowsRemoved(const QModelIndex &, int , int))); /*don't delete the model maybe someone else will use it*/ qxt_d().m_Model = 0; } if (model != 0) { /*initialize the new model*/ qxt_d().m_Model = model; connect(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(dataChanged(const QModelIndex &, const QModelIndex &))); connect(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)), this, SLOT(rowsAboutToBeInserted(const QModelIndex &, int , int))); connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SLOT(rowsInserted(const QModelIndex &, int , int))); connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), this, SLOT(rowsAboutToBeRemoved(const QModelIndex &, int , int))); connect(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SLOT(rowsRemoved(const QModelIndex &, int , int))); } qxt_d().init(); } QAbstractItemModel * QxtScheduleView::model() const { return qxt_d().m_Model; } /*! * changes the current ViewMode * The QxtScheduleView supports some different viewmodes. A viewmode defines how much time a column holds. * It is also possible to define custom viewmodes. To do that you have to set the currentView mode to Custom and * reimplement timePerColumn * * \a QxtScheduleView::ViewMode mode the new ViewMode * * \sa timePerColumn() * \sa viewMode() */ void QxtScheduleView::setViewMode(const QxtScheduleView::ViewMode mode) { qxt_d().m_currentViewMode = mode; //this will calculate the correct alignment //\BUG this may not work because the currentZoomDepth may not fit into the new viewMode setCurrentZoomDepth(qxt_d().m_currentZoomDepth); } /*! *\\esc returns the current used delegate */ QxtScheduleItemDelegate* QxtScheduleView::delegate () const { return qxt_d().delegate; } /*! *Sets the item delegate for this view and its model to delegate. This is useful if you want complete control over the editing and display of items. *Any existing delegate will be removed, but not deleted. QxtScheduleView does not take ownership of delegate. *Passing a 0 pointer will restore the view to use the default delegate. *\Warning You should not share the same instance of a delegate between views. Doing so can cause incorrect or unintuitive behavior. */ void QxtScheduleView::setItemDelegate (QxtScheduleItemDelegate * delegate) { if(!delegate) qxt_d().delegate = qxt_d().defaultDelegate; else qxt_d().delegate = delegate; //the delegate changed repaint everything viewport()->update(); } /*! * returns the current ViewMode * * Returns QxtScheduleView::ViewMode * \sa setViewMode() */ QxtScheduleView::ViewMode QxtScheduleView::viewMode() const { return (ViewMode)qxt_d().m_currentViewMode; } /*! * changes the current Zoom step width * Changes the current Zoom step width. Zooming in QxtScheduleView means to change the amount * of time one cell holds. For example 5 Minutes. The zoom step width defines how many time * is added / removed from the cell when zooming the view. * * \a int zoomWidth the new zoom step width * \a Qxt::Timeunit unit the unit of the new step width (Minutes , Seconds , Hours) * * \sa zoomIn() zoomOut() setCurrentZoomDepth() */ void QxtScheduleView::setZoomStepWidth(const int zoomWidth , const Qxt::Timeunit unit) { switch (unit) { case Qxt::Second: { qxt_d().m_zoomStepWidth = zoomWidth; } break; case Qxt::Minute: { qxt_d().m_zoomStepWidth = zoomWidth * 60; } break; case Qxt::Hour: { qxt_d().m_zoomStepWidth = zoomWidth * 60 * 60; } break; default: qWarning() << "This Timeunit is not implemented yet you can use Second,Minute,Hour using standart 15 minutes"; qxt_d().m_zoomStepWidth = 900; break; } } /*! * changes the current zoom depth * The current zoom depth in QxtScheduleView defines how many time one cell holds in the view. * If the new depth does not fit in the view the next possible value is used. If no possible value can be found * nothing changes. * Normally this is used only to initialize the view, later you want to use zoomIn and zoomOut * * \a int depth * \a Qxt::Timeunit unit * * \sa zoomIn() zoomOut() setCurrentZoomDepth() */ void QxtScheduleView::setCurrentZoomDepth(const int depth , const Qxt::Timeunit unit) { int newZoomDepth = 900; //a zoom depth of 0 is invalid if (depth == 0) return; switch (unit) { case Qxt::Second: { newZoomDepth = depth; } break; case Qxt::Minute: { newZoomDepth = depth * 60; } break; case Qxt::Hour: { newZoomDepth = depth * 60 * 60; } break; default: qWarning() << "This Timeunit is not implemented yet you can use Second,Minute,Hour using standart 15 minutes"; break; } //now we have to align the currentZoomDepth to the viewMode int timePerCol = timePerColumn(); newZoomDepth = newZoomDepth > timePerCol ? timePerCol : newZoomDepth; newZoomDepth = newZoomDepth <= 0 ? 1 : newZoomDepth; while (timePerCol % newZoomDepth) { if (depth > qxt_d().m_currentZoomDepth) { newZoomDepth++; if (newZoomDepth >= timePerCol) return; } else { newZoomDepth--; if (newZoomDepth <= 1) return; } } qDebug() << "Zoomed, old zoom depth: " << qxt_d().m_currentZoomDepth << " new zoom depth: " << newZoomDepth; qxt_d().m_currentZoomDepth = newZoomDepth; emit this->newZoomDepth(newZoomDepth); /*reinit the view*/ if (model()) { updateGeometries(); qxt_d().reloadItemsFromModel(); } } /*! * returns the current zoom depth */ int QxtScheduleView::currentZoomDepth(const Qxt::Timeunit unit) { switch (unit) { case Qxt::Second: { return qxt_d().m_currentZoomDepth; } break; case Qxt::Minute: { return qxt_d().m_currentZoomDepth / 60; } break; case Qxt::Hour: { return qxt_d().m_currentZoomDepth / 60 / 60; } break; default: qWarning() << "This Timeunit is not implemented yet you can use Second,Minute,Hour returning seconds"; return qxt_d().m_currentZoomDepth; break; } } /*! * zooms one step in * * \sa zoomOut() setCurrentZoomDepth() setZoomStepWidth() */ void QxtScheduleView::zoomIn() { setCurrentZoomDepth(qxt_d().m_currentZoomDepth - qxt_d().m_zoomStepWidth); } /*! * zooms one step out * * \sa zoomIn() setCurrentZoomDepth() setZoomStepWidth() */ void QxtScheduleView::zoomOut() { setCurrentZoomDepth(qxt_d().m_currentZoomDepth + qxt_d().m_zoomStepWidth); } void QxtScheduleView::paintEvent(QPaintEvent * /*event*/) { if (model()) { /*paint the grid*/ int iNumRows = qxt_d().m_vHeader->count(); qDebug() << "Painting rows " << iNumRows; int xRowEnd = qxt_d().m_hHeader->sectionViewportPosition(qxt_d().m_hHeader->count() - 1) + qxt_d().m_hHeader->sectionSize(qxt_d().m_hHeader->count() - 1); QPainter painter(viewport()); painter.save(); painter.setPen(QColor(220, 220, 220)); bool thinLine; thinLine = false; for (int iLoop = 0; iLoop < iNumRows; iLoop += 2) { painter.drawLine(0 , qxt_d().m_vHeader->sectionViewportPosition(iLoop), xRowEnd, qxt_d().m_vHeader->sectionViewportPosition(iLoop)); } int iNumCols = qxt_d().m_hHeader->count(); int iYColEnd = qxt_d().m_vHeader->sectionViewportPosition(qxt_d().m_vHeader->count() - 1) + qxt_d().m_vHeader->sectionSize(qxt_d().m_vHeader->count() - 1); for (int iLoop = 0; iLoop < iNumCols ; iLoop++) { painter.drawLine(qxt_d().m_hHeader->sectionViewportPosition(iLoop), 0, qxt_d().m_hHeader->sectionViewportPosition(iLoop), iYColEnd); } painter.restore(); QListIterator itemIterator(qxt_d().m_Items); while (itemIterator.hasNext()) { QxtScheduleInternalItem * currItem = itemIterator.next(); QxtStyleOptionScheduleViewItem style; //\BUG use the correct section here or find a way to forbit section resizing style.roundCornersRadius = qxt_d().m_vHeader->sectionSize(1) / 2; style.itemHeaderHeight = qxt_d().m_vHeader->sectionSize(1); style.maxSubItemHeight = qxt_d().m_vHeader->sectionSize(1); if (currItem->isDirty) currItem->m_cachedParts.clear(); style.itemGeometries = currItem->m_geometries; style.itemPaintCache = &currItem->m_cachedParts; style.translate = QPoint(-qxt_d().m_hHeader->offset(), -qxt_d().m_vHeader->offset()); painter.save(); qxt_d().delegate->paint(&painter, style, currItem->modelIndex()); painter.restore(); currItem->setDirty(false); } painter.end(); } } void QxtScheduleView::updateGeometries() { //check if we are already initialized if(!qxt_d().m_Model || !qxt_d().m_vHeader || !qxt_d().m_hHeader) return; this->setViewportMargins(qxt_d().m_vHeader->sizeHint().width() + 1, qxt_d().m_hHeader->sizeHint().height() + 1, 0, 0); verticalScrollBar()->setRange(0, qxt_d().m_vHeader->count()*qxt_d().m_vHeader->defaultSectionSize() - viewport()->height()); verticalScrollBar()->setSingleStep(qxt_d().m_vHeader->defaultSectionSize()); verticalScrollBar()->setPageStep(qxt_d().m_vHeader->defaultSectionSize()); int left = 2; int top = qxt_d().m_hHeader->sizeHint().height() + 2; int width = qxt_d().m_vHeader->sizeHint().width(); int height = viewport()->height(); qxt_d().m_vHeader->setGeometry(left, top, width, height); left = left + width; top = 1; width = viewport()->width(); height = qxt_d().m_hHeader->sizeHint().height(); qxt_d().m_hHeader->setGeometry(left, top, width, height); qxt_d().m_hHeader->setDefaultSectionSize(viewport()->width() / 5); for (int iLoop = 0; iLoop < qxt_d().m_hHeader->count(); iLoop++) qxt_d().m_hHeader->resizeSection(iLoop, viewport()->width() / 5); qxt_d().m_hHeader->setResizeMode(QHeaderView::Fixed); horizontalScrollBar()->setRange(0, (qxt_d().m_hHeader->count() * qxt_d().m_hHeader->defaultSectionSize() - viewport()->width())); horizontalScrollBar()->setSingleStep(qxt_d().m_hHeader->defaultSectionSize()); horizontalScrollBar()->setPageStep(qxt_d().m_hHeader->defaultSectionSize()); qxt_d().m_vHeader->show(); qxt_d().m_hHeader->show(); qxt_d().handleItemConcurrency(0, this->rows() * this->cols() - 1); viewport()->update(); } void QxtScheduleView::scrollContentsBy(int dx, int dy) { qxt_d().m_vHeader->setOffset(qxt_d().m_vHeader->offset() - dy); qxt_d().m_hHeader->setOffset(qxt_d().m_hHeader->offset() - dx); QAbstractScrollArea::scrollContentsBy(dx, dy); } void QxtScheduleView::mouseMoveEvent(QMouseEvent * e) { if (qxt_d().m_selectedItem) { int currentMousePosTableOffset = qxt_d().pointToOffset((e->pos())); if (currentMousePosTableOffset != qxt_d().m_lastMousePosOffset) { if (currentMousePosTableOffset >= 0) { /*i cannot use the model data here because all changes are committed to the model only when the move ends*/ int startTableOffset = qxt_d().m_selectedItem->visualStartTableOffset(); int endTableOffset = -1; /*i simply use the shape to check if we have a move or a resize. Because we enter this codepath the shape gets not changed*/ if (this->viewport()->cursor().shape() == Qt::SizeVerCursor) { QVector geo = qxt_d().m_selectedItem->geometry(); QRect rect = geo[geo.size()-1]; endTableOffset = currentMousePosTableOffset; } else { /*well the duration is the same for a move*/ //qint32 difference = qxt_d().rowsTo(qxt_d().m_lastMousePosIndex,currentMousePos); // tableCellToUnixTime(currentMousePos) - tableCellToUnixTime(this->m_lastMousePosIndex); int difference = currentMousePosTableOffset - qxt_d().m_lastMousePosOffset; //qDebug()<<"Difference Rows: "<rows() - 1; } if (startTableOffset >= 0 && endTableOffset >= startTableOffset && endTableOffset < (rows()*cols())) { QVector< QRect > newGeometry = qxt_d().calculateRangeGeometries(startTableOffset, endTableOffset); int oldStartOffset = qxt_d().m_selectedItem->visualStartTableOffset(); int newStartOffset = qxt_d().m_selectedItem->visualEndTableOffset(); qxt_d().m_selectedItem->setGeometry(newGeometry); qxt_d().m_selectedItem->setDirty(); qxt_d().m_lastMousePosOffset = currentMousePosTableOffset; #if 1 if (newGeometry.size() > 0) { int start = qxt_d().m_selectedItem->visualStartTableOffset(); int end = qxt_d().m_selectedItem->visualEndTableOffset(); qxt_d().handleItemConcurrency(oldStartOffset, newStartOffset); qxt_d().handleItemConcurrency(start, end); } #endif } } } return; } else { /*change the cursor to show the resize arrow*/ QPoint translatedPos = mapFromViewport(e->pos()); QxtScheduleInternalItem * it = qxt_d().internalItemAt(translatedPos); if (it) { QVector geo = it->geometry(); QRect rect = geo[geo.size()-1]; if (rect.contains(translatedPos) && (translatedPos.y() >= rect.bottom() - 5 && translatedPos.y() <= rect.bottom())) { this->viewport()->setCursor(Qt::SizeVerCursor); return; } } if (this->viewport()->cursor().shape() != Qt::ArrowCursor) this->viewport()->setCursor(Qt::ArrowCursor); } } void QxtScheduleView::mouseDoubleClickEvent ( QMouseEvent * e ) { qxt_d().m_currentItem = qxt_d().internalItemAt(mapFromViewport(e->pos())); if (qxt_d().m_currentItem) { emit indexDoubleClicked(qxt_d().m_currentItem->modelIndex()); } } void QxtScheduleView::mousePressEvent(QMouseEvent * e) { qxt_d().m_currentItem = qxt_d().internalItemAt(mapFromViewport(e->pos())); if (qxt_d().m_currentItem) { emit indexSelected(qxt_d().m_currentItem->modelIndex()); } else emit indexSelected(QModelIndex()); if (e->button() == Qt::RightButton) { if (qxt_d().m_currentItem) emit contextMenuRequested(qxt_d().m_currentItem->modelIndex()); } else { qxt_d().m_lastMousePosOffset = qxt_d().pointToOffset(e->pos()); if (qxt_d().m_lastMousePosOffset >= 0) { qxt_d().m_selectedItem = qxt_d().m_currentItem; if (qxt_d().m_selectedItem) { qDebug() << "Selected Item:" << qxt_d().m_selectedItem->m_iModelRow; raiseItem(qxt_d().m_selectedItem->modelIndex()); qxt_d().m_selectedItem->startMove(); qxt_d().scrollTimer.start(100); } else qxt_d().m_lastMousePosOffset = -1; } } } void QxtScheduleView::mouseReleaseEvent(QMouseEvent * /*e*/) { qxt_d().scrollTimer.stop(); if (qxt_d().m_selectedItem) { int oldStartTableOffset = qxt_d().m_selectedItem->startTableOffset(); int oldEndTableOffset = oldStartTableOffset + qxt_d().m_selectedItem->rows() - 1 ; QVector geo = qxt_d().m_selectedItem->geometry(); QRect rect = geo[geo.size()-1]; int newStartTableOffset = qxt_d().m_selectedItem->visualStartTableOffset(); int newEndTableOffset = qxt_d().m_selectedItem->visualEndTableOffset(); qxt_d().m_selectedItem->stopMove(); QVariant newStartUnixTime; QVariant newDuration; newStartUnixTime = qxt_d().offsetToUnixTime(newStartTableOffset); model()->setData(qxt_d().m_selectedItem->modelIndex(), newStartUnixTime, Qxt::ItemStartTimeRole); newDuration = qxt_d().offsetToUnixTime(newEndTableOffset, true) - newStartUnixTime.toInt(); model()->setData(qxt_d().m_selectedItem->modelIndex(), newDuration, Qxt::ItemDurationRole); qxt_d().m_selectedItem = NULL; qxt_d().m_lastMousePosOffset = -1; /*only call for the old geometry the dataChanged slot will call it for the new position*/ qxt_d().handleItemConcurrency(oldStartTableOffset, oldEndTableOffset); //qxt_d().handleItemConcurrency(newStartIndex,newEndIndex); //viewport()->update(); } } void QxtScheduleView::wheelEvent(QWheelEvent * e) { /*time scrolling when pressing ctrl while using the mouse wheel*/ if (e->modifiers() & Qt::ControlModifier) { if (e->delta() < 0) zoomOut(); else zoomIn(); } else QAbstractScrollArea::wheelEvent(e); } /*! * returns the current row count of the view */ int QxtScheduleView::rows() const { if (!model()) return 0; int timePerCol = timePerColumn(); Q_ASSERT(timePerCol % qxt_d().m_currentZoomDepth == 0); int iNeededRows = timePerCol / qxt_d().m_currentZoomDepth; return iNeededRows; } /*! * returns the current column count of the view */ int QxtScheduleView::cols() const { if (!model()) return 0; int cols = 0; int timeToShow = qxt_d().m_endUnixTime - qxt_d().m_startUnixTime + 1 ; int timePerCol = timePerColumn(); Q_ASSERT(timeToShow % timePerCol == 0); cols = (timeToShow / timePerCol); return cols; } /*! * reimplement this to support custom view modes *Returns the time per column in seconds */ int QxtScheduleView::timePerColumn() const { int timePerColumn = 0; switch (qxt_d().m_currentViewMode) { case DayView: timePerColumn = 24 * 60 * 60; break; case HourView: timePerColumn = 60 * 60; break; case MinuteView: timePerColumn = 60; break; default: Q_ASSERT(false); } return timePerColumn; } /*! * reimplement this to support custom view modes * This function has to adjust the given start and end time to the current view mode: * For example, the DayMode always adjust to time 0:00:00am for startTime and 11:59:59pm for endTime */ void QxtScheduleView::adjustRangeToViewMode(QDateTime *startTime, QDateTime *endTime) const { switch (qxt_d().m_currentViewMode) { case DayView: startTime->setTime(QTime(0, 0)); endTime ->setTime(QTime(23, 59, 59)); break; case HourView: startTime->setTime(QTime(startTime->time().hour(), 0)); endTime ->setTime(QTime(endTime->time().hour(), 59, 59)); break; case MinuteView: startTime->setTime(QTime(startTime->time().hour(), startTime->time().minute(), 0)); endTime ->setTime(QTime(endTime->time().hour(), endTime->time().minute(), 59)); break; default: Q_ASSERT(false); } } QPoint QxtScheduleView::mapFromViewport(const QPoint & point) const { return point + QPoint(qxt_d().m_hHeader->offset(), qxt_d().m_vHeader->offset()); } QPoint QxtScheduleView::mapToViewport(const QPoint & point) const { return point - QPoint(qxt_d().m_hHeader->offset(), qxt_d().m_vHeader->offset()); } /*! * raises the item belonging to index */ void QxtScheduleView::raiseItem(const QModelIndex &index) { QxtScheduleInternalItem *item = qxt_d().itemForModelIndex(index); if (item) { int iItemIndex = -1; if ((iItemIndex = qxt_d().m_Items.indexOf(item)) >= 0) { qxt_d().m_Items.takeAt(iItemIndex); qxt_d().m_Items.append(item); viewport()->update(); } } } void QxtScheduleView::dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight) { for (int iLoop = topLeft.row(); iLoop <= bottomRight.row();iLoop++) { QModelIndex index = model()->index(iLoop, 0); QxtScheduleInternalItem * item = qxt_d().itemForModelIndex(index); if (item) { int startOffset = item->startTableOffset(); int endIndex = item->startTableOffset() + item->rows() - 1; if (item->m_geometries.count() > 0) { int oldStartOffset = qxt_d().pointToOffset(mapToViewport(item->m_geometries[0].topLeft())); int oldEndOffset = qxt_d().pointToOffset(mapToViewport(item->m_geometries[item->m_geometries.size()-1].bottomRight())); qxt_d().handleItemConcurrency(oldStartOffset, oldEndOffset); } /*that maybe will set a empty geometry thats okay because the item maybe out of bounds of the view */ item->setGeometry(qxt_d().calculateRangeGeometries(startOffset, endIndex)); /*force item cache update even if the geometry is the same*/ item->setDirty(); qxt_d().handleItemConcurrency(startOffset, endIndex); viewport()->update(); } } } /*! * triggers the view to relayout the items that are concurrent to index */ void QxtScheduleView::handleItemConcurrency(const QModelIndex &index) { QxtScheduleInternalItem *item = qxt_d().itemForModelIndex(index); if (item) qxt_d().handleItemConcurrency(item); } void QxtScheduleView::resizeEvent(QResizeEvent * /* e*/) { updateGeometries(); } void QxtScheduleView::rowsRemoved(const QModelIndex & parent, int start, int end) { /*! *\FIXME write correct code here */ return qxt_d().reloadItemsFromModel(); /*for now we care only about toplevel items*/ if (!parent.isValid()) { for (int iLoop = 0; iLoop < qxt_d().m_Items.count();iLoop++) { QxtScheduleInternalItem *item = qxt_d().m_Items.at(iLoop); if (item) { if (item->m_iModelRow >= start && item->m_iModelRow <= end) { qxt_d().m_Items.takeAt(iLoop); if (item == qxt_d().m_currentItem) { qxt_d().m_currentItem = 0; emit indexSelected(QModelIndex()); } delete item; continue; } if (item->m_iModelRow > end) { int iDifference = end - start + 1; item->m_iModelRow -= iDifference; } } } } } void QxtScheduleView::rowsInserted(const QModelIndex & parent, int start, int end) { /*for now we care only about toplevel items*/ if (!parent.isValid()) { for (int iLoop = start; iLoop <= end;iLoop++) { /*now create the items*/ QxtScheduleInternalItem *currentItem = new QxtScheduleInternalItem(this, model()->index(iLoop, 0)); qxt_d().m_Items.append(currentItem); connect(currentItem, SIGNAL(geometryChanged(QxtScheduleInternalItem*, QVector)), &qxt_d(), SLOT(itemGeometryChanged(QxtScheduleInternalItem * , QVector< QRect >))); qxt_d().handleItemConcurrency(currentItem); } } viewport()->update(); } void QxtScheduleView::rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end) { Q_UNUSED(parent); Q_UNUSED(start); Q_UNUSED(end); /*for now we care only about toplevel items*/ return; } void QxtScheduleView::rowsAboutToBeInserted(const QModelIndex & parent, int start, int end) { /*for now we care only about toplevel items*/ if (!parent.isValid()) { int iDifference = end - start; for (int iLoop = 0; iLoop < qxt_d().m_Items.count();iLoop++) { QxtScheduleInternalItem * item = qxt_d().m_Items[iLoop]; if (item) if (item->m_iModelRow >= start && item->m_iModelRow < model()->rowCount()) item->m_iModelRow += iDifference + 1; } } } /*! * returns the current selected index */ QModelIndex QxtScheduleView::currentIndex() { QModelIndex currIndex; if (qxt_d().m_currentItem) currIndex = qxt_d().m_currentItem->modelIndex(); return currIndex; } /*! * sets the timerange * This function will set a Timerange from fromDate 00:00am to toDate 23:59pm */ void QxtScheduleView::setDateRange(const QDate & fromDate, const QDate & toDate) { Q_UNUSED(fromDate); Q_UNUSED(toDate); QDateTime startTime = QDateTime(fromDate, QTime(0, 0, 0)); QDateTime endTime = QDateTime(toDate, QTime(23, 59, 59)); setTimeRange(startTime, endTime); } /*! * sets the timerange * This function will set the passed timerange, but may adjust it to the current viewmode. * e.g You cannot start at 1:30am in a DayMode, this gets adjusted to 00:00am */ void QxtScheduleView::setTimeRange(const QDateTime & fromDateTime, const QDateTime & toDateTime) { QDateTime startTime = fromDateTime; QDateTime endTime = toDateTime; //adjust the timeranges to fit in the view adjustRangeToViewMode(&startTime, &endTime); qxt_d().m_startUnixTime = startTime.toTime_t(); qxt_d().m_endUnixTime = endTime.toTime_t(); } libqxt-0.6.2/src/gui/qxtscheduleview.h000066400000000000000000000126561215241066400200050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSCHEDULEVIEW_H_INCLUDED #define QXTSCHEDULEVIEW_H_INCLUDED #include #include #include #include #include #include #include "qxtglobal.h" #include "qxtnamespace.h" QT_FORWARD_DECLARE_CLASS(QAbstractItemModel) class QxtScheduleItemDelegate; class QxtScheduleViewPrivate; class QxtScheduleInternalItem; #if 0 enum { TIMERANGEPERCOL = 86400, TIMESTEP = 900 }; #endif class QXT_GUI_EXPORT QxtScheduleView : public QAbstractScrollArea { Q_OBJECT QXT_DECLARE_PRIVATE(QxtScheduleView) friend class QxtScheduleInternalItem; friend class QxtScheduleViewHeaderModel; public: enum ViewMode { MinuteView, HourView, DayView, CustomView }; QxtScheduleView(QWidget *parent = 0); void setModel(QAbstractItemModel *model); QAbstractItemModel* model() const; void setViewMode(const QxtScheduleView::ViewMode mode); QxtScheduleView::ViewMode viewMode() const; QHeaderView* verticalHeader ( ) const; QHeaderView* horizontalHeader ( ) const; void setDateRange(const QDate & fromDate , const QDate & toDate); void setTimeRange(const QDateTime &fromDateTime , const QDateTime &toTime); QxtScheduleItemDelegate* delegate () const; void setItemDelegate (QxtScheduleItemDelegate * delegate); void setZoomStepWidth(const int zoomWidth , const Qxt::Timeunit unit = Qxt::Second); void setCurrentZoomDepth(const int depth , const Qxt::Timeunit unit = Qxt::Second); int currentZoomDepth(const Qxt::Timeunit unit = Qxt::Second); QPoint mapFromViewport(const QPoint& point) const; QPoint mapToViewport(const QPoint& point) const; QModelIndex indexAt(const QPoint &pt); void raiseItem(const QModelIndex &index); void handleItemConcurrency(const QModelIndex &index); QModelIndex currentIndex(); int rows() const; int cols() const; Q_SIGNALS: void itemMoved(int rows, int cols, QModelIndex index); void indexSelected(QModelIndex index); void indexDoubleClicked(QModelIndex index); void contextMenuRequested(QModelIndex index); void newZoomDepth(const int newDepthInSeconds); void viewModeChanged(const int newViewMode); protected: virtual int timePerColumn() const; virtual void adjustRangeToViewMode(QDateTime *startTime, QDateTime *endTime) const; virtual void scrollContentsBy(int dx, int dy); virtual void paintEvent(QPaintEvent *e); virtual void mouseMoveEvent(QMouseEvent * e); virtual void mousePressEvent(QMouseEvent * e); virtual void mouseReleaseEvent(QMouseEvent * e); virtual void mouseDoubleClickEvent ( QMouseEvent * e ); virtual void resizeEvent(QResizeEvent * e); virtual void wheelEvent(QWheelEvent * e); public Q_SLOTS: void dataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight); void updateGeometries(); void zoomIn(); void zoomOut(); protected Q_SLOTS: virtual void rowsAboutToBeRemoved(const QModelIndex & parent, int start, int end); virtual void rowsAboutToBeInserted(const QModelIndex & parent, int start, int end); virtual void rowsRemoved(const QModelIndex & parent, int start, int end); virtual void rowsInserted(const QModelIndex & parent, int start, int end); }; #endif //QXTSCHEDULEVIEW_H_INCLUDED libqxt-0.6.2/src/gui/qxtscheduleview_p.cpp000066400000000000000000000636621215241066400206620ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtscheduleview_p.h" #include "qxtscheduleview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "qxtscheduleheaderwidget.h" /*-------------------------------------start private functions-------------------------------------------------------*/ int QxtScheduleViewPrivate::offsetToVisualColumn(const int iOffset) const { if (iOffset >= 0) return iOffset / qxt_p().rows(); return -1; } int QxtScheduleViewPrivate::visualIndexToOffset(const int iRow, const int iCol) const { return (iCol* qxt_p().rows()) + iRow; } int QxtScheduleViewPrivate::offsetToVisualRow(const int iOffset) const { if (iOffset >= 0 && qxt_p().model()) return iOffset % qxt_p().rows(); return -1; } QVector< QRect > QxtScheduleViewPrivate::calculateRangeGeometries(const int iStartOffset, const int iEndOffset) const { QVector rects; if (iStartOffset < 0 || iEndOffset < 0) return rects; if (iEndOffset < iStartOffset) return rects; int iCurrentStartOffset = iStartOffset; int iCurrentEndOffset; do { if (offsetToVisualColumn(iCurrentStartOffset) == offsetToVisualColumn(iEndOffset)) iCurrentEndOffset = iEndOffset; else iCurrentEndOffset = visualIndexToOffset(m_vHeader->count() - 1, offsetToVisualColumn(iCurrentStartOffset)); qint32 iLeft = m_hHeader->sectionPosition(offsetToVisualColumn(iCurrentStartOffset)); qint32 iTop = m_vHeader->sectionPosition(offsetToVisualRow(iCurrentStartOffset)); qint32 iBottom = m_vHeader->sectionPosition(offsetToVisualRow(iCurrentEndOffset)) + m_vHeader->sectionSize(offsetToVisualRow(iCurrentEndOffset)); qint32 iRight = m_hHeader->sectionPosition(offsetToVisualColumn(iCurrentEndOffset)) + m_hHeader->sectionSize(offsetToVisualColumn(iCurrentEndOffset)); rects.append(QRect(iLeft + 1, iTop + 1, iRight - iLeft - 1, iBottom - iTop - 1)); iCurrentStartOffset = visualIndexToOffset(0, offsetToVisualColumn(iCurrentEndOffset) + 1); } while (iCurrentEndOffset < iEndOffset); return rects; } int QxtScheduleViewPrivate::pointToOffset(const QPoint & point) { int iRow = m_vHeader->visualIndexAt(point.y()); int iCol = m_hHeader->visualIndexAt(point.x()); return visualIndexToOffset(iRow, iCol); } QxtScheduleInternalItem * QxtScheduleViewPrivate::internalItemAt(const QPoint & pt) { QListIteratoriterator(m_Items); QxtScheduleInternalItem *currentItem; iterator.toBack(); while (iterator.hasPrevious()) { currentItem = iterator.previous(); if (currentItem->contains(pt)) return currentItem; } return 0; } void QxtScheduleViewPrivate::reloadItemsFromModel() { qDeleteAll(m_Items.begin(), m_Items.end()); m_Items.clear(); m_selectedItem = NULL; int iNumItems = qxt_p().model()->rowCount(); //delete all old stuff here QxtScheduleInternalItem *currentItem; for (int iLoop = 0; iLoop < iNumItems; iLoop++) { currentItem = new QxtScheduleInternalItem(&qxt_p(), qxt_p().model()->index(iLoop, 0)); m_Items.append(currentItem); connect(currentItem, SIGNAL(geometryChanged(QxtScheduleInternalItem*, QVector)), this, SLOT(itemGeometryChanged(QxtScheduleInternalItem * , QVector< QRect >))); } handleItemConcurrency(0, (qxt_p().rows()*qxt_p().cols()) - 1); } void QxtScheduleViewPrivate::init() { if (qxt_p().model()) { qxt_p().viewport()->setMouseTracking(true); if (!m_vHeader) { m_vHeader = new QxtScheduleHeaderWidget(Qt::Vertical, &qxt_p()); connect(m_vHeader, SIGNAL(geometriesChanged()), &qxt_p(), SLOT(updateGeometries())); } m_vHeader->show(); if (!m_hHeader) { m_hHeader = new QxtScheduleHeaderWidget(Qt::Horizontal, &qxt_p()); connect(m_hHeader, SIGNAL(geometriesChanged()), &qxt_p(), SLOT(updateGeometries())); } m_hHeader->show(); /*here we also initialize the items*/ m_vHeader->setDefaultSectionSize(20); m_vHeader->setResizeMode(QHeaderView::Fixed); reloadItemsFromModel(); } qxt_p().updateGeometries(); } /*! * @desc collects groups of concurrent items in the offset range */ QList< QLinkedList > QxtScheduleViewPrivate::findConcurrentItems(const int from, const int to) const { QList< QLinkedList > allConcurrentItems; QList allItemsSorted = m_Items; if(m_Items.size() == 0) return allConcurrentItems; qSort(allItemsSorted.begin(), allItemsSorted.end(), qxtScheduleItemLessThan); int startItem = 0; int endItem = allItemsSorted.size() - 1; //find the startitem that interferes with our range for (int i = 0; i < allItemsSorted.size(); i++) { if (i > 0) { if (!(allItemsSorted.at(i - 1)->visualEndTableOffset() >= allItemsSorted.at(i)->visualStartTableOffset() && allItemsSorted.at(i - 1)->visualStartTableOffset() <= allItemsSorted.at(i)->visualEndTableOffset())) startItem = i; } if (allItemsSorted.at(i)->visualEndTableOffset() >= from && allItemsSorted.at(i)->visualStartTableOffset() <= to) break; } //find the last item that interferes with our range for (int i = allItemsSorted.size() - 1; i >= 0 ; i--) { if (i < allItemsSorted.size() - 1) { if (!(allItemsSorted.at(i + 1)->visualEndTableOffset() >= allItemsSorted.at(i)->visualStartTableOffset() && allItemsSorted.at(i + 1)->visualStartTableOffset() <= allItemsSorted.at(i)->visualEndTableOffset())) endItem = i; } if (allItemsSorted.at(i)->visualEndTableOffset() >= from && allItemsSorted.at(i)->visualStartTableOffset() <= to) break; } int startOffset = allItemsSorted.at(startItem)->visualStartTableOffset(); int endOffset = allItemsSorted.at(endItem)->visualEndTableOffset(); /*now we have to populate a list with all items that interfere with our range */ QLinkedList concurrentItems; for (int iAllItemLoop = startItem; iAllItemLoop <= endItem; iAllItemLoop++) { int tempStartOffset = allItemsSorted.at(iAllItemLoop)->visualStartTableOffset(); int tempEndOffset = allItemsSorted.at(iAllItemLoop)->visualEndTableOffset(); if (tempEndOffset >= startOffset && tempStartOffset <= endOffset) { if (concurrentItems.size() >= 1) { bool bAppend = false; /*check all items in the list if the current items interfers although the items are ordered by startIndex *we can loose some of them if the endTime of the last Item is before the endTime of the pre last item */ for (QLinkedList::iterator it = concurrentItems.begin(); it != concurrentItems.end(); ++it) { int lastStartOffset = (*it)->visualStartTableOffset(); int lastEndOffset = (*it)->visualEndTableOffset(); if (tempEndOffset >= lastStartOffset && tempStartOffset <= lastEndOffset) { bAppend = true; break; } } if (bAppend) { concurrentItems.append(allItemsSorted.at(iAllItemLoop)); } else { allConcurrentItems.append(concurrentItems); concurrentItems.clear(); concurrentItems.append(allItemsSorted.at(iAllItemLoop)); } } else concurrentItems.append(allItemsSorted.at(iAllItemLoop)); if (tempStartOffset < startOffset) startOffset = tempStartOffset; if (tempEndOffset > endOffset) endOffset = tempEndOffset; } } if (concurrentItems.size() > 0) allConcurrentItems.append(concurrentItems); return allConcurrentItems; } void QxtScheduleViewPrivate::handleItemConcurrency(const int from, const int to) { /*collect all items that interfere only in that range*/ if (from < 0 || to < 0 || m_Items.size() == 0){ //do a update or we may have artifacts qxt_p().viewport()->update(); return; } qDebug() << "handleItemConcurrency"; if (handlesConcurrency) return; handlesConcurrency = true; QList< QLinkedList > allConcurrentItems = findConcurrentItems(from, to); /*thx to ahigerd for suggesting that algorithm*/ //[16:24] Start with the first event. Put it in a list. //[16:25] Iterate until you find an event that doesn't overlap with the first event. Put it in the list. Repeat until you've reached the last event. //[16:25] This fills the left column optimally. //[16:25] Repeat the algorithm for the second column, etc., until there aren't any events left that don't have a column. //[16:27] This algorithm is O(n*m), where n is the number of events and m is the maximum number of overlapping events. QList< QList< QxtScheduleInternalItem *> >virtualTable; for (int iListLoop = 0; iListLoop < allConcurrentItems.size(); iListLoop++) { QLinkedList & currentItems = allConcurrentItems[iListLoop]; QList< QxtScheduleInternalItem * > currentColumn; qDebug() << "handle overlapping for " << currentItems.size() << " Items"; virtualTable.clear(); //we iterate over the currect collection and remove every item that can be placed in the current column //when the collection is empty we are done while (currentItems.size()) { QMutableLinkedListIterator< QxtScheduleInternalItem * > iter(currentItems); while (iter.hasNext()) { iter.next(); //initialize the current column if (currentColumn.isEmpty() || currentColumn[currentColumn.size()-1]->visualEndTableOffset() < iter.value()->visualStartTableOffset()) { currentColumn.append(iter.value()); iter.remove(); continue; } } if (!currentColumn.isEmpty()) { virtualTable.append(currentColumn); currentColumn.clear(); } } qDebug() << "Found columns" << virtualTable.size(); //this code part resizes the item geometries for (int col = 0; col < virtualTable.size(); col++) { for (int item = 0; item < virtualTable.at(col).size() ; item++) { int startVisualCol = offsetToVisualColumn(virtualTable[col][item]->visualStartTableOffset()); QVector geo = virtualTable[col][item]->geometry(); for (int rect = 0; rect < geo.size(); rect++) { int sectionStart = m_hHeader->sectionPosition(startVisualCol); int fullWidth = m_hHeader->sectionSize(startVisualCol); int oneItemWidth = fullWidth / virtualTable.size(); int itemWidth = oneItemWidth; int itemXStart = (col * oneItemWidth) + sectionStart; int overlap = oneItemWidth / 10; int adjustX1 = 0; int adjustX2 = 0; //this is very expensive.I try to check if my item can span over more than one col int possibleCols = 1; bool foundCollision; for (int tmpCol = col + 1; tmpCol < virtualTable.size(); tmpCol++) { foundCollision = false; for (int tmpItem = 0; tmpItem < virtualTable.at(tmpCol).size() ; tmpItem++) { if ((virtualTable[tmpCol][tmpItem]->visualEndTableOffset() >= virtualTable[col][item]->visualStartTableOffset() && virtualTable[tmpCol][tmpItem]->visualStartTableOffset() <= virtualTable[col][item]->visualEndTableOffset())) { foundCollision = true; break; } } if (!foundCollision) possibleCols++; else break; } //now lets adjust the size to get a nice overlapping of items if (virtualTable.size() > 1) { if (col == 0) adjustX2 = overlap; else if (col == virtualTable.size() - 1) { adjustX1 = -overlap; adjustX2 = overlap; } else { if (col + possibleCols == virtualTable.size()) adjustX2 = overlap; else adjustX2 = overlap * 2; adjustX1 = -overlap; } } // possibleCols = 1; itemWidth = oneItemWidth * possibleCols; qDebug() << "orginial rect" << geo[rect]; geo[rect].setLeft(itemXStart + adjustX1); geo[rect].setWidth(itemWidth + adjustX2); qDebug() << "new rect" << geo[rect]; startVisualCol++; } virtualTable[col][item]->setGeometry(geo); } } } handlesConcurrency = false; qxt_p().viewport()->update(); } QxtScheduleViewPrivate::QxtScheduleViewPrivate() { m_Cols = 0; m_vHeader = 0; m_hHeader = 0; m_Model = 0; m_selectedItem = 0; handlesConcurrency = false; delegate = 0; m_zoomStepWidth = 0; connect(&scrollTimer, SIGNAL(timeout()), this, SLOT(scrollTimerTimeout())); } void QxtScheduleViewPrivate::itemGeometryChanged(QxtScheduleInternalItem * item, QVector< QRect > oldGeometry) { QRegion oldRegion; if (item->geometry() == oldGeometry) return; QVectorIterator iter(oldGeometry); QRect currRect; while (iter.hasNext()) { currRect = iter.next(); currRect.adjust(-1, -1, 2, 2); oldRegion += currRect; } //viewport()->update(oldRegion); QRegion newRegion; QVectorIterator newIter(item->geometry()); while (newIter.hasNext()) { currRect = newIter.next(); currRect.adjust(-1, -1, 2, 2); newRegion += currRect; } //viewport()->update(newRegion); qxt_p().viewport()->update(); } int QxtScheduleViewPrivate::unixTimeToOffset(const uint constUnixTime, bool indexEndTime) const { uint unixTime = constUnixTime; if (unixTime >= m_startUnixTime && unixTime <= m_endUnixTime) { if (indexEndTime) { unixTime -= m_currentZoomDepth; } qint32 rows = qxt_p().rows(); qint32 iOffset = unixTime - m_startUnixTime; //round to the closest boundaries iOffset = qRound((qreal)iOffset / (qreal)m_currentZoomDepth); qint32 iCol = iOffset / rows; qint32 iRow = iOffset % rows; return visualIndexToOffset(iRow, iCol); } //virtual void handleItemOverlapping(QxtScheduleInternalItem *item); return -1; } void QxtScheduleViewPrivate::scrollTimerTimeout() { QPoint globalPos = QCursor::pos(); QPoint viewportPos = qxt_p().viewport()->mapFromGlobal(globalPos); int iScrollVertical = this->m_vHeader->defaultSectionSize(); int iScrollHorizontal = this->m_hHeader->defaultSectionSize(); if (viewportPos.y() <= iScrollVertical) { int iCurrPos = qxt_p().verticalScrollBar()->value(); if (iCurrPos > qxt_p().verticalScrollBar()->minimum() + iScrollVertical) { qxt_p().verticalScrollBar()->setValue(iCurrPos - iScrollVertical); } else qxt_p().verticalScrollBar()->setValue(qxt_p().verticalScrollBar()->minimum()); } else if (viewportPos.y() >= qxt_p().viewport()->height() - iScrollVertical) { int iCurrPos = qxt_p().verticalScrollBar()->value(); if (iCurrPos < qxt_p().verticalScrollBar()->maximum() - iScrollVertical) { qxt_p().verticalScrollBar()->setValue(iCurrPos + iScrollVertical); } else qxt_p().verticalScrollBar()->setValue(qxt_p().verticalScrollBar()->maximum()); } if (viewportPos.x() <= iScrollHorizontal / 2) { int iCurrPos = qxt_p().horizontalScrollBar()->value(); if (iCurrPos > qxt_p().horizontalScrollBar()->minimum() + iScrollHorizontal) { qxt_p().horizontalScrollBar()->setValue(iCurrPos - iScrollHorizontal); } else qxt_p().horizontalScrollBar()->setValue(qxt_p().horizontalScrollBar()->minimum()); } else if (viewportPos.x() >= qxt_p().viewport()->width() - (iScrollHorizontal / 2)) { int iCurrPos = qxt_p().horizontalScrollBar()->value(); if (iCurrPos < qxt_p().horizontalScrollBar()->maximum() - iScrollHorizontal) { qxt_p().horizontalScrollBar()->setValue(iCurrPos + iScrollHorizontal); } else qxt_p().horizontalScrollBar()->setValue(qxt_p().horizontalScrollBar()->maximum()); } } int QxtScheduleViewPrivate::offsetToUnixTime(const int offset, bool indexEndTime) const { qint32 rows = qxt_p().rows(); uint unixTime = (offsetToVisualRow(offset) + (offsetToVisualColumn(offset) * rows)) * m_currentZoomDepth; unixTime += m_startUnixTime; if (indexEndTime) { unixTime += m_currentZoomDepth; } if (unixTime >= m_startUnixTime && unixTime <= m_endUnixTime + 1) return unixTime; return -1; } QxtScheduleInternalItem::QxtScheduleInternalItem(QxtScheduleView *parent, QModelIndex index, QVector geometries) : QObject(parent), m_iModelRow(index.row()), m_geometries(geometries) { m_moving = false; if (parent) { if (index.isValid()) { if (m_geometries.empty()) { int startOffset = this->startTableOffset(); int endOffset = startOffset + this->rows() - 1; m_geometries = parent->qxt_d().calculateRangeGeometries(startOffset, endOffset); } } } } QxtScheduleView * QxtScheduleInternalItem::parentView() const { return qobject_cast(parent()); } /*! * @desc returns the currently VISUAL offset (changes when a item moves) */ int QxtScheduleInternalItem::visualStartTableOffset() const { if (m_geometries.size() == 0 || !parentView()) return -1; //are we in a move? if (!m_moving) return startTableOffset(); int offset = parentView()->qxt_d().pointToOffset(parentView()->mapToViewport((this->geometry()[0].topLeft()))); return offset; } /*! * @desc returns the currently VISUAL offset (changes when a item moves) */ int QxtScheduleInternalItem::visualEndTableOffset() const { if (m_geometries.size() == 0 || !parentView()) return -1; //are we in a move? if (!m_moving) return endTableOffset(); QRect rect = m_geometries[m_geometries.size()-1]; int endTableOffset = parentView()->qxt_d().pointToOffset(parentView()->mapToViewport(rect.bottomRight())); return endTableOffset; } bool QxtScheduleInternalItem::setData(QVariant data, int role) { if (parentView() && parentView()->model()) { return parentView()->model()->setData(modelIndex(), data, role); } return false; } QVariant QxtScheduleInternalItem::data(int role) const { if (modelIndex().isValid()) return modelIndex().data(role); return QVariant(); } int QxtScheduleInternalItem::startTableOffset() const { if (parentView() && parentView()->model()) { int startTime = data(Qxt::ItemStartTimeRole).toInt(); int zoomDepth = parentView()->currentZoomDepth(Qxt::Second); qint32 offset = startTime - parentView()->qxt_d().m_startUnixTime; //the start of the current item does not fit in the view //so we have to align it to the nearest boundaries if (offset % zoomDepth) { int lower = offset / zoomDepth * zoomDepth; int upper = lower + zoomDepth; offset = (offset - lower >= upper - offset ? upper : lower); return parentView()->qxt_d().unixTimeToOffset(offset + parentView()->qxt_d().m_startUnixTime); } return parentView()->qxt_d().unixTimeToOffset(startTime); } return -1; } int QxtScheduleInternalItem::endTableOffset() const { return startTableOffset() + rows() - 1; } void QxtScheduleInternalItem::setStartTableOffset(int iOffset) { if (parentView() && parentView()->model()) { setData(parentView()->qxt_d().offsetToUnixTime(iOffset), Qxt::ItemStartTimeRole); } } void QxtScheduleInternalItem::setRowsUsed(int rows) { if (parentView() && parentView()->model()) { int seconds = rows * parentView()->currentZoomDepth(Qxt::Second); setData(seconds, Qxt::ItemDurationRole); } } int QxtScheduleInternalItem::rows() const { if (parentView() && parentView()->model()) { int iNumSecs = data(Qxt::ItemDurationRole).toInt(); int zoomDepth = parentView()->currentZoomDepth(Qxt::Second); //the length of the current item does not fit in the view //so we have to align it to the nearest boundaries if (iNumSecs % zoomDepth) { int lower = iNumSecs / zoomDepth * zoomDepth; int upper = lower + zoomDepth; return (iNumSecs - lower >= upper - iNumSecs ? (upper / zoomDepth) : (lower / zoomDepth)); } return (iNumSecs / zoomDepth); } return -1; } bool qxtScheduleItemLessThan(const QxtScheduleInternalItem * item1, const QxtScheduleInternalItem * item2) { if (item1->visualStartTableOffset() < item2->visualStartTableOffset()) return true; if (item1->visualStartTableOffset() == item2->visualStartTableOffset() && item1->modelIndex().row() < item2->modelIndex().row()) return true; return false; } bool QxtScheduleInternalItem::contains(const QPoint & pt) { QVectorIterator iterator(this->m_geometries); while (iterator.hasNext()) { if (iterator.next().contains(pt)) return true; } return false; } void QxtScheduleInternalItem::setGeometry(const QVector< QRect > geo) { if (!this->parent()) return; QVector oldGeo = this->m_geometries; this->m_geometries.clear(); this->m_geometries = geo; emit geometryChanged(this, oldGeo); } QVector< QRect > QxtScheduleInternalItem::geometry() const { return this->m_geometries; } void QxtScheduleInternalItem::startMove() { //save old geometry before we start to move this->m_SavedGeometries = this->m_geometries; m_moving = true; } void QxtScheduleInternalItem::resetMove() { this->setGeometry(this->m_SavedGeometries); this->m_SavedGeometries.clear(); m_moving = false; } void QxtScheduleInternalItem::stopMove() { this->m_SavedGeometries.clear(); m_moving = false; } QModelIndex QxtScheduleInternalItem::modelIndex() const { QModelIndex indx; if (parentView() && parentView()->model()) { indx = parentView()->model()->index(this->m_iModelRow, 0); } return indx; } libqxt-0.6.2/src/gui/qxtscheduleview_p.h000066400000000000000000000135441215241066400203210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSCHEDULEVIEW_P_INCLUDED #define QXTSCHEDULEVIEW_P_INCLUDED // // W A R N I N G // ------------- // // This file is not part of the Qxt API. It exists for the convenience // of other Qxt classes. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include #include #include #include #include #include #include "qxtnamespace.h" #include "qxtscheduleitemdelegate.h" class QxtScheduleView; class QxtScheduleHeaderWidget; class QxtScheduleInternalItem : public QObject { Q_OBJECT friend class QxtScheduleView; public: QxtScheduleInternalItem(QxtScheduleView *parent , QModelIndex index , QVector geometries = QVector()); bool setData(QVariant data , int role); QVariant data(int role) const; int visualStartTableOffset() const; int visualEndTableOffset() const; int startTableOffset() const; int endTableOffset() const; void setStartTableOffset(int iOffset); int rows() const; void setRowsUsed(int rows); QxtScheduleView* parentView() const; void startMove(); void resetMove(); void stopMove(); bool contains(const QPoint &pt); void setGeometry(const QVector geo); QModelIndex modelIndex() const; void setDirty(bool state = true) { isDirty = state; } QVector geometry() const; Q_SIGNALS: void geometryChanged(QxtScheduleInternalItem * item , QVector oldGeometry); public: bool m_moving; bool isDirty; int m_iModelRow; QVector m_geometries; QVector m_SavedGeometries; QVector m_cachedParts; }; class QxtScheduleViewPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtScheduleView) QxtScheduleViewPrivate(); int offsetToVisualColumn(const int iOffset) const; int offsetToVisualRow(const int iOffset) const; int visualIndexToOffset(const int iRow, const int iCol) const; int unixTimeToOffset(const uint constUnixTime, bool indexEndTime = false) const; int offsetToUnixTime(const int offset, bool indexEndTime = false) const; QVector< QRect > calculateRangeGeometries(const int iStartOffset, const int iEndOffset) const; int pointToOffset(const QPoint & point); void handleItemConcurrency(const int from, const int to); QList< QLinkedList >findConcurrentItems(const int from, const int to) const; QxtScheduleInternalItem *internalItemAt(const QPoint &pt); QxtScheduleInternalItem *internalItemAtModelIndex(const QModelIndex &index); void init(); void reloadItemsFromModel(); QxtScheduleInternalItem * itemForModelIndex(const QModelIndex &index)const { for (int iLoop = 0; iLoop < m_Items.size(); iLoop++) { if (m_Items.at(iLoop)->modelIndex() == index) return m_Items.at(iLoop); } return 0; } void handleItemConcurrency(QxtScheduleInternalItem *item) { if (item) { int startOffset = item->startTableOffset(); int endOffset = startOffset + item->rows() - 1 ; handleItemConcurrency(startOffset, endOffset); } } QxtScheduleInternalItem *m_currentItem; QxtScheduleInternalItem *m_selectedItem; int m_lastMousePosOffset; int m_currentZoomDepth; int m_zoomStepWidth; int m_currentViewMode; uint m_startUnixTime; uint m_endUnixTime; QList m_Items ; QList m_InactiveItems; /*used for items that are not in the range of our view but we need to look if they get updates*/ QTimer scrollTimer; QxtScheduleHeaderWidget *m_vHeader; QxtScheduleHeaderWidget *m_hHeader; int m_Cols; QAbstractItemModel *m_Model; bool handlesConcurrency; QxtScheduleItemDelegate *delegate; QxtScheduleItemDelegate *defaultDelegate; public Q_SLOTS: void itemGeometryChanged(QxtScheduleInternalItem * item, QVector oldGeometry); void scrollTimerTimeout(); }; bool qxtScheduleItemLessThan(const QxtScheduleInternalItem * item1, const QxtScheduleInternalItem * item2); #endif libqxt-0.6.2/src/gui/qxtscheduleviewheadermodel_p.cpp000066400000000000000000000144301215241066400230410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtscheduleviewheadermodel_p.h" #include "qxtscheduleview.h" #include "qxtscheduleview_p.h" #include #include QxtScheduleViewHeaderModel::QxtScheduleViewHeaderModel(QObject *parent) : QAbstractTableModel(parent) , m_rowCountBuffer(0) , m_colCountBuffer(0) { } void QxtScheduleViewHeaderModel::newZoomDepth(const int zoomDepth) { Q_UNUSED(zoomDepth); if (this->m_dataSource) { /* qDebug()<<"old rows "<rows(); beginRemoveRows(QModelIndex(),0,m_rowCountBuffer); m_rowCountBuffer = 0; endRemoveRows(); beginInsertRows(QModelIndex(),0,m_dataSource->rows()); m_rowCountBuffer = m_dataSource->rows(); endInsertRows(); */ m_rowCountBuffer = m_dataSource->rows(); reset(); } } void QxtScheduleViewHeaderModel::viewModeChanged(const int viewMode) { Q_UNUSED(viewMode); if (this->m_dataSource) { beginRemoveRows(QModelIndex(), 0, m_rowCountBuffer); m_rowCountBuffer = 0; endRemoveRows(); beginInsertRows(QModelIndex(), 0, m_dataSource->rows()); m_rowCountBuffer = m_dataSource->rows(); endInsertRows(); beginRemoveColumns(QModelIndex(), 0, m_colCountBuffer); m_colCountBuffer = 0; endRemoveColumns(); beginInsertColumns(QModelIndex(), 0, m_dataSource->cols()); m_colCountBuffer = m_dataSource->cols(); endInsertColumns(); } } void QxtScheduleViewHeaderModel::setDataSource(QxtScheduleView *dataSource) { if (this->m_dataSource) { disconnect(m_dataSource, SIGNAL(newZoomDepth(const int)), this, SLOT(newZoomDepth(const int))); disconnect(m_dataSource, SIGNAL(viewModeChanged(const int)), this, SLOT(viewModeChanged(const int))); emit beginRemoveRows(QModelIndex(), 0, m_rowCountBuffer); m_rowCountBuffer = 0; emit endRemoveRows(); emit beginRemoveColumns(QModelIndex(), 0, m_colCountBuffer); m_colCountBuffer = 0; emit endRemoveColumns(); } if (dataSource) { connect(dataSource, SIGNAL(newZoomDepth(const int)), this, SLOT(newZoomDepth(const int))); connect(dataSource, SIGNAL(viewModeChanged(const int)), this, SLOT(viewModeChanged(const int))); emit beginInsertRows(QModelIndex(), 0, dataSource->rows()); m_rowCountBuffer = dataSource->rows(); emit endInsertRows(); emit beginInsertColumns(QModelIndex(), 0, dataSource->cols()); m_colCountBuffer = dataSource->cols(); emit endInsertColumns(); } m_dataSource = dataSource; } QModelIndex QxtScheduleViewHeaderModel::parent(const QModelIndex & index) const { Q_UNUSED(index); return QModelIndex(); } int QxtScheduleViewHeaderModel::rowCount(const QModelIndex & parent) const { if (!parent.isValid()) { if (this->m_dataSource) return m_dataSource->rows(); } return 0; } int QxtScheduleViewHeaderModel::columnCount(const QModelIndex & parent) const { if (!parent.isValid()) { if (this->m_dataSource) return m_dataSource->cols(); } return 0; } QVariant QxtScheduleViewHeaderModel::data(const QModelIndex & index, int role) const { Q_UNUSED(index); Q_UNUSED(role); return QVariant(); } bool QxtScheduleViewHeaderModel::setData(const QModelIndex & index, const QVariant & value, int role) { Q_UNUSED(index); Q_UNUSED(value); Q_UNUSED(role); return false; } bool QxtScheduleViewHeaderModel::insertRow(int row, const QModelIndex & parent) { Q_UNUSED(row); Q_UNUSED(parent); return false; } QVariant QxtScheduleViewHeaderModel::headerData(int section, Qt::Orientation orientation, int role) const { if (!m_dataSource) return QVariant(); #if 0 if (role == Qt::SizeHintRole) { if (this->viewModel) { return viewModel->headerData(section, orientation, role); } } #endif if (role == Qt::DisplayRole || role == Qt::EditRole) { if (Qt::Horizontal == orientation) { int iTableOffset = m_dataSource->qxt_d().visualIndexToOffset(0, section); QDateTime startTime = QDateTime::fromTime_t(m_dataSource->qxt_d().offsetToUnixTime(iTableOffset)); return QVariant(startTime.date().toString()); } else { int iTableOffset = m_dataSource->qxt_d().visualIndexToOffset(section, 0); QTime time = QDateTime::fromTime_t(m_dataSource->qxt_d().offsetToUnixTime(iTableOffset)).time(); return QVariant(time.toString()); } } return QVariant(); } Qt::ItemFlags QxtScheduleViewHeaderModel::flags(const QModelIndex & index) const { Q_UNUSED(index); return Qt::ItemIsEnabled; } bool QxtScheduleViewHeaderModel::hasChildren(const QModelIndex & parent) const { Q_UNUSED(parent); return false; } libqxt-0.6.2/src/gui/qxtscheduleviewheadermodel_p.h000066400000000000000000000062541215241066400225130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ // // W A R N I N G // ------------- // // This file is not part of the Qxt API. It exists for the convenience // of other Qxt classes. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #ifndef QXTSCHEDULEVIEWHEADERMODEL_P_H_INCLUDED #define QXTSCHEDULEVIEWHEADERMODEL_P_H_INCLUDED #include #include #include /*! *@author Benjamin Zeller *@desc This Model is used to tell the Header how many rows and columns the view has */ class QxtScheduleView; class QxtScheduleViewHeaderModel : public QAbstractTableModel { Q_OBJECT public: QxtScheduleViewHeaderModel(QObject *parent = 0); void setDataSource(QxtScheduleView *dataSource); virtual QModelIndex parent(const QModelIndex & index) const; virtual int rowCount(const QModelIndex & parent = QModelIndex()) const; virtual int columnCount(const QModelIndex & parent = QModelIndex()) const; virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; virtual bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole); virtual bool insertRow(int row, const QModelIndex & parent = QModelIndex()); virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; virtual Qt::ItemFlags flags(const QModelIndex &index) const; virtual bool hasChildren(const QModelIndex & parent = QModelIndex()) const; public Q_SLOTS: void newZoomDepth(const int zoomDepth); void viewModeChanged(const int viewMode); private: QPointer m_dataSource; int m_rowCountBuffer; int m_colCountBuffer; }; #endif // SPLITVIEWHEADERMODEL_H libqxt-0.6.2/src/gui/qxtscreen.cpp000066400000000000000000000136661215241066400171320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtscreen.h" #include "qxtscreen_p.h" #include #include QxtScreenPrivate::QxtScreenPrivate() : currReso(), setReso(), availResos(), currRate(-1), setRate(-1), availRates(), currDepth(-1), setDepth(-1), availDepths(), screen(-1) { } void QxtScreenPrivate::invalidate() { currReso = QSize(); availResos.clear(); currRate = -1; availRates.clear(); currDepth = -1; availDepths.clear(); screen = -1; } void QxtScreenPrivate::init() { if (screen < 0) screen = qApp->desktop()->primaryScreen(); if (availResos.isEmpty() || !currReso.isValid() || availRates.isEmpty() || currRate < 0 || availDepths.isEmpty() || currDepth < 0) init_sys(); } /*! \class QxtScreen \inmodule QxtGui \brief The QxtScreen class provides access to screen settings. QxtScreen provides access to screen settings. \bold {Note:} Currently supported platforms are X11 and Windows. */ /*! Constructs a new QxtScreen for \a screen. \bold {Note:} The primary screen is used if \a screen is \c -1. */ QxtScreen::QxtScreen(int screen) { qxt_d().screen = screen; } /*! Constructs a new QxtScreen for \a screen. */ QxtScreen::QxtScreen(QWidget* screen) { qxt_d().screen = qApp->desktop()->screenNumber(screen); } /*! Destructs the screen object. */ QxtScreen::~QxtScreen() { } /*! Returns the screen number. */ int QxtScreen::screenNumber() const { const_cast(this)->qxt_d().init(); return qxt_d().screen; } /*! Sets the \a screen number. */ void QxtScreen::setScreenNumber(int screen) { qxt_d().invalidate(); qxt_d().screen = screen; } /*! Returns the screen widget. \sa QDesktopWidget::screen() */ QWidget* QxtScreen::screen() const { const_cast(this)->qxt_d().init(); return qApp->desktop()->screen(qxt_d().screen); } /*! Sets the \a screen. \sa QDesktopWidget::screenNumber() */ void QxtScreen::setScreen(QWidget* screen) { qxt_d().invalidate(); qxt_d().screen = qApp->desktop()->screenNumber(screen); } /*! Returns the list of available resolutions. \sa availableRefreshRates() */ QList QxtScreen::availableResolutions() const { const_cast(this)->qxt_d().init(); return qxt_d().availResos; } /*! Returns the list of available refresh rates for \a resolution. \sa availableResolutions() */ QList QxtScreen::availableRefreshRates(const QSize& resolution) const { const_cast(this)->qxt_d().init(); return qxt_d().availRates.values(resolution); } /*! Returns the list of available color depths for \a resolution. \sa availableResolutions() */ QList QxtScreen::availableColorDepths(const QSize& resolution) const { const_cast(this)->qxt_d().init(); return qxt_d().availDepths.values(resolution); } /*! Returns the current resolution. */ QSize QxtScreen::resolution() const { const_cast(this)->qxt_d().init(); return qxt_d().currReso; } /*! Sets the \a resolution. \bold {Note:} No changes are applied until apply() is called. \sa apply() */ void QxtScreen::setResolution(const QSize& resolution) { qxt_d().setReso = resolution; } /*! Returns the current refresh rate. */ int QxtScreen::refreshRate() const { const_cast(this)->qxt_d().init(); return qxt_d().currRate; } /*! Sets the refresh \a rate. \bold {Note:} No changes are applied until apply() is called. \sa apply() */ void QxtScreen::setRefreshRate(int rate) { qxt_d().setRate = rate; } /*! Returns the current color depth. \bold {Note:} This is currently supported only on Windows. */ int QxtScreen::colorDepth() const { const_cast(this)->qxt_d().init(); return qxt_d().currDepth; } /*! Sets the color \a depth. \bold {Note:} No changes are applied until apply() is called. \bold {Note:} This is currently supported only on Windows. \sa apply() */ void QxtScreen::setColorDepth(int depth) { qxt_d().setDepth = depth; } /*! Applies the resolution and refresh rate. Returns \c true if succeeds, \c false otherwise. \sa setResolution(), setRefreshRate() */ bool QxtScreen::apply() { qxt_d().init(); return qxt_d().set(qxt_d().setReso, qxt_d().setRate, qxt_d().setDepth); } /*! Reverts the resolution and refresh rate. Returns \c true if succeeds, \c false otherwise. \sa setResolution(), setRefreshRate() */ bool QxtScreen::cancel() { qxt_d().init(); return qxt_d().set(qxt_d().currReso, qxt_d().currRate, qxt_d().currDepth); } /*! Refreshes the screen information. */ void QxtScreen::refresh() { qxt_d().invalidate(); qxt_d().init(); } libqxt-0.6.2/src/gui/qxtscreen.h000066400000000000000000000041251215241066400165650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSCREEN_H #define QXTSCREEN_H #include #include #include "qxtglobal.h" QT_FORWARD_DECLARE_CLASS(QWidget) class QxtScreenPrivate; class QXT_GUI_EXPORT QxtScreen { public: QxtScreen(int screen = -1); QxtScreen(QWidget* screen); ~QxtScreen(); int screenNumber() const; void setScreenNumber(int screen); QWidget* screen() const; void setScreen(QWidget* screen); QList availableResolutions() const; QList availableRefreshRates(const QSize& resolution) const; QList availableColorDepths(const QSize& resolution) const; QSize resolution() const; void setResolution(const QSize& resolution); int refreshRate() const; void setRefreshRate(int rate); int colorDepth() const; void setColorDepth(int depth); bool apply(); bool cancel(); void refresh(); private: QXT_DECLARE_PRIVATE(QxtScreen) }; #endif // QXTSCREEN_H libqxt-0.6.2/src/gui/qxtscreen_p.h000066400000000000000000000036221215241066400171050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSCREEN_P_H #define QXTSCREEN_P_H #include #include #include #include "qxtscreen.h" class QxtScreenPrivate : public QxtPrivate { public: QxtScreenPrivate(); void invalidate(); void init(); void init_sys(); bool set(const QSize& reso, int rate, int depth); QSize currReso; QSize setReso; QList availResos; int currRate; int setRate; QMultiHash availRates; int currDepth; int setDepth; QMultiHash availDepths; int screen; }; inline uint qHash(const QSize& key) { uint h1 = qHash(key.width()); uint h2 = qHash(key.height()); return ((h1 << 16) | (h1 >> 16)) ^ h2; } #endif // QXTSCREEN_P_H libqxt-0.6.2/src/gui/qxtscreen_win.cpp000066400000000000000000000100661215241066400177760ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtscreen_p.h" #include void QxtScreenPrivate::init_sys() { DISPLAY_DEVICE displayDevice; ::ZeroMemory(&displayDevice, sizeof(displayDevice)); displayDevice.cb = sizeof(displayDevice); if (::EnumDisplayDevices(NULL, screen, &displayDevice, 0)) { DEVMODE devMode; ::ZeroMemory(&devMode, sizeof(devMode)); devMode.dmSize = sizeof(devMode); // current resolution & rate if (!currReso.isValid() || currRate < 0 || currDepth < 0) { if (::EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode)) { currReso = QSize(devMode.dmPelsWidth, devMode.dmPelsHeight); currRate = devMode.dmDisplayFrequency; currDepth = devMode.dmBitsPerPel; } } // available resolutions & rates if (availResos.isEmpty() || availRates.isEmpty() || availDepths.isEmpty()) { availResos.clear(); availRates.clear(); availDepths.clear(); ::ZeroMemory(&devMode, sizeof(devMode)); devMode.dmSize = sizeof(devMode); DWORD i = 0; while (::EnumDisplaySettings(displayDevice.DeviceName, i++, &devMode)) { const QSize reso(devMode.dmPelsWidth, devMode.dmPelsHeight); if (!availResos.contains(reso)) availResos += reso; if (!availRates.contains(reso, devMode.dmDisplayFrequency)) availRates.insertMulti(reso, devMode.dmDisplayFrequency); if (!availDepths.contains(reso, devMode.dmBitsPerPel)) availDepths.insertMulti(reso, devMode.dmBitsPerPel); ::ZeroMemory(&devMode, sizeof(devMode)); devMode.dmSize = sizeof(devMode); } } } } bool QxtScreenPrivate::set(const QSize& reso, int rate, int depth) { bool result = false; DISPLAY_DEVICE displayDevice; ::ZeroMemory(&displayDevice, sizeof(displayDevice)); displayDevice.cb = sizeof(displayDevice); if (::EnumDisplayDevices(NULL, screen, &displayDevice, 0)) { DEVMODE devMode; ::ZeroMemory(&devMode, sizeof(devMode)); devMode.dmSize = sizeof(devMode); if (reso.isValid()) { devMode.dmPelsWidth = reso.width(); devMode.dmPelsHeight = reso.height(); devMode.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT; } if (rate != -1) { devMode.dmDisplayFrequency = rate; devMode.dmFields |= DM_DISPLAYFREQUENCY; } if (depth != -1) { devMode.dmBitsPerPel = depth; devMode.dmFields |= DM_BITSPERPEL; } result = ::ChangeDisplaySettingsEx(displayDevice.DeviceName, &devMode, NULL, 0, NULL) == DISP_CHANGE_SUCCESSFUL; } return result; } libqxt-0.6.2/src/gui/qxtscreen_x11.cpp000066400000000000000000000065431215241066400176170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtscreen_p.h" #ifdef HAVE_XRANDR #include #include #endif // HAVE_XRANDR void QxtScreenPrivate::init_sys() { #ifdef HAVE_XRANDR Display* display = XOpenDisplay(NULL); Window root = RootWindow(display, screen); XRRScreenConfiguration* config = XRRGetScreenInfo(display, root); // available resolutions & rates if (availResos.isEmpty() || availRates.isEmpty()) { availResos.clear(); availRates.clear(); int sizeCount = 0; XRRScreenSize* sizes = XRRSizes(display, 0, &sizeCount); for (int i = 0; i < sizeCount; ++i) { QSize reso(sizes[i].width, sizes[i].height); if (!availResos.contains(reso)) availResos += reso; int rateCount = 0; short* rates = XRRConfigRates(config, i, &rateCount); for (int j = 0; j < rateCount; ++j) availRates.insertMulti(reso, rates[j]); } } // current resolution & rate if (!currReso.isValid() || currRate < 0) { Rotation rotation; SizeID sizeId = XRRConfigCurrentConfiguration(config, &rotation); currReso = availResos.at(sizeId); currRate = XRRConfigCurrentRate(config); } XRRFreeScreenConfigInfo(config); XCloseDisplay(display); #endif // HAVE_XRANDR } bool QxtScreenPrivate::set(const QSize& reso, int rate, int depth) { bool result = false; Q_UNUSED(reso); Q_UNUSED(rate); Q_UNUSED(depth); #ifdef HAVE_XRANDR Display* display = XOpenDisplay(NULL); Window root = RootWindow(display, screen); XRRScreenConfiguration* config = XRRGetScreenInfo(display, root); int sizeIndex = 0; if (reso.isValid()) sizeIndex = availResos.indexOf(reso); else sizeIndex = availResos.indexOf(currReso); Q_ASSERT(sizeIndex != -1); if (rate == -1) result = XRRSetScreenConfig(display, config, root, sizeIndex, RR_Rotate_0, CurrentTime); else result = XRRSetScreenConfigAndRate(display, config, root, sizeIndex, RR_Rotate_0, rate, CurrentTime); XRRFreeScreenConfigInfo(config); XCloseDisplay(display); #endif // HAVE_XRANDR return result; } libqxt-0.6.2/src/gui/qxtsortfilterproxymodel.cpp000066400000000000000000000235551215241066400221710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtsortfilterproxymodel.h" #include class QxtModelFilterPrivate { public: QxtModelFilterPrivate (const QVariant &value = QVariant(), const int role = Qt::DisplayRole, const Qt::MatchFlags flags = Qt::MatchContains); bool acceptsValue ( const QVariant & value ); QVariant m_value; int m_role; Qt::MatchFlags m_flags; }; class QxtSortFilterProxyModelPrivate : public QxtPrivate { public: QMap filters; bool m_declaringFilter; }; QxtModelFilterPrivate::QxtModelFilterPrivate(const QVariant &value, const int role, const Qt::MatchFlags flags) :m_value(value),m_role(role),m_flags(flags) { } bool QxtModelFilterPrivate::acceptsValue ( const QVariant & value ) { uint matchType = m_flags & 0x0F; //if we have no value we accept everything if(!m_value.isValid() || !value.isValid()) return true; // QVariant based matching if (matchType == Qt::MatchExactly ){ if(m_value == value) return true; } // QString based matching else { Qt::CaseSensitivity cs = m_flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; QString filterText = m_value.toString(); QString modelText = value.toString(); switch (matchType){ case Qt::MatchRegExp: if (QRegExp(filterText, cs).exactMatch(modelText)) return true; break; case Qt::MatchWildcard: if (QRegExp(filterText, cs, QRegExp::Wildcard).exactMatch(modelText)) return true; break; case Qt::MatchStartsWith: if (modelText.startsWith(filterText, cs)) return true; break; case Qt::MatchEndsWith: if (modelText.endsWith(filterText, cs)) return true; break; case Qt::MatchFixedString: if (modelText.compare(filterText, cs) == 0) return true; break; default: case Qt::MatchContains: if (modelText.contains(filterText, cs)) return true; } } return false; } /*! \class QxtSortFilterProxyModel \inmodule QxtGui \brief The QxtSortFilterProxyModel class is a multi column filter model. The QxtSortFilterProxyModel makes it possible to filter over multiple columns. \code QxtSortFilterProxyModel * filterModel = new QxtSortFilterProxyModel(parent); filterModel->setSourceModel(sourceModel); filterModel->beginDeclareFilter(); filterModel->setFilter(1,QVariant("SomeStringValue"),Qt::DisplayRole,Qt::MatchExactly); //remove some old filter filterModel->removeFilter(2); filterModel->setFilter(5,QVariant(1234),Qt::DisplayRole,Qt::MatchExactly); filterModel->endDeclateFilter(); \endcode Now the model will filter column 1 and 5, to be accepted by the filtermodel a row needs to pass all filters */ /*! Constructs a new QxtSortFilterProxyModel with \a parent. */ QxtSortFilterProxyModel::QxtSortFilterProxyModel ( QObject *parent) : QSortFilterProxyModel(parent) { QXT_INIT_PRIVATE(QxtSortFilterProxyModel); qxt_d().m_declaringFilter = false; } /*! \brief tells the model you want to declare a new filter If you have a lot of data in your model it can be slow to declare more than one filter, because the model will always rebuild itself. If you call this member before setting the new filters the model will invalidate its contents not before you call \sa endDeclareFilter() */ void QxtSortFilterProxyModel::beginDeclareFilter ( ) { qxt_d().m_declaringFilter = true; } /*! \brief stops the filter declaration and invalidates the filter \sa beginDeclareFilter() */ void QxtSortFilterProxyModel::endDeclareFilter ( ) { if(qxt_d().m_declaringFilter){ qxt_d().m_declaringFilter = false; invalidateFilter(); } } /*! \reimp */ bool QxtSortFilterProxyModel::filterAcceptsRow ( int source_row, const QModelIndex &source_parent ) const { QList filterColumns = qxt_d().filters.keys(); foreach(int currCol,filterColumns){ QxtModelFilterPrivate filter = qxt_d().filters[currCol]; // if the column specified by the user is -1 // that means all columns need to pass the filter to get into the result if (currCol == -1) { int column_count = sourceModel()->columnCount(source_parent); for (int column = 0; column < column_count; ++column) { QModelIndex source_index = sourceModel()->index(source_row, column, source_parent); QVariant key = sourceModel()->data(source_index, filter.m_role); if (!filter.acceptsValue(key)) return false; } continue; } QModelIndex source_index = sourceModel()->index(source_row, currCol , source_parent); if (!source_index.isValid()) // the column may not exist continue; QVariant key = sourceModel()->data(source_index, filter.m_role); if(!filter.acceptsValue(key)) return false; } return true; } /*! \brief Sets the filter with \a value, \a role and \a flags to the given \a column */ void QxtSortFilterProxyModel::setFilter ( const int column, const QVariant &value, const int role, Qt::MatchFlags flags ) { if(qxt_d().filters.contains(column)) qxt_d().filters[column] = QxtModelFilterPrivate(value,role,flags); else qxt_d().filters.insert(column,QxtModelFilterPrivate(value,role,flags)); if(!qxt_d().m_declaringFilter) invalidateFilter(); } /*! \brief Removes the filter from the given \a column */ void QxtSortFilterProxyModel::removeFilter ( const int column ) { if(qxt_d().filters.contains(column)){ qxt_d().filters.remove(column); if(!qxt_d().m_declaringFilter) invalidateFilter(); } } /*! \brief Sets the filter \a value for the given \a column */ void QxtSortFilterProxyModel::setFilterValue ( const int column , const QVariant &value ) { if(qxt_d().filters.contains(column)) qxt_d().filters[column].m_value = value; else qxt_d().filters.insert(column,QxtModelFilterPrivate(value)); if(!qxt_d().m_declaringFilter) invalidateFilter(); } /*! \brief Sets the filter \a role for the given \a column */ void QxtSortFilterProxyModel::setFilterRole ( const int column , const int role ) { if(qxt_d().filters.contains(column)) qxt_d().filters[column].m_role=role; else qxt_d().filters.insert(column,QxtModelFilterPrivate(QVariant(),role)); if(!qxt_d().m_declaringFilter) invalidateFilter(); } /*! \brief Sets the filter \a flags for the given \a column */ void QxtSortFilterProxyModel::setFilterFlags ( const int column , const Qt::MatchFlags flags ) { if(qxt_d().filters.contains(column)) qxt_d().filters[column].m_flags = flags; else qxt_d().filters.insert(column,QxtModelFilterPrivate(QVariant(),Qt::DisplayRole,flags)); if(!qxt_d().m_declaringFilter) invalidateFilter(); } /*! \brief Returns the filter value for the given \a column \bold {Note:} if the column is not filtered it will return a null variant */ QVariant QxtSortFilterProxyModel::filterValue ( const int column ) const { if(qxt_d().filters.contains(column)) return qxt_d().filters[column].m_value; return QVariant(); } /*! \brief Returns the filter role for the given \a column \bold {Note:} if the column is not filtered it will return \c -1 */ int QxtSortFilterProxyModel::filterRole ( const int column ) const { if(qxt_d().filters.contains(column)) return qxt_d().filters[column].m_role; return -1; } /*! \brief returns the filter flags for the given \a column \bold {Note:} if the column is not filtered it will return the default value */ Qt::MatchFlags QxtSortFilterProxyModel::filterFlags ( const int column ) const { if(qxt_d().filters.contains(column)) return qxt_d().filters[column].m_flags; return Qt::MatchContains; } /*! Returns true if the \a column is filtered */ bool QxtSortFilterProxyModel::isFiltered ( const int column ) { return qxt_d().filters.contains(column); } libqxt-0.6.2/src/gui/qxtsortfilterproxymodel.h000066400000000000000000000047261215241066400216350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSORTFILTERPROXYMODEL_H #define QXTSORTFILTERPROXYMODEL_H #include #include #include #include #include "qxtglobal.h" class QxtSortFilterProxyModelPrivate; class QXT_GUI_EXPORT QxtSortFilterProxyModel : public QSortFilterProxyModel { Q_OBJECT public: QxtSortFilterProxyModel( QObject *parent = 0 ); void beginDeclareFilter( ); void endDeclareFilter( ); void setFilter( const int column, const QVariant &value, const int role = Qt::DisplayRole, Qt::MatchFlags flags = Qt::MatchContains ); void setFilterValue( const int column, const QVariant &value ); void setFilterRole( const int column, const int role = Qt::DisplayRole ); void setFilterFlags( const int column, const Qt::MatchFlags flags = Qt::MatchContains ); void removeFilter( const int column ); QVariant filterValue( const int column ) const; int filterRole( const int column ) const; Qt::MatchFlags filterFlags( const int column ) const; bool isFiltered( const int column ); protected: virtual bool filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const; private: QXT_DECLARE_PRIVATE(QxtSortFilterProxyModel) }; #endif // QXTSORTFILTERPROXYMODEL_H libqxt-0.6.2/src/gui/qxtspanslider.cpp000066400000000000000000000547371215241066400200230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtspanslider.h" #include "qxtspanslider_p.h" #include #include #include #include #include QxtSpanSliderPrivate::QxtSpanSliderPrivate() : lower(0), upper(0), lowerPos(0), upperPos(0), offset(0), position(0), lastPressed(NoHandle), mainControl(LowerHandle), lowerPressed(QStyle::SC_None), upperPressed(QStyle::SC_None), movement(QxtSpanSlider::FreeMovement), firstMovement(false), blockTracking(false) { } // TODO: get rid of this in Qt 4.3 void QxtSpanSliderPrivate::initStyleOption(QStyleOptionSlider* option, SpanHandle handle) const { if (!option) return; const QSlider* p = &qxt_p(); option->initFrom(p); option->subControls = QStyle::SC_None; option->activeSubControls = QStyle::SC_None; option->orientation = p->orientation(); option->maximum = p->maximum(); option->minimum = p->minimum(); option->tickPosition = p->tickPosition(); option->tickInterval = p->tickInterval(); option->upsideDown = (p->orientation() == Qt::Horizontal) ? (p->invertedAppearance() != (option->direction == Qt::RightToLeft)) : (!p->invertedAppearance()); option->direction = Qt::LeftToRight; // we use the upsideDown option instead option->sliderPosition = (handle == LowerHandle ? lowerPos : upperPos); option->sliderValue = (handle == LowerHandle ? lower : upper); option->singleStep = p->singleStep(); option->pageStep = p->pageStep(); if (p->orientation() == Qt::Horizontal) option->state |= QStyle::State_Horizontal; } int QxtSpanSliderPrivate::pixelPosToRangeValue(int pos) const { QStyleOptionSlider opt; initStyleOption(&opt); int sliderMin = 0; int sliderMax = 0; int sliderLength = 0; const QSlider* p = &qxt_p(); const QRect gr = p->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, p); const QRect sr = p->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, p); if (p->orientation() == Qt::Horizontal) { sliderLength = sr.width(); sliderMin = gr.x(); sliderMax = gr.right() - sliderLength + 1; } else { sliderLength = sr.height(); sliderMin = gr.y(); sliderMax = gr.bottom() - sliderLength + 1; } return QStyle::sliderValueFromPosition(p->minimum(), p->maximum(), pos - sliderMin, sliderMax - sliderMin, opt.upsideDown); } void QxtSpanSliderPrivate::handleMousePress(const QPoint& pos, QStyle::SubControl& control, int value, SpanHandle handle) { QStyleOptionSlider opt; initStyleOption(&opt, handle); QSlider* p = &qxt_p(); const QStyle::SubControl oldControl = control; control = p->style()->hitTestComplexControl(QStyle::CC_Slider, &opt, pos, p); const QRect sr = p->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, p); if (control == QStyle::SC_SliderHandle) { position = value; offset = pick(pos - sr.topLeft()); lastPressed = handle; p->setSliderDown(true); } if (control != oldControl) p->update(sr); } void QxtSpanSliderPrivate::setupPainter(QPainter* painter, Qt::Orientation orientation, qreal x1, qreal y1, qreal x2, qreal y2) const { QColor highlight = qxt_p().palette().color(QPalette::Highlight); QLinearGradient gradient(x1, y1, x2, y2); gradient.setColorAt(0, highlight.dark(120)); gradient.setColorAt(1, highlight.light(108)); painter->setBrush(gradient); if (orientation == Qt::Horizontal) painter->setPen(QPen(highlight.dark(130), 0)); else painter->setPen(QPen(highlight.dark(150), 0)); } void QxtSpanSliderPrivate::drawSpan(QStylePainter* painter, const QRect& rect) const { QStyleOptionSlider opt; initStyleOption(&opt); const QSlider* p = &qxt_p(); // area QRect groove = p->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, p); if (opt.orientation == Qt::Horizontal) groove.adjust(0, 0, -1, 0); else groove.adjust(0, 0, 0, -1); // pen & brush painter->setPen(QPen(p->palette().color(QPalette::Dark).light(110), 0)); if (opt.orientation == Qt::Horizontal) setupPainter(painter, opt.orientation, groove.center().x(), groove.top(), groove.center().x(), groove.bottom()); else setupPainter(painter, opt.orientation, groove.left(), groove.center().y(), groove.right(), groove.center().y()); // draw groove painter->drawRect(rect.intersected(groove)); } void QxtSpanSliderPrivate::drawHandle(QStylePainter* painter, SpanHandle handle) const { QStyleOptionSlider opt; initStyleOption(&opt, handle); opt.subControls = QStyle::SC_SliderHandle; QStyle::SubControl pressed = (handle == LowerHandle ? lowerPressed : upperPressed); if (pressed == QStyle::SC_SliderHandle) { opt.activeSubControls = pressed; opt.state |= QStyle::State_Sunken; } painter->drawComplexControl(QStyle::CC_Slider, opt); } void QxtSpanSliderPrivate::triggerAction(QAbstractSlider::SliderAction action, bool main) { int value = 0; bool no = false; bool up = false; const int min = qxt_p().minimum(); const int max = qxt_p().maximum(); const SpanHandle altControl = (mainControl == LowerHandle ? UpperHandle : LowerHandle); blockTracking = true; switch (action) { case QAbstractSlider::SliderSingleStepAdd: if ((main && mainControl == UpperHandle) || (!main && altControl == UpperHandle)) { value = qBound(min, upper + qxt_p().singleStep(), max); up = true; break; } value = qBound(min, lower + qxt_p().singleStep(), max); break; case QAbstractSlider::SliderSingleStepSub: if ((main && mainControl == UpperHandle) || (!main && altControl == UpperHandle)) { value = qBound(min, upper - qxt_p().singleStep(), max); up = true; break; } value = qBound(min, lower - qxt_p().singleStep(), max); break; case QAbstractSlider::SliderToMinimum: value = min; if ((main && mainControl == UpperHandle) || (!main && altControl == UpperHandle)) up = true; break; case QAbstractSlider::SliderToMaximum: value = max; if ((main && mainControl == UpperHandle) || (!main && altControl == UpperHandle)) up = true; break; case QAbstractSlider::SliderMove: if ((main && mainControl == UpperHandle) || (!main && altControl == UpperHandle)) up = true; case QAbstractSlider::SliderNoAction: no = true; break; default: qWarning("QxtSpanSliderPrivate::triggerAction: Unknown action"); break; } if (!no && !up) { if (movement == QxtSpanSlider::NoCrossing) value = qMin(value, upper); else if (movement == QxtSpanSlider::NoOverlapping) value = qMin(value, upper - 1); if (movement == QxtSpanSlider::FreeMovement && value > upper) { swapControls(); qxt_p().setUpperPosition(value); } else { qxt_p().setLowerPosition(value); } } else if (!no) { if (movement == QxtSpanSlider::NoCrossing) value = qMax(value, lower); else if (movement == QxtSpanSlider::NoOverlapping) value = qMax(value, lower + 1); if (movement == QxtSpanSlider::FreeMovement && value < lower) { swapControls(); qxt_p().setLowerPosition(value); } else { qxt_p().setUpperPosition(value); } } blockTracking = false; qxt_p().setLowerValue(lowerPos); qxt_p().setUpperValue(upperPos); } void QxtSpanSliderPrivate::swapControls() { qSwap(lower, upper); qSwap(lowerPressed, upperPressed); lastPressed = (lastPressed == LowerHandle ? UpperHandle : LowerHandle); mainControl = (mainControl == LowerHandle ? UpperHandle : LowerHandle); } void QxtSpanSliderPrivate::updateRange(int min, int max) { Q_UNUSED(min); Q_UNUSED(max); // setSpan() takes care of keeping span in range qxt_p().setSpan(lower, upper); } void QxtSpanSliderPrivate::movePressedHandle() { switch (lastPressed) { case QxtSpanSliderPrivate::LowerHandle: if (lowerPos != lower) { bool main = (mainControl == QxtSpanSliderPrivate::LowerHandle); triggerAction(QAbstractSlider::SliderMove, main); } break; case QxtSpanSliderPrivate::UpperHandle: if (upperPos != upper) { bool main = (mainControl == QxtSpanSliderPrivate::UpperHandle); triggerAction(QAbstractSlider::SliderMove, main); } break; default: break; } } /*! \class QxtSpanSlider \inmodule QxtGui \brief The QxtSpanSlider widget is a QSlider with two handles. QxtSpanSlider is a slider with two handles. QxtSpanSlider is handy for letting user to choose an span between min/max. The span color is calculated based on QPalette::Highlight. The keys are bound according to the following table: \table \header \o Orientation \o Key \o Handle \row \o Qt::Horizontal \o Qt::Key_Left \o lower \row \o Qt::Horizontal \o Qt::Key_Right \o lower \row \o Qt::Horizontal \o Qt::Key_Up \o upper \row \o Qt::Horizontal \o Qt::Key_Down \o upper \row \o Qt::Vertical \o Qt::Key_Up \o lower \row \o Qt::Vertical \o Qt::Key_Down \o lower \row \o Qt::Vertical \o Qt::Key_Left \o upper \row \o Qt::Vertical \o Qt::Key_Right \o upper \endtable Keys are bound by the time the slider is created. A key is bound to same handle for the lifetime of the slider. So even if the handle representation might change from lower to upper, the same key binding remains. \image qxtspanslider.png "QxtSpanSlider in Plastique style." \bold {Note:} QxtSpanSlider inherits QSlider for implementation specific reasons. Adjusting any single handle specific properties like \list \o QAbstractSlider::sliderPosition \o QAbstractSlider::value \endlist has no effect. However, all slider specific properties like \list \o QAbstractSlider::invertedAppearance \o QAbstractSlider::invertedControls \o QAbstractSlider::minimum \o QAbstractSlider::maximum \o QAbstractSlider::orientation \o QAbstractSlider::pageStep \o QAbstractSlider::singleStep \o QSlider::tickInterval \o QSlider::tickPosition \endlist are taken into consideration. */ /*! \enum QxtSpanSlider::HandleMovementMode This enum describes the available handle movement modes. \value FreeMovement The handles can be moved freely. \value NoCrossing The handles cannot cross, but they can still overlap each other. The lower and upper values can be the same. \value NoOverlapping The handles cannot overlap each other. The lower and upper values cannot be the same. */ /*! \fn QxtSpanSlider::lowerValueChanged(int lower) This signal is emitted whenever the \a lower value has changed. */ /*! \fn QxtSpanSlider::upperValueChanged(int upper) This signal is emitted whenever the \a upper value has changed. */ /*! \fn QxtSpanSlider::spanChanged(int lower, int upper) This signal is emitted whenever both the \a lower and the \a upper values have changed ie. the span has changed. */ /*! \fn QxtSpanSlider::lowerPositionChanged(int lower) This signal is emitted whenever the \a lower position has changed. */ /*! \fn QxtSpanSlider::upperPositionChanged(int upper) This signal is emitted whenever the \a upper position has changed. */ /*! Constructs a new QxtSpanSlider with \a parent. */ QxtSpanSlider::QxtSpanSlider(QWidget* parent) : QSlider(parent) { QXT_INIT_PRIVATE(QxtSpanSlider); connect(this, SIGNAL(rangeChanged(int, int)), &qxt_d(), SLOT(updateRange(int, int))); connect(this, SIGNAL(sliderReleased()), &qxt_d(), SLOT(movePressedHandle())); } /*! Constructs a new QxtSpanSlider with \a orientation and \a parent. */ QxtSpanSlider::QxtSpanSlider(Qt::Orientation orientation, QWidget* parent) : QSlider(orientation, parent) { QXT_INIT_PRIVATE(QxtSpanSlider); connect(this, SIGNAL(rangeChanged(int, int)), &qxt_d(), SLOT(updateRange(int, int))); connect(this, SIGNAL(sliderReleased()), &qxt_d(), SLOT(movePressedHandle())); } /*! Destructs the span slider. */ QxtSpanSlider::~QxtSpanSlider() { } /*! \property QxtSpanSlider::handleMovementMode \brief the handle movement mode */ QxtSpanSlider::HandleMovementMode QxtSpanSlider::handleMovementMode() const { return qxt_d().movement; } void QxtSpanSlider::setHandleMovementMode(QxtSpanSlider::HandleMovementMode mode) { qxt_d().movement = mode; } /*! \property QxtSpanSlider::lowerValue \brief the lower value of the span */ int QxtSpanSlider::lowerValue() const { return qMin(qxt_d().lower, qxt_d().upper); } void QxtSpanSlider::setLowerValue(int lower) { setSpan(lower, qxt_d().upper); } /*! \property QxtSpanSlider::upperValue \brief the upper value of the span */ int QxtSpanSlider::upperValue() const { return qMax(qxt_d().lower, qxt_d().upper); } void QxtSpanSlider::setUpperValue(int upper) { setSpan(qxt_d().lower, upper); } /*! Sets the span from \a lower to \a upper. */ void QxtSpanSlider::setSpan(int lower, int upper) { const int low = qBound(minimum(), qMin(lower, upper), maximum()); const int upp = qBound(minimum(), qMax(lower, upper), maximum()); if (low != qxt_d().lower || upp != qxt_d().upper) { if (low != qxt_d().lower) { qxt_d().lower = low; qxt_d().lowerPos = low; emit lowerValueChanged(low); } if (upp != qxt_d().upper) { qxt_d().upper = upp; qxt_d().upperPos = upp; emit upperValueChanged(upp); } emit spanChanged(qxt_d().lower, qxt_d().upper); update(); } } /*! \property QxtSpanSlider::lowerPosition \brief the lower position of the span */ int QxtSpanSlider::lowerPosition() const { return qxt_d().lowerPos; } void QxtSpanSlider::setLowerPosition(int lower) { if (qxt_d().lowerPos != lower) { qxt_d().lowerPos = lower; if (!hasTracking()) update(); if (isSliderDown()) emit lowerPositionChanged(lower); if (hasTracking() && !qxt_d().blockTracking) { bool main = (qxt_d().mainControl == QxtSpanSliderPrivate::LowerHandle); qxt_d().triggerAction(SliderMove, main); } } } /*! \property QxtSpanSlider::upperPosition \brief the upper position of the span */ int QxtSpanSlider::upperPosition() const { return qxt_d().upperPos; } void QxtSpanSlider::setUpperPosition(int upper) { if (qxt_d().upperPos != upper) { qxt_d().upperPos = upper; if (!hasTracking()) update(); if (isSliderDown()) emit upperPositionChanged(upper); if (hasTracking() && !qxt_d().blockTracking) { bool main = (qxt_d().mainControl == QxtSpanSliderPrivate::UpperHandle); qxt_d().triggerAction(SliderMove, main); } } } /*! \reimp */ void QxtSpanSlider::keyPressEvent(QKeyEvent* event) { QSlider::keyPressEvent(event); bool main = true; SliderAction action = SliderNoAction; switch (event->key()) { case Qt::Key_Left: main = (orientation() == Qt::Horizontal); action = !invertedAppearance() ? SliderSingleStepSub : SliderSingleStepAdd; break; case Qt::Key_Right: main = (orientation() == Qt::Horizontal); action = !invertedAppearance() ? SliderSingleStepAdd : SliderSingleStepSub; break; case Qt::Key_Up: main = (orientation() == Qt::Vertical); action = invertedControls() ? SliderSingleStepSub : SliderSingleStepAdd; break; case Qt::Key_Down: main = (orientation() == Qt::Vertical); action = invertedControls() ? SliderSingleStepAdd : SliderSingleStepSub; break; case Qt::Key_Home: main = (qxt_d().mainControl == QxtSpanSliderPrivate::LowerHandle); action = SliderToMinimum; break; case Qt::Key_End: main = (qxt_d().mainControl == QxtSpanSliderPrivate::UpperHandle); action = SliderToMaximum; break; default: event->ignore(); break; } if (action) qxt_d().triggerAction(action, main); } /*! \reimp */ void QxtSpanSlider::mousePressEvent(QMouseEvent* event) { if (minimum() == maximum() || (event->buttons() ^ event->button())) { event->ignore(); return; } qxt_d().handleMousePress(event->pos(), qxt_d().upperPressed, qxt_d().upper, QxtSpanSliderPrivate::UpperHandle); if (qxt_d().upperPressed != QStyle::SC_SliderHandle) qxt_d().handleMousePress(event->pos(), qxt_d().lowerPressed, qxt_d().lower, QxtSpanSliderPrivate::LowerHandle); qxt_d().firstMovement = true; event->accept(); } /*! \reimp */ void QxtSpanSlider::mouseMoveEvent(QMouseEvent* event) { if (qxt_d().lowerPressed != QStyle::SC_SliderHandle && qxt_d().upperPressed != QStyle::SC_SliderHandle) { event->ignore(); return; } QStyleOptionSlider opt; qxt_d().initStyleOption(&opt); const int m = style()->pixelMetric(QStyle::PM_MaximumDragDistance, &opt, this); int newPosition = qxt_d().pixelPosToRangeValue(qxt_d().pick(event->pos()) - qxt_d().offset); if (m >= 0) { const QRect r = rect().adjusted(-m, -m, m, m); if (!r.contains(event->pos())) { newPosition = qxt_d().position; } } // pick the preferred handle on the first movement if (qxt_d().firstMovement) { if (qxt_d().lower == qxt_d().upper) { if (newPosition < lowerValue()) { qxt_d().swapControls(); qxt_d().firstMovement = false; } } else { qxt_d().firstMovement = false; } } if (qxt_d().lowerPressed == QStyle::SC_SliderHandle) { if (qxt_d().movement == NoCrossing) newPosition = qMin(newPosition, upperValue()); else if (qxt_d().movement == NoOverlapping) newPosition = qMin(newPosition, upperValue() - 1); if (qxt_d().movement == FreeMovement && newPosition > qxt_d().upper) { qxt_d().swapControls(); setUpperPosition(newPosition); } else { setLowerPosition(newPosition); } } else if (qxt_d().upperPressed == QStyle::SC_SliderHandle) { if (qxt_d().movement == NoCrossing) newPosition = qMax(newPosition, lowerValue()); else if (qxt_d().movement == NoOverlapping) newPosition = qMax(newPosition, lowerValue() + 1); if (qxt_d().movement == FreeMovement && newPosition < qxt_d().lower) { qxt_d().swapControls(); setLowerPosition(newPosition); } else { setUpperPosition(newPosition); } } event->accept(); } /*! \reimp */ void QxtSpanSlider::mouseReleaseEvent(QMouseEvent* event) { QSlider::mouseReleaseEvent(event); setSliderDown(false); qxt_d().lowerPressed = QStyle::SC_None; qxt_d().upperPressed = QStyle::SC_None; update(); } /*! \reimp */ void QxtSpanSlider::paintEvent(QPaintEvent* event) { Q_UNUSED(event); QStylePainter painter(this); // groove & ticks QStyleOptionSlider opt; qxt_d().initStyleOption(&opt); opt.sliderValue = 0; opt.sliderPosition = 0; opt.subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderTickmarks; painter.drawComplexControl(QStyle::CC_Slider, opt); // handle rects opt.sliderPosition = qxt_d().lowerPos; const QRect lr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); const int lrv = qxt_d().pick(lr.center()); opt.sliderPosition = qxt_d().upperPos; const QRect ur = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); const int urv = qxt_d().pick(ur.center()); // span const int minv = qMin(lrv, urv); const int maxv = qMax(lrv, urv); const QPoint c = QRect(lr.center(), ur.center()).center(); QRect spanRect; if (orientation() == Qt::Horizontal) spanRect = QRect(QPoint(minv, c.y() - 2), QPoint(maxv, c.y() + 1)); else spanRect = QRect(QPoint(c.x() - 2, minv), QPoint(c.x() + 1, maxv)); qxt_d().drawSpan(&painter, spanRect); // handles switch (qxt_d().lastPressed) { case QxtSpanSliderPrivate::LowerHandle: qxt_d().drawHandle(&painter, QxtSpanSliderPrivate::UpperHandle); qxt_d().drawHandle(&painter, QxtSpanSliderPrivate::LowerHandle); break; case QxtSpanSliderPrivate::UpperHandle: default: qxt_d().drawHandle(&painter, QxtSpanSliderPrivate::LowerHandle); qxt_d().drawHandle(&painter, QxtSpanSliderPrivate::UpperHandle); break; } } libqxt-0.6.2/src/gui/qxtspanslider.h000066400000000000000000000060321215241066400174510ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSPANSLIDER_H #define QXTSPANSLIDER_H #include #include "qxtnamespace.h" #include "qxtglobal.h" class QxtSpanSliderPrivate; class QXT_GUI_EXPORT QxtSpanSlider : public QSlider { Q_OBJECT QXT_DECLARE_PRIVATE(QxtSpanSlider) Q_PROPERTY(int lowerValue READ lowerValue WRITE setLowerValue) Q_PROPERTY(int upperValue READ upperValue WRITE setUpperValue) Q_PROPERTY(int lowerPosition READ lowerPosition WRITE setLowerPosition) Q_PROPERTY(int upperPosition READ upperPosition WRITE setUpperPosition) Q_PROPERTY(HandleMovementMode handleMovementMode READ handleMovementMode WRITE setHandleMovementMode) Q_ENUMS(HandleMovementMode) public: explicit QxtSpanSlider(QWidget* parent = 0); explicit QxtSpanSlider(Qt::Orientation orientation, QWidget* parent = 0); virtual ~QxtSpanSlider(); enum HandleMovementMode { FreeMovement, NoCrossing, NoOverlapping }; HandleMovementMode handleMovementMode() const; void setHandleMovementMode(HandleMovementMode mode); int lowerValue() const; int upperValue() const; int lowerPosition() const; int upperPosition() const; public Q_SLOTS: void setLowerValue(int lower); void setUpperValue(int upper); void setSpan(int lower, int upper); void setLowerPosition(int lower); void setUpperPosition(int upper); Q_SIGNALS: void spanChanged(int lower, int upper); void lowerValueChanged(int lower); void upperValueChanged(int upper); void lowerPositionChanged(int lower); void upperPositionChanged(int upper); protected: virtual void keyPressEvent(QKeyEvent* event); virtual void mousePressEvent(QMouseEvent* event); virtual void mouseMoveEvent(QMouseEvent* event); virtual void mouseReleaseEvent(QMouseEvent* event); virtual void paintEvent(QPaintEvent* event); }; #endif // QXTSPANSLIDER_H libqxt-0.6.2/src/gui/qxtspanslider_p.h000066400000000000000000000054101215241066400177670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSPANSLIDER_P_H #define QXTSPANSLIDER_P_H #include #include #include "qxtspanslider.h" QT_FORWARD_DECLARE_CLASS(QStylePainter) QT_FORWARD_DECLARE_CLASS(QStyleOptionSlider) class QxtSpanSliderPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtSpanSlider) enum SpanHandle { NoHandle, LowerHandle, UpperHandle }; QxtSpanSliderPrivate(); void initStyleOption(QStyleOptionSlider* option, SpanHandle handle = UpperHandle) const; int pick(const QPoint& pt) const { return qxt_p().orientation() == Qt::Horizontal ? pt.x() : pt.y(); } int pixelPosToRangeValue(int pos) const; void handleMousePress(const QPoint& pos, QStyle::SubControl& control, int value, SpanHandle handle); void drawHandle(QStylePainter* painter, SpanHandle handle) const; void setupPainter(QPainter* painter, Qt::Orientation orientation, qreal x1, qreal y1, qreal x2, qreal y2) const; void drawSpan(QStylePainter* painter, const QRect& rect) const; void triggerAction(QAbstractSlider::SliderAction action, bool main); void swapControls(); int lower; int upper; int lowerPos; int upperPos; int offset; int position; SpanHandle lastPressed; SpanHandle mainControl; QStyle::SubControl lowerPressed; QStyle::SubControl upperPressed; QxtSpanSlider::HandleMovementMode movement; bool firstMovement; bool blockTracking; public Q_SLOTS: void updateRange(int min, int max); void movePressedHandle(); }; #endif // QXTSPANSLIDER_P_H libqxt-0.6.2/src/gui/qxtstandarditemeditorcreator.h000066400000000000000000000062051215241066400225550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSTANDARDITEMEDITORCREATOR_H #define QXTSTANDARDITEMEDITORCREATOR_H #include #include "qxtitemeditorcreatorbase.h" #include "qxtglobal.h" /*! \class QxtStandardItemEditorCreator QxtStandardItemEditorCreator \inmodule QxtGui \brief An extended QStandardItemEditorCreator with default values for user-chosen properties. The QxtStandardItemEditorCreator class provides the possibility to set default values for user-chosen properties. Usage: \code QItemEditorFactory *factory = new QItemEditorFactory; QxtStandardItemEditorCreator* spinBoxCreator = new QxtStandardItemEditorCreator(); QxtStandardItemEditorCreator* lineEditCreator = new QxtStandardItemEditorCreator(); // spin boxes for degrees between -180 and 180 spinBoxCreator->setDefaultPropertyValue("minimum", -180); spinBoxCreator->setDefaultPropertyValue("maximum", 180); // line edits for passwords lineEditCreator->setDefaultPropertyValue("echoMode", QLineEdit::Password); factory->registerEditor(QVariant::Int, spinBoxCreator); factory->registerEditor(QVariant::String, lineEditCreator); QItemEditorFactory::setDefaultFactory(factory); \endcode Setting default properties above makes sure that spin boxes have ranges from -180 to 180 and line editors' echo mode is set to QLineEdit::Password. \sa QStandardItemEditorCreator */ template class QXT_GUI_EXPORT QxtStandardItemEditorCreator : public QxtItemEditorCreatorBase, public QStandardItemEditorCreator { public: /*! Constructs a new QxtStandardItemEditorCreator. */ inline QxtStandardItemEditorCreator() : QStandardItemEditorCreator() { } /*! \reimp */ inline QWidget* createWidget(QWidget* parent) const { return initializeEditor(QStandardItemEditorCreator::createWidget(parent)); } }; #endif // QXTSTANDARDITEMEDITORCREATOR_H libqxt-0.6.2/src/gui/qxtstars.cpp000066400000000000000000000237211215241066400170000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtstars.h" #include #include #include #include class QxtStarsPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtStars) QxtStarsPrivate(); int pixelPosToRangeValue(int pos) const; inline int pick(const QPoint& pt) const; QStyleOptionSlider getStyleOption() const; QSize getStarSize() const; int snapBackPosition; bool readOnly; QSize starSize; QPainterPath star; }; QxtStarsPrivate::QxtStarsPrivate() : snapBackPosition(0), readOnly(false) { star.moveTo(14.285716, -43.352104); star.lineTo(38.404536, 9.1654726); star.lineTo(95.804846, 15.875014); star.lineTo(53.310787, 55.042197); star.lineTo(64.667306, 111.7065); star.lineTo(14.285714, 83.395573); star.lineTo(-36.095881, 111.7065); star.lineTo(-24.739359, 55.042198); star.lineTo(-67.233416, 15.875009); star.lineTo(-9.8331075, 9.1654728); star.closeSubpath(); } int QxtStarsPrivate::pixelPosToRangeValue(int pos) const { const QxtStars* p = &qxt_p(); QStyleOptionSlider opt = getStyleOption(); QRect gr = p->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, p); QRect sr = p->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, p); int sliderMin, sliderMax, sliderLength; gr.setSize(qxt_p().sizeHint()); if (p->orientation() == Qt::Horizontal) { sliderLength = sr.width(); sliderMin = gr.x(); sliderMax = gr.right() - sliderLength + 1; } else { sliderLength = sr.height(); sliderMin = gr.y(); sliderMax = gr.bottom() - sliderLength + 1; } return QStyle::sliderValueFromPosition(p->minimum(), p->maximum(), pos - sliderMin, sliderMax - sliderMin, opt.upsideDown); } inline int QxtStarsPrivate::pick(const QPoint& pt) const { return qxt_p().orientation() == Qt::Horizontal ? pt.x() : pt.y(); } // TODO: get rid of this in Qt 4.3 QStyleOptionSlider QxtStarsPrivate::getStyleOption() const { const QxtStars* p = &qxt_p(); QStyleOptionSlider opt; opt.initFrom(p); opt.subControls = QStyle::SC_None; opt.activeSubControls = QStyle::SC_None; opt.orientation = p->orientation(); opt.maximum = p->maximum(); opt.minimum = p->minimum(); opt.upsideDown = (p->orientation() == Qt::Horizontal) ? (p->invertedAppearance() != (opt.direction == Qt::RightToLeft)) : (!p->invertedAppearance()); opt.direction = Qt::LeftToRight; // we use the upsideDown option instead opt.sliderPosition = p->sliderPosition(); opt.sliderValue = p->value(); opt.singleStep = p->singleStep(); opt.pageStep = p->pageStep(); if (p->orientation() == Qt::Horizontal) opt.state |= QStyle::State_Horizontal; return opt; } QSize QxtStarsPrivate::getStarSize() const { QSize size = starSize; if (!size.isValid() || size.isNull()) { const int width = qxt_p().style()->pixelMetric(QStyle::PM_SmallIconSize); size = QSize(width, width); } return size; } /*! \class QxtStars \inmodule QxtGui \brief The QxtStars widget is a stars assessment widget. QxtStars is an optionally interactive stars assessment widget. By default, orientation is Qt::Horizontal and range is from \c 0 to \c 5. The stars are rendered accoring to palette with the following color roles: \table \header \o ColorRole \o Element \row \o QPalette::Text \o outlines \row \o QPalette::Base \o unselected stars \row \o QPalette::Highlight \o selected stars \endtable \image qxtstars.png "QxtStars in action." */ /*! Constructs a new QxtStars with \a parent. */ QxtStars::QxtStars(QWidget* parent) : QAbstractSlider(parent) { QXT_INIT_PRIVATE(QxtStars); setOrientation(Qt::Horizontal); setFocusPolicy(Qt::FocusPolicy(style()->styleHint(QStyle::SH_Button_FocusPolicy))); setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); setRange(0, 5); } /*! Destructs the stars. */ QxtStars::~QxtStars() {} /*! \property QxtStars::readOnly \brief whether stars are adjustable In read-only mode, the user is not able to change the value. The default value is \c false. */ bool QxtStars::isReadOnly() const { return qxt_d().readOnly; } void QxtStars::setReadOnly(bool readOnly) { if (qxt_d().readOnly != readOnly) { qxt_d().readOnly = readOnly; if (readOnly) setFocusPolicy(Qt::NoFocus); else setFocusPolicy(Qt::FocusPolicy(style()->styleHint(QStyle::SH_Button_FocusPolicy))); } } /*! \property QxtStars::starSize \brief the size of star icons The default value is QStyle::PM_SmallIconSize. */ QSize QxtStars::starSize() const { return qxt_d().starSize; } void QxtStars::setStarSize(const QSize& size) { if (qxt_d().starSize != size) { qxt_d().starSize = size; updateGeometry(); update(); } } /*! \reimp */ QSize QxtStars::sizeHint() const { return minimumSizeHint(); } /*! \reimp */ QSize QxtStars::minimumSizeHint() const { QSize size = qxt_d().getStarSize(); size.rwidth() *= maximum() - minimum(); if (orientation() == Qt::Vertical) size.transpose(); return size; } /*! \reimp */ void QxtStars::paintEvent(QPaintEvent* event) { QAbstractSlider::paintEvent(event); QPainter painter(this); painter.save(); painter.setPen(palette().color(QPalette::Text)); painter.setRenderHint(QPainter::Antialiasing); const bool invert = invertedAppearance(); const QSize size = qxt_d().getStarSize(); const QRectF star = qxt_d().star.boundingRect(); painter.scale(size.width() / star.width(), size.height() / star.height()); const int count = maximum() - minimum(); if (orientation() == Qt::Horizontal) { painter.translate(-star.x(), -star.y()); if (invert != isRightToLeft()) painter.translate((count - 1) * star.width(), 0); } else { painter.translate(-star.x(), -star.y()); if (!invert) painter.translate(0, (count - 1) * star.height()); } for (int i = 0; i < count; ++i) { if (value() > minimum() + i) painter.setBrush(palette().highlight()); else painter.setBrush(palette().base()); painter.drawPath(qxt_d().star); if (orientation() == Qt::Horizontal) painter.translate(invert != isRightToLeft() ? -star.width() : star.width(), 0); else painter.translate(0, invert ? star.height() : -star.height()); } painter.restore(); if (hasFocus()) { QStyleOptionFocusRect opt; opt.initFrom(this); opt.rect.setSize(sizeHint()); style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, &painter, this); } } /*! \reimp */ void QxtStars::keyPressEvent(QKeyEvent* event) { if (qxt_d().readOnly) { event->ignore(); return; } QAbstractSlider::keyPressEvent(event); } /*! \reimp */ void QxtStars::mousePressEvent(QMouseEvent* event) { if (qxt_d().readOnly) { event->ignore(); return; } QAbstractSlider::mousePressEvent(event); if (maximum() == minimum() || (event->buttons() ^ event->button())) { event->ignore(); return; } event->accept(); QStyleOptionSlider opt = qxt_d().getStyleOption(); const QRect sliderRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); const QPoint center = sliderRect.center() - sliderRect.topLeft(); const int pos = qxt_d().pixelPosToRangeValue(qxt_d().pick(event->pos() - center)); setSliderPosition(pos); triggerAction(SliderMove); setRepeatAction(SliderNoAction); qxt_d().snapBackPosition = pos; update(); } /*! \reimp */ void QxtStars::mouseMoveEvent(QMouseEvent* event) { if (qxt_d().readOnly) { event->ignore(); return; } QAbstractSlider::mouseMoveEvent(event); event->accept(); int newPosition = qxt_d().pixelPosToRangeValue(qxt_d().pick(event->pos())); QStyleOptionSlider opt = qxt_d().getStyleOption(); int m = style()->pixelMetric(QStyle::PM_MaximumDragDistance, &opt, this); if (m >= 0) { QRect r = rect(); r.adjust(-m, -m, m, m); if (!r.contains(event->pos())) newPosition = qxt_d().snapBackPosition; } setSliderPosition(newPosition); } /*! \reimp */ void QxtStars::mouseReleaseEvent(QMouseEvent* event) { if (qxt_d().readOnly) { event->ignore(); return; } QAbstractSlider::mouseReleaseEvent(event); if (event->buttons()) { event->ignore(); return; } event->accept(); setRepeatAction(SliderNoAction); } libqxt-0.6.2/src/gui/qxtstars.h000066400000000000000000000041241215241066400164410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSTARS_H #define QXTSTARS_H #include #include "qxtglobal.h" class QxtStarsPrivate; class QXT_GUI_EXPORT QxtStars : public QAbstractSlider { Q_OBJECT QXT_DECLARE_PRIVATE(QxtStars) Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly) Q_PROPERTY(QSize starSize READ starSize WRITE setStarSize) public: explicit QxtStars(QWidget* parent = 0); virtual ~QxtStars(); bool isReadOnly() const; void setReadOnly(bool readOnly); QSize starSize() const; void setStarSize(const QSize& size); virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; protected: virtual void keyPressEvent(QKeyEvent* event); virtual void mousePressEvent(QMouseEvent* event); virtual void mouseMoveEvent(QMouseEvent* event); virtual void mouseReleaseEvent(QMouseEvent* event); virtual void paintEvent(QPaintEvent* event); }; #endif // QXTSTARS_H libqxt-0.6.2/src/gui/qxtstringspinbox.cpp000066400000000000000000000107201215241066400205500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtstringspinbox.h" class QxtStringSpinBoxPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtStringSpinBox) int startsWith(const QString& start, QString& string) const; QStringList strings; }; int QxtStringSpinBoxPrivate::startsWith(const QString& start, QString& string) const { const int size = strings.size(); for (int i = 0; i < size; ++i) { if (strings.at(i).startsWith(start, Qt::CaseInsensitive)) { // found string = strings.at(i); return i; } } // not found return -1; } /*! \class QxtStringSpinBox \inmodule QxtGui \brief The QxtStringSpinBox widget is a spin box with string items. QxtStringSpinBox is spin box that takes strings. QxtStringSpinBox allows the user to choose a value by clicking the up and down buttons or by pressing Up or Down on the keyboard to increase or decrease the value currently displayed. The user can also type the value in manually. \image qxtstringspinbox.png "QxtStringSpinBox in Cleanlooks style." */ /*! Constructs a new QxtStringSpinBox with \a pParent. */ QxtStringSpinBox::QxtStringSpinBox(QWidget* pParent) : QSpinBox(pParent) { setRange(0, 0); } /*! Destructs the spin box. */ QxtStringSpinBox::~QxtStringSpinBox() {} /*! \property QxtStringSpinBox::strings \brief the string items of the spin box. */ const QStringList& QxtStringSpinBox::strings() const { return qxt_d().strings; } void QxtStringSpinBox::setStrings(const QStringList& strings) { qxt_d().strings = strings; setRange(0, strings.size() - 1); if (!strings.isEmpty()) setValue(0); } /*! \reimp */ void QxtStringSpinBox::fixup(QString& input) const { // just attempt to change the input string to be valid according to the string list // no need to result in a valid string, callers of this function are responsible to // re-test the validity afterwards // try finding a string from the list which starts with input input = input.simplified(); if (!input.isEmpty()) { qxt_d().startsWith(input, input); } } /*! \reimp */ QValidator::State QxtStringSpinBox::validate(QString& input, int& pos) const { // Invalid: input is invalid according to the string list // Intermediate: it is likely that a little more editing will make the input acceptable // (e.g. the user types "A" and stringlist contains "ABC") // Acceptable: the input is valid. Q_UNUSED(pos); QString temp; QValidator::State state = QValidator::Invalid; if (qxt_d().strings.contains(input)) { // exact match state = QValidator::Acceptable; } else if (input.isEmpty() || qxt_d().startsWith(input, temp) != -1) { // still empty or some string in the list starts with input state = QValidator::Intermediate; } // else invalid return state; } /*! \reimp */ QString QxtStringSpinBox::textFromValue(int value) const { Q_ASSERT(qxt_d().strings.isEmpty() || (value >= 0 && value < qxt_d().strings.size())); return qxt_d().strings.isEmpty() ? QLatin1String("") : qxt_d().strings.at(value); } /*! \reimp */ int QxtStringSpinBox::valueFromText(const QString& text) const { return qxt_d().strings.indexOf(text); } libqxt-0.6.2/src/gui/qxtstringspinbox.h000066400000000000000000000036521215241066400202230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSTRINGSPINBOX_H #define QXTSTRINGSPINBOX_H #include #include "qxtglobal.h" class QxtStringSpinBoxPrivate; class QXT_GUI_EXPORT QxtStringSpinBox : public QSpinBox { Q_OBJECT QXT_DECLARE_PRIVATE(QxtStringSpinBox) Q_PROPERTY(QStringList strings READ strings WRITE setStrings) public: explicit QxtStringSpinBox(QWidget* pParent = 0); virtual ~QxtStringSpinBox(); const QStringList& strings() const; void setStrings(const QStringList& strings); virtual void fixup(QString& input) const; virtual QValidator::State validate(QString& input, int& pos) const; protected: virtual QString textFromValue(int value) const; virtual int valueFromText(const QString& text) const; }; #endif // QXTSTRINGSPINBOX_H libqxt-0.6.2/src/gui/qxtstringvalidator.cpp000066400000000000000000000235141215241066400210600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtstringvalidator.h" #include "qxtstringvalidator_p.h" #include #include #include #include QxtStringValidatorPrivate::QxtStringValidatorPrivate() : isUserModel(false) , model(0) , cs(Qt::CaseSensitive) , lookupRole(Qt::EditRole) , userFlags(Qt::MatchWrap) , lookupStartModelIndex(QModelIndex()) {} QModelIndex QxtStringValidatorPrivate::lookupPartialMatch(const QString &value) const { //a empty string is always invalid if (value.isEmpty()) return QModelIndex(); Qt::MatchFlags matchFlags = Qt::MatchStartsWith | userFlags; if (cs == Qt::CaseSensitive) matchFlags |= Qt::MatchCaseSensitive; return lookup(value, matchFlags); } QModelIndex QxtStringValidatorPrivate::lookupExactMatch(const QString &value) const { Qt::MatchFlags matchFlags = Qt::MatchFixedString | userFlags; if (cs == Qt::CaseSensitive) matchFlags |= Qt::MatchCaseSensitive; return lookup(value, matchFlags); } QModelIndex QxtStringValidatorPrivate::lookup(const QString &value, const Qt::MatchFlags &matchFlags) const { QModelIndex startIndex = lookupStartModelIndex.isValid() ? lookupStartModelIndex : model->index(0, 0); QModelIndexList list = model->match(startIndex, lookupRole, value, 1, matchFlags); if (list.size() > 0) return list[0]; return QModelIndex(); } /* \class QxtStringValidator \inmodule QxtGui \brief The QxtStringValidator class provides validation on a QStringList or a QAbstractItemModel It provides a String based validation in a stringlist or a custom model. QxtStringValidator uses QAbstractItemModel::match() to validate the input. For a partial match it returns QValidator::Intermediate and for a full match QValidator::Acceptable. Example usage: \code QLineEdit * testLineEdit = new QLineEdit(); QStringList testList; testList << "StringTestString" << "sTrInGCaSe"<< "StringTest"<< "String"<< "Foobar"<< "BarFoo"<< "QxtLib"; QxtStringValidator *validator = new QxtStringValidator(ui.lineEdit); validator->setStringList(testList); //change lookup case sensitivity validator->setCaseSensitivity(Qt::CaseInsensitive); testLineEdit->setValidator(validator); \endcode */ /*! Constructs a validator object with a parent object that accepts any string in the stringlist. */ QxtStringValidator::QxtStringValidator(QObject * parent) : QValidator(parent) { QXT_INIT_PRIVATE(QxtStringValidator); } QxtStringValidator::~QxtStringValidator(void) {} /*! Fixes up the string input if there is no exact match in the stringlist/model. The default implementation does nothing */ void QxtStringValidator::fixup(QString & input) const { qDebug() << "Fixup called"; /*we can not choose whats the correct fixup, if a user needs a fixup he has to do it himself using the first match in the model is just wrong, because thats what QCompleter should do */ QValidator::fixup(input); } /*! uses stringlist as new validation list if a model was set before it is not deleted */ void QxtStringValidator::setStringList(const QStringList &stringList) { //delete model only if it is a model created by us if (qxt_d().model && !qxt_d().isUserModel) { delete qxt_d().model; qxt_d().model = 0; } qxt_d().isUserModel = false; qxt_d().lookupStartModelIndex = QModelIndex(); qxt_d().lookupRole = Qt::EditRole; qxt_d().model = new QStringListModel(stringList, this); } /*! Returns Acceptable if the string input matches a item in the stringlist. Returns Intermediate if the string input matches a item in the stringlist partial or if input is empty. Returns Invalid otherwise. Note: A partial match means the beginning of the strings are matching: qxtL matches qxtLib but not testqxtLib */ QValidator::State QxtStringValidator::validate(QString & input, int & pos) const { Q_UNUSED(pos); // no model or a empty model has only Acceptable values (like no validator was set) if (!qxt_d().model) return QValidator::Acceptable; if (qxt_d().model->rowCount() == 0) return QValidator::Acceptable; if (input.isEmpty()) return QValidator::Intermediate; if (qxt_d().lookupExactMatch(input).isValid()) { qDebug() << input << " is QValidator::Acceptable"; return QValidator::Acceptable; } if (qxt_d().lookupPartialMatch(input).isValid()) { qDebug() << input << " is QValidator::Intermediate"; return QValidator::Intermediate; } qDebug() << input << " is QValidator::Invalid"; return QValidator::Invalid; } /*! Returns the startModelIndex. Note: The return value will only we valid if the user has set the model with setLookupModel(). \sa setStartModelIndex() */ QModelIndex QxtStringValidator::startModelIndex() const { if (qxt_d().isUserModel && qxt_d().model) { if (qxt_d().lookupStartModelIndex.isValid()) return qxt_d().lookupStartModelIndex; else return qxt_d().model->index(0, 0); } return QModelIndex(); } /*! Returns if recursive lookup is enabled. \sa setRecursiveLookup() */ bool QxtStringValidator::recursiveLookup() const { if (qxt_d().userFlags & Qt::MatchRecursive) return true; return false; } /*! Returns if wrapping lookup is enabled. \sa setWrappingLookup() */ bool QxtStringValidator::wrappingLookup() const { if (qxt_d().userFlags & Qt::MatchWrap) return true; return false; } /*! Returns the used model if it was set by the user. \sa setLookupModel() */ QAbstractItemModel * QxtStringValidator::lookupModel() const { if (qxt_d().isUserModel) return qxt_d().model; return 0; } /*! Returns Qt::CaseSensitive if the QxtStringValidator is matched case sensitively; otherwise returns Qt::CaseInsensitive. \sa setCaseSensitivity() */ Qt::CaseSensitivity QxtStringValidator::caseSensitivity() const { return qxt_d().cs; } /*! Sets case sensitive matching to cs. If cs is Qt::CaseSensitive, inp matches input but not INPUT. The default is Qt::CaseSensitive. \sa caseSensitivity() */ void QxtStringValidator::setCaseSensitivity(Qt::CaseSensitivity caseSensitivity) { qxt_d().cs = caseSensitivity; } /*! Sets the index the search should start at The default is QModelIndex(0,0). Note: this is set to default when the model changes. Changing the startModelIndex is only possible if the validator uses a userdefined model and the modelindex comes from the used model \sa startModelIndex() */ void QxtStringValidator::setStartModelIndex(const QModelIndex &index) { if (index.model() == qxt_d().model) qxt_d().lookupStartModelIndex = index; else qWarning() << "ModelIndex from different model. Ignoring."; } /*! If enabled QxtStringValidator searches the entire hierarchy of the model. This is disabled by default. \sa recursiveLookup() */ void QxtStringValidator::setRecursiveLookup(bool enable) { if (enable) qxt_d().userFlags |= Qt::MatchRecursive; else qxt_d().userFlags &= ~Qt::MatchRecursive; } /*! If enabled QxtStringValidator performs a search that wraps around, so that when the search reaches the last item in the model, it begins again at the first item and continues until all items have been examined. This is set by default. \sa wrappingLookup() */ void QxtStringValidator::setWrappingLookup(bool enable) { if (enable) qxt_d().userFlags |= Qt::MatchWrap; else qxt_d().userFlags &= ~Qt::MatchWrap; } /*! Uses model as new validation model. Note: The validator does not take ownership of the model. sa\ lookupModel() */ void QxtStringValidator::setLookupModel(QAbstractItemModel *model) { if (!qxt_d().isUserModel && qxt_d().model) { delete qxt_d().model; qxt_d().model = 0; } qxt_d().lookupRole = Qt::EditRole; qxt_d().isUserModel = true; qxt_d().lookupStartModelIndex = QModelIndex(); qxt_d().model = QPointer(model); } /*! Sets the item role to be used to query the contents of items for validation. Note: this is only possible if the model was set with setLookupModel() This is set to default Value Qt::EditRole when the model changes \sa lookupRole() */ void QxtStringValidator::setLookupRole(const int role) { if (qxt_d().isUserModel) qxt_d().lookupRole = role; } /*! Returns the item role to be used to query the contents of items for validation. \sa setLookupRole() */ int QxtStringValidator::lookupRole() const { return qxt_d().lookupRole; } libqxt-0.6.2/src/gui/qxtstringvalidator.h000066400000000000000000000045361215241066400205300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSTRINGVALIDATOR_H_INCLUDED #define QXTSTRINGVALIDATOR_H_INCLUDED #include #include #include #include "qxtglobal.h" class QxtStringValidatorPrivate; QT_FORWARD_DECLARE_CLASS(QAbstractItemModel) class QXT_GUI_EXPORT QxtStringValidator : public QValidator { Q_OBJECT public: QxtStringValidator(QObject * parent); ~QxtStringValidator(); virtual void fixup(QString & input) const; virtual QValidator::State validate(QString & input, int & pos) const; Qt::CaseSensitivity caseSensitivity() const; void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity); void setStartModelIndex(const QModelIndex &index); void setStringList(const QStringList &stringList); void setRecursiveLookup(bool enable); void setWrappingLookup(bool enable); void setLookupModel(QAbstractItemModel *model); void setLookupRole(const int role); QModelIndex startModelIndex() const; bool recursiveLookup() const; bool wrappingLookup() const; QAbstractItemModel * lookupModel() const; int lookupRole() const; private: QXT_DECLARE_PRIVATE(QxtStringValidator) }; #endif //QXTSTRINGVALIDATOR_H_INCLUDED libqxt-0.6.2/src/gui/qxtstringvalidator_p.h000066400000000000000000000037041215241066400210430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSTRINGVALIDATOR_P_H_INCLUDED #define QXTSTRINGVALIDATOR_P_H_INCLUDED #include #include #include class QxtStringValidator; class QxtStringValidatorPrivate : public QxtPrivate { public: QxtStringValidatorPrivate(); QXT_DECLARE_PUBLIC(QxtStringValidator) bool isUserModel; QPointer model; Qt::CaseSensitivity cs; int lookupColumn; int lookupRole; Qt::MatchFlags userFlags; QModelIndex lookupStartModelIndex; QModelIndex lookupPartialMatch(const QString &value) const; QModelIndex lookupExactMatch(const QString &value) const; QModelIndex lookup(const QString &value, const Qt::MatchFlags &matchFlags) const; }; #endif //QXTSTRINGVALIDATOR_P_H_INCLUDED libqxt-0.6.2/src/gui/qxtstyleoptionscheduleviewitem.cpp000066400000000000000000000027721215241066400235270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtstyleoptionscheduleviewitem.h" QxtStyleOptionScheduleViewItem::QxtStyleOptionScheduleViewItem() : QStyleOptionViewItem() { //make qstyleoption_cast work version = Version; type = Type; } QxtStyleOptionScheduleViewItem::~QxtStyleOptionScheduleViewItem() { } libqxt-0.6.2/src/gui/qxtstyleoptionscheduleviewitem.h000066400000000000000000000036351215241066400231730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSTYLEOPTIONSCHEDULEVIEWITEM_H #define QXTSTYLEOPTIONSCHEDULEVIEWITEM_H #include #include #include #include /*! @author Benjamin Zeller */ class QxtStyleOptionScheduleViewItem : public QStyleOptionViewItem { public: QxtStyleOptionScheduleViewItem(); ~QxtStyleOptionScheduleViewItem(); enum StyleOptionType { Type = QStyleOption::SO_CustomBase }; enum StyleOptionVersion { Version = 1 }; QVector itemGeometries; mutable QVector *itemPaintCache; QPoint translate; int roundCornersRadius; int itemHeaderHeight; int maxSubItemHeight; }; #endif libqxt-0.6.2/src/gui/qxttablewidget.cpp000066400000000000000000000100021215241066400201230ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxttablewidget.h" #include "qxttablewidget_p.h" #include "qxtitemdelegate.h" QxtTableWidgetPrivate::QxtTableWidgetPrivate() { } void QxtTableWidgetPrivate::informStartEditing(const QModelIndex& index) { QTableWidgetItem* item = qxt_p().itemFromIndex(index); emit qxt_p().itemEditingStarted(item); } void QxtTableWidgetPrivate::informFinishEditing(const QModelIndex& index) { QTableWidgetItem* item = qxt_p().itemFromIndex(index); emit qxt_p().itemEditingFinished(item); } /*! \class QxtTableWidget \inmodule QxtGui \brief The QxtTableWidget class is an extended QTableWidget with additional signals. QxtTableWidget offers a few most commonly requested signals. \image qxttablewidget.png "QxtTableWidget in Plastique style." \sa QxtTableWidgetItem */ /*! \fn QxtTableWidget::itemEditingStarted(QTableWidgetItem* item) This signal is emitted after the editing of \a item has been started. \bold {Note:} The \a item can be \c 0 if no item has been set to the corresponding cell. \sa itemEditingFinished(), QTableWidget::setItem() */ /*! \fn QxtTableWidget::itemEditingFinished(QTableWidgetItem* item) This signal is emitted after the editing of \a item has been finished. \sa itemEditingStarted() */ /*! \fn QxtTableWidget::itemCheckStateChanged(QxtTableWidgetItem* item) This signal is emitted whenever the check state of \a item has changed. \bold {Note:} Use QxtTableWidgetItem in order to enable this feature. \sa QxtTableWidgetItem, QTableWidgetItem::checkState() */ /*! Constructs a new QxtTableWidget with \a parent. */ QxtTableWidget::QxtTableWidget(QWidget* parent) : QTableWidget(parent) { QXT_INIT_PRIVATE(QxtTableWidget); setItemPrototype(new QxtTableWidgetItem); QxtItemDelegate* delegate = new QxtItemDelegate(this); connect(delegate, SIGNAL(editingStarted(const QModelIndex&)), &qxt_d(), SLOT(informStartEditing(const QModelIndex&))); connect(delegate, SIGNAL(editingFinished(const QModelIndex&)), &qxt_d(), SLOT(informFinishEditing(const QModelIndex&))); setItemDelegate(delegate); } /*! Constructs a new QxtTableWidget with \a rows, \a columns and \a parent. */ QxtTableWidget::QxtTableWidget(int rows, int columns, QWidget* parent) : QTableWidget(rows, columns, parent) { QXT_INIT_PRIVATE(QxtTableWidget); setItemPrototype(new QxtTableWidgetItem); QxtItemDelegate* delegate = new QxtItemDelegate(this); connect(delegate, SIGNAL(editingStarted(const QModelIndex&)), &qxt_d(), SLOT(informStartEditing(const QModelIndex&))); connect(delegate, SIGNAL(editingFinished(const QModelIndex&)), &qxt_d(), SLOT(informFinishEditing(const QModelIndex&))); setItemDelegate(delegate); } /*! Destructs the table widget. */ QxtTableWidget::~QxtTableWidget() {} libqxt-0.6.2/src/gui/qxttablewidget.h000066400000000000000000000035231215241066400176020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTABLEWIDGET_H #define QXTTABLEWIDGET_H #include #include "qxtglobal.h" #include "qxttablewidgetitem.h" class QxtTableWidgetPrivate; class QXT_GUI_EXPORT QxtTableWidget : public QTableWidget { Q_OBJECT QXT_DECLARE_PRIVATE(QxtTableWidget) friend class QxtTableWidgetItem; public: explicit QxtTableWidget(QWidget* parent = 0); explicit QxtTableWidget(int rows, int columns, QWidget* parent = 0); virtual ~QxtTableWidget(); Q_SIGNALS: void itemEditingStarted(QTableWidgetItem* item); void itemEditingFinished(QTableWidgetItem* item); void itemCheckStateChanged(QxtTableWidgetItem* item); }; #endif // QXTTABLEWIDGET_H libqxt-0.6.2/src/gui/qxttablewidget_p.h000066400000000000000000000031421215241066400201160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTABLEWIDGET_P_H #define QXTTABLEWIDGET_P_H #include "qxttablewidget.h" class QxtItemDelegate; class QxtTableWidgetPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtTableWidget) QxtTableWidgetPrivate(); private Q_SLOTS: void informStartEditing(const QModelIndex& index); void informFinishEditing(const QModelIndex& index); }; #endif // QXTTABLEWIDGET_P_H libqxt-0.6.2/src/gui/qxttablewidgetitem.cpp000066400000000000000000000067651215241066400210270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxttablewidgetitem.h" #include "qxttablewidget.h" /*! \class QxtTableWidgetItem \inmodule QxtGui \brief The QxtTableWidgetItem class is an extended QTableWidgetItem. QxtTableWidgetItem provides means for offering check state change signals and convenience methods for testing and setting flags. \sa QxtTableWidget */ /*! Constructs a new QxtTableWidgetItem with \a type. */ QxtTableWidgetItem::QxtTableWidgetItem(int type) : QTableWidgetItem(type) { } /*! Constructs a new QxtTableWidgetItem with \a text and \a type. */ QxtTableWidgetItem::QxtTableWidgetItem(const QString& text, int type) : QTableWidgetItem(text, type) { } /*! Constructs a new QxtTableWidgetItem with \a icon, \a text and \a type. */ QxtTableWidgetItem::QxtTableWidgetItem(const QIcon& icon, const QString& text, int type) : QTableWidgetItem(icon, text, type) { } /*! Constructs a copy of \a other. */ QxtTableWidgetItem::QxtTableWidgetItem(const QTableWidgetItem& other) : QTableWidgetItem(other) { } /*! Destructs the table widget item. */ QxtTableWidgetItem::~QxtTableWidgetItem() { } /*! Returns \c true if the \a flag is set, otherwise \c false. \sa setFlag(), QTableWidgetItem::flags(), Qt::ItemFlag */ bool QxtTableWidgetItem::testFlag(Qt::ItemFlag flag) const { return (flags() & flag); } /*! If \a enabled is \c true, the item \a flag is enabled; otherwise, it is disabled. \sa testFlag(), QTableWidgetItem::setFlags(), Qt::ItemFlag */ void QxtTableWidgetItem::setFlag(Qt::ItemFlag flag, bool enabled) { if (enabled) setFlags(flags() | flag); else setFlags(flags() & ~flag); } /*! \reimp */ void QxtTableWidgetItem::setData(int role, const QVariant& value) { if (role == Qt::CheckStateRole) { const Qt::CheckState newState = static_cast(value.toInt()); const Qt::CheckState oldState = static_cast(data(role).toInt()); QTableWidgetItem::setData(role, value); if (newState != oldState) { QxtTableWidget* table = qobject_cast(tableWidget()); if (table) { emit table->itemCheckStateChanged(this); } } } else { QTableWidgetItem::setData(role, value); } } libqxt-0.6.2/src/gui/qxttablewidgetitem.h000066400000000000000000000035721215241066400204650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTABLEWIDGETITEM_H #define QXTTABLEWIDGETITEM_H #include #include "qxtnamespace.h" #include "qxtglobal.h" class QXT_GUI_EXPORT QxtTableWidgetItem : public QTableWidgetItem { public: explicit QxtTableWidgetItem(int type = Type); explicit QxtTableWidgetItem(const QString& text, int type = Type); explicit QxtTableWidgetItem(const QIcon& icon, const QString& text, int type = Type); explicit QxtTableWidgetItem(const QTableWidgetItem& other); virtual ~QxtTableWidgetItem(); bool testFlag(Qt::ItemFlag flag) const; void setFlag(Qt::ItemFlag flag, bool enabled = true); virtual void setData(int role, const QVariant& value); }; #endif // QXTTABLEWIDGETITEM_H libqxt-0.6.2/src/gui/qxttabwidget.cpp000066400000000000000000000332361215241066400176200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxttabwidget.h" #include "qxttabwidget_p.h" #include #include #include #include #include #include QxtTabWidgetPrivate::QxtTabWidgetPrivate() : always(true), policy(Qt::DefaultContextMenu) { } int QxtTabWidgetPrivate::tabIndexAt(const QPoint& pos) const { const int count = qxt_p().count(); const QTabBar* tabBar = qxt_p().tabBar(); for (int i = 0; i < count; ++i) if (tabBar->tabRect(i).contains(pos)) return i; return -1; } void QxtTabWidgetPrivate::setMovieFrame(int frame) { Q_UNUSED(frame); QMovie* movie = static_cast(sender()); if (movie) { int index = animations.indexOf(movie); if (index != -1) qxt_p().setTabIcon(index, movie->currentPixmap()); } } /*! \class QxtTabWidget \inmodule QxtGui \brief The QxtTabWidget class is an extended QTabWidget. QxtTabWidget provides some convenience for handling tab specific context menus and animations. Example usage: \code QxtTabWidget* tabWidget = new QxtTabWidget(); tabWidget->addTab(tab0, "1"); tabWidget->addTab(tab1, "2"); QList actions0; actions0 << new QAction("Quisque", tab0) << new QAction("Aenean", tab0); QList actions1; actions1 << new QAction("Phasellus", tab1) << new QAction("Maecenas", tab1); tabWidget->setTabContextMenuPolicy(Qt::ActionsContextMenu); tabWidget->addTabActions(0, actions0); tabWidget->addTabActions(1, actions1); \endcode \image qxttabwidget.png "QxtTabWidget in WindowsXP style." */ /*! \fn QxtTabWidget::tabContextMenuRequested(int index, const QPoint& globalPos) This signal is emitted whenever the context menu is requested over tab at \a index at \a globalPos. */ /*! Constructs a new QxtTabWidget with \a parent. */ QxtTabWidget::QxtTabWidget(QWidget* parent) : QTabWidget(parent) { QXT_INIT_PRIVATE(QxtTabWidget); } /*! Destructs the tab widget. */ QxtTabWidget::~QxtTabWidget() { } /*! \property QxtTabWidget::alwaysShowTabBar \brief whether the tab bar is shown always regardless of how many tabs there are. The default value of this property is \c true. Set this property to \c false if you want to show the tab bar only in case there are more than one tabs. */ bool QxtTabWidget::alwaysShowTabBar() const { return qxt_d().always; } void QxtTabWidget::setAlwaysShowTabBar(bool always) { qxt_d().always = always; tabBar()->setVisible(always || count() > 1); } /*! \property QxtTabWidget::tabContextMenuPolicy \brief how the tab specific context menus are handled. The default value of this property is Qt::DefaultContextMenu, which means that the tabContextMenuEvent() handler is called. Other values are Qt::NoContextMenu, Qt::PreventContextMenu (since Qt 4.2), Qt::ActionsContextMenu, and Qt::CustomContextMenu. With Qt::CustomContextMenu, the signal tabContextMenuRequested() is emitted. \sa tabContextMenuEvent(), tabContextMenuRequested(), tabActions() */ Qt::ContextMenuPolicy QxtTabWidget::tabContextMenuPolicy() const { return qxt_d().policy; } void QxtTabWidget::setTabContextMenuPolicy(Qt::ContextMenuPolicy policy) { qxt_d().policy = policy; } /*! Appends the \a action to the list of actions of the tab at \a index. \sa removeTabAction(), insertTabAction(), tabActions() */ void QxtTabWidget::addTabAction(int index, QAction* action) { insertTabAction(index, 0, action); } /*! This convenience function creates a new action with \a text. The function adds the newly created action to the list of actions of the tab at \a index, and returns it. \sa addTabAction() */ QAction* QxtTabWidget::addTabAction(int index, const QString& text) { return addTabAction(index, QIcon(), text, 0, 0); } /*! This convenience function creates a new action with \a icon and \a text. The function adds the newly created action to the list of actions of the tab at \a index, and returns it. \sa addTabAction() */ QAction* QxtTabWidget::addTabAction(int index, const QIcon& icon, const QString& text) { return addTabAction(index, icon, text, 0, 0); } /*! This convenience function creates a new action with \a text and an optional \a shortcut. The action's triggered() signal is connected to the \a receiver's \a member slot. The function adds the newly created action to the list of actions of the tab at \a index, and returns it. \bold {Note:} In order to make it possible for the shortcut to work even when the context menu is not open, the action must be added to a visible widget. The corresponding tab is a good alternative. \code QWidget* tab = createNewTab(); tabWidget->addTab(tab, title); QAction* action = tabWidget->addTabAction(index, tr("Close"), this, SLOT(closeCurrentTab()), tr("Ctrl+W")); tab->addAction(act); \endcode \sa addTabAction(), QWidget::addAction() */ QAction* QxtTabWidget::addTabAction(int index, const QString& text, const QObject* receiver, const char* member, const QKeySequence& shortcut) { return addTabAction(index, QIcon(), text, receiver, member, shortcut); } /*! This convenience function creates a new action with \a icon, \a text and an optional \a shortcut. The action's triggered() signal is connected to the \a receiver's \a member slot. The function adds the newly created action to the list of actions of the tab at \a index, and returns it. \sa addTabAction() */ QAction* QxtTabWidget::addTabAction(int index, const QIcon& icon, const QString& text, const QObject* receiver, const char* member, const QKeySequence& shortcut) { QAction* action = new QAction(icon, text, this); addTabAction(index, action); if (receiver && member) connect(action, SIGNAL(triggered()), receiver, member); action->setShortcut(shortcut); return action; } /*! Appends the \a actions to the list of actions of the tab at \a index. \sa removeTabAction(), addTabAction() */ void QxtTabWidget::addTabActions(int index, QList actions) { foreach(QAction* action, actions) { insertTabAction(index, 0, action); } } /*! Clears the list of actions of the tab at \a index. \bold {Note:} Only actions owned by the tab widget are deleted. \sa removeTabAction(), addTabAction() */ void QxtTabWidget::clearTabActions(int index) { Q_ASSERT(index >= 0 && index < qxt_d().actions.count()); while (qxt_d().actions[index].count()) { QAction* action = qxt_d().actions[index].last(); removeTabAction(index, action); if (action->parent() == this) delete action; } } /*! Inserts the \a action to the list of actions of the tab at \a index, before the action \a before. It appends the action if \a before is \c 0. \sa removeTabAction(), addTabAction(), tabContextMenuPolicy, tabActions() */ void QxtTabWidget::insertTabAction(int index, QAction* before, QAction* action) { Q_ASSERT(index >= 0 && index < qxt_d().actions.count()); if (!action) { qWarning("QxtTabWidget::insertTabAction: Attempt to insert a null action"); return; } const Actions& actions = qxt_d().actions.at(index); if (actions.contains(action)) removeTabAction(index, action); int pos = actions.indexOf(before); if (pos < 0) { before = 0; pos = actions.count(); } qxt_d().actions[index].insert(pos, action); QActionEvent e(QEvent::ActionAdded, action, before); QApplication::sendEvent(this, &e); } /*! Inserts the \a actions to the list of actions of the tab at \a index, before the action \a before. It appends the action if \a before is \c 0. \sa removeAction(), QMenu, insertAction(), contextMenuPolicy */ void QxtTabWidget::insertTabActions(int index, QAction* before, QList actions) { foreach(QAction* action, actions) { insertTabAction(index, before, action); } } /*! Removes the action \a action from the list of actions of the tab at \a index. \bold {Note:} The removed action is not deleted. \sa insertTabAction(), tabActions(), insertTabAction() */ void QxtTabWidget::removeTabAction(int index, QAction* action) { Q_ASSERT(index >= 0 && index < qxt_d().actions.count()); if (!action) { qWarning("QxtTabWidget::removeTabAction: Attempt to remove a null action"); return; } if (qxt_d().actions[index].removeAll(action)) { QActionEvent e(QEvent::ActionRemoved, action); QApplication::sendEvent(this, &e); } } /*! Returns the (possibly empty) list of actions for the tab at \a index. \sa tabContextMenuPolicy, insertTabAction(), removeTabAction() */ QList QxtTabWidget::tabActions(int index) const { Q_ASSERT(index >= 0 && index < qxt_d().actions.count()); return qxt_d().actions.at(index); } /*! Returns the animation of the tab at \a index or \c 0 if no animation has been set. \sa setTabAnimation() */ QMovie* QxtTabWidget::tabAnimation(int index) const { Q_ASSERT(index >= 0 && index < qxt_d().animations.count()); return qxt_d().animations.at(index); } /*! Sets the \a animation of the tab at \a index and optionally \a start the animation. \sa tabAnimation() */ void QxtTabWidget::setTabAnimation(int index, QMovie* animation, bool start) { Q_ASSERT(index >= 0 && index < qxt_d().animations.count()); delete takeTabAnimation(index); qxt_d().animations[index] = animation; if (animation) { connect(animation, SIGNAL(frameChanged(int)), &qxt_d(), SLOT(setMovieFrame(int))); if (start) animation->start(); } } /*! This is an overloaded member function, provided for convenience. The QMovie animation is constructed from \a fileName with \c this as parent. The animation is started if \a start is \c true. \sa setTabAnimation() */ void QxtTabWidget::setTabAnimation(int index, const QString& fileName, bool start) { setTabAnimation(index, new QMovie(fileName, QByteArray(), this), start); } /*! Removes the animation of the tab at \a index and returns it. \sa tabAnimation() */ QMovie* QxtTabWidget::takeTabAnimation(int index) { Q_ASSERT(index >= 0 && index < qxt_d().animations.count()); QMovie* animation = qxt_d().animations.at(index); qxt_d().animations[index] = 0; return animation; } /*! \reimp */ void QxtTabWidget::tabInserted(int index) { Q_ASSERT(index >= 0); Q_ASSERT(index <= qxt_d().actions.count()); Q_ASSERT(index <= qxt_d().animations.count()); qxt_d().actions.insert(index, Actions()); qxt_d().animations.insert(index, 0); tabBar()->setVisible(qxt_d().always || count() > 1); } /*! \reimp */ void QxtTabWidget::tabRemoved(int index) { Q_ASSERT(index >= 0); Q_ASSERT(index < qxt_d().actions.count()); Q_ASSERT(index < qxt_d().animations.count()); qxt_d().actions.removeAt(index); qxt_d().animations.removeAt(index); tabBar()->setVisible(qxt_d().always || count() > 1); } /*! \reimp */ void QxtTabWidget::contextMenuEvent(QContextMenuEvent* event) { const QPoint& pos = event->pos(); if (!tabBar()->geometry().contains(pos)) return QTabWidget::contextMenuEvent(event); const int index = qxt_d().tabIndexAt(event->pos()); switch (qxt_d().policy) { case Qt::NoContextMenu: event->ignore(); break; case Qt::PreventContextMenu: event->accept(); break; case Qt::ActionsContextMenu: if (index != -1 && qxt_d().actions.at(index).count()) { QMenu::exec(qxt_d().actions.at(index), event->globalPos()); } break; case Qt::CustomContextMenu: if (index != -1) { emit tabContextMenuRequested(index, event->globalPos()); } break; case Qt::DefaultContextMenu: default: if (index != -1) { tabContextMenuEvent(index, event); } break; } } /*! This event handler, for event \a event, can be reimplemented in a subclass to receive context menu events for the tab at \a index. The handler is called when \bold tabContextMenuPolicy is Qt::DefaultContextMenu. The default implementation ignores the context menu event. \sa tabContextMenuPolicy, tabContextMenuRequested() */ void QxtTabWidget::tabContextMenuEvent(int index, QContextMenuEvent* event) { Q_UNUSED(index); event->ignore(); } libqxt-0.6.2/src/gui/qxttabwidget.h000066400000000000000000000064271215241066400172670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTABWIDGET_H #define QXTTABWIDGET_H #include #include "qxtnamespace.h" #include "qxtglobal.h" class QxtTabWidgetPrivate; class QXT_GUI_EXPORT QxtTabWidget : public QTabWidget { Q_OBJECT QXT_DECLARE_PRIVATE(QxtTabWidget) Q_PROPERTY(bool alwaysShowTabBar READ alwaysShowTabBar WRITE setAlwaysShowTabBar) Q_PROPERTY(Qt::ContextMenuPolicy tabContextMenuPolicy READ tabContextMenuPolicy WRITE setTabContextMenuPolicy) public: explicit QxtTabWidget(QWidget* parent = 0); virtual ~QxtTabWidget(); bool alwaysShowTabBar() const; void setAlwaysShowTabBar(bool always); Qt::ContextMenuPolicy tabContextMenuPolicy() const; void setTabContextMenuPolicy(Qt::ContextMenuPolicy policy); void addTabAction(int index, QAction* action); QAction* addTabAction(int index, const QString& text); QAction* addTabAction(int index, const QIcon& icon, const QString& text); QAction* addTabAction(int index, const QString& text, const QObject* receiver, const char* member, const QKeySequence& shortcut = 0); QAction* addTabAction(int index, const QIcon& icon, const QString& text, const QObject* receiver, const char* member, const QKeySequence& shortcut = 0); void addTabActions(int index, QList actions); void clearTabActions(int index); void insertTabAction(int index, QAction* before, QAction* action); void insertTabActions(int index, QAction* before, QList actions); void removeTabAction(int index, QAction* action); QList tabActions(int index) const; QMovie* tabAnimation(int index) const; void setTabAnimation(int index, QMovie* animation, bool start = true); void setTabAnimation(int index, const QString& fileName, bool start = true); QMovie* takeTabAnimation(int index); Q_SIGNALS: void tabContextMenuRequested(int index, const QPoint& globalPos); protected: virtual void tabInserted(int index); virtual void tabRemoved(int index); virtual void contextMenuEvent(QContextMenuEvent* event); virtual void tabContextMenuEvent(int index, QContextMenuEvent* event); }; #endif // QXTTABWIDGET_H libqxt-0.6.2/src/gui/qxttabwidget_p.h000066400000000000000000000032621215241066400176000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTABWIDGET_P_H #define QXTTABWIDGET_P_H #include "qxttabwidget.h" typedef QList Actions; class QxtTabWidgetPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtTabWidget) QxtTabWidgetPrivate(); int tabIndexAt(const QPoint& pos) const; bool always; QList actions; Qt::ContextMenuPolicy policy; QList animations; public Q_SLOTS: void setMovieFrame(int frame); }; #endif // QXTQXTTABWIDGET_P_H libqxt-0.6.2/src/gui/qxttooltip.cpp000066400000000000000000000245161215241066400173410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxttooltip.h" #include "qxttooltip_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include static const Qt::WindowFlags FLAGS = Qt::ToolTip; QxtToolTipPrivate* QxtToolTipPrivate::self = 0; QxtToolTipPrivate* QxtToolTipPrivate::instance() { if (!self) self = new QxtToolTipPrivate(); return self; } QxtToolTipPrivate::QxtToolTipPrivate() : QWidget(qApp->desktop(), FLAGS) { setWindowFlags(FLAGS); vbox = new QVBoxLayout(this); setPalette(QToolTip::palette()); setWindowOpacity(style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, 0, this) / 255.0); layout()->setMargin(style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, 0, this)); qApp->installEventFilter(this); } QxtToolTipPrivate::~QxtToolTipPrivate() { qApp->removeEventFilter(this); // not really necessary but rather for completeness :) self = 0; } void QxtToolTipPrivate::show(const QPoint& pos, QWidget* tooltip, QWidget* parent, const QRect& rect) { Q_ASSERT(tooltip && parent); if (!isVisible()) { int scr = 0; if (QApplication::desktop()->isVirtualDesktop()) scr = QApplication::desktop()->screenNumber(pos); else scr = QApplication::desktop()->screenNumber(this); setParent(QApplication::desktop()->screen(scr)); setWindowFlags(FLAGS); setToolTip(tooltip); currentParent = parent; currentRect = rect; move(calculatePos(scr, pos)); QWidget::show(); } } void QxtToolTipPrivate::setToolTip(QWidget* tooltip) { for (int i = 0; i < vbox->count(); ++i) { QLayoutItem* item = layout()->takeAt(i); if (item->widget()) item->widget()->hide(); } vbox->addWidget(tooltip); tooltip->show(); } void QxtToolTipPrivate::enterEvent(QEvent* event) { Q_UNUSED(event); hideLater(); } void QxtToolTipPrivate::paintEvent(QPaintEvent* event) { Q_UNUSED(event); QStylePainter painter(this); QStyleOptionFrame opt; opt.initFrom(this); painter.drawPrimitive(QStyle::PE_PanelTipLabel, opt); } bool QxtToolTipPrivate::eventFilter(QObject* object, QEvent* event) { switch (event->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: { // accept only modifiers const QKeyEvent* keyEvent = static_cast(event); const int key = keyEvent->key(); const Qt::KeyboardModifiers mods = keyEvent->modifiers(); if ((mods & Qt::KeyboardModifierMask) || (key == Qt::Key_Shift || key == Qt::Key_Control || key == Qt::Key_Alt || key == Qt::Key_Meta)) break; } case QEvent::Leave: case QEvent::WindowActivate: case QEvent::WindowDeactivate: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::FocusIn: case QEvent::FocusOut: case QEvent::Wheel: hideLater(); break; case QEvent::MouseMove: { const QPoint pos = static_cast(event)->pos(); if (!currentRect.isNull() && !currentRect.contains(pos)) { hideLater(); } break; } case QEvent::ToolTip: { // eat appropriate tooltip events QWidget* widget = static_cast(object); if (tooltips.contains(widget)) { QHelpEvent* helpEvent = static_cast(event); const QRect area = tooltips.value(widget).second; if (area.isNull() || area.contains(helpEvent->pos())) { show(helpEvent->globalPos(), tooltips.value(widget).first, widget, area); return true; } } } default: break; } return false; } void QxtToolTipPrivate::hideLater() { currentRect = QRect(); if (isVisible()) QTimer::singleShot(0, this, SLOT(hide())); } QPoint QxtToolTipPrivate::calculatePos(int scr, const QPoint& eventPos) const { #ifdef Q_WS_MAC QRect screen = QApplication::desktop()->availableGeometry(scr); #else QRect screen = QApplication::desktop()->screenGeometry(scr); #endif QPoint p = eventPos; p += QPoint(2, #ifdef Q_WS_WIN 24 #else 16 #endif ); QSize s = sizeHint(); if (p.x() + s.width() > screen.x() + screen.width()) p.rx() -= 4 + s.width(); if (p.y() + s.height() > screen.y() + screen.height()) p.ry() -= 24 + s.height(); if (p.y() < screen.y()) p.setY(screen.y()); if (p.x() + s.width() > screen.x() + screen.width()) p.setX(screen.x() + screen.width() - s.width()); if (p.x() < screen.x()) p.setX(screen.x()); if (p.y() + s.height() > screen.y() + screen.height()) p.setY(screen.y() + screen.height() - s.height()); return p; } /*! \class QxtToolTip \inmodule QxtGui \brief The QxtToolTip class provides means for showing any arbitrary widget as a tooltip. QxtToolTip provides means for showing any arbitrary widget as a tooltip. \bold {Note:} The rich text support of QToolTip already makes it possible to show heavily customized tooltips with lists, tables, embedded images and such. However, for example dynamically created images like thumbnails cause problems. Basically the only way is to dump the thumbnail to a temporary file to be able to embed it into HTML. This is where QxtToolTip steps in. A generated thumbnail may simply be set on a QLabel which is then shown as a tooltip. Yet another use case is a tooltip with dynamically changing content. \image qxttooltip.png "QxtToolTip in action." \warning Added tooltip widgets remain in the memory for the lifetime of the application or until they are removed/deleted. Do NOT flood your application up with lots of complex tooltip widgets or it will end up being a resource hog. QToolTip is sufficient for most of the cases! */ /*! \internal */ QxtToolTip::QxtToolTip() { } /*! Shows the \a tooltip at \a pos for \a parent at \a rect. \sa hide() */ void QxtToolTip::show(const QPoint& pos, QWidget* tooltip, QWidget* parent, const QRect& rect) { QxtToolTipPrivate::instance()->show(pos, tooltip, parent, rect); } /*! Hides the tooltip. \sa show() */ void QxtToolTip::hide() { QxtToolTipPrivate::instance()->hide(); } /*! Returns the tooltip for \a parent. \sa setToolTip() */ QWidget* QxtToolTip::toolTip(QWidget* parent) { Q_ASSERT(parent); QWidget* tooltip = 0; if (!QxtToolTipPrivate::instance()->tooltips.contains(parent)) qWarning("QxtToolTip::toolTip: Unknown parent"); else tooltip = QxtToolTipPrivate::instance()->tooltips.value(parent).first; return tooltip; } /*! Sets the \a tooltip to be shown for \a parent. An optional \a rect may also be passed. \sa toolTip() */ void QxtToolTip::setToolTip(QWidget* parent, QWidget* tooltip, const QRect& rect) { Q_ASSERT(parent); if (tooltip) { // set tooltip->hide(); QxtToolTipPrivate::instance()->tooltips[parent] = qMakePair(QPointer(tooltip), rect); } else { // remove if (!QxtToolTipPrivate::instance()->tooltips.contains(parent)) qWarning("QxtToolTip::setToolTip: Unknown parent"); else QxtToolTipPrivate::instance()->tooltips.remove(parent); } } /*! Returns the rect on which tooltip is shown for \a parent. \sa setToolTipRect() */ QRect QxtToolTip::toolTipRect(QWidget* parent) { Q_ASSERT(parent); QRect rect; if (!QxtToolTipPrivate::instance()->tooltips.contains(parent)) qWarning("QxtToolTip::toolTipRect: Unknown parent"); else rect = QxtToolTipPrivate::instance()->tooltips.value(parent).second; return rect; } /*! Sets the \a rect on which tooltip is shown for \a parent. \sa toolTipRect() */ void QxtToolTip::setToolTipRect(QWidget* parent, const QRect& rect) { Q_ASSERT(parent); if (!QxtToolTipPrivate::instance()->tooltips.contains(parent)) qWarning("QxtToolTip::setToolTipRect: Unknown parent"); else QxtToolTipPrivate::instance()->tooltips[parent].second = rect; } /*! Returns the margin of the tooltip. \sa setMargin() */ int QxtToolTip::margin() { return QxtToolTipPrivate::instance()->layout()->margin(); } /*! Sets the \a margin of the tooltip. The default value is QStyle::PM_ToolTipLabelFrameWidth. \sa margin() */ void QxtToolTip::setMargin(int margin) { QxtToolTipPrivate::instance()->layout()->setMargin(margin); } /*! Returns the opacity level of the tooltip. \sa QWidget::windowOpacity() */ qreal QxtToolTip::opacity() { return QxtToolTipPrivate::instance()->windowOpacity(); } /*! Sets the opacity \a level of the tooltip. The default value is QStyle::SH_ToolTipLabel_Opacity. \sa QWidget::setWindowOpacity() */ void QxtToolTip::setOpacity(qreal level) { QxtToolTipPrivate::instance()->setWindowOpacity(level); } libqxt-0.6.2/src/gui/qxttooltip.h000066400000000000000000000040301215241066400167730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTOOLTIP_H #define QXTTOOLTIP_H #include #include #include #include "qxtglobal.h" class QXT_GUI_EXPORT QxtToolTip { QxtToolTip(); public: static void show(const QPoint& pos, QWidget* tooltip, QWidget* parent = 0, const QRect& rect = QRect()); static void hide(); static QWidget* toolTip(QWidget* parent); static void setToolTip(QWidget* parent, QWidget* tooltip, const QRect& rect = QRect()); static QRect toolTipRect(QWidget* parent); static void setToolTipRect(QWidget* parent, const QRect& rect); static int margin(); static void setMargin(int margin); static qreal opacity(); static void setOpacity(qreal level); }; QT_BEGIN_NAMESPACE inline uint qHash(const QPointer key) { return reinterpret_cast(key ? (&*key) : 0); } QT_END_NAMESPACE #endif // QXTTOOLTIP_H libqxt-0.6.2/src/gui/qxttooltip_p.h000066400000000000000000000041631215241066400173210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTOOLTIP_P_H #define QXTTOOLTIP_P_H #include #include #include #include "qxttooltip.h" QT_FORWARD_DECLARE_CLASS(QVBoxLayout) typedef QPointer WidgetPtr; typedef QPair WidgetArea; class QxtToolTipPrivate : public QWidget { Q_OBJECT public: QxtToolTipPrivate(); ~QxtToolTipPrivate(); static QxtToolTipPrivate* instance(); void show(const QPoint& pos, QWidget* tooltip, QWidget* parent = 0, const QRect& rect = QRect()); void setToolTip(QWidget* tooltip); bool eventFilter(QObject* parent, QEvent* event); void hideLater(); QPoint calculatePos(int scr, const QPoint& eventPos) const; QHash tooltips; QVBoxLayout* vbox; protected: void enterEvent(QEvent* event); void paintEvent(QPaintEvent* event); private: static QxtToolTipPrivate* self; QWidget* currentParent; QRect currentRect; }; #endif // QXTTOOLTIP_P_H libqxt-0.6.2/src/gui/qxttreewidget.cpp000066400000000000000000000125231215241066400200050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxttreewidget.h" #include "qxttreewidget_p.h" #include "qxtitemdelegate.h" #include QxtTreeWidgetPrivate::QxtTreeWidgetPrivate() {} QxtItemDelegate* QxtTreeWidgetPrivate::delegate() const { QxtItemDelegate* del = qobject_cast(qxt_p().itemDelegate()); Q_ASSERT(del); return del; } void QxtTreeWidgetPrivate::informStartEditing(const QModelIndex& index) { QTreeWidgetItem* item = qxt_p().itemFromIndex(index); Q_ASSERT(item); emit qxt_p().itemEditingStarted(item); } void QxtTreeWidgetPrivate::informFinishEditing(const QModelIndex& index) { QTreeWidgetItem* item = qxt_p().itemFromIndex(index); Q_ASSERT(item); emit qxt_p().itemEditingFinished(item); } void QxtTreeWidgetPrivate::expandCollapse(QTreeWidgetItem* item) { if (item && !item->parent() && delegate()->decorationStyle() != Qxt::NoDecoration) qxt_p().setItemExpanded(item, !qxt_p().isItemExpanded(item)); } /*! \class QxtTreeWidget \inmodule QxtGui \brief The QxtTreeWidget class is an extended QTreeWidget with additional signals. QxtTreeWidget offers an optional top level item decoration and a few most commonly requested signals. \image qxttreewidget.png "QxtTreeWidget with Qxt::Menulike and Qxt::Buttonlike decoration styles, respectively." \sa QxtTreeWidgetItem */ /*! \fn QxtTreeWidget::itemEditingStarted(QTreeWidgetItem* item) This signal is emitted after the editing of \a item has been started. \sa itemEditingFinished() */ /*! \fn QxtTreeWidget::itemEditingFinished(QTreeWidgetItem* item) This signal is emitted after the editing of \a item has been finished. \sa itemEditingStarted() */ /*! \fn QxtTreeWidget::itemCheckStateChanged(QxtTreeWidgetItem* item) This signal is emitted whenever the check state of \a item has changed. \bold {Note:} Use QxtTreeWidgetItem in order to enable this feature. \sa QxtTreeWidgetItem, QTreeWidgetItem::checkState() */ /*! Constructs a new QxtTreeWidget with \a parent. */ QxtTreeWidget::QxtTreeWidget(QWidget* parent) : QTreeWidget(parent) { QXT_INIT_PRIVATE(QxtTreeWidget); QxtItemDelegate* delegate = new QxtItemDelegate(this); connect(delegate, SIGNAL(editingStarted(const QModelIndex&)), &qxt_d(), SLOT(informStartEditing(const QModelIndex&))); connect(delegate, SIGNAL(editingFinished(const QModelIndex&)), &qxt_d(), SLOT(informFinishEditing(const QModelIndex&))); connect(this, SIGNAL(itemPressed(QTreeWidgetItem*, int)), &qxt_d(), SLOT(expandCollapse(QTreeWidgetItem*))); setItemDelegate(delegate); } /*! Destructs the tree widget. */ QxtTreeWidget::~QxtTreeWidget() {} /*! \property QxtTreeWidget::decorationStyle \brief the top level item decoration style Top level items are decorated according to this property. The default value is Qxt::NoDecoration. \bold {Note:} Setting the property to anything else than Qxt::NoDecoration hides the header and sets QTreeView::rootIsDecorated to \c false (to avoid multiple branch indicators). \sa Qxt::DecorationStyle, QTreeView::rootIsDecorated */ Qxt::DecorationStyle QxtTreeWidget::decorationStyle() const { return qxt_d().delegate()->decorationStyle(); } void QxtTreeWidget::setDecorationStyle(Qxt::DecorationStyle style) { if (qxt_d().delegate()->decorationStyle() != style) { qxt_d().delegate()->setDecorationStyle(style); if (style != Qxt::NoDecoration) { setRootIsDecorated(false); header()->hide(); } reset(); } } /*! \property QxtTreeWidget::elideMode \brief the text elide mode The text of a decorated top level item is elided according to this property. The default value is Qt::ElideMiddle. \bold {Note:} The property has effect only for decorated top level items. \sa decorationStyle, Qt::TextElideMode */ Qt::TextElideMode QxtTreeWidget::elideMode() const { return qxt_d().delegate()->elideMode(); } void QxtTreeWidget::setElideMode(Qt::TextElideMode mode) { if (qxt_d().delegate()->elideMode() != mode) { qxt_d().delegate()->setElideMode(mode); reset(); } } libqxt-0.6.2/src/gui/qxttreewidget.h000066400000000000000000000042131215241066400174470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTREEWIDGET_H #define QXTTREEWIDGET_H #include #include "qxttreewidgetitem.h" #include "qxtnamespace.h" #include "qxtglobal.h" class QxtTreeWidgetPrivate; class QXT_GUI_EXPORT QxtTreeWidget : public QTreeWidget { Q_OBJECT QXT_DECLARE_PRIVATE(QxtTreeWidget) Q_PROPERTY(Qxt::DecorationStyle decorationStyle READ decorationStyle WRITE setDecorationStyle) Q_PROPERTY(Qt::TextElideMode elideMode READ elideMode WRITE setElideMode) friend class QxtTreeWidgetItem; public: explicit QxtTreeWidget(QWidget* parent = 0); virtual ~QxtTreeWidget(); Qxt::DecorationStyle decorationStyle() const; void setDecorationStyle(Qxt::DecorationStyle style); Qt::TextElideMode elideMode() const; void setElideMode(Qt::TextElideMode mode); Q_SIGNALS: void itemEditingStarted(QTreeWidgetItem* item); void itemEditingFinished(QTreeWidgetItem* item); void itemCheckStateChanged(QxtTreeWidgetItem* item); }; #endif // QXTTREEWIDGET_H libqxt-0.6.2/src/gui/qxttreewidget_p.h000066400000000000000000000032611215241066400177700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTREEWIDGET_P_H #define QXTTREEWIDGET_P_H #include "qxttreewidget.h" class QxtItemDelegate; class QxtTreeWidgetPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtTreeWidget) QxtTreeWidgetPrivate(); QxtItemDelegate* delegate() const; private Q_SLOTS: void informStartEditing(const QModelIndex& index); void informFinishEditing(const QModelIndex& index); void expandCollapse(QTreeWidgetItem* item); }; #endif // QXTTREEWIDGET_P_H libqxt-0.6.2/src/gui/qxttreewidgetitem.cpp000066400000000000000000000111471215241066400206650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxttreewidgetitem.h" #include "qxttreewidget.h" /*! \class QxtTreeWidgetItem \inmodule QxtGui \brief The QxtTreeWidgetItem class is an extended QTreeWidgetItem. QxtTreeWidgetItem provides means for offering check state change signals and convenience methods for testing and setting flags. \sa QxtTreeWidget */ /*! Constructs a new QxtTreeWidgetItem with \a type. */ QxtTreeWidgetItem::QxtTreeWidgetItem(int type) : QTreeWidgetItem(type) { } /*! Constructs a new QxtTreeWidgetItem with \a strings and \a type. */ QxtTreeWidgetItem::QxtTreeWidgetItem(const QStringList& strings, int type) : QTreeWidgetItem(strings, type) { } /*! Constructs a new QxtTreeWidgetItem with \a parent and \a type. */ QxtTreeWidgetItem::QxtTreeWidgetItem(QTreeWidget* parent, int type) : QTreeWidgetItem(parent, type) { } /*! Constructs a new QxtTreeWidgetItem with \a parent, \a strings and \a type. */ QxtTreeWidgetItem::QxtTreeWidgetItem(QTreeWidget* parent, const QStringList& strings, int type) : QTreeWidgetItem(parent, strings, type) { } /*! Constructs a new QxtTreeWidgetItem with \a parent, \a preceding and \a type. */ QxtTreeWidgetItem::QxtTreeWidgetItem(QTreeWidget* parent, QTreeWidgetItem* preceding, int type) : QTreeWidgetItem(parent, preceding, type) { } /*! Constructs a new QxtTreeWidgetItem with \a parent and \a type. */ QxtTreeWidgetItem::QxtTreeWidgetItem(QTreeWidgetItem* parent, int type) : QTreeWidgetItem(parent, type) { } /*! Constructs a new QxtTreeWidgetItem with \a parent, \a strings and \a type. */ QxtTreeWidgetItem::QxtTreeWidgetItem(QTreeWidgetItem* parent, const QStringList& strings, int type) : QTreeWidgetItem(parent, strings, type) { } /*! Constructs a new QxtTreeWidgetItem with \a parent, \a preceding and \a type. */ QxtTreeWidgetItem::QxtTreeWidgetItem(QTreeWidgetItem* parent, QTreeWidgetItem* preceding, int type) : QTreeWidgetItem(parent, preceding, type) { } /*! Constructs a copy of \a other. */ QxtTreeWidgetItem::QxtTreeWidgetItem(const QxtTreeWidgetItem& other) : QTreeWidgetItem(other) { } /*! Destructs the tree widget item. */ QxtTreeWidgetItem::~QxtTreeWidgetItem() { } /*! Returns \c true if the \a flag is set, otherwise \c false. \sa setFlag(), QTreeWidgetItem::flags(), Qt::ItemFlag */ bool QxtTreeWidgetItem::testFlag(Qt::ItemFlag flag) const { return (flags() & flag); } /*! If \a enabled is \c true, the item \a flag is enabled; otherwise, it is disabled. \sa testFlag(), QTreeWidgetItem::setFlags(), Qt::ItemFlag */ void QxtTreeWidgetItem::setFlag(Qt::ItemFlag flag, bool enabled) { if (enabled) setFlags(flags() | flag); else setFlags(flags() & ~flag); } /*! \reimp */ void QxtTreeWidgetItem::setData(int column, int role, const QVariant& value) { if (role == Qt::CheckStateRole) { const Qt::CheckState newState = static_cast(value.toInt()); const Qt::CheckState oldState = static_cast(data(column, role).toInt()); QTreeWidgetItem::setData(column, role, value); if (newState != oldState) { QxtTreeWidget* tree = qobject_cast(treeWidget()); if (tree) { emit tree->itemCheckStateChanged(this); } } } else { QTreeWidgetItem::setData(column, role, value); } } libqxt-0.6.2/src/gui/qxttreewidgetitem.h000066400000000000000000000045121215241066400203300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTREEWIDGETITEM_H #define QXTTREEWIDGETITEM_H #include #include "qxtnamespace.h" #include "qxtglobal.h" class QXT_GUI_EXPORT QxtTreeWidgetItem : public QTreeWidgetItem { public: explicit QxtTreeWidgetItem(int type = Type); explicit QxtTreeWidgetItem(const QStringList& strings, int type = Type); explicit QxtTreeWidgetItem(QTreeWidget* parent, int type = Type); explicit QxtTreeWidgetItem(QTreeWidget* parent, const QStringList& strings, int type = Type); explicit QxtTreeWidgetItem(QTreeWidget* parent, QTreeWidgetItem* preceding, int type = Type); explicit QxtTreeWidgetItem(QTreeWidgetItem* parent, int type = Type); explicit QxtTreeWidgetItem(QTreeWidgetItem* parent, const QStringList& strings, int type = Type); explicit QxtTreeWidgetItem(QTreeWidgetItem* parent, QTreeWidgetItem* preceding, int type = Type); explicit QxtTreeWidgetItem(const QxtTreeWidgetItem& other); virtual ~QxtTreeWidgetItem(); bool testFlag(Qt::ItemFlag flag) const; void setFlag(Qt::ItemFlag flag, bool enabled = true); virtual void setData(int column, int role, const QVariant& value); }; #endif // QXTTREEWIDGETITEM_H libqxt-0.6.2/src/gui/qxtwindowsystem.cpp000066400000000000000000000102661215241066400204200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtwindowsystem.h" #include /*! \class QxtWindowSystem \inmodule QxtGui \brief The QxtWindowSystem class provides means for accessing native windows. \bold {Note:} The underlying window system might or might not allow one to alter states of windows belonging to other processes. \warning QxtWindowSystem is portable in principle, but be careful while using it since you are probably about to do something non-portable. \section1 Advanced example usage: \code class NativeWindow : public QWidget { public: NativeWindow(WId wid) { QWidget::create(wid, false, false); // window, initializeWindow, destroyOldWindow } ~NativeWindow() { QWidget::destroy(false, false); // destroyWindow, destroySubWindows } }; \endcode \code WindowList windows = QxtWindowSystem::windows(); QStringList titles = QxtWindowSystem::windowTitles(); bool ok = false; QString title = QInputDialog::getItem(0, "Choose Window", "Choose a window to be hid:", titles, 0, false, &ok); if (ok) { int index = titles.indexOf(title); if (index != -1) { NativeWindow window(windows.at(index)); window.hide(); } } \endcode \bold {Note:} Currently supported platforms are \bold X11 and \bold Windows. */ /*! \fn QxtWindowSystem::windows() Returns the list of native window system identifiers. \sa QApplication::topLevelWidgets(), windowTitles() */ /*! \fn QxtWindowSystem::activeWindow() Returns the native window system identifier of the active window if any. \sa QApplication::activeWindow() */ /*! \fn QxtWindowSystem::findWindow(const QString& title) Returns the native window system identifier of the window if any with given \a title. Example usage: \code WId wid = QxtWindowSystem::findWindow("Mail - Kontact"); QPixmap screenshot = QPixmap::grabWindow(wid); \endcode \sa QWidget::find() */ /*! \fn QxtWindowSystem::windowAt(const QPoint& pos) Returns the native window system identifier of the window if any at \a pos. \sa QApplication::widgetAt() */ /*! \fn QxtWindowSystem::windowTitle(WId window) Returns the title of the native \a window. \sa QWidget::windowTitle(), windowTitles() */ /*! \fn QxtWindowSystem::windowTitles() Returns a list of native window titles. \sa QWidget::windowTitle(), windowTitle(), windows() */ /*! \fn QxtWindowSystem::windowGeometry(WId window) Returns the geometry of the native \a window. \sa QWidget::frameGeometry() */ /*! \fn QxtWindowSystem::idleTime() Returns the system "idle time" ie. the time since last user input in milliseconds. */ QStringList QxtWindowSystem::windowTitles() { WindowList windows = QxtWindowSystem::windows(); QStringList titles; foreach(WId window, windows) titles += QxtWindowSystem::windowTitle(window); return titles; } libqxt-0.6.2/src/gui/qxtwindowsystem.h000066400000000000000000000032621215241066400200630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTWINDOWSYSTEM_H #define QXTWINDOWSYSTEM_H #include #include "qxtglobal.h" typedef QList WindowList; class QXT_GUI_EXPORT QxtWindowSystem { public: static WindowList windows(); static WId activeWindow(); static WId findWindow(const QString& title); static WId windowAt(const QPoint& pos); static QString windowTitle(WId window); static QStringList windowTitles(); static QRect windowGeometry(WId window); static uint idleTime(); }; #endif // QXTWINDOWSYSTEM_H libqxt-0.6.2/src/gui/qxtwindowsystem_win.cpp000066400000000000000000000061151215241066400212730ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtwindowsystem.h" #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0500 #endif #include #include // QT_WA static WindowList qxt_Windows; BOOL CALLBACK qxt_EnumWindowsProc(HWND hwnd, LPARAM lParam) { Q_UNUSED(lParam); if (::IsWindowVisible(hwnd)) qxt_Windows += hwnd; return true; } WindowList QxtWindowSystem::windows() { qxt_Windows.clear(); HDESK hdesk = ::OpenInputDesktop(0, false, DESKTOP_READOBJECTS); ::EnumDesktopWindows(hdesk, qxt_EnumWindowsProc, 0); ::CloseDesktop(hdesk); return qxt_Windows; } WId QxtWindowSystem::activeWindow() { return ::GetForegroundWindow(); } WId QxtWindowSystem::findWindow(const QString& title) { QT_WA({ return ::FindWindow(NULL, (TCHAR*)title.utf16()); }, { return ::FindWindowA(NULL, title.toLocal8Bit()); }); } WId QxtWindowSystem::windowAt(const QPoint& pos) { POINT pt; pt.x = pos.x(); pt.y = pos.y(); return ::WindowFromPoint(pt); } QString QxtWindowSystem::windowTitle(WId window) { QString title; int len = ::GetWindowTextLength(window); if (len >= 0) { TCHAR* buf = new TCHAR[len+1]; len = ::GetWindowText(window, buf, len+1); QT_WA({ title = QString::fromUtf16((const ushort*)buf, len); }, { title = QString::fromLocal8Bit((const char*)buf, len); }); delete[] buf; } return title; } QRect QxtWindowSystem::windowGeometry(WId window) { RECT rc; QRect rect; if (::GetWindowRect(window, &rc)) { rect.setTop(rc.top); rect.setBottom(rc.bottom); rect.setLeft(rc.left); rect.setRight(rc.right); } return rect; } uint QxtWindowSystem::idleTime() { uint idle = -1; LASTINPUTINFO info; info.cbSize = sizeof(LASTINPUTINFO); if (::GetLastInputInfo(&info)) idle = ::GetTickCount() - info.dwTime; return idle; } libqxt-0.6.2/src/gui/qxtwindowsystem_x11.cpp000066400000000000000000000136511215241066400211120ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtGui module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtwindowsystem.h" #include #include #include static WindowList qxt_getWindows(Atom prop) { WindowList res; Atom type = 0; int format = 0; uchar* data = 0; ulong count, after; Display* display = QX11Info::display(); Window window = QX11Info::appRootWindow(); if (XGetWindowProperty(display, window, prop, 0, 1024 * sizeof(Window) / 4, False, AnyPropertyType, &type, &format, &count, &after, &data) == Success) { Window* list = reinterpret_cast(data); for (uint i = 0; i < count; ++i) res += list[i]; if (data) XFree(data); } return res; } WindowList QxtWindowSystem::windows() { static Atom net_clients = 0; if (!net_clients) net_clients = XInternAtom(QX11Info::display(), "_NET_CLIENT_LIST_STACKING", True); return qxt_getWindows(net_clients); } WId QxtWindowSystem::activeWindow() { static Atom net_active = 0; if (!net_active) net_active = XInternAtom(QX11Info::display(), "_NET_ACTIVE_WINDOW", True); return qxt_getWindows(net_active).value(0); } WId QxtWindowSystem::findWindow(const QString& title) { Window result = 0; WindowList list = windows(); foreach (const Window &wid, list) { if (windowTitle(wid) == title) { result = wid; break; } } return result; } WId QxtWindowSystem::windowAt(const QPoint& pos) { Window result = 0; WindowList list = windows(); for (int i = list.size() - 1; i >= 0; --i) { WId wid = list.at(i); if (windowGeometry(wid).contains(pos)) { result = wid; break; } } return result; } QString QxtWindowSystem::windowTitle(WId window) { QString name; char* str = 0; if (XFetchName(QX11Info::display(), window, &str)) name = QString::fromLatin1(str); if (str) XFree(str); return name; } QRect QxtWindowSystem::windowGeometry(WId window) { int x, y; uint width, height, border, depth; Window root, child; Display* display = QX11Info::display(); XGetGeometry(display, window, &root, &x, &y, &width, &height, &border, &depth); XTranslateCoordinates(display, window, root, x, y, &x, &y, &child); static Atom net_frame = 0; if (!net_frame) net_frame = XInternAtom(QX11Info::display(), "_NET_FRAME_EXTENTS", True); QRect rect(x, y, width, height); Atom type = 0; int format = 0; uchar* data = 0; ulong count, after; if (XGetWindowProperty(display, window, net_frame, 0, 4, False, AnyPropertyType, &type, &format, &count, &after, &data) == Success) { // _NET_FRAME_EXTENTS, left, right, top, bottom, CARDINAL[4]/32 if (count == 4) { long* extents = reinterpret_cast(data); rect.adjust(-extents[0], -extents[2], extents[1], extents[3]); } if (data) XFree(data); } return rect; } typedef struct { Window window; /* screen saver window - may not exist */ int state; /* ScreenSaverOff, ScreenSaverOn, ScreenSaverDisabled*/ int kind; /* ScreenSaverBlanked, ...Internal, ...External */ unsigned long til_or_since; /* time til or since screen saver */ unsigned long idle; /* total time since last user input */ unsigned long eventMask; /* currently selected events for this client */ } XScreenSaverInfo; typedef XScreenSaverInfo* (*XScreenSaverAllocInfo)(); typedef Status (*XScreenSaverQueryInfo)(Display* display, Drawable* drawable, XScreenSaverInfo* info); static XScreenSaverAllocInfo _xScreenSaverAllocInfo = 0; static XScreenSaverQueryInfo _xScreenSaverQueryInfo = 0; uint QxtWindowSystem::idleTime() { static bool xssResolved = false; if (!xssResolved) { QLibrary xssLib(QLatin1String("Xss"), 1); if (xssLib.load()) { _xScreenSaverAllocInfo = (XScreenSaverAllocInfo) xssLib.resolve("XScreenSaverAllocInfo"); _xScreenSaverQueryInfo = (XScreenSaverQueryInfo) xssLib.resolve("XScreenSaverQueryInfo"); xssResolved = true; } } uint idle = 0; if (xssResolved) { XScreenSaverInfo* info = _xScreenSaverAllocInfo(); const int screen = QX11Info::appScreen(); Qt::HANDLE rootWindow = QX11Info::appRootWindow(screen); _xScreenSaverQueryInfo(QX11Info::display(), (Drawable*) rootWindow, info); idle = info->idle; if (info) XFree(info); } return idle; } libqxt-0.6.2/src/gui/resources.qrc000066400000000000000000000373431215241066400171310ustar00rootroot00000000000000 resources/flags/C.png resources/flags/AD.png resources/flags/AE.png resources/flags/AF.png resources/flags/AG.png resources/flags/AI.png resources/flags/AL.png resources/flags/AM.png resources/flags/AN.png resources/flags/AO.png resources/flags/AQ.png resources/flags/AR.png resources/flags/AS.png resources/flags/AT.png resources/flags/AU.png resources/flags/AW.png resources/flags/AX.png resources/flags/AZ.png resources/flags/BA.png resources/flags/BB.png resources/flags/BD.png resources/flags/BE.png resources/flags/BF.png resources/flags/BG.png resources/flags/BH.png resources/flags/BI.png resources/flags/BJ.png resources/flags/BM.png resources/flags/BN.png resources/flags/BO.png resources/flags/BR.png resources/flags/BS.png resources/flags/BT.png resources/flags/BV.png resources/flags/BW.png resources/flags/BY.png resources/flags/BZ.png resources/flags/CA.png resources/flags/CC.png resources/flags/CD.png resources/flags/CF.png resources/flags/CG.png resources/flags/CH.png resources/flags/CI.png resources/flags/CK.png resources/flags/CL.png resources/flags/CM.png resources/flags/CN.png resources/flags/CO.png resources/flags/CR.png resources/flags/CS.png resources/flags/CU.png resources/flags/CV.png resources/flags/CX.png resources/flags/CY.png resources/flags/CZ.png resources/flags/DE.png resources/flags/DJ.png resources/flags/DK.png resources/flags/DM.png resources/flags/DO.png resources/flags/DZ.png resources/flags/EC.png resources/flags/EE.png resources/flags/EG.png resources/flags/EH.png resources/flags/ER.png resources/flags/ES.png resources/flags/ET.png resources/flags/FI.png resources/flags/FJ.png resources/flags/FK.png resources/flags/FM.png resources/flags/FO.png resources/flags/FR.png resources/flags/FX.png resources/flags/GA.png resources/flags/GB.png resources/flags/GD.png resources/flags/GE.png resources/flags/GF.png resources/flags/GG.png resources/flags/GH.png resources/flags/GI.png resources/flags/GL.png resources/flags/GM.png resources/flags/GN.png resources/flags/GP.png resources/flags/GQ.png resources/flags/GR.png resources/flags/GS.png resources/flags/GT.png resources/flags/GU.png resources/flags/GW.png resources/flags/GY.png resources/flags/HK.png resources/flags/HM.png resources/flags/HN.png resources/flags/HR.png resources/flags/HT.png resources/flags/HU.png resources/flags/ID.png resources/flags/IE.png resources/flags/IL.png resources/flags/IM.png resources/flags/IN.png resources/flags/IO.png resources/flags/IQ.png resources/flags/IR.png resources/flags/IS.png resources/flags/IT.png resources/flags/JE.png resources/flags/JM.png resources/flags/JO.png resources/flags/JP.png resources/flags/KE.png resources/flags/KG.png resources/flags/KH.png resources/flags/KI.png resources/flags/KM.png resources/flags/KN.png resources/flags/KP.png resources/flags/KR.png resources/flags/KW.png resources/flags/KY.png resources/flags/KZ.png resources/flags/LA.png resources/flags/LB.png resources/flags/LC.png resources/flags/LI.png resources/flags/LK.png resources/flags/LR.png resources/flags/LS.png resources/flags/LT.png resources/flags/LU.png resources/flags/LV.png resources/flags/LY.png resources/flags/MA.png resources/flags/MC.png resources/flags/MD.png resources/flags/ME.png resources/flags/MG.png resources/flags/MH.png resources/flags/MK.png resources/flags/ML.png resources/flags/MM.png resources/flags/MN.png resources/flags/MO.png resources/flags/MP.png resources/flags/MQ.png resources/flags/MR.png resources/flags/MS.png resources/flags/MT.png resources/flags/MU.png resources/flags/MV.png resources/flags/MW.png resources/flags/MX.png resources/flags/MY.png resources/flags/MZ.png resources/flags/NA.png resources/flags/NC.png resources/flags/NE.png resources/flags/NF.png resources/flags/NG.png resources/flags/NI.png resources/flags/NL.png resources/flags/NO.png resources/flags/NP.png resources/flags/NR.png resources/flags/NU.png resources/flags/NZ.png resources/flags/OM.png resources/flags/PA.png resources/flags/PE.png resources/flags/PF.png resources/flags/PG.png resources/flags/PH.png resources/flags/PK.png resources/flags/PL.png resources/flags/PM.png resources/flags/PN.png resources/flags/PR.png resources/flags/PS.png resources/flags/PT.png resources/flags/PW.png resources/flags/PY.png resources/flags/QA.png resources/flags/RE.png resources/flags/RO.png resources/flags/RS.png resources/flags/RU.png resources/flags/RW.png resources/flags/SA.png resources/flags/SB.png resources/flags/SC.png resources/flags/SD.png resources/flags/SE.png resources/flags/SG.png resources/flags/SH.png resources/flags/SI.png resources/flags/SJ.png resources/flags/SK.png resources/flags/SL.png resources/flags/SM.png resources/flags/SN.png resources/flags/SO.png resources/flags/SR.png resources/flags/ST.png resources/flags/SV.png resources/flags/SY.png resources/flags/SZ.png resources/flags/TC.png resources/flags/TD.png resources/flags/TF.png resources/flags/TG.png resources/flags/TH.png resources/flags/TJ.png resources/flags/TK.png resources/flags/TL.png resources/flags/TM.png resources/flags/TN.png resources/flags/TO.png resources/flags/TR.png resources/flags/TT.png resources/flags/TV.png resources/flags/TW.png resources/flags/TZ.png resources/flags/UA.png resources/flags/UG.png resources/flags/UM.png resources/flags/US.png resources/flags/UY.png resources/flags/UZ.png resources/flags/VA.png resources/flags/VC.png resources/flags/VE.png resources/flags/VG.png resources/flags/VI.png resources/flags/VN.png resources/flags/VU.png resources/flags/WF.png resources/flags/WS.png resources/flags/YE.png resources/flags/YT.png resources/flags/ZA.png resources/flags/ZM.png resources/flags/ZW.png libqxt-0.6.2/src/gui/resources/000077500000000000000000000000001215241066400164105ustar00rootroot00000000000000libqxt-0.6.2/src/gui/resources/flags/000077500000000000000000000000001215241066400175045ustar00rootroot00000000000000libqxt-0.6.2/src/gui/resources/flags/AD.png000066400000000000000000000006141215241066400204770ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME ;"4.IDAT8͓N`kKDL 8..^7{ .&.N!Pw<9ONN+ιUcBgyٵÙgp^}Qg7q|c=pSz(O8hwěA8G-a}`d6wAwЎ43F jL[u`540@&I8_`K,jęĵ7$hB8DjJcT#`Ӝj厱vP5Djnbt',{Ѝ ]Fx_~ͨIENDB`libqxt-0.6.2/src/gui/resources/flags/AE.png000066400000000000000000000002701215241066400204760ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME6ZIDAT(c<' ԇ<8)b0 6A~ :jǩnpae%%0fĖ^=%c nq1*BbIENDB`libqxt-0.6.2/src/gui/resources/flags/AF.png000066400000000000000000000006031215241066400204770ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIMEom%IDAT8Փ1KefJF_6I$!@_!hAZ:K;km3N|{7<`] -Sg? x/!2I,0Uf?XZEi>?!s3 sN +QQD^~y% z$X@b}Ѧ?5mCPl$NCHYhSQ2eB+* Ġ!1&>_l޻mB9=|t1(nD+12ʱ+VrGnD-MB3$g(f||ADDcaĪI~V|y lx]e,ӊ78FC* AQ q e˶`\Txsc hX#ԯwI`Z kdX+x$}!Zc·x蘔S=\hkKɶ/pʶ9hZ@vpĽYE:,g*N[SD6QWa;uM%ڬh~6*{Œk]sXBH1%R:B+f(/KT3kZ;[$h3u?>uR)Y|,QqM}|,Q9Mx|eGɳ4>B&IENDB`libqxt-0.6.2/src/gui/resources/flags/AI.png000066400000000000000000000010331215241066400205000ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME#wYIDAT(kqzQk,ʵktMq .NjUhE"␀RT4KhCL!`19ypT!J~xyEf\{]"K=k0<c{7|(=:}_*36:|LJ0eeƽ̤1ϭ0 Ǔ6y(՗2oR 4 LSѤ\o[ DA0Z5%F/ӨT)|*E8DbLB x}u6+|'TAndž6+Gt@]NR^?ӯ&G FN1^M2G,& ], [$sq,@qqu+`LOq6@SWdeY&ȟJץo>V̽IENDB`libqxt-0.6.2/src/gui/resources/flags/AL.png000066400000000000000000000006341215241066400205110ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME ;+i0/>IDAT8=JQF}wb!A,ANظ.kk7l+Bl, DI&3,b)1 w8}cC<)ߥ\QmYŽan!ǕEnӘA(7cP4Vɀ;kp2Q+:g։\_xlhȘe YZY ѐi2+ex4vNQaPeX*] 1bX׀87S\{.q=`ݨAW#ĹsE565mSȾgg8WG\&UIENDB`libqxt-0.6.2/src/gui/resources/flags/AM.png000066400000000000000000000002261215241066400205070ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME(08IDAT(c` ia0#ê0f`````,q&9! 2].IENDB`libqxt-0.6.2/src/gui/resources/flags/AN.png000066400000000000000000000003741215241066400205140ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME(r~TIDAT8cO4qY~TB31  QvU f')*WÇ202* ZqqW0| 1H\ ^/>c"ҎҎ- 9o CuIENDB`libqxt-0.6.2/src/gui/resources/flags/AO.png000066400000000000000000000005761215241066400205210ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME  IDAT8͔=/a}Y;;&BATj?@DN/T RBo02_fJǼc'FYHXZ: L7b\%\(ߋ9J #pOt a*#R<>K>[Fx?7 K/I/Ik+yZ7UZxK]:p:2R5'YO`lX!QNlX5d xW9=R7!z^UW}n(xIENDB`libqxt-0.6.2/src/gui/resources/flags/AQ.png000066400000000000000000000007601215241066400205160ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME # Qt6>IDAT8;/CaUN+Zuk*1█D,Ql$X,bHFt:q:Z9m|4jL&Հ rv#cN0G7,ԃ z oDamKA:̸]fFl=P}EP-ծ @S(;$`utRTtZufzOqTX //Xŝ %&==֚BEyʶ~kACeanͤ8O5@Q;ʓVR" ѸOE LL DA9xe Ǟ$\z B3.HA(nIENDB`libqxt-0.6.2/src/gui/resources/flags/AS.png000066400000000000000000000007171215241066400205220ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME 7S˨qIDAT(KKBϽ^ 󁢙(ED%PAvѢ?(h(h/ q!A D.̊iW6-Y93g`3VLnn'%Fĵ ;n'~${*|A(c0Q?qD  '; ,#C6%W!i}A7h%QQuyҚ|NF&Eb>)?c)=I^+Pq,Aò5i˅*(X!brͣ5 X\<=[4e9~)mtd JYjFSs_QI ?@&AR 7ѿ* ,aIENDB`libqxt-0.6.2/src/gui/resources/flags/AT.png000066400000000000000000000002061215241066400205140ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 7zU(IDAT8c!?yC`ќ7t  -qIENDB`libqxt-0.6.2/src/gui/resources/flags/AU.png000066400000000000000000000010431215241066400205150ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME)4IDAT(=LSazUI ĦBBD4ġء$ &,@c" @I;'&f:Մh`M@P z2!c+Gzc #vMi(@<=J >ReM}'gy`몕gݼV eEI$B(l ]Uusp qAt@ɷLFvZ,h}1]}.EFue66IgKmF|_Zz޸E64Ԇ[mxnpgy<)π~mW;m2W 897^"/MM62O`̘1`*%ym'E"nN"wr`hԃ_O$ B$Izrc| ?*.{;IENDB`libqxt-0.6.2/src/gui/resources/flags/AW.png000066400000000000000000000003521215241066400205210ustar00rootroot00000000000000PNG  IHDRm?hsBIT|dIDAT8ch s)L0 3Cobp_cXc0##C(ݚ ,3}< B0V`fH|u͜bC懿 +b( ^C`{'ˆA0E m ^5&,$ IENDB`libqxt-0.6.2/src/gui/resources/flags/AX.png000066400000000000000000000003501215241066400205200ustar00rootroot00000000000000PNG  IHDR+1sBIT|dIDAT8cd^ p$ᪧ[ K) VI"z*C Z(I%Z1)joicM0>'?6IL, xEĪkANǤX%,2@åraC Zl`e ,&*+[IENDB`libqxt-0.6.2/src/gui/resources/flags/AZ.png000066400000000000000000000003301215241066400205200ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME #fCzIDAT(cd9`ljR@cW9tsÇ qL0(84_ju1x{d$H=UIENDB`libqxt-0.6.2/src/gui/resources/flags/BB.png000066400000000000000000000005001215241066400204700ustar00rootroot00000000000000PNG  IHDRm?hsBIT|dIDAT8͓jPD שK_@W(.1/[(88U*8PHE*2%^|ñhMEgc]#j { .X722 BS2cR}JJPSQZ +껂yt*GZJڌ}W\ruw|bfMN|RSN1xn~Mu⷗:䔽M sIp̎1Nڤ95IGyu%IENDB`libqxt-0.6.2/src/gui/resources/flags/BD.png000066400000000000000000000004561215241066400205040ustar00rootroot00000000000000PNG  IHDR cbKGDtIME 59 s3IDAT8cd@D CXI*}ǐ 03LacxH0/B_< 8q,VY? @1csAc5o߸_oH7X'" Gd6aVxb3-.2 S);C&^C$, &dc!A;ٸIENDB`libqxt-0.6.2/src/gui/resources/flags/BE.png000066400000000000000000000002221215241066400204740ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME (?}4IDAT8cd``π,`e*g7/Ïfq\ZpPF 5xQ`8XE`IENDB`libqxt-0.6.2/src/gui/resources/flags/BF.png000066400000000000000000000003771215241066400205100ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME "N IDAT81 1?(z %hc)^DNA3hYK "SM1F]Ò V? m4Z=s!.IG>`{k/bg 6>x z2G;~~>"7IIENDB`libqxt-0.6.2/src/gui/resources/flags/BG.png000066400000000000000000000002261215241066400205020ustar00rootroot00000000000000PNG  IHDR cbKGDtIME %58IDAT8c&Z:4 fQ]|&ƒ0x&axMMh4`} %fIENDB`libqxt-0.6.2/src/gui/resources/flags/BH.png000066400000000000000000000004471215241066400205100ustar00rootroot00000000000000PNG  IHDR cbKGDtIME fJIDAT8c47k0Y۹KDFlv0|>tdY ~Aj×'I6po ocx3o÷ WI6 ď;]# e`obxn+O2o~aZ1u#Ed\5YDC|xg0"Y?30 Q9tW.1IENDB`libqxt-0.6.2/src/gui/resources/flags/BI.png000066400000000000000000000011731215241066400205060ustar00rootroot00000000000000PNG  IHDR cbKGDtIMEG0_IDAT8OHq?6fSf"%heBt<,/BuDQ 1:DYII:]:QvȈMJQC6jI}xͻҳLvEϳ_bhCzUA%tq|~Ɠ-Ge8@HW͛83ɔ'o ]+-`ahdٳ$qm=_#d󈷯N=V7/:r:S `] @[QoR1Imv撿;xIu5U^rADx _{X꛶~%ޭLh50EDfs/q@q9=E ͮiU04KH0rn0_=eׄl3ާa>,b"58NvL%p=V7AzjÔټLvvY!3MKOm {rgjKEڊe!9c-7daIG"8Oyn ͎j0.Q( J,IENDB`libqxt-0.6.2/src/gui/resources/flags/BJ.png000066400000000000000000000002441215241066400205050ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME FLFIDAT8cdhπ}*>5F RO|n0+F_;8I5x7!sIENDB`libqxt-0.6.2/src/gui/resources/flags/BM.png000066400000000000000000000010501215241066400205040ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME :4#AIDAT(OHq?sjPp47W䭉(XB]Z.+O Q;DAaFD AQ[Uޗ|yH My4E<:'ћ\J☿Csfps3; l[>ˏGwpM KM0iBXJ-vt]G\F$&{Ip:WRt `u$9<yi_q{4JEa{,F}g'9{Ó-c2z&g5͚FR|?/0>Ok{ DkuQgy0x{3GSqA}mpƽ;y5E3u߂q)8clml| #K*)85=|(Zxő3({c%adUX.U\W0( OIENDB`libqxt-0.6.2/src/gui/resources/flags/BN.png000066400000000000000000000010401215241066400205040ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME '(jIDAT(NQFϝ2X*S"vC԰sCB],uGpS\΍ m*iEMն әMK0o's>e(}G( SDvHQz,EfPxߍ>6x]FPx6"0%wEKq Y:bs$.P3ҏVhW8J"21{-[|ĂTuvo# &cDN8?tt }f/qA:%W媇Yr[.o,e^(T'Z8a{>[s7 ̦ЃTaot+I``C# Om^vl cATL:Iָ?68ߤh搷`0W>H@k}\@lS, ԆX?swXYJmIENDB`libqxt-0.6.2/src/gui/resources/flags/BS.png000066400000000000000000000003601215241066400205150ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME  c,IDAT(cd0ϐP @M🁅3!8CD:k# 9pQ}u  u R5AH# n  l(˜BR?0X2"  EIENDB`libqxt-0.6.2/src/gui/resources/flags/BT.png000066400000000000000000000011361215241066400205200ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 66=aIDAT8ӽkSa}ɽI/E6 bAN" t.JZ`qpPRjJhlUL>8Y6- ;h',V;i- Ti^O Cfl@щiGQ 4 꽀3YܺKǏBWF**k `' C0RKE!c}+%[NIa:C}0Q2Z!BثaP`}=&XwrwiXX*kԃta,́h=;Ϡ#QC' sCtxudnزb@޼BCJ9_CYܧ]U*3 k (x$sk [A,vT$w26't4{mfJ]|b_I^?FGseM"6M}  ElB܅/ cZmpQq ⶁ9R$^9ppUErQVhPj0AY% rIJ-(99WM*6L׶<\mL*|:mB/UbY"L>??qc|!+(B3w0#9z^M46Ksm;7sB&!K71i$\~h>;B鉞]CBثt"@pIENDB`libqxt-0.6.2/src/gui/resources/flags/C.png000066400000000000000000000003131215241066400203710ustar00rootroot00000000000000PNG  IHDRm?hIDAT8ұ 0_A,jςwz-;Ҭ@&BiߓJr+ƨm ]89'3q!]P~o!xqU0\_yneYuWJIy~OCKIENDB`libqxt-0.6.2/src/gui/resources/flags/CA.png000066400000000000000000000004401215241066400204730ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME;S7IDAT(1 0DmRl,lmr!ko Nbc!,lDvƬLe,3̃p0h:⦁lou Qk q A𰱔eжֶZakXWK?g{5azBhϳ:y}o}= HO-nc- !M9 ocO^7"oAIsxIENDB`libqxt-0.6.2/src/gui/resources/flags/CC.png000066400000000000000000000010431215241066400204750ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME)4IDAT(=LSazUI ĦBBD4ġء$ &,@c" @I;'&f:Մh`M@P z2!c+Gzc #vMi(@<=J >ReM}'gy`몕gݼV eEI$B(l ]Uusp qAt@ɷLFvZ,h}1]}.EFue66IgKmF|_Zz޸E64Ԇ[mxnpgy<)π~mW;m2W 897^"/MM62O`̘1`*%ym'E"nN"wr`hԃ_O$ B$Izrc| ?*.{;IENDB`libqxt-0.6.2/src/gui/resources/flags/CD.png000066400000000000000000000011351215241066400205000ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME$&IDAT8]HSa=M[p_]X FuUDA!]. **  yD7ve эED@ 몏BѦN;t1֦XMʠ[ , kuA}j7 1/ژ@Q09#rLX!˹ 3`Khg*ZO3]'Mg'`ٙkQ+PƵL[i8Tۊz%AOY ⱼ .~]]ȂkNx# 휬{LL+"MW#:> y -x&h8UgLθ [QbXX/vWOpևz/F 2Tz q%oW/3k".:34ðR>Mwc/_3w_a>iZ8:d/~}U`\tՊXɐA:m{xܹ-׊JIk4]/E֎~9(IENDB`libqxt-0.6.2/src/gui/resources/flags/CF.png000066400000000000000000000005741215241066400205100ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME unIDAT8cd0hʢb@k`P6+CtcheX!4 ?6C)1/ 11DŽOQ1tY^OqdE٫fj }|_԰ Bn[G2vCKAr.6zAB|=3a`f```x4xuY1p1@= 71z`1s,Z8Y|?b|`:ffcDH;ֿ lfֿza ZU1 IENDB`libqxt-0.6.2/src/gui/resources/flags/CG.png000066400000000000000000000006771215241066400205150ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME^aIDAT8M(DQ}QSJ"hRSNDRl&%bQB) 1 c#{߼99שs̷2r lӒgikQK Fx0 (Z j;cV̀&C7?gOOf@_n~M+#ި,ԗ>q*]EN8WP׎`~g >۪%)zJ A۩K#T-գ$Τ;BM_}>zv{#`Ʀ\'bcOxfB|o޿ `Z2hBOSDG"_>=hdRίg)bY_cWuݍIENDB`libqxt-0.6.2/src/gui/resources/flags/CH.png000066400000000000000000000003121215241066400205000ustar00rootroot00000000000000PNG  IHDR bKGDtIME$)GlIDAT8c!@B -G?ˊ@^`BJPCpC? ܰ?^_(lx ^yZ $)QRrO4CIENDB`libqxt-0.6.2/src/gui/resources/flags/CI.png000066400000000000000000000002231215241066400205020ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME )Գa5IDAT8c^` ^Unٽ gSB0j<?vցIENDB`libqxt-0.6.2/src/gui/resources/flags/CK.png000066400000000000000000000012021215241066400205020ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME9X$IDAT(]Hq[S6%sma\PpJDB_PHX j APR!uDd^vEgrs(Ι,h є3Ej」Lu[=Ns eI)0kYW!U%)DڠbzeZvcԲ ڋ$AW}YFVF7D>Dmڀ"U3KGdF|NIJzeR$L iIP^A_wppϢ7D4 L8ѧkQ o'Ð zkZ&T~?} 5ËcnZlYXI@[Y+D9d9Jv(*.d[jc{6rЬǃ$$;V< A r9׫P6F~> yWhݤI"P4Ͷr4ɪ8^[c]H?NebrZI~^o||7pg)>3UXMZgozL IENDB`libqxt-0.6.2/src/gui/resources/flags/CL.png000066400000000000000000000003611215241066400205100ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME ; IDAT8cd0]Xl.K/`B0RFI7)].E{~v 0ǟcܸA+l7/+ņ20 ,S~ f'3SrG 6ʼ%IENDB`libqxt-0.6.2/src/gui/resources/flags/CM.png000066400000000000000000000003601215241066400205100ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME  IDAT8cdπYqoVD#~U `` f̍31 1%1zbN6_ (Y2F``d``zz8+}(-#ÃZnX!N?l & (&mytPIENDB`libqxt-0.6.2/src/gui/resources/flags/CN.png000066400000000000000000000003751215241066400205170ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME(אIDAT81AAE!D$؅( ,L/,E֋(ߗo7ɼn&/$:p ~TR >}.hP7%:(U-OsS@$^'t_>>)IDAT8MJ`K$EjiĂH:8tS]S"gAZTbi$4!gx{ኻ^"vs ͊J ނK%Fu_ ~e0K cTX00dUM?V ?igPßO/Q10}g#Q3>%(1p2>dU!a og0!*c l,D2+^XR 9RY4.G25Oc lwS+O,Ɉ--XZMo3 빐9C&9]dQ243vNUc-cGo"`r] 7uɬr6ھ#-aedwK.^2.O1⬲\;axEqqu;GSsw S &߷<;)!=²B:x*yMu~2Dܼϗ}t(c!hͷ=+ΌJ*6K66{i*N Sפ|M'MIENDB`libqxt-0.6.2/src/gui/resources/flags/CY.png000066400000000000000000000005551215241066400205320ustar00rootroot00000000000000PNG  IHDR cbKGDtIME:0]IDAT8.Qw>vUIWCQ+kx-B(֊H(6Yl ܝ2sw'9* *BgqT4'q7O7Q3WpAt{FI/pVWwr{r<+H ;}nމ2EJdhmgf2)|oqgz kd(aԕj.0jڨKuMb\^vHk,LpټcS{7⋫񉞓K ҟDCض+IENDB`libqxt-0.6.2/src/gui/resources/flags/CZ.png000066400000000000000000000006351215241066400205320ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME %oo2?=E !O)6n'j2000[ЖIENDB`libqxt-0.6.2/src/gui/resources/flags/DE.png000066400000000000000000000002201215241066400204740ustar00rootroot00000000000000PNG  IHDR cbKGDtIME B2IDAT8cd``@D C,{`ƻ,4 FØvfwEIENDB`libqxt-0.6.2/src/gui/resources/flags/DJ.png000066400000000000000000000006071215241066400205120ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME l#)IDAT8Jax/RhmMZJH".JĜ2KCm5 1ũyv Sy1R:Brlp`oPMƘro,58R4>4'X@H(\6uL[{-EcLdys캐A<>W|+m K dP,B4:WRrFw+#JiA8NWg`KI78ƿQH_`a+nIENDB`libqxt-0.6.2/src/gui/resources/flags/DK.png000066400000000000000000000002741215241066400205130ustar00rootroot00000000000000PNG  IHDRٱ\bKGDtIME 8 q^IDAT8ccмMVUSp) HR=j0Ӿ8ïG~}Bi0%S8%)rh5~&-Ak4IENDB`libqxt-0.6.2/src/gui/resources/flags/DM.png000066400000000000000000000005421215241066400205130ustar00rootroot00000000000000PNG  IHDR {}~sBIT|dIDAT(+q?lZA)'WY9e堬?@l렜B}s5H&2!iup~7yyJ-$5l⦟ٿ@0#Ov  h:"3:HUO-PAc?JB!RCrs9VPܢAv8x't=,wy= IENDB`libqxt-0.6.2/src/gui/resources/flags/EH.png000066400000000000000000000004721215241066400205110ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME)0IDAT(? qp:eb0nYL(2z"&e0dҍ b(ΠH^76 ~#:/*IDAT(ҽJC1E9uju.zn;pvF"b-J(ԓ8Tm". O*F`i?o4N_ḳD e|/BJ<@CXA?QNDYBaZ ٠"Z4Oߎm+T`[bYR,w֗N>`s'b!i ]ϜA&L@5o ϼY":ﻩYyP觼lXErIENDB`libqxt-0.6.2/src/gui/resources/flags/ES.png000066400000000000000000000005071215241066400205230ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME%8EIDAT8픱N`[~J@f(|'F߀Ę&P0g×sOw # h`H*` '3T@;n,~gAWi>oc#a0uuX\{LrMQuUb=1s6¢7Je#/A!%I&꒍\ mv9s̟mkrB*Jʟ?7NCvd%d@#FĬ%o_v(4{rQ@י/KDOJUEmi5'>>jJ3o2>G\:9w@ o93ZWEؙ#YŠDkj[ HѶlTIENDB`libqxt-0.6.2/src/gui/resources/flags/FI.png000066400000000000000000000003411215241066400205060ustar00rootroot00000000000000PNG  IHDR cbKGDtIME vbIDAT8c,@oãl JĦ '`"I6eϩ{X%~g:\kQ ^3>ykPD׭cx+C;I)a`cx9p^`!, IENDB`libqxt-0.6.2/src/gui/resources/flags/FJ.png000066400000000000000000000010641215241066400205120ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME  PtIDAT(KhQL4fFGI,bRA jPAԽ])IqQuHn|EX.14d\ՋB9ozn86_0I5TWF8ݴu1.LTk&8vMqG9Y&*6vl8۰ vK;UI¹,B8(J'BF[<3W7 :cQB3=c|gG!sn^؍<Ў?"ְ_å ݣ6]|뉪.dF?t[ml g.p/ӑ0yeRe^irݷ-uAIX7\4^#QM X|͚Y NV?̑aoh KsqwЙ]ZL*Wb6b/~"v?&IENDB`libqxt-0.6.2/src/gui/resources/flags/FK.png000066400000000000000000000010561215241066400205140ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME  ,IDAT(OHq?)V6m:k1͢¼t)󐳃eiRAԥKIQa :IA1:A&Eݻ19=̔NNkbYss4uu,Τgs K³#5~$ w;Q޻ }1MJ5۶!W2'";9uD_ "fbO# ny4]Fìp{6o IDAT8cdXr.!j0KƩ4I,O>KZC` ύlIENDB`libqxt-0.6.2/src/gui/resources/flags/GB.png000066400000000000000000000011131215241066400204760ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME & .IDAT(OH7״msNrCALŐ9j.#I IvHȓE1lNLh_\V>yyy^^!tR{ZQW J/O.9A'nZi)dN]m ")݇JVղAʛ1!v\M~F @JICj`nÆDlx7 | q>.}Z1&=/+ #hjQVVIׂW5m:%8wl"Ij8:j2VHQu%wNɮ+"oMӉ4+>cev^~FCC0*:jM?4/GfGc2=}[ n4  Z+6~7_d3ڿ,octTzF^h>&tIENDB`libqxt-0.6.2/src/gui/resources/flags/GD.png000066400000000000000000000011231215241066400205010ustar00rootroot00000000000000PNG  IHDR cbKGDtIME 8AeIDAT8MoRQs"n,Qu6+wn/\]Z+!&1ho@K9.E)t6$3;KHΘ isP%p]`vAKwYںF!~װܒU)ࠦN*.$m7n)]VOL;ލM:M41zRb7B@ZRxX΢\rBJ /d+ M(au#M!dїPa[\%fcܢ𝀉]H|l6fXyb)hĵ3 G: J5nO2)P@楐Y;&vL!R⠡ X 33oމشt^YcdƷ35٠3>n65wјBJ`-_B<D맒ꉩ>.)z' 6ryG]gHM(^HKeUVŅp[+KgR.xIENDB`libqxt-0.6.2/src/gui/resources/flags/GE.png000066400000000000000000000004221215241066400205030ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 5.IDAT8cO? A/uCL hǦ @ >}cn qlmBsV0}1|۔ ?6m05 2# l& ̲R53J1pƇ00(0p63:$1+0p*`3OID1 f X &zxMMZ4IENDB`libqxt-0.6.2/src/gui/resources/flags/GF.png000066400000000000000000000002221215241066400205020ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME+1"4IDAT8cπ̝Um +pie`)C!5xQG P.,d+deIENDB`libqxt-0.6.2/src/gui/resources/flags/GG.png000066400000000000000000000005611215241066400205110ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME/>p*IDAT8JA;h.Ej`CبZj`c2M Ꙅxk99jo曙5{O 7wH;]*el@F65vBTC֋&\ߔ:.qpzPĽHك !e3{I0w^vJ^a?[8. iNC*Lp+-u]TWeIENDB`libqxt-0.6.2/src/gui/resources/flags/GH.png000066400000000000000000000003751215241066400205150ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME'IDAT8c<'\#*nL]3aՎ ?g[X)?Cb'm10000a~ ;#^}Dţ}20000" 'I88ҭ?  Ȑm?Ĥ4&IENDB`libqxt-0.6.2/src/gui/resources/flags/GI.png000066400000000000000000000005601215241066400205120ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME 3Z_IDAT(JP` &.ϡoavrK5 ަ)%Mx3_h5"|ck3.nNjDu{Tk+ێIH$7)_VըߤDrz\NGc3;|>5s鹻~@8M\䶂3X=  jGefEx;,&-X Tyщ\궃}`ĀFO4,.طĪ/Trm~g%IENDB`libqxt-0.6.2/src/gui/resources/flags/GL.png000066400000000000000000000006171215241066400205200ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME %֐1IDAT8c&ZKO ve0e_iYߏbL bqD̈7cx[#;D"I3 u|~?ySm |&3oM Fj5 an"IENDB`libqxt-0.6.2/src/gui/resources/flags/GN.png000066400000000000000000000002271215241066400205170ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME9IDAT8c<'P__+lr=U<*KR0j< ܆IENDB`libqxt-0.6.2/src/gui/resources/flags/GP.png000066400000000000000000000002221215241066400205140ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME+1"4IDAT8cπ̝Um +pie`)C!5xQG P.,d+deIENDB`libqxt-0.6.2/src/gui/resources/flags/GQ.png000066400000000000000000000006621215241066400205250ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME !oTIDAT8+DQ9sJk+ KKedžFH,,BvXH)JnVYLIjĐ;#4ӸfkwNt#e+x=nAaqRaa){%HLrewy "1-]2f>Ӊg "@)۽[xUt[i bW(8~!i7Вo§>)Xh4d2@:-H:. Ua5˜cT1H.cb>@NTYUa-,B>qx&Pb:\c8 #Go{+f37IENDB`libqxt-0.6.2/src/gui/resources/flags/GR.png000066400000000000000000000005011215241066400205160ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME-".ߋIDAT8cG'aU6@!`A|C;'[>>v efbBHQs(I300p19p/?l-8YvWObǧcõIu1#rm_ #Ǡk5r`;w$H2 F9-#D5K淿qQP119gWVa U9IENDB`libqxt-0.6.2/src/gui/resources/flags/GS.png000066400000000000000000000011431215241066400205220ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME %2pIDAT(k?Amɭ\E9*:ѩڥաݢ:5,ǠCTɨA:]k[L-u?ԷeF/_U4v'WeNz{p͜Acw:ߥ ?%8_GZ*:2:)Q4n!UXzզRAFeu 5m:#Xkټ\ل|Y,Ȥ>&Q`.O;%р᫇/b_ڂu7EVހM` ZEH d9Gۖ²Rꛦ4rc F O twߔQMH'vyHᬺf+!IFqf?'ěM҇ f+qtjm߆(.ߨ] 8>c|8D"]JZ`BX<hbU:^~d -5)IENDB`libqxt-0.6.2/src/gui/resources/flags/GT.png000066400000000000000000000004551215241066400205300ustar00rootroot00000000000000PNG  IHDR+1bKGDtIME %0IDAT8 a8CX(r;XW:,&+R$T!hbl}jwKJt'>ui;[6 q~Z ,-ISo|ik4:Ҳm᭱% s sy!>P)1-UQPT{~RG6/WIENDB`libqxt-0.6.2/src/gui/resources/flags/GU.png000066400000000000000000000004621215241066400205270ustar00rootroot00000000000000PNG  IHDR csBIT|dIDAT8cjI3U a>ߘ1Q`f Ljpcyrh 23a1/qgl>1|c!Γ,(b`p`gg e#uI_13300C X21ehMp%1Zs z1M=6|%V)`2iUV838㡞IENDB`libqxt-0.6.2/src/gui/resources/flags/GW.png000066400000000000000000000003711215241066400205300ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME 0_IDAT(c<'P__+\9_Q eh ?p;рaϏ ~}fx7 vFF d`=H ,  , <CX[6R`c.c.r xr&Cp%,&UIENDB`libqxt-0.6.2/src/gui/resources/flags/GY.png000066400000000000000000000007651215241066400205410ustar00rootroot00000000000000PNG  IHDR cbKGDtIME 35[昞IDAT8AHSq?o-><9 ‚`v1:t=; ;ћHѩC,lc*Vl,x%=}'#|T>d?S .Bu/Ͽ])G88Do{J~n%V_ix4"8ЃPlZx-Iv@?D~S7wn ")W|,YRW^s |dF|D"v;}~V.Lb66Mٺ} p1n 5%gRr_0U `EtH6W=⯐+AO?k&}"{)xZ vIؾ ž4KWq;5EY;zxmM?\dK|YIENDB`libqxt-0.6.2/src/gui/resources/flags/HK.png000066400000000000000000000005111215241066400205110ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIMEHxIDAT8͓1 @EZlZV!`Z49`g&vVqr4AX+(003̴$HP 蟀>Y4x,eKWV0`i QqrWej%n`0p [ma 0AvjBhW1z aݮr9~ ,lx6]?z$l;ke.IENDB`libqxt-0.6.2/src/gui/resources/flags/HM.png000066400000000000000000000010431215241066400205140ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME)4IDAT(=LSazUI ĦBBD4ġء$ &,@c" @I;'&f:Մh`M@P z2!c+Gzc #vMi(@<=J >ReM}'gy`몕gݼV eEI$B(l ]Uusp qAt@ɷLFvZ,h}1]}.EFue66IgKmF|_Zz޸E64Ԇ[mxnpgy<)π~mW;m2W 897^"/MM62O`̘1`*%ym'E"nN"wr`hԃ_O$ B$Izrc| ?*.{;IENDB`libqxt-0.6.2/src/gui/resources/flags/HN.png000066400000000000000000000003401215241066400205140ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME5aD/IDAT(cdp`P[qژ\y3o0w{m}|Z3g󟁙aޮ ܥc`?+ #y.n]~֓1ķze].mH8a[%'uIENDB`libqxt-0.6.2/src/gui/resources/flags/HR.png000066400000000000000000000005571215241066400205320ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME 37IDAT(JP77VP7A*>CG7U7  6OM~sijiAvRKX:G}P _I7 ~$^*fӨߛ ;Or{śsK9$8iԻZ;N=:"<ۨycJa>E|UxYK0H,[w&c\k* $@^/v/ svT-` m0o<x5~DQIIENDB`libqxt-0.6.2/src/gui/resources/flags/HT.png000066400000000000000000000004261215241066400205270ustar00rootroot00000000000000PNG  IHDR cbKGDtIME!5IDAT8퓻 @EϪ/[{&X'"I,A|D; >6J!85502)B@K)Labߓ$qx`2rIߓʼn{zkEmBt{R2W>-?R#y"]Lږ@/H(<wxIENDB`libqxt-0.6.2/src/gui/resources/flags/HU.png000066400000000000000000000002271215241066400205270ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME  kڦ9IDAT(c`~O70f````` JW:D^3U 8IENDB`libqxt-0.6.2/src/gui/resources/flags/ID.png000066400000000000000000000002121215241066400205010ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME,IDAT8c<'< f|tthK3waxZ? 87go2 >e6dij 7ˏx f$&*0aRfW\;ǯ?x2u [ 30ˈ4i_,YCbg0 gxO cr16SIENDB`libqxt-0.6.2/src/gui/resources/flags/IN.png000066400000000000000000000003241215241066400205170ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME`vIDAT8c?? - 50;tQ3|۷_ '`b}aӦ ::b3ODL0fyC`r%J3IENDB`libqxt-0.6.2/src/gui/resources/flags/IO.png000066400000000000000000000016651215241066400205310ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME /1WIDAT(MYLrX6 ;X Pdj4Fh1:4e1˖e9- &fۜ(tz (m>ht|}JQ3zN'osξ9\jYdKd|qp=T9Xoǘ,[xP  {):ߩsXHLFN8Wxe-e;XK^?Pmj =rՅ~aIVcd҇'/GS#(CTܟԱqƝ ZFD`V>CK-m "ҧ4G9P>B>,r^~t:]iY]MbQg!~脄qQ8T f=Z;Pec(M#+M^"?W%t&-İj߅sg##2)MMd.X5 #β@&7|-wT)݄姬$h,@h1Z1KL:CMSmR֔Vr?c<]efڷH^E \Iskf2Z!JᏬP61)y 7-3Q{qGﭷqc؋ۻD]g4*UP[d|.^'L^\E8v[9iYlp3? R5b+qNƠUl2QCQ@;Au7/=cjY!U(7sV[.+rӉZFOp}BwZ֩c:jiM eb͉IENDB`libqxt-0.6.2/src/gui/resources/flags/IQ.png000066400000000000000000000005111215241066400205200ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 87V yIDAT8퓽j`ğ*$HiE\Zttpmti^AwA n"h*V1Sס s g;9N/HzHB`_Lm|{>|opD6qCƸ(Iʝ*[*&傫D#ܠV'S7)^.!鯈Ü(sm 3}~ĚIpWcFjIENDB`libqxt-0.6.2/src/gui/resources/flags/IR.png000066400000000000000000000004211215241066400205210ustar00rootroot00000000000000PNG  IHDR cbKGDtIME '_tIDAT8Փ@D߶%B u _ɿ "hO1odLVV2!B N65[(镲P(':~U2wL򼳊ߧx7wӢu8P%iQKesHn7ZF%}9e*1ZI973eA?ycIENDB`libqxt-0.6.2/src/gui/resources/flags/IS.png000066400000000000000000000003341215241066400205250ustar00rootroot00000000000000PNG  IHDR&bKGDtIME 5Ot~IDAT8cd $=҃URZ$ؔL$5xPx+BKQᱭ$ w|$;X f```)#33Abĥ%a PGsH2^'rh IENDB`libqxt-0.6.2/src/gui/resources/flags/IT.png000066400000000000000000000002271215241066400205270ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIMEbZ9IDAT8cduπ\K}LSH *KR0j< >$IENDB`libqxt-0.6.2/src/gui/resources/flags/JE.png000066400000000000000000000006521215241066400205130ustar00rootroot00000000000000PNG  IHDR cbKGDtIME 6 n LIDAT81K@/:Uɒ]S']vȗO`>@&R4S!:m!9MiwǻH !dŤ$Ʉ$iqI)) Zkͺ++yqV]~(O-F#/xݮ H:NZf`Pa`iJr?&:Jirjm[ixIBhz}!x j°ТxBF=#=킦JˍMաj[e;wLֿ:.?XWSQ2)^V _`[X RZSIENDB`libqxt-0.6.2/src/gui/resources/flags/JM.png000066400000000000000000000003701215241066400205200ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME  ,IDAT(cy?w o2|@0AW; \ CR-@7y 00b. B2dž]l\-J\q ÝvV׃`J]L0]Y:U(?.5IENDB`libqxt-0.6.2/src/gui/resources/flags/JO.png000066400000000000000000000004241215241066400205220ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME !oIDAT(c+߄?U19A g|cÙ?,0 r3Udx(ML ~DQcc YccFL00y LL( 9p/E \wg_ggX'pY$a]4+,c^3Ҭ $2Q P@úT~bHIENDB`libqxt-0.6.2/src/gui/resources/flags/JP.png000066400000000000000000000005101215241066400205170ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME)tIIDAT8c&Z:>{w!>#C|F >J`F|a~1K ~Du ; .Vo* ??Ǫ]Vn&6V838 e```9gp4852 Ƨ& 첒 d5!`&6Vym Lr9t^?kWOgo: KE[IENDB`libqxt-0.6.2/src/gui/resources/flags/KE.png000066400000000000000000000005741215241066400205170ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME  Ew;IDAT8JPi?)K08I>@ႏY]0BGP%:ԩ`])9}sp> j5WNC:EYJ90 yIQU@>rw(~] 0H*0qq0l8 ;9,9x<'qnRƭIWR{w*uVRHB9I0lRIENDB`libqxt-0.6.2/src/gui/resources/flags/KG.png000066400000000000000000000005351215241066400205160ustar00rootroot00000000000000PNG  IHDR cbKGDtIME6.cIDAT8=KAٹ((A0g)"hH‰)XZ)e9k(@.u} dY3EB="]M_h( ($Ws0Z&C$F)Qb1.-R RbY %j*xZ(.u9@6p@vis*2/ @:t |H"O&шj\gIT_ ZbAH7IENDB`libqxt-0.6.2/src/gui/resources/flags/KI.png000066400000000000000000000011431215241066400205140ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME-pSIDAT(NFϴC3S*)XT0W&&ƅ Wҕ?{!> BP2NgZ:.. Ƴ;nrO 墯''G !LOp.8tV p"}z=_8bi&tB6YEwt+(HK%Rrj+0:OyV_Ǫl"g4Vb`%7g1'K\07=Cq8ߪM2~V{g: q`,W~r*u[ndTF/~~,?j\"ylT[צ"D*Fcq_a6Fbi=|X@Z?&yi[4`0pA80L>%u݅IrgV}ɣ;Wj&.AtBFi25Ս=RALG78̤hIENDB`libqxt-0.6.2/src/gui/resources/flags/KM.png000066400000000000000000000007401215241066400205220ustar00rootroot00000000000000PNG  IHDR cbKGDtIME m.IDAT8OHqO^iTXD?JRHPv!A;xXx鐇,%KRP1AЃHYjskTwk}:Etr&- &9q/IENDB`libqxt-0.6.2/src/gui/resources/flags/KR.png000066400000000000000000000012201215241066400205210ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 28Lk!2IDAT8KSa?g?Ny֩0!w%jPn  x=jЅx16;/NTPsLBNsgkڷ n#xo|""׀f2\u8pa03??OZEUUbXs8z ">}|7 @ GGGF4Ul6Kww7a099TV7؊gCM5OX$?Iɲ,IR""R/vy;VhX~H*˲cDiՊox*?Cn=&|,z6DU?qٖ஡>>X4M2L!3::&sssO"0p*RFFFV$=4D"AP P.p=e `oo:(p""j6۲_2OIENDB`libqxt-0.6.2/src/gui/resources/flags/KW.png000066400000000000000000000003651215241066400205370ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME,;IDAT(cd0@M🁗!ҕXÀ\j0;/oJv)1]/i[Rb.E`0cfݢuۙ_0F1ؕKA3'P%KpJd6FUIENDB`libqxt-0.6.2/src/gui/resources/flags/KY.png000066400000000000000000000010711215241066400205340ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME $IDAT(OlK?ョ<TldF"k;$DDosP$͟H,p88,",!STi2MuM۵Ro>B]jpYp8BFN?].43RCOX zsZ4OXc<nFK H| 0M˕6*1z IS{L3/"h -,TF$D$jB6Kܝ*IӞMEz42RMf P=lr5^2!dpAr:'6 CW7v-jΑ@#ZiηvaDNceq%B,B,Zȱ]cQI730iޢ31Ǯzs`W(lbqW!+ FRm)6t&6 ttM*ءoD(Z>?uhcbJ'O}0~·fUc`IENDB`libqxt-0.6.2/src/gui/resources/flags/LA.png000066400000000000000000000004101215241066400205010ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME#SuIDAT8c<'`lB41A#` 2910000l f!@WMa߂A_&0\>aY7AD8 &E_(1 .]8/ LT8]܂&Y;Z; 00ÙIENDB`libqxt-0.6.2/src/gui/resources/flags/LB.png000066400000000000000000000005771215241066400205200ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME ,"!IDAT8A+qv-9(I6(o]E\8(%I9lp`Lv5'י9pƆmuY%M`31WClVRoS07k& .)Æm25Fvc1`srlf/_qb^rj^;FokP_󾰣&[iR:o$n l fIENDB`libqxt-0.6.2/src/gui/resources/flags/LC.png000066400000000000000000000004531215241066400205120ustar00rootroot00000000000000PNG  IHDR {}~sBIT|dIDAT(cL>?  !~Ǡ)vT;÷bS_ gX`>)/bgףfףc*EV3l!~tU c7,1Xp00000= &mVu]x!%.xq)/Cx fė30U/+ON<%HIENDB`libqxt-0.6.2/src/gui/resources/flags/LI.png000066400000000000000000000003541215241066400205200ustar00rootroot00000000000000PNG  IHDR cbKGDtIME2g6IDAT8cdЮ@. 񘁍\L´w0xAX{N}/)7X%Ei? Oc87d ?~dgïXD6Vǒ:-e`<'F6j1)>gIENDB`libqxt-0.6.2/src/gui/resources/flags/LK.png000066400000000000000000000007211215241066400205200ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME 99Da"L8`z?)7 003~9}_ɏ), SH/_沲f<'ܨ:PF?IENDB`libqxt-0.6.2/src/gui/resources/flags/LS.png000066400000000000000000000004341215241066400205310ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 2t/.IDAT8!@EߒBpu\SِQFr&Uap(n a7E|F+=hW"u,W gck-ibi0t1Z)B$s1ƸĩBkM]dY0 m֚$I؟ON 2^1fN?щpaaIENDB`libqxt-0.6.2/src/gui/resources/flags/LT.png000066400000000000000000000002261215241066400205310ustar00rootroot00000000000000PNG  IHDR cbKGDtIMEuh8IDAT8c|? - U; !&ơ?ib c ? aIENDB`libqxt-0.6.2/src/gui/resources/flags/LU.png000066400000000000000000000002311215241066400205260ustar00rootroot00000000000000PNG  IHDR cbKGDtIME#;IDAT8c|M.Yz&4X|s32,;ƴ5tIENDB`libqxt-0.6.2/src/gui/resources/flags/LV.png000066400000000000000000000002211215241066400205260ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIMEI3IDAT(clg@D CgI3&\20&7 ` IENDB`libqxt-0.6.2/src/gui/resources/flags/LY.png000066400000000000000000000001721215241066400205360ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME 9nIDAT(cdjk$XFq[4 ]/ 'eS"}/. IENDB`libqxt-0.6.2/src/gui/resources/flags/MC.png000066400000000000000000000002061215241066400205070ustar00rootroot00000000000000PNG  IHDR_%.-bKGDtIME-'iY(IDAT8c<'g`43HLH*@L6SكL`vv[8c/;)"Hv.~-q%ϧ!aH,Mܰ 7a)- hjeR8lpRc|ƍN+diw&38k| 2ݠIENDB`libqxt-0.6.2/src/gui/resources/flags/ME.png000066400000000000000000000005371215241066400205200ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME .MIDAT(бJPIc䚦(%P,u( 8>O398PAC88F9ߏQw})̳^_܏\ ڵ$@ﭢ~rN88XGm.;xIt Q4 vZ|Cf a?F JXӇK=pfQ73ѽ \hoNZ#Co'uM.D8FJ!,H[FZ#F ͼ E /mVS:dvdhs"@b;KDI26Tgft2b,UTz>r{2Lkn/7|B0jv*D& suv2$Þ(rQoD꺅Gk3>LpJab3 Ke4;_ d t*.ЧyAUSS}ֳ< M3X*ߋ\.7$խȝSOyRa~qì|iUzVzb˄L)^, pۓK$ap^2#c]aڿ`IENDB`libqxt-0.6.2/src/gui/resources/flags/MK.png000066400000000000000000000007041215241066400205220ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME 8EfIDAT(KBQ?O$"Zrj ZZ Zj Z٭4aCZP zʗ=5uVFa6 ?~ݮUg4 VAAtWrl=΀:厊]تAGi~@8Skn) _EfQ<7&ME垊Q)WuLE5;$`yxI H=ti G_~/LTi.IENDB`libqxt-0.6.2/src/gui/resources/flags/ML.png000066400000000000000000000002271215241066400205230ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME! 'bpS9IDAT8cj8$o+lr{1 . J!x|`Gb2RVނt"ނbd6U ܙr;|IENDB`libqxt-0.6.2/src/gui/resources/flags/MP.png000066400000000000000000000010271215241066400205260ustar00rootroot00000000000000PNG  IHDR {}~sBIT|dIDAT(_KSylxUna/FQUL>@P)2"o 2"2p+K0i3ps~/ ?޺t8Ѯ2LsrǡVqY \ C^a<1GhdF/dmt%/Tɼa81Kص菎1z F5>O{ډo+lY[O"pP~ +ȿ_pDRd2I*$+xmZ)PS8^#ZV b7 $%mo`@sqJo 7)PUI8(Iir%e^H # z=$Yd!qlYk+y^qaQbLIENDB`libqxt-0.6.2/src/gui/resources/flags/MQ.png000066400000000000000000000002221215241066400205230ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME+1"4IDAT8cπ̝Um +pie`)C!5xQG P.,d+deIENDB`libqxt-0.6.2/src/gui/resources/flags/MR.png000066400000000000000000000006051215241066400205310ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME5/ls:'IDAT8ՓNP^Z% )1qp@'} WVG߁ppҙQV7@Kmm{])Jɟ{ӕDZ*([A:`0 E](cpablk)1~p~y9R6=?D6LI?x>"q^/rt<33Rbp-_$97s!hYP;#Im|E,:KnV5lLХ')n 4h WFg,'=kDwb?fZB+[LD^T9 }fvSSnfK=U%mܿ1\+U tS;Bn n\MHYCjՕU!x6ó2'xnhIENDB`libqxt-0.6.2/src/gui/resources/flags/MT.png000066400000000000000000000003531215241066400205330ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 3 NPIDAT8c StXp :8G0W=Q(2K2Di1122;Ay2Z ^Gg(|rTZU##H&=N3\|~!"ΣKUiE10Mw$Y?ޏ65r|hIENDB`libqxt-0.6.2/src/gui/resources/flags/MX.png000066400000000000000000000004401215241066400205340ustar00rootroot00000000000000PNG  IHDR cbKGDtIME  TIDAT8cdLπ,I)c2s*nV帴20ᔡ S/^:0#M!TaAc~_Q/1z?fVN'O4122{3:!v C `1td1fh]o̠,R%þ+ ^ LJnpK Os3;]c;#CT÷$ I77û/ 22e'+\ˉ6Vw ^3T`Ptay9w$^}Xi3000bЗ{p0{boBA z XH &% hQJ,YIENDB`libqxt-0.6.2/src/gui/resources/flags/MZ.png000066400000000000000000000007311215241066400205410ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 1]^X{IDAT8=K[Q97/&FsA;4Sc'EA_AEAܪ"..:N8$@%p>7<^Nw/'-{rV?L3Z 33ȠB9D;C< MȦwF hdDΨ Cvũ]& 7Eq ~<;U5,)uN;Ad!ɠ߬.m8/})7h\GUIRI(#u},̤!_˓!E8!ڊ5jB|>L_]} B%ڵpCLG@g x8IENDB`libqxt-0.6.2/src/gui/resources/flags/NA.png000066400000000000000000000013201215241066400205040ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME -9 rIDAT8[Hq?5-ChʗPY$F*=$y W >"|H(JRd-:'ls9z]s g7QKr Ez}[=#ҽ`b´|x.ki~(h?-;g3%LfK1H-Itv1S>PyNOSJ0CT.ӱT/^gy_+SclC4kB3k `gWR Uy;([=R1%ޥNPAu{od+iV0;Ek1OCwN) VfrA۰30A"(IΉɉIQT"B9 ?<-*"ۥD0ݯ@ORufn>.J&,cD2m]1Wm:pϊ}(8B,{1>KZ[}Lt$ ޕ1EDE5?((Xu8vʨyQkֽ,(첽k|!c1YC-tt.'4YDdRt' hݣe3sd2rGxO ͜IENDB`libqxt-0.6.2/src/gui/resources/flags/NC.png000066400000000000000000000002221215241066400205060ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME+1"4IDAT8cπ̝Um +pie`)C!5xQG P.,d+deIENDB`libqxt-0.6.2/src/gui/resources/flags/NE.png000066400000000000000000000004101215241066400205070ustar00rootroot00000000000000PNG  IHDRybKGDtIME rE#mIDAT8c|L]CT#%̈́o00000pY0,``dfk0kPo0|5 9H6Mو(1 qKa BxR̸R˧ QȻA{5/GIENDB`libqxt-0.6.2/src/gui/resources/flags/NF.png000066400000000000000000000005351215241066400205200ustar00rootroot00000000000000PNG  IHDR {}~sBIT|dIDAT(̽J`>`+q)EEiq/KpuhAtIqqn\` usRZ[$iI&T`鳝sӲ("L۵BnM dbl??o=j]gqn˧2p᝛MӢ|5X= RhMt@*;|A*]^NRPIYi D4 ݠr;6=#IYiP0>a6@~j) rqu^Q\ƂY[#P"n_FbtEIENDB`libqxt-0.6.2/src/gui/resources/flags/NG.png000066400000000000000000000002171215241066400205160ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME 46_1IDAT(cdhπ,+dҲ*aM20ᔡ- ˗/de.~|𔝗A\\ӧL`11133033<|AZZDW9MifbϐD^Q'AG3 ҁ6cOIENDB`libqxt-0.6.2/src/gui/resources/flags/NL.png000066400000000000000000000002111215241066400205150ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 9BX+IDAT8c\'?yC`FEejIENDB`libqxt-0.6.2/src/gui/resources/flags/NO.png000066400000000000000000000002731215241066400205300ustar00rootroot00000000000000PNG  IHDR&bKGDtIME9khG]IDAT8c| rQ3 t) HR=j2E%42&7J͂8]AH,rzd0"0띨IENDB`libqxt-0.6.2/src/gui/resources/flags/NP.png000066400000000000000000000013771215241066400205370ustar00rootroot00000000000000PNG  IHDRbwbKGDtIME+7zIDAT8]HQ{L{їLr62̢o .dE}@QEuWta_ ď@B2pNkV2Sofjb9<}Gt3s0 R0(52u<{ٶSXN&?ewVo{.GX*nBD9OO }w-?5? !Q=_s.{W@݆VbZ E5bfo_U2aDYۖ3^c_H>\WLUo5%S_p,@G4˽ٔR:on_|ye[eO%MM#(4 Pt]fY !%.D}G"0%g@G"LH]C0+ L&N ~2%3撦ߛ hdU:* uvO$el2譑zkdPZXz`βα'9YV3G6|}WOgYLH[;]Q_#m\&>}#wuJݭ&ZB-CSڮy;/\x)CIi ~E״b:?TO{(3s->'9-2" I s_bO \IENDB`libqxt-0.6.2/src/gui/resources/flags/NR.png000066400000000000000000000003541215241066400205330ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME 7S˨IDAT(cdЮ@D CG Fw7i$S###( ÉKO}?y+3CW+Ü&?"W6Vf]b_{2l3/7;?|E,_@.b;IENDB`libqxt-0.6.2/src/gui/resources/flags/NU.png000066400000000000000000000006041215241066400205340ustar00rootroot00000000000000PNG  IHDR {}~sBIT|d;IDAT(нKq晊BāA"EP HA&DBDK4TM -M 5$BHVhTJ6Ysh?ᑲ]!l̥JleE[KOgy'd¨L]l?KP. Ȏ7hgMY8ӍHW~Lm˺Jg/St5~6C$ zu+WK-Fح5y .B~ؐ(xU7{709!f&{UW'|>HiXU[RI=g\"UvTЙ/W?:b#IENDB`libqxt-0.6.2/src/gui/resources/flags/NZ.png000066400000000000000000000010101215241066400205310ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME  )UIDAT(MHTa{qc5hڄ 2 g! %DZV6ԍH5UtcIj3ޯ$^FA=ssQCU`jiяt5>'rCEWUppf-^V.1h@whG"¿MS[ނHGR)_b˝ghEڰ쎗7* >I*D{S}#"L#%q(H)I^ C-EBfgVl80)rXp#8Qz!$@C͗ $u6yy )lx r`X*l~вMS.A}Q!VIENDB`libqxt-0.6.2/src/gui/resources/flags/PA.png000066400000000000000000000005021215241066400205070ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME1IDAT8c"eASb20a$* q%u C 0䭼? fAp1183US?.6&1pLQqA %0vxBt?xҏmDL~=zN]i~' `u fdgcc}ȊrQ1]CA2_cQd0N9#CJ4Y7IENDB`libqxt-0.6.2/src/gui/resources/flags/PE.png000066400000000000000000000002231215241066400205130ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME DQ|b5IDAT8c<P\A(* ܻeGGSB0j<~Q|4IENDB`libqxt-0.6.2/src/gui/resources/flags/PF.png000066400000000000000000000005341215241066400205210ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME5IDAT8?KBQ看5PIfS' 'M-.5: E AKč@-$Sl=xyxWܬ5$m@Z XhO|7=\o i1N :L/Oym/HfC: kxh2OhqC&,TB*I >%X8yQa@ Kf0]8RGNdUFsZ'@S˓MfpJ\NIk?IENDB`libqxt-0.6.2/src/gui/resources/flags/PG.png000066400000000000000000000012521215241066400205200ustar00rootroot00000000000000PNG  IHDRٱ\bKGDtIME 7vLIDAT8kSQ?k!KT8EVqtqJ$RA7$ĭ:T}jl^uMUp|W9o D`?EZ*~!c_,jIݩ䕽KUu6y^&8BPA1%񬇑&V@vϩQ'Hkg蚋9'ty;>X~|r3O.V.O۝sd( D3U«Ə6WRz`"cV:###ej\c C.Wl>'~uNaAym2im3yb[h')o[Ys{sss!(5]nV?ƭy;jW"CMڢT*uCR*y-YUOIv?nPh,bh&>[)5ZOQULe%j¦i2==m=E]6]-nƖO"rYiu.h|{bLJ|\vXUUuc]DZXO11z޿Bys%~IENDB`libqxt-0.6.2/src/gui/resources/flags/PH.png000066400000000000000000000006221215241066400205210ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME)Ƞ4IDAT(=KBqᅯ "zx 5lki"(j(q!6i AQ`E`{|${AV p8ued(CB/ӷ0M2 V" _f38aJV/GxMw\d!KhdQ"Q@Tl5"0E2jxp# g.맶tʆr̓q @)>ۖߓgy9>C c&s;,[pv ?TOw;lIENDB`libqxt-0.6.2/src/gui/resources/flags/PK.png000066400000000000000000000006351215241066400205300ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME4!?IDAT8c4бr}%0I"݃@@-I-\Up5XE,3V,+P^ R,c>ݷw JJn[_~{Pc , ?d@N`D,- +O#slvVvrDOظ,pADJ1tw3تbAqeM 0;ȝ# ,  y+0e0C˶[n102ب0l!kYËO/7aՙU ά"JҤBc=B_IENDB`libqxt-0.6.2/src/gui/resources/flags/PL.png000066400000000000000000000002031215241066400205200ustar00rootroot00000000000000PNG  IHDR+1bKGDtIME  3(2Y|%IDAT8c|&Z:j7hr5N~IENDB`libqxt-0.6.2/src/gui/resources/flags/PM.png000066400000000000000000000002221215241066400205220ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME+1"4IDAT8cπ̝Um +pie`)C!5xQG P.,d+deIENDB`libqxt-0.6.2/src/gui/resources/flags/PN.png000066400000000000000000000011651215241066400205320ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME6IDAT(MHN7s66uI.-=Fy ׵"O!dN]:e40mלͩM_׶]<0ujy2ymnNwsT7rk" J:x+8&>LR:g' B:Q$h"&PU? XǫI`)-a!cE" /rm,C3ϒl56*|Vl h BX;7K8&IUۯ> rZ9d[ύ Uy[EFB#Jdף7RƹhG'T SE99r_9GY$L-.۱i5 ojI%-6b1#MFRƚbXh6S $F^@|a1BMm"IENDB`libqxt-0.6.2/src/gui/resources/flags/PR.png000066400000000000000000000006711215241066400205370ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME   [IDAT8=HBq>" C[FmA$I845M64AAHAazM /wwpw"<6kJ4S)*8]ZyUΰIs?㢿oTy1\dLTS:& CTwᅊa/M!`rȁ+ ˬ}sIfj`떝*7wl^0ي:V$&Y PhE5LJSaɿǙ7^Q./9:H2$SCdVtznAqP;S.Gd$/f̍lF]t-+]ʞӊ ŌJ|VIENDB`libqxt-0.6.2/src/gui/resources/flags/PS.png000066400000000000000000000003561215241066400205400ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME 9 >ЈIDAT(cl06ɇ3000pÇA.A'0d4ɴ4 fBx6kgodZ1 s[i=9.1Î)3x:;.2 'Pl*4(v3Rcyia( %RoIENDB`libqxt-0.6.2/src/gui/resources/flags/PT.png000066400000000000000000000006571215241066400205450ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 533QIDAT8͓Ja㌣_iCFY.~vAQ.];oۨ[( Z"#$fuƟi&z眇9LD]|&zXw=6 [,uOa|6'-j; ćUdYƋ`(FV1,Յ1/C2L˅KH2)ݑrd^i:#OL0%B3XdȈ*!ւB(OX k_ 3%oCjxCar f```aŋ 8b'?:1^?+A g J7WcOB Hv3A0@Tȃ=%IENDB`libqxt-0.6.2/src/gui/resources/flags/PY.png000066400000000000000000000003571215241066400205470ustar00rootroot00000000000000PNG  IHDR cbKGDtIME 6-IDAT8c<'M_\tce```bdM'ybh:4?*A /1fͰUHh!`;g/ O_1pxe0U cY9 cuB&s?2IENDB`libqxt-0.6.2/src/gui/resources/flags/QA.png000066400000000000000000000002101215241066400205040ustar00rootroot00000000000000PNG  IHDR 64ubKGDtIME 'Y=*IDAT(c,՝G +;M `"Kר. @IENDB`libqxt-0.6.2/src/gui/resources/flags/RE.png000066400000000000000000000002221215241066400205140ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME+1"4IDAT8cπ̝Um +pie`)C!5xQG P.,d+deIENDB`libqxt-0.6.2/src/gui/resources/flags/RO.png000066400000000000000000000002271215241066400205330ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME  >9IDAT8cdЮπ\ZqLS6WَɅU `QG 5x@  s "BcIENDB`libqxt-0.6.2/src/gui/resources/flags/RS.png000066400000000000000000000006071215241066400205410ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME((_>)IDAT8MJ`K$EjiĂH:8tS]S"gAZTbi$4!gx{ኻ^"vs ͊J ނK%3j 9@ SіIl$&FTDj!'Q:B ! .f,nZ/Y+ KXTu*8O+F+"ޘs*XR9k\1+~0E hܰTf ,)iz<1ύ3$RT;\?PvN3I|z3/ 5ſ˱ KHJLg':#?ԐlPq81OG^6qҗyt=g߯5IENDB`libqxt-0.6.2/src/gui/resources/flags/SB.png000066400000000000000000000006131215241066400205160ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME.a-IDAT(1,azmBD bk Eb&b1tb*hZhD5ӻ@EZߓS]1;/lahHoG"wnO)a8|Bt z(;K!y7oaqdڥJ*m3 3!~ƧC=f ^ll`|b('Bl< ʠ0j࢈PH]ʎkaC>!3qO+bYše ih^ac@#JlOֈ+:N=  WL5/N;c~q*IENDB`libqxt-0.6.2/src/gui/resources/flags/SC.png000066400000000000000000000006051215241066400205200ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME$~z'IDAT(cdoπHztwyXy?lzXpI,}Yˆ ^g9>, {Tv?l` _o&?E"׉2SS.A@955 =qtadgWA19:a 09A CpaA'_}|O]O0tnyg 300,bk|}=̣w8UaM㬆X.)0]Tpٛ@IENDB`libqxt-0.6.2/src/gui/resources/flags/SD.png000066400000000000000000000004341215241066400205210ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME  IDAT(c_}/UF Q~ w1D}gبj32iGdRx=7# E^`Ac V= :d̄Mʋ ^}yG]u$Tg-`"`0yR×E00Rb(7?=TRX300PP?IENDB`libqxt-0.6.2/src/gui/resources/flags/SE.png000066400000000000000000000003401215241066400205160ustar00rootroot00000000000000PNG  IHDR+1bKGDtIME'GIDAT8cd p/a5=-ؔL$5jpw8[E.u㟋bXSvAwV] 0̻lL/`7{!\p܆tzHTIENDB`libqxt-0.6.2/src/gui/resources/flags/SG.png000066400000000000000000000004701215241066400205240ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME.yDAAIDAT8c<' `eP7њCE:Mncv: W84CX)3ˡ ҭ ?.]cx1A,Y{1ag  oaxj߿w1^D89XYY S"×~?@Aza|MڦQG Pn;~HIENDB`libqxt-0.6.2/src/gui/resources/flags/SH.png000066400000000000000000000007751215241066400205350ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME ;,A~IDAT(͐;H[$$ER-j|`A:K.DPqpBBE%C2D-%z\B5ɐ39~SK "N\f> 15* ,-R>.J|EG 6_*UWkÛp)f}[UY*s;;qݦwڗ I 9+b2WBLN/czx񒘊%&0L0tFDssD?[l8A x z#&AM\?a}#QnmųFi+)!UPS^p%_|cVmr96vL{xV*8q2kg#r9R'MO[YCW*%IENDB`libqxt-0.6.2/src/gui/resources/flags/SI.png000066400000000000000000000003651215241066400205310ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME(3f@IIDAT(c&tBXlj_0E@F!Ua r$6= ~b@#`t72<};6f43;ùL30'z0fIENDB`libqxt-0.6.2/src/gui/resources/flags/SJ.png000066400000000000000000000002731215241066400205300ustar00rootroot00000000000000PNG  IHDR&bKGDtIME9khG]IDAT8c| rQ3 t) HR=j2E%42&7J͂8]AH,rzd0"0띨IENDB`libqxt-0.6.2/src/gui/resources/flags/SK.png000066400000000000000000000006321215241066400205300ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 2" KҰ@UϠP-Q-Zڐ4mjOXxs{s"tਝ@9ܴ|۰Υ=%RJ7n=s yJdUL0 ߜnf0qĂ|$W*b(4̩dhgOF«.$U*2umĮ\Է'Ϯy>۸Cs?<׮Q[YSяH =QM#hyș e;O@ "_ge):LHOV+&UUC6=~9W.($H |eGIENDB`libqxt-0.6.2/src/gui/resources/flags/SN.png000066400000000000000000000004041215241066400205300ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME ;YIDAT8cd8z昆7+lr_gqƃU `` {. f!f/6=f````Sx`!rX20$G. _)5\8@]d````xz> T(R3'[IENDB`libqxt-0.6.2/src/gui/resources/flags/SO.png000066400000000000000000000003701215241066400205330ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 6DIDAT8ctL¬ ¬3AA,p21Tx2X(s10000K3tl{_\_ 0Ͽ vaDAY!o38է?1o(C܆#%IENDB`libqxt-0.6.2/src/gui/resources/flags/SR.png000066400000000000000000000004471215241066400205430ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 7 pIDAT8픽AA+\AB xo%4"jOxBtWbW! lT3ə3't+.D SD`bŔw򬌈YaELiGDȸ"p?y$\ ![E a8fLElFw n1XK#y8#DћT ʱ=ub[IENDB`libqxt-0.6.2/src/gui/resources/flags/ST.png000066400000000000000000000004571215241066400205460ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME &S ^IDAT(c,77SFM73^0Ǿd`}I3002b s~.g`  Cᅛ@U|VXoL^.bzE[z~!>c C\-bg Q$2l7f`>A^`0f}Nbp/Ͱ1U f* N9Dy-IENDB`libqxt-0.6.2/src/gui/resources/flags/SV.png000066400000000000000000000003051215241066400205400ustar00rootroot00000000000000PNG  IHDR fMsBIT|d|IDAT8cdPM~~{?#>^^>? Fk 8_A,]Jo?0q..\?B\Pc #^.IENDB`libqxt-0.6.2/src/gui/resources/flags/SY.png000066400000000000000000000003611215241066400205450ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME NIDAT8c<'53g`d`ī.sAWU Xy έ? ;?üfA[so0s3X`uбWw^~`$ #!3) 9o Tsꭂ?IENDB`libqxt-0.6.2/src/gui/resources/flags/SZ.png000066400000000000000000000010311215241066400205410ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME 3"4IDAT8kqor99=:H@"AA\bNɥ $XX)%br5!!]{\"n/|/AĢH "v9(j2GPٚ5@brp0p=Y&3wnj9Bf_BE!66F$TB$c45 '@Ӯ8|i4]D8h3^G`~w|4Zj&tbEUU4M<>lRyi+2I]m;loQ븮eYELu]x++|!nܢ~q fR~Ԍt:|3MJ|>j`cDSR|ճ<O07ǮrYX/WKO""G~Ҿe4:IENDB`libqxt-0.6.2/src/gui/resources/flags/TC.png000066400000000000000000000010001215241066400205070ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME A|IDAT(=Hqk(jE1p(EX~ ՂD vpR*EIj4(FzI<!w?'j EQut~e7&EtQٱL**u'xty9ZuB*+gf-BŻl^I@*$i"v( ~}5A?ba?Uʥ _7̩>\8-څVcbSd{!`#IENDB`libqxt-0.6.2/src/gui/resources/flags/TD.png000066400000000000000000000002271215241066400205220ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME |d"79IDAT8cdPπ\[qLS6+ŏ)U `QG 5x@ \v 3y{CIENDB`libqxt-0.6.2/src/gui/resources/flags/TF.png000066400000000000000000000002221215241066400205170ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME+1"4IDAT8cπ̝Um +pie`)C!5xQG P.,d+deIENDB`libqxt-0.6.2/src/gui/resources/flags/TG.png000066400000000000000000000005401215241066400205230ustar00rootroot00000000000000PNG  IHDR+1bKGDtIME '3oIDAT8c$`e-O Vcb`&lcomme:\LK30F fc)c7c``VexVNg8l0^4Na````x=e ïOH6  _cףܗb3Rß 0y f(PJ, O?H79 HOD v1LDeŧ0IENDB`libqxt-0.6.2/src/gui/resources/flags/TH.png000066400000000000000000000002351215241066400205250ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME +&*?IDAT8c<'2000``dPZ.5^rcy9q6M frN+IENDB`libqxt-0.6.2/src/gui/resources/flags/TJ.png000066400000000000000000000003641215241066400205320ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME$6eiIDAT(풱 1D߆xPP1^R++Ż[Iu ̼e 2K@K^ ыj)U-|[;@``u)l2(4Gl4U[uA0 ̶ e&! B#\;!I2_IENDB`libqxt-0.6.2/src/gui/resources/flags/TK.png000066400000000000000000000010101215241066400205200ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME  )UIDAT(MHTa{qc5hڄ 2 g! %DZV6ԍH5UtcIj3ޯ$^FA=ssQCU`jiяt5>'rCEWUppf-^V.1h@whG"¿MS[ނHGR)_b˝ghEڰ쎗7* >I*D{S}#"L#%q(H)I^ C-Q`x$6xB)EEZ-$0 :fU o.[3]ɲ򁱀e[!5;m[O nK=_$lUIENDB`libqxt-0.6.2/src/gui/resources/flags/TM.png000066400000000000000000000010071215241066400205300ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME  &IDAT8ӽOSQPCK _ƄAl&'\LݜɨQb ME\o˹/`BN>wZߺ ^ƓQq9\Ov* n^d/spBit'DO_Q (*$@wWEt<~XgF6@|N]fJ G'/ 4`Zr}v45IENDB`libqxt-0.6.2/src/gui/resources/flags/TN.png000066400000000000000000000005641215241066400205400ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME47IDAT8ՔJ`MA[Zp, J:8R2_šXѥO`"tP1mOd~=\sF i@SsMe2hu Lk;[ b_«{xn V1cb? _eh>~K366Uc w.#B20ԱKDgm[sX+KR4IV oxyNE6Lz}eC}"PJAJQN+obOhIENDB`libqxt-0.6.2/src/gui/resources/flags/TO.png000066400000000000000000000004031215241066400205310ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME  ="NIDAT(c(ۭ[ml$%a g^@ `B~zX×sH2O'L`8p="vZu 浰`d```` a`‚CA  66?!EO'L`id` h09Q)+llIENDB`libqxt-0.6.2/src/gui/resources/flags/TR.png000066400000000000000000000005561215241066400205450ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME !=#IDAT8c|%, lf Ld̂aO73} ߖ`i}  ~_ Unaen0& 20005fqQn2|ߴxY~_IF EIᅱi.Z =yyt&qQV 5?5=/ c7061du J,ßw}Hx  ^a2IENDB`libqxt-0.6.2/src/gui/resources/flags/TT.png000066400000000000000000000011441215241066400205410ustar00rootroot00000000000000PNG  IHDR cbKGDtIME-cEIDAT8OHqw^LxN(إC(V$ %ȱ`a"HIJH J"![S&PDd{cc[dJ/>BF{qrF,$1<8>;l{'x#2qjeAdaadݭ̍a6r\mjK.Ž-+bMrDGo7_bD"B}]Zΐhlk%S#*p/=ϰQ2[ڶF*Vq(zɮ^R3eÆ mHV'KF1DQ:+uT.l#F^foQT*YԶla< b:.ۋ }օjݻ>o3 |`{}B2a+Ssҙk<Ԁ)yq!Soru{vln& 2!jzHN^C:H .ףiv-"}}$IENDB`libqxt-0.6.2/src/gui/resources/flags/TV.png000066400000000000000000000011271215241066400205440ustar00rootroot00000000000000PNG  IHDR {}~sBIT|dIDAT(OHSq?﷽m9m66Zش,IԺ^A!H;E):EݺTBIuЉ3rAsmnoMWUJʝxdyxw_nƅJ$) ɼ >88y":8r@Kb mM<^%vFUlb%rCq &7:5VSE gXڇ)H(PU%1VWMM\Ra.#, m=qy^` 6j뷣ܙe}_-~{S,iY{߯-8 vKk׈mScllw>Z s;<4G7l0ܤfw 6J4'kjHv>BKM(g^muZfx5ŁaƖӢ'%Ee9vON8fI+[jƔb`ɲS"@Ϟ^t2gbHjnC'/p ofț5B3ڋ]b IENDB`libqxt-0.6.2/src/gui/resources/flags/TW.png000066400000000000000000000004621215241066400205460ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIMEzXIDAT8풱 P-Yh(.νDг( N>AC H-PEO!jP1kOb4dIӜz66A`yC<Eh 5 1өCq]к޿ŕ$ɑG$(JWZeNxM+t]`Y=LYȊ9zS;E<0m .@N;/IENDB`libqxt-0.6.2/src/gui/resources/flags/TZ.png000066400000000000000000000011741215241066400205520ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME ;,IDAT8]HQ]M)*- ,w"$/bV'eSGLŠ,H("D"‹."FKy7*WVps~y8#lgQ(Yug(i%(ɌG^.]Q r Kane(irʊpѩ*'m@k*5fOv;<-mYϮd*4Z/AI|UKh#Fqe{}ckQp{$ Z*9\?j\80_7C/sSYbK:EXux5jS,1Jz pDaECu#S(Nر87ғ3J$GPAӇt{OWIQI/ĸfxb _UZD:h[;s v њ|xa ݔPHV-6t6e ,)0Ҹ0 RKN,.&X*2:2ٶwc- ќ@IENDB`libqxt-0.6.2/src/gui/resources/flags/UA.png000066400000000000000000000002111215241066400205110ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME7PYW+IDAT8c*=< f4XOMǣ`R:IENDB`libqxt-0.6.2/src/gui/resources/flags/UG.png000066400000000000000000000004621215241066400205270ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME ZTq>IDAT8cd``@D CXshc0C,(Yrt19S{yq)-~]9I`.# ޵a I ]4e?x2 2<{a.0ܪ On'h|XPP7=r]Wī?x=Ýw8$d";'1k`rBa AQtaIENDB`libqxt-0.6.2/src/gui/resources/flags/UM.png000066400000000000000000000006371215241066400205410ustar00rootroot00000000000000PNG  IHDR fMbKGDtIME*lAIDAT8JawtD11ӔČ(ąADЪ]tA7ѺhѦ hdhV5?צmYR<5 py[gq.[qQy]Oq$?'iu ZlD61lIvK㭃x.qNLR2mP`^lֺsXz)7y݌TyAu(7XϜýldBѲdR" W3&ƗN:7 B\ H)Q.ĈiQu7S/r9^[ףl˱Ru+9 n&:Rq-0VSM~κ5sE)4dfHil.pt Ð_^{-U 6;\^VWStc`1-RKXfI.e7 :O|= et=a*$Q鞰aRAYdMtV:QpVJ$&(=_y~ɱgj< #QJ)o,=m `D6`gY l&h1יgOIENDB`libqxt-0.6.2/src/gui/resources/flags/VA.png000066400000000000000000000006061215241066400205220ustar00rootroot00000000000000PNG  IHDR bKGDtIMEwA'IDAT8JaG,??2) ˆAҦun}wt -%J*B )4>l7|y9=h[)ˇeתصx/մт!=dWݢyc(1l,#BS! ƌh FVac1kP6e)dĕ?~Z,,cBIENDB`libqxt-0.6.2/src/gui/resources/flags/VC.png000066400000000000000000000004501215241066400205210ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME:3mHIDAT8cd(: eh5^.tPf~!Dn2\+"}fpٯ }&h0 !@i)1'޷8V G (bA;ehŰ8C-%`D' &^#F qK`0gS`;*%`W1$cQ[2H0?IENDB`libqxt-0.6.2/src/gui/resources/flags/VE.png000066400000000000000000000004171215241066400205260ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME)3iIDAT8c~Q? - 502y j n}`/QN١* :* < < :* ١*]̂O=Gom=Grzq(ÓW}EfxwH2yC`2ޤIENDB`libqxt-0.6.2/src/gui/resources/flags/VG.png000066400000000000000000000010411215241066400205220ustar00rootroot00000000000000PNG  IHDR {}~sBIT|dIDAT(?L++B%-$vѩ&ƠuAVuE`\܈u08ʠvj B Ж+zN^thM/{{y?acwɷyffbftj"<Ęwsߊcxc4*y] \`r#A2/7<0;$\oOԘe+cz8^#c|O`&Q֙n$Bq.Ck}K3=-0>kHq'JrdPIcᶑqR$p_T&pABȥsd agoV17jR;˅tګ"JI./3M>W7o/74gIENDB`libqxt-0.6.2/src/gui/resources/flags/VI.png000066400000000000000000000014231215241066400205300ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME  !90nIDAT8IhqI&3$5MZECQjUCPQs CՃb="`ATDA #&m$d:YfDZ }M!اt6Ѕ@~3`2!,33)Ѣ$hH?ӲD8ug!j܁ZEA[d5w`2g_zK6k7{NLˁicKۇ'3d  k/ 8FZɦ#& f7`B;Q|^^&5*Wx[•=kt+r  G%}&ċ:%*%m9?DyY-}[ZZwXPAM@fL|*te ^76²~H4lctkdNa` 0xM^ފn.ջpnCsy0ML8Cst 3P((-YQHɡwf1pF<X+R5HkP% `nB@NGctvp#A"Ϛy?Ue+ZIj$/ ד@sIv.[K!܈WIg$f]``%].n\,˲BݢzU\}S[%6~IENDB`libqxt-0.6.2/src/gui/resources/flags/VN.png000066400000000000000000000005441215241066400205400ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIMEa1IDAT8N0?ǑQ & l4],P+Ut$i!7.jxs-3CnAF풣W9+go}10.|.V~\`E"*W'u4b͗) y̞Z$j(@9[ }+t#J~eW'1yuN`R)C:STeN}X ^CJ: 7Y3EUE57R!TKIENDB`libqxt-0.6.2/src/gui/resources/flags/VU.png000066400000000000000000000007051215241066400205460ustar00rootroot00000000000000PNG  IHDR cbKGDtIME  0*gIDAT8+Cqٙ-ڒl(.HJrG()˕$RK)EpCV"r傔ئlXvAjcZ,bc)d (-_N K @O;,ljQ6 t&ă6|Y;k#^4& rqI0Is]^#u) *$"1sH,M_B`/[ W逓5HWTR*L/98f(64ɔ[%3p^'8؏VdK^`ݗ X['0 "XuB_`ܥB9e+Op)IENDB`libqxt-0.6.2/src/gui/resources/flags/WF.png000066400000000000000000000002221215241066400205220ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME+1"4IDAT8cπ̝Um +pie`)C!5xQG P.,d+deIENDB`libqxt-0.6.2/src/gui/resources/flags/WS.png000066400000000000000000000004061215241066400205430ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME 6NNIDAT(cd0mπE- &d/ n`dgeW' 3H2y߿ ?~!`d֣ML,L E %Pww0ow=c"/ 'tSz))IENDB`libqxt-0.6.2/src/gui/resources/flags/YE.png000066400000000000000000000001641215241066400205300ustar00rootroot00000000000000PNG  IHDRm?hsBIT|d+IDAT8c|?yC`Fy]MOIENDB`libqxt-0.6.2/src/gui/resources/flags/YT.png000066400000000000000000000002221215241066400205420ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME+1"4IDAT8cπ̝Um +pie`)C!5xQG P.,d+deIENDB`libqxt-0.6.2/src/gui/resources/flags/ZA.png000066400000000000000000000010551215241066400205250ustar00rootroot00000000000000PNG  IHDRm?hbKGDtIME#+?HIDAT8_HSa9q;T mb9DBD" B]y/((A.M] "vH<{<|xx߇W`UM n`/AL5%IE L2M|³HoR[gI R}8|]2%L,dx>%/KdewljCNhF'GiS[fE;9L*s"֚01ҽ.?/9G-xk,IENDB`libqxt-0.6.2/src/gui/resources/flags/ZW.png000066400000000000000000000005301215241066400205500ustar00rootroot00000000000000PNG  IHDR {}~bKGDtIME ښfIDAT(J4RpTA: ҥN( 9)O..F)*Ap % JkHӃ[8 NuMa㞯11/ 23V n;t.R?KG_LUh/טjf'WkoY>m}T4UEm[@1M*ё83aH@6$oVrU I[zY1??i zIENDB`libqxt-0.6.2/src/network/000077500000000000000000000000001215241066400153035ustar00rootroot00000000000000libqxt-0.6.2/src/network/network.pri000066400000000000000000000013331215241066400175100ustar00rootroot00000000000000INCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += qxtjsonrpccall.h HEADERS += qxtjsonrpcclient.h HEADERS += qxtnetwork.h HEADERS += qxtmail_p.h HEADERS += qxtsmtp.h HEADERS += qxtmailattachment.h HEADERS += qxtmailmessage.h HEADERS += qxtrpcpeer.h HEADERS += qxtsmtp_p.h HEADERS += qxttcpconnectionmanager.h HEADERS += qxttcpconnectionmanager_p.h HEADERS += qxtxmlrpccall.h HEADERS += qxtxmlrpcclient.h HEADERS += qxtxmlrpc_p.h SOURCES += qxtjsonrpccall.cpp SOURCES += qxtjsonrpcclient.cpp SOURCES += qxtmailattachment.cpp SOURCES += qxtmailmessage.cpp SOURCES += qxtrpcpeer.cpp SOURCES += qxtsmtp.cpp SOURCES += qxttcpconnectionmanager.cpp SOURCES += qxtxmlrpccall.cpp SOURCES += qxtxmlrpcclient.cpp SOURCES += qxtxmlrpc_p.cpp libqxt-0.6.2/src/network/network.pro000066400000000000000000000003131215241066400175130ustar00rootroot00000000000000CLEAN_TARGET = QxtNetwork DEFINES += BUILD_QXT_NETWORK QT = core network QXT = core CONVENIENCE += $$CLEAN_TARGET include(network.pri) include(../qxtbase.pri) libqxt-0.6.2/src/network/qxtjsonrpccall.cpp000066400000000000000000000077041215241066400210660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtJSONRpcCall \inmodule QxtNetwork \brief The QxtJSONRpcCall class represents a Call to an JSON-RPC Service. */ /*! \fn QxtJSONRpcCall::downloadProgress ( qint64 bytesReceived, qint64 bytesTotal ) This signal is emitted to indicate the progress of retreiving the response from the remote service \sa QNetworkReply::downloadProgress() */ /*! \fn QxtJSONRpcCall::error(QNetworkReply::NetworkError code) Signals a network error \sa QNetworkReply::error() */ /*! \fn QxtJSONRpcCall::finished() emitted once the result is fully available \sa QNetworkReply::finished() */ /*! \fn QxtJSONRpcCall::sslErrors ( const QList & errors ); \sa QNetworkReply::sslErrors() */ /*! \fn QxtJSONRpcCall:: uploadProgress() This signal is emitted to indicate the progress of sending the request to the remote service \sa QNetworkReply::uploadProgress() */ #include "qxtjsonrpccall.h" #include #include #include class QxtJSONRpcCallPrivate { public: bool isFault; QNetworkReply * reply; QVariant result; void d_finished(); QxtJSONRpcCall * pub; }; /*! returns true if the remote service sent a fault message */ bool QxtJSONRpcCall::isFault() const { return d->isFault; } /*! returns the result or fault message or a null QVariant() if the call isnt finished yet \sa QxtJSON#type-conversion */ QVariant QxtJSONRpcCall::result() const { return d->result; } /*! returns an associated network error. */ QNetworkReply::NetworkError QxtJSONRpcCall::error() const { return d->reply->error(); } QxtJSONRpcCall::QxtJSONRpcCall(QNetworkReply * reply) : d(new QxtJSONRpcCallPrivate()) { d->isFault = false; d->reply = reply; d->pub = this; connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SIGNAL(downloadProgress(qint64, qint64))); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SIGNAL(error(QNetworkReply::NetworkError))); connect(reply, SIGNAL(sslErrors(const QList &)), this, SIGNAL(sslErrors(const QList &))); connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SIGNAL(uploadProgress(qint64, qint64))); connect(reply, SIGNAL(finished()), this, SLOT(d_finished())); } void QxtJSONRpcCallPrivate::d_finished() { if (!reply->error()) { QVariant m_=QxtJSON::parse(QString::fromUtf8(reply->readAll())); if(m_.isNull()){ qWarning("QxtJSONRpcCall: invalid JSON received"); } QVariantMap m=m_.toMap(); if(m["error"]!=QVariant()){ isFault=true; result=m["error"]; }else{ result=m["result"]; } } emit pub->finished(); } #include "moc_qxtjsonrpccall.cpp" libqxt-0.6.2/src/network/qxtjsonrpccall.h000066400000000000000000000040501215241066400205220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTJSONRPCRESPONSE_H #define QXTJSONRPCRESPONSE_H #include #include #include #include #include "qxtglobal.h" #include class QxtJSONRpcCallPrivate; class QXT_NETWORK_EXPORT QxtJSONRpcCall : public QObject { Q_OBJECT public: bool isFault() const; QVariant result() const; QNetworkReply::NetworkError error() const; signals: void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); void error(QNetworkReply::NetworkError code); void finished(); void sslErrors(const QList & errors); void uploadProgress(qint64 bytesSent, qint64 bytesTotal); protected: QxtJSONRpcCall(QNetworkReply * reply); friend class QxtJSONRpcClient; private: friend class QxtJSONRpcCallPrivate; std::auto_ptr d; Q_PRIVATE_SLOT(d, void d_finished()); }; #endif libqxt-0.6.2/src/network/qxtjsonrpcclient.cpp000066400000000000000000000062621215241066400214270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtJSONRpcClient \inmodule QxtNetwork \brief The QxtJSONRpcClient class implements a JSON-RPC Client. Implements a Client that can communicate with services implementing the JSON-RPC spec http://json-rpc.org/wiki/specification \sa QxtJSON */ #include "qxtjsonrpcclient.h" #include "qxtjsonrpccall.h" #include #include #include #include struct QxtJSONRpcClient::Private { int callid; QUrl url; QNetworkAccessManager * networkManager; }; QxtJSONRpcClient::QxtJSONRpcClient(QObject * parent) : QObject(parent) , d(new Private()) { d->callid=0; d->networkManager = new QNetworkAccessManager(this); } /*! returns the url of the remote service */ QUrl QxtJSONRpcClient::serviceUrl() const { return d->url; } /*! sets the url of the remote service to \a url */ void QxtJSONRpcClient::setServiceUrl(QUrl url) { d->url = url; } /*! returns the QNetworkAccessManager used for connecting to the remote service */ QNetworkAccessManager * QxtJSONRpcClient::networkManager() const { return d->networkManager; } /*! sets the QNetworkAccessManager used for connecting to the remote service to \a manager */ void QxtJSONRpcClient::setNetworkManager(QNetworkAccessManager * manager) { delete d->networkManager; d->networkManager = manager; } /*! calls the remote \a method with \a arguments and returns a QxtJSONRpcCall wrapping it. you can connect to QxtJSONRpcCall's signals to retreive the status of the call. */ QxtJSONRpcCall * QxtJSONRpcClient::call(QString method, QVariantList arguments) { QVariantMap m; m["id"]=d->callid++; m["method"]=method; m["params"]=arguments; QNetworkRequest request; request.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain; charset=utf-8"); request.setRawHeader("Connection", "close"); request.setUrl(d->url); return new QxtJSONRpcCall(d->networkManager->post(request, QxtJSON::stringify(m).toUtf8())); } libqxt-0.6.2/src/network/qxtjsonrpcclient.h000066400000000000000000000035141215241066400210710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTJSONRPCCLIENT_H #define QXTJSONRPCCLIENT_H #include #include #include #include #include "qxtglobal.h" #include class QxtJSONRpcCall; class QNetworkAccessManager; class QXT_NETWORK_EXPORT QxtJSONRpcClient : public QObject { Q_OBJECT public: QxtJSONRpcClient(QObject * parent = 0); QUrl serviceUrl() const; void setServiceUrl(QUrl uri); QNetworkAccessManager * networkManager() const; void setNetworkManager(QNetworkAccessManager * manager); QxtJSONRpcCall * call(QString method, QVariantList arguments); private: struct Private; const std::auto_ptr d; }; #endif libqxt-0.6.2/src/network/qxtmail_p.h000066400000000000000000000027671215241066400174660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTMAIL_P_H #define QXTMAIL_P_H #include #define QXT_MUST_QP(x) (x < char(32) || x > char(126) || x == '=' || x == '?') QByteArray qxt_fold_mime_header(const QString& key, const QString& value, QTextCodec* latin1, const QByteArray& prefix = QByteArray()); #endif // QXTMAIL_P_H libqxt-0.6.2/src/network/qxtmailattachment.cpp000066400000000000000000000126541215241066400215470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! * \class QxtMailAttachment * \inmodule QxtNetwork * \brief The QxtMailAttachment class represents an attachement to a QxtMailMessage */ #include "qxtmailattachment.h" #include "qxtmail_p.h" #include #include #include #include #include struct QxtMailAttachmentPrivate : public QSharedData { QHash extraHeaders; QString contentType; QPointer content; bool deleteContent; QxtMailAttachmentPrivate() { content = 0; deleteContent = false; contentType = "text/plain"; } ~QxtMailAttachmentPrivate() { if (deleteContent && content) content->deleteLater(); deleteContent = false; content = 0; } }; QxtMailAttachment::QxtMailAttachment() { qxt_d = new QxtMailAttachmentPrivate; } QxtMailAttachment::QxtMailAttachment(const QxtMailAttachment& other) : qxt_d(other.qxt_d) { // trivial copy constructor } QxtMailAttachment::QxtMailAttachment(const QByteArray& content, const QString& contentType) { qxt_d = new QxtMailAttachmentPrivate; setContentType(contentType); setContent(content); } QxtMailAttachment::QxtMailAttachment(QIODevice* content, const QString& contentType) { qxt_d = new QxtMailAttachmentPrivate; setContentType(contentType); setContent(content); } QxtMailAttachment& QxtMailAttachment::operator=(const QxtMailAttachment & other) { qxt_d = other.qxt_d; return *this; } QxtMailAttachment::~QxtMailAttachment() { // trivial destructor } QIODevice* QxtMailAttachment::content() const { return qxt_d->content; } void QxtMailAttachment::setContent(const QByteArray& content) { if (qxt_d->deleteContent && qxt_d->content) qxt_d->content->deleteLater(); qxt_d->content = new QBuffer; static_cast(qxt_d->content.data())->setData(content); } void QxtMailAttachment::setContent(QIODevice* content) { if (qxt_d->deleteContent && qxt_d->content) qxt_d->content->deleteLater(); qxt_d->content = content; } bool QxtMailAttachment::deleteContent() const { return qxt_d->deleteContent; } void QxtMailAttachment::setDeleteContent(bool enable) { qxt_d->deleteContent = enable; } QString QxtMailAttachment::contentType() const { return qxt_d->contentType; } void QxtMailAttachment::setContentType(const QString& contentType) { qxt_d->contentType = contentType; } QHash QxtMailAttachment::extraHeaders() const { return qxt_d->extraHeaders; } QString QxtMailAttachment::extraHeader(const QString& key) const { return qxt_d->extraHeaders[key.toLower()]; } bool QxtMailAttachment::hasExtraHeader(const QString& key) const { return qxt_d->extraHeaders.contains(key.toLower()); } void QxtMailAttachment::setExtraHeader(const QString& key, const QString& value) { qxt_d->extraHeaders[key.toLower()] = value; } void QxtMailAttachment::setExtraHeaders(const QHash& a) { QHash& headers = qxt_d->extraHeaders; headers.clear(); foreach(const QString& key, a.keys()) { headers[key.toLower()] = a[key]; } } void QxtMailAttachment::removeExtraHeader(const QString& key) { qxt_d->extraHeaders.remove(key.toLower()); } QByteArray QxtMailAttachment::mimeData() { QIODevice* c = content(); if (!c) { qWarning() << "QxtMailAttachment::mimeData(): Content not set or already output"; return QByteArray(); } if (!c->isOpen() && !c->open(QIODevice::ReadOnly)) { qWarning() << "QxtMailAttachment::mimeData(): Cannot open content for reading"; return QByteArray(); } QTextCodec* latin1 = QTextCodec::codecForName("latin1"); QByteArray rv = "Content-Type: " + qxt_d->contentType.toAscii() + "\r\nContent-Transfer-Encoding: base64\r\n"; foreach(const QString& r, qxt_d->extraHeaders.keys()) { rv += qxt_fold_mime_header(r.toAscii(), extraHeader(r), latin1); } rv += "\r\n"; while (!c->atEnd()) { rv += c->read(57).toBase64() + "\r\n"; } setContent((QIODevice*)0); return rv; } QxtMailAttachment QxtMailAttachment::fromFile(const QString& filename) { QxtMailAttachment rv(new QFile(filename)); rv.setDeleteContent(true); return rv; } libqxt-0.6.2/src/network/qxtmailattachment.h000066400000000000000000000052351215241066400212110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTMAILATTACHMENT_H #define QXTMAILATTACHMENT_H #include "qxtglobal.h" #include #include #include #include #include class QxtMailAttachmentPrivate; class QXT_NETWORK_EXPORT QxtMailAttachment { public: QxtMailAttachment(); QxtMailAttachment(const QxtMailAttachment& other); QxtMailAttachment(const QByteArray& content, const QString& contentType = QString("application/octet-stream")); QxtMailAttachment(QIODevice* content, const QString& contentType = QString("application/octet-stream")); QxtMailAttachment& operator=(const QxtMailAttachment& other); ~QxtMailAttachment(); static QxtMailAttachment fromFile(const QString& filename); QIODevice* content() const; void setContent(const QByteArray& content); void setContent(QIODevice* content); bool deleteContent() const; void setDeleteContent(bool enable); QString contentType() const; void setContentType(const QString& contentType); QHash extraHeaders() const; QString extraHeader(const QString&) const; bool hasExtraHeader(const QString&) const; void setExtraHeader(const QString& key, const QString& value); void setExtraHeaders(const QHash&); void removeExtraHeader(const QString& key); QByteArray mimeData(); private: QSharedDataPointer qxt_d; }; Q_DECLARE_TYPEINFO(QxtMailAttachment, Q_MOVABLE_TYPE); #endif // QXTMAILATTACHMENT_H libqxt-0.6.2/src/network/qxtmailmessage.cpp000066400000000000000000000361411215241066400210400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! * \class QxtMailMessage * \inmodule QxtNetwork * \brief The QxtMailMessage class encapsulates an e-mail according to RFC 2822 and related specifications * TODO: {implicitshared} */ #include "qxtmailmessage.h" #include "qxtmail_p.h" #include #include #include #include struct QxtMailMessagePrivate : public QSharedData { QxtMailMessagePrivate() {} QxtMailMessagePrivate(const QxtMailMessagePrivate& other) : QSharedData(other), rcptTo(other.rcptTo), rcptCc(other.rcptCc), rcptBcc(other.rcptBcc), subject(other.subject), body(other.body), sender(other.sender), extraHeaders(other.extraHeaders), attachments(other.attachments) {} QStringList rcptTo, rcptCc, rcptBcc; QString subject, body, sender; QHash extraHeaders; QHash attachments; mutable QByteArray boundary; }; QxtMailMessage::QxtMailMessage() { qxt_d = new QxtMailMessagePrivate; } QxtMailMessage::QxtMailMessage(const QxtMailMessage& other) : qxt_d(other.qxt_d) { // trivial copy constructor } QxtMailMessage::QxtMailMessage(const QString& sender, const QString& recipient) { qxt_d = new QxtMailMessagePrivate; setSender(sender); addRecipient(recipient); } QxtMailMessage::~QxtMailMessage() { // trivial destructor } QxtMailMessage& QxtMailMessage::operator=(const QxtMailMessage & other) { qxt_d = other.qxt_d; return *this; } QString QxtMailMessage::sender() const { return qxt_d->sender; } void QxtMailMessage::setSender(const QString& a) { qxt_d->sender = a; } QString QxtMailMessage::subject() const { return qxt_d->subject; } void QxtMailMessage::setSubject(const QString& a) { qxt_d->subject = a; } QString QxtMailMessage::body() const { return qxt_d->body; } void QxtMailMessage::setBody(const QString& a) { qxt_d->body = a; } QStringList QxtMailMessage::recipients(QxtMailMessage::RecipientType type) const { if (type == Bcc) return qxt_d->rcptBcc; if (type == Cc) return qxt_d->rcptCc; return qxt_d->rcptTo; } void QxtMailMessage::addRecipient(const QString& a, QxtMailMessage::RecipientType type) { if (type == Bcc) qxt_d->rcptBcc.append(a); else if (type == Cc) qxt_d->rcptCc.append(a); else qxt_d->rcptTo.append(a); } void QxtMailMessage::removeRecipient(const QString& a) { qxt_d->rcptTo.removeAll(a); qxt_d->rcptCc.removeAll(a); qxt_d->rcptBcc.removeAll(a); } QHash QxtMailMessage::extraHeaders() const { return qxt_d->extraHeaders; } QString QxtMailMessage::extraHeader(const QString& key) const { return qxt_d->extraHeaders[key.toLower()]; } bool QxtMailMessage::hasExtraHeader(const QString& key) const { return qxt_d->extraHeaders.contains(key.toLower()); } void QxtMailMessage::setExtraHeader(const QString& key, const QString& value) { qxt_d->extraHeaders[key.toLower()] = value; } void QxtMailMessage::setExtraHeaders(const QHash& a) { QHash& headers = qxt_d->extraHeaders; headers.clear(); foreach(const QString& key, a.keys()) { headers[key.toLower()] = a[key]; } } void QxtMailMessage::removeExtraHeader(const QString& key) { qxt_d->extraHeaders.remove(key.toLower()); } QHash QxtMailMessage::attachments() const { return qxt_d->attachments; } QxtMailAttachment QxtMailMessage::attachment(const QString& filename) const { return qxt_d->attachments[filename]; } void QxtMailMessage::addAttachment(const QString& filename, const QxtMailAttachment& attach) { if (qxt_d->attachments.contains(filename)) { qWarning() << "QxtMailMessage::addAttachment: " << filename << " already in use"; int i = 1; while (qxt_d->attachments.contains(filename + "." + QString::number(i))) { i++; } qxt_d->attachments[filename+"."+QString::number(i)] = attach; } else { qxt_d->attachments[filename] = attach; } } void QxtMailMessage::removeAttachment(const QString& filename) { qxt_d->attachments.remove(filename); } QByteArray qxt_fold_mime_header(const QString& key, const QString& value, QTextCodec* latin1, const QByteArray& prefix) { QByteArray rv = ""; QByteArray line = key.toAscii() + ": "; if (!prefix.isEmpty()) line += prefix; if (!value.contains("=?") && latin1->canEncode(value)) { bool firstWord = true; foreach(const QByteArray& word, value.toAscii().split(' ')) { if (line.size() > 78) { rv = rv + line + "\r\n"; line.clear(); } if (firstWord) line += word; else line += " " + word; firstWord = false; } } else { // The text cannot be losslessly encoded as Latin-1. Therefore, we // must use quoted-printable or base64 encoding. This is a quick // heuristic based on the first 100 characters to see which // encoding to use. QByteArray utf8 = value.toUtf8(); int ct = utf8.length(); int nonAscii = 0; for (int i = 0; i < ct && i < 100; i++) { if (QXT_MUST_QP(utf8[i])) nonAscii++; } if (nonAscii > 20) { // more than 20%-ish non-ASCII characters: use base64 QByteArray base64 = utf8.toBase64(); ct = base64.length(); line += "=?utf-8?b?"; for (int i = 0; i < ct; i += 4) { if (line.length() > 72) { rv += line + "?\r\n"; line = " =?utf-8?b?"; } line = line + base64.mid(i, 4); } } else { // otherwise use Q-encoding line += "=?utf-8?q?"; for (int i = 0; i < ct; i++) { if (line.length() > 73) { rv += line + "?\r\n"; line = " =?utf-8?q?"; } if (QXT_MUST_QP(utf8[i]) || utf8[i] == ' ') { line += "=" + utf8.mid(i, 1).toHex().toUpper(); } else { line += utf8[i]; } } } line += "?="; // end encoded-word atom } return rv + line + "\r\n"; } QByteArray QxtMailMessage::rfc2822() const { // Use quoted-printable if requested bool useQuotedPrintable = (extraHeader("Content-Transfer-Encoding").toLower() == "quoted-printable"); // Use base64 if requested bool useBase64 = (extraHeader("Content-Transfer-Encoding").toLower() == "base64"); // Check to see if plain text is ASCII-clean; assume it isn't if QP or base64 was requested QTextCodec* latin1 = QTextCodec::codecForName("latin1"); bool bodyIsAscii = latin1->canEncode(body()) && !useQuotedPrintable && !useBase64; QHash attach = attachments(); QByteArray rv; if (!sender().isEmpty() && !hasExtraHeader("From")) { rv += qxt_fold_mime_header("From", sender(), latin1); } if (!qxt_d->rcptTo.isEmpty()) { rv += qxt_fold_mime_header("To", qxt_d->rcptTo.join(", "), latin1); } if (!qxt_d->rcptCc.isEmpty()) { rv += qxt_fold_mime_header("Cc", qxt_d->rcptCc.join(", "), latin1); } if (!subject().isEmpty()) { rv += qxt_fold_mime_header("Subject", subject(), latin1); } if (!bodyIsAscii) { if (!hasExtraHeader("MIME-Version") && !attach.count()) rv += "MIME-Version: 1.0\r\n"; // If no transfer encoding has been requested, guess. // Heuristic: If >20% of the first 100 characters aren't // 7-bit clean, use base64, otherwise use Q-P. if(!bodyIsAscii && !useQuotedPrintable && !useBase64) { QString b = body(); int nonAscii = 0; int ct = b.length(); for (int i = 0; i < ct && i < 100; i++) { if (QXT_MUST_QP(b[i])) nonAscii++; } useQuotedPrintable = !(nonAscii > 20); useBase64 = !useQuotedPrintable; } } if (attach.count()) { if (qxt_d->boundary.isEmpty()) qxt_d->boundary = QUuid::createUuid().toString().toAscii().replace("{", "").replace("}", ""); if (!hasExtraHeader("MIME-Version")) rv += "MIME-Version: 1.0\r\n"; if (!hasExtraHeader("Content-Type")) rv += "Content-Type: multipart/mixed; boundary=" + qxt_d->boundary + "\r\n"; } else if (!bodyIsAscii && !hasExtraHeader("Content-Transfer-Encoding")) { if (!useQuotedPrintable) { // base64 rv += "Content-Transfer-Encoding: base64\r\n"; } else { // quoted-printable rv += "Content-Transfer-Encoding: quoted-printable\r\n"; } } foreach(const QString& r, qxt_d->extraHeaders.keys()) { if ((r.toLower() == "content-type" || r.toLower() == "content-transfer-encoding") && attach.count()) { // Since we're in multipart mode, we'll be outputting this later continue; } rv += qxt_fold_mime_header(r.toAscii(), extraHeader(r), latin1); } rv += "\r\n"; if (attach.count()) { // we're going to have attachments, so output the lead-in for the message body rv += "This is a message with multiple parts in MIME format.\r\n"; rv += "--" + qxt_d->boundary + "\r\nContent-Type: "; if (hasExtraHeader("Content-Type")) rv += extraHeader("Content-Type") + "\r\n"; else rv += "text/plain; charset=UTF-8\r\n"; if (hasExtraHeader("Content-Transfer-Encoding")) { rv += "Content-Transfer-Encoding: " + extraHeader("Content-Transfer-Encoding") + "\r\n"; } else if (!bodyIsAscii) { if (!useQuotedPrintable) { // base64 rv += "Content-Transfer-Encoding: base64\r\n"; } else { // quoted-printable rv += "Content-Transfer-Encoding: quoted-printable\r\n"; } } rv += "\r\n"; } if (bodyIsAscii) { QByteArray b = latin1->fromUnicode(body()); int len = b.length(); QByteArray line = ""; QByteArray word = ""; for (int i = 0; i < len; i++) { if (b[i] == '\n' || b[i] == '\r') { if (line.isEmpty()) { line = word; word = ""; } else if (line.length() + word.length() + 1 <= 78) { line = line + ' ' + word; word = ""; } if(line[0] == '.') rv += "."; rv += line + "\r\n"; if ((b[i+1] == '\n' || b[i+1] == '\r') && b[i] != b[i+1]) { // If we're looking at a CRLF pair, skip the second half i++; } line = word; } else if (b[i] == ' ') { if (line.length() + word.length() + 1 > 78) { if(line[0] == '.') rv += "."; rv += line + "\r\n"; line = word; } else if (line.isEmpty()) { line = word; } else { line = line + ' ' + word; } word = ""; } else { word += b[i]; } } if (line.length() + word.length() + 1 > 78) { if(line[0] == '.') rv += "."; rv += line + "\r\n"; line = word; } else if (!word.isEmpty()) { line += ' ' + word; } if(!line.isEmpty()) { if(line[0] == '.') rv += "."; rv += line + "\r\n"; } } else if (useQuotedPrintable) { QByteArray b = body().toUtf8(); int ct = b.length(); QByteArray line; for (int i = 0; i < ct; i++) { if(b[i] == '\n' || b[i] == '\r') { if(line[0] == '.') rv += "."; rv += line + "\r\n"; line = ""; if ((b[i+1] == '\n' || b[i+1] == '\r') && b[i] != b[i+1]) { // If we're looking at a CRLF pair, skip the second half i++; } } else if (line.length() > 74) { rv += line + "=\r\n"; line = ""; } if (QXT_MUST_QP(b[i])) { line += "=" + b.mid(i, 1).toHex().toUpper(); } else { line += b[i]; } } if(!line.isEmpty()) { if(line[0] == '.') rv += "."; rv += line + "\r\n"; } } else /* base64 */ { QByteArray b = body().toUtf8().toBase64(); int ct = b.length(); for (int i = 0; i < ct; i += 78) { rv += b.mid(i, 78) + "\r\n"; } } if (attach.count()) { foreach(const QString& filename, attach.keys()) { rv += "--" + qxt_d->boundary + "\r\n"; rv += qxt_fold_mime_header("Content-Disposition", QDir(filename).dirName(), latin1, "attachment; filename="); rv += attach[filename].mimeData(); } rv += "--" + qxt_d->boundary + "--\r\n"; } return rv; } libqxt-0.6.2/src/network/qxtmailmessage.h000066400000000000000000000054731215241066400205110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTMAILMESSAGE_H #define QXTMAILMESSAGE_H #include "qxtglobal.h" #include "qxtmailattachment.h" #include #include #include #include struct QxtMailMessagePrivate; class QXT_NETWORK_EXPORT QxtMailMessage { public: enum RecipientType { To, Cc, Bcc }; QxtMailMessage(); QxtMailMessage(const QxtMailMessage& other); QxtMailMessage(const QString& sender, const QString& recipient); QxtMailMessage& operator=(const QxtMailMessage& other); ~QxtMailMessage(); QString sender() const; void setSender(const QString&); QString subject() const; void setSubject(const QString&); QString body() const; void setBody(const QString&); QStringList recipients(RecipientType type = To) const; void addRecipient(const QString&, RecipientType type = To); void removeRecipient(const QString&); QHash extraHeaders() const; QString extraHeader(const QString&) const; bool hasExtraHeader(const QString&) const; void setExtraHeader(const QString& key, const QString& value); void setExtraHeaders(const QHash&); void removeExtraHeader(const QString& key); QHash attachments() const; QxtMailAttachment attachment(const QString& filename) const; void addAttachment(const QString& filename, const QxtMailAttachment& attach); void removeAttachment(const QString& filename); QByteArray rfc2822() const; private: QSharedDataPointer qxt_d; }; Q_DECLARE_TYPEINFO(QxtMailMessage, Q_MOVABLE_TYPE); #endif // QXTMAIL_H libqxt-0.6.2/src/network/qxtnetwork.h000066400000000000000000000030221215241066400176770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtNetwork module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTNETWORK_H_INCLUDED #define QXTNETWORK_H_INCLUDED #include "qxtjsonrpcclient.h" #include "qxtjsonrpcresponse.h" #include "qxtmailmessage.h" #include "qxtmailattachment.h" #include "qxtsmtp.h" #include "qxtrpcpeer.h" #include "qxttcpconnectionmanager.h" #include "qxtxmlrpcclient.h" #include "qxtxmlrpcresponse.h" #endif // QXTNETWORK_H_INCLUDED libqxt-0.6.2/src/network/qxtrpcpeer.cpp000066400000000000000000000127311215241066400202100ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtNetwork module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtrpcpeer.h" #include "qxttcpconnectionmanager.h" #include class QxtRPCPeerPrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtRPCPeer) QTcpSocket* getTcpSocket() { QxtRPCPeer* p = &qxt_p(); QTcpSocket* socket = new QTcpSocket(p); QObject::connect(socket, SIGNAL(connected()), p, SIGNAL(connectedToServer())); QObject::connect(socket, SIGNAL(disconnected()), p, SIGNAL(disconnectedFromServer())); QObject::connect(socket, SIGNAL(disconnected()), p, SLOT(disconnectServer())); QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), p, SIGNAL(serverError(QAbstractSocket::SocketError))); QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), p, SLOT(disconnectServer())); p->setDevice(socket); return socket; } }; /*! * \class QxtRPCPeer * \inmodule QxtNetwork * \brief The QxtRPCPeer class transmits Qt signals over a network connection * * QxtRPCPeer is a tool that encapsulates Qt signals and transmits them over a network connection. * The signal is subsequently re-emitted on the receiving end of the connection. * * As a QxtRPCService subclass, QxtRPCPeer can act as a client or a server. When acting as a server, * it uses a QxtTcpConnectionManager to accept connections. When acting as a client, applications * may use connect() to establish a TCP connection with a server. * * All data types used in attached signals and slots must be declared and registered with QMetaType using * Q_DECLARE_METATYPE and qRegisterMetaType. Additional requirements may be imposed by the * QxtAbstractSignalSerializer subclass in use; the default QxtDataStreamSignalSerializer requires * that they have stream operators registered with qRegisterMetaTypeStreamOperators. * * Due to a restriction of Qt's signals and slots mechanism, the number of parameters that can be passed * to call() and its related functions, as well as the number of parameters to any signal or slot attached * to QxtRPCPeer, is limited to 8. */ /*! * Creates a QxtRPCPeer object with the given \a parent. */ QxtRPCPeer::QxtRPCPeer(QObject* parent) : QxtRPCService(parent) { QXT_INIT_PRIVATE(QxtRPCPeer); setConnectionManager(new QxtTcpConnectionManager(this)); } /*! * Connects to the specified server \a addr on the selected \a port. * * When the connection is complete, the connectedToServer() signal will be emitted. If an error occurs, the serverError() signal will be emitted. */ void QxtRPCPeer::connect(QHostAddress addr, int port) { qxt_d().getTcpSocket()->connectToHost(addr, port); } /*! * Connects to the specified peer or server \a addr on the selected \a port. * * When the connection is complete, the connectedToServer() signal will be emitted. If an error occurs, the serverError() signal will be emitted. */ void QxtRPCPeer::connect(QString addr, int port) { qxt_d().getTcpSocket()->connectToHost(addr, port); } /*! * Listens on the specified interface \a iface on the specified \a port for connections. * * Attempting to listen while in Client mode or while connected in Peer mode will be ignored with a warning. In Peer mode, only one connection * can be active at a time. Additional incoming connections while connected to a peer will be dropped. When a peer connects, the peerConnected() * signal will be emitted. In Server mode, multiple connections can be active at a time. Each client that connects will be provided a unique ID, * included in the clientConnected() signal that will be emitted. Returns \c true if succeeds, \c false otherwise. */ bool QxtRPCPeer::listen(QHostAddress iface, int port) { QxtTcpConnectionManager* mgr = qobject_cast(connectionManager()); if (!mgr) { qWarning() << "QxtRPCPeer::listen: cannot listen with non-QxtTcpConnectionManager"; return false; } return mgr->listen(iface, port); } /*! * Stops listening for connections. Any connections still open will remain connected. */ void QxtRPCPeer::stopListening() { QxtTcpConnectionManager* mgr = qobject_cast(connectionManager()); if (!mgr) { qWarning() << "QxtRPCPeer::listen: cannot stop listening with non-QxtTcpConnectionManager"; } else { mgr->stopListening(); } } libqxt-0.6.2/src/network/qxtrpcpeer.h000066400000000000000000000041371215241066400176560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtNetwork module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTRPCPEER_H #define QXTRPCPEER_H #include #include #include #include class QxtRPCPeerPrivate; class QXT_NETWORK_EXPORT QxtRPCPeer : public QxtRPCService { Q_OBJECT public: QxtRPCPeer(QObject* parent = 0); void connect(QHostAddress addr, int port = 80); void connect(QString addr, int port = 80); bool listen(QHostAddress iface = QHostAddress::Any, int port = 80); void stopListening(); Q_SIGNALS: /*! * This signal is emitted after a successful connection to a server. */ void connectedToServer(); /*! * This signal is emitted after disconnecting from a server. */ void disconnectedFromServer(); /*! * This signal is emitted if an error occurs on the socket connected to the server. */ void serverError(QAbstractSocket::SocketError); private: QXT_DECLARE_PRIVATE(QxtRPCPeer) }; #endif libqxt-0.6.2/src/network/qxtsmtp.cpp000066400000000000000000000403511215241066400175320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! * \class QxtSmtp * \inmodule QxtNetwork * \brief The QxtSmtp class implements the SMTP protocol for sending email */ #include "qxtsmtp.h" #include "qxtsmtp_p.h" #include "qxthmac.h" #include #include #include #ifndef QT_NO_OPENSSL # include #endif QxtSmtpPrivate::QxtSmtpPrivate() : QObject(0) { // empty ctor } QxtSmtp::QxtSmtp(QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtSmtp); qxt_d().state = QxtSmtpPrivate::Disconnected; qxt_d().nextID = 0; #ifndef QT_NO_OPENSSL qxt_d().socket = new QSslSocket(this); QObject::connect(socket(), SIGNAL(encrypted()), this, SIGNAL(encrypted())); //QObject::connect(socket(), SIGNAL(encrypted()), &qxt_d(), SLOT(ehlo())); #else qxt_d().socket = new QTcpSocket(this); #endif QObject::connect(socket(), SIGNAL(connected()), this, SIGNAL(connected())); QObject::connect(socket(), SIGNAL(disconnected()), this, SIGNAL(disconnected())); QObject::connect(socket(), SIGNAL(error(QAbstractSocket::SocketError)), &qxt_d(), SLOT(socketError(QAbstractSocket::SocketError))); QObject::connect(this, SIGNAL(authenticated()), &qxt_d(), SLOT(sendNext())); QObject::connect(socket(), SIGNAL(readyRead()), &qxt_d(), SLOT(socketRead())); } QByteArray QxtSmtp::username() const { return qxt_d().username; } void QxtSmtp::setUsername(const QByteArray& username) { qxt_d().username = username; } QByteArray QxtSmtp::password() const { return qxt_d().password; } void QxtSmtp::setPassword(const QByteArray& password) { qxt_d().password = password; } int QxtSmtp::send(const QxtMailMessage& message) { int messageID = ++qxt_d().nextID; qxt_d().pending.append(qMakePair(messageID, message)); if (qxt_d().state == QxtSmtpPrivate::Waiting) qxt_d().sendNext(); return messageID; } int QxtSmtp::pendingMessages() const { return qxt_d().pending.count(); } QTcpSocket* QxtSmtp::socket() const { return qxt_d().socket; } void QxtSmtp::connectToHost(const QString& hostName, quint16 port) { qxt_d().useSecure = false; qxt_d().state = QxtSmtpPrivate::StartState; socket()->connectToHost(hostName, port); } void QxtSmtp::connectToHost(const QHostAddress& address, quint16 port) { connectToHost(address.toString(), port); } void QxtSmtp::disconnectFromHost() { socket()->disconnectFromHost(); } bool QxtSmtp::startTlsDisabled() const { return qxt_d().disableStartTLS; } void QxtSmtp::setStartTlsDisabled(bool disable) { qxt_d().disableStartTLS = disable; } #ifndef QT_NO_OPENSSL QSslSocket* QxtSmtp::sslSocket() const { return qxt_d().socket; } void QxtSmtp::connectToSecureHost(const QString& hostName, quint16 port) { qxt_d().useSecure = true; qxt_d().state = QxtSmtpPrivate::StartState; sslSocket()->connectToHostEncrypted(hostName, port); } void QxtSmtp::connectToSecureHost(const QHostAddress& address, quint16 port) { connectToSecureHost(address.toString(), port); } #endif bool QxtSmtp::hasExtension(const QString& extension) { return qxt_d().extensions.contains(extension); } QString QxtSmtp::extensionData(const QString& extension) { return qxt_d().extensions[extension]; } void QxtSmtpPrivate::socketError(QAbstractSocket::SocketError err) { if (err == QAbstractSocket::SslHandshakeFailedError) { emit qxt_p().encryptionFailed(); emit qxt_p().encryptionFailed( socket->errorString().toAscii() ); } else if (state == StartState) { emit qxt_p().connectionFailed(); emit qxt_p().connectionFailed( socket->errorString().toAscii() ); } } void QxtSmtpPrivate::socketRead() { buffer += socket->readAll(); while (true) { int pos = buffer.indexOf("\r\n"); if (pos < 0) return; QByteArray line = buffer.left(pos); buffer = buffer.mid(pos + 2); QByteArray code = line.left(3); switch (state) { case StartState: if (code[0] != '2') { socket->disconnectFromHost(); } else { ehlo(); } break; case HeloSent: case EhloSent: case EhloGreetReceived: parseEhlo(code, (line[3] != ' '), line.mid(4)); break; #ifndef QT_NO_OPENSSL case StartTLSSent: if (code == "220") { socket->startClientEncryption(); ehlo(); } else { authenticate(); } break; #endif case AuthRequestSent: case AuthUsernameSent: if (authType == AuthPlain) authPlain(); else if (authType == AuthLogin) authLogin(); else authCramMD5(line.mid(4)); break; case AuthSent: if (code[0] == '2') { state = Authenticated; emit qxt_p().authenticated(); } else { state = Disconnected; emit qxt_p().authenticationFailed(); emit qxt_p().authenticationFailed( line ); emit socket->disconnectFromHost(); } break; case MailToSent: case RcptAckPending: if (code[0] != '2') { emit qxt_p().mailFailed( pending.first().first, code.toInt() ); emit qxt_p().mailFailed(pending.first().first, code.toInt(), line); // pending.removeFirst(); // DO NOT remove it, the body sent state needs this message to assigned the next mail failed message that will // the sendNext // a reset will be sent to clear things out sendNext(); state = BodySent; } else sendNextRcpt(code, line); break; case SendingBody: sendBody(code, line); break; case BodySent: if ( pending.count() ) { // if you removeFirst in RcpActpending/MailToSent on an error, and the queue is now empty, // you will get into this state and then crash because no check is done. CHeck added but shouldnt // be necessary since I commented out the removeFirst if (code[0] != '2') { emit qxt_p().mailFailed(pending.first().first, code.toInt() ); emit qxt_p().mailFailed(pending.first().first, code.toInt(), line); } else emit qxt_p().mailSent(pending.first().first); pending.removeFirst(); } sendNext(); break; case Resetting: if (code[0] != '2') { emit qxt_p().connectionFailed(); emit qxt_p().connectionFailed( line ); } else { state = Waiting; sendNext(); } break; } } } void QxtSmtpPrivate::ehlo() { QByteArray address = "127.0.0.1"; foreach(const QHostAddress& addr, QNetworkInterface::allAddresses()) { if (addr == QHostAddress::LocalHost || addr == QHostAddress::LocalHostIPv6) continue; address = addr.toString().toAscii(); break; } socket->write("ehlo " + address + "\r\n"); extensions.clear(); state = EhloSent; } void QxtSmtpPrivate::parseEhlo(const QByteArray& code, bool cont, const QString& line) { if (code != "250") { // error! if (state != HeloSent) { // maybe let's try HELO socket->write("helo\r\n"); state = HeloSent; } else { // nope socket->write("QUIT\r\n"); socket->flush(); socket->disconnectFromHost(); } return; } else if (state != EhloGreetReceived) { if (!cont) { // greeting only, no extensions state = EhloDone; } else { // greeting followed by extensions state = EhloGreetReceived; return; } } else { extensions[line.section(' ', 0, 0).toUpper()] = line.section(' ', 1); if (!cont) state = EhloDone; } if (state != EhloDone) return; if (extensions.contains("STARTTLS") && !disableStartTLS) { startTLS(); } else { authenticate(); } } void QxtSmtpPrivate::startTLS() { #ifndef QT_NO_OPENSSL socket->write("starttls\r\n"); state = StartTLSSent; #else authenticate(); #endif } void QxtSmtpPrivate::authenticate() { if (!extensions.contains("AUTH") || username.isEmpty() || password.isEmpty()) { state = Authenticated; emit qxt_p().authenticated(); } else { QStringList auth = extensions["AUTH"].toUpper().split(' ', QString::SkipEmptyParts); if (auth.contains("CRAM-MD5")) { authCramMD5(); } else if (auth.contains("PLAIN")) { authPlain(); } else if (auth.contains("LOGIN")) { authLogin(); } else { state = Authenticated; emit qxt_p().authenticated(); } } } void QxtSmtpPrivate::authCramMD5(const QByteArray& challenge) { if (state != AuthRequestSent) { socket->write("auth cram-md5\r\n"); authType = AuthCramMD5; state = AuthRequestSent; } else { QxtHmac hmac(QCryptographicHash::Md5); hmac.setKey(password); hmac.addData(QByteArray::fromBase64(challenge)); QByteArray response = username + ' ' + hmac.result().toHex(); socket->write(response.toBase64() + "\r\n"); state = AuthSent; } } void QxtSmtpPrivate::authPlain() { if (state != AuthRequestSent) { socket->write("auth plain\r\n"); authType = AuthPlain; state = AuthRequestSent; } else { QByteArray auth; auth += '\0'; auth += username; auth += '\0'; auth += password; socket->write(auth.toBase64() + "\r\n"); state = AuthSent; } } void QxtSmtpPrivate::authLogin() { if (state != AuthRequestSent && state != AuthUsernameSent) { socket->write("auth login\r\n"); authType = AuthLogin; state = AuthRequestSent; } else if (state == AuthRequestSent) { socket->write(username.toBase64() + "\r\n"); state = AuthUsernameSent; } else { socket->write(password.toBase64() + "\r\n"); state = AuthSent; } } static QByteArray qxt_extract_address(const QString& address) { int parenDepth = 0; int addrStart = -1; bool inQuote = false; int ct = address.length(); for (int i = 0; i < ct; i++) { QChar ch = address[i]; if (inQuote) { if (ch == '"') inQuote = false; } else if (addrStart != -1) { if (ch == '>') return address.mid(addrStart, (i - addrStart)).toAscii(); } else if (ch == '(') { parenDepth++; } else if (ch == ')') { parenDepth--; if (parenDepth < 0) parenDepth = 0; } else if (ch == '"') { if (parenDepth == 0) inQuote = true; } else if (ch == '<') { if (!inQuote && parenDepth == 0) addrStart = i + 1; } } return address.toAscii(); } void QxtSmtpPrivate::sendNext() { if (state == Disconnected) { // leave the mail in the queue if not ready to send return; } if (pending.isEmpty()) { // if there are no additional mails to send, finish up state = Waiting; emit qxt_p().finished(); return; } if(state != Waiting) { state = Resetting; socket->write("rset\r\n"); return; } const QxtMailMessage& msg = pending.first().second; rcptNumber = rcptAck = mailAck = 0; recipients = msg.recipients(QxtMailMessage::To) + msg.recipients(QxtMailMessage::Cc) + msg.recipients(QxtMailMessage::Bcc); if (recipients.count() == 0) { // can't send an e-mail with no recipients emit qxt_p().mailFailed(pending.first().first, QxtSmtp::NoRecipients ); emit qxt_p().mailFailed(pending.first().first, QxtSmtp::NoRecipients, QByteArray( "e-mail has no recipients" ) ); pending.removeFirst(); sendNext(); return; } // We explicitly use lowercase keywords because for some reason gmail // interprets any string starting with an uppercase R as a request // to renegotiate the SSL connection. socket->write("mail from:<" + qxt_extract_address(msg.sender()) + ">\r\n"); if (extensions.contains("PIPELINING")) // almost all do nowadays { foreach(const QString& rcpt, recipients) { socket->write("rcpt to:<" + qxt_extract_address(rcpt) + ">\r\n"); } state = RcptAckPending; } else { state = MailToSent; } } void QxtSmtpPrivate::sendNextRcpt(const QByteArray& code, const QByteArray&line) { int messageID = pending.first().first; const QxtMailMessage& msg = pending.first().second; if (code[0] != '2') { // on failure, emit a warning signal if (!mailAck) { emit qxt_p().senderRejected(messageID, msg.sender()); emit qxt_p().senderRejected(messageID, msg.sender(), line ); } else { emit qxt_p().recipientRejected(messageID, msg.sender()); emit qxt_p().recipientRejected(messageID, msg.sender(), line); } } else if (!mailAck) { mailAck = true; } else { rcptAck++; } if (rcptNumber == recipients.count()) { // all recipients have been sent if (rcptAck == 0) { // no recipients were considered valid emit qxt_p().mailFailed(messageID, code.toInt() ); emit qxt_p().mailFailed(messageID, code.toInt(), line); pending.removeFirst(); sendNext(); } else { // at least one recipient was acknowledged, send mail body socket->write("data\r\n"); state = SendingBody; } } else if (state != RcptAckPending) { // send the next recipient unless we're only waiting on acks socket->write("rcpt to:<" + qxt_extract_address(recipients[rcptNumber]) + ">\r\n"); rcptNumber++; } else { // If we're only waiting on acks, just count them rcptNumber++; } } void QxtSmtpPrivate::sendBody(const QByteArray& code, const QByteArray & line) { int messageID = pending.first().first; const QxtMailMessage& msg = pending.first().second; if (code[0] != '3') { emit qxt_p().mailFailed(messageID, code.toInt() ); emit qxt_p().mailFailed(messageID, code.toInt(), line); pending.removeFirst(); sendNext(); return; } socket->write(msg.rfc2822()); socket->write(".\r\n"); state = BodySent; } libqxt-0.6.2/src/network/qxtsmtp.h000066400000000000000000000070711215241066400172010ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSMTP_H #define QXTSMTP_H #include #include #include #include "qxtglobal.h" #include "qxtmailmessage.h" class QTcpSocket; #ifndef QT_NO_OPENSSL class QSslSocket; #endif class QxtSmtpPrivate; class QXT_NETWORK_EXPORT QxtSmtp : public QObject { Q_OBJECT public: enum SmtpError { NoError, NoRecipients, CommandUnrecognized = 500, SyntaxError, CommandNotImplemented, BadSequence, ParameterNotImplemented, MailboxUnavailable = 550, UserNotLocal, MessageTooLarge, InvalidMailboxName, TransactionFailed }; QxtSmtp(QObject* parent = 0); QByteArray username() const; void setUsername(const QByteArray& name); QByteArray password() const; void setPassword(const QByteArray& password); int send(const QxtMailMessage& message); int pendingMessages() const; QTcpSocket* socket() const; void connectToHost(const QString& hostName, quint16 port = 25); void connectToHost(const QHostAddress& address, quint16 port = 25); void disconnectFromHost(); bool startTlsDisabled() const; void setStartTlsDisabled(bool disable); #ifndef QT_NO_OPENSSL QSslSocket* sslSocket() const; void connectToSecureHost(const QString& hostName, quint16 port = 465); void connectToSecureHost(const QHostAddress& address, quint16 port = 465); #endif bool hasExtension(const QString& extension); QString extensionData(const QString& extension); Q_SIGNALS: void connected(); void connectionFailed(); void connectionFailed( const QByteArray & msg ); void encrypted(); void encryptionFailed(); void encryptionFailed( const QByteArray & msg ); void authenticated(); void authenticationFailed(); void authenticationFailed( const QByteArray & msg ); void senderRejected(int mailID, const QString& address ); void senderRejected(int mailID, const QString& address, const QByteArray & msg ); void recipientRejected(int mailID, const QString& address ); void recipientRejected(int mailID, const QString& address, const QByteArray & msg ); void mailFailed(int mailID, int errorCode); void mailFailed(int mailID, int errorCode, const QByteArray & msg); void mailSent(int mailID); void finished(); void disconnected(); private: QXT_DECLARE_PRIVATE(QxtSmtp) }; #endif // QXTSMTP_H libqxt-0.6.2/src/network/qxtsmtp_p.h000066400000000000000000000057041215241066400175210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSMTP_P_H #define QXTSMTP_P_H #include "qxtsmtp.h" #include #include #include #include class QxtSmtpPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QxtSmtpPrivate(); QXT_DECLARE_PUBLIC(QxtSmtp) enum SmtpState { Disconnected, StartState, EhloSent, EhloGreetReceived, EhloExtensionsReceived, EhloDone, HeloSent, StartTLSSent, AuthRequestSent, AuthUsernameSent, AuthSent, Authenticated, MailToSent, RcptAckPending, SendingBody, BodySent, Waiting, Resetting }; enum AuthType { AuthPlain, AuthLogin, AuthCramMD5 }; bool useSecure, disableStartTLS; SmtpState state;// rather then an int use the enum. makes sure invalid states are entered at compile time, and makes debugging easier AuthType authType; QByteArray buffer, username, password; QHash extensions; QList > pending; QStringList recipients; int nextID, rcptNumber, rcptAck; bool mailAck; #ifndef QT_NO_OPENSSL QSslSocket* socket; #else QTcpSocket* socket; #endif void parseEhlo(const QByteArray& code, bool cont, const QString& line); void startTLS(); void authenticate(); void authCramMD5(const QByteArray& challenge = QByteArray()); void authPlain(); void authLogin(); void sendNextRcpt(const QByteArray& code, const QByteArray & line); void sendBody(const QByteArray& code, const QByteArray & line); public slots: void socketError(QAbstractSocket::SocketError err); void socketRead(); void ehlo(); void sendNext(); }; #endif // QXTSMTP_P_H libqxt-0.6.2/src/network/qxttcpconnectionmanager.cpp000066400000000000000000000131051215241066400227450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtNetwork module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxttcpconnectionmanager.h" #include "qxttcpconnectionmanager_p.h" #include #include /*! * \class QxtTcpConnectionManager * \inmodule QxtNetwork * \brief The QxtTcpConnectionManager class accepts TCP connections and maintains a connection pool * * QxtTcpConnectionManager is a standardized interface for accepting and tracking * incoming TCP connections. * * Each incoming connection is assigned an arbitrary, opaque client ID number. This * number can be used to retrieve the QTcpSocket associated with it. A list of IDs * for all current connections can be retrieved with the clients() function. * * Like QTcpServer, QxtTcpConnectionManager can listen for incoming connections on * a specified interface and port, and like QTcpServer you may override the * incomingConnection() function to change the handling of new connections. This * is, for instance, where you would create a QSslSocket to encrypt communications. * * \sa QTcpServer */ /*! * Constructs a new QxtTcpConnectionManager object with the specified \a parent. */ QxtTcpConnectionManager::QxtTcpConnectionManager(QObject* parent) : QxtAbstractConnectionManager(parent) { QXT_INIT_PRIVATE(QxtTcpConnectionManager); } QxtTcpConnectionManagerPrivate::QxtTcpConnectionManagerPrivate() : QTcpServer(0) { QObject::connect(&mapper, SIGNAL(mapped(QObject*)), this, SLOT(socketDisconnected(QObject*))); } void QxtTcpConnectionManagerPrivate::incomingConnection(int socketDescriptor) { QIODevice* device = qxt_p().incomingConnection(socketDescriptor); if (device) { qxt_p().addConnection(device, (quint64)static_cast(device)); mapper.setMapping(device, device); QObject::connect(device, SIGNAL(destroyed()), &mapper, SLOT(map())); QTcpSocket* sock = qobject_cast(device); if (sock) { QObject::connect(sock, SIGNAL(error(QAbstractSocket::SocketError)), &mapper, SLOT(map())); QObject::connect(sock, SIGNAL(disconnected()), &mapper, SLOT(map())); } } } /*! * Listens on the specified interface \a iface on the specified \a port for connections. * If \a iface is QHostAddress::Any, listens on all interfaces. * * Returns \c true on success; otherwise returns \c false. */ bool QxtTcpConnectionManager::listen(QHostAddress iface, int port) { return qxt_d().listen(iface, port); } /*! * Stops listening for connections. Any connections still open will remain connected. */ void QxtTcpConnectionManager::stopListening() { if (!qxt_d().isListening()) { qWarning() << "QxtTcpConnectionManager: Not listening"; return; } qxt_d().close(); } /*! * \reimp */ bool QxtTcpConnectionManager::isAcceptingConnections() const { return qxt_d().isListening(); } /*! * This function is called when a new TCP connection becomes available. The parameter * is the native \a socketDescriptor for the connection, suitable for use in * QTcpSocket::setSocketDescriptor. * * The default implementation returns a new QTcpSocket with the specified descriptor. * Subclasses may return QTcpSocket subclasses, such as QSslSocket. */ QIODevice* QxtTcpConnectionManager::incomingConnection(int socketDescriptor) { QTcpSocket* device = new QTcpSocket(this); device->setSocketDescriptor(socketDescriptor); return device; } /*! * \reimp */ void QxtTcpConnectionManager::removeConnection(QIODevice* device, quint64 clientID) { Q_UNUSED(clientID); if (device) { QAbstractSocket* sock = qobject_cast(device); if (sock) sock->disconnectFromHost(); device->close(); device->deleteLater(); } } /*! * Sets an explicit network \a proxy for the connection manager. * * \sa QTcpServer::setProxy() */ void QxtTcpConnectionManager::setProxy(const QNetworkProxy& proxy) { qxt_d().setProxy(proxy); } /*! * Returns the proxy in use for the connection manager. * * \sa QTcpServer::proxy() */ QNetworkProxy QxtTcpConnectionManager::proxy() const { return qxt_d().proxy(); } void QxtTcpConnectionManagerPrivate::socketDisconnected(QObject* client) { QTcpSocket* sock = qobject_cast(client); if (sock) { QObject::disconnect(sock, SIGNAL(error(QAbstractSocket::SocketError)), &mapper, SLOT(map())); QObject::disconnect(sock, SIGNAL(disconnected()), &mapper, SLOT(map())); } qxt_p().disconnect((quint64)(client)); } libqxt-0.6.2/src/network/qxttcpconnectionmanager.h000066400000000000000000000037501215241066400224170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtNetwork module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTCPCONNECTIONMANAGER_H #define QXTTCPCONNECTIONMANAGER_H #include #include #include QT_FORWARD_DECLARE_CLASS(QIODevice) class QxtTcpConnectionManagerPrivate; class QXT_NETWORK_EXPORT QxtTcpConnectionManager : public QxtAbstractConnectionManager { Q_OBJECT public: QxtTcpConnectionManager(QObject* parent); bool listen(QHostAddress iface = QHostAddress::Any, int port = 80); void stopListening(); bool isAcceptingConnections() const; void setProxy(const QNetworkProxy& proxy); QNetworkProxy proxy() const; protected: virtual QIODevice* incomingConnection(int socketDescriptor); virtual void removeConnection(QIODevice* device, quint64 clientID); private: QXT_DECLARE_PRIVATE(QxtTcpConnectionManager) }; #endif libqxt-0.6.2/src/network/qxttcpconnectionmanager_p.h000066400000000000000000000033421215241066400227330ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtNetwork module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTTCPCONNECTIONMANAGER_P_H #define QXTTCPCONNECTIONMANAGER_P_H #include #include #include #include class QxtTcpConnectionManagerPrivate : public QTcpServer, public QxtPrivate { Q_OBJECT public: QxtTcpConnectionManagerPrivate(); QXT_DECLARE_PUBLIC(QxtTcpConnectionManager) protected: void incomingConnection(int socketDescriptor); private Q_SLOTS: void socketDisconnected(QObject* client); private: QSignalMapper mapper; }; #endif libqxt-0.6.2/src/network/qxtxmlrpc_p.cpp000066400000000000000000000247041215241066400203770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include #include #include #include #include #include "qxtxmlrpc_p.h" using namespace QxtXmlRpc; QString xmlEncode(QString a) { return a.replace('&', "&") .replace('<', "<") .replace('>', ">"); } QString QxtXmlRpc::serialize(QVariant data) { if (data.isNull()) { return ""; } int t = data.type(); if (t == QVariant::String) { return "" + xmlEncode(data.toString()) + ""; } else if (t == QVariant::Bool) { return "" + (data.toBool() ? QString("1") : QString("0")) + ""; } else if (t == QVariant::Int) { return "" + QString::number(data.toInt()) + ""; } else if (t == QVariant::Double) { return "" + QString::number(data.toDouble()) + ""; } else if (t == QVariant::DateTime) { return "" + data.toDateTime().toString(Qt::ISODate) + ""; } else if (t == QVariant::ByteArray) { return "" + data.toByteArray().toBase64() + ""; } else if (t == QVariant::Map) { QString ret = ""; QMap map = data.toMap(); QMapIterator i(map); while (i.hasNext()) { i.next(); ret += "" + i.key() + "" + serialize(i.value()) + ""; } ret += ""; return ret; } #if QT_VERSION >= 0x040500 else if (t == QVariant::Hash) { QString ret = ""; QHash map = data.toHash(); QHashIterator i(map); while (i.hasNext()) { i.next(); ret += "" + i.key() + "" + serialize(i.value()) + ""; } ret += ""; return ret; } #endif else if (t == QVariant::StringList) { QString ret = ""; QStringList l = data.toStringList(); foreach(QString i, l) { ret += "" + xmlEncode(i) + ""; } ret += ""; return ret; } else if (t == QVariant::List) { QString ret = ""; QVariantList l = data.toList(); foreach(QVariant i, l) { ret += "" + serialize(i) + ""; } ret += ""; return ret; } else { return ""; } } QVariant deserializeArray(QXmlStreamReader & xml) { QVariantList l; int s = 0; while (!xml.atEnd()) { xml.readNext(); if (xml.isStartElement()) { if (s == 0) { if (xml.name().toString() == "data") { s = 1; } else { xml.raiseError("expected . got : <" + xml.name().toString() + ">"); } } else if (s == 1) { if (xml.name().toString() == "value") { l += deserialize(xml); s = 2; if (xml.isEndElement() && xml.name().toString() == "value"){ s=1; } } else { xml.raiseError("expected . got : <" + xml.name().toString() + ">"); } } else if (s == 2) { xml.raiseError("expected . got : <" + xml.name().toString() + ">"); } } else if (xml.isEndElement()) { if (s == 2) { if (xml.name().toString() == "value") { s = 1; } else { xml.raiseError("expected . got : "); } } else if (s == 1) { if (xml.name().toString() == "data") { s = -1; } else { xml.raiseError("expected . got : "); } } else if (s == -1) { if (xml.name().toString() == "array") { return l; } else { xml.raiseError("expected . got : "); } } else if (s == 0) { xml.raiseError("expected . got : "); } } } return QVariant(); } QVariant deserializeStruct(QXmlStreamReader & xml) { QVariantMap l; QString key; QVariant value; int s = 0; while (!xml.atEnd()) { xml.readNext(); if (xml.isStartElement()) { if (s == 0) { if (xml.name().toString() == "member") { s = 1; } else { xml.raiseError("expected . got : <" + xml.name().toString() + ">"); } } else if (s == 1) { if (xml.name().toString() == "name") { key = xml.readElementText(); } else if (xml.name().toString() == "value") { value = deserialize(xml); s = 2; if (xml.isEndElement() && xml.name().toString() == "value"){ s=1; } } else { xml.raiseError("expected or . got : <" + xml.name().toString() + ">"); } } else if (s == 2) { xml.raiseError("expected . got : <" + xml.name().toString() + ">"); } else if (s == 3) { xml.raiseError("expected . got : <" + xml.name().toString() + ">"); } } else if (xml.isEndElement()) { if (s == 2) { if (xml.name().toString() == "value") { s = 1; } else { xml.raiseError("expected . got : "); } } else if (s == 1) { if (xml.name().toString() == "member") { l[key] = value; s = 0; } else { xml.raiseError("expected . got : "); } } else if (s == 0) { if (xml.name().toString() == "struct") { return l; } else { xml.raiseError("expected . got : "); } } } } return QVariant(); } QVariant QxtXmlRpc::deserialize(QXmlStreamReader & xml) { QVariant ret; while (!xml.atEnd()) { xml.readNext(); if (xml.isStartElement()) { if (xml.name().toString() == "array") { return deserializeArray(xml); } else if (xml.name().toString() == "base64") { return QByteArray::fromBase64(xml.readElementText().toAscii()); } else if (xml.name().toString() == "boolean") { return (xml.readElementText().toInt() == 1); } else if (xml.name().toString() == "dateTime.iso8601") { return QDateTime::fromString(xml.readElementText(), Qt::ISODate); } else if (xml.name().toString() == "double") { return xml.readElementText().toDouble(); } else if (xml.name().toString() == "integer" || xml.name().toString() == "i4") { return xml.readElementText().toInt(); } else if (xml.name().toString() == "string") { return xml.readElementText(); } else if (xml.name().toString() == "struct") { return deserializeStruct(xml); } else { ret = QVariant(); } } // The spec say, "If no type is indicated, the type is string." else if (xml.isCharacters()) { return xml.text().toString(); } else if (xml.isEndElement() && xml.name().toString() == "value") { return QString(""); } } return QVariant(); } libqxt-0.6.2/src/network/qxtxmlrpc_p.h000066400000000000000000000024701215241066400200400ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include namespace QxtXmlRpc { QString serialize(QVariant data); QVariant deserialize(QXmlStreamReader & xml); }; libqxt-0.6.2/src/network/qxtxmlrpccall.cpp000066400000000000000000000133501215241066400207070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtXmlRpcCall \inmodule QxtNetwork \brief The QxtXmlRpcCall class represents a Call to an XMLRPC Service. */ /*! \fn QxtXmlRpcCall::downloadProgress ( qint64 bytesReceived, qint64 bytesTotal ) This signal is emitted to indicate the progress of retreiving the response from the remote service \sa QNetworkReply::downloadProgress() */ /*! \fn QxtXmlRpcCall::error(QNetworkReply::NetworkError code) Signals a network error \sa QNetworkReply::error() */ /*! \fn QxtXmlRpcCall::finished() emitted once the result is fully available \sa QNetworkReply::finished() */ /*! \fn QxtXmlRpcCall::sslErrors ( const QList & errors ); \sa QNetworkReply::sslErrors() */ /*! \fn QxtXmlRpcCall:: uploadProgress() This signal is emitted to indicate the progress of sending the request to the remote service \sa QNetworkReply::uploadProgress() */ #include "qxtxmlrpccall.h" #include "qxtxmlrpc_p.h" #include #include class QxtXmlRpcCallPrivate { public: bool isFault; QNetworkReply * reply; QVariant result; void d_finished(); QxtXmlRpcCall * pub; }; /*! returns true if the remote service sent a fault message */ bool QxtXmlRpcCall::isFault() const { return d->isFault; } /*! returns the result or fault message or a null QVariant() if the call isnt finished yet \sa QxtXmlRpcClient#type-conversion */ QVariant QxtXmlRpcCall::result() const { return d->result; } /*! returns an associated network error. */ QNetworkReply::NetworkError QxtXmlRpcCall::error() const { return d->reply->error(); } QxtXmlRpcCall::QxtXmlRpcCall(QNetworkReply * reply) : d(new QxtXmlRpcCallPrivate()) { d->isFault = false; d->reply = reply; d->pub = this; connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SIGNAL(downloadProgress(qint64, qint64))); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SIGNAL(error(QNetworkReply::NetworkError))); connect(reply, SIGNAL(sslErrors(const QList &)), this, SIGNAL(sslErrors(const QList &))); connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SIGNAL(uploadProgress(qint64, qint64))); connect(reply, SIGNAL(finished()), this, SLOT(d_finished())); } void QxtXmlRpcCallPrivate::d_finished() { if (!reply->error()) { int s = 0; QXmlStreamReader xml(reply->readAll()); while (!xml.atEnd()) { xml.readNext(); if (xml.isStartElement()) { if (s == 0) { if (xml.name().toString() == "methodResponse") { s = 1; } else { xml.raiseError("expected , got:<" + xml.name().toString() + ">"); } } else if (s == 1) { if (xml.name().toString() == "params") { s = 2; } else if (xml.name().toString() == "fault") { isFault = true; s = 3; } else { xml.raiseError("expected or , got:<" + xml.name().toString() + ">"); } } else if (s == 2) { if (xml.name().toString() == "param") { s = 3; } else { xml.raiseError("expected , got:<" + xml.name().toString() + ">"); } } else if (s == 3) { if (xml.name().toString() == "value") { result = QxtXmlRpc::deserialize(xml); s = 4; } else { xml.raiseError("expected , got:<" + xml.name().toString() + ">"); } } } } if (xml.hasError()) { qWarning("QxtXmlRpcCall: %s at line %lld column %lld", xml.errorString().toLocal8Bit().data(), xml.lineNumber(), xml.columnNumber()); } } emit pub->finished(); } #include "moc_qxtxmlrpccall.cpp" libqxt-0.6.2/src/network/qxtxmlrpccall.h000066400000000000000000000040401215241066400203500ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTXMLRPCRESPONSE_H #define QXTXMLRPCRESPONSE_H #include #include #include #include #include "qxtglobal.h" #include class QxtXmlRpcCallPrivate; class QXT_NETWORK_EXPORT QxtXmlRpcCall : public QObject { Q_OBJECT public: bool isFault() const; QVariant result() const; QNetworkReply::NetworkError error() const; signals: void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); void error(QNetworkReply::NetworkError code); void finished(); void sslErrors(const QList & errors); void uploadProgress(qint64 bytesSent, qint64 bytesTotal); protected: QxtXmlRpcCall(QNetworkReply * reply); friend class QxtXmlRpcClient; private: friend class QxtXmlRpcCallPrivate; std::auto_ptr d; Q_PRIVATE_SLOT(d, void d_finished()); }; #endif libqxt-0.6.2/src/network/qxtxmlrpcclient.cpp000066400000000000000000000073531215241066400212600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtXmlRpcClient \inmodule QxtNetwork \brief The QxtXmlRpcClient class implements an XML-RPC Client. Implements a Client that can communicate with services implementing the XML-RPC spec http://www.xmlrpc.com/spec \section2 Type Conversion \table 80% \header \o XML-RPC Type \o Qt Type \row \o array \o QVariantList \row \o base64 \o QByteArray (decoded from base64 to raw) \row \o boolean \o bool \row \o dateTime \o QDateTime \row \o double \o double \row \o int \o int \row \o i4 \o int \row \o string \o QString \row \o struct \o QVariantMap \row \o nil \o QVariant() \endtable */ #include "qxtxmlrpcclient.h" #include "qxtxmlrpccall.h" #include "qxtxmlrpc_p.h" #include #include #include struct QxtXmlRpcClient::Private { QUrl url; QNetworkAccessManager * networkManager; void serialize(QVariant); }; QxtXmlRpcClient::QxtXmlRpcClient(QObject * parent) : QObject(parent) , d(new Private()) { d->networkManager = new QNetworkAccessManager(this); } /*! returns the url of the remote service */ QUrl QxtXmlRpcClient::serviceUrl() const { return d->url; } /*! sets the url of the remote service to \a url */ void QxtXmlRpcClient::setServiceUrl(QUrl url) { d->url = url; } /*! returns the QNetworkAccessManager used for connecting to the remote service */ QNetworkAccessManager * QxtXmlRpcClient::networkManager() const { return d->networkManager; } /*! sets the QNetworkAccessManager used for connecting to the remote service to \a manager */ void QxtXmlRpcClient::setNetworkManager(QNetworkAccessManager * manager) { delete d->networkManager; d->networkManager = manager; } /*! calls the remote \a method with \a arguments and returns a QxtXmlRpcCall wrapping it. you can connect to QxtXmlRpcCall's signals to retreive the status of the call. */ QxtXmlRpcCall * QxtXmlRpcClient::call(QString method, QVariantList arguments) { QByteArray data = "" + method.toUtf8() + ""; foreach(QVariant i, arguments) { data += "" + QxtXmlRpc::serialize(i).toUtf8() + ""; } data += ""; QNetworkRequest request; request.setHeader(QNetworkRequest::ContentTypeHeader, "text/xml"); request.setRawHeader("Connection", "close"); request.setUrl(d->url); return new QxtXmlRpcCall(d->networkManager->post(request, data)); } libqxt-0.6.2/src/network/qxtxmlrpcclient.h000066400000000000000000000035061215241066400207210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTXMLRPCCLIENT_H #define QXTXMLRPCCLIENT_H #include #include #include #include #include "qxtglobal.h" #include class QxtXmlRpcCall; class QNetworkAccessManager; class QXT_NETWORK_EXPORT QxtXmlRpcClient : public QObject { Q_OBJECT public: QxtXmlRpcClient(QObject * parent = 0); QUrl serviceUrl() const; void setServiceUrl(QUrl uri); QNetworkAccessManager * networkManager() const; void setNetworkManager(QNetworkAccessManager * manager); QxtXmlRpcCall * call(QString method, QVariantList arguments); private: struct Private; const std::auto_ptr d; }; #endif libqxt-0.6.2/src/qxtbase.pri000066400000000000000000000057641215241066400160110ustar00rootroot00000000000000TEMPLATE = lib !win32:VERSION = 0.6.2 DESTDIR = $${QXT_BUILD_TREE}/lib win32:DLLDESTDIR = $${QXT_BUILD_TREE}/bin target.path = $${QXT_INSTALL_LIBS} win32:dlltarget.path = $${QXT_INSTALL_BINS} headers.path = $${QXT_INSTALL_HEADERS}/$${CLEAN_TARGET} contains(CONVENIENCE, $${CLEAN_TARGET}){ for(header,HEADERS){ headers.files += $$header } headers.files += $${QXT_SOURCE_TREE}/include/$${CLEAN_TARGET}/* } INSTALLS += target headers win32:INSTALLS += dlltarget defineReplace(qxtLibraryTarget) { unset(LIBRARY_NAME) LIBRARY_NAME = $$1 mac:!static:contains(QT_CONFIG, qt_framework) { QMAKE_FRAMEWORK_BUNDLE_NAME = $$LIBRARY_NAME export(QMAKE_FRAMEWORK_BUNDLE_NAME) } contains(TEMPLATE, .*lib):CONFIG(debug, debug|release) { !debug_and_release|build_pass { mac:RET = $$member(LIBRARY_NAME, 0) else:win32:RET = $$member(LIBRARY_NAME, 0)d } } isEmpty(RET):RET = $$LIBRARY_NAME return($$RET) } TARGET = $$qxtLibraryTarget($$CLEAN_TARGET) include(qxtlibs.pri) macx { CONFIG(qt_no_framework): CONFIG += absolute_library_soname CONFIG(qt_framework, qt_framework|qt_no_framework): CONFIG += lib_bundle FRAMEWORK_HEADERS.version = Versions FRAMEWORK_HEADERS.files = $${HEADERS} FRAMEWORK_HEADERS.path = Headers QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS QMAKE_LFLAGS += -F$${QXT_BUILD_TREE}/lib } win32-msvc|win32-msvc2005|win32-msvc2008: QMAKE_LFLAGS_DEBUG += /PDB:$$DESTDIR/$${TARGET}.pdb astyle.params += --pad=oper astyle.params += --unpad=paren astyle.params += --convert-tabs astyle.params += --brackets=break astyle.params += --indent-namespaces astyle.commands = astyle $$astyle.params $$HEADERS $$SOURCES QMAKE_EXTRA_TARGETS += astyle # cannot use .moc/.obj with gcov ("cannot open graph file") !symbian:!contains(CONFIG, coverage) { CONFIG(debug, debug|release) { MOC_DIR = debug/.moc OBJECTS_DIR = debug/.obj RCC_DIR = debug/.rcc } else { MOC_DIR = release/.moc OBJECTS_DIR = release/.obj RCC_DIR = release/.rcc } } QMAKE_CLEAN += *.gcda *.gcno contains(CONFIG, coverage) { QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage QMAKE_LIBS += -lgcov zerocounters.commands = @lcov --directory \$(OBJECTS_DIR) --zerocounters QMAKE_EXTRA_UNIX_TARGETS *= zerocounters capture.commands = @mkdir -p ../../coverage capture.commands += && lcov --directory \$(OBJECTS_DIR) --capture --output-file ../../coverage/\$(QMAKE_TARGET).cov capture.filters = \"/usr/*\" \"moc_*.cpp\" \"qrc_*.cpp\" capture.commands += && lcov --remove ../../coverage/\$(QMAKE_TARGET).cov $$capture.filters --output-file ../../coverage/\$(QMAKE_TARGET).cov QMAKE_EXTRA_UNIX_TARGETS *= capture genhtml.commands = @genhtml --output-directory ../../coverage/\$(QMAKE_TARGET) ../../coverage/\$(QMAKE_TARGET).cov genhtml.commands += && xdg-open ../../coverage/\$(QMAKE_TARGET)/index.html QMAKE_EXTRA_UNIX_TARGETS *= genhtml } libqxt-0.6.2/src/qxtlibs.pri000066400000000000000000000017001215241066400160120ustar00rootroot00000000000000INCLUDEPATH += $${QXT_SOURCE_TREE}/include DEPENDPATH += $${QXT_SOURCE_TREE}/include QMAKE_RPATHDIR += $${QXT_BUILD_TREE}/lib macx:LIBS += -F$${QXT_BUILD_TREE}/lib LIBS += -L$${QXT_BUILD_TREE}/lib defineTest(qxtAddLibrary) { INCLUDEPATH += $${QXT_SOURCE_TREE}/src/$$1 INCLUDEPATH += $${QXT_SOURCE_TREE}/include/$$2 DEPENDPATH += $${QXT_SOURCE_TREE}/src/$$1 DEPENDPATH += $${QXT_SOURCE_TREE}/include/$$2 qtAddLibrary($$2) } contains(QXT, berkeley) { qxtAddLibrary(berkeley, QxtBerkeley) QXT += core } contains(QXT, web) { qxtAddLibrary(web, QxtWeb) QXT += core network QT += network } contains(QXT, gui) { qxtAddLibrary(gui, QxtGui) QXT += core QT += gui } contains(QXT, network) { qxtAddLibrary(network, QxtNetwork) QXT += core QT += network } contains(QXT, sql) { qxtAddLibrary(sql, QxtSql) QXT += core QT += sql } contains(QXT, core) { qxtAddLibrary(core, QxtCore) } libqxt-0.6.2/src/sql/000077500000000000000000000000001215241066400144115ustar00rootroot00000000000000libqxt-0.6.2/src/sql/qxtsql.h000066400000000000000000000024661215241066400161260ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtSql module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSQL_H_INCLUDED #define QXTSQL_H_INCLUDED #include "qxtsqlpackage.h" #include "qxtsqlpackagemodel.h" #endif // QXTSQL_H_INCLUDED libqxt-0.6.2/src/sql/qxtsqlpackage.cpp000066400000000000000000000150131215241066400177650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtSql module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtsqlpackage.h" #include #include #include #include #include #include /*! \class QxtSqlPackage \inmodule QxtSql \brief The QxtSqlPackage class provides a full serializable QSqlQuery storage Sometimes you want to send sql results over network or store them into files. QxtSqlPackage can provide you a storage that is still valid after the actual QSqlQuery has been destroyed. for confidence the interface is similar to QSqlQuery. */ /*! \fn bool QxtSqlPackage::isValid() \brief determinates if the package curently points to a valid row */ /*! \fn int QxtSqlPackage::at() \brief curent pointer position */ /*! \fn bool QxtSqlPackage::next() \brief point to next entry returns false if there is no next entry. provided for easy porting from QSqlQuery. \code while (query.next()) { } \endcode */ /*! \fn bool QxtSqlPackage::last(); \brief point to last entry in storage */ /*! \fn bool QxtSqlPackage::first(); \brief point to first entry in storage */ /*! \fn QString QxtSqlPackage::value(const QString& key); \brief return a column in current row in contrast to QSqlQuery you have to provide the name of the \a key. the entry is returned as QString becouse in most cases you need QString anyway, and converting to needed data type is easy. \code QString name = query.value("name"); \endcode */ /*! \fn void QxtSqlPackage::insert(QSqlQuery query); \brief read from \a query read out a QSqlQuery and store the result. you may close the query after reading, the data will stay. \code QxSqlPackage::insert(QSqlQuery::exec("select name,foo,bar from table;")); \endcode */ /*! \fn int QxtSqlPackage::count() const; \brief Returns the number of rows stored */ /*! \fn QByteArray QxtSqlPackage::data() const; \brief Returns serialised data */ /*! \fn void QxtSqlPackage::setData(const QByteArray& data); \brief Deserialise \a data */ /*! \fn QHash QxtSqlPackage::hash(int index); \brief return a specific \a index as Hash */ /*! \fn QHash QxtSqlPackage::hash(); \brief return the curent row as Hash */ /*! \fn QxtSqlPackage& QxtSqlPackage::operator= (const QxtSqlPackage& other); \brief copy \a other */ /*! Constructs a QxtSqlPackage with \a parent. */ QxtSqlPackage::QxtSqlPackage(QObject *parent) : QObject(parent) { record = -1; } /*! Constructs a copy of \a other with \a parent. */ QxtSqlPackage::QxtSqlPackage(const QxtSqlPackage & other, QObject *parent) : QObject(parent) { record = -1; setData(other.data()); } /*! Returns \c true if the package is valid, \c false otherwise. */ bool QxtSqlPackage::isValid() { if ((record >= 0) && (record < map.count())) return true; else return false; } int QxtSqlPackage::at() { return record; } bool QxtSqlPackage::next() { record++; if (record > (map.count() - 1)) { last(); return false; } return true; } bool QxtSqlPackage::last() { record = map.count() - 1; if (record >= 0) return true; else return false; } bool QxtSqlPackage::first() { if (map.count()) { record = 0; return true; } else { record = -1; return false; } } QString QxtSqlPackage::value(const QString& key) { if ((record < 0) || !map.count()) return QString(); return map.at(record).value(key); } void QxtSqlPackage::insert(QSqlQuery query) { map.clear(); record = -1; /*query will be invalid if next is not called first*/ if (!query.isValid()) query.next(); QSqlRecord infoRecord = query.record(); int iNumCols = infoRecord.count(); QVector tableMap = QVector(iNumCols); /*first create a map of index->colname pairs*/ for (int iLoop = 0; iLoop < iNumCols; iLoop++) { tableMap[iLoop] = infoRecord.fieldName(iLoop); } /*now use this created map to get column names *this should be faster than querying the QSqlRecord every time *but that depends on the databasetype and size of the table (number of rows and cols) */ do { QHash hash; for (int iColLoop = 0; iColLoop < iNumCols; iColLoop++) { hash[tableMap[iColLoop]] = query.value(iColLoop).toString(); } map.append(hash); } while (query.next()); } int QxtSqlPackage::count() const { return map.count(); } QByteArray QxtSqlPackage::data() const { QBuffer buff; buff.open(QBuffer::WriteOnly); QDataStream stream(&buff); stream << count(); for (int i = 0; i < count();i++) stream << map.at(i); buff.close(); return buff.data(); } void QxtSqlPackage::setData(const QByteArray& data) { map.clear(); record = -1; QBuffer buff; buff.setData(data); buff.open(QBuffer::ReadOnly); QDataStream stream(&buff); int c; stream >> c; for (int i = 0; i < c;i++) { QHash hash; stream >> hash; map.append(hash); } } QHash QxtSqlPackage::hash(int index) { if (index > count()) return QHash(); return map.at(index); } QHash QxtSqlPackage::hash() { qDebug() << record; return map.at(record); } QxtSqlPackage& QxtSqlPackage::operator= (const QxtSqlPackage & other) { setData(other.data()); return *this; } libqxt-0.6.2/src/sql/qxtsqlpackage.h000066400000000000000000000037001215241066400174320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtSql module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSQLPACKAGE_H #define QXTSQLPACKAGE_H #include #include #include #include class QXT_SQL_EXPORT QxtSqlPackage : public QObject { Q_OBJECT public: QxtSqlPackage(QObject *parent = 0); QxtSqlPackage(const QxtSqlPackage & other, QObject *parent = 0); bool isValid(); int at(); bool next(); bool last(); bool first(); QString value(const QString& key); void insert(QSqlQuery query); int count() const; QByteArray data() const; void setData(const QByteArray& data); QHash hash(int index); QHash hash(); QxtSqlPackage& operator= (const QxtSqlPackage& other); private: QList > map; int record; }; #endif libqxt-0.6.2/src/sql/qxtsqlpackagemodel.cpp000066400000000000000000000056611215241066400210160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtSql module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtsqlpackagemodel.h" /*! \class QxtSqlPackageModel \inmodule QxtSql \brief The QxtSqlPackageModel class provides a read-only data model for QxtSqlPackage result.. example usage: \code QSqlQuery q; q.exec("SELECT *"); QxtSqlPackage p; p.insert(q); QxtSqlPackageModel m; m.setQuery(p); QTableView v; v.setModel(&m); v.show(); \endcode */ /*! \fn void QxtSqlPackageModel::setQuery(QxtSqlPackage package) \brief set the \a package for the model. \warning do this before any access. */ /*! Creates a QxtSqlPackageModel with \a parent. */ QxtSqlPackageModel::QxtSqlPackageModel(QObject * parent) : QAbstractTableModel(parent) { } void QxtSqlPackageModel::setQuery(QxtSqlPackage package) { pack = package; } /*! \reimp */ int QxtSqlPackageModel::rowCount(const QModelIndex &) const { return pack.count(); } /*! \reimp */ int QxtSqlPackageModel::columnCount(const QModelIndex &) const { QxtSqlPackage p = pack; return p.hash(0).count(); } /*! \reimp */ QVariant QxtSqlPackageModel::data(const QModelIndex & index, int role) const { if (role != Qt::DisplayRole) return QVariant(); if ((index.row() < 0) || (index.column() < 0)) return QVariant(); QxtSqlPackage p = pack; return p.hash(index.row()).values().at(index.column()); } /*! \reimp */ QVariant QxtSqlPackageModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Vertical && role == Qt::DisplayRole) return section; if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { QxtSqlPackage p = pack; return p.hash(0).keys().at(section) ; } return QAbstractItemModel::headerData(section, orientation, role); } libqxt-0.6.2/src/sql/qxtsqlpackagemodel.h000066400000000000000000000037001215241066400204530ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtSql module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTSQLPACKAGEMODEL_H_INCLUDED #define QXTSQLPACKAGEMODEL_H_INCLUDED #include #include #include #include class QXT_SQL_EXPORT QxtSqlPackageModel : public QAbstractTableModel { public: /// \reimp QxtSqlPackageModel(QObject * parent = 0); void setQuery(QxtSqlPackage a) ; /// \reimp int rowCount(const QModelIndex & = QModelIndex()) const ; /// \reimp int columnCount(const QModelIndex & = QModelIndex()) const ; /// \reimp QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; /// \reimp QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; private: QxtSqlPackage pack; }; #endif // QXTSQLPACKAGEMODEL_H_INCLUDED libqxt-0.6.2/src/sql/sql.pri000066400000000000000000000002761215241066400157310ustar00rootroot00000000000000INCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += qxtsql.h HEADERS += qxtsqlpackage.h HEADERS += qxtsqlpackagemodel.h SOURCES += qxtsqlpackage.cpp SOURCES += qxtsqlpackagemodel.cpp libqxt-0.6.2/src/sql/sql.pro000066400000000000000000000002731215241066400157340ustar00rootroot00000000000000CLEAN_TARGET = QxtSql DEFINES += BUILD_QXT_SQL QT = core sql QXT = core CONVENIENCE += $$CLEAN_TARGET include(sql.pri) include(../qxtbase.pri) libqxt-0.6.2/src/web/000077500000000000000000000000001215241066400143675ustar00rootroot00000000000000libqxt-0.6.2/src/web/qxtabstracthttpconnector.cpp000066400000000000000000000167671215241066400222670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtAbstractHttpConnector \inmodule QxtWeb \brief The QxtAbstractHttpConnector class is a base class for defining HTTP-based protocols for use with QxtHttpSessionManager QxtHttpSessionManager does the work of managing sessions and state for the otherwise stateless HTTP protocol, but it relies on QxtAbstractHttpConnector subclasses to implement the protocol used to communicate with the web server. Subclasses are responsible for accepting new connections (by implementing listen(const QHostAddress&, quint16) and invoking addConnection(QIODevice*)), for informing the session manager when request headers are available (by implementing canParseRequest(const QByteArray&)), for parsing the request headers (by implementing parseRequest(QByteArray&)), and for writing response headers (by implementing writeHeaders(QIODevice*, const QHttpResponseHeader&)). \sa QxtHttpSessionManager */ #include "qxthttpsessionmanager.h" #include "qxtwebcontent.h" #include #include #include #include #ifndef QXT_DOXYGEN_RUN class QxtAbstractHttpConnectorPrivate : public QxtPrivate { public: QxtHttpSessionManager* manager; QReadWriteLock bufferLock, requestLock; QHash buffers; // connection->buffer QHash requests; // requestID->connection quint32 nextRequestID; inline quint32 getNextRequestID(QIODevice* connection) { QWriteLocker locker(&requestLock); do { nextRequestID++; if (nextRequestID == 0xFFFFFFFF) nextRequestID = 1; } while (requests.contains(nextRequestID)); // yeah, right requests[nextRequestID] = connection; return nextRequestID; } inline void doneWithBuffer(QIODevice* device) { QWriteLocker locker(&bufferLock); buffers.remove(device); } inline void doneWithRequest(quint32 requestID) { QWriteLocker locker(&requestLock); requests.remove(requestID); } inline QIODevice* getRequestConnection(quint32 requestID) { QReadLocker locker(&requestLock); return requests[requestID]; } }; #endif /*! * Creates a QxtAbstractHttpConnector with the specified \a parent. * * Note that this is an abstract class and cannot be instantiated directly. */ QxtAbstractHttpConnector::QxtAbstractHttpConnector(QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtAbstractHttpConnector); qxt_d().nextRequestID = 0; } /*! * \internal */ void QxtAbstractHttpConnector::setSessionManager(QxtHttpSessionManager* manager) { qxt_d().manager = manager; } /*! * Returns the session manager into which the connector is installed. * * \sa QxtHttpSessionManager::setConnector */ QxtHttpSessionManager* QxtAbstractHttpConnector::sessionManager() const { return qxt_d().manager; } /*! * \internal * Returns the QIODevice associated with a \a requestID. * * The request ID is generated internally and used by the session manager. */ QIODevice* QxtAbstractHttpConnector::getRequestConnection(quint32 requestID) { return qxt_d().getRequestConnection(requestID); } /*! * Starts managing a new connection from \a device. * * This function should be invoked by a subclass to attach incoming connections * to the session manager. */ void QxtAbstractHttpConnector::addConnection(QIODevice* device) { if(!device) return; QWriteLocker locker(&qxt_d().bufferLock); qxt_d().buffers[device] = QByteArray(); QObject::connect(device, SIGNAL(readyRead()), this, SLOT(incomingData())); QObject::connect(device, SIGNAL(aboutToClose()), this, SLOT(disconnected())); QObject::connect(device, SIGNAL(disconnected()), this, SLOT(disconnected())); QObject::connect(device, SIGNAL(destroyed()), this, SLOT(disconnected())); } /*! * \internal */ void QxtAbstractHttpConnector::incomingData(QIODevice* device) { if (!device) { device = qobject_cast(sender()); if (!device) return; } QReadLocker locker(&qxt_d().bufferLock); QByteArray& buffer = qxt_d().buffers[device]; buffer.append(device->readAll()); if (!canParseRequest(buffer)) return; QHttpRequestHeader header = parseRequest(buffer); QxtWebContent* content = 0; QByteArray start; if (header.contentLength() > 0) { start = buffer.left(header.value("content-length").toInt()); buffer = buffer.mid(header.value("content-length").toInt()); content = new QxtWebContent(header.contentLength(), start, device); } else if (header.hasKey("connection") && header.value("connection").toLower() == "close") { start = buffer; buffer.clear(); content = new QxtWebContent(header.contentLength(), start, device); } // else no content quint32 requestID = qxt_d().getNextRequestID(device); sessionManager()->incomingRequest(requestID, header, content); } /*! * \internal */ void QxtAbstractHttpConnector::disconnected() { quint32 requestID=0; QIODevice* device = qobject_cast(sender()); if (!device) return; requestID = qxt_d().requests.key(device); qxt_d().doneWithRequest(requestID); qxt_d().doneWithBuffer(device); sessionManager()->disconnected(device); } /*! * \fn virtual bool QxtAbstractHttpConnector::listen(const QHostAddress& interface, quint16 port) * Invoked by the session manager to indicate that the connector should listen * for incoming connections on the specified \a interface and \a port. * * If the interface is QHostAddress::Any, the server will listen on all network interfaces. * * Returns true on success, or false if the server could not begin listening. * * \sa addConnection(QIODevice*) */ /*! * \fn virtual bool QxtAbstractHttpConnector::canParseRequest(const QByteArray& buffer) * Returns true if a complete set of request headers can be extracted from the provided \a buffer. */ /*! * \fn virtual QHttpRequestHeader QxtAbstractHttpConnector::parseRequest(QByteArray& buffer) * Extracts a set of request headers from the provided \a buffer. * * Subclasses implementing this function must be sure to remove the parsed data from the buffer. */ /*! * \fn virtual void QxtAbstractHttpConnector::writeHeaders(QIODevice* device, const QHttpResponseHeader& header) * Writes a the response \a header to the specified \a device. */ libqxt-0.6.2/src/web/qxtabstracthttpconnector.h000066400000000000000000000074001215241066400217140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTABSTRACTHTTPCONNECTOR_H #define QXTABSTRACTHTTPCONNECTOR_H #include "qxtglobal.h" #include #include #include QT_FORWARD_DECLARE_CLASS(QIODevice) class QxtHttpSessionManager; class QxtAbstractHttpConnectorPrivate; class QXT_WEB_EXPORT QxtAbstractHttpConnector : public QObject { friend class QxtHttpSessionManager; Q_OBJECT public: QxtAbstractHttpConnector(QObject* parent = 0); virtual bool listen(const QHostAddress& iface, quint16 port) = 0; protected: QxtHttpSessionManager* sessionManager() const; void addConnection(QIODevice* device); QIODevice* getRequestConnection(quint32 requestID); virtual bool canParseRequest(const QByteArray& buffer) = 0; virtual QHttpRequestHeader parseRequest(QByteArray& buffer) = 0; virtual void writeHeaders(QIODevice* device, const QHttpResponseHeader& header) = 0; private Q_SLOTS: void incomingData(QIODevice* device = 0); void disconnected(); private: void setSessionManager(QxtHttpSessionManager* manager); QXT_DECLARE_PRIVATE(QxtAbstractHttpConnector) }; class QxtHttpServerConnectorPrivate; class QXT_WEB_EXPORT QxtHttpServerConnector : public QxtAbstractHttpConnector { Q_OBJECT public: QxtHttpServerConnector(QObject* parent = 0); virtual bool listen(const QHostAddress& iface, quint16 port); protected: virtual bool canParseRequest(const QByteArray& buffer); virtual QHttpRequestHeader parseRequest(QByteArray& buffer); virtual void writeHeaders(QIODevice* device, const QHttpResponseHeader& header); private Q_SLOTS: void acceptConnection(); private: QXT_DECLARE_PRIVATE(QxtHttpServerConnector) }; class QxtScgiServerConnectorPrivate; class QXT_WEB_EXPORT QxtScgiServerConnector : public QxtAbstractHttpConnector { Q_OBJECT public: QxtScgiServerConnector(QObject* parent = 0); virtual bool listen(const QHostAddress& iface, quint16 port); protected: virtual bool canParseRequest(const QByteArray& buffer); virtual QHttpRequestHeader parseRequest(QByteArray& buffer); virtual void writeHeaders(QIODevice* device, const QHttpResponseHeader& header); private Q_SLOTS: void acceptConnection(); private: QXT_DECLARE_PRIVATE(QxtScgiServerConnector) }; /* Commented out pending implementation class QxtFcgiConnectorPrivate; class QXT_WEB_EXPORT QxtFcgiConnector : public QxtAbstractHttpConnector { Q_OBJECT public: QxtFcgiConnector(QObject* parent = 0); virtual bool listen(const QHostAddress& iface, quint16 port); private: QXT_DECLARE_PRIVATE(QxtFcgiConnector) }; */ #endif // QXTABSTRACTHTTPCONNECTOR_H libqxt-0.6.2/src/web/qxtabstractwebservice.cpp000066400000000000000000000112531215241066400215140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtAbstractWebService \inmodule QxtWeb \brief The QxtAbstractWebService class is a base interface for web services QxtAbstractWebService provides a common interface for all web service classes. It uses an event-driven design instead of the more traditional request-response design used by many web scripting languages. When the user requests a web page, the service receives a pageRequestedEvent; after the service assembles the response, it must post a QxtWebPageEvent (or a subclass, such as QxtWebRedirectEvent or QxtWebErrorEvent). Usually, an application providing web services will instantiate one QxtAbstractWebService object for each session, but this is not a requirement. For services that do not require session management, such as those that serve only static content, the session factory may return the same pointer for every invocation, or it may use some more exotic scheme. When using one service object per session, each service's data members are independent and may be used to track state across requests. A service object shared among multiple sessions will retain state across requests as well but it must implement its own mechanism for separating non-shared data. The QxtWeb architecture is not multithreaded; that is, QxtAbstractWebService does not automatically spawn a process for every session. However, QxtAbstractWebSessionManager performs thread-safe event dispatching, so subclasses of QxtAbstractWebService are free to create threads themselves. A web service object may delete itself (see QObject::deleteLater()) to end the associated session. \sa QxtAbstractWebSessionManager::ServiceFactory */ /* * TODO: * The current architecture only allows for two behaviors: creating a new session * for every connection without a session cookie, or not using sessions at all. * This needs to be fixed by adding a function to the session manager to explicitly * create a new session. */ #include "qxtabstractwebservice.h" #ifndef QXT_DOXYGEN_RUN class QxtAbstractWebServicePrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtAbstractWebService) QxtAbstractWebServicePrivate() {} QxtAbstractWebSessionManager* manager; }; #endif /*! * Creates a QxtAbstractWebService with the specified \a parent and session \a manager. * * Often, the session manager will also be the parent, but this is not a requirement. * * Note that this is an abstract class and cannot be instantiated directly. */ QxtAbstractWebService::QxtAbstractWebService(QxtAbstractWebSessionManager* manager, QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtAbstractWebService); qxt_d().manager = manager; } /*! * Returns the session manager associated with the web service. */ QxtAbstractWebSessionManager* QxtAbstractWebService::sessionManager() const { return qxt_d().manager; } /*! * \fn void QxtAbstractWebService::postEvent(QxtWebEvent* event) * Posts an \a event to a web browser that has made a request to the service. */ /*! * \fn virtual void QxtAbstractWebService::pageRequestedEvent(QxtWebRequestEvent* event) * This \a event handler must be reimplemented in subclasses to receive page * request events. * * Every page request event received MUST be responded to with a QxtWebPageEvent * or a QxtWebPageEvent subclass. This response does not have to be posted * during the execution of this function, to support asynchronous design, but * failure to post an event will cause the web browser making the request to * wait until it times out. * * \sa QxtWebRequestEvent */ libqxt-0.6.2/src/web/qxtabstractwebservice.h000066400000000000000000000037151215241066400211650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTABSTRACTWEBSERVICE_H #define QXTABSTRACTWEBSERVICE_H #include #include "qxtabstractwebsessionmanager.h" class QxtWebEvent; class QxtWebRequestEvent; class QxtAbstractWebServicePrivate; class QXT_WEB_EXPORT QxtAbstractWebService : public QObject { Q_OBJECT public: explicit QxtAbstractWebService(QxtAbstractWebSessionManager* manager, QObject* parent = 0); QxtAbstractWebSessionManager* sessionManager() const; inline void postEvent(QxtWebEvent* event) { sessionManager()->postEvent(event); } virtual void pageRequestedEvent(QxtWebRequestEvent* event) = 0; // virtual void functionInvokedEvent(QxtWebRequestEvent* event) = 0; // todo: implement private: QXT_DECLARE_PRIVATE(QxtAbstractWebService) }; #endif // QXTABSTRACTWEBSERVICE_H libqxt-0.6.2/src/web/qxtabstractwebsessionmanager.cpp000066400000000000000000000163621215241066400231000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtAbstractWebSessionManager \inmodule QxtWeb \brief The QxtAbstractWebSessionManager class is a base class for QxtWeb session managers QxtAbstractWebSessionManager is the base class for all QxtWeb session managers. Session managers are responsible for managing connections between web browsers and web services, for creating sessions and their corresponding service objects, and for managing and dispatching events between browsers and services. Note that the session manager is not responsible for destroying service objects. A service object that wishes to end its corresponding session may destroy itself (see QObject::deleteLater()) and QxtAbstractWebSessionManager will automatically clean up its internal session tracking data. \sa QxtAbstractWebService */ /*! * \typedef QxtAbstractWebSessionManager::ServiceFactory * \brief Pointer to a function that generates QxtAbstractWebService objects * * \bold TYPEDEF: The ServiceFactory type represents a pointer to a function that takes two * parameters -- a QxtAbstractWebSessionManager* pointer and an int session ID. * The function must return a QxtAbstractWebService* pointer. * * Usually, an application providing web services will instantiate one * QxtAbstractWebService object for each session. For services that do not * require session management, such as those that serve only static pages, a * single service object may be shared for all requests, or it may use some * more exotic scheme. See QxtAbstractWebService for more details. */ #include "qxtabstractwebsessionmanager.h" #include "qxtabstractwebsessionmanager_p.h" #include "qxtabstractwebservice.h" #include "qxtmetaobject.h" #include #ifndef QXT_DOXYGEN_RUN QxtAbstractWebSessionManagerPrivate::QxtAbstractWebSessionManagerPrivate() : factory(0), maxID(1) { // initializers only } void QxtAbstractWebSessionManagerPrivate::sessionDestroyed(int sessionID) { if (sessions.contains(sessionID)) { freeList.enqueue(sessionID); sessions.remove(sessionID); } } int QxtAbstractWebSessionManagerPrivate::getNextID() { if (freeList.empty()) { int next = maxID; maxID++; return next; } return freeList.dequeue(); } #endif /*! * Creates a QxtAbstractWebSessionManager with the specified \a parent. * * Note that this is an abstract class and cannot be instantiated directly. */ QxtAbstractWebSessionManager::QxtAbstractWebSessionManager(QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtAbstractWebSessionManager); } /*! * Sets the service \a factory for the session manager. * * The service factory is invoked every time the session manager creates a new * session. Usually, an application providing web services will instantiate one * QxtAbstractWebService object for each session. For services that do not * require separate sessions, such as those that serve only static pages, the * factory may return a pointer to the same object for multiple requests. * * \sa QxtAbstractWebSessionManager::ServiceFactory */ void QxtAbstractWebSessionManager::setServiceFactory(ServiceFactory* factory) { qxt_d().factory = factory; } /*! * Returns the service factory in use by the session manager. * * \sa setServiceFactory(ServiceFactory*) */ QxtAbstractWebSessionManager::ServiceFactory* QxtAbstractWebSessionManager::serviceFactory() const { return qxt_d().factory; } /*! * Returns the service object corresponding to the provided \a sessionID. */ QxtAbstractWebService* QxtAbstractWebSessionManager::session(int sessionID) const { if (qxt_d().sessions.contains(sessionID)) return qxt_d().sessions[sessionID]; return 0; } /*! * Creates a new session and returns its session ID. * * This function uses the serviceFactory() to request an instance of the web service. * \sa serviceFactory() */ int QxtAbstractWebSessionManager::createService() { int sessionID = qxt_d().getNextID(); if (!qxt_d().factory) return sessionID; QxtAbstractWebService* service = serviceFactory()(this, sessionID); qxt_d().sessions[sessionID] = service; // Using QxtBoundFunction to bind the sessionID to the slot invocation QxtMetaObject::connect(service, SIGNAL(destroyed()), QxtMetaObject::bind(&qxt_d(), SLOT(sessionDestroyed(int)), Q_ARG(int, sessionID)), Qt::QueuedConnection); return sessionID; // you can always get the service with this } /*! * \fn virtual bool QxtAbstractWebSessionManager::start() * Starts the session manager. * * Session managers should not create sessions before start() is invoked. * Subclasses are encouraged to refrain from accepting connections until the * session manager is started. */ /*! * \fn virtual void QxtAbstractWebSessionManager::postEvent(QxtWebEvent* event) * Adds the event to the event queue for its associated session. * * Since different protocols may require different event processing behavior, * there is no default implementation in QxtAbstractWebSessionManager. Subclasses * are responsible for maintaining event queues and deciding when and where to * dispatch events. * * Depending on the subclass's implementation posted events may not be dispatched * for some time, and is is possible that an event may never be dispatched if * the session is terminated before the event is handled. * * \sa QxtWebEvent */ /*! * \fn virtual void QxtAbstractWebSessionManager::processEvents() * Processes pending events for all sessions. * * Since different protocols may require different event processing behavior, * there is no default implementation in QxtAbstractWebSessionManager. Subclasses * are responsible for maintaining event queues and deciding when and where to * dispatch events. * * processEvents() is not required to dispatch all events immediately. In * particular, some events may require certain conditions to be met before * they may be fully processed. (For example, because HTTP cookies are sent * as response headers, QxtHttpServerConnector may not dispatch a * QxtWebStoreCookieEvent until a QxtWebPageEvent for the same session is * available.) Unprocessed events may remain in the event queue. * * \sa QxtWebEvent */ libqxt-0.6.2/src/web/qxtabstractwebsessionmanager.h000066400000000000000000000040421215241066400225350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTABSTRACTWEBSESSIONMANAGER_H #define QXTABSTRACTWEBSESSIONMANAGER_H #include #include class QxtAbstractWebService; class QxtWebEvent; class QxtAbstractWebSessionManagerPrivate; class QXT_WEB_EXPORT QxtAbstractWebSessionManager : public QObject { Q_OBJECT public: typedef QxtAbstractWebService* ServiceFactory(QxtAbstractWebSessionManager*, int); QxtAbstractWebSessionManager(QObject* parent = 0); virtual bool start() = 0; virtual void postEvent(QxtWebEvent* event) = 0; void setServiceFactory(ServiceFactory* factory); ServiceFactory* serviceFactory() const; QxtAbstractWebService* session(int sessionID) const; protected: int createService(); protected Q_SLOTS: virtual void processEvents() = 0; private: QXT_DECLARE_PRIVATE(QxtAbstractWebSessionManager) }; #endif // QXTABSTRACTWEBSESSIONMANAGER_H libqxt-0.6.2/src/web/qxtabstractwebsessionmanager_p.h000066400000000000000000000036351215241066400230630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTABSTRACTWEBSESSIONMANAGER_P_H #define QXTABSTRACTWEBSESSIONMANAGER_P_H #include #include #include #include #include "qxtabstractwebsessionmanager.h" #ifndef QXT_DOXYGEN_RUN class QxtAbstractWebSessionManagerPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QxtAbstractWebSessionManagerPrivate(); QXT_DECLARE_PUBLIC(QxtAbstractWebSessionManager) QxtAbstractWebSessionManager::ServiceFactory* factory; QHash sessions; QQueue freeList; int maxID; int getNextID(); public Q_SLOTS: void sessionDestroyed(int sessionID); }; #endif // QXT_DOXYGEN_RUN #endif // QXTABSTRACTWEBSESSIONMANAGER_P_H libqxt-0.6.2/src/web/qxthtmltemplate.cpp000066400000000000000000000110621215241066400203300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtHtmlTemplate \inmodule QxtWeb \brief The QxtHtmlTemplate class provides a basic HTML template engine open a file containing html code and php style variables. use the square bracket operators to assign content for a variable \code QxtHtmlTemplate index; if(!index.open) return 404; index["content"]="hello world"; echo()< Test Page \endcode funny storry: whe are using this class to make our documentation (eat your own dogfood, you know ;). but when we where parsing exactly this file you read right now the first time, QxtHtmlTemplate got stuck in an infinite loop. guess why. becouse of that example above :D So be warned: when you assign content to a variable that contains the variable name itself, render() will never return. */ /*! \fn QxtHtmlTemplate::open(const QString& filename) Opens \a filename. Returns \c true on success and \c false on failure. Note that it will also return false for an empty html file. */ /*! \fn QString QxtHtmlTemplate::render() const Uses the variables you set and renders the opened file. returns an empty string on failure. Does NOT take care of not assigned variables, they will remain in the returned string */ #include "qxthtmltemplate.h" #include #include /*! Constructs a new QxtHtmlTemplate. */ QxtHtmlTemplate::QxtHtmlTemplate() : QMap() {} /*! Loads data \a d. */ void QxtHtmlTemplate::load(const QString& d) { data = d; } bool QxtHtmlTemplate::open(const QString& filename) { QFile f(filename); f.open(QIODevice::ReadOnly); data = QString::fromLocal8Bit(f.readAll()); f.close(); if (data.isEmpty()) { qWarning("QxtHtmlTemplate::open(\"%s\") empty or nonexistent", qPrintable(filename)); return false; } return true; } QString QxtHtmlTemplate::render() const { ///try to preserve indention by parsing char by char and saving the last non-space character QString output = data; int lastnewline = 0; for (int i = 0;i < output.count();i++) { if (output.at(i) == '\n') { lastnewline = i; } if (output.at(i) == '<' && output.at(i + 1) == '?' && output.at(i + 2) == '=') { int j = i + 3; QString var; for (int jj = j;jj < output.count();jj++) { if (output.at(jj) == '?' && output.at(jj + 1) == '>') { j = jj; break; } var += output.at(jj); } if (j == i) { qWarning("QxtHtmlTemplate::render() unterminated ** ****************************************************************************/ #ifndef QXTHTMLTEMPLATE_H #define QXTHTMLTEMPLATE_H #include #include #include #include class QXT_WEB_EXPORT QxtHtmlTemplate : public QMap { public: QxtHtmlTemplate(); bool open(const QString& filename); void load(const QString& data); QString render() const; private: QString data; }; #endif // QXTHTMLTEMPLATE_H libqxt-0.6.2/src/web/qxthttpserverconnector.cpp000066400000000000000000000075231215241066400217600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtHttpServerConnector \inmodule QxtWeb \brief The QxtHttpServerConnector class provides a built-in HTTP server for QxtHttpSessionManager QxtHttpSessionManager does the work of managing sessions and state for the otherwise stateless HTTP protocol, but it relies on QxtAbstractHttpConnector subclasses to implement the protocol used to communicate with the web server. QxtHttpServerConnector implements a complete HTTP server internally and does not require an external web server to function. However, it provides very little control over the behavior of the web server and may not suitable for high traffic scenarios or virtual hosting configurations. \sa QxtHttpSessionManager */ #include "qxthttpsessionmanager.h" #include "qxtwebevent.h" #include #include #include #include #ifndef QXT_DOXYGEN_RUN class QxtHttpServerConnectorPrivate : public QxtPrivate { public: QTcpServer* server; }; #endif /*! * Creates a QxtHttpServerConnector with the given \a parent. */ QxtHttpServerConnector::QxtHttpServerConnector(QObject* parent) : QxtAbstractHttpConnector(parent) { QXT_INIT_PRIVATE(QxtHttpServerConnector); qxt_d().server = new QTcpServer(this); QObject::connect(qxt_d().server, SIGNAL(newConnection()), this, SLOT(acceptConnection())); } /*! * \reimp */ bool QxtHttpServerConnector::listen(const QHostAddress& iface, quint16 port) { return qxt_d().server->listen(iface, port); } /*! * \internal */ void QxtHttpServerConnector::acceptConnection() { QTcpSocket* socket = qxt_d().server->nextPendingConnection(); addConnection(socket); } /*! * \reimp */ bool QxtHttpServerConnector::canParseRequest(const QByteArray& buffer) { if (buffer.indexOf("\r\n\r\n") >= 0) return true; // 1.0+ if (buffer.indexOf("\r\n") >= 0 && buffer.indexOf("HTTP/") == -1) return true; // 0.9 return false; } /*! * \reimp */ QHttpRequestHeader QxtHttpServerConnector::parseRequest(QByteArray& buffer) { int pos = buffer.indexOf("\r\n\r\n"), endpos = pos + 3; if (pos == -1) { pos = buffer.indexOf("\r\n"); // 0.9 endpos = pos + 1; } QHttpRequestHeader header(QString::fromUtf8(buffer.left(endpos))); QByteArray firstLine = buffer.left(buffer.indexOf('\r')); if (firstLine.indexOf("HTTP/") == -1) { header.setRequest(header.method(), header.path(), 0, 9); } buffer.remove(0, endpos + 1); return header; } /*! * \reimp */ void QxtHttpServerConnector::writeHeaders(QIODevice* device, const QHttpResponseHeader& header) { if (header.majorVersion() == 0) return; // 0.9 doesn't have headers device->write(header.toString().toUtf8()); } libqxt-0.6.2/src/web/qxthttpsessionmanager.cpp000066400000000000000000000541371215241066400215600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtHttpSessionManager \inmodule QxtWeb \brief The QxtHttpSessionManager class provides a session manager for HTTP-based protocols QxtHttpSessionManager is a QxtWeb session manager that adds session management support to the normally stateless HTTP model. In addition to session management, QxtHttpSessionManager also supports a static service, which can serve content that does not require session management, such as static web pages. The static service is also used to respond to HTTP/0.9 clients that do not support cookies and HTTP/1.0 and HTTP/1.1 clients that are rejecting cookies. If no static service is provided, these clients will only see an "Internal Configuration Error", so it is recommended to supply a static service, even one that only returns a more useful error message. QxtHttpSessionManager attempts to be thread-safe in accepting connections and posting events. It is reentrant for all other functionality. \sa QxtAbstractWebService */ #include "qxthttpsessionmanager.h" #include "qxtwebevent.h" #include "qxtwebcontent.h" #include "qxtabstractwebservice.h" #include #include #include #include #include #include #include #include #include #include #include #ifndef QXT_DOXYGEN_RUN class QxtHttpSessionManagerPrivate : public QxtPrivate { public: struct ConnectionState { QxtBoundFunction* onBytesWritten; bool readyRead; bool finishedTransfer; bool keepAlive; bool streaming; int httpMajorVersion; int httpMinorVersion; int sessionID; }; QxtHttpSessionManagerPrivate() : iface(QHostAddress::Any), port(80), sessionCookieName("sessionID"), connector(0), staticService(0), autoCreateSession(true), eventLock(QMutex::Recursive), sessionLock(QMutex::Recursive) {} QXT_DECLARE_PUBLIC(QxtHttpSessionManager) QHostAddress iface; quint16 port; QByteArray sessionCookieName; QxtAbstractHttpConnector* connector; QxtAbstractWebService* staticService; bool autoCreateSession; QMutex eventLock; QList eventQueue; QMutex sessionLock; QHash sessionKeys; // sessionKey->sessionID QHash connectionState; // connection->state Qt::HANDLE mainThread; }; #endif /*! * Constructs a new QxtHttpSessionManager with the specified \a parent. */ QxtHttpSessionManager::QxtHttpSessionManager(QObject* parent) : QxtAbstractWebSessionManager(parent) { QXT_INIT_PRIVATE(QxtHttpSessionManager); qxt_d().mainThread = QThread::currentThreadId(); } /*! * Returns the interface on which the session manager will listen for incoming connections. * \sa setInterface */ QHostAddress QxtHttpSessionManager::listenInterface() const { return qxt_d().iface; } /*! * Sets the interface \a iface on which the session manager will listen for incoming * connections. * * The default value is QHostAddress::Any, which will cause the session manager * to listen on all network interfaces. * * \sa QxtAbstractHttpConnector::listen */ void QxtHttpSessionManager::setListenInterface(const QHostAddress& iface) { qxt_d().iface = iface; } /*! * Returns the port on which the session manager will listen for incoming connections. * \sa setInterface */ quint16 QxtHttpSessionManager::port() const { return qxt_d().port; } /*! * Sets the \a port on which the session manager will listen for incoming connections. * * The default value is to listen on port 80. This is an acceptable value when * using QxtHttpServerConnector, but it is not likely to be desirable for other * connectors. * * \sa port */ void QxtHttpSessionManager::setPort(quint16 port) { qxt_d().port = port; } /*! * \reimp */ bool QxtHttpSessionManager::start() { Q_ASSERT(qxt_d().connector); return connector()->listen(listenInterface(), port()); } /*! * Returns the name of the HTTP cookie used to track sessions in the web browser. * \sa setSessionCookieName */ QByteArray QxtHttpSessionManager::sessionCookieName() const { return qxt_d().sessionCookieName; } /*! * Sets the \a name of the HTTP cookie used to track sessions in the web browser. * * The default value is "sessionID". * * \sa sessionCookieName */ void QxtHttpSessionManager::setSessionCookieName(const QByteArray& name) { qxt_d().sessionCookieName = name; } /*! * Sets the \a connector used to manage connections to web browsers. * * \sa connector */ void QxtHttpSessionManager::setConnector(QxtAbstractHttpConnector* connector) { connector->setSessionManager(this); qxt_d().connector = connector; } /*! * Sets the \a connector used to manage connections to web browsers. * * This overload is provided for convenience and can construct the predefined * connectors provided with Qxt. * * \sa connector */ void QxtHttpSessionManager::setConnector(Connector connector) { if (connector == HttpServer) setConnector(new QxtHttpServerConnector(this)); else if (connector == Scgi) setConnector(new QxtScgiServerConnector(this)); /* commented out pending implementation else if(connector == Fcgi) setConnector(new QxtFcgiConnector(this)); */ } /*! * Returns the connector used to manage connections to web browsers. * \sa setConnector */ QxtAbstractHttpConnector* QxtHttpSessionManager::connector() const { return qxt_d().connector; } /*! * Returns \c true if sessions are automatically created for every connection * that does not already have a session cookie associated with it; otherwise * returns \c false. * \sa setAutoCreateSession */ bool QxtHttpSessionManager::autoCreateSession() const { return qxt_d().autoCreateSession; } /*! * Sets \a enabled whether sessions are automatically created for every connection * that does not already have a session cookie associated with it. * * Sessions are only created for clients that support HTTP cookies. HTTP/0.9 * clients will never generate a session. * * \sa autoCreateSession */ void QxtHttpSessionManager::setAutoCreateSession(bool enable) { qxt_d().autoCreateSession = enable; } /*! * Returns the QxtAbstractWebService that is used to respond to requests from * connections that are not associated with a session. * * \sa setStaticContentService */ QxtAbstractWebService* QxtHttpSessionManager::staticContentService() const { return qxt_d().staticService; } /*! * Sets the \a service that is used to respond to requests from * connections that are not associated with a session. * * If no static content service is set, connections that are not associated * with a session will receive an "Internal Configuration Error". * * \sa staticContentService */ void QxtHttpSessionManager::setStaticContentService(QxtAbstractWebService* service) { qxt_d().staticService = service; } /*! * \reimp */ void QxtHttpSessionManager::postEvent(QxtWebEvent* h) { qxt_d().eventLock.lock(); qxt_d().eventQueue.append(h); qxt_d().eventLock.unlock(); // if(h->type() == QxtWebEvent::Page) QMetaObject::invokeMethod(this, "processEvents", Qt::QueuedConnection); } /*! * Creates a new session and sends the session key to the web browser. * * Subclasses may override this function to perform custom session initialization, * but they must call the base class implementation in order to update the internal * session database and fetch a new session ID. */ int QxtHttpSessionManager::newSession() { QMutexLocker locker(&qxt_d().sessionLock); int sessionID = createService(); QUuid key; do { key = QUuid::createUuid(); } while (qxt_d().sessionKeys.contains(key)); qxt_d().sessionKeys[key] = sessionID; postEvent(new QxtWebStoreCookieEvent(sessionID, qxt_d().sessionCookieName, key)); return sessionID; } /*! * Handles incoming HTTP requests and dispatches them to the appropriate service. * * The \a requestID is an opaque value generated by the connector. * * Subclasses may override this function to perform preprocessing on each * request, but they must call the base class implementation in order to * generate and dispatch the appropriate events. */ void QxtHttpSessionManager::incomingRequest(quint32 requestID, const QHttpRequestHeader& header, QxtWebContent* content) { QMultiHash cookies; foreach(const QString& cookie, header.allValues("cookie")) // QHttpHeader is case-insensitive, thankfully { foreach(const QString& kv, cookie.split("; ")) { int pos = kv.indexOf('='); if (pos == -1) continue; cookies.insert(kv.left(pos), kv.mid(pos + 1)); } } int sessionID; QString sessionCookie = cookies.value(qxt_d().sessionCookieName); qxt_d().sessionLock.lock(); if (qxt_d().sessionKeys.contains(sessionCookie)) { sessionID = qxt_d().sessionKeys[sessionCookie]; } else if (header.majorVersion() > 0 && qxt_d().autoCreateSession) { sessionID = newSession(); } else { sessionID = 0; } QIODevice* device = connector()->getRequestConnection(requestID); QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[device]; state.sessionID = sessionID; state.httpMajorVersion = header.majorVersion(); state.httpMinorVersion = header.minorVersion(); if (state.httpMajorVersion == 0 || (state.httpMajorVersion == 1 && state.httpMinorVersion == 0) || header.value("connection").toLower() == "close") state.keepAlive = false; else state.keepAlive = true; qxt_d().sessionLock.unlock(); QxtWebRequestEvent* event = new QxtWebRequestEvent(sessionID, requestID, QUrl(header.path())); QTcpSocket* socket = qobject_cast(device); if (socket) { event->remoteAddress = socket->peerAddress().toString(); } event->method = header.method(); event->cookies = cookies; event->url.setScheme("http"); if (event->url.host().isEmpty()) event->url.setHost(header.value("host")); if (event->url.port() == -1) event->url.setPort(port()); event->contentType = header.contentType(); event->content = content; typedef QPair StringPair; foreach(const StringPair& line, header.values()) { if (line.first.toLower() == "cookie") continue; event->headers.insert(line.first, line.second); } event->headers.insert("X-Request-Protocol", "HTTP/" + QString::number(state.httpMajorVersion) + '.' + QString::number(state.httpMinorVersion)); if (sessionID && session(sessionID)) { session(sessionID)->pageRequestedEvent(event); } else if (qxt_d().staticService) { qxt_d().staticService->pageRequestedEvent(event); } else { postEvent(new QxtWebErrorEvent(0, requestID, 500, "Internal Configuration Error")); } } /*! * \internal */ void QxtHttpSessionManager::disconnected(QIODevice* device) { QMutexLocker locker(&qxt_d().sessionLock); if (qxt_d().connectionState.contains(device)) delete qxt_d().connectionState[device].onBytesWritten; qxt_d().connectionState.remove(device); } /*! * \reimp */ void QxtHttpSessionManager::processEvents() { if (QThread::currentThreadId() != qxt_d().mainThread) { QMetaObject::invokeMethod(this, "processEvents", Qt::QueuedConnection); return; } QxtHttpSessionManagerPrivate& d = qxt_d(); QMutexLocker locker(&d.eventLock); if (!d.eventQueue.count()) return; int ct = d.eventQueue.count(), sessionID = 0, requestID = 0, pagePos = -1; QxtWebRedirectEvent* re = 0; QxtWebPageEvent* pe = 0; for (int i = 0; i < ct; i++) { if (d.eventQueue[i]->type() != QxtWebEvent::Page && d.eventQueue[i]->type() != QxtWebEvent::Redirect) continue; pagePos = i; sessionID = d.eventQueue[i]->sessionID; if (d.eventQueue[pagePos]->type() == QxtWebEvent::Redirect) { re = static_cast(d.eventQueue[pagePos]); } pe = static_cast(d.eventQueue[pagePos]); requestID = pe->requestID; break; } if (pagePos == -1) return; // no pages to send yet QHttpResponseHeader header; QList removeIDs; QxtWebEvent* e = 0; for (int i = 0; i < pagePos; i++) { if (d.eventQueue[i]->sessionID != sessionID) continue; e = d.eventQueue[i]; if (e->type() == QxtWebEvent::StoreCookie) { QxtWebStoreCookieEvent* ce = static_cast(e); QString cookie = ce->name + '=' + ce->data; if (ce->expiration.isValid()) { cookie += "; max-age=" + QString::number(QDateTime::currentDateTime().secsTo(ce->expiration)) + "; expires=" + ce->expiration.toUTC().toString("ddd, dd-MMM-YYYY hh:mm:ss GMT"); } header.addValue("set-cookie", cookie); removeIDs.push_front(i); } else if (e->type() == QxtWebEvent::RemoveCookie) { QxtWebRemoveCookieEvent* ce = static_cast(e); header.addValue("set-cookie", ce->name + "=; max-age=0; expires=" + QDateTime(QDate(1970, 1, 1)).toString("ddd, dd-MMM-YYYY hh:mm:ss GMT")); removeIDs.push_front(i); } } removeIDs.push_front(pagePos); QIODevice* device = connector()->getRequestConnection(requestID); QxtWebContent* content = qobject_cast(device); // TODO: This should only be invoked when pipelining occurs // In theory it shouldn't cause any problems as POST is specced to not be pipelined if (content) content->ignoreRemainingContent(); QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[connector()->getRequestConnection(requestID)]; QIODevice* source; header.setStatusLine(pe->status, pe->statusMessage, state.httpMajorVersion, state.httpMinorVersion); if (re) { header.setValue("location", re->destination); } // Set custom header values for (QMultiHash::iterator it = pe->headers.begin(); it != pe->headers.end(); ++it) { header.setValue(it.key(), it.value()); } header.setContentType(pe->contentType); if (state.httpMajorVersion == 0 || (state.httpMajorVersion == 1 && state.httpMinorVersion == 0)) pe->chunked = false; source = pe->dataSource; state.finishedTransfer = false; bool emptyContent = !source->bytesAvailable() && !pe->streaming; state.readyRead = source->bytesAvailable(); state.streaming = pe->streaming; if (emptyContent) { header.setValue("connection", "close"); connector()->writeHeaders(device, header); closeConnection(requestID); } else { pe->dataSource = 0; // so that it isn't destroyed when the event is deleted if (state.onBytesWritten) delete state.onBytesWritten; // disconnect old handler if (!pe->chunked) { state.keepAlive = false; state.onBytesWritten = QxtMetaObject::bind(this, SLOT(sendNextBlock(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source)); QxtMetaObject::connect(source, SIGNAL(readyRead()), QxtMetaObject::bind(this, SLOT(blockReadyRead(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source)), Qt::QueuedConnection); QxtMetaObject::connect(source, SIGNAL(aboutToClose()), QxtMetaObject::bind(this, SLOT(closeConnection(int)), Q_ARG(int, requestID)), Qt::QueuedConnection); } else { header.setValue("transfer-encoding", "chunked"); state.onBytesWritten = QxtMetaObject::bind(this, SLOT(sendNextChunk(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source)); QxtMetaObject::connect(source, SIGNAL(readyRead()), QxtMetaObject::bind(this, SLOT(chunkReadyRead(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source)), Qt::QueuedConnection); QxtMetaObject::connect(source, SIGNAL(aboutToClose()), QxtMetaObject::bind(this, SLOT(sendEmptyChunk(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source)), Qt::QueuedConnection); } QxtMetaObject::connect(device, SIGNAL(bytesWritten(qint64)), state.onBytesWritten, Qt::QueuedConnection); if (state.keepAlive) { header.setValue("connection", "keep-alive"); } else { header.setValue("connection", "close"); } connector()->writeHeaders(device, header); if (state.readyRead) { if (pe->chunked) sendNextChunk(requestID, source); else sendNextBlock(requestID, source); } } foreach(int id, removeIDs) { delete d.eventQueue.takeAt(id); } if (d.eventQueue.count()) QMetaObject::invokeMethod(this, "processEvents", Qt::QueuedConnection); } /*! * \internal */ void QxtHttpSessionManager::chunkReadyRead(int requestID, QObject* dataSourceObject) { QIODevice* dataSource = static_cast(dataSourceObject); if (!dataSource->bytesAvailable()) return; QIODevice* device = connector()->getRequestConnection(requestID); if (!device->bytesToWrite() || qxt_d().connectionState[device].readyRead == false) { qxt_d().connectionState[device].readyRead = true; sendNextChunk(requestID, dataSourceObject); } } /*! * \internal */ void QxtHttpSessionManager::sendNextChunk(int requestID, QObject* dataSourceObject) { QIODevice* dataSource = static_cast(dataSourceObject); QIODevice* device = connector()->getRequestConnection(requestID); QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[device]; if (state.finishedTransfer) { // This is just the last block written; we're done with it return; } if (!dataSource->bytesAvailable()) { state.readyRead = false; return; } QByteArray chunk = dataSource->read(32768); // this is a good chunk size if (chunk.size()) { QByteArray data = QString::number(chunk.size(), 16).toUtf8() + "\r\n" + chunk + "\r\n"; device->write(data); } state.readyRead = false; if (!state.streaming && !dataSource->bytesAvailable()) QMetaObject::invokeMethod(this, "sendEmptyChunk", Q_ARG(int, requestID), Q_ARG(QObject*, dataSource)); } /*! * \internal */ void QxtHttpSessionManager::sendEmptyChunk(int requestID, QObject* dataSource) { QIODevice* device = connector()->getRequestConnection(requestID); if (!qxt_d().connectionState.contains(device)) return; // in case a disconnect signal and a bytesWritten signal get fired in the wrong order QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[device]; if (state.finishedTransfer) return; state.finishedTransfer = true; device->write("0\r\n\r\n"); dataSource->deleteLater(); if (state.keepAlive) { delete state.onBytesWritten; state.onBytesWritten = 0; connector()->incomingData(device); } else { closeConnection(requestID); } } /*! * \internal */ void QxtHttpSessionManager::closeConnection(int requestID) { QIODevice* device = connector()->getRequestConnection(requestID); QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[device]; state.finishedTransfer = true; QTcpSocket* socket = qobject_cast(device); if (socket) socket->disconnectFromHost(); else device->close(); } /*! * \internal */ void QxtHttpSessionManager::blockReadyRead(int requestID, QObject* dataSourceObject) { QIODevice* dataSource = static_cast(dataSourceObject); if (!dataSource->bytesAvailable()) return; QIODevice* device = connector()->getRequestConnection(requestID); if (!device->bytesToWrite() || qxt_d().connectionState[device].readyRead == false) { qxt_d().connectionState[device].readyRead = true; sendNextBlock(requestID, dataSourceObject); } } /*! * \internal */ void QxtHttpSessionManager::sendNextBlock(int requestID, QObject* dataSourceObject) { QIODevice* dataSource = static_cast(dataSourceObject); QIODevice* device = connector()->getRequestConnection(requestID); if (!qxt_d().connectionState.contains(device)) return; // in case a disconnect signal and a bytesWritten signal get fired in the wrong order QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[device]; if (state.finishedTransfer) return; if (!dataSource->bytesAvailable()) { state.readyRead = false; return; } QByteArray chunk = dataSource->read(32768); // this is a good chunk size device->write(chunk); state.readyRead = false; if (!state.streaming && !dataSource->bytesAvailable()) { closeConnection(requestID); dataSource->deleteLater(); } } libqxt-0.6.2/src/web/qxthttpsessionmanager.h000066400000000000000000000057751215241066400212310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTHTTPSESSIONMANAGER_H #define QXTHTTPSESSIONMANAGER_H #include "qxtabstractwebsessionmanager.h" #include "qxtabstracthttpconnector.h" #include #include class QxtWebEvent; class QxtWebContent; class QxtHttpSessionManagerPrivate; class QXT_WEB_EXPORT QxtHttpSessionManager : public QxtAbstractWebSessionManager { friend class QxtAbstractHttpConnector; Q_OBJECT public: enum Connector { HttpServer, Scgi, Fcgi }; QxtHttpSessionManager(QObject* parent = 0); virtual void postEvent(QxtWebEvent*); QHostAddress listenInterface() const; void setListenInterface(const QHostAddress& iface); quint16 port() const; void setPort(quint16 port); QByteArray sessionCookieName() const; void setSessionCookieName(const QByteArray& name); bool autoCreateSession() const; void setAutoCreateSession(bool enable); QxtAbstractWebService* staticContentService() const; void setStaticContentService(QxtAbstractWebService* service); void setConnector(QxtAbstractHttpConnector* connector); void setConnector(Connector connector); QxtAbstractHttpConnector* connector() const; virtual bool start(); protected: virtual int newSession(); virtual void incomingRequest(quint32 requestID, const QHttpRequestHeader& header, QxtWebContent* device); protected Q_SLOTS: virtual void processEvents(); private Q_SLOTS: void closeConnection(int requestID); void chunkReadyRead(int requestID, QObject* dataSource); void sendNextChunk(int requestID, QObject* dataSource); void sendEmptyChunk(int requestID, QObject* dataSource); void blockReadyRead(int requestID, QObject* dataSource); void sendNextBlock(int requestID, QObject* dataSource); private: void disconnected(QIODevice* device); QXT_DECLARE_PRIVATE(QxtHttpSessionManager) }; #endif libqxt-0.6.2/src/web/qxtscgiserverconnector.cpp000066400000000000000000000111061215241066400217160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtScgiServerConnector \inmodule QxtWeb \brief The QxtScgiServerConnector class provides an SCGI connector for QxtHttpSessionManager QxtScgiServerConnector implements the SCGI protocoll supported by almost all modern web servers. \sa QxtHttpSessionManager */ #include "qxthttpsessionmanager.h" #include "qxtwebevent.h" #include #include #include #include #ifndef QXT_DOXYGEN_RUN class QxtScgiServerConnectorPrivate : public QxtPrivate { public: QTcpServer* server; }; #endif /*! * Creates a QxtHttpServerConnector with the given \a parent. */ QxtScgiServerConnector::QxtScgiServerConnector(QObject* parent) : QxtAbstractHttpConnector(parent) { QXT_INIT_PRIVATE(QxtScgiServerConnector); qxt_d().server = new QTcpServer(this); QObject::connect(qxt_d().server, SIGNAL(newConnection()), this, SLOT(acceptConnection())); } /*! * \reimp */ bool QxtScgiServerConnector::listen(const QHostAddress& iface, quint16 port) { return qxt_d().server->listen(iface, port); } /*! * \internal */ void QxtScgiServerConnector::acceptConnection() { QTcpSocket* socket = qxt_d().server->nextPendingConnection(); addConnection(socket); } /*! * \reimp */ bool QxtScgiServerConnector::canParseRequest(const QByteArray& buffer) { if (buffer.size() < 10) return false; QString expectedsize; for (int i = 0;i < 10;i++) { if (buffer.at(i) == ':') { break; } else { expectedsize += buffer.at(i); } } if (expectedsize.isEmpty()) { //protocoll error return false; } return (buffer.size() > expectedsize.toInt()); } /*! * \reimp */ QHttpRequestHeader QxtScgiServerConnector::parseRequest(QByteArray& buffer) { QString expectedsize_s; for (int i = 0;i < 20;i++) { if (buffer.at(i) == ':') { break; } else { expectedsize_s += buffer.at(i); } } if (expectedsize_s.isEmpty()) { //protocoll error return QHttpRequestHeader(); } buffer = buffer.right(buffer.size() - (expectedsize_s.count() + 1)); QHttpRequestHeader request_m; QByteArray name; int i = 0; while ((i = buffer.indexOf('\0')) > -1) { if (name.isEmpty()) { name = buffer.left(i); } else { request_m.setValue(QString::fromAscii(name).toLower(), QString::fromAscii(buffer.left(i))); name = ""; } buffer = buffer.mid(i + 1); } request_m.setRequest(request_m.value("request_method"), request_m.value("request_uri"), 1, 0); foreach(const QString& key, request_m.keys()) { if (key.startsWith(QString("http_"))) { request_m.setValue(key.right(key.size() - 5), request_m.value(key)); } } request_m.setValue("Connection", "close"); buffer.chop(1); return request_m; } /*! * \reimp */ void QxtScgiServerConnector::writeHeaders(QIODevice* device, const QHttpResponseHeader& response_m) { device->write(("Status:" + QString::number(response_m.statusCode()) + ' ' + response_m.reasonPhrase() + "\r\n").toAscii()); foreach(const QString& key, response_m.keys()) { device->write((key + ':' + response_m.value(key) + "\r\n").toAscii()); } device->write("\r\n"); } libqxt-0.6.2/src/web/qxtweb.h000066400000000000000000000031031215241066400160470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTWEB_H_INCLUDED #define QXTWEB_H_INCLUDED #include "qxtabstracthttpconnector.h" #include "qxtabstractwebservice.h" #include "qxtabstractwebsessionmanager.h" #include "qxtwebcgiservice.h" #include "qxthtmltemplate.h" #include "qxthttpsessionmanager.h" #include "qxtwebcontent.h" #include "qxtwebevent.h" #include "qxtwebservicedirectory.h" #include "qxtwebslotservice.h" #endif // QXTWEB_H_INCLUDED libqxt-0.6.2/src/web/qxtwebcgiservice.cpp000066400000000000000000000362721215241066400204630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtWebCgiService \inmodule QxtWeb \brief The QxtWebCgiService class provides a CGI/1.1 gateway for QxtWeb TODO: write docs TODO: implement timeout */ #include "qxtwebcgiservice.h" #include "qxtwebcgiservice_p.h" #include "qxtwebevent.h" #include "qxtwebcontent.h" #include #include #include #include QxtCgiRequestInfo::QxtCgiRequestInfo() : sessionID(0), requestID(0), eventSent(false), terminateSent(false) {} QxtCgiRequestInfo::QxtCgiRequestInfo(QxtWebRequestEvent* req) : sessionID(req->sessionID), requestID(req->requestID), eventSent(false), terminateSent(false) {} /*! * Constructs a QxtWebCgiService object with the specified session \a manager and \a parent. * This service will invoke the specified \a binary to handle incoming requests. * * Often, the session manager will also be the parent, but this is not a requirement. */ QxtWebCgiService::QxtWebCgiService(const QString& binary, QxtAbstractWebSessionManager* manager, QObject* parent) : QxtAbstractWebService(manager, parent) { QXT_INIT_PRIVATE(QxtWebCgiService); qxt_d().binary = binary; QObject::connect(&qxt_d().timeoutMapper, SIGNAL(mapped(QObject*)), &qxt_d(), SLOT(terminateProcess(QObject*))); } /*! * Returns the path to the CGI script that will be executed to handle requests. * * \sa setBinary() */ QString QxtWebCgiService::binary() const { return qxt_d().binary; } /*! * Sets the path to the CGI script \a bin that will be executed to handle requests. * * \sa binary() */ void QxtWebCgiService::setBinary(const QString& bin) { if (!QFile::exists(bin) || !(QFile::permissions(bin) & (QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther))) { qWarning() << "QxtWebCgiService::setBinary: " + bin + " does not appear to be executable."; } qxt_d().binary = bin; } /*! * Returns the maximum time a CGI script may execute, in milliseconds. * * The default value is 0, which indicates that CGI scripts will not be terminated * due to long running times. * * \sa setTimeout() */ int QxtWebCgiService::timeout() const { return qxt_d().timeout; } /*! * Sets the maximum \a time a CGI script may execute, in milliseconds. * * The timer is started when the script is launched. After the timeout elapses once, * the script will be asked to stop, as QProcess::terminate(). (That is, the script * will receive WM_CLOSE on Windows or SIGTERM on UNIX.) If the process has still * failed to terminate after another timeout, it will be forcibly terminated, as * QProcess::kill(). (That is, the script will receive TerminateProcess on Windows * or SIGKILL on UNIX.) * * Set the timeout to 0 to disable this behavior; scripts will not be terminated * due to excessive run time. This is the default behavior. * * CAUTION: Keep in mind that the timeout applies to the real running time of the * script, not processor time used. A script that initiates a lengthy download * may be interrupted while transferring data to the web browser. To avoid this * behavior, see the timeoutOverride property to allow the script to request * an extended timeout, or use a different QxtAbstractWebService object for * serving streaming content or large files. * * * \sa timeout(), timeoutOverride(), setTimeoutOverride(), QProcess::terminate(), QProcess::kill() */ void QxtWebCgiService::setTimeout(int time) { qxt_d().timeout = time; } /*! * Returns whether or not to allow scripts to override the timeout. * * \sa setTimeoutOverride(), setTimeout() */ bool QxtWebCgiService::timeoutOverride() const { return qxt_d().timeoutOverride; } /*! * Sets whether or not to allow scripts to override the timeout. * Scripts are allowed to override if \a enable is \c true. * * As an extension to the CGI/1.1 gateway specification, a CGI script may * output a "X-QxtWeb-Timeout" header to change the termination timeout * on a per-script basis. Only enable this option if you trust the scripts * being executed. * * \sa timeoutOverride(), setTimeout() */ void QxtWebCgiService::setTimeoutOverride(bool enable) { qxt_d().timeoutOverride = enable; } /*! * \reimp */ void QxtWebCgiService::pageRequestedEvent(QxtWebRequestEvent* event) { // Create the process object and initialize connections QProcess* process = new QProcess(this); qxt_d().requests[process] = QxtCgiRequestInfo(event); qxt_d().processes[event->content] = process; QxtCgiRequestInfo& requestInfo = qxt_d().requests[process]; QObject::connect(process, SIGNAL(readyRead()), &qxt_d(), SLOT(processReadyRead())); QObject::connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), &qxt_d(), SLOT(processFinished())); QObject::connect(process, SIGNAL(error(QProcess::ProcessError)), &qxt_d(), SLOT(processFinished())); requestInfo.timeout = new QTimer(process); qxt_d().timeoutMapper.setMapping(requestInfo.timeout, process); QObject::connect(requestInfo.timeout, SIGNAL(timeout()), &qxt_d().timeoutMapper, SLOT(map())); // Initialize the system environment QStringList s_env = process->systemEnvironment(); QMap env; foreach(const QString& entry, s_env) { int pos = entry.indexOf('='); env[entry.left(pos)] = entry.mid(pos + 1); } // Populate CGI/1.1 environment variables env["SERVER_SOFTWARE"] = QString("QxtWeb/" QXT_VERSION_STR); env["SERVER_NAME"] = event->url.host(); env["GATEWAY_INTERFACE"] = "CGI/1.1"; if (event->headers.contains("X-Request-Protocol")) env["SERVER_PROTOCOL"] = event->headers.value("X-Request-Protocol"); else env.remove("SERVER_PROTOCOL"); if (event->url.port() != -1) env["SERVER_PORT"] = QString::number(event->url.port()); else env.remove("SERVER_PORT"); env["REQUEST_METHOD"] = event->method; env["PATH_INFO"] = event->url.path(); env["PATH_TRANSLATED"] = event->url.path(); // CGI/1.1 says we should resolve this, but we have no logical interpretation env["SCRIPT_NAME"] = event->originalUrl.path().remove(QRegExp(QRegExp::escape(event->url.path()) + '$')); env["SCRIPT_FILENAME"] = qxt_d().binary; // CGI/1.1 doesn't define this but PHP demands it env.remove("REMOTE_HOST"); env["REMOTE_ADDR"] = event->remoteAddress; // TODO: If we ever support HTTP authentication, we should use these env.remove("AUTH_TYPE"); env.remove("REMOTE_USER"); env.remove("REMOTE_IDENT"); if (event->contentType.isEmpty()) { env.remove("CONTENT_TYPE"); env.remove("CONTENT_LENGTH"); } else { env["CONTENT_TYPE"] = event->contentType; env["CONTENT_LENGTH"] = QString::number(event->content->unreadBytes()); } env["QUERY_STRING"] = event->url.encodedQuery(); // Populate HTTP header environment variables QMultiHash::const_iterator iter = event->headers.begin(); while (iter != event->headers.end()) { QString key = "HTTP_" + iter.key().toUpper().replace('-', '_'); if (key != "HTTP_CONTENT_TYPE" && key != "HTTP_CONTENT_LENGTH") env[key] = iter.value(); iter++; } // Populate HTTP_COOKIE parameter iter = event->cookies.begin(); QString cookies; while (iter != event->cookies.end()) { if (!cookies.isEmpty()) cookies += "; "; cookies += iter.key() + '=' + iter.value(); iter++; } if (!cookies.isEmpty()) env["HTTP_COOKIE"] = cookies; // Load environment into process space QStringList p_env; QMap::iterator env_iter = env.begin(); while (env_iter != env.end()) { p_env << env_iter.key() + '=' + env_iter.value(); env_iter++; } process->setEnvironment(p_env); // Launch process if (event->url.hasQuery() && event->url.encodedQuery().contains('=')) { // CGI/1.1 spec says to pass the query on the command line if there's no embedded = sign process->start(qxt_d().binary + ' ' + QUrl::fromPercentEncoding(event->url.encodedQuery()), QIODevice::ReadWrite); } else { process->start(qxt_d().binary, QIODevice::ReadWrite); } // Start the timeout if(qxt_d().timeout > 0) { requestInfo.timeout->start(qxt_d().timeout); } // Transmit POST data if (event->content) { QObject::connect(event->content, SIGNAL(readyRead()), &qxt_d(), SLOT(browserReadyRead())); qxt_d().browserReadyRead(event->content); } } /*! * \internal */ void QxtWebCgiServicePrivate::browserReadyRead(QObject* o_content) { if (!o_content) o_content = sender(); QxtWebContent* content = static_cast(o_content); // this is a private class, no worries about type safety // Read POST data and copy it to the process QByteArray data = content->readAll(); if (!data.isEmpty()) processes[content]->write(data); // If no POST data remains unsent, clean up if (!content->unreadBytes() && processes.contains(content)) { processes[content]->closeWriteChannel(); processes.remove(content); } } /*! * \internal */ void QxtWebCgiServicePrivate::processReadyRead() { QProcess* process = static_cast(sender()); QxtCgiRequestInfo& request = requests[process]; QByteArray line; while (process->canReadLine()) { // Read in a CGI/1.1 header line line = process->readLine().replace(QByteArray("\r"), ""); //krazy:exclude=doublequote_chars if (line == "\n") { // An otherwise-empty line indicates the end of CGI/1.1 headers and the start of content QObject::disconnect(process, SIGNAL(readyRead()), this, 0); QxtWebPageEvent* event = 0; int code = 200; if (request.headers.contains("status")) { // CGI/1.1 defines a "Status:" header that dictates the HTTP response code code = request.headers["status"].left(3).toInt(); if (code >= 300 && code < 400) // redirect { event = new QxtWebRedirectEvent(request.sessionID, request.requestID, request.headers["location"], code); } } // If a previous header (currently just status) hasn't created an event, create a normal page event here if (!event) { event = new QxtWebPageEvent(request.sessionID, request.requestID, process); event->status = code; } // Add other response headers passed from CGI (currently only Content-Type is supported) if (request.headers.contains("content-type")) event->contentType = request.headers["content-type"].toUtf8(); // TODO: QxtWeb doesn't support transmitting arbitrary HTTP headers right now, but it may be desirable // for applications that know what kind of server frontend they're using to allow scripts to send // protocol-specific headers. // Post the event qxt_p().postEvent(event); request.eventSent = true; return; } else { // Since we haven't reached the end of headers yet, parse a header int pos = line.indexOf(": "); QByteArray hdrName = line.left(pos).toLower(); QByteArray hdrValue = line.mid(pos + 2).replace(QByteArray("\n"), ""); //krazy:exclude=doublequote_chars if (hdrName == "set-cookie") { // Parse a new cookie and post an event to send it to the client QList cookies = hdrValue.split(','); foreach(const QByteArray& cookie, cookies) { int equals = cookie.indexOf("="); int semi = cookie.indexOf(";"); QByteArray cookieName = cookie.left(equals); int age = cookie.toLower().indexOf("max-age=", semi); int secs = -1; if (age >= 0) secs = cookie.mid(age + 8, cookie.indexOf(";", age) - age - 8).toInt(); if (secs == 0) { qxt_p().postEvent(new QxtWebRemoveCookieEvent(request.sessionID, cookieName)); } else { QByteArray cookieValue = cookie.mid(equals + 1, semi - equals - 1); QDateTime cookieExpires; if (secs != -1) cookieExpires = QDateTime::currentDateTime().addSecs(secs); qxt_p().postEvent(new QxtWebStoreCookieEvent(request.sessionID, cookieName, cookieValue, cookieExpires)); } } } else if(hdrName == "x-qxtweb-timeout") { if(timeoutOverride) request.timeout->setInterval(hdrValue.toInt()); } else { // Store other headers for later inspection request.headers[hdrName] = hdrValue; } } } } /*! * \internal */ void QxtWebCgiServicePrivate::processFinished() { QProcess* process = static_cast(sender()); QxtCgiRequestInfo& request = requests[process]; if (!request.eventSent) { // If no event was posted, issue an internal error qxt_p().postEvent(new QxtWebErrorEvent(request.sessionID, request.requestID, 500, "Internal Server Error")); } // Clean up data structures process->close(); QxtWebContent* key = processes.key(process); if (key) processes.remove(key); timeoutMapper.removeMappings(request.timeout); requests.remove(process); } /*! * \internal */ void QxtWebCgiServicePrivate::terminateProcess(QObject* o_process) { QProcess* process = static_cast(o_process); QxtCgiRequestInfo& request = requests[process]; if(request.terminateSent) { // kill with fire process->kill(); } else { // kill nicely process->terminate(); request.terminateSent = true; } } libqxt-0.6.2/src/web/qxtwebcgiservice.h000066400000000000000000000037131215241066400201220ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTWEBCGISERVICE_H #define QXTWEBCGISERVICE_H #include #include #include "qxtabstractwebsessionmanager.h" #include "qxtabstractwebservice.h" class QxtWebEvent; class QxtWebRequestEvent; class QxtWebCgiServicePrivate; class QXT_WEB_EXPORT QxtWebCgiService : public QxtAbstractWebService { Q_OBJECT public: QxtWebCgiService(const QString& binary, QxtAbstractWebSessionManager* manager, QObject* parent = 0); QString binary() const; void setBinary(const QString& bin); int timeout() const; void setTimeout(int time); bool timeoutOverride() const; void setTimeoutOverride(bool enable); virtual void pageRequestedEvent(QxtWebRequestEvent* event); private: QXT_DECLARE_PRIVATE(QxtWebCgiService) }; #endif // QXTWEBCGISERVICE_H libqxt-0.6.2/src/web/qxtwebcgiservice_p.h000066400000000000000000000043361215241066400204430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTWEBCGISERVICE_P_H #define QXTWEBCGISERVICE_P_H #include "qxtwebcgiservice.h" #include #include #include #include #include #ifndef QXT_DOXYGEN_RUN QT_FORWARD_DECLARE_CLASS(QProcess) class QxtWebContent; struct QxtCgiRequestInfo { QxtCgiRequestInfo(); QxtCgiRequestInfo(QxtWebRequestEvent* req); int sessionID, requestID; QHash headers; bool eventSent, terminateSent; QTimer* timeout; }; class QxtWebCgiServicePrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtWebCgiService) QHash requests; QHash processes; QString binary; int timeout; bool timeoutOverride; QSignalMapper timeoutMapper; public Q_SLOTS: void browserReadyRead(QObject* o_content = 0); void processReadyRead(); void processFinished(); void terminateProcess(QObject* o_process); }; #endif // QXT_DOXYGEN_RUN #endif // QXTWEBSERVICEDIRECTORY_P_H libqxt-0.6.2/src/web/qxtwebcontent.cpp000066400000000000000000000177201215241066400200070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtWebContent \inmodule QxtWeb \brief The QxtWebContent class provides and I/O device for data sent by the web browser QxtWebContent is a read-only QIODevice subclass that encapsulates data sent from the web browser, for instance in a POST or PUT request. In order to avoid delays while reading content sent from the client, and to insulate multiple pipelined requests on the same connection from each other, QxtWeb uses QxtWebContent as an abstraction for streaming data. \sa QxtAbstractWebService */ #include "qxtwebcontent.h" #include #include #ifndef QXT_DOXYGEN_RUN class QxtWebContentPrivate : public QxtPrivate { public: QxtWebContentPrivate() : ignoreRemaining(false) {} QXT_DECLARE_PUBLIC(QxtWebContent) void init(int contentLength, const QByteArray& start, QIODevice* device) { this->start = start; this->device = device; if (contentLength <= 0) bytesRemaining = -1; else bytesRemaining = contentLength - start.length(); if (device) { QObject::connect(device, SIGNAL(readyRead()), &qxt_p(), SIGNAL(readyRead())); // QObject::connect(device, SIGNAL(aboutToClose()), this, SIGNAL(aboutToClose())); // QObject::connect(device, SIGNAL(destroyed()), this, SIGNAL(aboutToClose())); // ask the object if it has an error signal if (device->metaObject()->indexOfSignal(QMetaObject::normalizedSignature(SIGNAL(error(QAbstractSocket::SocketError)))) >= 0) { QObject::connect(device, SIGNAL(error(QAbstractSocket::SocketError)), &qxt_p(), SLOT(errorReceived(QAbstractSocket::SocketError))); } } qxt_p().setOpenMode(QIODevice::ReadOnly); } qint64 bytesRemaining; QByteArray start; QIODevice* device; bool ignoreRemaining; }; #endif /*! * Constructs a QxtWebContent object. * * The content provided by this constructor is the first \a contentLength bytes * read from the provided \a device. * * The QxtWebContent object is parented to the \a device. */ QxtWebContent::QxtWebContent(int contentLength, QIODevice* device) : QIODevice(device) { QXT_INIT_PRIVATE(QxtWebContent); qxt_d().init(contentLength, QByteArray(), device); } /*! * Constructs a QxtWebContent object. * * The content provided by this constructor is the data contained in \a start, * followed by enough data read from the provided \a device to fill the desired * \a contentLength. * * The QxtWebContent object is parented to the \a device. */ QxtWebContent::QxtWebContent(int contentLength, const QByteArray& start, QIODevice* device) : QIODevice(device) { QXT_INIT_PRIVATE(QxtWebContent); qxt_d().init(contentLength, start, device); } /*! * Constructs a QxtWebContent object with the specified \a parent. * * The content provided by this constructor is exactly the data contained in * \a content. */ QxtWebContent::QxtWebContent(const QByteArray& content, QObject* parent) : QIODevice(parent) { QXT_INIT_PRIVATE(QxtWebContent); qxt_d().init(content.size(), content, 0); } /*! * \reimp */ qint64 QxtWebContent::bytesAvailable() const { qint64 available = QIODevice::bytesAvailable() + (qxt_d().device ? qxt_d().device->bytesAvailable() : 0) + qxt_d().start.count(); if (available > qxt_d().bytesRemaining) return qxt_d().bytesRemaining; return available; } /*! * \reimp */ qint64 QxtWebContent::readData(char* data, qint64 maxSize) { char* writePtr = data; // read more than 32k; TCP ideally handles 48k blocks but we need wiggle room if (maxSize > 32768) maxSize = 32768; // don't read more than the content-length int sz = qxt_d().start.count(); if (sz > 0 && maxSize > sz) { memcpy(writePtr, qxt_d().start.constData(), sz); writePtr += sz; maxSize -= sz; qxt_d().start.clear(); } else if (sz > 0 && sz >= maxSize) { memcpy(writePtr, qxt_d().start.constData(), maxSize); qxt_d().start = qxt_d().start.mid(maxSize); return maxSize; } if (qxt_d().device == 0) { return sz; } else if (qxt_d().bytesRemaining >= 0) { qint64 readBytes = qxt_d().device->read(writePtr, (maxSize > qxt_d().bytesRemaining) ? qxt_d().bytesRemaining : maxSize); qxt_d().bytesRemaining -= readBytes; if (qxt_d().bytesRemaining == 0) QMetaObject::invokeMethod(this, "aboutToClose", Qt::QueuedConnection); return sz + readBytes; } else { return sz + qxt_d().device->read(writePtr, maxSize); } } /*! * Returns the number of bytes of content that have not yet been read. * * Note that not all of the remaining content may be immediately available for * reading. This function returns the content length, minus the number of * bytes that have already been read. */ qint64 QxtWebContent::unreadBytes() const { return qxt_d().start.size() + qxt_d().bytesRemaining; } /*! * \reimp */ qint64 QxtWebContent::writeData(const char*, qint64) { // always an error to write return -1; } /*! * \internal */ void QxtWebContent::errorReceived(QAbstractSocket::SocketError) { setErrorString(qxt_d().device->errorString()); } /*! * Blocks until all of the streaming data has been read from the browser. * * Note that this function will block events for the thread on which it is called. * If the main thread is blocked, QxtWeb will be unable to process additional * requests until the content has been received. */ void QxtWebContent::waitForAllContent() { if (!qxt_d().device) return; QByteArray buffer; while (qxt_d().device && qxt_d().bytesRemaining > 0) { buffer = qxt_d().device->readAll(); qxt_d().start += buffer; qxt_d().bytesRemaining -= buffer.size(); if (qxt_d().bytesRemaining > 0) qxt_d().device->waitForReadyRead(-1); } } /*! * Discards any data not yet read. * * After invoking this function, any further data received from the browser * is silently discarded. */ void QxtWebContent::ignoreRemainingContent() { if (qxt_d().bytesRemaining <= 0 || !qxt_d().device) return; if (!qxt_d().ignoreRemaining) { qxt_d().ignoreRemaining = true; QObject::connect(qxt_d().device, SIGNAL(readyRead()), this, SLOT(ignoreRemainingContent())); } } #ifndef QXT_DOXYGEN_RUN typedef QPair QxtQueryItem; #endif /*! * Extracts the key/value pairs from application/x-www-form-urlencoded \a data, * such as the query string from the URL or the form data from a POST request. */ QHash QxtWebContent::parseUrlEncodedQuery(const QString& data) { QUrl post("/?" + data); QHash rv; foreach(const QxtQueryItem& item, post.queryItems()) { rv.insertMulti(item.first, item.second); } return rv; } libqxt-0.6.2/src/web/qxtwebcontent.h000066400000000000000000000041761215241066400174550ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTWEBCONTENT_H #define QXTWEBCONTENT_H #include #include #include #include class QxtWebContentPrivate; class QXT_WEB_EXPORT QxtWebContent : public QIODevice { Q_OBJECT public: QxtWebContent(int contentLength, const QByteArray& start, QIODevice* device); QxtWebContent(int contentLength, QIODevice* device); explicit QxtWebContent(const QByteArray& content, QObject* parent = 0); static QHash parseUrlEncodedQuery(const QString& data); virtual qint64 bytesAvailable() const; qint64 unreadBytes() const; void waitForAllContent(); public Q_SLOTS: void ignoreRemainingContent(); protected: virtual qint64 readData(char* data, qint64 maxSize); virtual qint64 writeData(const char* data, qint64 maxSize); private Q_SLOTS: void errorReceived(QAbstractSocket::SocketError); private: QXT_DECLARE_PRIVATE(QxtWebContent) }; #endif // QXTWEBCONTENT_H libqxt-0.6.2/src/web/qxtwebevent.cpp000066400000000000000000000313461215241066400174560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtwebevent.h" #include "qxtwebcontent.h" #include /*! \class QxtWebEvent \inmodule QxtWeb \brief The QxtWebEvent class is a base class of all QxtWeb event types QxtWebEvent is the base class for all QxtWeb event classes. Event objects contain event parameters. The base QxtWebEvent class contains the type of the event and a session ID for the session it relates to. Subclasses of QxtWebEvent contain additional parameters describing the particular event. */ /*! \enum QxtWebEvent::EventType \value None Not an event. \value Request A request event. \value FileUpload A file upload event. \value Page A page event. \value StoreCookie A store cookie event. \value RemoveCookie A remove cookie event. \value Redirect A redirect event. */ /*! * Constructs a QxtWebEvent of the specified \a type for the specified \a sessionID. */ QxtWebEvent::QxtWebEvent(EventType type, int sessionID) : sessionID(sessionID), m_type(type) {} /*! * Destroys the event. */ QxtWebEvent::~QxtWebEvent() {} /*! * \fn EventType QxtWebEvent::type() const * Returns the event type. */ /*! * \variable QxtWebEvent::sessionID * Contains the ID of the session the event is related to. */ /*! \class QxtWebRequestEvent \inmodule QxtWeb \brief The QxtWebRequestEvent class describes a request from a web browser The QxtWebRequestEvent class contains information about a request from a web browser. */ /*! * Constructs a QxtWebRequestEvent for the specified \a sessionID, \a requestID and \a url. */ QxtWebRequestEvent::QxtWebRequestEvent(int sessionID, int requestID, const QUrl& url) : QxtWebEvent(QxtWebEvent::Request, sessionID), requestID(requestID), url(url), originalUrl(url) {} /*! * Destroys the event and any content that may still be associated with it. */ QxtWebRequestEvent::~QxtWebRequestEvent() { if (content) delete content; } /*! * \variable QxtWebRequestEvent::requestID * Contains an opaque value generated by the session manager. This request ID * must be included in the QxtWebPageEvent or QxtWebPageEvent subclass that * is the response to the request. */ /*! * \variable QxtWebRequestEvent::url * Contains the request URL, possibly after rewriting by intermediate services * such as QxtWebServiceDirectory. */ /*! * \variable QxtWebRequestEvent::originalUrl * Contains the request URL exactly as it was sent from the web browser. */ /*! * \variable QxtWebRequestEvent::contentType * Contains the MIME type of the request body, if present. */ /*! * \variable QxtWebRequestEvent::content * Contains the content of the request body, if present. */ /*! * \variable QxtWebRequestEvent::cookies * Contains all of the cookies sent by the web browser. */ /*! * \variable QxtWebRequestEvent::headers * Contains all of the headers sent by the web browser. * * Note that use of these values may not be portable across session maangers. */ /* QxtWebFileUploadEvent::QxtWebFileUploadEvent(int sessionID) : QxtWebEvent(QxtWebEvent::FileUpload, sessionID) {} */ /*! \class QxtWebErrorEvent \inmodule QxtWeb \brief The QxtWebErrorEvent class describes an error condition to be sent to a web browser The QxtWebErrorEvent class contains information about an error that will be sent to a web browser. QxtWebErrorEvent is a QxtWebPageEvent, so the \a dataSource may be replaced with a custom error page. If you choose to do this, be sure to delete the original data source automatically generated by the constructor first. */ /*! * Constructs a QxtWebErrorEvent for the specified \a sessionID and \a requestID, * with the provided \a statusCode and \a statusMessage. * * The requestID is an opaque value generated by the session manager; services * will receive this value via QxtWebRequestEvent and must use it in every * event that responds to that request. */ QxtWebErrorEvent::QxtWebErrorEvent(int sessionID, int requestID, int statusCode, QByteArray statusMessage) : QxtWebPageEvent(sessionID, requestID, "

" + statusMessage + "

\r\n") { status = statusCode; QxtWebPageEvent::statusMessage = statusMessage; } /*! \class QxtWebPageEvent \inmodule QxtWeb \brief The QxtWebPageEvent class describes a web page or other content to be sent to a web browser The QxtWebPageEvent class contains information about a web page or other similar content that will be sent to a web browser. */ /*! * Constructs a QxtWebPageEvent for the specified \a sessionID and \a requestID that will * use the data from \a source as the content to be sent to the web browser. * * The requestID is an opaque value generated by the session manager; services * will receive this value via QxtWebRequestEvent and must use it in every * event that responds to that request. * * QxtWeb takes ownership of the source and will delete it when the response * is completed. */ QxtWebPageEvent::QxtWebPageEvent(int sessionID, int requestID, QIODevice* source) : QxtWebEvent(QxtWebEvent::Page, sessionID), dataSource(source), chunked(true), streaming(true), requestID(requestID), status(200), statusMessage("OK"), contentType("text/html") {} /*! * Constructs a QxtWebPageEvent for the specified \a sessionID and \a requestID that will * use \a source as the content to be sent to the web browser. * * The requestID is an opaque value generated by the session manager; services * will receive this value via QxtWebRequestEvent and must use it in every * event that responds to that request. */ QxtWebPageEvent::QxtWebPageEvent(int sessionID, int requestID, QByteArray source) : QxtWebEvent(QxtWebEvent::Page, sessionID), chunked(false), streaming(false), requestID(requestID), status(200), statusMessage("OK"), contentType("text/html") { QBuffer* buffer = new QBuffer; buffer->setData(source); buffer->open(QIODevice::ReadOnly); dataSource = buffer; } /*! * \internal */ QxtWebPageEvent::QxtWebPageEvent(QxtWebEvent::EventType typeOverride, int sessionID, int requestID, QByteArray source) : QxtWebEvent(typeOverride, sessionID), chunked(false), streaming(false), requestID(requestID), status(200), statusMessage("OK"), contentType("text/html") { QBuffer* buffer = new QBuffer; buffer->setData(source); buffer->open(QIODevice::ReadOnly); dataSource = buffer; } /*! * Destroys the event and any data source attached to it. */ QxtWebPageEvent::~QxtWebPageEvent() { if (!dataSource.isNull()) dataSource->deleteLater(); } /*! * \variable QxtWebPageEvent::dataSource * Data will be read from this device and relayed to the web browser. */ /*! * \variable QxtWebPageEvent::chunked * If true, and if the web browser supports "chunked" encoding, the content * will be sent using "chunked" encoding. If false, or if the browser does not * support this encoding (for instance, HTTP/0.9 and HTTP/1.0 user agents), * HTTP keep-alive will be disabled. * * The default value is true when using the QIODevice* constructor and false * when using the QByteArray constructor. */ /*! * \variable QxtWebPageEvent::streaming * If true, the data source is considered to be a source of streaming data. * The QIODevice must emit the readyRead() signal when data is available and * must emit aboutToClose() after all data has been transferred. (This can * be accomplished by invoking QIODevice::close() on it after all data is * determined to have been transferred.) * * The default value is true when using the QIODevice* constructor and false * when using the QByteArray constructor. If using a QIODevice that does not * produce streaming data, such as QFile, this \a must be set to false to * ensure correct behavior. */ /*! * \variable QxtWebPageEvent::requestID * Contains the opaque requestID provided by QxtWebRequestEvent. */ /*! * \variable QxtWebPageEvent::status * Contains the HTTP status code that will be sent with the response. * * The default value is 200 ("OK"). */ /*! * \variable QxtWebPageEvent::statusMessage * Contains the human-readable message associated with the HTTP status code * that will be sent with the response. * * The default value is "OK". */ /*! * \variable QxtWebPageEvent::contentType * Contains the MIME type of the content being sent to the web browser. * * The default value is "text/html". */ /*! * \variable QxtWebPageEvent::headers * Contains custom headers to be sent to the web browser. * * It is empty by default. */ /*! \class QxtWebStoreCookieEvent \inmodule QxtWeb \brief The QxtWebStoreCookieEvent class describes a cookie to be sent to a web browser The QxtWebStoreCookieEvent class instructs the session manager to store a cookie on the web browser. */ /*! * Constructs a QxtWebStoreCookieEvent for the specified \a sessionID that will * store a cookie with the specified \a name and \a data on the web browser. * * If an \a expiration date is supplied, it will be passed to the browser along * with the cookie. The browser will delete the cookie automatically after * the specified date. If an expiration date is not supplied, the cookie will * expire when the browser is closed. */ QxtWebStoreCookieEvent::QxtWebStoreCookieEvent(int sessionID, QString name, QString data, QDateTime expiration) : QxtWebEvent(QxtWebEvent::StoreCookie, sessionID), name(name), data(data), expiration(expiration) {} /*! * \variable QxtWebStoreCookieEvent::name * Contains the name of the cookie to be stored. */ /*! * \variable QxtWebStoreCookieEvent::data * Contains the content of the cookie to be stored. */ /*! * \variable QxtWebStoreCookieEvent::expiration * Contains the expiration date of the cookie to be stored. If null, the * cookie will expire when the web browser is closed. */ /*! \class QxtWebRemoveCookieEvent \inmodule QxtWeb \brief The QxtWebRemoveCookieEvent class describes a cookie to be deleted from a web browser The QxtWebStoreCookieEvent class instructs the session manager to remove a cookie stored on the web browser. */ /*! * Constructs a QxtWebRemoveCookieEvent for the specified \a sessionID that * removed the cookie with \a name from the web browser. */ QxtWebRemoveCookieEvent::QxtWebRemoveCookieEvent(int sessionID, QString name) : QxtWebEvent(QxtWebEvent::RemoveCookie, sessionID), name(name) {} /*! * \variable QxtWebRemoveCookieEvent::name * Contains the name of the cookie to be removed. */ /*! \class QxtWebRedirectEvent \inmodule QxtWeb \brief The QxtWebRedirectEvent class describes a redirect event to be sent to a web browser The QxtWebRedirectEvent class instructs the web browser to load a page found at another location. The default status code, 302, indicates that the requested page was found at a different location. Other useful status codes are 301, which indicates that the web browser should always use the new URL in place of the old one, and (in HTTP/1.1) 307, which indicates that the web browser should reissue the same request (including POST data) to the new URL. */ /*! * Constructs a QxtWebRedirectEvent for the specified \a sessionID and \a requestID that * instructs the browser to move to the specified \a destination URL with \a statusCode. */ QxtWebRedirectEvent::QxtWebRedirectEvent(int sessionID, int requestID, const QString& destination, int statusCode) : QxtWebPageEvent(QxtWebEvent::Redirect, sessionID, requestID, QString("Redirect:
%1").arg(destination).toUtf8()), destination(destination) { QxtWebPageEvent::status = statusCode; QxtWebPageEvent::statusMessage = ("Redirect to " + destination).toUtf8(); } /*! * \variable QxtWebRedirectEvent::destination * Contains the new location (absolute or relative) to which the browser * should redirect. */ libqxt-0.6.2/src/web/qxtwebevent.h000066400000000000000000000077641215241066400171320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTWEBEVENT_H #define QXTWEBEVENT_H #include #include #include #include #include #include #include #include QT_FORWARD_DECLARE_CLASS(QIODevice) class QxtWebContent; class QXT_WEB_EXPORT QxtWebEvent { public: enum EventType { None = 0, Request, FileUpload, Page, StoreCookie, RemoveCookie, Redirect }; QxtWebEvent(EventType type, int sessionID); virtual ~QxtWebEvent(); inline EventType type() const { return m_type; } const int sessionID; private: EventType m_type; }; class QXT_WEB_EXPORT QxtWebRequestEvent : public QxtWebEvent { public: QxtWebRequestEvent(int sessionID, int requestID, const QUrl& url); ~QxtWebRequestEvent(); const int requestID; QUrl url; const QUrl originalUrl; QString contentType; QPointer content; QString method; QString remoteAddress; QMultiHash cookies; QMultiHash headers; }; /* TODO: refactor and implement class QXT_WEB_EXPORT QxtWebFileUploadEvent : public QxtWebEvent { public: QxtWebFileUploadEvent(int sessionID); QString filename; int contentLength; QIODevice* content; }; */ class QxtWebRedirectEvent; class QXT_WEB_EXPORT QxtWebPageEvent : public QxtWebEvent { public: QxtWebPageEvent(int sessionID, int requestID, QIODevice* source = 0); QxtWebPageEvent(int sessionID, int requestID, QByteArray source); // creates a QBuffer virtual ~QxtWebPageEvent(); QPointer dataSource; // data is read from this device and written to the client bool chunked; bool streaming; const int requestID; int status; QByteArray statusMessage; QByteArray contentType; QMultiHash headers; private: friend class QxtWebRedirectEvent; QxtWebPageEvent(QxtWebEvent::EventType typeOverride, int sessionID, int requestID, QByteArray source); }; class QXT_WEB_EXPORT QxtWebErrorEvent : public QxtWebPageEvent { public: QxtWebErrorEvent(int sessionID, int requestID, int status, QByteArray statusMessage); }; class QXT_WEB_EXPORT QxtWebStoreCookieEvent : public QxtWebEvent { public: QxtWebStoreCookieEvent(int sessionID, QString name, QString data, QDateTime expiration = QDateTime()); QString name; QString data; QDateTime expiration; }; class QXT_WEB_EXPORT QxtWebRemoveCookieEvent : public QxtWebEvent { public: QxtWebRemoveCookieEvent(int sessionID, QString name); QString name; }; class QXT_WEB_EXPORT QxtWebRedirectEvent : public QxtWebPageEvent { public: QxtWebRedirectEvent(int sessionID, int requestID, const QString& destination, int statusCode = 302); QString destination; }; #endif // QXTWEBEVENT_H libqxt-0.6.2/src/web/qxtwebservicedirectory.cpp000066400000000000000000000167741215241066400217320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtWebServiceDirectory \inmodule QxtWeb \brief The QxtWebServiceDirectory class provides Path-based web service dispatcher QxtWebServiceDirectory allows multiple services to be associated with a single session. Selection between services is determined by the first path component in the URL. For example, the URL "/site/request?param=true" would relay the URL "/request?param=true" to the service named "site". This class can be used recursively to declare a hierarchy of services. For example: \code QxtWebServiceDirectory* top = new QxtWebServiceDirectory(sm, sm); QxtWebServiceDirectory* service1 = new QxtWebServiceDirectory(sm, top); QxtWebServiceDirectory* service2 = new QxtWebServiceDirectory(sm, top); QxtWebServiceDirectory* service1a = new QxtWebServiceDirectory(sm, service1); QxtWebServiceDirectory* service1b = new QxtWebServiceDirectory(sm, service1); top->addService("1", service1); top->addService("2", service2); service1->addService("a", service1a); service1->addService("b", service1b); \endcode This accepts the URLs "/1/a/", "/1/b/", and "/2/". */ #include "qxtwebservicedirectory.h" #include "qxtwebservicedirectory_p.h" #include "qxtwebevent.h" #include #include #ifndef QXT_DOXYGEN_RUN QxtWebServiceDirectoryPrivate::QxtWebServiceDirectoryPrivate() : QObject(0) { // initializers only } void QxtWebServiceDirectoryPrivate::serviceDestroyed() { QxtAbstractWebService* service = qobject_cast(sender()); if (!service) return; // this shouldn't happen QString path; while (!(path = services.key(service)).isNull()) { services.remove(path); } } #endif /*! * Constructs a QxtWebServiceDirectory object with the specified session manager \a sm and \a parent. * * Often, the session manager will also be the parent, but this is not a requirement. */ QxtWebServiceDirectory::QxtWebServiceDirectory(QxtAbstractWebSessionManager* sm, QObject* parent) : QxtAbstractWebService(sm, parent) { QXT_INIT_PRIVATE(QxtWebServiceDirectory); } /*! * Adds a \a service to the directory at the given \a path. * \sa removeService(), service() */ void QxtWebServiceDirectory::addService(const QString& path, QxtAbstractWebService* service) { if (qxt_d().services.contains(path)) { qWarning() << "QxtWebServiceDirectory::addService:" << path << "already registered"; } qxt_d().services[path] = service; if (qxt_d().defaultRedirect.isEmpty()) setDefaultRedirect(path); connect(service, SIGNAL(destroyed()), &qxt_d(), SLOT(serviceDestroyed())); } /*! * Removes the service at the given \a path. * * Note that the service object is not destroyed. */ void QxtWebServiceDirectory::removeService(const QString& path) { if (!qxt_d().services.contains(path)) { qWarning() << "QxtWebServiceDirectory::removeService:" << path << "not registered"; } else { qxt_d().services.remove(path); } } /*! * Returns the service at the given \a path. */ QxtAbstractWebService* QxtWebServiceDirectory::service(const QString& path) const { if (!qxt_d().services.contains(path)) return 0; return qxt_d().services[path]; } /*! * \internal * Returns the first path segment from the URL in the \a event object. * (i.e. "a" from "/a/b/c") This also removes the path segment from the * event object. (in the previous example, the event's URL is now "/b/c") */ static QString extractPathLevel(QxtWebRequestEvent* event) { QString path = event->url.path(); int pos = path.indexOf("/", 1); // the path always starts with / if (pos == -1) event->url.setPath(""); // cue to redirect to /service/ else event->url.setPath(path.mid(pos)); return path.mid(1, pos - 1); } /*! * \reimp */ void QxtWebServiceDirectory::pageRequestedEvent(QxtWebRequestEvent* event) { QString path = extractPathLevel(event); if (path.isEmpty()) { indexRequested(event); } else if (!qxt_d().services.contains(path)) { unknownServiceRequested(event, path); } else if (event->url.path().isEmpty()) { postEvent(new QxtWebRedirectEvent(event->sessionID, event->requestID, path + '/', 307)); } else { qxt_d().services[path]->pageRequestedEvent(event); } } /* * \reimp unimplemented */ /* void QxtWebServiceDirectory::functionInvokedEvent(QxtWebRequestEvent* event) { QString path = extractPathLevel(event); if(path == "") { indexRequested(event); } else if(!qxt_d().services.contains(path)) { unknownServiceRequested(event, path); } else { qxt_d().services[path]->functionInvokedEvent(event); } } */ /*! * This \a event handler is called whenever the URL requests a service with \a name that has * not been added to the directory. * * The default implementation returns a 404 "Service not known" error. * Subclasses may reimplement this event handler to customize this behavior. */ void QxtWebServiceDirectory::unknownServiceRequested(QxtWebRequestEvent* event, const QString& name) { postEvent(new QxtWebErrorEvent(event->sessionID, event->requestID, 404, ("Service "" + QString(name).replace('<', "<") + "" not known").toUtf8())); } /*! * This \a event handler is called whenever the URL does not contain a path, that * is, the URL is "/" or empty. * * The default implementation redirects to the service specified by * setDefaultRedirect(), or invokes unknownServiceRequested() if no default * redirect has been set. */ void QxtWebServiceDirectory::indexRequested(QxtWebRequestEvent* event) { if (defaultRedirect().isEmpty()) { unknownServiceRequested(event, "/"); } else { postEvent(new QxtWebRedirectEvent(event->sessionID, event->requestID, defaultRedirect() + '/', 307)); } } /*! * Returns the path that will be used by default by the indexRequested event. * \sa indexRequested(), setDefaultRedirect() */ QString QxtWebServiceDirectory::defaultRedirect() const { return qxt_d().defaultRedirect; } /*! * Sets the \a path that will be used by default by the indexRequested event. * \sa indexRequested(), defaultRedirect() */ void QxtWebServiceDirectory::setDefaultRedirect(const QString& path) { if (!qxt_d().services.contains(path)) qWarning() << "QxtWebServiceDirectory::setDefaultRedirect:" << path << "not registered"; qxt_d().defaultRedirect = path; } libqxt-0.6.2/src/web/qxtwebservicedirectory.h000066400000000000000000000043261215241066400213650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTWEBSERVICEDIRECTORY_H #define QXTWEBSERVICEDIRECTORY_H #include #include class QxtAbstractWebSessionManager; class QxtWebEvent; class QxtWebServiceDirectoryPrivate; class QXT_WEB_EXPORT QxtWebServiceDirectory : public QxtAbstractWebService { Q_OBJECT public: explicit QxtWebServiceDirectory(QxtAbstractWebSessionManager* sm, QObject* parent = 0); void addService(const QString& path, QxtAbstractWebService* service); void removeService(const QString& path); QxtAbstractWebService* service(const QString& path) const; virtual void pageRequestedEvent(QxtWebRequestEvent* event); // virtual void functionInvokedEvent(QxtWebRequestEvent* event); QString defaultRedirect() const; void setDefaultRedirect(const QString& path); protected: virtual void unknownServiceRequested(QxtWebRequestEvent* event, const QString& name); virtual void indexRequested(QxtWebRequestEvent* event); private: QXT_DECLARE_PRIVATE(QxtWebServiceDirectory) }; #endif // QXTWEBSERVICEDIRECTORY_H libqxt-0.6.2/src/web/qxtwebservicedirectory_p.h000066400000000000000000000033411215241066400217000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTWEBSERVICEDIRECTORY_P_H #define QXTWEBSERVICEDIRECTORY_P_H #include "qxtwebservicedirectory.h" #include #include #ifndef QXT_DOXYGEN_RUN class QxtWebServiceDirectoryPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtWebServiceDirectory) QxtWebServiceDirectoryPrivate(); QHash services; QString defaultRedirect; public Q_SLOTS: void serviceDestroyed(); }; #endif // QXT_DOXYGEN_RUN #endif // QXTWEBSERVICEDIRECTORY_P_H libqxt-0.6.2/src/web/qxtwebslotservice.cpp000066400000000000000000000174671215241066400207070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ /*! \class QxtWebSlotService \inmodule QxtWeb \brief The QxtWebSlotService class provides a Slot based webservice A WebService that resolves the first part of the path to a slot name and passes the rest as arguments. \code class MyService : public QxtWebSlotService { Q_OBJECT public slots: void hello(QxtWebRequestEvent* event, QString a) { postEvent(new QxtWebPageEvent(event->sessionID, event->requestID, "<h1>"+a.toUtf8()+"</h1>)); } } \endcode /hello/foo
will output
<h1>Foo</h1>
\sa QxtAbstractWebService */ #include "qxtwebslotservice.h" #include "qxtwebevent.h" /*! Constructs a new QxtWebSlotService with \a sm and \a parent. */ QxtWebSlotService::QxtWebSlotService(QxtAbstractWebSessionManager* sm, QObject* parent): QxtAbstractWebService(sm, parent) { } /*! Returns the current absolute url of this service depending on the request \a event. */ QUrl QxtWebSlotService::self(QxtWebRequestEvent* event) { QStringList u = event->url.path().split('/'); QStringList o = event->originalUrl.path().split('/'); u.removeFirst(); o.removeFirst(); for (int i = 0;i < u.count();i++) o.removeLast(); QString r = "/"; foreach(const QString& d, o) { r += d + '/'; } return r; } /*! \reimp */ void QxtWebSlotService::pageRequestedEvent(QxtWebRequestEvent* event) { QList args = event->url.path().split('/'); args.removeFirst(); if (args.at(args.count() - 1).isEmpty()) args.removeLast(); ///--------------find action ------------------ QByteArray action = "index"; if (args.count()) { action = args.at(0).toUtf8(); if (action.trimmed().isEmpty()) action = "index"; args.removeFirst(); } bool ok = false; if (args.count() > 7) { ok = QMetaObject::invokeMethod(this, action, Q_ARG(QxtWebRequestEvent*, event), Q_ARG(QString, args.at(0)), Q_ARG(QString, args.at(1)), Q_ARG(QString, args.at(2)), Q_ARG(QString, args.at(3)), Q_ARG(QString, args.at(4)), Q_ARG(QString, args.at(5)), Q_ARG(QString, args.at(6)), Q_ARG(QString, args.at(7)) ); } else if (args.count() > 6) { ok = QMetaObject::invokeMethod(this, action, Q_ARG(QxtWebRequestEvent*, event), Q_ARG(QString, args.at(0)), Q_ARG(QString, args.at(1)), Q_ARG(QString, args.at(2)), Q_ARG(QString, args.at(3)), Q_ARG(QString, args.at(4)), Q_ARG(QString, args.at(5)), Q_ARG(QString, args.at(6)) ); } else if (args.count() > 5) { ok = QMetaObject::invokeMethod(this, action, Q_ARG(QxtWebRequestEvent*, event), Q_ARG(QString, args.at(0)), Q_ARG(QString, args.at(1)), Q_ARG(QString, args.at(2)), Q_ARG(QString, args.at(3)), Q_ARG(QString, args.at(4)), Q_ARG(QString, args.at(5)) ); } else if (args.count() > 4) { ok = QMetaObject::invokeMethod(this, action, Q_ARG(QxtWebRequestEvent*, event), Q_ARG(QString, args.at(0)), Q_ARG(QString, args.at(1)), Q_ARG(QString, args.at(2)), Q_ARG(QString, args.at(3)), Q_ARG(QString, args.at(4)) ); } else if (args.count() > 3) { ok = QMetaObject::invokeMethod(this, action, Q_ARG(QxtWebRequestEvent*, event), Q_ARG(QString, args.at(0)), Q_ARG(QString, args.at(1)), Q_ARG(QString, args.at(2)), Q_ARG(QString, args.at(3)) ); } else if (args.count() > 2) { ok = QMetaObject::invokeMethod(this, action, Q_ARG(QxtWebRequestEvent*, event), Q_ARG(QString, args.at(0)), Q_ARG(QString, args.at(1)), Q_ARG(QString, args.at(2)) ); } else if (args.count() > 1) { ok = QMetaObject::invokeMethod(this, action, Q_ARG(QxtWebRequestEvent*, event), Q_ARG(QString, args.at(0)), Q_ARG(QString, args.at(1)) ); } else if (args.count() > 0) { ok = QMetaObject::invokeMethod(this, action, Q_ARG(QxtWebRequestEvent*, event), Q_ARG(QString, args.at(0)) ); } else { ok = QMetaObject::invokeMethod(this, action, Q_ARG(QxtWebRequestEvent*, event) ); } if (!ok) { QByteArray err = "

Can not find slot

Class " + QByteArray(metaObject()->className()) + "\r{\npublic slots:\r    void " + action.replace('<', "<") + " ( QxtWebRequestEvent* event, ";
        for (int i = 0;i < args.count();i++)
            err += "QString arg" + QByteArray::number(i) + ", ";
        err.chop(2);

        err += " ); \r};\r
"; postEvent(new QxtWebErrorEvent(event->sessionID, event->requestID, 404, err)); } } /*! \reimp */ void QxtWebSlotService::functionInvokedEvent(QxtWebRequestEvent* event) { postEvent(new QxtWebErrorEvent(event->sessionID, event->requestID, 500, "

Not supported

")); } libqxt-0.6.2/src/web/qxtwebslotservice.h000066400000000000000000000032461215241066400203420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTWEBSLOTSERVICE_H #define QXTWEBSLOTSERVICE_H #include "qxtabstractwebservice.h" #include class QXT_WEB_EXPORT QxtWebSlotService : public QxtAbstractWebService { Q_OBJECT public: explicit QxtWebSlotService(QxtAbstractWebSessionManager* sm, QObject* parent = 0); protected: QUrl self(QxtWebRequestEvent* event); virtual void pageRequestedEvent(QxtWebRequestEvent* event); virtual void functionInvokedEvent(QxtWebRequestEvent* event); }; #endif // QXTWEBSLOTSERVICE_H libqxt-0.6.2/src/web/web.pri000066400000000000000000000016411215241066400156620ustar00rootroot00000000000000INCLUDEPATH += $$PWD DEPENDPATH += $$PWD SOURCES += qxtabstracthttpconnector.cpp SOURCES += qxtabstractwebservice.cpp SOURCES += qxtabstractwebsessionmanager.cpp SOURCES += qxthtmltemplate.cpp SOURCES += qxthttpserverconnector.cpp SOURCES += qxthttpsessionmanager.cpp SOURCES += qxtscgiserverconnector.cpp SOURCES += qxtwebcontent.cpp SOURCES += qxtwebevent.cpp SOURCES += qxtwebservicedirectory.cpp SOURCES += qxtwebslotservice.cpp SOURCES += qxtwebcgiservice.cpp HEADERS += qxtabstracthttpconnector.h HEADERS += qxtabstractwebservice.h HEADERS += qxtabstractwebsessionmanager.h HEADERS += qxtabstractwebsessionmanager_p.h HEADERS += qxthtmltemplate.h HEADERS += qxthttpsessionmanager.h HEADERS += qxtweb.h HEADERS += qxtwebcontent.h HEADERS += qxtwebevent.h HEADERS += qxtwebservicedirectory.h HEADERS += qxtwebservicedirectory_p.h HEADERS += qxtwebslotservice.h HEADERS += qxtwebcgiservice.h HEADERS += qxtwebcgiservice_p.h libqxt-0.6.2/src/web/web.pro000066400000000000000000000003071215241066400156660ustar00rootroot00000000000000CLEAN_TARGET = QxtWeb DEFINES += BUILD_QXT_WEB QT = core network QXT = core network CONVENIENCE += $$CLEAN_TARGET include(web.pri) include(../qxtbase.pri) libqxt-0.6.2/src/zeroconf/000077500000000000000000000000001215241066400154375ustar00rootroot00000000000000libqxt-0.6.2/src/zeroconf/qxtavahipoll.cpp000066400000000000000000000135701215241066400206650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtavahipoll.h" #include "qxtavahipoll_p.h" #include #include #include // declare the functions for the struct // comments copied from watch.h so that I know what they do :P /* Create a new watch for the specified file descriptor and for * the specified events. The API will call the callback function * whenever any of the events happens. */ AvahiWatch* qxtAvahiWatchNew(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata); /* Update the events to wait for. It is safe to call this function from an AvahiWatchCallback */ void qxtAvahiWatchUpdate(AvahiWatch *w, AvahiWatchEvent event); /* Return the events that happened. It is safe to call this function from an AvahiWatchCallback */ AvahiWatchEvent qxtAvahiWatchGetEvents(AvahiWatch *w); /* Free a watch. It is safe to call this function from an AvahiWatchCallback */ void qxtAvahiWatchFree(AvahiWatch *w); /* Set a wakeup time for the polling loop. The API will call the callback function when the absolute time *tv is reached. If tv is NULL, the timeout is disabled. After the timeout expired the callback function will be called and the timeout is disabled. You can reenable it by calling timeout_update() */ AvahiTimeout* qxtAvahiTimeoutNew(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata); /* Update the absolute expiration time for a timeout, If tv is * NULL, the timeout is disabled. It is safe to call this function from an AvahiTimeoutCallback */ void qxtAvahiTimeoutUpdate(AvahiTimeout *, const struct timeval *tv); /* Free a timeout. It is safe to call this function from an AvahiTimeoutCallback */ void qxtAvahiTimeoutFree(AvahiTimeout *t); const AvahiPoll* qxtAvahiPoll(void) { static const AvahiPoll avahiPoll = { NULL, qxtAvahiWatchNew, qxtAvahiWatchUpdate, qxtAvahiWatchGetEvents, qxtAvahiWatchFree, qxtAvahiTimeoutNew, qxtAvahiTimeoutUpdate, qxtAvahiTimeoutFree }; return &avahiPoll; } AvahiWatch* qxtAvahiWatchNew(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata) { return new AvahiWatch(fd, event, callback, userdata); } void qxtAvahiWatchUpdate(AvahiWatch *w, AvahiWatchEvent event) { w->setEventType(event); } AvahiWatchEvent qxtAvahiWatchGetEvents(AvahiWatch *w) { return w->lastEvent(); } void qxtAvahiWatchFree(AvahiWatch *w) { if (w->thread() == QThread::currentThread()) delete w; else w->deleteLater(); } AvahiTimeout* qxtAvahiTimeoutNew(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata) { return new AvahiTimeout(tv, callback, userdata); } void qxtAvahiTimeoutUpdate(AvahiTimeout *t, const struct timeval *tv) { t->updateTimeout(tv); } void qxtAvahiTimeoutFree(AvahiTimeout *t) { if (t->thread() == QThread::currentThread()) delete t; else t->deleteLater(); } /* WATCH */ AvahiWatch::AvahiWatch(int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata) : _notifier(0), _fd(fd), _event(event), _lastEvent((AvahiWatchEvent)0), _callback(callback), _userdata(userdata) { setEventType(event); } AvahiWatch::~AvahiWatch() { } void AvahiWatch::setEventType(AvahiWatchEvent event) { if (_notifier != 0) { if (_notifier->thread() == QThread::currentThread()) delete _notifier; else _notifier->deleteLater(); _notifier = 0; } _event = event; switch (_event) { case AVAHI_WATCH_IN: { _notifier = new QSocketNotifier(_fd, QSocketNotifier::Read, this); connect(_notifier, SIGNAL(activated(int)), this, SLOT(activated(int))); break; } case AVAHI_WATCH_OUT: { _notifier = new QSocketNotifier(_fd, QSocketNotifier::Write, this); connect(_notifier, SIGNAL(activated(int)), this, SLOT(activated(int))); break; } default: //The constructor should only get in or out... qWarning("AvahiWatch: Bad event type passed to AvahiWatch constructor"); break; } } void AvahiWatch::activated(int fd) { _lastEvent = _event; _callback(this, _fd, _event, _userdata); _lastEvent = (AvahiWatchEvent)0; } AvahiWatchEvent AvahiWatch::lastEvent() { return _lastEvent; } /* TIMEOUT */ AvahiTimeout::AvahiTimeout(const struct timeval *tv, AvahiTimeoutCallback callback, void* userdata) : _callback(callback), _userdata(userdata) { connect(&_timer, SIGNAL(timeout()), this, SLOT(timeout())); updateTimeout(tv); } AvahiTimeout::~AvahiTimeout() { } void AvahiTimeout::updateTimeout(const struct timeval *tv) { if (tv == 0) { _timer.stop(); return; } qint64 msecs = (avahi_age(tv)) / 1000; if (msecs > 0) msecs = 0; else msecs = -msecs; _timer.setInterval(msecs); _timer.start(); } void AvahiTimeout::timeout() { _timer.stop(); _callback(this, _userdata); } libqxt-0.6.2/src/zeroconf/qxtavahipoll.h000066400000000000000000000030641215241066400203270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTAVAHIPOLL_H #define QXTAVAHIPOLL_H /*! @author Chris Vickery */ struct AvahiPoll; /*! * This function makes the avahi and Qt get along nicely. * This function is only useful for programs using the Avahi library, otherwise it will effectively do nothing. * @return AvahiPoll structure for use with avahi */ const AvahiPoll* qxtAvahiPoll(void); #endif libqxt-0.6.2/src/zeroconf/qxtavahipoll_p.h000066400000000000000000000042221215241066400206430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtWeb module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTAVAHIPOLL_P_H #define QXTAVAHIPOLL_P_H #include #include #include #include // Private QObject that does all the work /** @author Chris Vickery */ class AvahiWatch : public QObject { Q_OBJECT public: AvahiWatch(int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void* userdata); ~AvahiWatch(); void setEventType(AvahiWatchEvent event); AvahiWatchEvent lastEvent(); private slots: void activated(int); private: QSocketNotifier* _notifier; int _fd; AvahiWatchEvent _event; AvahiWatchEvent _lastEvent; AvahiWatchCallback _callback; void* _userdata; }; class AvahiTimeout : public QObject { Q_OBJECT public: AvahiTimeout(const struct timeval *tv, AvahiTimeoutCallback callback, void* userdata); ~AvahiTimeout(); void updateTimeout(const struct timeval *tv); private slots: void timeout(); private: QTimer _timer; AvahiTimeoutCallback _callback; void* _userdata; }; #endif libqxt-0.6.2/src/zeroconf/qxtdiscoverableservice.cpp000066400000000000000000000314011215241066400227220ustar00rootroot00000000000000#include "qxtdiscoverableservice.h" #include "qxtdiscoverableservice_p.h" #include #include #include #include #include /*! \class QxtDiscoverableService \inmodule QxtZeroconf \brief The QxtDiscoverableService class registers a service that can be discovered with Zeroconf, or resolve such a service QxtDiscoverableService represents a service on the local network that can be discovered using Zeroconf. It can function to provide such a service so that other systems on the network can find it, or it can resolve the connection parameters for a service provided by another system on the network. Note that resolving a service requires that you already know the service name in addition to the service type for the remote service; to find all services on the network that offer a given service type, use QxtServiceBrowser. When registering a service, you may specify a set of service subtypes to indicate what kind of optional capabilities your service offers. Other applications browsing for discoverable services (for instance, using QxtServiceBrowser) can limit their search to only those services that provide a given subtype. Use the properties inherited from QxtDiscoverableServiceName to configure the other service parameters. For more information about Zeroconf, see the documentation available on www.zeroconf.org. \sa QxtDiscoverableServiceName \sa QxtServiceBrowser */ void QxtDiscoverableServicePrivate::registerServiceCallback(DNSServiceRef service, DNSServiceFlags flags, DNSServiceErrorType errCode, const char* name, const char* regtype, const char* domain, void* context) { Q_UNUSED(service); Q_UNUSED(flags); Q_UNUSED(regtype); QxtDiscoverableServicePrivate* self = reinterpret_cast(context); QxtDiscoverableService* pub = &(self->qxt_p()); if(errCode == kDNSServiceErr_NoError) { pub->setServiceName(name); pub->setDomain(domain); self->state = QxtDiscoverableService::Registered; emit self->qxt_p().registered(); } else { self->state = QxtDiscoverableService::Unknown; emit self->qxt_p().registrationError((QxtDiscoverableService::ErrorCode)errCode); } } #ifdef Q_OS_WIN void QxtDiscoverableServicePrivate::resolveServiceCallback(DNSServiceRef service, DNSServiceFlags flags, quint32 iface, DNSServiceErrorType errCode, const char* fullname, const char* host, quint16 port, quint16 txtLen, const char* txt, void* context) #else void QxtDiscoverableServicePrivate::resolveServiceCallback(DNSServiceRef service, DNSServiceFlags flags, quint32 iface, DNSServiceErrorType errCode, const char* fullname, const char* host, quint16 port, quint16 txtLen, const unsigned char* txt, void* context) #endif { Q_UNUSED(service); Q_UNUSED(txtLen); Q_UNUSED(txt); Q_UNUSED(flags); QxtDiscoverableServicePrivate* self = reinterpret_cast(context); QxtDiscoverableService* pub = &self->qxt_p(); if(errCode == kDNSServiceErr_NoError) { QxtDiscoverableServiceName name(fullname); pub->setServiceName(name.serviceName()); pub->setDomain(name.domain()); pub->setHost(host); pub->setPort(qFromBigEndian(port)); self->iface = iface; emit pub->resolved(fullname); } else { self->state = QxtDiscoverableService::Unknown; emit pub->resolveError((QxtDiscoverableService::ErrorCode)errCode); } } void QxtDiscoverableServicePrivate::socketData() { DNSServiceProcessResult(service); } /*! * Constructs a QxtDiscoverableService object using the specified service type. * * The service type may be a plain type name or it may be provided in the standard format * specified by the Zeroconf specification. * * The service name will be automatically generated based on the system's hostname. */ QxtDiscoverableService::QxtDiscoverableService(const QString& serviceType, QObject* parent) : QObject(parent), QxtDiscoverableServiceName(QString(), serviceType, QString()) { QXT_INIT_PRIVATE(QxtDiscoverableService); qxt_zeroconf_parse_subtypes(&qxt_d(), serviceType.toUtf8()); } /*! * Constructs a QxtDiscoverableService object using the specified service type. * * The service type may be a plain type name or it may be provided in the standard format * specified by the Zeroconf specification. * * If the specified service name is already in use, it will be updated with a number to * make it unique. */ QxtDiscoverableService::QxtDiscoverableService(const QString& serviceType, const QString& serviceName, QObject* parent) : QObject(parent), QxtDiscoverableServiceName(serviceName, serviceType, QString()) { QXT_INIT_PRIVATE(QxtDiscoverableService); qxt_zeroconf_parse_subtypes(&qxt_d(), serviceType.toUtf8()); } /*! * Destroys the QxtDiscoverableService. * * TIf registered, the service will be unregistered. */ QxtDiscoverableService::~QxtDiscoverableService() { if(state() == Registered || state() == Resolved) releaseService(); } /*! * Returns the current state of the service. */ QxtDiscoverableService::State QxtDiscoverableService::state() const { return qxt_d().state; } /*! * Returns a list of all subtypes known for the service. * * When discovering a service, only subtypes that were included in the service * discovery request will be included in this list. * * \sa setServiceSubTypes * \sa addServiceSubType * \sa removeServiceSubType * \sa hasServiceSubType */ QStringList QxtDiscoverableService::serviceSubTypes() const { return qxt_d().serviceSubTypes; } /*! * Sets the list of subtypes for this service. * * \sa serviceSubTypes * \sa addServiceSubType * \sa removeServiceSubType * \sa hasServiceSubType */ void QxtDiscoverableService::setServiceSubTypes(const QStringList& subtypes) { if(state() != Unknown) qWarning() << "QxtDiscoverableService: Setting service subtypes while not in Unknown state has no effect"; qxt_d().serviceSubTypes = subtypes; } /*! * Adds a subtype to the service. * * \sa serviceSubTypes * \sa setServiceSubTypes * \sa removeServiceSubType * \sa hasServiceSubType */ void QxtDiscoverableService::addServiceSubType(const QString& subtype) { if(state() != Unknown) qWarning() << "QxtDiscoverableService: Setting service subtypes while not in Unknown state has no effect"; qxt_d().serviceSubTypes << subtype; } /*! * Removes a subtype from the service. * * \sa serviceSubTypes * \sa setServiceSubTypes * \sa addServiceSubType * \sa hasServiceSubType */ void QxtDiscoverableService::removeServiceSubType(const QString& subtype) { if(state() != Unknown) qWarning() << "QxtDiscoverableService: Setting service subtypes while not in Unknown state has no effect"; qxt_d().serviceSubTypes.removeAll(subtype); } /*! * Tests to see if the specified service is available and known for the service. * * When discovering a service, only subtypes that were included in the service * discovery request will be available. * * \sa serviceSubTypes * \sa setServiceSubTypes * \sa addServiceSubType * \sa removeServiceSubType */ bool QxtDiscoverableService::hasServiceSubType(const QString& subtype) { return qxt_d().serviceSubTypes.contains(subtype); } /*! * Returns the port number used for connecting to the service. * * \sa setPort */ quint16 QxtDiscoverableService::port() const { return qFromBigEndian(qxt_d().port); } /*! * Sets the port number used for connecting to the service. * * When registering a service with a port number of 0 (the default), the service will not be found when browsing, * but the service name will be marked as reserved. * * Setting the port is only meaningful when registering a service. * * \sa port */ void QxtDiscoverableService::setPort(quint16 port) { qxt_d().port = qToBigEndian(port); } /*! * Attempts to register the service on the local network. * * If noAutoRename is set to true, registration will fail if another service of the same service type * is already registered with the same service name. Otherwise, the service name will be updated with * a number to make it unique. * * \sa registered * \sa registrationError */ void QxtDiscoverableService::registerService(bool noAutoRename) { if(state() != Unknown) { qWarning() << "QxtDiscoverableService: Cannot register service while not in Unknown state"; emit registrationError(0); return; } QStringList subtypes = qxt_d().serviceSubTypes; subtypes.prepend(fullServiceType()); DNSServiceErrorType err; err = DNSServiceRegister(&(qxt_d().service), noAutoRename ? kDNSServiceFlagsNoAutoRename : 0, qxt_d().iface, serviceName().isEmpty() ? 0 : serviceName().toUtf8().constData(), subtypes.join(",_").toUtf8().constData(), domain().isEmpty() ? 0 : domain().toUtf8().constData(), host().isEmpty() ? 0 : host().toUtf8().constData(), qxt_d().port, 1, // must include null terminator "", QxtDiscoverableServicePrivate::registerServiceCallback, &qxt_d()); if(err != kDNSServiceErr_NoError) { qxt_d().state = Unknown; emit registrationError(err); } else { qxt_d().state = Registering; qxt_d().notifier = new QSocketNotifier(DNSServiceRefSockFD(qxt_d().service), QSocketNotifier::Read, this); QObject::connect(qxt_d().notifier, SIGNAL(activated(int)), &qxt_d(), SLOT(socketData())); } } /*! * Attempts to resolve the service in order to determine the host and port necessary to establish a connection. * * If forceMulticast is set to true, QxtDiscoverableService will use a multicast request to resolve the service, * even if the host name appears to be a unicast address (that is, outside the local network). * * \sa resolved * \sa resolveError */ void QxtDiscoverableService::resolve(bool forceMulticast) { if(state() != Unknown && state() != Found) { qWarning() << "QxtDiscoverableService: Cannot resolve service while not in Unknown or Found state"; emit resolveError(0); return; } DNSServiceErrorType err; err = DNSServiceResolve(&(qxt_d().service), (forceMulticast ? kDNSServiceFlagsForceMulticast : 0), qxt_d().iface, serviceName().toUtf8().constData(), fullServiceType().constData(), domain().toUtf8().constData(), QxtDiscoverableServicePrivate::resolveServiceCallback, &qxt_d()); if(err != kDNSServiceErr_NoError) { qxt_d().state = Unknown; emit resolveError(err); } else { qxt_d().state = Resolving; qxt_d().notifier = new QSocketNotifier(DNSServiceRefSockFD(qxt_d().service), QSocketNotifier::Read, this); QObject::connect(qxt_d().notifier, SIGNAL(activated(int)), &qxt_d(), SLOT(socketData())); } } /*! * Releases the service. * * If the service is registered, it will be unregistered. Any outstanding resolve attempt will be aborted. */ void QxtDiscoverableService::releaseService() { if(state() != Registered && state() != Resolved) { qWarning() << "QxtDiscoverableService: Attempting to unregister an unresolved, unregistered service"; } else { DNSServiceRefDeallocate(qxt_d().service); qxt_d().notifier->deleteLater(); } } /*! * \fn registered() * * This signal is emitted after a call to registerService() when the service has been successfully registered * on the network. The service name may have been updated to ensure uniqueness. * * \sa registerService * \sa registrationError */ /*! * \fn registrationError(int code) * * This signal is emitted after a call to registerService() when the service cannot be registered. This could * be because the service name is already in use and noAutoRename was requested, or because the mDNSResponder * or Avahi daemon on the local machine could not be contacted. * * \sa registerService * \sa registered */ /*! * \fn resolved(const QByteArray& domainName) * * This signal is emitted after a call to resolve() when a service matching the requested parameters is found. * domainName contains the complete domain name of the resolved service. The host name, port, and socket type * will be updated to match the connection parameters announced by the service. * * \sa resolve * \sa resolveError */ /*! * \fn resolveError(int code) * * This signal is emitted after a call to resolve() if an error occurs while attempting to resolve the service. * * \sa resolve * \sa resolveError */ libqxt-0.6.2/src/zeroconf/qxtdiscoverableservice.h000066400000000000000000000045071215241066400223760ustar00rootroot00000000000000#ifndef QXTDISCOVERABLESERVICE_H #define QXTDISCOVERABLESERVICE_H #include "qxtglobal.h" #include #include #include #include #include "qxtdiscoverableservicename.h" class QxtDiscoverableServicePrivate; class QxtServiceBrowser; class QXT_ZEROCONF_EXPORT QxtDiscoverableService : public QObject, public QxtDiscoverableServiceName { Q_OBJECT QXT_DECLARE_PRIVATE(QxtDiscoverableService) friend class QxtServiceBrowser; private: QxtDiscoverableService(const QByteArray& domainName, QxtServiceBrowser* parent); public: enum State { Unknown, Registering, Registered, Found, Resolving, Resolved }; enum ServiceFlag { MoreComing = 0x1, Add = 0x2, Remove = 0x0, AddDefault = 0x6, ForceRemove = 0x800, AutoRename = 0x0, NoAutoRename = 0x8, RecordShared = 0x10, RecordUnique = 0x20, BrowseDomains = 0x40, RegistrationDomains = 0x80, LongLivedQuery = 0x100, AllowRemoteQuery = 0x200, ForceMulticast = 0x400, ReturnIntermediates = 0x1000, NonBrowsable = 0x2000, ShareConnection = 0x4000 }; Q_DECLARE_FLAGS(ServiceFlags, ServiceFlag); enum ErrorCode { NoError = 0 }; QxtDiscoverableService(const QString& serviceType, QObject* parent = 0); QxtDiscoverableService(const QString& serviceType, const QString& serviceName, QObject* parent = 0); virtual ~QxtDiscoverableService(); QStringList serviceSubTypes() const; void setServiceSubTypes(const QStringList& subtypes); void addServiceSubType(const QString& subtype); void removeServiceSubType(const QString& subtype); bool hasServiceSubType(const QString& subtype); quint16 port() const; void setPort(quint16 port); void resolve(bool forceMulticast = false); void registerService(bool noAutoRename = false); void releaseService(); State state() const; //bool addRecord(RecordType type, const QByteArray& record, int ttl = 0); Q_SIGNALS: void registered(); void registrationError(int code); void resolved(const QByteArray& domainName); void resolveError(int code); }; Q_DECLARE_OPERATORS_FOR_FLAGS(QxtDiscoverableService::ServiceFlags); #endif // QXTDISCOVERABLESERVICE_H libqxt-0.6.2/src/zeroconf/qxtdiscoverableservice_p.h000066400000000000000000000042401215241066400227070ustar00rootroot00000000000000#ifndef QXTDISCOVERABLESERVICE_P_H #define QXTDISCOVERABLESERVICE_P_H #include "qxtdiscoverableservice.h" #include class QSocketNotifier; class QxtDiscoverableServicePrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtDiscoverableService) QxtDiscoverableServicePrivate() { port = 0; iface = 0; notifier = 0; state = QxtDiscoverableService::Unknown; } QxtDiscoverableService::State state; DNSServiceRef service; QStringList serviceSubTypes; quint16 port; int iface; QString txtRecord; QSocketNotifier* notifier; static void DNSSD_API registerServiceCallback(DNSServiceRef service, DNSServiceFlags flags, DNSServiceErrorType errCode, const char* name, const char* regtype, const char* domain, void* context); #ifdef Q_OS_WIN static void DNSSD_API resolveServiceCallback(DNSServiceRef service, DNSServiceFlags flags, quint32 iface, DNSServiceErrorType errCode, const char* fullname, const char* host, quint16 port, quint16 txtLen, const char* txt, void* context); #else static void resolveServiceCallback(DNSServiceRef service, DNSServiceFlags flags, quint32 iface, DNSServiceErrorType errCode, const char* fullname, const char* host, quint16 port, quint16 txtLen, const unsigned char* txt, void* context); #endif public Q_SLOTS: void socketData(); }; template void qxt_zeroconf_parse_subtypes(T* t, const QByteArray& regtype) { QList subtypes = regtype.split(','); QList rt = subtypes[0].split('.'); int ct = subtypes.count(); t->serviceSubTypes.clear(); if(ct > 1) { for(int i = 1; i < ct; i++) { if(subtypes.at(i)[0] == '_') { t->serviceSubTypes.append(subtypes[i].mid(1)); } else { t->serviceSubTypes.append(subtypes[i]); } } } } #endif // QXTDISCOVERABLESERVICE_P_H libqxt-0.6.2/src/zeroconf/qxtdiscoverableservicename.cpp000066400000000000000000000105661215241066400235740ustar00rootroot00000000000000#include "qxtdiscoverableservicename.h" #include #include #include #include #ifdef USE_AVAHI #include #else #include #endif class QxtDiscoverableServiceNamePrivate : public QxtPrivate { public: QXT_DECLARE_PUBLIC(QxtDiscoverableServiceName) QString name; QString domain; QAbstractSocket::SocketType socketType; QString serviceType; QString host; //mDNS stuff static int id; static QMutex idMutex; static QHash > lookups; }; int QxtDiscoverableServiceNamePrivate::id = 0; QMutex QxtDiscoverableServiceNamePrivate::idMutex; QHash > QxtDiscoverableServiceNamePrivate::lookups; QxtDiscoverableServiceName::QxtDiscoverableServiceName() { QXT_INIT_PRIVATE(QxtDiscoverableServiceName); qxt_d().socketType = QAbstractSocket::UnknownSocketType; } QxtDiscoverableServiceName::QxtDiscoverableServiceName(const QByteArray& domainName) { QXT_INIT_PRIVATE(QxtDiscoverableServiceName); // TODO: parse domainName } QxtDiscoverableServiceName::QxtDiscoverableServiceName(const QString& name, const QString& serviceType, const QString& domain, QAbstractSocket::SocketType socketType) { QXT_INIT_PRIVATE(QxtDiscoverableServiceName); qxt_d().name = name; setServiceType(serviceType); qxt_d().domain = domain; if (socketType != QAbstractSocket::UnknownSocketType) qxt_d().socketType = socketType; } QString QxtDiscoverableServiceName::serviceName() const { return qxt_d().name; } void QxtDiscoverableServiceName::setServiceName(const QString& name) { qxt_d().name = name; } QAbstractSocket::SocketType QxtDiscoverableServiceName::socketType() const { return qxt_d().socketType; } void QxtDiscoverableServiceName::setSocketType(QAbstractSocket::SocketType type) { qxt_d().socketType = type; } QString QxtDiscoverableServiceName::serviceType() const { return qxt_d().serviceType; } void QxtDiscoverableServiceName::setServiceType(const QString& type) { QList subtypes = type.toUtf8().split(','); QList rt = subtypes[0].split('.'); setSocketType(QAbstractSocket::TcpSocket); if (rt.count() != 2) { qxt_d().serviceType = subtypes[0]; } else { if (rt.at(0)[0] == '_') { qxt_d().serviceType = rt[0].mid(1); } else { qxt_d().serviceType = rt[0]; } if (rt[1] == "_udp") { setSocketType(QAbstractSocket::UdpSocket); } else if (rt[1] != "_tcp") { setSocketType(QAbstractSocket::UnknownSocketType); } } } QString QxtDiscoverableServiceName::domain() const { return qxt_d().domain; } void QxtDiscoverableServiceName::setDomain(const QString& domain) { qxt_d().domain = domain; } QString QxtDiscoverableServiceName::host() const { return qxt_d().host; } void QxtDiscoverableServiceName::setHost(const QString& host) { qxt_d().host = host; } QByteArray QxtDiscoverableServiceName::fullServiceType() const { QString regtype = "_" + qxt_d().serviceType + "._"; if (qxt_d().socketType == QAbstractSocket::TcpSocket) regtype += "tcp"; else regtype += "udp"; return regtype.toUtf8(); } QByteArray QxtDiscoverableServiceName::escapedFullDomainName() const { char buffer[kDNSServiceMaxDomainName] = ""; int err = DNSServiceConstructFullName(buffer, qxt_d().name.isEmpty() ? 0 : qxt_d().name.toUtf8().constData(), fullServiceType().constData(), domain().toUtf8().constData()); if (err) return QByteArray(); // error return buffer; } int QxtDiscoverableServiceName::lookupHost(const QString name, QObject* receiver, const char* member) { QMutexLocker locker(&QxtDiscoverableServiceNamePrivate::idMutex); QxtDiscoverableServiceNamePrivate::id++; QxtMDNS* md = new QxtMDNS(QxtDiscoverableServiceNamePrivate::id); md->doLookup(name, receiver, member); QxtDiscoverableServiceNamePrivate::lookups[QxtDiscoverableServiceNamePrivate::id] = md; return QxtDiscoverableServiceNamePrivate::id; } void QxtDiscoverableServiceName::abortHostLookup(int id) { QMutexLocker locker(&QxtDiscoverableServiceNamePrivate::idMutex); if (QxtDiscoverableServiceNamePrivate::lookups.contains(id)) { if (QxtDiscoverableServiceNamePrivate::lookups[id].isNull()) QxtDiscoverableServiceNamePrivate::lookups.remove(id); else QxtDiscoverableServiceNamePrivate::lookups.take(id)->cancelLookup(); } } libqxt-0.6.2/src/zeroconf/qxtdiscoverableservicename.h000066400000000000000000000024371215241066400232370ustar00rootroot00000000000000#ifndef QXTDISCOVERABLESERVICENAME_H #define QXTDISCOVERABLESERVICENAME_H #include "qxtglobal.h" #include #include #include class QxtDiscoverableServiceNamePrivate; class QXT_ZEROCONF_EXPORT QxtDiscoverableServiceName { QXT_DECLARE_PRIVATE(QxtDiscoverableServiceName) public: QxtDiscoverableServiceName(); QxtDiscoverableServiceName(const QByteArray& domainName); QxtDiscoverableServiceName(const QString& name, const QString& serviceType, const QString& domain, QAbstractSocket::SocketType socketType = QAbstractSocket::UnknownSocketType); QString serviceName() const; void setServiceName(const QString& name); QAbstractSocket::SocketType socketType() const; void setSocketType(QAbstractSocket::SocketType type); QString serviceType() const; void setServiceType(const QString& type); QByteArray fullServiceType() const; QString domain() const; void setDomain(const QString& domain); QString host() const; void setHost(const QString& host); QByteArray escapedFullDomainName() const; //mDNS stuff static int lookupHost(const QString name, QObject* receiver, const char* member); static void abortHostLookup(int id); }; #endif // QXTDISCOVERABLESERVICENAME_H libqxt-0.6.2/src/zeroconf/qxtmdns_avahi.cpp000066400000000000000000000127521215241066400210200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtZeroconf module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #include "qxtmdns_avahi.h" #include "qxtmdns_avahi_p.h" #include #include #include #include #include #include QxtMDNS::QxtMDNS(int id, QObject* parent) : QObject(parent) { QXT_INIT_PRIVATE(QxtMDNS); qxt_d().info = id; qxt_d().client = NULL; qxt_d().recordbrowser = NULL; qxt_d().sent = false; } void QxtMDNS::doLookup(QString n, QObject * r, const char * m) { qxt_d().name = n; qxt_d().receiver = r; qxt_d().member = QxtMetaObject::methodName(m); int error; qxt_d().client = avahi_client_new( qxtAvahiPoll(), // use the qt event loop (AvahiClientFlags)0, QxtMDNSPrivate::avahiClientCallback, &(qxt_d()), &error ); } void QxtMDNSPrivate::avahiClientCallback(AvahiClient *s, AvahiClientState state, void *userdata) { QxtMDNSPrivate* self = static_cast(userdata); self->client = s; if (state == AVAHI_CLIENT_S_RUNNING) { self->recordbrowser = avahi_record_browser_new( s, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, self->name.toAscii().constData(), AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A, (AvahiLookupFlags)0, QxtMDNSPrivate::avahiRecordBrowserCallback, self); if (self->recordbrowser == NULL) { self->info.setError(QHostInfo::UnknownError); self->info.setErrorString(avahi_strerror(avahi_client_errno(self->client))); QMetaObject::invokeMethod(self->receiver, self->member, Q_ARG(QHostInfo, self->info)); self->sent = true; self->qxt_p().cancelLookup(); } } } void QxtMDNSPrivate::avahiRecordBrowserCallback(AvahiRecordBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, uint16_t clazz, uint16_t type, const void *rdata, size_t size, AvahiLookupResultFlags flags, void *userdata) { ///@TODO Support IPv6 Q_UNUSED(interface); Q_UNUSED(protocol); Q_UNUSED(name); Q_UNUSED(clazz); Q_UNUSED(type); Q_UNUSED(size); Q_UNUSED(flags); QxtMDNSPrivate* self = static_cast(userdata); self->recordbrowser = b; // qDebug() << "Return thing" << md->name << name << size; switch (event) { case AVAHI_BROWSER_NEW: { //Found an entry! uint32_t ip = qFromBigEndian(*static_cast(rdata)); if (self->sent) { QHostInfo info(self->info.lookupId()); info.setAddresses(QList() << QHostAddress(ip)); QMetaObject::invokeMethod(self->receiver, self->member, Q_ARG(QHostInfo, info)); } else { self->addresses << QHostAddress(ip); } break; } case AVAHI_BROWSER_REMOVE: { uint32_t ip = qFromBigEndian(*static_cast(rdata)); self->addresses.removeAll(QHostAddress(ip)); break; } case AVAHI_BROWSER_CACHE_EXHAUSTED: break; case AVAHI_BROWSER_ALL_FOR_NOW: if (self->addresses.count() == 0) { self->info.setError(QHostInfo::HostNotFound); self->info.setErrorString("The host was not found."); } else { self->info.setAddresses(self->addresses); self->addresses.clear(); } QMetaObject::invokeMethod(self->receiver, self->member, Q_ARG(QHostInfo, self->info)); self->sent = true; break; case AVAHI_BROWSER_FAILURE: if (self->sent) { QHostInfo info(self->info.lookupId()); info.setError(QHostInfo::UnknownError); info.setErrorString(avahi_strerror(avahi_client_errno(self->client))); info.setAddresses(self->addresses); QMetaObject::invokeMethod(self->receiver, self->member, Q_ARG(QHostInfo, info)); } else { self->info.setError(QHostInfo::UnknownError); self->info.setErrorString(avahi_strerror(avahi_client_errno(self->client))); self->info.setAddresses(self->addresses); self->addresses.clear(); QMetaObject::invokeMethod(self->receiver, self->member, Q_ARG(QHostInfo, self->info)); self->sent = true; } break; } } void QxtMDNS::cancelLookup() { if (qxt_d().recordbrowser != NULL) avahi_record_browser_free(qxt_d().recordbrowser); if (qxt_d().client != NULL) avahi_client_free(qxt_d().client); deleteLater(); } libqxt-0.6.2/src/zeroconf/qxtmdns_avahi.h000066400000000000000000000032651215241066400204640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtZeroconf module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTMDNS_H #define QXTMDNS_H #include "qxtglobal.h" #include #include class QxtMDNSPrivate; // This class just throws QHostInfo objects at the receiver... // The receiver slot should take 1 parameter, a QHostInfo... class QXT_ZEROCONF_EXPORT QxtMDNS : public QObject { QXT_DECLARE_PRIVATE(QxtMDNS); Q_OBJECT public: QxtMDNS(int id = -1, QObject* parent = 0); void doLookup(QString name, QObject * receiver, const char * member); void cancelLookup(); }; #endif //#ifndef QXTMDNS_H libqxt-0.6.2/src/zeroconf/qxtmdns_avahi_p.h000066400000000000000000000040151215241066400207750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) Qxt Foundation. Some rights reserved. ** ** This file is part of the QxtZeroconf module of the Qxt library. ** ** This library is free software; you can redistribute it and/or modify it ** under the terms of the Common Public License, version 1.0, as published ** by IBM, and/or under the terms of the GNU Lesser General Public License, ** version 2.1, as published by the Free Software Foundation. ** ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR ** FITNESS FOR A PARTICULAR PURPOSE. ** ** You should have received a copy of the CPL and the LGPL along with this ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files ** included with the source distribution for more information. ** If you did not receive a copy of the licenses, contact the Qxt Foundation. ** ** ** ****************************************************************************/ #ifndef QXTMDNS_P_H #define QXTMDNS_P_H #include "qxtmdns_avahi.h" #include #include #include #include #include class QxtMDNSPrivate : public QxtPrivate { public: QxtMDNSPrivate() { } static void avahiClientCallback(AvahiClient *s, AvahiClientState state, void *userdata); static void avahiRecordBrowserCallback(AvahiRecordBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, uint16_t clazz, uint16_t type, const void *rdata, size_t size, AvahiLookupResultFlags flags, void *userdata); QHostInfo info; QList addresses; QString name; QObject* receiver; QByteArray member; AvahiClient* client; AvahiRecordBrowser* recordbrowser; bool sent; int id; }; #endif //#ifndef QXTMDNS_H libqxt-0.6.2/src/zeroconf/qxtmdns_bonjour.cpp000066400000000000000000000034571215241066400214100ustar00rootroot00000000000000#include "qxtmdns_bonjour.h" #include #include #include QxtMDNS::QxtMDNS(int id, QObject * parent) : QObject(parent), info(id) { } void QxtMDNS::doLookup(QString n, QObject * r, const char * m) { name = n; receiver = r; member = QxtMetaObject::methodName(m); DNSServiceErrorType err = DNSServiceQueryRecord( &ref, 0, 0, name.toAscii().constData(), kDNSServiceType_SRV, kDNSServiceClass_IN, QxtMDNS::DNSServiceQueryRecordCallback, this ); if (err != kDNSServiceErr_NoError) { QHostInfo info(info.lookupId()); info.setErrorString("Failed to initialize the Bonjour request."); QMetaObject::invokeMethod(receiver, member, Q_ARG(QHostInfo, info)); } else { notifier = new QSocketNotifier(DNSServiceRefSockFD(ref), QSocketNotifier::Read, this); QObject::connect(notifier, SIGNAL(activated(int)), this, SLOT(socketData())); } } void QxtMDNS::DNSServiceQueryRecordCallback(DNSServiceRef DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context) { QxtMDNS* md = static_cast(context); QHostInfo info(md->info.lookupId()); uint32_t ip = qFromBigEndian(*static_cast(rdata)); info.setAddresses(QList() << QHostAddress(ip)); QMetaObject::invokeMethod(md->receiver, md->member, Q_ARG(QHostInfo, info)); } void QxtMDNS::socketData() { DNSServiceProcessResult(ref); } void QxtMDNS::cancelLookup() { } libqxt-0.6.2/src/zeroconf/qxtmdns_bonjour.h000066400000000000000000000022571215241066400210520ustar00rootroot00000000000000#ifndef QXTMDNS_H #define QXTMDNS_H #include #include #include #include ///@TODO Finish and test implementation of Bonjour mDNS, and remove the following warning. // Sadly I can't test this because this part of the avahi Bonjour compatibility layer is broken on Ubuntu Linux version 8.04... -chrisinajar #ifndef Q_CC_MSVC #warning The Bonjour implementation is in no way tested, and is not fully implemented either. Try again later. #endif class QxtMDNS : public QObject { Q_OBJECT public: QxtMDNS(int id = -1, QObject* parent = 0); void doLookup(QString name, QObject * receiver, const char * member); void cancelLookup(); static void DNSSD_API DNSServiceQueryRecordCallback(DNSServiceRef DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, void *context); QHostInfo info; QList addresses; QString name; QObject* receiver; const char* member; DNSServiceRef ref; QSocketNotifier* notifier; int id; public Q_SLOTS: void socketData(); }; #endif //#ifndef QXTMDNS_H libqxt-0.6.2/src/zeroconf/qxtservicebrowser.cpp000066400000000000000000000120661215241066400217510ustar00rootroot00000000000000#include "qxtservicebrowser.h" #include "qxtservicebrowser_p.h" #include "qxtdiscoverableservice_p.h" #include /*! \class QxtServiceBrowser \inmodule QxtZeroconf \brief The QxtServiceBrowser class locates Zeroconf-enabled services on the network QxtServiceBrowser is a tool for locating Zeroconf-enabled services on the local network. When starting to browse, all existing services reachable on the local network matching the specified search parameters will be announced with the serviceAdded() signal. Afterward, while browsing, new services apearing on the network will be announced with the same signal, and services that are closed will be announced with the serviceRemoved() signal. Services on the network are identified by a service type and may be further disambiguated by service subtypes. If any service subtypes are added to the QxtServiceBrowser, only services offering the specified subtypes will be found. Use the properties inherited from QxtDiscoverableServiceName to configure the search parameters. For more information about Zeroconf, see the documentation available on www.zeroconf.org. \sa QxtDiscoverableService \sa QxtDiscoverableServiceName */ /*! * Constructs a QxtServiceBrowser that will search for services with the specified type. * The service type may be a plain type name, which will default to searching for a UDP * service, or it may be provided in the standard format specified by the Zeroconf * specification. */ QxtServiceBrowser::QxtServiceBrowser(const QString& serviceType, QObject* parent) : QObject(parent), QxtDiscoverableServiceName(QString(), serviceType, QString()) { QXT_INIT_PRIVATE(QxtServiceBrowser); qxt_zeroconf_parse_subtypes(&qxt_d(), serviceType.toUtf8()); } /*! * Constructs a QxtServiceBrowser that will search for services with the specified type * and socket type. */ QxtServiceBrowser::QxtServiceBrowser(const QString& serviceType, QAbstractSocket::SocketType socketType, QObject* parent) : QObject(parent), QxtDiscoverableServiceName(QString(), serviceType, QString(), socketType) { QXT_INIT_PRIVATE(QxtServiceBrowser); qxt_zeroconf_parse_subtypes(&qxt_d(), serviceType.toUtf8()); } QxtServiceBrowser::~QxtServiceBrowser() { if(isBrowsing()) stopBrowsing(); } bool QxtServiceBrowser::isBrowsing() const { return bool(qxt_d().notifier); } void QxtServiceBrowser::browse(/* int iface */) { QStringList subtypes = qxt_d().serviceSubTypes; subtypes.prepend(fullServiceType()); DNSServiceErrorType err; err = DNSServiceBrowse(&(qxt_d().service), 0, qxt_d().iface, subtypes.join(",_").toUtf8().constData(), domain().isEmpty() ? 0 : domain().toUtf8().constData(), QxtServiceBrowserPrivate::browseServiceCallback, &qxt_d()); if(err) { emit browsingFailed(err); } else { qxt_d().notifier = new QSocketNotifier(DNSServiceRefSockFD(qxt_d().service), QSocketNotifier::Read, this); QObject::connect(qxt_d().notifier, SIGNAL(activated(int)), &qxt_d(), SLOT(socketData())); } } void QxtServiceBrowser::stopBrowsing() { if(qxt_d().notifier) { DNSServiceRefDeallocate(qxt_d().service); qxt_d().notifier->deleteLater(); } qxt_d().notifier = 0; } QStringList QxtServiceBrowser::serviceSubTypes() const { return qxt_d().serviceSubTypes; } void QxtServiceBrowser::setServiceSubTypes(const QStringList& subtypes) { if(isBrowsing()) qWarning() << "QxtServiceBrowser: Setting service subtypes while browsing has no effect"; qxt_d().serviceSubTypes = subtypes; } void QxtServiceBrowser::addServiceSubType(const QString& subtype) { if(isBrowsing()) qWarning() << "QxtServiceBrowser: Setting service subtypes while browsing has no effect"; qxt_d().serviceSubTypes << subtype; } void QxtServiceBrowser::removeServiceSubType(const QString& subtype) { if(isBrowsing()) qWarning() << "QxtServiceBrowser: Setting service subtypes while browsing has no effect"; qxt_d().serviceSubTypes.removeAll(subtype); } bool QxtServiceBrowser::hasServiceSubType(const QString& subtype) { return qxt_d().serviceSubTypes.contains(subtype); } void QxtServiceBrowserPrivate::socketData() { DNSServiceProcessResult(service); } void QxtServiceBrowserPrivate::browseServiceCallback(DNSServiceRef service, DNSServiceFlags flags, quint32 iface, DNSServiceErrorType errCode, const char* serviceName, const char* regtype, const char* replyDomain, void* context) { Q_UNUSED(service); Q_UNUSED(iface); Q_UNUSED(regtype); QxtServiceBrowserPrivate* self = reinterpret_cast(context); if(errCode == kDNSServiceErr_NoError) { if(flags & kDNSServiceFlagsAdd) emit self->qxt_p().serviceAdded(serviceName, replyDomain); else emit self->qxt_p().serviceRemoved(serviceName, replyDomain); } else { emit self->qxt_p().stopBrowsing(); emit self->qxt_p().browsingFailed(errCode); } } libqxt-0.6.2/src/zeroconf/qxtservicebrowser.h000066400000000000000000000022321215241066400214100ustar00rootroot00000000000000#ifndef QXTSERVICEBROWSER_H #define QXTSERVICEBROWSER_H #include "qxtglobal.h" #include #include #include "qxtdiscoverableservicename.h" class QxtServiceBrowserPrivate; class QXT_ZEROCONF_EXPORT QxtServiceBrowser : public QObject, public QxtDiscoverableServiceName { Q_OBJECT QXT_DECLARE_PRIVATE(QxtServiceBrowser) public: QxtServiceBrowser(const QString& serviceType, QObject* parent = 0); QxtServiceBrowser(const QString& serviceType, QAbstractSocket::SocketType socketType, QObject* parent = 0); virtual ~QxtServiceBrowser(); bool isBrowsing() const; public slots: void browse(/* int iface */); void stopBrowsing(); public: QStringList serviceSubTypes() const; void setServiceSubTypes(const QStringList& subtypes); void addServiceSubType(const QString& subtype); void removeServiceSubType(const QString& subtype); bool hasServiceSubType(const QString& subtype); Q_SIGNALS: void browsingFailed(int errorCode); void serviceAdded(const QString& serviceName, const QString& domain); void serviceRemoved(const QString& serviceName, const QString& domain); }; #endif // QXTSERVICEBROWSER_H libqxt-0.6.2/src/zeroconf/qxtservicebrowser_p.h000066400000000000000000000016461215241066400217370ustar00rootroot00000000000000#ifndef QXTSERVICEBROWSER_P_H #define QXTSERVICEBROWSER_P_H #include "qxtservicebrowser.h" #include #include class QSocketNotifier; class QxtServiceBrowserPrivate : public QObject, public QxtPrivate { Q_OBJECT public: QXT_DECLARE_PUBLIC(QxtServiceBrowser) QxtServiceBrowserPrivate() { notifier = 0; iface = 0; } DNSServiceRef service; QString domain; QAbstractSocket::SocketType socketType; QString serviceType; QStringList serviceSubTypes; int iface; QSocketNotifier* notifier; static void DNSSD_API browseServiceCallback(DNSServiceRef service, DNSServiceFlags flags, quint32 iface, DNSServiceErrorType errCode, const char* serviceName, const char* regtype, const char* replyDomain, void* context); public Q_SLOTS: void socketData(); }; #endif // QXTSERVICEBROWSER_P_H libqxt-0.6.2/src/zeroconf/qxtzeroconf.h000066400000000000000000000003031215241066400201660ustar00rootroot00000000000000#ifndef QXTSERVICEBROWSER_H #define QXTSERVICEBROWSER_H #include "qxtdiscoverableservice.h" #include "qxtdiscoverableservicename.h" #include "qxtservicebrowser.h" #endif // QXTSERVICEBROWSER_H libqxt-0.6.2/src/zeroconf/zeroconf.pri000066400000000000000000000013051215241066400177770ustar00rootroot00000000000000INCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += qxtdiscoverableservice.h HEADERS += qxtdiscoverableservice_p.h HEADERS += qxtservicebrowser.h HEADERS += qxtservicebrowser_p.h HEADERS += qxtdiscoverableservicename.h SOURCES += qxtdiscoverableservice.cpp SOURCES += qxtservicebrowser.cpp SOURCES += qxtdiscoverableservicename.cpp !contains(CONFIG,NO_AVAHI): unix : !macx { DEFINES += USE_AVAHI SOURCES += qxtmdns_avahi.cpp SOURCES += qxtavahipoll.cpp HEADERS += qxtmdns_avahi.h HEADERS += qxtmdns_avahi_p.h HEADERS += qxtavahipoll.h HEADERS += qxtavahipoll_p.h } else { SOURCES += qxtmdns_bonjour.cpp HEADERS += qxtmdns_bonjour.h } libqxt-0.6.2/src/zeroconf/zeroconf.pro000066400000000000000000000007051215241066400200100ustar00rootroot00000000000000CLEAN_TARGET = QxtZeroconf DEFINES += BUILD_QXT_ZEROCONF QT = core network QXT = core network CONVENIENCE += $$CLEAN_TARGET include(zeroconf.pri) include(../qxtbase.pri) unix:!macx:LIBS += -ldns_sd !contains(CONFIG,NO_AVAHI): unix:!macx:LIBS += -lavahi-client -lavahi-common win32:LIBS += -L"c:\\PROGRA~1\\BONJOU~1\\lib\\win32" -ldnssd win32:INCLUDEPATH += "c:\\program files\\bonjour sdk\\include" libqxt-0.6.2/tests/000077500000000000000000000000001215241066400141655ustar00rootroot00000000000000libqxt-0.6.2/tests/other/000077500000000000000000000000001215241066400153065ustar00rootroot00000000000000libqxt-0.6.2/tests/other/QxtFileLock/000077500000000000000000000000001215241066400174735ustar00rootroot00000000000000libqxt-0.6.2/tests/other/QxtFileLock/QxtFileLock.pro000066400000000000000000000001301215241066400223740ustar00rootroot00000000000000SUBDIRS += src TEMPLATE = subdirs CONFIG += warn_on \ qt \ thread libqxt-0.6.2/tests/other/QxtFileLock/src/000077500000000000000000000000001215241066400202625ustar00rootroot00000000000000libqxt-0.6.2/tests/other/QxtFileLock/src/HelperClass.cpp000066400000000000000000000004701215241066400231740ustar00rootroot00000000000000#include "HelperClass.h" #include "locktestclient.h" HelperClass::HelperClass(QObject *parent) : QThread(parent) { } HelperClass::~HelperClass() { } void HelperClass::run() { QObject threadParent; LockTestClient *client = new LockTestClient(&threadParent); client->startTests(); exec(); } libqxt-0.6.2/tests/other/QxtFileLock/src/HelperClass.h000066400000000000000000000004041215241066400226360ustar00rootroot00000000000000#ifndef HELPERCLASS_H #define HELPERCLASS_H #include /** @author Benjamin Zeller */ class HelperClass : public QThread { Q_OBJECT public: HelperClass(QObject *parent = 0); ~HelperClass(); void run(); }; #endif libqxt-0.6.2/tests/other/QxtFileLock/src/locktestclient.cpp000066400000000000000000000064431215241066400240240ustar00rootroot00000000000000#include "locktestclient.h" #include #include #include #include #include LockTestClient::LockTestClient(QObject *parent) : QObject(parent) { } LockTestClient::~LockTestClient() { } void LockTestClient::startTests() { QTcpSocket socket; socket.connectToHost ( "localhost", 55555); char control; #define GetNextCommand() if(socket.waitForReadyRead (-1) )\ {\ if(socket.bytesAvailable() > 1)\ qDebug()<<"Something is wrong here";\ socket.getChar(&control);\ if(control == 'a')\ {\ socket.disconnectFromHost();\ return;\ }\ if(control != 'n')\ { \ qDebug()<<"Wrong control command";\ }\ } if(socket.waitForConnected (-1)) { QFile file("lock.file"); if(!file.open(QIODevice::ReadWrite)) { qDebug()<<"Could not open lockfile"; return; } if(1) { GetNextCommand(); //Trying to readlock the same region QxtFileLock lock(&file,0x10,20,QxtFileLock::ReadLock); if(lock.lock()) socket.putChar('s'); //s for success f for fail else socket.putChar('f'); socket.waitForBytesWritten(-1); } if(1) { GetNextCommand(); //Trying to lock the same region with different locks QxtFileLock lock(&file,0x10,20,QxtFileLock::WriteLock); if(!lock.lock()) socket.putChar('s'); //s for success f for fail else socket.putChar('f'); socket.waitForBytesWritten(-1); } if(1) { GetNextCommand(); //Trying to writelock the same region QxtFileLock lock(&file,0x10,20,QxtFileLock::WriteLock); if(!lock.lock()) socket.putChar('s'); //s for success f for fail else socket.putChar('f'); socket.waitForBytesWritten(-1); } if(1) { GetNextCommand(); //Trying to writelock different regions QxtFileLock lock(&file,0x10+21,20,QxtFileLock::WriteLock); if(lock.lock()) socket.putChar('s'); //s for success f for fail else socket.putChar('f'); socket.waitForBytesWritten(-1); } } } libqxt-0.6.2/tests/other/QxtFileLock/src/locktestclient.h000066400000000000000000000006131215241066400234620ustar00rootroot00000000000000#ifndef LOCKTESTCLIENT_H #define LOCKTESTCLIENT_H #include /** @author Benjamin Zeller */ class QTcpSocket; class LockTestClient : public QObject { Q_OBJECT public: LockTestClient(QObject *parent = 0); ~LockTestClient(); public slots: void startTests(); private: QTcpSocket *socket; }; #endif libqxt-0.6.2/tests/other/QxtFileLock/src/main.cpp000066400000000000000000000120461215241066400217150ustar00rootroot00000000000000 #include #include #include #include #ifdef Q_OS_WIN32 #include #endif #include "threadtestcontroller.h" #include "HelperClass.h" /* Needed Test: 1. one thread test - open the same file twice - lock fileregion with readlock (handle 1) - try to lock the same region with a read lock -> should work - try to lock the same region with a write lock -> should fail - remove all locks - create a writelock on handle 1 - create a writelock on handle 2 ->>fail - try to lock totally different regions --> should work 2. multiple threadstest: - spawn two threads - open the same file twice - let thread 1 lock (READLOCK) a region of a file - let thread 2 do the same lock ---> should work - let thread 1 upgrade its lock to a WRITELOCK -->should fail (because thread 2 holds the readlock) - remove all locks - try to lock totally different regions of the file -> should work */ int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); if(1) { QFile file1("lock.file"); QFile file2("lock.file"); if(file1.open(QIODevice::ReadWrite) && file2.open(QIODevice::ReadWrite)) { if(1) { qDebug()<<"----Starting first test----"; qDebug()<<"Trying to create some locks without collison"; QxtFileLock lock1(&file1,0x10,20,QxtFileLock::WriteLock); if(lock1.lock()) qDebug()<<"---- Write Lock Test passed----"; else qDebug()<<"---- Write Lock Test failed----"; lock1.unlock(); QxtFileLock lock2(&file2,0x10,20,QxtFileLock::ReadLock); if(lock2.lock()) qDebug()<<"---- Read Lock Test passed----"; else qDebug()<<"---- Read Lock Test failed----"; lock2.unlock(); } if(1) { qDebug()<<"----Starting next test-----"; qDebug()<<"Trying to readlock the same region with DIFFERENT handles "; QxtFileLock *lock1 = new QxtFileLock(&file1,0x10,20,QxtFileLock::ReadLock); QxtFileLock *lock2 = new QxtFileLock(&file2,0x10,20,QxtFileLock::ReadLock); if(lock1->lock() && lock2->lock()) qDebug()<<"----Test passed----"; else qDebug()<<"----Test failed----"; delete lock1; delete lock2; } if(1) { qDebug()<<"----Starting next test-----"; qDebug()<<"Trying to lock the same region with DIFFERENT handles and different locks"; QxtFileLock *lock1 = new QxtFileLock(&file1,0x10,20,QxtFileLock::ReadLock); QxtFileLock *lock2 = new QxtFileLock(&file2,0x10,20,QxtFileLock::WriteLock); if(lock1->lock() && !lock2->lock()) qDebug()<<"----Test passed----"; else qDebug()<<"----Test failed----"; delete lock1; delete lock2; } if(1) { qDebug()<<"----Starting next test-----"; qDebug()<<"Trying to writelock the same region with DIFFERENT handles"; QxtFileLock *lock1 = new QxtFileLock(&file1,0x10,20,QxtFileLock::WriteLock); QxtFileLock *lock2 = new QxtFileLock(&file2,0x10,20,QxtFileLock::WriteLock); if(lock1->lock() && !lock2->lock()) qDebug()<<"----Test passed----"; else qDebug()<<"----Test failed----"; delete lock1; delete lock2; } if(1) { qDebug()<<"----Starting next test-----"; qDebug()<<"Trying to writelock the different regions with DIFFERENT handles"; QxtFileLock *lock1 = new QxtFileLock(&file1,0x10,20,QxtFileLock::WriteLock); QxtFileLock *lock2 = new QxtFileLock(&file2,0x10+21,20,QxtFileLock::WriteLock); if(lock1->lock() && lock2->lock()) qDebug()<<"----Test passed----"; else qDebug()<<"----Test failed----"; delete lock1; delete lock2; } } } qDebug()<<"All base tests are finished, now starting the threaded tests"; ThreadTestController controller; if(controller.startTests()) { HelperClass *testClient = new HelperClass(); testClient->start(); return app.exec(); } return 0; } libqxt-0.6.2/tests/other/QxtFileLock/src/src.pro000066400000000000000000000004601215241066400215730ustar00rootroot00000000000000SOURCES += main.cpp \ threadtestcontroller.cpp \ locktestclient.cpp \ HelperClass.cpp TEMPLATE = app TARGET = ../bin/qxtfilelock QT -= gui QT += core \ network CONFIG += console QXT += core include($$QXT_SOURCE_TREE/src/qxtlibs.pri) HEADERS += threadtestcontroller.h \ locktestclient.h \ HelperClass.h libqxt-0.6.2/tests/other/QxtFileLock/src/threadtestcontroller.cpp000066400000000000000000000060701215241066400252440ustar00rootroot00000000000000#include "threadtestcontroller.h" #include #include #include #include #include #include ThreadTestController::ThreadTestController(QObject *parent) : QObject(parent) { server = new QTcpServer(this); connect(server,SIGNAL(newConnection ()),this,SLOT(doTests())); } ThreadTestController::~ThreadTestController() { } void ThreadTestController::doTests() { QTcpSocket *socket = server->nextPendingConnection(); QFile file("lock.file"); #define DoNextTest() socket->putChar('n');\ if(socket->waitForReadyRead(-1))\ {\ socket->getChar(&testResult);\ if(testResult == 'f')\ qDebug()<<"----Test failed----";\ else if(testResult == 's')\ qDebug()<<"----Test passed----";\ else\ qDebug()<<"----Wrong result value----";\ }\ else qDebug()<<"No ready read"; if(socket && file.open(QIODevice::ReadWrite)) { char testResult = 'f'; if(1) { qDebug()<<"----Starting next test-----"; qDebug()<<"Trying to readlock the same region "; QxtFileLock lock(&file,0x10,20,QxtFileLock::ReadLock); if(lock.lock()) { DoNextTest(); } } if(1) { qDebug()<<"----Starting next test-----"; qDebug()<<"Trying to lock the same region with different locks"; QxtFileLock lock(&file,0x10,20,QxtFileLock::ReadLock); if(lock.lock()) { DoNextTest(); } } if(1) { qDebug()<<"----Starting next test-----"; qDebug()<<"Trying to writelock the same region twice"; QxtFileLock lock(&file,0x10,20,QxtFileLock::WriteLock); if(lock.lock()) { DoNextTest(); } } if(1) { qDebug()<<"----Starting next test-----"; qDebug()<<"Trying to writelock different regions"; QxtFileLock lock(&file,0x10,20,QxtFileLock::WriteLock); if(lock.lock()) { DoNextTest(); } } } QCoreApplication::instance()->exit(); } bool ThreadTestController::startTests() { if (!server->listen(QHostAddress::Any,55555)) { qDebug()<<"Could not start listening Server "<serverError(); return false; } return true; } libqxt-0.6.2/tests/other/QxtFileLock/src/threadtestcontroller.h000066400000000000000000000013071215241066400247070ustar00rootroot00000000000000#ifndef THREADTESTCONTROLLER_H #define THREADTESTCONTROLLER_H #include /** @author Benjamin Zeller */ /** * the test controller controls the client over a QTcpSocker port 55555 * there are some control commands * n : start next test * a : abort testing * from the client there are two possible answers * s: the test succeeded * f: the test failed */ class QTcpServer; class ThreadTestController : public QObject { Q_OBJECT public: ThreadTestController(QObject *parent = 0); ~ThreadTestController(); bool startTests(); public slots: void doTests(); private: QTcpServer *server; }; #endif libqxt-0.6.2/tests/other/QxtScheduleView/000077500000000000000000000000001215241066400203725ustar00rootroot00000000000000libqxt-0.6.2/tests/other/QxtScheduleView/QxtScheduleView.pro000066400000000000000000000004221215241066400241760ustar00rootroot00000000000000TEMPLATE = app TARGET = QxtScheduleViewTest QT += core gui QXT += core gui include($$QXT_SOURCE_TREE/src/qxtlibs.pri) HEADERS += qxtscheduleviewtest.h SOURCES += main.cpp \ qxtscheduleviewtest.cpp FORMS += qxtscheduleviewtest.ui RESOURCES += libqxt-0.6.2/tests/other/QxtScheduleView/main.cpp000066400000000000000000000003771215241066400220310ustar00rootroot00000000000000#include "qxtscheduleviewtest.h" #include int main(int argc, char *argv[]) { QApplication a(argc, argv); QxtScheduleViewTest w; w.show(); a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit())); return a.exec(); } libqxt-0.6.2/tests/other/QxtScheduleView/qxtscheduleviewtest.cpp000066400000000000000000000002771215241066400252300ustar00rootroot00000000000000#include "qxtscheduleviewtest.h" QxtScheduleViewTest::QxtScheduleViewTest(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); } QxtScheduleViewTest::~QxtScheduleViewTest() { } libqxt-0.6.2/tests/other/QxtScheduleView/qxtscheduleviewtest.h000066400000000000000000000005431215241066400246710ustar00rootroot00000000000000#ifndef QXTSCHEDULEVIEWTEST_H #define QXTSCHEDULEVIEWTEST_H #include #include "ui_qxtscheduleviewtest.h" class QxtScheduleViewTest : public QMainWindow { Q_OBJECT public: QxtScheduleViewTest(QWidget *parent = 0); ~QxtScheduleViewTest(); private: Ui::QxtScheduleViewTestClass ui; }; #endif // QXTSCHEDULEVIEWTEST_H libqxt-0.6.2/tests/other/QxtScheduleView/qxtscheduleviewtest.ui000066400000000000000000000012611215241066400250550ustar00rootroot00000000000000 QxtScheduleViewTestClass 0 0 800 600 MainWindow 0 0 800 21 libqxt-0.6.2/tests/other/app/000077500000000000000000000000001215241066400160665ustar00rootroot00000000000000libqxt-0.6.2/tests/other/app/app.pro000066400000000000000000000004031215241066400173650ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . CONFIG += console QXT += core gui include($$QXT_SOURCE_TREE/src/qxtlibs.pri) FORMS += mainwindow.ui tab.ui HEADERS += mainwindow.h tab.h SOURCES += main.cpp mainwindow.cpp tab.cpp RESOURCES += app.qrc libqxt-0.6.2/tests/other/app/app.qrc000066400000000000000000000003271215241066400173570ustar00rootroot00000000000000 images/calendar.png images/tree.png images/list.png libqxt-0.6.2/tests/other/app/images/000077500000000000000000000000001215241066400173335ustar00rootroot00000000000000libqxt-0.6.2/tests/other/app/images/calendar.png000066400000000000000000000105131215241066400216120ustar00rootroot00000000000000PNG  IHDR>a-tEXtCreation Timema 28 touko 2007 21:23:51 +0200C51tIME pHYsiTSgAMA aIDATx] xMGH$DRbXFPATHQRRUIc_j+-ԾKCE/Bh""&9:s̽";̝wfΙ|gy}@QC1:9=H`mm}'33ZKC8::=xATZ]fE,XZo׷A]_F5nj1 $PSܤѽ̟?P@BCCCCì ʗŋhQ"o:v>iX<{.N𛯹uk~vB#M(;bbxv]m(i_YвU+;u*V(O߾lG`_:w*Wz?LM9S&E4^-geqq~_]-Dl\EZX@ 6mVr2ܿwocgGAFCHٓ q ]HJ;=c3do ?OO7FnǑ{l=t8'm};qC <2,%c4o ֥Kävmj}-4aY4{ؾ #}b%w.~bN2s]W&Ϥ |x1;|xǎpQ\Y*;:B4.|O <'wA0i@^}qv(̓ C| 6y┿n0#!sݢ{&N%+"==쬬Lp +´aaM܄0ܿ+ ӵ/ 48oooX7pd4u<2vOn{?Yqԯ:uD;k1 \6--ߥhc,jԩȹ[0} N=ۋ1[CF-ww3y2  "aA Bo(CB=|QA2e#!͝4uYju .NI5 )?jB0s0s0s0s0s0smJ:QS$fCAcpxNf^𮃭ɛ"c\:V9æ˹&G۱nf<[ZE;FE{B}aˉǠߧ P{H S6l.D9 i $;dO2U1OA:e*83] VBÇ8i'':aܾs߲-=vpx~ n(GDۡvF4o+{k18M}i rW[R5(^63gX+>.|!dKߗc`O\|##͋а5Pϣ!Tpqz0"{=VYו ӷg/nӎ\}r4CvvA?"q'kw-@L rg5e8G"=< 9%1_"o%·-ȃcٴ ;l!ikpo`kkfl `čjxD%(G8vNYZ{e/D44lPa:ݙǠTBKԯu_ "]aBwxhӆWv](LǏ&+k445j__E&4n>i(򭶴䓸o#j˗j,,,!Mr/zAnmRVVD8߀ϠQ߻w෈lia'E,Зw $!?ti䕺]V* ժ@kB0`-BvהȢ̹.,֭ƖJ\|vӔkg3ÊYߓs1} e9',eET+g1G#\ۃGf#G`ҥs\(!dbr2|Ϥ ;%c m˭ߴ~ui)$٤$p pƧ^^{cǓI'xĴܲ<%m[\<a#4!9kVQ'ǭ$G !p[F5Ŋ%ᚲSꔦ?'O6$aG%- ! ( IB&afafafafafafWbBjUrԨaE$≞ *1Sc236֖$jJ| X6ث$K#W=zIn ʢlבEѳP("GϪT#$&LkG {kԀWpza]4۬iZ_i+zh(Z#°9_jA;=KmhI~9}߯icʕS$ f$≞G5.'79%Lާi@O:Q}m/t$n~瑸)ɿn[f͠}dM~%Iؙ:T6$#8q"0{9Jؓ=K_6mTUݸq|Z[BIlU~`(qCQ %nYY06{汣 גĭ[`_QID2yy}`-U@gorQ817O"P)JO,m? t8M9AT<<.K%wTD3qQ&{4VJhX%nr.( 't+$R:h /E?2}Yo,m>J9eoW TZ(tK7~6L\a}ylmPFP*qӗsm+aCr~y6Pg8z5F5k{z_J(Y1Y|TРJ'i5,4R &9^m1qQҵ4dČ&Uw,qȹ_ғo'CK7؆$0cf \>`#E (Y(_"P,%%vm >||,"6vVFwv660{w/6$ahxtfA}i ! g $Lx! P030303030303tE]S건*FaL|%ZϚgI I*i3ԇ!I-O2H`'%!!D*|1ZEhY4R.YB&TEFœ x8"bc6ǏhYe4+%)$MIZ4/dJmz-]J&~\.$\_1L(̳tSgE+EVEIۘo!lH|*iY%mjѼA^NIan'Ns',9d'_䍖'!$-#KRH:<6m>F*㕴G2&vE4X1$pREhY䍬 !i|Jux$m|^IR4/dm$ 9zt;r!YhDakr6"VVV}NLʽQJ5tɹ'nE§pM)@f_.Ή αᇏf2]K8Tz22{ZEhY4>kBH%)$MI-O2H6j8??*UqB$,B&P`WзioMFٲe$L@o&0u}Mɚ@pij#@r$'yG MR5j?E&kY3tD sLRCn\˚D ܤ 'gQɚ@pi4壭PA@'NC$zh?E&kY3thoשå˓ٴQr^RѴN!zb'%(dM piJyn αJ||5\^zѴ?"eQw1xV 2K 9JAi| YA.|W-f,0Y` FdRp-0xdŌ4~I Jd,@B2]rcB[[{浨@D `IENDB`libqxt-0.6.2/tests/other/app/images/list.png000066400000000000000000000011601215241066400210120ustar00rootroot00000000000000PNG  IHDR>a-tEXtCreation Timema 28 touko 2007 21:19:29 +0200ltIME pHYsiTSgAMA aIDATx1nQFQLT;$7I'xszߝǬ|q۶n,}{'8 Nq@trqգL3h۶_k8Y'8 Nqfg2d2'8ę ȐT@⬀ ` `* Nq3<3!3'8Y T@g.xf Cf S Nq@ L%8 Nqfg2d2'8ę ȐT@g.xf Cf S Nq@ L%8 Nqfg2d2'8ę ȐT@'8 Nq{8>\.gYiYm7@IENDB`libqxt-0.6.2/tests/other/app/images/tree.png000066400000000000000000000017621215241066400210060ustar00rootroot00000000000000PNG  IHDR>a-tEXtCreation Timema 28 touko 2007 21:19:29 +0200ltIME4-^ pHYsiTSgAMA aHIDATxM@af1d7;/eLvl2D@hCUr*.D7[V_|qMeѶ=߯ڿ"@r*X.OnW=HM%v1 tb HNxi?l jR?)`|!12=$2㔀zT]Lə >SD1(4Jp7|O01>,=. _;keҶmu]#|.1[cgg:S# M>S`>S>S+9K·RMGg%$gb>SSrBYYNKi̕Ϲ^4T׬ݍi\YFBY,B\˸\H.tmࣶF[hmaR"2fw0D ˹kKpW.r!@X.dh˅ ʥvd`)7>Rh˥44hcS؁bƔ(GS %Z[?"(r1"T@1cS@r4ɩ7TN]*#vznsTFnfM`rLə maf@[X3=mafFmPPuh 0.` HUh \.c/k]&]0W`<3M` . $G#@r 9HN nC-Y_p?Zdž7onIENDB`libqxt-0.6.2/tests/other/app/main.cpp000066400000000000000000000002431215241066400175150ustar00rootroot00000000000000#include #include "mainwindow.h" int main(int argc, char* argv[]) { QxtApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } libqxt-0.6.2/tests/other/app/mainwindow.cpp000066400000000000000000000103661215241066400207540ustar00rootroot00000000000000#include "mainwindow.h" #include "tab.h" #include #include #include #include #ifndef Q_WS_MAC #include #endif #include #include #include #include #include #include #include #include #include #include #include MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags) : QMainWindow(parent, flags) { ui.setupUi(this); createProgressBar(); ui.tabWidget->setTabContextMenuPolicy(Qt::ActionsContextMenu); connect(ui.actionQuit, SIGNAL(triggered()), this, SLOT(close())); connect(ui.actionAddTab, SIGNAL(triggered()), this, SLOT(addTab())); connect(ui.actionAboutQt, SIGNAL(triggered()), qApp, SLOT(aboutQt())); connect(ui.actionAboutQxtGui, SIGNAL(triggered()), this, SLOT(aboutQxtGui())); connect(ui.actionSwitchLayoutDirection, SIGNAL(triggered()), this, SLOT(switchLayoutDirection())); connect(ui.actionConfigure, SIGNAL(triggered()), this, SLOT(configure())); QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(this); connect(shortcut, SIGNAL(activated()), this, SLOT(toggleVisibility())); QKeySequence key("Ctrl+Shift+Alt+S"); if (shortcut->setShortcut(key)) ui.labelVisibility->setText(ui.labelVisibility->text().arg(key.toString(QKeySequence::NativeText))); else ui.labelVisibility->hide(); #ifndef Q_WS_MAC QTimer* timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(updateIdleTime())); timer->start(150); updateIdleTime(); #endif } MainWindow::~MainWindow() { } void MainWindow::closeEvent(QCloseEvent* event) { static const QString title("QxtConfirmationMessage"); static const QString text(tr("Are you sure you want to quit?")); if (QxtConfirmationMessage::confirm(this, title, text) == QMessageBox::No) event->ignore(); } void MainWindow::aboutQxtGui() { QMessageBox::information(this, tr("About QxtGui"), tr("

About QxtGui

" "

QxtGui is part of Qxt, the Qxt library <" "http://libqxt.sf.net>.

")); } void MainWindow::addTab() { Tab* tab = new Tab(ui.tabWidget); ui.tabWidget->addTab(tab, tr("Tab %1").arg(ui.tabWidget->count() + 1)); QAction* act = ui.tabWidget->addTabAction(ui.tabWidget->indexOf(tab), tr("Close"), tab, SLOT(close()), tr("Ctrl+W")); tab->addAction(act); ui.tabWidget->setCurrentWidget(tab); connect(tab, SIGNAL(somethingHappened(const QString&)), statusBar(), SLOT(showMessage(const QString&))); } void MainWindow::switchLayoutDirection() { qApp->setLayoutDirection(layoutDirection() == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight); } void MainWindow::toggleVisibility() { setVisible(!isVisible()); } void MainWindow::updateIdleTime() { #ifndef Q_WS_MAC setWindowTitle(tr("QxtDemo - System Idle: %1ms").arg(QxtWindowSystem::idleTime())); #endif } void MainWindow::createProgressBar() { QxtProgressLabel* label = new QxtProgressLabel(statusBar()); QProgressBar* bar = new QProgressBar(statusBar()); bar->setMaximumWidth(label->sizeHint().width() * 2); bar->setRange(0, 120); QTimeLine* timeLine = new QTimeLine(120000, this); timeLine->setFrameRange(0, 120); connect(timeLine, SIGNAL(frameChanged(int)), bar, SLOT(setValue(int))); connect(timeLine, SIGNAL(finished()), label, SLOT(restart())); connect(bar, SIGNAL(valueChanged(int)), label, SLOT(setValue(int))); timeLine->start(); statusBar()->addPermanentWidget(new QLabel(tr("Dummy Progress:"), this)); statusBar()->addPermanentWidget(bar); statusBar()->addPermanentWidget(label); } void MainWindow::configure() { QxtConfigDialog dialog(this); dialog.setWindowTitle(tr("QxtConfigDialog")); QTreeView* page2 = new QTreeView(&dialog); page2->setModel(new QDirModel(page2)); QListWidget* page3 = new QListWidget(&dialog); for (int i = 0; i < 100; ++i) page3->addItem(QString::number(i)); dialog.configWidget()->addPage(page2, QIcon(":tree.png"), "A directory tree"); dialog.configWidget()->addPage(page3, QIcon(":list.png"), "Some kind of list"); QCalendarWidget* page1 = new QCalendarWidget(&dialog); dialog.configWidget()->addPage(page1, QIcon(":calendar.png"), "Calendar"); dialog.exec(); } libqxt-0.6.2/tests/other/app/mainwindow.h000066400000000000000000000007631215241066400204210ustar00rootroot00000000000000#ifndef MAINWINDOW_H #define MAINWINDOW_H #include "ui_mainwindow.h" class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget* parent = 0, Qt::WindowFlags flags = 0); ~MainWindow(); protected: void closeEvent(QCloseEvent* event); private slots: void aboutQxtGui(); void addTab(); void switchLayoutDirection(); void toggleVisibility(); void configure(); void updateIdleTime(); private: void createProgressBar(); Ui::MainWindow ui; }; #endif // MAINWINDOW_H libqxt-0.6.2/tests/other/app/mainwindow.ui000066400000000000000000000115301215241066400206010ustar00rootroot00000000000000 MainWindow 0 0 629 438 MainWindow 0 6 QxtTabWidget QxtTabWidget 0 Tab 1 9 6 Qt::Vertical 20 40 Welcome to QxtGui test application. Start with adding a tab from View->Add Tab. Qt::ElideRight The visibility of the application may be toggled with %1. Qt::ElideRight Qt::Vertical 20 40 0 0 629 29 &File &Help &View &Quit Ctrl+Q About QxtGui About Qt &Add Tab Ctrl+T Switch Layout Direction Configure... QxtTabWidget QTabWidget
QxtTabWidget
QxtLabel QFrame
QxtLabel
libqxt-0.6.2/tests/other/app/tab.cpp000066400000000000000000000210441215241066400173410ustar00rootroot00000000000000#include "tab.h" #include #include Tab::Tab(QWidget* parent) : QWidget(parent) { ui.setupUi(this); setAttribute(Qt::WA_DeleteOnClose); fillItemViews(); } Tab::~Tab() { } void Tab::on_qxtCheckComboBox_checkedItemsChanged(const QStringList& items) { QString what = QString("QxtCheckComboBox::checkedItemsChanged(%1)"); what = what.arg(items.join(ui.qxtCheckComboBox->separator())); emit somethingHappened(what); } void Tab::on_qxtGroupBox_toggled(bool on) { QString what = QString("QxtGroupBox::toggled(%1)").arg(on ? tr("true") : tr("false")); emit somethingHappened(what); } void Tab::on_qxtLabel_clicked() { emit somethingHappened("QxtLabel::clicked()"); } void Tab::on_qxtListWidget_itemEditingStarted(QListWidgetItem* item) { QString what = QString("QxtListWidget::itemEditingStarted(%1)").arg(item->text()); emit somethingHappened(what); } void Tab::on_qxtListWidget_itemEditingFinished(QListWidgetItem* item) { QString what = QString("QxtListWidget::itemEditingFinished(%1)").arg(item->text()); emit somethingHappened(what); } void Tab::on_qxtListWidget_itemCheckStateChanged(QxtListWidgetItem* item) { QString what = QString("QxtListWidget::itemCheckStateChanged(%1, %2)"); what = what.arg(item->text()).arg(item->checkState() == Qt::Unchecked ? "Qt::Unchecked" : "Qt::Checked"); emit somethingHappened(what); } void Tab::on_qxtSpanSliderHor_spanChanged(int lower, int upper) { QString what = QString("QxtSpanSlider::spanChanged(%1,%2)").arg(lower).arg(upper); emit somethingHappened(what); } void Tab::on_qxtSpanSliderVer_lowerValueChanged(int value) { QString what = QString("QxtSpanSlider::lowerValueChanged(%1)").arg(value); emit somethingHappened(what); } void Tab::on_qxtSpanSliderVer_upperValueChanged(int value) { QString what = QString("QxtSpanSlider::upperValueChanged(%1)").arg(value); emit somethingHappened(what); } void Tab::on_qxtSpanSliderVer_lowerPositionChanged(int pos) { QString what = QString("QxtSpanSlider::lowerPositionChanged(%1)").arg(pos); emit somethingHappened(what); } void Tab::on_qxtSpanSliderVer_upperPositionChanged(int pos) { QString what = QString("QxtSpanSlider::upperPositionChanged(%1)").arg(pos); emit somethingHappened(what); } void Tab::on_qxtStarsHor_valueChanged(int value) { QString what = QString("QxtStars::valueChanged(%1)").arg(value); emit somethingHappened(what); } void Tab::on_qxtStarsVer_valueChanged(int value) { QString what = QString("QxtStars::valueChanged(%1)").arg(value); emit somethingHappened(what); } void Tab::on_qxtStringSpinBox_valueChanged(const QString& value) { QString what = QString("QxtStringSpinBox::valueChanged(%1)").arg(value); emit somethingHappened(what); } void Tab::on_qxtTableWidget_itemEditingStarted(QTableWidgetItem* item) { int row = item->row(); int col = item->column(); QString what = QString("QxtTableWidget::itemEditingStarted(%1,%2)").arg(row).arg(col); emit somethingHappened(what); } void Tab::on_qxtTableWidget_itemEditingFinished(QTableWidgetItem* item) { int row = item->row(); int col = item->column(); QString what = QString("QxtTableWidget::itemEditingFinished(%1,%2)").arg(row).arg(col); emit somethingHappened(what); } void Tab::on_qxtTableWidget_itemCheckStateChanged(QxtTableWidgetItem* item) { int row = item->row(); int col = item->column(); QString what = QString("QxtTableWidget::itemCheckStateChanged(%1, %2, %3)").arg(row).arg(col); what = what.arg(item->checkState() == Qt::Unchecked ? "Qt::Unchecked" : "Qt::Checked"); emit somethingHappened(what); } void Tab::on_qxtTreeWidget_itemEditingStarted(QTreeWidgetItem* item) { QString what = QString("QxtTreeWidget::itemEditingStarted(%1)").arg(item->text(0)); emit somethingHappened(what); } void Tab::on_qxtTreeWidget_itemEditingFinished(QTreeWidgetItem* item) { QString what = QString("QxtTreeWidget::itemEditingFinished(%1)").arg(item->text(0)); emit somethingHappened(what); } void Tab::on_qxtTreeWidget_itemCheckStateChanged(QxtTreeWidgetItem* item) { QString what = QString("QxtTreeWidget::itemCheckStateChanged(%1, %2)"); what = what.arg(item->text(0)).arg(item->checkState(0) == Qt::Unchecked ? "Qt::Unchecked" : "Qt::Checked"); emit somethingHappened(what); } void Tab::fillItemViews() { ui.qxtTreeWidget->header()->hide(); ui.qxtTreeWidget->header()->setResizeMode(QHeaderView::ResizeToContents); QxtTreeWidgetItem* treeItem = new QxtTreeWidgetItem(ui.qxtTreeWidget, QStringList() << tr("Phasellus")); treeItem = new QxtTreeWidgetItem(treeItem, QStringList() << tr("Faucibus")); treeItem->setFlag(Qt::ItemIsUserCheckable); treeItem->setFlag(Qt::ItemIsEditable); treeItem->setCheckState(0, Qt::Unchecked); treeItem->setData(1, QxtItemDelegate::ProgressValueRole, 75); treeItem = new QxtTreeWidgetItem(ui.qxtTreeWidget, QStringList() << tr("Curabitur")); treeItem = new QxtTreeWidgetItem(treeItem, QStringList() << tr("Mauris")); treeItem->setFlag(Qt::ItemIsUserCheckable); treeItem->setFlag(Qt::ItemIsEditable); treeItem->setCheckState(0, Qt::Unchecked); treeItem->setData(1, QxtItemDelegate::ProgressValueRole, 98); treeItem = new QxtTreeWidgetItem(ui.qxtTreeWidget, QStringList() << tr("Quisque")); treeItem = new QxtTreeWidgetItem(treeItem, QStringList() << tr("Vestibulum")); treeItem->setFlag(Qt::ItemIsUserCheckable); treeItem->setFlag(Qt::ItemIsEditable); treeItem->setCheckState(0, Qt::Unchecked); treeItem->setData(1, QxtItemDelegate::ProgressMinimumRole, 0); treeItem->setData(1, QxtItemDelegate::ProgressMaximumRole, 0); treeItem->setData(1, QxtItemDelegate::ProgressValueRole, 0); treeItem = new QxtTreeWidgetItem(treeItem, QStringList() << tr("Pellentesque")); treeItem->setFlag(Qt::ItemIsUserCheckable); treeItem->setFlag(Qt::ItemIsEditable); treeItem->setCheckState(0, Qt::Unchecked); treeItem->setData(1, QxtItemDelegate::ProgressValueRole, 99); QxtListWidgetItem* listItem = new QxtListWidgetItem(tr("Phasellus"), ui.qxtListWidget); listItem->setFlag(Qt::ItemIsUserCheckable); listItem->setFlag(Qt::ItemIsEditable); listItem->setCheckState(Qt::Unchecked); listItem = new QxtListWidgetItem(tr("Faucibus"), ui.qxtListWidget); listItem->setFlag(Qt::ItemIsUserCheckable); listItem->setFlag(Qt::ItemIsEditable); listItem->setCheckState(Qt::Unchecked); listItem = new QxtListWidgetItem(tr("Curabitur"), ui.qxtListWidget); listItem->setFlag(Qt::ItemIsUserCheckable); listItem->setFlag(Qt::ItemIsEditable); listItem->setCheckState(Qt::Unchecked); listItem = new QxtListWidgetItem(tr("Mauris"), ui.qxtListWidget); listItem->setFlag(Qt::ItemIsUserCheckable); listItem->setFlag(Qt::ItemIsEditable); listItem->setCheckState(Qt::Unchecked); listItem = new QxtListWidgetItem(tr("Quisque"), ui.qxtListWidget); listItem->setFlag(Qt::ItemIsUserCheckable); listItem->setFlag(Qt::ItemIsEditable); listItem->setCheckState(Qt::Unchecked); listItem = new QxtListWidgetItem(tr("Vestibulum"), ui.qxtListWidget); listItem->setFlag(Qt::ItemIsUserCheckable); listItem->setFlag(Qt::ItemIsEditable); listItem->setCheckState(Qt::Unchecked); listItem = new QxtListWidgetItem(tr("Pellentesque"), ui.qxtListWidget); listItem->setFlag(Qt::ItemIsUserCheckable); listItem->setFlag(Qt::ItemIsEditable); listItem->setCheckState(Qt::Unchecked); ui.qxtTableWidget->setColumnCount(2); ui.qxtTableWidget->setRowCount(3); QxtTableWidgetItem* tableItem = new QxtTableWidgetItem(tr("Phasellus")); tableItem->setFlag(Qt::ItemIsUserCheckable); tableItem->setFlag(Qt::ItemIsEditable); tableItem->setCheckState(Qt::Unchecked); ui.qxtTableWidget->setItem(0, 0, tableItem); tableItem = new QxtTableWidgetItem(tr("Faucibus")); tableItem->setFlag(Qt::ItemIsUserCheckable); tableItem->setFlag(Qt::ItemIsEditable); tableItem->setCheckState(Qt::Unchecked); ui.qxtTableWidget->setItem(0, 1, tableItem); tableItem = new QxtTableWidgetItem(tr("Curabitur")); tableItem->setFlag(Qt::ItemIsUserCheckable); tableItem->setFlag(Qt::ItemIsEditable); tableItem->setCheckState(Qt::Unchecked); ui.qxtTableWidget->setItem(1, 0, tableItem); tableItem = new QxtTableWidgetItem(tr("Mauris")); tableItem->setFlag(Qt::ItemIsUserCheckable); tableItem->setFlag(Qt::ItemIsEditable); tableItem->setCheckState(Qt::Unchecked); ui.qxtTableWidget->setItem(1, 1, tableItem); tableItem = new QxtTableWidgetItem(tr("Quisque")); tableItem->setFlag(Qt::ItemIsUserCheckable); tableItem->setFlag(Qt::ItemIsEditable); tableItem->setCheckState(Qt::Unchecked); ui.qxtTableWidget->setItem(2, 0, tableItem); tableItem = new QxtTableWidgetItem(tr("Vestibulum")); tableItem->setFlag(Qt::ItemIsUserCheckable); tableItem->setFlag(Qt::ItemIsEditable); tableItem->setCheckState(Qt::Unchecked); ui.qxtTableWidget->setItem(2, 1, tableItem); } libqxt-0.6.2/tests/other/app/tab.h000066400000000000000000000027151215241066400170120ustar00rootroot00000000000000#ifndef TAB_H #define TAB_H #include "ui_tab.h" class Tab : public QWidget { Q_OBJECT public: Tab(QWidget* parent = 0); ~Tab(); signals: void somethingHappened(const QString& what); private slots: void on_qxtCheckComboBox_checkedItemsChanged(const QStringList& items); void on_qxtGroupBox_toggled(bool on); void on_qxtLabel_clicked(); void on_qxtListWidget_itemEditingStarted(QListWidgetItem* item); void on_qxtListWidget_itemEditingFinished(QListWidgetItem* item); void on_qxtListWidget_itemCheckStateChanged(QxtListWidgetItem* item); void on_qxtSpanSliderHor_spanChanged(int lower, int upper); void on_qxtSpanSliderVer_lowerValueChanged(int value); void on_qxtSpanSliderVer_upperValueChanged(int value); void on_qxtSpanSliderVer_lowerPositionChanged(int pos); void on_qxtSpanSliderVer_upperPositionChanged(int pos); void on_qxtStarsHor_valueChanged(int value); void on_qxtStarsVer_valueChanged(int value); void on_qxtStringSpinBox_valueChanged(const QString& value); void on_qxtTableWidget_itemEditingStarted(QTableWidgetItem* item); void on_qxtTableWidget_itemEditingFinished(QTableWidgetItem* item); void on_qxtTableWidget_itemCheckStateChanged(QxtTableWidgetItem* item); void on_qxtTreeWidget_itemEditingStarted(QTreeWidgetItem* item); void on_qxtTreeWidget_itemEditingFinished(QTreeWidgetItem* item); void on_qxtTreeWidget_itemCheckStateChanged(QxtTreeWidgetItem* item); private: void fillItemViews(); Ui::Tab ui; }; #endif // TAB_H libqxt-0.6.2/tests/other/app/tab.ui000066400000000000000000000330251215241066400171760ustar00rootroot00000000000000 Tab 0 0 436 315 Form 0 0 Click me! QxtLabel QxtLabel QFrame::Panel QFrame::Sunken 2 0 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Qxt::CounterClockwise QxtGroupBox QxtGroupBox GroupBox false QxtStars QxtStars 3 3 1 Qt::Vertical QxtCheckComboBox QxtCheckComboBox ... Curabitur eleifend purus id velit QxtStringSpinBox QxtStringSpinBox Curabitur eleifend purus id velit 0x 0 2147483647 47806 16 true QxtSpanSlider QxtSpanSlider false Qt::Vertical true true 0 99 QxtSpanSlider QxtSpanSlider 5 Qt::Horizontal QSlider::TicksAbove 15 0 0 QxtStars QxtStars 5 3 4 Qt::Horizontal QxtPushButton QxtPushButton <h1>Nam <font color="red">dapibus</font> semper.</h1> Qxt::Clockwise Qt::AutoText 0 0 1 0 0 98 80 List 6 9 9 9 9 QxtListWidget QxtListWidget 0 0 360 167 Tree 6 9 9 9 9 QxtTreeWidget QxtTreeWidget 2 Qxt::Buttonlike 1 2 0 0 98 80 Table 6 9 9 9 9 QxtLabel QFrame
QxtLabel
QxtPushButton QPushButton
QxtPushButton
QxtCheckComboBox QComboBox
QxtCheckComboBox
QxtSpanSlider QSlider
QxtSpanSlider
QxtBaseSpinBox QSpinBox
QxtBaseSpinBox
QxtStringSpinBox QSpinBox
QxtStringSpinBox
QxtGroupBox QGroupBox
QxtGroupBox
1
QxtListWidget QListWidget
QxtListWidget
QxtTreeWidget QTreeWidget
QxtTreeWidget
QxtTableWidget QTableWidget
QxtTableWidget
QxtStars QWidget
QxtStars
libqxt-0.6.2/tests/other/no_keywords/000077500000000000000000000000001215241066400176515ustar00rootroot00000000000000libqxt-0.6.2/tests/other/no_keywords/main.cpp000066400000000000000000000005001215241066400212740ustar00rootroot00000000000000#include #ifdef QXT_BERKELEY_LIB #include #endif #ifdef QXT_CORE_LIB #include #endif #ifdef QXT_GUI_LIB #include #endif #ifdef QXT_NETWORK_LIB #include #endif #ifdef QXT_SQL_LIB #include #endif #ifdef QXT_WEB_LIB #include #endif int main() { } libqxt-0.6.2/tests/other/no_keywords/no_keywords.pro000066400000000000000000000007721215241066400227440ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . CONFIG += no_keywords contains(DEFINES,HAVE_DB):contains(QXT_MODULES, berkeley):QXT += berkeley contains(QXT_MODULES, core):QXT += core contains(QXT_MODULES, gui):QXT += gui contains(QXT_MODULES, network):QXT += network contains(QXT_MODULES, sql):QXT += sql contains(QXT_MODULES, web):QXT += web contains(DEFINES,HAVE_ZEROCONF):contains(QXT_MODULES, zeroconf):QXT += zeroconf include($$QXT_SOURCE_TREE/src/qxtlibs.pri) # Input SOURCES += main.cpp libqxt-0.6.2/tests/other/other.pro000066400000000000000000000001221215241066400171440ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS += app no_keywords QxtFileLock QxtScheduleView slotjob libqxt-0.6.2/tests/other/slotjob/000077500000000000000000000000001215241066400167625ustar00rootroot00000000000000libqxt-0.6.2/tests/other/slotjob/main.cpp000066400000000000000000000012441215241066400204130ustar00rootroot00000000000000#include #include #include class Q43Thread : public QThread{public:void run(){exec();}}; /// qt < 4.3 backwards compatibility #include #include class Bla : public QObject { Q_OBJECT public slots: QString say(QString a) { qDebug()< #include #include #include class Test: public QObject { Q_OBJECT private slots: void begin() { db.open("test.db"); } void readInvalidIterator() { QVERIFY(db.begin().value().size()==0); } void insert() { QVERIFY(db.insert(454.332,QStringList()<<"hello"<<"how are you?")); QVERIFY(db.insert(235,QStringList()<<"hey"<<"how's it going?")); QVERIFY(db.insert(234,QStringList()<<"jo"<<"sup?")); } void contains() { QVERIFY(db.contains(235)); QVERIFY(!db.contains(34.24)); } void implicitCopy() { QxtBdbHash d=db; QVERIFY(d.contains(235)); QVERIFY(!d.contains(34.24)); } void read() { QVERIFY(db[235].count()==2); QVERIFY(db[235].at(1)=="how's it going?"); } void readBeginIterator() { QVERIFY(db.begin().value().at(1)=="sup?"); } void readEndIterator() { QVERIFY(db.end().value().at(1)=="how are you?"); } void find() { QxtBdbHashIterator it=db.find(234); QVERIFY(it.isValid()); QVERIFY(it.value().at(1)=="sup?"); } void readNextAndPrevIterator() { QxtBdbHashIterator it=db.begin(); QVERIFY(it.isValid()); ++it; QVERIFY(it.isValid()); QVERIFY(it.value().at(1)=="how's it going?"); QVERIFY(it.key()==235); --it; QVERIFY(it.isValid()); QVERIFY(it.value().at(1)=="sup?"); } void readIteratorOutOfBounds() { QxtBdbHashIterator it=db.begin(); --it; it--; --it; it--; QVERIFY(!it.isValid()); QVERIFY(it.value().count()==0); QVERIFY(it.key()==0); it+=4; } void erase() { QxtBdbHashIterator it=db.find(235); QVERIFY(it.isValid()); QxtBdbHashIterator it2; QVERIFY(!it2.isValid()); it2=it.erase(); QVERIFY(!it.isValid()); QVERIFY(it2.isValid()); QVERIFY(it2.key()==454.332); } void remove() { QVERIFY(db.contains(234)); db.remove(234); QVERIFY(!db.contains(234)); } void clear() { QVERIFY(db.contains(454.332)); db.clear(); QVERIFY(!db.contains(454.332)); } void end() { } private: QxtBdbHash db; }; QTEST_MAIN(Test) #include "main.moc" libqxt-0.6.2/tests/unit/berkeley/qxtbdbhash/qxtbdbhash.pro000066400000000000000000000003641215241066400237530ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QXT += berkeley SOURCES += main.cpp QMAKE_CLEAN += test.db include(../../unit.pri) # TODO: fix public QxtBDB headers NOT to include BDB headers! win32:include(../../../../depends.pri) libqxt-0.6.2/tests/unit/berkeley/qxtbdbtree/000077500000000000000000000000001215241066400211125ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/berkeley/qxtbdbtree/main.cpp000066400000000000000000000033661215241066400225520ustar00rootroot00000000000000#include #include #include #include class Test: public QObject { Q_OBJECT private slots: void begin() { db.open("test.db"); db.clear(); } void readRoot() { QVERIFY(db.root().value().size()==0); } void readInvalid() { QVERIFY(db.root().child().value().size()==0); QVERIFY(db.root().next().value().size()==0); QVERIFY(db.root().previous().value().size()==0); QVERIFY(db.root().parent().value().size()==0); } void append() { QVERIFY(db.root().append(QStringList()<<"asda"<<"asfg").isValid()); QVERIFY(db.root().append(QStringList()<<"sh00"<<"xcv").append(QStringList()<<"vvvv").isValid()); } void prepend() { QVERIFY(db.root().append(QStringList()<<"xylophon").prepend(QStringList()<<"you"<<"rock").isValid()); } void read() { QVERIFY( (db.root().child()+1).child().value().at(0)=="vvvv"); QVERIFY( (db.root().child()+2).value().at(1)=="rock"); } void erasePersistance() { QxtBdbTreeIterator sib=db.root().child()+1; QVERIFY(sib.value().at(0)=="sh00"); // QVERIFY(db.root().child().erase() == sib ); ///doesn't work yet QVERIFY(db.root().child().erase().value() == sib.value() ); QVERIFY(sib.value().at(0)=="sh00"); sib=db.root().child()+2; QVERIFY(sib.value().at(0)=="xylophon"); // QVERIFY(db.root().child().erase() == sib ); ///doesn't work yet QVERIFY((db.root().child()+1).erase().value() == sib.value() ); QVERIFY(sib.value().at(0)=="xylophon"); } void end() { } private: QxtBdbTree db; }; QTEST_MAIN(Test) #include "main.moc" libqxt-0.6.2/tests/unit/berkeley/qxtbdbtree/qxtbdbtree.pro000066400000000000000000000003631215241066400240020ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QXT += berkeley SOURCES += main.cpp QMAKE_CLEAN += test.db include(../../unit.pri) # TODO: fix public QxtBDB headers NOT to include BDB headers! win32:include(../../../../depends.pri) libqxt-0.6.2/tests/unit/core/000077500000000000000000000000001215241066400160745ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/core/bind/000077500000000000000000000000001215241066400170105ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/core/bind/bind.pro000066400000000000000000000001731215241066400204470ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = core SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/core/bind/main.cpp000066400000000000000000000057121215241066400204450ustar00rootroot00000000000000#include #include #include #include #include void unaryVoidFunction(QObject* obj); void nullaryVoidFunction() { qDebug() << "If you don't see this, it's broken."; } int nullaryIntFunction() { return 5; } int unaryIntFunction(int x) { return x * 2; } class QxtMetaObjectTest: public QObject { Q_OBJECT signals: void say(QString); void doit(); void success(); public: void unaryVoidFunctionSuccess() { emit success(); } private slots: void readwrite() { QxtMetaObject::connect(this, SIGNAL(doit()), QxtMetaObject::bind(this, SLOT(say(QString)), Q_ARG(QString,"hello"))); QSignalSpy spy(this, SIGNAL(say(QString))); emit(doit()); QVERIFY2 (spy.count()> 0, "no signal received" ); QVERIFY2 (spy.count()< 2, "wtf, two signals received?" ); QList arguments = spy.takeFirst(); QVERIFY2(arguments.at(0).toString()=="hello","argument missmatch"); QxtBoundFunction* nullaryVoid = QxtMetaObject::bind(qxtFuncPtr(nullaryVoidFunction)); QxtBoundFunction* unaryVoid = QxtMetaObject::bind(qxtFuncPtr(unaryVoidFunction), Q_ARG(QObject*, this)); QxtBoundFunction* nullaryInt = QxtMetaObject::bind(qxtFuncPtr(nullaryIntFunction)); QxtBoundFunction* unaryIntFixed = QxtMetaObject::bind(qxtFuncPtr(unaryIntFunction), Q_ARG(int, 7)); QxtBoundFunction* unaryIntBound = QxtMetaObject::bind(qxtFuncPtr(unaryIntFunction), QXT_BIND(1)); QVERIFY2(nullaryVoid != 0, "nullaryVoidFunction bind failed"); QVERIFY2(unaryVoid != 0, "unaryVoidFunction bind failed"); QVERIFY2(nullaryInt != 0, "nullaryIntFunction bind failed"); QVERIFY2(unaryIntFixed != 0, "unaryIntFunction bind failed with Q_ARG"); QVERIFY2(unaryIntBound != 0, "unaryIntFunction bind failed with QXT_BIND"); bool ok; ok = nullaryVoid->invoke(); QVERIFY2(ok, "nullaryVoid invoke failed"); QSignalSpy spy2(this, SIGNAL(success())); ok = unaryVoid->invoke(QVariant::fromValue(this)); QVERIFY2(ok, "unaryVoid invoke failed"); QVERIFY2(spy2.count() == 1, "unaryVoid did not emit success"); int v1 = nullaryIntFunction(); int v2 = nullaryInt->invoke(); QVERIFY2(v1 == v2, "nullaryInt returned wrong value"); v1 = unaryIntFunction(7); v2 = unaryIntFixed->invoke(); QVERIFY2(v1 == v2, "unaryIntFixed returned wrong value"); v1 = unaryIntFunction(12); v2 = unaryIntBound->invoke(12); QVERIFY2(v1 == v2, "unaryIntBound returned wrong value"); } }; Q_DECLARE_METATYPE(QxtMetaObjectTest*) void unaryVoidFunction(QObject* obj) { QxtMetaObjectTest* o = qobject_cast(obj); if(!o) return; o->unaryVoidFunctionSuccess(); } QTEST_MAIN(QxtMetaObjectTest) #include "main.moc" libqxt-0.6.2/tests/unit/core/core.pro000066400000000000000000000002641215241066400175500ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS += bind fifo json job modelserializer pipe sharedprivate slotmapper SUBDIRS += filelock #permfail test.CONFIG += recursive QMAKE_EXTRA_TARGETS += test libqxt-0.6.2/tests/unit/core/fifo/000077500000000000000000000000001215241066400170175ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/core/fifo/fifo.pro000066400000000000000000000001731215241066400204650ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = core SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/core/fifo/main.cpp000066400000000000000000000024101215241066400204440ustar00rootroot00000000000000#include #include #include #include #include #include #include class QxtFifoPipeTest: public QObject { Q_OBJECT private slots: void initTestCase() { io= new QxtFifo; } void readwrite() { QDataStream w(io); w << QString("hello"); w << 34; QString str; int i; QDataStream r(io); r >> str; r >> i; QVERIFY2(i==34,"output not matching input"); QVERIFY2(str==QString("hello"),"output not mathing input"); } void readyread() { QSignalSpy spyr(io, SIGNAL(readyRead())); io->write("hello"); QCoreApplication::processEvents(); QVERIFY2 (spyr.count()> 0, "not emitting readyRead" ); io->readAll(); } void size() { QByteArray data("askdoamsdoiasmdpoeiowaopimwaioemfowefnwaoief"); QVERIFY(io->write(data)==data.size()); QVERIFY(io->bytesAvailable()==data.size()); io->readAll(); QVERIFY(io->bytesAvailable()==0); } void cleanupTestCase() { delete(io); } private: QxtFifo * io; }; QTEST_MAIN(QxtFifoPipeTest) #include "main.moc" libqxt-0.6.2/tests/unit/core/filelock/000077500000000000000000000000001215241066400176645ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/core/filelock/filelock.pro000066400000000000000000000002351215241066400221760ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = core SOURCES += main.cpp QMAKE_CLEAN += lock.file include(../../unit.pri) libqxt-0.6.2/tests/unit/core/filelock/main.cpp000066400000000000000000000153261215241066400213230ustar00rootroot00000000000000/** ***** QxtFileLock test ***** */ #include #include #include #include #include #include class QxtFileLockTest: public QObject { Q_OBJECT private: QFile * file1; QFile * file2; private slots: void initTestCase() { file1=new QFile("lock.file"); file2=new QFile("lock.file"); QVERIFY(file1->open(QIODevice::ReadWrite)); QVERIFY(file2->open(QIODevice::ReadWrite)); } ///read and write lock on the same handle void rw_same() { QxtFileLock lock1(file1,0x10,20,QxtFileLock::ReadLock); QxtFileLock lock2(file1,0x10,20,QxtFileLock::WriteLock); QVERIFY(lock1.lock() && !lock2.lock()); } ///Trying to readlock the same region with DIFFERENT handles void rr_different() { QxtFileLock lock1(file1,0x10,20,QxtFileLock::ReadLock); QxtFileLock lock2(file2,0x10,20,QxtFileLock::ReadLock); QVERIFY(lock1.lock() && lock2.lock()); } ///Trying to lock the same region with DIFFERENT handles and different locks void rw_different() { QxtFileLock lock1(file1,0x10,20,QxtFileLock::ReadLock); QxtFileLock lock2(file2,0x10,20,QxtFileLock::WriteLock); QVERIFY(lock1.lock() && !lock2.lock()); } ///Trying to writelock the same region with DIFFERENT handles void ww_different() { QxtFileLock lock1(file1,0x10,20,QxtFileLock::WriteLock); QxtFileLock lock2(file2,0x10,20,QxtFileLock::WriteLock); QVERIFY(lock1.lock() && !lock2.lock()); } ///Trying to writelock the different regions with DIFFERENT handles void ww_different_region() { QxtFileLock lock1(file1,0x10 ,20,QxtFileLock::WriteLock); QxtFileLock lock2(file2,0x10+21,20,QxtFileLock::WriteLock); QVERIFY(lock1.lock() && lock2.lock()); } ///different region, different handles, different locks/usr/bin/ void rw_different_region() { QxtFileLock lock1(file1,0x10 ,20,QxtFileLock::ReadLock); QxtFileLock lock2(file2,0x10+21,20,QxtFileLock::WriteLock); QVERIFY(lock1.lock() && lock2.lock()); } ///different region, same handles, different locks void rw_same_region() { QxtFileLock lock1(file1,0x10 ,20,QxtFileLock::ReadLock); QxtFileLock lock2(file1,0x10+21,20,QxtFileLock::WriteLock); QVERIFY(lock1.lock() && lock2.lock()); } void cleanupTestCase() { delete file1; delete file2; } }; #include #include class Q43Thread : public QThread { public: void run() { exec(); } } ; /// qt < 4.3 backwards compatibility ///this is a job hack, not part of the testcase, ignore it if you don't what it is ///here is the interesting part of the job. this executes one lock on a spefic thread and asserts the result class LockJob : public QxtJob { public: LockJob(QxtFileLock*f,bool expectedresult):QxtJob() { lock =f; expected=expectedresult; } QxtFileLock*lock ; bool expected; virtual void run() { qDebug("locking on %p",QThread::currentThread ()); QVERIFY(lock ->lock ()==expected); } void exec(QThread * o) { QxtJob::exec(o); join(); } }; class QxtFileLockThreadTest : public QObject { Q_OBJECT private: Q43Thread t1; Q43Thread t2; private slots: void initTestCase() { qDebug("main thread is %p",QThread::currentThread ()); QxtSignalWaiter w1(&t1,SIGNAL(started())); t1.start(); QVERIFY(w1.wait()); QxtSignalWaiter w2(&t2,SIGNAL(started())); t2.start(); QVERIFY(w2.wait()); } ///Trying to writelock the same region twice void ww_same() { QFile* file1 = new QFile("lock.file"); QVERIFY(file1->open(QIODevice::ReadWrite)); QFile* file2 = new QFile("lock.file"); QVERIFY(file2->open(QIODevice::ReadWrite)); QxtFileLock* lock1 = new QxtFileLock(file1,0x10,20,QxtFileLock::WriteLock); file1->moveToThread(&t1); LockJob l(lock1,true); l.exec(&t1); QxtFileLock* lock2 = new QxtFileLock(file2,0x10,20,QxtFileLock::WriteLock); file2->moveToThread(&t2); LockJob l2(lock2,false); l2.exec(&t2); l2.join(); file1->deleteLater(); file2->deleteLater(); } ///Trying to readlock the same region void rr_same() { QFile* file1 = new QFile("lock.file"); QVERIFY(file1->open(QIODevice::ReadWrite)); QFile* file2 = new QFile("lock.file"); QVERIFY(file2->open(QIODevice::ReadWrite)); QxtFileLock* lock1 = new QxtFileLock(file1,0x10,20,QxtFileLock::ReadLock); file1->moveToThread(&t1); LockJob l1(lock1,true); l1.exec(&t1); l1.join(); QxtFileLock* lock2 = new QxtFileLock(file2,0x10,20,QxtFileLock::ReadLock); file2->moveToThread(&t2); LockJob l2(lock2,true); l2.exec(&t2); l2.join(); file1->deleteLater(); file2->deleteLater(); } ///Trying to lock the same region with different locks void rw_same() { QFile* file1 = new QFile("lock.file"); QVERIFY(file1->open(QIODevice::ReadWrite)); QFile* file2 = new QFile("lock.file"); QVERIFY(file2->open(QIODevice::ReadWrite)); QxtFileLock* lock1 = new QxtFileLock(file1,0x10,20,QxtFileLock::WriteLock); file1->moveToThread(&t1); LockJob(lock1,true).exec(&t1); QxtFileLock* lock2 = new QxtFileLock(file2,0x10,20,QxtFileLock::ReadLock); file2->moveToThread(&t2); LockJob(lock2,false).exec(&t2); file1->deleteLater(); file2->deleteLater(); } ///Trying to writelock different regions void ww_different() { QFile* file1 = new QFile("lock.file"); QVERIFY(file1->open(QIODevice::ReadWrite)); QFile* file2 = new QFile("lock.file"); QVERIFY(file2->open(QIODevice::ReadWrite)); QxtFileLock* lock1 = new QxtFileLock(file1,0x10,20,QxtFileLock::WriteLock); file1->moveToThread(&t1); LockJob(lock1,true).exec(&t1); QxtFileLock* lock2 = new QxtFileLock(file2,0x10+21,20,QxtFileLock::WriteLock); file2->moveToThread(&t2); LockJob(lock2,true).exec(&t2); file1->deleteLater(); file2->deleteLater(); } void cleanupTestCase() { t1.quit (); t1.wait (); t2.quit (); t2.wait (); } }; int main(int argc, char ** argv) { QCoreApplication app(argc,argv); QxtFileLockTest test1; QxtFileLockThreadTest test2; return QTest::qExec(&test1,argc,argv)+QTest::qExec(&test2,argc,argv); } #include "main.moc" libqxt-0.6.2/tests/unit/core/job/000077500000000000000000000000001215241066400166465ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/core/job/job.pro000066400000000000000000000001731215241066400201430ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = core SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/core/job/main.cpp000066400000000000000000000024131215241066400202760ustar00rootroot00000000000000/** ***** QxtJob test ***** */ #include #include class Q43Thread : public QThread{public:void run(){exec();}}; /// qt < 4.3 backwards compatibility #include #include #include class TestJob : public QxtJob { public: bool b; TestJob():QxtJob() { b=false; } virtual void run() { qDebug("job on on %p",QThread::currentThread ()); b=true; } }; class QxtJobTest : public QObject { Q_OBJECT private: Q43Thread t; private slots: void initTestCase() { t.start(); } void lined() { TestJob l; QSignalSpy spy(&l, SIGNAL(done())); QxtSignalWaiter w(&l,SIGNAL(done())); l.exec(&t); QVERIFY(w.wait(50)); QCOMPARE(spy.count(), 1); QVERIFY(l.b); } void joined() { TestJob l; l.exec(&t); QxtSignalWaiter w(&l,SIGNAL(done())); l.join(); QVERIFY(w.wait(100)); QVERIFY(l.b); } void cleanupTestCase() { t.quit(); QVERIFY(t.wait(50)); } }; int main(int argc, char ** argv) { QCoreApplication app(argc,argv); QxtJobTest test1; return QTest::qExec(&test1,argc,argv); } #include "main.moc" libqxt-0.6.2/tests/unit/core/json/000077500000000000000000000000001215241066400170455ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/core/json/json.pro000066400000000000000000000002031215241066400205330ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core testlib QXT = core SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/core/json/main.cpp000066400000000000000000000053201215241066400204750ustar00rootroot00000000000000#include #include #include class QxtJSONTest: public QObject{ Q_OBJECT; private slots: void initTestCase(){ } void stringifyBasic(){ QCOMPARE(QxtJSON::stringify((int)4),QString("4")); QCOMPARE(QxtJSON::stringify(false),QString("false")); QCOMPARE(QxtJSON::stringify(true),QString("true")); QCOMPARE(QxtJSON::stringify(QVariant()),QString("null")); QCOMPARE(QxtJSON::stringify("hi"),QString("\"hi\"")); QCOMPARE(QxtJSON::stringify("hi"),QString("\"hi\"")); QCOMPARE(QxtJSON::stringify(0.4),QString("0.4")); QCOMPARE(QxtJSON::stringify(QVariantList()<<4),QString("[4]")); QCOMPARE(QxtJSON::stringify(QVariantList()),QString("[]")); } void stringifyList(){ QVariantList e; e<<"fish"; e<<5; e< #include //krazy:exclude=qxtincludes #include #include #include #include #include class tst_QxtModelSerializer : public QObject { Q_OBJECT private slots: void initTestCase(); void serializationTest(); void sanityTest(); private: bool copyModel(QAbstractItemModel* src, QAbstractItemModel* dst); bool compareModels(const QAbstractItemModel* a, const QAbstractItemModel* b, const QModelIndex& ai = QModelIndex(), const QModelIndex &bi = QModelIndex()) const; }; void tst_QxtModelSerializer::initTestCase() { QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName(":memory:"); QVERIFY(db.open()); QSqlQuery query; query.exec("create table person (id int primary key, " "firstname varchar(20), lastname varchar(20))"); query.exec("insert into person values(101, 'Danny', 'Young')"); query.exec("insert into person values(102, 'Christine', 'Holand')"); query.exec("insert into person values(103, 'Lars', 'Gordon')"); query.exec("insert into person values(104, 'Roberto', 'Robitaille')"); query.exec("insert into person values(105, 'Maria', 'Papadopoulos')"); query.exec("create table offices (id int primary key," "imagefile int," "location varchar(20)," "country varchar(20)," "description varchar(100))"); query.exec("insert into offices " "values(0, 0, 'Oslo', 'Norway'," "'Oslo is home to more than 500 000 citizens and has a " "lot to offer.It has been called \"The city with the big " "heart\" and this is a nickname we are happy to live up to.')"); query.exec("insert into offices " "values(1, 1, 'Brisbane', 'Australia'," "'Brisbane is the capital of Queensland, the Sunshine State, " "where it is beautiful one day, perfect the next. " "Brisbane is Australia''s 3rd largest city, being home " "to almost 2 million people.')"); query.exec("insert into offices " "values(2, 2, 'Redwood City', 'US'," "'You find Redwood City in the heart of the Bay Area " "just north of Silicon Valley. The largest nearby city is " "San Jose which is the third largest city in California " "and the 10th largest in the US.')"); query.exec("insert into offices " "values(3, 3, 'Berlin', 'Germany'," "'Berlin, the capital of Germany is dynamic, cosmopolitan " "and creative, allowing for every kind of lifestyle. " "East meets West in the metropolis at the heart of a " "changing Europe.')"); query.exec("insert into offices " "values(4, 4, 'Munich', 'Germany'," "'Several technology companies are represented in Munich, " "and the city is often called the \"Bavarian Silicon Valley\". " "The exciting city is also filled with culture, " "art and music. ')"); query.exec("insert into offices " "values(5, 5, 'Beijing', 'China'," "'Beijing as a capital city has more than 3000 years of " "history. Today the city counts 12 million citizens, and " "is the political, economic and cultural centre of China.')"); } void tst_QxtModelSerializer::serializationTest() { QSqlTableModel srcPersonModel; srcPersonModel.setTable("person"); srcPersonModel.select(); QStandardItemModel dstPersonModel; QVERIFY(copyModel(&srcPersonModel, &dstPersonModel)); QVERIFY(compareModels(&srcPersonModel, &dstPersonModel)); QSqlTableModel srcOfficesModel; srcOfficesModel.setTable("offices"); srcOfficesModel.select(); QSqlTableModel dstOfficesModel; srcOfficesModel.setTable("offices2"); QVERIFY(copyModel(&srcOfficesModel, &dstOfficesModel)); QVERIFY(compareModels(&srcOfficesModel, &dstOfficesModel)); QStandardItemModel srcTreeModel; QStandardItem *parentItem = srcTreeModel.invisibleRootItem(); for (int i = 0; i < 4; ++i) { QStandardItem* item = new QStandardItem(QString("item %0").arg(i)); parentItem->appendRow(item); parentItem = item; } QStandardItemModel dstTreeModel; QVERIFY(copyModel(&srcTreeModel, &dstTreeModel)); QVERIFY(compareModels(&srcTreeModel, &dstTreeModel)); } void tst_QxtModelSerializer::sanityTest() { QxtModelSerializer serializer; QVERIFY(!serializer.model()); QCOMPARE(serializer.saveModel(), QByteArray()); QCOMPARE(serializer.restoreModel(QByteArray()), false); } bool tst_QxtModelSerializer::copyModel(QAbstractItemModel* src, QAbstractItemModel* dst) { QxtModelSerializer serializer(src); QByteArray data = serializer.saveModel(); serializer.setModel(dst); return serializer.restoreModel(data); } bool tst_QxtModelSerializer::compareModels(const QAbstractItemModel* a, const QAbstractItemModel* b, const QModelIndex& ai, const QModelIndex &bi) const { QMap ad = a->itemData(ai); QMap bd = b->itemData(bi); ad.remove(31); // because of QStandardItemModel bd.remove(31); // because of QStandardItemModel //if (ad != bd) //{ //qDebug() << ad << bd; //return false; //} if (a->rowCount(ai) != b->rowCount(bi)) return false; if (a->columnCount(ai) != b->columnCount(bi)) return false; for (int r = 0; r < a->rowCount(ai); ++r) for (int c = 0; c < a->columnCount(ai); ++c) return compareModels(a, b, a->index(r, c, ai), b->index(r, c, bi)); return true; } QTEST_MAIN(tst_QxtModelSerializer) #include "tst_modelserializer.moc" libqxt-0.6.2/tests/unit/core/pipe/000077500000000000000000000000001215241066400170315ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/core/pipe/main.cpp000066400000000000000000000027331215241066400204660ustar00rootroot00000000000000#include #include #include #include #include class QxtPipeTest: public QObject { Q_OBJECT private slots: void simple() { QxtPipe p1; QxtPipe p2; p1|p2; p1.write("hi"); QVERIFY(p2.readAll()=="hi"); } void chain() { QxtPipe p1; QxtPipe p2; QxtPipe p3; p1|p2; p2|p3; p1.write("hi"); QVERIFY(p3.readAll()=="hi"); } void bidirectional() { QxtPipe p1; QxtPipe p2; p1|p2; p1.write("hi"); QVERIFY(p2.readAll()=="hi"); QVERIFY(p1.bytesAvailable()==0); p2.write("rehi"); QVERIFY(p1.readAll()=="rehi"); QVERIFY(p2.bytesAvailable()==0); } void readOnly() { QxtPipe p1; QxtPipe p2; p1.connect(&p2,QIODevice::ReadOnly); p1.write("hi"); QVERIFY(p1.bytesAvailable()==0); QVERIFY(p2.bytesAvailable()==0); p2.write("rehi"); QVERIFY(p1.readAll()=="rehi"); QVERIFY(p2.bytesAvailable()==0); } void writeOnly() { QxtPipe p1; QxtPipe p2; p1.connect(&p2,QIODevice::WriteOnly); p1.write("hi"); QVERIFY(p1.bytesAvailable()==0); QVERIFY(p2.readAll()=="hi"); p2.write("rehi"); QVERIFY(p1.bytesAvailable()==0); QVERIFY(p2.bytesAvailable()==0); } }; QTEST_MAIN(QxtPipeTest) #include "main.moc" libqxt-0.6.2/tests/unit/core/pipe/pipe.pro000066400000000000000000000001731215241066400205110ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = core SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/core/sharedprivate/000077500000000000000000000000001215241066400207355ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/core/sharedprivate/main.cpp000066400000000000000000000061541215241066400223730ustar00rootroot00000000000000#include #include #include #include #include int instances=0; class MyPrivate; class My { public: My(); QString string() const; void setString(QString a); private: QxtSharedPrivate d; }; class MyPrivate { public: MyPrivate() { instances++; } ~MyPrivate() { instances--; } QString string() const { return m_string; } void setString(QString a) { m_string=a; } QString m_string; }; My::My() { d=new MyPrivate; } QString My::string() const { return d().string(); } void My::setString(QString a) { return d().setString(a); } class My2Private; class My2 { public: My2(); QString string() const; void setString(QString a); void couseDetach(); private: QxtSharedPrivate d; }; class My2Private { public: My2Private() { instances++; } virtual ~My2Private() { instances--; } My2Private(const My2Private & ) { instances++; m_string="foo"; } QString string() const { return m_string; } void setString(QString a) { m_string=a; } QString m_string; void couseDetach() { //nothing. but it's not const } }; My2::My2() { d=new My2Private; } QString My2::string() const { return d().string(); } void My2::setString(QString a) { d().setString(a); } void My2::couseDetach() { d().couseDetach(); } class QxtSharedPrivateTest : public QObject { Q_OBJECT private slots: void sanity() { { QCOMPARE(instances,0); My m1; QCOMPARE(instances,1); My m2; QCOMPARE(instances,2); } QCOMPARE(instances,0); } void share() { My m1; QCOMPARE(instances,1); My m2(m1); QCOMPARE(instances,1); } void keepShareOnConstCall() { QCOMPARE(instances,0); My m1; QCOMPARE(instances,1); My m2(m1); QCOMPARE(instances,1); m1.string(); QCOMPARE(instances,1); } void copyOnWrite() { QCOMPARE(instances,0); My2 m1; QCOMPARE(instances,1); My2 m2(m1); QCOMPARE(instances,1); m1.setString("bla"); QCOMPARE(instances,2); } void implicitCopyCtor() { QCOMPARE(instances,0); My m1; m1.setString("bla"); QCOMPARE(instances,1); My m2(m1); QCOMPARE(instances,1); QVERIFY(m1.string()=="bla"); QCOMPARE(instances,1); } void explicitCopyCtor() { QCOMPARE(instances,0); My2 m1; m1.setString("bla"); QCOMPARE(instances,1); My2 m2(m1); QCOMPARE(instances,1); m2.couseDetach(); QVERIFY(m2.string()=="foo"); QCOMPARE(instances,2); } }; int main(int argc, char ** argv) { QCoreApplication app(argc,argv); QxtSharedPrivateTest test1; return QTest::qExec(&test1,argc,argv); } #include "main.moc" libqxt-0.6.2/tests/unit/core/sharedprivate/sharedprivate.pro000066400000000000000000000002031215241066400243130ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = core SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/core/slotmapper/000077500000000000000000000000001215241066400202625ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/core/slotmapper/receiver.h000066400000000000000000000056121215241066400222430ustar00rootroot00000000000000#ifndef RECEIVER_H #define RECEIVER_H #include //krazy:exclude=qxtincludes class Receiver : public QObject { Q_OBJECT public: Receiver() { } public slots: void intSlot(int val) { ints << val; } void uintSlot(uint val) { uints << val; } void qlonglongSlot(qlonglong val) { qlonglongs << val; } void qulonglongSlot(qulonglong val) { qulonglongs << val; } void boolSlot(bool val) { bools << val; } void doubleSlot(double val) { doubles << val; } //void charSlot(const char* val) { chars << val; } "const char*" is not a meta type void byteArraySlot(const QByteArray& val) { byteArrays << val; } void bitArraySlot(const QBitArray& val) { bitArrays << val; } void stringSlot(const QString& val) { strings << val; } //void latin1StringList(const QLatin1String& val) { latin1Strings << val; } "QLatin1String" is not a meta type void stringListSlot(const QStringList& val) { stringLists << val; } void qcharSlot(const QChar& val) { qchars << val; } void dateSlot(const QDate& val) { dates << val; } void timeSlot(const QTime& val) { times << val; } void dateTimeSlot(const QDateTime& val) { dateTimes << val; } void listSlot(const QVariantList& val) { lists << val; } void mapSlot(const QVariantMap& val) { maps << val; } void sizeSlot(const QSize& val) { sizes << val; } void sizeFSlot(const QSizeF& val) { sizeFs << val; } void pointSlot(const QPoint& val) { points << val; } void pointFSlot(const QPointF& val) { pointFs << val; } void lineSlot(const QLine& val) { lines << val; } void lineFSlot(const QLineF& val) { lineFs << val; } void rectSlot(const QRect& val) { rects << val; } void rectFSlot(const QRectF& val) { rectFs << val; } void urlSlot(const QUrl& val) { urls << val; } void localeSlot(const QLocale& val) { locales << val; } void regExpSlot(const QRegExp& val) { regExps << val; } void globalColorSlot(Qt::GlobalColor val) { globalColors << val; } public: QList ints; QList uints; QList qlonglongs; QList qulonglongs; QList bools; QList doubles; //QList chars; "const char*" is not a meta type QList byteArrays; QList bitArrays; QList strings; //QList latin1Strings; "QLatin1String" is not a meta type QList stringLists; QList qchars; QList dates; QList times; QList dateTimes; QList lists; QList maps; QList sizes; QList sizeFs; QList points; QList pointFs; QList lines; QList lineFs; QList rects; QList rectFs; QList urls; QList locales; QList regExps; QList globalColors; }; #endif // RECEIVER_H libqxt-0.6.2/tests/unit/core/slotmapper/sender.h000066400000000000000000000030131215241066400217100ustar00rootroot00000000000000#ifndef SENDER_H #define SENDER_H #include //krazy:exclude=qxtincludes class Sender : public QObject { Q_OBJECT public: Sender() { } signals: void intSignal(int val); void uintSignal(uint val); void qlonglongSignal(qlonglong val); void qulonglongSignal(qulonglong val); void boolSignal(bool val); void doubleSignal(double val); //void charSignal(const char* val); "const char*" is not a meta type void byteArraySignal(const QByteArray& val); void bitArraySignal(const QBitArray& val); void stringSignal(const QString& val); //void latin1StringSignal(const QLatin1String& val); "QLatin1String" is not a meta type void stringListSignal(const QStringList& val); void qcharSignal(const QChar& val); void dateSignal(const QDate& val); void timeSignal(const QTime& val); void dateTimeSignal(const QDateTime& val); void listSignal(const QVariantList& val); void mapSignal(const QVariantMap& val); void sizeSignal(const QSize& val); void sizeFSignal(const QSizeF& val); void pointSignal(const QPoint& val); void pointFSignal(const QPointF& val); void lineSignal(const QLine& val); void lineFSignal(const QLineF& val); void rectSignal(const QRect& val); void rectFSignal(const QRectF& val); void urlSignal(const QUrl& val); void localeSignal(const QLocale& val); void regExpSignal(const QRegExp& val); void globalColorSignal(Qt::GlobalColor val); private: friend class tst_QxtSlotMapper; }; #endif // SENDER_H libqxt-0.6.2/tests/unit/core/slotmapper/slotmapper.pro000066400000000000000000000002471215241066400231750ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = core HEADERS += sender.h receiver.h SOURCES += tst_qxtslotmapper.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/core/slotmapper/tst_qxtslotmapper.cpp000066400000000000000000000446741215241066400246220ustar00rootroot00000000000000#include #include //krazy:exclude=qxtincludes #include #include "sender.h" #include "receiver.h" class tst_QxtSlotMapper : public QObject { Q_OBJECT private slots: void intTest(); void uintTest(); void qlonglongTest(); void qulonglongTest(); void boolTest(); void doubleTest(); //void charTest(); "const char*" is not a meta type void byteArrayTest(); void bitArrayTest(); void stringTest(); //void latin1StringTest(); "QLatin1String" is not a meta type void stringListTest(); void qcharTest(); void dateTest(); void timeTest(); void dateTimeTest(); void listTest(); void mapTest(); void sizeTest(); void sizeFTest(); void pointTest(); void pointFTest(); void lineTest(); void lineFTest(); void rectTest(); void rectFTest(); void urlTest(); void localeTest(); void regExpTest(); void globalColorTest(); }; void tst_QxtSlotMapper::intTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(intSignal(int))); mapper.connect(&sender2, SIGNAL(intSignal(int))); Receiver receiver1; Receiver receiver2; mapper.addMapping(1, &receiver1, SLOT(intSlot(int))); mapper.addMapping(2, &receiver2, SLOT(intSlot(int))); emit sender1.intSignal(1); QCOMPARE(receiver1.ints.value(0), 1); emit sender2.intSignal(2); QCOMPARE(receiver2.ints.at(0), 2); } void tst_QxtSlotMapper::uintTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(uintSignal(uint))); mapper.connect(&sender2, SIGNAL(uintSignal(uint))); Receiver receiver1; Receiver receiver2; mapper.addMapping(1, &receiver1, SLOT(uintSlot(uint))); mapper.addMapping(2, &receiver2, SLOT(uintSlot(uint))); emit sender1.uintSignal(1); QVERIFY(receiver1.uints.value(0) == 1); emit sender2.uintSignal(2); QVERIFY(receiver2.uints.at(0) == 2); } void tst_QxtSlotMapper::qlonglongTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(qlonglongSignal(qlonglong))); mapper.connect(&sender2, SIGNAL(qlonglongSignal(qlonglong))); Receiver receiver1; Receiver receiver2; mapper.addMapping(1, &receiver1, SLOT(qlonglongSlot(qlonglong))); mapper.addMapping(2, &receiver2, SLOT(qlonglongSlot(qlonglong))); emit sender1.qlonglongSignal(1); QVERIFY(receiver1.qlonglongs.value(0) == 1); emit sender2.qlonglongSignal(2); QVERIFY(receiver2.qlonglongs.at(0) == 2); } void tst_QxtSlotMapper::qulonglongTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(qulonglongSignal(qulonglong))); mapper.connect(&sender2, SIGNAL(qulonglongSignal(qulonglong))); Receiver receiver1; Receiver receiver2; mapper.addMapping(1, &receiver1, SLOT(qulonglongSlot(qulonglong))); mapper.addMapping(2, &receiver2, SLOT(qulonglongSlot(qulonglong))); emit sender1.qulonglongSignal(1); QVERIFY(receiver1.qulonglongs.value(0) == 1); emit sender2.qulonglongSignal(2); QVERIFY(receiver2.qulonglongs.at(0) == 2); } void tst_QxtSlotMapper::boolTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(boolSignal(bool))); mapper.connect(&sender2, SIGNAL(boolSignal(bool))); Receiver receiver1; Receiver receiver2; mapper.addMapping(true, &receiver1, SLOT(boolSlot(bool))); mapper.addMapping(false, &receiver2, SLOT(boolSlot(bool))); emit sender1.boolSignal(true); QCOMPARE(receiver1.bools.value(0), true); emit sender2.boolSignal(false); QCOMPARE(receiver2.bools.at(0), false); } void tst_QxtSlotMapper::doubleTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(doubleSignal(double))); mapper.connect(&sender2, SIGNAL(doubleSignal(double))); Receiver receiver1; Receiver receiver2; mapper.addMapping(1.1, &receiver1, SLOT(doubleSlot(double))); mapper.addMapping(2.2, &receiver2, SLOT(doubleSlot(double))); emit sender1.doubleSignal(1.1); QCOMPARE(receiver1.doubles.value(0), 1.1); emit sender2.doubleSignal(2.2); QCOMPARE(receiver2.doubles.at(0), 2.2); } /* "const char*" is not a meta type void tst_QxtSlotMapper::charTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(charSignal(const char*))); mapper.connect(&sender2, SIGNAL(charSignal(const char*))); Receiver receiver1; Receiver receiver2; mapper.addMapping("foo", &receiver1, SLOT(charSlot(const char*))); mapper.addMapping("bar", &receiver2, SLOT(charSlot(const char*))); emit sender1.charSignal("foo"); QCOMPARE(receiver1.chars.value(0), "foo"); emit sender2.charSignal("bar"); QCOMPARE(receiver2.chars.at(0), "bar"); } */ void tst_QxtSlotMapper::byteArrayTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(byteArraySignal(QByteArray))); mapper.connect(&sender2, SIGNAL(byteArraySignal(QByteArray))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QByteArray("foo"), &receiver1, SLOT(byteArraySlot(QByteArray))); mapper.addMapping(QByteArray("bar"), &receiver2, SLOT(byteArraySlot(QByteArray))); emit sender1.byteArraySignal("foo"); QCOMPARE(receiver1.byteArrays.value(0), QByteArray("foo")); emit sender2.byteArraySignal("bar"); QCOMPARE(receiver2.byteArrays.at(0), QByteArray("bar")); } void tst_QxtSlotMapper::bitArrayTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(bitArraySignal(QBitArray))); mapper.connect(&sender2, SIGNAL(bitArraySignal(QBitArray))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QBitArray(1, true), &receiver1, SLOT(bitArraySlot(QBitArray))); mapper.addMapping(QBitArray(2, false), &receiver2, SLOT(bitArraySlot(QBitArray))); emit sender1.bitArraySignal(QBitArray(1, true)); QCOMPARE(receiver1.bitArrays.value(0), QBitArray(1, true)); emit sender2.bitArraySignal(QBitArray(2, false)); QCOMPARE(receiver2.bitArrays.at(0), QBitArray(2, false)); } void tst_QxtSlotMapper::stringTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(stringSignal(QString))); mapper.connect(&sender2, SIGNAL(stringSignal(QString))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QString("foo"), &receiver1, SLOT(stringSlot(QString))); mapper.addMapping(QString("bar"), &receiver2, SLOT(stringSlot(QString))); emit sender1.stringSignal("foo"); QCOMPARE(receiver1.strings.value(0), QString("foo")); emit sender2.stringSignal("bar"); QCOMPARE(receiver2.strings.at(0), QString("bar")); } /* "QLatin1String" is not a meta type void tst_QxtSlotMapper::latin1StringTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(latin1StringSignal(QLatin1String))); mapper.connect(&sender2, SIGNAL(latin1StringSignal(QLatin1String))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QLatin1String("foo"), &receiver1, SLOT(latin1StringSlot(QLatin1String))); mapper.addMapping(QLatin1String("bar"), &receiver2, SLOT(latin1StringSlot(QLatin1String))); emit sender1.latin1StringSignal("foo"); QCOMPARE(receiver1.latin1Strings.value(0), QLatin1String("foo")); emit sender2.latin1StringSignal("bar"); QCOMPARE(receiver2.latin1Strings.at(0), QLatin1String("bar")); } */ void tst_QxtSlotMapper::stringListTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(stringListSignal(QStringList))); mapper.connect(&sender2, SIGNAL(stringListSignal(QStringList))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QStringList("foo"), &receiver1, SLOT(stringListSlot(QStringList))); mapper.addMapping(QStringList("bar"), &receiver2, SLOT(stringListSlot(QStringList))); emit sender1.stringListSignal(QStringList("foo")); QCOMPARE(receiver1.stringLists.value(0), QStringList("foo")); emit sender2.stringListSignal(QStringList("bar")); QCOMPARE(receiver2.stringLists.at(0), QStringList("bar")); } void tst_QxtSlotMapper::qcharTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(qcharSignal(QChar))); mapper.connect(&sender2, SIGNAL(qcharSignal(QChar))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QChar('a'), &receiver1, SLOT(qcharSlot(QChar))); mapper.addMapping(QChar('b'), &receiver2, SLOT(qcharSlot(QChar))); emit sender1.qcharSignal(QChar('a')); QCOMPARE(receiver1.qchars.value(0), QChar('a')); emit sender2.qcharSignal(QChar('b')); QCOMPARE(receiver2.qchars.value(0), QChar('b')); } void tst_QxtSlotMapper::dateTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(dateSignal(QDate))); mapper.connect(&sender2, SIGNAL(dateSignal(QDate))); QDate date1 = QDate::currentDate().addDays(1); QDate date2 = QDate::currentDate().addDays(2); Receiver receiver1; Receiver receiver2; mapper.addMapping(date1, &receiver1, SLOT(dateSlot(QDate))); mapper.addMapping(date2, &receiver2, SLOT(dateSlot(QDate))); emit sender1.dateSignal(date1); QCOMPARE(receiver1.dates.value(0), date1); emit sender2.dateSignal(date2); QCOMPARE(receiver2.dates.value(0), date2); } void tst_QxtSlotMapper::timeTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(timeSignal(QTime))); mapper.connect(&sender2, SIGNAL(timeSignal(QTime))); QTime time1 = QTime::currentTime().addSecs(1); QTime time2 = QTime::currentTime().addSecs(2); Receiver receiver1; Receiver receiver2; mapper.addMapping(time1, &receiver1, SLOT(timeSlot(QTime))); mapper.addMapping(time2, &receiver2, SLOT(timeSlot(QTime))); emit sender1.timeSignal(time1); QCOMPARE(receiver1.times.value(0), time1); emit sender2.timeSignal(time2); QCOMPARE(receiver2.times.value(0), time2); } void tst_QxtSlotMapper::dateTimeTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(dateTimeSignal(QDateTime))); mapper.connect(&sender2, SIGNAL(dateTimeSignal(QDateTime))); QDateTime dateTime1 = QDateTime::currentDateTime().addYears(1); QDateTime dateTime2 = QDateTime::currentDateTime().addYears(2); Receiver receiver1; Receiver receiver2; mapper.addMapping(dateTime1, &receiver1, SLOT(dateTimeSlot(QDateTime))); mapper.addMapping(dateTime2, &receiver2, SLOT(dateTimeSlot(QDateTime))); emit sender1.dateTimeSignal(dateTime1); QCOMPARE(receiver1.dateTimes.value(0), dateTime1); emit sender2.dateTimeSignal(dateTime2); QCOMPARE(receiver2.dateTimes.value(0), dateTime2); } void tst_QxtSlotMapper::listTest() { } void tst_QxtSlotMapper::mapTest() { } void tst_QxtSlotMapper::sizeTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(sizeSignal(QSize))); mapper.connect(&sender2, SIGNAL(sizeSignal(QSize))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QSize(1,1), &receiver1, SLOT(sizeSlot(QSize))); mapper.addMapping(QSize(2,2), &receiver2, SLOT(sizeSlot(QSize))); emit sender1.sizeSignal(QSize(1,1)); QCOMPARE(receiver1.sizes.value(0), QSize(1,1)); emit sender2.sizeSignal(QSize(2,2)); QCOMPARE(receiver2.sizes.value(0), QSize(2,2)); } void tst_QxtSlotMapper::sizeFTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(sizeFSignal(QSizeF))); mapper.connect(&sender2, SIGNAL(sizeFSignal(QSizeF))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QSizeF(1.1,1.1), &receiver1, SLOT(sizeFSlot(QSizeF))); mapper.addMapping(QSizeF(2.2,2.2), &receiver2, SLOT(sizeFSlot(QSizeF))); emit sender1.sizeFSignal(QSizeF(1.1,1.1)); QCOMPARE(receiver1.sizeFs.value(0), QSizeF(1.1,1.1)); emit sender2.sizeFSignal(QSizeF(2.2,2.2)); QCOMPARE(receiver2.sizeFs.value(0), QSizeF(2.2,2.2)); } void tst_QxtSlotMapper::pointTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(pointSignal(QPoint))); mapper.connect(&sender2, SIGNAL(pointSignal(QPoint))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QPoint(1,1), &receiver1, SLOT(pointSlot(QPoint))); mapper.addMapping(QPoint(2,2), &receiver2, SLOT(pointSlot(QPoint))); emit sender1.pointSignal(QPoint(1,1)); QCOMPARE(receiver1.points.value(0), QPoint(1,1)); emit sender2.pointSignal(QPoint(2,2)); QCOMPARE(receiver2.points.value(0), QPoint(2,2)); } void tst_QxtSlotMapper::pointFTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(pointFSignal(QPointF))); mapper.connect(&sender2, SIGNAL(pointFSignal(QPointF))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QPointF(1.1,1.1), &receiver1, SLOT(pointFSlot(QPointF))); mapper.addMapping(QPointF(2.2,2.2), &receiver2, SLOT(pointFSlot(QPointF))); emit sender1.pointFSignal(QPointF(1.1,1.1)); QCOMPARE(receiver1.pointFs.value(0), QPointF(1.1,1.1)); emit sender2.pointFSignal(QPointF(2.2,2.2)); QCOMPARE(receiver2.pointFs.value(0), QPointF(2.2,2.2)); } void tst_QxtSlotMapper::lineTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(lineSignal(QLine))); mapper.connect(&sender2, SIGNAL(lineSignal(QLine))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QLine(1,1,1,1), &receiver1, SLOT(lineSlot(QLine))); mapper.addMapping(QLine(2,2,2,2), &receiver2, SLOT(lineSlot(QLine))); emit sender1.lineSignal(QLine(1,1,1,1)); QCOMPARE(receiver1.lines.value(0), QLine(1,1,1,1)); emit sender2.lineSignal(QLine(2,2,2,2)); QCOMPARE(receiver2.lines.value(0), QLine(2,2,2,2)); } void tst_QxtSlotMapper::lineFTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(lineFSignal(QLineF))); mapper.connect(&sender2, SIGNAL(lineFSignal(QLineF))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QLineF(1.1,1.1,1.1,1.1), &receiver1, SLOT(lineFSlot(QLineF))); mapper.addMapping(QLineF(2.2,2.2,2.2,2.2), &receiver2, SLOT(lineFSlot(QLineF))); emit sender1.lineFSignal(QLineF(1.1,1.1,1.1,1.1)); QCOMPARE(receiver1.lineFs.value(0), QLineF(1.1,1.1,1.1,1.1)); emit sender2.lineFSignal(QLineF(2.2,2.2,2.2,2.2)); QCOMPARE(receiver2.lineFs.value(0), QLineF(2.2,2.2,2.2,2.2)); } void tst_QxtSlotMapper::rectTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(rectSignal(QRect))); mapper.connect(&sender2, SIGNAL(rectSignal(QRect))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QRect(1,1,1,1), &receiver1, SLOT(rectSlot(QRect))); mapper.addMapping(QRect(2,2,2,2), &receiver2, SLOT(rectSlot(QRect))); emit sender1.rectSignal(QRect(1,1,1,1)); QCOMPARE(receiver1.rects.value(0), QRect(1,1,1,1)); emit sender2.rectSignal(QRect(2,2,2,2)); QCOMPARE(receiver2.rects.value(0), QRect(2,2,2,2)); } void tst_QxtSlotMapper::rectFTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(rectFSignal(QRectF))); mapper.connect(&sender2, SIGNAL(rectFSignal(QRectF))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QRectF(1.1,1.1,1.1,1.1), &receiver1, SLOT(rectFSlot(QRectF))); mapper.addMapping(QRectF(2.2,2.2,2.2,2.2), &receiver2, SLOT(rectFSlot(QRectF))); emit sender1.rectFSignal(QRectF(1.1,1.1,1.1,1.1)); QCOMPARE(receiver1.rectFs.value(0), QRectF(1.1,1.1,1.1,1.1)); emit sender2.rectFSignal(QRectF(2.2,2.2,2.2,2.2)); QCOMPARE(receiver2.rectFs.value(0), QRectF(2.2,2.2,2.2,2.2)); } void tst_QxtSlotMapper::urlTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(urlSignal(QUrl))); mapper.connect(&sender2, SIGNAL(urlSignal(QUrl))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QUrl("1"), &receiver1, SLOT(urlSlot(QUrl))); mapper.addMapping(QUrl("2"), &receiver2, SLOT(urlSlot(QUrl))); emit sender1.urlSignal(QUrl("1")); QCOMPARE(receiver1.urls.value(0), QUrl("1")); emit sender2.urlSignal(QUrl("2")); QCOMPARE(receiver2.urls.value(0), QUrl("2")); } void tst_QxtSlotMapper::localeTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(localeSignal(QLocale))); mapper.connect(&sender2, SIGNAL(localeSignal(QLocale))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QLocale("en"), &receiver1, SLOT(localeSlot(QLocale))); mapper.addMapping(QLocale("fi"), &receiver2, SLOT(localeSlot(QLocale))); emit sender1.localeSignal(QLocale("en")); QCOMPARE(receiver1.locales.value(0), QLocale("en")); emit sender2.localeSignal(QLocale("fi")); QCOMPARE(receiver2.locales.value(0), QLocale("fi")); } void tst_QxtSlotMapper::regExpTest() { QxtSlotMapper mapper; Sender sender1; Sender sender2; mapper.connect(&sender1, SIGNAL(regExpSignal(QRegExp))); mapper.connect(&sender2, SIGNAL(regExpSignal(QRegExp))); Receiver receiver1; Receiver receiver2; mapper.addMapping(QRegExp("foo"), &receiver1, SLOT(regExpSlot(QRegExp))); mapper.addMapping(QRegExp("bar"), &receiver2, SLOT(regExpSlot(QRegExp))); emit sender1.regExpSignal(QRegExp("foo")); QCOMPARE(receiver1.regExps.value(0), QRegExp("foo")); emit sender2.regExpSignal(QRegExp("bar")); QCOMPARE(receiver2.regExps.value(0), QRegExp("bar")); } void tst_QxtSlotMapper::globalColorTest() { } QTEST_MAIN(tst_QxtSlotMapper) #include "tst_qxtslotmapper.moc" libqxt-0.6.2/tests/unit/gui/000077500000000000000000000000001215241066400157305ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/gui/gui.pro000066400000000000000000000004541215241066400172410ustar00rootroot00000000000000###################################################################### # Automatically generated by qmake (2.01a) Fri Jan 16 22:24:22 2009 ###################################################################### TEMPLATE = subdirs SUBDIRS += unit test.CONFIG += recursive QMAKE_EXTRA_TARGETS += test libqxt-0.6.2/tests/unit/gui/unit/000077500000000000000000000000001215241066400167075ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/gui/unit/main.cpp000066400000000000000000000445761215241066400203570ustar00rootroot00000000000000#include #include #include class TestQxtGui : public QObject { Q_OBJECT private slots: void testQxtApplication(); void testQxtCheckComboBox_data(); void testQxtCheckComboBox(); void testQxtConfigDialog(); void testQxtConfirmationMessage(); void testQxtWindowSystem(); void testQxtDockWidget(); void testQxtGroupBox(); void testQxtItemDelegate(); void testQxtLabel(); void testQxtListWidget_data(); void testQxtListWidget(); void testQxtProgressLabel(); void testQxtProxyStyle(); void testQxtPushButton(); void testQxtSpanSlider(); void testQxtStars(); void testQxtStringSpinBox(); void testQxtTableWidget_data(); void testQxtTableWidget(); void testQxtTabWidget(); void testQxtToolTip(); void testQxtTreeWidget_data(); void testQxtTreeWidget(); }; void TestQxtGui::testQxtApplication() { // See: test/app } void TestQxtGui::testQxtCheckComboBox_data() { QTest::addColumn("popup"); QTest::addColumn("select"); QTest::addColumn("close"); QTest::addColumn("expected"); QTestEventList popup1; popup1.addKeyClick(Qt::Key_Up); // popup QTestEventList popup2; popup2.addKeyClick(Qt::Key_Down); // popup QTestEventList close1; close1.addKeyClick(Qt::Key_Escape); // close QTestEventList select0; QStringList result0; QTestEventList select1; select1.addKeyClick(Qt::Key_Space); // select first select1.addKeyClick(Qt::Key_Down); // move to second select1.addKeyClick(Qt::Key_Down); // move to third select1.addKeyClick(Qt::Key_Space); // select third QStringList result1 = QStringList() << "1" << "3"; QTestEventList select2; select2.addKeyClick(Qt::Key_Down); // move to second select2.addKeyClick(Qt::Key_Down); // move to third select2.addKeyClick(Qt::Key_Up); // move back to second select2.addKeyClick(Qt::Key_Space); // select second QStringList result2 = QStringList() << "2"; QTest::newRow("-") << popup1 << select0 << close1 << result0; QTest::newRow("1,3") << popup1 << select1 << close1 << result1; QTest::newRow("2") << popup2 << select2 << close1 << result2; } void TestQxtGui::testQxtCheckComboBox() { QFETCH(QTestEventList, popup); QFETCH(QTestEventList, select); QFETCH(QTestEventList, close); QFETCH(QStringList, expected); QxtCheckComboBox combo; combo.addItems(QStringList() << "1" << "2" << "3" << "4"); QSignalSpy spy(&combo, SIGNAL(checkedItemsChanged(const QStringList&))); QVERIFY(spy.isValid()); popup.simulate(&combo); select.simulate(combo.view()); close.simulate(&combo); QCOMPARE(combo.checkedItems(), expected); if (!combo.checkedItems().isEmpty()) { QVERIFY(spy.count() > 0); while (!spy.isEmpty()) { QList arguments = spy.takeFirst(); QVERIFY(arguments.at(0).type() == QVariant::StringList); } } else { QVERIFY(spy.count() == 0); } } void TestQxtGui::testQxtConfigDialog() { // See: test/app, demos/configdialog } void TestQxtGui::testQxtConfirmationMessage() { // See: test/app } void TestQxtGui::testQxtWindowSystem() { #ifndef Q_WS_MAC // See: demos/qxtsnapshot WId activeId = QxtWindowSystem::activeWindow(); QString activeTitle = QxtWindowSystem::windowTitle(activeId); WId foundId = QxtWindowSystem::findWindow(activeTitle); QString foundTitle = QxtWindowSystem::windowTitle(foundId); QRect activeRect = QxtWindowSystem::windowGeometry(activeId); WId atId = QxtWindowSystem::windowAt(activeRect.center()); QString atTitle = QxtWindowSystem::windowTitle(atId); QVERIFY(activeId == foundId); QVERIFY(foundId == atId); QVERIFY(activeTitle == foundTitle); QVERIFY(foundTitle == atTitle); #endif } void TestQxtGui::testQxtDockWidget() { // See: demos/dockwidgets } void TestQxtGui::testQxtGroupBox() { // See: test/app } void TestQxtGui::testQxtItemDelegate() { // See: // - testQxtListWidget() // - testQxtTableWidget() // - testQxtTreeWidget() } void TestQxtGui::testQxtLabel() { QxtLabel label("Text"); QTestEventList events; events.addMouseClick(Qt::LeftButton); QSignalSpy clicked(&label, SIGNAL(clicked())); QSignalSpy textChanged(&label, SIGNAL(textChanged(const QString&))); QVERIFY(clicked.isValid()); QVERIFY(textChanged.isValid()); events.simulate(&label); label.setText("Changed"); QCOMPARE(clicked.count(), 1); QCOMPARE(textChanged.count(), 1); QList arguments = clicked.takeFirst(); QVERIFY(arguments.isEmpty()); arguments = textChanged.takeFirst(); QVERIFY(arguments.at(0).toString() == "Changed"); } void TestQxtGui::testQxtListWidget_data() { QTest::addColumn("events"); QTest::addColumn("amount"); QTestEventList all; for (int i = 0; i < 10; ++i) { all.addKeyClick(Qt::Key_Down); // select/finish edit all.addKeyClick(Qt::Key_Space); // check all.addKeyClick(Qt::Key_F2); // start edit } all.addKeyClick(Qt::Key_Up); QTest::newRow("all checked") << all << 10; QTestEventList second; for (int i = 0; i < 10; i += 2) { second.addKeyClick(Qt::Key_Down); // select second.addKeyClick(Qt::Key_Space); // check second.addKeyClick(Qt::Key_F2); // start edit second.addKeyClick(Qt::Key_Escape); // finish edit } second.addKeyClick(Qt::Key_Up); QTest::newRow("every second checked") << second << 5; QTestEventList none; QTest::newRow("none checked") << none << 0; } void TestQxtGui::testQxtListWidget() { QFETCH(QTestEventList, events); QFETCH(int, amount); QxtListWidget listWidget; listWidget.setEditTriggers(QAbstractItemView::EditKeyPressed); for (int i = 0; i < 10; ++i) { QxtListWidgetItem* item = new QxtListWidgetItem(QString::number(i), &listWidget); item->setFlag(Qt::ItemIsUserCheckable); item->setFlag(Qt::ItemIsEditable); item->setCheckState(Qt::Unchecked); } qRegisterMetaType("QListWidgetItem*"); qRegisterMetaType("QxtListWidgetItem*"); QSignalSpy editStarted(&listWidget, SIGNAL(itemEditingStarted(QListWidgetItem*))); QSignalSpy editFinished(&listWidget, SIGNAL(itemEditingFinished(QListWidgetItem*))); QSignalSpy checkChanged(&listWidget, SIGNAL(itemCheckStateChanged(QxtListWidgetItem*))); QVERIFY(editStarted.isValid()); QVERIFY(editFinished.isValid()); QVERIFY(checkChanged.isValid()); events.simulate(listWidget.viewport()); QList checkedItems; for (int i = 0; i < 10; ++i) { QListWidgetItem* item = listWidget.item(i); if (item && item->data(Qt::CheckStateRole).toInt() == Qt::Checked) checkedItems += item; } QCOMPARE(checkChanged.count(), checkedItems.count()); QCOMPARE(editStarted.count(), amount); QCOMPARE(editFinished.count(), amount); } void TestQxtGui::testQxtProgressLabel() { // See: test/app } void TestQxtGui::testQxtProxyStyle() { // Nothing to test } void TestQxtGui::testQxtPushButton() { // See: test/app } void TestQxtGui::testQxtStars() { // See: test/app } void TestQxtGui::testQxtSpanSlider() { QxtSpanSlider slider; slider.setRange(0, 99); QSignalSpy spanChanged(&slider, SIGNAL(spanChanged(int, int))); QSignalSpy lowerChanged(&slider, SIGNAL(lowerValueChanged(int))); QSignalSpy upperChanged(&slider, SIGNAL(upperValueChanged(int))); QVERIFY(spanChanged.isValid()); QVERIFY(lowerChanged.isValid()); QVERIFY(upperChanged.isValid()); // #1 setSpan() - basic change slider.setSpan(4, 75); QCOMPARE(slider.lowerValue(), 4); QCOMPARE(slider.upperValue(), 75); QCOMPARE(spanChanged.count(), 1); QCOMPARE(lowerChanged.count(), 1); QCOMPARE(upperChanged.count(), 1); QList args = spanChanged.takeLast(); QVERIFY(args.at(0).toInt() == 4); QVERIFY(args.at(1).toInt() == 75); QVERIFY(lowerChanged.takeLast().at(0).toInt() == 4); QVERIFY(upperChanged.takeLast().at(0).toInt() == 75); // #2 setSpan() - no change slider.setSpan(75, 4); QCOMPARE(slider.lowerValue(), 4); QCOMPARE(slider.upperValue(), 75); QCOMPARE(spanChanged.count(), 0); QCOMPARE(lowerChanged.count(), 0); QCOMPARE(upperChanged.count(), 0); // #3 setSpan() - inverse span slider.setSpan(66, 33); QCOMPARE(slider.lowerValue(), 33); QCOMPARE(slider.upperValue(), 66); QCOMPARE(spanChanged.count(), 1); QCOMPARE(lowerChanged.count(), 1); QCOMPARE(upperChanged.count(), 1); args = spanChanged.takeLast(); QVERIFY(args.at(0).toInt() == 33); QVERIFY(args.at(1).toInt() == 66); QVERIFY(lowerChanged.takeLast().at(0).toInt() == 33); QVERIFY(upperChanged.takeLast().at(0).toInt() == 66); // #4 setSpan() - keep span in range slider.setSpan(-400, 400); QCOMPARE(slider.lowerValue(), 0); QCOMPARE(slider.upperValue(), 99); QCOMPARE(spanChanged.count(), 1); QCOMPARE(lowerChanged.count(), 1); QCOMPARE(upperChanged.count(), 1); args = spanChanged.takeLast(); QVERIFY(args.at(0).toInt() == 0); QVERIFY(args.at(1).toInt() == 99); QVERIFY(lowerChanged.takeLast().at(0).toInt() == 0); QVERIFY(upperChanged.takeLast().at(0).toInt() == 99); // #5 setLowerValue() - basic change slider.setLowerValue(3); QCOMPARE(slider.lowerValue(), 3); QCOMPARE(slider.upperValue(), 99); QCOMPARE(spanChanged.count(), 1); QCOMPARE(lowerChanged.count(), 1); QCOMPARE(upperChanged.count(), 0); args = spanChanged.takeLast(); QVERIFY(args.at(0).toInt() == 3); QVERIFY(args.at(1).toInt() == 99); QVERIFY(lowerChanged.takeLast().at(0).toInt() == 3); // #6 setLowerValue() - no change slider.setLowerValue(3); QCOMPARE(slider.lowerValue(), 3); QCOMPARE(slider.upperValue(), 99); QCOMPARE(spanChanged.count(), 0); QCOMPARE(lowerChanged.count(), 0); QCOMPARE(upperChanged.count(), 0); // #7 setLowerValue() - keep span in range slider.setLowerValue(-3); QCOMPARE(slider.lowerValue(), 0); QCOMPARE(slider.upperValue(), 99); QCOMPARE(spanChanged.count(), 1); QCOMPARE(lowerChanged.count(), 1); QCOMPARE(upperChanged.count(), 0); args = spanChanged.takeLast(); QVERIFY(args.at(0).toInt() == 0); QVERIFY(args.at(1).toInt() == 99); QVERIFY(lowerChanged.takeLast().at(0).toInt() == 0); // #8 setUpperValue() - basic change slider.setUpperValue(77); QCOMPARE(slider.lowerValue(), 0); QCOMPARE(slider.upperValue(), 77); QCOMPARE(spanChanged.count(), 1); QCOMPARE(lowerChanged.count(), 0); QCOMPARE(upperChanged.count(), 1); args = spanChanged.takeLast(); QVERIFY(args.at(0).toInt() == 0); QVERIFY(args.at(1).toInt() == 77); QVERIFY(upperChanged.takeLast().at(0).toInt() == 77); // #9 setUpperValue() - no change slider.setUpperValue(77); QCOMPARE(slider.lowerValue(), 0); QCOMPARE(slider.upperValue(), 77); QCOMPARE(spanChanged.count(), 0); QCOMPARE(lowerChanged.count(), 0); QCOMPARE(upperChanged.count(), 0); // #10 setUpperValue() - keep span in range slider.setUpperValue(111); QCOMPARE(slider.lowerValue(), 0); QCOMPARE(slider.upperValue(), 99); QCOMPARE(spanChanged.count(), 1); QCOMPARE(lowerChanged.count(), 0); QCOMPARE(upperChanged.count(), 1); args = spanChanged.takeLast(); QVERIFY(args.at(0).toInt() == 0); QVERIFY(args.at(1).toInt() == 99); QVERIFY(upperChanged.takeLast().at(0).toInt() == 99); // #11 setLowerValue(), setUpperValue() - inverse span slider.setLowerValue(66); // a: lower->66,upper=99 slider.setUpperValue(33); // b: lower->33,upper->66 slider.setLowerValue(77); // c: lower->66,upper->77 QCOMPARE(spanChanged.count(), 3); QCOMPARE(lowerChanged.count(), 3); QCOMPARE(upperChanged.count(), 2); // a args = spanChanged.takeFirst(); QVERIFY(args.at(0).toInt() == 66); QVERIFY(args.at(1).toInt() == 99); QVERIFY(lowerChanged.takeFirst().at(0).toInt() == 66); // b args = spanChanged.takeFirst(); QVERIFY(args.at(0).toInt() == 33); QVERIFY(args.at(1).toInt() == 66); QVERIFY(lowerChanged.takeFirst().at(0).toInt() == 33); QVERIFY(upperChanged.takeFirst().at(0).toInt() == 66); // c args = spanChanged.takeFirst(); QVERIFY(args.at(0).toInt() == 66); QVERIFY(args.at(1).toInt() == 77); QVERIFY(lowerChanged.takeFirst().at(0).toInt() == 66); QVERIFY(upperChanged.takeFirst().at(0).toInt() == 77); // # 12 change of range slider.setRange(68, 72); QCOMPARE(slider.lowerValue(), 68); QCOMPARE(slider.upperValue(), 72); QCOMPARE(spanChanged.count(), 1); QCOMPARE(lowerChanged.count(), 1); QCOMPARE(upperChanged.count(), 1); args = spanChanged.takeLast(); QVERIFY(args.at(0).toInt() == 68); QVERIFY(args.at(1).toInt() == 72); QVERIFY(lowerChanged.takeLast().at(0).toInt() == 68); QVERIFY(upperChanged.takeLast().at(0).toInt() == 72); } void TestQxtGui::testQxtStringSpinBox() { QStringList strings; for (int i = 0; i < 10; ++i) strings += QString::number(i); QxtStringSpinBox spinBox; spinBox.setStrings(strings); QTestEventList up; up.addKeyClick(Qt::Key_Up); QTestEventList down; down.addKeyClick(Qt::Key_Down); for (int i = 0; i < 10; ++i) { QCOMPARE(spinBox.cleanText(), QString::number(i)); up.simulate(&spinBox); QCOMPARE(spinBox.cleanText(), QString::number(qMin(i+1, 9))); } for (int i = 9; i >= 0; --i) { QCOMPARE(spinBox.cleanText(), QString::number(i)); down.simulate(&spinBox); QCOMPARE(spinBox.cleanText(), QString::number(qMax(i-1, 0))); } } void TestQxtGui::testQxtTableWidget_data() { QTest::addColumn("events"); QTest::addColumn("amount"); QTestEventList all; all.addKeyClick(Qt::Key_Tab); // select first all.addKeyClick(Qt::Key_F2); // start editing all.addKeyClick(Qt::Key_Tab); // select second all.addKeyClick(Qt::Key_F2); // start editing all.addKeyClick(Qt::Key_Tab); // select third all.addKeyClick(Qt::Key_F2); // start editing all.addKeyClick(Qt::Key_Tab); // select fourth all.addKeyClick(Qt::Key_F2); // start editing all.addKeyClick(Qt::Key_Tab); // finish editing QTest::newRow("all edited") << all << 4; QTestEventList second; second.addKeyClick(Qt::Key_Tab); // select second second.addKeyClick(Qt::Key_Tab); second.addKeyClick(Qt::Key_F2); // edit second.addKeyClick(Qt::Key_Tab); // select fourth second.addKeyClick(Qt::Key_Tab); second.addKeyClick(Qt::Key_F2); // edit second.addKeyClick(Qt::Key_Tab); // abort QTest::newRow("every second edited") << second << 2; QTestEventList none; QTest::newRow("none edited") << none << 0; } void TestQxtGui::testQxtTableWidget() { QFETCH(QTestEventList, events); QFETCH(int, amount); QxtTableWidget tableWidget(2, 2); tableWidget.setEditTriggers(QAbstractItemView::EditKeyPressed); qRegisterMetaType("QTableWidgetItem*"); QSignalSpy editStarted(&tableWidget, SIGNAL(itemEditingStarted(QTableWidgetItem*))); QSignalSpy editFinished(&tableWidget, SIGNAL(itemEditingFinished(QTableWidgetItem*))); QVERIFY(editStarted.isValid()); QVERIFY(editFinished.isValid()); events.simulate(tableWidget.viewport()); QCOMPARE(editStarted.count(), amount); QCOMPARE(editFinished.count(), amount); } void TestQxtGui::testQxtTabWidget() { QxtTabWidget tabWidget; tabWidget.setTabContextMenuPolicy(Qt::ActionsContextMenu); tabWidget.addTab(new QLabel("1"), "1"); tabWidget.addTab(new QLabel("2"), "2"); tabWidget.addTab(new QLabel("3"), "3"); QPointer act1a = new QAction("1a", &tabWidget); QPointer act1b = new QAction("1b", &tabWidget); QPointer act2 = new QAction("2", &tabWidget); tabWidget.addTabAction(1, act2); QCOMPARE(tabWidget.tabActions(0).count(), 0); QCOMPARE(tabWidget.tabActions(1).count(), 1); QCOMPARE(tabWidget.tabActions(2).count(), 0); QPointer act3 = tabWidget.addTabAction(2, "3"); QCOMPARE(tabWidget.tabActions(0).count(), 0); QCOMPARE(tabWidget.tabActions(1).count(), 1); QCOMPARE(tabWidget.tabActions(2).count(), 1); QList actions; actions << act1a << act1b; tabWidget.addTabActions(0, actions); QCOMPARE(tabWidget.tabActions(0).count(), 2); QCOMPARE(tabWidget.tabActions(1).count(), 1); QCOMPARE(tabWidget.tabActions(2).count(), 1); tabWidget.clearTabActions(0); QCOMPARE(tabWidget.tabActions(0).count(), 0); QCOMPARE(tabWidget.tabActions(1).count(), 1); QCOMPARE(tabWidget.tabActions(2).count(), 1); QVERIFY(act1a == 0 && act1b == 0); // must have been deleted tabWidget.removeTabAction(1, act2); QCOMPARE(tabWidget.tabActions(0).count(), 0); QCOMPARE(tabWidget.tabActions(1).count(), 0); QCOMPARE(tabWidget.tabActions(2).count(), 1); QVERIFY(act2 != 0); // must not have been deleted tabWidget.insertTabAction(2, act3, act2); QCOMPARE(tabWidget.tabActions(0).count(), 0); QCOMPARE(tabWidget.tabActions(1).count(), 0); QCOMPARE(tabWidget.tabActions(2).count(), 2); QVERIFY(tabWidget.tabActions(2).first() == act2); QVERIFY(tabWidget.tabActions(2).last() == act3); } void TestQxtGui::testQxtToolTip() { // See demos/qxtsnapshot } void TestQxtGui::testQxtTreeWidget_data() { QTest::addColumn("events"); QTest::addColumn("amount"); QTestEventList all; for (int i = 0; i < 10; ++i) { all.addKeyClick(Qt::Key_Down); // select next all.addKeyClick(Qt::Key_Space); // check all.addKeyClick(Qt::Key_F2); // start editing } all.addKeyClick(Qt::Key_Up); QTest::newRow("all checked") << all << 10; QTestEventList second; for (int i = 0; i < 10; i += 2) { second.addKeyClick(Qt::Key_Down); // select second.addKeyClick(Qt::Key_Space); // check second.addKeyClick(Qt::Key_F2); // start edit second.addKeyClick(Qt::Key_Escape); // finish edit } second.addKeyClick(Qt::Key_Up); QTest::newRow("every second checked") << second << 5; QTestEventList none; QTest::newRow("none checked") << none << 0; } void TestQxtGui::testQxtTreeWidget() { QFETCH(QTestEventList, events); QFETCH(int, amount); QxtTreeWidget treeWidget; treeWidget.setColumnCount(1); treeWidget.setEditTriggers(QAbstractItemView::EditKeyPressed); for (int i = 0; i < 10; ++i) { QxtTreeWidgetItem* item = new QxtTreeWidgetItem(&treeWidget, QStringList(QString::number(i))); item->setFlag(Qt::ItemIsEditable); item->setFlag(Qt::ItemIsUserCheckable); item->setCheckState(0, Qt::Unchecked); } qRegisterMetaType("QTreeWidgetItem*"); qRegisterMetaType("QxtTreeWidgetItem*"); QSignalSpy editStarted(&treeWidget, SIGNAL(itemEditingStarted(QTreeWidgetItem*))); QSignalSpy editFinished(&treeWidget, SIGNAL(itemEditingFinished(QTreeWidgetItem*))); QSignalSpy checkChanged(&treeWidget, SIGNAL(itemCheckStateChanged(QxtTreeWidgetItem*))); QVERIFY(editStarted.isValid()); QVERIFY(editFinished.isValid()); QVERIFY(checkChanged.isValid()); events.simulate(treeWidget.viewport()); QList checkedItems; for (int i = 0; i < 10; ++i) { QTreeWidgetItem* item = treeWidget.topLevelItem(i); if (item && item->data(0, Qt::CheckStateRole).toInt() == Qt::Checked) checkedItems += item; } QCOMPARE(checkChanged.count(), checkedItems.count()); QCOMPARE(editStarted.count(), amount); QCOMPARE(editFinished.count(), amount); } QTEST_MAIN(TestQxtGui) #include "main.moc" libqxt-0.6.2/tests/unit/gui/unit/unit.pro000066400000000000000000000002031215241066400204030ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core gui QXT = core gui SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/network/000077500000000000000000000000001215241066400166355ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/network/network.pro000066400000000000000000000004531215241066400210520ustar00rootroot00000000000000###################################################################### # Automatically generated by qmake (2.01a) Fri Jan 16 22:24:46 2009 ###################################################################### TEMPLATE = subdirs SUBDIRS += rpc test.CONFIG += recursive QMAKE_EXTRA_TARGETS += test libqxt-0.6.2/tests/unit/network/rpc/000077500000000000000000000000001215241066400174215ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/network/rpc/main.cpp000066400000000000000000000125611215241066400210560ustar00rootroot00000000000000/** ***** QxtRPCPeer loopback test ******/ #include #include #include #include #include #include #include #include #include #include class RPCTest: public QObject { Q_OBJECT public: RPCTest() : client_id(0) {} private: quint64 client_id; signals: void wave(QString); void counterwave(QString); void networkedwave(quint64,QString); private slots: void initTestCase() { client_id = 0; } void clientConnected(quint64 id) { client_id = id; } void serverError(QAbstractSocket::SocketError e) { if (e != QAbstractSocket::RemoteHostClosedError) { qCritical("socket error: %i", e); QVERIFY2(false, "socket error"); } } void loopback() { QxtRPCService peer(new QxtFifo, 0); QVERIFY2(peer.attachSignal (this, SIGNAL( wave ( QString ) ) ),"cannot attach signal"); QVERIFY2(peer.attachSlot ( SIGNAL( wave ( QString ) ),this, SIGNAL( counterwave(QString )) ),"cannot attach slot"); QSignalSpy spy(this, SIGNAL(counterwave(QString))); QSignalSpy spyr(peer.device(), SIGNAL(readyRead())); emit(wave("world")); QCoreApplication::processEvents (); QCoreApplication::processEvents (); QVERIFY2 (spyr.count()> 0, "buffer not emitting readyRead" ); QVERIFY2 (spy.count()> 0, "no signal received" ); QVERIFY2 (spy.count()< 2, "wtf, two signals received?" ); QList arguments = spy.takeFirst(); QVERIFY2(arguments.at(0).toString()=="world","argument missmatch"); } void directcall() { QxtRPCService peer(new QxtFifo, 0); QVERIFY2(peer.attachSlot ( SIGNAL( wave ( QString ) ),this, SIGNAL( counterwave(QString )) ),"cannot attach slot"); QSignalSpy spy(this, SIGNAL(counterwave(QString))); QSignalSpy spyr(peer.device(), SIGNAL(readyRead())); peer.call(SIGNAL(wave ( QString ) ),QString("world")); QCoreApplication::processEvents (); QCoreApplication::processEvents (); QVERIFY2 (spyr.count()> 0, "buffer not emitting readyRead" ); QVERIFY2 (spy.count()> 0, "no signal received" ); QVERIFY2 (spy.count()< 2, "wtf, two signals received?" ); QList arguments = spy.takeFirst(); QVERIFY2(arguments.at(0).toString()=="world","argument missmatch"); } void TcpServerIo() { QxtRPCPeer server; QVERIFY2(server.attachSlot (SIGNAL(wave(QString)),this,SIGNAL(networkedwave(quint64,QString))),"cannot attach slot"); QVERIFY(server.listen (QHostAddress::LocalHost, 23444)); QxtRPCPeer client; client.connect (QHostAddress::LocalHost, 23444); QVERIFY(qobject_cast(client.device())->waitForConnected ( 30000 )); QSignalSpy spy(this, SIGNAL(networkedwave(quint64,QString))); client.call(SIGNAL(wave(QString)),QString("world")); QCoreApplication::processEvents (); QThread::yieldCurrentThread(); QCoreApplication::processEvents (); QThread::yieldCurrentThread(); QCoreApplication::processEvents (); QThread::yieldCurrentThread(); QCoreApplication::processEvents (); QVERIFY2 (spy.count()> 0, "no signal received" ); QVERIFY2 (spy.count()< 2, "wtf, two signals received?" ); QList arguments = spy.takeFirst(); QVERIFY2(arguments.at(1).toString()=="world","argument missmatch"); } void TcpServerIoDisconnect() { // check that disconnect from server doesn't crash client (which it did in 0.5.1) QxtRPCPeer server; QVERIFY2(connect(&server, SIGNAL(clientConnected(quint64)),this,SLOT(clientConnected(quint64))),"cannot connect"); QVERIFY2(connect(&server, SIGNAL(serverError(QAbstractSocket::SocketError)),this,SLOT(serverError(QAbstractSocket::SocketError))),"cannot connect"); QVERIFY(server.listen (QHostAddress::LocalHost, 23444)); QVERIFY(client_id == 0); QxtRPCPeer client; client.connect (QHostAddress::LocalHost, 23444); QVERIFY2(connect(&client, SIGNAL(serverError(QAbstractSocket::SocketError)),this,SLOT(serverError(QAbstractSocket::SocketError))),"cannot connect"); QVERIFY(qobject_cast(client.device())->waitForConnected ( 30000 )); QCoreApplication::processEvents (); QThread::yieldCurrentThread(); QCoreApplication::processEvents (); QThread::yieldCurrentThread(); QCoreApplication::processEvents (); QThread::yieldCurrentThread(); QCoreApplication::processEvents (); QCoreApplication::processEvents (); QCoreApplication::processEvents (); QVERIFY(client.isClient()); QVERIFY(client_id != 0); server.disconnectClient(client_id); QCoreApplication::processEvents (); QThread::yieldCurrentThread(); QCoreApplication::processEvents (); QThread::yieldCurrentThread(); QCoreApplication::processEvents (); QThread::yieldCurrentThread(); QCoreApplication::processEvents (); QVERIFY(server.isServer()); QVERIFY(!client.isClient()); } void cleanupTestCase() {} }; QTEST_MAIN(RPCTest) #include "main.moc" libqxt-0.6.2/tests/unit/network/rpc/rpc.pro000066400000000000000000000001761215241066400207330ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = network SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/sql/000077500000000000000000000000001215241066400157435ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/sql/sql.pro000066400000000000000000000004341215241066400172650ustar00rootroot00000000000000###################################################################### # Automatically generated by qmake (2.01a) Fri Jan 16 22:25:17 2009 ###################################################################### TEMPLATE = subdirs test.CONFIG += recursive QMAKE_EXTRA_TARGETS += test libqxt-0.6.2/tests/unit/unit.pri000066400000000000000000000005131215241066400166360ustar00rootroot00000000000000CONFIG += qtestlib CONFIG -= app_bundle include($$QXT_SOURCE_TREE/src/qxtlibs.pri) test.depends = first !isEmpty(DESTDIR):test.commands += cd $(DESTDIR) && unix { test.commands += ./$(TARGET) } else:win32 { DESTDIR = ./ test.CONFIG += recursive build_pass:test.commands += $(TARGET) } QMAKE_EXTRA_TARGETS += test libqxt-0.6.2/tests/unit/unit.pro000066400000000000000000000012331215241066400166440ustar00rootroot00000000000000###################################################################### # Automatically generated by qmake (2.01a) Fri Jan 30 20:13:42 2009 ###################################################################### TEMPLATE = subdirs contains(DEFINES,HAVE_DB):contains(QXT_MODULES, berkeley):SUBDIRS += berkeley contains(QXT_MODULES, core):SUBDIRS += core contains(QXT_MODULES, gui):SUBDIRS += gui contains(QXT_MODULES, network):SUBDIRS += network contains(QXT_MODULES, sql):SUBDIRS += sql contains(QXT_MODULES, web):SUBDIRS += web #contains(DEFINES,HAVE_ZEROCONF):contains(QXT_MODULES, zeroconf):SUBDIRS += zeroconf test.CONFIG += recursive QMAKE_EXTRA_TARGETS += test libqxt-0.6.2/tests/unit/web/000077500000000000000000000000001215241066400157215ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/web/async/000077500000000000000000000000001215241066400170365ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/web/async/async.pro000066400000000000000000000001721215241066400206750ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = web SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/web/async/main.cpp000066400000000000000000000024401215241066400204660ustar00rootroot00000000000000#include #include #include #include #include class test : public QxtWebController { Q_OBJECT public: test():QxtWebController("root") { } public slots: int index() { QTimer::singleShot(20,this,SLOT(async())); echo()<<"foo"; return 2; } private slots: void async() { QxtWebCore::send("bar"); QxtWebCore::close(); } }; class err : public QxtWebController { Q_OBJECT public: err():QxtWebController("error") { } public slots: int index(QString a=QString("500"),QString b=QString(),QString c=QString(),QString d=QString(), QString e=QString(),QString f=QString(),QString g=QString()) { echo()<<"shits
" "error "<" <" <" <" <" <" <"; return 0; } }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QxtWebCore core(new QxtScgiConnector()); core.start(4000); test t; err e; return app.exec(); } #include "main.moc" libqxt-0.6.2/tests/unit/web/cgi/000077500000000000000000000000001215241066400164635ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/web/cgi/cgi.pro000066400000000000000000000000531215241066400177450ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS = server client libqxt-0.6.2/tests/unit/web/cgi/cgiclient.php000077500000000000000000000010421215241066400211350ustar00rootroot00000000000000#!/usr/bin/php-cgi libqxt-0.6.2/tests/unit/web/cgi/client/000077500000000000000000000000001215241066400177415ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/web/cgi/client/client.pro000066400000000000000000000001051215241066400217350ustar00rootroot00000000000000DESTDIR = .. TARGET = cgiclient CONFIG -= qt SOURCES += main.cpp libqxt-0.6.2/tests/unit/web/cgi/client/main.cpp000066400000000000000000000003201215241066400213640ustar00rootroot00000000000000#include using namespace std; int main(int argc, char** argv) { cout << "Content-type: text/html\r\n"; cout << "\r\n"; cout << "I've got lots of content!"; } libqxt-0.6.2/tests/unit/web/cgi/server/000077500000000000000000000000001215241066400177715ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/web/cgi/server/main.cpp000066400000000000000000000011731215241066400214230ustar00rootroot00000000000000#include #include #include #include #ifdef Q_OS_WIN # define CLIENT_NAME "\\cgiclient.exe" #else # define CLIENT_NAME "/cgiclient" #endif int main(int argc, char** argv) { QCoreApplication app(argc, argv); QxtHttpSessionManager m; m.setConnector(QxtHttpSessionManager::HttpServer); QxtWebCgiService* svc = new QxtWebCgiService(app.applicationDirPath() + CLIENT_NAME, &m, &m); qDebug() << svc->binary(); m.setStaticContentService(svc); m.setAutoCreateSession(false); m.setPort(8192); m.start(); return app.exec(); } libqxt-0.6.2/tests/unit/web/cgi/server/server.pro000066400000000000000000000001621215241066400220200ustar00rootroot00000000000000DESTDIR = .. TARGET = cgiserver CONFIG += qxt QT = core network QXT = core web SOURCES += main.cpp libqxt-0.6.2/tests/unit/web/direct/000077500000000000000000000000001215241066400171735ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/web/direct/direct.pro000066400000000000000000000001721215241066400211670ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = web SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/web/direct/main.cpp000066400000000000000000000015331215241066400206250ustar00rootroot00000000000000#include #include #include #include #include int main (int argc,char ** argv) { QCoreApplication app(argc,argv); QxtWebScgiConnector c; qDebug()<<"start:"<waitForReadyRead(10000); QTextStream stream(st); stream<<"

HI!

"; stream<<"You requested: "<request().path()<<"
"; stream<<"And sent me: "<readAll()<<"
"; stream<<"
"; stream.flush(); delete (st); } } libqxt-0.6.2/tests/unit/web/htmltemplate/000077500000000000000000000000001215241066400204215ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/web/htmltemplate/htmltemplate.pro000066400000000000000000000001721215241066400236430ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = web SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/web/htmltemplate/main.cpp000066400000000000000000000012471215241066400220550ustar00rootroot00000000000000#include #include #include class Test: public QObject { Q_OBJECT private slots: void simple() { QxtHtmlTemplate t; t.load(""); t["foo"]="bla"; QVERIFY(t.render()=="bla"); } void surounded() { QxtHtmlTemplate t; t.load("123456789123456789"); t["foo"]="heyJO"; QVERIFY(t.render()=="123456789heyJO123456789"); } void indented() { QxtHtmlTemplate t; t.load("\n "); t["foo"]="baz\nbar"; QVERIFY(t.render()=="\n baz\n bar"); } }; QTEST_MAIN(Test) #include "main.moc" libqxt-0.6.2/tests/unit/web/invoketest/000077500000000000000000000000001215241066400201145ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/web/invoketest/invoketest.pro000066400000000000000000000001721215241066400230310ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = web SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/web/invoketest/main.cpp000066400000000000000000000025401215241066400215450ustar00rootroot00000000000000#include #include #include #include class test : public QxtWebController { Q_OBJECT public: test():QxtWebController("root") { } public slots: int index() { echo()<<"foo"; return 0; } int index(QString a, QString b=QString("default"), QString c=QString("default2")) { echo()<<"a: "< b: "< c: "<" "error "<" <" <" <" <" <" <"; return 0; } }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QxtWebCore core(new QxtScgiConnector()); core.start(4000); test t; err e; return app.exec(); } #include "main.moc" libqxt-0.6.2/tests/unit/web/upload/000077500000000000000000000000001215241066400172055ustar00rootroot00000000000000libqxt-0.6.2/tests/unit/web/upload/main.cpp000066400000000000000000000020151215241066400206330ustar00rootroot00000000000000#include #include #include #include #include class test : public QxtWebController { Q_OBJECT public: test():QxtWebController("root") { } public slots: int index() { echo()<< "
" "File to upload:
" "Notes about the file:
" "
" " to upload the file!" "
"; return 0; } int upload() { QByteArray d= QxtWebCore::content(100000000); QxtWebCore::sendHeader(); QByteArray io; QxtWebCore::socket()->write(d); return 0; } }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QxtWebCore core(new QxtFcgiConnector()); core.start(); test t; return app.exec(); } #include "main.moc" libqxt-0.6.2/tests/unit/web/upload/upload.pro000066400000000000000000000001721215241066400212130ustar00rootroot00000000000000TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT = core QXT = web SOURCES += main.cpp include(../../unit.pri) libqxt-0.6.2/tests/unit/web/web.pro000066400000000000000000000006011215241066400172150ustar00rootroot00000000000000###################################################################### # Automatically generated by qmake (2.01a) Fri Jan 16 22:25:31 2009 ###################################################################### TEMPLATE = subdirs # SUBDIRS += async cgi direct invoketest upload # TODO: fix these unit tests SUBDIRS += htmltemplate test.CONFIG += recursive QMAKE_EXTRA_TARGETS += test libqxt-0.6.2/tools/000077500000000000000000000000001215241066400141635ustar00rootroot00000000000000libqxt-0.6.2/tools/3rdparty/000077500000000000000000000000001215241066400157335ustar00rootroot00000000000000libqxt-0.6.2/tools/3rdparty/qdoc3/000077500000000000000000000000001215241066400167445ustar00rootroot00000000000000libqxt-0.6.2/tools/3rdparty/qdoc3/JAVATODO.txt000066400000000000000000000021421215241066400207130ustar00rootroot00000000000000 * index page on "O" and downwards? * flag types, e.g. QTextStream::NumberFlags * example references doc.trolltech.com etc. * fix enum value table (e.g. QCoreApplication.Encoding.html) * check reimplementation of interface functions (e.g. QWidget::widthMM()) * handle '::' in doc, e.g. in QAbstractEventDispatcher's detailed desc * make sure default constructor logic doesn't interfere with default params (e.g. QAbstractEventDispatcher ctors) * document default constructor provided for Java (e.g.?) * document "protected QAbstractEventDispatcher(QtObject.QPrivateConstructor p)" and the like * memory-managed, type * replace QString with String, etc. * nested classes * enum_1 * fix stylesheet * no link to class itself * support \ifjava * add // C++ * support Java-only /*! ... */ comments * links to property names have to be fixed * example: version 1 in QStyleOptionFrame * example: foo -> isFoo() * lowercase, and remove final stop, in \brief texts for variables and properties * omit "see alsos" that don't work instead of showing them as broken links libqxt-0.6.2/tools/3rdparty/qdoc3/README.TXT000066400000000000000000000004521215241066400203030ustar00rootroot00000000000000qdoc3 is the tool used to generate the Qt reference documentation. The source code is included as part of this package primarily to fulfill our GPL obligations. We highly recommend using Doxygen (http://www.stack.nl/~dimitri/doxygen/) for generating documentation for your Qt-based application. libqxt-0.6.2/tools/3rdparty/qdoc3/TODO.txt000066400000000000000000000062701215241066400202570ustar00rootroot00000000000000 * fix QWSPointerCalibrationData::devPoints and qwsServer * Fix QMenu::addAction(QAction *) overload, "using" etc. * fix space between two tables using

* qpixmap-qt3.html; remove 8 public functions inherited from QPaintDevice * \variable array * Added support for parameterless macros (e.g. \macro Q_OBJECT). * Made qdoc stricter regarding the data types (e.g. can't use \enum to document a typedef). * Parse QT_MODULE() macro and generate proper warnings for the various editions. * Fix parsing of \image following \value (e.g. qt.html). * Don't turn X11 and similar names into links. * Added automatic links from getters to setters and vice versa. * Support \module and show which module each class is from. * Use bullet list for the list of all functions, now that Assistant handles these gracefully. * Fix occasional crash caused by misuse of const_cast(). * Provide clearer error messages when resolves fail. CHECK: * Identify editions * Automatic \sa getter setter * \macro Q_OBJECT MUST HAVES: * resolve [gs]etters for \sa using base class * fix \overload when one is a signal and the other a normal function * use "project" for .dcf files * functions.html: include the types from QtGlobal as well as the functions (whatever that means) * nice template function/class syntax * spellchecker: built-in vs. builtin * verbose mode for functions that don't exist * No links to Porting Guide sections (e.g. QStringList) * link toggled(bool) * autolink foo(1) * handle using correctly * QObject "reentrant" list: duplicates * operator<< \overload * \compat \overload * qWarning() link * operator<<() autolink * get rid of spurious 'global' functions * Make automatic links in code work * Fix encoding bug (see Important email from Simon Hausmann) * Make links to QFoo::bar().baz() work * Fix automatic links in \sectionX (e.g. qt4-getting-started.html) * Provide a "List of all properties" page. * expand QObjectList -> QList * make \macro work (?) * warning for unnamed parameters in property access functions * \center...\endcenter * warning for undocumented enum values LINKS: * explanation following nonstandard wording warning * omit \overload in operator<< and operator>> * make operator-() unary and binary independent functions (no \overload) * fix \overload * fix \legalese * remove warning for undocumented enum item like QLocale::LastLanguage * improve the \a warnings for overloads; if one overload documents a para, fine * implement \sidebar * implement qbook * implement \legalesefile * show in which module each class is * list namespaces, list header files NICE FEATURES: * implement inheritance tree for each class (as a PNG) * avoid

...

in table/item cells without relying on horrible kludge * prevent macros from having same name as commands * be smart about enum types Foo::Bar vs. Bar when comparing functions * be smart about const & non-const when comparing functions OTHER: * make qdoc run faster * make sure \headerfile works even if specified after \relates * use qtstyle.css instead of inline style for each page libqxt-0.6.2/tools/3rdparty/qdoc3/apigenerator.cpp000066400000000000000000000115611215241066400221340ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "apigenerator.h" #include "codemarker.h" #include "tree.h" QT_BEGIN_NAMESPACE static QString indentStr(int indent) { QString str; str.fill(QLatin1Char(' '), indent * 4); return str; } static bool lessThanName(Node *node1, Node *node2) { return node1->name() < node2->name(); } QString ApiGenerator::format() { return QLatin1String("API"); } void ApiGenerator::generateTree(const Tree *tree, CodeMarker *marker) { QFile outFile(QLatin1String("api")); outFile.open(QIODevice::WriteOnly); out.setDevice(&outFile); generateNode(tree->root(), marker); out.flush(); } void ApiGenerator::generateNode(const Node *node, CodeMarker *marker, int indent) { if (node->access() == Node::Private) return; switch (node->type()) { case Node::Namespace: if (!node->name().isEmpty()) { out << indentStr(indent) << "Namespace: " << node->name() << "\n"; ++indent; } break; case Node::Class: { const ClassNode *classe = static_cast(node); out << indentStr(indent) << "Class: " << node->name(); foreach (const RelatedClass &baseClass, classe->baseClasses()) { if (baseClass.access == Node::Public) out << " inherits " << baseClass.dataTypeWithTemplateArgs; } out << "\n"; ++indent; } break; case Node::Enum: { const EnumNode *enume = static_cast(node); out << indentStr(indent) << "Enum: " << node->name() << "\n"; ++indent; QStringList enumNames; foreach (const EnumItem &item, enume->items()) enumNames << item.name(); qSort(enumNames); foreach (const QString &name, enumNames) out << indentStr(indent) << "Enum value: " << name << "\n"; } break; case Node::Typedef: out << indentStr(indent) << "Typedef: " << node->name() << "\n"; ++indent; break; case Node::Function: { out << indentStr(indent) << "Function: " << plainCode(marker->markedUpSynopsis(node, 0, CodeMarker::Detailed)) << "\n"; ++indent; } break; case Node::Property: { const PropertyNode *property = static_cast(node); out << indentStr(indent) << "Property: " << property->name() << " type " << property->dataType() << "\n"; ++indent; } break; default: ; } if (node->isInnerNode()) { const InnerNode *inner = static_cast(node); NodeList nodes = inner->childNodes(); qSort(nodes.begin(), nodes.end(), lessThanName); foreach (const Node *child, nodes) generateNode(child, marker, indent); } out.flush(); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/apigenerator.h000066400000000000000000000044441215241066400216030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef APIGENERATOR_H #define APIGENERATOR_H #include #include "generator.h" QT_BEGIN_NAMESPACE class ApiGenerator : public Generator { public: QString format(); void generateTree(const Tree *tree, CodeMarker *marker); private: void generateNode(const Node *node, CodeMarker *marker, int indent = 0); QTextStream out; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/archiveextractor.cpp000066400000000000000000000072471215241066400230370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* archiveextractor.cpp */ #include "archiveextractor.h" QT_BEGIN_NAMESPACE QList ArchiveExtractor::extractors; /*! \class ArchiveExtractor \brief The ArchiveExtractor class is a base class for classes that know how to unpack a certain kind of archive file. The archive extractor contains a list of the filename extensions of the files that the archive extractor knows how to unpack. It maintains a static list of all the instances of ArchiveExtractor that have been created. It also has a static function for searching that list to find the archive extracter for a file with a certain extension. */ /*! The constructor takes a list of filename extensions, which it copies and saves internally. This archive extractor is prepended to the static list. */ ArchiveExtractor::ArchiveExtractor( const QStringList& extensions ) : fileExts( extensions ) { extractors.prepend( this ); } /*! The destructor deletes all the filename extensions. */ ArchiveExtractor::~ArchiveExtractor() { extractors.removeAll( this ); } /*! This function searches the static list of archive extractors to find the first one that can handle \a fileName. If it finds an acceptable extractor, it returns a pointer to it. Otherwise it returns null. */ ArchiveExtractor* ArchiveExtractor::extractorForFileName( const QString& fileName ) { int dot = -1; while ( (dot = fileName.indexOf(QLatin1Char('.'), dot + 1)) != -1 ) { QString ext = fileName.mid( dot + 1 ); QList::ConstIterator e = extractors.begin(); while ( e != extractors.end() ) { if ( (*e)->fileExtensions().contains(ext) ) return *e; ++e; } } return 0; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/archiveextractor.h000066400000000000000000000050771215241066400225030ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* archiveextractor.h */ #ifndef ARCHIVEEXTRACTOR_H #define ARCHIVEEXTRACTOR_H #include #include "location.h" QT_BEGIN_NAMESPACE class ArchiveExtractor { public: ArchiveExtractor( const QStringList& extensions ); virtual ~ArchiveExtractor(); virtual void extractArchive( const Location& location, const QString& filePath, const QString& outputDir ) = 0; static ArchiveExtractor *extractorForFileName( const QString& fileName ); protected: const QStringList& fileExtensions() { return fileExts; } private: QStringList fileExts; static QList extractors; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/atom.cpp000066400000000000000000000241751215241066400204210ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "atom.h" #include "location.h" #include QT_BEGIN_NAMESPACE QString Atom::BOLD_ ("bold"); QString Atom::INDEX_ ("index"); QString Atom::ITALIC_ ("italic"); QString Atom::LINK_ ("link"); QString Atom::PARAMETER_ ("parameter"); QString Atom::SUBSCRIPT_ ("subscript"); QString Atom::SUPERSCRIPT_ ("superscript"); QString Atom::TELETYPE_ ("teletype"); QString Atom::UNDERLINE_ ("underline"); QString Atom::BULLET_ ("bullet"); QString Atom::TAG_ ("tag"); QString Atom::VALUE_ ("value"); QString Atom::LOWERALPHA_ ("loweralpha"); QString Atom::LOWERROMAN_ ("lowerroman"); QString Atom::NUMERIC_ ("numeric"); QString Atom::UPPERALPHA_ ("upperalpha"); QString Atom::UPPERROMAN_ ("upperroman"); /*! \class Atom \brief The Atom class is the fundamental unit for representing documents internally. Atoms have a \i type and are completed by a \i string whose meaning depends on the \i type. For example, the string \quotation \i italic text looks nicer than \bold bold text \endquotation is represented by the following atoms: \quotation (FormattingLeft, ATOM_FORMATTING_ITALIC) (String, "italic") (FormattingRight, ATOM_FORMATTING_ITALIC) (String, " text is more attractive than ") (FormattingLeft, ATOM_FORMATTING_BOLD) (String, "bold") (FormattingRight, ATOM_FORMATTING_BOLD) (String, " text") \endquotation \also Text */ /*! \enum Atom::Type \value AbstractLeft \value AbstractRight \value AutoLink \value BaseName \value BriefLeft \value BriefRight \value C \value CaptionLeft \value CaptionRight \value Code \value CodeBad \value CodeNew \value CodeOld \value CodeQuoteArgument \value CodeQuoteCommand \value EndQmlText \value FormatElse \value FormatEndif \value FormatIf \value FootnoteLeft \value FootnoteRight \value FormattingLeft \value FormattingRight \value GeneratedList \value Image \value ImageText \value InlineImage \value LineBreak \value Link \value LinkNode \value ListLeft \value ListItemNumber \value ListTagLeft \value ListTagRight \value ListItemLeft \value ListItemRight \value ListRight \value Nop \value ParaLeft \value ParaRight \value Qml \value QmlText \value QuotationLeft \value QuotationRight \value RawString \value SectionLeft \value SectionRight \value SectionHeadingLeft \value SectionHeadingRight \value SidebarLeft \value SidebarRight \value String \value TableLeft \value TableRight \value TableHeaderLeft \value TableHeaderRight \value TableRowLeft \value TableRowRight \value TableItemLeft \value TableItemRight \value TableOfContents \value Target \value UnhandledFormat \value UnknownCommand */ static const struct { const char *english; int no; } atms[] = { { "AbstractLeft", Atom::AbstractLeft }, { "AbstractRight", Atom::AbstractRight }, { "AutoLink", Atom::AutoLink }, { "BaseName", Atom::BaseName }, { "BriefLeft", Atom::BriefLeft }, { "BriefRight", Atom::BriefRight }, { "C", Atom::C }, { "CaptionLeft", Atom::CaptionLeft }, { "CaptionRight", Atom::CaptionRight }, { "Code", Atom::Code }, { "CodeBad", Atom::CodeBad }, { "CodeNew", Atom::CodeNew }, { "CodeOld", Atom::CodeOld }, { "CodeQuoteArgument", Atom::CodeQuoteArgument }, { "CodeQuoteCommand", Atom::CodeQuoteCommand }, #ifdef QDOC_QML { "EndQmlText", Atom::EndQmlText }, #endif { "FootnoteLeft", Atom::FootnoteLeft }, { "FootnoteRight", Atom::FootnoteRight }, { "FormatElse", Atom::FormatElse }, { "FormatEndif", Atom::FormatEndif }, { "FormatIf", Atom::FormatIf }, { "FormattingLeft", Atom::FormattingLeft }, { "FormattingRight", Atom::FormattingRight }, { "GeneratedList", Atom::GeneratedList }, { "Image", Atom::Image }, { "ImageText", Atom::ImageText }, { "InlineImage", Atom::InlineImage }, { "LegaleseLeft", Atom::LegaleseLeft }, { "LegaleseRight", Atom::LegaleseRight }, { "LineBreak", Atom::LineBreak }, { "Link", Atom::Link }, { "LinkNode", Atom::LinkNode }, { "ListLeft", Atom::ListLeft }, { "ListItemNumber", Atom::ListItemNumber }, { "ListTagLeft", Atom::ListTagLeft }, { "ListTagRight", Atom::ListTagRight }, { "ListItemLeft", Atom::ListItemLeft }, { "ListItemRight", Atom::ListItemRight }, { "ListRight", Atom::ListRight }, { "Nop", Atom::Nop }, { "ParaLeft", Atom::ParaLeft }, { "ParaRight", Atom::ParaRight }, #ifdef QDOC_QML { "Qml", Atom::Qml}, { "QmlText", Atom::QmlText }, #endif { "QuotationLeft", Atom::QuotationLeft }, { "QuotationRight", Atom::QuotationRight }, { "RawString", Atom::RawString }, { "SectionLeft", Atom::SectionLeft }, { "SectionRight", Atom::SectionRight }, { "SectionHeadingLeft", Atom::SectionHeadingLeft }, { "SectionHeadingRight", Atom::SectionHeadingRight }, { "SidebarLeft", Atom::SidebarLeft }, { "SidebarRight", Atom::SidebarRight }, { "SnippetCommand", Atom::SnippetCommand }, { "SnippetIdentifier", Atom::SnippetIdentifier }, { "SnippetLocation", Atom::SnippetLocation }, { "String", Atom::String }, { "TableLeft", Atom::TableLeft }, { "TableRight", Atom::TableRight }, { "TableHeaderLeft", Atom::TableHeaderLeft }, { "TableHeaderRight", Atom::TableHeaderRight }, { "TableRowLeft", Atom::TableRowLeft }, { "TableRowRight", Atom::TableRowRight }, { "TableItemLeft", Atom::TableItemLeft }, { "TableItemRight", Atom::TableItemRight }, { "TableOfContents", Atom::TableOfContents }, { "Target", Atom::Target }, { "UnhandledFormat", Atom::UnhandledFormat }, { "UnknownCommand", Atom::UnknownCommand }, { 0, 0 } }; /*! \fn Atom::Atom( Type type, const QString& string ) Constructs an atom (\a type, \a string) outside of any atom list. */ /*! \fn Atom( Atom *prev, Type type, const QString& string ) Constructs an atom (\a type, \a string) that follows \a prev in \a prev's atom list. */ /*! \fn void Atom::appendChar( QChar ch ) Appends \a ch to the string parameter of this atom. \also string() */ /*! \fn void Atom::appendString( const QString& string ) Appends \a string to the string parameter of this atom. \also string() */ /*! \fn void Atom::chopString() \also string() */ /*! \fn Atom *Atom::next() Return the next atom in the atom list. \also type(), string() */ /*! Return the next Atom in the list if it is of Type \a t. Otherwise return 0. */ const Atom* Atom::next(Type t) const { return (nxt && (nxt->type() == t)) ? nxt : 0; } /*! Return the next Atom in the list if it is of Type \a t and its string part is \a s. Otherwise return 0. */ const Atom* Atom::next(Type t, const QString& s) const { return (nxt && (nxt->type() == t) && (nxt->string() == s)) ? nxt : 0; } /*! \fn const Atom *Atom::next() const Return the next atom in the atom list. \also type(), string() */ /*! \fn Type Atom::type() const Return the type of this atom. \also string(), next() */ /*! Return the type of this atom as a string. Return "Invalid" if type() returns an impossible value. This is only useful for debugging. \also type() */ QString Atom::typeString() const { static bool deja = false; if ( !deja ) { int i = 0; while ( atms[i].english != 0 ) { if ( atms[i].no != i ) Location::internalError( tr("atom %1 missing").arg(i) ); i++; } deja = true; } int i = (int) type(); if ( i < 0 || i > (int) Last ) return QLatin1String("Invalid"); return QLatin1String(atms[i].english); } /*! \fn const QString& Atom::string() const Returns the string parameter that together with the type characterizes this atom. \also type(), next() */ /*! Dumps this Atom to stderr in printer friendly form. */ void Atom::dump() const { QString str = string(); str.replace( "\\", "\\\\" ); str.replace( "\"", "\\\"" ); str.replace( "\n", "\\n" ); str.replace( QRegExp("[^\x20-\x7e]"), "?" ); if (!str.isEmpty()) str = " \"" + str + "\""; fprintf(stderr, " %-15s%s\n", typeString().toLatin1().data(), str.toLatin1().data()); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/atom.h000066400000000000000000000133601215241066400200600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* atom.h */ #ifndef ATOM_H #define ATOM_H #include #define QDOC_QML QT_BEGIN_NAMESPACE class Atom { public: enum Type { AbstractLeft, AbstractRight, AutoLink, BaseName, BriefLeft, BriefRight, C, CaptionLeft, CaptionRight, Code, CodeBad, CodeNew, CodeOld, CodeQuoteArgument, CodeQuoteCommand, #ifdef QDOC_QML EndQmlText, #endif FootnoteLeft, FootnoteRight, FormatElse, FormatEndif, FormatIf, FormattingLeft, FormattingRight, GeneratedList, Image, ImageText, InlineImage, LegaleseLeft, LegaleseRight, LineBreak, Link, LinkNode, ListLeft, ListItemNumber, ListTagLeft, ListTagRight, ListItemLeft, ListItemRight, ListRight, Nop, ParaLeft, ParaRight, #ifdef QDOC_QML Qml, QmlText, #endif QuotationLeft, QuotationRight, RawString, SectionLeft, SectionRight, SectionHeadingLeft, SectionHeadingRight, SidebarLeft, SidebarRight, SnippetCommand, SnippetIdentifier, SnippetLocation, String, TableLeft, TableRight, TableHeaderLeft, TableHeaderRight, TableRowLeft, TableRowRight, TableItemLeft, TableItemRight, TableOfContents, Target, UnhandledFormat, UnknownCommand, Last = UnknownCommand }; Atom(Type type, const QString &string = "") : nxt(0), typ(type), str(string) { } Atom(Atom *prev, Type type, const QString &string = "") : nxt(prev->nxt), typ(type), str(string) { prev->nxt = this; } void appendChar(QChar ch) { str += ch; } void appendString(const QString& string) { str += string; } void chopString() { str.chop(1); } void setString(const QString &string) { str = string; } Atom *next() { return nxt; } void setNext(Atom *newNext) { nxt = newNext; } const Atom *next() const { return nxt; } const Atom *next(Type t) const; const Atom *next(Type t, const QString& s) const; Type type() const { return typ; } QString typeString() const; const QString& string() const { return str; } void dump() const; static QString BOLD_; static QString INDEX_; static QString ITALIC_; static QString LINK_; static QString PARAMETER_; static QString SUBSCRIPT_; static QString SUPERSCRIPT_; static QString TELETYPE_; static QString UNDERLINE_; static QString BULLET_; static QString TAG_; static QString VALUE_; static QString LOWERALPHA_; static QString LOWERROMAN_; static QString NUMERIC_; static QString UPPERALPHA_; static QString UPPERROMAN_; private: Atom *nxt; Type typ; QString str; }; #define ATOM_FORMATTING_BOLD "bold" #define ATOM_FORMATTING_INDEX "index" #define ATOM_FORMATTING_ITALIC "italic" #define ATOM_FORMATTING_LINK "link" #define ATOM_FORMATTING_PARAMETER "parameter" #define ATOM_FORMATTING_SUBSCRIPT "subscript" #define ATOM_FORMATTING_SUPERSCRIPT "superscript" #define ATOM_FORMATTING_TELETYPE "teletype" #define ATOM_FORMATTING_UNDERLINE "underline" #define ATOM_LIST_BULLET "bullet" #define ATOM_LIST_TAG "tag" #define ATOM_LIST_VALUE "value" #define ATOM_LIST_LOWERALPHA "loweralpha" #define ATOM_LIST_LOWERROMAN "lowerroman" #define ATOM_LIST_NUMERIC "numeric" #define ATOM_LIST_UPPERALPHA "upperalpha" #define ATOM_LIST_UPPERROMAN "upperroman" QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/bookgenerator.cpp000066400000000000000000000043031215241066400223110ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* bookgenerator.cpp */ #include "bookgenerator.h" QT_BEGIN_NAMESPACE BookGenerator::BookGenerator() { } BookGenerator::~BookGenerator() { } void BookGenerator::generateTree( const Tree *tree, CodeMarker *marker ) { Q_UNUSED( tree ) Q_UNUSED( marker ) } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/bookgenerator.h000066400000000000000000000043331215241066400217610ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* bookgenerator.h */ #ifndef BOOKGENERATOR_H #define BOOKGENERATOR_H #include "generator.h" QT_BEGIN_NAMESPACE class BookGenerator : public Generator { public: BookGenerator(); ~BookGenerator(); virtual void generateTree( const Tree *tree, CodeMarker *marker ); }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/ccodeparser.cpp000066400000000000000000000044521215241066400217470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* ccodeparser.cpp */ #include "ccodeparser.h" QT_BEGIN_NAMESPACE CCodeParser::CCodeParser() { } CCodeParser::~CCodeParser() { } QString CCodeParser::language() { return QLatin1String("C"); } QString CCodeParser::headerFileNameFilter() { return QLatin1String("*.ch *.h"); } QString CCodeParser::sourceFileNameFilter() { return QLatin1String("*.c"); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/ccodeparser.h000066400000000000000000000044101215241066400214060ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* ccodeparser.h */ #ifndef CCODEPARSER_H #define CCODEPARSER_H #include "cppcodeparser.h" QT_BEGIN_NAMESPACE class CCodeParser : public CppCodeParser { public: CCodeParser(); ~CCodeParser(); virtual QString language(); virtual QString headerFileNameFilter(); virtual QString sourceFileNameFilter(); }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/codechunk.cpp000066400000000000000000000131261215241066400214160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* codechunk.cpp */ #include #include #include "codechunk.h" QT_BEGIN_NAMESPACE enum { Other, Alnum, Gizmo, Comma, LParen, RParen, RAngle, Colon }; // entries 128 and above are Other static const int charCategory[256] = { Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, Other, // ! " # $ % & ' Other, Other, Other, Other, Other, Gizmo, Gizmo, Other, // ( ) * + , - . / LParen, RParen, Gizmo, Gizmo, Comma, Other, Other, Gizmo, // 0 1 2 3 4 5 6 7 Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, // 8 9 : ; < = > ? Alnum, Alnum, Colon, Other, Other, Gizmo, RAngle, Gizmo, // @ A B C D E F G Other, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, // H I J K L M N O Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, // P Q R S T U V W Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, // X Y Z [ \ ] ^ _ Alnum, Alnum, Alnum, Other, Other, Other, Gizmo, Alnum, // ` a b c d e f g Other, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, // h i j k l m n o Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, // p q r s t u v w Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, // x y z { | } ~ Alnum, Alnum, Alnum, LParen, Gizmo, RParen, Other, Other }; static const bool needSpace[8][8] = { /* [ a + , ( ) > : */ /* [ */ { false, false, false, false, false, true, false, false }, /* a */ { false, true, true, false, false, true, false, false }, /* + */ { false, true, false, false, false, true, false, true }, /* , */ { true, true, true, true, true, true, true, true }, /* ( */ { true, true, true, false, true, false, true, true }, /* ) */ { true, true, true, false, true, true, true, true }, /* > */ { true, true, true, false, true, true, true, false }, /* : */ { false, false, true, true, true, true, true, false } }; static int category( QChar ch ) { return charCategory[(int)ch.toLatin1()]; } CodeChunk::CodeChunk() : hotspot( -1 ) { } CodeChunk::CodeChunk( const QString& str ) : s( str ), hotspot( -1 ) { } void CodeChunk::append( const QString& lexeme ) { if ( !s.isEmpty() && !lexeme.isEmpty() ) { /* Should there be a space or not between the code chunk so far and the new lexeme? */ int cat1 = category(s.at(s.size() - 1)); int cat2 = category(lexeme[0]); if ( needSpace[cat1][cat2] ) s += QLatin1Char( ' ' ); } s += lexeme; } void CodeChunk::appendHotspot() { /* The first hotspot is the right one. */ if ( hotspot == -1 ) hotspot = s.length(); } QString CodeChunk::toString() const { return s; } QStringList CodeChunk::toPath() const { QString t = s; t.remove(QRegExp(QLatin1String("<([^<>]|<([^<>]|<[^<>]*>)*>)*>"))); return t.split(QLatin1String("::")); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/codechunk.h000066400000000000000000000074721215241066400210720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* codechunk.h */ #ifndef CODECHUNK_H #define CODECHUNK_H #include QT_BEGIN_NAMESPACE // ### get rid of that class /* The CodeChunk class represents a tiny piece of C++ code. The class provides convertion between a list of lexemes and a string. It adds spaces at the right place for consistent style. The tiny pieces of code it represents are data types, enum values, and default parameter values. Apart from the piece of code itself, there are two bits of metainformation stored in CodeChunk: the base and the hotspot. The base is the part of the piece that may be a hypertext link. The base of QMap is QMap. The hotspot is the place the variable name should be inserted in the case of a variable (or parameter) declaration. The base of char * [] is between '*' and '[]'. */ class CodeChunk { public: CodeChunk(); CodeChunk( const QString& str ); void append( const QString& lexeme ); void appendHotspot(); bool isEmpty() const { return s.isEmpty(); } QString toString() const; QStringList toPath() const; QString left() const { return s.left(hotspot == -1 ? s.length() : hotspot); } QString right() const { return s.mid(hotspot == -1 ? s.length() : hotspot); } private: QString s; int hotspot; }; inline bool operator==( const CodeChunk& c, const CodeChunk& d ) { return c.toString() == d.toString(); } inline bool operator!=( const CodeChunk& c, const CodeChunk& d ) { return !( c == d ); } inline bool operator<( const CodeChunk& c, const CodeChunk& d ) { return c.toString() < d.toString(); } inline bool operator>( const CodeChunk& c, const CodeChunk& d ) { return d < c; } inline bool operator<=( const CodeChunk& c, const CodeChunk& d ) { return !( c > d ); } inline bool operator>=( const CodeChunk& c, const CodeChunk& d ) { return !( c < d ); } QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/codemarker.cpp000066400000000000000000000407301215241066400215700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include "codemarker.h" #include "config.h" #include "node.h" #include QT_BEGIN_NAMESPACE QString CodeMarker::defaultLang; QList CodeMarker::markers; /*! When a code marker constructs itself, it puts itself into the static list of code markers. All the code markers in the static list get initialized in initialize(), which is not called until after the qdoc configuration file has been read. */ CodeMarker::CodeMarker() : slow(false) { markers.prepend(this); } /*! When a code marker destroys itself, it removes itself from the static list of code markers. */ CodeMarker::~CodeMarker() { markers.removeAll(this); } /*! The only thing a code market initializes is its \e{slow} flag. The \e{slow} flag indicates whether the operations that slow down qdoc are to be performed or not. It is turned off by default. */ void CodeMarker::initializeMarker(const Config &config) { slow = config.getBool(QLatin1String(CONFIG_SLOW)); } /*! Terminating a code marker is trivial. */ void CodeMarker::terminateMarker() { // nothing. } /*! All the code markers in the static list are initialized here, after the qdoc configuration file has been loaded. */ void CodeMarker::initialize(const Config& config) { defaultLang = config.getString(QLatin1String(CONFIG_LANGUAGE)); QList::ConstIterator m = markers.begin(); while (m != markers.end()) { (*m)->initializeMarker(config); ++m; } } /*! All the code markers in the static list are terminated here. */ void CodeMarker::terminate() { QList::ConstIterator m = markers.begin(); while (m != markers.end()) { (*m)->terminateMarker(); ++m; } } CodeMarker *CodeMarker::markerForCode(const QString& code) { CodeMarker *defaultMarker = markerForLanguage(defaultLang); if (defaultMarker != 0 && defaultMarker->recognizeCode(code)) return defaultMarker; QList::ConstIterator m = markers.begin(); while (m != markers.end()) { if ((*m)->recognizeCode(code)) return *m; ++m; } return defaultMarker; } CodeMarker *CodeMarker::markerForFileName(const QString& fileName) { CodeMarker *defaultMarker = markerForLanguage(defaultLang); int dot = -1; while ((dot = fileName.lastIndexOf(QLatin1Char('.'), dot)) != -1) { QString ext = fileName.mid(dot + 1); if (defaultMarker != 0 && defaultMarker->recognizeExtension(ext)) return defaultMarker; QList::ConstIterator m = markers.begin(); while (m != markers.end()) { if ((*m)->recognizeExtension(ext)) return *m; ++m; } --dot; } return defaultMarker; } CodeMarker *CodeMarker::markerForLanguage(const QString& lang) { QList::ConstIterator m = markers.begin(); while (m != markers.end()) { if ((*m)->recognizeLanguage(lang)) return *m; ++m; } return 0; } const Node *CodeMarker::nodeForString(const QString& string) { if (sizeof(const Node *) == sizeof(uint)) { return reinterpret_cast(string.toUInt()); } else { return reinterpret_cast(string.toULongLong()); } } QString CodeMarker::stringForNode(const Node *node) { if (sizeof(const Node *) == sizeof(ulong)) { return QString::number(reinterpret_cast(node)); } else { return QString::number(reinterpret_cast(node)); } } static const QString samp = QLatin1String("&"); static const QString slt = QLatin1String("<"); static const QString sgt = QLatin1String(">"); static const QString squot = QLatin1String("""); QString CodeMarker::protect(const QString& str) { int n = str.length(); QString marked; marked.reserve(n * 2 + 30); const QChar *data = str.constData(); for (int i = 0; i != n; ++i) { switch (data[i].unicode()) { case '&': marked += samp; break; case '<': marked += slt; break; case '>': marked += sgt; break; case '"': marked += squot; break; default : marked += data[i]; } } return marked; } QString CodeMarker::typified(const QString &string) { QString result; QString pendingWord; for (int i = 0; i <= string.size(); ++i) { QChar ch; if (i != string.size()) ch = string.at(i); QChar lower = ch.toLower(); if ((lower >= QLatin1Char('a') && lower <= QLatin1Char('z')) || ch.digitValue() >= 0 || ch == QLatin1Char('_') || ch == QLatin1Char(':')) { pendingWord += ch; } else { if (!pendingWord.isEmpty()) { bool isProbablyType = (pendingWord != QLatin1String("const")); if (isProbablyType) result += QLatin1String("<@type>"); result += pendingWord; if (isProbablyType) result += QLatin1String(""); } pendingWord.clear(); switch (ch.unicode()) { case '\0': break; case '&': result += QLatin1String("&"); break; case '<': result += QLatin1String("<"); break; case '>': result += QLatin1String(">"); break; default: result += ch; } } } return result; } QString CodeMarker::taggedNode(const Node *node) { QString tag; switch (node->type()) { case Node::Namespace: tag = QLatin1String("@namespace"); break; case Node::Class: tag = QLatin1String("@class"); break; case Node::Enum: tag = QLatin1String("@enum"); break; case Node::Typedef: tag = QLatin1String("@typedef"); break; case Node::Function: tag = QLatin1String("@function"); break; case Node::Property: tag = QLatin1String("@property"); break; default: tag = QLatin1String("@unknown"); } return QLatin1Char('<') + tag + QLatin1Char('>') + protect(node->name()) + QLatin1String("'); } QString CodeMarker::linkTag(const Node *node, const QString& body) { return QLatin1String("<@link node=\"") + stringForNode(node) + QLatin1String("\">") + body + QLatin1String(""); } QString CodeMarker::sortName(const Node *node) { QString nodeName = node->name(); int numDigits = 0; for (int i = nodeName.size() - 1; i > 0; --i) { if (nodeName.at(i).digitValue() == -1) break; ++numDigits; } // we want 'qint8' to appear before 'qint16' if (numDigits > 0) { for (int i = 0; i < 4 - numDigits; ++i) nodeName.insert(nodeName.size()-numDigits-1, QLatin1String("0")); } if (node->type() == Node::Function) { const FunctionNode *func = static_cast(node); QString sortNo; if (func->metaness() == FunctionNode::Ctor) { sortNo = QLatin1String("C"); } else if (func->metaness() == FunctionNode::Dtor) { sortNo = QLatin1String("D"); } else { if (nodeName.startsWith(QLatin1String("operator")) && nodeName.length() > 8 && !nodeName[8].isLetterOrNumber()) sortNo = QLatin1String("F"); else sortNo = QLatin1String("E"); } return sortNo + nodeName + QLatin1Char(' ') + QString::number(func->overloadNumber(), 36); } if (node->type() == Node::Class) return QLatin1Char('A') + nodeName; if (node->type() == Node::Property || node->type() == Node::Variable) return QLatin1Char('E') + nodeName; return QLatin1Char('B') + nodeName; } void CodeMarker::insert(FastSection &fastSection, Node *node, SynopsisStyle style, Status status) { bool inheritedMember = (!node->relates() && (node->parent() != (const InnerNode *)fastSection.innerNode)); bool irrelevant = false; if (node->access() == Node::Private) { irrelevant = true; } else if (node->type() == Node::Function) { FunctionNode *func = (FunctionNode *) node; irrelevant = (inheritedMember && (func->metaness() == FunctionNode::Ctor || func->metaness() == FunctionNode::Dtor)); } else if (node->type() == Node::Class || node->type() == Node::Enum || node->type() == Node::Typedef) { irrelevant = (inheritedMember && style != SeparateList); if (!irrelevant && style == Detailed && node->type() == Node::Typedef) { const TypedefNode* typedeffe = static_cast(node); if (typedeffe->associatedEnum()) irrelevant = true; } } if (!irrelevant) { if (status == Compat) { irrelevant = (node->status() != Node::Compat); } else if (status == Obsolete) { irrelevant = (node->status() != Node::Obsolete); } else { irrelevant = (node->status() == Node::Compat || node->status() == Node::Obsolete); } } if (!irrelevant) { if (!inheritedMember || style == SeparateList) { QString key = sortName(node); if (!fastSection.memberMap.contains(key)) fastSection.memberMap.insert(key, node); } else { if (node->parent()->type() == Node::Class) { if (fastSection.inherited.isEmpty() || fastSection.inherited.last().first != node->parent()) { QPair p((ClassNode *)node->parent(), 0); fastSection.inherited.append(p); } fastSection.inherited.last().second++; } } } } void CodeMarker::append(QList
& sectionList, const FastSection& fastSection) { if (!fastSection.memberMap.isEmpty() || !fastSection.inherited.isEmpty()) { Section section(fastSection.name, fastSection.singularMember, fastSection.pluralMember); section.members = fastSection.memberMap.values(); section.inherited = fastSection.inherited; sectionList.append(section); } } static QString encode(const QString &string) { #if 0 QString result = string; for (int i = string.size() - 1; i >= 0; --i) { uint ch = string.at(i).unicode(); if (ch > 0xFF) ch = '?'; if ((ch - '0') >= 10 && (ch - 'a') >= 26 && (ch - 'A') >= 26 && ch != '/' && ch != '(' && ch != ')' && ch != ',' && ch != '*' && ch != '&' && ch != '_' && ch != '<' && ch != '>' && ch != ':' && ch != '~') result.replace(i, 1, QString("%") + QString("%1").arg(ch, 2, 16)); } return result; #else return string; #endif } QStringList CodeMarker::macRefsForNode(const Node *node) { QString result = QLatin1String("cpp/"); switch (node->type()) { case Node::Class: { const ClassNode *classe = static_cast(node); #if 0 if (!classe->templateStuff().isEmpty()) { result += QLatin1String("tmplt/"); } else #endif { result += QLatin1String("cl/"); } result += macName(classe); // ### Maybe plainName? } break; case Node::Enum: { QStringList stringList; stringList << encode(result + QLatin1String("tag/") + macName(node)); foreach (const QString &enumName, node->doc().enumItemNames()) { // ### Write a plainEnumValue() and use it here stringList << encode(result + QLatin1String("econst/") + macName(node->parent(), enumName)); } return stringList; } case Node::Typedef: result += QLatin1String("tdef/") + macName(node); break; case Node::Function: { bool isMacro = false; const FunctionNode *func = static_cast(node); // overloads are too clever for the Xcode documentation browser if (func->isOverload()) return QStringList(); if (func->metaness() == FunctionNode::MacroWithParams || func->metaness() == FunctionNode::MacroWithoutParams) { result += QLatin1String("macro/"); isMacro = true; #if 0 } else if (!func->templateStuff().isEmpty()) { result += QLatin1String("ftmplt/"); #endif } else if (func->isStatic()) { result += QLatin1String("clm/"); } else if (!func->parent()->name().isEmpty()) { result += QLatin1String("instm/"); } else { result += QLatin1String("func/"); } result += macName(func); if (result.endsWith(QLatin1String("()"))) result.chop(2); #if 0 // this code is too clever for the Xcode documentation // browser and/or pbhelpindexer if (!isMacro) { result += "/" + QLatin1String(QMetaObject::normalizedSignature(func->returnType().toLatin1().constData())) + "/("; const QList ¶ms = func->parameters(); for (int i = 0; i < params.count(); ++i) { QString type = params.at(i).leftType() + params.at(i).rightType(); type = QLatin1String(QMetaObject::normalizedSignature(type.toLatin1().constData())); if (i != 0) result += ","; result += type; } result += ")"; } #endif } break; case Node::Variable: result += QLatin1String("data/") + macName(node); break; case Node::Property: { NodeList list = static_cast(node)->functions(); QStringList stringList; foreach (const Node *node, list) { stringList += macRefsForNode(node); } return stringList; } case Node::Namespace: case Node::Fake: case Node::Target: default: return QStringList(); } return QStringList(encode(result)); } QString CodeMarker::macName(const Node *node, const QString &name) { QString myName = name; if (myName.isEmpty()) { myName = node->name(); node = node->parent(); } if (node->name().isEmpty()) { return QLatin1Char('/') + myName; } else { return plainFullName(node) + QLatin1Char('/') + myName; } } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/codemarker.h000066400000000000000000000136621215241066400212410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* codemarker.h */ #ifndef CODEMARKER_H #define CODEMARKER_H #include #include "node.h" QT_BEGIN_NAMESPACE class Config; class Tree; struct Section { QString name; QString singularMember; QString pluralMember; NodeList members; QList > inherited; Section() { } Section(const QString& name0, const QString& singularMember0, const QString& pluralMember0) : name(name0), singularMember(singularMember0), pluralMember(pluralMember0) { } }; struct FastSection { const InnerNode *innerNode; QString name; QString singularMember; QString pluralMember; QMap memberMap; QList > inherited; FastSection(const InnerNode *innerNode0, const QString& name0 = "", const QString& singularMember0 = "member", const QString& pluralMember0 = "members") : innerNode(innerNode0), name(name0), singularMember(singularMember0), pluralMember(pluralMember0) { } }; class CodeMarker { public: enum SynopsisStyle { Summary, Detailed, SeparateList, Accessors }; enum Status { Compat, Obsolete, Okay }; CodeMarker(); virtual ~CodeMarker(); virtual void initializeMarker(const Config& config); virtual void terminateMarker(); virtual bool recognizeCode(const QString& code) = 0; virtual bool recognizeExtension(const QString& ext) = 0; virtual bool recognizeLanguage(const QString& lang) = 0; virtual QString plainName(const Node *node) = 0; virtual QString plainFullName(const Node *node, const Node *relative = 0) = 0; virtual QString markedUpCode(const QString& code, const Node *relative, const QString& dirPath) = 0; virtual QString markedUpSynopsis(const Node *node, const Node *relative, SynopsisStyle style) = 0; virtual QString markedUpName(const Node *node) = 0; virtual QString markedUpFullName(const Node *node, const Node *relative = 0) = 0; virtual QString markedUpEnumValue(const QString &enumValue, const Node *relative) = 0; virtual QString markedUpIncludes(const QStringList& includes) = 0; virtual QString functionBeginRegExp(const QString& funcName) = 0; virtual QString functionEndRegExp(const QString& funcName) = 0; virtual QList
sections(const InnerNode *inner, SynopsisStyle style, Status status) = 0; virtual const Node *resolveTarget(const QString& target, const Tree *tree, const Node *relative) = 0; virtual QStringList macRefsForNode(const Node *node); static void initialize(const Config& config); static void terminate(); static CodeMarker *markerForCode(const QString& code); static CodeMarker *markerForFileName(const QString& fileName); static CodeMarker *markerForLanguage(const QString& lang); static const Node *nodeForString(const QString& string); static QString stringForNode(const Node *node); protected: bool hurryUp() const { return !slow; } virtual QString sortName(const Node *node); QString protect(const QString &string); QString typified(const QString &string); QString taggedNode(const Node *node); QString linkTag(const Node *node, const QString& body); void insert(FastSection &fastSection, Node *node, SynopsisStyle style, Status status); void append(QList
& sectionList, const FastSection& fastSection); private: QString macName(const Node *parent, const QString &name = QString()); bool slow; static QString defaultLang; static QList markers; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/codeparser.cpp000066400000000000000000000211311215241066400215750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* codeparser.cpp */ #include #include "codeparser.h" #include "node.h" #include "tree.h" QT_BEGIN_NAMESPACE #define COMMAND_COMPAT Doc::alias(QLatin1String("compat")) #define COMMAND_DEPRECATED Doc::alias(QLatin1String("deprecated")) // ### don't document #define COMMAND_INGROUP Doc::alias(QLatin1String("ingroup")) #define COMMAND_INMODULE Doc::alias(QLatin1String("inmodule")) // ### don't document #define COMMAND_INTERNAL Doc::alias(QLatin1String("internal")) #define COMMAND_MAINCLASS Doc::alias(QLatin1String("mainclass")) #define COMMAND_NONREENTRANT Doc::alias(QLatin1String("nonreentrant")) #define COMMAND_OBSOLETE Doc::alias(QLatin1String("obsolete")) #define COMMAND_PRELIMINARY Doc::alias(QLatin1String("preliminary")) #define COMMAND_INPUBLICGROUP Doc::alias(QLatin1String("inpublicgroup")) #define COMMAND_REENTRANT Doc::alias(QLatin1String("reentrant")) #define COMMAND_SINCE Doc::alias(QLatin1String("since")) #define COMMAND_SUBTITLE Doc::alias(QLatin1String("subtitle")) #define COMMAND_THREADSAFE Doc::alias(QLatin1String("threadsafe")) #define COMMAND_TITLE Doc::alias(QLatin1String("title")) QList CodeParser::parsers; /*! The constructor adds this code parser to the static list of code parsers. */ CodeParser::CodeParser() { parsers.prepend(this); } /*! The destructor removes this code parser from the static list of code parsers. */ CodeParser::~CodeParser() { parsers.removeAll(this); } /*! Initializing a code parser is trivial. */ void CodeParser::initializeParser(const Config & /* config */) { // nothing. } /*! Teerminating a code parser is trivial. */ void CodeParser::terminateParser() { // nothing. } QString CodeParser::headerFileNameFilter() { return sourceFileNameFilter(); } void CodeParser::parseHeaderFile(const Location& location, const QString& filePath, Tree *tree) { parseSourceFile(location, filePath, tree); } void CodeParser::doneParsingHeaderFiles(Tree *tree) { doneParsingSourceFiles(tree); } /*! All the code parsers in the static list are initialized here, after the qdoc configuration variables have been set. */ void CodeParser::initialize(const Config& config) { QList::ConstIterator p = parsers.begin(); while (p != parsers.end()) { (*p)->initializeParser(config); ++p; } } /*! All the code parsers in the static list are terminated here. */ void CodeParser::terminate() { QList::ConstIterator p = parsers.begin(); while (p != parsers.end()) { (*p)->terminateParser(); ++p; } } CodeParser *CodeParser::parserForLanguage(const QString& language) { QList::ConstIterator p = parsers.begin(); while (p != parsers.end()) { if ((*p)->language() == language) return *p; ++p; } return 0; } /*! Returns the set of strings representing the common metacommands. */ QSet CodeParser::commonMetaCommands() { return QSet() << COMMAND_COMPAT << COMMAND_DEPRECATED << COMMAND_INGROUP << COMMAND_INMODULE << COMMAND_INTERNAL << COMMAND_MAINCLASS << COMMAND_NONREENTRANT << COMMAND_OBSOLETE << COMMAND_PRELIMINARY << COMMAND_INPUBLICGROUP << COMMAND_REENTRANT << COMMAND_SINCE << COMMAND_SUBTITLE << COMMAND_THREADSAFE << COMMAND_TITLE; } /*! The topic command has been processed. Now process the other metacommands that were found. These are not the text markup commands. */ void CodeParser::processCommonMetaCommand(const Location &location, const QString &command, const QString &arg, Node *node, Tree *tree) { if (command == COMMAND_COMPAT) { node->setStatus(Node::Compat); } else if (command == COMMAND_DEPRECATED) { node->setStatus(Node::Deprecated); } else if (command == COMMAND_INGROUP) { tree->addToGroup(node, arg); } else if (command == COMMAND_INPUBLICGROUP) { tree->addToPublicGroup(node, arg); } else if (command == COMMAND_INMODULE) { node->setModuleName(arg); } else if (command == COMMAND_MAINCLASS) { node->setStatus(Node::Main); } else if (command == COMMAND_OBSOLETE) { if (node->status() != Node::Compat) node->setStatus(Node::Obsolete); } else if (command == COMMAND_NONREENTRANT) { node->setThreadSafeness(Node::NonReentrant); } else if (command == COMMAND_PRELIMINARY) { node->setStatus(Node::Preliminary); } else if (command == COMMAND_INTERNAL) { node->setAccess(Node::Private); node->setStatus(Node::Internal); } else if (command == COMMAND_REENTRANT) { node->setThreadSafeness(Node::Reentrant); } else if (command == COMMAND_SINCE) { node->setSince(arg); } else if (command == COMMAND_SUBTITLE) { if (node->type() == Node::Fake) { FakeNode *fake = static_cast(node); fake->setSubTitle(arg); } else location.warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE)); } else if (command == COMMAND_THREADSAFE) { node->setThreadSafeness(Node::ThreadSafe); } else if (command == COMMAND_TITLE) { if (node->type() == Node::Fake) { FakeNode *fake = static_cast(node); fake->setTitle(arg); #ifdef QDOC2DOX /* qdoc -> doxygen. I think this must be done here, because there can be multiple "\externalpage" and "\title" metacommands in a single qdoc comment, which means, among other things, that the "\title" commands are not inserted into the metacommand map used by the Doc class. I'm sure there4 is a better way to do this in the DoxWriter class using the information in the FakeNode, but I don't have time to figure it out right now. */ if (DoxWriter::isDoxPass(1)) DoxWriter::insertTitle(fake,arg); #endif } else location.warning(tr("Ignored '\\%1'").arg(COMMAND_TITLE)); } } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/codeparser.h000066400000000000000000000062311215241066400212460ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* codeparser.h */ #ifndef CODEPARSER_H #define CODEPARSER_H #include #include "location.h" QT_BEGIN_NAMESPACE class Config; class Node; class QString; class Tree; class CodeParser { public: CodeParser(); virtual ~CodeParser(); virtual void initializeParser(const Config& config); virtual void terminateParser(); virtual QString language() = 0; virtual QString headerFileNameFilter(); virtual QString sourceFileNameFilter() = 0; virtual void parseHeaderFile(const Location& location, const QString& filePath, Tree *tree); virtual void parseSourceFile(const Location& location, const QString& filePath, Tree *tree) = 0; virtual void doneParsingHeaderFiles(Tree *tree); virtual void doneParsingSourceFiles(Tree *tree) = 0; static void initialize(const Config& config); static void terminate(); static CodeParser *parserForLanguage(const QString& language); protected: QSet commonMetaCommands(); void processCommonMetaCommand(const Location& location, const QString& command, const QString& arg, Node *node, Tree *tree); private: static QList parsers; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/command.cpp000066400000000000000000000063231215241066400210720ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* command.cpp */ #include #include "command.h" QT_BEGIN_NAMESPACE void executeCommand( const Location& location, const QString& format, const QStringList& args ) { QString actualCommand; for ( int i = 0; i < (int) format.length(); i++ ) { int ch = format[i].unicode(); if ( ch > 0 && ch < 8 ) { actualCommand += args[ch - 1]; } else { actualCommand += format[i]; } } QString toolName = actualCommand; int space = toolName.indexOf( QLatin1Char(' ') ); if ( space != -1 ) toolName.truncate( space ); QProcess process; process.start(QLatin1String("sh"), QStringList() << QLatin1String("-c") << actualCommand ); process.waitForFinished(); if (process.exitCode() == 127) location.fatal( tr("Couldn't launch the '%1' tool") .arg(toolName), tr("Make sure the tool is installed and in the" " path.") ); QString errors = QString::fromLocal8Bit(process.readAllStandardError()); while ( errors.endsWith(QLatin1Char('\n')) ) errors.truncate( errors.length() - 1 ); if ( !errors.isEmpty() ) location.fatal( tr("The '%1' tool encountered some problems") .arg(toolName), tr("The tool was invoked like this:\n%1\n" "It emitted these errors:\n%2") .arg(actualCommand).arg(errors) ); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/command.h000066400000000000000000000042521215241066400205360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* command.h */ #ifndef COMMAND_H #define COMMAND_H #include #include "location.h" QT_BEGIN_NAMESPACE void executeCommand( const Location& location, const QString& commandFormat, const QStringList& args ); QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/config.cpp000066400000000000000000000633101215241066400207200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* config.cpp */ #include #include "archiveextractor.h" #include "config.h" #include "uncompressor.h" #include QT_BEGIN_NAMESPACE /* An entry on the MetaStack. */ class MetaStackEntry { public: void open(); void close(); QStringList accum; QStringList next; }; /* */ void MetaStackEntry::open() { next.append(QString()); } /* */ void MetaStackEntry::close() { accum += next; next.clear(); } /* ### */ class MetaStack : private QStack { public: MetaStack(); void process(QChar ch, const Location& location); QStringList getExpanded(const Location& location); }; MetaStack::MetaStack() { push(MetaStackEntry()); top().open(); } void MetaStack::process(QChar ch, const Location& location) { if (ch == QLatin1Char('{')) { push(MetaStackEntry()); top().open(); } else if (ch == QLatin1Char('}')) { if (count() == 1) location.fatal(tr("Unexpected '}'")); top().close(); QStringList suffixes = pop().accum; QStringList prefixes = top().next; top().next.clear(); QStringList::ConstIterator pre = prefixes.begin(); while (pre != prefixes.end()) { QStringList::ConstIterator suf = suffixes.begin(); while (suf != suffixes.end()) { top().next << (*pre + *suf); ++suf; } ++pre; } } else if (ch == QLatin1Char(',') && count() > 1) { top().close(); top().open(); } else { QStringList::Iterator pre = top().next.begin(); while (pre != top().next.end()) { *pre += ch; ++pre; } } } QStringList MetaStack::getExpanded(const Location& location) { if (count() > 1) location.fatal(tr("Missing '}'")); top().close(); return top().accum; } QT_STATIC_CONST_IMPL QString Config::dot = QLatin1String("."); QMap Config::uncompressedFiles; QMap Config::extractedDirs; int Config::numInstances; /*! \class Config \brief The Config class contains the configuration variables for controlling how qdoc produces documentation. Its load() function, reads, parses, and processes a qdocconf file. */ /*! The constructor sets the \a programName and initializes all internal state variables to empty values. */ Config::Config(const QString& programName) : prog(programName) { loc = Location::null; lastLoc = Location::null; locMap.clear(); stringValueMap.clear(); stringListValueMap.clear(); numInstances++; } /*! The destructor deletes all the temporary files and directories it built. */ Config::~Config() { if (--numInstances == 0) { QMap::ConstIterator f = uncompressedFiles.begin(); while (f != uncompressedFiles.end()) { QDir().remove(*f); ++f; } uncompressedFiles.clear(); QMap::ConstIterator d = extractedDirs.begin(); while (d != extractedDirs.end()) { removeDirContents(*d); QDir dir(*d); QString name = dir.dirName(); dir.cdUp(); dir.rmdir(name); ++d; } extractedDirs.clear(); } } /*! Loads and parses the qdoc configuration file \a fileName. This function calls the other load() function, which does the loading, parsing, and processing of the configuration file. Intializes the location variables returned by location() and lastLocation(). */ void Config::load(const QString& fileName) { load(Location::null, fileName); if (loc.isEmpty()) { loc = Location(fileName); } else { loc.setEtc(true); } lastLoc = Location::null; } /*! Joins all the strings in \a values into a single string with the individual \a values separated by ' '. Then it inserts the result into the string list map with \a var as the key. It also inserts the \a values string list into a separate map, also with \a var as the key. */ void Config::setStringList(const QString& var, const QStringList& values) { stringValueMap[var] = values.join(QLatin1String(" ")); stringListValueMap[var] = values; } /*! Looks up the configuarion variable \a var in the string map and returns the boolean value. */ bool Config::getBool(const QString& var) const { return QVariant(getString(var)).toBool(); } /*! Looks up the configuration variable \a var in the string list map. Iterates through the string list found, interpreting each string in the list as an integer and adding it to a total sum. Returns the sum. */ int Config::getInt(const QString& var) const { QStringList strs = getStringList(var); QStringList::ConstIterator s = strs.begin(); int sum = 0; while (s != strs.end()) { sum += (*s).toInt(); ++s; } return sum; } /*! First, this function looks up the configuration variable \a var in the location map and, if found, sets the internal variable \c{lastLoc} to the Location that \a var maps to. Then it looks up the configuration variable \a var in the string map, and returns the string that \a var maps to. */ QString Config::getString(const QString& var) const { if (!locMap[var].isEmpty()) (Location&) lastLoc = locMap[var]; return stringValueMap[var]; } /*! Looks up the configuration variable \a var in the string list map, converts the string list it maps to into a set of strings, and returns the set. */ QSet Config::getStringSet(const QString& var) const { return QSet::fromList(getStringList(var)); } /*! First, this function looks up the configuration variable \a var in the location map and, if found, sets the internal variable \c{lastLoc} the Location that \a var maps to. Then it looks up the configuration variable \a var in the string list map, and returns the string list that \a var maps to. */ QStringList Config::getStringList(const QString& var) const { if (!locMap[var].isEmpty()) (Location&) lastLoc = locMap[var]; return stringListValueMap[var]; } /*! Calls getRegExpList() with the control variable \a var and iterates through the resulting list of regular expressions, concatening them with some extras characters to form a single QRegExp, which is returned/ \sa getRegExpList() */ QRegExp Config::getRegExp(const QString& var) const { QString pattern; QList subRegExps = getRegExpList(var); QList::ConstIterator s = subRegExps.begin(); while (s != subRegExps.end()) { if (!(*s).isValid()) return *s; if (!pattern.isEmpty()) pattern += QLatin1Char('|'); pattern += QLatin1String("(?:") + (*s).pattern() + QLatin1Char(')'); ++s; } if (pattern.isEmpty()) pattern = QLatin1String("$x"); // cannot match return QRegExp(pattern); } /*! Looks up the configuration variable \a var in the string list map, converts the string list to a list of regular expressions, and returns it. */ QList Config::getRegExpList(const QString& var) const { QStringList strs = getStringList(var); QStringList::ConstIterator s = strs.begin(); QList regExps; while (s != strs.end()) { regExps += QRegExp(*s); ++s; } return regExps; } /*! This function is slower than it could be. */ QSet Config::subVars(const QString& var) const { QSet result; QString varDot = var + QLatin1Char('.'); QMap::ConstIterator v = stringValueMap.begin(); while (v != stringValueMap.end()) { if (v.key().startsWith(varDot)) { QString subVar = v.key().mid(varDot.length()); int dot = subVar.indexOf(QLatin1Char('.')); if (dot != -1) subVar.truncate(dot); result.insert(subVar); } ++v; } return result; } /*! Builds and returns a list of file pathnames for the file type specified by \a filesVar (e.g. "headers" or "sources"). The files are found in the directories specified by \a dirsVar, and they are filtered by \a defaultNameFilter if a better filter can't be constructed from \a filesVar. The directories in \a excludedDirs are avoided. */ QStringList Config::getAllFiles(const QString &filesVar, const QString &dirsVar, const QString &defaultNameFilter, const QSet &excludedDirs) { QStringList result = getStringList(filesVar); QStringList dirs = getStringList(dirsVar); QString nameFilter = getString(filesVar + dot + QLatin1String(CONFIG_FILEEXTENSIONS)); if (nameFilter.isEmpty()) nameFilter = defaultNameFilter; QStringList::ConstIterator d = dirs.begin(); while (d != dirs.end()) { result += getFilesHere(*d, nameFilter, excludedDirs); ++d; } return result; } /*! */ QString Config::findFile(const Location& location, const QStringList& files, const QStringList& dirs, const QString& fileName, QString& userFriendlyFilePath) { if (fileName.isEmpty() || fileName.startsWith(QLatin1Char('/'))) { userFriendlyFilePath = fileName; return fileName; } QFileInfo fileInfo; QStringList components = fileName.split(QLatin1Char('?')); QString firstComponent = components.first(); QStringList::ConstIterator f = files.begin(); while (f != files.end()) { if (*f == firstComponent || (*f).endsWith(QLatin1Char('/') + firstComponent)) { fileInfo.setFile(*f); if (!fileInfo.exists()) location.fatal(tr("File '%1' does not exist").arg(*f)); break; } ++f; } if (fileInfo.fileName().isEmpty()) { QStringList::ConstIterator d = dirs.begin(); while (d != dirs.end()) { fileInfo.setFile(QDir(*d), firstComponent); if (fileInfo.exists()) { break; } ++d; } } userFriendlyFilePath = QString(); if (!fileInfo.exists()) return QString(); QStringList::ConstIterator c = components.begin(); for (;;) { bool isArchive = (c != components.end() - 1); ArchiveExtractor *extractor = 0; QString userFriendly = *c; if (isArchive) { extractor = ArchiveExtractor::extractorForFileName(userFriendly); } if (extractor == 0) { Uncompressor *uncompressor = Uncompressor::uncompressorForFileName(userFriendly); if (uncompressor != 0) { QString fileNameWithCorrectExtension = uncompressor->uncompressedFilePath( fileInfo.filePath()); QString uncompressed = uncompressedFiles[fileInfo.filePath()]; if (uncompressed.isEmpty()) { uncompressed = QTemporaryFile(fileInfo.filePath()).fileName(); uncompressor->uncompressFile(location, fileInfo.filePath(), uncompressed); uncompressedFiles[fileInfo.filePath()] = uncompressed; } fileInfo.setFile(uncompressed); if (isArchive) { extractor = ArchiveExtractor::extractorForFileName( fileNameWithCorrectExtension); } else { userFriendly = fileNameWithCorrectExtension; } } } userFriendlyFilePath += userFriendly; if (isArchive) { if (extractor == 0) location.fatal(tr("Unknown archive type '%1'") .arg(userFriendlyFilePath)); QString extracted = extractedDirs[fileInfo.filePath()]; if (extracted.isEmpty()) { extracted = QTemporaryFile(fileInfo.filePath()).fileName(); if (!QDir().mkdir(extracted)) location.fatal(tr("Cannot create temporary directory '%1'") .arg(extracted)); extractor->extractArchive(location, fileInfo.filePath(), extracted); extractedDirs[fileInfo.filePath()] = extracted; } ++c; fileInfo.setFile(QDir(extracted), *c); } else { break; } userFriendlyFilePath += "?"; } return fileInfo.filePath(); } /*! */ QString Config::findFile(const Location& location, const QStringList& files, const QStringList& dirs, const QString& fileBase, const QStringList& fileExtensions, QString& userFriendlyFilePath) { QStringList::ConstIterator e = fileExtensions.begin(); while (e != fileExtensions.end()) { QString filePath = findFile(location, files, dirs, fileBase + "." + *e, userFriendlyFilePath); if (!filePath.isEmpty()) return filePath; ++e; } return findFile(location, files, dirs, fileBase, userFriendlyFilePath); } /*! */ QString Config::copyFile(const Location& location, const QString& sourceFilePath, const QString& userFriendlySourceFilePath, const QString& targetDirPath) { QFile inFile(sourceFilePath); if (!inFile.open(QFile::ReadOnly)) { location.fatal(tr("Cannot open input file '%1': %2") .arg(inFile.fileName()).arg(inFile.errorString())); return ""; } QString outFileName = userFriendlySourceFilePath; int slash = outFileName.lastIndexOf("/"); if (slash != -1) outFileName = outFileName.mid(slash); QFile outFile(targetDirPath + "/" + outFileName); if (!outFile.open(QFile::WriteOnly)) { location.fatal(tr("Cannot open output file '%1': %2") .arg(outFile.fileName()).arg(outFile.errorString())); return ""; } char buffer[1024]; int len; while ((len = inFile.read(buffer, sizeof(buffer))) > 0) { outFile.write(buffer, len); } return outFileName; } /*! Finds the largest unicode digit in \a value in the range 1..7 and returns it. */ int Config::numParams(const QString& value) { int max = 0; for (int i = 0; i != value.length(); i++) { uint c = value[i].unicode(); if (c > 0 && c < 8) max = qMax(max, (int)c); } return max; } /*! Removes everything from \a dir. This function is recursive. It doesn't remove \a dir itself, but if it was called recursively, then the caller will remove \a dir. */ bool Config::removeDirContents(const QString& dir) { QDir dirInfo(dir); QFileInfoList entries = dirInfo.entryInfoList(); bool ok = true; QFileInfoList::Iterator it = entries.begin(); while (it != entries.end()) { if ((*it).isFile()) { if (!dirInfo.remove((*it).fileName())) ok = false; } else if ((*it).isDir()) { if ((*it).fileName() != "." && (*it).fileName() != "..") { if (removeDirContents((*it).absoluteFilePath())) { if (!dirInfo.rmdir((*it).fileName())) ok = false; } else { ok = false; } } } ++it; } return ok; } /*! Returns true if \a ch is a letter, number, '_', '.', '{', '}', or ','. */ bool Config::isMetaKeyChar(QChar ch) { return ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char('.') || ch == QLatin1Char('{') || ch == QLatin1Char('}') || ch == QLatin1Char(','); } /*! Load, parse, and process a qdoc configuration file. This function is only called by the other load() function, but this one is recursive, i.e., it calls itself when it sees an \c{include} statement in the qdog configuration file. */ void Config::load(Location location, const QString& fileName) { QRegExp keySyntax("\\w+(?:\\.\\w+)*"); #define SKIP_CHAR() \ do { \ location.advance(c); \ ++i; \ c = text.at(i); \ cc = c.unicode(); \ } while (0) #define SKIP_SPACES() \ while (c.isSpace() && cc != '\n') \ SKIP_CHAR() #define PUT_CHAR() \ word += c; \ SKIP_CHAR(); if (location.depth() > 16) location.fatal(tr("Too many nested includes")); QFile fin(fileName); if (!fin.open(QFile::ReadOnly | QFile::Text)) { fin.setFileName(fileName + ".qdoc"); if (!fin.open(QFile::ReadOnly | QFile::Text)) location.fatal(tr("Cannot open file '%1': %2").arg(fileName).arg(fin.errorString())); } QString text = fin.readAll(); text += QLatin1String("\n\n"); text += QChar('\0'); fin.close(); location.push(fileName); location.start(); int i = 0; QChar c = text.at(0); uint cc = c.unicode(); while (i < (int) text.length()) { if (cc == 0) ++i; else if (c.isSpace()) { SKIP_CHAR(); } else if (cc == '#') { do { SKIP_CHAR(); } while (cc != '\n'); } else if (isMetaKeyChar(c)) { Location keyLoc = location; bool plus = false; QString stringValue; QStringList stringListValue; QString word; bool inQuote = false; bool prevWordQuoted = true; bool metWord = false; MetaStack stack; do { stack.process(c, location); SKIP_CHAR(); } while (isMetaKeyChar(c)); QStringList keys = stack.getExpanded(location); SKIP_SPACES(); if (keys.count() == 1 && keys.first() == "include") { QString includeFile; if (cc != '(') location.fatal(tr("Bad include syntax")); SKIP_CHAR(); SKIP_SPACES(); while (!c.isSpace() && cc != '#' && cc != ')') { includeFile += c; SKIP_CHAR(); } SKIP_SPACES(); if (cc != ')') location.fatal(tr("Bad include syntax")); SKIP_CHAR(); SKIP_SPACES(); if (cc != '#' && cc != '\n') location.fatal(tr("Trailing garbage")); /* Here is the recursive call. */ load(location, QFileInfo(QFileInfo(fileName).dir(), includeFile) .filePath()); } else { /* It wasn't an include statement, so it;s something else. */ if (cc == '+') { plus = true; SKIP_CHAR(); } if (cc != '=') location.fatal(tr("Expected '=' or '+=' after key")); SKIP_CHAR(); SKIP_SPACES(); for (;;) { if (cc == '\\') { int metaCharPos; SKIP_CHAR(); if (cc == '\n') { SKIP_CHAR(); } else if (cc > '0' && cc < '8') { word += QChar(c.digitValue()); SKIP_CHAR(); } else if ((metaCharPos = QString(QLatin1String("abfnrtv")).indexOf(c)) != -1) { word += "\a\b\f\n\r\t\v"[metaCharPos]; SKIP_CHAR(); } else { PUT_CHAR(); } } else if (c.isSpace() || cc == '#') { if (inQuote) { if (cc == '\n') location.fatal(tr("Unterminated string")); PUT_CHAR(); } else { if (!word.isEmpty()) { if (metWord) stringValue += QLatin1Char(' '); stringValue += word; stringListValue << word; metWord = true; word.clear(); prevWordQuoted = false; } if (cc == '\n' || cc == '#') break; SKIP_SPACES(); } } else if (cc == '"') { if (inQuote) { if (!prevWordQuoted) stringValue += QLatin1Char(' '); stringValue += word; if (!word.isEmpty()) stringListValue << word; metWord = true; word.clear(); prevWordQuoted = true; } inQuote = !inQuote; SKIP_CHAR(); } else if (cc == '$') { QString var; SKIP_CHAR(); while (c.isLetterOrNumber() || cc == '_') { var += c; SKIP_CHAR(); } if (!var.isEmpty()) { char *val = getenv(var.toLatin1().data()); if (val == 0) { location.fatal(tr("Environment variable '%1' undefined").arg(var)); } else { word += QString(val); } } } else { if (!inQuote && cc == '=') location.fatal(tr("Unexpected '='")); PUT_CHAR(); } } QStringList::ConstIterator key = keys.begin(); while (key != keys.end()) { if (!keySyntax.exactMatch(*key)) keyLoc.fatal(tr("Invalid key '%1'").arg(*key)); if (plus) { if (locMap[*key].isEmpty()) { locMap[*key] = keyLoc; } else { locMap[*key].setEtc(true); } if (stringValueMap[*key].isEmpty()) { stringValueMap[*key] = stringValue; } else { stringValueMap[*key] += QLatin1Char(' ') + stringValue; } stringListValueMap[*key] += stringListValue; } else { locMap[*key] = keyLoc; stringValueMap[*key] = stringValue; stringListValueMap[*key] = stringListValue; } ++key; } } } else { location.fatal(tr("Unexpected character '%1' at beginning of line") .arg(c)); } } } QStringList Config::getFilesHere(const QString& dir, const QString& nameFilter, const QSet &excludedDirs) { QStringList result; if (excludedDirs.contains(dir)) return result; QDir dirInfo(dir); QStringList fileNames; QStringList::const_iterator fn; dirInfo.setNameFilters(nameFilter.split(' ')); dirInfo.setSorting(QDir::Name); dirInfo.setFilter(QDir::Files); fileNames = dirInfo.entryList(); fn = fileNames.constBegin(); while (fn != fileNames.constEnd()) { if (!fn->startsWith(QLatin1Char('~'))) result.append(dirInfo.filePath(*fn)); ++fn; } dirInfo.setNameFilters(QStringList("*")); dirInfo.setFilter(QDir::Dirs|QDir::NoDotAndDotDot); fileNames = dirInfo.entryList(); fn = fileNames.constBegin(); while (fn != fileNames.constEnd()) { result += getFilesHere(dirInfo.filePath(*fn), nameFilter, excludedDirs); ++fn; } return result; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/config.h000066400000000000000000000154421215241066400203700ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* config.h */ #ifndef CONFIG_H #define CONFIG_H #include #include #include #include "location.h" QT_BEGIN_NAMESPACE class Config { public: Config(const QString& programName); ~Config(); void load(const QString& fileName); void setStringList(const QString& var, const QStringList& values); const QString& programName() const { return prog; } const Location& location() const { return loc; } const Location& lastLocation() const { return lastLoc; } bool getBool(const QString& var) const; int getInt(const QString& var) const; QString getString(const QString& var) const; QSet getStringSet(const QString& var) const; QStringList getStringList(const QString& var) const; QRegExp getRegExp(const QString& var) const; QList getRegExpList(const QString& var) const; QSet subVars(const QString& var) const; QStringList getAllFiles(const QString& filesVar, const QString& dirsVar, const QString& defaultNameFilter, const QSet &excludedDirs = QSet()); static QStringList getFilesHere(const QString& dir, const QString& nameFilter, const QSet &excludedDirs = QSet()); static QString findFile(const Location& location, const QStringList &files, const QStringList& dirs, const QString& fileName, QString& userFriendlyFilePath); static QString findFile(const Location &location, const QStringList &files, const QStringList &dirs, const QString &fileBase, const QStringList &fileExtensions, QString &userFriendlyFilePath); static QString copyFile(const Location& location, const QString& sourceFilePath, const QString& userFriendlySourceFilePath, const QString& targetDirPath); static int numParams(const QString& value); static bool removeDirContents(const QString& dir); QT_STATIC_CONST QString dot; private: static bool isMetaKeyChar(QChar ch); void load(Location location, const QString& fileName); QString prog; Location loc; Location lastLoc; QMap locMap; QMap stringListValueMap; QMap stringValueMap; static QMap uncompressedFiles; static QMap extractedDirs; static int numInstances; }; #define CONFIG_ALIAS "alias" #define CONFIG_BASE "base" // ### don't document for now #define CONFIG_CODEINDENT "codeindent" #define CONFIG_DEFINES "defines" #define CONFIG_DESCRIPTION "description" #define CONFIG_EDITION "edition" #define CONFIG_EXAMPLEDIRS "exampledirs" #define CONFIG_EXAMPLES "examples" #define CONFIG_EXCLUDEDIRS "excludedirs" #define CONFIG_EXTRAIMAGES "extraimages" #define CONFIG_FALSEHOODS "falsehoods" #define CONFIG_FORMATTING "formatting" #define CONFIG_GENERATEINDEX "generateindex" #define CONFIG_HEADERDIRS "headerdirs" #define CONFIG_HEADERS "headers" #define CONFIG_IGNOREDIRECTIVES "ignoredirectives" #define CONFIG_IGNORETOKENS "ignoretokens" #define CONFIG_IMAGEDIRS "imagedirs" #define CONFIG_IMAGES "images" #define CONFIG_INDEXES "indexes" #define CONFIG_LANGUAGE "language" #define CONFIG_MACRO "macro" #define CONFIG_OUTPUTDIR "outputdir" #define CONFIG_OUTPUTLANGUAGE "outputlanguage" #define CONFIG_OUTPUTFORMATS "outputformats" #define CONFIG_PROJECT "project" #define CONFIG_QHP "qhp" #define CONFIG_QUOTINGINFORMATION "quotinginformation" #define CONFIG_SLOW "slow" #define CONFIG_SOURCEDIRS "sourcedirs" #define CONFIG_SOURCES "sources" #define CONFIG_SPURIOUS "spurious" #define CONFIG_STYLESHEETS "stylesheets" #define CONFIG_TABSIZE "tabsize" #define CONFIG_TAGFILE "tagfile" #define CONFIG_TRANSLATORS "translators" // ### don't document for now #define CONFIG_URL "url" #define CONFIG_VERSION "version" #define CONFIG_VERSIONSYM "versionsym" #define CONFIG_FILEEXTENSIONS "fileextensions" QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/cppcodemarker.cpp000066400000000000000000001037131215241066400222740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* cppcodemarker.cpp */ #include "atom.h" #include "cppcodemarker.h" #include "node.h" #include "text.h" #include "tree.h" QT_BEGIN_NAMESPACE static int insertTagAround(QString &result, int pos, int len, const QString &tagName, const QString &attributes = QString()) { QString s; //s.reserve(result.size() + tagName.size() * 2 + attributes.size() + 20); s += result.midRef(0, pos); s += QLatin1Char('<'); s += tagName; if (!attributes.isEmpty()) { s += QLatin1Char(' '); s += attributes; } s += QLatin1Char('>'); s += result.midRef(pos, len); s += QLatin1String("'); s += result.midRef(pos + len); int diff = s.length() - result.length(); result = s; return diff; } /*! The constructor does nothing. */ CppCodeMarker::CppCodeMarker() { // nothing. } /*! The destructor does nothing. */ CppCodeMarker::~CppCodeMarker() { // nothing. } /*! Returns true. */ bool CppCodeMarker::recognizeCode(const QString & /* code */) { return true; } /*! Returns true if \a ext is any of a list of file extensions for the C++ language. */ bool CppCodeMarker::recognizeExtension(const QString& ext) { return ext == "c" || ext == "c++" || ext == "cc" || ext == "cpp" || ext == "cxx" || ext == "ch" || ext == "h" || ext == "h++" || ext == "hh" || ext == "hpp" || ext == "hxx"; } /*! Returns true if \a lang is either "C" or "Cpp". */ bool CppCodeMarker::recognizeLanguage(const QString &lang) { return lang == "C" || lang == "Cpp"; } /*! Returns the \a node name, or "()" if \a node is a Node::Function node. */ QString CppCodeMarker::plainName(const Node *node) { QString name = node->name(); if (node->type() == Node::Function) name += "()"; return name; } QString CppCodeMarker::plainFullName(const Node *node, const Node *relative) { if (node->name().isEmpty()) { return "global"; } else { QString fullName; for (;;) { fullName.prepend(plainName(node)); if (node->parent() == relative || node->parent()->name().isEmpty()) break; fullName.prepend("::"); node = node->parent(); } return fullName; } } QString CppCodeMarker::markedUpCode(const QString &code, const Node *relative, const QString &dirPath) { return addMarkUp(protect(code), relative, dirPath); } QString CppCodeMarker::markedUpSynopsis(const Node *node, const Node * /* relative */, SynopsisStyle style) { const int MaxEnumValues = 6; const FunctionNode *func; const PropertyNode *property; const VariableNode *variable; const EnumNode *enume; const TypedefNode *typedeff; QString synopsis; QString extra; QString name; name = taggedNode(node); if (style != Detailed) name = linkTag(node, name); name = "<@name>" + name + ""; if (style == Detailed && !node->parent()->name().isEmpty() && node->type() != Node::Property) name.prepend(taggedNode(node->parent()) + "::"); switch (node->type()) { case Node::Namespace: synopsis = "namespace " + name; break; case Node::Class: synopsis = "class " + name; break; case Node::Function: func = (const FunctionNode *) node; if (style != SeparateList && !func->returnType().isEmpty()) synopsis = typified(func->returnType()) + " "; synopsis += name; if (func->metaness() != FunctionNode::MacroWithoutParams) { synopsis += " ("; if (!func->parameters().isEmpty()) { synopsis += " "; QList::ConstIterator p = func->parameters().begin(); while (p != func->parameters().end()) { if (p != func->parameters().begin()) synopsis += ", "; synopsis += typified((*p).leftType()); if (style != SeparateList && !(*p).name().isEmpty()) synopsis += " <@param>" + protect((*p).name()) + ""; synopsis += protect((*p).rightType()); if (style != SeparateList && !(*p).defaultValue().isEmpty()) synopsis += " = " + protect((*p).defaultValue()); ++p; } synopsis += " "; } synopsis += ")"; } if (func->isConst()) synopsis += " const"; if (style == Summary || style == Accessors) { if (func->virtualness() != FunctionNode::NonVirtual) synopsis.prepend("virtual "); if (func->virtualness() == FunctionNode::PureVirtual) synopsis.append(" = 0"); } else if (style == SeparateList) { if (!func->returnType().isEmpty() && func->returnType() != "void") synopsis += " : " + typified(func->returnType()); } else { QStringList bracketed; if (func->isStatic()) { bracketed += "static"; } else if (func->virtualness() != FunctionNode::NonVirtual) { if (func->virtualness() == FunctionNode::PureVirtual) bracketed += "pure"; bracketed += "virtual"; } if (func->access() == Node::Protected) { bracketed += "protected"; } else if (func->access() == Node::Private) { bracketed += "private"; } if (func->metaness() == FunctionNode::Signal) { bracketed += "signal"; } else if (func->metaness() == FunctionNode::Slot) { bracketed += "slot"; } if (!bracketed.isEmpty()) extra += " [" + bracketed.join(" ") + "]"; } break; case Node::Enum: enume = static_cast(node); synopsis = "enum " + name; if (style == Summary) { synopsis += " { "; QStringList documentedItems = enume->doc().enumItemNames(); if (documentedItems.isEmpty()) { foreach (const EnumItem &item, enume->items()) documentedItems << item.name(); } QStringList omitItems = enume->doc().omitEnumItemNames(); foreach (const QString &item, omitItems) documentedItems.removeAll(item); if (documentedItems.size() <= MaxEnumValues) { for (int i = 0; i < documentedItems.size(); ++i) { if (i != 0) synopsis += ", "; synopsis += documentedItems.at(i); } } else { for (int i = 0; i < documentedItems.size(); ++i) { if (i < MaxEnumValues - 2 || i == documentedItems.size() - 1) { if (i != 0) synopsis += ", "; synopsis += documentedItems.at(i); } else if (i == MaxEnumValues - 1) { synopsis += ", ..."; } } } if (!documentedItems.isEmpty()) synopsis += " "; synopsis += "}"; } break; case Node::Typedef: typedeff = static_cast(node); if (typedeff->associatedEnum()) { synopsis = "flags " + name; } else { synopsis = "typedef " + name; } break; case Node::Property: property = static_cast(node); synopsis = name + " : " + typified(property->qualifiedDataType()); break; case Node::Variable: variable = static_cast(node); if (style == SeparateList) { synopsis = name + " : " + typified(variable->dataType()); } else { synopsis = typified(variable->leftType()) + " " + name + protect(variable->rightType()); } break; default: synopsis = name; } if (style == Summary) { if (node->status() == Node::Preliminary) { extra += " (preliminary)"; } else if (node->status() == Node::Deprecated) { extra += " (deprecated)"; } else if (node->status() == Node::Obsolete) { extra += " (obsolete)"; } } if (!extra.isEmpty()) { extra.prepend("<@extra>"); extra.append(""); } return synopsis + extra; } QString CppCodeMarker::markedUpName(const Node *node) { QString name = linkTag(node, taggedNode(node)); if (node->type() == Node::Function) name += "()"; return name; } QString CppCodeMarker::markedUpFullName(const Node *node, const Node *relative) { if (node->name().isEmpty()) { return "global"; } else { QString fullName; for (;;) { fullName.prepend(markedUpName(node)); if (node->parent() == relative || node->parent()->name().isEmpty()) break; fullName.prepend("<@op>::"); node = node->parent(); } return fullName; } } QString CppCodeMarker::markedUpEnumValue(const QString &enumValue, const Node *relative) { const Node *node = relative->parent(); QString fullName; while (node->parent()) { fullName.prepend(markedUpName(node)); if (node->parent() == relative || node->parent()->name().isEmpty()) break; fullName.prepend("<@op>::"); node = node->parent(); } if (!fullName.isEmpty()) fullName.append("<@op>::"); fullName.append(enumValue); return fullName; } QString CppCodeMarker::markedUpIncludes(const QStringList& includes) { QString code; QStringList::ConstIterator inc = includes.begin(); while (inc != includes.end()) { code += "#include <<@headerfile>" + *inc + ">\n"; ++inc; } return addMarkUp(code, 0, ""); } QString CppCodeMarker::functionBeginRegExp(const QString& funcName) { return "^" + QRegExp::escape(funcName) + "$"; } QString CppCodeMarker::functionEndRegExp(const QString& /* funcName */) { return "^\\}$"; } QList
CppCodeMarker::sections(const InnerNode *inner, SynopsisStyle style, Status status) { QList
sections; if (inner->type() == Node::Class) { const ClassNode *classe = static_cast(inner); if (style == Summary) { FastSection privateFunctions(classe, "Private Functions", "private function", "private functions"); FastSection privateSlots(classe, "Private Slots", "private slot", "private slots"); FastSection privateTypes(classe, "Private Types", "private type", "private types"); FastSection protectedFunctions(classe, "Protected Functions", "protected function", "protected functions"); FastSection protectedSlots(classe, "Protected Slots", "protected slot", "protected slots"); FastSection protectedTypes(classe, "Protected Types", "protected type", "protected types"); FastSection protectedVariables(classe, "Protected Variables", "protected type", "protected variables"); FastSection publicFunctions(classe, "Public Functions", "public function", "public functions"); FastSection publicSignals(classe, "Signals", "signal", "signals"); FastSection publicSlots(classe, "Public Slots", "public slot", "public slots"); FastSection publicTypes(classe, "Public Types", "public type", "public types"); FastSection publicVariables(classe, "Public Variables", "public type", "public variables"); FastSection properties(classe, "Properties", "property", "properties"); FastSection relatedNonMembers(classe, "Related Non-Members", "related non-member", "related non-members"); FastSection staticPrivateMembers(classe, "Static Private Members", "static private member", "static private members"); FastSection staticProtectedMembers(classe, "Static Protected Members", "static protected member", "static protected members"); FastSection staticPublicMembers(classe, "Static Public Members", "static public member", "static public members"); FastSection macros(inner, "Macros", "macro", "macros"); NodeList::ConstIterator r = classe->relatedNodes().begin(); while (r != classe->relatedNodes().end()) { if ((*r)->type() == Node::Function) { FunctionNode *func = static_cast(*r); if (func->isMacro()) insert(macros, *r, style, status); else insert(relatedNonMembers, *r, style, status); } else { insert(relatedNonMembers, *r, style, status); } ++r; } QStack stack; stack.push(classe); while (!stack.isEmpty()) { const ClassNode *ancestorClass = stack.pop(); NodeList::ConstIterator c = ancestorClass->childNodes().begin(); while (c != ancestorClass->childNodes().end()) { bool isSlot = false; bool isSignal = false; bool isStatic = false; if ((*c)->type() == Node::Function) { const FunctionNode *func = (const FunctionNode *) *c; isSlot = (func->metaness() == FunctionNode::Slot); isSignal = (func->metaness() == FunctionNode::Signal); isStatic = func->isStatic(); } else if ((*c)->type() == Node::Variable) { const VariableNode *var = static_cast(*c); isStatic = var->isStatic(); } switch ((*c)->access()) { case Node::Public: if (isSlot) { insert(publicSlots, *c, style, status); } else if (isSignal) { insert(publicSignals, *c, style, status); } else if (isStatic) { if ((*c)->type() != Node::Variable || !(*c)->doc().isEmpty()) insert(staticPublicMembers, *c, style, status); } else if ((*c)->type() == Node::Property) { insert(properties, *c, style, status); } else if ((*c)->type() == Node::Variable) { if (!(*c)->doc().isEmpty()) insert(publicVariables, *c, style, status); } else if ((*c)->type() == Node::Function) { insert(publicFunctions, *c, style, status); } else { insert(publicTypes, *c, style, status); } break; case Node::Protected: if (isSlot) { insert(protectedSlots, *c, style, status); } else if (isStatic) { if ((*c)->type() != Node::Variable || !(*c)->doc().isEmpty()) insert(staticProtectedMembers, *c, style, status); } else if ((*c)->type() == Node::Variable) { if (!(*c)->doc().isEmpty()) insert(protectedVariables, *c, style, status); } else if ((*c)->type() == Node::Function) { insert(protectedFunctions, *c, style, status); } else { insert(protectedTypes, *c, style, status); } break; case Node::Private: if (isSlot) { insert(privateSlots, *c, style, status); } else if (isStatic) { if ((*c)->type() != Node::Variable || !(*c)->doc().isEmpty()) insert(staticPrivateMembers, *c, style, status); } else if ((*c)->type() == Node::Function) { insert(privateFunctions, *c, style, status); } else { insert(privateTypes, *c, style, status); } } ++c; } QList::ConstIterator r = ancestorClass->baseClasses().begin(); while (r != ancestorClass->baseClasses().end()) { stack.prepend((*r).node); ++r; } } append(sections, publicTypes); append(sections, properties); append(sections, publicFunctions); append(sections, publicSlots); append(sections, publicSignals); append(sections, publicVariables); append(sections, staticPublicMembers); append(sections, protectedTypes); append(sections, protectedFunctions); append(sections, protectedSlots); append(sections, protectedVariables); append(sections, staticProtectedMembers); append(sections, privateTypes); append(sections, privateFunctions); append(sections, privateSlots); append(sections, staticPrivateMembers); append(sections, relatedNonMembers); append(sections, macros); } else if (style == Detailed) { FastSection memberFunctions(classe,"Member Function Documentation"); FastSection memberTypes(classe,"Member Type Documentation"); FastSection memberVariables(classe,"Member Variable Documentation"); FastSection properties(classe,"Property Documentation"); FastSection relatedNonMembers(classe,"Related Non-Members"); FastSection macros(classe,"Macro Documentation"); NodeList::ConstIterator r = classe->relatedNodes().begin(); while (r != classe->relatedNodes().end()) { if ((*r)->type() == Node::Function) { FunctionNode *func = static_cast(*r); if (func->isMacro()) insert(macros, *r, style, status); else insert(relatedNonMembers, *r, style, status); } else { insert(relatedNonMembers, *r, style, status); } ++r; } NodeList::ConstIterator c = classe->childNodes().begin(); while (c != classe->childNodes().end()) { if ((*c)->type() == Node::Enum || (*c)->type() == Node::Typedef) { insert(memberTypes, *c, style, status); } else if ((*c)->type() == Node::Property) { insert(properties, *c, style, status); } else if ((*c)->type() == Node::Variable) { if (!(*c)->doc().isEmpty()) insert(memberVariables, *c, style, status); } else if ((*c)->type() == Node::Function) { FunctionNode *function = static_cast(*c); if (!function->associatedProperty()) insert(memberFunctions, function, style, status); } ++c; } append(sections, memberTypes); append(sections, properties); append(sections, memberFunctions); append(sections, memberVariables); append(sections, relatedNonMembers); append(sections, macros); } else { FastSection all(classe); QStack stack; stack.push(classe); while (!stack.isEmpty()) { const ClassNode *ancestorClass = stack.pop(); NodeList::ConstIterator c = ancestorClass->childNodes().begin(); while (c != ancestorClass->childNodes().end()) { if ((*c)->access() != Node::Private && (*c)->type() != Node::Property) insert(all, *c, style, status); ++c; } QList::ConstIterator r = ancestorClass->baseClasses().begin(); while (r != ancestorClass->baseClasses().end()) { stack.prepend((*r).node); ++r; } } append(sections, all); } } else { if (style == Summary || style == Detailed) { FastSection namespaces(inner, "Namespaces", "namespace", "namespaces"); FastSection classes(inner, "Classes", "class", "classes"); FastSection types(inner, style == Summary ? "Types" : "Type Documentation", "type", "types"); FastSection functions(inner, style == Summary ? "Functions" : "Function Documentation", "function", "functions"); FastSection macros(inner, style == Summary ? "Macros" : "Macro Documentation", "macro", "macros"); NodeList nodeList = inner->childNodes(); nodeList += inner->relatedNodes(); NodeList::ConstIterator n = nodeList.begin(); while (n != nodeList.end()) { switch ((*n)->type()) { case Node::Namespace: insert(namespaces, *n, style, status); break; case Node::Class: insert(classes, *n, style, status); break; case Node::Enum: case Node::Typedef: insert(types, *n, style, status); break; case Node::Function: { FunctionNode *func = static_cast(*n); if (func->isMacro()) insert(macros, *n, style, status); else insert(functions, *n, style, status); } break; default: ; } ++n; } append(sections, namespaces); append(sections, classes); append(sections, types); append(sections, functions); append(sections, macros); } } return sections; } const Node *CppCodeMarker::resolveTarget(const QString &target, const Tree *tree, const Node *relative) { if (target.endsWith("()")) { const FunctionNode *func; QString funcName = target; funcName.chop(2); QStringList path = funcName.split("::"); if ((func = tree->findFunctionNode(path, relative, Tree::SearchBaseClasses)) && func->metaness() != FunctionNode::MacroWithoutParams) return func; } else if (target.contains("#")) { // ### this doesn't belong here; get rid of TargetNode hack int hashAt = target.indexOf("#"); QString link = target.left(hashAt); QString ref = target.mid(hashAt + 1); const Node *node; if (link.isEmpty()) { node = relative; } else { QStringList path(link); node = tree->findNode(path, tree->root(), Tree::SearchBaseClasses); } if (node && node->isInnerNode()) { const Atom *atom = node->doc().body().firstAtom(); while (atom) { if (atom->type() == Atom::Target && atom->string() == ref) { Node *parentNode = const_cast(node); return new TargetNode(static_cast(parentNode), ref); } atom = atom->next(); } } } else { QStringList path = target.split("::"); const Node *node; if ((node = tree->findNode(path, relative, Tree::SearchBaseClasses | Tree::SearchEnumValues | Tree::NonFunction))) return node; } return 0; } QString CppCodeMarker::addMarkUp(const QString& protectedCode, const Node * /* relative */, const QString& /* dirPath */) { static QRegExp globalInclude("#include +<([^<>&]+)>"); static QRegExp yHasTypeX("(?:^|\n *)([a-zA-Z_][a-zA-Z_0-9]*)" "(?:<[^;{}]+>)?(?: *(?:\\*|&) *| +)" "([a-zA-Z_][a-zA-Z_0-9]*)? *[,;()=]"); static QRegExp xNewY("([a-zA-Z_][a-zA-Z_0-9]*) *= *new +([a-zA-Z_0-9]+)"); static QRegExp xDotY("\\b([a-zA-Z_][a-zA-Z_0-9]*) *(?:\\.|->|,[ \n]*S(?:IGNAL|LOT)\\() *" "([a-zA-Z_][a-zA-Z_0-9]*)(?= *\\()"); static QRegExp xIsStaticZOfY("[\n:;{(=] *(([a-zA-Z_0-9]+)::([a-zA-Z_0-9]+))(?= *\\()"); static QRegExp classX("[:,][ \n]*(?:p(?:ublic|r(?:otected|ivate))[ \n]+)?" "([a-zA-Z_][a-zA-Z_0-9]*)"); static QRegExp globalX("[\n{()=] *([a-zA-Z_][a-zA-Z_0-9]*)[ \n]*\\("); static QRegExp multiLineComment("/(?:( )?\\*(?:[^*]+|\\*(?! /))*\\*\\1/)"); multiLineComment.setMinimal(true); static QRegExp singleLineComment("//(?!!)[^!\n]*"); static QRegExp preprocessor("(?:^|\n)(#[ \t]*(?:include|if|elif|endif|error|pragma|define" "|warning)(?:(?:\\\\\n|\\n#)[^\n]*)*)"); static QRegExp literals(""(?:[^\\\\&]|\\\\[^\n]|&(?!quot;))*"" "|'(?:[^\\\\]|\\\\(?:[^x0-9']|x[0-9a-f]{1,4}|[0-9]{1,3}))'"); QString result = protectedCode; int pos; if (!hurryUp()) { /* Mark global includes. For example: #include <<@headerfile>QString */ pos = 0; while ((pos = result.indexOf(globalInclude, pos)) != -1) pos += globalInclude.matchedLength() + insertTagAround(result, globalInclude.pos(1), globalInclude.cap(1).length(), "@headerfile"); /* Look for variable definitions and similar constructs, mark the data type, and remember the type of the variable. */ QMap > typesForVariable; pos = 0; while ((pos = yHasTypeX.indexIn(result, pos)) != -1) { QString x = yHasTypeX.cap(1); QString y = yHasTypeX.cap(2); if (!y.isEmpty()) typesForVariable[y].insert(x); /* Without the minus one at the end, 'void member(Class var)' would give 'member' as a variable of type 'void', but would ignore 'Class var'. (### Is that true?) */ pos += yHasTypeX.matchedLength() + insertTagAround(result, yHasTypeX.pos(1), x.length(), "@type") - 1; } /* Do syntax highlighting of preprocessor directives. */ pos = 0; while ((pos = preprocessor.indexIn(result, pos)) != -1) pos += preprocessor.matchedLength() + insertTagAround(result, preprocessor.pos(1), preprocessor.cap(1).length(), "@preprocessor"); /* Deal with string and character literals. */ pos = 0; while ((pos = literals.indexIn(result, pos)) != -1) pos += literals.matchedLength() + insertTagAround(result, pos, literals.matchedLength(), result.at(pos) == QLatin1Char(' ') ? "@string" : "@char"); /* Look for 'var = new Class'. */ pos = 0; while ((pos = xNewY.indexIn(result, pos)) != -1) { QString x = xNewY.cap(1); QString y = xNewY.cap(2); typesForVariable[x].insert(y); pos += xNewY.matchedLength() + insertTagAround(result, xNewY.pos(2), y.length(), "@type"); } /* Insert some stuff that cannot harm. */ typesForVariable["qApp"].insert("QApplication"); /* Add link to ': Class'. */ pos = 0; while ((pos = classX.indexIn(result, pos)) != -1) pos += classX.matchedLength() + insertTagAround(result, classX.pos(1), classX.cap(1).length(), "@type") - 1; /* Find use of any of var.method() var->method() var, SIGNAL(method()) var, SLOT(method()). */ pos = 0; while ((pos = xDotY.indexIn(result, pos)) != -1) { QString x = xDotY.cap(1); QString y = xDotY.cap(2); QSet types = typesForVariable.value(x); pos += xDotY.matchedLength() + insertTagAround(result, xDotY.pos(2), xDotY.cap(2).length(), "@func", (types.count() == 1) ? "target=\"" + protect(*types.begin() + "::" + y) + "()\"" : QString()); } /* Add link to 'Class::method()'. */ pos = 0; while ((pos = xIsStaticZOfY.indexIn(result, pos)) != -1) { QString x = xIsStaticZOfY.cap(1); QString z = xIsStaticZOfY.cap(3); pos += insertTagAround(result, xIsStaticZOfY.pos(3), z.length(), "@func", "target=\"" + protect(x) + "()\""); pos += insertTagAround(result, xIsStaticZOfY.pos(2), xIsStaticZOfY.cap(2).length(), "@type"); pos += xIsStaticZOfY.matchedLength() - 1; } /* Add link to 'globalFunction()'. */ pos = 0; while ((pos = globalX.indexIn(result, pos)) != -1) { QString x = globalX.cap(1); if (x != "QT_FORWARD_DECLARE_CLASS") { pos += globalX.matchedLength() + insertTagAround(result, globalX.pos(1), x.length(), "@func", "target=\"" + protect(x) + "()\"") - 1; } else pos += globalX.matchedLength(); } } /* Do syntax highlighting of comments. Also alter the code in a minor way, so that we can include comments in documentation comments. */ pos = 0; while (pos != -1) { int mlpos; int slpos; int len; slpos = singleLineComment.indexIn(result, pos); mlpos = multiLineComment.indexIn(result, pos); if (slpos == -1 && mlpos == -1) break; if (slpos == -1) { pos = mlpos; len = multiLineComment.matchedLength(); } else if (mlpos == -1) { pos = slpos; len = singleLineComment.matchedLength(); } else { if (slpos < mlpos) { pos = slpos; len = singleLineComment.matchedLength(); } else { pos = mlpos; len = multiLineComment.matchedLength(); } } if (result.at(pos + 1) == QLatin1Char(' ')) { result.remove(pos + len - 2, 1); result.remove(pos + 1, 1); len -= 2; forever { int endcodePos = result.indexOf("\\ endcode", pos); if (endcodePos == -1 || endcodePos >= pos + len) break; result.remove(endcodePos + 1, 1); len -= 1; } } pos += len + insertTagAround(result, pos, len, "@comment"); } return result; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/cppcodemarker.h000066400000000000000000000067651215241066400217520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* cppcodemarker.h */ #ifndef CPPCODEMARKER_H #define CPPCODEMARKER_H #include "codemarker.h" QT_BEGIN_NAMESPACE class CppCodeMarker : public CodeMarker { public: CppCodeMarker(); ~CppCodeMarker(); bool recognizeCode(const QString& code); bool recognizeExtension(const QString& ext); bool recognizeLanguage(const QString& lang); QString plainName(const Node *node); QString plainFullName(const Node *node, const Node *relative); QString markedUpCode(const QString& code, const Node *relative, const QString& dirPath); QString markedUpSynopsis(const Node *node, const Node *relative, SynopsisStyle style); QString markedUpName(const Node *node); QString markedUpFullName(const Node *node, const Node *relative); QString markedUpEnumValue(const QString &enumValue, const Node *relative); QString markedUpIncludes(const QStringList& includes); QString functionBeginRegExp(const QString& funcName); QString functionEndRegExp(const QString& funcName); QList
sections(const InnerNode *innerNode, SynopsisStyle style, Status status); const Node *resolveTarget(const QString& target, const Tree *tree, const Node *relative); private: QString addMarkUp(const QString& protectedCode, const Node *relative, const QString& dirPath); }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/cppcodeparser.cpp000066400000000000000000002033411215241066400223050ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* cppcodeparser.cpp */ #include #include #include #include "codechunk.h" #include "config.h" #include "cppcodeparser.h" #include "tokenizer.h" #include "tree.h" QT_BEGIN_NAMESPACE /* qmake ignore Q_OBJECT */ #define COMMAND_CLASS Doc::alias("class") #define COMMAND_CONTENTSPAGE Doc::alias("contentspage") #define COMMAND_ENUM Doc::alias("enum") #define COMMAND_EXAMPLE Doc::alias("example") #define COMMAND_EXTERNALPAGE Doc::alias("externalpage") #define COMMAND_FILE Doc::alias("file") // ### don't document #define COMMAND_FN Doc::alias("fn") #define COMMAND_GROUP Doc::alias("group") #define COMMAND_HEADERFILE Doc::alias("headerfile") #define COMMAND_INDEXPAGE Doc::alias("indexpage") #define COMMAND_INHEADERFILE Doc::alias("inheaderfile") // ### don't document #define COMMAND_MACRO Doc::alias("macro") #define COMMAND_MODULE Doc::alias("module") // ### don't document #define COMMAND_NAMESPACE Doc::alias("namespace") #define COMMAND_OVERLOAD Doc::alias("overload") #define COMMAND_NEXTPAGE Doc::alias("nextpage") #define COMMAND_PAGE Doc::alias("page") #define COMMAND_PREVIOUSPAGE Doc::alias("previouspage") #define COMMAND_PROPERTY Doc::alias("property") #define COMMAND_REIMP Doc::alias("reimp") #define COMMAND_RELATES Doc::alias("relates") #define COMMAND_SERVICE Doc::alias("service") #define COMMAND_STARTPAGE Doc::alias("startpage") #define COMMAND_TYPEDEF Doc::alias("typedef") #define COMMAND_VARIABLE Doc::alias("variable") #ifdef QDOC_QML #define COMMAND_QMLCLASS Doc::alias("qmlclass") #define COMMAND_QMLPROPERTY Doc::alias("qmlproperty") #endif QStringList CppCodeParser::exampleFiles; QStringList CppCodeParser::exampleDirs; static void extractPageLinkAndDesc(const QString &arg, QString *link, QString *desc) { QRegExp bracedRegExp("\\{([^{}]*)\\}(?:\\{([^{}]*)\\})?"); if (bracedRegExp.exactMatch(arg)) { *link = bracedRegExp.cap(1); *desc = bracedRegExp.cap(2); if (desc->isEmpty()) *desc = *link; } else { int spaceAt = arg.indexOf(" "); if (arg.contains(".html") && spaceAt != -1) { *link = arg.left(spaceAt).trimmed(); *desc = arg.mid(spaceAt).trimmed(); } else { *link = arg; *desc = arg; } } } static void setLink(Node *node, Node::LinkType linkType, const QString &arg) { QString link; QString desc; extractPageLinkAndDesc(arg, &link, &desc); node->setLink(linkType, link, desc); } /* This is used for fuzzy matching only, which in turn is only used for Qt Jambi. */ static QString cleanType(const QString &type, const Tree *tree) { QString result = type; result.replace("qlonglong", "long long"); result.replace("qulonglong", "unsigned long long"); result.replace("qreal", "double"); result.replace(QRegExp("\\bu(int|short|char|long)\\b"), "unsigned \\1"); result.replace("QRgb", "unsigned int"); result.replace(" >", ">"); result.remove(" const[]"); result.replace("QStringList", "QStringList"); result.replace("qint8", "char"); result.replace("qint16", "short"); result.replace("qint32", "int"); result.replace("qint64", "long long"); result.replace("quint8", "unsigned char"); result.replace("quint16", "unsigned short"); result.replace("quint32", "unsigned int"); result.replace("quint64", "unsigned long long"); if (result.contains("QFlags")) { QRegExp regExp("QFlags<(((?:[^<>]+::)*)([^<>:]+))>"); int pos = 0; while ((pos = result.indexOf(regExp, pos)) != -1) { // we assume that the path for the associated enum // is the same as for the flag typedef QStringList path = regExp.cap(2).split("::", QString::SkipEmptyParts); const EnumNode *enume = static_cast( tree->findNode(QStringList(path) << regExp.cap(3), Node::Enum)); if (enume && enume->flagsType()) result.replace(pos, regExp.matchedLength(), (QStringList(path) << enume->flagsType()->name()).join("::")); ++pos; } } if (result.contains("::")) { // remove needless (and needful) class prefixes QRegExp regExp("[A-Za-z0-9_]+::"); result.replace(regExp, ""); } return result; } /*! The constructor initializes some regular expressions and calls reset(). */ CppCodeParser::CppCodeParser() : varComment("/\\*\\s*([a-zA-Z_0-9]+)\\s*\\*/"), sep("(?:<[^>]+>)?::") { reset(0); } /*! The destructor is trivial. */ CppCodeParser::~CppCodeParser() { } void CppCodeParser::initializeParser(const Config &config) { CodeParser::initializeParser(config); nodeTypeMap.insert(COMMAND_NAMESPACE, Node::Namespace); nodeTypeMap.insert(COMMAND_CLASS, Node::Class); nodeTypeMap.insert(COMMAND_SERVICE, Node::Class); nodeTypeMap.insert(COMMAND_ENUM, Node::Enum); nodeTypeMap.insert(COMMAND_TYPEDEF, Node::Typedef); nodeTypeMap.insert(COMMAND_PROPERTY, Node::Property); nodeTypeMap.insert(COMMAND_VARIABLE, Node::Variable); #ifdef QDOC_QML // nodeTypeMap.insert(COMMAND_QMLCLASS, Node::Class); nodeTypeMap.insert(COMMAND_QMLPROPERTY, Node::Property); #endif exampleFiles = config.getStringList(CONFIG_EXAMPLES); exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS); QStringList exampleFilePatterns = config.getStringList( CONFIG_EXAMPLES + Config::dot + CONFIG_FILEEXTENSIONS); if (!exampleFilePatterns.isEmpty()) exampleNameFilter = exampleFilePatterns.join(" "); else exampleNameFilter = "*.cpp *.h *.js *.xq *.svg *.xml *.ui"; } void CppCodeParser::terminateParser() { nodeTypeMap.clear(); CodeParser::terminateParser(); } QString CppCodeParser::language() { return "Cpp"; } QString CppCodeParser::headerFileNameFilter() { return "*.ch *.h *.h++ *.hh *.hpp *.hxx"; } QString CppCodeParser::sourceFileNameFilter() { return "*.c++ *.cc *.cpp *.cxx"; } /*! Parse the C++ header file identified by \a filePath and add the parsed contents to the big \a tree. The \a location is used for reporting errors. */ void CppCodeParser::parseHeaderFile(const Location& location, const QString& filePath, Tree *tree) { FILE *in = fopen(QFile::encodeName(filePath), "r"); if (!in) { location.error(tr("Cannot open C++ header file '%1'").arg(filePath)); return; } reset(tree); Location fileLocation(filePath); Tokenizer fileTokenizer(fileLocation, in); tokenizer = &fileTokenizer; readToken(); matchDeclList(tree->root()); if (!fileTokenizer.version().isEmpty()) tree->setVersion(fileTokenizer.version()); fclose(in); if (fileLocation.fileName() == "qiterator.h") parseQiteratorDotH(location, filePath); } /*! Get ready to parse the C++ cpp file identified by \a filePath and add its parsed contents to the big \a tree. \a location is used for reporting errors. Call matchDocsAndStuff() to do all the parsing and tree building. */ void CppCodeParser::parseSourceFile(const Location& location, const QString& filePath, Tree *tree) { FILE *in = fopen(QFile::encodeName(filePath), "r"); if (!in) { location.error(tr("Cannot open C++ source file '%1'").arg(filePath)); return; } reset(tree); Location fileLocation(filePath); Tokenizer fileTokenizer(fileLocation, in); tokenizer = &fileTokenizer; readToken(); usedNamespaces.clear(); matchDocsAndStuff(); fclose(in); } void CppCodeParser::doneParsingHeaderFiles(Tree *tree) { tree->resolveInheritance(); QMapIterator i(sequentialIteratorClasses); while (i.hasNext()) { i.next(); instantiateIteratorMacro(i.key(), i.value(), sequentialIteratorDefinition, tree); } i = mutableSequentialIteratorClasses; while (i.hasNext()) { i.next(); instantiateIteratorMacro(i.key(), i.value(), mutableSequentialIteratorDefinition, tree); } i = associativeIteratorClasses; while (i.hasNext()) { i.next(); instantiateIteratorMacro(i.key(), i.value(), associativeIteratorDefinition, tree); } i = mutableAssociativeIteratorClasses; while (i.hasNext()) { i.next(); instantiateIteratorMacro(i.key(), i.value(), mutableAssociativeIteratorDefinition, tree); } sequentialIteratorDefinition.clear(); mutableSequentialIteratorDefinition.clear(); associativeIteratorDefinition.clear(); mutableAssociativeIteratorDefinition.clear(); sequentialIteratorClasses.clear(); mutableSequentialIteratorClasses.clear(); associativeIteratorClasses.clear(); mutableAssociativeIteratorClasses.clear(); } void CppCodeParser::doneParsingSourceFiles(Tree *tree) { tree->root()->makeUndocumentedChildrenInternal(); tree->root()->normalizeOverloads(); tree->fixInheritance(); tree->resolveProperties(); } const FunctionNode *CppCodeParser::findFunctionNode(const QString& synopsis, Tree *tree, Node *relative, bool fuzzy) { QStringList parentPath; FunctionNode *clone; FunctionNode *func = 0; int flags = fuzzy ? int(Tree::SearchBaseClasses) : 0; reset(tree); if (makeFunctionNode(synopsis, &parentPath, &clone)) { func = tree->findFunctionNode(parentPath, clone, relative, flags); /* This is necessary because Roberto's parser resolves typedefs. */ if (!func && fuzzy) { func = tre->findFunctionNode(parentPath + QStringList(clone->name()), relative, flags); if (!func && clone->name().contains('_')) { QStringList path = parentPath; path << clone->name().split('_'); func = tre->findFunctionNode(path, relative, flags); } if (func) { NodeList overloads = func->parent()->overloads(func->name()); NodeList candidates; for (int i = 0; i < overloads.count(); ++i) { FunctionNode *overload = static_cast(overloads.at(i)); if (overload->status() != Node::Compat && overload->parameters().count() == clone->parameters().count() && !overload->isConst() == !clone->isConst()) candidates << overload; } if (candidates.count() == 0) return 0; /* There's only one function with the correct number of parameters. That must be the one. */ if (candidates.count() == 1) return static_cast(candidates.first()); overloads = candidates; candidates.clear(); for (int i = 0; i < overloads.count(); ++i) { FunctionNode *overload = static_cast(overloads.at(i)); QList params1 = overload->parameters(); QList params2 = clone->parameters(); int j; for (j = 0; j < params1.count(); ++j) { if (!params2.at(j).name().startsWith(params1.at(j).name())) break; } if (j == params1.count()) candidates << overload; } /* There are several functions with the correct parameter count, but only one has the correct parameter names. */ if (candidates.count() == 1) return static_cast(candidates.first()); candidates.clear(); for (int i = 0; i < overloads.count(); ++i) { FunctionNode *overload = static_cast(overloads.at(i)); QList params1 = overload->parameters(); QList params2 = clone->parameters(); int j; for (j = 0; j < params1.count(); ++j) { if (params1.at(j).rightType() != params2.at(j).rightType()) break; if (cleanType(params1.at(j).leftType(), tree) != cleanType(params2.at(j).leftType(), tree)) break; } if (j == params1.count()) candidates << overload; } /* There are several functions with the correct parameter count, but only one has the correct types, loosely compared. */ if (candidates.count() == 1) return static_cast(candidates.first()); return 0; } } delete clone; } return func; } /*! Returns the set of strings reopresenting the topic commands. */ QSet CppCodeParser::topicCommands() { return QSet() << COMMAND_CLASS << COMMAND_ENUM << COMMAND_EXAMPLE << COMMAND_EXTERNALPAGE << COMMAND_FILE << COMMAND_FN << COMMAND_GROUP << COMMAND_HEADERFILE << COMMAND_MACRO << COMMAND_MODULE << COMMAND_NAMESPACE << COMMAND_PAGE << COMMAND_PROPERTY << COMMAND_SERVICE << COMMAND_TYPEDEF #ifdef QDOC_QML << COMMAND_VARIABLE << COMMAND_QMLCLASS << COMMAND_QMLPROPERTY; #else << COMMAND_VARIABLE; #endif } /*! Process the topic \a command in context \a doc with argument \a arg. */ Node *CppCodeParser::processTopicCommand(const Doc& doc, const QString& command, const QString& arg) { if (command == COMMAND_FN) { QStringList parentPath; FunctionNode *func = 0; FunctionNode *clone = 0; if (!makeFunctionNode(arg, &parentPath, &clone) && !makeFunctionNode("void " + arg, &parentPath, &clone)) { doc.location().warning(tr("Invalid syntax in '\\%1'") .arg(COMMAND_FN)); } else { if (!usedNamespaces.isEmpty()) { foreach (const QString &usedNamespace, usedNamespaces) { QStringList newPath = usedNamespace.split("::") + parentPath; func = tre->findFunctionNode(newPath, clone); if (func) break; } } // Search the root namespace if no match was found. if (func == 0) func = tre->findFunctionNode(parentPath, clone); if (func == 0) { if (parentPath.isEmpty() && !lastPath.isEmpty()) func = tre->findFunctionNode(lastPath, clone); if (func == 0) { doc.location().warning(tr("Cannot find '%1' in '\\%2'") .arg(clone->name() + "(...)") .arg(COMMAND_FN), tr("I cannot find any function of that name with the " "specified signature. Make sure that the signature " "is identical to the declaration, including 'const' " "qualifiers.")); } else { doc.location().warning(tr("Missing '%1::' for '%2' in '\\%3'") .arg(lastPath.join("::")) .arg(clone->name() + "()") .arg(COMMAND_FN)); } } else { lastPath = parentPath; } if (func) func->borrowParameterNames(clone); delete clone; } return func; } else if (command == COMMAND_MACRO) { QStringList parentPath; FunctionNode *func = 0; if (makeFunctionNode(arg, &parentPath, &func, tre->root())) { if (!parentPath.isEmpty()) { doc.location().warning(tr("Invalid syntax in '\\%1'") .arg(COMMAND_MACRO)); delete func; func = 0; } else { func->setMetaness(FunctionNode::MacroWithParams); QList params = func->parameters(); for (int i = 0; i < params.size(); ++i) { Parameter ¶m = params[i]; if (param.name().isEmpty() && !param.leftType().isEmpty() && param.leftType() != "...") param = Parameter("", "", param.leftType()); } func->setParameters(params); } return func; } else if (QRegExp("[A-Za-z_][A-Za-z0-9_]+").exactMatch(arg)) { func = new FunctionNode(tre->root(), arg); func->setAccess(Node::Public); func->setLocation(doc.location()); func->setMetaness(FunctionNode::MacroWithoutParams); } else { doc.location().warning(tr("Invalid syntax in '\\%1'") .arg(COMMAND_MACRO)); } return func; } else if (nodeTypeMap.contains(command)) { /* The command was neither "fn" nor "macro" . */ // ### split(" ") hack is there to support header file syntax QStringList paths = arg.split(" "); QStringList path = paths[0].split("::"); #if QDOC2DOX // qdoc -> doxygen. if (Doc::isDoxPass(1)) { if (command == COMMAND_PROPERTY) { Doc::insertProperty(path); } else if (command == COMMAND_VARIABLE) { Doc::insertVariable(path); } else if (command == COMMAND_ENUM) { // zzz } } #endif Node *node = 0; if (!usedNamespaces.isEmpty()) { foreach (const QString &usedNamespace, usedNamespaces) { QStringList newPath = usedNamespace.split("::") + path; node = tre->findNode(newPath, nodeTypeMap[command]); if (node) { path = newPath; break; } } } // Search the root namespace if no match was found. if (node == 0) node = tre->findNode(path, nodeTypeMap[command]); if (node == 0) { doc.location().warning(tr("Cannot find '%1' specified with '\\%2' in any header file") .arg(arg).arg(command)); lastPath = path; } else if (command == COMMAND_SERVICE) { // If the command is "\service", then we need to tag the // class with the actual service name. QStringList args = arg.split(" "); if (args.size() > 1) { ClassNode *cnode = static_cast(node); cnode->setServiceName(args[1]); cnode->setHideFromMainList(true); } } else if (node->isInnerNode()) { if (path.size() > 1) { path.pop_back(); usedNamespaces.insert(path.join("::")); } } return node; } else if (command == COMMAND_EXAMPLE) { FakeNode *fake = new FakeNode(tre->root(), arg, FakeNode::Example); createExampleFileNodes(fake); return fake; } else if (command == COMMAND_EXTERNALPAGE) { return new FakeNode(tre->root(), arg, FakeNode::ExternalPage); } else if (command == COMMAND_FILE) { return new FakeNode(tre->root(), arg, FakeNode::File); } else if (command == COMMAND_GROUP) { return new FakeNode(tre->root(), arg, FakeNode::Group); } else if (command == COMMAND_HEADERFILE) { return new FakeNode(tre->root(), arg, FakeNode::HeaderFile); } else if (command == COMMAND_MODULE) { return new FakeNode(tre->root(), arg, FakeNode::Module); } else if (command == COMMAND_PAGE) { return new FakeNode(tre->root(), arg, FakeNode::Page); } #ifdef QDOC_QML else if (command == COMMAND_QMLCLASS) { const ClassNode* classNode = 0; QStringList names = arg.split(" "); //qDebug() << "QMLCLASS" << names; if (names.size() > 1) { Node* n = tre->findNode(names[1].split("::"),Node::Class); if (n) { classNode = static_cast(n); //qDebug() << "FOUND IT!" << classNode->name(); } } return new QmlNode(tre->root(), names[0], classNode); } #endif return 0; } /*! Returns the set of strings representing the common metacommands plus some other metacommands. */ QSet CppCodeParser::otherMetaCommands() { return commonMetaCommands() << COMMAND_INHEADERFILE << COMMAND_OVERLOAD << COMMAND_REIMP << COMMAND_RELATES << COMMAND_CONTENTSPAGE << COMMAND_NEXTPAGE << COMMAND_PREVIOUSPAGE << COMMAND_INDEXPAGE << COMMAND_STARTPAGE; } /*! Process the metacommand \a command in the context of the \a node associated with the topic command and the \a doc. \a arg is the argument to the metacommand. */ void CppCodeParser::processOtherMetaCommand(const Doc& doc, const QString& command, const QString& arg, Node *node) { if (command == COMMAND_INHEADERFILE) { if (node != 0 && node->isInnerNode()) { ((InnerNode *) node)->addInclude(arg); } else { doc.location().warning(tr("Ignored '\\%1'") .arg(COMMAND_INHEADERFILE)); } } else if (command == COMMAND_OVERLOAD) { if (node != 0 && node->type() == Node::Function) { ((FunctionNode *) node)->setOverload(true); } else { doc.location().warning(tr("Ignored '\\%1'") .arg(COMMAND_OVERLOAD)); } } else if (command == COMMAND_REIMP) { if (node != 0 && node->type() == Node::Function) { FunctionNode *func = (FunctionNode *) node; const FunctionNode *from = func->reimplementedFrom(); if (from == 0) { doc.location().warning( tr("Cannot find base function for '\\%1' in %2()") .arg(COMMAND_REIMP).arg(node->name()), tr("The function either doesn't exist in any base class " "with the same signature or it exists but isn't virtual.")); } #if 0 // Ideally, we would enable this check to warn whenever \reimp is used // incorrectly, and only make the node internal if the function is a // reimplementation of another function in a base class. else if (from->access() == Node::Private || from->parent()->access() == Node::Private) { doc.location().warning( tr("Base function for '\\%1' in %2() is private or internal") .arg(COMMAND_REIMP).arg(node->name())); } #endif // Note: Setting the access to Private hides the documentation, // but setting the status to Internal makes the node available // in the XML output when the WebXMLGenerator is used. func->setAccess(Node::Private); func->setStatus(Node::Internal); } else { doc.location().warning(tr("Ignored '\\%1' in %2") .arg(COMMAND_REIMP) .arg(node->name())); } } else if (command == COMMAND_RELATES) { InnerNode *pseudoParent; if (arg.startsWith("<") || arg.startsWith("\"")) { pseudoParent = static_cast(tre->findNode(QStringList(arg), Node::Fake)); } else { QStringList newPath = arg.split("::"); pseudoParent = static_cast(tre->findNode(QStringList(newPath), Node::Class)); if (!pseudoParent) pseudoParent = static_cast(tre->findNode(QStringList(newPath), Node::Namespace)); } if (!pseudoParent) { doc.location().warning(tr("Cannot find '%1' in '\\%2'") .arg(arg).arg(COMMAND_RELATES)); } else { node->setRelates(pseudoParent); } } else if (command == COMMAND_CONTENTSPAGE) { setLink(node, Node::ContentsLink, arg); } else if (command == COMMAND_NEXTPAGE) { setLink(node, Node::NextLink, arg); } else if (command == COMMAND_PREVIOUSPAGE) { setLink(node, Node::PreviousLink, arg); } else if (command == COMMAND_INDEXPAGE) { setLink(node, Node::IndexLink, arg); } else if (command == COMMAND_STARTPAGE) { setLink(node, Node::StartLink, arg); } else { processCommonMetaCommand(doc.location(),command,arg,node,tre); } } /*! The topic command has been processed resulting in the \a doc and \a node passed in here. Process the other meta commands, which are found in \a doc, in the context of the topic \a node. */ void CppCodeParser::processOtherMetaCommands(const Doc& doc, Node *node) { const QSet metaCommands = doc.metaCommandsUsed(); QSet::ConstIterator cmd = metaCommands.begin(); while (cmd != metaCommands.end()) { QStringList args = doc.metaCommandArgs(*cmd); QStringList::ConstIterator arg = args.begin(); while (arg != args.end()) { processOtherMetaCommand(doc, *cmd, *arg, node); ++arg; } ++cmd; } } /*! Resets the C++ code parser to its default initialized state. */ void CppCodeParser::reset(Tree *tree) { tre = tree; tokenizer = 0; tok = 0; access = Node::Public; metaness = FunctionNode::Plain; lastPath.clear(); moduleName = ""; } /*! Get the next token from the file being parsed and store it in the token variable. */ void CppCodeParser::readToken() { tok = tokenizer->getToken(); } /*! Return the current location in the file being parsed, i.e. the file name, line number, and column number. */ const Location& CppCodeParser::location() { return tokenizer->location(); } /*! Return the previous string read from the file being parsed. */ QString CppCodeParser::previousLexeme() { return tokenizer->previousLexeme(); } /*! Return the current string string from the file being parsed. */ QString CppCodeParser::lexeme() { return tokenizer->lexeme(); } bool CppCodeParser::match(int target) { if (tok == target) { readToken(); return true; } else { return false; } } /*! If the current token is one of the keyword thingees that are used in Qt, skip over it to the next token and return true. Otherwise just return false without reading the next token. */ bool CppCodeParser::matchCompat() { switch (tok) { case Tok_QT_COMPAT: case Tok_QT_COMPAT_CONSTRUCTOR: case Tok_QT_DEPRECATED: case Tok_QT_MOC_COMPAT: case Tok_QT3_SUPPORT: case Tok_QT3_SUPPORT_CONSTRUCTOR: case Tok_QT3_MOC_SUPPORT: readToken(); return true; default: return false; } } bool CppCodeParser::matchTemplateAngles(CodeChunk *dataType) { bool matches = (tok == Tok_LeftAngle); if (matches) { int leftAngleDepth = 0; int parenAndBraceDepth = 0; do { if (tok == Tok_LeftAngle) { leftAngleDepth++; } else if (tok == Tok_RightAngle) { leftAngleDepth--; } else if (tok == Tok_LeftParen || tok == Tok_LeftBrace) { ++parenAndBraceDepth; } else if (tok == Tok_RightParen || tok == Tok_RightBrace) { if (--parenAndBraceDepth < 0) return false; } if (dataType != 0) dataType->append(lexeme()); readToken(); } while (leftAngleDepth > 0 && tok != Tok_Eoi); } return matches; } bool CppCodeParser::matchTemplateHeader() { readToken(); return matchTemplateAngles(); } bool CppCodeParser::matchDataType(CodeChunk *dataType, QString *var) { /* This code is really hard to follow... sorry. The loop is there to match Alpha::Beta::Gamma::...::Omega. */ for (;;) { bool virgin = true; if (tok != Tok_Ident) { /* There is special processing for 'Foo::operator int()' and such elsewhere. This is the only case where we return something with a trailing gulbrandsen ('Foo::'). */ if (tok == Tok_operator) return true; /* People may write 'const unsigned short' or 'short unsigned const' or any other permutation. */ while (match(Tok_const) || match(Tok_volatile)) dataType->append(previousLexeme()); while (match(Tok_signed) || match(Tok_unsigned) || match(Tok_short) || match(Tok_long) || match(Tok_int64)) { dataType->append(previousLexeme()); virgin = false; } while (match(Tok_const) || match(Tok_volatile)) dataType->append(previousLexeme()); if (match(Tok_Tilde)) dataType->append(previousLexeme()); } if (virgin) { if (match(Tok_Ident)) dataType->append(previousLexeme()); else if (match(Tok_void) || match(Tok_int) || match(Tok_char) || match(Tok_double) || match(Tok_Ellipsis)) dataType->append(previousLexeme()); else return false; } else if (match(Tok_int) || match(Tok_char) || match(Tok_double)) { dataType->append(previousLexeme()); } matchTemplateAngles(dataType); while (match(Tok_const) || match(Tok_volatile)) dataType->append(previousLexeme()); if (match(Tok_Gulbrandsen)) dataType->append(previousLexeme()); else break; } while (match(Tok_Ampersand) || match(Tok_Aster) || match(Tok_const) || match(Tok_Caret)) dataType->append(previousLexeme()); if (match(Tok_LeftParenAster)) { /* A function pointer. This would be rather hard to handle without a tokenizer hack, because a type can be followed with a left parenthesis in some cases (e.g., 'operator int()'). The tokenizer recognizes '(*' as a single token. */ dataType->append(previousLexeme()); dataType->appendHotspot(); if (var != 0 && match(Tok_Ident)) *var = previousLexeme(); if (!match(Tok_RightParen) || tok != Tok_LeftParen) return false; dataType->append(previousLexeme()); int parenDepth0 = tokenizer->parenDepth(); while (tokenizer->parenDepth() >= parenDepth0 && tok != Tok_Eoi) { dataType->append(lexeme()); readToken(); } if (match(Tok_RightParen)) dataType->append(previousLexeme()); } else { /* The common case: Look for an optional identifier, then for some array brackets. */ dataType->appendHotspot(); if (var != 0) { if (match(Tok_Ident)) { *var = previousLexeme(); } else if (match(Tok_Comment)) { /* A neat hack: Commented-out parameter names are recognized by qdoc. It's impossible to illustrate here inside a C-style comment, because it requires an asterslash. It's also impossible to illustrate inside a C++-style comment, because the explanation does not fit on one line. */ if (varComment.exactMatch(previousLexeme())) *var = varComment.cap(1); } } if (tok == Tok_LeftBracket) { int bracketDepth0 = tokenizer->bracketDepth(); while ((tokenizer->bracketDepth() >= bracketDepth0 && tok != Tok_Eoi) || tok == Tok_RightBracket) { dataType->append(lexeme()); readToken(); } } } return true; } bool CppCodeParser::matchParameter(FunctionNode *func) { CodeChunk dataType; QString name; CodeChunk defaultValue; if (!matchDataType(&dataType, &name)) return false; match(Tok_Comment); if (match(Tok_Equal)) { int parenDepth0 = tokenizer->parenDepth(); while (tokenizer->parenDepth() >= parenDepth0 && (tok != Tok_Comma || tokenizer->parenDepth() > parenDepth0) && tok != Tok_Eoi) { defaultValue.append(lexeme()); readToken(); } } func->addParameter(Parameter(dataType.toString(), "", name, defaultValue.toString())); // ### return true; } bool CppCodeParser::matchFunctionDecl(InnerNode *parent, QStringList *parentPathPtr, FunctionNode **funcPtr, const QString &templateStuff) { CodeChunk returnType; QStringList parentPath; QString name; bool compat = false; if (match(Tok_friend)) return false; match(Tok_explicit); if (matchCompat()) compat = true; bool sta = false; if (match(Tok_static)) { sta = true; if (matchCompat()) compat = true; } FunctionNode::Virtualness vir = FunctionNode::NonVirtual; if (match(Tok_virtual)) { vir = FunctionNode::ImpureVirtual; if (matchCompat()) compat = true; } if (!matchDataType(&returnType)) { if (tokenizer->parsingFnOrMacro() && (match(Tok_Q_DECLARE_FLAGS) || match(Tok_Q_PROPERTY))) returnType = CodeChunk(previousLexeme()); else return false; } if (returnType.toString() == "QBool") returnType = CodeChunk("bool"); if (matchCompat()) compat = true; if (tok == Tok_operator && (returnType.toString().isEmpty() || returnType.toString().endsWith("::"))) { // 'QString::operator const char *()' parentPath = returnType.toString().split(sep); parentPath.removeAll(QString()); returnType = CodeChunk(); readToken(); CodeChunk restOfName; if (tok != Tok_Tilde && matchDataType(&restOfName)) { name = "operator " + restOfName.toString(); } else { name = previousLexeme() + lexeme(); readToken(); while (tok != Tok_LeftParen && tok != Tok_Eoi) { name += lexeme(); readToken(); } } if (tok != Tok_LeftParen) return false; } else if (tok == Tok_LeftParen) { // constructor or destructor parentPath = returnType.toString().split(sep); if (!parentPath.isEmpty()) { name = parentPath.last(); parentPath.erase(parentPath.end() - 1); } returnType = CodeChunk(); } else { while (match(Tok_Ident)) { name = previousLexeme(); matchTemplateAngles(); if (match(Tok_Gulbrandsen)) { parentPath.append(name); } else { break; } } if (tok == Tok_operator) { name = lexeme(); readToken(); while (tok != Tok_Eoi) { name += lexeme(); readToken(); if (tok == Tok_LeftParen) break; } } if (parent && (tok == Tok_Semicolon || tok == Tok_LeftBracket || tok == Tok_Colon) && access != Node::Private) { if (tok == Tok_LeftBracket) { returnType.appendHotspot(); int bracketDepth0 = tokenizer->bracketDepth(); while ((tokenizer->bracketDepth() >= bracketDepth0 && tok != Tok_Eoi) || tok == Tok_RightBracket) { returnType.append(lexeme()); readToken(); } if (tok != Tok_Semicolon) return false; } else if (tok == Tok_Colon) { returnType.appendHotspot(); while (tok != Tok_Semicolon && tok != Tok_Eoi) { returnType.append(lexeme()); readToken(); } if (tok != Tok_Semicolon) return false; } VariableNode *var = new VariableNode(parent, name); var->setAccess(access); var->setLocation(location()); var->setLeftType(returnType.left()); var->setRightType(returnType.right()); if (compat) var->setStatus(Node::Compat); var->setStatic(sta); return false; } if (tok != Tok_LeftParen) return false; } readToken(); FunctionNode *func = new FunctionNode(parent, name); func->setAccess(access); func->setLocation(location()); func->setReturnType(returnType.toString()); func->setTemplateStuff(templateStuff); if (compat) func->setStatus(Node::Compat); func->setMetaness(metaness); if (parent) { if (name == parent->name()) { func->setMetaness(FunctionNode::Ctor); } else if (name.startsWith("~")) { func->setMetaness(FunctionNode::Dtor); } } func->setStatic(sta); if (tok != Tok_RightParen) { do { if (!matchParameter(func)) return false; } while (match(Tok_Comma)); } if (!match(Tok_RightParen)) return false; func->setConst(match(Tok_const)); if (match(Tok_Equal) && match(Tok_Number)) vir = FunctionNode::PureVirtual; func->setVirtualness(vir); if (match(Tok_Colon)) { while (tok != Tok_LeftBrace && tok != Tok_Eoi) readToken(); } if (!match(Tok_Semicolon) && tok != Tok_Eoi) { int braceDepth0 = tokenizer->braceDepth(); if (!match(Tok_LeftBrace)) return false; while (tokenizer->braceDepth() >= braceDepth0 && tok != Tok_Eoi) readToken(); match(Tok_RightBrace); } if (parentPathPtr != 0) *parentPathPtr = parentPath; if (funcPtr != 0) *funcPtr = func; return true; } bool CppCodeParser::matchBaseSpecifier(ClassNode *classe, bool isClass) { Node::Access access; switch (tok) { case Tok_public: access = Node::Public; readToken(); break; case Tok_protected: access = Node::Protected; readToken(); break; case Tok_private: access = Node::Private; readToken(); break; default: access = isClass ? Node::Private : Node::Public; } if (tok == Tok_virtual) readToken(); CodeChunk baseClass; if (!matchDataType(&baseClass)) return false; tre->addBaseClass(classe, access, baseClass.toPath(), baseClass.toString(), classe->parent()); return true; } bool CppCodeParser::matchBaseList(ClassNode *classe, bool isClass) { for (;;) { if (!matchBaseSpecifier(classe, isClass)) return false; if (tok == Tok_LeftBrace) return true; if (!match(Tok_Comma)) return false; } } /*! Parse a C++ class, union, or struct declarion. */ bool CppCodeParser::matchClassDecl(InnerNode *parent, const QString &templateStuff) { bool isClass = (tok == Tok_class); readToken(); bool compat = matchCompat(); if (tok != Tok_Ident) return false; while (tok == Tok_Ident) readToken(); if (tok != Tok_Colon && tok != Tok_LeftBrace) return false; /* So far, so good. We have 'class Foo {' or 'class Foo :'. This is enough to recognize a class definition. */ ClassNode *classe = new ClassNode(parent, previousLexeme()); classe->setAccess(access); classe->setLocation(location()); if (compat) classe->setStatus(Node::Compat); if (!moduleName.isEmpty()) classe->setModuleName(moduleName); classe->setTemplateStuff(templateStuff); if (match(Tok_Colon) && !matchBaseList(classe, isClass)) return false; if (!match(Tok_LeftBrace)) return false; Node::Access outerAccess = access; access = isClass ? Node::Private : Node::Public; FunctionNode::Metaness outerMetaness = metaness; metaness = FunctionNode::Plain; bool matches = (matchDeclList(classe) && match(Tok_RightBrace) && match(Tok_Semicolon)); access = outerAccess; metaness = outerMetaness; return matches; } bool CppCodeParser::matchNamespaceDecl(InnerNode *parent) { readToken(); // skip 'namespace' if (tok != Tok_Ident) return false; while (tok == Tok_Ident) readToken(); if (tok != Tok_LeftBrace) return false; /* So far, so good. We have 'namespace Foo {'. */ QString namespaceName = previousLexeme(); NamespaceNode *namespasse = 0; if (parent) namespasse = static_cast(parent->findNode(namespaceName, Node::Namespace)); if (!namespasse) { namespasse = new NamespaceNode(parent, namespaceName); namespasse->setAccess(access); namespasse->setLocation(location()); } readToken(); // skip '{' bool matched = matchDeclList(namespasse); return matched && match(Tok_RightBrace); } bool CppCodeParser::matchUsingDecl() { readToken(); // skip 'using' // 'namespace' if (tok != Tok_namespace) return false; readToken(); // identifier if (tok != Tok_Ident) return false; QString name; while (tok == Tok_Ident) { name += lexeme(); readToken(); if (tok == Tok_Semicolon) break; else if (tok != Tok_Gulbrandsen) return false; name += "::"; readToken(); } /* So far, so good. We have 'using namespace Foo;'. */ usedNamespaces.insert(name); return true; } bool CppCodeParser::matchEnumItem(InnerNode *parent, EnumNode *enume) { if (!match(Tok_Ident)) return false; QString name = previousLexeme(); CodeChunk val; if (match(Tok_Equal)) { while (tok != Tok_Comma && tok != Tok_RightBrace && tok != Tok_Eoi) { val.append(lexeme()); readToken(); } } if (enume) { QString strVal = val.toString(); if (strVal.isEmpty()) { if (enume->items().isEmpty()) { strVal = "0"; } else { QString last = enume->items().last().value(); bool ok; int n = last.toInt(&ok); if (ok) { if (last.startsWith("0") && last.size() > 1) { if (last.startsWith("0x") || last.startsWith("0X")) strVal = last.left(2) + QString::number(n + 1, 16); else strVal = "0" + QString::number(n + 1, 8); } else { strVal = QString::number(n + 1); } } } } enume->addItem(EnumItem(name, strVal)); } else { VariableNode *var = new VariableNode(parent, name); var->setAccess(access); var->setLocation(location()); var->setLeftType("const int"); var->setStatic(true); } return true; } bool CppCodeParser::matchEnumDecl(InnerNode *parent) { QString name; if (!match(Tok_enum)) return false; if (match(Tok_Ident)) name = previousLexeme(); if (tok != Tok_LeftBrace) return false; EnumNode *enume = 0; if (!name.isEmpty()) { enume = new EnumNode(parent, name); enume->setAccess(access); enume->setLocation(location()); } readToken(); if (!matchEnumItem(parent, enume)) return false; while (match(Tok_Comma)) { if (!matchEnumItem(parent, enume)) return false; } return match(Tok_RightBrace) && match(Tok_Semicolon); } bool CppCodeParser::matchTypedefDecl(InnerNode *parent) { CodeChunk dataType; QString name; if (!match(Tok_typedef)) return false; if (!matchDataType(&dataType, &name)) return false; if (!match(Tok_Semicolon)) return false; if (parent && !parent->findNode(name, Node::Typedef)) { TypedefNode *typedeffe = new TypedefNode(parent, name); typedeffe->setAccess(access); typedeffe->setLocation(location()); } return true; } bool CppCodeParser::matchProperty(InnerNode *parent) { if (!match(Tok_Q_PROPERTY) && !match(Tok_Q_OVERRIDE) && !match(Tok_QDOC_PROPERTY)) return false; if (!match(Tok_LeftParen)) return false; QString name; CodeChunk dataType; if (!matchDataType(&dataType, &name)) return false; PropertyNode *property = new PropertyNode(parent, name); property->setAccess(Node::Public); property->setLocation(location()); property->setDataType(dataType.toString()); while (tok != Tok_RightParen && tok != Tok_Eoi) { if (!match(Tok_Ident)) return false; QString key = previousLexeme(); QString value; if (match(Tok_Ident)) { value = previousLexeme(); } else if (match(Tok_LeftParen)) { int depth = 1; while (tok != Tok_Eoi) { if (tok == Tok_LeftParen) { readToken(); ++depth; } else if (tok == Tok_RightParen) { readToken(); if (--depth == 0) break; } else { readToken(); } } value = "?"; } if (key == "READ") tre->addPropertyFunction(property, value, PropertyNode::Getter); else if (key == "WRITE") tre->addPropertyFunction(property, value, PropertyNode::Setter); else if (key == "STORED") property->setStored(value.toLower() == "true"); else if (key == "DESIGNABLE") property->setDesignable(value.toLower() == "true"); else if (key == "RESET") tre->addPropertyFunction(property, value, PropertyNode::Resetter); } match(Tok_RightParen); return true; } /*! Parse a C++ declaration. */ bool CppCodeParser::matchDeclList(InnerNode *parent) { QString templateStuff; int braceDepth0 = tokenizer->braceDepth(); if (tok == Tok_RightBrace) // prevents failure on empty body braceDepth0++; while (tokenizer->braceDepth() >= braceDepth0 && tok != Tok_Eoi) { switch (tok) { case Tok_Colon: readToken(); break; case Tok_class: case Tok_struct: case Tok_union: matchClassDecl(parent, templateStuff); break; case Tok_namespace: matchNamespaceDecl(parent); break; case Tok_using: matchUsingDecl(); break; case Tok_template: templateStuff = matchTemplateHeader(); continue; case Tok_enum: matchEnumDecl(parent); break; case Tok_typedef: matchTypedefDecl(parent); break; case Tok_private: readToken(); access = Node::Private; metaness = FunctionNode::Plain; break; case Tok_protected: readToken(); access = Node::Protected; metaness = FunctionNode::Plain; break; case Tok_public: readToken(); access = Node::Public; metaness = FunctionNode::Plain; break; case Tok_signals: case Tok_Q_SIGNALS: readToken(); access = Node::Public; metaness = FunctionNode::Signal; break; case Tok_slots: case Tok_Q_SLOTS: readToken(); metaness = FunctionNode::Slot; break; case Tok_Q_OBJECT: readToken(); break; case Tok_Q_OVERRIDE: case Tok_Q_PROPERTY: case Tok_QDOC_PROPERTY: matchProperty(parent); break; case Tok_Q_DECLARE_SEQUENTIAL_ITERATOR: readToken(); if (match(Tok_LeftParen) && match(Tok_Ident)) sequentialIteratorClasses.insert(previousLexeme(), location().fileName()); match(Tok_RightParen); break; case Tok_Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR: readToken(); if (match(Tok_LeftParen) && match(Tok_Ident)) mutableSequentialIteratorClasses.insert(previousLexeme(), location().fileName()); match(Tok_RightParen); break; case Tok_Q_DECLARE_ASSOCIATIVE_ITERATOR: readToken(); if (match(Tok_LeftParen) && match(Tok_Ident)) associativeIteratorClasses.insert(previousLexeme(), location().fileName()); match(Tok_RightParen); break; case Tok_Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR: readToken(); if (match(Tok_LeftParen) && match(Tok_Ident)) mutableAssociativeIteratorClasses.insert(previousLexeme(), location().fileName()); match(Tok_RightParen); break; case Tok_Q_DECLARE_FLAGS: readToken(); if (match(Tok_LeftParen) && match(Tok_Ident)) { QString flagsType = previousLexeme(); if (match(Tok_Comma) && match(Tok_Ident)) { QString enumType = previousLexeme(); TypedefNode *flagsNode = new TypedefNode(parent, flagsType); flagsNode->setAccess(access); flagsNode->setLocation(location()); EnumNode *enumNode = static_cast(parent->findNode(enumType, Node::Enum)); if (enumNode) enumNode->setFlagsType(flagsNode); } } match(Tok_RightParen); break; case Tok_QT_MODULE: readToken(); if (match(Tok_LeftParen) && match(Tok_Ident)) moduleName = previousLexeme(); if (!moduleName.startsWith("Qt")) moduleName.prepend("Qt"); match(Tok_RightParen); break; default: if (!matchFunctionDecl(parent, 0, 0, templateStuff)) { while (tok != Tok_Eoi && (tokenizer->braceDepth() > braceDepth0 || (!match(Tok_Semicolon) && tok != Tok_public && tok != Tok_protected && tok != Tok_private))) readToken(); } } templateStuff.clear(); } return true; } /*! This is called by parseSourceFile() to do the actual parsing and tree building. */ bool CppCodeParser::matchDocsAndStuff() { QSet topicCommandsAllowed = topicCommands(); QSet otherMetacommandsAllowed = otherMetaCommands(); QSet metacommandsAllowed = topicCommandsAllowed + otherMetacommandsAllowed; while (tok != Tok_Eoi) { if (tok == Tok_Doc) { /* lexeme() returns an entire qdoc comment. */ QString comment = lexeme(); Location start_loc(location()); readToken(); Doc::trimCStyleComment(start_loc,comment); /* qdoc --> doxygen We must also remember the location of the end of the comment, so we can construct a diff for it. */ Location end_loc(location()); /* Doc parses the comment. */ Doc doc(start_loc,end_loc,comment,metacommandsAllowed); QString topic; QStringList args; QSet topicCommandsUsed = topicCommandsAllowed & doc.metaCommandsUsed(); /* There should be one topic command in the set, or none. If the set is empty, then the comment should be a function description. */ if (topicCommandsUsed.count() > 0) { topic = *topicCommandsUsed.begin(); args = doc.metaCommandArgs(topic); } NodeList nodes; QList docs; if (topic.isEmpty()) { QStringList parentPath; FunctionNode *clone; FunctionNode *func = 0; if (matchFunctionDecl(0, &parentPath, &clone)) { foreach (const QString &usedNamespace, usedNamespaces) { QStringList newPath = usedNamespace.split("::") + parentPath; func = tre->findFunctionNode(newPath, clone); if (func) break; } if (func == 0) func = tre->findFunctionNode(parentPath, clone); if (func) { func->borrowParameterNames(clone); nodes.append(func); docs.append(doc); } delete clone; } else { doc.location().warning( tr("Cannot tie this documentation to anything"), tr("I found a /*! ... */ comment, but there was no " "topic command (e.g., '\\%1', '\\%2') in the " "comment and no function definition following " "the comment.") .arg(COMMAND_FN).arg(COMMAND_PAGE)); } } else { /* There is a topic command. Process it. */ QStringList::ConstIterator a = args.begin(); while (a != args.end()) { Doc nodeDoc = doc; Node *node = processTopicCommand(nodeDoc, topic, *a); if (node != 0) { nodes.append(node); docs.append(nodeDoc); } ++a; } } NodeList::Iterator n = nodes.begin(); QList::Iterator d = docs.begin(); while (n != nodes.end()) { processOtherMetaCommands(*d, *n); (*n)->setDoc(*d); if ((*n)->isInnerNode() && ((InnerNode *)*n)->includes().isEmpty()) { InnerNode *m = static_cast(*n); while (m->parent() != tre->root()) m = m->parent(); if (m == *n) ((InnerNode *)*n)->addInclude((*n)->name()); else ((InnerNode *)*n)->setIncludes(m->includes()); } ++d; ++n; } } else if (tok == Tok_using) { matchUsingDecl(); } else { QStringList parentPath; FunctionNode *clone; FunctionNode *node = 0; if (matchFunctionDecl(0, &parentPath, &clone)) { /* The location of the definition is more interesting than that of the declaration. People equipped with a sophisticated text editor can respond to warnings concerning undocumented functions very quickly. Signals are implemented in uninteresting files generated by moc. */ node = tre->findFunctionNode(parentPath, clone); if (node != 0 && node->metaness() != FunctionNode::Signal) node->setLocation(clone->location()); delete clone; } else { if (tok != Tok_Doc) readToken(); } } } return true; } bool CppCodeParser::makeFunctionNode(const QString& synopsis, QStringList *parentPathPtr, FunctionNode **funcPtr, InnerNode *root) { Tokenizer *outerTokenizer = tokenizer; int outerTok = tok; Location loc; QByteArray latin1 = synopsis.toLatin1(); Tokenizer stringTokenizer(loc, latin1); stringTokenizer.setParsingFnOrMacro(true); tokenizer = &stringTokenizer; readToken(); bool ok = matchFunctionDecl(root, parentPathPtr, funcPtr); // potential memory leak with funcPtr tokenizer = outerTokenizer; tok = outerTok; return ok; } void CppCodeParser::parseQiteratorDotH(const Location &location, const QString &filePath) { QFile file(filePath); if (!file.open(QFile::ReadOnly)) return; QString text = file.readAll(); text.remove("\r"); text.replace("\\\n", ""); QStringList lines = text.split("\n"); lines = lines.filter("Q_DECLARE"); lines.replaceInStrings(QRegExp("#define Q[A-Z_]*\\(C\\)"), ""); if (lines.size() == 4) { sequentialIteratorDefinition = lines[0]; mutableSequentialIteratorDefinition = lines[1]; associativeIteratorDefinition = lines[2]; mutableAssociativeIteratorDefinition = lines[3]; } else { location.warning(tr("The qiterator.h hack failed")); } } void CppCodeParser::instantiateIteratorMacro(const QString &container, const QString &includeFile, const QString ¯oDef, Tree * /* tree */) { QString resultingCode = macroDef; resultingCode.replace(QRegExp("\\bC\\b"), container); resultingCode.replace(QRegExp("\\s*##\\s*"), ""); Location loc(includeFile); // hack to get the include file for free QByteArray latin1 = resultingCode.toLatin1(); Tokenizer stringTokenizer(loc, latin1); tokenizer = &stringTokenizer; readToken(); matchDeclList(tre->root()); } void CppCodeParser::createExampleFileNodes(FakeNode *fake) { QString examplePath = fake->name(); // we can assume that this file always exists QString proFileName = examplePath + "/" + examplePath.split("/").last() + ".pro"; QString userFriendlyFilePath; QString fullPath = Config::findFile(fake->doc().location(), exampleFiles, exampleDirs, proFileName, userFriendlyFilePath); if (fullPath.isEmpty()) { QString tmp = proFileName; proFileName = examplePath + "/" + "qbuild.pro"; userFriendlyFilePath.clear(); fullPath = Config::findFile(fake->doc().location(), exampleFiles, exampleDirs, proFileName, userFriendlyFilePath); if (fullPath.isEmpty()) { fake->doc().location().warning( tr("Cannot find file '%1' or '%2'").arg(tmp).arg(proFileName)); return; } } int sizeOfBoringPartOfName = fullPath.size() - proFileName.size(); fullPath.truncate(fullPath.lastIndexOf('/')); QStringList exampleFiles = Config::getFilesHere(fullPath, exampleNameFilter); if (!exampleFiles.isEmpty()) { // move main.cpp and to the end, if it exists QString mainCpp; QMutableStringListIterator i(exampleFiles); i.toBack(); while (i.hasPrevious()) { QString fileName = i.previous(); if (fileName.endsWith("/main.cpp")) { mainCpp = fileName; i.remove(); } else if (fileName.contains("/qrc_") || fileName.contains("/moc_") || fileName.contains("/ui_")) i.remove(); } if (!mainCpp.isEmpty()) exampleFiles.append(mainCpp); // add any qmake Qt resource files and qmake project files exampleFiles += Config::getFilesHere(fullPath, "*.qrc *.pro"); } foreach (const QString &exampleFile, exampleFiles) (void) new FakeNode(fake, exampleFile.mid(sizeOfBoringPartOfName), FakeNode::File); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/cppcodeparser.h000066400000000000000000000143001215241066400217450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* cppcodeparser.h */ #ifndef CPPCODEPARSER_H #define CPPCODEPARSER_H #include #include "codeparser.h" #include "node.h" QT_BEGIN_NAMESPACE class ClassNode; class CodeChunk; class CppCodeParserPrivate; class FunctionNode; class InnerNode; class Tokenizer; class CppCodeParser : public CodeParser { public: CppCodeParser(); ~CppCodeParser(); virtual void initializeParser(const Config& config); virtual void terminateParser(); virtual QString language(); virtual QString headerFileNameFilter(); virtual QString sourceFileNameFilter(); virtual void parseHeaderFile(const Location& location, const QString& filePath, Tree *tree); virtual void parseSourceFile(const Location& location, const QString& filePath, Tree *tree); virtual void doneParsingHeaderFiles(Tree *tree); virtual void doneParsingSourceFiles(Tree *tree); const FunctionNode *findFunctionNode(const QString& synopsis, Tree *tree, Node *relative = 0, bool fuzzy = false); protected: virtual QSet topicCommands(); virtual Node *processTopicCommand(const Doc& doc, const QString& command, const QString& arg); virtual QSet otherMetaCommands(); virtual void processOtherMetaCommand(const Doc& doc, const QString& command, const QString& arg, Node *node); void processOtherMetaCommands(const Doc& doc, Node *node); private: void reset(Tree *tree); void readToken(); const Location& location(); QString previousLexeme(); QString lexeme(); bool match(int target); bool matchCompat(); bool matchTemplateAngles(CodeChunk *type = 0); bool matchTemplateHeader(); bool matchDataType(CodeChunk *type, QString *var = 0); bool matchParameter(FunctionNode *func); bool matchFunctionDecl(InnerNode *parent, QStringList *parentPathPtr = 0, FunctionNode **funcPtr = 0, const QString &templateStuff = QString()); bool matchBaseSpecifier(ClassNode *classe, bool isClass); bool matchBaseList(ClassNode *classe, bool isClass); bool matchClassDecl(InnerNode *parent, const QString &templateStuff = QString()); bool matchNamespaceDecl(InnerNode *parent); bool matchUsingDecl(); bool matchEnumItem(InnerNode *parent, EnumNode *enume); bool matchEnumDecl(InnerNode *parent); bool matchTypedefDecl(InnerNode *parent); bool matchProperty(InnerNode *parent); bool matchDeclList(InnerNode *parent); bool matchDocsAndStuff(); bool makeFunctionNode(const QString &synopsis, QStringList *parentPathPtr, FunctionNode **funcPtr, InnerNode *root = 0); void parseQiteratorDotH(const Location &location, const QString &filePath); void instantiateIteratorMacro(const QString &container, const QString &includeFile, const QString ¯oDef, Tree *tree); void createExampleFileNodes(FakeNode *fake); QMap nodeTypeMap; Tree *tre; Tokenizer *tokenizer; int tok; Node::Access access; FunctionNode::Metaness metaness; QString moduleName; QStringList lastPath; QRegExp varComment; QRegExp sep; QString sequentialIteratorDefinition; QString mutableSequentialIteratorDefinition; QString associativeIteratorDefinition; QString mutableAssociativeIteratorDefinition; QSet usedNamespaces; QMap sequentialIteratorClasses; QMap mutableSequentialIteratorClasses; QMap associativeIteratorClasses; QMap mutableAssociativeIteratorClasses; static QStringList exampleFiles; static QStringList exampleDirs; QString exampleNameFilter; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/cpptoqsconverter.cpp000066400000000000000000000300221215241066400230660ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* cpptoqsconverter.cpp */ #include "config.h" #include "cpptoqsconverter.h" QT_BEGIN_NAMESPACE #define CONFIG_QUICK "quick" #define CONFIG_INDENTSIZE "indentsize" void setTabSize( int size ); void setIndentSize( int size ); int columnForIndex( const QString& t, int index ); int indentForBottomLine( const QStringList& program, QChar typedIn ); static QString balancedParens = "(?:[^()]+|\\([^()]*\\))*"; QRegExp CppToQsConverter::qClassRegExp; QRegExp CppToQsConverter::addressOperatorRegExp; QRegExp CppToQsConverter::gulbrandsenRegExp; int CppToQsConverter::tabSize; ClassNode *CppToQsConverter::findClassNode( Tree *qsTree, const QString& qtName ) { ClassNode *classe = (ClassNode *) qsTree->findNode( QStringList(qtName), Node::Class ); if ( classe == 0 ) classe = (ClassNode *) qsTree->findNode( QStringList(qtName.mid(1)), Node::Class ); return classe; } QString CppToQsConverter::convertedDataType( Tree *qsTree, const QString& leftType, const QString& /* rightType */ ) { QString s = leftType; if ( s.startsWith("const ") ) s = s.mid( 6 ); while ( s.endsWith("*") || s.endsWith("&") || s.endsWith(" ") ) s.truncate( s.length() - 1 ); switch ( s[0].unicode() ) { case 'Q': if ( s == "QCString" ) { return "String"; } else { Node *node = findClassNode( qsTree, s ); if ( node == 0 ) { return ""; } else { return node->name(); } } break; case 'b': if ( s == "bool" ) return "Boolean"; break; case 'c': if ( s == "char" ) { if ( leftType == "const char *" ) { return "String"; } else { return "Number"; } } break; case 'd': if ( s == "double" ) return "Number"; break; case 'f': if ( s == "float" ) return "Number"; case 'i': if ( s == "int" ) return "Number"; break; case 'l': if ( s == "long" || s == "long int" || s == "long long" || s == "long long int" || s == "long double" ) return "Number"; break; case 's': if ( s == "short" || s == "short int" || s == "signed char" || s == "signed short" || s == "signed short int" || s == "signed" || s == "signed int" || s == "signed long" || s == "signed long int" ) return "Number"; break; case 'u': if ( s == "uchar" || s == "unsigned" || s == "unsigned char" || s == "ushort" || s == "unsigned short" || s == "unsigned short int" || s == "uint" || s == "unsigned int" || s == "ulong" || s == "unsigned long" || s == "unsigned long int" ) return "Number"; break; case 'v': if ( s == "void" ) return ""; } return s; } QString CppToQsConverter::convertedCode( Tree *qsTree, const QString& code, const QSet& classesWithNoQ ) { QString result; QStringList program; QStringList comments; int programWidth = 0; QStringList originalLines = code.split("\n"); QStringList::ConstIterator ol = originalLines.begin(); while ( ol != originalLines.end() ) { QString code = (*ol).trimmed(); QString comment; int slashSlash = code.indexOf( "//" ); if ( slashSlash != -1 ) { comment = code.mid( slashSlash ); code.truncate( slashSlash ); code = code.trimmed(); } code = convertCodeLine( qsTree, program, code, classesWithNoQ ); program.append( code ); comment = convertComment( qsTree, comment, classesWithNoQ ); comments.append( comment ); int n = indentForBottomLine( program, QChar::Null ); for ( int i = 0; i < n; i++ ) program.last().prepend( " " ); int width = columnForIndex( program.last(), program.last().length() ); if ( !comment.isEmpty() && width > programWidth ) programWidth = width; ++ol; } programWidth = ( (programWidth + (tabSize - 1) + 2) / tabSize ) * tabSize; QStringList::ConstIterator p = program.begin(); QStringList::ConstIterator c = comments.begin(); while ( c != comments.end() ) { if ( c != comments.begin() ) result += "\n"; if ( (*p).trimmed().isEmpty() ) { if ( !(*c).isEmpty() ) result += *p; } else { result += *p; if ( !(*c).isEmpty() ) { int i = columnForIndex( *p, (*p).length() ); while ( i++ < programWidth ) result += " "; } } result += *c; ++p; ++c; } return result; } void CppToQsConverter::initialize( const Config& config ) { qClassRegExp.setPattern( "\\bQ([A-Z][A-Za-z]+)\\b" ); addressOperatorRegExp.setPattern( "([(\\s])[*&]([a-zA-Z])" ); gulbrandsenRegExp.setPattern( "\\b::\\b|->" ); tabSize = config.getInt( CONFIG_TABSIZE ); setTabSize( tabSize ); int size = config.getInt( CONFIG_QUICK + Config::dot + CONFIG_INDENTSIZE ); if ( size > 0 ) setIndentSize( size ); } void CppToQsConverter::terminate() { } QString CppToQsConverter::convertCodeLine( Tree *qsTree, const QStringList& program, const QString& code, const QSet& classesWithNoQ ) { static QString dataTypeFmt = "(?!return)(?:const\\b\\s*)?[A-Za-z_]+(?:\\s*[*&])?"; static QRegExp funcPrototypeRegExp( "(" + dataTypeFmt + ")\\s*\\b([A-Z][a-zA-Z_0-9]*::)?" "([a-z][a-zA-Z_0-9]*)\\(([^);]*)(\\)?)(?:\\s*const)?" ); static QRegExp paramRegExp( "^\\s*(" + dataTypeFmt + ")\\s*\\b([a-z][a-zA-Z_0-9]*)\\s*(,)?\\s*" ); static QRegExp uninitVarRegExp( "(" + dataTypeFmt + ")\\s*\\b([a-z][a-zA-Z_0-9]*);" ); static QRegExp eqVarRegExp( dataTypeFmt + "\\s*\\b([a-z][a-zA-Z_0-9]*)\\s*=(\\s*)(.*)" ); static QRegExp ctorVarRegExp( "(" + dataTypeFmt + ")\\s*\\b([a-z][a-zA-Z_0-9]*)\\((.*)\\);" ); static QRegExp qdebugRegExp( "q(?:Debug|Warning|Fatal)\\(\\s*(\"(?:\\\\.|[^\"])*\")\\s*" "(?:,\\s*(\\S(?:[^,]*\\S)?))?\\s*\\);" ); static QRegExp coutRegExp( "c(?:out|err)\\b(.*);" ); static QRegExp lshiftRegExp( "\\s*<<\\s*" ); static QRegExp endlRegExp( "^endl$" ); if ( code.isEmpty() || code == "{" || code == "}" ) return code; QString result; if ( funcPrototypeRegExp.exactMatch(code) ) { QString returnType = funcPrototypeRegExp.cap( 1 ); QString className = funcPrototypeRegExp.cap( 2 ); QString funcName = funcPrototypeRegExp.cap( 3 ); QString params = funcPrototypeRegExp.cap( 4 ).trimmed(); bool toBeContinued = funcPrototypeRegExp.cap( 5 ).isEmpty(); // ### unused Q_UNUSED(toBeContinued); className.replace( "::", "." ); result = "function " + className + funcName + "("; if ( !params.isEmpty() && params != "void" ) { result += " "; int i = funcPrototypeRegExp.pos( 4 ); while ( (i = paramRegExp.indexIn(code, i, QRegExp::CaretAtOffset)) != -1 ) { QString dataType = paramRegExp.cap( 1 ); QString paramName = paramRegExp.cap( 2 ); QString comma = paramRegExp.cap( 3 ); result += paramName + " : " + convertedDataType( qsTree, dataType ); if ( comma.isEmpty() ) break; result += ", "; i += paramRegExp.matchedLength(); } result += " "; } result += ")"; returnType = convertedDataType( qsTree, returnType ); if ( !returnType.isEmpty() ) result += " : " + returnType; } else if ( uninitVarRegExp.exactMatch(code) ) { QString dataType = uninitVarRegExp.cap( 1 ); QString varName = uninitVarRegExp.cap( 2 ); result = "var " + varName; dataType = convertedDataType( qsTree, dataType ); if ( !dataType.isEmpty() ) result += " : " + dataType; result += ";"; } else if ( eqVarRegExp.exactMatch(code) ) { QString varName = eqVarRegExp.cap( 1 ); QString value = eqVarRegExp.cap( 3 ); value = convertExpr( qsTree, value, classesWithNoQ ); result += "var " + varName + " = " + value; } else if ( ctorVarRegExp.exactMatch(code) ) { QString dataType = ctorVarRegExp.cap( 1 ); QString varName = ctorVarRegExp.cap( 2 ); QString value = ctorVarRegExp.cap( 3 ).trimmed(); result += "var " + varName + " = "; dataType = convertedDataType( qsTree, dataType ); value = convertExpr( qsTree, value, classesWithNoQ ); if ( dataType.isEmpty() || dataType == "String" ) { if ( value.contains(",") ) { result += "..."; } else { result += value; } } else { result += "new " + dataType; if ( !value.isEmpty() ) result += "( " + value + " )"; } result += ";"; } else if ( qdebugRegExp.exactMatch(code) ) { QString fmt = qdebugRegExp.cap( 1 ); QString arg1 = qdebugRegExp.cap( 2 ); result += "println "; int i = 0; while ( i < (int) fmt.length() ) { if ( fmt[i] == '%' ) { int percent = i; i++; while ( i < (int) fmt.length() && QString("diouxXeEfFgGaAcsCSpn%\"").indexOf(fmt[i]) == -1 ) i++; if ( fmt[i] == '%' ) { result += fmt[i++]; } else if ( fmt[i] != '"' ) { if ( percent == 1 ) { result.truncate( result.length() - 1 ); } else { result += "\" + "; } i++; if ( arg1.endsWith(".latin1()") ) arg1.truncate( arg1.length() - 9 ); result += arg1; if ( i == (int) fmt.length() - 1 ) { i++; } else { result += " + \""; } } } else { result += fmt[i++]; } } result += ";"; } else if ( coutRegExp.exactMatch(code) && program.filter("var cout").isEmpty() ) { QStringList args = coutRegExp.cap(1).split(lshiftRegExp); args.replaceInStrings( endlRegExp, "\"\\n\"" ); if ( args.last() == "\"\\n\"" ) { args.erase( args.end() - 1 ); if ( args.isEmpty() ) args << "\"\""; result += "println "; } else { result += "print "; } result += args.join( " + " ) + ";"; } else { result = convertExpr( qsTree, code, classesWithNoQ ); } return result; } QString CppToQsConverter::convertComment( Tree * /* qsTree */, const QString& comment, const QSet& classesWithNoQ ) { QString result = comment; result.replace( "TRUE", "true" ); result.replace( "FALSE", "false" ); result.replace( addressOperatorRegExp, "\\1\\2" ); result.replace( gulbrandsenRegExp, "." ); int i = 0; while ( (i = result.indexOf(qClassRegExp, i)) != -1 ) { if ( classesWithNoQ.contains(qClassRegExp.cap(1)) ) result.remove( i, 1 ); i++; } return result; } QString CppToQsConverter::convertExpr( Tree *qsTree, const QString& expr, const QSet& classesWithNoQ ) { // suboptimal return convertComment( qsTree, expr, classesWithNoQ ); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/cpptoqsconverter.h000066400000000000000000000061111215241066400225350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* cpptoqsconverter.h */ #ifndef CPPTOQSCONVERTER_H #define CPPTOQSCONVERTER_H #include #include "tree.h" QT_BEGIN_NAMESPACE class CppToQsConverter { public: CppToQsConverter() { } ClassNode *findClassNode( Tree *qsTree, const QString& qtName ); QString convertedDataType( Tree *qsTree, const QString& leftType, const QString& rightType = "" ); QString convertedCode( Tree *qsTree, const QString& code, const QSet& classesWithNoQ ); static void initialize( const Config& config ); static void terminate(); private: void clearState(); QString convertCodeLine( Tree *qsTree, const QStringList& program, const QString& code, const QSet& classesWithNoQ ); QString convertComment( Tree *qsTree, const QString& comment, const QSet& classesWithNoQ ); QString convertExpr( Tree *qsTree, const QString& expr, const QSet& classesWithNoQ ); void updateDelimDepths( const QString& code ); static QRegExp qClassRegExp; static QRegExp addressOperatorRegExp; static QRegExp gulbrandsenRegExp; static int tabSize; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/dcfsection.cpp000066400000000000000000000077341215241066400216040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include "dcfsection.h" #include "htmlgenerator.h" QT_BEGIN_NAMESPACE void appendDcfSubSection( DcfSection *dcfSect, const DcfSection& sub ) { dcfSect->subsections.append( sub ); } void appendDcfSubSections( DcfSection *dcfSect, const QList& subs ) { dcfSect->subsections += subs; } void generateDcfSubSections( QString indent, QTextStream& out, const DcfSection& sect ) { QList::const_iterator ss = sect.subsections.constBegin(); while ( ss != sect.subsections.constEnd() ) { out << indent << "
\n"; } else { out << ">\n"; QString indentIndent = indent + " "; QList >::const_iterator k = (*ss).keywords.constBegin(); while ( k != (*ss).keywords.constEnd() ) { out << indentIndent << "" << HtmlGenerator::protect((*k).first) << "\n"; ++k; } generateDcfSubSections( indentIndent, out, *ss ); out << indent << "
\n"; } ++ss; } out.flush(); } void generateDcfSections( const DcfSection& rootSect, const QString& fileName, const QString& /* category */ ) { QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) return ; QTextStream out(&file); QString icon = QFileInfo(fileName).baseName() + ".png"; out << "\n"; out << "\n"; generateDcfSubSections( "", out, rootSect ); out << "\n"; out.flush(); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/dcfsection.h000066400000000000000000000070301215241066400212360ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef DCFSECTION_H #define DCFSECTION_H #include #include #include QT_BEGIN_NAMESPACE class QTextStream; struct DcfSection { QString title; QString ref; QList > keywords; QList subsections; }; inline bool operator<( const DcfSection& s1, const DcfSection& s2 ) { QString title1 = s1.title; QString title2 = s2.title; // cheat with Q3 classes if (title1.startsWith("Q3")) title1.insert(1, '~'); if (title2.startsWith("Q3")) title2.insert(1, '~'); int delta = title1.toLower().compare( title2.toLower() ); if ( delta == 0 ) { delta = title1.compare( title2 ); if ( delta == 0 ) delta = s1.ref.localeAwareCompare( s2.ref ); } return delta < 0; } inline bool operator>( const DcfSection& s1, const DcfSection& s2 ) { return s2 < s1; } inline bool operator<=( const DcfSection& s1, const DcfSection& s2 ) { return !( s2 < s1 ); } inline bool operator>=( const DcfSection& s1, const DcfSection& s2 ) { return !( s1 < s2 ); } inline bool operator==( const DcfSection& s1, const DcfSection& s2 ) { return &s1 == &s2; } inline bool operator!=( const DcfSection& s1, const DcfSection& s2 ) { return !( s1 == s2 ); } void appendDcfSubSection(DcfSection *dcfSect, const DcfSection &sub); void appendDcfSubSections(DcfSection *dcfSect, const QList &subs); void generateDcfSubSections(QString indent, QTextStream &out, const DcfSection §); void generateDcfSections(const DcfSection &rootSect, const QString& fileName, const QString& category ); QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/doc.cpp000066400000000000000000004734211215241066400202300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "config.h" #include "doc.h" #include "codemarker.h" #include "editdistance.h" #include "openedlist.h" #include "quoter.h" #include "text.h" #include "tokenizer.h" #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QSet, null_Set_QString) Q_GLOBAL_STATIC(QStringList, null_QStringList) Q_GLOBAL_STATIC(QList, null_QList_Text) Q_GLOBAL_STATIC(QStringMap, null_QStringMap) struct Macro { QString defaultDef; Location defaultDefLocation; QStringMap otherDefs; int numParams; }; enum { CMD_A, CMD_ABSTRACT, CMD_BADCODE, CMD_BASENAME, CMD_BOLD, CMD_BRIEF, CMD_C, CMD_CAPTION, CMD_CHAPTER, CMD_CODE, CMD_CODELINE, CMD_DOTS, CMD_ELSE, CMD_ENDABSTRACT, CMD_ENDCHAPTER, CMD_ENDCODE, CMD_ENDFOOTNOTE, CMD_ENDIF, CMD_ENDLEGALESE, CMD_ENDLINK, CMD_ENDLIST, CMD_ENDOMIT, CMD_ENDPART, CMD_ENDQUOTATION, CMD_ENDRAW, CMD_ENDSECTION1, CMD_ENDSECTION2, CMD_ENDSECTION3, CMD_ENDSECTION4, CMD_ENDSIDEBAR, CMD_ENDTABLE, CMD_EXPIRE, CMD_FOOTNOTE, CMD_GENERATELIST, CMD_GRANULARITY, CMD_HEADER, CMD_I, CMD_IF, CMD_IMAGE, CMD_INCLUDE, CMD_INLINEIMAGE, CMD_INDEX, CMD_KEYWORD, CMD_L, CMD_LEGALESE, CMD_LINK, CMD_LIST, CMD_META, CMD_NEWCODE, CMD_O, CMD_OLDCODE, CMD_OMIT, CMD_OMITVALUE, CMD_OVERLOAD, CMD_PART, CMD_PRINTLINE, CMD_PRINTTO, CMD_PRINTUNTIL, CMD_QUOTATION, CMD_QUOTEFILE, CMD_QUOTEFROMFILE, CMD_QUOTEFUNCTION, CMD_RAW, CMD_ROW, CMD_SA, CMD_SECTION1, CMD_SECTION2, CMD_SECTION3, CMD_SECTION4, CMD_SIDEBAR, CMD_SKIPLINE, CMD_SKIPTO, CMD_SKIPUNTIL, CMD_SNIPPET, CMD_SUB, CMD_SUP, CMD_TABLE, CMD_TABLEOFCONTENTS, CMD_TARGET, CMD_TT, CMD_UNDERLINE, CMD_UNICODE, CMD_VALUE, CMD_WARNING, #ifdef QDOC_QML CMD_QML, CMD_ENDQML, CMD_CPP, CMD_ENDCPP, CMD_QMLTEXT, CMD_ENDQMLTEXT, CMD_CPPTEXT, CMD_ENDCPPTEXT, #endif NOT_A_CMD }; static struct { const char *english; int no; QString *alias; } cmds[] = { { "a", CMD_A, 0 }, { "abstract", CMD_ABSTRACT, 0 }, { "badcode", CMD_BADCODE, 0 }, { "basename", CMD_BASENAME, 0 }, // ### don't document for now { "bold", CMD_BOLD, 0 }, { "brief", CMD_BRIEF, 0 }, { "c", CMD_C, 0 }, { "caption", CMD_CAPTION, 0 }, { "chapter", CMD_CHAPTER, 0 }, { "code", CMD_CODE, 0 }, { "codeline", CMD_CODELINE, 0}, { "dots", CMD_DOTS, 0 }, { "else", CMD_ELSE, 0 }, { "endabstract", CMD_ENDABSTRACT, 0 }, { "endchapter", CMD_ENDCHAPTER, 0 }, { "endcode", CMD_ENDCODE, 0 }, { "endfootnote", CMD_ENDFOOTNOTE, 0 }, { "endif", CMD_ENDIF, 0 }, { "endlegalese", CMD_ENDLEGALESE, 0 }, { "endlink", CMD_ENDLINK, 0 }, { "endlist", CMD_ENDLIST, 0 }, { "endomit", CMD_ENDOMIT, 0 }, { "endpart", CMD_ENDPART, 0 }, { "endquotation", CMD_ENDQUOTATION, 0 }, { "endraw", CMD_ENDRAW, 0 }, { "endsection1", CMD_ENDSECTION1, 0 }, // ### don't document for now { "endsection2", CMD_ENDSECTION2, 0 }, // ### don't document for now { "endsection3", CMD_ENDSECTION3, 0 }, // ### don't document for now { "endsection4", CMD_ENDSECTION4, 0 }, // ### don't document for now { "endsidebar", CMD_ENDSIDEBAR, 0 }, { "endtable", CMD_ENDTABLE, 0 }, { "expire", CMD_EXPIRE, 0 }, { "footnote", CMD_FOOTNOTE, 0 }, { "generatelist", CMD_GENERATELIST, 0 }, { "granularity", CMD_GRANULARITY, 0 }, // ### don't document for now { "header", CMD_HEADER, 0 }, { "i", CMD_I, 0 }, { "if", CMD_IF, 0 }, { "image", CMD_IMAGE, 0 }, { "include", CMD_INCLUDE, 0 }, { "inlineimage", CMD_INLINEIMAGE, 0 }, { "index", CMD_INDEX, 0 }, // ### don't document for now { "keyword", CMD_KEYWORD, 0 }, { "l", CMD_L, 0 }, { "legalese", CMD_LEGALESE, 0 }, { "link", CMD_LINK, 0 }, { "list", CMD_LIST, 0 }, { "meta", CMD_META, 0 }, { "newcode", CMD_NEWCODE, 0 }, { "o", CMD_O, 0 }, { "oldcode", CMD_OLDCODE, 0 }, { "omit", CMD_OMIT, 0 }, { "omitvalue", CMD_OMITVALUE, 0 }, { "overload", CMD_OVERLOAD, 0 }, { "part", CMD_PART, 0 }, { "printline", CMD_PRINTLINE, 0 }, { "printto", CMD_PRINTTO, 0 }, { "printuntil", CMD_PRINTUNTIL, 0 }, { "quotation", CMD_QUOTATION, 0 }, { "quotefile", CMD_QUOTEFILE, 0 }, { "quotefromfile", CMD_QUOTEFROMFILE, 0 }, { "quotefunction", CMD_QUOTEFUNCTION, 0 }, // ### don't document for now { "raw", CMD_RAW, 0 }, { "row", CMD_ROW, 0 }, { "sa", CMD_SA, 0 }, { "section1", CMD_SECTION1, 0 }, { "section2", CMD_SECTION2, 0 }, { "section3", CMD_SECTION3, 0 }, { "section4", CMD_SECTION4, 0 }, { "sidebar", CMD_SIDEBAR, 0 }, // ### don't document for now { "skipline", CMD_SKIPLINE, 0 }, { "skipto", CMD_SKIPTO, 0 }, { "skipuntil", CMD_SKIPUNTIL, 0 }, { "snippet", CMD_SNIPPET, 0 }, { "sub", CMD_SUB, 0 }, { "sup", CMD_SUP, 0 }, { "table", CMD_TABLE, 0 }, { "tableofcontents", CMD_TABLEOFCONTENTS, 0 }, { "target", CMD_TARGET, 0 }, { "tt", CMD_TT, 0 }, { "underline", CMD_UNDERLINE, 0 }, { "unicode", CMD_UNICODE, 0 }, { "value", CMD_VALUE, 0 }, { "warning", CMD_WARNING, 0 }, #ifdef QDOC_QML { "qml", CMD_QML, 0 }, { "endqml", CMD_ENDQML, 0 }, { "cpp", CMD_CPP, 0 }, { "endcpp", CMD_ENDCPP, 0 }, { "qmltext", CMD_QMLTEXT, 0 }, { "endqmltext", CMD_ENDQMLTEXT, 0 }, { "cpptext", CMD_CPPTEXT, 0 }, { "endcpptext", CMD_ENDCPPTEXT, 0 }, #endif { 0, 0, 0 } }; typedef QHash QHash_QString_int; typedef QHash QHash_QString_Macro; Q_GLOBAL_STATIC(QStringMap, aliasMap) Q_GLOBAL_STATIC(QHash_QString_int, cmdHash) Q_GLOBAL_STATIC(QHash_QString_Macro, macroHash) class DocPrivateExtra { public: QString baseName; Doc::SectioningUnit granularity; Doc::SectioningUnit sectioningUnit; // ### QList tableOfContents; QList tableOfContentsLevels; QList keywords; QList targets; QStringMap metaMap; DocPrivateExtra() : granularity(Doc::Part) { } }; struct Shared // ### get rid of { Shared() : count(1) { } void ref() { ++count; } bool deref() { return (--count == 0); } int count; }; static QString cleanLink(const QString &link) { int colonPos = link.indexOf(':'); if ((colonPos == -1) || (!link.startsWith("file:") && !link.startsWith("mailto:"))) return link; return link.mid(colonPos + 1).simplified(); } class DocPrivate : public Shared { public: DocPrivate(const Location& start = Location::null, const Location& end = Location::null, const QString& source = ""); ~DocPrivate(); void addAlso(const Text& also); void constructExtra(); bool isEnumDocSimplifiable() const; // ### move some of this in DocPrivateExtra Location start_loc; Location end_loc; QString src; Text text; QSet params; QList alsoList; QStringList enumItemList; QStringList omitEnumItemList; QSet metacommandsUsed; QCommandMap metaCommandMap; bool hasLegalese : 1; bool hasSectioningUnits : 1; DocPrivateExtra *extra; }; DocPrivate::DocPrivate(const Location& start, const Location& end, const QString& source) : start_loc(start), end_loc(end), src(source), hasLegalese(false), hasSectioningUnits(false), extra(0) { // nothing. } DocPrivate::~DocPrivate() { delete extra; } void DocPrivate::addAlso(const Text& also) { alsoList.append(also); } void DocPrivate::constructExtra() { if (extra == 0) extra = new DocPrivateExtra; } bool DocPrivate::isEnumDocSimplifiable() const { bool justMetColon = false; int numValueTables = 0; const Atom *atom = text.firstAtom(); while (atom) { if (atom->type() == Atom::AutoLink || atom->type() == Atom::String) { justMetColon = atom->string().endsWith(":"); } else if ((atom->type() == Atom::ListLeft) && (atom->string() == ATOM_LIST_VALUE)) { if (justMetColon || numValueTables > 0) return false; ++numValueTables; } atom = atom->next(); } return true; } class DocParser { public: void parse(const QString &source, DocPrivate *docPrivate, const QSet &metaCommandSet); static int endCmdFor(int cmd); static QString cmdName(int cmd); static QString endCmdName(int cmd); static QString untabifyEtc(const QString& str); static int indentLevel(const QString& str); static QString unindent(int level, const QString& str); static QString slashed(const QString& str); static int tabSize; static QStringList exampleFiles; static QStringList exampleDirs; static QStringList sourceFiles; static QStringList sourceDirs; static bool quoting; private: Location& location(); QString detailsUnknownCommand(const QSet& metaCommandSet, const QString& str); void checkExpiry(const QString& date); void insertBaseName(const QString &baseName); void insertTarget(const QString& target, bool keyword); void include(const QString& fileName); void startFormat(const QString& format, int cmd); bool openCommand(int cmd); bool closeCommand(int endCmd); void startSection(Doc::SectioningUnit unit, int cmd); void endSection(int unit, int endCmd); void parseAlso(); void append(Atom::Type type, const QString& string = ""); void appendChar(QChar ch); void appendWord(const QString &word); void appendToCode(const QString &code); void startNewPara(); void enterPara(Atom::Type leftType = Atom::ParaLeft, Atom::Type rightType = Atom::ParaRight, const QString& string = ""); void leavePara(); void leaveValue(); void leaveValueList(); void leaveTableRow(); CodeMarker *quoteFromFile(); void expandMacro(const QString& name, const QString& def, int numParams); Doc::SectioningUnit getSectioningUnit(); QString getArgument(bool verbatim = false); QString getOptionalArgument(); QString getRestOfLine(); QString getMetaCommandArgument(const QString &cmdStr); QString getUntilEnd(int cmd); QString getCode(int cmd, CodeMarker *marker); QString getUnmarkedCode(int cmd); bool isBlankLine(); bool isLeftBraceAhead(); void skipSpacesOnLine(); void skipSpacesOrOneEndl(); void skipAllSpaces(); void skipToNextPreprocessorCommand(); QStack openedInputs; QString in; int pos; int len; Location cachedLoc; int cachedPos; DocPrivate *priv; enum ParaState { OutsidePara, InsideSingleLinePara, InsideMultiLinePara }; ParaState paraState; bool inTableHeader; bool inTableRow; bool inTableItem; bool indexStartedPara; // ### rename Atom::Type pendingParaLeftType; Atom::Type pendingParaRightType; QString pendingParaString; int braceDepth; int minIndent; Doc::SectioningUnit currentSectioningUnit; QMap targetMap; QMap pendingFormats; QStack openedCommands; QStack openedLists; Quoter quoter; }; int DocParser::tabSize; QStringList DocParser::exampleFiles; QStringList DocParser::exampleDirs; QStringList DocParser::sourceFiles; QStringList DocParser::sourceDirs; bool DocParser::quoting; /*! Parse the \a source string to build a Text data structure in \a docPrivate. The Text data structure is a linked list of Atoms. \a metaCommandSet is the set of metacommands that may be found in \a source. These metacommands are not markup text commands. They are topic commands and related metacommands. */ void DocParser::parse(const QString& source, DocPrivate *docPrivate, const QSet& metaCommandSet) { in = source; pos = 0; len = in.length(); cachedLoc = docPrivate->start_loc; cachedPos = 0; priv = docPrivate; priv->text << Atom::Nop; paraState = OutsidePara; inTableHeader = false; inTableRow = false; inTableItem = false; indexStartedPara = false; pendingParaLeftType = Atom::Nop; pendingParaRightType = Atom::Nop; braceDepth = 0; minIndent = INT_MAX; currentSectioningUnit = Doc::Book; openedCommands.push(CMD_OMIT); quoter.reset(); CodeMarker *marker = 0; Atom *currentLinkAtom = 0; QString x; QStack preprocessorSkipping; int numPreprocessorSkipping = 0; while (pos < len) { QChar ch = in.at(pos); switch (ch.unicode()) { case '\\': { QString cmdStr; pos++; while (pos < len) { ch = in.at(pos); if (ch.isLetterOrNumber()) { cmdStr += ch; pos++; } else { break; } } if (cmdStr.isEmpty()) { if (pos < len) { enterPara(); if (in.at(pos).isSpace()) { skipAllSpaces(); appendChar(QLatin1Char(' ')); } else { appendChar(in.at(pos++)); } } } else { int cmd = cmdHash()->value(cmdStr,NOT_A_CMD); switch (cmd) { case CMD_A: enterPara(); x = getArgument(); append(Atom::FormattingLeft,ATOM_FORMATTING_PARAMETER); append(Atom::String, x); append(Atom::FormattingRight,ATOM_FORMATTING_PARAMETER); priv->params.insert(x); break; case CMD_ABSTRACT: if (openCommand(cmd)) { leavePara(); append(Atom::AbstractLeft); } break; case CMD_BADCODE: leavePara(); #ifdef QDOC2DOX if (DoxWriter::isDoxPass()) append(Atom::CodeBad,getUnmarkedCode(CMD_BADCODE)); else append(Atom::CodeBad,getCode(CMD_BADCODE, marker)); #else append(Atom::CodeBad,getCode(CMD_BADCODE, marker)); #endif break; case CMD_BASENAME: leavePara(); insertBaseName(getArgument()); break; case CMD_BOLD: startFormat(ATOM_FORMATTING_BOLD, cmd); break; case CMD_BRIEF: leavePara(); enterPara(Atom::BriefLeft, Atom::BriefRight); break; case CMD_C: enterPara(); x = untabifyEtc(getArgument(true)); #ifdef QDOC2DOX if (DoxWriter::isDoxPass()) append(Atom::C, x); else { marker = CodeMarker::markerForCode(x); append(Atom::C, marker->markedUpCode(x, 0, "")); } #else marker = CodeMarker::markerForCode(x); append(Atom::C, marker->markedUpCode(x, 0, "")); #endif break; case CMD_CAPTION: leavePara(); /* ... */ break; case CMD_CHAPTER: startSection(Doc::Chapter, cmd); break; case CMD_CODE: leavePara(); #ifdef QDOC2DOX if (DoxWriter::isDoxPass()) append(Atom::Code, getUnmarkedCode(CMD_CODE)); else append(Atom::Code, getCode(CMD_CODE, marker)); #else append(Atom::Code, getCode(CMD_CODE, marker)); #endif break; #ifdef QDOC_QML case CMD_QML: leavePara(); append(Atom::Qml, getCode(CMD_QML, marker)); break; case CMD_QMLTEXT: append(Atom::QmlText); break; #endif case CMD_CODELINE: { #ifdef QDOC2DOX if (!quoting && !DoxWriter::isDoxPass()) { if (priv->text.lastAtom()->type() == Atom::Code && priv->text.lastAtom()->string().endsWith("\n\n")) priv->text.lastAtom()->chopString(); appendToCode("\n"); } lse { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, " "); } #else if (!quoting) { if (priv->text.lastAtom()->type() == Atom::Code && priv->text.lastAtom()->string().endsWith("\n\n")) priv->text.lastAtom()->chopString(); appendToCode("\n"); } else { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, " "); } #endif } break; case CMD_DOTS: { #ifdef QDOC2DOX if (DoxWriter::isDoxPass()) { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, " ..."); } else if (!quoting) { if (priv->text.lastAtom()->type() == Atom::Code && priv->text.lastAtom()->string().endsWith("\n\n")) priv->text.lastAtom()->chopString(); QString arg = getOptionalArgument(); int indent = 4; if (!arg.isEmpty()) indent = arg.toInt(); for (int i = 0; i < indent; ++i) appendToCode(" "); appendToCode("...\n"); } else { append(Atom::CodeQuoteCommand, cmdStr); QString arg = getOptionalArgument(); if (arg.isEmpty()) arg = "4"; append(Atom::CodeQuoteArgument, arg); } #else if (!quoting) { if (priv->text.lastAtom()->type() == Atom::Code && priv->text.lastAtom()->string().endsWith("\n\n")) priv->text.lastAtom()->chopString(); QString arg = getOptionalArgument(); int indent = 4; if (!arg.isEmpty()) indent = arg.toInt(); for (int i = 0; i < indent; ++i) appendToCode(" "); appendToCode("...\n"); } else { append(Atom::CodeQuoteCommand, cmdStr); QString arg = getOptionalArgument(); if (arg.isEmpty()) arg = "4"; append(Atom::CodeQuoteArgument, arg); } #endif } break; case CMD_ELSE: if (preprocessorSkipping.size() > 0) { if (preprocessorSkipping.top()) { --numPreprocessorSkipping; } else { ++numPreprocessorSkipping; } preprocessorSkipping.top() = !preprocessorSkipping.top(); (void)getRestOfLine(); // ### should ensure that it's empty if (numPreprocessorSkipping) skipToNextPreprocessorCommand(); } else { location().warning(tr("Unexpected '\\%1'").arg(cmdName(CMD_ELSE))); } break; case CMD_ENDABSTRACT: if (closeCommand(cmd)) { leavePara(); append(Atom::AbstractRight); } break; case CMD_ENDCHAPTER: endSection(0, cmd); break; case CMD_ENDCODE: closeCommand(cmd); break; #ifdef QDOC_QML case CMD_ENDQML: closeCommand(cmd); break; case CMD_ENDQMLTEXT: append(Atom::EndQmlText); break; #endif case CMD_ENDFOOTNOTE: if (closeCommand(cmd)) { leavePara(); append(Atom::FootnoteRight); paraState = InsideMultiLinePara; // ### } break; case CMD_ENDIF: if (preprocessorSkipping.count() > 0) { if (preprocessorSkipping.pop()) --numPreprocessorSkipping; (void)getRestOfLine(); // ### should ensure that it's empty if (numPreprocessorSkipping) skipToNextPreprocessorCommand(); } else { location().warning(tr("Unexpected '\\%1'").arg(cmdName(CMD_ENDIF))); } break; case CMD_ENDLEGALESE: if (closeCommand(cmd)) { leavePara(); append(Atom::LegaleseRight); } break; case CMD_ENDLINK: if (closeCommand(cmd)) { if (priv->text.lastAtom()->type() == Atom::String && priv->text.lastAtom()->string().endsWith(" ")) priv->text.lastAtom()->chopString(); append(Atom::FormattingRight, ATOM_FORMATTING_LINK); } break; case CMD_ENDLIST: if (closeCommand(cmd)) { leavePara(); if (openedLists.top().isStarted()) { append(Atom::ListItemRight, openedLists.top().styleString()); append(Atom::ListRight, openedLists.top().styleString()); } openedLists.pop(); } break; case CMD_ENDOMIT: closeCommand(cmd); break; case CMD_ENDPART: endSection(-1, cmd); break; case CMD_ENDQUOTATION: if (closeCommand(cmd)) { leavePara(); append(Atom::QuotationRight); } break; case CMD_ENDRAW: location().warning(tr("Unexpected '\\%1'").arg(cmdName(CMD_ENDRAW))); break; case CMD_ENDSECTION1: endSection(1, cmd); break; case CMD_ENDSECTION2: endSection(2, cmd); break; case CMD_ENDSECTION3: endSection(3, cmd); break; case CMD_ENDSECTION4: endSection(4, cmd); break; case CMD_ENDSIDEBAR: if (closeCommand(cmd)) { leavePara(); append(Atom::SidebarRight); } break; case CMD_ENDTABLE: if (closeCommand(cmd)) { leaveTableRow(); append(Atom::TableRight); } break; case CMD_EXPIRE: checkExpiry(getArgument()); break; case CMD_FOOTNOTE: if (openCommand(cmd)) { enterPara(); append(Atom::FootnoteLeft); paraState = OutsidePara; // ### } break; case CMD_GENERATELIST: append(Atom::GeneratedList, getArgument()); break; case CMD_GRANULARITY: priv->constructExtra(); priv->extra->granularity = getSectioningUnit(); break; case CMD_HEADER: if (openedCommands.top() == CMD_TABLE) { leaveTableRow(); append(Atom::TableHeaderLeft); inTableHeader = true; } else { if (openedCommands.contains(CMD_TABLE)) { location().warning(tr("Cannot use '\\%1' within '\\%2'") .arg(cmdName(CMD_HEADER)) .arg(cmdName(openedCommands.top()))); } else { location().warning(tr("Cannot use '\\%1' outside of '\\%2'") .arg(cmdName(CMD_HEADER)) .arg(cmdName(CMD_TABLE))); } } break; case CMD_I: startFormat(ATOM_FORMATTING_ITALIC, cmd); break; case CMD_IF: preprocessorSkipping.push(!Tokenizer::isTrue(getRestOfLine())); if (preprocessorSkipping.top()) ++numPreprocessorSkipping; if (numPreprocessorSkipping) skipToNextPreprocessorCommand(); break; case CMD_IMAGE: leaveValueList(); append(Atom::Image, getArgument()); append(Atom::ImageText, getRestOfLine()); break; case CMD_INCLUDE: include(getArgument()); break; case CMD_INLINEIMAGE: enterPara(); append(Atom::InlineImage, getArgument()); append(Atom::ImageText, getRestOfLine()); append(Atom::String, " "); break; case CMD_INDEX: if (paraState == OutsidePara) { enterPara(); indexStartedPara = true; } else { const Atom *last = priv->text.lastAtom(); if (indexStartedPara && (last->type() != Atom::FormattingRight || last->string() != ATOM_FORMATTING_INDEX)) indexStartedPara = false; } startFormat(ATOM_FORMATTING_INDEX, cmd); break; case CMD_KEYWORD: insertTarget(getRestOfLine(),true); break; case CMD_L: enterPara(); if (isLeftBraceAhead()) { x = getArgument(); append(Atom::Link, x); if (isLeftBraceAhead()) { currentLinkAtom = priv->text.lastAtom(); startFormat(ATOM_FORMATTING_LINK, cmd); } else { append(Atom::FormattingLeft, ATOM_FORMATTING_LINK); append(Atom::String, cleanLink(x)); append(Atom::FormattingRight, ATOM_FORMATTING_LINK); } } else { x = getArgument(); append(Atom::Link, x); append(Atom::FormattingLeft, ATOM_FORMATTING_LINK); append(Atom::String, cleanLink(x)); append(Atom::FormattingRight, ATOM_FORMATTING_LINK); } break; case CMD_LEGALESE: leavePara(); if (openCommand(cmd)) append(Atom::LegaleseLeft); docPrivate->hasLegalese = true; break; case CMD_LINK: if (openCommand(cmd)) { enterPara(); x = getArgument(); append(Atom::Link, x); append(Atom::FormattingLeft, ATOM_FORMATTING_LINK); skipSpacesOrOneEndl(); } break; case CMD_LIST: if (openCommand(cmd)) { leavePara(); openedLists.push(OpenedList(location(), getOptionalArgument())); } break; case CMD_META: priv->constructExtra(); x = getArgument(); priv->extra->metaMap.insert(x, getRestOfLine()); break; case CMD_NEWCODE: location().warning(tr("Unexpected '\\%1'").arg(cmdName(CMD_NEWCODE))); break; case CMD_O: leavePara(); if (openedCommands.top() == CMD_LIST) { if (openedLists.top().isStarted()) { append(Atom::ListItemRight, openedLists.top().styleString()); } else { append(Atom::ListLeft, openedLists.top().styleString()); } openedLists.top().next(); append(Atom::ListItemNumber, openedLists.top().numberString()); append(Atom::ListItemLeft, openedLists.top().styleString()); enterPara(); } else if (openedCommands.top() == CMD_TABLE) { x = "1,1"; if (isLeftBraceAhead()) x = getArgument(); if (!inTableHeader && !inTableRow) { location().warning(tr("Missing '\\%1' or '\\%1' before '\\%3'") .arg(cmdName(CMD_HEADER)) .arg(cmdName(CMD_ROW)) .arg(cmdName(CMD_O))); append(Atom::TableRowLeft); inTableRow = true; } else if (inTableItem) { append(Atom::TableItemRight); inTableItem = false; } append(Atom::TableItemLeft, x); inTableItem = true; } else { location().warning(tr("Command '\\%1' outside of '\\%2' and '\\%3'") .arg(cmdName(cmd)) .arg(cmdName(CMD_LIST)) .arg(cmdName(CMD_TABLE))); } break; case CMD_OLDCODE: leavePara(); #ifdef QDOC2DOX if (DoxWriter::isDoxPass()) { append(Atom::CodeOld, getUnmarkedCode(CMD_OLDCODE)); append(Atom::CodeNew, getUnmarkedCode(CMD_NEWCODE)); } else { append(Atom::CodeOld, getCode(CMD_OLDCODE, marker)); append(Atom::CodeNew, getCode(CMD_NEWCODE, marker)); } #else append(Atom::CodeOld, getCode(CMD_OLDCODE, marker)); append(Atom::CodeNew, getCode(CMD_NEWCODE, marker)); #endif break; case CMD_OMIT: getUntilEnd(cmd); break; case CMD_OMITVALUE: x = getArgument(); if (!priv->enumItemList.contains(x)) priv->enumItemList.append(x); if (!priv->omitEnumItemList.contains(x)) priv->omitEnumItemList.append(x); break; case CMD_PART: startSection(Doc::Part, cmd); break; case CMD_PRINTLINE: leavePara(); if (!quoting) appendToCode(quoter.quoteLine(location(), cmdStr, getRestOfLine())); else { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, getRestOfLine()); } break; case CMD_PRINTTO: leavePara(); if (!quoting) appendToCode(quoter.quoteTo(location(), cmdStr, getRestOfLine())); else { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, getRestOfLine()); } break; case CMD_PRINTUNTIL: leavePara(); if (!quoting) appendToCode(quoter.quoteUntil(location(), cmdStr, getRestOfLine())); else { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, getRestOfLine()); } break; case CMD_QUOTATION: if (openCommand(cmd)) { leavePara(); append(Atom::QuotationLeft); } break; case CMD_QUOTEFILE: { leavePara(); QString fileName = getArgument(); Doc::quoteFromFile(location(), quoter, fileName); if (!quoting) { append(Atom::Code, quoter.quoteTo(location(), cmdStr, "")); quoter.reset(); } else { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, fileName); } break; } case CMD_QUOTEFROMFILE: leavePara(); if (!quoting) quoteFromFile(); else { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, getArgument()); } break; case CMD_QUOTEFUNCTION: leavePara(); marker = quoteFromFile(); x = getRestOfLine(); if (!quoting) { quoter.quoteTo(location(), cmdStr, slashed(marker->functionBeginRegExp(x))); append(Atom::Code, quoter.quoteUntil(location(), cmdStr, slashed(marker->functionEndRegExp(x)))); quoter.reset(); } else { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, slashed(marker->functionEndRegExp(x))); } break; case CMD_RAW: leavePara(); x = getRestOfLine(); if (x.isEmpty()) location().warning(tr("Missing format name after '\\%1") .arg(cmdName(CMD_RAW))); append(Atom::FormatIf, x); append(Atom::RawString, untabifyEtc(getUntilEnd(cmd))); append(Atom::FormatElse); append(Atom::FormatEndif); break; case CMD_ROW: if (openedCommands.top() == CMD_TABLE) { leaveTableRow(); append(Atom::TableRowLeft); inTableRow = true; } else { if (openedCommands.contains(CMD_TABLE)) { location().warning(tr("Cannot use '\\%1' within '\\%2'") .arg(cmdName(CMD_ROW)) .arg(cmdName(openedCommands.top()))); } else { location().warning(tr("Cannot use '\\%1' outside of '\\%2'") .arg(cmdName(CMD_ROW)) .arg(cmdName(CMD_TABLE))); } } break; case CMD_SA: parseAlso(); break; case CMD_SECTION1: startSection(Doc::Section1, cmd); break; case CMD_SECTION2: startSection(Doc::Section2, cmd); break; case CMD_SECTION3: startSection(Doc::Section3, cmd); break; case CMD_SECTION4: startSection(Doc::Section4, cmd); break; case CMD_SIDEBAR: if (openCommand(cmd)) { leavePara(); append(Atom::SidebarLeft); } break; case CMD_SKIPLINE: leavePara(); if (!quoting) quoter.quoteLine(location(), cmdStr, getRestOfLine()); else { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, getRestOfLine()); } break; case CMD_SKIPTO: leavePara(); if (!quoting) quoter.quoteTo(location(), cmdStr, getRestOfLine()); else { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, getRestOfLine()); } break; case CMD_SKIPUNTIL: leavePara(); if (!quoting) quoter.quoteUntil(location(), cmdStr, getRestOfLine()); else { append(Atom::CodeQuoteCommand, cmdStr); append(Atom::CodeQuoteArgument, getRestOfLine()); } break; case CMD_SNIPPET: leavePara(); { QString snippet = getArgument(); QString identifier = getRestOfLine(); #ifdef QDOC2DOX if (quoting || DoxWriter::isDoxPass()) { append(Atom::SnippetCommand, cmdStr); append(Atom::SnippetLocation, snippet); append(Atom::SnippetIdentifier, identifier); } else { Doc::quoteFromFile(location(),quoter,snippet); appendToCode(quoter.quoteSnippet(location(), identifier)); } #else if (quoting) { append(Atom::SnippetCommand, cmdStr); append(Atom::SnippetLocation, snippet); append(Atom::SnippetIdentifier, identifier); } else { Doc::quoteFromFile(location(),quoter,snippet); appendToCode(quoter.quoteSnippet(location(), identifier)); } #endif } break; case CMD_SUB: startFormat(ATOM_FORMATTING_SUBSCRIPT, cmd); break; case CMD_SUP: startFormat(ATOM_FORMATTING_SUPERSCRIPT, cmd); break; case CMD_TABLE: x = getRestOfLine(); if (openCommand(cmd)) { leavePara(); append(Atom::TableLeft, x); inTableHeader = false; inTableRow = false; inTableItem = false; } break; case CMD_TABLEOFCONTENTS: x = "1"; if (isLeftBraceAhead()) x = getArgument(); x += ","; x += QString::number((int)getSectioningUnit()); append(Atom::TableOfContents, x); break; case CMD_TARGET: insertTarget(getRestOfLine(),false); break; case CMD_TT: startFormat(ATOM_FORMATTING_TELETYPE, cmd); break; case CMD_UNDERLINE: startFormat(ATOM_FORMATTING_UNDERLINE, cmd); break; case CMD_UNICODE: enterPara(); x = getArgument(); { bool ok; uint unicodeChar = x.toUInt(&ok, 0); if (!ok || (unicodeChar == 0x0000) || (unicodeChar > 0xFFFE)) { location().warning(tr("Invalid Unicode character '%1' specified " "with '%2'") .arg(x, cmdName(CMD_UNICODE))); } else { append(Atom::String, QChar(unicodeChar)); } } break; case CMD_VALUE: leaveValue(); if (openedLists.top().style() == OpenedList::Value) { x = getArgument(); if (!priv->enumItemList.contains(x)) priv->enumItemList.append(x); openedLists.top().next(); append(Atom::ListTagLeft, ATOM_LIST_VALUE); append(Atom::String, x); append(Atom::ListTagRight, ATOM_LIST_VALUE); append(Atom::ListItemLeft, ATOM_LIST_VALUE); skipSpacesOrOneEndl(); if (isBlankLine()) append(Atom::Nop); } else { // ### problems } break; case CMD_WARNING: startNewPara(); append(Atom::FormattingLeft, ATOM_FORMATTING_BOLD); append(Atom::String, "Warning:"); append(Atom::FormattingRight, ATOM_FORMATTING_BOLD); append(Atom::String, " "); break; case CMD_OVERLOAD: // qdoc --> doxygen priv->metacommandsUsed.insert(cmdStr); x.clear(); if (!isBlankLine()) x = getRestOfLine(); if (!x.isEmpty()) { append(Atom::ParaLeft); append(Atom::String, "This function overloads "); append(Atom::AutoLink,x); append(Atom::String, "."); append(Atom::ParaRight); } else { append(Atom::ParaLeft); append(Atom::String, "This is an overloaded member function, " "provided for convenience."); append(Atom::ParaRight); x = getMetaCommandArgument(cmdStr); } priv->metaCommandMap[cmdStr].append(x); break; case NOT_A_CMD: if (metaCommandSet.contains(cmdStr)) { priv->metacommandsUsed.insert(cmdStr); QString xxx = getMetaCommandArgument(cmdStr); priv->metaCommandMap[cmdStr].append(xxx); } else if (macroHash()->contains(cmdStr)) { const Macro ¯o = macroHash()->value(cmdStr); int numPendingFi = 0; QStringMap::ConstIterator d; d = macro.otherDefs.begin(); while (d != macro.otherDefs.end()) { append(Atom::FormatIf, d.key()); expandMacro(cmdStr, *d, macro.numParams); ++d; if (d == macro.otherDefs.end()) { append(Atom::FormatEndif); } else { append(Atom::FormatElse); numPendingFi++; } } while (numPendingFi-- > 0) append(Atom::FormatEndif); if (!macro.defaultDef.isEmpty()) { if (!macro.otherDefs.isEmpty()) { macro.defaultDefLocation.warning( tr("Macro cannot have both " "format-specific and qdoc- " "syntax definitions")); } else { location().push(macro.defaultDefLocation.filePath()); in.insert(pos, macro.defaultDef); len = in.length(); openedInputs.push(pos + macro.defaultDef.length()); } } } else { location().warning( tr("Unknown command '\\%1'").arg(cmdStr), detailsUnknownCommand(metaCommandSet,cmdStr)); enterPara(); append(Atom::UnknownCommand, cmdStr); } } } } break; case '{': enterPara(); appendChar('{'); braceDepth++; pos++; break; case '}': { braceDepth--; pos++; QMap::Iterator f = pendingFormats.find(braceDepth); if (f == pendingFormats.end()) { enterPara(); appendChar('}'); } else { append(Atom::FormattingRight, *f); if (*f == ATOM_FORMATTING_INDEX) { if (indexStartedPara) skipAllSpaces(); } else if (*f == ATOM_FORMATTING_LINK) { // hack for C++ to support links like // \l{QString::}{count()} if (currentLinkAtom && currentLinkAtom->string().endsWith("::")) { QString suffix = Text::subText(currentLinkAtom, priv->text.lastAtom()).toString(); currentLinkAtom->appendString(suffix); } currentLinkAtom = 0; } pendingFormats.erase(f); } } break; default: { bool newWord; switch (priv->text.lastAtom()->type()) { case Atom::ParaLeft: newWord = true; break; default: newWord = false; } if (paraState == OutsidePara) { if (ch.isSpace()) { ++pos; newWord = false; } else { enterPara(); newWord = true; } } else { if (ch.isSpace()) { ++pos; if ((ch == '\n') && (paraState == InsideSingleLinePara || isBlankLine())) { leavePara(); newWord = false; } else { appendChar(' '); newWord = true; } } else { newWord = true; } } if (newWord) { int startPos = pos; int numInternalUppercase = 0; int numLowercase = 0; int numStrangeSymbols = 0; while (pos < len) { unsigned char latin1Ch = in.at(pos).toLatin1(); if (islower(latin1Ch)) { ++numLowercase; ++pos; } else if (isupper(latin1Ch)) { if (pos > startPos) ++numInternalUppercase; ++pos; } else if (isdigit(latin1Ch)) { if (pos > startPos) { ++pos; } else { break; } } else if (latin1Ch == '_' || latin1Ch == '@') { ++numStrangeSymbols; ++pos; } else if (latin1Ch == ':' && pos < len - 1 && in.at(pos + 1) == QLatin1Char(':')) { ++numStrangeSymbols; pos += 2; } else if (latin1Ch == '(') { if (pos > startPos) { if (pos < len - 1 && in.at(pos + 1) == QLatin1Char(')')) { ++numStrangeSymbols; pos += 2; break; } else { // ### handle functions with signatures // and function calls break; } } else { break; } } else { break; } } if (pos == startPos) { if (!ch.isSpace()) { appendChar(ch); ++pos; } } else { QString word = in.mid(startPos, pos - startPos); // is word a C++ symbol or an English word? if ((numInternalUppercase >= 1 && numLowercase >= 2) || numStrangeSymbols >= 1) { append(Atom::AutoLink, word); } else { appendWord(word); } } } } } } leaveValueList(); // for compatibility if (openedCommands.top() == CMD_LEGALESE) { append(Atom::LegaleseRight); openedCommands.pop(); } if (openedCommands.top() != CMD_OMIT) { location().warning(tr("Missing '\\%1'").arg(endCmdName(openedCommands.top()))); } else if (preprocessorSkipping.count() > 0) { location().warning(tr("Missing '\\%1'").arg(cmdName(CMD_ENDIF))); } while (currentSectioningUnit > Doc::Chapter) { int delta = currentSectioningUnit - priv->extra->sectioningUnit; append(Atom::SectionRight, QString::number(delta)); currentSectioningUnit = Doc::SectioningUnit(int(currentSectioningUnit) - 1); } if (priv->extra && priv->extra->granularity < priv->extra->sectioningUnit) priv->extra->granularity = priv->extra->sectioningUnit; priv->text.stripFirstAtom(); } Location &DocParser::location() { while (!openedInputs.isEmpty() && openedInputs.top() <= pos) { cachedLoc.pop(); cachedPos = openedInputs.pop(); } while (cachedPos < pos) cachedLoc.advance(in.at(cachedPos++)); return cachedLoc; } QString DocParser::detailsUnknownCommand(const QSet &metaCommandSet, const QString &str) { QSet commandSet = metaCommandSet; int i = 0; while (cmds[i].english != 0) { commandSet.insert(*cmds[i].alias); i++; } if (aliasMap()->contains(str)) return tr("The command '\\%1' was renamed '\\%2' by the configuration" " file. Use the new name.") .arg(str).arg((*aliasMap())[str]); QString best = nearestName(str, commandSet); if (best.isEmpty()) return QString(); return tr("Maybe you meant '\\%1'?").arg(best); } void DocParser::checkExpiry(const QString& date) { QRegExp ymd("(\\d{4})(?:-(\\d{2})(?:-(\\d{2})))"); if (ymd.exactMatch(date)) { int y = ymd.cap(1).toInt(); int m = ymd.cap(2).toInt(); int d = ymd.cap(3).toInt(); if (m == 0) m = 1; if (d == 0) d = 1; QDate expiryDate(y, m, d); if (expiryDate.isValid()) { int days = expiryDate.daysTo(QDate::currentDate()); if (days == 0) { location().warning(tr("Documentation expires today")); } else if (days == 1) { location().warning(tr("Documentation expired yesterday")); } else if (days >= 2) { location().warning(tr("Documentation expired %1 days ago") .arg(days)); } } else { location().warning(tr("Date '%1' invalid").arg(date)); } } else { location().warning(tr("Date '%1' not in YYYY-MM-DD format") .arg(date)); } } void DocParser::insertBaseName(const QString &baseName) { priv->constructExtra(); if (currentSectioningUnit == priv->extra->sectioningUnit) { priv->extra->baseName = baseName; } else { Atom *atom = priv->text.firstAtom(); Atom *sectionLeft = 0; int delta = currentSectioningUnit - priv->extra->sectioningUnit; while (atom != 0) { if (atom->type() == Atom::SectionLeft && atom->string().toInt() == delta) sectionLeft = atom; atom = atom->next(); } if (sectionLeft != 0) (void) new Atom(sectionLeft, Atom::BaseName, baseName); } } void DocParser::insertTarget(const QString &target, bool keyword) { if (targetMap.contains(target)) { location().warning(tr("Duplicate target name '%1'").arg(target)); targetMap[target].warning(tr("(The previous occurrence is here)")); } else { targetMap.insert(target, location()); append(Atom::Target, target); priv->constructExtra(); if (keyword) priv->extra->keywords.append(priv->text.lastAtom()); else priv->extra->targets.append(priv->text.lastAtom()); } } void DocParser::include(const QString& fileName) { if (location().depth() > 16) location().fatal(tr("Too many nested '\\%1's") .arg(cmdName(CMD_INCLUDE))); QString userFriendlyFilePath; // ### use current directory? QString filePath = Config::findFile(location(), sourceFiles, sourceDirs, fileName, userFriendlyFilePath); if (filePath.isEmpty()) { location().warning(tr("Cannot find leaf file '%1'").arg(fileName)); } else { QFile inFile(filePath); if (!inFile.open(QFile::ReadOnly)) { location().warning(tr("Cannot open leaf file '%1'") .arg(userFriendlyFilePath)); } else { location().push(userFriendlyFilePath); QTextStream inStream(&inFile); QString includedStuff = inStream.readAll(); inFile.close(); in.insert(pos, includedStuff); len = in.length(); openedInputs.push(pos + includedStuff.length()); } } } void DocParser::startFormat(const QString& format, int cmd) { enterPara(); QMap::ConstIterator f = pendingFormats.begin(); while (f != pendingFormats.end()) { if (*f == format) { location().warning(tr("Cannot nest '\\%1' commands") .arg(cmdName(cmd))); return; } ++f; } append(Atom::FormattingLeft, format); if (isLeftBraceAhead()) { skipSpacesOrOneEndl(); pendingFormats.insert(braceDepth, format); ++braceDepth; ++pos; } else { append(Atom::String, getArgument()); append(Atom::FormattingRight, format); if (format == ATOM_FORMATTING_INDEX && indexStartedPara) { skipAllSpaces(); indexStartedPara = false; } } } bool DocParser::openCommand(int cmd) { int outer = openedCommands.top(); bool ok = true; if (cmd != CMD_LINK) { if (outer == CMD_LIST) { ok = (cmd == CMD_FOOTNOTE || cmd == CMD_LIST); } else if (outer == CMD_ABSTRACT) { ok = (cmd == CMD_LIST || cmd == CMD_QUOTATION || cmd == CMD_TABLE); } else if (outer == CMD_SIDEBAR) { ok = (cmd == CMD_LIST || cmd == CMD_QUOTATION || cmd == CMD_SIDEBAR); } else if (outer == CMD_QUOTATION) { ok = (cmd == CMD_LIST); } else if (outer == CMD_TABLE) { ok = (cmd == CMD_LIST || cmd == CMD_FOOTNOTE || cmd == CMD_QUOTATION); } else if (outer == CMD_FOOTNOTE || outer == CMD_LINK) { ok = false; } } if (ok) { openedCommands.push(cmd); } else { location().warning(tr("Cannot use '\\%1' within '\\%2'") .arg(cmdName(cmd)).arg(cmdName(outer))); } return ok; } bool DocParser::closeCommand(int endCmd) { if (endCmdFor(openedCommands.top()) == endCmd && openedCommands.size() > 1) { openedCommands.pop(); return true; } else { bool contains = false; QStack opened2 = openedCommands; while (opened2.size() > 1) { if (endCmdFor(opened2.top()) == endCmd) { contains = true; break; } opened2.pop(); } if (contains) { while (endCmdFor(openedCommands.top()) != endCmd && openedCommands.size() > 1) { location().warning(tr("Missing '\\%1' before '\\%2'") .arg(endCmdName(openedCommands.top())) .arg(cmdName(endCmd))); openedCommands.pop(); } } else { location().warning(tr("Unexpected '\\%1'") .arg(cmdName(endCmd))); } return false; } } void DocParser::startSection(Doc::SectioningUnit unit, int cmd) { leavePara(); if (currentSectioningUnit == Doc::Book) { if (unit > Doc::Section1) location().warning(tr("Unexpected '\\%1' without '\\%2'") .arg(cmdName(cmd)) .arg(cmdName(CMD_SECTION1))); currentSectioningUnit = (Doc::SectioningUnit) (unit - 1); priv->constructExtra(); priv->extra->sectioningUnit = currentSectioningUnit; } if (unit <= priv->extra->sectioningUnit) { location().warning(tr("Unexpected '\\%1' in this documentation") .arg(cmdName(cmd))); } else if (unit - currentSectioningUnit > 1) { location().warning(tr("Unexpected '\\%1' at this point") .arg(cmdName(cmd))); } else { if (currentSectioningUnit >= unit) endSection(unit, cmd); int delta = unit - priv->extra->sectioningUnit; append(Atom::SectionLeft, QString::number(delta)); priv->constructExtra(); priv->extra->tableOfContents.append(priv->text.lastAtom()); priv->extra->tableOfContentsLevels.append(unit); enterPara(Atom::SectionHeadingLeft, Atom::SectionHeadingRight, QString::number(delta)); currentSectioningUnit = unit; } } void DocParser::endSection(int unit, int endCmd) { leavePara(); if (unit < priv->extra->sectioningUnit) { location().warning(tr("Unexpected '\\%1' in this documentation") .arg(cmdName(endCmd))); } else if (unit > currentSectioningUnit) { location().warning(tr("Unexpected '\\%1' at this point") .arg(cmdName(endCmd))); } else { while (currentSectioningUnit >= unit) { int delta = currentSectioningUnit - priv->extra->sectioningUnit; append(Atom::SectionRight, QString::number(delta)); currentSectioningUnit = (Doc::SectioningUnit) (currentSectioningUnit - 1); } } } void DocParser::parseAlso() { leavePara(); skipSpacesOnLine(); while (pos < len && in[pos] != '\n') { QString target; QString str; if (in[pos] == '{') { target = getArgument(); skipSpacesOnLine(); if (in[pos] == '{') { str = getArgument(); // hack for C++ to support links like \l{QString::}{count()} if (target.endsWith("::")) target += str; } else { str = target; } #ifdef QDOC2_COMPAT } else if (in[pos] == '\\' && in.mid(pos, 5) == "\\link") { pos += 6; target = getArgument(); int endPos = in.indexOf("\\endlink", pos); if (endPos != -1) { str = in.mid(pos, endPos - pos).trimmed(); pos = endPos + 8; } #endif } else { target = getArgument(); str = cleanLink(target); } Text also; also << Atom(Atom::Link, target) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << str << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); priv->addAlso(also); skipSpacesOnLine(); if (pos < len && in[pos] == ',') { pos++; skipSpacesOrOneEndl(); } else if (in[pos] != '\n') { location().warning(tr("Missing comma in '\\%1'").arg(cmdName(CMD_SA))); } } } void DocParser::append(Atom::Type type, const QString &string) { Atom::Type lastType = priv->text.lastAtom()->type(); #ifdef QDOC_QML if (((lastType == Atom::Code) || (lastType == Atom::Code)) && #else if ((lastType == Atom::Code) && #endif priv->text.lastAtom()->string().endsWith(QLatin1String("\n\n"))) priv->text.lastAtom()->chopString(); priv->text << Atom(type, string); } void DocParser::appendChar(QChar ch) { if (priv->text.lastAtom()->type() != Atom::String) append(Atom::String); Atom *atom = priv->text.lastAtom(); if (ch == QLatin1Char(' ')) { if (!atom->string().endsWith(QLatin1Char(' '))) atom->appendChar(QLatin1Char(' ')); } else atom->appendChar(ch); } void DocParser::appendWord(const QString &word) { if (priv->text.lastAtom()->type() != Atom::String) { append(Atom::String, word); } else priv->text.lastAtom()->appendString(word); } void DocParser::appendToCode(const QString& markedCode) { Atom::Type lastType = priv->text.lastAtom()->type(); #ifdef QDOC_QML if (lastType != Atom::Qml) append(Atom::Qml); #else if (lastType != Atom::Code) append(Atom::Code); #endif priv->text.lastAtom()->appendString(markedCode); } void DocParser::startNewPara() { leavePara(); enterPara(); } void DocParser::enterPara(Atom::Type leftType, Atom::Type rightType, const QString& string) { if (paraState == OutsidePara) { if (priv->text.lastAtom()->type() != Atom::ListItemLeft) leaveValueList(); append(leftType, string); indexStartedPara = false; pendingParaLeftType = leftType; pendingParaRightType = rightType; pendingParaString = string; if ( #if 0 leftType == Atom::BriefLeft || #endif leftType == Atom::SectionHeadingLeft) { paraState = InsideSingleLinePara; } else { paraState = InsideMultiLinePara; } skipSpacesOrOneEndl(); } } void DocParser::leavePara() { if (paraState != OutsidePara) { if (!pendingFormats.isEmpty()) { location().warning(tr("Missing '}'")); pendingFormats.clear(); } if (priv->text.lastAtom()->type() == pendingParaLeftType) { priv->text.stripLastAtom(); } else { if (priv->text.lastAtom()->type() == Atom::String && priv->text.lastAtom()->string().endsWith(" ")) { priv->text.lastAtom()->chopString(); } append(pendingParaRightType, pendingParaString); } paraState = OutsidePara; indexStartedPara = false; pendingParaRightType = Atom::Nop; pendingParaString = ""; } } void DocParser::leaveValue() { leavePara(); if (openedLists.isEmpty()) { openedLists.push(OpenedList(OpenedList::Value)); append(Atom::ListLeft, ATOM_LIST_VALUE); } else { if (priv->text.lastAtom()->type() == Atom::Nop) priv->text.stripLastAtom(); append(Atom::ListItemRight, ATOM_LIST_VALUE); } } void DocParser::leaveValueList() { leavePara(); if (!openedLists.isEmpty() && (openedLists.top().style() == OpenedList::Value)) { if (priv->text.lastAtom()->type() == Atom::Nop) priv->text.stripLastAtom(); append(Atom::ListItemRight, ATOM_LIST_VALUE); append(Atom::ListRight, ATOM_LIST_VALUE); openedLists.pop(); } } void DocParser::leaveTableRow() { if (inTableItem) { leavePara(); append(Atom::TableItemRight); inTableItem = false; } if (inTableHeader) { append(Atom::TableHeaderRight); inTableHeader = false; } if (inTableRow) { append(Atom::TableRowRight); inTableRow = false; } } CodeMarker *DocParser::quoteFromFile() { return Doc::quoteFromFile(location(), quoter, getArgument()); } void DocParser::expandMacro(const QString &name, const QString &def, int numParams) { if (numParams == 0) { append(Atom::RawString, def); } else { QStringList args; QString rawString; for (int i = 0; i < numParams; i++) { if (numParams == 1 || isLeftBraceAhead()) { args << getArgument(true); } else { location().warning(tr("Macro '\\%1' invoked with too few" " arguments (expected %2, got %3)") .arg(name).arg(numParams).arg(i)); break; } } int j = 0; while (j < def.size()) { int paramNo; if ((def[j] == '\\') && (j < def.size() - 1) && ((paramNo = def[j + 1].digitValue()) >= 1) && (paramNo <= numParams)) { if (!rawString.isEmpty()) { append(Atom::RawString, rawString); rawString = ""; } append(Atom::String, args[paramNo - 1]); j += 2; } else { rawString += def[j++]; } } if (!rawString.isEmpty()) append(Atom::RawString, rawString); } } Doc::SectioningUnit DocParser::getSectioningUnit() { QString name = getOptionalArgument(); if (name == "part") { return Doc::Part; } else if (name == "chapter") { return Doc::Chapter; } else if (name == "section1") { return Doc::Section1; } else if (name == "section2") { return Doc::Section2; } else if (name == "section3") { return Doc::Section3; } else if (name == "section4") { return Doc::Section4; } else if (name.isEmpty()) { return Doc::Section4; } else { location().warning(tr("Invalid sectioning unit '%1'").arg(name)); return Doc::Book; } } QString DocParser::getArgument(bool verbatim) { QString arg; int delimDepth = 0; skipSpacesOrOneEndl(); int startPos = pos; /* Typically, an argument ends at the next white-space. However, braces can be used to group words: {a few words} Also, opening and closing parentheses have to match. Thus, printf("%d\n", x) is an argument too, although it contains spaces. Finally, trailing punctuation is not included in an argument, nor is 's. */ if (pos < (int) in.length() && in[pos] == '{') { pos++; while (pos < (int) in.length() && delimDepth >= 0) { switch (in[pos].unicode()) { case '{': delimDepth++; arg += "{"; pos++; break; case '}': delimDepth--; if (delimDepth >= 0) arg += "}"; pos++; break; case '\\': if (verbatim) { arg += in[pos]; pos++; } else { pos++; if (pos < (int) in.length()) { if (in[pos].isLetterOrNumber()) break; arg += in[pos]; if (in[pos].isSpace()) { skipAllSpaces(); } else { pos++; } } } break; default: arg += in[pos]; pos++; } } if (delimDepth > 0) location().warning(tr("Missing '}'")); } else { while (pos < in.length() && ((delimDepth > 0) || ((delimDepth == 0) && !in[pos].isSpace()))) { switch (in[pos].unicode()) { case '(': case '[': case '{': delimDepth++; arg += in[pos]; pos++; break; case ')': case ']': case '}': delimDepth--; if (pos == startPos || delimDepth >= 0) { arg += in[pos]; pos++; } break; case '\\': if (verbatim) { arg += in[pos]; pos++; } else { pos++; if (pos < (int) in.length()) { if (in[pos].isLetterOrNumber()) break; arg += in[pos]; if (in[pos].isSpace()) { skipAllSpaces(); } else { pos++; } } } break; default: arg += in[pos]; pos++; } } if ((arg.length() > 1) && (QString(".,:;!?").indexOf(in[pos - 1]) != -1) && !arg.endsWith("...")) { arg.truncate(arg.length() - 1); pos--; } if (arg.length() > 2 && in.mid(pos - 2, 2) == "'s") { arg.truncate(arg.length() - 2); pos -= 2; } } return arg.simplified(); } QString DocParser::getOptionalArgument() { skipSpacesOrOneEndl(); if (pos + 1 < (int) in.length() && in[pos] == '\\' && in[pos + 1].isLetterOrNumber()) { return ""; } else { return getArgument(); } } QString DocParser::getRestOfLine() { QString t; skipSpacesOnLine(); bool trailingSlash = false; do { int begin = pos; while (pos < in.size() && in[pos] != '\n') { if (in[pos] == '\\' && !trailingSlash) { trailingSlash = true; ++pos; while ((pos < in.size()) && in[pos].isSpace() && (in[pos] != '\n')) ++pos; } else { trailingSlash = false; ++pos; } } if (!t.isEmpty()) t += " "; t += in.mid(begin, pos - begin).simplified(); if (trailingSlash) { t.chop(1); t = t.simplified(); } if (pos < in.size()) ++pos; } while (pos < in.size() && trailingSlash); return t; } /*! The metacommand argument is normally the remaining text to the right of the metacommand itself. The extra blanks are stripped and the argument string is returned. */ QString DocParser::getMetaCommandArgument(const QString &cmdStr) { skipSpacesOnLine(); int begin = pos; int parenDepth = 0; while (pos < in.size() && (in[pos] != '\n' || parenDepth > 0)) { if (in.at(pos) == '(') ++parenDepth; else if (in.at(pos) == ')') --parenDepth; ++pos; } if (pos == in.size() && parenDepth > 0) { pos = begin; location().warning(tr("Unbalanced parentheses in '%1'").arg(cmdStr)); } QString t = in.mid(begin, pos - begin).simplified(); skipSpacesOnLine(); return t; } QString DocParser::getUntilEnd(int cmd) { int endCmd = endCmdFor(cmd); QRegExp rx("\\\\" + cmdName(endCmd) + "\\b"); QString t; int end = rx.indexIn(in, pos); if (end == -1) { location().warning(tr("Missing '\\%1'").arg(cmdName(endCmd))); pos = in.length(); } else { t = in.mid(pos, end - pos); pos = end + rx.matchedLength(); } return t; } QString DocParser::getCode(int cmd, CodeMarker *marker) { QString code = untabifyEtc(getUntilEnd(cmd)); int indent = indentLevel(code); if (indent < minIndent) minIndent = indent; code = unindent(minIndent, code); marker = CodeMarker::markerForCode(code); return marker->markedUpCode(code, 0, ""); } /*! Used only for generating doxygen output. */ QString DocParser::getUnmarkedCode(int cmd) { QString code = getUntilEnd(cmd); #if 0 int indent = indentLevel(code); if (indent < minIndent) minIndent = indent; code = unindent(minIndent, code); #endif return code; } bool DocParser::isBlankLine() { int i = pos; while (i < len && in[i].isSpace()) { if (in[i] == '\n') return true; i++; } return false; } bool DocParser::isLeftBraceAhead() { int numEndl = 0; int i = pos; while (i < len && in[i].isSpace() && numEndl < 2) { // ### bug with '\\' if (in[i] == '\n') numEndl++; i++; } return numEndl < 2 && i < len && in[i] == '{'; } void DocParser::skipSpacesOnLine() { while ((pos < in.length()) && in[pos].isSpace() && (in[pos].unicode() != '\n')) ++pos; } void DocParser::skipSpacesOrOneEndl() { int firstEndl = -1; while (pos < (int) in.length() && in[pos].isSpace()) { QChar ch = in[pos]; if (ch == '\n') { if (firstEndl == -1) { firstEndl = pos; } else { pos = firstEndl; break; } } pos++; } } void DocParser::skipAllSpaces() { while (pos < len && in[pos].isSpace()) pos++; } void DocParser::skipToNextPreprocessorCommand() { QRegExp rx("\\\\(?:" + cmdName(CMD_IF) + "|" + cmdName(CMD_ELSE) + "|" + cmdName(CMD_ENDIF) + ")\\b"); int end = rx.indexIn(in, pos + 1); // ### + 1 necessary? if (end == -1) pos = in.length(); else pos = end; } int DocParser::endCmdFor(int cmd) { switch (cmd) { case CMD_ABSTRACT: return CMD_ENDABSTRACT; case CMD_BADCODE: return CMD_ENDCODE; case CMD_CHAPTER: return CMD_ENDCHAPTER; case CMD_CODE: return CMD_ENDCODE; #ifdef QDOC_QML case CMD_QML: return CMD_ENDQML; case CMD_QMLTEXT: return CMD_ENDQMLTEXT; #endif case CMD_FOOTNOTE: return CMD_ENDFOOTNOTE; case CMD_LEGALESE: return CMD_ENDLEGALESE; case CMD_LINK: return CMD_ENDLINK; case CMD_LIST: return CMD_ENDLIST; case CMD_NEWCODE: return CMD_ENDCODE; case CMD_OLDCODE: return CMD_NEWCODE; case CMD_OMIT: return CMD_ENDOMIT; case CMD_PART: return CMD_ENDPART; case CMD_QUOTATION: return CMD_ENDQUOTATION; case CMD_RAW: return CMD_ENDRAW; case CMD_SECTION1: return CMD_ENDSECTION1; case CMD_SECTION2: return CMD_ENDSECTION2; case CMD_SECTION3: return CMD_ENDSECTION3; case CMD_SECTION4: return CMD_ENDSECTION4; case CMD_SIDEBAR: return CMD_ENDSIDEBAR; case CMD_TABLE: return CMD_ENDTABLE; default: return cmd; } } QString DocParser::cmdName(int cmd) { return *cmds[cmd].alias; } QString DocParser::endCmdName(int cmd) { return cmdName(endCmdFor(cmd)); } QString DocParser::untabifyEtc(const QString& str) { QString result; result.reserve(str.length()); int column = 0; for (int i = 0; i < str.length(); i++) { const QChar c = str.at(i); if (c == QLatin1Char('\r')) continue; if (c == QLatin1Char('\t')) { result += " " + (column % tabSize); column = ((column / tabSize) + 1) * tabSize; continue; } if (c == QLatin1Char('\n')) { while (result.endsWith(QLatin1Char(' '))) result.chop(1); result += c; column = 0; continue; } result += c; column++; } while (result.endsWith("\n\n")) result.truncate(result.length() - 1); while (result.startsWith("\n")) result = result.mid(1); return result; } int DocParser::indentLevel(const QString& str) { int minIndent = INT_MAX; int column = 0; for (int i = 0; i < (int) str.length(); i++) { if (str[i] == '\n') { column = 0; } else { if (str[i] != ' ' && column < minIndent) minIndent = column; column++; } } return minIndent; } QString DocParser::unindent(int level, const QString& str) { if (level == 0) return str; QString t; int column = 0; for (int i = 0; i < (int) str.length(); i++) { if (str[i] == QLatin1Char('\n')) { t += '\n'; column = 0; } else { if (column >= level) t += str[i]; column++; } } return t; } QString DocParser::slashed(const QString& str) { QString result = str; result.replace("/", "\\/"); return "/" + result + "/"; } #define COMMAND_BRIEF Doc::alias("brief") #ifdef QDOC_QML #define COMMAND_QMLBRIEF Doc::alias("qmlbrief") #endif #ifdef QDOC2DOX #define DOXYGEN_INDENT 2 #define DOXYGEN_TAB_SIZE 4 #define DOXYGEN_INDENT_STRING " " #define DOXYGEN_TAB_STRING " " static QRegExp ws_rx("\\s"); static QRegExp not_ws_rx("\\S"); int DoxWriter::doxPass = 0; QString DoxWriter::currentClass; QSet DoxWriter::anchors; QStringMap DoxWriter::exampleTitles; QStringMap DoxWriter::headerFileTitles; QStringMap DoxWriter::fileTitles; QStringMap DoxWriter::groupTitles; QStringMap DoxWriter::moduleTitles; QStringMap DoxWriter::pageTitles; QStringMap DoxWriter::externalPageTitles; QStringMap DoxWriter::exampleTitlesInverse; QStringMap DoxWriter::headerFileTitlesInverse; QStringMap DoxWriter::fileTitlesInverse; QStringMap DoxWriter::groupTitlesInverse; QStringMap DoxWriter::moduleTitlesInverse; QStringMap DoxWriter::pageTitlesInverse; QStringMap DoxWriter::externalPageTitlesInverse; QStringMultiMap DoxWriter::variables; QStringMultiMap DoxWriter::properties; QStringMultiMap DoxWriter::enums; #endif Doc::Doc(const Location& start_loc, const Location& end_loc, const QString& source, const QSet& metaCommandSet) { priv = new DocPrivate(start_loc,end_loc,source); DocParser parser; parser.parse(source,priv,metaCommandSet); #ifdef QDOC2DOX if (DoxWriter::isDoxPass()) { DoxWriter doxWriter(source,priv); if (DoxWriter::isDoxPass(1)) doxWriter.pass1(); else doxWriter.pass2(); } #endif } Doc::Doc(const Doc& doc) : priv(0) { operator=(doc); } Doc::~Doc() { if (priv && priv->deref()) delete priv; } Doc &Doc::operator=(const Doc& doc) { if (doc.priv) doc.priv->ref(); if (priv && priv->deref()) delete priv; priv = doc.priv; return *this; } void Doc::renameParameters(const QStringList &oldNames, const QStringList &newNames) { if (priv && oldNames != newNames) { detach(); priv->params = newNames.toSet(); Atom *atom = priv->text.firstAtom(); while (atom) { if (atom->type() == Atom::FormattingLeft && atom->string() == ATOM_FORMATTING_PARAMETER) { atom = atom->next(); if (!atom) return; int index = oldNames.indexOf(atom->string()); if (index != -1 && index < newNames.count()) atom->setString(newNames.at(index)); } atom = atom->next(); } } } void Doc::simplifyEnumDoc() { if (priv) { if (priv->isEnumDocSimplifiable()) { detach(); Text newText; Atom *atom = priv->text.firstAtom(); while (atom) { if ((atom->type() == Atom::ListLeft) && (atom->string() == ATOM_LIST_VALUE)) { while (atom && ((atom->type() != Atom::ListRight) || (atom->string() != ATOM_LIST_VALUE))) atom = atom->next(); if (atom) atom = atom->next(); } else { newText << *atom; atom = atom->next(); } } priv->text = newText; } } } void Doc::setBody(const Text &text) { detach(); priv->text = text; } /*! Returns the starting location of a qdoc comment. */ const Location &Doc::location() const { static const Location dummy; return priv == 0 ? dummy : priv->start_loc; } const QString &Doc::source() const { static QString null; return priv == 0 ? null : priv->src; } bool Doc::isEmpty() const { return priv == 0 || priv->src.isEmpty(); } const Text& Doc::body() const { static const Text dummy; return priv == 0 ? dummy : priv->text; } Text Doc::briefText() const { return body().subText(Atom::BriefLeft, Atom::BriefRight); } Text Doc::trimmedBriefText(const QString &className) const { QString classNameOnly = className; if (className.contains("::")) classNameOnly = className.split("::").last(); Text originalText = briefText(); Text resultText; const Atom *atom = originalText.firstAtom(); if (atom) { QString briefStr; QString whats; bool standardWording = true; /* This code is really ugly. The entire \brief business should be rethought. */ while (atom && (atom->type() == Atom::AutoLink || atom->type() == Atom::String)) { briefStr += atom->string(); atom = atom->next(); } QStringList w = briefStr.split(" "); if (!w.isEmpty() && w.first() == "The") w.removeFirst(); else { location().warning( tr("Nonstandard wording in '\\%1' text for '%2' (expected 'The')") .arg(COMMAND_BRIEF).arg(className)); standardWording = false; } if (!w.isEmpty() && (w.first() == className || w.first() == classNameOnly)) w.removeFirst(); else { location().warning( tr("Nonstandard wording in '\\%1' text for '%2' (expected '%3')") .arg(COMMAND_BRIEF).arg(className).arg(className)); standardWording = false; } if (!w.isEmpty() && (w.first() == "class" || w.first() == "widget" || w.first() == "namespace" || w.first() == "header")) w.removeFirst(); else { location().warning( tr("Nonstandard wording in '\\%1' text for '%2' (" "expected 'class', 'widget', 'namespace' or 'header')") .arg(COMMAND_BRIEF).arg(className)); standardWording = false; } if (!w.isEmpty() && (w.first() == "is" || w.first() == "provides")) w.removeFirst(); if (!w.isEmpty() && (w.first() == "a" || w.first() == "an")) w.removeFirst(); whats = w.join(" "); if (whats.endsWith(".")) whats.truncate(whats.length() - 1); if (whats.isEmpty()) { location().warning( tr("Nonstandard wording in '\\%1' text for '%2' (expected more text)") .arg(COMMAND_BRIEF).arg(className)); standardWording = false; } else whats[0] = whats[0].toUpper(); // ### move this once \brief is abolished for properties if (standardWording) resultText << whats; } return resultText; } Text Doc::legaleseText() const { if (priv == 0 || !priv->hasLegalese) return Text(); else return body().subText(Atom::LegaleseLeft, Atom::LegaleseRight); } const QString& Doc::baseName() const { static QString null; if (priv == 0 || priv->extra == 0) { return null; } else { return priv->extra->baseName; } } Doc::SectioningUnit Doc::granularity() const { if (priv == 0 || priv->extra == 0) { return DocPrivateExtra().granularity; } else { return priv->extra->granularity; } } #if notyet // ### Doc::SectioningUnit Doc::sectioningUnit() const { if (priv == 0 || priv->extra == 0) { return DocPrivateExtra().sectioningUnit; } else { return priv->extra->sectioningUnit; } } #endif const QSet &Doc::parameterNames() const { return priv == 0 ? *null_Set_QString() : priv->params; } const QStringList &Doc::enumItemNames() const { return priv == 0 ? *null_QStringList() : priv->enumItemList; } const QStringList &Doc::omitEnumItemNames() const { return priv == 0 ? *null_QStringList() : priv->omitEnumItemList; } const QSet &Doc::metaCommandsUsed() const { return priv == 0 ? *null_Set_QString() : priv->metacommandsUsed; } QStringList Doc::metaCommandArgs(const QString& metacommand) const { return priv == 0 ? QStringList() : priv->metaCommandMap.value(metacommand); } const QList &Doc::alsoList() const { return priv == 0 ? *null_QList_Text() : priv->alsoList; } bool Doc::hasTableOfContents() const { return priv && priv->extra && !priv->extra->tableOfContents.isEmpty(); } bool Doc::hasKeywords() const { return priv && priv->extra && !priv->extra->keywords.isEmpty(); } bool Doc::hasTargets() const { return priv && priv->extra && !priv->extra->targets.isEmpty(); } const QList &Doc::tableOfContents() const { priv->constructExtra(); return priv->extra->tableOfContents; } const QList &Doc::tableOfContentsLevels() const { priv->constructExtra(); return priv->extra->tableOfContentsLevels; } const QList &Doc::keywords() const { priv->constructExtra(); return priv->extra->keywords; } const QList &Doc::targets() const { priv->constructExtra(); return priv->extra->targets; } const QStringMap &Doc::metaTagMap() const { return priv && priv->extra ? priv->extra->metaMap : *null_QStringMap(); } void Doc::initialize(const Config& config) { DocParser::tabSize = config.getInt(CONFIG_TABSIZE); DocParser::exampleFiles = config.getStringList(CONFIG_EXAMPLES); DocParser::exampleDirs = config.getStringList(CONFIG_EXAMPLEDIRS); DocParser::sourceFiles = config.getStringList(CONFIG_SOURCES); DocParser::sourceDirs = config.getStringList(CONFIG_SOURCEDIRS); DocParser::quoting = config.getBool(CONFIG_QUOTINGINFORMATION); QStringMap reverseAliasMap; QSet commands = config.subVars(CONFIG_ALIAS); QSet::ConstIterator c = commands.begin(); while (c != commands.end()) { QString alias = config.getString(CONFIG_ALIAS + Config::dot + *c); if (reverseAliasMap.contains(alias)) { config.lastLocation().warning(tr("Command name '\\%1' cannot stand" " for both '\\%2' and '\\%3'") .arg(alias) .arg(reverseAliasMap[alias]) .arg(*c)); } else { reverseAliasMap.insert(alias, *c); } aliasMap()->insert(*c, alias); ++c; } int i = 0; while (cmds[i].english) { cmds[i].alias = new QString(alias(cmds[i].english)); cmdHash()->insert(*cmds[i].alias, cmds[i].no); if (cmds[i].no != i) Location::internalError(tr("command %1 missing").arg(i)); i++; } QSet macroNames = config.subVars(CONFIG_MACRO); QSet::ConstIterator n = macroNames.begin(); while (n != macroNames.end()) { QString macroDotName = CONFIG_MACRO + Config::dot + *n; Macro macro; macro.numParams = -1; macro.defaultDef = config.getString(macroDotName); if (!macro.defaultDef.isEmpty()) { macro.defaultDefLocation = config.lastLocation(); macro.numParams = Config::numParams(macro.defaultDef); } bool silent = false; QSet formats = config.subVars(macroDotName); QSet::ConstIterator f = formats.begin(); while (f != formats.end()) { QString def = config.getString(macroDotName + Config::dot + *f); if (!def.isEmpty()) { macro.otherDefs.insert(*f, def); int m = Config::numParams(macro.defaultDef); if (macro.numParams == -1) { macro.numParams = m; } else if (macro.numParams != m) { if (!silent) { QString other = tr("default"); if (macro.defaultDef.isEmpty()) other = macro.otherDefs.begin().key(); config.lastLocation().warning(tr("Macro '\\%1' takes" " inconsistent number" " of arguments (%2" " %3, %4 %5)") .arg(*n) .arg(*f) .arg(m) .arg(other) .arg(macro.numParams)); silent = true; } if (macro.numParams < m) macro.numParams = m; } } ++f; } if (macro.numParams != -1) macroHash()->insert(*n, macro); ++n; } } void Doc::terminate() { DocParser::exampleFiles.clear(); DocParser::exampleDirs.clear(); DocParser::sourceFiles.clear(); DocParser::sourceDirs.clear(); aliasMap()->clear(); cmdHash()->clear(); macroHash()->clear(); int i = 0; while (cmds[i].english) { delete cmds[i].alias; cmds[i].alias = 0; ++i; } } QString Doc::alias(const QString &english) { return aliasMap()->value(english, english); } /*! Trims the deadwood out of \a str. i.e., this function cleans up \a str. */ void Doc::trimCStyleComment(Location& location, QString& str) { QString cleaned; Location m = location; bool metAsterColumn = true; int asterColumn = location.columnNo() + 1; int i; for (i = 0; i < (int) str.length(); i++) { if (m.columnNo() == asterColumn) { if (str[i] != '*') break; cleaned += ' '; metAsterColumn = true; } else { if (str[i] == '\n') { if (!metAsterColumn) break; metAsterColumn = false; } cleaned += str[i]; } m.advance(str[i]); } if (cleaned.length() == str.length()) str = cleaned; for (int i = 0; i < 3; i++) location.advance(str[i]); str = str.mid(3, str.length() - 5); } CodeMarker *Doc::quoteFromFile(const Location &location, Quoter "er, const QString &fileName) { quoter.reset(); QString code; QString userFriendlyFilePath; QString filePath = Config::findFile(location, DocParser::exampleFiles, DocParser::exampleDirs, fileName, userFriendlyFilePath); if (filePath.isEmpty()) { location.warning(tr("Cannot find example file '%1'").arg(fileName)); } else { QFile inFile(filePath); if (!inFile.open(QFile::ReadOnly)) { location.warning(tr("Cannot open example file '%1'").arg(userFriendlyFilePath)); } else { QTextStream inStream(&inFile); code = DocParser::untabifyEtc(inStream.readAll()); } } QString dirPath = QFileInfo(filePath).path(); CodeMarker *marker = CodeMarker::markerForFileName(fileName); quoter.quoteFromFile(userFriendlyFilePath, code, marker->markedUpCode(code, 0, dirPath)); return marker; } QString Doc::canonicalTitle(const QString &title) { // The code below is equivalent to the following chunk, but _much_ // faster (accounts for ~10% of total running time) // // QRegExp attributeExpr("[^A-Za-z0-9]+"); // QString result = title.toLower(); // result.replace(attributeExpr, " "); // result = result.simplified(); // result.replace(QLatin1Char(' '), QLatin1Char('-')); QString result; result.reserve(title.size()); bool slurping = false; bool begun = false; int lastAlnum = 0; for (int i = 0; i != title.size(); ++i) { uint c = title.at(i).unicode(); if (c >= 'A' && c <= 'Z') c -= 'A' - 'a'; bool alnum = (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); if (alnum) { result += QLatin1Char(c); begun = true; slurping = false; lastAlnum = result.size(); } else if (!slurping) { if (begun) result += QLatin1Char('-'); slurping = true; } else { // !alnum && slurping -> nothin } } result.truncate(lastAlnum); return result; } void Doc::detach() { if (!priv) { priv = new DocPrivate; return; } if (priv->count == 1) return; --priv->count; DocPrivate *newPriv = new DocPrivate(*priv); newPriv->count = 1; if (priv->extra) newPriv->extra = new DocPrivateExtra(*priv->extra); priv = newPriv; } #ifdef QDOC2DOX /*! Sets the doxygen writer pass to \a pass. You can use isDoxPass(), with or without a parameter, to test if you are in a doxygen writer run or in a specific pass of a doxygen writer run. This function is only called from main() if either the \e doxygen1 or \e doxygen2 flag is passed to qdoc3 on the command line. */ void DoxWriter::setDoxPass(int pass) { qDebug() << "SETTING doxygen pass to " << pass << " in DoxWriter::setDoxPass()"; doxPass = pass; } /*! Returns true if the doxygen pass is set to \a pass, which means we are in the specified \a pass of a doxygen writer run of qdoc3. */ bool DoxWriter::isDoxPass(int pass) { return (doxPass == pass); } /*! Returns true if the doxygen pass is 1 or 2, which means this is a doxygen writer run to transform qdoc comments into doxygen comments. */ bool DoxWriter::isDoxPass() { return (doxPass > 0); } bool DoxWriter::conversionRequired() const { /* Loop through all the topic commands searching for one that must be transformed to doxygen format. If one is found, return true. */ QCommandMap::const_iterator i; i = priv->metaCommandMap.constBegin(); while (i != priv->metaCommandMap.constEnd()) { QString s = i.key(); if (s == "enum") return true; else if (s == "example") return true; else if (s == "externalpage") return true; else if (s == "group") return true; else if (s == "headerfile") return true; else if (s == "module") return true; else if (s == "page") return true; else if (s == "property") return true; else if (s == "typedef") return true; else if (s == "variable") return true; else if (s == "overload") return true; else if (s == "reimp") return true; else if (s == "relates") return true; else if (s == "macro") return true; else { #if 0 if (s == "class") else if (s == "namespace") else if (s == "service") else if (s == "inheaderfile") else if (s == "file") else if (s == "fn") else if (s == "contentspage") else if (s == "nextpage") else if (s == "previous") else if (s == "indexpage") else if (s == "startpage") #endif } ++i; } /* Loop through all the qdoc atoms searching for one that must be transformed to doxygen format. If one is found, return true. */ const Atom* next = priv->text.firstAtom(); while (next != 0) { Atom::Type atomType = next->type(); switch (atomType) { case Atom::C: case Atom::CaptionLeft: case Atom::Code: case Atom::CodeBad: case Atom::CodeNew: case Atom::CodeOld: case Atom::CodeQuoteArgument: case Atom::CodeQuoteCommand: case Atom::FootnoteLeft: case Atom::FormatElse: case Atom::FormatEndif: case Atom::FormatIf: case Atom::GeneratedList: case Atom::Image: case Atom::ImageText: case Atom::InlineImage: case Atom::LegaleseLeft: case Atom::LineBreak: case Atom::Link: case Atom::LinkNode: case Atom::ListLeft: case Atom::ListItemNumber: case Atom::ListTagLeft: case Atom::ListItemLeft: case Atom::QuotationLeft: case Atom::RawString: case Atom::SectionLeft: case Atom::SectionHeadingLeft: case Atom::SidebarLeft: case Atom::SnippetCommand: case Atom::SnippetIdentifier: case Atom::SnippetLocation: case Atom::TableLeft: case Atom::TableHeaderLeft: case Atom::TableRowLeft: case Atom::TableItemLeft: case Atom::TableOfContents: case Atom::Target: return true; case Atom::AbstractLeft: case Atom::AbstractRight: case Atom::AutoLink: case Atom::BaseName: case Atom::BriefLeft: case Atom::BriefRight: case Atom::CaptionRight: case Atom::FormattingLeft: case Atom::FormattingRight: case Atom::Nop: case Atom::ParaLeft: case Atom::ParaRight: case Atom::FootnoteRight: case Atom::LegaleseRight: case Atom::ListTagRight: case Atom::ListItemRight: case Atom::ListRight: case Atom::QuotationRight: case Atom::SectionRight: case Atom::SectionHeadingRight: case Atom::SidebarRight: case Atom::String: case Atom::TableRight: case Atom::TableHeaderRight: case Atom::TableRowRight: case Atom::TableItemRight: default: break; } next = next->next(); } return false; } /*! A convenience function to write a qdoc metacommand as a doxygen command, without conversion. i.e., some of the qdoc metacommands don't require conversion for doxygen. */ void DoxWriter::writeCommand(QCommandMap::const_iterator cmd) { concatenate("\\" + cmd.key() + " " + cmd.value()[0]); newLine(); } /*! Convert the qdoc commands in the metacommand map to doxygen format. This function is called only in pass2(). The metacommand map contains all the metacommands that were found in the qdoc comment that is being converted. The metacommands are the ones that begin with the '\'. These are not considered part of the text of the comment. The text is converted by convertText(). */ void DoxWriter::convertMetaCommands() { QCommandMap& metaCmdMap = priv->metaCommandMap; QCommandMap::iterator cmd; int c; currentPage.clear(); currentFn.clear(); currentTitle.clear(); currentEnum.clear(); currentProperty.clear(); currentVariable.clear(); currentClass.clear(); currentExample.clear(); currentGroup.clear(); currentModule.clear(); currentMacro.clear(); currentService.clear(); currentTypedef.clear(); currentHeaderFile.clear(); commentType = OtherComment; if ((cmd = metaCmdMap.find("class")) != metaCmdMap.end()) { currentClass = cmd.value()[0]; if ((c = currentClass.indexOf(' ')) > 0) currentClass = currentClass.left(c); writeCommand(cmd); metaCmdMap.erase(cmd); commentType = ClassComment; } else if ((cmd = metaCmdMap.find("fn")) != metaCmdMap.end()) { currentFn = cmd.value()[0]; writeCommand(cmd); metaCmdMap.erase(cmd); commentType = FnComment; } else if ((cmd = metaCmdMap.find("enum")) != metaCmdMap.end()) { currentEnum = cmd.value()[0]; if ((c = currentEnum.lastIndexOf("::")) > 0) { currentClass = currentEnum.left(c); currentEnum = currentEnum.right(currentEnum.size()-c-2); qDebug() << "currentEnum =" << currentEnum; qDebug() << "currentClass =" << currentClass; } writeCommand(cmd); metaCmdMap.erase(cmd); commentType = EnumComment; } else if ((cmd = metaCmdMap.find("property")) != metaCmdMap.end()) { currentClass = cmd.value()[0]; if ((c = currentClass.lastIndexOf("::")) > 0) { currentProperty = currentClass.right(currentClass.size()-c-2); currentClass = currentClass.left(c); qDebug() << "currentProperty =" << currentProperty; qDebug() << "currentClass =" << currentClass; } writeCommand(cmd); metaCmdMap.erase(cmd); commentType = PropertyComment; } else if ((cmd = metaCmdMap.find("variable")) != metaCmdMap.end()) { currentClass = cmd.value()[0]; if ((c = currentClass.lastIndexOf("::")) > 0) { currentVariable = currentClass.right(currentClass.size()-c-2); currentClass = currentClass.left(c); qDebug() << "currentVariable =" << currentVariable; qDebug() << "currentClass =" << currentClass; } concatenate("\\var " + cmd.value()[0]); newLine(); metaCmdMap.erase(cmd); commentType = VariableComment; } if ((cmd = metaCmdMap.find("page")) != metaCmdMap.end()) { currentPage = cmd.value()[0]; QString htmlFile = currentPage; const QString* title = getPageTitle(htmlFile); QStringList parts = htmlFile.split('.'); metaCmdMap.erase(cmd); if (title) { concatenate("\\page " + parts[0] + " " + *title); newLine(); } commentType = PageComment; qDebug() << "currentPage =" << currentPage; } if ((cmd = metaCmdMap.find("example")) != metaCmdMap.end()) { currentExample = cmd.value()[0]; metaCmdMap.erase(cmd); commentType = ExampleComment; qDebug() << "currentExample =" << currentExample; } if ((cmd = metaCmdMap.find("macro")) != metaCmdMap.end()) { currentMacro = cmd.value()[0]; metaCmdMap.erase(cmd); commentType = MacroComment; qDebug() << "currentMacro =" << currentMacro; } if ((cmd = metaCmdMap.find("group")) != metaCmdMap.end()) { currentGroup = cmd.value()[0]; metaCmdMap.erase(cmd); commentType = GroupComment; qDebug() << "currentGroup =" << currentGroup; } if ((cmd = metaCmdMap.find("module")) != metaCmdMap.end()) { currentModule = cmd.value()[0]; metaCmdMap.erase(cmd); commentType = ModuleComment; qDebug() << "currentModule =" << currentModule; } if ((cmd = metaCmdMap.find("headerfile")) != metaCmdMap.end()) { currentHeaderFile = cmd.value()[0]; metaCmdMap.erase(cmd); commentType = HeaderFileComment; qDebug() << "currentHeaderFile =" << currentHeaderFile; } if ((cmd = metaCmdMap.find("typedef")) != metaCmdMap.end()) { currentClass = cmd.value()[0]; if ((c = currentClass.lastIndexOf("::")) > 0) { currentTypedef = currentClass.right(currentClass.size()-c-2); currentClass = currentClass.left(c); } metaCmdMap.erase(cmd); commentType = TypedefComment; qDebug() << "currentTypedef =" << currentTypedef; qDebug() << "currentClass =" << currentClass; } cmd = priv->metaCommandMap.begin(); while (cmd != priv->metaCommandMap.end()) { for (int i=0; itext.firstAtom(); while (next != 0) { next->dump(); Atom::Type atomType = next->type(); switch (atomType) { case Atom::AbstractLeft: break; case Atom::AbstractRight: break; case Atom::AutoLink: concatenate(next->string()); break; case Atom::BaseName: break; case Atom::BriefLeft: concatenate("\\brief "); break; case Atom::BriefRight: newLine(); break; case Atom::C: tt(next); break; case Atom::CaptionLeft: unhandled(next); break; case Atom::CaptionRight: unhandled(next); break; case Atom::Code: code(next); break; case Atom::CodeBad: code(next); break; case Atom::CodeNew: newLine(); concatenate("you can rewrite it as"); code(next); break; case Atom::CodeOld: newLine(); concatenate("For example, if you have code like"); code(next); break; case Atom::CodeQuoteArgument: unhandled(next); break; case Atom::CodeQuoteCommand: next = codeQuoteCommand(next); break; case Atom::FootnoteLeft: break; case Atom::FootnoteRight: break; case Atom::FormatElse: formatElse(); break; case Atom::FormatEndif: formatEndif(); break; case Atom::FormatIf: formatIf(next); break; case Atom::FormattingLeft: formattingLeft(next,next->next()); break; case Atom::FormattingRight: formattingRight(next,prev); break; case Atom::GeneratedList: break; case Atom::Image: break; case Atom::ImageText: break; case Atom::InlineImage: break; case Atom::LegaleseLeft: break; case Atom::LegaleseRight: break; case Atom::LineBreak: break; case Atom::Link: next = link(next); break; case Atom::LinkNode: break; case Atom::ListLeft: { bool nested = false; if (structs.isEmpty()) { const Atom* i = next->next(); while (i->type() != Atom::ListRight) { if ((i->type() == Atom::ListLeft) || (i->type() == Atom::TableLeft)) { nested = true; break; } i = i->next(); } } else nested = true; StructDesc d(BulletList,nested); if (next->string() == "numeric") d.structType = NumericList; else if (next->string() == "value") { d.structType = ValueList; } else if (next->string() != "bullet") qDebug() << "UNKNOWN LIST TYPE" << next->string(); structs.push(d); if (nested || (d.structType != BulletList)) { if (d.structType == BulletList) concatenate("
    "); else if (d.structType == NumericList) concatenate("
      "); else if (d.structType == ValueList) concatenate("
      "); newLine(); } } break; case Atom::ListItemNumber: structs.top().count = next->string().toInt(); break; case Atom::ListTagLeft: { structs.top().count++; concatenate("
      "); const Atom* n = next->next(); if (n->type() == Atom::String) { qDebug() << "ENUM VALUE" << n->string(); } else qDebug() << "NOT EN ENUM"; } break; case Atom::ListTagRight: concatenate("
      "); break; case Atom::ListItemLeft: { newLine(); const StructDesc& d = structs.top(); if (d.structType == BulletList) { if (!d.nested) concatenate("\\arg "); else concatenate("
    1. "); } else if (d.structType == NumericList) concatenate("
    2. "); else if (d.structType == ValueList) concatenate("
      "); } break; case Atom::ListItemRight: { const StructDesc& d = structs.top(); if (d.structType == BulletList) { if (d.nested) { concatenate("
    3. "); newLine(); } } else if (d.structType == NumericList) { concatenate(""); newLine(); } else if (d.structType == ValueList) { concatenate(""); newLine(); } } break; case Atom::ListRight: { if (!structs.isEmpty()) { const StructDesc& d = structs.top(); if (d.nested || (d.structType != BulletList)) { if (d.structType == BulletList) concatenate("
"); else if (d.structType == NumericList) concatenate(""); else if (d.structType == ValueList) concatenate(""); newLine(); } structs.pop(); } } break; case Atom::Nop: // nothing. break; case Atom::ParaLeft: if (structs.isEmpty()) newLine(); break; case Atom::ParaRight: { if (structs.isEmpty()) newLine(); else { const StructDesc& d = structs.top(); if (d.nested || (d.structType != BulletList)) { Atom::Type t = next->next()->type(); if ((t != Atom::ListItemRight) && (t != Atom::TableItemRight)) newLine(); } else newLine(); } } break; case Atom::QuotationLeft: break; case Atom::QuotationRight: break; case Atom::RawString: concatenate(next->string()); break; case Atom::SectionLeft: // nothing. break; case Atom::SectionRight: // nothing. break; case Atom::SectionHeadingLeft: next = sectionHeading(next); break; case Atom::SectionHeadingRight: newLine(); break; case Atom::SidebarLeft: break; case Atom::SidebarRight: break; case Atom::SnippetCommand: newLine(); concatenate("\\snippet "); break; case Atom::SnippetIdentifier: newText += next->string(); lineLength += next->string().size(); newLine(); break; case Atom::SnippetLocation: newText += next->string() + " "; lineLength += next->string().size() + 1; break; case Atom::String: wrap(next->string()); break; case Atom::TableLeft: { bool nested = false; if (structs.isEmpty()) { const Atom* i = next->next(); while (i->type() != Atom::TableRight) { if ((i->type() == Atom::ListLeft) || (i->type() == Atom::TableLeft)) { nested = true; break; } i = i->next(); } } else nested = true; StructDesc d(Table,nested); structs.push(d); if (next->string().isEmpty()) concatenate(""); else { QString attrs = "width=\"" + next->string() + "\""; attrs += " align=\"center\""; concatenate("
"); } newLine(); } break; case Atom::TableRight: concatenate("
"); if (!structs.isEmpty()) structs.pop(); newLine(); break; case Atom::TableHeaderLeft: concatenate(""); if (!structs.isEmpty()) structs.top().inTableHeader = true; newLine(); break; case Atom::TableHeaderRight: concatenate(""); if (!structs.isEmpty()) structs.top().inTableHeader = false; newLine(); break; case Atom::TableRowLeft: if (!structs.isEmpty()) { structs.top().inTableRow = true; concatenate(""); else concatenate("even\">"); structs.top().odd = !structs.top().odd; } newLine(); break; case Atom::TableRowRight: concatenate(""); if (!structs.isEmpty()) structs.top().inTableRow = false; newLine(); break; case Atom::TableItemLeft: if (!structs.isEmpty()) { structs.top().inTableItem = true; concatenate(""); if (structs.top().inTableHeader) concatenate(" "); } break; case Atom::TableItemRight: if (!structs.isEmpty()) { structs.top().inTableItem = false; if (structs.top().inTableHeader) concatenate(" "); concatenate(""); } newLine(); break; case Atom::TableOfContents: break; case Atom::Target: { QString text = next->string(); text.remove(ws_rx); newLine(); concatenate("\\anchor "); newText += text; lineLength += text.size(); newLine(); } break; case Atom::UnhandledFormat: unhandled(next); break; case Atom::UnknownCommand: unhandled(next); break; default: //next->dump(); break; } prev = next; next = next->next(); } } /*! Pass one looks for topic commands and target and section commands, and maybe other stuff. These are serialized to text files, which are read back in by pass2(). */ void DoxWriter::pass1() { QCommandMap& metaCmdMap = priv->metaCommandMap; if (!metaCmdMap.isEmpty()) { int c; QCommandMap::iterator cmd; if ((cmd = metaCmdMap.find("enum")) != metaCmdMap.end()) { commentType = EnumComment; currentEnum = cmd.value()[0]; if ((c = currentEnum.lastIndexOf("::")) > 0) { currentClass = currentEnum.left(c); currentEnum = currentEnum.right(currentEnum.size()-c-2); qDebug() << "currentEnum =" << currentEnum; qDebug() << "currentClass =" << currentClass; if (enums.contains(currentEnum,currentClass)) { qWarning() << "DoxWriter::pass1():" << "Duplicate enum:" << currentClass << currentEnum; } else enums.insert(currentEnum,currentClass); } } else if ((cmd = metaCmdMap.find("property")) != metaCmdMap.end()) { commentType = PropertyComment; currentClass = cmd.value()[0]; if ((c = currentClass.lastIndexOf("::")) > 0) { currentProperty = currentClass.right(currentClass.size()-c-2); currentClass = currentClass.left(c); qDebug() << "currentProperty =" << currentProperty; qDebug() << "currentClass =" << currentClass; if (properties.contains(currentProperty,currentClass)) { qWarning() << "DoxWriter::pass1():" << "Duplicate property:" << currentClass << currentProperty; } else properties.insert(currentProperty,currentClass); } } else if ((cmd = metaCmdMap.find("variable")) != metaCmdMap.end()) { commentType = VariableComment; currentClass = cmd.value()[0]; if ((c = currentClass.lastIndexOf("::")) > 0) { currentVariable = currentClass.right(currentClass.size()-c-2); currentClass = currentClass.left(c); qDebug() << "currentVariable =" << currentVariable; qDebug() << "currentClass =" << currentClass; if (variables.contains(currentVariable,currentClass)) { qWarning() << "DoxWriter::pass1():" << "Duplicate variable:" << currentClass << currentVariable; } else variables.insert(currentVariable,currentClass); } } } /* */ const Atom* next = priv->text.firstAtom(); while (next != 0) { switch (next->type()) { case Atom::SectionHeadingLeft: { QString text; next = next->next(); while (next) { if (next->type() == Atom::SectionHeadingRight) break; else text += next->string(); next = next->next(); } //text.remove(ws_rx); insertAnchor(text); } break; case Atom::Target: { QString text = next->string(); //text.remove(ws_rx); insertAnchor(text); } default: break; } next = next->next(); } } /*! Output a parsed, tokenized qdoc comment as a doxygen comment in diff format for input to the patch command. */ void DoxWriter::pass2() { if (!conversionRequired()) { qDebug() << "NO CONVERSION - FILE:" << priv->start_loc.fileName() << "START:" << priv->start_loc.lineNo() << "END:" << priv->end_loc.lineNo() - 1; return; } /* Transformation to doxygen required... */ newText = "\n/*! \n"; convertMetaCommands(); convertText(); if (newText[newText.size()-1] == ' ') newText.remove(newText.size()-1,1); newText += " */\n"; qDebug() << "CONVERTED COMMENT - FILE:" << priv->start_loc.fileName() << "START:" << priv->start_loc.lineNo() << "END:" << priv->end_loc.lineNo() - 1; qDebug() << newText; } /*! Unparse the second parameter of a "\l" command. */ const Atom* DoxWriter::link(const Atom* atom) { QString first_text = atom->string(); QString second_text; const QString* value = 0; const Atom* next = atom->next(Atom::FormattingLeft,Atom::LINK_); if (next) { next->dump(); while (1) { next = next->next(); next->dump(); if (next->type() == Atom::FormattingRight) { if (next->string() == Atom::LINK_) break; else { // ignore it. } } else second_text += next->string(); } int i = first_text.indexOf('#'); if (i >= 0) first_text = first_text.right(first_text.size() - i - 1); //newLine(); if ((value = getExternalPage(first_text))) { //qDebug() << "USED AN EXTERNAL PAGE TITLE" << first_text; QString href = ""+first_text+""; concatenate(href); } else if (first_text.startsWith("http:",Qt::CaseInsensitive)) { if (first_text == second_text) { concatenate(first_text); } else { QString href = ""+second_text+""; concatenate(href); } } else if ((value = getPageFile(first_text))) { //qDebug() << "USED A PAGE TITLE" << first_text; QStringList parts = (*value).split('.'); QString ref = "\\ref " + parts[0] + " \"" + second_text + "\""; concatenate(ref); } else if ((value = getGroup(first_text))) { //qDebug() << "USED A GROUP TITLE" << first_text; concatenate("\\ref " + *value + " \"" + second_text + "\""); } else if ((value = getModule(first_text))) { //qDebug() << "USED A MODULE TITLE" << first_text; concatenate("\\ref " + *value + " \"" + second_text + "\""); } else if ((value = getExamplePath(first_text))) { //qDebug() << "USED AN EXAMPLE TITLE" << first_text; first_text.remove(ws_rx); QString ref = "\\ref " + first_text + " \"" + second_text + "\""; concatenate(ref); } else if ((value = getFile(first_text))) { //qDebug() << "USED A FILE TITLE" << first_text; // I think this command is no longer available. first_text.remove(ws_rx); QString ref = "\\ref " + first_text + " \"" + second_text + "\""; concatenate(ref); } else if ((value = getHeaderFile(first_text))) { //qDebug() << "USED A HEADER FILE TITLE" << first_text; first_text.remove(ws_rx); QString ref = "\\ref " + first_text + " \"" + second_text + "\""; concatenate(ref); } else if (isAnchor(first_text)) { //qDebug() << "USED AN ANCHOR" << first_text; first_text.remove(ws_rx); QString ref = "\\ref " + first_text + " \"" + second_text + "\""; concatenate(ref); } else if ((value = getPageTitle(first_text))) { //qDebug() << "USED AN INVERSE PAGE TITLE" << first_text; QStringList parts = first_text.split('.'); QString ref = "\\ref " + parts[0] + " \"" + second_text + "\""; concatenate(ref); } else if ((value = getExampleTitle(first_text))) { //qDebug() << "USED AN INVERSE EXAMPLE TITLE" << first_text; QString title = *value; title.remove(ws_rx); QString ref = "\\ref " + title + " \"" + second_text + "\""; concatenate(ref); } else if ((value = getGroupTitle(first_text))) { //qDebug() << "USED AN INVERSE GROUP TITLE" << first_text; concatenate("\\ref " + first_text + " \"" + second_text + "\""); } else if ((value = getModuleTitle(first_text))) { //qDebug() << "USED AN INVERSE MODULE TITLE" << first_text; concatenate("\\ref " + first_text + " \"" + second_text + "\""); } else if ((value = getFileTitle(first_text))) { qDebug() << "USED AN INVERSE FILE TITLE" << first_text; } else if ((value = getHeaderFileTitle(first_text))) { qDebug() << "USED AN INVERSE HEADER FILE TITLE" << first_text; } else if ((first_text.indexOf("::") >= 0) || (first_text.indexOf("()") >= 0) || (first_text[0] == 'Q')) { //qDebug() << "AUTO-LINKABLE" << first_text; if (first_text == second_text) concatenate(first_text); else { QString link = first_text + " " + second_text; concatenate("\\link " + link + "\\endlink"); } } else { QString link; QStringList propertyClasses; QStringList variableClasses; QStringList enumClasses; bool p = isProperty(first_text,propertyClasses); bool v = isVariable(first_text,variableClasses); bool e = isEnum(first_text,enumClasses); if (e) { if (enumClasses.size() == 1) link = enumClasses[0]; else if (enumClasses.contains(currentClass)) link = currentClass; else { QString msg = "Unqualified enum name: " + first_text; QString details = "Classes: " + enumClasses.join(", "); priv->start_loc.error(msg,details); } if (!link.isEmpty()) qDebug() << "FOUND ENUM" << link << first_text; } else if (p && v) { if (propertyClasses.size() == 1) { if (variableClasses.size() == 1) { if (propertyClasses[0] == variableClasses[0]) link = propertyClasses[0]; } } if (link.isEmpty()) { if (propertyClasses.contains(currentClass) || variableClasses.contains(currentClass)) link = currentClass; else { propertyClasses += variableClasses; QString msg = "Unqualified property or variable name: " + first_text; QString details = "Classes: " + propertyClasses.join(", "); priv->start_loc.error(msg,details); } } } else if (p) { if (propertyClasses.size() == 1) link = propertyClasses[0]; else if (propertyClasses.contains(currentClass)) link = currentClass; else { QString msg = "Unqualified property name: " + first_text; QString details = "Classes: " + propertyClasses.join(", "); priv->start_loc.error(msg,details); } } else if (v) { if (variableClasses.size() == 1) link = variableClasses[0]; else if (variableClasses.contains(currentClass)) link = currentClass; else { QString msg = "Unqualified variable name: " + first_text; QString details = "Classes: " + variableClasses.join(", "); priv->start_loc.error(msg,details); } } else { qDebug() << "NOT AUTO-LINKABLE" << first_text; QString s = first_text + " " + second_text; concatenate("\\link " + s + "\\endlink"); } if (!link.isEmpty()) { link += "::" + first_text + " " + second_text; concatenate("\\link " + link + "\\endlink"); } } } else qDebug() << "LINK with no second parameter!!!!"; return next? next : atom; } /*! If the current line length is 0, the current line is indented according to the context. */ void DoxWriter::indentLine() { if (lineLength == 0) { newText += DOXYGEN_INDENT_STRING; lineLength = DOXYGEN_INDENT; if (!structs.isEmpty()) { for (int i=1; i maxLineLength) newLine(); indentLine(); newText += text; lineLength += text.size(); } static bool punctuation(QChar c) { switch (c.toAscii()) { case '.': case ',': case ':': case ';': case '/': case '+': case '-': case '?': case '!': case '\"': return true; default: break; } return false; } /*! Concatenate the \a text string to the doxygen text, doing line wrapping where necessary. */ void DoxWriter::wrap(QString text) { int from = 0; int to = -1; if ((lineLength == 0) || (lineLength >= maxLineLength)) { if (!text.isEmpty() && (text[0] == ' ')) text = text.right(text.size() - 1); } indentLine(); while (text.size()) { int avail = maxLineLength - lineLength; from = text.indexOf(' ',from); if (from >= 0) { if (from < avail) to = from++; else if (from == 1 && punctuation(text[0])) to = from++; else { if (to >= 0) { newText += text.left(to+1); lineLength += to + 1; text = text.right(text.size() - to - 1); } else { newLine(); indentLine(); newText += text.left(from+1); lineLength += from + 1; text = text.right(text.size() - from - 1); } from = 0; to = -1; if (text.size() && (lineLength > maxLineLength)) { newLine(); indentLine(); } } } else break; } if (text.size()) { if (lineLength >= maxLineLength) { newLine(); indentLine(); } newText += text; lineLength += text.size(); } } /*! This will output something, but it depends on what the \a atom string and the \a next atom string are. */ void DoxWriter::formattingLeft(const Atom* atom, const Atom* next) { if (atom->string() == "parameter") { concatenate("\\a "); return; } else if (atom->string() == "underline") { concatenate(""); return; } else if (atom->string() == "superscript") { concatenate(""); return; } else if (atom->string() == "subscript") { concatenate(""); return; } int ws = -1; if (next) ws = next->string().indexOf(ws_rx); if (atom->string() == "bold") { if (ws < 0) concatenate("\\b "); else concatenate(""); } else if (atom->string() == "italic") { if (ws < 0) concatenate("\\e "); else concatenate(""); } else if (atom->string() == "teletype") { if (ws < 0) concatenate("\\c "); else concatenate(""); } else qDebug() << "UNHANDLED FormattingLeft: " << atom->string(); } /*! This will output something, but it depends on what the \a atom string and the \a prev atom string are. */ void DoxWriter::formattingRight(const Atom* atom, const Atom* prev) { if (atom->string() == "parameter") return; else if (atom->string() == "underline") { concatenate(""); return; } else if (atom->string() == "superscript") { concatenate(""); return; } else if (atom->string() == "subscript") { concatenate(""); return; } int ws = -1; if (prev) ws = prev->string().indexOf(ws_rx); if (ws < 0) return; if (atom->string() == "bold") concatenate(""); else if (atom->string() == "italic") concatenate(""); else if (atom->string() == "teletype") concatenate(""); else qDebug() << "UNHANDLED FormattingRight: " << atom->string(); } /*! Output a \c or a .... */ void DoxWriter::tt(const Atom* atom) { if (atom->string().indexOf(ws_rx) < 0) { concatenate("\\c "); concatenate(atom->string()); } else { concatenate(""); concatenate(atom->string()); concatenate(""); } } /*! */ void DoxWriter::formatIf(const Atom* atom) { if (atom->string() == "HTML") { newLine(); concatenate("\\htmlonly"); newLine(); } } /*! */ void DoxWriter::formatEndif() { newLine(); concatenate("\\endhtmlonly"); newLine(); } /*! */ void DoxWriter::formatElse() { // nothing. } /*! Pass 1: Construct a section identifier and insert it into the anchor set. Pass 2: Convert section1, section2, and section3 commands to section, subsection, and subsubsection respectively. Warn if a section command higher than 3 is seen. */ const Atom* DoxWriter::sectionHeading(const Atom* atom) { QString heading_level = atom->string(); QString heading_text; const Atom* next = atom->next(); while (next) { next->dump(); if (next->type() == Atom::SectionHeadingRight) { if (next->string() == heading_level) break; else { qDebug() << "WRONG SectionHeading number!!!!"; } } else heading_text += next->string(); next = next->next(); } QString heading_identifier = heading_text; heading_identifier.remove(ws_rx); newLine(); if (heading_level == "1") heading_level = "\\section "; else if (heading_level == "2") heading_level = "\\subsection "; else if (heading_level == "3") heading_level = "\\subsubsection "; else if (heading_level == "4") { heading_level = "\\subsubsection "; qDebug() << "WARNING section4 converted to \\subsubsection"; } else { heading_level = "\\subsubsection "; qDebug() << "WARNING section5 converted to \\subsubsection"; } concatenate(heading_level); newText += heading_identifier + " "; lineLength += heading_identifier.size() + 1; newText += heading_text; lineLength += heading_text.size(); newLine(); return next? next : atom; } /*! Report an unhandled atom. */ void DoxWriter::unhandled(const Atom* atom) { qDebug() << "UNHANDLED ATOM"; atom->dump(); } /*! Output a code/endcode block. */ void DoxWriter::code(const Atom* atom) { newLine(); concatenate("\\code"); writeCode(atom->string()); concatenate("\\endcode"); newLine(); } /*! Output a code/endcode block depending on the CodeQuote Command and CodeQuoteArgument parameters. */ const Atom* DoxWriter::codeQuoteCommand(const Atom* atom) { QString command = atom->string(); atom = atom->next(); concatenate("\\code"); if (command == "codeline") { newLine(); concatenate(atom->string()); newLine(); } else if (command == "dots") { newLine(); concatenate(atom->string()); newLine(); } else { writeCode(atom->string()); } concatenate("\\endcode"); return atom; } /*! Appends a block of code to the comment. */ void DoxWriter::writeCode(QString text) { int cr_count = text.count('\n') - 1; if (cr_count >= 0) { int last_cr = text.lastIndexOf('\n'); newText += text.left(last_cr); lineCount += cr_count; } else newText += text; newLine(); } /*! Inserts \a text into the anchor set. This function is called during doxygen pass 1. */ void DoxWriter::insertAnchor(const QString& text) { anchors.insert(text); } /*! Returns true if \a text identifies an anchor, section, subsection, subsubsection, or page. */ bool DoxWriter::isAnchor(const QString& text) { return anchors.contains(text); } /*! Write the set of anchors to a file, one per line. */ void DoxWriter::writeAnchors() { QFile file("anchors.txt"); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qWarning("Unable to open anchors.txt for writing."); return; } QTextStream out(&file); QSet::const_iterator i = anchors.constBegin(); while (i != anchors.constEnd()) { out << *i << "\n"; ++i; } file.close(); } /*! Read the set of anchors from the anchors file, one per line, and insert each one into the anchor set. */ void DoxWriter::readAnchors() { QFile file("anchors.txt"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning("Unable to open anchors.txt for reading."); return; } QTextStream in(&file); while (!in.atEnd()) { QString line = in.readLine(); anchors.insert(line); } file.close(); #if 0 QSet::const_iterator i = anchors.constBegin(); while (i != anchors.constEnd()) { qDebug() << *i; ++i; } #endif } /*! Inserts \a title into one of the title maps. \a title is mapped to the \a node name. This function is called during doxygen pass 1. */ void DoxWriter::insertTitle(FakeNode* node, const QString& title) { switch (node->subType()) { case FakeNode::Example: if (exampleTitles.contains(title)) { qWarning() << "DoxWriter::insertTitle():" << "Duplicate example title:" << title; } else { exampleTitles[title] = node->name(); exampleTitlesInverse[node->name()] = title; } break; case FakeNode::HeaderFile: if (headerFileTitles.contains(title)) { qWarning() << "DoxWriter::insertTitle():" << "Duplicate header file title:" << title; } else { headerFileTitles[title] = node->name(); headerFileTitlesInverse[node->name()] = title; } break; case FakeNode::File: if (fileTitles.contains(title)) { qWarning() << "DoxWriter::insertTitle():" << "Duplicate file title:" << title; } else { fileTitles[title] = node->name(); fileTitlesInverse[node->name()] = title; } break; case FakeNode::Group: if (groupTitles.contains(title)) { qWarning() << "DoxWriter::insertTitle():" << "Duplicate group title:" << title; } else { groupTitles[title] = node->name(); groupTitlesInverse[node->name()] = title; } break; case FakeNode::Module: if (moduleTitles.contains(title)) { qWarning() << "DoxWriter::insertTitle():" << "Duplicate module title:" << title; } else { moduleTitles[title] = node->name(); moduleTitlesInverse[node->name()] = title; } break; case FakeNode::Page: if (pageTitles.contains(title)) { qWarning() << "DoxWriter::insertTitle():" << "Duplicate page title:" << title; } else { pageTitles[title] = node->name(); pageTitlesInverse[node->name()] = title; } break; case FakeNode::ExternalPage: if (externalPageTitles.contains(title)) { qWarning() << "DoxWriter::insertTitle():" << "Duplicate external page title:" << title; } else { externalPageTitles[title] = node->name(); externalPageTitlesInverse[node->name()] = title; } break; default: break; } } /*! */ const QString* DoxWriter::getPageFile(const QString& title) { QStringMapEntry entry = pageTitles.find(title); return (entry == pageTitles.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getExamplePath(const QString& title) { QStringMapEntry entry = exampleTitles.find(title); return (entry == exampleTitles.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getFile(const QString& title) { QStringMapEntry entry = fileTitles.find(title); return (entry == fileTitles.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getHeaderFile(const QString& title) { QStringMapEntry entry = headerFileTitles.find(title); return (entry == headerFileTitles.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getGroup(const QString& title) { QStringMapEntry entry = groupTitles.find(title); return (entry == groupTitles.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getModule(const QString& title) { QStringMapEntry entry = moduleTitles.find(title); return (entry == moduleTitles.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getExternalPage(const QString& title) { QStringMapEntry entry = externalPageTitles.find(title); return (entry == externalPageTitles.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getPageTitle(const QString& text) { QStringMapEntry entry = pageTitlesInverse.find(text); return (entry == pageTitlesInverse.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getExampleTitle(const QString& text) { QStringMapEntry entry = exampleTitlesInverse.find(text); return (entry == exampleTitlesInverse.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getFileTitle(const QString& text) { QStringMapEntry entry = fileTitlesInverse.find(text); return (entry == fileTitlesInverse.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getHeaderFileTitle(const QString& text) { QStringMapEntry entry = headerFileTitlesInverse.find(text); return (entry == headerFileTitlesInverse.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getGroupTitle(const QString& text) { QStringMapEntry entry = groupTitlesInverse.find(text); return (entry == groupTitlesInverse.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getModuleTitle(const QString& text) { QStringMapEntry entry = moduleTitlesInverse.find(text); return (entry == moduleTitlesInverse.end()) ? 0 : &entry.value(); } /*! */ const QString* DoxWriter::getExternalPageTitle(const QString& text) { QStringMapEntry entry = externalPageTitlesInverse.find(text); return (entry == externalPageTitlesInverse.end()) ? 0 : &entry.value(); } /*! Serialize \a map to file \a name. */ void DoxWriter::writeMap(const QStringMap& map, const QString& name) { QFile file(name); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qWarning() << "Unable to open" << name << "for writing."; return; } QTextStream out(&file); QStringMap::const_iterator i = map.constBegin(); while (i != map.constEnd()) { out << i.key() << "\n"; out << i.value() << "\n"; ++i; } file.close(); } /*! Read file \a name into the \a map. */ void DoxWriter::readMap(QStringMap& map, QStringMap& inverseMap, const QString& name) { QFile file(name); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning() << "Unable to open" << name << "for reading."; return; } QTextStream in(&file); while (!in.atEnd()) { QString title = in.readLine(); QString value = in.readLine(); map[title] = value; inverseMap[value] = title; } file.close(); } /*! Write the sets of titles to text files, one per line. */ void DoxWriter::writeTitles() { if (!pageTitles.isEmpty()) writeMap(pageTitles,"pagetitles.txt"); if (!fileTitles.isEmpty()) writeMap(fileTitles,"filetitles.txt"); if (!headerFileTitles.isEmpty()) writeMap(headerFileTitles,"headerfiletitles.txt"); if (!exampleTitles.isEmpty()) writeMap(exampleTitles,"exampletitles.txt"); if (!moduleTitles.isEmpty()) writeMap(moduleTitles,"moduletitles.txt"); if (!groupTitles.isEmpty()) writeMap(groupTitles,"grouptitles.txt"); if (!externalPageTitles.isEmpty()) writeMap(externalPageTitles,"externalpagetitles.txt"); } /*! Read the sets of titles from the titles files, one per line, and insert each one into the appropriate title set. */ void DoxWriter::readTitles() { readMap(pageTitles,pageTitlesInverse,"pagetitles.txt"); readMap(fileTitles,fileTitlesInverse,"filetitles.txt"); readMap(headerFileTitles,headerFileTitlesInverse,"headerfiletitles.txt"); readMap(exampleTitles,exampleTitlesInverse,"exampletitles.txt"); readMap(moduleTitles,moduleTitlesInverse,"moduletitles.txt"); readMap(groupTitles,groupTitlesInverse,"grouptitles.txt"); readMap(externalPageTitles, externalPageTitlesInverse, "externalpagetitles.txt"); } /*! Serialize \a map to file \a name. */ void DoxWriter::writeMultiMap(const QStringMultiMap& map, const QString& name) { QFile file(name); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qWarning() << "Unable to open" << name << "for writing."; return; } QTextStream out(&file); QStringMultiMap::const_iterator i = map.constBegin(); while (i != map.constEnd()) { out << i.key() << "\n"; out << i.value() << "\n"; ++i; } file.close(); } /*! Write the4 property names and variable names to text files. */ void DoxWriter::writeMembers() { if (!variables.isEmpty()) writeMultiMap(variables,"variables.txt"); if (!properties.isEmpty()) writeMultiMap(properties,"properties.txt"); if (!enums.isEmpty()) writeMultiMap(enums,"enums.txt"); } /*! Read file \a name into the \a map. */ void DoxWriter::readMultiMap(QStringMultiMap& map, const QString& name) { QFile file(name); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning() << "Unable to open" << name << "for reading."; return; } QTextStream in(&file); while (!in.atEnd()) { QString member = in.readLine(); QString className = in.readLine(); map.insert(member,className); } file.close(); } /*! Read the property names and variable names from the test files. */ void DoxWriter::readMembers() { readMultiMap(variables,"variables.txt"); readMultiMap(properties,"properties.txt"); readMultiMap(enums,"enums.txt"); } /*! Return true if \a name is a property. Loads \a classes with the names of all the classes in which \a name is a property. */ bool DoxWriter::isProperty(const QString& name, QStringList& classes) { classes = properties.values(name); return !classes.isEmpty(); } /*! Return true if \a name is a variable. Loads \a classes with the names of all the classes in which \a name is a variable. */ bool DoxWriter::isVariable(const QString& name, QStringList& classes) { classes = variables.values(name); return !classes.isEmpty(); } /*! Return true if \a name is an enum type. Loads \a classes with the names of all the classes in which \a name is an enum type. */ bool DoxWriter::isEnum(const QString& name, QStringList& classes) { classes = enums.values(name); return !classes.isEmpty(); } #endif QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/doc.h000066400000000000000000000241531215241066400176670ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* doc.h */ #ifndef DOC_H #define DOC_H #include #include #include "location.h" QT_BEGIN_NAMESPACE class Atom; class CodeMarker; class Config; class DocPrivate; class Quoter; class Text; class FakeNode; typedef QMap QCommandMap; typedef QMap QStringMap; typedef QStringMap::const_iterator QStringMapEntry; typedef QMultiMap QStringMultiMap; class Doc { public: // the order is important enum SectioningUnit { Book = -2, Part, Chapter, Section1, Section2, Section3, Section4 }; Doc() : priv(0) {} Doc(const Location &start_loc, const Location &end_loc, const QString &source, const QSet &metaCommandSet); Doc(const Doc &doc); ~Doc(); Doc& operator=( const Doc& doc ); void renameParameters(const QStringList &oldNames, const QStringList &newNames); void simplifyEnumDoc(); void setBody(const Text &body); const Location &location() const; bool isEmpty() const; const QString& source() const; const Text& body() const; Text briefText() const; Text trimmedBriefText(const QString &className) const; Text legaleseText() const; const QString& baseName() const; SectioningUnit granularity() const; const QSet ¶meterNames() const; const QStringList &enumItemNames() const; const QStringList &omitEnumItemNames() const; const QSet &metaCommandsUsed() const; QStringList metaCommandArgs( const QString& metaCommand ) const; const QList &alsoList() const; bool hasTableOfContents() const; bool hasKeywords() const; bool hasTargets() const; const QList &tableOfContents() const; const QList &tableOfContentsLevels() const; const QList &keywords() const; const QList &targets() const; const QStringMap &metaTagMap() const; static void initialize( const Config &config ); static void terminate(); static QString alias( const QString &english ); static void trimCStyleComment( Location& location, QString& str ); static CodeMarker *quoteFromFile(const Location &location, Quoter "er, const QString &fileName); static QString canonicalTitle(const QString &title); private: void detach(); DocPrivate *priv; }; #ifdef QDOC2DOX class DoxWriter { public: DoxWriter(const QString& source, DocPrivate* docPrivate) : commentType(OtherComment), lineLength(0), lineCount(0), priv(docPrivate), oldText(source) {} ~DoxWriter() {} void pass1(); void pass2(); static void setDoxPass(int pass); static bool isDoxPass(int pass); static bool isDoxPass(); static void insertTitle(FakeNode* node, const QString& title); static void writeTitles(); static void readTitles(); static void writeMembers(); static void readMembers(); static void writeAnchors(); static void readAnchors(); private: void indentLine(); void newLine(); void concatenate(QString text); void wrap(QString text); bool conversionRequired() const; void convertMetaCommands(); void convertText(); const Atom* link(const Atom* atom); void formattingLeft(const Atom* atom, const Atom* next); void formattingRight(const Atom* atom, const Atom* prev); void tt(const Atom* atom); void formatIf(const Atom* atom); void formatEndif(); void formatElse(); const Atom* sectionHeading(const Atom* atom); void unhandled(const Atom* atom); void code(const Atom* atom); const Atom* codeQuoteCommand(const Atom* atom); void writeCode(QString text); void writeCommand(QCommandMap::const_iterator cmd); static void insertAnchor(const QString& text); static bool isAnchor(const QString& text); static const QString* getPageFile(const QString& title); static const QString* getFile(const QString& title); static const QString* getExamplePath(const QString& title); static const QString* getHeaderFile(const QString& title); static const QString* getGroup(const QString& title); static const QString* getModule(const QString& title); static const QString* getExternalPage(const QString& title); static const QString* getPageTitle(const QString& text); static const QString* getFileTitle(const QString& text); static const QString* getExampleTitle(const QString& text); static const QString* getHeaderFileTitle(const QString& text); static const QString* getGroupTitle(const QString& text); static const QString* getModuleTitle(const QString& text); static const QString* getExternalPageTitle(const QString& text); static bool isProperty(const QString& title, QStringList& classes); static bool isVariable(const QString& title, QStringList& classes); static bool isEnum(const QString& title, QStringList& classes); private: static void writeMap(const QStringMap& map, const QString& name); static void readMap(QStringMap& map, QStringMap& inverseMap, const QString& name); static void writeMultiMap(const QStringMultiMap& map, const QString& name); static void readMultiMap(QStringMultiMap& map, const QString& name); public: // VS 6, SunCC need this to be public enum StructType { BulletList, NumericList, ValueList, Table }; private: struct StructDesc { StructType structType; int count; bool nested; bool inTableHeader; bool inTableRow; bool inTableItem; bool odd; StructDesc() : structType(BulletList), count(0), nested(false), inTableHeader(false), inTableRow(false), inTableItem(false), odd(true) { } StructDesc(StructType t, bool n) : structType(t), count(0), nested(n), inTableHeader(false), inTableRow(false), inTableItem(false), odd(true) { } }; typedef QStack StructStack; enum CommentType { ClassComment, EnumComment, ExampleComment, FnComment, GroupComment, HeaderFileComment, MacroComment, ModuleComment, PageComment, PropertyComment, ServiceComment, TypedefComment, VariableComment, OtherComment }; private: CommentType commentType; int lineLength; int lineCount; DocPrivate* priv; QString oldText; QString newText; StructStack structs; QString currentPage; QString currentFn; QString currentTitle; QString currentEnum; QString currentProperty; QString currentVariable; QString currentExample; QString currentGroup; QString currentModule; QString currentMacro; QString currentService; QString currentTypedef; QString currentHeaderFile; static QString currentClass; static int doxPass; static QSet anchors; static QStringMap exampleTitles; static QStringMap headerFileTitles; static QStringMap fileTitles; static QStringMap groupTitles; static QStringMap moduleTitles; static QStringMap pageTitles; static QStringMap externalPageTitles; static QStringMap exampleTitlesInverse; static QStringMap headerFileTitlesInverse; static QStringMap fileTitlesInverse; static QStringMap groupTitlesInverse; static QStringMap moduleTitlesInverse; static QStringMap pageTitlesInverse; static QStringMap externalPageTitlesInverse; static QStringMultiMap variables; static QStringMultiMap properties; static QStringMultiMap enums; }; #endif QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/documentation.pri000066400000000000000000000003301215241066400223250ustar00rootroot00000000000000# NOTE: THIS FILE IS SHARED BY qdoc3.pro AND projects.pro # # So while changing this file, please make sure to that your changes # work in root qt soure dir with (n)make docs and for building with qdoc # libqxt-0.6.2/tools/3rdparty/qdoc3/editdistance.cpp000066400000000000000000000063711215241066400221170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* editdistance.cpp */ #include "editdistance.h" QT_BEGIN_NAMESPACE int editDistance( const QString& s, const QString& t ) { #define D( i, j ) d[(i) * n + (j)] int i; int j; int m = s.length() + 1; int n = t.length() + 1; int *d = new int[m * n]; int result; for ( i = 0; i < m; i++ ) D( i, 0 ) = i; for ( j = 0; j < n; j++ ) D( 0, j ) = j; for ( i = 1; i < m; i++ ) { for ( j = 1; j < n; j++ ) { if ( s[i - 1] == t[j - 1] ) { D( i, j ) = D( i - 1, j - 1 ); } else { int x = D( i - 1, j ); int y = D( i - 1, j - 1 ); int z = D( i, j - 1 ); D( i, j ) = 1 + qMin( qMin(x, y), z ); } } } result = D( m - 1, n - 1 ); delete[] d; return result; #undef D } QString nearestName( const QString& actual, const QSet& candidates ) { int deltaBest = 10000; int numBest = 0; QString best; QSet::ConstIterator c = candidates.begin(); while ( c != candidates.end() ) { if ( (*c)[0] == actual[0] ) { int delta = editDistance( actual, *c ); if ( delta < deltaBest ) { deltaBest = delta; numBest = 1; best = *c; } else if ( delta == deltaBest ) { numBest++; } } ++c; } if ( numBest == 1 && deltaBest <= 2 && actual.length() + best.length() >= 5 ) { return best; } else { return ""; } } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/editdistance.h000066400000000000000000000043041215241066400215560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* editdistance.h */ #ifndef EDITDISTANCE_H #define EDITDISTANCE_H #include #include QT_BEGIN_NAMESPACE int editDistance( const QString& s, const QString& t ); QString nearestName( const QString& actual, const QSet& candidates ); QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/generator.cpp000066400000000000000000001063501215241066400214430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* generator.cpp */ #include #include "codemarker.h" #include "config.h" #include "doc.h" #include "editdistance.h" #include "generator.h" #include "node.h" #include "openedlist.h" #include "quoter.h" #include "separator.h" #include "tokenizer.h" QT_BEGIN_NAMESPACE QList Generator::generators; QMap > Generator::fmtLeftMaps; QMap > Generator::fmtRightMaps; QMap Generator::imgFileExts; QSet Generator::outputFormats; QStringList Generator::imageFiles; QStringList Generator::imageDirs; QString Generator::outDir; QString Generator::project; static Text stockLink(const QString &target) { return Text() << Atom(Atom::Link, target) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << target << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); } Generator::Generator() : amp("&"), lt("<"), gt(">"), quot("""), tag("]*>") { generators.prepend(this); } Generator::~Generator() { generators.removeAll(this); } void Generator::initializeGenerator(const Config & /* config */) { } void Generator::terminateGenerator() { } void Generator::initialize(const Config &config) { outputFormats = config.getStringSet(CONFIG_OUTPUTFORMATS); if (!outputFormats.isEmpty()) { outDir = config.getString(CONFIG_OUTPUTDIR); if (outDir.isEmpty()) config.lastLocation().fatal(tr("No output directory specified in configuration file")); QDir dirInfo; if (dirInfo.exists(outDir)) { if (!Config::removeDirContents(outDir)) config.lastLocation().error(tr("Cannot empty output directory '%1'").arg(outDir)); } else { if (!dirInfo.mkpath(outDir)) config.lastLocation().fatal(tr("Cannot create output directory '%1'").arg(outDir)); } if (!dirInfo.mkdir(outDir + "/images")) config.lastLocation().fatal(tr("Cannot create output directory '%1'") .arg(outDir + "/images")); } imageFiles = config.getStringList(CONFIG_IMAGES); imageDirs = config.getStringList(CONFIG_IMAGEDIRS); QString imagesDotFileExtensions = CONFIG_IMAGES + Config::dot + CONFIG_FILEEXTENSIONS; QSet formats = config.subVars(imagesDotFileExtensions); QSet::ConstIterator f = formats.begin(); while (f != formats.end()) { imgFileExts[*f] = config.getStringList(imagesDotFileExtensions + Config::dot + *f); ++f; } QList::ConstIterator g = generators.begin(); while (g != generators.end()) { if (outputFormats.contains((*g)->format())) { (*g)->initializeGenerator(config); QStringList extraImages = config.getStringList(CONFIG_EXTRAIMAGES + Config::dot + (*g)->format()); QStringList::ConstIterator e = extraImages.begin(); while (e != extraImages.end()) { QString userFriendlyFilePath; QString filePath = Config::findFile(config.lastLocation(), imageFiles, imageDirs, *e, imgFileExts[(*g)->format()], userFriendlyFilePath); if (!filePath.isEmpty()) Config::copyFile(config.lastLocation(), filePath, userFriendlyFilePath, (*g)->outputDir() + "/images"); ++e; } } ++g; } QRegExp secondParamAndAbove("[\2-\7]"); QSet formattingNames = config.subVars(CONFIG_FORMATTING); QSet::ConstIterator n = formattingNames.begin(); while (n != formattingNames.end()) { QString formattingDotName = CONFIG_FORMATTING + Config::dot + *n; QSet formats = config.subVars(formattingDotName); QSet::ConstIterator f = formats.begin(); while (f != formats.end()) { QString def = config.getString(formattingDotName + Config::dot + *f); if (!def.isEmpty()) { int numParams = Config::numParams(def); int numOccs = def.count("\1"); if (numParams != 1) { config.lastLocation().warning(tr("Formatting '%1' must have exactly one" " parameter (found %2)") .arg(*n).arg(numParams)); } else if (numOccs > 1) { config.lastLocation().fatal(tr("Formatting '%1' must contain exactly one" " occurrence of '\\1' (found %2)") .arg(*n).arg(numOccs)); } else { int paramPos = def.indexOf("\1"); fmtLeftMaps[*f].insert(*n, def.left(paramPos)); fmtRightMaps[*f].insert(*n, def.mid(paramPos + 1)); } } ++f; } ++n; } project = config.getString(CONFIG_PROJECT); } void Generator::terminate() { QList::ConstIterator g = generators.begin(); while (g != generators.end()) { if (outputFormats.contains((*g)->format())) (*g)->terminateGenerator(); ++g; } fmtLeftMaps.clear(); fmtRightMaps.clear(); imgFileExts.clear(); imageFiles.clear(); imageDirs.clear(); outDir = ""; } Generator *Generator::generatorForFormat(const QString& format) { QList::ConstIterator g = generators.begin(); while (g != generators.end()) { if ((*g)->format() == format) return *g; ++g; } return 0; } void Generator::startText(const Node * /* relative */, CodeMarker * /* marker */) { } void Generator::endText(const Node * /* relative */, CodeMarker * /* marker */) { } int Generator::generateAtom(const Atom * /* atom */, const Node * /* relative */, CodeMarker * /* marker */) { return 0; } void Generator::generateClassLikeNode(const InnerNode * /* classe */, CodeMarker * /* marker */) { } void Generator::generateFakeNode(const FakeNode * /* fake */, CodeMarker * /* marker */) { } void Generator::generateText(const Text& text, const Node *relative, CodeMarker *marker) { if (text.firstAtom() != 0) { int numAtoms = 0; startText(relative, marker); generateAtomList(text.firstAtom(), relative, marker, true, numAtoms); endText(relative, marker); } } #ifdef QDOC_QML void Generator::generateQmlText(const Text& text, const Node *relative, CodeMarker *marker) { if (text.firstAtom() != 0) { startText(relative, marker); const Atom *atom = text.firstAtom(); while (atom) { if (atom->type() != Atom::QmlText) atom = atom->next(); else { atom = atom->next(); while (atom && (atom->type() != Atom::EndQmlText)) { int n = 1 + generateAtom(atom, relative, marker); while (n-- > 0) atom = atom->next(); } } } endText(relative, marker); } } #endif void Generator::generateBody(const Node *node, CodeMarker *marker) { bool quiet = false; if (node->type() == Node::Function) { #if 0 const FunctionNode *func = (const FunctionNode *) node; if (func->isOverload() && func->metaness() != FunctionNode::Ctor) generateOverload(node, marker); #endif } else if (node->type() == Node::Fake) { const FakeNode *fake = static_cast(node); if (fake->subType() == FakeNode::Example) generateExampleFiles(fake, marker); else if (fake->subType() == FakeNode::File) quiet = true; } if (node->doc().isEmpty()) { if (!quiet) // ### might be unnecessary node->location().warning(tr("No documentation for '%1'") .arg(marker->plainFullName(node))); } else { generateText(node->doc().body(), node, marker); if (node->type() == Node::Enum) { const EnumNode *enume = (const EnumNode *) node; QSet definedItems; QList::ConstIterator it = enume->items().begin(); while (it != enume->items().end()) { definedItems.insert((*it).name()); ++it; } QSet documentedItems = enume->doc().enumItemNames().toSet(); QSet allItems = definedItems + documentedItems; if (allItems.count() > definedItems.count() || allItems.count() > documentedItems.count()) { QSet::ConstIterator a = allItems.begin(); while (a != allItems.end()) { if (!definedItems.contains(*a)) { QString details; QString best = nearestName(*a, definedItems); if (!best.isEmpty() && !documentedItems.contains(best)) details = tr("Maybe you meant '%1'?").arg(best); node->doc().location().warning( tr("No such enum item '%1' in %2").arg(*a).arg(marker->plainFullName(node)), details); } else if (!documentedItems.contains(*a)) { node->doc().location().warning( tr("Undocumented enum item '%1' in %2").arg(*a).arg(marker->plainFullName(node))); } ++a; } } } else if (node->type() == Node::Function) { const FunctionNode *func = static_cast(node); QSet definedParams; QList::ConstIterator p = func->parameters().begin(); while (p != func->parameters().end()) { if ((*p).name().isEmpty() && (*p).leftType() != QLatin1String("...") && func->name() != QLatin1String("operator++") && func->name() != QLatin1String("operator--")) { node->doc().location().warning(tr("Missing parameter name")); } else { definedParams.insert((*p).name()); } ++p; } QSet documentedParams = func->doc().parameterNames(); QSet allParams = definedParams + documentedParams; if (allParams.count() > definedParams.count() || allParams.count() > documentedParams.count()) { QSet::ConstIterator a = allParams.begin(); while (a != allParams.end()) { if (!definedParams.contains(*a)) { QString details; QString best = nearestName(*a, definedParams); if (!best.isEmpty()) details = tr("Maybe you meant '%1'?").arg(best); node->doc().location().warning( tr("No such parameter '%1' in %2").arg(*a).arg(marker->plainFullName(node)), details); } else if (!(*a).isEmpty() && !documentedParams.contains(*a)) { bool needWarning = (func->status() > Node::Obsolete); if (func->overloadNumber() > 1) { FunctionNode *primaryFunc = func->parent()->findFunctionNode(func->name()); if (primaryFunc) { foreach (const Parameter ¶m, primaryFunc->parameters()) { if (param.name() == *a) { needWarning = false; break; } } } } if (needWarning) node->doc().location().warning( tr("Undocumented parameter '%1' in %2").arg(*a).arg(marker->plainFullName(node))); } ++a; } } /* Something like this return value check should be implemented at some point. */ if (func->status() > Node::Obsolete && func->returnType() == "bool" && func->reimplementedFrom() == 0 && !func->isOverload()) { QString body = func->doc().body().toString(); if (!body.contains("return", Qt::CaseInsensitive)) node->doc().location().warning(tr("Undocumented return value")); } if (func->reimplementedFrom() != 0) generateReimplementedFrom(func, marker); } } if (node->type() == Node::Fake) { const FakeNode *fake = static_cast(node); if (fake->subType() == FakeNode::File) { Text text; Quoter quoter; Doc::quoteFromFile(fake->doc().location(), quoter, fake->name()); QString code = quoter.quoteTo(fake->location(), "", ""); text << Atom(Atom::Code, code); generateText(text, fake, marker); } } } void Generator::generateAlsoList(const Node *node, CodeMarker *marker) { QList alsoList = node->doc().alsoList(); supplementAlsoList(node, alsoList); if (!alsoList.isEmpty()) { Text text; text << Atom::ParaLeft << "See also "; for (int i = 0; i < alsoList.size(); ++i) text << alsoList.at(i) << separator(i, alsoList.size()); text << Atom::ParaRight; generateText(text, node, marker); } } void Generator::generateInherits(const ClassNode *classe, CodeMarker *marker) { QList::ConstIterator r; int index; if (!classe->baseClasses().isEmpty()) { Text text; text << Atom::ParaLeft << "Inherits "; r = classe->baseClasses().begin(); index = 0; while (r != classe->baseClasses().end()) { text << Atom(Atom::LinkNode, CodeMarker::stringForNode((*r).node)) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << Atom(Atom::String, (*r).dataTypeWithTemplateArgs) << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); if ((*r).access == Node::Protected) { text << " (protected)"; } else if ((*r).access == Node::Private) { text << " (private)"; } text << separator(index++, classe->baseClasses().count()); ++r; } text << Atom::ParaRight; generateText(text, classe, marker); } } void Generator::generateInheritedBy(const ClassNode *classe, CodeMarker *marker) { if (!classe->derivedClasses().isEmpty()) { Text text; text << Atom::ParaLeft << "Inherited by "; appendSortedNames(text, classe, classe->derivedClasses(), marker); text << Atom::ParaRight; generateText(text, classe, marker); } } void Generator::generateExampleFiles(const FakeNode *fake, CodeMarker *marker) { if (fake->childNodes().isEmpty()) return; OpenedList openedList(OpenedList::Bullet); Text text; text << Atom::ParaLeft << "Files:" << Atom::ParaRight << Atom(Atom::ListLeft, openedList.styleString()); foreach (const Node *child, fake->childNodes()) { QString exampleFile = child->name(); openedList.next(); text << Atom(Atom::ListItemNumber, openedList.numberString()) << Atom(Atom::ListItemLeft, openedList.styleString()) << Atom::ParaLeft << Atom(Atom::Link, exampleFile) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << exampleFile << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK) << Atom::ParaRight << Atom(Atom::ListItemRight, openedList.styleString()); } text << Atom(Atom::ListRight, openedList.styleString()); generateText(text, fake, marker); } void Generator::generateModuleWarning(const ClassNode *classe, CodeMarker *marker) { QString module = classe->moduleName(); if (!module.isEmpty()) { Text text; if (Tokenizer::isTrue("defined(consoleedition)") && !editionModuleMap["Console"].contains(module)) { text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This class is not part of the Qt Console Edition." << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << Atom::ParaRight; } else if (Tokenizer::isTrue("defined(desktoplightedition)") && !editionModuleMap["DesktopLight"].contains(module)) { text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This class is not part of the Qt Desktop Light Edition." << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << Atom::ParaRight; } else if (module == "Qt3Support" && Tokenizer::isTrue("defined(opensourceedition)")) { text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "Note to Qt Desktop Light Edition users:" << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " This class is only available in the " << Atom(Atom::AutoLink, "Qt Desktop Edition") << "." << Atom::ParaRight; } generateText(text, classe, marker); } } QString Generator::indent(int level, const QString& markedCode) { if (level == 0) return markedCode; QString t; int column = 0; int i = 0; while (i < (int) markedCode.length()) { if (markedCode.at(i) == QLatin1Char('<')) { while (i < (int) markedCode.length()) { t += markedCode.at(i++); if (markedCode.at(i - 1) == QLatin1Char('>')) break; } } else { if (markedCode.at(i) == QLatin1Char('\n')) { column = 0; } else { if (column == 0) { for (int j = 0; j < level; j++) t += QLatin1Char(' '); } column++; } t += markedCode.at(i++); } } return t; } QString Generator::plainCode(const QString& markedCode) { QString t = markedCode; t.replace(tag, QString()); t.replace(quot, QLatin1String("\"")); t.replace(gt, QLatin1String(">")); t.replace(lt, QLatin1String("<")); t.replace(amp, QLatin1String("&")); return t; } QString Generator::typeString(const Node *node) { switch (node->type()) { case Node::Namespace: return "namespace"; case Node::Class: return "class"; case Node::Fake: default: return "documentation"; case Node::Enum: return "enum"; case Node::Typedef: return "typedef"; case Node::Function: return "function"; case Node::Property: return "property"; } } QString Generator::imageFileName(const Node *relative, const QString& fileBase) { QString userFriendlyFilePath; QString filePath = Config::findFile( relative->doc().location(), imageFiles, imageDirs, fileBase, imgFileExts[format()], userFriendlyFilePath); if (filePath.isEmpty()) return QString(); return QLatin1String("images/") + Config::copyFile(relative->doc().location(), filePath, userFriendlyFilePath, outputDir() + QLatin1String("/images")); } void Generator::setImageFileExtensions(const QStringList& extensions) { imgFileExts[format()] = extensions; } void Generator::unknownAtom(const Atom *atom) { Location::internalError(tr("unknown atom type '%1' in %2 generator") .arg(atom->typeString()).arg(format())); } bool Generator::matchAhead(const Atom *atom, Atom::Type expectedAtomType) { return atom->next() != 0 && atom->next()->type() == expectedAtomType; } void Generator::supplementAlsoList(const Node *node, QList &alsoList) { if (node->type() == Node::Function) { const FunctionNode *func = static_cast(node); if (func->overloadNumber() == 1) { QString alternateName; const FunctionNode *alternateFunc = 0; if (func->name().startsWith("set") && func->name().size() >= 4) { alternateName = func->name()[3].toLower(); alternateName += func->name().mid(4); alternateFunc = func->parent()->findFunctionNode(alternateName); if (!alternateFunc) { alternateName = "is" + func->name().mid(3); alternateFunc = func->parent()->findFunctionNode(alternateName); if (!alternateFunc) { alternateName = "has" + func->name().mid(3); alternateFunc = func->parent()->findFunctionNode(alternateName); } } } else if (!func->name().isEmpty()) { alternateName = "set"; alternateName += func->name()[0].toUpper(); alternateName += func->name().mid(1); alternateFunc = func->parent()->findFunctionNode(alternateName); } if (alternateFunc && alternateFunc->access() != Node::Private) { int i; for (i = 0; i < alsoList.size(); ++i) { if (alsoList.at(i).toString().contains(alternateName)) break; } if (i == alsoList.size()) { alternateName += "()"; Text also; also << Atom(Atom::Link, alternateName) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << alternateName << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); alsoList.prepend(also); } } } } } QMap& Generator::formattingLeftMap() { return fmtLeftMaps[format()]; } QMap& Generator::formattingRightMap() { return fmtRightMaps[format()]; } QString Generator::trimmedTrailing(const QString &string) { QString trimmed = string; while (trimmed.length() > 0 && trimmed[trimmed.length() - 1].isSpace()) trimmed.truncate(trimmed.length() - 1); return trimmed; } void Generator::generateStatus(const Node *node, CodeMarker *marker) { Text text; switch (node->status()) { case Node::Commendable: case Node::Main: break; case Node::Preliminary: text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This " << typeString(node) << " is under development and is subject to change." << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << Atom::ParaRight; break; case Node::Deprecated: text << Atom::ParaLeft; if (node->isInnerNode()) text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD); text << "This " << typeString(node) << " is deprecated."; if (node->isInnerNode()) text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD); text << Atom::ParaRight; break; case Node::Obsolete: text << Atom::ParaLeft; if (node->isInnerNode()) text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD); text << "This " << typeString(node) << " is obsolete."; if (node->isInnerNode()) text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD); text << " It is provided to keep old source code working. We strongly advise against " << "using it in new code." << Atom::ParaRight; break; case Node::Compat: // reimplemented in HtmlGenerator subclass if (node->isInnerNode()) { text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "This " << typeString(node) << " is part of the Qt 3 compatibility layer." << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " It is provided to keep old source code working. We strongly advise against " << "using it in new code. See " << Atom(Atom::AutoLink, "Porting to Qt 4") << " for more information." << Atom::ParaRight; } break; case Node::Internal: default: break; } generateText(text, node, marker); } void Generator::generateThreadSafeness(const Node *node, CodeMarker *marker) { Text text; Text theStockLink; Node::ThreadSafeness parent = node->parent()->inheritedThreadSafeness(); switch (node->threadSafeness()) { case Node::UnspecifiedSafeness: break; case Node::NonReentrant: text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "Warning:" << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " This " << typeString(node) << " is not " << stockLink("reentrant") << "." << Atom::ParaRight; break; case Node::Reentrant: case Node::ThreadSafe: text << Atom::ParaLeft << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD); if (parent == Node::ThreadSafe) { text << "Warning:"; } else { text << "Note:"; } text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " "; if (node->threadSafeness() == Node::ThreadSafe) theStockLink = stockLink("thread-safe"); else theStockLink = stockLink("reentrant"); if (node->isInnerNode()) { const InnerNode *innerNode = static_cast(node); text << "All the functions in this " << typeString(node) << " are " << theStockLink; NodeList except; NodeList::ConstIterator c = innerNode->childNodes().begin(); while (c != innerNode->childNodes().end()) { if ((*c)->threadSafeness() != Node::UnspecifiedSafeness) except.append(*c); ++c; } if (except.isEmpty()) { text << "."; } else { text << ", except "; NodeList::ConstIterator e = except.begin(); int index = 0; while (e != except.end()) { appendFullName(text, *e, innerNode, marker); text << separator(index++, except.count()); ++e; } } } else { text << "This " << typeString(node) << " is " << theStockLink << "."; } text << Atom::ParaRight; } generateText(text, node, marker); } void Generator::generateSince(const Node *node, CodeMarker *marker) { if (!node->since().isEmpty()) { Text text; text << Atom::ParaLeft << "This " << typeString(node) << " was introduced in "; if (project.isEmpty()) text << "version"; else text << project; text << " " << node->since() << "." << Atom::ParaRight; generateText(text, node, marker); } } /*! No longer in use. */ void Generator::generateOverload(const Node *node, CodeMarker *marker) { Text text; text << Atom::ParaLeft << "This function overloads "; QString t = node->name() + "()"; text << Atom::AutoLink << t << Atom::ParaRight; generateText(text, node, marker); } void Generator::generateReimplementedFrom(const FunctionNode *func, CodeMarker *marker) { if (func->reimplementedFrom() != 0) { const FunctionNode *from = func->reimplementedFrom(); if (from->access() != Node::Private && from->parent()->access() != Node::Private) { Text text; text << Atom::ParaLeft << "Reimplemented from "; appendFullName(text, from->parent(), func, marker, from); text << "." << Atom::ParaRight; generateText(text, func, marker); } } } const Atom *Generator::generateAtomList(const Atom *atom, const Node *relative, CodeMarker *marker, bool generate, int &numAtoms) { while (atom) { if (atom->type() == Atom::FormatIf) { int numAtoms0 = numAtoms; bool rightFormat = canHandleFormat(atom->string()); atom = generateAtomList(atom->next(), relative, marker, generate && rightFormat, numAtoms); if (!atom) return 0; if (atom->type() == Atom::FormatElse) { ++numAtoms; atom = generateAtomList(atom->next(), relative, marker, generate && !rightFormat, numAtoms); if (!atom) return 0; } if (atom->type() == Atom::FormatEndif) { if (generate && numAtoms0 == numAtoms) { relative->location().warning(tr("Output format %1 not handled"). arg(format())); Atom unhandledFormatAtom(Atom::UnhandledFormat, format()); generateAtomList(&unhandledFormatAtom, relative, marker, generate, numAtoms); } atom = atom->next(); } } else if (atom->type() == Atom::FormatElse || atom->type() == Atom::FormatEndif) { return atom; } else { int n = 1; if (generate) { n += generateAtom(atom, relative, marker); numAtoms += n; } while (n-- > 0) atom = atom->next(); } } return 0; } void Generator::appendFullName(Text& text, const Node *apparentNode, const Node *relative, CodeMarker *marker, const Node *actualNode) { if (actualNode == 0) actualNode = apparentNode; text << Atom(Atom::LinkNode, CodeMarker::stringForNode(actualNode)) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << Atom(Atom::String, marker->plainFullName(apparentNode, relative)) << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK); } void Generator::appendSortedNames(Text& text, const ClassNode *classe, const QList &classes, CodeMarker *marker) { QList::ConstIterator r; QMap classMap; int index = 0; r = classes.begin(); while (r != classes.end()) { if ((*r).node->access() == Node::Public && (*r).node->status() != Node::Internal && !(*r).node->doc().isEmpty()) { Text className; appendFullName(className, (*r).node, classe, marker); classMap[className.toString().toLower()] = className; } ++r; } QStringList classNames = classMap.keys(); classNames.sort(); foreach (const QString &className, classNames) { text << classMap[className]; text << separator(index++, classNames.count()); } } int Generator::skipAtoms(const Atom *atom, Atom::Type type) const { int skipAhead = 0; atom = atom->next(); while (atom != 0 && atom->type() != type) { skipAhead++; atom = atom->next(); } return skipAhead; } QString Generator::fullName(const Node *node, const Node *relative, CodeMarker *marker) const { if (node->type() == Node::Fake) return static_cast(node)->title(); else if (node->type() == Node::Class && !(static_cast(node))->serviceName().isEmpty()) return (static_cast(node))->serviceName(); else return marker->plainFullName(node, relative); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/generator.h000066400000000000000000000152211215241066400211040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* generator.h */ #ifndef GENERATOR_H #define GENERATOR_H #include #include #include #include #include #include "node.h" #include "text.h" QT_BEGIN_NAMESPACE class ClassNode; class Config; class CodeMarker; class FakeNode; class FunctionNode; class InnerNode; class Location; class NamespaceNode; class Node; class Tree; class Generator { public: Generator(); virtual ~Generator(); virtual void initializeGenerator(const Config &config); virtual void terminateGenerator(); virtual QString format() = 0; virtual bool canHandleFormat(const QString &format) { return format == this->format(); } virtual void generateTree(const Tree *tree, CodeMarker *marker) = 0; static void initialize(const Config& config); static void terminate(); static Generator *generatorForFormat(const QString& format); protected: virtual void startText(const Node *relative, CodeMarker *marker); virtual void endText(const Node *relative, CodeMarker *marker); virtual int generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker); virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker); virtual void generateText(const Text& text, const Node *relative, CodeMarker *marker); #ifdef QDOC_QML virtual void generateQmlText(const Text& text, const Node *relative, CodeMarker *marker); #endif virtual void generateBody(const Node *node, CodeMarker *marker); virtual void generateAlsoList(const Node *node, CodeMarker *marker); virtual void generateInherits(const ClassNode *classe, CodeMarker *marker); virtual void generateInheritedBy(const ClassNode *classe, CodeMarker *marker); void generateThreadSafeness(const Node *node, CodeMarker *marker); void generateSince(const Node *node, CodeMarker *marker); void generateStatus(const Node *node, CodeMarker *marker); const Atom *generateAtomList(const Atom *atom, const Node *relative, CodeMarker *marker, bool generate, int& numGeneratedAtoms); void generateExampleFiles(const FakeNode *fake, CodeMarker *marker); void generateModuleWarning(const ClassNode *classe, CodeMarker *marker); virtual int skipAtoms(const Atom *atom, Atom::Type type) const; virtual QString fullName(const Node *node, const Node *relative, CodeMarker *marker) const; const QString& outputDir() { return outDir; } QString indent(int level, const QString& markedCode); QString plainCode(const QString& markedCode); virtual QString typeString(const Node *node); virtual QString imageFileName(const Node *relative, const QString& fileBase); void setImageFileExtensions(const QStringList& extensions); void unknownAtom(const Atom *atom); QMap &formattingLeftMap(); QMap &formattingRightMap(); QMap editionModuleMap; QMap editionGroupMap; static QString trimmedTrailing(const QString &string); static bool matchAhead(const Atom *atom, Atom::Type expectedAtomType); static void supplementAlsoList(const Node *node, QList &alsoList); private: void generateOverload(const Node *node, CodeMarker *marker); void generateReimplementedFrom(const FunctionNode *func, CodeMarker *marker); void appendFullName(Text& text, const Node *apparentNode, const Node *relative, CodeMarker *marker, const Node *actualNode = 0); void appendSortedNames(Text& text, const ClassNode *classe, const QList &classes, CodeMarker *marker); QString amp; QString lt; QString gt; QString quot; QRegExp tag; static QList generators; static QMap > fmtLeftMaps; static QMap > fmtRightMaps; static QMap imgFileExts; static QSet outputFormats; static QStringList imageFiles; static QStringList imageDirs; static QString outDir; static QString project; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/helpprojectwriter.cpp000066400000000000000000000643621215241066400232370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include "atom.h" #include "helpprojectwriter.h" #include "htmlgenerator.h" #include "config.h" #include "node.h" #include "tree.h" QT_BEGIN_NAMESPACE HelpProjectWriter::HelpProjectWriter(const Config &config, const QString &defaultFileName) { // The output directory should already have been checked by the calling // generator. outputDir = config.getString(CONFIG_OUTPUTDIR); QStringList names = config.getStringList(CONFIG_QHP + Config::dot + "projects"); foreach (const QString &projectName, names) { HelpProject project; project.name = projectName; QString prefix = CONFIG_QHP + Config::dot + projectName + Config::dot; project.helpNamespace = config.getString(prefix + "namespace"); project.virtualFolder = config.getString(prefix + "virtualFolder"); project.fileName = config.getString(prefix + "file"); if (project.fileName.isEmpty()) project.fileName = defaultFileName; project.extraFiles = config.getStringSet(prefix + "extraFiles"); project.indexTitle = config.getString(prefix + "indexTitle"); project.indexRoot = config.getString(prefix + "indexRoot"); project.filterAttributes = config.getStringList(prefix + "filterAttributes").toSet(); QSet customFilterNames = config.subVars(prefix + "customFilters"); foreach (const QString &filterName, customFilterNames) { QString name = config.getString(prefix + "customFilters" + Config::dot + filterName + Config::dot + "name"); QSet filters = config.getStringList(prefix + "customFilters" + Config::dot + filterName + Config::dot + "filterAttributes").toSet(); project.customFilters[name] = filters; } //customFilters = config.defs. foreach (QString name, config.getStringSet(prefix + "excluded")) project.excluded.insert(name.replace("\\", "/")); foreach (const QString &name, config.getStringList(prefix + "subprojects")) { SubProject subproject; QString subprefix = prefix + "subprojects" + Config::dot + name + Config::dot; subproject.title = config.getString(subprefix + "title"); subproject.indexTitle = config.getString(subprefix + "indexTitle"); subproject.sortPages = config.getBool(subprefix + "sortPages"); readSelectors(subproject, config.getStringList(subprefix + "selectors")); project.subprojects[name] = subproject; } if (project.subprojects.isEmpty()) { SubProject subproject; readSelectors(subproject, config.getStringList(prefix + "selectors")); project.subprojects[""] = subproject; } projects.append(project); } } void HelpProjectWriter::readSelectors(SubProject &subproject, const QStringList &selectors) { QHash typeHash; typeHash["namespace"] = Node::Namespace; typeHash["class"] = Node::Class; typeHash["fake"] = Node::Fake; typeHash["enum"] = Node::Enum; typeHash["typedef"] = Node::Typedef; typeHash["function"] = Node::Function; typeHash["property"] = Node::Property; typeHash["variable"] = Node::Variable; typeHash["target"] = Node::Target; QHash subTypeHash; subTypeHash["example"] = FakeNode::Example; subTypeHash["headerfile"] = FakeNode::HeaderFile; subTypeHash["file"] = FakeNode::File; subTypeHash["group"] = FakeNode::Group; subTypeHash["module"] = FakeNode::Module; subTypeHash["page"] = FakeNode::Page; subTypeHash["externalpage"] = FakeNode::ExternalPage; QSet allSubTypes = QSet::fromList(subTypeHash.values()); foreach (const QString &selector, selectors) { QStringList pieces = selector.split(":"); if (pieces.size() == 1) { QString lower = selector.toLower(); if (typeHash.contains(lower)) subproject.selectors[typeHash[lower]] = allSubTypes; } else if (pieces.size() >= 2) { QString lower = pieces[0].toLower(); pieces = pieces[1].split(","); if (typeHash.contains(lower)) { QSet subTypes; for (int i = 0; i < pieces.size(); ++i) { QString lower = pieces[i].toLower(); if (subTypeHash.contains(lower)) subTypes.insert(subTypeHash[lower]); } subproject.selectors[typeHash[lower]] = subTypes; } } } } void HelpProjectWriter::addExtraFile(const QString &file) { for (int i = 0; i < projects.size(); ++i) projects[i].extraFiles.insert(file); } void HelpProjectWriter::addExtraFiles(const QSet &files) { for (int i = 0; i < projects.size(); ++i) projects[i].extraFiles.unite(files); } /* Returns a list of strings describing the keyword details for a given node. The first string is the human-readable name to be shown in Assistant. The second string is a unique identifier. The third string is the location of the documentation for the keyword. */ QStringList HelpProjectWriter::keywordDetails(const Node *node) const { QStringList details; if (node->parent() && !node->parent()->name().isEmpty()) { // "name" if (node->type() == Node::Enum || node->type() == Node::Typedef) details << node->parent()->name()+"::"+node->name(); else details << node->name(); // "id" details << node->parent()->name()+"::"+node->name(); } else if (node->type() == Node::Fake) { const FakeNode *fake = static_cast(node); details << fake->fullTitle(); details << fake->fullTitle(); } else { details << node->name(); details << node->name(); } details << tree->fullDocumentLocation(node); return details; } bool HelpProjectWriter::generateSection(HelpProject &project, QXmlStreamWriter & /* writer */, const Node *node) { if (!node->url().isEmpty()) return false; if (node->access() == Node::Private || node->status() == Node::Internal) return false; if (node->name().isEmpty()) return true; QString docPath = node->doc().location().filePath(); if (!docPath.isEmpty() && project.excluded.contains(docPath)) return false; QString objName; if (node->type() == Node::Fake) { const FakeNode *fake = static_cast(node); objName = fake->fullTitle(); } else objName = tree->fullDocumentName(node); // Only add nodes to the set for each subproject if they match a selector. // Those that match will be listed in the table of contents. foreach (const QString &name, project.subprojects.keys()) { SubProject subproject = project.subprojects[name]; // No selectors: accept all nodes. if (subproject.selectors.isEmpty()) project.subprojects[name].nodes[objName] = node; else if (subproject.selectors.contains(node->type())) { // Accept only the node types in the selectors hash. if (node->type() != Node::Fake) project.subprojects[name].nodes[objName] = node; else { // Accept only fake nodes with subtypes contained in the selector's // mask. const FakeNode *fakeNode = static_cast(node); if (subproject.selectors[node->type()].contains(fakeNode->subType()) && fakeNode->subType() != FakeNode::ExternalPage && !fakeNode->fullTitle().isEmpty()) project.subprojects[name].nodes[objName] = node; } } } switch (node->type()) { case Node::Class: project.keywords.append(keywordDetails(node)); project.files.insert(tree->fullDocumentLocation(node)); break; case Node::Namespace: project.keywords.append(keywordDetails(node)); project.files.insert(tree->fullDocumentLocation(node)); break; case Node::Enum: project.keywords.append(keywordDetails(node)); { const EnumNode *enumNode = static_cast(node); foreach (const EnumItem &item, enumNode->items()) { QStringList details; if (enumNode->itemAccess(item.name()) == Node::Private) continue; if (!node->parent()->name().isEmpty()) { details << node->parent()->name()+"::"+item.name(); // "name" details << node->parent()->name()+"::"+item.name(); // "id" } else { details << item.name(); // "name" details << item.name(); // "id" } details << tree->fullDocumentLocation(node); project.keywords.append(details); } } break; case Node::Property: project.keywords.append(keywordDetails(node)); break; case Node::Function: { const FunctionNode *funcNode = static_cast(node); // Only insert keywords for non-constructors. Constructors are covered // by the classes themselves. if (funcNode->metaness() != FunctionNode::Ctor) project.keywords.append(keywordDetails(node)); // Insert member status flags into the entries for the parent // node of the function, or the node it is related to. // Since parent nodes should have already been inserted into // the set of files, we only need to ensure that related nodes // are inserted. if (node->relates()) { project.memberStatus[node->relates()].insert(node->status()); project.files.insert(tree->fullDocumentLocation(node->relates())); } else if (node->parent()) project.memberStatus[node->parent()].insert(node->status()); } break; case Node::Typedef: { const TypedefNode *typedefNode = static_cast(node); QStringList typedefDetails = keywordDetails(node); const EnumNode *enumNode = typedefNode->associatedEnum(); // Use the location of any associated enum node in preference // to that of the typedef. if (enumNode) typedefDetails[2] = tree->fullDocumentLocation(enumNode); project.keywords.append(typedefDetails); } break; // Fake nodes (such as manual pages) contain subtypes, titles and other // attributes. case Node::Fake: { const FakeNode *fakeNode = static_cast(node); if (fakeNode->subType() != FakeNode::ExternalPage && !fakeNode->fullTitle().isEmpty()) { if (fakeNode->subType() != FakeNode::File) { if (fakeNode->doc().hasKeywords()) { foreach (const Atom *keyword, fakeNode->doc().keywords()) { if (!keyword->string().isEmpty()) { QStringList details; details << keyword->string() << keyword->string() << tree->fullDocumentLocation(node) + "#" + Doc::canonicalTitle(keyword->string()); project.keywords.append(details); } else fakeNode->doc().location().warning( tr("Bad keyword in %1").arg(tree->fullDocumentLocation(node)) ); } } project.keywords.append(keywordDetails(node)); } /* if (fakeNode->doc().hasTableOfContents()) { foreach (const Atom *item, fakeNode->doc().tableOfContents()) { QString title = Text::sectionHeading(item).toString(); if (!title.isEmpty()) { QStringList details; details << title << title << tree->fullDocumentLocation(node) + "#" + Doc::canonicalTitle(title); project.keywords.append(details); } else fakeNode->doc().location().warning( tr("Bad contents item in %1").arg(tree->fullDocumentLocation(node)) ); } } */ project.files.insert(tree->fullDocumentLocation(node)); } break; } default: ; } // Add all images referenced in the page to the set of files to include. const Atom *atom = node->doc().body().firstAtom(); while (atom) { if (atom->type() == Atom::Image || atom->type() == Atom::InlineImage) { // Images are all placed within a single directory regardless of // whether the source images are in a nested directory structure. QStringList pieces = atom->string().split("/"); project.files.insert("images/" + pieces.last()); } atom = atom->next(); } return true; } void HelpProjectWriter::generateSections(HelpProject &project, QXmlStreamWriter &writer, const Node *node) { if (!generateSection(project, writer, node)) return; if (node->isInnerNode()) { const InnerNode *inner = static_cast(node); // Ensure that we don't visit nodes more than once. QMap childMap; foreach (const Node *node, inner->childNodes()) { if (node->access() == Node::Private) continue; if (node->type() == Node::Fake) childMap[static_cast(node)->fullTitle()] = node; else { if (node->type() == Node::Function) { const FunctionNode *funcNode = static_cast(node); if (funcNode->isOverload()) continue; } childMap[tree->fullDocumentName(node)] = node; } } foreach (const Node *child, childMap) generateSections(project, writer, child); } } void HelpProjectWriter::generate(const Tree *tre) { this->tree = tre; for (int i = 0; i < projects.size(); ++i) generateProject(projects[i]); } void HelpProjectWriter::writeNode(HelpProject &project, QXmlStreamWriter &writer, const Node *node) { QString href = tree->fullDocumentLocation(node); QString objName = node->name(); switch (node->type()) { case Node::Class: writer.writeStartElement("section"); writer.writeAttribute("ref", href); if (node->parent() && !node->parent()->name().isEmpty()) writer.writeAttribute("title", tr("%1::%2 Class Reference").arg(node->parent()->name()).arg(objName)); else writer.writeAttribute("title", tr("%1 Class Reference").arg(objName)); // Write subsections for all members, obsolete members and Qt 3 // members. if (!project.memberStatus[node].isEmpty()) { QString membersPath = href.left(href.size()-5) + "-members.html"; writer.writeStartElement("section"); writer.writeAttribute("ref", membersPath); writer.writeAttribute("title", tr("List of all members")); writer.writeEndElement(); // section project.files.insert(membersPath); } if (project.memberStatus[node].contains(Node::Compat)) { QString compatPath = href.left(href.size()-5) + "-qt3.html"; writer.writeStartElement("section"); writer.writeAttribute("ref", compatPath); writer.writeAttribute("title", tr("Qt 3 support members")); writer.writeEndElement(); // section project.files.insert(compatPath); } if (project.memberStatus[node].contains(Node::Obsolete)) { QString obsoletePath = href.left(href.size()-5) + "-obsolete.html"; writer.writeStartElement("section"); writer.writeAttribute("ref", obsoletePath); writer.writeAttribute("title", tr("Obsolete members")); writer.writeEndElement(); // section project.files.insert(obsoletePath); } writer.writeEndElement(); // section break; case Node::Namespace: writer.writeStartElement("section"); writer.writeAttribute("ref", href); writer.writeAttribute("title", objName); writer.writeEndElement(); // section break; case Node::Fake: { // Fake nodes (such as manual pages) contain subtypes, titles and other // attributes. const FakeNode *fakeNode = static_cast(node); writer.writeStartElement("section"); writer.writeAttribute("ref", href); writer.writeAttribute("title", fakeNode->fullTitle()); // qDebug() << "Title:" << fakeNode->fullTitle(); if (fakeNode->subType() == FakeNode::HeaderFile) { // Write subsections for all members, obsolete members and Qt 3 // members. if (!project.memberStatus[node].isEmpty()) { QString membersPath = href.left(href.size()-5) + "-members.html"; writer.writeStartElement("section"); writer.writeAttribute("ref", membersPath); writer.writeAttribute("title", tr("List of all members")); writer.writeEndElement(); // section project.files.insert(membersPath); } if (project.memberStatus[node].contains(Node::Compat)) { QString compatPath = href.left(href.size()-5) + "-qt3.html"; writer.writeStartElement("section"); writer.writeAttribute("ref", compatPath); writer.writeAttribute("title", tr("Qt 3 support members")); writer.writeEndElement(); // section project.files.insert(compatPath); } if (project.memberStatus[node].contains(Node::Obsolete)) { QString obsoletePath = href.left(href.size()-5) + "-obsolete.html"; writer.writeStartElement("section"); writer.writeAttribute("ref", obsoletePath); writer.writeAttribute("title", tr("Obsolete members")); writer.writeEndElement(); // section project.files.insert(obsoletePath); } } writer.writeEndElement(); // section } break; default: ; } } void HelpProjectWriter::generateProject(HelpProject &project) { const Node *rootNode; if (!project.indexRoot.isEmpty()) rootNode = tree->findFakeNodeByTitle(project.indexRoot); else rootNode = tree->root(); if (!rootNode) return; project.files.clear(); project.keywords.clear(); QFile file(outputDir + QDir::separator() + project.fileName); if (!file.open(QFile::WriteOnly | QFile::Text)) return; QXmlStreamWriter writer(&file); writer.setAutoFormatting(true); writer.writeStartDocument(); writer.writeStartElement("QtHelpProject"); writer.writeAttribute("version", "1.0"); // Write metaData, virtualFolder and namespace elements. writer.writeTextElement("namespace", project.helpNamespace); writer.writeTextElement("virtualFolder", project.virtualFolder); // Write customFilter elements. QHash >::ConstIterator it; for (it = project.customFilters.begin(); it != project.customFilters.end(); ++it) { writer.writeStartElement("customFilter"); writer.writeAttribute("name", it.key()); foreach (const QString &filter, it.value()) writer.writeTextElement("filterAttribute", filter); writer.writeEndElement(); // customFilter } // Start the filterSection. writer.writeStartElement("filterSection"); // Write filterAttribute elements. foreach (const QString &filterName, project.filterAttributes) writer.writeTextElement("filterAttribute", filterName); writer.writeStartElement("toc"); writer.writeStartElement("section"); QString indexPath = tree->fullDocumentLocation(tree->findFakeNodeByTitle(project.indexTitle)); if (indexPath.isEmpty()) indexPath = "index.html"; writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath)); writer.writeAttribute("title", project.indexTitle); project.files.insert(tree->fullDocumentLocation(rootNode)); generateSections(project, writer, rootNode); foreach (const QString &name, project.subprojects.keys()) { SubProject subproject = project.subprojects[name]; if (!name.isEmpty()) { writer.writeStartElement("section"); QString indexPath = tree->fullDocumentLocation(tree->findFakeNodeByTitle(subproject.indexTitle)); writer.writeAttribute("ref", HtmlGenerator::cleanRef(indexPath)); writer.writeAttribute("title", subproject.title); project.files.insert(indexPath); } if (subproject.sortPages) { QStringList titles = subproject.nodes.keys(); titles.sort(); foreach (const QString &title, titles) writeNode(project, writer, subproject.nodes[title]); } else { // Find a contents node and navigate from there, using the NextLink values. foreach (const Node *node, subproject.nodes) { QString nextTitle = node->links().value(Node::NextLink).first; if (!nextTitle.isEmpty() && node->links().value(Node::ContentsLink).first.isEmpty()) { FakeNode *nextPage = const_cast(tree->findFakeNodeByTitle(nextTitle)); // Write the contents node. writeNode(project, writer, node); while (nextPage) { writeNode(project, writer, nextPage); nextTitle = nextPage->links().value(Node::NextLink).first; if (nextTitle.isEmpty()) break; nextPage = const_cast(tree->findFakeNodeByTitle(nextTitle)); } break; } } } if (!name.isEmpty()) writer.writeEndElement(); // section } writer.writeEndElement(); // section writer.writeEndElement(); // toc writer.writeStartElement("keywords"); foreach (const QStringList &details, project.keywords) { writer.writeStartElement("keyword"); writer.writeAttribute("name", details[0]); writer.writeAttribute("id", details[1]); writer.writeAttribute("ref", HtmlGenerator::cleanRef(details[2])); writer.writeEndElement(); //keyword } writer.writeEndElement(); // keywords writer.writeStartElement("files"); foreach (const QString &usedFile, project.files) { if (!usedFile.isEmpty()) writer.writeTextElement("file", usedFile); } foreach (const QString &usedFile, project.extraFiles) writer.writeTextElement("file", usedFile); writer.writeEndElement(); // files writer.writeEndElement(); // filterSection writer.writeEndElement(); // QtHelpProject writer.writeEndDocument(); file.close(); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/helpprojectwriter.h000066400000000000000000000072311215241066400226740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef HELPPROJECTWRITER_H #define HELPPROJECTWRITER_H #include #include #include #include "config.h" #include "node.h" QT_BEGIN_NAMESPACE class Tree; typedef QPair QStringNodePair; struct SubProject { QString title; QString indexTitle; QHash > selectors; bool sortPages; QHash nodes; }; struct HelpProject { QString name; QString helpNamespace; QString virtualFolder; QString fileName; QString indexRoot; QString indexTitle; QList keywords; QSet files; QSet extraFiles; QSet filterAttributes; QHash > customFilters; QSet excluded; QMap subprojects; QHash > memberStatus; }; class HelpProjectWriter { public: HelpProjectWriter(const Config &config, const QString &defaultFileName); void addExtraFile(const QString &file); void addExtraFiles(const QSet &files); void generate(const Tree *tre); private: void generateProject(HelpProject &project); void generateSections(HelpProject &project, QXmlStreamWriter &writer, const Node *node); bool generateSection(HelpProject &project, QXmlStreamWriter &writer, const Node *node); QStringList keywordDetails(const Node *node) const; void writeNode(HelpProject &project, QXmlStreamWriter &writer, const Node *node); void readSelectors(SubProject &subproject, const QStringList &selectors); const Tree *tree; QString outputDir; QList projects; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/htmlgenerator.cpp000066400000000000000000003274751215241066400223450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* htmlgenerator.cpp */ #include "codemarker.h" #include "helpprojectwriter.h" #include "htmlgenerator.h" #include "node.h" #include "separator.h" #include "tree.h" #include #include #include #include QT_BEGIN_NAMESPACE #define COMMAND_VERSION Doc::alias("version") static bool showBrokenLinks = false; HtmlGenerator::HtmlGenerator() : helpProjectWriter(0), inLink(false), inContents(false), inSectionHeading(false), inTableHeader(false), numTableRows(0), threeColumnEnumValueTable(true), funcLeftParen("\\S(\\()"), tre(0), slow(false) { } HtmlGenerator::~HtmlGenerator() { if (helpProjectWriter) delete helpProjectWriter; } void HtmlGenerator::initializeGenerator(const Config &config) { static const struct { const char *key; const char *left; const char *right; } defaults[] = { { ATOM_FORMATTING_BOLD, "", "" }, { ATOM_FORMATTING_INDEX, "" }, { ATOM_FORMATTING_ITALIC, "", "" }, { ATOM_FORMATTING_PARAMETER, "", "" }, { ATOM_FORMATTING_SUBSCRIPT, "", "" }, { ATOM_FORMATTING_SUPERSCRIPT, "", "" }, { ATOM_FORMATTING_TELETYPE, "", "" }, { ATOM_FORMATTING_UNDERLINE, "", "" }, { 0, 0, 0 } }; Generator::initializeGenerator(config); setImageFileExtensions(QStringList() << "png" << "jpg" << "jpeg" << "gif"); int i = 0; while (defaults[i].key) { formattingLeftMap().insert(defaults[i].key, defaults[i].left); formattingRightMap().insert(defaults[i].key, defaults[i].right); i++; } style = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_STYLE); postHeader = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_POSTHEADER); footer = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_FOOTER); address = config.getString(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_ADDRESS); pleaseGenerateMacRef = config.getBool(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_GENERATEMACREFS); project = config.getString(CONFIG_PROJECT); projectDescription = config.getString(CONFIG_DESCRIPTION); if (projectDescription.isEmpty() && !project.isEmpty()) projectDescription = project + " Reference Documentation"; projectUrl = config.getString(CONFIG_URL); QSet editionNames = config.subVars(CONFIG_EDITION); QSet::ConstIterator edition = editionNames.begin(); while (edition != editionNames.end()) { QString editionName = *edition; QStringList editionModules = config.getStringList( CONFIG_EDITION + Config::dot + editionName + Config::dot + "modules"); QStringList editionGroups = config.getStringList( CONFIG_EDITION + Config::dot + editionName + Config::dot + "groups"); if (!editionModules.isEmpty()) editionModuleMap[editionName] = editionModules; if (!editionGroups.isEmpty()) editionGroupMap[editionName] = editionGroups; ++edition; } slow = config.getBool(CONFIG_SLOW); stylesheets = config.getStringList(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_STYLESHEETS); customHeadElements = config.getStringList(HtmlGenerator::format() + Config::dot + HTMLGENERATOR_CUSTOMHEADELEMENTS); codeIndent = config.getInt(CONFIG_CODEINDENT); helpProjectWriter = new HelpProjectWriter(config, project.toLower() + ".qhp"); } void HtmlGenerator::terminateGenerator() { Generator::terminateGenerator(); } QString HtmlGenerator::format() { return "HTML"; } /*! This is where the html files and dcf files are written. \note The html file generation is done in the base class, PageGenerator::generateTree(). */ void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker) { // Copy the stylesheets from the directory containing the qdocconf file. // ### This should be changed to use a special directory in doc/src. QStringList::ConstIterator styleIter = stylesheets.begin(); QDir configPath = QDir::current(); while (styleIter != stylesheets.end()) { QString filePath = configPath.absoluteFilePath(*styleIter); Config::copyFile(Location(), filePath, filePath, outputDir()); ++styleIter; } tre = tree; nonCompatClasses.clear(); mainClasses.clear(); compatClasses.clear(); moduleClassMap.clear(); moduleNamespaceMap.clear(); funcIndex.clear(); legaleseTexts.clear(); serviceClasses.clear(); findAllClasses(tree->root()); findAllFunctions(tree->root()); findAllLegaleseTexts(tree->root()); findAllNamespaces(tree->root()); #ifdef ZZZ_QDOC_QML findAllQmlClasses(tree->root()); #endif PageGenerator::generateTree(tree, marker); dcfClassesRoot.ref = "classes.html"; dcfClassesRoot.title = "Classes"; qSort(dcfClassesRoot.subsections); dcfOverviewsRoot.ref = "overviews.html"; dcfOverviewsRoot.title = "Overviews"; qSort(dcfOverviewsRoot.subsections); dcfExamplesRoot.ref = "examples.html"; dcfExamplesRoot.title = "Tutorial & Examples"; qSort(dcfExamplesRoot.subsections); DcfSection qtRoot; appendDcfSubSection(&qtRoot, dcfClassesRoot); appendDcfSubSection(&qtRoot, dcfOverviewsRoot); appendDcfSubSection(&qtRoot, dcfExamplesRoot); generateDcf(project.toLower().simplified().replace(" ", "-"), "index.html", projectDescription, qtRoot); generateDcf("designer", "designer-manual.html", "Qt Designer Manual", dcfDesignerRoot); generateDcf("linguist", "linguist-manual.html", "Qt Linguist Manual", dcfLinguistRoot); generateDcf("assistant", "assistant-manual.html", "Qt Assistant Manual", dcfAssistantRoot); generateDcf("qmake", "qmake-manual.html", "qmake Manual", dcfQmakeRoot); generateIndex(project.toLower().simplified().replace(" ", "-"), projectUrl, projectDescription); helpProjectWriter->generate(tre); } void HtmlGenerator::startText(const Node * /* relative */, CodeMarker * /* marker */) { inLink = false; inContents = false; inSectionHeading = false; inTableHeader = false; numTableRows = 0; threeColumnEnumValueTable = true; link.clear(); sectionNumber.clear(); } int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker) { int skipAhead = 0; static bool in_para = false; switch (atom->type()) { case Atom::AbstractLeft: break; case Atom::AbstractRight: break; case Atom::AutoLink: if (!inLink && !inContents && !inSectionHeading) { const Node *node = 0; QString link = getLink(atom, relative, marker, node); if (!link.isEmpty()) { beginLink(link, node, relative, marker); generateLink(atom, relative, marker); endLink(); } else { out() << protect(atom->string()); } } else { out() << protect(atom->string()); } break; case Atom::BaseName: break; case Atom::BriefLeft: if (relative->type() == Node::Fake) { skipAhead = skipAtoms(atom, Atom::BriefRight); break; } out() << "

"; if (relative->type() == Node::Property || relative->type() == Node::Variable) { QString str; atom = atom->next(); while (atom != 0 && atom->type() != Atom::BriefRight) { if (atom->type() == Atom::String || atom->type() == Atom::AutoLink) str += atom->string(); skipAhead++; atom = atom->next(); } str[0] = str[0].toLower(); if (str.right(1) == ".") str.truncate(str.length() - 1); out() << "This "; if (relative->type() == Node::Property) out() << "property"; else out() << "variable"; QStringList words = str.split(" "); if (!(words.first() == "contains" || words.first() == "specifies" || words.first() == "describes" || words.first() == "defines" || words.first() == "holds" || words.first() == "determines")) out() << " holds "; else out() << " "; out() << str << "."; } break; case Atom::BriefRight: if (relative->type() != Node::Fake) out() << "

\n"; break; case Atom::C: out() << formattingLeftMap()[ATOM_FORMATTING_TELETYPE]; if (inLink) { out() << protect(plainCode(atom->string())); } else { out() << highlightedCode(atom->string(), marker, relative); } out() << formattingRightMap()[ATOM_FORMATTING_TELETYPE]; break; case Atom::Code: out() << "
" << trimmedTrailing(highlightedCode(indent(codeIndent, atom->string()),
                                                            marker, relative))
              << "
\n"; break; #ifdef QDOC_QML case Atom::Qml: out() << "
" << trimmedTrailing(highlightedCode(indent(codeIndent, atom->string()),
                                                            marker, relative))
              << "
\n"; break; #endif case Atom::CodeNew: out() << "

you can rewrite it as

\n" << "
" << trimmedTrailing(highlightedCode(indent(codeIndent, atom->string()),
                                                            marker, relative))
              << "
\n"; break; case Atom::CodeOld: out() << "

For example, if you have code like

\n"; // fallthrough case Atom::CodeBad: out() << "
"
              << trimmedTrailing(protect(plainCode(indent(codeIndent, atom->string()))))
              << "
\n"; break; case Atom::FootnoteLeft: // ### For now if (in_para) { out() << "

\n"; in_para = false; } out() << ""; break; case Atom::FormatElse: case Atom::FormatEndif: case Atom::FormatIf: break; case Atom::FormattingLeft: out() << formattingLeftMap()[atom->string()]; if (atom->string() == ATOM_FORMATTING_PARAMETER) { if (atom->next() != 0 && atom->next()->type() == Atom::String) { QRegExp subscriptRegExp("([a-z]+)_([0-9n])"); if (subscriptRegExp.exactMatch(atom->next()->string())) { out() << subscriptRegExp.cap(1) << "" << subscriptRegExp.cap(2) << ""; skipAhead = 1; } } } break; case Atom::FormattingRight: if (atom->string() == ATOM_FORMATTING_LINK) { endLink(); } else { out() << formattingRightMap()[atom->string()]; } break; case Atom::GeneratedList: if (atom->string() == "annotatedclasses") { generateAnnotatedList(relative, marker, nonCompatClasses); } else if (atom->string() == "classes") { generateCompactList(relative, marker, nonCompatClasses); } else if (atom->string().contains("classesbymodule")) { QString arg = atom->string().trimmed(); QString moduleName = atom->string().mid(atom->string().indexOf( "classesbymodule") + 15).trimmed(); if (moduleClassMap.contains(moduleName)) generateAnnotatedList(relative, marker, moduleClassMap[moduleName]); } else if (atom->string().contains("classesbyedition")) { QString arg = atom->string().trimmed(); QString editionName = atom->string().mid(atom->string().indexOf( "classesbyedition") + 16).trimmed(); if (editionModuleMap.contains(editionName)) { // Add all classes in the modules listed for that edition. QMap editionClasses; foreach (const QString &moduleName, editionModuleMap[editionName]) { if (moduleClassMap.contains(moduleName)) editionClasses.unite(moduleClassMap[moduleName]); } // Add additional groups and remove groups of classes that // should be excluded from the edition. QMultiMap groups = tre->groups(); foreach (const QString &groupName, editionGroupMap[editionName]) { QList groupClasses; if (groupName.startsWith("-")) { groupClasses = groups.values(groupName.mid(1)); foreach (const Node *node, groupClasses) editionClasses.remove(node->name()); } else { groupClasses = groups.values(groupName); foreach (const Node *node, groupClasses) editionClasses.insert(node->name(), node); } } generateAnnotatedList(relative, marker, editionClasses); } } else if (atom->string() == "classhierarchy") { generateClassHierarchy(relative, marker, nonCompatClasses); } else if (atom->string() == "compatclasses") { generateCompactList(relative, marker, compatClasses); } else if (atom->string() == "functionindex") { generateFunctionIndex(relative, marker); } else if (atom->string() == "legalese") { generateLegaleseList(relative, marker); } else if (atom->string() == "mainclasses") { generateCompactList(relative, marker, mainClasses); } else if (atom->string() == "services") { generateCompactList(relative, marker, serviceClasses); } else if (atom->string() == "overviews") { generateOverviewList(relative, marker); } else if (atom->string() == "namespaces") { generateAnnotatedList(relative, marker, namespaceIndex); } else if (atom->string() == "related") { const FakeNode *fake = static_cast(relative); if (fake && !fake->groupMembers().isEmpty()) { QMap groupMembersMap; foreach (const Node *node, fake->groupMembers()) { if (node->type() == Node::Fake) groupMembersMap[fullName(node, relative, marker)] = node; } generateAnnotatedList(fake, marker, groupMembersMap); } } else if (atom->string() == "relatedinline") { const FakeNode *fake = static_cast(relative); if (fake && !fake->groupMembers().isEmpty()) { // Reverse the list into the original scan order. // Should be sorted. But on what? It may not be a // regular class or page definition. QList list; foreach (const Node *node, fake->groupMembers()) list.prepend(node); foreach (const Node *node, list) generateBody(node, marker); } } break; case Atom::Image: case Atom::InlineImage: { QString fileName = imageFileName(relative, atom->string()); QString text; if (atom->next() != 0) text = atom->next()->string(); if (atom->type() == Atom::Image) out() << "

"; if (fileName.isEmpty()) { out() << "[Missing image " << protect(atom->string()) << "]"; } else { out() << "\"""; helpProjectWriter->addExtraFile(fileName); } if (atom->type() == Atom::Image) out() << "

"; } break; case Atom::ImageText: break; case Atom::LegaleseLeft: out() << "
"; break; case Atom::LegaleseRight: out() << "
"; break; case Atom::LineBreak: out() << "
"; break; case Atom::Link: { const Node *node = 0; QString myLink = getLink(atom, relative, marker, node); if (myLink.isEmpty()) relative->doc().location().warning(tr("Cannot link to '%1' in %2") .arg(atom->string()) .arg(marker->plainFullName(relative))); beginLink(myLink, node, relative, marker); skipAhead = 1; } break; case Atom::LinkNode: { const Node *node = CodeMarker::nodeForString(atom->string()); beginLink(linkForNode(node, relative), node, relative, marker); skipAhead = 1; } break; case Atom::ListLeft: if (in_para) { out() << "

\n"; in_para = false; } if (atom->string() == ATOM_LIST_BULLET) { out() << "
    \n"; } else if (atom->string() == ATOM_LIST_TAG) { out() << "
    \n"; } else if (atom->string() == ATOM_LIST_VALUE) { threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom); if (threeColumnEnumValueTable) { out() << "

    \n" "" "\n"; } else { out() << "

    ConstantValueDescription
    \n" << "\n"; } } else { out() << "
      string() == ATOM_LIST_LOWERALPHA) { out() << "\"a\""; } else if (atom->string() == ATOM_LIST_UPPERROMAN) { out() << "\"I\""; } else if (atom->string() == ATOM_LIST_LOWERROMAN) { out() << "\"i\""; } else { // (atom->string() == ATOM_LIST_NUMERIC) out() << "\"1\""; } if (atom->next() != 0 && atom->next()->string().toInt() != 1) out() << " start=\"" << atom->next()->string() << "\""; out() << ">\n"; } break; case Atom::ListItemNumber: break; case Atom::ListTagLeft: if (atom->string() == ATOM_LIST_TAG) { out() << "
      "; } else { // (atom->string() == ATOM_LIST_VALUE) // ### Trenton out() << "
    \n"; } else { out() << "\n"; } break; case Atom::ListRight: if (atom->string() == ATOM_LIST_BULLET) { out() << "\n"; } else if (atom->string() == ATOM_LIST_TAG) { out() << "\n"; } else if (atom->string() == ATOM_LIST_VALUE) { out() << "
    ConstantValue
    " << protect(plainCode(marker->markedUpEnumValue(atom->next()->string(), relative))) << ""; QString itemValue; if (relative->type() == Node::Enum) { const EnumNode *enume = static_cast(relative); itemValue = enume->itemValue(atom->next()->string()); } if (itemValue.isEmpty()) out() << "?"; else out() << "" << protect(itemValue) << ""; skipAhead = 1; } break; case Atom::ListTagRight: if (atom->string() == ATOM_LIST_TAG) out() << "\n"; break; case Atom::ListItemLeft: if (atom->string() == ATOM_LIST_TAG) { out() << "
    "; } else if (atom->string() == ATOM_LIST_VALUE) { if (threeColumnEnumValueTable) { out() << "
    "; if (matchAhead(atom, Atom::ListItemRight)) out() << " "; } } else { out() << "
  • "; } if (matchAhead(atom, Atom::ParaLeft)) skipAhead = 1; break; case Atom::ListItemRight: if (atom->string() == ATOM_LIST_TAG) { out() << "\n"; } else if (atom->string() == ATOM_LIST_VALUE) { out() << "
  • \n"; } else { out() << "\n"; } break; case Atom::Nop: break; case Atom::ParaLeft: out() << "

    "; in_para = true; break; case Atom::ParaRight: endLink(); if (in_para) { out() << "

    \n"; in_para = false; } //if (!matchAhead(atom, Atom::ListItemRight) && !matchAhead(atom, Atom::TableItemRight)) // out() << "

    \n"; break; case Atom::QuotationLeft: out() << "
    "; break; case Atom::QuotationRight: out() << "
    \n"; break; case Atom::RawString: out() << atom->string(); break; case Atom::SectionLeft: #if 0 { int nextLevel = atom->string().toInt(); if (sectionNumber.size() < nextLevel) { do { sectionNumber.append("1"); } while (sectionNumber.size() < nextLevel); } else { while (sectionNumber.size() > nextLevel) { sectionNumber.removeLast(); } sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1); } out() << "\n"; } #else out() << "\n"; #endif break; case Atom::SectionRight: break; case Atom::SectionHeadingLeft: out() << "string().toInt() + hOffset(relative)) + ">"; inSectionHeading = true; break; case Atom::SectionHeadingRight: out() << "string().toInt() + hOffset(relative)) + ">\n"; inSectionHeading = false; break; case Atom::SidebarLeft: break; case Atom::SidebarRight: break; case Atom::String: if (inLink && !inContents && !inSectionHeading) { generateLink(atom, relative, marker); } else { out() << protect(atom->string()); } break; case Atom::TableLeft: if (in_para) { out() << "

    \n"; in_para = false; } if (!atom->string().isEmpty()) { if (atom->string().contains("%")) out() << "

    string() << "\" " << "align=\"center\" cellpadding=\"2\" " << "cellspacing=\"1\" border=\"0\">\n"; else out() << "

    \n"; } else { out() << "

    \n"; } numTableRows = 0; break; case Atom::TableRight: out() << "

    \n"; break; case Atom::TableHeaderLeft: out() << ""; inTableHeader = true; break; case Atom::TableHeaderRight: out() << ""; if (matchAhead(atom, Atom::TableHeaderLeft)) { skipAhead = 1; out() << "\n"; } else { out() << "\n"; inTableHeader = false; } break; case Atom::TableRowLeft: if (++numTableRows % 2 == 1) out() << ""; else out() << ""; break; case Atom::TableRowRight: out() << "\n"; break; case Atom::TableItemLeft: { if (inTableHeader) out() << "string().split(","); if (spans.size() == 2) { if (spans.at(0) != "1") out() << " colspan=\"" << spans.at(0) << "\""; if (spans.at(1) != "1") out() << " rowspan=\"" << spans.at(1) << "\""; out() << ">"; } if (matchAhead(atom, Atom::ParaLeft)) skipAhead = 1; } break; case Atom::TableItemRight: if (inTableHeader) out() << ""; else out() << ""; if (matchAhead(atom, Atom::ParaLeft)) skipAhead = 1; break; case Atom::TableOfContents: { int numColumns = 1; const Node *node = relative; Doc::SectioningUnit sectioningUnit = Doc::Section4; QStringList params = atom->string().split(","); QString columnText = params.at(0); QStringList pieces = columnText.split(" ", QString::SkipEmptyParts); if (pieces.size() >= 2) { columnText = pieces.at(0); pieces.pop_front(); QString path = pieces.join(" ").trimmed(); node = findNodeForTarget(path, relative, marker, atom); } if (params.size() == 2) { numColumns = qMax(columnText.toInt(), numColumns); sectioningUnit = (Doc::SectioningUnit)params.at(1).toInt(); } if (node) generateTableOfContents(node, marker, sectioningUnit, numColumns, relative); } break; case Atom::Target: out() << "string()) << "\">"; break; case Atom::UnhandledFormat: out() << "<Missing HTML>"; break; case Atom::UnknownCommand: out() << "\\" << protect(atom->string()) << ""; break; #ifdef QDOC_QML case Atom::QmlText: case Atom::EndQmlText: // don't do anything with these. They are just tags. break; #endif default: unknownAtom(atom); } return skipAhead; } void HtmlGenerator::generateClassLikeNode(const InnerNode *inner, CodeMarker *marker) { QList
    sections; QList
    ::ConstIterator s; const ClassNode *classe = 0; const NamespaceNode *namespasse = 0; QString title; QString rawTitle; QString fullTitle; if (inner->type() == Node::Namespace) { namespasse = static_cast(inner); rawTitle = marker->plainName(inner); fullTitle = marker->plainFullName(inner); title = rawTitle + " Namespace Reference"; } else if (inner->type() == Node::Class) { classe = static_cast(inner); rawTitle = marker->plainName(inner); fullTitle = marker->plainFullName(inner); title = rawTitle + " Class Reference"; } DcfSection classSection; classSection.title = title; classSection.ref = linkForNode(inner, 0); classSection.keywords += qMakePair(inner->name(), classSection.ref); Text subtitleText; if (rawTitle != fullTitle) subtitleText << "(" << Atom(Atom::AutoLink, fullTitle) << ")" << Atom(Atom::LineBreak); QString fixedModule = inner->moduleName(); if (fixedModule == "Qt3SupportLight") fixedModule = "Qt3Support"; if (!fixedModule.isEmpty()) subtitleText << "[" << Atom(Atom::AutoLink, fixedModule) << " module]"; if (fixedModule.isEmpty()) { QMultiMap publicGroups = tre->publicGroups(); QList groupNames = publicGroups.values(inner->name()); if (!groupNames.isEmpty()) { qSort(groupNames.begin(), groupNames.end()); subtitleText << "["; for (int j=0; j\n"; QString membersLink = generateListOfAllMemberFile(inner, marker); if (!membersLink.isEmpty()) out() << "
  • " << "List of all members, including inherited members
  • \n"; QString obsoleteLink = generateLowStatusMemberFile(inner, marker, CodeMarker::Obsolete); if (!obsoleteLink.isEmpty()) out() << "
  • " << "Obsolete members
  • \n"; QString compatLink = generateLowStatusMemberFile(inner, marker, CodeMarker::Compat); if (!compatLink.isEmpty()) out() << "
  • " << "Qt 3 support members
  • \n"; out() << "
\n"; bool needOtherSection = false; sections = marker->sections(inner, CodeMarker::Summary, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { if (s->members.isEmpty()) { if (!s->inherited.isEmpty()) needOtherSection = true; } else { out() << "\n"; out() << "

" << protect((*s).name) << "

\n"; generateSectionList(*s, inner, marker, CodeMarker::Summary); } ++s; } if (needOtherSection) { out() << "

Additional Inherited Members

\n" "
    \n"; s = sections.begin(); while (s != sections.end()) { if (s->members.isEmpty() && !s->inherited.isEmpty()) generateSectionInheritedList(*s, inner, marker); ++s; } out() << "
\n"; } out() << "\n"; if (!inner->doc().isEmpty()) { out() << "
\n" << "

" << "Detailed Description" << "

\n"; generateBody(inner, marker); generateAlsoList(inner, marker); } sections = marker->sections(inner, CodeMarker::Detailed, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { out() << "
\n"; out() << "

" << protect((*s).name) << "

\n"; NodeList::ConstIterator m = (*s).members.begin(); while (m != (*s).members.end()) { if ((*m)->access() != Node::Private) { // ### check necessary? if ((*m)->type() != Node::Class) generateDetailedMember(*m, inner, marker); else { out() << "

class "; generateFullName(*m, inner, marker); out() << "

"; generateBrief(*m, marker, inner); } QStringList names; names << (*m)->name(); if ((*m)->type() == Node::Function) { const FunctionNode *func = reinterpret_cast(*m); if (func->metaness() == FunctionNode::Ctor || func->metaness() == FunctionNode::Dtor || func->overloadNumber() != 1) names.clear(); } else if ((*m)->type() == Node::Property) { const PropertyNode *prop = reinterpret_cast(*m); if (!prop->getters().isEmpty() && !names.contains(prop->getters().first()->name())) names << prop->getters().first()->name(); if (!prop->setters().isEmpty()) names << prop->setters().first()->name(); if (!prop->resetters().isEmpty()) names << prop->resetters().first()->name(); } else if ((*m)->type() == Node::Enum) { const EnumNode *enume = reinterpret_cast(*m); if (enume->flagsType()) names << enume->flagsType()->name(); foreach (const QString &enumName, enume->doc().enumItemNames().toSet() - enume->doc().omitEnumItemNames().toSet()) names << plainCode(marker->markedUpEnumValue(enumName, enume)); } foreach (const QString &name, names) classSection.keywords += qMakePair(name, linkForNode(*m, 0)); } ++m; } ++s; } generateFooter(inner); if (!membersLink.isEmpty()) { DcfSection membersSection; membersSection.title = "List of all members"; membersSection.ref = membersLink; appendDcfSubSection(&classSection, membersSection); } if (!obsoleteLink.isEmpty()) { DcfSection obsoleteSection; obsoleteSection.title = "Obsolete members"; obsoleteSection.ref = obsoleteLink; appendDcfSubSection(&classSection, obsoleteSection); } if (!compatLink.isEmpty()) { DcfSection compatSection; compatSection.title = "Qt 3 support members"; compatSection.ref = compatLink; appendDcfSubSection(&classSection, compatSection); } appendDcfSubSection(&dcfClassesRoot, classSection); } void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) { SubTitleSize subTitleSize = LargeSubTitle; DcfSection fakeSection; fakeSection.title = fake->fullTitle(); fakeSection.ref = linkForNode(fake, 0); QList
sections; QList
::const_iterator s; QString htmlTitle = fake->fullTitle(); if (fake->subType() == FakeNode::File && !fake->subTitle().isEmpty()) { subTitleSize = SmallSubTitle; htmlTitle += " (" + fake->subTitle() + ")"; } generateHeader(htmlTitle, fake, marker, true); generateTitle(fake->fullTitle(), Text() << fake->subTitle(), subTitleSize, fake, marker); if (fake->subType() == FakeNode::Module) { // Generate brief text and status for modules. generateBrief(fake, marker); generateStatus(fake, marker); if (moduleNamespaceMap.contains(fake->name())) { out() << "

Namespaces

\n"; generateAnnotatedList(fake, marker, moduleNamespaceMap[fake->name()]); } if (moduleClassMap.contains(fake->name())) { out() << "

Classes

\n"; generateAnnotatedList(fake, marker, moduleClassMap[fake->name()]); } } else if (fake->subType() == FakeNode::HeaderFile) { // Generate brief text and status for modules. generateBrief(fake, marker); generateStatus(fake, marker); out() << "\n"; if (!membersLink.isEmpty()) { DcfSection membersSection; membersSection.title = "List of all members"; membersSection.ref = membersLink; appendDcfSubSection(&fakeSection, membersSection); } if (!obsoleteLink.isEmpty()) { DcfSection obsoleteSection; obsoleteSection.title = "Obsolete members"; obsoleteSection.ref = obsoleteLink; appendDcfSubSection(&fakeSection, obsoleteSection); } if (!compatLink.isEmpty()) { DcfSection compatSection; compatSection.title = "Qt 3 support members"; compatSection.ref = compatLink; appendDcfSubSection(&fakeSection, compatSection); } } sections = marker->sections(fake, CodeMarker::Summary, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { out() << "\n"; out() << "

" << protect((*s).name) << "

\n"; generateSectionList(*s, fake, marker, CodeMarker::Summary); ++s; } Text brief = fake->doc().briefText(); if (fake->subType() == FakeNode::Module && !brief.isEmpty()) { out() << "\n"; out() << "

" << "Detailed Description" << "

\n"; } generateBody(fake, marker); #ifdef QDOC_QML if (fake->subType() == FakeNode::QmlClass) { //qDebug() << "generateFakeNode(): QML CLASS" << fake->name(); const QmlNode* qmlNode = static_cast(fake); const ClassNode* cn = qmlNode->classNode(); if (cn) { //qDebug() << " CPP CLASS" << cn->name(); generateQmlText(cn->doc().body(), cn, marker); } } #endif generateAlsoList(fake, marker); if (!fake->groupMembers().isEmpty()) { QMap groupMembersMap; foreach (const Node *node, fake->groupMembers()) { if (node->type() == Node::Class || node->type() == Node::Namespace) groupMembersMap[node->name()] = node; } generateAnnotatedList(fake, marker, groupMembersMap); } fakeSection.keywords += qMakePair(fakeSection.title, fakeSection.ref); sections = marker->sections(fake, CodeMarker::Detailed, CodeMarker::Okay); s = sections.begin(); while (s != sections.end()) { out() << "
\n"; out() << "

" << protect((*s).name) << "

\n"; NodeList::ConstIterator m = (*s).members.begin(); while (m != (*s).members.end()) { generateDetailedMember(*m, fake, marker); fakeSection.keywords += qMakePair((*m)->name(), linkForNode(*m, 0)); ++m; } ++s; } generateFooter(fake); if (fake->subType() == FakeNode::Example) { appendDcfSubSection(&dcfExamplesRoot, fakeSection); } else if (fake->subType() != FakeNode::File) { QString contentsPage = fake->links().value(Node::ContentsLink).first; if (contentsPage == "Qt Designer Manual") { appendDcfSubSection(&dcfDesignerRoot, fakeSection); } else if (contentsPage == "Qt Linguist Manual") { appendDcfSubSection(&dcfLinguistRoot, fakeSection); } else if (contentsPage == "Qt Assistant Manual") { appendDcfSubSection(&dcfAssistantRoot, fakeSection); } else if (contentsPage == "qmake Manual") { appendDcfSubSection(&dcfQmakeRoot, fakeSection); } else { appendDcfSubSection(&dcfOverviewsRoot, fakeSection); } } } QString HtmlGenerator::fileExtension(const Node * /* node */) { return "html"; } void HtmlGenerator::generateHeader(const QString& title, const Node *node, CodeMarker *marker, bool mainPage) { out() << "\n"; out() << "\n" "\n"; QString shortVersion; if ((project != "Qtopia") && (project != "Qt Extended")) { shortVersion = project + " " + shortVersion + ": "; if (node && !node->doc().location().isEmpty()) out() << "\n"; shortVersion = tre->version(); if (shortVersion.count(QChar('.')) == 2) shortVersion.truncate(shortVersion.lastIndexOf(QChar('.'))); if (!shortVersion.isEmpty()) { if (project == "QSA") shortVersion = "QSA " + shortVersion + ": "; else shortVersion = "Qt " + shortVersion + ": "; } } out() << "\n" " " << shortVersion << protect(title) << "\n"; if (!style.isEmpty()) out() << " \n"; const QMap &metaMap = node->doc().metaTagMap(); if (!metaMap.isEmpty()) { QMapIterator i(metaMap); while (i.hasNext()) { i.next(); out() << " \n"; } } navigationLinks.clear(); if (node && !node->links().empty()) { QPair linkPair; QPair anchorPair; const Node *linkNode; if (node->links().contains(Node::PreviousLink)) { linkPair = node->links()[Node::PreviousLink]; linkNode = findNodeForTarget(linkPair.first, node, marker); if (!linkNode || linkNode == node) anchorPair = linkPair; else anchorPair = anchorForNode(linkNode); out() << " \n"; navigationLinks += "[Previous: "; if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty()) navigationLinks += protect(anchorPair.second); else navigationLinks += protect(linkPair.second); navigationLinks += "]\n"; } if (node->links().contains(Node::ContentsLink)) { linkPair = node->links()[Node::ContentsLink]; linkNode = findNodeForTarget(linkPair.first, node, marker); if (!linkNode || linkNode == node) anchorPair = linkPair; else anchorPair = anchorForNode(linkNode); out() << " \n"; navigationLinks += "["; if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty()) navigationLinks += protect(anchorPair.second); else navigationLinks += protect(linkPair.second); navigationLinks += "]\n"; } if (node->links().contains(Node::NextLink)) { linkPair = node->links()[Node::NextLink]; linkNode = findNodeForTarget(linkPair.first, node, marker); if (!linkNode || linkNode == node) anchorPair = linkPair; else anchorPair = anchorForNode(linkNode); out() << " \n"; navigationLinks += "[Next: "; if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty()) navigationLinks += protect(anchorPair.second); else navigationLinks += protect(linkPair.second); navigationLinks += "]\n"; } if (node->links().contains(Node::IndexLink)) { linkPair = node->links()[Node::IndexLink]; linkNode = findNodeForTarget(linkPair.first, node, marker); if (!linkNode || linkNode == node) anchorPair = linkPair; else anchorPair = anchorForNode(linkNode); out() << " \n"; } if (node->links().contains(Node::StartLink)) { linkPair = node->links()[Node::StartLink]; linkNode = findNodeForTarget(linkPair.first, node, marker); if (!linkNode || linkNode == node) anchorPair = linkPair; else anchorPair = anchorForNode(linkNode); out() << " \n"; } } foreach (const QString &stylesheet, stylesheets) { out() << " \n"; } foreach (const QString &customHeadElement, customHeadElements) { out() << " " << customHeadElement << "\n"; } out() << "\n" "\n"; if (mainPage) generateMacRef(node, marker); out() << QString(postHeader).replace("\\" + COMMAND_VERSION, tre->version()); if (node && !node->links().empty()) out() << "

\n" << navigationLinks << "

\n"; } void HtmlGenerator::generateTitle(const QString& title, const Text &subTitle, SubTitleSize subTitleSize, const Node *relative, CodeMarker *marker) { out() << "

" << protect(title); if (!subTitle.isEmpty()) { out() << "
"; if (subTitleSize == SmallSubTitle) out() << ""; else out() << ""; generateText(subTitle, relative, marker); out() << "\n"; } out() << "

\n"; } void HtmlGenerator::generateFooter(const Node *node) { if (node && !node->links().empty()) out() << "

\n" << navigationLinks << "

\n"; out() << QString(footer).replace("\\" + COMMAND_VERSION, tre->version()) << QString(address).replace("\\" + COMMAND_VERSION, tre->version()) << "\n" "\n"; } void HtmlGenerator::generateBrief(const Node *node, CodeMarker *marker, const Node *relative) { Text brief = node->doc().briefText(); if (!brief.isEmpty()) { out() << "

"; generateText(brief, node, marker); if (!relative || node == relative) out() << " More...

\n"; } } void HtmlGenerator::generateIncludes(const InnerNode *inner, CodeMarker *marker) { if (!inner->includes().isEmpty()) { out() << "
" << trimmedTrailing(highlightedCode(indent(codeIndent,
                                                                   marker->markedUpIncludes(
                                                                        inner->includes())),
                                                                        marker, inner))
              << "
"; } } void HtmlGenerator::generateTableOfContents(const Node *node, CodeMarker *marker, Doc::SectioningUnit sectioningUnit, int numColumns, const Node *relative) { if (!node->doc().hasTableOfContents()) return; QList toc = node->doc().tableOfContents(); if (toc.isEmpty()) return; QString nodeName = ""; if (node != relative) nodeName = node->name(); QStringList sectionNumber; int columnSize = 0; QString tdTag; if (numColumns > 1) { tdTag = ""; out() << "

\n" << tdTag << "\n"; } // disable nested links in table of contents inContents = true; inLink = true; for (int i = 0; i < toc.size(); ++i) { Atom *atom = toc.at(i); int nextLevel = atom->string().toInt(); if (nextLevel > (int)sectioningUnit) continue; if (sectionNumber.size() < nextLevel) { do { out() << "
    "; sectionNumber.append("1"); } while (sectionNumber.size() < nextLevel); } else { while (sectionNumber.size() > nextLevel) { out() << "
\n"; sectionNumber.removeLast(); } sectionNumber.last() = QString::number(sectionNumber.last().toInt() + 1); } int numAtoms; Text headingText = Text::sectionHeading(atom); if (sectionNumber.size() == 1 && columnSize > toc.size() / numColumns) { out() << "" << tdTag << "\n"; sectionNumber.removeLast(); } if (numColumns > 1) out() << "

\n"; inContents = false; inLink = false; } #if 0 void HtmlGenerator::generateNavigationBar(const NavigationBar& bar, const Node *node, CodeMarker *marker) { if (bar.prev.begin() != 0 || bar.current.begin() != 0 || bar.next.begin() != 0) { out() << "

"; if (bar.prev.begin() != 0) { #if 0 out() << "[Prev: "; generateText(section.previousHeading(), node, marker); out() << "]\n"; #endif } if (bar.current.begin() != 0) { out() << "[Home]\n"; } if (bar.next.begin() != 0) { out() << "[Next: "; generateText(Text::sectionHeading(bar.next.begin()), node, marker); out() << "]\n"; } out() << "

\n"; } } #endif QString HtmlGenerator::generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker) { QList
sections; QList
::ConstIterator s; sections = marker->sections(inner, CodeMarker::SeparateList, CodeMarker::Okay); if (sections.isEmpty()) return QString(); QString fileName = fileBase(inner) + "-members." + fileExtension(inner); beginSubPage(inner->location(), fileName); QString title = "List of All Members for " + inner->name(); generateHeader(title, inner, marker, false); generateTitle(title, Text(), SmallSubTitle, inner, marker); out() << "

This is the complete list of members for "; generateFullName(inner, 0, marker); out() << ", including inherited members.

\n"; Section section = sections.first(); generateSectionList(section, 0, marker, CodeMarker::SeparateList); generateFooter(); endSubPage(); return fileName; } QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner, CodeMarker *marker, CodeMarker::Status status) { QList
sections = marker->sections(inner, CodeMarker::Summary, status); QMutableListIterator
j(sections); while (j.hasNext()) { if (j.next().members.size() == 0) j.remove(); } if (sections.isEmpty()) return QString(); int i; QString title; QString fileName; if (status == CodeMarker::Compat) { title = "Qt 3 Support Members for " + inner->name(); fileName = fileBase(inner) + "-qt3." + fileExtension(inner); } else { title = "Obsolete Members for " + inner->name(); fileName = fileBase(inner) + "-obsolete." + fileExtension(inner); } beginSubPage(inner->location(), fileName); generateHeader(title, inner, marker, false); generateTitle(title, Text(), SmallSubTitle, inner, marker); if (status == CodeMarker::Compat) { out() << "

The following class members are part of the " "Qt 3 support layer. " "They are provided to help you port old code to Qt 4. We advise against " "using them in new code.

\n"; } else { out() << "

The following class members are obsolete. They are provided to keep " "old source code working. We strongly advise against using them in new " "code.

\n"; } out() << "

\n"; for (i = 0; i < sections.size(); ++i) { out() << "

" << protect(sections.at(i).name) << "

\n"; generateSectionList(sections.at(i), inner, marker, CodeMarker::Summary); } sections = marker->sections(inner, CodeMarker::Detailed, status); for (i = 0; i < sections.size(); ++i) { out() << "
\n"; out() << "

" << protect(sections.at(i).name) << "

\n"; NodeList::ConstIterator m = sections.at(i).members.begin(); while (m != sections.at(i).members.end()) { if ((*m)->access() != Node::Private) generateDetailedMember(*m, inner, marker); ++m; } } generateFooter(); endSubPage(); return fileName; } void HtmlGenerator::generateClassHierarchy(const Node *relative, CodeMarker *marker, const QMap &classMap) { if (classMap.isEmpty()) return; QMap topLevel; QMap::ConstIterator c = classMap.begin(); while (c != classMap.end()) { const ClassNode *classe = static_cast(*c); if (classe->baseClasses().isEmpty()) topLevel.insert(classe->name(), classe); ++c; } QStack > stack; stack.push(topLevel); out() << "
    \n"; while (!stack.isEmpty()) { if (stack.top().isEmpty()) { stack.pop(); out() << "
\n"; } else { const ClassNode *child = static_cast(*stack.top().begin()); out() << "
  • "; generateFullName(child, relative, marker); out() << "
  • \n"; stack.top().erase(stack.top().begin()); QMap newTop; foreach (const RelatedClass &d, child->derivedClasses()) { if (d.access != Node::Private) newTop.insert(d.node->name(), d.node); } if (!newTop.isEmpty()) { stack.push(newTop); out() << "
      \n"; } } } } void HtmlGenerator::generateAnnotatedList(const Node *relative, CodeMarker *marker, const QMap &nodeMap) { out() << "

      \n"; int row = 0; foreach (const QString &name, nodeMap.keys()) { const Node *node = nodeMap[name]; if (++row % 2 == 1) out() << ""; else out() << ""; out() << ""; if (!(node->type() == Node::Fake)) { Text brief = node->doc().trimmedBriefText(name); if (!brief.isEmpty()) { out() << ""; } } else { out() << ""; } out() << "\n"; } out() << "
      "; generateFullName(node, relative, marker); out() << ""; generateText(brief, node, marker); out() << ""; out() << protect(node->doc().briefText().toString()); out() << "

      \n"; } void HtmlGenerator::generateCompactList(const Node *relative, CodeMarker *marker, const QMap &classMap) { const int NumParagraphs = 37; // '0' to '9', 'A' to 'Z', '_' const int NumColumns = 4; // number of columns in the result if (classMap.isEmpty()) return; /* First, find out the common prefix of all non-namespaced classes. For Qt, the prefix is Q. It can easily be derived from the first and last classes in alphabetical order (QAccel and QXtWidget in Qt 2.1). */ int commonPrefixLen = 0; QString commonPrefix; QString first; QString last; QMap::const_iterator iter = classMap.begin(); while (iter != classMap.end()) { if (!iter.key().contains("::")) { first = iter.key(); break; } ++iter; } if (first.isEmpty()) first = classMap.begin().key(); iter = classMap.end(); while (iter != classMap.begin()) { --iter; if (!iter.key().contains("::")) { last = iter.key(); break; } } if (last.isEmpty()) last = classMap.begin().key(); if (classMap.size() > 1) { while (commonPrefixLen < first.length() + 1 && commonPrefixLen < last.length() + 1 && first[commonPrefixLen] == last[commonPrefixLen]) ++commonPrefixLen; } commonPrefix = first.left(commonPrefixLen); /* Divide the data into 37 paragraphs: 0, ..., 9, A, ..., Z, underscore (_). QAccel will fall in paragraph 10 (A) and QXtWidget in paragraph 33 (X). This is the only place where we assume that NumParagraphs is 37. Each paragraph is a QMap. */ QMap paragraph[NumParagraphs]; QString paragraphName[NumParagraphs]; QMap::ConstIterator c = classMap.begin(); while (c != classMap.end()) { QStringList pieces = c.key().split("::"); QString key; if (pieces.size() == 1) key = pieces.last().mid(commonPrefixLen).toLower(); else key = pieces.last().toLower(); int paragraphNo = NumParagraphs - 1; if (key[0].digitValue() != -1) { paragraphNo = key[0].digitValue(); } else if (key[0] >= QLatin1Char('a') && key[0] <= QLatin1Char('z')) { paragraphNo = 10 + key[0].unicode() - 'a'; } paragraphName[paragraphNo] = key[0].toUpper(); paragraph[paragraphNo].insert(key, c.value()); ++c; } /* Each paragraph j has a size: paragraph[j].count(). In the discussion, we will assume paragraphs 0 to 5 will have sizes 3, 1, 4, 1, 5, 9. We now want to compute the paragraph offset. Paragraphs 0 to 6 start at offsets 0, 3, 4, 8, 9, 14, 23. */ int paragraphOffset[NumParagraphs + 1]; int i, j, k; paragraphOffset[0] = 0; for (j = 0; j < NumParagraphs; j++) paragraphOffset[j + 1] = paragraphOffset[j] + paragraph[j].count(); int firstOffset[NumColumns + 1]; int currentOffset[NumColumns]; int currentParagraphNo[NumColumns]; int currentOffsetInParagraph[NumColumns]; int numRows = (classMap.count() + NumColumns - 1) / NumColumns; int curParagNo = 0; for (i = 0; i < NumColumns; i++) { firstOffset[i] = qMin(i * numRows, classMap.size()); currentOffset[i] = firstOffset[i]; for (j = curParagNo; j < NumParagraphs; j++) { if (paragraphOffset[j] > firstOffset[i]) break; if (paragraphOffset[j] <= firstOffset[i]) curParagNo = j; } currentParagraphNo[i] = curParagNo; currentOffsetInParagraph[i] = firstOffset[i] - paragraphOffset[curParagNo]; } firstOffset[NumColumns] = classMap.count(); out() << "

      \n"; for (k = 0; k < numRows; k++) { out() << "\n"; for (i = 0; i < NumColumns; i++) { if (currentOffset[i] >= firstOffset[i + 1]) { // this column is finished out() << "\n"; } else { while (currentOffsetInParagraph[i] == paragraph[currentParagraphNo[i]].count()) { ++currentParagraphNo[i]; currentOffsetInParagraph[i] = 0; } out() << "\n"; // bad loop QMap::Iterator it; it = paragraph[currentParagraphNo[i]].begin(); for (j = 0; j < currentOffsetInParagraph[i]; j++) ++it; out() << "\n"; currentOffset[i]++; currentOffsetInParagraph[i]++; } } out() << "\n"; } out() << "
      \n"; if (currentOffsetInParagraph[i] == 0) { // start a new paragraph out() << "" << paragraphName[currentParagraphNo[i]] << " "; } out() << ""; // Previously, we used generateFullName() for this, but we // require some special formatting. out() << ""; QStringList pieces = fullName(it.value(), relative, marker).split("::"); out() << protect(pieces.last()); out() << ""; if (pieces.size() > 1) { out() << " ("; generateFullName(it.value()->parent(), relative, marker); out() << ")"; } out() << "

      \n"; } void HtmlGenerator::generateFunctionIndex(const Node *relative, CodeMarker *marker) { out() << "

      "; for (int i = 0; i < 26; i++) { QChar ch('a' + i); out() << QString("%2 ").arg(ch).arg(ch.toUpper()); } out() << "

      \n"; char nextLetter = 'a'; char currentLetter; #if 1 out() << "
        \n"; #endif QMap >::ConstIterator f = funcIndex.begin(); while (f != funcIndex.end()) { #if 1 out() << "
      • "; #else out() << "

        "; #endif out() << protect(f.key()) << ":"; currentLetter = f.key()[0].unicode(); while (islower(currentLetter) && currentLetter >= nextLetter) { out() << QString("").arg(nextLetter); nextLetter++; } QMap::ConstIterator s = (*f).begin(); while (s != (*f).end()) { out() << " "; generateFullName((*s)->parent(), relative, marker, *s); ++s; } #if 1 out() << "

      • "; #else out() << "

        "; #endif out() << "\n"; ++f; } #if 1 out() << "
      \n"; #endif } void HtmlGenerator::generateLegaleseList(const Node *relative, CodeMarker *marker) { QMap::ConstIterator it = legaleseTexts.begin(); while (it != legaleseTexts.end()) { Text text = it.key(); out() << "
      \n"; generateText(text, relative, marker); out() << "
        \n"; do { out() << "
      • "; generateFullName(it.value(), relative, marker); out() << "
      • \n"; ++it; } while (it != legaleseTexts.end() && it.key() == text); out() << "
      \n"; } } void HtmlGenerator::generateSynopsis(const Node *node, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style) { QString marked = marker->markedUpSynopsis(node, relative, style); QRegExp templateTag("(<[^@>]*>)"); if (marked.indexOf(templateTag) != -1) { QString contents = protect(marked.mid(templateTag.pos(1), templateTag.cap(1).length())); marked.replace(templateTag.pos(1), templateTag.cap(1).length(), contents); } marked.replace(QRegExp("<@param>([a-z]+)_([1-9n])"), "\\1\\2"); marked.replace("<@param>", ""); marked.replace("", ""); if (style == CodeMarker::Summary) marked.replace("@name>", "b>"); if (style == CodeMarker::SeparateList) { QRegExp extraRegExp("<@extra>.*"); extraRegExp.setMinimal(true); marked.replace(extraRegExp, ""); } else { marked.replace("<@extra>", "  "); marked.replace("", ""); } if (style != CodeMarker::Detailed) { marked.replace("<@type>", ""); marked.replace("", ""); } out() << highlightedCode(marked, marker, relative); } void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* marker */) { QMap > fakeNodeMap; QMap groupTitlesMap; QMap uncategorizedNodeMap; QRegExp singleDigit("\\b([0-9])\\b"); const NodeList children = tre->root()->childNodes(); foreach (Node *child, children) { if (child->type() == Node::Fake && child != relative) { FakeNode *fakeNode = static_cast(child); // Check whether the page is part of a group or is the group // definition page. QString group; bool isGroupPage = false; if (fakeNode->doc().metaCommandsUsed().contains("group")) { group = fakeNode->doc().metaCommandArgs("group")[0]; isGroupPage = true; } // there are too many examples; they would clutter the list if (fakeNode->subType() == FakeNode::Example) continue; // not interested either in individual (Qt Designer etc.) manual chapters if (fakeNode->links().contains(Node::ContentsLink)) continue; // Discard external nodes. if (fakeNode->subType() == FakeNode::ExternalPage) continue; QString sortKey = fakeNode->fullTitle().toLower(); if (sortKey.startsWith("the ")) sortKey.remove(0, 4); sortKey.replace(singleDigit, "0\\1"); if (!group.isEmpty()) { if (isGroupPage) { // If we encounter a group definition page, we add all // the pages in that group to the list for that group. foreach (Node *member, fakeNode->groupMembers()) { if (member->type() != Node::Fake) continue; FakeNode *page = static_cast(member); if (page) { QString sortKey = page->fullTitle().toLower(); if (sortKey.startsWith("the ")) sortKey.remove(0, 4); sortKey.replace(singleDigit, "0\\1"); fakeNodeMap[const_cast(fakeNode)].insert(sortKey, page); groupTitlesMap[fakeNode->fullTitle()] = const_cast(fakeNode); } } } else if (!isGroupPage) { // If we encounter a page that belongs to a group then // we add that page to the list for that group. const FakeNode *groupNode = static_cast(tre->root()->findNode(group, Node::Fake)); if (groupNode) fakeNodeMap[groupNode].insert(sortKey, fakeNode); //else // uncategorizedNodeMap.insert(sortKey, fakeNode); }// else // uncategorizedNodeMap.insert(sortKey, fakeNode); }// else // uncategorizedNodeMap.insert(sortKey, fakeNode); } } // We now list all the pages found that belong to groups. // If only certain pages were found for a group, but the definition page // for that group wasn't listed, the list of pages will be intentionally // incomplete. However, if the group definition page was listed, all the // pages in that group are listed for completeness. if (!fakeNodeMap.isEmpty()) { foreach (const QString &groupTitle, groupTitlesMap.keys()) { const FakeNode *groupNode = groupTitlesMap[groupTitle]; out() << QString("

      %2

      \n").arg( linkForNode(groupNode, relative)).arg( protect(groupNode->fullTitle())); if (fakeNodeMap[groupNode].count() == 0) continue; out() << "
        \n"; foreach (const FakeNode *fakeNode, fakeNodeMap[groupNode]) { QString title = fakeNode->fullTitle(); if (title.startsWith("The ")) title.remove(0, 4); out() << "
      • " << protect(title) << "
      • \n"; } out() << "
      \n"; } } if (!uncategorizedNodeMap.isEmpty()) { out() << QString("

      Miscellaneous

      \n"); out() << "
        \n"; foreach (const FakeNode *fakeNode, uncategorizedNodeMap) { QString title = fakeNode->fullTitle(); if (title.startsWith("The ")) title.remove(0, 4); out() << "
      • " << protect(title) << "
      • \n"; } out() << "
      \n"; } } void HtmlGenerator::generateSectionList(const Section& section, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style) { if (!section.members.isEmpty()) { bool twoColumn = false; if (style == CodeMarker::SeparateList) { twoColumn = (section.members.count() >= 16); } else if (section.members.first()->type() == Node::Property) { twoColumn = (section.members.count() >= 5); } if (twoColumn) out() << "

      \n" << "\n
      "; out() << "
        \n"; int i = 0; NodeList::ConstIterator m = section.members.begin(); while (m != section.members.end()) { if ((*m)->access() == Node::Private) { ++m; continue; } if (twoColumn && i == (int) (section.members.count() + 1) / 2) out() << "
        \n"; out() << "
      • "; if (style == CodeMarker::Accessors) out() << ""; generateSynopsis(*m, relative, marker, style); if (style == CodeMarker::Accessors) out() << ""; out() << "
      • \n"; i++; ++m; } out() << "
      \n"; if (twoColumn) out() << "

      \n"; } if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { out() << "
        \n"; generateSectionInheritedList(section, relative, marker); out() << "
      \n"; } } void HtmlGenerator::generateSectionInheritedList(const Section& section, const Node *relative, CodeMarker *marker) { QList >::ConstIterator p = section.inherited.begin(); while (p != section.inherited.end()) { out() << "
    • "; out() << (*p).second << " "; if ((*p).second == 1) { out() << section.singularMember; } else { out() << section.pluralMember; } out() << " inherited from " << protect(marker->plainFullName((*p).first, relative)) << "
    • \n"; ++p; } } void HtmlGenerator::generateLink(const Atom *atom, const Node * /* relative */, CodeMarker *marker) { static QRegExp camelCase("[A-Z][A-Z][a-z]|[a-z][A-Z0-9]|_"); if (funcLeftParen.indexIn(atom->string()) != -1 && marker->recognizeLanguage("Cpp")) { // hack for C++: move () outside of link int k = funcLeftParen.pos(1); out() << protect(atom->string().left(k)); if (link.isEmpty()) { if (showBrokenLinks) out() << ""; } else { out() << ""; } inLink = false; out() << protect(atom->string().mid(k)); } else if (marker->recognizeLanguage("Java")) { // hack for Java: remove () and use when appropriate bool func = atom->string().endsWith("()"); bool tt = (func || atom->string().contains(camelCase)); if (tt) out() << ""; if (func) { out() << protect(atom->string().left(atom->string().length() - 2)); } else { out() << protect(atom->string()); } out() << ""; } else { out() << protect(atom->string()); } } QString HtmlGenerator::cleanRef(const QString& ref) { QString clean; if (ref.isEmpty()) return clean; clean.reserve(ref.size() + 20); const QChar c = ref[0]; const uint u = c.unicode(); if ((u >= 'a' && u <= 'z') || (u >= 'A' && u <= 'Z') || (u >= '0' && u <= '9')) { clean += c; } else if (u == '~') { clean += "dtor."; } else if (u == '_') { clean += "underscore."; } else { clean += "A"; } for (int i = 1; i < (int) ref.length(); i++) { const QChar c = ref[i]; const uint u = c.unicode(); if ((u >= 'a' && u <= 'z') || (u >= 'A' && u <= 'Z') || (u >= '0' && u <= '9') || u == '-' || u == '_' || u == ':' || u == '.') { clean += c; } else if (c.isSpace()) { clean += "-"; } else if (u == '!') { clean += "-not"; } else if (u == '&') { clean += "-and"; } else if (u == '<') { clean += "-lt"; } else if (u == '=') { clean += "-eq"; } else if (u == '>') { clean += "-gt"; } else if (u == '#') { clean += "#"; } else { clean += "-"; clean += QString::number((int)u, 16); } } return clean; } QString HtmlGenerator::registerRef(const QString& ref) { QString clean = HtmlGenerator::cleanRef(ref); for (;;) { QString& prevRef = refMap[clean.toLower()]; if (prevRef.isEmpty()) { prevRef = ref; break; } else if (prevRef == ref) { break; } clean += "x"; } return clean; } QString HtmlGenerator::protect(const QString& string) { #define APPEND(x) \ if (html.isEmpty()) { \ html = string; \ html.truncate(i); \ } \ html += (x); QString html; int n = string.length(); for (int i = 0; i < n; ++i) { QChar ch = string.at(i); if (ch == QLatin1Char('&')) { APPEND("&"); } else if (ch == QLatin1Char('<')) { APPEND("<"); } else if (ch == QLatin1Char('>')) { APPEND(">"); } else if (ch == QLatin1Char('"')) { APPEND("""); } else if (ch.unicode() > 0x007F || (ch == QLatin1Char('*') && i + 1 < n && string.at(i) == QLatin1Char('/')) || (ch == QLatin1Char('.') && i > 2 && string.at(i - 2) == QLatin1Char('.'))) { // we escape '*/' and the last dot in 'e.g.' and 'i.e.' for the Javadoc generator APPEND("&#x"); html += QString::number(ch.unicode(), 16); html += QLatin1Char(';'); } else { if (!html.isEmpty()) html += ch; } } if (!html.isEmpty()) return html; return string; #undef APPEND } static QRegExp linkTag("(<@link node=\"([^\"]+)\">).*()"); static QRegExp funcTag("(<@func target=\"([^\"]*)\">)(.*)()"); static QRegExp typeTag("(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)()"); static QRegExp spanTag(""); static QRegExp unknownTag("]*>"); bool parseArg(const QString &src, const QString &tag, int *pos, int n, QStringRef *contents, QStringRef *par1 = 0, bool debug = false) { #define SKIP_CHAR(c) \ if (debug) \ qDebug() << "looking for " << c << " at " << QString(src.data() + i, n - i); \ if (i >= n || src[i] != c) { \ if (debug) \ qDebug() << " char '" << c << "' not found"; \ return false; \ } \ ++i; #define SKIP_SPACE \ while (i < n && src[i] == ' ') \ ++i; int i = *pos; int j = i; // assume "<@" has been parsed outside //SKIP_CHAR('<'); //SKIP_CHAR('@'); if (tag != QStringRef(&src, i, tag.length())) { if (0 && debug) qDebug() << "tag " << tag << " not found at " << i; return false; } if (debug) qDebug() << "haystack:" << src << "needle:" << tag << "i:" <).*()"); if (par1) { SKIP_SPACE; // read parameter name j = i; while (i < n && src[i].isLetter()) ++i; if (src[i] == '=') { if (debug) qDebug() << "read parameter" << QString(src.data() + j, i - j); SKIP_CHAR('='); SKIP_CHAR('"'); // skip parameter name j = i; while (i < n && src[i] != '"') ++i; *par1 = QStringRef(&src, j, i - j); SKIP_CHAR('"'); SKIP_SPACE; } else { if (debug) qDebug() << "no optional parameter found"; } } SKIP_SPACE; SKIP_CHAR('>'); // find contents up to closing " j = i; for (; true; ++i) { if (i + 4 + tag.length() > n) return false; if (src[i] != '<') continue; if (src[i + 1] != '/') continue; if (src[i + 2] != '@') continue; if (tag != QStringRef(&src, i + 3, tag.length())) continue; if (src[i + 3 + tag.length()] != '>') continue; break; } *contents = QStringRef(&src, j, i - j); i += tag.length() + 4; *pos = i; if (debug) qDebug() << " tag " << tag << " found: pos now: " << i; return true; #undef SKIP_CHAR } static void addLink(const QString &linkTarget, const QStringRef &nestedStuff, QString *res) { if (!linkTarget.isEmpty()) { *res += ""; *res += nestedStuff; *res += ""; } else { *res += nestedStuff; } } QString HtmlGenerator::highlightedCode(const QString& markedCode, CodeMarker *marker, const Node *relative) { QString src = markedCode; QString html; QStringRef arg; QStringRef par1; const QChar charLangle = '<'; const QChar charAt = '@'; // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*()" static const QString linkTag("link"); for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle && src.at(i + 1) == charAt) { i += 2; if (parseArg(src, linkTag, &i, n, &arg, &par1)) { QString link = linkForNode( CodeMarker::nodeForString(par1.toString()), relative); addLink(link, arg, &html); } else { html += charLangle; html += charAt; } } else { html += src.at(i++); } } if (slow) { // is this block ever used at all? // replace all <@func> tags: "(<@func target=\"([^\"]*)\">)(.*)()" src = html; html = QString(); static const QString funcTag("func"); for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle && src.at(i + 1) == charAt) { i += 2; if (parseArg(src, funcTag, &i, n, &arg, &par1)) { QString link = linkForNode( marker->resolveTarget(par1.toString(), tre, relative), relative); addLink(link, arg, &html); par1 = QStringRef(); } else { html += charLangle; html += charAt; } } else { html += src.at(i++); } } } // replace all "(<@(type|headerfile|func)(?: +[^>]*)?>)(.*)()" tags src = html; html = QString(); static const QString typeTags[] = { "type", "headerfile", "func" }; for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle && src.at(i + 1) == charAt) { i += 2; bool handled = false; for (int k = 0; k != 3; ++k) { if (parseArg(src, typeTags[k], &i, n, &arg, &par1)) { par1 = QStringRef(); QString link = linkForNode( marker->resolveTarget(arg.toString(), tre, relative), relative); addLink(link, arg, &html); handled = true; break; } } if (!handled) { html += charLangle; html += charAt; } } else { html += src.at(i++); } } // replace all // "<@comment>" -> ""; // "<@preprocessor>" -> ""; // "<@string>" -> ""; // "<@char>" -> ""; // "" -> "" src = html; html = QString(); static const QString spanTags[] = { "<@comment>", "", "<@preprocessor>", "", "<@string>", "", "<@char>", "", "", "", "","", "", "", "", "" // "<@char>", "", // "", "", // "<@func>", "", // "", "", // "<@id>", "", // "", "", // "<@keyword>", "", // "", "", // "<@number>", "", // "", "", // "<@op>", "", // "", "", // "<@param>", "", // "", "", // "<@string>", "", // "", "", }; for (int i = 0, n = src.size(); i < n;) { if (src.at(i) == charLangle) { bool handled = false; for (int k = 0; k != 8; ++k) { const QString & tag = spanTags[2 * k]; if (tag == QStringRef(&src, i, tag.length())) { html += spanTags[2 * k + 1]; i += tag.length(); handled = true; break; } } if (!handled) { ++i; if (src.at(i) == charAt || (src.at(i) == QLatin1Char('/') && src.at(i + 1) == charAt)) { // drop 'our' unknown tags (the ones still containing '@') while (i < n && src.at(i) != QLatin1Char('>')) ++i; ++i; } else { // retain all others html += charLangle; } } } else { html += src.at(i); ++i; } } return html; } QString HtmlGenerator::fileBase(const Node *node) { QString result; result = PageGenerator::fileBase(node); if (!node->isInnerNode()) { switch (node->status()) { case Node::Compat: result += "-qt3"; break; case Node::Obsolete: result += "-obsolete"; break; default: ; } } return result; } #if 0 QString HtmlGenerator::fileBase(const Node *node, const SectionIterator& section) { QStringList::ConstIterator s = section.sectionNumber().end(); QStringList::ConstIterator b = section.baseNameStack().end(); QString suffix; QString base = fileBase(node); while (s != section.sectionNumber().begin()) { --s; --b; if (!(*b).isEmpty()) { base = *b; break; } suffix.prepend("-" + *s); } return base + suffix; } #endif QString HtmlGenerator::fileName(const Node *node) { if (node->type() == Node::Fake) { if (static_cast(node)->subType() == FakeNode::ExternalPage) return node->name(); } return PageGenerator::fileName(node); } QString HtmlGenerator::refForNode(const Node *node) { const FunctionNode *func; const TypedefNode *typedeffe; QString ref; switch (node->type()) { case Node::Namespace: case Node::Class: default: break; case Node::Enum: ref = node->name() + "-enum"; break; case Node::Typedef: typedeffe = static_cast(node); if (typedeffe->associatedEnum()) { return refForNode(typedeffe->associatedEnum()); } else { ref = node->name() + "-typedef"; } break; case Node::Function: func = static_cast(node); if (func->associatedProperty()) { return refForNode(func->associatedProperty()); } else { ref = func->name(); if (func->overloadNumber() != 1) ref += "-" + QString::number(func->overloadNumber()); } break; case Node::Property: ref = node->name() + "-prop"; break; case Node::Variable: ref = node->name() + "-var"; break; case Node::Target: return protect(node->name()); } return registerRef(ref); } QString HtmlGenerator::linkForNode(const Node *node, const Node *relative) { QString link; QString fn; QString ref; if (node == 0 || node == relative) return QString(); if (!node->url().isEmpty()) return node->url(); if (fileBase(node).isEmpty()) return QString(); if (node->access() == Node::Private) return QString(); fn = fileName(node); /* if (!node->url().isEmpty()) return fn;*/ #if 0 // ### reintroduce this test, without breaking .dcf files if (fn != outFileName()) #endif link += fn; if (!node->isInnerNode()) { ref = refForNode(node); if (relative && fn == fileName(relative) && ref == refForNode(relative)) return QString(); link += "#"; link += ref; } return link; } QString HtmlGenerator::refForAtom(Atom *atom, const Node * /* node */) { if (atom->type() == Atom::SectionLeft) { return Doc::canonicalTitle(Text::sectionHeading(atom).toString()); } else if (atom->type() == Atom::Target) { return Doc::canonicalTitle(atom->string()); } else { return QString(); } } void HtmlGenerator::generateFullName(const Node *apparentNode, const Node *relative, CodeMarker *marker, const Node *actualNode) { if (actualNode == 0) actualNode = apparentNode; out() << "status() != actualNode->status()) { switch (actualNode->status()) { case Node::Obsolete: out() << "\" class=\"obsolete"; break; case Node::Compat: out() << "\" class=\"compat"; break; default: ; } } out() << "\">"; out() << protect(fullName(apparentNode, relative, marker)); out() << ""; } void HtmlGenerator::generateDetailedMember(const Node *node, const InnerNode *relative, CodeMarker *marker) { const EnumNode *enume; generateMacRef(node, marker); if (node->type() == Node::Enum && (enume = static_cast(node))->flagsType()) { generateMacRef(enume->flagsType(), marker); out() << "

      "; out() << ""; generateSynopsis(enume, relative, marker, CodeMarker::Detailed); out() << "
      "; generateSynopsis(enume->flagsType(), relative, marker, CodeMarker::Detailed); out() << "

      \n"; } else { out() << "

      "; out() << ""; generateSynopsis(node, relative, marker, CodeMarker::Detailed); out() << "

      \n"; } generateStatus(node, marker); generateBody(node, marker); generateThreadSafeness(node, marker); generateSince(node, marker); if (node->type() == Node::Property) { const PropertyNode *property = static_cast(node); Section section; section.members += property->getters(); section.members += property->setters(); section.members += property->resetters(); if (!section.members.isEmpty()) { out() << "

      Access functions:

      \n"; generateSectionList(section, node, marker, CodeMarker::Accessors); } } else if (node->type() == Node::Enum) { const EnumNode *enume = static_cast(node); if (enume->flagsType()) { out() << "

      The " << protect(enume->flagsType()->name()) << " type is a typedef for " << "QFlags<" << protect(enume->name()) << ">. It stores an OR combination of " << protect(enume->name()) << " values.

      \n"; } } generateAlsoList(node, marker); } void HtmlGenerator::findAllClasses(const InnerNode *node) { NodeList::const_iterator c = node->childNodes().constBegin(); while (c != node->childNodes().constEnd()) { if ((*c)->access() != Node::Private && (*c)->url().isEmpty()) { if ((*c)->type() == Node::Class && !(*c)->doc().isEmpty()) { QString className = (*c)->name(); if ((*c)->parent() && (*c)->parent()->type() == Node::Namespace && !(*c)->parent()->name().isEmpty()) className = (*c)->parent()->name()+"::"+className; if (!(static_cast(*c))->hideFromMainList()) { if ((*c)->status() == Node::Compat) { compatClasses.insert(className, *c); } else { nonCompatClasses.insert(className, *c); if ((*c)->status() == Node::Main) mainClasses.insert(className, *c); } } QString moduleName = (*c)->moduleName(); if (moduleName == "Qt3SupportLight") { moduleClassMap[moduleName].insert((*c)->name(), *c); moduleName = "Qt3Support"; } if (!moduleName.isEmpty()) moduleClassMap[moduleName].insert((*c)->name(), *c); QString serviceName = (static_cast(*c))->serviceName(); if (!serviceName.isEmpty()) serviceClasses.insert(serviceName, *c); } else if ((*c)->isInnerNode()) { findAllClasses(static_cast(*c)); } } ++c; } } void HtmlGenerator::findAllFunctions(const InnerNode *node) { NodeList::ConstIterator c = node->childNodes().begin(); while (c != node->childNodes().end()) { if ((*c)->access() != Node::Private) { if ((*c)->isInnerNode() && (*c)->url().isEmpty()) { findAllFunctions(static_cast(*c)); } else if ((*c)->type() == Node::Function) { const FunctionNode *func = static_cast(*c); if (func->status() > Node::Obsolete && func->metaness() != FunctionNode::Ctor && func->metaness() != FunctionNode::Dtor) { funcIndex[(*c)->name()].insert((*c)->parent()->name(), *c); } } } ++c; } } void HtmlGenerator::findAllLegaleseTexts(const InnerNode *node) { NodeList::ConstIterator c = node->childNodes().begin(); while (c != node->childNodes().end()) { if ((*c)->access() != Node::Private) { if (!(*c)->doc().legaleseText().isEmpty()) legaleseTexts.insertMulti((*c)->doc().legaleseText(), *c); if ((*c)->isInnerNode()) findAllLegaleseTexts(static_cast(*c)); } ++c; } } void HtmlGenerator::findAllNamespaces(const InnerNode *node) { NodeList::ConstIterator c = node->childNodes().begin(); while (c != node->childNodes().end()) { if ((*c)->access() != Node::Private) { if ((*c)->isInnerNode() && (*c)->url().isEmpty()) { findAllNamespaces(static_cast(*c)); if ((*c)->type() == Node::Namespace) { const NamespaceNode *nspace = static_cast(*c); // Ensure that the namespace's name is not empty (the root // namespace has no name). if (!nspace->name().isEmpty()) { namespaceIndex.insert(nspace->name(), *c); QString moduleName = (*c)->moduleName(); if (moduleName == "Qt3SupportLight") { moduleNamespaceMap[moduleName].insert((*c)->name(), *c); moduleName = "Qt3Support"; } if (!moduleName.isEmpty()) moduleNamespaceMap[moduleName].insert((*c)->name(), *c); } } } } ++c; } } #ifdef ZZZ_QDOC_QML /*! This function finds all the qml element nodes and stores them in a map for later use. */ void HtmlGenerator::findAllQmlClasses(const InnerNode *node) { NodeList::const_iterator c = node->childNodes().constBegin(); while (c != node->childNodes().constEnd()) { if ((*c)->type() == Node::Fake) { const FakeNode* fakeNode = static_cast(*c); if (fakeNode->subType() == FakeNode::QmlClass) { const QmlNode* qmlNode = static_cast(fakeNode); //qDebug() << "HtmlGenerator: QML CLASS" << qmlNode->name(); const Node* n = qmlNode->classNode(); if (n) //qDebug() << " FOUND IT!" << n->name(); } qmlClasses.insert(fakeNode->name(),*c); } ++c; } } #endif #if 0 else if ((*c)->isInnerNode()) { findAllClasses(static_cast(*c)); } #endif int HtmlGenerator::hOffset(const Node *node) { switch (node->type()) { case Node::Namespace: case Node::Class: return 2; case Node::Fake: if (node->doc().briefText().isEmpty()) return 1; else return 2; case Node::Enum: case Node::Typedef: case Node::Function: case Node::Property: default: return 3; } } bool HtmlGenerator::isThreeColumnEnumValueTable(const Atom *atom) { while (atom != 0 && !(atom->type() == Atom::ListRight && atom->string() == ATOM_LIST_VALUE)) { if (atom->type() == Atom::ListItemLeft && !matchAhead(atom, Atom::ListItemRight)) return true; atom = atom->next(); } return false; } const Node *HtmlGenerator::findNodeForTarget(const QString &target, const Node *relative, CodeMarker *marker, const Atom *atom) { const Node *node = 0; if (target.isEmpty()) { node = relative; } else if (target.endsWith(".html")) { node = tre->root()->findNode(target, Node::Fake); } else if (marker) { node = marker->resolveTarget(target, tre, relative); if (!node) node = tre->findFakeNodeByTitle(target); if (!node && atom) { node = tre->findUnambiguousTarget(target, *const_cast(&atom)); } } if (!node) relative->doc().location().warning(tr("Cannot link to '%1'").arg(target)); return node; } const QPair HtmlGenerator::anchorForNode(const Node *node) { QPair anchorPair; anchorPair.first = PageGenerator::fileName(node); if (node->type() == Node::Fake) { const FakeNode *fakeNode = static_cast(node); anchorPair.second = fakeNode->title(); } return anchorPair; } QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, CodeMarker *marker, const Node *node) { QString link; node = 0; if (atom->string().contains(":") && (atom->string().startsWith("file:") || atom->string().startsWith("http:") || atom->string().startsWith("https:") || atom->string().startsWith("ftp:") || atom->string().startsWith("mailto:"))) { link = atom->string(); } else { QStringList path; if (atom->string().contains('#')) { path = atom->string().split('#'); } else { path.append(atom->string()); } Atom *targetAtom = 0; QString first = path.first().trimmed(); if (first.isEmpty()) { node = relative; } else if (first.endsWith(".html")) { node = tre->root()->findNode(first, Node::Fake); } else { node = marker->resolveTarget(first, tre, relative); if (!node) node = tre->findFakeNodeByTitle(first); if (!node) node = tre->findUnambiguousTarget(first, targetAtom); } if (node) { if (!node->url().isEmpty()) return node->url(); else path.removeFirst(); } else { node = relative; } while (!path.isEmpty()) { targetAtom = tre->findTarget(path.first(), node); if (targetAtom == 0) break; path.removeFirst(); } if (path.isEmpty()) { link = linkForNode(node, relative); if (targetAtom) link += "#" + refForAtom(targetAtom, node); } } return link; } void HtmlGenerator::generateDcf(const QString &fileBase, const QString &startPage, const QString &title, DcfSection &dcfRoot) { dcfRoot.ref = startPage; dcfRoot.title = title; generateDcfSections(dcfRoot, outputDir() + "/" + fileBase + ".dcf", fileBase + "/reference"); } void HtmlGenerator::generateIndex(const QString &fileBase, const QString &url, const QString &title) { tre->generateIndex(outputDir() + "/" + fileBase + ".index", url, title); } void HtmlGenerator::generateStatus(const Node *node, CodeMarker *marker) { Text text; switch (node->status()) { case Node::Obsolete: if (node->isInnerNode()) Generator::generateStatus(node, marker); break; case Node::Compat: if (node->isInnerNode()) { text << Atom::ParaLeft << Atom(Atom::FormattingLeft,ATOM_FORMATTING_BOLD) << "This " << typeString(node) << " is part of the Qt 3 support library." << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << " It is provided to keep old source code working. We strongly advise against " << "using it in new code. See "; const FakeNode *fakeNode = tre->findFakeNodeByTitle("Porting To Qt 4"); Atom *targetAtom = 0; if (fakeNode && node->type() == Node::Class) { QString oldName(node->name()); targetAtom = tre->findTarget(oldName.replace("3", ""), fakeNode); } if (targetAtom) { text << Atom(Atom::Link, linkForNode(fakeNode, node) + "#" + refForAtom(targetAtom, fakeNode)); } else text << Atom(Atom::Link, "Porting to Qt 4"); text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << Atom(Atom::String, "Porting to Qt 4") << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK) << " for more information." << Atom::ParaRight; } generateText(text, node, marker); break; default: Generator::generateStatus(node, marker); } } void HtmlGenerator::generateMacRef(const Node *node, CodeMarker *marker) { if (!pleaseGenerateMacRef || marker == 0) return; QStringList macRefs = marker->macRefsForNode(node); foreach (const QString &macRef, macRefs) out() << "\n"; } void HtmlGenerator::beginLink(const QString &link, const Node *node, const Node *relative, CodeMarker *marker) { Q_UNUSED(marker) Q_UNUSED(relative) this->link = link; if (link.isEmpty()) { if (showBrokenLinks) out() << ""; } else if (node == 0 || (relative != 0 && node->status() == relative->status())) { out() << ""; } else { switch (node->status()) { case Node::Obsolete: out() << ""; break; case Node::Compat: out() << ""; break; default: out() << ""; } } inLink = true; } void HtmlGenerator::endLink() { if (inLink) { if (link.isEmpty()) { if (showBrokenLinks) out() << ""; } else { out() << ""; } } inLink = false; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/htmlgenerator.h000066400000000000000000000236221215241066400217750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* htmlgenerator.h */ #ifndef HTMLGENERATOR_H #define HTMLGENERATOR_H #include #include #include "codemarker.h" #include "config.h" #include "dcfsection.h" #include "pagegenerator.h" QT_BEGIN_NAMESPACE #if 0 struct NavigationBar { SectionIterator prev; SectionIterator current; SectionIterator next; }; #endif class HelpProjectWriter; class HtmlGenerator : public PageGenerator { public: HtmlGenerator(); ~HtmlGenerator(); virtual void initializeGenerator(const Config& config); virtual void terminateGenerator(); virtual QString format(); virtual void generateTree(const Tree *tree, CodeMarker *marker); static QString protect(const QString& string); static QString cleanRef(const QString& ref); protected: virtual void startText(const Node *relative, CodeMarker *marker); virtual int generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker); virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker); virtual QString fileExtension(const Node *node); virtual QString refForNode(const Node *node); virtual QString linkForNode(const Node *node, const Node *relative); virtual QString refForAtom(Atom *atom, const Node *node); private: enum SubTitleSize { SmallSubTitle, LargeSubTitle }; const QPair anchorForNode(const Node *node); const Node *findNodeForTarget(const QString &target, const Node *relative, CodeMarker *marker, const Atom *atom = 0); void generateHeader(const QString& title, const Node *node = 0, CodeMarker *marker = 0, bool mainPage = true); void generateTitle(const QString& title, const Text &subTitle, SubTitleSize subTitleSize, const Node *relative, CodeMarker *marker); void generateFooter(const Node *node = 0); void generateBrief(const Node *node, CodeMarker *marker, const Node *relative = 0); void generateIncludes(const InnerNode *inner, CodeMarker *marker); #if 0 void generateNavigationBar(const NavigationBar& bar, const Node *node, CodeMarker *marker); #endif void generateTableOfContents(const Node *node, CodeMarker *marker, Doc::SectioningUnit sectioningUnit, int numColumns, const Node *relative = 0); QString generateListOfAllMemberFile(const InnerNode *inner, CodeMarker *marker); QString generateLowStatusMemberFile(const InnerNode *inner, CodeMarker *marker, CodeMarker::Status status); void generateClassHierarchy(const Node *relative, CodeMarker *marker, const QMap &classMap); void generateAnnotatedList(const Node *relative, CodeMarker *marker, const QMap &nodeMap); void generateCompactList(const Node *relative, CodeMarker *marker, const QMap &classMap); void generateFunctionIndex(const Node *relative, CodeMarker *marker); void generateLegaleseList(const Node *relative, CodeMarker *marker); void generateOverviewList(const Node *relative, CodeMarker *marker); void generateSynopsis(const Node *node, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style); void generateSectionList(const Section& section, const Node *relative, CodeMarker *marker, CodeMarker::SynopsisStyle style); void generateSectionInheritedList(const Section& section, const Node *relative, CodeMarker *marker); void generateFullName(const Node *apparentNode, const Node *relative, CodeMarker *marker, const Node *actualNode = 0); void generateDetailedMember(const Node *node, const InnerNode *relative, CodeMarker *marker); void generateLink(const Atom *atom, const Node *relative, CodeMarker *marker); void generateStatus(const Node *node, CodeMarker *marker); QString registerRef(const QString& ref); QString highlightedCode(const QString& markedCode, CodeMarker *marker, const Node *relative); QString fileBase(const Node *node); #if 0 QString fileBase(const Node *node, const SectionIterator& section); #endif QString fileName(const Node *node); void findAllClasses(const InnerNode *node); void findAllFunctions(const InnerNode *node); void findAllLegaleseTexts(const InnerNode *node); void findAllNamespaces(const InnerNode *node); #ifdef ZZZ_QDOC_QML void findAllQmlClasses(const InnerNode *node); #endif static int hOffset(const Node *node); static bool isThreeColumnEnumValueTable(const Atom *atom); virtual QString getLink(const Atom *atom, const Node *relative, CodeMarker *marker, const Node *node = 0); virtual void generateDcf(const QString &fileBase, const QString &startPage, const QString &title, DcfSection &dcfRoot); virtual void generateIndex(const QString &fileBase, const QString &url, const QString &title); void generateMacRef(const Node *node, CodeMarker *marker); void beginLink(const QString &link, const Node *node, const Node *relative, CodeMarker *marker); void endLink(); #if 0 NavigationBar currentNavigationBar; #endif QMap refMap; int codeIndent; DcfSection dcfClassesRoot; DcfSection dcfOverviewsRoot; DcfSection dcfExamplesRoot; DcfSection dcfDesignerRoot; DcfSection dcfLinguistRoot; DcfSection dcfAssistantRoot; DcfSection dcfQmakeRoot; HelpProjectWriter *helpProjectWriter; bool inLink; bool inContents; bool inSectionHeading; bool inTableHeader; int numTableRows; bool threeColumnEnumValueTable; QString link; QStringList sectionNumber; QRegExp funcLeftParen; QString style; QString postHeader; QString footer; QString address; bool pleaseGenerateMacRef; QString project; QString projectDescription; QString projectUrl; QString navigationLinks; QStringList stylesheets; QStringList customHeadElements; const Tree *tre; bool slow; QMap > moduleClassMap; QMap > moduleNamespaceMap; QMap nonCompatClasses; QMap mainClasses; QMap compatClasses; QMap namespaceIndex; QMap serviceClasses; #ifdef QDOC_QML QMap qmlClasses; #endif QMap > funcIndex; QMap legaleseTexts; }; #define HTMLGENERATOR_ADDRESS "address" #define HTMLGENERATOR_FOOTER "footer" #define HTMLGENERATOR_GENERATEMACREFS "generatemacrefs" // ### document me #define HTMLGENERATOR_POSTHEADER "postheader" #define HTMLGENERATOR_STYLE "style" #define HTMLGENERATOR_STYLESHEETS "stylesheets" #define HTMLGENERATOR_CUSTOMHEADELEMENTS "customheadelements" QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/jambiapiparser.cpp000066400000000000000000000461001215241066400224420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* jambiapiparser.cpp */ #include #include "cppcodeparser.h" #include "jambiapiparser.h" #include "node.h" #include "tree.h" QT_BEGIN_NAMESPACE static const char USED_INTERNALLY[] = ""; static Text textWithFixedBrief(const Text &text, const Text &beforeBrief, const Text &afterBrief) { Text result; const Atom *atom = text.firstAtom(); while (atom) { if (atom->type() == Atom::BriefLeft) { result << Atom::ParaLeft << beforeBrief; } else if (atom->type() == Atom::BriefRight) { result << afterBrief << Atom::ParaRight; } else { result << *atom; } atom = atom->next(); } return result; } static void setPass1JambifiedDoc(Node *javaNode, const Node *cppNode, const QString &qName = "") { Doc newDoc(cppNode->doc()); if (javaNode->type() == Node::Function) { const FunctionNode *javaFunc = static_cast(javaNode); if (cppNode->type() == Node::Function) { const FunctionNode *cppFunc = static_cast(cppNode); if (const PropertyNode *property = cppFunc->associatedProperty()) { newDoc = property->doc(); Text text(newDoc.body()); Node *mutableCppNode = const_cast(cppNode); if (property->getters().contains(mutableCppNode)) { text = textWithFixedBrief(text, Text("Returns "), Text(".")); } else if (property->setters().contains(mutableCppNode)) { Text afterBrief; if (javaFunc->parameterNames().count() == 1 && !javaFunc->parameterNames().first().isEmpty()) { afterBrief << " to " << Atom(Atom::FormattingLeft, ATOM_FORMATTING_PARAMETER) << javaFunc->parameterNames().first() << Atom(Atom::FormattingRight, ATOM_FORMATTING_PARAMETER); } afterBrief << "."; text = textWithFixedBrief(text, Text("Sets "), afterBrief); } else if (property->resetters().contains(mutableCppNode)) { text = textWithFixedBrief(text, Text("Resets "), Text(".")); } newDoc.setBody(text); } else { QStringList javaParams = javaFunc->parameterNames(); QStringList cppParams = cppFunc->parameterNames(); newDoc.renameParameters(cppParams, javaParams); if (cppNode->access() == Node::Private) { Text text; text << Atom::ParaLeft; if (cppFunc->reimplementedFrom()) { text << "This function is reimplemented for internal reasons."; } else { text << USED_INTERNALLY; } text << Atom::ParaRight; newDoc.setBody(text); } } } else if (cppNode->type() == Node::Variable) { Text text(newDoc.body()); if (qName == "variablegetter") { text = textWithFixedBrief(text, Text("Returns "), Text(".")); } else if (qName == "variablesetter") { Text afterBrief; if (javaFunc->parameterNames().count() == 1 && !javaFunc->parameterNames().first().isEmpty()) { afterBrief << " to " << Atom(Atom::FormattingLeft, ATOM_FORMATTING_PARAMETER) << javaFunc->parameterNames().first() << Atom(Atom::FormattingRight, ATOM_FORMATTING_PARAMETER); } afterBrief << "."; text = textWithFixedBrief(text, Text("Sets "), afterBrief); } newDoc.setBody(text); } } else { // ### enum value names? } javaNode->setDoc(newDoc, true); } static void setStatus(Node *javaNode, const Node *cppNode) { if (cppNode->status() == Node::Compat) { javaNode->setStatus(Node::Obsolete); } else { javaNode->setStatus(cppNode->status()); } } static Text findEnumText(Node *javaEnum, const QString &enumItemName) { const Text &body = javaEnum->doc().body(); const Atom *atom = body.firstAtom(); while (atom) { if (atom->type() == Atom::ListTagLeft && atom->string() == ATOM_LIST_VALUE) { atom = atom->next(); if (atom) { // ### paras? if (atom->string() == enumItemName) return body.subText(Atom::ListItemLeft, Atom::ListItemRight, atom); } } else { atom = atom->next(); } } return Text(); } JambiApiParser::JambiApiParser(Tree *cppTree) : cppTre(cppTree), javaTre(0), metJapiTag(false) { } JambiApiParser::~JambiApiParser() { } void JambiApiParser::initializeParser(const Config &config) { CodeParser::initializeParser(config); } void JambiApiParser::terminateParser() { CodeParser::terminateParser(); } QString JambiApiParser::language() { return "Java"; } QString JambiApiParser::sourceFileNameFilter() { return "*.japi"; } void JambiApiParser::parseSourceFile(const Location &location, const QString &filePath, Tree *tree) { javaTre = tree; metJapiTag = false; QXmlSimpleReader reader; reader.setContentHandler(this); reader.setErrorHandler(this); QFile file(filePath); if (!file.open(QFile::ReadOnly)) { location.warning(tr("Cannot open JAPI file '%1'").arg(filePath)); return; } japiLocation = Location(filePath); QXmlInputSource xmlSource(&file); reader.parse(xmlSource); } void JambiApiParser::doneParsingSourceFiles(Tree * /* tree */) { /* Also import the overview documents. */ foreach (Node *cppNode, cppTre->root()->childNodes()) { if (cppNode->type() == Node::Fake) { FakeNode *cppFake = static_cast(cppNode); if (cppFake->subType() == FakeNode::Page) { FakeNode *javaFake = new FakeNode(javaTre->root(), cppFake->name(), cppFake->subType()); javaFake->setModuleName("com.trolltech.qt"); // ### hard-coded javaFake->setTitle(cppFake->title()); javaFake->setSubTitle(cppFake->subTitle()); setStatus(javaFake, cppFake); setPass1JambifiedDoc(javaFake, cppFake); } } } /* Fix the docs. */ if (javaTre) { javaTre->resolveInheritance(); jambifyDocsPass2(javaTre->root()); javaTre = 0; } } bool JambiApiParser::startElement(const QString & /* namespaceURI */, const QString & /* localName */, const QString &qName, const QXmlAttributes &attributes) { if (!metJapiTag && qName != "japi") { // ### The file is not a JAPI file. return true; } metJapiTag = true; EnumNode *javaEnum = 0; EnumNode *cppEnum = 0; InnerNode *javaParent = javaTre->root(); InnerNode *cppParent = cppTre->root(); for (int i = 0; i < classAndEnumStack.count(); ++i) { const ClassOrEnumInfo &info = classAndEnumStack.at(i); if (info.cppNode) { if (info.cppNode->type() == Node::Enum) { Q_ASSERT(info.javaNode->type() == Node::Enum); javaEnum = static_cast(info.javaNode); cppEnum = static_cast(info.cppNode); } else { Q_ASSERT(info.javaNode->type() == Node::Class || info.javaNode->type() == Node::Namespace); javaParent = static_cast(info.javaNode); cppParent = static_cast(info.cppNode); } } } if (qName == "class" || qName == "enum") { Node::Type type = (qName == "class") ? Node::Class : Node::Enum; QString javaExtends = attributes.value("java-extends"); QString javaImplements = attributes.value("javaimplements"); ClassOrEnumInfo info; info.tag = qName; info.javaName = attributes.value("java"); info.cppName = attributes.value("cpp"); info.cppNode = cppTre->findNode(info.cppName.split("::"), type, cppParent); if (!info.cppNode && type == Node::Class) { type = Node::Namespace; info.cppNode = cppTre->findNode(info.cppName.split("::"), type, cppParent); } if (!info.cppNode) { japiLocation.warning(tr("Cannot find C++ class or enum '%1'").arg(info.cppName)); } else { if (qName == "class") { ClassNode *javaClass = new ClassNode(javaParent, info.javaName); javaClass->setModuleName(attributes.value("package")); if (!javaExtends.isEmpty()) javaTre->addBaseClass(javaClass, Node::Public, javaExtends.split('.'), javaExtends); if (!javaImplements.isEmpty()) javaTre->addBaseClass(javaClass, Node::Public, javaImplements.split('.'), javaExtends); info.javaNode = javaClass; } else { info.javaNode = new EnumNode(javaParent, info.javaName); } info.javaNode->setLocation(japiLocation); setStatus(info.javaNode, info.cppNode); setPass1JambifiedDoc(info.javaNode, info.cppNode); } classAndEnumStack.push(info); } else if (qName == "method" || qName == "signal") { QString javaSignature = attributes.value("java"); if (javaSignature.startsWith("private")) return true; QString cppSignature = attributes.value("cpp"); CppCodeParser cppParser; const FunctionNode *cppNode = cppParser.findFunctionNode(cppSignature, cppTre, cppParent, true /* fuzzy */); if (!cppNode) { bool quiet = false; /* Default constructors sometimes don't exist in C++. */ if (!quiet && javaSignature == "public " + javaParent->name() + "()") quiet = true; if (!quiet) japiLocation.warning(tr("Cannot find C++ function '%1' ('%2')") .arg(cppSignature).arg(cppParent->name())); } FunctionNode *javaNode; if (makeFunctionNode(javaParent, javaSignature, &javaNode)) { javaNode->setLocation(japiLocation); if (qName == "signal") javaNode->setMetaness(FunctionNode::Signal); if (cppNode) { setStatus(javaNode, cppNode); int overloadNo = cppNode->parameters().count() - javaNode->parameters().count() + 1; if (overloadNo == 1) { setPass1JambifiedDoc(javaNode, cppNode); } else { Text text; text << Atom::ParaLeft << "Equivalent to " << Atom(Atom::Link, javaNode->name() + "()") << Atom(Atom::FormattingLeft, ATOM_FORMATTING_LINK) << javaNode->name() << Atom(Atom::FormattingRight, ATOM_FORMATTING_LINK) << "("; for (int i = 0; i < cppNode->parameters().count(); ++i) { if (i > 0) text << ", "; if (i < javaNode->parameters().count()) { text << Atom(Atom::FormattingLeft, ATOM_FORMATTING_PARAMETER) << javaNode->parameters().at(i).name() << Atom(Atom::FormattingRight, ATOM_FORMATTING_PARAMETER); } else { // ### convert to Java text << cppNode->parameters().at(i).defaultValue(); } } text << ")."; Doc doc; doc.setBody(text); javaNode->setDoc(doc, true); } javaNode->setOverload(overloadNo > 1); } } } else if (qName == "variablesetter" || qName == "variablegetter") { QString javaSignature = attributes.value("java"); if (javaSignature.startsWith("private")) return true; QString cppVariable = attributes.value("cpp"); VariableNode *cppNode = static_cast(cppParent->findNode(cppVariable, Node::Variable)); FunctionNode *javaNode; if (makeFunctionNode(javaParent, javaSignature, &javaNode)) { javaNode->setLocation(japiLocation); if (!cppNode) { #if 0 japiLocation.warning(tr("Cannot find C++ variable '%1' ('%2')") .arg(cppVariable).arg(cppParent->name())); #endif javaNode->setDoc(Doc(japiLocation, japiLocation, USED_INTERNALLY, QSet()), true); } else { setPass1JambifiedDoc(javaNode, cppNode, qName); setStatus(javaNode, cppNode); } } } else if (qName == "enum-value") { QString javaName = attributes.value("java"); QString cppName = attributes.value("cpp"); QString value = attributes.value("value"); if (javaEnum) { EnumItem item(javaName, value, findEnumText(javaEnum, javaName)); javaEnum->addItem(item); } } return true; } bool JambiApiParser::endElement(const QString & /* namespaceURI */, const QString & /* localName */, const QString &qName) { if (qName == "class" || qName == "enum") classAndEnumStack.pop(); return true; } bool JambiApiParser::fatalError(const QXmlParseException &exception) { japiLocation.setLineNo(exception.lineNumber()); japiLocation.setColumnNo(exception.columnNumber()); japiLocation.warning(tr("Syntax error in JAPI file (%1)").arg(exception.message())); return true; } void JambiApiParser::jambifyDocsPass2(Node *node) { const Doc &doc = node->doc(); if (!doc.isEmpty()) { if (node->type() == Node::Enum) { Doc newDoc(doc); newDoc.simplifyEnumDoc(); node->setDoc(newDoc, true); } } if (node->isInnerNode()) { InnerNode *innerNode = static_cast(node); foreach (Node *child, innerNode->childNodes()) jambifyDocsPass2(child); } } bool JambiApiParser::makeFunctionNode(InnerNode *parent, const QString &synopsis, FunctionNode **funcPtr) { Node::Access access = Node::Public; FunctionNode::Metaness metaness = FunctionNode::Plain; bool final = false; bool statique = false; QString mySynopsis = synopsis.simplified(); int oldLen; do { oldLen = mySynopsis.length(); if (mySynopsis.startsWith("public ")) { mySynopsis.remove(0, 7); access = Node::Public; } if (mySynopsis.startsWith("protected ")) { mySynopsis.remove(0, 10); access = Node::Protected; } if (mySynopsis.startsWith("private ")) { mySynopsis.remove(0, 8); access = Node::Private; } if (mySynopsis.startsWith("native ")) { mySynopsis.remove(0, 7); metaness = FunctionNode::Native; } if (mySynopsis.startsWith("final ")) { mySynopsis.remove(0, 6); final = true; } if (mySynopsis.startsWith("static ")) { mySynopsis.remove(0, 7); statique = true; } } while (oldLen != mySynopsis.length()); // method or constructor QRegExp funcRegExp("(?:(.*) )?([A-Za-z_0-9]+)\\((.*)\\)"); if (!funcRegExp.exactMatch(mySynopsis)) return false; QString retType = funcRegExp.cap(1); QString funcName = funcRegExp.cap(2); QStringList params = funcRegExp.cap(3).split(","); FunctionNode *func = new FunctionNode(parent, funcName); func->setReturnType(retType); func->setAccess(access); func->setStatic(statique); func->setConst(final); func->setMetaness(metaness); QRegExp paramRegExp(" ?([^ ].*) ([A-Za-z_0-9]+) ?"); foreach (const QString ¶m, params) { if (paramRegExp.exactMatch(param)) { func->addParameter(Parameter(paramRegExp.cap(1), "", paramRegExp.cap(2))); } else { // problem } } if (funcPtr) { *funcPtr = func; } else if (!parent) { delete func; } return true; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/jambiapiparser.h000066400000000000000000000064451215241066400221170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* jambiapiparser.h */ #ifndef JAMBIAPIPARSER_H #define JAMBIAPIPARSER_H #include #include #include "codeparser.h" QT_BEGIN_NAMESPACE struct ClassOrEnumInfo { QString tag; QString javaName; QString cppName; Node *javaNode; Node *cppNode; ClassOrEnumInfo() : javaNode(0), cppNode(0) {} }; class JambiApiParser : public CodeParser, private QXmlDefaultHandler { public: JambiApiParser(Tree *cppTree); ~JambiApiParser(); void initializeParser(const Config &config); void terminateParser(); QString language(); QString sourceFileNameFilter(); void parseSourceFile(const Location &location, const QString &filePath, Tree *tree); virtual void doneParsingSourceFiles(Tree *tree); private: bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &attributes); bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName); bool fatalError(const QXmlParseException &exception); void jambifyDocsPass2(Node *node); bool makeFunctionNode(InnerNode *parent, const QString &synopsis, FunctionNode **funcPtr); Tree *cppTre; Tree *javaTre; bool metJapiTag; Location japiLocation; QStack classAndEnumStack; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/javacodemarker.cpp000066400000000000000000000134321215241066400224310ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* javacodemarker.cpp */ #include "javacodemarker.h" #include "node.h" #include "text.h" #include "tree.h" QT_BEGIN_NAMESPACE JavaCodeMarker::JavaCodeMarker() { } JavaCodeMarker::~JavaCodeMarker() { } bool JavaCodeMarker::recognizeCode( const QString& /* code */ ) { return true; } bool JavaCodeMarker::recognizeExtension( const QString& ext ) { return ext == "java"; } bool JavaCodeMarker::recognizeLanguage( const QString& lang ) { return lang == "Java"; } QString JavaCodeMarker::plainName( const Node *node ) { return node->name(); } QString JavaCodeMarker::plainFullName( const Node *node, const Node * /* relative */ ) { if (!node) return QString(); QString fullName; for ( ;; ) { fullName.prepend( plainName(node) ); if ( node->parent() && node->parent()->name().isEmpty() ) break; node = node->parent(); if (!node) break; fullName.prepend("."); } return fullName; } QString JavaCodeMarker::markedUpCode( const QString& code, const Node * /* relative */, const QString& /* dirPath */ ) { return protect( code ); } QString JavaCodeMarker::markedUpSynopsis(const Node * /* node */, const Node * /* relative */, SynopsisStyle /* style */) { return QString(); } QString JavaCodeMarker::markedUpName( const Node *node ) { return linkTag(node, taggedNode(node)); } QString JavaCodeMarker::markedUpFullName(const Node *node, const Node * /* relative */ ) { QString fullName; for ( ;; ) { fullName.prepend( markedUpName(node) ); if ( node->parent()->name().isEmpty() ) break; node = node->parent(); fullName.prepend( "." ); } return fullName; } QString JavaCodeMarker::markedUpEnumValue(const QString &enumValue, const Node * /* relative */) { return protect(enumValue); } QString JavaCodeMarker::markedUpIncludes( const QStringList& /* includes */ ) { return QString(); } QString JavaCodeMarker::functionBeginRegExp( const QString& /* funcName */) { return "^x$"; // ### invalid regexp } QString JavaCodeMarker::functionEndRegExp( const QString& /* funcName */ ) { return "^}"; } QList
      JavaCodeMarker::sections(const InnerNode * /* inner */, SynopsisStyle /* style */, Status /* status */) { return QList
      (); } const Node *JavaCodeMarker::resolveTarget(const QString &target, const Tree *tree, const Node *relative) { if (target.endsWith("()")) { const FunctionNode *func; QString funcName = target; funcName.chop(2); QStringList path = funcName.split('.'); if ((func = tree->findFunctionNode(path, relative, Tree::SearchBaseClasses))) return func; } else if (target.contains("#")) { int hashAt = target.indexOf("#"); QString link = target.left(hashAt); QString ref = target.mid(hashAt + 1); const Node *node; if (link.isEmpty()) { node = relative; } else { QStringList path(link); node = tree->findNode(path, tree->root(), Tree::SearchBaseClasses); } if (node && node->isInnerNode()) { const Atom *atom = node->doc().body().firstAtom(); while (atom) { if (atom->type() == Atom::Target && atom->string() == ref) { Node *parentNode = const_cast(node); return new TargetNode(static_cast(parentNode), ref); } atom = atom->next(); } } } else { QStringList path = target.split('.'); const Node *node; if ((node = tree->findNode(path, relative, Tree::SearchBaseClasses | Tree::SearchEnumValues))) return node; } return 0; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/javacodemarker.h000066400000000000000000000062541215241066400221020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* javacodemarker.h */ #ifndef JAVACODEMARKER_H #define JAVACODEMARKER_H #include "codemarker.h" QT_BEGIN_NAMESPACE class JavaCodeMarker : public CodeMarker { public: JavaCodeMarker(); ~JavaCodeMarker(); bool recognizeCode( const QString& code ); bool recognizeExtension( const QString& ext ); bool recognizeLanguage( const QString& lang ); QString plainName(const Node *node); QString plainFullName(const Node *node, const Node *relative); QString markedUpCode( const QString& code, const Node *relative, const QString& dirPath ); QString markedUpSynopsis( const Node *node, const Node *relative, SynopsisStyle style ); QString markedUpName( const Node *node ); QString markedUpFullName( const Node *node, const Node *relative ); QString markedUpEnumValue(const QString &enumValue, const Node *relative); QString markedUpIncludes( const QStringList& includes ); QList
      sections(const InnerNode *innerNode, SynopsisStyle style, Status status); QString functionBeginRegExp( const QString& funcName ); QString functionEndRegExp( const QString& funcName ); const Node *resolveTarget( const QString& target, const Tree *tree, const Node *relative ); }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/javadocgenerator.cpp000066400000000000000000000340671215241066400230000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "javadocgenerator.h" QT_BEGIN_NAMESPACE enum JavaSignatureSyntax { GeneratedJdocFile, JavadocRef, SlotSignature }; static QString javaSignature(const FunctionNode *func, JavaSignatureSyntax syntax, int maxParams = 65535) { maxParams = qMin(maxParams, func->parameters().count()); QString result; if (syntax == GeneratedJdocFile) { if (func->access() == Node::Public) { result += "public "; } else if (func->access() == Node::Protected) { result += "protected "; } else { result += "private "; } if (func->metaness() == FunctionNode::Native) result += "native "; if (func->isConst()) result += "final "; // ### func->metaness() == FunctionNode::Abstract if (func->isStatic()) result += "static "; if (!func->returnType().isEmpty()) { result += func->returnType(); result += ' '; } } if (syntax == SlotSignature) { result += "void mySlot"; } else { result += func->name(); } result += '('; for (int i = 0; i < maxParams; ++i) { if (i != 0) result += ", "; result += func->parameters().at(i).leftType(); if (syntax != JavadocRef) { result += ' '; result += func->parameters().at(i).name(); } } result += ')'; return result; } static QString packageName(const Node *node) { while (node && node->type() != Node::Class && node->type() != Node::Fake) node = node->parent(); if (!node) return QString(); return node->moduleName(); } JavadocGenerator::JavadocGenerator() : oldDevice(0), currentDepth(0) { } JavadocGenerator::~JavadocGenerator() { } void JavadocGenerator::initializeGenerator(const Config &config) { HtmlGenerator::initializeGenerator(config); formattingLeftMap().insert(ATOM_FORMATTING_PARAMETER, formattingLeftMap().value(ATOM_FORMATTING_TELETYPE)); formattingRightMap().insert(ATOM_FORMATTING_PARAMETER, formattingRightMap().value(ATOM_FORMATTING_TELETYPE)); } void JavadocGenerator::terminateGenerator() { HtmlGenerator::terminateGenerator(); } QString JavadocGenerator::format() { return "javadoc"; } void JavadocGenerator::generateTree(const Tree *tree, CodeMarker *marker) { HtmlGenerator::generateTree(tree, marker); } QString JavadocGenerator::fileExtension(const Node *node) { if (node->type() == Node::Fake) { return "html"; } else { return "jdoc"; } } QString JavadocGenerator::typeString(const Node *node) { if (node->type() == Node::Function) { const FunctionNode *func = static_cast(node); return func->metaness() == FunctionNode::Signal ? "signal" : "method"; } else { return HtmlGenerator::typeString(node); } } QString JavadocGenerator::imageFileName(const Node *relative, const QString& fileBase) { QString result = HtmlGenerator::imageFileName(relative, fileBase); if (!result.isEmpty()) { QString package = packageName(relative); int numSubPackages = package.count('.') - 2; while (numSubPackages > 0) { result.prepend("%2E%2E/"); // javadoc 1.5.0_06 chokes on '../' --numSubPackages; } } return result; } static int textDepth = 0; void JavadocGenerator::startText(const Node *relative, CodeMarker *marker) { if (textDepth++ == 0 && relative->type() != Node::Fake) { Q_ASSERT(!oldDevice); oldDevice = out().device(); Q_ASSERT(oldDevice); out().setString(&buffer); } HtmlGenerator::startText(relative, marker); } void JavadocGenerator::endText(const Node *relative, CodeMarker *marker) { HtmlGenerator::endText(relative, marker); if (--textDepth == 0 && relative->type() != Node::Fake) { Q_ASSERT(oldDevice); out().setDevice(oldDevice); oldDevice = 0; /* Need to escape XML metacharacters in .jdoc files. */ buffer.replace("*/", "*<!-- noop -->/"); buffer.replace("&", "&"); buffer.replace("\"", """); buffer.replace("<", "<"); buffer.replace(">", ">"); out() << buffer; buffer.clear(); } } int JavadocGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMarker *marker) { return HtmlGenerator::generateAtom(atom, relative, marker); } void JavadocGenerator::generateClassLikeNode(const InnerNode *inner, CodeMarker *marker) { generateIndent(); out() << "name()) << "\""; generateDoc(inner, marker); out() << ">\n"; ++currentDepth; foreach (Node *node, inner->childNodes()) { if (node->isInnerNode()) { generateClassLikeNode(static_cast(node), marker); } else { if (node->type() == Node::Enum) { EnumNode *enume = static_cast(node); generateIndent(); out() << "name()) << "\""; generateDoc(node, marker); out() << ">\n"; ++currentDepth; const QList &items = enume->items(); for (int i = 0; i < items.count(); ++i) { const EnumItem &item = items.at(i); generateIndent(); out() << "\n"; } --currentDepth; out() << "\n"; } else if (node->type() == Node::Function) { FunctionNode *func = static_cast(node); generateIndent(); out() << (func->metaness() == FunctionNode::Signal ? "\n"; } } } --currentDepth; generateIndent(); out() << "\n"; } void JavadocGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker) { HtmlGenerator::generateFakeNode(fake, marker); } void JavadocGenerator::generateText(const Text& text, const Node *relative, CodeMarker *marker) { HtmlGenerator::generateText(text, relative, marker); } void JavadocGenerator::generateBody(const Node *node, CodeMarker *marker) { generateText(node->doc().body(), node, marker); } void JavadocGenerator::generateAlsoList( const Node *node, CodeMarker *marker ) { QList alsoList = node->doc().alsoList(); supplementAlsoList(node, alsoList); if (node->type() == Node::Fake || (node->type() == Node::Function && static_cast(node)->metaness() == FunctionNode::Signal)) { Text text; if (!alsoList.isEmpty()) { text << Atom(Atom::ListLeft, ATOM_LIST_TAG) << Atom(Atom::ListTagLeft, ATOM_LIST_TAG) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD) << "See Also:" << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << Atom(Atom::ListTagRight, ATOM_LIST_TAG) << Atom(Atom::ListItemLeft, ATOM_LIST_TAG); for (int i = 0; i < alsoList.count(); ++i) { if (i != 0) text << ", "; text << alsoList.at(i); } text << Atom(Atom::ListItemRight, ATOM_LIST_TAG) << Atom(Atom::ListRight, ATOM_LIST_TAG); } generateText(text, node, marker); } else { foreach (const Text &text, alsoList) { out() << "\n@see "; generateText(text, node, marker); } } } QString JavadocGenerator::refForNode( const Node *node ) { if (node->type() == Node::Function) return javaSignature(static_cast(node), JavadocRef); return HtmlGenerator::refForNode(node); } QString JavadocGenerator::linkForNode( const Node *node, const Node *relative ) { // ### EVIL, relative should never be null if (!relative) relative = node; if (packageName(node).isEmpty()) { // ### jasmin: Fixme return QString(); } QString result; if (node->type() == Node::Fake) { result = node->name(); } else { if (!node->isInnerNode()) { result = linkForNode(node->parent(), relative) + "#" + refForNode(node); } else { result = node->name() + ".html"; } } QStringList nodePackage = packageName(node).split("."); QStringList relativePackage = packageName(relative).split("."); if (nodePackage == QStringList(QString()) || relativePackage == QStringList(QString())) { qWarning("I'm in trouble [%s][%s]", qPrintable(node->name()), qPrintable(relative->name())); return QString(); } int i = nodePackage.count() - 1; while (nodePackage.value(i) != relativePackage.value(i)) { result.prepend(nodePackage.at(i) + "/"); --i; } ++i; while (i < relativePackage.count()) { result.prepend("%2E%2E/"); // javadoc 1.5.0_06 chokes on '../' ++i; } return result; } QString JavadocGenerator::refForAtom(Atom *atom, const Node *node) { return HtmlGenerator::refForAtom(atom, node); } /* Neutralize dumb functions called from HtmlGenerator. */ void JavadocGenerator::generateDcf(const QString & /* fileBase */, const QString & /* startPage */, const QString & /* title */, DcfSection & /* dcfRoot */) { } void JavadocGenerator::generateIndex(const QString & /* fileBase */, const QString & /* url */, const QString & /* title */) { } void JavadocGenerator::generateIndent() { for (int i = 0; i < currentDepth; ++i) out() << " "; } void JavadocGenerator::generateDoc(const Node *node, CodeMarker *marker) { const Text &text = node->doc().body(); if (!text.isEmpty()) { out() << " doc=\"/**\n"; Generator::generateStatus(node, marker); generateText(text, node, marker); if (node && node->type() == Node::Function) { const FunctionNode *func = static_cast(node); if (func->metaness() == FunctionNode::Signal) { QStringList slotSignatures; for (int i = func->parameters().count(); i >= 0; --i) slotSignatures += javaSignature(func, SlotSignature, i); Text text; text << Atom(Atom::ListLeft, ATOM_LIST_TAG) << Atom(Atom::ListTagLeft, ATOM_LIST_TAG) << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD); if (slotSignatures.count() == 1) { text << "Compatible Slot Signature:"; } else { text << "Compatible Slot Signatures:"; } text << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD) << Atom(Atom::ListTagRight, ATOM_LIST_TAG); for (int i = 0; i < slotSignatures.count(); ++i) { text << Atom(Atom::ListItemLeft, ATOM_LIST_TAG) << Atom(Atom::C, marker->markedUpCode(slotSignatures.at(i), 0, "")) << Atom(Atom::ListItemRight, ATOM_LIST_TAG); } text << Atom(Atom::ListRight, ATOM_LIST_TAG); generateText(text, node, marker); } } if (node) generateAlsoList(node, marker); out() << " */\""; } } void JavadocGenerator::generateEnumItemDoc(const Text &text, const Node *node, CodeMarker *marker) { out() << " doc=\"/**\n"; if (text.isEmpty()) { out() << "Internal."; } else { generateText(text, node, marker); } out() << " */\""; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/javadocgenerator.h000066400000000000000000000074431215241066400224430ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef JAVADOCGENERATOR_H #define JAVADOCGENERATOR_H #include "htmlgenerator.h" QT_BEGIN_NAMESPACE class JavadocGenerator : public HtmlGenerator { public: JavadocGenerator(); ~JavadocGenerator(); void initializeGenerator(const Config &config); void terminateGenerator(); QString format(); bool canHandleFormat(const QString &format) { return format == "HTML" || format == "javadoc"; } void generateTree(const Tree *tree, CodeMarker *marker); QString typeString(const Node *node); QString imageFileName(const Node *relative, const QString &fileBase); protected: QString fileExtension(const Node *node); void startText( const Node *relative, CodeMarker *marker ); void endText( const Node *relative, CodeMarker *marker ); int generateAtom( const Atom *atom, const Node *relative, CodeMarker *marker ); void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); void generateFakeNode( const FakeNode *fake, CodeMarker *marker ); void generateText( const Text& text, const Node *relative, CodeMarker *marker ); void generateBody( const Node *node, CodeMarker *marker ); void generateAlsoList( const Node *node, CodeMarker *marker ); QString refForNode( const Node *node ); QString linkForNode( const Node *node, const Node *relative ); QString refForAtom(Atom *atom, const Node *node); private: void generateDcf(const QString &fileBase, const QString &startPage, const QString &title, DcfSection &dcfRoot); void generateIndex(const QString &fileBase, const QString &url, const QString &title); void generateIndent(); void generateDoc(const Node *node, CodeMarker *marker); void generateEnumItemDoc(const Text &text, const Node *node, CodeMarker *marker); QString buffer; QIODevice *oldDevice; int currentDepth; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/linguistgenerator.cpp000066400000000000000000000200361215241066400232160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* linguistgenerator.cpp */ #include "codemarker.h" #include "pagegenerator.h" #include "linguistgenerator.h" #include "node.h" #include "separator.h" #include "tree.h" #include #include #include QT_BEGIN_NAMESPACE #define COMMAND_VERSION Doc::alias("version") LinguistGenerator::LinguistGenerator() : PageGenerator() { } LinguistGenerator::~LinguistGenerator() { } void LinguistGenerator::initializeGenerator(const Config &config) { Generator::initializeGenerator(config); } void LinguistGenerator::terminateGenerator() { PageGenerator::terminateGenerator(); } QString LinguistGenerator::format() { return "Linguist"; } QString LinguistGenerator::fileExtension(const Node * /* node */) { return "ts"; } void LinguistGenerator::generateClassLikeNode(const InnerNode *inner, CodeMarker *marker) { out().setCodec("utf-8"); QDomDocument document("TS"); QDomElement documentElement = document.createElement("TS"); documentElement.setAttribute("version", "1.1"); QList contextElements = generateIndexSections(document, inner, marker); foreach (const QDomElement &element, contextElements) documentElement.appendChild(element); QDomProcessingInstruction process = document.createProcessingInstruction( "xml", QString("version=\"1.0\" encoding=\"%1\"").arg("utf-8")); document.appendChild(process); document.appendChild(documentElement); out() << document; out().flush(); } void LinguistGenerator::generateFakeNode( const FakeNode *fake, CodeMarker *marker ) { out().setCodec("utf-8"); QDomDocument document("TS"); QDomElement documentElement = document.createElement("TS"); documentElement.setAttribute("version", "1.1"); QList contextElements = generateIndexSections(document, fake, marker); foreach (const QDomElement &element, contextElements) documentElement.appendChild(element); QDomProcessingInstruction process = document.createProcessingInstruction( "xml", QString("version=\"1.0\" encoding=\"%1\"").arg("utf-8")); document.appendChild(process); document.appendChild(documentElement); out() << document; out().flush(); } QList LinguistGenerator::generateIndexSections( QDomDocument &document, const Node *node, CodeMarker *marker) { QList contexts; if (node->isInnerNode()) { const InnerNode *inner = static_cast(node); foreach (const Node *child, inner->childNodes()) { // Recurse to generate a DOM element for this child node and all // its children. contexts += generateIndexSections(document, child, marker); } /* foreach (const Node *child, inner->relatedNodes()) { QDomElement childElement = generateIndexSections(document, child, marker); element.appendChild(childElement); } */ } // Add documentation to this node if it exists. if (!node->doc().isEmpty()) { QString nodeName = fullName(node); QString signature; if (node->type() == Node::Function) { QStringList pieces; const FunctionNode *functionNode = static_cast(node); foreach (const Parameter ¶meter, functionNode->parameters()) { QString typeString = parameter.leftType() + parameter.rightType(); if (typeString.split(" ").size() > 1) pieces.append(typeString + parameter.name()); else pieces.append(typeString + " " + parameter.name()); } signature = "(" + pieces.join(", ") + ")"; } QDomElement contextElement = document.createElement("context"); QDomElement nameElement = document.createElement("name"); nameElement.appendChild(document.createTextNode(nodeName + signature)); contextElement.appendChild(nameElement); QDomElement messageElement = document.createElement("message"); contextElement.appendChild(messageElement); QDomElement sourceElement = document.createElement("source"); QString sourceText = simplified(node->doc().source()); if (!signature.isEmpty() && signature != "()" && !sourceText.contains("\\fn")) sourceText.prepend(QString("\\fn %1%2\n").arg(nodeName).arg(signature)); sourceElement.appendChild(document.createTextNode(sourceText)); messageElement.appendChild(sourceElement); QDomElement translationElement = document.createElement("translation"); translationElement.setAttribute("type", "unfinished"); messageElement.appendChild(translationElement); QDomElement locationElement = document.createElement("location"); locationElement.setAttribute("filename", node->doc().location().filePath()); locationElement.setAttribute("line", node->doc().location().lineNo()); messageElement.appendChild(locationElement); contexts.append(contextElement); } return contexts; } QString LinguistGenerator::fullName(const Node *node) const { if (!node) return ""; else if (node->parent() && !node->parent()->name().isEmpty()) return fullName(node->parent()) + "::" + node->name(); else return node->name(); } QString LinguistGenerator::simplified(const QString &text) const { QStringList lines = text.split("\n"); while (lines.size() > 0 && lines.first().trimmed().isEmpty()) lines.pop_front(); while (lines.size() > 0 && lines.last().trimmed().isEmpty()) lines.pop_back(); int min = 0; bool set = false; foreach (const QString &line, lines) { int j = 0; while (j < line.length()) { if (line[j] != ' ') break; ++j; } if (j < line.length()) { if (!set) { min = j; set = true; } else min = qMin(min, j); } } for (int i = 0; i < lines.size(); ++i) lines[i] = lines[i].mid(min); return lines.join("\n"); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/linguistgenerator.h000066400000000000000000000056371215241066400226750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* LinguistGenerator.h */ #ifndef LINGUISTGENERATOR_H #define LINGUISTGENERATOR_H #include #include #include #include "codemarker.h" #include "config.h" #include "pagegenerator.h" QT_BEGIN_NAMESPACE class LinguistGenerator : public PageGenerator { public: LinguistGenerator(); ~LinguistGenerator(); virtual void initializeGenerator( const Config& config ); virtual void terminateGenerator(); virtual QString format(); protected: virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); virtual void generateFakeNode( const FakeNode *fake, CodeMarker *marker ); virtual QString fileExtension(const Node *node); QList generateIndexSections(QDomDocument &document, const Node *node, CodeMarker *marker); virtual QString fullName(const Node *node) const; private: QString simplified(const QString &text) const; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/location.cpp000066400000000000000000000241151215241066400212630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "config.h" #include "location.h" #include #include #include #include #include QT_BEGIN_NAMESPACE QT_STATIC_CONST_IMPL Location Location::null; int Location::tabSize; QString Location::programName; QRegExp *Location::spuriousRegExp = 0; /*! \class Location \brief The Location class keeps track of where we are in a file. It maintains a stack of file positions. A file position consists of the file path, line number, and column number. The location is used for printing error messages that are tied to a location in a file. */ /*! Constructs an empty location. */ Location::Location() : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false) { // nothing. } /*! Constructs a location with (fileName, 1, 1) on its file position stack. */ Location::Location(const QString& fileName) : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false) { push(fileName); } /*! The copy constructor copies the contents of \a other into this Location using the assignment operator. */ Location::Location(const Location& other) : stk(0), stkTop(&stkBottom), stkDepth(0), etcetera(false) { *this = other; } /*! The assignment operator does a deep copy of the entire state of \a other into this Location. */ Location& Location::operator=(const Location& other) { QStack *oldStk = stk; stkBottom = other.stkBottom; if (other.stk == 0) { stk = 0; stkTop = &stkBottom; } else { stk = new QStack(*other.stk); stkTop = &stk->top(); } stkDepth = other.stkDepth; etcetera = other.etcetera; delete oldStk; return *this; } /*! If the file position on top of the stack has a line number less than 1, set its line number to 1 and its column number to 1. Otherwise, do nothing. */ void Location::start() { if (stkTop->lineNo < 1) { stkTop->lineNo = 1; stkTop->columnNo = 1; } } /*! Advance the current file position, using \a ch to decide how to do that. If \a ch is a \c{'\\n'}, increment the current line number and set the column number to 1. If \ch is a \c{'\\t'}, increment to the next tab column. Otherwise, increment the column number by 1. The current file position is the one on top of the position stack. */ void Location::advance(QChar ch) { if (ch == QLatin1Char('\n')) { stkTop->lineNo++; stkTop->columnNo = 1; } else if (ch == QLatin1Char('\t')) { stkTop->columnNo = 1 + tabSize * (stkTop->columnNo + tabSize-1) / tabSize; } else { stkTop->columnNo++; } } /*! Pushes \a filePath onto the file position stack. The current file position becomes (\a filePath, 1, 1). \sa pop() */ void Location::push(const QString& filePath) { if (stkDepth++ >= 1) { if (stk == 0) stk = new QStack; stk->push(StackEntry()); stkTop = &stk->top(); } stkTop->filePath = filePath; stkTop->lineNo = INT_MIN; stkTop->columnNo = 1; } /*! Pops the top of the internal stack. The current file position becomes the next one in the new top of stack. \sa push() */ void Location::pop() { if (--stkDepth == 0) { stkBottom = StackEntry(); } else { stk->pop(); if (stk->isEmpty()) { delete stk; stk = 0; stkTop = &stkBottom; } else { stkTop = &stk->top(); } } } /*! \fn bool Location::isEmpty() const Returns true if there is no file name set yet; returns false otherwise. The functions filePath(), lineNo() and columnNo() must not be called on an empty Location object. */ /*! \fn const QString& Location::filePath() const Returns the current path and file name. Must not be called on an empty Location object. \sa lineNo(), columnNo() */ /*! Returns the file name part of the file path, ie the current file. Must not be called on an empty Location object. */ QString Location::fileName() const { QString fp = filePath(); return fp.mid(fp.lastIndexOf('/') + 1); } /*! \fn int Location::lineNo() const Returns the current line number. Must not be called on an empty Location object. \sa filePath(), columnNo() */ /*! \fn int Location::columnNo() const Returns the current column number. Must not be called on an empty Location object. \sa filePath(), lineNo() */ /*! Writes \a message and \a detals to stderr as a formatted warning message. */ void Location::warning(const QString& message, const QString& details) const { emitMessage(Warning, message, details); } /*! Writes \a message and \a detals to stderr as a formatted error message. */ void Location::error(const QString& message, const QString& details) const { emitMessage(Error, message, details); } /*! Writes \a message and \a detals to stderr as a formatted error message and then exits the program. */ void Location::fatal(const QString& message, const QString& details) const { emitMessage(Error, message, details); information("Aborting"); exit(EXIT_FAILURE); } /*! Gets several parameters from the \a config, including tab size, program name, and a regular expression that appears to be used for matching certain error messages so that emitMessage() can avoid printing them. */ void Location::initialize(const Config& config) { tabSize = config.getInt(CONFIG_TABSIZE); programName = config.programName(); QRegExp regExp = config.getRegExp(CONFIG_SPURIOUS); if (regExp.isValid()) { spuriousRegExp = new QRegExp(regExp); } else { config.lastLocation().warning(tr("Invalid regular expression '%1'") .arg(regExp.pattern())); } } /*! Apparently, all this does is delete the regular expression used for intercepting certain error messages that should not be emitted by emitMessage(). */ void Location::terminate() { delete spuriousRegExp; spuriousRegExp = 0; } /*! Prints \a message to \c stdout followed by a \c{'\n'}. */ void Location::information(const QString& message) { printf("%s\n", message.toLatin1().data()); fflush(stdout); } /*! Report a program bug, including the \a hint. */ void Location::internalError(const QString& hint) { Location::null.fatal(tr("Internal error (%1)").arg(hint), tr("There is a bug in %1. Seek advice from your local" " %2 guru.") .arg(programName).arg(programName)); } /*! Formats \a message and \a details into a single string and outputs that string to \c stderr. \a type specifies whether the \a message is an error or a warning. */ void Location::emitMessage(MessageType type, const QString& message, const QString& details) const { if (type == Warning && spuriousRegExp != 0 && spuriousRegExp->exactMatch(message)) return; QString result = message; if (!details.isEmpty()) result += "\n[" + details + "]"; result.replace("\n", "\n "); if (type == Error) result.prepend(tr("error: ")); result.prepend(toString()); fprintf(stderr, "%s\n", result.toLatin1().data()); fflush(stderr); } /*! Converts the location to a string to be prepended to error messages. */ QString Location::toString() const { QString str; if (isEmpty()) { str = programName; } else { Location loc2 = *this; loc2.setEtc(false); loc2.pop(); if (!loc2.isEmpty()) { QString blah = tr("In file included from "); for (;;) { str += blah; str += loc2.top(); loc2.pop(); if (loc2.isEmpty()) break; str += tr(","); str += QLatin1Char('\n'); blah.fill(' '); } str += tr(":"); str += QLatin1Char('\n'); } str += top(); } str += QLatin1String(": "); return str; } QString Location::top() const { QString str = filePath(); if (lineNo() >= 1) { str += QLatin1Char(':'); str += QString::number(lineNo()); #if 0 if (columnNo() >= 1) str += ":" + QString::number(columnNo()); #endif } if (etc()) str += QLatin1String(" (etc.)"); return str; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/location.h000066400000000000000000000077661215241066400207450ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* location.h */ #ifndef LOCATION_H #define LOCATION_H #include #include "tr.h" #define QDOC_QML QT_BEGIN_NAMESPACE class Config; class QRegExp; class Location { public: Location(); Location(const QString& filePath); Location(const Location& other); ~Location() { delete stk; } Location& operator=(const Location& other); void start(); void advance(QChar ch); void advanceLines(int n) { stkTop->lineNo += n; stkTop->columnNo = 1; } void push(const QString& filePath); void pop(); void setEtc(bool etc) { etcetera = etc; } void setLineNo(int no) { stkTop->lineNo = no; } void setColumnNo(int no) { stkTop->columnNo = no; } bool isEmpty() const { return stkDepth == 0; } int depth() const { return stkDepth; } const QString& filePath() const { return stkTop->filePath; } QString fileName() const; int lineNo() const { return stkTop->lineNo; } int columnNo() const { return stkTop->columnNo; } bool etc() const { return etcetera; } void warning(const QString& message, const QString& details = QString()) const; void error(const QString& message, const QString& details = QString()) const; void fatal(const QString& message, const QString& details = QString()) const; QT_STATIC_CONST Location null; static void initialize(const Config& config); static void terminate(); static void information(const QString& message); static void internalError(const QString& hint); private: enum MessageType { Warning, Error }; struct StackEntry { QString filePath; int lineNo; int columnNo; }; void emitMessage(MessageType type, const QString& message, const QString& details) const; QString toString() const; QString top() const; private: StackEntry stkBottom; QStack *stk; StackEntry *stkTop; int stkDepth; bool etcetera; static int tabSize; static QString programName; static QRegExp *spuriousRegExp; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/loutgenerator.cpp000066400000000000000000000042011215241066400223370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* loutgenerator.cpp */ #include "loutgenerator.h" QT_BEGIN_NAMESPACE LoutGenerator::LoutGenerator() { } LoutGenerator::~LoutGenerator() { } QString LoutGenerator::format() { return "lout"; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/loutgenerator.h000066400000000000000000000043211215241066400220070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* loutgenerator.h */ #ifndef LOUTGENERATOR_H #define LOUTGENERATOR_H #include "bookgenerator.h" QT_BEGIN_NAMESPACE class LoutGenerator : public BookGenerator { public: LoutGenerator(); ~LoutGenerator(); virtual QString format(); protected: // ### }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/main.cpp000066400000000000000000000355001215241066400203770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* main.cpp */ #include #include #include "apigenerator.h" #include "codemarker.h" #include "codeparser.h" #include "config.h" #include "cppcodemarker.h" #include "cppcodeparser.h" #include "cpptoqsconverter.h" #include "doc.h" #include "htmlgenerator.h" #include "jambiapiparser.h" #include "javacodemarker.h" #include "javadocgenerator.h" #include "linguistgenerator.h" #include "loutgenerator.h" #include "mangenerator.h" #include "plaincodemarker.h" #include "polyarchiveextractor.h" #include "polyuncompressor.h" #include "qsakernelparser.h" #include "qscodemarker.h" #include "qscodeparser.h" #include "sgmlgenerator.h" #include "webxmlgenerator.h" #include "tokenizer.h" #include "tree.h" QT_BEGIN_NAMESPACE /* The default indent for code is 4. The default value for false is 0. The default language is c++. The default output format is html. The default tab size is 8. And those are all the default values for configuration variables. */ static const struct { const char *key; const char *value; } defaults[] = { { CONFIG_CODEINDENT, "4" }, { CONFIG_FALSEHOODS, "0" }, { CONFIG_LANGUAGE, "Cpp" }, { CONFIG_OUTPUTFORMATS, "HTML" }, { CONFIG_TABSIZE, "8" }, { 0, 0 } }; static bool slow = false; static QStringList defines; static QHash trees; //static int doxygen = 0; /*! Find the Tree for language \a lang and return a pointer to it. If there is no Tree for language \a lang in the Tree table, add a new one. The Tree table is indexed by \a lang strings. */ static Tree* treeForLanguage(const QString &lang) { Tree* tree = trees.value(lang); if (tree == 0) { tree = new Tree; trees.insert( lang, tree ); } return tree; } /*! Print the help message to \c stdout. */ static void printHelp() { Location::information(tr("Usage: qdoc [options] file1.qdocconf ...\n" "Options:\n" " -help " "Display this information and exit\n" " -version " "Display version of qdoc and exit\n" " -D " "Define as a macro while parsing sources\n" " -slow " "Turn on features that slow down qdoc") ); } /*! Prints the qdoc version number to stdout. */ static void printVersion() { Location::information(tr("qdoc version 4.4.1")); } /*! Processes the qdoc config file \a fileName. This is the controller for all of qdoc. */ static void processQdocconfFile(const QString &fileName) { QList translators; /* The Config instance represents the configuration data for qdoc. All the other classes are initialized with the config. Here we initialize the configuration with some default values. */ Config config(tr("qdoc")); int i = 0; while (defaults[i].key) { config.setStringList(defaults[i].key, QStringList() << defaults[i].value); ++i; } config.setStringList(CONFIG_SLOW, QStringList(slow ? "true" : "false")); /* With the default configuration values in place, load the qdoc configuration file. Note that the configuration file may include other configuration files. The Location class keeps track of the current location in the file being processed, mainly for error reporting purposes. */ Location::initialize(config); config.load(fileName); /* Add the defines to the configuration variables. */ QStringList defs = defines + config.getStringList(CONFIG_DEFINES); config.setStringList(CONFIG_DEFINES,defs); Location::terminate(); QString prevCurrentDir = QDir::currentPath(); QString dir = QFileInfo(fileName).path(); if (!dir.isEmpty()) QDir::setCurrent(dir); /* Initialize all the classes and data structures with the qdoc configuration. */ Location::initialize(config); Tokenizer::initialize(config); Doc::initialize(config); CppToQsConverter::initialize(config); CodeMarker::initialize(config); CodeParser::initialize(config); Generator::initialize(config); /* Load the language translators, if the configuration specifies any. */ QStringList fileNames = config.getStringList(CONFIG_TRANSLATORS); QStringList::Iterator fn = fileNames.begin(); while (fn != fileNames.end()) { QTranslator *translator = new QTranslator(0); if (!translator->load(*fn)) config.lastLocation().error(tr("Cannot load translator '%1'") .arg(*fn)); QCoreApplication::instance()->installTranslator(translator); translators.append(translator); ++fn; } //QSet outputLanguages = config.getStringSet(CONFIG_OUTPUTLANGUAGES); /* Get the source language (Cpp) from the configuration and the location in the configuration file where the source language was set. */ QString lang = config.getString(CONFIG_LANGUAGE); Location langLocation = config.lastLocation(); #ifdef QDOC2DOX // qdoc -> doxygen if (doxygen == 2) { qDebug() << "READING anchors.txt"; DoxWriter::readAnchors(); qDebug() << "READING title maps"; DoxWriter::readTitles(); qDebug() << "READING member multimaps"; DoxWriter::readMembers(); } #endif /* Initialize the tree where all the parsed sources will be stored. The tree gets built as the source files are parsed, and then the documentation output is generated by traversing the tree. */ Tree *tree = new Tree; tree->setVersion(config.getString(CONFIG_VERSION)); /* There must be a code parser for the source code language, e.g. C++. If there isn't one, give up. */ CodeParser *codeParser = CodeParser::parserForLanguage(lang); if (codeParser == 0) config.lastLocation().fatal(tr("Cannot parse programming language '%1'").arg(lang)); /* By default, the only output format is HTML. */ QSet outputFormats = config.getStringSet(CONFIG_OUTPUTFORMATS); Location outputFormatsLocation = config.lastLocation(); /* There must be a code marker for the source code language, e.g. C++. If there isn't one, give up. */ CodeMarker *marker = CodeMarker::markerForLanguage(lang); if (!marker && !outputFormats.isEmpty()) langLocation.fatal(tr("Cannot output documentation for programming language '%1'").arg(lang)); /* Read some XML indexes. What are they??? */ QStringList indexFiles = config.getStringList(CONFIG_INDEXES); tree->readIndexes(indexFiles); /* Get all the header files: "*.ch *.h *.h++ *.hh *.hpp *.hxx" Put them in a set. */ QSet excludedDirs; QStringList excludedDirsList = config.getStringList(CONFIG_EXCLUDEDIRS); foreach (const QString &excludeDir, excludedDirsList) excludedDirs.insert(QDir::fromNativeSeparators(excludeDir)); QSet headers = QSet::fromList( config.getAllFiles(CONFIG_HEADERS, CONFIG_HEADERDIRS, codeParser->headerFileNameFilter(), excludedDirs)); /* Parse each header file in the set and add it to the big tree. */ QSet::ConstIterator h = headers.begin(); while (h != headers.end()) { codeParser->parseHeaderFile(config.location(), *h, tree); ++h; } codeParser->doneParsingHeaderFiles(tree); /* Get all the source text files: "*.cpp *.qdoc *.mm" Put them in a set. */ QSet sources = QSet::fromList( config.getAllFiles(CONFIG_SOURCES, CONFIG_SOURCEDIRS, codeParser->sourceFileNameFilter(), excludedDirs)); /* Parse each source text file in the set and add it to the big tree. */ QSet::ConstIterator s = sources.begin(); while (s != sources.end()) { codeParser->parseSourceFile(config.location(), *s, tree); ++s; } codeParser->doneParsingSourceFiles(tree); /* Now the big tree has been built from all the header and source files. Resolve all the class names, function names, targets, URLs, links, and other stuff that needs resolving. */ tree->resolveGroups(); tree->resolveTargets(); #ifdef QDOC2DOX // qdoc -> doxygen if (doxygen == 1) { DoxWriter::writeAnchors(); DoxWriter::writeTitles(); DoxWriter::writeMembers(); } if (doxygen == 0) { #endif /* Now the tree has been built, and all the stuff that needed resolving has been resolved. Now it is time to traverse the big tree and generate the documentation output. */ QSet::ConstIterator of = outputFormats.begin(); while (of != outputFormats.end()) { Generator *generator = Generator::generatorForFormat(*of); if (generator == 0) outputFormatsLocation.fatal(tr("Unknown output format '%1'") .arg(*of)); generator->generateTree(tree, marker); ++of; } /* Generate the XML tag file, if it was requested. */ QString tagFile = config.getString(CONFIG_TAGFILE); if (!tagFile.isEmpty()) tree->generateTagFile(tagFile); tree->setVersion(""); Generator::terminate(); #ifdef QDOC2DOX } #endif CodeParser::terminate(); CodeMarker::terminate(); CppToQsConverter::terminate(); Doc::terminate(); Tokenizer::terminate(); Location::terminate(); QDir::setCurrent(prevCurrentDir); foreach (QTranslator *translator, translators) delete translator; delete tree; } QT_END_NAMESPACE int main(int argc, char **argv) { QT_USE_NAMESPACE QCoreApplication app(argc, argv); QString cf = "qsauncompress \1 \2"; PolyArchiveExtractor qsaExtractor(QStringList() << "qsa",cf); cf = "tar -C \2 -xf \1"; PolyArchiveExtractor tarExtractor(QStringList() << "tar",cf); cf = "tar -C \2 -Zxf \1"; PolyArchiveExtractor tazExtractor(QStringList() << "taz",cf); cf = "tar -C \2 -jxf \1"; PolyArchiveExtractor tbz2Extractor(QStringList() << "tbz" << "tbz2",cf); cf = "tar -C \2 -zxf \1"; PolyArchiveExtractor tgzExtractor(QStringList() << "tgz",cf); cf = "unzip \1 -d \2"; PolyArchiveExtractor zipExtractor(QStringList() << "zip",cf); cf = "bunzip2 -c \1 > \2"; PolyUncompressor bz2Uncompressor(QStringList() << "bz" << "bz2",cf); cf = "gunzip -c \1 > \2"; PolyUncompressor gzAndZUncompressor(QStringList() << "gz" << "z" << "Z",cf); cf = "unzip -c \1 > \2"; PolyUncompressor zipUncompressor(QStringList() << "zip",cf); /* Create code parsers for the languages to be parsed, and create a tree for C++. */ CppCodeParser cppParser; Tree *cppTree = treeForLanguage(cppParser.language()); QsCodeParser qsParser(cppTree); QsaKernelParser qsaKernelParser(cppTree); JambiApiParser jambiParser(cppTree); /* Create code markers for plain text, C++, Java, and qs. */ PlainCodeMarker plainMarker; CppCodeMarker cppMarker; JavaCodeMarker javaMarker; QsCodeMarker qsMarker; ApiGenerator apiGenerator; HtmlGenerator htmlGenerator; JavadocGenerator javadocGenerator; LinguistGenerator linguistGenerator; LoutGenerator loutGenerator; ManGenerator manGenerator; SgmlGenerator smglGenerator; WebXMLGenerator webxmlGenerator; QStringList qdocFiles; QString opt; int i = 1; while (i < argc) { opt = argv[i++]; if (opt == "-help") { printHelp(); return EXIT_SUCCESS; } else if (opt == "-version") { printVersion(); return EXIT_SUCCESS; } else if (opt == "--") { while (i < argc) qdocFiles.append(argv[i++]); } else if (opt.startsWith("-D")) { QString define = opt.mid(2); defines += define; } else if (opt == "-slow") { slow = true; } #ifdef QDOC2DOX else if (opt == "-doxygen1") { // qdoc -> doxygen // Don't use this; it isn't ready yet. // Now it's a fossil. qDebug() << "doxygen pass 1"; doxygen = 1; DoxWriter::setDoxPass(1); } else if (opt == "-doxygen2") { // qdoc -> doxygen // Don't use this; it isn't ready yet. // Now it's a fossil. qDebug() << "doxygen pass 2"; doxygen = 2; DoxWriter::setDoxPass(2); } #endif else { qdocFiles.append(opt); } } if (qdocFiles.isEmpty()) { printHelp(); return EXIT_FAILURE; } /* Main loop. */ foreach (QString qf, qdocFiles) processQdocconfFile(qf); qDeleteAll(trees); return EXIT_SUCCESS; } libqxt-0.6.2/tools/3rdparty/qdoc3/mangenerator.cpp000066400000000000000000000125541215241066400221410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* mangenerator.cpp */ #include #include #include "mangenerator.h" #include "node.h" #include "tree.h" QT_BEGIN_NAMESPACE ManGenerator::ManGenerator() { date = QDate::currentDate().toString( "d MMMM yyyy" ); } ManGenerator::~ManGenerator() { } QString ManGenerator::format() { return "man"; } int ManGenerator::generateAtom( const Atom *atom, const Node * /* relative */, CodeMarker * /* marker */ ) { #if 0 switch ( atom->type() ) { case Atom::AbstractBegin: break; case Atom::AbstractEnd: break; case Atom::Alias: break; case Atom::AliasArg: break; case Atom::BaseName: break; case Atom::BriefBegin: break; case Atom::BriefEnd: break; case Atom::C: break; case Atom::CaptionBegin: break; case Atom::CaptionEnd: break; case Atom::CitationBegin: break; case Atom::CitationEnd: break; case Atom::Code: break; case Atom::FootnoteBegin: break; case Atom::FootnoteEnd: break; case Atom::FormatBegin: break; case Atom::FormatEnd: break; case Atom::GeneratedList: break; case Atom::Image: break; case Atom::ImageText: break; case Atom::Link: break; case Atom::LinkNode: break; case Atom::ListBegin: break; case Atom::ListItemNumber: break; case Atom::ListItemBegin: out() << ".IP " << atom->string() << ".\n"; break; case Atom::ListItemEnd: break; case Atom::ListEnd: break; case Atom::Nop: break; case Atom::ParaBegin: out() << ".PP\n"; break; case Atom::ParaEnd: out() << "\n"; break; case Atom::RawFormat: break; case Atom::RawString: break; case Atom::SectionBegin: break; case Atom::SectionEnd: break; case Atom::SectionHeadingBegin: break; case Atom::SectionHeadingEnd: break; case Atom::SidebarBegin: break; case Atom::SidebarEnd: break; case Atom::String: out() << protectTextLine( atom->string() ); break; case Atom::TableBegin: break; case Atom::TableEnd: break; case Atom::TableOfContents: break; case Atom::Target: break; case Atom::UnknownCommand: ; } #endif unknownAtom( atom ); return 0; } void ManGenerator::generateClassLikeNode( const InnerNode *classe, CodeMarker *marker ) { generateHeader( classe->name() ); out() << ".SH NAME\n" << classe->name() << "\n" << ".SH SYNOPSYS\n"; generateBody( classe, marker ); generateFooter(); } void ManGenerator::generateFakeNode( const FakeNode *fake, CodeMarker *marker ) { generateHeader( "foo" ); generateBody( fake, marker ); generateFooter(); } QString ManGenerator::fileExtension(const Node * /* node */) { return "3qt"; } void ManGenerator::generateHeader( const QString& name ) { out() << ".TH " << protectArg( name ) << " " << protectArg( "3qt" ) << " " << protectArg( date ) << " " << protectArg( "Nokia Corporation and/or its subsidiary(-ies)" ) << " " << protectArg( "Qt Toolkit" ) << "\n"; } void ManGenerator::generateFooter() { } QString ManGenerator::protectArg( const QString& str ) { for ( int i = 0; i < (int) str.length(); i++ ) { if ( str[i] == ' ' || str[i].isSpace() ) { QString quoted = str; quoted.replace( "\"", "\"\"" ); return "\"" + quoted + "\""; } } return str; } QString ManGenerator::protectTextLine( const QString& str ) { QString t = str; if ( t.startsWith(".") || t.startsWith("'") ) t.prepend( "\\&" ); return t; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/mangenerator.h000066400000000000000000000053051215241066400216020ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* mangenerator.h */ #ifndef MANGENERATOR_H #define MANGENERATOR_H #include "pagegenerator.h" QT_BEGIN_NAMESPACE class ManGenerator : public PageGenerator { public: ManGenerator(); ~ManGenerator(); virtual QString format(); protected: virtual int generateAtom( const Atom *atom, const Node *relative, CodeMarker *marker ); virtual void generateClassLikeNode(const InnerNode *node, CodeMarker *marker); virtual void generateFakeNode( const FakeNode *fake, CodeMarker *marker ); virtual QString fileExtension(const Node *node); private: void generateHeader( const QString& name ); void generateFooter(); QString protectArg( const QString& str ); QString protectTextLine( const QString& str ); QString date; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/node.cpp000066400000000000000000000530051215241066400204000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* node.cpp */ #include "node.h" QT_BEGIN_NAMESPACE /*! \class Node \brief A node in a Tree. */ /*! */ Node::~Node() { if (par) par->removeChild(this); if (rel) rel->removeRelated(this); } /*! */ void Node::setDoc(const Doc& doc, bool replace) { if (!d.isEmpty() && !replace) { doc.location().warning(tr("Overrides a previous doc")); d.location().warning(tr("(The previous doc is here)")); } d = doc; } /*! */ Node::Node(Type type, InnerNode *parent, const QString& name) : typ(type), acc(Public), sta(Commendable), saf(UnspecifiedSafeness), par(parent), rel(0), nam(name) { if (par) par->addChild(this); } /*! */ QString Node::url() const { return u; } /*! */ void Node::setUrl(const QString &url) { u = url; } /*! */ void Node::setRelates(InnerNode *pseudoParent) { if (rel) rel->removeRelated(this); rel = pseudoParent; pseudoParent->related.append(this); } /*! */ void Node::setLink(LinkType linkType, const QString &link, const QString &desc) { QPair linkPair; linkPair.first = link; linkPair.second = desc; linkMap[linkType] = linkPair; } /*! */ Node::Status Node::inheritedStatus() const { Status parentStatus = Commendable; if (par) parentStatus = par->inheritedStatus(); return (Status)qMin((int)sta, (int)parentStatus); } /*! */ Node::ThreadSafeness Node::threadSafeness() const { if (par && saf == par->inheritedThreadSafeness()) return UnspecifiedSafeness; return saf; } /*! */ Node::ThreadSafeness Node::inheritedThreadSafeness() const { if (par && saf == UnspecifiedSafeness) return par->inheritedThreadSafeness(); return saf; } /*! */ QString Node::fileBase() const { QString base = name(); if (base.endsWith(".html")) base.chop(5); base.replace(QRegExp("[^A-Za-z0-9]+"), " "); base = base.trimmed(); base.replace(" ", "-"); return base.toLower(); } /*! \class InnerNode */ /*! */ InnerNode::~InnerNode() { deleteChildren(); removeFromRelated(); } /*! */ Node *InnerNode::findNode(const QString& name) { Node *node = childMap.value(name); if (node) return node; return primaryFunctionMap.value(name); } /*! */ Node *InnerNode::findNode(const QString& name, Type type) { if (type == Function) { return primaryFunctionMap.value(name); } else { Node *node = childMap.value(name); if (node && node->type() == type) { return node; } else { return 0; } } } /*! */ FunctionNode *InnerNode::findFunctionNode(const QString& name) { return static_cast(primaryFunctionMap.value(name)); } /*! */ FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) { QMap::ConstIterator c = primaryFunctionMap.find(clone->name()); if (c != primaryFunctionMap.end()) { if (isSameSignature(clone, (FunctionNode *) *c)) { return (FunctionNode *) *c; } else if (secondaryFunctionMap.contains(clone->name())) { const NodeList& secs = secondaryFunctionMap[clone->name()]; NodeList::ConstIterator s = secs.begin(); while (s != secs.end()) { if (isSameSignature(clone, (FunctionNode *) *s)) return (FunctionNode *) *s; ++s; } } } return 0; } /*! */ void InnerNode::setOverload(const FunctionNode *func, bool overlode) { Node *node = (Node *) func; Node *&primary = primaryFunctionMap[func->name()]; if (secondaryFunctionMap.contains(func->name())) { NodeList& secs = secondaryFunctionMap[func->name()]; if (overlode) { if (primary == node) { primary = secs.first(); secs.erase(secs.begin()); secs.append(node); } else { secs.removeAll(node); secs.append(node); } } else { if (primary != node) { secs.removeAll(node); secs.prepend(primary); primary = node; } } } } /*! */ void InnerNode::makeUndocumentedChildrenInternal() { foreach (Node *child, childNodes()) { if (child->doc().isEmpty()) { child->setAccess(Node::Private); child->setStatus(Node::Internal); } } } /*! */ void InnerNode::normalizeOverloads() { QMap::Iterator p1 = primaryFunctionMap.begin(); while (p1 != primaryFunctionMap.end()) { FunctionNode *primaryFunc = (FunctionNode *) *p1; if (secondaryFunctionMap.contains(primaryFunc->name()) && (primaryFunc->status() != Commendable || primaryFunc->access() == Private)) { NodeList& secs = secondaryFunctionMap[primaryFunc->name()]; NodeList::ConstIterator s = secs.begin(); while (s != secs.end()) { FunctionNode *secondaryFunc = (FunctionNode *) *s; // Any non-obsolete, non-compatibility, non-private functions // (i.e, visible functions) are preferable to the primary // function. if (secondaryFunc->status() == Commendable && secondaryFunc->access() != Private) { *p1 = secondaryFunc; int index = secondaryFunctionMap[primaryFunc->name()].indexOf(secondaryFunc); secondaryFunctionMap[primaryFunc->name()].replace(index, primaryFunc); break; } ++s; } } ++p1; } QMap::ConstIterator p = primaryFunctionMap.begin(); while (p != primaryFunctionMap.end()) { FunctionNode *primaryFunc = (FunctionNode *) *p; if (primaryFunc->isOverload()) primaryFunc->ove = false; if (secondaryFunctionMap.contains(primaryFunc->name())) { NodeList& secs = secondaryFunctionMap[primaryFunc->name()]; NodeList::ConstIterator s = secs.begin(); while (s != secs.end()) { FunctionNode *secondaryFunc = (FunctionNode *) *s; if (!secondaryFunc->isOverload()) secondaryFunc->ove = true; ++s; } } ++p; } NodeList::ConstIterator c = childNodes().begin(); while (c != childNodes().end()) { if ((*c)->isInnerNode()) ((InnerNode *) *c)->normalizeOverloads(); ++c; } } /*! */ void InnerNode::removeFromRelated() { while (!related.isEmpty()) { Node *p = static_cast(related.takeFirst()); if (p != 0 && p->relates() == this) p->clearRelated(); } } /*! */ void InnerNode::deleteChildren() { qDeleteAll(children); } /*! Returns true. */ bool InnerNode::isInnerNode() const { return true; } /*! */ const Node *InnerNode::findNode(const QString& name) const { InnerNode *that = (InnerNode *) this; return that->findNode(name); } /*! */ const Node *InnerNode::findNode(const QString& name, Type type) const { InnerNode *that = (InnerNode *) this; return that->findNode(name, type); } /*! */ const FunctionNode *InnerNode::findFunctionNode(const QString& name) const { InnerNode *that = (InnerNode *) this; return that->findFunctionNode(name); } /*! */ const FunctionNode *InnerNode::findFunctionNode( const FunctionNode *clone) const { InnerNode *that = (InnerNode *) this; return that->findFunctionNode(clone); } /*! */ const EnumNode *InnerNode::findEnumNodeForValue(const QString &enumValue) const { foreach (const Node *node, enumChildren) { const EnumNode *enume = static_cast(node); if (enume->hasItem(enumValue)) return enume; } return 0; } /*! */ int InnerNode::overloadNumber(const FunctionNode *func) const { Node *node = (Node *) func; if (primaryFunctionMap[func->name()] == node) { return 1; } else { return secondaryFunctionMap[func->name()].indexOf(node) + 2; } } /*! */ int InnerNode::numOverloads(const QString& funcName) const { if (primaryFunctionMap.contains(funcName)) { return secondaryFunctionMap[funcName].count() + 1; } else { return 0; } } /*! */ NodeList InnerNode::overloads(const QString &funcName) const { NodeList result; Node *primary = primaryFunctionMap.value(funcName); if (primary) { result << primary; result += secondaryFunctionMap[funcName]; } return result; } /*! */ InnerNode::InnerNode(Type type, InnerNode *parent, const QString& name) : Node(type, parent, name) { } /*! */ void InnerNode::addInclude(const QString& include) { inc.append(include); } /*! */ void InnerNode::setIncludes(const QStringList& includes) { inc = includes; } /*! f1 is always the clone */ bool InnerNode::isSameSignature(const FunctionNode *f1, const FunctionNode *f2) { if (f1->parameters().count() != f2->parameters().count()) return false; if (f1->isConst() != f2->isConst()) return false; QList::ConstIterator p1 = f1->parameters().begin(); QList::ConstIterator p2 = f2->parameters().begin(); while (p2 != f2->parameters().end()) { if ((*p1).hasType() && (*p2).hasType()) { if ((*p1).rightType() != (*p2).rightType()) return false; QString t1 = p1->leftType(); QString t2 = p2->leftType(); if (t1.length() < t2.length()) qSwap(t1, t2); /* ### hack for C++ to handle superfluous "Foo::" prefixes gracefully */ if (t1 != t2 && t1 != (f2->parent()->name() + "::" + t2)) return false; } ++p1; ++p2; } return true; } /*! */ void InnerNode::addChild(Node *child) { children.append(child); if (child->type() == Function) { FunctionNode *func = (FunctionNode *) child; if (!primaryFunctionMap.contains(func->name())) { primaryFunctionMap.insert(func->name(), func); } else { NodeList &secs = secondaryFunctionMap[func->name()]; secs.append(func); } } else { if (child->type() == Enum) enumChildren.append(child); childMap.insert(child->name(), child); } } /*! */ void InnerNode::removeChild(Node *child) { children.removeAll(child); enumChildren.removeAll(child); if (child->type() == Function) { QMap::Iterator prim = primaryFunctionMap.find(child->name()); NodeList& secs = secondaryFunctionMap[child->name()]; if (*prim == child) { if (secs.isEmpty()) { primaryFunctionMap.remove(child->name()); } else { primaryFunctionMap.insert(child->name(), secs.takeFirst()); } } else { secs.removeAll(child); } QMap::Iterator ent = childMap.find( child->name() ); if ( *ent == child ) childMap.erase( ent ); } else { QMap::Iterator ent = childMap.find(child->name()); if (*ent == child) childMap.erase(ent); } } /*! Find the module (QtCore, QtGui, etc.) to which the class belongs. We do this by obtaining the full path to the header file's location and examine everything between "src/" and the filename. This is semi-dirty because we are assuming a particular directory structure. This function is only really useful if the class's module has not been defined in the header file with a QT_MODULE macro or with an \inmodule command in the documentation. */ QString Node::moduleName() const { if (!mod.isEmpty()) return mod; QString path = location().filePath(); QString pattern = QString("src") + QDir::separator(); int start = path.lastIndexOf(pattern); if (start == -1) return ""; QString moduleDir = path.mid(start + pattern.size()); int finish = moduleDir.indexOf(QDir::separator()); if (finish == -1) return ""; QString moduleName = moduleDir.left(finish); if (moduleName == "corelib") return "QtCore"; else if (moduleName == "uitools") return "QtUiTools"; else if (moduleName == "gui") return "QtGui"; else if (moduleName == "network") return "QtNetwork"; else if (moduleName == "opengl") return "QtOpenGL"; else if (moduleName == "qt3support") return "Qt3Support"; else if (moduleName == "svg") return "QtSvg"; else if (moduleName == "sql") return "QtSql"; else if (moduleName == "qtestlib") return "QtTest"; else if (moduleDir.contains("webkit")) return "QtWebKit"; else if (moduleName == "xml") return "QtXml"; else return ""; } /*! */ void InnerNode::removeRelated(Node *pseudoChild) { related.removeAll(pseudoChild); } /*! \class LeafNode */ /*! Returns false because this is an InnerNode. */ bool LeafNode::isInnerNode() const { return false; } /*! */ LeafNode::LeafNode(Type type, InnerNode *parent, const QString& name) : Node(type, parent, name) { } /*! \class NamespaceNode */ /*! */ NamespaceNode::NamespaceNode(InnerNode *parent, const QString& name) : InnerNode(Namespace, parent, name) { } /*! \class ClassNode */ /*! */ ClassNode::ClassNode(InnerNode *parent, const QString& name) : InnerNode(Class, parent, name) { hidden = false; } /*! */ void ClassNode::addBaseClass(Access access, ClassNode *node, const QString &dataTypeWithTemplateArgs) { bas.append(RelatedClass(access, node, dataTypeWithTemplateArgs)); node->der.append(RelatedClass(access, this)); } /*! */ void ClassNode::fixBaseClasses() { int i; i = 0; while (i < bas.size()) { ClassNode *baseClass = bas.at(i).node; if (baseClass->access() == Node::Private) { bas.removeAt(i); const QList &basesBases = baseClass->baseClasses(); for (int j = basesBases.size() - 1; j >= 0; --j) bas.insert(i, basesBases.at(j)); } else { ++i; } } i = 0; while (i < der.size()) { ClassNode *derivedClass = der.at(i).node; if (derivedClass->access() == Node::Private) { der.removeAt(i); const QList &dersDers = derivedClass->derivedClasses(); for (int j = dersDers.size() - 1; j >= 0; --j) der.insert(i, dersDers.at(j)); } else { ++i; } } } /*! \class FakeNode */ /*! */ FakeNode::FakeNode(InnerNode *parent, const QString& name, SubType subType) : InnerNode(Fake, parent, name), sub(subType) { } /*! */ QString FakeNode::fullTitle() const { if (sub == File) { if (title().isEmpty()) return name().mid(name().lastIndexOf('/') + 1) + " Example File"; else return title(); } else if (sub == HeaderFile) { if (title().isEmpty()) return name(); else return name() + " - " + title(); } else { return title(); } } /*! */ QString FakeNode::subTitle() const { if (!stle.isEmpty()) return stle; if (sub == File) { if (title().isEmpty() && name().contains("/")) return name(); } return QString(); } /*! \class EnumNode */ /*! */ EnumNode::EnumNode(InnerNode *parent, const QString& name) : LeafNode(Enum, parent, name), ft(0) { } /*! */ void EnumNode::addItem(const EnumItem& item) { itms.append(item); names.insert(item.name()); } /*! */ Node::Access EnumNode::itemAccess(const QString &name) const { if (doc().omitEnumItemNames().contains(name)) { return Private; } else { return Public; } } /*! Returns the enum value associated with the enum \a name. */ QString EnumNode::itemValue(const QString &name) const { foreach (const EnumItem &item, itms) { if (item.name() == name) return item.value(); } return QString(); } /*! \class TypedefNode */ /*! */ TypedefNode::TypedefNode(InnerNode *parent, const QString& name) : LeafNode(Typedef, parent, name), ae(0) { } /*! */ void TypedefNode::setAssociatedEnum(const EnumNode *enume) { ae = enume; } /*! \class Parameter */ /*! */ Parameter::Parameter(const QString& leftType, const QString& rightType, const QString& name, const QString& defaultValue) : lef(leftType), rig(rightType), nam(name), def(defaultValue) { } /*! */ Parameter::Parameter(const Parameter& p) : lef(p.lef), rig(p.rig), nam(p.nam), def(p.def) { } /*! */ Parameter& Parameter::operator=(const Parameter& p) { lef = p.lef; rig = p.rig; nam = p.nam; def = p.def; return *this; } /*! \class FunctionNode */ /*! */ FunctionNode::FunctionNode(InnerNode *parent, const QString& name) : LeafNode(Function, parent, name), met(Plain), vir(NonVirtual), con(false), sta(false), ove(false), rf(0), ap(0) { } /*! */ void FunctionNode::setOverload(bool overlode) { parent()->setOverload(this, overlode); ove = overlode; } /*! */ void FunctionNode::addParameter(const Parameter& parameter) { params.append(parameter); } /*! */ void FunctionNode::borrowParameterNames(const FunctionNode *source) { QList::Iterator t = params.begin(); QList::ConstIterator s = source->params.begin(); while (s != source->params.end() && t != params.end()) { if (!(*s).name().isEmpty()) (*t).setName((*s).name()); ++s; ++t; } } /*! */ void FunctionNode::setReimplementedFrom(FunctionNode *from) { rf = from; from->rb.append(this); } /*! */ void FunctionNode::setAssociatedProperty(PropertyNode *property) { ap = property; } /*! */ int FunctionNode::overloadNumber() const { return parent()->overloadNumber(this); } /*! */ int FunctionNode::numOverloads() const { return parent()->numOverloads(name()); } /*! */ QStringList FunctionNode::parameterNames() const { QStringList names; QList::ConstIterator p = parameters().begin(); while (p != parameters().end()) { names << (*p).name(); ++p; } return names; } /*! \class PropertyNode */ /*! */ PropertyNode::PropertyNode(InnerNode *parent, const QString& name) : LeafNode(Property, parent, name), sto(Trool_Default), des(Trool_Default), overrides(0) { } /*! */ void PropertyNode::setOverriddenFrom(const PropertyNode *baseProperty) { for (int i = 0; i < NumFunctionRoles; ++i) { if (funcs[i].isEmpty()) funcs[i] = baseProperty->funcs[i]; } if (sto == Trool_Default) sto = baseProperty->sto; if (des == Trool_Default) des = baseProperty->des; overrides = baseProperty; } /*! */ QString PropertyNode::qualifiedDataType() const { if (setters().isEmpty() && resetters().isEmpty()) { if (dt.contains("*") || dt.contains("&")) { // 'QWidget *' becomes 'QWidget *' const return dt + " const"; } else { /* 'int' becomes 'const int' ('int const' is correct C++, but looks wrong) */ return "const " + dt; } } else { return dt; } } /*! */ PropertyNode::Trool PropertyNode::toTrool(bool boolean) { return boolean ? Trool_True : Trool_False; } /*! */ bool PropertyNode::fromTrool(Trool troolean, bool defaultValue) { switch (troolean) { case Trool_True: return true; case Trool_False: return false; default: return defaultValue; } } /*! \class TargetNode */ /*! */ TargetNode::TargetNode(InnerNode *parent, const QString& name) : LeafNode(Target, parent, name) { } /*! Returns false because this is a TargetNode. */ bool TargetNode::isInnerNode() const { return false; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/node.h000066400000000000000000000401761215241066400200520ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* node.h */ #ifndef NODE_H #define NODE_H #include #include #include #include #include "codechunk.h" #include "doc.h" #include "location.h" #include "text.h" QT_BEGIN_NAMESPACE class InnerNode; class Node { public: enum Type { Namespace, Class, Fake, Enum, Typedef, Function, Property, Variable, Target }; enum Access { Public, Protected, Private }; enum Status { Compat, Obsolete, Deprecated, Preliminary, Commendable, Main, Internal }; // don't reorder thisw enum enum ThreadSafeness { UnspecifiedSafeness, NonReentrant, Reentrant, ThreadSafe }; enum LinkType { StartLink, NextLink, PreviousLink, ContentsLink, IndexLink /*, GlossaryLink, CopyrightLink, ChapterLink, SectionLink, SubsectionLink, AppendixLink */ }; virtual ~Node(); void setAccess(Access access) { acc = access; } void setLocation(const Location& location) { loc = location; } void setDoc(const Doc& doc, bool replace = false); void setStatus(Status status) { sta = status; } void setThreadSafeness(ThreadSafeness safeness) { saf = safeness; } void setSince(const QString &since) { sinc = since; } void setRelates(InnerNode *pseudoParent); void setModuleName(const QString &module) { mod = module; } void setLink(LinkType linkType, const QString &link, const QString &desc); void setUrl(const QString &url); void setTemplateStuff(const QString &templateStuff) { tpl = templateStuff; } virtual bool isInnerNode() const = 0; Type type() const { return typ; } InnerNode *parent() const { return par; } InnerNode *relates() const { return rel; } const QString& name() const { return nam; } QMap > links() const { return linkMap; } QString moduleName() const; QString url() const; Access access() const { return acc; } const Location& location() const { return loc; } const Doc& doc() const { return d; } Status status() const { return sta; } Status inheritedStatus() const; ThreadSafeness threadSafeness() const; ThreadSafeness inheritedThreadSafeness() const; QString since() const { return sinc; } QString templateStuff() const { return tpl; } void clearRelated() { rel = 0; } QString fileBase() const; protected: Node(Type type, InnerNode *parent, const QString& name); private: #ifdef Q_WS_WIN Type typ; Access acc; Status sta; ThreadSafeness saf; #else Type typ : 4; Access acc : 2; Status sta : 3; ThreadSafeness saf : 2; #endif InnerNode *par; InnerNode *rel; QString nam; Location loc; Doc d; QMap > linkMap; QString mod; QString u; QString sinc; QString tpl; }; class FunctionNode; class EnumNode; typedef QList NodeList; class InnerNode : public Node { public: ~InnerNode(); Node *findNode(const QString& name); Node *findNode(const QString& name, Type type); FunctionNode *findFunctionNode(const QString& name); FunctionNode *findFunctionNode(const FunctionNode *clone); void addInclude(const QString &include); void setIncludes(const QStringList &includes); void setOverload(const FunctionNode *func, bool overlode); void normalizeOverloads(); void makeUndocumentedChildrenInternal(); void deleteChildren(); void removeFromRelated(); virtual bool isInnerNode() const; const Node *findNode(const QString& name) const; const Node *findNode(const QString& name, Type type) const; const FunctionNode *findFunctionNode(const QString& name) const; const FunctionNode *findFunctionNode(const FunctionNode *clone) const; const EnumNode *findEnumNodeForValue(const QString &enumValue) const; const NodeList & childNodes() const { return children; } const NodeList & relatedNodes() const { return related; } int overloadNumber(const FunctionNode *func) const; int numOverloads(const QString& funcName) const; NodeList overloads(const QString &funcName) const; const QStringList& includes() const { return inc; } protected: InnerNode(Type type, InnerNode *parent, const QString& name); private: friend class Node; static bool isSameSignature(const FunctionNode *f1, const FunctionNode *f2); void addChild(Node *child); void removeChild(Node *child); void removeRelated(Node *pseudoChild); QStringList inc; NodeList children; NodeList enumChildren; NodeList related; QMap childMap; QMap primaryFunctionMap; QMap secondaryFunctionMap; }; class LeafNode : public Node { public: LeafNode(); virtual bool isInnerNode() const; protected: LeafNode(Type type, InnerNode *parent, const QString& name); }; class NamespaceNode : public InnerNode { public: NamespaceNode(InnerNode *parent, const QString& name); }; class ClassNode; struct RelatedClass { RelatedClass() { } RelatedClass(Node::Access access0, ClassNode* node0, const QString& dataTypeWithTemplateArgs0 = "") : access(access0), node(node0), dataTypeWithTemplateArgs(dataTypeWithTemplateArgs0) { } Node::Access access; ClassNode* node; QString dataTypeWithTemplateArgs; }; class ClassNode : public InnerNode { public: ClassNode(InnerNode *parent, const QString& name); void addBaseClass(Access access, ClassNode *node, const QString &dataTypeWithTemplateArgs = ""); void fixBaseClasses(); const QList &baseClasses() const { return bas; } const QList &derivedClasses() const { return der; } bool hideFromMainList() const { return hidden; } void setHideFromMainList(bool value) { hidden = value; } QString serviceName() const { return sname; } void setServiceName(const QString& value) { sname = value; } private: QList bas; QList der; bool hidden; QString sname; }; class FakeNode : public InnerNode { public: enum SubType { Example, HeaderFile, File, Group, Module, Page, ExternalPage, QmlClass }; FakeNode(InnerNode *parent, const QString& name, SubType subType); void setTitle(const QString &title) { tle = title; } void setSubTitle(const QString &subTitle) { stle = subTitle; } void addGroupMember(Node *node) { gr.append(node); } SubType subType() const { return sub; } QString title() const { return tle; } QString fullTitle() const; QString subTitle() const; const NodeList &groupMembers() const { return gr; } private: SubType sub; QString tle; QString stle; NodeList gr; }; class QmlNode : public FakeNode { public: QmlNode(InnerNode *parent, const QString& name, const ClassNode* cn) : FakeNode(parent, name, QmlClass), cnode(cn) { } const ClassNode* classNode() const { return cnode; } private: const ClassNode* cnode; }; class EnumItem { public: EnumItem() { } EnumItem(const QString& name, const QString& value) : nam(name), val(value) { } EnumItem(const QString& name, const QString& value, const Text &txt) : nam(name), val(value), txt(txt) { } const QString& name() const { return nam; } const QString& value() const { return val; } const Text &text() const { return txt; } private: QString nam; QString val; Text txt; }; class TypedefNode; class EnumNode : public LeafNode { public: EnumNode(InnerNode *parent, const QString& name); void addItem(const EnumItem& item); void setFlagsType(TypedefNode *typedeff); bool hasItem(const QString &name) const { return names.contains(name); } const QList& items() const { return itms; } Access itemAccess(const QString& name) const; const TypedefNode *flagsType() const { return ft; } QString itemValue(const QString &name) const; private: QList itms; QSet names; const TypedefNode *ft; }; class TypedefNode : public LeafNode { public: TypedefNode(InnerNode *parent, const QString& name); const EnumNode *associatedEnum() const { return ae; } private: void setAssociatedEnum(const EnumNode *enume); friend class EnumNode; const EnumNode *ae; }; inline void EnumNode::setFlagsType(TypedefNode *typedeff) { ft = typedeff; typedeff->setAssociatedEnum(this); } class Parameter { public: Parameter() {} Parameter(const QString& leftType, const QString& rightType = "", const QString& name = "", const QString& defaultValue = ""); Parameter(const Parameter& p); Parameter& operator=(const Parameter& p); void setName(const QString& name) { nam = name; } bool hasType() const { return lef.length() + rig.length() > 0; } const QString& leftType() const { return lef; } const QString& rightType() const { return rig; } const QString& name() const { return nam; } const QString& defaultValue() const { return def; } private: QString lef; QString rig; QString nam; QString def; }; class PropertyNode; class FunctionNode : public LeafNode { public: enum Metaness { Plain, Signal, Slot, Ctor, Dtor, MacroWithParams, MacroWithoutParams, Native }; enum Virtualness { NonVirtual, ImpureVirtual, PureVirtual }; FunctionNode(InnerNode *parent, const QString &name); void setReturnType(const QString& returnType) { rt = returnType; } void setMetaness(Metaness metaness) { met = metaness; } void setVirtualness(Virtualness virtualness) { vir = virtualness; } void setConst(bool conste) { con = conste; } void setStatic(bool statique) { sta = statique; } void setOverload(bool overlode); void addParameter(const Parameter& parameter); inline void setParameters(const QList& parameters); void borrowParameterNames(const FunctionNode *source); void setReimplementedFrom(FunctionNode *from); const QString& returnType() const { return rt; } Metaness metaness() const { return met; } bool isMacro() const { return met == MacroWithParams || met == MacroWithoutParams; } Virtualness virtualness() const { return vir; } bool isConst() const { return con; } bool isStatic() const { return sta; } bool isOverload() const { return ove; } int overloadNumber() const; int numOverloads() const; const QList& parameters() const { return params; } QStringList parameterNames() const; const FunctionNode *reimplementedFrom() const { return rf; } const QList &reimplementedBy() const { return rb; } const PropertyNode *associatedProperty() const { return ap; } private: void setAssociatedProperty(PropertyNode *property); friend class InnerNode; friend class PropertyNode; QString rt; #ifdef Q_WS_WIN Metaness met; Virtualness vir; #else Metaness met : 4; Virtualness vir : 2; #endif bool con : 1; bool sta : 1; bool ove : 1; QList params; const FunctionNode *rf; const PropertyNode *ap; QList rb; }; class PropertyNode : public LeafNode { public: enum FunctionRole { Getter, Setter, Resetter }; enum { NumFunctionRoles = Resetter + 1 }; PropertyNode(InnerNode *parent, const QString& name); void setDataType(const QString& dataType) { dt = dataType; } void addFunction(FunctionNode *function, FunctionRole role); void setStored(bool stored) { sto = toTrool(stored); } void setDesignable(bool designable) { des = toTrool(designable); } void setOverriddenFrom(const PropertyNode *baseProperty); const QString &dataType() const { return dt; } QString qualifiedDataType() const; NodeList functions() const; NodeList functions(FunctionRole role) const { return funcs[(int)role]; } NodeList getters() const { return functions(Getter); } NodeList setters() const { return functions(Setter); } NodeList resetters() const { return functions(Resetter); } bool isStored() const { return fromTrool(sto, storedDefault()); } bool isDesignable() const { return fromTrool(des, designableDefault()); } const PropertyNode *overriddenFrom() const { return overrides; } private: enum Trool { Trool_True, Trool_False, Trool_Default }; static Trool toTrool(bool boolean); static bool fromTrool(Trool troolean, bool defaultValue); bool storedDefault() const { return true; } bool designableDefault() const { return !setters().isEmpty(); } QString dt; NodeList funcs[NumFunctionRoles]; Trool sto; Trool des; const PropertyNode *overrides; }; inline void FunctionNode::setParameters(const QList ¶meters) { params = parameters; } inline void PropertyNode::addFunction(FunctionNode *function, FunctionRole role) { funcs[(int)role].append(function); function->setAssociatedProperty(this); } inline NodeList PropertyNode::functions() const { NodeList list; for (int i = 0; i < NumFunctionRoles; ++i) list += funcs[i]; return list; } class VariableNode : public LeafNode { public: VariableNode(InnerNode *parent, const QString &name); void setLeftType(const QString &leftType) { lt = leftType; } void setRightType(const QString &rightType) { rt = rightType; } void setStatic(bool statique) { sta = statique; } const QString &leftType() const { return lt; } const QString &rightType() const { return rt; } QString dataType() const { return lt + rt; } bool isStatic() const { return sta; } private: QString lt; QString rt; bool sta; }; inline VariableNode::VariableNode(InnerNode *parent, const QString &name) : LeafNode(Variable, parent, name), sta(false) { } class TargetNode : public LeafNode { public: TargetNode(InnerNode *parent, const QString& name); virtual bool isInnerNode() const; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/openedlist.cpp000066400000000000000000000123331215241066400216200ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* openedlist.cpp */ #include #include "atom.h" #include "openedlist.h" QT_BEGIN_NAMESPACE static const char roman[] = "m\2d\5c\2l\5x\2v\5i"; OpenedList::OpenedList( Style style ) : sty( style ), ini( 1 ), nex( 0 ) { } OpenedList::OpenedList( const Location& location, const QString& hint ) : sty( Bullet ), ini( 1 ) { QRegExp hintSyntax( "(\\W*)([0-9]+|[A-Z]+|[a-z]+)(\\W*)" ); if ( hintSyntax.exactMatch(hint) ) { bool ok; int asNumeric = hint.toInt( &ok ); int asRoman = fromRoman( hintSyntax.cap(2) ); int asAlpha = fromAlpha( hintSyntax.cap(2) ); if ( ok ) { sty = Numeric; ini = asNumeric; } else if ( asRoman > 0 && asRoman != 100 && asRoman != 500 ) { sty = ( hint == hint.toLower() ) ? LowerRoman : UpperRoman; ini = asRoman; } else { sty = ( hint == hint.toLower() ) ? LowerAlpha : UpperAlpha; ini = asAlpha; } pref = hintSyntax.cap( 1 ); suff = hintSyntax.cap( 3 ); } else if ( !hint.isEmpty() ) { location.warning( tr("Unrecognized list style '%1'").arg(hint) ); } nex = ini - 1; } QString OpenedList::styleString() const { switch ( style() ) { case Bullet: default: return ATOM_LIST_BULLET; case Tag: return ATOM_LIST_TAG; case Value: return ATOM_LIST_VALUE; case Numeric: return ATOM_LIST_NUMERIC; case UpperAlpha: return ATOM_LIST_UPPERALPHA; case LowerAlpha: return ATOM_LIST_LOWERALPHA; case UpperRoman: return ATOM_LIST_UPPERROMAN; case LowerRoman: return ATOM_LIST_LOWERROMAN; } } QString OpenedList::numberString() const { return QString::number( number() ); /* switch ( style() ) { case Numeric: return QString::number( number() ); case UpperAlpha: return toAlpha( number() ).toUpper(); case LowerAlpha: return toAlpha( number() ); case UpperRoman: return toRoman( number() ).toUpper(); case LowerRoman: return toRoman( number() ); case Bullet: default: return "*"; }*/ } QString OpenedList::toAlpha( int n ) { QString str; while ( n > 0 ) { n--; str.prepend( (n % 26) + 'a' ); n /= 26; } return str; } int OpenedList::fromAlpha( const QString& str ) { int n = 0; int u; for ( int i = 0; i < (int) str.length(); i++ ) { u = str[i].toLower().unicode(); if ( u >= 'a' && u <= 'z' ) { n *= 26; n += u - 'a' + 1; } else { return 0; } } return n; } QString OpenedList::toRoman( int n ) { /* See p. 30 of Donald E. Knuth's "TeX: The Program". */ QString str; int j = 0; int k; int u; int v = 1000; for ( ;; ) { while ( n >= v ) { str += roman[j]; n -= v; } if ( n <= 0 ) break; k = j + 2; u = v / roman[k - 1]; if ( roman[k - 1] == 2 ) { k += 2; u /= 5; } if ( n + u >= v ) { str += roman[k]; n += u; } else { j += 2; v /= roman[j - 1]; } } return str; } int OpenedList::fromRoman( const QString& str ) { int n = 0; int j; int u; int v = 0; for ( int i = str.length() - 1; i >= 0; i-- ) { j = 0; u = 1000; while ( roman[j] != 'i' && roman[j] != str[i].toLower() ) { j += 2; u /= roman[j - 1]; } if ( u < v ) { n -= u; } else { n += u; } v = u; } if ( str.toLower() == toRoman(n) ) { return n; } else { return 0; } } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/openedlist.h000066400000000000000000000056271215241066400212750ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* openedlist.h */ #ifndef OPENEDLIST_H #define OPENEDLIST_H #include #include "location.h" QT_BEGIN_NAMESPACE class OpenedList { public: enum Style { Bullet, Tag, Value, Numeric, UpperAlpha, LowerAlpha, UpperRoman, LowerRoman }; OpenedList() : sty( Bullet ), ini( 1 ), nex( 0 ) { } OpenedList( Style style ); OpenedList( const Location& location, const QString& hint ); void next() { nex++; } bool isStarted() const { return nex >= ini; } Style style() const { return sty; } QString styleString() const; int number() const { return nex; } QString numberString() const; QString prefix() const { return pref; } QString suffix() const { return suff; } private: static QString toAlpha( int n ); static int fromAlpha( const QString& str ); static QString toRoman( int n ); static int fromRoman( const QString& str ); Style sty; int ini; int nex; QString pref; QString suff; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/pagegenerator.cpp000066400000000000000000000143161215241066400223000ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* pagegenerator.cpp */ #include #include #include #include "pagegenerator.h" #include "tree.h" QT_BEGIN_NAMESPACE /*! Nothing to do in the constructor. */ PageGenerator::PageGenerator() { // nothing. } /*! The destructor */ PageGenerator::~PageGenerator() { while (!outStreamStack.isEmpty()) endSubPage(); } /*! This function is recursive. */ void PageGenerator::generateTree(const Tree *tree, CodeMarker *marker) { generateInnerNode(tree->root(), marker); } QString PageGenerator::fileBase(const Node *node) { if (node->relates()) node = node->relates(); else if (!node->isInnerNode()) node = node->parent(); QString base = node->doc().baseName(); if (!base.isEmpty()) return base; const Node *p = node; forever { base.prepend(p->name()); const Node *pp = p->parent(); if (!pp || pp->name().isEmpty() || pp->type() == Node::Fake) break; base.prepend(QLatin1Char('-')); p = pp; } if (node->type() == Node::Fake) { #ifdef QDOC2_COMPAT if (base.endsWith(".html")) base.truncate(base.length() - 5); #endif } // the code below is effectively equivalent to: // base.replace(QRegExp("[^A-Za-z0-9]+"), " "); // base = base.trimmed(); // base.replace(" ", "-"); // base = base.toLower(); // as this function accounted for ~8% of total running time // we optimize a bit... QString res; // +5 prevents realloc in fileName() below res.reserve(base.size() + 5); bool begun = false; for (int i = 0; i != base.size(); ++i) { QChar c = base.at(i); uint u = c.unicode(); if (u >= 'A' && u <= 'Z') u -= 'A' - 'a'; if ((u >= 'a' && u <= 'z') || (u >= '0' && u <= '9')) { res += QLatin1Char(u); begun = true; } else if (begun) { res += QLatin1Char('-'); begun = false; } } while (res.endsWith(QLatin1Char('-'))) res.chop(1); return res; } QString PageGenerator::fileName(const Node *node) { if (!node->url().isEmpty()) return node->url(); QString name = fileBase(node); name += QLatin1Char('.'); name += fileExtension(node); return name; } QString PageGenerator::outFileName() { return QFileInfo(static_cast(out().device())->fileName()).fileName(); } void PageGenerator::beginSubPage(const Location& location, const QString& fileName) { QFile *outFile = new QFile(outputDir() + "/" + fileName); if (!outFile->open(QFile::WriteOnly)) location.fatal(tr("Cannot open output file '%1'") .arg(outFile->fileName())); QTextStream *out = new QTextStream(outFile); out->setCodec("ISO-8859-1"); outStreamStack.push(out); } void PageGenerator::endSubPage() { outStreamStack.top()->flush(); delete outStreamStack.top()->device(); delete outStreamStack.pop(); } QTextStream &PageGenerator::out() { return *outStreamStack.top(); } /*! Recursive writing of html files from the root \a node. */ void PageGenerator::generateInnerNode(const InnerNode *node, CodeMarker *marker) { if (!node->url().isNull()) return; if (node->type() == Node::Fake) { const FakeNode *fakeNode = static_cast(node); if (fakeNode->subType() == FakeNode::ExternalPage) return; } if (node->parent() != 0) { beginSubPage(node->location(), fileName(node)); if (node->type() == Node::Namespace || node->type() == Node::Class) { generateClassLikeNode(node, marker); } else if (node->type() == Node::Fake) { const FakeNode* fakeNode = static_cast(node); #ifdef QDOC_QML if (fakeNode->subType() == FakeNode::QmlClass) { //qDebug() << "FILENAME:" << fileName(node); } #endif generateFakeNode(static_cast(node), marker); } endSubPage(); } NodeList::ConstIterator c = node->childNodes().begin(); while (c != node->childNodes().end()) { if ((*c)->isInnerNode() && (*c)->access() != Node::Private) generateInnerNode((const InnerNode *) *c, marker); ++c; } } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/pagegenerator.h000066400000000000000000000054121215241066400217420ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* pagegenerator.h */ #ifndef PAGEGENERATOR_H #define PAGEGENERATOR_H #include #include #include "generator.h" #include "location.h" QT_BEGIN_NAMESPACE class ClassNode; class InnerNode; class NamespaceNode; class PageGenerator : public Generator { public: PageGenerator(); ~PageGenerator(); virtual void generateTree(const Tree *tree, CodeMarker *marker); protected: virtual QString fileBase(const Node *node); virtual QString fileExtension(const Node *node) = 0; QString fileName(const Node *node); QString outFileName(); void beginSubPage(const Location& location, const QString& fileName); void endSubPage(); virtual void generateInnerNode(const InnerNode *node, CodeMarker *marker); QTextStream& out(); private: QStack outStreamStack; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/plaincodemarker.cpp000066400000000000000000000076221215241066400226170ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "plaincodemarker.h" QT_BEGIN_NAMESPACE PlainCodeMarker::PlainCodeMarker() { } PlainCodeMarker::~PlainCodeMarker() { } bool PlainCodeMarker::recognizeCode( const QString& /* code */ ) { return true; } bool PlainCodeMarker::recognizeExtension( const QString& /* ext */ ) { return true; } bool PlainCodeMarker::recognizeLanguage( const QString& /* lang */ ) { return false; } QString PlainCodeMarker::plainName( const Node * /* node */ ) { return ""; } QString PlainCodeMarker::plainFullName(const Node * /* node */, const Node * /* relative */) { return ""; } QString PlainCodeMarker::markedUpCode( const QString& code, const Node * /* relative */, const QString& /* dirPath */ ) { return protect( code ); } QString PlainCodeMarker::markedUpSynopsis( const Node * /* node */, const Node * /* relative */, SynopsisStyle /* style */ ) { return "foo"; } QString PlainCodeMarker::markedUpName( const Node * /* node */ ) { return ""; } QString PlainCodeMarker::markedUpFullName( const Node * /* node */, const Node * /* relative */ ) { return ""; } QString PlainCodeMarker::markedUpEnumValue(const QString & /* enumValue */, const Node * /* relative */) { return ""; } QString PlainCodeMarker::markedUpIncludes( const QStringList& /* includes */ ) { return ""; } QString PlainCodeMarker::functionBeginRegExp( const QString& /* funcName */ ) { return ""; } QString PlainCodeMarker::functionEndRegExp( const QString& /* funcName */ ) { return ""; } QList
      PlainCodeMarker::sections(const InnerNode * /* innerNode */, SynopsisStyle /* style */, Status /* status */) { return QList
      (); } const Node *PlainCodeMarker::resolveTarget( const QString& /* target */, const Tree * /* tree */, const Node * /* relative */ ) { return 0; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/plaincodemarker.h000066400000000000000000000062501215241066400222600ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* plaincodemarker.h */ #ifndef PLAINCODEMARKER_H #define PLAINCODEMARKER_H #include "codemarker.h" QT_BEGIN_NAMESPACE class PlainCodeMarker : public CodeMarker { public: PlainCodeMarker(); ~PlainCodeMarker(); bool recognizeCode( const QString& code ); bool recognizeExtension( const QString& ext ); bool recognizeLanguage( const QString& lang ); QString plainName( const Node *node ); QString plainFullName( const Node *node, const Node *relative ); QString markedUpCode( const QString& code, const Node *relative, const QString& dirPath ); QString markedUpSynopsis( const Node *node, const Node *relative, SynopsisStyle style ); QString markedUpName( const Node *node ); QString markedUpFullName( const Node *node, const Node *relative ); QString markedUpEnumValue(const QString &enumValue, const Node *relative); QString markedUpIncludes( const QStringList& includes ); QString functionBeginRegExp( const QString& funcName ); QString functionEndRegExp( const QString& funcName ); QList
      sections(const InnerNode *innerNode, SynopsisStyle style, Status status); const Node *resolveTarget(const QString &target, const Tree *tree, const Node *relative); }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/polyarchiveextractor.cpp000066400000000000000000000062711215241066400237370ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* polyarchiveextractor.cpp */ #include "command.h" #include "polyarchiveextractor.h" QT_BEGIN_NAMESPACE /*! \class PolyArchiveExtractor \brief The PolyArchiveExtractor class is a class for unpacking archive files. This subclass of ArchiveExtractor contains a parameterized command for doing the archive extraction. It has an extractArchive() function you call to do the actual archive extraction. */ /*! The constructor takes the list of filename \a extensions, which it passes to the base class, and the \a commandFormat, which it stores locally. The \a commandFormat is a command template string. */ PolyArchiveExtractor::PolyArchiveExtractor( const QStringList& extensions, const QString& commandFormat ) : ArchiveExtractor( extensions ), cmd( commandFormat ) { } /*! The destructor doesn't have to do anything. */ PolyArchiveExtractor::~PolyArchiveExtractor() { } /*! Call this function to do the actual archive extraction. It calls the executeCommand() function to do the work. That's all it does. */ void PolyArchiveExtractor::extractArchive( const Location& location, const QString& filePath, const QString& outputDir ) { executeCommand( location, cmd, QStringList() << filePath << outputDir ); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/polyarchiveextractor.h000066400000000000000000000046361215241066400234070ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* polyarchiveextractor.h */ #ifndef POLYARCHIVEEXTRACTOR_H #define POLYARCHIVEEXTRACTOR_H #include "archiveextractor.h" QT_BEGIN_NAMESPACE class PolyArchiveExtractor : public ArchiveExtractor { public: PolyArchiveExtractor(const QStringList& extensions, const QString& commandFormat); ~PolyArchiveExtractor(); virtual void extractArchive(const Location& location, const QString& filePath, const QString& outputDir); private: QString cmd; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/polyuncompressor.cpp000066400000000000000000000073121215241066400231160ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "command.h" #include "polyuncompressor.h" QT_BEGIN_NAMESPACE /*! \class PolyUncompressor \brief The PolyUncompressor class is a class for uncompressing compressed files. This subclass of Uncompressor contains a parameterized command for doing the uncompression It has an uncompressFile() function you call to do the actual uncompression. */ /*! The constructor takes the list of filename \a extensions, which it passes to the base class, and the \a commandFormat, which it stores locally. The \a commandFormat is a command template string. */ PolyUncompressor::PolyUncompressor( const QStringList& extensions, const QString& commandFormat ) : Uncompressor( extensions ), cmd( commandFormat ) { } /*! The destructor doesn't have to do anything. */ PolyUncompressor::~PolyUncompressor() { } /*! From \a filePath, derive a file path for the uncompressed file and return it. If it can't figure out what the file path should be, it just concatenates ".out" to the \a filePath and returns that. */ QString PolyUncompressor::uncompressedFilePath( const QString& filePath ) { QStringList::ConstIterator e = fileExtensions().begin(); while ( e != fileExtensions().end() ) { QString dotExt = "." + *e; if ( filePath.endsWith(dotExt) ) return filePath.left( filePath.length() - dotExt.length() ); ++e; } return filePath + ".out"; // doesn't really matter } /*! Call this function to do the actual uncompressing. It calls the executeCommand() function to do the work. That's all it does. */ void PolyUncompressor::uncompressFile( const Location& location, const QString& filePath, const QString& outputFilePath ) { executeCommand( location, cmd, QStringList() << filePath << outputFilePath ); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/polyuncompressor.h000066400000000000000000000047111215241066400225630ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* polyuncompressor.h */ #ifndef POLYUNCOMPRESSOR_H #define POLYUNCOMPRESSOR_H #include "uncompressor.h" QT_BEGIN_NAMESPACE class PolyUncompressor : public Uncompressor { public: PolyUncompressor(const QStringList& extensions, const QString& commandFormat); ~PolyUncompressor(); virtual QString uncompressedFilePath(const QString& filePath); virtual void uncompressFile(const Location& location, const QString& filePath, const QString& outputFilePath); private: QString cmd; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/qdoc3.pro000066400000000000000000000044101215241066400204760ustar00rootroot00000000000000DEFINES += QDOC2_COMPAT #DEFINES += QT_NO_CAST_TO_ASCII #DEFINES += QT_NO_CAST_FROM_ASCII QT = core xml CONFIG += console build_all:!build_pass { CONFIG -= build_all CONFIG += release } mac:CONFIG -= app_bundle HEADERS += apigenerator.h \ archiveextractor.h \ atom.h \ bookgenerator.h \ ccodeparser.h \ codechunk.h \ codemarker.h \ codeparser.h \ command.h \ config.h \ cppcodemarker.h \ cppcodeparser.h \ cpptoqsconverter.h \ dcfsection.h \ doc.h \ editdistance.h \ generator.h \ helpprojectwriter.h \ htmlgenerator.h \ jambiapiparser.h \ javacodemarker.h \ javadocgenerator.h \ linguistgenerator.h \ location.h \ loutgenerator.h \ mangenerator.h \ node.h \ openedlist.h \ pagegenerator.h \ plaincodemarker.h \ polyarchiveextractor.h \ polyuncompressor.h \ qsakernelparser.h \ qscodemarker.h \ qscodeparser.h \ quoter.h \ separator.h \ sgmlgenerator.h \ text.h \ tokenizer.h \ tr.h \ tree.h \ uncompressor.h \ webxmlgenerator.h SOURCES += apigenerator.cpp \ archiveextractor.cpp \ atom.cpp \ bookgenerator.cpp \ ccodeparser.cpp \ codechunk.cpp \ codemarker.cpp \ codeparser.cpp \ command.cpp \ config.cpp \ cppcodemarker.cpp \ cppcodeparser.cpp \ cpptoqsconverter.cpp \ dcfsection.cpp \ doc.cpp \ editdistance.cpp \ generator.cpp \ helpprojectwriter.cpp \ htmlgenerator.cpp \ jambiapiparser.cpp \ javacodemarker.cpp \ javadocgenerator.cpp \ linguistgenerator.cpp \ location.cpp \ loutgenerator.cpp \ mangenerator.cpp \ main.cpp \ node.cpp \ openedlist.cpp \ pagegenerator.cpp \ plaincodemarker.cpp \ polyarchiveextractor.cpp \ polyuncompressor.cpp \ qsakernelparser.cpp \ qscodemarker.cpp \ qscodeparser.cpp \ quoter.cpp \ separator.cpp \ sgmlgenerator.cpp \ text.cpp \ tokenizer.cpp \ tree.cpp \ uncompressor.cpp \ webxmlgenerator.cpp \ yyindent.cpp libqxt-0.6.2/tools/3rdparty/qdoc3/qsakernelparser.cpp000066400000000000000000000126211215241066400226540ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "qsakernelparser.h" #include "tokenizer.h" #include "tree.h" QT_BEGIN_NAMESPACE QsaKernelParser::QsaKernelParser( Tree *cppTree ) : cppTre( cppTree ) { } QsaKernelParser::~QsaKernelParser() { } QString QsaKernelParser::language() { return "QSA Kernel C++"; } QString QsaKernelParser::sourceFileNameFilter() { return "*.cpp"; } void QsaKernelParser::parseSourceFile( const Location& location, const QString& filePath, Tree * /* tree */ ) { FILE *in = fopen( QFile::encodeName(filePath), "r" ); if ( in == 0 ) { location.error( tr("Cannot open QSA kernel file '%1'").arg(filePath) ); return; } Location fileLocation( filePath ); Tokenizer fileTokenizer( fileLocation, in ); tokenizer = &fileTokenizer; readToken(); QString ident; QString className; int delimDepth = 0; while ( tok != Tok_Eoi ) { if ( tok == Tok_Ident ) { ident = tokenizer->lexeme(); readToken(); if ( tok == Tok_Gulbrandsen && tokenizer->braceDepth() == 0 && tokenizer->parenDepth() == 0 ) { className = ident; } else if ( ident.startsWith("add") && ident.endsWith("Member") && tok == Tok_LeftParen ) { bool isProperty = ident.endsWith( "VariableMember" ); bool isStatic = ident.startsWith( "addStatic" ); bool isWritable = !isStatic; readToken(); if ( tok == Tok_String ) { QString member = tokenizer->lexeme(); member = member.mid( 1, member.length() - 2 ); readToken(); if ( tok == Tok_Comma ) readToken(); if ( tok == Tok_Ident && tokenizer->lexeme() == "QSMember" ) readToken(); if ( tok == Tok_LeftParen ) { delimDepth++; readToken(); } while ( tok != Tok_Eoi && tok != Tok_RightParen && tok != Tok_Semicolon ) { if ( tok == Tok_Ident ) { ident = tokenizer->lexeme(); if ( ident == "Custom" ) { isProperty = true; } else if ( ident == "AttributeNonWritable" ) { isWritable = false; } else if ( ident == "AttributeStatic" ) { isStatic = true; } } readToken(); } ClassNode *classe = (ClassNode *) cppTre->findNode( QStringList(className), Node::Class ); if ( classe == 0 ) { classe = new ClassNode( cppTre->root(), className ); classe->setLocation( tokenizer->location() ); } if ( isProperty ) { PropertyNode *property = new PropertyNode(classe, member); property->setLocation( tokenizer->location() ); property->setDataType( "Object" ); #if 0 property->setGetter( member ); if ( isWritable ) { QString setter = member; setter[0] = setter[0].toUpper(); setter.prepend( "set" ); property->setSetter( setter ); } #endif } else { FunctionNode *func = new FunctionNode( classe, member ); func->setLocation( tokenizer->location() ); func->setAccess( FunctionNode::Public ); func->setMetaness( FunctionNode::Slot ); if ( member == "toLocaleString" || member == "toString" ) { func->setReturnType( "QString" ); } else if ( member == "valueOf" ) { func->setReturnType( "Object" ); } else { func->setReturnType( "Object" ); func->addParameter( Parameter("...") ); } func->setStatic( false ); // ### } } } } else { readToken(); } } fclose( in ); } void QsaKernelParser::doneParsingSourceFiles( Tree * /* tree */ ) { } void QsaKernelParser::readToken() { tok = tokenizer->getToken(); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/qsakernelparser.h000066400000000000000000000050111215241066400223140ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* qsakernelparser.h */ #ifndef QSAKERNELPARSER_H #define QSAKERNELPARSER_H #include "codeparser.h" QT_BEGIN_NAMESPACE class Tokenizer; class QsaKernelParser : public CodeParser { public: QsaKernelParser( Tree *cppTree ); ~QsaKernelParser(); virtual QString language(); virtual QString sourceFileNameFilter(); virtual void parseSourceFile( const Location& location, const QString& filePath, Tree *tree ); virtual void doneParsingSourceFiles( Tree *tree ); private: void readToken(); Tree *cppTre; Tokenizer *tokenizer; int tok; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/qscodemarker.cpp000066400000000000000000000257561215241066400221470ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* qscodemarker.cpp */ #include "node.h" #include "qscodemarker.h" QT_BEGIN_NAMESPACE QsCodeMarker::QsCodeMarker() { } QsCodeMarker::~QsCodeMarker() { } bool QsCodeMarker::recognizeCode( const QString& /* code */ ) { return true; } bool QsCodeMarker::recognizeExtension( const QString& ext ) { return ext == "js" || ext == "qs"; } bool QsCodeMarker::recognizeLanguage( const QString& lang ) { return lang == "JavaScript" || lang == "Qt Script"; } QString QsCodeMarker::plainName( const Node *node ) { QString name = node->name(); if ( node->type() == Node::Function ) name += "()"; return name; } QString QsCodeMarker::plainFullName( const Node *node, const Node * /* relative */ ) { QString fullName; for ( ;; ) { fullName.prepend( plainName(node) ); if ( node->parent()->name().isEmpty() ) break; node = node->parent(); fullName.prepend("."); } return fullName; } QString QsCodeMarker::markedUpCode( const QString& code, const Node * /* relative */, const QString& /* dirPath */ ) { return protect( code ); } QString QsCodeMarker::markedUpSynopsis( const Node *node, const Node * /* relative */, SynopsisStyle style ) { QString synopsis; QStringList extras; QString name; name = taggedNode( node ); if ( style != Detailed ) name = linkTag( node, name ); name = "<@name>" + name + ""; if ( style == Detailed && !node->parent()->name().isEmpty() && node->type() != Node::Enum ) name.prepend( taggedNode(node->parent()) + "." ); switch ( node->type() ) { case Node::Class: synopsis = "class " + name; break; case Node::Function: { const FunctionNode *func = (const FunctionNode *) node; synopsis = name; if ( style == SeparateList ) { synopsis += "()"; } else { synopsis += " ("; if ( !func->parameters().isEmpty() ) { synopsis += " "; int numOptional = 0; QList::ConstIterator p = func->parameters().begin(); while ( p != func->parameters().end() ) { if ( !(*p).defaultValue().isEmpty() ) { if ( p == func->parameters().begin() ) { synopsis += "[ "; } else { synopsis += " [ , "; } numOptional++; } else { if ( p != func->parameters().begin() ) synopsis += ", "; } if ( !(*p).name().isEmpty() ) synopsis += "<@param>" + protect( (*p).name() ) + " : "; synopsis += protect( (*p).leftType() ); ++p; } for ( int i = 0; i < numOptional; i++ ) synopsis += " ]"; synopsis += " "; } synopsis += ")"; } if ( style != SeparateList && !func->returnType().isEmpty() ) synopsis += " : " + protect( func->returnType() ); if ( style == Detailed && func->metaness() == FunctionNode::Signal ) extras << "[signal]"; } break; case Node::Property: { const PropertyNode *property = (const PropertyNode *) node; synopsis = name; if ( style != SeparateList ) synopsis += " : " + property->dataType(); if ( style == Detailed && property->setters().isEmpty() ) extras << "[read only]"; } break; case Node::Enum: { /* The letters A to F and X (upper- and lower-case) can appear in a hexadecimal constant (e.g. 0x3F). */ QRegExp letterRegExp( "[G-WYZg-wyz_]" ); const EnumNode *enume = (const EnumNode *) node; synopsis = name; if ( style == Summary && !enume->items().isEmpty() ) { synopsis += " : "; QString comma; QList::ConstIterator it = enume->items().begin(); while ( it != enume->items().end() ) { if ( enume->itemAccess((*it).name()) == Node::Public ) { synopsis += comma; synopsis += (*it).name(); if ( (*it).value().indexOf(letterRegExp) != -1 ) synopsis += " = " + (*it).value(); comma = ", "; } ++it; } } } break; case Node::Namespace: case Node::Typedef: default: synopsis = name; } if ( style == Summary ) { if ( node->status() == Node::Preliminary ) { extras << "(preliminary)"; } else if ( node->status() == Node::Deprecated ) { extras << "(deprecated)"; } else if ( node->status() == Node::Obsolete ) { extras << "(obsolete)"; } } QString extra; if ( !extras.isEmpty() ) extra = "<@extra>" + extras.join(" ") + ""; return synopsis + extra; } QString QsCodeMarker::markedUpName( const Node *node ) { QString name = linkTag( node, taggedNode(node) ); if ( node->type() == Node::Function ) name += "()"; return name; } QString QsCodeMarker::markedUpFullName( const Node *node, const Node * /* relative */ ) { QString fullName; for ( ;; ) { fullName.prepend( markedUpName(node) ); if ( node->parent()->name().isEmpty() ) break; node = node->parent(); fullName.prepend( "<@op>." ); } return fullName; } QString QsCodeMarker::markedUpEnumValue(const QString & /* enumValue */, const Node * /* relative */) { return QString(); } QString QsCodeMarker::markedUpIncludes( const QStringList& /* includes */ ) { return QString(); } QString QsCodeMarker::functionBeginRegExp( const QString& funcName ) { return "^function[ \t].*\\b" + QRegExp::escape( funcName ); } QString QsCodeMarker::functionEndRegExp( const QString& /* funcName */ ) { return "^}"; } QList
      QsCodeMarker::sections( const InnerNode *inner, SynopsisStyle style, Status status ) { QList
      sections; if (inner->type() != Node::Class) return sections; const ClassNode *classe = static_cast(inner); if ( style == Summary ) { FastSection enums(classe, "Enums", "enum", "enums"); FastSection functions(classe, "Functions", "function", "functions"); FastSection readOnlyProperties(classe, "Read-Only Properties", "property", "properties"); FastSection signalz(classe, "Signals", "signal", "signals"); FastSection writableProperties(classe, "Writable Properties", "property", "properties"); QStack stack; stack.push( classe ); while ( !stack.isEmpty() ) { const ClassNode *ancestorClass = stack.pop(); NodeList::ConstIterator c = ancestorClass->childNodes().begin(); while ( c != ancestorClass->childNodes().end() ) { if ( (*c)->access() == Node::Public ) { if ( (*c)->type() == Node::Enum ) { insert( enums, *c, style, status ); } else if ( (*c)->type() == Node::Function ) { const FunctionNode *func = (const FunctionNode *) *c; if ( func->metaness() == FunctionNode::Signal ) { insert( signalz, *c, style, status ); } else { insert( functions, *c, style, status ); } } else if ( (*c)->type() == Node::Property ) { const PropertyNode *property = (const PropertyNode *) *c; if ( property->setters().isEmpty() ) { insert( readOnlyProperties, *c, style, status ); } else { insert( writableProperties, *c, style, status ); } } } ++c; } QList::ConstIterator r = ancestorClass->baseClasses().begin(); while ( r != ancestorClass->baseClasses().end() ) { stack.prepend( (*r).node ); ++r; } } append( sections, enums ); append( sections, writableProperties ); append( sections, readOnlyProperties ); append( sections, functions ); append( sections, signalz ); } else if ( style == Detailed ) { FastSection enums( classe, "Enum Documentation" ); FastSection functionsAndSignals( classe, "Function and Signal Documentation" ); FastSection properties( classe, "Property Documentation" ); NodeList::ConstIterator c = classe->childNodes().begin(); while ( c != classe->childNodes().end() ) { if ( (*c)->access() == Node::Public ) { if ( (*c)->type() == Node::Enum ) { insert( enums, *c, style, status ); } else if ( (*c)->type() == Node::Function ) { insert( functionsAndSignals, *c, style, status ); } else if ( (*c)->type() == Node::Property ) { insert( properties, *c, style, status ); } } ++c; } append( sections, enums ); append( sections, properties ); append( sections, functionsAndSignals ); } else { // ( style == SeparateList ) FastSection all( classe ); QStack stack; stack.push( classe ); while ( !stack.isEmpty() ) { const ClassNode *ancestorClass = stack.pop(); NodeList::ConstIterator c = ancestorClass->childNodes().begin(); while ( c != ancestorClass->childNodes().end() ) { if ( (*c)->access() == Node::Public ) insert( all, *c, style, status ); ++c; } QList::ConstIterator r = ancestorClass->baseClasses().begin(); while ( r != ancestorClass->baseClasses().end() ) { stack.prepend( (*r).node ); ++r; } } append( sections, all ); } return sections; } const Node *QsCodeMarker::resolveTarget( const QString& /* target */, const Tree * /* tree */, const Node * /* relative */ ) { return 0; } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/qscodemarker.h000066400000000000000000000062361215241066400216040ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* qscodemarker.h */ #ifndef QSCODEMARKER_H #define QSCODEMARKER_H #include "codemarker.h" QT_BEGIN_NAMESPACE class QsCodeMarker : public CodeMarker { public: QsCodeMarker(); ~QsCodeMarker(); bool recognizeCode( const QString& code ); bool recognizeExtension( const QString& ext ); bool recognizeLanguage( const QString& lang ); QString plainName(const Node *node); QString plainFullName(const Node *node, const Node *relative); QString markedUpCode( const QString& code, const Node *relative, const QString& dirPath ); QString markedUpSynopsis( const Node *node, const Node *relative, SynopsisStyle style ); QString markedUpName( const Node *node ); QString markedUpFullName( const Node *node, const Node *relative ); QString markedUpEnumValue(const QString &enumValue, const Node *relative); QString markedUpIncludes( const QStringList& includes ); QList
      sections(const InnerNode *innerNode, SynopsisStyle style, Status status); QString functionBeginRegExp( const QString& funcName ); QString functionEndRegExp( const QString& funcName ); const Node *resolveTarget( const QString& target, const Tree *tree, const Node *relative ); }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/qscodeparser.cpp000066400000000000000000000705631215241066400221560ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* qscodeparser.cpp */ #include #include #include "config.h" #include "qscodeparser.h" #include "text.h" #include "tokenizer.h" #include "tree.h" QT_BEGIN_NAMESPACE #define CONFIG_QUICK "quick" #define CONFIG_REPLACES "replaces" #define COMMAND_BRIEF Doc::alias( "brief") #define COMMAND_CODE Doc::alias( "code") #define COMMAND_ENDCODE Doc::alias( "endcode") #define COMMAND_ENDQUICKCODE Doc::alias( "endquickcode") #define COMMAND_FILE Doc::alias( "file") #define COMMAND_GROUP Doc::alias( "group") #define COMMAND_MODULE Doc::alias( "module") #define COMMAND_PAGE Doc::alias( "page") #define COMMAND_QUICKCLASS Doc::alias( "quickclass") #define COMMAND_QUICKCODE Doc::alias( "quickcode") #define COMMAND_QUICKENUM Doc::alias( "quickenum") #define COMMAND_QUICKFN Doc::alias( "quickfn") #define COMMAND_QUICKIFY Doc::alias( "quickify") #define COMMAND_QUICKPROPERTY Doc::alias( "quickproperty") #define COMMAND_PROTECTED Doc::alias( "protected") #define COMMAND_REPLACE Doc::alias( "replace") static QString balancedParens = "(?:[^()]+|\\([^()]*\\))*"; QsCodeParser::QsCodeParser(Tree *cppTree) : cppTre(cppTree), qsTre(0), replaceRegExp("/(.+)/([^/]*)/") { } QsCodeParser::~QsCodeParser() { } void QsCodeParser::initializeParser(const Config& config) { CppCodeParser::initializeParser(config); nodeTypeMap.insert(COMMAND_QUICKCLASS, Node::Class); nodeTypeMap.insert(COMMAND_QUICKENUM, Node::Enum); nodeTypeMap.insert(COMMAND_QUICKPROPERTY, Node::Property); nodeTypeMap.insert(COMMAND_QUICKFN, Node::Function); QString quickDotReplaces = CONFIG_QUICK + Config::dot + CONFIG_REPLACES; QStringList replaces = config.getStringList(quickDotReplaces); QStringList::ConstIterator r = replaces.begin(); while (r != replaces.end()) { if (replaceRegExp.exactMatch(*r)) { QRegExp before(replaceRegExp.cap(1)); before.setMinimal(true); QString after = replaceRegExp.cap(2); if (before.isValid()) { replaceBefores << before; replaceAfters << after; } else { config.lastLocation().warning( tr("Invalid regular expression '%1'") .arg(before.pattern())); } } else { config.lastLocation().warning(tr("Bad syntax in '%1'") .arg(quickDotReplaces)); } ++r; } } void QsCodeParser::terminateParser() { nodeTypeMap.clear(); classesWithNoQuickDoc.clear(); replaceBefores.clear(); replaceAfters.clear(); CppCodeParser::terminateParser(); } QString QsCodeParser::language() { return "Qt Script"; } QString QsCodeParser::headerFileNameFilter() { return "*"; } QString QsCodeParser::sourceFileNameFilter() { return "*.qs *.qsd"; } void QsCodeParser::parseHeaderFile(const Location& location, const QString& filePath, Tree *tree) { qsTre = tree; FILE *in = fopen(QFile::encodeName(filePath), "r"); if (in == 0) { location.error(tr("Cannot open Qt Script class list '%1'") .arg(filePath)); return; } Location fileLocation(filePath); Tokenizer fileTokenizer(fileLocation, in); int tok = fileTokenizer.getToken(); while (tok != Tok_Eoi) { if (tok == Tok_Ident) { ClassNode *quickClass = new ClassNode(qsTre->root(), fileTokenizer.lexeme()); quickClass->setLocation(fileTokenizer.location()); } else { fileTokenizer.location().error(tr("Unexpected token '%1' in Qt" " Script class list") .arg(fileTokenizer.lexeme())); break; } tok = fileTokenizer.getToken(); } fclose(in); } void QsCodeParser::parseSourceFile(const Location& location, const QString& filePath, Tree *tree) { qsTre = tree; CppCodeParser::parseSourceFile(location, filePath, tree); } void QsCodeParser::doneParsingHeaderFiles(Tree *tree) { NodeList::ConstIterator c = tree->root()->childNodes().begin(); while (c != tree->root()->childNodes().end()) { if ((*c)->type() == Node::Class) quickifyClass((ClassNode *) *c); ++c; } cppTre->root()->deleteChildren(); // save memory tree->resolveInheritance(); tree->resolveProperties(); } void QsCodeParser::doneParsingSourceFiles(Tree *tree) { tree->root()->normalizeOverloads(); NodeList::ConstIterator c = tree->root()->childNodes().begin(); while (c != tree->root()->childNodes().end()) { if ((*c)->type() == Node::Class) { QMap::ConstIterator cwnqd = classesWithNoQuickDoc.find((*c)->name()); if (cwnqd != classesWithNoQuickDoc.end()) { (*cwnqd)->location().warning(tr("No '\\%1' documentation for" " class '%2'") .arg(COMMAND_QUICKCLASS) .arg(cwnqd.key())); (*cwnqd)->setDoc(Doc(), true); } } ++c; } // ### check which enum types are used } FunctionNode *QsCodeParser::findFunctionNode(const QString& synopsis, Tree *tree) { QStringList parentPath; FunctionNode *clone; FunctionNode *func = 0; if (makeFunctionNode(synopsis, &parentPath, &clone)) { func = tree->findFunctionNode(parentPath, clone); delete clone; } return func; } QSet QsCodeParser::topicCommands() { return QSet() << COMMAND_FILE << COMMAND_GROUP << COMMAND_MODULE << COMMAND_PAGE << COMMAND_QUICKCLASS << COMMAND_QUICKENUM << COMMAND_QUICKFN << COMMAND_QUICKPROPERTY; } Node *QsCodeParser::processTopicCommand(const Doc& doc, const QString& command, const QString& arg) { if (command == COMMAND_QUICKFN) { QStringList parentPath; FunctionNode *quickFunc = 0; FunctionNode *clone; if (makeFunctionNode(arg, &parentPath, &clone)) { FunctionNode *kernelFunc = findKernelFunction(parentPath, clone->name()); if (kernelFunc != 0) kernelFunc->setAccess(Node::Private); quickFunc = qsTre->findFunctionNode(parentPath, clone); if (quickFunc == 0 && kernelFunc != 0) { quickFunc = new FunctionNode(kernelFunc->parent(), kernelFunc->name()); quickFunc->setLocation(kernelFunc->location()); quickFunc->setReturnType(clone->returnType()); quickFunc->setParameters(clone->parameters()); } if (quickFunc == 0) { doc.location().warning(tr("Cannot find '%1' specified with '\\%2'") .arg(arg).arg(command)); } else { quickFunc->setAccess(Node::Public); QStringList qtParams = quickFunc->parameterNames(); quickFunc->borrowParameterNames(clone); QStringList quickParams = quickFunc->parameterNames(); setQuickDoc(quickFunc, doc, qtParams, quickParams); } delete clone; } else { doc.location().warning(tr("Cannot find '%1' specified with '\\%2'") .arg(arg).arg(command)); } return 0; } else if (nodeTypeMap.contains(command)) { QStringList subArgs = arg.split(" "); QString dataType; if (subArgs.count() == 3 && subArgs[1] == ":") { dataType = subArgs[2]; } else if (subArgs.count() != 1) { doc.location().warning(tr("Invalid syntax in '\\%1'") .arg(command)); } QStringList path = subArgs[0].split("."); Node *quickNode = qsTre->findNode(path, nodeTypeMap[command]); if (quickNode == 0) { doc.location().warning(tr("Cannot find '%1' specified with '\\%2'") .arg(arg).arg(command)); } else { setQuickDoc(quickNode, doc); if (quickNode->type() == Node::Class) { classesWithNoQuickDoc.remove(quickNode->name()); if (doc.briefText().isEmpty()) doc.location().warning(tr("Missing '\\%1' for class '%2'") .arg(COMMAND_BRIEF) .arg(quickNode->name())); } else if (quickNode->type() == Node::Property) { PropertyNode *quickProperty = (PropertyNode *) quickNode; if (quickProperty->dataType() == "Object") { if (dataType.isEmpty()) { doc.location().warning(tr("Missing data type in '\\%1'" " (assuming 'Object')") .arg(command)); } else { quickProperty->setDataType(dataType); } } else if (dataType != quickProperty->dataType()) { doc.location().warning(tr("Ignored contradictory data type" " in '\\%1'") .arg(command)); } } } return 0; } else { return CppCodeParser::processTopicCommand(doc, command, arg); } } QSet QsCodeParser::otherMetaCommands() { return commonMetaCommands() << COMMAND_ENDQUICKCODE << COMMAND_QUICKCODE << COMMAND_QUICKIFY << COMMAND_REPLACE; } void QsCodeParser::processOtherMetaCommand(const Doc& doc, const QString& command, const QString& arg, Node *node) { if (command == COMMAND_PROTECTED) { doc.location().warning(tr("Cannot use '\\%1' in %2") .arg(COMMAND_PROTECTED).arg(language())); } else { CppCodeParser::processOtherMetaCommand(doc,command,arg,node); } } ClassNode *QsCodeParser::tryClass(const QString& className) { return (ClassNode*) cppTre->findNode(QStringList(className),Node::Class); } FunctionNode *QsCodeParser::findKernelFunction(const QStringList& parentPath, const QString& name) { FunctionNode clone(0, name); clone.setReturnType("Object"); clone.addParameter(Parameter("...")); return qsTre->findFunctionNode(parentPath, &clone); } void QsCodeParser::extractRegExp(const QRegExp& regExp, QString& source, const Doc& doc) { QRegExp blankLineRegExp( "[ \t]*(?:\n(?:[ \t]*\n)+[ \t]*|[ \n\t]*\\\\code|" "\\\\endcode[ \n\t]*)"); QStringList paras = source.trimmed().split(blankLineRegExp); paras = paras.filter(regExp); if (paras.count() == 0) { doc.location().warning(tr("Cannot find regular expression '%1'") .arg(regExp.pattern())); } else if (paras.count() > 1) { doc.location().warning(tr("Regular rexpression '%1' matches multiple" "times").arg(regExp.pattern())); } else { source = paras.first() + "\n\n"; } } void QsCodeParser::extractTarget(const QString& target, QString& source, const Doc& doc) { QRegExp targetRegExp( "(\\\\target\\s+(\\S+)[^\n]*\n" "(?:(?!\\s*\\\\code)[^\n]+\n|\\s*\\\\code.*\\\\endcode\\s*\n)*)" "(?:\\s*\n|[^\n]*$)"); targetRegExp.setMinimal(true); int pos = 0; while ((pos = source.indexOf(targetRegExp, pos)) != -1) { if (targetRegExp.cap(2) == target) { source = targetRegExp.cap(1) + "\n\n"; return; } pos += targetRegExp.matchedLength(); } doc.location().warning(tr("Cannot find target '%1'").arg(target)); } void QsCodeParser::renameParameters(QString& source, const Doc& /* doc */, const QStringList& qtParams, const QStringList& quickParams) { QRegExp paramRegExp("(\\\\a\\s*\\{?\\s*)([A-Za-z0-9_]+)"); int pos = 0; while ((pos = paramRegExp.indexIn(source, pos)) != -1) { pos += paramRegExp.cap(1).length(); QString before = paramRegExp.cap(2); int index = qtParams.indexOf(before); if (index != -1) { QString after = quickParams[index]; source.replace(pos, before.size(), after); } } } void QsCodeParser::applyReplacementList(QString& source, const Doc& doc) { QStringList args = doc.metaCommandArgs(COMMAND_REPLACE); QStringList::ConstIterator a = args.begin(); while (a != args.end()) { if (replaceRegExp.exactMatch(*a)) { QRegExp before(replaceRegExp.cap(1)); before.setMinimal(true); QString after = replaceRegExp.cap(2); if (before.isValid()) { int oldLen = source.size(); source.replace(before, after); // this condition is sufficient but not necessary if (oldLen == source.size() && !source.contains(after)) doc.location().warning( tr("Regular expression '%1' did not match anything") .arg(before.pattern())); } else { doc.location().warning( tr("Invalid regular expression '%1'") .arg(before.pattern())); } } else { doc.location().warning(tr("Bad syntax in '\\%1'") .arg(COMMAND_REPLACE)); } ++a; } QRegExp codeRegExp("\\\\" + COMMAND_CODE + "(.*)\\\\" + COMMAND_ENDCODE); codeRegExp.setMinimal(true); QRegExp quickcodeRegExp( "\\\\" + COMMAND_QUICKCODE + "(.*)\\\\" + COMMAND_ENDQUICKCODE); quickcodeRegExp.setMinimal(true); int quickcodePos = doc.source().indexOf(quickcodeRegExp); if (quickcodePos != -1) { int codePos = source.indexOf(codeRegExp); if (codePos == -1) { doc.location().warning( tr("Cannot find any '\\%1' snippet corresponding to '\\%2'") .arg(COMMAND_CODE).arg(COMMAND_QUICKCODE)); } else { source.replace(codeRegExp.pos(1), codeRegExp.cap(1).length(), quickcodeRegExp.cap(1)); codePos = codeRegExp.pos(1) + quickcodeRegExp.cap(1).length(); if (doc.source().indexOf(quickcodeRegExp, quickcodePos + 1) != -1) { doc.location().warning( tr("Cannot use '\\%1' twice in a row") .arg(COMMAND_QUICKCODE)); } else if (source.indexOf(codeRegExp, codePos + 1) != -1) { doc.location().warning(tr("Ambiguous '\\%1'") .arg(COMMAND_QUICKCODE)); } } } } void QsCodeParser::quickifyClass(ClassNode *quickClass) { QString qtClassName = quickClass->name(); QString bare = quickClass->name(); if (bare != "Qt" && bare != "Object") { if (bare.startsWith("Q")) { bare = bare.mid(1); } else { qtClassName.prepend("Q"); classesWithNoQ.insert(bare); } } ClassNode *qtClass = 0; ClassNode *wrapperClass = 0; if ((wrapperClass = tryClass("Quick" + bare)) != 0 || (wrapperClass = tryClass("QS" + bare + "Class")) != 0) { qtClass = tryClass(qtClassName); if (qtClass == 0) { qtClass = wrapperClass; wrapperClass = 0; } } else if ((wrapperClass = tryClass("Quick" + bare + "Ptr")) != 0) { QRegExp ptrToQtType("(Q[A-Za-z0-9_]+)\\s*\\*"); FunctionNode *ctor = wrapperClass->findFunctionNode(wrapperClass->name()); if (ctor != 0 && !ctor->parameters().isEmpty() && ptrToQtType.exactMatch(ctor->parameters().first().leftType())) qtClassName = ptrToQtType.cap(1); qtClass = tryClass(qtClassName); } else { wrapperClass = tryClass("Q" + bare + "Ptr"); if (wrapperClass == 0) wrapperClass = tryClass("Quick" + bare + "Interface"); qtClass = tryClass(qtClassName); } if (qtClass == 0) { if (wrapperClass == 0) { quickClass->location().warning(tr("Cannot find Qt class '%1'") .arg(qtClassName)); } else { quickClass->location().warning(tr("Cannot find Qt class '%1'" " wrapped by '%2'") .arg(qtClassName) .arg(wrapperClass->name())); } return; } QList::ConstIterator r = qtClass->baseClasses().begin(); while (r != qtClass->baseClasses().end()) { ClassNode *quickBaseClass = cpp2qs.findClassNode(qsTre, (*r).node->name()); if (quickBaseClass) quickClass->addBaseClass((*r).access, quickBaseClass); ++r; } if (quickClass->baseClasses().isEmpty() && quickClass->name() != "Object") quickClass->addBaseClass(Node::Public, cpp2qs.findClassNode(qsTre,"Object")); QSet funcBlackList; QSet propertyBlackList; NodeList children; if (wrapperClass != 0) { children = wrapperClass->childNodes(); funcBlackList.insert(wrapperClass->name()); funcBlackList.insert("~" + wrapperClass->name()); } children += qtClass->childNodes(); for (int pass = 0; pass < 2; pass++) { NodeList::ConstIterator c = children.begin(); while (c != children.end()) { if ((*c)->access() != Node::Private && (*c)->status() == Node::Commendable) { if (pass == 0) { if ((*c)->type() == Node::Enum) { EnumNode *enume = (EnumNode *) *c; quickifyEnum(quickClass, enume); } else if ((*c)->type() == Node::Property) { if (!propertyBlackList.contains((*c)->name())) { PropertyNode *property = (PropertyNode *) *c; quickifyProperty(quickClass, qtClass, property); if (!property->getters().isEmpty()) funcBlackList.insert(property->getters().first()->name()); if (!property->setters().isEmpty()) funcBlackList.insert(property->setters().first()->name()); if (!property->resetters().isEmpty()) funcBlackList.insert(property->resetters().first()->name()); propertyBlackList.insert(property->name()); } } } else if ((*c)->type() == Node::Function) { FunctionNode *func = (FunctionNode *) *c; quickifyFunction(quickClass, qtClass, func, funcBlackList.contains((*c)->name()) && func->parameters().count() < 2); } } ++c; } } setQtDoc(quickClass, qtClass->doc()); classesWithNoQuickDoc.insert(quickClass->name(), quickClass); } void QsCodeParser::quickifyEnum(ClassNode *quickClass, EnumNode *enume) { EnumNode *quickEnum = new EnumNode(quickClass, enume->name()); quickEnum->setLocation(enume->location()); #if 0 // ### not yet quickEnum->setAccess(Node::Protected); #endif QList::ConstIterator it = enume->items().begin(); while (it != enume->items().end()) { QString name = (*it).name(); QString value = (*it).value(); quickEnum->addItem(EnumItem(name, value)); ++it; } setQtDoc(quickEnum, enume->doc()); } void QsCodeParser::quickifyFunction(ClassNode *quickClass, ClassNode *qtClass, FunctionNode *func, bool onBlackList) { if (func->metaness() == FunctionNode::Dtor) return; FunctionNode *kernelFunc = findKernelFunction( QStringList() << quickClass->name(), func->name()); QString quickName = func->name(); if (func->metaness() == FunctionNode::Ctor) quickName = quickClass->name(); FunctionNode *quickFunc = new FunctionNode(quickClass, quickName); quickFunc->setLocation(func->location()); if (onBlackList) { quickFunc->setAccess(Node::Protected); } else { if (kernelFunc != 0 && func->numOverloads() == 1 && (func->parameters().count() == 0 || func->parameters().last().defaultValue().isEmpty())) { kernelFunc->setAccess(Node::Private); } else { if (func->metaness() == FunctionNode::Plain) quickFunc->setAccess(Node::Protected); } } quickFunc->setReturnType(cpp2qs.convertedDataType(qsTre, func->returnType())); if (func->metaness() != FunctionNode::Slot) quickFunc->setMetaness(func->metaness()); quickFunc->setVirtualness(FunctionNode::ImpureVirtual); quickFunc->setOverload(func->isOverload()); QList::ConstIterator q = func->parameters().begin(); while (q != func->parameters().end()) { QString dataType = cpp2qs.convertedDataType(qsTre, (*q).leftType(), (*q).rightType()); if (dataType.isEmpty()) { dataType = "UNKNOWN"; quickFunc->setAccess(Node::Private); } Parameter param(dataType, "", (*q).name(), (*q).defaultValue().isEmpty() ? "" : "undefined"); quickFunc->addParameter(param); ++q; } if (func->doc().isEmpty()) { if (func->parent() != (InnerNode *) qtClass) { func = qtClass->findFunctionNode(func); if (func != 0) setQtDoc(quickFunc, func->doc()); } } else { setQtDoc(quickFunc, func->doc()); } } void QsCodeParser::quickifyProperty(ClassNode *quickClass, ClassNode * /* qtClass */, PropertyNode *property) { PropertyNode *quickProperty = new PropertyNode(quickClass, property->name()); quickProperty->setLocation(property->location()); quickProperty->setDataType(cpp2qs.convertedDataType(qsTre, property->dataType())); #if 0 quickProperty->setGetter(property->getter()); quickProperty->setSetter(property->setter()); quickProperty->setResetter(property->resetter()); #endif quickProperty->setStored(property->isStored()); quickProperty->setDesignable(property->isDesignable()); setQtDoc(quickProperty, property->doc()); } QString QsCodeParser::quickifiedDoc(const QString& source) { QString result; int i = 0; while (i < (int) source.length()) { if (leftWordBoundary(source, i)) { if (source[i] == 'Q') { if (source[i + 1] == 'C' && source.mid(i, 8) == "QCString") { i += 2; } else { int end = i + 1; while (isWord(source[end])) ++end; if (!classesWithNoQ.contains( source.mid(i + 1, end - (i + 1)))) result += "Q"; i++; } } else if (source[i] == 'T' && source.mid(i, 4) == "TRUE" && rightWordBoundary(source, i + 4)) { result += "\\c{true}"; i += 4; } else if (source[i] == 'F' && source.mid(i, 5) == "FALSE" && rightWordBoundary(source, i + 5)) { result += "\\c{false}"; i += 5; } else if (source[i] == 'c' && source.mid(i, 6) == "const ") { i += 6; } else { result += source[i++]; } } else if ((source[i] == ':' && source[i + 1] == ':') || (source[i] == '-' && source[i + 1] == '>')) { result += '.'; i += 2; } else if (source[i] == '\\') { // ### make independent of the command name if (source.mid(i, 5) == "\\code") { do { result += source[i++]; } while (source[i - 1] != '\n'); int begin = i; int end = source.indexOf("\\endcode", i); if (end != -1) { QString code = source.mid(begin, end - begin); result += cpp2qs.convertedCode(qsTre, code, classesWithNoQ); i = end; } } else { result += source[i++]; } } else { result += source[i++]; } } QList::ConstIterator b = replaceBefores.begin(); QStringList::ConstIterator a = replaceAfters.begin(); while (a != replaceAfters.end()) { result.replace(*b, *a); ++b; ++a; } return result; } void QsCodeParser::setQtDoc(Node *quickNode, const Doc& doc) { if (!doc.isEmpty()) { Doc quickDoc(doc.location(), doc.location(), quickifiedDoc(doc.source()), CppCodeParser::topicCommands() + CppCodeParser::otherMetaCommands()); quickNode->setDoc(quickDoc, true); } } void QsCodeParser::setQuickDoc(Node *quickNode, const Doc& doc, const QStringList& qtParams, const QStringList& quickParams) { QRegExp quickifyCommand("\\\\" + COMMAND_QUICKIFY + "([^\n]*)(?:\n|$)"); if (quickNode->type() == Node::Function) { FunctionNode *quickFunc = (FunctionNode *) quickNode; quickFunc->setOverload(false); } if (doc.metaCommandsUsed().contains(COMMAND_QUICKIFY)) { QString source = doc.source(); int pos = source.indexOf(quickifyCommand); if (pos != -1) { QString quickifiedSource = quickNode->doc().source(); if (!qtParams.isEmpty() && qtParams != quickParams) renameParameters(quickifiedSource, doc, qtParams, quickParams); applyReplacementList(quickifiedSource, doc); do { QString extract = quickifiedSource; QString arg = quickifyCommand.cap(1).simplified(); if (!arg.isEmpty()) { if (arg.startsWith("/") && arg.endsWith("/") && arg.length() > 2) { QString pattern = arg.mid(1, arg.length() - 2); extractRegExp(QRegExp(pattern), extract, doc); } else { extractTarget(arg, extract, doc); } } source.replace(pos, quickifyCommand.matchedLength(), extract); pos += extract.length(); } while ((pos = source.indexOf(quickifyCommand, pos)) != -1); QRegExp quickcodeRegExp( "\\\\" + COMMAND_QUICKCODE + "(.*)\\\\" + COMMAND_ENDQUICKCODE); quickcodeRegExp.setMinimal(true); source.replace(quickcodeRegExp, ""); } Doc quickDoc(doc.location(), doc.location(), source, (CppCodeParser::topicCommands() + topicCommands() + CppCodeParser::otherMetaCommands()) << COMMAND_REPLACE); quickNode->setDoc(quickDoc, true); processOtherMetaCommands(quickDoc, quickNode); } else { quickNode->setDoc(doc, true); processOtherMetaCommands(doc, quickNode); } } bool QsCodeParser::makeFunctionNode(const QString& synopsis, QStringList *parentPathPtr, FunctionNode **funcPtr) { QRegExp funcRegExp( "\\s*([A-Za-z0-9_]+)\\.([A-Za-z0-9_]+)\\s*\\((" + balancedParens + ")\\)(?:\\s*:\\s*([A-Za-z0-9_]+))?\\s*"); QRegExp paramRegExp( "\\s*(\\[)?\\s*(?:([A-Za-z0-9_]+)\\s*:\\s*)?" "([A-Za-z0-9_]+|\\.\\.\\.)\\s*(\\[)?[\\s\\]]*"); if (!funcRegExp.exactMatch(synopsis)) return false; ClassNode *classe = (ClassNode*) qsTre->findNode(QStringList(funcRegExp.cap(1)),Node::Class); if (classe == 0) return false; FunctionNode *clone = new FunctionNode(0, funcRegExp.cap(2)); bool optional = false; QString paramStr = funcRegExp.cap(3); QStringList params = paramStr.split(","); QStringList::ConstIterator p = params.begin(); while (p != params.end()) { if (paramRegExp.exactMatch(*p)) { if (!paramRegExp.cap(1).isEmpty()) optional = true; clone->addParameter(Parameter(paramRegExp.cap(3), "", paramRegExp.cap(2), optional ? "undefined" : "")); if (!paramRegExp.cap(4).isEmpty()) optional = true; } else { delete clone; return false; } ++p; } QString returnType = funcRegExp.cap(4); if (!returnType.isEmpty()) clone->setReturnType(returnType); if (parentPathPtr != 0) *parentPathPtr = QStringList() << classe->name(); if (funcPtr != 0) { *funcPtr = clone; } else { delete clone; } return true; } bool QsCodeParser::isWord(QChar ch) { return ch.isLetterOrNumber() || ch == QChar('_'); } bool QsCodeParser::leftWordBoundary(const QString& str, int pos) { return !isWord(str[pos - 1]) && isWord(str[pos]); } bool QsCodeParser::rightWordBoundary(const QString& str, int pos) { return isWord(str[pos - 1]) && !isWord(str[pos]); } QT_END_NAMESPACE libqxt-0.6.2/tools/3rdparty/qdoc3/qscodeparser.h000066400000000000000000000123611215241066400216130ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ /* qscodeparser.h */ #ifndef QSCODEPARSER_H #define QSCODEPARSER_H #include "cppcodeparser.h" #include "cpptoqsconverter.h" QT_BEGIN_NAMESPACE class QsCodeParser : public CppCodeParser { public: QsCodeParser(Tree *cppTree); ~QsCodeParser(); virtual void initializeParser(const Config& config); virtual void terminateParser(); virtual QString language(); virtual QString headerFileNameFilter(); virtual QString sourceFileNameFilter(); virtual void parseHeaderFile(const Location& location, const QString& filePath, Tree *tree); virtual void parseSourceFile(const Location& location, const QString& filePath, Tree *tree); virtual void doneParsingHeaderFiles(Tree *tree); virtual void doneParsingSourceFiles(Tree *tree); FunctionNode *findFunctionNode(const QString& synopsis, Tree *tree); protected: virtual QSet topicCommands(); virtual Node *processTopicCommand(const Doc& doc, const QString& command, const QString& arg); virtual QSet otherMetaCommands(); virtual void processOtherMetaCommand(const Doc& doc, const QString& command, const QString& arg, Node *node); private: ClassNode *tryClass(const QString& className); FunctionNode *findKernelFunction(const QStringList& parentPath, const QString& name); void extractRegExp(const QRegExp& regExp, QString& source, const Doc& doc); void extractTarget(const QString& target, QString& source, const Doc& doc); void renameParameters(QString& source, const Doc& doc, const QStringList& qtNames, const QStringList& quickNames); void applyReplacementList(QString& source, const Doc& doc); void quickifyClass(ClassNode *quickClass); void quickifyEnum(ClassNode *quickClass, EnumNode *enume); void quickifyFunction(ClassNode *quickClass, ClassNode *qtClass, FunctionNode *func, bool onBlackList); void quickifyProperty(ClassNode *quickClass, ClassNode *qtClass, PropertyNode *property); QString quickifiedDoc(const QString& source); void setQtDoc(Node *quickNode, const Doc& doc); void setQuickDoc(Node *quickNode, const Doc& doc, const QStringList& qtParams = QStringList(), const QStringList& quickParams = QStringList()); bool makeFunctionNode(const QString& synopsis, QStringList *parentPathPtr, FunctionNode **funcPtr); static bool isWord(QChar ch); static bool leftWordBoundary(const QString& str, int pos); static bool rightWordBoundary(const QString& str, int pos); QMap nodeTypeMap; QMap classesWithNoQuickDoc; QList replaceBefores; QStringList replaceAfters; QSet classesWithNoQ; Tree* cppTre; Tree* qsTre; QRegExp replaceRegExp; CppToQsConverter cpp2qs; static int tabSize; }; QT_END_NAMESPACE #endif libqxt-0.6.2/tools/3rdparty/qdoc3/quoter.cpp000066400000000000000000000250101215241066400207650ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the tools applications of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** 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.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include "quoter.h" QT_BEGIN_NAMESPACE static void replaceMultipleNewlines(QString &s) { const int n = s.size(); bool slurping = false; int j = -1; const QChar newLine = QLatin1Char('\n'); QChar *d = s.data(); for (int i = 0; i != n; ++i) { const QChar c = d[i]; bool hit = (c == newLine); if (slurping && hit) continue; d[++j] = c; slurping = hit; } s.resize(++j); } // This is equivalent to line.split( QRegExp("\n(?!\n|$)") ) but much faster static QStringList splitLines(const QString &line) { QStringList result; int i = line.size(); while (true) { int j = i - 1; while (j >= 0 && line.at(j) == QLatin1Char('\n')) --j; while (j >= 0 && line.at(j) != QLatin1Char('\n')) --j; result.prepend(line.mid(j + 1, i - j - 1)); if (j < 0) break; i = j; } return result; } /* Transforms 'int x = 3 + 4' into 'int x=3+4'. A white space is kept between 'int' and 'x' because it is meaningful in C++. */ static void trimWhiteSpace( QString& str ) { enum { Normal, MetAlnum, MetSpace } state = Normal; const int n = str.length(); int j = -1; QChar *d = str.data(); for ( int i = 0; i != n; ++i ) { const QChar c = d[i]; if ( c.isLetterOrNumber() ) { if ( state == Normal ) { state = MetAlnum; } else { if ( state == MetSpace ) str[++j] = c; state = Normal; } str[++j] = c; } else if ( c.isSpace() ) { if ( state == MetAlnum ) state = MetSpace; } else { state = Normal; str[++j] = c; } } str.resize(++j); } Quoter::Quoter() : silent( false ) { /* We're going to hard code these delimiters: * C++, Qt, Qt Script, Java: //! [] * .pro files: #! [] * .xq, .xml, .html files: */ commentHash["pro"] = "#!"; commentHash["py"] = "#!"; commentHash["html"] = "